-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRepository.java
More file actions
313 lines (263 loc) · 10.9 KB
/
Copy pathRepository.java
File metadata and controls
313 lines (263 loc) · 10.9 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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
import java.util.*;
import java.text.SimpleDateFormat;
/*
* This class called Repository represents a traditional repository for users to essentially track
* changes (like in a Google Docs, for example). There are a few key usability features: users can
* create a new Repository (which stores individual commits), create new commits, retrieve the size
* of their repo and most recent commit made to the repo, see as far back in their history as they
* want to, remove a certain commit from their repository, and merge two Repos while still
* maintaining the timestamp ordering of the two original repositories.
*/
public class Repository {
// private fields
private Commit head;
private String name;
/*
* Creates a new Repository
* Parameters: String name of new Repository
* Exceptions: IllegalArgumentException if the Repository name given is null or empty
*/
public Repository (String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("The given Repository name is null or empty");
}
this.head = null;
this.name = name;
}
/*
* Provides the id of the most recently added commit. Null if no commits in Repository
* Returns: String id of the most recent commit or null if no commits in Repository
*/
public String getRepoHead() {
if (this.head == null) {
return null;
}
return this.head.id;
}
/*
* Provides the number of commits in the Repository
* Returns: int number of commits in the Repository
*/
public int getRepoSize() {
int commits = 0;
Commit curr = this.head;
while (curr != null) {
commits++;
curr = curr.past;
}
return commits;
}
/*
* Provides the user with a text representation of the Repository:
* => if the repo has no commits, then will provide name and " - no Commits" statement
* => otherwise, will provide "<name of repo> - Current head: <most recent commit>"
* (commit is provided as a text representation of commitwith id, timestamp, and message)
* Returns: String representation of Repository
*/
public String toString() {
if (getRepoSize() == 0) {
return this.name + " - No commits";
}
return this.name + " - Current head: " + this.head.toString();
}
/*
* Provides information if the Repository contains a commit with a certain id (true or false)
* Parameters: String targetId which is the id to search for in the Repo
* Returns: boolean true if Repo contains commit with targetId, false if not
* Exceptions: throws IllegalArgumentException if the targetId given by user is null
*/
public boolean contains(String targetId) {
if (targetId == null) {
throw new IllegalArgumentException("targetId is null");
}
Commit curr = this.head;
while (curr != null) {
if (curr.id.equals(targetId)) {
return true;
}
curr = curr.past;
}
return false;
}
/*
* Provides user with text based representation of latest n commits
* => if n is greater than num of commits in Repo, will show all commits
* => if there are no commits in the repo, provide an empty text string
* Parameters: int n representing the number of most recent commits to return
* Returns: a String based representation of the latest n commits separated by nextLine
* Exceptions: throws IllegalArgumentException if n is nonpositive
*/
public String getHistory(int n) {
if (n <= 0) {
throw new IllegalArgumentException("given int n for getHistory was non-positive");
}
String result = "";
int index = 0;
Commit curr = this.head;
while (curr != null && index < n) {
result += curr.toString() + "\n";
curr = curr.past;
index++;
}
return result;
}
/*
* Creates a new commit in the Repo w/ given message
* Parameters: String message which is the commit's message
* Returns: String representing the id of the newly created commit
* Exceptions: throws IllegalArgumentException if the message for the commit is null
*/
public String commit(String message) {
if (message == null) {
throw new IllegalArgumentException("message for the commit() method param is null");
}
this.head = new Commit(message, this.head);
return this.head.id;
}
/*
* Removes the commit with the target id from the repo while maintaining the rest of history;
* provides the user with true/ false info on whether the commit was dropped/ not found in repo
* Parameters: String targetID which the id to look for in repo and remove form repo if found
* Returns: a boolean representing whether the commit was succesfully removed or not found
* Exceptions: throws an IllegalArgumentException if the targetId given is null
*/
public boolean drop(String targetId) {
if (targetId == null) {
throw new IllegalArgumentException("targetId parameter for drop() method is null");
}
if (this.head != null) {
if (this.head.id.equals(targetId)) {
this.head = this.head.past;
return true;
}
Commit curr = this.head;
while (curr.past != null) {
if (curr.past.id.equals(targetId)) {
curr.past = curr.past.past;
return true;
}
curr = curr.past;
}
}
return false;
}
/*
* Takes all commits from the given other repo and moves them into current repo. Combines
* in such a way so that the commits in the repo is still organized by timestamps
* Parameters: Repository other to chronologically move to the current Repo
* Exceptions: if the other repository is null, throws an IllegalArgumentException
*/
public void synchronize(Repository other) {
if (other == null) {
throw new IllegalArgumentException("other repository is null; synchronize()");
}
// comments are notes for future reference:
// if THIS repo has NO COMMITS (i.e. null or empty)
if (this.head == null || this.getRepoSize() == 0) {
this.head = other.head; // this repo head refers to other's repo head
// if THIS repo HAS COMMITS (i.e. nonnull or non-empty)
} else if (other.head != null) {
// front vase: if other head is bigger than current head, add other node to the front
if (this.head.timeStamp < other.head.timeStamp) {
Commit temp = this.head;
this.head = other.head;
this.head.past = other.head.past;
other.head = temp;
// temp = other.head.past;
}
Commit curr1 = this.head;
// middle case: check if a node is less than the curent one but greater than the next one
while (curr1 != null && other.head != null && curr1.past != null) {
if (curr1.timeStamp > other.head.timeStamp && other.head.timeStamp > curr1.past.timeStamp) {
Commit temp = curr1.past;
curr1.past = other.head;
other.head = other.head.past;
curr1.past.past = temp;
}
System.out.println(this.head.toString());
curr1 = curr1.past;
}
// end case
if (curr1.past == null && other.head != null) {
if (other.head.timeStamp > curr1.timeStamp) {
curr1 = other.head;
} else {
curr1.past = other.head;
}
}
}
other.head = null; // end with the other repo being null (in spec)
}
/**
* DO NOT MODIFY
* A class that represents a single commit in the repository.
* Commits are characterized by an identifier, a commit message,
* and the time that the commit was made. A commit also stores
* a reference to the immediately previous commit if it exists.
*
* Staff Note: You may notice that the comments in this
* class openly mention the fields of the class. This is fine
* because the fields of the Commit class are public. In general,
* be careful about revealing implementation details!
*/
public static class Commit {
private static int currentCommitID;
/**
* The time, in milliseconds, at which this commit was created.
*/
public final long timeStamp;
/**
* A unique identifier for this commit.
*/
public final String id;
/**
* A message describing the changes made in this commit.
*/
public final String message;
/**
* A reference to the previous commit, if it exists. Otherwise, null.
*/
public Commit past;
/**
* Constructs a commit object. The unique identifier and timestamp
* are automatically generated.
* @param message A message describing the changes made in this commit. Should be non-null.
* @param past A reference to the commit made immediately before this
* commit.
*/
public Commit(String message, Commit past) {
this.id = "" + currentCommitID++;
this.message = message;
this.timeStamp = System.currentTimeMillis();
this.past = past;
}
/**
* Constructs a commit object with no previous commit. The unique
* identifier and timestamp are automatically generated.
* @param message A message describing the changes made in this commit. Should be non-null.
*/
public Commit(String message) {
this(message, null);
}
/**
* Returns a string representation of this commit. The string
* representation consists of this commit's unique identifier,
* timestamp, and message, in the following form:
* "[identifier] at [timestamp]: [message]"
* @return The string representation of this collection.
*/
@Override
public String toString() {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
Date date = new Date(timeStamp);
return id + " at " + formatter.format(date) + ": " + message;
}
/**
* Resets the IDs of the commit nodes such that they reset to 0.
* Primarily for testing purposes.
*/
public static void resetIds() {
Commit.currentCommitID = 0;
}
}
}