package nodebox.localhistory; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class Commit { public final static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private Repository repository; private String id; //private Tree tree; private String treeId; private String parentId; private Commit parent; private Date time; private String message; public Commit(Repository repository, String id) { this.repository = repository; this.id = id; // Retrieve and parse the commit from the object database. String commitData = new String(repository.readObject(id)); // The commit consists of a number of lines, each with identifiers. String[] commitLines = commitData.split("\n"); int pos = 0; while (true) { // Get a line from the commit data. String commitLine = commitLines[pos]; // Examine the contents to see what it means if (commitLine.trim().length() == 0) { // Last line of the commit metadata. The rest of the commit is the message. break; } else if (commitLine.startsWith("tree")) { // The tree line contains a reference to the root tree of the commit. // The line looks like this (without the quotes): "tree 19e8ac9f8e2349e8ac9f8e2349e8ac9f8e234da1" // The 6th character (5, zero-based) is the start of the id. // The id is always 40 characters long. treeId = commitLine.substring(5); if (treeId.length() != 40) throw new AssertionError("Could not parse commit " + id + ": the tree line is in the wrong format. " + commitLine); } else if (commitLine.startsWith("parent")) { // The parent line contains a reference to the parent commit. // The line looks like this (without the quotes): "parent 19e8ac9f8e2349e8ac9f8e2349e8ac9f8e234da1" // The 8th character (7, zero-based) is the start of the id. // The id is always 40 characters long. parentId = commitLine.substring(7); if (parentId.length() != 40) throw new AssertionError("Could not parse commit " + id + ": the parent line is in the wrong format. " + commitLine); } else if (commitLine.startsWith("time")) { // The time line stores when the commit was made. // The line looks like this (without the quotes): "time 2009-02-19 18:38:17" // The 6th character (5, zero-based) is the start of the time string. String timeString = commitLine.substring(5); try { time = dateFormat.parse(timeString); } catch (ParseException e) { throw new AssertionError("Could not parse commit " + id + ": the time is in the wrong format. (" + e.getMessage() + ") " + commitLine); } } else { throw new AssertionError("Could not parse commit " + id + ": unknown line " + commitLine); } // Increase the position (move to the next line) pos++; } // Check if the required metadata was parsed (tree and time are required, parent is optional) if (treeId == null) throw new AssertionError("Could not parse commit" + id + ": no tree encountered in the commit data"); if (time == null) throw new AssertionError("Could not parse commit" + id + ": no time encountered in the commit data"); StringBuffer messageBuffer = new StringBuffer(); for (; pos < commitLines.length; pos++) messageBuffer.append(commitLines[pos]).append("\n"); message = messageBuffer.toString(); } public Repository getRepository() { return repository; } public String getId() { return id; } public String getTreeId() { return treeId; } public String getParentId() { return parentId; } public Commit getParent() { return parent; } public Date getTime() { return time; } public String getMessage() { return message; } @Override public boolean equals(Object obj) { if (!(obj instanceof Commit)) return false; return id.equals(((Commit) obj).id); } }