diff --git a/src/main/java/jenkins/plugins/svnmerge/AbstractSvnmergeTaskAction.java b/src/main/java/jenkins/plugins/svnmerge/AbstractSvnmergeTaskAction.java
index ca95997..c975324 100644
--- a/src/main/java/jenkins/plugins/svnmerge/AbstractSvnmergeTaskAction.java
+++ b/src/main/java/jenkins/plugins/svnmerge/AbstractSvnmergeTaskAction.java
@@ -27,6 +27,7 @@
import java.io.File;
import java.io.IOException;
+import java.util.List;
import java.util.concurrent.Future;
/**
@@ -90,7 +91,7 @@ public synchronized void doPerform(StaplerRequest req, StaplerResponse rsp) thro
*
* This requires that the calling thread owns the workspace.
*/
- /*package*/ abstract long perform(TaskListener listener, P param) throws IOException, InterruptedException;
+ /*package*/ abstract List perform(TaskListener listener, P param) throws IOException, InterruptedException;
/**
* Which page to render in the top page?
diff --git a/src/main/java/jenkins/plugins/svnmerge/FeatureBranchProperty.java b/src/main/java/jenkins/plugins/svnmerge/FeatureBranchProperty.java
index 4e227ee..f8ee8b4 100644
--- a/src/main/java/jenkins/plugins/svnmerge/FeatureBranchProperty.java
+++ b/src/main/java/jenkins/plugins/svnmerge/FeatureBranchProperty.java
@@ -2,6 +2,7 @@
import hudson.EnvVars;
import hudson.Extension;
+import hudson.FilePath;
import hudson.FilePath.FileCallable;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
@@ -95,16 +96,24 @@ public AbstractProject,?> getUpstreamProject() {
return Jenkins.getInstance().getItemByFullName(upstream,AbstractProject.class);
}
- public ModuleLocation getUpstreamSubversionLocation() {
+ /**
+ *
+ * @return All existing SVN Modules in project.
+ */
+ public List getUpstreamSubversionLocation() {
+ List toReturn = new ArrayList();
AbstractProject,?> p = getUpstreamProject();
if(p==null) return null;
SCM scm = p.getScm();
if (scm instanceof SubversionSCM) {
SubversionSCM svn = (SubversionSCM) scm;
- ModuleLocation ml = svn.getLocations()[0];
- // expand system and node environment variables as well as the project parameters
- ml = Utility.getExpandedLocation(ml, p);
- return ml;
+ for(ModuleLocation ml : svn.getLocations()){
+ // expand system and node environment variables as well as the project parameters
+ ml = Utility.getExpandedLocation(ml, p);
+ toReturn.add(ml);
+ }
+
+ return toReturn;
}
return null;
}
@@ -112,10 +121,14 @@ public ModuleLocation getUpstreamSubversionLocation() {
/**
* Gets the {@link #getUpstreamSubversionLocation()} as {@link SVNURL}
*/
- public SVNURL getUpstreamURL() throws SVNException {
- ModuleLocation location = getUpstreamSubversionLocation();
- if(location==null) return null;
- return location.getSVNURL();
+ public List getUpstreamURL() throws SVNException {
+ List toReturn = new ArrayList();
+ List locations = getUpstreamSubversionLocation();
+ for(ModuleLocation ml : locations){
+ if(ml!=null)
+ toReturn.add(ml.getSVNURL());
+ }
+ return toReturn;
}
public AbstractProject,?> getOwner() {
@@ -157,86 +170,110 @@ public boolean prebuild(AbstractBuild, ?> build, BuildListener listener) {
* -1 if it failed and the failure was handled gracefully
* (typically this means a merge conflict.)
*/
- public long rebase(final TaskListener listener, final long upstreamRev) throws IOException, InterruptedException {
+ public List rebase(final TaskListener listener, final long upstreamRev) throws IOException, InterruptedException {
+ List toReturn = new ArrayList();
final SubversionSCM svn = (SubversionSCM) getOwner().getScm();
+
final ISVNAuthenticationProvider provider = svn.createAuthenticationProvider(getOwner(), svn.getLocations()[0]);
- final ModuleLocation upstreamLocation = getUpstreamSubversionLocation();
+ final List upstreamLocations = getUpstreamSubversionLocation();
AbstractBuild build = owner.getSomeBuildWithWorkspace();
if (build == null) {
final PrintStream logger = listener.getLogger();
logger.print("No workspace found for project! Please perform a build first.\n");
- return -1L;
+ return null;
}
- return build.getModuleRoot().act(new FileCallable() {
- public Long invoke(File mr, VirtualChannel virtualChannel) throws IOException {
- try {
- final PrintStream logger = listener.getLogger();
- final boolean[] foundConflict = new boolean[1];
- ISVNEventHandler printHandler = new SubversionEventHandlerImpl(logger,mr) {
- @Override
- public void handleEvent(SVNEvent event, double progress) throws SVNException {
- super.handleEvent(event, progress);
- if (event.getContentsStatus() == SVNStatusType.CONFLICTED
- || event.getContentsStatus() == SVNStatusType.CONFLICTED_UNRESOLVED) {
- foundConflict[0] = true;
- }
+
+ FilePath[] svnModules = build.getModuleRoots();
+ for(int i = 0; i < svnModules.length; i++){
+ //There seems to be no way to match a subversion module url to job's local path
+ //So use indexes and pray that "svnModules" will match the order of "upstreamLocations"
+ final int currentIndex = i;
+ FilePath module = svnModules[i];
+ List results = module.act(new FileCallable>() {
+ public List invoke(File mr, VirtualChannel virtualChannel) throws IOException {
+ List toReturn = new ArrayList();
+ try {
+ final PrintStream logger = listener.getLogger();
+ final boolean[] foundConflict = new boolean[1];
+ ISVNEventHandler printHandler = new SubversionEventHandlerImpl(logger,mr) {
+ @Override
+ public void handleEvent(SVNEvent event, double progress) throws SVNException {
+ super.handleEvent(event, progress);
+ if (event.getContentsStatus() == SVNStatusType.CONFLICTED
+ || event.getContentsStatus() == SVNStatusType.CONFLICTED_UNRESOLVED) {
+ foundConflict[0] = true;
+ }
+ }
+ };
+
+ SvnClientManager svnm = SubversionSCM.createClientManager(provider);
+ ModuleLocation currentLocation = upstreamLocations.get(currentIndex);
+
+ SVNURL up = currentLocation == null ? null : currentLocation.getSVNURL();
+ SVNClientManager cm = svnm.getCore();
+ cm.setEventHandler(printHandler);
+
+ SVNWCClient wc = cm.getWCClient();
+ SVNDiffClient dc = cm.getDiffClient();
+
+ logger.printf("Updating workspace to the latest revision\n");
+ long wsr = cm.getUpdateClient().doUpdate(mr, HEAD, INFINITY, false, false);
+// logger.printf(" Updated to rev.%d\n",wsr); // reported by printHandler
+
+ SVNRevision mergeRev = upstreamRev >= 0 ? SVNRevision.create(upstreamRev) : cm.getWCClient().doInfo(up,HEAD,HEAD).getCommittedRevision();
+
+ logger.printf("Merging change from the upstream %s at rev.%s\n",up,mergeRev);
+ SVNRevisionRange r = new SVNRevisionRange(SVNRevision.create(0),mergeRev);
+ dc.doMerge(up, mergeRev, Arrays.asList(r), mr, INFINITY, true, false, false, false);
+ if(foundConflict[0]) {
+ logger.println("Found conflict. Reverting this failed merge");
+ wc.doRevert(new File[]{mr},INFINITY, null);
+ return null;
+ } else {
+ try {
+ logger.println("Committing changes");
+ SVNCommitClient cc = cm.getCommitClient();
+ SVNCommitInfo ci = cc.doCommit(new File[] { mr },
+ false, RebaseAction.COMMIT_MESSAGE_PREFIX
+ + "Rebasing from " + up + "@"
+ + mergeRev, null, null, false,
+ false, INFINITY);
+ if (ci.getNewRevision() < 0) {
+ logger.println(" No changes since the last rebase. This rebase was a no-op.");
+ toReturn.add(0L);
+ } else {
+ logger.println(" committed revision "
+ + ci.getNewRevision());
+ toReturn.add(ci.getNewRevision());
+ }
+ } catch (SVNException e) {
+ logger.println("Failed to commit!");
+ logger.println(e.getLocalizedMessage());
+ logger.println("Reverting this failed merge.");
+ wc.doRevert(new File[] { mr }, INFINITY, null);
+ return null;
+ }
}
- };
-
- SvnClientManager svnm = SubversionSCM.createClientManager(provider);
-
- SVNURL up = upstreamLocation == null ? null : upstreamLocation.getSVNURL();
- SVNClientManager cm = svnm.getCore();
- cm.setEventHandler(printHandler);
-
- SVNWCClient wc = cm.getWCClient();
- SVNDiffClient dc = cm.getDiffClient();
-
- logger.printf("Updating workspace to the latest revision\n");
- long wsr = cm.getUpdateClient().doUpdate(mr, HEAD, INFINITY, false, false);
-// logger.printf(" Updated to rev.%d\n",wsr); // reported by printHandler
-
- SVNRevision mergeRev = upstreamRev >= 0 ? SVNRevision.create(upstreamRev) : cm.getWCClient().doInfo(up,HEAD,HEAD).getCommittedRevision();
-
- logger.printf("Merging change from the upstream %s at rev.%s\n",up,mergeRev);
- SVNRevisionRange r = new SVNRevisionRange(SVNRevision.create(0),mergeRev);
- dc.doMerge(up, mergeRev, Arrays.asList(r), mr, INFINITY, true, false, false, false);
- if(foundConflict[0]) {
- logger.println("Found conflict. Reverting this failed merge");
- wc.doRevert(new File[]{mr},INFINITY, null);
- return -1L;
- } else {
- try {
- logger.println("Committing changes");
- SVNCommitClient cc = cm.getCommitClient();
- SVNCommitInfo ci = cc.doCommit(new File[] { mr },
- false, RebaseAction.COMMIT_MESSAGE_PREFIX
- + "Rebasing from " + up + "@"
- + mergeRev, null, null, false,
- false, INFINITY);
- if (ci.getNewRevision() < 0) {
- logger.println(" No changes since the last rebase. This rebase was a no-op.");
- return 0L;
- } else {
- logger.println(" committed revision "
- + ci.getNewRevision());
- return ci.getNewRevision();
- }
- } catch (SVNException e) {
- logger.println("Failed to commit!");
- logger.println(e.getLocalizedMessage());
- logger.println("Reverting this failed merge.");
- wc.doRevert(new File[] { mr }, INFINITY, null);
- return -1L;
- }
+
+ } catch (SVNException e) {
+ throw new IOException2("Failed to merge", e);
}
- } catch (SVNException e) {
- throw new IOException2("Failed to merge", e);
+ return toReturn;
}
+ });
+
+ //If at least one result is null, it means that we have a conflict. So exit for loop and return null
+ if(results != null){
+ toReturn.addAll(results);
+ } else {
+ toReturn = null;
+ break;
}
- });
+ }
+
+ return toReturn;
}
/**
@@ -273,146 +310,169 @@ public IntegrationResult(long mergeCommit, SVNRevision integrationSource) {
*
* @param listener
* Where the progress is sent.
- * @param branchURL
- * URL of the branch to be integrated. If null, use the workspace URL.
- * @param branchRev
- * Revision of the branch to be integrated to the upstream.
- * If -1, use the current workspace revision.
+ * @param svnInfo
+ * Contains:
+ * - URL of the branch to be integrated. If null, use the workspace URL.
+ * - Revision of the branch to be integrated to the upstream.
+ * If -1, use the current workspace revision.
* @return
* Always non-null. See {@link IntegrationResult}
*/
- public IntegrationResult integrate(final TaskListener listener, final String branchURL, final long branchRev, final String commitMessage) throws IOException, InterruptedException {
+ public List integrate(final TaskListener listener, final List svnInfo, final String commitMessage) throws IOException, InterruptedException {
+ List toReturn = new ArrayList();
final Long lastIntegrationSourceRevision = getlastIntegrationSourceRevision();
final SubversionSCM svn = (SubversionSCM) getUpstreamProject().getScm();
final ISVNAuthenticationProvider provider = svn.createAuthenticationProvider(getUpstreamProject(), svn.getLocations()[0]);
- final ModuleLocation upstreamLocation = getUpstreamSubversionLocation();
-
- return owner.getModuleRoot().act(new FileCallable() {
- public IntegrationResult invoke(File mr, VirtualChannel virtualChannel) throws IOException {
- try {
- final PrintStream logger = listener.getLogger();
- final boolean[] foundConflict = new boolean[1];
- ISVNEventHandler printHandler = new SubversionEventHandlerImpl(logger,mr) {
- @Override
- public void handleEvent(SVNEvent event, double progress) throws SVNException {
- super.handleEvent(event, progress);
- if(event.getContentsStatus()== SVNStatusType.CONFLICTED)
- foundConflict[0] = true;
- }
- };
-
- SvnClientManager svnm = SubversionSCM.createClientManager(provider);
-
- SVNURL up = upstreamLocation == null ? null : upstreamLocation.getSVNURL();
- SVNClientManager cm = svnm.getCore();
- cm.setEventHandler(printHandler);
-
- // capture the working directory state before the switch
- SVNWCClient wc = cm.getWCClient();
- SVNInfo wsState = wc.doInfo(mr, null);
- SVNURL mergeUrl = branchURL != null ? SVNURL.parseURIDecoded(branchURL) : wsState.getURL();
- SVNRevision mergeRev = branchRev >= 0 ? SVNRevision.create(branchRev) : wsState.getRevision();
-
- // do we have any meaningful changes in this branch worthy of integration?
- if (lastIntegrationSourceRevision !=null) {
- final MutableBoolean changesFound = new MutableBoolean(false);
- cm.getLogClient().doLog(new File[]{mr},mergeRev,SVNRevision.create(lastIntegrationSourceRevision),mergeRev,true,false,-1,new ISVNLogEntryHandler() {
- public void handleLogEntry(SVNLogEntry e) throws SVNException {
- if (!changesFound.booleanValue()) {
- String message = e.getMessage();
-
- if (!message.startsWith(RebaseAction.COMMIT_MESSAGE_PREFIX)
- && !message.startsWith(IntegrateAction.COMMIT_MESSAGE_PREFIX)) {
- changesFound.setValue(true);
+ final List upstreamLocations = getUpstreamSubversionLocation();
+
+ FilePath[] svnModules = owner.getModuleRoots();
+ for(int i = 0; i < svnModules.length; i++){
+ //There seems to be no way to match a subversion module url to job's local path
+ //So use indexes and pray that "svnModules" will match the order of "upstreamLocations"
+ final int currentIndex = i;
+ FilePath module = svnModules[i];
+ final String branchURL = svnInfo.get(i).url;
+ final long branchRev = svnInfo.get(i).revision;
+
+ IntegrationResult result = module.act(new FileCallable() {
+ public IntegrationResult invoke(File mr, VirtualChannel virtualChannel) throws IOException {
+ try {
+ final PrintStream logger = listener.getLogger();
+ final boolean[] foundConflict = new boolean[1];
+ ISVNEventHandler printHandler = new SubversionEventHandlerImpl(logger,mr) {
+ @Override
+ public void handleEvent(SVNEvent event, double progress) throws SVNException {
+ super.handleEvent(event, progress);
+ if(event.getContentsStatus()== SVNStatusType.CONFLICTED)
+ foundConflict[0] = true;
+ }
+ };
+
+ SvnClientManager svnm = SubversionSCM.createClientManager(provider);
+
+ ModuleLocation currentLocation = upstreamLocations.get(currentIndex);
+ SVNURL up = currentLocation == null ? null : currentLocation.getSVNURL();
+ SVNClientManager cm = svnm.getCore();
+ cm.setEventHandler(printHandler);
+
+ // capture the working directory state before the switch
+ SVNWCClient wc = cm.getWCClient();
+ SVNInfo wsState = wc.doInfo(mr, null);
+ SVNURL mergeUrl = branchURL != null ? SVNURL.parseURIDecoded(branchURL) : wsState.getURL();
+ SVNRevision mergeRev = branchRev >= 0 ? SVNRevision.create(branchRev) : wsState.getRevision();
+
+ // do we have any meaningful changes in this branch worthy of integration?
+ if (lastIntegrationSourceRevision !=null) {
+ final MutableBoolean changesFound = new MutableBoolean(false);
+ cm.getLogClient().doLog(new File[]{mr},mergeRev,SVNRevision.create(lastIntegrationSourceRevision),mergeRev,true,false,-1,new ISVNLogEntryHandler() {
+ public void handleLogEntry(SVNLogEntry e) throws SVNException {
+ if (!changesFound.booleanValue()) {
+ String message = e.getMessage();
+
+ if (!message.startsWith(RebaseAction.COMMIT_MESSAGE_PREFIX)
+ && !message.startsWith(IntegrateAction.COMMIT_MESSAGE_PREFIX)) {
+ changesFound.setValue(true);
+ }
}
}
+ });
+ // didn't find anything interesting. all the changes are our merges
+ if (!changesFound.booleanValue()) {
+ logger.println("No changes to be integrated. Skipping integration.");
+ return new IntegrationResult(0,mergeRev);
+
}
- });
- // didn't find anything interesting. all the changes are our merges
- if (!changesFound.booleanValue()) {
- logger.println("No changes to be integrated. Skipping integration.");
- return new IntegrationResult(0,mergeRev);
}
- }
-
- logger.println("Switching to the upstream (" + up+")");
- SVNUpdateClient uc = cm.getUpdateClient();
- uc.doSwitch(mr, up, HEAD, HEAD, INFINITY, false, false);
-
- logger.printf("Merging %s (rev.%s) to the upstream\n",mergeUrl,mergeRev);
- SVNDiffClient dc = cm.getDiffClient();
- dc.doMergeReIntegrate(
- mergeUrl,
- mergeRev, mr, false);
- SVNCommitInfo ci=null;
- if(foundConflict[0]) {
- logger.println("Found conflict with the upstream. Reverting this failed merge");
- wc.doRevert(new File[]{mr},INFINITY, null);
- } else {
- logger.println("Committing changes to the upstream");
- SVNCommitClient cc = cm.getCommitClient();
- ci = cc.doCommit(new File[]{mr}, false, commitMessage+"\n"+mergeUrl+"@"+mergeRev, null, null, false, false, INFINITY);
- if(ci.getNewRevision()<0)
- logger.println(" No changes since the last integration");
- else
- logger.println(" committed revision "+ci.getNewRevision());
- }
- logger.println("Switching back to the branch (" + wsState.getURL()+"@"+wsState.getRevision()+")");
- uc.doSwitch(mr, wsState.getURL(), wsState.getRevision(), wsState.getRevision(), INFINITY, false, true);
+ logger.println("Switching to the upstream (" + up+")");
+ SVNUpdateClient uc = cm.getUpdateClient();
+ uc.doSwitch(mr, up, HEAD, HEAD, INFINITY, false, false);
- if(foundConflict[0]) {
- logger.println("Conflict found. Please sync with the upstream to resolve this error.");
- return new IntegrationResult(-1,mergeRev);
- }
+ logger.printf("Merging %s (rev.%s) to the upstream\n",mergeUrl,mergeRev);
+ SVNDiffClient dc = cm.getDiffClient();
+ dc.doMergeReIntegrate(
+ mergeUrl,
+ mergeRev, mr, false);
+ SVNCommitInfo ci=null;
+ if(foundConflict[0]) {
+ logger.println("Found conflict with the upstream. Reverting this failed merge");
+ wc.doRevert(new File[]{mr},INFINITY, null);
+ } else {
+ logger.println("Committing changes to the upstream");
+ SVNCommitClient cc = cm.getCommitClient();
+ ci = cc.doCommit(new File[]{mr}, false, commitMessage+"\n"+mergeUrl+"@"+mergeRev, null, null, false, false, INFINITY);
+ if(ci.getNewRevision()<0)
+ logger.println(" No changes since the last integration");
+ else
+ logger.println(" committed revision "+ci.getNewRevision());
+ }
- long trunkCommit = ci.getNewRevision();
+ logger.println("Switching back to the branch (" + wsState.getURL()+"@"+wsState.getRevision()+")");
+ uc.doSwitch(mr, wsState.getURL(), wsState.getRevision(), wsState.getRevision(), INFINITY, false, true);
+
+ if(foundConflict[0]) {
+ logger.println("Conflict found. Please sync with the upstream to resolve this error.");
+ return new IntegrationResult(-1,mergeRev);
+ }
- if (trunkCommit>=0) {
- cm.getUpdateClient().doUpdate(mr, HEAD, INFINITY, false, false);
- SVNCommitClient cc = cm.getCommitClient();
+ long trunkCommit = ci.getNewRevision();
- if (false) {
- // taking Jack Repennings advise not to do this.
+ if (trunkCommit>=0) {
+ cm.getUpdateClient().doUpdate(mr, HEAD, INFINITY, false, false);
+ SVNCommitClient cc = cm.getCommitClient();
+
+ if (false) {
+ // taking Jack Repennings advise not to do this.
+
+ // if the trunk merge produces a commit M, then we want to do "svn merge --record-only -c M "
+ // to convince Subversion not to try to merge rev.M again when re-integrating from the trunk in the future,
+ // equivalent of single commit
+ SVNRevisionRange r = new SVNRevisionRange(SVNRevision.create(trunkCommit-1),
+ SVNRevision.create(trunkCommit));
+ String msg = "Block the merge commit rev." + trunkCommit + " from getting merged back into our branch";
+ logger.println(msg);
+ dc.doMerge(up,HEAD,Arrays.asList(r), mr, INFINITY, true/*opposite of --ignore-ancestory in CLI*/, false, false, true);
+
+ SVNCommitInfo bci = cc.doCommit(new File[]{mr}, false, msg, null, null, false, false, INFINITY);
+ logger.println(" committed revision "+bci.getNewRevision());
+ cm.getUpdateClient().doUpdate(mr, HEAD, INFINITY, false, false);
+ }
- // if the trunk merge produces a commit M, then we want to do "svn merge --record-only -c M "
- // to convince Subversion not to try to merge rev.M again when re-integrating from the trunk in the future,
- // equivalent of single commit
- SVNRevisionRange r = new SVNRevisionRange(SVNRevision.create(trunkCommit-1),
- SVNRevision.create(trunkCommit));
- String msg = "Block the merge commit rev." + trunkCommit + " from getting merged back into our branch";
- logger.println(msg);
- dc.doMerge(up,HEAD,Arrays.asList(r), mr, INFINITY, true/*opposite of --ignore-ancestory in CLI*/, false, false, true);
+ // this is the black magic part, but my experiments reveal that we need to run trunk->branch merge --reintegrate
+ // or else future rebase fails
+ logger.printf("Merging change from the upstream %s at rev.%s\n",up,trunkCommit);
+ dc.doMergeReIntegrate(up, SVNRevision.create(trunkCommit), mr, false);
+ if(foundConflict[0]) {
+ uc.doSwitch(mr, wsState.getURL(), wsState.getRevision(), wsState.getRevision(), INFINITY, false, true);
+ logger.println("Conflict found. Please sync with the upstream to resolve this error.");
+ return new IntegrationResult(-1,mergeRev);
+ }
+ String msg = RebaseAction.COMMIT_MESSAGE_PREFIX+"Rebasing with the integration commit that was just made in rev."+trunkCommit;
SVNCommitInfo bci = cc.doCommit(new File[]{mr}, false, msg, null, null, false, false, INFINITY);
logger.println(" committed revision "+bci.getNewRevision());
- cm.getUpdateClient().doUpdate(mr, HEAD, INFINITY, false, false);
- }
-
- // this is the black magic part, but my experiments reveal that we need to run trunk->branch merge --reintegrate
- // or else future rebase fails
- logger.printf("Merging change from the upstream %s at rev.%s\n",up,trunkCommit);
- dc.doMergeReIntegrate(up, SVNRevision.create(trunkCommit), mr, false);
- if(foundConflict[0]) {
- uc.doSwitch(mr, wsState.getURL(), wsState.getRevision(), wsState.getRevision(), INFINITY, false, true);
- logger.println("Conflict found. Please sync with the upstream to resolve this error.");
- return new IntegrationResult(-1,mergeRev);
}
- String msg = RebaseAction.COMMIT_MESSAGE_PREFIX+"Rebasing with the integration commit that was just made in rev."+trunkCommit;
- SVNCommitInfo bci = cc.doCommit(new File[]{mr}, false, msg, null, null, false, false, INFINITY);
- logger.println(" committed revision "+bci.getNewRevision());
- }
-
- // -1 is returned if there was no commit, so normalize that to 0
- return new IntegrationResult(Math.max(0,trunkCommit),mergeRev);
+ // -1 is returned if there was no commit, so normalize that to 0
+ return new IntegrationResult(Math.max(0,trunkCommit),mergeRev);
} catch (SVNException e) {
throw new IOException2("Failed to merge", e);
}
+ }
+ });
+
+ //If at least one result is null, it means that we have a conflict. So exit for loop and return null:
+ if(result != null){
+ toReturn.add(result);
+ } else {
+ toReturn = null;
+ break;
}
- });
+ }
+
+ return toReturn;
}
private Long getlastIntegrationSourceRevision() {
diff --git a/src/main/java/jenkins/plugins/svnmerge/IntegratableProjectAction.java b/src/main/java/jenkins/plugins/svnmerge/IntegratableProjectAction.java
index f734a12..5a628ec 100644
--- a/src/main/java/jenkins/plugins/svnmerge/IntegratableProjectAction.java
+++ b/src/main/java/jenkins/plugins/svnmerge/IntegratableProjectAction.java
@@ -94,24 +94,28 @@ public List> getBranches() {
*
* @return
*/
- public RepositoryLayoutInfo getRepositoryLayout() {
+ public ArrayList getRepositoryLayout() {
+ ArrayList toReturn = new ArrayList();
SCM scm = project.getScm();
if (!(scm instanceof SubversionSCM)) {
return null;
}
- //TODO: check for multiple locations ?
+
SubversionSCM svn = (SubversionSCM) scm;
- ModuleLocation firstLocation = svn.getLocations()[0];
- // expand system and node environment variables as well as the project parameters
- firstLocation = Utility.getExpandedLocation(firstLocation, project);
- return getRepositoryLayout(firstLocation);
+ for(ModuleLocation ml : svn.getLocations()){
+ // expand system and node environment variables as well as the project parameters
+ ml = Utility.getExpandedLocation(ml, project);
+ toReturn.add(getRepositoryLayout(ml));
+ }
+
+ return toReturn;
}
private RepositoryLayoutInfo getRepositoryLayout(ModuleLocation location) {
return new RepositoryLayoutInfo(location.getURL());
}
- @RequirePOST
+ @RequirePOST
public void doNewBranch(StaplerRequest req, StaplerResponse rsp,
@QueryParameter String name,
@QueryParameter boolean attach,
@@ -139,123 +143,133 @@ public void doNewBranch(StaplerRequest req, StaplerResponse rsp,
sendError("This project doesn't use Subversion as SCM");
return;
}
- // TODO: check for multiple locations
+
SubversionSCM svn = (SubversionSCM) scm;
- ModuleLocation firstLocation = svn.getLocations()[0];
- // expand system and node environment variables as well as the project parameters
- firstLocation = Utility.getExpandedLocation(firstLocation, project);
- RepositoryLayoutInfo layoutInfo = getRepositoryLayout(firstLocation);
-
- branchLocation = Util.fixEmptyAndTrim(branchLocation);
- tagLocation = Util.fixEmptyAndTrim(tagLocation);
-
- if (layoutInfo.getLayout() == RepositoryLayoutEnum.CUSTOM) {
+ //Create list with all new locations. This will be later copied to the new job
+ List locationsToCopy = new ArrayList();
+
+ for(ModuleLocation currentLocation : svn.getLocations()){
+ // expand system and node environment variables as well as the project parameters
+ currentLocation = Utility.getExpandedLocation(currentLocation, project);
+
+ RepositoryLayoutInfo layoutInfo = getRepositoryLayout(currentLocation);
+
+ branchLocation = Util.fixEmptyAndTrim(branchLocation);
+ tagLocation = Util.fixEmptyAndTrim(tagLocation);
+
+ if (layoutInfo.getLayout() == RepositoryLayoutEnum.CUSTOM) {
/*
* in case of custom layout the user must provide the full new branch url
* (and optionally the full new tag url)
*/
- if (StringUtils.isEmpty(branchLocation)) {
- sendError("Branch Location is required for custom repository layout");
- }
- if (!attach && createTag && StringUtils.isEmpty(tagLocation)) {
- sendError("Tag Location is required for custom repository layout");
- }
- }
-
- String branchUrl;
- if (StringUtils.isNotEmpty(branchLocation)) {
- //using override value
- branchUrl = branchLocation;
- } else {
- //using default value
- branchUrl = layoutInfo.getDefaultNewBranchUrl().replace("", name);
- }
-
- if (!attach) {
- SvnClientManager svnMgr = SubversionSCM.createClientManager(
- svn.createAuthenticationProvider(project, firstLocation));
-
- List urlsToCopyTo = new ArrayList();
- SVNURL svnUrl = null;
- try {
- svnUrl = SVNURL.parseURIEncoded(branchUrl);
- SVNInfo info = svnMgr.getWCClient().doInfo(svnUrl, SVNRevision.HEAD, SVNRevision.HEAD);
- if(info.getKind()== SVNNodeKind.DIR) {
- // ask the user if we should attach
- req.getView(this,"_attach.jelly").forward(req,rsp);
- return;
- } else {
- sendError(info.getURL()+" already exists.");
- return;
- }
- } catch (SVNException e) {
- // path doesn't exist, the new branch can be created
- }
- urlsToCopyTo.add(branchUrl);
-
- String tagUrl = null;
- if (createTag) {
- //can be true only when not attaching
- if (StringUtils.isNotEmpty(tagLocation)) {
- //using override value
- tagUrl = tagLocation;
- } else {
- //using default value
- tagUrl = layoutInfo.getDefaultNewDevTagUrl().replace("", name);
- }
- try {
- svnUrl = SVNURL.parseURIEncoded(tagUrl);
- SVNInfo info = svnMgr.getWCClient().doInfo(svnUrl, SVNRevision.HEAD, SVNRevision.HEAD);
- sendError(info.getURL()+" already exists.");
- return;
- } catch (SVNException e) {
- // path doesn't exist, the new tag can be created
- }
- urlsToCopyTo.add(tagUrl);
- }
-
- if (!createSVNCopy(svnMgr, firstLocation, urlsToCopyTo, commitMessage, req, rsp)) {
- return;
+ if (StringUtils.isEmpty(branchLocation)) {
+ sendError("Branch Location is required for custom repository layout");
+ }
+ if (!attach && createTag && StringUtils.isEmpty(tagLocation)) {
+ sendError("Tag Location is required for custom repository layout");
+ }
}
- }
-
- // if the request wasn't forwarded
- // copy a job, and adjust its properties for integration
- AbstractProject,?> copy = Jenkins.getInstance().copy(project, project.getName() + "-" + name.replaceAll("/", "-"));
- BulkChange bc = new BulkChange(copy);
- try {
+ String branchUrl;
+ if (StringUtils.isNotEmpty(branchLocation)) {
+ //using override value
+ branchUrl = branchLocation;
+ } else {
+ //using default value
+ branchUrl = layoutInfo.getDefaultNewBranchUrl().replace("", name);
+ }
+
+ if (!attach) {
+ SvnClientManager svnMgr = SubversionSCM.createClientManager(
+ svn.createAuthenticationProvider(project, currentLocation));
+
+ List urlsToCopyTo = new ArrayList();
+ SVNURL svnUrl = null;
+ try {
+ svnUrl = SVNURL.parseURIEncoded(branchUrl);
+ SVNInfo info = svnMgr.getWCClient().doInfo(svnUrl, SVNRevision.HEAD, SVNRevision.HEAD);
+ if(info.getKind()== SVNNodeKind.DIR) {
+ // ask the user if we should attach
+ req.getView(this,"_attach.jelly").forward(req,rsp);
+ return;
+ } else {
+ sendError(info.getURL()+" already exists.");
+ return;
+ }
+ } catch (SVNException e) {
+ // path doesn't exist, the new branch can be created
+ }
+ urlsToCopyTo.add(branchUrl);
+
+ String tagUrl = null;
+ if (createTag) {
+ //can be true only when not attaching
+ if (StringUtils.isNotEmpty(tagLocation)) {
+ //using override value
+ tagUrl = tagLocation;
+ } else {
+ //using default value
+ tagUrl = layoutInfo.getDefaultNewDevTagUrl().replace("", name);
+ }
+ try {
+ svnUrl = SVNURL.parseURIEncoded(tagUrl);
+ SVNInfo info = svnMgr.getWCClient().doInfo(svnUrl, SVNRevision.HEAD, SVNRevision.HEAD);
+ sendError(info.getURL()+" already exists.");
+ return;
+ } catch (SVNException e) {
+ // path doesn't exist, the new tag can be created
+ }
+ urlsToCopyTo.add(tagUrl);
+ }
+
+ if (!createSVNCopy(svnMgr, currentLocation, urlsToCopyTo, commitMessage, req, rsp)) {
+ return;
+ }
+ }
+ //Add new location, we will copy in new job's Subversion
+ locationsToCopy.add(currentLocation.withRemote(branchUrl));
+ }
+
+ // if the request wasn't forwarded
+ // copy a job, and adjust its properties for integration
+ AbstractProject,?> copy = Jenkins.getInstance().copy(project, project.getName() + "-" + name.replaceAll("/", "-"));
+ BulkChange bc = new BulkChange(copy);
- // moving the copy to its parent location
- moveProjectToItsUpstreamProjectLocation(copy, project);
- // the copy doesn't born accepting integration from subversion feature branches..
- copy.removeProperty(IntegratableProject.class);
+ try {
+
+ // moving the copy to its parent location
+ moveProjectToItsUpstreamProjectLocation(copy, project);
+ // the copy doesn't born accepting integration from subversion feature branches..
+ copy.removeProperty(IntegratableProject.class);
// ... and it's a feature branch of its upstream project (which can
// be located anywhere in the tree, that's why we are pointing
// to its full name)
- ((AbstractProject)copy).addProperty(new FeatureBranchProperty(project.getFullName())); // pointless cast for working around javac bug as of JDK1.6.0_02
- // update the SCM config to point to the branch
- SubversionSCM svnScm = (SubversionSCM)copy.getScm();
- copy.setScm(
- new SubversionSCM(
- Arrays.asList(firstLocation.withRemote(branchUrl)),
- svnScm.getWorkspaceUpdater(),
- svnScm.getBrowser(),
- svnScm.getExcludedRegions(),
- svnScm.getExcludedUsers(),
- svnScm.getExcludedRevprop(),
- svnScm.getExcludedCommitMessages(),
- svnScm.getIncludedRegions(),
- svnScm.isIgnoreDirPropChanges(),
- svnScm.isFilterChangelog(),
- svnScm.getAdditionalCredentials()
- ));
- } finally {
- bc.commit();
- }
-
- rsp.sendRedirect2(req.getContextPath()+"/"+copy.getUrl());
+ ((AbstractProject)copy).addProperty(new FeatureBranchProperty(project.getFullName())); // pointless cast for working around javac bug as of JDK1.6.0_02
+ // update the SCM config to point to the branch
+ SubversionSCM svnScm = (SubversionSCM)copy.getScm();
+
+
+ copy.setScm(
+ new SubversionSCM(
+ locationsToCopy,
+ svnScm.getWorkspaceUpdater(),
+ svnScm.getBrowser(),
+ svnScm.getExcludedRegions(),
+ svnScm.getExcludedUsers(),
+ svnScm.getExcludedRevprop(),
+ svnScm.getExcludedCommitMessages(),
+ svnScm.getIncludedRegions(),
+ svnScm.isIgnoreDirPropChanges(),
+ svnScm.isFilterChangelog(),
+ svnScm.getAdditionalCredentials()
+ ));
+ } finally {
+ bc.commit();
+ }
+
+ rsp.sendRedirect2(req.getContextPath()+"/"+copy.getUrl());
+
}
/**
@@ -293,7 +307,7 @@ private void moveProjectToItsUpstreamPro
/**
* Utility method for SVN copies creation.
* First checks if all the given urls already exist; if any exist, creates a copy for each of them.
- * @param scm the project scm
+ * @param svnMgr the project scm
* @param urlsToCopyTo a list of urls to copy to (i.e. where the copies'll be created).
* @param commitMessage the commit message to use
* @param req the original StaplerRequest
diff --git a/src/main/java/jenkins/plugins/svnmerge/IntegrateAction.java b/src/main/java/jenkins/plugins/svnmerge/IntegrateAction.java
index f15c479..7e7c27b 100644
--- a/src/main/java/jenkins/plugins/svnmerge/IntegrateAction.java
+++ b/src/main/java/jenkins/plugins/svnmerge/IntegrateAction.java
@@ -31,7 +31,9 @@
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Hashtable;
+import java.util.List;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
@@ -129,31 +131,31 @@ protected IntegrateSetting createParams(StaplerRequest req) throws IOException {
/**
* URL and revision to be integrated from this action.
*/
- public SvnInfo getSvnInfo() {
+ public List getSvnInfo() {
+ List toReturn = new ArrayList();
SCM scm = getProject().getScm();
if (!(scm instanceof SubversionSCM)) {
return null;
}
- // TODO: check for multiple locations ?
SubversionSCM svn = (SubversionSCM) scm;
- ModuleLocation[] locations = svn.getLocations();
-
- ModuleLocation firstLocation = svn.getLocations()[0];
- // expand system and node environment variables as well as the
- // project parameters
- firstLocation = Utility.getExpandedLocation(firstLocation, getProject());
-
- try {
- SVNRevisionState state = build.getAction(SVNRevisionState.class);
- long revision = state.getRevision(firstLocation.getURL());
-
- return new SvnInfo(firstLocation.getSVNURL().toDecodedString(), revision);
- } catch (SVNException e) {
- LOGGER.log(WARNING, "Could not get SVN URL and revision", e);
+ ModuleLocation[] locations = svn.getLocations();
+ for(ModuleLocation currentLocation : locations){
+ // expand system and node environment variables as well as the
+ // project parameters
+ currentLocation = Utility.getExpandedLocation(currentLocation, getProject());
+
+ try {
+ SVNRevisionState state = build.getAction(SVNRevisionState.class);
+ long revision = state.getRevision(currentLocation.getURL().toLowerCase());
+
+ toReturn.add(new SvnInfo(currentLocation.getSVNURL().toDecodedString(), revision));
+ } catch (SVNException e) {
+ LOGGER.log(WARNING, "Could not get SVN URL and revision", e);
+ }
}
- return null;
+ return toReturn;
}
/**
@@ -161,7 +163,7 @@ public SvnInfo getSvnInfo() {
*
* This requires that the calling thread owns the workspace.
*/
- /*package*/ long perform(TaskListener listener, IntegrateSetting _) throws IOException, InterruptedException {
+ /*package*/ List perform(TaskListener listener, IntegrateSetting _) throws IOException, InterruptedException {
return perform(listener, getSvnInfo());
}
@@ -169,21 +171,29 @@ public SvnInfo getSvnInfo() {
* @param src
* We are taking this revision and merge it into the upstream.
*/
- public long perform(TaskListener listener, SvnInfo src) throws IOException, InterruptedException {
+ public List perform(TaskListener listener, List src) throws IOException, InterruptedException {
String commitMessage = getCommitMessage();
-
- IntegrationResult r = getProperty().integrate(listener, src.url, src.revision, commitMessage);
- integratedRevision = r.mergeCommit;
- integrationSource = r.integrationSource;
- if(integratedRevision>0) {
- // record this integration as a fingerprint.
- // this will allow us to find where this change is integrated.
- Jenkins.getInstance().getFingerprintMap().getOrCreate(
- build, IntegrateAction.class.getName(),
- getFingerprintKey());
+ List toReturn = new ArrayList();
+
+ List integrations = getProperty().integrate(listener, src, commitMessage);
+
+ if(integrations != null && integrations.size() > 0){
+ for(IntegrationResult r : integrations){
+ integratedRevision = r.mergeCommit;
+ integrationSource = r.integrationSource;
+ if(integratedRevision>0) {
+ // record this integration as a fingerprint.
+ // this will allow us to find where this change is integrated.
+ Jenkins.getInstance().getFingerprintMap().getOrCreate(
+ build, IntegrateAction.class.getName(),
+ getFingerprintKey());
+ }
+ build.save();
+ toReturn.add(integratedRevision);
+ }
}
- build.save();
- return integratedRevision;
+
+ return toReturn;
}
/**
diff --git a/src/main/java/jenkins/plugins/svnmerge/IntegrationPublisher.java b/src/main/java/jenkins/plugins/svnmerge/IntegrationPublisher.java
index 370ce5e..316f8f7 100644
--- a/src/main/java/jenkins/plugins/svnmerge/IntegrationPublisher.java
+++ b/src/main/java/jenkins/plugins/svnmerge/IntegrationPublisher.java
@@ -16,6 +16,7 @@
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.IOException;
+import java.util.List;
/**
* {@link Publisher} that integrates the current workspace to the upstream.
@@ -48,8 +49,17 @@ public boolean perform(AbstractBuild,?> build, Launcher launcher, final BuildL
return false;
}
- if(ia.perform(listener,new IntegrateSetting())<0)
+ List integrationResults = ia.perform(listener,new IntegrateSetting());
+
+ if(integrationResults != null && integrationResults.size() > 0){
+ for(Long result : integrationResults){
+ if(result<0)
+ build.setResult(Result.FAILURE);
+ }
+ } else {
build.setResult(Result.FAILURE);
+ }
+
return true;
}
diff --git a/src/main/java/jenkins/plugins/svnmerge/RebaseAction.java b/src/main/java/jenkins/plugins/svnmerge/RebaseAction.java
index 53acb06..db63ed0 100644
--- a/src/main/java/jenkins/plugins/svnmerge/RebaseAction.java
+++ b/src/main/java/jenkins/plugins/svnmerge/RebaseAction.java
@@ -16,11 +16,14 @@
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
+import org.tmatesoft.svn.core.wc.SVNInfo;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
/**
* {@link AbstractProject}-level action to rebase changes from the upstream branch into the current branch.
@@ -89,8 +92,9 @@ protected TaskImpl createTask(RebaseSetting param) throws IOException {
*
* This requires that the calling thread owns the workspace.
*/
- /*package*/ long perform(TaskListener listener, RebaseSetting param) throws IOException, InterruptedException {
- long rev = param.revision;
+ /*package*/ List perform(TaskListener listener, RebaseSetting param) throws IOException, InterruptedException {
+ List revisions = new ArrayList();
+ revisions.add(param.revision);
if (param.permalink!=null) {
AbstractProject, ?> up = getProperty().getUpstreamProject();
@@ -99,20 +103,29 @@ protected TaskImpl createTask(RebaseSetting param) throws IOException {
Run,?> b = p.resolve(up);
if (b==null) {
listener.getLogger().println("No build that matches "+p.getDisplayName()+". Rebase is no-nop.");
- return -1;
+ return null;
}
SubversionTagAction a = b.getAction(SubversionTagAction.class);
if (a==null)
throw new AbortException("Unable to determine the Subversion revision number from "+b.getFullDisplayName());
- // TODO: what to do if this involves multiple URLs?
- SvnInfo sv = a.getTags().keySet().iterator().next();
- rev = sv.revision;
+ revisions = new ArrayList();
+ for(SvnInfo sv : a.getTags().keySet()){
+ long currentRev = sv.revision;
+ revisions.add(currentRev);
+ }
}
}
- long integratedRevision = getProperty().rebase(listener, rev);
+ List integratedRevisions = new ArrayList();
+ for(Long rev : revisions){
+ List integrated = getProperty().rebase(listener, rev);
+ if(integrated != null)
+ integratedRevisions.addAll(integrated);
+ else
+ return null;
+ }
// if(integratedRevision>0) {
// // record this integration as a fingerprint.
// // this will allow us to find where this change is integrated.
@@ -120,7 +133,7 @@ protected TaskImpl createTask(RebaseSetting param) throws IOException {
// build, IntegrateAction.class.getName(),
// getFingerprintKey());
// }
- return integratedRevision;
+ return integratedRevisions;
}
/**
diff --git a/src/main/java/jenkins/plugins/svnmerge/RebaseBuilder.java b/src/main/java/jenkins/plugins/svnmerge/RebaseBuilder.java
index 0bbaf91..c560047 100644
--- a/src/main/java/jenkins/plugins/svnmerge/RebaseBuilder.java
+++ b/src/main/java/jenkins/plugins/svnmerge/RebaseBuilder.java
@@ -16,6 +16,7 @@
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.IOException;
+import java.util.List;
/**
* @author Kohsuke Kawaguchi
@@ -50,11 +51,21 @@ public boolean perform(AbstractBuild, ?> build, Launcher launcher, BuildListen
}
RebaseAction rebaseAction = new RebaseAction(project);
- long result = rebaseAction.perform(listener,new RebaseSetting(permalink));
- if(result<0){
- build.setResult(Result.UNSTABLE);
+ List results = rebaseAction.perform(listener,new RebaseSetting(permalink));
+ boolean buildStable = true;
+
+ if(results != null && results.size() > 0){
+ for(Long result : results){
+ if(result<0){
+ build.setResult(Result.UNSTABLE);
+ buildStable = false;
+ }
+ }
+ } else {
+ buildStable = false;
}
- return !stopBuildIfMergeFails || result >= 0;
+
+ return !stopBuildIfMergeFails || buildStable;
}
@Extension
diff --git a/src/main/resources/jenkins/plugins/svnmerge/IntegratableProjectAction/index.groovy b/src/main/resources/jenkins/plugins/svnmerge/IntegratableProjectAction/index.groovy
index 72ba443..f62433a 100644
--- a/src/main/resources/jenkins/plugins/svnmerge/IntegratableProjectAction/index.groovy
+++ b/src/main/resources/jenkins/plugins/svnmerge/IntegratableProjectAction/index.groovy
@@ -24,7 +24,7 @@ l.layout(norefresh:"true",title:_("title",my.project.displayName)) {
def repoLayout = my.repositoryLayout
p(_("Repository URL: "+repoLayout.scmModuleLocation))
p(_("Detected repository layout: "+repoLayout.layout))
- if (StringUtils.isNotEmpty(repoLayout.subProjectName)) {
+ if (repoLayout.subProjectName != null) {
p(_("Detected subproject name: "+repoLayout.subProjectName))
}
diff --git a/src/test/java/jenkins/plugins/svnmerge/FeatureBranchPropertyTest.java b/src/test/java/jenkins/plugins/svnmerge/FeatureBranchPropertyTest.java
index c15e6cb..9f22325 100644
--- a/src/test/java/jenkins/plugins/svnmerge/FeatureBranchPropertyTest.java
+++ b/src/test/java/jenkins/plugins/svnmerge/FeatureBranchPropertyTest.java
@@ -23,6 +23,8 @@
import hudson.slaves.EnvironmentVariablesNodeProperty;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.wc.SVNInfo;
/**
* @author Kohsuke Kawaguchi
@@ -48,7 +50,7 @@ public void testConfigRoundtrip2() throws Exception {
@Bug(24735)
public void testUpStreamURLwithParams()
throws Exception {
- EnvironmentVariablesNodeProperty envNodeProp = new EnvironmentVariablesNodeProperty(new hudson.slaves.EnvironmentVariablesNodeProperty.Entry("ROOT_SVN_URL", "root/"));
+ EnvironmentVariablesNodeProperty envNodeProp = new EnvironmentVariablesNodeProperty(new hudson.slaves.EnvironmentVariablesNodeProperty.Entry("ROOT_SVN_URL", "root/"));
Computer.currentComputer().getNode().getNodeProperties().add(envNodeProp);
Jenkins.getInstance().getDescriptorList(JobProperty.class).add(new FeatureBranchProperty.DescriptorImpl());
FreeStyleProject p = createFreeStyleProject();
@@ -59,7 +61,9 @@ public void testUpStreamURLwithParams()
FeatureBranchProperty jobProp = new FeatureBranchProperty(p.getName());
FreeStyleProject p2 = createFreeStyleProject();
p2.addProperty(jobProp);
- assertEquals( "https://root/a/b/trunk",jobProp.getUpstreamURL().toDecodedString());
+ for(SVNURL svnURL : jobProp.getUpstreamURL()){
+ assertEquals( "https://root/a/b/trunk",svnURL.toDecodedString());
+ }
}
diff --git a/src/test/java/jenkins/plugins/svnmerge/MergeTest.java b/src/test/java/jenkins/plugins/svnmerge/MergeTest.java
index f387f1c..412f54c 100644
--- a/src/test/java/jenkins/plugins/svnmerge/MergeTest.java
+++ b/src/test/java/jenkins/plugins/svnmerge/MergeTest.java
@@ -122,13 +122,17 @@ public void testUpstreamMerge() throws Exception {
*/
private boolean trunkHasE() throws SVNException {
// make sure the merge went in by checking if /trunk/e exists.
- SVNRepository rep = SVNRepositoryFactory.create(upp.getUpstreamURL());
- long latest = rep.getLatestRevision();
- try {
- return latest==rep.getFile("/trunk/e", latest,new SVNProperties(), null);
- } catch (SVNException e) {
- return false;
+ boolean toReturn = false;
+ for(SVNURL url : upp.getUpstreamURL()){
+ SVNRepository rep = SVNRepositoryFactory.create(url);
+ long latest = rep.getLatestRevision();
+ try {
+ toReturn = latest==rep.getFile("/trunk/e", latest,new SVNProperties(), null);
+ } catch (SVNException e) {
+ return false;
+ }
}
+ return toReturn;
}
/**