Browse Source

Support parsing git describe style output

We now match on the -gABBREV style output created by git describe
when its describing a non-tagged commit, and resolve that back to
the full ObjectId using the abbreviation resolution feature that
we already support.

Change-Id: Ib3033f9483d9e1c66c8bb721ff48d4485bcdaef1
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
stable-0.9
Shawn O. Pearce 14 years ago
parent
commit
8da17c5046
  1. 20
      org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java
  2. 46
      org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java

20
org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java

@ -48,6 +48,8 @@ package org.eclipse.jgit.lib;
import java.io.IOException; import java.io.IOException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
public class RepositoryResolveTest extends SampleDataRepositoryTestCase { public class RepositoryResolveTest extends SampleDataRepositoryTestCase {
public void testObjectId_existing() throws IOException { public void testObjectId_existing() throws IOException {
@ -140,4 +142,22 @@ public class RepositoryResolveTest extends SampleDataRepositoryTestCase {
assertEquals("856ec208ae6cadac25a6d74f19b12bb27a24fe24",db.resolve("refs/tags/B10th^{tree}").name()); assertEquals("856ec208ae6cadac25a6d74f19b12bb27a24fe24",db.resolve("refs/tags/B10th^{tree}").name());
} }
public void testParseGitDescribeOutput() throws IOException {
ObjectId exp = db.resolve("b");
assertEquals(exp, db.resolve("B-g7f82283")); // old style
assertEquals(exp, db.resolve("B-6-g7f82283")); // new style
assertEquals(exp, db.resolve("B-6-g7f82283^0"));
assertEquals(exp, db.resolve("B-6-g7f82283^{commit}"));
try {
db.resolve("B-6-g7f82283^{blob}");
fail("expected IncorrectObjectTypeException");
} catch (IncorrectObjectTypeException badType) {
// Expected
}
assertEquals(db.resolve("b^1"), db.resolve("B-6-g7f82283^1"));
assertEquals(db.resolve("b~2"), db.resolve("B-6-g7f82283~2"));
}
} }

46
org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java

@ -375,8 +375,6 @@ public abstract class Repository {
* Currently supported is combinations of these. * Currently supported is combinations of these.
* <ul> * <ul>
* <li>SHA-1 - a SHA-1</li> * <li>SHA-1 - a SHA-1</li>
* <li>SHA-1 abbreviation - a leading prefix of a SHA-1. At least the first
* two bytes must be supplied.</li>
* <li>refs/... - a ref name</li> * <li>refs/... - a ref name</li>
* <li>ref^n - nth parent reference</li> * <li>ref^n - nth parent reference</li>
* <li>ref~n - distance via parent reference</li> * <li>ref~n - distance via parent reference</li>
@ -387,7 +385,6 @@ public abstract class Repository {
* *
* Not supported is: * Not supported is:
* <ul> * <ul>
* <li>tag-NNN-gcommit - a non tagged revision from git describe</li>
* <li>timestamps in reflogs, ref@{full or relative timestamp}</li> * <li>timestamps in reflogs, ref@{full or relative timestamp}</li>
* </ul> * </ul>
* *
@ -562,6 +559,25 @@ public abstract class Repository {
revstr); revstr);
i = m - 1; i = m - 1;
break; break;
case '-':
if (i + 4 < rev.length && rev[i + 1] == 'g'
&& isHex(rev[i + 2]) && isHex(rev[i + 3])) {
// Possibly output from git describe?
// Resolve longest valid abbreviation.
int cnt = 2;
while (i + 2 + cnt < rev.length && isHex(rev[i + 2 + cnt]))
cnt++;
String s = new String(rev, i + 2, cnt);
if (AbbreviatedObjectId.isId(s)) {
ObjectId id = resolveAbbreviation(s);
if (id != null) {
ref = rw.parseAny(id);
i += 1 + s.length();
}
}
}
break;
default: default:
if (ref != null) if (ref != null)
throw new RevisionSyntaxException(revstr); throw new RevisionSyntaxException(revstr);
@ -570,6 +586,12 @@ public abstract class Repository {
return ref != null ? ref.copy() : resolveSimple(revstr); return ref != null ? ref.copy() : resolveSimple(revstr);
} }
private static boolean isHex(char c) {
return ('0' <= c && c <= '9') //
|| ('a' <= c && c <= 'f') //
|| ('A' <= c && c <= 'F');
}
private RevObject parseSimple(RevWalk rw, String revstr) throws IOException { private RevObject parseSimple(RevWalk rw, String revstr) throws IOException {
ObjectId id = resolveSimple(revstr); ObjectId id = resolveSimple(revstr);
return id != null ? rw.parseAny(id) : null; return id != null ? rw.parseAny(id) : null;
@ -583,23 +605,29 @@ public abstract class Repository {
if (r != null) if (r != null)
return r.getObjectId(); return r.getObjectId();
if (AbbreviatedObjectId.isId(revstr)) { if (AbbreviatedObjectId.isId(revstr))
return resolveAbbreviation(revstr);
return null;
}
private ObjectId resolveAbbreviation(final String revstr) throws IOException,
AmbiguousObjectException {
AbbreviatedObjectId id = AbbreviatedObjectId.fromString(revstr); AbbreviatedObjectId id = AbbreviatedObjectId.fromString(revstr);
ObjectReader reader = newObjectReader(); ObjectReader reader = newObjectReader();
try { try {
Collection<ObjectId> matches = reader.resolve(id); Collection<ObjectId> matches = reader.resolve(id);
if (matches.size() == 1) if (matches.size() == 0)
return null;
else if (matches.size() == 1)
return matches.iterator().next(); return matches.iterator().next();
if (1 < matches.size()) else
throw new AmbiguousObjectException(id, matches); throw new AmbiguousObjectException(id, matches);
} finally { } finally {
reader.release(); reader.release();
} }
} }
return null;
}
/** Increment the use counter by one, requiring a matched {@link #close()}. */ /** Increment the use counter by one, requiring a matched {@link #close()}. */
public void incrementOpen() { public void incrementOpen() {
useCnt.incrementAndGet(); useCnt.incrementAndGet();

Loading…
Cancel
Save