diff options
author | Oliver Lockwood <oliver.lockwood@cantab.net> | 2017-06-21 17:25:19 +0100 |
---|---|---|
committer | Oliver Lockwood <oliver.lockwood@cantab.net> | 2017-06-21 17:25:19 +0100 |
commit | 060f3699d473a977b86b2ad9d653df4c83e8b681 (patch) | |
tree | 87934c9f76b7945a4b8b636589a1c0671eba8034 /org.eclipse.jgit/src/org/eclipse/jgit/api | |
parent | af0867cb86a3b10ab3851245fb148a817201e6ca (diff) | |
download | jgit-060f3699d473a977b86b2ad9d653df4c83e8b681.tar.gz jgit-060f3699d473a977b86b2ad9d653df4c83e8b681.zip |
Fix bug in multiple tag handling on DescribeCommand
In the case of multiple tags on the same commit, jgit previously
only ever looked at the last of those tags; git behaviour is to
return the first tag (or first matching one if --match is
specified).
Bug: 518377
Change-Id: I3b6b58ad9f8aa3879ae35b84542b7bddc74a27d6
Signed-off-by: Oliver Lockwood <oliver.lockwood@cantab.net>
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/api')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java | 60 |
1 files changed, 37 insertions, 23 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java index 1353bf11a4..d365171ed1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java @@ -47,11 +47,13 @@ import static org.eclipse.jgit.lib.Constants.R_TAGS; 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 java.util.Optional; +import java.util.stream.Collectors; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; @@ -197,17 +199,34 @@ public class DescribeCommand extends GitCommand<String> { return this; } - private boolean tagMatches(Ref tag) { - if (tag == null) { - return false; + private Optional<Ref> getBestMatch(List<Ref> tags) { + if (tags == null || tags.size() == 0) { + return Optional.empty(); } else if (matchers.size() == 0) { - return true; + // No matchers, simply return the first tag entry + return Optional.of(tags.get(0)); } else { - return matchers.stream() - .anyMatch(m -> m.matches(tag.getName(), false)); + // Find the first tag that matches one of the matchers; precedence according to matcher definition order + for (IMatcher matcher : matchers) { + Optional<Ref> match = tags.stream() + .filter(tag -> matcher.matches(tag.getName(), false)) + .findFirst(); + if (match.isPresent()) { + return match; + } + } + return Optional.empty(); } } + private ObjectId getObjectIdFromRef(Ref r) { + ObjectId key = repo.peel(r).getPeeledObjectId(); + if (key == null) { + key = r.getObjectId(); + } + return key; + } + /** * Describes the specified commit. Target defaults to HEAD if no commit was * set explicitly. @@ -228,14 +247,9 @@ public class DescribeCommand extends GitCommand<String> { if (target == null) setTarget(Constants.HEAD); - Map<ObjectId, Ref> tags = new HashMap<>(); - - for (Ref r : repo.getRefDatabase().getRefs(R_TAGS).values()) { - ObjectId key = repo.peel(r).getPeeledObjectId(); - if (key == null) - key = r.getObjectId(); - tags.put(key, r); - } + Collection<Ref> tagList = repo.getRefDatabase().getRefs(R_TAGS).values(); + Map<ObjectId, List<Ref>> tags = tagList.stream() + .collect(Collectors.groupingBy(this::getObjectIdFromRef)); // combined flags of all the candidate instances final RevFlagSet allFlags = new RevFlagSet(); @@ -281,11 +295,11 @@ public class DescribeCommand extends GitCommand<String> { } List<Candidate> candidates = new ArrayList<>(); // all the candidates we find - // is the target already pointing to a tag? if so, we are done! - Ref tagOnTarget = tags.get(target); - if (tagMatches(tagOnTarget)) { - return longDesc ? longDescription(tagOnTarget, 0, target) : tagOnTarget - .getName().substring(R_TAGS.length()); + // is the target already pointing to a suitable tag? if so, we are done! + Optional<Ref> bestMatch = getBestMatch(tags.get(target)); + if (bestMatch.isPresent()) { + return longDesc ? longDescription(bestMatch.get(), 0, target) : + bestMatch.get().getName().substring(R_TAGS.length()); } w.markStart(target); @@ -297,9 +311,9 @@ public class DescribeCommand extends GitCommand<String> { // if a tag already dominates this commit, // then there's no point in picking a tag on this commit // since the one that dominates it is always more preferable - Ref t = tags.get(c); - if (tagMatches(t)) { - Candidate cd = new Candidate(c, t); + bestMatch = getBestMatch(tags.get(c)); + if (bestMatch.isPresent()) { + Candidate cd = new Candidate(c, bestMatch.get()); candidates.add(cd); cd.depth = seen; } |