提交 0c4fe2dd 编写于 作者: J Jesse Glick

[FIXED JENKINS-17775] Find (model) parent POMs properly during fingerprint...

[FIXED JENKINS-17775] Find (model) parent POMs properly during fingerprint recording at end of build.
上级 f6a8c31f
...@@ -58,6 +58,9 @@ Upcoming changes</a> ...@@ -58,6 +58,9 @@ Upcoming changes</a>
<li class=bug> <li class=bug>
Display Name is not shown. Display Name is not shown.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17715">issue 17715</a>) (<a href="https://issues.jenkins-ci.org/browse/JENKINS-17715">issue 17715</a>)
<li class='major bug'>
Properly find parent POMs when fingerprinting a Maven project.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17775">issue 17775</a>)
</ul> </ul>
</div><!--=TRUNK-END=--> </div><!--=TRUNK-END=-->
...@@ -73,7 +76,7 @@ Upcoming changes</a> ...@@ -73,7 +76,7 @@ Upcoming changes</a>
Third-party license display for core was broken since 1.506. Third-party license display for core was broken since 1.506.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17724">issue 17724</a>) (<a href="https://issues.jenkins-ci.org/browse/JENKINS-17724">issue 17724</a>)
<li class='major bug'> <li class='major bug'>
Amelioration of exception from fingerprinting in a Maven project when a parent POM could not be located. Mitigation of exception from fingerprinting in a Maven project when a parent POM could not be located.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17775">issue 17775</a>) (<a href="https://issues.jenkins-ci.org/browse/JENKINS-17775">issue 17775</a>)
<li class=bug> <li class=bug>
NPE from <code>MatrixConfiguration.newBuild</code>. NPE from <code>MatrixConfiguration.newBuild</code>.
......
...@@ -21,9 +21,13 @@ package hudson.maven; ...@@ -21,9 +21,13 @@ package hudson.maven;
*/ */
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.artifact.versioning.ComparableVersion;
import org.apache.maven.model.Model;
import org.apache.maven.project.MavenProject;
/** /**
* @author Olivier Lamy * @author Olivier Lamy
...@@ -33,6 +37,15 @@ public class MavenBuildInformation implements Serializable { ...@@ -33,6 +37,15 @@ public class MavenBuildInformation implements Serializable {
private static final long serialVersionUID = -3719709179508200057L; private static final long serialVersionUID = -3719709179508200057L;
private String mavenVersion; 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) { public MavenBuildInformation(String mavenVersion) {
this.mavenVersion = mavenVersion; this.mavenVersion = mavenVersion;
......
...@@ -65,6 +65,7 @@ import java.io.File; ...@@ -65,6 +65,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InterruptedIOException; import java.io.InterruptedIOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.Serializable;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
...@@ -582,7 +583,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -582,7 +583,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
LOGGER.fine(getFullDisplayName()+" is building with mavenVersion " + mavenVersion + " from file " + mavenInformation.getVersionResourcePath()); LOGGER.fine(getFullDisplayName()+" is building with mavenVersion " + mavenVersion + " from file " + mavenInformation.getVersionResourcePath());
if(!project.isAggregatorStyleBuild()) { if(!project.isAggregatorStyleBuild()) {
parsePoms(listener, logger, envVars, mvn, mavenVersion); parsePoms(listener, logger, envVars, mvn, mavenVersion, mavenBuildInformation);
// start module builds // start module builds
logger.println("Triggering "+project.getRootModule().getModuleName()); logger.println("Triggering "+project.getRootModule().getModuleName());
project.getRootModule().scheduleBuild(new UpstreamCause((Run<?,?>)MavenModuleSetBuild.this)); project.getRootModule().scheduleBuild(new UpstreamCause((Run<?,?>)MavenModuleSetBuild.this));
...@@ -619,7 +620,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -619,7 +620,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
return r; 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); SplittableBuildListener slistener = new SplittableBuildListener(listener);
proxies = new HashMap<ModuleName, ProxyImpl2>(); proxies = new HashMap<ModuleName, ProxyImpl2>();
List<ModuleName> changedModules = new ArrayList<ModuleName>(); List<ModuleName> changedModules = new ArrayList<ModuleName>();
...@@ -856,12 +857,14 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -856,12 +857,14 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
return unbuiltModules; 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"); logger.println("Parsing POMs");
List<PomInfo> poms; List<PomInfo> poms;
try { 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) { } catch (IOException e) {
if (project.isIncrementalBuild()) { if (project.isIncrementalBuild()) {
// If POM parsing failed we should do a full build next time. // If POM parsing failed we should do a full build next time.
...@@ -997,7 +1000,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -997,7 +1000,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
* Executed on the slave to parse POM and extract information into {@link PomInfo}, * Executed on the slave to parse POM and extract information into {@link PomInfo},
* which will be then brought back to the master. * 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 BuildListener listener;
private final String rootPOM; private final String rootPOM;
/** /**
...@@ -1028,7 +1031,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -1028,7 +1031,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
String rootPOMRelPrefix; 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. // project cannot be shipped to the remote JVM, so all the relevant properties need to be captured now.
MavenModuleSet project = build.getProject(); MavenModuleSet project = build.getProject();
this.listener = listener; this.listener = listener;
...@@ -1082,7 +1085,16 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -1082,7 +1085,16 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
return StringUtils.contains(goals, "-U") || StringUtils.contains(goals, "--update-snapshots"); 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; File pom;
PrintStream logger = listener.getLogger(); PrintStream logger = listener.getLogger();
...@@ -1194,10 +1206,23 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -1194,10 +1206,23 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
} }
} }
Map<String,MavenProject> canonicalPaths = new HashMap<String, MavenProject>( mps.size() ); Map<String,MavenProject> canonicalPaths = new HashMap<String, MavenProject>( mps.size() );
Map<String,String> modelParents = new HashMap<String,String>();
for(MavenProject mp : mps) { for(MavenProject mp : mps) {
// Projects are indexed by POM path and not module path because // Projects are indexed by POM path and not module path because
// Maven allows to have several POMs with different names in the same directory // Maven allows to have several POMs with different names in the same directory
canonicalPaths.put( mp.getFile().getCanonicalPath(), mp ); 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); //MavenUtil.resolveModules(embedder,mp,getRootPath(rootPOMRelPrefix),relPath,listener,nonRecursive);
...@@ -1225,7 +1250,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -1225,7 +1250,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
for (PomInfo pi : infos) for (PomInfo pi : infos)
pi.cutCycle(); pi.cutCycle();
return new ArrayList<PomInfo>(infos); return new Result(new ArrayList<PomInfo>(infos), modelParents);
} catch (MavenEmbedderException e) { } catch (MavenEmbedderException e) {
throw new MavenExecutionException(e); throw new MavenExecutionException(e);
} catch (ProjectBuildingException e) { } catch (ProjectBuildingException e) {
......
...@@ -138,60 +138,28 @@ public class MavenFingerprinter extends MavenReporter { ...@@ -138,60 +138,28 @@ public class MavenFingerprinter extends MavenReporter {
} }
private void recordParents(MavenBuildProxy build, MavenProject pom, BuildListener listener) 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) { while (parent != null) {
File parentFile = parent.getFile(); String[] parts = parent.split(":");
assert parts.length == 4 : parent;
if (parentFile == null) { // Maven 2.x lacks DefaultArtifact constructor with String version and ArtifactRepository.find:
// Parent artifact contains no actual file, so we resolve against Artifact parentArtifact = new DefaultArtifact(parts[0], parts[1], VersionRange.createFromVersion(parts[3]), null, parts[2], null, new DefaultArtifactHandler(parts[2]));
// the local repository File parentFile = new File(localRepository.getBasedir(), localRepository.pathOf(parentArtifact));
ArtifactRepository localRepository = getLocalRepository(build.getMavenBuildInformation(), parent, pom); // we need to include the artifact Id for poms as well, otherwise a project with the same groupId would override its parent's fingerprint
if (localRepository != null) { record(parts[0] + ":" + parts[1], parentFile, used);
Artifact parentArtifact = getArtifact(parent); parent = modelParents.get(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);
} }
} }
// XXX consider calling also from PomInfo which makes a naked call to getParent private ArtifactRepository getLocalRepository(MavenBuildInformation mavenBuildInformation, MavenProject pom) {
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) {
if (mavenBuildInformation.isMaven3OrLater()) { if (mavenBuildInformation.isMaven3OrLater()) {
return parent.getProjectBuildingRequest().getLocalRepository(); return pom.getProjectBuildingRequest().getLocalRepository();
} else if (mavenBuildInformation.isAtLeastMavenVersion("2.2")) { } 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 // principally this should also work with Maven 2.1, but it's not tested, so err on the safe side
return getArtifactRepositoryMaven21(pom); return getArtifactRepositoryMaven21(pom);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册