View Javadoc
1   /*
2    * Copyright (C) 2011, Abhishek Bhatnagar <abhatnag@redhat.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.api;
44  
45  import static org.eclipse.jgit.lib.Constants.DOT_GIT_MODULES;
46  import static org.junit.Assert.assertEquals;
47  import static org.junit.Assert.assertFalse;
48  import static org.junit.Assert.assertTrue;
49  
50  import java.io.File;
51  import java.util.Set;
52  import java.util.TreeSet;
53  
54  import org.eclipse.jgit.api.errors.GitAPIException;
55  import org.eclipse.jgit.errors.NoWorkTreeException;
56  import org.eclipse.jgit.junit.RepositoryTestCase;
57  import org.eclipse.jgit.lib.Repository;
58  import org.junit.Before;
59  import org.junit.Test;
60  
61  /**
62   * Tests for CleanCommand
63   */
64  public class CleanCommandTest extends RepositoryTestCase {
65  	private Git git;
66  
67  	@Override
68  	@Before
69  	public void setUp() throws Exception {
70  		super.setUp();
71  		git = new Git(db);
72  
73  		// create test files
74  		writeTrashFile("File1.txt", "Hello world");
75  		writeTrashFile("File2.txt", "Delete Me");
76  		writeTrashFile("File3.txt", "Delete Me");
77  
78  		// create files in sub-directories.
79  		writeTrashFile("sub-noclean/File1.txt", "Hello world");
80  		writeTrashFile("sub-noclean/File2.txt", "Delete Me");
81  		writeTrashFile("sub-clean/File4.txt", "Delete Me");
82  		writeTrashFile("sub-noclean/Ignored.txt", "Ignored");
83  		writeTrashFile(".gitignore", "/ignored-dir\n/sub-noclean/Ignored.txt");
84  		writeTrashFile("ignored-dir/Ignored2.txt", "Ignored");
85  
86  		// add and commit first file
87  		git.add().addFilepattern("File1.txt").call();
88  		git.add().addFilepattern("sub-noclean/File1.txt").call();
89  		git.add().addFilepattern(".gitignore").call();
90  		git.commit().setMessage("Initial commit").call();
91  	}
92  
93  	@Test
94  	public void testClean() throws NoWorkTreeException, GitAPIException {
95  		// create status
96  		StatusCommand command = git.status();
97  		Status status = command.call();
98  		Set<String> files = status.getUntracked();
99  		assertTrue(files.size() > 0);
100 
101 		// run clean
102 		Set<String> cleanedFiles = git.clean().call();
103 
104 		status = git.status().call();
105 		files = status.getUntracked();
106 
107 		assertTrue(files.size() == 1); // one remains (directories not cleaned)
108 		assertTrue(cleanedFiles.contains("File2.txt"));
109 		assertTrue(cleanedFiles.contains("File3.txt"));
110 		assertTrue(!cleanedFiles.contains("sub-noclean/File1.txt"));
111 		assertTrue(cleanedFiles.contains("sub-noclean/File2.txt"));
112 		assertTrue(!cleanedFiles.contains("sub-clean/File4.txt"));
113 	}
114 
115 	@Test
116 	public void testCleanDirs() throws NoWorkTreeException, GitAPIException {
117 		// create status
118 		StatusCommand command = git.status();
119 		Status status = command.call();
120 		Set<String> files = status.getUntracked();
121 		assertTrue(files.size() > 0);
122 
123 		// run clean
124 		Set<String> cleanedFiles = git.clean().setCleanDirectories(true).call();
125 
126 		status = git.status().call();
127 		files = status.getUntracked();
128 
129 		assertTrue(files.size() == 0);
130 		assertTrue(cleanedFiles.contains("File2.txt"));
131 		assertTrue(cleanedFiles.contains("File3.txt"));
132 		assertTrue(!cleanedFiles.contains("sub-noclean/File1.txt"));
133 		assertTrue(cleanedFiles.contains("sub-noclean/File2.txt"));
134 		assertTrue(cleanedFiles.contains("sub-clean/"));
135 	}
136 
137 	@Test
138 	public void testCleanWithPaths() throws NoWorkTreeException,
139 			GitAPIException {
140 		// create status
141 		StatusCommand command = git.status();
142 		Status status = command.call();
143 		Set<String> files = status.getUntracked();
144 		assertTrue(files.size() > 0);
145 
146 		// run clean with setPaths
147 		Set<String> paths = new TreeSet<>();
148 		paths.add("File3.txt");
149 		Set<String> cleanedFiles = git.clean().setPaths(paths).call();
150 
151 		status = git.status().call();
152 		files = status.getUntracked();
153 		assertTrue(files.size() == 3);
154 		assertTrue(cleanedFiles.contains("File3.txt"));
155 		assertFalse(cleanedFiles.contains("File2.txt"));
156 	}
157 
158 	@Test
159 	public void testCleanWithDryRun() throws NoWorkTreeException,
160 			GitAPIException {
161 		// create status
162 		StatusCommand command = git.status();
163 		Status status = command.call();
164 		Set<String> files = status.getUntracked();
165 		assertTrue(files.size() > 0);
166 
167 		// run clean
168 		Set<String> cleanedFiles = git.clean().setDryRun(true).call();
169 
170 		status = git.status().call();
171 		files = status.getUntracked();
172 
173 		assertEquals(4, files.size());
174 		assertTrue(cleanedFiles.contains("File2.txt"));
175 		assertTrue(cleanedFiles.contains("File3.txt"));
176 		assertTrue(!cleanedFiles.contains("sub-noclean/File1.txt"));
177 		assertTrue(cleanedFiles.contains("sub-noclean/File2.txt"));
178 	}
179 
180 	@Test
181 	public void testCleanDirsWithDryRun() throws NoWorkTreeException,
182 			GitAPIException {
183 		// create status
184 		StatusCommand command = git.status();
185 		Status status = command.call();
186 		Set<String> files = status.getUntracked();
187 		assertTrue(files.size() > 0);
188 
189 		// run clean
190 		Set<String> cleanedFiles = git.clean().setDryRun(true)
191 				.setCleanDirectories(true).call();
192 
193 		status = git.status().call();
194 		files = status.getUntracked();
195 
196 		assertTrue(files.size() == 4);
197 		assertTrue(cleanedFiles.contains("File2.txt"));
198 		assertTrue(cleanedFiles.contains("File3.txt"));
199 		assertTrue(!cleanedFiles.contains("sub-noclean/File1.txt"));
200 		assertTrue(cleanedFiles.contains("sub-noclean/File2.txt"));
201 		assertTrue(cleanedFiles.contains("sub-clean/"));
202 	}
203 
204 	@Test
205 	public void testCleanWithDryRunAndNoIgnore() throws NoWorkTreeException,
206 			GitAPIException {
207 		// run clean
208 		Set<String> cleanedFiles = git.clean().setDryRun(true).setIgnore(false)
209 				.call();
210 
211 		Status status = git.status().call();
212 		Set<String> files = status.getIgnoredNotInIndex();
213 
214 		assertTrue(files.size() == 2);
215 		assertTrue(cleanedFiles.contains("sub-noclean/Ignored.txt"));
216 		assertTrue(!cleanedFiles.contains("ignored-dir/"));
217 	}
218 
219 	@Test
220 	public void testCleanDirsWithDryRunAndNoIgnore()
221 			throws NoWorkTreeException, GitAPIException {
222 		// run clean
223 		Set<String> cleanedFiles = git.clean().setDryRun(true).setIgnore(false)
224 				.setCleanDirectories(true).call();
225 
226 		Status status = git.status().call();
227 		Set<String> files = status.getIgnoredNotInIndex();
228 
229 		assertTrue(files.size() == 2);
230 		assertTrue(cleanedFiles.contains("sub-noclean/Ignored.txt"));
231 		assertTrue(cleanedFiles.contains("ignored-dir/"));
232 	}
233 
234 	@Test
235 	public void testCleanDirsWithSubmodule() throws Exception {
236 		SubmoduleAddCommand command = new SubmoduleAddCommand(db);
237 		String path = "sub";
238 		command.setPath(path);
239 		String uri = db.getDirectory().toURI().toString();
240 		command.setURI(uri);
241 		Repository repo = command.call();
242 		repo.close();
243 
244 		Status beforeCleanStatus = git.status().call();
245 		assertTrue(beforeCleanStatus.getAdded().contains(DOT_GIT_MODULES));
246 		assertTrue(beforeCleanStatus.getAdded().contains(path));
247 
248 		Set<String> cleanedFiles = git.clean().setCleanDirectories(true).call();
249 
250 		// The submodule should not be cleaned.
251 		assertTrue(!cleanedFiles.contains(path + "/"));
252 
253 		assertTrue(cleanedFiles.contains("File2.txt"));
254 		assertTrue(cleanedFiles.contains("File3.txt"));
255 		assertTrue(!cleanedFiles.contains("sub-noclean/File1.txt"));
256 		assertTrue(cleanedFiles.contains("sub-noclean/File2.txt"));
257 		assertTrue(cleanedFiles.contains("sub-clean/"));
258 		assertTrue(cleanedFiles.size() == 4);
259 	}
260 
261 	@Test
262 	public void testCleanDirsWithRepository() throws Exception {
263 		// Set up a repository inside the outer repository
264 		String innerRepoName = "inner-repo";
265 		File innerDir = new File(trash, innerRepoName);
266 		innerDir.mkdir();
267 		InitCommand initRepoCommand = new InitCommand();
268 		initRepoCommand.setDirectory(innerDir);
269 		initRepoCommand.call();
270 
271 		Status beforeCleanStatus = git.status().call();
272 		Set<String> untrackedFolders = beforeCleanStatus.getUntrackedFolders();
273 		Set<String> untrackedFiles = beforeCleanStatus.getUntracked();
274 
275 		// The inner repository should be listed as an untracked file
276 		assertTrue(untrackedFiles.contains(innerRepoName));
277 
278 		// The inner repository should not be listed as an untracked folder
279 		assertTrue(!untrackedFolders.contains(innerRepoName));
280 
281 		Set<String> cleanedFiles = git.clean().setCleanDirectories(true).call();
282 
283 		// The inner repository should not be cleaned.
284 		assertTrue(!cleanedFiles.contains(innerRepoName + "/"));
285 
286 		assertTrue(cleanedFiles.contains("File2.txt"));
287 		assertTrue(cleanedFiles.contains("File3.txt"));
288 		assertTrue(!cleanedFiles.contains("sub-noclean/File1.txt"));
289 		assertTrue(cleanedFiles.contains("sub-noclean/File2.txt"));
290 		assertTrue(cleanedFiles.contains("sub-clean/"));
291 		assertTrue(cleanedFiles.size() == 4);
292 
293 		Set<String> forceCleanedFiles = git.clean().setCleanDirectories(true)
294 				.setForce(true).call();
295 
296 		// The inner repository should be cleaned this time
297 		assertTrue(forceCleanedFiles.contains(innerRepoName + "/"));
298 	}
299 }