Merge changes Ic8f371d9,Iae4cffcd,I4213004f
* changes:
Implement DynamicSet<T>, DynamicMap<T> to provide bindings in Guice
Automatically register plugin bindings
Define gerrit-extension-api module
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index fa727b5..5172e03 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -703,6 +703,21 @@
is already restricted to the correct set of users.
+[[category_rebase]]
+Rebase
+~~~~~~
+
+This category permits users to rebase changes via the web UI by pushing
+the `Rebase Change` button.
+
+The change owner and submitters can always rebase changes in the web UI
+(even without having the `Rebase` access right assigned).
+
+Users without this access right who are able to upload new patch sets
+can still do the rebase locally and upload the rebased commit as a new
+patch set.
+
+
[[category_submit]]
Submit
~~~~~~
diff --git a/Documentation/user-search.txt b/Documentation/user-search.txt
index 890c964..4fd6b2f 100644
--- a/Documentation/user-search.txt
+++ b/Documentation/user-search.txt
@@ -16,9 +16,10 @@
|All > Open | status:open '(or is:open)'
|All > Merged | status:merged
|All > Abandoned | status:abandoned
-|My > Dafts | has:draft
+|My > Drafts | is:draft
|My > Watched Changes | status:open is:watched
|My > Starred Changes | is:starred
+|My > Draft Comments | has:draft
|Open changes in Foo | status:open project:Foo
|=================================================
@@ -230,6 +231,10 @@
+
True if the change is other open or submitted, merge pending.
+is:draft::
++
+True if the change is a draft.
+
is:closed::
+
True if the change is either merged or abandoned.
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
index 71df400..25f4f22a 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
@@ -59,6 +59,10 @@
return "/admin/projects/" + p.get() + ",access";
}
+ public static String toAccountQuery(final String fullname) {
+ return "/q/owner:\"" + KeyUtil.encode(fullname) + "\"," + TOP;
+ }
+
public static String toAccountDashboard(final AccountInfo acct) {
return toAccountDashboard(acct.getId());
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/Permission.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/Permission.java
index f818d7b..20261de 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/Permission.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/Permission.java
@@ -30,6 +30,7 @@
public static final String PUSH_MERGE = "pushMerge";
public static final String PUSH_TAG = "pushTag";
public static final String READ = "read";
+ public static final String REBASE = "rebase";
public static final String SUBMIT = "submit";
private static final List<String> NAMES_LC;
@@ -47,6 +48,7 @@
NAMES_LC.add(PUSH_MERGE.toLowerCase());
NAMES_LC.add(PUSH_TAG.toLowerCase());
NAMES_LC.add(LABEL.toLowerCase());
+ NAMES_LC.add(REBASE.toLowerCase());
NAMES_LC.add(SUBMIT.toLowerCase());
labelIndex = NAMES_LC.indexOf(Permission.LABEL);
diff --git a/gerrit-ehcache/src/main/java/com/google/gerrit/ehcache/EhcachePoolImpl.java b/gerrit-ehcache/src/main/java/com/google/gerrit/ehcache/EhcachePoolImpl.java
index c25c381..f4e85ba 100644
--- a/gerrit-ehcache/src/main/java/com/google/gerrit/ehcache/EhcachePoolImpl.java
+++ b/gerrit-ehcache/src/main/java/com/google/gerrit/ehcache/EhcachePoolImpl.java
@@ -94,6 +94,7 @@
this.caches = new HashMap<String, CacheProvider<?, ?>>();
}
+ @SuppressWarnings({"rawtypes", "unchecked"})
private void start() {
synchronized (lock) {
if (manager != null) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
index ffa76ed..40ffc7d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
@@ -235,6 +235,10 @@
}
if (matchExact("mine,drafts", token)) {
+ return PageLinks.toChangeQuery("is:draft");
+ }
+
+ if (matchExact("mine,comments", token)) {
return PageLinks.toChangeQuery("has:draft");
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index 6dbfeee..fd6ba2d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -548,9 +548,10 @@
if (signedIn) {
m = new LinkMenuBar();
addLink(m, C.menuMyChanges(), PageLinks.MINE);
- addLink(m, C.menuMyDrafts(), PageLinks.toChangeQuery("has:draft"));
+ addLink(m, C.menuMyDrafts(), PageLinks.toChangeQuery("is:draft"));
addLink(m, C.menuMyWatchedChanges(), PageLinks.toChangeQuery("is:watched status:open"));
addLink(m, C.menuMyStarredChanges(), PageLinks.toChangeQuery("is:starred"));
+ addLink(m, C.menuMyDraftComments(), PageLinks.toChangeQuery("has:draft"));
menuLeft.add(m, C.menuMine());
menuLeft.selectTab(1);
} else {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
index ee107d0..f716814 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
@@ -60,6 +60,7 @@
String menuMyDrafts();
String menuMyWatchedChanges();
String menuMyStarredChanges();
+ String menuMyDraftComments();
String menuDiff();
String menuDiffCommit();
@@ -96,4 +97,5 @@
String jumpMineDrafts();
String jumpMineWatched();
String jumpMineStarred();
+ String jumpMineDraftComments();
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
index 41db3d5..8e3ca6c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
@@ -43,6 +43,7 @@
menuMyDrafts = Drafts
menuMyStarredChanges = Starred Changes
menuMyWatchedChanges = Watched Changes
+menuMyDraftComments = Draft Comments
menuDiff = Differences
menuDiffCommit = Commit Message
@@ -79,3 +80,4 @@
jumpMineWatched = Go to watched changes
jumpMineDrafts = Go to drafts
jumpMineStarred = Go to starred changes
+jumpMineDraftComments = Go to draft comments
\ No newline at end of file
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java
index 873045d..a41ff02 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/JumpKeys.java
@@ -55,6 +55,12 @@
jumps.add(new KeyCommand(0, 'd', Gerrit.C.jumpMineDrafts()) {
@Override
public void onKeyPress(final KeyPressEvent event) {
+ Gerrit.display(PageLinks.toChangeQuery("is:draft"));
+ }
+ });
+ jumps.add(new KeyCommand(0, 'c', Gerrit.C.jumpMineDraftComments()) {
+ @Override
+ public void onKeyPress(final KeyPressEvent event) {
Gerrit.display(PageLinks.toChangeQuery("has:draft"));
}
});
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java
index b777be7..3bd2e77 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java
@@ -14,7 +14,6 @@
package com.google.gerrit.client.account;
-import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.FancyFlexTable;
@@ -24,8 +23,6 @@
import com.google.gerrit.common.data.ContributorAgreement;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
public class MyAgreementsScreen extends SettingsScreen {
private AgreementTable agreements;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java
index 936bfe5..eaf564f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java
@@ -374,39 +374,41 @@
new GerritCallback<List<AccountGroup.ExternalNameKey>>() {
@Override
public void onSuccess(List<AccountGroup.ExternalNameKey> result) {
- final CellFormatter fmt = externalMatches.getCellFormatter();
+ try {
+ final CellFormatter fmt = externalMatches.getCellFormatter();
- if (result.isEmpty()) {
- externalMatches.resize(1, 1);
- externalMatches.setText(0, 0, Util.C.errorNoMatchingGroups());
+ if (result.isEmpty()) {
+ externalMatches.resize(1, 1);
+ externalMatches.setText(0, 0, Util.C.errorNoMatchingGroups());
+ fmt.setStyleName(0, 0, Gerrit.RESOURCES.css().header());
+ return;
+ }
+
+ externalMatches.resize(1 + result.size(), 2);
+
+ externalMatches.setText(0, 0, Util.C.columnGroupName());
+ externalMatches.setText(0, 1, "");
fmt.setStyleName(0, 0, Gerrit.RESOURCES.css().header());
- return;
+ fmt.setStyleName(0, 1, Gerrit.RESOURCES.css().header());
+
+ for (int row = 0; row < result.size(); row++) {
+ final AccountGroup.ExternalNameKey key = result.get(row);
+ final Button b = new Button(Util.C.buttonSelectGroup());
+ b.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ setExternalGroup(key);
+ }
+ });
+ externalMatches.setText(1 + row, 0, key.get());
+ externalMatches.setWidget(1 + row, 1, b);
+ fmt.setStyleName(1 + row, 1, Gerrit.RESOURCES.css().rightmost());
+ }
+ } finally {
+ externalMatches.setVisible(true);
+ externalNameFilter.setEnabled(true);
+ externalNameSearch.setEnabled(true);
}
-
- externalMatches.resize(1 + result.size(), 2);
-
- externalMatches.setText(0, 0, Util.C.columnGroupName());
- externalMatches.setText(0, 1, "");
- fmt.setStyleName(0, 0, Gerrit.RESOURCES.css().header());
- fmt.setStyleName(0, 1, Gerrit.RESOURCES.css().header());
-
- for (int row = 0; row < result.size(); row++) {
- final AccountGroup.ExternalNameKey key = result.get(row);
- final Button b = new Button(Util.C.buttonSelectGroup());
- b.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- setExternalGroup(key);
- }
- });
- externalMatches.setText(1 + row, 0, key.get());
- externalMatches.setWidget(1 + row, 1, b);
- fmt.setStyleName(1 + row, 1, Gerrit.RESOURCES.css().rightmost());
- }
- externalMatches.setVisible(true);
-
- externalNameFilter.setEnabled(true);
- externalNameSearch.setEnabled(true);
}
@Override
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
index 7e0edec..4330513 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
@@ -102,6 +102,7 @@
pushMerge, \
pushTag, \
read, \
+ rebase, \
submit
create = Create Reference
forgeAuthor = Forge Author Identity
@@ -112,6 +113,7 @@
pushMerge = Push Merge Commit
pushTag = Push Annotated Tag
read = Read
+rebase = Rebase
submit = Submit
refErrorEmpty = Reference must be supplied
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable2.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable2.java
index 1372aa2..1b9db39 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable2.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable2.java
@@ -20,6 +20,7 @@
import com.google.gerrit.client.changes.ChangeInfo.LabelInfo;
import com.google.gerrit.client.ui.BranchLink;
import com.google.gerrit.client.ui.ChangeLink;
+import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.client.ui.NavigationTable;
import com.google.gerrit.client.ui.NeedsSignInKeyCommand;
import com.google.gerrit.client.ui.ProjectLink;
@@ -209,7 +210,9 @@
if (c.owner() != null && c.owner().name() != null) {
owner = c.owner().name();
}
- table.setText(row, C_OWNER, owner);
+
+ table.setWidget(row, C_OWNER, new InlineHyperlink(owner,
+ PageLinks.toAccountQuery(owner)));
table.setWidget(
row, C_PROJECT, new ProjectLink(c.project_name_key(), c.status()));
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/AbandonChangeHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/AbandonChangeHandler.java
index 4d1c1f5..1d4d3e2 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/AbandonChangeHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/AbandonChangeHandler.java
@@ -65,7 +65,7 @@
PatchSetInfoNotAvailableException, RepositoryNotFoundException,
IOException {
final ReviewResult result =
- abandonChangeFactory.create(patchSetId, message).call();
+ abandonChangeFactory.create(patchSetId.getParentKey(), message).call();
if (result.getErrors().size() > 0) {
throw new NoSuchChangeException(result.getChangeId());
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChangeHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChangeHandler.java
index bcb03b0..5d7fe32 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChangeHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChangeHandler.java
@@ -64,7 +64,7 @@
PatchSetInfoNotAvailableException, RepositoryNotFoundException,
IOException {
final ReviewResult result =
- restoreChangeFactory.create(patchSetId, message).call();
+ restoreChangeFactory.create(patchSetId.getParentKey(), message).call();
if (result.getErrors().size() > 0) {
throw new NoSuchChangeException(result.getChangeId());
}
diff --git a/gerrit-patch-jgit/src/main/java/org/eclipse/jgit/diff/EditDeserializer.java b/gerrit-patch-jgit/src/main/java/org/eclipse/jgit/diff/EditDeserializer.java
index 1df89b7..9a55e0f 100644
--- a/gerrit-patch-jgit/src/main/java/org/eclipse/jgit/diff/EditDeserializer.java
+++ b/gerrit-patch-jgit/src/main/java/org/eclipse/jgit/diff/EditDeserializer.java
@@ -76,7 +76,7 @@
public JsonElement serialize(final Edit src, final Type typeOfSrc,
final JsonSerializationContext context) {
if (src == null) {
- return new JsonNull();
+ return JsonNull.INSTANCE;
}
final JsonArray a = new JsonArray();
add(a, src);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java b/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java
index 727207f..274e73ff 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java
@@ -30,7 +30,6 @@
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.events.ApprovalAttribute;
import com.google.gerrit.server.events.ChangeAbandonedEvent;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
index c5a66bb..556ae82 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
@@ -27,7 +27,6 @@
import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import java.io.IOException;
@@ -35,6 +34,16 @@
import java.util.List;
import java.util.Set;
+/**
+ * Utility functions to manipulate patchset approvals.
+ * <p>
+ * Approvals are overloaded, they represent both approvals and reviewers
+ * which should be CCed on a change. To ensure that reviewers are not lost
+ * there must always be an approval on each patchset for each reviewer,
+ * even if the reviewer hasn't actually given a score to the change. To
+ * mark the "no score" case, a dummy approval, which may live in any of
+ * the available categories, with a score of 0 is used.
+ */
public class ApprovalsUtil {
private final ReviewDb db;
private final ApprovalTypes approvalTypes;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/AbandonChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/AbandonChange.java
index 1fac8c5..83fa671 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/AbandonChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/AbandonChange.java
@@ -35,10 +35,12 @@
import java.util.concurrent.Callable;
+import javax.annotation.Nullable;
+
public class AbandonChange implements Callable<ReviewResult> {
public interface Factory {
- AbandonChange create(PatchSet.Id patchSetId, String changeComment);
+ AbandonChange create(Change.Id changeId, String changeComment);
}
private final AbandonedSender.Factory abandonedSenderFactory;
@@ -47,22 +49,22 @@
private final IdentifiedUser currentUser;
private final ChangeHooks hooks;
- private final PatchSet.Id patchSetId;
+ private final Change.Id changeId;
private final String changeComment;
@Inject
AbandonChange(final AbandonedSender.Factory abandonedSenderFactory,
final ChangeControl.Factory changeControlFactory, final ReviewDb db,
final IdentifiedUser currentUser, final ChangeHooks hooks,
- @Assisted final PatchSet.Id patchSetId,
- @Assisted final String changeComment) {
+ @Assisted final Change.Id changeId,
+ @Assisted @Nullable final String changeComment) {
this.abandonedSenderFactory = abandonedSenderFactory;
this.changeControlFactory = changeControlFactory;
this.db = db;
this.currentUser = currentUser;
this.hooks = hooks;
- this.patchSetId = patchSetId;
+ this.changeId = changeId;
this.changeComment = changeComment;
}
@@ -70,10 +72,11 @@
public ReviewResult call() throws EmailException,
InvalidChangeOperationException, NoSuchChangeException, OrmException {
final ReviewResult result = new ReviewResult();
-
- final Change.Id changeId = patchSetId.getParentKey();
result.setChangeId(changeId);
+
final ChangeControl control = changeControlFactory.validateFor(changeId);
+ final Change change = db.changes().get(changeId);
+ final PatchSet.Id patchSetId = change.currentPatchSetId();
final PatchSet patch = db.patchSets().get(patchSetId);
if (!control.canAbandon()) {
result.addError(new ReviewResult.Error(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RestoreChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RestoreChange.java
index 7e52564..966efce 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RestoreChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RestoreChange.java
@@ -41,10 +41,12 @@
import java.io.IOException;
import java.util.concurrent.Callable;
+import javax.annotation.Nullable;
+
public class RestoreChange implements Callable<ReviewResult> {
public interface Factory {
- RestoreChange create(PatchSet.Id patchSetId, String changeComment);
+ RestoreChange create(Change.Id changeId, String changeComment);
}
private final RestoredSender.Factory restoredSenderFactory;
@@ -54,15 +56,15 @@
private final IdentifiedUser currentUser;
private final ChangeHooks hooks;
- private final PatchSet.Id patchSetId;
+ private final Change.Id changeId;
private final String changeComment;
@Inject
RestoreChange(final RestoredSender.Factory restoredSenderFactory,
final ChangeControl.Factory changeControlFactory, final ReviewDb db,
final GitRepositoryManager repoManager, final IdentifiedUser currentUser,
- final ChangeHooks hooks, @Assisted final PatchSet.Id patchSetId,
- @Assisted final String changeComment) {
+ final ChangeHooks hooks, @Assisted final Change.Id changeId,
+ @Assisted @Nullable final String changeComment) {
this.restoredSenderFactory = restoredSenderFactory;
this.changeControlFactory = changeControlFactory;
this.db = db;
@@ -70,7 +72,7 @@
this.currentUser = currentUser;
this.hooks = hooks;
- this.patchSetId = patchSetId;
+ this.changeId = changeId;
this.changeComment = changeComment;
}
@@ -79,10 +81,11 @@
InvalidChangeOperationException, NoSuchChangeException, OrmException,
RepositoryNotFoundException, IOException {
final ReviewResult result = new ReviewResult();
-
- final Change.Id changeId = patchSetId.getParentKey();
result.setChangeId(changeId);
+
final ChangeControl control = changeControlFactory.validateFor(changeId);
+ final Change change = db.changes().get(changeId);
+ final PatchSet.Id patchSetId = change.currentPatchSetId();
if (!control.canRestore()) {
result.addError(new ReviewResult.Error(
ReviewResult.Error.Type.RESTORE_NOT_PERMITTED));
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailTokenVerifier.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailTokenVerifier.java
index 4307854..8501426 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailTokenVerifier.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailTokenVerifier.java
@@ -40,6 +40,8 @@
/** Exception thrown when a token does not parse correctly. */
public static class InvalidTokenException extends Exception {
+ private static final long serialVersionUID = 1L;
+
public InvalidTokenException() {
super("Invalid token");
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
index 7652bed..f232c5c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
@@ -204,7 +204,8 @@
/** Can this user rebase this change? */
public boolean canRebase() {
- return isOwner() || getRefControl().canSubmit();
+ return isOwner() || getRefControl().canSubmit()
+ || getRefControl().canRebase();
}
/** Can this user restore this change? */
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index a865603..db370e0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -125,6 +125,12 @@
&& canWrite();
}
+ /** @return true if this user can rebase changes on this ref */
+ public boolean canRebase() {
+ return canPerform(Permission.REBASE)
+ && canWrite();
+ }
+
/** @return true if this user can submit patch sets to this ref */
public boolean canSubmit() {
if (GitRepositoryManager.REF_CONFIG.equals(refName)) {
diff --git a/gerrit-server/src/main/java/gerrit/AbstractCommitUserIdentityPredicate.java b/gerrit-server/src/main/java/gerrit/AbstractCommitUserIdentityPredicate.java
index ac74147..606e883 100644
--- a/gerrit-server/src/main/java/gerrit/AbstractCommitUserIdentityPredicate.java
+++ b/gerrit-server/src/main/java/gerrit/AbstractCommitUserIdentityPredicate.java
@@ -27,7 +27,6 @@
import com.googlecode.prolog_cafe.lang.Term;
abstract class AbstractCommitUserIdentityPredicate extends Predicate.P3 {
- private static final long serialVersionUID = 1L;
private static final SymbolTerm user = SymbolTerm.intern("user", 1);
private static final SymbolTerm anonymous = SymbolTerm.intern("anonymous");
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java
index b32d54c..0e556f3 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java
@@ -73,6 +73,7 @@
private GitRepositoryManager repoManager;
private ReplicationQueue replication;
+ @SuppressWarnings("unchecked")
@Override
@Before
public void setUp() throws Exception {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
index 28e3c25..340db7e 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
@@ -29,13 +29,11 @@
import com.google.gerrit.reviewdb.client.AccountProjectWatch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.rules.PrologEnvironment;
import com.google.gerrit.rules.RulesCache;
import com.google.gerrit.server.AccessPath;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.ListGroupMembership;
import com.google.gerrit.server.cache.ConcurrentHashMapCache;
@@ -44,7 +42,6 @@
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.ProjectConfig;
-import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Guice;
import com.google.inject.Injector;
@@ -375,8 +372,6 @@
}
private ProjectControl user(String name, AccountGroup.UUID... memberOf) {
- SchemaFactory<ReviewDb> schema = null;
- GroupCache groupCache = null;
String canonicalWebUrl = "http://localhost";
return new ProjectControl(Collections.<AccountGroup.UUID> emptySet(),
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java
index c8e684f..93d86e5 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java
@@ -224,7 +224,7 @@
break;
} else {
expect(repoManager.list()).andReturn(
- new TreeSet<Project.NameKey>(Collections.EMPTY_LIST));
+ new TreeSet<Project.NameKey>(Collections.<Project.NameKey> emptyList()));
}
}
}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
index a814111..bc094f9 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
@@ -19,6 +19,7 @@
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
@@ -39,6 +40,7 @@
import com.google.gerrit.sshd.args4j.AccountGroupIdHandler;
import com.google.gerrit.sshd.args4j.AccountGroupUUIDHandler;
import com.google.gerrit.sshd.args4j.AccountIdHandler;
+import com.google.gerrit.sshd.args4j.ChangeIdHandler;
import com.google.gerrit.sshd.args4j.ObjectIdHandler;
import com.google.gerrit.sshd.args4j.PatchSetIdHandler;
import com.google.gerrit.sshd.args4j.ProjectControlHandler;
@@ -134,6 +136,7 @@
registerOptionHandler(Account.Id.class, AccountIdHandler.class);
registerOptionHandler(AccountGroup.Id.class, AccountGroupIdHandler.class);
registerOptionHandler(AccountGroup.UUID.class, AccountGroupUUIDHandler.class);
+ registerOptionHandler(Change.Id.class, ChangeIdHandler.class);
registerOptionHandler(ObjectId.class, ObjectIdHandler.class);
registerOptionHandler(PatchSet.Id.class, PatchSetIdHandler.class);
registerOptionHandler(ProjectControl.class, ProjectControlHandler.class);
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ChangeIdHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ChangeIdHandler.java
new file mode 100644
index 0000000..0194b91
--- /dev/null
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ChangeIdHandler.java
@@ -0,0 +1,77 @@
+// Copyright (C) 2012 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.args4j;
+
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
+
+public class ChangeIdHandler extends OptionHandler<Change.Id> {
+
+ @Inject
+ private ReviewDb db;
+
+ @Inject
+ public ChangeIdHandler(
+ final ReviewDb db,
+ @Assisted final CmdLineParser parser, @Assisted final OptionDef option,
+ @Assisted final Setter<Change.Id> setter) {
+ super(parser, option, setter);
+ this.db = db;
+ }
+
+ @Override
+ public final int parseArguments(final Parameters params)
+ throws CmdLineException {
+ final String token = params.getParameter(0);
+ final String[] tokens = token.split(",");
+ if (tokens.length != 3) {
+ throw new CmdLineException(owner, "change should be specified as "
+ + "<project>,<branch>,<change-id>");
+ }
+
+ try {
+ final Change.Key key = Change.Key.parse(tokens[2]);
+ final Project.NameKey project = new Project.NameKey(tokens[0]);
+ final Branch.NameKey branch = new Branch.NameKey(project, tokens[1]);
+ for (final Change change : db.changes().byBranchKey(branch, key)) {
+ setter.addValue(change.getId());
+ return 1;
+ }
+ } catch (IllegalArgumentException e) {
+ throw new CmdLineException(owner, "Change-Id is not valid");
+ } catch (OrmException e) {
+ throw new CmdLineException(owner, "Database error: " + e.getMessage());
+ }
+
+ throw new CmdLineException(owner, "\"" + token + "\": change not found");
+ }
+
+ @Override
+ public final String getDefaultMetaVariable() {
+ return "CHANGE";
+ }
+}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
index 74782ed..f38e17e 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
@@ -202,11 +202,11 @@
if (abandonChange) {
final ReviewResult result = abandonChangeFactory.create(
- patchSetId, changeComment).call();
+ patchSetId.getParentKey(), changeComment).call();
handleReviewResultErrors(result);
} else if (restoreChange) {
final ReviewResult result = restoreChangeFactory.create(
- patchSetId, changeComment).call();
+ patchSetId.getParentKey(), changeComment).call();
handleReviewResultErrors(result);
}
if (submitChange) {