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.pgm.opt;
45
46 import java.io.IOException;
47 import java.io.Writer;
48 import java.lang.reflect.Field;
49 import java.util.ArrayList;
50 import java.util.Iterator;
51 import java.util.List;
52 import java.util.ResourceBundle;
53
54 import org.eclipse.jgit.lib.ObjectId;
55 import org.eclipse.jgit.lib.Repository;
56 import org.eclipse.jgit.pgm.Die;
57 import org.eclipse.jgit.pgm.TextBuiltin;
58 import org.eclipse.jgit.pgm.internal.CLIText;
59 import org.eclipse.jgit.revwalk.RevCommit;
60 import org.eclipse.jgit.revwalk.RevTree;
61 import org.eclipse.jgit.revwalk.RevWalk;
62 import org.eclipse.jgit.transport.RefSpec;
63 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
64 import org.kohsuke.args4j.CmdLineException;
65 import org.kohsuke.args4j.IllegalAnnotationError;
66 import org.kohsuke.args4j.NamedOptionDef;
67 import org.kohsuke.args4j.OptionDef;
68 import org.kohsuke.args4j.OptionHandlerRegistry;
69 import org.kohsuke.args4j.spi.OptionHandler;
70 import org.kohsuke.args4j.spi.RestOfArgumentsHandler;
71 import org.kohsuke.args4j.spi.Setter;
72
73
74
75
76
77
78
79
80
81 public class CmdLineParser extends org.kohsuke.args4j.CmdLineParser {
82 static {
83 OptionHandlerRegistry registry = OptionHandlerRegistry.getRegistry();
84 registry.registerHandler(AbstractTreeIterator.class,
85 AbstractTreeIteratorHandler.class);
86 registry.registerHandler(ObjectId.class, ObjectIdHandler.class);
87 registry.registerHandler(RefSpec.class, RefSpecHandler.class);
88 registry.registerHandler(RevCommit.class, RevCommitHandler.class);
89 registry.registerHandler(RevTree.class, RevTreeHandler.class);
90 registry.registerHandler(List.class, OptionWithValuesListHandler.class);
91 }
92
93 private final Repository db;
94
95 private RevWalk walk;
96
97 private boolean seenHelp;
98
99 private TextBuiltin cmd;
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 public CmdLineParser(Object bean) {
115 this(bean, null);
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 public CmdLineParser(Object bean, Repository repo) {
134 super(bean);
135 if (bean instanceof TextBuiltin) {
136 cmd = (TextBuiltin) bean;
137 }
138 if (repo == null && cmd != null) {
139 repo = cmd.getRepository();
140 }
141 this.db = repo;
142 }
143
144
145 @Override
146 public void parseArgument(String... args) throws CmdLineException {
147 final ArrayList<String> tmp = new ArrayList<>(args.length);
148 for (int argi = 0; argi < args.length; argi++) {
149 final String str = args[argi];
150 if (str.equals("--")) {
151 while (argi < args.length)
152 tmp.add(args[argi++]);
153 break;
154 }
155
156 if (str.startsWith("--")) {
157 final int eq = str.indexOf('=');
158 if (eq > 0) {
159 tmp.add(str.substring(0, eq));
160 tmp.add(str.substring(eq + 1));
161 continue;
162 }
163 }
164
165 tmp.add(str);
166
167 if (containsHelp(args)) {
168
169 seenHelp = true;
170
171 break;
172 }
173 }
174 List<OptionHandler> backup = null;
175 if (seenHelp) {
176 backup = unsetRequiredOptions();
177 }
178
179 try {
180 super.parseArgument(tmp.toArray(new String[0]));
181 } catch (Die e) {
182 if (!seenHelp) {
183 throw e;
184 }
185 printToErrorWriter(CLIText.fatalError(e.getMessage()));
186 } finally {
187
188 if (backup != null && !backup.isEmpty()) {
189 restoreRequiredOptions(backup);
190 }
191 seenHelp = false;
192 }
193 }
194
195 private void printToErrorWriter(String error) {
196 if (cmd == null) {
197 System.err.println(error);
198 } else {
199 try {
200 cmd.getErrorWriter().println(error);
201 } catch (IOException e1) {
202 System.err.println(error);
203 }
204 }
205 }
206
207 private List<OptionHandler> unsetRequiredOptions() {
208 List<OptionHandler> options = getOptions();
209 List<OptionHandler> backup = new ArrayList<>(options);
210 for (Iterator<OptionHandler> iterator = options.iterator(); iterator
211 .hasNext();) {
212 OptionHandler handler = iterator.next();
213 if (handler.option instanceof NamedOptionDef
214 && handler.option.required()) {
215 iterator.remove();
216 }
217 }
218 return backup;
219 }
220
221 private void restoreRequiredOptions(List<OptionHandler> backup) {
222 List<OptionHandler> options = getOptions();
223 options.clear();
224 options.addAll(backup);
225 }
226
227
228
229
230
231
232
233
234
235 protected boolean containsHelp(String... args) {
236 return TextBuiltin.containsHelp(args);
237 }
238
239
240
241
242
243
244 public Repository getRepository() {
245 if (db == null)
246 throw new IllegalStateException(CLIText.get().noGitRepositoryConfigured);
247 return db;
248 }
249
250
251
252
253
254
255 public RevWalk getRevWalk() {
256 if (walk == null)
257 walk = new RevWalk(getRepository());
258 return walk;
259 }
260
261
262
263
264
265
266
267
268 public RevWalk getRevWalkGently() {
269 return walk;
270 }
271
272 class MyOptionDef extends OptionDef {
273
274 public MyOptionDef(OptionDef o) {
275 super(o.usage(), o.metaVar(), o.required(), o.help(), o.hidden(),
276 o.handler(), o.isMultiValued());
277 }
278
279 @Override
280 public String toString() {
281 if (metaVar() == null)
282 return "ARG";
283 try {
284 Field field = CLIText.class.getField(metaVar());
285 String ret = field.get(CLIText.get()).toString();
286 return ret;
287 } catch (Exception e) {
288 e.printStackTrace(System.err);
289 return metaVar();
290 }
291 }
292
293 @Override
294 public boolean required() {
295 return seenHelp ? false : super.required();
296 }
297 }
298
299
300 @Override
301 protected OptionHandler createOptionHandler(OptionDef o, Setter setter) {
302 if (o instanceof NamedOptionDef)
303 return super.createOptionHandler(o, setter);
304 else
305 return super.createOptionHandler(new MyOptionDef(o), setter);
306
307 }
308
309
310 @Override
311 public void printSingleLineUsage(Writer w, ResourceBundle rb) {
312 List<OptionHandler> options = getOptions();
313 if (options.isEmpty()) {
314 super.printSingleLineUsage(w, rb);
315 return;
316 }
317 List<OptionHandler> backup = new ArrayList<>(options);
318 boolean changed = sortRestOfArgumentsHandlerToTheEnd(options);
319 try {
320 super.printSingleLineUsage(w, rb);
321 } finally {
322 if (changed) {
323 options.clear();
324 options.addAll(backup);
325 }
326 }
327 }
328
329 private boolean sortRestOfArgumentsHandlerToTheEnd(
330 List<OptionHandler> options) {
331 for (int i = 0; i < options.size(); i++) {
332 OptionHandler handler = options.get(i);
333 if (handler instanceof RestOfArgumentsHandler
334 || handler instanceof PathTreeFilterHandler) {
335 options.remove(i);
336 options.add(handler);
337 return true;
338 }
339 }
340 return false;
341 }
342 }