View Javadoc
1   /*
2    * Copyright (C) 2011, Christian Halstrick <christian.halstrick@sap.com> 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.api;
11  
12  import static org.junit.Assert.assertEquals;
13  import static org.junit.Assert.assertFalse;
14  import static org.junit.Assert.assertTrue;
15  import static org.junit.Assume.assumeTrue;
16  
17  import java.io.File;
18  import java.io.IOException;
19  
20  import org.eclipse.jgit.api.errors.GitAPIException;
21  import org.eclipse.jgit.api.errors.NoFilepatternException;
22  import org.eclipse.jgit.errors.NoWorkTreeException;
23  import org.eclipse.jgit.junit.RepositoryTestCase;
24  import org.eclipse.jgit.lib.Repository;
25  import org.eclipse.jgit.lib.Sets;
26  import org.eclipse.jgit.storage.file.FileBasedConfig;
27  import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
28  import org.eclipse.jgit.util.FS;
29  import org.junit.Test;
30  
31  public class StatusCommandTest extends RepositoryTestCase {
32  
33  	@Test
34  	public void testEmptyStatus() throws NoWorkTreeException,
35  			GitAPIException {
36  		try (Git git = new Git(db)) {
37  			Status stat = git.status().call();
38  			assertEquals(0, stat.getAdded().size());
39  			assertEquals(0, stat.getChanged().size());
40  			assertEquals(0, stat.getMissing().size());
41  			assertEquals(0, stat.getModified().size());
42  			assertEquals(0, stat.getRemoved().size());
43  			assertEquals(0, stat.getUntracked().size());
44  		}
45  	}
46  
47  	@Test
48  	public void testDifferentStates() throws IOException,
49  			NoFilepatternException, GitAPIException {
50  		try (Git git = new Git(db)) {
51  			writeTrashFile("a", "content of a");
52  			writeTrashFile("b", "content of b");
53  			writeTrashFile("c", "content of c");
54  			git.add().addFilepattern("a").addFilepattern("b").call();
55  			Status stat = git.status().call();
56  			assertEquals(Sets.of("a", "b"), stat.getAdded());
57  			assertEquals(0, stat.getChanged().size());
58  			assertEquals(0, stat.getMissing().size());
59  			assertEquals(0, stat.getModified().size());
60  			assertEquals(0, stat.getRemoved().size());
61  			assertEquals(Sets.of("c"), stat.getUntracked());
62  			git.commit().setMessage("initial").call();
63  
64  			writeTrashFile("a", "modified content of a");
65  			writeTrashFile("b", "modified content of b");
66  			writeTrashFile("d", "content of d");
67  			git.add().addFilepattern("a").addFilepattern("d").call();
68  			writeTrashFile("a", "again modified content of a");
69  			stat = git.status().call();
70  			assertEquals(Sets.of("d"), stat.getAdded());
71  			assertEquals(Sets.of("a"), stat.getChanged());
72  			assertEquals(0, stat.getMissing().size());
73  			assertEquals(Sets.of("b", "a"), stat.getModified());
74  			assertEquals(0, stat.getRemoved().size());
75  			assertEquals(Sets.of("c"), stat.getUntracked());
76  			git.add().addFilepattern(".").call();
77  			git.commit().setMessage("second").call();
78  
79  			stat = git.status().call();
80  			assertEquals(0, stat.getAdded().size());
81  			assertEquals(0, stat.getChanged().size());
82  			assertEquals(0, stat.getMissing().size());
83  			assertEquals(0, stat.getModified().size());
84  			assertEquals(0, stat.getRemoved().size());
85  			assertEquals(0, stat.getUntracked().size());
86  
87  			deleteTrashFile("a");
88  			assertFalse(new File(git.getRepository().getWorkTree(), "a").exists());
89  			git.add().addFilepattern("a").setUpdate(true).call();
90  			writeTrashFile("a", "recreated content of a");
91  			stat = git.status().call();
92  			assertEquals(0, stat.getAdded().size());
93  			assertEquals(0, stat.getChanged().size());
94  			assertEquals(0, stat.getMissing().size());
95  			assertEquals(0, stat.getModified().size());
96  			assertEquals(Sets.of("a"), stat.getRemoved());
97  			assertEquals(Sets.of("a"), stat.getUntracked());
98  			git.commit().setMessage("t").call();
99  
100 			writeTrashFile("sub/a", "sub-file");
101 			stat = git.status().call();
102 			assertEquals(1, stat.getUntrackedFolders().size());
103 			assertTrue(stat.getUntrackedFolders().contains("sub"));
104 		}
105 	}
106 
107 	@Test
108 	public void testDifferentStatesWithPaths() throws IOException,
109 			NoFilepatternException, GitAPIException {
110 		try (Git git = new Git(db)) {
111 			writeTrashFile("a", "content of a");
112 			writeTrashFile("D/b", "content of b");
113 			writeTrashFile("D/c", "content of c");
114 			writeTrashFile("D/D/d", "content of d");
115 			git.add().addFilepattern(".").call();
116 
117 			writeTrashFile("a", "new content of a");
118 			writeTrashFile("D/b", "new content of b");
119 			writeTrashFile("D/D/d", "new content of d");
120 
121 
122 			// filter on an not existing path
123 			Status stat = git.status().addPath("x").call();
124 			assertEquals(0, stat.getModified().size());
125 
126 			// filter on an existing file
127 			stat = git.status().addPath("a").call();
128 			assertEquals(Sets.of("a"), stat.getModified());
129 
130 			// filter on an existing folder
131 			stat = git.status().addPath("D").call();
132 			assertEquals(Sets.of("D/b", "D/D/d"), stat.getModified());
133 
134 			// filter on an existing folder and file
135 			stat = git.status().addPath("D/D").addPath("a").call();
136 			assertEquals(Sets.of("a", "D/D/d"), stat.getModified());
137 
138 			// do not filter at all
139 			stat = git.status().call();
140 			assertEquals(Sets.of("a", "D/b", "D/D/d"), stat.getModified());
141 		}
142 	}
143 
144 	@Test
145 	public void testExecutableWithNonNormalizedIndex() throws Exception {
146 		assumeTrue(FS.DETECTED.supportsExecute());
147 		try (Git git = new Git(db)) {
148 			// Commit a file with CR/LF into the index
149 			FileBasedConfig config = db.getConfig();
150 			config.setString("core", null, "autocrlf", "false");
151 			config.save();
152 			File testFile = writeTrashFile("file.txt", "line 1\r\nline 2\r\n");
153 			FS.DETECTED.setExecute(testFile, true);
154 			git.add().addFilepattern("file.txt").call();
155 			git.commit().setMessage("Initial").call();
156 			assertEquals(
157 					"[file.txt, mode:100755, content:line 1\r\nline 2\r\n]",
158 					indexState(CONTENT));
159 			config.setString("core", null, "autocrlf", "true");
160 			config.save();
161 			Status status = git.status().call();
162 			assertTrue("Expected no differences", status.isClean());
163 		}
164 	}
165 
166 	@Test
167 	public void testFolderPrefix() throws Exception {
168 		// "audio" is a prefix of "audio-new" and "audio.new".
169 		try (Git git = new Git(db)) {
170 			// Order here is the git order, but that doesn't really matter.
171 			// They are processed by StatusCommand in this order even if written
172 			// in a different order. Bug 566799 would, when having processed
173 			// audio/foo, remove previously recorded untracked folders that have
174 			// "audio" as a prefix: audio-new and audio.new.
175 			writeTrashFile("audi", "foo", "foo");
176 			writeTrashFile("audio-new", "foo", "foo");
177 			writeTrashFile("audio.new", "foo", "foo");
178 			writeTrashFile("audio", "foo", "foo");
179 			writeTrashFile("audio_new", "foo", "foo");
180 			Status stat = git.status().call();
181 			assertEquals(Sets.of("audi", "audio-new", "audio.new", "audio",
182 					"audio_new"), stat.getUntrackedFolders());
183 		}
184 	}
185 
186 	@Test
187 	public void testNestedCommittedGitRepoAndPathFilter() throws Exception {
188 		commitFile("file.txt", "file", "master");
189 		try (Repository inner = new FileRepositoryBuilder()
190 				.setWorkTree(new File(db.getWorkTree(), "subgit")).build()) {
191 			inner.create();
192 			writeTrashFile("subgit/sub.txt", "sub");
193 			try (Git outerGit = new Git(db); Git innerGit = new Git(inner)) {
194 				innerGit.add().addFilepattern("sub.txt").call();
195 				innerGit.commit().setMessage("Inner commit").call();
196 				outerGit.add().addFilepattern("subgit").call();
197 				outerGit.commit().setMessage("Outer commit").call();
198 				assertTrue(innerGit.status().call().isClean());
199 				assertTrue(outerGit.status().call().isClean());
200 				writeTrashFile("subgit/sub.txt", "sub2");
201 				assertFalse(innerGit.status().call().isClean());
202 				assertFalse(outerGit.status().call().isClean());
203 				assertTrue(
204 						outerGit.status().addPath("file.txt").call().isClean());
205 				assertTrue(outerGit.status().addPath("doesntexist").call()
206 						.isClean());
207 				assertFalse(
208 						outerGit.status().addPath("subgit").call().isClean());
209 			}
210 		}
211 	}
212 
213 }