Browse Source

Add setContains to ListBranchCommand (branch --contains)

To correspond to the behavior of "git branch", also return HEAD in case
it is detached.

Bug: 425678
Change-Id: Ie615731434d70b99bd18c7a02e832c0a2c3ceef3
Signed-off-by: Robin Stocker <robin@nibor.org>
stable-3.4
Robin Stocker 11 years ago
parent
commit
c096b42e3e
  1. 14
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java
  2. 78
      org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java

14
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java

@ -196,6 +196,20 @@ public class BranchCommandTest extends RepositoryTestCase {
git.branchList().setListMode(ListMode.ALL).call();
}
@Test
public void testListBranchesWithContains() throws Exception {
git.branchCreate().setName("foo").setStartPoint(secondCommit).call();
List<Ref> refs = git.branchList().call();
assertEquals(2, refs.size());
List<Ref> refsContainingSecond = git.branchList()
.setContains(secondCommit.name()).call();
assertEquals(1, refsContainingSecond.size());
// master is on initial commit, so it should not be returned
assertEquals("refs/heads/foo", refsContainingSecond.get(0).getName());
}
@Test
public void testCreateFromCommit() throws Exception {
Ref branch = git.branchCreate().setName("FromInitial").setStartPoint(

78
org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java

@ -1,6 +1,7 @@
/*
* Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
* Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
* Copyright (C) 2014, Robin Stocker <robin@nibor.org>
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@ -44,21 +45,30 @@
package org.eclipse.jgit.api;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.RevWalkUtils;
/**
* Used to obtain a list of branches.
* <p>
* In case HEAD is detached (it points directly to a commit), it is also
* returned in the results.
*
* @see <a
* href="http://www.kernel.org/pub/software/scm/git/docs/git-branch.html"
@ -67,6 +77,8 @@ import org.eclipse.jgit.lib.Repository;
public class ListBranchCommand extends GitCommand<List<Ref>> {
private ListMode listMode;
private String containsCommitish;
/**
* The modes available for listing branches (corresponding to the -r and -a
* options)
@ -91,23 +103,28 @@ public class ListBranchCommand extends GitCommand<List<Ref>> {
public List<Ref> call() throws GitAPIException {
checkCallable();
Map<String, Ref> refList;
List<Ref> resultRefs;
try {
Collection<Ref> refs = new ArrayList<Ref>();
// Also return HEAD if it's detached
Ref head = repo.getRef(Constants.HEAD);
if (head != null && head.getLeaf().getName().equals(Constants.HEAD))
refs.add(head);
if (listMode == null) {
refList = repo.getRefDatabase().getRefs(Constants.R_HEADS);
refs.addAll(getRefs(Constants.R_HEADS));
} else if (listMode == ListMode.REMOTE) {
refList = repo.getRefDatabase().getRefs(Constants.R_REMOTES);
refs.addAll(getRefs(Constants.R_REMOTES));
} else {
refList = new HashMap<String,Ref>(repo.getRefDatabase().getRefs(
Constants.R_HEADS));
refList.putAll(repo.getRefDatabase().getRefs(
Constants.R_REMOTES));
refs.addAll(getRefs(Constants.R_HEADS));
refs.addAll(getRefs(Constants.R_REMOTES));
}
resultRefs = new ArrayList<Ref>(filterRefs(refs));
} catch (IOException e) {
throw new JGitInternalException(e.getMessage(), e);
}
List<Ref> resultRefs = new ArrayList<Ref>();
resultRefs.addAll(refList.values());
Collections.sort(resultRefs, new Comparator<Ref>() {
public int compare(Ref o1, Ref o2) {
return o1.getName().compareTo(o2.getName());
@ -117,6 +134,26 @@ public class ListBranchCommand extends GitCommand<List<Ref>> {
return resultRefs;
}
private Collection<Ref> filterRefs(Collection<Ref> refs)
throws RefNotFoundException, IOException {
if (containsCommitish == null)
return refs;
RevWalk walk = new RevWalk(repo);
try {
ObjectId resolved = repo.resolve(containsCommitish);
if (resolved == null)
throw new RefNotFoundException(MessageFormat.format(
JGitText.get().refNotResolved, containsCommitish));
RevCommit containsCommit = walk.parseCommit(resolved);
return RevWalkUtils.findBranchesReachableFrom(containsCommit, walk,
refs);
} finally {
walk.release();
}
}
/**
* @param listMode
* optional: corresponds to the -r/-a options; by default, only
@ -128,4 +165,23 @@ public class ListBranchCommand extends GitCommand<List<Ref>> {
this.listMode = listMode;
return this;
}
/**
* If this is set, only the branches that contain the specified commit-ish
* as an ancestor are returned.
*
* @param containsCommitish
* a commit ID or ref name
* @return this instance
* @since 3.3
*/
public ListBranchCommand setContains(String containsCommitish) {
checkCallable();
this.containsCommitish = containsCommitish;
return this;
}
private Collection<Ref> getRefs(String prefix) throws IOException {
return repo.getRefDatabase().getRefs(prefix).values();
}
}

Loading…
Cancel
Save