Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

FileReftableTest.java 22KB

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