diff --git a/Documentation/cmd-ls-groups.txt b/Documentation/cmd-ls-groups.txt index 842abfd738..cb65f7ed53 100644 --- a/Documentation/cmd-ls-groups.txt +++ b/Documentation/cmd-ls-groups.txt @@ -9,6 +9,7 @@ SYNOPSIS -------- [verse] 'ssh' -p 'gerrit ls-groups' + [--project ] DESCRIPTION ----------- @@ -26,6 +27,17 @@ SCRIPTING --------- This command is intended to be used in scripts. +OPTIONS +------- +--project:: +-p:: + Name of the project for which the groups should be listed. Only + groups are listed for which any permission is set on this project + (or for which a permission is inherited from a parent project). + Multiple --project options may be specified to specify additional + projects. In this case all groups are listed that have a + permission for any of the specified projects. + EXAMPLES -------- @@ -39,6 +51,15 @@ List visible groups: Registered Users ===== +List all groups for which any permission is set for the project +"MyProject": +===== + $ ssh -p 29418 review.example.com gerrit ls-groups --project MyProject + MyProject_Committers + Project Owners + Registered Users +===== + GERRIT ------ Part of link:index.html[Gerrit Code Review] diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupComparator.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupComparator.java new file mode 100644 index 0000000000..9348a0cbe6 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupComparator.java @@ -0,0 +1,27 @@ +// Copyright (C) 2011 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.server.account; + +import com.google.gerrit.reviewdb.AccountGroup; + +import java.util.Comparator; + +public class GroupComparator implements Comparator { + + @Override + public int compare(final AccountGroup group1, final AccountGroup group2) { + return group1.getName().compareTo(group2.getName()); + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/VisibleGroups.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/VisibleGroups.java index c47c2317a5..c7487f3f25 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/VisibleGroups.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/VisibleGroups.java @@ -16,17 +16,22 @@ package com.google.gerrit.server.account; import com.google.gerrit.common.data.GroupDetail; import com.google.gerrit.common.data.GroupList; +import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.reviewdb.AccountGroup; import com.google.gerrit.server.IdentifiedUser; +import com.google.gerrit.server.project.ProjectControl; import com.google.gwtorm.client.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; -import org.apache.commons.collections.CollectionUtils; - import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; public class VisibleGroups { @@ -39,6 +44,8 @@ public class VisibleGroups { private final GroupControl.Factory groupControlFactory; private final GroupDetailFactory.Factory groupDetailFactory; + private Collection projects; + @Inject VisibleGroups(final Provider currentUser, final GroupCache groupCache, @@ -50,24 +57,59 @@ public class VisibleGroups { this.groupDetailFactory = groupDetailFactory; } + public void setProjects(final Collection projects) { + this.projects = projects; + } + public GroupList get() throws OrmException, NoSuchGroupException { - final IdentifiedUser user = identifiedUser.get(); - final List list = new ArrayList(); - if (user.getCapabilities().canAdministrateServer()) { - CollectionUtils.addAll(list, groupCache.all().iterator()); + final Iterable groups; + if (projects != null && !projects.isEmpty()) { + groups = getGroupsForProjects(); } else { - for(final AccountGroup group : groupCache.all()) { - final GroupControl c = groupControlFactory.controlFor(group); - if (c.isVisible()) { - list.add(c.getAccountGroup()); + groups = groupCache.all(); + } + return createGroupList(filterGroups(groups)); + } + + private Set getGroupsForProjects() throws NoSuchGroupException { + final SortedSet groups = + new TreeSet(new GroupComparator()); + for (final ProjectControl projectControl : projects) { + final Set groupsRefs = projectControl.getAllGroups(); + for (final GroupReference groupRef : groupsRefs) { + final AccountGroup group = groupCache.get(groupRef.getUUID()); + if (group == null) { + throw new NoSuchGroupException(groupRef.getUUID()); } + groups.add(group); } } + return groups; + } - List l = new ArrayList(); - for(AccountGroup group : list) { - l.add(groupDetailFactory.create(group.getId()).call()); + private List filterGroups(final Iterable groups) { + final List filteredGroups = new LinkedList(); + final boolean isAdmin = + identifiedUser.get().getCapabilities().canAdministrateServer(); + for (final AccountGroup group : groups) { + if (!isAdmin) { + final GroupControl c = groupControlFactory.controlFor(group); + if (!c.isVisible()) { + continue; + } + } + filteredGroups.add(group); } - return new GroupList(l, user.getCapabilities().canCreateGroup()); + return filteredGroups; + } + + private GroupList createGroupList(final List groups) + throws OrmException, NoSuchGroupException { + final List groupDetailList = new ArrayList(); + for (final AccountGroup group : groups) { + groupDetailList.add(groupDetailFactory.create(group.getId()).call()); + } + return new GroupList(groupDetailList, identifiedUser.get() + .getCapabilities().canCreateGroup()); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java index 5a3f0bdbe7..b6fb074488 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java @@ -17,6 +17,7 @@ package com.google.gerrit.server.project; import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.data.AccessSection; import com.google.gerrit.common.data.Capable; +import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.common.data.Permission; import com.google.gerrit.common.data.PermissionRule; import com.google.gerrit.reviewdb.AbstractAgreement; @@ -252,6 +253,19 @@ public class ProjectControl { return Capable.OK; } + public Set getAllGroups() { + final Set all = new HashSet(); + for (final SectionMatcher matcher : access()) { + final AccessSection section = matcher.section; + for (final Permission permission : section.getPermissions()) { + for (final PermissionRule rule : permission.getRules()) { + all.add(rule.getGroup()); + } + } + } + return all; + } + private Capable verifyActiveContributorAgreement() throws OrmException { if (! (user instanceof IdentifiedUser)) { return new Capable("Must be logged in to verify Contributor Agreement"); diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListGroupsCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListGroupsCommand.java index b25bee4334..f70f74209d 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListGroupsCommand.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListGroupsCommand.java @@ -18,20 +18,29 @@ import com.google.gerrit.common.data.GroupDetail; import com.google.gerrit.common.data.GroupList; import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.server.account.VisibleGroups; +import com.google.gerrit.server.project.ProjectControl; import com.google.gerrit.sshd.BaseCommand; import com.google.gwtorm.client.OrmException; import com.google.inject.Inject; import org.apache.sshd.server.Environment; +import org.kohsuke.args4j.Option; import java.io.IOException; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; public class ListGroupsCommand extends BaseCommand { @Inject private VisibleGroups.Factory visibleGroupsFactory; + + @Option(name = "--project", aliases = {"-p"}, + usage = "projects for which the groups should be listed") + private final List projects = new ArrayList(); + @Override public void start(final Environment env) throws IOException { startThread(new CommandRunnable() { @@ -46,9 +55,10 @@ public class ListGroupsCommand extends BaseCommand { private void display() throws Failure { final PrintWriter stdout = toPrintWriter(out); try { - final GroupList visibleGroups = - visibleGroupsFactory.create().get(); - for (final GroupDetail groupDetail : visibleGroups.getGroups()) { + final VisibleGroups visibleGroups = visibleGroupsFactory.create(); + visibleGroups.setProjects(projects); + final GroupList groupList = visibleGroups.get(); + for (final GroupDetail groupDetail : groupList.getGroups()) { stdout.print(groupDetail.group.getName() + "\n"); } } catch (OrmException e) {