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