Make sure CLIGitCommand and Main produce (almost) same results

Currently execution of tests in pgm uses CLIGitCommand which
re-implements few things from Main. Unfortunately this can results in a
different test behavior compared to the real CLI runtime.

The change let CLIGitCommand extend Main and only slightly modifies the
runtime (stream redirection and undesired exit() termination).

Change-Id: I87b7b61d1c84a89e5917610d84409f01be90b70b
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
This commit is contained in:
Andrey Loskutov 2016-01-03 12:29:55 +01:00
parent fb5056c2c5
commit 7780a4ee31
4 changed files with 230 additions and 140 deletions

View File

@ -54,7 +54,8 @@
import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.JGitTestUtil;
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
import org.eclipse.jgit.pgm.CLIGitCommand; import org.eclipse.jgit.pgm.CLIGitCommand;
import org.eclipse.jgit.pgm.Die; import org.eclipse.jgit.pgm.CLIGitCommand.Result;
import org.eclipse.jgit.pgm.TextBuiltin.TerminatedByHelpException;
import org.junit.Before; import org.junit.Before;
public class CLIRepositoryTestCase extends LocalDiskRepositoryTestCase { public class CLIRepositoryTestCase extends LocalDiskRepositoryTestCase {
@ -84,7 +85,7 @@ public void setUp() throws Exception {
protected String[] executeUnchecked(String... cmds) throws Exception { protected String[] executeUnchecked(String... cmds) throws Exception {
List<String> result = new ArrayList<String>(cmds.length); List<String> result = new ArrayList<String>(cmds.length);
for (String cmd : cmds) { for (String cmd : cmds) {
result.addAll(CLIGitCommand.execute(cmd, db)); result.addAll(CLIGitCommand.executeUnchecked(cmd, db));
} }
return result.toArray(new String[0]); return result.toArray(new String[0]);
} }
@ -102,11 +103,13 @@ protected String[] executeUnchecked(String... cmds) throws Exception {
protected String[] execute(String... cmds) throws Exception { protected String[] execute(String... cmds) throws Exception {
List<String> result = new ArrayList<String>(cmds.length); List<String> result = new ArrayList<String>(cmds.length);
for (String cmd : cmds) { for (String cmd : cmds) {
List<String> out = CLIGitCommand.execute(cmd, db); Result r = CLIGitCommand.executeRaw(cmd, db);
if (contains(out, "fatal: ")) { if (r.ex instanceof TerminatedByHelpException) {
throw new Die(toString(out)); result.addAll(r.errLines());
} else if (r.ex != null) {
throw r.ex;
} }
result.addAll(out); result.addAll(r.outLines());
} }
return result.toArray(new String[0]); return result.toArray(new String[0]);
} }

View File

@ -42,33 +42,31 @@
*/ */
package org.eclipse.jgit.pgm; package org.eclipse.jgit.pgm;
import static org.junit.Assert.assertNull;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.pgm.TextBuiltin.TerminatedByHelpException; import org.eclipse.jgit.pgm.TextBuiltin.TerminatedByHelpException;
import org.eclipse.jgit.pgm.internal.CLIText;
import org.eclipse.jgit.pgm.opt.CmdLineParser;
import org.eclipse.jgit.pgm.opt.SubcommandHandler;
import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.IO;
import org.kohsuke.args4j.Argument;
public class CLIGitCommand { public class CLIGitCommand extends Main {
@Argument(index = 0, metaVar = "metaVar_command", required = true, handler = SubcommandHandler.class)
private TextBuiltin subcommand;
@Argument(index = 1, metaVar = "metaVar_arg") private final Result result;
private List<String> arguments = new ArrayList<String>();
public TextBuiltin getSubcommand() { private final Repository db;
return subcommand;
}
public List<String> getArguments() { public CLIGitCommand(Repository db) {
return arguments; super();
this.db = db;
result = new Result();
} }
/** /**
@ -102,57 +100,82 @@ public static void main(String[] args) throws Exception {
public static List<String> execute(String str, Repository db) public static List<String> execute(String str, Repository db)
throws Exception { throws Exception {
Result result = executeRaw(str, db);
return getOutput(result);
}
public static Result executeRaw(String str, Repository db)
throws Exception {
CLIGitCommand cmd = new CLIGitCommand(db);
cmd.run(str);
return cmd.result;
}
public static List<String> executeUnchecked(String str, Repository db)
throws Exception {
CLIGitCommand cmd = new CLIGitCommand(db);
try { try {
return IO.readLines(new String(rawExecute(str, db))); cmd.run(str);
} catch (Die e) { return getOutput(cmd.result);
return IO.readLines(CLIText.fatalError(e.getMessage())); } catch (Throwable e) {
return cmd.result.errLines();
} }
} }
public static byte[] rawExecute(String str, Repository db) private static List<String> getOutput(Result result) {
if (result.ex instanceof TerminatedByHelpException) {
return result.errLines();
}
return result.outLines();
}
private void run(String commandLine) throws Exception {
String[] argv = convertToMainArgs(commandLine);
try {
super.run(argv);
} catch (TerminatedByHelpException e) {
// this is not a failure, super called exit() on help
} finally {
writer.flush();
}
}
private static String[] convertToMainArgs(String str)
throws Exception { throws Exception {
String[] args = split(str); String[] args = split(str);
if (!args[0].equalsIgnoreCase("git") || args.length < 2) if (!args[0].equalsIgnoreCase("git") || args.length < 2) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Expected 'git <command> [<args>]', was:" + str); "Expected 'git <command> [<args>]', was:" + str);
}
String[] argv = new String[args.length - 1]; String[] argv = new String[args.length - 1];
System.arraycopy(args, 1, argv, 0, args.length - 1); System.arraycopy(args, 1, argv, 0, args.length - 1);
return argv;
}
CLIGitCommand bean = new CLIGitCommand(); @Override
final CmdLineParser clp = new TestCmdLineParser(bean); PrintWriter createErrorWriter() {
clp.parseArgument(argv); return new PrintWriter(result.err);
}
final TextBuiltin cmd = bean.getSubcommand(); void init(final TextBuiltin cmd) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); cmd.outs = result.out;
cmd.outs = baos; cmd.errs = result.err;
ByteArrayOutputStream errs = new ByteArrayOutputStream(); super.init(cmd);
cmd.errs = errs; }
boolean seenHelp = TextBuiltin.containsHelp(argv);
if (cmd.requiresRepository()) @Override
cmd.init(db, null); protected Repository openGitDir(String aGitdir) throws IOException {
else assertNull(aGitdir);
cmd.init(null, null); return db;
try { }
cmd.execute(bean.getArguments().toArray(
new String[bean.getArguments().size()])); @Override
} catch (TerminatedByHelpException e) { void exit(int status, Exception t) throws Exception {
seenHelp = true; if (t == null) {
// this is not a failure, command execution should just not happen t = new IllegalStateException(Integer.toString(status));
} finally {
if (cmd.outw != null) {
cmd.outw.flush();
}
if (cmd.errw != null) {
cmd.errw.flush();
}
if (seenHelp) {
return errs.toByteArray();
} else if (errs.size() > 0) {
// forward the errors to the standard err
System.err.print(errs.toString());
}
} }
return baos.toByteArray(); result.ex = t;
throw t;
} }
/** /**
@ -210,14 +233,36 @@ else if (r.length() > 0) {
return list.toArray(new String[list.size()]); return list.toArray(new String[list.size()]);
} }
static class TestCmdLineParser extends CmdLineParser { public static class Result {
public TestCmdLineParser(Object bean) { public final ByteArrayOutputStream out = new ByteArrayOutputStream();
super(bean);
public final ByteArrayOutputStream err = new ByteArrayOutputStream();
public Exception ex;
public byte[] outBytes() {
return out.toByteArray();
} }
@Override public byte[] errBytes() {
protected boolean containsHelp(String... args) { return err.toByteArray();
return false; }
public String outString() {
return out.toString();
}
public List<String> outLines() {
return IO.readLines(out.toString());
}
public String errString() {
return err.toString();
}
public List<String> errLines() {
return IO.readLines(err.toString());
} }
} }
} }

View File

@ -87,21 +87,22 @@ public void setUp() throws Exception {
@Test @Test
public void testEmptyArchive() throws Exception { public void testEmptyArchive() throws Exception {
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=zip " + emptyTree, db); "git archive --format=zip " + emptyTree, db).outBytes();
assertArrayEquals(new String[0], listZipEntries(result)); assertArrayEquals(new String[0], listZipEntries(result));
} }
@Test @Test
public void testEmptyTar() throws Exception { public void testEmptyTar() throws Exception {
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=tar " + emptyTree, db); "git archive --format=tar " + emptyTree, db).outBytes();
assertArrayEquals(new String[0], listTarEntries(result)); assertArrayEquals(new String[0], listTarEntries(result));
} }
@Test @Test
public void testUnrecognizedFormat() throws Exception { public void testUnrecognizedFormat() throws Exception {
String[] expect = new String[] { "fatal: Unknown archive format 'nonsense'" }; String[] expect = new String[] {
"fatal: Unknown archive format 'nonsense'", "" };
String[] actual = executeUnchecked( String[] actual = executeUnchecked(
"git archive --format=nonsense " + emptyTree); "git archive --format=nonsense " + emptyTree);
assertArrayEquals(expect, actual); assertArrayEquals(expect, actual);
@ -116,8 +117,8 @@ public void testArchiveWithFiles() throws Exception {
git.add().addFilepattern("c").call(); git.add().addFilepattern("c").call();
git.commit().setMessage("populate toplevel").call(); git.commit().setMessage("populate toplevel").call();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=zip HEAD", db); "git archive --format=zip HEAD", db).outBytes();
assertArrayEquals(new String[] { "a", "c" }, assertArrayEquals(new String[] { "a", "c" },
listZipEntries(result)); listZipEntries(result));
} }
@ -131,8 +132,8 @@ private void commitGreeting() throws Exception {
@Test @Test
public void testDefaultFormatIsTar() throws Exception { public void testDefaultFormatIsTar() throws Exception {
commitGreeting(); commitGreeting();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive HEAD", db); "git archive HEAD", db).outBytes();
assertArrayEquals(new String[] { "greeting" }, assertArrayEquals(new String[] { "greeting" },
listTarEntries(result)); listTarEntries(result));
} }
@ -298,8 +299,8 @@ public void testArchiveWithSubdir() throws Exception {
git.add().addFilepattern("b").call(); git.add().addFilepattern("b").call();
git.commit().setMessage("add subdir").call(); git.commit().setMessage("add subdir").call();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=zip master", db); "git archive --format=zip master", db).outBytes();
String[] expect = { "a", "b.c", "b0c", "b/", "b/a", "b/b", "c" }; String[] expect = { "a", "b.c", "b0c", "b/", "b/a", "b/b", "c" };
String[] actual = listZipEntries(result); String[] actual = listZipEntries(result);
@ -324,8 +325,8 @@ public void testTarWithSubdir() throws Exception {
git.add().addFilepattern("b").call(); git.add().addFilepattern("b").call();
git.commit().setMessage("add subdir").call(); git.commit().setMessage("add subdir").call();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=tar master", db); "git archive --format=tar master", db).outBytes();
String[] expect = { "a", "b.c", "b0c", "b/", "b/a", "b/b", "c" }; String[] expect = { "a", "b.c", "b0c", "b/", "b/a", "b/b", "c" };
String[] actual = listTarEntries(result); String[] actual = listTarEntries(result);
@ -345,8 +346,8 @@ private void commitBazAndFooSlashBar() throws Exception {
@Test @Test
public void testArchivePrefixOption() throws Exception { public void testArchivePrefixOption() throws Exception {
commitBazAndFooSlashBar(); commitBazAndFooSlashBar();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --prefix=x/ --format=zip master", db); "git archive --prefix=x/ --format=zip master", db).outBytes();
String[] expect = { "x/baz", "x/foo/", "x/foo/bar" }; String[] expect = { "x/baz", "x/foo/", "x/foo/bar" };
String[] actual = listZipEntries(result); String[] actual = listZipEntries(result);
@ -358,8 +359,8 @@ public void testArchivePrefixOption() throws Exception {
@Test @Test
public void testTarPrefixOption() throws Exception { public void testTarPrefixOption() throws Exception {
commitBazAndFooSlashBar(); commitBazAndFooSlashBar();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --prefix=x/ --format=tar master", db); "git archive --prefix=x/ --format=tar master", db).outBytes();
String[] expect = { "x/baz", "x/foo/", "x/foo/bar" }; String[] expect = { "x/baz", "x/foo/", "x/foo/bar" };
String[] actual = listTarEntries(result); String[] actual = listTarEntries(result);
@ -377,8 +378,8 @@ private void commitFoo() throws Exception {
@Test @Test
public void testPrefixDoesNotNormalizeDoubleSlash() throws Exception { public void testPrefixDoesNotNormalizeDoubleSlash() throws Exception {
commitFoo(); commitFoo();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --prefix=x// --format=zip master", db); "git archive --prefix=x// --format=zip master", db).outBytes();
String[] expect = { "x//foo" }; String[] expect = { "x//foo" };
assertArrayEquals(expect, listZipEntries(result)); assertArrayEquals(expect, listZipEntries(result));
} }
@ -386,8 +387,8 @@ public void testPrefixDoesNotNormalizeDoubleSlash() throws Exception {
@Test @Test
public void testPrefixDoesNotNormalizeDoubleSlashInTar() throws Exception { public void testPrefixDoesNotNormalizeDoubleSlashInTar() throws Exception {
commitFoo(); commitFoo();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --prefix=x// --format=tar master", db); "git archive --prefix=x// --format=tar master", db).outBytes();
String[] expect = { "x//foo" }; String[] expect = { "x//foo" };
assertArrayEquals(expect, listTarEntries(result)); assertArrayEquals(expect, listTarEntries(result));
} }
@ -404,8 +405,8 @@ public void testPrefixDoesNotNormalizeDoubleSlashInTar() throws Exception {
@Test @Test
public void testPrefixWithoutTrailingSlash() throws Exception { public void testPrefixWithoutTrailingSlash() throws Exception {
commitBazAndFooSlashBar(); commitBazAndFooSlashBar();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --prefix=my- --format=zip master", db); "git archive --prefix=my- --format=zip master", db).outBytes();
String[] expect = { "my-baz", "my-foo/", "my-foo/bar" }; String[] expect = { "my-baz", "my-foo/", "my-foo/bar" };
String[] actual = listZipEntries(result); String[] actual = listZipEntries(result);
@ -417,8 +418,8 @@ public void testPrefixWithoutTrailingSlash() throws Exception {
@Test @Test
public void testTarPrefixWithoutTrailingSlash() throws Exception { public void testTarPrefixWithoutTrailingSlash() throws Exception {
commitBazAndFooSlashBar(); commitBazAndFooSlashBar();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --prefix=my- --format=tar master", db); "git archive --prefix=my- --format=tar master", db).outBytes();
String[] expect = { "my-baz", "my-foo/", "my-foo/bar" }; String[] expect = { "my-baz", "my-foo/", "my-foo/bar" };
String[] actual = listTarEntries(result); String[] actual = listTarEntries(result);
@ -437,8 +438,8 @@ public void testArchiveIncludesSubmoduleDirectory() throws Exception {
git.submoduleAdd().setURI("./.").setPath("b").call().close(); git.submoduleAdd().setURI("./.").setPath("b").call().close();
git.commit().setMessage("add submodule").call(); git.commit().setMessage("add submodule").call();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=zip master", db); "git archive --format=zip master", db).outBytes();
String[] expect = { ".gitmodules", "a", "b/", "c" }; String[] expect = { ".gitmodules", "a", "b/", "c" };
String[] actual = listZipEntries(result); String[] actual = listZipEntries(result);
@ -457,8 +458,8 @@ public void testTarIncludesSubmoduleDirectory() throws Exception {
git.submoduleAdd().setURI("./.").setPath("b").call().close(); git.submoduleAdd().setURI("./.").setPath("b").call().close();
git.commit().setMessage("add submodule").call(); git.commit().setMessage("add submodule").call();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=tar master", db); "git archive --format=tar master", db).outBytes();
String[] expect = { ".gitmodules", "a", "b/", "c" }; String[] expect = { ".gitmodules", "a", "b/", "c" };
String[] actual = listTarEntries(result); String[] actual = listTarEntries(result);
@ -487,8 +488,8 @@ public void testArchivePreservesMode() throws Exception {
git.commit().setMessage("three files with different modes").call(); git.commit().setMessage("three files with different modes").call();
byte[] zipData = CLIGitCommand.rawExecute( byte[] zipData = CLIGitCommand.executeRaw(
"git archive --format=zip master", db); "git archive --format=zip master", db).outBytes();
writeRaw("zip-with-modes.zip", zipData); writeRaw("zip-with-modes.zip", zipData);
assertContainsEntryWithMode("zip-with-modes.zip", "-rw-", "plain"); assertContainsEntryWithMode("zip-with-modes.zip", "-rw-", "plain");
assertContainsEntryWithMode("zip-with-modes.zip", "-rwx", "executable"); assertContainsEntryWithMode("zip-with-modes.zip", "-rwx", "executable");
@ -516,8 +517,8 @@ public void testTarPreservesMode() throws Exception {
git.commit().setMessage("three files with different modes").call(); git.commit().setMessage("three files with different modes").call();
byte[] archive = CLIGitCommand.rawExecute( byte[] archive = CLIGitCommand.executeRaw(
"git archive --format=tar master", db); "git archive --format=tar master", db).outBytes();
writeRaw("with-modes.tar", archive); writeRaw("with-modes.tar", archive);
assertTarContainsEntry("with-modes.tar", "-rw-r--r--", "plain"); assertTarContainsEntry("with-modes.tar", "-rw-r--r--", "plain");
assertTarContainsEntry("with-modes.tar", "-rwxr-xr-x", "executable"); assertTarContainsEntry("with-modes.tar", "-rwxr-xr-x", "executable");
@ -539,8 +540,8 @@ public void testArchiveWithLongFilename() throws Exception {
git.add().addFilepattern("1234567890").call(); git.add().addFilepattern("1234567890").call();
git.commit().setMessage("file with long name").call(); git.commit().setMessage("file with long name").call();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=zip HEAD", db); "git archive --format=zip HEAD", db).outBytes();
assertArrayEquals(l.toArray(new String[l.size()]), assertArrayEquals(l.toArray(new String[l.size()]),
listZipEntries(result)); listZipEntries(result));
} }
@ -559,8 +560,8 @@ public void testTarWithLongFilename() throws Exception {
git.add().addFilepattern("1234567890").call(); git.add().addFilepattern("1234567890").call();
git.commit().setMessage("file with long name").call(); git.commit().setMessage("file with long name").call();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=tar HEAD", db); "git archive --format=tar HEAD", db).outBytes();
assertArrayEquals(l.toArray(new String[l.size()]), assertArrayEquals(l.toArray(new String[l.size()]),
listTarEntries(result)); listTarEntries(result));
} }
@ -572,8 +573,8 @@ public void testArchivePreservesContent() throws Exception {
git.add().addFilepattern("xyzzy").call(); git.add().addFilepattern("xyzzy").call();
git.commit().setMessage("add file with content").call(); git.commit().setMessage("add file with content").call();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=zip HEAD", db); "git archive --format=zip HEAD", db).outBytes();
assertArrayEquals(new String[] { payload }, assertArrayEquals(new String[] { payload },
zipEntryContent(result, "xyzzy")); zipEntryContent(result, "xyzzy"));
} }
@ -585,8 +586,8 @@ public void testTarPreservesContent() throws Exception {
git.add().addFilepattern("xyzzy").call(); git.add().addFilepattern("xyzzy").call();
git.commit().setMessage("add file with content").call(); git.commit().setMessage("add file with content").call();
byte[] result = CLIGitCommand.rawExecute( byte[] result = CLIGitCommand.executeRaw(
"git archive --format=tar HEAD", db); "git archive --format=tar HEAD", db).outBytes();
assertArrayEquals(new String[] { payload }, assertArrayEquals(new String[] { payload },
tarEntryContent(result, "xyzzy")); tarEntryContent(result, "xyzzy"));
} }

View File

@ -90,14 +90,23 @@ public class Main {
@Argument(index = 1, metaVar = "metaVar_arg") @Argument(index = 1, metaVar = "metaVar_arg")
private List<String> arguments = new ArrayList<String>(); private List<String> arguments = new ArrayList<String>();
PrintWriter writer;
/**
*
*/
public Main() {
HttpTransport.setConnectionFactory(new HttpClientConnectionFactory());
}
/** /**
* Execute the command line. * Execute the command line.
* *
* @param argv * @param argv
* arguments. * arguments.
* @throws Exception
*/ */
public static void main(final String[] argv) { public static void main(final String[] argv) throws Exception {
HttpTransport.setConnectionFactory(new HttpClientConnectionFactory());
new Main().run(argv); new Main().run(argv);
} }
@ -116,8 +125,10 @@ public static void main(final String[] argv) {
* *
* @param argv * @param argv
* arguments. * arguments.
* @throws Exception
*/ */
protected void run(final String[] argv) { protected void run(final String[] argv) throws Exception {
writer = createErrorWriter();
try { try {
if (!installConsole()) { if (!installConsole()) {
AwtAuthenticator.install(); AwtAuthenticator.install();
@ -126,12 +137,14 @@ protected void run(final String[] argv) {
configureHttpProxy(); configureHttpProxy();
execute(argv); execute(argv);
} catch (Die err) { } catch (Die err) {
if (err.isAborted()) if (err.isAborted()) {
System.exit(1); exit(1, err);
System.err.println(CLIText.fatalError(err.getMessage())); }
if (showStackTrace) writer.println(CLIText.fatalError(err.getMessage()));
err.printStackTrace(); if (showStackTrace) {
System.exit(128); err.printStackTrace(writer);
}
exit(128, err);
} catch (Exception err) { } catch (Exception err) {
// Try to detect errno == EPIPE and exit normally if that happens // Try to detect errno == EPIPE and exit normally if that happens
// There may be issues with operating system versions and locale, // There may be issues with operating system versions and locale,
@ -139,46 +152,54 @@ protected void run(final String[] argv) {
// under other circumstances. // under other circumstances.
if (err.getClass() == IOException.class) { if (err.getClass() == IOException.class) {
// Linux, OS X // Linux, OS X
if (err.getMessage().equals("Broken pipe")) //$NON-NLS-1$ if (err.getMessage().equals("Broken pipe")) { //$NON-NLS-1$
System.exit(0); exit(0, err);
}
// Windows // Windows
if (err.getMessage().equals("The pipe is being closed")) //$NON-NLS-1$ if (err.getMessage().equals("The pipe is being closed")) { //$NON-NLS-1$
System.exit(0); exit(0, err);
}
} }
if (!showStackTrace && err.getCause() != null if (!showStackTrace && err.getCause() != null
&& err instanceof TransportException) && err instanceof TransportException) {
System.err.println(CLIText.fatalError(err.getCause().getMessage())); writer.println(CLIText.fatalError(err.getCause().getMessage()));
}
if (err.getClass().getName().startsWith("org.eclipse.jgit.errors.")) { //$NON-NLS-1$ if (err.getClass().getName().startsWith("org.eclipse.jgit.errors.")) { //$NON-NLS-1$
System.err.println(CLIText.fatalError(err.getMessage())); writer.println(CLIText.fatalError(err.getMessage()));
if (showStackTrace) if (showStackTrace) {
err.printStackTrace(); err.printStackTrace();
System.exit(128); }
exit(128, err);
} }
err.printStackTrace(); err.printStackTrace();
System.exit(1); exit(1, err);
} }
if (System.out.checkError()) { if (System.out.checkError()) {
System.err.println(CLIText.get().unknownIoErrorStdout); writer.println(CLIText.get().unknownIoErrorStdout);
System.exit(1); exit(1, null);
} }
if (System.err.checkError()) { if (writer.checkError()) {
// No idea how to present an error here, most likely disk full or // No idea how to present an error here, most likely disk full or
// broken pipe // broken pipe
System.exit(1); exit(1, null);
} }
} }
PrintWriter createErrorWriter() {
return new PrintWriter(System.err);
}
private void execute(final String[] argv) throws Exception { private void execute(final String[] argv) throws Exception {
final CmdLineParser clp = new SubcommandLineParser(this); final CmdLineParser clp = new SubcommandLineParser(this);
PrintWriter writer = new PrintWriter(System.err);
try { try {
clp.parseArgument(argv); clp.parseArgument(argv);
} catch (CmdLineException err) { } catch (CmdLineException err) {
if (argv.length > 0 && !help && !version) { if (argv.length > 0 && !help && !version) {
writer.println(CLIText.fatalError(err.getMessage())); writer.println(CLIText.fatalError(err.getMessage()));
writer.flush(); writer.flush();
System.exit(1); exit(1, err);
} }
} }
@ -194,22 +215,24 @@ private void execute(final String[] argv) throws Exception {
writer.println(CLIText.get().mostCommonlyUsedCommandsAre); writer.println(CLIText.get().mostCommonlyUsedCommandsAre);
final CommandRef[] common = CommandCatalog.common(); final CommandRef[] common = CommandCatalog.common();
int width = 0; int width = 0;
for (final CommandRef c : common) for (final CommandRef c : common) {
width = Math.max(width, c.getName().length()); width = Math.max(width, c.getName().length());
}
width += 2; width += 2;
for (final CommandRef c : common) { for (final CommandRef c : common) {
writer.print(' '); writer.print(' ');
writer.print(c.getName()); writer.print(c.getName());
for (int i = c.getName().length(); i < width; i++) for (int i = c.getName().length(); i < width; i++) {
writer.print(' '); writer.print(' ');
}
writer.print(CLIText.get().resourceBundle().getString(c.getUsage())); writer.print(CLIText.get().resourceBundle().getString(c.getUsage()));
writer.println(); writer.println();
} }
writer.println(); writer.println();
} }
writer.flush(); writer.flush();
System.exit(1); exit(1, null);
} }
if (version) { if (version) {
@ -218,20 +241,38 @@ private void execute(final String[] argv) throws Exception {
} }
final TextBuiltin cmd = subcommand; final TextBuiltin cmd = subcommand;
if (cmd.requiresRepository()) init(cmd);
cmd.init(openGitDir(gitdir), null);
else
cmd.init(null, gitdir);
try { try {
cmd.execute(arguments.toArray(new String[arguments.size()])); cmd.execute(arguments.toArray(new String[arguments.size()]));
} finally { } finally {
if (cmd.outw != null) if (cmd.outw != null) {
cmd.outw.flush(); cmd.outw.flush();
if (cmd.errw != null) }
if (cmd.errw != null) {
cmd.errw.flush(); cmd.errw.flush();
}
} }
} }
void init(final TextBuiltin cmd) throws IOException {
if (cmd.requiresRepository()) {
cmd.init(openGitDir(gitdir), null);
} else {
cmd.init(null, gitdir);
}
}
/**
* @param status
* @param t
* can be {@code null}
* @throws Exception
*/
void exit(int status, Exception t) throws Exception {
writer.flush();
System.exit(status);
}
/** /**
* Evaluate the {@code --git-dir} option and open the repository. * Evaluate the {@code --git-dir} option and open the repository.
* *
@ -281,7 +322,7 @@ private static void install(final String name)
throws IllegalAccessException, InvocationTargetException, throws IllegalAccessException, InvocationTargetException,
NoSuchMethodException, ClassNotFoundException { NoSuchMethodException, ClassNotFoundException {
try { try {
Class.forName(name).getMethod("install").invoke(null); //$NON-NLS-1$ Class.forName(name).getMethod("install").invoke(null); //$NON-NLS-1$
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
if (e.getCause() instanceof RuntimeException) if (e.getCause() instanceof RuntimeException)
throw (RuntimeException) e.getCause(); throw (RuntimeException) e.getCause();