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