提交 8e0b5527 编写于 作者: A abayer

[FIXED HUDSON-4102] Private repository will now be used for POM parsing - but...

[FIXED HUDSON-4102] Private repository will now be used for POM parsing - but more importantly, incremental Maven build support now added!

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@20113 71c3de6d-444a-0410-be80-ed276b4c234a
上级 7173ecf5
......@@ -27,7 +27,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>pom</artifactId>
<version>1.317-SNAPSHOT</version>
<version>1.316-SNAPSHOT</version>
</parent>
<artifactId>maven-plugin</artifactId>
......
......@@ -79,7 +79,7 @@ public class FilteredChangeLogSet extends ChangeLogSet<Entry> {
belongs = false;
for (String path : e.getAffectedPaths()) {
if(!belongsToSubsidiary(subsidiaries, path)) {
if(!MavenUtil.belongsToSubsidiary(subsidiaries, path)) {
belongs = true;
break;
}
......@@ -91,13 +91,6 @@ public class FilteredChangeLogSet extends ChangeLogSet<Entry> {
}
}
private boolean belongsToSubsidiary(List<MavenModule> subsidiaries, String path) {
for (MavenModule sub : subsidiaries)
if(path.startsWith(sub.getRelativePath()))
return true;
return false;
}
public Iterator<Entry> iterator() {
return master.iterator();
}
......
......@@ -107,6 +107,9 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
*/
private boolean aggregatorStyleBuild = true;
private boolean incrementalBuild = false;
/**
* If true, the build will use its own local Maven repository
* via "-Dmaven.repo.local=...".
......@@ -260,6 +263,10 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
};
}
public boolean isIncrementalBuild() {
return incrementalBuild;
}
public boolean isAggregatorStyleBuild() {
return aggregatorStyleBuild;
}
......@@ -622,6 +629,7 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
aggregatorStyleBuild = !req.hasParameter("maven.perModuleBuild");
usePrivateRepository = req.hasParameter("maven.usePrivateRepository");
ignoreUpstremChanges = !json.has("triggerByDependency");
incrementalBuild = req.hasParameter("maven.incrementalBuild");
reporters.rebuild(req,json,MavenReporters.getConfigurableList());
publishers.rebuild(req,json,BuildStepDescriptor.filter(Publisher.all(),this.getClass()));
......
......@@ -330,7 +330,13 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
PrintStream logger = listener.getLogger();
try {
EnvVars envVars = getEnvironment(listener);
parsePoms(listener, logger, envVars);
MavenInstallation mvn = project.getMaven();
if(mvn==null)
throw new AbortException("A Maven installation needs to be available for this project to be built.\n"+
"Either your server has no Maven installations defined, or the requested Maven version does not exist.");
mvn = mvn.forEnvironment(envVars).forNode(Computer.currentComputer().getNode(), listener);
parsePoms(listener, logger, envVars, mvn);
if(!project.isAggregatorStyleBuild()) {
// start module builds
......@@ -360,8 +366,21 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
SplittableBuildListener slistener = new SplittableBuildListener(listener);
proxies = new HashMap<ModuleName, ProxyImpl2>();
for (MavenModule m : project.sortedActiveModules)
List<String> changedModules = new ArrayList<String>();
for (MavenModule m : project.sortedActiveModules) {
// Check if incrementalBuild is selected and that there are changes -
// we act as if incrementalBuild is not set if there are no changes.
if (!MavenModuleSetBuild.this.getChangeSet().isEmptySet()
&& project.isIncrementalBuild()) {
if (MavenUtil.isModuleInChangeset(m, MavenModuleSetBuild.this)) {
changedModules.add(m.getModuleName().toString());
}
}
proxies.put(m.getModuleName(),m.newBuild().new ProxyImpl2(MavenModuleSetBuild.this,slistener));
}
// run the complete build here
......@@ -381,6 +400,13 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
ArgumentListBuilder margs = new ArgumentListBuilder().add("-B").add("-f", pom.getRemote());
if(project.usesPrivateRepository())
margs.add("-Dmaven.repo.local="+project.getWorkspace().child(".repository"));
// If incrementalBuild is set, and we're on Maven 2.1 or later, *and* there's at least one module
// listed in changedModules, do the Maven incremental build commands - if there are no changed modules,
// We're building everything anyway.
if (project.isIncrementalBuild() && mvn.isMaven2_1(launcher) && !changedModules.isEmpty()) {
margs.add("-amd");
margs.add("-pl", Util.join(changedModules, ","));
}
margs.addTokenized(envVars.expand(project.getGoals()));
Builder builder = new Builder(slistener, proxies, project.sortedActiveModules, margs.toList(), envVars);
......@@ -445,14 +471,8 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
}
}
private void parsePoms(BuildListener listener, PrintStream logger, EnvVars envVars) throws IOException, InterruptedException {
private void parsePoms(BuildListener listener, PrintStream logger, EnvVars envVars, MavenInstallation mvn) throws IOException, InterruptedException {
logger.println("Parsing POMs");
MavenInstallation mvn = project.getMaven();
if(mvn==null)
throw new AbortException("A Maven installation needs to be available for this project to be built.\n"+
"Either your server has no Maven installations defined, or the requested Maven version does not exist.");
mvn = mvn.forEnvironment(envVars).forNode(Computer.currentComputer().getNode(), listener);
List<PomInfo> poms;
try {
......@@ -714,6 +734,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
private final MavenInstallation mavenHome;
private final String profiles;
private final Properties properties;
private final String privateRepository;
public PomParser(BuildListener listener, MavenInstallation mavenHome, MavenModuleSet project) {
// project cannot be shipped to the remote JVM, so all the relevant properties need to be captured now.
......@@ -722,6 +743,12 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
this.rootPOM = project.getRootPOM();
this.profiles = project.getProfiles();
this.properties = project.getMavenProperties();
if (project.usesPrivateRepository()) {
this.privateRepository = project.getWorkspace().child(".repository").getRemote();
}
else {
this.privateRepository = null;
}
}
/**
......@@ -756,7 +783,8 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
try {
MavenEmbedder embedder = MavenUtil.
createEmbedder(listener,mavenHome.getHomeDir(),profiles,properties);
createEmbedder(listener, mavenHome.getHomeDir(), profiles,
properties, privateRepository);
MavenProject mp = embedder.readProject(pom);
Map<MavenProject,String> relPath = new HashMap<MavenProject,String>();
MavenUtil.resolveModules(embedder,mp,getRootPath(),relPath,listener);
......
......@@ -29,6 +29,10 @@ import hudson.model.TaskListener;
import hudson.model.AbstractProject;
import hudson.tasks.Maven.MavenInstallation;
import hudson.tasks.Maven.ProjectWithMaven;
import hudson.scm.ChangeLogSet;
import hudson.scm.ChangeLogSet.Entry;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.embedder.MavenEmbedderLogger;
import org.apache.maven.project.MavenProject;
......@@ -39,6 +43,7 @@ import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
......@@ -77,6 +82,10 @@ public class MavenUtil {
return createEmbedder(listener,mavenHome,profiles,new Properties());
}
public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles, Properties systemProperties) throws MavenEmbedderException, IOException {
return createEmbedder(listener,mavenHome,profiles,systemProperties,null);
}
/**
* Creates a fresh {@link MavenEmbedder} instance.
*
......@@ -89,8 +98,11 @@ public class MavenUtil {
* Profiles to activate/deactivate. Can be null.
* @param systemProperties
* The system properties that the embedded Maven sees. See {@link MavenEmbedder#setSystemProperties(Properties)}.
* @param privateRepository
* Optional private repository to use as the local repository.
*/
public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles, Properties systemProperties) throws MavenEmbedderException, IOException {
public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles, Properties systemProperties,
String privateRepository) throws MavenEmbedderException, IOException {
MavenEmbedder maven = new MavenEmbedder(mavenHome);
ClassLoader cl = MavenUtil.class.getClassLoader();
......@@ -113,6 +125,9 @@ public class MavenUtil {
throw new AbortException("Failed to create "+m2Home+
"\nSee https://hudson.dev.java.net/cannot-create-.m2.html");
if (privateRepository!=null)
maven.setLocalRepositoryDirectory(new File(privateRepository));
maven.setProfiles(profiles);
maven.setSystemProperties(systemProperties);
maven.start();
......@@ -236,6 +251,61 @@ public class MavenUtil {
}
}
public static boolean isModuleInChangeset(MavenModule mod, MavenModuleSetBuild parentBuild) {
// modules that are under 'mod'. lazily computed
List<MavenModule> subsidiaries = null;
boolean moduleChanged = false;
ChangeLogSet<? extends Entry> changes = parentBuild.getChangeSet();
for (Entry e : changes) {
boolean belongs = false;
for (String path : e.getAffectedPaths()) {
if(path.startsWith(mod.getRelativePath())) {
belongs = true;
break;
}
}
if(belongs) {
// make sure at least one change belongs to this module proper,
// and not its subsidiary module
if(subsidiaries==null) {
subsidiaries = new ArrayList<MavenModule>();
for (MavenModule mm : mod.getParent().getModules()) {
if(mm!=mod && mm.getRelativePath().startsWith(mod.getRelativePath()))
subsidiaries.add(mm);
}
}
belongs = false;
for (String path : e.getAffectedPaths()) {
if(!belongsToSubsidiary(subsidiaries, path)) {
belongs = true;
break;
}
}
if (belongs) {
moduleChanged = true;
}
}
}
return moduleChanged;
}
public static boolean belongsToSubsidiary(List<MavenModule> subsidiaries, String path) {
for (MavenModule sub : subsidiaries)
if(path.startsWith(sub.getRelativePath()))
return true;
return false;
}
/**
* If set to true, maximize the logging level of Maven embedder.
*/
......
......@@ -69,6 +69,10 @@ THE SOFTWARE.
<f:entry title="MAVEN_OPTS" help="/help/maven/maven-opts.html">
<f:expandableTextbox name="mavenOpts" value="${it.mavenOpts}" />
</f:entry>
<f:optionalBlock name="maven.incrementalBuild"
title="${%Incremental build - only build changed modules}"
help="/help/maven/incremental.html"
checked="${it.isIncrementalBuild()}" />
<f:optionalBlock name="maven.perModuleBuild" title="${%Build modules in parallel}" help="/help/maven/aggregator.html"
checked="${!it.aggregatorStyleBuild}" />
<f:optionalBlock name="maven.usePrivateRepository" title="${%Use private Maven repository}" help="/help/maven/private-repository.html"
......
<div>
<p>
If checked, Hudson will only build any modules with changes from SCM
and any modules which depend on those changed modules, using Maven's
"-amd -pl group1:artifact1,group1:artifact2" command-line
options. If the SCM reports no changes to any modules, however, all
modules will be
built. See <a href="http://docs.codehaus.org/display/MAVEN/Make+Like+Reactor+Mode">http://docs.codehaus.org/display/MAVEN/Make+Like+Reactor+Mode</a>
for more information on the Maven behavior this utilizes.
<p>
This functionality requires Maven 2.1 or later, and will not have
any impact if "Build modules in parallel" is selected.
</div>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册