From 48b67012d610f9151b425a27a4287eeedfbff0a4 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Fri, 5 Jun 2015 16:08:55 -0700 Subject: [PATCH] Allow lookup of multiple exact refs in one shot exactRef(ref1, ref2, ref3) requests multiple specific refs in a single lookup, which may be faster in some backends than looking them up one by one. firstExactRef generalizes getRef by finding the first existing ref from the list of refs named. Its main purpose is for the default implementation of getRef (finding the first existing ref in a search path). Hopefully it can be useful for other operations that look for refs in a search path (e.g., git log --notes=), too. Change-Id: I5c6fcf1d3920f6968b8b97f3d4c3a267258c4b86 Signed-off-by: Jonathan Nieder --- .../storage/file/RefDirectoryTest.java | 42 ++++++++++++++++ .../src/org/eclipse/jgit/lib/RefDatabase.java | 50 +++++++++++++++++++ 2 files changed, 92 insertions(+) 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 292e50447..099159892 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 @@ -358,6 +358,33 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { assertEquals(A, c.getObjectId()); } + @Test + public void testFirstExactRef_IgnoresGarbageRef() throws IOException { + writeLooseRef("refs/heads/A", A); + write(new File(diskRepo.getDirectory(), "refs/heads/bad"), "FAIL\n"); + + Ref a = refdir.firstExactRef("refs/heads/bad", "refs/heads/A"); + assertEquals("refs/heads/A", a.getName()); + assertEquals(A, a.getObjectId()); + } + + @Test + public void testExactRef_IgnoresGarbageRef() throws IOException { + writeLooseRef("refs/heads/A", A); + write(new File(diskRepo.getDirectory(), "refs/heads/bad"), "FAIL\n"); + + Map refs = + refdir.exactRef("refs/heads/bad", "refs/heads/A"); + + assertNull("no refs/heads/bad", refs.get("refs/heads/bad")); + + Ref a = refs.get("refs/heads/A"); + assertEquals("refs/heads/A", a.getName()); + assertEquals(A, a.getObjectId()); + + assertEquals(1, refs.size()); + } + @Test public void testGetRefs_InvalidName() throws IOException { writeLooseRef("refs/heads/A", A); @@ -463,6 +490,21 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { assertEquals(B, b.getObjectId()); } + @Test + public void testFirstExactRef_Mixed() throws IOException { + writeLooseRef("refs/heads/A", A); + writePackedRef("refs/tags/v1.0", v1_0); + + Ref a = refdir.firstExactRef("refs/heads/A", "refs/tags/v1.0"); + Ref one = refdir.firstExactRef("refs/tags/v1.0", "refs/heads/A"); + + assertEquals("refs/heads/A", a.getName()); + assertEquals("refs/tags/v1.0", one.getName()); + + assertEquals(A, a.getObjectId()); + assertEquals(v1_0, one.getObjectId()); + } + @Test public void testGetRefs_TagsOnly_AllLoose() throws IOException { Map tags; 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 1a58c5138..fd99e4d03 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java @@ -47,6 +47,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -254,6 +255,55 @@ public abstract class RefDatabase { return null; } + /** + * Read the specified references. + *

+ * This method expects a list of unshortened reference names and returns + * a map from reference names to refs. Any named references that do not + * exist will not be included in the returned map. + * + * @param refs + * the unabbreviated names of references to look up. + * @return modifiable map describing any refs that exist among the ref + * ref names supplied. The map can be an unsorted map. + * @throws IOException + * the reference space cannot be accessed. + * @since 4.1 + */ + public Map exactRef(String... refs) throws IOException { + Map result = new HashMap<>(refs.length); + for (String name : refs) { + Ref ref = exactRef(name); + if (ref != null) { + result.put(name, ref); + } + } + return result; + } + + /** + * Find the first named reference. + *

+ * This method expects a list of unshortened reference names and returns + * the first that exists. + * + * @param refs + * the unabbreviated names of references to look up. + * @return the first named reference that exists (if any); else {@code null}. + * @throws IOException + * the reference space cannot be accessed. + * @since 4.1 + */ + public Ref firstExactRef(String... refs) throws IOException { + for (String name : refs) { + Ref ref = exactRef(name); + if (ref != null) { + return ref; + } + } + return null; + } + /** * Get a section of the reference namespace. *