Add new SSH command to rename groups
Change-Id: Ie113bf27b778582ab02dd39220acd9b94563b8c4 Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
parent
f7b65a20d4
commit
aef2a352cb
@ -57,6 +57,9 @@ see link:user-upload.html#test_ssh[Testing Your SSH Connection].
|
|||||||
link:cmd-ls-projects.html[gerrit ls-projects]::
|
link:cmd-ls-projects.html[gerrit ls-projects]::
|
||||||
List projects visible to the caller.
|
List projects visible to the caller.
|
||||||
|
|
||||||
|
link:cmd-ls-projects.html[gerrit rename-group]::
|
||||||
|
Rename an account group.
|
||||||
|
|
||||||
link:cmd-set-reviewers.html[gerrit set-reviewers]::
|
link:cmd-set-reviewers.html[gerrit set-reviewers]::
|
||||||
Add or remove reviewers on a change.
|
Add or remove reviewers on a change.
|
||||||
|
|
||||||
|
46
Documentation/cmd-rename-group.txt
Normal file
46
Documentation/cmd-rename-group.txt
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
gerrit rename-group
|
||||||
|
===================
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
gerrit rename-group - Rename an account group.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
--------
|
||||||
|
[verse]
|
||||||
|
'ssh' -p <port> <host> 'gerrit rename-group'
|
||||||
|
<GROUP>
|
||||||
|
<NEWNAME>
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
Renames an account group.
|
||||||
|
|
||||||
|
ACCESS
|
||||||
|
------
|
||||||
|
Caller must be a member of the group owning the group to be renamed
|
||||||
|
or be a member of the privileged 'Administrators' group.
|
||||||
|
|
||||||
|
SCRIPTING
|
||||||
|
---------
|
||||||
|
This command is intended to be used in scripts.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
<GROUP>::
|
||||||
|
Required; name of the group to be renamed.
|
||||||
|
|
||||||
|
<NEWNAME>::
|
||||||
|
Required; new name of the group.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
Rename the group "MyGroup" to "MyCommitters".
|
||||||
|
|
||||||
|
====
|
||||||
|
$ ssh -p 29418 user@review.example.com gerrit rename-group MyGroup MyCommitters
|
||||||
|
====
|
||||||
|
|
||||||
|
GERRIT
|
||||||
|
------
|
||||||
|
Part of link:index.html[Gerrit Code Review]
|
@ -19,51 +19,25 @@ 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.httpd.rpc.Handler;
|
import com.google.gerrit.httpd.rpc.Handler;
|
||||||
import com.google.gerrit.reviewdb.AccountGroup;
|
import com.google.gerrit.reviewdb.AccountGroup;
|
||||||
import com.google.gerrit.reviewdb.AccountGroupName;
|
import com.google.gerrit.server.account.PerformRenameGroup;
|
||||||
import com.google.gerrit.reviewdb.ReviewDb;
|
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
|
||||||
import com.google.gerrit.server.account.GroupCache;
|
|
||||||
import com.google.gerrit.server.account.GroupControl;
|
|
||||||
import com.google.gerrit.server.account.GroupDetailFactory;
|
|
||||||
import com.google.gerrit.server.git.RenameGroupOp;
|
|
||||||
import com.google.gwtorm.client.OrmDuplicateKeyException;
|
|
||||||
import com.google.gwtorm.client.OrmException;
|
import com.google.gwtorm.client.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.assistedinject.Assisted;
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
class RenameGroup extends Handler<GroupDetail> {
|
class RenameGroup extends Handler<GroupDetail> {
|
||||||
interface Factory {
|
interface Factory {
|
||||||
RenameGroup create(AccountGroup.Id id, String newName);
|
RenameGroup create(AccountGroup.Id id, String newName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ReviewDb db;
|
private final PerformRenameGroup.Factory performRenameGroupFactory;
|
||||||
private final GroupCache groupCache;
|
|
||||||
private final GroupControl.Factory groupControlFactory;
|
|
||||||
private final GroupDetailFactory.Factory groupDetailFactory;
|
|
||||||
private final RenameGroupOp.Factory renameGroupOpFactory;
|
|
||||||
private final IdentifiedUser currentUser;
|
|
||||||
|
|
||||||
private final AccountGroup.Id groupId;
|
private final AccountGroup.Id groupId;
|
||||||
private final String newName;
|
private final String newName;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
RenameGroup(final ReviewDb db, final GroupCache groupCache,
|
RenameGroup(final PerformRenameGroup.Factory performRenameGroupFactory,
|
||||||
final GroupControl.Factory groupControlFactory,
|
|
||||||
final GroupDetailFactory.Factory groupDetailFactory,
|
|
||||||
final RenameGroupOp.Factory renameGroupOpFactory,
|
|
||||||
final IdentifiedUser currentUser,
|
|
||||||
@Assisted final AccountGroup.Id groupId, @Assisted final String newName) {
|
@Assisted final AccountGroup.Id groupId, @Assisted final String newName) {
|
||||||
this.db = db;
|
this.performRenameGroupFactory = performRenameGroupFactory;
|
||||||
this.groupCache = groupCache;
|
|
||||||
this.groupControlFactory = groupControlFactory;
|
|
||||||
this.groupDetailFactory = groupDetailFactory;
|
|
||||||
this.renameGroupOpFactory = renameGroupOpFactory;
|
|
||||||
this.currentUser = currentUser;
|
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.newName = newName;
|
this.newName = newName;
|
||||||
}
|
}
|
||||||
@ -71,46 +45,6 @@ class RenameGroup extends Handler<GroupDetail> {
|
|||||||
@Override
|
@Override
|
||||||
public GroupDetail call() throws OrmException, NameAlreadyUsedException,
|
public GroupDetail call() throws OrmException, NameAlreadyUsedException,
|
||||||
NoSuchGroupException {
|
NoSuchGroupException {
|
||||||
final GroupControl ctl = groupControlFactory.validateFor(groupId);
|
return performRenameGroupFactory.create().renameGroup(groupId, newName);
|
||||||
final AccountGroup group = db.accountGroups().get(groupId);
|
|
||||||
if (group == null || !ctl.isOwner()) {
|
|
||||||
throw new NoSuchGroupException(groupId);
|
|
||||||
}
|
|
||||||
|
|
||||||
final AccountGroup.NameKey old = group.getNameKey();
|
|
||||||
final AccountGroup.NameKey key = new AccountGroup.NameKey(newName);
|
|
||||||
|
|
||||||
try {
|
|
||||||
final AccountGroupName id = new AccountGroupName(key, groupId);
|
|
||||||
db.accountGroupNames().insert(Collections.singleton(id));
|
|
||||||
} catch (OrmDuplicateKeyException dupeErr) {
|
|
||||||
// If we are using this identity, don't report the exception.
|
|
||||||
//
|
|
||||||
AccountGroupName other = db.accountGroupNames().get(key);
|
|
||||||
if (other != null && other.getId().equals(groupId)) {
|
|
||||||
return groupDetailFactory.create(groupId).call();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, someone else has this identity.
|
|
||||||
//
|
|
||||||
throw new NameAlreadyUsedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
group.setNameKey(key);
|
|
||||||
db.accountGroups().update(Collections.singleton(group));
|
|
||||||
|
|
||||||
AccountGroupName priorName = db.accountGroupNames().get(old);
|
|
||||||
if (priorName != null) {
|
|
||||||
db.accountGroupNames().delete(Collections.singleton(priorName));
|
|
||||||
}
|
|
||||||
|
|
||||||
groupCache.evict(group);
|
|
||||||
groupCache.evictAfterRename(old);
|
|
||||||
renameGroupOpFactory.create( //
|
|
||||||
currentUser.newCommitterIdent(new Date(), TimeZone.getDefault()), //
|
|
||||||
group.getGroupUUID(), //
|
|
||||||
old.get(), newName).start(0, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
return groupDetailFactory.create(groupId).call();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,118 @@
|
|||||||
|
// 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.common.data.GroupDetail;
|
||||||
|
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
||||||
|
import com.google.gerrit.common.errors.NoSuchGroupException;
|
||||||
|
import com.google.gerrit.reviewdb.AccountGroup;
|
||||||
|
import com.google.gerrit.reviewdb.AccountGroupName;
|
||||||
|
import com.google.gerrit.reviewdb.ReviewDb;
|
||||||
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.server.git.RenameGroupOp;
|
||||||
|
import com.google.gwtorm.client.OrmDuplicateKeyException;
|
||||||
|
import com.google.gwtorm.client.OrmException;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class PerformRenameGroup {
|
||||||
|
|
||||||
|
public interface Factory {
|
||||||
|
PerformRenameGroup create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ReviewDb db;
|
||||||
|
private final GroupCache groupCache;
|
||||||
|
private final GroupControl.Factory groupControlFactory;
|
||||||
|
private final GroupDetailFactory.Factory groupDetailFactory;
|
||||||
|
private final RenameGroupOp.Factory renameGroupOpFactory;
|
||||||
|
private final IdentifiedUser currentUser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PerformRenameGroup(final ReviewDb db, final GroupCache groupCache,
|
||||||
|
final GroupControl.Factory groupControlFactory,
|
||||||
|
final GroupDetailFactory.Factory groupDetailFactory,
|
||||||
|
final RenameGroupOp.Factory renameGroupOpFactory,
|
||||||
|
final IdentifiedUser currentUser) {
|
||||||
|
this.db = db;
|
||||||
|
this.groupCache = groupCache;
|
||||||
|
this.groupControlFactory = groupControlFactory;
|
||||||
|
this.groupDetailFactory = groupDetailFactory;
|
||||||
|
this.renameGroupOpFactory = renameGroupOpFactory;
|
||||||
|
this.currentUser = currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupDetail renameGroup(final String groupName,
|
||||||
|
final String newGroupName) throws OrmException, NameAlreadyUsedException,
|
||||||
|
NoSuchGroupException {
|
||||||
|
final AccountGroup.NameKey groupNameKey =
|
||||||
|
new AccountGroup.NameKey(groupName);
|
||||||
|
final AccountGroup group = groupCache.get(groupNameKey);
|
||||||
|
if (group == null) {
|
||||||
|
throw new NoSuchGroupException(groupNameKey);
|
||||||
|
}
|
||||||
|
return renameGroup(group.getId(), newGroupName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupDetail renameGroup(final AccountGroup.Id groupId,
|
||||||
|
final String newName) throws OrmException, NameAlreadyUsedException,
|
||||||
|
NoSuchGroupException {
|
||||||
|
final GroupControl ctl = groupControlFactory.validateFor(groupId);
|
||||||
|
final AccountGroup group = db.accountGroups().get(groupId);
|
||||||
|
if (group == null || !ctl.isOwner()) {
|
||||||
|
throw new NoSuchGroupException(groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
final AccountGroup.NameKey old = group.getNameKey();
|
||||||
|
final AccountGroup.NameKey key = new AccountGroup.NameKey(newName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final AccountGroupName id = new AccountGroupName(key, groupId);
|
||||||
|
db.accountGroupNames().insert(Collections.singleton(id));
|
||||||
|
} catch (OrmDuplicateKeyException dupeErr) {
|
||||||
|
// If we are using this identity, don't report the exception.
|
||||||
|
//
|
||||||
|
AccountGroupName other = db.accountGroupNames().get(key);
|
||||||
|
if (other != null && other.getId().equals(groupId)) {
|
||||||
|
return groupDetailFactory.create(groupId).call();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, someone else has this identity.
|
||||||
|
//
|
||||||
|
throw new NameAlreadyUsedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
group.setNameKey(key);
|
||||||
|
db.accountGroups().update(Collections.singleton(group));
|
||||||
|
|
||||||
|
AccountGroupName priorName = db.accountGroupNames().get(old);
|
||||||
|
if (priorName != null) {
|
||||||
|
db.accountGroupNames().delete(Collections.singleton(priorName));
|
||||||
|
}
|
||||||
|
|
||||||
|
groupCache.evict(group);
|
||||||
|
groupCache.evictAfterRename(old);
|
||||||
|
renameGroupOpFactory.create( //
|
||||||
|
currentUser.newCommitterIdent(new Date(), TimeZone.getDefault()), //
|
||||||
|
group.getGroupUUID(), //
|
||||||
|
old.get(), newName).start(0, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
return groupDetailFactory.create(groupId).call();
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,7 @@ import com.google.gerrit.server.account.GroupControl;
|
|||||||
import com.google.gerrit.server.account.GroupDetailFactory;
|
import com.google.gerrit.server.account.GroupDetailFactory;
|
||||||
import com.google.gerrit.server.account.GroupMembersFactory;
|
import com.google.gerrit.server.account.GroupMembersFactory;
|
||||||
import com.google.gerrit.server.account.PerformCreateGroup;
|
import com.google.gerrit.server.account.PerformCreateGroup;
|
||||||
|
import com.google.gerrit.server.account.PerformRenameGroup;
|
||||||
import com.google.gerrit.server.git.CreateCodeReviewNotes;
|
import com.google.gerrit.server.git.CreateCodeReviewNotes;
|
||||||
import com.google.gerrit.server.git.MergeOp;
|
import com.google.gerrit.server.git.MergeOp;
|
||||||
import com.google.gerrit.server.git.MetaDataUpdate;
|
import com.google.gerrit.server.git.MetaDataUpdate;
|
||||||
@ -89,6 +90,7 @@ public class GerritRequestModule extends FactoryModule {
|
|||||||
factory(MergeFailSender.Factory.class);
|
factory(MergeFailSender.Factory.class);
|
||||||
factory(RegisterNewEmailSender.Factory.class);
|
factory(RegisterNewEmailSender.Factory.class);
|
||||||
factory(PerformCreateGroup.Factory.class);
|
factory(PerformCreateGroup.Factory.class);
|
||||||
|
factory(PerformRenameGroup.Factory.class);
|
||||||
factory(GroupDetailFactory.Factory.class);
|
factory(GroupDetailFactory.Factory.class);
|
||||||
factory(GroupMembersFactory.Factory.class);
|
factory(GroupMembersFactory.Factory.class);
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ public class MasterCommandModule extends CommandModule {
|
|||||||
command(gerrit, "approve").to(ReviewCommand.class);
|
command(gerrit, "approve").to(ReviewCommand.class);
|
||||||
command(gerrit, "create-account").to(CreateAccountCommand.class);
|
command(gerrit, "create-account").to(CreateAccountCommand.class);
|
||||||
command(gerrit, "create-group").to(CreateGroupCommand.class);
|
command(gerrit, "create-group").to(CreateGroupCommand.class);
|
||||||
|
command(gerrit, "rename-group").to(RenameGroupCommand.class);
|
||||||
command(gerrit, "create-project").to(CreateProject.class);
|
command(gerrit, "create-project").to(CreateProject.class);
|
||||||
command(gerrit, "gsql").to(AdminQueryShell.class);
|
command(gerrit, "gsql").to(AdminQueryShell.class);
|
||||||
command(gerrit, "set-reviewers").to(SetReviewersCommand.class);
|
command(gerrit, "set-reviewers").to(SetReviewersCommand.class);
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
// 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.sshd.commands;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
||||||
|
import com.google.gerrit.common.errors.NoSuchGroupException;
|
||||||
|
import com.google.gerrit.server.account.PerformRenameGroup;
|
||||||
|
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.Argument;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class RenameGroupCommand extends BaseCommand {
|
||||||
|
|
||||||
|
@Argument(index = 0, required = true, metaVar = "GROUP", usage = "name of the group to be renamed")
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
@Argument(index = 1, required = true, metaVar = "NEWNAME", usage = "new name of the group")
|
||||||
|
private String newGroupName;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PerformRenameGroup.Factory performRenameGroupFactory;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(final Environment env) throws IOException {
|
||||||
|
startThread(new CommandRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() throws Exception {
|
||||||
|
parseCommandLine();
|
||||||
|
try {
|
||||||
|
performRenameGroupFactory.create().renameGroup(groupName, newGroupName);
|
||||||
|
} catch (OrmException e) {
|
||||||
|
throw die(e);
|
||||||
|
} catch (NameAlreadyUsedException e) {
|
||||||
|
throw die(e);
|
||||||
|
} catch (NoSuchGroupException e) {
|
||||||
|
throw die(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user