]> source.dussan.org Git - gitblit.git/commitdiff
Create git and gitblit dispatchers
authorJames Moger <james.moger@gitblit.com>
Tue, 18 Mar 2014 01:23:44 +0000 (21:23 -0400)
committerJames Moger <james.moger@gitblit.com>
Thu, 10 Apr 2014 22:58:09 +0000 (18:58 -0400)
26 files changed:
src/main/java/com/gitblit/transport/ssh/SshCommandFactory.java
src/main/java/com/gitblit/transport/ssh/commands/AddKeyCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/BaseGitCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/BaseKeyCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/CreateRepository.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/DispatchCommand.java
src/main/java/com/gitblit/transport/ssh/commands/ListRepositoriesCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/Receive.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/RemoveKeyCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/ReviewCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/Upload.java [deleted file]
src/main/java/com/gitblit/transport/ssh/commands/VersionCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/git/BaseGitCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/git/GitDispatchCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/git/Receive.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/git/Upload.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/AddKeyCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/CreateRepository.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/GitblitDispatchCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/LsCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/RemoveKeyCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/ReviewCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/SetAccountCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/VersionCommand.java [new file with mode: 0644]

index b8dd5b9f418dc12ca752349c57afc82c87402b3a..de7aad1f9b3aa6e7780e5c88a23314e8a3ab09bd 100644 (file)
@@ -34,21 +34,11 @@ import org.apache.sshd.server.session.ServerSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.gitblit.git.GitblitReceivePackFactory;
-import com.gitblit.git.GitblitUploadPackFactory;
-import com.gitblit.git.RepositoryResolver;
 import com.gitblit.manager.IGitblit;
 import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.commands.AddKeyCommand;
-import com.gitblit.transport.ssh.commands.CreateRepository;
 import com.gitblit.transport.ssh.commands.DispatchCommand;
-import com.gitblit.transport.ssh.commands.ListRepositoriesCommand;
-import com.gitblit.transport.ssh.commands.Receive;
-import com.gitblit.transport.ssh.commands.RemoveKeyCommand;
-import com.gitblit.transport.ssh.commands.ReviewCommand;
-import com.gitblit.transport.ssh.commands.SetAccountCommand;
-import com.gitblit.transport.ssh.commands.Upload;
-import com.gitblit.transport.ssh.commands.VersionCommand;
+import com.gitblit.transport.ssh.git.GitDispatchCommand;
+import com.gitblit.transport.ssh.gitblit.GitblitDispatchCommand;
 import com.gitblit.utils.IdGenerator;
 import com.gitblit.utils.WorkQueue;
 import com.google.common.util.concurrent.Atomics;
