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
49 import java.io.File;
50 import java.io.IOException;
51 import java.io.OutputStreamWriter;
52 import java.io.PrintWriter;
53 import java.lang.reflect.InvocationTargetException;
54 import java.net.MalformedURLException;
55 import java.net.URL;
56 import java.text.MessageFormat;
57 import java.util.ArrayList;
58 import java.util.List;
59 import java.util.Locale;
60 import java.util.concurrent.ExecutorService;
61 import java.util.concurrent.Executors;
62 import java.util.concurrent.ThreadFactory;
63 import java.util.concurrent.TimeUnit;
64
65 import org.eclipse.jgit.awtui.AwtAuthenticator;
66 import org.eclipse.jgit.awtui.AwtCredentialsProvider;
67 import org.eclipse.jgit.errors.TransportException;
68 import org.eclipse.jgit.lfs.BuiltinLFS;
69 import org.eclipse.jgit.lib.Repository;
70 import org.eclipse.jgit.lib.RepositoryBuilder;
71 import org.eclipse.jgit.pgm.internal.CLIText;
72 import org.eclipse.jgit.pgm.opt.CmdLineParser;
73 import org.eclipse.jgit.pgm.opt.SubcommandHandler;
74 import org.eclipse.jgit.transport.HttpTransport;
75 import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
76 import org.eclipse.jgit.util.CachedAuthenticator;
77 import org.kohsuke.args4j.Argument;
78 import org.kohsuke.args4j.CmdLineException;
79 import org.kohsuke.args4j.Option;
80 import org.kohsuke.args4j.OptionHandlerFilter;
81
82
83
84
85 public class Main {
86 @Option(name = "--help", usage = "usage_displayThisHelpText", aliases = { "-h" })
87 private boolean help;
88
89 @Option(name = "--version", usage = "usage_displayVersion")
90 private boolean version;
91
92 @Option(name = "--show-stack-trace", usage = "usage_displayThejavaStackTraceOnExceptions")
93 private boolean showStackTrace;
94
95 @Option(name = "--git-dir", metaVar = "metaVar_gitDir", usage = "usage_setTheGitRepositoryToOperateOn")
96 private String gitdir;
97
98 @Argument(index = 0, metaVar = "metaVar_command", required = true, handler = SubcommandHandler.class)
99 private TextBuiltin subcommand;
100
101 @Argument(index = 1, metaVar = "metaVar_arg")
102 private List<String> arguments = new ArrayList<>();
103
104 PrintWriter writer;
105
106 private ExecutorService gcExecutor;
107
108
109
110
111 public Main() {
112 HttpTransport.setConnectionFactory(new HttpClientConnectionFactory());
113 BuiltinLFS.register();
114 gcExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
115 private final ThreadFactory baseFactory = Executors
116 .defaultThreadFactory();
117
118 @Override
119 public Thread newThread(Runnable taskBody) {
120 Thread thr = baseFactory.newThread(taskBody);
121 thr.setName("JGit-autoGc");
122 return thr;
123 }
124 });
125 }
126
127
128
129
130
131
132
133
134 public static void main(String[] argv) throws Exception {
135
136 BuiltinLFS.register();
137
138 new Main().run(argv);
139 }
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 protected void run(String[] argv) throws Exception {
159 writer = createErrorWriter();
160 try {
161 if (!installConsole()) {
162 AwtAuthenticator.install();
163 AwtCredentialsProvider.install();
164 }
165 configureHttpProxy();
166 execute(argv);
167 } catch (Die err) {
168 if (err.isAborted()) {
169 exit(1, err);
170 }
171 writer.println(CLIText.fatalError(err.getMessage()));
172 if (showStackTrace) {
173 err.printStackTrace(writer);
174 }
175 exit(128, err);
176 } catch (Exception err) {
177
178
179
180
181 if (err.getClass() == IOException.class) {
182
183 if (err.getMessage().equals("Broken pipe")) {
184 exit(0, err);
185 }
186
187 if (err.getMessage().equals("The pipe is being closed")) {
188 exit(0, err);
189 }
190 }
191 if (!showStackTrace && err.getCause() != null
192 && err instanceof TransportException) {
193 writer.println(CLIText.fatalError(err.getCause().getMessage()));
194 }
195
196 if (err.getClass().getName().startsWith("org.eclipse.jgit.errors.")) {
197 writer.println(CLIText.fatalError(err.getMessage()));
198 if (showStackTrace) {
199 err.printStackTrace();
200 }
201 exit(128, err);
202 }
203 err.printStackTrace();
204 exit(1, err);
205 }
206 if (System.out.checkError()) {
207 writer.println(CLIText.get().unknownIoErrorStdout);
208 exit(1, null);
209 }
210 if (writer.checkError()) {
211
212
213 exit(1, null);
214 }
215 gcExecutor.shutdown();
216 gcExecutor.awaitTermination(10, TimeUnit.MINUTES);
217 }
218
219 PrintWriter createErrorWriter() {
220 return new PrintWriter(new OutputStreamWriter(System.err, UTF_8));
221 }
222
223 private void execute(String[] argv) throws Exception {
224 final CmdLineParser clp = new SubcommandLineParser(this);
225
226 try {
227 clp.parseArgument(argv);
228 } catch (CmdLineException err) {
229 if (argv.length > 0 && !help && !version) {
230 writer.println(CLIText.fatalError(err.getMessage()));
231 writer.flush();
232 exit(1, err);
233 }
234 }
235
236 if (argv.length == 0 || help) {
237 final String ex = clp.printExample(OptionHandlerFilter.ALL,
238 CLIText.get().resourceBundle());
239 writer.println("jgit" + ex + " command [ARG ...]");
240 if (help) {
241 writer.println();
242 clp.printUsage(writer, CLIText.get().resourceBundle());
243 writer.println();
244 } else if (subcommand == null) {
245 writer.println();
246 writer.println(CLIText.get().mostCommonlyUsedCommandsAre);
247 final CommandRef[] common = CommandCatalog.common();
248 int width = 0;
249 for (CommandRef c : common) {
250 width = Math.max(width, c.getName().length());
251 }
252 width += 2;
253
254 for (CommandRef c : common) {
255 writer.print(' ');
256 writer.print(c.getName());
257 for (int i = c.getName().length(); i < width; i++) {
258 writer.print(' ');
259 }
260 writer.print(CLIText.get().resourceBundle().getString(c.getUsage()));
261 writer.println();
262 }
263 writer.println();
264 }
265 writer.flush();
266 exit(1, null);
267 }
268
269 if (version) {
270 String cmdId = Version.class.getSimpleName()
271 .toLowerCase(Locale.ROOT);
272 subcommand = CommandCatalog.get(cmdId).create();
273 }
274
275 final TextBuiltin cmd = subcommand;
276 init(cmd);
277 try {
278 cmd.execute(arguments.toArray(new String[0]));
279 } finally {
280 if (cmd.outw != null) {
281 cmd.outw.flush();
282 }
283 if (cmd.errw != null) {
284 cmd.errw.flush();
285 }
286 }
287 }
288
289 void init(TextBuiltin cmd) throws IOException {
290 if (cmd.requiresRepository()) {
291 cmd.init(openGitDir(gitdir), null);
292 } else {
293 cmd.init(null, gitdir);
294 }
295 }
296
297
298
299
300
301
302
303 void exit(int status, Exception t) throws Exception {
304 writer.flush();
305 System.exit(status);
306 }
307
308
309
310
311
312
313
314
315
316
317
318 protected Repository openGitDir(String aGitdir) throws IOException {
319 RepositoryBuilder rb = new RepositoryBuilder()
320 .setGitDir(aGitdir != null ? new File(aGitdir) : null)
321 .readEnvironment()
322 .findGitDir();
323 if (rb.getGitDir() == null)
324 throw new Die(CLIText.get().cantFindGitDirectory);
325 return rb.build();
326 }
327
328 private static boolean installConsole() {
329 try {
330 install("org.eclipse.jgit.console.ConsoleAuthenticator");
331 install("org.eclipse.jgit.console.ConsoleCredentialsProvider");
332 return true;
333 } catch (ClassNotFoundException e) {
334 return false;
335 } catch (NoClassDefFoundError e) {
336 return false;
337 } catch (UnsupportedClassVersionError e) {
338 return false;
339
340 } catch (IllegalArgumentException e) {
341 throw new RuntimeException(CLIText.get().cannotSetupConsole, e);
342 } catch (SecurityException e) {
343 throw new RuntimeException(CLIText.get().cannotSetupConsole, e);
344 } catch (IllegalAccessException e) {
345 throw new RuntimeException(CLIText.get().cannotSetupConsole, e);
346 } catch (InvocationTargetException e) {
347 throw new RuntimeException(CLIText.get().cannotSetupConsole, e);
348 } catch (NoSuchMethodException e) {
349 throw new RuntimeException(CLIText.get().cannotSetupConsole, e);
350 }
351 }
352
353 private static void install(String name)
354 throws IllegalAccessException, InvocationTargetException,
355 NoSuchMethodException, ClassNotFoundException {
356 try {
357 Class.forName(name).getMethod("install").invoke(null);
358 } catch (InvocationTargetException e) {
359 if (e.getCause() instanceof RuntimeException)
360 throw (RuntimeException) e.getCause();
361 if (e.getCause() instanceof Error)
362 throw (Error) e.getCause();
363 throw e;
364 }
365 }
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384 static void configureHttpProxy() throws MalformedURLException {
385 for (String protocol : new String[] { "http", "https" }) {
386 if (System.getProperty(protocol + ".proxyHost") != null) {
387 continue;
388 }
389 String s = System.getenv(protocol + "_proxy");
390 if (s == null && protocol.equals("https")) {
391 s = System.getenv("HTTPS_PROXY");
392 }
393 if (s == null || s.equals("")) {
394 continue;
395 }
396
397 final URL u = new URL(
398 (s.indexOf("://") == -1) ? protocol + "://" + s : s); //$NON-NLS-1$ //$NON-NLS-2$
399 if (!u.getProtocol().startsWith("http"))
400 throw new MalformedURLException(MessageFormat.format(
401 CLIText.get().invalidHttpProxyOnlyHttpSupported, s));
402
403 final String proxyHost = u.getHost();
404 final int proxyPort = u.getPort();
405
406 System.setProperty(protocol + ".proxyHost", proxyHost);
407 if (proxyPort > 0)
408 System.setProperty(protocol + ".proxyPort",
409 String.valueOf(proxyPort));
410
411 final String userpass = u.getUserInfo();
412 if (userpass != null && userpass.contains(":")) {
413 final int c = userpass.indexOf(':');
414 final String user = userpass.substring(0, c);
415 final String pass = userpass.substring(c + 1);
416 CachedAuthenticator.add(
417 new CachedAuthenticator.CachedAuthentication(proxyHost,
418 proxyPort, user, pass));
419 }
420 }
421 }
422
423
424
425
426
427 static class SubcommandLineParser extends CmdLineParser {
428 public SubcommandLineParser(Object bean) {
429 super(bean);
430 }
431
432 @Override
433 protected boolean containsHelp(String... args) {
434 return false;
435 }
436 }
437 }