diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt index 6205dfbf05..c77bf96e76 100644 --- a/Documentation/rest-api-changes.txt +++ b/Documentation/rest-api-changes.txt @@ -142,8 +142,9 @@ default. Optional fields are: approvers that have granted (or rejected) with that label. * `DETAILED_LABELS`: detailed label information, including numeric - values of all existing approvals, recognized label values, and - values permitted to be set by the current user. + values of all existing approvals, recognized label values, values + permitted to be set by the current user, and reviewers that may be + removed by the current user. * `CURRENT_REVISION`: describe the current revision (patch set) of the change, including the commit SHA-1 and URLs to fetch from. diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java index f857169175..21ecb6c15c 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java @@ -76,6 +76,7 @@ public class ChangeInfo extends JavaScriptObject { public final native String branch() /*-{ return this.branch; }-*/; public final native String topic() /*-{ return this.topic; }-*/; public final native String change_id() /*-{ return this.change_id; }-*/; + public final native boolean mergeable() /*-{ return this.mergeable; }-*/; private final native String statusRaw() /*-{ return this.status; }-*/; public final native String subject() /*-{ return this.subject; }-*/; public final native AccountInfo owner() /*-{ return this.owner; }-*/; @@ -95,6 +96,9 @@ public class ChangeInfo extends JavaScriptObject { public final native JsArrayString permitted_values(String n) /*-{ return this.permitted_labels[n]; }-*/; + public final native JsArray removable_reviewers() + /*-{ return this.removable_reviewers; }-*/; + final native int _number() /*-{ return this._number; }-*/; final native boolean _more_changes() /*-{ return this._more_changes ? true : false; }-*/; diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java index 8bd76ad9e1..8799b822d2 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java @@ -31,6 +31,7 @@ import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import com.google.gerrit.common.changes.ListChangesOption; import com.google.gerrit.common.data.ApprovalType; import com.google.gerrit.common.data.ApprovalTypes; @@ -82,6 +83,7 @@ import java.util.Comparator; import java.util.EnumSet; import java.util.List; import java.util.Map; +import java.util.Set; public class ChangeJson { private static final Logger log = LoggerFactory.getLogger(ChangeJson.class); @@ -222,6 +224,7 @@ public class ChangeJson { out.branch = in.getDest().getShortName(); out.topic = in.getTopic(); out.changeId = in.getKey().get(); + out.mergeable = in.isMergeable(); out.subject = in.getSubject(); out.status = in.getStatus(); out.owner = accountLoader.get(in.getOwner()); @@ -235,6 +238,7 @@ public class ChangeJson { options.contains(DETAILED_LABELS)); if (options.contains(DETAILED_LABELS)) { out.permitted_labels = permittedLabels(cd); + out.removable_reviewers = removableReviewers(cd); } out.finish(); @@ -435,7 +439,6 @@ public class ChangeJson { } } - private Map> permittedLabels(ChangeData cd) throws OrmException { ChangeControl ctl = control(cd); @@ -471,6 +474,36 @@ public class ChangeJson { return permitted.asMap(); } + private Collection removableReviewers(ChangeData cd) + throws OrmException { + ChangeControl ctl = control(cd); + if (ctl == null) { + return ImmutableList.of(); + } + Change change = ctl.getChange(); + if (!change.getStatus().isOpen() || + !(ctl.getCurrentUser() instanceof IdentifiedUser)) { + return ImmutableList.of(); + } + + Set fixed = Sets.newHashSet(); + Set removable = Sets.newHashSet(); + for (PatchSetApproval app : cd.currentApprovals(db)) { + if (ctl.canRemoveReviewer(app)) { + removable.add(app.getAccountId()); + } else { + fixed.add(app.getAccountId()); + } + } + removable.removeAll(fixed); + + List result = Lists.newArrayListWithCapacity(removable.size()); + for (Account.Id id : removable) { + result.add(accountLoader.get(id)); + } + return result; + } + private boolean isChangeReviewed(ChangeData cd) throws OrmException { if (user instanceof IdentifiedUser) { PatchSet currentPatchSet = cd.currentPatchSet(db); @@ -661,13 +694,17 @@ public class ChangeJson { Timestamp updated; Boolean starred; Boolean reviewed; + Boolean mergeable; String _sortkey; int _number; AccountInfo owner; + Map labels; Map> permitted_labels; + Collection removable_reviewers; + String current_revision; Map revisions; public Boolean _moreChanges;