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

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