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