diff --git a/gerrit-server/pom.xml b/gerrit-server/pom.xml index b0c2125dd0..674d3b64c8 100644 --- a/gerrit-server/pom.xml +++ b/gerrit-server/pom.xml @@ -121,6 +121,12 @@ limitations under the License. ${project.version} + + com.google.gerrit + gerrit-util-cli + ${project.version} + + com.google.gerrit gerrit-util-ssl diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java index 90a0890d94..99dd54a6a9 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java @@ -57,6 +57,7 @@ import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.PermissionCollection; import com.google.gerrit.server.project.ProjectCacheImpl; import com.google.gerrit.server.project.ProjectControl; +import com.google.gerrit.server.project.ProjectNode; import com.google.gerrit.server.project.ProjectState; import com.google.gerrit.server.project.SectionSortCache; import com.google.gerrit.server.tools.ToolsCatalog; @@ -118,6 +119,7 @@ public class GerritGlobalModule extends FactoryModule { factory(AccountInfoCacheFactory.Factory.class); factory(CapabilityControl.Factory.class); factory(GroupInfoCacheFactory.Factory.class); + factory(ProjectNode.Factory.class); factory(ProjectState.Factory.class); factory(MaterializedGroupMembership.Factory.class); bind(PermissionCollection.Factory.class); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java index 00562b0bd5..71bcc6cce7 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java @@ -53,6 +53,7 @@ import com.google.gerrit.server.patch.PublishComments; import com.google.gerrit.server.patch.RemoveReviewer; import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.CreateProject; +import com.google.gerrit.server.project.ListProjects; import com.google.gerrit.server.project.PerRequestProjectControlCache; import com.google.gerrit.server.project.ProjectControl; import com.google.gerrit.server.project.SuggestParentCandidates; @@ -71,6 +72,7 @@ public class GerritRequestModule extends FactoryModule { bind(MetaDataUpdate.User.class).in(RequestScoped.class); bind(AccountResolver.class); bind(ChangeQueryRewriter.class); + bind(ListProjects.class); bind(AnonymousUser.class).in(RequestScoped.class); bind(PerRequestProjectControlCache.class).in(RequestScoped.class); diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java similarity index 80% rename from gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java rename to gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java index 3eb9f52695..95a8b775e1 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java @@ -12,18 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.gerrit.sshd.commands; +package com.google.gerrit.server.project; import com.google.gerrit.reviewdb.client.Project; -import com.google.gerrit.server.IdentifiedUser; +import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.git.GitRepositoryManager; -import com.google.gerrit.server.project.ProjectCache; -import com.google.gerrit.server.project.ProjectControl; -import com.google.gerrit.server.project.ProjectState; -import com.google.gerrit.sshd.BaseCommand; +import com.google.gerrit.server.util.TreeFormatter; import com.google.inject.Inject; -import org.apache.sshd.server.Environment; import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; @@ -32,18 +28,23 @@ import org.kohsuke.args4j.Option; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.BufferedWriter; import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.List; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; -final class ListProjects extends BaseCommand { +/** List projects visible to the calling user. */ +public class ListProjects { private static final Logger log = LoggerFactory.getLogger(ListProjects.class); - static enum FilterType { + public static enum FilterType { CODE { @Override boolean matches(Repository git) throws IOException { @@ -69,24 +70,18 @@ final class ListProjects extends BaseCommand { abstract boolean matches(Repository git) throws IOException; } - @Inject - private IdentifiedUser currentUser; - - @Inject - private ProjectCache projectCache; - - @Inject - private GitRepositoryManager repoManager; - - @Inject - private ProjectNode.Factory projectNodeFactory; + private final CurrentUser currentUser; + private final ProjectCache projectCache; + private final GitRepositoryManager repoManager; + private final ProjectNode.Factory projectNodeFactory; @Option(name = "--show-branch", aliases = {"-b"}, multiValued = true, usage = "displays the sha of each project in the specified branch") private List showBranch; - @Option(name = "--tree", aliases = {"-t"}, usage = "displays project inheritance in a tree-like format\n" + - "this option does not work together with the show-branch option") + @Option(name = "--tree", aliases = {"-t"}, usage = + "displays project inheritance in a tree-like format\n" + + "this option does not work together with the show-branch option") private boolean showTree; @Option(name = "--type", usage = "type of project") @@ -98,27 +93,37 @@ final class ListProjects extends BaseCommand { @Option(name = "--all", usage = "display all projects that are accessible by the calling user") private boolean all; - @Override - public void start(final Environment env) { - startThread(new CommandRunnable() { - @Override - public void run() throws Exception { - parseCommandLine(); - ListProjects.this.display(); - } - }); + @Inject + protected ListProjects(CurrentUser currentUser, ProjectCache projectCache, + GitRepositoryManager repoManager, + ProjectNode.Factory projectNodeFactory) { + this.currentUser = currentUser; + this.projectCache = projectCache; + this.repoManager = repoManager; + this.projectNodeFactory = projectNodeFactory; } - private void display() throws Failure { - if (showTree && (showBranch != null)) { - throw new UnloggedFailure(1, "fatal: --tree and --show-branch options are not compatible."); + public List getShowBranch() { + return showBranch; + } + + public boolean isShowTree() { + return showTree; + } + + public boolean isShowDescription() { + return showDescription; + } + + public void display(OutputStream out) { + final PrintWriter stdout; + try { + stdout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))); + } catch (UnsupportedEncodingException e) { + // Our encoding is required by the specifications for the runtime. + throw new RuntimeException("JVM lacks UTF-8 encoding", e); } - if (showTree && showDescription) { - throw new UnloggedFailure(1, "fatal: --tree and --description options are not compatible."); - } - - final PrintWriter stdout = toPrintWriter(out); final TreeMap treeMap = new TreeMap(); try { diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ProjectNode.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectNode.java similarity index 90% rename from gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ProjectNode.java rename to gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectNode.java index 64a310b197..1c4d7c4f76 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ProjectNode.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectNode.java @@ -12,32 +12,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.gerrit.sshd.commands; +package com.google.gerrit.server.project; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.config.AllProjectsName; -import com.google.gerrit.sshd.commands.TreeFormatter.TreeNode; +import com.google.gerrit.server.util.TreeFormatter.TreeNode; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import java.util.SortedSet; import java.util.TreeSet; +/** Node of a Project in a tree formatted by {@link ListProjects}. */ public class ProjectNode implements TreeNode, Comparable { - public interface Factory { ProjectNode create(final Project project, final boolean isVisible); } private final AllProjectsName allProjectsName; - private final Project project; private final boolean isVisible; private final SortedSet children = new TreeSet(); @Inject - public ProjectNode(final AllProjectsName allProjectsName, + protected ProjectNode(final AllProjectsName allProjectsName, @Assisted final Project project, @Assisted final boolean isVisible) { this.allProjectsName = allProjectsName; this.project = project; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/TreeFormatter.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/TreeFormatter.java similarity index 98% rename from gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/TreeFormatter.java rename to gerrit-server/src/main/java/com/google/gerrit/server/util/TreeFormatter.java index 3aa83c3ad4..1c68a75797 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/TreeFormatter.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/TreeFormatter.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.gerrit.sshd.commands; +package com.google.gerrit.server.util; import java.io.PrintWriter; import java.util.SortedSet; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java index 00281b848f..54b0bb5ab4 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java @@ -40,7 +40,6 @@ import com.google.gerrit.sshd.args4j.PatchSetIdHandler; import com.google.gerrit.sshd.args4j.ProjectControlHandler; import com.google.gerrit.sshd.args4j.SocketAddressHandler; import com.google.gerrit.sshd.commands.DefaultCommandModule; -import com.google.gerrit.sshd.commands.ProjectNode; import com.google.gerrit.sshd.commands.QueryShell; import com.google.gerrit.util.cli.CmdLineParser; import com.google.gerrit.util.cli.OptionHandlerUtil; @@ -79,7 +78,6 @@ public class SshModule extends FactoryModule { bind(QueueProvider.class).to(CommandExecutorQueueProvider.class).in(SINGLETON); bind(AccountManager.class); factory(ChangeUserName.Factory.class); - factory(ProjectNode.Factory.class); bind(PublickeyAuthenticator.class).to(DatabasePubKeyAuth.class); bind(KeyPairProvider.class).toProvider(HostKeyProvider.class).in(SINGLETON); diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java index 5cee06ee96..16461b6b06 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java @@ -36,7 +36,7 @@ public class DefaultCommandModule extends CommandModule { command(gerrit).toProvider(new DispatchCommandProvider(gerrit)); command(gerrit, "flush-caches").to(FlushCaches.class); - command(gerrit, "ls-projects").to(ListProjects.class); + command(gerrit, "ls-projects").to(ListProjectsCommand.class); command(gerrit, "ls-groups").to(ListGroupsCommand.class); command(gerrit, "query").to(Query.class); command(gerrit, "show-caches").to(ShowCaches.class); diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjectsCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjectsCommand.java new file mode 100644 index 0000000000..d0bbc72079 --- /dev/null +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjectsCommand.java @@ -0,0 +1,43 @@ +// Copyright (C) 2009 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.commands; + +import com.google.gerrit.server.project.ListProjects; +import com.google.gerrit.sshd.BaseCommand; +import com.google.inject.Inject; + +import org.apache.sshd.server.Environment; + +final class ListProjectsCommand extends BaseCommand { + @Inject + private ListProjects impl; + + @Override + public void start(final Environment env) { + startThread(new CommandRunnable() { + @Override + public void run() throws Exception { + parseCommandLine(impl); + if (impl.isShowTree() && (impl.getShowBranch() != null)) { + throw new UnloggedFailure(1, "fatal: --tree and --show-branch options are not compatible."); + } + if (impl.isShowTree() && impl.isShowDescription()) { + throw new UnloggedFailure(1, "fatal: --tree and --description options are not compatible."); + } + impl.display(out); + } + }); + } +}