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.

SubmoduleWalkTest.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /*
  2. * Copyright (C) 2011, GitHub 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.submodule;
  44. import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_PATH;
  45. import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_URL;
  46. import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_SUBMODULE_SECTION;
  47. import static org.eclipse.jgit.lib.Constants.DOT_GIT_MODULES;
  48. import static org.junit.Assert.assertEquals;
  49. import static org.junit.Assert.assertFalse;
  50. import static org.junit.Assert.assertNotNull;
  51. import static org.junit.Assert.assertNull;
  52. import static org.junit.Assert.assertTrue;
  53. import java.io.File;
  54. import java.io.FileWriter;
  55. import java.io.IOException;
  56. import org.eclipse.jgit.api.Git;
  57. import org.eclipse.jgit.api.Status;
  58. import org.eclipse.jgit.api.errors.GitAPIException;
  59. import org.eclipse.jgit.dircache.DirCache;
  60. import org.eclipse.jgit.dircache.DirCacheEditor;
  61. import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
  62. import org.eclipse.jgit.dircache.DirCacheEntry;
  63. import org.eclipse.jgit.errors.ConfigInvalidException;
  64. import org.eclipse.jgit.errors.NoWorkTreeException;
  65. import org.eclipse.jgit.internal.storage.file.FileRepository;
  66. import org.eclipse.jgit.junit.RepositoryTestCase;
  67. import org.eclipse.jgit.junit.TestRepository;
  68. import org.eclipse.jgit.lib.Config;
  69. import org.eclipse.jgit.lib.Constants;
  70. import org.eclipse.jgit.lib.FileMode;
  71. import org.eclipse.jgit.lib.ObjectId;
  72. import org.eclipse.jgit.lib.Repository;
  73. import org.eclipse.jgit.revwalk.RevBlob;
  74. import org.eclipse.jgit.revwalk.RevCommit;
  75. import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
  76. import org.eclipse.jgit.treewalk.CanonicalTreeParser;
  77. import org.eclipse.jgit.treewalk.filter.PathFilter;
  78. import org.junit.Before;
  79. import org.junit.Test;
  80. /**
  81. * Unit tests of {@link SubmoduleWalk}
  82. */
  83. public class SubmoduleWalkTest extends RepositoryTestCase {
  84. private TestRepository<Repository> testDb;
  85. @Override
  86. @Before
  87. public void setUp() throws Exception {
  88. super.setUp();
  89. testDb = new TestRepository<>(db);
  90. }
  91. @Test
  92. public void repositoryWithNoSubmodules() throws IOException {
  93. SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
  94. assertFalse(gen.next());
  95. assertNull(gen.getPath());
  96. assertEquals(ObjectId.zeroId(), gen.getObjectId());
  97. }
  98. @Test
  99. public void bareRepositoryWithNoSubmodules() throws IOException {
  100. FileRepository bareRepo = createBareRepository();
  101. boolean result = SubmoduleWalk.containsGitModulesFile(bareRepo);
  102. assertFalse(result);
  103. }
  104. @Test
  105. public void repositoryWithRootLevelSubmodule() throws IOException,
  106. ConfigInvalidException, NoWorkTreeException, GitAPIException {
  107. final ObjectId id = ObjectId
  108. .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
  109. final String path = "sub";
  110. DirCache cache = db.lockDirCache();
  111. DirCacheEditor editor = cache.editor();
  112. editor.add(new PathEdit(path) {
  113. @Override
  114. public void apply(DirCacheEntry ent) {
  115. ent.setFileMode(FileMode.GITLINK);
  116. ent.setObjectId(id);
  117. }
  118. });
  119. editor.commit();
  120. SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
  121. assertTrue(gen.next());
  122. assertEquals(path, gen.getPath());
  123. assertEquals(id, gen.getObjectId());
  124. assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
  125. assertNull(gen.getConfigUpdate());
  126. assertNull(gen.getConfigUrl());
  127. assertNull(gen.getModulesPath());
  128. assertNull(gen.getModulesUpdate());
  129. assertNull(gen.getModulesUrl());
  130. assertNull(gen.getRepository());
  131. Status status = Git.wrap(db).status().call();
  132. assertTrue(!status.isClean());
  133. assertFalse(gen.next());
  134. }
  135. @SuppressWarnings("resource" /* java 7 */)
  136. @Test
  137. public void repositoryWithRootLevelSubmoduleAbsoluteRef()
  138. throws IOException, ConfigInvalidException {
  139. final ObjectId id = ObjectId
  140. .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
  141. final String path = "sub";
  142. File dotGit = new File(db.getWorkTree(), path + File.separatorChar
  143. + Constants.DOT_GIT);
  144. if (!dotGit.getParentFile().exists())
  145. dotGit.getParentFile().mkdirs();
  146. File modulesGitDir = new File(db.getDirectory(), "modules"
  147. + File.separatorChar + path);
  148. new FileWriter(dotGit).append(
  149. "gitdir: " + modulesGitDir.getAbsolutePath()).close();
  150. FileRepositoryBuilder builder = new FileRepositoryBuilder();
  151. builder.setWorkTree(new File(db.getWorkTree(), path));
  152. builder.build().create();
  153. DirCache cache = db.lockDirCache();
  154. DirCacheEditor editor = cache.editor();
  155. editor.add(new PathEdit(path) {
  156. @Override
  157. public void apply(DirCacheEntry ent) {
  158. ent.setFileMode(FileMode.GITLINK);
  159. ent.setObjectId(id);
  160. }
  161. });
  162. editor.commit();
  163. SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
  164. assertTrue(gen.next());
  165. assertEquals(path, gen.getPath());
  166. assertEquals(id, gen.getObjectId());
  167. assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
  168. assertNull(gen.getConfigUpdate());
  169. assertNull(gen.getConfigUrl());
  170. assertNull(gen.getModulesPath());
  171. assertNull(gen.getModulesUpdate());
  172. assertNull(gen.getModulesUrl());
  173. Repository subRepo = gen.getRepository();
  174. assertNotNull(subRepo);
  175. assertEquals(modulesGitDir.getAbsolutePath(),
  176. subRepo.getDirectory().getAbsolutePath());
  177. assertEquals(new File(db.getWorkTree(), path).getAbsolutePath(),
  178. subRepo.getWorkTree().getAbsolutePath());
  179. subRepo.close();
  180. assertFalse(gen.next());
  181. }
  182. @SuppressWarnings("resource" /* java 7 */)
  183. @Test
  184. public void repositoryWithRootLevelSubmoduleRelativeRef()
  185. throws IOException, ConfigInvalidException {
  186. final ObjectId id = ObjectId
  187. .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
  188. final String path = "sub";
  189. File dotGit = new File(db.getWorkTree(), path + File.separatorChar
  190. + Constants.DOT_GIT);
  191. if (!dotGit.getParentFile().exists())
  192. dotGit.getParentFile().mkdirs();
  193. File modulesGitDir = new File(db.getDirectory(), "modules"
  194. + File.separatorChar + path);
  195. new FileWriter(dotGit).append(
  196. "gitdir: " + "../" + Constants.DOT_GIT + "/modules/" + path)
  197. .close();
  198. FileRepositoryBuilder builder = new FileRepositoryBuilder();
  199. builder.setWorkTree(new File(db.getWorkTree(), path));
  200. builder.build().create();
  201. DirCache cache = db.lockDirCache();
  202. DirCacheEditor editor = cache.editor();
  203. editor.add(new PathEdit(path) {
  204. @Override
  205. public void apply(DirCacheEntry ent) {
  206. ent.setFileMode(FileMode.GITLINK);
  207. ent.setObjectId(id);
  208. }
  209. });
  210. editor.commit();
  211. SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
  212. assertTrue(gen.next());
  213. assertEquals(path, gen.getPath());
  214. assertEquals(id, gen.getObjectId());
  215. assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
  216. assertNull(gen.getConfigUpdate());
  217. assertNull(gen.getConfigUrl());
  218. assertNull(gen.getModulesPath());
  219. assertNull(gen.getModulesUpdate());
  220. assertNull(gen.getModulesUrl());
  221. Repository subRepo = gen.getRepository();
  222. assertNotNull(subRepo);
  223. assertEqualsFile(modulesGitDir, subRepo.getDirectory());
  224. assertEqualsFile(new File(db.getWorkTree(), path),
  225. subRepo.getWorkTree());
  226. subRepo.close();
  227. assertFalse(gen.next());
  228. }
  229. @Test
  230. public void repositoryWithNestedSubmodule() throws IOException,
  231. ConfigInvalidException {
  232. final ObjectId id = ObjectId
  233. .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
  234. final String path = "sub/dir/final";
  235. DirCache cache = db.lockDirCache();
  236. DirCacheEditor editor = cache.editor();
  237. editor.add(new PathEdit(path) {
  238. @Override
  239. public void apply(DirCacheEntry ent) {
  240. ent.setFileMode(FileMode.GITLINK);
  241. ent.setObjectId(id);
  242. }
  243. });
  244. editor.commit();
  245. SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
  246. assertTrue(gen.next());
  247. assertEquals(path, gen.getPath());
  248. assertEquals(id, gen.getObjectId());
  249. assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
  250. assertNull(gen.getConfigUpdate());
  251. assertNull(gen.getConfigUrl());
  252. assertNull(gen.getModulesPath());
  253. assertNull(gen.getModulesUpdate());
  254. assertNull(gen.getModulesUrl());
  255. assertNull(gen.getRepository());
  256. assertFalse(gen.next());
  257. }
  258. @Test
  259. public void generatorFilteredToOneOfTwoSubmodules() throws IOException {
  260. final ObjectId id1 = ObjectId
  261. .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
  262. final String path1 = "sub1";
  263. final ObjectId id2 = ObjectId
  264. .fromString("abcd1234abcd1234abcd1234abcd1234abcd1235");
  265. final String path2 = "sub2";
  266. DirCache cache = db.lockDirCache();
  267. DirCacheEditor editor = cache.editor();
  268. editor.add(new PathEdit(path1) {
  269. @Override
  270. public void apply(DirCacheEntry ent) {
  271. ent.setFileMode(FileMode.GITLINK);
  272. ent.setObjectId(id1);
  273. }
  274. });
  275. editor.add(new PathEdit(path2) {
  276. @Override
  277. public void apply(DirCacheEntry ent) {
  278. ent.setFileMode(FileMode.GITLINK);
  279. ent.setObjectId(id2);
  280. }
  281. });
  282. editor.commit();
  283. SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
  284. gen.setFilter(PathFilter.create(path1));
  285. assertTrue(gen.next());
  286. assertEquals(path1, gen.getPath());
  287. assertEquals(id1, gen.getObjectId());
  288. assertFalse(gen.next());
  289. }
  290. @Test
  291. public void indexWithGitmodules() throws Exception {
  292. final ObjectId subId = ObjectId
  293. .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
  294. final String path = "sub";
  295. final Config gitmodules = new Config();
  296. gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_PATH,
  297. "sub");
  298. // Different config in the index should be overridden by the working tree.
  299. gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_URL,
  300. "git://example.com/bad");
  301. final RevBlob gitmodulesBlob = testDb.blob(gitmodules.toText());
  302. gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_URL,
  303. "git://example.com/sub");
  304. writeTrashFile(DOT_GIT_MODULES, gitmodules.toText());
  305. DirCache cache = db.lockDirCache();
  306. DirCacheEditor editor = cache.editor();
  307. editor.add(new PathEdit(path) {
  308. @Override
  309. public void apply(DirCacheEntry ent) {
  310. ent.setFileMode(FileMode.GITLINK);
  311. ent.setObjectId(subId);
  312. }
  313. });
  314. editor.add(new PathEdit(DOT_GIT_MODULES) {
  315. @Override
  316. public void apply(DirCacheEntry ent) {
  317. ent.setFileMode(FileMode.REGULAR_FILE);
  318. ent.setObjectId(gitmodulesBlob);
  319. }
  320. });
  321. editor.commit();
  322. SubmoduleWalk gen = SubmoduleWalk.forIndex(db);
  323. assertTrue(gen.next());
  324. assertEquals(path, gen.getPath());
  325. assertEquals(subId, gen.getObjectId());
  326. assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
  327. assertNull(gen.getConfigUpdate());
  328. assertNull(gen.getConfigUrl());
  329. assertEquals("sub", gen.getModulesPath());
  330. assertNull(gen.getModulesUpdate());
  331. assertEquals("git://example.com/sub", gen.getModulesUrl());
  332. assertNull(gen.getRepository());
  333. assertFalse(gen.next());
  334. }
  335. @Test
  336. public void treeIdWithGitmodules() throws Exception {
  337. final ObjectId subId = ObjectId
  338. .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
  339. final String path = "sub";
  340. final Config gitmodules = new Config();
  341. gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_PATH,
  342. "sub");
  343. gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_URL,
  344. "git://example.com/sub");
  345. RevCommit commit = testDb.getRevWalk().parseCommit(testDb.commit()
  346. .noParents()
  347. .add(DOT_GIT_MODULES, gitmodules.toText())
  348. .edit(new PathEdit(path) {
  349. @Override
  350. public void apply(DirCacheEntry ent) {
  351. ent.setFileMode(FileMode.GITLINK);
  352. ent.setObjectId(subId);
  353. }
  354. })
  355. .create());
  356. SubmoduleWalk gen = SubmoduleWalk.forPath(db, commit.getTree(), "sub");
  357. assertEquals(path, gen.getPath());
  358. assertEquals(subId, gen.getObjectId());
  359. assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
  360. assertNull(gen.getConfigUpdate());
  361. assertNull(gen.getConfigUrl());
  362. assertEquals("sub", gen.getModulesPath());
  363. assertNull(gen.getModulesUpdate());
  364. assertEquals("git://example.com/sub", gen.getModulesUrl());
  365. assertNull(gen.getRepository());
  366. assertFalse(gen.next());
  367. }
  368. @Test
  369. public void testTreeIteratorWithGitmodules() throws Exception {
  370. final ObjectId subId = ObjectId
  371. .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
  372. final String path = "sub";
  373. final Config gitmodules = new Config();
  374. gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_PATH,
  375. "sub");
  376. gitmodules.setString(CONFIG_SUBMODULE_SECTION, path, CONFIG_KEY_URL,
  377. "git://example.com/sub");
  378. RevCommit commit = testDb.getRevWalk().parseCommit(testDb.commit()
  379. .noParents()
  380. .add(DOT_GIT_MODULES, gitmodules.toText())
  381. .edit(new PathEdit(path) {
  382. @Override
  383. public void apply(DirCacheEntry ent) {
  384. ent.setFileMode(FileMode.GITLINK);
  385. ent.setObjectId(subId);
  386. }
  387. })
  388. .create());
  389. final CanonicalTreeParser p = new CanonicalTreeParser();
  390. p.reset(testDb.getRevWalk().getObjectReader(), commit.getTree());
  391. SubmoduleWalk gen = SubmoduleWalk.forPath(db, p, "sub");
  392. assertEquals(path, gen.getPath());
  393. assertEquals(subId, gen.getObjectId());
  394. assertEquals(new File(db.getWorkTree(), path), gen.getDirectory());
  395. assertNull(gen.getConfigUpdate());
  396. assertNull(gen.getConfigUrl());
  397. assertEquals("sub", gen.getModulesPath());
  398. assertNull(gen.getModulesUpdate());
  399. assertEquals("git://example.com/sub", gen.getModulesUrl());
  400. assertNull(gen.getRepository());
  401. assertFalse(gen.next());
  402. }
  403. }