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.

AttributesHandlerTest.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /*
  2. * Copyright (C) 2015, 2017 Ivan Motsch <ivan.motsch@bsiag.com>
  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.attributes;
  44. import static org.junit.Assert.assertEquals;
  45. import static org.junit.Assert.assertFalse;
  46. import static org.junit.Assert.assertTrue;
  47. import java.io.File;
  48. import java.io.IOException;
  49. import java.util.ArrayList;
  50. import java.util.Collection;
  51. import java.util.Collections;
  52. import org.eclipse.jgit.junit.RepositoryTestCase;
  53. import org.eclipse.jgit.lib.ConfigConstants;
  54. import org.eclipse.jgit.lib.Constants;
  55. import org.eclipse.jgit.lib.FileMode;
  56. import org.eclipse.jgit.storage.file.FileBasedConfig;
  57. import org.eclipse.jgit.treewalk.FileTreeIterator;
  58. import org.eclipse.jgit.treewalk.TreeWalk;
  59. import org.junit.Test;
  60. /**
  61. * Tests {@link AttributesHandler}
  62. */
  63. public class AttributesHandlerTest extends RepositoryTestCase {
  64. private static final FileMode D = FileMode.TREE;
  65. private static final FileMode F = FileMode.REGULAR_FILE;
  66. private TreeWalk walk;
  67. @Test
  68. public void testExpandNonMacro1() throws Exception {
  69. setupRepo(null, null, null, "*.txt text");
  70. walk = beginWalk();
  71. assertIteration(D, "sub");
  72. assertIteration(F, "sub/.gitattributes");
  73. assertIteration(F, "sub/a.txt", attrs("text"));
  74. endWalk();
  75. }
  76. @Test
  77. public void testExpandNonMacro2() throws Exception {
  78. setupRepo(null, null, null, "*.txt -text");
  79. walk = beginWalk();
  80. assertIteration(D, "sub");
  81. assertIteration(F, "sub/.gitattributes");
  82. assertIteration(F, "sub/a.txt", attrs("-text"));
  83. endWalk();
  84. }
  85. @Test
  86. public void testExpandNonMacro3() throws Exception {
  87. setupRepo(null, null, null, "*.txt !text");
  88. walk = beginWalk();
  89. assertIteration(D, "sub");
  90. assertIteration(F, "sub/.gitattributes");
  91. assertIteration(F, "sub/a.txt", attrs(""));
  92. endWalk();
  93. }
  94. @Test
  95. public void testExpandNonMacro4() throws Exception {
  96. setupRepo(null, null, null, "*.txt text=auto");
  97. walk = beginWalk();
  98. assertIteration(D, "sub");
  99. assertIteration(F, "sub/.gitattributes");
  100. assertIteration(F, "sub/a.txt", attrs("text=auto"));
  101. endWalk();
  102. }
  103. @Test
  104. public void testExpandBuiltInMacro1() throws Exception {
  105. setupRepo(null, null, null, "*.txt binary");
  106. walk = beginWalk();
  107. assertIteration(D, "sub");
  108. assertIteration(F, "sub/.gitattributes");
  109. assertIteration(F, "sub/a.txt", attrs("binary -diff -merge -text"));
  110. endWalk();
  111. }
  112. @Test
  113. public void testExpandBuiltInMacro2() throws Exception {
  114. setupRepo(null, null, null, "*.txt -binary");
  115. walk = beginWalk();
  116. assertIteration(D, "sub");
  117. assertIteration(F, "sub/.gitattributes");
  118. assertIteration(F, "sub/a.txt", attrs("-binary diff merge text"));
  119. endWalk();
  120. }
  121. @Test
  122. public void testExpandBuiltInMacro3() throws Exception {
  123. setupRepo(null, null, null, "*.txt !binary");
  124. walk = beginWalk();
  125. assertIteration(D, "sub");
  126. assertIteration(F, "sub/.gitattributes");
  127. assertIteration(F, "sub/a.txt", attrs(""));
  128. endWalk();
  129. }
  130. @Test
  131. public void testCustomGlobalMacro1() throws Exception {
  132. setupRepo(
  133. "[attr]foo a -b !c d=e", null, null, "*.txt foo");
  134. walk = beginWalk();
  135. assertIteration(D, "sub");
  136. assertIteration(F, "sub/.gitattributes");
  137. assertIteration(F, "sub/a.txt", attrs("foo a -b d=e"));
  138. endWalk();
  139. }
  140. @Test
  141. public void testCustomGlobalMacro2() throws Exception {
  142. setupRepo("[attr]foo a -b !c d=e", null, null, "*.txt -foo");
  143. walk = beginWalk();
  144. assertIteration(D, "sub");
  145. assertIteration(F, "sub/.gitattributes");
  146. assertIteration(F, "sub/a.txt", attrs("-foo -a b d=e"));
  147. endWalk();
  148. }
  149. @Test
  150. public void testCustomGlobalMacro3() throws Exception {
  151. setupRepo("[attr]foo a -b !c d=e", null, null, "*.txt !foo");
  152. walk = beginWalk();
  153. assertIteration(D, "sub");
  154. assertIteration(F, "sub/.gitattributes");
  155. assertIteration(F, "sub/a.txt", attrs(""));
  156. endWalk();
  157. }
  158. @Test
  159. public void testCustomGlobalMacro4() throws Exception {
  160. setupRepo("[attr]foo a -b !c d=e", null, null, "*.txt foo=bar");
  161. walk = beginWalk();
  162. assertIteration(D, "sub");
  163. assertIteration(F, "sub/.gitattributes");
  164. assertIteration(F, "sub/a.txt", attrs("foo=bar a -b d=bar"));
  165. endWalk();
  166. }
  167. @Test
  168. public void testInfoOverridesGlobal() throws Exception {
  169. setupRepo("[attr]foo bar1",
  170. "[attr]foo bar2", null, "*.txt foo");
  171. walk = beginWalk();
  172. assertIteration(D, "sub");
  173. assertIteration(F, "sub/.gitattributes");
  174. assertIteration(F, "sub/a.txt", attrs("foo bar2"));
  175. endWalk();
  176. }
  177. @Test
  178. public void testWorkDirRootOverridesGlobal() throws Exception {
  179. setupRepo("[attr]foo bar1",
  180. null,
  181. "[attr]foo bar3", "*.txt foo");
  182. walk = beginWalk();
  183. assertIteration(F, ".gitattributes");
  184. assertIteration(D, "sub");
  185. assertIteration(F, "sub/.gitattributes");
  186. assertIteration(F, "sub/a.txt", attrs("foo bar3"));
  187. endWalk();
  188. }
  189. @Test
  190. public void testInfoOverridesWorkDirRoot() throws Exception {
  191. setupRepo("[attr]foo bar1",
  192. "[attr]foo bar2", "[attr]foo bar3", "*.txt foo");
  193. walk = beginWalk();
  194. assertIteration(F, ".gitattributes");
  195. assertIteration(D, "sub");
  196. assertIteration(F, "sub/.gitattributes");
  197. assertIteration(F, "sub/a.txt", attrs("foo bar2"));
  198. endWalk();
  199. }
  200. @Test
  201. public void testRecursiveMacro() throws Exception {
  202. setupRepo(
  203. "[attr]foo x bar -foo",
  204. null, null, "*.txt foo");
  205. walk = beginWalk();
  206. assertIteration(D, "sub");
  207. assertIteration(F, "sub/.gitattributes");
  208. assertIteration(F, "sub/a.txt", attrs("foo x bar"));
  209. endWalk();
  210. }
  211. @Test
  212. public void testCyclicMacros() throws Exception {
  213. setupRepo(
  214. "[attr]foo x -bar\n[attr]bar y -foo", null, null, "*.txt foo");
  215. walk = beginWalk();
  216. assertIteration(D, "sub");
  217. assertIteration(F, "sub/.gitattributes");
  218. assertIteration(F, "sub/a.txt", attrs("foo x -bar -y"));
  219. endWalk();
  220. }
  221. @Test
  222. public void testRelativePaths() throws Exception {
  223. setupRepo("sub/ global", "sub/** init",
  224. "sub/** top_sub\n*.txt top",
  225. "sub/** subsub\nsub/ subsub2\n*.txt foo");
  226. // The last sub/** is in sub/.gitattributes. It must not
  227. // apply to any of the files here. It would match for a
  228. // further subdirectory sub/sub. The sub/ rules must match
  229. // only for directories.
  230. walk = beginWalk();
  231. assertIteration(F, ".gitattributes");
  232. assertIteration(D, "sub", attrs("global"));
  233. assertIteration(F, "sub/.gitattributes", attrs("init top_sub"));
  234. assertIteration(F, "sub/a.txt", attrs("init foo top top_sub"));
  235. endWalk();
  236. // All right, let's see that they *do* apply in sub/sub:
  237. writeTrashFile("sub/sub/b.txt", "b");
  238. walk = beginWalk();
  239. assertIteration(F, ".gitattributes");
  240. assertIteration(D, "sub", attrs("global"));
  241. assertIteration(F, "sub/.gitattributes", attrs("init top_sub"));
  242. assertIteration(F, "sub/a.txt", attrs("init foo top top_sub"));
  243. assertIteration(D, "sub/sub", attrs("init subsub2 top_sub global"));
  244. assertIteration(F, "sub/sub/b.txt",
  245. attrs("init foo subsub top top_sub"));
  246. endWalk();
  247. }
  248. @Test
  249. public void testNestedMatchNot() throws Exception {
  250. setupRepo(null, null, "*.xml xml\n*.jar jar", null);
  251. writeTrashFile("foo.xml/bar.jar", "b");
  252. writeTrashFile("foo.xml/bar.xml", "bx");
  253. writeTrashFile("sub/b.jar", "bj");
  254. writeTrashFile("sub/b.xml", "bx");
  255. // On foo.xml/bar.jar we must not have 'xml'
  256. walk = beginWalk();
  257. assertIteration(F, ".gitattributes");
  258. assertIteration(D, "foo.xml", attrs("xml"));
  259. assertIteration(F, "foo.xml/bar.jar", attrs("jar"));
  260. assertIteration(F, "foo.xml/bar.xml", attrs("xml"));
  261. assertIteration(D, "sub");
  262. assertIteration(F, "sub/a.txt");
  263. assertIteration(F, "sub/b.jar", attrs("jar"));
  264. assertIteration(F, "sub/b.xml", attrs("xml"));
  265. endWalk();
  266. }
  267. @Test
  268. public void testNestedMatch() throws Exception {
  269. // See also CGitAttributeTest.testNestedMatch()
  270. setupRepo(null, null, "foo/ xml\nsub/foo/ sub\n*.jar jar", null);
  271. writeTrashFile("foo/bar.jar", "b");
  272. writeTrashFile("foo/bar.xml", "bx");
  273. writeTrashFile("sub/b.jar", "bj");
  274. writeTrashFile("sub/b.xml", "bx");
  275. writeTrashFile("sub/foo/b.jar", "bf");
  276. walk = beginWalk();
  277. assertIteration(F, ".gitattributes");
  278. assertIteration(D, "foo", attrs("xml"));
  279. assertIteration(F, "foo/bar.jar", attrs("jar"));
  280. assertIteration(F, "foo/bar.xml");
  281. assertIteration(D, "sub");
  282. assertIteration(F, "sub/a.txt");
  283. assertIteration(F, "sub/b.jar", attrs("jar"));
  284. assertIteration(F, "sub/b.xml");
  285. assertIteration(D, "sub/foo", attrs("sub xml"));
  286. assertIteration(F, "sub/foo/b.jar", attrs("jar"));
  287. endWalk();
  288. }
  289. @Test
  290. public void testNestedMatchRecursive() throws Exception {
  291. setupRepo(null, null, "foo/** xml\n*.jar jar", null);
  292. writeTrashFile("foo/bar.jar", "b");
  293. writeTrashFile("foo/bar.xml", "bx");
  294. writeTrashFile("sub/b.jar", "bj");
  295. writeTrashFile("sub/b.xml", "bx");
  296. writeTrashFile("sub/foo/b.jar", "bf");
  297. // On foo.xml/bar.jar we must not have 'xml'
  298. walk = beginWalk();
  299. assertIteration(F, ".gitattributes");
  300. assertIteration(D, "foo");
  301. assertIteration(F, "foo/bar.jar", attrs("jar xml"));
  302. assertIteration(F, "foo/bar.xml", attrs("xml"));
  303. assertIteration(D, "sub");
  304. assertIteration(F, "sub/a.txt");
  305. assertIteration(F, "sub/b.jar", attrs("jar"));
  306. assertIteration(F, "sub/b.xml");
  307. assertIteration(D, "sub/foo");
  308. assertIteration(F, "sub/foo/b.jar", attrs("jar"));
  309. endWalk();
  310. }
  311. @Test
  312. public void testStarMatchOnSlashNot() throws Exception {
  313. setupRepo(null, null, "s*xt bar", null);
  314. writeTrashFile("sub/a.txt", "1");
  315. writeTrashFile("foo/sext", "2");
  316. writeTrashFile("foo/s.txt", "3");
  317. walk = beginWalk();
  318. assertIteration(F, ".gitattributes");
  319. assertIteration(D, "foo");
  320. assertIteration(F, "foo/s.txt", attrs("bar"));
  321. assertIteration(F, "foo/sext", attrs("bar"));
  322. assertIteration(D, "sub");
  323. assertIteration(F, "sub/a.txt");
  324. endWalk();
  325. }
  326. @Test
  327. public void testPrefixMatchNot() throws Exception {
  328. setupRepo(null, null, "sub/new bar", null);
  329. writeTrashFile("sub/new/foo.txt", "1");
  330. walk = beginWalk();
  331. assertIteration(F, ".gitattributes");
  332. assertIteration(D, "sub");
  333. assertIteration(F, "sub/a.txt");
  334. assertIteration(D, "sub/new", attrs("bar"));
  335. assertIteration(F, "sub/new/foo.txt");
  336. endWalk();
  337. }
  338. @Test
  339. public void testComplexPathMatch() throws Exception {
  340. setupRepo(null, null, "s[t-v]b/n[de]w bar", null);
  341. writeTrashFile("sub/new/foo.txt", "1");
  342. writeTrashFile("sub/ndw", "2");
  343. walk = beginWalk();
  344. assertIteration(F, ".gitattributes");
  345. assertIteration(D, "sub");
  346. assertIteration(F, "sub/a.txt");
  347. assertIteration(F, "sub/ndw", attrs("bar"));
  348. assertIteration(D, "sub/new", attrs("bar"));
  349. assertIteration(F, "sub/new/foo.txt");
  350. endWalk();
  351. }
  352. @Test
  353. public void testStarPathMatch() throws Exception {
  354. setupRepo(null, null, "sub/new/* bar", null);
  355. writeTrashFile("sub/new/foo.txt", "1");
  356. writeTrashFile("sub/new/lower/foo.txt", "2");
  357. walk = beginWalk();
  358. assertIteration(F, ".gitattributes");
  359. assertIteration(D, "sub");
  360. assertIteration(F, "sub/a.txt");
  361. assertIteration(D, "sub/new");
  362. assertIteration(F, "sub/new/foo.txt", attrs("bar"));
  363. assertIteration(D, "sub/new/lower", attrs("bar"));
  364. assertIteration(F, "sub/new/lower/foo.txt");
  365. endWalk();
  366. }
  367. @Test
  368. public void testDirectoryMatchSubSimple() throws Exception {
  369. setupRepo(null, null, "sub/new/ bar", null);
  370. writeTrashFile("sub/new/foo.txt", "1");
  371. writeTrashFile("foo/sub/new/foo.txt", "2");
  372. writeTrashFile("sub/sub/new/foo.txt", "3");
  373. walk = beginWalk();
  374. assertIteration(F, ".gitattributes");
  375. assertIteration(D, "foo");
  376. assertIteration(D, "foo/sub");
  377. assertIteration(D, "foo/sub/new");
  378. assertIteration(F, "foo/sub/new/foo.txt");
  379. assertIteration(D, "sub");
  380. assertIteration(F, "sub/a.txt");
  381. assertIteration(D, "sub/new", attrs("bar"));
  382. assertIteration(F, "sub/new/foo.txt");
  383. assertIteration(D, "sub/sub");
  384. assertIteration(D, "sub/sub/new");
  385. assertIteration(F, "sub/sub/new/foo.txt");
  386. endWalk();
  387. }
  388. @Test
  389. public void testDirectoryMatchSubRecursive() throws Exception {
  390. setupRepo(null, null, "**/sub/new/ bar", null);
  391. writeTrashFile("sub/new/foo.txt", "1");
  392. writeTrashFile("foo/sub/new/foo.txt", "2");
  393. walk = beginWalk();
  394. assertIteration(F, ".gitattributes");
  395. assertIteration(D, "foo");
  396. assertIteration(D, "foo/sub");
  397. assertIteration(D, "foo/sub/new", attrs("bar"));
  398. assertIteration(F, "foo/sub/new/foo.txt");
  399. assertIteration(D, "sub");
  400. assertIteration(F, "sub/a.txt");
  401. assertIteration(D, "sub/new", attrs("bar"));
  402. assertIteration(F, "sub/new/foo.txt");
  403. endWalk();
  404. }
  405. @Test
  406. public void testDirectoryMatchSubRecursiveBacktrack() throws Exception {
  407. setupRepo(null, null, "**/sub/new/ bar", null);
  408. writeTrashFile("sub/new/foo.txt", "1");
  409. writeTrashFile("foo/sub/new/foo.txt", "2");
  410. writeTrashFile("sub/sub/new/foo.txt", "3");
  411. walk = beginWalk();
  412. assertIteration(F, ".gitattributes");
  413. assertIteration(D, "foo");
  414. assertIteration(D, "foo/sub");
  415. assertIteration(D, "foo/sub/new", attrs("bar"));
  416. assertIteration(F, "foo/sub/new/foo.txt");
  417. assertIteration(D, "sub");
  418. assertIteration(F, "sub/a.txt");
  419. assertIteration(D, "sub/new", attrs("bar"));
  420. assertIteration(F, "sub/new/foo.txt");
  421. assertIteration(D, "sub/sub");
  422. assertIteration(D, "sub/sub/new", attrs("bar"));
  423. assertIteration(F, "sub/sub/new/foo.txt");
  424. endWalk();
  425. }
  426. @Test
  427. public void testDirectoryMatchSubRecursiveBacktrack2() throws Exception {
  428. setupRepo(null, null, "**/**/sub/new/ bar", null);
  429. writeTrashFile("sub/new/foo.txt", "1");
  430. writeTrashFile("foo/sub/new/foo.txt", "2");
  431. writeTrashFile("sub/sub/new/foo.txt", "3");
  432. walk = beginWalk();
  433. assertIteration(F, ".gitattributes");
  434. assertIteration(D, "foo");
  435. assertIteration(D, "foo/sub");
  436. assertIteration(D, "foo/sub/new", attrs("bar"));
  437. assertIteration(F, "foo/sub/new/foo.txt");
  438. assertIteration(D, "sub");
  439. assertIteration(F, "sub/a.txt");
  440. assertIteration(D, "sub/new", attrs("bar"));
  441. assertIteration(F, "sub/new/foo.txt");
  442. assertIteration(D, "sub/sub");
  443. assertIteration(D, "sub/sub/new", attrs("bar"));
  444. assertIteration(F, "sub/sub/new/foo.txt");
  445. endWalk();
  446. }
  447. @Test
  448. public void testDirectoryMatchSubComplex() throws Exception {
  449. setupRepo(null, null, "s[uv]b/n*/ bar", null);
  450. writeTrashFile("sub/new/foo.txt", "1");
  451. writeTrashFile("foo/sub/new/foo.txt", "2");
  452. walk = beginWalk();
  453. assertIteration(F, ".gitattributes");
  454. assertIteration(D, "foo");
  455. assertIteration(D, "foo/sub");
  456. assertIteration(D, "foo/sub/new");
  457. assertIteration(F, "foo/sub/new/foo.txt");
  458. assertIteration(D, "sub");
  459. assertIteration(F, "sub/a.txt");
  460. assertIteration(D, "sub/new", attrs("bar"));
  461. assertIteration(F, "sub/new/foo.txt");
  462. endWalk();
  463. }
  464. @Test
  465. public void testDirectoryMatch() throws Exception {
  466. setupRepo(null, null, "new/ bar", null);
  467. writeTrashFile("sub/new/foo.txt", "1");
  468. writeTrashFile("foo/sub/new/foo.txt", "2");
  469. writeTrashFile("foo/new", "3");
  470. walk = beginWalk();
  471. assertIteration(F, ".gitattributes");
  472. assertIteration(D, "foo");
  473. assertIteration(F, "foo/new");
  474. assertIteration(D, "foo/sub");
  475. assertIteration(D, "foo/sub/new", attrs("bar"));
  476. assertIteration(F, "foo/sub/new/foo.txt");
  477. assertIteration(D, "sub");
  478. assertIteration(F, "sub/a.txt");
  479. assertIteration(D, "sub/new", attrs("bar"));
  480. assertIteration(F, "sub/new/foo.txt");
  481. endWalk();
  482. }
  483. private static Collection<Attribute> attrs(String s) {
  484. return new AttributesRule("*", s).getAttributes();
  485. }
  486. private void assertIteration(FileMode type, String pathName)
  487. throws IOException {
  488. assertIteration(type, pathName, Collections.<Attribute> emptyList());
  489. }
  490. private void assertIteration(FileMode type, String pathName,
  491. Collection<Attribute> expectedAttrs) throws IOException {
  492. assertTrue("walk has entry", walk.next());
  493. assertEquals(pathName, walk.getPathString());
  494. assertEquals(type, walk.getFileMode(0));
  495. if (expectedAttrs != null) {
  496. assertEquals(new ArrayList<>(expectedAttrs),
  497. new ArrayList<>(walk.getAttributes().getAll()));
  498. }
  499. if (D.equals(type))
  500. walk.enterSubtree();
  501. }
  502. /**
  503. * @param globalAttributesContent
  504. * @param infoAttributesContent
  505. * @param rootAttributesContent
  506. * @param subDirAttributesContent
  507. * @throws Exception
  508. * Setup a repo with .gitattributes files and a test file
  509. * sub/a.txt
  510. */
  511. private void setupRepo(
  512. String globalAttributesContent,
  513. String infoAttributesContent, String rootAttributesContent, String subDirAttributesContent)
  514. throws Exception {
  515. FileBasedConfig config = db.getConfig();
  516. if (globalAttributesContent != null) {
  517. File f = new File(db.getDirectory(), "global/attributes");
  518. write(f, globalAttributesContent);
  519. config.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
  520. ConfigConstants.CONFIG_KEY_ATTRIBUTESFILE,
  521. f.getAbsolutePath());
  522. }
  523. if (infoAttributesContent != null) {
  524. File f = new File(db.getDirectory(), Constants.INFO_ATTRIBUTES);
  525. write(f, infoAttributesContent);
  526. }
  527. config.save();
  528. if (rootAttributesContent != null) {
  529. writeAttributesFile(Constants.DOT_GIT_ATTRIBUTES,
  530. rootAttributesContent);
  531. }
  532. if (subDirAttributesContent != null) {
  533. writeAttributesFile("sub/" + Constants.DOT_GIT_ATTRIBUTES,
  534. subDirAttributesContent);
  535. }
  536. writeTrashFile("sub/a.txt", "a");
  537. }
  538. private void writeAttributesFile(String name, String... rules)
  539. throws IOException {
  540. StringBuilder data = new StringBuilder();
  541. for (String line : rules)
  542. data.append(line + "\n");
  543. writeTrashFile(name, data.toString());
  544. }
  545. private TreeWalk beginWalk() {
  546. TreeWalk newWalk = new TreeWalk(db);
  547. newWalk.addTree(new FileTreeIterator(db));
  548. return newWalk;
  549. }
  550. private void endWalk() throws IOException {
  551. assertFalse("Not all files tested", walk.next());
  552. }
  553. }