Initial implementations
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -40,3 +40,6 @@ bin/
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Mac OS ###
 | 
					### Mac OS ###
 | 
				
			||||||
.DS_Store
 | 
					.DS_Store
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Custom ###
 | 
				
			||||||
 | 
					_tmp/
 | 
				
			||||||
							
								
								
									
										1
									
								
								.idea/gradle.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								.idea/gradle.xml
									
									
									
										generated
									
									
									
								
							@@ -1,5 +1,6 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
<project version="4">
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="GradleMigrationSettings" migrationVersion="1" />
 | 
				
			||||||
  <component name="GradleSettings">
 | 
					  <component name="GradleSettings">
 | 
				
			||||||
    <option name="linkedExternalProjectsSettings">
 | 
					    <option name="linkedExternalProjectsSettings">
 | 
				
			||||||
      <GradleProjectSettings>
 | 
					      <GradleProjectSettings>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
				
			|||||||
  <component name="FrameworkDetectionExcludesConfiguration">
 | 
					  <component name="FrameworkDetectionExcludesConfiguration">
 | 
				
			||||||
    <file type="web" url="file://$PROJECT_DIR$" />
 | 
					    <file type="web" url="file://$PROJECT_DIR$" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="corretto-19" project-jdk-type="JavaSDK">
 | 
					  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="corretto-19" project-jdk-type="JavaSDK">
 | 
				
			||||||
    <output url="file://$PROJECT_DIR$/out" />
 | 
					    <output url="file://$PROJECT_DIR$/out" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
</project>
 | 
					</project>
 | 
				
			||||||
