diff --git a/pom.xml b/pom.xml index bc343cd3b6..aeccd65645 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,7 @@ false true false + 2.6.4-SNAPSHOT 1.36 1.7.26 @@ -116,6 +117,7 @@ org.jenkins-ci.plugins scm-api + ${scm-api-plugin.version} org.jenkins-ci.plugins diff --git a/src/main/java/jenkins/plugins/git/GitSCMFileSystem.java b/src/main/java/jenkins/plugins/git/GitSCMFileSystem.java index 893587bcaf..c6730644af 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; @@ -281,6 +282,94 @@ public boolean supportsDescriptor(SCMSourceDescriptor descriptor) { return AbstractGitSCMSource.class.isAssignableFrom(descriptor.clazz); } + @Override + public SCMFileSystem build(@NonNull Run build, @NonNull SCM scm, @CheckForNull SCMRevision rev) + throws IOException, InterruptedException { + if (rev != null && !(rev instanceof AbstractGitSCMSource.SCMRevisionImpl)) { + return null; + } + Item owner = build.getParent(); + TaskListener listener = new LogTaskListener(LOGGER, Level.FINE); + GitSCM gitSCM = (GitSCM) scm; + UserRemoteConfig config = gitSCM.getUserRemoteConfigs().get(0); + BranchSpec branchSpec = gitSCM.getBranches().get(0); + EnvVars environment = build.getEnvironment(listener); + String remote = environment.expand(config.getUrl()).trim(); + String cacheEntry = AbstractGitSCMSource.getCacheEntry(remote); + Lock cacheLock = AbstractGitSCMSource.getCacheLock(cacheEntry); + cacheLock.lock(); + try { + File cacheDir = AbstractGitSCMSource.getCacheDir(cacheEntry); + Git git = Git.with(listener, environment).in(cacheDir); + GitTool tool = gitSCM.resolveGitTool(listener); + if (tool != null) { + git.using(tool.getGitExe()); + } + GitClient client = git.getClient(); + String credentialsId = config.getCredentialsId(); + if (credentialsId != null) { + StandardCredentials credential = CredentialsMatchers.firstOrNull( + CredentialsProvider.lookupCredentials( + StandardUsernameCredentials.class, + owner, + ACL.SYSTEM, + URIRequirementBuilder.fromUri(remote).build() + ), + CredentialsMatchers.allOf( + CredentialsMatchers.withId(credentialsId), + GitClient.CREDENTIALS_MATCHER + ) + ); + client.addDefaultCredentials(credential); + CredentialsProvider.track(owner, credential); + } + + if (!client.hasGitRepo()) { + listener.getLogger().println("Creating git repository in " + cacheDir); + client.init(); + } + String remoteName = StringUtils.defaultIfBlank(environment.expand(config.getName()).trim(), Constants.DEFAULT_REMOTE_NAME); + listener.getLogger().println("Setting " + remoteName + " to " + remote); + client.setRemoteUrl(remoteName, remote); + listener.getLogger().println("Fetching & pruning " + remoteName + "..."); + URIish remoteURI = null; + try { + remoteURI = new URIish(remoteName); + } catch (URISyntaxException ex) { + listener.getLogger().println("URI syntax exception for '" + remoteName + "' " + ex); + } + String headName; + if (rev != null) { + headName = environment.expand(rev.getHead().getName()).trim(); + } else { + String branch = environment.expand(branchSpec.getName()).trim(); + if (branch.startsWith(Constants.R_HEADS)) { + headName = branch.substring(Constants.R_HEADS.length()); + } else if (branch.startsWith("*/")) { + headName = branch.substring(2); + } else { + headName = branch; + } + } + + String refspec = environment.expand(config.getRefspec()); + 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().from(remoteURI, Arrays + .asList(new RefSpec (refspec))).execute(); + listener.getLogger().println("Done."); + return new GitSCMFileSystem(client, remote, head, (AbstractGitSCMSource.SCMRevisionImpl) rev); + } finally { + cacheLock.unlock(); + } + } + @Override public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull SCMRevision rev) throws IOException, InterruptedException { diff --git a/src/main/java/jenkins/plugins/git/GitSCMTelescope.java b/src/main/java/jenkins/plugins/git/GitSCMTelescope.java index 4e762dfd97..5e95996d8f 100644 --- a/src/main/java/jenkins/plugins/git/GitSCMTelescope.java +++ b/src/main/java/jenkins/plugins/git/GitSCMTelescope.java @@ -35,6 +35,7 @@ import hudson.ExtensionList; import hudson.model.Item; import hudson.model.Queue; +import hudson.model.Run; import hudson.model.queue.Tasks; import hudson.plugins.git.BranchSpec; import hudson.plugins.git.GitSCM; @@ -235,6 +236,12 @@ public final SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, SCMRevis return null; } + @Override + public final SCMFileSystem build(@NonNull Run build, @NonNull SCM scm, @CheckForNull SCMRevision rev) + throws IOException, InterruptedException { + return null; + } + /** * Given a {@link SCM} this should try to build a corresponding {@link SCMFileSystem} instance that * reflects the content at the specified {@link SCMRevision}. If the {@link SCM} is supported but not