-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCommitTree.java
More file actions
234 lines (209 loc) · 8.25 KB
/
CommitTree.java
File metadata and controls
234 lines (209 loc) · 8.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
package gitlet;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
public class CommitTree implements Serializable {
/* a data structure that holds CommitNodes objects.
A headPointer points at the current CommitNode in question
*/
private static final String LOG_FORMAT = "===\nCommit %s\n%s\n%s\n\n";
/**
* currPtr: the pointer pointing to the foremost node of the branch it belongs
* BranchPointers: a map that contains all the pointers, including the above one.
* It's worth noting that BranchPointers use the name of
* the branch instead of the commitID to retrieve the commitNode.
* nodeIds: the database for CommitNodes.
*/
CommitNode currPtr;
String currBranch;
/* branchPointers maps the name of the branch
to the commitId of the foremost node of the branch */
HashMap<String, String> branchPointers = new HashMap<>();
ArrayList<String> nodeIds = new ArrayList<>();
public CommitTree() {
CommitNode initial = new CommitNode("initial commit");
CommitNode masterBranchPtr = initial;
branchPointers.put("master", initial.commitID);
currBranch = "master";
currPtr = initial;
addCommitNode(initial);
File outFile = new File(GitLet.REPO + "/objects/" + initial.commitID);
FileUtil.serialize(outFile, initial);
}
/* getCommitNode retrieves the commitNode corresponding to the commitId passed in */
public CommitNode getCommitNode(String commitId) {
File inFile = new File(GitLet.REPO + "/objects/" + commitId);
CommitNode commitNode = (CommitNode) FileUtil.deSerialize(inFile);
return commitNode;
}
public void addCommitNode(CommitNode newNode) {
nodeIds.add(newNode.commitID);
currPtr = newNode;
branchPointers.put(currBranch, newNode.commitID);
}
// write content
public void addBranch(String name) {
if (branchPointers.containsKey(name)) {
System.out.println("A branch with that name already exists.");
System.exit(0);
}
branchPointers.put(name, currPtr.commitID);
}
public void rmBranch(String name) {
if (!branchPointers.containsKey(name)) {
System.out.println("A branch with that name does not exist.");
System.exit(0);
}
if (name.equals(currBranch)) {
System.out.println("Cannot remove the current branch.");
System.exit(0);
}
branchPointers.remove(name);
}
public void find(String message) {
boolean found = false;
for (String nodeId : nodeIds) {
CommitNode node = getCommitNode(nodeId);
if (node.message.equals(message)) {
System.out.println(node.commitID);
found = true;
}
}
if (!found) {
System.out.println("Found no commit with that message.");
System.exit(0);
}
}
public String log() {
CommitNode node = currPtr;
String result = "";
while (node != null) {
result += String.format(LOG_FORMAT, node.commitID, node.timeStamp, node.message);
if (node.parentName != null) {
node = getCommitNode(node.parentName);
} else {
node = null;
}
}
return result;
}
public String globalLog() {
String result = "";
for (int i = nodeIds.size() - 1; i >= 0; --i) {
CommitNode node = getCommitNode(nodeIds.get(i));
result += String.format(LOG_FORMAT, node.commitID, node.timeStamp, node.message);
}
return result;
}
public void checkoutBranch(String name) {
File inFile2 = new File(GitLet.REPO + "/stagingArea");
StagingArea stage = (StagingArea) FileUtil.deSerialize(inFile2);
File workingDir = new File(System.getProperty("user.dir"));
if (!branchPointers.containsKey(name)) {
System.out.println("No such branch exists.");
System.exit(0);
}
if (name.equals(currBranch)) {
System.out.println("No need to checkout the current branch.");
System.exit(0);
}
CommitNode branchCommit = getCommitNode(branchPointers.get(name));
for (File file : workingDir.listFiles()) {
if (!currPtr.fileNames.containsKey(file.getName())
&& branchCommit.fileNames.containsKey(file.getName())) {
System.out.println("There is an untracked file "
+ "in the way; delete it or add it first.");
System.exit(0);
}
if (!branchCommit.fileNames.containsKey(file.getName())) {
file.delete();
}
}
for (String filename : branchCommit.fileNames.keySet()) {
String fileId = branchCommit.fileNames.get(filename);
CommitNode.Blob commitFile = branchCommit.getBlob(fileId);
File userFile = new File(filename);
if (userFile.exists()) {
Utils.writeContents(userFile, commitFile.content);
} else {
try {
File f = new File(filename);
f.createNewFile();
Utils.writeContents(f, commitFile.content);
} catch (IOException e) {
e.printStackTrace();
}
}
}
stage.clearAdd();
stage.getRemovedFiles().clear();
FileUtil.serialize(inFile2, stage);
currBranch = name;
currPtr = branchCommit;
}
public void checkoutFile(String filename) {
if (!currPtr.fileNames.containsKey(filename)) {
System.out.println("File does not exist in that commit.");
System.exit(0);
}
String fileId = currPtr.fileNames.get(filename);
CommitNode.Blob commitFile = currPtr.getBlob(fileId);
File userFile = new File(filename);
Utils.writeContents(userFile, commitFile.content);
}
public void checkoutFile(String filename, String commitId) {
if (commitId.length() < 40) {
for (String hashID: nodeIds) {
if (hashID.contains(commitId)) {
commitId = hashID;
}
}
}
if (!nodeIds.contains(commitId)) {
System.out.println("No commit with that id exists.");
System.exit(0);
}
CommitNode commit = getCommitNode(commitId);
if (!commit.fileNames.containsKey(filename)) {
System.out.println("File does not exist in that commit.");
System.exit(0);
}
String fileId = commit.fileNames.get(filename);
CommitNode.Blob commitFile = commit.getBlob(fileId);
File userFile = new File(filename);
Utils.writeContents(userFile, commitFile.content);
}
public String findSplitNode(String branchName) {
String givenBranchId = branchPointers.get(branchName);
List<String> currBranchHistory = new ArrayList<>();
HashSet<String> givenBranchHistory = new HashSet<>();
CommitNode tempCurrPtr = currPtr;
CommitNode tempGivenPtr = getCommitNode(givenBranchId);
if (tempCurrPtr.commitID.equals(givenBranchId)) {
return null;
}
currBranchHistory.add(0, branchPointers.get(currBranch));
givenBranchHistory.add(givenBranchId);
while (tempCurrPtr.parentName != null) {
if (givenBranchId.equals(tempCurrPtr.parentName)) {
return null;
}
currBranchHistory.add(tempCurrPtr.parentName);
tempCurrPtr = getCommitNode(tempCurrPtr.parentName);
}
while (tempGivenPtr.parentName != null) {
givenBranchHistory.add(tempGivenPtr.parentName);
tempGivenPtr = getCommitNode(tempGivenPtr.parentName);
}
for (int i = 0; i < currBranchHistory.size(); ++i) {
if (givenBranchHistory.contains(currBranchHistory.get(i))) {
return currBranchHistory.get(i);
}
}
return null;
}
}