Merge branch 'stable-2.11'
* stable-2.11: Release notes for Gerrit 2.11.4 Fix link in 2.10.7 release notes Set version to 2.11.4 Do not double decode the login URL token ReceiveCommits: Fire add comment hook when approvals provided ReceiveCommits: Include approvals from magic branch in change message Update no-new-change error message documentation Release notes for Gerrit 2.10.7 Fix: User could get around ref-update hook through gerrit-created commits Set version to 2.10.7 PatchListLoader: Synchronize MyersDiff and HistogramDiff invocations Change-Id: Id28f13876f16bb5194f7b078860b95004dba369d
This commit is contained in:
19
ReleaseNotes/ReleaseNotes-2.10.7.txt
Normal file
19
ReleaseNotes/ReleaseNotes-2.10.7.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Release notes for Gerrit 2.10.7
|
||||||
|
===============================
|
||||||
|
|
||||||
|
There are no schema changes from link:ReleaseNotes-2.10.6.html[2.10.6].
|
||||||
|
|
||||||
|
Download:
|
||||||
|
link:https://gerrit-releases.storage.googleapis.com/gerrit-2.10.7.war[
|
||||||
|
https://gerrit-releases.storage.googleapis.com/gerrit-2.10.7.war]
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
* link:https://code.google.com/p/gerrit/issues/detail?id=3361[Issue 3361]:
|
||||||
|
Synchronize Myers diff and Histogram diff invocations to prevent pack file
|
||||||
|
corruption.
|
||||||
|
+
|
||||||
|
See also the link:https://bugs.eclipse.org/bugs/show_bug.cgi?id=467467[
|
||||||
|
bug report on JGit].
|
||||||
|
|
111
ReleaseNotes/ReleaseNotes-2.11.4.txt
Normal file
111
ReleaseNotes/ReleaseNotes-2.11.4.txt
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
Release notes for Gerrit 2.11.4
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Gerrit 2.11.4 is now available:
|
||||||
|
|
||||||
|
link:https://gerrit-releases.storage.googleapis.com/gerrit-2.11.4.war[
|
||||||
|
https://gerrit-releases.storage.googleapis.com/gerrit-2.11.4.war]
|
||||||
|
|
||||||
|
Gerrit 2.11.4 includes the bug fixes done with
|
||||||
|
link:ReleaseNotes-2.10.7.html[Gerrit 2.10.7]. These bug fixes are *not* listed
|
||||||
|
in these release notes.
|
||||||
|
|
||||||
|
There are no schema changes from link:ReleaseNotes-2.11.3.html[2.11.3].
|
||||||
|
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Fix NullPointerException in `ls-project` command with `--has-acl-for` option.
|
||||||
|
+
|
||||||
|
Using the `--has-acl-for` option for external groups (e.g. LDAP groups) was
|
||||||
|
causing a NullPointerException.
|
||||||
|
|
||||||
|
* link:https://code.google.com/p/gerrit/issues/detail?id=3328[Issue 3328]:
|
||||||
|
Allow to push a tag that points to a non-commit object.
|
||||||
|
+
|
||||||
|
When pushing a tag that points to a non-commit object, like
|
||||||
|
link:https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tag/?id=v2.6.11[
|
||||||
|
`v2.6.11` on linux-stable] which points to a tree, or
|
||||||
|
link:https://git.eclipse.org/c/jgit/jgit.git/tag/?id=spearce-gpg-pub[
|
||||||
|
`spearce-gpg-pub` on jgit] which points to a blob, Gerrit rejected the push with
|
||||||
|
the error message 'missing object(s)'.
|
||||||
|
+
|
||||||
|
Note: This was previously fixed in Gerrit version 2.11.1, but was inadvertently
|
||||||
|
reverted in 2.11.2 and 2.11.3.
|
||||||
|
|
||||||
|
* link:https://code.google.com/p/gerrit/issues/detail?id=2817[Issue 2817]:
|
||||||
|
Insert Change-Id into access right changes.
|
||||||
|
+
|
||||||
|
When modifications of access rights were saved for review, the change
|
||||||
|
did not have a Change-Id in the commit message.
|
||||||
|
|
||||||
|
* Fix duplicated log lines after reloading a plugin.
|
||||||
|
+
|
||||||
|
If a plugin was reloaded, logs emitted from the plugin were duplicated.
|
||||||
|
|
||||||
|
* Remove `--recheck-mergeable` option from `reindex` command documentation.
|
||||||
|
+
|
||||||
|
The `--recheck-mergeable` option was removed in Gerrit version 2.11.
|
||||||
|
|
||||||
|
* Use the correct validation policy for commits created by Gerrit.
|
||||||
|
+
|
||||||
|
Commits created by Gerrit were being validated in the same way as commits
|
||||||
|
received from users.
|
||||||
|
|
||||||
|
* link:https://code.google.com/p/gerrit/issues/detail?id=3557[Issue 3557]:
|
||||||
|
Disallow invalid reference patterns in project configuration.
|
||||||
|
+
|
||||||
|
When editing a project configuration by using the UI or by submitting a change
|
||||||
|
to `refs/meta/config`, it was possible to add a permission to an invalid
|
||||||
|
reference pattern. This caused the project to be unavailable and the `ls-projects`
|
||||||
|
command to fail whenever this project was encountered.
|
||||||
|
|
||||||
|
* link:https://code.google.com/p/gerrit/issues/detail?id=3574[Issue 3574]:
|
||||||
|
Fix review labels with `AnyWithBlock` function.
|
||||||
|
+
|
||||||
|
The review labels with `AnyWithBlock` with 0 and +1 values blocked submit when
|
||||||
|
reviewers were added.
|
||||||
|
|
||||||
|
* Fix ref in tag list for signed/annotated tags.
|
||||||
|
+
|
||||||
|
The tag name from the header was used, rather than the ref name. In some cases
|
||||||
|
this resulted in the wrong tag ref being listed.
|
||||||
|
|
||||||
|
* singleusergroup plugin: enable to add a user within a project's ACL using `user/username`.
|
||||||
|
+
|
||||||
|
A user could not be added to a project's ACL unless the user already had READ
|
||||||
|
permission in the project's ACL.
|
||||||
|
|
||||||
|
* Prevent user from bypassing ref-update hook through gerrit-created commits.
|
||||||
|
+
|
||||||
|
If the user used the cherry-pick ability in the UI or via the REST API, they
|
||||||
|
could put a commit on a branch that bypassed the requirements of the ref-update
|
||||||
|
hook (such as that certain branches require QA-tickets to be referenced in the
|
||||||
|
commit message).
|
||||||
|
|
||||||
|
* Allow InternalUsers to see drafts.
|
||||||
|
+
|
||||||
|
According to the documentation, InternalUsers should have full read access.
|
||||||
|
This was not true, since InternalUsers could not see drafts.
|
||||||
|
|
||||||
|
* link:https://code.google.com/p/gerrit/issues/detail?id=2683[Issue 2683]:
|
||||||
|
Fix non-ASCII password authentication failure under tomcat (LDAP).
|
||||||
|
+
|
||||||
|
The authentication with LDAP failed when the password contained non-ASCII
|
||||||
|
characters such as ä, ö, Ä, and Ö.
|
||||||
|
|
||||||
|
* Do not double decode the login URL token.
|
||||||
|
+
|
||||||
|
The login URL token used to redirect from the login servlet to the target page
|
||||||
|
is already decoded and should not be decoded again.
|
||||||
|
|
||||||
|
* Include approvals from magic branch in change message.
|
||||||
|
+
|
||||||
|
When using the `%l` option to apply a review label on uploaded changes or
|
||||||
|
patch sets, the applied label was not mentioned in the change message.
|
||||||
|
|
||||||
|
* Fire the `comment-added` hook for approvals from the magic branch.
|
||||||
|
+
|
||||||
|
When using the `%l` option to apply a review label on uploaded changes or
|
||||||
|
patch sets, the `comment-added` hook was not being fired.
|
@@ -4,6 +4,7 @@ Gerrit Code Review - Release Notes
|
|||||||
[[2_11]]
|
[[2_11]]
|
||||||
Version 2.11.x
|
Version 2.11.x
|
||||||
--------------
|
--------------
|
||||||
|
* link:ReleaseNotes-2.11.4.html[2.11.4]
|
||||||
* link:ReleaseNotes-2.11.3.html[2.11.3]
|
* link:ReleaseNotes-2.11.3.html[2.11.3]
|
||||||
* link:ReleaseNotes-2.11.2.html[2.11.2]
|
* link:ReleaseNotes-2.11.2.html[2.11.2]
|
||||||
* link:ReleaseNotes-2.11.1.html[2.11.1]
|
* link:ReleaseNotes-2.11.1.html[2.11.1]
|
||||||
@@ -12,6 +13,7 @@ Version 2.11.x
|
|||||||
[[2_10]]
|
[[2_10]]
|
||||||
Version 2.10.x
|
Version 2.10.x
|
||||||
--------------
|
--------------
|
||||||
|
* link:ReleaseNotes-2.10.7.html[2.10.7]
|
||||||
* link:ReleaseNotes-2.10.6.html[2.10.6]
|
* link:ReleaseNotes-2.10.6.html[2.10.6]
|
||||||
* link:ReleaseNotes-2.10.5.html[2.10.5]
|
* link:ReleaseNotes-2.10.5.html[2.10.5]
|
||||||
* link:ReleaseNotes-2.10.4.html[2.10.4]
|
* link:ReleaseNotes-2.10.4.html[2.10.4]
|
||||||
|
@@ -16,8 +16,11 @@ package com.google.gerrit.acceptance.git;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.common.truth.TruthJUnit.assume;
|
import static com.google.common.truth.TruthJUnit.assume;
|
||||||
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||||
import com.google.gerrit.acceptance.GitUtil;
|
import com.google.gerrit.acceptance.GitUtil;
|
||||||
import com.google.gerrit.acceptance.PushOneCommit;
|
import com.google.gerrit.acceptance.PushOneCommit;
|
||||||
@@ -32,10 +35,16 @@ import com.google.gerrit.testutil.ConfigSuite;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.DateTimeUtils;
|
||||||
|
import org.joda.time.DateTimeUtils.MillisProvider;
|
||||||
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
||||||
@ConfigSuite.Config
|
@ConfigSuite.Config
|
||||||
@@ -53,6 +62,24 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
|||||||
|
|
||||||
private String sshUrl;
|
private String sshUrl;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setTimeForTesting() {
|
||||||
|
final long clockStepMs = MILLISECONDS.convert(1, SECONDS);
|
||||||
|
final AtomicLong clockMs = new AtomicLong(
|
||||||
|
new DateTime(2009, 9, 30, 17, 0, 0).getMillis());
|
||||||
|
DateTimeUtils.setCurrentMillisProvider(new MillisProvider() {
|
||||||
|
@Override
|
||||||
|
public long getMillis() {
|
||||||
|
return clockMs.getAndAdd(clockStepMs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void restoreTime() {
|
||||||
|
DateTimeUtils.setCurrentMillisSystem();
|
||||||
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
sshUrl = sshSession.getUrl();
|
sshUrl = sshSession.getUrl();
|
||||||
@@ -177,6 +204,8 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
|||||||
assertThat(cr.all).hasSize(1);
|
assertThat(cr.all).hasSize(1);
|
||||||
assertThat(cr.all.get(0).name).isEqualTo("Administrator");
|
assertThat(cr.all.get(0).name).isEqualTo("Administrator");
|
||||||
assertThat(cr.all.get(0).value).isEqualTo(1);
|
assertThat(cr.all.get(0).value).isEqualTo(1);
|
||||||
|
assertThat(Iterables.getLast(ci.messages).message).isEqualTo(
|
||||||
|
"Uploaded patch set 1: Code-Review+1.");
|
||||||
|
|
||||||
PushOneCommit push =
|
PushOneCommit push =
|
||||||
pushFactory.create(db, admin.getIdent(), testRepo, PushOneCommit.SUBJECT,
|
pushFactory.create(db, admin.getIdent(), testRepo, PushOneCommit.SUBJECT,
|
||||||
@@ -185,9 +214,20 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
|||||||
|
|
||||||
ci = get(r.getChangeId());
|
ci = get(r.getChangeId());
|
||||||
cr = ci.labels.get("Code-Review");
|
cr = ci.labels.get("Code-Review");
|
||||||
|
assertThat(Iterables.getLast(ci.messages).message).isEqualTo(
|
||||||
|
"Uploaded patch set 2: Code-Review+2.");
|
||||||
|
|
||||||
assertThat(cr.all).hasSize(1);
|
assertThat(cr.all).hasSize(1);
|
||||||
assertThat(cr.all.get(0).name).isEqualTo("Administrator");
|
assertThat(cr.all.get(0).name).isEqualTo("Administrator");
|
||||||
assertThat(cr.all.get(0).value).isEqualTo(2);
|
assertThat(cr.all.get(0).value).isEqualTo(2);
|
||||||
|
|
||||||
|
push =
|
||||||
|
pushFactory.create(db, admin.getIdent(), testRepo, PushOneCommit.SUBJECT,
|
||||||
|
"c.txt", "moreContent", r.getChangeId());
|
||||||
|
r = push.to("refs/for/master/%l=Code-Review+2");
|
||||||
|
ci = get(r.getChangeId());
|
||||||
|
assertThat(Iterables.getLast(ci.messages).message).isEqualTo(
|
||||||
|
"Uploaded patch set 3.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@@ -22,7 +22,10 @@ acceptance_tests(
|
|||||||
java_library(
|
java_library(
|
||||||
name = 'push_for_review',
|
name = 'push_for_review',
|
||||||
srcs = ['AbstractPushForReview.java'],
|
srcs = ['AbstractPushForReview.java'],
|
||||||
deps = ['//gerrit-acceptance-tests:lib'],
|
deps = [
|
||||||
|
'//gerrit-acceptance-tests:lib',
|
||||||
|
'//lib/joda:joda-time',
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
java_library(
|
java_library(
|
||||||
|
@@ -17,7 +17,6 @@ package com.google.gerrit.httpd;
|
|||||||
import com.google.common.base.CharMatcher;
|
import com.google.common.base.CharMatcher;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.gerrit.common.PageLinks;
|
import com.google.gerrit.common.PageLinks;
|
||||||
import com.google.gerrit.extensions.restapi.Url;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
@@ -25,11 +24,11 @@ public class LoginUrlToken {
|
|||||||
private static final String DEFAULT_TOKEN = '#' + PageLinks.MINE;
|
private static final String DEFAULT_TOKEN = '#' + PageLinks.MINE;
|
||||||
|
|
||||||
public static String getToken(final HttpServletRequest req){
|
public static String getToken(final HttpServletRequest req){
|
||||||
String encodedToken = req.getPathInfo();
|
String token = req.getPathInfo();
|
||||||
if (Strings.isNullOrEmpty(encodedToken)) {
|
if (Strings.isNullOrEmpty(token)) {
|
||||||
return DEFAULT_TOKEN;
|
return DEFAULT_TOKEN;
|
||||||
} else {
|
} else {
|
||||||
return CharMatcher.is('/').trimLeadingFrom(Url.decode(encodedToken));
|
return CharMatcher.is('/').trimLeadingFrom(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -341,6 +341,12 @@ public class ChangeInserter extends BatchUpdate.InsertChangeOp {
|
|||||||
accountCache.get(change.getOwner()).getAccount(),
|
accountCache.get(change.getOwner()).getAccount(),
|
||||||
hashtags, null, hashtags, db);
|
hashtags, null, hashtags, db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (approvals != null && !approvals.isEmpty()) {
|
||||||
|
hooks.doCommentAddedHook(change,
|
||||||
|
((IdentifiedUser) refControl.getCurrentUser()).getAccount(),
|
||||||
|
patchSet, null, approvals, db);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -71,6 +71,7 @@ import com.google.gerrit.reviewdb.client.Branch;
|
|||||||
import com.google.gerrit.reviewdb.client.Change;
|
import com.google.gerrit.reviewdb.client.Change;
|
||||||
import com.google.gerrit.reviewdb.client.ChangeMessage;
|
import com.google.gerrit.reviewdb.client.ChangeMessage;
|
||||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||||
|
import com.google.gerrit.reviewdb.client.PatchSetApproval;
|
||||||
import com.google.gerrit.reviewdb.client.PatchSetInfo;
|
import com.google.gerrit.reviewdb.client.PatchSetInfo;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
@@ -1761,6 +1762,8 @@ public class ReceiveCommits {
|
|||||||
}
|
}
|
||||||
recipients.add(getRecipientsFromFooters(accountResolver, ps, footerLines));
|
recipients.add(getRecipientsFromFooters(accountResolver, ps, footerLines));
|
||||||
recipients.remove(me);
|
recipients.remove(me);
|
||||||
|
StringBuilder msgs = renderMessageWithApprovals(ps.getPatchSetId(),
|
||||||
|
approvals, Collections.<String, PatchSetApproval>emptyMap());
|
||||||
try (ObjectInserter oi = repo.newObjectInserter();
|
try (ObjectInserter oi = repo.newObjectInserter();
|
||||||
BatchUpdate bu = batchUpdateFactory.create(
|
BatchUpdate bu = batchUpdateFactory.create(
|
||||||
db, change.getProject(), currentUser, change.getCreatedOn())) {
|
db, change.getProject(), currentUser, change.getCreatedOn())) {
|
||||||
@@ -1769,7 +1772,7 @@ public class ReceiveCommits {
|
|||||||
.setReviewers(recipients.getReviewers())
|
.setReviewers(recipients.getReviewers())
|
||||||
.setExtraCC(recipients.getCcOnly())
|
.setExtraCC(recipients.getCcOnly())
|
||||||
.setApprovals(approvals)
|
.setApprovals(approvals)
|
||||||
.setMessage("Uploaded patch set " + ps.getPatchSetId() + ".")
|
.setMessage(msgs.toString() + ".")
|
||||||
.setRequestScopePropagator(requestScopePropagator)
|
.setRequestScopePropagator(requestScopePropagator)
|
||||||
.setSendMail(true)
|
.setSendMail(true)
|
||||||
.setUpdateRef(false));
|
.setUpdateRef(false));
|
||||||
@@ -1881,6 +1884,27 @@ public class ReceiveCommits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private StringBuilder renderMessageWithApprovals(int patchSetId,
|
||||||
|
Map<String, Short> n, Map<String, PatchSetApproval> c) {
|
||||||
|
StringBuilder msgs = new StringBuilder("Uploaded patch set " + patchSetId);
|
||||||
|
if (!n.isEmpty()) {
|
||||||
|
boolean first = true;
|
||||||
|
for (Map.Entry<String, Short> e : n.entrySet()) {
|
||||||
|
if (c.containsKey(e.getKey())
|
||||||
|
&& c.get(e.getKey()).getValue() == e.getValue()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (first) {
|
||||||
|
msgs.append(":");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
msgs.append(" ")
|
||||||
|
.append(LabelVote.create(e.getKey(), e.getValue()).format());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msgs;
|
||||||
|
}
|
||||||
|
|
||||||
private class ReplaceRequest {
|
private class ReplaceRequest {
|
||||||
final Change.Id ontoChange;
|
final Change.Id ontoChange;
|
||||||
final RevCommit newCommit;
|
final RevCommit newCommit;
|
||||||
@@ -2118,29 +2142,52 @@ public class ReceiveCommits {
|
|||||||
return Futures.makeChecked(future, INSERT_EXCEPTION);
|
return Futures.makeChecked(future, INSERT_EXCEPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangeMessage newChangeMessage(ReviewDb db, ChangeKind changeKind)
|
private ChangeMessage newChangeMessage(ReviewDb db, ChangeKind changeKind,
|
||||||
|
Map<String, Short> approvals)
|
||||||
throws OrmException {
|
throws OrmException {
|
||||||
msg =
|
msg =
|
||||||
new ChangeMessage(new ChangeMessage.Key(change.getId(), ChangeUtil
|
new ChangeMessage(new ChangeMessage.Key(change.getId(), ChangeUtil
|
||||||
.messageUUID(db)), currentUser.getAccountId(), newPatchSet.getCreatedOn(),
|
.messageUUID(db)), currentUser.getAccountId(), newPatchSet.getCreatedOn(),
|
||||||
newPatchSet.getId());
|
newPatchSet.getId());
|
||||||
String message = "Uploaded patch set " + newPatchSet.getPatchSetId();
|
StringBuilder msgs = renderMessageWithApprovals(
|
||||||
|
newPatchSet.getPatchSetId(), approvals, scanLabels(db, approvals));
|
||||||
switch (changeKind) {
|
switch (changeKind) {
|
||||||
case TRIVIAL_REBASE:
|
case TRIVIAL_REBASE:
|
||||||
case NO_CHANGE:
|
case NO_CHANGE:
|
||||||
message += ": Patch Set " + priorPatchSet.get() + " was rebased";
|
msgs.append(": Patch Set " + priorPatchSet.get() + " was rebased");
|
||||||
break;
|
break;
|
||||||
case NO_CODE_CHANGE:
|
case NO_CODE_CHANGE:
|
||||||
message += ": Commit message was updated";
|
msgs.append(": Commit message was updated");
|
||||||
break;
|
break;
|
||||||
case REWORK:
|
case REWORK:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
msg.setMessage(message + ".");
|
msg.setMessage(msgs.toString() + ".");
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, PatchSetApproval> scanLabels(ReviewDb db,
|
||||||
|
Map<String, Short> approvals)
|
||||||
|
throws OrmException {
|
||||||
|
Map<String, PatchSetApproval> current = new HashMap<>();
|
||||||
|
// We optimize here and only retrieve current when approvals provided
|
||||||
|
if (!approvals.isEmpty()) {
|
||||||
|
for (PatchSetApproval a : approvalsUtil.byPatchSetUser(
|
||||||
|
db, changeCtl, priorPatchSet, currentUser.getAccountId())) {
|
||||||
|
if (a.isSubmit()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelType lt = labelTypes.byLabel(a.getLabelId());
|
||||||
|
if (lt != null) {
|
||||||
|
current.put(lt.getName(), a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
PatchSet.Id upsertEdit() {
|
PatchSet.Id upsertEdit() {
|
||||||
if (cmd.getResult() == NOT_ATTEMPTED) {
|
if (cmd.getResult() == NOT_ATTEMPTED) {
|
||||||
cmd.execute(rp);
|
cmd.execute(rp);
|
||||||
@@ -2205,7 +2252,8 @@ public class ReceiveCommits {
|
|||||||
changeKind = changeKindCache.getChangeKind(
|
changeKind = changeKindCache.getChangeKind(
|
||||||
projectControl.getProjectState(), repo, priorCommit, newCommit);
|
projectControl.getProjectState(), repo, priorCommit, newCommit);
|
||||||
|
|
||||||
cmUtil.addChangeMessage(db, update, newChangeMessage(db, changeKind));
|
cmUtil.addChangeMessage(db, update, newChangeMessage(db, changeKind,
|
||||||
|
approvals));
|
||||||
|
|
||||||
if (mergedIntoRef == null) {
|
if (mergedIntoRef == null) {
|
||||||
// Change should be new, so it can go through review again.
|
// Change should be new, so it can go through review again.
|
||||||
@@ -2304,6 +2352,11 @@ public class ReceiveCommits {
|
|||||||
change, currentUser.getAccount(), newPatchSet, db, newCommit.getName());
|
change, currentUser.getAccount(), newPatchSet, db, newCommit.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!approvals.isEmpty()) {
|
||||||
|
hooks.doCommentAddedHook(change, currentUser.getAccount(), newPatchSet,
|
||||||
|
null, approvals, db);
|
||||||
|
}
|
||||||
|
|
||||||
if (magicBranch != null && magicBranch.submit) {
|
if (magicBranch != null && magicBranch.submit) {
|
||||||
submit(changeCtl, newPatchSet);
|
submit(changeCtl, newPatchSet);
|
||||||
}
|
}
|
||||||
|
@@ -14,12 +14,17 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.git.validators;
|
package com.google.gerrit.server.git.validators;
|
||||||
|
|
||||||
|
import static com.google.gerrit.reviewdb.client.RefNames.REFS_CHANGES;
|
||||||
|
import static com.google.gerrit.reviewdb.client.RefNames.REFS_CONFIG;
|
||||||
|
import static org.eclipse.jgit.lib.Constants.R_HEADS;
|
||||||
|
|
||||||
import com.google.common.base.CharMatcher;
|
import com.google.common.base.CharMatcher;
|
||||||
|
import com.google.gerrit.common.ChangeHookRunner.HookResult;
|
||||||
|
import com.google.gerrit.common.ChangeHooks;
|
||||||
import com.google.gerrit.common.FooterConstants;
|
import com.google.gerrit.common.FooterConstants;
|
||||||
import com.google.gerrit.common.Nullable;
|
import com.google.gerrit.common.Nullable;
|
||||||
import com.google.gerrit.common.PageLinks;
|
import com.google.gerrit.common.PageLinks;
|
||||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
|
||||||
import com.google.gerrit.server.GerritPersonIdent;
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||||
@@ -39,6 +44,7 @@ import com.jcraft.jsch.HostKey;
|
|||||||
|
|
||||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.lib.PersonIdent;
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.notes.NoteMap;
|
import org.eclipse.jgit.notes.NoteMap;
|
||||||
@@ -82,6 +88,7 @@ public class CommitValidators {
|
|||||||
private final String installCommitMsgHookCommand;
|
private final String installCommitMsgHookCommand;
|
||||||
private final SshInfo sshInfo;
|
private final SshInfo sshInfo;
|
||||||
private final Repository repo;
|
private final Repository repo;
|
||||||
|
private final ChangeHooks hooks;
|
||||||
private final DynamicSet<CommitValidationListener> commitValidationListeners;
|
private final DynamicSet<CommitValidationListener> commitValidationListeners;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -89,6 +96,7 @@ public class CommitValidators {
|
|||||||
@CanonicalWebUrl @Nullable final String canonicalWebUrl,
|
@CanonicalWebUrl @Nullable final String canonicalWebUrl,
|
||||||
@GerritServerConfig final Config config,
|
@GerritServerConfig final Config config,
|
||||||
final DynamicSet<CommitValidationListener> commitValidationListeners,
|
final DynamicSet<CommitValidationListener> commitValidationListeners,
|
||||||
|
final ChangeHooks hooks,
|
||||||
@Assisted final SshInfo sshInfo,
|
@Assisted final SshInfo sshInfo,
|
||||||
@Assisted final Repository repo, @Assisted final RefControl refControl) {
|
@Assisted final Repository repo, @Assisted final RefControl refControl) {
|
||||||
this.gerritIdent = gerritIdent;
|
this.gerritIdent = gerritIdent;
|
||||||
@@ -98,6 +106,7 @@ public class CommitValidators {
|
|||||||
config.getString("gerrit", null, "installCommitMsgHookCommand");
|
config.getString("gerrit", null, "installCommitMsgHookCommand");
|
||||||
this.sshInfo = sshInfo;
|
this.sshInfo = sshInfo;
|
||||||
this.repo = repo;
|
this.repo = repo;
|
||||||
|
this.hooks = hooks;
|
||||||
this.commitValidationListeners = commitValidationListeners;
|
this.commitValidationListeners = commitValidationListeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +164,7 @@ public class CommitValidators {
|
|||||||
}
|
}
|
||||||
validators.add(new ConfigValidator(refControl, repo));
|
validators.add(new ConfigValidator(refControl, repo));
|
||||||
validators.add(new PluginCommitValidationListener(commitValidationListeners));
|
validators.add(new PluginCommitValidationListener(commitValidationListeners));
|
||||||
|
validators.add(new ChangeHookValidator(refControl, hooks));
|
||||||
|
|
||||||
List<CommitValidationMessage> messages = new LinkedList<>();
|
List<CommitValidationMessage> messages = new LinkedList<>();
|
||||||
|
|
||||||
@@ -308,7 +318,7 @@ public class CommitValidators {
|
|||||||
CommitReceivedEvent receiveEvent) throws CommitValidationException {
|
CommitReceivedEvent receiveEvent) throws CommitValidationException {
|
||||||
IdentifiedUser currentUser = (IdentifiedUser) refControl.getCurrentUser();
|
IdentifiedUser currentUser = (IdentifiedUser) refControl.getCurrentUser();
|
||||||
|
|
||||||
if (RefNames.REFS_CONFIG.equals(refControl.getRefName())) {
|
if (REFS_CONFIG.equals(refControl.getRefName())) {
|
||||||
List<CommitValidationMessage> messages = new LinkedList<>();
|
List<CommitValidationMessage> messages = new LinkedList<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -535,6 +545,48 @@ public class CommitValidators {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Reject commits that don't pass user-supplied ref-update hook. */
|
||||||
|
public static class ChangeHookValidator implements
|
||||||
|
CommitValidationListener {
|
||||||
|
private final RefControl refControl;
|
||||||
|
private final ChangeHooks hooks;
|
||||||
|
|
||||||
|
public ChangeHookValidator(RefControl refControl, ChangeHooks hooks) {
|
||||||
|
this.refControl = refControl;
|
||||||
|
this.hooks = hooks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CommitValidationMessage> onCommitReceived(
|
||||||
|
CommitReceivedEvent receiveEvent) throws CommitValidationException {
|
||||||
|
|
||||||
|
if (refControl.getCurrentUser().isIdentifiedUser()) {
|
||||||
|
IdentifiedUser user = (IdentifiedUser) refControl.getCurrentUser();
|
||||||
|
|
||||||
|
String refname = receiveEvent.refName;
|
||||||
|
ObjectId old = receiveEvent.commit.getParent(0);
|
||||||
|
|
||||||
|
if (receiveEvent.command.getRefName().startsWith(REFS_CHANGES)) {
|
||||||
|
/*
|
||||||
|
* If the ref-update hook tries to distinguish behavior between pushes to
|
||||||
|
* refs/heads/... and refs/for/..., make sure we send it the correct refname.
|
||||||
|
* Also, if this is targetting refs/for/, make sure we behave the same as
|
||||||
|
* what a push to refs/for/ would behave; in particular, setting oldrev to
|
||||||
|
* 0000000000000000000000000000000000000000.
|
||||||
|
*/
|
||||||
|
refname = refname.replace(R_HEADS, "refs/for/refs/heads/");
|
||||||
|
old = ObjectId.zeroId();
|
||||||
|
}
|
||||||
|
HookResult result = hooks.doRefUpdateHook(receiveEvent.project, refname,
|
||||||
|
user.getAccount(), old, receiveEvent.commit);
|
||||||
|
if (result != null && result.getExitValue() != 0) {
|
||||||
|
throw new CommitValidationException(result.toString().trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static CommitValidationMessage getInvalidEmailError(RevCommit c, String type,
|
private static CommitValidationMessage getInvalidEmailError(RevCommit c, String type,
|
||||||
PersonIdent who, IdentifiedUser currentUser, String canonicalWebUrl) {
|
PersonIdent who, IdentifiedUser currentUser, String canonicalWebUrl) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
Reference in New Issue
Block a user