From b21c82fdb0edc79735251550cacf37491adb8a61 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 3 Mar 2011 16:17:29 -0800 Subject: [PATCH] resolve(): Fix wrong parsing of branch "foo-gbed2-dev" When parsing a string such as "foo-gbed2" resolve() was assuming the suffix was from git describe output. This lead to JGit trying to find the completion for the object abbreviation "bed2", rather than using the current value of the reference. If there was only one such object in the repository, JGit might actually use the wrong value here, as resolve() would return the completion of the abbreviation "bed2" rather than the current value of the reference "refs/heads/foo-gbed2". Move the parsing of git describe abbreviations out of the operator portion of the resolve() method and into the simple portion that is supposed to handle only object ids or reference names, and only do the describe parsing after all other approaches have already failed to provide a resolution. Add new unit tests to verify the behavior is as expected by users. Bug: 338839 Change-Id: I52054d7b89628700c730f9a4bd7743b16b9042a9 Signed-off-by: Shawn O. Pearce --- .../jgit/lib/RepositoryResolveTest.java | 19 ++++++++++ .../src/org/eclipse/jgit/lib/Repository.java | 37 ++++++++++--------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java index 5ad913c56..d55856ace 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryResolveTest.java @@ -48,6 +48,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import java.io.IOException; @@ -181,6 +182,24 @@ public void testParseGitDescribeOutput() throws IOException { assertEquals(db.resolve("b~2"), db.resolve("B-6-g7f82283~2")); } + @Test + public void testParseNonGitDescribe() throws IOException { + ObjectId id = id("49322bb17d3acc9146f98c97d078513228bbf3c0"); + RefUpdate ru = db.updateRef("refs/heads/foo-g032c"); + ru.setNewObjectId(id); + assertSame(RefUpdate.Result.NEW, ru.update()); + + assertEquals(id, db.resolve("refs/heads/foo-g032c")); + assertEquals(id, db.resolve("foo-g032c")); + + ru = db.updateRef("refs/heads/foo-g032c-dev"); + ru.setNewObjectId(id); + assertSame(RefUpdate.Result.NEW, ru.update()); + + assertEquals(id, db.resolve("refs/heads/foo-g032c-dev")); + assertEquals(id, db.resolve("foo-g032c-dev")); + } + @Test public void testParseLookupPath() throws IOException { ObjectId b2_txt = id("10da5895682013006950e7da534b705252b03be6"); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java index c4d2d73bc..6916a86f4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java @@ -577,24 +577,6 @@ private ObjectId resolve(final RevWalk rw, final String revstr) throws IOExcepti revstr); i = m - 1; 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; case ':': { RevTree tree; if (ref == null) { @@ -637,6 +619,14 @@ private static boolean isHex(char c) { || ('A' <= c && c <= 'F'); } + private static boolean isAllHex(String str, int ptr) { + while (ptr < str.length()) { + if (!isHex(str.charAt(ptr++))) + return false; + } + return true; + } + private RevObject parseSimple(RevWalk rw, String revstr) throws IOException { ObjectId id = resolveSimple(revstr); return id != null ? rw.parseAny(id) : null; @@ -653,6 +643,17 @@ private ObjectId resolveSimple(final String revstr) throws IOException { if (AbbreviatedObjectId.isId(revstr)) return resolveAbbreviation(revstr); + int dashg = revstr.indexOf("-g"); + if (4 < revstr.length() && 0 <= dashg + && isHex(revstr.charAt(dashg + 2)) + && isHex(revstr.charAt(dashg + 3)) + && isAllHex(revstr, dashg + 4)) { + // Possibly output from git describe? + String s = revstr.substring(dashg + 2); + if (AbbreviatedObjectId.isId(s)) + return resolveAbbreviation(s); + } + return null; }