Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 31 additions & 15 deletions src/main/java/hudson/scm/SubversionSCM.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,10 @@
import hudson.Launcher;
import hudson.Util;
import hudson.init.InitMilestone;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.model.ModelObject;
import hudson.model.TaskListener;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Hudson;
import hudson.model.*;

import java.io.ByteArrayOutputStream;
import java.net.URLClassLoader;
import java.nio.charset.UnsupportedCharsetException;
import java.security.KeyStore;
import java.security.KeyStoreException;
Expand All @@ -90,8 +83,6 @@
import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;
import jenkins.model.Jenkins.MasterComputer;
import hudson.model.ParametersAction;
import hudson.model.Run;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.VirtualChannel;
Expand Down Expand Up @@ -194,7 +185,6 @@
import com.trilead.ssh2.DebugLogger;
import com.trilead.ssh2.SCPClient;
import com.trilead.ssh2.crypto.Base64;
import hudson.model.Job;

/**
* Subversion SCM.
Expand Down Expand Up @@ -1402,7 +1392,7 @@ else if (project.getLastBuild()!=null) {
for (ModuleLocation loc: getLocations()) {
String url;
try {
url = loc.getSVNURL().toDecodedString();
url = loc.getExpandedLocation(project).getSVNURL().toDecodedString();
} catch (SVNException ex) {
ex.printStackTrace(listener.error(Messages.SubversionSCM_pollChanges_exception(loc.getURL())));
return BUILD_NOW;
Expand Down Expand Up @@ -2907,6 +2897,32 @@ public static List<ModuleLocation> parse(String[] remoteLocations, String[] cred
return modules;
}

/**
* If a subversion remote uses $VAR or ${VAR} as a parameterized build,
* we expand the url. This will expand using the DEFAULT item. If there
* is a choice parameter, it will expand with the FIRST item.
*/
public ModuleLocation getExpandedLocation(Job<?, ?> project) {
String url = this.getURL();
String returnURL = url;
for (JobProperty property : project.getProperties().values()) {
if (property instanceof ParametersDefinitionProperty) {
ParametersDefinitionProperty pdp = (ParametersDefinitionProperty) property;
for (String propertyName : pdp.getParameterDefinitionNames()) {
if (url.contains(propertyName)) {
ParameterDefinition pd = pdp.getParameterDefinition(propertyName);
String replacement = String.valueOf(pd.getDefaultParameterValue().createVariableResolver(null).resolve(propertyName));
returnURL = returnURL.replace("${" + propertyName + "}", replacement);
returnURL = returnURL.replace("$" + propertyName, replacement);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sure there is a utility in Jenkins core to do macro expansion which you should be using.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@christ66 could probably do that... but IIRC the correct utility is actually in a plugin because there are multiple ways to expand tokens or something... anywho I'll leave it up to @christ66 how he wants to respond

}
}
}
}

return new ModuleLocation(returnURL, credentialsId, getLocalDir(), getDepthOption(),
isIgnoreExternalsOption());
}

