View Javadoc
1   /*
2    * Copyright (C) 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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  
12  import static org.junit.Assert.assertArrayEquals;
13  import static org.junit.Assert.assertEquals;
14  import static org.junit.Assert.assertTrue;
15  import static org.junit.Assert.fail;
16  
17  import java.io.BufferedInputStream;
18  import java.io.File;
19  import java.io.InputStream;
20  import java.nio.charset.StandardCharsets;
21  import java.nio.file.Files;
22  import java.util.Arrays;
23  
24  import org.eclipse.jgit.api.Git;
25  import org.eclipse.jgit.api.ResetCommand.ResetType;
26  import org.eclipse.jgit.dircache.DirCache;
27  import org.eclipse.jgit.dircache.DirCacheEntry;
28  import org.eclipse.jgit.junit.RepositoryTestCase;
29  import org.eclipse.jgit.lib.ConfigConstants;
30  import org.eclipse.jgit.lib.Constants;
31  import org.eclipse.jgit.storage.file.FileBasedConfig;
32  import org.eclipse.jgit.util.IO;
33  import org.eclipse.jgit.util.RawParseUtils;
34  import org.junit.Test;
35  
36  /**
37   * End-to-end tests for some attribute combinations. Writes files, commit them,
38   * examines the index, deletes the files, performs a hard reset and checks file
39   * contents again.
40   */
41  public class AttributeFileTests extends RepositoryTestCase {
42  
43  	@Test
44  	public void testTextAutoCoreEolCoreAutoCrLfInput() throws Exception {
45  		FileBasedConfig cfg = db.getConfig();
46  		cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
47  				ConfigConstants.CONFIG_KEY_AUTOCRLF, false);
48  		cfg.save();
49  		final String content = "Line1\nLine2\n";
50  		try (Git git = Git.wrap(db)) {
51  			writeTrashFile(".gitattributes", "* text=auto");
52  			File dummy = writeTrashFile("dummy.txt", content);
53  			git.add().addFilepattern(".").call();
54  			git.commit().setMessage("Commit with LF").call();
55  			assertEquals("Unexpected index state",
56  					"[.gitattributes, mode:100644, content:* text=auto]"
57  							+ "[dummy.txt, mode:100644, content:" + content
58  							+ ']',
59  					indexState(CONTENT));
60  			assertTrue("Should be able to delete " + dummy, dummy.delete());
61  			cfg.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
62  					ConfigConstants.CONFIG_KEY_EOL, "crlf");
63  			cfg.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
64  					ConfigConstants.CONFIG_KEY_AUTOCRLF, "input");
65  			cfg.save();
66  			git.reset().setMode(ResetType.HARD).call();
67  			assertTrue("File " + dummy + "should exist", dummy.isFile());
68  			String textFile = RawParseUtils.decode(IO.readFully(dummy, 512));
69  			assertEquals("Unexpected text content", content, textFile);
70  		}
71  	}
72  
73  	@Test
74  	public void testTextAutoEolLf() throws Exception {
75  		writeTrashFile(".gitattributes", "* text=auto eol=lf");
76  		performTest("Test\r\nFile", "Test\nFile", "Test\nFile");
77  	}
78  
79  	@Test
80  	public void testTextAutoEolCrLf() throws Exception {
81  		writeTrashFile(".gitattributes", "* text=auto eol=crlf");
82  		performTest("Test\r\nFile", "Test\nFile", "Test\r\nFile");
83  	}
84  
85  	private void performTest(String initial, String index, String finalText)
86  			throws Exception {
87  		File dummy = writeTrashFile("dummy.foo", initial);
88  		byte[] data = readTestResource("add.png");
89  		assertTrue("Expected some binary data", data.length > 100);
90  		File binary = writeTrashFile("add.png", "");
91  		Files.write(binary.toPath(), data);
92  		try (Git git = Git.wrap(db)) {
93  			git.add().addFilepattern(".").call();
94  			git.commit().setMessage("test commit").call();
95  			// binary should be unchanged, dummy should match "index"
96  			verifyIndexContent("dummy.foo",
97  					index.getBytes(StandardCharsets.UTF_8));
98  			verifyIndexContent("add.png", data);
99  			assertTrue("Should be able to delete " + dummy, dummy.delete());
100 			assertTrue("Should be able to delete " + binary, binary.delete());
101 			git.reset().setMode(ResetType.HARD).call();
102 			assertTrue("File " + dummy + " should exist", dummy.isFile());
103 			assertTrue("File " + binary + " should exist", binary.isFile());
104 			// binary should be unchanged, dummy should match "finalText"
105 			String textFile = RawParseUtils.decode(IO.readFully(dummy, 512));
106 			assertEquals("Unexpected text content", finalText, textFile);
107 			byte[] binaryFile = IO.readFully(binary, 512);
108 			assertArrayEquals("Unexpected binary content", data, binaryFile);
109 		}
110 	}
111 
112 	private byte[] readTestResource(String name) throws Exception {
113 		try (InputStream in = new BufferedInputStream(
114 				getClass().getResourceAsStream(name))) {
115 			byte[] data = new byte[512];
116 			int read = in.read(data);
117 			if (read == data.length) {
118 				return data;
119 			}
120 			return Arrays.copyOf(data, read);
121 		}
122 	}
123 
124 	private void verifyIndexContent(String path, byte[] expectedContent)
125 			throws Exception {
126 		DirCache dc = db.readDirCache();
127 		for (int i = 0; i < dc.getEntryCount(); ++i) {
128 			DirCacheEntry entry = dc.getEntry(i);
129 			if (path.equals(entry.getPathString())) {
130 				byte[] data = db.open(entry.getObjectId(), Constants.OBJ_BLOB)
131 						.getCachedBytes();
132 				assertArrayEquals("Unexpected index content for " + path,
133 						expectedContent, data);
134 				return;
135 			}
136 		}
137 		fail("Path not found in index: " + path);
138 	}
139 }