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 package org.eclipse.jgit.junit;
45
46 import static java.nio.charset.StandardCharsets.UTF_8;
47 import static org.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertFalse;
49 import static org.junit.Assert.assertNotEquals;
50 import static org.junit.Assert.assertNull;
51 import static org.junit.Assert.assertSame;
52 import static org.junit.Assert.assertTrue;
53
54 import java.util.Date;
55 import java.util.regex.Pattern;
56
57 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
58 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
59 import org.eclipse.jgit.lib.AnyObjectId;
60 import org.eclipse.jgit.lib.Constants;
61 import org.eclipse.jgit.lib.ObjectId;
62 import org.eclipse.jgit.lib.ObjectLoader;
63 import org.eclipse.jgit.lib.PersonIdent;
64 import org.eclipse.jgit.lib.Ref;
65 import org.eclipse.jgit.lib.RefUpdate;
66 import org.eclipse.jgit.revwalk.RevBlob;
67 import org.eclipse.jgit.revwalk.RevCommit;
68 import org.eclipse.jgit.revwalk.RevObject;
69 import org.eclipse.jgit.revwalk.RevWalk;
70 import org.eclipse.jgit.treewalk.TreeWalk;
71 import org.junit.After;
72 import org.junit.Before;
73 import org.junit.Test;
74
75 public class TestRepositoryTest {
76 private TestRepository<InMemoryRepository> tr;
77 private InMemoryRepository repo;
78 private RevWalk rw;
79
80 @Before
81 public void setUp() throws Exception {
82 tr = new TestRepository<>(new InMemoryRepository(
83 new DfsRepositoryDescription("test")));
84 repo = tr.getRepository();
85 rw = tr.getRevWalk();
86 }
87
88 @After
89 public void tearDown() {
90 rw.close();
91 repo.close();
92 }
93
94 @Test
95 public void insertChangeId() throws Exception {
96 RevCommit c1 = tr.commit().message("message").insertChangeId().create();
97 rw.parseBody(c1);
98 assertTrue(Pattern.matches(
99 "^message\n\nChange-Id: I[0-9a-f]{40}\n$", c1.getFullMessage()));
100
101 RevCommit c2 = tr.commit().message("").insertChangeId().create();
102 rw.parseBody(c2);
103 assertEquals("\n\nChange-Id: I0000000000000000000000000000000000000000\n",
104 c2.getFullMessage());
105 }
106
107 @Test
108 public void insertChangeIdIgnoresExisting() throws Exception {
109 String msg = "message\n"
110 + "\n"
111 + "Change-Id: Ideadbeefdeadbeefdeadbeefdeadbeefdeadbeef\n";
112 RevCommit c = tr.commit().message(msg).insertChangeId().create();
113 rw.parseBody(c);
114 assertEquals(msg, c.getFullMessage());
115 }
116
117 @Test
118 public void insertExplicitChangeId() throws Exception {
119 RevCommit c = tr.commit().message("message")
120 .insertChangeId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
121 .create();
122 rw.parseBody(c);
123 assertEquals("message\n\n"
124 + "Change-Id: Ideadbeefdeadbeefdeadbeefdeadbeefdeadbeef\n"
125 , c.getFullMessage());
126 }
127
128 @Test
129 public void resetFromSymref() throws Exception {
130 repo.updateRef("HEAD").link("refs/heads/master");
131 Ref head = repo.exactRef("HEAD");
132 RevCommit master = tr.branch("master").commit().create();
133 RevCommit branch = tr.branch("branch").commit().create();
134 RevCommit detached = tr.commit().create();
135
136 assertTrue(head.isSymbolic());
137 assertEquals("refs/heads/master", head.getTarget().getName());
138 assertEquals(master, repo.exactRef("refs/heads/master").getObjectId());
139 assertEquals(branch, repo.exactRef("refs/heads/branch").getObjectId());
140
141
142 tr.reset("master");
143 head = repo.exactRef("HEAD");
144 assertEquals(master, head.getObjectId());
145 assertTrue(head.isSymbolic());
146 assertEquals("refs/heads/master", head.getTarget().getName());
147
148 tr.reset("branch");
149 head = repo.exactRef("HEAD");
150 assertEquals(branch, head.getObjectId());
151 assertTrue(head.isSymbolic());
152 assertEquals("refs/heads/master", head.getTarget().getName());
153 ObjectId lastHeadBeforeDetach = head.getObjectId().copy();
154
155
156 tr.reset(detached);
157 head = repo.exactRef("HEAD");
158 assertEquals(detached, head.getObjectId());
159 assertFalse(head.isSymbolic());
160
161 tr.reset(detached.name());
162 head = repo.exactRef("HEAD");
163 assertEquals(detached, head.getObjectId());
164 assertFalse(head.isSymbolic());
165
166
167 tr.reset("master");
168 head = repo.exactRef("HEAD");
169 assertEquals(lastHeadBeforeDetach, head.getObjectId());
170 assertFalse(head.isSymbolic());
171 }
172
173 @Test
174 public void resetFromDetachedHead() throws Exception {
175 Ref head = repo.exactRef("HEAD");
176 RevCommit master = tr.branch("master").commit().create();
177 RevCommit branch = tr.branch("branch").commit().create();
178 RevCommit detached = tr.commit().create();
179
180 assertNull(head);
181 assertEquals(master, repo.exactRef("refs/heads/master").getObjectId());
182 assertEquals(branch, repo.exactRef("refs/heads/branch").getObjectId());
183
184 tr.reset("master");
185 head = repo.exactRef("HEAD");
186 assertEquals(master, head.getObjectId());
187 assertFalse(head.isSymbolic());
188
189 tr.reset("branch");
190 head = repo.exactRef("HEAD");
191 assertEquals(branch, head.getObjectId());
192 assertFalse(head.isSymbolic());
193
194 tr.reset(detached);
195 head = repo.exactRef("HEAD");
196 assertEquals(detached, head.getObjectId());
197 assertFalse(head.isSymbolic());
198
199 tr.reset(detached.name());
200 head = repo.exactRef("HEAD");
201 assertEquals(detached, head.getObjectId());
202 assertFalse(head.isSymbolic());
203 }
204
205 @Test
206 public void amendRef() throws Exception {
207 RevCommit root = tr.commit()
208 .add("todelete", "to be deleted")
209 .create();
210 RevCommit orig = tr.commit().parent(root)
211 .rm("todelete")
212 .add("foo", "foo contents")
213 .add("bar", "bar contents")
214 .add("dir/baz", "baz contents")
215 .create();
216 rw.parseBody(orig);
217 tr.branch("master").update(orig);
218 assertEquals("foo contents", blobAsString(orig, "foo"));
219 assertEquals("bar contents", blobAsString(orig, "bar"));
220 assertEquals("baz contents", blobAsString(orig, "dir/baz"));
221
222 RevCommit amended = tr.amendRef("master")
223 .tick(3)
224 .add("bar", "fixed bar contents")
225 .create();
226 assertEquals(amended, repo.exactRef("refs/heads/master").getObjectId());
227 rw.parseBody(amended);
228
229 assertEquals(1, amended.getParentCount());
230 assertEquals(root, amended.getParent(0));
231 assertEquals(orig.getFullMessage(), amended.getFullMessage());
232 assertEquals(orig.getAuthorIdent(), amended.getAuthorIdent());
233
234
235 assertEquals(new PersonIdent(orig.getCommitterIdent(), new Date(0)),
236 new PersonIdent(amended.getCommitterIdent(), new Date(0)));
237 assertTrue(orig.getCommitTime() < amended.getCommitTime());
238
239 assertEquals("foo contents", blobAsString(amended, "foo"));
240 assertEquals("fixed bar contents", blobAsString(amended, "bar"));
241 assertEquals("baz contents", blobAsString(amended, "dir/baz"));
242 assertNull(TreeWalk.forPath(repo, "todelete", amended.getTree()));
243 }
244
245 @Test
246 public void amendHead() throws Exception {
247 repo.updateRef("HEAD").link("refs/heads/master");
248 RevCommit root = tr.commit()
249 .add("foo", "foo contents")
250 .create();
251 RevCommit orig = tr.commit().parent(root)
252 .message("original message")
253 .add("bar", "bar contents")
254 .create();
255 tr.branch("master").update(orig);
256
257 RevCommit amended = tr.amendRef("HEAD")
258 .add("foo", "fixed foo contents")
259 .create();
260
261 Ref head = repo.exactRef(Constants.HEAD);
262 assertEquals(amended, head.getObjectId());
263 assertTrue(head.isSymbolic());
264 assertEquals("refs/heads/master", head.getTarget().getName());
265
266 rw.parseBody(amended);
267 assertEquals("original message", amended.getFullMessage());
268 assertEquals("fixed foo contents", blobAsString(amended, "foo"));
269 assertEquals("bar contents", blobAsString(amended, "bar"));
270 }
271
272 @Test
273 public void amendCommit() throws Exception {
274 RevCommit root = tr.commit()
275 .add("foo", "foo contents")
276 .create();
277 RevCommit orig = tr.commit().parent(root)
278 .message("original message")
279 .add("bar", "bar contents")
280 .create();
281 RevCommit amended = tr.amend(orig.copy())
282 .add("foo", "fixed foo contents")
283 .create();
284
285 rw.parseBody(amended);
286 assertEquals("original message", amended.getFullMessage());
287 assertEquals("fixed foo contents", blobAsString(amended, "foo"));
288 assertEquals("bar contents", blobAsString(amended, "bar"));
289 }
290
291 @Test
292 public void commitToUnbornHead() throws Exception {
293 repo.updateRef("HEAD").link("refs/heads/master");
294 RevCommit root = tr.branch("HEAD").commit().create();
295 Ref ref = repo.exactRef(Constants.HEAD);
296 assertEquals(root, ref.getObjectId());
297 assertTrue(ref.isSymbolic());
298 assertEquals("refs/heads/master", ref.getTarget().getName());
299 }
300
301 @Test
302 public void cherryPick() throws Exception {
303 repo.updateRef("HEAD").link("refs/heads/master");
304 RevCommit head = tr.branch("master").commit()
305 .add("foo", "foo contents\n")
306 .create();
307 rw.parseBody(head);
308 RevCommit toPick = tr.commit()
309 .parent(tr.commit().create())
310 .author(new PersonIdent("Cherrypick Author", "cpa@example.com",
311 tr.getDate(), tr.getTimeZone()))
312 .author(new PersonIdent("Cherrypick Committer", "cpc@example.com",
313 tr.getDate(), tr.getTimeZone()))
314 .message("message to cherry-pick")
315 .add("bar", "bar contents\n")
316 .create();
317 RevCommit result = tr.cherryPick(toPick);
318 rw.parseBody(result);
319
320 Ref headRef = tr.getRepository().exactRef("HEAD");
321 assertEquals(result, headRef.getObjectId());
322 assertTrue(headRef.isSymbolic());
323 assertEquals("refs/heads/master", headRef.getLeaf().getName());
324
325 assertEquals(1, result.getParentCount());
326 assertEquals(head, result.getParent(0));
327 assertEquals(toPick.getAuthorIdent(), result.getAuthorIdent());
328
329
330 assertEquals(new PersonIdent(head.getCommitterIdent(), new Date(0)),
331 new PersonIdent(result.getCommitterIdent(), new Date(0)));
332 assertTrue(toPick.getCommitTime() < result.getCommitTime());
333
334 assertEquals("message to cherry-pick", result.getFullMessage());
335 assertEquals("foo contents\n", blobAsString(result, "foo"));
336 assertEquals("bar contents\n", blobAsString(result, "bar"));
337 }
338
339 @Test
340 public void cherryPickWithContentMerge() throws Exception {
341 RevCommit base = tr.branch("HEAD").commit()
342 .add("foo", "foo contents\n\n")
343 .create();
344 tr.branch("HEAD").commit()
345 .add("foo", "foo contents\n\nlast line\n")
346 .create();
347 RevCommit toPick = tr.commit()
348 .message("message to cherry-pick")
349 .parent(base)
350 .add("foo", "changed foo contents\n\n")
351 .create();
352 RevCommit result = tr.cherryPick(toPick);
353 rw.parseBody(result);
354
355 assertEquals("message to cherry-pick", result.getFullMessage());
356 assertEquals("changed foo contents\n\nlast line\n",
357 blobAsString(result, "foo"));
358 }
359
360 @Test
361 public void cherryPickWithIdenticalContents() throws Exception {
362 RevCommit base = tr.branch("HEAD").commit().add("foo", "foo contents\n")
363 .create();
364 RevCommit head = tr.branch("HEAD").commit()
365 .parent(base)
366 .add("bar", "bar contents\n")
367 .create();
368 RevCommit toPick = tr.commit()
369 .parent(base)
370 .message("message to cherry-pick")
371 .add("bar", "bar contents\n")
372 .create();
373 assertNotEquals(head, toPick);
374 assertNull(tr.cherryPick(toPick));
375 assertEquals(head, repo.exactRef("HEAD").getObjectId());
376 }
377
378 @Test
379 public void reattachToMaster_Race() throws Exception {
380 RevCommit commit = tr.branch("master").commit().create();
381 tr.branch("master").update(commit);
382 tr.branch("other").update(commit);
383 repo.updateRef("HEAD").link("refs/heads/master");
384
385
386 tr.reset(commit);
387 Ref head = repo.exactRef("HEAD");
388 assertEquals(commit, head.getObjectId());
389 assertFalse(head.isSymbolic());
390
391
392 RefUpdate refUpdate = repo.updateRef("HEAD");
393
394
395 repo.updateRef("HEAD").link("refs/heads/other");
396
397 assertEquals(
398 RefUpdate.Result.LOCK_FAILURE, refUpdate.link("refs/heads/master"));
399 }
400
401 @Test
402 public void nonRacingChange() throws Exception {
403 tr.branch("master").update(tr.branch("master").commit().create());
404 tr.branch("other").update(tr.branch("other").commit().create());
405 repo.updateRef("HEAD").link("refs/heads/master");
406
407
408 RefUpdate refUpdate = repo.updateRef("HEAD");
409
410
411 tr.branch("master").update(tr.branch("master").commit().create());
412
413 assertEquals(RefUpdate.Result.FORCED, refUpdate.link("refs/heads/other"));
414 }
415
416 private String blobAsString(AnyObjectId treeish, String path)
417 throws Exception {
418 RevObject obj = tr.get(rw.parseTree(treeish), path);
419 assertSame(RevBlob.class, obj.getClass());
420 ObjectLoader loader = rw.getObjectReader().open(obj);
421 return new String(loader.getCachedBytes(), UTF_8);
422 }
423 }