in git-server/src/main/java/jetbrains/buildServer/buildTriggers/vcs/git/Cleanup.java [224:306]
private void runGcInCopy(@NotNull File originalRepo) {
Lock rmLock = myRepositoryManager.getRmLock(originalRepo).readLock();
rmLock.lock();
File gcRepo;
try {
if (!isGcNeeded(originalRepo)) {
CLEANUP.debug("[" + originalRepo.getName() + "] no git gc is needed");
myGcErrors.clearError(originalRepo);
return;
}
try {
gcRepo = setupGcRepo(originalRepo);
} catch (Exception e) {
myGcErrors.registerError(originalRepo, "Failed to create temporary repository for garbage collection", e);
CLEANUP.warnAndDebugDetails("Failed to create temporary repository for garbage collection, original repository: " + originalRepo.getAbsolutePath(), e);
return;
}
CLEANUP.info("[" + originalRepo.getName() + "] run git gc in dedicated dir [" + gcRepo.getName() + "]");
try {
repack(gcRepo);
packRefs(gcRepo);
} catch (Exception e) {
myGcErrors.registerError(originalRepo, "Error while running garbage collection", e);
CLEANUP.warnAndDebugDetails("Error while running garbage collection in " + originalRepo.getAbsolutePath(), e);
FileUtil.delete(gcRepo);
return;
}
} finally {
rmLock.unlock();
}
//remove alternates pointing to the original repo before swapping repositories
FileUtil.delete(new File(gcRepo, "objects/info/alternates"));
long swapStart = System.currentTimeMillis();
File oldDir;
try {
oldDir = createTempDir(originalRepo.getParentFile(), originalRepo.getName() + ".old");
FileUtil.delete(oldDir);
} catch (Exception e) {
myGcErrors.registerError(originalRepo, "Error while creating temporary directory", e);
CLEANUP.warnAndDebugDetails("Error while creating temporary directory for " + originalRepo.getAbsolutePath(), e);
FileUtil.delete(gcRepo);
return;
}
//swap repositories with write rm lock which guarantees no one uses the original repository
Lock rmWriteLock = myRepositoryManager.getRmLock(originalRepo).writeLock();
long lockStart = System.currentTimeMillis();
rmWriteLock.lock();
long lockDuration = System.currentTimeMillis() - lockStart;
try {
if (!renameDir(originalRepo, oldDir, 5)) {
myGcErrors.registerError(originalRepo, "Failed to rename " + originalRepo.getName() + " to " + oldDir.getName());
CLEANUP.warn("Failed to rename " + originalRepo.getName() + " to " + oldDir.getName() + " after several attempts");
return;
}
if (!renameDir(gcRepo, originalRepo, 5)) {
myGcErrors.registerError(originalRepo, "Failed to rename " + gcRepo.getName() + " to " + originalRepo.getName());
CLEANUP.warn("Failed to rename " + gcRepo.getName() + " to " + originalRepo.getName() + " after several attempts, will try restoring old repository");
if (!oldDir.renameTo(originalRepo)) {
CLEANUP.warn("Failed to rename " + oldDir.getName() + " to " + originalRepo.getName());
}
return;
}
} finally {
rmWriteLock.unlock();
FileUtil.delete(oldDir);
FileUtil.delete(gcRepo);
}
long swapDuration = System.currentTimeMillis() - swapStart;
if (swapDuration > TimeUnit.SECONDS.toMillis(5)) {
String msg = "[" + originalRepo.getName() + "] swap with compacted repository finished in " + swapDuration + "ms";
if (lockDuration > TimeUnit.SECONDS.toMillis(1)) {
msg += " (lock acquired in " + lockDuration + "ms)";
}
CLEANUP.info(msg);
}
myGcErrors.clearError(originalRepo);
}