Last active
May 9, 2016 11:43
-
-
Save sim642/d5028f2a9dbcc70b2b1397c0a9ec5733 to your computer and use it in GitHub Desktop.
diff of refactoring Java NIO into shy, produced by shy, after importing git repository to shy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- /src/main/java/ee/shy/cli/command/AddCommand.java | |
+++ /src/main/java/ee/shy/cli/command/AddCommand.java | |
@@ -2,21 +2,21 @@ | |
import ee.shy.cli.Command; | |
import ee.shy.cli.HelptextBuilder; | |
import ee.shy.core.Repository; | |
-import java.io.File; | |
import java.io.IOException; | |
+import java.nio.file.Paths; | |
/** | |
* A command to add given file to its respective directory in the repository. | |
*/ | |
public class AddCommand implements Command { | |
@Override | |
public void execute(String[] args) throws IOException { | |
Repository repository = Repository.newExisting(); | |
- repository.add(new File(args[0])); | |
+ repository.add(Paths.get(args[0])); | |
} | |
@Override | |
public String getHelp() { | |
return new HelptextBuilder() | |
--- /src/main/java/ee/shy/cli/command/RemoveCommand.java | |
+++ /src/main/java/ee/shy/cli/command/RemoveCommand.java | |
@@ -2,21 +2,21 @@ | |
import ee.shy.cli.Command; | |
import ee.shy.cli.HelptextBuilder; | |
import ee.shy.core.Repository; | |
-import java.io.File; | |
import java.io.IOException; | |
+import java.nio.file.Paths; | |
/** | |
* A command to remove given file from its respective directory in the repository. | |
*/ | |
public class RemoveCommand implements Command { | |
@Override | |
public void execute(String[] args) throws IOException { | |
Repository repository = Repository.newExisting(); | |
- repository.remove(new File(args[0])); | |
+ repository.remove(Paths.get(args[0])); | |
} | |
@Override | |
public String getHelp() { | |
return new HelptextBuilder() | |
--- /src/main/java/ee/shy/cli/command/TestCommand.java | |
+++ /src/main/java/ee/shy/cli/command/TestCommand.java | |
@@ -2,10 +2,12 @@ | |
import ee.shy.cli.Command; | |
import ee.shy.cli.HelptextBuilder; | |
import ee.shy.core.Repository; | |
+import java.io.IOException; | |
+ | |
/** | |
* A simple command for testing. | |
*/ | |
public class TestCommand implements Command { | |
private final String name; | |
@@ -13,11 +15,11 @@ | |
public TestCommand(String name) { | |
this.name = name; | |
} | |
@Override | |
- public void execute(String[] args) { | |
+ public void execute(String[] args) throws IOException { | |
System.out.println(name); | |
Repository repository = Repository.newExisting(); | |
} | |
@Override | |
--- /src/main/java/ee/shy/core/Repository.java | |
+++ /src/main/java/ee/shy/core/Repository.java | |
@@ -1,213 +1,219 @@ | |
package ee.shy.core; | |
import ee.shy.io.Json; | |
+import ee.shy.io.PathUtils; | |
import ee.shy.map.DirectoryJsonMap; | |
import ee.shy.map.NamedObjectMap; | |
import ee.shy.storage.*; | |
import org.apache.commons.io.IOUtils; | |
-import org.apache.commons.io.output.TeeOutputStream; | |
-import java.io.*; | |
+import java.io.IOException; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
-import java.nio.file.Paths; | |
import java.util.Arrays; | |
- | |
/** | |
* Class for creating and interacting with a repository. | |
*/ | |
public class Repository { | |
/** | |
- * Repository's root directory. | |
+ * Repository root directory path. | |
*/ | |
- private final File repositoryDirectory; | |
+ private final Path rootPath; | |
- /** | |
- * {@link #repositoryDirectory}'s parent directory. | |
- */ | |
- private final File rootDirectory; | |
- | |
private final DataStorage storage; | |
private final NamedObjectMap<Branch> branches; | |
/** | |
* Constructs a new repository class. | |
- * @param rootDirectory root directory for repository | |
+ * @param rootPath root directory for repository | |
*/ | |
- private Repository(File rootDirectory) { | |
- this.rootDirectory = rootDirectory; | |
- this.repositoryDirectory = new File(rootDirectory, ".shy"); | |
+ private Repository(Path rootPath) throws IOException { | |
+ this.rootPath = rootPath; | |
this.storage = new FileStorage( | |
Arrays.asList( | |
- new FlatFileLocator(new File(repositoryDirectory, "storage")) | |
+ new FlatFileLocator(getRepositoryPath().resolve("storage")) | |
), | |
new PlainFileAccessor()); | |
- branches = new DirectoryJsonMap<>(Branch.class, repositoryDirectory.toPath().resolve("branches")); | |
+ branches = new DirectoryJsonMap<>(Branch.class, getRepositoryPath().resolve("branches")); | |
} | |
/** | |
* Tries to find an existing repository in the directory shy was executed or its parent directories. | |
* @return repository object if existing repository was found, null otherwise | |
*/ | |
- public static Repository newExisting() throws RepositoryNotFoundException { | |
- File currentDirectory = new File(System.getProperty("user.dir")); | |
- while (currentDirectory != null) { | |
- File repositoryDirectory = new File(currentDirectory, ".shy"); | |
- if (repositoryDirectory.exists() && repositoryDirectory.isDirectory()) { | |
- return new Repository(currentDirectory); | |
+ public static Repository newExisting() throws RepositoryNotFoundException, IOException { | |
+ Path currentPath = PathUtils.getCurrentPath(); | |
+ while (currentPath != null) { | |
+ Path repositoryPath = getRepositoryPath(currentPath); | |
+ if (Files.isDirectory(repositoryPath)) { | |
+ return new Repository(currentPath); | |
} | |
- currentDirectory = currentDirectory.getParentFile(); | |
+ currentPath = currentPath.getParent(); | |
} | |
+ | |
throw new RepositoryNotFoundException(); | |
} | |
/** | |
* Creates a new repository in the directory where shy was executed. | |
* @return a Repository object if repository creation was successful | |
* @throws IOException if repository hierarchy generation fails | |
*/ | |
public static Repository newEmpty() throws IOException { | |
- File currentDirectory = new File(System.getProperty("user.dir")); | |
- File repositoryDirectory = new File(currentDirectory, ".shy"); | |
- if (repositoryDirectory.exists() || repositoryDirectory.mkdir()) { | |
- String[] subDirectories = {"commit", "branches", "tags", "storage"}; | |
- for (String subDirectory : subDirectories) { | |
- File f = new File(repositoryDirectory, subDirectory); | |
- if (!f.exists()) | |
- f.mkdir(); | |
- } | |
+ Path repositoryPath = getRepositoryPath(PathUtils.getCurrentPath()); | |
+ Files.createDirectory(repositoryPath); | |
- String[] repositoryFiles = {"author", "current"}; | |
- for (String repositoryFile : repositoryFiles) { | |
- File f = new File(repositoryDirectory, repositoryFile); | |
- if (!f.exists()) | |
- f.createNewFile(); | |
- } | |
+ String[] subDirectories = {"commit", "branches", "tags", "storage"}; | |
+ for (String subDirectory : subDirectories) { | |
+ Files.createDirectory(repositoryPath.resolve(subDirectory)); | |
+ } | |
- // The following will be refactored later in the project development(Phase 2) | |
- File current = new File(repositoryDirectory, "current"); | |
- try (FileOutputStream currentStream = new FileOutputStream(current)) { | |
- currentStream.write(Hash.ZERO.toString().getBytes()); | |
- } | |
+ String[] repositoryFiles = {"author", "current"}; | |
+ for (String repositoryFile : repositoryFiles) { | |
+ Files.createFile(repositoryPath.resolve(repositoryFile)); | |
+ } | |
- // TODO: 26.03.16 Create a config file to home directory upon installation to get author's details from. | |
- Author author = new Author(null, null); | |
- author.write(new FileOutputStream(new File(repositoryDirectory, "author"))); | |
+ // TODO: 6.04.16 move current commit handling into separate class | |
+ IOUtils.write(Hash.ZERO.toString(), Files.newOutputStream(repositoryPath.resolve("current"))); | |
- System.out.println("Initialized a shy repository in " + currentDirectory.getAbsolutePath()); | |
+ Repository repository = new Repository(repositoryPath.getParent()); | |
- Repository repository = new Repository(currentDirectory); | |
- repository.getBranches().put("master", new Branch(Hash.ZERO)); | |
+ // TODO: 26.03.16 Create a config file to home directory upon installation to get author's details from. | |
+ Author author = new Author(null, null); | |
+ repository.setAuthor(author); | |
- return repository; | |
- } | |
- else { | |
- throw new IOException("Repository initialization failed!"); | |
- } | |
+ repository.getBranches().put("master", new Branch(Hash.ZERO)); | |
+ | |
+ System.out.println("Initialized a shy repository in " + repository.getRootPath()); | |
+ return repository; | |
} | |
/** | |
+ * Returns current directory file's path in ".shy/commit/" directory. | |
+ * @param path file which's path to transform | |
+ * @return transformed path in ".shy/commit/" | |
+ */ | |
+ private Path getCommitPath(Path path) throws IOException { | |
+ Path commitPath = getRepositoryPath().resolve("commit"); | |
+ /* | |
+ Beware of the pitfalls of oh-so-wonderful Path: | |
+ Path#toAbsolutePath does NOT normalize the path to an actual absolute path, | |
+ but simply prepends the current working directory. | |
+ */ | |
+ return commitPath.resolve(rootPath.relativize(path.toRealPath())); | |
+ } | |
+ | |
+ /** | |
* Copies given file to its respective directory in ".shy/commit/" directory. | |
- * @param file file that user wants to add to repository | |
+ * @param path file that user wants to add to repository | |
* @throws IOException if file can't be found or copying fails | |
*/ | |
- public void add(File file) throws IOException { | |
- File fullFilePath = fullFilePath(file); | |
- fullFilePath.getParentFile().mkdirs(); | |
- try (InputStream input = new FileInputStream(file)) { | |
- try (OutputStream output = new FileOutputStream(fullFilePath)) { | |
- IOUtils.copy(input, output); | |
- } | |
- } | |
+ public void add(Path path) throws IOException { | |
+ Path commitPath = getCommitPath(path); | |
+ /* | |
+ Beware of the pitfalls of oh-so-wonderful Path: | |
+ Files.createDirectories does unintuitive things for paths ending in "..". | |
+ For example, "/tmp/foo/bar/.." will cause "/tmp/foo/bar/" to be created yet it's not in the normalized path. | |
+ */ | |
+ Files.createDirectories(commitPath.getParent()); | |
+ Files.copy(path, commitPath); | |
} | |
/** | |
* Removes given file from its directory in ".shy/commit". | |
- * @param file file that user wants to remove from repository | |
+ * @param path file that user wants to remove from repository | |
* @throws IOException if file could not be deleted | |
*/ | |
- public void remove(File file) throws IOException { | |
- Files.deleteIfExists(fullFilePath(file).toPath()); | |
+ public void remove(Path path) throws IOException { | |
+ Files.deleteIfExists(getCommitPath(path)); | |
} | |
/** | |
* Creates and stores the complete ".shy/commit/" directory tree. | |
* @return hash of stored tree | |
* @throws IOException if there was a problem storing the tree | |
*/ | |
private Hash createCommitTree() throws IOException { | |
- Tree tree = new Tree.Builder(storage).fromDirectory(new File(repositoryDirectory, "commit")).create(); | |
+ Tree tree = new Tree.Builder(storage).fromDirectory(getRepositoryPath().resolve("commit")).create(); | |
return storage.put(tree.inputify()); | |
} | |
/** | |
* Commits current commit with given message. | |
* @param message commit message | |
* @throws IOException if there was a problem storing the tree/commit or modifying ".shy/current" | |
*/ | |
public void commit(String message) throws IOException { | |
Hash tree = createCommitTree(); | |
- File currentFile = new File(repositoryDirectory, "current"); | |
- Hash parent = new Hash(IOUtils.toString(new FileInputStream(currentFile), "UTF-8")); | |
+ Path currentPath = getRepositoryPath().resolve("current"); | |
+ Hash parent = new Hash(IOUtils.toString(Files.newInputStream(currentPath), "UTF-8")); | |
Commit commit = new Commit.Builder() | |
.setTree(tree) | |
.addParent(parent) | |
.setAuthor(getAuthor()) | |
.setTimeCurrent() | |
.setMessage(message) | |
.create(); | |
Hash hash = storage.put(commit.inputify()); | |
- File branchFile = new File(new File(repositoryDirectory, "branches"), "master"); // TODO: 26.03.16 update correct branch | |
- IOUtils.write(hash.toString(), new TeeOutputStream(new FileOutputStream(currentFile), new FileOutputStream(branchFile)), "UTF-8"); | |
+ branches.put("master", new Branch(hash)); // TODO: 26.03.16 update correct branch | |
+ IOUtils.write(hash.toString(), Files.newOutputStream(currentPath)); | |
} | |
/** | |
- * Creates given file's path relative to repository's directory. | |
- * @param file file that's relative path is wanted to be create | |
- * @return file's path relative to repository's directory | |
- */ | |
- private File relativeFilePath(File file) { | |
- File fileDir = new File(System.getProperty("user.dir"), file.getPath()).getParentFile(); | |
- | |
- Path path = Paths.get(fileDir.getPath()); | |
- path = this.rootDirectory.toPath().relativize(path); | |
- | |
- return new File(path.toFile().getPath(), file.getName()); | |
- } | |
- | |
- /** | |
- * Creates full path from system's root to given file in ".shy/commit/" directory. | |
- * @param file file that's path is wanted to be create | |
- * @return file path from system's root to given file'is directory in ".shy/commit/" | |
- */ | |
- private File fullFilePath(File file) { | |
- File repositoryDirectory = new File(this.rootDirectory.getPath(), ".shy/commit/"); | |
- return new File(repositoryDirectory, relativeFilePath(file).getPath()); | |
- } | |
- | |
- /** | |
* Get the Author object of this repository. | |
* @return Author object of '.shy/author' file | |
* @throws IOException if file '.shy/author' does not exist or reading fails | |
*/ | |
public Author getAuthor() throws IOException { | |
- FileInputStream fis = new FileInputStream(new File(repositoryDirectory, "author")); | |
- return Json.read(fis, Author.class); | |
+ return Json.read(Files.newInputStream(getAuthorPath()), Author.class); | |
} | |
/** | |
* Set the '.shy/author' file contents to given Author file contents. | |
* @param author Author object that is assigned to this repository | |
* @throws IOException if write fails | |
*/ | |
public void setAuthor(Author author) throws IOException { | |
- author.write(new FileOutputStream(new File(repositoryDirectory, "author"))); | |
+ author.write(Files.newOutputStream(getAuthorPath())); | |
} | |
public NamedObjectMap<Branch> getBranches() { | |
return branches; | |
} | |
+ | |
+ /** | |
+ * Returns repository's root path. | |
+ * @return root directory path | |
+ */ | |
+ public Path getRootPath() { | |
+ return rootPath; | |
+ } | |
+ | |
+ /** | |
+ * Returns repository's ".shy/" directory path in given root directory. | |
+ * @param rootPath root directory of repository | |
+ * @return repository directory path | |
+ */ | |
+ private static Path getRepositoryPath(Path rootPath) { | |
+ return rootPath.resolve(".shy"); | |
+ } | |
+ | |
+ /** | |
+ * Returns repository's ".shy/" directory path. | |
+ * @return repository directory path | |
+ */ | |
+ private Path getRepositoryPath() { | |
+ return getRepositoryPath(rootPath); | |
+ } | |
+ | |
+ /** | |
+ * Returns repository's "author" file path. | |
+ * @return author file path | |
+ */ | |
+ private Path getAuthorPath() { | |
+ return getRepositoryPath().resolve("author"); | |
+ } | |
} | |
--- /src/main/java/ee/shy/core/Tree.java | |
+++ /src/main/java/ee/shy/core/Tree.java | |
@@ -2,16 +2,15 @@ | |
import ee.shy.io.Jsonable; | |
import ee.shy.storage.DataStorage; | |
import ee.shy.storage.Hash; | |
-import java.io.File; | |
-import java.io.FileInputStream; | |
import java.io.IOException; | |
-import java.util.Arrays; | |
-import java.util.Map; | |
-import java.util.TreeMap; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
+import java.util.*; | |
+import java.util.stream.Collectors; | |
/** | |
* Class representing a directory tree. | |
*/ | |
public class Tree extends Jsonable { | |
@@ -66,26 +65,24 @@ | |
* Builds tree using given directory content and stores all referenced data. | |
* @param directory directory to build tree from | |
* @return builder itself | |
* @throws IOException if there was a problem reading an addable file or tree to storage | |
*/ | |
- public Builder fromDirectory(File directory) throws IOException { | |
- File[] files = directory.listFiles(); | |
- if (files == null) | |
- throw new IOException("Attempted to build Tree from a non-directory"); | |
+ public Builder fromDirectory(Path directory) throws IOException { | |
+ List<Path> files = new ArrayList<>(Files.list(directory).collect(Collectors.toList())); // TODO: 6.04.16 Stream#toCollection for creating ArrayList | |
- Arrays.sort(files); // guarantee stable order | |
+ Collections.sort(files); | |
- for (File file : files) { | |
- if (file.isFile()) { | |
- Hash hash = storage.put(new FileInputStream(file)); | |
- addItem(file.getName(), new TreeItem(TreeItem.Type.FILE, hash)); | |
+ for (Path file : files) { | |
+ if (Files.isRegularFile(file)) { | |
+ Hash hash = storage.put(Files.newInputStream(file)); | |
+ addItem(file.getFileName().toString(), new TreeItem(TreeItem.Type.FILE, hash)); | |
} | |
- else if (file.isDirectory()) { | |
+ else if (Files.isDirectory(file)) { | |
Tree tree = new Builder(storage).fromDirectory(file).create(); | |
Hash hash = storage.put(tree.inputify()); | |
- addItem(file.getName(), new TreeItem(TreeItem.Type.TREE, hash)); | |
+ addItem(file.getFileName().toString(), new TreeItem(TreeItem.Type.TREE, hash)); | |
} | |
} | |
return this; | |
} | |
+++ /src/main/java/ee/shy/io/PathUtils.java | |
@@ -1,0 +1,42 @@ | |
+package ee.shy.io; | |
+ | |
+import java.io.IOException; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
+import java.nio.file.Paths; | |
+ | |
+/** | |
+ * Utilities class for I/O-related methods. | |
+ */ | |
+public class PathUtils { | |
+ private PathUtils() { | |
+ | |
+ } | |
+ | |
+ /** | |
+ * Returns current working directory as path. | |
+ * @return current working directory | |
+ */ | |
+ public static Path getCurrentPath() { | |
+ return Paths.get(System.getProperty("user.dir")); | |
+ } | |
+ | |
+ /** | |
+ * Adds given extension to file path. | |
+ * @param path file path to extend | |
+ * @param extension extension to add | |
+ * @return file path with given extension | |
+ */ | |
+ public static Path addExtension(Path path, String extension) { | |
+ return path.resolveSibling(path.getFileName().toString() + extension); | |
+ } | |
+ | |
+ /** | |
+ * Creates given path's parent directories. | |
+ * If path itself is a directory, it too will be created. | |
+ * @param path path which's parent directories to create | |
+ */ | |
+ public static void createParentDirectories(Path path) throws IOException { | |
+ Files.createDirectories(Files.isDirectory(path) ? path : path.getParent()); | |
+ } | |
+} | |
+++ /src/main/java/ee/shy/io/Utils.java | |
@@ -1,0 +1,14 @@ | |
+package ee.shy.io; | |
+ | |
+import java.nio.file.Path; | |
+import java.nio.file.Paths; | |
+ | |
+public class Utils { | |
+ private Utils() { | |
+ | |
+ } | |
+ | |
+ public static Path getCurrentPath() { | |
+ return Paths.get(System.getProperty("user.dir")); | |
+ } | |
+} | |
--- /src/main/java/ee/shy/storage/AggregateFileAccessor.java | |
+++ /src/main/java/ee/shy/storage/AggregateFileAccessor.java | |
@@ -1,10 +1,10 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
import java.io.IOException; | |
import java.io.InputStream; | |
+import java.nio.file.Path; | |
import java.util.List; | |
/** | |
* File accessor to aggregate other file accessors. | |
* Allows simultaneous support for multiple accessors. | |
@@ -23,30 +23,30 @@ | |
this.accessors = accessors; | |
} | |
/** | |
* Adds file content via first file accessor. | |
- * @param file base path of file to add | |
+ * @param path base path of file to add | |
* @param source input stream to get data from | |
* @throws IOException if there was a problem reading the input stream or writing to the file | |
*/ | |
@Override | |
- public void add(File file, InputStream source) throws IOException { | |
- accessors.get(0).add(file, source); // always use first accessor for add | |
+ public void add(Path path, InputStream source) throws IOException { | |
+ accessors.get(0).add(path, source); // always use first accessor for add | |
} | |
/** | |
* Gets file content via first successful file accessor. | |
- * @param file base path of file to get | |
+ * @param path base path of file to get | |
* @return input stream to get data from | |
* @throws IOException if there was a problem reading from the file | |
*/ | |
@Override | |
- public InputStream get(File file) throws IOException { | |
+ public InputStream get(Path path) throws IOException { | |
InputStream source; | |
for (FileAccessor accessor : accessors) { | |
- if ((source = accessor.get(file)) != null) | |
+ if ((source = accessor.get(path)) != null) | |
return source; | |
} | |
return null; | |
} | |
} | |
--- /src/main/java/ee/shy/storage/FileAccessor.java | |
+++ /src/main/java/ee/shy/storage/FileAccessor.java | |
@@ -1,27 +1,27 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
import java.io.IOException; | |
import java.io.InputStream; | |
+import java.nio.file.Path; | |
/** | |
* An interface for accessing file content by base path from a {@link FileLocator}. | |
* Used to add/get data via a stream. | |
*/ | |
public interface FileAccessor { | |
/** | |
* Adds file content to given base path of file | |
- * @param file base path of file to add | |
+ * @param path base path of file to add | |
* @param source input stream to get data from | |
* @throws IOException if there was a problem reading the input stream or writing to the file | |
*/ | |
- void add(File file, InputStream source) throws IOException; | |
+ void add(Path path, InputStream source) throws IOException; | |
/** | |
* Gets file content from given base path of file | |
- * @param file base path of file to get | |
+ * @param path base path of file to get | |
* @return input stream to get data from | |
* @throws IOException if there was a problem reading from some input | |
*/ | |
- InputStream get(File file) throws IOException; | |
+ InputStream get(Path path) throws IOException; | |
} | |
--- /src/main/java/ee/shy/storage/FileLocator.java | |
+++ /src/main/java/ee/shy/storage/FileLocator.java | |
@@ -1,57 +1,55 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
+import java.io.IOException; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
/** | |
* An abstract class for locating files by hash. | |
* Used to get file paths by hash to use with {@link FileAccessor}. | |
*/ | |
public abstract class FileLocator { | |
/** | |
* Root directory to use. | |
*/ | |
- protected final File root; | |
+ protected final Path root; | |
/** | |
* Constructs a new locator with given root. | |
* @param root root directory to use | |
*/ | |
- public FileLocator(File root) { | |
- if (!root.exists()) | |
- root.mkdirs(); | |
- if (!root.isDirectory()) | |
- throw new RuntimeException("root must be a directory"); // TODO: 9.03.16 throw better exception | |
- | |
+ public FileLocator(Path root) throws IOException { | |
+ Files.createDirectories(root); | |
this.root = root; | |
} | |
/** | |
* Locates a file by hash. | |
* Suitable for overriding both {@link #locateAdd(Hash)} and {@link #locateGet(Hash)}. | |
* @param hash hash to get path for | |
* @return path to file for given hash | |
*/ | |
- public File locate(Hash hash) { | |
+ public Path locate(Hash hash) throws IOException { | |
return null; | |
} | |
/** | |
* Locates a supposed file by hash for addition. | |
* Suitable for overriding to add extra behavior on addition. | |
* @param hash hash to get path for | |
* @return supposed path to file for given hash | |
*/ | |
- public File locateAdd(Hash hash) { | |
+ public Path locateAdd(Hash hash) throws IOException { | |
return locate(hash); | |
} | |
/** | |
* Locates a file by hash for retrieval. | |
* Suitable for overriding to add extra behavior on retrieval. | |
* @param hash hash to get path for | |
* @return path to file for given hash | |
*/ | |
- public File locateGet(Hash hash) { | |
+ public Path locateGet(Hash hash) throws IOException { | |
return locate(hash); | |
} | |
} | |
--- /src/main/java/ee/shy/storage/FlatFileLocator.java | |
+++ /src/main/java/ee/shy/storage/FlatFileLocator.java | |
@@ -1,21 +1,22 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
+import java.io.IOException; | |
+import java.nio.file.Path; | |
/** | |
* File locator for having all hashes in the root directory. | |
*/ | |
public class FlatFileLocator extends FileLocator { | |
/** | |
* Constructs a new flat file locator with given root. | |
* @param root root directory to use | |
*/ | |
- public FlatFileLocator(File root) { | |
+ public FlatFileLocator(Path root) throws IOException { | |
super(root); | |
} | |
@Override | |
- public File locate(Hash hash) { | |
- return new File(root, hash.toString()); | |
+ public Path locate(Hash hash) { | |
+ return root.resolve(hash.toString()); | |
} | |
} | |
--- /src/main/java/ee/shy/storage/GitFileLocator.java | |
+++ /src/main/java/ee/shy/storage/GitFileLocator.java | |
@@ -1,8 +1,9 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
+import java.io.IOException; | |
+import java.nio.file.Path; | |
/** | |
* File locator for having hashes in git-like directory structure in the root directory: | |
* first two characters of hash represent a subdirectory, | |
* remaining hash characters the filename. | |
@@ -10,9 +11,9 @@ | |
public class GitFileLocator extends NestedFileLocator { | |
/** | |
* Constructs a new git file locator with given root. | |
* @param root root directory to use | |
*/ | |
- public GitFileLocator(File root) { | |
+ public GitFileLocator(Path root) throws IOException { | |
super(root, 2, 1); | |
} | |
} | |
--- /src/main/java/ee/shy/storage/GzipFileAccessor.java | |
+++ /src/main/java/ee/shy/storage/GzipFileAccessor.java | |
@@ -1,10 +1,13 @@ | |
package ee.shy.storage; | |
+import ee.shy.io.PathUtils; | |
import org.apache.commons.io.IOUtils; | |
import java.io.*; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
import java.util.zip.GZIPInputStream; | |
import java.util.zip.GZIPOutputStream; | |
/** | |
* File accessor to store data compressed using GZIP. | |
@@ -15,20 +18,20 @@ | |
* Extension used on base paths. | |
*/ | |
private static final String EXTENSION = ".gz"; // TODO: 9.03.16 create superclass for extension handling | |
@Override | |
- public void add(File file, InputStream source) throws IOException { | |
- try (GZIPOutputStream target = new GZIPOutputStream(new FileOutputStream(Util.addExtension(file, EXTENSION)))) { | |
+ public void add(Path path, InputStream source) throws IOException { | |
+ try (GZIPOutputStream target = new GZIPOutputStream(Files.newOutputStream(PathUtils.addExtension(path, EXTENSION)))) { | |
IOUtils.copy(source, target); | |
} | |
} | |
@Override | |
- public InputStream get(File file) throws IOException { | |
+ public InputStream get(Path path) throws IOException { | |
try { | |
- return new GZIPInputStream(new FileInputStream(Util.addExtension(file, EXTENSION))); | |
+ return new GZIPInputStream(Files.newInputStream(PathUtils.addExtension(path, EXTENSION))); | |
} | |
catch (FileNotFoundException e) { | |
return null; | |
} | |
} | |
--- /src/main/java/ee/shy/storage/NestedFileLocator.java | |
+++ /src/main/java/ee/shy/storage/NestedFileLocator.java | |
@@ -1,9 +1,12 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
+import ee.shy.io.PathUtils; | |
+import java.io.IOException; | |
+import java.nio.file.Path; | |
+ | |
/** | |
* File locator for having hashes in nested directory structure in the root directory: | |
* every {@link #directoryLength} characters of hash represent a subdirectory, | |
* limited by having at most {@link #depthMax} subdirectories, | |
* remaining hash characters the filename. | |
@@ -27,40 +30,41 @@ | |
/** | |
* Constructs a new nested file locator with given root with unlimited nesting depth. | |
* @param root root directory to use | |
* @param directoryLength length of each subdirectory name | |
*/ | |
- public NestedFileLocator(File root, int directoryLength) { | |
+ public NestedFileLocator(Path root, int directoryLength) throws IOException { | |
this(root, directoryLength, DEPTH_UNLIMITED); | |
} | |
/** | |
* Constructs a new nested file locator with given root. | |
* @param root root directory to use | |
* @param directoryLength length of each subdirectory name | |
* @param depthMax maximum nesting depth, unlimited with {@link #DEPTH_UNLIMITED} | |
*/ | |
- public NestedFileLocator(File root, int directoryLength, int depthMax) { | |
+ public NestedFileLocator(Path root, int directoryLength, int depthMax) throws IOException { | |
super(root); | |
this.directoryLength = directoryLength; | |
this.depthMax = depthMax; | |
} | |
@Override | |
- public File locate(Hash hash) { | |
+ public Path locate(Hash hash) { | |
String hashString = hash.toString(); | |
- File file = root; | |
+ Path path = root; | |
int depth; | |
for (depth = 0; (depthMax == DEPTH_UNLIMITED || depth < depthMax) && (directoryLength * (depth + 1) < hashString.length()); depth++) | |
- file = new File(file, hashString.substring(directoryLength * depth, directoryLength * (depth + 1))); | |
+ path = path.resolve(hashString.substring(directoryLength * depth, directoryLength * (depth + 1))); | |
- file = new File(file, hashString.substring(directoryLength * depth)); | |
- return file; | |
+ path = path.resolve(hashString.substring(directoryLength * depth)); | |
+ return path; | |
} | |
@Override | |
- public File locateAdd(Hash hash) { | |
- File file = locate(hash); | |
- return Util.ensurePath(file) ? file : null; | |
+ public Path locateAdd(Hash hash) throws IOException { | |
+ Path path = locate(hash); | |
+ PathUtils.createParentDirectories(path); | |
+ return path; | |
} | |
} | |
--- /src/main/java/ee/shy/storage/PlainFileAccessor.java | |
+++ /src/main/java/ee/shy/storage/PlainFileAccessor.java | |
@@ -1,29 +1,31 @@ | |
package ee.shy.storage; | |
import org.apache.commons.io.IOUtils; | |
import java.io.*; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
/** | |
* File accessor to store data plainly as-is. | |
* No extension is used on base paths. | |
*/ | |
public class PlainFileAccessor implements FileAccessor { | |
@Override | |
- public void add(File file, InputStream source) throws IOException { | |
- try (FileOutputStream target = new FileOutputStream(file)) { | |
+ public void add(Path path, InputStream source) throws IOException { | |
+ try (OutputStream target = Files.newOutputStream(path)) { | |
IOUtils.copy(source, target); | |
} | |
} | |
@Override | |
- public InputStream get(File file) { | |
+ public InputStream get(Path path) throws IOException { | |
try { | |
- return new FileInputStream(file); | |
+ return Files.newInputStream(path); | |
} | |
- catch (FileNotFoundException e) { | |
+ catch (FileNotFoundException e) { // TODO: 6.04.16 don't catch exception | |
return null; | |
} | |
} | |
} | |
--- /src/main/java/ee/shy/storage/StorageTest.java | |
+++ /src/main/java/ee/shy/storage/StorageTest.java | |
@@ -1,36 +1,37 @@ | |
package ee.shy.storage; | |
import org.apache.commons.io.IOUtils; | |
import java.io.*; | |
+import java.nio.file.Paths; | |
import java.util.Arrays; | |
public class StorageTest { | |
public static void main(String[] args) throws IOException { | |
DataStorage storage = new FileStorage( | |
Arrays.asList( | |
- new GitFileLocator(new File("teststore")), | |
- new FlatFileLocator(new File("teststore2"))), | |
+ new GitFileLocator(Paths.get("teststore")), | |
+ new FlatFileLocator(Paths.get("teststore2"))), | |
new AggregateFileAccessor(Arrays.asList( | |
new GzipFileAccessor(), | |
new PlainFileAccessor()))); | |
- /*Hash h1 = storage.add(new ByteArrayInputStream("foo".getBytes("UTF-8"))); | |
- Hash h2 = storage.add(new ByteArrayInputStream("bar".getBytes("UTF-8"))); | |
- Hash h3 = storage.add(new FileInputStream("README.md")); | |
+ Hash h1 = storage.put(new ByteArrayInputStream("foo".getBytes("UTF-8"))); | |
+ Hash h2 = storage.put(new ByteArrayInputStream("bar".getBytes("UTF-8"))); | |
+ Hash h3 = storage.put(new FileInputStream("README.md")); | |
System.out.println(h1); | |
System.out.println(h2); | |
System.out.println(h3); | |
InputStream i1 = storage.get(new Hash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")); | |
System.out.println(new String(IOUtils.toByteArray(i1), "UTF-8")); | |
InputStream i2 = storage.get(h2); | |
System.out.println(new String(IOUtils.toByteArray(i2), "UTF-8")); | |
InputStream i3 = storage.get(h3); | |
- IOUtils.copyStream(i3, new FileOutputStream("README2.md"));*/ | |
+ IOUtils.copy(i3, new FileOutputStream("README2.md")); | |
InputStream i = storage.get(new Hash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")); | |
System.out.println(new String(IOUtils.toByteArray(i), "UTF-8")); | |
} | |
} | |
--- /src/main/java/ee/shy/storage/Util.java | |
+++ /src/main/java/ee/shy/storage/Util.java | |
@@ -1,8 +1,10 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
+import java.io.IOException; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
/** | |
* Utilities class for storage-related functions. | |
*/ | |
public class Util { | |
@@ -10,30 +12,22 @@ | |
} | |
/** | |
* Adds given extension to file path. | |
- * @param file file path to extend | |
+ * @param path file path to extend | |
* @param extension extension to add | |
* @return file path with given extension | |
*/ | |
- public static File addExtension(File file, String extension) { | |
- return new File(file.getAbsolutePath() + extension); | |
+ public static Path addExtension(Path path, String extension) { | |
+ return path.resolveSibling(path.getFileName().toString() + extension); | |
} | |
/** | |
* Ensures file path's validity by creating required missing parent directories. | |
- * @param file file path which's validity to ensure | |
- * @return whether file path is now valid | |
+ * @param path file path which's validity to ensure | |
*/ | |
- public static boolean ensurePath(File file) { | |
- if (file.isDirectory()) | |
- return true; | |
- else { | |
- File parent = file.getParentFile(); | |
- if (parent.exists()) | |
- return parent.isDirectory(); | |
- else | |
- return parent.mkdirs(); | |
- } | |
+ public static void ensurePath(Path path) throws IOException { | |
+ if (!Files.isDirectory(path)) | |
+ Files.createDirectories(path.getParent()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/main/java/ee/shy/cli/command/AddCommand.java b/src/main/java/ee/shy/cli/command/AddCommand.java | |
index b60dd61..1a47318 100644 | |
--- a/src/main/java/ee/shy/cli/command/AddCommand.java | |
+++ b/src/main/java/ee/shy/cli/command/AddCommand.java | |
@@ -4,8 +4,8 @@ import ee.shy.cli.Command; | |
import ee.shy.cli.HelptextBuilder; | |
import ee.shy.core.Repository; | |
-import java.io.File; | |
import java.io.IOException; | |
+import java.nio.file.Paths; | |
/** | |
* A command to add given file to its respective directory in the repository. | |
@@ -14,7 +14,7 @@ public class AddCommand implements Command { | |
@Override | |
public void execute(String[] args) throws IOException { | |
Repository repository = Repository.newExisting(); | |
- repository.add(new File(args[0])); | |
+ repository.add(Paths.get(args[0])); | |
} | |
@Override | |
diff --git a/src/main/java/ee/shy/cli/command/RemoveCommand.java b/src/main/java/ee/shy/cli/command/RemoveCommand.java | |
index d1caff9..2f1039c 100644 | |
--- a/src/main/java/ee/shy/cli/command/RemoveCommand.java | |
+++ b/src/main/java/ee/shy/cli/command/RemoveCommand.java | |
@@ -4,8 +4,8 @@ import ee.shy.cli.Command; | |
import ee.shy.cli.HelptextBuilder; | |
import ee.shy.core.Repository; | |
-import java.io.File; | |
import java.io.IOException; | |
+import java.nio.file.Paths; | |
/** | |
* A command to remove given file from its respective directory in the repository. | |
@@ -14,7 +14,7 @@ public class RemoveCommand implements Command { | |
@Override | |
public void execute(String[] args) throws IOException { | |
Repository repository = Repository.newExisting(); | |
- repository.remove(new File(args[0])); | |
+ repository.remove(Paths.get(args[0])); | |
} | |
@Override | |
diff --git a/src/main/java/ee/shy/cli/command/TestCommand.java b/src/main/java/ee/shy/cli/command/TestCommand.java | |
index 7a7ca34..21be95b 100644 | |
--- a/src/main/java/ee/shy/cli/command/TestCommand.java | |
+++ b/src/main/java/ee/shy/cli/command/TestCommand.java | |
@@ -4,6 +4,8 @@ import ee.shy.cli.Command; | |
import ee.shy.cli.HelptextBuilder; | |
import ee.shy.core.Repository; | |
+import java.io.IOException; | |
+ | |
/** | |
* A simple command for testing. | |
*/ | |
@@ -15,7 +17,7 @@ public class TestCommand implements Command { | |
} | |
@Override | |
- public void execute(String[] args) { | |
+ public void execute(String[] args) throws IOException { | |
System.out.println(name); | |
Repository repository = Repository.newExisting(); | |
} | |
diff --git a/src/main/java/ee/shy/core/Repository.java b/src/main/java/ee/shy/core/Repository.java | |
index 5e9b077..b25d4a2 100644 | |
--- a/src/main/java/ee/shy/core/Repository.java | |
+++ b/src/main/java/ee/shy/core/Repository.java | |
@@ -1,64 +1,57 @@ | |
package ee.shy.core; | |
import ee.shy.io.Json; | |
+import ee.shy.io.PathUtils; | |
import ee.shy.map.DirectoryJsonMap; | |
import ee.shy.map.NamedObjectMap; | |
import ee.shy.storage.*; | |
import org.apache.commons.io.IOUtils; | |
-import org.apache.commons.io.output.TeeOutputStream; | |
-import java.io.*; | |
+import java.io.IOException; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
-import java.nio.file.Paths; | |
import java.util.Arrays; | |
- | |
/** | |
* Class for creating and interacting with a repository. | |
*/ | |
public class Repository { | |
/** | |
- * Repository's root directory. | |
- */ | |
- private final File repositoryDirectory; | |
- | |
- /** | |
- * {@link #repositoryDirectory}'s parent directory. | |
+ * Repository root directory path. | |
*/ | |
- private final File rootDirectory; | |
+ private final Path rootPath; | |
private final DataStorage storage; | |
private final NamedObjectMap<Branch> branches; | |
/** | |
* Constructs a new repository class. | |
- * @param rootDirectory root directory for repository | |
+ * @param rootPath root directory for repository | |
*/ | |
- private Repository(File rootDirectory) { | |
- this.rootDirectory = rootDirectory; | |
- this.repositoryDirectory = new File(rootDirectory, ".shy"); | |
+ private Repository(Path rootPath) throws IOException { | |
+ this.rootPath = rootPath; | |
this.storage = new FileStorage( | |
Arrays.asList( | |
- new FlatFileLocator(new File(repositoryDirectory, "storage")) | |
+ new FlatFileLocator(getRepositoryPath().resolve("storage")) | |
), | |
new PlainFileAccessor()); | |
- branches = new DirectoryJsonMap<>(Branch.class, repositoryDirectory.toPath().resolve("branches")); | |
+ branches = new DirectoryJsonMap<>(Branch.class, getRepositoryPath().resolve("branches")); | |
} | |
/** | |
* Tries to find an existing repository in the directory shy was executed or its parent directories. | |
* @return repository object if existing repository was found, null otherwise | |
*/ | |
- public static Repository newExisting() throws RepositoryNotFoundException { | |
- File currentDirectory = new File(System.getProperty("user.dir")); | |
- while (currentDirectory != null) { | |
- File repositoryDirectory = new File(currentDirectory, ".shy"); | |
- if (repositoryDirectory.exists() && repositoryDirectory.isDirectory()) { | |
- return new Repository(currentDirectory); | |
+ public static Repository newExisting() throws RepositoryNotFoundException, IOException { | |
+ Path currentPath = PathUtils.getCurrentPath(); | |
+ while (currentPath != null) { | |
+ Path repositoryPath = getRepositoryPath(currentPath); | |
+ if (Files.isDirectory(repositoryPath)) { | |
+ return new Repository(currentPath); | |
} | |
- currentDirectory = currentDirectory.getParentFile(); | |
+ currentPath = currentPath.getParent(); | |
} | |
+ | |
throw new RepositoryNotFoundException(); | |
} | |
@@ -68,67 +61,72 @@ public class Repository { | |
* @throws IOException if repository hierarchy generation fails | |
*/ | |
public static Repository newEmpty() throws IOException { | |
- File currentDirectory = new File(System.getProperty("user.dir")); | |
- File repositoryDirectory = new File(currentDirectory, ".shy"); | |
- if (repositoryDirectory.exists() || repositoryDirectory.mkdir()) { | |
- String[] subDirectories = {"commit", "branches", "tags", "storage"}; | |
- for (String subDirectory : subDirectories) { | |
- File f = new File(repositoryDirectory, subDirectory); | |
- if (!f.exists()) | |
- f.mkdir(); | |
- } | |
+ Path repositoryPath = getRepositoryPath(PathUtils.getCurrentPath()); | |
+ Files.createDirectory(repositoryPath); | |
- String[] repositoryFiles = {"author", "current"}; | |
- for (String repositoryFile : repositoryFiles) { | |
- File f = new File(repositoryDirectory, repositoryFile); | |
- if (!f.exists()) | |
- f.createNewFile(); | |
- } | |
+ String[] subDirectories = {"commit", "branches", "tags", "storage"}; | |
+ for (String subDirectory : subDirectories) { | |
+ Files.createDirectory(repositoryPath.resolve(subDirectory)); | |
+ } | |
- // The following will be refactored later in the project development(Phase 2) | |
- File current = new File(repositoryDirectory, "current"); | |
- try (FileOutputStream currentStream = new FileOutputStream(current)) { | |
- currentStream.write(Hash.ZERO.toString().getBytes()); | |
- } | |
+ String[] repositoryFiles = {"author", "current"}; | |
+ for (String repositoryFile : repositoryFiles) { | |
+ Files.createFile(repositoryPath.resolve(repositoryFile)); | |
+ } | |
- // TODO: 26.03.16 Create a config file to home directory upon installation to get author's details from. | |
- Author author = new Author(null, null); | |
- author.write(new FileOutputStream(new File(repositoryDirectory, "author"))); | |
+ // TODO: 6.04.16 move current commit handling into separate class | |
+ IOUtils.write(Hash.ZERO.toString(), Files.newOutputStream(repositoryPath.resolve("current"))); | |
- System.out.println("Initialized a shy repository in " + currentDirectory.getAbsolutePath()); | |
+ Repository repository = new Repository(repositoryPath.getParent()); | |
- Repository repository = new Repository(currentDirectory); | |
- repository.getBranches().put("master", new Branch(Hash.ZERO)); | |
+ // TODO: 26.03.16 Create a config file to home directory upon installation to get author's details from. | |
+ Author author = new Author(null, null); | |
+ repository.setAuthor(author); | |
- return repository; | |
- } | |
- else { | |
- throw new IOException("Repository initialization failed!"); | |
- } | |
+ repository.getBranches().put("master", new Branch(Hash.ZERO)); | |
+ | |
+ System.out.println("Initialized a shy repository in " + repository.getRootPath()); | |
+ return repository; | |
+ } | |
+ | |
+ /** | |
+ * Returns current directory file's path in ".shy/commit/" directory. | |
+ * @param path file which's path to transform | |
+ * @return transformed path in ".shy/commit/" | |
+ */ | |
+ private Path getCommitPath(Path path) throws IOException { | |
+ Path commitPath = getRepositoryPath().resolve("commit"); | |
+ /* | |
+ Beware of the pitfalls of oh-so-wonderful Path: | |
+ Path#toAbsolutePath does NOT normalize the path to an actual absolute path, | |
+ but simply prepends the current working directory. | |
+ */ | |
+ return commitPath.resolve(rootPath.relativize(path.toRealPath())); | |
} | |
/** | |
* Copies given file to its respective directory in ".shy/commit/" directory. | |
- * @param file file that user wants to add to repository | |
+ * @param path file that user wants to add to repository | |
* @throws IOException if file can't be found or copying fails | |
*/ | |
- public void add(File file) throws IOException { | |
- File fullFilePath = fullFilePath(file); | |
- fullFilePath.getParentFile().mkdirs(); | |
- try (InputStream input = new FileInputStream(file)) { | |
- try (OutputStream output = new FileOutputStream(fullFilePath)) { | |
- IOUtils.copy(input, output); | |
- } | |
- } | |
+ public void add(Path path) throws IOException { | |
+ Path commitPath = getCommitPath(path); | |
+ /* | |
+ Beware of the pitfalls of oh-so-wonderful Path: | |
+ Files.createDirectories does unintuitive things for paths ending in "..". | |
+ For example, "/tmp/foo/bar/.." will cause "/tmp/foo/bar/" to be created yet it's not in the normalized path. | |
+ */ | |
+ Files.createDirectories(commitPath.getParent()); | |
+ Files.copy(path, commitPath); | |
} | |
/** | |
* Removes given file from its directory in ".shy/commit". | |
- * @param file file that user wants to remove from repository | |
+ * @param path file that user wants to remove from repository | |
* @throws IOException if file could not be deleted | |
*/ | |
- public void remove(File file) throws IOException { | |
- Files.deleteIfExists(fullFilePath(file).toPath()); | |
+ public void remove(Path path) throws IOException { | |
+ Files.deleteIfExists(getCommitPath(path)); | |
} | |
/** | |
@@ -137,7 +135,7 @@ public class Repository { | |
* @throws IOException if there was a problem storing the tree | |
*/ | |
private Hash createCommitTree() throws IOException { | |
- Tree tree = new Tree.Builder(storage).fromDirectory(new File(repositoryDirectory, "commit")).create(); | |
+ Tree tree = new Tree.Builder(storage).fromDirectory(getRepositoryPath().resolve("commit")).create(); | |
return storage.put(tree.inputify()); | |
} | |
@@ -148,8 +146,8 @@ public class Repository { | |
*/ | |
public void commit(String message) throws IOException { | |
Hash tree = createCommitTree(); | |
- File currentFile = new File(repositoryDirectory, "current"); | |
- Hash parent = new Hash(IOUtils.toString(new FileInputStream(currentFile), "UTF-8")); | |
+ Path currentPath = getRepositoryPath().resolve("current"); | |
+ Hash parent = new Hash(IOUtils.toString(Files.newInputStream(currentPath), "UTF-8")); | |
Commit commit = new Commit.Builder() | |
.setTree(tree) | |
@@ -160,32 +158,8 @@ public class Repository { | |
.create(); | |
Hash hash = storage.put(commit.inputify()); | |
- File branchFile = new File(new File(repositoryDirectory, "branches"), "master"); // TODO: 26.03.16 update correct branch | |
- IOUtils.write(hash.toString(), new TeeOutputStream(new FileOutputStream(currentFile), new FileOutputStream(branchFile)), "UTF-8"); | |
- } | |
- | |
- /** | |
- * Creates given file's path relative to repository's directory. | |
- * @param file file that's relative path is wanted to be create | |
- * @return file's path relative to repository's directory | |
- */ | |
- private File relativeFilePath(File file) { | |
- File fileDir = new File(System.getProperty("user.dir"), file.getPath()).getParentFile(); | |
- | |
- Path path = Paths.get(fileDir.getPath()); | |
- path = this.rootDirectory.toPath().relativize(path); | |
- | |
- return new File(path.toFile().getPath(), file.getName()); | |
- } | |
- | |
- /** | |
- * Creates full path from system's root to given file in ".shy/commit/" directory. | |
- * @param file file that's path is wanted to be create | |
- * @return file path from system's root to given file'is directory in ".shy/commit/" | |
- */ | |
- private File fullFilePath(File file) { | |
- File repositoryDirectory = new File(this.rootDirectory.getPath(), ".shy/commit/"); | |
- return new File(repositoryDirectory, relativeFilePath(file).getPath()); | |
+ branches.put("master", new Branch(hash)); // TODO: 26.03.16 update correct branch | |
+ IOUtils.write(hash.toString(), Files.newOutputStream(currentPath)); | |
} | |
/** | |
@@ -194,8 +168,7 @@ public class Repository { | |
* @throws IOException if file '.shy/author' does not exist or reading fails | |
*/ | |
public Author getAuthor() throws IOException { | |
- FileInputStream fis = new FileInputStream(new File(repositoryDirectory, "author")); | |
- return Json.read(fis, Author.class); | |
+ return Json.read(Files.newInputStream(getAuthorPath()), Author.class); | |
} | |
/** | |
@@ -204,10 +177,43 @@ public class Repository { | |
* @throws IOException if write fails | |
*/ | |
public void setAuthor(Author author) throws IOException { | |
- author.write(new FileOutputStream(new File(repositoryDirectory, "author"))); | |
+ author.write(Files.newOutputStream(getAuthorPath())); | |
} | |
public NamedObjectMap<Branch> getBranches() { | |
return branches; | |
} | |
+ | |
+ /** | |
+ * Returns repository's root path. | |
+ * @return root directory path | |
+ */ | |
+ public Path getRootPath() { | |
+ return rootPath; | |
+ } | |
+ | |
+ /** | |
+ * Returns repository's ".shy/" directory path in given root directory. | |
+ * @param rootPath root directory of repository | |
+ * @return repository directory path | |
+ */ | |
+ private static Path getRepositoryPath(Path rootPath) { | |
+ return rootPath.resolve(".shy"); | |
+ } | |
+ | |
+ /** | |
+ * Returns repository's ".shy/" directory path. | |
+ * @return repository directory path | |
+ */ | |
+ private Path getRepositoryPath() { | |
+ return getRepositoryPath(rootPath); | |
+ } | |
+ | |
+ /** | |
+ * Returns repository's "author" file path. | |
+ * @return author file path | |
+ */ | |
+ private Path getAuthorPath() { | |
+ return getRepositoryPath().resolve("author"); | |
+ } | |
} | |
\ No newline at end of file | |
diff --git a/src/main/java/ee/shy/core/Tree.java b/src/main/java/ee/shy/core/Tree.java | |
index a4ecfe4..274d4c3 100644 | |
--- a/src/main/java/ee/shy/core/Tree.java | |
+++ b/src/main/java/ee/shy/core/Tree.java | |
@@ -4,12 +4,11 @@ import ee.shy.io.Jsonable; | |
import ee.shy.storage.DataStorage; | |
import ee.shy.storage.Hash; | |
-import java.io.File; | |
-import java.io.FileInputStream; | |
import java.io.IOException; | |
-import java.util.Arrays; | |
-import java.util.Map; | |
-import java.util.TreeMap; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
+import java.util.*; | |
+import java.util.stream.Collectors; | |
/** | |
* Class representing a directory tree. | |
@@ -68,22 +67,20 @@ public class Tree extends Jsonable { | |
* @return builder itself | |
* @throws IOException if there was a problem reading an addable file or tree to storage | |
*/ | |
- public Builder fromDirectory(File directory) throws IOException { | |
- File[] files = directory.listFiles(); | |
- if (files == null) | |
- throw new IOException("Attempted to build Tree from a non-directory"); | |
+ public Builder fromDirectory(Path directory) throws IOException { | |
+ List<Path> files = new ArrayList<>(Files.list(directory).collect(Collectors.toList())); // TODO: 6.04.16 Stream#toCollection for creating ArrayList | |
- Arrays.sort(files); // guarantee stable order | |
+ Collections.sort(files); | |
- for (File file : files) { | |
- if (file.isFile()) { | |
- Hash hash = storage.put(new FileInputStream(file)); | |
- addItem(file.getName(), new TreeItem(TreeItem.Type.FILE, hash)); | |
+ for (Path file : files) { | |
+ if (Files.isRegularFile(file)) { | |
+ Hash hash = storage.put(Files.newInputStream(file)); | |
+ addItem(file.getFileName().toString(), new TreeItem(TreeItem.Type.FILE, hash)); | |
} | |
- else if (file.isDirectory()) { | |
+ else if (Files.isDirectory(file)) { | |
Tree tree = new Builder(storage).fromDirectory(file).create(); | |
Hash hash = storage.put(tree.inputify()); | |
- addItem(file.getName(), new TreeItem(TreeItem.Type.TREE, hash)); | |
+ addItem(file.getFileName().toString(), new TreeItem(TreeItem.Type.TREE, hash)); | |
} | |
} | |
diff --git a/src/main/java/ee/shy/io/PathUtils.java b/src/main/java/ee/shy/io/PathUtils.java | |
new file mode 100644 | |
index 0000000..b3b4bc2 | |
--- /dev/null | |
+++ b/src/main/java/ee/shy/io/PathUtils.java | |
@@ -0,0 +1,42 @@ | |
+package ee.shy.io; | |
+ | |
+import java.io.IOException; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
+import java.nio.file.Paths; | |
+ | |
+/** | |
+ * Utilities class for I/O-related methods. | |
+ */ | |
+public class PathUtils { | |
+ private PathUtils() { | |
+ | |
+ } | |
+ | |
+ /** | |
+ * Returns current working directory as path. | |
+ * @return current working directory | |
+ */ | |
+ public static Path getCurrentPath() { | |
+ return Paths.get(System.getProperty("user.dir")); | |
+ } | |
+ | |
+ /** | |
+ * Adds given extension to file path. | |
+ * @param path file path to extend | |
+ * @param extension extension to add | |
+ * @return file path with given extension | |
+ */ | |
+ public static Path addExtension(Path path, String extension) { | |
+ return path.resolveSibling(path.getFileName().toString() + extension); | |
+ } | |
+ | |
+ /** | |
+ * Creates given path's parent directories. | |
+ * If path itself is a directory, it too will be created. | |
+ * @param path path which's parent directories to create | |
+ */ | |
+ public static void createParentDirectories(Path path) throws IOException { | |
+ Files.createDirectories(Files.isDirectory(path) ? path : path.getParent()); | |
+ } | |
+} | |
diff --git a/src/main/java/ee/shy/storage/AggregateFileAccessor.java b/src/main/java/ee/shy/storage/AggregateFileAccessor.java | |
index 8bf8388..df6ae83 100644 | |
--- a/src/main/java/ee/shy/storage/AggregateFileAccessor.java | |
+++ b/src/main/java/ee/shy/storage/AggregateFileAccessor.java | |
@@ -1,8 +1,8 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
import java.io.IOException; | |
import java.io.InputStream; | |
+import java.nio.file.Path; | |
import java.util.List; | |
/** | |
@@ -25,26 +25,26 @@ public class AggregateFileAccessor implements FileAccessor { | |
/** | |
* Adds file content via first file accessor. | |
- * @param file base path of file to add | |
+ * @param path base path of file to add | |
* @param source input stream to get data from | |
* @throws IOException if there was a problem reading the input stream or writing to the file | |
*/ | |
@Override | |
- public void add(File file, InputStream source) throws IOException { | |
- accessors.get(0).add(file, source); // always use first accessor for add | |
+ public void add(Path path, InputStream source) throws IOException { | |
+ accessors.get(0).add(path, source); // always use first accessor for add | |
} | |
/** | |
* Gets file content via first successful file accessor. | |
- * @param file base path of file to get | |
+ * @param path base path of file to get | |
* @return input stream to get data from | |
* @throws IOException if there was a problem reading from the file | |
*/ | |
@Override | |
- public InputStream get(File file) throws IOException { | |
+ public InputStream get(Path path) throws IOException { | |
InputStream source; | |
for (FileAccessor accessor : accessors) { | |
- if ((source = accessor.get(file)) != null) | |
+ if ((source = accessor.get(path)) != null) | |
return source; | |
} | |
return null; | |
diff --git a/src/main/java/ee/shy/storage/FileAccessor.java b/src/main/java/ee/shy/storage/FileAccessor.java | |
index 6bc11e4..91c9b70 100644 | |
--- a/src/main/java/ee/shy/storage/FileAccessor.java | |
+++ b/src/main/java/ee/shy/storage/FileAccessor.java | |
@@ -1,8 +1,8 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
import java.io.IOException; | |
import java.io.InputStream; | |
+import java.nio.file.Path; | |
/** | |
* An interface for accessing file content by base path from a {@link FileLocator}. | |
@@ -11,17 +11,17 @@ import java.io.InputStream; | |
public interface FileAccessor { | |
/** | |
* Adds file content to given base path of file | |
- * @param file base path of file to add | |
+ * @param path base path of file to add | |
* @param source input stream to get data from | |
* @throws IOException if there was a problem reading the input stream or writing to the file | |
*/ | |
- void add(File file, InputStream source) throws IOException; | |
+ void add(Path path, InputStream source) throws IOException; | |
/** | |
* Gets file content from given base path of file | |
- * @param file base path of file to get | |
+ * @param path base path of file to get | |
* @return input stream to get data from | |
* @throws IOException if there was a problem reading from some input | |
*/ | |
- InputStream get(File file) throws IOException; | |
+ InputStream get(Path path) throws IOException; | |
} | |
diff --git a/src/main/java/ee/shy/storage/FileLocator.java b/src/main/java/ee/shy/storage/FileLocator.java | |
index cf40257..f178c12 100644 | |
--- a/src/main/java/ee/shy/storage/FileLocator.java | |
+++ b/src/main/java/ee/shy/storage/FileLocator.java | |
@@ -1,6 +1,8 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
+import java.io.IOException; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
/** | |
* An abstract class for locating files by hash. | |
@@ -10,18 +12,14 @@ public abstract class FileLocator { | |
/** | |
* Root directory to use. | |
*/ | |
- protected final File root; | |
+ protected final Path root; | |
/** | |
* Constructs a new locator with given root. | |
* @param root root directory to use | |
*/ | |
- public FileLocator(File root) { | |
- if (!root.exists()) | |
- root.mkdirs(); | |
- if (!root.isDirectory()) | |
- throw new RuntimeException("root must be a directory"); // TODO: 9.03.16 throw better exception | |
- | |
+ public FileLocator(Path root) throws IOException { | |
+ Files.createDirectories(root); | |
this.root = root; | |
} | |
@@ -31,7 +29,7 @@ public abstract class FileLocator { | |
* @param hash hash to get path for | |
* @return path to file for given hash | |
*/ | |
- public File locate(Hash hash) { | |
+ public Path locate(Hash hash) throws IOException { | |
return null; | |
} | |
@@ -41,7 +39,7 @@ public abstract class FileLocator { | |
* @param hash hash to get path for | |
* @return supposed path to file for given hash | |
*/ | |
- public File locateAdd(Hash hash) { | |
+ public Path locateAdd(Hash hash) throws IOException { | |
return locate(hash); | |
} | |
@@ -51,7 +49,7 @@ public abstract class FileLocator { | |
* @param hash hash to get path for | |
* @return path to file for given hash | |
*/ | |
- public File locateGet(Hash hash) { | |
+ public Path locateGet(Hash hash) throws IOException { | |
return locate(hash); | |
} | |
} | |
diff --git a/src/main/java/ee/shy/storage/FlatFileLocator.java b/src/main/java/ee/shy/storage/FlatFileLocator.java | |
index 22faf46..197d249 100644 | |
--- a/src/main/java/ee/shy/storage/FlatFileLocator.java | |
+++ b/src/main/java/ee/shy/storage/FlatFileLocator.java | |
@@ -1,6 +1,7 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
+import java.io.IOException; | |
+import java.nio.file.Path; | |
/** | |
* File locator for having all hashes in the root directory. | |
@@ -10,12 +11,12 @@ public class FlatFileLocator extends FileLocator { | |
* Constructs a new flat file locator with given root. | |
* @param root root directory to use | |
*/ | |
- public FlatFileLocator(File root) { | |
+ public FlatFileLocator(Path root) throws IOException { | |
super(root); | |
} | |
@Override | |
- public File locate(Hash hash) { | |
- return new File(root, hash.toString()); | |
+ public Path locate(Hash hash) { | |
+ return root.resolve(hash.toString()); | |
} | |
} | |
diff --git a/src/main/java/ee/shy/storage/GitFileLocator.java b/src/main/java/ee/shy/storage/GitFileLocator.java | |
index 46ff539..36728a6 100644 | |
--- a/src/main/java/ee/shy/storage/GitFileLocator.java | |
+++ b/src/main/java/ee/shy/storage/GitFileLocator.java | |
@@ -1,6 +1,7 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
+import java.io.IOException; | |
+import java.nio.file.Path; | |
/** | |
* File locator for having hashes in git-like directory structure in the root directory: | |
@@ -12,7 +13,7 @@ public class GitFileLocator extends NestedFileLocator { | |
* Constructs a new git file locator with given root. | |
* @param root root directory to use | |
*/ | |
- public GitFileLocator(File root) { | |
+ public GitFileLocator(Path root) throws IOException { | |
super(root, 2, 1); | |
} | |
} | |
diff --git a/src/main/java/ee/shy/storage/GzipFileAccessor.java b/src/main/java/ee/shy/storage/GzipFileAccessor.java | |
index ca1fb2b..393bc76 100644 | |
--- a/src/main/java/ee/shy/storage/GzipFileAccessor.java | |
+++ b/src/main/java/ee/shy/storage/GzipFileAccessor.java | |
@@ -1,8 +1,11 @@ | |
package ee.shy.storage; | |
+import ee.shy.io.PathUtils; | |
import org.apache.commons.io.IOUtils; | |
import java.io.*; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
import java.util.zip.GZIPInputStream; | |
import java.util.zip.GZIPOutputStream; | |
@@ -17,16 +20,16 @@ public class GzipFileAccessor implements FileAccessor { | |
private static final String EXTENSION = ".gz"; // TODO: 9.03.16 create superclass for extension handling | |
@Override | |
- public void add(File file, InputStream source) throws IOException { | |
- try (GZIPOutputStream target = new GZIPOutputStream(new FileOutputStream(Util.addExtension(file, EXTENSION)))) { | |
+ public void add(Path path, InputStream source) throws IOException { | |
+ try (GZIPOutputStream target = new GZIPOutputStream(Files.newOutputStream(PathUtils.addExtension(path, EXTENSION)))) { | |
IOUtils.copy(source, target); | |
} | |
} | |
@Override | |
- public InputStream get(File file) throws IOException { | |
+ public InputStream get(Path path) throws IOException { | |
try { | |
- return new GZIPInputStream(new FileInputStream(Util.addExtension(file, EXTENSION))); | |
+ return new GZIPInputStream(Files.newInputStream(PathUtils.addExtension(path, EXTENSION))); | |
} | |
catch (FileNotFoundException e) { | |
return null; | |
diff --git a/src/main/java/ee/shy/storage/NestedFileLocator.java b/src/main/java/ee/shy/storage/NestedFileLocator.java | |
index e57f194..126a358 100644 | |
--- a/src/main/java/ee/shy/storage/NestedFileLocator.java | |
+++ b/src/main/java/ee/shy/storage/NestedFileLocator.java | |
@@ -1,6 +1,9 @@ | |
package ee.shy.storage; | |
-import java.io.File; | |
+import ee.shy.io.PathUtils; | |
+ | |
+import java.io.IOException; | |
+import java.nio.file.Path; | |
/** | |
* File locator for having hashes in nested directory structure in the root directory: | |
@@ -29,7 +32,7 @@ public class NestedFileLocator extends FileLocator { | |
* @param root root directory to use | |
* @param directoryLength length of each subdirectory name | |
*/ | |
- public NestedFileLocator(File root, int directoryLength) { | |
+ public NestedFileLocator(Path root, int directoryLength) throws IOException { | |
this(root, directoryLength, DEPTH_UNLIMITED); | |
} | |
@@ -39,28 +42,29 @@ public class NestedFileLocator extends FileLocator { | |
* @param directoryLength length of each subdirectory name | |
* @param depthMax maximum nesting depth, unlimited with {@link #DEPTH_UNLIMITED} | |
*/ | |
- public NestedFileLocator(File root, int directoryLength, int depthMax) { | |
+ public NestedFileLocator(Path root, int directoryLength, int depthMax) throws IOException { | |
super(root); | |
this.directoryLength = directoryLength; | |
this.depthMax = depthMax; | |
} | |
@Override | |
- public File locate(Hash hash) { | |
+ public Path locate(Hash hash) { | |
String hashString = hash.toString(); | |
- File file = root; | |
+ Path path = root; | |
int depth; | |
for (depth = 0; (depthMax == DEPTH_UNLIMITED || depth < depthMax) && (directoryLength * (depth + 1) < hashString.length()); depth++) | |
- file = new File(file, hashString.substring(directoryLength * depth, directoryLength * (depth + 1))); | |
+ path = path.resolve(hashString.substring(directoryLength * depth, directoryLength * (depth + 1))); | |
- file = new File(file, hashString.substring(directoryLength * depth)); | |
- return file; | |
+ path = path.resolve(hashString.substring(directoryLength * depth)); | |
+ return path; | |
} | |
@Override | |
- public File locateAdd(Hash hash) { | |
- File file = locate(hash); | |
- return Util.ensurePath(file) ? file : null; | |
+ public Path locateAdd(Hash hash) throws IOException { | |
+ Path path = locate(hash); | |
+ PathUtils.createParentDirectories(path); | |
+ return path; | |
} | |
} | |
diff --git a/src/main/java/ee/shy/storage/PlainFileAccessor.java b/src/main/java/ee/shy/storage/PlainFileAccessor.java | |
index 8bd6b14..8cf010a 100644 | |
--- a/src/main/java/ee/shy/storage/PlainFileAccessor.java | |
+++ b/src/main/java/ee/shy/storage/PlainFileAccessor.java | |
@@ -3,6 +3,8 @@ package ee.shy.storage; | |
import org.apache.commons.io.IOUtils; | |
import java.io.*; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
/** | |
* File accessor to store data plainly as-is. | |
@@ -10,19 +12,19 @@ import java.io.*; | |
*/ | |
public class PlainFileAccessor implements FileAccessor { | |
@Override | |
- public void add(File file, InputStream source) throws IOException { | |
- try (FileOutputStream target = new FileOutputStream(file)) { | |
+ public void add(Path path, InputStream source) throws IOException { | |
+ try (OutputStream target = Files.newOutputStream(path)) { | |
IOUtils.copy(source, target); | |
} | |
} | |
@Override | |
- public InputStream get(File file) { | |
+ public InputStream get(Path path) throws IOException { | |
try { | |
- return new FileInputStream(file); | |
+ return Files.newInputStream(path); | |
} | |
- catch (FileNotFoundException e) { | |
+ catch (FileNotFoundException e) { // TODO: 6.04.16 don't catch exception | |
return null; | |
} | |
} | |
diff --git a/src/main/java/ee/shy/storage/StorageTest.java b/src/main/java/ee/shy/storage/StorageTest.java | |
index 6abc1f9..83db965 100644 | |
--- a/src/main/java/ee/shy/storage/StorageTest.java | |
+++ b/src/main/java/ee/shy/storage/StorageTest.java | |
@@ -3,21 +3,22 @@ package ee.shy.storage; | |
import org.apache.commons.io.IOUtils; | |
import java.io.*; | |
+import java.nio.file.Paths; | |
import java.util.Arrays; | |
public class StorageTest { | |
public static void main(String[] args) throws IOException { | |
DataStorage storage = new FileStorage( | |
Arrays.asList( | |
- new GitFileLocator(new File("teststore")), | |
- new FlatFileLocator(new File("teststore2"))), | |
+ new GitFileLocator(Paths.get("teststore")), | |
+ new FlatFileLocator(Paths.get("teststore2"))), | |
new AggregateFileAccessor(Arrays.asList( | |
new GzipFileAccessor(), | |
new PlainFileAccessor()))); | |
- /*Hash h1 = storage.add(new ByteArrayInputStream("foo".getBytes("UTF-8"))); | |
- Hash h2 = storage.add(new ByteArrayInputStream("bar".getBytes("UTF-8"))); | |
- Hash h3 = storage.add(new FileInputStream("README.md")); | |
+ Hash h1 = storage.put(new ByteArrayInputStream("foo".getBytes("UTF-8"))); | |
+ Hash h2 = storage.put(new ByteArrayInputStream("bar".getBytes("UTF-8"))); | |
+ Hash h3 = storage.put(new FileInputStream("README.md")); | |
System.out.println(h1); | |
System.out.println(h2); | |
@@ -28,7 +29,7 @@ public class StorageTest { | |
InputStream i2 = storage.get(h2); | |
System.out.println(new String(IOUtils.toByteArray(i2), "UTF-8")); | |
InputStream i3 = storage.get(h3); | |
- IOUtils.copyStream(i3, new FileOutputStream("README2.md"));*/ | |
+ IOUtils.copy(i3, new FileOutputStream("README2.md")); | |
InputStream i = storage.get(new Hash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")); | |
System.out.println(new String(IOUtils.toByteArray(i), "UTF-8")); | |
diff --git a/src/main/java/ee/shy/storage/Util.java b/src/main/java/ee/shy/storage/Util.java | |
deleted file mode 100644 | |
index c3f4dbc..0000000 | |
--- a/src/main/java/ee/shy/storage/Util.java | |
+++ /dev/null | |
@@ -1,39 +0,0 @@ | |
-package ee.shy.storage; | |
- | |
-import java.io.File; | |
- | |
-/** | |
- * Utilities class for storage-related functions. | |
- */ | |
-public class Util { | |
- private Util() { | |
- | |
- } | |
- | |
- /** | |
- * Adds given extension to file path. | |
- * @param file file path to extend | |
- * @param extension extension to add | |
- * @return file path with given extension | |
- */ | |
- public static File addExtension(File file, String extension) { | |
- return new File(file.getAbsolutePath() + extension); | |
- } | |
- | |
- /** | |
- * Ensures file path's validity by creating required missing parent directories. | |
- * @param file file path which's validity to ensure | |
- * @return whether file path is now valid | |
- */ | |
- public static boolean ensurePath(File file) { | |
- if (file.isDirectory()) | |
- return true; | |
- else { | |
- File parent = file.getParentFile(); | |
- if (parent.exists()) | |
- return parent.isDirectory(); | |
- else | |
- return parent.mkdirs(); | |
- } | |
- } | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment