Merge "Add "--long" option to JGit describe"
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java
index 4ab849b..6352a26 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java
@@ -96,4 +96,11 @@ public void testDescribeCommit() throws Exception {
 		assertArrayEquals(new String[] { "v1.0-1-g56f6ceb", "" },
 				execute("git describe"));
 	}
+
+	@Test
+	public void testDescribeTagLong() throws Exception {
+		initialCommitAndTag();
+		assertArrayEquals(new String[] { "v1.0-0-g6fd41be", "" },
+				execute("git describe --long HEAD"));
+	}
 }
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 e40c326..4bbb613 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
@@ -209,6 +209,7 @@
 usage_Gc=Cleanup unnecessary files and optimize the local repository
 usage_Glog=View commit history as a graph
 usage_IndexPack=Build pack index file for an existing packed archive
+usage_LongFormat=Always output the long format
 usage_LsRemote=List references in a remote repository
 usage_lsRemoteHeads=Show only refs starting with refs/heads
 usage_lsRemoteTags=Show only refs starting with refs/tags
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 52e8809..901e560 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
@@ -48,6 +48,7 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.pgm.internal.CLIText;
 import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
 
 @Command(common = true, usage = "usage_Describe")
 class Describe extends TextBuiltin {
@@ -55,11 +56,15 @@ class Describe extends TextBuiltin {
 	@Argument(index = 0, metaVar = "metaVar_treeish")
 	private ObjectId tree;
 
+	@Option(name = "--long", usage = "usage_LongFormat")
+	private boolean longDesc;
+
 	@Override
 	protected void run() throws Exception {
 		DescribeCommand cmd = new Git(db).describe();
 		if (tree != null)
 			cmd.setTarget(tree);
+		cmd.setLong(longDesc);
 		String result = null;
 		try {
 			result = cmd.call();
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 eb598e8..1e5d3bc 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
@@ -49,17 +49,33 @@
 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.junit.RepositoryTestCase;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class DescribeCommandTest extends RepositoryTestCase {
 
 	private Git git;
 
+	@Parameter
+	public boolean useAnnotatedTags;
+
+	@Parameters
+	public static Collection<Boolean[]> getUseAnnotatedTagsValues() {
+		return Arrays.asList(new Boolean[][] { { Boolean.TRUE },
+				{ Boolean.FALSE } });
+	}
+
 	@Override
 	public void setUp() throws Exception {
 		super.setUp();
@@ -84,12 +100,15 @@ public void testDescribe() throws Exception {
 		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));
 
 		assertNameStartsWith(c4, "3e563c5");
 		// the value verified with git-describe(1)
 		assertEquals("t2-1-g3e563c5", describe(c4));
+		assertEquals("t2-1-g3e563c5", describe(c4, true));
 
 		// test default target
 		assertEquals("t2-1-g3e563c5", git.describe().call());
@@ -122,6 +141,7 @@ public void testDescribeBranch() throws Exception {
 		assertNameStartsWith(c4, "119892b");
 		assertEquals("t-2-g119892b", describe(c4)); // 2 commits: c4 and c3
 		assertNull(describe(c3));
+		assertNull(describe(c3, true));
 	}
 
 	private void branch(String name, ObjectId base) throws GitAPIException {
@@ -229,7 +249,11 @@ private ObjectId modify(String content) throws Exception {
 	}
 
 	private void tag(String tag) throws GitAPIException {
-		git.tag().setName(tag).setMessage(tag).call();
+		TagCommand tagCommand = git.tag().setName(tag)
+				.setAnnotated(useAnnotatedTags);
+		if (useAnnotatedTags)
+			tagCommand.setMessage(tag);
+		tagCommand.call();
 	}
 
 	private static void touch(File f, String contents) throws Exception {
@@ -238,8 +262,13 @@ private static void touch(File f, String contents) throws Exception {
 		w.close();
 	}
 
+	private String describe(ObjectId c1, boolean longDesc)
+			throws GitAPIException, IOException {
+		return git.describe().setTarget(c1).setLong(longDesc).call();
+	}
+
 	private String describe(ObjectId c1) throws GitAPIException, IOException {
-		return git.describe().setTarget(c1).call();
+		return describe(c1, false);
 	}
 
 	private static void assertNameStartsWith(ObjectId c4, String prefix) {
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 08e41e4..bf6da45 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
@@ -89,6 +89,11 @@ public class DescribeCommand extends GitCommand<String> {
 	private int maxCandidates = 10;
 
 	/**
+	 * Whether to always use long output format or not.
+	 */
+	private boolean longDesc;
+
+	/**
 	 *
 	 * @param repo
 	 */
@@ -139,6 +144,32 @@ public DescribeCommand setTarget(String rev) throws IOException,
 	}
 
 	/**
+	 * Determine whether always to use the long format or not. When set to
+	 * <code>true</code> the long format is used even the commit matches a tag.
+	 *
+	 * @param longDesc
+	 *            <code>true</code> if always the long format should be used.
+	 * @return {@code this}
+	 *
+	 * @see <a
+	 *      href="https://www.kernel.org/pub/software/scm/git/docs/git-describe.html"
+	 *      >Git documentation about describe</a>
+	 * @since 4.0
+	 */
+	public DescribeCommand setLong(boolean longDesc) {
+		this.longDesc = longDesc;
+		return this;
+	}
+
+	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$
+				Integer.valueOf(depth), w.getObjectReader().abbreviate(tip)
+						.name());
+	}
+
+	/**
 	 * Describes the specified commit. Target defaults to HEAD if no commit was
 	 * set explicitly.
 	 *
@@ -205,16 +236,18 @@ boolean reaches(RevCommit c) {
 				}
 
 				String describe(ObjectId tip) throws IOException {
-					return String.format("%s-%d-g%s", tag.getName().substring(R_TAGS.length()), //$NON-NLS-1$
-							Integer.valueOf(depth), w.getObjectReader().abbreviate(tip).name());
+					return longDescription(tag, depth, tip);
 				}
+
 			}
 			List<Candidate> candidates = new ArrayList<Candidate>();    // 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 lucky.getName().substring(R_TAGS.length());
+			if (lucky != null) {
+				return longDesc ? longDescription(lucky, 0, target) : lucky
+						.getName().substring(R_TAGS.length());
+			}
 
 			w.markStart(target);