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.Arrays;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Set;
25
26 import org.eclipse.jgit.api.Git;
27 import org.eclipse.jgit.api.errors.GitAPIException;
28 import org.eclipse.jgit.api.errors.NoFilepatternException;
29 import org.eclipse.jgit.attributes.Attribute.State;
30 import org.eclipse.jgit.dircache.DirCacheIterator;
31 import org.eclipse.jgit.errors.NoWorkTreeException;
32 import org.eclipse.jgit.junit.JGitTestUtil;
33 import org.eclipse.jgit.junit.RepositoryTestCase;
34 import org.eclipse.jgit.lib.FileMode;
35 import org.eclipse.jgit.lib.Repository;
36 import org.eclipse.jgit.treewalk.FileTreeIterator;
37 import org.eclipse.jgit.treewalk.TreeWalk;
38 import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
39 import org.junit.After;
40 import org.junit.Before;
41 import org.junit.Test;
42
43
44
45
46
47
48 public class TreeWalkAttributeTest extends RepositoryTestCase {
49
50 private static final FileMode M = FileMode.MISSING;
51
52 private static final FileMode D = FileMode.TREE;
53
54 private static final FileMode F = FileMode.REGULAR_FILE;
55
56 private static Attribute EOL_CRLF = new Attribute("eol", "crlf");
57
58 private static Attribute EOL_LF = new Attribute("eol", "lf");
59
60 private static Attribute TEXT_SET = new Attribute("text", State.SET);
61
62 private static Attribute TEXT_UNSET = new Attribute("text", State.UNSET);
63
64 private static Attribute DELTA_UNSET = new Attribute("delta", State.UNSET);
65
66 private static Attribute DELTA_SET = new Attribute("delta", State.SET);
67
68 private static Attribute CUSTOM_GLOBAL = new Attribute("custom", "global");
69
70 private static Attribute CUSTOM_INFO = new Attribute("custom", "info");
71
72 private static Attribute CUSTOM_ROOT = new Attribute("custom", "root");
73
74 private static Attribute CUSTOM_PARENT = new Attribute("custom", "parent");
75
76 private static Attribute CUSTOM_CURRENT = new Attribute("custom", "current");
77
78 private static Attribute CUSTOM2_UNSET = new Attribute("custom2",
79 State.UNSET);
80
81 private static Attribute CUSTOM2_SET = new Attribute("custom2", State.SET);
82
83 private TreeWalk walk;
84
85 private TreeWalk ci_walk;
86
87 private Git git;
88
89 private File customAttributeFile;
90
91 @Override
92 @Before
93 public void setUp() throws Exception {
94 super.setUp();
95 git = new Git(db);
96 }
97
98 @Override
99 @After
100 public void tearDown() throws Exception {
101 if (walk != null) {
102 walk.close();
103 }
104 if (ci_walk != null) {
105 ci_walk.close();
106 }
107 super.tearDown();
108 if (customAttributeFile != null)
109 customAttributeFile.delete();
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123
124 @Test
125 public void testCheckinCheckoutDifferences() throws IOException,
126 NoFilepatternException, GitAPIException {
127
128 writeGlobalAttributeFile("globalAttributesFile", "*.txt -custom2");
129 writeAttributesFile(".git/info/attributes", "*.txt eol=crlf");
130 writeAttributesFile(".gitattributes", "*.txt custom=root");
131 writeAttributesFile("level1/.gitattributes", "*.txt text");
132 writeAttributesFile("level1/level2/.gitattributes", "*.txt -delta");
133
134 writeTrashFile("l0.txt", "");
135
136 writeTrashFile("level1/l1.txt", "");
137
138 writeTrashFile("level1/level2/l2.txt", "");
139
140 git.add().addFilepattern(".").call();
141
142 beginWalk();
143
144
145 writeGlobalAttributeFile("globalAttributesFile", "*.txt custom2");
146 writeAttributesFile(".git/info/attributes", "*.txt eol=lf");
147 writeAttributesFile(".gitattributes", "*.txt custom=info");
148 writeAttributesFile("level1/.gitattributes", "*.txt -text");
149 writeAttributesFile("level1/level2/.gitattributes", "*.txt delta");
150
151 assertEntry(F, ".gitattributes");
152 assertEntry(F, "l0.txt", asSet(EOL_LF, CUSTOM_INFO, CUSTOM2_SET),
153 asSet(EOL_LF, CUSTOM_ROOT, CUSTOM2_SET));
154
155 assertEntry(D, "level1");
156 assertEntry(F, "level1/.gitattributes");
157 assertEntry(F, "level1/l1.txt",
158 asSet(EOL_LF, CUSTOM_INFO, CUSTOM2_SET, TEXT_UNSET),
159 asSet(EOL_LF, CUSTOM_ROOT, CUSTOM2_SET, TEXT_SET));
160
161 assertEntry(D, "level1/level2");
162 assertEntry(F, "level1/level2/.gitattributes");
163 assertEntry(F, "level1/level2/l2.txt",
164 asSet(EOL_LF, CUSTOM_INFO, CUSTOM2_SET, TEXT_UNSET, DELTA_SET),
165 asSet(EOL_LF, CUSTOM_ROOT, CUSTOM2_SET, TEXT_SET, DELTA_UNSET));
166
167 endWalk();
168 }
169
170
171
172
173
174
175
176
177
178 @Test
179 public void testIndexOnly() throws IOException, NoFilepatternException,
180 GitAPIException {
181 List<File> attrFiles = new ArrayList<>();
182 attrFiles.add(writeGlobalAttributeFile("globalAttributesFile",
183 "*.txt -custom2"));
184 attrFiles.add(writeAttributesFile(".git/info/attributes",
185 "*.txt eol=crlf"));
186 attrFiles
187 .add(writeAttributesFile(".gitattributes", "*.txt custom=root"));
188 attrFiles
189 .add(writeAttributesFile("level1/.gitattributes", "*.txt text"));
190 attrFiles.add(writeAttributesFile("level1/level2/.gitattributes",
191 "*.txt -delta"));
192
193 writeTrashFile("l0.txt", "");
194
195 writeTrashFile("level1/l1.txt", "");
196
197 writeTrashFile("level1/level2/l2.txt", "");
198
199 git.add().addFilepattern(".").call();
200
201
202 for (File attrFile : attrFiles)
203 attrFile.delete();
204
205 beginWalk();
206
207 assertEntry(M, ".gitattributes");
208 assertEntry(F, "l0.txt", asSet(CUSTOM_ROOT));
209
210 assertEntry(D, "level1");
211 assertEntry(M, "level1/.gitattributes");
212 assertEntry(F, "level1/l1.txt",
213
214 asSet(CUSTOM_ROOT, TEXT_SET));
215
216 assertEntry(D, "level1/level2");
217 assertEntry(M, "level1/level2/.gitattributes");
218 assertEntry(F, "level1/level2/l2.txt",
219
220 asSet(CUSTOM_ROOT, TEXT_SET, DELTA_UNSET));
221
222 endWalk();
223 }
224
225
226
227
228
229
230
231
232
233 @Test
234 public void testIndexOnly2()
235 throws IOException, NoFilepatternException, GitAPIException {
236 File l2 = writeTrashFile("level1/level2/l2.txt", "");
237 writeTrashFile("level1/level2/l1.txt", "");
238
239 git.add().addFilepattern(".").call();
240
241 writeAttributesFile(".gitattributes", "*.txt custom=root");
242 assertTrue(l2.delete());
243
244 beginWalk();
245
246 assertEntry(F, ".gitattributes");
247 assertEntry(D, "level1");
248 assertEntry(D, "level1/level2");
249 assertEntry(F, "level1/level2/l1.txt", asSet(CUSTOM_ROOT));
250 assertEntry(M, "level1/level2/l2.txt", asSet(CUSTOM_ROOT));
251
252 endWalk();
253 }
254
255
256
257
258
259
260
261
262
263
264
265 @Test
266 public void testRules() throws IOException, NoFilepatternException,
267 GitAPIException {
268 writeAttributesFile(".git/info/attributes", "windows* eol=crlf");
269
270 writeAttributesFile(".gitattributes", "*.txt eol=lf");
271 writeTrashFile("windows.file", "");
272 writeTrashFile("windows.txt", "");
273 writeTrashFile("readme.txt", "");
274
275 writeAttributesFile("src/config/.gitattributes", "*.txt -delta");
276 writeTrashFile("src/config/readme.txt", "");
277 writeTrashFile("src/config/windows.file", "");
278 writeTrashFile("src/config/windows.txt", "");
279
280 beginWalk();
281
282 git.add().addFilepattern(".").call();
283
284 assertEntry(F, ".gitattributes");
285 assertEntry(F, "readme.txt", asSet(EOL_LF));
286
287 assertEntry(D, "src");
288 assertEntry(D, "src/config");
289 assertEntry(F, "src/config/.gitattributes");
290 assertEntry(F, "src/config/readme.txt", asSet(DELTA_UNSET, EOL_LF));
291 assertEntry(F, "src/config/windows.file", asSet(EOL_CRLF));
292 assertEntry(F, "src/config/windows.txt", asSet(DELTA_UNSET, EOL_CRLF));
293
294 assertEntry(F, "windows.file", asSet(EOL_CRLF));
295 assertEntry(F, "windows.txt", asSet(EOL_CRLF));
296
297 endWalk();
298 }
299
300
301
302
303
304
305
306 @Test
307 public void testNoAttributes() throws IOException {
308 writeTrashFile("l0.txt", "");
309 writeTrashFile("level1/l1.txt", "");
310 writeTrashFile("level1/level2/l2.txt", "");
311
312 beginWalk();
313
314 assertEntry(F, "l0.txt");
315
316 assertEntry(D, "level1");
317 assertEntry(F, "level1/l1.txt");
318
319 assertEntry(D, "level1/level2");
320 assertEntry(F, "level1/level2/l2.txt");
321
322 endWalk();
323 }
324
325
326
327
328
329
330 @Test
331 public void testEmptyGitAttributeFile() throws IOException {
332 writeAttributesFile(".git/info/attributes", "");
333 writeTrashFile("l0.txt", "");
334 writeAttributesFile(".gitattributes", "");
335 writeTrashFile("level1/l1.txt", "");
336 writeTrashFile("level1/level2/l2.txt", "");
337
338 beginWalk();
339
340 assertEntry(F, ".gitattributes");
341 assertEntry(F, "l0.txt");
342
343 assertEntry(D, "level1");
344 assertEntry(F, "level1/l1.txt");
345
346 assertEntry(D, "level1/level2");
347 assertEntry(F, "level1/level2/l2.txt");
348
349 endWalk();
350 }
351
352 @Test
353 public void testNoMatchingAttributes() throws IOException {
354 writeAttributesFile(".git/info/attributes", "*.java delta");
355 writeAttributesFile(".gitattributes", "*.java -delta");
356 writeAttributesFile("levelA/.gitattributes", "*.java eol=lf");
357 writeAttributesFile("levelB/.gitattributes", "*.txt eol=lf");
358
359 writeTrashFile("levelA/lA.txt", "");
360
361 beginWalk();
362
363 assertEntry(F, ".gitattributes");
364
365 assertEntry(D, "levelA");
366 assertEntry(F, "levelA/.gitattributes");
367 assertEntry(F, "levelA/lA.txt");
368
369 assertEntry(D, "levelB");
370 assertEntry(F, "levelB/.gitattributes");
371
372 endWalk();
373 }
374
375
376
377
378
379
380 @Test
381 public void testPrecedenceInfo() throws IOException {
382 writeGlobalAttributeFile("globalAttributesFile", "*.txt custom=global");
383 writeAttributesFile(".git/info/attributes", "*.txt custom=info");
384 writeAttributesFile(".gitattributes", "*.txt custom=root");
385 writeAttributesFile("level1/.gitattributes", "*.txt custom=parent");
386 writeAttributesFile("level1/level2/.gitattributes",
387 "*.txt custom=current");
388
389 writeTrashFile("level1/level2/file.txt", "");
390
391 beginWalk();
392
393 assertEntry(F, ".gitattributes");
394
395 assertEntry(D, "level1");
396 assertEntry(F, "level1/.gitattributes");
397
398 assertEntry(D, "level1/level2");
399 assertEntry(F, "level1/level2/.gitattributes");
400 assertEntry(F, "level1/level2/file.txt", asSet(CUSTOM_INFO));
401
402 endWalk();
403 }
404
405
406
407
408
409
410
411 @Test
412 public void testPrecedenceCurrent() throws IOException {
413 writeGlobalAttributeFile("globalAttributesFile", "*.txt custom=global");
414 writeAttributesFile(".gitattributes", "*.txt custom=root");
415 writeAttributesFile("level1/.gitattributes", "*.txt custom=parent");
416 writeAttributesFile("level1/level2/.gitattributes",
417 "*.txt custom=current");
418
419 writeTrashFile("level1/level2/file.txt", "");
420
421 beginWalk();
422
423 assertEntry(F, ".gitattributes");
424
425 assertEntry(D, "level1");
426 assertEntry(F, "level1/.gitattributes");
427
428 assertEntry(D, "level1/level2");
429 assertEntry(F, "level1/level2/.gitattributes");
430 assertEntry(F, "level1/level2/file.txt", asSet(CUSTOM_CURRENT));
431
432 endWalk();
433 }
434
435
436
437
438
439
440 @Test
441 public void testPrecedenceParent() throws IOException {
442 writeGlobalAttributeFile("globalAttributesFile", "*.txt custom=global");
443 writeAttributesFile(".gitattributes", "*.txt custom=root");
444 writeAttributesFile("level1/.gitattributes", "*.txt custom=parent");
445
446 writeTrashFile("level1/level2/file.txt", "");
447
448 beginWalk();
449
450 assertEntry(F, ".gitattributes");
451
452 assertEntry(D, "level1");
453 assertEntry(F, "level1/.gitattributes");
454
455 assertEntry(D, "level1/level2");
456 assertEntry(F, "level1/level2/file.txt", asSet(CUSTOM_PARENT));
457
458 endWalk();
459 }
460
461
462
463
464
465
466 @Test
467 public void testPrecedenceRoot() throws IOException {
468 writeGlobalAttributeFile("globalAttributesFile", "*.txt custom=global");
469 writeAttributesFile(".gitattributes", "*.txt custom=root");
470
471 writeTrashFile("level1/level2/file.txt", "");
472
473 beginWalk();
474
475 assertEntry(F, ".gitattributes");
476
477 assertEntry(D, "level1");
478
479 assertEntry(D, "level1/level2");
480 assertEntry(F, "level1/level2/file.txt", asSet(CUSTOM_ROOT));
481
482 endWalk();
483 }
484
485
486
487
488
489
490 @Test
491 public void testPrecedenceGlobal() throws IOException {
492 writeGlobalAttributeFile("globalAttributesFile", "*.txt custom=global");
493
494 writeTrashFile("level1/level2/file.txt", "");
495
496 beginWalk();
497
498 assertEntry(D, "level1");
499
500 assertEntry(D, "level1/level2");
501 assertEntry(F, "level1/level2/file.txt", asSet(CUSTOM_GLOBAL));
502
503 endWalk();
504 }
505
506
507
508
509
510
511
512
513
514
515
516 @Test
517 public void testHierarchyBothIterator() throws IOException,
518 NoFilepatternException, GitAPIException {
519 writeAttributesFile(".git/info/attributes", "*.global eol=crlf");
520 writeAttributesFile(".gitattributes", "*.local eol=lf");
521 writeAttributesFile("level1/.gitattributes", "*.local text");
522 writeAttributesFile("level1/level2/.gitattributes", "*.local -text");
523
524 writeTrashFile("l0.global", "");
525 writeTrashFile("l0.local", "");
526
527 writeTrashFile("level1/l1.global", "");
528 writeTrashFile("level1/l1.local", "");
529
530 writeTrashFile("level1/level2/l2.global", "");
531 writeTrashFile("level1/level2/l2.local", "");
532
533 beginWalk();
534
535 git.add().addFilepattern(".").call();
536
537 assertEntry(F, ".gitattributes");
538 assertEntry(F, "l0.global", asSet(EOL_CRLF));
539 assertEntry(F, "l0.local", asSet(EOL_LF));
540
541 assertEntry(D, "level1");
542 assertEntry(F, "level1/.gitattributes");
543 assertEntry(F, "level1/l1.global", asSet(EOL_CRLF));
544 assertEntry(F, "level1/l1.local", asSet(EOL_LF, TEXT_SET));
545
546 assertEntry(D, "level1/level2");
547 assertEntry(F, "level1/level2/.gitattributes");
548 assertEntry(F, "level1/level2/l2.global", asSet(EOL_CRLF));
549 assertEntry(F, "level1/level2/l2.local", asSet(EOL_LF, TEXT_UNSET));
550
551 endWalk();
552
553 }
554
555
556
557
558
559
560
561
562
563
564
565 @Test
566 public void testHierarchyWorktreeOnly()
567 throws IOException, NoFilepatternException, GitAPIException {
568 writeAttributesFile(".git/info/attributes", "*.global eol=crlf");
569 writeAttributesFile(".gitattributes", "*.local eol=lf");
570 writeAttributesFile("level1/.gitattributes", "*.local text");
571 writeAttributesFile("level1/level2/.gitattributes", "*.local -text");
572
573 writeTrashFile("l0.global", "");
574 writeTrashFile("l0.local", "");
575
576 writeTrashFile("level1/l1.global", "");
577 writeTrashFile("level1/l1.local", "");
578
579 writeTrashFile("level1/level2/l2.global", "");
580 writeTrashFile("level1/level2/l2.local", "");
581
582 beginWalk();
583
584 assertEntry(F, ".gitattributes");
585 assertEntry(F, "l0.global", asSet(EOL_CRLF));
586 assertEntry(F, "l0.local", asSet(EOL_LF));
587
588 assertEntry(D, "level1");
589 assertEntry(F, "level1/.gitattributes");
590 assertEntry(F, "level1/l1.global", asSet(EOL_CRLF));
591 assertEntry(F, "level1/l1.local", asSet(EOL_LF, TEXT_SET));
592
593 assertEntry(D, "level1/level2");
594 assertEntry(F, "level1/level2/.gitattributes");
595 assertEntry(F, "level1/level2/l2.global", asSet(EOL_CRLF));
596 assertEntry(F, "level1/level2/l2.local", asSet(EOL_LF, TEXT_UNSET));
597
598 endWalk();
599
600 }
601
602
603
604
605
606
607
608 @Test
609 public void testAggregation() throws IOException {
610 writeGlobalAttributeFile("globalAttributesFile", "*.txt -custom2");
611 writeAttributesFile(".git/info/attributes", "*.txt eol=crlf");
612 writeAttributesFile(".gitattributes", "*.txt custom=root");
613 writeAttributesFile("level1/.gitattributes", "*.txt text");
614 writeAttributesFile("level1/level2/.gitattributes", "*.txt -delta");
615
616 writeTrashFile("l0.txt", "");
617
618 writeTrashFile("level1/l1.txt", "");
619
620 writeTrashFile("level1/level2/l2.txt", "");
621
622 beginWalk();
623
624 assertEntry(F, ".gitattributes");
625 assertEntry(F, "l0.txt", asSet(EOL_CRLF, CUSTOM_ROOT, CUSTOM2_UNSET));
626
627 assertEntry(D, "level1");
628 assertEntry(F, "level1/.gitattributes");
629 assertEntry(F, "level1/l1.txt",
630 asSet(EOL_CRLF, CUSTOM_ROOT, TEXT_SET, CUSTOM2_UNSET));
631
632 assertEntry(D, "level1/level2");
633 assertEntry(F, "level1/level2/.gitattributes");
634 assertEntry(
635 F,
636 "level1/level2/l2.txt",
637 asSet(EOL_CRLF, CUSTOM_ROOT, TEXT_SET, DELTA_UNSET,
638 CUSTOM2_UNSET));
639
640 endWalk();
641
642 }
643
644
645
646
647
648
649
650 @Test
651 public void testOverriding() throws IOException {
652 writeAttributesFile(".git/info/attributes",
653
654 "*.txt custom=current",
655 "*.txt custom=parent",
656 "*.txt custom=root",
657 "*.txt custom=info",
658
659 "*.txt delta",
660 "*.txt -delta",
661
662 "*.txt eol=lf",
663 "*.txt eol=crlf",
664
665 "*.txt text",
666 "*.txt -text");
667
668 writeTrashFile("l0.txt", "");
669 beginWalk();
670
671 assertEntry(F, "l0.txt",
672 asSet(TEXT_UNSET, EOL_CRLF, DELTA_UNSET, CUSTOM_INFO));
673
674 endWalk();
675 }
676
677
678
679
680
681
682
683 @Test
684 public void testOverriding2() throws IOException {
685 writeAttributesFile(".git/info/attributes",
686 "*.txt custom=current custom=parent custom=root custom=info",
687 "*.txt delta -delta",
688 "*.txt eol=lf eol=crlf",
689 "*.txt text -text");
690 writeTrashFile("l0.txt", "");
691 beginWalk();
692
693 assertEntry(F, "l0.txt",
694 asSet(TEXT_UNSET, EOL_CRLF, DELTA_UNSET, CUSTOM_INFO));
695
696 endWalk();
697 }
698
699 @Test
700 public void testRulesInherited() throws Exception {
701 writeAttributesFile(".gitattributes", "**/*.txt eol=lf");
702 writeTrashFile("src/config/readme.txt", "");
703 writeTrashFile("src/config/windows.file", "");
704
705 beginWalk();
706
707 assertEntry(F, ".gitattributes");
708 assertEntry(D, "src");
709 assertEntry(D, "src/config");
710
711 assertEntry(F, "src/config/readme.txt", asSet(EOL_LF));
712 assertEntry(F, "src/config/windows.file",
713 Collections.<Attribute> emptySet());
714
715 endWalk();
716 }
717
718 private void beginWalk() throws NoWorkTreeException, IOException {
719 walk = new TreeWalk(db);
720 walk.addTree(new FileTreeIterator(db));
721 walk.addTree(new DirCacheIterator(db.readDirCache()));
722
723 ci_walk = new TreeWalk(db);
724 ci_walk.setOperationType(OperationType.CHECKIN_OP);
725 ci_walk.addTree(new FileTreeIterator(db));
726 ci_walk.addTree(new DirCacheIterator(db.readDirCache()));
727 }
728
729
730
731
732
733
734
735
736
737
738 private void assertEntry(FileMode type, String pathName,
739 Set<Attribute> forBothOperaiton) throws IOException {
740 assertEntry(type, pathName, forBothOperaiton, forBothOperaiton);
741 }
742
743
744
745
746
747
748
749
750 private void assertEntry(FileMode type, String pathName) throws IOException {
751 assertEntry(type, pathName, Collections.<Attribute> emptySet(),
752 Collections.<Attribute> emptySet());
753 }
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770 private void assertEntry(FileMode type, String pathName,
771 Set<Attribute> checkinAttributes, Set<Attribute> checkoutAttributes)
772 throws IOException {
773 assertTrue("walk has entry", walk.next());
774 assertTrue("walk has entry", ci_walk.next());
775 assertEquals(pathName, walk.getPathString());
776 assertEquals(type, walk.getFileMode(0));
777
778 assertEquals(checkinAttributes,
779 asSet(ci_walk.getAttributes().getAll()));
780 assertEquals(checkoutAttributes,
781 asSet(walk.getAttributes().getAll()));
782
783 if (D.equals(type)) {
784 walk.enterSubtree();
785 ci_walk.enterSubtree();
786 }
787 }
788
789 private static Set<Attribute> asSet(Collection<Attribute> attributes) {
790 Set<Attribute> ret = new HashSet<>();
791 for (Attribute a : attributes) {
792 ret.add(a);
793 }
794 return (ret);
795 }
796
797 private File writeAttributesFile(String name, String... rules)
798 throws IOException {
799 StringBuilder data = new StringBuilder();
800 for (String line : rules)
801 data.append(line + "\n");
802 return writeTrashFile(name, data.toString());
803 }
804
805
806
807
808
809
810
811
812
813
814 private File writeGlobalAttributeFile(String fileName, String... attributes)
815 throws IOException {
816 customAttributeFile = File.createTempFile("tmp_", fileName, null);
817 customAttributeFile.deleteOnExit();
818 StringBuilder attributesFileContent = new StringBuilder();
819 for (String attr : attributes) {
820 attributesFileContent.append(attr).append("\n");
821 }
822 JGitTestUtil.write(customAttributeFile,
823 attributesFileContent.toString());
824 db.getConfig().setString("core", null, "attributesfile",
825 customAttributeFile.getAbsolutePath());
826 return customAttributeFile;
827 }
828
829 static Set<Attribute> asSet(Attribute... attrs) {
830 HashSet<Attribute> result = new HashSet<>();
831 result.addAll(Arrays.asList(attrs));
832 return result;
833 }
834
835 private void endWalk() throws IOException {
836 assertFalse("Not all files tested", walk.next());
837 assertFalse("Not all files tested", ci_walk.next());
838 }
839 }