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