diff --git a/.gitignore b/.gitignore index 2ad6453..0d7fbd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /git .DS_Store +*.txt \ No newline at end of file diff --git a/Git.java b/Git.java index f6a74a6..1dfccab 100644 --- a/Git.java +++ b/Git.java @@ -1,13 +1,15 @@ import java.io.*; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; -import java.util.Stack; +import java.util.*; import java.util.ArrayList; import java.util.Base64; import java.util.Comparator; import java.util.HashSet; import java.util.zip.Deflater; import java.util.zip.Inflater; +import java.time.*; +import java.time.format.*; //LOOK AT TOP OF README FOR AN IMPORTANT EXPLANATION! @@ -38,7 +40,10 @@ public static void makeDirectory(String filePath, String folderName){ File newDir = new File(path); newDir.mkdir(); } - + //IF THE HEAD EVER HAS STUFF OTHER THAN THE LATEST COMMIT, EDIT THIS METHOD + public static String retrieveLatestCommit(){ + return readFile("git", "HEAD"); + } private static void deleteDirectory(File file) { for (File subfile : file.listFiles()) { @@ -163,9 +168,9 @@ && directoryExists("git", "objects") && directoryExists(null, "git")){ deleteDirectory("git", "index"); //in case "cloggs" options makeFile("git/objects", "index"); - + //FIXED: THE HEAD FILE ISN'T SUPPOSED TO BE IN THE OBEJCTS FOLDER deleteDirectory("git", "HEAD"); //in case "cloggs" options - makeFile("git/objects", "HEAD"); + makeFile("git", "HEAD"); } public static void blobify(String filePath, String fileName){ @@ -307,7 +312,7 @@ public static String makeTree(String filePath, String fileName){ //returns hash //NOTE: Does not automatically BLOB everything inside of it! //That should have been done when indexed anyway. - public static void makeIndexTree(){ + public static String makeIndexTree(){ StringBuilder rootTreeContents = new StringBuilder(); String indexFile = readFile("git/objects", "index"); String[] entriesArr = indexFile.split("\n"); @@ -334,8 +339,9 @@ public static void makeIndexTree(){ } String contents = rootTreeContents.toString(); String hash = hash(contents); - makeFile(null, hash); - writeToFile(null, hash, contents); + makeFile("git/objects", hash); + writeToFile("git/objects", hash, contents); + return hash; } //returns tree hash @@ -372,7 +378,28 @@ public static String makeIndexTreeHelper(ArrayList entries, String direc writeToFile("git/objects", treeHash, entryContent); return treeHash; } - + public static String makeCommit(){ + StringBuilder outputSB = new StringBuilder(); + outputSB.append("tree: "+makeIndexTree()+"\n"); + outputSB.append("parent: "+retrieveLatestCommit()+"\n"); + Scanner sc = new Scanner(System.in); + System.out.println("Enter author name:"); + outputSB.append("author: "+sc.nextLine()+"\n"); + sc.reset(); + //i hope geeksForGeeks was right about what this code does + LocalDateTime localDateTime = LocalDateTime.now(); + DateTimeFormatter validDateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss"); + outputSB.append("date: "+ localDateTime.format(validDateTimeFormatter) + "\n"); + System.out.println("Enter commit message:"); + outputSB.append("message: "+sc.nextLine()); + sc.close(); + String commitHash = hash(outputSB.toString()); + makeFile("git/objects", commitHash); + writeToFile("git/objects", commitHash, outputSB.toString()); + // change this if more info needs to be stored on the HEAD + writeToFile("git", "HEAD", commitHash); + return commitHash; + } public static void main(String[] args){ cleanGit(); intializeRepo(); @@ -381,6 +408,6 @@ public static void main(String[] args){ index("A/C", "f4"); index("A", "f1"); index(null, ".gitignore"); - makeIndexTree(); + makeIndexTree(); } } \ No newline at end of file diff --git a/GitWrapper.java b/GitWrapper.java new file mode 100644 index 0000000..c974b22 --- /dev/null +++ b/GitWrapper.java @@ -0,0 +1,82 @@ +import java.nio.file.Paths; +import java.time.*; +import java.time.format.*; +public class GitWrapper { + /** + * Initializes a new Git repository. + * This method creates the necessary directory structure + * and initial files (index, HEAD) required for a Git repository. + */ + public void init() { + Git.intializeRepo(); + }; + + /** + * Stages a file for the next commit. + * This method adds a file to the index file. + * If the file does not exist, it throws an IOException. + * If the file is a directory, it throws an IOException. + * If the file is already in the index, it does nothing. + * If the file is successfully staged, it creates a blob for the file. + * @param filePath The path to the file to be staged. + */ + public void add(String filePath) { + //Shimone, this is what you get when you split the parent path, and file name + String parentPath = Paths.get(filePath).getParent().toString(); + String childPath = Paths.get(filePath).getFileName().toString(); + Git.index(parentPath, childPath); + Git.blobify(parentPath, childPath); + }; + + /** + * Creates a commit with the given author and message. + * It should capture the current state of the repository by building trees based on the index file, + * writing the tree to the objects directory, + * writing the commit to the objects directory, + * updating the HEAD file, + * and returning the commit hash. + * + * The commit should be formatted as follows: + * tree: + * parent: + * author: + * date: + * summary: + * + * @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. + */ + public String commit(String author, String message) { + //this is literally a ctrl c + ctrl v without the scanner + StringBuilder outputSB = new StringBuilder(); + outputSB.append("tree: "+Git.makeIndexTree()+"\n"); + outputSB.append("parent: "+Git.retrieveLatestCommit()+"\n"); + outputSB.append("author: "+author+"\n"); + LocalDateTime localDateTime = LocalDateTime.now(); + DateTimeFormatter validDateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss"); + outputSB.append("date: "+ localDateTime.format(validDateTimeFormatter) + "\n"); + outputSB.append("message: "+message); + String commitHash = Git.hash(outputSB.toString()); + Git.makeFile("git/objects", commitHash); + Git.writeToFile("git/objects", commitHash, outputSB.toString()); + // change this if more info needs to be stored on the HEAD + Git.writeToFile("git", "HEAD", commitHash); + return commitHash; + }; + + /** + * EXTRA CREDIT: + * Checks out a specific commit given its hash. + * This method should read the HEAD file to determine the "checked out" commit. + * Then it should update the working directory to match the + * state of the repository at that commit by tracing through the root tree and + * all its children. + * + * @param commitHash The SHA1 hash of the commit to check out. + */ + public void checkout(String commitHash) { + // to-do: implement functionality here + + }; +} \ No newline at end of file diff --git a/README.md b/README.md index cd48774..50f765a 100644 --- a/README.md +++ b/README.md @@ -84,4 +84,35 @@ decompress: takes a compressed String and returns the original GP 3.2 -makeTree: from file path, recursively creates tree by makign subtrees and blobifying subfiles. returns the name of the hash! \ No newline at end of file +makeTree: from file path, recursively creates tree by makign subtrees and blobifying subfiles. returns the name of the hash! + +-- + +GP 4.1 + +makeIndexTree now returns the hash of the root tree + +-- + +GP 4.2 + +makeCommit: Generates a new commit file by calling makeIndexTree to make a new root hash and prompting the user for the author name and commit message. appends the HEAD with the commit's hash +retriveLastCommit: reads the HEAD (which shoudl have the most recent commit hash) CHANGE THIS IF ANY OTHER STUFF IS IN THE HEAD FILE + +-- + +GP 4.3 + +GitWrapper - new wrapper class for Git +init: calls Git.initRepo +add: indexes and blobs the filepath given +commit: copy of Git.makeCommit without the scanner +checkout: WIP (I'm not quite sure how it's supposed to work) + +-- + +Final Testing + Extras + +FIXED: HEAD is no longer in the objects folder +FIXED: Date no longer throws exceptions when making commits +full wraper test implemented \ No newline at end of file diff --git a/Tester.java b/Tester.java index bb5ea45..fc65b74 100644 --- a/Tester.java +++ b/Tester.java @@ -215,12 +215,74 @@ public static void indexTester(){ Git.deleteDirectory(null, "testFiles"); System.out.println("PASSED"); } - + public static void indexTreeTester(){ + System.out.println("Index Tree Test"); + //make a bunch of files and folders to test different combinations of files and folders + Git.intializeRepo(); + makeLargeFileSystem(); + Git.blobify("indexTreetest", "testFile1"); + Git.index("indexTreeTest", "testFile1"); + Git.blobify("indexTreetest", "testFile2"); + Git.index("indexTreeTest", "testFile2"); + Git.blobify("indexTreetest/firstLayer", "testFile3"); + Git.index("indexTreeTest/firstLayer", "testFile3"); + Git.blobify("indexTreeTest/firstlayer/secondLayer", "testFile4"); + Git.index("indexTreeTest/firstlayer/secondLayer", "testFile4"); + Git.blobify("indexTreeTest/altLayer", "testFile5"); + Git.index("indexTreeTest/altLayer", "testFile5"); + recursiveTreeTest(Git.makeIndexTree()); + } + public static void makeLargeFileSystem(){ + Git.makeDirectory(null, "indexTreeTest"); + Git.makeDirectory("indexTreeTest", "firstLayer"); + Git.makeDirectory("indexTreeTest/firstLayer", "secondLayer"); + Git.makeDirectory("indexTreeTest", "altLayer"); + Git.makeFile("indexTreeTest", "testFile1"); + Git.makeFile("indexTreeTest", "testFile2"); + Git.makeFile("indexTreeTest/firstLayer", "testFile3"); + Git.makeFile("indexTreeTest/firstLayer/secondLayer", "testFile4"); + Git.makeFile("indexTreeTest/altLayer", "testFile5"); + } + public static void recursiveTreeTest(String treePath){ + String contents = Git.readFile("git/objects", treePath); + String [] contentsArr = contents.split("\n"); + for(String e : contentsArr){ + if(e.split(" ")[1].equals("tree")){ + recursiveTreeTest(e.split(" ")[2]); + } + else{ + if(Git.fileExists("git/objects", e.split(" ")[2])){ + System.out.println("File "+e.split(" ")[3]+" correctly blobbed, indexed, and treed"); + } + } + } + } + public static void gitWrapperTest(){ + GitWrapper git = new GitWrapper(); + System.out.println("Full Wrapper Test Started"); + System.out.println("Testing Repo Initialization"); + git.init(); + if (Git.fileExists("git/objects", "index") && Git.fileExists("git/objects", "HEAD") + && Git.directoryExists("git", "objects") && Git.directoryExists(null, "git")){ + System.out.println("Repo initialization sucess"); + } + makeLargeFileSystem(); + System.out.println("File System created"); + git.add("indexTreeTest/testFile1"); + git.add("indexTreeTest/testFile2"); + git.add("indexTreeTest/firstLayer/testFile3"); + git.add("indexTreeTest/firstLayer/secondLayer/testFile4"); + System.out.println("File adding sucessful"); + String commithash = git.commit("Hunter Madden", "THIS IS A TEST"); + System.out.println("COMMIT EXISTS: " + Git.fileExists("git/objects", commithash)); + } public static void main(String[] args){ - initializationTester(); - hashTester(); - blobTester(); - indexTester(); - Git.cleanGit(); + // initializationTester(); + // hashTester(); + // blobTester(); + // indexTester(); + // indexTreeTester(); + gitWrapperTest(); + //Git.cleanGit(); } }