Skip to content
Permalink
Browse files
JENKINS-24735 - Add support for build parameters in Subversion URLs.
 * When resolving the UpStream ModuleLocation in FeatureBranchProperty,
make sure we take into accout the parameter from the parent project,
Computer environment and Node environment.
 * Subversion dependenvy changed from 2.2 to 2.4.4 - we need
ModuleLocation#(Job<?,?> project) as well as ModuleLocation#(EnvVars
env) to expand consisntently the variables.
 * Added testUpStreamURLwithParams in FeatureBranchPropertyTest
  • Loading branch information
alexouzounis committed Oct 19, 2014
1 parent 990dc84 commit 9231b9191724a194e18fa5c48e9e3c28df501869
Showing with 107 additions and 62 deletions.
  1. +1 −1 pom.xml
  2. +67 −61 src/main/java/jenkins/plugins/svnmerge/FeatureBranchProperty.java
  3. +39 −0 src/test/java/jenkins/plugins/svnmerge/FeatureBranchPropertyTest.java
@@ -49,7 +49,7 @@
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>subversion</artifactId>
<version>2.2</version>
<version>2.4.4</version>
</dependency>
</dependencies>

@@ -1,11 +1,13 @@
package jenkins.plugins.svnmerge;

import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath.FileCallable;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.BuildListener;
import hudson.model.Computer;
import hudson.model.Item;
import hudson.model.JobProperty;
import hudson.model.JobPropertyDescriptor;
@@ -15,18 +17,17 @@
import hudson.scm.SCM;
import hudson.scm.SubversionEventHandlerImpl;
import hudson.scm.SubversionSCM;
import hudson.scm.SvnClientManager;
import hudson.scm.SubversionSCM.ModuleLocation;
import hudson.slaves.NodeProperty;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.util.IOException2;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;

