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 20KB

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