]> source.dussan.org Git - jgit.git/commitdiff
Fix GarbageCollection not to pack HEAD 25/23925/1
authorChristian Halstrick <christian.halstrick@sap.com>
Wed, 26 Mar 2014 14:27:48 +0000 (15:27 +0100)
committerChristian Halstrick <christian.halstrick@sap.com>
Wed, 26 Mar 2014 14:27:48 +0000 (15:27 +0100)
When working on a non-bare repository with a detached HEAD jgit's GC was
packing the ref named "HEAD" into the packed-refs file and deleted the
loose ref (the file .git/HEAD!). This made the repo unusable for native
git. This is fixed by telling jgit to only pack refs starting from
"refs/"

Change-Id: I50018aa006f18b244d2cae2ff78b5ffe1b821d63

org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java

index 0ade902601aa2501a2ad25d95a34e00e6daa5e9d..c7336da4081463880d7fc3bcfd3638da9d612064 100644 (file)
@@ -45,6 +45,7 @@ package org.eclipse.jgit.internal.storage.file;
 
 import static java.lang.Integer.valueOf;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 
 import java.io.File;
@@ -57,10 +58,16 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.Ref.Storage;
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.RefUpdate.Result;
 import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
 import org.junit.Test;
 
 public class GcPackRefsTest extends GcTestCase {
@@ -177,4 +184,65 @@ public class GcPackRefsTest extends GcTestCase {
 
                assertEquals(repo.getRef("refs/tags/t").getObjectId(), b);
        }
+
+       @Test
+       public void dontPackHEAD_nonBare() throws Exception {
+               BranchBuilder bb = tr.branch("refs/heads/side");
+               RevCommit first = bb.commit().add("A", "A").add("B", "B").create();
+               bb.commit().add("A", "A2").add("B", "B2").create();
+               Git git = Git.wrap(repo);
+
+               // check for the unborn branch master. HEAD should point to master and
+               // master doesn't exist.
+               assertEquals(repo.getRef("HEAD").getTarget().getName(),
+                               "refs/heads/master");
+               assertNull(repo.getRef("HEAD").getTarget().getObjectId());
+               gc.packRefs();
+               assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE);
+               assertEquals(repo.getRef("HEAD").getTarget().getName(),
+                               "refs/heads/master");
+               assertNull(repo.getRef("HEAD").getTarget().getObjectId());
+
+               git.checkout().setName("refs/heads/side").call();
+               gc.packRefs();
+               assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE);
+
+               // check for detached HEAD
+               git.checkout().setName(first.getName()).call();
+               gc.packRefs();
+               assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE);
+       }
+
+       @Test
+       public void dontPackHEAD_bare() throws Exception {
+               BranchBuilder bb = tr.branch("refs/heads/side");
+               bb.commit().add("A", "A").add("B", "B").create();
+               RevCommit second = bb.commit().add("A", "A2").add("B", "B2").create();
+
+               // Convert the repo to be bare
+               FileBasedConfig cfg = repo.getConfig();
+               cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
+                               ConfigConstants.CONFIG_KEY_BARE, true);
+               cfg.save();
+               Git git = Git.open(repo.getDirectory());
+               repo = (FileRepository) git.getRepository();
+
+               // check for the unborn branch master. HEAD should point to master and
+               // master doesn't exist.
+               assertEquals(repo.getRef("HEAD").getTarget().getName(),
+                               "refs/heads/master");
+               assertNull(repo.getRef("HEAD").getTarget().getObjectId());
+               gc.packRefs();
+               assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE);
+               assertEquals(repo.getRef("HEAD").getTarget().getName(),
+                               "refs/heads/master");
+               assertNull(repo.getRef("HEAD").getTarget().getObjectId());
+
+               // check for non-detached HEAD
+               repo.updateRef(Constants.HEAD).link("refs/heads/side");
+               gc.packRefs();
+               assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE);
+               assertEquals(repo.getRef("HEAD").getTarget().getObjectId(),
+                               second.getId());
+       }
 }
index 6c19b7b7f80189340ac25496f8020c8f0592c2cc..3cc4e7b97b7c69a1db3f22dfea424d4cd8321f0e 100644 (file)
@@ -481,7 +481,7 @@ public class GC {
         * @throws IOException
         */
        public void packRefs() throws IOException {
-               Collection<Ref> refs = repo.getRefDatabase().getRefs(ALL).values();
+               Collection<Ref> refs = repo.getRefDatabase().getRefs(Constants.R_REFS).values();
                List<String> refsToBePacked = new ArrayList<String>(refs.size());
                pm.beginTask(JGitText.get().packRefs, refs.size());
                try {