diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/TagCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/TagCommandTest.java index 99034174b..c3f72135d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/TagCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/TagCommandTest.java @@ -17,13 +17,16 @@ import static org.junit.Assert.fail; import java.io.IOException; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidTagNameException; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.api.errors.RefAlreadyExistsException; import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.Repository; @@ -286,4 +289,45 @@ public void testListAllTagsInRepositoryInOrder() throws Exception { } } + @Test + public void testListTagsContainingCommit() throws Exception { + /* c3 + * | + * v2 - c2 b2 - v1 + * | | + * c1 b1 + * \ / + * a + */ + try (TestRepository r = new TestRepository<>( + db)) { + Git git = Git.wrap(db); + RevCommit a = r.commit().create(); + RevCommit b1 = r.commit(a); + RevCommit b2 = r.commit(b1); + RevCommit c1 = r.commit(a); + RevCommit c2 = r.commit(c1); + RevCommit c3 = r.commit(c2); + r.update("refs/tags/v1", r.tag("v1", b2)); + r.update("refs/tags/v2", r.tag("v1.1", c2)); + List res = git.tagList().setContains(a).call(); + assertEquals(2, res.size()); + assertTrue(res.stream().map(Ref::getName) + .collect(Collectors.toSet()).containsAll( + Arrays.asList("refs/tags/v1", "refs/tags/v2"))); + + res = git.tagList().setContains(b1).call(); + assertEquals(1, res.size()); + assertTrue(res.stream().map(Ref::getName) + .collect(Collectors.toSet()).contains("refs/tags/v1")); + + res = git.tagList().setContains(c1).call(); + assertEquals(1, res.size()); + assertTrue(res.stream().map(Ref::getName) + .collect(Collectors.toSet()).contains("refs/tags/v2")); + + res = git.tagList().setContains(c3).call(); + assertEquals(0, res.size()); + } + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java index d7b34ab7f..27a528842 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java @@ -16,9 +16,13 @@ import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.errors.IncorrectObjectTypeException; +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; /** @@ -29,6 +33,9 @@ */ public class ListTagCommand extends GitCommand> { + private final RevWalk rw; + private RevCommit commit; + /** * Constructor for ListTagCommand. * @@ -37,21 +44,49 @@ public class ListTagCommand extends GitCommand> { */ protected ListTagCommand(Repository repo) { super(repo); + rw = new RevWalk(repo); + } + + /** + * Only list tags which contain the specified commit. + * + * @param commit + * the specified commit + * @return this command + * @throws IOException + * @throws IncorrectObjectTypeException + * @throws MissingObjectException + * + * @since 6.6 + */ + public ListTagCommand setContains(AnyObjectId commit) + throws MissingObjectException, IncorrectObjectTypeException, + IOException { + checkCallable(); + this.commit = rw.parseCommit(commit); + return this; } /** {@inheritDoc} */ @Override public List call() throws GitAPIException { checkCallable(); - List tags = new ArrayList<>(); - try (RevWalk revWalk = new RevWalk(repo)) { + List tags; + try { List refList = repo.getRefDatabase() .getRefsByPrefix(Constants.R_TAGS); - for (Ref ref : refList) { - tags.add(ref); + if (commit != null) { + // if body is retained #getMergedInto needs to access data not + // available in commit graph which is slower + rw.setRetainBody(false); + tags = rw.getMergedInto(commit, refList); + } else { + tags = new ArrayList<>(refList); } } catch (IOException e) { throw new JGitInternalException(e.getMessage(), e); + } finally { + rw.close(); } Collections.sort(tags, (Ref o1, Ref o2) -> o1.getName().compareTo(o2.getName()));