You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RefUpdateTest.java 38KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  1. /*
  2. * Copyright (C) 2008, Charles O'Farrell <charleso@charleso.org>
  3. * Copyright (C) 2009-2010, Google Inc.
  4. * Copyright (C) 2008-2013, Robin Rosenberg <robin.rosenberg@dewire.com>
  5. * and other copyright owners as documented in the project's IP log.
  6. *
  7. * This program and the accompanying materials are made available
  8. * under the terms of the Eclipse Distribution License v1.0 which
  9. * accompanies this distribution, is reproduced below, and is
  10. * available at http://www.eclipse.org/org/documents/edl-v10.php
  11. *
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or
  15. * without modification, are permitted provided that the following
  16. * conditions are met:
  17. *
  18. * - Redistributions of source code must retain the above copyright
  19. * notice, this list of conditions and the following disclaimer.
  20. *
  21. * - Redistributions in binary form must reproduce the above
  22. * copyright notice, this list of conditions and the following
  23. * disclaimer in the documentation and/or other materials provided
  24. * with the distribution.
  25. *
  26. * - Neither the name of the Eclipse Foundation, Inc. nor the
  27. * names of its contributors may be used to endorse or promote
  28. * products derived from this software without specific prior
  29. * written permission.
  30. *
  31. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  32. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  33. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  34. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  36. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  37. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  38. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  39. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  40. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  41. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  42. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  43. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. */
  45. package org.eclipse.jgit.internal.storage.file;
  46. import static java.nio.charset.StandardCharsets.UTF_8;
  47. import static org.eclipse.jgit.junit.Assert.assertEquals;
  48. import static org.eclipse.jgit.lib.Constants.LOCK_SUFFIX;
  49. import static org.eclipse.jgit.lib.RefUpdate.Result.FORCED;
  50. import static org.eclipse.jgit.lib.RefUpdate.Result.IO_FAILURE;
  51. import static org.eclipse.jgit.lib.RefUpdate.Result.LOCK_FAILURE;
  52. import static org.junit.Assert.assertEquals;
  53. import static org.junit.Assert.assertFalse;
  54. import static org.junit.Assert.assertNotNull;
  55. import static org.junit.Assert.assertNotSame;
  56. import static org.junit.Assert.assertNull;
  57. import static org.junit.Assert.assertSame;
  58. import static org.junit.Assert.assertTrue;
  59. import static org.junit.Assert.fail;
  60. import java.io.File;
  61. import java.io.IOException;
  62. import java.util.List;
  63. import java.util.Map;
  64. import java.util.Map.Entry;
  65. import java.util.Optional;
  66. import org.eclipse.jgit.lib.AnyObjectId;
  67. import org.eclipse.jgit.lib.Constants;
  68. import org.eclipse.jgit.lib.ObjectId;
  69. import org.eclipse.jgit.lib.ObjectInserter;
  70. import org.eclipse.jgit.lib.PersonIdent;
  71. import org.eclipse.jgit.lib.Ref;
  72. import org.eclipse.jgit.lib.RefRename;
  73. import org.eclipse.jgit.lib.RefUpdate;
  74. import org.eclipse.jgit.lib.RefUpdate.Result;
  75. import org.eclipse.jgit.lib.ReflogEntry;
  76. import org.eclipse.jgit.lib.ReflogReader;
  77. import org.eclipse.jgit.lib.Repository;
  78. import org.eclipse.jgit.revwalk.RevCommit;
  79. import org.eclipse.jgit.revwalk.RevWalk;
  80. import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
  81. import org.junit.Test;
  82. public class RefUpdateTest extends SampleDataRepositoryTestCase {
  83. private void writeSymref(String src, String dst) throws IOException {
  84. RefUpdate u = db.updateRef(src);
  85. switch (u.link(dst)) {
  86. case NEW:
  87. case FORCED:
  88. case NO_CHANGE:
  89. break;
  90. default:
  91. fail("link " + src + " to " + dst);
  92. }
  93. }
  94. private RefUpdate updateRef(String name) throws IOException {
  95. final RefUpdate ref = db.updateRef(name);
  96. ref.setNewObjectId(db.resolve(Constants.HEAD));
  97. return ref;
  98. }
  99. private void delete(RefUpdate ref, Result expected)
  100. throws IOException {
  101. delete(ref, expected, true, true);
  102. }
  103. private void delete(final RefUpdate ref, final Result expected,
  104. final boolean exists, final boolean removed) throws IOException {
  105. delete(db, ref, expected, exists, removed);
  106. }
  107. private void delete(Repository repo, final RefUpdate ref,
  108. final Result expected, final boolean exists, final boolean removed)
  109. throws IOException {
  110. assertEquals(exists, getRef(repo, ref.getName()).isPresent());
  111. assertEquals(expected, ref.delete());
  112. assertEquals(!removed, getRef(repo, ref.getName()).isPresent());
  113. }
  114. private Optional<Ref> getRef(Repository repo, String name)
  115. throws IOException {
  116. return getRef(repo.getRefDatabase().getRefs(), name);
  117. }
  118. private Optional<Ref> getRef(List<Ref> refs, String name) {
  119. return refs.stream().filter(r -> r.getName().equals(name)).findAny();
  120. }
  121. @Test
  122. public void testNoCacheObjectIdSubclass() throws IOException {
  123. final String newRef = "refs/heads/abc";
  124. final RefUpdate ru = updateRef(newRef);
  125. final SubclassedId newid = new SubclassedId(ru.getNewObjectId());
  126. ru.setNewObjectId(newid);
  127. Result update = ru.update();
  128. assertEquals(Result.NEW, update);
  129. final Ref r = getRef(db, newRef).get();
  130. assertEquals(newRef, r.getName());
  131. assertNotNull(r.getObjectId());
  132. assertNotSame(newid, r.getObjectId());
  133. assertSame(ObjectId.class, r.getObjectId().getClass());
  134. assertEquals(newid, r.getObjectId());
  135. List<ReflogEntry> reverseEntries1 = db
  136. .getReflogReader("refs/heads/abc").getReverseEntries();
  137. ReflogEntry entry1 = reverseEntries1.get(0);
  138. assertEquals(1, reverseEntries1.size());
  139. assertEquals(ObjectId.zeroId(), entry1.getOldId());
  140. assertEquals(r.getObjectId(), entry1.getNewId());
  141. assertEquals(new PersonIdent(db).toString(), entry1.getWho().toString());
  142. assertEquals("", entry1.getComment());
  143. List<ReflogEntry> reverseEntries2 = db.getReflogReader("HEAD")
  144. .getReverseEntries();
  145. assertEquals(0, reverseEntries2.size());
  146. }
  147. @Test
  148. public void testNewNamespaceConflictWithLoosePrefixNameExists()
  149. throws IOException {
  150. final String newRef = "refs/heads/z";
  151. final RefUpdate ru = updateRef(newRef);
  152. Result update = ru.update();
  153. assertEquals(Result.NEW, update);
  154. // end setup
  155. final String newRef2 = "refs/heads/z/a";
  156. final RefUpdate ru2 = updateRef(newRef2);
  157. Result update2 = ru2.update();
  158. assertEquals(Result.LOCK_FAILURE, update2);
  159. assertEquals(1, db.getReflogReader("refs/heads/z").getReverseEntries().size());
  160. assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
  161. }
  162. @Test
  163. public void testNewNamespaceConflictWithPackedPrefixNameExists()
  164. throws IOException {
  165. final String newRef = "refs/heads/master/x";
  166. final RefUpdate ru = updateRef(newRef);
  167. Result update = ru.update();
  168. assertEquals(Result.LOCK_FAILURE, update);
  169. assertNull(db.getReflogReader("refs/heads/master/x"));
  170. assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
  171. }
  172. @Test
  173. public void testNewNamespaceConflictWithLoosePrefixOfExisting()
  174. throws IOException {
  175. final String newRef = "refs/heads/z/a";
  176. final RefUpdate ru = updateRef(newRef);
  177. Result update = ru.update();
  178. assertEquals(Result.NEW, update);
  179. // end setup
  180. final String newRef2 = "refs/heads/z";
  181. final RefUpdate ru2 = updateRef(newRef2);
  182. Result update2 = ru2.update();
  183. assertEquals(Result.LOCK_FAILURE, update2);
  184. assertEquals(1, db.getReflogReader("refs/heads/z/a").getReverseEntries().size());
  185. assertNull(db.getReflogReader("refs/heads/z"));
  186. assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
  187. }
  188. @Test
  189. public void testNewNamespaceConflictWithPackedPrefixOfExisting()
  190. throws IOException {
  191. final String newRef = "refs/heads/prefix";
  192. final RefUpdate ru = updateRef(newRef);
  193. Result update = ru.update();
  194. assertEquals(Result.LOCK_FAILURE, update);
  195. assertNull(db.getReflogReader("refs/heads/prefix"));
  196. assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
  197. }
  198. /**
  199. * Delete a ref that is pointed to by HEAD
  200. *
  201. * @throws IOException
  202. */
  203. @Test
  204. public void testDeleteHEADreferencedRef() throws IOException {
  205. ObjectId pid = db.resolve("refs/heads/master^");
  206. RefUpdate updateRef = db.updateRef("refs/heads/master");
  207. updateRef.setNewObjectId(pid);
  208. updateRef.setForceUpdate(true);
  209. Result update = updateRef.update();
  210. assertEquals(Result.FORCED, update); // internal
  211. RefUpdate updateRef2 = db.updateRef("refs/heads/master");
  212. Result delete = updateRef2.delete();
  213. assertEquals(Result.REJECTED_CURRENT_BRANCH, delete);
  214. assertEquals(pid, db.resolve("refs/heads/master"));
  215. assertEquals(1,db.getReflogReader("refs/heads/master").getReverseEntries().size());
  216. assertEquals(0,db.getReflogReader("HEAD").getReverseEntries().size());
  217. }
  218. @Test
  219. public void testWriteReflog() throws IOException {
  220. ObjectId pid = db.resolve("refs/heads/master^");
  221. RefUpdate updateRef = db.updateRef("refs/heads/master");
  222. updateRef.setNewObjectId(pid);
  223. updateRef.setForceUpdate(true);
  224. Result update = updateRef.update();
  225. assertEquals(Result.FORCED, update);
  226. assertEquals(1,db.getReflogReader("refs/heads/master").getReverseEntries().size());
  227. }
  228. @Test
  229. public void testLooseDelete() throws IOException {
  230. final String newRef = "refs/heads/abc";
  231. RefUpdate ref = updateRef(newRef);
  232. ref.update(); // create loose ref
  233. ref = updateRef(newRef); // refresh
  234. delete(ref, Result.NO_CHANGE);
  235. assertNull(db.getReflogReader("refs/heads/abc"));
  236. }
  237. @Test
  238. public void testDeleteHead() throws IOException {
  239. final RefUpdate ref = updateRef(Constants.HEAD);
  240. delete(ref, Result.REJECTED_CURRENT_BRANCH, true, false);
  241. assertEquals(0, db.getReflogReader("refs/heads/master").getReverseEntries().size());
  242. assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
  243. }
  244. @Test
  245. public void testDeleteHeadInBareRepo() throws IOException {
  246. Repository bareRepo = createBareRepository();
  247. String master = "refs/heads/master";
  248. Ref head = bareRepo.exactRef(Constants.HEAD);
  249. assertNotNull(head);
  250. assertTrue(head.isSymbolic());
  251. assertEquals(master, head.getLeaf().getName());
  252. assertNull(head.getObjectId());
  253. assertNull(bareRepo.exactRef(master));
  254. ObjectId blobId;
  255. try (ObjectInserter ins = bareRepo.newObjectInserter()) {
  256. blobId = ins.insert(Constants.OBJ_BLOB, "contents".getBytes(UTF_8));
  257. ins.flush();
  258. }
  259. // Create master via HEAD, so we delete it.
  260. RefUpdate ref = bareRepo.updateRef(Constants.HEAD);
  261. ref.setNewObjectId(blobId);
  262. assertEquals(Result.NEW, ref.update());
  263. head = bareRepo.exactRef(Constants.HEAD);
  264. assertTrue(head.isSymbolic());
  265. assertEquals(master, head.getLeaf().getName());
  266. assertEquals(blobId, head.getLeaf().getObjectId());
  267. assertEquals(blobId, bareRepo.exactRef(master).getObjectId());
  268. // Unlike in a non-bare repo, deleting the HEAD is allowed, and leaves HEAD
  269. // back in a dangling state.
  270. ref = bareRepo.updateRef(Constants.HEAD);
  271. ref.setExpectedOldObjectId(blobId);
  272. ref.setForceUpdate(true);
  273. delete(bareRepo, ref, Result.FORCED, true, true);
  274. head = bareRepo.exactRef(Constants.HEAD);
  275. assertNotNull(head);
  276. assertTrue(head.isSymbolic());
  277. assertEquals(master, head.getLeaf().getName());
  278. assertNull(head.getObjectId());
  279. assertNull(bareRepo.exactRef(master));
  280. }
  281. @Test
  282. public void testDeleteSymref() throws IOException {
  283. RefUpdate dst = updateRef("refs/heads/abc");
  284. assertEquals(Result.NEW, dst.update());
  285. ObjectId id = dst.getNewObjectId();
  286. RefUpdate u = db.updateRef("refs/symref");
  287. assertEquals(Result.NEW, u.link(dst.getName()));
  288. Ref ref = db.exactRef(u.getName());
  289. assertNotNull(ref);
  290. assertTrue(ref.isSymbolic());
  291. assertEquals(dst.getName(), ref.getLeaf().getName());
  292. assertEquals(id, ref.getLeaf().getObjectId());
  293. u = db.updateRef(u.getName());
  294. u.setDetachingSymbolicRef();
  295. u.setForceUpdate(true);
  296. assertEquals(Result.FORCED, u.delete());
  297. assertNull(db.exactRef(u.getName()));
  298. ref = db.exactRef(dst.getName());
  299. assertNotNull(ref);
  300. assertFalse(ref.isSymbolic());
  301. assertEquals(id, ref.getObjectId());
  302. }
  303. /**
  304. * Delete a loose ref and make sure the directory in refs is deleted too,
  305. * and the reflog dir too
  306. *
  307. * @throws IOException
  308. */
  309. @Test
  310. public void testDeleteLooseAndItsDirectory() throws IOException {
  311. ObjectId pid = db.resolve("refs/heads/c^");
  312. RefUpdate updateRef = db.updateRef("refs/heads/z/c");
  313. updateRef.setNewObjectId(pid);
  314. updateRef.setForceUpdate(true);
  315. updateRef.setRefLogMessage("new test ref", false);
  316. Result update = updateRef.update();
  317. assertEquals(Result.NEW, update); // internal
  318. assertTrue(new File(db.getDirectory(), Constants.R_HEADS + "z")
  319. .exists());
  320. assertTrue(new File(db.getDirectory(), "logs/refs/heads/z").exists());
  321. // The real test here
  322. RefUpdate updateRef2 = db.updateRef("refs/heads/z/c");
  323. updateRef2.setForceUpdate(true);
  324. Result delete = updateRef2.delete();
  325. assertEquals(Result.FORCED, delete);
  326. assertNull(db.resolve("refs/heads/z/c"));
  327. assertFalse(new File(db.getDirectory(), Constants.R_HEADS + "z")
  328. .exists());
  329. assertFalse(new File(db.getDirectory(), "logs/refs/heads/z").exists());
  330. }
  331. @Test
  332. public void testDeleteNotFound() throws IOException {
  333. final RefUpdate ref = updateRef("refs/heads/xyz");
  334. delete(ref, Result.NEW, false, true);
  335. }
  336. @Test
  337. public void testDeleteFastForward() throws IOException {
  338. final RefUpdate ref = updateRef("refs/heads/a");
  339. delete(ref, Result.FAST_FORWARD);
  340. }
  341. @Test
  342. public void testDeleteForce() throws IOException {
  343. final RefUpdate ref = db.updateRef("refs/heads/b");
  344. ref.setNewObjectId(db.resolve("refs/heads/a"));
  345. delete(ref, Result.REJECTED, true, false);
  346. ref.setForceUpdate(true);
  347. delete(ref, Result.FORCED);
  348. }
  349. @Test
  350. public void testDeleteWithoutHead() throws IOException {
  351. // Prepare repository without HEAD
  352. RefUpdate refUpdate = db.updateRef(Constants.HEAD, true);
  353. refUpdate.setForceUpdate(true);
  354. refUpdate.setNewObjectId(ObjectId.zeroId());
  355. Result updateResult = refUpdate.update();
  356. assertEquals(Result.FORCED, updateResult);
  357. assertEquals(ObjectId.zeroId(), db.exactRef("HEAD").getObjectId());
  358. Result deleteHeadResult = db.updateRef(Constants.HEAD).delete();
  359. assertEquals(Result.NO_CHANGE, deleteHeadResult);
  360. // Any result is ok as long as it's not an NPE
  361. db.updateRef(Constants.R_HEADS + "master").delete();
  362. }
  363. @Test
  364. public void testRefKeySameAsName() {
  365. @SuppressWarnings("deprecation")
  366. Map<String, Ref> allRefs = db.getAllRefs();
  367. for (Entry<String, Ref> e : allRefs.entrySet()) {
  368. assertEquals(e.getKey(), e.getValue().getName());
  369. }
  370. }
  371. /**
  372. * Try modify a ref forward, fast forward
  373. *
  374. * @throws IOException
  375. */
  376. @Test
  377. public void testUpdateRefForward() throws IOException {
  378. ObjectId ppid = db.resolve("refs/heads/master^");
  379. ObjectId pid = db.resolve("refs/heads/master");
  380. RefUpdate updateRef = db.updateRef("refs/heads/master");
  381. updateRef.setNewObjectId(ppid);
  382. updateRef.setForceUpdate(true);
  383. Result update = updateRef.update();
  384. assertEquals(Result.FORCED, update);
  385. assertEquals(ppid, db.resolve("refs/heads/master"));
  386. // real test
  387. RefUpdate updateRef2 = db.updateRef("refs/heads/master");
  388. updateRef2.setNewObjectId(pid);
  389. Result update2 = updateRef2.update();
  390. assertEquals(Result.FAST_FORWARD, update2);
  391. assertEquals(pid, db.resolve("refs/heads/master"));
  392. }
  393. /**
  394. * Update the HEAD ref. Only it should be changed, not what it points to.
  395. *
  396. * @throws Exception
  397. */
  398. @Test
  399. public void testUpdateRefDetached() throws Exception {
  400. ObjectId pid = db.resolve("refs/heads/master");
  401. ObjectId ppid = db.resolve("refs/heads/master^");
  402. RefUpdate updateRef = db.updateRef("HEAD", true);
  403. updateRef.setForceUpdate(true);
  404. updateRef.setNewObjectId(ppid);
  405. Result update = updateRef.update();
  406. assertEquals(Result.FORCED, update);
  407. assertEquals(ppid, db.resolve("HEAD"));
  408. Ref ref = db.exactRef("HEAD");
  409. assertEquals("HEAD", ref.getName());
  410. assertTrue("is detached", !ref.isSymbolic());
  411. // the branch HEAD referred to is left untouched
  412. assertEquals(pid, db.resolve("refs/heads/master"));
  413. ReflogReader reflogReader = db.getReflogReader("HEAD");
  414. ReflogEntry e = reflogReader.getReverseEntries().get(0);
  415. assertEquals(pid, e.getOldId());
  416. assertEquals(ppid, e.getNewId());
  417. assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
  418. assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
  419. assertEquals(1250379778000L, e.getWho().getWhen().getTime());
  420. }
  421. /**
  422. * Update the HEAD ref when the referenced branch is unborn
  423. *
  424. * @throws Exception
  425. */
  426. @Test
  427. public void testUpdateRefDetachedUnbornHead() throws Exception {
  428. ObjectId ppid = db.resolve("refs/heads/master^");
  429. writeSymref("HEAD", "refs/heads/unborn");
  430. RefUpdate updateRef = db.updateRef("HEAD", true);
  431. updateRef.setForceUpdate(true);
  432. updateRef.setNewObjectId(ppid);
  433. Result update = updateRef.update();
  434. assertEquals(Result.NEW, update);
  435. assertEquals(ppid, db.resolve("HEAD"));
  436. Ref ref = db.exactRef("HEAD");
  437. assertEquals("HEAD", ref.getName());
  438. assertTrue("is detached", !ref.isSymbolic());
  439. // the branch HEAD referred to is left untouched
  440. assertNull(db.resolve("refs/heads/unborn"));
  441. ReflogReader reflogReader = db.getReflogReader("HEAD");
  442. ReflogEntry e = reflogReader.getReverseEntries().get(0);
  443. assertEquals(ObjectId.zeroId(), e.getOldId());
  444. assertEquals(ppid, e.getNewId());
  445. assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
  446. assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
  447. assertEquals(1250379778000L, e.getWho().getWhen().getTime());
  448. }
  449. /**
  450. * Delete a ref that exists both as packed and loose. Make sure the ref
  451. * cannot be resolved after delete.
  452. *
  453. * @throws IOException
  454. */
  455. @Test
  456. public void testDeleteLoosePacked() throws IOException {
  457. ObjectId pid = db.resolve("refs/heads/c^");
  458. RefUpdate updateRef = db.updateRef("refs/heads/c");
  459. updateRef.setNewObjectId(pid);
  460. updateRef.setForceUpdate(true);
  461. Result update = updateRef.update();
  462. assertEquals(Result.FORCED, update); // internal
  463. // The real test here
  464. RefUpdate updateRef2 = db.updateRef("refs/heads/c");
  465. updateRef2.setForceUpdate(true);
  466. Result delete = updateRef2.delete();
  467. assertEquals(Result.FORCED, delete);
  468. assertNull(db.resolve("refs/heads/c"));
  469. }
  470. /**
  471. * Try modify a ref to same
  472. *
  473. * @throws IOException
  474. */
  475. @Test
  476. public void testUpdateRefNoChange() throws IOException {
  477. ObjectId pid = db.resolve("refs/heads/master");
  478. RefUpdate updateRef = db.updateRef("refs/heads/master");
  479. updateRef.setNewObjectId(pid);
  480. Result update = updateRef.update();
  481. assertEquals(Result.NO_CHANGE, update);
  482. assertEquals(pid, db.resolve("refs/heads/master"));
  483. }
  484. /**
  485. * Test case originating from
  486. * <a href="http://bugs.eclipse.org/285991">bug 285991</a>
  487. *
  488. * Make sure the in memory cache is updated properly after
  489. * update of symref. This one did not fail because the
  490. * ref was packed due to implementation issues.
  491. *
  492. * @throws Exception
  493. */
  494. @Test
  495. public void testRefsCacheAfterUpdate() throws Exception {
  496. // Do not use the default repo for this case.
  497. List<Ref> allRefs = db.getRefDatabase().getRefs();
  498. ObjectId oldValue = db.resolve("HEAD");
  499. ObjectId newValue = db.resolve("HEAD^");
  500. // first make HEAD refer to loose ref
  501. RefUpdate updateRef = db.updateRef(Constants.HEAD);
  502. updateRef.setForceUpdate(true);
  503. updateRef.setNewObjectId(newValue);
  504. Result update = updateRef.update();
  505. assertEquals(Result.FORCED, update);
  506. // now update that ref
  507. updateRef = db.updateRef(Constants.HEAD);
  508. updateRef.setNewObjectId(oldValue);
  509. update = updateRef.update();
  510. assertEquals(Result.FAST_FORWARD, update);
  511. allRefs = db.getRefDatabase().getRefs();
  512. Ref master = getRef(allRefs, "refs/heads/master").get();
  513. Ref head = getRef(allRefs, "HEAD").get();
  514. assertEquals("refs/heads/master", master.getName());
  515. assertEquals("HEAD", head.getName());
  516. assertTrue("is symbolic reference", head.isSymbolic());
  517. assertSame(master, head.getTarget());
  518. }
  519. /**
  520. * Test case originating from
  521. * <a href="http://bugs.eclipse.org/285991">bug 285991</a>
  522. *
  523. * Make sure the in memory cache is updated properly after
  524. * update of symref.
  525. *
  526. * @throws Exception
  527. */
  528. @Test
  529. public void testRefsCacheAfterUpdateLooseOnly() throws Exception {
  530. // Do not use the default repo for this case.
  531. List<Ref> allRefs = db.getRefDatabase().getRefs();
  532. ObjectId oldValue = db.resolve("HEAD");
  533. writeSymref(Constants.HEAD, "refs/heads/newref");
  534. RefUpdate updateRef = db.updateRef(Constants.HEAD);
  535. updateRef.setForceUpdate(true);
  536. updateRef.setNewObjectId(oldValue);
  537. Result update = updateRef.update();
  538. assertEquals(Result.NEW, update);
  539. allRefs = db.getRefDatabase().getRefs();
  540. Ref head = getRef(allRefs, "HEAD").get();
  541. Ref newref = getRef(allRefs, "refs/heads/newref").get();
  542. assertEquals("refs/heads/newref", newref.getName());
  543. assertEquals("HEAD", head.getName());
  544. assertTrue("is symbolic reference", head.isSymbolic());
  545. assertSame(newref, head.getTarget());
  546. }
  547. /**
  548. * Try modify a ref, but get wrong expected old value
  549. *
  550. * @throws IOException
  551. */
  552. @Test
  553. public void testUpdateRefLockFailureWrongOldValue() throws IOException {
  554. ObjectId pid = db.resolve("refs/heads/master");
  555. RefUpdate updateRef = db.updateRef("refs/heads/master");
  556. updateRef.setNewObjectId(pid);
  557. updateRef.setExpectedOldObjectId(db.resolve("refs/heads/master^"));
  558. Result update = updateRef.update();
  559. assertEquals(Result.LOCK_FAILURE, update);
  560. assertEquals(pid, db.resolve("refs/heads/master"));
  561. }
  562. /**
  563. * Try modify a ref forward, fast forward, checking old value first
  564. *
  565. * @throws IOException
  566. */
  567. @Test
  568. public void testUpdateRefForwardWithCheck1() throws IOException {
  569. ObjectId ppid = db.resolve("refs/heads/master^");
  570. ObjectId pid = db.resolve("refs/heads/master");
  571. RefUpdate updateRef = db.updateRef("refs/heads/master");
  572. updateRef.setNewObjectId(ppid);
  573. updateRef.setForceUpdate(true);
  574. Result update = updateRef.update();
  575. assertEquals(Result.FORCED, update);
  576. assertEquals(ppid, db.resolve("refs/heads/master"));
  577. // real test
  578. RefUpdate updateRef2 = db.updateRef("refs/heads/master");
  579. updateRef2.setExpectedOldObjectId(ppid);
  580. updateRef2.setNewObjectId(pid);
  581. Result update2 = updateRef2.update();
  582. assertEquals(Result.FAST_FORWARD, update2);
  583. assertEquals(pid, db.resolve("refs/heads/master"));
  584. }
  585. /**
  586. * Try modify a ref forward, fast forward, checking old commit first
  587. *
  588. * @throws IOException
  589. */
  590. @Test
  591. public void testUpdateRefForwardWithCheck2() throws IOException {
  592. ObjectId ppid = db.resolve("refs/heads/master^");
  593. ObjectId pid = db.resolve("refs/heads/master");
  594. RefUpdate updateRef = db.updateRef("refs/heads/master");
  595. updateRef.setNewObjectId(ppid);
  596. updateRef.setForceUpdate(true);
  597. Result update = updateRef.update();
  598. assertEquals(Result.FORCED, update);
  599. assertEquals(ppid, db.resolve("refs/heads/master"));
  600. // real test
  601. try (RevWalk rw = new RevWalk(db)) {
  602. RevCommit old = rw.parseCommit(ppid);
  603. RefUpdate updateRef2 = db.updateRef("refs/heads/master");
  604. updateRef2.setExpectedOldObjectId(old);
  605. updateRef2.setNewObjectId(pid);
  606. Result update2 = updateRef2.update();
  607. assertEquals(Result.FAST_FORWARD, update2);
  608. assertEquals(pid, db.resolve("refs/heads/master"));
  609. }
  610. }
  611. /**
  612. * Try modify a ref that is locked
  613. *
  614. * @throws IOException
  615. */
  616. @Test
  617. public void testUpdateRefLockFailureLocked() throws IOException {
  618. ObjectId opid = db.resolve("refs/heads/master");
  619. ObjectId pid = db.resolve("refs/heads/master^");
  620. RefUpdate updateRef = db.updateRef("refs/heads/master");
  621. updateRef.setNewObjectId(pid);
  622. LockFile lockFile1 = new LockFile(new File(db.getDirectory(),
  623. "refs/heads/master"));
  624. try {
  625. assertTrue(lockFile1.lock()); // precondition to test
  626. Result update = updateRef.update();
  627. assertEquals(Result.LOCK_FAILURE, update);
  628. assertEquals(opid, db.resolve("refs/heads/master"));
  629. LockFile lockFile2 = new LockFile(new File(db.getDirectory(),"refs/heads/master"));
  630. assertFalse(lockFile2.lock()); // was locked, still is
  631. } finally {
  632. lockFile1.unlock();
  633. }
  634. }
  635. /**
  636. * Try to delete a ref. Delete requires force.
  637. *
  638. * @throws IOException
  639. */
  640. @Test
  641. public void testDeleteLoosePackedRejected() throws IOException {
  642. ObjectId pid = db.resolve("refs/heads/c^");
  643. ObjectId oldpid = db.resolve("refs/heads/c");
  644. RefUpdate updateRef = db.updateRef("refs/heads/c");
  645. updateRef.setNewObjectId(pid);
  646. Result update = updateRef.update();
  647. assertEquals(Result.REJECTED, update);
  648. assertEquals(oldpid, db.resolve("refs/heads/c"));
  649. }
  650. @Test
  651. public void testRenameBranchNoPreviousLog() throws IOException {
  652. assertFalse("precondition, no log on old branchg", new File(db
  653. .getDirectory(), "logs/refs/heads/b").exists());
  654. ObjectId rb = db.resolve("refs/heads/b");
  655. ObjectId oldHead = db.resolve(Constants.HEAD);
  656. assertFalse(rb.equals(oldHead)); // assumption for this test
  657. RefRename renameRef = db.renameRef("refs/heads/b",
  658. "refs/heads/new/name");
  659. Result result = renameRef.rename();
  660. assertEquals(Result.RENAMED, result);
  661. assertEquals(rb, db.resolve("refs/heads/new/name"));
  662. assertNull(db.resolve("refs/heads/b"));
  663. assertEquals(1, db.getReflogReader("new/name").getReverseEntries().size());
  664. assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name")
  665. .getLastEntry().getComment());
  666. assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
  667. assertEquals(oldHead, db.resolve(Constants.HEAD)); // unchanged
  668. }
  669. @Test
  670. public void testRenameBranchHasPreviousLog() throws IOException {
  671. ObjectId rb = db.resolve("refs/heads/b");
  672. ObjectId oldHead = db.resolve(Constants.HEAD);
  673. assertFalse("precondition for this test, branch b != HEAD", rb
  674. .equals(oldHead));
  675. writeReflog(db, rb, "Just a message", "refs/heads/b");
  676. assertTrue("log on old branch", new File(db.getDirectory(),
  677. "logs/refs/heads/b").exists());
  678. RefRename renameRef = db.renameRef("refs/heads/b",
  679. "refs/heads/new/name");
  680. Result result = renameRef.rename();
  681. assertEquals(Result.RENAMED, result);
  682. assertEquals(rb, db.resolve("refs/heads/new/name"));
  683. assertNull(db.resolve("refs/heads/b"));
  684. assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size());
  685. assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name")
  686. .getLastEntry().getComment());
  687. assertEquals("Just a message", db.getReflogReader("new/name")
  688. .getReverseEntries().get(1).getComment());
  689. assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
  690. assertEquals(oldHead, db.resolve(Constants.HEAD)); // unchanged
  691. }
  692. @Test
  693. public void testRenameCurrentBranch() throws IOException {
  694. ObjectId rb = db.resolve("refs/heads/b");
  695. writeSymref(Constants.HEAD, "refs/heads/b");
  696. ObjectId oldHead = db.resolve(Constants.HEAD);
  697. assertEquals("internal test condition, b == HEAD", oldHead, rb);
  698. writeReflog(db, rb, "Just a message", "refs/heads/b");
  699. assertTrue("log on old branch", new File(db.getDirectory(),
  700. "logs/refs/heads/b").exists());
  701. RefRename renameRef = db.renameRef("refs/heads/b",
  702. "refs/heads/new/name");
  703. Result result = renameRef.rename();
  704. assertEquals(Result.RENAMED, result);
  705. assertEquals(rb, db.resolve("refs/heads/new/name"));
  706. assertNull(db.resolve("refs/heads/b"));
  707. assertEquals("Branch: renamed b to new/name", db.getReflogReader(
  708. "new/name").getLastEntry().getComment());
  709. assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
  710. assertEquals(rb, db.resolve(Constants.HEAD));
  711. assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size());
  712. assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name").getReverseEntries().get(0).getComment());
  713. assertEquals("Just a message", db.getReflogReader("new/name").getReverseEntries().get(1).getComment());
  714. }
  715. @Test
  716. public void testRenameBranchAlsoInPack() throws IOException {
  717. ObjectId rb = db.resolve("refs/heads/b");
  718. ObjectId rb2 = db.resolve("refs/heads/b~1");
  719. assertEquals(Ref.Storage.PACKED, db.exactRef("refs/heads/b").getStorage());
  720. RefUpdate updateRef = db.updateRef("refs/heads/b");
  721. updateRef.setNewObjectId(rb2);
  722. updateRef.setForceUpdate(true);
  723. Result update = updateRef.update();
  724. assertEquals("internal check new ref is loose", Result.FORCED, update);
  725. assertEquals(Ref.Storage.LOOSE, db.exactRef("refs/heads/b").getStorage());
  726. writeReflog(db, rb, "Just a message", "refs/heads/b");
  727. assertTrue("log on old branch", new File(db.getDirectory(),
  728. "logs/refs/heads/b").exists());
  729. RefRename renameRef = db.renameRef("refs/heads/b",
  730. "refs/heads/new/name");
  731. Result result = renameRef.rename();
  732. assertEquals(Result.RENAMED, result);
  733. assertEquals(rb2, db.resolve("refs/heads/new/name"));
  734. assertNull(db.resolve("refs/heads/b"));
  735. assertEquals("Branch: renamed b to new/name", db.getReflogReader(
  736. "new/name").getLastEntry().getComment());
  737. assertEquals(3, db.getReflogReader("refs/heads/new/name").getReverseEntries().size());
  738. assertEquals("Branch: renamed b to new/name", db.getReflogReader("refs/heads/new/name").getReverseEntries().get(0).getComment());
  739. assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
  740. // make sure b's log file is gone too.
  741. assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
  742. // Create new Repository instance, to reread caches and make sure our
  743. // assumptions are persistent.
  744. try (Repository ndb = new FileRepository(db.getDirectory())) {
  745. assertEquals(rb2, ndb.resolve("refs/heads/new/name"));
  746. assertNull(ndb.resolve("refs/heads/b"));
  747. }
  748. }
  749. public void tryRenameWhenLocked(String toLock, String fromName,
  750. String toName, String headPointsTo) throws IOException {
  751. // setup
  752. writeSymref(Constants.HEAD, headPointsTo);
  753. ObjectId oldfromId = db.resolve(fromName);
  754. ObjectId oldHeadId = db.resolve(Constants.HEAD);
  755. writeReflog(db, oldfromId, "Just a message", fromName);
  756. List<ReflogEntry> oldFromLog = db
  757. .getReflogReader(fromName).getReverseEntries();
  758. List<ReflogEntry> oldHeadLog = oldHeadId != null ? db
  759. .getReflogReader(Constants.HEAD).getReverseEntries() : null;
  760. assertTrue("internal check, we have a log", new File(db.getDirectory(),
  761. "logs/" + fromName).exists());
  762. // "someone" has branch X locked
  763. LockFile lockFile = new LockFile(new File(db.getDirectory(), toLock));
  764. try {
  765. assertTrue(lockFile.lock());
  766. // Now this is our test
  767. RefRename renameRef = db.renameRef(fromName, toName);
  768. Result result = renameRef.rename();
  769. assertEquals(Result.LOCK_FAILURE, result);
  770. // Check that the involved refs are the same despite the failure
  771. assertExists(false, toName);
  772. if (!toLock.equals(toName))
  773. assertExists(false, toName + LOCK_SUFFIX);
  774. assertExists(true, toLock + LOCK_SUFFIX);
  775. if (!toLock.equals(fromName))
  776. assertExists(false, "logs/" + fromName + LOCK_SUFFIX);
  777. assertExists(false, "logs/" + toName + LOCK_SUFFIX);
  778. assertEquals(oldHeadId, db.resolve(Constants.HEAD));
  779. assertEquals(oldfromId, db.resolve(fromName));
  780. assertNull(db.resolve(toName));
  781. assertEquals(oldFromLog.toString(), db.getReflogReader(fromName)
  782. .getReverseEntries().toString());
  783. if (oldHeadId != null && oldHeadLog != null)
  784. assertEquals(oldHeadLog.toString(), db.getReflogReader(
  785. Constants.HEAD).getReverseEntries().toString());
  786. } finally {
  787. lockFile.unlock();
  788. }
  789. }
  790. private void assertExists(boolean positive, String toName) {
  791. assertEquals(toName + (positive ? " " : " does not ") + "exist",
  792. positive, new File(db.getDirectory(), toName).exists());
  793. }
  794. @Test
  795. public void testRenameBranchCannotLockAFileHEADisFromLockHEAD()
  796. throws IOException {
  797. tryRenameWhenLocked("HEAD", "refs/heads/b", "refs/heads/new/name",
  798. "refs/heads/b");
  799. }
  800. @Test
  801. public void testRenameBranchCannotLockAFileHEADisFromLockFrom()
  802. throws IOException {
  803. tryRenameWhenLocked("refs/heads/b", "refs/heads/b",
  804. "refs/heads/new/name", "refs/heads/b");
  805. }
  806. @Test
  807. public void testRenameBranchCannotLockAFileHEADisFromLockTo()
  808. throws IOException {
  809. tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b",
  810. "refs/heads/new/name", "refs/heads/b");
  811. }
  812. @Test
  813. public void testRenameBranchCannotLockAFileHEADisToLockFrom()
  814. throws IOException {
  815. tryRenameWhenLocked("refs/heads/b", "refs/heads/b",
  816. "refs/heads/new/name", "refs/heads/new/name");
  817. }
  818. @Test
  819. public void testRenameBranchCannotLockAFileHEADisToLockTo()
  820. throws IOException {
  821. tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b",
  822. "refs/heads/new/name", "refs/heads/new/name");
  823. }
  824. @Test
  825. public void testRenameBranchCannotLockAFileHEADisOtherLockFrom()
  826. throws IOException {
  827. tryRenameWhenLocked("refs/heads/b", "refs/heads/b",
  828. "refs/heads/new/name", "refs/heads/a");
  829. }
  830. @Test
  831. public void testRenameBranchCannotLockAFileHEADisOtherLockTo()
  832. throws IOException {
  833. tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b",
  834. "refs/heads/new/name", "refs/heads/a");
  835. }
  836. @Test
  837. public void testUpdateChecksOldValue() throws Exception {
  838. ObjectId cur = db.resolve("master");
  839. ObjectId prev = db.resolve("master^");
  840. RefUpdate u1 = db.updateRef("refs/heads/master");
  841. RefUpdate u2 = db.updateRef("refs/heads/master");
  842. u1.setExpectedOldObjectId(cur);
  843. u1.setNewObjectId(prev);
  844. u1.setForceUpdate(true);
  845. u2.setExpectedOldObjectId(cur);
  846. u2.setNewObjectId(prev);
  847. u2.setForceUpdate(true);
  848. assertEquals(FORCED, u1.update());
  849. assertEquals(LOCK_FAILURE, u2.update());
  850. }
  851. @Test
  852. public void testRenameAtomic() throws IOException {
  853. ObjectId prevId = db.resolve("refs/heads/master^");
  854. RefRename rename = db.renameRef("refs/heads/master", "refs/heads/newmaster");
  855. RefUpdate updateRef = db.updateRef("refs/heads/master");
  856. updateRef.setNewObjectId(prevId);
  857. updateRef.setForceUpdate(true);
  858. assertEquals(FORCED, updateRef.update());
  859. assertEquals(RefUpdate.Result.LOCK_FAILURE, rename.rename());
  860. }
  861. @Test
  862. public void testRenameSymref() throws IOException {
  863. db.resolve("HEAD");
  864. RefRename r = db.renameRef("HEAD", "KOPF");
  865. assertEquals(IO_FAILURE, r.rename());
  866. }
  867. @Test
  868. public void testRenameRefNameColission1avoided() throws IOException {
  869. // setup
  870. ObjectId rb = db.resolve("refs/heads/b");
  871. writeSymref(Constants.HEAD, "refs/heads/a");
  872. RefUpdate updateRef = db.updateRef("refs/heads/a");
  873. updateRef.setNewObjectId(rb);
  874. updateRef.setRefLogMessage("Setup", false);
  875. assertEquals(Result.FAST_FORWARD, updateRef.update());
  876. ObjectId oldHead = db.resolve(Constants.HEAD);
  877. assertEquals(oldHead, rb); // assumption for this test
  878. writeReflog(db, rb, "Just a message", "refs/heads/a");
  879. assertTrue("internal check, we have a log", new File(db.getDirectory(),
  880. "logs/refs/heads/a").exists());
  881. // Now this is our test
  882. RefRename renameRef = db.renameRef("refs/heads/a", "refs/heads/a/b");
  883. Result result = renameRef.rename();
  884. assertEquals(Result.RENAMED, result);
  885. assertNull(db.resolve("refs/heads/a"));
  886. assertEquals(rb, db.resolve("refs/heads/a/b"));
  887. assertEquals(3, db.getReflogReader("a/b").getReverseEntries().size());
  888. assertEquals("Branch: renamed a to a/b", db.getReflogReader("a/b")
  889. .getReverseEntries().get(0).getComment());
  890. assertEquals("Just a message", db.getReflogReader("a/b")
  891. .getReverseEntries().get(1).getComment());
  892. assertEquals("Setup", db.getReflogReader("a/b").getReverseEntries()
  893. .get(2).getComment());
  894. // same thing was logged to HEAD
  895. assertEquals("Branch: renamed a to a/b", db.getReflogReader("HEAD")
  896. .getReverseEntries().get(0).getComment());
  897. }
  898. @Test
  899. public void testRenameRefNameColission2avoided() throws IOException {
  900. // setup
  901. ObjectId rb = db.resolve("refs/heads/b");
  902. writeSymref(Constants.HEAD, "refs/heads/prefix/a");
  903. RefUpdate updateRef = db.updateRef("refs/heads/prefix/a");
  904. updateRef.setNewObjectId(rb);
  905. updateRef.setRefLogMessage("Setup", false);
  906. updateRef.setForceUpdate(true);
  907. assertEquals(Result.FORCED, updateRef.update());
  908. ObjectId oldHead = db.resolve(Constants.HEAD);
  909. assertEquals(oldHead, rb); // assumption for this test
  910. writeReflog(db, rb, "Just a message", "refs/heads/prefix/a");
  911. assertTrue("internal check, we have a log", new File(db.getDirectory(),
  912. "logs/refs/heads/prefix/a").exists());
  913. // Now this is our test
  914. RefRename renameRef = db.renameRef("refs/heads/prefix/a",
  915. "refs/heads/prefix");
  916. Result result = renameRef.rename();
  917. assertEquals(Result.RENAMED, result);
  918. assertNull(db.resolve("refs/heads/prefix/a"));
  919. assertEquals(rb, db.resolve("refs/heads/prefix"));
  920. assertEquals(3, db.getReflogReader("prefix").getReverseEntries().size());
  921. assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader(
  922. "prefix").getReverseEntries().get(0).getComment());
  923. assertEquals("Just a message", db.getReflogReader("prefix")
  924. .getReverseEntries().get(1).getComment());
  925. assertEquals("Setup", db.getReflogReader("prefix").getReverseEntries()
  926. .get(2).getComment());
  927. assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader(
  928. "HEAD").getReverseEntries().get(0).getComment());
  929. }
  930. @Test
  931. public void testCreateMissingObject() throws IOException {
  932. String name = "refs/heads/abc";
  933. ObjectId bad =
  934. ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
  935. RefUpdate ru = db.updateRef(name);
  936. ru.setNewObjectId(bad);
  937. Result update = ru.update();
  938. assertEquals(Result.REJECTED_MISSING_OBJECT, update);
  939. Ref ref = db.exactRef(name);
  940. assertNull(ref);
  941. }
  942. @Test
  943. public void testUpdateMissingObject() throws IOException {
  944. String name = "refs/heads/abc";
  945. RefUpdate ru = updateRef(name);
  946. Result update = ru.update();
  947. assertEquals(Result.NEW, update);
  948. ObjectId oldId = ru.getNewObjectId();
  949. ObjectId bad =
  950. ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
  951. ru = db.updateRef(name);
  952. ru.setNewObjectId(bad);
  953. update = ru.update();
  954. assertEquals(Result.REJECTED_MISSING_OBJECT, update);
  955. Ref ref = db.exactRef(name);
  956. assertNotNull(ref);
  957. assertEquals(oldId, ref.getObjectId());
  958. }
  959. @Test
  960. public void testForceUpdateMissingObject() throws IOException {
  961. String name = "refs/heads/abc";
  962. RefUpdate ru = updateRef(name);
  963. Result update = ru.update();
  964. assertEquals(Result.NEW, update);
  965. ObjectId oldId = ru.getNewObjectId();
  966. ObjectId bad =
  967. ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
  968. ru = db.updateRef(name);
  969. ru.setNewObjectId(bad);
  970. update = ru.forceUpdate();
  971. assertEquals(Result.REJECTED_MISSING_OBJECT, update);
  972. Ref ref = db.exactRef(name);
  973. assertNotNull(ref);
  974. assertEquals(oldId, ref.getObjectId());
  975. }
  976. private static void writeReflog(Repository db, ObjectId newId, String msg,
  977. String refName) throws IOException {
  978. RefDirectory refs = (RefDirectory) db.getRefDatabase();
  979. RefDirectoryUpdate update = refs.newUpdate(refName, true);
  980. update.setNewObjectId(newId);
  981. refs.log(false, update, msg, true);
  982. }
  983. private static class SubclassedId extends ObjectId {
  984. SubclassedId(AnyObjectId src) {
  985. super(src);
  986. }
  987. }
  988. }