ListTagCommand: implement git tag --contains

Change-Id: I07e57ba098eace9656393837fad4cb3590f31b22
This commit is contained in:
Matthias Sohn 2023-04-09 20:51:15 +02:00
parent 5cc9ecde8f
commit 060dcf1cca
2 changed files with 83 additions and 4 deletions

View File

@ -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<Repository> 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<Ref> 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());
}
}
}

View File

@ -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<List<Ref>> {
private final RevWalk rw;
private RevCommit commit;
/**
* Constructor for ListTagCommand.
*
@ -37,21 +44,49 @@ public class ListTagCommand extends GitCommand<List<Ref>> {
*/
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<Ref> call() throws GitAPIException {
checkCallable();
List<Ref> tags = new ArrayList<>();
try (RevWalk revWalk = new RevWalk(repo)) {
List<Ref> tags;
try {
List<Ref> 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()));