@Extension
public static class DescriptorImpl extends Descriptor<ModuleLocation> {

Expand Down Expand Up @@ -3082,12 +3098,12 @@ public FormValidation doCheckLocal(@QueryParameter String value) throws IOExcept
/**
* Property to control whether SCM polling happens from the slave or master
*/
private static boolean POLL_FROM_MASTER = Boolean.getBoolean(SubversionSCM.class.getName()+".pollFromMaster");
private static boolean POLL_FROM_MASTER = Boolean.getBoolean(SubversionSCM.class.getName() + ".pollFromMaster");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid making formatting changes in PRs or really any commits. It makes diffs harder to read, git blame useless, and merges and cherry picks more likely to end in spurious merge conflicts.


/**
* If set to non-null, read configuration from this directory instead of "~/.subversion".
*/
public static String CONFIG_DIR = System.getProperty(SubversionSCM.class.getName()+".configDir");
public static String CONFIG_DIR = System.getProperty(SubversionSCM.class.getName() + ".configDir");

/**
* Enables trace logging of Ganymed SSH library.
Expand Down
157 changes: 88 additions & 69 deletions src/test/java/hudson/scm/SubversionSCMTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,83 +25,36 @@
*/
package hudson.scm;

import static hudson.scm.SubversionSCM.compareSVNAuthentications;
import static org.jvnet.hudson.test.recipes.PresetData.DataSet.ANONYMOUS_READONLY;

import com.cloudbees.plugins.credentials.Credentials;
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
import com.cloudbees.plugins.credentials.domains.Domain;
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Proc;
import hudson.model.BuildListener;
import hudson.model.FreeStyleBuild;
import hudson.model.Item;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Cause;
import hudson.model.FreeStyleProject;
import hudson.model.ParametersAction;
import hudson.model.Run;
import hudson.model.StringParameterValue;
import hudson.model.*;
import hudson.scm.ChangeLogSet.Entry;
import hudson.scm.SubversionSCM.ModuleLocation;
import hudson.scm.browsers.Sventon;
import hudson.scm.subversion.CheckoutUpdater;
import hudson.scm.subversion.UpdateUpdater;
import hudson.scm.subversion.UpdateWithCleanUpdater;
import hudson.scm.subversion.UpdateWithRevertUpdater;
import hudson.scm.subversion.WorkspaceUpdater;
import hudson.scm.subversion.*;
import hudson.slaves.DumbSlave;
import hudson.triggers.SCMTrigger;
import hudson.util.FormValidation;
import hudson.util.StreamTaskListener;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.dom4j.Document;
import org.dom4j.io.DOMReader;
import org.junit.Test;
import org.jvnet.hudson.test.Bug;
import org.jvnet.hudson.test.Email;
import org.jvnet.hudson.test.*;
import org.jvnet.hudson.test.HudsonHomeLoader.CopyExisting;
import org.jvnet.hudson.test.TestBuilder;
import org.jvnet.hudson.test.Url;
import org.jvnet.hudson.test.CaptureEnvironmentBuilder;
import org.jvnet.hudson.test.recipes.PresetData;
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNPropertyValue;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.auth.SVNAuthentication;
import org.tmatesoft.svn.core.auth.SVNPasswordAuthentication;
import org.tmatesoft.svn.core.auth.SVNSSHAuthentication;
import org.tmatesoft.svn.core.auth.SVNSSLAuthentication;
import org.tmatesoft.svn.core.auth.SVNUserNameAuthentication;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.*;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
Expand All @@ -110,18 +63,17 @@
import org.tmatesoft.svn.core.wc.SVNStatus;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.EnvVars;
import hudson.model.EnvironmentContributor;
import hudson.model.TopLevelItem;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import static hudson.scm.SubversionSCM.compareSVNAuthentications;
import static org.jvnet.hudson.test.recipes.PresetData.DataSet.ANONYMOUS_READONLY;

/**
* @author Kohsuke Kawaguchi
Expand Down Expand Up @@ -344,6 +296,73 @@ public void testRevisionParameter() throws Exception {
assertBuildStatus(Result.SUCCESS,b);
}

@Bug(22568)
public void testPollingWithDefaultParametersWithCurlyBraces() throws Exception {
FreeStyleProject p = createFreeStyleProject();

String url = "http://svn.codehaus.org/sxc/tags/sxc-0.5/sxc-core/src/test/java/com/envoisolutions/sxc/builder/";
p.setScm(new SubversionSCM("${REPO}" + url.substring(10)));
String var = url.substring(0, 10);
ParametersDefinitionProperty property = new ParametersDefinitionProperty(new StringParameterDefinition("REPO", var));
p.addProperty(property);

FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserIdCause(),
new ParametersAction(new StringParameterValue("REPO", var))).get();

assertBuildStatus(Result.SUCCESS,b);
assertTrue(b.getWorkspace().child("Node.java").exists());

// as a baseline, this shouldn't detect any change
TaskListener listener = createTaskListener();
PollingResult poll = p.poll(listener);
assertFalse("Polling shouldn't have any changes.", poll.hasChanges());
}

@Bug(22568)
public void testPollingWithDefaultParametersWithOutCurlyBraces() throws Exception {
FreeStyleProject p = createFreeStyleProject();

String url = "http://svn.codehaus.org/sxc/tags/sxc-0.5/sxc-core/src/test/java/com/envoisolutions/sxc/builder/";
p.setScm(new SubversionSCM("$REPO" + url.substring(10)));
String var = url.substring(0, 10);
ParametersDefinitionProperty property = new ParametersDefinitionProperty(new StringParameterDefinition("REPO", var));
p.addProperty(property);

FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserIdCause(),
new ParametersAction(new StringParameterValue("REPO", var))).get();

assertBuildStatus(Result.SUCCESS,b);
assertTrue(b.getWorkspace().child("Node.java").exists());

// as a baseline, this shouldn't detect any change
TaskListener listener = createTaskListener();
PollingResult poll = p.poll(listener);
assertFalse("Polling shouldn't have any changes.", poll.hasChanges());
}

@Bug(22568)
public void testPollingWithChoiceParametersWithOutCurlyBraces() throws Exception {
FreeStyleProject p = createFreeStyleProject();

String url = "http://svn.codehaus.org/sxc/tags/sxc-0.5/sxc-core/src/test/java/com/envoisolutions/sxc/builder/";
p.setScm(new SubversionSCM("${REPO}" + url.substring(10)));
String var = url.substring(0, 10);
ParametersDefinitionProperty property = new ParametersDefinitionProperty(new ChoiceParameterDefinition("REPO", new String[] {var, "test"}, ""));
p.addProperty(property);

FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserIdCause(),
new ParametersAction(new StringParameterValue("REPO", var))).get();

assertBuildStatus(Result.SUCCESS,b);
assertTrue(b.getWorkspace().child("Node.java").exists());

// as a baseline, this shouldn't detect any change
TaskListener listener = createTaskListener();
PollingResult poll = p.poll(listener);
assertFalse("Polling shouldn't have any changes.", poll.hasChanges());
}


public void testRevisionParameterFolding() throws Exception {
FreeStyleProject p = createFreeStyleProject();
String url = "https://svn.jenkins-ci.org/trunk/hudson/test-projects/trivial-ant";
Expand Down