]> source.dussan.org Git - gitblit.git/commitdiff
Split administration commands into a plugin, enhance plugin manager
authorJames Moger <james.moger@gitblit.com>
Sun, 30 Mar 2014 18:21:19 +0000 (14:21 -0400)
committerJames Moger <james.moger@gitblit.com>
Thu, 10 Apr 2014 23:00:52 +0000 (19:00 -0400)
24 files changed:
build.xml
src/main/java/com/gitblit/manager/GitblitManager.java
src/main/java/com/gitblit/manager/IPluginManager.java
src/main/java/com/gitblit/manager/PluginManager.java
src/main/java/com/gitblit/transport/ssh/WelcomeShell.java
src/main/java/com/gitblit/transport/ssh/commands/PluginDispatcher.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/commands/RootDispatcher.java
src/main/java/com/gitblit/transport/ssh/commands/VersionCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/ConfigCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/GitblitDispatcher.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/KeysDispatcher.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/ListDispatcher.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/ProjectsDispatcher.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/RepositoriesDispatcher.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/ReviewCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/TeamsDispatcher.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/TicketsDispatcher.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/UsersDispatcher.java [deleted file]
src/main/java/com/gitblit/transport/ssh/gitblit/VersionCommand.java [deleted file]
src/main/java/com/gitblit/transport/ssh/keys/BaseKeyCommand.java [new file with mode: 0644]
src/main/java/com/gitblit/transport/ssh/keys/KeysDispatcher.java [new file with mode: 0644]
src/site/setup_transport_ssh.mkd
src/test/java/com/gitblit/tests/SshDaemonTest.java

index a802c8276938c010cdeeaefd1a70b6e65d890983..0baf090edadb58cab39df19b9dc938898a9f4d6f 100644 (file)
--- a/build.xml
+++ b/build.xml
                                                <page name="using the Eclipse plugin" src="eclipse_plugin.mkd" />\r
                                        </menu>\r
                                        <divider />\r
-                                       <menu name="Tickets" pager="true" pagerPlacement="bottom" pagerLayout="justified">
-                                         <page name="overview" src="tickets_overview.mkd" />
-                                         <page name="using" src="tickets_using.mkd" />
-                                         <page name="barnum" src="tickets_barnum.mkd" />
+                                       <menu name="Tickets" pager="true" pagerPlacement="bottom" pagerLayout="justified">\r
+                                         <page name="overview" src="tickets_overview.mkd" />\r
+                                         <page name="using" src="tickets_using.mkd" />\r
+                                         <page name="barnum" src="tickets_barnum.mkd" />\r
                                          <page name="setup" src="tickets_setup.mkd" />\r
-                                         <page name="replication &amp; advanced administration" src="tickets_replication.mkd" />
-                                       </menu>
-                                       <divider />
+                                         <page name="replication &amp; advanced administration" src="tickets_replication.mkd" />\r
+                                       </menu>\r
+                                       <divider />\r
                                        <page name="federation" src="federation.mkd" />\r
                                        <divider />\r
                                        <page name="settings" src="properties.mkd" />\r
                                                        <page name="using the Eclipse plugin" src="eclipse_plugin.mkd" />\r
                                                </menu>\r
                                                <divider />\r
-                                               <menu name="Tickets" pager="true" pagerPlacement="bottom" pagerLayout="justified">
-                                                       <page name="overview" src="tickets_overview.mkd" />
-                                                       <page name="using" src="tickets_using.mkd" />
-                                                       <page name="barnum" src="tickets_barnum.mkd" />
-                                                       <page name="setup" src="tickets_setup.mkd" />
+                                               <menu name="Tickets" pager="true" pagerPlacement="bottom" pagerLayout="justified">\r
+                                                       <page name="overview" src="tickets_overview.mkd" />\r
+                                                       <page name="using" src="tickets_using.mkd" />\r
+                                                       <page name="barnum" src="tickets_barnum.mkd" />\r
+                                                       <page name="setup" src="tickets_setup.mkd" />\r
                                                        <page name="replication &amp; advanced administration" src="tickets_replication.mkd" />\r
-                                               </menu>
-                                               <divider />
+                                               </menu>\r
+                                               <divider />\r
                                                <page name="federation" src="federation.mkd" />\r
                                                <divider />\r
                                                <page name="settings" src="properties.mkd" />\r
                        <arg value="-DcreateChecksum=true" />\r
                </exec>\r
        </target>\r
+\r
+       <!--\r
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+               Install Gitblit JAR for usage as Moxie artifact\r
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+       -->\r
+       <target name="installMoxie" depends="compile" description="Install Gitblit JAR as a Moxie artifact">\r
+               <local name="project.jar" />\r
+               <property name="project.jar" value="${project.targetDirectory}/${project.artifactId}-${project.version}.jar" />\r
+               <property name="resourceFolderPrefix" value="" />\r
+               <mx:jar destfile="${project.jar}" includeresources="true" resourceFolderPrefix="${resourceFolderPrefix}" />\r
+\r
+               <mx:install />\r
+       </target>\r
        \r
 </project>\r
index 0001706c637f1369e27e07f9a1e9b3f37500335d..6b1cc8a547290a60d1b75fa088abaf920fb6be65 100644 (file)
@@ -42,7 +42,9 @@ import org.eclipse.jgit.transport.RefSpec;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import ro.fortsoft.pf4j.PluginClassLoader;
 import ro.fortsoft.pf4j.PluginWrapper;
+import ro.fortsoft.pf4j.RuntimeMode;
 
 import com.gitblit.Constants;
 import com.gitblit.Constants.AccessPermission;
@@ -1187,4 +1189,54 @@ public class GitblitManager implements IGitblit {
        public PluginWrapper whichPlugin(Class<?> clazz) {
                return pluginManager.whichPlugin(clazz);
        }
+
+       @Override
+       public boolean deletePlugin(PluginWrapper wrapper) {
+               return pluginManager.deletePlugin(wrapper);
+       }
+
+       @Override
+       public List<PluginWrapper> getPlugins() {
+               return pluginManager.getPlugins();
+       }
+
+       @Override
+       public List<PluginWrapper> getResolvedPlugins() {
+               return pluginManager.getResolvedPlugins();
+       }
+
+       @Override
+       public List<PluginWrapper> getUnresolvedPlugins() {
+               return pluginManager.getUnresolvedPlugins();
+       }
+
+       @Override
+       public List<PluginWrapper> getStartedPlugins() {
+               return pluginManager.getStartedPlugins();
+       }
+
+       @Override
+       public void loadPlugins() {
+               pluginManager.loadPlugins();
+       }
+
+       @Override
+       public void startPlugins() {
+               pluginManager.startPlugins();
+       }
+
+       @Override
+       public void stopPlugins() {
+               pluginManager.stopPlugins();
+       }
+
+       @Override
+       public PluginClassLoader getPluginClassLoader(String pluginId) {
+               return pluginManager.getPluginClassLoader(pluginId);
+       }
+
+       @Override
+       public RuntimeMode getRuntimeMode() {
+               return pluginManager.getRuntimeMode();
+       }
 }
index 670e97693fe095f57b0b06d5fea6ae83ca286d94..11b81ea3b2c6d1054d194ef72f10a2b9db1bfe12 100644 (file)
  */
 package com.gitblit.manager;
 
-import java.util.List;
-
+import ro.fortsoft.pf4j.PluginManager;
 import ro.fortsoft.pf4j.PluginWrapper;
 
