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
45 package org.eclipse.jgit.pgm;
46
47 import static java.nio.charset.StandardCharsets.UTF_8;
48 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_LOG_OUTPUT_ENCODING;
49 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_SECTION_I18N;
50 import static org.eclipse.jgit.lib.Constants.R_HEADS;
51 import static org.eclipse.jgit.lib.Constants.R_REMOTES;
52 import static org.eclipse.jgit.lib.Constants.R_TAGS;
53
54 import java.io.BufferedWriter;
55 import java.io.FileDescriptor;
56 import java.io.FileInputStream;
57 import java.io.FileOutputStream;
58 import java.io.IOException;
59 import java.io.InputStream;
60 import java.io.OutputStream;
61 import java.io.OutputStreamWriter;
62 import java.nio.charset.Charset;
63 import java.text.MessageFormat;
64 import java.util.ResourceBundle;
65
66 import org.eclipse.jgit.lib.ObjectId;
67 import org.eclipse.jgit.lib.Repository;
68 import org.eclipse.jgit.pgm.internal.CLIText;
69 import org.eclipse.jgit.pgm.internal.SshDriver;
70 import org.eclipse.jgit.pgm.opt.CmdLineParser;
71 import org.eclipse.jgit.revwalk.RevWalk;
72 import org.eclipse.jgit.transport.SshSessionFactory;
73 import org.eclipse.jgit.transport.sshd.DefaultProxyDataFactory;
74 import org.eclipse.jgit.transport.sshd.JGitKeyCache;
75 import org.eclipse.jgit.transport.sshd.SshdSessionFactory;
76 import org.eclipse.jgit.util.io.ThrowingPrintWriter;
77 import org.kohsuke.args4j.CmdLineException;
78 import org.kohsuke.args4j.Option;
79
80
81
82
83
84
85
86
87
88
89
90
91 public abstract class TextBuiltin {
92 private String commandName;
93
94 @Option(name = "--help", usage = "usage_displayThisHelpText", aliases = { "-h" })
95 private boolean help;
96
97 @Option(name = "--ssh", usage = "usage_sshDriver")
98 private SshDriver sshDriver = SshDriver.JSCH;
99
100
101
102
103
104
105 protected InputStream ins;
106
107
108
109
110
111
112 protected ThrowingPrintWriter outw;
113
114
115
116
117
118
119 protected OutputStream outs;
120
121
122
123
124
125
126 protected ThrowingPrintWriter errw;
127
128
129
130
131
132
133 protected OutputStream errs;
134
135
136 protected Repository db;
137
138
139 protected String gitdir;
140
141
142 protected RevWalk argWalk;
143
144 final void setCommandName(String name) {
145 commandName = name;
146 }
147
148
149
150
151
152
153 protected boolean requiresRepository() {
154 return true;
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 public void initRaw(final Repository repository, final String gitDir,
175 InputStream input, OutputStream output, OutputStream error) {
176 this.ins = input;
177 this.outs = output;
178 this.errs = error;
179 init(repository, gitDir);
180 }
181
182
183
184
185
186
187
188
189
190
191 private Charset getLogOutputEncodingCharset(Repository repository) {
192 if (repository != null) {
193 String logOutputEncoding = repository.getConfig().getString(
194 CONFIG_SECTION_I18N, null, CONFIG_KEY_LOG_OUTPUT_ENCODING);
195 if (logOutputEncoding != null) {
196 try {
197 return Charset.forName(logOutputEncoding);
198 } catch (IllegalArgumentException e) {
199 throw die(CLIText.get().cannotCreateOutputStream, e);
200 }
201 }
202 }
203 return UTF_8;
204 }
205
206
207
208
209
210
211
212
213
214
215 protected void init(Repository repository, String gitDir) {
216 Charset charset = getLogOutputEncodingCharset(repository);
217
218 if (ins == null)
219 ins = new FileInputStream(FileDescriptor.in);
220 if (outs == null)
221 outs = new FileOutputStream(FileDescriptor.out);
222 if (errs == null)
223 errs = new FileOutputStream(FileDescriptor.err);
224 outw = new ThrowingPrintWriter(new BufferedWriter(
225 new OutputStreamWriter(outs, charset)));
226 errw = new ThrowingPrintWriter(new BufferedWriter(
227 new OutputStreamWriter(errs, charset)));
228
229 if (repository != null && repository.getDirectory() != null) {
230 db = repository;
231 gitdir = repository.getDirectory().getAbsolutePath();
232 } else {
233 db = repository;
234 gitdir = gitDir;
235 }
236 }
237
238
239
240
241
242
243
244
245
246
247
248 public final void execute(String[] args) throws Exception {
249 parseArguments(args);
250 switch (sshDriver) {
251 case APACHE: {
252 SshdSessionFactory factory = new SshdSessionFactory(
253 new JGitKeyCache(), new DefaultProxyDataFactory());
254 Runtime.getRuntime()
255 .addShutdownHook(new Thread(() -> factory.close()));
256 SshSessionFactory.setInstance(factory);
257 break;
258 }
259 case JSCH:
260 default:
261 SshSessionFactory.setInstance(null);
262 break;
263 }
264 run();
265 }
266
267
268
269
270
271
272
273
274
275
276
277
278 protected void parseArguments(String[] args) throws IOException {
279 final CmdLineParserParser.html#CmdLineParser">CmdLineParser clp = new CmdLineParser(this);
280 help = containsHelp(args);
281 try {
282 clp.parseArgument(args);
283 } catch (CmdLineException err) {
284 this.errw.println(CLIText.fatalError(err.getMessage()));
285 if (help) {
286 printUsage("", clp);
287 }
288 throw die(true, err);
289 }
290
291 if (help) {
292 printUsage("", clp);
293 throw new TerminatedByHelpException();
294 }
295
296 argWalk = clp.getRevWalkGently();
297 }
298
299
300
301
302
303
304
305
306 public void printUsageAndExit(CmdLineParser clp) throws IOException {
307 printUsageAndExit("", clp);
308 }
309
310
311
312
313
314
315
316
317
318
319 public void printUsageAndExit(String message, CmdLineParser clp) throws IOException {
320 printUsage(message, clp);
321 throw die(true);
322 }
323
324
325
326
327
328
329
330
331
332
333
334 protected void printUsage(String message, CmdLineParser clp)
335 throws IOException {
336 errw.println(message);
337 errw.print("jgit ");
338 errw.print(commandName);
339 clp.printSingleLineUsage(errw, getResourceBundle());
340 errw.println();
341
342 errw.println();
343 clp.printUsage(errw, getResourceBundle());
344 errw.println();
345
346 errw.flush();
347 }
348
349
350
351
352
353
354
355 public ThrowingPrintWriter getErrorWriter() {
356 return errw;
357 }
358
359
360
361
362
363
364
365 public ThrowingPrintWriter getOutputWriter() {
366 return outw;
367 }
368
369
370
371
372
373
374
375 protected ResourceBundle getResourceBundle() {
376 return CLIText.get().resourceBundle();
377 }
378
379
380
381
382
383
384
385
386
387
388
389 protected abstract void run() throws Exception;
390
391
392
393
394
395
396 public Repository getRepository() {
397 return db;
398 }
399
400 ObjectId resolve(String s) throws IOException {
401 final ObjectId r = db.resolve(s);
402 if (r == null)
403 throw die(MessageFormat.format(CLIText.get().notARevision, s));
404 return r;
405 }
406
407
408
409
410
411
412
413
414 protected static Die die(String why) {
415 return new Die(why);
416 }
417
418
419
420
421
422
423
424
425
426
427 protected static Die die(String why, Throwable cause) {
428 return new Die(why, cause);
429 }
430
431
432
433
434
435
436
437
438
439
440 protected static Die die(boolean aborted) {
441 return new Die(aborted);
442 }
443
444
445
446
447
448
449
450
451
452
453
454
455 protected static Die die(boolean aborted, Throwable cause) {
456 return new Die(aborted, cause);
457 }
458
459 String abbreviateRef(String dst, boolean abbreviateRemote) {
460 if (dst.startsWith(R_HEADS))
461 dst = dst.substring(R_HEADS.length());
462 else if (dst.startsWith(R_TAGS))
463 dst = dst.substring(R_TAGS.length());
464 else if (abbreviateRemote && dst.startsWith(R_REMOTES))
465 dst = dst.substring(R_REMOTES.length());
466 return dst;
467 }
468
469
470
471
472
473
474
475
476
477 public static boolean containsHelp(String[] args) {
478 for (String str : args) {
479 if (str.equals("-h") || str.equals("--help")) {
480 return true;
481 }
482 }
483 return false;
484 }
485
486
487
488
489
490
491 public static class TerminatedByHelpException extends Die {
492 private static final long serialVersionUID = 1L;
493
494
495
496
497 public TerminatedByHelpException() {
498 super(true);
499 }
500
501 }
502 }