diff --git a/.gitignore b/.gitignore index d2d8423..3fe45fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ /git .DS_Store index -.txt \ No newline at end of file +*.txt \ No newline at end of file diff --git a/Blob.java b/Blob.java index 437752d..7095d8e 100644 --- a/Blob.java +++ b/Blob.java @@ -10,8 +10,8 @@ public class Blob { //Global variable to toggle compression on or off private static boolean compressionEnabled = false; - //backs up a directory via making its tree given its path - public static void createTree (String directoryPath) throws IOException, NoSuchAlgorithmException, ObjectsDirectoryNotFoundException{ + //backs up a directory via making its tree given its path and returns the tree file + public static String createTree (String directoryPath) throws IOException, NoSuchAlgorithmException, ObjectsDirectoryNotFoundException{ File direct = new File (directoryPath); //checks if the directory exists @@ -29,43 +29,38 @@ public static void createTree (String directoryPath) throws IOException, NoSuchA File [] directoryList = direct.listFiles(); StringBuilder tree = new StringBuilder(); - // Check if the directory is empty - if (directoryList == null || directoryList.length == 0) { - System.out.println("Empty directory: " + directoryPath); - tree.append("empty directory\n"); // Special marker for an empty directory - } - //goes through the directory - for (int i=0; i=3) { + if (pathExistsCounter>=4) { System.out.println("Git Repository already exists"); } } + public String commit (String author, String message) throws IOException, NoSuchAlgorithmException{ + String hashOfCommit, hashOfCurrentTree, hashOfLastCommit; + StringBuilder commitData = new StringBuilder(); + File head = new File ("./git/HEAD"); + hashOfLastCommit = new String (Blob.readFileContent(head.getPath()), StandardCharsets.UTF_8); //grabbing hash of last commit from head file + //getting the hash of the current tree; adding index file data to previous index file data + StringBuilder snapShot = new StringBuilder(); + if (!hashOfLastCommit.equals("")){ + BufferedReader cr = new BufferedReader(new FileReader("./git/objects/" + hashOfLastCommit)); + String treeOfPreviousCommit = cr.readLine().split(" ")[1]; + cr.close(); + if(!treeOfPreviousCommit.equals("")){ + BufferedReader tr = new BufferedReader(new FileReader ("./git/objects/" + treeOfPreviousCommit)); + while (tr.ready()){ + snapShot.append(tr.readLine() + "\n"); + } + tr.close(); + } + } + BufferedReader ir = new BufferedReader(new FileReader("./git/index")); + while (ir.ready()){ + snapShot.append(ir.readLine() + "\n"); + } + ir.close(); + hashOfCurrentTree = Blob.generateSha1(snapShot.toString()); + File thisTreeFile = new File ("./git/objects/" + hashOfCurrentTree); + thisTreeFile.createNewFile(); + BufferedWriter bww = new BufferedWriter(new FileWriter (thisTreeFile)); + bww.write(snapShot.toString()); + bww.close(); + + //making commit file data + commitData.append("tree: " + hashOfCurrentTree + "\nparent: " + hashOfLastCommit + "\nauthor: " + + author + "\ndate: " + LocalDate.now() + "\nmessage: " + message); + + // backing up the commit file in the objects folder + hashOfCommit = Blob.generateSha1(commitData.toString()); + File thisCommit = new File ("./git/objects/" + hashOfCommit); + thisCommit.createNewFile(); + BufferedWriter bw = new BufferedWriter(new FileWriter (thisCommit)); + bw.write(commitData.toString()); + bw.close(); + + //updating head file + BufferedWriter br = new BufferedWriter(new FileWriter("./git/HEAD")); + br.write(hashOfCommit); + br.close(); + //clearing index file + File index = new File ("./git/index"); + index.delete(); + index.createNewFile(); + + //returning hash of new commit + return hashOfCommit; + } + //Prepares a file to + public void stage (String filePath) throws NoSuchAlgorithmException, IOException, ObjectsDirectoryNotFoundException{ + File fileToStage = new File (filePath); + if (!fileToStage.exists()) + fileToStage.createNewFile(); + if (fileToStage.isDirectory()) + Blob.createTree(filePath); + else + Blob.createBlob(filePath); + } + + public void checkout (String commitHash) throws IOException{ + //deleting all current files besides git + File current = new File ("."); + File [] currentFiles = current.listFiles(); + for (File f : currentFiles){ + if (!f.getName().equals("git")){ + deleteRecursive (f); + } + } + BufferedReader treeFinder = new BufferedReader (new FileReader ("./git/objects/" + commitHash)); + BufferedReader br = new BufferedReader (new FileReader ("./git/objects/" + treeFinder.readLine().split(" ") [1])); + while (br.ready()){ + String [] currentFileInfo = br.readLine().split(" "); + makeFile(currentFileInfo); + } + } + + private void makeFile(String[] currentFileInfo) throws IOException { + if (currentFileInfo [0].equals("blob")){ + File newBlob = new File (currentFileInfo[2]); + newBlob.createNewFile(); + BufferedReader br = new BufferedReader (new FileReader ("./git/objects" + currentFileInfo[1])); + BufferedWriter bw = new BufferedWriter (new FileWriter (newBlob)); + while (br.ready()){ + bw.write (br.read()); + } + br.close(); + bw.close(); + } + else{ + File newTree = new File (currentFileInfo[2]); + newTree.mkdirs(); + BufferedReader br = new BufferedReader (new FileReader ("./git/objects" + currentFileInfo[1])); + while (br.ready()){ + makeFile(br.readLine().split(" ")); + } + br.close(); + } + } + + private static void deleteRecursive (File file){ + if (!file.isDirectory()){ + file.delete(); + } + else{ + File [] files = file.listFiles(); + for (File f : files){ + deleteRecursive(f); + f.delete(); + } + file.delete(); + } + } //Tests main methods private static void testRepoInit() { //Testing file creation @@ -71,7 +203,19 @@ private static void testRepoInit() { private static boolean doesPathExist (String path) { return Files.exists(Paths.get(path)); } - + private static void resetTestFiles (String filePath) throws IOException{ + File git = new File (filePath); + File [] files = git.listFiles(); + for (File f : files){ + if (!f.isDirectory()) + f.delete(); + else{ + resetTestFiles(f.getPath()); + f.delete(); + } + } + initGitRepo(); + } //Deletes chosen path, returns true if path deleted, false if path did not exist private static boolean deletePath(String path) { try { @@ -104,4 +248,4 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx return false; } } -} \ No newline at end of file +} diff --git a/GitInterface.java b/GitInterface.java new file mode 100644 index 0000000..d5155ac --- /dev/null +++ b/GitInterface.java @@ -0,0 +1,31 @@ +import java.io.*; +import java.security.NoSuchAlgorithmException; +public abstract interface GitInterface { + + /** + * Stages a file for the next commit. + * + * @param filePath The path to the file to be staged. + */ + void stage(String filePath)throws NoSuchAlgorithmException, IOException, ObjectsDirectoryNotFoundException; + + /** + * Creates a commit with the given author and message. + * It should capture the current state of the repository, + * update the HEAD, and return the commit hash. + * + * @param author The name of the author making the commit. + * @param message The commit message describing the changes. + * @return The SHA1 hash of the new commit. + */ + String commit(String author, String message) throws IOException, NoSuchAlgorithmException; + + /** + * EXTRA CREDIT: Checks out a specific commit given its hash. + * This should update the working directory to match the + * state of the repository at that commit. + * + * @param commitHash The SHA1 hash of the commit to check out. + */ + void checkout(String commitHash) throws NoSuchAlgorithmException, IOException, ObjectsDirectoryNotFoundException; +} diff --git a/README.md b/README.md index 727262b..a74bac9 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ -# git-project-Nathaniel +I did code commit, I tested it, seems to work well + +I did code stage, I tested it, it also seems to work well + +I did code checkout, I tested it, works for checking out commits with just added files, but is not fully functional for checking out commits with +added directories because of inconsistencies between the full relative path listed in the index file, and just the parent/name type path listed in the +tree files. (this was coded in a previous day, but the formatting was again, incosistent with index so I didnt fully work it out) + +^^this was the major bug that I ran into. \ No newline at end of file