mirror of
https://github.com/rife2/bld
synced 2026-08-05 07:07:48 +02:00
Compare commits
1 commit
6a588fceae
...
295dfb1973
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
295dfb1973 |
|
|
@ -9,4 +9,4 @@ bld.javaOptions=
|
||||||
bld.javacOptions=
|
bld.javacOptions=
|
||||||
bld.repositories=MAVEN_CENTRAL,RIFE2_RELEASES,RIFE2_SNAPSHOTS
|
bld.repositories=MAVEN_CENTRAL,RIFE2_RELEASES,RIFE2_SNAPSHOTS
|
||||||
bld.sourceDirectories=core/src/bld/java
|
bld.sourceDirectories=core/src/bld/java
|
||||||
bld.version=2.4.0-SNAPSHOT
|
bld.version=2.3.1-SNAPSHOT
|
||||||
|
|
@ -1019,61 +1019,6 @@ public class BaseProject extends BuildExecutor {
|
||||||
return Module.parse(description);
|
return Module.parse(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new bill of materials instance.
|
|
||||||
*
|
|
||||||
* @param groupId the BOM group identifier
|
|
||||||
* @param artifactId the BOM artifact identifier
|
|
||||||
* @return a newly created {@code Bom} instance
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public Bom bom(String groupId, String artifactId) {
|
|
||||||
return new Bom(groupId, artifactId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new bill of materials instance.
|
|
||||||
*
|
|
||||||
* @param groupId the BOM group identifier
|
|
||||||
* @param artifactId the BOM artifact identifier
|
|
||||||
* @param version the BOM version
|
|
||||||
* @return a newly created {@code Bom} instance
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public Bom bom(String groupId, String artifactId, String version) {
|
|
||||||
return new Bom(groupId, artifactId, version(version));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new bill of materials instance.
|
|
||||||
*
|
|
||||||
* @param groupId the BOM group identifier
|
|
||||||
* @param artifactId the BOM artifact identifier
|
|
||||||
* @param version the BOM version
|
|
||||||
* @return a newly created {@code Bom} instance
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public Bom bom(String groupId, String artifactId, Version version) {
|
|
||||||
return new Bom(groupId, artifactId, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new bill of materials instance from a string representation.
|
|
||||||
* The format is {@code groupId:artifactId:version:classifier}.
|
|
||||||
* The {@code version} and {@code classifier} are optional, and an
|
|
||||||
* optional {@code @bom} or {@code @pom} type suffix is accepted.
|
|
||||||
* <p>
|
|
||||||
* If the string can't be successfully parsed, {@code null} will be returned.
|
|
||||||
*
|
|
||||||
* @param description the BOM string to parse
|
|
||||||
* @return a parsed instance of {@code Bom}; or
|
|
||||||
* {@code null} when the string couldn't be parsed
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public Bom bom(String description) {
|
|
||||||
return Bom.parse(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a local module instance.
|
* Creates a local module instance.
|
||||||
* <p>
|
* <p>
|
||||||
|
|
|
||||||
|
|
@ -271,10 +271,6 @@ public class BldCache {
|
||||||
finger_print.append(entry.getKey());
|
finger_print.append(entry.getKey());
|
||||||
finger_print.append('\n');
|
finger_print.append('\n');
|
||||||
if (entry.getValue() != null) {
|
if (entry.getValue() != null) {
|
||||||
for (var bom : entry.getValue().boms()) {
|
|
||||||
finger_print.append(bom.toString());
|
|
||||||
finger_print.append('\n');
|
|
||||||
}
|
|
||||||
for (var dependency : entry.getValue()) {
|
for (var dependency : entry.getValue()) {
|
||||||
finger_print.append(dependency.toString());
|
finger_print.append(dependency.toString());
|
||||||
finger_print.append('\n');
|
finger_print.append('\n');
|
||||||
|
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2001-2026 Geert Bevin (gbevin[remove] at uwyn dot com)
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
||||||
*/
|
|
||||||
package rife.bld.dependencies;
|
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains the information required to describe a bill of materials (BOM)
|
|
||||||
* in the build system.
|
|
||||||
* <p>
|
|
||||||
* A BOM is a POM whose dependency management section supplies versions
|
|
||||||
* during dependency resolution: dependencies that are declared without a
|
|
||||||
* version take the BOM's version, and transitive dependencies that match a
|
|
||||||
* BOM entry are pinned to the BOM's version. Versions that are explicitly
|
|
||||||
* declared in the build file, and versions provided through the
|
|
||||||
* {@code bld.override} property, always take precedence over a BOM.
|
|
||||||
* <p>
|
|
||||||
* BOMs don't transfer any artifacts, they only participate in resolution.
|
|
||||||
*
|
|
||||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public class Bom extends Dependency {
|
|
||||||
public Bom(String groupId, String artifactId) {
|
|
||||||
this(groupId, artifactId, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bom(String groupId, String artifactId, Version version) {
|
|
||||||
this(groupId, artifactId, version, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bom(String groupId, String artifactId, Version version, String classifier) {
|
|
||||||
super(groupId, artifactId, version, classifier, TYPE_BOM);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Pattern BOM_PATTERN = Pattern.compile("^(?<groupId>[^:@]+):(?<artifactId>[^:@]+)(?::(?<version>[^:@]+)(?::(?<classifier>[^:@]+))?)?(?:@(?:bom|pom))?$");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a BOM from a string representation.
|
|
||||||
* The format is {@code groupId:artifactId:version:classifier}.
|
|
||||||
* The {@code version} and {@code classifier} are optional, and an
|
|
||||||
* optional {@code @bom} or {@code @pom} type suffix is accepted.
|
|
||||||
* <p>
|
|
||||||
* If the string can't be successfully parsed, {@code null} will be returned.
|
|
||||||
*
|
|
||||||
* @param bom the BOM string to parse
|
|
||||||
* @return a parsed instance of {@code Bom}; or
|
|
||||||
* {@code null} when the string couldn't be parsed
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public static Bom parse(String bom) {
|
|
||||||
if (bom == null || bom.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var matcher = BOM_PATTERN.matcher(bom);
|
|
||||||
if (!matcher.matches()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var groupId = matcher.group("groupId");
|
|
||||||
var artifactId = matcher.group("artifactId");
|
|
||||||
var version = Version.parse(matcher.group("version"));
|
|
||||||
var classifier = matcher.group("classifier");
|
|
||||||
|
|
||||||
return new Bom(groupId, artifactId, version, classifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -40,14 +40,6 @@ public class Dependency {
|
||||||
// see https://github.com/apache/maven/blob/maven-4.0.0-beta-3/api/maven-api-core/src/main/java/org/apache/maven/api/Type.java
|
// see https://github.com/apache/maven/blob/maven-4.0.0-beta-3/api/maven-api-core/src/main/java/org/apache/maven/api/Type.java
|
||||||
public static final String TYPE_MODULAR_JAR = "modular-jar";
|
public static final String TYPE_MODULAR_JAR = "modular-jar";
|
||||||
|
|
||||||
/**
|
|
||||||
* The dependency type name for a bill of materials POM whose
|
|
||||||
* dependency management supplies versions during resolution.
|
|
||||||
*
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public static final String TYPE_BOM = "bom";
|
|
||||||
|
|
||||||
private final String groupId_;
|
private final String groupId_;
|
||||||
private final String artifactId_;
|
private final String artifactId_;
|
||||||
private final Version version_;
|
private final Version version_;
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ public class DependencyResolver {
|
||||||
var pom_dependencies = getMavenPom(dependency_).getDependencies(scopes);
|
var pom_dependencies = getMavenPom(dependency_).getDependencies(scopes);
|
||||||
var result = new DependencySet();
|
var result = new DependencySet();
|
||||||
for (var dependency : pom_dependencies) {
|
for (var dependency : pom_dependencies) {
|
||||||
result.add(resolution_.overrideTransitiveDependency(dependency.convertToDependency()));
|
result.add(resolution_.overrideDependency(dependency.convertToDependency()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -121,17 +121,19 @@ public class DependencyResolver {
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public DependencySet getAllDependencies(Scope... scopes) {
|
public DependencySet getAllDependencies(Scope... scopes) {
|
||||||
var prefetcher = new PomPrefetcher(resolution_, retriever_, repositories_);
|
var prefetcher = PomPrefetcher.create(resolution_, retriever_, repositories_);
|
||||||
try {
|
try {
|
||||||
return getAllDependencies(prefetcher, scopes);
|
return getAllDependencies(prefetcher, scopes);
|
||||||
} finally {
|
} finally {
|
||||||
|
if (prefetcher != null) {
|
||||||
prefetcher.shutdown();
|
prefetcher.shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DependencySet getAllDependencies(PomPrefetcher prefetcher, Scope... scopes) {
|
DependencySet getAllDependencies(PomPrefetcher prefetcher, Scope... scopes) {
|
||||||
var result = new DependencySet();
|
var result = new DependencySet();
|
||||||
var overridden = resolution_.overrideDeclaredDependency(dependency_);
|
var overridden = resolution_.overrideDependency(dependency_);
|
||||||
result.add(overridden);
|
result.add(overridden);
|
||||||
|
|
||||||
var dependency_queue = new ArrayList<PomDependency>();
|
var dependency_queue = new ArrayList<PomDependency>();
|
||||||
|
|
@ -149,9 +151,11 @@ public class DependencyResolver {
|
||||||
dependency_queue.addAll(next_dependencies);
|
dependency_queue.addAll(next_dependencies);
|
||||||
// speculatively retrieve the POMs of the queued dependencies in
|
// speculatively retrieve the POMs of the queued dependencies in
|
||||||
// parallel so that they are cached when they're processed in order
|
// parallel so that they are cached when they're processed in order
|
||||||
|
if (prefetcher != null) {
|
||||||
prefetcher.prefetch(next_dependencies);
|
prefetcher.prefetch(next_dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
// unless we find the next set of dependencies to add, stop resolving
|
// unless we find a next set of dependencies to add, stop resolving
|
||||||
parent = null;
|
parent = null;
|
||||||
next_dependencies = null;
|
next_dependencies = null;
|
||||||
|
|
||||||
|
|
@ -159,7 +163,7 @@ public class DependencyResolver {
|
||||||
// part of the results yet
|
// part of the results yet
|
||||||
while (!dependency_queue.isEmpty()) {
|
while (!dependency_queue.isEmpty()) {
|
||||||
var candidate = dependency_queue.remove(0);
|
var candidate = dependency_queue.remove(0);
|
||||||
var dependency = resolution_.overrideTransitiveDependency(candidate.convertToDependency());
|
var dependency = resolution_.overrideDependency(candidate.convertToDependency());
|
||||||
if (!result.contains(dependency)) {
|
if (!result.contains(dependency)) {
|
||||||
result.add(dependency);
|
result.add(dependency);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,7 @@ public class DependencyScopes extends LinkedHashMap<Scope, DependencySet> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Includes all the dependencies, local dependencies, local modules and
|
* Includes all the dependencies from another dependency scope map.
|
||||||
* BOMs from another dependency scope map.
|
|
||||||
*
|
*
|
||||||
* @param other the other map to include dependencies from
|
* @param other the other map to include dependencies from
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
|
|
@ -51,7 +50,7 @@ public class DependencyScopes extends LinkedHashMap<Scope, DependencySet> {
|
||||||
dependencies = new DependencySet();
|
dependencies = new DependencySet();
|
||||||
put(entry.getKey(), dependencies);
|
put(entry.getKey(), dependencies);
|
||||||
}
|
}
|
||||||
dependencies.include(entry.getValue());
|
dependencies.addAll(entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,37 +66,6 @@ public class DependencyScopes extends LinkedHashMap<Scope, DependencySet> {
|
||||||
return computeIfAbsent(scope, k -> new DependencySet());
|
return computeIfAbsent(scope, k -> new DependencySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the version-less dependencies that are not covered by the
|
|
||||||
* BOMs that are declared in their scope.
|
|
||||||
* <p>
|
|
||||||
* Scopes that don't declare any BOMs are not considered, their
|
|
||||||
* version-less dependencies simply resolve to the latest version.
|
|
||||||
*
|
|
||||||
* @param properties the properties to use to get artifacts
|
|
||||||
* @param retriever the retriever to use to get artifacts
|
|
||||||
* @param repositories the repositories to use for the BOM resolution
|
|
||||||
* @return the version-less dependencies that no BOM in their scope covers
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public List<Dependency> versionlessDependenciesWithoutBom(HierarchicalProperties properties, ArtifactRetriever retriever, List<Repository> repositories) {
|
|
||||||
var result = new ArrayList<Dependency>();
|
|
||||||
for (var scoped_dependencies : values()) {
|
|
||||||
if (scoped_dependencies.boms().isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var resolution = new VersionResolution(properties, retriever, repositories, scoped_dependencies.boms());
|
|
||||||
for (var dependency : scoped_dependencies) {
|
|
||||||
if (dependency.version().equals(VersionNumber.UNKNOWN) &&
|
|
||||||
!resolution.bomVersions().containsKey(dependency.toArtifactString()) &&
|
|
||||||
!result.contains(dependency)) {
|
|
||||||
result.add(dependency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the transitive set of dependencies that would be used for the compile scope in a project.
|
* Returns the transitive set of dependencies that would be used for the compile scope in a project.
|
||||||
*
|
*
|
||||||
|
|
@ -179,16 +147,14 @@ public class DependencyScopes extends LinkedHashMap<Scope, DependencySet> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DependencySet resolveScopedDependencies(HierarchicalProperties properties, ArtifactRetriever retriever, List<Repository> repositories, Scope[] resolvedScopes, Scope[] transitiveScopes, DependencySet excluded) {
|
private DependencySet resolveScopedDependencies(HierarchicalProperties properties, ArtifactRetriever retriever, List<Repository> repositories, Scope[] resolvedScopes, Scope[] transitiveScopes, DependencySet excluded) {
|
||||||
|
var resolution = new VersionResolution(properties);
|
||||||
var roots = new ArrayList<Dependency>();
|
var roots = new ArrayList<Dependency>();
|
||||||
var boms = new ArrayList<Bom>();
|
|
||||||
for (var scope : resolvedScopes) {
|
for (var scope : resolvedScopes) {
|
||||||
var scoped_dependencies = get(scope);
|
var scoped_dependencies = get(scope);
|
||||||
if (scoped_dependencies != null) {
|
if (scoped_dependencies != null) {
|
||||||
roots.addAll(scoped_dependencies);
|
roots.addAll(scoped_dependencies);
|
||||||
boms.addAll(scoped_dependencies.boms());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var resolution = new VersionResolution(properties, retriever, repositories, boms);
|
|
||||||
var dependencies = new ParallelDependencyResolver(resolution, retriever, repositories).resolveAllDependencies(roots, transitiveScopes);
|
var dependencies = new ParallelDependencyResolver(resolution, retriever, repositories).resolveAllDependencies(roots, transitiveScopes);
|
||||||
if (excluded != null) {
|
if (excluded != null) {
|
||||||
dependencies.removeAll(excluded);
|
dependencies.removeAll(excluded);
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ public class DependencySet extends AbstractSet<Dependency> implements Set<Depend
|
||||||
private final Map<Dependency, Dependency> dependencies_ = new LinkedHashMap<>();
|
private final Map<Dependency, Dependency> dependencies_ = new LinkedHashMap<>();
|
||||||
private final Set<LocalDependency> localDependencies_ = new LinkedHashSet<>();
|
private final Set<LocalDependency> localDependencies_ = new LinkedHashSet<>();
|
||||||
private final Set<LocalModule> localModules_ = new LinkedHashSet<>();
|
private final Set<LocalModule> localModules_ = new LinkedHashSet<>();
|
||||||
private final Set<Bom> boms_ = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty dependency set.
|
* Creates an empty dependency set.
|
||||||
|
|
@ -41,23 +40,7 @@ public class DependencySet extends AbstractSet<Dependency> implements Set<Depend
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public DependencySet(DependencySet other) {
|
public DependencySet(DependencySet other) {
|
||||||
include(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Includes all the dependencies, local dependencies, local modules and
|
|
||||||
* BOMs from another dependency set.
|
|
||||||
*
|
|
||||||
* @param other the other set to include
|
|
||||||
* @return this dependency set instance
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public DependencySet include(DependencySet other) {
|
|
||||||
addAll(other);
|
addAll(other);
|
||||||
localDependencies_.addAll(other.localDependencies_);
|
|
||||||
localModules_.addAll(other.localModules_);
|
|
||||||
boms_.addAll(other.boms_);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -98,32 +81,7 @@ public class DependencySet extends AbstractSet<Dependency> implements Set<Depend
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Includes a bill of materials in the dependency set.
|
* Includes a local module into the dependency set.
|
||||||
* <p>
|
|
||||||
* BOMs aren't transferred, their dependency management sections supply
|
|
||||||
* versions during the resolution of this dependency set.
|
|
||||||
*
|
|
||||||
* @param bom the BOM to include
|
|
||||||
* @return this dependency set instance
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public DependencySet include(Bom bom) {
|
|
||||||
boms_.add(bom);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the bills of materials.
|
|
||||||
*
|
|
||||||
* @return the set of BOMs
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public Set<Bom> boms() {
|
|
||||||
return boms_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Includes a local module in the dependency set.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Local modules aren't resolved and point to a location on
|
* Local modules aren't resolved and point to a location on
|
||||||
* the file system.
|
* the file system.
|
||||||
|
|
@ -195,7 +153,7 @@ public class DependencySet extends AbstractSet<Dependency> implements Set<Depend
|
||||||
/**
|
/**
|
||||||
* Returns the dependency that was stored in the set.
|
* Returns the dependency that was stored in the set.
|
||||||
* <p>
|
* <p>
|
||||||
* The version can be different from the dependency passed in, and this
|
* The version can be different from the dependency passed in and this
|
||||||
* method can be used to look up the actual version of the dependency in the set.
|
* method can be used to look up the actual version of the dependency in the set.
|
||||||
*
|
*
|
||||||
* @param dependency the dependency to look for
|
* @param dependency the dependency to look for
|
||||||
|
|
@ -220,7 +178,6 @@ public class DependencySet extends AbstractSet<Dependency> implements Set<Depend
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public String generateTransitiveDependencyTree(VersionResolution resolution, ArtifactRetriever retriever, List<Repository> repositories, Scope... scopes) {
|
public String generateTransitiveDependencyTree(VersionResolution resolution, ArtifactRetriever retriever, List<Repository> repositories, Scope... scopes) {
|
||||||
resolution = resolution.withBoms(retriever, repositories, boms_);
|
|
||||||
return new ParallelDependencyResolver(resolution, retriever, repositories).resolveAllDependencies(this, scopes).generateDependencyTree();
|
return new ParallelDependencyResolver(resolution, retriever, repositories).resolveAllDependencies(this, scopes).generateDependencyTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ public class ParallelDependencyResolver {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
var prefetcher = new PomPrefetcher(resolution_, retriever_, repositories_);
|
var prefetcher = PomPrefetcher.create(resolution_, retriever_, repositories_);
|
||||||
try {
|
try {
|
||||||
var resolutions = new ArrayList<Supplier<DependencySet>>(roots.size());
|
var resolutions = new ArrayList<Supplier<DependencySet>>(roots.size());
|
||||||
for (var root : roots) {
|
for (var root : roots) {
|
||||||
|
|
@ -73,8 +73,10 @@ public class ParallelDependencyResolver {
|
||||||
result.addAll(dependencies);
|
result.addAll(dependencies);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
if (prefetcher != null) {
|
||||||
prefetcher.shutdown();
|
prefetcher.shutdown();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,6 @@ import java.util.concurrent.Executors;
|
||||||
* <p>
|
* <p>
|
||||||
* A single instance can be shared by multiple concurrent resolutions, the
|
* A single instance can be shared by multiple concurrent resolutions, the
|
||||||
* POM of each unique dependency will only be prefetched once.
|
* POM of each unique dependency will only be prefetched once.
|
||||||
* <p>
|
|
||||||
* Prefetching only has benefits when the retrieved POMs are cached for the
|
|
||||||
* sequential resolution that follows, the prefetcher is inert when the
|
|
||||||
* retriever doesn't cache or when the resolution parallelism disables it.
|
|
||||||
*
|
*
|
||||||
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||||
* @since 2.4.0
|
* @since 2.4.0
|
||||||
|
|
@ -33,23 +29,32 @@ class PomPrefetcher {
|
||||||
private final ExecutorService executor_;
|
private final ExecutorService executor_;
|
||||||
private final Set<Dependency> submitted_ = ConcurrentHashMap.newKeySet();
|
private final Set<Dependency> submitted_ = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
PomPrefetcher(VersionResolution resolution, ArtifactRetriever retriever, List<Repository> repositories) {
|
/**
|
||||||
|
* Creates a prefetcher when it can be beneficial.
|
||||||
|
*
|
||||||
|
* @return the prefetcher; or {@code null} when the retriever doesn't
|
||||||
|
* cache the retrieved POMs or when the resolution parallelism disables it
|
||||||
|
* @since 2.4.0
|
||||||
|
*/
|
||||||
|
static PomPrefetcher create(VersionResolution resolution, ArtifactRetriever retriever, List<Repository> repositories) {
|
||||||
|
// prefetching only has benefits when the retrieved POMs are
|
||||||
|
// cached for the sequential resolution that follows
|
||||||
|
if (!retriever.isCaching() || resolution.resolutionParallelism() <= 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new PomPrefetcher(resolution, retriever, repositories);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PomPrefetcher(VersionResolution resolution, ArtifactRetriever retriever, List<Repository> repositories) {
|
||||||
resolution_ = resolution;
|
resolution_ = resolution;
|
||||||
retriever_ = retriever;
|
retriever_ = retriever;
|
||||||
repositories_ = repositories;
|
repositories_ = repositories;
|
||||||
if (retriever.isCaching() && resolution.resolutionParallelism() > 1) {
|
|
||||||
executor_ = Executors.newFixedThreadPool(resolution.resolutionParallelism());
|
executor_ = Executors.newFixedThreadPool(resolution.resolutionParallelism());
|
||||||
} else {
|
|
||||||
executor_ = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void prefetch(Collection<PomDependency> candidates) {
|
void prefetch(Collection<PomDependency> candidates) {
|
||||||
if (executor_ == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (var candidate : candidates) {
|
for (var candidate : candidates) {
|
||||||
var dependency = resolution_.overrideTransitiveDependency(candidate.convertToDependency());
|
var dependency = resolution_.overrideDependency(candidate.convertToDependency());
|
||||||
if (submitted_.add(dependency)) {
|
if (submitted_.add(dependency)) {
|
||||||
executor_.submit(() -> {
|
executor_.submit(() -> {
|
||||||
try {
|
try {
|
||||||
|
|
@ -65,8 +70,6 @@ class PomPrefetcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
if (executor_ != null) {
|
|
||||||
executor_.shutdownNow();
|
executor_.shutdownNow();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,14 @@ package rife.bld.dependencies;
|
||||||
|
|
||||||
import rife.ioc.HierarchicalProperties;
|
import rife.ioc.HierarchicalProperties;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for managing the versions that are applied
|
* This class is responsible for managing version overrides for dependencies.
|
||||||
* during dependency resolution.
|
|
||||||
* <p>
|
* <p>
|
||||||
* It allows users to specify a property key with the prefix "{@code bld.override}" where the values will be parsed as
|
* It allows users to specify a property keys with the prefix "{@code bld.override}" where the values will be parsed as
|
||||||
* a comma-separated list of dependencies with the versions that should override any other versions that are encountered.
|
* a comma-separated list of dependencies with the versions that should override any other versions that are encountered.
|
||||||
* <p>
|
* <p>
|
||||||
* For instance:
|
* For instance:
|
||||||
|
|
@ -32,18 +29,8 @@ import java.util.logging.Logger;
|
||||||
* bld.override-h2=com.h2database:h2:2.2.222
|
* bld.override-h2=com.h2database:h2:2.2.222
|
||||||
* </pre>
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* It can also import versions from the dependency management sections of
|
|
||||||
* bills of materials (BOMs). When resolving versions, the
|
|
||||||
* following precedence applies: a version from a "{@code bld.override}"
|
|
||||||
* property always wins, followed by a version explicitly declared
|
|
||||||
* in the build file, followed by a version from a BOM. Dependencies that
|
|
||||||
* are declared without a version and that are not covered by a BOM,
|
|
||||||
* resolve to their latest version.
|
|
||||||
* <p>
|
|
||||||
* It also captures other dependency resolution preferences, like the number
|
* It also captures other dependency resolution preferences, like the number
|
||||||
* of parallel artifact transfers through the "{@code bld.transferParallelism}"
|
* of parallel artifact transfers through the "{@code bld.transferParallelism}"
|
||||||
* property and the number of parallel POM retrievals during transitive
|
|
||||||
* dependency resolution through the "{@code bld.resolutionParallelism}"
|
|
||||||
* property.
|
* property.
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
|
|
@ -72,7 +59,6 @@ public class VersionResolution {
|
||||||
private static final int DEFAULT_RESOLUTION_PARALLELISM = 6;
|
private static final int DEFAULT_RESOLUTION_PARALLELISM = 6;
|
||||||
|
|
||||||
private final Map<String, Version> versionOverrides_ = new HashMap<>();
|
private final Map<String, Version> versionOverrides_ = new HashMap<>();
|
||||||
private final Map<String, Version> bomVersions_;
|
|
||||||
private final int transferParallelism_;
|
private final int transferParallelism_;
|
||||||
private final int resolutionParallelism_;
|
private final int resolutionParallelism_;
|
||||||
|
|
||||||
|
|
@ -114,61 +100,6 @@ public class VersionResolution {
|
||||||
}
|
}
|
||||||
transferParallelism_ = parseParallelism(properties, PROPERTY_TRANSFER_PARALLELISM, DEFAULT_TRANSFER_PARALLELISM);
|
transferParallelism_ = parseParallelism(properties, PROPERTY_TRANSFER_PARALLELISM, DEFAULT_TRANSFER_PARALLELISM);
|
||||||
resolutionParallelism_ = parseParallelism(properties, PROPERTY_RESOLUTION_PARALLELISM, DEFAULT_RESOLUTION_PARALLELISM);
|
resolutionParallelism_ = parseParallelism(properties, PROPERTY_RESOLUTION_PARALLELISM, DEFAULT_RESOLUTION_PARALLELISM);
|
||||||
bomVersions_ = Map.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
private VersionResolution(VersionResolution base, Map<String, Version> bomVersions) {
|
|
||||||
versionOverrides_.putAll(base.versionOverrides_);
|
|
||||||
transferParallelism_ = base.transferParallelism_;
|
|
||||||
resolutionParallelism_ = base.resolutionParallelism_;
|
|
||||||
bomVersions_ = Map.copyOf(bomVersions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance of the {@code VersionResolution} class from
|
|
||||||
* hierarchical properties and bills of materials whose dependency
|
|
||||||
* management sections supply versions during resolution.
|
|
||||||
* <p>
|
|
||||||
* The BOMs are imported in the order they're provided, the first BOM
|
|
||||||
* that manages a particular dependency determines its version. The
|
|
||||||
* version overrides of the properties take precedence over any BOM
|
|
||||||
* version, they also apply when resolving the BOMs themselves.
|
|
||||||
*
|
|
||||||
* @param properties the hierarchical properties that will be used to determine the version overrides
|
|
||||||
* @param retriever the retriever to use to get the BOMs
|
|
||||||
* @param repositories the repositories to resolve the BOMs in
|
|
||||||
* @param boms the BOMs to import
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public VersionResolution(HierarchicalProperties properties, ArtifactRetriever retriever, List<Repository> repositories, Collection<Bom> boms) {
|
|
||||||
this(new VersionResolution(properties), retriever, repositories, boms);
|
|
||||||
}
|
|
||||||
|
|
||||||
private VersionResolution(VersionResolution base, ArtifactRetriever retriever, List<Repository> repositories, Collection<Bom> boms) {
|
|
||||||
this(base, resolveBomVersions(base, retriever, repositories, boms));
|
|
||||||
}
|
|
||||||
|
|
||||||
VersionResolution withBoms(ArtifactRetriever retriever, List<Repository> repositories, Collection<Bom> boms) {
|
|
||||||
if (boms == null || boms.isEmpty()) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return new VersionResolution(this, retriever, repositories, boms);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<String, Version> resolveBomVersions(VersionResolution resolution, ArtifactRetriever retriever, List<Repository> repositories, Collection<Bom> boms) {
|
|
||||||
var bom_versions = new HashMap<String, Version>();
|
|
||||||
if (boms != null) {
|
|
||||||
for (var bom : boms) {
|
|
||||||
var pom = new DependencyResolver(resolution, retriever, repositories, bom).getMavenPom(bom);
|
|
||||||
for (var managed : pom.getManagedDependencies()) {
|
|
||||||
if (managed.version() != null && !managed.version().isBlank()) {
|
|
||||||
var dependency = managed.convertToDependency();
|
|
||||||
bom_versions.putIfAbsent(dependency.toArtifactString(), dependency.version());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bom_versions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int parseParallelism(HierarchicalProperties properties, String property, int defaultValue) {
|
private static int parseParallelism(HierarchicalProperties properties, String property, int defaultValue) {
|
||||||
|
|
@ -194,17 +125,11 @@ public class VersionResolution {
|
||||||
*/
|
*/
|
||||||
public Version overrideVersion(Dependency original) {
|
public Version overrideVersion(Dependency original) {
|
||||||
var overridden = versionOverrides_.get(original.toArtifactString());
|
var overridden = versionOverrides_.get(original.toArtifactString());
|
||||||
if (overridden != null) {
|
if (overridden == null) {
|
||||||
return overridden;
|
|
||||||
}
|
|
||||||
if (VersionNumber.UNKNOWN.equals(original.version())) {
|
|
||||||
var bom_version = bomVersions_.get(original.toArtifactString());
|
|
||||||
if (bom_version != null) {
|
|
||||||
return bom_version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return original.version();
|
return original.version();
|
||||||
}
|
}
|
||||||
|
return overridden;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides the version of a given dependency with the corresponding overridden version and
|
* Overrides the version of a given dependency with the corresponding overridden version and
|
||||||
|
|
@ -219,63 +144,9 @@ public class VersionResolution {
|
||||||
if (overridden == null) {
|
if (overridden == null) {
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
return withVersion(original, overridden);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies version overrides to a dependency that was explicitly declared
|
|
||||||
* in the build file.
|
|
||||||
* <p>
|
|
||||||
* A version from the {@code bld.override} property always takes
|
|
||||||
* precedence. A bill of materials version is only applied when the
|
|
||||||
* dependency was declared without a version, an explicitly declared
|
|
||||||
* version is never rewritten by a BOM.
|
|
||||||
*
|
|
||||||
* @param declared the declared dependency to apply overrides to
|
|
||||||
* @return the dependency with the overridden version if one applies; or
|
|
||||||
* the original dependency otherwise
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public Dependency overrideDeclaredDependency(Dependency declared) {
|
|
||||||
var overridden = versionOverrides_.get(declared.toArtifactString());
|
|
||||||
if (overridden == null && VersionNumber.UNKNOWN.equals(declared.version())) {
|
|
||||||
overridden = bomVersions_.get(declared.toArtifactString());
|
|
||||||
}
|
|
||||||
if (overridden == null) {
|
|
||||||
return declared;
|
|
||||||
}
|
|
||||||
return withVersion(declared, overridden);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies version overrides to a transitive dependency that was
|
|
||||||
* encountered during resolution.
|
|
||||||
* <p>
|
|
||||||
* A version from the {@code bld.override} property always takes
|
|
||||||
* precedence, followed by a matching bill of materials version that
|
|
||||||
* pins the transitive dependency regardless of the version its parent
|
|
||||||
* POM declared.
|
|
||||||
*
|
|
||||||
* @param transitive the transitive dependency to apply overrides to
|
|
||||||
* @return the dependency with the overridden version if one applies; or
|
|
||||||
* the original dependency otherwise
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public Dependency overrideTransitiveDependency(Dependency transitive) {
|
|
||||||
var overridden = versionOverrides_.get(transitive.toArtifactString());
|
|
||||||
if (overridden == null) {
|
|
||||||
overridden = bomVersions_.get(transitive.toArtifactString());
|
|
||||||
}
|
|
||||||
if (overridden == null) {
|
|
||||||
return transitive;
|
|
||||||
}
|
|
||||||
return withVersion(transitive, overridden);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dependency withVersion(Dependency original, Version version) {
|
|
||||||
return new Dependency(original.groupId(),
|
return new Dependency(original.groupId(),
|
||||||
original.artifactId(),
|
original.artifactId(),
|
||||||
version,
|
overridden,
|
||||||
original.classifier(),
|
original.classifier(),
|
||||||
original.type(),
|
original.type(),
|
||||||
original.exclusions(),
|
original.exclusions(),
|
||||||
|
|
@ -292,18 +163,6 @@ public class VersionResolution {
|
||||||
return versionOverrides_;
|
return versionOverrides_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the map of versions that were imported from bills of
|
|
||||||
* materials, where the key is the name of the dependency and the value
|
|
||||||
* is the managed version.
|
|
||||||
*
|
|
||||||
* @return the map of BOM versions
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public Map<String, Version> bomVersions() {
|
|
||||||
return bomVersions_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of artifact transfers that are performed in parallel,
|
* Returns the number of artifact transfers that are performed in parallel,
|
||||||
* {@code 1} means transfers are sequential.
|
* {@code 1} means transfers are sequential.
|
||||||
|
|
|
||||||
|
|
@ -129,17 +129,6 @@ class Xml2MavenPom extends Xml2Data {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<PomDependency> getManagedDependencies() {
|
|
||||||
var result = new LinkedHashSet<PomDependency>();
|
|
||||||
// iterate the values since putting an entry with an equal key
|
|
||||||
// preserves the original key instance while the value reflects
|
|
||||||
// the actual managed dependency
|
|
||||||
for (var managed : dependencyManagement_.values()) {
|
|
||||||
result.add(resolveDependency(managed));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
PomDependency resolveDependency(PomDependency dependency) {
|
PomDependency resolveDependency(PomDependency dependency) {
|
||||||
return new PomDependency(
|
return new PomDependency(
|
||||||
resolveMavenProperties(dependency.groupId()),
|
resolveMavenProperties(dependency.groupId()),
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,6 @@ public class DownloadOperation extends AbstractOperation<DownloadOperation> {
|
||||||
if (!silent()) {
|
if (!silent()) {
|
||||||
System.out.println("Analyzing dependencies...");
|
System.out.println("Analyzing dependencies...");
|
||||||
}
|
}
|
||||||
executeReportUncoveredDependencies();
|
|
||||||
executeDownloadCompileDependencies();
|
executeDownloadCompileDependencies();
|
||||||
executeDownloadProvidedDependencies();
|
executeDownloadProvidedDependencies();
|
||||||
executeDownloadRuntimeDependencies();
|
executeDownloadRuntimeDependencies();
|
||||||
|
|
@ -73,21 +72,6 @@ public class DownloadOperation extends AbstractOperation<DownloadOperation> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Part of the {@link #execute} operation, warns about version-less
|
|
||||||
* dependencies that are not covered by a BOM in their scope.
|
|
||||||
*
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
protected void executeReportUncoveredDependencies() {
|
|
||||||
if (silent()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (var dependency : dependencies().versionlessDependenciesWithoutBom(properties(), artifactRetriever(), repositories())) {
|
|
||||||
System.out.println("Warning: '" + dependency.toArtifactString() + "' isn't covered by a BOM, its latest version will be used");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part of the {@link #execute} operation, download the {@code compile} scope artifacts.
|
* Part of the {@link #execute} operation, download the {@code compile} scope artifacts.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ public class PublishOperation extends AbstractOperation<PublishOperation> {
|
||||||
|
|
||||||
private ZonedDateTime moment_ = null;
|
private ZonedDateTime moment_ = null;
|
||||||
private final List<Repository> repositories_ = new ArrayList<>();
|
private final List<Repository> repositories_ = new ArrayList<>();
|
||||||
private final List<Repository> dependencyRepositories_ = new ArrayList<>();
|
|
||||||
private final DependencyScopes dependencies_ = new DependencyScopes();
|
private final DependencyScopes dependencies_ = new DependencyScopes();
|
||||||
private PublishInfo info_ = new PublishInfo();
|
private PublishInfo info_ = new PublishInfo();
|
||||||
private PublishProperties publishProperties_ = new PublishProperties();
|
private PublishProperties publishProperties_ = new PublishProperties();
|
||||||
|
|
@ -79,7 +78,6 @@ public class PublishOperation extends AbstractOperation<PublishOperation> {
|
||||||
}
|
}
|
||||||
|
|
||||||
executeValidateArtifacts();
|
executeValidateArtifacts();
|
||||||
executeResolveVersionlessDependencies();
|
|
||||||
|
|
||||||
var actual_version = info().version();
|
var actual_version = info().version();
|
||||||
|
|
||||||
|
|
@ -105,50 +103,6 @@ public class PublishOperation extends AbstractOperation<PublishOperation> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Part of the {@link #execute} operation, resolves the versions of
|
|
||||||
* dependencies that were declared without one and that are not covered
|
|
||||||
* by a BOM in the same scope, so that the published POM is always
|
|
||||||
* complete.
|
|
||||||
* <p>
|
|
||||||
* BOMs that were declared without a version are resolved to their
|
|
||||||
* latest version too.
|
|
||||||
*
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
protected void executeResolveVersionlessDependencies() {
|
|
||||||
for (var scope : List.of(Scope.compile, Scope.runtime, Scope.provided)) {
|
|
||||||
var scoped_dependencies = dependencies().get(scope);
|
|
||||||
if (scoped_dependencies == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve the versions of BOMs that were declared without one
|
|
||||||
if (!scoped_dependencies.boms().isEmpty()) {
|
|
||||||
var base_resolution = new VersionResolution(properties());
|
|
||||||
var declared_boms = List.copyOf(scoped_dependencies.boms());
|
|
||||||
scoped_dependencies.boms().clear();
|
|
||||||
for (var bom : declared_boms) {
|
|
||||||
if (bom.version().equals(VersionNumber.UNKNOWN)) {
|
|
||||||
var latest = new DependencyResolver(base_resolution, artifactRetriever(), dependencyRepositories(), bom).latestVersion();
|
|
||||||
bom = new Bom(bom.groupId(), bom.artifactId(), latest, bom.classifier());
|
|
||||||
}
|
|
||||||
scoped_dependencies.boms().add(bom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var resolution = new VersionResolution(properties(), artifactRetriever(), dependencyRepositories(), scoped_dependencies.boms());
|
|
||||||
for (var dependency : List.copyOf(scoped_dependencies)) {
|
|
||||||
if (dependency.version().equals(VersionNumber.UNKNOWN) &&
|
|
||||||
!resolution.bomVersions().containsKey(dependency.toArtifactString())) {
|
|
||||||
var latest = new DependencyResolver(resolution, artifactRetriever(), dependencyRepositories(), dependency).latestVersion();
|
|
||||||
scoped_dependencies.add(new Dependency(dependency.groupId(), dependency.artifactId(), latest,
|
|
||||||
dependency.classifier(), dependency.type(), dependency.exclusions(), dependency.parent()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part of the {@link #execute} operation, validates the publishing artifacts.
|
* Part of the {@link #execute} operation, validates the publishing artifacts.
|
||||||
*
|
*
|
||||||
|
|
@ -671,7 +625,6 @@ public class PublishOperation extends AbstractOperation<PublishOperation> {
|
||||||
offline(project.offline());
|
offline(project.offline());
|
||||||
properties(project.properties());
|
properties(project.properties());
|
||||||
artifactRetriever(project.artifactRetriever());
|
artifactRetriever(project.artifactRetriever());
|
||||||
dependencyRepositories(project.repositories());
|
|
||||||
dependencies().include(project.dependencies());
|
dependencies().include(project.dependencies());
|
||||||
artifacts(List.of(
|
artifacts(List.of(
|
||||||
new PublishArtifact(new File(project.buildDistDirectory(), project.jarFileName()), "", TYPE_JAR),
|
new PublishArtifact(new File(project.buildDistDirectory(), project.jarFileName()), "", TYPE_JAR),
|
||||||
|
|
@ -780,33 +733,6 @@ public class PublishOperation extends AbstractOperation<PublishOperation> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a list of repositories to resolve the dependencies against.
|
|
||||||
* <p>
|
|
||||||
* These are used to resolve the versions of dependencies that were
|
|
||||||
* declared without one, they are not publication targets.
|
|
||||||
*
|
|
||||||
* @param repositories a list of repositories against which dependencies will be resolved
|
|
||||||
* @return this operation instance
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public PublishOperation dependencyRepositories(List<Repository> repositories) {
|
|
||||||
dependencyRepositories_.addAll(repositories);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the repositories that dependencies will be resolved against.
|
|
||||||
* <p>
|
|
||||||
* This is a modifiable list that can be retrieved and changed.
|
|
||||||
*
|
|
||||||
* @return the repositories used for dependency resolution
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
public List<Repository> dependencyRepositories() {
|
|
||||||
return dependencyRepositories_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides scoped dependencies to reference in the publication.
|
* Provides scoped dependencies to reference in the publication.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ public class PurgeOperation extends AbstractOperation<PurgeOperation> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
executeReportUncoveredDependencies();
|
|
||||||
executePurgeCompileDependencies();
|
executePurgeCompileDependencies();
|
||||||
executePurgeProvidedDependencies();
|
executePurgeProvidedDependencies();
|
||||||
executePurgeRuntimeDependencies();
|
executePurgeRuntimeDependencies();
|
||||||
|
|
@ -65,21 +64,6 @@ public class PurgeOperation extends AbstractOperation<PurgeOperation> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Part of the {@link #execute} operation, warns about version-less
|
|
||||||
* dependencies that are not covered by a BOM in their scope.
|
|
||||||
*
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
protected void executeReportUncoveredDependencies() {
|
|
||||||
if (silent()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (var dependency : dependencies().versionlessDependenciesWithoutBom(properties(), artifactRetriever(), repositories())) {
|
|
||||||
System.out.println("Warning: '" + dependency.toArtifactString() + "' isn't covered by a BOM, its latest version will be used");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part of the {@link #execute} operation, purge the {@code compile} scope artifacts.
|
* Part of the {@link #execute} operation, purge the {@code compile} scope artifacts.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -35,21 +35,7 @@ public class UpdatesOperation extends AbstractOperation<UpdatesOperation> {
|
||||||
var scopes = new ArrayList<Scope>();
|
var scopes = new ArrayList<Scope>();
|
||||||
var dependencies = new ArrayList<Dependency>();
|
var dependencies = new ArrayList<Dependency>();
|
||||||
for (var entry : dependencies_.entrySet()) {
|
for (var entry : dependencies_.entrySet()) {
|
||||||
var scoped_dependencies = entry.getValue();
|
for (var dependency : entry.getValue()) {
|
||||||
for (var bom : scoped_dependencies.boms()) {
|
|
||||||
scopes.add(entry.getKey());
|
|
||||||
dependencies.add(bom);
|
|
||||||
}
|
|
||||||
|
|
||||||
// dependencies that are declared without a version and that are
|
|
||||||
// covered by a BOM in the same scope have their version governed
|
|
||||||
// by that BOM, the BOM update itself carries their update signal
|
|
||||||
var scope_resolution = new VersionResolution(properties(), artifactRetriever(), repositories(), scoped_dependencies.boms());
|
|
||||||
for (var dependency : scoped_dependencies) {
|
|
||||||
if (VersionNumber.UNKNOWN.equals(dependency.version()) &&
|
|
||||||
scope_resolution.bomVersions().containsKey(dependency.toArtifactString())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
scopes.add(entry.getKey());
|
scopes.add(entry.getKey());
|
||||||
dependencies.add(dependency);
|
dependencies.add(dependency);
|
||||||
}
|
}
|
||||||
|
|
@ -62,13 +48,9 @@ public class UpdatesOperation extends AbstractOperation<UpdatesOperation> {
|
||||||
var dependency = dependencies.get(i);
|
var dependency = dependencies.get(i);
|
||||||
var latest = latest_versions.get(i);
|
var latest = latest_versions.get(i);
|
||||||
if (latest.compareTo(dependency.version()) > 0) {
|
if (latest.compareTo(dependency.version()) > 0) {
|
||||||
if (dependency instanceof Bom) {
|
var latest_dependency = new Dependency(dependency.groupId(), dependency.artifactId(), latest,
|
||||||
result.scope(scopes.get(i)).include(new Bom(dependency.groupId(), dependency.artifactId(), latest,
|
dependency.classifier(), dependency.type());
|
||||||
dependency.classifier()));
|
result.scope(scopes.get(i)).include(latest_dependency);
|
||||||
} else {
|
|
||||||
result.scope(scopes.get(i)).include(new Dependency(dependency.groupId(), dependency.artifactId(), latest,
|
|
||||||
dependency.classifier(), dependency.type()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,9 +63,6 @@ public class UpdatesOperation extends AbstractOperation<UpdatesOperation> {
|
||||||
for (var entry : result.entrySet()) {
|
for (var entry : result.entrySet()) {
|
||||||
var scope = entry.getKey();
|
var scope = entry.getKey();
|
||||||
System.out.println(scope + ":");
|
System.out.println(scope + ":");
|
||||||
for (var bom : entry.getValue().boms()) {
|
|
||||||
System.out.println(" " + bom);
|
|
||||||
}
|
|
||||||
for (var dependency : entry.getValue()) {
|
for (var dependency : entry.getValue()) {
|
||||||
System.out.println(" " + dependency);
|
System.out.println(" " + dependency);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@ import rife.tools.StringUtils;
|
||||||
import rife.tools.exceptions.FileUtilsErrorException;
|
import rife.tools.exceptions.FileUtilsErrorException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static rife.bld.dependencies.Dependency.TYPE_JAR;
|
import static rife.bld.dependencies.Dependency.TYPE_JAR;
|
||||||
|
|
@ -154,7 +152,6 @@ public class PomBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dependencies() != null && !dependencies().isEmpty()) {
|
if (dependencies() != null && !dependencies().isEmpty()) {
|
||||||
addDependencyManagement(t);
|
|
||||||
addDependencies(t, Scope.compile);
|
addDependencies(t, Scope.compile);
|
||||||
addDependencies(t, Scope.runtime);
|
addDependencies(t, Scope.runtime);
|
||||||
addDependencies(t, Scope.provided);
|
addDependencies(t, Scope.provided);
|
||||||
|
|
@ -175,32 +172,6 @@ public class PomBuilder {
|
||||||
FileUtils.writeString(pomBuilder.build(), file);
|
FileUtils.writeString(pomBuilder.build(), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDependencyManagement(Template t) {
|
|
||||||
var boms = new LinkedHashMap<String, Bom>();
|
|
||||||
for (var scope : List.of(Scope.compile, Scope.runtime, Scope.provided)) {
|
|
||||||
var scoped_dependencies = dependencies().get(scope);
|
|
||||||
if (scoped_dependencies == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (var bom : scoped_dependencies.boms()) {
|
|
||||||
if (!bom.version().equals(VersionNumber.UNKNOWN)) {
|
|
||||||
boms.putIfAbsent(bom.toArtifactString(), bom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (boms.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var bom : boms.values()) {
|
|
||||||
t.setValueEncoded("dependency-management-groupId", bom.groupId());
|
|
||||||
t.setValueEncoded("dependency-management-artifactId", bom.artifactId());
|
|
||||||
t.setValueEncoded("dependency-management-version", bom.version());
|
|
||||||
t.appendBlock("dependency-management", "dependency-management-entry");
|
|
||||||
}
|
|
||||||
t.setBlock("dependency-management-tag");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addDependencies(Template t, Scope scope) {
|
private void addDependencies(Template t, Scope scope) {
|
||||||
var scoped_dependencies = dependencies().scope(scope);
|
var scoped_dependencies = dependencies().scope(scope);
|
||||||
if (!scoped_dependencies.isEmpty()) {
|
if (!scoped_dependencies.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -32,24 +32,6 @@
|
||||||
</properties>
|
</properties>
|
||||||
<!--/b-->
|
<!--/b-->
|
||||||
|
|
||||||
<!--v dependency-management-tag--><!--/v-->
|
|
||||||
<!--b dependency-management-tag-->
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<!--v dependency-management--><!--/v-->
|
|
||||||
<!--b dependency-management-entry-->
|
|
||||||
<dependency>
|
|
||||||
<groupId><!--v dependency-management-groupId--><!--/v--></groupId>
|
|
||||||
<artifactId><!--v dependency-management-artifactId--><!--/v--></artifactId>
|
|
||||||
<version><!--v dependency-management-version--><!--/v--></version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
<!--/b-->
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
<!--/b-->
|
|
||||||
|
|
||||||
<!--v dependencies-tag--><!--/v-->
|
<!--v dependencies-tag--><!--/v-->
|
||||||
<!--b dependencies-tag-->
|
<!--b dependencies-tag-->
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
||||||
|
|
@ -1,992 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2001-2026 Geert Bevin (gbevin[remove] at uwyn dot com)
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
||||||
*/
|
|
||||||
package rife.bld.dependencies;
|
|
||||||
|
|
||||||
import com.sun.net.httpserver.HttpServer;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import rife.bld.BldCache;
|
|
||||||
import rife.bld.dependencies.exceptions.ArtifactNotFoundException;
|
|
||||||
import rife.ioc.HierarchicalProperties;
|
|
||||||
import rife.tools.FileUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import static rife.bld.dependencies.RepositoryTestHelper.*;
|
|
||||||
import static rife.bld.dependencies.Scope.compile;
|
|
||||||
|
|
||||||
public class TestBom {
|
|
||||||
@Test
|
|
||||||
void testParse() {
|
|
||||||
assertEquals(new Bom("com.example", "bom1"), Bom.parse("com.example:bom1"));
|
|
||||||
assertEquals(new Bom("com.example", "bom1", new VersionNumber(1, 2, 3)), Bom.parse("com.example:bom1:1.2.3"));
|
|
||||||
assertEquals(new Bom("com.example", "bom1", new VersionNumber(1, 2, 3)), Bom.parse("com.example:bom1:1.2.3@bom"));
|
|
||||||
assertEquals(new Bom("com.example", "bom1", new VersionNumber(1, 2, 3)), Bom.parse("com.example:bom1:1.2.3@pom"));
|
|
||||||
assertEquals(new Bom("com.example", "bom1", new VersionNumber(1, 2, 3), "classifier1"), Bom.parse("com.example:bom1:1.2.3:classifier1"));
|
|
||||||
assertNull(Bom.parse(null));
|
|
||||||
assertNull(Bom.parse(""));
|
|
||||||
assertNull(Bom.parse("not@a@bom"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomFillsDeclaredVersion() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("1.4.0"), resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomPinsTransitiveDependency() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("b", "1.5.0")),
|
|
||||||
"a:1.0.0", pom("a", "1.0.0", dependency("b", "2.0.0")),
|
|
||||||
"b:1.5.0", pom("b", "1.5.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("1.5.0"), resolved.get(new Dependency("com.example", "b")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testExplicitDeclaredVersionWinsOverBom() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0")),
|
|
||||||
"a:3.0.0", pom("a", "3.0.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a", new VersionNumber(3, 0, 0)));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("3.0.0"), resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testVersionOverridePropertyWinsOverBomForTransitive() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("b", "1.5.0")),
|
|
||||||
"a:1.0.0", pom("a", "1.0.0", dependency("b", "2.0.0")),
|
|
||||||
"b:2.5.0", pom("b", "2.5.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var properties = new HierarchicalProperties();
|
|
||||||
properties.put(VersionResolution.PROPERTY_OVERRIDE_PREFIX, "com.example:b:2.5.0");
|
|
||||||
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(properties, ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("2.5.0"), resolved.get(new Dependency("com.example", "b")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testVersionOverridePropertyWinsOverBomForDeclared() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0")),
|
|
||||||
"a:2.5.0", pom("a", "2.5.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var properties = new HierarchicalProperties();
|
|
||||||
properties.put(VersionResolution.PROPERTY_OVERRIDE_PREFIX, "com.example:a:2.5.0");
|
|
||||||
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(properties, ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("2.5.0"), resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testVersionOverridePropertyAppliesToBomItself() throws Exception {
|
|
||||||
// only version 2.0.0 of the BOM is served, resolution succeeds
|
|
||||||
// solely when the override rewrites the declared BOM version
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:2.0.0", bomPom("bom1", "2.0.0", managed("a", "1.4.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var properties = new HierarchicalProperties();
|
|
||||||
properties.put(VersionResolution.PROPERTY_OVERRIDE_PREFIX, "com.example:bom1:2.0.0");
|
|
||||||
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(properties, ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("1.4.0"), resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testFirstBomWinsOnConflict() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("c", "1.0.0")),
|
|
||||||
"bom2:1.0.0", bomPom("bom2", "1.0.0", managed("c", "2.0.0")),
|
|
||||||
"c:1.0.0", pom("c", "1.0.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Bom("com.example", "bom2", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "c"));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("1.0.0"), resolved.get(new Dependency("com.example", "c")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testNestedBomImport() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0",
|
|
||||||
managed("d", "1.0.0") +
|
|
||||||
"<dependency><groupId>com.example</groupId><artifactId>bom2</artifactId><version>1.0.0</version><type>pom</type><scope>import</scope></dependency>"),
|
|
||||||
"bom2:1.0.0", bomPom("bom2", "1.0.0", managed("d", "9.9.9") + managed("e", "2.0.0")),
|
|
||||||
"d:1.0.0", pom("d", "1.0.0", ""),
|
|
||||||
"e:2.0.0", pom("e", "2.0.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "d"))
|
|
||||||
.include(new Dependency("com.example", "e"));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
// the importing BOM's own entry wins over the imported entry
|
|
||||||
assertEquals(Version.parse("1.0.0"), resolved.get(new Dependency("com.example", "d")).version());
|
|
||||||
// entries that are only imported apply as well
|
|
||||||
assertEquals(Version.parse("2.0.0"), resolved.get(new Dependency("com.example", "e")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomParentPomInheritance() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bomparent:1.0.0", bomPom("bomparent", "1.0.0", managed("a", "1.4.0") + managed("b", "9.9.9")),
|
|
||||||
"bom1:1.0.0", bomPomWithParent("bom1", "1.0.0", "bomparent", managed("b", "1.5.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", ""),
|
|
||||||
"b:1.5.0", pom("b", "1.5.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"))
|
|
||||||
.include(new Dependency("com.example", "b"));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
// entries inherited from the BOM's parent POM apply
|
|
||||||
assertEquals(Version.parse("1.4.0"), resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
// the BOM's own entry wins over its parent's entry
|
|
||||||
assertEquals(Version.parse("1.5.0"), resolved.get(new Dependency("com.example", "b")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomPropertyPlaceholders() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>bom1</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
<properties>
|
|
||||||
<dep.version>1.4.0</dep.version>
|
|
||||||
</properties>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency><groupId>com.example</groupId><artifactId>a</artifactId><version>${dep.version}</version></dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
</project>""",
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("1.4.0"), resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testUncoveredVersionlessStillResolvesLatest() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", ""),
|
|
||||||
"f:2.2.0", pom("f", "2.2.0", "")),
|
|
||||||
Map.of("f", metadata("f", "2.2.0", "1.0.0", "2.2.0")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var retriever = ArtifactRetriever.cachingInstance();
|
|
||||||
var repositories = serverRepositories(server);
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"))
|
|
||||||
.include(new Dependency("com.example", "f"));
|
|
||||||
scopes.scope(Scope.test)
|
|
||||||
// no BOMs in this scope : it's not reported on
|
|
||||||
.include(new Dependency("com.example", "f"));
|
|
||||||
|
|
||||||
// only the dependency that the BOM doesn't cover is reported
|
|
||||||
assertEquals(List.of(new Dependency("com.example", "f")),
|
|
||||||
scopes.versionlessDependenciesWithoutBom(new HierarchicalProperties(), retriever, repositories));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), retriever, repositories);
|
|
||||||
|
|
||||||
// covered by the BOM : the BOM version applies
|
|
||||||
assertEquals(Version.parse("1.4.0"), resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
// not covered by the BOM : the version stays unknown in the set,
|
|
||||||
// exactly as it would without any BOM declared
|
|
||||||
assertEquals(VersionNumber.UNKNOWN, resolved.get(new Dependency("com.example", "f")).version());
|
|
||||||
// and it still resolves to the latest version from the metadata
|
|
||||||
var resolution = new VersionResolution(new HierarchicalProperties())
|
|
||||||
.withBoms(retriever, repositories, List.of(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0))));
|
|
||||||
assertEquals(Version.parse("2.2.0"), new DependencyResolver(resolution, retriever, repositories, new Dependency("com.example", "f")).resolveVersion());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomScopeIsolation() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", ""),
|
|
||||||
"a:2.2.0", pom("a", "2.2.0", "")),
|
|
||||||
Map.of("a", metadata("a", "2.2.0", "1.4.0", "2.2.0")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
scopes.scope(Scope.test)
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
// the compile scope BOM applies to the compile scope resolution
|
|
||||||
var compile_resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("1.4.0"), compile_resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
|
|
||||||
// and doesn't leak into the test scope resolution, whose version
|
|
||||||
// stays unknown and falls back to the latest from the metadata
|
|
||||||
var test_resolved = scopes.resolveTestDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(VersionNumber.UNKNOWN, test_resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testMissingBomFailsLoudly() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of());
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "missing", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
|
|
||||||
assertThrows(ArtifactNotFoundException.class,
|
|
||||||
() -> scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server)));
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testManagedEntryWithoutVersionIsIgnored() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0",
|
|
||||||
"<dependency><groupId>com.example</groupId><artifactId>x</artifactId></dependency>" +
|
|
||||||
managed("a", "1.4.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
assertEquals(Version.parse("1.4.0"), resolved.get(new Dependency("com.example", "a")).version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomIsNotTransferred() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", "")));
|
|
||||||
server.start();
|
|
||||||
var tmp = Files.createTempDirectory("bomtransfers").toFile();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
var resolution = new VersionResolution(new HierarchicalProperties());
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), serverRepositories(server));
|
|
||||||
resolved.transferIntoDirectory(resolution, ArtifactRetriever.cachingInstance(), serverRepositories(server), tmp, tmp);
|
|
||||||
|
|
||||||
assertTrue(new File(tmp, "a-1.4.0.jar").exists());
|
|
||||||
assertEquals(1, tmp.list().length, "expected only the dependency artifact, found: " + List.of(tmp.list()));
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testGenerateTransitiveDependencyTreeWithBom() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("b", "1.5.0")),
|
|
||||||
"a:1.0.0", pom("a", "1.0.0", dependency("b", "2.0.0")),
|
|
||||||
"b:1.5.0", pom("b", "1.5.0", "")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var dependencies = new DependencySet();
|
|
||||||
dependencies.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)));
|
|
||||||
dependencies.include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
|
|
||||||
var tree = dependencies.generateTransitiveDependencyTree(new VersionResolution(null), ArtifactRetriever.cachingInstance(), serverRepositories(server), compile);
|
|
||||||
assertTrue(tree.contains("com.example:a:1.0.0"), "tree was:\n" + tree);
|
|
||||||
assertTrue(tree.contains("com.example:b:1.5.0"), "tree was:\n" + tree);
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testVersionResolutionBomSemantics() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0"))));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var properties = new HierarchicalProperties();
|
|
||||||
properties.put(VersionResolution.PROPERTY_OVERRIDE_PREFIX, "com.example:o:5.0.0");
|
|
||||||
properties.put(VersionResolution.PROPERTY_TRANSFER_PARALLELISM, "3");
|
|
||||||
var base = new VersionResolution(properties);
|
|
||||||
|
|
||||||
// no BOMs returns the same instance
|
|
||||||
assertSame(base, base.withBoms(ArtifactRetriever.cachingInstance(), serverRepositories(server), List.of()));
|
|
||||||
assertSame(base, base.withBoms(ArtifactRetriever.cachingInstance(), serverRepositories(server), null));
|
|
||||||
|
|
||||||
var resolution = base.withBoms(ArtifactRetriever.cachingInstance(), serverRepositories(server),
|
|
||||||
List.of(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0))));
|
|
||||||
|
|
||||||
// the public constructor imports BOMs identically
|
|
||||||
var constructed = new VersionResolution(properties, ArtifactRetriever.cachingInstance(), serverRepositories(server),
|
|
||||||
List.of(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0))));
|
|
||||||
assertEquals(resolution.bomVersions(), constructed.bomVersions());
|
|
||||||
assertEquals(resolution.versionOverrides(), constructed.versionOverrides());
|
|
||||||
assertEquals(resolution.transferParallelism(), constructed.transferParallelism());
|
|
||||||
|
|
||||||
// the derived instance preserves the overrides and parallelism settings
|
|
||||||
assertNotSame(base, resolution);
|
|
||||||
assertEquals(base.versionOverrides(), resolution.versionOverrides());
|
|
||||||
assertEquals(3, resolution.transferParallelism());
|
|
||||||
assertEquals(Map.of("com.example:a", Version.parse("1.4.0")), resolution.bomVersions());
|
|
||||||
|
|
||||||
// a declared dependency without version is filled in from the BOM
|
|
||||||
assertEquals(Version.parse("1.4.0"), resolution.overrideDeclaredDependency(new Dependency("com.example", "a")).version());
|
|
||||||
// a declared dependency with an explicit version is never rewritten by the BOM
|
|
||||||
assertEquals(Version.parse("3.0.0"), resolution.overrideDeclaredDependency(new Dependency("com.example", "a", new VersionNumber(3, 0, 0))).version());
|
|
||||||
// a transitive dependency is pinned by the BOM even when it has a version
|
|
||||||
assertEquals(Version.parse("1.4.0"), resolution.overrideTransitiveDependency(new Dependency("com.example", "a", new VersionNumber(2, 0, 0))).version());
|
|
||||||
// the version override property beats the BOM
|
|
||||||
assertEquals(Version.parse("5.0.0"), resolution.overrideDeclaredDependency(new Dependency("com.example", "o")).version());
|
|
||||||
// version resolution consults the BOM for unknown versions only
|
|
||||||
assertEquals(Version.parse("1.4.0"), resolution.overrideVersion(new Dependency("com.example", "a")));
|
|
||||||
assertEquals(Version.parse("2.0.0"), resolution.overrideVersion(new Dependency("com.example", "a", new VersionNumber(2, 0, 0))));
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomChangesInvalidateDependenciesCache() throws Exception {
|
|
||||||
var tmp = Files.createTempDirectory("bomcache").toFile();
|
|
||||||
try {
|
|
||||||
var repositories = List.of(new Repository("http://localhost/"));
|
|
||||||
|
|
||||||
var scopes_without_bom = new DependencyScopes();
|
|
||||||
scopes_without_bom.scope(compile).include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
|
|
||||||
var scopes_with_bom = new DependencyScopes();
|
|
||||||
scopes_with_bom.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
|
|
||||||
var cache = new BldCache(tmp, VersionResolution.dummy());
|
|
||||||
cache.cacheDependenciesHash(repositories, scopes_without_bom);
|
|
||||||
cache.writeCache();
|
|
||||||
|
|
||||||
// the same dependencies without BOM validate against the cache
|
|
||||||
var cache_same = new BldCache(tmp, VersionResolution.dummy());
|
|
||||||
cache_same.cacheDependenciesHash(repositories, scopes_without_bom);
|
|
||||||
assertTrue(cache_same.isDependenciesHashValid());
|
|
||||||
|
|
||||||
// adding a BOM invalidates the cache
|
|
||||||
var cache_bom = new BldCache(tmp, VersionResolution.dummy());
|
|
||||||
cache_bom.cacheDependenciesHash(repositories, scopes_with_bom);
|
|
||||||
assertFalse(cache_bom.isDependenciesHashValid());
|
|
||||||
|
|
||||||
// a different BOM version invalidates the cache too
|
|
||||||
cache_bom.writeCache();
|
|
||||||
var scopes_with_other_bom = new DependencyScopes();
|
|
||||||
scopes_with_other_bom.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(2, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
var cache_other_bom = new BldCache(tmp, VersionResolution.dummy());
|
|
||||||
cache_other_bom.cacheDependenciesHash(repositories, scopes_with_other_bom);
|
|
||||||
assertFalse(cache_other_bom.isDependenciesHashValid());
|
|
||||||
} finally {
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomSurvivesOperationDependenciesCopy() throws Exception {
|
|
||||||
// regression test : operations copy the project's dependency scopes
|
|
||||||
// through DependencyScopes.include, which used to lose the BOMs so
|
|
||||||
// that version-less dependencies resolved to their latest versions
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", ""),
|
|
||||||
"a:2.2.0", pom("a", "2.2.0", "")),
|
|
||||||
Map.of("a", metadata("a", "2.2.0", "1.4.0", "2.2.0")));
|
|
||||||
server.start();
|
|
||||||
var tmp = Files.createTempDirectory("bomcopy").toFile();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
var operation = new rife.bld.operations.DownloadOperation()
|
|
||||||
.artifactRetriever(ArtifactRetriever.cachingInstance())
|
|
||||||
.repositories(serverRepositories(server))
|
|
||||||
.dependencies(scopes)
|
|
||||||
.libCompileDirectory(tmp).libCompileModulesDirectory(tmp)
|
|
||||||
.libProvidedDirectory(tmp).libProvidedModulesDirectory(tmp)
|
|
||||||
.libRuntimeDirectory(tmp).libRuntimeModulesDirectory(tmp)
|
|
||||||
.libStandaloneDirectory(tmp).libStandaloneModulesDirectory(tmp)
|
|
||||||
.libTestDirectory(tmp).libTestModulesDirectory(tmp)
|
|
||||||
.silent(true);
|
|
||||||
operation.execute();
|
|
||||||
|
|
||||||
// the BOM version is downloaded, not the latest version
|
|
||||||
assertTrue(new File(tmp, "a-1.4.0.jar").exists());
|
|
||||||
assertFalse(new File(tmp, "a-2.2.0.jar").exists());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testMissingBomFailsLoudlyThroughOperation() throws Exception {
|
|
||||||
// regression test : a missing BOM also has to fail when the
|
|
||||||
// dependency scopes were copied into an operation, the BOM is
|
|
||||||
// deliberately the only artifact that is missing
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"a:1.0.0", pom("a", "1.0.0", "")));
|
|
||||||
server.start();
|
|
||||||
var tmp = Files.createTempDirectory("bommissing").toFile();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("com.example", "missing", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
|
|
||||||
var operation = new rife.bld.operations.DownloadOperation()
|
|
||||||
.artifactRetriever(ArtifactRetriever.cachingInstance())
|
|
||||||
.repositories(serverRepositories(server))
|
|
||||||
.dependencies(scopes)
|
|
||||||
.libCompileDirectory(tmp).libCompileModulesDirectory(tmp)
|
|
||||||
.libProvidedDirectory(tmp).libProvidedModulesDirectory(tmp)
|
|
||||||
.libRuntimeDirectory(tmp).libRuntimeModulesDirectory(tmp)
|
|
||||||
.libStandaloneDirectory(tmp).libStandaloneModulesDirectory(tmp)
|
|
||||||
.libTestDirectory(tmp).libTestModulesDirectory(tmp)
|
|
||||||
.silent(true);
|
|
||||||
|
|
||||||
assertThrows(ArtifactNotFoundException.class, operation::execute);
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class BomProject extends rife.bld.Project {
|
|
||||||
BomProject(File tmp, Repository repository) {
|
|
||||||
workDirectory = tmp;
|
|
||||||
pkg = "test.pkg";
|
|
||||||
name = "bom_project";
|
|
||||||
version = new VersionNumber(0, 0, 1);
|
|
||||||
repositories = List.of(repository);
|
|
||||||
}
|
|
||||||
|
|
||||||
void enableAutoDownloadPurge() {
|
|
||||||
autoDownloadPurge = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testProjectDownloadWithBoms() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0") + managed("b", "2.1.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", ""),
|
|
||||||
"a:2.2.0", pom("a", "2.2.0", ""),
|
|
||||||
"b:2.1.0", pom("b", "2.1.0", "")),
|
|
||||||
Map.of("a", metadata("a", "2.2.0", "1.4.0", "2.2.0"),
|
|
||||||
"b", metadata("b", "2.1.0", "2.1.0")));
|
|
||||||
server.start();
|
|
||||||
var tmp = Files.createTempDirectory("bomproject").toFile();
|
|
||||||
try {
|
|
||||||
var project = new BomProject(tmp, transferRepository(server));
|
|
||||||
project.dependencies().scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
project.dependencies().scope(Scope.test)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"))
|
|
||||||
.include(new Dependency("com.example", "b"));
|
|
||||||
|
|
||||||
assertEquals(0, project.execute(new String[]{"download"}));
|
|
||||||
|
|
||||||
// the BOM versions are downloaded in every scope,
|
|
||||||
// never the latest versions
|
|
||||||
assertTrue(new File(tmp, "lib/compile/a-1.4.0.jar").exists());
|
|
||||||
assertFalse(new File(tmp, "lib/compile/a-2.2.0.jar").exists());
|
|
||||||
assertTrue(new File(tmp, "lib/test/a-1.4.0.jar").exists());
|
|
||||||
assertFalse(new File(tmp, "lib/test/a-2.2.0.jar").exists());
|
|
||||||
assertTrue(new File(tmp, "lib/test/b-2.1.0.jar").exists());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testProjectAutoDownloadPurgeBomUpgrade() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0")),
|
|
||||||
"bom1:2.0.0", bomPom("bom1", "2.0.0", managed("a", "2.2.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", ""),
|
|
||||||
"a:2.2.0", pom("a", "2.2.0", "")),
|
|
||||||
Map.of("a", metadata("a", "2.2.0", "1.4.0", "2.2.0")));
|
|
||||||
server.start();
|
|
||||||
var tmp = Files.createTempDirectory("bomupgrade").toFile();
|
|
||||||
try {
|
|
||||||
var project = new BomProject(tmp, transferRepository(server));
|
|
||||||
project.enableAutoDownloadPurge();
|
|
||||||
project.dependencies().scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
assertEquals(0, project.execute(new String[]{"version"}));
|
|
||||||
assertTrue(new File(tmp, "lib/compile/a-1.4.0.jar").exists());
|
|
||||||
|
|
||||||
// running again with an identical BOM declaration
|
|
||||||
// doesn't invalidate the dependencies cache
|
|
||||||
project = new BomProject(tmp, transferRepository(server));
|
|
||||||
project.enableAutoDownloadPurge();
|
|
||||||
project.dependencies().scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
assertEquals(0, project.execute(new String[]{"version"}));
|
|
||||||
assertTrue(new File(tmp, "lib/compile/a-1.4.0.jar").exists());
|
|
||||||
|
|
||||||
// upgrading the BOM version invalidates the cache,
|
|
||||||
// downloads the new version and purges the old one
|
|
||||||
project = new BomProject(tmp, transferRepository(server));
|
|
||||||
project.enableAutoDownloadPurge();
|
|
||||||
project.dependencies().scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(2, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
assertEquals(0, project.execute(new String[]{"version"}));
|
|
||||||
assertTrue(new File(tmp, "lib/compile/a-2.2.0.jar").exists());
|
|
||||||
assertFalse(new File(tmp, "lib/compile/a-1.4.0.jar").exists());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testProjectUpdatesWithBom() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0"))),
|
|
||||||
Map.of("bom1", metadata("bom1", "2.0.0", "1.0.0", "2.0.0"),
|
|
||||||
"a", metadata("a", "9.9.9", "1.4.0", "9.9.9")));
|
|
||||||
server.start();
|
|
||||||
var tmp = Files.createTempDirectory("bomupdates").toFile();
|
|
||||||
try {
|
|
||||||
var project = new BomProject(tmp, transferRepository(server));
|
|
||||||
project.dependencies().scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
var original_out = System.out;
|
|
||||||
var captured = new java.io.ByteArrayOutputStream();
|
|
||||||
System.setOut(new java.io.PrintStream(captured, true));
|
|
||||||
int status;
|
|
||||||
try {
|
|
||||||
status = project.execute(new String[]{"updates"});
|
|
||||||
} finally {
|
|
||||||
System.setOut(original_out);
|
|
||||||
}
|
|
||||||
var output = captured.toString();
|
|
||||||
|
|
||||||
assertEquals(0, status);
|
|
||||||
// the newer BOM version is reported with its type suffix
|
|
||||||
assertTrue(output.contains("com.example:bom1:2.0.0@bom"), output);
|
|
||||||
// the version-less dependency covered by the BOM
|
|
||||||
// is not reported individually
|
|
||||||
assertFalse(output.contains("com.example:a"), output);
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testProjectDependencyTreeWithBom() throws Exception {
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"bom1:1.0.0", bomPom("bom1", "1.0.0", managed("a", "1.4.0")),
|
|
||||||
"a:1.4.0", pom("a", "1.4.0", "")),
|
|
||||||
Map.of("a", metadata("a", "2.2.0", "1.4.0", "2.2.0")));
|
|
||||||
server.start();
|
|
||||||
var tmp = Files.createTempDirectory("bomtree").toFile();
|
|
||||||
try {
|
|
||||||
var project = new BomProject(tmp, transferRepository(server));
|
|
||||||
project.dependencies().scope(compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
var original_out = System.out;
|
|
||||||
var captured = new java.io.ByteArrayOutputStream();
|
|
||||||
System.setOut(new java.io.PrintStream(captured, true));
|
|
||||||
int status;
|
|
||||||
try {
|
|
||||||
status = project.execute(new String[]{"dependency-tree"});
|
|
||||||
} finally {
|
|
||||||
System.setOut(original_out);
|
|
||||||
}
|
|
||||||
var output = captured.toString();
|
|
||||||
|
|
||||||
assertEquals(0, status);
|
|
||||||
// the tree reflects the BOM version, not the latest version
|
|
||||||
assertTrue(output.contains("com.example:a:1.4.0"), output);
|
|
||||||
assertFalse(output.contains("com.example:a:2.2.0"), output);
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testProjectMissingBomFails() throws Exception {
|
|
||||||
// the BOM is deliberately the only artifact that is missing
|
|
||||||
var server = createArtifactServer(Map.of(
|
|
||||||
"a:1.0.0", pom("a", "1.0.0", "")));
|
|
||||||
server.start();
|
|
||||||
var tmp = Files.createTempDirectory("bommissingproject").toFile();
|
|
||||||
try {
|
|
||||||
var project = new BomProject(tmp, transferRepository(server));
|
|
||||||
project.dependencies().scope(compile)
|
|
||||||
.include(new Bom("com.example", "missing", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
|
|
||||||
assertNotEquals(0, project.execute(new String[]{"download"}));
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Repository transferRepository(HttpServer server) {
|
|
||||||
return new Repository("http://localhost:" + server.getAddress().getPort() + "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testProjectDownloadVertxBom() throws Exception {
|
|
||||||
// real-world reproduction of the scenario in
|
|
||||||
// https://github.com/rife2/bld/issues/59 through a full project
|
|
||||||
var tmp = Files.createTempDirectory("bomvertx").toFile();
|
|
||||||
try {
|
|
||||||
var project = new BomProject(tmp, getNextRepository());
|
|
||||||
project.dependencies().scope(compile)
|
|
||||||
.include(new Bom("io.vertx", "vertx-stack-depchain", new VersionNumber(4, 5, 12)))
|
|
||||||
.include(new Dependency("io.vertx", "vertx-core"))
|
|
||||||
.include(new Dependency("com.fasterxml.jackson.core", "jackson-databind"));
|
|
||||||
|
|
||||||
assertEquals(0, project.execute(new String[]{"download"}));
|
|
||||||
|
|
||||||
var jars = List.of(java.util.Objects.requireNonNull(new File(tmp, "lib/compile").list()));
|
|
||||||
assertTrue(jars.contains("vertx-core-4.5.12.jar"), jars.toString());
|
|
||||||
assertTrue(jars.contains("jackson-databind-2.16.1.jar"), jars.toString());
|
|
||||||
assertTrue(jars.contains("jackson-core-2.16.1.jar"), jars.toString());
|
|
||||||
// no jackson artifact resolved to anything but the BOM version
|
|
||||||
assertEquals(0, jars.stream().filter(jar -> jar.startsWith("jackson-") && !jar.contains("2.16.1")).count(), jars.toString());
|
|
||||||
} finally {
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testProjectDownloadJUnitBomTestScope() throws Exception {
|
|
||||||
// real-world reproduction of the scenario reported for the
|
|
||||||
// BOMs getting lost when operations copy the project scopes
|
|
||||||
var tmp = Files.createTempDirectory("bomjunit").toFile();
|
|
||||||
try {
|
|
||||||
var project = new BomProject(tmp, getNextRepository());
|
|
||||||
project.dependencies().scope(Scope.test)
|
|
||||||
.include(new Bom("org.junit", "junit-bom", new VersionNumber(6, 1, 1)))
|
|
||||||
.include(new Dependency("org.junit.jupiter", "junit-jupiter"))
|
|
||||||
.include(new Dependency("org.junit.platform", "junit-platform-console-standalone"));
|
|
||||||
|
|
||||||
assertEquals(0, project.execute(new String[]{"download"}));
|
|
||||||
|
|
||||||
var jars = List.of(java.util.Objects.requireNonNull(new File(tmp, "lib/test").list()));
|
|
||||||
assertTrue(jars.contains("junit-jupiter-6.1.1.jar"), jars.toString());
|
|
||||||
// every artifact that junit-bom manages is pinned to the BOM version
|
|
||||||
assertEquals(0, jars.stream().filter(jar -> jar.startsWith("junit-") &&
|
|
||||||
!jar.startsWith("junit-platform-console-standalone-") &&
|
|
||||||
!jar.contains("6.1.1")).count(), jars.toString());
|
|
||||||
// junit-bom deliberately doesn't manage the console-standalone
|
|
||||||
// distribution artifact, so it resolves to its latest version
|
|
||||||
assertTrue(jars.stream().anyMatch(jar -> jar.startsWith("junit-platform-console-standalone-")), jars.toString());
|
|
||||||
} finally {
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testProjectUpdatesRealBom() throws Exception {
|
|
||||||
// a real-world BOM with known newer releases reports its own
|
|
||||||
// update while its covered dependencies stay silent
|
|
||||||
var tmp = Files.createTempDirectory("bomupdatesreal").toFile();
|
|
||||||
try {
|
|
||||||
var project = new BomProject(tmp, getNextRepository());
|
|
||||||
project.dependencies().scope(Scope.test)
|
|
||||||
.include(new Bom("org.junit", "junit-bom", new VersionNumber(6, 1, 1)))
|
|
||||||
.include(new Dependency("org.junit.jupiter", "junit-jupiter"));
|
|
||||||
|
|
||||||
var original_out = System.out;
|
|
||||||
var captured = new java.io.ByteArrayOutputStream();
|
|
||||||
System.setOut(new java.io.PrintStream(captured, true));
|
|
||||||
int status;
|
|
||||||
try {
|
|
||||||
status = project.execute(new String[]{"updates"});
|
|
||||||
} finally {
|
|
||||||
System.setOut(original_out);
|
|
||||||
}
|
|
||||||
var output = captured.toString();
|
|
||||||
|
|
||||||
assertEquals(0, status);
|
|
||||||
assertTrue(output.contains("org.junit:junit-bom:"), output);
|
|
||||||
assertTrue(output.contains("@bom"), output);
|
|
||||||
assertFalse(output.contains("org.junit.jupiter:junit-jupiter:"), output);
|
|
||||||
} finally {
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomVertxAcceptance() {
|
|
||||||
// reproduction of the scenario in https://github.com/rife2/bld/issues/59
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(compile)
|
|
||||||
.include(new Bom("io.vertx", "vertx-stack-depchain", new VersionNumber(4, 5, 12)))
|
|
||||||
.include(new Dependency("io.vertx", "vertx-core"))
|
|
||||||
.include(new Dependency("com.fasterxml.jackson.core", "jackson-databind"));
|
|
||||||
|
|
||||||
var resolved = scopes.resolveCompileDependencies(new HierarchicalProperties(), ArtifactRetriever.cachingInstance(), getNextRepositories());
|
|
||||||
assertEquals(Version.parse("4.5.12"), resolved.get(new Dependency("io.vertx", "vertx-core")).version());
|
|
||||||
assertEquals(Version.parse("2.16.1"), resolved.get(new Dependency("com.fasterxml.jackson.core", "jackson-databind")).version());
|
|
||||||
assertEquals(Version.parse("2.16.1"), resolved.get(new Dependency("com.fasterxml.jackson.core", "jackson-core")).version());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Repository> serverRepositories(HttpServer server) {
|
|
||||||
return List.of(new Repository("http://localhost:" + server.getAddress().getPort() + "/"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpServer createArtifactServer(Map<String, String> poms)
|
|
||||||
throws IOException {
|
|
||||||
return createArtifactServer(poms, Map.of());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpServer createArtifactServer(Map<String, String> poms, Map<String, String> metadata)
|
|
||||||
throws IOException {
|
|
||||||
var server = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
|
|
||||||
server.createContext("/", exchange -> {
|
|
||||||
var segments = exchange.getRequestURI().getPath().split("/");
|
|
||||||
var filename = segments[segments.length - 1];
|
|
||||||
byte[] body = null;
|
|
||||||
if (filename.endsWith(".pom") && segments.length >= 3) {
|
|
||||||
var content = poms.get(segments[segments.length - 3] + ":" + segments[segments.length - 2]);
|
|
||||||
if (content != null) {
|
|
||||||
body = content.getBytes();
|
|
||||||
}
|
|
||||||
} else if (filename.endsWith(".jar") && segments.length >= 3) {
|
|
||||||
if (poms.containsKey(segments[segments.length - 3] + ":" + segments[segments.length - 2])) {
|
|
||||||
body = "jar".getBytes();
|
|
||||||
}
|
|
||||||
} else if (filename.equals("maven-metadata.xml") && segments.length >= 2) {
|
|
||||||
var content = metadata.get(segments[segments.length - 2]);
|
|
||||||
if (content != null) {
|
|
||||||
body = content.getBytes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (body == null) {
|
|
||||||
exchange.sendResponseHeaders(404, -1);
|
|
||||||
} else {
|
|
||||||
exchange.sendResponseHeaders(200, body.length);
|
|
||||||
exchange.getResponseBody().write(body);
|
|
||||||
}
|
|
||||||
exchange.close();
|
|
||||||
});
|
|
||||||
server.setExecutor(Executors.newCachedThreadPool());
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String dependency(String artifact, String version) {
|
|
||||||
return "<dependency><groupId>com.example</groupId><artifactId>" + artifact + "</artifactId><version>" + version + "</version></dependency>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String managed(String artifact, String version) {
|
|
||||||
return dependency(artifact, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String pom(String artifact, String version, String dependencies) {
|
|
||||||
return """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>%s</artifactId>
|
|
||||||
<version>%s</version>
|
|
||||||
<dependencies>%s</dependencies>
|
|
||||||
</project>""".formatted(artifact, version, dependencies);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String bomPom(String artifact, String version, String managedDependencies) {
|
|
||||||
return """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>%s</artifactId>
|
|
||||||
<version>%s</version>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>%s</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
</project>""".formatted(artifact, version, managedDependencies);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String bomPomWithParent(String artifact, String version, String parentArtifact, String managedDependencies) {
|
|
||||||
return """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>%s</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
</parent>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>%s</artifactId>
|
|
||||||
<version>%s</version>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>%s</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
</project>""".formatted(parentArtifact, artifact, version, managedDependencies);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String metadata(String artifact, String latest, String... versions) {
|
|
||||||
var versions_xml = new StringBuilder();
|
|
||||||
for (var version : versions) {
|
|
||||||
versions_xml.append("<version>").append(version).append("</version>");
|
|
||||||
}
|
|
||||||
return """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>%s</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<latest>%s</latest>
|
|
||||||
<release>%s</release>
|
|
||||||
<versions>%s</versions>
|
|
||||||
</versioning>
|
|
||||||
</metadata>""".formatted(artifact, latest, latest, versions_xml);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -379,39 +379,6 @@ public class TestDependencySet {
|
||||||
"""), dependencies.generateTransitiveDependencyTree(VersionResolution.dummy(), ArtifactRetriever.instance(), RepositoryTestHelper.getNextRepositories(), compile, runtime));
|
"""), dependencies.generateTransitiveDependencyTree(VersionResolution.dummy(), ArtifactRetriever.instance(), RepositoryTestHelper.getNextRepositories(), compile, runtime));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void testCopyAndIncludePreserveAllContents() {
|
|
||||||
var set = new DependencySet()
|
|
||||||
.include(new Dependency("com.uwyn.rife2", "rife2", new VersionNumber(1, 9, 1)))
|
|
||||||
.include(new Bom("io.vertx", "vertx-stack-depchain", new VersionNumber(4, 5, 12)))
|
|
||||||
.include(new LocalDependency("lib/local.jar"))
|
|
||||||
.include(new LocalModule("lib/module.jar"));
|
|
||||||
|
|
||||||
var copy = new DependencySet(set);
|
|
||||||
assertEquals(set, copy);
|
|
||||||
assertEquals(set.boms(), copy.boms());
|
|
||||||
assertEquals(set.localDependencies(), copy.localDependencies());
|
|
||||||
assertEquals(set.localModules(), copy.localModules());
|
|
||||||
|
|
||||||
var included = new DependencySet().include(set);
|
|
||||||
assertEquals(set, included);
|
|
||||||
assertEquals(set.boms(), included.boms());
|
|
||||||
assertEquals(set.localDependencies(), included.localDependencies());
|
|
||||||
assertEquals(set.localModules(), included.localModules());
|
|
||||||
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(Scope.compile).include(set);
|
|
||||||
var scopes_copy = new DependencyScopes();
|
|
||||||
scopes_copy.include(scopes);
|
|
||||||
assertEquals(set.boms(), scopes_copy.scope(Scope.compile).boms());
|
|
||||||
assertEquals(set.localDependencies(), scopes_copy.scope(Scope.compile).localDependencies());
|
|
||||||
|
|
||||||
var scopes_ctor_copy = new DependencyScopes(scopes);
|
|
||||||
assertEquals(set.boms(), scopes_ctor_copy.scope(Scope.compile).boms());
|
|
||||||
assertEquals(set.localDependencies(), scopes_ctor_copy.scope(Scope.compile).localDependencies());
|
|
||||||
assertEquals(set.localModules(), scopes_ctor_copy.scope(Scope.compile).localModules());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testTransferIntoDirectoryParallel() throws Exception {
|
void testTransferIntoDirectoryParallel() throws Exception {
|
||||||
var max_concurrent_transfers = new AtomicInteger();
|
var max_concurrent_transfers = new AtomicInteger();
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,9 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.condition.DisabledOnOs;
|
import org.junit.jupiter.api.condition.DisabledOnOs;
|
||||||
import org.junit.jupiter.api.condition.OS;
|
import org.junit.jupiter.api.condition.OS;
|
||||||
import rife.bld.Project;
|
import rife.bld.Project;
|
||||||
import rife.bld.WebProject;
|
|
||||||
import rife.bld.blueprints.AppProjectBlueprint;
|
import rife.bld.blueprints.AppProjectBlueprint;
|
||||||
import rife.bld.dependencies.*;
|
import rife.bld.dependencies.*;
|
||||||
import rife.bld.publish.PublishArtifact;
|
import rife.bld.publish.PublishArtifact;
|
||||||
import rife.bld.publish.PublishInfo;
|
|
||||||
import rife.tools.FileUtils;
|
import rife.tools.FileUtils;
|
||||||
import rife.tools.exceptions.FileUtilsErrorException;
|
import rife.tools.exceptions.FileUtilsErrorException;
|
||||||
|
|
||||||
|
|
@ -706,246 +704,4 @@ public class TestPublishOperation {
|
||||||
FileUtils.deleteDirectory(tmp1);
|
FileUtils.deleteDirectory(tmp1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void testPublishLocalWithBom()
|
|
||||||
throws Exception {
|
|
||||||
var poms = java.util.Map.of(
|
|
||||||
"bom1:1.0.0", """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>bom1</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency><groupId>com.example</groupId><artifactId>a</artifactId><version>1.4.0</version></dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
</project>""");
|
|
||||||
var metadata = java.util.Map.of(
|
|
||||||
"b", """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>b</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<latest>2.2.0</latest>
|
|
||||||
<release>2.2.0</release>
|
|
||||||
<versions><version>2.2.0</version></versions>
|
|
||||||
</versioning>
|
|
||||||
</metadata>""");
|
|
||||||
var server = com.sun.net.httpserver.HttpServer.create(new java.net.InetSocketAddress("localhost", 0), 0);
|
|
||||||
server.createContext("/", exchange -> {
|
|
||||||
var segments = exchange.getRequestURI().getPath().split("/");
|
|
||||||
var filename = segments[segments.length - 1];
|
|
||||||
String content = null;
|
|
||||||
if (filename.endsWith(".pom") && segments.length >= 3) {
|
|
||||||
content = poms.get(segments[segments.length - 3] + ":" + segments[segments.length - 2]);
|
|
||||||
} else if (filename.equals("maven-metadata.xml") && segments.length >= 2) {
|
|
||||||
content = metadata.get(segments[segments.length - 2]);
|
|
||||||
}
|
|
||||||
if (content == null) {
|
|
||||||
exchange.sendResponseHeaders(404, -1);
|
|
||||||
} else {
|
|
||||||
var body = content.getBytes();
|
|
||||||
exchange.sendResponseHeaders(200, body.length);
|
|
||||||
exchange.getResponseBody().write(body);
|
|
||||||
}
|
|
||||||
exchange.close();
|
|
||||||
});
|
|
||||||
server.start();
|
|
||||||
|
|
||||||
var tmp_local = Files.createTempDirectory("bomlocal").toFile();
|
|
||||||
var artifact_file = File.createTempFile("myapp", ".jar");
|
|
||||||
try {
|
|
||||||
var operation = new PublishOperation()
|
|
||||||
.artifactRetriever(ArtifactRetriever.cachingInstance())
|
|
||||||
.repositories(new Repository(tmp_local.getAbsolutePath()))
|
|
||||||
.dependencyRepositories(List.of(new Repository("http://localhost:" + server.getAddress().getPort() + "/")))
|
|
||||||
.info(new PublishInfo()
|
|
||||||
.groupId("test.pkg")
|
|
||||||
.artifactId("myapp")
|
|
||||||
.version(new VersionNumber(3, 3, 3)))
|
|
||||||
.artifacts(List.of(new PublishArtifact(artifact_file, "", "jar")));
|
|
||||||
operation.dependencies().scope(Scope.compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"))
|
|
||||||
.include(new Dependency("com.example", "b"));
|
|
||||||
operation.execute();
|
|
||||||
|
|
||||||
var pom = FileUtils.readString(Path.of(tmp_local.getAbsolutePath(), "test", "pkg", "myapp", "3.3.3", "myapp-3.3.3.pom").toFile());
|
|
||||||
|
|
||||||
// the BOM is imported through dependency management
|
|
||||||
assertTrue(pom.contains("<dependencyManagement>"), pom);
|
|
||||||
assertTrue(pom.contains("<artifactId>bom1</artifactId>"), pom);
|
|
||||||
assertTrue(pom.contains("<version>1.0.0</version>"), pom);
|
|
||||||
assertTrue(pom.contains("<type>pom</type>"), pom);
|
|
||||||
assertTrue(pom.contains("<scope>import</scope>"), pom);
|
|
||||||
|
|
||||||
// the covered dependency stays version-less,
|
|
||||||
// the BOM import provides its version downstream
|
|
||||||
assertTrue(pom.contains("<artifactId>a</artifactId>"), pom);
|
|
||||||
assertFalse(java.util.regex.Pattern.compile("<artifactId>a</artifactId>\\s*<version>").matcher(pom).find(), pom);
|
|
||||||
|
|
||||||
// the uncovered dependency is frozen to its resolved version
|
|
||||||
assertTrue(java.util.regex.Pattern.compile("<artifactId>b</artifactId>\\s*<version>2\\.2\\.0</version>").matcher(pom).find(), pom);
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
artifact_file.delete();
|
|
||||||
FileUtils.deleteDirectory(tmp_local);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testResolveVersionlessDependenciesUntouchedScopes() {
|
|
||||||
// no network access is needed when nothing has to be resolved :
|
|
||||||
// explicitly versioned dependencies are untouched and the test
|
|
||||||
// scope isn't part of the publication
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(Scope.compile)
|
|
||||||
.include(new Dependency("com.example", "c", new VersionNumber(5, 0, 0)));
|
|
||||||
scopes.scope(Scope.test)
|
|
||||||
.include(new Dependency("com.example", "t"));
|
|
||||||
|
|
||||||
var operation = new PublishOperation()
|
|
||||||
.dependencies(scopes);
|
|
||||||
operation.executeResolveVersionlessDependencies();
|
|
||||||
|
|
||||||
assertEquals(new VersionNumber(5, 0, 0), operation.dependencies().scope(Scope.compile).get(new Dependency("com.example", "c")).version());
|
|
||||||
assertEquals(VersionNumber.UNKNOWN, operation.dependencies().scope(Scope.test).get(new Dependency("com.example", "t")).version());
|
|
||||||
}
|
|
||||||
|
|
||||||
static class BomPublishProject extends WebProject {
|
|
||||||
BomPublishProject(File tmp) {
|
|
||||||
workDirectory = tmp;
|
|
||||||
pkg = "test.pkg";
|
|
||||||
name = "myapp";
|
|
||||||
version = new VersionNumber(0, 0, 1);
|
|
||||||
repositories = List.of(new Repository("https://example.com/resolve"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testFromProjectDependencyRepositories()
|
|
||||||
throws Exception {
|
|
||||||
var tmp = Files.createTempDirectory("test").toFile();
|
|
||||||
try {
|
|
||||||
var project = new BomPublishProject(tmp);
|
|
||||||
var operation = new PublishOperation()
|
|
||||||
.fromProject(project);
|
|
||||||
assertEquals(project.repositories(), operation.dependencyRepositories());
|
|
||||||
} finally {
|
|
||||||
FileUtils.deleteDirectory(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testResolveVersionlessDependencies()
|
|
||||||
throws Exception {
|
|
||||||
var poms = java.util.Map.of(
|
|
||||||
"bom1:1.0.0", """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>bom1</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency><groupId>com.example</groupId><artifactId>a</artifactId><version>1.4.0</version></dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
</project>""",
|
|
||||||
"bom2:3.0.0", """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>bom2</artifactId>
|
|
||||||
<version>3.0.0</version>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency><groupId>com.example</groupId><artifactId>d</artifactId><version>4.0.0</version></dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
</project>""");
|
|
||||||
var metadata = java.util.Map.of(
|
|
||||||
"b", """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>b</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<latest>2.2.0</latest>
|
|
||||||
<release>2.2.0</release>
|
|
||||||
<versions><version>2.2.0</version></versions>
|
|
||||||
</versioning>
|
|
||||||
</metadata>""",
|
|
||||||
"bom2", """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>bom2</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<latest>3.0.0</latest>
|
|
||||||
<release>3.0.0</release>
|
|
||||||
<versions><version>3.0.0</version></versions>
|
|
||||||
</versioning>
|
|
||||||
</metadata>""");
|
|
||||||
var server = com.sun.net.httpserver.HttpServer.create(new java.net.InetSocketAddress("localhost", 0), 0);
|
|
||||||
server.createContext("/", exchange -> {
|
|
||||||
var segments = exchange.getRequestURI().getPath().split("/");
|
|
||||||
var filename = segments[segments.length - 1];
|
|
||||||
String content = null;
|
|
||||||
if (filename.endsWith(".pom") && segments.length >= 3) {
|
|
||||||
content = poms.get(segments[segments.length - 3] + ":" + segments[segments.length - 2]);
|
|
||||||
} else if (filename.equals("maven-metadata.xml") && segments.length >= 2) {
|
|
||||||
content = metadata.get(segments[segments.length - 2]);
|
|
||||||
}
|
|
||||||
if (content == null) {
|
|
||||||
exchange.sendResponseHeaders(404, -1);
|
|
||||||
} else {
|
|
||||||
var body = content.getBytes();
|
|
||||||
exchange.sendResponseHeaders(200, body.length);
|
|
||||||
exchange.getResponseBody().write(body);
|
|
||||||
}
|
|
||||||
exchange.close();
|
|
||||||
});
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var scopes = new DependencyScopes();
|
|
||||||
scopes.scope(Scope.compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"))
|
|
||||||
.include(new Dependency("com.example", "b"))
|
|
||||||
.include(new Dependency("com.example", "c", new VersionNumber(5, 0, 0)));
|
|
||||||
scopes.scope(Scope.runtime)
|
|
||||||
.include(new Bom("com.example", "bom2"));
|
|
||||||
|
|
||||||
var operation = new PublishOperation()
|
|
||||||
.artifactRetriever(ArtifactRetriever.cachingInstance())
|
|
||||||
.dependencyRepositories(List.of(new Repository("http://localhost:" + server.getAddress().getPort() + "/")))
|
|
||||||
.dependencies(scopes);
|
|
||||||
operation.executeResolveVersionlessDependencies();
|
|
||||||
|
|
||||||
var compile_scope = operation.dependencies().scope(Scope.compile);
|
|
||||||
// covered by the BOM : stays version-less for the POM,
|
|
||||||
// the dependency management import provides the version
|
|
||||||
assertEquals(VersionNumber.UNKNOWN, compile_scope.get(new Dependency("com.example", "a")).version());
|
|
||||||
// not covered : resolved to its latest version
|
|
||||||
assertEquals(new VersionNumber(2, 2, 0), compile_scope.get(new Dependency("com.example", "b")).version());
|
|
||||||
// explicitly versioned : untouched
|
|
||||||
assertEquals(new VersionNumber(5, 0, 0), compile_scope.get(new Dependency("com.example", "c")).version());
|
|
||||||
// a version-less BOM is resolved to its latest version
|
|
||||||
var runtime_boms = operation.dependencies().scope(Scope.runtime).boms();
|
|
||||||
assertEquals(new Bom("com.example", "bom2", new VersionNumber(3, 0, 0)), runtime_boms.iterator().next());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,14 @@
|
||||||
*/
|
*/
|
||||||
package rife.bld.operations;
|
package rife.bld.operations;
|
||||||
|
|
||||||
import com.sun.net.httpserver.HttpServer;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import rife.bld.WebProject;
|
import rife.bld.WebProject;
|
||||||
import rife.bld.dependencies.*;
|
import rife.bld.dependencies.*;
|
||||||
import rife.tools.FileUtils;
|
import rife.tools.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
|
@ -172,123 +168,4 @@ public class TestUpdatesOperation {
|
||||||
FileUtils.deleteDirectory(tmp);
|
FileUtils.deleteDirectory(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBomUpdateReported()
|
|
||||||
throws Exception {
|
|
||||||
var server = createArtifactServer(
|
|
||||||
Map.of("bom1:1.0.0", bomPom("bom1", "1.0.0", "<dependency><groupId>com.example</groupId><artifactId>a</artifactId><version>1.4.0</version></dependency>")),
|
|
||||||
Map.of("bom1", metadata("bom1", "2.0.0", "1.0.0", "2.0.0"),
|
|
||||||
"a", metadata("a", "9.9.9", "1.4.0", "9.9.9")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var operation = new UpdatesOperation()
|
|
||||||
.artifactRetriever(ArtifactRetriever.cachingInstance())
|
|
||||||
.repositories(List.of(new Repository("http://localhost:" + server.getAddress().getPort() + "/")));
|
|
||||||
operation.dependencies().scope(Scope.compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a"));
|
|
||||||
|
|
||||||
operation.execute();
|
|
||||||
|
|
||||||
// the newer BOM version is reported
|
|
||||||
var boms = operation.updates().scope(Scope.compile).boms();
|
|
||||||
assertEquals(1, boms.size());
|
|
||||||
assertEquals(new Bom("com.example", "bom1", new VersionNumber(2, 0, 0)), boms.iterator().next());
|
|
||||||
|
|
||||||
// the version-less dependency covered by the BOM is not reported,
|
|
||||||
// even though newer versions exist in the metadata
|
|
||||||
assertTrue(operation.updates().scope(Scope.compile).isEmpty());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testExplicitVersionCheckedDespiteBom()
|
|
||||||
throws Exception {
|
|
||||||
var server = createArtifactServer(
|
|
||||||
Map.of("bom1:1.0.0", bomPom("bom1", "1.0.0", "<dependency><groupId>com.example</groupId><artifactId>a</artifactId><version>1.4.0</version></dependency>")),
|
|
||||||
Map.of("bom1", metadata("bom1", "1.0.0", "1.0.0"),
|
|
||||||
"a", metadata("a", "2.0.0", "1.0.0", "2.0.0")));
|
|
||||||
server.start();
|
|
||||||
try {
|
|
||||||
var operation = new UpdatesOperation()
|
|
||||||
.artifactRetriever(ArtifactRetriever.cachingInstance())
|
|
||||||
.repositories(List.of(new Repository("http://localhost:" + server.getAddress().getPort() + "/")));
|
|
||||||
operation.dependencies().scope(Scope.compile)
|
|
||||||
.include(new Bom("com.example", "bom1", new VersionNumber(1, 0, 0)))
|
|
||||||
.include(new Dependency("com.example", "a", new VersionNumber(1, 0, 0)));
|
|
||||||
|
|
||||||
operation.execute();
|
|
||||||
|
|
||||||
// the BOM is up to date and not reported
|
|
||||||
assertTrue(operation.updates().scope(Scope.compile).boms().isEmpty());
|
|
||||||
|
|
||||||
// the explicitly versioned dependency is still checked for
|
|
||||||
// updates, even though the BOM covers it
|
|
||||||
var dependencies = operation.updates().scope(Scope.compile);
|
|
||||||
assertEquals(1, dependencies.size());
|
|
||||||
assertEquals(new VersionNumber(2, 0, 0), dependencies.iterator().next().version());
|
|
||||||
} finally {
|
|
||||||
server.stop(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpServer createArtifactServer(Map<String, String> poms, Map<String, String> metadata)
|
|
||||||
throws IOException {
|
|
||||||
var server = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
|
|
||||||
server.createContext("/", exchange -> {
|
|
||||||
var segments = exchange.getRequestURI().getPath().split("/");
|
|
||||||
var filename = segments[segments.length - 1];
|
|
||||||
String content = null;
|
|
||||||
if (filename.endsWith(".pom") && segments.length >= 3) {
|
|
||||||
content = poms.get(segments[segments.length - 3] + ":" + segments[segments.length - 2]);
|
|
||||||
} else if (filename.equals("maven-metadata.xml") && segments.length >= 2) {
|
|
||||||
content = metadata.get(segments[segments.length - 2]);
|
|
||||||
}
|
|
||||||
if (content == null) {
|
|
||||||
exchange.sendResponseHeaders(404, -1);
|
|
||||||
} else {
|
|
||||||
var body = content.getBytes();
|
|
||||||
exchange.sendResponseHeaders(200, body.length);
|
|
||||||
exchange.getResponseBody().write(body);
|
|
||||||
}
|
|
||||||
exchange.close();
|
|
||||||
});
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String bomPom(String artifact, String version, String managedDependencies) {
|
|
||||||
return """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>%s</artifactId>
|
|
||||||
<version>%s</version>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>%s</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
</project>""".formatted(artifact, version, managedDependencies);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String metadata(String artifact, String latest, String... versions) {
|
|
||||||
var versions_xml = new StringBuilder();
|
|
||||||
for (var version : versions) {
|
|
||||||
versions_xml.append("<version>").append(version).append("</version>");
|
|
||||||
}
|
|
||||||
return """
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>%s</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<latest>%s</latest>
|
|
||||||
<release>%s</release>
|
|
||||||
<versions>%s</versions>
|
|
||||||
</versioning>
|
|
||||||
</metadata>""".formatted(artifact, latest, latest, versions_xml);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -652,93 +652,4 @@ public class TestPomBuilder {
|
||||||
</project>
|
</project>
|
||||||
""", builder.build());
|
""", builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void testDependencyManagementScopeBoundaries() {
|
|
||||||
var builder = new PomBuilder();
|
|
||||||
builder.dependencies().scope(Scope.provided)
|
|
||||||
.include(new Bom("org.eclipse.jetty", "jetty-bom", new VersionNumber(12, 0, 16)));
|
|
||||||
builder.dependencies().scope(Scope.test)
|
|
||||||
// the test scope isn't published, its BOMs are not emitted
|
|
||||||
.include(new Bom("org.junit", "junit-bom", new VersionNumber(6, 1, 1)));
|
|
||||||
assertEquals("""
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId></groupId>
|
|
||||||
<artifactId></artifactId>
|
|
||||||
<version></version>
|
|
||||||
<name></name>
|
|
||||||
<description></description>
|
|
||||||
<url></url>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-bom</artifactId>
|
|
||||||
<version>12.0.16</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
||||||
""", builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testDependencyManagement() {
|
|
||||||
var builder = new PomBuilder();
|
|
||||||
builder.dependencies().scope(Scope.compile)
|
|
||||||
.include(new Bom("io.vertx", "vertx-stack-depchain", new VersionNumber(4, 5, 12)))
|
|
||||||
.include(new Dependency("io.vertx", "vertx-core"));
|
|
||||||
builder.dependencies().scope(Scope.runtime)
|
|
||||||
// duplicate BOMs are only emitted once
|
|
||||||
.include(new Bom("io.vertx", "vertx-stack-depchain", new VersionNumber(4, 5, 12)))
|
|
||||||
.include(new Bom("org.junit", "junit-bom", new VersionNumber(6, 1, 1)));
|
|
||||||
builder.dependencies().scope(Scope.provided)
|
|
||||||
// BOMs without a version are not emitted
|
|
||||||
.include(new Bom("com.example", "versionless-bom"));
|
|
||||||
assertEquals("""
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId></groupId>
|
|
||||||
<artifactId></artifactId>
|
|
||||||
<version></version>
|
|
||||||
<name></name>
|
|
||||||
<description></description>
|
|
||||||
<url></url>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.vertx</groupId>
|
|
||||||
<artifactId>vertx-stack-depchain</artifactId>
|
|
||||||
<version>4.5.12</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.junit</groupId>
|
|
||||||
<artifactId>junit-bom</artifactId>
|
|
||||||
<version>6.1.1</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.vertx</groupId>
|
|
||||||
<artifactId>vertx-core</artifactId>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
||||||
""", builder.build());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue