package gitlet; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.util.*; import java.text.SimpleDateFormat; import static gitlet.Utils.*; /** Represents a gitlet commit object. * a commit is a node in a directed graph that keeps track of files * does at a high level. * * @author Bassem Halim */ public class Commit implements Serializable { /** * * List all instance variables of the Commit class here with a useful * comment above them describing what that variable represents and how that * variable is used. We've provided one example for `message`. */ /** The message of this Commit. */ private String message; private Date date; private String ID; //sha1 of itself protected String[] parents; // array of parents of this containing sha1 of commits //store the file names of each file tracked so far by commit protected HashMap trackedFiles = new HashMap<>(); private static final SimpleDateFormat SDF = new SimpleDateFormat("E MMM d HH:mm:ss" + " yyyy Z"); public static final File CWD = new File(System.getProperty("user.dir")); public static final File GITLET_DIR = join(CWD, ".gitlet"); public static final File COMMIT_DIR = join(GITLET_DIR, "commit"); public static final File BLOBS_DIR = join(COMMIT_DIR, "BLOBS"); public Commit(String msg, long date, String[] parents) { this.message = msg; this.date = new Date(date); this.ID = Utils.sha1(Utils.serialize(this)); this.parents = parents; } public Commit(String msg, String[] parents) { this.message = msg; this.date = new Date(); this.ID = Utils.sha1(Utils.serialize(this)); this.parents = parents; } /** * prints important commit variables */ public void print() { System.out.println("==="); System.out.println("commit " + this.ID); if (parents != null && parents.length != 1) { //2 parents System.out.printf("Merge: %s %s\n", parents[0].substring(0, 7), parents[1].substring(0, 7)); } System.out.println("Date: " + SDF.format(this.date)); System.out.println(this.message + "\n"); } /** * returns true if is tracked in this commit */ public boolean contains(String key) { return trackedFiles.containsKey(key); } /** * returns the sha1 of filename * if file doesn't exist return null */ public String getsha1(String filename) { return trackedFiles.get(filename); } /** * return commit ID */ public String getID() { return this.ID; } /** * returns an array list of all file names of tracked files in this commit */ public List getFiles() { Set files = trackedFiles.keySet(); List list = new ArrayList<>(files); return list; } /** * prints all filenames tracked by this commit for debugging */ public void printFiles() { System.out.println("printing file names"); List files = getFiles(); for (String str : files) { System.out.println(str); } } /** * adds the filename as key and the sha1 as value */ private void add(String key, String value) { trackedFiles.put(key, value); } /** * adds staged files to the list of tracked files */ public void addStaged(File[] files) { for (File f : files) { String content = readContentsAsString(f); String sha1content = sha1(content); File newBlob = join(BLOBS_DIR, sha1content + ".txt"); try { newBlob.createNewFile(); } catch (IOException excp) { throw new IllegalArgumentException(excp.getMessage()); } writeContents(newBlob, content); add(f.getName(), sha1content); } } /** * adds any unchanged files from the previous commits */ public void addUnchanged(List removed) { Commit[] lastCmt = getPrev(); for (Commit cmt: lastCmt) { if (cmt == null) { continue; } List files = cmt.getFiles(); for (String file : files) { // track the files from previous commit if they weren't modified or staged for removal if (!this.trackedFiles.containsKey(file) && !removed.contains(file)) { add(file, cmt.trackedFiles.get(file)); } } } } /** * returns an array of parent commits */ public Commit[] getPrev() { Commit[] cmts = new Commit[2]; // max 2 parents if (this.parents == null) { return null; } for (int i = 0; i < parents.length; i++) { String id = parents[i]; if (id == null) { //has no parents return null; } String abv = id.substring(0, 4); File dir = join(COMMIT_DIR, abv); File last = join(dir, id + ".txt"); Commit prevCom; try { prevCom = readObject(last, Commit.class); } catch (IllegalArgumentException excp) { prevCom = null; } cmts[i] = prevCom; } return cmts; } /** * returns tracked File with name filename.txt */ public File getFile(String filename) { if (!contains(filename)) { return null; } String fileID = trackedFiles.get(filename); File file = join(BLOBS_DIR, fileID + ".txt"); return file; } /** * returns True if this.message == msg */ public boolean find(String msg) { return this.message.equals(msg); } public boolean equal(Object cmt) { if (cmt instanceof Commit) { return this.getID().equals(((Commit) cmt).getID()); } return false; } }