Skip to content

Commit

Permalink
Provide better support for mapping package requirements to dependencies
Browse files Browse the repository at this point in the history
In particular, support the ability to specify the version range of the
dependency, including expressions to extract the version components from
the bundle that provides the capability that satisfies the requirement,
e.g., [major.minor.micro,major+1.0.0)

#11

eclipse-platform/eclipse.platform.releng#119
  • Loading branch information
merks committed Oct 9, 2022
1 parent 8fd55fe commit ea7cf7b
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ public enum Type {

private static final Version DUMMY_VERSION = Version.parseVersion("1");

private static final Pattern VERSION_EXPRESSION_PATTERN = Pattern
.compile("(major|minor|micro|qualifier)(?:(\\+|-)([0-9]+))?");

private static final Pattern VERSION_PATTERN = Pattern
.compile("([0-9]+)(?:\\.([0-9]+)(?:\\.([0-9]+)(?:([.-])(.*))?)?)?");

private Type type;

private IInstallableUnit installableUnit;
Expand Down Expand Up @@ -275,28 +281,9 @@ public Model asPOM() {

InputLocation inputLocation = new InputLocation(myRequirements.indexOf(req), 0, null);
String mappedVersionRange = trimOrNull(dependencyItem.getMappedVersionRange());
VersionRange reqRange = mappedVersionRange == null ? null : VersionRange.create(mappedVersionRange);

if (!"*".equals(dependecyItemGroupId)) {
String artifactId = dependencyItem.getArtifactId();
if (dependencies.add(dependecyItemGroupId + ":" + artifactId)) {
Dependency dependency = new Dependency();
result.add(dependency);

dependency.setLocation("", inputLocation);
dependency.setGroupId(dependecyItemGroupId);
dependency.setArtifactId(artifactId);
if (mappedVersionRange != null) {
dependency.setVersion(mappedVersionRange);
} else {
dependency.setVersion("[0.0,)");
}
dependency.setOptional(req.getMin() == 0);
}
continue;
}

Collection<MavenItem> dependencyMappings = map(mavenItem, req);
Collection<MavenItem> dependencyMappings = map(mavenItem, req, dependecyItemGroupId,
dependencyItem.getArtifactId());
for (MavenItem dependencyMapping : dependencyMappings) {
String groupId = dependencyMapping.getGroupId();
String artifactId = dependencyMapping.getArtifactId();
Expand All @@ -313,29 +300,7 @@ public Model asPOM() {
dependency.setLocation("", inputLocation);
dependency.setGroupId(groupId);
dependency.setArtifactId(artifactId);

if (reqRange != null && !reqRange.equals(VersionRange.emptyRange)) {
StringBuilder versionRangeString = new StringBuilder();
Version low = reqRange.getMinimum();
Version high = reqRange.getMaximum();
String lowDependencyVersion = getVersionStringForDependency(dependencyMapping, low);
if (reqRange.getIncludeMinimum() && Version.MAX_VERSION.equals(high)) {
versionRangeString.append("[").append(lowDependencyVersion).append(",)");
} else {
versionRangeString.append(reqRange.getIncludeMinimum() ? '[' : '(');
versionRangeString.append(lowDependencyVersion);
String highDependencyVersion = getVersionStringForDependency(dependencyMapping, high);
if (!lowDependencyVersion.equals(highDependencyVersion)) {
versionRangeString.append(',');
versionRangeString.append(highDependencyVersion);
}
versionRangeString.append(reqRange.getIncludeMaximum() ? ']' : ')');
}
dependency.setVersion(versionRangeString.toString());
} else {
dependency.setVersion("[0.0,)");
}

dependency.setVersion(getVersionRange(dependencyMapping, mappedVersionRange));
dependency.setOptional(req.getMin() == 0);

result.add(dependency);
Expand Down Expand Up @@ -633,6 +598,96 @@ public String getVersionStringForDependency(MavenItem dependencyMapping, Version
return VersionUtil.getVersionString(dependencyVersion, versionFormat, false, -1);
}

public String getVersionRange(MavenItem mavenItem, String versionRange) {
if (versionRange != null) {
Matcher matcher = VERSION_EXPRESSION_PATTERN.matcher(versionRange);
if (matcher.find()) {
StringBuilder result = new StringBuilder();
String dependencyVersion = mavenItem.getMappedVersion();
Matcher versionMatcher = VERSION_PATTERN.matcher(dependencyVersion);
if (!versionMatcher.matches()) {
throw new IllegalStateException("The version '" + dependencyVersion
+ "' does not conform to the expected pattern:" + VERSION_PATTERN);
}

String major = versionMatcher.group(1);
String minor = versionMatcher.group(2);
String micro = versionMatcher.group(3);
String qualifierType = versionMatcher.group(4);
String qualifier = "-".equals(qualifierType) ? null : versionMatcher.group(5);

do {
String operator = matcher.group(2);
String operand = matcher.group(3);
String versionSegment = null;
switch (matcher.group(1)) {
case "major": {
versionSegment = getVersionSegment(major, operator, operand);
break;
}
case "minor": {
versionSegment = getVersionSegment(minor, operator, operand);
break;
}
case "micro": {
versionSegment = getVersionSegment(micro, operator, operand);
break;
}
case "qualifier": {
versionSegment = getVersionSegment(qualifier, operator, operand);
break;
}
}
matcher.appendReplacement(result,
versionSegment == null ? "" : Matcher.quoteReplacement(versionSegment));
if (result.length() > 0 && result.charAt(result.length() - 1) == '.') {
result.setLength(result.length() - 1);
}
} while (matcher.find());
matcher.appendTail(result);
return result.toString();
}
}

VersionRange reqRange = versionRange == null ? null : VersionRange.create(versionRange);
if (reqRange != null && !reqRange.equals(VersionRange.emptyRange)) {
StringBuilder versionRangeString = new StringBuilder();
Version low = reqRange.getMinimum();
Version high = reqRange.getMaximum();
String lowDependencyVersion = getVersionStringForDependency(mavenItem, low);
if (reqRange.getIncludeMinimum() && Version.MAX_VERSION.equals(high)) {
versionRangeString.append("[").append(lowDependencyVersion).append(",)");
} else {
versionRangeString.append(reqRange.getIncludeMinimum() ? '[' : '(');
versionRangeString.append(lowDependencyVersion);
String highDependencyVersion = getVersionStringForDependency(mavenItem, high);
if (!lowDependencyVersion.equals(highDependencyVersion)) {
versionRangeString.append(',');
versionRangeString.append(highDependencyVersion);
}
versionRangeString.append(reqRange.getIncludeMaximum() ? ']' : ')');
}
return versionRangeString.toString();
} else {
return "[0.0,)";
}
}

private static String getVersionSegment(String value, String operator, String operand) {
if (value != null && operator != null) {
switch (operator) {
case "+": {
return Integer.toString(Math.max(0, Integer.parseInt(value) + Integer.parseInt(operand)));
}
case "-": {
return Integer.toString(Math.max(0, Integer.parseInt(value) - Integer.parseInt(operand)));
}
}
}

return value;
}

@Override
public boolean isResolved() {
return installableUnit.isResolved();
Expand Down Expand Up @@ -712,6 +767,10 @@ private MavenItem mapIU(IInstallableUnit iu) {

usedMavenMappings.add(mapping);

if (mavenItem.getMappedVersion() == null) {
mavenItem.setMappedVersion(version.toString());
}

return mavenItem;
}
}
Expand Down Expand Up @@ -770,7 +829,8 @@ private Set<IInstallableUnit> resolveMapping(IRequiredCapability requirement) {
return ius;
}

private Collection<MavenItem> map(MavenItem containingMavenItem, IRequiredCapability requirement) {
private Collection<MavenItem> map(MavenItem containingMavenItem, IRequiredCapability requirement,
String targetGroupId, String targetArtifactId) {
Set<IInstallableUnit> ius = resolveMapping(requirement);
if (ius.isEmpty()) {
if (requirement.getMin() == 0) {
Expand All @@ -783,7 +843,9 @@ private Collection<MavenItem> map(MavenItem containingMavenItem, IRequiredCapabi
String artifactId = containingMavenItem.getArtifactId();
MavenItem[] mavenItems = ius.stream().map(this::mapIU)
.filter(it -> !(groupId.equals(it.getGroupId()) && artifactId.equals(it.getArtifactId()))
&& !"a.jre.javase".equals(it.getArtifactId()))
&& !"a.jre.javase".equals(it.getArtifactId())
&& ("*".equals(targetGroupId) || targetGroupId.equals(it.getGroupId())
&& targetArtifactId.equals(it.getArtifactId())))
.toArray(MavenItem[]::new);

if (mavenItems.length > 1) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde version="3.8"?>
<target name="Generated from P2 Repository Aggregator" sequenceNumber="24">
<target name="Generated from P2 Repository Aggregator" sequenceNumber="25">
<locations>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="com.google.guava.failureaccess" version="0.0.0"/>
Expand All @@ -23,6 +23,7 @@
<unit id="org.kohsuke.args4j" version="0.0.0"/>
<unit id="org.objectweb.asm" version="0.0.0"/>
<unit id="org.objectweb.asm.tree" version="0.0.0"/>
<unit id="org.slf4j.api" version="0.0.0"/>
<repository location="https://download.eclipse.org/cbi/updates/license"/>
<repository location="https://download.eclipse.org/eclipse/updates/4.26-I-builds"/>
<repository location="https://download.eclipse.org/nebula/releases/2.6.0"/>
Expand Down

0 comments on commit ea7cf7b

Please sign in to comment.