浏览代码

delete empty directories inside ./d/

Sebastian Stenzel 9 年之前
父节点
当前提交
293ac0ea3c

+ 19 - 19
main/filesystem-api/src/main/java/org/cryptomator/filesystem/FileSystemVisitor.java

@@ -12,7 +12,7 @@ import static java.lang.String.format;
 
 import java.util.function.Consumer;
 
-public class FileSystemVisitor {
+public class FolderVisitor {
 
 	private final Consumer<Folder> beforeFolderVisitor;
 	private final Consumer<Folder> afterFolderVisitor;
@@ -20,7 +20,7 @@ public class FileSystemVisitor {
 	private final Consumer<Node> nodeVisitor;
 	private final int maxDepth;
 
-	public FileSystemVisitor(FileSystemVisitorBuilder builder) {
+	public FolderVisitor(FolderVisitorBuilder builder) {
 		this.beforeFolderVisitor = builder.beforeFolderVisitor;
 		this.afterFolderVisitor = builder.afterFolderVisitor;
 		this.fileVisitor = builder.fileVisitor;
@@ -28,19 +28,19 @@ public class FileSystemVisitor {
 		this.maxDepth = builder.maxDepth;
 	}
 
-	public static FileSystemVisitorBuilder fileSystemVisitor() {
-		return new FileSystemVisitorBuilder();
+	public static FolderVisitorBuilder folderVisitor() {
+		return new FolderVisitorBuilder();
 	}
 
-	public FileSystemVisitor visit(Folder folder) {
+	public FolderVisitor visit(Folder folder) {
 		return visit(folder, 0);
 	}
 
-	public FileSystemVisitor visit(File file) {
+	public FolderVisitor visit(File file) {
 		return visit(file, 0);
 	}
 
-	private FileSystemVisitor visit(Folder folder, int depth) {
+	private FolderVisitor visit(Folder folder, int depth) {
 		beforeFolderVisitor.accept(folder);
 		nodeVisitor.accept(folder);
 		final int childDepth = depth + 1;
@@ -52,13 +52,13 @@ public class FileSystemVisitor {
 		return this;
 	}
 
-	private FileSystemVisitor visit(File file, int depth) {
+	private FolderVisitor visit(File file, int depth) {
 		nodeVisitor.accept(file);
 		fileVisitor.accept(file);
 		return this;
 	}
 
-	public static class FileSystemVisitorBuilder {
+	public static class FolderVisitorBuilder {
 
 		private Consumer<Folder> beforeFolderVisitor = noOp();
 		private Consumer<Folder> afterFolderVisitor = noOp();
@@ -66,10 +66,10 @@ public class FileSystemVisitor {
 		private Consumer<Node> nodeVisitor = noOp();
 		private int maxDepth = Integer.MAX_VALUE;
 
-		private FileSystemVisitorBuilder() {
+		private FolderVisitorBuilder() {
 		}
 
-		public FileSystemVisitorBuilder beforeFolder(Consumer<Folder> beforeFolderVisitor) {
+		public FolderVisitorBuilder beforeFolder(Consumer<Folder> beforeFolderVisitor) {
 			if (beforeFolderVisitor == null) {
 				throw new IllegalArgumentException("Vistior may not be null");
 			}
@@ -77,7 +77,7 @@ public class FileSystemVisitor {
 			return this;
 		}
 
-		public FileSystemVisitorBuilder afterFolder(Consumer<Folder> afterFolderVisitor) {
+		public FolderVisitorBuilder afterFolder(Consumer<Folder> afterFolderVisitor) {
 			if (afterFolderVisitor == null) {
 				throw new IllegalArgumentException("Vistior may not be null");
 			}
@@ -85,7 +85,7 @@ public class FileSystemVisitor {
 			return this;
 		}
 
-		public FileSystemVisitorBuilder forEachFile(Consumer<File> fileVisitor) {
+		public FolderVisitorBuilder forEachFile(Consumer<File> fileVisitor) {
 			if (fileVisitor == null) {
 				throw new IllegalArgumentException("Vistior may not be null");
 			}
@@ -93,7 +93,7 @@ public class FileSystemVisitor {
 			return this;
 		}
 
-		public FileSystemVisitorBuilder forEachNode(Consumer<Node> nodeVisitor) {
+		public FolderVisitorBuilder forEachNode(Consumer<Node> nodeVisitor) {
 			if (nodeVisitor == null) {
 				throw new IllegalArgumentException("Vistior may not be null");
 			}
@@ -101,7 +101,7 @@ public class FileSystemVisitor {
 			return this;
 		}
 
-		public FileSystemVisitorBuilder withMaxDepth(int maxDepth) {
+		public FolderVisitorBuilder withMaxDepth(int maxDepth) {
 			if (maxDepth < 0) {
 				throw new IllegalArgumentException(format("maxDepth must not be smaller 0 but was %d", maxDepth));
 			}
@@ -109,16 +109,16 @@ public class FileSystemVisitor {
 			return this;
 		}
 
-		public FileSystemVisitor visit(Folder folder) {
+		public FolderVisitor visit(Folder folder) {
 			return build().visit(folder);
 		}
 
-		public FileSystemVisitor visit(File file) {
+		public FolderVisitor visit(File file) {
 			return build().visit(file);
 		}
 
-		public FileSystemVisitor build() {
-			return new FileSystemVisitor(this);
+		public FolderVisitor build() {
+			return new FolderVisitor(this);
 		}
 
 		private static <T> Consumer<T> noOp() {

+ 7 - 2
main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java

@@ -160,8 +160,8 @@ class CryptoFolder extends CryptoNode implements Folder {
 		assert target.parent().isPresent() : "Target can not be root, thus has a parent";
 
 		// prepare target:
-		target.parent().get().create();
 		target.delete();
+		target.parent().get().create();
 
 		// perform the actual move:
 		final File dirFile = forceGetPhysicalFile();
@@ -186,7 +186,12 @@ class CryptoFolder extends CryptoNode implements Folder {
 			return;
 		}
 		Deleter.deleteContent(this);
-		forceGetPhysicalFolder().delete();
+		Folder physicalFolder = forceGetPhysicalFolder();
+		physicalFolder.delete();
+		Folder physicalFolderParent = physicalFolder.parent().get();
+		if (physicalFolderParent.folders().count() == 0) {
+			physicalFolderParent.delete();
+		}
 		forceGetPhysicalFile().delete();
 		invalidateDirectoryIdsRecursively();
 	}

+ 23 - 19
main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemTest.java

@@ -8,14 +8,15 @@
  *******************************************************************************/
 package org.cryptomator.filesystem.crypto;
 
-import static org.cryptomator.filesystem.FileSystemVisitor.fileSystemVisitor;
+import static org.hamcrest.Matchers.both;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.lessThanOrEqualTo;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.nio.ByteBuffer;
 import java.time.Instant;
 import java.util.Arrays;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import org.cryptomator.crypto.engine.Cryptor;
 import org.cryptomator.crypto.engine.NoCryptor;
@@ -37,7 +38,6 @@ public class CryptoFileSystemTest {
 		final FileSystem physicalFs = new InMemoryFileSystem();
 		final Folder physicalDataRoot = physicalFs.folder("d");
 		final FileSystem fs = new CryptoFileSystem(physicalFs, cryptor, Mockito.mock(CryptoFileSystemDelegate.class), "foo");
-		fs.create();
 
 		// add another encrypted folder:
 		final Folder fooFolder = fs.folder("foo");
@@ -47,8 +47,24 @@ public class CryptoFileSystemTest {
 		fooBarFolder.create();
 		Assert.assertTrue(fooFolder.exists());
 		Assert.assertTrue(fooBarFolder.exists());
-		Assert.assertEquals(3, countDataFolders(physicalDataRoot)); // parent +
-																	// foo + bar
+		Assert.assertEquals(3, countDataFolders(physicalDataRoot)); // parent + foo + bar
+	}
+
+	@Test(timeout = 1000)
+	public void testDirectoryDeletion() throws UncheckedIOException, IOException {
+		// mock stuff and prepare crypto FS:
+		final Cryptor cryptor = new NoCryptor();
+		final FileSystem physicalFs = new InMemoryFileSystem();
+		final Folder physicalDataRoot = physicalFs.folder("d");
+		final FileSystem fs = new CryptoFileSystem(physicalFs, cryptor, Mockito.mock(CryptoFileSystemDelegate.class), "foo");
+
+		// create and delete folders:
+		fs.folder("foo").folder("bar").folder("baz").create();
+		Assert.assertEquals(4, countDataFolders(physicalDataRoot)); // root + foo + bar + baz
+		Assert.assertThat(physicalDataRoot.folders().count(), both(greaterThanOrEqualTo(1l)).and(lessThanOrEqualTo(4l))); // parent folders of the 4 folders
+		fs.folder("foo").delete();
+		Assert.assertEquals(1, countDataFolders(physicalDataRoot)); // just root
+		Assert.assertEquals(1, physicalDataRoot.folders().count()); // just the parent of root
 	}
 
 	@Test(timeout = 2000)
@@ -204,22 +220,10 @@ public class CryptoFileSystemTest {
 	}
 
 	/**
-	 * @return number of folders on second level inside the given dataRoot
-	 *         folder.
+	 * @return number of folders on second level inside the given dataRoot folder.
 	 */
 	private static int countDataFolders(Folder dataRoot) {
-		final AtomicInteger num = new AtomicInteger();
-		fileSystemVisitor() //
-				.afterFolder(folder -> {
-					final Folder parent = folder.parent().get();
-					final Folder parentOfParent = parent.parent().orElse(null);
-					if (parentOfParent != null && parentOfParent.equals(dataRoot)) {
-						num.incrementAndGet();
-					}
-				}) //
-				.withMaxDepth(2) //
-				.visit(dataRoot);
-		return num.get();
+		return (int) dataRoot.folders().flatMap(Folder::folders).count();
 	}
 
 }