Merge "Check for open changes on branch deletion"

This commit is contained in:
Shawn Pearce 2012-05-03 14:03:19 -07:00 committed by gerrit code review
commit faaf5b823d
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

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

View File

@ -68,6 +68,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,16 +16,19 @@ 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.GitwebLink;
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.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,24 +264,52 @@ public class ProjectBranchesScreen extends ProjectScreen {
b.toSafeHtml(), new ConfirmationCallback() {
@Override
public void onOk() {
Util.PROJECT_SVC.deleteBranch(getProjectKey(), ids,
new GerritCallback<Set<Branch.NameKey>>() {
public void onSuccess(final Set<Branch.NameKey> deleted) {
for (int row = 1; row < table.getRowCount();) {
final Branch k = getRowItem(row);
if (k != null && deleted.contains(k.getNameKey())) {
table.removeRow(row);
} else {
row++;
}
}
}
});
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())) {
table.removeRow(row);
} else {
row++;
}
}
}
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();
}
}
});
}
void display(final List<Branch> result) {
canDelete = false;

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>();