Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,21 @@ public class Artifact {

private final Coordinates coordinates;
private final Set<Coordinates> exclusions;
private final boolean forceVersion;

public Artifact(Coordinates coordinates, Coordinates... exclusions) {
this(coordinates, ImmutableSet.copyOf(exclusions));
}

public Artifact(Coordinates coordinates, Collection<Coordinates> exclusions) {
this(coordinates, exclusions, false);
}

public Artifact(
Coordinates coordinates, Collection<Coordinates> exclusions, boolean forceVersion) {
this.coordinates = Objects.requireNonNull(coordinates);
this.exclusions = ImmutableSet.copyOf(exclusions);
this.forceVersion = forceVersion;
}

public Coordinates getCoordinates() {
Expand All @@ -42,6 +49,10 @@ public Set<Coordinates> getExclusions() {
return exclusions;
}

public boolean isForceVersion() {
return forceVersion;
}

@Override
public String toString() {
if (exclusions.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class ConfigArtifact {
private String packaging;
private String version;
private Set<String> exclusions;
private boolean force_version;

public String getGroupId() {
return group;
Expand Down Expand Up @@ -56,4 +57,8 @@ public Set<Coordinates> getExclusions() {

return exclusions.stream().map(Coordinates::new).collect(ImmutableSet.toImmutableSet());
}

public boolean isForceVersion() {
return force_version;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,10 @@ public ResolverConfig(EventListener listener, String... args) throws IOException
art.getExtension(),
art.getClassifier(),
art.getVersion());
request.addArtifact(
coords.toString(),
art.getExclusions().stream()
.map(c -> c.getGroupId() + ":" + c.getArtifactId())
.toArray(String[]::new));
com.github.bazelbuild.rules_jvm_external.resolver.Artifact artifact =
new com.github.bazelbuild.rules_jvm_external.resolver.Artifact(
coords, art.getExclusions(), art.isForceVersion());
request.addArtifact(artifact);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,10 +496,18 @@ private GradleDependencyImpl createDependency(Artifact artifact) {
exclusion -> {
exclusions.add(new ExclusionImpl(exclusion.getGroupId(), exclusion.getArtifactId()));
});

// When force_version is true, use Gradle's !! shorthand which is equivalent to strictly()
// This forces the exact version and prevents transitive dependencies from overriding it
String version = coordinates.getVersion();
if (artifact.isForceVersion() && version != null && !version.isEmpty()) {
version = version + "!!";
}

return new GradleDependencyImpl(
coordinates.getGroupId(),
coordinates.getArtifactId(),
coordinates.getVersion(),
version,
exclusions,
coordinates.getClassifier(),
coordinates.getExtension());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,20 @@ private Dependency createBom(
private Dependency createDependency(
com.github.bazelbuild.rules_jvm_external.resolver.Artifact source) {
Coordinates coords = source.getCoordinates();

// When force_version is true, use Maven version range syntax [version] to force exact version
String version = coords.getVersion();
if (source.isForceVersion() && version != null && !version.isEmpty()) {
version = "[" + version + "]";
}

Artifact artifact =
new DefaultArtifact(
coords.getGroupId(),
coords.getArtifactId(),
coords.getClassifier(),
coords.getExtension(),
coords.getVersion());
version);

Set<Exclusion> excluded =
source.getExclusions().stream().map(this::createExclusion).collect(Collectors.toSet());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,47 @@ public boolean checkCredentials(String username, String pwd) {
assertEquals(coords, resolved.nodes().iterator().next());
}

@Test
public void shouldRespectForceVersionWhenResolvingConflicts() {
// When force_version is set on a lower version, it should win over the higher version
// that would normally be selected during version conflict resolution.
Coordinates lowerVersion = new Coordinates("com.example:forced:1.0");
Coordinates higherVersion = new Coordinates("com.example:forced:2.0");
Coordinates dependsOnLower = new Coordinates("com.example:uses-lower:1.0");
Coordinates dependsOnHigher = new Coordinates("com.example:uses-higher:1.0");

Path repo =
MavenRepo.create()
.add(lowerVersion)
.add(higherVersion)
.add(dependsOnLower, lowerVersion)
.add(dependsOnHigher, higherVersion)
.getPath();

// Create a request that forces the lower version using the new forceVersion capability
ResolutionRequest request = new ResolutionRequest().addRepository(repo.toUri());
request.addArtifact(dependsOnLower.toString());
// Force the lower version by creating an Artifact with forceVersion=true
Artifact forcedArtifact = new Artifact(lowerVersion, Set.of(), true);
request.addArtifact(forcedArtifact);
request.addArtifact(dependsOnHigher.toString());

// Without force_version implementation, this test will fail for Gradle resolver
// because it will resolve to the higher version (2.0) instead of the forced lower version (1.0)
Graph<Coordinates> graph = resolver.resolve(request).getResolution();

Set<Coordinates> forcedNodes =
graph.nodes().stream()
.filter(c -> "forced".equals(c.getArtifactId()))
.collect(Collectors.toSet());

assertEquals("Should resolve to exactly one version", 1, forcedNodes.size());

assertTrue(
"Should resolve to forced lower version when force_version is set",
forcedNodes.contains(lowerVersion));
}

protected ResolutionRequest prepareRequestFor(URI repo, Coordinates... coordinates) {
ResolutionRequest request = new ResolutionRequest().addRepository(repo);
for (Coordinates coordinate : coordinates) {
Expand Down
150 changes: 128 additions & 22 deletions tests/custom_maven_install/regression_testing_gradle_index.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
{
"__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
"packages": {
"androidx.annotation:annotation-jvm": [
"androidx.annotation"
],
"androidx.arch.core:core-common": [
"androidx.arch.core.internal",
"androidx.arch.core.util"
Expand Down Expand Up @@ -37,25 +34,6 @@
"com.google.guava:listenablefuture": [
"com.google.common.util.concurrent"
],
"com.squareup.okhttp3:okhttp": [
"okhttp3",
"okhttp3.internal",
"okhttp3.internal.authenticator",
"okhttp3.internal.cache",
"okhttp3.internal.cache2",
"okhttp3.internal.concurrent",
"okhttp3.internal.connection",
"okhttp3.internal.http",
"okhttp3.internal.http1",
"okhttp3.internal.http2",
"okhttp3.internal.io",
"okhttp3.internal.platform",
"okhttp3.internal.platform.android",
"okhttp3.internal.proxy",
"okhttp3.internal.publicsuffix",
"okhttp3.internal.tls",
"okhttp3.internal.ws"
],
"com.squareup.okio:okio-jvm": [
"okio",
"okio.internal"
Expand Down Expand Up @@ -136,6 +114,134 @@
]
},
"split_package_classes": {
"androidx.annotation:annotation": {
"androidx.annotation": [
"AnimRes",
"AnimatorRes",
"AnyRes",
"AnyThread",
"ArrayRes",
"AttrRes",
"BinderThread",
"BoolRes",
"CallSuper",
"CheckResult",
"ChecksSdkIntAtLeast",
"ColorInt",
"ColorLong",
"ColorRes",
"ContentView",
"DimenRes",
"Dimension",
"DoNotInline",
"DrawableRes",
"FloatRange",
"FontRes",
"FractionRes",
"GuardedBy",
"HalfFloat",
"IdRes",
"InspectableProperty",
"IntDef",
"IntRange",
"IntegerRes",
"InterpolatorRes",
"Keep",
"LayoutRes",
"LongDef",
"MainThread",
"MenuRes",
"NavigationRes",
"NonNull",
"Nullable",
"PluralsRes",
"Px",
"RawRes",
"RequiresApi",
"RequiresFeature",
"RequiresPermission",
"RestrictTo",
"Size",
"StringDef",
"StringRes",
"StyleRes",
"StyleableRes",
"TransitionRes",
"UiThread",
"VisibleForTesting",
"WorkerThread",
"XmlRes"
]
},
"androidx.annotation:annotation-jvm": {
"androidx.annotation": [
"AnimRes",
"AnimatorRes",
"AnyRes",
"AnyThread",
"ArrayRes",
"AttrRes",
"BinderThread",
"BoolRes",
"CallSuper",
"CheckResult",
"ChecksSdkIntAtLeast",
"ColorInt",
"ColorLong",
"ColorRes",
"ContentView",
"DeprecatedSinceApi",
"DimenRes",
"Dimension",
"Discouraged",
"DisplayContext",
"DoNotInline",
"DrawableRes",
"EmptySuper",
"FloatRange",
"FontRes",
"FractionRes",
"GravityInt",
"GuardedBy",
"HalfFloat",
"IdRes",
"InspectableProperty",
"IntDef",
"IntRange",
"IntegerRes",
"InterpolatorRes",
"Keep",
"LayoutRes",
"LongDef",
"MainThread",
"MenuRes",
"NavigationRes",
"NonNull",
"NonUiContext",
"Nullable",
"OpenForTesting",
"PluralsRes",
"Px",
"RawRes",
"RequiresApi",
"RequiresExtension",
"RequiresFeature",
"RequiresPermission",
"RestrictTo",
"ReturnThis",
"Size",
"StringDef",
"StringRes",
"StyleRes",
"StyleableRes",
"TransitionRes",
"UiContext",
"UiThread",
"VisibleForTesting",
"WorkerThread",
"XmlRes"
]
},
"androidx.collection:collection": {
"androidx.collection": [
"ArrayMap",
Expand Down
Loading