package gitlet; import java.io.File; import java.io.Serial; import java.io.Serializable; import java.time.Instant; import java.util.*; import static gitlet.Utils.*; /** * Represents a gitlet commit object. * * @author Abraham Briones */ public class Commit implements Serializable { /** * Serial ID so Java can serialize and deserialize. */ @Serial private static final long serialVersionUID = 1234567L; /** * The message of this Commit. */ private final String message; /** * The date and time when the commit object was made */ private final Instant datetime; /** * The files that this commit will track. * It is composed of FileName(String):Blob (Key:value) pairings. */ private final TreeMap commitFiles; /** * The SHA-1 representation of the current commit. */ private final String commitID; /** * The SHA-1 representation of the parent commit */ private final String parentCommit; /** * The name of the branch that this commit belongs to. */ private final String branch; /** * The constructor used when initializing a repository. It record EPOC time and a predefined * commit message. It does not track any files nor does it have a parent commit. */ public Commit() { this.message = "initial commit"; this.datetime = Instant.EPOCH; this.commitFiles = null; this.parentCommit = null; this.commitID = this.setSHA(); this.branch = "master"; } /** * A second constructor used for all other commits after the initial commit. * * @param message the message encoded into the commit * @param commitFiles a map of files that this commit should track * @param parentCommit the SHA-1 hash of the parent commit * @param branch the name of the branch this commit belongs to */ public Commit(String message, TreeMap commitFiles, String parentCommit, String branch) { this.message = message; this.datetime = Instant.now(); this.commitFiles = commitFiles; this.parentCommit = parentCommit; this.commitID = this.setSHA(); this.branch = branch; } /** * Contstructor to make a copy of a commit. */ public Commit(Commit copyCommit) { this.message = copyCommit.message; this.datetime = Instant.now(); this.commitFiles = copyCommit.commitFiles; this.parentCommit = copyCommit.parentCommit; this.commitID = copyCommit.commitID; this.branch = copyCommit.branch; } /** * Retrieve the date and time when this commit object was made. * * @return datetime string */ public String getDateTime() { return this.datetime.toString(); } public String getCommitID() { return this.commitID; } public String getMessage() { return this.message; } public String getBranch() { return this.branch; } /** * Get parent commit SHa */ public String getParentCommit() { return this.parentCommit; } public TreeMap getCommitFiles() { return this.commitFiles; } /** * Set and return the SHA-1 of the commit object. * The SHA-1 is composed of the metadata as well as the string representation * of the blob objects the commit object tracks. */ private String setSHA() { String commitContents = this.message + this.getDateTime() + this.parentCommit + this.branch; StringBuilder fileContentsString = new StringBuilder(); if (this.parentCommit != null) { for (Blob b : commitFiles.values()) { fileContentsString.append(b.toString()); } } commitContents += fileContentsString; return Utils.sha1(commitContents); } public void saveCommit() { File commitFile = join(Repository.OBJECT_DIR, this.commitID); Utils.writeObject(commitFile, this); } /* * Override this method in your custom class * used as key or value in the LinkedHashMap */ @Override public String toString() { String files = this.commitFiles == null ? "EMPTY FILES" : this.getCommitFiles().toString(); return String.format("Commit: %s\nCommit message: %s\nParent commit: %s\nFiles tracking:\n%s\nBranch:%s\n", this.getCommitID(), this.message, this.getParentCommit(), files, this.getBranch()); } }