Check for open changes on branch deletion

Check for open changes when deleting a branch in the Gerrit WebUI.
Delete a branch only if there are no open changes for this branch.

The motivation for this change is to make the user aware of open
changes when deleting a branch.

Change-Id: Ifa5068dc5f93a48ced69b171465193ee35d5ab3b
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
Edwin Kempin
2012-01-23 09:24:37 +01:00
parent bc87753e7e
commit 1f3ba74925
7 changed files with 81 additions and 15 deletions

View File

@@ -25,6 +25,7 @@ import com.google.gwt.user.client.rpc.StatusCodeException;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.user.client.PluginSafePopupPanel;
import com.google.gwtjsonrpc.client.RemoteJsonException;
@@ -94,6 +95,11 @@ public class ErrorDialog extends PluginSafePopupPanel {
body.add(message.toBlockWidget());
}
public ErrorDialog(final Widget w) {
this();
body.add(w);
}
/** Create a dialog box to nicely format an exception. */
public ErrorDialog(final Throwable what) {
this();

View File

@@ -104,6 +104,7 @@ public interface GerritCss extends CssResource {
String errorDialogTitle();
String errorDialogButtons();
String errorDialogErrorType();
String errorDialogText();
String fileColumnHeader();
String fileLine();
String fileLineCONTEXT();

View File

@@ -91,6 +91,7 @@ public interface AdminConstants extends Constants {
String initialRevision();
String buttonAddBranch();
String buttonDeleteBranch();
String branchDeletionOpenChanges();
String groupListPrev();
String groupListNext();

View File

@@ -71,6 +71,8 @@ columnBranchRevision = Revision
initialRevision = Initial Revision
buttonAddBranch = Create Branch
buttonDeleteBranch = Delete
branchDeletionOpenChanges = The following branches were not deleted \
because they have open changes:
groupListPrev = Previous group
groupListNext = Next group

View File

@@ -16,9 +16,11 @@ package com.google.gerrit.client.admin;
import com.google.gerrit.client.ConfirmationCallback;
import com.google.gerrit.client.ConfirmationDialog;
import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.BranchLink;
import com.google.gerrit.client.ui.FancyFlexTable;
import com.google.gerrit.client.ui.HintTextBox;
import com.google.gerrit.common.data.GitwebLink;
@@ -26,6 +28,7 @@ import com.google.gerrit.common.data.ListBranchesResult;
import com.google.gerrit.common.errors.InvalidNameException;
import com.google.gerrit.common.errors.InvalidRevisionException;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
@@ -41,6 +44,7 @@ import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtjsonrpc.client.RemoteJsonException;
@@ -260,9 +264,17 @@ public class ProjectBranchesScreen extends ProjectScreen {
b.toSafeHtml(), new ConfirmationCallback() {
@Override
public void onOk() {
Util.PROJECT_SVC.deleteBranch(getProjectKey(), ids,
deleteBranches(ids);
}
});
confirmationDialog.center();
}
private void deleteBranches(final Set<Branch.NameKey> branchIds) {
Util.PROJECT_SVC.deleteBranch(getProjectKey(), branchIds,
new GerritCallback<Set<Branch.NameKey>>() {
public void onSuccess(final Set<Branch.NameKey> deleted) {
if (!deleted.isEmpty()) {
for (int row = 1; row < table.getRowCount();) {
final Branch k = getRowItem(row);
if (k != null && deleted.contains(k.getNameKey())) {
@@ -272,10 +284,30 @@ public class ProjectBranchesScreen extends ProjectScreen {
}
}
}
});
branchIds.removeAll(deleted);
if (!branchIds.isEmpty()) {
final VerticalPanel p = new VerticalPanel();
final ErrorDialog errorDialog = new ErrorDialog(p);
final Label l = new Label(Util.C.branchDeletionOpenChanges());
l.setStyleName(Gerrit.RESOURCES.css().errorDialogText());
p.add(l);
for (final Branch.NameKey branch : branchIds) {
final BranchLink link =
new BranchLink(branch.getParentKey(), Change.Status.NEW,
branch.get(), null) {
@Override
public void go() {
errorDialog.hide();
super.go();
};
};
p.add(link);
}
errorDialog.center();
}
}
});
confirmationDialog.center();
}
void display(final List<Branch> result) {

View File

@@ -375,6 +375,18 @@
width: 100%;
margin-top: 15px;
}
.errorDialogText {
font-size: 15px;
font-family: verdana;
}
.errorDialog a,
.errorDialog a:visited,
.errorDialog a:hover {
color: white;
font-weight: bold;
font-size: 15px;
font-family: verdana;
}
/** Screen **/

View File

@@ -18,11 +18,13 @@ import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.ReplicationQueue;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -34,6 +36,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
class DeleteBranches extends Handler<Set<Branch.NameKey>> {
@@ -50,6 +53,7 @@ class DeleteBranches extends Handler<Set<Branch.NameKey>> {
private final ReplicationQueue replication;
private final IdentifiedUser identifiedUser;
private final ChangeHooks hooks;
private final ReviewDb db;
private final Project.NameKey projectName;
private final Set<Branch.NameKey> toRemove;
@@ -60,6 +64,7 @@ class DeleteBranches extends Handler<Set<Branch.NameKey>> {
final ReplicationQueue replication,
final IdentifiedUser identifiedUser,
final ChangeHooks hooks,
final ReviewDb db,
@Assisted Project.NameKey name, @Assisted Set<Branch.NameKey> toRemove) {
this.projectControlFactory = projectControlFactory;
@@ -67,6 +72,7 @@ class DeleteBranches extends Handler<Set<Branch.NameKey>> {
this.replication = replication;
this.identifiedUser = identifiedUser;
this.hooks = hooks;
this.db = db;
this.projectName = name;
this.toRemove = toRemove;
@@ -74,17 +80,23 @@ class DeleteBranches extends Handler<Set<Branch.NameKey>> {
@Override
public Set<Branch.NameKey> call() throws NoSuchProjectException,
RepositoryNotFoundException {
RepositoryNotFoundException, OrmException {
final ProjectControl projectControl =
projectControlFactory.controlFor(projectName);
for (Branch.NameKey k : toRemove) {
final Iterator<Branch.NameKey> branchIt = toRemove.iterator();
while (branchIt.hasNext()) {
final Branch.NameKey k = branchIt.next();
if (!projectName.equals(k.getParentKey())) {
throw new IllegalArgumentException("All keys must be from same project");
}
if (!projectControl.controlForRef(k).canDelete()) {
throw new IllegalStateException("Cannot delete " + k.getShortName());
}
if (db.changes().byBranchOpenAll(k).iterator().hasNext()) {
branchIt.remove();
}
}
final Set<Branch.NameKey> deleted = new HashSet<Branch.NameKey>();