Skip to content

Commit

Permalink
[#56] resolve all declared version ranges per IU ID
Browse files Browse the repository at this point in the history
Regarding overrides:
- a specified version range always is resolved
- within the same location declaration:
  - first declaration (with or without version) resolves
  - subsequent unversioned declaration is ignored
- across subsequent location declarations:
  - earlier unversioned declaration is overridden
  - later unversioned declaration resolves to most recent available
Regarding duplicates to be ignored:
  - within same location: has real 'duplicate' semantics
  - across locations: has 'redundant override' semantics
  • Loading branch information
haubi authored and merks committed Mar 26, 2024
1 parent 9056de7 commit 7877870
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 38 deletions.
Expand Up @@ -332,13 +332,16 @@ class TestTargetConversion {
target "TP1"
include "tp2.tpd"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava
com.google.guava // no version, last location (top level): resolve newest version
com.google.guava // ignore duplicate
com.google.guava;version="[11.0.0,12.0.0)" // redundant override
}
''', URI.createURI("tmp:/tp1.tpd"), resourceSet)
parser.parse('''
target "TP2"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava;version="[11.0.0,12.0.0)"
com.google.guava;version="[11.0.0,12.0.0)" // resolve specified version
com.google.guava;version="[11.0.0,12.0.0)" // ignore duplicate
}
''', URI.createURI("tmp:/tp2.tpd"), resourceSet)

Expand All @@ -362,9 +365,12 @@ class TestTargetConversion {

val String[] ids = targetDef.locations.map[resolvedIUs.map[id]].flatten
val Version[] versions = targetDef.locations.map[resolvedIUs.map[version]].flatten
assertEquals(1, ids.size)
assertEquals("com.google.guava", ids.head)
assertEquals("12.0.0", versions.head.toString)
assertEquals(2, ids.size)
assertEquals("com.google.guava", ids.get(0))
assertEquals("com.google.guava", ids.get(1))
assertEquals(2, versions.size)
assertTrue(versions.findFirst[it.toString == "11.0.2"] !== null)
assertTrue(versions.findFirst[it.toString == "12.0.0"] !== null)
}

@Test
Expand All @@ -378,13 +384,16 @@ class TestTargetConversion {
parser.parse('''
target "TP2"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava;version=[11.0.0,12.0.0)
com.google.guava;version=[11.0.0,12.0.0) // resolve specified version
com.google.guava;version=[11.0.0,12.0.0) // ignore duplicate
}
''', URI.createURI("tmp:/tp2.tpd"), resourceSet)
parser.parse('''
target "TP3"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava
com.google.guava // no version, last location (via includes): resolve newest version
com.google.guava // ignore duplicate
com.google.guava;version=[11.0.0,12.0.0) // redundant override
}
''', URI.createURI("tmp:/tp3.tpd"), resourceSet)

Expand All @@ -408,9 +417,12 @@ class TestTargetConversion {

val String[] ids = targetDef.locations.map[resolvedIUs.map[id]].flatten
val Version[] versions = targetDef.locations.map[resolvedIUs.map[version]].flatten
assertEquals(1, ids.size)
assertEquals("com.google.guava", ids.head)
assertEquals("12.0.0", versions.head.toString)
assertEquals(2, ids.size)
assertEquals("com.google.guava", ids.get(0))
assertEquals("com.google.guava", ids.get(1))
assertEquals(2, versions.size)
assertTrue(versions.findFirst[it.toString == "11.0.2"] !== null)
assertTrue(versions.findFirst[it.toString == "12.0.0"] !== null)
}

@Test
Expand All @@ -424,13 +436,15 @@ class TestTargetConversion {
parser.parse('''
target "TP2"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava;version=[11.0.0,12.0.0)
com.google.guava;version=[11.0.0,12.0.0) // resolve specified version
com.google.guava;version=[11.0.0,12.0.0) // ignore duplicate
}
''', URI.createURI("tmp:/tp2.tpd"), resourceSet)
parser.parse('''
target "TP3"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava
com.google.guava // no version: is overridden by subsequent location (via includes)
com.google.guava // ignore duplicate
}
''', URI.createURI("tmp:/tp3.tpd"), resourceSet)

Expand Down Expand Up @@ -470,13 +484,15 @@ class TestTargetConversion {
target "TP2"
include "tp3.tpd"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava;version=[11.0.0,12.0.0)
com.google.guava;version=[11.0.0,12.0.0) // resolve specified version
com.google.guava;version=[11.0.0,12.0.0) // ignore duplicate
}
''', URI.createURI("tmp:/tp2.tpd"), resourceSet)
parser.parse('''
target "TP3"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava
com.google.guava // no version: is overridden by subsequent location (via includes)
com.google.guava // ignore duplicate
}
''', URI.createURI("tmp:/tp3.tpd"), resourceSet)

