Skip to content
Permalink
Browse files

[JENKINS-48061] Retrieve other refs

  • Loading branch information...
rsandell committed Apr 13, 2018
1 parent 75177c4 commit f67a66ec0900c83d6785955d32de32b1f17f4724
@@ -440,6 +440,7 @@ protected void retrieve(@CheckForNull SCMSourceCriteria criteria,
if (context.wantTags()) {
referenceTypes.add(GitSCMTelescope.ReferenceType.TAG);
}
//TODO DiscoverOtherRefsTrait?
if (!referenceTypes.isEmpty()) {
try (GitSCMSourceRequest request = context.newRequest(AbstractGitSCMSource.this, listener)) {
listener.getLogger().println("Listing remote references...");
@@ -545,10 +546,12 @@ public Void run(GitClient client, String remoteName) throws IOException, Interru
try (RevWalk walk = new RevWalk(repository);
GitSCMSourceRequest request = context.newRequest(AbstractGitSCMSource.this, listener)) {
Map<String, ObjectId> remoteReferences = null;
if (context.wantBranches() || context.wantTags()) {
if (context.wantBranches() || context.wantTags() || context.wantOtherRefs()) {
listener.getLogger().println("Listing remote references...");
remoteReferences = client.getRemoteReferences( //TODO DiscoverOtherRefsTrait
client.getRemoteUrl(remoteName), null, context.wantBranches(), context.wantTags()
boolean headsOnly = !context.wantOtherRefs() && context.wantBranches();
boolean tagsOnly = !context.wantOtherRefs() && context.wantTags();
remoteReferences = client.getRemoteReferences(
client.getRemoteUrl(remoteName), null, headsOnly, tagsOnly
);
}
if (context.wantBranches()) {
@@ -557,10 +560,84 @@ public Void run(GitClient client, String remoteName) throws IOException, Interru
if (context.wantTags()) {
discoverTags(repository, walk, request, remoteReferences);
}
if (context.wantOtherRefs()) {
discoverOtherRefs(repository, walk, request, remoteReferences,
(Collection<GitSCMSourceContext.WantedOtherRef>)context.getOtherWantedRefs());
}
}
return null;
}

private void discoverOtherRefs(final Repository repository,
final RevWalk walk, GitSCMSourceRequest request,
Map<String, ObjectId> remoteReferences,
Collection<GitSCMSourceContext.WantedOtherRef> wantedRefs)
throws IOException, InterruptedException {
listener.getLogger().println("Checking other refs...");
walk.setRetainBody(false);
int count = 0;
for (final Map.Entry<String, ObjectId> ref : remoteReferences.entrySet()) {
if (ref.getKey().startsWith(Constants.R_HEADS) || ref.getKey().startsWith(Constants.R_TAGS)) {
continue;
}
for (GitSCMSourceContext.WantedOtherRef otherRef : wantedRefs) {
if (!otherRef.matches(ref.getKey())) {
continue;
}
final String refName = otherRef.getName(ref.getKey());
if (refName == null) {
listener.getLogger().println(" Possible badly configured name mapping (" + otherRef.getName() + ") (for " + ref.getKey() + ") ignoring.");
continue;
}
count++;
if (request.process(new GitRefSCMHead(refName, ref.getKey()),
new SCMSourceRequest.IntermediateLambda<ObjectId>() {
@Nullable
@Override
public ObjectId create() throws IOException, InterruptedException {
listener.getLogger().println(" Checking ref " + refName + " (" + ref.getKey() + ")");
return ref.getValue();
}
},
new SCMSourceRequest.ProbeLambda<GitRefSCMHead, ObjectId>() {
@NonNull
@Override
public SCMSourceCriteria.Probe create(@NonNull GitRefSCMHead head,
@Nullable ObjectId revisionInfo)
throws IOException, InterruptedException {
RevCommit commit = walk.parseCommit(revisionInfo);
final long lastModified = TimeUnit.SECONDS.toMillis(commit.getCommitTime());
final RevTree tree = commit.getTree();
return new TreeWalkingSCMProbe(refName, lastModified, repository, tree);
}
}, new SCMSourceRequest.LazyRevisionLambda<GitRefSCMHead, SCMRevision, ObjectId>() {
@NonNull
@Override
public SCMRevision create(@NonNull GitRefSCMHead head, @Nullable ObjectId intermediate)
throws IOException, InterruptedException {
return new GitRefSCMRevision(head, ref.getValue().name());
}
}, new SCMSourceRequest.Witness() {
@Override
public void record(@NonNull SCMHead head, SCMRevision revision, boolean isMatch) {
if (isMatch) {
listener.getLogger().println(" Met criteria");
} else {
listener.getLogger().println(" Does not meet criteria");
}
}
}
)) {
listener.getLogger().format("Processed %d refs (query complete)%n", count);
return;
}
break;
}
}
listener.getLogger().format("Processed %d refs%n", count);

}

private void discoverBranches(final Repository repository,
final RevWalk walk, GitSCMSourceRequest request,
Map<String, ObjectId> remoteReferences)
@@ -317,6 +317,9 @@ public final C withRemoteName(String remoteName) {
@NonNull
public final List<RefSpec> asRefSpecs() {
List<RefSpec> result = new ArrayList<>(Math.max(refSpecs.size(), 1));
if (wantOtherRefs() && wantBranches()) {
result.add(new RefSpec("+" + Constants.R_HEADS + "*:" + Constants.R_REMOTES + remoteName() + "/*"));
}
for (String template : refSpecs()) {
result.add(new RefSpec(
template.replaceAll(AbstractGitSCMSource.REF_SPEC_REMOTE_NAME_PLACEHOLDER, remoteName())
@@ -388,7 +391,7 @@ public int compareTo(WantedOtherRef o) {
public boolean matches(String revision, String remoteName, String remoteRev) {
final Matcher matcher = refAsPattern().matcher(remoteName);
if (matcher.matches()) {
//TODO support multiple capture groups
//TODO support multiple capture groups?
if (matcher.groupCount() > 0) { //Group 0 apparently not in this count according to javadoc
String resolvedName = name.replace("@{1}", matcher.group(1));
return resolvedName.equals(revision);
@@ -398,6 +401,23 @@ public boolean matches(String revision, String remoteName, String remoteRev) {
}
return false;
}

public boolean matches(String remoteName) {
final Matcher matcher = refAsPattern().matcher(remoteName);
return matcher.matches();
}

public String getName(String remoteName) {
final Matcher matcher = refAsPattern().matcher(remoteName);
if (matcher.matches()) {
if (matcher.groupCount() > 0) { //Group 0 apparently not in this count according to javadoc
return name.replace("@{1}", matcher.group(1));
} else if (!name.contains("@{1}")) {
return name;
}
}
return null;
}
}

}
@@ -23,6 +23,7 @@
*/
package jenkins.plugins.git.traits;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import jenkins.plugins.git.GitSCMBuilder;
import jenkins.plugins.git.GitSCMSource;
@@ -121,6 +122,7 @@ protected void decorateContext(SCMSourceContext<?, ?> context) {
* {@inheritDoc}
*/
@Override
@NonNull
public String getDisplayName() {
return Messages.DiscoverOtherRefsTrait_displayName();
}
@@ -1,5 +1,6 @@
package jenkins.plugins.git;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.Action;
@@ -15,6 +16,7 @@
import hudson.plugins.git.extensions.impl.LocalBranch;
import hudson.util.StreamTaskListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -29,10 +31,12 @@
import jenkins.plugins.git.traits.RefSpecsSCMSourceTrait;
import jenkins.plugins.git.traits.TagDiscoveryTrait;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMHeadObserver;
import jenkins.scm.api.SCMRevision;
import jenkins.scm.api.SCMSource;
import static org.hamcrest.Matchers.*;

import jenkins.scm.api.SCMSourceCriteria;
import jenkins.scm.api.SCMSourceOwner;
import jenkins.scm.api.metadata.PrimaryInstanceMetadataAction;
import jenkins.scm.api.trait.SCMSourceTrait;
@@ -621,6 +625,46 @@ private String fileAt(String revision, Run<?,?> run, SCMSource source, TaskListe
}
}

@Issue("JENKINS-48061")
@Test
public void fetchOtherRef() throws Exception {
sampleRepo.init();
sampleRepo.write("file", "v1");
sampleRepo.git("commit", "--all", "--message=v1");
sampleRepo.git("tag", "v1");
String v1 = sampleRepo.head();
sampleRepo.write("file", "v2");
sampleRepo.git("commit", "--all", "--message=v2"); // master
sampleRepo.git("checkout", "-b", "dev");
sampleRepo.write("file", "v3");
sampleRepo.git("commit", "--all", "--message=v3"); // dev
String v3 = sampleRepo.head();
sampleRepo.git("update-ref", "refs/custom/1", v3);
sampleRepo.git("reset", "--hard", "HEAD^"); // dev
sampleRepo.write("file", "v4");
sampleRepo.git("commit", "--all", "--message=v4"); // dev
// SCM.checkout does not permit a null build argument, unfortunately.
Run<?,?> run = r.buildAndAssertSuccess(r.createFreeStyleProject());
GitSCMSource source = new GitSCMSource(sampleRepo.toString());
source.setTraits(Arrays.asList(new BranchDiscoveryTrait(), new TagDiscoveryTrait(), new DiscoverOtherRefsTrait("custom/*")));
StreamTaskListener listener = StreamTaskListener.fromStderr();

final SCMHeadObserver.Collector collector =
source.fetch(new SCMSourceCriteria() {
@Override
public boolean isHead(@NonNull Probe probe, @NonNull TaskListener listener) throws IOException {
return true;
}
}, new SCMHeadObserver.Collector(), listener);

final Map<SCMHead, SCMRevision> result = collector.result();
assertThat(result.entrySet(), hasSize(4));
assertThat(result, hasKey(allOf(
instanceOf(GitRefSCMHead.class),
hasProperty("name", equalTo("custom-1"))
)));
}

@Issue("JENKINS-37727")
@Test
public void pruneRemovesDeletedBranches() throws Exception {

0 comments on commit f67a66e

Please sign in to comment.
You can’t perform that action at this time.