Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Nieder2015-11-10 23:11:04 +0000
committerJonathan Nieder2015-11-11 18:56:39 +0000
commit797f94d3319a6bea2cacce707a6a5ee67f00ea17 (patch)
tree8d4a7746dc06ae7f034cb6f38ee49013a74651de
parentee66914e410a258d8d8acd877a97f9152e2c1a41 (diff)
downloadjgit-797f94d3319a6bea2cacce707a6a5ee67f00ea17.tar.gz
jgit-797f94d3319a6bea2cacce707a6a5ee67f00ea17.tar.xz
jgit-797f94d3319a6bea2cacce707a6a5ee67f00ea17.zip
RefDirectory.exactRef: Do not ignore symrefs to unborn branch
When asked to read a symref pointing to a branch-yet-to-be-born (such as HEAD in a newly initialized repository), DfsRepository and FileRepository return different results. FileRepository: exactRef("HEAD") => null DfsRepository: exactRef("HEAD") => SymbolicRef[HEAD -> refs/heads/master=00000000] getRef("HEAD") returns the same as DfsRepository's exactRef in both backends. The intended behavior is the DfsRepository one: exactRef() is supposed to be like getRef(), but more exact because it doesn't need to traverse the search path. The discrepancy is because DfsRefDatabase implements exactRef() directly with the intended semantics, while RefDirectory uses a fallback implementation built on top of getRefs(). getRefs() skips symrefs to an unborn branch. Override the fallback implementation with a correct implementation that is similar to getRef() to avoid this. A followup change will fix the fallback. Change-Id: Ic138a5564a099ebf32248d86b93e2de9ab3c94ee Reported-by: David Pursehouse <david.pursehouse@sonymobile.com> Improved-by: Christian Halstrick <christian.halstrick@sap.com> Bug: 478865
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java19
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java24
2 files changed, 43 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 0991598920..d66753da08 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
@@ -1025,6 +1025,25 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase {
}
@Test
+ public void testExactRef_EmptyDatabase() throws IOException {
+ Ref r;
+
+ r = refdir.exactRef(HEAD);
+ assertTrue(r.isSymbolic());
+ assertSame(LOOSE, r.getStorage());
+ assertEquals("refs/heads/master", r.getTarget().getName());
+ assertSame(NEW, r.getTarget().getStorage());
+ assertNull(r.getTarget().getObjectId());
+
+ assertNull(refdir.exactRef("refs/heads/master"));
+ assertNull(refdir.exactRef("refs/tags/v1.0"));
+ assertNull(refdir.exactRef("FETCH_HEAD"));
+ assertNull(refdir.exactRef("NOT.A.REF.NAME"));
+ assertNull(refdir.exactRef("master"));
+ assertNull(refdir.exactRef("v1.0"));
+ }
+
+ @Test
public void testGetRef_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
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
index 6a04a538ef..bb5b044405 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
@@ -262,6 +262,30 @@ public class RefDirectory extends RefDatabase {
}
@Override
+ public Ref exactRef(String name) throws IOException {
+ RefList<Ref> packed = getPackedRefs();
+ Ref ref;
+ try {
+ ref = readRef(name, packed);
+ if (ref != null) {
+ ref = resolve(ref, 0, null, null, packed);
+ }
+ } catch (IOException e) {
+ if (name.contains("/") //$NON-NLS-1$
+ || !(e.getCause() instanceof InvalidObjectIdException)) {
+ throw e;
+ }
+
+ // While looking for a ref outside of refs/ (e.g., 'config'), we
+ // found a non-ref file (e.g., a config file) instead. Treat this
+ // as a ref-not-found condition.
+ ref = null;
+ }
+ fireRefsChanged();
+ return ref;
+ }
+
+ @Override
public Ref getRef(final String needle) throws IOException {
final RefList<Ref> packed = getPackedRefs();
Ref ref = null;

Back to the top