Skip to content

Commit 2e6f310

Browse files
committed
Multi-threading commit hook leads to "Cannot lock .git/index" error
1 parent 06d77fd commit 2e6f310

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

core/src/main/java/com/cosium/code/format/git/GitStagedFiles.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,16 @@ public static GitStagedFiles read(Log log, Repository repository, Predicate<Path
5959
Stream.concat(gitStatus.getChanged().stream(), gitStatus.getAdded().stream())
6060
.filter(relativePath -> fileFilter.test(workTree.resolve(relativePath)))
6161
.collect(Collectors.toSet());
62-
log.debug("Staged files: " + filePaths.toString());
62+
log.debug("Staged files: " + filePaths);
6363
return new GitStagedFiles(log, repository, filePaths);
6464
}
6565

6666
public void format(CodeFormatters formatters) throws IOException {
67+
if (filePaths.isEmpty()) {
68+
log.debug("No staged files to format");
69+
return;
70+
}
71+
6772
Git git = new Git(repository);
6873

6974
try (Index index = Index.lock(repository);

core/src/main/java/com/cosium/code/format/git/Index.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package com.cosium.code.format.git;
22

3+
import java.io.File;
34
import java.io.IOException;
5+
import java.util.Map;
6+
import java.util.concurrent.ConcurrentHashMap;
7+
import java.util.concurrent.locks.Lock;
8+
import java.util.concurrent.locks.ReentrantLock;
49
import org.eclipse.jgit.dircache.DirCache;
510
import org.eclipse.jgit.dircache.DirCacheEditor;
611
import org.eclipse.jgit.dircache.DirCacheIterator;
@@ -12,10 +17,23 @@
1217
*/
1318
public class Index implements AutoCloseable {
1419

20+
private static final Map<File, Lock> GLOBAL_LOCK_BY_REPOSITORY_DIRECTORY =
21+
new ConcurrentHashMap<>();
22+
23+
private final Lock globalLock;
1524
private final DirCache dirCache;
1625

1726
private Index(Repository repository) throws IOException {
18-
dirCache = repository.lockDirCache();
27+
globalLock =
28+
GLOBAL_LOCK_BY_REPOSITORY_DIRECTORY.computeIfAbsent(
29+
repository.getDirectory(), repositoryDirectory -> new ReentrantLock());
30+
globalLock.lock();
31+
try {
32+
dirCache = repository.lockDirCache();
33+
} catch (RuntimeException e) {
34+
globalLock.unlock();
35+
throw e;
36+
}
1937
}
2038

2139
public static Index lock(Repository repository) throws IOException {
@@ -40,6 +58,10 @@ public AbstractTreeIterator treeIterator() {
4058

4159
@Override
4260
public void close() {
43-
dirCache.unlock();
61+
try {
62+
dirCache.unlock();
63+
} finally {
64+
globalLock.unlock();
65+
}
4466
}
4567
}

0 commit comments

Comments
 (0)