Tidy up FilesystemDeleteHandler * Inline one-time use variables * Remove final from method parameters * Rename, reorder and extract additional methods to improve readability * Use Guava's MoreFiles.deleteRecursively instead of Path walkers Change-Id: I3808c3e78e3a572c158a88abe8cb77d3f2168b6e
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/FilesystemDeleteHandler.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/FilesystemDeleteHandler.java index 2989449..c19538c 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/FilesystemDeleteHandler.java +++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/FilesystemDeleteHandler.java
@@ -14,6 +14,7 @@ package com.googlesource.gerrit.plugins.deleteproject.fs; +import com.google.common.io.MoreFiles; import com.google.gerrit.extensions.api.changes.NotifyHandling; import com.google.gerrit.extensions.events.ProjectDeletedListener; import com.google.gerrit.extensions.registration.DynamicSet; @@ -23,13 +24,10 @@ import com.googlesource.gerrit.plugins.deleteproject.TimeMachine; import java.io.File; import java.io.IOException; -import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryCache; @@ -53,38 +51,63 @@ throws IOException, RepositoryNotFoundException { // Remove from the jgit cache Repository repository = repoManager.openRepository(project.getNameKey()); - File repoFile = repository.getDirectory(); cleanCache(repository); if (!preserveGitRepository) { - deleteGitRepository(project.getNameKey(), repoFile); + deleteGitRepository(project.getNameKey(), repository.getDirectory()); } } + private void cleanCache(Repository repository) { + repository.close(); + RepositoryCache.close(repository); + } + private void deleteGitRepository(final Project.NameKey project, final File repoFile) throws IOException { // Delete the repository from disk Path basePath = getBasePath(repoFile.toPath(), project); Path trash = moveToTrash(repoFile.toPath(), basePath, project); - boolean ok = false; try { - recursiveDelete(trash); - ok = true; + MoreFiles.deleteRecursively(trash); + recursivelyDeleteEmptyParents(repoFile.getParentFile(), basePath.toFile()); } catch (IOException e) { // Only log if delete failed - repo already moved to trash. - // Otherwise, listeners are never called. - log.warn("Error trying to delete {}", trash, e); + log.warn("Error trying to delete {} or its parents", trash, e); + } finally { + sendProjectDeletedEvent(project); } + } - // Delete parent folders if they are (now) empty - if (ok) { - try { - recursiveDeleteParent(repoFile.getParentFile(), basePath.toFile()); - } catch (IOException e) { - log.warn("Couldn't delete (empty) parents of {}", repoFile, e); - } + private Path getBasePath(Path repo, Project.NameKey project) { + Path projectPath = Paths.get(project.get()); + return repo.getRoot() + .resolve(repo.subpath(0, repo.getNameCount() - projectPath.getNameCount())); + } + + private Path moveToTrash(Path directory, Path basePath, Project.NameKey nameKey) + throws IOException { + Path trashRepo = + basePath.resolve(nameKey.get() + "." + TimeMachine.now().toEpochMilli() + ".%deleted%.git"); + return Files.move(directory, trashRepo, StandardCopyOption.ATOMIC_MOVE); + } + + /** + * Recursively delete the specified file and its parent files until we hit the file {@code Until} + * or the parent file is populated. This is used when we have a tree structure such as a/b/c/d.git + * and a/b/e.git - if we delete a/b/c/d.git, we no longer need a/b/c/. + */ + private void recursivelyDeleteEmptyParents(File file, File until) throws IOException { + if (file.equals(until)) { + return; } + if (file.listFiles().length == 0) { + File parent = file.getParentFile(); + Files.delete(file.toPath()); + recursivelyDeleteEmptyParents(parent, until); + } + } - // Send an event that the repository was deleted + private void sendProjectDeletedEvent(Project.NameKey project) { ProjectDeletedListener.Event event = new ProjectDeletedListener.Event() { @Override @@ -105,65 +128,4 @@ } } } - - private Path getBasePath(Path repo, Project.NameKey project) { - Path projectPath = Paths.get(project.get()); - return repo.getRoot() - .resolve(repo.subpath(0, repo.getNameCount() - projectPath.getNameCount())); - } - - private Path moveToTrash(Path directory, Path basePath, Project.NameKey nameKey) - throws IOException { - Path trashRepo = - basePath.resolve(nameKey.get() + "." + TimeMachine.now().toEpochMilli() + ".%deleted%.git"); - return Files.move(directory, trashRepo, StandardCopyOption.ATOMIC_MOVE); - } - - private void cleanCache(final Repository repository) { - repository.close(); - RepositoryCache.close(repository); - } - - /** - * Recursively delete the specified file and all of its contents. - * - * @throws IOException - */ - private void recursiveDelete(Path file) throws IOException { - Files.walkFileTree( - file, - new SimpleFileVisitor<Path>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { - if (e != null) { - throw e; - } - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - }); - } - - /** - * Recursively delete the specified file and its parent files until we hit the file {@code Until} - * or the parent file is populated. This is used when we have a tree structure such as a/b/c/d.git - * and a/b/e.git - if we delete a/b/c/d.git, we no longer need a/b/c/. - */ - private void recursiveDeleteParent(File file, File until) throws IOException { - if (file.equals(until)) { - return; - } - if (file.listFiles().length == 0) { - File parent = file.getParentFile(); - Files.delete(file.toPath()); - recursiveDeleteParent(parent, until); - } - } }