Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-17775] Find (model) parent POMs properly during finger…
…print recording at end of build.

Originally-Committed-As: 0c4fe2ddbac2963c0b633fe27bb1a6016134da50
  • Loading branch information
jglick committed Apr 30, 2013
1 parent b0bbf6c commit 36c841f
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 57 deletions.
13 changes: 13 additions & 0 deletions src/main/java/hudson/maven/MavenBuildInformation.java
Expand Up @@ -21,9 +21,13 @@
*/

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.apache.maven.model.Model;
import org.apache.maven.project.MavenProject;

/**
* @author Olivier Lamy
Expand All @@ -33,6 +37,15 @@ public class MavenBuildInformation implements Serializable {

private static final long serialVersionUID = -3719709179508200057L;
private String mavenVersion;
/**
* Map of model IDs to IDs of the model parents (if defined).
* @see MavenProject#getId
* @see Model#getId
* @see MavenProject#getParent
* @see Model#getParent
* @since 1.515
*/
public final Map<String,String> modelParents = new HashMap<String,String>();

public MavenBuildInformation(String mavenVersion) {
this.mavenVersion = mavenVersion;
Expand Down
41 changes: 33 additions & 8 deletions src/main/java/hudson/maven/MavenModuleSetBuild.java
Expand Up @@ -65,6 +65,7 @@
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.PrintStream;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -582,7 +583,7 @@ protected Result doRun(final BuildListener listener) throws Exception {
LOGGER.fine(getFullDisplayName()+" is building with mavenVersion " + mavenVersion + " from file " + mavenInformation.getVersionResourcePath());

if(!project.isAggregatorStyleBuild()) {
parsePoms(listener, logger, envVars, mvn, mavenVersion);
parsePoms(listener, logger, envVars, mvn, mavenVersion, mavenBuildInformation);
// start module builds
logger.println("Triggering "+project.getRootModule().getModuleName());
project.getRootModule().scheduleBuild(new UpstreamCause((Run<?,?>)MavenModuleSetBuild.this));
Expand Down Expand Up @@ -619,7 +620,7 @@ protected Result doRun(final BuildListener listener) throws Exception {
return r;
}

parsePoms(listener, logger, envVars, mvn, mavenVersion); // #5428 : do pre-build *before* parsing pom
parsePoms(listener, logger, envVars, mvn, mavenVersion, mavenBuildInformation); // #5428 : do pre-build *before* parsing pom
SplittableBuildListener slistener = new SplittableBuildListener(listener);
proxies = new HashMap<ModuleName, ProxyImpl2>();
List<ModuleName> changedModules = new ArrayList<ModuleName>();
Expand Down Expand Up @@ -856,12 +857,14 @@ private Collection<ModuleName> getUnbuildModulesSinceLastSuccessfulBuild() {
return unbuiltModules;
}

private void parsePoms(BuildListener listener, PrintStream logger, EnvVars envVars, MavenInstallation mvn, String mavenVersion) throws IOException, InterruptedException {
private void parsePoms(BuildListener listener, PrintStream logger, EnvVars envVars, MavenInstallation mvn, String mavenVersion, MavenBuildInformation mavenBuildInformation) throws IOException, InterruptedException {
logger.println("Parsing POMs");

List<PomInfo> poms;
try {
poms = getModuleRoot().act(new PomParser(listener, mvn, mavenVersion, envVars, MavenModuleSetBuild.this));
PomParser.Result result = getModuleRoot().act(new PomParser(listener, mvn, mavenVersion, envVars, MavenModuleSetBuild.this));
poms = result.infos;
mavenBuildInformation.modelParents.putAll(result.modelParents);
} catch (IOException e) {
if (project.isIncrementalBuild()) {
// If POM parsing failed we should do a full build next time.
Expand Down Expand Up @@ -997,7 +1000,7 @@ public Exception getCause() {
* Executed on the slave to parse POM and extract information into {@link PomInfo},
* which will be then brought back to the master.
*/
private static final class PomParser implements FileCallable<List<PomInfo>> {
private static final class PomParser implements FileCallable<PomParser.Result> {
private final BuildListener listener;
private final String rootPOM;
/**
Expand Down Expand Up @@ -1028,7 +1031,7 @@ private static final class PomParser implements FileCallable<List<PomInfo>> {

String rootPOMRelPrefix;

public PomParser(BuildListener listener, MavenInstallation mavenHome, String mavenVersion, EnvVars envVars, MavenModuleSetBuild build) {
PomParser(BuildListener listener, MavenInstallation mavenHome, String mavenVersion, EnvVars envVars, MavenModuleSetBuild build) {
// project cannot be shipped to the remote JVM, so all the relevant properties need to be captured now.
MavenModuleSet project = build.getProject();
this.listener = listener;
Expand Down Expand Up @@ -1082,7 +1085,16 @@ private boolean isUpdateSnapshots(String goals) {
return StringUtils.contains(goals, "-U") || StringUtils.contains(goals, "--update-snapshots");
}

public List<PomInfo> invoke(File ws, VirtualChannel channel) throws IOException {
public static final class Result implements Serializable {
public final List<PomInfo> infos;
public final Map<String,String> modelParents;
public Result(List<PomInfo> infos, Map<String,String> modelParents) {
this.infos = infos;
this.modelParents = modelParents;
}
}

public Result invoke(File ws, VirtualChannel channel) throws IOException {
File pom;

PrintStream logger = listener.getLogger();
Expand Down Expand Up @@ -1194,10 +1206,23 @@ public List<PomInfo> invoke(File ws, VirtualChannel channel) throws IOException
}
}
Map<String,MavenProject> canonicalPaths = new HashMap<String, MavenProject>( mps.size() );
Map<String,String> modelParents = new HashMap<String,String>();
for(MavenProject mp : mps) {
// Projects are indexed by POM path and not module path because
// Maven allows to have several POMs with different names in the same directory
canonicalPaths.put( mp.getFile().getCanonicalPath(), mp );
while (true) {
String k = mp.getId();
if (modelParents.containsKey(k)) {
break;
}
MavenProject mpp = mp.getParent();
if (mpp == null) {
break;
}
modelParents.put(k, mpp.getId());
mp = mpp;
}
}
//MavenUtil.resolveModules(embedder,mp,getRootPath(rootPOMRelPrefix),relPath,listener,nonRecursive);

Expand Down Expand Up @@ -1225,7 +1250,7 @@ public List<PomInfo> invoke(File ws, VirtualChannel channel) throws IOException
for (PomInfo pi : infos)
pi.cutCycle();

return new ArrayList<PomInfo>(infos);
return new Result(new ArrayList<PomInfo>(infos), modelParents);
} catch (MavenEmbedderException e) {
throw new MavenExecutionException(e);
} catch (ProjectBuildingException e) {
Expand Down
66 changes: 17 additions & 49 deletions src/main/java/hudson/maven/reporters/MavenFingerprinter.java
Expand Up @@ -138,60 +138,28 @@ public Void call(MavenBuild build) throws IOException, InterruptedException {
}

private void recordParents(MavenBuildProxy build, MavenProject pom, BuildListener listener) throws IOException, InterruptedException {
MavenProject parent = getParent(pom, listener);
Map<String,String> modelParents = build.getMavenBuildInformation().modelParents;
ArtifactRepository localRepository = getLocalRepository(build.getMavenBuildInformation(), pom);
if (localRepository == null) {
listener.error("Could not find local repository for " + build.getMavenBuildInformation().getMavenVersion());
return;
}
String parent = modelParents.get(pom.getId());
while (parent != null) {
File parentFile = parent.getFile();

if (parentFile == null) {
// Parent artifact contains no actual file, so we resolve against
// the local repository
ArtifactRepository localRepository = getLocalRepository(build.getMavenBuildInformation(), parent, pom);
if (localRepository != null) {
Artifact parentArtifact = getArtifact(parent);
// Don't use ArtifactRepository.find(), for compatibility with Maven 2.x
if (parentArtifact != null) {
parentFile = new File(localRepository.getBasedir(),
localRepository.pathOf(parentArtifact));
}
}
}

if (parentFile != null) {
// we need to include the artifact Id for poms as well, otherwise a
// project with the same groupId would override its parent's
// fingerprint
record(parent.getGroupId() + ":" + parent.getArtifactId(),
parentFile, used);
}
parent = getParent(parent, listener);
String[] parts = parent.split(":");
assert parts.length == 4 : parent;
// Maven 2.x lacks DefaultArtifact constructor with String version and ArtifactRepository.find:
Artifact parentArtifact = new DefaultArtifact(parts[0], parts[1], VersionRange.createFromVersion(parts[3]), null, parts[2], null, new DefaultArtifactHandler(parts[2]));
File parentFile = new File(localRepository.getBasedir(), localRepository.pathOf(parentArtifact));
// we need to include the artifact Id for poms as well, otherwise a project with the same groupId would override its parent's fingerprint
record(parts[0] + ":" + parts[1], parentFile, used);
parent = modelParents.get(parent);
}
}

// XXX consider calling also from PomInfo which makes a naked call to getParent
private static MavenProject getParent(MavenProject pom, BuildListener listener) {
try {
return pom.getParent();
} catch (IllegalStateException x) { // MNG-5075
x.printStackTrace(listener.error("Warning: failed to resolve parent of " + pom.getId()));
return null;
}
}

private Artifact getArtifact(MavenProject parent) {
Artifact art = parent.getArtifact();
if (art == null) {
// happens for Maven 2.x
DefaultArtifactHandler artifactHandler = new DefaultArtifactHandler("pom");
art = new DefaultArtifact(parent.getGroupId(), parent.getArtifactId(), VersionRange.createFromVersion(parent.getVersion()),
null, "pom", "", artifactHandler);
}
return art;
}

private ArtifactRepository getLocalRepository(MavenBuildInformation mavenBuildInformation, MavenProject parent, MavenProject pom) {

private ArtifactRepository getLocalRepository(MavenBuildInformation mavenBuildInformation, MavenProject pom) {
if (mavenBuildInformation.isMaven3OrLater()) {
return parent.getProjectBuildingRequest().getLocalRepository();
return pom.getProjectBuildingRequest().getLocalRepository();
} else if (mavenBuildInformation.isAtLeastMavenVersion("2.2")) {
// principally this should also work with Maven 2.1, but it's not tested, so err on the safe side
return getArtifactRepositoryMaven21(pom);
Expand Down

0 comments on commit 36c841f

Please sign in to comment.