Merge "Use 'Merge list' as display name for /MERGE_LIST"
diff --git a/.mailmap b/.mailmap
index f14afde..c35b2ec 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1,28 +1,40 @@
Adrian Görler <adrian.goerler@sap.com> Adrian Goerler <adrian.goerler@sap.com>
Ahaan Ugale <ahaanugale@gmail.com> <augale@codeaurora.org>
Alex Blewitt <alex.blewitt@gmail.com> <alex.blewitt@gs.com>
+Alex Blewitt <alex.blewitt@gmail.com> <alex.blewitt@credit-suisse.com>
Alex Ryazantsev <alex.ryazantsev@gmail.com> alex <alex.ryazantsev@gmail.com>
Alex Ryazantsev <alex.ryazantsev@gmail.com> alex.ryazantsev <alex.ryazantsev@gmail.com>
+Andrew Bonventre <andybons@chromium.org> <andybons@google.com>
Becky Siegel <beckysiegel@google.com> beckysiegel <beckysiegel@google.com>
Brad Larson <bklarson@gmail.com> <brad.larson@garmin.com>
-Bruce Zu <bruce.zu@sonymobile.com> <bruce.zu@sonyericsson.com>
+Bruce Zu <bruce.zu.run10@gmail.com> <bruce.zu@sonyericsson.com>
+Bruce Zu <bruce.zu.run10@gmail.com> <bruce.zu@sonymobile.com>
Carlos Eduardo Baldacin <carloseduardo.baldacin@sonyericsson.com> carloseduardo.baldacin <carloseduardo.baldacin@sonyericsson.com>
+Dariusz Luksza <dluksza@collab.net> <dariusz@luksza.org>
David Ostrovsky <david@ostrovsky.org> <d.ostrovsky@gmx.de>
+David Ostrovsky <david@ostrovsky.org> <david.ostrovsky@gmail.com>
+David Pursehouse <dpursehouse@collab.net> <david.pursehouse@sonymobile.com>
Deniz Türkoglu <deniz@spotify.com> Deniz Türkoglu <deniz@spotify.com>
Deniz Türkoglu <deniz@spotify.com> Deniz Turkoglu <deniz@spotify.com>
+Doug Kelly <dougk.ff7@gmail.com> <doug.kelly@garmin.com>
Edwin Kempin <ekempin@google.com> Edwin Kempin <edwin.kempin@gmail.com>
Edwin Kempin <ekempin@google.com> Edwin Kempin <edwin.kempin@sap.com>
Edwin Kempin <ekempin@google.com> ekempin <ekempin@google.com>
Eryk Szymanski <eryksz@gmail.com> <eryksz@google.com>
Fredrik Luthander <fredrik.luthander@sonymobile.com> <fredrik@gandaraj.com>
Fredrik Luthander <fredrik.luthander@sonymobile.com> <fredrik.luthander@sonyericsson.com>
-Gustaf Lundh <gustaf.lundh@sonymobile.com> <gustaf.lundh@sonyericsson.com>
+Gustaf Lundh <gustaflh@axis.com> <gustaf.lundh@axis.com>
+Gustaf Lundh <gustaflh@axis.com> <gustaf.lundh@sonyericsson.com>
+Gustaf Lundh <gustaflh@axis.com> <gustaf.lundh@sonymobile.com>
Hugo Arès <hugo.ares@ericsson.com> Hugo Ares <hugo.ares@ericsson.com>
+Jacek Centkowski <jcentkowski@collab.net> <gemincia.programs@gmail.com>
+Jacek Centkowski <jcentkowski@collab.net> <geminica.programs@gmail.com>
Jason Huntley <jhuntley@houghtonassociates.com> jhuntley <jhuntley@houghtonassociates.com>
Jiří Engelthaler <EngyCZ@gmail.com> <engycz@gmail.com>
Joe Onorato <onoratoj@gmail.com> <joeo@android.com>
Joel Dodge <dodgejoel@gmail.com> dodgejoel <dodgejoel@gmail.com>
Johan Björk <jbjoerk@gmail.com> Johan Bjork <phb@spotify.com>
+JT Olds <hello@jtolds.com> <jtolds@gmail.com>
Lincoln Oliveira Campos Do Nascimento <lincoln.oliveiracamposdonascimento@sonyericsson.com> lincoln <lincoln.oliveiracamposdonascimento@sonyericsson.com>
Luca Milanesio <luca.milanesio@gmail.com> <luca@gitent-scm.com>
Magnus Bäck <baeck@google.com> <magnus.back@sonyericsson.com>
@@ -36,12 +48,15 @@
Peter Jönsson <peter.joensson@gmail.com> Peter Jönsson <peter.joensson@gmail.com>
Rafael Rabelo Silva <rafael.rabelosilva@sonyericsson.com> rafael.rabelosilva <rafael.rabelosilva@sonyericsson.com>
Richard Möhn <richard.moehn@posteo.de> <richard.moehn@fu-berlin.de>
+Sam Saccone <samccone@google.com> <samccone@gmail.com>
Saša Živkov <sasa.zivkov@sap.com> Sasa Zivkov <sasa.zivkov@sap.com>
Saša Živkov <sasa.zivkov@sap.com> Saša Živkov <zivkov@gmail.com>
Saša Živkov <sasa.zivkov@sap.com> Sasa Zivkov <zivkov@gmail.com>
+Scott Dial <scott@scottdial.com> <geekmug@gmail.com>
Shawn Pearce <sop@google.com> Shawn O. Pearce <sop@google.com>
Sixin Li <sixin210@gmail.com> sixin li <sixin210@gmail.com>
-Sven Selberg <svense@axis.com> sven <sven.selberg@sonymobile.com>
+Sven Selberg <svense@axis.com> <sven.selberg@axis.com>
+Sven Selberg <svense@axis.com> <sven.selberg@sonymobile.com>
Tom Wang <twang10@gmail.com> Tom <twang10@gmail.com>
Tomas Westling <thomas.westling@sonyericsson.com> thomas.westling <thomas.westling@sonyericsson.com>
Ulrik Sjölin <ulrik.sjolin@sonyericsson.com> <ulrik.sjolin@gmail.com>
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 58389fd..da30264 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -4636,6 +4636,11 @@
Gets the content of a file from a certain revision.
+The optional, integer-valued `parent` parameter can be specified to request
+the named file from a parent commit of the specified revision. The value is
+the 1-based index of the parent's position in the commit object. If the
+parameter is omitted or the value is non-positive, the patch set is referenced.
+
.Request
----
GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/674ac754f91e64a0efb8087e59a176484bd534d1/files/gerrit-server%2Fsrc%2Fmain%2Fjava%2Fcom%2Fgoogle%2Fgerrit%2Fserver%2Fproject%2FRefControl.java/content HTTP/1.0
@@ -5536,6 +5541,10 @@
|`topic` |optional|The topic to which this change belongs.
|`status` |optional, default to `NEW`|
The status of the change (only `NEW` and `DRAFT` accepted here).
+|`is_private` |optional, default to `false`|
+Whether the new change should be marked as private.
+|`work_in_progress` |optional, default to `false`|
+Whether the new change should be set to work in progress.
|`base_change` |optional|
A link:#change-id[\{change-id\}] that identifies the base change for a create
change operation.
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 6345c67..6ee2b1c 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -21,6 +21,7 @@
import static com.google.gerrit.reviewdb.client.Patch.COMMIT_MSG;
import static com.google.gerrit.reviewdb.client.Patch.MERGE_LIST;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;
import static org.eclipse.jgit.lib.Constants.HEAD;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
@@ -98,6 +99,7 @@
import com.google.gerrit.server.project.Util;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
+import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.testutil.ConfigSuite;
import com.google.gerrit.testutil.FakeEmailSender;
import com.google.gerrit.testutil.FakeEmailSender.Message;
@@ -109,6 +111,7 @@
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -152,6 +155,7 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.ExpectedException;
+import org.junit.rules.RuleChain;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
@@ -163,93 +167,13 @@
private static GerritServer commonServer;
@ConfigSuite.Parameter public Config baseConfig;
-
@ConfigSuite.Name private String configName;
- @Inject protected AllProjectsName allProjects;
-
- @Inject protected AccountCreator accounts;
-
- @Inject private SchemaFactory<ReviewDb> reviewDbProvider;
-
- @Inject protected GerritApi gApi;
-
- @Inject protected AcceptanceTestRequestScope atrScope;
-
- @Inject protected AccountCache accountCache;
-
- @Inject protected IdentifiedUser.GenericFactory identifiedUserFactory;
-
- @Inject protected PushOneCommit.Factory pushFactory;
-
- @Inject protected MetaDataUpdate.Server metaDataUpdateFactory;
-
- @Inject protected ProjectCache projectCache;
-
- @Inject protected GroupCache groupCache;
-
- @Inject protected GitRepositoryManager repoManager;
-
- @Inject protected ChangeIndexer indexer;
-
- @Inject protected Provider<InternalChangeQuery> queryProvider;
-
- @Inject @CanonicalWebUrl protected Provider<String> canonicalWebUrl;
-
- @Inject @GerritServerConfig protected Config cfg;
-
- @Inject private InProcessProtocol inProcessProtocol;
-
- @Inject private Provider<AnonymousUser> anonymousUser;
-
- @Inject @GerritPersonIdent protected Provider<PersonIdent> serverIdent;
-
- @Inject protected ChangeData.Factory changeDataFactory;
-
- @Inject protected PatchSetUtil psUtil;
-
- @Inject protected ChangeFinder changeFinder;
-
- @Inject protected Revisions revisions;
-
- @Inject protected FakeEmailSender sender;
-
- @Inject protected ChangeNoteUtil changeNoteUtil;
-
- @Inject protected ChangeResource.Factory changeResourceFactory;
-
- @Inject protected SystemGroupBackend systemGroupBackend;
-
- @Inject private EventRecorder.Factory eventRecorderFactory;
-
- @Inject private ChangeIndexCollection changeIndexes;
-
- protected TestRepository<InMemoryRepository> testRepo;
- protected GerritServer server;
- protected TestAccount admin;
- protected TestAccount user;
- protected RestSession adminRestSession;
- protected RestSession userRestSession;
- protected SshSession adminSshSession;
- protected SshSession userSshSession;
- protected ReviewDb db;
- protected Project.NameKey project;
- protected EventRecorder eventRecorder;
-
- @Inject protected TestNotesMigration notesMigration;
-
- @Inject protected ChangeNotes.Factory notesFactory;
-
- @Inject protected Abandon changeAbandoner;
-
@Rule public ExpectedException exception = ExpectedException.none();
- private String resourcePrefix;
- private List<Repository> toClose;
- private boolean useSsh;
+ protected final TemporaryFolder tempSiteDir = new TemporaryFolder();
- @Rule
- public TestRule testRunner =
+ private final TestRule testRunner =
new TestRule() {
@Override
public Statement apply(final Statement base, final Description description) {
@@ -267,7 +191,58 @@
}
};
- @Rule public TemporaryFolder tempSiteDir = new TemporaryFolder();
+ @Rule public RuleChain ruleChain = RuleChain.outerRule(tempSiteDir).around(testRunner);
+
+ @Inject @CanonicalWebUrl protected Provider<String> canonicalWebUrl;
+ @Inject @GerritPersonIdent protected Provider<PersonIdent> serverIdent;
+ @Inject @GerritServerConfig protected Config cfg;
+ @Inject protected AcceptanceTestRequestScope atrScope;
+ @Inject protected AccountCache accountCache;
+ @Inject protected AccountCreator accounts;
+ @Inject protected AllProjectsName allProjects;
+ @Inject protected BatchUpdate.Factory batchUpdateFactory;
+ @Inject protected ChangeData.Factory changeDataFactory;
+ @Inject protected ChangeFinder changeFinder;
+ @Inject protected ChangeIndexer indexer;
+ @Inject protected ChangeNoteUtil changeNoteUtil;
+ @Inject protected ChangeResource.Factory changeResourceFactory;
+ @Inject protected FakeEmailSender sender;
+ @Inject protected GerritApi gApi;
+ @Inject protected GitRepositoryManager repoManager;
+ @Inject protected GroupCache groupCache;
+ @Inject protected IdentifiedUser.GenericFactory identifiedUserFactory;
+ @Inject protected MetaDataUpdate.Server metaDataUpdateFactory;
+ @Inject protected PatchSetUtil psUtil;
+ @Inject protected ProjectCache projectCache;
+ @Inject protected Provider<InternalChangeQuery> queryProvider;
+ @Inject protected PushOneCommit.Factory pushFactory;
+ @Inject protected Revisions revisions;
+ @Inject protected SystemGroupBackend systemGroupBackend;
+ @Inject protected TestNotesMigration notesMigration;
+ @Inject protected ChangeNotes.Factory notesFactory;
+ @Inject protected Abandon changeAbandoner;
+
+ protected EventRecorder eventRecorder;
+ protected GerritServer server;
+ protected Project.NameKey project;
+ protected RestSession adminRestSession;
+ protected RestSession userRestSession;
+ protected ReviewDb db;
+ protected SshSession adminSshSession;
+ protected SshSession userSshSession;
+ protected TestAccount admin;
+ protected TestAccount user;
+ protected TestRepository<InMemoryRepository> testRepo;
+
+ @Inject private ChangeIndexCollection changeIndexes;
+ @Inject private EventRecorder.Factory eventRecorderFactory;
+ @Inject private InProcessProtocol inProcessProtocol;
+ @Inject private Provider<AnonymousUser> anonymousUser;
+ @Inject private SchemaFactory<ReviewDb> reviewDbProvider;
+
+ private List<Repository> toClose;
+ private String resourcePrefix;
+ private boolean useSsh;
@Before
public void clearSender() {
@@ -1264,4 +1239,18 @@
projectsToWatch.add(pwi);
gApi.accounts().self().setWatchedProjects(projectsToWatch);
}
+
+ protected void assertContent(PushOneCommit.Result pushResult, String path, String expectedContent)
+ throws Exception {
+ BinaryResult bin =
+ gApi.changes()
+ .id(pushResult.getChangeId())
+ .revision(pushResult.getCommit().name())
+ .file(path)
+ .content();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ bin.writeTo(os);
+ String res = new String(os.toByteArray(), UTF_8);
+ assertThat(res).isEqualTo(expectedContent);
+ }
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index b32349b..a3ca832 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -82,6 +82,7 @@
import com.google.gerrit.server.util.MagicBranch;
import com.google.gerrit.testutil.ConfigSuite;
import com.google.gerrit.testutil.FakeEmailSender.Message;
+import com.google.gerrit.testutil.SshMode;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.ByteArrayOutputStream;
@@ -147,7 +148,9 @@
@After
public void removeAccountIndexEventCounter() {
- accountIndexEventCounterHandle.remove();
+ if (accountIndexEventCounterHandle != null) {
+ accountIndexEventCounterHandle.remove();
+ }
}
@Before
@@ -209,7 +212,11 @@
TestAccount foo = accounts.create("foo");
AccountInfo info = gApi.accounts().id(foo.id.get()).get();
assertThat(info.username).isEqualTo("foo");
- accountIndexedCounter.assertReindexOf(foo, 2); // account creation + adding SSH keys
+ if (SshMode.useSsh()) {
+ accountIndexedCounter.assertReindexOf(foo, 2); // account creation + adding SSH keys
+ } else {
+ accountIndexedCounter.assertReindexOf(foo, 1); // account creation
+ }
// check user branch
try (Repository repo = repoManager.openRepository(allUsers);
@@ -376,7 +383,6 @@
gApi.accounts()
.self()
.setStars(triplet, new StarsInput(ImmutableSet.of(DEFAULT_LABEL, "blue", IGNORE_LABEL)));
- accountIndexedCounter.assertNoReindex();
}
@Test
@@ -653,12 +659,13 @@
assertThat(userSelfRef).isNotNull();
assertThat(userSelfRef.getObjectId()).isEqualTo(userRef.getObjectId());
+ accountIndexedCounter.assertNoReindex();
+
// fetching user branch of another user fails
String otherUserRefName = RefNames.refsUsers(admin.id);
exception.expect(TransportException.class);
exception.expectMessage("Remote does not have " + otherUserRefName + " available for fetch.");
fetch(allUsersRepo, otherUserRefName + ":otherUserRef");
- accountIndexedCounter.assertNoReindex();
}
@Test
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 0456aa1..a4a3c04 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -145,8 +145,6 @@
public class ChangeIT extends AbstractDaemonTest {
private String systemTimeZone;
- @Inject private BatchUpdate.Factory updateFactory;
-
@Inject private DynamicSet<ChangeMessageModifier> changeMessageModifiers;
@Before
@@ -191,7 +189,7 @@
setApiUser(user);
String changeId = result.getChangeId();
- assertThat(gApi.changes().id(changeId).get().isPrivate).isFalse();
+ assertThat(gApi.changes().id(changeId).get().isPrivate).isNull();
gApi.changes().id(changeId).setPrivate(true);
ChangeInfo info = gApi.changes().id(changeId).get();
@@ -201,7 +199,7 @@
gApi.changes().id(changeId).setPrivate(false);
info = gApi.changes().id(changeId).get();
- assertThat(info.isPrivate).isFalse();
+ assertThat(info.isPrivate).isNull();
assertThat(Iterables.getLast(info.messages).message).isEqualTo("Unset private");
assertThat(Iterables.getLast(info.messages).tag).contains(ChangeMessagesUtil.TAG_UNSET_PRIVATE);
}
@@ -212,7 +210,7 @@
PushOneCommit.Result result =
pushFactory.create(db, user.getIdent(), userRepo).to("refs/for/master");
- assertThat(gApi.changes().id(result.getChangeId()).get().isPrivate).isFalse();
+ assertThat(gApi.changes().id(result.getChangeId()).get().isPrivate).isNull();
exception.expect(AuthException.class);
exception.expectMessage("not allowed to mark private");
gApi.changes().id(result.getChangeId()).setPrivate(true);
@@ -295,7 +293,7 @@
gApi.changes().id(changeId).setReadyForReview("PTAL");
info = gApi.changes().id(changeId).get();
- assertThat(info.workInProgress).isFalse();
+ assertThat(info.workInProgress).isNull();
assertThat(Iterables.getLast(info.messages).message).contains("PTAL");
assertThat(Iterables.getLast(info.messages).tag).contains(ChangeMessagesUtil.TAG_SET_READY);
@@ -311,7 +309,7 @@
gApi.changes().id(changeId).setReadyForReview();
info = gApi.changes().id(changeId).get();
- assertThat(info.workInProgress).isFalse();
+ assertThat(info.workInProgress).isNull();
assertThat(Iterables.getLast(info.messages).message).isEqualTo("Set Ready For Review");
assertThat(Iterables.getLast(info.messages).tag).contains(ChangeMessagesUtil.TAG_SET_READY);
}
@@ -368,7 +366,8 @@
List<ChangeControl> controlB = changeFinder.find(b.getChangeId(), user);
assertThat(controlB).hasSize(1);
List<ChangeControl> list = ImmutableList.of(controlA.get(0), controlB.get(0));
- changeAbandoner.batchAbandon(controlA.get(0).getProject().getNameKey(), user, list, "deadbeef");
+ changeAbandoner.batchAbandon(
+ batchUpdateFactory, controlA.get(0).getProject().getNameKey(), user, list, "deadbeef");
ChangeInfo info = get(a.getChangeId());
assertThat(info.status).isEqualTo(ChangeStatus.ABANDONED);
@@ -401,7 +400,7 @@
exception.expect(ResourceConflictException.class);
exception.expectMessage(
String.format("Project name \"%s\" doesn't match \"%s\"", project2Name, project1Name));
- changeAbandoner.batchAbandon(new Project.NameKey(project1Name), user, list);
+ changeAbandoner.batchAbandon(batchUpdateFactory, new Project.NameKey(project1Name), user, list);
}
@Test
@@ -2784,7 +2783,7 @@
private void setChangeStatus(Change.Id id, Change.Status newStatus) throws Exception {
try (BatchUpdate batchUpdate =
- updateFactory.create(db, project, atrScope.get().getUser(), TimeUtil.nowTs())) {
+ batchUpdateFactory.create(db, project, atrScope.get().getUser(), TimeUtil.nowTs())) {
batchUpdate.addOp(id, new ChangeStatusUpdateOp(newStatus));
batchUpdate.execute();
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index 3a535ba..8c0662b 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -1062,20 +1062,6 @@
return eTag;
}
- private void assertContent(PushOneCommit.Result pushResult, String path, String expectedContent)
- throws Exception {
- BinaryResult bin =
- gApi.changes()
- .id(pushResult.getChangeId())
- .revision(pushResult.getCommit().name())
- .file(path)
- .content();
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- bin.writeTo(os);
- String res = new String(os.toByteArray(), UTF_8);
- assertThat(res).isEqualTo(expectedContent);
- }
-
private void assertDiffForNewFile(
PushOneCommit.Result pushResult, String path, String expectedContentSideB) throws Exception {
DiffInfo diff =
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index 0a03125..4f4b6c6 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -929,14 +929,9 @@
PushResult pr =
GitUtil.pushHead(testRepo, "refs/for/foo%base=" + rBase.getCommit().name(), false, false);
- if (notesMigration.fuseUpdates()) {
- // InMemoryRepository's atomic BatchRefUpdate implementation doesn't update the progress
- // monitor. That's fine, we just care that there was at least one new change and no errors.
- assertThat(pr.getMessages()).contains("changes: new: 1, done");
- } else {
- assertThat(pr.getMessages()).contains("changes: new: 1, refs: 1, done");
- }
-
+ // BatchUpdate implementations differ in how they hook into progress monitors. We mostly just
+ // care that there is a new change.
+ assertThat(pr.getMessages()).containsMatch("changes: new: 1,( refs: 1)? done");
assertTwoChangesWithSameRevision(r);
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
index 2a4c188..0abdde6 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
@@ -264,20 +264,25 @@
}
@Test
- public void uploadPackSubsetOfBranchesVisibleWithEditForOtherUser() throws Exception {
+ public void uploadPackSubsetOfBranchesAndEditsVisibleWithViewPrivateChanges() throws Exception {
allow(Permission.READ, REGISTERED_USERS, "refs/heads/master");
allow(Permission.VIEW_PRIVATE_CHANGES, REGISTERED_USERS, "refs/*");
- Change c = notesFactory.createChecked(db, project, c1.getId()).getChange();
- String changeId = c.getKey().get();
+ Change change1 = notesFactory.createChecked(db, project, c1.getId()).getChange();
+ String changeId1 = change1.getKey().get();
+ Change change2 = notesFactory.createChecked(db, project, c2.getId()).getChange();
+ String changeId2 = change2.getKey().get();
- // Admin's edit is visible.
+ // Admin's edit on change1 is visible.
setApiUser(admin);
- gApi.changes().id(changeId).edit().create();
+ gApi.changes().id(changeId1).edit().create();
+
+ // Admin's edit on change2 is not visible since user cannot see the change.
+ gApi.changes().id(changeId2).edit().create();
// User's edit is visible.
setApiUser(user);
- gApi.changes().id(changeId).edit().create();
+ gApi.changes().id(changeId1).edit().create();
assertUploadPackRefs(
"HEAD",
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index 359883a..4111a3d 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -114,8 +114,6 @@
@Inject private IdentifiedUser.GenericFactory userFactory;
- @Inject private BatchUpdate.Factory updateFactory;
-
@Inject private DynamicSet<OnSubmitValidationListener> onSubmitValidationListeners;
private RegistrationHandle onSubmitValidatorHandle;
@@ -807,7 +805,7 @@
private void setChangeStatusToNew(PushOneCommit.Result... changes) throws Exception {
for (PushOneCommit.Result change : changes) {
try (BatchUpdate bu =
- updateFactory.create(db, project, userFactory.create(admin.id), TimeUtil.nowTs())) {
+ batchUpdateFactory.create(db, project, userFactory.create(admin.id), TimeUtil.nowTs())) {
bu.addOp(
change.getChange().getId(),
new BatchUpdateOp() {
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
index 146b5ca..153e70b 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
@@ -156,6 +156,20 @@
}
@Test
+ public void createNewPrivateChange() throws Exception {
+ ChangeInput input = newChangeInput(ChangeStatus.NEW);
+ input.isPrivate = true;
+ assertCreateSucceeds(input);
+ }
+
+ @Test
+ public void createNewWorkInProgressChange() throws Exception {
+ ChangeInput input = newChangeInput(ChangeStatus.NEW);
+ input.workInProgress = true;
+ assertCreateSucceeds(input);
+ }
+
+ @Test
public void noteDbCommit() throws Exception {
assume().that(notesMigration.readChanges()).isTrue();
@@ -376,6 +390,8 @@
assertThat(out.subject).isEqualTo(in.subject);
assertThat(out.topic).isEqualTo(in.topic);
assertThat(out.status).isEqualTo(in.status);
+ assertThat(out.isPrivate).isEqualTo(in.isPrivate);
+ assertThat(out.workInProgress).isEqualTo(in.workInProgress);
assertThat(out.revisions).hasSize(1);
assertThat(out.submitted).isNull();
Boolean draft = Iterables.getOnlyElement(out.revisions.values()).draft;
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftPatchSetIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftPatchSetIT.java
index 228b478..3eee3a4 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftPatchSetIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DeleteDraftPatchSetIT.java
@@ -188,6 +188,26 @@
}
@Test
+ public void deleteCurrentDraftPatchSetWhenPreviousPatchSetDoesNotExist() throws Exception {
+ PushOneCommit push = pushFactory.create(db, admin.getIdent(), testRepo);
+ String changeId = push.to("refs/for/master").getChangeId();
+ pushFactory
+ .create(db, admin.getIdent(), testRepo, PushOneCommit.SUBJECT, "b.txt", "foo", changeId)
+ .to("refs/drafts/master");
+ pushFactory
+ .create(db, admin.getIdent(), testRepo, PushOneCommit.SUBJECT, "b.txt", "bar", changeId)
+ .to("refs/drafts/master");
+
+ deletePatchSet(changeId, 2);
+ deletePatchSet(changeId, 3);
+
+ ChangeData cd = getChange(changeId);
+ assertThat(cd.patchSets()).hasSize(1);
+ assertThat(Iterables.getOnlyElement(cd.patchSets()).getId().get()).isEqualTo(1);
+ assertThat(cd.currentPatchSet().getId().get()).isEqualTo(1);
+ }
+
+ @Test
public void deleteDraftPatchSetAndPushNewDraftPatchSet() throws Exception {
String ref = "refs/drafts/master";
@@ -263,6 +283,10 @@
}
private void deletePatchSet(String changeId, PatchSet ps) throws Exception {
- gApi.changes().id(changeId).revision(ps.getId().get()).delete();
+ deletePatchSet(changeId, ps.getId().get());
+ }
+
+ private void deletePatchSet(String changeId, int ps) throws Exception {
+ gApi.changes().id(changeId).revision(ps).delete();
}
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DraftChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DraftChangeIT.java
index 26e6847..c2822ce 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DraftChangeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/DraftChangeIT.java
@@ -45,7 +45,6 @@
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.testutil.ConfigSuite;
-import com.google.inject.Inject;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
@@ -58,8 +57,6 @@
return allowDraftsDisabledConfig();
}
- @Inject private BatchUpdate.Factory updateFactory;
-
@Test
public void deleteDraftChange() throws Exception {
assume().that(isAllowDrafts()).isTrue();
@@ -244,7 +241,7 @@
private void markChangeAsDraft(Change.Id id) throws Exception {
try (BatchUpdate batchUpdate =
- updateFactory.create(db, project, atrScope.get().getUser(), TimeUtil.nowTs())) {
+ batchUpdateFactory.create(db, project, atrScope.get().getUser(), TimeUtil.nowTs())) {
batchUpdate.addOp(id, new MarkChangeAsDraftUpdateOp());
batchUpdate.execute();
}
@@ -256,7 +253,7 @@
private void setDraftStatusOfPatchSetsOfChange(Change.Id id, boolean draftStatus)
throws Exception {
try (BatchUpdate batchUpdate =
- updateFactory.create(db, project, atrScope.get().getUser(), TimeUtil.nowTs())) {
+ batchUpdateFactory.create(db, project, atrScope.get().getUser(), TimeUtil.nowTs())) {
batchUpdate.addOp(id, new DraftStatusOfPatchSetsUpdateOp(draftStatus));
batchUpdate.execute();
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/revision/BUILD b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/revision/BUILD
new file mode 100644
index 0000000..f47ac46
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/revision/BUILD
@@ -0,0 +1,7 @@
+load("//gerrit-acceptance-tests:tests.bzl", "acceptance_tests")
+
+acceptance_tests(
+ srcs = glob(["*IT.java"]),
+ group = "rest_revision",
+ labels = ["rest"],
+)
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/revision/RevisionIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/revision/RevisionIT.java
new file mode 100644
index 0000000..89fdeff
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/revision/RevisionIT.java
@@ -0,0 +1,78 @@
+// Copyright (C) 2017 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.acceptance.rest.revision;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.acceptance.PushOneCommit.FILE_CONTENT;
+import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
+import org.eclipse.jgit.util.Base64;
+import org.junit.Test;
+
+public class RevisionIT extends AbstractDaemonTest {
+ @Test
+ public void contentOfParent() throws Exception {
+ String parentContent = "parent content";
+ PushOneCommit.Result parent = createChange("Parent change", FILE_NAME, parentContent);
+ parent.assertOkStatus();
+
+ gApi.changes().id(parent.getChangeId()).current().review(ReviewInput.approve());
+ gApi.changes().id(parent.getChangeId()).current().submit();
+
+ PushOneCommit.Result child = createChange("Child change", FILE_NAME, FILE_CONTENT);
+ child.assertOkStatus();
+ assertContent(child, FILE_NAME, FILE_CONTENT);
+
+ RestResponse response =
+ adminRestSession.get(
+ "/changes/"
+ + child.getChangeId()
+ + "/revisions/current/files/"
+ + FILE_NAME
+ + "/content?parent=1");
+ response.assertOK();
+ assertThat(new String(Base64.decode(response.getEntityContent()), UTF_8))
+ .isEqualTo(parentContent);
+ }
+
+ @Test
+ public void contentOfInvalidParent() throws Exception {
+ String parentContent = "parent content";
+ PushOneCommit.Result parent = createChange("Parent change", FILE_NAME, parentContent);
+ parent.assertOkStatus();
+
+ gApi.changes().id(parent.getChangeId()).current().review(ReviewInput.approve());
+ gApi.changes().id(parent.getChangeId()).current().submit();
+
+ PushOneCommit.Result child = createChange("Child change", FILE_NAME, FILE_CONTENT);
+ child.assertOkStatus();
+ assertContent(child, FILE_NAME, FILE_CONTENT);
+
+ RestResponse response =
+ adminRestSession.get(
+ "/changes/"
+ + child.getChangeId()
+ + "/revisions/current/files/"
+ + FILE_NAME
+ + "/content?parent=10");
+ response.assertBadRequest();
+ assertThat(response.getEntityContent()).isEqualTo("invalid parent");
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/CommentsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/CommentsIT.java
index 7e95da6..26a49b1 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/CommentsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/CommentsIT.java
@@ -380,7 +380,7 @@
ChangeResource changeRsrc =
changes.get().parse(TopLevelResource.INSTANCE, IdString.fromDecoded(changeId));
RevisionResource revRsrc = revisions.parse(changeRsrc, IdString.fromDecoded(revId));
- postReview.get().apply(revRsrc, input, timestamp);
+ postReview.get().apply(batchUpdateFactory, revRsrc, input, timestamp);
Map<String, List<CommentInfo>> result = getPublishedComments(changeId, revId);
assertThat(result).isNotEmpty();
CommentInfo actual = Iterables.getOnlyElement(result.get(comment.path));
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
index 329716f..8f256be 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
@@ -79,8 +79,6 @@
@Inject private IdentifiedUser.GenericFactory userFactory;
- @Inject private BatchUpdate.Factory updateFactory;
-
@Inject private ChangeInserter.Factory changeInserterFactory;
@Inject private PatchSetInserter.Factory patchSetInserterFactory;
@@ -784,7 +782,7 @@
}
private BatchUpdate newUpdate(Account.Id owner) {
- return updateFactory.create(db, project, userFactory.create(owner), TimeUtil.nowTs());
+ return batchUpdateFactory.create(db, project, userFactory.create(owner), TimeUtil.nowTs());
}
private ChangeControl insertChange() throws Exception {
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/GetRelatedIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
index fcbad4f..e957c88 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
@@ -64,8 +64,6 @@
System.setProperty("user.timezone", systemTimeZone);
}
- @Inject private BatchUpdate.Factory updateFactory;
-
@Inject private ChangesCollection changes;
@Test
@@ -578,7 +576,7 @@
}
private void clearGroups(final PatchSet.Id psId) throws Exception {
- try (BatchUpdate bu = updateFactory.create(db, project, user(user), TimeUtil.nowTs())) {
+ try (BatchUpdate bu = batchUpdateFactory.create(db, project, user(user), TimeUtil.nowTs())) {
bu.addOp(
psId.getParentKey(),
new BatchUpdateOp() {
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
index 15b74bd..aaf01f36 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
@@ -139,8 +139,6 @@
@Inject private TestChangeRebuilderWrapper rebuilderWrapper;
- @Inject private BatchUpdate.Factory batchUpdateFactory;
-
@Inject private Sequences seq;
@Inject private ChangeBundleReader bundleReader;
@@ -754,7 +752,7 @@
assertThat(ts).isGreaterThan(c.getCreatedOn());
assertThat(ts).isLessThan(db.patchSets().get(psId).getCreatedOn());
RevisionResource revRsrc = parseCurrentRevisionResource(r.getChangeId());
- postReview.get().apply(revRsrc, rin, ts);
+ postReview.get().apply(batchUpdateFactory, revRsrc, rin, ts);
checker.rebuildAndCheckChanges(id);
}
@@ -772,7 +770,7 @@
Timestamp ts = new Timestamp(c.getCreatedOn().getTime() - 10000);
RevisionResource revRsrc = parseCurrentRevisionResource(r.getChangeId());
setApiUser(user);
- postReview.get().apply(revRsrc, rin, ts);
+ postReview.get().apply(batchUpdateFactory, revRsrc, rin, ts);
checker.rebuildAndCheckChanges(id);
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java
index 4a5d496..2c61e64 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java
@@ -20,30 +20,45 @@
import static com.google.common.truth.TruthJUnit.assume;
import static java.util.stream.Collectors.toList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Streams;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.BatchUpdateListener;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.RepoContext;
+import com.google.gerrit.server.update.RetryHelper;
import com.google.inject.Inject;
import java.io.IOException;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.lib.CommitBuilder;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevSort;
+import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;
public class NoteDbOnlyIT extends AbstractDaemonTest {
- @Inject private BatchUpdate.Factory batchUpdateFactory;
+ @Inject private RetryHelper retryHelper;
@Before
public void setUp() throws Exception {
@@ -81,7 +96,7 @@
}
};
- try (BatchUpdate bu = newBatchUpdate()) {
+ try (BatchUpdate bu = newBatchUpdate(batchUpdateFactory)) {
bu.addOp(id, backupMasterOp);
bu.execute();
}
@@ -97,7 +112,7 @@
assertThat(master2).isNotEqualTo(master1);
int msgCount = getMessages(id).size();
- try (BatchUpdate bu = newBatchUpdate()) {
+ try (BatchUpdate bu = newBatchUpdate(batchUpdateFactory)) {
// This time, we attempt to back up master, but we fail during updateChange.
bu.addOp(id, backupMasterOp);
String msg = "Change is bad";
@@ -122,9 +137,175 @@
assertThat(getMessages(id)).hasSize(msgCount);
}
- private BatchUpdate newBatchUpdate() {
- return batchUpdateFactory.create(
- db, project, identifiedUserFactory.create(user.getId()), TimeUtil.nowTs());
+ @Test
+ public void retryOnLockFailureWithAtomicUpdates() throws Exception {
+ assume().that(notesMigration.fuseUpdates()).isTrue();
+ PushOneCommit.Result r = createChange();
+ Change.Id id = r.getChange().getId();
+ String master = "refs/heads/master";
+ ObjectId initial;
+ try (Repository repo = repoManager.openRepository(project)) {
+ ((InMemoryRepository) repo).setPerformsAtomicTransactions(true);
+ initial = repo.exactRef(master).getObjectId();
+ }
+
+ AtomicInteger updateRepoCalledCount = new AtomicInteger();
+ AtomicInteger updateChangeCalledCount = new AtomicInteger();
+ AtomicInteger afterUpdateReposCalledCount = new AtomicInteger();
+
+ String result =
+ retryHelper.execute(
+ batchUpdateFactory -> {
+ try (BatchUpdate bu = newBatchUpdate(batchUpdateFactory)) {
+ bu.addOp(
+ id,
+ new UpdateRefAndAddMessageOp(updateRepoCalledCount, updateChangeCalledCount));
+ bu.execute(new ConcurrentWritingListener(afterUpdateReposCalledCount));
+ }
+ return "Done";
+ });
+
+ assertThat(result).isEqualTo("Done");
+ assertThat(updateRepoCalledCount.get()).isEqualTo(2);
+ assertThat(afterUpdateReposCalledCount.get()).isEqualTo(2);
+ assertThat(updateChangeCalledCount.get()).isEqualTo(2);
+
+ List<String> messages = getMessages(id);
+ assertThat(Iterables.getLast(messages)).isEqualTo(UpdateRefAndAddMessageOp.CHANGE_MESSAGE);
+ assertThat(Collections.frequency(messages, UpdateRefAndAddMessageOp.CHANGE_MESSAGE))
+ .isEqualTo(1);
+
+ try (Repository repo = repoManager.openRepository(project)) {
+ // Op lost the race, so the other writer's commit happened first. Then op retried and wrote
+ // its commit with the other writer's commit as parent.
+ assertThat(commitMessages(repo, initial, repo.exactRef(master).getObjectId()))
+ .containsExactly(
+ ConcurrentWritingListener.MSG_PREFIX + "1", UpdateRefAndAddMessageOp.COMMIT_MESSAGE)
+ .inOrder();
+ }
+ }
+
+ @Test
+ public void noRetryOnLockFailureWithoutAtomicUpdates() throws Exception {
+ assume().that(notesMigration.fuseUpdates()).isFalse();
+
+ PushOneCommit.Result r = createChange();
+ Change.Id id = r.getChange().getId();
+ String master = "refs/heads/master";
+ ObjectId initial;
+ try (Repository repo = repoManager.openRepository(project)) {
+ initial = repo.exactRef(master).getObjectId();
+ }
+
+ AtomicInteger updateRepoCalledCount = new AtomicInteger();
+ AtomicInteger updateChangeCalledCount = new AtomicInteger();
+ AtomicInteger afterUpdateReposCalledCount = new AtomicInteger();
+
+ try {
+ retryHelper.execute(
+ batchUpdateFactory -> {
+ try (BatchUpdate bu = newBatchUpdate(batchUpdateFactory)) {
+ bu.addOp(
+ id, new UpdateRefAndAddMessageOp(updateRepoCalledCount, updateChangeCalledCount));
+ bu.execute(new ConcurrentWritingListener(afterUpdateReposCalledCount));
+ }
+ return null;
+ });
+ assert_().fail("expected RestApiException");
+ } catch (RestApiException e) {
+ // Expected.
+ }
+
+ assertThat(updateRepoCalledCount.get()).isEqualTo(1);
+ assertThat(afterUpdateReposCalledCount.get()).isEqualTo(1);
+ assertThat(updateChangeCalledCount.get()).isEqualTo(0);
+
+ // updateChange was never called, so no message was ever added.
+ assertThat(getMessages(id)).doesNotContain(UpdateRefAndAddMessageOp.CHANGE_MESSAGE);
+
+ try (Repository repo = repoManager.openRepository(project)) {
+ // Op lost the race, so the other writer's commit happened first. Op didn't retry, because the
+ // ref updates weren't atomic, so it didn't throw LockFailureException on failure.
+ assertThat(commitMessages(repo, initial, repo.exactRef(master).getObjectId()))
+ .containsExactly(ConcurrentWritingListener.MSG_PREFIX + "1");
+ }
+ }
+
+ private class ConcurrentWritingListener implements BatchUpdateListener {
+ static final String MSG_PREFIX = "Other writer ";
+
+ private final AtomicInteger calledCount;
+
+ private ConcurrentWritingListener(AtomicInteger calledCount) {
+ this.calledCount = calledCount;
+ }
+
+ @Override
+ public void afterUpdateRepos() throws Exception {
+ // Reopen repo and update ref, to simulate a concurrent write in another
+ // thread. Only do this the first time the listener is called.
+ if (calledCount.getAndIncrement() > 0) {
+ return;
+ }
+ try (Repository repo = repoManager.openRepository(project);
+ RevWalk rw = new RevWalk(repo);
+ ObjectInserter ins = repo.newObjectInserter()) {
+ String master = "refs/heads/master";
+ ObjectId oldId = repo.exactRef(master).getObjectId();
+ ObjectId newId = newCommit(rw, ins, oldId, MSG_PREFIX + calledCount.get());
+ ins.flush();
+ RefUpdate ru = repo.updateRef(master);
+ ru.setExpectedOldObjectId(oldId);
+ ru.setNewObjectId(newId);
+ assertThat(ru.update(rw)).isEqualTo(RefUpdate.Result.FAST_FORWARD);
+ }
+ }
+ }
+
+ private class UpdateRefAndAddMessageOp implements BatchUpdateOp {
+ static final String COMMIT_MESSAGE = "A commit";
+ static final String CHANGE_MESSAGE = "A change message";
+
+ private final AtomicInteger updateRepoCalledCount;
+ private final AtomicInteger updateChangeCalledCount;
+
+ private UpdateRefAndAddMessageOp(
+ AtomicInteger updateRepoCalledCount, AtomicInteger updateChangeCalledCount) {
+ this.updateRepoCalledCount = updateRepoCalledCount;
+ this.updateChangeCalledCount = updateChangeCalledCount;
+ }
+
+ @Override
+ public void updateRepo(RepoContext ctx) throws Exception {
+ String master = "refs/heads/master";
+ ObjectId oldId = ctx.getRepoView().getRef(master).get();
+ ObjectId newId = newCommit(ctx.getRevWalk(), ctx.getInserter(), oldId, COMMIT_MESSAGE);
+ ctx.addRefUpdate(oldId, newId, master);
+ updateRepoCalledCount.incrementAndGet();
+ }
+
+ @Override
+ public boolean updateChange(ChangeContext ctx) throws Exception {
+ ctx.getUpdate(ctx.getChange().currentPatchSetId()).setChangeMessage(CHANGE_MESSAGE);
+ updateChangeCalledCount.incrementAndGet();
+ return true;
+ }
+ }
+
+ private ObjectId newCommit(RevWalk rw, ObjectInserter ins, ObjectId parent, String msg)
+ throws IOException {
+ PersonIdent ident = serverIdent.get();
+ CommitBuilder cb = new CommitBuilder();
+ cb.setParentId(parent);
+ cb.setTreeId(rw.parseCommit(parent).getTree());
+ cb.setMessage(msg);
+ cb.setAuthor(ident);
+ cb.setCommitter(ident);
+ return ins.insert(Constants.OBJ_COMMIT, cb.build());
+ }
+
+ private BatchUpdate newBatchUpdate(BatchUpdate.Factory buf) {
+ return buf.create(db, project, identifiedUserFactory.create(user.getId()), TimeUtil.nowTs());
}
private Optional<ObjectId> getRef(String name) throws Exception {
@@ -142,4 +323,15 @@
.map(m -> m.message)
.collect(toList());
}
+
+ private static List<String> commitMessages(
+ Repository repo, ObjectId fromExclusive, ObjectId toInclusive) throws Exception {
+ try (RevWalk rw = new RevWalk(repo)) {
+ rw.markStart(rw.parseCommit(toInclusive));
+ rw.markUninteresting(rw.parseCommit(fromExclusive));
+ rw.sort(RevSort.REVERSE);
+ rw.setRetainBody(true);
+ return Streams.stream(rw).map(c -> c.getShortMessage()).collect(toList());
+ }
+ }
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/NoteDbPrimaryIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/NoteDbPrimaryIT.java
index dd2e8af..d628268 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/NoteDbPrimaryIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/NoteDbPrimaryIT.java
@@ -62,7 +62,6 @@
import com.google.gerrit.server.notedb.PrimaryStorageMigrator;
import com.google.gerrit.server.notedb.TestChangeRebuilderWrapper;
import com.google.gerrit.server.project.ChangeControl;
-import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.testutil.ConfigSuite;
import com.google.gerrit.testutil.NoteDbMode;
import com.google.gerrit.testutil.TestTimeUtil;
@@ -95,7 +94,6 @@
}
@Inject private AllUsersName allUsers;
- @Inject private BatchUpdate.Factory batchUpdateFactory;
@Inject private ChangeBundleReader bundleReader;
@Inject private CommentsUtil commentsUtil;
@Inject private TestChangeRebuilderWrapper rebuilderWrapper;
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/ChangeInput.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/ChangeInput.java
index b50bcf3..1552554 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/ChangeInput.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/ChangeInput.java
@@ -27,6 +27,8 @@
public String topic;
public ChangeStatus status;
+ public Boolean isPrivate;
+ public Boolean workInProgress;
public String baseChange;
public Boolean newBranch;
public MergeInput merge;
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java
index abcfe31..9149230 100644
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java
+++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/ChangeInfo.java
@@ -142,6 +142,9 @@
public final native boolean isPrivate() /*-{ return this.is_private ? true : false; }-*/;
+ public final native boolean
+ isWorkInProgress() /*-{ return this.work_in_progress ? true : false; }-*/;
+
public final native NativeMap<LabelInfo> allLabels() /*-{ return this.labels; }-*/;
public final native LabelInfo label(String n) /*-{ return this.labels[n]; }-*/;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java
index 1e29be8..6e088c4 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java
@@ -199,6 +199,7 @@
@UiField Element statusText;
@UiField Element privateText;
+ @UiField Element wipText;
@UiField Image projectSettings;
@UiField AnchorElement projectSettingsLink;
@UiField InlineHyperlink projectDashboard;
@@ -1392,6 +1393,10 @@
privateText.setInnerText(Util.C.isPrivate());
}
+ if (info.isWorkInProgress()) {
+ wipText.setInnerText(Util.C.isWorkInProgress());
+ }
+
if (Gerrit.isSignedIn()) {
replyAction =
new ReplyAction(
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.ui.xml
index e2297cb..09bdc24 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.ui.xml
@@ -103,6 +103,10 @@
font-weight: bold;
}
+ .wipText {
+ font-weight: bold;
+ }
+
div.popdown {
display: inline-block;
margin-top: 2px;
@@ -380,7 +384,8 @@
<ui:msg>Change <g:Anchor ui:field='permalink' title='Reload the change (Shortcut: R)'>
<ui:attribute name='title'/>
</g:Anchor> - <span ui:field='statusText' class='{style.statusText}'/>
- <span ui:field='privateText' class='{style.privateText}'/></ui:msg>
+ <span ui:field='privateText' class='{style.privateText}'/>
+ <span ui:field='wipText' class='{style.wipText}'/></ui:msg>
</span>
<g:SimplePanel ui:field='headerExtension' styleName='{style.headerExtension}'/>
</div>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
index 4543217..80049df 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
@@ -35,6 +35,8 @@
String isPrivate();
+ String isWorkInProgress();
+
String changeEdit();
String myDashboardTitle();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
index 3545a2f..8a9f323 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
@@ -8,6 +8,7 @@
notCurrent = Not Current
changeEdit = Change Edit
isPrivate = (Private)
+isWorkInProgress = (WorkInProgress)
myDashboardTitle = My Reviews
unknownDashboardTitle = Code Review Dashboard
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index 3385bf2..05e1698 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -15,6 +15,7 @@
package com.google.gerrit.httpd.restapi;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS;
@@ -115,6 +116,7 @@
import com.google.gwtexpui.server.CacheHeaders;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
import com.google.inject.util.Providers;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@@ -638,40 +640,21 @@
}
private static Type inputType(RestModifyView<RestResource, Object> m) {
- Type inputType = extractInputType(m.getClass());
- if (inputType == null) {
- throw new IllegalStateException(
- String.format(
- "View %s does not correctly implement %s",
- m.getClass(), RestModifyView.class.getSimpleName()));
- }
- return inputType;
- }
+ // MyModifyView implements RestModifyView<SomeResource, MyInput>
+ TypeLiteral<?> typeLiteral = TypeLiteral.get(m.getClass());
- @SuppressWarnings("rawtypes")
- private static Type extractInputType(Class clazz) {
- for (Type t : clazz.getGenericInterfaces()) {
- if (t instanceof ParameterizedType
- && ((ParameterizedType) t).getRawType() == RestModifyView.class) {
- return ((ParameterizedType) t).getActualTypeArguments()[1];
- }
- }
+ // RestModifyView<SomeResource, MyInput>
+ // This is smart enough to resolve even when there are intervening subclasses, even if they have
+ // reordered type arguments.
+ TypeLiteral<?> supertypeLiteral = typeLiteral.getSupertype(RestModifyView.class);
- if (clazz.getSuperclass() != null) {
- Type i = extractInputType(clazz.getSuperclass());
- if (i != null) {
- return i;
- }
- }
-
- for (Class t : clazz.getInterfaces()) {
- Type i = extractInputType(t);
- if (i != null) {
- return i;
- }
- }
-
- return null;
+ Type supertype = supertypeLiteral.getType();
+ checkState(
+ supertype instanceof ParameterizedType,
+ "supertype of %s is not parameterized: %s",
+ typeLiteral,
+ supertypeLiteral);
+ return ((ParameterizedType) supertype).getActualTypeArguments()[1];
}
private Object parseRequest(HttpServletRequest req, Type type)
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ReviewProjectAccess.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ReviewProjectAccess.java
index 8ba0978..1a79d57 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ReviewProjectAccess.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ReviewProjectAccess.java
@@ -14,6 +14,7 @@
package com.google.gerrit.httpd.rpc.project;
+import com.google.common.base.Throwables;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.AccessSection;
@@ -38,7 +39,6 @@
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.RefControl;
@@ -115,6 +115,9 @@
this.updateFactory = updateFactory;
}
+ // TODO(dborowitz): Hack MetaDataUpdate so it can be created within a BatchUpdate and we can avoid
+ // calling setUpdateRef(false).
+ @SuppressWarnings("deprecation")
@Override
protected Change.Id updateProjectConfig(
ProjectControl projectControl,
@@ -175,13 +178,10 @@
AddReviewerInput input = new AddReviewerInput();
input.reviewer = projectOwners;
reviewersProvider.get().apply(rsrc, input);
- } catch (IOException
- | OrmException
- | RestApiException
- | UpdateException
- | PermissionBackendException e) {
+ } catch (Exception e) {
// one of the owner groups is not visible to the user and this it why it
// can't be added as reviewer
+ Throwables.throwIfUnchecked(e);
}
}
@@ -198,12 +198,9 @@
AddReviewerInput input = new AddReviewerInput();
input.reviewer = r.getGroup().getUUID().get();
reviewersProvider.get().apply(rsrc, input);
- } catch (IOException
- | OrmException
- | RestApiException
- | UpdateException
- | PermissionBackendException e) {
+ } catch (Exception e) {
// ignore
+ Throwables.throwIfUnchecked(e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ReviewersUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ReviewersUtil.java
index 7b4777e..08f879f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ReviewersUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ReviewersUtil.java
@@ -53,7 +53,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -65,6 +64,7 @@
final Timer0 recommendAccountsLatency;
final Timer0 loadAccountsLatency;
final Timer0 queryGroupsLatency;
+ final Timer0 filterVisibility;
@Inject
Metrics(MetricMaker metricMaker) {
@@ -92,12 +92,18 @@
new Description("Latency for querying groups for reviewer suggestion")
.setCumulative()
.setUnit(Units.MILLISECONDS));
+ filterVisibility =
+ metricMaker.newTimer(
+ "reviewer_suggestion/filter_visibility",
+ new Description("Latency for removing users that can't see the change")
+ .setCumulative()
+ .setUnit(Units.MILLISECONDS));
}
}
// Generate a candidate list at 3x the size of what the user wants to see to
// give the ranking algorithm a good set of candidates it can work with
- private static final int CANDIDATE_LIST_MULTIPLIER = 3;
+ private static final int CANDIDATE_LIST_MULTIPLIER = 2;
private final AccountLoader accountLoader;
private final AccountQueryBuilder accountQueryBuilder;
@@ -150,13 +156,26 @@
List<Account.Id> candidateList = new ArrayList<>();
if (!Strings.isNullOrEmpty(query)) {
- candidateList = suggestAccounts(suggestReviewers, visibilityControl);
+ candidateList = suggestAccounts(suggestReviewers);
}
List<Account.Id> sortedRecommendations =
recommendAccounts(changeNotes, suggestReviewers, projectControl, candidateList);
- List<SuggestedReviewerInfo> suggestedReviewer = loadAccounts(sortedRecommendations);
+ // Filter accounts by visibility and enforce limit
+ List<Account.Id> filteredRecommendations = new ArrayList<>();
+ try (Timer0.Context ctx = metrics.filterVisibility.start()) {
+ for (Account.Id reviewer : sortedRecommendations) {
+ if (filteredRecommendations.size() >= limit) {
+ break;
+ }
+ if (visibilityControl.isVisibleTo(reviewer)) {
+ filteredRecommendations.add(reviewer);
+ }
+ }
+ }
+
+ List<SuggestedReviewerInfo> suggestedReviewer = loadAccounts(filteredRecommendations);
if (!excludeGroups && suggestedReviewer.size() < limit && !Strings.isNullOrEmpty(query)) {
// Add groups at the end as individual accounts are usually more
// important.
@@ -174,22 +193,14 @@
return suggestedReviewer.subList(0, limit);
}
- private List<Account.Id> suggestAccounts(
- SuggestReviewers suggestReviewers, VisibilityControl visibilityControl) throws OrmException {
+ private List<Account.Id> suggestAccounts(SuggestReviewers suggestReviewers) throws OrmException {
try (Timer0.Context ctx = metrics.queryAccountsLatency.start()) {
try {
- Set<Account.Id> matches = new HashSet<>();
QueryResult<AccountState> result =
accountQueryProcessor
.setLimit(suggestReviewers.getLimit() * CANDIDATE_LIST_MULTIPLIER)
.query(accountQueryBuilder.defaultQuery(suggestReviewers.getQuery()));
- for (AccountState accountState : result.entities()) {
- Account.Id id = accountState.getAccount().getId();
- if (visibilityControl.isVisibleTo(id)) {
- matches.add(id);
- }
- }
- return new ArrayList<>(matches);
+ return result.entities().stream().map(a -> a.getAccount().getId()).collect(toList());
} catch (QueryParseException e) {
return ImmutableList.of();
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/ApiUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/ApiUtil.java
new file mode 100644
index 0000000..c5b8b12
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/ApiUtil.java
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 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.api;
+
+import com.google.common.base.Throwables;
+import com.google.gerrit.extensions.restapi.RestApiException;
+
+/** Static utilities for API implementations. */
+public class ApiUtil {
+ /**
+ * Convert an exception encountered during API execution to a {@link RestApiException}.
+ *
+ * @param msg message to be used in the case where a new {@code RestApiException} is wrapped
+ * around {@code e}.
+ * @param e exception being handled.
+ * @return {@code e} if it is already a {@code RestApiException}, otherwise a new {@code
+ * RestApiException} wrapped around {@code e}.
+ * @throws RuntimeException if {@code e} is a runtime exception, it is rethrown as-is.
+ */
+ public static RestApiException asRestApiException(String msg, Exception e)
+ throws RuntimeException {
+ Throwables.throwIfUnchecked(e);
+ return e instanceof RestApiException ? (RestApiException) e : new RestApiException(msg, e);
+ }
+
+ private ApiUtil() {}
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java
index 6604496..64760a65 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java
@@ -14,10 +14,10 @@
package com.google.gerrit.server.api.accounts;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.gerrit.common.RawInputUtil;
-import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.accounts.AccountApi;
import com.google.gerrit.extensions.api.accounts.EmailInput;
import com.google.gerrit.extensions.api.accounts.GpgKeyApi;
@@ -38,7 +38,6 @@
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.TopLevelResource;
-import com.google.gerrit.server.GpgException;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.account.AddSshKey;
@@ -71,15 +70,11 @@
import com.google.gerrit.server.account.Stars;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.ChangesCollection;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
-import org.eclipse.jgit.errors.ConfigInvalidException;
public class AccountApiImpl implements AccountApi {
interface Factory {
@@ -203,8 +198,8 @@
AccountInfo ai = accountLoader.get(account.getUser().getAccountId());
accountLoader.fill();
return ai;
- } catch (OrmException e) {
- throw new RestApiException("Cannot parse change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot parse change", e);
}
}
@@ -222,8 +217,8 @@
} else {
deleteActive.apply(account, new DeleteActive.Input());
}
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot set active", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set active", e);
}
}
@@ -237,8 +232,8 @@
public GeneralPreferencesInfo getPreferences() throws RestApiException {
try {
return getPreferences.apply(account);
- } catch (PermissionBackendException e) {
- throw new RestApiException("Cannot get preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get preferences", e);
}
}
@@ -246,8 +241,8 @@
public GeneralPreferencesInfo setPreferences(GeneralPreferencesInfo in) throws RestApiException {
try {
return setPreferences.apply(account, in);
- } catch (IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot set preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set preferences", e);
}
}
@@ -255,8 +250,8 @@
public DiffPreferencesInfo getDiffPreferences() throws RestApiException {
try {
return getDiffPreferences.apply(account);
- } catch (IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot query diff preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot query diff preferences", e);
}
}
@@ -264,8 +259,8 @@
public DiffPreferencesInfo setDiffPreferences(DiffPreferencesInfo in) throws RestApiException {
try {
return setDiffPreferences.apply(account, in);
- } catch (IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot set diff preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set diff preferences", e);
}
}
@@ -273,8 +268,8 @@
public EditPreferencesInfo getEditPreferences() throws RestApiException {
try {
return getEditPreferences.apply(account);
- } catch (IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot query edit preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot query edit preferences", e);
}
}
@@ -282,8 +277,8 @@
public EditPreferencesInfo setEditPreferences(EditPreferencesInfo in) throws RestApiException {
try {
return setEditPreferences.apply(account, in);
- } catch (IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot set edit preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set edit preferences", e);
}
}
@@ -291,8 +286,8 @@
public List<ProjectWatchInfo> getWatchedProjects() throws RestApiException {
try {
return getWatchedProjects.apply(account);
- } catch (OrmException | IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot get watched projects", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get watched projects", e);
}
}
@@ -301,8 +296,8 @@
throws RestApiException {
try {
return postWatchedProjects.apply(account, in);
- } catch (OrmException | IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot update watched projects", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot update watched projects", e);
}
}
@@ -310,8 +305,8 @@
public void deleteWatchedProjects(List<ProjectWatchInfo> in) throws RestApiException {
try {
deleteWatchedProjects.apply(account, in);
- } catch (OrmException | IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot delete watched projects", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete watched projects", e);
}
}
@@ -321,8 +316,8 @@
ChangeResource rsrc = changes.parse(TopLevelResource.INSTANCE, IdString.fromUrl(changeId));
starredChangesCreate.setChange(rsrc);
starredChangesCreate.apply(account, new StarredChanges.EmptyInput());
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot star change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot star change", e);
}
}
@@ -333,8 +328,8 @@
AccountResource.StarredChange starredChange =
new AccountResource.StarredChange(account.getUser(), rsrc);
starredChangesDelete.apply(starredChange, new StarredChanges.EmptyInput());
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot unstar change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot unstar change", e);
}
}
@@ -343,8 +338,8 @@
try {
AccountResource.Star rsrc = stars.parse(account, IdString.fromUrl(changeId));
starsPost.apply(rsrc, input);
- } catch (OrmException e) {
- throw new RestApiException("Cannot post stars", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot post stars", e);
}
}
@@ -353,8 +348,8 @@
try {
AccountResource.Star rsrc = stars.parse(account, IdString.fromUrl(changeId));
return starsGet.apply(rsrc);
- } catch (OrmException e) {
- throw new RestApiException("Cannot get stars", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get stars", e);
}
}
@@ -362,8 +357,8 @@
public List<ChangeInfo> getStarredChanges() throws RestApiException {
try {
return stars.list().apply(account);
- } catch (OrmException e) {
- throw new RestApiException("Cannot get starred changes", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get starred changes", e);
}
}
@@ -377,12 +372,8 @@
AccountResource.Email rsrc = new AccountResource.Email(account.getUser(), input.email);
try {
createEmailFactory.create(input.email).apply(rsrc, input);
- } catch (EmailException
- | OrmException
- | IOException
- | ConfigInvalidException
- | PermissionBackendException e) {
- throw new RestApiException("Cannot add email", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot add email", e);
}
}
@@ -391,8 +382,8 @@
AccountResource.Email rsrc = new AccountResource.Email(account.getUser(), email);
try {
deleteEmail.apply(rsrc, null);
- } catch (OrmException | IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot delete email", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete email", e);
}
}
@@ -401,8 +392,8 @@
PutStatus.Input in = new PutStatus.Input(status);
try {
putStatus.apply(account, in);
- } catch (OrmException | IOException | PermissionBackendException e) {
- throw new RestApiException("Cannot set status", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set status", e);
}
}
@@ -410,8 +401,8 @@
public List<SshKeyInfo> listSshKeys() throws RestApiException {
try {
return getSshKeys.apply(account);
- } catch (OrmException | IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot list SSH keys", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list SSH keys", e);
}
}
@@ -421,8 +412,8 @@
in.raw = RawInputUtil.create(key);
try {
return addSshKey.apply(account, in).value();
- } catch (OrmException | IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot add SSH key", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot add SSH key", e);
}
}
@@ -432,8 +423,8 @@
AccountResource.SshKey sshKeyRes =
sshKeys.parse(account, IdString.fromDecoded(Integer.toString(seq)));
deleteSshKey.apply(sshKeyRes, null);
- } catch (OrmException | IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot delete SSH key", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete SSH key", e);
}
}
@@ -441,8 +432,8 @@
public Map<String, GpgKeyInfo> listGpgKeys() throws RestApiException {
try {
return gpgApiAdapter.listGpgKeys(account);
- } catch (GpgException e) {
- throw new RestApiException("Cannot list GPG keys", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list GPG keys", e);
}
}
@@ -451,8 +442,8 @@
throws RestApiException {
try {
return gpgApiAdapter.putGpgKeys(account, add, delete);
- } catch (GpgException e) {
- throw new RestApiException("Cannot add GPG key", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot add GPG key", e);
}
}
@@ -460,8 +451,8 @@
public GpgKeyApi gpgKey(String id) throws RestApiException {
try {
return gpgApiAdapter.gpgKey(account, IdString.fromDecoded(id));
- } catch (GpgException e) {
- throw new RestApiException("Cannot get PGP key", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get PGP key", e);
}
}
@@ -476,8 +467,8 @@
AgreementInput input = new AgreementInput();
input.name = agreementName;
putAgreement.apply(account, input);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot sign agreement", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot sign agreement", e);
}
}
@@ -485,8 +476,8 @@
public void index() throws RestApiException {
try {
index.apply(account, new Index.Input());
- } catch (IOException | PermissionBackendException e) {
- throw new RestApiException("Cannot index account", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot index account", e);
}
}
@@ -494,8 +485,8 @@
public List<AccountExternalIdInfo> getExternalIds() throws RestApiException {
try {
return getExternalIds.apply(account);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot get external IDs", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get external IDs", e);
}
}
@@ -503,8 +494,8 @@
public void deleteExternalIds(List<String> externalIds) throws RestApiException {
try {
deleteExternalIds.apply(account, externalIds);
- } catch (IOException | OrmException | ConfigInvalidException e) {
- throw new RestApiException("Cannot delete external IDs", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete external IDs", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java
index bade8ce..5257aec 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.api.accounts;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
import com.google.gerrit.extensions.api.accounts.AccountApi;
import com.google.gerrit.extensions.api.accounts.AccountInput;
@@ -33,14 +34,10 @@
import com.google.gerrit.server.account.QueryAccounts;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
-import java.io.IOException;
import java.util.List;
-import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class AccountsImpl implements Accounts {
@@ -71,8 +68,8 @@
public AccountApi id(String id) throws RestApiException {
try {
return api.create(accounts.parse(TopLevelResource.INSTANCE, IdString.fromDecoded(id)));
- } catch (OrmException e) {
- throw new RestApiException("Cannot parse change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot parse change", e);
}
}
@@ -106,8 +103,8 @@
permissionBackend.user(self).checkAny(GlobalPermission.fromAnnotation(impl.getClass()));
AccountInfo info = impl.apply(TopLevelResource.INSTANCE, in).value();
return id(info._accountId);
- } catch (OrmException | IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot create account " + in.username, e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot create account " + in.username, e);
}
}
@@ -133,8 +130,8 @@
myQueryAccounts.setQuery(r.getQuery());
myQueryAccounts.setLimit(r.getLimit());
return myQueryAccounts.apply(TopLevelResource.INSTANCE);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve suggested accounts", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve suggested accounts", e);
}
}
@@ -163,8 +160,8 @@
myQueryAccounts.addOption(option);
}
return myQueryAccounts.apply(TopLevelResource.INSTANCE);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve suggested accounts", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve suggested accounts", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
index f75adbc..5338e89 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
@@ -14,7 +14,8 @@
package com.google.gerrit.server.api.changes;
-import com.google.gerrit.common.errors.EmailException;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.changes.AbandonInput;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.AddReviewerResult;
@@ -82,14 +83,9 @@
import com.google.gerrit.server.change.Unignore;
import com.google.gerrit.server.change.Unmute;
import com.google.gerrit.server.change.WorkInProgressOp;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.InvalidChangeOperationException;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
@@ -247,8 +243,8 @@
public RevisionApi revision(String id) throws RestApiException {
try {
return revisionApi.create(revisions.parse(change, IdString.fromDecoded(id)));
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot parse revision", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot parse revision", e);
}
}
@@ -256,8 +252,8 @@
public ReviewerApi reviewer(String id) throws RestApiException {
try {
return reviewerApi.create(reviewers.parse(change, IdString.fromDecoded(id)));
- } catch (OrmException e) {
- throw new RestApiException("Cannot parse reviewer", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot parse reviewer", e);
}
}
@@ -270,8 +266,8 @@
public void abandon(AbandonInput in) throws RestApiException {
try {
abandon.apply(change, in);
- } catch (OrmException | UpdateException | PermissionBackendException e) {
- throw new RestApiException("Cannot abandon change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot abandon change", e);
}
}
@@ -284,8 +280,8 @@
public void restore(RestoreInput in) throws RestApiException {
try {
restore.apply(change, in);
- } catch (OrmException | UpdateException | PermissionBackendException e) {
- throw new RestApiException("Cannot restore change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot restore change", e);
}
}
@@ -300,8 +296,8 @@
public void move(MoveInput in) throws RestApiException {
try {
move.apply(change, in);
- } catch (OrmException | UpdateException e) {
- throw new RestApiException("Cannot move change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot move change", e);
}
}
@@ -313,8 +309,8 @@
} else {
deletePrivate.apply(change, null);
}
- } catch (UpdateException e) {
- throw new RestApiException("Cannot change private status", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot change private status", e);
}
}
@@ -322,8 +318,8 @@
public void setWorkInProgress(String message) throws RestApiException {
try {
setWip.apply(change, new WorkInProgressOp.Input(message));
- } catch (UpdateException e) {
- throw new RestApiException("Cannot set work in progress state", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set work in progress state", e);
}
}
@@ -331,8 +327,8 @@
public void setReadyForReview(String message) throws RestApiException {
try {
setReady.apply(change, new WorkInProgressOp.Input(message));
- } catch (UpdateException e) {
- throw new RestApiException("Cannot set ready for review state", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set ready for review state", e);
}
}
@@ -345,8 +341,8 @@
public ChangeApi revert(RevertInput in) throws RestApiException {
try {
return changeApi.id(revert.apply(change, in)._number);
- } catch (OrmException | IOException | UpdateException e) {
- throw new RestApiException("Cannot revert change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot revert change", e);
}
}
@@ -354,8 +350,8 @@
public ChangeInfo createMergePatchSet(MergePatchSetInput in) throws RestApiException {
try {
return updateByMerge.apply(change, in).value();
- } catch (IOException | UpdateException | InvalidChangeOperationException | OrmException e) {
- throw new RestApiException("Cannot update change by merge", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot update change by merge", e);
}
}
@@ -383,8 +379,8 @@
.addListChangesOption(listOptions)
.addSubmittedTogetherOption(submitOptions)
.applyInfo(change);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot query submittedTogether", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot query submittedTogether", e);
}
}
@@ -392,8 +388,8 @@
public void publish() throws RestApiException {
try {
publishDraftChange.apply(change, null);
- } catch (UpdateException e) {
- throw new RestApiException("Cannot publish change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot publish change", e);
}
}
@@ -406,12 +402,8 @@
public void rebase(RebaseInput in) throws RestApiException {
try {
rebase.apply(change, in);
- } catch (EmailException
- | OrmException
- | UpdateException
- | IOException
- | PermissionBackendException e) {
- throw new RestApiException("Cannot rebase change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot rebase change", e);
}
}
@@ -419,8 +411,8 @@
public void delete() throws RestApiException {
try {
deleteChange.apply(change, null);
- } catch (UpdateException | PermissionBackendException e) {
- throw new RestApiException("Cannot delete change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete change", e);
}
}
@@ -435,8 +427,8 @@
in.topic = topic;
try {
putTopic.apply(change, in);
- } catch (UpdateException | PermissionBackendException e) {
- throw new RestApiException("Cannot set topic", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set topic", e);
}
}
@@ -444,8 +436,8 @@
public IncludedInInfo includedIn() throws RestApiException {
try {
return includedIn.apply(change);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Could not extract IncludedIn data", e);
+ } catch (Exception e) {
+ throw asRestApiException("Could not extract IncludedIn data", e);
}
}
@@ -460,8 +452,8 @@
public AddReviewerResult addReviewer(AddReviewerInput in) throws RestApiException {
try {
return postReviewers.apply(change, in);
- } catch (OrmException | IOException | UpdateException | PermissionBackendException e) {
- throw new RestApiException("Cannot add change reviewer", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot add change reviewer", e);
}
}
@@ -486,8 +478,8 @@
suggestReviewers.setQuery(r.getQuery());
suggestReviewers.setLimit(r.getLimit());
return suggestReviewers.apply(change);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot retrieve suggested reviewers", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve suggested reviewers", e);
}
}
@@ -495,8 +487,8 @@
public ChangeInfo get(EnumSet<ListChangesOption> s) throws RestApiException {
try {
return changeJson.create(s).format(change);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve change", e);
}
}
@@ -524,8 +516,8 @@
public void setHashtags(HashtagsInput input) throws RestApiException {
try {
postHashtags.apply(change, input);
- } catch (UpdateException | PermissionBackendException e) {
- throw new RestApiException("Cannot post hashtags", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot post hashtags", e);
}
}
@@ -533,8 +525,8 @@
public Set<String> getHashtags() throws RestApiException {
try {
return getHashtags.apply(change).value();
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot get hashtags", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get hashtags", e);
}
}
@@ -542,8 +534,8 @@
public AccountInfo setAssignee(AssigneeInput input) throws RestApiException {
try {
return putAssignee.apply(change, input);
- } catch (UpdateException | IOException | OrmException | PermissionBackendException e) {
- throw new RestApiException("Cannot set assignee", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set assignee", e);
}
}
@@ -552,8 +544,8 @@
try {
Response<AccountInfo> r = getAssignee.apply(change);
return r.isNone() ? null : r.value();
- } catch (OrmException e) {
- throw new RestApiException("Cannot get assignee", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get assignee", e);
}
}
@@ -561,8 +553,8 @@
public List<AccountInfo> getPastAssignees() throws RestApiException {
try {
return getPastAssignees.apply(change).value();
- } catch (OrmException e) {
- throw new RestApiException("Cannot get past assignees", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get past assignees", e);
}
}
@@ -571,8 +563,8 @@
try {
Response<AccountInfo> r = deleteAssignee.apply(change, null);
return r.isNone() ? null : r.value();
- } catch (UpdateException | OrmException | PermissionBackendException e) {
- throw new RestApiException("Cannot delete assignee", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete assignee", e);
}
}
@@ -580,8 +572,8 @@
public Map<String, List<CommentInfo>> comments() throws RestApiException {
try {
return listComments.apply(change);
- } catch (OrmException e) {
- throw new RestApiException("Cannot get comments", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get comments", e);
}
}
@@ -589,8 +581,8 @@
public Map<String, List<RobotCommentInfo>> robotComments() throws RestApiException {
try {
return listChangeRobotComments.apply(change);
- } catch (OrmException e) {
- throw new RestApiException("Cannot get robot comments", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get robot comments", e);
}
}
@@ -598,8 +590,8 @@
public Map<String, List<CommentInfo>> drafts() throws RestApiException {
try {
return listDrafts.apply(change);
- } catch (OrmException e) {
- throw new RestApiException("Cannot get drafts", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get drafts", e);
}
}
@@ -607,17 +599,19 @@
public ChangeInfo check() throws RestApiException {
try {
return check.apply(change).value();
- } catch (OrmException e) {
- throw new RestApiException("Cannot check change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot check change", e);
}
}
@Override
public ChangeInfo check(FixInput fix) throws RestApiException {
try {
+ // TODO(dborowitz): Convert to RetryingRestModifyView. Needs to plumb BatchUpdate.Factory into
+ // ConsistencyChecker.
return check.apply(change, fix).value();
- } catch (OrmException | PermissionBackendException e) {
- throw new RestApiException("Cannot check change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot check change", e);
}
}
@@ -625,13 +619,15 @@
public void index() throws RestApiException {
try {
index.apply(change, new Index.Input());
- } catch (IOException | OrmException | PermissionBackendException e) {
- throw new RestApiException("Cannot index change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot index change", e);
}
}
@Override
public void ignore(boolean ignore) throws RestApiException {
+ // TODO(dborowitz): Convert to RetryingRestModifyView. Needs to plumb BatchUpdate.Factory into
+ // StarredChangesUtil.
if (ignore) {
this.ignore.apply(change, new Ignore.Input());
} else {
@@ -641,6 +637,8 @@
@Override
public void mute(boolean mute) throws RestApiException {
+ // TODO(dborowitz): Convert to RetryingRestModifyView. Needs to plumb BatchUpdate.Factory into
+ // StarredChangesUtil.
if (mute) {
this.mute.apply(change, new Mute.Input());
} else {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeEditApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeEditApiImpl.java
index 80d5071..5184e89 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeEditApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeEditApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.changes;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.changes.ChangeEditApi;
import com.google.gerrit.extensions.api.changes.PublishChangeEditInput;
import com.google.gerrit.extensions.common.EditInfo;
@@ -30,7 +32,6 @@
import com.google.gerrit.server.change.DeleteChangeEdit;
import com.google.gerrit.server.change.PublishChangeEdit;
import com.google.gerrit.server.change.RebaseChangeEdit;
-import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -88,8 +89,8 @@
try {
Response<EditInfo> edit = editDetail.apply(changeResource);
return edit.isNone() ? Optional.empty() : Optional.of(edit.value());
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot retrieve change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve change edit", e);
}
}
@@ -97,8 +98,8 @@
public void create() throws RestApiException {
try {
changeEditsPost.apply(changeResource, null);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot create change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot create change edit", e);
}
}
@@ -106,8 +107,8 @@
public void delete() throws RestApiException {
try {
deleteChangeEdit.apply(changeResource, new DeleteChangeEdit.Input());
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot delete change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete change edit", e);
}
}
@@ -115,8 +116,8 @@
public void rebase() throws RestApiException {
try {
rebaseChangeEdit.apply(changeResource, null);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot rebase change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot rebase change edit", e);
}
}
@@ -129,8 +130,8 @@
public void publish(PublishChangeEditInput publishChangeEditInput) throws RestApiException {
try {
publishChangeEdit.apply(changeResource, publishChangeEditInput);
- } catch (IOException | OrmException | UpdateException e) {
- throw new RestApiException("Cannot publish change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot publish change edit", e);
}
}
@@ -140,8 +141,8 @@
ChangeEditResource changeEditResource = getChangeEditResource(filePath);
Response<BinaryResult> fileResponse = changeEditsGet.apply(changeEditResource);
return fileResponse.isNone() ? Optional.empty() : Optional.of(fileResponse.value());
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot retrieve file of change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve file of change edit", e);
}
}
@@ -152,8 +153,8 @@
renameInput.oldPath = oldFilePath;
renameInput.newPath = newFilePath;
changeEditsPost.apply(changeResource, renameInput);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot rename file of change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot rename file of change edit", e);
}
}
@@ -163,8 +164,8 @@
ChangeEdits.Post.Input restoreInput = new ChangeEdits.Post.Input();
restoreInput.restorePath = filePath;
changeEditsPost.apply(changeResource, restoreInput);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot restore file of change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot restore file of change edit", e);
}
}
@@ -172,8 +173,8 @@
public void modifyFile(String filePath, RawInput newContent) throws RestApiException {
try {
changeEditsPut.apply(changeResource.getControl(), filePath, newContent);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot modify file of change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot modify file of change edit", e);
}
}
@@ -181,8 +182,8 @@
public void deleteFile(String filePath) throws RestApiException {
try {
changeEditDeleteContent.apply(changeResource.getControl(), filePath);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot delete file of change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete file of change edit", e);
}
}
@@ -192,8 +193,8 @@
try (BinaryResult binaryResult = getChangeEditCommitMessage.apply(changeResource)) {
return binaryResult.asString();
}
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot get commit message of change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get commit message of change edit", e);
}
}
@@ -203,8 +204,8 @@
input.message = newCommitMessage;
try {
modifyChangeEditCommitMessage.apply(changeResource, input);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot modify commit message of change edit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot modify commit message of change edit", e);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangesImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangesImpl.java
index 9a89d48..b800655 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangesImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangesImpl.java
@@ -16,6 +16,7 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
@@ -24,7 +25,6 @@
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeInput;
-import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.TopLevelResource;
@@ -32,15 +32,10 @@
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.change.ChangesCollection;
import com.google.gerrit.server.change.CreateChange;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.query.change.QueryChanges;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
-import java.io.IOException;
import java.util.List;
@Singleton
@@ -78,8 +73,8 @@
public ChangeApi id(String id) throws RestApiException {
try {
return api.create(changes.parse(TopLevelResource.INSTANCE, IdString.fromUrl(id)));
- } catch (OrmException e) {
- throw new RestApiException("Cannot parse change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot parse change", e);
}
}
@@ -88,12 +83,8 @@
try {
ChangeInfo out = createChange.apply(TopLevelResource.INSTANCE, in).value();
return api.create(changes.parse(new Change.Id(out._number)));
- } catch (OrmException
- | IOException
- | InvalidChangeOperationException
- | UpdateException
- | PermissionBackendException e) {
- throw new RestApiException("Cannot create change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot create change", e);
}
}
@@ -137,8 +128,8 @@
List<ChangeInfo> infos = (List<ChangeInfo>) result;
return ImmutableList.copyOf(infos);
- } catch (AuthException | OrmException e) {
- throw new RestApiException("Cannot query changes", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot query changes", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/CommentApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/CommentApiImpl.java
index 5c61e23..243833a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/CommentApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/CommentApiImpl.java
@@ -14,12 +14,13 @@
package com.google.gerrit.server.api.changes;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.changes.CommentApi;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.change.CommentResource;
import com.google.gerrit.server.change.GetComment;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -41,8 +42,8 @@
public CommentInfo get() throws RestApiException {
try {
return getComment.apply(comment);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve comment", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve comment", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/DraftApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/DraftApiImpl.java
index 1bd9216..2daf1dc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/DraftApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/DraftApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.changes;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.changes.DraftApi;
import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.common.CommentInfo;
@@ -22,8 +24,6 @@
import com.google.gerrit.server.change.DraftCommentResource;
import com.google.gerrit.server.change.GetDraftComment;
import com.google.gerrit.server.change.PutDraftComment;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -53,8 +53,8 @@
public CommentInfo get() throws RestApiException {
try {
return getDraft.apply(draft);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve draft", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve draft", e);
}
}
@@ -62,8 +62,8 @@
public CommentInfo update(DraftInput in) throws RestApiException {
try {
return putDraft.apply(draft, in).value();
- } catch (UpdateException | OrmException e) {
- throw new RestApiException("Cannot update draft", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot update draft", e);
}
}
@@ -71,8 +71,8 @@
public void delete() throws RestApiException {
try {
deleteDraft.apply(draft, null);
- } catch (UpdateException e) {
- throw new RestApiException("Cannot delete draft", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete draft", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/FileApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/FileApiImpl.java
index aa66e7b..f0a934f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/FileApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/FileApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.changes;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.changes.FileApi;
import com.google.gerrit.extensions.common.DiffInfo;
import com.google.gerrit.extensions.restapi.BinaryResult;
@@ -21,11 +23,8 @@
import com.google.gerrit.server.change.FileResource;
import com.google.gerrit.server.change.GetContent;
import com.google.gerrit.server.change.GetDiff;
-import com.google.gerrit.server.project.InvalidChangeOperationException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
class FileApiImpl implements FileApi {
interface Factory {
@@ -47,8 +46,8 @@
public BinaryResult content() throws RestApiException {
try {
return getContent.apply(file);
- } catch (IOException | OrmException e) {
- throw new RestApiException("Cannot retrieve file content", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve file content", e);
}
}
@@ -56,8 +55,8 @@
public DiffInfo diff() throws RestApiException {
try {
return getDiff.apply(file).value();
- } catch (IOException | InvalidChangeOperationException | OrmException e) {
- throw new RestApiException("Cannot retrieve diff", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve diff", e);
}
}
@@ -65,8 +64,8 @@
public DiffInfo diff(String base) throws RestApiException {
try {
return getDiff.setBase(base).apply(file).value();
- } catch (IOException | InvalidChangeOperationException | OrmException e) {
- throw new RestApiException("Cannot retrieve diff", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve diff", e);
}
}
@@ -74,8 +73,8 @@
public DiffInfo diff(int parent) throws RestApiException {
try {
return getDiff.setParent(parent).apply(file).value();
- } catch (OrmException | InvalidChangeOperationException | IOException e) {
- throw new RestApiException("Cannot retrieve diff", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve diff", e);
}
}
@@ -104,8 +103,8 @@
}
try {
return getDiff.apply(file).value();
- } catch (IOException | InvalidChangeOperationException | OrmException e) {
- throw new RestApiException("Cannot retrieve diff", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve diff", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ReviewerApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ReviewerApiImpl.java
index 8ac874a..2f8b7d8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ReviewerApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ReviewerApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.changes;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.changes.DeleteReviewerInput;
import com.google.gerrit.extensions.api.changes.DeleteVoteInput;
import com.google.gerrit.extensions.api.changes.ReviewerApi;
@@ -23,8 +25,6 @@
import com.google.gerrit.server.change.ReviewerResource;
import com.google.gerrit.server.change.VoteResource;
import com.google.gerrit.server.change.Votes;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.Map;
@@ -55,8 +55,8 @@
public Map<String, Short> votes() throws RestApiException {
try {
return listVotes.apply(reviewer);
- } catch (OrmException e) {
- throw new RestApiException("Cannot list votes", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list votes", e);
}
}
@@ -64,8 +64,8 @@
public void deleteVote(String label) throws RestApiException {
try {
deleteVote.apply(new VoteResource(reviewer, label), null);
- } catch (UpdateException e) {
- throw new RestApiException("Cannot delete vote", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete vote", e);
}
}
@@ -73,8 +73,8 @@
public void deleteVote(DeleteVoteInput input) throws RestApiException {
try {
deleteVote.apply(new VoteResource(reviewer, input.label), input);
- } catch (UpdateException e) {
- throw new RestApiException("Cannot delete vote", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete vote", e);
}
}
@@ -87,8 +87,8 @@
public void remove(DeleteReviewerInput input) throws RestApiException {
try {
deleteReviewer.apply(reviewer, input);
- } catch (UpdateException e) {
- throw new RestApiException("Cannot remove reviewer", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot remove reviewer", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java
index 6440509..21fb578 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java
@@ -14,8 +14,9 @@
package com.google.gerrit.server.api.changes;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.common.collect.ImmutableSet;
-import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.Changes;
import com.google.gerrit.extensions.api.changes.CherryPickInput;
@@ -72,14 +73,9 @@
import com.google.gerrit.server.change.Submit;
import com.google.gerrit.server.change.TestSubmitType;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -214,8 +210,8 @@
public void review(ReviewInput in) throws RestApiException {
try {
review.apply(revision, in);
- } catch (OrmException | UpdateException | IOException | PermissionBackendException e) {
- throw new RestApiException("Cannot post review", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot post review", e);
}
}
@@ -228,9 +224,11 @@
@Override
public void submit(SubmitInput in) throws RestApiException {
try {
+ // TODO(dborowitz): Convert to RetryingRestModifyHandler. Requires converting MergeOp to a
+ // Factory that takes BatchUpdate.Factory. (Enough Factories yet?)
submit.apply(revision, in);
- } catch (OrmException | IOException | PermissionBackendException e) {
- throw new RestApiException("Cannot submit change", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot submit change", e);
}
}
@@ -242,10 +240,12 @@
@Override
public BinaryResult submitPreview(String format) throws RestApiException {
try {
+ // TODO(dborowitz): Convert to RetryingRestModifyHandler. Requires converting MergeOp to a
+ // Factory that takes BatchUpdate.Factory.
submitPreview.setFormat(format);
return submitPreview.apply(revision);
- } catch (OrmException e) {
- throw new RestApiException("Cannot get submit preview", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get submit preview", e);
}
}
@@ -253,8 +253,8 @@
public void publish() throws RestApiException {
try {
publish.apply(revision, new PublishDraftPatchSet.Input());
- } catch (UpdateException e) {
- throw new RestApiException("Cannot publish draft patch set", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot publish draft patch set", e);
}
}
@@ -262,8 +262,8 @@
public void delete() throws RestApiException {
try {
deleteDraft.apply(revision, null);
- } catch (UpdateException | OrmException | PermissionBackendException e) {
- throw new RestApiException("Cannot delete draft ps", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete draft ps", e);
}
}
@@ -277,12 +277,8 @@
public ChangeApi rebase(RebaseInput in) throws RestApiException {
try {
return changes.id(rebase.apply(revision, in)._number);
- } catch (OrmException
- | EmailException
- | UpdateException
- | IOException
- | PermissionBackendException e) {
- throw new RestApiException("Cannot rebase ps", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot rebase ps", e);
}
}
@@ -291,8 +287,8 @@
try (Repository repo = repoManager.openRepository(revision.getProject());
RevWalk rw = new RevWalk(repo)) {
return rebaseUtil.canRebase(revision.getPatchSet(), revision.getChange().getDest(), repo, rw);
- } catch (IOException e) {
- throw new RestApiException("Cannot check if rebase is possible", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot check if rebase is possible", e);
}
}
@@ -300,8 +296,8 @@
public ChangeApi cherryPick(CherryPickInput in) throws RestApiException {
try {
return changes.id(cherryPick.apply(revision, in)._number);
- } catch (OrmException | IOException | UpdateException e) {
- throw new RestApiException("Cannot cherry pick", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot cherry pick", e);
}
}
@@ -310,8 +306,8 @@
try {
return revisionReviewerApi.create(
revisionReviewers.parse(revision, IdString.fromDecoded(id)));
- } catch (OrmException e) {
- throw new RestApiException("Cannot parse reviewer", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot parse reviewer", e);
}
}
@@ -326,7 +322,7 @@
}
view.apply(files.parse(revision, IdString.fromDecoded(path)), new Reviewed.Input());
} catch (Exception e) {
- throw new RestApiException("Cannot update reviewed flag", e);
+ throw asRestApiException("Cannot update reviewed flag", e);
}
}
@@ -336,8 +332,8 @@
try {
return ImmutableSet.copyOf(
(Iterable<String>) listFiles.setReviewed(true).apply(revision).value());
- } catch (OrmException | IOException | PatchListNotAvailableException e) {
- throw new RestApiException("Cannot list reviewed files", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list reviewed files", e);
}
}
@@ -345,8 +341,8 @@
public MergeableInfo mergeable() throws RestApiException {
try {
return mergeable.apply(revision);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot check mergeability", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot check mergeability", e);
}
}
@@ -355,8 +351,8 @@
try {
mergeable.setOtherBranches(true);
return mergeable.apply(revision);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot check mergeability", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot check mergeability", e);
}
}
@@ -365,8 +361,8 @@
public Map<String, FileInfo> files() throws RestApiException {
try {
return (Map<String, FileInfo>) listFiles.apply(revision).value();
- } catch (OrmException | IOException | PatchListNotAvailableException e) {
- throw new RestApiException("Cannot retrieve files", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve files", e);
}
}
@@ -375,8 +371,8 @@
public Map<String, FileInfo> files(String base) throws RestApiException {
try {
return (Map<String, FileInfo>) listFiles.setBase(base).apply(revision).value();
- } catch (OrmException | IOException | PatchListNotAvailableException e) {
- throw new RestApiException("Cannot retrieve files", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve files", e);
}
}
@@ -385,8 +381,8 @@
public Map<String, FileInfo> files(int parentNum) throws RestApiException {
try {
return (Map<String, FileInfo>) listFiles.setParent(parentNum).apply(revision).value();
- } catch (OrmException | IOException | PatchListNotAvailableException e) {
- throw new RestApiException("Cannot retrieve files", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve files", e);
}
}
@@ -399,8 +395,8 @@
public Map<String, List<CommentInfo>> comments() throws RestApiException {
try {
return listComments.apply(revision);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve comments", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve comments", e);
}
}
@@ -408,8 +404,8 @@
public Map<String, List<RobotCommentInfo>> robotComments() throws RestApiException {
try {
return listRobotComments.apply(revision);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve robot comments", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve robot comments", e);
}
}
@@ -417,8 +413,8 @@
public List<CommentInfo> commentsAsList() throws RestApiException {
try {
return listComments.getComments(revision);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve comments", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve comments", e);
}
}
@@ -426,8 +422,8 @@
public Map<String, List<CommentInfo>> drafts() throws RestApiException {
try {
return listDrafts.apply(revision);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve drafts", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve drafts", e);
}
}
@@ -435,8 +431,8 @@
public List<RobotCommentInfo> robotCommentsAsList() throws RestApiException {
try {
return listRobotComments.getComments(revision);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve robot comments", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve robot comments", e);
}
}
@@ -444,8 +440,8 @@
public EditInfo applyFix(String fixId) throws RestApiException {
try {
return applyFix.apply(fixes.parse(revision, IdString.fromDecoded(fixId)), null).value();
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot apply fix", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot apply fix", e);
}
}
@@ -453,8 +449,8 @@
public List<CommentInfo> draftsAsList() throws RestApiException {
try {
return listDrafts.getComments(revision);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve drafts", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve drafts", e);
}
}
@@ -462,8 +458,8 @@
public DraftApi draft(String id) throws RestApiException {
try {
return draftFactory.create(drafts.parse(revision, IdString.fromDecoded(id)));
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve draft", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve draft", e);
}
}
@@ -476,8 +472,8 @@
.id(revision.getChange().getId().get())
.revision(revision.getPatchSet().getId().get())
.draft(id);
- } catch (UpdateException | OrmException e) {
- throw new RestApiException("Cannot create draft", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot create draft", e);
}
}
@@ -485,8 +481,8 @@
public CommentApi comment(String id) throws RestApiException {
try {
return commentFactory.create(comments.parse(revision, IdString.fromDecoded(id)));
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve comment", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve comment", e);
}
}
@@ -494,8 +490,8 @@
public RobotCommentApi robotComment(String id) throws RestApiException {
try {
return robotCommentFactory.create(robotComments.parse(revision, IdString.fromDecoded(id)));
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve robot comment", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve robot comment", e);
}
}
@@ -503,8 +499,8 @@
public BinaryResult patch() throws RestApiException {
try {
return getPatch.apply(revision);
- } catch (IOException e) {
- throw new RestApiException("Cannot get patch", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get patch", e);
}
}
@@ -512,8 +508,8 @@
public BinaryResult patch(String path) throws RestApiException {
try {
return getPatch.setPath(path).apply(revision);
- } catch (IOException e) {
- throw new RestApiException("Cannot get patch", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get patch", e);
}
}
@@ -521,8 +517,8 @@
public Map<String, ActionInfo> actions() throws RestApiException {
try {
return revisionActions.apply(revision).value();
- } catch (OrmException e) {
- throw new RestApiException("Cannot get actions", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get actions", e);
}
}
@@ -530,8 +526,8 @@
public SubmitType submitType() throws RestApiException {
try {
return getSubmitType.apply(revision);
- } catch (OrmException e) {
- throw new RestApiException("Cannot get submit type", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get submit type", e);
}
}
@@ -539,8 +535,8 @@
public SubmitType testSubmitType(TestSubmitRuleInput in) throws RestApiException {
try {
return testSubmitType.apply(revision, in);
- } catch (OrmException e) {
- throw new RestApiException("Cannot test submit type", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot test submit type", e);
}
}
@@ -554,8 +550,8 @@
gml.setUninterestingParent(getUninterestingParent());
gml.setAddLinks(getAddLinks());
return gml.apply(revision).value();
- } catch (IOException e) {
- throw new RestApiException("Cannot get merge list", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get merge list", e);
}
}
};
@@ -567,8 +563,8 @@
in.description = description;
try {
putDescription.apply(revision, in);
- } catch (UpdateException | PermissionBackendException e) {
- throw new RestApiException("Cannot set description", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set description", e);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionReviewerApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionReviewerApiImpl.java
index 5c56321..60dc1d2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionReviewerApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionReviewerApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.changes;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.changes.DeleteVoteInput;
import com.google.gerrit.extensions.api.changes.RevisionReviewerApi;
import com.google.gerrit.extensions.restapi.RestApiException;
@@ -21,8 +23,6 @@
import com.google.gerrit.server.change.ReviewerResource;
import com.google.gerrit.server.change.VoteResource;
import com.google.gerrit.server.change.Votes;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.Map;
@@ -48,8 +48,8 @@
public Map<String, Short> votes() throws RestApiException {
try {
return listVotes.apply(reviewer);
- } catch (OrmException e) {
- throw new RestApiException("Cannot list votes", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list votes", e);
}
}
@@ -57,8 +57,8 @@
public void deleteVote(String label) throws RestApiException {
try {
deleteVote.apply(new VoteResource(reviewer, label), null);
- } catch (UpdateException e) {
- throw new RestApiException("Cannot delete vote", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete vote", e);
}
}
@@ -66,8 +66,8 @@
public void deleteVote(DeleteVoteInput input) throws RestApiException {
try {
deleteVote.apply(new VoteResource(reviewer, input.label), input);
- } catch (UpdateException e) {
- throw new RestApiException("Cannot delete vote", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete vote", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RobotCommentApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RobotCommentApiImpl.java
index ded98cb..b19939b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RobotCommentApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RobotCommentApiImpl.java
@@ -14,12 +14,13 @@
package com.google.gerrit.server.api.changes;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.changes.RobotCommentApi;
import com.google.gerrit.extensions.common.RobotCommentInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.change.GetRobotComment;
import com.google.gerrit.server.change.RobotCommentResource;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -41,8 +42,8 @@
public RobotCommentInfo get() throws RestApiException {
try {
return getComment.apply(comment);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve robot comment", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve robot comment", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/config/ServerImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/config/ServerImpl.java
index 21b42dd..87118c7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/config/ServerImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/config/ServerImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.config;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.common.Version;
import com.google.gerrit.extensions.api.config.AccessCheckInfo;
import com.google.gerrit.extensions.api.config.AccessCheckInput;
@@ -32,13 +34,9 @@
import com.google.gerrit.server.config.GetServerInfo;
import com.google.gerrit.server.config.SetDiffPreferences;
import com.google.gerrit.server.config.SetPreferences;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
-import java.io.IOException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class ServerImpl implements Server {
@@ -77,8 +75,8 @@
public ServerInfo getInfo() throws RestApiException {
try {
return getServerInfo.apply(new ConfigResource());
- } catch (IOException e) {
- throw new RestApiException("Cannot get server info", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get server info", e);
}
}
@@ -86,8 +84,8 @@
public GeneralPreferencesInfo getDefaultPreferences() throws RestApiException {
try {
return getPreferences.apply(new ConfigResource());
- } catch (IOException | ConfigInvalidException e) {
- throw new RestApiException("Cannot get default general preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get default general preferences", e);
}
}
@@ -96,8 +94,8 @@
throws RestApiException {
try {
return setPreferences.apply(new ConfigResource(), in);
- } catch (IOException | ConfigInvalidException e) {
- throw new RestApiException("Cannot set default general preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set default general preferences", e);
}
}
@@ -105,8 +103,8 @@
public DiffPreferencesInfo getDefaultDiffPreferences() throws RestApiException {
try {
return getDiffPreferences.apply(new ConfigResource());
- } catch (IOException | ConfigInvalidException e) {
- throw new RestApiException("Cannot get default diff preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get default diff preferences", e);
}
}
@@ -115,8 +113,8 @@
throws RestApiException {
try {
return setDiffPreferences.apply(new ConfigResource(), in);
- } catch (IOException | ConfigInvalidException e) {
- throw new RestApiException("Cannot set default diff preferences", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot set default diff preferences", e);
}
}
@@ -124,8 +122,8 @@
public ConsistencyCheckInfo checkConsistency(ConsistencyCheckInput in) throws RestApiException {
try {
return checkConsistency.get().apply(new ConfigResource(), in);
- } catch (IOException e) {
- throw new RestApiException("Cannot check consistency", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot check consistency", e);
}
}
@@ -133,8 +131,8 @@
public AccessCheckInfo checkAccess(AccessCheckInput in) throws RestApiException {
try {
return checkAccess.get().apply(new ConfigResource(), in);
- } catch (OrmException | IOException | PermissionBackendException e) {
- throw new RestApiException("Cannot check access", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot check access", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/groups/GroupApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/groups/GroupApiImpl.java
index 2c1ee3e..d7f868c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/groups/GroupApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/groups/GroupApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.groups;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.api.groups.GroupApi;
import com.google.gerrit.extensions.common.AccountInfo;
@@ -41,10 +43,8 @@
import com.google.gerrit.server.group.PutName;
import com.google.gerrit.server.group.PutOptions;
import com.google.gerrit.server.group.PutOwner;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
import java.util.Arrays;
import java.util.List;
@@ -119,8 +119,8 @@
public GroupInfo get() throws RestApiException {
try {
return getGroup.apply(rsrc);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve group", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve group", e);
}
}
@@ -128,8 +128,8 @@
public GroupInfo detail() throws RestApiException {
try {
return getDetail.apply(rsrc);
- } catch (OrmException e) {
- throw new RestApiException("Cannot retrieve group", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve group", e);
}
}
@@ -146,8 +146,8 @@
putName.apply(rsrc, in);
} catch (NoSuchGroupException e) {
throw new ResourceNotFoundException(name, e);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot put group name", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot put group name", e);
}
}
@@ -155,8 +155,8 @@
public GroupInfo owner() throws RestApiException {
try {
return getOwner.apply(rsrc);
- } catch (OrmException e) {
- throw new RestApiException("Cannot get group owner", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get group owner", e);
}
}
@@ -166,8 +166,8 @@
in.owner = owner;
try {
putOwner.apply(rsrc, in);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot put group owner", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot put group owner", e);
}
}
@@ -182,8 +182,8 @@
in.description = description;
try {
putDescription.apply(rsrc, in);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot put group description", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot put group description", e);
}
}
@@ -196,8 +196,8 @@
public void options(GroupOptionsInfo options) throws RestApiException {
try {
putOptions.apply(rsrc, options);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot put group options", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot put group options", e);
}
}
@@ -211,8 +211,8 @@
listMembers.setRecursive(recursive);
try {
return listMembers.apply(rsrc);
- } catch (OrmException e) {
- throw new RestApiException("Cannot list group members", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list group members", e);
}
}
@@ -220,8 +220,8 @@
public void addMembers(String... members) throws RestApiException {
try {
addMembers.apply(rsrc, AddMembers.Input.fromMembers(Arrays.asList(members)));
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot add group members", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot add group members", e);
}
}
@@ -229,8 +229,8 @@
public void removeMembers(String... members) throws RestApiException {
try {
deleteMembers.apply(rsrc, AddMembers.Input.fromMembers(Arrays.asList(members)));
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot remove group members", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot remove group members", e);
}
}
@@ -238,8 +238,8 @@
public List<GroupInfo> includedGroups() throws RestApiException {
try {
return listGroups.apply(rsrc);
- } catch (OrmException e) {
- throw new RestApiException("Cannot list included groups", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list included groups", e);
}
}
@@ -247,8 +247,8 @@
public void addGroups(String... groups) throws RestApiException {
try {
addGroups.apply(rsrc, AddIncludedGroups.Input.fromGroups(Arrays.asList(groups)));
- } catch (OrmException e) {
- throw new RestApiException("Cannot add group members", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot add group members", e);
}
}
@@ -256,8 +256,8 @@
public void removeGroups(String... groups) throws RestApiException {
try {
deleteGroups.apply(rsrc, AddIncludedGroups.Input.fromGroups(Arrays.asList(groups)));
- } catch (OrmException e) {
- throw new RestApiException("Cannot remove group members", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot remove group members", e);
}
}
@@ -265,8 +265,8 @@
public List<? extends GroupAuditEventInfo> auditLog() throws RestApiException {
try {
return getAuditLog.apply(rsrc);
- } catch (OrmException e) {
- throw new RestApiException("Cannot get audit log", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get audit log", e);
}
}
@@ -274,8 +274,8 @@
public void index() throws RestApiException {
try {
index.apply(rsrc, new Index.Input());
- } catch (IOException e) {
- throw new RestApiException("Cannot index group", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot index group", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/groups/GroupsImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/groups/GroupsImpl.java
index ecbde59..5f816bb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/groups/GroupsImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/groups/GroupsImpl.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.api.groups;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
import com.google.gerrit.extensions.api.groups.GroupApi;
import com.google.gerrit.extensions.api.groups.GroupInput;
@@ -33,13 +34,10 @@
import com.google.gerrit.server.group.QueryGroups;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
-import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectsCollection;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
-import java.io.IOException;
import java.util.List;
import java.util.SortedMap;
@@ -99,8 +97,8 @@
permissionBackend.user(user).checkAny(GlobalPermission.fromAnnotation(impl.getClass()));
GroupInfo info = impl.apply(TopLevelResource.INSTANCE, in);
return id(info.id);
- } catch (OrmException | IOException | PermissionBackendException e) {
- throw new RestApiException("Cannot create group " + in.name, e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot create group " + in.name, e);
}
}
@@ -122,8 +120,8 @@
for (String project : req.getProjects()) {
try {
list.addProject(projects.parse(tlr, IdString.fromDecoded(project)).getControl());
- } catch (IOException | PermissionBackendException e) {
- throw new RestApiException("Error looking up project " + project, e);
+ } catch (Exception e) {
+ throw asRestApiException("Error looking up project " + project, e);
}
}
@@ -136,8 +134,8 @@
if (req.getUser() != null) {
try {
list.setUser(accounts.parse(req.getUser()).getAccountId());
- } catch (OrmException e) {
- throw new RestApiException("Error looking up user " + req.getUser(), e);
+ } catch (Exception e) {
+ throw asRestApiException("Error looking up user " + req.getUser(), e);
}
}
@@ -148,8 +146,8 @@
list.setSuggest(req.getSuggest());
try {
return list.apply(tlr);
- } catch (OrmException e) {
- throw new RestApiException("Cannot list groups", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list groups", e);
}
}
@@ -178,8 +176,8 @@
myQueryGroups.addOption(option);
}
return myQueryGroups.apply(TopLevelResource.INSTANCE);
- } catch (OrmException e) {
- throw new RestApiException("Cannot query groups", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot query groups", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/BranchApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/BranchApiImpl.java
index 2fc7833..4a587a8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/BranchApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/BranchApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.projects;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.projects.BranchApi;
import com.google.gerrit.extensions.api.projects.BranchInfo;
import com.google.gerrit.extensions.api.projects.BranchInput;
@@ -28,7 +30,6 @@
import com.google.gerrit.server.project.FilesCollection;
import com.google.gerrit.server.project.GetContent;
import com.google.gerrit.server.project.ProjectResource;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
@@ -69,8 +70,8 @@
try {
createBranchFactory.create(ref).apply(project, input);
return this;
- } catch (IOException e) {
- throw new RestApiException("Cannot create branch", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot create branch", e);
}
}
@@ -78,8 +79,8 @@
public BranchInfo get() throws RestApiException {
try {
return resource().getBranchInfo();
- } catch (IOException e) {
- throw new RestApiException("Cannot read branch", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot read branch", e);
}
}
@@ -87,8 +88,8 @@
public void delete() throws RestApiException {
try {
deleteBranch.apply(resource(), new DeleteBranch.Input());
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot delete branch", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete branch", e);
}
}
@@ -97,8 +98,8 @@
try {
FileResource resource = filesCollection.parse(resource(), IdString.fromDecoded(path));
return getContent.apply(resource);
- } catch (IOException e) {
- throw new RestApiException("Cannot retrieve file", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve file", e);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/CommitApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/CommitApiImpl.java
index 9e17498..cbdd03d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/CommitApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/CommitApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.projects;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.Changes;
import com.google.gerrit.extensions.api.changes.CherryPickInput;
@@ -21,11 +23,8 @@
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.change.CherryPickCommit;
import com.google.gerrit.server.project.CommitResource;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
public class CommitApiImpl implements CommitApi {
public interface Factory {
@@ -48,8 +47,8 @@
public ChangeApi cherryPick(CherryPickInput input) throws RestApiException {
try {
return changes.id(cherryPickCommit.apply(commitResource, input)._number);
- } catch (OrmException | IOException | UpdateException e) {
- throw new RestApiException("Cannot cherry pick", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot cherry pick", e);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java
index 1aa203c..104fb94 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.projects;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.access.ProjectAccessInfo;
import com.google.gerrit.extensions.api.access.ProjectAccessInput;
import com.google.gerrit.extensions.api.projects.BranchApi;
@@ -39,7 +41,6 @@
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
-import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ChildProjectsCollection;
import com.google.gerrit.server.project.CommitsCollection;
import com.google.gerrit.server.project.CreateProject;
@@ -57,12 +58,9 @@
import com.google.gerrit.server.project.PutConfig;
import com.google.gerrit.server.project.PutDescription;
import com.google.gerrit.server.project.SetAccess;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
-import java.io.IOException;
import java.util.List;
-import org.eclipse.jgit.errors.ConfigInvalidException;
public class ProjectApiImpl implements ProjectApi {
interface Factory {
@@ -269,8 +267,8 @@
permissionBackend.user(user).checkAny(GlobalPermission.fromAnnotation(impl.getClass()));
impl.apply(TopLevelResource.INSTANCE, in);
return projectApi.create(projects.parse(name));
- } catch (IOException | ConfigInvalidException | PermissionBackendException e) {
- throw new RestApiException("Cannot create project: " + e.getMessage(), e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot create project: " + e.getMessage(), e);
}
}
@@ -291,8 +289,8 @@
public ProjectAccessInfo access() throws RestApiException {
try {
return getAccess.apply(checkExists());
- } catch (IOException e) {
- throw new RestApiException("Cannot get access rights", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get access rights", e);
}
}
@@ -300,8 +298,8 @@
public ProjectAccessInfo access(ProjectAccessInput p) throws RestApiException {
try {
return setAccess.apply(checkExists(), p);
- } catch (IOException | PermissionBackendException e) {
- throw new RestApiException("Cannot put access rights", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot put access rights", e);
}
}
@@ -309,8 +307,8 @@
public void description(DescriptionInput in) throws RestApiException {
try {
putDescription.apply(checkExists(), in);
- } catch (IOException e) {
- throw new RestApiException("Cannot put project description", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot put project description", e);
}
}
@@ -342,8 +340,8 @@
listBranches.setMatchRegex(request.getRegex());
try {
return listBranches.apply(checkExists());
- } catch (IOException e) {
- throw new RestApiException("Cannot list branches", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list branches", e);
}
}
@@ -364,8 +362,8 @@
listTags.setMatchRegex(request.getRegex());
try {
return listTags.apply(checkExists());
- } catch (IOException e) {
- throw new RestApiException("Cannot list tags", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list tags", e);
}
}
@@ -380,8 +378,8 @@
list.setRecursive(recursive);
try {
return list.apply(checkExists());
- } catch (PermissionBackendException e) {
- throw new RestApiException("Cannot list children", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot list children", e);
}
}
@@ -389,8 +387,8 @@
public ChildProjectApi child(String name) throws RestApiException {
try {
return childApi.create(children.parse(checkExists(), IdString.fromDecoded(name)));
- } catch (IOException | PermissionBackendException e) {
- throw new RestApiException("Cannot parse child project", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot parse child project", e);
}
}
@@ -408,8 +406,8 @@
public void deleteBranches(DeleteBranchesInput in) throws RestApiException {
try {
deleteBranches.apply(checkExists(), in);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot delete branches", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete branches", e);
}
}
@@ -417,8 +415,8 @@
public void deleteTags(DeleteTagsInput in) throws RestApiException {
try {
deleteTags.apply(checkExists(), in);
- } catch (OrmException | IOException e) {
- throw new RestApiException("Cannot delete tags", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete tags", e);
}
}
@@ -426,8 +424,8 @@
public CommitApi commit(String commit) throws RestApiException {
try {
return commitApi.create(commitsCollection.parse(checkExists(), IdString.fromDecoded(commit)));
- } catch (IOException e) {
- throw new RestApiException("Cannot parse commit", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot parse commit", e);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectsImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectsImpl.java
index dc19f71..702a7e9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectsImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectsImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.projects;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.projects.ProjectApi;
import com.google.gerrit.extensions.api.projects.ProjectInput;
import com.google.gerrit.extensions.api.projects.Projects;
@@ -28,7 +30,6 @@
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
-import java.io.IOException;
import java.util.SortedMap;
@Singleton
@@ -53,8 +54,8 @@
return api.create(projects.parse(name));
} catch (UnprocessableEntityException e) {
return api.create(name);
- } catch (IOException | PermissionBackendException e) {
- throw new RestApiException("Cannot retrieve project", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot retrieve project", e);
}
}
@@ -80,8 +81,8 @@
public SortedMap<String, ProjectInfo> getAsMap() throws RestApiException {
try {
return list(this);
- } catch (PermissionBackendException e) {
- throw new RestApiException("project list unavailable", e);
+ } catch (Exception e) {
+ throw asRestApiException("project list unavailable", e);
}
}
};
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/TagApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/TagApiImpl.java
index 4e81407..283d117 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/TagApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/TagApiImpl.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.api.projects;
+import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
+
import com.google.gerrit.extensions.api.projects.TagApi;
import com.google.gerrit.extensions.api.projects.TagInfo;
import com.google.gerrit.extensions.api.projects.TagInput;
@@ -25,7 +27,6 @@
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.project.TagResource;
import com.google.gerrit.server.project.TagsCollection;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
@@ -63,8 +64,8 @@
try {
createTagFactory.create(ref).apply(project, input);
return this;
- } catch (IOException e) {
- throw new RestApiException("Cannot create tag", e);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot create tag", e);
}
}
@@ -72,8 +73,8 @@
public TagInfo get() throws RestApiException {
try {
return listTags.get(project, IdString.fromDecoded(ref));
- } catch (IOException e) {
- throw new RestApiException(e.getMessage());
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get tag", e);
}
}
@@ -81,8 +82,8 @@
public void delete() throws RestApiException {
try {
deleteTag.apply(resource(), new DeleteTag.Input());
- } catch (OrmException | IOException e) {
- throw new RestApiException(e.getMessage());
+ } catch (Exception e) {
+ throw asRestApiException("Cannot delete tag", e);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Abandon.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Abandon.java
index 95e1f2f..df22a3a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Abandon.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Abandon.java
@@ -23,7 +23,6 @@
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
@@ -35,6 +34,8 @@
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -43,11 +44,10 @@
import java.util.Collection;
@Singleton
-public class Abandon
- implements RestModifyView<ChangeResource, AbandonInput>, UiAction<ChangeResource> {
+public class Abandon extends RetryingRestModifyView<ChangeResource, AbandonInput, ChangeInfo>
+ implements UiAction<ChangeResource> {
private final Provider<ReviewDb> dbProvider;
private final ChangeJson.Factory json;
- private final BatchUpdate.Factory batchUpdateFactory;
private final AbandonOp.Factory abandonOpFactory;
private final NotifyUtil notifyUtil;
@@ -55,23 +55,25 @@
Abandon(
Provider<ReviewDb> dbProvider,
ChangeJson.Factory json,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
AbandonOp.Factory abandonOpFactory,
NotifyUtil notifyUtil) {
+ super(retryHelper);
this.dbProvider = dbProvider;
this.json = json;
- this.batchUpdateFactory = batchUpdateFactory;
this.abandonOpFactory = abandonOpFactory;
this.notifyUtil = notifyUtil;
}
@Override
- public ChangeInfo apply(ChangeResource req, AbandonInput input)
+ protected ChangeInfo applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource req, AbandonInput input)
throws RestApiException, UpdateException, OrmException, PermissionBackendException {
req.permissions().database(dbProvider).check(ChangePermission.ABANDON);
Change change =
abandon(
+ updateFactory,
req.getControl(),
input.message,
input.notify,
@@ -79,16 +81,18 @@
return json.noOptions().format(change);
}
- public Change abandon(ChangeControl control) throws RestApiException, UpdateException {
- return abandon(control, "", NotifyHandling.ALL, ImmutableListMultimap.of());
+ public Change abandon(BatchUpdate.Factory updateFactory, ChangeControl control)
+ throws RestApiException, UpdateException {
+ return abandon(updateFactory, control, "", NotifyHandling.ALL, ImmutableListMultimap.of());
}
- public Change abandon(ChangeControl control, String msgTxt)
+ public Change abandon(BatchUpdate.Factory updateFactory, ChangeControl control, String msgTxt)
throws RestApiException, UpdateException {
- return abandon(control, msgTxt, NotifyHandling.ALL, ImmutableListMultimap.of());
+ return abandon(updateFactory, control, msgTxt, NotifyHandling.ALL, ImmutableListMultimap.of());
}
public Change abandon(
+ BatchUpdate.Factory updateFactory,
ChangeControl control,
String msgTxt,
NotifyHandling notifyHandling,
@@ -98,7 +102,7 @@
Account account = user.isIdentifiedUser() ? user.asIdentifiedUser().getAccount() : null;
AbandonOp op = abandonOpFactory.create(account, msgTxt, notifyHandling, accountsToNotify);
try (BatchUpdate u =
- batchUpdateFactory.create(
+ updateFactory.create(
dbProvider.get(),
control.getProject().getNameKey(),
control.getUser(),
@@ -116,6 +120,7 @@
* matching project from its ChangeControl. Violations will result in a ResourceConflictException.
*/
public void batchAbandon(
+ BatchUpdate.Factory updateFactory,
Project.NameKey project,
CurrentUser user,
Collection<ChangeControl> controls,
@@ -127,8 +132,7 @@
return;
}
Account account = user.isIdentifiedUser() ? user.asIdentifiedUser().getAccount() : null;
- try (BatchUpdate u =
- batchUpdateFactory.create(dbProvider.get(), project, user, TimeUtil.nowTs())) {
+ try (BatchUpdate u = updateFactory.create(dbProvider.get(), project, user, TimeUtil.nowTs())) {
for (ChangeControl control : controls) {
if (!project.equals(control.getProject().getNameKey())) {
throw new ResourceConflictException(
@@ -145,15 +149,30 @@
}
public void batchAbandon(
- Project.NameKey project, CurrentUser user, Collection<ChangeControl> controls, String msgTxt)
+ BatchUpdate.Factory updateFactory,
+ Project.NameKey project,
+ CurrentUser user,
+ Collection<ChangeControl> controls,
+ String msgTxt)
throws RestApiException, UpdateException {
- batchAbandon(project, user, controls, msgTxt, NotifyHandling.ALL, ImmutableListMultimap.of());
+ batchAbandon(
+ updateFactory,
+ project,
+ user,
+ controls,
+ msgTxt,
+ NotifyHandling.ALL,
+ ImmutableListMultimap.of());
}
public void batchAbandon(
- Project.NameKey project, CurrentUser user, Collection<ChangeControl> controls)
+ BatchUpdate.Factory updateFactory,
+ Project.NameKey project,
+ CurrentUser user,
+ Collection<ChangeControl> controls)
throws RestApiException, UpdateException {
- batchAbandon(project, user, controls, "", NotifyHandling.ALL, ImmutableListMultimap.of());
+ batchAbandon(
+ updateFactory, project, user, controls, "", NotifyHandling.ALL, ImmutableListMultimap.of());
}
@Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/AbandonUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/AbandonUtil.java
index 7c408c8..7645685 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/AbandonUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/AbandonUtil.java
@@ -24,6 +24,7 @@
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeQueryProcessor;
+import com.google.gerrit.server.update.BatchUpdate;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -38,6 +39,7 @@
public class AbandonUtil {
private static final Logger log = LoggerFactory.getLogger(AbandonUtil.class);
+ private final BatchUpdate.Factory updateFactory;
private final ChangeCleanupConfig cfg;
private final ChangeQueryProcessor queryProcessor;
private final ChangeQueryBuilder queryBuilder;
@@ -46,11 +48,13 @@
@Inject
AbandonUtil(
+ BatchUpdate.Factory updateFactory,
ChangeCleanupConfig cfg,
InternalUser.Factory internalUserFactory,
ChangeQueryProcessor queryProcessor,
ChangeQueryBuilder queryBuilder,
Abandon abandon) {
+ this.updateFactory = updateFactory;
this.cfg = cfg;
this.queryProcessor = queryProcessor;
this.queryBuilder = queryBuilder;
@@ -85,7 +89,7 @@
for (Project.NameKey project : abandons.keySet()) {
Collection<ChangeControl> changes = getValidChanges(abandons.get(project), query);
try {
- abandon.batchAbandon(project, internalUser, changes, message);
+ abandon.batchAbandon(updateFactory, project, internalUser, changes, message);
count += changes.size();
} catch (Throwable e) {
StringBuilder msg = new StringBuilder("Failed to auto-abandon inactive change(s):");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java
index 332c3c6..c1db891 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java
@@ -397,8 +397,9 @@
base
? ObjectId.fromString(edit.getBasePatchSet().getRevision().get())
: edit.getEditCommit(),
- rsrc.getPath()));
- } catch (ResourceNotFoundException rnfe) {
+ rsrc.getPath(),
+ null));
+ } catch (ResourceNotFoundException | BadRequestException e) {
return Response.none();
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeInserter.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeInserter.java
index e2d9eb1..5391635 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeInserter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeInserter.java
@@ -121,12 +121,12 @@
private Set<Account.Id> extraCC;
private Map<String, Short> approvals;
private RequestScopePropagator requestScopePropagator;
- private ReceiveCommand updateRefCommand;
private boolean fireRevisionCreated;
private boolean sendMail;
private boolean updateRef;
// Fields set during the insertion process.
+ private ReceiveCommand cmd;
private Change change;
private ChangeMessage changeMessage;
private PatchSetInfo patchSetInfo;
@@ -170,7 +170,6 @@
this.reviewers = Collections.emptySet();
this.extraCC = Collections.emptySet();
this.approvals = Collections.emptyMap();
- this.updateRefCommand = null;
this.fireRevisionCreated = true;
this.sendMail = true;
this.updateRef = true;
@@ -310,10 +309,6 @@
return this;
}
- public void setUpdateRefCommand(ReceiveCommand cmd) {
- updateRefCommand = cmd;
- }
-
public void setPushCertificate(String cert) {
pushCert = cert;
}
@@ -328,6 +323,18 @@
return this;
}
+ /**
+ * Set whether to include the new patch set ref update in this update.
+ *
+ * <p>If false, the caller is responsible for creating the patch set ref <strong>before</strong>
+ * executing the containing {@code BatchUpdate}.
+ *
+ * <p>Should not be used in new code, as it doesn't result in a single atomic batch ref update for
+ * code and NoteDb meta refs.
+ *
+ * @param updateRef whether to update the ref during {@code updateRepo}.
+ */
+ @Deprecated
public ChangeInserter setUpdateRef(boolean updateRef) {
this.updateRef = updateRef;
return this;
@@ -341,17 +348,18 @@
return changeMessage;
}
+ public ReceiveCommand getCommand() {
+ return cmd;
+ }
+
@Override
public void updateRepo(RepoContext ctx) throws ResourceConflictException, IOException {
+ cmd = new ReceiveCommand(ObjectId.zeroId(), commitId, psId.toRefName());
validate(ctx);
if (!updateRef) {
return;
}
- if (updateRefCommand == null) {
- ctx.addRefUpdate(ObjectId.zeroId(), commitId, psId.toRefName());
- } else {
- ctx.addRefUpdate(updateRefCommand);
- }
+ ctx.addRefUpdate(cmd);
}
@Override
@@ -525,10 +533,9 @@
try {
RefControl refControl =
projectControlFactory.controlFor(ctx.getProject(), ctx.getUser()).controlForRef(refName);
- String refName = psId.toRefName();
try (CommitReceivedEvent event =
new CommitReceivedEvent(
- new ReceiveCommand(ObjectId.zeroId(), commitId, refName),
+ cmd,
refControl.getProjectControl().getProject(),
change.getDest().get(),
ctx.getRevWalk().getObjectReader(),
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 d197a2c..d690984 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
@@ -447,8 +447,8 @@
info.updated = c.getLastUpdatedOn();
info._number = c.getId().get();
info.problems = result.problems();
- info.isPrivate = c.isPrivate();
- info.workInProgress = c.isWorkInProgress();
+ info.isPrivate = c.isPrivate() ? true : null;
+ info.workInProgress = c.isWorkInProgress() ? true : null;
finish(info);
} else {
info = new ChangeInfo();
@@ -503,8 +503,8 @@
out.insertions = changedLines.get().insertions;
out.deletions = changedLines.get().deletions;
}
- out.isPrivate = in.isPrivate();
- out.workInProgress = in.isWorkInProgress();
+ out.isPrivate = in.isPrivate() ? true : null;
+ out.workInProgress = in.isWorkInProgress() ? true : null;
out.subject = in.getSubject();
out.status = in.getStatus().asChangeStatus();
out.owner = accountLoader.get(in.getOwner());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
index 18d2fc1..18ed4de 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
@@ -21,7 +21,6 @@
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.RefNames;
@@ -32,6 +31,9 @@
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.RefControl;
+import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -41,21 +43,27 @@
@Singleton
public class CherryPick
- implements RestModifyView<RevisionResource, CherryPickInput>, UiAction<RevisionResource> {
+ extends RetryingRestModifyView<RevisionResource, CherryPickInput, ChangeInfo>
+ implements UiAction<RevisionResource> {
private final Provider<ReviewDb> dbProvider;
private final CherryPickChange cherryPickChange;
private final ChangeJson.Factory json;
@Inject
CherryPick(
- Provider<ReviewDb> dbProvider, CherryPickChange cherryPickChange, ChangeJson.Factory json) {
+ RetryHelper retryHelper,
+ Provider<ReviewDb> dbProvider,
+ CherryPickChange cherryPickChange,
+ ChangeJson.Factory json) {
+ super(retryHelper);
this.dbProvider = dbProvider;
this.cherryPickChange = cherryPickChange;
this.json = json;
}
@Override
- public ChangeInfo apply(RevisionResource revision, CherryPickInput input)
+ protected ChangeInfo applyImpl(
+ BatchUpdate.Factory updateFactory, RevisionResource revision, CherryPickInput input)
throws OrmException, IOException, UpdateException, RestApiException {
final ChangeControl control = revision.getControl();
int parent = input.parent == null ? 1 : input.parent;
@@ -88,6 +96,7 @@
try {
Change.Id cherryPickedChangeId =
+ // TODO(dborowitz): Pass updateFactory here.
cherryPickChange.cherryPick(
revision.getChange(),
revision.getPatchSet(),
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
index e0cb2e1..3c404d6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
@@ -33,7 +33,6 @@
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.reviewdb.client.Change;
@@ -61,6 +60,8 @@
import com.google.gerrit.server.project.ProjectsCollection;
import com.google.gerrit.server.project.RefControl;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -86,7 +87,8 @@
import org.eclipse.jgit.util.ChangeIdUtil;
@Singleton
-public class CreateChange implements RestModifyView<TopLevelResource, ChangeInput> {
+public class CreateChange
+ extends RetryingRestModifyView<TopLevelResource, ChangeInput, Response<ChangeInfo>> {
private final String anonymousCowardName;
private final Provider<ReviewDb> db;
@@ -99,7 +101,6 @@
private final ChangeInserter.Factory changeInserterFactory;
private final ChangeJson.Factory jsonFactory;
private final ChangeFinder changeFinder;
- private final BatchUpdate.Factory updateFactory;
private final PatchSetUtil psUtil;
private final boolean allowDrafts;
private final MergeUtil.Factory mergeUtilFactory;
@@ -119,11 +120,12 @@
ChangeInserter.Factory changeInserterFactory,
ChangeJson.Factory json,
ChangeFinder changeFinder,
- BatchUpdate.Factory updateFactory,
+ RetryHelper retryHelper,
PatchSetUtil psUtil,
@GerritServerConfig Config config,
MergeUtil.Factory mergeUtilFactory,
NotifyUtil notifyUtil) {
+ super(retryHelper);
this.anonymousCowardName = anonymousCowardName;
this.db = db;
this.gitManager = gitManager;
@@ -135,7 +137,6 @@
this.changeInserterFactory = changeInserterFactory;
this.jsonFactory = json;
this.changeFinder = changeFinder;
- this.updateFactory = updateFactory;
this.psUtil = psUtil;
this.allowDrafts = config.getBoolean("change", "allowDrafts", true);
this.submitType = config.getEnum("project", null, "submitType", SubmitType.MERGE_IF_NECESSARY);
@@ -144,7 +145,8 @@
}
@Override
- public Response<ChangeInfo> apply(TopLevelResource parent, ChangeInput input)
+ protected Response<ChangeInfo> applyImpl(
+ BatchUpdate.Factory updateFactory, TopLevelResource parent, ChangeInput input)
throws OrmException, IOException, InvalidChangeOperationException, RestApiException,
UpdateException, PermissionBackendException {
if (Strings.isNullOrEmpty(input.project)) {
@@ -260,6 +262,8 @@
}
ins.setTopic(topic);
ins.setDraft(input.status == ChangeStatus.DRAFT);
+ ins.setPrivate(input.isPrivate != null && input.isPrivate);
+ ins.setWorkInProgress(input.workInProgress != null && input.workInProgress);
ins.setGroups(groups);
ins.setNotify(input.notify);
ins.setAccountsToNotify(notifyUtil.resolveAccounts(input.notifyDetails));
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateDraftComment.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateDraftComment.java
index 6536550f..002c8b7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateDraftComment.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateDraftComment.java
@@ -24,7 +24,6 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.reviewdb.client.Comment;
@@ -37,6 +36,8 @@
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -45,9 +46,9 @@
import java.util.Collections;
@Singleton
-public class CreateDraftComment implements RestModifyView<RevisionResource, DraftInput> {
+public class CreateDraftComment
+ extends RetryingRestModifyView<RevisionResource, DraftInput, Response<CommentInfo>> {
private final Provider<ReviewDb> db;
- private final BatchUpdate.Factory updateFactory;
private final Provider<CommentJson> commentJson;
private final CommentsUtil commentsUtil;
private final PatchSetUtil psUtil;
@@ -56,13 +57,13 @@
@Inject
CreateDraftComment(
Provider<ReviewDb> db,
- BatchUpdate.Factory updateFactory,
+ RetryHelper retryHelper,
Provider<CommentJson> commentJson,
CommentsUtil commentsUtil,
PatchSetUtil psUtil,
PatchListCache patchListCache) {
+ super(retryHelper);
this.db = db;
- this.updateFactory = updateFactory;
this.commentJson = commentJson;
this.commentsUtil = commentsUtil;
this.psUtil = psUtil;
@@ -70,7 +71,8 @@
}
@Override
- public Response<CommentInfo> apply(RevisionResource rsrc, DraftInput in)
+ protected Response<CommentInfo> applyImpl(
+ BatchUpdate.Factory updateFactory, RevisionResource rsrc, DraftInput in)
throws RestApiException, UpdateException, OrmException {
if (Strings.isNullOrEmpty(in.path)) {
throw new BadRequestException("path must be non-empty");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateMergePatchSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateMergePatchSet.java
index 42bfb8a..02c91ac 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateMergePatchSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateMergePatchSet.java
@@ -28,7 +28,6 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
@@ -46,6 +45,8 @@
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -65,7 +66,8 @@
import org.eclipse.jgit.util.ChangeIdUtil;
@Singleton
-public class CreateMergePatchSet implements RestModifyView<ChangeResource, MergePatchSetInput> {
+public class CreateMergePatchSet
+ extends RetryingRestModifyView<ChangeResource, MergePatchSetInput, Response<ChangeInfo>> {
private final Provider<ReviewDb> db;
private final GitRepositoryManager gitManager;
@@ -74,7 +76,6 @@
private final ChangeJson.Factory jsonFactory;
private final PatchSetUtil psUtil;
private final MergeUtil.Factory mergeUtilFactory;
- private final BatchUpdate.Factory batchUpdateFactory;
private final PatchSetInserter.Factory patchSetInserterFactory;
@Inject
@@ -86,8 +87,9 @@
ChangeJson.Factory json,
PatchSetUtil psUtil,
MergeUtil.Factory mergeUtilFactory,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
PatchSetInserter.Factory patchSetInserterFactory) {
+ super(retryHelper);
this.db = db;
this.gitManager = gitManager;
this.serverTimeZone = myIdent.getTimeZone();
@@ -95,12 +97,12 @@
this.jsonFactory = json;
this.psUtil = psUtil;
this.mergeUtilFactory = mergeUtilFactory;
- this.batchUpdateFactory = batchUpdateFactory;
this.patchSetInserterFactory = patchSetInserterFactory;
}
@Override
- public Response<ChangeInfo> apply(ChangeResource req, MergePatchSetInput in)
+ protected Response<ChangeInfo> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource req, MergePatchSetInput in)
throws OrmException, IOException, InvalidChangeOperationException, RestApiException,
UpdateException {
if (in.merge == null) {
@@ -157,7 +159,7 @@
PatchSet.Id nextPsId = ChangeUtil.nextPatchSetId(ps.getId());
PatchSetInserter psInserter = patchSetInserterFactory.create(ctl, nextPsId, newCommit);
- try (BatchUpdate bu = batchUpdateFactory.create(db.get(), project, me, now)) {
+ try (BatchUpdate bu = updateFactory.create(db.get(), project, me, now)) {
bu.setRepository(git, rw, oi);
bu.addOp(
ctl.getId(),
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteAssignee.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteAssignee.java
index 1d5a916..d3feb31 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteAssignee.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteAssignee.java
@@ -18,7 +18,6 @@
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -35,6 +34,8 @@
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -42,10 +43,10 @@
import com.google.inject.Singleton;
@Singleton
-public class DeleteAssignee implements RestModifyView<ChangeResource, Input> {
+public class DeleteAssignee
+ extends RetryingRestModifyView<ChangeResource, Input, Response<AccountInfo>> {
public static class Input {}
- private final BatchUpdate.Factory batchUpdateFactory;
private final ChangeMessagesUtil cmUtil;
private final Provider<ReviewDb> db;
private final AssigneeChanged assigneeChanged;
@@ -54,13 +55,13 @@
@Inject
DeleteAssignee(
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
ChangeMessagesUtil cmUtil,
Provider<ReviewDb> db,
AssigneeChanged assigneeChanged,
IdentifiedUser.GenericFactory userFactory,
AccountLoader.Factory accountLoaderFactory) {
- this.batchUpdateFactory = batchUpdateFactory;
+ super(retryHelper);
this.cmUtil = cmUtil;
this.db = db;
this.assigneeChanged = assigneeChanged;
@@ -69,12 +70,13 @@
}
@Override
- public Response<AccountInfo> apply(ChangeResource rsrc, Input input)
+ protected Response<AccountInfo> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
throws RestApiException, UpdateException, OrmException, PermissionBackendException {
rsrc.permissions().check(ChangePermission.EDIT_ASSIGNEE);
try (BatchUpdate bu =
- batchUpdateFactory.create(db.get(), rsrc.getProject(), rsrc.getUser(), TimeUtil.nowTs())) {
+ updateFactory.create(db.get(), rsrc.getProject(), rsrc.getUser(), TimeUtil.nowTs())) {
Op op = new Op();
bu.addOp(rsrc.getChange().getId(), op);
bu.execute();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteChange.java
index 151ffa1..b9b05e8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteChange.java
@@ -19,7 +19,6 @@
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -32,6 +31,8 @@
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.Order;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -39,12 +40,11 @@
import org.eclipse.jgit.lib.Config;
@Singleton
-public class DeleteChange
- implements RestModifyView<ChangeResource, Input>, UiAction<ChangeResource> {
+public class DeleteChange extends RetryingRestModifyView<ChangeResource, Input, Response<?>>
+ implements UiAction<ChangeResource> {
public static class Input {}
private final Provider<ReviewDb> db;
- private final BatchUpdate.Factory updateFactory;
private final Provider<DeleteChangeOp> opProvider;
private final Provider<CurrentUser> user;
private final PermissionBackend permissionBackend;
@@ -53,13 +53,13 @@
@Inject
public DeleteChange(
Provider<ReviewDb> db,
- BatchUpdate.Factory updateFactory,
+ RetryHelper retryHelper,
Provider<DeleteChangeOp> opProvider,
Provider<CurrentUser> user,
PermissionBackend permissionBackend,
@GerritServerConfig Config cfg) {
+ super(retryHelper);
this.db = db;
- this.updateFactory = updateFactory;
this.opProvider = opProvider;
this.user = user;
this.permissionBackend = permissionBackend;
@@ -67,7 +67,8 @@
}
@Override
- public Response<?> apply(ChangeResource rsrc, Input input)
+ protected Response<?> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
throws RestApiException, UpdateException, PermissionBackendException {
if (rsrc.getChange().getStatus() == Change.Status.MERGED) {
throw new MethodNotAllowedException("delete not permitted");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftComment.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftComment.java
index d1b26ec..021fd45 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftComment.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftComment.java
@@ -21,7 +21,6 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -32,6 +31,8 @@
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -41,13 +42,13 @@
import java.util.Optional;
@Singleton
-public class DeleteDraftComment implements RestModifyView<DraftCommentResource, Input> {
+public class DeleteDraftComment
+ extends RetryingRestModifyView<DraftCommentResource, Input, Response<CommentInfo>> {
static class Input {}
private final Provider<ReviewDb> db;
private final CommentsUtil commentsUtil;
private final PatchSetUtil psUtil;
- private final BatchUpdate.Factory updateFactory;
private final PatchListCache patchListCache;
@Inject
@@ -55,17 +56,18 @@
Provider<ReviewDb> db,
CommentsUtil commentsUtil,
PatchSetUtil psUtil,
- BatchUpdate.Factory updateFactory,
+ RetryHelper retryHelper,
PatchListCache patchListCache) {
+ super(retryHelper);
this.db = db;
this.commentsUtil = commentsUtil;
this.psUtil = psUtil;
- this.updateFactory = updateFactory;
this.patchListCache = patchListCache;
}
@Override
- public Response<CommentInfo> apply(DraftCommentResource rsrc, Input input)
+ protected Response<CommentInfo> applyImpl(
+ BatchUpdate.Factory updateFactory, DraftCommentResource rsrc, Input input)
throws RestApiException, UpdateException {
try (BatchUpdate bu =
updateFactory.create(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftPatchSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftPatchSet.java
index 583bc58..615c32b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftPatchSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftPatchSet.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.change;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.common.collect.Iterables;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.registration.DynamicItem;
@@ -22,7 +24,6 @@
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
@@ -41,6 +42,8 @@
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Order;
import com.google.gerrit.server.update.RepoContext;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -48,16 +51,17 @@
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
+import java.util.Map;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
@Singleton
public class DeleteDraftPatchSet
- implements RestModifyView<RevisionResource, Input>, UiAction<RevisionResource> {
+ extends RetryingRestModifyView<RevisionResource, Input, Response<?>>
+ implements UiAction<RevisionResource> {
public static class Input {}
private final Provider<ReviewDb> db;
- private final BatchUpdate.Factory updateFactory;
private final PatchSetInfoFactory patchSetInfoFactory;
private final PatchSetUtil psUtil;
private final Provider<DeleteChangeOp> deleteChangeOpProvider;
@@ -67,14 +71,14 @@
@Inject
public DeleteDraftPatchSet(
Provider<ReviewDb> db,
- BatchUpdate.Factory updateFactory,
+ RetryHelper retryHelper,
PatchSetInfoFactory patchSetInfoFactory,
PatchSetUtil psUtil,
Provider<DeleteChangeOp> deleteChangeOpProvider,
DynamicItem<AccountPatchReviewStore> accountPatchReviewStore,
@GerritServerConfig Config cfg) {
+ super(retryHelper);
this.db = db;
- this.updateFactory = updateFactory;
this.patchSetInfoFactory = patchSetInfoFactory;
this.psUtil = psUtil;
this.deleteChangeOpProvider = deleteChangeOpProvider;
@@ -83,7 +87,8 @@
}
@Override
- public Response<?> apply(RevisionResource rsrc, Input input)
+ protected Response<?> applyImpl(
+ BatchUpdate.Factory updateFactory, RevisionResource rsrc, Input input)
throws RestApiException, UpdateException, OrmException, PermissionBackendException {
if (isDeletingOnlyPatchSet(rsrc)) {
// A change cannot have zero patch sets; the change is deleted instead.
@@ -119,7 +124,8 @@
@Override
public boolean updateChange(ChangeContext ctx)
throws RestApiException, OrmException, IOException, NoSuchChangeException {
- patchSet = psUtil.get(ctx.getDb(), ctx.getNotes(), psId);
+ Map<PatchSet.Id, PatchSet> patchSets = psUtil.byChangeAsMap(db.get(), ctx.getNotes());
+ patchSet = patchSets.get(psId);
if (patchSet == null) {
return false; // Nothing to do.
}
@@ -133,9 +139,9 @@
throw new AuthException("Not permitted to delete this draft patch set");
}
- patchSetsBeforeDeletion = psUtil.byChange(ctx.getDb(), ctx.getNotes());
+ patchSetsBeforeDeletion = patchSets.values();
deleteDraftPatchSet(patchSet, ctx);
- deleteOrUpdateDraftChange(ctx);
+ deleteOrUpdateDraftChange(ctx, patchSets);
return true;
}
@@ -164,7 +170,7 @@
db.patchSetApprovals().delete(db.patchSetApprovals().byPatchSet(psId));
}
- private void deleteOrUpdateDraftChange(ChangeContext ctx)
+ private void deleteOrUpdateDraftChange(ChangeContext ctx, Map<PatchSet.Id, PatchSet> patchSets)
throws OrmException, RestApiException, IOException, NoSuchChangeException {
Change c = ctx.getChange();
if (deletedOnlyPatchSet()) {
@@ -173,7 +179,7 @@
return;
}
if (c.currentPatchSetId().equals(psId)) {
- c.setCurrentPatchSet(previousPatchSetInfo(ctx));
+ c.setCurrentPatchSet(previousPatchSetInfo(ctx, patchSets));
}
}
@@ -182,12 +188,22 @@
&& patchSetsBeforeDeletion.iterator().next().getId().equals(psId);
}
- private PatchSetInfo previousPatchSetInfo(ChangeContext ctx) throws OrmException {
+ private PatchSetInfo previousPatchSetInfo(
+ ChangeContext ctx, Map<PatchSet.Id, PatchSet> patchSets) throws OrmException {
+ PatchSet.Id prevPsId = null;
+ for (PatchSet.Id id : patchSets.keySet()) {
+ if (id.get() < psId.get() && (prevPsId == null || id.get() > prevPsId.get())) {
+ prevPsId = id;
+ }
+ }
+
try {
// TODO(dborowitz): Get this in a way that doesn't involve re-opening
// the repo after the updateRepo phase.
return patchSetInfoFactory.get(
- ctx.getDb(), ctx.getNotes(), new PatchSet.Id(psId.getParentKey(), psId.get() - 1));
+ ctx.getDb(),
+ ctx.getNotes(),
+ new PatchSet.Id(psId.getParentKey(), checkNotNull(prevPsId).get()));
} catch (PatchSetInfoNotAvailableException e) {
throw new OrmException(e);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeletePrivate.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeletePrivate.java
index fc1c3f1..a951d66 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeletePrivate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeletePrivate.java
@@ -19,12 +19,13 @@
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -32,25 +33,23 @@
@Singleton
public class DeletePrivate
- implements RestModifyView<ChangeResource, DeletePrivate.Input>, UiAction<ChangeResource> {
+ extends RetryingRestModifyView<ChangeResource, DeletePrivate.Input, Response<String>>
+ implements UiAction<ChangeResource> {
public static class Input {}
private final ChangeMessagesUtil cmUtil;
private final Provider<ReviewDb> dbProvider;
- private final BatchUpdate.Factory batchUpdateFactory;
@Inject
- DeletePrivate(
- Provider<ReviewDb> dbProvider,
- BatchUpdate.Factory batchUpdateFactory,
- ChangeMessagesUtil cmUtil) {
+ DeletePrivate(Provider<ReviewDb> dbProvider, RetryHelper retryHelper, ChangeMessagesUtil cmUtil) {
+ super(retryHelper);
this.dbProvider = dbProvider;
- this.batchUpdateFactory = batchUpdateFactory;
this.cmUtil = cmUtil;
}
@Override
- public Response<String> apply(ChangeResource rsrc, DeletePrivate.Input input)
+ protected Response<String> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, DeletePrivate.Input input)
throws RestApiException, UpdateException {
if (!rsrc.isUserOwner()) {
throw new AuthException("not allowed to unmark private");
@@ -63,7 +62,7 @@
ChangeControl control = rsrc.getControl();
SetPrivateOp op = new SetPrivateOp(cmUtil, false);
try (BatchUpdate u =
- batchUpdateFactory.create(
+ updateFactory.create(
dbProvider.get(),
control.getProject().getNameKey(),
control.getUser(),
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
index 4822478..6bee46d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
@@ -19,37 +19,39 @@
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@Singleton
-public class DeleteReviewer implements RestModifyView<ReviewerResource, DeleteReviewerInput> {
+public class DeleteReviewer
+ extends RetryingRestModifyView<ReviewerResource, DeleteReviewerInput, Response<?>> {
private final Provider<ReviewDb> dbProvider;
- private final BatchUpdate.Factory batchUpdateFactory;
private final DeleteReviewerOp.Factory deleteReviewerOpFactory;
private final DeleteReviewerByEmailOp.Factory deleteReviewerByEmailOpFactory;
@Inject
DeleteReviewer(
Provider<ReviewDb> dbProvider,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
DeleteReviewerOp.Factory deleteReviewerOpFactory,
DeleteReviewerByEmailOp.Factory deleteReviewerByEmailOpFactory) {
+ super(retryHelper);
this.dbProvider = dbProvider;
- this.batchUpdateFactory = batchUpdateFactory;
this.deleteReviewerOpFactory = deleteReviewerOpFactory;
this.deleteReviewerByEmailOpFactory = deleteReviewerByEmailOpFactory;
}
@Override
- public Response<?> apply(ReviewerResource rsrc, DeleteReviewerInput input)
+ protected Response<?> applyImpl(
+ BatchUpdate.Factory updateFactory, ReviewerResource rsrc, DeleteReviewerInput input)
throws RestApiException, UpdateException {
if (input == null) {
input = new DeleteReviewerInput();
@@ -59,7 +61,7 @@
}
try (BatchUpdate bu =
- batchUpdateFactory.create(
+ updateFactory.create(
dbProvider.get(),
rsrc.getChangeResource().getProject(),
rsrc.getChangeResource().getUser(),
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteVote.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteVote.java
index 963e7b4..6dd1e2c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteVote.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteVote.java
@@ -26,7 +26,6 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -46,6 +45,8 @@
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.LabelVote;
import com.google.gwtorm.server.OrmException;
@@ -59,11 +60,10 @@
import org.slf4j.LoggerFactory;
@Singleton
-public class DeleteVote implements RestModifyView<VoteResource, DeleteVoteInput> {
+public class DeleteVote extends RetryingRestModifyView<VoteResource, DeleteVoteInput, Response<?>> {
private static final Logger log = LoggerFactory.getLogger(DeleteVote.class);
private final Provider<ReviewDb> db;
- private final BatchUpdate.Factory batchUpdateFactory;
private final ApprovalsUtil approvalsUtil;
private final PatchSetUtil psUtil;
private final ChangeMessagesUtil cmUtil;
@@ -75,7 +75,7 @@
@Inject
DeleteVote(
Provider<ReviewDb> db,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
ApprovalsUtil approvalsUtil,
PatchSetUtil psUtil,
ChangeMessagesUtil cmUtil,
@@ -83,8 +83,8 @@
VoteDeleted voteDeleted,
DeleteVoteSender.Factory deleteVoteSenderFactory,
NotifyUtil notifyUtil) {
+ super(retryHelper);
this.db = db;
- this.batchUpdateFactory = batchUpdateFactory;
this.approvalsUtil = approvalsUtil;
this.psUtil = psUtil;
this.cmUtil = cmUtil;
@@ -95,7 +95,8 @@
}
@Override
- public Response<?> apply(VoteResource rsrc, DeleteVoteInput input)
+ protected Response<?> applyImpl(
+ BatchUpdate.Factory updateFactory, VoteResource rsrc, DeleteVoteInput input)
throws RestApiException, UpdateException {
if (input == null) {
input = new DeleteVoteInput();
@@ -114,7 +115,7 @@
}
try (BatchUpdate bu =
- batchUpdateFactory.create(
+ updateFactory.create(
db.get(), change.getProject(), r.getControl().getUser(), TimeUtil.nowTs())) {
bu.addOp(change.getId(), new Op(r.getReviewerUser().getAccountId(), rsrc.getLabel(), input));
bu.execute();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java
index 166197e..e812002 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java
@@ -22,6 +22,7 @@
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.PatchScript.FileMode;
+import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.reviewdb.client.Patch;
@@ -67,9 +68,33 @@
this.registry = ftr;
}
- public BinaryResult getContent(ProjectState project, ObjectId revstr, String path)
- throws ResourceNotFoundException, IOException {
- try (Repository repo = openRepository(project)) {
+ /**
+ * Get the content of a file at a specific commit or one of it's parent commits.
+ *
+ * @param project A {@code Project} that this request refers to.
+ * @param revstr An {@code ObjectId} specifying the commit.
+ * @param path A string specifying the filepath.
+ * @param parent A 1-based parent index to get the content from instead. Null if the content
+ * should be obtained from {@param revstr} instead.
+ * @return Content of the file as {@code BinaryResult}.
+ * @throws ResourceNotFoundException
+ * @throws IOException
+ */
+ public BinaryResult getContent(
+ ProjectState project, ObjectId revstr, String path, @Nullable Integer parent)
+ throws BadRequestException, ResourceNotFoundException, IOException {
+ try (Repository repo = openRepository(project);
+ RevWalk rw = new RevWalk(repo)) {
+ if (parent != null) {
+ RevCommit revCommit = rw.parseCommit(revstr);
+ if (revCommit == null) {
+ throw new ResourceNotFoundException("commit not found");
+ }
+ if (parent > revCommit.getParentCount()) {
+ throw new BadRequestException("invalid parent");
+ }
+ revstr = rw.parseCommit(revstr).getParent(Integer.max(0, parent - 1)).toObjectId();
+ }
return getContent(repo, project, revstr, path);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java
index abb9e66..5433653 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.change;
+import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestReadView;
@@ -30,21 +31,23 @@
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
-import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.kohsuke.args4j.Option;
-@Singleton
public class GetContent implements RestReadView<FileResource> {
private final Provider<ReviewDb> db;
private final GitRepositoryManager gitManager;
private final PatchSetUtil psUtil;
private final FileContentUtil fileContentUtil;
+ @Option(name = "--parent")
+ private Integer parent;
+
@Inject
GetContent(
Provider<ReviewDb> db,
@@ -59,7 +62,7 @@
@Override
public BinaryResult apply(FileResource rsrc)
- throws ResourceNotFoundException, IOException, NoSuchChangeException, OrmException {
+ throws ResourceNotFoundException, IOException, BadRequestException, OrmException {
String path = rsrc.getPatchKey().get();
if (Patch.COMMIT_MSG.equals(path)) {
String msg = getMessage(rsrc.getRevision().getChangeResource().getNotes());
@@ -75,7 +78,8 @@
return fileContentUtil.getContent(
rsrc.getRevision().getControl().getProjectControl().getProjectState(),
ObjectId.fromString(rsrc.getRevision().getPatchSet().getRevision().get()),
- path);
+ path,
+ parent);
}
private String getMessage(ChangeNotes notes) throws OrmException, IOException {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Index.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Index.java
index 13a94d3..7c4d158 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Index.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Index.java
@@ -16,7 +16,6 @@
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.Response;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.change.Index.Input;
@@ -24,6 +23,9 @@
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -31,7 +33,7 @@
import java.io.IOException;
@Singleton
-public class Index implements RestModifyView<ChangeResource, Input> {
+public class Index extends RetryingRestModifyView<ChangeResource, Input, Response<?>> {
public static class Input {}
private final Provider<ReviewDb> db;
@@ -42,9 +44,11 @@
@Inject
Index(
Provider<ReviewDb> db,
+ RetryHelper retryHelper,
PermissionBackend permissionBackend,
Provider<CurrentUser> user,
ChangeIndexer indexer) {
+ super(retryHelper);
this.db = db;
this.permissionBackend = permissionBackend;
this.user = user;
@@ -52,7 +56,8 @@
}
@Override
- public Response<?> apply(ChangeResource rsrc, Input input)
+ protected Response<?> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
throws IOException, AuthException, OrmException, PermissionBackendException {
permissionBackend.user(user).check(GlobalPermission.MAINTAIN_SERVER);
indexer.index(db.get(), rsrc.getChange());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Move.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Move.java
index ec494ce..98b79d1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Move.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Move.java
@@ -23,7 +23,6 @@
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
@@ -42,6 +41,8 @@
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -55,13 +56,12 @@
import org.eclipse.jgit.revwalk.RevWalk;
@Singleton
-public class Move implements RestModifyView<ChangeResource, MoveInput> {
+public class Move extends RetryingRestModifyView<ChangeResource, MoveInput, ChangeInfo> {
private final Provider<ReviewDb> dbProvider;
private final ChangeJson.Factory json;
private final GitRepositoryManager repoManager;
private final Provider<InternalChangeQuery> queryProvider;
private final ChangeMessagesUtil cmUtil;
- private final BatchUpdate.Factory batchUpdateFactory;
private final PatchSetUtil psUtil;
@Inject
@@ -71,19 +71,20 @@
GitRepositoryManager repoManager,
Provider<InternalChangeQuery> queryProvider,
ChangeMessagesUtil cmUtil,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
PatchSetUtil psUtil) {
+ super(retryHelper);
this.dbProvider = dbProvider;
this.json = json;
this.repoManager = repoManager;
this.queryProvider = queryProvider;
this.cmUtil = cmUtil;
- this.batchUpdateFactory = batchUpdateFactory;
this.psUtil = psUtil;
}
@Override
- public ChangeInfo apply(ChangeResource req, MoveInput input)
+ protected ChangeInfo applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource req, MoveInput input)
throws RestApiException, OrmException, UpdateException {
ChangeControl control = req.getControl();
input.destinationBranch = RefNames.fullName(input.destinationBranch);
@@ -92,7 +93,7 @@
}
try (BatchUpdate u =
- batchUpdateFactory.create(
+ updateFactory.create(
dbProvider.get(), req.getChange().getProject(), control.getUser(), TimeUtil.nowTs())) {
u.addOp(req.getChange().getId(), new Op(input));
u.execute();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostHashtags.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostHashtags.java
index ebe8f7e..0c8f010 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostHashtags.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostHashtags.java
@@ -19,12 +19,13 @@
import com.google.gerrit.extensions.api.changes.HashtagsInput;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -32,28 +33,28 @@
@Singleton
public class PostHashtags
- implements RestModifyView<ChangeResource, HashtagsInput>, UiAction<ChangeResource> {
+ extends RetryingRestModifyView<
+ ChangeResource, HashtagsInput, Response<ImmutableSortedSet<String>>>
+ implements UiAction<ChangeResource> {
private final Provider<ReviewDb> db;
- private final BatchUpdate.Factory batchUpdateFactory;
private final SetHashtagsOp.Factory hashtagsFactory;
@Inject
PostHashtags(
- Provider<ReviewDb> db,
- BatchUpdate.Factory batchUpdateFactory,
- SetHashtagsOp.Factory hashtagsFactory) {
+ Provider<ReviewDb> db, RetryHelper retryHelper, SetHashtagsOp.Factory hashtagsFactory) {
+ super(retryHelper);
this.db = db;
- this.batchUpdateFactory = batchUpdateFactory;
this.hashtagsFactory = hashtagsFactory;
}
@Override
- public Response<ImmutableSortedSet<String>> apply(ChangeResource req, HashtagsInput input)
+ protected Response<ImmutableSortedSet<String>> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource req, HashtagsInput input)
throws RestApiException, UpdateException, PermissionBackendException {
req.permissions().check(ChangePermission.EDIT_HASHTAGS);
try (BatchUpdate bu =
- batchUpdateFactory.create(
+ updateFactory.create(
db.get(), req.getChange().getProject(), req.getControl().getUser(), TimeUtil.nowTs())) {
SetHashtagsOp op = hashtagsFactory.create(input);
bu.addOp(req.getId(), op);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java
index 69aa19d..0f229f2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java
@@ -61,7 +61,6 @@
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.reviewdb.client.Account;
@@ -101,10 +100,11 @@
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.update.BatchUpdate;
-import com.google.gerrit.server.update.BatchUpdate.Factory;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.LabelVote;
import com.google.gson.Gson;
@@ -131,13 +131,13 @@
import org.slf4j.LoggerFactory;
@Singleton
-public class PostReview implements RestModifyView<RevisionResource, ReviewInput> {
+public class PostReview
+ extends RetryingRestModifyView<RevisionResource, ReviewInput, Response<ReviewResult>> {
private static final Logger log = LoggerFactory.getLogger(PostReview.class);
private static final Gson GSON = OutputFormat.JSON_COMPACT.newGson();
private static final int DEFAULT_ROBOT_COMMENT_SIZE_LIMIT_IN_BYTES = 1024 * 1024;
private final Provider<ReviewDb> db;
- private final BatchUpdate.Factory batchUpdateFactory;
private final ChangesCollection changes;
private final ChangeData.Factory changeDataFactory;
private final ApprovalsUtil approvalsUtil;
@@ -156,7 +156,7 @@
@Inject
PostReview(
Provider<ReviewDb> db,
- Factory batchUpdateFactory,
+ RetryHelper retryHelper,
ChangesCollection changes,
ChangeData.Factory changeDataFactory,
ApprovalsUtil approvalsUtil,
@@ -171,8 +171,8 @@
NotesMigration migration,
NotifyUtil notifyUtil,
@GerritServerConfig Config gerritConfig) {
+ super(retryHelper);
this.db = db;
- this.batchUpdateFactory = batchUpdateFactory;
this.changes = changes;
this.changeDataFactory = changeDataFactory;
this.commentsUtil = commentsUtil;
@@ -190,13 +190,15 @@
}
@Override
- public Response<ReviewResult> apply(RevisionResource revision, ReviewInput input)
+ protected Response<ReviewResult> applyImpl(
+ BatchUpdate.Factory updateFactory, RevisionResource revision, ReviewInput input)
throws RestApiException, UpdateException, OrmException, IOException,
PermissionBackendException {
- return apply(revision, input, TimeUtil.nowTs());
+ return apply(updateFactory, revision, input, TimeUtil.nowTs());
}
- public Response<ReviewResult> apply(RevisionResource revision, ReviewInput input, Timestamp ts)
+ public Response<ReviewResult> apply(
+ BatchUpdate.Factory updateFactory, RevisionResource revision, ReviewInput input, Timestamp ts)
throws RestApiException, UpdateException, OrmException, IOException,
PermissionBackendException {
// Respect timestamp, but truncate at change created-on time.
@@ -264,8 +266,7 @@
output.labels = input.labels;
try (BatchUpdate bu =
- batchUpdateFactory.create(
- db.get(), revision.getChange().getProject(), revision.getUser(), ts)) {
+ updateFactory.create(db.get(), revision.getChange().getProject(), revision.getUser(), ts)) {
Account.Id id = revision.getUser().getAccountId();
boolean ccOrReviewer = false;
if (input.labels != null && !input.labels.isEmpty()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
index 13d5271..c7b0031 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
@@ -37,7 +37,6 @@
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -65,6 +64,8 @@
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -78,7 +79,8 @@
import org.eclipse.jgit.lib.Config;
@Singleton
-public class PostReviewers implements RestModifyView<ChangeResource, AddReviewerInput> {
+public class PostReviewers
+ extends RetryingRestModifyView<ChangeResource, AddReviewerInput, AddReviewerResult> {
public static final int DEFAULT_MAX_REVIEWERS_WITHOUT_CHECK = 10;
public static final int DEFAULT_MAX_REVIEWERS = 20;
@@ -92,7 +94,6 @@
private final AccountLoader.Factory accountLoaderFactory;
private final Provider<ReviewDb> dbProvider;
private final ChangeData.Factory changeDataFactory;
- private final BatchUpdate.Factory batchUpdateFactory;
private final IdentifiedUser.GenericFactory identifiedUserFactory;
private final Config cfg;
private final ReviewerJson json;
@@ -113,7 +114,7 @@
AccountLoader.Factory accountLoaderFactory,
Provider<ReviewDb> db,
ChangeData.Factory changeDataFactory,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
IdentifiedUser.GenericFactory identifiedUserFactory,
@GerritServerConfig Config cfg,
ReviewerJson json,
@@ -123,6 +124,7 @@
Provider<AnonymousUser> anonymousProvider,
PostReviewersOp.Factory postReviewersOpFactory,
OutgoingEmailValidator validator) {
+ super(retryHelper);
this.accounts = accounts;
this.reviewerFactory = reviewerFactory;
this.permissionBackend = permissionBackend;
@@ -131,7 +133,6 @@
this.accountLoaderFactory = accountLoaderFactory;
this.dbProvider = db;
this.changeDataFactory = changeDataFactory;
- this.batchUpdateFactory = batchUpdateFactory;
this.identifiedUserFactory = identifiedUserFactory;
this.cfg = cfg;
this.json = json;
@@ -144,7 +145,8 @@
}
@Override
- public AddReviewerResult apply(ChangeResource rsrc, AddReviewerInput input)
+ protected AddReviewerResult applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, AddReviewerInput input)
throws IOException, OrmException, RestApiException, UpdateException,
PermissionBackendException {
if (input.reviewer == null) {
@@ -156,7 +158,7 @@
return addition.result;
}
try (BatchUpdate bu =
- batchUpdateFactory.create(
+ updateFactory.create(
dbProvider.get(), rsrc.getProject(), rsrc.getUser(), TimeUtil.nowTs())) {
Change.Id id = rsrc.getChange().getId();
bu.addOp(id, addition.op);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PublishDraftPatchSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PublishDraftPatchSet.java
index 4cbeaf63c..3a614a3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PublishDraftPatchSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PublishDraftPatchSet.java
@@ -25,7 +25,6 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
@@ -49,6 +48,8 @@
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -65,14 +66,14 @@
@Singleton
public class PublishDraftPatchSet
- implements RestModifyView<RevisionResource, Input>, UiAction<RevisionResource> {
+ extends RetryingRestModifyView<RevisionResource, Input, Response<?>>
+ implements UiAction<RevisionResource> {
private static final Logger log = LoggerFactory.getLogger(PublishDraftPatchSet.class);
public static class Input {}
private final AccountResolver accountResolver;
private final ApprovalsUtil approvalsUtil;
- private final BatchUpdate.Factory updateFactory;
private final CreateChangeSender.Factory createChangeSenderFactory;
private final PatchSetInfoFactory patchSetInfoFactory;
private final PatchSetUtil psUtil;
@@ -84,16 +85,16 @@
public PublishDraftPatchSet(
AccountResolver accountResolver,
ApprovalsUtil approvalsUtil,
- BatchUpdate.Factory updateFactory,
+ RetryHelper retryHelper,
CreateChangeSender.Factory createChangeSenderFactory,
PatchSetInfoFactory patchSetInfoFactory,
PatchSetUtil psUtil,
Provider<ReviewDb> dbProvider,
ReplacePatchSetSender.Factory replacePatchSetFactory,
DraftPublished draftPublished) {
+ super(retryHelper);
this.accountResolver = accountResolver;
this.approvalsUtil = approvalsUtil;
- this.updateFactory = updateFactory;
this.createChangeSenderFactory = createChangeSenderFactory;
this.patchSetInfoFactory = patchSetInfoFactory;
this.psUtil = psUtil;
@@ -103,12 +104,19 @@
}
@Override
- public Response<?> apply(RevisionResource rsrc, Input input)
+ protected Response<?> applyImpl(
+ BatchUpdate.Factory updateFactory, RevisionResource rsrc, Input input)
throws RestApiException, UpdateException {
- return apply(rsrc.getUser(), rsrc.getChange(), rsrc.getPatchSet().getId(), rsrc.getPatchSet());
+ return apply(
+ updateFactory,
+ rsrc.getUser(),
+ rsrc.getChange(),
+ rsrc.getPatchSet().getId(),
+ rsrc.getPatchSet());
}
- private Response<?> apply(CurrentUser u, Change c, PatchSet.Id psId, PatchSet ps)
+ private Response<?> apply(
+ BatchUpdate.Factory updateFactory, CurrentUser u, Change c, PatchSet.Id psId, PatchSet ps)
throws RestApiException, UpdateException {
try (BatchUpdate bu =
updateFactory.create(dbProvider.get(), c.getProject(), u, TimeUtil.nowTs())) {
@@ -131,18 +139,22 @@
}
}
- public static class CurrentRevision implements RestModifyView<ChangeResource, Input> {
+ public static class CurrentRevision
+ extends RetryingRestModifyView<ChangeResource, Input, Response<?>> {
private final PublishDraftPatchSet publish;
@Inject
- CurrentRevision(PublishDraftPatchSet publish) {
+ CurrentRevision(RetryHelper retryHelper, PublishDraftPatchSet publish) {
+ super(retryHelper);
this.publish = publish;
}
@Override
- public Response<?> apply(ChangeResource rsrc, Input input)
+ protected Response<?> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
throws RestApiException, UpdateException {
return publish.apply(
+ updateFactory,
rsrc.getControl().getUser(),
rsrc.getChange(),
rsrc.getChange().currentPatchSetId(),
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutAssignee.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutAssignee.java
index 735107f..b07d24b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutAssignee.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutAssignee.java
@@ -24,7 +24,6 @@
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -35,6 +34,8 @@
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -43,12 +44,11 @@
import java.io.IOException;
@Singleton
-public class PutAssignee
- implements RestModifyView<ChangeResource, AssigneeInput>, UiAction<ChangeResource> {
+public class PutAssignee extends RetryingRestModifyView<ChangeResource, AssigneeInput, AccountInfo>
+ implements UiAction<ChangeResource> {
private final AccountsCollection accounts;
private final SetAssigneeOp.Factory assigneeFactory;
- private final BatchUpdate.Factory batchUpdateFactory;
private final Provider<ReviewDb> db;
private final PostReviewers postReviewers;
private final AccountLoader.Factory accountLoaderFactory;
@@ -57,20 +57,21 @@
PutAssignee(
AccountsCollection accounts,
SetAssigneeOp.Factory assigneeFactory,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
Provider<ReviewDb> db,
PostReviewers postReviewers,
AccountLoader.Factory accountLoaderFactory) {
+ super(retryHelper);
this.accounts = accounts;
this.assigneeFactory = assigneeFactory;
- this.batchUpdateFactory = batchUpdateFactory;
this.db = db;
this.postReviewers = postReviewers;
this.accountLoaderFactory = accountLoaderFactory;
}
@Override
- public AccountInfo apply(ChangeResource rsrc, AssigneeInput input)
+ protected AccountInfo applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, AssigneeInput input)
throws RestApiException, UpdateException, OrmException, IOException,
PermissionBackendException {
rsrc.permissions().check(ChangePermission.EDIT_ASSIGNEE);
@@ -91,7 +92,7 @@
}
try (BatchUpdate bu =
- batchUpdateFactory.create(
+ updateFactory.create(
db.get(),
rsrc.getChange().getProject(),
rsrc.getControl().getUser(),
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDescription.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDescription.java
index e872206..f2614c3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDescription.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDescription.java
@@ -19,7 +19,6 @@
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
@@ -33,6 +32,8 @@
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -42,10 +43,10 @@
@Singleton
public class PutDescription
- implements RestModifyView<RevisionResource, PutDescription.Input>, UiAction<RevisionResource> {
+ extends RetryingRestModifyView<RevisionResource, PutDescription.Input, Response<String>>
+ implements UiAction<RevisionResource> {
private final Provider<ReviewDb> dbProvider;
private final ChangeMessagesUtil cmUtil;
- private final BatchUpdate.Factory batchUpdateFactory;
private final PatchSetUtil psUtil;
public static class Input {
@@ -56,23 +57,24 @@
PutDescription(
Provider<ReviewDb> dbProvider,
ChangeMessagesUtil cmUtil,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
PatchSetUtil psUtil) {
+ super(retryHelper);
this.dbProvider = dbProvider;
this.cmUtil = cmUtil;
- this.batchUpdateFactory = batchUpdateFactory;
this.psUtil = psUtil;
}
@Override
- public Response<String> apply(RevisionResource rsrc, Input input)
+ protected Response<String> applyImpl(
+ BatchUpdate.Factory updateFactory, RevisionResource rsrc, Input input)
throws UpdateException, RestApiException, PermissionBackendException {
rsrc.permissions().check(ChangePermission.EDIT_DESCRIPTION);
ChangeControl ctl = rsrc.getControl();
Op op = new Op(input != null ? input : new Input(), rsrc.getPatchSet().getId());
try (BatchUpdate u =
- batchUpdateFactory.create(
+ updateFactory.create(
dbProvider.get(), rsrc.getChange().getProject(), ctl.getUser(), TimeUtil.nowTs())) {
u.addOp(rsrc.getChange().getId(), op);
u.execute();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDraftComment.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDraftComment.java
index ecdb382..90716ce 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDraftComment.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDraftComment.java
@@ -23,7 +23,6 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
@@ -36,6 +35,8 @@
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -46,13 +47,13 @@
import java.util.Optional;
@Singleton
-public class PutDraftComment implements RestModifyView<DraftCommentResource, DraftInput> {
+public class PutDraftComment
+ extends RetryingRestModifyView<DraftCommentResource, DraftInput, Response<CommentInfo>> {
private final Provider<ReviewDb> db;
private final DeleteDraftComment delete;
private final CommentsUtil commentsUtil;
private final PatchSetUtil psUtil;
- private final BatchUpdate.Factory updateFactory;
private final Provider<CommentJson> commentJson;
private final PatchListCache patchListCache;
@@ -62,23 +63,24 @@
DeleteDraftComment delete,
CommentsUtil commentsUtil,
PatchSetUtil psUtil,
- BatchUpdate.Factory updateFactory,
+ RetryHelper retryHelper,
Provider<CommentJson> commentJson,
PatchListCache patchListCache) {
+ super(retryHelper);
this.db = db;
this.delete = delete;
this.commentsUtil = commentsUtil;
this.psUtil = psUtil;
- this.updateFactory = updateFactory;
this.commentJson = commentJson;
this.patchListCache = patchListCache;
}
@Override
- public Response<CommentInfo> apply(DraftCommentResource rsrc, DraftInput in)
+ protected Response<CommentInfo> applyImpl(
+ BatchUpdate.Factory updateFactory, DraftCommentResource rsrc, DraftInput in)
throws RestApiException, UpdateException, OrmException {
if (in == null || in.message == null || in.message.trim().isEmpty()) {
- return delete.apply(rsrc, null);
+ return delete.applyImpl(updateFactory, rsrc, null);
} else if (in.id != null && !rsrc.getId().equals(in.id)) {
throw new BadRequestException("id must match URL");
} else if (in.line != null && in.line < 0) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutPrivate.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutPrivate.java
index d9105f1..bd2bf05 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutPrivate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutPrivate.java
@@ -18,13 +18,14 @@
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -32,25 +33,23 @@
@Singleton
public class PutPrivate
- implements RestModifyView<ChangeResource, PutPrivate.Input>, UiAction<ChangeResource> {
+ extends RetryingRestModifyView<ChangeResource, PutPrivate.Input, Response<String>>
+ implements UiAction<ChangeResource> {
public static class Input {}
private final ChangeMessagesUtil cmUtil;
private final Provider<ReviewDb> dbProvider;
- private final BatchUpdate.Factory batchUpdateFactory;
@Inject
- PutPrivate(
- Provider<ReviewDb> dbProvider,
- BatchUpdate.Factory batchUpdateFactory,
- ChangeMessagesUtil cmUtil) {
+ PutPrivate(Provider<ReviewDb> dbProvider, RetryHelper retryHelper, ChangeMessagesUtil cmUtil) {
+ super(retryHelper);
this.dbProvider = dbProvider;
- this.batchUpdateFactory = batchUpdateFactory;
this.cmUtil = cmUtil;
}
@Override
- public Response<String> apply(ChangeResource rsrc, Input input)
+ protected Response<String> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
throws RestApiException, UpdateException {
if (!rsrc.isUserOwner()) {
throw new AuthException("not allowed to mark private");
@@ -63,7 +62,7 @@
ChangeControl control = rsrc.getControl();
SetPrivateOp op = new SetPrivateOp(cmUtil, true);
try (BatchUpdate u =
- batchUpdateFactory.create(
+ updateFactory.create(
dbProvider.get(),
control.getProject().getNameKey(),
control.getUser(),
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java
index b1e351b..5d9f7b9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java
@@ -19,7 +19,6 @@
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -34,6 +33,8 @@
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -41,10 +42,10 @@
import com.google.inject.Singleton;
@Singleton
-public class PutTopic implements RestModifyView<ChangeResource, Input>, UiAction<ChangeResource> {
+public class PutTopic extends RetryingRestModifyView<ChangeResource, Input, Response<String>>
+ implements UiAction<ChangeResource> {
private final Provider<ReviewDb> dbProvider;
private final ChangeMessagesUtil cmUtil;
- private final BatchUpdate.Factory batchUpdateFactory;
private final TopicEdited topicEdited;
public static class Input {
@@ -55,29 +56,27 @@
PutTopic(
Provider<ReviewDb> dbProvider,
ChangeMessagesUtil cmUtil,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
TopicEdited topicEdited) {
+ super(retryHelper);
this.dbProvider = dbProvider;
this.cmUtil = cmUtil;
- this.batchUpdateFactory = batchUpdateFactory;
this.topicEdited = topicEdited;
}
@Override
- public Response<String> apply(ChangeResource req, Input input)
+ protected Response<String> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource req, Input input)
throws UpdateException, RestApiException, PermissionBackendException {
req.permissions().check(ChangePermission.EDIT_TOPIC_NAME);
-
Op op = new Op(input != null ? input : new Input());
try (BatchUpdate u =
- batchUpdateFactory.create(
+ updateFactory.create(
dbProvider.get(), req.getChange().getProject(), req.getUser(), TimeUtil.nowTs())) {
u.addOp(req.getId(), op);
u.execute();
}
- return Strings.isNullOrEmpty(op.newTopicName)
- ? Response.<String>none()
- : Response.ok(op.newTopicName);
+ return Strings.isNullOrEmpty(op.newTopicName) ? Response.none() : Response.ok(op.newTopicName);
}
private class Op implements BatchUpdateOp {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Rebase.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Rebase.java
index b866489..7131e20 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Rebase.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Rebase.java
@@ -40,6 +40,8 @@
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -57,13 +59,12 @@
import org.slf4j.LoggerFactory;
@Singleton
-public class Rebase
+public class Rebase extends RetryingRestModifyView<RevisionResource, RebaseInput, ChangeInfo>
implements RestModifyView<RevisionResource, RebaseInput>, UiAction<RevisionResource> {
private static final Logger log = LoggerFactory.getLogger(Rebase.class);
private static final ImmutableSet<ListChangesOption> OPTIONS =
Sets.immutableEnumSet(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT);
- private final BatchUpdate.Factory updateFactory;
private final GitRepositoryManager repoManager;
private final RebaseChangeOp.Factory rebaseFactory;
private final RebaseUtil rebaseUtil;
@@ -72,13 +73,13 @@
@Inject
public Rebase(
- BatchUpdate.Factory updateFactory,
+ RetryHelper retryHelper,
GitRepositoryManager repoManager,
RebaseChangeOp.Factory rebaseFactory,
RebaseUtil rebaseUtil,
ChangeJson.Factory json,
Provider<ReviewDb> dbProvider) {
- this.updateFactory = updateFactory;
+ super(retryHelper);
this.repoManager = repoManager;
this.rebaseFactory = rebaseFactory;
this.rebaseUtil = rebaseUtil;
@@ -87,7 +88,8 @@
}
@Override
- public ChangeInfo apply(RevisionResource rsrc, RebaseInput input)
+ protected ChangeInfo applyImpl(
+ BatchUpdate.Factory updateFactory, RevisionResource rsrc, RebaseInput input)
throws EmailException, OrmException, UpdateException, RestApiException, IOException,
NoSuchChangeException, PermissionBackendException {
rsrc.permissions().database(dbProvider).check(ChangePermission.REBASE);
@@ -210,18 +212,21 @@
.setEnabled(enabled);
}
- public static class CurrentRevision implements RestModifyView<ChangeResource, RebaseInput> {
+ public static class CurrentRevision
+ extends RetryingRestModifyView<ChangeResource, RebaseInput, ChangeInfo> {
private final PatchSetUtil psUtil;
private final Rebase rebase;
@Inject
- CurrentRevision(PatchSetUtil psUtil, Rebase rebase) {
+ CurrentRevision(RetryHelper retryHelper, PatchSetUtil psUtil, Rebase rebase) {
+ super(retryHelper);
this.psUtil = psUtil;
this.rebase = rebase;
}
@Override
- public ChangeInfo apply(ChangeResource rsrc, RebaseInput input)
+ protected ChangeInfo applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, RebaseInput input)
throws EmailException, OrmException, UpdateException, RestApiException, IOException,
PermissionBackendException {
PatchSet ps = psUtil.current(rebase.dbProvider.get(), rsrc.getNotes());
@@ -230,7 +235,7 @@
} else if (!rsrc.getControl().isPatchVisible(ps, rebase.dbProvider.get())) {
throw new AuthException("current revision not accessible");
}
- return rebase.apply(new RevisionResource(rsrc, ps), input);
+ return rebase.applyImpl(updateFactory, new RevisionResource(rsrc, ps), input);
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java
index b362472..6f74ddd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java
@@ -20,7 +20,6 @@
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
@@ -41,6 +40,8 @@
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -50,8 +51,8 @@
import org.slf4j.LoggerFactory;
@Singleton
-public class Restore
- implements RestModifyView<ChangeResource, RestoreInput>, UiAction<ChangeResource> {
+public class Restore extends RetryingRestModifyView<ChangeResource, RestoreInput, ChangeInfo>
+ implements UiAction<ChangeResource> {
private static final Logger log = LoggerFactory.getLogger(Restore.class);
private final RestoredSender.Factory restoredSenderFactory;
@@ -59,7 +60,6 @@
private final ChangeJson.Factory json;
private final ChangeMessagesUtil cmUtil;
private final PatchSetUtil psUtil;
- private final BatchUpdate.Factory batchUpdateFactory;
private final ChangeRestored changeRestored;
@Inject
@@ -69,26 +69,27 @@
ChangeJson.Factory json,
ChangeMessagesUtil cmUtil,
PatchSetUtil psUtil,
- BatchUpdate.Factory batchUpdateFactory,
+ RetryHelper retryHelper,
ChangeRestored changeRestored) {
+ super(retryHelper);
this.restoredSenderFactory = restoredSenderFactory;
this.dbProvider = dbProvider;
this.json = json;
this.cmUtil = cmUtil;
this.psUtil = psUtil;
- this.batchUpdateFactory = batchUpdateFactory;
this.changeRestored = changeRestored;
}
@Override
- public ChangeInfo apply(ChangeResource req, RestoreInput input)
+ protected ChangeInfo applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource req, RestoreInput input)
throws RestApiException, UpdateException, OrmException, PermissionBackendException {
req.permissions().database(dbProvider).check(ChangePermission.RESTORE);
ChangeControl ctl = req.getControl();
Op op = new Op(input);
try (BatchUpdate u =
- batchUpdateFactory.create(
+ updateFactory.create(
dbProvider.get(), req.getChange().getProject(), ctl.getUser(), TimeUtil.nowTs())) {
u.addOp(req.getId(), op).execute();
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java
index 14e55c5..039aa9e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java
@@ -23,7 +23,6 @@
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
@@ -50,6 +49,8 @@
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -74,15 +75,14 @@
import org.slf4j.LoggerFactory;
@Singleton
-public class Revert
- implements RestModifyView<ChangeResource, RevertInput>, UiAction<ChangeResource> {
+public class Revert extends RetryingRestModifyView<ChangeResource, RevertInput, ChangeInfo>
+ implements UiAction<ChangeResource> {
private static final Logger log = LoggerFactory.getLogger(Revert.class);
private final Provider<ReviewDb> db;
private final GitRepositoryManager repoManager;
private final ChangeInserter.Factory changeInserterFactory;
private final ChangeMessagesUtil cmUtil;
- private final BatchUpdate.Factory updateFactory;
private final Sequences seq;
private final PatchSetUtil psUtil;
private final RevertedSender.Factory revertedSenderFactory;
@@ -97,7 +97,7 @@
GitRepositoryManager repoManager,
ChangeInserter.Factory changeInserterFactory,
ChangeMessagesUtil cmUtil,
- BatchUpdate.Factory updateFactory,
+ RetryHelper retryHelper,
Sequences seq,
PatchSetUtil psUtil,
RevertedSender.Factory revertedSenderFactory,
@@ -105,11 +105,11 @@
@GerritPersonIdent PersonIdent serverIdent,
ApprovalsUtil approvalsUtil,
ChangeReverted changeReverted) {
+ super(retryHelper);
this.db = db;
this.repoManager = repoManager;
this.changeInserterFactory = changeInserterFactory;
this.cmUtil = cmUtil;
- this.updateFactory = updateFactory;
this.seq = seq;
this.psUtil = psUtil;
this.revertedSenderFactory = revertedSenderFactory;
@@ -120,7 +120,8 @@
}
@Override
- public ChangeInfo apply(ChangeResource req, RevertInput input)
+ protected ChangeInfo applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource req, RevertInput input)
throws IOException, OrmException, RestApiException, UpdateException, NoSuchChangeException {
RefControl refControl = req.getControl().getRefControl();
ProjectControl projectControl = req.getControl().getProjectControl();
@@ -137,11 +138,12 @@
throw new ResourceConflictException("change is " + ChangeUtil.status(change));
}
- Change.Id revertedChangeId = revert(req.getControl(), Strings.emptyToNull(input.message));
+ Change.Id revertedChangeId =
+ revert(updateFactory, req.getControl(), Strings.emptyToNull(input.message));
return json.noOptions().format(req.getProject(), revertedChangeId);
}
- private Change.Id revert(ChangeControl ctl, String message)
+ private Change.Id revert(BatchUpdate.Factory updateFactory, ChangeControl ctl, String message)
throws OrmException, IOException, RestApiException, UpdateException {
Change.Id changeIdToRevert = ctl.getChange().getId();
PatchSet.Id patchSetId = ctl.getChange().currentPatchSetId();
@@ -196,7 +198,6 @@
Change.Id changeId = new Change.Id(seq.nextChangeId());
ObjectId id = oi.insert(revertCommitBuilder);
- oi.flush();
RevCommit revertCommit = revWalk.parseCommit(id);
ChangeInserter ins =
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/SetReadyForReview.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/SetReadyForReview.java
index dbc82b7..ef174ac 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/SetReadyForReview.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/SetReadyForReview.java
@@ -19,7 +19,6 @@
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
@@ -28,28 +27,29 @@
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.change.WorkInProgressOp.Input;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@Singleton
-public class SetReadyForReview
- implements RestModifyView<ChangeResource, Input>, UiAction<ChangeResource> {
- private final BatchUpdate.Factory batchUpdateFactory;
+public class SetReadyForReview extends RetryingRestModifyView<ChangeResource, Input, Response<?>>
+ implements UiAction<ChangeResource> {
private final ChangeMessagesUtil cmUtil;
private final Provider<ReviewDb> db;
@Inject
- SetReadyForReview(
- BatchUpdate.Factory batchUpdateFactory, ChangeMessagesUtil cmUtil, Provider<ReviewDb> db) {
- this.batchUpdateFactory = batchUpdateFactory;
+ SetReadyForReview(RetryHelper retryHelper, ChangeMessagesUtil cmUtil, Provider<ReviewDb> db) {
+ super(retryHelper);
this.cmUtil = cmUtil;
this.db = db;
}
@Override
- public Response<?> apply(ChangeResource rsrc, Input input)
+ protected Response<?> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
throws RestApiException, UpdateException {
Change change = rsrc.getChange();
if (!rsrc.isUserOwner()) {
@@ -65,7 +65,7 @@
}
try (BatchUpdate bu =
- batchUpdateFactory.create(db.get(), rsrc.getProject(), rsrc.getUser(), TimeUtil.nowTs())) {
+ updateFactory.create(db.get(), rsrc.getProject(), rsrc.getUser(), TimeUtil.nowTs())) {
bu.addOp(rsrc.getChange().getId(), new WorkInProgressOp(cmUtil, false, input));
bu.execute();
return Response.ok("");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/SetWorkInProgress.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/SetWorkInProgress.java
index aa93fc2..2b481a4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/SetWorkInProgress.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/SetWorkInProgress.java
@@ -19,7 +19,6 @@
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
@@ -28,28 +27,29 @@
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.change.WorkInProgressOp.Input;
import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.RetryHelper;
+import com.google.gerrit.server.update.RetryingRestModifyView;
import com.google.gerrit.server.update.UpdateException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@Singleton
-public class SetWorkInProgress
- implements RestModifyView<ChangeResource, Input>, UiAction<ChangeResource> {
- private final BatchUpdate.Factory batchUpdateFactory;
+public class SetWorkInProgress extends RetryingRestModifyView<ChangeResource, Input, Response<?>>
+ implements UiAction<ChangeResource> {
private final ChangeMessagesUtil cmUtil;
private final Provider<ReviewDb> db;
@Inject
- SetWorkInProgress(
- BatchUpdate.Factory batchUpdateFactory, ChangeMessagesUtil cmUtil, Provider<ReviewDb> db) {
- this.batchUpdateFactory = batchUpdateFactory;
+ SetWorkInProgress(RetryHelper retryHelper, ChangeMessagesUtil cmUtil, Provider<ReviewDb> db) {
+ super(retryHelper);
this.cmUtil = cmUtil;
this.db = db;
}
@Override
- public Response<?> apply(ChangeResource rsrc, Input input)
+ protected Response<?> applyImpl(
+ BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
throws RestApiException, UpdateException {
Change change = rsrc.getChange();
if (!rsrc.isUserOwner()) {
@@ -65,7 +65,7 @@
}
try (BatchUpdate bu =
- batchUpdateFactory.create(db.get(), rsrc.getProject(), rsrc.getUser(), TimeUtil.nowTs())) {
+ updateFactory.create(db.get(), rsrc.getProject(), rsrc.getUser(), TimeUtil.nowTs())) {
bu.addOp(rsrc.getChange().getId(), new WorkInProgressOp(cmUtil, true, input));
bu.execute();
return Response.ok("");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
index 3e489da..b1b980f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
@@ -209,6 +209,11 @@
submitter = rsrc.getUser().asIdentifiedUser();
}
+ return new Output(mergeChange(rsrc, submitter, input));
+ }
+
+ public Change mergeChange(RevisionResource rsrc, IdentifiedUser submitter, SubmitInput input)
+ throws OrmException, RestApiException, IOException {
Change change = rsrc.getChange();
if (!change.getStatus().isOpen()) {
throw new ResourceConflictException("change is " + ChangeUtil.status(change));
@@ -235,7 +240,7 @@
switch (change.getStatus()) {
case MERGED:
- return new Output(change);
+ return change;
case NEW:
ChangeMessage msg = getConflictMessage(rsrc);
if (msg != null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 11871e7..bb07884 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -92,7 +92,6 @@
import com.google.gerrit.server.edit.ChangeEdit;
import com.google.gerrit.server.edit.ChangeEditUtil;
import com.google.gerrit.server.events.CommitReceivedEvent;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.MultiProgressMonitor.Task;
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
@@ -122,6 +121,9 @@
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
+import com.google.gerrit.server.update.Context;
+import com.google.gerrit.server.update.RepoContext;
+import com.google.gerrit.server.update.RepoOnlyOp;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.LabelVote;
import com.google.gerrit.server.util.MagicBranch;
@@ -152,7 +154,6 @@
import java.util.regex.Pattern;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
@@ -300,7 +301,6 @@
private final PermissionBackend permissionBackend;
private final PermissionBackend.ForProject permissions;
private final CmdLineParser.Factory optionParserFactory;
- private final GitReferenceUpdated gitRefUpdated;
private final PatchSetInfoFactory patchSetInfoFactory;
private final PatchSetUtil psUtil;
private final ProjectCache projectCache;
@@ -348,6 +348,15 @@
private final ChangeEditUtil editUtil;
private final ChangeIndexer indexer;
+ /**
+ * Actual commands to be executed, as opposed to the mix of actual and magic commands that were
+ * provided over the wire.
+ *
+ * <p>Excludes commands executed implicitly as part of other {@link BatchUpdateOp}s, such as
+ * creating patch set refs.
+ */
+ private final List<ReceiveCommand> actualCommands = new ArrayList<>();
+
private final List<ValidationMessage> messages = new ArrayList<>();
private ListMultimap<Error, String> errors = LinkedListMultimap.create();
private Task newProgress;
@@ -355,7 +364,6 @@
private Task closeProgress;
private Task commandProgress;
private MessageSender messageSender;
- private BatchRefUpdate batch;
@Inject
ReceiveCommits(
@@ -366,7 +374,6 @@
AccountResolver accountResolver,
PermissionBackend permissionBackend,
CmdLineParser.Factory optionParserFactory,
- GitReferenceUpdated gitRefUpdated,
PatchSetInfoFactory patchSetInfoFactory,
PatchSetUtil psUtil,
ProjectCache projectCache,
@@ -406,7 +413,6 @@
this.accountResolver = accountResolver;
this.permissionBackend = permissionBackend;
this.optionParserFactory = optionParserFactory;
- this.gitRefUpdated = gitRefUpdated;
this.patchSetInfoFactory = patchSetInfoFactory;
this.psUtil = psUtil;
this.projectCache = projectCache;
@@ -589,15 +595,10 @@
closeProgress = progress.beginSubTask("closed", UNKNOWN);
commandProgress = progress.beginSubTask("refs", UNKNOWN);
- batch = repo.getRefDatabase().newBatchUpdate();
- batch.setPushCertificate(rp.getPushCertificate());
- batch.setRefLogIdent(rp.getRefLogIdent());
- batch.setRefLogMessage("push", true);
-
try {
parseCommands(commands);
} catch (PermissionBackendException err) {
- for (ReceiveCommand cmd : batch.getCommands()) {
+ for (ReceiveCommand cmd : actualCommands) {
if (cmd.getResult() == NOT_ATTEMPTED) {
cmd.setResult(REJECTED_OTHER_REASON, "internal server error");
}
@@ -608,27 +609,6 @@
selectNewAndReplacedChangesFromMagicBranch();
}
preparePatchSetsForReplace();
-
- logDebug("Executing batch with {} commands", batch.getCommands().size());
- if (!batch.getCommands().isEmpty()) {
- try {
- if (!batch.isAllowNonFastForwards() && magicBranch != null && magicBranch.edit) {
- logDebug("Allowing non-fast-forward for edit ref");
- batch.setAllowNonFastForwards(true);
- }
- batch.execute(rp.getRevWalk(), commandProgress);
- } catch (IOException err) {
- int cnt = 0;
- for (ReceiveCommand cmd : batch.getCommands()) {
- if (cmd.getResult() == NOT_ATTEMPTED) {
- cmd.setResult(REJECTED_OTHER_REASON, "internal server error");
- cnt++;
- }
- }
- logError(String.format("Failed to store %d refs in %s", cnt, project.getName()), err);
- }
- }
-
insertChangesAndPatchSets();
newProgress.end();
replaceProgress.end();
@@ -643,44 +623,24 @@
}
Set<Branch.NameKey> branches = new HashSet<>();
- for (ReceiveCommand c : batch.getCommands()) {
- if (c.getResult() == OK) {
- String refName = c.getRefName();
- if (c.getType() == ReceiveCommand.Type.UPDATE) { // aka fast-forward
- logDebug("Updating tag cache on fast-forward of {}", c.getRefName());
- tagCache.updateFastForward(project.getNameKey(), refName, c.getOldId(), c.getNewId());
- }
+ for (ReceiveCommand c : actualCommands) {
+ // Most post-update steps should happen in UpdateOneRefOp#postUpdate. The only steps that
+ // should happen in this loop are things that can't happen within one BatchUpdate because they
+ // involve kicking off an additional BatchUpdate.
+ if (c.getResult() != OK) {
+ continue;
+ }
+ if (isHead(c) || isConfig(c)) {
+ switch (c.getType()) {
+ case CREATE:
+ case UPDATE:
+ case UPDATE_NONFASTFORWARD:
+ autoCloseChanges(c);
+ branches.add(new Branch.NameKey(project.getNameKey(), c.getRefName()));
+ break;
- if (isHead(c) || isConfig(c)) {
- switch (c.getType()) {
- case CREATE:
- case UPDATE:
- case UPDATE_NONFASTFORWARD:
- autoCloseChanges(c);
- branches.add(new Branch.NameKey(project.getNameKey(), refName));
- break;
-
- case DELETE:
- break;
- }
- }
-
- if (isConfig(c)) {
- logDebug("Reloading project in cache");
- projectCache.evict(project);
- ProjectState ps = projectCache.get(project.getNameKey());
- try {
- repo.setGitwebDescription(ps.getProject().getDescription());
- } catch (IOException e) {
- log.warn("cannot update description of " + project.getName(), e);
- }
- }
-
- if (!MagicBranch.isMagicBranch(refName)) {
- logDebug("Firing ref update for {}", c.getRefName());
- gitRefUpdated.fire(project.getNameKey(), c, user.getAccount());
- } else {
- logDebug("Assuming ref update event for {} has fired", c.getRefName());
+ case DELETE:
+ break;
}
}
}
@@ -775,117 +735,42 @@
}
private void insertChangesAndPatchSets() {
- int replaceCount = 0;
- int okToInsert = 0;
-
- for (Map.Entry<Change.Id, ReplaceRequest> e : replaceByChange.entrySet()) {
- ReplaceRequest replace = e.getValue();
- if (magicBranch != null && replace.inputCommand == magicBranch.cmd) {
- replaceCount++;
-
- if (replace.cmd != null && replace.cmd.getResult() == OK) {
- okToInsert++;
- }
- } else if (replace.cmd != null && replace.cmd.getResult() == OK) {
- String refName = replace.inputCommand.getRefName();
- checkState(
- NEW_PATCHSET.matcher(refName).matches(),
- "expected a new patch set command as input when creating %s; got %s",
- replace.cmd.getRefName(),
- refName);
- try {
- logDebug("One-off insertion of patch set for {}", refName);
- replace.insertPatchSetWithoutBatchUpdate();
- replace.inputCommand.setResult(OK);
- } catch (IOException | UpdateException | RestApiException err) {
- reject(replace.inputCommand, "internal server error");
- logError(
- String.format(
- "Cannot add patch set to change %d in project %s",
- e.getKey().get(), project.getName()),
- err);
- }
- } else if (replace.inputCommand.getResult() == NOT_ATTEMPTED) {
- reject(replace.inputCommand, "internal server error");
- logError(String.format("Replacement for project %s was not attempted", project.getName()));
- }
- }
-
- // refs/for/ or refs/drafts/ not used, or it already failed earlier.
- // No need to continue.
- if (magicBranch == null) {
- logDebug("No magic branch, nothing more to do");
- return;
- } else if (magicBranch.cmd.getResult() != NOT_ATTEMPTED) {
+ ReceiveCommand magicBranchCmd = magicBranch != null ? magicBranch.cmd : null;
+ if (magicBranchCmd != null && magicBranchCmd.getResult() != NOT_ATTEMPTED) {
logWarn(
String.format(
"Skipping change updates on %s because ref update failed: %s %s",
project.getName(),
- magicBranch.cmd.getResult(),
- Strings.nullToEmpty(magicBranch.cmd.getMessage())));
- return;
- }
-
- List<String> lastCreateChangeErrors = new ArrayList<>();
- for (CreateRequest create : newChanges) {
- if (create.cmd.getResult() == OK) {
- okToInsert++;
- } else {
- String createChangeResult =
- String.format(
- "%s %s", create.cmd.getResult(), Strings.nullToEmpty(create.cmd.getMessage()))
- .trim();
- lastCreateChangeErrors.add(createChangeResult);
- logError(
- String.format(
- "Command %s on %s:%s not completed: %s",
- create.cmd.getType(),
- project.getName(),
- create.cmd.getRefName(),
- createChangeResult));
- }
- }
-
- logDebug(
- "Counted {} ok to insert, out of {} to replace and {} new",
- okToInsert,
- replaceCount,
- newChanges.size());
-
- if (okToInsert != replaceCount + newChanges.size()) {
- // One or more new references failed to create. Assume the
- // system isn't working correctly anymore and abort.
- reject(
- magicBranch.cmd,
- "Unable to create changes: " + lastCreateChangeErrors.stream().collect(joining(" ")));
- logError(
- String.format(
- "Only %d of %d new change refs created in %s; aborting",
- okToInsert, replaceCount + newChanges.size(), project.getName()));
+ magicBranchCmd.getResult(),
+ Strings.nullToEmpty(magicBranchCmd.getMessage())));
return;
}
try (BatchUpdate bu =
batchUpdateFactory.create(
- db, magicBranch.dest.getParentKey(), user.materializedCopy(), TimeUtil.nowTs());
+ db, project.getNameKey(), user.materializedCopy(), TimeUtil.nowTs());
ObjectInserter ins = repo.newObjectInserter();
ObjectReader reader = ins.newReader();
RevWalk rw = new RevWalk(reader)) {
bu.setRepository(repo, rw, ins).updateChangesInParallel();
bu.setRequestId(receiveId);
+ bu.setRefLogMessage("push");
+
+ logDebug("Adding {} replace requests", newChanges.size());
for (ReplaceRequest replace : replaceByChange.values()) {
- if (replace.inputCommand == magicBranch.cmd) {
- replace.addOps(bu, replaceProgress);
- }
+ replace.addOps(bu, replaceProgress);
}
+ logDebug("Adding {} create requests", newChanges.size());
for (CreateRequest create : newChanges) {
create.addOps(bu);
}
- for (UpdateGroupsRequest update : updateGroups) {
- update.addOps(bu);
- }
+ logDebug("Adding {} group update requests", newChanges.size());
+ updateGroups.forEach(r -> r.addOps(bu));
+
+ logDebug("Adding {} additional ref updates", actualCommands.size());
+ actualCommands.forEach(c -> bu.addRepoOnlyOp(new UpdateOneRefOp(c)));
logDebug("Executing batch");
try {
@@ -893,10 +778,17 @@
} catch (UpdateException e) {
throw INSERT_EXCEPTION.apply(e);
}
- magicBranch.cmd.setResult(OK);
+ if (magicBranchCmd != null) {
+ magicBranchCmd.setResult(OK);
+ }
for (ReplaceRequest replace : replaceByChange.values()) {
String rejectMessage = replace.getRejectMessage();
- if (rejectMessage != null) {
+ if (rejectMessage == null) {
+ if (replace.inputCommand.getResult() == NOT_ATTEMPTED) {
+ // Not necessarily the magic branch, so need to set OK on the original value.
+ replace.inputCommand.setResult(OK);
+ }
+ } else {
logDebug("Rejecting due to message from ReplaceOp");
reject(replace.inputCommand, rejectMessage);
}
@@ -904,10 +796,10 @@
} catch (ResourceConflictException e) {
addMessage(e.getMessage());
- reject(magicBranch.cmd, "conflict");
+ reject(magicBranchCmd, "conflict");
} catch (RestApiException | IOException err) {
logError("Can't insert change/patch set for " + project.getName(), err);
- reject(magicBranch.cmd, "internal server error: " + err.getMessage());
+ reject(magicBranchCmd, "internal server error: " + err.getMessage());
}
if (magicBranch != null && magicBranch.submit) {
@@ -915,10 +807,10 @@
submit(newChanges, replaceByChange.values());
} catch (ResourceConflictException e) {
addMessage(e.getMessage());
- reject(magicBranch.cmd, "conflict");
+ reject(magicBranchCmd, "conflict");
} catch (RestApiException | OrmException e) {
logError("Error submitting changes to " + project.getName(), e);
- reject(magicBranch.cmd, "error during submit");
+ reject(magicBranchCmd, "error during submit");
}
}
}
@@ -1176,7 +1068,7 @@
return;
}
validateNewCommits(ctl, cmd);
- batch.addCommand(cmd);
+ actualCommands.add(cmd);
} else {
reject(cmd, "prohibited by Gerrit: create access denied for " + cmd.getRefName());
}
@@ -1199,7 +1091,7 @@
return;
}
validateNewCommits(projectControl.controlForRef(cmd.getRefName()), cmd);
- batch.addCommand(cmd);
+ actualCommands.add(cmd);
} else {
if (RefNames.REFS_CONFIG.equals(cmd.getRefName())) {
errors.put(Error.CONFIG_UPDATE, RefNames.REFS_CONFIG);
@@ -1237,7 +1129,7 @@
if (!validRefOperation(cmd)) {
return;
}
- batch.addCommand(cmd);
+ actualCommands.add(cmd);
} else {
if (RefNames.REFS_CONFIG.equals(ctl.getRefName())) {
reject(cmd, "cannot delete project configuration");
@@ -1282,7 +1174,7 @@
if (!validRefOperation(cmd)) {
return;
}
- batch.setAllowNonFastForwards(true).addCommand(cmd);
+ actualCommands.add(cmd);
} else {
cmd.setResult(
REJECTED_NONFASTFORWARD, " need '" + PermissionRule.FORCE_PUSH + "' privilege.");
@@ -2039,7 +1931,6 @@
for (int i = 0; i < newChanges.size(); i++) {
CreateRequest create = newChanges.get(i);
create.setChangeId(newIds.get(i));
- batch.addCommand(create.cmd);
create.groups = ImmutableList.copyOf(groups.get(create.commit));
}
for (ReplaceRequest replace : replaceByChange.values()) {
@@ -2252,7 +2143,6 @@
.setAccountsToNotify(magicBranch.getAccountsToNotify())
.setRequestScopePropagator(requestScopePropagator)
.setSendMail(true)
- .setUpdateRef(false)
.setPatchSetDescription(magicBranch.message));
if (!magicBranch.hashtags.isEmpty()) {
// Any change owner is allowed to add hashtags when creating a change.
@@ -2342,15 +2232,6 @@
}
logDebug("Read {} changes to replace", replaceByChange.size());
- for (ReplaceRequest req : replaceByChange.values()) {
- if (req.inputCommand.getResult() == NOT_ATTEMPTED && req.cmd != null) {
- if (req.prev != null) {
- batch.addCommand(req.prev);
- }
- batch.addCommand(req.cmd);
- }
- }
-
if (magicBranch != null && magicBranch.cmd.getResult() != NOT_ATTEMPTED) {
// Cancel creations tied to refs/for/ or refs/drafts/ command.
for (ReplaceRequest req : replaceByChange.values()) {
@@ -2394,7 +2275,7 @@
Change.Id toChange, RevCommit newCommit, ReceiveCommand cmd, boolean checkMergedInto) {
this.ontoChange = toChange;
this.newCommitId = newCommit.copy();
- this.inputCommand = cmd;
+ this.inputCommand = checkNotNull(cmd);
this.checkMergedInto = checkMergedInto;
revisions = HashBiMap.create();
@@ -2572,21 +2453,12 @@
}
void addOps(BatchUpdate bu, @Nullable Task progress) throws IOException {
- if (cmd.getResult() == NOT_ATTEMPTED) {
- // TODO(dborowitz): When does this happen? Only when an edit ref is
- // involved?
- cmd.execute(rp);
- }
if (magicBranch != null && magicBranch.edit) {
- bu.addOp(
- notes.getChangeId(),
- new BatchUpdateOp() {
- @Override
- public boolean updateChange(ChangeContext ctx) throws Exception {
- // return pseudo dirty state to trigger reindexing
- return true;
- }
- });
+ bu.addOp(notes.getChangeId(), new ReindexOnlyOp());
+ if (prev != null) {
+ bu.addRepoOnlyOp(new UpdateOneRefOp(prev));
+ }
+ bu.addRepoOnlyOp(new UpdateOneRefOp(cmd));
return;
}
RevWalk rw = rp.getRevWalk();
@@ -2609,28 +2481,13 @@
groups,
magicBranch,
rp.getPushCertificate())
- .setRequestScopePropagator(requestScopePropagator)
- .setUpdateRef(false);
+ .setRequestScopePropagator(requestScopePropagator);
bu.addOp(notes.getChangeId(), replaceOp);
if (progress != null) {
bu.addOp(notes.getChangeId(), new ChangeProgressOp(progress));
}
}
- void insertPatchSetWithoutBatchUpdate() throws IOException, UpdateException, RestApiException {
- try (BatchUpdate bu =
- batchUpdateFactory.create(
- db, projectControl.getProject().getNameKey(), user, TimeUtil.nowTs());
- ObjectInserter ins = repo.newObjectInserter();
- ObjectReader reader = ins.newReader();
- RevWalk rw = new RevWalk(reader)) {
- bu.setRepository(repo, rw, ins);
- bu.setRequestId(receiveId);
- addOps(bu, replaceProgress);
- bu.execute();
- }
- }
-
String getRejectMessage() {
return replaceOp != null ? replaceOp.getRejectMessage() : null;
}
@@ -2672,6 +2529,47 @@
}
}
+ private class UpdateOneRefOp implements RepoOnlyOp {
+ private final ReceiveCommand cmd;
+
+ private UpdateOneRefOp(ReceiveCommand cmd) {
+ this.cmd = checkNotNull(cmd);
+ }
+
+ @Override
+ public void updateRepo(RepoContext ctx) throws IOException {
+ ctx.addRefUpdate(cmd);
+ }
+
+ @Override
+ public void postUpdate(Context ctx) {
+ String refName = cmd.getRefName();
+ if (cmd.getType() == ReceiveCommand.Type.UPDATE) { // aka fast-forward
+ logDebug("Updating tag cache on fast-forward of {}", cmd.getRefName());
+ tagCache.updateFastForward(project.getNameKey(), refName, cmd.getOldId(), cmd.getNewId());
+ }
+ if (isConfig(cmd)) {
+ logDebug("Reloading project in cache");
+ projectCache.evict(project);
+ ProjectState ps = projectCache.get(project.getNameKey());
+ try {
+ logDebug("Updating project description");
+ repo.setGitwebDescription(ps.getProject().getDescription());
+ } catch (IOException e) {
+ log.warn("cannot update description of " + project.getName(), e);
+ }
+ }
+ }
+ }
+
+ private static class ReindexOnlyOp implements BatchUpdateOp {
+ @Override
+ public boolean updateChange(ChangeContext ctx) {
+ // Trigger reindexing even though change isn't actually updated.
+ return true;
+ }
+ }
+
private List<Ref> refs(Change.Id changeId) {
return refsByChange().get(changeId);
}
@@ -2953,9 +2851,11 @@
return r;
}
- private void reject(ReceiveCommand cmd, String why) {
- cmd.setResult(REJECTED_OTHER_REASON, why);
- commandProgress.update(1);
+ private void reject(@Nullable ReceiveCommand cmd, String why) {
+ if (cmd != null) {
+ cmd.setResult(REJECTED_OTHER_REASON, why);
+ commandProgress.update(1);
+ }
}
private static boolean isHead(ReceiveCommand cmd) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplaceOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplaceOp.java
index 5322b2e..0cee090 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplaceOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplaceOp.java
@@ -27,7 +27,6 @@
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.client.ChangeKind;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -41,7 +40,6 @@
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.change.ChangeKindCache;
import com.google.gerrit.server.extensions.events.CommentAdded;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.extensions.events.RevisionCreated;
import com.google.gerrit.server.git.ReceiveCommits.MagicBranchInput;
import com.google.gerrit.server.mail.MailUtil.MailRecipients;
@@ -71,6 +69,7 @@
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.PushCertificate;
+import org.eclipse.jgit.transport.ReceiveCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -102,7 +101,6 @@
private final ChangeKindCache changeKindCache;
private final ChangeMessagesUtil cmUtil;
private final ExecutorService sendEmailExecutor;
- private final GitReferenceUpdated gitRefUpdated;
private final RevisionCreated revisionCreated;
private final CommentAdded commentAdded;
private final MergedByPushOp.Factory mergedByPushOpFactory;
@@ -124,6 +122,7 @@
private final Map<String, Short> approvals = new HashMap<>();
private final MailRecipients recipients = new MailRecipients();
private RevCommit commit;
+ private ReceiveCommand cmd;
private Change change;
private PatchSet newPatchSet;
private ChangeKind changeKind;
@@ -131,7 +130,6 @@
private String rejectMessage;
private MergedByPushOp mergedByPushOp;
private RequestScopePropagator requestScopePropagator;
- private boolean updateRef;
@Inject
ReplaceOp(
@@ -142,7 +140,6 @@
ChangeData.Factory changeDataFactory,
ChangeKindCache changeKindCache,
ChangeMessagesUtil cmUtil,
- GitReferenceUpdated gitRefUpdated,
RevisionCreated revisionCreated,
CommentAdded commentAdded,
MergedByPushOp.Factory mergedByPushOpFactory,
@@ -167,7 +164,6 @@
this.changeDataFactory = changeDataFactory;
this.changeKindCache = changeKindCache;
this.cmUtil = cmUtil;
- this.gitRefUpdated = gitRefUpdated;
this.revisionCreated = revisionCreated;
this.commentAdded = commentAdded;
this.mergedByPushOpFactory = mergedByPushOpFactory;
@@ -186,7 +182,6 @@
this.groups = groups;
this.magicBranch = magicBranch;
this.pushCertificate = pushCertificate;
- this.updateRef = true;
}
@Override
@@ -209,9 +204,8 @@
}
}
- if (updateRef) {
- ctx.addRefUpdate(ObjectId.zeroId(), commitId, patchSetId.toRefName());
- }
+ cmd = new ReceiveCommand(ObjectId.zeroId(), commitId, patchSetId.toRefName());
+ ctx.addRefUpdate(cmd);
}
@Override
@@ -403,17 +397,7 @@
}
@Override
- public void postUpdate(final Context ctx) throws Exception {
- // Normally the ref updated hook is fired by BatchUpdate, but ReplaceOp is
- // special because its ref is actually updated by ReceiveCommits, so from
- // BatchUpdate's perspective there is no ref update. Thus we have to fire it
- // manually.
- final Account account = ctx.getAccount();
- if (!updateRef) {
- gitRefUpdated.fire(
- ctx.getProject(), newPatchSet.getRefName(), ObjectId.zeroId(), commitId, account);
- }
-
+ public void postUpdate(Context ctx) throws Exception {
if (changeKind != ChangeKind.TRIVIAL_REBASE) {
Runnable sender =
new Runnable() {
@@ -423,7 +407,7 @@
ReplacePatchSetSender cm =
replacePatchSetFactory.create(
projectControl.getProject().getNameKey(), change.getId());
- cm.setFrom(account.getId());
+ cm.setFrom(ctx.getAccountId());
cm.setPatchSet(newPatchSet, info);
cm.setChangeMessage(msg.getMessage(), ctx.getWhen());
if (magicBranch != null) {
@@ -508,9 +492,8 @@
return rejectMessage;
}
- public ReplaceOp setUpdateRef(boolean updateRef) {
- this.updateRef = updateRef;
- return this;
+ public ReceiveCommand getCommand() {
+ return cmd;
}
public ReplaceOp setRequestScopePropagator(RequestScopePropagator requestScopePropagator) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
index b58fb55..3756d73 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
@@ -231,7 +231,8 @@
}
if (id != null) {
return (userEditPrefix != null && name.startsWith(userEditPrefix) && visible(id))
- || projectCtl.controlForRef(visibleChanges.get(id)).isEditVisible();
+ || (visibleChanges.containsKey(id)
+ && projectCtl.controlForRef(visibleChanges.get(id)).isEditVisible());
}
return false;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java
index 83193d5..3aa2748 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/NoteDbUpdateManager.java
@@ -64,6 +64,7 @@
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.PushCertificate;
import org.eclipse.jgit.transport.ReceiveCommand;
/**
@@ -212,6 +213,7 @@
private boolean checkExpectedState = true;
private String refLogMessage;
private PersonIdent refLogIdent;
+ private PushCertificate pushCert;
@Inject
NoteDbUpdateManager(
@@ -279,6 +281,25 @@
return this;
}
+ /**
+ * Set a push certificate for the push that originally triggered this NoteDb update.
+ *
+ * <p>The pusher will not necessarily have specified any of the NoteDb refs explicitly, such as
+ * when processing a push to {@code refs/for/master}. That's fine; this is just passed to the
+ * underlying {@link BatchRefUpdate}, and the implementation decides what to do with it.
+ *
+ * <p>The cert should be associated with the main repo. There is currently no way of associating a
+ * push cert with the {@code All-Users} repo, since it is not currently possible to update draft
+ * changes via push.
+ *
+ * @param pushCert push certificate; may be null.
+ * @return this
+ */
+ public NoteDbUpdateManager setPushCertificate(PushCertificate pushCert) {
+ this.pushCert = pushCert;
+ return this;
+ }
+
public OpenRepo getChangeRepo() throws IOException {
initChangeRepo();
return changeRepo;
@@ -490,15 +511,16 @@
// we may have stale draft comments. Doing it in this order allows stale
// comments to be filtered out by ChangeNotes, reflecting the fact that
// comments can only go from DRAFT to PUBLISHED, not vice versa.
- BatchRefUpdate result = execute(changeRepo, dryrun);
- execute(allUsersRepo, dryrun);
+ BatchRefUpdate result = execute(changeRepo, dryrun, pushCert);
+ execute(allUsersRepo, dryrun, null);
return result;
} finally {
close();
}
}
- private BatchRefUpdate execute(OpenRepo or, boolean dryrun) throws IOException {
+ private BatchRefUpdate execute(OpenRepo or, boolean dryrun, @Nullable PushCertificate pushCert)
+ throws IOException {
if (or == null || or.cmds.isEmpty()) {
return null;
}
@@ -511,6 +533,7 @@
}
BatchRefUpdate bru = or.repo.getRefDatabase().newBatchUpdate();
+ bru.setPushCertificate(pushCert);
bru.setRefLogMessage(firstNonNull(refLogMessage, "Update NoteDb refs"), false);
bru.setRefLogIdent(refLogIdent != null ? refLogIdent : serverIdent.get());
or.cmds.addTo(bru);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java
index 10da990f..387c966 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.project;
+import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestReadView;
@@ -32,8 +33,9 @@
}
@Override
- public BinaryResult apply(FileResource rsrc) throws ResourceNotFoundException, IOException {
+ public BinaryResult apply(FileResource rsrc)
+ throws ResourceNotFoundException, BadRequestException, IOException {
return fileContentUtil.getContent(
- rsrc.getProject().getProjectState(), rsrc.getRev(), rsrc.getPath());
+ rsrc.getProject().getProjectState(), rsrc.getRev(), rsrc.getPath(), null);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index 22e8d58..099a3d1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -572,9 +572,12 @@
}
if ("reviewer".equalsIgnoreCase(value)) {
- return Predicate.and(
- Predicate.not(new BooleanPredicate(ChangeField.WIP, args.fillArgs)),
- ReviewerPredicate.reviewer(args, self()));
+ if (args.getSchema().hasField(ChangeField.WIP)) {
+ return Predicate.and(
+ Predicate.not(new BooleanPredicate(ChangeField.WIP, args.fillArgs)),
+ ReviewerPredicate.reviewer(args, self()));
+ }
+ return ReviewerPredicate.reviewer(args, self());
}
if ("cc".equalsIgnoreCase(value)) {
@@ -606,7 +609,10 @@
}
if ("wip".equalsIgnoreCase(value)) {
- return new BooleanPredicate(ChangeField.WIP, args.fillArgs);
+ if (args.getSchema().hasField(ChangeField.WIP)) {
+ return new BooleanPredicate(ChangeField.WIP, args.fillArgs);
+ }
+ throw new QueryParseException("'is:wip' operator is not supported by change index version");
}
try {
@@ -962,9 +968,12 @@
@Operator
public Predicate<ChangeData> reviewer(String who) throws QueryParseException, OrmException {
- return Predicate.and(
- Predicate.not(new BooleanPredicate(ChangeField.WIP, args.fillArgs)),
- reviewerByState(who, ReviewerStateInternal.REVIEWER));
+ if (args.getSchema().hasField(ChangeField.WIP)) {
+ return Predicate.and(
+ Predicate.not(new BooleanPredicate(ChangeField.WIP, args.fillArgs)),
+ reviewerByState(who, ReviewerStateInternal.REVIEWER));
+ }
+ return reviewerByState(who, ReviewerStateInternal.REVIEWER);
}
@Operator
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdate.java
index 22329fd..fdae8e9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdate.java
@@ -60,6 +60,7 @@
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.PushCertificate;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -107,6 +108,7 @@
private final FusedNoteDbBatchUpdate.AssistedFactory fusedNoteDbBatchUpdateFactory;
private final UnfusedNoteDbBatchUpdate.AssistedFactory unfusedNoteDbBatchUpdateFactory;
+ // TODO(dborowitz): Make this non-injectable to force all callers to use RetryHelper.
@Inject
Factory(
NotesMigration migration,
@@ -261,6 +263,8 @@
protected Order order;
protected OnSubmitValidators onSubmitValidators;
protected RequestId requestId;
+ protected PushCertificate pushCert;
+ protected String refLogMessage;
private boolean updateChangesInParallel;
@@ -305,6 +309,16 @@
return this;
}
+ public BatchUpdate setPushCertificate(@Nullable PushCertificate pushCert) {
+ this.pushCert = pushCert;
+ return this;
+ }
+
+ public BatchUpdate setRefLogMessage(@Nullable String refLogMessage) {
+ this.refLogMessage = refLogMessage;
+ return this;
+ }
+
public BatchUpdate setOrder(Order order) {
this.order = order;
return this;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdateOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdateOp.java
index 39e25dd..87a43a3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdateOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdateOp.java
@@ -22,8 +22,11 @@
* BatchUpdate#addOp(com.google.gerrit.reviewdb.client.Change.Id, BatchUpdateOp)}.
*
* <p>Usually, a single {@code BatchUpdateOp} instance is only associated with a single change, i.e.
- * {@code addOp} is only called once with that instance. This allows an instance to communicate
- * between phases by storing data in private fields.
+ * {@code addOp} is only called once with that instance. Additionally, each method in {@code
+ * BatchUpdateOp} is called at most once per {@link BatchUpdate} execution.
+ *
+ * <p>Taken together, these two properties mean an instance may communicate between phases by
+ * storing data in private fields, and a single instance must not be reused.
*/
public interface BatchUpdateOp extends RepoOnlyOp {
/**
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/update/FusedNoteDbBatchUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/update/FusedNoteDbBatchUpdate.java
index ad758484..f8ef5f9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/update/FusedNoteDbBatchUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/update/FusedNoteDbBatchUpdate.java
@@ -402,6 +402,8 @@
if (user.isIdentifiedUser()) {
handle.manager.setRefLogIdent(user.asIdentifiedUser().newRefLogIdent(when, tz));
}
+ handle.manager.setRefLogMessage(refLogMessage);
+ handle.manager.setPushCertificate(pushCert);
for (Map.Entry<Change.Id, Collection<BatchUpdateOp>> e : ops.asMap().entrySet()) {
Change.Id id = e.getKey();
ChangeContextImpl ctx = newChangeContext(id);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/update/RetryHelper.java b/gerrit-server/src/main/java/com/google/gerrit/server/update/RetryHelper.java
new file mode 100644
index 0000000..dbbce2b
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/update/RetryHelper.java
@@ -0,0 +1,79 @@
+// Copyright (C) 2017 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.update;
+
+import com.github.rholder.retry.RetryException;
+import com.github.rholder.retry.RetryerBuilder;
+import com.github.rholder.retry.StopStrategies;
+import com.github.rholder.retry.WaitStrategies;
+import com.google.common.base.Throwables;
+import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.server.git.LockFailureException;
+import com.google.gerrit.server.notedb.NotesMigration;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+@Singleton
+public class RetryHelper {
+ public interface Action<T> {
+ T call(BatchUpdate.Factory updateFactory) throws Exception;
+ }
+
+ private final BatchUpdate.Factory updateFactory;
+
+ @Inject
+ RetryHelper(
+ NotesMigration migration,
+ ReviewDbBatchUpdate.AssistedFactory reviewDbBatchUpdateFactory,
+ FusedNoteDbBatchUpdate.AssistedFactory fusedNoteDbBatchUpdateFactory,
+ UnfusedNoteDbBatchUpdate.AssistedFactory unfusedNoteDbBatchUpdateFactory) {
+ this.updateFactory =
+ new BatchUpdate.Factory(
+ migration,
+ reviewDbBatchUpdateFactory,
+ fusedNoteDbBatchUpdateFactory,
+ unfusedNoteDbBatchUpdateFactory);
+ }
+
+ public <T> T execute(Action<T> action) throws RestApiException, UpdateException {
+ try {
+ // TODO(dborowitz): Make configurable.
+ return RetryerBuilder.<T>newBuilder()
+ .withStopStrategy(StopStrategies.stopAfterDelay(20, TimeUnit.SECONDS))
+ .withWaitStrategy(
+ WaitStrategies.join(
+ WaitStrategies.exponentialWait(5, TimeUnit.SECONDS),
+ WaitStrategies.randomWait(50, TimeUnit.MILLISECONDS)))
+ .retryIfException(RetryHelper::isLockFailure)
+ .build()
+ .call(() -> action.call(updateFactory));
+ } catch (ExecutionException | RetryException e) {
+ if (e.getCause() != null) {
+ Throwables.throwIfInstanceOf(e.getCause(), UpdateException.class);
+ Throwables.throwIfInstanceOf(e.getCause(), RestApiException.class);
+ }
+ throw new UpdateException(e);
+ }
+ }
+
+ private static boolean isLockFailure(Throwable t) {
+ if (t instanceof UpdateException) {
+ t = t.getCause();
+ }
+ return t instanceof LockFailureException;
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/update/RetryingRestModifyView.java b/gerrit-server/src/main/java/com/google/gerrit/server/update/RetryingRestModifyView.java
new file mode 100644
index 0000000..e2f4a02
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/update/RetryingRestModifyView.java
@@ -0,0 +1,35 @@
+// Copyright (C) 2017 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.update;
+
+import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.extensions.restapi.RestResource;
+
+public abstract class RetryingRestModifyView<R extends RestResource, I, O>
+ implements RestModifyView<R, I> {
+ private final RetryHelper retryHelper;
+
+ protected RetryingRestModifyView(RetryHelper retryHelper) {
+ this.retryHelper = retryHelper;
+ }
+
+ @Override
+ public final O apply(R resource, I input) throws Exception {
+ return retryHelper.execute((updateFactory) -> applyImpl(updateFactory, resource, input));
+ }
+
+ protected abstract O applyImpl(BatchUpdate.Factory updateFactory, R resource, I input)
+ throws Exception;
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
index 95ed053..aaf7486 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
@@ -412,6 +412,9 @@
// TODO(dborowitz): Really?
initRepository();
batchRefUpdate = repoView.getRepository().getRefDatabase().newBatchUpdate();
+ batchRefUpdate.setPushCertificate(pushCert);
+ batchRefUpdate.setRefLogMessage(refLogMessage, true);
+ batchRefUpdate.setAllowNonFastForwards(true);
repoView.getCommands().addTo(batchRefUpdate);
logDebug("Executing batch of {} ref updates", batchRefUpdate.getCommands().size());
if (dryrun) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/update/UnfusedNoteDbBatchUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/update/UnfusedNoteDbBatchUpdate.java
index 2f7de46..ab4b701 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/update/UnfusedNoteDbBatchUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/update/UnfusedNoteDbBatchUpdate.java
@@ -332,6 +332,9 @@
// May not be opened if the caller added ref updates but no new objects.
initRepository();
batchRefUpdate = repoView.getRepository().getRefDatabase().newBatchUpdate();
+ batchRefUpdate.setPushCertificate(pushCert);
+ batchRefUpdate.setRefLogMessage(refLogMessage, true);
+ batchRefUpdate.setAllowNonFastForwards(true);
repoView.getCommands().addTo(batchRefUpdate);
logDebug("Executing batch of {} ref updates", batchRefUpdate.getCommands().size());
if (dryrun) {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/IndexChangesCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/IndexChangesCommand.java
index 0ee1c28..86209fe 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/IndexChangesCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/IndexChangesCommand.java
@@ -14,17 +14,14 @@
package com.google.gerrit.sshd.commands;
-import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.Index;
-import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.sshd.ChangeArgumentParser;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.kohsuke.args4j.Argument;
@@ -58,7 +55,7 @@
for (ChangeResource rsrc : changes.values()) {
try {
index.apply(rsrc, new Index.Input());
- } catch (IOException | RestApiException | OrmException | PermissionBackendException e) {
+ } catch (Exception e) {
ok = false;
writeError(
"error", String.format("failed to index change %s: %s", rsrc.getId(), e.getMessage()));
diff --git a/polygerrit-ui/.eslintrc.json b/polygerrit-ui/.eslintrc.json
new file mode 100644
index 0000000..8c4ee99
--- /dev/null
+++ b/polygerrit-ui/.eslintrc.json
@@ -0,0 +1,70 @@
+{
+ "extends": ["eslint:recommended", "google"],
+ "installedESLint": true,
+ "env": {
+ "browser": true,
+ "es6": true
+ },
+ "globals": {
+ "__dirname": false,
+ "app": false,
+ "page": false,
+ "Polymer": false,
+ "process": false,
+ "require": false,
+ "Gerrit": false,
+ "Promise": false,
+ "assert": false,
+ "test": false,
+ "flushAsynchronousOperations": false
+ },
+ "rules": {
+ "arrow-parens": ["error", "as-needed"],
+ "brace-style": ["error", "1tbs", { "allowSingleLine": true }],
+ "camelcase": "off",
+ "comma-dangle": ["error", "always-multiline"],
+ "eol-last": "off",
+ "indent": ["error", 2, {
+ "MemberExpression": 2,
+ "FunctionDeclaration": {"body": 1, "parameters": 2},
+ "FunctionExpression": {"body": 1, "parameters": 2},
+ "CallExpression": {"arguments": 2},
+ "ArrayExpression": 1,
+ "ObjectExpression": 1,
+ "SwitchCase": 1
+ }],
+ "max-len": [
+ "error",
+ 80,
+ 2,
+ {"ignoreComments": true}
+ ],
+ "new-cap": ["error", { "capIsNewExceptions": ["Polymer"] }],
+ "no-console": "off",
+ "no-restricted-syntax": [
+ "error",
+ {
+ "selector": "BinaryExpression > CallExpression > MemberExpression > Identifier[name = 'indexOf']",
+ "message": "Prefer includes/startsWith to indexOf."
+ },
+ {
+ "selector": "ExpressionStatement > CallExpression > MemberExpression > Identifier[name = 'forEach']",
+ "message": "Prefer for-of to Array.forEach."
+ }
+ ],
+ "no-undef": "off",
+ "no-var": "error",
+ "object-shorthand": ["error", "always"],
+ "prefer-arrow-callback": "error",
+ "prefer-const": "error",
+ "prefer-spread": "error",
+ "quote-props": ["error", "consistent-as-needed"],
+ "require-jsdoc": "off",
+ "semi": [2, "always"],
+ "template-curly-spacing": "error",
+ "valid-jsdoc": "off"
+ },
+ "plugins": [
+ "html"
+ ]
+}
diff --git a/polygerrit-ui/README.md b/polygerrit-ui/README.md
index 77d5781..0fdbd44 100644
--- a/polygerrit-ui/README.md
+++ b/polygerrit-ui/README.md
@@ -116,3 +116,22 @@
We follow the [Google JavaScript Style Guide](https://google.github.io/styleguide/javascriptguide.xml)
with a few exceptions. When in doubt, remain consistent with the code around you.
+
+In addition, we encourage the use of [ESLint](http://eslint.org/).
+It is available as a command line utility, as well as a plugin for most editors
+and IDEs. It, along with a few dependencies, can also be installed through NPM:
+
+```sh
+sudo npm install -g eslint eslint-config-google eslint-plugin-html
+```
+
+`eslint-config-google` is a port of the Google JS Style Guide to an ESLint
+config module, and `eslint-plugin-html` allows ESLint to lint scripts inside
+HTML.
+We have an .eslintrc.json config file in the polygerrit-ui/ directory configured
+to enforce the preferred style of the PolyGerrit project.
+After installing, you can use `eslint` on any new file you create.
+In addition, you can supply the `--fix` flag to apply some suggested fixes for
+simple style issues.
+If you modify JS inside of `<script>` tags, like for test suites, you may have
+to supply the `--ext .html` flag.
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
index a51632a..31721a0 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
@@ -47,8 +47,10 @@
var ChangeActions = {
ABANDON: 'abandon',
DELETE: '/',
+ IGNORE: 'ignore',
RESTORE: 'restore',
REVERT: 'revert',
+ UNIGNORE: 'unignore',
};
// TODO(andybons): Add the rest of the revision actions.
@@ -206,6 +208,14 @@
type: ActionType.REVISION,
key: RevisionActions.DOWNLOAD,
},
+ {
+ type: ActionType.CHANGE,
+ key: ChangeActions.IGNORE,
+ },
+ {
+ type: ActionType.CHANGE,
+ key: ChangeActions.UNIGNORE,
+ },
];
return value;
},
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
index fa56bb5..4721fdf 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
@@ -557,6 +557,89 @@
});
});
+ suite('ignore change', function() {
+ var fireActionStub;
+
+ setup(function(done) {
+ fireActionStub = sandbox.stub(element, '_fireAction');
+
+ var IgnoreAction = {
+ __key: 'ignore',
+ __type: 'change',
+ __primary: false,
+ method: 'PUT',
+ label: 'Ignore',
+ title: 'Working...',
+ enabled: true,
+ };
+
+ element.actions = {
+ ignore: IgnoreAction,
+ };
+
+ element.changeNum = '2';
+ element.patchNum = '2';
+
+ element.reload().then(function() {flush(done)});
+ });
+
+ test('make sure the ignore button is not outside of the overflow menu',
+ function() {
+ assert.isNotOk(element.$$('[data-action-key="ignore"]'));
+ });
+
+ test('ignoring change', function() {
+ assert.isOk(element.$.moreActions.$$('span[data-id="ignore-change"]'));
+ element.setActionOverflow('change', 'ignore', false);
+ flushAsynchronousOperations();
+ assert.isOk(element.$$('[data-action-key="ignore"]'));
+ assert.isNotOk(
+ element.$.moreActions.$$('span[data-id="ignore-change"]'));
+ });
+ });
+
+ suite('unignore change', function() {
+ var fireActionStub;
+
+ setup(function(done) {
+ fireActionStub = sandbox.stub(element, '_fireAction');
+
+ var UnignoreAction = {
+ __key: 'unignore',
+ __type: 'change',
+ __primary: false,
+ method: 'PUT',
+ label: 'Unignore',
+ title: 'Working...',
+ enabled: true,
+ };
+
+ element.actions = {
+ unignore: UnignoreAction,
+ };
+
+ element.changeNum = '2';
+ element.patchNum = '2';
+
+ element.reload().then(function() {flush(done)});
+ });
+
+
+ test('unignore button is not outside of the overflow menu', function() {
+ assert.isNotOk(element.$$('[data-action-key="unignore"]'));
+ });
+
+ test('unignoring change', function() {
+ assert.isOk(
+ element.$.moreActions.$$('span[data-id="unignore-change"]'));
+ element.setActionOverflow('change', 'unignore', false);
+ flushAsynchronousOperations();
+ assert.isOk(element.$$('[data-action-key="unignore"]'));
+ assert.isNotOk(
+ element.$.moreActions.$$('span[data-id="unignore-change"]'));
+ });
+ });
+
suite('quick approve', function() {
setup(function() {
element.change = {
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
index 32b0a4d..1c5dd59 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
@@ -22,40 +22,10 @@
<script src="../../../bower_components/web-component-tester/browser.js"></script>
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
+<link rel="import" href="../../plugins/gr-plugin-host/gr-plugin-host.html">
<link rel="import" href="gr-change-metadata.html">
-<test-fixture id="plugin">
- <template>
- <script>
- Gerrit.install(function(plugin) {
- plugin.registerStyleModule('change-metadata', 'some-style');
- }, '', 'http://x/plugins/foo.js');
- </script>
- </template>
-</test-fixture>
-
-<test-fixture id="some-style">
- <template>
- <dom-module id="some-style">
- <style>
- :root {
- --change-metadata-assignee: {
- display: none;
- }
- --change-metadata-label-status: {
- display: none;
- }
- --change-metadata-strategy: {
- display: none;
- }
- --change-metadata-topic: {
- display: none;
- }
- }
- </style>
- </dom-module>
- </template>
-</test-fixture>
+<script>void(0);</script>
<test-fixture id="element">
<template>
@@ -63,10 +33,15 @@
</template>
</test-fixture>
+<test-fixture id="plugin-host">
+ <template>
+ <gr-plugin-host></gr-plugin-host>
+ </template>
+</test-fixture>
+
<script>
suite('gr-change-metadata integration tests', function() {
var sandbox;
- var plugin;
var element;
var sectionSelectors = [
@@ -82,19 +57,20 @@
};
setup(function() {
- Gerrit._pluginsPending = 0;
sandbox = sinon.sandbox.create();
stub('gr-change-metadata', {
_computeShowLabelStatus: function() { return true; },
_computeShowReviewersByState: function() { return true; },
ready: function() {
- this.change = {labels:[]};
+ this.change = {labels: []};
this.serverConfig = {};
},
});
});
teardown(function() {
+ Gerrit._pluginsPending = -1;
+ Gerrit._allPluginsPromise = undefined;
sandbox.restore();
});
@@ -106,26 +82,32 @@
sectionSelectors.forEach(function(sectionSelector) {
test(sectionSelector + ' does not have display: none', function() {
- assert.notEqual(
- getStyle(sectionSelector, 'display'), 'none');
- });
+ assert.notEqual(getStyle(sectionSelector, 'display'), 'none');
+ });
});
});
suite('with plugin style', function() {
- var styleEl;
-
setup(function(done) {
- styleEl = fixture('some-style');
+ var pluginHost = fixture('plugin-host');
+ pluginHost.config = {
+ js_resource_paths: [],
+ html_resource_paths: [
+ new URL('test/plugin.html', window.location.href).toString(),
+ ]
+ };
element = fixture('element');
- plugin = fixture('plugin');
- flush(done);
+ var importSpy = sandbox.spy(element.$.externalStyle, '_import');
+ Gerrit.awaitPluginsLoaded().then(function() {
+ Promise.all(importSpy.returnValues).then(function() {
+ flush(done);
+ });
+ });
});
sectionSelectors.forEach(function(sectionSelector) {
test(sectionSelector + ' may have display: none', function() {
- assert.equal(
- getStyle(sectionSelector, 'display'), 'none');
+ assert.equal(getStyle(sectionSelector, 'display'), 'none');
});
});
});
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
index 2feab27..778b09c 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
@@ -78,6 +78,11 @@
.webLink {
display: block;
}
+ #missingLabels {
+ padding-left: 1.5em;
+ }
+
+ /* CSS Mixins should be applied last. */
section.assignee {
@apply(--change-metadata-assignee);
}
@@ -90,9 +95,6 @@
section.topic {
@apply(--change-metadata-topic);
}
- #missingLabels {
- padding-left: 1.5em;
- }
@media screen and (max-width: 50em), screen and (min-width: 75em) {
:host {
display: table;
@@ -114,7 +116,7 @@
}
}
</style>
- <gr-external-style name="change-metadata">
+ <gr-external-style id="externalStyle" name="change-metadata">
<section>
<span class="title">Updated</span>
<span class="value">
@@ -163,7 +165,7 @@
</section>
</template>
<template is="dom-if" if="[[!_showReviewersByState]]">
- <section>
+ <section class="assignee">
<span class="title">Assignee</span>
<span class="value">
<gr-account-list
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/test/plugin.html b/polygerrit-ui/app/elements/change/gr-change-metadata/test/plugin.html
new file mode 100644
index 0000000..1cd3138
--- /dev/null
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/test/plugin.html
@@ -0,0 +1,26 @@
+<dom-module id="my-plugin">
+ <script>
+ Gerrit.install(function(plugin) {
+ plugin.registerStyleModule('change-metadata', 'my-plugin-style');
+ });
+ </script>
+</dom-module>
+
+<dom-module id="my-plugin-style">
+ <style>
+ html {
+ --change-metadata-assignee: {
+ display: none;
+ }
+ --change-metadata-label-status: {
+ display: none;
+ }
+ --change-metadata-strategy: {
+ display: none;
+ }
+ --change-metadata-topic: {
+ display: none;
+ }
+ }
+ </style>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index 1a7765c..4a50dbb 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -1177,10 +1177,14 @@
this._updateCheckTimerHandle = this.async(function() {
this.fetchIsLatestKnown(this._change, this.$.restAPI)
.then(function(latest) {
- if (!latest) {
+ if (latest) {
+ this._startUpdateCheckTimer();
+ } else {
this._cancelUpdateCheckTimer();
this.fire('show-alert', {
message: 'A newer patch has been uploaded.',
+ // Persist this alert.
+ dismissOnNavigation: true,
action: 'Reload',
callback: function() {
// Load the current change without any patch range.
@@ -1189,7 +1193,6 @@
}.bind(this),
});
}
- this._startUpdateCheckTimer();
}.bind(this));
}, this.serverConfig.change.update_delay * 1000);
},
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
index 27dcd4a..ab5ecc2 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
@@ -96,7 +96,8 @@
},
_handleShowAlert: function(e) {
- this._showAlert(e.detail.message, e.detail.action, e.detail.callback);
+ this._showAlert(e.detail.message, e.detail.action, e.detail.callback,
+ e.detail.dismissOnNavigation);
},
_handleNetworkError: function(e) {
@@ -108,12 +109,18 @@
return this.$.restAPI.getLoggedIn();
},
- _showAlert: function(text, opt_actionText, opt_actionCallback) {
+ _showAlert: function(text, opt_actionText, opt_actionCallback,
+ dismissOnNavigation) {
if (this._alertElement) { return; }
this._clearHideAlertHandle();
- this._hideAlertHandle =
- this.async(this._hideAlert, HIDE_ALERT_TIMEOUT_MS);
+ if (dismissOnNavigation) {
+ // Persist alert until navigation.
+ this.listen(document, 'location-change', '_hideAlert');
+ } else {
+ this._hideAlertHandle =
+ this.async(this._hideAlert, HIDE_ALERT_TIMEOUT_MS);
+ }
var el = this._createToastAlert();
el.show(text, opt_actionText, opt_actionCallback);
this._alertElement = el;
@@ -124,6 +131,9 @@
this._alertElement.hide();
this._alertElement = null;
+
+ // Remove listener for page navigation, if it exists.
+ this.unlisten(document, 'location-change', '_hideAlert');
},
_clearHideAlertHandle: function() {
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
index c8743fb..83d4a7b 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
@@ -272,5 +272,21 @@
done();
});
});
+
+ test('dismissOnNavigation respected', function() {
+ var asyncStub = sandbox.stub(element, 'async');
+ var hideSpy = sandbox.spy(element, '_hideAlert');
+ // No async call when dismissOnNavigation supplied.
+ element._showAlert('test', null, null, true);
+ assert.isFalse(asyncStub.called);
+
+ // When page nav happens, clear alert.
+ document.dispatchEvent(new CustomEvent('location-change'));
+ assert.isTrue(hideSpy.called);
+
+ // When timeout is not supplied, use HIDE_ALERT_TIMEOUT_MS.
+ element._showAlert('test');
+ assert.isTrue(asyncStub.called);
+ });
});
</script>
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html
index 1e6596b..265e970 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html
@@ -51,7 +51,7 @@
position: relative;
}
.linksTitle {
- color: black;
+ color: var(--primary-text-color);
display: inline-block;
position: relative;
}
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
index affa8e5..ab042c4 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
@@ -244,7 +244,7 @@
this.$.restAPI.getPreferences().then(function(prefs) {
this._userLinks =
- prefs.my.map(this._stripHashPrefix).filter(this._isSupportedLink);
+ prefs.my.map(this._fixMyMenuItem).filter(this._isSupportedLink);
}.bind(this));
this._loadAccountCapabilities();
},
@@ -260,10 +260,20 @@
}.bind(this));
},
- _stripHashPrefix: function(linkObj) {
+ _fixMyMenuItem: function(linkObj) {
+ // Normalize all urls to PolyGerrit style.
if (linkObj.url.indexOf('#') === 0) {
linkObj.url = linkObj.url.slice(1);
}
+
+ // Delete target property due to complications of
+ // https://bugs.chromium.org/p/gerrit/issues/detail?id=5888
+ //
+ // The server tries to guess whether URL is a view within the UI.
+ // If not, it sets target='_blank' on the menu item. The server
+ // makes assumptions that work for the GWT UI, but not PolyGerrit,
+ // so we'll just disable it altogether for now.
+ delete linkObj.target;
return linkObj;
},
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html
index 4582b4f..94f1f66 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html
@@ -53,14 +53,16 @@
sandbox.restore();
});
- test('strip hash prefix', function() {
+ test('fix my menu item', function() {
assert.deepEqual([
{url: '#/q/owner:self+is:draft'},
{url: 'https://awesometown.com/#hashyhash'},
- ].map(element._stripHashPrefix),
+ {url: 'url', target: '_blank'},
+ ].map(element._fixMyMenuItem),
[
{url: '/q/owner:self+is:draft'},
{url: 'https://awesometown.com/#hashyhash'},
+ {url: 'url'},
]);
});
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.js b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
index 1e3481f..cc8d478 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -33,16 +33,16 @@
getReporting().pageLoaded();
};
- var base = window.Gerrit.BaseUrlBehavior.getBaseUrl();
- if (base) {
- page.base(base);
- }
-
window.addEventListener('WebComponentsReady', function() {
getReporting().timeEnd('WebComponentsReady');
});
function startRouter() {
+ var base = window.Gerrit.BaseUrlBehavior.getBaseUrl();
+ if (base) {
+ page.base(base);
+ }
+
var restAPI = document.createElement('gr-rest-api-interface');
var reporting = getReporting();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.js b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.js
index 62e8915..30d01cb 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.js
@@ -36,11 +36,11 @@
* The maximum size for an addition or removal chunk before it is broken down
* into a series of chunks that are this size at most.
*
- * Note: The value of 70 is chosen so that it is larger than the default
+ * Note: The value of 120 is chosen so that it is larger than the default
* _asyncThreshold of 64, but feel free to tune this constant to your
* performance needs.
*/
- var MAX_GROUP_SIZE = 70;
+ var MAX_GROUP_SIZE = 120;
Polymer({
is: 'gr-diff-processor',
@@ -364,8 +364,11 @@
if (this.context === -1) {
var newContent = [];
content.forEach(function(group) {
- if (group.ab) {
- newContent.push.apply(newContent, this._breakdownGroup(group));
+ if (group.ab && group.ab.length > MAX_GROUP_SIZE * 2) {
+ // Split large shared groups in two, where the first is the maximum
+ // group size.
+ newContent.push({ab: group.ab.slice(0, MAX_GROUP_SIZE)});
+ newContent.push({ab: group.ab.slice(MAX_GROUP_SIZE)});
} else {
newContent.push(group);
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html
index 687b3dd..1a5ccc5 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html
@@ -337,15 +337,16 @@
});
test('breaks-down shared chunks w/ whole-file', function() {
+ var size = 120 * 2 + 5;
var lineNums = {left: 0, right: 0};
var content = [{
- ab: _.times(75, function() { return '' + Math.random(); }),
+ ab: _.times(size, function() { return '' + Math.random(); }),
}];
element.context = -1;
var result = element._splitCommonGroupsWithComments(content, lineNums);
assert.equal(result.length, 2);
- assert.deepEqual(result[0].ab, content[0].ab.slice(0, 5));
- assert.deepEqual(result[1].ab, content[0].ab.slice(5));
+ assert.deepEqual(result[0].ab, content[0].ab.slice(0, 120));
+ assert.deepEqual(result[1].ab, content[0].ab.slice(120));
});
test('does not break-down shared chunks w/ context', function() {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
index c267eb0..5868f77 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
@@ -331,7 +331,10 @@
function() { return Promise.resolve(mockFile1); }));
stubs.push(sandbox.stub(element.$.restAPI,
'getChangeFileContents',
- function() { return Promise.resolve(mockFile2); }));
+ function(changeId, patchNum, path, opt_parentIndex) {
+ return Promise.resolve(opt_parentIndex === 1 ? mockFile1 :
+ mockFile2);
+ }));
stubs.push(sandbox.stub(element.$.restAPI, '_getDiffComments',
function() { return Promise.resolve(mockComments); }));
stubs.push(sandbox.stub(element.$.restAPI, 'getDiffDrafts',
diff --git a/polygerrit-ui/app/elements/gr-app-it_test.html b/polygerrit-ui/app/elements/gr-app-it_test.html
new file mode 100644
index 0000000..66b0f8f
--- /dev/null
+++ b/polygerrit-ui/app/elements/gr-app-it_test.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<!--
+Copyright (C) 2017 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.
+-->
+
+<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
+<title>gr-app-it_test</title>
+
+<script src="../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
+<script src="../bower_components/web-component-tester/browser.js"></script>
+
+<link rel="import" href="../bower_components/iron-test-helpers/iron-test-helpers.html">
+<link rel="import" href="gr-app.html">
+
+<script>void(0);</script>
+
+<test-fixture id="element">
+ <template>
+ <gr-app id="app"></gr-app>
+ </template>
+</test-fixture>
+
+<script>
+ suite('gr-app integration tests', function() {
+ var sandbox;
+ var element;
+
+ setup(function(done) {
+ sandbox = sinon.sandbox.create();
+ stub('gr-reporting', {
+ appStarted: sandbox.stub(),
+ });
+ stub('gr-account-dropdown', {
+ _getTopContent: sinon.stub(),
+ });
+ stub('gr-rest-api-interface', {
+ getAccount: function() { return Promise.resolve(null); },
+ getAccountCapabilities: function() { return Promise.resolve({}); },
+ getConfig: function() {
+ return Promise.resolve({
+ gerrit: {web_uis: ['GWT', 'POLYGERRIT']},
+ plugin: {
+ js_resource_paths: [],
+ html_resource_paths: [
+ new URL('test/plugin.html', window.location.href).toString()
+ ]
+ },
+ });
+ },
+ getVersion: function() { return Promise.resolve(42); },
+ getLoggedIn: function() { return Promise.resolve(false); },
+ });
+ element = fixture('element');
+
+ var importSpy = sandbox.spy(element.$.externalStyle, '_import');
+ Gerrit.awaitPluginsLoaded().then(function() {
+ Promise.all(importSpy.returnValues).then(function() {
+ flush(done);
+ });
+ });
+ });
+
+ teardown(function() {
+ sandbox.restore();
+ });
+
+ test('applies --primary-text-color', function() {
+ assert.equal(
+ element.getComputedStyleValue('--primary-text-color'), '#F00BAA');
+ });
+
+ test('applies --header-background-color', function() {
+ assert.equal(element.getComputedStyleValue('--header-background-color'),
+ '#F01BAA');
+ });
+ test('applies --footer-background-color', function() {
+ assert.equal(element.getComputedStyleValue('--footer-background-color'),
+ '#F02BAA');
+ });
+ });
+</script>
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index bc88b14..6f09701 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -14,28 +14,25 @@
limitations under the License.
-->
+<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../behaviors/base-url-behavior/base-url-behavior.html">
<link rel="import" href="../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html">
-<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../styles/app-theme.html">
-<link rel="import" href="./plugins/gr-plugin-host/gr-plugin-host.html">
-
<link rel="import" href="./admin/gr-admin-view/gr-admin-view.html">
-
-<link rel="import" href="./core/gr-error-manager/gr-error-manager.html">
-<link rel="import" href="./core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.html">
-<link rel="import" href="./core/gr-main-header/gr-main-header.html">
-<link rel="import" href="./core/gr-router/gr-router.html">
-<link rel="import" href="./core/gr-reporting/gr-reporting.html">
-
<link rel="import" href="./change-list/gr-change-list-view/gr-change-list-view.html">
<link rel="import" href="./change-list/gr-dashboard-view/gr-dashboard-view.html">
<link rel="import" href="./change/gr-change-view/gr-change-view.html">
+<link rel="import" href="./core/gr-error-manager/gr-error-manager.html">
+<link rel="import" href="./core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.html">
+<link rel="import" href="./core/gr-main-header/gr-main-header.html">
+<link rel="import" href="./core/gr-reporting/gr-reporting.html">
+<link rel="import" href="./core/gr-router/gr-router.html">
<link rel="import" href="./diff/gr-diff-view/gr-diff-view.html">
+<link rel="import" href="./plugins/gr-external-style/gr-external-style.html">
+<link rel="import" href="./plugins/gr-plugin-host/gr-plugin-host.html">
<link rel="import" href="./settings/gr-cla-view/gr-cla-view.html">
<link rel="import" href="./settings/gr-registration-dialog/gr-registration-dialog.html">
<link rel="import" href="./settings/gr-settings-view/gr-settings-view.html">
-
<link rel="import" href="./shared/gr-overlay/gr-overlay.html">
<link rel="import" href="./shared/gr-rest-api-interface/gr-rest-api-interface.html">
@@ -54,11 +51,11 @@
color: var(--primary-text-color);
}
gr-main-header {
- background-color: var(--header-background-color, #eee);
+ background-color: var(--header-background-color);
padding: 0 var(--default-horizontal-margin);
}
footer {
- background-color: var(--footer-background-color, #eee);
+ background-color: var(--footer-background-color);
display: flex;
justify-content: space-between;
padding: .5rem var(--default-horizontal-margin);
@@ -175,6 +172,7 @@
<gr-plugin-host id="plugins"
config="[[_serverConfig.plugin]]">
</gr-plugin-host>
+ <gr-external-style id="externalStyle" name="app-theme"></gr-external-style>
</template>
<script src="gr-app.js" crossorigin="anonymous"></script>
</dom-module>
diff --git a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js
index 94bc534..162921a 100644
--- a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js
+++ b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js
@@ -21,6 +21,12 @@
name: String,
},
+ _import: function(url) {
+ return new Promise(function(resolve, reject) {
+ this.importHref(url, resolve, reject);
+ }.bind(this));
+ },
+
_applyStyle: function(name) {
var s = document.createElement('style', 'custom-style');
s.setAttribute('include', name);
@@ -31,7 +37,21 @@
Gerrit.awaitPluginsLoaded().then(function() {
var sharedStyles = Gerrit._styleModules[this.name];
if (sharedStyles) {
- sharedStyles.map(this._applyStyle.bind(this));
+ var pluginUrls = [];
+ var moduleNames = [];
+ sharedStyles.reduce(function(result, item) {
+ if (!result.pluginUrls.includes(item.pluginUrl)) {
+ result.pluginUrls.push(item.pluginUrl);
+ }
+ result.moduleNames.push(item.moduleName);
+ return result;
+ }, {pluginUrls: pluginUrls, moduleNames: moduleNames});
+ Promise.all(pluginUrls.map(this._import.bind(this)))
+ .then(function() {
+ moduleNames.forEach(function(name) {
+ this._applyStyle(name);
+ }.bind(this));
+ }.bind(this));
}
}.bind(this));
},
diff --git a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html
index 9c9ab35..f626f71 100644
--- a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html
@@ -35,23 +35,27 @@
var sandbox;
var element;
- setup(function() {
+ setup(function(done) {
sandbox = sinon.sandbox.create();
sandbox.stub(Gerrit, 'awaitPluginsLoaded').returns(Promise.resolve());
+ Gerrit._styleModules = {'foo': [{pluginUrl: 'bar', moduleName: 'baz',}]};
+
element = fixture('basic');
+ sandbox.stub(element, '_applyStyle');
+ sandbox.stub(element, 'importHref', function(url, resolve) { resolve() });
+ flush(done);
});
teardown(function() {
sandbox.restore();
});
- test('applies plugin-provided styles', function(done) {
- Gerrit._styleModules = {'foo': ['bar']};
- sandbox.stub(element, '_applyStyle');
- flush(function() {
- assert.isTrue(element._applyStyle.calledWith('bar'));
- done();
- });
+ test('imports plugin-provided module', function() {
+ assert.isTrue(element.importHref.calledWith('bar'));
+ });
+
+ test('applies plugin-provided styles', function() {
+ assert.isTrue(element._applyStyle.calledWith('baz'));
});
});
</script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js
index ccfe604..1c78689 100644
--- a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js
+++ b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js
@@ -34,7 +34,11 @@
_importHtmlPlugins: function(plugins) {
plugins.forEach(function(url) {
- this.importHref('/' + url, null, Gerrit._pluginInstalled, true);
+ if (url.indexOf('http') !== 0) {
+ url = '/' + url;
+ }
+ this.importHref(
+ url, Gerrit._pluginInstalled, Gerrit._pluginInstalled, true);
}.bind(this));
},
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html
index b0c7c71..5965bc3 100644
--- a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html
@@ -59,9 +59,9 @@
html_resource_paths: ['foo/bar', 'baz'],
};
assert.isTrue(element.importHref.calledWith(
- '/foo/bar', null, Gerrit._pluginInstalled, true));
+ '/foo/bar', Gerrit._pluginInstalled, Gerrit._pluginInstalled, true));
assert.isTrue(element.importHref.calledWith(
- '/baz', null, Gerrit._pluginInstalled, true));
+ '/baz', Gerrit._pluginInstalled, Gerrit._pluginInstalled, true));
});
});
</script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
index 3c8c4a0..402b371 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
@@ -59,7 +59,10 @@
if (!Gerrit._styleModules[stylingEndpointName]) {
Gerrit._styleModules[stylingEndpointName] = [];
}
- Gerrit._styleModules[stylingEndpointName].push(moduleName);
+ Gerrit._styleModules[stylingEndpointName].push({
+ pluginUrl: this._url,
+ moduleName: moduleName,
+ });
};
Plugin.prototype.getServerInfo = function() {
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index dab22d6..d7e3328 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -963,22 +963,25 @@
},
_fetchB64File: function(url) {
- return fetch(this.getBaseUrl() + url, {credentials: 'same-origin'}).then(
- function(response) {
- var type = response.headers.get('X-FYI-Content-Type');
- return response.text()
- .then(function(text) {
- return {body: text, type: type};
+ return fetch(this.getBaseUrl() + url, {credentials: 'same-origin'})
+ .then(function(response) {
+ if (!response.ok) { return Promise.reject(response.statusText); }
+ var type = response.headers.get('X-FYI-Content-Type');
+ return response.text()
+ .then(function(text) {
+ return {body: text, type: type};
+ });
});
- });
},
- getChangeFileContents: function(changeId, patchNum, path) {
+ getChangeFileContents: function(changeId, patchNum, path, opt_parentIndex) {
+ var parent = typeof opt_parentIndex === 'number' ?
+ '?parent=' + opt_parentIndex : '';
return this._fetchB64File(
'/changes/' + encodeURIComponent(changeId) +
'/revisions/' + encodeURIComponent(patchNum) +
'/files/' + encodeURIComponent(path) +
- '/content');
+ '/content' + parent);
},
getCommitFileContents: function(projectName, commit, path) {
@@ -995,16 +998,17 @@
if (diff.meta_a && diff.meta_a.content_type.indexOf('image/') === 0) {
if (patchRange.basePatchNum === 'PARENT') {
- // Need the commit info know the parent SHA.
- promiseA = this.getCommitInfo(project, commit).then(function(info) {
- if (info.parents.length !== 1) {
- return Promise.reject('Change commit has multiple parents.');
- }
- var parent = info.parents[0].commit;
- return this.getCommitFileContents(project, parent,
- diff.meta_a.name);
- }.bind(this));
-
+ // Note: we only attempt to get the image from the first parent.
+ promiseA = this.getChangeFileContents(changeNum, patchRange.patchNum,
+ diff.meta_a.name, 1)
+ .catch(function(result) {
+ // If getting the parent-indexed version of the image fails, it
+ // may be because the API has not been rolled out. Fall back to
+ // getting the file from the commit using the slow API.
+ // NOTE(wyatta): Remove this when the rollout is complete.
+ return this._getImageFromCommit(project, commit,
+ diff.meta_a.name);
+ }.bind(this));
} else {
promiseA = this.getChangeFileContents(changeNum,
patchRange.basePatchNum, diff.meta_a.name);
@@ -1039,6 +1043,19 @@
}.bind(this));
},
+ /**
+ * Remove when parent-indexed file requests are completely rolled out.
+ */
+ _getImageFromCommit: function(project, commit, path) {
+ return this.getCommitInfo(project, commit).then(function(info) {
+ if (info.parents.length !== 1) {
+ return Promise.reject('Change commit has multiple parents.');
+ }
+ var parent = info.parents[0].commit;
+ return this.getCommitFileContents(project, parent, path);
+ }.bind(this));
+ },
+
setChangeTopic: function(changeNum, topic) {
return this.send('PUT', '/changes/' + encodeURIComponent(changeNum) +
'/topic', {topic: topic});
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
index 0ff162d..f2f41b8 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
@@ -34,63 +34,63 @@
</test-fixture>
<script>
- suite('gr-rest-api-interface tests', function() {
- var element;
- var sandbox;
+ suite('gr-rest-api-interface tests', () => {
+ let element;
+ let sandbox;
- setup(function() {
+ setup(() => {
sandbox = sinon.sandbox.create();
element = fixture('basic');
- var testJSON = ')]}\'\n{"hello": "bonjour"}';
+ const testJSON = ')]}\'\n{"hello": "bonjour"}';
sandbox.stub(window, 'fetch').returns(Promise.resolve({
ok: true,
- text: function() {
+ text() {
return Promise.resolve(testJSON);
},
}));
});
- teardown(function() {
+ teardown(() => {
sandbox.restore();
});
- test('JSON prefix is properly removed', function(done) {
- element.fetchJSON('/dummy/url').then(function(obj) {
+ test('JSON prefix is properly removed', done => {
+ element.fetchJSON('/dummy/url').then(obj => {
assert.deepEqual(obj, {hello: 'bonjour'});
done();
});
});
- test('cached results', function(done) {
- var n = 0;
- sandbox.stub(element, 'fetchJSON', function() {
+ test('cached results', done => {
+ let n = 0;
+ sandbox.stub(element, 'fetchJSON', () => {
return Promise.resolve(++n);
});
- var promises = [];
+ const promises = [];
promises.push(element._fetchSharedCacheURL('/foo'));
promises.push(element._fetchSharedCacheURL('/foo'));
promises.push(element._fetchSharedCacheURL('/foo'));
- Promise.all(promises).then(function(results) {
+ Promise.all(promises).then(results => {
assert.deepEqual(results, [1, 1, 1]);
- element._fetchSharedCacheURL('/foo').then(function(foo) {
+ element._fetchSharedCacheURL('/foo').then(foo => {
assert.equal(foo, 1);
done();
});
});
});
- test('cached promise', function(done) {
- var promise = Promise.reject('foo');
+ test('cached promise', done => {
+ const promise = Promise.reject('foo');
element._cache['/foo'] = promise;
- element._fetchSharedCacheURL('/foo').catch(function(p) {
+ element._fetchSharedCacheURL('/foo').catch(p => {
assert.equal(p, 'foo');
done();
});
});
- test('params are properly encoded', function() {
- var url = element._urlWithParams('/path/', {
+ test('params are properly encoded', () => {
+ let url = element._urlWithParams('/path/', {
sp: 'hola',
gr: 'guten tag',
noval: null,
@@ -110,23 +110,23 @@
assert.equal(url, '/path/?l=c&l=b&l=a');
});
- test('request callbacks can be canceled', function(done) {
- var cancelCalled = false;
+ test('request callbacks can be canceled', done => {
+ let cancelCalled = false;
window.fetch.returns(Promise.resolve({
body: {
- cancel: function() { cancelCalled = true; },
+ cancel() { cancelCalled = true; },
},
}));
- element.fetchJSON('/dummy/url', null, function() { return true; }).then(
- function(obj) {
- assert.isUndefined(obj);
- assert.isTrue(cancelCalled);
- done();
- });
+ element.fetchJSON('/dummy/url', null, () => { return true; }).then(
+ obj => {
+ assert.isUndefined(obj);
+ assert.isTrue(cancelCalled);
+ done();
+ });
});
- test('parent diff comments are properly grouped', function(done) {
- sandbox.stub(element, 'fetchJSON', function() {
+ test('parent diff comments are properly grouped', done => {
+ sandbox.stub(element, 'fetchJSON', () => {
return Promise.resolve({
'/COMMIT_MSG': [],
'sieve.go': [
@@ -143,26 +143,26 @@
});
});
element._getDiffComments('42', '', 'PARENT', 1, 'sieve.go').then(
- function(obj) {
- assert.equal(obj.baseComments.length, 1);
- assert.deepEqual(obj.baseComments[0], {
- side: 'PARENT',
- message: 'how did this work in the first place?',
- path: 'sieve.go',
- updated: '2017-02-03 22:33:28.000000000',
+ obj => {
+ assert.equal(obj.baseComments.length, 1);
+ assert.deepEqual(obj.baseComments[0], {
+ side: 'PARENT',
+ message: 'how did this work in the first place?',
+ path: 'sieve.go',
+ updated: '2017-02-03 22:33:28.000000000',
+ });
+ assert.equal(obj.comments.length, 1);
+ assert.deepEqual(obj.comments[0], {
+ message: 'this isn’t quite right',
+ path: 'sieve.go',
+ updated: '2017-02-03 22:32:28.000000000',
+ });
+ done();
});
- assert.equal(obj.comments.length, 1);
- assert.deepEqual(obj.comments[0], {
- message: 'this isn’t quite right',
- path: 'sieve.go',
- updated: '2017-02-03 22:32:28.000000000',
- });
- done();
- });
});
- test('_setRange', function() {
- var comments = [
+ test('_setRange', () => {
+ const comments = [
{
id: 1,
side: 'PARENT',
@@ -182,7 +182,7 @@
updated: '2017-02-03 22:33:28.000000000',
},
];
- var expectedResult = {
+ const expectedResult = {
id: 2,
in_reply_to: 1,
message: 'this isn’t quite right',
@@ -194,12 +194,12 @@
end_character: 1,
},
};
- var comment = comments[1];
+ const comment = comments[1];
assert.deepEqual(element._setRange(comments, comment), expectedResult);
});
- test('_setRanges', function() {
- var comments = [
+ test('_setRanges', () => {
+ const comments = [
{
id: 3,
in_reply_to: 2,
@@ -225,7 +225,7 @@
},
},
];
- var expectedResult = [
+ const expectedResult = [
{
id: 1,
side: 'PARENT',
@@ -266,8 +266,8 @@
assert.deepEqual(element._setRanges(comments), expectedResult);
});
- test('differing patch diff comments are properly grouped', function(done) {
- sandbox.stub(element, 'fetchJSON', function(url) {
+ test('differing patch diff comments are properly grouped', done => {
+ sandbox.stub(element, 'fetchJSON', url => {
if (url == '/changes/42/revisions/1') {
return Promise.resolve({
'/COMMIT_MSG': [],
@@ -305,29 +305,29 @@
}
});
element._getDiffComments('42', '', 1, 2, 'sieve.go').then(
- function(obj) {
- assert.equal(obj.baseComments.length, 1);
- assert.deepEqual(obj.baseComments[0], {
- message: 'this isn’t quite right',
- path: 'sieve.go',
- updated: '2017-02-03 22:32:28.000000000',
+ obj => {
+ assert.equal(obj.baseComments.length, 1);
+ assert.deepEqual(obj.baseComments[0], {
+ message: 'this isn’t quite right',
+ path: 'sieve.go',
+ updated: '2017-02-03 22:32:28.000000000',
+ });
+ assert.equal(obj.comments.length, 2);
+ assert.deepEqual(obj.comments[0], {
+ message: 'What on earth are you thinking, here?',
+ path: 'sieve.go',
+ updated: '2017-02-03 22:32:28.000000000',
+ });
+ assert.deepEqual(obj.comments[1], {
+ message: '¯\\_(ツ)_/¯',
+ path: 'sieve.go',
+ updated: '2017-02-04 22:33:28.000000000',
+ });
+ done();
});
- assert.equal(obj.comments.length, 2);
- assert.deepEqual(obj.comments[0], {
- message: 'What on earth are you thinking, here?',
- path: 'sieve.go',
- updated: '2017-02-03 22:32:28.000000000',
- });
- assert.deepEqual(obj.comments[1], {
- message: '¯\\_(ツ)_/¯',
- path: 'sieve.go',
- updated: '2017-02-04 22:33:28.000000000',
- });
- done();
- });
});
- test('special file path sorting', function() {
+ test('special file path sorting', () => {
assert.deepEqual(
['.b', '/COMMIT_MSG', '.a', 'file'].sort(
element.specialFilePathCompare),
@@ -354,13 +354,13 @@
['foo/bar.h', 'foo/bar.hpp', 'foo/bar.hxx']);
// Regression test for Issue 4448.
- assert.deepEqual([
- 'minidump/minidump_memory_writer.cc',
- 'minidump/minidump_memory_writer.h',
- 'minidump/minidump_thread_writer.cc',
- 'minidump/minidump_thread_writer.h',
- ]
- .sort(element.specialFilePathCompare),
+ assert.deepEqual(
+ [
+ 'minidump/minidump_memory_writer.cc',
+ 'minidump/minidump_memory_writer.h',
+ 'minidump/minidump_thread_writer.cc',
+ 'minidump/minidump_thread_writer.h',
+ ].sort(element.specialFilePathCompare),
[
'minidump/minidump_memory_writer.h',
'minidump/minidump_memory_writer.cc',
@@ -369,102 +369,102 @@
]);
// Regression test for Issue 4545.
- assert.deepEqual([
- 'task_test.go',
- 'task.go',
- ]
- .sort(element.specialFilePathCompare),
+ assert.deepEqual(
+ [
+ 'task_test.go',
+ 'task.go',
+ ].sort(element.specialFilePathCompare),
[
'task.go',
'task_test.go',
]);
});
- suite('rebase action', function() {
- var resolveFetchJSON;
- setup(function() {
+ suite('rebase action', () => {
+ let resolveFetchJSON;
+ setup(() => {
sandbox.stub(element, 'fetchJSON').returns(
- new Promise(function(resolve) {
+ new Promise(resolve => {
resolveFetchJSON = resolve;
}));
});
- test('no rebase on current', function(done) {
+ test('no rebase on current', done => {
element.getChangeRevisionActions('42', '1337').then(
- function(response) {
- assert.isTrue(response.rebase.enabled);
- assert.isFalse(response.rebase.rebaseOnCurrent);
- done();
- });
+ response => {
+ assert.isTrue(response.rebase.enabled);
+ assert.isFalse(response.rebase.rebaseOnCurrent);
+ done();
+ });
resolveFetchJSON({rebase: {}});
});
- test('rebase on current', function(done) {
+ test('rebase on current', done => {
element.getChangeRevisionActions('42', '1337').then(
- function(response) {
- assert.isTrue(response.rebase.enabled);
- assert.isTrue(response.rebase.rebaseOnCurrent);
- done();
- });
+ response => {
+ assert.isTrue(response.rebase.enabled);
+ assert.isTrue(response.rebase.rebaseOnCurrent);
+ done();
+ });
resolveFetchJSON({rebase: {enabled: true}});
});
});
- test('server error', function(done) {
- var getResponseObjectStub = sandbox.stub(element, 'getResponseObject');
+ test('server error', done => {
+ const getResponseObjectStub = sandbox.stub(element, 'getResponseObject');
window.fetch.returns(Promise.resolve({ok: false}));
- var serverErrorEventPromise = new Promise(function(resolve) {
- element.addEventListener('server-error', function() { resolve(); });
+ const serverErrorEventPromise = new Promise(resolve => {
+ element.addEventListener('server-error', () => { resolve(); });
});
element.fetchJSON().then(
- function(response) {
+ response => {
assert.isUndefined(response);
assert.isTrue(getResponseObjectStub.notCalled);
- serverErrorEventPromise.then(function() {
+ serverErrorEventPromise.then(() => {
done();
});
});
});
- test('checkCredentials', function(done) {
- var responses = [
+ test('checkCredentials', done => {
+ const responses = [
{
ok: false,
status: 403,
- text: function() { return Promise.resolve(); },
+ text() { return Promise.resolve(); },
},
{
ok: true,
status: 200,
- text: function() { return Promise.resolve(')]}\'{}'); },
+ text() { return Promise.resolve(')]}\'{}'); },
},
];
window.fetch.restore();
- sandbox.stub(window, 'fetch', function(url) {
+ sandbox.stub(window, 'fetch', url => {
if (url === '/accounts/self/detail') {
return Promise.resolve(responses.shift());
}
});
- element.getLoggedIn().then(function(account) {
+ element.getLoggedIn().then(account => {
assert.isNotOk(account);
- element.checkCredentials().then(function(account) {
+ element.checkCredentials().then(account => {
assert.isOk(account);
done();
});
});
});
- test('legacy n,z key in change url is replaced', function() {
- var stub = sandbox.stub(element, 'fetchJSON');
+ test('legacy n,z key in change url is replaced', () => {
+ const stub = sandbox.stub(element, 'fetchJSON');
element.getChanges(1, null, 'n,z');
assert.equal(stub.args[0][3].S, 0);
});
- test('saveDiffPreferences invalidates cache line', function() {
- var cacheKey = '/accounts/self/preferences.diff';
+ test('saveDiffPreferences invalidates cache line', () => {
+ const cacheKey = '/accounts/self/preferences.diff';
sandbox.stub(element, 'send');
element._cache[cacheKey] = {tab_size: 4};
element.saveDiffPreferences({tab_size: 8});
@@ -472,108 +472,106 @@
assert.notOk(element._cache[cacheKey]);
});
- var preferenceSetup = function(testJSON, loggedIn, smallScreen) {
- sandbox.stub(element, 'getLoggedIn', function() {
+ const preferenceSetup = function(testJSON, loggedIn, smallScreen) {
+ sandbox.stub(element, 'getLoggedIn', () => {
return Promise.resolve(loggedIn);
});
- sandbox.stub(element, '_isNarrowScreen', function() {
+ sandbox.stub(element, '_isNarrowScreen', () => {
return smallScreen;
});
- sandbox.stub(element, '_fetchSharedCacheURL', function() {
+ sandbox.stub(element, '_fetchSharedCacheURL', () => {
return Promise.resolve(testJSON);
});
};
test('getPreferences returns correctly on small screens logged in',
- function(done) {
+ done => {
+ const testJSON = {diff_view: 'SIDE_BY_SIDE'};
+ const loggedIn = true;
+ const smallScreen = true;
- var testJSON = {diff_view: 'SIDE_BY_SIDE'};
- var loggedIn = true;
- var smallScreen = true;
+ preferenceSetup(testJSON, loggedIn, smallScreen);
- preferenceSetup(testJSON, loggedIn, smallScreen);
-
- element.getPreferences().then(function(obj) {
- assert.equal(obj.default_diff_view, 'UNIFIED_DIFF');
- assert.equal(obj.diff_view, 'SIDE_BY_SIDE');
- done();
- });
- });
+ element.getPreferences().then(obj => {
+ assert.equal(obj.default_diff_view, 'UNIFIED_DIFF');
+ assert.equal(obj.diff_view, 'SIDE_BY_SIDE');
+ done();
+ });
+ });
test('getPreferences returns correctly on small screens not logged in',
- function(done) {
+ done => {
+ const testJSON = {diff_view: 'SIDE_BY_SIDE'};
+ const loggedIn = false;
+ const smallScreen = true;
- var testJSON = {diff_view: 'SIDE_BY_SIDE'};
- var loggedIn = false;
- var smallScreen = true;
-
- preferenceSetup(testJSON, loggedIn, smallScreen);
- element.getPreferences().then(function(obj) {
- assert.equal(obj.default_diff_view, 'UNIFIED_DIFF');
- assert.equal(obj.diff_view, 'SIDE_BY_SIDE');
- done();
- });
- });
+ preferenceSetup(testJSON, loggedIn, smallScreen);
+ element.getPreferences().then(obj => {
+ assert.equal(obj.default_diff_view, 'UNIFIED_DIFF');
+ assert.equal(obj.diff_view, 'SIDE_BY_SIDE');
+ done();
+ });
+ });
test('getPreferences returns correctly on larger screens logged in',
- function(done) {
- var testJSON = {diff_view: 'UNIFIED_DIFF'};
- var loggedIn = true;
- var smallScreen = false;
+ done => {
+ const testJSON = {diff_view: 'UNIFIED_DIFF'};
+ const loggedIn = true;
+ const smallScreen = false;
- preferenceSetup(testJSON, loggedIn, smallScreen);
+ preferenceSetup(testJSON, loggedIn, smallScreen);
- element.getPreferences().then(function(obj) {
- assert.equal(obj.default_diff_view, 'UNIFIED_DIFF');
- assert.equal(obj.diff_view, 'UNIFIED_DIFF');
- done();
- });
- });
+ element.getPreferences().then(obj => {
+ assert.equal(obj.default_diff_view, 'UNIFIED_DIFF');
+ assert.equal(obj.diff_view, 'UNIFIED_DIFF');
+ done();
+ });
+ });
test('getPreferences returns correctly on larger screens not logged in',
- function(done) {
- var testJSON = {diff_view: 'UNIFIED_DIFF'};
- var loggedIn = false;
- var smallScreen = false;
+ done => {
+ const testJSON = {diff_view: 'UNIFIED_DIFF'};
+ const loggedIn = false;
+ const smallScreen = false;
- preferenceSetup(testJSON, loggedIn, smallScreen);
+ preferenceSetup(testJSON, loggedIn, smallScreen);
- element.getPreferences().then(function(obj) {
- assert.equal(obj.default_diff_view, 'SIDE_BY_SIDE');
- assert.equal(obj.diff_view, 'SIDE_BY_SIDE');
- done();
- });
- });
+ element.getPreferences().then(obj => {
+ assert.equal(obj.default_diff_view, 'SIDE_BY_SIDE');
+ assert.equal(obj.diff_view, 'SIDE_BY_SIDE');
+ done();
+ });
+ });
- test('savPreferences normalizes download scheme', function() {
+ test('savPreferences normalizes download scheme', () => {
sandbox.stub(element, 'send');
element.savePreferences({download_scheme: 'HTTP'});
assert.isTrue(element.send.called);
assert.equal(element.send.lastCall.args[2].download_scheme, 'http');
});
- test('confirmEmail', function() {
+ test('confirmEmail', () => {
sandbox.spy(element, 'send');
element.confirmEmail('foo');
assert.isTrue(element.send.calledWith(
'PUT', '/config/server/email.confirm', {token: 'foo'}));
});
- test('GrReviewerUpdatesParser.parse is used', function() {
+ test('GrReviewerUpdatesParser.parse is used', () => {
sandbox.stub(GrReviewerUpdatesParser, 'parse').returns(
Promise.resolve('foo'));
- return element.getChangeDetail(42).then(function(result) {
+ return element.getChangeDetail(42).then(result => {
assert.isTrue(GrReviewerUpdatesParser.parse.calledOnce);
assert.equal(result, 'foo');
});
});
- test('setAccountStatus', function(done) {
+ test('setAccountStatus', done => {
sandbox.stub(element, 'send').returns(Promise.resolve('OOO'));
sandbox.stub(element, 'getResponseObject')
.returns(Promise.resolve('OOO'));
element._cache['/accounts/self/detail'] = {};
- element.setAccountStatus('OOO').then(function() {
+ element.setAccountStatus('OOO').then(() => {
assert.isTrue(element.send.calledWith('PUT', '/accounts/self/status',
{status: 'OOO'}));
assert.deepEqual(element._cache['/accounts/self/detail'],
@@ -582,24 +580,24 @@
});
});
- test('_sendDiffDraft pending requests tracked', function(done) {
- sandbox.stub(element, 'send', function() {
+ test('_sendDiffDraft pending requests tracked', done => {
+ sandbox.stub(element, 'send', () => {
assert.equal(element._pendingRequests.sendDiffDraft, 1);
return Promise.resolve([]);
});
- element.saveDiffDraft('', 1, 1).then(function() {
+ element.saveDiffDraft('', 1, 1).then(() => {
assert.equal(element._pendingRequests.sendDiffDraft, 0);
- element.deleteDiffDraft('', 1, 1).then(function() {
+ element.deleteDiffDraft('', 1, 1).then(() => {
assert.equal(element._pendingRequests.sendDiffDraft, 0);
done();
});
});
});
- test('saveChangeEdit', function(done) {
- var change_num = '1';
- var file_name = 'index.php';
- var file_contents = '<?php';
+ test('saveChangeEdit', done => {
+ const change_num = '1';
+ const file_name = 'index.php';
+ const file_contents = '<?php';
sandbox.stub(element, 'send').returns(
Promise.resolve([change_num, file_name, file_contents])
);
@@ -607,7 +605,7 @@
.returns(Promise.resolve([change_num, file_name, file_contents]));
element._cache['/changes/' + change_num + '/edit/' + file_name] = {};
element.saveChangeEdit(change_num, file_name, file_contents).then(
- function() {
+ () => {
assert.isTrue(element.send.calledWith('PUT',
'/changes/' + change_num + '/edit/' + file_name,
file_contents));
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html
index 1ae04a0..73d0dd2 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html
@@ -27,20 +27,20 @@
<script src="gr-reviewer-updates-parser.js"></script>
<script>
- suite('gr-reviewer-updates-parser tests', function() {
- var sandbox;
- var instance;
+ suite('gr-reviewer-updates-parser tests', () => {
+ let sandbox;
+ let instance;
- setup(function() {
+ setup(() => {
sandbox = sinon.sandbox.create();
});
- teardown(function() {
+ teardown(() => {
sandbox.restore();
});
- test('ignores changes without messages', function() {
- var change = {};
+ test('ignores changes without messages', () => {
+ const change = {};
sandbox.stub(
GrReviewerUpdatesParser.prototype, '_filterRemovedMessages');
sandbox.stub(
@@ -56,8 +56,8 @@
GrReviewerUpdatesParser.prototype._formatUpdates.called);
});
- test('ignores changes without reviewer updates', function() {
- var change = {
+ test('ignores changes without reviewer updates', () => {
+ const change = {
messages: [],
};
sandbox.stub(
@@ -75,8 +75,8 @@
GrReviewerUpdatesParser.prototype._formatUpdates.called);
});
- test('ignores changes with empty reviewer updates', function() {
- var change = {
+ test('ignores changes with empty reviewer updates', () => {
+ const change = {
messages: [],
reviewer_updates: [],
};
@@ -95,18 +95,18 @@
GrReviewerUpdatesParser.prototype._formatUpdates.called);
});
- test('filter removed messages', function() {
- var change = {
- messages: [
- {
- message: 'msg1',
- tag: 'autogenerated:gerrit:deleteReviewer',
- },
- {
- message: 'msg2',
- tag: 'foo',
- }
- ],
+ test('filter removed messages', () => {
+ const change = {
+ messages: [
+ {
+ message: 'msg1',
+ tag: 'autogenerated:gerrit:deleteReviewer',
+ },
+ {
+ message: 'msg2',
+ tag: 'foo',
+ },
+ ],
};
instance = new GrReviewerUpdatesParser(change);
instance._filterRemovedMessages();
@@ -118,22 +118,22 @@
});
});
- test('group reviewer updates', function() {
- var reviewer1 = {_account_id: 1};
- var reviewer2 = {_account_id: 2};
- var date1 = '2017-01-26 12:11:50.000000000';
- var date2 = '2017-01-26 12:11:55.000000000'; // Within threshold.
- var date3 = '2017-01-26 12:33:50.000000000';
- var date4 = '2017-01-26 12:44:50.000000000';
- var makeItem = function(state, reviewer, opt_date, opt_author) {
+ test('group reviewer updates', () => {
+ const reviewer1 = {_account_id: 1};
+ const reviewer2 = {_account_id: 2};
+ const date1 = '2017-01-26 12:11:50.000000000';
+ const date2 = '2017-01-26 12:11:55.000000000'; // Within threshold.
+ const date3 = '2017-01-26 12:33:50.000000000';
+ const date4 = '2017-01-26 12:44:50.000000000';
+ const makeItem = function(state, reviewer, opt_date, opt_author) {
return {
- reviewer: reviewer,
+ reviewer,
updated: opt_date || date1,
updated_by: opt_author || reviewer1,
- state: state,
+ state,
};
};
- var change = {
+ let change = {
reviewer_updates: [
makeItem('REVIEWER', reviewer1), // New group.
makeItem('CC', reviewer2), // Appended.
@@ -198,36 +198,36 @@
]);
});
- test('format reviewer updates', function() {
- var reviewer1 = {_account_id: 1};
- var reviewer2 = {_account_id: 2};
- var makeItem = function(prev, state, opt_reviewer) {
+ test('format reviewer updates', () => {
+ const reviewer1 = {_account_id: 1};
+ const reviewer2 = {_account_id: 2};
+ const makeItem = function(prev, state, opt_reviewer) {
return {
reviewer: opt_reviewer || reviewer1,
prev_state: prev,
- state: state,
+ state,
};
};
- var makeUpdate = function(items) {
+ const makeUpdate = function(items) {
return {
author: reviewer1,
updated: '',
updates: items,
};
};
- var change = {
- reviewer_updates: [
- makeUpdate([
- makeItem(undefined, 'CC'),
- makeItem(undefined, 'CC', reviewer2)
- ]),
- makeUpdate([
- makeItem('CC', 'REVIEWER'),
- makeItem('REVIEWER', 'REMOVED'),
- makeItem('REMOVED', 'REVIEWER'),
- makeItem(undefined, 'REVIEWER', reviewer2),
- ]),
- ],
+ const change = {
+ reviewer_updates: [
+ makeUpdate([
+ makeItem(undefined, 'CC'),
+ makeItem(undefined, 'CC', reviewer2),
+ ]),
+ makeUpdate([
+ makeItem('CC', 'REVIEWER'),
+ makeItem('REVIEWER', 'REMOVED'),
+ makeItem('REMOVED', 'REVIEWER'),
+ makeItem(undefined, 'REVIEWER', reviewer2),
+ ]),
+ ],
};
instance = new GrReviewerUpdatesParser(change);
@@ -237,7 +237,7 @@
assert.equal(change.reviewer_updates[0].updates.length, 1);
assert.equal(change.reviewer_updates[1].updates.length, 3);
- var items = change.reviewer_updates[0].updates;
+ let items = change.reviewer_updates[0].updates;
assert.equal(items[0].message, 'added to CC: ');
assert.deepEqual(items[0].reviewers, [reviewer1, reviewer2]);
diff --git a/polygerrit-ui/app/elements/test/plugin.html b/polygerrit-ui/app/elements/test/plugin.html
new file mode 100644
index 0000000..0314655
--- /dev/null
+++ b/polygerrit-ui/app/elements/test/plugin.html
@@ -0,0 +1,17 @@
+<dom-module id="my-plugin">
+ <script>
+ Gerrit.install(function(plugin) {
+ plugin.registerStyleModule('app-theme', 'myplugin-app-theme');
+ });
+ </script>
+</dom-module>
+
+<dom-module id="myplugin-app-theme">
+ <style>
+ html {
+ --primary-text-color: #F00BAA;
+ --header-background-color: #F01BAA;
+ --footer-background-color: #F02BAA;
+ }
+ </style>
+</dom-module>
diff --git a/polygerrit-ui/app/styles/app-theme.html b/polygerrit-ui/app/styles/app-theme.html
index 773b341..e88b70c 100644
--- a/polygerrit-ui/app/styles/app-theme.html
+++ b/polygerrit-ui/app/styles/app-theme.html
@@ -15,7 +15,12 @@
-->
<style is="custom-style">
:root {
+ /* Following vars have LTS for plugin API. */
--primary-text-color: #000;
+ --header-background-color: #eee;
+ --footer-background-color: var(--header-background-color);
+
+ /* Following are not part of plugin API. */
--search-border-color: #ddd;
--selection-background-color: #ebf5fb;
--default-text-color: #000;
@@ -23,7 +28,6 @@
--default-horizontal-margin: 1rem;
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
--monospace-font-family: 'Source Code Pro', Menlo, 'Lucida Console', Monaco, monospace;
-
--iron-overlay-backdrop: {
transition: none;
};