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