@@ -18,5 +18,5 @@ tasks.test {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kotlin {
 | 
					kotlin {
 | 
				
			||||||
    jvmToolchain(8)
 | 
					    jvmToolchain(11)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,9 +1,13 @@
 | 
				
			|||||||
package filesystem
 | 
					package filesystem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.nio.file.FileAlreadyExistsException
 | 
				
			||||||
 | 
					import java.nio.file.FileSystemException
 | 
				
			||||||
import java.nio.file.Files
 | 
					import java.nio.file.Files
 | 
				
			||||||
import java.nio.file.Path
 | 
					import java.nio.file.Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FSCreator {
 | 
					class FSCreator {
 | 
				
			||||||
 | 
					    // Create entry, leaving existing folders' contents, but overwriting existing files.
 | 
				
			||||||
 | 
					    @Throws(FileSystemException::class)
 | 
				
			||||||
    fun create(entryToCreate: FSEntry, destination: String) {
 | 
					    fun create(entryToCreate: FSEntry, destination: String) {
 | 
				
			||||||
        val queue = ArrayDeque<Pair<FSEntry, Path>>()
 | 
					        val queue = ArrayDeque<Pair<FSEntry, Path>>()
 | 
				
			||||||
        queue.add(entryToCreate to Path.of(destination))
 | 
					        queue.add(entryToCreate to Path.of(destination))
 | 
				
			||||||
@@ -17,8 +21,9 @@ class FSCreator {
 | 
				
			|||||||
                    is FSFolder -> Files.createDirectory(path)
 | 
					                    is FSFolder -> Files.createDirectory(path)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } catch (_: FileAlreadyExistsException) {} // Allow files/folders to already exist.
 | 
					            } catch (_: FileAlreadyExistsException) {} // Allow files/folders to already exist.
 | 
				
			||||||
            if (entry is FSFolder) {
 | 
					            when (entry) {
 | 
				
			||||||
                queue.addAll(entry.entries.map { it to path })
 | 
					                is FSFile -> Files.write(path, entry.content.toByteArray())
 | 
				
			||||||
 | 
					                is FSFolder -> queue.addAll(entry.entries.map { it to path })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										103
									
								
								src/test/kotlin/filesystem/FSCreatorTest.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/test/kotlin/filesystem/FSCreatorTest.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					package filesystem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.*
 | 
				
			||||||
 | 
					import java.nio.file.FileSystemException
 | 
				
			||||||
 | 
					import java.nio.file.Files
 | 
				
			||||||
 | 
					import java.nio.file.Path
 | 
				
			||||||
 | 
					import java.util.concurrent.TimeUnit
 | 
				
			||||||
 | 
					import kotlin.test.Test
 | 
				
			||||||
 | 
					import kotlin.test.assertEquals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FSCreatorTest {
 | 
				
			||||||
 | 
					    private val creator = FSCreator()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @BeforeEach
 | 
				
			||||||
 | 
					    fun `before each`() {
 | 
				
			||||||
 | 
					        assertDoesNotThrow("should create _tmp directory") {
 | 
				
			||||||
 | 
					            Files.createDirectory(Path.of("_tmp"))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @AfterEach
 | 
				
			||||||
 | 
					    fun `after each`() {
 | 
				
			||||||
 | 
					        assertDoesNotThrow("should delete _tmp directory") {
 | 
				
			||||||
 | 
					            deleteRecursive(Path.of("_tmp"))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun `create entries`() {
 | 
				
			||||||
 | 
					        val readme = FSFile("README", "Hello World!")
 | 
				
			||||||
 | 
					        val gomod = FSFile("go.mod", "module example.com/hello-world\n\ngo1.21.5")
 | 
				
			||||||
 | 
					        val maingo = FSFile("main.go", "package main\n\nimport \"example.com/hello-world/utils\"\n\n" +
 | 
				
			||||||
 | 
					            "func main() {\n\tprintln(\"Hello World!\")\n}")
 | 
				
			||||||
 | 
					        val helloworldgo = FSFile("hello-world.go", "package utils\n\nfunc PrintHelloWorld() {\n" +
 | 
				
			||||||
 | 
					            "\tprintln(\"Hello World!\")\n}")
 | 
				
			||||||
 | 
					        assertDoesNotThrow("should create entries") {
 | 
				
			||||||
 | 
					            creator.create(FSFolder("folder", listOf(
 | 
				
			||||||
 | 
					                readme,
 | 
				
			||||||
 | 
					                gomod,
 | 
				
			||||||
 | 
					                maingo,
 | 
				
			||||||
 | 
					                FSFolder("utils", listOf(
 | 
				
			||||||
 | 
					                    helloworldgo
 | 
				
			||||||
 | 
					                ))
 | 
				
			||||||
 | 
					            )), "_tmp")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // If objects don't exist, these functions will throw anyway, so don't explicitly check for existence.
 | 
				
			||||||
 | 
					        // Similarly, don't explicitly check if an object is a directory.
 | 
				
			||||||
 | 
					        assertEquals(readme.content, Files.readString(Path.of("_tmp/folder", readme.name)))
 | 
				
			||||||
 | 
					        assertEquals(gomod.content, Files.readString(Path.of("_tmp/folder", gomod.name)))
 | 
				
			||||||
 | 
					        assertEquals(maingo.content, Files.readString(Path.of("_tmp/folder", maingo.name)))
 | 
				
			||||||
 | 
					        assertEquals(helloworldgo.content, Files.readString(Path.of("_tmp/folder/utils", helloworldgo.name)))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun `create existing entries`() {
 | 
				
			||||||
 | 
					        assertDoesNotThrow("creation one") {
 | 
				
			||||||
 | 
					            creator.create(FSFolder("folder", listOf(
 | 
				
			||||||
 | 
					                FSFolder("sub-folder", listOf(
 | 
				
			||||||
 | 
					                    FSFile("hi", "hi")
 | 
				
			||||||
 | 
					                )),
 | 
				
			||||||
 | 
					                FSFolder("another-folder", listOf()),
 | 
				
			||||||
 | 
					                FSFile("1.txt", "One!"),
 | 
				
			||||||
 | 
					                FSFile("2.txt", "Two!")
 | 
				
			||||||
 | 
					            )), "_tmp")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        assertDoesNotThrow("creation two") {
 | 
				
			||||||
 | 
					            creator.create(FSFolder("folder", listOf(
 | 
				
			||||||
 | 
					                FSFolder("another-folder", listOf(
 | 
				
			||||||
 | 
					                    FSFolder("secrets", listOf(
 | 
				
			||||||
 | 
					                        FSFile("secret", "P4ssW0rd")
 | 
				
			||||||
 | 
					                    ))
 | 
				
			||||||
 | 
					                )),
 | 
				
			||||||
 | 
					                FSFile("1.txt", "One is a good number"),
 | 
				
			||||||
 | 
					                FSFile("3.txt", "Three!")
 | 
				
			||||||
 | 
					            )), "_tmp")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        assertEquals("hi", Files.readString(Path.of("_tmp/folder/sub-folder/hi")))
 | 
				
			||||||
 | 
					        assertEquals("P4ssW0rd", Files.readString(Path.of("_tmp/folder/another-folder/secrets/secret")))
 | 
				
			||||||
 | 
					        assertEquals("One is a good number", Files.readString(Path.of("_tmp/folder/1.txt")))
 | 
				
			||||||
 | 
					        assertEquals("Two!", Files.readString(Path.of("_tmp/folder/2.txt")))
 | 
				
			||||||
 | 
					        assertEquals("Three!", Files.readString(Path.of("_tmp/folder/3.txt")))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    @Timeout(500, unit = TimeUnit.MILLISECONDS) // in case implementation starts trying to handle recursion
 | 
				
			||||||
 | 
					    fun `create throws on recursive folder`() {
 | 
				
			||||||
 | 
					        val files = mutableListOf<FSEntry>()
 | 
				
			||||||
 | 
					        val folder = FSFolder("folder", files)
 | 
				
			||||||
 | 
					        files.add(folder)
 | 
				
			||||||
 | 
					        assertThrows<FileSystemException> {
 | 
				
			||||||
 | 
					            creator.create(folder, "_tmp")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun deleteRecursive(path: Path) {
 | 
				
			||||||
 | 
					    if (Files.isDirectory(path)) {
 | 
				
			||||||
 | 
					        for (child in Files.list(path)) {
 | 
				
			||||||
 | 
					            deleteRecursive(child)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Files.delete(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user