Merge branch 'stable-4.6'

* stable-4.6:
  GC: delete empty directories after purging loose objects
  GC.prune(Set<ObjectId>): return early if objects directory is empty

Change-Id: I3d6cacf80d3b4c69ba108e970855963bd9f6ee78
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
This commit is contained in:
Matthias Sohn 2017-02-02 23:36:28 +01:00
commit 566794d001
1 changed files with 41 additions and 31 deletions

View File

@ -455,47 +455,50 @@ public void prune(Set<ObjectId> objectsToKeep) throws IOException,
Set<ObjectId> indexObjects = null; Set<ObjectId> indexObjects = null;
File objects = repo.getObjectsDirectory(); File objects = repo.getObjectsDirectory();
String[] fanout = objects.list(); String[] fanout = objects.list();
if (fanout != null && fanout.length > 0) { if (fanout == null || fanout.length == 0) {
pm.beginTask(JGitText.get().pruneLooseUnreferencedObjects, return;
fanout.length); }
try { pm.beginTask(JGitText.get().pruneLooseUnreferencedObjects,
for (String d : fanout) { fanout.length);
try {
for (String d : fanout) {
checkCancelled();
pm.update(1);
if (d.length() != 2)
continue;
File[] entries = new File(objects, d).listFiles();
if (entries == null)
continue;
for (File f : entries) {
checkCancelled(); checkCancelled();
pm.update(1); String fName = f.getName();
if (d.length() != 2) if (fName.length() != Constants.OBJECT_ID_STRING_LENGTH - 2)
continue; continue;
File[] entries = new File(objects, d).listFiles(); if (repo.getFS().lastModified(f) >= expireDate)
if (entries == null)
continue; continue;
for (File f : entries) { try {
checkCancelled(); ObjectId id = ObjectId.fromString(d + fName);
String fName = f.getName(); if (objectsToKeep.contains(id))
if (fName.length() != Constants.OBJECT_ID_STRING_LENGTH - 2)
continue; continue;
if (repo.getFS().lastModified(f) >= expireDate) if (indexObjects == null)
indexObjects = listNonHEADIndexObjects();
if (indexObjects.contains(id))
continue; continue;
try { deletionCandidates.put(id, f);
ObjectId id = ObjectId.fromString(d + fName); } catch (IllegalArgumentException notAnObject) {
if (objectsToKeep.contains(id)) // ignoring the file that does not represent loose
continue; // object
if (indexObjects == null) continue;
indexObjects = listNonHEADIndexObjects();
if (indexObjects.contains(id))
continue;
deletionCandidates.put(id, f);
} catch (IllegalArgumentException notAnObject) {
// ignoring the file that does not represent loose
// object
continue;
}
} }
} }
} finally {
pm.endTask();
} }
} finally {
pm.endTask();
} }
if (deletionCandidates.isEmpty())
if (deletionCandidates.isEmpty()) {
return; return;
}
checkCancelled(); checkCancelled();
@ -576,12 +579,19 @@ public void prune(Set<ObjectId> objectsToKeep) throws IOException,
// loose objects. Make a last check, though, to avoid deleting objects // loose objects. Make a last check, though, to avoid deleting objects
// that could have been referenced while the candidates list was being // that could have been referenced while the candidates list was being
// built (by an incoming push, for example). // built (by an incoming push, for example).
Set<File> touchedFanout = new HashSet<>();
for (File f : deletionCandidates.values()) { for (File f : deletionCandidates.values()) {
if (f.lastModified() < expireDate) { if (f.lastModified() < expireDate) {
f.delete(); f.delete();
touchedFanout.add(f.getParentFile());
} }
} }
for (File f : touchedFanout) {
FileUtils.delete(f,
FileUtils.EMPTY_DIRECTORIES_ONLY | FileUtils.IGNORE_ERRORS);
}
repo.getObjectDatabase().close(); repo.getObjectDatabase().close();
} }