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
This commit is contained in:
parent
8887a6779a
commit
276fcb2a11
|
@ -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
|
||||
|
|
|
@ -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]));
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* <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 @@ 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();
|
||||
|
|
|
@ -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 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
|
||||
* <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 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<Ref> getBestMatch(List<Ref> tags) {
|
|||
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 String call() throws GitAPIException {
|
|||
}
|
||||
|
||||
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 @@ String describe(ObjectId tip) throws IOException {
|
|||
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 @@ 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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue