Merge "Add cooperative cancellation to RevWalk traversal"
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 4dc40df..79f2013 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
@@ -1533,6 +1533,25 @@ public void testCommonRefPrefix() {
StringUtils.commonPrefix("refs/heads/", "refs/heads/main"));
}
+ @Test
+ public void testPackDoesNotUnlockHeldLocks() throws IOException {
+ String ref = "refs/heads/master";
+ writeLooseRef(ref, A);
+
+ File refFile = refdir.fileFor(ref);
+ LockFile held = new LockFile(refFile);
+ assertTrue("must acquire lock", held.lock());
+ try {
+ refdir.pack(Map.of(ref, held));
+ assertFalse("loose ref must be deleted after packing",
+ refFile.exists());
+ assertTrue("held lock must still be locked after pack()",
+ held.isLocked());
+ } finally {
+ held.unlock();
+ }
+ }
+
void writePackedRef(String name, AnyObjectId id) throws IOException {
writePackedRefs(id.name() + " " + name + "\n");
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java
index f33fe0b..cd03600 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java
@@ -146,20 +146,15 @@ public void execute(RevWalk walk, ProgressMonitor monitor,
return;
}
- // Pack refs normally, so we can create lock files even in the case where
- // refs/x is deleted and refs/x/y is created in this batch.
- try {
- refdb.pack(
- pending.stream().map(ReceiveCommand::getRefName).collect(toList()));
- } catch (LockFailedException e) {
- lockFailure(pending.get(0), pending);
- return;
- }
-
Map<String, LockFile> locks = null;
LockFile packedRefsLock = null;
refdb.inProcessPackedRefsLock.lock();
try {
+ // Pack refs normally, so we can create lock files even in the case
+ // where refs/x is deleted and refs/x/y is created in this batch.
+ refdb.pack(pending.stream().map(ReceiveCommand::getRefName)
+ .collect(toList()));
+
// During clone locking isn't needed since no refs exist yet.
// This also helps to avoid problems with refs only differing in
// case on a case insensitive filesystem (bug 528497)
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 a9211fe..d5ac5aa 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
@@ -876,8 +876,13 @@ private void pack(Collection<String> refs,
}
newLoose = curLoose.remove(idx);
} while (!looseRefs.compareAndSet(curLoose, newLoose));
- int levels = levelsIn(refName) - 2;
- deleteAndUnlock(refFile, levels, rLck);
+ if (shouldUnlock) {
+ int levels = levelsIn(refName) - 2;
+ deleteAndUnlock(refFile, levels, rLck);
+ shouldUnlock = false;
+ } else {
+ delete(refFile);
+ }
LOG.debug(JGitText.get().deleteLooseRef, refFile, clr_oid);
}
} finally {