@@ -86,31 +76,16 @@ public class SshCommandFactory implements CommandFactory {
        protected DispatchCommand createRootDispatcher(SshDaemonClient client, String cmdLine) {
                final UserModel user = client.getUser();
 
-               DispatchCommand gitblitCmd = new DispatchCommand();
-               gitblitCmd.registerCommand(user, VersionCommand.class);
-               gitblitCmd.registerCommand(user, AddKeyCommand.class);
-               gitblitCmd.registerCommand(user, RemoveKeyCommand.class);
-               gitblitCmd.registerCommand(user, ListRepositoriesCommand.class);
-               gitblitCmd.registerCommand(user, ReviewCommand.class);
-
-               gitblitCmd.registerCommand(user, CreateRepository.class);
-               gitblitCmd.registerCommand(user, SetAccountCommand.class);
-
-               DispatchCommand gitCmd = new DispatchCommand();
-               gitCmd.registerCommand(user, Upload.class);
-               gitCmd.registerCommand(user, Receive.class);
+               DispatchCommand root = new DispatchCommand() {
+               };
+               root.setContext(new SshCommandContext(gitblit, client, cmdLine));
 
-               DispatchCommand root = new DispatchCommand();
-               root.registerDispatcher("gitblit", gitblitCmd);
-               root.registerDispatcher("git", gitCmd);
+               // TODO convert these dispatchers to plugin extension points
+               root.registerDispatcher(user, GitblitDispatchCommand.class);
+               root.registerDispatcher(user, GitDispatchCommand.class);
 
-               root.setRepositoryResolver(new RepositoryResolver<SshDaemonClient>(gitblit));
-               root.setUploadPackFactory(new GitblitUploadPackFactory<SshDaemonClient>(gitblit));
-               root.setReceivePackFactory(new GitblitReceivePackFactory<SshDaemonClient>(gitblit));
                root.setAuthenticator(keyAuthenticator);
 
-               root.setContext(new SshCommandContext(gitblit, client, cmdLine));
-
                return root;
        }
 
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/AddKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/AddKeyCommand.java
deleted file mode 100644 (file)
index 35bb1bb..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.gitblit.transport.ssh.commands;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.kohsuke.args4j.Argument;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.gitblit.transport.ssh.CommandMetaData;
-import com.gitblit.transport.ssh.IKeyManager;
-
-/**
- * Add a key to the current user's authorized keys list.
- *
- * @author James Moger
- *
- */
-@CommandMetaData(name = "add-key", description = "Add an SSH public key to your account")
-public class AddKeyCommand extends BaseKeyCommand {
-
-       protected final Logger log = LoggerFactory.getLogger(getClass());
-
-       @Argument(metaVar = "<stdin>|KEY", usage = "the key to add")
-       private List<String> addKeys = new ArrayList<String>();
-
-       @Override
-       public void run() throws IOException, UnloggedFailure {
-               String username = ctx.getClient().getUsername();
-               List<String> keys = readKeys(addKeys);
-               IKeyManager keyManager = authenticator.getKeyManager();
-               for (String key : keys) {
-                       keyManager.addKey(username, key);
-                       log.info("added SSH public key for {}", username);
-               }
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/BaseGitCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/BaseGitCommand.java
deleted file mode 100644 (file)
index a341161..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gitblit.transport.ssh.commands;
-
-import java.io.IOException;
-
-import org.apache.sshd.server.Environment;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
-import org.eclipse.jgit.transport.resolver.UploadPackFactory;
-import org.kohsuke.args4j.Argument;
-
-import com.gitblit.git.GitblitReceivePackFactory;
-import com.gitblit.git.GitblitUploadPackFactory;
-import com.gitblit.git.RepositoryResolver;
-import com.gitblit.transport.ssh.SshDaemonClient;
-
-/**
- * @author Eric Myhre
- *
- */
-public abstract class BaseGitCommand extends BaseCommand {
-       @Argument(index = 0, metaVar = "REPOSITORY", required = true, usage = "repository name")
-       protected String repository;
-
-       protected RepositoryResolver<SshDaemonClient> repositoryResolver;
-       protected ReceivePackFactory<SshDaemonClient> receivePackFactory;
-       protected UploadPackFactory<SshDaemonClient> uploadPackFactory;
-
-       protected Repository repo;
-
-       @Override
-       public void start(final Environment env) {
-               startThread(new RepositoryCommandRunnable() {
-                       @Override
-                       public void run() throws Exception {
-                               parseCommandLine();
-                               BaseGitCommand.this.service();
-                       }
-
-                       @Override
-                       public String getRepository() {
-                               return repository;
-                       }
-               });
-       }
-
-       private void service() throws IOException, Failure {
-               try {
-                       repo = openRepository();
-                       runImpl();
-               } finally {
-                       if (repo != null) {
-                               repo.close();
-                       }
-               }
-       }
-
-       protected abstract void runImpl() throws IOException, Failure;
-
-       protected Repository openRepository() throws Failure {
-               // Assume any attempt to use \ was by a Windows client
-               // and correct to the more typical / used in Git URIs.
-               //
-               repository = repository.replace('\\', '/');
-               // ssh://git@thishost/path should always be name="/path" here
-               //
-               if (!repository.startsWith("/")) {
-                       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);
-               }
-       }
-
-       public void setRepositoryResolver(RepositoryResolver<SshDaemonClient> repositoryResolver) {
-               this.repositoryResolver = repositoryResolver;
-       }
-
-       public void setReceivePackFactory(GitblitReceivePackFactory<SshDaemonClient> receivePackFactory) {
-               this.receivePackFactory = receivePackFactory;
-       }
-
-       public void setUploadPackFactory(GitblitUploadPackFactory<SshDaemonClient> uploadPackFactory) {
-               this.uploadPackFactory = uploadPackFactory;
-       }
-}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/BaseKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/BaseKeyCommand.java
deleted file mode 100644 (file)
index f92ea6f..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.gitblit.transport.ssh.commands;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.util.List;
-
-import com.gitblit.transport.ssh.CachingPublicKeyAuthenticator;
-import com.google.common.base.Charsets;
-
-/**
- *
- * Base class for commands that read SSH keys from stdin or a parameter list.
- *
- */
-public abstract class BaseKeyCommand extends SshCommand {
-
-       protected List<String> readKeys(List<String> sshKeys)
-                       throws UnsupportedEncodingException, IOException {
-               int idx = -1;
-               if (sshKeys.isEmpty() || ((idx = sshKeys.indexOf("-")) >= 0)) {
-                       String sshKey = "";
-                       BufferedReader br = new BufferedReader(new InputStreamReader(
-                                       in, Charsets.UTF_8));
-                       String line;
-                       while ((line = br.readLine()) != null) {
-                               sshKey += line + "\n";
-                       }
-                       if (idx == -1) {
-                               sshKeys.add(sshKey.trim());
-                       } else {
-                               sshKeys.set(idx, sshKey.trim());
-                       }
-               }
-               return sshKeys;
-       }
-
-       protected CachingPublicKeyAuthenticator authenticator;
-       public void setAuthenticator(CachingPublicKeyAuthenticator authenticator) {
-               this.authenticator = authenticator;
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/CreateRepository.java b/src/main/java/com/gitblit/transport/ssh/commands/CreateRepository.java
deleted file mode 100644 (file)
index 20f6901..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.gitblit.transport.ssh.commands;
-
-import org.kohsuke.args4j.Option;
-
-import com.gitblit.transport.ssh.CommandMetaData;
-
-@CommandMetaData(name = "create-repository", description = "Create new GIT repository", admin = true, hidden = true)
-public class CreateRepository extends SshCommand {
-
-  @Option(name = "--name", aliases = {"-n"}, required = true, metaVar = "NAME", usage = "name of repository to be created")
-  private String name;
-
-  @Option(name = "--description", aliases = {"-d"}, metaVar = "DESCRIPTION", usage = "description of repository")
-  private String repositoryDescription;
-
-  @Override
-  public void run() {
-    stdout.println(String.format("Repository <%s> was created", name));
-  }
-}
index 00d3b8192d9ba2065b87d41926066fd8412c5fb0..38f1a48f44e2b55f1d9183fdcb20324d227b8c8a 100644 (file)
@@ -30,21 +30,17 @@ import org.kohsuke.args4j.Argument;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.gitblit.git.GitblitReceivePackFactory;
-import com.gitblit.git.GitblitUploadPackFactory;
-import com.gitblit.git.RepositoryResolver;
 import com.gitblit.models.UserModel;
 import com.gitblit.transport.ssh.CommandMetaData;
 import com.gitblit.transport.ssh.CachingPublicKeyAuthenticator;
-import com.gitblit.transport.ssh.SshDaemonClient;
-mport com.gitblit.utils.StringUtils;
+import com.gitblit.transport.ssh.gitblit.BaseKeyCommand;
+import com.gitblit.utils.StringUtils;
 import com.gitblit.utils.cli.SubcommandHandler;
 import com.google.common.base.Charsets;
 import com.google.common.base.Strings;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
 
-public class DispatchCommand extends BaseCommand {
+public abstract class DispatchCommand extends BaseCommand {
 
        private Logger log = LoggerFactory.getLogger(getClass());
 
@@ -62,11 +58,31 @@ public class DispatchCommand extends BaseCommand {
                commands = new HashSet<Class<? extends BaseCommand>>();
        }
 
-       public void registerDispatcher(String name, Command cmd) {
+       public void registerDispatcher(UserModel user, Class<? extends DispatchCommand> cmd) {
+               if (!cmd.isAnnotationPresent(CommandMetaData.class)) {
+                       throw new RuntimeException(MessageFormat.format("{0} must be annotated with {1}!", cmd.getName(),
+                                       CommandMetaData.class.getName()));
+               }
                if (dispatchers == null) {
                        dispatchers = Maps.newHashMap();
                }
-               dispatchers.put(name, cmd);
+
+               CommandMetaData meta = cmd.getAnnotation(CommandMetaData.class);
+               if (meta.admin() && !user.canAdmin()) {
+                       log.debug(MessageFormat.format("excluding admin dispatch command {0} for {1}", meta.name(), user.username));
+                       return;
+               }
+
+               try {
+                       DispatchCommand dispatcher = cmd.newInstance();
+                       dispatcher.registerCommands(user);
+                       dispatchers.put(meta.name(), dispatcher);
+               } catch (Exception e) {
+                       log.error("failed to register {} dispatcher", meta.name());
+               }
+       }
+
+       protected void registerCommands(UserModel user) {
        }
 
 
@@ -237,41 +253,12 @@ public class DispatchCommand extends BaseCommand {
                cmd.setErrorStream(err);
                cmd.setExitCallback(exit);
 
-               if (cmd instanceof BaseGitCommand) {
-                       BaseGitCommand a = (BaseGitCommand) cmd;
-                       a.setRepositoryResolver(repositoryResolver);
-                       a.setUploadPackFactory(gitblitUploadPackFactory);
-                       a.setReceivePackFactory(gitblitReceivePackFactory);
-               } else if (cmd instanceof DispatchCommand) {
-                       DispatchCommand d = (DispatchCommand) cmd;
-                       d.setRepositoryResolver(repositoryResolver);
-                       d.setUploadPackFactory(gitblitUploadPackFactory);
-                       d.setReceivePackFactory(gitblitReceivePackFactory);
-                       d.setAuthenticator(authenticator);
-               } else if (cmd instanceof BaseKeyCommand) {
+               if (cmd instanceof BaseKeyCommand) {
                        BaseKeyCommand k = (BaseKeyCommand) cmd;
                        k.setAuthenticator(authenticator);
                }
        }
 
-       private RepositoryResolver<SshDaemonClient> repositoryResolver;
-
-       public void setRepositoryResolver(RepositoryResolver<SshDaemonClient> repositoryResolver) {
-               this.repositoryResolver = repositoryResolver;
-       }
-
-       private GitblitUploadPackFactory<SshDaemonClient> gitblitUploadPackFactory;
-
-       public void setUploadPackFactory(GitblitUploadPackFactory<SshDaemonClient> gitblitUploadPackFactory) {
-               this.gitblitUploadPackFactory = gitblitUploadPackFactory;
-       }
-
-       private GitblitReceivePackFactory<SshDaemonClient> gitblitReceivePackFactory;
-
-       public void setReceivePackFactory(GitblitReceivePackFactory<SshDaemonClient> gitblitReceivePackFactory) {
-               this.gitblitReceivePackFactory = gitblitReceivePackFactory;
-       }
-
        private CachingPublicKeyAuthenticator authenticator;
 
        public void setAuthenticator(CachingPublicKeyAuthenticator authenticator) {
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/ListRepositoriesCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/ListRepositoriesCommand.java
deleted file mode 100644 (file)
index 7c58e7f..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.gitblit.transport.ssh.commands;
-
-import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
-import java.util.List;
-
-import org.kohsuke.args4j.Option;
-import org.parboiled.common.StringUtils;
-
-import com.gitblit.manager.IGitblit;
-import com.gitblit.models.RepositoryModel;
-import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.CommandMetaData;
-
-@CommandMetaData(name = "repositories", description = "List the available repositories")
-public class ListRepositoriesCommand extends SshCommand {
-
-       @Option(name = "--verbose", aliases = { "-v" }, usage = "verbose")
-       private boolean verbose;
-
-       @Override
-       public void run() {
-               IGitblit gitblit = ctx.getGitblit();
-               UserModel user = ctx.getClient().getUser();
-               List<RepositoryModel> repositories = gitblit.getRepositoryModels(user);
-               int nameLen = 0;
-               int descLen = 0;
-               for (RepositoryModel repo : repositories) {
-                       int len = repo.name.length();
-                       if (len > nameLen) {
-                               nameLen = len;
-                       }
-                       if (!StringUtils.isEmpty(repo.description)) {
-                               len = repo.description.length();
-                               if (len > descLen) {
-                                       descLen = len;
-                               }
-                       }
-               }
-               SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
-
-               String pattern;
-               if (verbose) {
-                       pattern = MessageFormat.format("%-{0,number,0}s\t%-{1,number,0}s\t%s", nameLen, descLen);
-               } else {
-                       pattern = "%s";
-               }
-
-               for (RepositoryModel repo : repositories) {
-                       stdout.println(String.format(pattern,
-                                       repo.name,
-                                       repo.description == null ? "" : repo.description,
-                                       df.format(repo.lastChange)));
-               }
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/Receive.java b/src/main/java/com/gitblit/transport/ssh/commands/Receive.java
deleted file mode 100644 (file)
index 559cfa5..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gitblit.transport.ssh.commands;
-
-import org.eclipse.jgit.transport.ReceivePack;
-
-import com.gitblit.transport.ssh.CommandMetaData;
-
-@CommandMetaData(name = "git-receive-pack", description = "Receive pack")
-public class Receive extends BaseGitCommand {
-       @Override
-       protected void runImpl() throws Failure {
-               try {
-                       ReceivePack rp = receivePackFactory.create(ctx.getClient(), repo);
-                       rp.receive(in, out, null);
-               } catch (Exception e) {
-                       throw new Failure(1, "fatal: Cannot receive pack: ", e);
-               }
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/RemoveKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/RemoveKeyCommand.java
deleted file mode 100644 (file)
index 90e7041..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.gitblit.transport.ssh.commands;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.kohsuke.args4j.Argument;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.gitblit.transport.ssh.CommandMetaData;
-import com.gitblit.transport.ssh.IKeyManager;
-
-
-/**
- * Remove an SSH public key from the current user's authorized key list.
- *
- * @author James Moger
- *
- */
-@CommandMetaData(name = "rm-key", description = "Remove an SSH public key from your account")
-public class RemoveKeyCommand extends BaseKeyCommand {
-
-       protected final Logger log = LoggerFactory.getLogger(getClass());
-
-       private static final String ALL = "ALL";
-
-       @Argument(metaVar = "<stdin>|<KEY>|ALL", usage = "the key to remove")
-       private List<String> removeKeys = new ArrayList<String>();
-
-       @Override
-       public void run() throws IOException, UnloggedFailure {
-               String username = ctx.getClient().getUsername();
-               List<String> keys = readKeys(removeKeys);
-               IKeyManager keyManager = authenticator.getKeyManager();
-               if (keys.contains(ALL)) {
-                       keyManager.removeAllKeys(username);
-                       log.info("removed all SSH public keys from {}", username);
-               } else {
-                       for (String key : keys) {
-                               keyManager.removeKey(username, key);
-                               log.info("removed SSH public key from {}", username);
-                       }
-               }
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/ReviewCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/ReviewCommand.java
deleted file mode 100644 (file)
index b088a2e..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gitblit.transport.ssh.commands;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
-
-import com.gitblit.models.TicketModel.Change;
-import com.gitblit.models.TicketModel.Patchset;
-import com.gitblit.models.TicketModel.Score;
-import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.CommandMetaData;
-import com.gitblit.wicket.GitBlitWebSession;
-
-@CommandMetaData(name = "review", description = "Verify, approve and/or submit one or more patch sets", hidden = true)
-public class ReviewCommand extends SshCommand {
-
-       private final static short REV_ID_LEN = 40;
-       private final Set<Patchset> patchSets = new HashSet<Patchset>();
-
-       @Argument(index = 0, required = true, multiValued = true, metaVar = "{COMMIT | CHANGE,PATCHSET}", usage = "list of commits or patch sets to review")
-       void addPatchSetId(final String token) {
-               try {
-                       patchSets.add(parsePatchSet(token));
-               } catch (UnloggedFailure e) {
-                       throw new IllegalArgumentException(e.getMessage(), e);
-               }
-       }
-
-       @Option(name = "--project", required = true, aliases = "-p", usage = "project containing the specified patch set(s)")
-       private String project;
-
-       @Option(name = "--message", aliases = "-m", usage = "cover message to publish on change(s)", metaVar = "MESSAGE")
-       private String changeComment;
-
-       @Option(name = "--vote", aliases = "-v", usage = "vote on this patch set", metaVar = "VOTE")
-       private int vote;
-
-       @Option(name = "--submit", aliases = "-s", usage = "submit the specified patch set(s)")
-       private boolean submitChange;
-
-       @Override
-       public void run() throws UnloggedFailure {
-               UserModel user = GitBlitWebSession.get().getUser();
-               // TODO ensure user has permission to score +2/-2
-               for (Patchset ps : patchSets) {
-                       // review
-                       Change change = new Change(user.username);
-                       change.review(ps, Score.fromScore(vote), false);
-                       // TODO(davido): add patchset comment
-                       if (submitChange) {
-                               // TODO(davido): merge (when desired and the change is mergeable)
-                       }
-               }
-       }
-
-       private Patchset parsePatchSet(String ps) throws UnloggedFailure {
-               // By commit?
-               //
-               if (ps.matches("^([0-9a-fA-F]{4," + REV_ID_LEN + "})$")) {
-                       // TODO; parse
-               }
-
-               // By older style change,patchset?
-               //
-               if (ps.matches("^[1-9][0-9]*,[1-9][0-9]*$")) {
-                       // TODO: parse
-               }
-
-               throw new UnloggedFailure(1, "fatal: Cannot parse patchset: " + ps);
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/SetAccountCommand.java
deleted file mode 100644 (file)
index 1f0d902..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-//Copyright (C) 2012 The Android Open Source Project
-//
-//Licensed under the Apache License, Version 2.0 (the "License");
-//you may not use this file except in compliance with the License.
-//You may obtain a copy of the License at
-//
-//http://www.apache.org/licenses/LICENSE-2.0
-//
-//Unless required by applicable law or agreed to in writing, software
-//distributed under the License is distributed on an "AS IS" BASIS,
-//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//See the License for the specific language governing permissions and
-//limitations under the License.
-
-package com.gitblit.transport.ssh.commands;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
-
-import com.gitblit.transport.ssh.CommandMetaData;
-import com.gitblit.transport.ssh.IKeyManager;
-
-/** Set a user's account settings. **/
-@CommandMetaData(name = "set-account", description = "Change an account's settings", admin = true)
-public class SetAccountCommand extends BaseKeyCommand {
-
-       private static final String ALL = "ALL";
-
-       @Argument(index = 0, required = true, metaVar = "USER", usage = "full name, email-address, ssh username or account id")
-       private String user;
-
-       @Option(name = "--add-ssh-key", metaVar = "-|KEY", usage = "public keys to add to the account")
-       private List<String> addSshKeys = new ArrayList<String>();
-
-       @Option(name = "--delete-ssh-key", metaVar = "-|KEY", usage = "public keys to delete from the account")
-       private List<String> deleteSshKeys = new ArrayList<String>();
-
-       @Override
-       public void run() throws IOException, UnloggedFailure {
-               validate();
-               setAccount();
-       }
-
-       private void validate() throws UnloggedFailure {
-               if (addSshKeys.contains("-") && deleteSshKeys.contains("-")) {
-                       throw new UnloggedFailure(1, "Only one option may use the stdin");
-               }
-               if (deleteSshKeys.contains(ALL)) {
-                       deleteSshKeys = Collections.singletonList(ALL);
-               }
-       }
-
-       private void setAccount() throws IOException, UnloggedFailure {
-               addSshKeys = readKeys(addSshKeys);
-               if (!addSshKeys.isEmpty()) {
-                       addSshKeys(addSshKeys);
-               }
-
-               deleteSshKeys = readKeys(deleteSshKeys);
-               if (!deleteSshKeys.isEmpty()) {
-                       deleteSshKeys(deleteSshKeys);
-               }
-       }
-
-       private void addSshKeys(List<String> sshKeys) throws UnloggedFailure,
-                       IOException {
-               IKeyManager keyManager = authenticator.getKeyManager();
-               for (String sshKey : sshKeys) {
-                       keyManager.addKey(user, sshKey);
-               }
-       }
-
-       private void deleteSshKeys(List<String> sshKeys) {
-               IKeyManager keyManager = authenticator.getKeyManager();
-               if (sshKeys.contains(ALL)) {
-                       keyManager.removeAllKeys(user);
-               } else {
-                       for (String sshKey : sshKeys) {
-                               keyManager.removeKey(user, sshKey);
-                       }
-               }
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/Upload.java b/src/main/java/com/gitblit/transport/ssh/commands/Upload.java
deleted file mode 100644 (file)
index ac98bb2..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gitblit.transport.ssh.commands;
-
-import org.eclipse.jgit.transport.UploadPack;
-
-import com.gitblit.transport.ssh.CommandMetaData;
-
-@CommandMetaData(name = "git-upload-pack", description = "Upload pack")
-public class Upload extends BaseGitCommand {
-       @Override
-       protected void runImpl() throws Failure {
-               try {
-                       UploadPack up = uploadPackFactory.create(ctx.getClient(), repo);
-                       up.upload(in, out, null);
-               } catch (Exception e) {
-                       throw new Failure(1, "fatal: Cannot upload pack: ", e);
-               }
-       }
-}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/VersionCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/VersionCommand.java
deleted file mode 100644 (file)
index c2c4f52..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.gitblit.transport.ssh.commands;
-
-import com.gitblit.Constants;
-import com.gitblit.transport.ssh.CommandMetaData;
-
-@CommandMetaData(name="version", description = "Display the Gitblit version")
-public class VersionCommand extends SshCommand {
-
-  @Override
-  public void run() {
-         stdout.println(Constants.getGitBlitVersion());
-  }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/git/BaseGitCommand.java b/src/main/java/com/gitblit/transport/ssh/git/BaseGitCommand.java
new file mode 100644 (file)
index 0000000..b203d47
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.transport.ssh.git;
+
+import java.io.IOException;
+
+import org.apache.sshd.server.Environment;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
+import org.eclipse.jgit.transport.resolver.UploadPackFactory;
+import org.kohsuke.args4j.Argument;
+
+import com.gitblit.git.GitblitReceivePackFactory;
+import com.gitblit.git.GitblitUploadPackFactory;
+import com.gitblit.git.RepositoryResolver;
+import com.gitblit.transport.ssh.SshDaemonClient;
+import com.gitblit.transport.ssh.commands.BaseCommand;
+
+/**
+ * @author Eric Myhre
+ *
+ */
+abstract class BaseGitCommand extends BaseCommand {
+       @Argument(index = 0, metaVar = "REPOSITORY", required = true, usage = "repository name")
+       protected String repository;
+
+       protected RepositoryResolver<SshDaemonClient> repositoryResolver;
+       protected ReceivePackFactory<SshDaemonClient> receivePackFactory;
+       protected UploadPackFactory<SshDaemonClient> uploadPackFactory;
+
+       protected Repository repo;
+
+       @Override
+       public void start(final Environment env) {
+               startThread(new RepositoryCommandRunnable() {
+                       @Override
+                       public void run() throws Exception {
+                               parseCommandLine();
+                               BaseGitCommand.this.service();
+                       }
+
+                       @Override
+                       public String getRepository() {
+                               return repository;
+                       }
+               });
+       }
+
+       private void service() throws IOException, Failure {
+               try {
+                       repo = openRepository();
+                       runImpl();
+               } finally {
+                       if (repo != null) {
+                               repo.close();
+                       }
+               }
+       }
+
+       protected abstract void runImpl() throws IOException, Failure;
+
+       protected Repository openRepository() throws Failure {
+               // Assume any attempt to use \ was by a Windows client
+               // and correct to the more typical / used in Git URIs.
+               //
+               repository = repository.replace('\\', '/');
+               // ssh://git@thishost/path should always be name="/path" here
+               //
+               if (!repository.startsWith("/")) {
+                       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);
+               }
+       }
+
+       public void setRepositoryResolver(RepositoryResolver<SshDaemonClient> repositoryResolver) {
+               this.repositoryResolver = repositoryResolver;
+       }
+
+       public void setReceivePackFactory(GitblitReceivePackFactory<SshDaemonClient> receivePackFactory) {
+               this.receivePackFactory = receivePackFactory;
+       }
+
+       public void setUploadPackFactory(GitblitUploadPackFactory<SshDaemonClient> uploadPackFactory) {
+               this.uploadPackFactory = uploadPackFactory;
+       }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/transport/ssh/git/GitDispatchCommand.java b/src/main/java/com/gitblit/transport/ssh/git/GitDispatchCommand.java
new file mode 100644 (file)
index 0000000..adeace5
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.transport.ssh.git;
+
+import com.gitblit.git.GitblitReceivePackFactory;
+import com.gitblit.git.GitblitUploadPackFactory;
+import com.gitblit.git.RepositoryResolver;
+import com.gitblit.manager.IGitblit;
+import com.gitblit.models.UserModel;
+import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.transport.ssh.SshCommandContext;
+import com.gitblit.transport.ssh.SshDaemonClient;
+import com.gitblit.transport.ssh.commands.BaseCommand;
+import com.gitblit.transport.ssh.commands.DispatchCommand;
+
+@CommandMetaData(name = "git", description="Dispatcher for git receive and upload commands", hidden = true)
+public class GitDispatchCommand extends DispatchCommand {
+
+       protected RepositoryResolver<SshDaemonClient> repositoryResolver;
+       protected GitblitUploadPackFactory<SshDaemonClient> uploadPackFactory;
+       protected GitblitReceivePackFactory<SshDaemonClient> receivePackFactory;
+
+       @Override
+       public void setContext(SshCommandContext context) {
+               super.setContext(context);
+
+               IGitblit gitblit = context.getGitblit();
+               repositoryResolver = new RepositoryResolver<SshDaemonClient>(gitblit);
+               uploadPackFactory = new GitblitUploadPackFactory<SshDaemonClient>(gitblit);
+               receivePackFactory = new GitblitReceivePackFactory<SshDaemonClient>(gitblit);
+       }
+
+       @Override
+       protected void registerCommands(UserModel user) {
+               registerCommand(user, Upload.class);
+               registerCommand(user, Receive.class);
+       }
+
+       @Override
+       protected void provideStateTo(final BaseCommand cmd) {
+               super.provideStateTo(cmd);
+
+               BaseGitCommand a = (BaseGitCommand) cmd;
+               a.setRepositoryResolver(repositoryResolver);
+               a.setUploadPackFactory(uploadPackFactory);
+               a.setReceivePackFactory(receivePackFactory);
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/git/Receive.java b/src/main/java/com/gitblit/transport/ssh/git/Receive.java
new file mode 100644 (file)
index 0000000..4089f1d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.transport.ssh.git;
+
+import org.eclipse.jgit.transport.ReceivePack;
+
+import com.gitblit.transport.ssh.CommandMetaData;
+
+@CommandMetaData(name = "git-receive-pack", description = "Receives pushes from a client")
+public class Receive extends BaseGitCommand {
+       @Override
+       protected void runImpl() throws Failure {
+               try {
+                       ReceivePack rp = receivePackFactory.create(ctx.getClient(), repo);
+                       rp.receive(in, out, null);
+               } catch (Exception e) {
+                       throw new Failure(1, "fatal: Cannot receive pack: ", e);
+               }
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/git/Upload.java b/src/main/java/com/gitblit/transport/ssh/git/Upload.java
new file mode 100644 (file)
index 0000000..5793c3e
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.transport.ssh.git;
+
+import org.eclipse.jgit.transport.UploadPack;
+
+import com.gitblit.transport.ssh.CommandMetaData;
+
+@CommandMetaData(name = "git-upload-pack", description = "Sends packs to a client for clone and fetch")
+public class Upload extends BaseGitCommand {
+       @Override
+       protected void runImpl() throws Failure {
+               try {
+                       UploadPack up = uploadPackFactory.create(ctx.getClient(), repo);
+                       up.upload(in, out, null);
+               } catch (Exception e) {
+                       throw new Failure(1, "fatal: Cannot upload pack: ", e);
+               }
+       }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/AddKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/AddKeyCommand.java
new file mode 100644 (file)
index 0000000..6d5c85c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.gitblit.transport.ssh.gitblit;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.transport.ssh.CommandMetaData;
+
+/**
+ * Add a key to the current user's authorized keys list.
+ *
+ * @author James Moger
+ *
+ */
+@CommandMetaData(name = "add-key", description = "Add an SSH public key to your account")
+public class AddKeyCommand extends BaseKeyCommand {
+
+       protected final Logger log = LoggerFactory.getLogger(getClass());
+
+       @Argument(metaVar = "<stdin>|KEY", usage = "the key to add")
+       private List<String> addKeys = new ArrayList<String>();
+
+       @Override
+       public void run() throws IOException, UnloggedFailure {
+               String username = ctx.getClient().getUsername();
+               List<String> keys = readKeys(addKeys);
+               for (String key : keys) {
+                       getKeyManager().addKey(username, key);
+                       log.info("added SSH public key for {}", username);
+               }
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java
new file mode 100644 (file)
index 0000000..0909957
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.gitblit.transport.ssh.gitblit;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import com.gitblit.transport.ssh.IKeyManager;
+import com.gitblit.transport.ssh.CachingPublicKeyAuthenticator;
+import com.gitblit.transport.ssh.commands.SshCommand;
+import com.google.common.base.Charsets;
+
+/**
+ *
+ * Base class for commands that read SSH keys from stdin or a parameter list.
+ *
+ */
+abstract class BaseKeyCommand extends SshCommand {
+
+       protected List<String> readKeys(List<String> sshKeys)
+                       throws UnsupportedEncodingException, IOException {
+               int idx = -1;
+               if (sshKeys.isEmpty() || ((idx = sshKeys.indexOf("-")) >= 0)) {
+                       String sshKey = "";
+                       BufferedReader br = new BufferedReader(new InputStreamReader(
+                                       in, Charsets.UTF_8));
+                       String line;
+                       while ((line = br.readLine()) != null) {
+                               sshKey += line + "\n";
+                       }
+                       if (idx == -1) {
+                               sshKeys.add(sshKey.trim());
+                       } else {
+                               sshKeys.set(idx, sshKey.trim());
+                       }
+               }
+               return sshKeys;
+       }
+
+       protected CachingPublicKeyAuthenticator authenticator;
+       public void setAuthenticator(CachingPublicKeyAuthenticator authenticator) {
+               this.authenticator = authenticator;
+       }
+       
+       protected IKeyManager getKeyManager() {
+               return authenticator.getKeyManager();
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/CreateRepository.java b/src/main/java/com/gitblit/transport/ssh/gitblit/CreateRepository.java
new file mode 100644 (file)
index 0000000..b2e1b1b
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.gitblit.transport.ssh.gitblit;
+
+import org.kohsuke.args4j.Option;
+
+import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.transport.ssh.commands.SshCommand;
+
+@CommandMetaData(name = "create-repository", description = "Create new GIT repository", admin = true, hidden = true)
+public class CreateRepository extends SshCommand {
+
+  @Option(name = "--name", aliases = {"-n"}, required = true, metaVar = "NAME", usage = "name of repository to be created")
+  private String name;
+
+  @Option(name = "--description", aliases = {"-d"}, metaVar = "DESCRIPTION", usage = "description of repository")
+  private String repositoryDescription;
+
+  @Override
+  public void run() {
+    stdout.println(String.format("Repository <%s> was created", name));
+  }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/GitblitDispatchCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/GitblitDispatchCommand.java
new file mode 100644 (file)
index 0000000..544b204
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.transport.ssh.gitblit;
+
+import com.gitblit.models.UserModel;
+import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.transport.ssh.commands.DispatchCommand;
+
+@CommandMetaData(name = "gitblit", description = "Gitblit server commands")
+public class GitblitDispatchCommand extends DispatchCommand {
+
+       @Override
+       protected void registerCommands(UserModel user) {
+               // normal usage commands
+               registerCommand(user, VersionCommand.class);
+               registerCommand(user, AddKeyCommand.class);
+               registerCommand(user, RemoveKeyCommand.class);
+               registerCommand(user, LsCommand.class);
+               registerCommand(user, ReviewCommand.class);
+
+               // administrative commands
+               registerCommand(user, CreateRepository.class);
+               registerCommand(user, SetAccountCommand.class);
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/LsCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/LsCommand.java
new file mode 100644 (file)
index 0000000..cf50a2e
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.gitblit.transport.ssh.gitblit;
+
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.List;
+
+import org.kohsuke.args4j.Option;
+import org.parboiled.common.StringUtils;
+
+import com.gitblit.manager.IGitblit;
+import com.gitblit.models.ProjectModel;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.UserModel;
+import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.transport.ssh.commands.SshCommand;
+
+@CommandMetaData(name = "ls", description = "List repositories or projects")
+public class LsCommand extends SshCommand {
+
+       @Option(name = "--projects", aliases = { "-p" }, usage = "list projects")
+       private boolean projects;
+
+       @Option(name = "--verbose", aliases = { "-v" }, usage = "verbose")
+       private boolean verbose;
+
+       @Override
+       public void run() {
+               if (projects) {
+                       listProjects();
+               } else {
+                       listRepositories();
+               }
+       }
+
+       protected void listProjects() {
+               IGitblit gitblit = ctx.getGitblit();
+               UserModel user = ctx.getClient().getUser();
+               SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+
+               List<ProjectModel> projects = gitblit.getProjectModels(user, false);
+               int nameLen = 0;
+               int descLen = 0;
+               for (ProjectModel project : projects) {
+                       int len = project.name.length();
+                       if (len > nameLen) {
+                               nameLen = len;
+                       }
+                       if (!StringUtils.isEmpty(project.description)) {
+                               len = project.description.length();
+                               if (len > descLen) {
+                                       descLen = len;
+                               }
+                       }
+               }
+
+               String pattern;
+               if (verbose) {
+                       pattern = MessageFormat.format("%-{0,number,0}s\t%-{1,number,0}s\t%s", nameLen, descLen);
+               } else {
+                       pattern = "%s";
+               }
+
+               for (ProjectModel project : projects) {
+                       stdout.println(String.format(pattern,
+                                       project.name,
+                                       project.description == null ? "" : project.description,
+                                       df.format(project.lastChange)));
+               }
+       }
+
+       protected void listRepositories() {
+               IGitblit gitblit = ctx.getGitblit();
+               UserModel user = ctx.getClient().getUser();
+               SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+
+               List<RepositoryModel> repositories = gitblit.getRepositoryModels(user);
+               int nameLen = 0;
+               int descLen = 0;
+               for (RepositoryModel repo : repositories) {
+                       int len = repo.name.length();
+                       if (len > nameLen) {
+                               nameLen = len;
+                       }
+                       if (!StringUtils.isEmpty(repo.description)) {
+                               len = repo.description.length();
+                               if (len > descLen) {
+                                       descLen = len;
+                               }
+                       }
+               }
+
+               String pattern;
+               if (verbose) {
+                       pattern = MessageFormat.format("%-{0,number,0}s\t%-{1,number,0}s\t%s", nameLen, descLen);
+               } else {
+                       pattern = "%s";
+               }
+
+               for (RepositoryModel repo : repositories) {
+                       stdout.println(String.format(pattern,
+                                       repo.name,
+                                       repo.description == null ? "" : repo.description,
+                                       df.format(repo.lastChange)));
+               }
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/RemoveKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/RemoveKeyCommand.java
new file mode 100644 (file)
index 0000000..7c9abfd
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.gitblit.transport.ssh.gitblit;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.transport.ssh.CommandMetaData;
+
+
+/**
+ * Remove an SSH public key from the current user's authorized key list.
+ *
+ * @author James Moger
+ *
+ */
+@CommandMetaData(name = "rm-key", description = "Remove an SSH public key from your account")
+public class RemoveKeyCommand extends BaseKeyCommand {
+
+       protected final Logger log = LoggerFactory.getLogger(getClass());
+
+       private static final String ALL = "ALL";
+
+       @Argument(metaVar = "<stdin>|<KEY>|ALL", usage = "the key to remove")
+       private List<String> removeKeys = new ArrayList<String>();
+
+       @Override
+       public void run() throws IOException, UnloggedFailure {
+               String username = ctx.getClient().getUsername();
+               List<String> keys = readKeys(removeKeys);
+               if (keys.contains(ALL)) {
+                       getKeyManager().removeAllKeys(username);
+                       log.info("removed all SSH public keys from {}", username);
+               } else {
+                       for (String key : keys) {
+                               getKeyManager().removeKey(username, key);
+                               log.info("removed SSH public key from {}", username);
+                       }
+               }
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/ReviewCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/ReviewCommand.java
new file mode 100644 (file)
index 0000000..9e4d8ba
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.transport.ssh.gitblit;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+
+import com.gitblit.models.TicketModel.Change;
+import com.gitblit.models.TicketModel.Patchset;
+import com.gitblit.models.TicketModel.Score;
+import com.gitblit.models.UserModel;
+import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.transport.ssh.commands.SshCommand;
+import com.gitblit.wicket.GitBlitWebSession;
+
+@CommandMetaData(name = "review", description = "Verify, approve and/or submit one or more patch sets", hidden = true)
+public class ReviewCommand extends SshCommand {
+
+       private final static short REV_ID_LEN = 40;
+       private final Set<Patchset> patchSets = new HashSet<Patchset>();
+
+       @Argument(index = 0, required = true, multiValued = true, metaVar = "{COMMIT | CHANGE,PATCHSET}", usage = "list of commits or patch sets to review")
+       void addPatchSetId(final String token) {
+               try {
+                       patchSets.add(parsePatchSet(token));
+               } catch (UnloggedFailure e) {
+                       throw new IllegalArgumentException(e.getMessage(), e);
+               }
+       }
+
+       @Option(name = "--project", required = true, aliases = "-p", usage = "project containing the specified patch set(s)")
+       private String project;
+
+       @Option(name = "--message", aliases = "-m", usage = "cover message to publish on change(s)", metaVar = "MESSAGE")
+       private String changeComment;
+
+       @Option(name = "--vote", aliases = "-v", usage = "vote on this patch set", metaVar = "VOTE")
+       private int vote;
+
+       @Option(name = "--submit", aliases = "-s", usage = "submit the specified patch set(s)")
+       private boolean submitChange;
+
+       @Override
+       public void run() throws UnloggedFailure {
+               UserModel user = GitBlitWebSession.get().getUser();
+               // TODO ensure user has permission to score +2/-2
+               for (Patchset ps : patchSets) {
+                       // review
+                       Change change = new Change(user.username);
+                       change.review(ps, Score.fromScore(vote), false);
+                       // TODO(davido): add patchset comment
+                       if (submitChange) {
+                               // TODO(davido): merge (when desired and the change is mergeable)
+                       }
+               }
+       }
+
+       private Patchset parsePatchSet(String ps) throws UnloggedFailure {
+               // By commit?
+               //
+               if (ps.matches("^([0-9a-fA-F]{4," + REV_ID_LEN + "})$")) {
+                       // TODO; parse
+               }
+
+               // By older style change,patchset?
+               //
+               if (ps.matches("^[1-9][0-9]*,[1-9][0-9]*$")) {
+                       // TODO: parse
+               }
+
+               throw new UnloggedFailure(1, "fatal: Cannot parse patchset: " + ps);
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/SetAccountCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/SetAccountCommand.java
new file mode 100644 (file)
index 0000000..28ac9e1
--- /dev/null
@@ -0,0 +1,85 @@
+//Copyright (C) 2012 The Android Open Source Project
+//
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+package com.gitblit.transport.ssh.gitblit;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+
+import com.gitblit.transport.ssh.CommandMetaData;
+
+/** Set a user's account settings. **/
+@CommandMetaData(name = "set-account", description = "Change an account's settings", admin = true)
+public class SetAccountCommand extends BaseKeyCommand {
+
+       private static final String ALL = "ALL";
+
+       @Argument(index = 0, required = true, metaVar = "USER", usage = "full name, email-address, ssh username or account id")
+       private String user;
+
+       @Option(name = "--add-ssh-key", metaVar = "-|KEY", usage = "public keys to add to the account")
+       private List<String> addSshKeys = new ArrayList<String>();
+
+       @Option(name = "--delete-ssh-key", metaVar = "-|KEY", usage = "public keys to delete from the account")
+       private List<String> deleteSshKeys = new ArrayList<String>();
+
+       @Override
+       public void run() throws IOException, UnloggedFailure {
+               validate();
+               setAccount();
+       }
+
+       private void validate() throws UnloggedFailure {
+               if (addSshKeys.contains("-") && deleteSshKeys.contains("-")) {
+                       throw new UnloggedFailure(1, "Only one option may use the stdin");
+               }
+               if (deleteSshKeys.contains(ALL)) {
+                       deleteSshKeys = Collections.singletonList(ALL);
+               }
+       }
+
+       private void setAccount() throws IOException, UnloggedFailure {
+               addSshKeys = readKeys(addSshKeys);
+               if (!addSshKeys.isEmpty()) {
+                       addSshKeys(addSshKeys);
+               }
+
+               deleteSshKeys = readKeys(deleteSshKeys);
+               if (!deleteSshKeys.isEmpty()) {
+                       deleteSshKeys(deleteSshKeys);
+               }
+       }
+
+       private void addSshKeys(List<String> sshKeys) throws UnloggedFailure,
+                       IOException {
+               for (String sshKey : sshKeys) {
+                       getKeyManager().addKey(user, sshKey);
+               }
+       }
+
+       private void deleteSshKeys(List<String> sshKeys) {
+               if (sshKeys.contains(ALL)) {
+                       getKeyManager().removeAllKeys(user);
+               } else {
+                       for (String sshKey : sshKeys) {
+                               getKeyManager().removeKey(user, sshKey);
+                       }
+               }
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/VersionCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/VersionCommand.java
new file mode 100644 (file)
index 0000000..513f6d9
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.gitblit.transport.ssh.gitblit;
+
+import com.gitblit.Constants;
+import com.gitblit.transport.ssh.CommandMetaData;
+import com.gitblit.transport.ssh.commands.SshCommand;
+
+@CommandMetaData(name="version", description = "Display the Gitblit version")
+public class VersionCommand extends SshCommand {
+
+  @Override
+  public void run() {
+         stdout.println(Constants.getGitBlitVersion());
+  }
+}