Browse Source

Implement git describe --all

This enables jgit to use any refs in the refs/ namespace when describing
commits.

Signed-off-by: Jason Yeo <jasonyeo88@gmail.com>
Change-Id: I1fa22d1c39c0e2f5e4c2938c9751d8556494ac26
tags/v5.10.0.202011041322-m2
Jason Yeo 3 years ago
parent
commit
276fcb2a11

+ 1
- 0
org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties View File

@@ -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

+ 4
- 0
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java View File

@@ -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 @@ class Describe extends TextBuiltin {
cmd.setTarget(tree);
}
cmd.setLong(longDesc);
cmd.setAll(useAll);
cmd.setTags(useTags);
cmd.setAlways(always);
cmd.setMatch(patterns.toArray(new String[0]));

+ 46
- 1
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java View File

@@ -310,7 +310,7 @@ public class DescribeCommandTest extends RepositoryTestCase {
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 class DescribeCommandTest extends RepositoryTestCase {
}
}

@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
*
* <pre>
* c1 -+ -> c2
* |
* +-> t1
* </pre>
* @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 @@ public class DescribeCommandTest extends RepositoryTestCase {
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();

+ 37
- 6
org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java View File

@@ -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<String> {
*/
private List<FileNameMatcher> 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 class DescribeCommand extends GitCommand<String> {
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
* <code>true</code> 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 class DescribeCommand extends GitCommand<String> {
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 @@ public class DescribeCommand extends GitCommand<String> {
for (FileNameMatcher matcher : matchers) {
Stream<Ref> 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 class DescribeCommand extends GitCommand<String> {
}

Collection<Ref> tagList = repo.getRefDatabase()
.getRefsByPrefix(R_TAGS);
.getRefsByPrefix(useAll ? R_REFS : R_TAGS);
Map<ObjectId, List<Ref>> tags = tagList.stream()
.filter(this::filterLightweightTags)
.collect(Collectors.groupingBy(this::getObjectIdFromRef));
@@ -336,7 +357,7 @@ public class DescribeCommand extends GitCommand<String> {
Optional<Ref> 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 @@ public class DescribeCommand extends GitCommand<String> {
}
}

/**
* 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 @@ public class DescribeCommand extends GitCommand<String> {
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;
}

Loading…
Cancel
Save