-public interface IPluginManager extends IManager {
-
-       /**
-        * Retrieves the extension for given class 'clazz'.
-        *
-        * @param clazz extension point class to retrieve extension for
-        * @return list of extensions
-        */
-       public <T> List<T> getExtensions(Class<T> clazz);
+public interface IPluginManager extends IManager, PluginManager {
 
        /**
      * Retrieves the {@link PluginWrapper} that loaded the given class 'clazz'.
@@ -35,5 +26,13 @@ public interface IPluginManager extends IManager {
      * @param clazz extension point class to retrieve extension for
      * @return PluginWrapper that loaded the given class
      */
-    public PluginWrapper whichPlugin(Class<?> clazz);
+    PluginWrapper whichPlugin(Class<?> clazz);
+    
+    /**
+     * Delete the plugin represented by {@link PluginWrapper}.
+     * 
+     * @param wrapper
+     * @return true if successful
+     */
+    boolean deletePlugin(PluginWrapper wrapper);
 }
index 5eb00e92c32f6fb74bb1ef3a3762021735f70b24..e23aaec00ac4257527a87c7096be379184f69ff7 100644 (file)
  */
 package com.gitblit.manager;
 
+import java.io.File;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import ro.fortsoft.pf4j.DefaultPluginManager;
+import ro.fortsoft.pf4j.PluginWrapper;
 
 import com.gitblit.Keys;
+import com.gitblit.utils.FileUtils;
 
 /**
  * The plugin manager maintains the lifecycle of plugins. It is exposed as
@@ -30,27 +34,45 @@ import com.gitblit.Keys;
  * @author David Ostrovsky
  * 
  */
-public class PluginManager extends DefaultPluginManager implements
-               IPluginManager {
+public class PluginManager extends DefaultPluginManager implements IPluginManager {
 
        private final Logger logger = LoggerFactory.getLogger(getClass());
+       
+       private final IRuntimeManager runtimeManager;
 
        public PluginManager(IRuntimeManager runtimeManager) {
-               super(runtimeManager.getFileOrFolder(Keys.plugins.folder,
-                               "${baseFolder}/plugins"));
+               super(runtimeManager.getFileOrFolder(Keys.plugins.folder, "${baseFolder}/plugins"));
+               this.runtimeManager = runtimeManager;
        }
 
        @Override
        public PluginManager start() {
-               logger.info("Plugin manager started");
+               logger.info("Loading plugins...");
                loadPlugins();
+               logger.info("Starting loaded plugins...");
                startPlugins();
                return this;
        }
 
        @Override
        public PluginManager stop() {
+               logger.info("Stopping loaded plugins...");
                stopPlugins();
                return null;
        }
+       
+       @Override
+       public boolean deletePlugin(PluginWrapper pw) {
+               File folder = runtimeManager.getFileOrFolder(Keys.plugins.folder, "${baseFolder}/plugins");
+               File pluginFolder = new File(folder, pw.getPluginPath());
+               File pluginZip = new File(folder, pw.getPluginPath() + ".zip");
+               
+               if (pluginFolder.exists()) {
+                       FileUtils.delete(pluginFolder);
+               }
+               if (pluginZip.exists()) {
+                       FileUtils.delete(pluginZip);
+               }
+               return true;
+       }
 }
index 6809ba629198b9a8fa1084af2d92d6f85a4a098e..4341a3ead81632557e0237babda0af4c7adb9a48 100644 (file)
@@ -165,7 +165,7 @@ public class WelcomeShell implements Factory<Command> {
                                msg.append(nl);
                                msg.append(nl);
 
-                               msg.append(String.format("   cat ~/.ssh/id_rsa.pub | ssh -l %s -p %d %s gitblit keys add", user.username, port, hostname));
+                               msg.append(String.format("   cat ~/.ssh/id_rsa.pub | ssh -l %s -p %d %s keys add", user.username, port, hostname));
                                msg.append(nl);
                                msg.append(nl);
 
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/PluginDispatcher.java b/src/main/java/com/gitblit/transport/ssh/commands/PluginDispatcher.java
new file mode 100644 (file)
index 0000000..5c413db
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+
+import ro.fortsoft.pf4j.PluginDependency;
+import ro.fortsoft.pf4j.PluginDescriptor;
+import ro.fortsoft.pf4j.PluginState;
+import ro.fortsoft.pf4j.PluginWrapper;
+
+import com.gitblit.manager.IGitblit;
+import com.gitblit.models.UserModel;
+import com.gitblit.utils.FlipTable;
+import com.gitblit.utils.FlipTable.Borders;
+
+/**
+ * The plugin dispatcher and commands for runtime plugin management.
+ *
+ * @author James Moger
+ *
+ */
+@CommandMetaData(name = "plugin", description = "Plugin management commands", admin = true)
+public class PluginDispatcher extends DispatchCommand {
+
+       @Override
+       protected void setup(UserModel user) {
+               register(user, ListPlugins.class);
+               register(user, StartPlugin.class);
+               register(user, StopPlugin.class);
+               register(user, ShowPlugin.class);
+               register(user, RemovePlugin.class);
+               register(user, UploadPlugin.class);
+       }
+
+       @CommandMetaData(name = "list", aliases = { "ls" }, description = "List the loaded plugins")
+       public static class ListPlugins extends ListCommand<PluginWrapper> {
+
+               @Override
+               protected List<PluginWrapper> getItems() throws UnloggedFailure {
+                       IGitblit gitblit = getContext().getGitblit();
+                       List<PluginWrapper> list = gitblit.getPlugins();
+                       return list;
+               }
+
+               @Override
+               protected void asTable(List<PluginWrapper> list) {
+                       String[] headers;
+                       if (verbose) {
+                               String [] h = { "#", "Id", "Version", "State", "Mode", "Path", "Provider"};
+                               headers = h;
+                       } else {
+                               String [] h = { "#", "Id", "Version", "State", "Path"};
+                               headers = h;
+                       }
+                       Object[][] data = new Object[list.size()][];
+                       for (int i = 0; i < list.size(); i++) {
+                               PluginWrapper p = list.get(i);
+                               PluginDescriptor d = p.getDescriptor();
+                               if (verbose) {
+                                       data[i] = new Object[] { "" + (i + 1), d.getPluginId(), d.getVersion(), p.getPluginState(), p.getRuntimeMode(), p.getPluginPath(), d.getProvider() };
+                               } else {
+                                       data[i] = new Object[] { "" + (i + 1), d.getPluginId(), d.getVersion(), p.getPluginState(), p.getPluginPath() };
+                               }
+                       }
+
+                       stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
+               }
+               
+               @Override
+               protected void asTabbed(List<PluginWrapper> list) {
+                       for (PluginWrapper pw : list) {
+                               PluginDescriptor d = pw.getDescriptor();
+                               if (verbose) {
+                                       outTabbed(d.getPluginId(), d.getVersion(), pw.getPluginState(), pw.getRuntimeMode(), pw.getPluginPath(), d.getProvider());
+                               } else {
+                                       outTabbed(d.getPluginId(), d.getVersion(), pw.getPluginState(), pw.getPluginPath());
+                               }
+                       }
+               }
+       }
+       
+       @CommandMetaData(name = "start", description = "Start a plugin")
+       public static class StartPlugin extends SshCommand {
+
+               @Argument(index = 0, required = true, metaVar = "ALL|<id>", usage = "the plugin to start")
+               protected String plugin;
+
+               @Override
+               public void run() throws UnloggedFailure {
+                       IGitblit gitblit = getContext().getGitblit();
+                       if (plugin.equalsIgnoreCase("ALL")) {
+                               gitblit.startPlugins();
+                               stdout.println("All plugins started");
+                       } else {
+                               try {
+                                       int index = Integer.parseInt(plugin);
+                                       List<PluginWrapper> plugins = gitblit.getPlugins();
+                                       if (index > plugins.size()) {
+                                               throw new UnloggedFailure(1,  "Invalid plugin index specified!");
+                                       }
+                                       PluginWrapper pw = plugins.get(index - 1);
+                                       start(pw);
+                               } catch (NumberFormatException n) {
+                                       for (PluginWrapper pw : gitblit.getPlugins()) {
+                                               PluginDescriptor pd = pw.getDescriptor();
+                                               if (pd.getPluginId().equalsIgnoreCase(plugin)) {
+                                                       start(pw);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
+               protected void start(PluginWrapper pw) throws UnloggedFailure {
+                       String id = pw.getDescriptor().getPluginId();
+                       if (pw.getPluginState() == PluginState.STARTED) {
+                               throw new UnloggedFailure(1, String.format("%s is already started.", id));
+                       }
+                       try {
+                               pw.getPlugin().start();
+//             pw.setPluginState(PluginState.STARTED);
+                               stdout.println(String.format("%s started", id));
+                       } catch (Exception pe) {
+                               throw new UnloggedFailure(1, String.format("Failed to start %s", id), pe);
+                       }
+               }
+       }
+       
+
+       @CommandMetaData(name = "stop", description = "Stop a plugin")
+       public static class StopPlugin extends SshCommand {
+
+               @Argument(index = 0, required = true, metaVar = "ALL|<id>", usage = "the plugin to stop")
+               protected String plugin;
+
+               @Override
+               public void run() throws UnloggedFailure {
+                       IGitblit gitblit = getContext().getGitblit();
+                       if (plugin.equalsIgnoreCase("ALL")) {
+                               gitblit.stopPlugins();
+                               stdout.println("All plugins stopped");
+                       } else {
+                               try {
+                               int index = Integer.parseInt(plugin);
+                               List<PluginWrapper> plugins = gitblit.getPlugins();
+                               if (index > plugins.size()) {
+                                       throw new UnloggedFailure(1,  "Invalid plugin index specified!");
+                               }
+                               PluginWrapper pw = plugins.get(index - 1);
+                               stop(pw);
+                       } catch (NumberFormatException n) {
+                               for (PluginWrapper pw : gitblit.getPlugins()) {
+                                       PluginDescriptor pd = pw.getDescriptor();
+                                       if (pd.getPluginId().equalsIgnoreCase(plugin)) {
+                                               stop(pw);
+                                               break;
+                                       }
+                               }
+                       }
+                       }
+               }
+               
+               protected void stop(PluginWrapper pw) throws UnloggedFailure {
+                       String id = pw.getDescriptor().getPluginId();
+                       if (pw.getPluginState() == PluginState.STOPPED) {
+                               throw new UnloggedFailure(1, String.format("%s is already stopped.", id));
+                       }
+                       try {
+                               pw.getPlugin().stop();
+//             pw.setPluginState(PluginState.STOPPED);
+                               stdout.println(String.format("%s stopped", id));
+                       } catch (Exception pe) {
+                               throw new UnloggedFailure(1, String.format("Failed to stop %s", id), pe);
+                       }
+               }
+       }
+       
+       @CommandMetaData(name = "show", description = "Show the details of a plugin")
+       public static class ShowPlugin extends SshCommand {
+
+               @Argument(index = 0, required = true, metaVar = "<id>", usage = "the plugin to stop")
+               protected int index;
+
+               @Override
+               public void run() throws UnloggedFailure {
+                       IGitblit gitblit = getContext().getGitblit();
+                       List<PluginWrapper> plugins = gitblit.getPlugins();
+                       if (index > plugins.size()) {
+                               throw new UnloggedFailure(1, "Invalid plugin index specified!");
+                       }
+                       PluginWrapper pw = plugins.get(index - 1);
+                       PluginDescriptor d = pw.getDescriptor();
+
+                       // FIELDS
+                       StringBuilder sb = new StringBuilder();
+                       sb.append("Version  : ").append(d.getVersion()).append('\n');
+                       sb.append("Provider : ").append(d.getProvider()).append('\n');
+                       sb.append("Path     : ").append(pw.getPluginPath()).append('\n');
+                       sb.append("State    : ").append(pw.getPluginState()).append('\n');
+                       final String fields = sb.toString();
+
+                       // TODO EXTENSIONS
+                       sb.setLength(0);
+                       List<String> exts = new ArrayList<String>();
+                       String extensions;
+                       if (exts.isEmpty()) {
+                               extensions = FlipTable.EMPTY;
+                       } else {
+                               String[] headers = { "Id", "Version" };
+                               Object[][] data = new Object[exts.size()][];
+                               for (int i = 0; i < exts.size(); i++) {
+                                       String ext = exts.get(i);
+                                       data[0] = new Object[] { ext.toString(), ext.toString() };
+                               }
+                               extensions = FlipTable.of(headers, data, Borders.COLS);         
+                       }
+
+                       // DEPENDENCIES
+                       sb.setLength(0);
+                       List<PluginDependency> deps = d.getDependencies();
+                       String dependencies;
+                       if (deps.isEmpty()) {
+                               dependencies = FlipTable.EMPTY;
+                       } else {
+                               String[] headers = { "Id", "Version" };
+                               Object[][] data = new Object[deps.size()][];
+                               for (int i = 0; i < deps.size(); i++) {
+                                       PluginDependency dep = deps.get(i);
+                                       data[0] = new Object[] { dep.getPluginId(), dep.getPluginVersion() };
+                               }
+                               dependencies = FlipTable.of(headers, data, Borders.COLS);               
+                       }
+                       
+                       String[] headers = { d.getPluginId() };
+                       Object[][] data = new Object[5][];
+                       data[0] = new Object[] { fields };
+                       data[1] = new Object[] { "EXTENSIONS" };
+                       data[2] = new Object[] { extensions };
+                       data[3] = new Object[] { "DEPENDENCIES" };
+                       data[4] = new Object[] { dependencies };
+                       stdout.println(FlipTable.of(headers, data));            
+               }
+       }
+       
+       @CommandMetaData(name = "remove", aliases= { "rm", "del" }, description = "Remove a plugin", hidden = true)
+       public static class RemovePlugin extends SshCommand {
+
+               @Argument(index = 0, required = true, metaVar = "<id>", usage = "the plugin to stop")
+               protected int index;
+
+               @Override
+               public void run() throws UnloggedFailure {
+                       IGitblit gitblit = getContext().getGitblit();
+                       List<PluginWrapper> plugins = gitblit.getPlugins();
+                       if (index > plugins.size()) {
+                               throw new UnloggedFailure(1, "Invalid plugin index specified!");
+                       }
+                       PluginWrapper pw = plugins.get(index - 1);
+                       PluginDescriptor d = pw.getDescriptor();
+                       if (gitblit.deletePlugin(pw)) {
+                               stdout.println(String.format("Deleted %s %s", d.getPluginId(), d.getVersion()));
+                       } else {
+                               throw new UnloggedFailure(1,  String.format("Failed to delete %s %s", d.getPluginId(), d.getVersion()));
+                       }
+               }
+       }
+       
+       @CommandMetaData(name = "receive", aliases= { "upload" }, description = "Upload a plugin to the server", hidden = true)
+       public static class UploadPlugin extends SshCommand {
+
+               @Override
+               public void run() throws UnloggedFailure {
+               }
+       }
+}
index 8a871ebbb8a61be7c5ee5ba7f13173ae954ee95d..3c378669ae027bee9e1c67c3aa0b915a8af8bad1 100644 (file)
@@ -24,7 +24,7 @@ import com.gitblit.manager.IGitblit;
 import com.gitblit.models.UserModel;
 import com.gitblit.transport.ssh.SshDaemonClient;
 import com.gitblit.transport.ssh.git.GitDispatcher;
-import com.gitblit.transport.ssh.gitblit.GitblitDispatcher;
+import com.gitblit.transport.ssh.keys.KeysDispatcher;
 
 /**
  * The root dispatcher is the dispatch command that handles registering all
@@ -41,8 +41,10 @@ class RootDispatcher extends DispatchCommand {
                setContext(new SshCommandContext(gitblit, client, cmdLine));
 
                UserModel user = client.getUser();
-               register(user, GitblitDispatcher.class);
+               register(user, VersionCommand.class);
                register(user, GitDispatcher.class);
+               register(user, KeysDispatcher.class);
+               register(user, PluginDispatcher.class);
 
                List<DispatchCommand> exts = gitblit.getExtensions(DispatchCommand.class);
                for (DispatchCommand ext : exts) {
diff --git a/src/main/java/com/gitblit/transport/ssh/commands/VersionCommand.java b/src/main/java/com/gitblit/transport/ssh/commands/VersionCommand.java
new file mode 100644 (file)
index 0000000..3a2fd5e
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+@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/gitblit/BaseKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/BaseKeyCommand.java
deleted file mode 100644 (file)
index 930c058..0000000
+++ /dev/null
@@ -1,67 +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.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.IPublicKeyManager;
-import com.gitblit.transport.ssh.SshKey;
-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 IPublicKeyManager getKeyManager() {
-               return getContext().getGitblit().getPublicKeyManager();
-       }
-
-       protected SshKey parseKey(String rawData) throws UnloggedFailure {
-               if (rawData.contains("PRIVATE")) {
-                       throw new UnloggedFailure(1,  "Please provide a PUBLIC key, not a PRIVATE key!");
-               }
-               SshKey key = new SshKey(rawData);
-               return key;
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/ConfigCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/ConfigCommand.java
deleted file mode 100644 (file)
index f674034..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-package com.gitblit.transport.ssh.gitblit;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
-import org.parboiled.common.StringUtils;
-
-import com.gitblit.manager.IGitblit;
-import com.gitblit.models.ServerSettings;
-import com.gitblit.models.SettingModel;
-import com.gitblit.transport.ssh.commands.CommandMetaData;
-import com.gitblit.transport.ssh.commands.SshCommand;
-import com.gitblit.transport.ssh.commands.UsageExample;
-import com.gitblit.transport.ssh.commands.UsageExamples;
-import com.google.common.collect.Maps;
-
-@CommandMetaData(name = "config", description = "Administer Gitblit settings", admin = true)
-@UsageExamples(examples = {
-               @UsageExample(syntax = "${cmd} --list", description = "List all settings"),
-               @UsageExample(syntax = "${cmd} git.sshPort", description = "Describe the git.sshPort setting"),
-               @UsageExample(syntax = "${cmd} git.sshPort 29418", description = "Set git.sshPort to 29418"),
-               @UsageExample(syntax = "${cmd} git.sshPort --reset", description = "Reset git.sshPort to it's default value"),
-})
-public class ConfigCommand extends SshCommand {
-
-       @Argument(index = 0, metaVar = "KEY", usage = "The setting to describe or update")
-       protected String setting;
-
-       @Argument(index = 1, metaVar = "VALUE", usage = "The new value for the setting")
-       protected String value;
-
-       @Option(name = "--list", aliases = { "-l" }, usage = "List all settings")
-       private boolean listAll;
-
-       @Option(name = "--modified", aliases = { "-m" }, usage = "List modified settings")
-       private boolean listModified;
-
-       @Option(name = "--reset", usage = "Reset a setting to it's default value")
-       private boolean reset;
-
-       @Override
-       public void run() throws UnloggedFailure {
-               IGitblit gitblit = getContext().getGitblit();
-               ServerSettings settings = gitblit.getSettingsModel();
-
-               if (listAll || listModified) {
-                       /*
-                        *  List settings
-                        */
-                       List<SettingModel> list = new ArrayList<SettingModel>();
-                       int maxLen = 0;
-                       for (String key : settings.getKeys()) {
-                               SettingModel model = settings.get(key);
-                               if (listModified) {
-                                       if (!model.isDefaultValue()) {
-                                               list.add(model);
-                                       } else {
-                                               continue;
-                                       }
-                               } else {
-                                       list.add(model);
-                               }
-
-                               if (key.length() > maxLen) {
-                                       maxLen = key.length();
-                               }
-                       }
-                       String pattern = MessageFormat.format("%s%-{0,number,0}s : %s", maxLen);
-                       for (SettingModel model : list) {
-                               stdout.println(String.format(pattern,
-                                               model.isDefaultValue() ? " " : "*",
-                                               model.name,
-                                               model.currentValue));
-                       }
-               } else if (!StringUtils.isEmpty(setting) && value == null && !reset) {
-                       /*
-                        *  Describe a setting
-                        */
-                       SettingModel model = settings.get(setting);
-                       if (model == null) {
-                               // unknown setting
-                               String value = gitblit.getSettings().getString(setting, null);
-                               if (value == null) {
-                                       // setting does not exist, can not describe
-                                       stdout.println(String.format("\"%s\" is not a valid setting.", setting));
-                                       return;
-                               }
-
-                               model = new SettingModel();
-                               model.defaultValue = "";
-                               model.currentValue = value;
-                       }
-                       stdout.println();
-                       stdout.println(model.name);
-                       if (!StringUtils.isEmpty(model.since)) {
-                               stdout.println(SettingModel.SINCE + " " + model.since);
-                       }
-                       if (model.restartRequired) {
-                               stdout.println(SettingModel.RESTART_REQUIRED);
-                       }
-                       if (model.spaceDelimited) {
-                               stdout.println(SettingModel.SPACE_DELIMITED);
-                       }
-                       if (!StringUtils.isEmpty(model.description)) {
-                               stdout.println();
-                               stdout.println(model.description);
-                       }
-                       stdout.println();
-                       if (model.defaultValue != null) {
-                               stdout.println("default: " + model.defaultValue);
-                       }
-                       if (!model.isDefaultValue()) {
-                               stdout.println("current: " + model.currentValue);
-                       } else {
-                               stdout.println("current: <default>");
-                       }
-                       stdout.println();
-               } else if (!StringUtils.isEmpty(setting) && value == null && reset) {
-                       /*
-                        *  Reset a setting
-                        */
-                       SettingModel model = settings.get(setting);
-                       if (model == null) {
-                               stdout.println(String.format("\"%s\" is not a valid setting.", setting));
-                               return;
-                       }
-
-                       if (model.defaultValue == null || model.defaultValue.equals("null")) {
-                               // no default value, remove setting
-                               gitblit.getSettings().removeSetting(setting);
-                               gitblit.getSettings().saveSettings();
-                               settings.remove(setting);
-
-                               stdout.println(String.format("%s removed.", setting));
-                       } else {
-                               // reset to default value
-                               Map<String, String> updates = Maps.newHashMap();
-                               updates.put(setting, model.defaultValue == null ? "" : model.defaultValue);
-                               gitblit.getSettings().saveSettings(updates);
-
-                               // confirm reset
-                               String newValue = gitblit.getSettings().getString(setting, null);
-                               if (model.defaultValue.equals(newValue)) {
-                                       stdout.println(String.format("%s reset to the default value.", setting));
-                               } else {
-                                       stdout.println(String.format("failed to reset %s!", setting));
-                               }
-                       }
-
-               } else if (!StringUtils.isEmpty(setting) && value != null) {
-                       /*
-                        *  Update a setting
-                        */
-                       Map<String, String> updates = Maps.newHashMap();
-                       updates.put(setting, value);
-                       gitblit.getSettings().saveSettings(updates);
-
-                       // confirm update
-                       String newValue = gitblit.getSettings().getString(setting, null);
-                       if (value.equals(newValue)) {
-                               stdout.println(String.format("%s updated.", setting));
-                       } else {
-                               stdout.println(String.format("failed to update %s!", setting));
-                       }
-               } else {
-                       // Display usage
-                       showHelp();
-               }
-       }
-}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/GitblitDispatcher.java b/src/main/java/com/gitblit/transport/ssh/gitblit/GitblitDispatcher.java
deleted file mode 100644 (file)
index 67fedea..0000000
+++ /dev/null
@@ -1,40 +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.gitblit;
-
-import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.commands.CommandMetaData;
-import com.gitblit.transport.ssh.commands.DispatchCommand;
-
-@CommandMetaData(name = "gitblit", description = "Gitblit server commands")
-public class GitblitDispatcher extends DispatchCommand {
-
-       @Override
-       protected void setup(UserModel user) {
-               // commands in this dispatcher
-               register(user, VersionCommand.class);
-               register(user, ConfigCommand.class);
-
-               // nested dispatchers
-               register(user, ListDispatcher.class);
-               register(user, KeysDispatcher.class);
-               register(user, TicketsDispatcher.class);
-               register(user, UsersDispatcher.class);
-               register(user, TeamsDispatcher.class);
-               register(user, ProjectsDispatcher.class);
-               register(user, RepositoriesDispatcher.class);
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/KeysDispatcher.java b/src/main/java/com/gitblit/transport/ssh/gitblit/KeysDispatcher.java
deleted file mode 100644 (file)
index 9bb6000..0000000
+++ /dev/null
@@ -1,252 +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.gitblit;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.IPublicKeyManager;
-import com.gitblit.transport.ssh.SshKey;
-import com.gitblit.transport.ssh.commands.CommandMetaData;
-import com.gitblit.transport.ssh.commands.DispatchCommand;
-import com.gitblit.transport.ssh.commands.SshCommand;
-import com.gitblit.transport.ssh.commands.UsageExample;
-import com.gitblit.utils.FlipTable;
-import com.gitblit.utils.FlipTable.Borders;
-import com.google.common.base.Joiner;
-
-/**
- * The dispatcher and it's commands for SSH public key management.
- *
- * @author James Moger
- *
- */
-@CommandMetaData(name = "keys", description = "SSH public key management commands")
-public class KeysDispatcher extends DispatchCommand {
-
-       @Override
-       protected void setup(UserModel user) {
-               register(user, AddKey.class);
-               register(user, RemoveKey.class);
-               register(user, ListKeys.class);
-               register(user, WhichKey.class);
-               register(user, CommentKey.class);
-       }
-
-       @CommandMetaData(name = "add", description = "Add an SSH public key to your account")
-       @UsageExample(syntax = "cat ~/.ssh/id_rsa.pub | ${ssh} ${cmd} -", description = "Upload your SSH public key and add it to your account")
-       public static class AddKey extends BaseKeyCommand {
-
-               protected final Logger log = LoggerFactory.getLogger(getClass());
-
-               @Argument(metaVar = "<KEY>", usage = "the key(s) to add")
-               private List<String> addKeys = new ArrayList<String>();
-
-               @Override
-               public void run() throws IOException, UnloggedFailure {
-                       String username = getContext().getClient().getUsername();
-                       List<String> keys = readKeys(addKeys);
-                       for (String key : keys) {
-                               SshKey sshKey = parseKey(key);
-                               getKeyManager().addKey(username, sshKey);
-                               log.info("added SSH public key for {}", username);
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "remove", aliases = { "rm" }, description = "Remove an SSH public key from your account")
-       @UsageExample(syntax = "${cmd} 2", description = "Remove the SSH key identified as #2 in `keys list`")
-       public static class RemoveKey extends BaseKeyCommand {
-
-               protected final Logger log = LoggerFactory.getLogger(getClass());
-
-               private final String ALL = "ALL";
-
-               @Argument(metaVar = "<INDEX>|<KEY>|ALL", usage = "the key to remove", required = true)
-               private List<String> removeKeys = new ArrayList<String>();
-
-               @Override
-               public void run() throws IOException, UnloggedFailure {
-                       String username = getContext().getClient().getUsername();
-                       // remove a key that has been piped to the command
-                       // or remove all keys
-
-                       List<SshKey> currentKeys = getKeyManager().getKeys(username);
-                       if (currentKeys == null || currentKeys.isEmpty()) {
-                               throw new UnloggedFailure(1, "There are no registered keys!");
-                       }
-
-                       List<String> keys = readKeys(removeKeys);
-                       if (keys.contains(ALL)) {
-                               if (getKeyManager().removeAllKeys(username)) {
-                                       stdout.println("Removed all keys.");
-                                       log.info("removed all SSH public keys from {}", username);
-                               } else {
-                                       log.warn("failed to remove all SSH public keys from {}", username);
-                               }
-                       } else {
-                               for (String key : keys) {
-                                       try {
-                                               // remove a key by it's index (1-based indexing)
-                                               int index = Integer.parseInt(key);
-                                               if (index > keys.size()) {
-                                                       if (keys.size() == 1) {
-                                                               throw new UnloggedFailure(1, "Invalid index specified. There is only 1 registered key.");
-                                                       }
-                                                       throw new UnloggedFailure(1, String.format("Invalid index specified. There are %d registered keys.", keys.size()));
-                                               }
-                                               SshKey sshKey = currentKeys.get(index - 1);
-                                               if (getKeyManager().removeKey(username, sshKey)) {
-                                                       stdout.println(String.format("Removed %s", sshKey.getFingerprint()));
-                                               } else {
-                                                       throw new UnloggedFailure(1,  String.format("failed to remove #%s: %s", key, sshKey.getFingerprint()));
-                                               }
-                                       } catch (Exception e) {
-                                               // remove key by raw key data
-                                               SshKey sshKey = parseKey(key);
-                                               if (getKeyManager().removeKey(username, sshKey)) {
-                                                       stdout.println(String.format("Removed %s", sshKey.getFingerprint()));
-                                                       log.info("removed SSH public key {} from {}", sshKey.getFingerprint(), username);
-                                               } else {
-                                                       log.warn("failed to remove SSH public key {} from {}", sshKey.getFingerprint(), username);
-                                                       throw new UnloggedFailure(1,  String.format("failed to remove %s", sshKey.getFingerprint()));
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "list", aliases = { "ls" }, description = "List your registered SSH public keys")
-       public static class ListKeys extends SshCommand {
-
-               @Option(name = "-L", usage = "list complete public key parameters")
-               private boolean showRaw;
-
-               @Override
-               public void run() {
-                       IPublicKeyManager keyManager = getContext().getGitblit().getPublicKeyManager();
-                       String username = getContext().getClient().getUsername();
-                       List<SshKey> keys = keyManager.getKeys(username);
-
-                       if (showRaw) {
-                               asRaw(keys);
-                       } else {
-                               asTable(keys);
-                       }
-               }
-
-               /* output in the same format as authorized_keys */
-               protected void asRaw(List<SshKey> keys) {
-                       if (keys == null) {
-                               return;
-                       }
-                       for (SshKey key : keys) {
-                               stdout.println(key.getRawData());
-                       }
-               }
-
-               protected void asTable(List<SshKey> keys) {
-                       String[] headers = { "#", "Fingerprint", "Comment", "Type" };
-                       int len = keys == null ? 0 : keys.size();
-                       Object[][] data = new Object[len][];
-                       for (int i = 0; i < len; i++) {
-                               // show 1-based index numbers with the fingerprint
-                               // this is useful for comparing with "ssh-add -l"
-                               SshKey k = keys.get(i);
-                               data[i] = new Object[] { (i + 1), k.getFingerprint(), k.getComment(), k.getAlgorithm() };
-                       }
-
-                       stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
-               }
-       }
-
-       @CommandMetaData(name = "which", description = "Display the SSH public key used for this session")
-       public static class WhichKey extends SshCommand {
-
-               @Option(name = "-L", usage = "list complete public key parameters")
-               private boolean showRaw;
-
-               @Override
-               public void run() throws UnloggedFailure {
-                       SshKey key = getContext().getClient().getKey();
-                       if (key == null) {
-                               throw new UnloggedFailure(1,  "You have not authenticated with an SSH public key.");
-                       }
-
-                       if (showRaw) {
-                               stdout.println(key.getRawData());
-                       } else {
-                               final String username = getContext().getClient().getUsername();
-                               List<SshKey> keys = getContext().getGitblit().getPublicKeyManager().getKeys(username);
-                               int index = 0;
-                               for (int i = 0; i < keys.size(); i++) {
-                                       if (key.equals(keys.get(i))) {
-                                               index = i + 1;
-                                               break;
-                                       }
-                               }
-                               asTable(index, key);
-                       }
-               }
-
-               protected void asTable(int index, SshKey key) {
-                       String[] headers = { "#", "Fingerprint", "Comment", "Type" };
-                       Object[][] data = new Object[1][];
-                       data[0] = new Object[] { index, key.getFingerprint(), key.getComment(), key.getAlgorithm() };
-
-                       stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
-               }
-       }
-
-       @CommandMetaData(name = "comment", description = "Set the comment for an SSH public key")
-       @UsageExample(syntax = "${cmd} 3 Home workstation", description = "Set the comment for key #3")
-       public static class CommentKey extends SshCommand {
-
-               @Argument(index = 0, metaVar = "INDEX", usage = "the key index", required = true)
-               private int index;
-
-               @Argument(index = 1, metaVar = "COMMENT", usage = "the new comment", required = true)
-               private List<String> values = new ArrayList<String>();
-
-               @Override
-               public void run() throws UnloggedFailure {
-                       final String username = getContext().getClient().getUsername();
-                       IPublicKeyManager keyManager = getContext().getGitblit().getPublicKeyManager();
-                       List<SshKey> keys = keyManager.getKeys(username);
-                       if (index > keys.size()) {
-                               throw new UnloggedFailure(1,  "Invalid key index!");
-                       }
-
-                       String comment = Joiner.on(" ").join(values);
-                       SshKey key = keys.get(index - 1);
-                       key.setComment(comment);
-                       if (keyManager.addKey(username, key)) {
-                               stdout.println(String.format("Updated the comment for key #%d.", index));
-                       } else {
-                               throw new UnloggedFailure(1, String.format("Failed to update the comment for key #%d!", index));
-                       }
-               }
-
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/ListDispatcher.java b/src/main/java/com/gitblit/transport/ssh/gitblit/ListDispatcher.java
deleted file mode 100644 (file)
index 343e59a..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.gitblit;
-
-import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.commands.CommandMetaData;
-import com.gitblit.transport.ssh.commands.DispatchCommand;
-
-/**
- * The dispatcher and it's commands for Gitblit object listing.
- *
- * @author James Moger
- *
- */
-@CommandMetaData(name = "list", aliases = { "ls" }, description = "Gitblit object list commands")
-public class ListDispatcher extends DispatchCommand {
-
-       @Override
-       protected void setup(UserModel user) {
-               register(user, ListRepositories.class);
-               register(user, ListProjects.class);
-               register(user, ListUsers.class);
-               register(user, ListKeys.class);
-       }
-
-       /* List SSH public keys */
-       @CommandMetaData(name = "keys",  description = "List your public keys")
-       public static class ListKeys extends KeysDispatcher.ListKeys {
-       }
-
-       /* List repositories */
-       @CommandMetaData(name = "repositories", aliases = { "repos" }, description = "List repositories")
-       public static class ListRepositories extends RepositoriesDispatcher.ListRepositories {
-       }
-
-       /* List projects */
-       @CommandMetaData(name = "projects", description = "List projects")
-       public static class ListProjects extends ProjectsDispatcher.ListProjects {
-       }
-
-       /* List users */
-       @CommandMetaData(name = "users", description = "List users", admin = true)
-       public static class ListUsers extends UsersDispatcher.ListUsers {
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/ProjectsDispatcher.java b/src/main/java/com/gitblit/transport/ssh/gitblit/ProjectsDispatcher.java
deleted file mode 100644 (file)
index 97076ad..0000000
+++ /dev/null
@@ -1,94 +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.gitblit;
-
-import java.util.List;
-
-import com.gitblit.manager.IGitblit;
-import com.gitblit.models.ProjectModel;
-import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.commands.CommandMetaData;
-import com.gitblit.transport.ssh.commands.DispatchCommand;
-import com.gitblit.transport.ssh.commands.ListFilterCommand;
-import com.gitblit.utils.FlipTable;
-import com.gitblit.utils.FlipTable.Borders;
-
-@CommandMetaData(name = "projects", description = "Project management commands")
-public class ProjectsDispatcher extends DispatchCommand {
-
-       @Override
-       protected void setup(UserModel user) {
-               register(user, ListProjects.class);
-       }
-
-       /* List projects */
-       @CommandMetaData(name = "list", aliases= { "ls" }, description = "List projects")
-       public static class ListProjects extends ListFilterCommand<ProjectModel> {
-
-               @Override
-               protected List<ProjectModel> getItems() {
-                       IGitblit gitblit = getContext().getGitblit();
-                       UserModel user = getContext().getClient().getUser();
-
-                       List<ProjectModel> projects = gitblit.getProjectModels(user, false);
-                       return projects;
-               }
-
-               @Override
-               protected boolean matches(String filter, ProjectModel p) {
-                       return p.name.matches(filter);
-               }
-
-               @Override
-               protected void asTable(List<ProjectModel> list) {
-                       String[] headers;
-                       if (verbose) {
-                               String[] h = { "Name", "Description", "Last Modified", "# Repos" };
-                               headers = h;
-                       } else {
-                               String[] h = { "Name", "Last Modified", "# Repos" };
-                               headers = h;
-                       }
-
-                       Object[][] data = new Object[list.size()][];
-                       for (int i = 0; i < list.size(); i++) {
-                               ProjectModel p = list.get(i);
-
-                               if (verbose) {
-                                       data[i] = new Object[] { p.name, p.description, formatDate(p.lastChange), p.repositories.size() };
-                               } else {
-                                       data[i] = new Object[] { p.name, formatDate(p.lastChange), p.repositories.size() };
-                               }
-                       }
-                       stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
-               }
-
-               @Override
-               protected void asTabbed(List<ProjectModel> list) {
-                       if (verbose) {
-                               for (ProjectModel project : list) {
-                                       outTabbed(project.name,
-                                                       project.description == null ? "" : project.description,
-                                                                       formatDate(project.lastChange));
-                               }
-                       } else {
-                               for (ProjectModel project : list) {
-                                       outTabbed(project.name);
-                               }
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/RepositoriesDispatcher.java b/src/main/java/com/gitblit/transport/ssh/gitblit/RepositoriesDispatcher.java
deleted file mode 100644 (file)
index 292c212..0000000
+++ /dev/null
@@ -1,532 +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.gitblit;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.kohsuke.args4j.Argument;
-
-import com.gitblit.GitBlitException;
-import com.gitblit.Keys;
-import com.gitblit.Constants.AccessRestrictionType;
-import com.gitblit.Constants.AuthorizationControl;
-import com.gitblit.manager.IGitblit;
-import com.gitblit.models.RegistrantAccessPermission;
-import com.gitblit.models.RepositoryModel;
-import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.commands.CommandMetaData;
-import com.gitblit.transport.ssh.commands.DispatchCommand;
-import com.gitblit.transport.ssh.commands.ListFilterCommand;
-import com.gitblit.transport.ssh.commands.SshCommand;
-import com.gitblit.transport.ssh.commands.UsageExample;
-import com.gitblit.utils.ArrayUtils;
-import com.gitblit.utils.FlipTable;
-import com.gitblit.utils.FlipTable.Borders;
-import com.gitblit.utils.StringUtils;
-import com.google.common.base.Joiner;
-
-@CommandMetaData(name = "repositories", aliases = { "repos" }, description = "Repository management commands")
-public class RepositoriesDispatcher extends DispatchCommand {
-
-       @Override
-       protected void setup(UserModel user) {
-               // primary commands
-               register(user, NewRepository.class);
-               register(user, RenameRepository.class);
-               register(user, RemoveRepository.class);
-               register(user, ShowRepository.class);
-               register(user, ListRepositories.class);
-
-               // repository-specific commands
-               register(user, SetField.class);
-       }
-
-       public static abstract class RepositoryCommand extends SshCommand {
-               @Argument(index = 0, required = true, metaVar = "REPOSITORY", usage = "repository")
-               protected String repository;
-
-               protected RepositoryModel getRepository(boolean requireRepository) throws UnloggedFailure {
-                       IGitblit gitblit = getContext().getGitblit();
-                       RepositoryModel repo = gitblit.getRepositoryModel(repository);
-                       if (requireRepository && repo == null) {
-                               throw new UnloggedFailure(1, String.format("Repository %s does not exist!", repository));
-                       }
-                       return repo;
-               }
-               
-               protected String sanitize(String name) throws UnloggedFailure {
-                       // automatically convert backslashes to forward slashes
-                       name = name.replace('\\', '/');
-                       // Automatically replace // with /
-                       name = name.replace("//", "/");
-
-                       // prohibit folder paths
-                       if (name.startsWith("/")) {
-                               throw new UnloggedFailure(1,  "Illegal leading slash");
-                       }
-                       if (name.startsWith("../")) {
-                               throw new UnloggedFailure(1,  "Illegal relative slash");
-                       }
-                       if (name.contains("/../")) {
-                               throw new UnloggedFailure(1,  "Illegal relative slash");
-                       }
-                       if (name.endsWith("/")) {
-                               name = name.substring(0, name.length() - 1);
-                       }
-                       return name;
-               }
-       }
-
-       @CommandMetaData(name = "new", aliases = { "add" }, description = "Create a new repository")
-       @UsageExample(syntax = "${cmd} myRepo")
-       public static class NewRepository extends RepositoryCommand {
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       UserModel user = getContext().getClient().getUser();
-
-                       String name = sanitize(repository);
-                       
-                       if (!user.canCreate(name)) {
-                               // try to prepend personal path
-                               String path  = StringUtils.getFirstPathElement(name);
-                               if ("".equals(path)) {
-                                       name = user.getPersonalPath() + "/" + name;
-                               }
-                       }
-
-                       if (getRepository(false) != null) {
-                               throw new UnloggedFailure(1, String.format("Repository %s already exists!", name));
-                       }
-                                               
-                       if (!user.canCreate(name)) {
-                               throw new UnloggedFailure(1,  String.format("Sorry, you do not have permission to create %s", name));
-                       }
-
-                       IGitblit gitblit = getContext().getGitblit();
-
-                       RepositoryModel repo = new RepositoryModel();
-                       repo.name = name;
-                       repo.projectPath = StringUtils.getFirstPathElement(name);
-                       String restriction = gitblit.getSettings().getString(Keys.git.defaultAccessRestriction, "PUSH");
-                       repo.accessRestriction = AccessRestrictionType.fromName(restriction);
-                       String authorization = gitblit.getSettings().getString(Keys.git.defaultAuthorizationControl, null);
-                       repo.authorizationControl = AuthorizationControl.fromName(authorization);
-
-                       if (user.isMyPersonalRepository(name)) {
-                               // personal repositories are private by default
-                               repo.addOwner(user.username);
-                               repo.accessRestriction = AccessRestrictionType.VIEW;
-                               repo.authorizationControl = AuthorizationControl.NAMED;
-                       }
-
-                       try {
-                               gitblit.updateRepositoryModel(repository,  repo, true);
-                               stdout.println(String.format("%s created.", repo.name));
-                       } catch (GitBlitException e) {
-                               log.error("Failed to add " + repository, e);
-                               throw new UnloggedFailure(1, e.getMessage());
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "rename", aliases = { "mv" }, description = "Rename a repository")
-       @UsageExample(syntax = "${cmd} myRepo.git otherRepo.git", description = "Rename the repository from myRepo.git to otherRepo.git")
-       public static class RenameRepository extends RepositoryCommand {
-               @Argument(index = 1, required = true, metaVar = "NEWNAME", usage = "the new repository name")
-               protected String newRepositoryName;
-
-                               @Override
-               public void run() throws UnloggedFailure {
-                       RepositoryModel repo = getRepository(true);
-                       IGitblit gitblit = getContext().getGitblit();
-                       UserModel user = getContext().getClient().getUser();
-
-                       String name = sanitize(newRepositoryName);
-                       if (!user.canCreate(name)) {
-                               // try to prepend personal path
-                               String path  = StringUtils.getFirstPathElement(name);
-                               if ("".equals(path)) {
-                                       name = user.getPersonalPath() + "/" + name;
-                               }
-                       }
-
-                       if (null != gitblit.getRepositoryModel(name)) {
-                               throw new UnloggedFailure(1, String.format("Repository %s already exists!", name));
-                       }
-
-                       if (repo.name.equalsIgnoreCase(name)) {
-                               throw new UnloggedFailure(1, "Repository names are identical");
-                       }
-                       
-                       if (!user.canAdmin(repo)) {
-                               throw new UnloggedFailure(1,  String.format("Sorry, you do not have permission to rename %s", repository));
-                       }
-                       
-                       if (!user.canCreate(name)) {
-                               throw new UnloggedFailure(1, String.format("Sorry, you don't have permission to move %s to %s/", repository, name));
-                       }
-
-                       // set the new name
-                       repo.name = name;
-
-                       try {
-                               gitblit.updateRepositoryModel(repository, repo, false);
-                               stdout.println(String.format("Renamed repository %s to %s.", repository, name));
-                       } catch (GitBlitException e) {
-                               String msg = String.format("Failed to rename repository from %s to %s", repository, name);
-                               log.error(msg, e);
-                               throw new UnloggedFailure(1, msg);
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "set", description = "Set the specified field of a repository")
-       @UsageExample(syntax = "${cmd} myRepo description John's personal projects", description = "Set the description of a repository")
-       public static class SetField extends RepositoryCommand {
-
-               @Argument(index = 1, required = true, metaVar = "FIELD", usage = "the field to update")
-               protected String fieldName;
-
-               @Argument(index = 2, required = true, metaVar = "VALUE", usage = "the new value")
-               protected List<String> fieldValues = new ArrayList<String>();
-
-               protected enum Field {
-                       description;
-
-                       static Field fromString(String name) {
-                               for (Field field : values()) {
-                                       if (field.name().equalsIgnoreCase(name)) {
-                                               return field;
-                                       }
-                               }
-                               return null;
-                       }
-               }
-
-               @Override
-               protected String getUsageText() {
-                       String fields = Joiner.on(", ").join(Field.values());
-                       StringBuilder sb = new StringBuilder();
-                       sb.append("Valid fields are:\n   ").append(fields);
-                       return sb.toString();
-               }
-
-               @Override
-               public void run() throws UnloggedFailure {
-                       RepositoryModel repo = getRepository(true);
-
-                       Field field = Field.fromString(fieldName);
-                       if (field == null) {
-                               throw new UnloggedFailure(1, String.format("Unknown field %s", fieldName));
-                       }
-
-                       if (!getContext().getClient().getUser().canAdmin(repo)) {
-                               throw new UnloggedFailure(1,  String.format("Sorry, you do not have permission to administer %s", repository));
-                       }
-
-                       String value = Joiner.on(" ").join(fieldValues).trim();
-                       IGitblit gitblit = getContext().getGitblit();
-
-                       switch(field) {
-                       case description:
-                               repo.description = value;
-                               break;
-                       default:
-                               throw new UnloggedFailure(1,  String.format("Field %s was not properly handled by the set command.", fieldName));
-                       }
-
-                       try {
-                               gitblit.updateRepositoryModel(repo.name,  repo, false);
-                               stdout.println(String.format("Set %s.%s = %s", repo.name, fieldName, value));
-                       } catch (GitBlitException e) {
-                               String msg = String.format("Failed to set %s.%s = %s", repo.name, fieldName, value);
-                               log.error(msg, e);
-                               throw new UnloggedFailure(1, msg);
-                       }
-               }
-
-               protected boolean toBool(String value) throws UnloggedFailure {
-                       String v = value.toLowerCase();
-                       if (v.equals("t")
-                                       || v.equals("true")
-                                       || v.equals("yes")
-                                       || v.equals("on")
-                                       || v.equals("y")
-                                       || v.equals("1")) {
-                               return true;
-                       } else if (v.equals("f")
-                                       || v.equals("false")
-                                       || v.equals("no")
-                                       || v.equals("off")
-                                       || v.equals("n")
-                                       || v.equals("0")) {
-                               return false;
-                       }
-                       throw new UnloggedFailure(1,  String.format("Invalid boolean value %s", value));
-               }
-       }
-
-       @CommandMetaData(name = "remove", aliases = { "rm" }, description = "Remove a repository")
-       @UsageExample(syntax = "${cmd} myRepo.git", description = "Delete myRepo.git")
-       public static class RemoveRepository extends RepositoryCommand {
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       RepositoryModel repo = getRepository(true);
-                       
-                       if (!getContext().getClient().getUser().canAdmin(repo)) {
-                               throw new UnloggedFailure(1,  String.format("Sorry, you do not have permission to delete %s", repository));
-                       }
-
-                       IGitblit gitblit = getContext().getGitblit();
-                       if (gitblit.deleteRepositoryModel(repo)) {
-                               stdout.println(String.format("%s has been deleted.", repository));
-                       } else {
-                               throw new UnloggedFailure(1, String.format("Failed to delete %s!", repository));
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "show", description = "Show the details of a repository")
-       @UsageExample(syntax = "${cmd} myRepo.git", description = "Display myRepo.git")
-       public static class ShowRepository extends RepositoryCommand {
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       RepositoryModel r = getRepository(true);
-
-                       if (!getContext().getClient().getUser().canAdmin(r)) {
-                               throw new UnloggedFailure(1,  String.format("Sorry, you do not have permission to see the %s settings.", repository));
-                       }
-
-                       IGitblit gitblit = getContext().getGitblit();
-
-                       // fields
-                       StringBuilder fb = new StringBuilder();
-                       fb.append("Description    : ").append(toString(r.description)).append('\n');
-                       fb.append("Origin         : ").append(toString(r.origin)).append('\n');
-                       fb.append("Default Branch : ").append(toString(r.HEAD)).append('\n');
-                       fb.append('\n');
-                       fb.append("GC Period    : ").append(r.gcPeriod).append('\n');
-                       fb.append("GC Threshold : ").append(r.gcThreshold).append('\n');
-                       fb.append('\n');
-                       fb.append("Accept Tickets   : ").append(toString(r.acceptNewTickets)).append('\n');
-                       fb.append("Accept Patchsets : ").append(toString(r.acceptNewPatchsets)).append('\n');
-                       fb.append("Require Approval : ").append(toString(r.requireApproval)).append('\n');
-                       fb.append("Merge To         : ").append(toString(r.mergeTo)).append('\n');
-                       fb.append('\n');
-                       fb.append("Incremental push tags    : ").append(toString(r.useIncrementalPushTags)).append('\n');
-                       fb.append("Show remote branches     : ").append(toString(r.showRemoteBranches)).append('\n');
-                       fb.append("Skip size calculations   : ").append(toString(r.skipSizeCalculation)).append('\n');
-                       fb.append("Skip summary metrics     : ").append(toString(r.skipSummaryMetrics)).append('\n');
-                       fb.append("Max activity commits     : ").append(r.maxActivityCommits).append('\n');
-                       fb.append("Author metric exclusions : ").append(toString(r.metricAuthorExclusions)).append('\n');
-                       fb.append("Commit Message Renderer  : ").append(r.commitMessageRenderer).append('\n');
-                       fb.append("Mailing Lists            : ").append(toString(r.mailingLists)).append('\n');
-                       fb.append('\n');
-                       fb.append("Access Restriction    : ").append(r.accessRestriction).append('\n');
-                       fb.append("Authorization Control : ").append(r.authorizationControl).append('\n');
-                       fb.append('\n');
-                       fb.append("Is Frozen        : ").append(toString(r.isFrozen)).append('\n');
-                       fb.append("Allow Forks      : ").append(toString(r.allowForks)).append('\n');
-                       fb.append("Verify Committer : ").append(toString(r.verifyCommitter)).append('\n');
-                       fb.append('\n');
-                       fb.append("Federation Strategy : ").append(r.federationStrategy).append('\n');
-                       fb.append("Federation Sets     : ").append(toString(r.federationSets)).append('\n');
-                       fb.append('\n');
-                       fb.append("Indexed Branches : ").append(toString(r.indexedBranches)).append('\n');
-                       fb.append('\n');
-                       fb.append("Pre-Receive Scripts  : ").append(toString(r.preReceiveScripts)).append('\n');
-                       fb.append("           inherited : ").append(toString(gitblit.getPreReceiveScriptsInherited(r))).append('\n');
-                       fb.append("Post-Receive Scripts : ").append(toString(r.postReceiveScripts)).append('\n');
-                       fb.append("           inherited : ").append(toString(gitblit.getPostReceiveScriptsInherited(r))).append('\n');
-                       String fields = fb.toString();
-
-                       // owners
-                       String owners;
-                       if (r.owners.isEmpty()) {
-                               owners = FlipTable.EMPTY;
-                       } else {
-                               String[] pheaders = { "Account", "Name" };
-                               Object [][] pdata = new Object[r.owners.size()][];
-                               for (int i = 0; i < r.owners.size(); i++) {
-                                       String owner = r.owners.get(i);
-                                       UserModel u = gitblit.getUserModel(owner);
-                                       pdata[i] = new Object[] { owner, u == null ? "" : u.getDisplayName() };
-                               }
-                               owners = FlipTable.of(pheaders, pdata, Borders.COLS);
-                       }
-
-                       // team permissions
-                       List<RegistrantAccessPermission> tperms = gitblit.getTeamAccessPermissions(r);
-                       String tpermissions;
-                       if (tperms.isEmpty()) {
-                               tpermissions = FlipTable.EMPTY;
-                       } else {
-                               String[] pheaders = { "Team", "Permission", "Type" };
-                               Object [][] pdata = new Object[tperms.size()][];
-                               for (int i = 0; i < tperms.size(); i++) {
-                                       RegistrantAccessPermission ap = tperms.get(i);
-                                       pdata[i] = new Object[] { ap.registrant, ap.permission, ap.permissionType };
-                               }
-                               tpermissions = FlipTable.of(pheaders, pdata, Borders.COLS);
-                       }
-
-                       // user permissions
-                       List<RegistrantAccessPermission> uperms = gitblit.getUserAccessPermissions(r);
-                       String upermissions;
-                       if (uperms.isEmpty()) {
-                               upermissions = FlipTable.EMPTY;
-                       } else {
-                               String[] pheaders = { "Account", "Name", "Permission", "Type", "Source", "Mutable" };
-                               Object [][] pdata = new Object[uperms.size()][];
-                               for (int i = 0; i < uperms.size(); i++) {
-                                       RegistrantAccessPermission ap = uperms.get(i);
-                                       String name = "";
-                                       try {
-                                               String dn = gitblit.getUserModel(ap.registrant).displayName;
-                                               if (dn != null) {
-                                                       name = dn;
-                                               }
-                                       } catch (Exception e) {
-                                       }
-                                       pdata[i] = new Object[] { ap.registrant, name, ap.permission, ap.permissionType, ap.source, ap.mutable ? "Y":"" };
-                               }
-                               upermissions = FlipTable.of(pheaders, pdata, Borders.COLS);
-                       }
-
-                       // assemble table
-                       String title = r.name;
-                       String [] headers = new String[] { title };
-                       String[][] data = new String[8][];
-                       data[0] = new String [] { "FIELDS" };
-                       data[1] = new String [] {fields };
-                       data[2] = new String [] { "OWNERS" };
-                       data[3] = new String [] { owners };
-                       data[4] = new String [] { "TEAM PERMISSIONS" };
-                       data[5] = new String [] { tpermissions };
-                       data[6] = new String [] { "USER PERMISSIONS" };
-                       data[7] = new String [] { upermissions };
-                       stdout.println(FlipTable.of(headers, data));
-               }
-               
-               protected String toString(String val) {
-                       if (val == null) {
-                               return "";
-                       }
-                       return val;
-               }
-               
-               protected String toString(Collection<?> collection) {
-                       if (collection == null) {
-                               return "";
-                       }
-                       return Joiner.on(", ").join(collection);
-               }
-               
-               protected String toString(boolean val) {
-                       if (val) {
-                               return "Y";
-                       }
-                       return "";
-               }
-
-       }
-
-       /* List repositories */
-       @CommandMetaData(name = "list", aliases = { "ls" }, description = "List repositories")
-       @UsageExample(syntax = "${cmd} mirror/.* -v", description = "Verbose list of all repositories in the 'mirror' directory")
-       public static class ListRepositories extends ListFilterCommand<RepositoryModel> {
-
-               @Override
-               protected List<RepositoryModel> getItems() {
-                       IGitblit gitblit = getContext().getGitblit();
-                       UserModel user = getContext().getClient().getUser();
-                       List<RepositoryModel> repositories = gitblit.getRepositoryModels(user);
-                       return repositories;
-               }
-
-               @Override
-               protected boolean matches(String filter, RepositoryModel r) {
-                       return r.name.matches(filter);
-               }
-
-               @Override
-               protected void asTable(List<RepositoryModel> list) {
-                       String[] headers;
-                       if (verbose) {
-                               String[] h = { "Name", "Description", "Owners", "Last Modified", "Size" };
-                               headers = h;
-                       } else {
-                               String[] h = { "Name", "Last Modified", "Size" };
-                               headers = h;
-                       }
-
-                       Object[][] data = new Object[list.size()][];
-                       for (int i = 0; i < list.size(); i++) {
-                               RepositoryModel r = list.get(i);
-
-                               String lm = formatDate(r.lastChange);
-                               String size = r.size;
-                               if (!r.hasCommits) {
-                                       lm = "";
-                                       size = FlipTable.EMPTY;
-                               }
-                               if (verbose) {
-                                       String owners = "";
-                                       if (!ArrayUtils.isEmpty(r.owners)) {
-                                               owners = Joiner.on(",").join(r.owners);
-                                       }
-                                       data[i] = new Object[] { r.name, r.description, owners, lm, size };
-                               } else {
-                                       data[i] = new Object[] { r.name, lm, size };
-                               }
-                       }
-                       stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
-               }
-
-               @Override
-               protected void asTabbed(List<RepositoryModel> list) {
-                       if (verbose) {
-                               for (RepositoryModel r : list) {
-                                       String lm = formatDate(r.lastChange);
-                                       String owners = "";
-                                       if (!ArrayUtils.isEmpty(r.owners)) {
-                                               owners = Joiner.on(",").join(r.owners);
-                                       }
-                                       String size = r.size;
-                                       if (!r.hasCommits) {
-                                               lm = "";
-                                               size = "(empty)";
-                                       }
-
-                                       outTabbed(r.name, r.description == null ? "" : r.description,
-                                                       owners, lm, size);
-                               }
-                       } else {
-                               for (RepositoryModel r : list) {
-                                       outTabbed(r.name);
-                               }
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/ReviewCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/ReviewCommand.java
deleted file mode 100644 (file)
index b3691cb..0000000
+++ /dev/null
@@ -1,89 +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.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.commands.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/TeamsDispatcher.java b/src/main/java/com/gitblit/transport/ssh/gitblit/TeamsDispatcher.java
deleted file mode 100644 (file)
index d0ec58f..0000000
+++ /dev/null
@@ -1,507 +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.gitblit;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
-
-import com.gitblit.Constants.AccessPermission;
-import com.gitblit.GitBlitException;
-import com.gitblit.manager.IGitblit;
-import com.gitblit.models.RegistrantAccessPermission;
-import com.gitblit.models.RepositoryModel;
-import com.gitblit.models.TeamModel;
-import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.commands.CommandMetaData;
-import com.gitblit.transport.ssh.commands.DispatchCommand;
-import com.gitblit.transport.ssh.commands.ListFilterCommand;
-import com.gitblit.transport.ssh.commands.SshCommand;
-import com.gitblit.transport.ssh.commands.UsageExample;
-import com.gitblit.transport.ssh.commands.UsageExamples;
-import com.gitblit.utils.ArrayUtils;
-import com.gitblit.utils.FlipTable;
-import com.gitblit.utils.FlipTable.Borders;
-import com.gitblit.utils.StringUtils;
-import com.google.common.base.Joiner;
-
-@CommandMetaData(name = "teams", description = "Team management commands", admin = true)
-public class TeamsDispatcher extends DispatchCommand {
-
-       @Override
-       protected void setup(UserModel user) {
-               // primary team commands
-               register(user, NewTeam.class);
-               register(user, RenameTeam.class);
-               register(user, RemoveTeam.class);
-               register(user, ShowTeam.class);
-               register(user, ListTeams.class);
-
-               // team-specific commands
-               register(user, SetField.class);
-               register(user, Permissions.class);
-               register(user, Members.class);
-       }
-
-       public static abstract class TeamCommand extends SshCommand {
-               @Argument(index = 0, required = true, metaVar = "TEAM", usage = "team name")
-               protected String teamname;
-
-               protected TeamModel getTeam(boolean requireTeam) throws UnloggedFailure {
-                       IGitblit gitblit = getContext().getGitblit();
-                       TeamModel team = gitblit.getTeamModel(teamname);
-                       if (requireTeam && team == null) {
-                               throw new UnloggedFailure(1, String.format("Team %s does not exist!", teamname));
-                       }
-                       return team;
-               }
-       }
-
-       @CommandMetaData(name = "new", aliases = { "add" }, description = "Create a new team")
-       @UsageExample(syntax = "${cmd} contributors --canFork --canCreate")
-       public static class NewTeam extends TeamCommand {
-
-               @Option(name = "--canAdmin", usage = "can administer the server")
-               protected boolean canAdmin;
-
-               @Option(name = "--canFork", usage = "can fork repositories")
-               protected boolean canFork;
-
-               @Option(name = "--canCreate", usage = "can create personal repositories")
-               protected boolean canCreate;
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       if (getTeam(false) != null) {
-                               throw new UnloggedFailure(1, String.format("Team %s already exists!", teamname));
-                       }
-
-                       TeamModel team = new TeamModel(teamname);
-                       team.canAdmin = canAdmin;
-                       team.canFork = canFork;
-                       team.canCreate = canCreate;
-
-                       IGitblit gitblit = getContext().getGitblit();
-                       try {
-                               gitblit.addTeam(team);
-                               stdout.println(String.format("%s created.", teamname));
-                       } catch (GitBlitException e) {
-                               String msg = String.format("Failed to create %s!", teamname);
-                               log.error(msg, e);
-                               throw new UnloggedFailure(1, msg);
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "rename", aliases = { "mv" }, description = "Rename a team")
-       @UsageExample(syntax = "${cmd} contributors friends", description = "Rename the contributors team to the friends team")
-       public static class RenameTeam extends TeamCommand {
-               @Argument(index = 1, required = true, metaVar = "NEWNAME", usage = "the new team name")
-               protected String newTeamName;
-
-                               @Override
-               public void run() throws UnloggedFailure {
-                       TeamModel team = getTeam(true);
-                       IGitblit gitblit = getContext().getGitblit();
-                       if (null != gitblit.getTeamModel(newTeamName)) {
-                               throw new UnloggedFailure(1, String.format("Team %s already exists!", newTeamName));
-                       }
-
-                       // set the new team name
-                       team.name = newTeamName;
-
-                       try {
-                               gitblit.reviseTeam(teamname, team);
-                               stdout.println(String.format("Renamed team %s to %s.", teamname, newTeamName));
-                       } catch (GitBlitException e) {
-                               String msg = String.format("Failed to rename team from %s to %s", teamname, newTeamName);
-                               log.error(msg, e);
-                               throw new UnloggedFailure(1, msg);
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "set", description = "Set the specified field of a team")
-       @UsageExample(syntax = "${cmd} contributors canFork true", description = "Allow the contributors team to fork repositories")
-       public static class SetField extends TeamCommand {
-
-               @Argument(index = 1, required = true, metaVar = "FIELD", usage = "the field to update")
-               protected String fieldName;
-
-               @Argument(index = 2, required = true, metaVar = "VALUE", usage = "the new value")
-               protected List<String> fieldValues = new ArrayList<String>();
-
-               protected enum Field {
-                       mailingList, preReceive, postReceive, canAdmin, canFork, canCreate;
-
-                       static Field fromString(String name) {
-                               for (Field field : values()) {
-                                       if (field.name().equalsIgnoreCase(name)) {
-                                               return field;
-                                       }
-                               }
-                               return null;
-                       }
-               }
-
-               @Override
-               protected String getUsageText() {
-                       String fields = Joiner.on(", ").join(Field.values());
-                       StringBuilder sb = new StringBuilder();
-                       sb.append("Valid fields are:\n    ").append(fields);
-                       return sb.toString();
-               }
-
-               @Override
-               public void run() throws UnloggedFailure {
-                       TeamModel team = getTeam(true);
-
-                       Field field = Field.fromString(fieldName);
-                       if (field == null) {
-                               throw new UnloggedFailure(1, String.format("Unknown field %s", fieldName));
-                       }
-
-                       String value = Joiner.on(" ").join(fieldValues);
-                       IGitblit gitblit = getContext().getGitblit();
-
-                       switch(field) {
-                       case mailingList:
-                               team.mailingLists.clear();
-                               team.mailingLists.addAll(fieldValues);
-                               break;
-                       case preReceive:
-                               team.preReceiveScripts.clear();
-                               team.preReceiveScripts.addAll(fieldValues);
-                               break;
-                       case postReceive:
-                               team.postReceiveScripts.clear();
-                               team.postReceiveScripts.addAll(fieldValues);
-                               break;
-                       case canAdmin:
-                               team.canAdmin = toBool(value);
-                               break;
-                       case canFork:
-                               team.canFork = toBool(value);
-                               break;
-                       case canCreate:
-                               team.canCreate = toBool(value);
-                               break;
-                       default:
-                               throw new UnloggedFailure(1,  String.format("Field %s was not properly handled by the set command.", fieldName));
-                       }
-
-                       try {
-                               gitblit.reviseTeam(teamname, team);
-                               stdout.println(String.format("Set %s.%s = %s", teamname, fieldName, value));
-                       } catch (GitBlitException e) {
-                               String msg = String.format("Failed to set %s.%s = %s", teamname, fieldName, value);
-                               log.error(msg, e);
-                               throw new UnloggedFailure(1, msg);
-                       }
-               }
-
-               protected boolean toBool(String value) throws UnloggedFailure {
-                       String v = value.toLowerCase();
-                       if (v.equals("t")
-                                       || v.equals("true")
-                                       || v.equals("yes")
-                                       || v.equals("on")
-                                       || v.equals("y")
-                                       || v.equals("1")) {
-                               return true;
-                       } else if (v.equals("f")
-                                       || v.equals("false")
-                                       || v.equals("no")
-                                       || v.equals("off")
-                                       || v.equals("n")
-                                       || v.equals("0")) {
-                               return false;
-                       }
-                       throw new UnloggedFailure(1,  String.format("Invalid boolean value %s", value));
-               }
-       }
-
-       @CommandMetaData(name = "permissions", aliases = { "perms" }, description = "Add or remove permissions from a team")
-       @UsageExample(syntax = "${cmd} contributors RW:alpha/repo.git RWC:alpha/repo2.git", description = "Add or set permissions for contributors")
-       public static class Permissions extends TeamCommand {
-
-               @Argument(index = 1, multiValued = true, metaVar = "[PERMISSION:]REPOSITORY", usage = "a repository expression")
-               protected List<String> permissions;
-
-               @Option(name = "--remove", aliases = { "-r" }, metaVar = "REPOSITORY|ALL", usage = "remove a repository permission")
-               protected List<String> removals;
-
-               @Override
-               public void run() throws UnloggedFailure {
-                       IGitblit gitblit = getContext().getGitblit();
-                       TeamModel team = getTeam(true);
-
-                       boolean modified = false;
-                       if (!ArrayUtils.isEmpty(removals)) {
-                               if (removals.contains("ALL")) {
-                                       team.permissions.clear();
-                               } else {
-                                       for (String repo : removals) {
-                                               team.removeRepositoryPermission(repo);
-                                               log.info(String.format("Removing permission for %s from %s", repo, teamname));
-                                       }
-                               }
-                               modified = true;
-                       }
-
-                       if (!ArrayUtils.isEmpty(permissions)) {
-                               for (String perm : permissions) {
-                                       String repo = AccessPermission.repositoryFromRole(perm);
-                                       if (StringUtils.findInvalidCharacter(repo) == null) {
-                                               // explicit permision, confirm repository
-                                               RepositoryModel r = gitblit.getRepositoryModel(repo);
-                                               if (r == null) {
-                                                       throw new UnloggedFailure(1, String.format("Repository %s does not exist!", repo));
-                                               }
-                                       }
-                                       AccessPermission ap = AccessPermission.permissionFromRole(perm);
-                                       team.setRepositoryPermission(repo, ap);
-                                       log.info(String.format("Setting %s:%s for %s", ap.name(), repo, teamname));
-                               }
-                               modified = true;
-                       }
-
-                       if (modified && gitblit.updateTeamModel(teamname, team)) {
-                               // reload & display new permissions
-                               team = gitblit.getTeamModel(teamname);
-                       }
-
-                       showPermissions(team);
-               }
-
-               protected void showPermissions(TeamModel team) {
-                       List<RegistrantAccessPermission> perms = team.getRepositoryPermissions();
-                       String[] pheaders = { "Repository", "Permission", "Type" };
-                       Object [][] pdata = new Object[perms.size()][];
-                       for (int i = 0; i < perms.size(); i++) {
-                               RegistrantAccessPermission ap = perms.get(i);
-                               pdata[i] = new Object[] { ap.registrant, ap.permission, ap.permissionType };
-                       }
-                       stdout.println(FlipTable.of(pheaders, pdata, Borders.BODY_HCOLS));
-               }
-       }
-
-       @CommandMetaData(name = "members", aliases = { "users" }, description = "Add or remove team members")
-       @UsageExample(syntax = "${cmd} contributors RW:alpha/repo.git RWC:alpha/repo2.git", description = "Add or set permissions for contributors")
-       public static class Members extends TeamCommand {
-
-               @Argument(index = 1, multiValued = true, metaVar = "USERNAME", usage = "a username")
-               protected List<String> members;
-
-               @Option(name = "--remove", aliases = { "-r" }, metaVar = "USERNAME|ALL", usage = "remove a team member")
-               protected List<String> removals;
-
-               @Override
-               public void run() throws UnloggedFailure {
-                       IGitblit gitblit = getContext().getGitblit();
-                       TeamModel team = getTeam(true);
-
-                       boolean canEditMemberships = gitblit.supportsTeamMembershipChanges(team);
-                       if (!canEditMemberships) {
-                               String msg = String.format("Team %s (%s) does not permit membership changes!", team.name, team.accountType);
-                               throw new UnloggedFailure(1, msg);
-                       }
-
-                       boolean modified = false;
-                       if (!ArrayUtils.isEmpty(removals)) {
-                               if (removals.contains("ALL")) {
-                                       team.users.clear();
-                               } else {
-                                       for (String member : removals) {
-                                               team.removeUser(member);
-                                               log.info(String.format("Removing member %s from %s", member, teamname));
-                                       }
-                               }
-                               modified = true;
-                       }
-
-                       if (!ArrayUtils.isEmpty(members)) {
-                               for (String username : members) {
-                                       UserModel u = gitblit.getUserModel(username);
-                                       if (u == null) {
-                                               throw new UnloggedFailure(1,  String.format("Unknown user %s", username));
-                                       }
-                                       boolean canEditTeams = gitblit.supportsTeamMembershipChanges(u);
-                                       if (!canEditTeams) {
-                                               String msg = String.format("User %s (%s) does not allow team membership changes ", u.username, u.accountType);
-                                               throw new UnloggedFailure(1, msg);
-                                       }
-                                       team.addUser(username);
-                               }
-                               modified = true;
-                       }
-
-                       if (modified && gitblit.updateTeamModel(teamname, team)) {
-                               // reload & display new permissions
-                               team = gitblit.getTeamModel(teamname);
-                       }
-
-                       String[] headers = { "Username", "Display Name" };
-                       Object [][] data = new Object[team.users.size()][];
-                       int i = 0;
-                       for (String username : team.users) {
-                               UserModel u = gitblit.getUserModel(username);
-                               data[i] = new Object[] { username, u.displayName };
-                               i++;
-                       }
-                       stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
-               }
-       }
-
-       @CommandMetaData(name = "remove", aliases = { "rm" }, description = "Remove a team")
-       @UsageExample(syntax = "${cmd} contributors", description = "Delete the contributors team")
-       public static class RemoveTeam extends TeamCommand {
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       TeamModel team = getTeam(true);
-                       IGitblit gitblit = getContext().getGitblit();
-                       if (gitblit.deleteTeamModel(team)) {
-                               stdout.println(String.format("%s has been deleted.", teamname));
-                       } else {
-                               throw new UnloggedFailure(1, String.format("Failed to delete %s!", teamname));
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "show", description = "Show the details of a team")
-       @UsageExample(syntax = "${cmd} contributors", description = "Display the 'contributors' team")
-       public static class ShowTeam extends TeamCommand {
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       TeamModel t = getTeam(true);
-
-                       // fields
-                       StringBuilder fb = new StringBuilder();
-                       fb.append("Mailing Lists : ").append(Joiner.on(", ").join(t.mailingLists)).append('\n');
-                       fb.append("Type          : ").append(t.accountType).append('\n');
-                       fb.append("Can Admin     : ").append(t.canAdmin ? "Y":"").append('\n');
-                       fb.append("Can Fork      : ").append(t.canFork ? "Y":"").append('\n');
-                       fb.append("Can Create    : ").append(t.canCreate ? "Y":"").append('\n');
-                       fb.append("Pre-Receive   : ").append(Joiner.on(", ").join(t.preReceiveScripts)).append('\n');
-                       fb.append("Post-Receive  : ").append(Joiner.on(", ").join(t.postReceiveScripts)).append('\n');
-                       String fields = fb.toString();
-
-                       // members
-                       String members;
-                       if (t.users.size() == 0) {
-                               members = FlipTable.EMPTY;
-                       } else {
-                               IGitblit gitblit = getContext().getGitblit();
-                               String[] headers = { "Username", "Display Name" };
-                               Object [][] data = new Object[t.users.size()][];
-                               int i = 0;
-                               for (String username : t.users) {
-                                       UserModel u = gitblit.getUserModel(username);
-                                       data[i] = new Object[] { username,  u == null ? null : u.displayName };
-                                       i++;
-                               }
-                               members = FlipTable.of(headers, data, Borders.COLS);
-                       }
-
-                       // permissions
-                       List<RegistrantAccessPermission> perms = t.getRepositoryPermissions();
-                       String permissions;
-                       if (perms.isEmpty()) {
-                               permissions = FlipTable.EMPTY;
-                       } else {
-                               String[] pheaders = { "Repository", "Permission", "Type" };
-                               Object [][] pdata = new Object[perms.size()][];
-                               for (int i = 0; i < perms.size(); i++) {
-                                       RegistrantAccessPermission ap = perms.get(i);
-                                       pdata[i] = new Object[] { ap.registrant, ap.permission, ap.permissionType };
-                               }
-                               permissions = FlipTable.of(pheaders, pdata, Borders.COLS);
-                       }
-
-                       // assemble team table
-                       String [] headers = new String[] { t.name };
-                       String[][] data = new String[6][];
-                       data[0] = new String [] { "FIELDS" };
-                       data[1] = new String [] { fields };
-                       data[2] = new String [] { "MEMBERS" };
-                       data[3] = new String [] { members };
-                       data[4] = new String [] { "PERMISSIONS" };
-                       data[5] = new String [] { permissions };
-                       stdout.println(FlipTable.of(headers, data));
-               }
-       }
-
-       @CommandMetaData(name = "list", aliases= { "ls" }, description = "List teams")
-       @UsageExamples(examples = {
-               @UsageExample(syntax = "${cmd}", description = "List teams as a table"),
-               @UsageExample(syntax = "${cmd} j.*", description = "List all teams that start with 'j'"),
-       })
-       public static class ListTeams extends ListFilterCommand<TeamModel> {
-
-               @Override
-               protected List<TeamModel> getItems() {
-                       IGitblit gitblit = getContext().getGitblit();
-                       List<TeamModel> teams = gitblit.getAllTeams();
-                       return teams;
-               }
-
-               @Override
-               protected boolean matches(String filter, TeamModel t) {
-                       return t.name.matches(filter);
-               }
-
-               @Override
-               protected void asTable(List<TeamModel> list) {
-                       String[] headers = { "Name", "Members", "Type", "Create?", "Fork?"};
-                       Object[][] data = new Object[list.size()][];
-                       for (int i = 0; i < list.size(); i++) {
-                               TeamModel t = list.get(i);
-                               data[i] = new Object[] {
-                                               (t.canAdmin ? "*" : " ") + t.name,
-                                               t.users.isEmpty() ? "" : t.users.size(),
-                                               t.accountType + (t.canAdmin ? ",admin":""),
-                                               (t.canAdmin || t.canCreate) ? "Y":"",
-                                               (t.canAdmin || t.canFork) ? "Y" : ""};
-                       }
-                       stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
-               }
-
-               @Override
-               protected void asTabbed(List<TeamModel> teams) {
-                       if (verbose) {
-                               for (TeamModel t : teams) {
-                                       outTabbed(
-                                                       t.name,
-                                                       t.users.isEmpty() ? "" : t.users.size(),
-                                                       t.accountType + (t.canAdmin ? ",admin":""),
-                                                       (t.canAdmin || t.canCreate) ? "Y":"",
-                                                       (t.canAdmin || t.canFork) ? "Y" : "");
-                               }
-                       } else {
-                               for (TeamModel u : teams) {
-                                       outTabbed((u.canAdmin ? "*" : " ") + u.name);
-                               }
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/TicketsDispatcher.java b/src/main/java/com/gitblit/transport/ssh/gitblit/TicketsDispatcher.java
deleted file mode 100644 (file)
index dd29b6a..0000000
+++ /dev/null
@@ -1,157 +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.gitblit;
-
-import java.util.List;
-
-import org.kohsuke.args4j.Argument;
-
-import com.gitblit.manager.IGitblit;
-import com.gitblit.models.RepositoryModel;
-import com.gitblit.models.TicketModel.Status;
-import com.gitblit.models.UserModel;
-import com.gitblit.tickets.ITicketService;
-import com.gitblit.tickets.QueryBuilder;
-import com.gitblit.tickets.QueryResult;
-import com.gitblit.tickets.TicketIndexer.Lucene;
-import com.gitblit.transport.ssh.commands.CommandMetaData;
-import com.gitblit.transport.ssh.commands.DispatchCommand;
-import com.gitblit.transport.ssh.commands.ListCommand;
-import com.gitblit.utils.ArrayUtils;
-import com.gitblit.utils.FlipTable;
-import com.gitblit.utils.FlipTable.Borders;
-import com.gitblit.utils.StringUtils;
-
-@CommandMetaData(name = "tickets", description = "Ticket commands", hidden = true)
-public class TicketsDispatcher extends DispatchCommand {
-
-       @Override
-       protected void setup(UserModel user) {
-               register(user, ReviewCommand.class);
-               register(user, ListTickets.class);
-       }
-
-       /* List tickets */
-       @CommandMetaData(name = "list", aliases = { "ls" }, description = "List tickets")
-       public static class ListTickets extends ListCommand<QueryResult> {
-
-               private final String ALL = "ALL";
-
-               @Argument(index = 0, metaVar = "ALL|REPOSITORY", usage = "the repository or ALL")
-               protected String repository;
-
-               @Argument(index = 1, multiValued = true, metaVar="CONDITION", usage = "query condition")
-               protected List<String> query;
-
-               protected String userQuery;
-
-               @Override
-               protected List<QueryResult> getItems() throws UnloggedFailure {
-                       IGitblit gitblit = getContext().getGitblit();
-                       ITicketService tickets = gitblit.getTicketService();
-
-                       QueryBuilder sb = new QueryBuilder();
-                       if (ArrayUtils.isEmpty(query)) {
-                               sb.and(Lucene.status.matches(Status.New.toString())).or(Lucene.status.matches(Status.Open.toString()));
-                       } else {
-                               StringBuilder b = new StringBuilder();
-                               for (String q : query) {
-                                       b.append(q).append(' ');
-                               }
-                               b.setLength(b.length() - 1);
-                               sb.and(b.toString());
-                       }
-
-                       QueryBuilder qb;
-                       if (StringUtils.isEmpty(repository) || ALL.equalsIgnoreCase(repository)) {
-                               qb = sb;
-                               userQuery = sb.build();
-                       } else {
-                               qb = new QueryBuilder();
-                               RepositoryModel r = gitblit.getRepositoryModel(repository);
-                               if (r == null) {
-                                       throw new UnloggedFailure(1,  String.format("%s is not a repository!", repository));
-                               }
-                               qb.and(Lucene.rid.matches(r.getRID()));
-                               qb.and(sb.toSubquery().toString());
-                               userQuery = sb.build();
-                       }
-
-                       String query = qb.build();
-                       List<QueryResult> list = tickets.queryFor(query, 0, 0, null, true);
-                       return list;
-               }
-
-               @Override
-               protected void asTable(List<QueryResult> list) {
-                       boolean forRepo = !StringUtils.isEmpty(repository) && !ALL.equalsIgnoreCase(repository);
-                       String[] headers;
-                       if (verbose) {
-                               if (forRepo) {
-                                       String[] h = { "ID", "Title", "Status", "Last Modified", "Votes", "Commits" };
-                                       headers = h;
-                               } else {
-                                       String[] h = { "Repository", "ID", "Title", "Status", "Last Modified", "Votes", "Commits" };
-                                       headers = h;
-                               }
-                       } else {
-                               if (forRepo) {
-                                       String[] h = { "ID", "Title", "Status", "Last Modifed" };
-                                       headers = h;
-                               } else {
-                                       String[] h = { "Repository", "ID", "Title", "Status", "Last Modified" };
-                                       headers = h;
-                               }
-                       }
-
-                       Object[][] data = new Object[list.size()][];
-                       for (int i = 0; i < list.size(); i++) {
-                               QueryResult q = list.get(i);
-
-                               if (verbose) {
-                                       if (forRepo) {
-                                               data[i] = new Object[] { q.number, q.title, q.status, formatDate(q.getDate()), q.votesCount, q.patchset == null ? "": q.patchset.commits };
-                                       } else {
-                                               data[i] = new Object[] { q.repository, q.number, q.title, q.status, formatDate(q.getDate()), q.votesCount, q.patchset == null ? "": q.patchset.commits };
-                                       }
-                               } else {
-                                       if (forRepo) {
-                                               data[i] = new Object[] { q.number, q.title, q.status, formatDate(q.getDate()) };
-                                       } else {
-                                               data[i] = new Object[] { q.repository, q.number, q.title, q.status, formatDate(q.getDate()) };
-                                       }
-                               }
-                       }
-                       stdout.print(FlipTable.of(headers, data, Borders.BODY_HCOLS));
-                       stdout.println("  " + repository + ": " + userQuery);
-                       stdout.println();
-               }
-
-               @Override
-               protected void asTabbed(List<QueryResult> list) {
-                       if (verbose) {
-                               for (QueryResult q : list) {
-                                       outTabbed(q.repository, q.number, q.title, q.status.toString(),
-                                                       formatDate(q.getDate()));
-                               }
-                       } else {
-                               for (QueryResult q : list) {
-                                       outTabbed(q.repository, q.number, q.title);
-                               }
-                       }
-               }
-       }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/UsersDispatcher.java b/src/main/java/com/gitblit/transport/ssh/gitblit/UsersDispatcher.java
deleted file mode 100644 (file)
index 1a6dee4..0000000
+++ /dev/null
@@ -1,592 +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.gitblit;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
-
-import com.gitblit.Constants.AccessPermission;
-import com.gitblit.GitBlitException;
-import com.gitblit.Keys;
-import com.gitblit.manager.IGitblit;
-import com.gitblit.models.RegistrantAccessPermission;
-import com.gitblit.models.RepositoryModel;
-import com.gitblit.models.UserModel;
-import com.gitblit.transport.ssh.SshKey;
-import com.gitblit.transport.ssh.commands.CommandMetaData;
-import com.gitblit.transport.ssh.commands.DispatchCommand;
-import com.gitblit.transport.ssh.commands.ListFilterCommand;
-import com.gitblit.transport.ssh.commands.SshCommand;
-import com.gitblit.transport.ssh.commands.UsageExample;
-import com.gitblit.transport.ssh.commands.UsageExamples;
-import com.gitblit.utils.ArrayUtils;
-import com.gitblit.utils.FlipTable;
-import com.gitblit.utils.FlipTable.Borders;
-import com.gitblit.utils.StringUtils;
-import com.google.common.base.Joiner;
-
-@CommandMetaData(name = "users", description = "User management commands", admin = true)
-public class UsersDispatcher extends DispatchCommand {
-
-       @Override
-       protected void setup(UserModel user) {
-               // primary user commands
-               register(user, NewUser.class);
-               register(user, RenameUser.class);
-               register(user, RemoveUser.class);
-               register(user, ShowUser.class);
-               register(user, ListUsers.class);
-
-               // user-specific commands
-               register(user, SetField.class);
-               register(user, Permissions.class);
-               register(user, DisableUser.class);
-               register(user, EnableUser.class);
-       }
-
-       public static abstract class UserCommand extends SshCommand {
-               @Argument(index = 0, required = true, metaVar = "USERNAME", usage = "username")
-               protected String username;
-
-               protected UserModel getUser(boolean requireUser) throws UnloggedFailure {
-                       IGitblit gitblit = getContext().getGitblit();
-                       UserModel user = gitblit.getUserModel(username);
-                       if (requireUser && user == null) {
-                               throw new UnloggedFailure(1, String.format("User %s does not exist!", username));
-                       }
-                       return user;
-               }
-       }
-
-       @CommandMetaData(name = "new", aliases = { "add" }, description = "Create a new user account")
-       @UsageExample(syntax = "${cmd} john 12345 --email john@smith.com --canFork --canCreate")
-       public static class NewUser extends UserCommand {
-
-               @Argument(index = 1, required = true, metaVar = "PASSWORD", usage = "password")
-               protected String password;
-
-               @Option(name = "--email", metaVar = "ADDRESS", usage = "email address")
-               protected String email;
-
-               @Option(name = "--canAdmin", usage = "can administer the server")
-               protected boolean canAdmin;
-
-               @Option(name = "--canFork", usage = "can fork repositories")
-               protected boolean canFork;
-
-               @Option(name = "--canCreate", usage = "can create personal repositories")
-               protected boolean canCreate;
-
-               @Option(name = "--disabled", usage = "create a disabled user account")
-               protected boolean disabled;
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       if (getUser(false) != null) {
-                               throw new UnloggedFailure(1, String.format("User %s already exists!", username));
-                       }
-
-                       UserModel user = new UserModel(username);
-                       user.password = password;
-
-                       if (email != null) {
-                               user.emailAddress = email;
-                       }
-
-                       user.canAdmin = canAdmin;
-                       user.canFork = canFork;
-                       user.canCreate = canCreate;
-                       user.disabled = disabled;
-
-                       IGitblit gitblit = getContext().getGitblit();
-                       try {
-                               gitblit.addUser(user);
-                               stdout.println(String.format("%s created.", username));
-                       } catch (GitBlitException e) {
-                               log.error("Failed to add " + username, e);
-                               throw new UnloggedFailure(1, e.getMessage());
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "rename", aliases = { "mv" }, description = "Rename an account")
-       @UsageExample(syntax = "${cmd} john frank", description = "Rename the account from john to frank")
-       public static class RenameUser extends UserCommand {
-               @Argument(index = 1, required = true, metaVar = "NEWNAME", usage = "the new account name")
-               protected String newUserName;
-
-                               @Override
-               public void run() throws UnloggedFailure {
-                       UserModel user = getUser(true);
-                       IGitblit gitblit = getContext().getGitblit();
-                       if (null != gitblit.getTeamModel(newUserName)) {
-                               throw new UnloggedFailure(1, String.format("Team %s already exists!", newUserName));
-                       }
-
-                       // set the new name
-                       user.username = newUserName;
-
-                       try {
-                               gitblit.reviseUser(username, user);
-                               stdout.println(String.format("Renamed user %s to %s.", username, newUserName));
-                       } catch (GitBlitException e) {
-                               String msg = String.format("Failed to rename user from %s to %s", username, newUserName);
-                               log.error(msg, e);
-                               throw new UnloggedFailure(1, msg);
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "set", description = "Set the specified field of an account")
-       @UsageExample(syntax = "${cmd} john name John Smith", description = "Set the display name to \"John Smith\" for john's account")
-       public static class SetField extends UserCommand {
-
-               @Argument(index = 1, required = true, metaVar = "FIELD", usage = "the field to update")
-               protected String fieldName;
-
-               @Argument(index = 2, required = true, metaVar = "VALUE", usage = "the new value")
-               protected List<String> fieldValues = new ArrayList<String>();
-
-               protected enum Field {
-                       name, displayName, email, password, canAdmin, canFork, canCreate, disabled;
-
-                       static Field fromString(String name) {
-                               for (Field field : values()) {
-                                       if (field.name().equalsIgnoreCase(name)) {
-                                               return field;
-                                       }
-                               }
-                               return null;
-                       }
-               }
-
-               @Override
-               protected String getUsageText() {
-                       String fields = Joiner.on(", ").join(Field.values());
-                       StringBuilder sb = new StringBuilder();
-                       sb.append("Valid fields are:\n   ").append(fields);
-                       return sb.toString();
-               }
-
-               @Override
-               public void run() throws UnloggedFailure {
-                       UserModel user = getUser(true);
-
-                       Field field = Field.fromString(fieldName);
-                       if (field == null) {
-                               throw new UnloggedFailure(1, String.format("Unknown field %s", fieldName));
-                       }
-
-                       String value = Joiner.on(" ").join(fieldValues).trim();
-                       IGitblit gitblit = getContext().getGitblit();
-
-                       boolean editCredentials = gitblit.supportsCredentialChanges(user);
-                       boolean editDisplayName = gitblit.supportsDisplayNameChanges(user);
-                       boolean editEmailAddress = gitblit.supportsEmailAddressChanges(user);
-
-                       String m = String.format("Can not edit %s for %s (%s)", field, user.username, user.accountType);
-
-                       switch(field) {
-                       case name:
-                       case displayName:
-                               if (!editDisplayName) {
-                                       throw new UnloggedFailure(1, m);
-                               }
-                               user.displayName = value;
-                               break;
-                       case email:
-                               if (!editEmailAddress) {
-                                       throw new UnloggedFailure(1, m);
-                               }
-                               user.emailAddress = value;
-                               break;
-                       case password:
-                               if (!editCredentials) {
-                                       throw new UnloggedFailure(1, m);
-                               }
-                               int minLength = gitblit.getSettings().getInteger(Keys.realm.minPasswordLength, 5);
-                               if (minLength < 4) {
-                                       minLength = 4;
-                               }
-                               if (value.trim().length() < minLength) {
-                                       throw new UnloggedFailure(1,  "Password is too short.");
-                               }
-
-                               // Optionally store the password MD5 digest.
-                               String type = gitblit.getSettings().getString(Keys.realm.passwordStorage, "md5");
-                               if (type.equalsIgnoreCase("md5")) {
-                                       // store MD5 digest of password
-                                       user.password = StringUtils.MD5_TYPE + StringUtils.getMD5(value);
-                               } else if (type.equalsIgnoreCase("combined-md5")) {
-                                       // store MD5 digest of username+password
-                                       user.password = StringUtils.COMBINED_MD5_TYPE + StringUtils.getMD5(username + value);
-                               } else {
-                                       user.password = value;
-                               }
-
-                               // reset the cookie
-                               user.cookie = StringUtils.getSHA1(user.username + value);
-                               break;
-                       case canAdmin:
-                               user.canAdmin = toBool(value);
-                               break;
-                       case canFork:
-                               user.canFork = toBool(value);
-                               break;
-                       case canCreate:
-                               user.canCreate = toBool(value);
-                               break;
-                       case disabled:
-                               user.disabled = toBool(value);
-                               break;
-                       default:
-                               throw new UnloggedFailure(1,  String.format("Field %s was not properly handled by the set command.", fieldName));
-                       }
-
-                       try {
-                               gitblit.reviseUser(username, user);
-                               stdout.println(String.format("Set %s.%s = %s", username, fieldName, value));
-                       } catch (GitBlitException e) {
-                               String msg = String.format("Failed to set %s.%s = %s", username, fieldName, value);
-                               log.error(msg, e);
-                               throw new UnloggedFailure(1, msg);
-                       }
-               }
-
-               protected boolean toBool(String value) throws UnloggedFailure {
-                       String v = value.toLowerCase();
-                       if (v.equals("t")
-                                       || v.equals("true")
-                                       || v.equals("yes")
-                                       || v.equals("on")
-                                       || v.equals("y")
-                                       || v.equals("1")) {
-                               return true;
-                       } else if (v.equals("f")
-                                       || v.equals("false")
-                                       || v.equals("no")
-                                       || v.equals("off")
-                                       || v.equals("n")
-                                       || v.equals("0")) {
-                               return false;
-                       }
-                       throw new UnloggedFailure(1,  String.format("Invalid boolean value %s", value));
-               }
-       }
-
-       @CommandMetaData(name = "disable", description = "Prohibit an account from authenticating")
-       @UsageExample(syntax = "${cmd} john", description = "Prevent John from authenticating")
-       public static class DisableUser extends UserCommand {
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       UserModel user = getUser(true);
-                       user.disabled = true;
-
-                       IGitblit gitblit = getContext().getGitblit();
-                       if (gitblit.updateUserModel(username, user)) {
-                               stdout.println(String.format("%s is not allowed to authenticate.", username));
-                       } else {
-                               throw new UnloggedFailure(1, String.format("Failed to disable %s!", username));
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "enable", description = "Allow an account to authenticate")
-       @UsageExample(syntax = "${cmd} john", description = "Allow John to authenticate")
-       public static class EnableUser extends UserCommand {
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       UserModel user = getUser(true);
-                       user.disabled = false;
-
-                       IGitblit gitblit = getContext().getGitblit();
-                       if (gitblit.updateUserModel(username, user)) {
-                               stdout.println(String.format("%s may now authenticate.", username));
-                       } else {
-                               throw new UnloggedFailure(1, String.format("Failed to enable %s!", username));
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "permissions", aliases = { "perms" }, description = "Add or remove permissions from an account")
-       @UsageExample(syntax = "${cmd} john RW:alpha/repo.git RWC:alpha/repo2.git", description = "Add or set permissions for John")
-       public static class Permissions extends UserCommand {
-
-               @Argument(index = 1, multiValued = true, metaVar = "[PERMISSION:]REPOSITORY", usage = "a repository expression")
-               protected List<String> permissions;
-
-               @Option(name = "--remove", aliases = { "-r" }, metaVar = "REPOSITORY|ALL", usage = "remove a repository permission")
-               protected List<String> removals;
-
-               @Override
-               public void run() throws UnloggedFailure {
-                       IGitblit gitblit = getContext().getGitblit();
-                       UserModel user = getUser(true);
-
-                       boolean modified = false;
-                       if (!ArrayUtils.isEmpty(removals)) {
-                               if (removals.contains("ALL")) {
-                                       user.permissions.clear();
-                               } else {
-                                       for (String repo : removals) {
-                                               user.removeRepositoryPermission(repo);
-                                               log.info(String.format("Removing permission for %s from %s", repo, username));
-                                       }
-                               }
-                               modified = true;
-                       }
-
-                       if (!ArrayUtils.isEmpty(permissions)) {
-                               for (String perm : permissions) {
-                                       String repo = AccessPermission.repositoryFromRole(perm);
-                                       if (StringUtils.findInvalidCharacter(repo) == null) {
-                                               // explicit permision, confirm repository
-                                               RepositoryModel r = gitblit.getRepositoryModel(repo);
-                                               if (r == null) {
-                                                       throw new UnloggedFailure(1, String.format("Repository %s does not exist!", repo));
-                                               }
-                                       }
-                                       AccessPermission ap = AccessPermission.permissionFromRole(perm);
-                                       user.setRepositoryPermission(repo, ap);
-                                       log.info(String.format("Setting %s:%s for %s", ap.name(), repo, username));
-                               }
-                               modified = true;
-                       }
-
-                       if (modified && gitblit.updateUserModel(username, user)) {
-                               // reload & display new permissions
-                               user = gitblit.getUserModel(username);
-                       }
-
-                       showPermissions(user);
-               }
-
-               protected void showPermissions(UserModel user) {
-                       List<RegistrantAccessPermission> perms = user.getRepositoryPermissions();
-                       String[] pheaders = { "Repository", "Permission", "Type", "Source", "Mutable" };
-                       Object [][] pdata = new Object[perms.size()][];
-                       for (int i = 0; i < perms.size(); i++) {
-                               RegistrantAccessPermission ap = perms.get(i);
-                               pdata[i] = new Object[] { ap.registrant, ap.permission, ap.permissionType, ap.source, ap.mutable ? "Y":"" };
-                       }
-                       stdout.println(FlipTable.of(pheaders, pdata, Borders.BODY_HCOLS));
-               }
-       }
-
-       @CommandMetaData(name = "remove", aliases = { "rm" }, description = "Remove a user account")
-       @UsageExample(syntax = "${cmd} john", description = "Delete john's account")
-       public static class RemoveUser extends UserCommand {
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       UserModel user = getUser(true);
-                       IGitblit gitblit = getContext().getGitblit();
-                       if (gitblit.deleteUserModel(user)) {
-                               stdout.println(String.format("%s has been deleted.", username));
-                       } else {
-                               throw new UnloggedFailure(1, String.format("Failed to delete %s!", username));
-                       }
-               }
-       }
-
-       @CommandMetaData(name = "show", description = "Show the details of an account")
-       @UsageExample(syntax = "${cmd} john", description = "Display john's account")
-       public static class ShowUser extends UserCommand {
-
-               @Override
-               public void run() throws UnloggedFailure {
-
-                       UserModel u = getUser(true);
-
-                       // fields
-                       StringBuilder fb = new StringBuilder();
-                       fb.append("Email      : ").append(u.emailAddress == null ? "": u.emailAddress).append('\n');
-                       fb.append("Type       : ").append(u.accountType).append('\n');
-                       fb.append("Can Admin  : ").append(u.canAdmin() ? "Y":"").append('\n');
-                       fb.append("Can Fork   : ").append(u.canFork() ? "Y":"").append('\n');
-                       fb.append("Can Create : ").append(u.canCreate() ? "Y":"").append('\n');
-                       String fields = fb.toString();
-
-                       // teams
-                       String teams;
-                       if (u.teams.size() == 0) {
-                               teams = FlipTable.EMPTY;
-                       } else {
-                               teams = Joiner.on(", ").join(u.teams);
-                       }
-
-                       // owned repositories
-                       String ownedTable;
-                       List<RepositoryModel> owned = new ArrayList<RepositoryModel>();
-                       for (RepositoryModel repository : getContext().getGitblit().getRepositoryModels(u)) {
-                               if (repository.isOwner(u.username)) {
-                                       owned.add(repository);
-                               }
-                       }
-                       if (owned.isEmpty()) {
-                               ownedTable = FlipTable.EMPTY;
-                       } else {
-                               String [] theaders = new String [] { "Repository", "Description" };
-                               Object [][] tdata = new Object[owned.size()][];
-                               int i = 0;
-                               for (RepositoryModel r : owned) {
-                                       tdata[i] = new Object [] { r.name, r.description };
-                                       i++;
-                               }
-                               ownedTable = FlipTable.of(theaders, tdata, Borders.COLS);
-                       }
-
-                       // permissions
-                       List<RegistrantAccessPermission> perms = u.getRepositoryPermissions();
-                       String permissions;
-                       if (perms.isEmpty()) {
-                               permissions = FlipTable.EMPTY;
-                       } else {
-                               String[] pheaders = { "Repository", "Permission", "Type", "Source", "Mutable" };
-                               Object [][] pdata = new Object[perms.size()][];
-                               for (int i = 0; i < perms.size(); i++) {
-                                       RegistrantAccessPermission ap = perms.get(i);
-                                       pdata[i] = new Object[] { ap.registrant, ap.permission, ap.permissionType, ap.source, ap.mutable ? "Y":"" };
-                               }
-                               permissions = FlipTable.of(pheaders, pdata, Borders.COLS);
-                       }
-
-                       // keys
-                       String keyTable;
-                       List<SshKey> keys = getContext().getGitblit().getPublicKeyManager().getKeys(u.username);
-                       if (ArrayUtils.isEmpty(keys)) {
-                               keyTable = FlipTable.EMPTY;
-                       } else {
-                               String[] headers = { "#", "Fingerprint", "Comment", "Type" };
-                               int len = keys == null ? 0 : keys.size();
-                               Object[][] data = new Object[len][];
-                               for (int i = 0; i < len; i++) {
-                                       // show 1-based index numbers with the fingerprint
-                                       // this is useful for comparing with "ssh-add -l"
-                                       SshKey k = keys.get(i);
-                                       data[i] = new Object[] { (i + 1), k.getFingerprint(), k.getComment(), k.getAlgorithm() };
-                               }
-                               keyTable = FlipTable.of(headers, data, Borders.COLS);
-                       }
-
-                       // assemble user table
-                       String userTitle = u.getDisplayName() + (u.username.equals(u.getDisplayName()) ? "" : (" (" + u.username + ")"));
-                       if (u.disabled) {
-                               userTitle += "  [DISABLED]";
-                       }
-                       String [] headers = new String[] { userTitle };
-                       String[][] data = new String[8][];
-                       data[0] = new String [] { "FIELDS" };
-                       data[1] = new String [] { fields };
-                       data[2] = new String [] { "TEAMS" };
-                       data[3] = new String [] { teams };
-                       data[4] = new String [] { "OWNED REPOSITORIES" };
-                       data[5] = new String [] { ownedTable };
-                       data[4] = new String [] { "PERMISSIONS" };
-                       data[5] = new String [] { permissions };
-                       data[6] = new String [] { "SSH PUBLIC KEYS" };
-                       data[7] = new String [] { keyTable };
-                       stdout.println(FlipTable.of(headers, data));
-               }
-       }
-
-       @CommandMetaData(name = "list", aliases= { "ls" }, description = "List accounts")
-       @UsageExamples(examples = {
-               @UsageExample(syntax = "${cmd}", description = "List accounts as a table"),
-               @UsageExample(syntax = "${cmd} j.*", description = "List all accounts that start with 'j'"),
-       })
-       public static class ListUsers extends ListFilterCommand<UserModel> {
-
-               @Override
-               protected List<UserModel> getItems() {
-                       IGitblit gitblit = getContext().getGitblit();
-                       List<UserModel> users = gitblit.getAllUsers();
-                       return users;
-               }
-
-               @Override
-               protected boolean matches(String filter, UserModel u) {
-                       return u.username.matches(filter);
-               }
-
-               @Override
-               protected void asTable(List<UserModel> list) {
-                       String[] headers;
-                       if (verbose) {
-                               String[] h = { "Name", "Display name", "Email", "Type", "Teams", "Create?", "Fork?"};
-                               headers = h;
-                       } else {
-                               String[] h = { "Name", "Display name", "Email", "Type"};
-                               headers = h;
-                       }
-
-                       Object[][] data = new Object[list.size()][];
-                       for (int i = 0; i < list.size(); i++) {
-                               UserModel u = list.get(i);
-
-                               String name = (u.disabled ? "-" : ((u.canAdmin() ? "*" : " "))) + u.username;
-                               if (verbose) {
-                                       data[i] = new Object[] {
-                                                       name,
-                                                       u.displayName,
-                                                       u.emailAddress,
-                                                       u.accountType + (u.canAdmin() ? ",admin":""),
-                                                       u.teams.isEmpty() ? "" : u.teams.size(),
-                                                       (u.canAdmin() || u.canCreate()) ? "Y":"",
-                                                       (u.canAdmin() || u.canFork()) ? "Y" : ""};
-                               } else {
-                                       data[i] = new Object[] {
-                                                       name,
-                                                       u.displayName,
-                                                       u.emailAddress,
-                                                       u.accountType + (u.canAdmin() ? ",admin":"")};
-                               }
-                       }
-                       stdout.print(FlipTable.of(headers, data, Borders.BODY_HCOLS));
-                       stdout.println("  * = admin account,  - = disabled account");
-                       stdout.println();
-               }
-
-               @Override
-               protected void asTabbed(List<UserModel> users) {
-                       if (verbose) {
-                               for (UserModel u : users) {
-                                       outTabbed(
-                                                       u.disabled ? "-" : ((u.canAdmin() ? "*" : " ")) + u.username,
-                                                       u.getDisplayName(),
-                                                       u.emailAddress == null ? "" : u.emailAddress,
-                                                       u.accountType + (u.canAdmin() ? ",admin":""),
-                                                       u.teams.isEmpty() ? "" : u.teams.size(),
-                                                       (u.canAdmin() || u.canCreate()) ? "Y":"",
-                                                       (u.canAdmin() || u.canFork()) ? "Y" : "");
-                               }
-                       } else {
-                               for (UserModel u : users) {
-                                       outTabbed(u.disabled ? "-" : ((u.canAdmin() ? "*" : " ")) + u.username);
-                               }
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/transport/ssh/gitblit/VersionCommand.java b/src/main/java/com/gitblit/transport/ssh/gitblit/VersionCommand.java
deleted file mode 100644 (file)
index 384c6ce..0000000
+++ /dev/null
@@ -1,30 +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.gitblit;
-
-import com.gitblit.Constants;
-import com.gitblit.transport.ssh.commands.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());
-  }
-}
diff --git a/src/main/java/com/gitblit/transport/ssh/keys/BaseKeyCommand.java b/src/main/java/com/gitblit/transport/ssh/keys/BaseKeyCommand.java
new file mode 100644 (file)
index 0000000..588770f
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.keys;
+
+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.IPublicKeyManager;
+import com.gitblit.transport.ssh.SshKey;
+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 IPublicKeyManager getKeyManager() {
+               return getContext().getGitblit().getPublicKeyManager();
+       }
+
+       protected SshKey parseKey(String rawData) throws UnloggedFailure {
+               if (rawData.contains("PRIVATE")) {
+                       throw new UnloggedFailure(1,  "Please provide a PUBLIC key, not a PRIVATE key!");
+               }
+               SshKey key = new SshKey(rawData);
+               return key;
+       }
+}
diff --git a/src/main/java/com/gitblit/transport/ssh/keys/KeysDispatcher.java b/src/main/java/com/gitblit/transport/ssh/keys/KeysDispatcher.java
new file mode 100644 (file)
index 0000000..ad37306
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * 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.keys;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.models.UserModel;
+import com.gitblit.transport.ssh.IPublicKeyManager;
+import com.gitblit.transport.ssh.SshKey;
+import com.gitblit.transport.ssh.commands.CommandMetaData;
+import com.gitblit.transport.ssh.commands.DispatchCommand;
+import com.gitblit.transport.ssh.commands.SshCommand;
+import com.gitblit.transport.ssh.commands.UsageExample;
+import com.gitblit.utils.FlipTable;
+import com.gitblit.utils.FlipTable.Borders;
+import com.google.common.base.Joiner;
+
+/**
+ * The dispatcher and it's commands for SSH public key management.
+ *
+ * @author James Moger
+ *
+ */
+@CommandMetaData(name = "keys", description = "SSH public key management commands")
+public class KeysDispatcher extends DispatchCommand {
+
+       @Override
+       protected void setup(UserModel user) {
+               register(user, AddKey.class);
+               register(user, RemoveKey.class);
+               register(user, ListKeys.class);
+               register(user, WhichKey.class);
+               register(user, CommentKey.class);
+       }
+
+       @CommandMetaData(name = "add", description = "Add an SSH public key to your account")
+       @UsageExample(syntax = "cat ~/.ssh/id_rsa.pub | ${ssh} ${cmd} -", description = "Upload your SSH public key and add it to your account")
+       public static class AddKey extends BaseKeyCommand {
+
+               protected final Logger log = LoggerFactory.getLogger(getClass());
+
+               @Argument(metaVar = "<KEY>", usage = "the key(s) to add")
+               private List<String> addKeys = new ArrayList<String>();
+
+               @Override
+               public void run() throws IOException, UnloggedFailure {
+                       String username = getContext().getClient().getUsername();
+                       List<String> keys = readKeys(addKeys);
+                       for (String key : keys) {
+                               SshKey sshKey = parseKey(key);
+                               getKeyManager().addKey(username, sshKey);
+                               log.info("added SSH public key for {}", username);
+                       }
+               }
+       }
+
+       @CommandMetaData(name = "remove", aliases = { "rm" }, description = "Remove an SSH public key from your account")
+       @UsageExample(syntax = "${cmd} 2", description = "Remove the SSH key identified as #2 in `keys list`")
+       public static class RemoveKey extends BaseKeyCommand {
+
+               protected final Logger log = LoggerFactory.getLogger(getClass());
+
+               private final String ALL = "ALL";
+
+               @Argument(metaVar = "<INDEX>|<KEY>|ALL", usage = "the key to remove", required = true)
+               private List<String> removeKeys = new ArrayList<String>();
+
+               @Override
+               public void run() throws IOException, UnloggedFailure {
+                       String username = getContext().getClient().getUsername();
+                       // remove a key that has been piped to the command
+                       // or remove all keys
+
+                       List<SshKey> currentKeys = getKeyManager().getKeys(username);
+                       if (currentKeys == null || currentKeys.isEmpty()) {
+                               throw new UnloggedFailure(1, "There are no registered keys!");
+                       }
+
+                       List<String> keys = readKeys(removeKeys);
+                       if (keys.contains(ALL)) {
+                               if (getKeyManager().removeAllKeys(username)) {
+                                       stdout.println("Removed all keys.");
+                                       log.info("removed all SSH public keys from {}", username);
+                               } else {
+                                       log.warn("failed to remove all SSH public keys from {}", username);
+                               }
+                       } else {
+                               for (String key : keys) {
+                                       try {
+                                               // remove a key by it's index (1-based indexing)
+                                               int index = Integer.parseInt(key);
+                                               if (index > keys.size()) {
+                                                       if (keys.size() == 1) {
+                                                               throw new UnloggedFailure(1, "Invalid index specified. There is only 1 registered key.");
+                                                       }
+                                                       throw new UnloggedFailure(1, String.format("Invalid index specified. There are %d registered keys.", keys.size()));
+                                               }
+                                               SshKey sshKey = currentKeys.get(index - 1);
+                                               if (getKeyManager().removeKey(username, sshKey)) {
+                                                       stdout.println(String.format("Removed %s", sshKey.getFingerprint()));
+                                               } else {
+                                                       throw new UnloggedFailure(1,  String.format("failed to remove #%s: %s", key, sshKey.getFingerprint()));
+                                               }
+                                       } catch (Exception e) {
+                                               // remove key by raw key data
+                                               SshKey sshKey = parseKey(key);
+                                               if (getKeyManager().removeKey(username, sshKey)) {
+                                                       stdout.println(String.format("Removed %s", sshKey.getFingerprint()));
+                                                       log.info("removed SSH public key {} from {}", sshKey.getFingerprint(), username);
+                                               } else {
+                                                       log.warn("failed to remove SSH public key {} from {}", sshKey.getFingerprint(), username);
+                                                       throw new UnloggedFailure(1,  String.format("failed to remove %s", sshKey.getFingerprint()));
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       @CommandMetaData(name = "list", aliases = { "ls" }, description = "List your registered SSH public keys")
+       public static class ListKeys extends SshCommand {
+
+               @Option(name = "-L", usage = "list complete public key parameters")
+               private boolean showRaw;
+
+               @Override
+               public void run() {
+                       IPublicKeyManager keyManager = getContext().getGitblit().getPublicKeyManager();
+                       String username = getContext().getClient().getUsername();
+                       List<SshKey> keys = keyManager.getKeys(username);
+
+                       if (showRaw) {
+                               asRaw(keys);
+                       } else {
+                               asTable(keys);
+                       }
+               }
+
+               /* output in the same format as authorized_keys */
+               protected void asRaw(List<SshKey> keys) {
+                       if (keys == null) {
+                               return;
+                       }
+                       for (SshKey key : keys) {
+                               stdout.println(key.getRawData());
+                       }
+               }
+
+               protected void asTable(List<SshKey> keys) {
+                       String[] headers = { "#", "Fingerprint", "Comment", "Type" };
+                       int len = keys == null ? 0 : keys.size();
+                       Object[][] data = new Object[len][];
+                       for (int i = 0; i < len; i++) {
+                               // show 1-based index numbers with the fingerprint
+                               // this is useful for comparing with "ssh-add -l"
+                               SshKey k = keys.get(i);
+                               data[i] = new Object[] { (i + 1), k.getFingerprint(), k.getComment(), k.getAlgorithm() };
+                       }
+
+                       stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
+               }
+       }
+
+       @CommandMetaData(name = "which", description = "Display the SSH public key used for this session")
+       public static class WhichKey extends SshCommand {
+
+               @Option(name = "-L", usage = "list complete public key parameters")
+               private boolean showRaw;
+
+               @Override
+               public void run() throws UnloggedFailure {
+                       SshKey key = getContext().getClient().getKey();
+                       if (key == null) {
+                               throw new UnloggedFailure(1,  "You have not authenticated with an SSH public key.");
+                       }
+
+                       if (showRaw) {
+                               stdout.println(key.getRawData());
+                       } else {
+                               final String username = getContext().getClient().getUsername();
+                               List<SshKey> keys = getContext().getGitblit().getPublicKeyManager().getKeys(username);
+                               int index = 0;
+                               for (int i = 0; i < keys.size(); i++) {
+                                       if (key.equals(keys.get(i))) {
+                                               index = i + 1;
+                                               break;
+                                       }
+                               }
+                               asTable(index, key);
+                       }
+               }
+
+               protected void asTable(int index, SshKey key) {
+                       String[] headers = { "#", "Fingerprint", "Comment", "Type" };
+                       Object[][] data = new Object[1][];
+                       data[0] = new Object[] { index, key.getFingerprint(), key.getComment(), key.getAlgorithm() };
+
+                       stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
+               }
+       }
+
+       @CommandMetaData(name = "comment", description = "Set the comment for an SSH public key")
+       @UsageExample(syntax = "${cmd} 3 Home workstation", description = "Set the comment for key #3")
+       public static class CommentKey extends SshCommand {
+
+               @Argument(index = 0, metaVar = "INDEX", usage = "the key index", required = true)
+               private int index;
+
+               @Argument(index = 1, metaVar = "COMMENT", usage = "the new comment", required = true)
+               private List<String> values = new ArrayList<String>();
+
+               @Override
+               public void run() throws UnloggedFailure {
+                       final String username = getContext().getClient().getUsername();
+                       IPublicKeyManager keyManager = getContext().getGitblit().getPublicKeyManager();
+                       List<SshKey> keys = keyManager.getKeys(username);
+                       if (index > keys.size()) {
+                               throw new UnloggedFailure(1,  "Invalid key index!");
+                       }
+
+                       String comment = Joiner.on(" ").join(values);
+                       SshKey key = keys.get(index - 1);
+                       key.setComment(comment);
+                       if (keyManager.addKey(username, key)) {
+                               stdout.println(String.format("Updated the comment for key #%d.", index));
+                       } else {
+                               throw new UnloggedFailure(1, String.format("Failed to update the comment for key #%d!", index));
+                       }
+               }
+
+       }
+}
index 0f09910e88e8442c1d659be6335a38fcd1469dc2..a671e5af3fec225befdcef9e2ac9b2a79a76a13d 100644 (file)
@@ -23,8 +23,8 @@ First you'll need to create an SSH key pair, if you don't already have one or if
 \r
 Then you can upload your *public* key right from the command-line.\r
 \r
-    cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys add\r
-    cat c:\<userfolder>\.ssh\id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys add\r
+    cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> keys add\r
+    cat c:\<userfolder>\.ssh\id_rsa.pub | ssh -l <username> -p 29418 <hostname> keys add\r
 \r
 **NOTE:** It is important to note that *ssh-keygen* generates a public/private keypair (e.g. id_rsa and id_rsa.pub).  You want to upload the *public* key, which is denoted by the *.pub* file extension.\r
 \r
@@ -36,7 +36,7 @@ Once you've done both of those steps you should be able to execute the following
 \r
 Typing the following command syntax all the time gets to be rather tedious.\r
 \r
-    ssh -l <username> -p 29418 <hostname> gitblit version\r
+    ssh -l <username> -p 29418 <hostname>\r
 \r
 You can define an alias for your server which will reduce your command syntax to something like this.\r
 \r
@@ -54,29 +54,33 @@ Create or modify your `~/.ssh/config` file and add a host entry.  If you are on
 \r
 Gitblit supports SSH command plugins and provides several commands out-of-the-box.\r
 \r
-#### gitblit\r
+#### keys\r
 \r
-The *gitblit* command has many subcommands for interacting with Gitblit.\r
+The *keys* command dispatcher allows you to manage your public ssh keys.  You can list keys, add keys, remove keys, and identify the key in-use for the active session.\r
 \r
 ##### keys add\r
 \r
 Add an SSH public key to your account.  This command accepts a public key piped to stdin.\r
 \r
-    cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> gitblit keys add\r
+    cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> keys add\r
 \r
 ##### keys list\r
 \r
 Show the SSH public keys you have added to your account.\r
 \r
-    ssh -l <username> -p 29418 <hostname> gitblit keys list\r
+    ssh -l <username> -p 29418 <hostname> keys list\r
 \r
 ##### keys remove\r
 \r
 Remove an SSH public key from your account.  This command accepts several input values, the most useful one is an index number which matches the index number displayed in the `list` command.\r
 \r
-    ssh -l <username> -p 29418 <hostname> gitblit keys remove 2\r
+    ssh -l <username> -p 29418 <hostname> keys remove 2\r
 \r
 You can also remove all your public keys from your account.\r
 \r
-    ssh -l <username> -p 29418 <hostname> gitblit keys remove ALL\r
+    ssh -l <username> -p 29418 <hostname> keys remove ALL\r
+\r
+### SSH Command Plugins\r
+\r
+Gitblit supports loading custom SSH command plugins.\r
 \r
index dbd1d86841e6bb9a69e9b513897f04e98c44055c..620190ef8a7ff75b78c17e55267c7a2ea4837a08 100644 (file)
@@ -93,7 +93,7 @@ public class SshDaemonTest extends GitblitUnitTest {
         pair.getPublic().getEncoded();
         assertTrue(session.authPublicKey("admin", pair).await().isSuccess());
 
-        ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, "gitblit version");
+        ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_EXEC, "version");
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         Writer w = new OutputStreamWriter(baos);
         w.close();