James Moger
2014-03-14 503a853acad49ac6da7f520c26b3b27942dbfec5
Merge AbstractSshCommand and BaseCommand into a single class
1 files renamed
1 files deleted
5 files modified
249 ■■■■■ changed files
src/main/java/com/gitblit/transport/ssh/AbstractSshCommand.java 84 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/commands/AbstractGitCommand.java 21 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/commands/BaseCommand.java 141 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java 1 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/commands/Receive.java 1 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/commands/SshCommand.java patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/commands/Upload.java 1 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/transport/ssh/AbstractSshCommand.java
File was deleted
src/main/java/com/gitblit/transport/ssh/commands/AbstractGitCommand.java
File was renamed from src/main/java/com/gitblit/transport/ssh/AbstractGitCommand.java
@@ -13,7 +13,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit.transport.ssh;
package com.gitblit.transport.ssh.commands;
import java.io.IOException;
@@ -26,14 +26,14 @@
import com.gitblit.git.GitblitReceivePackFactory;
import com.gitblit.git.GitblitUploadPackFactory;
import com.gitblit.git.RepositoryResolver;
import com.gitblit.transport.ssh.commands.BaseCommand;
import com.gitblit.transport.ssh.SshDaemonClient;
/**
 * @author Eric Myhre
 * 
 */
