Merge "Add project specific nav to sidebar"
diff --git a/WORKSPACE b/WORKSPACE
index 5da3d522..63d10c6 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -581,10 +581,10 @@
maven_jar(
name = "blame_cache",
- artifact = "com/google/gitiles:blame-cache:0.2-1",
+ artifact = "com/google/gitiles:blame-cache:0.2-2",
attach_source = False,
repository = GERRIT,
- sha1 = "da7977e8b140b63f18054214c1d1b86ffa6896cb",
+ sha1 = "ac8693b319b3e70506fb27df1b77b598cfdcd00f",
)
# Keep this version of Soy synchronized with the version used in Gitiles.
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 1c5f178..5fbf8ca 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
@@ -1174,7 +1174,6 @@
assertThat(actual.fingerprint)
.named(id)
.isEqualTo(Fingerprint.toString(expected.getPublicKey().getFingerprint()));
- @SuppressWarnings("unchecked")
List<String> userIds = ImmutableList.copyOf(expected.getPublicKey().getUserIDs());
assertThat(actual.userIds).named(id).containsExactlyElementsIn(userIds);
assertThat(actual.key).named(id).startsWith("-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AbstractPushTag.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AbstractPushTag.java
new file mode 100644
index 0000000..cea907d
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AbstractPushTag.java
@@ -0,0 +1,261 @@
+// Copyright (C) 2016 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.project;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.acceptance.GitUtil.createAnnotatedTag;
+import static com.google.gerrit.acceptance.GitUtil.deleteRef;
+import static com.google.gerrit.acceptance.GitUtil.pushHead;
+import static com.google.gerrit.acceptance.GitUtil.updateAnnotatedTag;
+import static com.google.gerrit.acceptance.rest.project.AbstractPushTag.TagType.ANNOTATED;
+import static com.google.gerrit.acceptance.rest.project.AbstractPushTag.TagType.LIGHTWEIGHT;
+import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
+
+import com.google.common.base.MoreObjects;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.GitUtil;
+import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.reviewdb.client.RefNames;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.PushResult;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
+import org.junit.Before;
+import org.junit.Test;
+
+@NoHttpd
+public abstract class AbstractPushTag extends AbstractDaemonTest {
+ enum TagType {
+ LIGHTWEIGHT(Permission.CREATE),
+ ANNOTATED(Permission.CREATE_TAG);
+
+ final String createPermission;
+
+ TagType(String createPermission) {
+ this.createPermission = createPermission;
+ }
+ }
+
+ private RevCommit initialHead;
+ private TagType tagType;
+
+ @Before
+ public void setup() throws Exception {
+ // clone with user to avoid inherited tag permissions of admin user
+ testRepo = cloneProject(project, user);
+
+ initialHead = getRemoteHead();
+ tagType = getTagType();
+ }
+
+ protected abstract TagType getTagType();
+
+ @Test
+ public void createTagForExistingCommit() throws Exception {
+ pushTagForExistingCommit(Status.REJECTED_OTHER_REASON);
+
+ allowTagCreation();
+ pushTagForExistingCommit(Status.OK);
+
+ allowPushOnRefsTags();
+ pushTagForExistingCommit(Status.OK);
+
+ removePushFromRefsTags();
+ }
+
+ @Test
+ public void createTagForNewCommit() throws Exception {
+ pushTagForNewCommit(Status.REJECTED_OTHER_REASON);
+
+ allowTagCreation();
+ pushTagForNewCommit(Status.REJECTED_OTHER_REASON);
+
+ allowPushOnRefsTags();
+ pushTagForNewCommit(Status.OK);
+
+ removePushFromRefsTags();
+ }
+
+ @Test
+ public void fastForward() throws Exception {
+ allowTagCreation();
+ String tagName = pushTagForExistingCommit(Status.OK);
+
+ fastForwardTagToExistingCommit(tagName, Status.REJECTED_OTHER_REASON);
+ fastForwardTagToNewCommit(tagName, Status.REJECTED_OTHER_REASON);
+
+ allowTagDeletion();
+ fastForwardTagToExistingCommit(tagName, Status.REJECTED_OTHER_REASON);
+ fastForwardTagToNewCommit(tagName, Status.REJECTED_OTHER_REASON);
+
+ allowPushOnRefsTags();
+ Status expectedStatus = tagType == ANNOTATED ? Status.REJECTED_OTHER_REASON : Status.OK;
+ fastForwardTagToExistingCommit(tagName, expectedStatus);
+ fastForwardTagToNewCommit(tagName, expectedStatus);
+
+ allowForcePushOnRefsTags();
+ fastForwardTagToExistingCommit(tagName, Status.OK);
+ fastForwardTagToNewCommit(tagName, Status.OK);
+
+ removePushFromRefsTags();
+ }
+
+ @Test
+ public void forceUpdate() throws Exception {
+ allowTagCreation();
+ String tagName = pushTagForExistingCommit(Status.OK);
+
+ forceUpdateTagToExistingCommit(tagName, Status.REJECTED_OTHER_REASON);
+ forceUpdateTagToNewCommit(tagName, Status.REJECTED_OTHER_REASON);
+
+ allowPushOnRefsTags();
+ forceUpdateTagToExistingCommit(tagName, Status.REJECTED_OTHER_REASON);
+ forceUpdateTagToNewCommit(tagName, Status.REJECTED_OTHER_REASON);
+
+ allowTagDeletion();
+ forceUpdateTagToExistingCommit(tagName, Status.REJECTED_OTHER_REASON);
+ forceUpdateTagToNewCommit(tagName, Status.REJECTED_OTHER_REASON);
+
+ allowForcePushOnRefsTags();
+ forceUpdateTagToExistingCommit(tagName, Status.OK);
+ forceUpdateTagToNewCommit(tagName, Status.OK);
+
+ removePushFromRefsTags();
+ }
+
+ @Test
+ public void delete() throws Exception {
+ allowTagCreation();
+ String tagName = pushTagForExistingCommit(Status.OK);
+
+ pushTagDeletion(tagName, Status.REJECTED_OTHER_REASON);
+
+ allowPushOnRefsTags();
+ pushTagDeletion(tagName, Status.REJECTED_OTHER_REASON);
+
+ allowForcePushOnRefsTags();
+ tagName = pushTagForExistingCommit(Status.OK);
+ pushTagDeletion(tagName, Status.OK);
+
+ removePushFromRefsTags();
+ allowTagDeletion();
+ tagName = pushTagForExistingCommit(Status.OK);
+ pushTagDeletion(tagName, Status.OK);
+ }
+
+ private String pushTagForExistingCommit(Status expectedStatus) throws Exception {
+ return pushTag(null, false, false, expectedStatus);
+ }
+
+ private String pushTagForNewCommit(Status expectedStatus) throws Exception {
+ return pushTag(null, true, false, expectedStatus);
+ }
+
+ private void fastForwardTagToExistingCommit(String tagName, Status expectedStatus)
+ throws Exception {
+ pushTag(tagName, false, false, expectedStatus);
+ }
+
+ private void fastForwardTagToNewCommit(String tagName, Status expectedStatus) throws Exception {
+ pushTag(tagName, true, false, expectedStatus);
+ }
+
+ private void forceUpdateTagToExistingCommit(String tagName, Status expectedStatus)
+ throws Exception {
+ pushTag(tagName, false, true, expectedStatus);
+ }
+
+ private void forceUpdateTagToNewCommit(String tagName, Status expectedStatus) throws Exception {
+ pushTag(tagName, true, true, expectedStatus);
+ }
+
+ private String pushTag(String tagName, boolean newCommit, boolean force, Status expectedStatus)
+ throws Exception {
+ if (force) {
+ testRepo.reset(initialHead);
+ }
+ commit(user.getIdent(), "subject");
+
+ boolean createTag = tagName == null;
+ tagName = MoreObjects.firstNonNull(tagName, "v1_" + System.nanoTime());
+ switch (tagType) {
+ case LIGHTWEIGHT:
+ break;
+ case ANNOTATED:
+ if (createTag) {
+ createAnnotatedTag(testRepo, tagName, user.getIdent());
+ } else {
+ updateAnnotatedTag(testRepo, tagName, user.getIdent());
+ }
+ break;
+ default:
+ throw new IllegalStateException("unexpected tag type: " + tagType);
+ }
+
+ if (!newCommit) {
+ grant(project, "refs/for/refs/heads/master", Permission.SUBMIT, false, REGISTERED_USERS);
+ pushHead(testRepo, "refs/for/master%submit");
+ }
+
+ String tagRef = tagRef(tagName);
+ PushResult r =
+ tagType == LIGHTWEIGHT
+ ? pushHead(testRepo, tagRef, false, force)
+ : GitUtil.pushTag(testRepo, tagName, !createTag);
+ RemoteRefUpdate refUpdate = r.getRemoteUpdate(tagRef);
+ assertThat(refUpdate.getStatus()).named(tagType.name()).isEqualTo(expectedStatus);
+ return tagName;
+ }
+
+ private void pushTagDeletion(String tagName, Status expectedStatus) throws Exception {
+ String tagRef = tagRef(tagName);
+ PushResult r = deleteRef(testRepo, tagRef);
+ RemoteRefUpdate refUpdate = r.getRemoteUpdate(tagRef);
+ assertThat(refUpdate.getStatus()).named(tagType.name()).isEqualTo(expectedStatus);
+ }
+
+ private void allowTagCreation() throws Exception {
+ grant(project, "refs/tags/*", tagType.createPermission, false, REGISTERED_USERS);
+ }
+
+ private void allowPushOnRefsTags() throws Exception {
+ removePushFromRefsTags();
+ grant(project, "refs/tags/*", Permission.PUSH, false, REGISTERED_USERS);
+ }
+
+ private void allowForcePushOnRefsTags() throws Exception {
+ removePushFromRefsTags();
+ grant(project, "refs/tags/*", Permission.PUSH, true, REGISTERED_USERS);
+ }
+
+ private void allowTagDeletion() throws Exception {
+ removePushFromRefsTags();
+ grant(project, "refs/tags/*", Permission.DELETE, true, REGISTERED_USERS);
+ }
+
+ private void removePushFromRefsTags() throws Exception {
+ removePermission(project, "refs/tags/*", Permission.PUSH);
+ }
+
+ private void commit(PersonIdent ident, String subject) throws Exception {
+ commitBuilder().ident(ident).message(subject + " (" + System.nanoTime() + ")").create();
+ }
+
+ private static String tagRef(String tagName) {
+ return RefNames.REFS_TAGS + tagName;
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BUILD b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BUILD
index 3266be8..fbe5d80 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BUILD
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BUILD
@@ -6,6 +6,7 @@
labels = ["rest"],
deps = [
":project",
+ ":push_tag_util",
":refassert",
],
)
@@ -35,3 +36,14 @@
"//lib:truth",
],
)
+
+java_library(
+ name = "push_tag_util",
+ testonly = 1,
+ srcs = [
+ "AbstractPushTag.java",
+ ],
+ deps = [
+ "//gerrit-acceptance-tests:lib",
+ ],
+)
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/PushAnnotatedTagIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/PushAnnotatedTagIT.java
new file mode 100644
index 0000000..24c8ed0
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/PushAnnotatedTagIT.java
@@ -0,0 +1,23 @@
+// 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.project;
+
+public class PushAnnotatedTagIT extends AbstractPushTag {
+
+ @Override
+ protected TagType getTagType() {
+ return TagType.ANNOTATED;
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/PushLightweightTagIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/PushLightweightTagIT.java
new file mode 100644
index 0000000..20d83a0
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/PushLightweightTagIT.java
@@ -0,0 +1,23 @@
+// 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.project;
+
+public class PushLightweightTagIT extends AbstractPushTag {
+
+ @Override
+ protected TagType getTagType() {
+ return TagType.LIGHTWEIGHT;
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/PushTagIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/PushTagIT.java
deleted file mode 100644
index 691ea8a..0000000
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/PushTagIT.java
+++ /dev/null
@@ -1,275 +0,0 @@
-// Copyright (C) 2016 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.project;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.acceptance.GitUtil.createAnnotatedTag;
-import static com.google.gerrit.acceptance.GitUtil.deleteRef;
-import static com.google.gerrit.acceptance.GitUtil.pushHead;
-import static com.google.gerrit.acceptance.GitUtil.updateAnnotatedTag;
-import static com.google.gerrit.acceptance.rest.project.PushTagIT.TagType.ANNOTATED;
-import static com.google.gerrit.acceptance.rest.project.PushTagIT.TagType.LIGHTWEIGHT;
-import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-
-import com.google.common.base.MoreObjects;
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GitUtil;
-import com.google.gerrit.acceptance.NoHttpd;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.reviewdb.client.RefNames;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.transport.PushResult;
-import org.eclipse.jgit.transport.RemoteRefUpdate;
-import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
-import org.junit.Before;
-import org.junit.Test;
-
-@NoHttpd
-public class PushTagIT extends AbstractDaemonTest {
- enum TagType {
- LIGHTWEIGHT(Permission.CREATE),
- ANNOTATED(Permission.CREATE_TAG);
-
- final String createPermission;
-
- TagType(String createPermission) {
- this.createPermission = createPermission;
- }
- }
-
- private RevCommit initialHead;
-
- @Before
- public void setup() throws Exception {
- // clone with user to avoid inherited tag permissions of admin user
- testRepo = cloneProject(project, user);
-
- initialHead = getRemoteHead();
- }
-
- @Test
- public void createTagForExistingCommit() throws Exception {
- for (TagType tagType : TagType.values()) {
- pushTagForExistingCommit(tagType, Status.REJECTED_OTHER_REASON);
-
- allowTagCreation(tagType);
- pushTagForExistingCommit(tagType, Status.OK);
-
- allowPushOnRefsTags();
- pushTagForExistingCommit(tagType, Status.OK);
-
- removePushFromRefsTags();
- }
- }
-
- @Test
- public void createTagForNewCommit() throws Exception {
- for (TagType tagType : TagType.values()) {
- pushTagForNewCommit(tagType, Status.REJECTED_OTHER_REASON);
-
- allowTagCreation(tagType);
- pushTagForNewCommit(tagType, Status.REJECTED_OTHER_REASON);
-
- allowPushOnRefsTags();
- pushTagForNewCommit(tagType, Status.OK);
-
- removePushFromRefsTags();
- }
- }
-
- @Test
- public void fastForward() throws Exception {
- for (TagType tagType : TagType.values()) {
- allowTagCreation(tagType);
- String tagName = pushTagForExistingCommit(tagType, Status.OK);
-
- fastForwardTagToExistingCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
- fastForwardTagToNewCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
-
- allowTagDeletion();
- fastForwardTagToExistingCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
- fastForwardTagToNewCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
-
- allowPushOnRefsTags();
- Status expectedStatus = tagType == ANNOTATED ? Status.REJECTED_OTHER_REASON : Status.OK;
- fastForwardTagToExistingCommit(tagType, tagName, expectedStatus);
- fastForwardTagToNewCommit(tagType, tagName, expectedStatus);
-
- allowForcePushOnRefsTags();
- fastForwardTagToExistingCommit(tagType, tagName, Status.OK);
- fastForwardTagToNewCommit(tagType, tagName, Status.OK);
-
- removePushFromRefsTags();
- }
- }
-
- @Test
- public void forceUpdate() throws Exception {
- for (TagType tagType : TagType.values()) {
- allowTagCreation(tagType);
- String tagName = pushTagForExistingCommit(tagType, Status.OK);
-
- forceUpdateTagToExistingCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
- forceUpdateTagToNewCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
-
- allowPushOnRefsTags();
- forceUpdateTagToExistingCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
- forceUpdateTagToNewCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
-
- allowTagDeletion();
- forceUpdateTagToExistingCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
- forceUpdateTagToNewCommit(tagType, tagName, Status.REJECTED_OTHER_REASON);
-
- allowForcePushOnRefsTags();
- forceUpdateTagToExistingCommit(tagType, tagName, Status.OK);
- forceUpdateTagToNewCommit(tagType, tagName, Status.OK);
-
- removePushFromRefsTags();
- }
- }
-
- @Test
- public void delete() throws Exception {
- for (TagType tagType : TagType.values()) {
- allowTagCreation(tagType);
- String tagName = pushTagForExistingCommit(tagType, Status.OK);
-
- pushTagDeletion(tagType, tagName, Status.REJECTED_OTHER_REASON);
-
- allowPushOnRefsTags();
- pushTagDeletion(tagType, tagName, Status.REJECTED_OTHER_REASON);
- }
-
- allowForcePushOnRefsTags();
- for (TagType tagType : TagType.values()) {
- String tagName = pushTagForExistingCommit(tagType, Status.OK);
- pushTagDeletion(tagType, tagName, Status.OK);
- }
-
- removePushFromRefsTags();
- allowTagDeletion();
- for (TagType tagType : TagType.values()) {
- String tagName = pushTagForExistingCommit(tagType, Status.OK);
- pushTagDeletion(tagType, tagName, Status.OK);
- }
- }
-
- private String pushTagForExistingCommit(TagType tagType, Status expectedStatus) throws Exception {
- return pushTag(tagType, null, false, false, expectedStatus);
- }
-
- private String pushTagForNewCommit(TagType tagType, Status expectedStatus) throws Exception {
- return pushTag(tagType, null, true, false, expectedStatus);
- }
-
- private void fastForwardTagToExistingCommit(
- TagType tagType, String tagName, Status expectedStatus) throws Exception {
- pushTag(tagType, tagName, false, false, expectedStatus);
- }
-
- private void fastForwardTagToNewCommit(TagType tagType, String tagName, Status expectedStatus)
- throws Exception {
- pushTag(tagType, tagName, true, false, expectedStatus);
- }
-
- private void forceUpdateTagToExistingCommit(
- TagType tagType, String tagName, Status expectedStatus) throws Exception {
- pushTag(tagType, tagName, false, true, expectedStatus);
- }
-
- private void forceUpdateTagToNewCommit(TagType tagType, String tagName, Status expectedStatus)
- throws Exception {
- pushTag(tagType, tagName, true, true, expectedStatus);
- }
-
- private String pushTag(
- TagType tagType, String tagName, boolean newCommit, boolean force, Status expectedStatus)
- throws Exception {
- if (force) {
- testRepo.reset(initialHead);
- }
- commit(user.getIdent(), "subject");
-
- boolean createTag = tagName == null;
- tagName = MoreObjects.firstNonNull(tagName, "v1_" + System.nanoTime());
- switch (tagType) {
- case LIGHTWEIGHT:
- break;
- case ANNOTATED:
- if (createTag) {
- createAnnotatedTag(testRepo, tagName, user.getIdent());
- } else {
- updateAnnotatedTag(testRepo, tagName, user.getIdent());
- }
- break;
- default:
- throw new IllegalStateException("unexpected tag type: " + tagType);
- }
-
- if (!newCommit) {
- grant(project, "refs/for/refs/heads/master", Permission.SUBMIT, false, REGISTERED_USERS);
- pushHead(testRepo, "refs/for/master%submit");
- }
-
- String tagRef = tagRef(tagName);
- PushResult r =
- tagType == LIGHTWEIGHT
- ? pushHead(testRepo, tagRef, false, force)
- : GitUtil.pushTag(testRepo, tagName, !createTag);
- RemoteRefUpdate refUpdate = r.getRemoteUpdate(tagRef);
- assertThat(refUpdate.getStatus()).named(tagType.name()).isEqualTo(expectedStatus);
- return tagName;
- }
-
- private void pushTagDeletion(TagType tagType, String tagName, Status expectedStatus)
- throws Exception {
- String tagRef = tagRef(tagName);
- PushResult r = deleteRef(testRepo, tagRef);
- RemoteRefUpdate refUpdate = r.getRemoteUpdate(tagRef);
- assertThat(refUpdate.getStatus()).named(tagType.name()).isEqualTo(expectedStatus);
- }
-
- private void allowTagCreation(TagType tagType) throws Exception {
- grant(project, "refs/tags/*", tagType.createPermission, false, REGISTERED_USERS);
- }
-
- private void allowPushOnRefsTags() throws Exception {
- removePushFromRefsTags();
- grant(project, "refs/tags/*", Permission.PUSH, false, REGISTERED_USERS);
- }
-
- private void allowForcePushOnRefsTags() throws Exception {
- removePushFromRefsTags();
- grant(project, "refs/tags/*", Permission.PUSH, true, REGISTERED_USERS);
- }
-
- private void allowTagDeletion() throws Exception {
- removePushFromRefsTags();
- grant(project, "refs/tags/*", Permission.DELETE, true, REGISTERED_USERS);
- }
-
- private void removePushFromRefsTags() throws Exception {
- removePermission(project, "refs/tags/*", Permission.PUSH);
- }
-
- private void commit(PersonIdent ident, String subject) throws Exception {
- commitBuilder().ident(ident).message(subject + " (" + System.nanoTime() + ")").create();
- }
-
- private static String tagRef(String tagName) {
- return RefNames.REFS_TAGS + tagName;
- }
-}
diff --git a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java
index b0429cb..ffedcfb 100644
--- a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java
+++ b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/GerritPublicKeyChecker.java
@@ -176,7 +176,6 @@
private boolean hasAllowedUserId(PGPPublicKey key, Set<String> allowedUserIds)
throws PGPException {
- @SuppressWarnings("unchecked")
Iterator<String> userIds = key.getUserIDs();
while (userIds.hasNext()) {
String userId = userIds.next();
diff --git a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/PublicKeyChecker.java b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/PublicKeyChecker.java
index c0ab26c..70e9a24 100644
--- a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/PublicKeyChecker.java
+++ b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/PublicKeyChecker.java
@@ -381,7 +381,6 @@
}
List<CheckResult> signerResults = new ArrayList<>();
- @SuppressWarnings("unchecked")
Iterator<String> userIds = key.getUserIDs();
while (userIds.hasNext()) {
String userId = userIds.next();
diff --git a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/PublicKeyStore.java b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/PublicKeyStore.java
index 144606a..8ab5fbd 100644
--- a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/PublicKeyStore.java
+++ b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/PublicKeyStore.java
@@ -398,7 +398,6 @@
}
public static String keyToString(PGPPublicKey key) {
- @SuppressWarnings("unchecked")
Iterator<String> it = key.getUserIDs();
return String.format(
"%s %s(%s)",
diff --git a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/GpgKeys.java b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/GpgKeys.java
index 678247e..303499e 100644
--- a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/GpgKeys.java
+++ b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/GpgKeys.java
@@ -219,7 +219,6 @@
if (key != null) {
info.id = PublicKeyStore.keyIdToString(key.getKeyID());
info.fingerprint = Fingerprint.toString(key.getFingerprint());
- @SuppressWarnings("unchecked")
Iterator<String> userIds = key.getUserIDs();
info.userIds = ImmutableList.copyOf(userIds);
diff --git a/gerrit-gpg/src/test/java/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java b/gerrit-gpg/src/test/java/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
index 64311e0..524af50 100644
--- a/gerrit-gpg/src/test/java/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
+++ b/gerrit-gpg/src/test/java/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
@@ -374,7 +374,7 @@
PGPPublicKeyRing keyRingB = keyB().getPublicKeyRing();
PGPPublicKey keyB = keyRingB.getPublicKey();
- keyB = PGPPublicKey.removeCertification(keyB, (String) keyB.getUserIDs().next());
+ keyB = PGPPublicKey.removeCertification(keyB, keyB.getUserIDs().next());
keyRingB = PGPPublicKeyRing.insertPublicKey(keyRingB, keyB);
add(keyRingB, addUser("userB"));
@@ -392,8 +392,7 @@
List<ExternalId> newExtIds = new ArrayList<>(2);
newExtIds.add(ExternalId.create(toExtIdKey(kr.getPublicKey()), id));
- @SuppressWarnings("unchecked")
- String userId = (String) Iterators.getOnlyElement(kr.getPublicKey().getUserIDs(), null);
+ String userId = Iterators.getOnlyElement(kr.getPublicKey().getUserIDs(), null);
if (userId != null) {
String email = PushCertificateIdent.parse(userId).getEmailAddress();
assertThat(email).contains("@");
diff --git a/gerrit-gpg/src/test/java/com/google/gerrit/gpg/PublicKeyStoreTest.java b/gerrit-gpg/src/test/java/com/google/gerrit/gpg/PublicKeyStoreTest.java
index c9c0b18..94eff06 100644
--- a/gerrit-gpg/src/test/java/com/google/gerrit/gpg/PublicKeyStoreTest.java
+++ b/gerrit-gpg/src/test/java/com/google/gerrit/gpg/PublicKeyStoreTest.java
@@ -231,7 +231,6 @@
private void assertUserIds(PGPPublicKeyRing keyRing, String... expected) throws Exception {
List<String> actual = new ArrayList<>();
- @SuppressWarnings("unchecked")
Iterator<String> userIds =
store.get(keyRing.getPublicKey().getKeyID()).iterator().next().getPublicKey().getUserIDs();
while (userIds.hasNext()) {
diff --git a/gerrit-gpg/src/test/java/com/google/gerrit/gpg/testutil/TestKey.java b/gerrit-gpg/src/test/java/com/google/gerrit/gpg/testutil/TestKey.java
index 420dedf..b2ef65d 100644
--- a/gerrit-gpg/src/test/java/com/google/gerrit/gpg/testutil/TestKey.java
+++ b/gerrit-gpg/src/test/java/com/google/gerrit/gpg/testutil/TestKey.java
@@ -77,7 +77,7 @@
}
public String getFirstUserId() {
- return (String) getPublicKey().getUserIDs().next();
+ return getPublicKey().getUserIDs().next();
}
public PGPPrivateKey getPrivateKey() throws PGPException {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
index d78e592..8bbc988 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
@@ -541,26 +541,31 @@
mode = ModeInfo.findMode(content.getContentType(), path);
}
}
- mv =
- MergeView.create(
- editor,
- Configuration.create()
- .set("autoCloseBrackets", prefs.autoCloseBrackets())
- .set("cursorBlinkRate", prefs.cursorBlinkRate())
- .set("cursorHeight", 0.85)
- .set("indentUnit", prefs.indentUnit())
- .set("keyMap", prefs.keyMapType().name().toLowerCase())
- .set("lineNumbers", prefs.hideLineNumbers())
- .set("lineWrapping", false)
- .set("matchBrackets", prefs.matchBrackets())
- .set("mode", mode != null ? mode.mime() : null)
- .set("origLeft", editContent)
- .set("scrollbarStyle", "overlay")
- .set("showTrailingSpace", prefs.showWhitespaceErrors())
- .set("styleSelectedText", true)
- .set("tabSize", prefs.tabSize())
- .set("theme", prefs.theme().name().toLowerCase())
- .set("value", ""));
+
+ Configuration cfg =
+ Configuration.create()
+ .set("autoCloseBrackets", prefs.autoCloseBrackets())
+ .set("cursorBlinkRate", prefs.cursorBlinkRate())
+ .set("cursorHeight", 0.85)
+ .set("indentUnit", prefs.indentUnit())
+ .set("keyMap", prefs.keyMapType().name().toLowerCase())
+ .set("lineNumbers", prefs.hideLineNumbers())
+ .set("lineWrapping", false)
+ .set("matchBrackets", prefs.matchBrackets())
+ .set("mode", mode != null ? mode.mime() : null)
+ .set("origLeft", editContent)
+ .set("scrollbarStyle", "overlay")
+ .set("showTrailingSpace", prefs.showWhitespaceErrors())
+ .set("styleSelectedText", true)
+ .set("tabSize", prefs.tabSize())
+ .set("theme", prefs.theme().name().toLowerCase())
+ .set("value", "");
+
+ if (editContent.contains("\r\n")) {
+ cfg.set("lineSeparator", "\r\n");
+ }
+
+ mv = MergeView.create(editor, cfg);
cmBase = mv.leftOriginal();
cmBase.getWrapperElement().addClassName(style.base());
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
index 01c5ea4..8561dce 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
@@ -30,7 +30,6 @@
import com.google.inject.Singleton;
import com.google.inject.servlet.ServletModule;
import java.io.IOException;
-import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.regex.Matcher;
@@ -114,7 +113,7 @@
cont.suspend(rsp);
cont.setAttribute(TASK, task);
- Future f = getExecutor().submit(task);
+ Future<?> f = getExecutor().submit(task);
cont.addContinuationListener(new Listener(f));
} else if (cont.isExpired()) {
rsp.sendError(SC_SERVICE_UNAVAILABLE);
@@ -150,9 +149,9 @@
public void destroy() {}
private final class Listener implements ContinuationListener {
- final Future future;
+ final Future<?> future;
- Listener(Future future) {
+ Listener(Future<?> future) {
this.future = future;
}
@@ -163,7 +162,6 @@
public void onTimeout(Continuation self) {
future.cancel(true);
}
-
}
private final class TaskThunk implements CancelableRunnable {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/StarredChangesUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/StarredChangesUtil.java
index a7c04f6..26cb3e3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/StarredChangesUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/StarredChangesUtil.java
@@ -17,7 +17,6 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toSet;
import com.google.auto.value.AutoValue;
import com.google.common.base.CharMatcher;
@@ -267,49 +266,6 @@
}
}
- public Set<Account.Id> byChange(Change.Id changeId, String label) throws OrmException {
- try (Repository repo = repoManager.openRepository(allUsers)) {
- return getRefNames(repo, RefNames.refsStarredChangesPrefix(changeId))
- .stream()
- .map(Account.Id::parse)
- .filter(accountId -> hasStar(repo, changeId, accountId, label))
- .collect(toSet());
- } catch (IOException e) {
- throw new OrmException(
- String.format("Get accounts that starred change %d failed", changeId.get()), e);
- }
- }
-
- @Deprecated
- // To be used only for IsStarredByLegacyPredicate.
- public Set<Change.Id> byAccount(Account.Id accountId, String label) throws OrmException {
- try (Repository repo = repoManager.openRepository(allUsers)) {
- return getRefNames(repo, RefNames.REFS_STARRED_CHANGES)
- .stream()
- .filter(refPart -> refPart.endsWith("/" + accountId.get()))
- .map(Change.Id::fromRefPart)
- .filter(changeId -> hasStar(repo, changeId, accountId, label))
- .collect(toSet());
- } catch (IOException e) {
- throw new OrmException(
- String.format("Get changes that were starred by %d failed", accountId.get()), e);
- }
- }
-
- private boolean hasStar(Repository repo, Change.Id changeId, Account.Id accountId, String label) {
- try {
- return readLabels(repo, RefNames.refsStarredChanges(changeId, accountId))
- .labels()
- .contains(label);
- } catch (IOException e) {
- log.error(
- String.format(
- "Cannot query stars by account %d on change %d", accountId.get(), changeId.get()),
- e);
- return false;
- }
- }
-
public ImmutableListMultimap<Account.Id, String> byChangeFromIndex(Change.Id changeId)
throws OrmException {
Set<String> fields = ImmutableSet.of(ChangeField.ID.getName(), ChangeField.STAR.getName());
@@ -351,7 +307,7 @@
}
public boolean isIgnoredBy(Change.Id changeId, Account.Id accountId) throws OrmException {
- return byChange(changeId, IGNORE_LABEL).contains(accountId);
+ return getLabels(accountId, changeId).contains(IGNORE_LABEL);
}
private static String getMuteLabel(Change change) {
@@ -379,7 +335,7 @@
}
public boolean isMutedBy(Change change, Account.Id accountId) throws OrmException {
- return byChange(change.getId(), getMuteLabel(change)).contains(accountId);
+ return getLabels(accountId, change.getId()).contains(getMuteLabel(change));
}
private static StarRef readLabels(Repository repo, String refName) throws IOException {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java
index 040b6de..d8ff050 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java
@@ -15,6 +15,8 @@
package com.google.gerrit.server.change;
import com.google.common.collect.Lists;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
import com.google.gerrit.extensions.common.FileInfo;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicMap;
@@ -22,10 +24,10 @@
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.CacheControl;
import com.google.gerrit.extensions.restapi.ChildCollection;
+import com.google.gerrit.extensions.restapi.ETagView;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
-import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
@@ -38,6 +40,7 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListCache;
+import com.google.gerrit.server.patch.PatchListKey;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -90,7 +93,7 @@
return new FileResource(rev, id.get());
}
- public static final class ListFiles implements RestReadView<RevisionResource> {
+ public static final class ListFiles implements ETagView<RevisionResource> {
private static final Logger log = LoggerFactory.getLogger(ListFiles.class);
@Option(name = "--base", metaVar = "revision-id")
@@ -322,5 +325,15 @@
this.parentNum = parentNum;
return this;
}
+
+ @Override
+ public String getETag(RevisionResource resource) {
+ Hasher h = Hashing.murmur3_128().newHasher();
+ resource.prepareETag(h, resource.getUser());
+ // File list comes from the PatchListCache, so any change to the key or value should
+ // invalidate ETag.
+ h.putLong(PatchListKey.serialVersionUID);
+ return h.hash().toString();
+ }
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/RevisionResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/RevisionResource.java
index 32132bc..a582e2c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/RevisionResource.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/RevisionResource.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.change;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestResource.HasETag;
import com.google.gerrit.extensions.restapi.RestView;
@@ -82,10 +84,15 @@
@Override
public String getETag() {
- // Conservative estimate: refresh the revision if its parent change has
- // changed, so we don't have to check whether a given modification affected
- // this revision specifically.
- return change.getETag();
+ Hasher h = Hashing.murmur3_128().newHasher();
+ prepareETag(h, getUser());
+ return h.hash().toString();
+ }
+
+ void prepareETag(Hasher h, CurrentUser user) {
+ // Conservative estimate: refresh the revision if its parent change has changed, so we don't
+ // have to check whether a given modification affected this revision specifically.
+ change.prepareETag(h, user);
}
Account.Id getAccountId() {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfig.java
index 2ac6695..674a5c6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfig.java
@@ -159,6 +159,7 @@
}
public void setGroupReference(String name, GroupReference value) {
- setString(name, value.toConfigValue());
+ GroupReference groupRef = projectConfig.resolve(value);
+ setString(name, groupRef.toConfigValue());
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/AsyncReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/AsyncReceiveCommits.java
index db0066d..a48b3ea 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/AsyncReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/AsyncReceiveCommits.java
@@ -29,7 +29,7 @@
import java.io.OutputStream;
import java.util.Collection;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
@@ -125,7 +125,7 @@
}
private final ReceiveCommits rc;
- private final ScheduledThreadPoolExecutor executor;
+ private final ScheduledExecutorService executor;
private final RequestScopePropagator scopePropagator;
private final MultiProgressMonitor progress;
private final long timeoutMillis;
@@ -133,7 +133,7 @@
@Inject
AsyncReceiveCommits(
ReceiveCommits.Factory factory,
- @ReceiveCommitsExecutor ScheduledThreadPoolExecutor executor,
+ @ReceiveCommitsExecutor ScheduledExecutorService executor,
RequestScopePropagator scopePropagator,
@Named(TIMEOUT_NAME) long timeoutMillis,
@Assisted ProjectControl projectControl,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
index 0c73d05..91379fd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
@@ -416,7 +416,13 @@
}
public GroupReference resolve(GroupReference group) {
- return groupList.resolve(group);
+ GroupReference groupRef = groupList.resolve(group);
+ if (groupRef != null
+ && groupRef.getUUID() != null
+ && !groupsByName.containsKey(groupRef.getName())) {
+ groupsByName.put(groupRef.getName(), groupRef);
+ }
+ return groupRef;
}
/** @return the group reference, if the group is used by at least one rule. */
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 86daf8e..8cac1a4 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
@@ -1070,22 +1070,19 @@
}
RefControl ctl = projectControl.controlForRef(cmd.getRefName());
- boolean ok;
- try {
- permissions.ref(cmd.getRefName()).check(RefPermission.CREATE);
- ok = true;
- } catch (AuthException err) {
- ok = false;
+ String rejectReason = ctl.canCreate(rp.getRepository(), obj);
+ if (rejectReason != null) {
+ reject(cmd, "prohibited by Gerrit: " + rejectReason);
+ return;
}
- if (ok && ctl.canCreate(rp.getRepository(), obj)) {
- if (!validRefOperation(cmd)) {
- return;
- }
- validateNewCommits(ctl, cmd);
- actualCommands.add(cmd);
- } else {
- reject(cmd, "prohibited by Gerrit: create access denied for " + cmd.getRefName());
+
+ if (!validRefOperation(cmd)) {
+ // validRefOperation sets messages, so no need to provide more feedback.
+ return;
}
+
+ validateNewCommits(ctl, cmd);
+ actualCommands.add(cmd);
}
private void parseUpdate(ReceiveCommand cmd) throws PermissionBackendException {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutorModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutorModule.java
index 55707bd..76f1369 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutorModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutorModule.java
@@ -24,7 +24,7 @@
import com.google.inject.Singleton;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.Config;
@@ -37,7 +37,7 @@
@Provides
@Singleton
@ReceiveCommitsExecutor
- public ScheduledThreadPoolExecutor createReceiveCommitsExecutor(
+ public ScheduledExecutorService createReceiveCommitsExecutor(
@GerritServerConfig Config config, WorkQueue queues) {
int poolSize =
config.getInt(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/WorkQueue.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/WorkQueue.java
index 33e7961..0adb45a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/WorkQueue.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/WorkQueue.java
@@ -35,6 +35,7 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RunnableScheduledFuture;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@@ -82,7 +83,7 @@
}
};
- private ScheduledThreadPoolExecutor defaultQueue;
+ private ScheduledExecutorService defaultQueue;
private int defaultQueueSize;
private final IdGenerator idGenerator;
private final CopyOnWriteArrayList<Executor> queues;
@@ -99,7 +100,7 @@
}
/** Get the default work queue, for miscellaneous tasks. */
- public synchronized ScheduledThreadPoolExecutor getDefaultQueue() {
+ public synchronized ScheduledExecutorService getDefaultQueue() {
if (defaultQueue == null) {
defaultQueue = createQueue(defaultQueueSize, "WorkQueue");
}
@@ -107,7 +108,7 @@
}
/** Create a new executor queue. */
- public ScheduledThreadPoolExecutor createQueue(int poolsize, String prefix) {
+ public ScheduledExecutorService createQueue(int poolsize, String prefix) {
return createQueue(poolsize, prefix, Thread.NORM_PRIORITY);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java
index e42a1cf..0c15063 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java
@@ -117,8 +117,9 @@
}
}
- if (!refControl.canCreate(repo, object)) {
- throw new AuthException("Cannot create \"" + ref + "\"");
+ String rejectReason = refControl.canCreate(repo, object);
+ if (rejectReason != null) {
+ throw new AuthException("Cannot create \"" + ref + "\": " + rejectReason);
}
try {
@@ -155,7 +156,7 @@
}
refPrefix = RefUtil.getRefPrefix(refPrefix);
}
- //$FALL-THROUGH$
+ // $FALL-THROUGH$
case FORCED:
case IO_FAILURE:
case NOT_ATTEMPTED:
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index de22e23..2a22b1e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -16,6 +16,7 @@
import static com.google.common.base.Preconditions.checkArgument;
+import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.common.data.PermissionRule;
@@ -259,17 +260,18 @@
*
* @param repo repository on which user want to create
* @param object the object the user will start the reference with.
- * @return {@code true} if the user specified can create a new Git ref
+ * @return {@code null} if the user specified can create a new Git ref, or a String describing why
+ * the creation is not allowed.
*/
- public boolean canCreate(Repository repo, RevObject object) {
+ @Nullable
+ public String canCreate(Repository repo, RevObject object) {
if (!isProjectStatePermittingWrite()) {
- return false;
+ return "project state does not permit write";
}
if (object instanceof RevCommit) {
if (!canPerform(Permission.CREATE)) {
- // No create permissions.
- return false;
+ return "lacks permission: " + Permission.CREATE;
}
return canCreateCommit(repo, (RevCommit) object);
} else if (object instanceof RevTag) {
@@ -277,7 +279,13 @@
try (RevWalk rw = new RevWalk(repo)) {
rw.parseBody(tag);
} catch (IOException e) {
- return false;
+ String msg =
+ String.format(
+ "RevWalk(%s) for pushing tag %s:",
+ projectControl.getProject().getNameKey(), tag.name());
+ log.error(msg, e);
+
+ return "I/O exception for revwalk";
}
// If tagger is present, require it matches the user's email.
@@ -292,18 +300,20 @@
valid = false;
}
if (!valid && !canForgeCommitter()) {
- return false;
+ return "lacks permission: " + Permission.FORGE_COMMITTER;
}
}
RevObject tagObject = tag.getObject();
if (tagObject instanceof RevCommit) {
- if (!canCreateCommit(repo, (RevCommit) tagObject)) {
- return false;
+ String rejectReason = canCreateCommit(repo, (RevCommit) tagObject);
+ if (rejectReason != null) {
+ return rejectReason;
}
} else {
- if (!canCreate(repo, tagObject)) {
- return false;
+ String rejectReason = canCreate(repo, tagObject);
+ if (rejectReason != null) {
+ return rejectReason;
}
}
@@ -311,27 +321,34 @@
// than if it doesn't have a PGP signature.
//
if (tag.getFullMessage().contains("-----BEGIN PGP SIGNATURE-----\n")) {
- return canPerform(Permission.CREATE_SIGNED_TAG);
+ return canPerform(Permission.CREATE_SIGNED_TAG)
+ ? null
+ : "lacks permission: " + Permission.CREATE_SIGNED_TAG;
}
- return canPerform(Permission.CREATE_TAG);
- } else {
- return false;
+ return canPerform(Permission.CREATE_TAG) ? null : "lacks permission " + Permission.CREATE_TAG;
}
+
+ return null;
}
- private boolean canCreateCommit(Repository repo, RevCommit commit) {
+ /**
+ * Check if the user is allowed to create a new commit object if this introduces a new commit to
+ * the project. If not allowed, returns a string describing why it's not allowed.
+ */
+ @Nullable
+ private String canCreateCommit(Repository repo, RevCommit commit) {
if (canUpdate()) {
// If the user has push permissions, they can create the ref regardless
// of whether they are pushing any new objects along with the create.
- return true;
+ return null;
} else if (isMergedIntoBranchOrTag(repo, commit)) {
// If the user has no push permissions, check whether the object is
// merged into a branch or tag readable by this user. If so, they are
// not effectively "pushing" more objects, so they can create the ref
// even if they don't have push permission.
- return true;
+ return null;
}
- return false;
+ return "lacks permission " + Permission.PUSH + " for creating new commit object";
}
private boolean isMergedIntoBranchOrTag(Repository repo, RevCommit commit) {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java
index 914e074..fed0be4 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java
@@ -474,6 +474,14 @@
+ "\tkey1 = "
+ staff.toConfigValue()
+ "\n");
+ assertThat(text(rev, "groups"))
+ .isEqualTo(
+ "# UUID\tGroup Name\n" //
+ + "#\n" //
+ + staff.getUUID().get()
+ + " \t"
+ + staff.getName()
+ + "\n");
}
private ProjectConfig read(RevCommit rev) throws IOException, ConfigInvalidException {
diff --git a/lib/fonts/BUILD b/lib/fonts/BUILD
index 6b3b4ee..57429f3 100644
--- a/lib/fonts/BUILD
+++ b/lib/fonts/BUILD
@@ -10,4 +10,4 @@
],
data = ["//lib:LICENSE-Apache2.0"],
visibility = ["//visibility:public"],
-)
\ No newline at end of file
+)
diff --git a/plugins/replication b/plugins/replication
index 1085b45..fae5360 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit 1085b453039b0fe230c3584e0024a7965cc1e323
+Subproject commit fae5360380023e8351f39be3d4effd4bb2cd8906
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-project/gr-admin-project.html b/polygerrit-ui/app/elements/admin/gr-admin-project/gr-admin-project.html
index a9dd3df8..448e713 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-project/gr-admin-project.html
+++ b/polygerrit-ui/app/elements/admin/gr-admin-project/gr-admin-project.html
@@ -97,7 +97,7 @@
id="submitTypeSelect"
is="gr-select"
bind-value="{{_projectConfig.submit_type}}"
- disabled$="[[_readOnly]]">>
+ disabled$="[[_readOnly]]">
<template is="dom-repeat" items="[[_submitTypes]]">
<option value="[[item.value]]">[[item.label]]</option>
</template>
@@ -128,7 +128,7 @@
id="newChangeSelect"
is="gr-select"
bind-value="{{_projectConfig.create_new_change_for_all_not_in_target.configured_value}}"
- disabled$="[[_readOnly]]">>
+ disabled$="[[_readOnly]]">
<template is="dom-repeat"
items="[[_formatBooleanSelect(_projectConfig.create_new_change_for_all_not_in_target)]]">
<option value="[[item.value]]">[[item.label]]</option>
@@ -143,7 +143,7 @@
id="requireChangeIdSelect"
is="gr-select"
bind-value="{{_projectConfig.require_change_id.configured_value}}"
- disabled$="[[_readOnly]]">>
+ disabled$="[[_readOnly]]">
<template is="dom-repeat"
items="[[_formatBooleanSelect(_projectConfig.require_change_id)]]">
<option value="[[item.value]]">[[item.label]]</option>
@@ -159,7 +159,7 @@
id="rejectImplicitMergesSelect"
is="gr-select"
bind-value="{{_projectConfig.reject_implicit_merges.configured_value}}"
- disabled$="[[_readOnly]]">>
+ disabled$="[[_readOnly]]">
<template is="dom-repeat"
items="[[_formatBooleanSelect(_projectConfig.reject_implicit_merges)]]">
<option value="[[item.value]]">[[item.label]]</option>
@@ -189,7 +189,7 @@
id="contributorAgreementSelect"
is="gr-select"
bind-value="{{_projectConfig.use_contributor_agreements.configured_value}}"
- disabled$="[[_readOnly]]">>
+ disabled$="[[_readOnly]]">
<template is="dom-repeat"
items="[[_formatBooleanSelect(_projectConfig.use_contributor_agreements)]]">
<option value="[[item.value]]">[[item.label]]</option>
@@ -204,7 +204,7 @@
id="useSignedOffBySelect"
is="gr-select"
bind-value="{{_projectConfig.use_signed_off_by.configured_value}}"
- disabled$="[[_readOnly]]">>
+ disabled$="[[_readOnly]]">
<template is="dom-repeat"
items="[[_formatBooleanSelect(_projectConfig.use_signed_off_by)]]">
<option value="[[item.value]]">[[item.label]]</option>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
index c1640fa..010a01f 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
@@ -93,8 +93,14 @@
this._reviewers = result.filter(reviewer => {
return reviewer._account_id != owner._account_id;
});
- this._displayedReviewers =
+ // If there is one more than the max reviewers, don't show the 'show more'
+ // button, because it takes up just as much space.
+ if (this._reviewers.length <= MAX_REVIEWERS_DISPLAYED + 1) {
+ this._displayedReviewers = this._reviewers;
+ } else {
+ this._displayedReviewers =
this._reviewers.slice(0, MAX_REVIEWERS_DISPLAYED);
+ }
},
_computeHiddenCount(reviewers, displayedReviewers) {
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
index 4e0541e6..3c1773d 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
@@ -188,9 +188,9 @@
{value: {ccsOnly: true}}));
});
- test('no show all reviewers button with 5 reviewers', () => {
+ test('no show all reviewers button with 6 reviewers', () => {
const reviewers = [];
- for (let i = 0; i < 5; i++) {
+ for (let i = 0; i < 6; i++) {
reviewers.push(
{email: i+'reviewer@google.com', name: 'reviewer-' + i});
}
@@ -206,11 +206,34 @@
};
flushAsynchronousOperations();
assert.equal(element._hiddenReviewerCount, 0);
- assert.equal(element._displayedReviewers.length, 5);
- assert.equal(element._reviewers.length, 5);
+ assert.equal(element._displayedReviewers.length, 6);
+ assert.equal(element._reviewers.length, 6);
assert.isTrue(element.$$('.hiddenReviewers').hidden);
});
+ test('how all reviewers button with 7 reviewers', () => {
+ const reviewers = [];
+ for (let i = 0; i < 7; i++) {
+ reviewers.push(
+ {email: i+'reviewer@google.com', name: 'reviewer-' + i});
+ }
+ element.ccsOnly = true;
+
+ element.change = {
+ owner: {
+ _account_id: 1,
+ },
+ reviewers: {
+ CC: reviewers,
+ },
+ };
+ flushAsynchronousOperations();
+ assert.equal(element._hiddenReviewerCount, 2);
+ assert.equal(element._displayedReviewers.length, 5);
+ assert.equal(element._reviewers.length, 7);
+ assert.isFalse(element.$$('.hiddenReviewers').hidden);
+ });
+
test('show all reviewers button', () => {
const reviewers = [];
for (let i = 0; i < 100; i++) {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index 5319ace..6aae8d1 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -142,20 +142,6 @@
.content.remove {
background-color: var(--light-remove-highlight-color);
}
- .dueToRebase .content.add .intraline,
- .delta.total.dueToRebase .content.add {
- background-color: var(--dark-rebased-add-highlight-color);
- }
- .dueToRebase .content.add {
- background-color: var(--light-rebased-add-highlight-color);
- }
- .dueToRebase .content.remove .intraline,
- .delta.total.dueToRebase .content.remove {
- background-color: var(--dark-rebased-remove-highlight-color);
- }
- .dueToRebase .content.remove {
- background-color: var(--light-rebased-remove-highlight-color);
- }
.content .contentText:after {
/* Newline, to ensure all lines are one line-height tall. */
content: '\A';
diff --git a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.html b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.html
new file mode 100644
index 0000000..c93c509
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.html
@@ -0,0 +1,57 @@
+<!--
+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.
+-->
+
+<link rel="import" href="../../../behaviors/base-url-behavior/base-url-behavior.html">
+<link rel="import" href="../../../bower_components/polymer/polymer.html">
+<link rel="import" href="../../../styles/gr-form-styles.html">
+<link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
+
+<dom-module id="gr-agreements-list">
+ <template>
+ <style include="shared-styles">
+ .nameHeader {
+ width: 15em;
+ }
+ .descriptionHeader {
+ width: 21.5em;
+ }
+ </style>
+ <style include="gr-form-styles"></style>
+ <div class="gr-form-styles">
+ <table>
+ <thead>
+ <tr>
+ <th class="nameHeader">Name</th>
+ <th class="descriptionHeader">Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <template is="dom-repeat" items="[[_agreements]]">
+ <tr>
+ <td><a href$="[[getUrlBase(item.url)]]">[[item.name]]</a></td>
+ <td>[[item.description]]</td>
+ </tr>
+ </template>
+ </tbody>
+ </table>
+ <!-- TODO: Renable this when supported in polygerrit -->
+ <!-- <a href$="[[getUrl()]]">New Contributor Agreement</a> -->
+ </div>
+ <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+ </template>
+ <script src="gr-agreements-list.js"></script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.js b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.js
new file mode 100644
index 0000000..4e25523
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.js
@@ -0,0 +1,46 @@
+// 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.
+(function() {
+ 'use strict';
+
+ Polymer({
+ is: 'gr-agreements-list',
+
+ properties: {
+ _agreements: Array,
+ },
+
+ behaviors: [
+ Gerrit.BaseUrlBehavior,
+ ],
+
+ attached() {
+ this.loadData();
+ },
+
+ loadData() {
+ return this.$.restAPI.getAccountAgreements().then(agreements => {
+ this._agreements = agreements;
+ });
+ },
+
+ getUrl() {
+ return this.getBaseUrl() + '/settings/new-agreement';
+ },
+
+ getUrlBase(item) {
+ return this.getBaseUrl() + '/' + item;
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html
new file mode 100644
index 0000000..13b8952
--- /dev/null
+++ b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html
@@ -0,0 +1,67 @@
+<!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-settings-view</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="../../../test/common-test-setup.html"/>
+<link rel="import" href="gr-agreements-list.html">
+
+<script>void(0);</script>
+
+<test-fixture id="basic">
+ <template>
+ <gr-agreements-list></gr-agreements-list>
+ </template>
+</test-fixture>
+
+<script>
+ suite('gr-agreements-list tests', () => {
+ let element;
+ let agreements;
+
+ setup(done => {
+ agreements = [{
+ url: 'some url',
+ description: 'Agreements 1 description',
+ name: 'Agreements 1',
+ }];
+
+ stub('gr-rest-api-interface', {
+ getAccountGroups() { return Promise.resolve(agreements); },
+ });
+
+ element = fixture('basic');
+
+ element.loadData().then(() => { flush(done); });
+ });
+
+ test('renders', () => {
+ const rows = Polymer.dom(element.root).querySelectorAll('tbody tr');
+
+ assert.equal(rows.length, 3);
+
+ const nameCells = rows.map(row =>
+ row.querySelectorAll('td')[0].textContent
+ );
+
+ assert.equal(nameCells[0], 'Agreements 1');
+ });
+ });
+</script>
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
index aa568b3..2cf3c94 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
@@ -16,22 +16,23 @@
<link rel="import" href="../../../bower_components/polymer/polymer.html">
-<link rel="import" href="../gr-account-info/gr-account-info.html">
-<link rel="import" href="../gr-email-editor/gr-email-editor.html">
-<link rel="import" href="../gr-group-list/gr-group-list.html">
-<link rel="import" href="../gr-http-password/gr-http-password.html">
-<link rel="import" href="../gr-menu-editor/gr-menu-editor.html">
-<link rel="import" href="../gr-ssh-editor/gr-ssh-editor.html">
-<link rel="import" href="../gr-watched-projects-editor/gr-watched-projects-editor.html">
+<link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../../../styles/gr-menu-page-styles.html">
+<link rel="import" href="../../../styles/gr-form-styles.html">
<link rel="import" href="../../settings/gr-change-table-editor/gr-change-table-editor.html">
<link rel="import" href="../../shared/gr-button/gr-button.html">
<link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
<link rel="import" href="../../shared/gr-page-nav/gr-page-nav.html">
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
<link rel="import" href="../../shared/gr-select/gr-select.html">
-<link rel="import" href="../../../styles/shared-styles.html">
-<link rel="import" href="../../../styles/gr-menu-page-styles.html">
-<link rel="import" href="../../../styles/gr-form-styles.html">
+<link rel="import" href="../gr-account-info/gr-account-info.html">
+<link rel="import" href="../gr-agreements-list/gr-agreements-list.html">
+<link rel="import" href="../gr-email-editor/gr-email-editor.html">
+<link rel="import" href="../gr-group-list/gr-group-list.html">
+<link rel="import" href="../gr-http-password/gr-http-password.html">
+<link rel="import" href="../gr-menu-editor/gr-menu-editor.html">
+<link rel="import" href="../gr-ssh-editor/gr-ssh-editor.html">
+<link rel="import" href="../gr-watched-projects-editor/gr-watched-projects-editor.html">
<dom-module id="gr-settings-view">
<template>
@@ -58,6 +59,9 @@
SSH Keys
</a></li>
<li><a href="#Groups">Groups</a></li>
+ <li hidden$="[[!_serverConfig.auth.contributor_agreements]]">
+ <a href="#Agreements">Agreements</a>
+ </li>
</ul>
</gr-page-nav>
<main class="gr-form-styles">
@@ -360,6 +364,12 @@
<fieldset>
<gr-group-list id="groupList"></gr-group-list>
</fieldset>
+ <div hidden$="[[!_serverConfig.auth.contributor_agreements]]">
+ <h2 id="Agreements">Agreements</h2>
+ <fieldset>
+ <gr-agreements-list id="agreementsList"></gr-agreements-list>
+ </fieldset>
+ </div>
</main>
</div>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
diff --git a/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav.js b/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav.js
index f093505..6d7f979 100644
--- a/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav.js
+++ b/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav.js
@@ -48,6 +48,7 @@
/* Functions used for test purposes */
_getOffsetParent(element) {
+ if (!element.offsetParent) { return ''; }
return element.offsetParent;
},
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 1a192bd..eb2b8c6 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
@@ -282,6 +282,10 @@
return this._fetchSharedCacheURL('/accounts/self/groups');
},
+ getAccountAgreements() {
+ return this._fetchSharedCacheURL('/accounts/self/agreements');
+ },
+
getAccountCapabilities(opt_params) {
let queryString = '';
if (opt_params) {
diff --git a/polygerrit-ui/app/embed/change-diff-views.html b/polygerrit-ui/app/embed/change-diff-views.html
index b4f521b..8426585 100644
--- a/polygerrit-ui/app/embed/change-diff-views.html
+++ b/polygerrit-ui/app/embed/change-diff-views.html
@@ -16,3 +16,4 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../elements/change/gr-change-view/gr-change-view.html">
<link rel="import" href="../elements/diff/gr-diff-view/gr-diff-view.html">
+<link rel="import" href="../styles/app-theme.html">
diff --git a/polygerrit-ui/server.go b/polygerrit-ui/server.go
index f2a97bf..a42acc3 100644
--- a/polygerrit-ui/server.go
+++ b/polygerrit-ui/server.go
@@ -122,6 +122,9 @@
}
func injectLocalPlugins(r io.Reader) io.Reader {
+ if len(*plugins) == 0 {
+ return r
+ }
// Skip escape prefix
io.CopyN(ioutil.Discard, r, 5)
dec := json.NewDecoder(r)