diff --git a/pom.xml b/pom.xml
index 8958f8d1e5..cc7a26754c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -112,6 +112,7 @@
org.jenkins-ci.plugins
scm-api
+ ${scm-api-plugin.version}
org.jenkins-ci.plugins
diff --git a/src/main/java/hudson/plugins/git/util/GitUtils.java b/src/main/java/hudson/plugins/git/util/GitUtils.java
index 1f016b1562..9cb55bc6ab 100644
--- a/src/main/java/hudson/plugins/git/util/GitUtils.java
+++ b/src/main/java/hudson/plugins/git/util/GitUtils.java
@@ -410,6 +410,10 @@ public static String[] fixupNames(String[] names, String[] urls) {
return returnNames;
}
+ public static String expand(String str, EnvVars env) {
+ return env == null ? str : env.expand(str);
+ }
+
private static final Logger LOGGER = Logger.getLogger(GitUtils.class.getName());
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/jenkins/plugins/git/GitSCMFileSystem.java b/src/main/java/jenkins/plugins/git/GitSCMFileSystem.java
index 6e7847d271..063a00dfd7 100644
--- a/src/main/java/jenkins/plugins/git/GitSCMFileSystem.java
+++ b/src/main/java/jenkins/plugins/git/GitSCMFileSystem.java
@@ -34,6 +34,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.EnvVars;
import hudson.Extension;
+import hudson.model.Run;
import hudson.model.Item;
import hudson.model.TaskListener;
import hudson.plugins.git.BranchSpec;
@@ -53,6 +54,7 @@
import java.io.Writer;
import java.net.URISyntaxException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@@ -76,6 +78,8 @@
import org.jenkinsci.plugins.gitclient.Git;
import org.jenkinsci.plugins.gitclient.GitClient;
+import static hudson.plugins.git.util.GitUtils.expand;
+
/**
* Base implementation of {@link SCMFileSystem}.
*
@@ -286,6 +290,18 @@ public boolean supportsDescriptor(SCMSourceDescriptor descriptor) {
@Override
public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull SCMRevision rev)
throws IOException, InterruptedException {
+ return getScmFileSystem(scm, rev, owner, null);
+ }
+
+ @Override
+ public SCMFileSystem build(@NonNull Run, ?> build, @NonNull SCM scm, SCMRevision rev)
+ throws IOException, InterruptedException {
+ Item owner = build.getParent();
+ return getScmFileSystem(scm, rev, owner, build);
+ }
+
+ private SCMFileSystem getScmFileSystem(@NonNull SCM scm,
+ SCMRevision rev, Item owner, @CheckForNull Run, ?> build) throws IOException, InterruptedException {
if (rev != null && !(rev instanceof AbstractGitSCMSource.SCMRevisionImpl)) {
return null;
}
@@ -293,14 +309,16 @@ public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull
return null; // Spotbugs warns about unchecked cast without this check
}
GitSCM gitSCM = (GitSCM) scm;
+ TaskListener listener = new LogTaskListener(LOGGER, Level.FINE);
UserRemoteConfig config = gitSCM.getUserRemoteConfigs().get(0);
BranchSpec branchSpec = gitSCM.getBranches().get(0);
- String remote = config.getUrl();
- TaskListener listener = new LogTaskListener(LOGGER, Level.FINE);
+ EnvVars env = build == null ? null : build.getEnvironment(listener);
+ String remote = expand(config.getUrl(), env);
if (remote == null) {
listener.getLogger().println("Git remote url is null");
return null;
}
+ remote = remote.trim();
String cacheEntry = AbstractGitSCMSource.getCacheEntry(remote);
Lock cacheLock = AbstractGitSCMSource.getCacheLock(cacheEntry);
cacheLock.lock();
@@ -334,7 +352,7 @@ public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull
listener.getLogger().println("Creating git repository in " + cacheDir);
client.init();
}
- String remoteName = StringUtils.defaultIfBlank(config.getName(), Constants.DEFAULT_REMOTE_NAME);
+ String remoteName = StringUtils.defaultIfBlank(expand(config.getName(), env), Constants.DEFAULT_REMOTE_NAME).trim();
listener.getLogger().println("Setting " + remoteName + " to " + remote);
client.setRemoteUrl(remoteName, remote);
listener.getLogger().println("Fetching & pruning " + remoteName + "...");
@@ -344,28 +362,37 @@ public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull
} catch (URISyntaxException ex) {
listener.getLogger().println("URI syntax exception for '" + remoteName + "' " + ex);
}
- String prefix = Constants.R_HEADS;
+ String prefix = Constants.R_HEADS;
if(branchSpec.getName().startsWith(Constants.R_TAGS)){
- prefix = Constants.R_TAGS;
+ prefix = Constants.R_TAGS;
}
String headName;
if (rev != null) {
headName = rev.getHead().getName();
} else {
if (branchSpec.getName().startsWith(prefix)){
- headName = branchSpec.getName().substring(prefix.length());
+ headName = branchSpec.getName().substring(prefix.length());
} else if (branchSpec.getName().startsWith("*/")) {
headName = branchSpec.getName().substring(2);
} else {
headName = branchSpec.getName();
}
}
- client.fetch_().prune(true).from(remoteURI, Arrays
- .asList(new RefSpec(
- "+" + prefix + headName + ":" + Constants.R_REMOTES + remoteName + "/"
- + headName))).execute();
+ headName = expand(headName, env).trim();
+
+ String refspec = expand(config.getRefspec(), env);
+ String head = headName;
+ if (refspec == null) {
+ refspec = "+" + Constants.R_HEADS + headName + ":" + Constants.R_REMOTES + remoteName + "/" + headName;
+ head = Constants.R_REMOTES + remoteName + "/" +headName;
+ }
+ else {
+ refspec = refspec.trim();
+ }
+ client.fetch_().prune(true).from(remoteURI,
+ Collections.singletonList(new RefSpec(refspec))).execute();
listener.getLogger().println("Done.");
- return new GitSCMFileSystem(client, remote, Constants.R_REMOTES + remoteName + "/" +headName, (AbstractGitSCMSource.SCMRevisionImpl) rev);
+ return new GitSCMFileSystem(client, remote, head, (AbstractGitSCMSource.SCMRevisionImpl) rev);
} finally {
cacheLock.unlock();
}
diff --git a/src/main/java/jenkins/plugins/git/GitSCMTelescope.java b/src/main/java/jenkins/plugins/git/GitSCMTelescope.java
index 4e762dfd97..375422012e 100644
--- a/src/main/java/jenkins/plugins/git/GitSCMTelescope.java
+++ b/src/main/java/jenkins/plugins/git/GitSCMTelescope.java
@@ -32,9 +32,12 @@
import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
+import hudson.EnvVars;
import hudson.ExtensionList;
import hudson.model.Item;
import hudson.model.Queue;
+import hudson.model.Run;
+import hudson.model.TaskListener;
import hudson.model.queue.Tasks;
import hudson.plugins.git.BranchSpec;
import hudson.plugins.git.GitSCM;
@@ -54,6 +57,8 @@
import org.eclipse.jgit.lib.Constants;
import org.jenkinsci.plugins.gitclient.GitClient;
+import static hudson.plugins.git.util.GitUtils.expand;
+
/**
* An implementation of this extension point allows {@link AbstractGitSCMSource} to examine a repository from a distance
* without requiring a local checkout.
@@ -181,14 +186,27 @@ public final SCMFileSystem build(@NonNull SCMSource source, @NonNull SCMHead hea
@Override
public final SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, SCMRevision rev)
throws IOException, InterruptedException {
+ return build(scm, rev, owner, null);
+ }
+
+ @Override
+ public SCMFileSystem build(@NonNull Run, ?> build, @NonNull SCM scm, SCMRevision rev)
+ throws IOException, InterruptedException {
+ Item owner = build.getParent();
+ return build(scm, rev, owner, build);
+ }
+
+ private SCMFileSystem build(@NonNull SCM scm, SCMRevision rev, Item owner, @CheckForNull Run, ?> build)
+ throws IOException, InterruptedException {
if (scm instanceof GitSCM) {
// we only support the GitSCM if the branch is completely unambiguous
GitSCM git = (GitSCM) scm;
List configs = git.getUserRemoteConfigs();
List branches = git.getBranches();
+ EnvVars env = build == null ? null : build.getEnvironment(TaskListener.NULL);
if (configs.size() == 1) {
UserRemoteConfig config = configs.get(0);
- String remote = config.getUrl();
+ String remote = expand(config.getUrl(), env);
if (remote != null && supports(remote)
&& branches.size() == 1 && !branches.get(0).getName().contains("*")) {
StandardCredentials credentials;
@@ -210,7 +228,7 @@ public final SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, SCMRevis
validate(remote, credentials);
SCMHead head;
if (rev == null) {
- String name = branches.get(0).getName();
+ String name = expand(branches.get(0).getName(), env);
if (name.startsWith(Constants.R_TAGS)) {
head = new GitTagSCMHead(
name.substring(Constants.R_TAGS.length()),
@@ -219,8 +237,10 @@ public final SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, SCMRevis
} else if (name.startsWith(Constants.R_HEADS)) {
head = new GitBranchSCMHead(name.substring(Constants.R_HEADS.length()));
} else {
- if (name.startsWith(config.getName() + "/")) {
- head = new GitBranchSCMHead(name.substring(config.getName().length() + 1));
+ String remoteName = expand(config.getName(), env);
+ if (name.startsWith(remoteName + "/")) {
+ head = new GitBranchSCMHead(name.substring(
+ remoteName.length() + 1));
} else {
head = new GitBranchSCMHead(name);
}