Gitlet / src / gitlet / Commit.java
Commit.java
Raw
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 <filename, sha1 of its content>
    protected HashMap<String, String> 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 <key> 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<String> getFiles() {
        Set<String> files = trackedFiles.keySet();
        List<String> 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<String> 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<String> removed) {
        Commit[] lastCmt = getPrev();
        for (Commit cmt: lastCmt) {
            if (cmt == null) {
                continue;
            }
            List<String> 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;
    }
}