Merge branch 'master' into stable-2.14
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index ddabe77..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright 2014 Criteo
-#
-# 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.
-
-language: java
-
-sudo: false
-
-addons:
- apt:
- pakages:
- - automake
- - autoconf
- - autogen
-
-install:
- - cd ../..
- - mkdir -p build
- - cd build
- - git clone https://gerrit.googlesource.com/buck
- - cd buck
- - ant
- - export PATH=$PATH:$TRAVIS_BUILD_DIR/../../build/buck/bin
- - cd ..
- - git clone -b stable-2.11 https://gerrit.googlesource.com/gerrit
- - cd gerrit
- - ln -s $TRAVIS_BUILD_DIR plugins
- - travis_retry tools/download_all.py > download.log
-
-script:
- - buck clean
- - buck build gerrit > buck.log
- - buck build plugins/automerge-plugin:automerge-plugin >> buck.log
-
-after_failure:
- - cat buck.log
-
-before_deploy:
- - cd $TRAVIS_BUILD_DIR
- - git fetch --tags
-
-deploy:
- provider: releases
- skip_cleanup: true
- api_key:
- secure: Hze64QC7F5SSOVoufSIPtRWb+t6Pzzvx2kJgLtPJYUj87CKOXYzVHVqHuWsa50DPfed9knDnm5nOJawZAxleXG5VxSvBERvSyUNhjNUbDkKson1/TcCl12YM5FcyM2ocsLYe/mc59V3h9LZR2mHDqVj/incxwAIxV/MJIgu5PBg=
- file: ../../build/gerrit/buck-out/gen/plugins/automerge-plugin/automerge-plugin.jar
- on:
- repo: criteo/automerge-plugin
- tags: true
- all_branches: true
diff --git a/BUCK b/BUCK
deleted file mode 100644
index 9a96483..0000000
--- a/BUCK
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2014 Criteo
-#
-# 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.
-
-include_defs('//bucklets/gerrit_plugin.bucklet')
-
-gerrit_plugin(
- name = 'automerge-plugin',
- srcs = glob(['src/main/java/**/*.java']),
- manifest_entries = [
- 'Gerrit-PluginName: automerge',
- 'Gerrit-Module: com.criteo.gerrit.plugins.automerge.AutomergeModule',
- 'Implementation-Title: Automerge plugin',
- 'Implementation-URL: https://github.com/criteo/automerge-plugin'
- ]
-)
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..30b996a
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,11 @@
+load("//tools/bzl:plugin.bzl", "gerrit_plugin")
+
+gerrit_plugin(
+ name = "automerge-plugin",
+ srcs = glob(["src/main/java/**/*.java"]),
+ manifest_entries = [
+ "Gerrit-PluginName: automerge-plugin",
+ "Gerrit-Module: com.criteo.gerrit.plugins.automerge.AutomergeModule",
+ ],
+ resources = glob(["src/main/resources/*"]),
+)
diff --git a/README.md b/README.md
index cace79e..0be924e 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
automerge-plugin
================
-[![Build Status](https://travis-ci.org/criteo/automerge-plugin.svg?branch=master)](https://travis-ci.org/criteo/automerge-plugin)
+[![Build Status](https://gerrit-ci.gerritforge.com/view/Plugins-stable-2.14/job/plugin-automerge-plugin-gh-bazel-stable-2.14/badge/icon)](https://gerrit-ci.gerritforge.com/view/Plugins-stable-2.14/job/plugin-automerge-plugin-gh-bazel-stable-2.14/)
-A [gerrit](https://code.google.com/p/gerrit/) plugin that takes care of
+A [gerrit](https://www.gerritcodereview.com) plugin that takes care of
automatically merging reviews when all approvals are present.
Also, it introduces the concept of cross-repository reviews.
@@ -11,4 +11,4 @@
in different gerrit repositories. They will be merged at the same time,
when all approvals for all reviews are present, and all reviews are mergeable.
-Requires Gerrit 2.11 or later.
+Requires Gerrit 2.14 or later.
diff --git a/src/main/java/com/criteo/gerrit/plugins/automerge/AtomicityHelper.java b/src/main/java/com/criteo/gerrit/plugins/automerge/AtomicityHelper.java
index e65d35e..00604e4 100644
--- a/src/main/java/com/criteo/gerrit/plugins/automerge/AtomicityHelper.java
+++ b/src/main/java/com/criteo/gerrit/plugins/automerge/AtomicityHelper.java
@@ -6,6 +6,7 @@
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountByEmailCache;
@@ -73,15 +74,16 @@
* Check if the current patchset of the specified change has dependent
* unmerged changes.
*
+ * @param project
* @param number
* @return true or false
* @throws IOException
* @throws NoSuchChangeException
* @throws OrmException
*/
- public boolean hasDependentReview(final int number) throws IOException, NoSuchChangeException, OrmException {
- final RevisionResource r = getRevisionResource(number);
- final RelatedInfo related = getRelated.apply(r);
+ public boolean hasDependentReview(String project, int number) throws IOException, NoSuchChangeException, OrmException {
+ RevisionResource r = getRevisionResource(project, number);
+ RelatedInfo related = getRelated.apply(r);
log.debug(String.format("Checking for related changes on review %d", number));
return related.changes.size() > 0;
}
@@ -102,16 +104,17 @@
/**
* Check if a change is submitable.
*
+ * @param project a change project
* @param change a change number
* @return true or false
* @throws OrmException
*/
- public boolean isSubmittable(final int change) throws OrmException {
- final ChangeData changeData = changeDataFactory.create(db.get(), new Change.Id(change));
+ public boolean isSubmittable(String project, int change) throws OrmException {
+ ChangeData changeData = changeDataFactory.create(db.get(), new Project.NameKey(project), new Change.Id(change));
// For draft reviews, the patchSet must be set to avoid an NPE.
final List<SubmitRecord> cansubmit = new SubmitRuleEvaluator(changeData).setPatchSet(changeData.currentPatchSet()).evaluate();
log.debug(String.format("Checking if change %d is submitable.", change));
- for (final SubmitRecord submit : cansubmit) {
+ for (SubmitRecord submit : cansubmit) {
if (submit.status != SubmitRecord.Status.OK) {
log.debug(String.format("Change %d is not submitable", change));
return false;
@@ -133,14 +136,14 @@
public void mergeReview(ChangeInfo info) throws RestApiException, NoSuchChangeException, OrmException, IOException {
final SubmitInput input = new SubmitInput();
input.waitForMerge = true;
- final RevisionResource r = getRevisionResource(info._number);
+ final RevisionResource r = getRevisionResource(info.project, info._number);
submitter.apply(r, input);
}
- public RevisionResource getRevisionResource(int changeNumber) throws NoSuchChangeException, OrmException {
- final ChangeControl ctl = changeFactory.controlFor(new Change.Id(changeNumber), getBotUser());
- final ChangeData changeData = changeDataFactory.create(db.get(), new Change.Id(changeNumber));
- final RevisionResource r = new RevisionResource(collection.parse(ctl), changeData.currentPatchSet());
+ public RevisionResource getRevisionResource(String project, int changeNumber) throws NoSuchChangeException, OrmException {
+ ChangeControl ctl = changeFactory.validateFor(db.get(), new Change.Id(changeNumber), getBotUser());
+ ChangeData changeData = changeDataFactory.create(db.get(), new Project.NameKey(project), new Change.Id(changeNumber));
+ RevisionResource r = new RevisionResource(collection.parse(ctl), changeData.currentPatchSet());
return r;
}
diff --git a/src/main/java/com/criteo/gerrit/plugins/automerge/AutomaticMerger.java b/src/main/java/com/criteo/gerrit/plugins/automerge/AutomaticMerger.java
index b27e7cf..21bf51d 100644
--- a/src/main/java/com/criteo/gerrit/plugins/automerge/AutomaticMerger.java
+++ b/src/main/java/com/criteo/gerrit/plugins/automerge/AutomaticMerger.java
@@ -26,6 +26,7 @@
import com.google.gerrit.server.change.GetRelated;
import com.google.gerrit.server.change.PostReview;
import com.google.gerrit.server.change.Submit;
+import com.google.gerrit.server.data.AccountAttribute;
import com.google.gerrit.server.data.ApprovalAttribute;
import com.google.gerrit.server.data.ChangeAttribute;
import com.google.gerrit.server.events.CommentAddedEvent;
@@ -33,6 +34,7 @@
import com.google.gerrit.server.events.PatchSetCreatedEvent;
import com.google.gerrit.server.events.TopicChangedEvent;
import com.google.gerrit.server.git.MergeUtil;
+import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
@@ -98,17 +100,19 @@
}
private void onTopicChanged(final TopicChangedEvent event) {
- if (!atomicityHelper.isAtomicReview(event.change)) {
+ ChangeAttribute change = event.change.get();
+ if (!atomicityHelper.isAtomicReview(change)) {
return;
}
- processNewAtomicPatchSet(event.change);
+ processNewAtomicPatchSet(change);
}
private void onPatchSetCreated(final PatchSetCreatedEvent event) {
- if (!atomicityHelper.isAtomicReview(event.change)) {
+ ChangeAttribute change = event.change.get();
+ if (!atomicityHelper.isAtomicReview(change)) {
return;
}
- processNewAtomicPatchSet(event.change);
+ processNewAtomicPatchSet(change);
}
private void onCommendAdded(final CommentAddedEvent newComment) {
@@ -116,15 +120,14 @@
return;
}
- final ChangeAttribute change = newComment.change;
- final int reviewNumber = Integer.parseInt(change.number);
+ ChangeAttribute change = newComment.change.get();
try {
- checkReviewExists(reviewNumber);
- if (atomicityHelper.isSubmittable(reviewNumber)) {
- log.info(String.format("Change %d is submittable. Will try to merge all related changes.", reviewNumber));
+ checkReviewExists(change.number);
+ if (atomicityHelper.isSubmittable(change.project, change.number)) {
+ log.info(String.format("Change %d is submittable. Will try to merge all related changes.", change.number));
attemptToMerge(change);
}
- } catch (final RestApiException | NoSuchChangeException | OrmException | IOException e) {
+ } catch (RestApiException | OrmException | UpdateException | IOException e) {
log.error("An exception occured while trying to atomic merge a change.", e);
throw new RuntimeException(e);
}
@@ -138,11 +141,13 @@
* @return a boolean
*/
private boolean shouldProcessCommentEvent(CommentAddedEvent comment) {
- if (!config.getBotEmail().equals(comment.author.email)) {
+ AccountAttribute account = comment.author.get();
+ if (!config.getBotEmail().equals(account.email)) {
return true;
}
- if (comment.approvals != null) {
- for (ApprovalAttribute approval : comment.approvals) {
+ ApprovalAttribute[] approvals = comment.approvals.get();
+ if (approvals != null) {
+ for (ApprovalAttribute approval : approvals) {
// See ReviewUpdate#setMinusOne
if (!("Code-Review".equals(approval.type) && "-1".equals(approval.value))) {
return true;
@@ -152,7 +157,7 @@
return false;
}
- private void attemptToMerge(ChangeAttribute change) throws RestApiException, OrmException, NoSuchChangeException, IOException {
+ private void attemptToMerge(ChangeAttribute change) throws RestApiException, OrmException, NoSuchChangeException, IOException, UpdateException {
final List<ChangeInfo> related = Lists.newArrayList();
if (atomicityHelper.isAtomicReview(change)) {
related.addAll(api.changes().query("status: open AND topic: " + change.topic)
@@ -167,37 +172,35 @@
if (!info.mergeable) {
mergeable = false;
}
- if (!atomicityHelper.isSubmittable(info._number)) {
+ if (!atomicityHelper.isSubmittable(info.project, info._number)) {
submittable = false;
}
}
- final int reviewNumber = Integer.parseInt(change.number);
if (submittable) {
if (mergeable) {
- log.debug(String.format("Change %d is mergeable", reviewNumber));
+ log.debug(String.format("Change %d is mergeable", change.number));
for (final ChangeInfo info : related) {
atomicityHelper.mergeReview(info);
}
} else {
- reviewUpdater.commentOnReview(reviewNumber, AutomergeConfig.CANT_MERGE_COMMENT_FILE);
+ reviewUpdater.commentOnReview(change.project, change.number, AutomergeConfig.CANT_MERGE_COMMENT_FILE);
}
}
}
- private void processNewAtomicPatchSet(final ChangeAttribute change) {
- final int reviewNumber = Integer.parseInt(change.number);
+ private void processNewAtomicPatchSet(ChangeAttribute change) {
try {
- checkReviewExists(reviewNumber);
- if (atomicityHelper.hasDependentReview(reviewNumber)) {
+ checkReviewExists(change.number);
+ if (atomicityHelper.hasDependentReview(change.project, change.number)) {
log.info(String.format("Warn the user by setting -1 on change %d, as other atomic changes exists on the same repository.",
- reviewNumber));
- reviewUpdater.setMinusOne(reviewNumber, AutomergeConfig.ATOMIC_REVIEWS_SAME_REPO_FILE);
+ change.number));
+ reviewUpdater.setMinusOne(change.project, change.number, AutomergeConfig.ATOMIC_REVIEWS_SAME_REPO_FILE);
} else {
- log.info(String.format("Detected atomic review on change %d.", reviewNumber));
- reviewUpdater.commentOnReview(reviewNumber, AutomergeConfig.ATOMIC_REVIEW_DETECTED_FILE);
+ log.info(String.format("Detected atomic review on change %d.", change.number));
+ reviewUpdater.commentOnReview(change.project, change.number, AutomergeConfig.ATOMIC_REVIEW_DETECTED_FILE);
}
- } catch (RestApiException | IOException | NoSuchChangeException | OrmException e) {
+ } catch (RestApiException | IOException | OrmException | UpdateException e) {
throw new RuntimeException(e);
}
}
diff --git a/src/main/java/com/criteo/gerrit/plugins/automerge/AutomergeConfig.java b/src/main/java/com/criteo/gerrit/plugins/automerge/AutomergeConfig.java
index 135c8df..40d0811 100644
--- a/src/main/java/com/criteo/gerrit/plugins/automerge/AutomergeConfig.java
+++ b/src/main/java/com/criteo/gerrit/plugins/automerge/AutomergeConfig.java
@@ -45,7 +45,7 @@
topicPrefix = defaultTopicPrefix;
}
- templatesPath = paths.etc_dir;
+ templatesPath = paths.etc_dir.toFile();
}
public final String getBotEmail() {
diff --git a/src/main/java/com/criteo/gerrit/plugins/automerge/ReviewUpdater.java b/src/main/java/com/criteo/gerrit/plugins/automerge/ReviewUpdater.java
index 32c05fe..9ee5e0e 100644
--- a/src/main/java/com/criteo/gerrit/plugins/automerge/ReviewUpdater.java
+++ b/src/main/java/com/criteo/gerrit/plugins/automerge/ReviewUpdater.java
@@ -10,6 +10,7 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.change.PostReview;
import com.google.gerrit.server.change.RevisionResource;
+import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
@@ -40,14 +41,14 @@
@Inject
private AtomicityHelper atomicityHelper;
- public void commentOnReview(final int number, final String commentTemplate) throws RestApiException, OrmException, IOException, NoSuchChangeException {
- final ReviewInput comment = createComment(commentTemplate);
- applyComment(number, comment);
+ public void commentOnReview(String project, int number, String commentTemplate) throws RestApiException, OrmException, IOException, NoSuchChangeException, UpdateException {
+ ReviewInput comment = createComment(commentTemplate);
+ applyComment(project, number, comment);
}
- public void setMinusOne(final int number, final String commentTemplate) throws RestApiException, OrmException, IOException, NoSuchChangeException {
- final ReviewInput message = createComment(commentTemplate).label("Code-Review", -1);
- applyComment(number, message);
+ public void setMinusOne(String project, int number, String commentTemplate) throws RestApiException, OrmException, IOException, NoSuchChangeException, UpdateException {
+ ReviewInput message = createComment(commentTemplate).label("Code-Review", -1);
+ applyComment(project, number, message);
}
private ReviewInput createComment(final String commentTemplate) {
@@ -65,8 +66,8 @@
}
}
- private void applyComment(final int number, ReviewInput comment) throws RestApiException, OrmException, IOException, NoSuchChangeException {
- final RevisionResource r = atomicityHelper.getRevisionResource(number);
+ private void applyComment(String project, int number, ReviewInput comment) throws RestApiException, OrmException, IOException, NoSuchChangeException, UpdateException {
+ RevisionResource r = atomicityHelper.getRevisionResource(project, number);
reviewer.get().apply(r, comment);
}
}
diff --git a/src/test/java/com/criteo/gerrit/plugins/automerge/AutomergeConfigTest.java b/src/test/java/com/criteo/gerrit/plugins/automerge/AutomergeConfigTest.java
index 3ff50ee..49535db 100644
--- a/src/test/java/com/criteo/gerrit/plugins/automerge/AutomergeConfigTest.java
+++ b/src/test/java/com/criteo/gerrit/plugins/automerge/AutomergeConfigTest.java
@@ -8,16 +8,17 @@
import org.eclipse.jgit.lib.Config;
import org.junit.Test;
-import java.io.File;
import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Paths;
public class AutomergeConfigTest {
@Test
- public void testGetDefaultConfig() {
+ public void testGetDefaultConfig() throws IOException {
final Config conf = new Config();
try {
- final SitePaths paths = new SitePaths(new File("."));
+ final SitePaths paths = new SitePaths(Paths.get("."));
final AutomergeConfig amconf = new AutomergeConfig(conf, paths);
@@ -29,10 +30,10 @@
}
@Test
- public void testGetValues() {
+ public void testGetValues() throws IOException {
final Config conf = new Config();
try {
- final SitePaths paths = new SitePaths(new File("."));
+ final SitePaths paths = new SitePaths(Paths.get("."));
conf.setString(AutomergeConfig.AUTOMERGE_SECTION, null, AutomergeConfig.BOT_EMAIL_KEY, "Foo@bar.com");
conf.setString(AutomergeConfig.AUTOMERGE_SECTION, null, AutomergeConfig.TOPIC_PREFIX_KEY, "fake_topic_prefix");