diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties index f3e1fe31b..c116437c6 100644 --- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties +++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties @@ -294,6 +294,7 @@ usage_Status=Show the working tree status usage_StopTrackingAFile=Stop tracking a file usage_TextHashFunctions=Scan repository to compute maximum number of collisions for hash functions usage_UpdateRemoteRepositoryFromLocalRefs=Update remote repository from local refs +usage_UseAll=Use all refs found in refs/ usage_UseTags=Use any tag including lightweight tags usage_WriteDirCache=Write the DirCache usage_abbrevCommits=abbreviate commits to N + 1 digits diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java index 610b6472a..8aa119a35 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java @@ -32,6 +32,9 @@ class Describe extends TextBuiltin { @Option(name = "--long", usage = "usage_LongFormat") private boolean longDesc; + @Option(name = "--all", usage = "usage_UseTags") + private boolean useAll; + @Option(name = "--tags", usage = "usage_UseTags") private boolean useTags; @@ -50,6 +53,7 @@ protected void run() { cmd.setTarget(tree); } cmd.setLong(longDesc); + cmd.setAll(useAll); cmd.setTags(useTags); cmd.setAlways(always); cmd.setMatch(patterns.toArray(new String[0])); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java index 7ba7c8d2b..b460e3f52 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java @@ -310,7 +310,7 @@ public void t1AnnotatedDominatesT2lightweight() throws Exception { assertEquals( "2 commits for describe commit increment expected since lightweight tag: c4 and c3", "t2-2-g119892b", describe(c4)); // 2 commits: c4 and c3 - } else if (!useAnnotatedTags && !describeUseAllTags) { + } else if (!useAnnotatedTags) { assertEquals("no matching commits expected", null, describe(c4)); } else { assertEquals( @@ -405,6 +405,46 @@ public void globMatchWithSlashes() throws Exception { } } + @Test + public void testDescribeUseAllRefsMaster() throws Exception { + final ObjectId c1 = modify("aaa"); + tag("t1"); + + if (useAnnotatedTags || describeUseAllTags) { + assertEquals("t1", describe(c1)); + } else { + assertEquals(null, describe(c1)); + } + assertEquals("heads/master", describeAll(c1)); + } + + /** + * Branch off from master and then tag + * + *
+	 * c1 -+ -> c2
+	 *     |
+	 *     +-> t1
+	 * 
+ * @throws Exception + * */ + @Test + public void testDescribeUseAllRefsBranch() throws Exception { + final ObjectId c1 = modify("aaa"); + modify("bbb"); + + branch("b", c1); + final ObjectId c3 = modify("ccc"); + tag("t1"); + + if (!useAnnotatedTags && !describeUseAllTags) { + assertEquals(null, describe(c3)); + } else { + assertEquals("t1", describe(c3)); + } + assertEquals("heads/b", describeAll(c3)); + } + private ObjectId merge(ObjectId c2) throws GitAPIException { return git.merge().include(c2).call().getNewHead(); } @@ -444,6 +484,11 @@ private String describe(ObjectId c1) throws GitAPIException, IOException { return describe(c1, false, false); } + private String describeAll(ObjectId c1) throws GitAPIException, IOException { + return git.describe().setTarget(c1).setTags(describeUseAllTags) + .setLong(false).setAlways(false).setAll(true).call(); + } + private String describe(ObjectId c1, String... patterns) throws Exception { return git.describe().setTarget(c1).setTags(describeUseAllTags) .setMatch(patterns).call(); 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 8d427385d..6a9fbd4f6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java @@ -9,6 +9,7 @@ */ package org.eclipse.jgit.api; +import static org.eclipse.jgit.lib.Constants.R_REFS; import static org.eclipse.jgit.lib.Constants.R_TAGS; import java.io.IOException; @@ -72,6 +73,11 @@ public class DescribeCommand extends GitCommand { */ private List matchers = new ArrayList<>(); + /** + * Whether to use all refs in the refs/ namespace + */ + private boolean useAll; + /** * Whether to use all tags (incl. lightweight) or not. */ @@ -152,6 +158,22 @@ public DescribeCommand setLong(boolean longDesc) { return this; } + /** + * Instead of using only the annotated tags, use any ref found in refs/ + * namespace. This option enables matching any known branch, + * remote-tracking branch, or lightweight tag. + * + * @param all + * true enables matching any ref found in refs/ + * like setting option --all in c git + * @return {@code this} + * @since 5.10 + */ + public DescribeCommand setAll(boolean all) { + this.useAll = all; + return this; + } + /** * Instead of using only the annotated tags, use any tag found in refs/tags * namespace. This option enables matching lightweight (non-annotated) tags @@ -186,7 +208,7 @@ public DescribeCommand setAlways(boolean always) { private String longDescription(Ref tag, int depth, ObjectId tip) throws IOException { return String.format( - "%s-%d-g%s", tag.getName().substring(R_TAGS.length()), //$NON-NLS-1$ + "%s-%d-g%s", formatRefName(tag.getName()), //$NON-NLS-1$ Integer.valueOf(depth), w.getObjectReader().abbreviate(tip) .name()); } @@ -244,8 +266,7 @@ private Optional getBestMatch(List tags) { for (FileNameMatcher matcher : matchers) { Stream m = tags.stream().filter( tag -> { - matcher.append( - tag.getName().substring(R_TAGS.length())); + matcher.append(formatRefName(tag.getName())); boolean result = matcher.isMatch(); matcher.reset(); return result; @@ -283,7 +304,7 @@ public String call() throws GitAPIException { } Collection tagList = repo.getRefDatabase() - .getRefsByPrefix(R_TAGS); + .getRefsByPrefix(useAll ? R_REFS : R_TAGS); Map> tags = tagList.stream() .filter(this::filterLightweightTags) .collect(Collectors.groupingBy(this::getObjectIdFromRef)); @@ -336,7 +357,7 @@ String describe(ObjectId tip) throws IOException { Optional bestMatch = getBestMatch(tags.get(target)); if (bestMatch.isPresent()) { return longDesc ? longDescription(bestMatch.get(), 0, target) : - bestMatch.get().getName().substring(R_TAGS.length()); + formatRefName(bestMatch.get().getName()); } w.markStart(target); @@ -407,6 +428,16 @@ String describe(ObjectId tip) throws IOException { } } + /** + * Removes the refs/ or refs/tags prefix from tag names + * @param name the name of the tag + * @return the tag name with its prefix removed + */ + private String formatRefName(String name) { + return name.startsWith(R_TAGS) ? name.substring(R_TAGS.length()) : + name.substring(R_REFS.length()); + } + /** * Whether we use lightweight tags or not for describe Candidates * @@ -419,7 +450,7 @@ String describe(ObjectId tip) throws IOException { private boolean filterLightweightTags(Ref ref) { ObjectId id = ref.getObjectId(); try { - return this.useTags || (id != null && (w.parseTag(id) != null)); + return this.useAll || this.useTags || (id != null && (w.parseTag(id) != null)); } catch (IOException e) { return false; }