Browse Source

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
stable-4.1
Jonathan Nieder 9 years ago
parent
commit
797f94d331
  1. 19
      org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
  2. 24
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java

19
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java

@ -1024,6 +1024,25 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase {
assertNull(refdir.getRef("v1.0")); assertNull(refdir.getRef("v1.0"));
} }
@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 @Test
public void testGetRef_FetchHead() throws IOException { public void testGetRef_FetchHead() throws IOException {
// This is an odd special case where we need to make sure we read // This is an odd special case where we need to make sure we read

24
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java

@ -261,6 +261,30 @@ public class RefDirectory extends RefDatabase {
return loose; return loose;
} }
@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 @Override
public Ref getRef(final String needle) throws IOException { public Ref getRef(final String needle) throws IOException {
final RefList<Ref> packed = getPackedRefs(); final RefList<Ref> packed = getPackedRefs();

Loading…
Cancel
Save