Expand Down Expand Up @@ -516,13 +532,15 @@ class TestTargetConversion {
target "TP2"
include "tp3.tpd"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava
com.google.guava // no version, last location (via includes): resolve newest version
com.google.guava // ignore duplicate
}
''', URI.createURI("tmp:/tp2.tpd"), resourceSet)
parser.parse('''
target "TP3"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava;version=[11.0.0,12.0.0)
com.google.guava;version=[11.0.0,12.0.0) // resolve specified version
com.google.guava;version=[11.0.0,12.0.0) // ignore duplicate
}
''', URI.createURI("tmp:/tp3.tpd"), resourceSet)

Expand All @@ -546,9 +564,12 @@ class TestTargetConversion {

val String[] ids = targetDef.locations.map[resolvedIUs.map[id]].flatten
val Version[] versions = targetDef.locations.map[resolvedIUs.map[version]].flatten
assertEquals(1, ids.size)
assertEquals("com.google.guava", ids.head)
assertEquals("12.0.0", versions.head.toString)
assertEquals(2, ids.size)
assertEquals("com.google.guava", ids.get(0))
assertEquals("com.google.guava", ids.get(1))
assertEquals(2, versions.size)
assertTrue(versions.findFirst[it.toString == "11.0.2"] !== null)
assertTrue(versions.findFirst[it.toString == "12.0.0"] !== null)
}

@Test
Expand All @@ -558,10 +579,12 @@ class TestTargetConversion {
target "TP1"
include "tp2.tpd"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava
com.google.guava // no version: is overridden by subsequent location
com.google.guava // ignore duplicate
}
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava;version="[11.0.0,12.0.0)"
com.google.guava;version="[11.0.0,12.0.0)" // resolve specified version
com.google.guava;version="[11.0.0,12.0.0)" // ignore duplicate
}
''', URI.createURI("tmp:/tp1.tpd"), resourceSet)

Expand Down Expand Up @@ -597,10 +620,12 @@ class TestTargetConversion {
target "TP1"
include "tp2.tpd"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava;version="[11.0.0,12.0.0)"
com.google.guava;version="[11.0.0,12.0.0)" // resolve specified version
com.google.guava;version="[11.0.0,12.0.0)" // ignore duplicate
}
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava
com.google.guava // no version, last location: resolve newest version
com.google.guava // ignore duplicate
}
''', URI.createURI("tmp:/tp1.tpd"), resourceSet)

Expand All @@ -624,9 +649,12 @@ class TestTargetConversion {

val String[] ids = targetDef.locations.map[resolvedIUs.map[id]].flatten
val Version[] versions = targetDef.locations.map[resolvedIUs.map[version]].flatten
assertEquals(1, ids.size)
assertEquals("com.google.guava", ids.head)
assertEquals("12.0.0", versions.head.toString)
assertEquals(2, ids.size)
assertEquals("com.google.guava", ids.get(0))
assertEquals("com.google.guava", ids.get(1))
assertEquals(2, versions.size)
assertTrue(versions.findFirst[it.toString == "11.0.2"] !== null)
assertTrue(versions.findFirst[it.toString == "12.0.0"] !== null)
}

@Test
Expand All @@ -636,8 +664,10 @@ class TestTargetConversion {
target "TP1"
include "tp2.tpd"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava;version="[11.0.0,12.0.0)"
com.google.guava
com.google.guava;version="[11.0.0,12.0.0)" // resolve specified version
com.google.guava;version="[11.0.0,12.0.0)" // ignore duplicate
com.google.guava // no version, not first declaration in location: ignored
com.google.guava // ignore duplicate
}
''', URI.createURI("tmp:/tp1.tpd"), resourceSet)

