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.

FileReftableTest.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /*
  2. * Copyright (C) 2019, Google Inc.
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.internal.storage.file;
  44. import static org.eclipse.jgit.lib.RefUpdate.Result.FAST_FORWARD;
  45. import static org.eclipse.jgit.lib.RefUpdate.Result.FORCED;
  46. import static org.eclipse.jgit.lib.RefUpdate.Result.IO_FAILURE;
  47. import static org.eclipse.jgit.lib.RefUpdate.Result.LOCK_FAILURE;
  48. import static org.junit.Assert.assertEquals;
  49. import static org.junit.Assert.assertFalse;
  50. import static org.junit.Assert.assertNotEquals;
  51. import static org.junit.Assert.assertNotNull;
  52. import static org.junit.Assert.assertNotSame;
  53. import static org.junit.Assert.assertNull;
  54. import static org.junit.Assert.assertSame;
  55. import static org.junit.Assert.assertTrue;
  56. import static org.junit.Assert.fail;
  57. import java.io.File;
  58. import java.io.IOException;
  59. import java.security.SecureRandom;
  60. import java.util.ArrayList;
  61. import java.util.List;
  62. import org.eclipse.jgit.lib.AnyObjectId;
  63. import org.eclipse.jgit.lib.Constants;
  64. import org.eclipse.jgit.lib.NullProgressMonitor;
  65. import org.eclipse.jgit.lib.ObjectId;
  66. import org.eclipse.jgit.lib.PersonIdent;
  67. import org.eclipse.jgit.lib.Ref;
  68. import org.eclipse.jgit.lib.RefRename;
  69. import org.eclipse.jgit.lib.RefUpdate;
  70. import org.eclipse.jgit.lib.RefUpdate.Result;
  71. import org.eclipse.jgit.lib.ReflogEntry;
  72. import org.eclipse.jgit.lib.ReflogReader;
  73. import org.eclipse.jgit.lib.RepositoryCache;
  74. import org.eclipse.jgit.revwalk.RevWalk;
  75. import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
  76. import org.eclipse.jgit.transport.ReceiveCommand;
  77. import org.junit.Test;
  78. public class FileReftableTest extends SampleDataRepositoryTestCase {
  79. String bCommit;
  80. @Override
  81. public void setUp() throws Exception {
  82. super.setUp();
  83. Ref b = db.exactRef("refs/heads/b");
  84. bCommit = b.getObjectId().getName();
  85. db.convertToReftable(false, false);
  86. }
  87. @SuppressWarnings("boxing")
  88. @Test
  89. public void testRacyReload() throws Exception {
  90. ObjectId id = db.resolve("master");
  91. int retry = 0;
  92. try (FileRepository repo1 = new FileRepository(db.getDirectory());
  93. FileRepository repo2 = new FileRepository(db.getDirectory())) {
  94. FileRepository repos[] = { repo1, repo2 };
  95. for (int i = 0; i < 10; i++) {
  96. for (int j = 0; j < 2; j++) {
  97. FileRepository repo = repos[j];
  98. RefUpdate u = repo.getRefDatabase().newUpdate(
  99. String.format("branch%d", i * 10 + j), false);
  100. u.setNewObjectId(id);
  101. RefUpdate.Result r = u.update();
  102. if (!r.equals(Result.NEW)) {
  103. retry++;
  104. u = repo.getRefDatabase().newUpdate(
  105. String.format("branch%d", i * 10 + j), false);
  106. u.setNewObjectId(id);
  107. r = u.update();
  108. assertEquals(r, Result.NEW);
  109. }
  110. }
  111. }
  112. // only the first one succeeds
  113. assertEquals(retry, 19);
  114. }
  115. }
  116. @Test
  117. public void testCompactFully() throws Exception {
  118. ObjectId c1 = db.resolve("master^^");
  119. ObjectId c2 = db.resolve("master^");
  120. for (int i = 0; i < 5; i++) {
  121. RefUpdate u = db.updateRef("refs/heads/master");
  122. u.setForceUpdate(true);
  123. u.setNewObjectId((i%2) == 0 ? c1 : c2);
  124. assertEquals(u.update(), FORCED);
  125. }
  126. File tableDir = new File(db.getDirectory(), Constants.REFTABLE);
  127. assertTrue(tableDir.listFiles().length > 2);
  128. ((FileReftableDatabase)db.getRefDatabase()).compactFully();
  129. assertEquals(tableDir.listFiles().length,2);
  130. }
  131. @Test
  132. public void testOpenConvert() throws Exception {
  133. try (FileRepository repo = new FileRepository(db.getDirectory())) {
  134. assertTrue(repo.getRefDatabase() instanceof FileReftableDatabase);
  135. }
  136. }
  137. @Test
  138. public void testConvert() throws Exception {
  139. Ref h = db.exactRef("HEAD");
  140. assertTrue(h.isSymbolic());
  141. assertEquals("refs/heads/master", h.getTarget().getName());
  142. Ref b = db.exactRef("refs/heads/b");
  143. assertFalse(b.isSymbolic());
  144. assertTrue(b.isPeeled());
  145. assertEquals(bCommit, b.getObjectId().name());
  146. assertTrue(db.getRefDatabase().hasFastTipsWithSha1());
  147. }
  148. @Test
  149. public void testConvertToRefdir() throws Exception {
  150. db.convertToPackedRefs(false, false);
  151. assertTrue(db.getRefDatabase() instanceof RefDirectory);
  152. Ref h = db.exactRef("HEAD");
  153. assertTrue(h.isSymbolic());
  154. assertEquals("refs/heads/master", h.getTarget().getName());
  155. Ref b = db.exactRef("refs/heads/b");
  156. assertFalse(b.isSymbolic());
  157. assertTrue(b.isPeeled());
  158. assertEquals(bCommit, b.getObjectId().name());
  159. assertFalse(db.getRefDatabase().hasFastTipsWithSha1());
  160. }
  161. @Test
  162. public void testConvertToRefdirReflog() throws Exception {
  163. Ref a = db.exactRef("refs/heads/a");
  164. String aCommit = a.getObjectId().getName();
  165. RefUpdate u = db.updateRef("refs/heads/master");
  166. u.setForceUpdate(true);
  167. u.setNewObjectId(ObjectId.fromString(aCommit));
  168. u.setForceRefLog(true);
  169. u.setRefLogMessage("apple", false);
  170. u.update();
  171. RefUpdate v = db.updateRef("refs/heads/master");
  172. v.setForceUpdate(true);
  173. v.setNewObjectId(ObjectId.fromString(bCommit));
  174. v.setForceRefLog(true);
  175. v.setRefLogMessage("banana", false);
  176. v.update();
  177. db.convertToPackedRefs(true, false);
  178. List<ReflogEntry> logs = db.getReflogReader("refs/heads/master").getReverseEntries(2);
  179. assertEquals(logs.get(0).getComment(), "banana");
  180. assertEquals(logs.get(1).getComment(), "apple");
  181. }
  182. @Test
  183. public void testBatchrefUpdate() throws Exception {
  184. ObjectId cur = db.resolve("master");
  185. ObjectId prev = db.resolve("master^");
  186. PersonIdent person = new PersonIdent("name", "mail@example.com");
  187. ReceiveCommand rc1 = new ReceiveCommand(ObjectId.zeroId(), cur, "refs/heads/batch1");
  188. ReceiveCommand rc2 = new ReceiveCommand(ObjectId.zeroId(), prev, "refs/heads/batch2");
  189. String msg = "message";
  190. try (RevWalk rw = new RevWalk(db)) {
  191. db.getRefDatabase().newBatchUpdate()
  192. .addCommand(rc1, rc2)
  193. .setAtomic(true)
  194. .setRefLogIdent(person)
  195. .setRefLogMessage(msg, false)
  196. .execute(rw, NullProgressMonitor.INSTANCE);
  197. }
  198. assertEquals(rc1.getResult(), ReceiveCommand.Result.OK);
  199. assertEquals(rc2.getResult(), ReceiveCommand.Result.OK);
  200. ReflogEntry e = db.getReflogReader("refs/heads/batch1").getLastEntry();
  201. assertEquals(msg, e.getComment());
  202. assertEquals(person, e.getWho());
  203. assertEquals(cur, e.getNewId());
  204. e = db.getReflogReader("refs/heads/batch2").getLastEntry();
  205. assertEquals(msg, e.getComment());
  206. assertEquals(person, e.getWho());
  207. assertEquals(prev, e.getNewId());
  208. assertEquals(cur, db.exactRef("refs/heads/batch1").getObjectId());
  209. assertEquals(prev, db.exactRef("refs/heads/batch2").getObjectId());
  210. }
  211. @Test
  212. public void testFastforwardStatus() throws Exception {
  213. ObjectId cur = db.resolve("master");
  214. ObjectId prev = db.resolve("master^");
  215. RefUpdate u = db.updateRef("refs/heads/master");
  216. u.setNewObjectId(prev);
  217. u.setForceUpdate(true);
  218. assertEquals(FORCED, u.update());
  219. RefUpdate u2 = db.updateRef("refs/heads/master");
  220. u2.setNewObjectId(cur);
  221. assertEquals(FAST_FORWARD, u2.update());
  222. }
  223. @Test
  224. public void testUpdateChecksOldValue() throws Exception {
  225. ObjectId cur = db.resolve("master");
  226. ObjectId prev = db.resolve("master^");
  227. RefUpdate u1 = db.updateRef("refs/heads/master");
  228. RefUpdate u2 = db.updateRef("refs/heads/master");
  229. u1.setExpectedOldObjectId(cur);
  230. u1.setNewObjectId(prev);
  231. u1.setForceUpdate(true);
  232. u2.setExpectedOldObjectId(cur);
  233. u2.setNewObjectId(prev);
  234. u2.setForceUpdate(true);
  235. assertEquals(FORCED, u1.update());
  236. assertEquals(LOCK_FAILURE, u2.update());
  237. }
  238. @Test
  239. public void testWritesymref() throws Exception {
  240. writeSymref(Constants.HEAD, "refs/heads/a");
  241. assertNotNull(db.exactRef("refs/heads/b"));
  242. }
  243. @Test
  244. public void testFastforwardStatus2() throws Exception {
  245. writeSymref(Constants.HEAD, "refs/heads/a");
  246. ObjectId bId = db.exactRef("refs/heads/b").getObjectId();
  247. RefUpdate u = db.updateRef("refs/heads/a");
  248. u.setNewObjectId(bId);
  249. u.setRefLogMessage("Setup", false);
  250. assertEquals(FAST_FORWARD, u.update());
  251. }
  252. @Test
  253. public void testDelete() throws Exception {
  254. RefUpdate up = db.getRefDatabase().newUpdate("refs/heads/a", false);
  255. up.setForceUpdate(true);
  256. RefUpdate.Result res = up.delete();
  257. assertEquals(res, FORCED);
  258. assertNull(db.exactRef("refs/heads/a"));
  259. }
  260. @Test
  261. public void testDeleteWithoutHead() throws IOException {
  262. // Prepare repository without HEAD
  263. RefUpdate refUpdate = db.updateRef(Constants.HEAD, true);
  264. refUpdate.setForceUpdate(true);
  265. refUpdate.setNewObjectId(ObjectId.zeroId());
  266. RefUpdate.Result updateResult = refUpdate.update();
  267. assertEquals(FORCED, updateResult);
  268. Ref r = db.exactRef("HEAD");
  269. assertEquals(ObjectId.zeroId(), r.getObjectId());
  270. RefUpdate.Result deleteHeadResult = db.updateRef(Constants.HEAD)
  271. .delete();
  272. // why does doDelete say NEW ?
  273. assertEquals(RefUpdate.Result.NO_CHANGE, deleteHeadResult);
  274. // Any result is ok as long as it's not an NPE
  275. db.updateRef(Constants.R_HEADS + "master").delete();
  276. }
  277. @Test
  278. public void testUpdateRefDetached() throws Exception {
  279. ObjectId pid = db.resolve("refs/heads/master");
  280. ObjectId ppid = db.resolve("refs/heads/master^");
  281. RefUpdate updateRef = db.updateRef("HEAD", true);
  282. updateRef.setForceUpdate(true);
  283. updateRef.setNewObjectId(ppid);
  284. RefUpdate.Result update = updateRef.update();
  285. assertEquals(FORCED, update);
  286. assertEquals(ppid, db.resolve("HEAD"));
  287. Ref ref = db.exactRef("HEAD");
  288. assertEquals("HEAD", ref.getName());
  289. assertTrue("is detached", !ref.isSymbolic());
  290. // the branch HEAD referred to is left untouched
  291. assertEquals(pid, db.resolve("refs/heads/master"));
  292. ReflogReader reflogReader = db.getReflogReader("HEAD");
  293. ReflogEntry e = reflogReader.getReverseEntries().get(0);
  294. assertEquals(ppid, e.getNewId());
  295. assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
  296. assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
  297. assertEquals(1250379778000L, e.getWho().getWhen().getTime());
  298. assertEquals(pid, e.getOldId());
  299. }
  300. @Test
  301. public void testWriteReflog() throws Exception {
  302. ObjectId pid = db.resolve("refs/heads/master^");
  303. RefUpdate updateRef = db.updateRef("refs/heads/master");
  304. updateRef.setNewObjectId(pid);
  305. String msg = "REFLOG!";
  306. updateRef.setRefLogMessage(msg, true);
  307. PersonIdent person = new PersonIdent("name", "mail@example.com");
  308. updateRef.setRefLogIdent(person);
  309. updateRef.setForceUpdate(true);
  310. RefUpdate.Result update = updateRef.update();
  311. assertEquals(FORCED, update); // internal
  312. ReflogReader r = db.getReflogReader("refs/heads/master");
  313. ReflogEntry e = r.getLastEntry();
  314. assertEquals(e.getNewId(), pid);
  315. assertEquals(e.getComment(), "REFLOG!: FORCED");
  316. assertEquals(e.getWho(), person);
  317. }
  318. @Test
  319. public void testLooseDelete() throws IOException {
  320. final String newRef = "refs/heads/abc";
  321. assertNull(db.exactRef(newRef));
  322. RefUpdate ref = db.updateRef(newRef);
  323. ObjectId nonZero = db.resolve(Constants.HEAD);
  324. assertNotEquals(nonZero, ObjectId.zeroId());
  325. ref.setNewObjectId(nonZero);
  326. assertEquals(RefUpdate.Result.NEW, ref.update());
  327. ref = db.updateRef(newRef);
  328. ref.setNewObjectId(db.resolve(Constants.HEAD));
  329. assertEquals(ref.delete(), RefUpdate.Result.NO_CHANGE);
  330. // Differs from RefupdateTest. Deleting a loose ref leaves reflog trail.
  331. ReflogReader reader = db.getReflogReader("refs/heads/abc");
  332. assertEquals(ObjectId.zeroId(), reader.getReverseEntry(1).getOldId());
  333. assertEquals(nonZero, reader.getReverseEntry(1).getNewId());
  334. assertEquals(nonZero, reader.getReverseEntry(0).getOldId());
  335. assertEquals(ObjectId.zeroId(), reader.getReverseEntry(0).getNewId());
  336. }
  337. private static class SubclassedId extends ObjectId {
  338. SubclassedId(AnyObjectId src) {
  339. super(src);
  340. }
  341. }
  342. @Test
  343. public void testNoCacheObjectIdSubclass() throws IOException {
  344. final String newRef = "refs/heads/abc";
  345. final RefUpdate ru = updateRef(newRef);
  346. final SubclassedId newid = new SubclassedId(ru.getNewObjectId());
  347. ru.setNewObjectId(newid);
  348. RefUpdate.Result update = ru.update();
  349. assertEquals(RefUpdate.Result.NEW, update);
  350. Ref r = db.exactRef(newRef);
  351. assertEquals(newRef, r.getName());
  352. assertNotNull(r.getObjectId());
  353. assertNotSame(newid, r.getObjectId());
  354. assertSame(ObjectId.class, r.getObjectId().getClass());
  355. assertEquals(newid, r.getObjectId());
  356. List<ReflogEntry> reverseEntries1 = db.getReflogReader("refs/heads/abc")
  357. .getReverseEntries();
  358. ReflogEntry entry1 = reverseEntries1.get(0);
  359. assertEquals(1, reverseEntries1.size());
  360. assertEquals(ObjectId.zeroId(), entry1.getOldId());
  361. assertEquals(r.getObjectId(), entry1.getNewId());
  362. assertEquals(new PersonIdent(db).toString(),
  363. entry1.getWho().toString());
  364. assertEquals("", entry1.getComment());
  365. List<ReflogEntry> reverseEntries2 = db.getReflogReader("HEAD")
  366. .getReverseEntries();
  367. assertEquals(0, reverseEntries2.size());
  368. }
  369. @Test
  370. public void testDeleteSymref() throws IOException {
  371. RefUpdate dst = updateRef("refs/heads/abc");
  372. assertEquals(RefUpdate.Result.NEW, dst.update());
  373. ObjectId id = dst.getNewObjectId();
  374. RefUpdate u = db.updateRef("refs/symref");
  375. assertEquals(RefUpdate.Result.NEW, u.link(dst.getName()));
  376. Ref ref = db.exactRef(u.getName());
  377. assertNotNull(ref);
  378. assertTrue(ref.isSymbolic());
  379. assertEquals(dst.getName(), ref.getLeaf().getName());
  380. assertEquals(id, ref.getLeaf().getObjectId());
  381. u = db.updateRef(u.getName());
  382. u.setDetachingSymbolicRef();
  383. u.setForceUpdate(true);
  384. assertEquals(FORCED, u.delete());
  385. assertNull(db.exactRef(u.getName()));
  386. ref = db.exactRef(dst.getName());
  387. assertNotNull(ref);
  388. assertFalse(ref.isSymbolic());
  389. assertEquals(id, ref.getObjectId());
  390. }
  391. @Test
  392. public void writeUnbornHead() throws Exception {
  393. RefUpdate.Result r = db.updateRef("HEAD").link("refs/heads/unborn");
  394. assertEquals(FORCED, r);
  395. Ref head = db.exactRef("HEAD");
  396. assertTrue(head.isSymbolic());
  397. assertEquals(head.getTarget().getName(), "refs/heads/unborn");
  398. }
  399. /**
  400. * Update the HEAD ref when the referenced branch is unborn
  401. *
  402. * @throws Exception
  403. */
  404. @Test
  405. public void testUpdateRefDetachedUnbornHead() throws Exception {
  406. ObjectId ppid = db.resolve("refs/heads/master^");
  407. writeSymref("HEAD", "refs/heads/unborn");
  408. RefUpdate updateRef = db.updateRef("HEAD", true);
  409. updateRef.setForceUpdate(true);
  410. updateRef.setNewObjectId(ppid);
  411. RefUpdate.Result update = updateRef.update();
  412. assertEquals(RefUpdate.Result.NEW, update);
  413. assertEquals(ppid, db.resolve("HEAD"));
  414. Ref ref = db.exactRef("HEAD");
  415. assertEquals("HEAD", ref.getName());
  416. assertTrue("is detached", !ref.isSymbolic());
  417. // the branch HEAD referred to is left untouched
  418. assertNull(db.resolve("refs/heads/unborn"));
  419. ReflogReader reflogReader = db.getReflogReader("HEAD");
  420. ReflogEntry e = reflogReader.getReverseEntries().get(0);
  421. assertEquals(ObjectId.zeroId(), e.getOldId());
  422. assertEquals(ppid, e.getNewId());
  423. assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
  424. assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
  425. assertEquals(1250379778000L, e.getWho().getWhen().getTime());
  426. }
  427. @Test
  428. public void testDeleteNotFound() throws IOException {
  429. RefUpdate ref = updateRef("refs/heads/doesnotexist");
  430. assertNull(db.exactRef(ref.getName()));
  431. assertEquals(RefUpdate.Result.NEW, ref.delete());
  432. assertNull(db.exactRef(ref.getName()));
  433. }
  434. @Test
  435. public void testRenameSymref() throws IOException {
  436. db.resolve("HEAD");
  437. RefRename r = db.renameRef("HEAD", "KOPF");
  438. assertEquals(IO_FAILURE, r.rename());
  439. }
  440. @Test
  441. public void testRenameCurrentBranch() throws IOException {
  442. ObjectId rb = db.resolve("refs/heads/b");
  443. writeSymref(Constants.HEAD, "refs/heads/b");
  444. ObjectId oldHead = db.resolve(Constants.HEAD);
  445. assertEquals("internal test condition, b == HEAD", oldHead, rb);
  446. RefRename renameRef = db.renameRef("refs/heads/b",
  447. "refs/heads/new/name");
  448. RefUpdate.Result result = renameRef.rename();
  449. assertEquals(RefUpdate.Result.RENAMED, result);
  450. assertEquals(rb, db.resolve("refs/heads/new/name"));
  451. assertNull(db.resolve("refs/heads/b"));
  452. assertEquals(rb, db.resolve(Constants.HEAD));
  453. List<String> names = new ArrayList<>();
  454. names.add("HEAD");
  455. names.add("refs/heads/b");
  456. names.add("refs/heads/new/name");
  457. for (String nm : names) {
  458. ReflogReader rd = db.getReflogReader(nm);
  459. assertNotNull(rd);
  460. ReflogEntry last = rd.getLastEntry();
  461. ObjectId id = last.getNewId();
  462. assertTrue(ObjectId.zeroId().equals(id) || rb.equals(id));
  463. id = last.getNewId();
  464. assertTrue(ObjectId.zeroId().equals(id) || rb.equals(id));
  465. String want = "Branch: renamed b to new/name";
  466. assertEquals(want, last.getComment());
  467. }
  468. }
  469. @Test
  470. public void isGitRepository() {
  471. assertTrue(RepositoryCache.FileKey.isGitRepository(db.getDirectory(), db.getFS()));
  472. }
  473. @Test
  474. public void testRenameDestExists() throws IOException {
  475. ObjectId rb = db.resolve("refs/heads/b");
  476. writeSymref(Constants.HEAD, "refs/heads/b");
  477. ObjectId oldHead = db.resolve(Constants.HEAD);
  478. assertEquals("internal test condition, b == HEAD", oldHead, rb);
  479. RefRename renameRef = db.renameRef("refs/heads/b", "refs/heads/a");
  480. RefUpdate.Result result = renameRef.rename();
  481. assertEquals(RefUpdate.Result.LOCK_FAILURE, result);
  482. }
  483. @Test
  484. public void testRenameAtomic() throws IOException {
  485. ObjectId prevId = db.resolve("refs/heads/master^");
  486. RefRename rename = db.renameRef("refs/heads/master",
  487. "refs/heads/newmaster");
  488. RefUpdate updateRef = db.updateRef("refs/heads/master");
  489. updateRef.setNewObjectId(prevId);
  490. updateRef.setForceUpdate(true);
  491. assertEquals(FORCED, updateRef.update());
  492. assertEquals(RefUpdate.Result.LOCK_FAILURE, rename.rename());
  493. }
  494. @Test
  495. public void compactFully() throws Exception {
  496. FileReftableDatabase refDb = (FileReftableDatabase) db.getRefDatabase();
  497. PersonIdent person = new PersonIdent("jane", "jane@invalid");
  498. ObjectId aId = db.exactRef("refs/heads/a").getObjectId();
  499. ObjectId bId = db.exactRef("refs/heads/b").getObjectId();
  500. SecureRandom random = new SecureRandom();
  501. List<String> strs = new ArrayList<>();
  502. for (int i = 0; i < 1024; i++) {
  503. strs.add(String.format("%02x",
  504. Integer.valueOf(random.nextInt(256))));
  505. }
  506. String randomStr = String.join("", strs);
  507. String refName = "branch";
  508. for (long i = 0; i < 2; i++) {
  509. RefUpdate ru = refDb.newUpdate(refName, false);
  510. ru.setNewObjectId(i % 2 == 0 ? aId : bId);
  511. ru.setForceUpdate(true);
  512. // Only write a large string in the first table, so it becomes much larger
  513. // than the second, and the result is not autocompacted.
  514. ru.setRefLogMessage(i == 0 ? randomStr : "short", false);
  515. ru.setRefLogIdent(person);
  516. RefUpdate.Result res = ru.update();
  517. assertTrue(res == Result.NEW || res == FORCED);
  518. }
  519. assertEquals(refDb.exactRef(refName).getObjectId(), bId);
  520. assertTrue(randomStr.equals(refDb.getReflogReader(refName).getReverseEntry(1).getComment()));
  521. refDb.compactFully();
  522. assertEquals(refDb.exactRef(refName).getObjectId(), bId);
  523. assertTrue(randomStr.equals(refDb.getReflogReader(refName).getReverseEntry(1).getComment()));
  524. }
  525. @Test
  526. public void reftableRefsStorageClass() throws IOException {
  527. Ref b = db.exactRef("refs/heads/b");
  528. assertEquals(Ref.Storage.PACKED, b.getStorage());
  529. }
  530. private RefUpdate updateRef(String name) throws IOException {
  531. final RefUpdate ref = db.updateRef(name);
  532. ref.setNewObjectId(db.resolve(Constants.HEAD));
  533. return ref;
  534. }
  535. private void writeSymref(String src, String dst) throws IOException {
  536. RefUpdate u = db.updateRef(src);
  537. switch (u.link(dst)) {
  538. case NEW:
  539. case FORCED:
  540. case NO_CHANGE:
  541. break;
  542. default:
  543. fail("link " + src + " to " + dst);
  544. }
  545. }
  546. }