import org.apache.commons.lang.mutable.MutableBoolean;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import org.tmatesoft.svn.core.ISVNLogEntryHandler;
import org.tmatesoft.svn.core.SVNCommitInfo;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNURL;
@@ -46,7 +47,6 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -63,9 +63,7 @@
*
* @author Kohsuke Kawaguchi
*/
public class FeatureBranchProperty extends JobProperty<AbstractProject<?,?>> implements Serializable {
private static final long serialVersionUID = -1L;

public class FeatureBranchProperty extends JobProperty<AbstractProject<?,?>> {
/**
* Upstream job name.
*/
@@ -91,16 +89,42 @@ public String getUpstream() {
return Jenkins.getInstance().getItemByFullName(upstream,AbstractProject.class);
}

public ModuleLocation getUpstreamSubversionLocation() {
AbstractProject<?,?> p = getUpstreamProject();
if(p==null) return null;
SCM scm = p.getScm();
if (scm instanceof SubversionSCM) {
SubversionSCM svn = (SubversionSCM) scm;
return svn.getLocations()[0];
}
return null;
}
public ModuleLocation getUpstreamSubversionLocation() {
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 variables
Computer c = Computer.currentComputer();
if (c != null) {
try {
// JVM vars
EnvVars cEnv = c.getEnvironment();
ml = ml.getExpandedLocation(cEnv);
// node vars
for (NodeProperty<?> nodeProp: c.getNode().getNodeProperties()){
if(nodeProp instanceof EnvironmentVariablesNodeProperty){
EnvVars nodeEnvVars = ((EnvironmentVariablesNodeProperty) nodeProp).getEnvVars();
ml = ml.getExpandedLocation(nodeEnvVars);

}
}
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Failed to get computer environment",e);
} catch (InterruptedException e) {
LOGGER.log(Level.WARNING, "Failed to get computer environment",e);

}
}
// expand project variables
ml = ml.getExpandedLocation(this.getOwner());
return ml;
}
return null;
}

/**
* Gets the {@link #getUpstreamSubversionLocation()} as {@link SVNURL}
@@ -151,18 +175,9 @@ public boolean prebuild(AbstractBuild<?, ?> build, BuildListener listener) {
* (typically this means a merge conflict.)
*/
public long rebase(final TaskListener listener, final long upstreamRev) throws IOException, InterruptedException {
final SubversionSCM svn = (SubversionSCM) getOwner().getScm();
final ISVNAuthenticationProvider provider = svn.createAuthenticationProvider(getOwner(), svn.getLocations()[0]);

final ModuleLocation upstreamLocation = 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 build.getModuleRoot().act(new FileCallable<Long>() {
final ISVNAuthenticationProvider provider = Jenkins.getInstance().getDescriptorByType(
SubversionSCM.DescriptorImpl.class).createAuthenticationProvider();
return owner.getModuleRoot().act(new FileCallable<Long>() {
public Long invoke(File mr, VirtualChannel virtualChannel) throws IOException {
try {
final PrintStream logger = listener.getLogger();
@@ -176,10 +191,8 @@ public void handleEvent(SVNEvent event, double progress) throws SVNException {
}
};

SvnClientManager svnm = SubversionSCM.createClientManager(provider);

SVNURL up = upstreamLocation == null ? null : upstreamLocation.getSVNURL();
SVNClientManager cm = svnm.getCore();
SVNURL up = getUpstreamURL();
SVNClientManager cm = SubversionSCM.createSvnClientManager(provider);
cm.setEventHandler(printHandler);

SVNWCClient wc = cm.getWCClient();
@@ -220,9 +233,7 @@ public void handleEvent(SVNEvent event, double progress) throws SVNException {
/**
* Represents the result of integration.
*/
public static class IntegrationResult implements Serializable {
private static final long serialVersionUID = -1L;

public static class IntegrationResult {
/**
* The merge commit in the upstream where the integration is made visible to the upstream.
* Or 0 if the integration was no-op and no commit was made.
@@ -262,11 +273,8 @@ public IntegrationResult(long mergeCommit, SVNRevision integrationSource) {
public IntegrationResult integrate(final TaskListener listener, final String branchURL, final long branchRev, final String commitMessage) throws IOException, InterruptedException {
final Long lastIntegrationSourceRevision = getlastIntegrationSourceRevision();

final SubversionSCM svn = (SubversionSCM) getUpstreamProject().getScm();
final ISVNAuthenticationProvider provider = svn.createAuthenticationProvider(getUpstreamProject(), svn.getLocations()[0]);

final ModuleLocation upstreamLocation = getUpstreamSubversionLocation();

final ISVNAuthenticationProvider provider = Jenkins.getInstance().getDescriptorByType(
SubversionSCM.DescriptorImpl.class).createAuthenticationProvider();
return owner.getModuleRoot().act(new FileCallable<IntegrationResult>() {
public IntegrationResult invoke(File mr, VirtualChannel virtualChannel) throws IOException {
try {
@@ -281,10 +289,8 @@ public void handleEvent(SVNEvent event, double progress) throws SVNException {
}
};

SvnClientManager svnm = SubversionSCM.createClientManager(provider);

SVNURL up = upstreamLocation == null ? null : upstreamLocation.getSVNURL();
SVNClientManager cm = svnm.getCore();
SVNURL up = getUpstreamURL();
SVNClientManager cm = SubversionSCM.createSvnClientManager(provider);
cm.setEventHandler(printHandler);

// capture the working directory state before the switch
@@ -295,23 +301,23 @@ public void handleEvent(SVNEvent event, double progress) throws SVNException {

// 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 SVNException eureka = new SVNException(null);
try {
cm.getLogClient().doLog(new File[]{mr},mergeRev,SVNRevision.create(lastIntegrationSourceRevision),mergeRev,true,false,-1,new ISVNLogEntryHandler() {
public void handleLogEntry(SVNLogEntry e) throws SVNException {
if (e.getMessage().startsWith(RebaseAction.COMMIT_MESSAGE_PREFIX)
|| e.getMessage().startsWith(IntegrateAction.COMMIT_MESSAGE_PREFIX))
return; // merge commits
throw eureka;
}
}
});
// 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
logger.println("No changes to be integrated. Skipping integration.");
return new IntegrationResult(0,mergeRev);
} catch (SVNException e) {
if (e!=eureka)
throw e; // some other problems
// found some changes, keep on integrating
}
}

@@ -1,7 +1,27 @@
package jenkins.plugins.svnmerge;

import jenkins.model.Jenkins;

import org.apache.commons.collections.iterators.EntrySetMapIterator;
import org.jvnet.hudson.test.Bug;
import org.jvnet.hudson.test.HudsonTestCase;

import hudson.EnvVars;
import hudson.model.FreeStyleBuild;
import hudson.model.JobProperty;
import hudson.model.Cause;
import hudson.model.Computer;
import hudson.model.FreeStyleProject;
import hudson.model.Hudson;
import hudson.model.ParameterDefinition;
import hudson.model.ParametersAction;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.StringParameterDefinition;
import hudson.model.StringParameterValue;
import hudson.scm.SubversionSCM;
import hudson.slaves.NodeProperty;
import hudson.slaves.EnvironmentVariablesNodeProperty;

import com.gargoylesoftware.htmlunit.html.HtmlPage;

/**
@@ -24,4 +44,23 @@ public void testConfigRoundtrip2() throws Exception {
assertNotNull(ujp);
assertEquals("xyz",ujp.getUpstream());
}

@Bug(24735)
public void testUpStreamURLwithParams()
throws Exception {
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();
p.setScm(new SubversionSCM("https://${ROOT_SVN_URL}${REPO}/${PROJECT}/trunk"));
ParameterDefinition def1 = new StringParameterDefinition("REPO", "a");
ParameterDefinition def2 = new StringParameterDefinition("PROJECT", "b");
p.addProperty(new ParametersDefinitionProperty(def1,def2));
FeatureBranchProperty jobProp = new FeatureBranchProperty(p.getName());
p.addProperty(jobProp);
assertEquals( "https://root/a/b/trunk",jobProp.getUpstreamURL().toDecodedString());

}


}

0 comments on commit 9231b91

Please sign in to comment.