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