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