aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/api
diff options
context:
space:
mode:
authorOliver Lockwood <oliver.lockwood@cantab.net>2017-06-21 17:25:19 +0100
committerOliver Lockwood <oliver.lockwood@cantab.net>2017-06-21 17:25:19 +0100
commit060f3699d473a977b86b2ad9d653df4c83e8b681 (patch)
tree87934c9f76b7945a4b8b636589a1c0671eba8034 /org.eclipse.jgit/src/org/eclipse/jgit/api
parentaf0867cb86a3b10ab3851245fb148a817201e6ca (diff)
downloadjgit-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.java60
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;
}