2 * Copyright (C) 2008, Charles O'Farrell <charleso@charleso.org>
3 * Copyright (C) 2008-2009, Robin Rosenberg <robin.rosenberg@dewire.com>
4 * and other copyright owners as documented in the project's IP log.
6 * This program and the accompanying materials are made available
7 * under the terms of the Eclipse Distribution License v1.0 which
8 * accompanies this distribution, is reproduced below, and is
9 * available at http://www.eclipse.org/org/documents/edl-v10.php
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
17 * - Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials provided
23 * with the distribution.
25 * - Neither the name of the Eclipse Foundation, Inc. nor the
26 * names of its contributors may be used to endorse or promote
27 * products derived from this software without specific prior
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
42 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 package org
.eclipse
.jgit
.lib
;
48 import java
.io
.IOException
;
49 import java
.util
.List
;
51 import java
.util
.Map
.Entry
;
53 import org
.eclipse
.jgit
.lib
.RefUpdate
.Result
;
54 import org
.eclipse
.jgit
.revwalk
.RevCommit
;
55 import org
.eclipse
.jgit
.revwalk
.RevWalk
;
57 public class RefUpdateTest
extends SampleDataRepositoryTestCase
{
59 private RefUpdate
updateRef(final String name
) throws IOException
{
60 final RefUpdate ref
= db
.updateRef(name
);
61 ref
.setNewObjectId(db
.resolve(Constants
.HEAD
));
65 private void delete(final RefUpdate ref
, final Result expected
)
67 delete(ref
, expected
, true, true);
70 private void delete(final RefUpdate ref
, final Result expected
,
71 final boolean exists
, final boolean removed
) throws IOException
{
72 assertEquals(exists
, db
.getAllRefs().containsKey(ref
.getName()));
73 assertEquals(expected
, ref
.delete());
74 assertEquals(!removed
, db
.getAllRefs().containsKey(ref
.getName()));
77 public void testNoCacheObjectIdSubclass() throws IOException
{
78 final String newRef
= "refs/heads/abc";
79 final RefUpdate ru
= updateRef(newRef
);
80 final RevCommit newid
= new RevCommit(ru
.getNewObjectId()) {
83 ru
.setNewObjectId(newid
);
84 Result update
= ru
.update();
85 assertEquals(Result
.NEW
, update
);
86 final Ref r
= db
.getAllRefs().get(newRef
);
88 assertEquals(newRef
, r
.getName());
89 assertNotNull(r
.getObjectId());
90 assertNotSame(newid
, r
.getObjectId());
91 assertSame(ObjectId
.class, r
.getObjectId().getClass());
92 assertEquals(newid
.copy(), r
.getObjectId());
93 List
<org
.eclipse
.jgit
.lib
.ReflogReader
.Entry
> reverseEntries1
= db
.getReflogReader("refs/heads/abc").getReverseEntries();
94 org
.eclipse
.jgit
.lib
.ReflogReader
.Entry entry1
= reverseEntries1
.get(0);
95 assertEquals(1, reverseEntries1
.size());
96 assertEquals(ObjectId
.zeroId(), entry1
.getOldId());
97 assertEquals(r
.getObjectId(), entry1
.getNewId());
98 assertEquals(new PersonIdent(db
).toString(), entry1
.getWho().toString());
99 assertEquals("", entry1
.getComment());
100 List
<org
.eclipse
.jgit
.lib
.ReflogReader
.Entry
> reverseEntries2
= db
.getReflogReader("HEAD").getReverseEntries();
101 assertEquals(0, reverseEntries2
.size());
104 public void testNewNamespaceConflictWithLoosePrefixNameExists()
106 final String newRef
= "refs/heads/z";
107 final RefUpdate ru
= updateRef(newRef
);
108 final RevCommit newid
= new RevCommit(ru
.getNewObjectId()) {
111 ru
.setNewObjectId(newid
);
112 Result update
= ru
.update();
113 assertEquals(Result
.NEW
, update
);
115 final String newRef2
= "refs/heads/z/a";
116 final RefUpdate ru2
= updateRef(newRef2
);
117 final RevCommit newid2
= new RevCommit(ru2
.getNewObjectId()) {
120 ru
.setNewObjectId(newid2
);
121 Result update2
= ru2
.update();
122 assertEquals(Result
.LOCK_FAILURE
, update2
);
123 assertEquals(1, db
.getReflogReader("refs/heads/z").getReverseEntries().size());
124 assertEquals(0, db
.getReflogReader("HEAD").getReverseEntries().size());
127 public void testNewNamespaceConflictWithPackedPrefixNameExists()
129 final String newRef
= "refs/heads/master/x";
130 final RefUpdate ru
= updateRef(newRef
);
131 final RevCommit newid
= new RevCommit(ru
.getNewObjectId()) {
134 ru
.setNewObjectId(newid
);
135 Result update
= ru
.update();
136 assertEquals(Result
.LOCK_FAILURE
, update
);
137 assertNull(db
.getReflogReader("refs/heads/master/x"));
138 assertEquals(0, db
.getReflogReader("HEAD").getReverseEntries().size());
141 public void testNewNamespaceConflictWithLoosePrefixOfExisting()
143 final String newRef
= "refs/heads/z/a";
144 final RefUpdate ru
= updateRef(newRef
);
145 final RevCommit newid
= new RevCommit(ru
.getNewObjectId()) {
148 ru
.setNewObjectId(newid
);
149 Result update
= ru
.update();
150 assertEquals(Result
.NEW
, update
);
152 final String newRef2
= "refs/heads/z";
153 final RefUpdate ru2
= updateRef(newRef2
);
154 final RevCommit newid2
= new RevCommit(ru2
.getNewObjectId()) {
157 ru
.setNewObjectId(newid2
);
158 Result update2
= ru2
.update();
159 assertEquals(Result
.LOCK_FAILURE
, update2
);
160 assertEquals(1, db
.getReflogReader("refs/heads/z/a").getReverseEntries().size());
161 assertNull(db
.getReflogReader("refs/heads/z"));
162 assertEquals(0, db
.getReflogReader("HEAD").getReverseEntries().size());
165 public void testNewNamespaceConflictWithPackedPrefixOfExisting()
167 final String newRef
= "refs/heads/prefix";
168 final RefUpdate ru
= updateRef(newRef
);
169 final RevCommit newid
= new RevCommit(ru
.getNewObjectId()) {
172 ru
.setNewObjectId(newid
);
173 Result update
= ru
.update();
174 assertEquals(Result
.LOCK_FAILURE
, update
);
175 assertNull(db
.getReflogReader("refs/heads/prefix"));
176 assertEquals(0, db
.getReflogReader("HEAD").getReverseEntries().size());
180 * Delete a ref that is pointed to by HEAD
182 * @throws IOException
184 public void testDeleteHEADreferencedRef() throws IOException
{
185 ObjectId pid
= db
.resolve("refs/heads/master^");
186 RefUpdate updateRef
= db
.updateRef("refs/heads/master");
187 updateRef
.setNewObjectId(pid
);
188 updateRef
.setForceUpdate(true);
189 Result update
= updateRef
.update();
190 assertEquals(Result
.FORCED
, update
); // internal
192 RefUpdate updateRef2
= db
.updateRef("refs/heads/master");
193 Result delete
= updateRef2
.delete();
194 assertEquals(Result
.REJECTED_CURRENT_BRANCH
, delete
);
195 assertEquals(pid
, db
.resolve("refs/heads/master"));
196 assertEquals(1,db
.getReflogReader("refs/heads/master").getReverseEntries().size());
197 assertEquals(0,db
.getReflogReader("HEAD").getReverseEntries().size());
200 public void testLooseDelete() throws IOException
{
201 final String newRef
= "refs/heads/abc";
202 RefUpdate ref
= updateRef(newRef
);
203 ref
.update(); // create loose ref
204 ref
= updateRef(newRef
); // refresh
205 delete(ref
, Result
.NO_CHANGE
);
206 assertNull(db
.getReflogReader("refs/heads/abc"));
209 public void testDeleteHead() throws IOException
{
210 final RefUpdate ref
= updateRef(Constants
.HEAD
);
211 delete(ref
, Result
.REJECTED_CURRENT_BRANCH
, true, false);
212 assertEquals(0, db
.getReflogReader("refs/heads/master").getReverseEntries().size());
213 assertEquals(0, db
.getReflogReader("HEAD").getReverseEntries().size());
217 * Delete a loose ref and make sure the directory in refs is deleted too,
218 * and the reflog dir too
220 * @throws IOException
222 public void testDeleteLooseAndItsDirectory() throws IOException
{
223 ObjectId pid
= db
.resolve("refs/heads/c^");
224 RefUpdate updateRef
= db
.updateRef("refs/heads/z/c");
225 updateRef
.setNewObjectId(pid
);
226 updateRef
.setForceUpdate(true);
227 updateRef
.setRefLogMessage("new test ref", false);
228 Result update
= updateRef
.update();
229 assertEquals(Result
.NEW
, update
); // internal
230 assertTrue(new File(db
.getDirectory(), Constants
.R_HEADS
+ "z")
232 assertTrue(new File(db
.getDirectory(), "logs/refs/heads/z").exists());
234 // The real test here
235 RefUpdate updateRef2
= db
.updateRef("refs/heads/z/c");
236 updateRef2
.setForceUpdate(true);
237 Result delete
= updateRef2
.delete();
238 assertEquals(Result
.FORCED
, delete
);
239 assertNull(db
.resolve("refs/heads/z/c"));
240 assertFalse(new File(db
.getDirectory(), Constants
.R_HEADS
+ "z")
242 assertFalse(new File(db
.getDirectory(), "logs/refs/heads/z").exists());
245 public void testDeleteNotFound() throws IOException
{
246 final RefUpdate ref
= updateRef("refs/heads/xyz");
247 delete(ref
, Result
.NEW
, false, true);
250 public void testDeleteFastForward() throws IOException
{
251 final RefUpdate ref
= updateRef("refs/heads/a");
252 delete(ref
, Result
.FAST_FORWARD
);
255 public void testDeleteForce() throws IOException
{
256 final RefUpdate ref
= db
.updateRef("refs/heads/b");
257 ref
.setNewObjectId(db
.resolve("refs/heads/a"));
258 delete(ref
, Result
.REJECTED
, true, false);
259 ref
.setForceUpdate(true);
260 delete(ref
, Result
.FORCED
);
263 public void testRefKeySameAsOrigName() {
264 Map
<String
, Ref
> allRefs
= db
.getAllRefs();
265 for (Entry
<String
, Ref
> e
: allRefs
.entrySet()) {
266 assertEquals(e
.getKey(), e
.getValue().getOrigName());
272 * Try modify a ref forward, fast forward
274 * @throws IOException
276 public void testUpdateRefForward() throws IOException
{
277 ObjectId ppid
= db
.resolve("refs/heads/master^");
278 ObjectId pid
= db
.resolve("refs/heads/master");
280 RefUpdate updateRef
= db
.updateRef("refs/heads/master");
281 updateRef
.setNewObjectId(ppid
);
282 updateRef
.setForceUpdate(true);
283 Result update
= updateRef
.update();
284 assertEquals(Result
.FORCED
, update
);
285 assertEquals(ppid
, db
.resolve("refs/heads/master"));
288 RefUpdate updateRef2
= db
.updateRef("refs/heads/master");
289 updateRef2
.setNewObjectId(pid
);
290 Result update2
= updateRef2
.update();
291 assertEquals(Result
.FAST_FORWARD
, update2
);
292 assertEquals(pid
, db
.resolve("refs/heads/master"));
296 * Update the HEAD ref. Only it should be changed, not what it points to.
300 public void testUpdateRefDetached() throws Exception
{
301 ObjectId pid
= db
.resolve("refs/heads/master");
302 ObjectId ppid
= db
.resolve("refs/heads/master^");
303 RefUpdate updateRef
= db
.updateRef("HEAD", true);
304 updateRef
.setForceUpdate(true);
305 updateRef
.setNewObjectId(ppid
);
306 Result update
= updateRef
.update();
307 assertEquals(Result
.FORCED
, update
);
308 assertEquals(ppid
, db
.resolve("HEAD"));
309 Ref ref
= db
.getRef("HEAD");
310 assertEquals("HEAD", ref
.getName());
311 assertEquals("HEAD", ref
.getOrigName());
313 // the branch HEAD referred to is left untouched
314 assertEquals(pid
, db
.resolve("refs/heads/master"));
315 ReflogReader reflogReader
= new ReflogReader(db
, "HEAD");
316 org
.eclipse
.jgit
.lib
.ReflogReader
.Entry e
= reflogReader
.getReverseEntries().get(0);
317 assertEquals(pid
, e
.getOldId());
318 assertEquals(ppid
, e
.getNewId());
319 assertEquals("GIT_COMMITTER_EMAIL", e
.getWho().getEmailAddress());
320 assertEquals("GIT_COMMITTER_NAME", e
.getWho().getName());
321 assertEquals(1250379778000L, e
.getWho().getWhen().getTime());
325 * Update the HEAD ref when the referenced branch is unborn
329 public void testUpdateRefDetachedUnbornHead() throws Exception
{
330 ObjectId ppid
= db
.resolve("refs/heads/master^");
331 db
.writeSymref("HEAD", "refs/heads/unborn");
332 RefUpdate updateRef
= db
.updateRef("HEAD", true);
333 updateRef
.setForceUpdate(true);
334 updateRef
.setNewObjectId(ppid
);
335 Result update
= updateRef
.update();
336 assertEquals(Result
.NEW
, update
);
337 assertEquals(ppid
, db
.resolve("HEAD"));
338 Ref ref
= db
.getRef("HEAD");
339 assertEquals("HEAD", ref
.getName());
340 assertEquals("HEAD", ref
.getOrigName());
342 // the branch HEAD referred to is left untouched
343 assertNull(db
.resolve("refs/heads/unborn"));
344 ReflogReader reflogReader
= new ReflogReader(db
, "HEAD");
345 org
.eclipse
.jgit
.lib
.ReflogReader
.Entry e
= reflogReader
.getReverseEntries().get(0);
346 assertEquals(ObjectId
.zeroId(), e
.getOldId());
347 assertEquals(ppid
, e
.getNewId());
348 assertEquals("GIT_COMMITTER_EMAIL", e
.getWho().getEmailAddress());
349 assertEquals("GIT_COMMITTER_NAME", e
.getWho().getName());
350 assertEquals(1250379778000L, e
.getWho().getWhen().getTime());
354 * Delete a ref that exists both as packed and loose. Make sure the ref
355 * cannot be resolved after delete.
357 * @throws IOException
359 public void testDeleteLoosePacked() throws IOException
{
360 ObjectId pid
= db
.resolve("refs/heads/c^");
361 RefUpdate updateRef
= db
.updateRef("refs/heads/c");
362 updateRef
.setNewObjectId(pid
);
363 updateRef
.setForceUpdate(true);
364 Result update
= updateRef
.update();
365 assertEquals(Result
.FORCED
, update
); // internal
367 // The real test here
368 RefUpdate updateRef2
= db
.updateRef("refs/heads/c");
369 updateRef2
.setForceUpdate(true);
370 Result delete
= updateRef2
.delete();
371 assertEquals(Result
.FORCED
, delete
);
372 assertNull(db
.resolve("refs/heads/c"));
376 * Try modify a ref to same
378 * @throws IOException
380 public void testUpdateRefNoChange() throws IOException
{
381 ObjectId pid
= db
.resolve("refs/heads/master");
382 RefUpdate updateRef
= db
.updateRef("refs/heads/master");
383 updateRef
.setNewObjectId(pid
);
384 Result update
= updateRef
.update();
385 assertEquals(Result
.NO_CHANGE
, update
);
386 assertEquals(pid
, db
.resolve("refs/heads/master"));
390 * Test case originating from
391 * <a href="http://bugs.eclipse.org/285991">bug 285991</a>
393 * Make sure the in memory cache is updated properly after
394 * update of symref. This one did not fail because the
395 * ref was packed due to implementation issues.
399 public void testRefsCacheAfterUpdate() throws Exception
{
400 // Do not use the defalt repo for this case.
401 Map
<String
, Ref
> allRefs
= db
.getAllRefs();
402 ObjectId oldValue
= db
.resolve("HEAD");
403 ObjectId newValue
= db
.resolve("HEAD^");
404 // first make HEAD refer to loose ref
405 RefUpdate updateRef
= db
.updateRef(Constants
.HEAD
);
406 updateRef
.setForceUpdate(true);
407 updateRef
.setNewObjectId(newValue
);
408 Result update
= updateRef
.update();
409 assertEquals(Result
.FORCED
, update
);
411 // now update that ref
412 updateRef
= db
.updateRef(Constants
.HEAD
);
413 updateRef
.setForceUpdate(true);
414 updateRef
.setNewObjectId(oldValue
);
415 update
= updateRef
.update();
416 assertEquals(Result
.FAST_FORWARD
, update
);
417 allRefs
= db
.getAllRefs();
418 assertEquals("refs/heads/master", allRefs
.get("refs/heads/master").getName());
419 assertEquals("refs/heads/master", allRefs
.get("refs/heads/master").getOrigName());
420 assertEquals("refs/heads/master", allRefs
.get("HEAD").getName());
421 assertEquals("HEAD", allRefs
.get("HEAD").getOrigName());
425 * Test case originating from
426 * <a href="http://bugs.eclipse.org/285991">bug 285991</a>
428 * Make sure the in memory cache is updated properly after
433 public void testRefsCacheAfterUpdateLoosOnly() throws Exception
{
434 // Do not use the defalt repo for this case.
435 Map
<String
, Ref
> allRefs
= db
.getAllRefs();
436 ObjectId oldValue
= db
.resolve("HEAD");
437 db
.writeSymref(Constants
.HEAD
, "refs/heads/newref");
438 RefUpdate updateRef
= db
.updateRef(Constants
.HEAD
);
439 updateRef
.setForceUpdate(true);
440 updateRef
.setNewObjectId(oldValue
);
441 Result update
= updateRef
.update();
442 assertEquals(Result
.NEW
, update
);
443 allRefs
= db
.getAllRefs();
444 assertEquals("refs/heads/newref", allRefs
.get("HEAD").getName());
445 assertEquals("HEAD", allRefs
.get("HEAD").getOrigName());
446 assertEquals("refs/heads/newref", allRefs
.get("refs/heads/newref").getName());
447 assertEquals("refs/heads/newref", allRefs
.get("refs/heads/newref").getOrigName());
451 * Try modify a ref, but get wrong expected old value
453 * @throws IOException
455 public void testUpdateRefLockFailureWrongOldValue() throws IOException
{
456 ObjectId pid
= db
.resolve("refs/heads/master");
457 RefUpdate updateRef
= db
.updateRef("refs/heads/master");
458 updateRef
.setNewObjectId(pid
);
459 updateRef
.setExpectedOldObjectId(db
.resolve("refs/heads/master^"));
460 Result update
= updateRef
.update();
461 assertEquals(Result
.LOCK_FAILURE
, update
);
462 assertEquals(pid
, db
.resolve("refs/heads/master"));
466 * Try modify a ref forward, fast forward, checking old value first
468 * @throws IOException
470 public void testUpdateRefForwardWithCheck1() throws IOException
{
471 ObjectId ppid
= db
.resolve("refs/heads/master^");
472 ObjectId pid
= db
.resolve("refs/heads/master");
474 RefUpdate updateRef
= db
.updateRef("refs/heads/master");
475 updateRef
.setNewObjectId(ppid
);
476 updateRef
.setForceUpdate(true);
477 Result update
= updateRef
.update();
478 assertEquals(Result
.FORCED
, update
);
479 assertEquals(ppid
, db
.resolve("refs/heads/master"));
482 RefUpdate updateRef2
= db
.updateRef("refs/heads/master");
483 updateRef2
.setExpectedOldObjectId(ppid
);
484 updateRef2
.setNewObjectId(pid
);
485 Result update2
= updateRef2
.update();
486 assertEquals(Result
.FAST_FORWARD
, update2
);
487 assertEquals(pid
, db
.resolve("refs/heads/master"));
491 * Try modify a ref forward, fast forward, checking old commit first
493 * @throws IOException
495 public void testUpdateRefForwardWithCheck2() throws IOException
{
496 ObjectId ppid
= db
.resolve("refs/heads/master^");
497 ObjectId pid
= db
.resolve("refs/heads/master");
499 RefUpdate updateRef
= db
.updateRef("refs/heads/master");
500 updateRef
.setNewObjectId(ppid
);
501 updateRef
.setForceUpdate(true);
502 Result update
= updateRef
.update();
503 assertEquals(Result
.FORCED
, update
);
504 assertEquals(ppid
, db
.resolve("refs/heads/master"));
507 RevCommit old
= new RevWalk(db
).parseCommit(ppid
);
508 RefUpdate updateRef2
= db
.updateRef("refs/heads/master");
509 updateRef2
.setExpectedOldObjectId(old
);
510 updateRef2
.setNewObjectId(pid
);
511 Result update2
= updateRef2
.update();
512 assertEquals(Result
.FAST_FORWARD
, update2
);
513 assertEquals(pid
, db
.resolve("refs/heads/master"));
517 * Try modify a ref that is locked
519 * @throws IOException
521 public void testUpdateRefLockFailureLocked() throws IOException
{
522 ObjectId opid
= db
.resolve("refs/heads/master");
523 ObjectId pid
= db
.resolve("refs/heads/master^");
524 RefUpdate updateRef
= db
.updateRef("refs/heads/master");
525 updateRef
.setNewObjectId(pid
);
526 LockFile lockFile1
= new LockFile(new File(db
.getDirectory(),"refs/heads/master"));
528 assertTrue(lockFile1
.lock()); // precondition to test
529 Result update
= updateRef
.update();
530 assertEquals(Result
.LOCK_FAILURE
, update
);
531 assertEquals(opid
, db
.resolve("refs/heads/master"));
532 LockFile lockFile2
= new LockFile(new File(db
.getDirectory(),"refs/heads/master"));
533 assertFalse(lockFile2
.lock()); // was locked, still is
540 * Try to delete a ref. Delete requires force.
542 * @throws IOException
544 public void testDeleteLoosePackedRejected() throws IOException
{
545 ObjectId pid
= db
.resolve("refs/heads/c^");
546 ObjectId oldpid
= db
.resolve("refs/heads/c");
547 RefUpdate updateRef
= db
.updateRef("refs/heads/c");
548 updateRef
.setNewObjectId(pid
);
549 Result update
= updateRef
.update();
550 assertEquals(Result
.REJECTED
, update
);
551 assertEquals(oldpid
, db
.resolve("refs/heads/c"));
554 public void testRenameBranchNoPreviousLog() throws IOException
{
555 assertFalse("precondition, no log on old branchg", new File(db
556 .getDirectory(), "logs/refs/heads/b").exists());
557 ObjectId rb
= db
.resolve("refs/heads/b");
558 ObjectId oldHead
= db
.resolve(Constants
.HEAD
);
559 assertFalse(rb
.equals(oldHead
)); // assumption for this test
560 RefRename renameRef
= db
.renameRef("refs/heads/b",
561 "refs/heads/new/name");
562 Result result
= renameRef
.rename();
563 assertEquals(Result
.RENAMED
, result
);
564 assertEquals(rb
, db
.resolve("refs/heads/new/name"));
565 assertNull(db
.resolve("refs/heads/b"));
566 assertEquals(1, db
.getReflogReader("new/name").getReverseEntries().size());
567 assertEquals("Branch: renamed b to new/name", db
.getReflogReader("new/name")
568 .getLastEntry().getComment());
569 assertFalse(new File(db
.getDirectory(), "logs/refs/heads/b").exists());
570 assertEquals(oldHead
, db
.resolve(Constants
.HEAD
)); // unchanged
573 public void testRenameBranchHasPreviousLog() throws IOException
{
574 ObjectId rb
= db
.resolve("refs/heads/b");
575 ObjectId oldHead
= db
.resolve(Constants
.HEAD
);
576 assertFalse("precondition for this test, branch b != HEAD", rb
578 RefLogWriter
.writeReflog(db
, rb
, rb
, "Just a message", "refs/heads/b");
579 assertTrue("no log on old branch", new File(db
.getDirectory(),
580 "logs/refs/heads/b").exists());
581 RefRename renameRef
= db
.renameRef("refs/heads/b",
582 "refs/heads/new/name");
583 Result result
= renameRef
.rename();
584 assertEquals(Result
.RENAMED
, result
);
585 assertEquals(rb
, db
.resolve("refs/heads/new/name"));
586 assertNull(db
.resolve("refs/heads/b"));
587 assertEquals(2, db
.getReflogReader("new/name").getReverseEntries().size());
588 assertEquals("Branch: renamed b to new/name", db
.getReflogReader("new/name")
589 .getLastEntry().getComment());
590 assertEquals("Just a message", db
.getReflogReader("new/name")
591 .getReverseEntries().get(1).getComment());
592 assertFalse(new File(db
.getDirectory(), "logs/refs/heads/b").exists());
593 assertEquals(oldHead
, db
.resolve(Constants
.HEAD
)); // unchanged
596 public void testRenameCurrentBranch() throws IOException
{
597 ObjectId rb
= db
.resolve("refs/heads/b");
598 db
.writeSymref(Constants
.HEAD
, "refs/heads/b");
599 ObjectId oldHead
= db
.resolve(Constants
.HEAD
);
600 assertTrue("internal test condition, b == HEAD", rb
.equals(oldHead
));
601 RefLogWriter
.writeReflog(db
, rb
, rb
, "Just a message", "refs/heads/b");
602 assertTrue("no log on old branch", new File(db
.getDirectory(),
603 "logs/refs/heads/b").exists());
604 RefRename renameRef
= db
.renameRef("refs/heads/b",
605 "refs/heads/new/name");
606 Result result
= renameRef
.rename();
607 assertEquals(Result
.RENAMED
, result
);
608 assertEquals(rb
, db
.resolve("refs/heads/new/name"));
609 assertNull(db
.resolve("refs/heads/b"));
610 assertEquals("Branch: renamed b to new/name", db
.getReflogReader(
611 "new/name").getLastEntry().getComment());
612 assertFalse(new File(db
.getDirectory(), "logs/refs/heads/b").exists());
613 assertEquals(rb
, db
.resolve(Constants
.HEAD
));
614 assertEquals(2, db
.getReflogReader("new/name").getReverseEntries().size());
615 assertEquals("Branch: renamed b to new/name", db
.getReflogReader("new/name").getReverseEntries().get(0).getComment());
616 assertEquals("Just a message", db
.getReflogReader("new/name").getReverseEntries().get(1).getComment());
619 public void testRenameBranchAlsoInPack() throws IOException
{
620 ObjectId rb
= db
.resolve("refs/heads/b");
621 ObjectId rb2
= db
.resolve("refs/heads/b~1");
622 assertEquals(Ref
.Storage
.PACKED
, db
.getRef("refs/heads/b").getStorage());
623 RefUpdate updateRef
= db
.updateRef("refs/heads/b");
624 updateRef
.setNewObjectId(rb2
);
625 updateRef
.setForceUpdate(true);
626 Result update
= updateRef
.update();
627 assertEquals("internal check new ref is loose", Result
.FORCED
, update
);
628 assertEquals(Ref
.Storage
.LOOSE_PACKED
, db
.getRef("refs/heads/b")
630 RefLogWriter
.writeReflog(db
, rb
, rb
, "Just a message", "refs/heads/b");
631 assertTrue("no log on old branch", new File(db
.getDirectory(),
632 "logs/refs/heads/b").exists());
633 RefRename renameRef
= db
.renameRef("refs/heads/b",
634 "refs/heads/new/name");
635 Result result
= renameRef
.rename();
636 assertEquals(Result
.RENAMED
, result
);
637 assertEquals(rb2
, db
.resolve("refs/heads/new/name"));
638 assertNull(db
.resolve("refs/heads/b"));
639 assertEquals("Branch: renamed b to new/name", db
.getReflogReader(
640 "new/name").getLastEntry().getComment());
641 assertEquals(3, db
.getReflogReader("refs/heads/new/name").getReverseEntries().size());
642 assertEquals("Branch: renamed b to new/name", db
.getReflogReader("refs/heads/new/name").getReverseEntries().get(0).getComment());
643 assertEquals(0, db
.getReflogReader("HEAD").getReverseEntries().size());
644 // make sure b's log file is gone too.
645 assertFalse(new File(db
.getDirectory(), "logs/refs/heads/b").exists());
647 // Create new Repository instance, to reread caches and make sure our
648 // assumptions are persistent.
649 Repository ndb
= new Repository(db
.getDirectory());
650 assertEquals(rb2
, ndb
.resolve("refs/heads/new/name"));
651 assertNull(ndb
.resolve("refs/heads/b"));
654 public void tryRenameWhenLocked(String toLock
, String fromName
,
655 String toName
, String headPointsTo
) throws IOException
{
657 db
.writeSymref(Constants
.HEAD
, headPointsTo
);
658 ObjectId oldfromId
= db
.resolve(fromName
);
659 ObjectId oldHeadId
= db
.resolve(Constants
.HEAD
);
660 RefLogWriter
.writeReflog(db
, oldfromId
, oldfromId
, "Just a message",
662 List
<org
.eclipse
.jgit
.lib
.ReflogReader
.Entry
> oldFromLog
= db
663 .getReflogReader(fromName
).getReverseEntries();
664 List
<org
.eclipse
.jgit
.lib
.ReflogReader
.Entry
> oldHeadLog
= oldHeadId
!= null ? db
665 .getReflogReader(Constants
.HEAD
).getReverseEntries() : null;
667 assertTrue("internal check, we have a log", new File(db
.getDirectory(),
668 "logs/" + fromName
).exists());
670 // "someone" has branch X locked
671 LockFile lockFile
= new LockFile(new File(db
.getDirectory(), toLock
));
673 assertTrue(lockFile
.lock());
675 // Now this is our test
676 RefRename renameRef
= db
.renameRef(fromName
, toName
);
677 Result result
= renameRef
.rename();
678 assertEquals(Result
.LOCK_FAILURE
, result
);
680 // Check that the involved refs are the same despite the failure
681 assertExists(false, toName
);
682 if (!toLock
.equals(toName
))
683 assertExists(false, toName
+ ".lock");
684 assertExists(true, toLock
+ ".lock");
685 if (!toLock
.equals(fromName
))
686 assertExists(false, "logs/" + fromName
+ ".lock");
687 assertExists(false, "logs/" + toName
+ ".lock");
688 assertEquals(oldHeadId
, db
.resolve(Constants
.HEAD
));
689 assertEquals(oldfromId
, db
.resolve(fromName
));
690 assertNull(db
.resolve(toName
));
691 assertEquals(oldFromLog
.toString(), db
.getReflogReader(fromName
)
692 .getReverseEntries().toString());
693 if (oldHeadId
!= null)
694 assertEquals(oldHeadLog
, db
.getReflogReader(Constants
.HEAD
)
695 .getReverseEntries());
701 private void assertExists(boolean positive
, String toName
) {
702 assertEquals(toName
+ (positive ?
" " : " does not ") + "exist",
703 positive
, new File(db
.getDirectory(), toName
).exists());
706 public void testRenameBranchCannotLockAFileHEADisFromLockHEAD()
708 tryRenameWhenLocked("HEAD", "refs/heads/b", "refs/heads/new/name",
712 public void testRenameBranchCannotLockAFileHEADisFromLockFrom()
714 tryRenameWhenLocked("refs/heads/b", "refs/heads/b",
715 "refs/heads/new/name", "refs/heads/b");
718 public void testRenameBranchCannotLockAFileHEADisFromLockTo()
720 tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b",
721 "refs/heads/new/name", "refs/heads/b");
724 public void testRenameBranchCannotLockAFileHEADisToLockFrom()
726 tryRenameWhenLocked("refs/heads/b", "refs/heads/b",
727 "refs/heads/new/name", "refs/heads/new/name");
730 public void testRenameBranchCannotLockAFileHEADisToLockTo()
732 tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b",
733 "refs/heads/new/name", "refs/heads/new/name");
736 public void testRenameBranchCannotLockAFileHEADisToLockTmp()
738 tryRenameWhenLocked("RENAMED-REF.." + Thread
.currentThread().getId(),
739 "refs/heads/b", "refs/heads/new/name", "refs/heads/new/name");
742 public void testRenameBranchCannotLockAFileHEADisOtherLockFrom()
744 tryRenameWhenLocked("refs/heads/b", "refs/heads/b",
745 "refs/heads/new/name", "refs/heads/a");
748 public void testRenameBranchCannotLockAFileHEADisOtherLockTo()
750 tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b",
751 "refs/heads/new/name", "refs/heads/a");
754 public void testRenameBranchCannotLockAFileHEADisOtherLockTmp()
756 tryRenameWhenLocked("RENAMED-REF.." + Thread
.currentThread().getId(),
757 "refs/heads/b", "refs/heads/new/name", "refs/heads/a");
760 public void testRenameRefNameColission1avoided() throws IOException
{
762 ObjectId rb
= db
.resolve("refs/heads/b");
763 db
.writeSymref(Constants
.HEAD
, "refs/heads/a");
764 RefUpdate updateRef
= db
.updateRef("refs/heads/a");
765 updateRef
.setNewObjectId(rb
);
766 updateRef
.setRefLogMessage("Setup", false);
767 assertEquals(Result
.FAST_FORWARD
, updateRef
.update());
768 ObjectId oldHead
= db
.resolve(Constants
.HEAD
);
769 assertTrue(rb
.equals(oldHead
)); // assumption for this test
770 RefLogWriter
.writeReflog(db
, rb
, rb
, "Just a message", "refs/heads/a");
771 assertTrue("internal check, we have a log", new File(db
.getDirectory(),
772 "logs/refs/heads/a").exists());
774 // Now this is our test
775 RefRename renameRef
= db
.renameRef("refs/heads/a", "refs/heads/a/b");
776 Result result
= renameRef
.rename();
777 assertEquals(Result
.RENAMED
, result
);
778 assertNull(db
.resolve("refs/heads/a"));
779 assertEquals(rb
, db
.resolve("refs/heads/a/b"));
780 assertEquals(3, db
.getReflogReader("a/b").getReverseEntries().size());
781 assertEquals("Branch: renamed a to a/b", db
.getReflogReader("a/b")
782 .getReverseEntries().get(0).getComment());
783 assertEquals("Just a message", db
.getReflogReader("a/b")
784 .getReverseEntries().get(1).getComment());
785 assertEquals("Setup", db
.getReflogReader("a/b").getReverseEntries()
786 .get(2).getComment());
787 // same thing was logged to HEAD
788 assertEquals("Branch: renamed a to a/b", db
.getReflogReader("HEAD")
789 .getReverseEntries().get(0).getComment());
792 public void testRenameRefNameColission2avoided() throws IOException
{
794 ObjectId rb
= db
.resolve("refs/heads/b");
795 db
.writeSymref(Constants
.HEAD
, "refs/heads/prefix/a");
796 RefUpdate updateRef
= db
.updateRef("refs/heads/prefix/a");
797 updateRef
.setNewObjectId(rb
);
798 updateRef
.setRefLogMessage("Setup", false);
799 updateRef
.setForceUpdate(true);
800 assertEquals(Result
.FORCED
, updateRef
.update());
801 ObjectId oldHead
= db
.resolve(Constants
.HEAD
);
802 assertTrue(rb
.equals(oldHead
)); // assumption for this test
803 RefLogWriter
.writeReflog(db
, rb
, rb
, "Just a message",
804 "refs/heads/prefix/a");
805 assertTrue("internal check, we have a log", new File(db
.getDirectory(),
806 "logs/refs/heads/prefix/a").exists());
808 // Now this is our test
809 RefRename renameRef
= db
.renameRef("refs/heads/prefix/a",
810 "refs/heads/prefix");
811 Result result
= renameRef
.rename();
812 assertEquals(Result
.RENAMED
, result
);
814 assertNull(db
.resolve("refs/heads/prefix/a"));
815 assertEquals(rb
, db
.resolve("refs/heads/prefix"));
816 assertEquals(3, db
.getReflogReader("prefix").getReverseEntries().size());
817 assertEquals("Branch: renamed prefix/a to prefix", db
.getReflogReader(
818 "prefix").getReverseEntries().get(0).getComment());
819 assertEquals("Just a message", db
.getReflogReader("prefix")
820 .getReverseEntries().get(1).getComment());
821 assertEquals("Setup", db
.getReflogReader("prefix").getReverseEntries()
822 .get(2).getComment());
823 assertEquals("Branch: renamed prefix/a to prefix", db
.getReflogReader(
824 "HEAD").getReverseEntries().get(0).getComment());