Introduce a named constant for the .git directory.
[jgit.git] / org.eclipse.jgit.pgm / src / org / eclipse / jgit / pgm / Main.java
blob10ebef4637ae539a1ae39ce5b6aa2e011f866a7d
1 /*
2 * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
4 * and other copyright owners as documented in the project's IP log.
6 * This program and the accompanying materials are made available
7 * under the terms of the Eclipse Distribution License v1.0 which
8 * accompanies this distribution, is reproduced below, and is
9 * available at http://www.eclipse.org/org/documents/edl-v10.php
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
15 * conditions are met:
17 * - Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials provided
23 * with the distribution.
25 * - Neither the name of the Eclipse Foundation, Inc. nor the
26 * names of its contributors may be used to endorse or promote
27 * products derived from this software without specific prior
28 * written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
42 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 package org.eclipse.jgit.pgm;
47 import java.io.File;
48 import java.lang.reflect.InvocationTargetException;
49 import java.net.MalformedURLException;
50 import java.net.URL;
51 import java.util.ArrayList;
52 import java.util.Arrays;
53 import java.util.HashSet;
54 import java.util.List;
55 import java.util.Set;
57 import org.eclipse.jgit.awtui.AwtAuthenticator;
58 import org.eclipse.jgit.awtui.AwtSshSessionFactory;
59 import org.eclipse.jgit.errors.TransportException;
60 import org.eclipse.jgit.lib.Constants;
61 import org.eclipse.jgit.lib.Repository;
62 import org.eclipse.jgit.pgm.opt.CmdLineParser;
63 import org.eclipse.jgit.pgm.opt.SubcommandHandler;
64 import org.eclipse.jgit.util.CachedAuthenticator;
65 import org.eclipse.jgit.util.SystemReader;
66 import org.kohsuke.args4j.Argument;
67 import org.kohsuke.args4j.CmdLineException;
68 import org.kohsuke.args4j.ExampleMode;
69 import org.kohsuke.args4j.Option;
71 /** Command line entry point. */
72 public class Main {
73 @Option(name = "--help", usage = "display this help text", aliases = { "-h" })
74 private boolean help;
76 @Option(name = "--show-stack-trace", usage = "display the Java stack trace on exceptions")
77 private boolean showStackTrace;
79 @Option(name = "--git-dir", metaVar = "GIT_DIR", usage = "set the git repository to operate on")
80 private File gitdir;
82 @Argument(index = 0, metaVar = "command", required = true, handler = SubcommandHandler.class)
83 private TextBuiltin subcommand;
85 @Argument(index = 1, metaVar = "ARG")
86 private List<String> arguments = new ArrayList<String>();
88 /**
89 * Execute the command line.
91 * @param argv
92 * arguments.
94 public static void main(final String[] argv) {
95 final Main me = new Main();
96 try {
97 if (!installConsole()) {
98 AwtAuthenticator.install();
99 AwtSshSessionFactory.install();
101 configureHttpProxy();
102 me.execute(argv);
103 } catch (Die err) {
104 System.err.println("fatal: " + err.getMessage());
105 if (me.showStackTrace)
106 err.printStackTrace();
107 System.exit(128);
108 } catch (Exception err) {
109 if (!me.showStackTrace && err.getCause() != null
110 && err instanceof TransportException)
111 System.err.println("fatal: " + err.getCause().getMessage());
113 if (err.getClass().getName().startsWith("org.eclipse.jgit.errors.")) {
114 System.err.println("fatal: " + err.getMessage());
115 if (me.showStackTrace)
116 err.printStackTrace();
117 System.exit(128);
119 err.printStackTrace();
120 System.exit(1);
124 private void execute(final String[] argv) throws Exception {
125 final CmdLineParser clp = new CmdLineParser(this);
126 try {
127 clp.parseArgument(argv);
128 } catch (CmdLineException err) {
129 if (argv.length > 0 && !help) {
130 System.err.println("fatal: " + err.getMessage());
131 System.exit(1);
135 if (argv.length == 0 || help) {
136 final String ex = clp.printExample(ExampleMode.ALL);
137 System.err.println("jgit" + ex + " command [ARG ...]");
138 if (help) {
139 System.err.println();
140 clp.printUsage(System.err);
141 System.err.println();
142 } else if (subcommand == null) {
143 System.err.println();
144 System.err.println("The most commonly used commands are:");
145 final CommandRef[] common = CommandCatalog.common();
146 int width = 0;
147 for (final CommandRef c : common)
148 width = Math.max(width, c.getName().length());
149 width += 2;
151 for (final CommandRef c : common) {
152 System.err.print(' ');
153 System.err.print(c.getName());
154 for (int i = c.getName().length(); i < width; i++)
155 System.err.print(' ');
156 System.err.print(c.getUsage());
157 System.err.println();
159 System.err.println();
161 System.exit(1);
164 final TextBuiltin cmd = subcommand;
165 if (cmd.requiresRepository()) {
166 if (gitdir == null) {
167 String gitDirEnv = SystemReader.getInstance().getenv(Constants.GIT_DIR_KEY);
168 if (gitDirEnv != null)
169 gitdir = new File(gitDirEnv);
171 if (gitdir == null)
172 gitdir = findGitDir();
174 File gitworktree;
175 String gitWorkTreeEnv = SystemReader.getInstance().getenv(Constants.GIT_WORK_TREE_KEY);
176 if (gitWorkTreeEnv != null)
177 gitworktree = new File(gitWorkTreeEnv);
178 else
179 gitworktree = null;
181 File indexfile;
182 String indexFileEnv = SystemReader.getInstance().getenv(Constants.GIT_INDEX_KEY);
183 if (indexFileEnv != null)
184 indexfile = new File(indexFileEnv);
185 else
186 indexfile = null;
188 File objectdir;
189 String objectDirEnv = SystemReader.getInstance().getenv(Constants.GIT_OBJECT_DIRECTORY_KEY);
190 if (objectDirEnv != null)
191 objectdir = new File(objectDirEnv);
192 else
193 objectdir = null;
195 File[] altobjectdirs;
196 String altObjectDirEnv = SystemReader.getInstance().getenv(Constants.GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY);
197 if (altObjectDirEnv != null) {
198 String[] parserdAltObjectDirEnv = altObjectDirEnv.split(File.pathSeparator);
199 altobjectdirs = new File[parserdAltObjectDirEnv.length];
200 for (int i = 0; i < parserdAltObjectDirEnv.length; i++)
201 altobjectdirs[i] = new File(parserdAltObjectDirEnv[i]);
202 } else
203 altobjectdirs = null;
205 if (gitdir == null || !gitdir.isDirectory()) {
206 System.err.println("error: can't find git directory");
207 System.exit(1);
209 cmd.init(new Repository(gitdir, gitworktree, objectdir, altobjectdirs, indexfile), gitdir);
210 } else {
211 cmd.init(null, gitdir);
213 try {
214 cmd.execute(arguments.toArray(new String[arguments.size()]));
215 } finally {
216 if (cmd.out != null)
217 cmd.out.flush();
221 private static File findGitDir() {
222 Set<String> ceilingDirectories = new HashSet<String>();
223 String ceilingDirectoriesVar = SystemReader.getInstance().getenv(
224 Constants.GIT_CEILING_DIRECTORIES_KEY);
225 if (ceilingDirectoriesVar != null) {
226 ceilingDirectories.addAll(Arrays.asList(ceilingDirectoriesVar
227 .split(File.pathSeparator)));
229 File current = new File("").getAbsoluteFile();
230 while (current != null) {
231 final File gitDir = new File(current, Constants.DOT_GIT);
232 if (gitDir.isDirectory())
233 return gitDir;
234 current = current.getParentFile();
235 if (ceilingDirectories.contains(current.getPath()))
236 break;
238 return null;
241 private static boolean installConsole() {
242 try {
243 install("org.eclipse.jgit.console.ConsoleAuthenticator");
244 install("org.eclipse.jgit.console.ConsoleSshSessionFactory");
245 return true;
246 } catch (ClassNotFoundException e) {
247 return false;
248 } catch (NoClassDefFoundError e) {
249 return false;
250 } catch (UnsupportedClassVersionError e) {
251 return false;
253 } catch (IllegalArgumentException e) {
254 throw new RuntimeException("Cannot setup console", e);
255 } catch (SecurityException e) {
256 throw new RuntimeException("Cannot setup console", e);
257 } catch (IllegalAccessException e) {
258 throw new RuntimeException("Cannot setup console", e);
259 } catch (InvocationTargetException e) {
260 throw new RuntimeException("Cannot setup console", e);
261 } catch (NoSuchMethodException e) {
262 throw new RuntimeException("Cannot setup console", e);
266 private static void install(final String name)
267 throws IllegalAccessException, InvocationTargetException,
268 NoSuchMethodException, ClassNotFoundException {
269 try {
270 Class.forName(name).getMethod("install").invoke(null);
271 } catch (InvocationTargetException e) {
272 if (e.getCause() instanceof RuntimeException)
273 throw (RuntimeException) e.getCause();
274 if (e.getCause() instanceof Error)
275 throw (Error) e.getCause();
276 throw e;
281 * Configure the JRE's standard HTTP based on <code>http_proxy</code>.
282 * <p>
283 * The popular libcurl library honors the <code>http_proxy</code>
284 * environment variable as a means of specifying an HTTP proxy for requests
285 * made behind a firewall. This is not natively recognized by the JRE, so
286 * this method can be used by command line utilities to configure the JRE
287 * before the first request is sent.
289 * @throws MalformedURLException
290 * the value in <code>http_proxy</code> is unsupportable.
292 private static void configureHttpProxy() throws MalformedURLException {
293 final String s = System.getenv("http_proxy");
294 if (s == null || s.equals(""))
295 return;
297 final URL u = new URL((s.indexOf("://") == -1) ? "http://" + s : s);
298 if (!"http".equals(u.getProtocol()))
299 throw new MalformedURLException("Invalid http_proxy: " + s
300 + ": Only http supported.");
302 final String proxyHost = u.getHost();
303 final int proxyPort = u.getPort();
305 System.setProperty("http.proxyHost", proxyHost);
306 if (proxyPort > 0)
307 System.setProperty("http.proxyPort", String.valueOf(proxyPort));
309 final String userpass = u.getUserInfo();
310 if (userpass != null && userpass.contains(":")) {
311 final int c = userpass.indexOf(':');
312 final String user = userpass.substring(0, c);
313 final String pass = userpass.substring(c + 1);
314 CachedAuthenticator
315 .add(new CachedAuthenticator.CachedAuthentication(
316 proxyHost, proxyPort, user, pass));