Merge "PackedBatchRefUpdate: hold inProcessPackedRefsLock across pack step"
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/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 {