| /* |
| * Copyright (C) 2011-2012, IBM Corporation and others. and others |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Distribution License v. 1.0 which is available at |
| * https://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| package org.eclipse.jgit.pgm; |
| |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| import static org.junit.Assert.assertNull; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.jgit.internal.storage.file.FileRepository; |
| import org.eclipse.jgit.lib.Repository; |
| import org.eclipse.jgit.pgm.TextBuiltin.TerminatedByHelpException; |
| import org.eclipse.jgit.util.IO; |
| |
| public class CLIGitCommand extends Main { |
| |
| private final Result result; |
| |
| private final Repository db; |
| |
| public CLIGitCommand(Repository db) { |
| super(); |
| this.db = db; |
| result = new Result(); |
| } |
| |
| /** |
| * Executes git commands (with arguments) specified on the command line. The |
| * git repository (same for all commands) can be specified via system |
| * property "-Dgit_work_tree=path_to_work_tree". If the property is not set, |
| * current directory is used. |
| * |
| * @param args |
| * each element in the array must be a valid git command line, |
| * e.g. "git branch -h" |
| * @throws Exception |
| */ |
| public static void main(String[] args) throws Exception { |
| String workDir = System.getProperty("git_work_tree"); |
| if (workDir == null) { |
| workDir = "."; |
| System.out.println( |
| "System property 'git_work_tree' not specified, using current directory: " |
| + new File(workDir).getAbsolutePath()); |
| } |
| try (Repository db = new FileRepository(workDir + "/.git")) { |
| for (String cmd : args) { |
| List<String> result = execute(cmd, db); |
| for (String line : result) { |
| System.out.println(line); |
| } |
| } |
| } |
| } |
| |
| public static List<String> execute(String str, Repository db) |
| 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 { |
| cmd.run(str); |
| return getOutput(cmd.result); |
| } catch (Throwable e) { |
| return cmd.result.errLines(); |
| } |
| } |
| |
| 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 { |
| String[] args = split(str); |
| if (!args[0].equalsIgnoreCase("git") || args.length < 2) { |
| throw new IllegalArgumentException( |
| "Expected 'git <command> [<args>]', was:" + str); |
| } |
| String[] argv = new String[args.length - 1]; |
| System.arraycopy(args, 1, argv, 0, args.length - 1); |
| return argv; |
| } |
| |
| @Override |
| PrintWriter createErrorWriter() { |
| return new PrintWriter(new OutputStreamWriter( |
| result.err, UTF_8)); |
| } |
| |
| @Override |
| void init(TextBuiltin cmd) throws IOException { |
| cmd.outs = result.out; |
| cmd.errs = result.err; |
| super.init(cmd); |
| } |
| |
| @Override |
| protected Repository openGitDir(String aGitdir) throws IOException { |
| assertNull(aGitdir); |
| return db; |
| } |
| |
| @Override |
| void exit(int status, Exception t) throws Exception { |
| if (t == null) { |
| t = new IllegalStateException(Integer.toString(status)); |
| } |
| result.ex = t; |
| throw t; |
| } |
| |
| /** |
| * 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<>(); |
| 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; |
| case '\\': |
| if (inDblQuote || inquote || ip == commandLine.length()) |
| r.append(b); // literal within a quote |
| else |
| r.append(commandLine.charAt(ip++)); |
| continue; |
| default: |
| r.append(b); |
| continue; |
| } |
| } |
| if (r.length() > 0) |
| list.add(r.toString()); |
| return list.toArray(new String[0]); |
| } |
| |
| public static class Result { |
| public final ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| |
| public final ByteArrayOutputStream err = new ByteArrayOutputStream(); |
| |
| public Exception ex; |
| |
| public byte[] outBytes() { |
| return out.toByteArray(); |
| } |
| |
| public byte[] errBytes() { |
| return err.toByteArray(); |
| } |
| |
| public String outString() { |
| return new String(out.toByteArray(), UTF_8); |
| } |
| |
| public List<String> outLines() { |
| return IO.readLines(outString()); |
| } |
| |
| public String errString() { |
| return new String(err.toByteArray(), UTF_8); |
| } |
| |
| public List<String> errLines() { |
| return IO.readLines(errString()); |
| } |
| } |
| |
| } |