Expand Down Expand Up @@ -673,8 +703,10 @@ class TestTargetConversion {
target "TP1"
include "tp2.tpd"
location "http://download.eclipse.org/tools/orbit/downloads/drops/R20130517111416/repository/" {
com.google.guava
com.google.guava;version="[11.0.0,12.0.0)"
com.google.guava // no version, first declaration in location: resolve newest version
com.google.guava;version="[11.0.0,12.0.0)" // resolve specified version
com.google.guava;version="[11.0.0,12.0.0)" // ignore duplicate
com.google.guava // ignore duplicate
}
''', URI.createURI("tmp:/tp1.tpd"), resourceSet)

Expand All @@ -698,9 +730,12 @@ class TestTargetConversion {

val String[] ids = targetDef.locations.map[resolvedIUs.map[id]].flatten
val Version[] versions = targetDef.locations.map[resolvedIUs.map[version]].flatten
assertEquals(1, ids.size)
assertEquals("com.google.guava", ids.head)
assertEquals("12.0.0", versions.head.toString)
assertEquals(2, ids.size)
assertEquals("com.google.guava", ids.get(0))
assertEquals("com.google.guava", ids.get(1))
assertEquals(2, versions.size)
assertTrue(versions.findFirst[it.toString == "11.0.2"] !== null)
assertTrue(versions.findFirst[it.toString == "12.0.0"] !== null)
}

@Test
Expand Down
Expand Up @@ -220,6 +220,119 @@ class TestTargetGeneration {
'''.toString, content)
}

@Test
def void testSingleLocationManyIUVersions() {
val tp1 = parser.parse('''
target "TP1"
location "http://location.org/p2" {
an.iu;version=[1.2.0,2.0.0)
an.iu [2,3)
an.iu 3
} ''')

val resolvedTargetPlatform = ResolvedTargetPlatform.create(tp1, indexBuilder, mavenIndexBuilder);
resolvedTargetPlatform.resolve(new MetadataRepositoryManagerStub(new IQueryResultProvider<IInstallableUnit>() {
override listIUs(URI location) {
var List<IInstallableUnit> ret
if ("http://location.org/p2".equals(location.toString)) {
ret = newImmutableList(
IUStub.createBundle("an.iu", Version.createOSGi(1, 0, 0, "thequalifier")),
IUStub.createBundle("an.iu", Version.createOSGi(1, 2, 0, "thequalifier")),
IUStub.createBundle("an.iu", Version.createOSGi(2, 0, 0, null)),
IUStub.createBundle("an.iu", Version.createOSGi(2, 0, 1, "thequalifier")),
IUStub.createBundle("an.iu", Version.createOSGi(3, 0, 0, null)),
IUStub.createBundle("an.iu", Version.createOSGi(3, 1, 0, null)),
IUStub.createBundle("an.iu2", Version.createOSGi(1, 3, 74, null))
)
} else {
ret = emptyList
}
return ret;
}

}), new NullProgressMonitor());

val gen = new TargetDefinitionGenerator();
val content = gen.generate(resolvedTargetPlatform, 1);
assertTarget('''
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
<target name="TP1" sequenceNumber="1">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="false" includeConfigurePhase="false" type="InstallableUnit">
<unit id="an.iu" version="1.2.0.thequalifier"/>
<unit id="an.iu" version="2.0.1.thequalifier"/>
<unit id="an.iu" version="3.1.0"/>
<repository location="http://location.org/p2"/>
</location>
</locations>
</target>
'''.toString, content)
}

@Test
def void testManyLocationManyIUVersions() {
val tp1 = parser.parse('''
target "TP1"
location "http://location.org/p1" {
an.iu 3
}
location "http://location.org/p2" {
an.iu;version=[1.2.0,2.0.0)
an.iu [2,3)
}
''')

val resolvedTargetPlatform = ResolvedTargetPlatform.create(tp1, indexBuilder, mavenIndexBuilder);
resolvedTargetPlatform.resolve(new MetadataRepositoryManagerStub(new IQueryResultProvider<IInstallableUnit>() {
override listIUs(URI location) {
var List<IInstallableUnit> ret
if ("http://location.org/p1".equals(location.toString) ||
"http://location.org/p2".equals(location.toString)
) {
ret = newImmutableList(
IUStub.createBundle("an.iu", Version.createOSGi(1, 0, 0, "thequalifier")),
IUStub.createBundle("an.iu", Version.createOSGi(1, 2, 0, "thequalifier")),
IUStub.createBundle("an.iu", Version.createOSGi(2, 0, 0, null)),
IUStub.createBundle("an.iu", Version.createOSGi(2, 0, 1, "thequalifier")),
IUStub.createBundle("an.iu", Version.createOSGi(3, 0, 0, null)),
IUStub.createBundle("an.iu", Version.createOSGi(3, 1, 0, null)),
IUStub.createBundle("an.iu2", Version.createOSGi(1, 3, 74, null))
)
} else {
ret = emptyList
}
return ret;
}

}), new NullProgressMonitor());

val gen = new TargetDefinitionGenerator();
val content = gen.generate(resolvedTargetPlatform, 1);
assertTarget('''
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
<target name="TP1" sequenceNumber="1">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="false" includeConfigurePhase="false" type="InstallableUnit">
<unit id="an.iu" version="3.1.0"/>
<repository location="http://location.org/p1"/>
</location>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="false" includeConfigurePhase="false" type="InstallableUnit">
<unit id="an.iu" version="1.2.0.thequalifier"/>
<unit id="an.iu" version="2.0.1.thequalifier"/>
<repository location="http://location.org/p2"/>
</location>
</locations>
</target>
'''.toString, content)
}

@Test
def void testOptionSource() {
val tp1 = parser.parse('''
Expand Down
Expand Up @@ -139,12 +139,16 @@ private static ResolvedLocation resolveLocation(ListMultimap<String, Location> l
List<UnresolvedIU> ius = Lists.newArrayList();
Set<String> ids = Sets.newHashSet();
List<Location> list = locationIndex.get(locationUri);
for (Location location : list) {
for (Location location : list) { // in reverse order of declaration: overrides seen first
EList<IU> iuList = location.getIus();
for (IU iu : iuList) {
if (!ids.contains(iu.getID())) {
ids.add(iu.getID());
ius.add(new UnresolvedIU(iu.getID(), Strings.emptyToNull(iu.getVersion())));
for (IU iu : iuList) { // in order of declaration
String idv = iu.getID() + ":" + Strings.nullToEmpty(iu.getVersion());
if (!ids.contains(idv)) { // neither duplicates (same location), nor redundant overrides (across locations)
if (iu.getVersion() != null || !ids.contains(iu.getID())) { // can override the unversioned only
ids.add(idv);
ids.add(iu.getID());
ius.add(new UnresolvedIU(iu.getID(), Strings.emptyToNull(iu.getVersion())));
}
}
}
}
Expand Down

0 comments on commit 7877870

Please sign in to comment.