Skip to content

Instantly share code, notes, and snippets.

@nedtwigg
Last active March 12, 2016 01:30
Show Gist options
  • Save nedtwigg/54ceb8a9b5498ca04fb1 to your computer and use it in GitHub Desktop.
Save nedtwigg/54ceb8a9b5498ca04fb1 to your computer and use it in GitHub Desktop.
A way to call JGit commands and stream their output.
import java.io.File;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.pgm.TextBuiltin;
import org.eclipse.jgit.pgm.opt.CmdLineParser;
import org.eclipse.jgit.pgm.opt.SubcommandHandler;
import org.kohsuke.args4j.Argument;
import com.diffplug.common.base.Either;
public class GitCliJGitWrapper {
/** Returns the output encoding for the given repository. */
public static Charset getOutputEncoding(Optional<Repository> db) {
return db.map(d -> d.getConfig().getString("i18n", null, "logOutputEncoding"))
.map(Charset::forName).orElseGet(Charset::defaultCharset);
}
public static void rawExecute(String str, Either<Repository, File> repoOrFolder, OutputStream outputStream, OutputStream errorStream) throws Exception {
// either db or gitDir will be null
String[] args = split(str);
if (!args[0].equalsIgnoreCase("git") || args.length < 2) { //$NON-NLS-1$
throw new IllegalArgumentException("Expected 'git <command> [<args>]', was:" + str); //$NON-NLS-1$
}
String[] argv = new String[args.length - 1];
System.arraycopy(args, 1, argv, 0, args.length - 1);
Streaming bean = new Streaming();
final CmdLineParser clp = new CmdLineParser(bean);
clp.parseArgument(argv);
final TextBuiltin cmd = bean.subcommand;
cmd.outs = outputStream;
cmd.errs = errorStream;
cmd.init(repoOrFolder.asOptionalLeft().orElse(null), repoOrFolder.asOptionalRight().map(File::getAbsolutePath).orElse(null));
try {
cmd.execute(bean.arguments.toArray(new String[bean.arguments.size()]));
} finally {
if (cmd.outw != null) {
cmd.outw.flush();
}
if (cmd.errw != null) {
cmd.errw.flush();
}
}
}
/** Command line entry point for streaming the command output. */
private static class Streaming {
@Argument(index = 0, metaVar = "metaVar_command", required = true, handler = SubcommandHandler.class)
private TextBuiltin subcommand;
@Argument(index = 1, metaVar = "metaVar_arg")
private List<String> arguments = new ArrayList<String>();
}
/**
* Split a command line into a string array.
*
* A copy of Gerrit's
* com.google.gerrit.sshd.CommandFactoryProvider#split(String)
*
* @param commandLine
* a command line
* @return the array
*/
static String[] split(String commandLine) {
final List<String> list = new ArrayList<String>();
boolean inquote = false;
boolean inDblQuote = false;
StringBuilder r = new StringBuilder();
for (int ip = 0; ip < commandLine.length();) {
final char b = commandLine.charAt(ip++);
switch (b) {
case '\t':
case ' ':
if (inquote || inDblQuote) {
r.append(b);
} else if (r.length() > 0) {
list.add(r.toString());
r = new StringBuilder();
}
continue;
case '\"':
if (inquote) {
r.append(b);
} else {
inDblQuote = !inDblQuote;
}
continue;
case '\'':
if (inDblQuote) {
r.append(b);
} else {
inquote = !inquote;
}
continue;
default:
r.append(b);
continue;
}
}
if (r.length() > 0) {
list.add(r.toString());
}
return list.toArray(new String[list.size()]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment