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