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.

RefTest.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * Copyright (C) 2009-2010, Google Inc.
  3. * Copyright (C) 2009, Robin Rosenberg
  4. * Copyright (C) 2009, 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.lib;
  13. import static java.nio.charset.StandardCharsets.UTF_8;
  14. import static org.eclipse.jgit.junit.Assert.assertEquals;
  15. import static org.junit.Assert.assertEquals;
  16. import static org.junit.Assert.assertFalse;
  17. import static org.junit.Assert.assertNotNull;
  18. import static org.junit.Assert.assertNull;
  19. import static org.junit.Assert.assertSame;
  20. import static org.junit.Assert.assertTrue;
  21. import static org.junit.Assert.fail;
  22. import java.io.File;
  23. import java.io.FileOutputStream;
  24. import java.io.IOException;
  25. import java.util.Collection;
  26. import java.util.HashSet;
  27. import java.util.List;
  28. import java.util.Optional;
  29. import java.util.Set;
  30. import java.util.TreeSet;
  31. import org.eclipse.jgit.lib.Ref.Storage;
  32. import org.eclipse.jgit.lib.RefUpdate.Result;
  33. import org.eclipse.jgit.storage.file.FileBasedConfig;
  34. import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
  35. import org.junit.Test;
  36. /**
  37. * Misc tests for refs. A lot of things are tested elsewhere so not having a
  38. * test for a ref related method, does not mean it is untested.
  39. */
  40. public class RefTest extends SampleDataRepositoryTestCase {
  41. private void writeSymref(String src, String dst) throws IOException {
  42. RefUpdate u = db.updateRef(src);
  43. switch (u.link(dst)) {
  44. case NEW:
  45. case FORCED:
  46. case NO_CHANGE:
  47. break;
  48. default:
  49. fail("link " + src + " to " + dst);
  50. }
  51. }
  52. private void writeNewRef(String name, ObjectId value) throws IOException {
  53. RefUpdate updateRef = db.updateRef(name);
  54. updateRef.setNewObjectId(value);
  55. assertEquals(RefUpdate.Result.NEW, updateRef.update());
  56. }
  57. @Test
  58. public void testRemoteNames() throws Exception {
  59. FileBasedConfig config = db.getConfig();
  60. config.setBoolean(ConfigConstants.CONFIG_REMOTE_SECTION,
  61. "origin", "dummy", true);
  62. config.setBoolean(ConfigConstants.CONFIG_REMOTE_SECTION,
  63. "ab/c", "dummy", true);
  64. config.save();
  65. assertEquals("[ab/c, origin]",
  66. new TreeSet<>(db.getRemoteNames()).toString());
  67. // one-level deep remote branch
  68. assertEquals("master",
  69. db.shortenRemoteBranchName("refs/remotes/origin/master"));
  70. assertEquals("origin", db.getRemoteName("refs/remotes/origin/master"));
  71. // two-level deep remote branch
  72. assertEquals("masta/r",
  73. db.shortenRemoteBranchName("refs/remotes/origin/masta/r"));
  74. assertEquals("origin", db.getRemoteName("refs/remotes/origin/masta/r"));
  75. // Remote with slash and one-level deep branch name
  76. assertEquals("xmaster",
  77. db.shortenRemoteBranchName("refs/remotes/ab/c/xmaster"));
  78. assertEquals("ab/c", db.getRemoteName("refs/remotes/ab/c/xmaster"));
  79. // Remote with slash and two-level deep branch name
  80. assertEquals("xmasta/r",
  81. db.shortenRemoteBranchName("refs/remotes/ab/c/xmasta/r"));
  82. assertEquals("ab/c", db.getRemoteName("refs/remotes/ab/c/xmasta/r"));
  83. // no such remote
  84. assertNull(db.getRemoteName("refs/remotes/nosuchremote/x"));
  85. assertNull(db.shortenRemoteBranchName("refs/remotes/nosuchremote/x"));
  86. // no such remote too, no branch name either
  87. assertNull(db.getRemoteName("refs/remotes/abranch"));
  88. assertNull(db.shortenRemoteBranchName("refs/remotes/abranch"));
  89. // // local branch
  90. assertNull(db.getRemoteName("refs/heads/abranch"));
  91. assertNull(db.shortenRemoteBranchName("refs/heads/abranch"));
  92. }
  93. @Test
  94. public void testReadAllIncludingSymrefs() throws Exception {
  95. ObjectId masterId = db.resolve("refs/heads/master");
  96. RefUpdate updateRef = db.updateRef("refs/remotes/origin/master");
  97. updateRef.setNewObjectId(masterId);
  98. updateRef.setForceUpdate(true);
  99. updateRef.update();
  100. writeSymref("refs/remotes/origin/HEAD",
  101. "refs/remotes/origin/master");
  102. ObjectId r = db.resolve("refs/remotes/origin/HEAD");
  103. assertEquals(masterId, r);
  104. List<Ref> allRefs = db.getRefDatabase().getRefs();
  105. Optional<Ref> refHEAD = allRefs.stream()
  106. .filter(ref -> ref.getName().equals("refs/remotes/origin/HEAD"))
  107. .findAny();
  108. assertTrue(refHEAD.isPresent());
  109. assertEquals(masterId, refHEAD.get().getObjectId());
  110. assertFalse(refHEAD.get().isPeeled());
  111. assertNull(refHEAD.get().getPeeledObjectId());
  112. Optional<Ref> refmaster = allRefs.stream().filter(
  113. ref -> ref.getName().equals("refs/remotes/origin/master"))
  114. .findAny();
  115. assertTrue(refmaster.isPresent());
  116. assertEquals(masterId, refmaster.get().getObjectId());
  117. assertFalse(refmaster.get().isPeeled());
  118. assertNull(refmaster.get().getPeeledObjectId());
  119. }
  120. @Test
  121. public void testReadSymRefToPacked() throws IOException {
  122. writeSymref("HEAD", "refs/heads/b");
  123. Ref ref = db.exactRef("HEAD");
  124. assertEquals(Ref.Storage.LOOSE, ref.getStorage());
  125. assertTrue("is symref", ref.isSymbolic());
  126. ref = ref.getTarget();
  127. assertEquals("refs/heads/b", ref.getName());
  128. assertEquals(Ref.Storage.PACKED, ref.getStorage());
  129. }
  130. @Test
  131. public void testReadSymRefToLoosePacked() throws IOException {
  132. ObjectId pid = db.resolve("refs/heads/master^");
  133. RefUpdate updateRef = db.updateRef("refs/heads/master");
  134. updateRef.setNewObjectId(pid);
  135. updateRef.setForceUpdate(true);
  136. Result update = updateRef.update();
  137. assertEquals(Result.FORCED, update); // internal
  138. writeSymref("HEAD", "refs/heads/master");
  139. Ref ref = db.exactRef("HEAD");
  140. assertEquals(Ref.Storage.LOOSE, ref.getStorage());
  141. ref = ref.getTarget();
  142. assertEquals("refs/heads/master", ref.getName());
  143. assertEquals(Ref.Storage.LOOSE, ref.getStorage());
  144. }
  145. @Test
  146. public void testReadLooseRef() throws IOException {
  147. RefUpdate updateRef = db.updateRef("ref/heads/new");
  148. updateRef.setNewObjectId(db.resolve("refs/heads/master"));
  149. Result update = updateRef.update();
  150. assertEquals(Result.NEW, update);
  151. Ref ref = db.exactRef("ref/heads/new");
  152. assertEquals(Storage.LOOSE, ref.getStorage());
  153. }
  154. @Test
  155. public void testGetShortRef() throws IOException {
  156. Ref ref = db.exactRef("refs/heads/master");
  157. assertEquals("refs/heads/master", ref.getName());
  158. assertEquals(db.resolve("refs/heads/master"), ref.getObjectId());
  159. }
  160. @Test
  161. public void testGetShortExactRef() throws IOException {
  162. assertNull(db.getRefDatabase().exactRef("master"));
  163. Ref ref = db.getRefDatabase().exactRef("HEAD");
  164. assertEquals("HEAD", ref.getName());
  165. assertEquals("refs/heads/master", ref.getTarget().getName());
  166. assertEquals(db.resolve("refs/heads/master"), ref.getObjectId());
  167. }
  168. @Test
  169. public void testRefsUnderRefs() throws IOException {
  170. ObjectId masterId = db.resolve("refs/heads/master");
  171. writeNewRef("refs/heads/refs/foo/bar", masterId);
  172. assertNull(db.getRefDatabase().exactRef("refs/foo/bar"));
  173. Ref ref = db.findRef("refs/foo/bar");
  174. assertEquals("refs/heads/refs/foo/bar", ref.getName());
  175. assertEquals(db.resolve("refs/heads/master"), ref.getObjectId());
  176. }
  177. @Test
  178. public void testAmbiguousRefsUnderRefs() throws IOException {
  179. ObjectId masterId = db.resolve("refs/heads/master");
  180. writeNewRef("refs/foo/bar", masterId);
  181. writeNewRef("refs/heads/refs/foo/bar", masterId);
  182. Ref exactRef = db.getRefDatabase().exactRef("refs/foo/bar");
  183. assertEquals("refs/foo/bar", exactRef.getName());
  184. assertEquals(masterId, exactRef.getObjectId());
  185. Ref ref = db.findRef("refs/foo/bar");
  186. assertEquals("refs/foo/bar", ref.getName());
  187. assertEquals(masterId, ref.getObjectId());
  188. }
  189. /**
  190. * Let an "outsider" create a loose ref with the same name as a packed one
  191. *
  192. * @throws IOException
  193. * @throws InterruptedException
  194. */
  195. @Test
  196. public void testReadLoosePackedRef() throws IOException,
  197. InterruptedException {
  198. Ref ref = db.exactRef("refs/heads/master");
  199. assertEquals(Storage.PACKED, ref.getStorage());
  200. try (FileOutputStream os = new FileOutputStream(
  201. new File(db.getDirectory(), "refs/heads/master"))) {
  202. os.write(ref.getObjectId().name().getBytes(UTF_8));
  203. os.write('\n');
  204. }
  205. ref = db.exactRef("refs/heads/master");
  206. assertEquals(Storage.LOOSE, ref.getStorage());
  207. }
  208. /**
  209. * Modify a packed ref using the API. This creates a loose ref too, ie.
  210. * LOOSE_PACKED
  211. *
  212. * @throws IOException
  213. */
  214. @Test
  215. public void testReadSimplePackedRefSameRepo() throws IOException {
  216. Ref ref = db.exactRef("refs/heads/master");
  217. ObjectId pid = db.resolve("refs/heads/master^");
  218. assertEquals(Storage.PACKED, ref.getStorage());
  219. RefUpdate updateRef = db.updateRef("refs/heads/master");
  220. updateRef.setNewObjectId(pid);
  221. updateRef.setForceUpdate(true);
  222. Result update = updateRef.update();
  223. assertEquals(Result.FORCED, update);
  224. ref = db.exactRef("refs/heads/master");
  225. assertEquals(Storage.LOOSE, ref.getStorage());
  226. }
  227. @Test
  228. public void testResolvedNamesBranch() throws IOException {
  229. Ref ref = db.findRef("a");
  230. assertEquals("refs/heads/a", ref.getName());
  231. }
  232. @Test
  233. public void testResolvedSymRef() throws IOException {
  234. Ref ref = db.exactRef(Constants.HEAD);
  235. assertEquals(Constants.HEAD, ref.getName());
  236. assertTrue("is symbolic ref", ref.isSymbolic());
  237. assertSame(Ref.Storage.LOOSE, ref.getStorage());
  238. Ref dst = ref.getTarget();
  239. assertNotNull("has target", dst);
  240. assertEquals("refs/heads/master", dst.getName());
  241. assertSame(dst.getObjectId(), ref.getObjectId());
  242. assertSame(dst.getPeeledObjectId(), ref.getPeeledObjectId());
  243. assertEquals(dst.isPeeled(), ref.isPeeled());
  244. }
  245. private static void checkContainsRef(Collection<Ref> haystack, Ref needle) {
  246. for (Ref ref : haystack) {
  247. if (ref.getName().equals(needle.getName()) &&
  248. ref.getObjectId().equals(needle.getObjectId())) {
  249. return;
  250. }
  251. }
  252. fail("list " + haystack + " does not contain ref " + needle);
  253. }
  254. @Test
  255. public void testGetRefsByPrefix() throws IOException {
  256. List<Ref> refs = db.getRefDatabase().getRefsByPrefix("refs/heads/g");
  257. assertEquals(2, refs.size());
  258. checkContainsRef(refs, db.exactRef("refs/heads/g"));
  259. checkContainsRef(refs, db.exactRef("refs/heads/gitlink"));
  260. refs = db.getRefDatabase().getRefsByPrefix("refs/heads/prefix/");
  261. assertEquals(1, refs.size());
  262. checkContainsRef(refs, db.exactRef("refs/heads/prefix/a"));
  263. }
  264. @Test
  265. public void testGetRefsByPrefixes() throws IOException {
  266. List<Ref> refs = db.getRefDatabase().getRefsByPrefix();
  267. assertEquals(0, refs.size());
  268. refs = db.getRefDatabase().getRefsByPrefix("refs/heads/p",
  269. "refs/tags/A");
  270. assertEquals(3, refs.size());
  271. checkContainsRef(refs, db.exactRef("refs/heads/pa"));
  272. checkContainsRef(refs, db.exactRef("refs/heads/prefix/a"));
  273. checkContainsRef(refs, db.exactRef("refs/tags/A"));
  274. }
  275. @Test
  276. public void testGetRefsExcludingPrefix() throws IOException {
  277. Set<String> exclude = new HashSet<>();
  278. exclude.add("refs/tags");
  279. // HEAD + 12 refs/heads are present here.
  280. List<Ref> refs =
  281. db.getRefDatabase().getRefsByPrefixWithExclusions(RefDatabase.ALL, exclude);
  282. assertEquals(13, refs.size());
  283. checkContainsRef(refs, db.exactRef("HEAD"));
  284. checkContainsRef(refs, db.exactRef("refs/heads/a"));
  285. for (Ref notInResult : db.getRefDatabase().getRefsByPrefix("refs/tags")) {
  286. assertFalse(refs.contains(notInResult));
  287. }
  288. }
  289. @Test
  290. public void testGetRefsExcludingPrefixes() throws IOException {
  291. Set<String> exclude = new HashSet<>();
  292. exclude.add("refs/tags/");
  293. exclude.add("refs/heads/");
  294. List<Ref> refs = db.getRefDatabase().getRefsByPrefixWithExclusions(RefDatabase.ALL, exclude);
  295. assertEquals(1, refs.size());
  296. checkContainsRef(refs, db.exactRef("HEAD"));
  297. }
  298. @Test
  299. public void testGetRefsExcludingNonExistingPrefixes() throws IOException {
  300. Set<String> prefixes = new HashSet<>();
  301. prefixes.add("refs/tags/");
  302. prefixes.add("refs/heads/");
  303. prefixes.add("refs/nonexistent/");
  304. List<Ref> refs = db.getRefDatabase().getRefsByPrefixWithExclusions(RefDatabase.ALL, prefixes);
  305. assertEquals(1, refs.size());
  306. checkContainsRef(refs, db.exactRef("HEAD"));
  307. }
  308. @Test
  309. public void testGetRefsWithPrefixExcludingPrefixes() throws IOException {
  310. Set<String> exclude = new HashSet<>();
  311. exclude.add("refs/heads/pa");
  312. String include = "refs/heads/p";
  313. List<Ref> refs = db.getRefDatabase().getRefsByPrefixWithExclusions(include, exclude);
  314. assertEquals(1, refs.size());
  315. checkContainsRef(refs, db.exactRef("refs/heads/prefix/a"));
  316. }
  317. @Test
  318. public void testGetRefsWithPrefixExcludingOverlappingPrefixes() throws IOException {
  319. Set<String> exclude = new HashSet<>();
  320. exclude.add("refs/heads/pa");
  321. exclude.add("refs/heads/");
  322. exclude.add("refs/heads/p");
  323. exclude.add("refs/tags/");
  324. List<Ref> refs = db.getRefDatabase().getRefsByPrefixWithExclusions(RefDatabase.ALL, exclude);
  325. assertEquals(1, refs.size());
  326. checkContainsRef(refs, db.exactRef("HEAD"));
  327. }
  328. @Test
  329. public void testResolveTipSha1() throws IOException {
  330. ObjectId masterId = db.resolve("refs/heads/master");
  331. Set<Ref> resolved = db.getRefDatabase().getTipsWithSha1(masterId);
  332. assertEquals(2, resolved.size());
  333. checkContainsRef(resolved, db.exactRef("refs/heads/master"));
  334. checkContainsRef(resolved, db.exactRef("HEAD"));
  335. assertEquals(db.getRefDatabase()
  336. .getTipsWithSha1(ObjectId.zeroId()).size(), 0);
  337. }
  338. }