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 37KB

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