Refactor SSH commands with SshCommand base class
The SshCommand base class extends BaseCommand and provides the common pattern of calling startThread with a CommandRunnable that parses argments and then invokes the real logic. The new annotation @RequiresCapability can be declared on any concrete implementation of SshCommand to name a capability the caller must have before they can run the contained command. This is enforced inside of the DispatchCommand, which is what handles creating and delegating to any paticular command implementation. @AdminCommand is replaced by the new @RequriesCapability annotation, which is more explicitly declaring the administrate server dependency. Most existing commands have been ported to this SshCommand base class, cleaning up a lot of the code. A few special cases still exist such as StreamEvents or ScpCommand that are not trivial to port, as their start implementation is well outside of the common pattern. Plugin authors should be encouraged to extend from SshCommand for the foreseeable future. I eventually would like to get away from needing to extend this class, and instead use a simpler interface declaration, but that is a much bigger change to make with how DispatchCommand and BaseCommand are connected together. Change-Id: I4f1de60c6fdeb207197dfccc135b4d532443d5b2
This commit is contained in:
@@ -246,8 +246,8 @@ public abstract class BaseCommand implements Command {
|
|||||||
protected synchronized void startThread(final CommandRunnable thunk) {
|
protected synchronized void startThread(final CommandRunnable thunk) {
|
||||||
final TaskThunk tt = new TaskThunk(thunk);
|
final TaskThunk tt = new TaskThunk(thunk);
|
||||||
|
|
||||||
if (isAdminCommand() || (isAdminHighPriorityCommand()
|
if (isAdminHighPriorityCommand()
|
||||||
&& userProvider.get().getCapabilities().canAdministrateServer())) {
|
&& userProvider.get().getCapabilities().canAdministrateServer()) {
|
||||||
// Admin commands should not block the main work threads (there
|
// Admin commands should not block the main work threads (there
|
||||||
// might be an interactive shell there), nor should they wait
|
// might be an interactive shell there), nor should they wait
|
||||||
// for the main work threads.
|
// for the main work threads.
|
||||||
@@ -258,10 +258,6 @@ public abstract class BaseCommand implements Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final boolean isAdminCommand() {
|
|
||||||
return getClass().getAnnotation(AdminCommand.class) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final boolean isAdminHighPriorityCommand() {
|
private final boolean isAdminHighPriorityCommand() {
|
||||||
return getClass().getAnnotation(AdminHighPriorityCommand.class) != null;
|
return getClass().getAnnotation(AdminHighPriorityCommand.class) != null;
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
package com.google.gerrit.sshd;
|
package com.google.gerrit.sshd;
|
||||||
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
|
import com.google.gerrit.server.account.CapabilityControl;
|
||||||
import com.google.gerrit.sshd.args4j.SubcommandHandler;
|
import com.google.gerrit.sshd.args4j.SubcommandHandler;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
@@ -70,13 +71,7 @@ final class DispatchCommand extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Command cmd = p.get();
|
final Command cmd = p.get();
|
||||||
|
checkRequiresCapability(cmd);
|
||||||
if (isAdminCommand(cmd)
|
|
||||||
&& !currentUser.get().getCapabilities().canAdministrateServer()) {
|
|
||||||
final String msg = "fatal: Not a Gerrit administrator";
|
|
||||||
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd instanceof BaseCommand) {
|
if (cmd instanceof BaseCommand) {
|
||||||
final BaseCommand bc = (BaseCommand) cmd;
|
final BaseCommand bc = (BaseCommand) cmd;
|
||||||
if (prefix.isEmpty())
|
if (prefix.isEmpty())
|
||||||
@@ -107,8 +102,18 @@ final class DispatchCommand extends BaseCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAdminCommand(final Command cmd) {
|
private void checkRequiresCapability(Command cmd) throws UnloggedFailure {
|
||||||
return cmd.getClass().getAnnotation(AdminCommand.class) != null;
|
RequiresCapability rc = cmd.getClass().getAnnotation(RequiresCapability.class);
|
||||||
|
if (rc != null) {
|
||||||
|
CurrentUser user = currentUser.get();
|
||||||
|
CapabilityControl ctl = user.getCapabilities();
|
||||||
|
if (!ctl.canPerform(rc.value()) && !ctl.canAdministrateServer()) {
|
||||||
|
String msg = String.format(
|
||||||
|
"fatal: %s does not have \"%s\" capability.",
|
||||||
|
user.getUserName(), rc.value());
|
||||||
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2009 The Android Open Source Project
|
// Copyright (C) 2012 The Android Open Source Project
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -21,12 +21,10 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation tagged on a concrete Command that requires administrator access.
|
* Annotation on {@link SshCommand} declaring a capability must be granted.
|
||||||
* <p>
|
|
||||||
* Currently this annotation is only enforced by DispatchCommand after it has
|
|
||||||
* created the command object, but before it populates it or starts execution.
|
|
||||||
*/
|
*/
|
||||||
@Target( {ElementType.TYPE})
|
@Target({ElementType.TYPE})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface AdminCommand {
|
public @interface RequiresCapability {
|
||||||
|
String value();
|
||||||
}
|
}
|
@@ -0,0 +1,45 @@
|
|||||||
|
// 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.google.gerrit.sshd;
|
||||||
|
|
||||||
|
import org.apache.sshd.server.Environment;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
public abstract class SshCommand extends BaseCommand {
|
||||||
|
protected PrintWriter stdout;
|
||||||
|
protected PrintWriter stderr;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Environment env) throws IOException {
|
||||||
|
startThread(new CommandRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() throws Exception {
|
||||||
|
parseCommandLine();
|
||||||
|
stdout = toPrintWriter(out);
|
||||||
|
stderr = toPrintWriter(err);
|
||||||
|
try {
|
||||||
|
SshCommand.this.run();
|
||||||
|
} finally {
|
||||||
|
stdout.flush();
|
||||||
|
stderr.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void run() throws UnloggedFailure, Failure, Exception;
|
||||||
|
}
|
@@ -14,16 +14,18 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.sshd.AdminCommand;
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.AdminHighPriorityCommand;
|
||||||
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
/** Opens a query processor. */
|
/** Opens a query processor. */
|
||||||
@AdminCommand
|
@AdminHighPriorityCommand
|
||||||
final class AdminQueryShell extends BaseCommand {
|
@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
|
||||||
|
final class AdminQueryShell extends SshCommand {
|
||||||
@Inject
|
@Inject
|
||||||
private QueryShell.Factory factory;
|
private QueryShell.Factory factory;
|
||||||
|
|
||||||
@@ -34,19 +36,13 @@ final class AdminQueryShell extends BaseCommand {
|
|||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() {
|
||||||
startThread(new CommandRunnable() {
|
final QueryShell shell = factory.create(in, out);
|
||||||
@Override
|
shell.setOutputFormat(format);
|
||||||
public void run() throws Exception {
|
if (query != null) {
|
||||||
parseCommandLine();
|
shell.execute(query);
|
||||||
final QueryShell shell = factory.create(in, out);
|
} else {
|
||||||
shell.setOutputFormat(format);
|
shell.run();
|
||||||
if (query != null) {
|
}
|
||||||
shell.execute(query);
|
|
||||||
} else {
|
|
||||||
shell.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.server.config.AllProjectsName;
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
import com.google.gerrit.server.git.MetaDataUpdate;
|
import com.google.gerrit.server.git.MetaDataUpdate;
|
||||||
@@ -21,11 +22,10 @@ import com.google.gerrit.server.git.ProjectConfig;
|
|||||||
import com.google.gerrit.server.project.ProjectCache;
|
import com.google.gerrit.server.project.ProjectCache;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gerrit.server.project.ProjectState;
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
import com.google.gerrit.sshd.AdminCommand;
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
@@ -34,14 +34,13 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@AdminCommand
|
@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
|
||||||
final class AdminSetParent extends BaseCommand {
|
final class AdminSetParent extends SshCommand {
|
||||||
private static final Logger log = LoggerFactory.getLogger(AdminSetParent.class);
|
private static final Logger log = LoggerFactory.getLogger(AdminSetParent.class);
|
||||||
|
|
||||||
@Option(name = "--parent", aliases = {"-p"}, metaVar = "NAME", usage = "new parent project")
|
@Option(name = "--parent", aliases = {"-p"}, metaVar = "NAME", usage = "new parent project")
|
||||||
@@ -68,26 +67,10 @@ final class AdminSetParent extends BaseCommand {
|
|||||||
@Inject
|
@Inject
|
||||||
private AllProjectsName allProjectsName;
|
private AllProjectsName allProjectsName;
|
||||||
|
|
||||||
private PrintWriter stdout;
|
|
||||||
private Project.NameKey newParentKey = null;
|
private Project.NameKey newParentKey = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() throws Failure {
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
stdout = toPrintWriter(out);
|
|
||||||
try {
|
|
||||||
parseCommandLine();
|
|
||||||
updateParents();
|
|
||||||
} finally {
|
|
||||||
stdout.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateParents() throws Failure {
|
|
||||||
if (oldParent == null && children.isEmpty()) {
|
if (oldParent == null && children.isEmpty()) {
|
||||||
throw new UnloggedFailure(1, "fatal: child projects have to be specified as " +
|
throw new UnloggedFailure(1, "fatal: child projects have to be specified as " +
|
||||||
"arguments or the --children-of option has to be set");
|
"arguments or the --children-of option has to be set");
|
||||||
|
@@ -20,10 +20,9 @@ import com.google.gerrit.server.git.BanCommitResult;
|
|||||||
import com.google.gerrit.server.git.IncompleteUserInfoException;
|
import com.google.gerrit.server.git.IncompleteUserInfoException;
|
||||||
import com.google.gerrit.server.git.MergeException;
|
import com.google.gerrit.server.git.MergeException;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
@@ -33,8 +32,7 @@ import java.io.PrintWriter;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class BanCommitCommand extends BaseCommand {
|
public class BanCommitCommand extends SshCommand {
|
||||||
|
|
||||||
@Option(name = "--reason", aliases = {"-r"}, metaVar = "REASON", usage = "reason for banning the commit")
|
@Option(name = "--reason", aliases = {"-r"}, metaVar = "REASON", usage = "reason for banning the commit")
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
@@ -50,45 +48,30 @@ public class BanCommitCommand extends BaseCommand {
|
|||||||
private BanCommit.Factory banCommitFactory;
|
private BanCommit.Factory banCommitFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) throws IOException {
|
protected void run() throws Failure {
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
parseCommandLine();
|
|
||||||
BanCommitCommand.this.display();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void display() throws Failure {
|
|
||||||
try {
|
try {
|
||||||
final BanCommitResult result =
|
final BanCommitResult result =
|
||||||
banCommitFactory.create().ban(projectControl, commitsToBan, reason);
|
banCommitFactory.create().ban(projectControl, commitsToBan, reason);
|
||||||
|
|
||||||
final PrintWriter stdout = toPrintWriter(out);
|
final List<ObjectId> newlyBannedCommits =
|
||||||
try {
|
result.getNewlyBannedCommits();
|
||||||
final List<ObjectId> newlyBannedCommits =
|
if (!newlyBannedCommits.isEmpty()) {
|
||||||
result.getNewlyBannedCommits();
|
stdout.print("The following commits were banned:\n");
|
||||||
if (!newlyBannedCommits.isEmpty()) {
|
printCommits(stdout, newlyBannedCommits);
|
||||||
stdout.print("The following commits were banned:\n");
|
}
|
||||||
printCommits(stdout, newlyBannedCommits);
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<ObjectId> alreadyBannedCommits =
|
final List<ObjectId> alreadyBannedCommits =
|
||||||
result.getAlreadyBannedCommits();
|
result.getAlreadyBannedCommits();
|
||||||
if (!alreadyBannedCommits.isEmpty()) {
|
if (!alreadyBannedCommits.isEmpty()) {
|
||||||
stdout.print("The following commits were already banned:\n");
|
stdout.print("The following commits were already banned:\n");
|
||||||
printCommits(stdout, alreadyBannedCommits);
|
printCommits(stdout, alreadyBannedCommits);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<ObjectId> ignoredIds = result.getIgnoredObjectIds();
|
final List<ObjectId> ignoredIds = result.getIgnoredObjectIds();
|
||||||
if (!ignoredIds.isEmpty()) {
|
if (!ignoredIds.isEmpty()) {
|
||||||
stdout.print("The following ids do not represent commits"
|
stdout.print("The following ids do not represent commits"
|
||||||
+ " and were ignored:\n");
|
+ " and were ignored:\n");
|
||||||
printCommits(stdout, ignoredIds);
|
printCommits(stdout, ignoredIds);
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
stdout.flush();
|
|
||||||
}
|
}
|
||||||
} catch (PermissionDeniedException e) {
|
} catch (PermissionDeniedException e) {
|
||||||
throw die(e);
|
throw die(e);
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.ehcache.EhcachePoolImpl;
|
import com.google.gerrit.ehcache.EhcachePoolImpl;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import net.sf.ehcache.CacheManager;
|
import net.sf.ehcache.CacheManager;
|
||||||
@@ -25,7 +25,7 @@ import java.util.Arrays;
|
|||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
abstract class CacheCommand extends BaseCommand {
|
abstract class CacheCommand extends SshCommand {
|
||||||
@Inject
|
@Inject
|
||||||
protected EhcachePoolImpl cachePool;
|
protected EhcachePoolImpl cachePool;
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.common.errors.InvalidSshKeyException;
|
import com.google.gerrit.common.errors.InvalidSshKeyException;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
||||||
@@ -26,12 +27,12 @@ import com.google.gerrit.server.IdentifiedUser;
|
|||||||
import com.google.gerrit.server.account.AccountByEmailCache;
|
import com.google.gerrit.server.account.AccountByEmailCache;
|
||||||
import com.google.gerrit.server.account.AccountCache;
|
import com.google.gerrit.server.account.AccountCache;
|
||||||
import com.google.gerrit.server.ssh.SshKeyCache;
|
import com.google.gerrit.server.ssh.SshKeyCache;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.gwtorm.server.OrmDuplicateKeyException;
|
import com.google.gwtorm.server.OrmDuplicateKeyException;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
@@ -45,7 +46,8 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Create a new user account. **/
|
/** Create a new user account. **/
|
||||||
final class CreateAccountCommand extends BaseCommand {
|
@RequiresCapability(GlobalCapability.CREATE_ACCOUNT)
|
||||||
|
final class CreateAccountCommand extends SshCommand {
|
||||||
@Option(name = "--group", aliases = {"-g"}, metaVar = "GROUP", usage = "groups to add account to")
|
@Option(name = "--group", aliases = {"-g"}, metaVar = "GROUP", usage = "groups to add account to")
|
||||||
private List<AccountGroup.Id> groups = new ArrayList<AccountGroup.Id>();
|
private List<AccountGroup.Id> groups = new ArrayList<AccountGroup.Id>();
|
||||||
|
|
||||||
@@ -77,24 +79,7 @@ final class CreateAccountCommand extends BaseCommand {
|
|||||||
private AccountByEmailCache byEmailCache;
|
private AccountByEmailCache byEmailCache;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() throws OrmException, IOException,
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
if (!currentUser.getCapabilities().canCreateAccount()) {
|
|
||||||
String msg = String.format(
|
|
||||||
"fatal: %s does not have \"Create Account\" capability.",
|
|
||||||
currentUser.getUserName());
|
|
||||||
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
parseCommandLine();
|
|
||||||
createAccount();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createAccount() throws OrmException, IOException,
|
|
||||||
InvalidSshKeyException, UnloggedFailure {
|
InvalidSshKeyException, UnloggedFailure {
|
||||||
if (!username.matches(Account.USER_NAME_PATTERN)) {
|
if (!username.matches(Account.USER_NAME_PATTERN)) {
|
||||||
throw die("Username '" + username + "'"
|
throw die("Username '" + username + "'"
|
||||||
|
@@ -14,15 +14,17 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
||||||
import com.google.gerrit.common.errors.PermissionDeniedException;
|
import com.google.gerrit.common.errors.PermissionDeniedException;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
import com.google.gerrit.server.account.PerformCreateGroup;
|
import com.google.gerrit.server.account.PerformCreateGroup;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
@@ -34,7 +36,8 @@ import java.util.Set;
|
|||||||
* <p>
|
* <p>
|
||||||
* Optionally, puts an initial set of user in the newly created group.
|
* Optionally, puts an initial set of user in the newly created group.
|
||||||
*/
|
*/
|
||||||
final class CreateGroupCommand extends BaseCommand {
|
@RequiresCapability(GlobalCapability.CREATE_GROUP)
|
||||||
|
final class CreateGroupCommand extends SshCommand {
|
||||||
@Option(name = "--owner", aliases = {"-o"}, metaVar = "GROUP", usage = "owning group, if not specified the group will be self-owning")
|
@Option(name = "--owner", aliases = {"-o"}, metaVar = "GROUP", usage = "owning group, if not specified the group will be self-owning")
|
||||||
private AccountGroup.Id ownerGroupId;
|
private AccountGroup.Id ownerGroupId;
|
||||||
|
|
||||||
@@ -65,25 +68,19 @@ final class CreateGroupCommand extends BaseCommand {
|
|||||||
private PerformCreateGroup.Factory performCreateGroupFactory;
|
private PerformCreateGroup.Factory performCreateGroupFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Environment env) {
|
protected void run() throws Failure, OrmException {
|
||||||
startThread(new CommandRunnable() {
|
try {
|
||||||
@Override
|
performCreateGroupFactory.create().createGroup(groupName,
|
||||||
public void run() throws Exception {
|
groupDescription,
|
||||||
parseCommandLine();
|
visibleToAll,
|
||||||
try {
|
ownerGroupId,
|
||||||
performCreateGroupFactory.create().createGroup(groupName,
|
initialMembers,
|
||||||
groupDescription,
|
initialGroups);
|
||||||
visibleToAll,
|
} catch (PermissionDeniedException e) {
|
||||||
ownerGroupId,
|
throw die(e);
|
||||||
initialMembers,
|
|
||||||
initialGroups);
|
|
||||||
} catch (PermissionDeniedException e) {
|
|
||||||
throw die(e);
|
|
||||||
|
|
||||||
} catch (NameAlreadyUsedException e) {
|
} catch (NameAlreadyUsedException e) {
|
||||||
throw die(e);
|
throw die(e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,28 +14,28 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.common.errors.ProjectCreationFailedException;
|
import com.google.gerrit.common.errors.ProjectCreationFailedException;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
|
||||||
import com.google.gerrit.server.project.CreateProject;
|
import com.google.gerrit.server.project.CreateProject;
|
||||||
import com.google.gerrit.server.project.CreateProjectArgs;
|
import com.google.gerrit.server.project.CreateProjectArgs;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gerrit.server.project.SuggestParentCandidates;
|
import com.google.gerrit.server.project.SuggestParentCandidates;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Create a new project. **/
|
/** Create a new project. **/
|
||||||
final class CreateProjectCommand extends BaseCommand {
|
@RequiresCapability(GlobalCapability.CREATE_PROJECT)
|
||||||
|
final class CreateProjectCommand extends SshCommand {
|
||||||
@Option(name = "--name", aliases = {"-n"}, metaVar = "NAME", usage = "name of project to be created (deprecated option)")
|
@Option(name = "--name", aliases = {"-n"}, metaVar = "NAME", usage = "name of project to be created (deprecated option)")
|
||||||
void setProjectNameFromOption(String name) {
|
void setProjectNameFromOption(String name) {
|
||||||
if (projectName != null) {
|
if (projectName != null) {
|
||||||
@@ -95,9 +95,6 @@ final class CreateProjectCommand extends BaseCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
|
||||||
private IdentifiedUser currentUser;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CreateProject.Factory CreateProjectFactory;
|
private CreateProject.Factory CreateProjectFactory;
|
||||||
|
|
||||||
@@ -105,55 +102,39 @@ final class CreateProjectCommand extends BaseCommand {
|
|||||||
private SuggestParentCandidates.Factory suggestParentCandidatesFactory;
|
private SuggestParentCandidates.Factory suggestParentCandidatesFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() throws Exception {
|
||||||
startThread(new CommandRunnable() {
|
try {
|
||||||
@Override
|
if (!suggestParent) {
|
||||||
public void run() throws Exception {
|
if (projectName == null) {
|
||||||
if (!currentUser.getCapabilities().canCreateProject()) {
|
throw new UnloggedFailure(1, "fatal: Project name is required.");
|
||||||
String msg =
|
|
||||||
String.format(
|
|
||||||
"fatal: %s does not have \"Create Project\" capability.",
|
|
||||||
currentUser.getUserName());
|
|
||||||
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
|
||||||
}
|
}
|
||||||
PrintWriter p = toPrintWriter(out);
|
final CreateProjectArgs args = new CreateProjectArgs();
|
||||||
parseCommandLine();
|
args.setProjectName(projectName);
|
||||||
try {
|
args.ownerIds = ownerIds;
|
||||||
if (!suggestParent) {
|
args.newParent = newParent;
|
||||||
if (projectName == null) {
|
args.permissionsOnly = permissionsOnly;
|
||||||
throw new UnloggedFailure(1, "fatal: Project name is required.");
|
args.projectDescription = projectDescription;
|
||||||
}
|
args.submitType = submitType;
|
||||||
final CreateProjectArgs args = new CreateProjectArgs();
|
args.contributorAgreements = contributorAgreements;
|
||||||
args.setProjectName(projectName);
|
args.signedOffBy = signedOffBy;
|
||||||
args.ownerIds = ownerIds;
|
args.contentMerge = contentMerge;
|
||||||
args.newParent = newParent;
|
args.changeIdRequired = requireChangeID;
|
||||||
args.permissionsOnly = permissionsOnly;
|
args.branch = branch;
|
||||||
args.projectDescription = projectDescription;
|
args.createEmptyCommit = createEmptyCommit;
|
||||||
args.submitType = submitType;
|
|
||||||
args.contributorAgreements = contributorAgreements;
|
|
||||||
args.signedOffBy = signedOffBy;
|
|
||||||
args.contentMerge = contentMerge;
|
|
||||||
args.changeIdRequired = requireChangeID;
|
|
||||||
args.branch = branch;
|
|
||||||
args.createEmptyCommit = createEmptyCommit;
|
|
||||||
|
|
||||||
final CreateProject createProject =
|
final CreateProject createProject =
|
||||||
CreateProjectFactory.create(args);
|
CreateProjectFactory.create(args);
|
||||||
createProject.createProject();
|
createProject.createProject();
|
||||||
} else {
|
} else {
|
||||||
List<Project.NameKey> parentCandidates =
|
List<Project.NameKey> parentCandidates =
|
||||||
suggestParentCandidatesFactory.create().getNameKeys();
|
suggestParentCandidatesFactory.create().getNameKeys();
|
||||||
|
|
||||||
for (Project.NameKey parent : parentCandidates) {
|
for (Project.NameKey parent : parentCandidates) {
|
||||||
p.print(parent + "\n");
|
stdout.print(parent + "\n");
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ProjectCreationFailedException err) {
|
|
||||||
throw new UnloggedFailure(1, "fatal: " + err.getMessage(), err);
|
|
||||||
} finally {
|
|
||||||
p.flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
} catch (ProjectCreationFailedException err) {
|
||||||
|
throw new UnloggedFailure(1, "fatal: " + err.getMessage(), err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,21 +14,22 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.BaseCommand;
|
||||||
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import net.sf.ehcache.Ehcache;
|
import net.sf.ehcache.Ehcache;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
|
||||||
/** Causes the caches to purge all entries and reload. */
|
/** Causes the caches to purge all entries and reload. */
|
||||||
|
@RequiresCapability(GlobalCapability.FLUSH_CACHES)
|
||||||
final class FlushCaches extends CacheCommand {
|
final class FlushCaches extends CacheCommand {
|
||||||
private static final String WEB_SESSIONS = "web_sessions";
|
private static final String WEB_SESSIONS = "web_sessions";
|
||||||
|
|
||||||
@@ -44,27 +45,8 @@ final class FlushCaches extends CacheCommand {
|
|||||||
@Inject
|
@Inject
|
||||||
IdentifiedUser currentUser;
|
IdentifiedUser currentUser;
|
||||||
|
|
||||||
private PrintWriter p;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() throws Failure {
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
if (!currentUser.getCapabilities().canFlushCaches()) {
|
|
||||||
String msg = String.format(
|
|
||||||
"fatal: %s does not have \"Flush Caches\" capability.",
|
|
||||||
currentUser.getUserName());
|
|
||||||
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
parseCommandLine();
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void flush() throws Failure {
|
|
||||||
if (caches.contains(WEB_SESSIONS)
|
if (caches.contains(WEB_SESSIONS)
|
||||||
&& !currentUser.getCapabilities().canAdministrateServer()) {
|
&& !currentUser.getCapabilities().canAdministrateServer()) {
|
||||||
String msg = String.format(
|
String msg = String.format(
|
||||||
@@ -73,7 +55,6 @@ final class FlushCaches extends CacheCommand {
|
|||||||
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
p = toPrintWriter(err);
|
|
||||||
if (list) {
|
if (list) {
|
||||||
if (all || caches.size() > 0) {
|
if (all || caches.size() > 0) {
|
||||||
throw error("error: cannot use --list with --all or --cache");
|
throw error("error: cannot use --list with --all or --cache");
|
||||||
@@ -106,10 +87,10 @@ final class FlushCaches extends CacheCommand {
|
|||||||
|
|
||||||
private void doList() {
|
private void doList() {
|
||||||
for (final String name : cacheNames()) {
|
for (final String name : cacheNames()) {
|
||||||
p.print(name);
|
stderr.print(name);
|
||||||
p.print('\n');
|
stderr.print('\n');
|
||||||
}
|
}
|
||||||
p.flush();
|
stderr.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doBulkFlush() {
|
private void doBulkFlush() {
|
||||||
@@ -120,12 +101,12 @@ final class FlushCaches extends CacheCommand {
|
|||||||
try {
|
try {
|
||||||
c.removeAll();
|
c.removeAll();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
p.println("error: cannot flush cache \"" + name + "\": " + e);
|
stderr.println("error: cannot flush cache \"" + name + "\": " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
p.flush();
|
stderr.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,25 +14,24 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.server.git.WorkQueue;
|
import com.google.gerrit.server.git.WorkQueue;
|
||||||
import com.google.gerrit.server.git.WorkQueue.Task;
|
import com.google.gerrit.server.git.WorkQueue.Task;
|
||||||
import com.google.gerrit.server.util.IdGenerator;
|
import com.google.gerrit.server.util.IdGenerator;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.AdminHighPriorityCommand;
|
||||||
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/** Kill a task in the work queue. */
|
/** Kill a task in the work queue. */
|
||||||
final class KillCommand extends BaseCommand {
|
@AdminHighPriorityCommand
|
||||||
@Inject
|
@RequiresCapability(GlobalCapability.KILL_TASK)
|
||||||
private IdentifiedUser currentUser;
|
final class KillCommand extends SshCommand {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private WorkQueue workQueue;
|
private WorkQueue workQueue;
|
||||||
|
|
||||||
@@ -48,33 +47,14 @@ final class KillCommand extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() {
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
if (!currentUser.getCapabilities().canKillTask()) {
|
|
||||||
String msg = String.format(
|
|
||||||
"fatal: %s does not have \"Kill Task\" capability.",
|
|
||||||
currentUser.getUserName());
|
|
||||||
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
parseCommandLine();
|
|
||||||
KillCommand.this.commitMurder();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void commitMurder() {
|
|
||||||
final PrintWriter p = toPrintWriter(err);
|
|
||||||
for (final Integer id : taskIds) {
|
for (final Integer id : taskIds) {
|
||||||
final Task<?> task = workQueue.getTask(id);
|
final Task<?> task = workQueue.getTask(id);
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
task.cancel(true);
|
task.cancel(true);
|
||||||
} else {
|
} else {
|
||||||
p.print("kill: " + IdGenerator.format(id) + ": No such task\n");
|
stderr.print("kill: " + IdGenerator.format(id) + ": No such task\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,20 +22,16 @@ import com.google.gerrit.reviewdb.client.AccountGroup;
|
|||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.account.VisibleGroups;
|
import com.google.gerrit.server.account.VisibleGroups;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ListGroupsCommand extends BaseCommand {
|
public class ListGroupsCommand extends SshCommand {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private VisibleGroups.Factory visibleGroupsFactory;
|
private VisibleGroups.Factory visibleGroupsFactory;
|
||||||
|
|
||||||
@@ -57,18 +53,7 @@ public class ListGroupsCommand extends BaseCommand {
|
|||||||
private Account.Id user;
|
private Account.Id user;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) throws IOException {
|
protected void run() throws Failure {
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
parseCommandLine();
|
|
||||||
ListGroupsCommand.this.display();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void display() throws Failure {
|
|
||||||
final PrintWriter stdout = toPrintWriter(out);
|
|
||||||
try {
|
try {
|
||||||
if (user != null && !projects.isEmpty()) {
|
if (user != null && !projects.isEmpty()) {
|
||||||
throw new UnloggedFailure(1, "fatal: --user and --project options are not compatible.");
|
throw new UnloggedFailure(1, "fatal: --user and --project options are not compatible.");
|
||||||
@@ -92,8 +77,6 @@ public class ListGroupsCommand extends BaseCommand {
|
|||||||
throw die(e);
|
throw die(e);
|
||||||
} catch (NoSuchGroupException e) {
|
} catch (NoSuchGroupException e) {
|
||||||
throw die(e);
|
throw die(e);
|
||||||
} finally {
|
|
||||||
stdout.flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,16 +15,15 @@
|
|||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.server.query.change.QueryProcessor;
|
import com.google.gerrit.server.query.change.QueryProcessor;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class Query extends BaseCommand {
|
class Query extends SshCommand {
|
||||||
@Inject
|
@Inject
|
||||||
private QueryProcessor processor;
|
private QueryProcessor processor;
|
||||||
|
|
||||||
@@ -75,19 +74,14 @@ class Query extends BaseCommand {
|
|||||||
private List<String> query;
|
private List<String> query;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Environment env) {
|
protected void run() throws Exception {
|
||||||
startThread(new CommandRunnable() {
|
processor.query(join(query, " "));
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
processor.setOutput(out, QueryProcessor.OutputFormat.TEXT);
|
|
||||||
parseCommandLine();
|
|
||||||
verifyCommandLine();
|
|
||||||
processor.query(join(query, " "));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyCommandLine() throws UnloggedFailure {
|
@Override
|
||||||
|
protected void parseCommandLine() throws UnloggedFailure {
|
||||||
|
processor.setOutput(out, QueryProcessor.OutputFormat.TEXT);
|
||||||
|
super.parseCommandLine();
|
||||||
if (processor.getIncludeFiles() &&
|
if (processor.getIncludeFiles() &&
|
||||||
!(processor.getIncludePatchSets() || processor.getIncludeCurrentPatchSet())) {
|
!(processor.getIncludePatchSets() || processor.getIncludeCurrentPatchSet())) {
|
||||||
throw new UnloggedFailure(1, "--files option needs --patch-sets or --current-patch-set");
|
throw new UnloggedFailure(1, "--files option needs --patch-sets or --current-patch-set");
|
||||||
|
@@ -17,17 +17,13 @@ package com.google.gerrit.sshd.commands;
|
|||||||
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
||||||
import com.google.gerrit.common.errors.NoSuchGroupException;
|
import com.google.gerrit.common.errors.NoSuchGroupException;
|
||||||
import com.google.gerrit.server.account.PerformRenameGroup;
|
import com.google.gerrit.server.account.PerformRenameGroup;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
|
|
||||||
import java.io.IOException;
|
public class RenameGroupCommand extends SshCommand {
|
||||||
|
|
||||||
public class RenameGroupCommand extends BaseCommand {
|
|
||||||
|
|
||||||
@Argument(index = 0, required = true, metaVar = "GROUP", usage = "name of the group to be renamed")
|
@Argument(index = 0, required = true, metaVar = "GROUP", usage = "name of the group to be renamed")
|
||||||
private String groupName;
|
private String groupName;
|
||||||
|
|
||||||
@@ -38,21 +34,15 @@ public class RenameGroupCommand extends BaseCommand {
|
|||||||
private PerformRenameGroup.Factory performRenameGroupFactory;
|
private PerformRenameGroup.Factory performRenameGroupFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) throws IOException {
|
protected void run() throws Failure {
|
||||||
startThread(new CommandRunnable() {
|
try {
|
||||||
@Override
|
performRenameGroupFactory.create().renameGroup(groupName, newGroupName);
|
||||||
public void run() throws Exception {
|
} catch (OrmException e) {
|
||||||
parseCommandLine();
|
throw die(e);
|
||||||
try {
|
} catch (NameAlreadyUsedException e) {
|
||||||
performRenameGroupFactory.create().renameGroup(groupName, newGroupName);
|
throw die(e);
|
||||||
} catch (OrmException e) {
|
} catch (NoSuchGroupException e) {
|
||||||
throw die(e);
|
throw die(e);
|
||||||
} catch (NameAlreadyUsedException e) {
|
}
|
||||||
throw die(e);
|
|
||||||
} catch (NoSuchGroupException e) {
|
|
||||||
throw die(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,15 +14,16 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.git.PushAllProjectsOp;
|
import com.google.gerrit.server.git.PushAllProjectsOp;
|
||||||
import com.google.gerrit.server.git.ReplicationQueue;
|
import com.google.gerrit.server.git.ReplicationQueue;
|
||||||
import com.google.gerrit.server.project.ProjectCache;
|
import com.google.gerrit.server.project.ProjectCache;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
@@ -31,7 +32,8 @@ import java.util.List;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/** Force a project to replicate, again. */
|
/** Force a project to replicate, again. */
|
||||||
final class Replicate extends BaseCommand {
|
@RequiresCapability(GlobalCapability.START_REPLICATION)
|
||||||
|
final class Replicate extends SshCommand {
|
||||||
@Option(name = "--all", usage = "push all known projects")
|
@Option(name = "--all", usage = "push all known projects")
|
||||||
private boolean all;
|
private boolean all;
|
||||||
|
|
||||||
@@ -54,24 +56,7 @@ final class Replicate extends BaseCommand {
|
|||||||
private ProjectCache projectCache;
|
private ProjectCache projectCache;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() throws Failure {
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
if (!currentUser.getCapabilities().canStartReplication()) {
|
|
||||||
String msg = String.format(
|
|
||||||
"fatal: %s does not have \"Start Replication\" capability.",
|
|
||||||
currentUser.getUserName());
|
|
||||||
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
parseCommandLine();
|
|
||||||
Replicate.this.schedule();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void schedule() throws Failure {
|
|
||||||
if (all && projectNames.size() > 0) {
|
if (all && projectNames.size() > 0) {
|
||||||
throw new UnloggedFailure(1, "error: cannot combine --all and PROJECT");
|
throw new UnloggedFailure(1, "error: cannot combine --all and PROJECT");
|
||||||
}
|
}
|
||||||
|
@@ -33,13 +33,12 @@ import com.google.gerrit.server.patch.PublishComments;
|
|||||||
import com.google.gerrit.server.project.InvalidChangeOperationException;
|
import com.google.gerrit.server.project.InvalidChangeOperationException;
|
||||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.gerrit.util.cli.CmdLineParser;
|
import com.google.gerrit.util.cli.CmdLineParser;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.gwtorm.server.ResultSet;
|
import com.google.gwtorm.server.ResultSet;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -52,7 +51,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ReviewCommand extends BaseCommand {
|
public class ReviewCommand extends SshCommand {
|
||||||
private static final Logger log =
|
private static final Logger log =
|
||||||
LoggerFactory.getLogger(ReviewCommand.class);
|
LoggerFactory.getLogger(ReviewCommand.class);
|
||||||
|
|
||||||
@@ -130,63 +129,55 @@ public class ReviewCommand extends BaseCommand {
|
|||||||
private List<ApproveOption> optionList;
|
private List<ApproveOption> optionList;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void start(final Environment env) {
|
protected void run() throws UnloggedFailure {
|
||||||
startThread(new CommandRunnable() {
|
if (abandonChange) {
|
||||||
@Override
|
if (restoreChange) {
|
||||||
public void run() throws Failure {
|
throw error("abandon and restore actions are mutually exclusive");
|
||||||
initOptionList();
|
|
||||||
parseCommandLine();
|
|
||||||
if (abandonChange) {
|
|
||||||
if (restoreChange) {
|
|
||||||
throw error("abandon and restore actions are mutually exclusive");
|
|
||||||
}
|
|
||||||
if (submitChange) {
|
|
||||||
throw error("abandon and submit actions are mutually exclusive");
|
|
||||||
}
|
|
||||||
if (publishPatchSet) {
|
|
||||||
throw error("abandon and publish actions are mutually exclusive");
|
|
||||||
}
|
|
||||||
if (deleteDraftPatchSet) {
|
|
||||||
throw error("abandon and delete actions are mutually exclusive");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (publishPatchSet) {
|
|
||||||
if (restoreChange) {
|
|
||||||
throw error("publish and restore actions are mutually exclusive");
|
|
||||||
}
|
|
||||||
if (submitChange) {
|
|
||||||
throw error("publish and submit actions are mutually exclusive");
|
|
||||||
}
|
|
||||||
if (deleteDraftPatchSet) {
|
|
||||||
throw error("publish and delete actions are mutually exclusive");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean ok = true;
|
|
||||||
for (final PatchSet.Id patchSetId : patchSetIds) {
|
|
||||||
try {
|
|
||||||
approveOne(patchSetId);
|
|
||||||
} catch (UnloggedFailure e) {
|
|
||||||
ok = false;
|
|
||||||
writeError("error: " + e.getMessage() + "\n");
|
|
||||||
} catch (NoSuchChangeException e) {
|
|
||||||
ok = false;
|
|
||||||
writeError("no such change " + patchSetId.getParentKey().get());
|
|
||||||
} catch (Exception e) {
|
|
||||||
ok = false;
|
|
||||||
writeError("fatal: internal server error while approving "
|
|
||||||
+ patchSetId + "\n");
|
|
||||||
log.error("internal error while approving " + patchSetId, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
throw new UnloggedFailure(1, "one or more approvals failed;"
|
|
||||||
+ " review output above");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
if (submitChange) {
|
||||||
|
throw error("abandon and submit actions are mutually exclusive");
|
||||||
|
}
|
||||||
|
if (publishPatchSet) {
|
||||||
|
throw error("abandon and publish actions are mutually exclusive");
|
||||||
|
}
|
||||||
|
if (deleteDraftPatchSet) {
|
||||||
|
throw error("abandon and delete actions are mutually exclusive");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (publishPatchSet) {
|
||||||
|
if (restoreChange) {
|
||||||
|
throw error("publish and restore actions are mutually exclusive");
|
||||||
|
}
|
||||||
|
if (submitChange) {
|
||||||
|
throw error("publish and submit actions are mutually exclusive");
|
||||||
|
}
|
||||||
|
if (deleteDraftPatchSet) {
|
||||||
|
throw error("publish and delete actions are mutually exclusive");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean ok = true;
|
||||||
|
for (final PatchSet.Id patchSetId : patchSetIds) {
|
||||||
|
try {
|
||||||
|
approveOne(patchSetId);
|
||||||
|
} catch (UnloggedFailure e) {
|
||||||
|
ok = false;
|
||||||
|
writeError("error: " + e.getMessage() + "\n");
|
||||||
|
} catch (NoSuchChangeException e) {
|
||||||
|
ok = false;
|
||||||
|
writeError("no such change " + patchSetId.getParentKey().get());
|
||||||
|
} catch (Exception e) {
|
||||||
|
ok = false;
|
||||||
|
writeError("fatal: internal server error while approving "
|
||||||
|
+ patchSetId + "\n");
|
||||||
|
log.error("internal error while approving " + patchSetId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
throw new UnloggedFailure(1, "one or more approvals failed;"
|
||||||
|
+ " review output above");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void approveOne(final PatchSet.Id patchSetId) throws
|
private void approveOne(final PatchSet.Id patchSetId) throws
|
||||||
@@ -344,7 +335,8 @@ public class ReviewCommand extends BaseCommand {
|
|||||||
return projectControl.getProject().getNameKey().equals(change.getProject());
|
return projectControl.getProject().getNameKey().equals(change.getProject());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initOptionList() {
|
@Override
|
||||||
|
protected void parseCommandLine() throws UnloggedFailure {
|
||||||
optionList = new ArrayList<ApproveOption>();
|
optionList = new ArrayList<ApproveOption>();
|
||||||
|
|
||||||
for (ApprovalType type : approvalTypes.getApprovalTypes()) {
|
for (ApprovalType type : approvalTypes.getApprovalTypes()) {
|
||||||
@@ -360,6 +352,8 @@ public class ReviewCommand extends BaseCommand {
|
|||||||
"--" + category.getName().toLowerCase().replace(' ', '-');
|
"--" + category.getName().toLowerCase().replace(' ', '-');
|
||||||
optionList.add(new ApproveOption(name, usage, type));
|
optionList.add(new ApproveOption(name, usage, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.parseCommandLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeError(final String msg) {
|
private void writeError(final String msg) {
|
||||||
|
@@ -25,12 +25,11 @@ import com.google.gerrit.server.patch.RemoveReviewer;
|
|||||||
import com.google.gerrit.server.project.ChangeControl;
|
import com.google.gerrit.server.project.ChangeControl;
|
||||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.gwtorm.server.ResultSet;
|
import com.google.gwtorm.server.ResultSet;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -43,7 +42,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class SetReviewersCommand extends BaseCommand {
|
public class SetReviewersCommand extends SshCommand {
|
||||||
private static final Logger log =
|
private static final Logger log =
|
||||||
LoggerFactory.getLogger(SetReviewersCommand.class);
|
LoggerFactory.getLogger(SetReviewersCommand.class);
|
||||||
|
|
||||||
@@ -85,28 +84,21 @@ public class SetReviewersCommand extends BaseCommand {
|
|||||||
private Set<Change.Id> changes = new HashSet<Change.Id>();
|
private Set<Change.Id> changes = new HashSet<Change.Id>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void start(final Environment env) {
|
protected void run() throws UnloggedFailure {
|
||||||
startThread(new CommandRunnable() {
|
boolean ok = true;
|
||||||
@Override
|
for (Change.Id changeId : changes) {
|
||||||
public void run() throws Failure {
|
try {
|
||||||
parseCommandLine();
|
ok &= modifyOne(changeId);
|
||||||
|
} catch (Exception err) {
|
||||||
boolean ok = true;
|
ok = false;
|
||||||
for (Change.Id changeId : changes) {
|
log.error("Error updating reviewers on change " + changeId, err);
|
||||||
try {
|
writeError("fatal", "internal error while updating " + changeId);
|
||||||
ok &= modifyOne(changeId);
|
|
||||||
} catch (Exception err) {
|
|
||||||
ok = false;
|
|
||||||
log.error("Error updating reviewers on change " + changeId, err);
|
|
||||||
writeError("fatal", "internal error while updating " + changeId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
throw error("fatal: one or more updates failed; review output above");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
throw error("fatal: one or more updates failed; review output above");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean modifyOne(Change.Id changeId) throws Exception {
|
private boolean modifyOne(Change.Id changeId) throws Exception {
|
||||||
|
@@ -15,12 +15,12 @@
|
|||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.common.Version;
|
import com.google.gerrit.common.Version;
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.lifecycle.LifecycleListener;
|
import com.google.gerrit.lifecycle.LifecycleListener;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
|
||||||
import com.google.gerrit.server.config.SitePath;
|
import com.google.gerrit.server.config.SitePath;
|
||||||
import com.google.gerrit.server.git.WorkQueue;
|
import com.google.gerrit.server.git.WorkQueue;
|
||||||
import com.google.gerrit.server.git.WorkQueue.Task;
|
import com.google.gerrit.server.git.WorkQueue.Task;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
import com.google.gerrit.sshd.SshDaemon;
|
import com.google.gerrit.sshd.SshDaemon;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
@@ -30,13 +30,11 @@ import net.sf.ehcache.config.CacheConfiguration;
|
|||||||
|
|
||||||
import org.apache.mina.core.service.IoAcceptor;
|
import org.apache.mina.core.service.IoAcceptor;
|
||||||
import org.apache.mina.core.session.IoSession;
|
import org.apache.mina.core.session.IoSession;
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.eclipse.jgit.storage.file.WindowCacheStatAccessor;
|
import org.eclipse.jgit.storage.file.WindowCacheStatAccessor;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.management.OperatingSystemMXBean;
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
import java.lang.management.RuntimeMXBean;
|
import java.lang.management.RuntimeMXBean;
|
||||||
@@ -47,6 +45,7 @@ import java.util.Collection;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/** Show the current cache states. */
|
/** Show the current cache states. */
|
||||||
|
@RequiresCapability(GlobalCapability.VIEW_CACHES)
|
||||||
final class ShowCaches extends CacheCommand {
|
final class ShowCaches extends CacheCommand {
|
||||||
private static volatile long serverStarted;
|
private static volatile long serverStarted;
|
||||||
|
|
||||||
@@ -67,9 +66,6 @@ final class ShowCaches extends CacheCommand {
|
|||||||
@Option(name = "--show-jvm", usage = "show details about the JVM")
|
@Option(name = "--show-jvm", usage = "show details about the JVM")
|
||||||
private boolean showJVM;
|
private boolean showJVM;
|
||||||
|
|
||||||
@Inject
|
|
||||||
private IdentifiedUser currentUser;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private WorkQueue workQueue;
|
private WorkQueue workQueue;
|
||||||
|
|
||||||
@@ -80,42 +76,21 @@ final class ShowCaches extends CacheCommand {
|
|||||||
@SitePath
|
@SitePath
|
||||||
private File sitePath;
|
private File sitePath;
|
||||||
|
|
||||||
private PrintWriter p;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() {
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
if (!currentUser.getCapabilities().canViewCaches()) {
|
|
||||||
String msg = String.format(
|
|
||||||
"fatal: %s does not have \"View Caches\" capability.",
|
|
||||||
currentUser.getUserName());
|
|
||||||
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
parseCommandLine();
|
|
||||||
display();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void display() {
|
|
||||||
p = toPrintWriter(out);
|
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
p.format(
|
stdout.format(
|
||||||
"%-25s %-20s now %16s\n",
|
"%-25s %-20s now %16s\n",
|
||||||
"Gerrit Code Review",
|
"Gerrit Code Review",
|
||||||
Version.getVersion() != null ? Version.getVersion() : "",
|
Version.getVersion() != null ? Version.getVersion() : "",
|
||||||
new SimpleDateFormat("HH:mm:ss zzz").format(now));
|
new SimpleDateFormat("HH:mm:ss zzz").format(now));
|
||||||
p.format(
|
stdout.format(
|
||||||
"%-25s %-20s uptime %16s\n",
|
"%-25s %-20s uptime %16s\n",
|
||||||
"", "",
|
"", "",
|
||||||
uptime(now.getTime() - serverStarted));
|
uptime(now.getTime() - serverStarted));
|
||||||
p.print('\n');
|
stdout.print('\n');
|
||||||
|
|
||||||
p.print(String.format(//
|
stdout.print(String.format(//
|
||||||
"%1s %-18s %-4s|%-20s| %-5s |%-14s|\n" //
|
"%1s %-18s %-4s|%-20s| %-5s |%-14s|\n" //
|
||||||
, "" //
|
, "" //
|
||||||
, "Name" //
|
, "Name" //
|
||||||
@@ -124,7 +99,7 @@ final class ShowCaches extends CacheCommand {
|
|||||||
, "AvgGet" //
|
, "AvgGet" //
|
||||||
, "Hit Ratio" //
|
, "Hit Ratio" //
|
||||||
));
|
));
|
||||||
p.print(String.format(//
|
stdout.print(String.format(//
|
||||||
"%1s %-18s %-4s|%6s %6s %6s| %-5s |%-4s %-4s %-4s|\n" //
|
"%1s %-18s %-4s|%6s %6s %6s| %-5s |%-4s %-4s %-4s|\n" //
|
||||||
, "" //
|
, "" //
|
||||||
, "" //
|
, "" //
|
||||||
@@ -137,7 +112,7 @@ final class ShowCaches extends CacheCommand {
|
|||||||
, "Mem" //
|
, "Mem" //
|
||||||
, "Agg" //
|
, "Agg" //
|
||||||
));
|
));
|
||||||
p.print("------------------"
|
stdout.print("------------------"
|
||||||
+ "-------+--------------------+----------+--------------+\n");
|
+ "-------+--------------------+----------+--------------+\n");
|
||||||
for (final Ehcache cache : getAllCaches()) {
|
for (final Ehcache cache : getAllCaches()) {
|
||||||
final CacheConfiguration cfg = cache.getCacheConfiguration();
|
final CacheConfiguration cfg = cache.getCacheConfiguration();
|
||||||
@@ -146,7 +121,7 @@ final class ShowCaches extends CacheCommand {
|
|||||||
final long total = stat.getCacheHits() + stat.getCacheMisses();
|
final long total = stat.getCacheHits() + stat.getCacheMisses();
|
||||||
|
|
||||||
if (useDisk) {
|
if (useDisk) {
|
||||||
p.print(String.format(//
|
stdout.print(String.format(//
|
||||||
"D %-18s %-4s|%6s %6s %6s| %7s |%4s %4s %4s|\n" //
|
"D %-18s %-4s|%6s %6s %6s| %7s |%4s %4s %4s|\n" //
|
||||||
, cache.getName() //
|
, cache.getName() //
|
||||||
, interval(cfg.getTimeToLiveSeconds()) //
|
, interval(cfg.getTimeToLiveSeconds()) //
|
||||||
@@ -159,7 +134,7 @@ final class ShowCaches extends CacheCommand {
|
|||||||
, percent(stat.getCacheHits(), total) //
|
, percent(stat.getCacheHits(), total) //
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
p.print(String.format(//
|
stdout.print(String.format(//
|
||||||
" %-18s %-4s|%6s %6s %6s| %7s |%4s %4s %4s|\n" //
|
" %-18s %-4s|%6s %6s %6s| %7s |%4s %4s %4s|\n" //
|
||||||
, cache.getName() //
|
, cache.getName() //
|
||||||
, interval(cfg.getTimeToLiveSeconds()) //
|
, interval(cfg.getTimeToLiveSeconds()) //
|
||||||
@@ -171,7 +146,7 @@ final class ShowCaches extends CacheCommand {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.print('\n');
|
stdout.print('\n');
|
||||||
|
|
||||||
if (gc) {
|
if (gc) {
|
||||||
System.gc();
|
System.gc();
|
||||||
@@ -187,7 +162,7 @@ final class ShowCaches extends CacheCommand {
|
|||||||
jvmSummary();
|
jvmSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
p.flush();
|
stdout.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void memSummary() {
|
private void memSummary() {
|
||||||
@@ -200,17 +175,17 @@ final class ShowCaches extends CacheCommand {
|
|||||||
final int jgitOpen = WindowCacheStatAccessor.getOpenFiles();
|
final int jgitOpen = WindowCacheStatAccessor.getOpenFiles();
|
||||||
final long jgitBytes = WindowCacheStatAccessor.getOpenBytes();
|
final long jgitBytes = WindowCacheStatAccessor.getOpenBytes();
|
||||||
|
|
||||||
p.format("Mem: %s total = %s used + %s free + %s buffers\n",
|
stdout.format("Mem: %s total = %s used + %s free + %s buffers\n",
|
||||||
bytes(mTotal),
|
bytes(mTotal),
|
||||||
bytes(mInuse - jgitBytes),
|
bytes(mInuse - jgitBytes),
|
||||||
bytes(mFree),
|
bytes(mFree),
|
||||||
bytes(jgitBytes));
|
bytes(jgitBytes));
|
||||||
p.format(" %s max\n", bytes(mMax));
|
stdout.format(" %s max\n", bytes(mMax));
|
||||||
p.format(" %8d open files, %8d cpus available, %8d threads\n",
|
stdout.format(" %8d open files, %8d cpus available, %8d threads\n",
|
||||||
jgitOpen,
|
jgitOpen,
|
||||||
r.availableProcessors(),
|
r.availableProcessors(),
|
||||||
ManagementFactory.getThreadMXBean().getThreadCount());
|
ManagementFactory.getThreadMXBean().getThreadCount());
|
||||||
p.print('\n');
|
stdout.print('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
private void taskSummary() {
|
private void taskSummary() {
|
||||||
@@ -224,7 +199,7 @@ final class ShowCaches extends CacheCommand {
|
|||||||
case SLEEPING: tasksSleeping++; break;
|
case SLEEPING: tasksSleeping++; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.format(
|
stdout.format(
|
||||||
"Tasks: %4d total = %4d running + %4d ready + %4d sleeping\n",
|
"Tasks: %4d total = %4d running + %4d ready + %4d sleeping\n",
|
||||||
tasksTotal,
|
tasksTotal,
|
||||||
tasksRunning,
|
tasksRunning,
|
||||||
@@ -245,7 +220,7 @@ final class ShowCaches extends CacheCommand {
|
|||||||
oldest = Math.min(oldest, s.getCreationTime());
|
oldest = Math.min(oldest, s.getCreationTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
p.format(
|
stdout.format(
|
||||||
"SSH: %4d users, oldest session started %s ago\n",
|
"SSH: %4d users, oldest session started %s ago\n",
|
||||||
list.size(),
|
list.size(),
|
||||||
uptime(now - oldest));
|
uptime(now - oldest));
|
||||||
@@ -254,22 +229,22 @@ final class ShowCaches extends CacheCommand {
|
|||||||
private void jvmSummary() {
|
private void jvmSummary() {
|
||||||
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
|
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
|
||||||
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
||||||
p.format("JVM: %s %s %s\n",
|
stdout.format("JVM: %s %s %s\n",
|
||||||
runtimeBean.getVmVendor(),
|
runtimeBean.getVmVendor(),
|
||||||
runtimeBean.getVmName(),
|
runtimeBean.getVmName(),
|
||||||
runtimeBean.getVmVersion());
|
runtimeBean.getVmVersion());
|
||||||
p.format(" on %s %s %s\n", "",
|
stdout.format(" on %s %s %s\n", "",
|
||||||
osBean.getName(),
|
osBean.getName(),
|
||||||
osBean.getVersion(),
|
osBean.getVersion(),
|
||||||
osBean.getArch());
|
osBean.getArch());
|
||||||
try {
|
try {
|
||||||
p.format(" running as %s on %s\n",
|
stdout.format(" running as %s on %s\n",
|
||||||
System.getProperty("user.name"),
|
System.getProperty("user.name"),
|
||||||
InetAddress.getLocalHost().getHostName());
|
InetAddress.getLocalHost().getHostName());
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
}
|
}
|
||||||
p.format(" cwd %s\n", path(new File(".").getAbsoluteFile().getParentFile()));
|
stdout.format(" cwd %s\n", path(new File(".").getAbsoluteFile().getParentFile()));
|
||||||
p.format(" site %s\n", path(sitePath));
|
stdout.format(" site %s\n", path(sitePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String path(File file) {
|
private String path(File file) {
|
||||||
|
@@ -14,21 +14,21 @@
|
|||||||
|
|
||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.util.IdGenerator;
|
import com.google.gerrit.server.util.IdGenerator;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.RequiresCapability;
|
||||||
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.gerrit.sshd.SshDaemon;
|
import com.google.gerrit.sshd.SshDaemon;
|
||||||
import com.google.gerrit.sshd.SshSession;
|
import com.google.gerrit.sshd.SshSession;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.mina.core.service.IoAcceptor;
|
import org.apache.mina.core.service.IoAcceptor;
|
||||||
import org.apache.mina.core.session.IoSession;
|
import org.apache.mina.core.session.IoSession;
|
||||||
import org.apache.sshd.server.Environment;
|
|
||||||
import org.apache.sshd.server.session.ServerSession;
|
import org.apache.sshd.server.session.ServerSession;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
@@ -40,39 +40,16 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Show the current SSH connections. */
|
/** Show the current SSH connections. */
|
||||||
final class ShowConnections extends BaseCommand {
|
@RequiresCapability(GlobalCapability.VIEW_CONNECTIONS)
|
||||||
|
final class ShowConnections extends SshCommand {
|
||||||
@Option(name = "--numeric", aliases = {"-n"}, usage = "don't resolve names")
|
@Option(name = "--numeric", aliases = {"-n"}, usage = "don't resolve names")
|
||||||
private boolean numeric;
|
private boolean numeric;
|
||||||
|
|
||||||
private PrintWriter p;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
IdentifiedUser currentUser;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SshDaemon daemon;
|
private SshDaemon daemon;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() throws Failure {
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
if (!currentUser.getCapabilities().canViewConnections()) {
|
|
||||||
String msg = String.format(
|
|
||||||
"fatal: %s does not have \"View Connections\" capability.",
|
|
||||||
currentUser.getUserName());
|
|
||||||
throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
parseCommandLine();
|
|
||||||
ShowConnections.this.display();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void display() throws Failure {
|
|
||||||
p = toPrintWriter(out);
|
|
||||||
|
|
||||||
final IoAcceptor acceptor = daemon.getIoAcceptor();
|
final IoAcceptor acceptor = daemon.getIoAcceptor();
|
||||||
if (acceptor == null) {
|
if (acceptor == null) {
|
||||||
throw new Failure(1, "fatal: sshd no longer running");
|
throw new Failure(1, "fatal: sshd no longer running");
|
||||||
@@ -93,9 +70,9 @@ final class ShowConnections extends BaseCommand {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
p.print(String.format("%-8s %8s %8s %-15s %s\n", //
|
stdout.print(String.format("%-8s %8s %8s %-15s %s\n", //
|
||||||
"Session", "Start", "Idle", "User", "Remote Host"));
|
"Session", "Start", "Idle", "User", "Remote Host"));
|
||||||
p.print("--------------------------------------------------------------\n");
|
stdout.print("--------------------------------------------------------------\n");
|
||||||
for (final IoSession io : list) {
|
for (final IoSession io : list) {
|
||||||
ServerSession s = (ServerSession) ServerSession.getSession(io, true);
|
ServerSession s = (ServerSession) ServerSession.getSession(io, true);
|
||||||
SshSession sd = s != null ? s.getAttribute(SshSession.KEY) : null;
|
SshSession sd = s != null ? s.getAttribute(SshSession.KEY) : null;
|
||||||
@@ -104,16 +81,14 @@ final class ShowConnections extends BaseCommand {
|
|||||||
final long start = io.getCreationTime();
|
final long start = io.getCreationTime();
|
||||||
final long idle = now - io.getLastIoTime();
|
final long idle = now - io.getLastIoTime();
|
||||||
|
|
||||||
p.print(String.format("%8s %8s %8s %-15.15s %.30s\n", //
|
stdout.print(String.format("%8s %8s %8s %-15.15s %.30s\n", //
|
||||||
id(sd), //
|
id(sd), //
|
||||||
time(now, start), //
|
time(now, start), //
|
||||||
age(idle), //
|
age(idle), //
|
||||||
username(sd), //
|
username(sd), //
|
||||||
hostname(remoteAddress)));
|
hostname(remoteAddress)));
|
||||||
}
|
}
|
||||||
p.print("--\n");
|
stdout.print("--\n");
|
||||||
|
|
||||||
p.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String id(final SshSession sd) {
|
private static String id(final SshSession sd) {
|
||||||
|
@@ -23,13 +23,13 @@ import com.google.gerrit.server.project.ProjectCache;
|
|||||||
import com.google.gerrit.server.project.ProjectState;
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
import com.google.gerrit.server.util.IdGenerator;
|
import com.google.gerrit.server.util.IdGenerator;
|
||||||
import com.google.gerrit.sshd.AdminHighPriorityCommand;
|
import com.google.gerrit.sshd.AdminHighPriorityCommand;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
import org.apache.sshd.server.Environment;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@@ -39,7 +39,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
/** Display the current work queue. */
|
/** Display the current work queue. */
|
||||||
@AdminHighPriorityCommand
|
@AdminHighPriorityCommand
|
||||||
final class ShowQueue extends BaseCommand {
|
final class ShowQueue extends SshCommand {
|
||||||
@Option(name = "-w", usage = "display without line width truncation")
|
@Option(name = "-w", usage = "display without line width truncation")
|
||||||
private boolean wide;
|
private boolean wide;
|
||||||
|
|
||||||
@@ -52,12 +52,11 @@ final class ShowQueue extends BaseCommand {
|
|||||||
@Inject
|
@Inject
|
||||||
private IdentifiedUser currentUser;
|
private IdentifiedUser currentUser;
|
||||||
|
|
||||||
private PrintWriter p;
|
|
||||||
private int columns = 80;
|
private int columns = 80;
|
||||||
private int taskNameWidth;
|
private int taskNameWidth;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
public void start(final Environment env) throws IOException {
|
||||||
String s = env.getEnv().get(Environment.ENV_COLUMNS);
|
String s = env.getEnv().get(Environment.ENV_COLUMNS);
|
||||||
if (s != null && !s.isEmpty()) {
|
if (s != null && !s.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
@@ -66,19 +65,11 @@ final class ShowQueue extends BaseCommand {
|
|||||||
columns = 80;
|
columns = 80;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
super.start(env);
|
||||||
startThread(new CommandRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run() throws Exception {
|
|
||||||
parseCommandLine();
|
|
||||||
ShowQueue.this.display();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void display() {
|
@Override
|
||||||
p = toPrintWriter(out);
|
protected void run() {
|
||||||
|
|
||||||
final List<Task<?>> pending = workQueue.getTasks();
|
final List<Task<?>> pending = workQueue.getTasks();
|
||||||
Collections.sort(pending, new Comparator<Task<?>>() {
|
Collections.sort(pending, new Comparator<Task<?>>() {
|
||||||
public int compare(Task<?> a, Task<?> b) {
|
public int compare(Task<?> a, Task<?> b) {
|
||||||
@@ -103,9 +94,9 @@ final class ShowQueue extends BaseCommand {
|
|||||||
|
|
||||||
taskNameWidth = wide ? Integer.MAX_VALUE : columns - 8 - 12 - 8 - 4;
|
taskNameWidth = wide ? Integer.MAX_VALUE : columns - 8 - 12 - 8 - 4;
|
||||||
|
|
||||||
p.print(String.format("%-8s %-12s %-8s %s\n", //
|
stdout.print(String.format("%-8s %-12s %-8s %s\n", //
|
||||||
"Task", "State", "", "Command"));
|
"Task", "State", "", "Command"));
|
||||||
p.print("----------------------------------------------"
|
stdout.print("----------------------------------------------"
|
||||||
+ "--------------------------------\n");
|
+ "--------------------------------\n");
|
||||||
|
|
||||||
int numberOfPendingTasks = 0;
|
int numberOfPendingTasks = 0;
|
||||||
@@ -158,7 +149,7 @@ final class ShowQueue extends BaseCommand {
|
|||||||
|
|
||||||
// Shows information about tasks depending on the user rights
|
// Shows information about tasks depending on the user rights
|
||||||
if (viewAll || (!hasCustomizedPrint && regularUserCanSee)) {
|
if (viewAll || (!hasCustomizedPrint && regularUserCanSee)) {
|
||||||
p.print(String.format("%8s %-12s %-8s %s\n", //
|
stdout.print(String.format("%8s %-12s %-8s %s\n", //
|
||||||
id(task.getTaskId()), start, "", format(task)));
|
id(task.getTaskId()), start, "", format(task)));
|
||||||
} else if (regularUserCanSee) {
|
} else if (regularUserCanSee) {
|
||||||
if (remoteName == null) {
|
if (remoteName == null) {
|
||||||
@@ -167,20 +158,18 @@ final class ShowQueue extends BaseCommand {
|
|||||||
remoteName = remoteName + "/" + projectName;
|
remoteName = remoteName + "/" + projectName;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.print(String.format("%8s %-12s %-8s %s\n", //
|
stdout.print(String.format("%8s %-12s %-8s %s\n", //
|
||||||
id(task.getTaskId()), start, "", remoteName));
|
id(task.getTaskId()), start, "", remoteName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.print("----------------------------------------------"
|
stdout.print("----------------------------------------------"
|
||||||
+ "--------------------------------\n");
|
+ "--------------------------------\n");
|
||||||
|
|
||||||
if (viewAll) {
|
if (viewAll) {
|
||||||
numberOfPendingTasks = pending.size();
|
numberOfPendingTasks = pending.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
p.print(" " + numberOfPendingTasks + " tasks\n");
|
stdout.print(" " + numberOfPendingTasks + " tasks\n");
|
||||||
|
|
||||||
p.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String id(final int id) {
|
private static String id(final int id) {
|
||||||
|
@@ -15,29 +15,16 @@
|
|||||||
package com.google.gerrit.sshd.commands;
|
package com.google.gerrit.sshd.commands;
|
||||||
|
|
||||||
import com.google.gerrit.common.Version;
|
import com.google.gerrit.common.Version;
|
||||||
import com.google.gerrit.sshd.BaseCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
|
|
||||||
import org.apache.sshd.server.Environment;
|
final class VersionCommand extends SshCommand {
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
|
|
||||||
final class VersionCommand extends BaseCommand {
|
|
||||||
@Override
|
@Override
|
||||||
public void start(final Environment env) {
|
protected void run() throws Failure {
|
||||||
startThread(new CommandRunnable() {
|
String v = Version.getVersion();
|
||||||
@Override
|
if (v == null) {
|
||||||
public void run() throws Failure {
|
throw new Failure(1, "fatal: version unavailable");
|
||||||
parseCommandLine();
|
}
|
||||||
|
|
||||||
String v = Version.getVersion();
|
stdout.println("gerrit version " + v);
|
||||||
if (v == null) {
|
|
||||||
throw new Failure(1, "fatal: version unavailable");
|
|
||||||
}
|
|
||||||
|
|
||||||
final PrintWriter stdout = toPrintWriter(out);
|
|
||||||
stdout.println("gerrit version " + v);
|
|
||||||
stdout.flush();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user