A `match()` method has been added to the DescribeCommand, allowing users to specify one or more `glob(7)` matchers as per Git convention. Bug: 518377 Change-Id: Ib4cf34ce58128eed0334adf6c4a052dbea62c601 Signed-off-by: Oliver Lockwood <oliver.lockwood@cantab.net> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v4.9.0.201710071750-r
@@ -54,6 +54,7 @@ import java.util.Collection; | |||
import org.eclipse.jgit.api.errors.GitAPIException; | |||
import org.eclipse.jgit.api.errors.RefNotFoundException; | |||
import org.eclipse.jgit.errors.InvalidPatternException; | |||
import org.eclipse.jgit.junit.RepositoryTestCase; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.junit.Test; | |||
@@ -92,26 +93,41 @@ public class DescribeCommandTest extends RepositoryTestCase { | |||
ObjectId c1 = modify("aaa"); | |||
ObjectId c2 = modify("bbb"); | |||
tag("t1"); | |||
tag("alice-t1"); | |||
ObjectId c3 = modify("ccc"); | |||
tag("t2"); | |||
tag("bob-t2"); | |||
ObjectId c4 = modify("ddd"); | |||
assertNull(describe(c1)); | |||
assertNull(describe(c1, true)); | |||
assertEquals("t1", describe(c2)); | |||
assertEquals("t2", describe(c3)); | |||
assertEquals("t2-0-g44579eb", describe(c3, true)); | |||
assertNull(describe(c1, "a*", "b*", "c*")); | |||
assertEquals("alice-t1", describe(c2)); | |||
assertEquals("alice-t1", describe(c2, "alice*")); | |||
assertNull(describe(c2, "bob*")); | |||
assertNull(describe(c2, "?ob*")); | |||
assertEquals("alice-t1", describe(c2, "a*", "b*", "c*")); | |||
assertEquals("bob-t2", describe(c3)); | |||
assertEquals("bob-t2-0-g44579eb", describe(c3, true)); | |||
assertEquals("alice-t1-1-g44579eb", describe(c3, "alice*")); | |||
assertEquals("alice-t1-1-g44579eb", describe(c3, "a??c?-t*")); | |||
assertEquals("bob-t2", describe(c3, "bob*")); | |||
assertEquals("bob-t2", describe(c3, "?ob*")); | |||
assertEquals("bob-t2", describe(c3, "a*", "b*", "c*")); | |||
assertNameStartsWith(c4, "3e563c5"); | |||
// the value verified with git-describe(1) | |||
assertEquals("t2-1-g3e563c5", describe(c4)); | |||
assertEquals("t2-1-g3e563c5", describe(c4, true)); | |||
assertEquals("bob-t2-1-g3e563c5", describe(c4)); | |||
assertEquals("bob-t2-1-g3e563c5", describe(c4, true)); | |||
assertEquals("alice-t1-2-g3e563c5", describe(c4, "alice*")); | |||
assertEquals("bob-t2-1-g3e563c5", describe(c4, "bob*")); | |||
assertEquals("bob-t2-1-g3e563c5", describe(c4, "a*", "b*", "c*")); | |||
// test default target | |||
assertEquals("t2-1-g3e563c5", git.describe().call()); | |||
assertEquals("bob-t2-1-g3e563c5", git.describe().call()); | |||
} | |||
/** | |||
@@ -271,6 +287,10 @@ public class DescribeCommandTest extends RepositoryTestCase { | |||
return describe(c1, false); | |||
} | |||
private String describe(ObjectId c1, String... patterns) throws GitAPIException, IOException, InvalidPatternException { | |||
return git.describe().setTarget(c1).setMatch(patterns).call(); | |||
} | |||
private static void assertNameStartsWith(ObjectId c4, String prefix) { | |||
assertTrue(c4.name(), c4.name().startsWith(prefix)); | |||
} |
@@ -57,7 +57,10 @@ import org.eclipse.jgit.api.errors.GitAPIException; | |||
import org.eclipse.jgit.api.errors.JGitInternalException; | |||
import org.eclipse.jgit.api.errors.RefNotFoundException; | |||
import org.eclipse.jgit.errors.IncorrectObjectTypeException; | |||
import org.eclipse.jgit.errors.InvalidPatternException; | |||
import org.eclipse.jgit.errors.MissingObjectException; | |||
import org.eclipse.jgit.ignore.internal.IMatcher; | |||
import org.eclipse.jgit.ignore.internal.PathMatcher; | |||
import org.eclipse.jgit.internal.JGitText; | |||
import org.eclipse.jgit.lib.Constants; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
@@ -93,6 +96,11 @@ public class DescribeCommand extends GitCommand<String> { | |||
*/ | |||
private boolean longDesc; | |||
/** | |||
* Pattern matchers to be applied to tags under consideration | |||
*/ | |||
private List<IMatcher> matchers = new ArrayList<>(); | |||
/** | |||
* | |||
* @param repo | |||
@@ -169,6 +177,37 @@ public class DescribeCommand extends GitCommand<String> { | |||
.name()); | |||
} | |||
/** | |||
* Sets one or more {@code glob(7)} patterns that tags must match to be considered. | |||
* If multiple patterns are provided, tags only need match one of them. | |||
* | |||
* @param patterns the {@code glob(7)} pattern or patterns | |||
* @return {@code this} | |||
* @throws InvalidPatternException if the pattern passed in was invalid. | |||
* | |||
* @see <a | |||
* href="https://www.kernel.org/pub/software/scm/git/docs/git-describe.html" | |||
* >Git documentation about describe</a> | |||
* @since 4.9 | |||
*/ | |||
public DescribeCommand setMatch(String... patterns) throws InvalidPatternException { | |||
for (String p : patterns) { | |||
matchers.add(PathMatcher.createPathMatcher(p, null, false)); | |||
} | |||
return this; | |||
} | |||
private boolean tagMatches(Ref tag) { | |||
if (tag == null) { | |||
return false; | |||
} else if (matchers.size() == 0) { | |||
return true; | |||
} else { | |||
return matchers.stream() | |||
.anyMatch(m -> m.matches(tag.getName(), false)); | |||
} | |||
} | |||
/** | |||
* Describes the specified commit. Target defaults to HEAD if no commit was | |||
* set explicitly. | |||
@@ -243,9 +282,9 @@ 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 lucky = tags.get(target); | |||
if (lucky != null) { | |||
return longDesc ? longDescription(lucky, 0, target) : lucky | |||
Ref tagOnTarget = tags.get(target); | |||
if (tagMatches(tagOnTarget)) { | |||
return longDesc ? longDescription(tagOnTarget, 0, target) : tagOnTarget | |||
.getName().substring(R_TAGS.length()); | |||
} | |||
@@ -259,7 +298,7 @@ public class DescribeCommand extends GitCommand<String> { | |||
// 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 (t != null) { | |||
if (tagMatches(t)) { | |||
Candidate cd = new Candidate(c, t); | |||
candidates.add(cd); | |||
cd.depth = seen; |