Expand Up @@ -42,16 +42,6 @@
*/
package org.eclipse.jgit.api;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.errors.InvalidPatternException;
Expand All @@ -63,18 +53,35 @@
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

@RunWith(Parameterized.class)
public class DescribeCommandTest extends RepositoryTestCase {

private Git git;

@Parameter
@Parameter(0)
public boolean useAnnotatedTags;

@Parameter(1)
public boolean describeUseAllTags;

@Parameters
public static Collection<Boolean[]> getUseAnnotatedTagsValues() {
return Arrays.asList(new Boolean[][] { { Boolean.TRUE },
{ Boolean.FALSE } });
return Arrays.asList(new Boolean[][] {
{ Boolean.TRUE, Boolean.FALSE },
{ Boolean.FALSE, Boolean.FALSE },
{ Boolean.TRUE, Boolean.TRUE },
{ Boolean.FALSE, Boolean.TRUE }
});
}

@Override
Expand Down Expand Up @@ -221,6 +228,49 @@ public void t1DominatesT2() throws Exception {
assertEquals("t1-1-g0244e7f", describe(c3));
}

/**
* When t1 annotated dominates t2 leightweight tag
*
* <pre>
* t1 -+-> t2 -
* | |
* +-> c3 -+-> c4
* </pre>
*
* @throws Exception
*/
@Test
public void t1AnnotatedDominatesT2leightweight() throws Exception {
ObjectId c1 = modify("aaa");
tag("t1", useAnnotatedTags);

ObjectId c2 = modify("bbb");
tag("t2", !useAnnotatedTags);

assertNameStartsWith(c2, "3747db3");
if (useAnnotatedTags) {
assertEquals("t1-1-g3747db3", describe(c2)); // 1 commits: t2 overridden by t1
} else {
assertEquals("t2", describe(c2)); // 1 commits: t2
}

branch("b", c1);

ObjectId c3 = modify("ccc");

ObjectId c4 = merge(c2);

assertNameStartsWith(c4, "119892b");
if (describeUseAllTags) {
assertEquals("t2-1-g119892b", describe(c4)); // 2 commits: c4 and c3
} else {
assertEquals("t1-3-g119892b", describe(c4)); // 2 commits: c4 and c3
}

assertNameStartsWith(c3, "0244e7f");
assertEquals("t1-1-g0244e7f", describe(c3));
}

/**
* When t1 is nearer than t2, t2 should be found
*
Expand Down Expand Up @@ -289,6 +339,10 @@ private ObjectId modify(String content) throws Exception {
}

private void tag(String tag) throws GitAPIException {
tag(tag, this.useAnnotatedTags);
}

private void tag(String tag, Boolean useAnnotatedTags) throws GitAPIException {
TagCommand tagCommand = git.tag().setName(tag)
.setAnnotated(useAnnotatedTags);
if (useAnnotatedTags)
Expand All @@ -304,15 +358,15 @@ private static void touch(File f, String contents) throws Exception {

private String describe(ObjectId c1, boolean longDesc)
throws GitAPIException, IOException {
return git.describe().setTarget(c1).setLong(longDesc).call();
return git.describe().setTarget(c1).setAllTags(describeUseAllTags).setLong(longDesc).call();
}

private String describe(ObjectId c1) throws GitAPIException, IOException {
return describe(c1, false);
}

private String describe(ObjectId c1, String... patterns) throws GitAPIException, IOException, InvalidPatternException {
return git.describe().setTarget(c1).setMatch(patterns).call();
return git.describe().setTarget(c1).setAllTags(describeUseAllTags).setMatch(patterns).call();
}

private static void assertNameStartsWith(ObjectId c4, String prefix) {
Expand Down
55 changes: 40 additions & 15 deletions org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
Expand Up @@ -42,19 +42,6 @@
*/
package org.eclipse.jgit.api;

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.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;
import org.eclipse.jgit.api.errors.RefNotFoundException;
Expand All @@ -71,8 +58,21 @@
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevFlagSet;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static org.eclipse.jgit.lib.Constants.R_TAGS;

/**
* Given a commit, show the most recent tag that is reachable from a commit.
*
Expand Down Expand Up @@ -103,6 +103,11 @@ public class DescribeCommand extends GitCommand<String> {
*/
private List<IMatcher> matchers = new ArrayList<>();

/**
* wheter to use all tags (incl. leightweight) or not
*/
private boolean allTags = false;

/**
*
* @param repo
Expand Down Expand Up @@ -171,6 +176,19 @@ public DescribeCommand setLong(boolean longDesc) {
return this;
}

/**
* --tags
* Instead of using only the annotated tags, use any tag found in refs/tags namespace. This option enables matching a lightweight
* (non-annotated) tag.
*
* @param useAllTags <code>true</code> for as like setting --tags in c git
* @return {@code this}
*/
public DescribeCommand setAllTags(boolean useAllTags) {
this.allTags = useAllTags;
return this;
}

private String longDescription(Ref tag, int depth, ObjectId tip)
throws IOException {
return String.format(
Expand Down Expand Up @@ -247,8 +265,15 @@ public String call() throws GitAPIException {
if (target == null)
setTarget(Constants.HEAD);

Collection<Ref> tagList = repo.getRefDatabase().getRefs(R_TAGS).values();
Map<ObjectId, List<Ref>> tags = tagList.stream()
Map<ObjectId, List<Ref>> tags = repo.getTags().values().stream()
.filter(ref -> {
ObjectId id = ref.getObjectId();
try {
return Boolean.TRUE.equals(allTags) || (id != null && (w.parseAny(id) instanceof RevTag));
} catch (Exception e) {
return false;
}
})
.collect(Collectors.groupingBy(this::getObjectIdFromRef));

// combined flags of all the candidate instances
Expand Down
16 changes: 8 additions & 8 deletions org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java
Expand Up @@ -43,13 +43,6 @@

package org.eclipse.jgit.api;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.errors.MissingObjectException;
Expand All @@ -65,6 +58,13 @@
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
* Command to find human-readable names of revisions.
*
Expand Down Expand Up @@ -277,7 +277,7 @@ public NameRevCommand addAnnotatedTags() {
if (refs == null)
refs = new ArrayList<>();
try {
for (Ref ref : repo.getRefDatabase().getRefs(Constants.R_TAGS).values()) {
for (Ref ref : repo.getTags().values()) {
ObjectId id = ref.getObjectId();
if (id != null && (walk.parseAny(id) instanceof RevTag))
addRef(ref);
Expand Down