Browse Source

Fix GarbageCollection not to pack HEAD

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
stable-3.4
Christian Halstrick 11 years ago
parent
commit
16436ef6d9
  1. 68
      org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java
  2. 2
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java

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

@ -45,6 +45,7 @@ package org.eclipse.jgit.internal.storage.file;
import static java.lang.Integer.valueOf; import static java.lang.Integer.valueOf;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame; import static org.junit.Assert.assertSame;
import java.io.File; import java.io.File;
@ -57,10 +58,16 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; 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.Ref.Storage;
import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result; import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.junit.Test; import org.junit.Test;
public class GcPackRefsTest extends GcTestCase { public class GcPackRefsTest extends GcTestCase {
@ -177,4 +184,65 @@ public class GcPackRefsTest extends GcTestCase {
assertEquals(repo.getRef("refs/tags/t").getObjectId(), b); 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());
}
} }

2
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java

@ -481,7 +481,7 @@ public class GC {
* @throws IOException * @throws IOException
*/ */
public void packRefs() 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()); List<String> refsToBePacked = new ArrayList<String>(refs.size());
pm.beginTask(JGitText.get().packRefs, refs.size()); pm.beginTask(JGitText.get().packRefs, refs.size());
try { try {

Loading…
Cancel
Save