public abstract class AbstractGitCommand extends BaseCommand {
    @Argument(index = 0, metaVar = "PROJECT.git", required = true, usage = "project name")
    @Argument(index = 0, metaVar = "REPOSITORY", required = true, usage = "repository name")
    protected String repository;
    protected RepositoryResolver<SshDaemonClient> repositoryResolver;
@@ -79,30 +79,25 @@
        // ssh://git@thishost/path should always be name="/path" here
        //
        if (!repository.startsWith("/")) {
            throw new Failure(1, "fatal: '" + repository
                    + "': not starts with / character");
            throw new Failure(1, "fatal: '" + repository + "': not starts with / character");
        }
        repository = repository.substring(1);
        try {
            return repositoryResolver.open(ctx.getClient(), repository);
        } catch (Exception e) {
            throw new Failure(1, "fatal: '" + repository
                    + "': not a git archive", e);
            throw new Failure(1, "fatal: '" + repository + "': not a git archive", e);
        }
    }
    public void setRepositoryResolver(
            RepositoryResolver<SshDaemonClient> repositoryResolver) {
    public void setRepositoryResolver(RepositoryResolver<SshDaemonClient> repositoryResolver) {
        this.repositoryResolver = repositoryResolver;
    }
    public void setReceivePackFactory(
            GitblitReceivePackFactory<SshDaemonClient> receivePackFactory) {
    public void setReceivePackFactory(GitblitReceivePackFactory<SshDaemonClient> receivePackFactory) {
        this.receivePackFactory = receivePackFactory;
    }
    public void setUploadPackFactory(
            GitblitUploadPackFactory<SshDaemonClient> uploadPackFactory) {
    public void setUploadPackFactory(GitblitUploadPackFactory<SshDaemonClient> uploadPackFactory) {
        this.uploadPackFactory = uploadPackFactory;
    }
}
src/main/java/com/gitblit/transport/ssh/commands/BaseCommand.java
@@ -14,10 +14,13 @@
package com.gitblit.transport.ssh.commands;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
@@ -26,13 +29,14 @@
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
import org.apache.sshd.server.SessionAware;
import org.apache.sshd.server.session.ServerSession;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.transport.ssh.AbstractSshCommand;
import com.gitblit.transport.ssh.SshCommandContext;
import com.gitblit.utils.IdGenerator;
import com.gitblit.utils.WorkQueue;
@@ -41,18 +45,28 @@
import com.google.common.base.Charsets;
import com.google.common.util.concurrent.Atomics;
public abstract class BaseCommand extends AbstractSshCommand {
  private static final Logger log = LoggerFactory
      .getLogger(BaseCommand.class);
public abstract class BaseCommand implements Command, SessionAware {
    private static final Logger log = LoggerFactory.getLogger(BaseCommand.class);
    /** Ssh context */
    protected SshCommandContext ctx;
    protected InputStream in;
    protected OutputStream out;
    protected OutputStream err;
    protected ExitCallback exit;
    protected ServerSession session;
  /** Text of the command line which lead up to invoking this instance. */
  private String commandName = "";
  /** Unparsed command line options. */
  private String[] argv;
  /** Ssh context */
  protected SshCommandContext ctx;
  /** The task, as scheduled on a worker thread. */
  private final AtomicReference<Future<?>> task;
@@ -66,22 +80,42 @@
    this.executor = w.getDefaultQueue();
  }
    @Override
    public void setSession(final ServerSession session) {
        this.session = session;
    }
    @Override
    public void destroy() {
    }
    protected static PrintWriter toPrintWriter(final OutputStream o) {
        return new PrintWriter(new BufferedWriter(new OutputStreamWriter(o, Charsets.UTF_8)));
    }
    @Override
    public abstract void start(Environment env) throws IOException;
  public void setContext(SshCommandContext ctx) {
    this.ctx = ctx;
  }
    @Override
  public void setInputStream(final InputStream in) {
    this.in = in;
  }
    @Override
  public void setOutputStream(final OutputStream out) {
    this.out = out;
  }
    @Override
  public void setErrorStream(final OutputStream err) {
    this.err = err;
  }
    @Override
  public void setExitCallback(final ExitCallback callback) {
    this.exit = callback;
  }
@@ -117,7 +151,8 @@
   * <p>
   * This method must be explicitly invoked to cause a parse.
   *
   * @throws UnloggedFailure if the command line arguments were invalid.
     * @throws UnloggedFailure
     *             if the command line arguments were invalid.
   * @see Option
   * @see Argument
   */
@@ -130,9 +165,11 @@
   * <p>
   * This method must be explicitly invoked to cause a parse.
   *
   * @param options object whose fields declare Option and Argument annotations
   *        to describe the parameters of the command. Usually {@code this}.
   * @throws UnloggedFailure if the command line arguments were invalid.
     * @param options
     *            object whose fields declare Option and Argument annotations to
     *            describe the parameters of the command. Usually {@code this}.
     * @throws UnloggedFailure
     *             if the command line arguments were invalid.
   * @see Option
   * @see Argument
   */
@@ -233,7 +270,6 @@
    public void run() throws Exception;
  }
  /** Runnable function which can retrieve a project name related to the task */
  public static interface RepositoryCommandRunnable extends CommandRunnable {
    public String getRepository();
@@ -242,8 +278,8 @@
  /**
   * Spawn a function into its own thread.
   * <p>
   * Typically this should be invoked within {@link Command#start(Environment)},
   * such as:
     * Typically this should be invoked within
     * {@link Command#start(Environment)}, such as:
   *
   * <pre>
   * startThread(new Runnable() {
@@ -253,7 +289,8 @@
   * });
   * </pre>
   *
   * @param thunk the runnable to execute on the thread, performing the
     * @param thunk
     *            the runnable to execute on the thread, performing the
   *        command's logic.
   */
  protected void startThread(final Runnable thunk) {
@@ -272,7 +309,8 @@
   * lose access to request based resources as any callbacks previously
   * registered with {@link RequestCleanup} will fire.
   *
   * @param rc exit code for the remote client.
     * @param rc
     *            exit code for the remote client.
   */
  protected void onExit(final int rc) {
    exit.onExit(rc);
@@ -282,12 +320,8 @@
  }
  private int handleError(final Throwable e) {
    if ((e.getClass() == IOException.class
         && "Pipe closed".equals(e.getMessage()))
        || //
        (e.getClass() == SshException.class
         && "Already closed".equals(e.getMessage()))
        || //
        if ((e.getClass() == IOException.class && "Pipe closed".equals(e.getMessage())) || //
                (e.getClass() == SshException.class && "Already closed".equals(e.getMessage())) || //
        e.getClass() == InterruptedIOException.class) {
      // This is sshd telling us the client just dropped off while
      // we were waiting for a read or a write to complete. Either
@@ -339,8 +373,8 @@
  /**
   * Spawn a function into its own thread.
   * <p>
   * Typically this should be invoked within {@link Command#start(Environment)},
   * such as:
     * Typically this should be invoked within
     * {@link Command#start(Environment)}, such as:
   *
   * <pre>
   * startThread(new CommandRunnable() {
@@ -353,7 +387,8 @@
   * If the function throws an exception, it is translated to a simple message
   * for the client, a non-zero exit code, and the stack trace is logged.
   *
   * @param thunk the runnable to execute on the thread, performing the
     * @param thunk
     *            the runnable to execute on the thread, performing the
   *        command's logic.
   */
  protected void startThread(final CommandRunnable thunk) {
@@ -370,10 +405,12 @@
    /**
     * Create a new failure.
     *
     * @param exitCode exit code to return the client, which indicates the
     *        failure status of this command. Should be between 1 and 255,
     *        inclusive.
     * @param msg message to also send to the client's stderr.
         * @param exitCode
         *            exit code to return the client, which indicates the
         *            failure status of this command. Should be between 1 and
         *            255, inclusive.
         * @param msg
         *            message to also send to the client's stderr.
     */
    public Failure(final int exitCode, final String msg) {
      this(exitCode, msg, null);
@@ -382,12 +419,15 @@
    /**
     * Create a new failure.
     *
     * @param exitCode exit code to return the client, which indicates the
     *        failure status of this command. Should be between 1 and 255,
     *        inclusive.
     * @param msg message to also send to the client's stderr.
     * @param why stack trace to include in the server's log, but is not sent to
     *        the client's stderr.
         * @param exitCode
         *            exit code to return the client, which indicates the
         *            failure status of this command. Should be between 1 and
         *            255, inclusive.
         * @param msg
         *            message to also send to the client's stderr.
         * @param why
         *            stack trace to include in the server's log, but is not
         *            sent to the client's stderr.
     */
    public Failure(final int exitCode, final String msg, final Throwable why) {
      super(msg, why);
@@ -402,7 +442,8 @@
    /**
     * Create a new failure.
     *
     * @param msg message to also send to the client's stderr.
         * @param msg
         *            message to also send to the client's stderr.
     */
    public UnloggedFailure(final String msg) {
      this(1, msg);
@@ -411,10 +452,12 @@
    /**
     * Create a new failure.
     *
     * @param exitCode exit code to return the client, which indicates the
     *        failure status of this command. Should be between 1 and 255,
     *        inclusive.
     * @param msg message to also send to the client's stderr.
         * @param exitCode
         *            exit code to return the client, which indicates the
         *            failure status of this command. Should be between 1 and
         *            255, inclusive.
         * @param msg
         *            message to also send to the client's stderr.
     */
    public UnloggedFailure(final int exitCode, final String msg) {
      this(exitCode, msg, null);
@@ -423,15 +466,17 @@
    /**
     * Create a new failure.
     *
     * @param exitCode exit code to return the client, which indicates the
     *        failure status of this command. Should be between 1 and 255,
     *        inclusive.
     * @param msg message to also send to the client's stderr.
     * @param why stack trace to include in the server's log, but is not sent to
     *        the client's stderr.
         * @param exitCode
         *            exit code to return the client, which indicates the
         *            failure status of this command. Should be between 1 and
         *            255, inclusive.
         * @param msg
         *            message to also send to the client's stderr.
         * @param why
         *            stack trace to include in the server's log, but is not
         *            sent to the client's stderr.
     */
    public UnloggedFailure(final int exitCode, final String msg,
        final Throwable why) {
        public UnloggedFailure(final int exitCode, final String msg, final Throwable why) {
      super(exitCode, msg, why);
    }
  }
src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
@@ -30,7 +30,6 @@
import com.gitblit.git.GitblitReceivePackFactory;
import com.gitblit.git.GitblitUploadPackFactory;
import com.gitblit.git.RepositoryResolver;
import com.gitblit.transport.ssh.AbstractGitCommand;
import com.gitblit.transport.ssh.CommandMetaData;
import com.gitblit.transport.ssh.PublicKeyAuthenticator;
import com.gitblit.transport.ssh.SshDaemonClient;
src/main/java/com/gitblit/transport/ssh/commands/Receive.java
@@ -17,7 +17,6 @@
import org.eclipse.jgit.transport.ReceivePack;
import com.gitblit.transport.ssh.AbstractGitCommand;
import com.gitblit.transport.ssh.CommandMetaData;
@CommandMetaData(name = "git-receive-pack", description = "Receive pack")
src/main/java/com/gitblit/transport/ssh/commands/SshCommand.java
src/main/java/com/gitblit/transport/ssh/commands/Upload.java
@@ -17,7 +17,6 @@
import org.eclipse.jgit.transport.UploadPack;
import com.gitblit.transport.ssh.AbstractGitCommand;
import com.gitblit.transport.ssh.CommandMetaData;
@CommandMetaData(name = "git-upload-pack", description = "Upload pack")