Skip to content

Commit

Permalink
Use ChainedLocalRepositoryManager
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagobento committed Sep 19, 2024
1 parent bddf9a3 commit 5ae6c3b
Show file tree
Hide file tree
Showing 15 changed files with 355 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,15 @@
import org.eclipse.aether.repository.ArtifactRepository;
import org.eclipse.aether.repository.Authentication;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.LocalRepositoryManager;
import org.eclipse.aether.repository.Proxy;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.resolution.ArtifactDescriptorException;
import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
import org.eclipse.aether.transfer.TransferListener;
import org.eclipse.aether.util.repository.AuthenticationBuilder;
import org.eclipse.aether.util.repository.ChainedLocalRepositoryManager;
import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
import org.eclipse.aether.util.repository.DefaultMirrorSelector;
import org.eclipse.aether.util.repository.DefaultProxySelector;
Expand Down Expand Up @@ -128,6 +130,8 @@ public class BootstrapMavenContext {
private List<RemoteRepository> remotePluginRepos;
private RemoteRepositoryManager remoteRepoManager;
private String localRepo;
private String[] localRepoTail;
private Boolean localRepoTailIgnoreAvailability;
private Path currentPom;
private Boolean currentProjectExists;
private String alternatePomName;
Expand Down Expand Up @@ -157,6 +161,8 @@ public BootstrapMavenContext(BootstrapMavenContextConfig<?> config)
this.alternatePomName = config.alternatePomName;
this.artifactTransferLogging = config.artifactTransferLogging;
this.localRepo = config.localRepo;
this.localRepoTail = config.localRepoTail;
this.localRepoTailIgnoreAvailability = config.localRepoTailIgnoreAvailability;
this.offline = config.offline;
this.warnOnFailingWorkspaceModules = config.warnOnFailedWorkspaceModules;
this.repoSystem = config.repoSystem;
Expand Down Expand Up @@ -363,6 +369,16 @@ public String getLocalRepo() throws BootstrapMavenException {
return localRepo == null ? localRepo = resolveLocalRepo(getEffectiveSettings()) : localRepo;
}

private String[] getLocalRepoTail() {
return localRepoTail == null ? localRepoTail = resolveLocalRepoTail() : localRepoTail;
}

private boolean getLocalRepoTailIgnoreAvailability() {
return localRepoTailIgnoreAvailability == null
? localRepoTailIgnoreAvailability = resolveLocalRepoTailIgnoreAvailability()
: localRepoTailIgnoreAvailability;
}

private LocalProject resolveCurrentProject(Function<Path, Model> modelProvider) throws BootstrapMavenException {
try {
return LocalProject.loadWorkspace(this, modelProvider);
Expand All @@ -384,6 +400,29 @@ private String resolveLocalRepo(Settings settings) {
return localRepo == null ? new File(getUserMavenConfigurationHome(), "repository").getAbsolutePath() : localRepo;
}

private String[] resolveLocalRepoTail() {
final String localRepoTail = getProperty("maven.repo.local.tail");
if (localRepoTail == null) {
return new String[] {};
}
if (localRepoTail.trim().isEmpty()) {
return new String[] {};
}
return localRepoTail.split(",");
}

private boolean resolveLocalRepoTailIgnoreAvailability() {
final String ignoreAvailability = getProperty("maven.repo.local.tail.ignoreAvailability");

// The only "falsy" value is `false` itself
if ("false".equalsIgnoreCase(ignoreAvailability)) {
return false;
}

//All other strings are interpreted as `true`.
return true;
}

private File resolveSettingsFile(String settingsArg, Supplier<File> supplier) {
File userSettings;
if (settingsArg != null) {
Expand Down Expand Up @@ -460,9 +499,23 @@ private DefaultRepositorySystemSession newRepositorySystemSession() throws Boots
}
session.setMirrorSelector(ms);
}

final String localRepoPath = getLocalRepo();
session.setLocalRepositoryManager(
getRepositorySystem().newLocalRepositoryManager(session, new LocalRepository(localRepoPath)));
final String[] localRepoTailPaths = getLocalRepoTail();

final LocalRepositoryManager head = getRepositorySystem().newLocalRepositoryManager(session,
new LocalRepository(localRepoPath));

if (localRepoTailPaths.length == 0) {
session.setLocalRepositoryManager(head);
} else {
final List<LocalRepositoryManager> tail = new ArrayList<>(localRepoTailPaths.length);
for (final String tailPath : localRepoTailPaths) {
tail.add(getRepositorySystem().newLocalRepositoryManager(session, new LocalRepository(tailPath)));
}
session.setLocalRepositoryManager(
new ChainedLocalRepositoryManager(head, tail, getLocalRepoTailIgnoreAvailability()));
}

session.setOffline(isOffline());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
public class BootstrapMavenContextConfig<T extends BootstrapMavenContextConfig<?>> {

protected String localRepo;
protected String[] localRepoTail;
protected Boolean localRepoTailIgnoreAvailability;
protected Boolean offline;
protected LocalProject currentProject;
protected boolean workspaceDiscovery = true;
Expand Down Expand Up @@ -92,6 +94,30 @@ public T setLocalRepository(String localRepo) {
return (T) this;
}

/**
* Local repository tail locations (comma-separated)
*
* @param localRepoTail local repository tail locations (comma-separated)
* @return this instance
*/
@SuppressWarnings("unchecked")
public T setLocalRepositoryTail(String[] localRepoTail) {
this.localRepoTail = localRepoTail;
return (T) this;
}

/**
* Wheter to ignore availability on local repository tail (default: true)
*
* @param localRepoTailIgnoreAvailability whether to ignore availability on local repository tail
* @return this instance
*/
@SuppressWarnings("unchecked")
public T setLocalRepositoryTailIgnoreAvailability(boolean localRepoTailIgnoreAvailability) {
this.localRepoTailIgnoreAvailability = localRepoTailIgnoreAvailability;
return (T) this;
}

/**
* Whether to operate offline
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ protected RemoteRepository newRepo(String id, String url) {
}

protected BootstrapMavenContext bootstrapMavenContextForProject(String projectOnCp) throws Exception {

final BootstrapMavenContextConfig<?> config = BootstrapMavenContext.config();
initBootstrapMavenContextConfig(config);
return bootstrapMavenContextForProject(projectOnCp, config);
}

protected BootstrapMavenContext bootstrapMavenContextForProject(String projectOnCp, BootstrapMavenContextConfig<?> config)
throws Exception {
final Path projectLocation = getProjectLocation(projectOnCp);
config.setCurrentProject(projectLocation.toString());

Expand All @@ -56,9 +58,6 @@ protected BootstrapMavenContext bootstrapMavenContextForProject(String projectOn
return new BootstrapMavenContext(config);
}

protected void initBootstrapMavenContextConfig(BootstrapMavenContextConfig<?> config) throws Exception {
}

protected BootstrapMavenContext bootstrapMavenContextWithSettings(String configDirOnCp) throws Exception {

final BootstrapMavenContextConfig<?> config = initBootstrapMavenContextConfig();
Expand All @@ -75,7 +74,7 @@ protected BootstrapMavenContextConfig<?> initBootstrapMavenContextConfig() throw
return BootstrapMavenContext.config().setWorkspaceDiscovery(false);
}

protected Path getProjectLocation(String projectOnCp) throws URISyntaxException {
protected static Path getProjectLocation(String projectOnCp) throws URISyntaxException {
final URL basedirUrl = Thread.currentThread().getContextClassLoader().getResource(projectOnCp);
assertNotNull(basedirUrl);
return Paths.get(basedirUrl.toURI());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package io.quarkus.bootstrap.resolver.maven.test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;

import java.net.URISyntaxException;
import java.nio.file.Paths;

import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.junit.jupiter.api.Test;

import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContext;
import io.quarkus.bootstrap.resolver.maven.BootstrapMavenException;
import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;

public class ChainedLocalRepositoryManagerTest extends BootstrapMavenContextTestBase {

private static final String M2_LOCAL_1;
private static final String M2_LOCAL_2;
private static final String M2_FROM_REMOTE;

static {
final String projectLocation;
try {
projectLocation = getProjectLocation("workspace-with-local-repo-tail").toString();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}

M2_LOCAL_1 = Paths.get(projectLocation, ".m2-local-1", "repository").toAbsolutePath().toString();
M2_LOCAL_2 = Paths.get(projectLocation, ".m2-local-2", "repository").toAbsolutePath().toString();
M2_FROM_REMOTE = Paths.get(projectLocation, ".m2-from-remote", "repository").toAbsolutePath().toString();
}

// Tail configuration tests

@Test
public void testNoTail() throws Exception {
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail");
assertThrowsExactly(BootstrapMavenException.class, () -> resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testTailConfiguredButEmptyString() throws Exception {
setSystemProp("maven.repo.local.tail", "");
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail");
assertThrowsExactly(BootstrapMavenException.class, () -> resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testTailConfiguredButBlank() throws Exception {
setSystemProp("maven.repo.local.tail", " ");
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail");
assertThrowsExactly(BootstrapMavenException.class, () -> resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testTailConfiguredButNonExistent() throws Exception {
setSystemProp("maven.repo.local.tail", "/tmp/this-dir-does-not-exist");
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail");
assertThrowsExactly(BootstrapMavenException.class, () -> resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailViaSystemProp() throws Exception {
setSystemProp("maven.repo.local.tail", M2_LOCAL_1);
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail");
assertNotNull(resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailViaConfig() throws Exception {
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTail(new String[] { M2_LOCAL_1 }));

assertNotNull(resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailResolutionOrder() throws Exception {
final BootstrapMavenContext mvnLocal1first = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTail(new String[] { M2_LOCAL_1, M2_LOCAL_2 }));

final BootstrapMavenContext mvnLocal2first = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTail(new String[] { M2_LOCAL_2, M2_LOCAL_1 }));

assertEquals(resolveOrgAcmeFooJar001(mvnLocal1first).getFile().getAbsolutePath(),
Paths.get(M2_LOCAL_1, "org", "acme", "foo", "0.0.1", "foo-0.0.1.jar").toAbsolutePath().toString());
assertEquals(resolveOrgAcmeFooJar001(mvnLocal2first).getFile().getAbsolutePath(),
Paths.get(M2_LOCAL_2, "org", "acme", "foo", "0.0.1", "foo-0.0.1.jar").toAbsolutePath().toString());
}

@Test
public void testValidTailMultiplicity() throws Exception {
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTail(new String[] { M2_LOCAL_1, M2_LOCAL_2 }));

final Artifact foo = resolveOrgAcmeFooJar001(mvn);
assertNotNull(foo);
assertEquals(foo.getFile().getAbsolutePath(),
Paths.get(M2_LOCAL_1, "org", "acme", "foo", "0.0.1", "foo-0.0.1.jar").toAbsolutePath().toString());

final Artifact bar = resolveOrgAcmeBarJar002(mvn);
assertNotNull(bar);
assertEquals(bar.getFile().getAbsolutePath(),
Paths.get(M2_LOCAL_2, "org", "acme", "bar", "0.0.2", "bar-0.0.2.jar").toAbsolutePath().toString());
}

// ignoreAvailability tests

@Test
public void testValidTailLocalCheckingForAvailabilityViaConfig() throws Exception {
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTailIgnoreAvailability(false)
.setLocalRepositoryTail(new String[] { M2_LOCAL_1 }));

assertNotNull(resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailFromRemoteCheckingForAvailabilityViaConfig() throws Exception {
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTailIgnoreAvailability(false)
.setLocalRepositoryTail(new String[] { M2_FROM_REMOTE }));

assertThrowsExactly(BootstrapMavenException.class, () -> resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailFromRemoteCheckingForAvailabilityViaSystemProp() throws Exception {
setSystemProp("maven.repo.local.tail.ignoreAvailability", "false");
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTail(new String[] { M2_FROM_REMOTE }));

assertThrowsExactly(BootstrapMavenException.class, () -> resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailFromRemoteIgnoringAvailabilityViaSystemPropEmpty() throws Exception {
setSystemProp("maven.repo.local.tail.ignoreAvailability", ""); // will become `true`
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTail(new String[] { M2_FROM_REMOTE }));

assertNotNull(resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailFromRemoteIgnoringAvailabilityViaSystemPropBlank() throws Exception {
setSystemProp("maven.repo.local.tail.ignoreAvailability", " "); // will become `true`
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTail(new String[] { M2_FROM_REMOTE }));

assertNotNull(resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailFromRemoteIgnoringAvailabilityViaSystemPropTruthy() throws Exception {
setSystemProp("maven.repo.local.tail.ignoreAvailability", "fals"); // will become `true`
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTail(new String[] { M2_FROM_REMOTE }));

assertNotNull(resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailLocalIgnoringAvailabilityViaConfig() throws Exception {
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTailIgnoreAvailability(true)
.setLocalRepositoryTail(new String[] { M2_LOCAL_1 }));

assertNotNull(resolveOrgAcmeFooJar001(mvn));
}

@Test
public void testValidTailFromRemoteIgnoringAvailabilityViaConfig() throws Exception {
final BootstrapMavenContext mvn = bootstrapMavenContextForProject("workspace-with-local-repo-tail",
BootstrapMavenContext.config()
.setLocalRepositoryTailIgnoreAvailability(true)
.setLocalRepositoryTail(new String[] { M2_FROM_REMOTE }));

assertNotNull(resolveOrgAcmeFooJar001(mvn));
}

private Artifact resolveOrgAcmeFooJar001(BootstrapMavenContext ctx) throws BootstrapMavenException {
final MavenArtifactResolver resolver = new MavenArtifactResolver(ctx);
return resolver.resolve(new DefaultArtifact("org.acme", "foo", "", "jar", "0.0.1")).getArtifact();
}

private Artifact resolveOrgAcmeBarJar002(BootstrapMavenContext ctx) throws BootstrapMavenException {
final MavenArtifactResolver resolver = new MavenArtifactResolver(ctx);
return resolver.resolve(new DefaultArtifact("org.acme", "bar", "", "jar", "0.0.2")).getArtifact();
}
}
Loading

0 comments on commit 5ae6c3b

Please sign in to comment.