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