diff options
3 files changed, 101 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java index 8dbe64478e..292e50447e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java @@ -1000,6 +1000,23 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } @Test + public void testExactRef_FetchHead() throws IOException { + // This is an odd special case where we need to make sure we read + // exactly the first 40 bytes of the file and nothing further on + // that line, or the remainder of the file. + write(new File(diskRepo.getDirectory(), "FETCH_HEAD"), A.name() + + "\tnot-for-merge" + + "\tbranch 'master' of git://egit.eclipse.org/jgit\n"); + + Ref r = refdir.exactRef("FETCH_HEAD"); + assertFalse(r.isSymbolic()); + assertEquals(A, r.getObjectId()); + assertEquals("FETCH_HEAD", r.getName()); + assertFalse(r.isPeeled()); + assertNull(r.getPeeledObjectId()); + } + + @Test public void testGetRef_AnyHeadWithGarbage() throws IOException { write(new File(diskRepo.getDirectory(), "refs/heads/A"), A.name() + "012345 . this is not a standard reference\n" diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java index f2ed684511..109f401898 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java @@ -84,6 +84,12 @@ public class RefTest extends SampleDataRepositoryTestCase { } } + private void writeNewRef(String name, ObjectId value) throws IOException { + RefUpdate updateRef = db.updateRef(name); + updateRef.setNewObjectId(value); + assertEquals(RefUpdate.Result.NEW, updateRef.update()); + } + @Test public void testRemoteNames() throws Exception { FileBasedConfig config = db.getConfig(); @@ -192,6 +198,50 @@ public class RefTest extends SampleDataRepositoryTestCase { assertEquals(Storage.LOOSE, ref.getStorage()); } + @Test + public void testGetShortRef() throws IOException { + Ref ref = db.getRef("master"); + assertEquals("refs/heads/master", ref.getName()); + assertEquals(db.resolve("refs/heads/master"), ref.getObjectId()); + } + + @Test + public void testGetShortExactRef() throws IOException { + assertNull(db.getRefDatabase().exactRef("master")); + + Ref ref = db.getRefDatabase().exactRef("HEAD"); + assertEquals("HEAD", ref.getName()); + assertEquals("refs/heads/master", ref.getTarget().getName()); + assertEquals(db.resolve("refs/heads/master"), ref.getObjectId()); + } + + @Test + public void testRefsUnderRefs() throws IOException { + ObjectId masterId = db.resolve("refs/heads/master"); + writeNewRef("refs/heads/refs/foo/bar", masterId); + + assertNull(db.getRefDatabase().exactRef("refs/foo/bar")); + + Ref ref = db.getRef("refs/foo/bar"); + assertEquals("refs/heads/refs/foo/bar", ref.getName()); + assertEquals(db.resolve("refs/heads/master"), ref.getObjectId()); + } + + @Test + public void testAmbiguousRefsUnderRefs() throws IOException { + ObjectId masterId = db.resolve("refs/heads/master"); + writeNewRef("refs/foo/bar", masterId); + writeNewRef("refs/heads/refs/foo/bar", masterId); + + Ref exactRef = db.getRefDatabase().exactRef("refs/foo/bar"); + assertEquals("refs/foo/bar", exactRef.getName()); + assertEquals(masterId, exactRef.getObjectId()); + + Ref ref = db.getRef("refs/foo/bar"); + assertEquals("refs/foo/bar", ref.getName()); + assertEquals(masterId, ref.getObjectId()); + } + /** * Let an "outsider" create a loose ref with the same name as a packed one * diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java index 7fea880612..1a58c51382 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java @@ -211,6 +211,9 @@ public abstract class RefDatabase { * Aside from taking advantage of {@link #SEARCH_PATH}, this method may be * able to more quickly resolve a single reference name than obtaining the * complete namespace by {@code getRefs(ALL).get(name)}. + * <p> + * To read a specific reference without using @{link #SEARCH_PATH}, see + * {@link #exactRef(String)}. * * @param name * the name of the reference. May be a short name which must be @@ -222,6 +225,36 @@ public abstract class RefDatabase { public abstract Ref getRef(String name) throws IOException; /** + * Read a single reference. + * <p> + * Unlike {@link #getRef}, this method expects an unshortened reference + * name and does not search using the standard {@link #SEARCH_PATH}. + * + * @param name + * the unabbreviated name of the reference. + * @return the reference (if it exists); else {@code null}. + * @throws IOException + * the reference space cannot be accessed. + * @since 4.1 + */ + public Ref exactRef(String name) throws IOException { + int slash = name.lastIndexOf('/'); + String prefix = name.substring(0, slash + 1); + String rest = name.substring(slash + 1); + Ref result = getRefs(prefix).get(rest); + if (result != null || slash != -1) { + return result; + } + + for (Ref ref : getAdditionalRefs()) { + if (name.equals(ref.getName())) { + return ref; + } + } + return null; + } + + /** * Get a section of the reference namespace. * * @param prefix @@ -242,6 +275,7 @@ public abstract class RefDatabase { * The result list includes non-ref items such as MERGE_HEAD and * FETCH_RESULT cast to be refs. The names of these refs are not returned by * <code>getRefs(ALL)</code> but are accepted by {@link #getRef(String)} + * and {@link exactRef(String)}. * * @return a list of additional refs * @throws IOException |