1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.api;
12
13 import static org.eclipse.jgit.lib.Constants.DOT_GIT;
14
15 import java.io.File;
16 import java.io.IOException;
17 import java.util.Collections;
18 import java.util.Set;
19 import java.util.TreeSet;
20
21 import org.eclipse.jgit.api.errors.GitAPIException;
22 import org.eclipse.jgit.api.errors.JGitInternalException;
23 import org.eclipse.jgit.errors.NoWorkTreeException;
24 import org.eclipse.jgit.events.WorkingTreeModifiedEvent;
25 import org.eclipse.jgit.lib.Repository;
26 import org.eclipse.jgit.util.FS;
27 import org.eclipse.jgit.util.FileUtils;
28
29
30
31
32
33
34
35
36 public class CleanCommand extends GitCommand<Set<String>> {
37
38 private Set<String> paths = Collections.emptySet();
39
40 private boolean dryRun;
41
42 private boolean directories;
43
44 private boolean ignore = true;
45
46 private boolean force = false;
47
48
49
50
51
52
53
54 protected CleanCommand(Repository repo) {
55 super(repo);
56 }
57
58
59
60
61
62
63
64
65
66 @Override
67 public Set<String> call() throws NoWorkTreeException, GitAPIException {
68 Set<String> files = new TreeSet<>();
69 try {
70 StatusCommand command = new StatusCommand(repo);
71 Status status = command.call();
72
73 Set<String> untrackedFiles = new TreeSet<>(status.getUntracked());
74 Set<String> untrackedDirs = new TreeSet<>(
75 status.getUntrackedFolders());
76
77 FS fs = getRepository().getFS();
78 for (String p : status.getIgnoredNotInIndex()) {
79 File f = new File(repo.getWorkTree(), p);
80 if (fs.isFile(f) || fs.isSymLink(f)) {
81 untrackedFiles.add(p);
82 } else if (fs.isDirectory(f)) {
83 untrackedDirs.add(p);
84 }
85 }
86
87 Set<String> filtered = filterFolders(untrackedFiles, untrackedDirs);
88
89 Set<String> notIgnoredFiles = filterIgnorePaths(filtered,
90 status.getIgnoredNotInIndex(), true);
91 Set<String> notIgnoredDirs = filterIgnorePaths(untrackedDirs,
92 status.getIgnoredNotInIndex(), false);
93
94 for (String file : notIgnoredFiles)
95 if (paths.isEmpty() || paths.contains(file)) {
96 files = cleanPath(file, files);
97 }
98
99 for (String dir : notIgnoredDirs)
100 if (paths.isEmpty() || paths.contains(dir)) {
101 files = cleanPath(dir, files);
102 }
103 } catch (IOException e) {
104 throw new JGitInternalException(e.getMessage(), e);
105 } finally {
106 if (!dryRun && !files.isEmpty()) {
107 repo.fireEvent(new WorkingTreeModifiedEvent(null, files));
108 }
109 }
110 return files;
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 private Set<String> cleanPath(String path, Set<String> inFiles)
134 throws IOException {
135 File curFile = new File(repo.getWorkTree(), path);
136 if (curFile.isDirectory()) {
137 if (directories) {
138
139 if (new File(curFile, DOT_GIT).exists()) {
140 if (force) {
141 if (!dryRun) {
142 FileUtils.delete(curFile, FileUtils.RECURSIVE
143 | FileUtils.SKIP_MISSING);
144 }
145 inFiles.add(path + "/");
146 }
147 } else {
148 if (!dryRun) {
149 FileUtils.delete(curFile,
150 FileUtils.RECURSIVE | FileUtils.SKIP_MISSING);
151 }
152 inFiles.add(path + "/");
153 }
154 }
155 } else {
156 if (!dryRun) {
157 FileUtils.delete(curFile, FileUtils.SKIP_MISSING);
158 }
159 inFiles.add(path);
160 }
161
162 return inFiles;
163 }
164
165 private Set<String> filterIgnorePaths(Set<String> inputPaths,
166 Set<String> ignoredNotInIndex, boolean exact) {
167 if (ignore) {
168 Set<String> filtered = new TreeSet<>(inputPaths);
169 for (String path : inputPaths)
170 for (String ignored : ignoredNotInIndex)
171 if ((exact && path.equals(ignored))
172 || (!exact && path.startsWith(ignored))) {
173 filtered.remove(path);
174 break;
175 }
176
177 return filtered;
178 }
179 return inputPaths;
180 }
181
182 private Set<String> filterFolders(Set<String> untracked,
183 Set<String> untrackedFolders) {
184 Set<String> filtered = new TreeSet<>(untracked);
185 for (String file : untracked)
186 for (String folder : untrackedFolders)
187 if (file.startsWith(folder)) {
188 filtered.remove(file);
189 break;
190 }
191
192
193 return filtered;
194 }
195
196
197
198
199
200
201
202
203 public CleanCommand setPaths(Set<String> paths) {
204 this.paths = paths;
205 return this;
206 }
207
208
209
210
211
212
213
214
215 public CleanCommand setDryRun(boolean dryRun) {
216 this.dryRun = dryRun;
217 return this;
218 }
219
220
221
222
223
224
225
226
227
228
229 public CleanCommand setForce(boolean force) {
230 this.force = force;
231 return this;
232 }
233
234
235
236
237
238
239
240
241 public CleanCommand setCleanDirectories(boolean dirs) {
242 directories = dirs;
243 return this;
244 }
245
246
247
248
249
250
251
252
253
254 public CleanCommand setIgnore(boolean ignore) {
255 this.ignore = ignore;
256 return this;
257 }
258 }