jgit

Distinguish between lightweight and annotated tags in JGit


I'm trying to figure out how to distinguish between lightweight and annotated tags in JGit without catching any exceptions. In my special case, I need that distinction for getting all tag names of a given commit.


public List<String> getTagNamesOfCommit(String commitHash) throws Exception {
  List<String> tagNames = new ArrayList<>();
  RevWalk walk = new RevWalk(repository);
  List<Ref> tagList = git.tagList().call();
  for (Ref tag : tagList) {
    ObjectId peeledObjectId = tag.getPeeledObjectId();
    try {
      // Try to get annotated tag
      RevTag refetchedTag = walk.parseTag(tag.getObjectId());
      RevObject peeled = walk.peel(refetchedTag.getObject());
      if (peeled.getId().getName().equals(commitHash)) {
        tagNames.add(Repository.shortenRefName(tag.getName()));
      }
    } catch(IncorrectObjectTypeException notAnAnnotatedTag) {
      // Tag is not annotated. Yes, that's how you find out ...
      if (tag.getObjectId().getName().equals(commitHash)) {
        tagNames.add(Repository.shortenRefName(tag.getName()));
      }
    }
  }
  walk.close();
  return tagNames;
}

This is an equivalent solution as contained in an answer to this question

RevTag tag;
try {
  tag = revWalk.parseTag(ref.getObjectId());
  // ref points to an annotated tag
} catch(IncorrectObjectTypeException notAnAnnotatedTag) {
  // ref is a lightweight (aka unannotated) tag
}

The class org.eclipse.jgit.lib.Ref has the method getPeeledObjectId() which should return the id of the commit in case of an annotated tag.

* return if this ref is an annotated tag the id of the commit (or tree or
*        blob) that the annotated tag refers to; {@code null} if this ref
*        does not refer to an annotated tag.

This way I could check for null, which is much nicer than catching an exception. Unfortunately the method returns null in every case.

Two questions:

  1. Is there anything wrong with the use of git.tagList().call()?
  2. What would be the correct way to find out if a tag is an annotated one?

Solution

  • If you run the example ReadTagForName in the jgit-cookbook the output contains the following:

    Commit: (class org.eclipse.jgit.revwalk.RevCommit)commit a3033aec313556ba4e1ef55a66167a35432a4bc1 1369660983 ------p
    Tag: (class org.eclipse.jgit.revwalk.RevTag)tag 25f629b5e8ddfabd55650c05ffbb5199633b6df0 ------p
    

    So you should be able to check for the actual class of the Ref object that is returned. If it is "RevCommit" it is a lightweight tag, and if it is "RevTag" it seems to be an annotated tag.