Merge "Set a maximum length on topic display"
diff --git a/Documentation/config-project-config.txt b/Documentation/config-project-config.txt
index 22f785e..3644845 100644
--- a/Documentation/config-project-config.txt
+++ b/Documentation/config-project-config.txt
@@ -326,6 +326,8 @@
A boolean indicating if reviewers and CCs that do not currently have a Gerrit
account can be added to a change by providing their email address.
+This setting only takes affect for changes that are readable by anonymous users.
+
Default is `INHERIT`, which means that this property is inherited from
the parent project. If the property is not set in any parent project, the
default value is `FALSE`.
diff --git a/WORKSPACE b/WORKSPACE
index 5f3d1e9..53a45a9 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -444,6 +444,7 @@
sha1 = "18a9a2ce6abf32ea1b5fd31dae5210ad93f4e5e3",
)
+# When upgrading Lucene, make sure it's compatible with Elasticsearch
LUCENE_VERS = "5.5.4"
maven_jar(
@@ -918,6 +919,7 @@
sha1 = "00d0003e99da3c4d830b12c099691ce910c84e39",
)
+# When upgrading Elasticsearch, make sure it's compatible with Lucene
maven_jar(
name = "elasticsearch",
artifact = "org.elasticsearch:elasticsearch:2.4.5",
@@ -1055,8 +1057,8 @@
bower_archive(
name = "iron-dropdown",
package = "polymerelements/iron-dropdown",
- sha1 = "63e3d669a09edaa31c4f05afc76b53b919ef0595",
- version = "1.4.0",
+ sha1 = "ac96fe31cdf203a63426fa75131b43c98c0597d3",
+ version = "1.5.5",
)
bower_archive(
@@ -1069,15 +1071,15 @@
bower_archive(
name = "iron-overlay-behavior",
package = "polymerelements/iron-overlay-behavior",
- sha1 = "83181085fda59446ce74fd0d5ca30c223f38ee4a",
- version = "1.7.6",
+ sha1 = "74cda9d7bf98e7a5e5004bc7ebdb6d208d49e11e",
+ version = "2.0.0",
)
bower_archive(
name = "iron-selector",
package = "polymerelements/iron-selector",
- sha1 = "c57235dfda7fbb987c20ad0e97aac70babf1a1bf",
- version = "1.5.2",
+ sha1 = "e0ee46c28523bf17730318c3b481a8ed4331c3b2",
+ version = "2.0.0",
)
bower_archive(
@@ -1095,6 +1097,20 @@
)
bower_archive(
+ name = "paper-item",
+ package = "polymerelements/paper-item",
+ sha1 = "803273ceb9ffebec8ecc9373ea638af4cd34af58",
+ version = "1.1.4",
+)
+
+bower_archive(
+ name = "paper-listbox",
+ package = "polymerelements/paper-listbox",
+ sha1 = "ccc1a90ab0a96878c7bf7c9c4cfe47c85b09c8e3",
+ version = "2.0.0",
+)
+
+bower_archive(
name = "polymer",
package = "polymer/polymer",
sha1 = "566b5fe9a2a3eea2cf3417c67d975a6752d131eb",
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 4943b7e..1af8f7d 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -1067,7 +1067,8 @@
protected void grant(Project.NameKey project, String ref, String permission, boolean force)
throws RepositoryNotFoundException, IOException, ConfigInvalidException {
- AccountGroup adminGroup = groupCache.get(new AccountGroup.NameKey("Administrators"));
+ InternalGroup adminGroup =
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);
grant(project, ref, permission, force, adminGroup.getGroupUUID());
}
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AccountCreator.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AccountCreator.java
index faa674e..a8f7767 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AccountCreator.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AccountCreator.java
@@ -24,11 +24,12 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.account.AccountsUpdate;
+import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.VersionedAuthorizedKeys;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIdsUpdate;
-import com.google.gerrit.server.group.Groups;
import com.google.gerrit.server.group.GroupsUpdate;
+import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.ServerInitiated;
import com.google.gerrit.server.ssh.SshKeyCache;
import com.google.gwtorm.server.SchemaFactory;
@@ -54,7 +55,7 @@
private final Sequences sequences;
private final AccountsUpdate.Server accountsUpdate;
private final VersionedAuthorizedKeys.Accessor authorizedKeys;
- private final Groups groups;
+ private final GroupCache groupCache;
private final Provider<GroupsUpdate> groupsUpdateProvider;
private final SshKeyCache sshKeyCache;
private final ExternalIdsUpdate.Server externalIdsUpdate;
@@ -66,7 +67,7 @@
Sequences sequences,
AccountsUpdate.Server accountsUpdate,
VersionedAuthorizedKeys.Accessor authorizedKeys,
- Groups groups,
+ GroupCache groupCache,
@ServerInitiated Provider<GroupsUpdate> groupsUpdateProvider,
SshKeyCache sshKeyCache,
ExternalIdsUpdate.Server externalIdsUpdate,
@@ -76,7 +77,7 @@
this.sequences = sequences;
this.accountsUpdate = accountsUpdate;
this.authorizedKeys = authorizedKeys;
- this.groups = groups;
+ this.groupCache = groupCache;
this.groupsUpdateProvider = groupsUpdateProvider;
this.sshKeyCache = sshKeyCache;
this.externalIdsUpdate = externalIdsUpdate;
@@ -121,7 +122,7 @@
if (groupNames != null) {
for (String n : groupNames) {
AccountGroup.NameKey k = new AccountGroup.NameKey(n);
- Optional<AccountGroup> group = groups.getGroup(db, k);
+ Optional<InternalGroup> group = groupCache.get(k);
if (!group.isPresent()) {
throw new NoSuchGroupException(n);
}
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 8ac063b..84f3533 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
@@ -91,6 +91,7 @@
import com.google.gerrit.server.account.externalids.ExternalIdsUpdate;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.ProjectConfig;
+import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.rebuild.ChangeRebuilderImpl;
import com.google.gerrit.server.project.RefPattern;
@@ -1014,7 +1015,8 @@
String userRef = RefNames.refsUsers(foo.id);
accountIndexedCounter.clear();
- AccountGroup adminGroup = groupCache.get(new AccountGroup.NameKey("Administrators"));
+ InternalGroup adminGroup =
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);
grant(allUsers, userRef, Permission.PUSH, false, adminGroup.getGroupUUID());
grantLabel("Code-Review", -2, 2, allUsers, userRef, false, adminGroup.getGroupUUID(), false);
grant(allUsers, userRef, Permission.SUBMIT, false, adminGroup.getGroupUUID());
@@ -1179,7 +1181,8 @@
accountsUpdate.create().update(foo.id, a -> a.setPreferredEmail(noEmail));
accountIndexedCounter.clear();
- AccountGroup adminGroup = groupCache.get(new AccountGroup.NameKey("Administrators"));
+ InternalGroup adminGroup =
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);
grant(allUsers, userRef, Permission.PUSH, false, adminGroup.getGroupUUID());
TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
@@ -1214,7 +1217,8 @@
String userRef = RefNames.refsUsers(foo.id);
accountIndexedCounter.clear();
- AccountGroup adminGroup = groupCache.get(new AccountGroup.NameKey("Administrators"));
+ InternalGroup adminGroup =
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);
grant(allUsers, userRef, Permission.PUSH, false, adminGroup.getGroupUUID());
TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
@@ -1273,7 +1277,8 @@
String userRef = RefNames.refsUsers(foo.id);
accountIndexedCounter.clear();
- AccountGroup adminGroup = groupCache.get(new AccountGroup.NameKey("Administrators"));
+ InternalGroup adminGroup =
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);
grant(allUsers, userRef, Permission.PUSH, false, adminGroup.getGroupUUID());
TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
index d399e2b..a8a712c 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -1225,7 +1225,7 @@
Util.allow(
cfg,
Permission.READ,
- groupCache.get(new AccountGroup.NameKey("Administrators")).getGroupUUID(),
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null).getGroupUUID(),
"refs/*");
Util.block(cfg, Permission.READ, REGISTERED_USERS, "refs/*");
saveProjectConfig(p, cfg);
@@ -1302,7 +1302,7 @@
Util.allow(
cfg,
Permission.READ,
- groupCache.get(new AccountGroup.NameKey("Administrators")).getGroupUUID(),
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null).getGroupUUID(),
"refs/*");
Util.block(cfg, Permission.READ, REGISTERED_USERS, "refs/*");
saveProjectConfig(p, cfg);
@@ -1349,7 +1349,7 @@
Util.allow(
cfg,
Permission.READ,
- groupCache.get(new AccountGroup.NameKey("Administrators")).getGroupUUID(),
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null).getGroupUUID(),
"refs/*");
Util.block(cfg, Permission.READ, REGISTERED_USERS, "refs/*");
saveProjectConfig(p, cfg);
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupAssert.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupAssert.java
index ccdd03b..dd891ce 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupAssert.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupAssert.java
@@ -19,7 +19,7 @@
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.Url;
-import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.server.group.InternalGroup;
import java.util.Set;
public class GroupAssert {
@@ -31,7 +31,7 @@
assertWithMessage("unexpected groups: " + actual).that(actual).isEmpty();
}
- public static void assertGroupInfo(AccountGroup group, GroupInfo info) {
+ public static void assertGroupInfo(InternalGroup group, GroupInfo info) {
if (info.name != null) {
// 'name' is not set if returned in a map
assertThat(info.name).isEqualTo(group.getName());
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 1b5e544a..eb4df15 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -47,6 +47,7 @@
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.group.GroupsUpdate;
+import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.ServerInitiated;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.inject.Inject;
@@ -257,13 +258,13 @@
@Test
public void getGroup() throws Exception {
- AccountGroup adminGroup = groupCache.get(new AccountGroup.NameKey("Administrators"));
+ InternalGroup adminGroup = getFromCache("Administrators");
testGetGroup(adminGroup.getGroupUUID().get(), adminGroup);
testGetGroup(adminGroup.getName(), adminGroup);
testGetGroup(adminGroup.getId().get(), adminGroup);
}
- private void testGetGroup(Object id, AccountGroup expectedGroup) throws Exception {
+ private void testGetGroup(Object id, InternalGroup expectedGroup) throws Exception {
GroupInfo group = gApi.groups().id(id.toString()).get();
assertGroupInfo(expectedGroup, group);
}
@@ -559,7 +560,7 @@
@Test
public void allGroupInfoFieldsSetCorrectly() throws Exception {
- AccountGroup adminGroup = getFromCache("Administrators");
+ InternalGroup adminGroup = getFromCache("Administrators");
Map<String, GroupInfo> groups = gApi.groups().list().addGroup(adminGroup.getName()).getAsMap();
assertThat(groups).hasSize(1);
assertThat(groups).containsKey("Administrators");
@@ -683,8 +684,8 @@
assertThat(gApi.groups().id(group).includedGroups()).isEmpty();
}
- private AccountGroup getFromCache(String name) throws Exception {
- return groupCache.get(new AccountGroup.NameKey(name));
+ private InternalGroup getFromCache(String name) throws Exception {
+ return groupCache.get(new AccountGroup.NameKey(name)).orElse(null);
}
private void setCreatedOnToNull(AccountGroup.UUID groupUuid) throws Exception {
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/project/CheckAccessIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/project/CheckAccessIT.java
index b471efc..2f92e7a 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/project/CheckAccessIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/project/CheckAccessIT.java
@@ -28,6 +28,7 @@
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.SystemGroupBackend;
import java.util.List;
import org.junit.Before;
@@ -39,14 +40,15 @@
private Project.NameKey secretProject;
private Project.NameKey secretRefProject;
private TestAccount privilegedUser;
- private AccountGroup privilegedGroup;
+ private InternalGroup privilegedGroup;
@Before
public void setUp() throws Exception {
normalProject = createProject("normal");
secretProject = createProject("secret");
secretRefProject = createProject("secretRef");
- privilegedGroup = groupCache.get(new AccountGroup.NameKey(createGroup("privilegedGroup")));
+ privilegedGroup =
+ groupCache.get(new AccountGroup.NameKey(createGroup("privilegedGroup"))).orElse(null);
privilegedUser = accountCreator.create("privilegedUser", "snowden@nsa.gov", "Ed Snowden");
gApi.groups().id(privilegedGroup.getGroupUUID().get()).addMembers(privilegedUser.username);
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
index 84c2901..4dac61f 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
@@ -82,7 +82,7 @@
@Before
public void setUp() throws Exception {
- admins = groupCache.get(new AccountGroup.NameKey("Administrators")).getGroupUUID();
+ admins = groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null).getGroupUUID();
setUpPermissions();
setUpChanges();
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/config/FlushCacheIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/config/FlushCacheIT.java
index 41f7d4a..b586ab2 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/config/FlushCacheIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/config/FlushCacheIT.java
@@ -23,13 +23,14 @@
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.config.ListCaches.CacheInfo;
+import com.google.gerrit.server.group.InternalGroup;
import org.junit.Test;
public class FlushCacheIT extends AbstractDaemonTest {
@Test
public void flushCache() throws Exception {
- AccountGroup group = groupCache.get(new AccountGroup.NameKey("Administrators"));
+ InternalGroup group = groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);
assertWithMessage("Precondition: The group 'Administrators' was loaded by the group cache")
.that(group)
.isNotNull();
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AccessIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AccessIT.java
index b6ac5e9..f67012a 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AccessIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AccessIT.java
@@ -41,6 +41,7 @@
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.AllProjectsNameProvider;
+import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.SystemGroupBackend;
import java.util.HashMap;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
@@ -53,12 +54,12 @@
public class AccessIT extends AbstractDaemonTest {
- private final String PROJECT_NAME = "newProject";
+ private static final String PROJECT_NAME = "newProject";
- private final String REFS_ALL = Constants.R_REFS + "*";
- private final String REFS_HEADS = Constants.R_HEADS + "*";
+ private static final String REFS_ALL = Constants.R_REFS + "*";
+ private static final String REFS_HEADS = Constants.R_HEADS + "*";
- private final String LABEL_CODE_REVIEW = "Code-Review";
+ private static final String LABEL_CODE_REVIEW = "Code-Review";
private String newProjectName;
private ProjectApi pApi;
@@ -394,7 +395,8 @@
@Test
public void addNonGlobalCapabilityToGlobalCapabilities() throws Exception {
- AccountGroup adminGroup = groupCache.get(new AccountGroup.NameKey("Administrators"));
+ InternalGroup adminGroup =
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);
ProjectAccessInput accessInput = newProjectAccessInput();
AccessSectionInfo accessSectionInfo = newAccessSectionInfo();
@@ -423,7 +425,8 @@
@Test
public void removeGlobalCapabilityAsAdmin() throws Exception {
- AccountGroup adminGroup = groupCache.get(new AccountGroup.NameKey("Administrators"));
+ InternalGroup adminGroup =
+ groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);
ProjectAccessInput accessInput = newProjectAccessInput();
AccessSectionInfo accessSectionInfo = newAccessSectionInfo();
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
index 7640328..0409fbc 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
@@ -191,7 +191,11 @@
in.owners.add(SystemGroupBackend.REGISTERED_USERS.get()); // by UUID
in.owners.add(
Integer.toString(
- groupCache.get(new AccountGroup.NameKey("Administrators")).getId().get())); // by ID
+ groupCache
+ .get(new AccountGroup.NameKey("Administrators"))
+ .orElse(null)
+ .getId()
+ .get())); // by ID
gApi.projects().create(in);
ProjectState projectState = projectCache.get(new Project.NameKey(newProjectName));
Set<AccountGroup.UUID> expectedOwnerIds = Sets.newHashSetWithExpectedSize(3);
@@ -293,7 +297,7 @@
}
private AccountGroup.UUID groupUuid(String groupName) {
- return groupCache.get(new AccountGroup.NameKey(groupName)).getGroupUUID();
+ return groupCache.get(new AccountGroup.NameKey(groupName)).orElse(null).getGroupUUID();
}
private void assertHead(String projectName, String expectedRef) throws Exception {
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/QueryIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/QueryIT.java
index ce0787f..ca45e7c 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/QueryIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/QueryIT.java
@@ -26,6 +26,7 @@
import com.google.gerrit.acceptance.UseSsh;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.server.data.ChangeAttribute;
import com.google.gson.Gson;
@@ -310,6 +311,19 @@
userSession.close();
}
+ @Test
+ public void allChangeOptionsAreServedWithoutExceptions() throws Exception {
+ PushOneCommit.Result r = createChange();
+ // Merge the change so that the result has more data and potentially went through more
+ // computation while formatting the output, such as labels, reviewers etc.
+ merge(r);
+ for (ListChangesOption option : ListChangesOption.values()) {
+ assertThat(gApi.changes().query(r.getChangeId()).withOption(option).get())
+ .named("Option: " + option)
+ .hasSize(1);
+ }
+ }
+
private List<ChangeAttribute> executeSuccessfulQuery(String params, SshSession session)
throws Exception {
String rawResponse = session.exec("gerrit query --format=JSON " + params);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
index 1484809..0465902 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
@@ -46,6 +46,7 @@
private final Account.Id ownerId;
private final boolean mine;
private ChangeTable table;
+ private ChangeTable.Section workInProgress;
private ChangeTable.Section outgoing;
private ChangeTable.Section incoming;
private ChangeTable.Section closed;
@@ -72,11 +73,15 @@
};
table.addStyleName(Gerrit.RESOURCES.css().accountDashboard());
+ workInProgress = new ChangeTable.Section();
outgoing = new ChangeTable.Section();
incoming = new ChangeTable.Section();
closed = new ChangeTable.Section();
String who = mine ? "self" : ownerId.toString();
+ workInProgress.setTitleWidget(
+ new InlineHyperlink(
+ Util.C.workInProgress(), PageLinks.toChangeQuery(queryWorkInProgress(who))));
outgoing.setTitleWidget(
new InlineHyperlink(Util.C.outgoingReviews(), PageLinks.toChangeQuery(queryOutgoing(who))));
incoming.setTitleWidget(
@@ -85,6 +90,7 @@
closed.setTitleWidget(
new InlineHyperlink(Util.C.recentlyClosed(), PageLinks.toChangeQuery(queryClosed(who))));
+ table.addSection(workInProgress);
table.addSection(outgoing);
table.addSection(incoming);
table.addSection(closed);
@@ -92,8 +98,12 @@
table.setSavePointerId("owner:" + ownerId);
}
+ private static String queryWorkInProgress(String who) {
+ return "is:open is:wip owner:" + who;
+ }
+
private static String queryOutgoing(String who) {
- return "is:open owner:" + who;
+ return "is:open -is:wip owner:" + who;
}
private static String queryIncoming(String who) {
@@ -123,6 +133,7 @@
}
},
mine ? MY_DASHBOARD_OPTIONS : DashboardTable.OPTIONS,
+ queryWorkInProgress(who),
queryOutgoing(who),
queryIncoming(who),
queryClosed(who) + " -age:4w limit:10");
@@ -142,9 +153,10 @@
return;
}
- ChangeList out = result.get(0);
- ChangeList in = result.get(1);
- ChangeList done = result.get(2);
+ ChangeList wip = result.get(0);
+ ChangeList out = result.get(1);
+ ChangeList in = result.get(2);
+ ChangeList done = result.get(3);
if (mine) {
setWindowTitle(Util.C.myDashboardTitle());
@@ -167,7 +179,8 @@
Collections.sort(Natives.asList(out), outComparator());
- table.updateColumnsForLabels(out, in, done);
+ table.updateColumnsForLabels(wip, out, in, done);
+ workInProgress.display(wip);
outgoing.display(out);
incoming.display(in);
closed.display(done);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
index 402179c..aa6c4ec 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
@@ -43,6 +43,8 @@
String unknownDashboardTitle();
+ String workInProgress();
+
String incomingReviews();
String outgoingReviews();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
index dd11a60..9860cb2 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
@@ -12,6 +12,7 @@
myDashboardTitle = My Reviews
unknownDashboardTitle = Code Review Dashboard
+workInProgress Work in progress
incomingReviews = Incoming reviews
outgoingReviews = Outgoing reviews
recentlyClosed = Recently closed
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/MigrateToNoteDb.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/MigrateToNoteDb.java
index 5fbd411..dda8d14 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/MigrateToNoteDb.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/MigrateToNoteDb.java
@@ -20,8 +20,11 @@
import static java.util.stream.Collectors.toList;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.elasticsearch.ElasticIndexModule;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.lifecycle.LifecycleManager;
+import com.google.gerrit.lucene.LuceneIndexModule;
import com.google.gerrit.pgm.util.BatchProgramModule;
import com.google.gerrit.pgm.util.RuntimeShutdown;
import com.google.gerrit.pgm.util.SiteProgram;
@@ -30,10 +33,11 @@
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.index.DummyIndexModule;
+import com.google.gerrit.server.index.IndexModule;
import com.google.gerrit.server.notedb.rebuild.NoteDbMigrator;
import com.google.inject.Inject;
import com.google.inject.Injector;
+import com.google.inject.Module;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.List;
@@ -160,12 +164,23 @@
public void configure() {
install(dbInjector.getInstance(BatchProgramModule.class));
bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED);
- install(new DummyIndexModule());
+ install(getIndexModule());
factory(ChangeResource.Factory.class);
}
});
}
+ private Module getIndexModule() {
+ switch (IndexModule.getIndexType(dbInjector)) {
+ case LUCENE:
+ return LuceneIndexModule.singleVersionWithExplicitVersions(ImmutableMap.of(), threads);
+ case ELASTICSEARCH:
+ return ElasticIndexModule.singleVersionWithExplicitVersions(ImmutableMap.of(), threads);
+ default:
+ throw new IllegalStateException("unsupported index.type");
+ }
+ }
+
private void stop() {
try {
LifecycleManager m = sysManager;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
index 4c6f670..2427ea2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
@@ -20,6 +20,7 @@
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Streams;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
@@ -33,8 +34,13 @@
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.group.Groups;
+import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.index.account.AccountIndexer;
+import com.google.gerrit.server.index.group.GroupField;
+import com.google.gerrit.server.index.group.GroupIndex;
+import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.query.account.InternalAccountQuery;
+import com.google.gerrit.server.query.group.InternalGroupQuery;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
@@ -46,10 +52,10 @@
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
+import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -155,8 +161,9 @@
private final SchemaFactory<ReviewDb> schema;
private final AllUsersName allUsersName;
private final Accounts accounts;
+ private final Provider<GroupIndex> groupIndexProvider;
+ private final Provider<InternalGroupQuery> groupQueryProvider;
private final GroupCache groupCache;
- private final Groups groups;
private final GeneralPreferencesLoader loader;
private final Provider<WatchConfig.Accessor> watchConfig;
private final ExternalIds externalIds;
@@ -166,16 +173,18 @@
SchemaFactory<ReviewDb> sf,
AllUsersName allUsersName,
Accounts accounts,
+ GroupIndexCollection groupIndexCollection,
+ Provider<InternalGroupQuery> groupQueryProvider,
GroupCache groupCache,
- Groups groups,
GeneralPreferencesLoader loader,
Provider<WatchConfig.Accessor> watchConfig,
ExternalIds externalIds) {
this.schema = sf;
this.allUsersName = allUsersName;
this.accounts = accounts;
+ this.groupIndexProvider = groupIndexCollection::getSearchIndex;
+ this.groupQueryProvider = groupQueryProvider;
this.groupCache = groupCache;
- this.groups = groups;
this.loader = loader;
this.watchConfig = watchConfig;
this.externalIds = externalIds;
@@ -195,13 +204,7 @@
return Optional.empty();
}
- Set<AccountGroup.UUID> internalGroups =
- groups
- .getGroupsWithMember(db, who)
- .map(groupCache::get)
- .map(AccountGroup::getGroupUUID)
- .filter(Objects::nonNull)
- .collect(toImmutableSet());
+ Set<AccountGroup.UUID> internalGroups = getGroupsWithMember(db, who);
try {
account.setGeneralPreferences(loader.load(who));
@@ -218,6 +221,21 @@
externalIds.byAccount(who),
watchConfig.get().getProjectWatches(who)));
}
+
+ private ImmutableSet<AccountGroup.UUID> getGroupsWithMember(ReviewDb db, Account.Id memberId)
+ throws OrmException {
+ Stream<InternalGroup> internalGroupStream;
+ if (groupIndexProvider.get().getSchema().hasField(GroupField.MEMBER)) {
+ internalGroupStream = groupQueryProvider.get().byMember(memberId).stream();
+ } else {
+ internalGroupStream =
+ Groups.getGroupsWithMemberFromReviewDb(db, memberId)
+ .map(groupCache::get)
+ .flatMap(Streams::stream);
+ }
+
+ return internalGroupStream.map(InternalGroup::getGroupUUID).collect(toImmutableSet());
+ }
}
static class ByNameLoader extends CacheLoader<String, Optional<Account.Id>> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
index cafdaed..ec756bc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
@@ -32,7 +32,6 @@
import com.google.gerrit.server.account.externalids.ExternalIdsUpdate;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.group.GroupsUpdate;
-import com.google.gerrit.server.group.ServerInitiated;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.account.InternalAccountQuery;
import com.google.gwtorm.server.OrmException;
@@ -70,7 +69,7 @@
private final Provider<InternalAccountQuery> accountQueryProvider;
private final ExternalIds externalIds;
private final ExternalIdsUpdate.Server externalIdsUpdateFactory;
- private final Provider<GroupsUpdate> groupsUpdateProvider;
+ private final GroupsUpdate.Factory groupsUpdateFactory;
@Inject
AccountManager(
@@ -87,7 +86,7 @@
Provider<InternalAccountQuery> accountQueryProvider,
ExternalIds externalIds,
ExternalIdsUpdate.Server externalIdsUpdateFactory,
- @ServerInitiated Provider<GroupsUpdate> groupsUpdateProvider) {
+ GroupsUpdate.Factory groupsUpdateFactory) {
this.schema = schema;
this.sequences = sequences;
this.accounts = accounts;
@@ -102,7 +101,7 @@
this.accountQueryProvider = accountQueryProvider;
this.externalIds = externalIds;
this.externalIdsUpdateFactory = externalIdsUpdateFactory;
- this.groupsUpdateProvider = groupsUpdateProvider;
+ this.groupsUpdateFactory = groupsUpdateFactory;
}
/** @return user identified by this external identity string */
@@ -253,9 +252,8 @@
.getPermission(GlobalCapability.ADMINISTRATE_SERVER);
AccountGroup.UUID uuid = admin.getRules().get(0).getGroup().getUUID();
- GroupsUpdate groupsUpdate = groupsUpdateProvider.get();
// The user initiated this request by logging in. -> Attribute all modifications to that user.
- groupsUpdate.setCurrentUser(user);
+ GroupsUpdate groupsUpdate = groupsUpdateFactory.create(user);
try {
groupsUpdate.addGroupMember(db, uuid, newId);
} catch (NoSuchGroupException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCache.java
index 82f1559..82bcce3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCache.java
@@ -22,9 +22,23 @@
/** Tracks group objects in memory for efficient access. */
public interface GroupCache {
- AccountGroup get(AccountGroup.Id groupId);
+ /**
+ * Looks up an internal group by its ID.
+ *
+ * @param groupId the ID of the internal group
+ * @return an {@code Optional} of the internal group, or an empty {@code Optional} if no internal
+ * group with this ID exists on this server or an error occurred during lookup
+ */
+ Optional<InternalGroup> get(AccountGroup.Id groupId);
- AccountGroup get(AccountGroup.NameKey name);
+ /**
+ * Looks up an internal group by its name.
+ *
+ * @param name the name of the internal group
+ * @return an {@code Optional} of the internal group, or an empty {@code Optional} if no internal
+ * group with this name exists on this server or an error occurred during lookup
+ */
+ Optional<InternalGroup> get(AccountGroup.NameKey name);
/**
* Looks up an internal group by its UUID.
@@ -39,11 +53,10 @@
ImmutableList<AccountGroup> all();
/** Notify the cache that a new group was constructed. */
- void onCreateGroup(AccountGroup.NameKey newGroupName) throws IOException;
+ void onCreateGroup(AccountGroup group) throws IOException;
void evict(AccountGroup.UUID groupUuid, AccountGroup.Id groupId, AccountGroup.NameKey groupName)
throws IOException;
- void evictAfterRename(AccountGroup.NameKey oldName, AccountGroup.NameKey newName)
- throws IOException;
+ void evictAfterRename(AccountGroup.NameKey oldName) throws IOException;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCacheImpl.java
index 2901501..edbc2d8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCacheImpl.java
@@ -15,20 +15,17 @@
package com.google.gerrit.server.account;
import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.google.common.collect.ImmutableSet.toImmutableSet;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.gerrit.common.TimeUtil;
-import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.group.Groups;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.index.group.GroupIndexer;
+import com.google.gerrit.server.query.group.InternalGroupQuery;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
@@ -56,10 +53,10 @@
return new CacheModule() {
@Override
protected void configure() {
- cache(BYID_NAME, AccountGroup.Id.class, new TypeLiteral<Optional<AccountGroup>>() {})
+ cache(BYID_NAME, AccountGroup.Id.class, new TypeLiteral<Optional<InternalGroup>>() {})
.loader(ByIdLoader.class);
- cache(BYNAME_NAME, String.class, new TypeLiteral<Optional<AccountGroup>>() {})
+ cache(BYNAME_NAME, String.class, new TypeLiteral<Optional<InternalGroup>>() {})
.loader(ByNameLoader.class);
cache(BYUUID_NAME, String.class, new TypeLiteral<Optional<InternalGroup>>() {})
@@ -71,8 +68,8 @@
};
}
- private final LoadingCache<AccountGroup.Id, Optional<AccountGroup>> byId;
- private final LoadingCache<String, Optional<AccountGroup>> byName;
+ private final LoadingCache<AccountGroup.Id, Optional<InternalGroup>> byId;
+ private final LoadingCache<String, Optional<InternalGroup>> byName;
private final LoadingCache<String, Optional<InternalGroup>> byUUID;
private final SchemaFactory<ReviewDb> schema;
private final Provider<GroupIndexer> indexer;
@@ -80,8 +77,8 @@
@Inject
GroupCacheImpl(
- @Named(BYID_NAME) LoadingCache<AccountGroup.Id, Optional<AccountGroup>> byId,
- @Named(BYNAME_NAME) LoadingCache<String, Optional<AccountGroup>> byName,
+ @Named(BYID_NAME) LoadingCache<AccountGroup.Id, Optional<InternalGroup>> byId,
+ @Named(BYNAME_NAME) LoadingCache<String, Optional<InternalGroup>> byName,
@Named(BYUUID_NAME) LoadingCache<String, Optional<InternalGroup>> byUUID,
SchemaFactory<ReviewDb> schema,
Provider<GroupIndexer> indexer,
@@ -95,13 +92,12 @@
}
@Override
- public AccountGroup get(AccountGroup.Id groupId) {
+ public Optional<InternalGroup> get(AccountGroup.Id groupId) {
try {
- Optional<AccountGroup> g = byId.get(groupId);
- return g.isPresent() ? g.get() : missing(groupId);
+ return byId.get(groupId);
} catch (ExecutionException e) {
log.warn("Cannot load group " + groupId, e);
- return missing(groupId);
+ return Optional.empty();
}
}
@@ -122,27 +118,22 @@
}
@Override
- public void evictAfterRename(final AccountGroup.NameKey oldName, AccountGroup.NameKey newName)
- throws IOException {
+ public void evictAfterRename(AccountGroup.NameKey oldName) throws IOException {
if (oldName != null) {
byName.invalidate(oldName.get());
}
- if (newName != null) {
- byName.invalidate(newName.get());
- }
- indexer.get().index(get(newName).getGroupUUID());
}
@Override
- public AccountGroup get(AccountGroup.NameKey name) {
+ public Optional<InternalGroup> get(AccountGroup.NameKey name) {
if (name == null) {
- return null;
+ return Optional.empty();
}
try {
- return byName.get(name.get()).orElse(null);
+ return byName.get(name.get());
} catch (ExecutionException e) {
log.warn(String.format("Cannot look up group %s by name", name.get()), e);
- return null;
+ return Optional.empty();
}
}
@@ -171,49 +162,35 @@
}
@Override
- public void onCreateGroup(AccountGroup.NameKey newGroupName) throws IOException {
- byName.invalidate(newGroupName.get());
- indexer.get().index(get(newGroupName).getGroupUUID());
+ public void onCreateGroup(AccountGroup group) throws IOException {
+ indexer.get().index(group.getGroupUUID());
}
- private static AccountGroup missing(AccountGroup.Id key) {
- AccountGroup.NameKey name = new AccountGroup.NameKey("Deleted Group" + key);
- return new AccountGroup(name, key, null, TimeUtil.nowTs());
- }
-
- static class ByIdLoader extends CacheLoader<AccountGroup.Id, Optional<AccountGroup>> {
- private final SchemaFactory<ReviewDb> schema;
- private final Groups groups;
+ static class ByIdLoader extends CacheLoader<AccountGroup.Id, Optional<InternalGroup>> {
+ private final Provider<InternalGroupQuery> groupQueryProvider;
@Inject
- ByIdLoader(SchemaFactory<ReviewDb> sf, Groups groups) {
- schema = sf;
- this.groups = groups;
+ ByIdLoader(Provider<InternalGroupQuery> groupQueryProvider) {
+ this.groupQueryProvider = groupQueryProvider;
}
@Override
- public Optional<AccountGroup> load(AccountGroup.Id key) throws Exception {
- try (ReviewDb db = schema.open()) {
- return groups.getGroup(db, key);
- }
+ public Optional<InternalGroup> load(AccountGroup.Id key) throws Exception {
+ return groupQueryProvider.get().byId(key);
}
}
- static class ByNameLoader extends CacheLoader<String, Optional<AccountGroup>> {
- private final SchemaFactory<ReviewDb> schema;
- private final Groups groups;
+ static class ByNameLoader extends CacheLoader<String, Optional<InternalGroup>> {
+ private final Provider<InternalGroupQuery> groupQueryProvider;
@Inject
- ByNameLoader(SchemaFactory<ReviewDb> sf, Groups groups) {
- schema = sf;
- this.groups = groups;
+ ByNameLoader(Provider<InternalGroupQuery> groupQueryProvider) {
+ this.groupQueryProvider = groupQueryProvider;
}
@Override
- public Optional<AccountGroup> load(String name) throws Exception {
- try (ReviewDb db = schema.open()) {
- return groups.getGroup(db, new AccountGroup.NameKey(name));
- }
+ public Optional<InternalGroup> load(String name) throws Exception {
+ return groupQueryProvider.get().byName(new AccountGroup.NameKey(name));
}
}
@@ -230,18 +207,7 @@
@Override
public Optional<InternalGroup> load(String uuid) throws Exception {
try (ReviewDb db = schema.open()) {
- AccountGroup.UUID groupUuid = new AccountGroup.UUID(uuid);
- Optional<AccountGroup> accountGroup = groups.getGroup(db, groupUuid);
-
- if (!accountGroup.isPresent()) {
- return Optional.empty();
- }
-
- ImmutableSet<Account.Id> members =
- groups.getMembers(db, groupUuid).collect(toImmutableSet());
- ImmutableSet<AccountGroup.UUID> subgroups =
- groups.getSubgroups(db, groupUuid).collect(toImmutableSet());
- return accountGroup.map(group -> InternalGroup.create(group, members, subgroups));
+ return groups.getGroup(db, new AccountGroup.UUID(uuid));
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java
index 5af4898..020a04d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java
@@ -21,12 +21,15 @@
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.group.InternalGroup;
+import com.google.gerrit.server.group.InternalGroupDescription;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
+import java.util.Optional;
/** Access control management for a group of accounts managed in Gerrit. */
public class GroupControl {
@@ -71,11 +74,11 @@
}
public GroupControl controlFor(AccountGroup.Id groupId) throws NoSuchGroupException {
- final AccountGroup group = groupCache.get(groupId);
- if (group == null) {
- throw new NoSuchGroupException(groupId);
- }
- return controlFor(GroupDescriptions.forAccountGroup(group));
+ Optional<InternalGroup> group = groupCache.get(groupId);
+ return group
+ .map(InternalGroupDescription::new)
+ .map(this::controlFor)
+ .orElseThrow(() -> new NoSuchGroupException(groupId));
}
public GroupControl controlFor(AccountGroup.UUID groupId) throws NoSuchGroupException {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
index 10c002c..8d63fb7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
@@ -19,22 +19,29 @@
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Streams;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.group.Groups;
+import com.google.gerrit.server.group.InternalGroup;
+import com.google.gerrit.server.index.group.GroupField;
+import com.google.gerrit.server.index.group.GroupIndex;
+import com.google.gerrit.server.index.group.GroupIndexCollection;
+import com.google.gerrit.server.query.group.InternalGroupQuery;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Module;
+import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import java.util.Collection;
import java.util.Collections;
-import java.util.Objects;
import java.util.concurrent.ExecutionException;
+import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -158,26 +165,36 @@
static class ParentGroupsLoader
extends CacheLoader<AccountGroup.UUID, ImmutableList<AccountGroup.UUID>> {
private final SchemaFactory<ReviewDb> schema;
+ private final Provider<GroupIndex> groupIndexProvider;
+ private final Provider<InternalGroupQuery> groupQueryProvider;
private final GroupCache groupCache;
- private final Groups groups;
@Inject
- ParentGroupsLoader(SchemaFactory<ReviewDb> sf, GroupCache groupCache, Groups groups) {
+ ParentGroupsLoader(
+ SchemaFactory<ReviewDb> sf,
+ GroupIndexCollection groupIndexCollection,
+ Provider<InternalGroupQuery> groupQueryProvider,
+ GroupCache groupCache) {
schema = sf;
+ this.groupIndexProvider = groupIndexCollection::getSearchIndex;
+ this.groupQueryProvider = groupQueryProvider;
this.groupCache = groupCache;
- this.groups = groups;
}
@Override
public ImmutableList<AccountGroup.UUID> load(AccountGroup.UUID key) throws OrmException {
- try (ReviewDb db = schema.open()) {
- return groups
- .getParentGroups(db, key)
- .map(groupCache::get)
- .map(AccountGroup::getGroupUUID)
- .filter(Objects::nonNull)
- .collect(toImmutableList());
+ Stream<InternalGroup> internalGroupStream;
+ if (groupIndexProvider.get().getSchema().hasField(GroupField.SUBGROUP)) {
+ internalGroupStream = groupQueryProvider.get().bySubgroup(key).stream();
+ } else {
+ try (ReviewDb db = schema.open()) {
+ internalGroupStream =
+ Groups.getParentGroupsFromReviewDb(db, key)
+ .map(groupCache::get)
+ .flatMap(Streams::stream);
+ }
}
+ return internalGroupStream.map(InternalGroup::getGroupUUID).collect(toImmutableList());
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/args4j/AccountGroupIdHandler.java b/gerrit-server/src/main/java/com/google/gerrit/server/args4j/AccountGroupIdHandler.java
index d41f02c..f3393c1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/args4j/AccountGroupIdHandler.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/args4j/AccountGroupIdHandler.java
@@ -16,8 +16,10 @@
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.GroupCache;
+import com.google.gerrit.server.group.InternalGroup;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
+import java.util.Optional;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.OptionDef;
@@ -41,11 +43,11 @@
@Override
public final int parseArguments(Parameters params) throws CmdLineException {
final String n = params.getParameter(0);
- final AccountGroup group = groupCache.get(new AccountGroup.NameKey(n));
- if (group == null) {
+ Optional<InternalGroup> group = groupCache.get(new AccountGroup.NameKey(n));
+ if (!group.isPresent()) {
throw new CmdLineException(owner, "Group \"" + n + "\" does not exist");
}
- setter.addValue(group.getId());
+ setter.addValue(group.get().getId());
return 1;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
index 63f8138..59a48fe 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
@@ -416,6 +416,12 @@
| RuntimeException e) {
if (has(CHECK)) {
i = checkOnly(cd);
+ } else if (e instanceof NoSuchChangeException) {
+ log.info(
+ "NoSuchChangeException: Omitting corrupt change "
+ + cd.getId()
+ + " from results. Seems to be stale in the index.");
+ continue;
} else {
log.warn("Omitting corrupt change " + cd.getId() + " from results", e);
continue;
@@ -1074,7 +1080,7 @@
for (PatchSetApproval psa :
approvalsUtil.byPatchSetUser(
db.get(),
- cd.notes(),
+ lazyLoad ? cd.notes() : notesFactory.createFromIndexedChange(cd.change()),
user,
cd.change().currentPatchSetId(),
user.getAccountId(),
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeSuperSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeSuperSet.java
index 227367e..32dc7bc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeSuperSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeSuperSet.java
@@ -242,7 +242,6 @@
// completeChangeSet computation, for example.
visible = false;
}
- Collection<RevCommit> toWalk = visible ? visibleCommits : nonVisibleCommits;
// Pick a revision to use for traversal. If any of the patch sets
// is visible, we use the most recent one. Otherwise, use the current
@@ -276,16 +275,16 @@
// Always include the input, even if merged. This allows
// SubmitStrategyOp to correct the situation later, assuming it gets
// returned by byCommitsOnBranchNotMerged below.
- toWalk.add(commit);
+ if (visible) {
+ visibleCommits.add(commit);
+ } else {
+ nonVisibleCommits.add(commit);
+ }
}
- Set<String> emptySet = Collections.emptySet();
- Set<String> visibleHashes = walkChangesByHashes(visibleCommits, emptySet, or, b);
-
- List<ChangeData> cds = byCommitsOnBranchNotMerged(or, db, b, visibleHashes);
- for (ChangeData chd : cds) {
- visibleChanges.add(chd);
- }
+ Set<String> visibleHashes =
+ walkChangesByHashes(visibleCommits, Collections.emptySet(), or, b);
+ Iterables.addAll(visibleChanges, byCommitsOnBranchNotMerged(or, db, b, visibleHashes));
Set<String> nonVisibleHashes = walkChangesByHashes(nonVisibleCommits, visibleHashes, or, b);
Iterables.addAll(nonVisibleChanges, byCommitsOnBranchNotMerged(or, db, b, nonVisibleHashes));
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/CreateGroup.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/CreateGroup.java
index a1aefc5..e55397e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/CreateGroup.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/CreateGroup.java
@@ -56,6 +56,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
@@ -198,10 +199,8 @@
new AccountGroup(createGroupArgs.getGroup(), groupId, uuid, TimeUtil.nowTs());
group.setVisibleToAll(createGroupArgs.visibleToAll);
if (createGroupArgs.ownerGroupId != null) {
- AccountGroup ownerGroup = groupCache.get(createGroupArgs.ownerGroupId);
- if (ownerGroup != null) {
- group.setOwnerGroupUUID(ownerGroup.getGroupUUID());
- }
+ Optional<InternalGroup> ownerGroup = groupCache.get(createGroupArgs.ownerGroupId);
+ ownerGroup.map(InternalGroup::getGroupUUID).ifPresent(group::setOwnerGroupUUID);
}
if (createGroupArgs.groupDescription != null) {
group.setDescription(createGroupArgs.groupDescription);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/DbGroupMemberAuditListener.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/DbGroupMemberAuditListener.java
index ce287d0..5af7ebd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/DbGroupMemberAuditListener.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/DbGroupMemberAuditListener.java
@@ -152,7 +152,7 @@
Account.Id accountId = m.getAccountId();
String userName = accountCache.get(accountId).getUserName();
AccountGroup.Id groupId = m.getAccountGroupId();
- String groupName = groupCache.get(groupId).getName();
+ String groupName = getGroupName(groupId);
descriptions.add(
MessageFormat.format(
@@ -168,7 +168,7 @@
AccountGroup.UUID groupUuid = m.getIncludeUUID();
String groupName = groupBackend.get(groupUuid).getName();
AccountGroup.Id targetGroupId = m.getGroupId();
- String targetGroupName = groupCache.get(targetGroupId).getName();
+ String targetGroupName = getGroupName(targetGroupId);
descriptions.add(
MessageFormat.format(
@@ -178,6 +178,10 @@
logOrmException(header, me, descriptions, e);
}
+ private String getGroupName(AccountGroup.Id groupId) {
+ return groupCache.get(groupId).map(InternalGroup::getName).orElse("Deleted group " + groupId);
+ }
+
private void logOrmException(String header, Account.Id me, Iterable<?> values, OrmException e) {
StringBuilder message = new StringBuilder(header);
message.append(" ");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/Groups.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/Groups.java
index b835d22..a2660f2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/Groups.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/Groups.java
@@ -14,6 +14,9 @@
package com.google.gerrit.server.group;
+import static com.google.common.collect.ImmutableSet.toImmutableSet;
+
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.gerrit.common.errors.NoSuchGroupException;
@@ -21,7 +24,6 @@
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupById;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
-import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
@@ -45,6 +47,29 @@
public class Groups {
/**
+ * Returns the {@code InternalGroup} for the specified UUID if it exists.
+ *
+ * @param db the {@code ReviewDb} instance to use for lookups
+ * @param groupUuid the UUID of the group
+ * @return the found {@code InternalGroup} if it exists, or else an empty {@code Optional}
+ * @throws OrmDuplicateKeyException if multiple groups are found for the specified UUID
+ * @throws OrmException if the group couldn't be retrieved from ReviewDb
+ */
+ public Optional<InternalGroup> getGroup(ReviewDb db, AccountGroup.UUID groupUuid)
+ throws OrmException, NoSuchGroupException {
+ Optional<AccountGroup> accountGroup = getGroupFromReviewDb(db, groupUuid);
+
+ if (!accountGroup.isPresent()) {
+ return Optional.empty();
+ }
+
+ ImmutableSet<Account.Id> members = getMembers(db, groupUuid).collect(toImmutableSet());
+ ImmutableSet<AccountGroup.UUID> subgroups =
+ getSubgroups(db, groupUuid).collect(toImmutableSet());
+ return accountGroup.map(group -> InternalGroup.create(group, members, subgroups));
+ }
+
+ /**
* Returns the {@code AccountGroup} for the specified UUID.
*
* @param db the {@code ReviewDb} instance to use for lookups
@@ -54,25 +79,13 @@
* @throws OrmException if the group couldn't be retrieved from ReviewDb
* @throws NoSuchGroupException if a group with such a UUID doesn't exist
*/
- public AccountGroup getExistingGroup(ReviewDb db, AccountGroup.UUID groupUuid)
+ static AccountGroup getExistingGroupFromReviewDb(ReviewDb db, AccountGroup.UUID groupUuid)
throws OrmException, NoSuchGroupException {
- Optional<AccountGroup> group = getGroup(db, groupUuid);
+ Optional<AccountGroup> group = getGroupFromReviewDb(db, groupUuid);
return group.orElseThrow(() -> new NoSuchGroupException(groupUuid));
}
/**
- * Returns the {@code AccountGroup} for the specified ID if it exists.
- *
- * @param db the {@code ReviewDb} instance to use for lookups
- * @param groupId the ID of the group
- * @return the found {@code AccountGroup} if it exists, or else an empty {@code Optional}
- * @throws OrmException if the group couldn't be retrieved from ReviewDb
- */
- public Optional<AccountGroup> getGroup(ReviewDb db, AccountGroup.Id groupId) throws OrmException {
- return Optional.ofNullable(db.accountGroups().get(groupId));
- }
-
- /**
* Returns the {@code AccountGroup} for the specified UUID if it exists.
*
* @param db the {@code ReviewDb} instance to use for lookups
@@ -81,8 +94,8 @@
* @throws OrmDuplicateKeyException if multiple groups are found for the specified UUID
* @throws OrmException if the group couldn't be retrieved from ReviewDb
*/
- public Optional<AccountGroup> getGroup(ReviewDb db, AccountGroup.UUID groupUuid)
- throws OrmException {
+ private static Optional<AccountGroup> getGroupFromReviewDb(
+ ReviewDb db, AccountGroup.UUID groupUuid) throws OrmException {
List<AccountGroup> accountGroups = db.accountGroups().byUUID(groupUuid).toList();
if (accountGroups.size() == 1) {
return Optional.of(Iterables.getOnlyElement(accountGroups));
@@ -93,25 +106,6 @@
}
}
- /**
- * Returns the {@code AccountGroup} for the specified name if it exists.
- *
- * @param db the {@code ReviewDb} instance to use for lookups
- * @param groupName the name of the group
- * @return the found {@code AccountGroup} if it exists, or else an empty {@code Optional}
- * @throws OrmException if the group couldn't be retrieved from ReviewDb
- */
- public Optional<AccountGroup> getGroup(ReviewDb db, AccountGroup.NameKey groupName)
- throws OrmException {
- AccountGroupName accountGroupName = db.accountGroupNames().get(groupName);
- if (accountGroupName == null) {
- return Optional.empty();
- }
-
- AccountGroup.Id groupId = accountGroupName.getId();
- return Optional.ofNullable(db.accountGroups().get(groupId));
- }
-
public Stream<AccountGroup> getAll(ReviewDb db) throws OrmException {
return Streams.stream(db.accountGroups().all());
}
@@ -130,7 +124,7 @@
*/
public boolean isMember(ReviewDb db, AccountGroup.UUID groupUuid, Account.Id accountId)
throws OrmException, NoSuchGroupException {
- AccountGroup group = getExistingGroup(db, groupUuid);
+ AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid);
AccountGroupMember.Key key = new AccountGroupMember.Key(accountId, group.getId());
return db.accountGroupMembers().get(key) != null;
}
@@ -153,7 +147,7 @@
public boolean isSubgroup(
ReviewDb db, AccountGroup.UUID parentGroupUuid, AccountGroup.UUID subgroupUuid)
throws OrmException, NoSuchGroupException {
- AccountGroup parentGroup = getExistingGroup(db, parentGroupUuid);
+ AccountGroup parentGroup = getExistingGroupFromReviewDb(db, parentGroupUuid);
AccountGroupById.Key key = new AccountGroupById.Key(parentGroup.getId(), subgroupUuid);
return db.accountGroupById().get(key) != null;
}
@@ -171,7 +165,7 @@
*/
public Stream<Account.Id> getMembers(ReviewDb db, AccountGroup.UUID groupUuid)
throws OrmException, NoSuchGroupException {
- AccountGroup group = getExistingGroup(db, groupUuid);
+ AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid);
ResultSet<AccountGroupMember> accountGroupMembers =
db.accountGroupMembers().byGroup(group.getId());
return Streams.stream(accountGroupMembers).map(AccountGroupMember::getAccountId);
@@ -193,7 +187,7 @@
*/
public Stream<AccountGroup.UUID> getSubgroups(ReviewDb db, AccountGroup.UUID groupUuid)
throws OrmException, NoSuchGroupException {
- AccountGroup group = getExistingGroup(db, groupUuid);
+ AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid);
ResultSet<AccountGroupById> accountGroupByIds = db.accountGroupById().byGroup(group.getId());
return Streams.stream(accountGroupByIds).map(AccountGroupById::getIncludeUUID).distinct();
}
@@ -209,8 +203,8 @@
* @return a stream of the IDs of the groups of which the account is a member
* @throws OrmException if an error occurs while reading from ReviewDb
*/
- public Stream<AccountGroup.Id> getGroupsWithMember(ReviewDb db, Account.Id accountId)
- throws OrmException {
+ public static Stream<AccountGroup.Id> getGroupsWithMemberFromReviewDb(
+ ReviewDb db, Account.Id accountId) throws OrmException {
ResultSet<AccountGroupMember> accountGroupMembers =
db.accountGroupMembers().byAccount(accountId);
return Streams.stream(accountGroupMembers).map(AccountGroupMember::getAccountGroupId);
@@ -230,8 +224,8 @@
* @return a stream of the IDs of the parent groups
* @throws OrmException if an error occurs while reading from ReviewDb
*/
- public Stream<AccountGroup.Id> getParentGroups(ReviewDb db, AccountGroup.UUID subgroupUuid)
- throws OrmException {
+ public static Stream<AccountGroup.Id> getParentGroupsFromReviewDb(
+ ReviewDb db, AccountGroup.UUID subgroupUuid) throws OrmException {
ResultSet<AccountGroupById> accountGroupByIds =
db.accountGroupById().byIncludeUUID(subgroupUuid);
return Streams.stream(accountGroupByIds).map(AccountGroupById::getGroupId);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java
index d688e4c..736eeec 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/GroupsUpdate.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.group;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
+import static com.google.gerrit.server.group.Groups.getExistingGroupFromReviewDb;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
@@ -58,6 +59,17 @@
*/
public class GroupsUpdate {
public interface Factory {
+ /**
+ * Creates a {@code GroupsUpdate} which uses the identity of the specified user to mark database
+ * modifications executed by it. For NoteDb, this identity is used as author and committer for
+ * all related commits.
+ *
+ * <p><strong>Note</strong>: Please use this method with care and rather consider to use the
+ * correct annotation on the provider of a {@code GroupsUpdate} instead.
+ *
+ * @param currentUser the user to which modifications should be attributed, or {@code null} if
+ * the Gerrit server identity should be used
+ */
GroupsUpdate create(@Nullable IdentifiedUser currentUser);
}
@@ -67,10 +79,8 @@
private final AuditService auditService;
private final AccountCache accountCache;
private final RenameGroupOp.Factory renameGroupOpFactory;
- private final PersonIdent serverIdent;
-
- @Nullable private IdentifiedUser currentUser;
- private PersonIdent committerIdent;
+ @Nullable private final IdentifiedUser currentUser;
+ private final PersonIdent committerIdent;
@Inject
GroupsUpdate(
@@ -88,33 +98,13 @@
this.auditService = auditService;
this.accountCache = accountCache;
this.renameGroupOpFactory = renameGroupOpFactory;
- this.serverIdent = serverIdent;
-
- setCurrentUser(currentUser);
- }
-
- /**
- * Uses the identity of the specified user to mark database modifications executed by this {@code
- * GroupsUpdate}. For NoteDb, this identity is used as author and committer for all related
- * commits.
- *
- * <p><strong>Note</strong>: Please use this method with care and rather consider to use the
- * correct annotation on the provider of this class instead.
- *
- * @param currentUser the user to which modifications should be attributed, or {@code null} if the
- * Gerrit server identity should be used
- */
- public void setCurrentUser(@Nullable IdentifiedUser currentUser) {
this.currentUser = currentUser;
- setCommitterIdent(currentUser);
+ committerIdent = getCommitterIdent(serverIdent, currentUser);
}
- private void setCommitterIdent(@Nullable IdentifiedUser currentUser) {
- if (currentUser != null) {
- committerIdent = createPersonIdent(serverIdent, currentUser);
- } else {
- committerIdent = serverIdent;
- }
+ private static PersonIdent getCommitterIdent(
+ PersonIdent serverIdent, @Nullable IdentifiedUser currentUser) {
+ return currentUser != null ? createPersonIdent(serverIdent, currentUser) : serverIdent;
}
private static PersonIdent createPersonIdent(PersonIdent ident, IdentifiedUser user) {
@@ -135,7 +125,7 @@
throws OrmException, IOException {
addNewGroup(db, group);
addNewGroupMembers(db, group, memberIds);
- groupCache.onCreateGroup(group.getNameKey());
+ groupCache.onCreateGroup(group);
}
/**
@@ -177,7 +167,7 @@
public AccountGroup updateGroupInDb(
ReviewDb db, AccountGroup.UUID groupUuid, Consumer<AccountGroup> groupConsumer)
throws OrmException, NoSuchGroupException {
- AccountGroup group = groups.getExistingGroup(db, groupUuid);
+ AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid);
groupConsumer.accept(group);
db.accountGroups().update(ImmutableList.of(group));
return group;
@@ -196,7 +186,7 @@
*/
public void renameGroup(ReviewDb db, AccountGroup.UUID groupUuid, AccountGroup.NameKey newName)
throws OrmException, IOException, NameAlreadyUsedException, NoSuchGroupException {
- AccountGroup group = groups.getExistingGroup(db, groupUuid);
+ AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid);
AccountGroup.NameKey oldName = group.getNameKey();
try {
@@ -221,8 +211,8 @@
db.accountGroupNames().deleteKeys(ImmutableList.of(oldName));
+ groupCache.evictAfterRename(oldName);
groupCache.evict(group.getGroupUUID(), group.getId(), group.getNameKey());
- groupCache.evictAfterRename(oldName, newName);
@SuppressWarnings("unused")
Future<?> possiblyIgnoredError =
@@ -264,7 +254,7 @@
*/
public void addGroupMembers(ReviewDb db, AccountGroup.UUID groupUuid, Set<Account.Id> accountIds)
throws OrmException, IOException, NoSuchGroupException {
- AccountGroup group = groups.getExistingGroup(db, groupUuid);
+ AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid);
Set<Account.Id> newMemberIds = new HashSet<>();
for (Account.Id accountId : accountIds) {
boolean isMember = groups.isMember(db, groupUuid, accountId);
@@ -313,7 +303,7 @@
public void removeGroupMembers(
ReviewDb db, AccountGroup.UUID groupUuid, Set<Account.Id> accountIds)
throws OrmException, IOException, NoSuchGroupException {
- AccountGroup group = groups.getExistingGroup(db, groupUuid);
+ AccountGroup group = getExistingGroupFromReviewDb(db, groupUuid);
AccountGroup.Id groupId = group.getId();
Set<AccountGroupMember> membersToRemove = new HashSet<>();
for (Account.Id accountId : accountIds) {
@@ -357,7 +347,7 @@
public void addSubgroups(
ReviewDb db, AccountGroup.UUID parentGroupUuid, Set<AccountGroup.UUID> subgroupUuids)
throws OrmException, NoSuchGroupException, IOException {
- AccountGroup parentGroup = groups.getExistingGroup(db, parentGroupUuid);
+ AccountGroup parentGroup = getExistingGroupFromReviewDb(db, parentGroupUuid);
AccountGroup.Id parentGroupId = parentGroup.getId();
Set<AccountGroupById> newSubgroups = new HashSet<>();
for (AccountGroup.UUID includedGroupUuid : subgroupUuids) {
@@ -400,7 +390,7 @@
public void removeSubgroups(
ReviewDb db, AccountGroup.UUID parentGroupUuid, Set<AccountGroup.UUID> subgroupUuids)
throws OrmException, NoSuchGroupException, IOException {
- AccountGroup parentGroup = groups.getExistingGroup(db, parentGroupUuid);
+ AccountGroup parentGroup = getExistingGroupFromReviewDb(db, parentGroupUuid);
AccountGroup.Id parentGroupId = parentGroup.getId();
Set<AccountGroupById> subgroupsToRemove = new HashSet<>();
for (AccountGroup.UUID subgroupUuid : subgroupUuids) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/InternalGroup.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/InternalGroup.java
index 228d86f..fafc591 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/InternalGroup.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/InternalGroup.java
@@ -19,10 +19,12 @@
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
+import java.io.Serializable;
import java.sql.Timestamp;
@AutoValue
-public abstract class InternalGroup {
+public abstract class InternalGroup implements Serializable {
+ private static final long serialVersionUID = 1L;
public static InternalGroup create(
AccountGroup accountGroup,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/receive/HtmlParser.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/receive/HtmlParser.java
index 64539d1..14cb09a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/receive/HtmlParser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/receive/HtmlParser.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.mail.receive;
import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
import com.google.gerrit.reviewdb.client.Comment;
@@ -28,6 +29,12 @@
/** Provides functionality for parsing the HTML part of a {@link MailMessage}. */
public class HtmlParser {
+ private static final ImmutableList<String> MAIL_PROVIDER_EXTRAS =
+ ImmutableList.of(
+ "gmail_extra", // "On 01/01/2017 User<user@gmail.com> wrote:"
+ "gmail_quote" // Used for quoting original content
+ );
+
private HtmlParser() {}
/**
@@ -96,7 +103,7 @@
}
} else if (!isInBlockQuote
&& elementName.equals("div")
- && !e.className().startsWith("gmail")) {
+ && !MAIL_PROVIDER_EXTRAS.contains(e.className())) {
// This is a comment typed by the user
// Replace non-breaking spaces and trim string
String content = e.ownText().replace('\u00a0', ' ').trim();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java
index 30cc3d3..73e82a1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java
@@ -71,12 +71,6 @@
return new PatchListKey(otherCommitId, newId, whitespace, Algorithm.OPTIMIZED_DIFF);
}
- // Please keep this method for the moment even though it is unused.
- public static PatchListKey againstCommitWithPureTreeDiff(
- AnyObjectId otherCommitId, AnyObjectId newId, Whitespace whitespace) {
- return new PatchListKey(otherCommitId, newId, whitespace, Algorithm.PURE_TREE_DIFF);
- }
-
/**
* Old patch-set ID
*
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/group/GroupPredicates.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/group/GroupPredicates.java
index 983d3b3..d02f6a4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/group/GroupPredicates.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/group/GroupPredicates.java
@@ -24,6 +24,10 @@
import java.util.Locale;
public class GroupPredicates {
+ public static Predicate<InternalGroup> id(AccountGroup.Id groupId) {
+ return new GroupPredicate(GroupField.ID, groupId.toString());
+ }
+
public static Predicate<InternalGroup> uuid(AccountGroup.UUID uuid) {
return new GroupPredicate(GroupField.UUID, GroupQueryBuilder.FIELD_UUID, uuid.get());
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/group/InternalGroupQuery.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/group/InternalGroupQuery.java
new file mode 100644
index 0000000..7a3a905
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/group/InternalGroupQuery.java
@@ -0,0 +1,82 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.query.group;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.gerrit.index.IndexConfig;
+import com.google.gerrit.index.query.InternalQuery;
+import com.google.gerrit.index.query.Predicate;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.server.group.InternalGroup;
+import com.google.gerrit.server.index.group.GroupIndexCollection;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import java.util.List;
+import java.util.Optional;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Query wrapper for the group index.
+ *
+ * <p>Instances are one-time-use. Other singleton classes should inject a Provider rather than
+ * holding on to a single instance.
+ */
+public class InternalGroupQuery extends InternalQuery<InternalGroup> {
+ private static final Logger log = LoggerFactory.getLogger(InternalGroupQuery.class);
+
+ @Inject
+ InternalGroupQuery(
+ GroupQueryProcessor queryProcessor, GroupIndexCollection indexes, IndexConfig indexConfig) {
+ super(queryProcessor, indexes, indexConfig);
+ }
+
+ public Optional<InternalGroup> byName(AccountGroup.NameKey groupName) throws OrmException {
+ return getOnlyGroup(GroupPredicates.name(groupName.get()), "group name '" + groupName + "'");
+ }
+
+ public Optional<InternalGroup> byId(AccountGroup.Id groupId) throws OrmException {
+ return getOnlyGroup(GroupPredicates.id(groupId), "group id '" + groupId + "'");
+ }
+
+ public List<InternalGroup> byMember(Account.Id memberId) throws OrmException {
+ return query(GroupPredicates.member(memberId));
+ }
+
+ public List<InternalGroup> bySubgroup(AccountGroup.UUID subgroupId) throws OrmException {
+ return query(GroupPredicates.subgroup(subgroupId));
+ }
+
+ private Optional<InternalGroup> getOnlyGroup(
+ Predicate<InternalGroup> predicate, String groupDescription) throws OrmException {
+ List<InternalGroup> groups = query(predicate);
+ if (groups.isEmpty()) {
+ return Optional.empty();
+ }
+
+ if (groups.size() == 1) {
+ return Optional.of(Iterables.getOnlyElement(groups));
+ }
+
+ ImmutableList<AccountGroup.UUID> groupUuids =
+ groups.stream().map(InternalGroup::getGroupUUID).collect(toImmutableList());
+ log.warn(String.format("Ambiguous %s for groups %s.", groupDescription, groupUuids));
+ return Optional.empty();
+ }
+}
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/mail/receive/GmailHtmlParserTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/mail/receive/GmailHtmlParserTest.java
index c0e8050..e210847 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/mail/receive/GmailHtmlParserTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/mail/receive/GmailHtmlParserTest.java
@@ -20,7 +20,7 @@
String changeMessage, String c1, String c2, String c3, String f1, String f2, String fc1) {
String email =
""
- + "<div dir=\"ltr\">"
+ + "<div class=\"gmail_default\" dir=\"ltr\">"
+ (changeMessage != null ? changeMessage : "")
+ "<div class=\"gmail_extra\"><br><div class=\"gmail_quote\">"
+ "On Fri, Nov 18, 2016 at 11:15 AM, foobar (Gerrit) noreply@gerrit.com"
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/project/CommitsCollectionTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/project/CommitsCollectionTest.java
index 0d8080f..7f1b233 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/project/CommitsCollectionTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/project/CommitsCollectionTest.java
@@ -90,7 +90,7 @@
// registered user.
// See AccountManager#create().
accountManager.authenticate(AuthRequest.forUser("admin")).getAccountId();
- admins = groupCache.get(new AccountGroup.NameKey("Administrators")).getGroupUUID();
+ admins = groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null).getGroupUUID();
setUpPermissions();
Account.Id userId = accountManager.authenticate(AuthRequest.forUser("user")).getAccountId();
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListMembersCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListMembersCommand.java
index 1c903c7..ffaf923 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListMembersCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListMembersCommand.java
@@ -23,6 +23,7 @@
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupControl;
+import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.ListMembers;
import com.google.gerrit.server.ioutil.ColumnFormatter;
import com.google.gerrit.sshd.CommandMetaData;
@@ -31,6 +32,7 @@
import com.google.inject.Inject;
import java.io.PrintWriter;
import java.util.List;
+import java.util.Optional;
import org.kohsuke.args4j.Argument;
/** Implements a command that allows the user to see the members of a group. */
@@ -68,16 +70,16 @@
}
void display(PrintWriter writer) throws OrmException {
- AccountGroup group = groupCache.get(new AccountGroup.NameKey(name));
+ Optional<InternalGroup> group = groupCache.get(new AccountGroup.NameKey(name));
String errorText = "Group not found or not visible\n";
- if (group == null) {
+ if (!group.isPresent()) {
writer.write(errorText);
writer.flush();
return;
}
- List<AccountInfo> members = apply(group.getGroupUUID());
+ List<AccountInfo> members = apply(group.get().getGroupUUID());
ColumnFormatter formatter = new ColumnFormatter(writer, '\t');
formatter.addColumn("id");
formatter.addColumn("username");
diff --git a/lib/js/bower_archives.bzl b/lib/js/bower_archives.bzl
index 3ac2351..7657994 100644
--- a/lib/js/bower_archives.bzl
+++ b/lib/js/bower_archives.bzl
@@ -23,6 +23,11 @@
version = "3.5.0",
sha1 = "849ad3ee7c77506548b7b5db603a4e150b9431aa")
bower_archive(
+ name = "font-roboto",
+ package = "PolymerElements/font-roboto",
+ version = "1.0.3",
+ sha1 = "edf478d20ae2fc0704d7c155e20162caaabdd5ae")
+ bower_archive(
name = "iron-a11y-announcer",
package = "PolymerElements/iron-a11y-announcer",
version = "1.0.6",
@@ -45,8 +50,13 @@
bower_archive(
name = "iron-flex-layout",
package = "PolymerElements/iron-flex-layout",
- version = "2.0.0",
- sha1 = "feae42cc5d2d948a50074f430cfb8ab28cb6dc9e")
+ version = "1.3.7",
+ sha1 = "4d4cf3232cf750a17a7df0a37476117f831ac633")
+ bower_archive(
+ name = "iron-menu-behavior",
+ package = "PolymerElements/iron-menu-behavior",
+ version = "2.0.1",
+ sha1 = "139528ee1e8d86257e2aa445de7761b8ec70ae91")
bower_archive(
name = "iron-meta",
package = "PolymerElements/iron-meta",
@@ -54,7 +64,7 @@
sha1 = "f77eba3f6f6817f10bda33918bde8f963d450041")
bower_archive(
name = "iron-resizable-behavior",
- package = "PolymerElements/iron-resizable-behavior",
+ package = "polymerelements/iron-resizable-behavior",
version = "1.0.6",
sha1 = "719c2a8a1a784f8aefcdeef41fcc2e5a03518d9e")
bower_archive(
@@ -70,14 +80,19 @@
bower_archive(
name = "mocha",
package = "mocha",
- version = "3.5.0",
- sha1 = "09aa92f4f89949ed5f501a57f082e96510b18318")
+ version = "3.5.3",
+ sha1 = "c14f149821e4e96241b20f85134aa757b73038f1")
bower_archive(
name = "neon-animation",
package = "polymerelements/neon-animation",
version = "1.2.5",
sha1 = "588d289f779d02b21ce5b676e257bbd6155649e8")
bower_archive(
+ name = "paper-styles",
+ package = "PolymerElements/paper-styles",
+ version = "1.3.1",
+ sha1 = "4ee9c692366949a754e0e39f8031aa60ce66f24d")
+ bower_archive(
name = "sinon-chai",
package = "sinon-chai",
version = "2.13.0",
diff --git a/lib/js/bower_components.bzl b/lib/js/bower_components.bzl
index e36a759..906d6e3 100644
--- a/lib/js/bower_components.bzl
+++ b/lib/js/bower_components.bzl
@@ -30,6 +30,10 @@
seed = True,
)
bower_component(
+ name = "font-roboto",
+ license = "//lib:LICENSE-polymer",
+ )
+ bower_component(
name = "iron-a11y-announcer",
license = "//lib:LICENSE-polymer",
deps = [ ":polymer" ],
@@ -62,7 +66,6 @@
name = "iron-dropdown",
license = "//lib:LICENSE-polymer",
deps = [
- ":iron-a11y-keys-behavior",
":iron-behaviors",
":iron-overlay-behavior",
":iron-resizable-behavior",
@@ -92,6 +95,16 @@
seed = True,
)
bower_component(
+ name = "iron-menu-behavior",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-a11y-keys-behavior",
+ ":iron-flex-layout",
+ ":iron-selector",
+ ":polymer",
+ ],
+ )
+ bower_component(
name = "iron-meta",
license = "//lib:LICENSE-polymer",
deps = [ ":polymer" ],
@@ -162,6 +175,37 @@
seed = True,
)
bower_component(
+ name = "paper-item",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-behaviors",
+ ":iron-flex-layout",
+ ":paper-styles",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "paper-listbox",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-behaviors",
+ ":iron-menu-behavior",
+ ":paper-styles",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "paper-styles",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":font-roboto",
+ ":iron-flex-layout",
+ ":polymer",
+ ],
+ )
+ bower_component(
name = "polymer-resin",
license = "//lib:LICENSE-polymer",
deps = [
diff --git a/plugins/hooks b/plugins/hooks
index 18f8c78..a96c0b9 160000
--- a/plugins/hooks
+++ b/plugins/hooks
@@ -1 +1 @@
-Subproject commit 18f8c78aad50509d39b489286b64d869752cccd6
+Subproject commit a96c0b937e412a44b00a7574fe0f7c5f010aabf5
diff --git a/polygerrit-ui/BUILD b/polygerrit-ui/BUILD
index 31ab6aa..3e490eb 100644
--- a/polygerrit-ui/BUILD
+++ b/polygerrit-ui/BUILD
@@ -20,6 +20,8 @@
"//lib/js:iron-selector",
"//lib/js:moment",
"//lib/js:page",
+ "//lib/js:paper-item",
+ "//lib/js:paper-listbox",
"//lib/js:polymer",
"//lib/js:polymer-resin",
"//lib/js:promise-polyfill",
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
index 24673ff..161dfe7 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
@@ -266,7 +266,7 @@
<section>
<gr-button
primary
- disabled="[[_computeSendButtonDisabled(knownLatestState, _sendButtonLabel, diffDrafts, draft, _reviewersMutated, _labelsChanged)]]"
+ disabled="[[_computeSendButtonDisabled(knownLatestState, _sendButtonLabel, diffDrafts, draft, _reviewersMutated, _labelsChanged, _includeComments)]]"
class="action send"
on-tap="_sendTapHandler">[[_sendButtonLabel]]</gr-button>
<template is="dom-if" if="[[canBeStarted]]">
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
index 9f4a79a..5168e8f 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
@@ -810,15 +810,15 @@
},
_computeSendButtonDisabled(knownLatestState, buttonLabel, drafts, text,
- reviewersMutated, labelsChanged) {
+ reviewersMutated, labelsChanged, includeComments) {
if (this._isState(knownLatestState, LatestPatchState.NOT_LATEST)) {
return true;
}
if (buttonLabel === ButtonLabels.START_REVIEW) {
return false;
}
- return !(drafts.length || text.length || reviewersMutated ||
- labelsChanged);
+ const hasDrafts = includeComments && Object.keys(drafts).length;
+ return !hasDrafts && !text.length && !reviewersMutated && !labelsChanged;
},
});
})();
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
index 9a83259..278f2c6 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
@@ -1014,15 +1014,19 @@
const fn = element._computeSendButtonDisabled.bind(element);
assert.isTrue(fn('not-latest'));
assert.isFalse(fn('latest', 'Start review'));
- assert.isTrue(fn('latest', 'Send', [], '', false, false));
- // Mock nonempty comment draft array.
- assert.isFalse(fn('latest', 'Send', ['test'], '', false, false));
+ assert.isTrue(fn('latest', 'Send', {}, '', false, false, false));
+ // Mock nonempty comment draft array, with seding comments.
+ assert.isFalse(fn('latest', 'Send', {file: ['draft']}, '', false, false,
+ true));
+ // Mock nonempty comment draft array, without seding comments.
+ assert.isTrue(fn('latest', 'Send', {file: ['draft']}, '', false, false,
+ false));
// Mock nonempty change message.
- assert.isFalse(fn('latest', 'Send', [], 'test', false, false));
+ assert.isFalse(fn('latest', 'Send', {}, 'test', false, false, false));
// Mock reviewers mutated.
- assert.isFalse(fn('latest', 'Send', [], '', true, false));
+ assert.isFalse(fn('latest', 'Send', {}, '', true, false, false));
// Mock labels changed.
- assert.isFalse(fn('latest', 'Send', [], '', false, true));
+ assert.isFalse(fn('latest', 'Send', {}, '', false, true, false));
});
});
</script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
index 72f557e..c29d494 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
@@ -58,8 +58,10 @@
suite('gr-diff-builder tests', () => {
let element;
let builder;
+ let sandbox;
setup(() => {
+ sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn() { return Promise.resolve(false); },
getProjectConfig() { return Promise.resolve({}); },
@@ -74,6 +76,8 @@
{content: []}, {left: [], right: []}, prefs, projectName);
});
+ teardown(() => { sandbox.restore(); });
+
test('context control buttons', () => {
const section = {};
const line = {contextGroup: {lines: []}};
@@ -141,11 +145,10 @@
const text = (new Array(52)).join('a');
const line = {text, highlights: []};
- const newLineStub = sinon.stub(builder, '_addNewlines');
+ const newLineStub = sandbox.stub(builder, '_addNewlines');
builder._createTextEl(line);
flush(() => {
assert.isFalse(newLineStub.called);
- newLineStub.restore();
done();
});
});
@@ -156,12 +159,11 @@
const text = (new Array(52)).join('a');
const line = {text, highlights: []};
- const newLineStub = sinon.stub(builder, '_addNewlines');
+ const newLineStub = sandbox.stub(builder, '_addNewlines');
builder._createTextEl(line);
flush(() => {
assert.isTrue(newLineStub.called);
- newLineStub.restore();
done();
});
});
@@ -358,15 +360,11 @@
setup(() => {
el = fixture('div-with-text');
str = el.textContent;
- annotateElementSpy = sinon.spy(GrAnnotation, 'annotateElement');
+ annotateElementSpy = sandbox.spy(GrAnnotation, 'annotateElement');
layer = document.createElement('gr-diff-builder')
._createIntralineLayer();
});
- teardown(() => {
- annotateElementSpy.restore();
- });
-
test('annotate no highlights', () => {
const line = {
text: str,
@@ -513,21 +511,15 @@
});
suite('tab indicators', () => {
- let sandbox;
let element;
let layer;
setup(() => {
- sandbox = sinon.sandbox.create();
element = fixture('basic');
element._showTabs = true;
layer = element._createTabIndicatorLayer();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('does nothing with empty line', () => {
const line = {text: ''};
const el = document.createElement('div');
@@ -630,21 +622,15 @@
});
suite('trailing whitespace', () => {
- let sandbox;
let element;
let layer;
setup(() => {
- sandbox = sinon.sandbox.create();
element = fixture('basic');
element._showTrailingWhitespace = true;
layer = element._createTrailingWhitespaceLayer();
});
- teardown(() => {
- sandbox.restore();
- });
-
test('does nothing with empty line', () => {
const line = {text: ''};
const el = document.createElement('div');
@@ -733,10 +719,8 @@
suite('rendering', () => {
let content;
let outputEl;
- let sandbox;
setup(done => {
- sandbox = sinon.sandbox.create();
const prefs = {
line_length: 10,
show_tabs: true,
@@ -779,10 +763,6 @@
element.render({left: [], right: []}, prefs).then(done);
});
- teardown(() => {
- sandbox.restore();
- });
-
test('reporting', done => {
const timeStub = element.$.reporting.time;
const timeEndStub = element.$.reporting.timeEnd;
@@ -828,7 +808,7 @@
});
test('render-start and render are fired', done => {
- const dispatchEventStub = sinon.stub(element, 'dispatchEvent');
+ const dispatchEventStub = sandbox.stub(element, 'dispatchEvent');
element.render({left: [], right: []}, {}).then(() => {
const firedEventTypes = dispatchEventStub.getCalls()
.map(c => { return c.args[0].type; });
@@ -929,7 +909,7 @@
});
test('_renderContentByRange', () => {
- const spy = sinon.spy(builder, '_createTextEl');
+ const spy = sandbox.spy(builder, '_createTextEl');
const start = 9;
const end = 14;
const count = end - start + 1;
@@ -940,8 +920,6 @@
spy.getCalls().forEach((call, i) => {
assert.equal(call.args[0].beforeNumber, start + i);
});
-
- spy.restore();
});
test('_getNextContentOnSide side-by-side left', () => {
diff --git a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.html b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.html
index ab91fc5..21552d9 100644
--- a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.html
+++ b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.html
@@ -20,6 +20,7 @@
<link rel="import" href="../../../styles/shared-styles.html">
<script src="../../../bower_components/moment/moment.js"></script>
+<script src="../../../scripts/util.js"></script>
<dom-module id="gr-date-formatter">
<template>
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.html b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.html
new file mode 100644
index 0000000..59f63fa
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.html
@@ -0,0 +1,174 @@
+<!--
+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="../../../bower_components/polymer/polymer.html">
+
+<link rel="import" href="../../../bower_components/iron-dropdown/iron-dropdown.html">
+<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
+<link rel="import" href="../../../bower_components/paper-listbox/paper-listbox.html">
+
+<link rel="import" href="../../../styles/shared-styles.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-select/gr-select.html">
+
+
+<dom-module id="gr-dropdown-list">
+ <template>
+ <style include="shared-styles">
+ :host {
+ display: inline-block;
+ }
+ #trigger {
+ -moz-user-select: text;
+ -ms-user-select: text;
+ -webkit-user-select: text;
+ user-select: text;
+ }
+ .downArrow {
+ display: inline-block;
+ font-size: .6em;
+ user-select: none;
+ vertical-align: middle;
+ }
+ .dropdown-trigger {
+ cursor: pointer;
+ padding: 0;
+ }
+ .dropdown-content {
+ background-color: #fff;
+ box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
+ max-height: 70vh;
+ margin-top: 1.5em;
+ width: 266px;
+ }
+ paper-listbox {
+ --paper-listbox: {
+ padding: 0;
+ }
+ }
+ paper-item {
+ cursor: pointer;
+ flex-direction: column;
+ --paper-item: {
+ min-height: 0;
+ padding: 10px 16px;
+ }
+ --paper-item-selected: {
+ background-color: rgba(161,194,250,.12);
+ }
+ --paper-item-focused-before: {
+ background-color: #f2f2f2;
+ }
+ --paper-item-focused: {
+ background-color: #f2f2f2;
+ }
+ }
+ paper-item:not(:last-of-type) {
+ border-bottom: 1px solid #ddd;
+ }
+ gr-button {
+ color: black;
+ font: inherit;
+ padding: .3em 0;
+ text-decoration: none;
+ }
+ .bottomContent {
+ color: rgba(0,0,0,.54);
+ font-size: .85em;
+ line-height: 16px;
+ }
+ .bottomContent,
+ .topContent {
+ display: flex;
+ line-height: 16px;
+ justify-content: space-between;
+ flex-direction: row;
+ width: 100%;
+ }
+ gr-date-formatter {
+ color: rgba(0,0,0,.54);
+ margin-left: 2em;
+ }
+ gr-select {
+ display: none;
+ }
+ @media only screen and (max-width: 50em) {
+ gr-select {
+ display: inline;
+ }
+ gr-button,
+ iron-dropdown {
+ display: none;
+ }
+ select {
+ max-width: 5.25em;
+ }
+ }
+ </style>
+ <gr-button
+ link
+ id="trigger"
+ class="dropdown-trigger"
+ on-tap="_showDropdownTapHandler">
+ <span>[[text]]</span>
+ <span
+ class="downArrow"
+ on-tap="_showDropdownTapHandler">▼</span>
+ </gr-button>
+ <iron-dropdown
+ id="dropdown"
+ vertical-align="top"
+ allow-outside-scroll="true">
+ <paper-listbox
+ class="dropdown-content"
+ slot="dropdown-content"
+ attr-for-selected="value"
+ on-tap="_handleDropdownTap"
+ selected="{{value}}">
+ <template is="dom-repeat" items="[[items]]">
+ <paper-item
+ disabled="[[item.disabled]]"
+ value="[[item.value]]">
+ <div class="topContent">
+ <div>[[item.text]]</div>
+ <template is="dom-if" if="[[item.date]]">
+ <gr-date-formatter
+ date-str="[[item.date]]"></gr-date-formatter>
+ </template>
+ </div>
+ <template is="dom-if" if="[[item.bottomText]]">
+ <div class="bottomContent">
+ <div>[[item.bottomText]]</div>
+ </div>
+ </template>
+ </paper-item>
+ </template>
+ </paper-listbox>
+ </iron-dropdown>
+ <gr-select bind-value="{{value}}">
+ <select>
+ <template is="dom-repeat" items="[[items]]">
+ <option
+ disabled$="[[item.disabled]]"
+ value="[[item.value]]">
+ [[_computeMobileText(item)]]
+ </option>
+ </template>
+ </select>
+ </gr-select>
+ </template>
+ <script src="gr-dropdown-list.js"></script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.js b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.js
new file mode 100644
index 0000000..27c6ba8
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.js
@@ -0,0 +1,102 @@
+// 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';
+
+ /**
+ * fired when the selected value of the dropdown changes
+ *
+ * @event {change}
+ */
+
+ const Defs = {};
+
+ /**
+ * Requred values are text and value. mobileText and triggerText will
+ * fall back to text if not provided.
+ *
+ * If bottomText is not provided, nothing will display on the second
+ * line.
+ *
+ * If date is not provided, nothing will be displayed in its place.
+ *
+ * @typedef {{
+ * text: string,
+ * value: (string|number),
+ * bottomText: (string|undefined),
+ * triggerText: (string|undefined),
+ * mobileText: (string|undefined),
+ * date: (!Date|undefined),
+ * }}
+ */
+ Defs.item;
+
+ Polymer({
+ is: 'gr-dropdown-list',
+
+ properties: {
+ /** @type {!Array<!Defs.item>} */
+ items: Object,
+ text: String,
+ value: {
+ type: String,
+ notify: true,
+ },
+ },
+
+ observers: [
+ '_handleValueChange(value, items)',
+ ],
+
+ /**
+ * Handle a click on the iron-dropdown element.
+ * @param {!Event} e
+ */
+ _handleDropdownTap(e) {
+ // async is needed so that that the click event is fired before the
+ // dropdown closes (This was a bug for touch devices).
+ this.async(() => {
+ this.$.dropdown.close();
+ }, 1);
+ },
+
+ /**
+ * Handle a click on the button to open the dropdown.
+ * @param {!Event} e
+ */
+ _showDropdownTapHandler(e) {
+ this._open();
+ },
+
+ /**
+ * Open the dropdown.
+ */
+ _open() {
+ this.$.dropdown.open();
+ },
+
+ _computeMobileText(item) {
+ return item.mobileText ? item.mobileText : item.text;
+ },
+
+ _handleValueChange(value, items) {
+ if (!value) { return; }
+ const selectedObj = items.find(item => {
+ return item.value + '' === value + '';
+ });
+ this.text = selectedObj.triggerText? selectedObj.triggerText :
+ selectedObj.text;
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html
new file mode 100644
index 0000000..d3c6d83
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html
@@ -0,0 +1,167 @@
+<!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-dropdown-list</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-dropdown-list.html">
+
+<script>void(0);</script>
+
+<test-fixture id="basic">
+ <template>
+ <gr-dropdown-list></gr-dropdown-list>
+ </template>
+</test-fixture>
+
+<script>
+ suite('gr-dropdown-list tests', () => {
+ let element;
+ let sandbox;
+
+ setup(() => {
+ stub('gr-rest-api-interface', {
+ getConfig() { return Promise.resolve({}); },
+ });
+ element = fixture('basic');
+ sandbox = sinon.sandbox.create();
+ });
+
+ teardown(() => {
+ sandbox.restore();
+ });
+
+ test('tap on trigger opens menu', () => {
+ sandbox.stub(element, '_open', () => { element.$.dropdown.open(); });
+ assert.isFalse(element.$.dropdown.opened);
+ MockInteractions.tap(element.$.trigger);
+ assert.isTrue(element.$.dropdown.opened);
+ });
+
+ test('_computeMobileText', () => {
+ const item = {
+ value: 1,
+ text: 'text',
+ };
+ assert.equal(element._computeMobileText(item), item.text);
+ item.mobileText = 'mobile text';
+ assert.equal(element._computeMobileText(item), item.mobileText);
+ });
+
+ test('options are selected and laid out correctly', () => {
+ element.value = 2;
+ element.items = [
+ {
+ value: 1,
+ text: 'Top Text 1',
+ },
+ {
+ value: 2,
+ bottomText: 'Bottom Text 2',
+ triggerText: 'Button Text 2',
+ text: 'Top Text 2',
+ mobileText: 'Mobile Text 2',
+ },
+ {
+ value: 3,
+ disabled: true,
+ bottomText: 'Bottom Text 3',
+ triggerText: 'Button Text 3',
+ date: '2017-08-18 23:11:42.569000000',
+ text: 'Top Text 3',
+ mobileText: 'Mobile Text 3',
+ },
+ ];
+ assert.equal(element.$$('paper-listbox').selected, element.value);
+ assert.equal(element.text, 'Button Text 2');
+ flushAsynchronousOperations();
+ const items = Polymer.dom(element.root).querySelectorAll('paper-item');
+ const mobileItems = Polymer.dom(element.root).querySelectorAll('option');
+ assert.equal(items.length, 3);
+ assert.equal(mobileItems.length, 3);
+
+ // First Item
+ // The first item should be disabled, has no bottom text, and no date.
+ assert.isFalse(!!items[0].disabled);
+ assert.isFalse(mobileItems[0].disabled);
+ assert.isFalse(items[0].classList.contains('iron-selected'));
+ assert.isFalse(mobileItems[0].selected);
+
+ assert.isNotOk(Polymer.dom(items[0]).querySelector('gr-date-formatter'));
+ assert.isNotOk(Polymer.dom(items[0]).querySelector('.bottomContent'));
+ assert.equal(items[0].value, element.items[0].value);
+ assert.equal(mobileItems[0].value, element.items[0].value);
+ assert.equal(Polymer.dom(items[0]).querySelector('.topContent div')
+ .innerText, element.items[0].text);
+
+ // Since no mobile specific text, it should fall back to text.
+ assert.equal(mobileItems[0].text, element.items[0].text);
+
+
+ // Second Item
+ // The second item should have top text, bottom text, and no date.
+ assert.isFalse(!!items[1].disabled);
+ assert.isFalse(mobileItems[1].disabled);
+ assert.isTrue(items[1].classList.contains('iron-selected'));
+ assert.isTrue(mobileItems[1].selected);
+
+ assert.isNotOk(Polymer.dom(items[1]).querySelector('gr-date-formatter'));
+ assert.isOk(Polymer.dom(items[1]).querySelector('.bottomContent'));
+ assert.equal(items[1].value, element.items[1].value);
+ assert.equal(mobileItems[1].value, element.items[1].value);
+ assert.equal(Polymer.dom(items[1]).querySelector('.topContent div')
+ .innerText, element.items[1].text);
+
+ // Since there is mobile specific text, it should that.
+ assert.equal(mobileItems[1].text, element.items[1].mobileText);
+
+ // Since this item is selected, and it has triggerText defined, that
+ // should be used.
+ assert.equal(element.text, element.items[1].triggerText);
+
+ // Third item
+ // The third item should be disabled, and have a date, and bottom content.
+ assert.isTrue(!!items[2].disabled);
+ assert.isTrue(mobileItems[2].disabled);
+ assert.isFalse(items[2].classList.contains('iron-selected'));
+ assert.isFalse(mobileItems[2].selected);
+
+ assert.isOk(Polymer.dom(items[2]).querySelector('gr-date-formatter'));
+ assert.isOk(Polymer.dom(items[2]).querySelector('.bottomContent'));
+ assert.equal(items[2].value, element.items[2].value);
+ assert.equal(mobileItems[2].value, element.items[2].value);
+ assert.equal(Polymer.dom(items[2]).querySelector('.topContent div')
+ .innerText, element.items[2].text);
+
+ // Since there is mobile specific text, it should that.
+ assert.equal(mobileItems[2].text, element.items[2].mobileText);
+
+ // Select a new item.
+ MockInteractions.tap(items[0]);
+ flushAsynchronousOperations();
+ assert.equal(element.value, 1);
+ assert.isTrue(items[0].classList.contains('iron-selected'));
+ assert.isTrue(mobileItems[0].selected);
+
+ // Since no triggerText, the fallback is used.
+ assert.equal(element.text, element.items[0].text);
+ });
+ });
+</script>
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
index 3f2879f..7c8b6ff 100644
--- a/polygerrit-ui/app/test/index.html
+++ b/polygerrit-ui/app/test/index.html
@@ -130,6 +130,7 @@
'shared/gr-cursor-manager/gr-cursor-manager_test.html',
'shared/gr-date-formatter/gr-date-formatter_test.html',
'shared/gr-download-commands/gr-download-commands_test.html',
+ 'shared/gr-dropdown-list/gr-dropdown-list_test.html',
'shared/gr-editable-content/gr-editable-content_test.html',
'shared/gr-editable-label/gr-editable-label_test.html',
'shared/gr-formatted-text/gr-formatted-text_test.html',
diff --git a/tools/checkstyle.xml b/tools/checkstyle.xml
deleted file mode 100644
index cb24e8f..0000000
--- a/tools/checkstyle.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
-
-<!--
- This configuration file was written by the eclipse-cs plugin configuration editor
--->
-<!--
- Checkstyle-Configuration: Google Checks for Gerrit
- Description:
-Checkstyle configuration based on the Google coding conventions (https://google-styleguide.googlecode.com/svn-history/r130/trunk/javaguide.html),
-edited to remove noisy warnings.
--->
-<module name="Checker">
- <property name="severity" value="warning"/>
- <property name="charset" value="UTF-8"/>
- <module name="TreeWalker">
- <module name="FileContentsHolder"/>
- <module name="OuterTypeFilename"/>
- <module name="LineLength">
- <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
- <property name="max" value="150"/>
- <property name="tabWidth" value="2"/>
- </module>
- <module name="OneTopLevelClass"/>
- <module name="NoLineWrap"/>
- <module name="EmptyBlock">
- <property name="option" value="TEXT"/>
- <property name="tokens" value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
- </module>
- <module name="NeedBraces"/>
- <module name="LeftCurly">
- <property name="maxLineLength" value="150"/>
- </module>
- <module name="RightCurly">
- <property name="option" value="alone"/>
- <property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
- </module>
- <module name="WhitespaceAround">
- <property name="severity" value="ignore"/>
- <property name="allowEmptyConstructors" value="true"/>
- <property name="allowEmptyMethods" value="true"/>
- <property name="allowEmptyTypes" value="true"/>
- <property name="allowEmptyLoops" value="true"/>
- <message key="ws.notFollowed" value="WhitespaceAround: ''{0}'' is not followed by whitespace."/>
- <message key="ws.notPreceded" value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="OneStatementPerLine"/>
- <module name="MultipleVariableDeclarations"/>
- <module name="ArrayTypeStyle"/>
- <module name="UpperEll"/>
- <module name="ModifierOrder"/>
- <module name="EmptyLineSeparator">
- <property name="severity" value="ignore"/>
- <property name="allowNoEmptyLineBetweenFields" value="true"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="SeparatorWrap">
- <property name="severity" value="ignore"/>
- <property name="option" value="nl"/>
- <property name="tokens" value="DOT"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="SeparatorWrap">
- <property name="severity" value="ignore"/>
- <property name="option" value="EOL"/>
- <property name="tokens" value="COMMA"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="NoFinalizer"/>
- <module name="GenericWhitespace">
- <property name="severity" value="ignore"/>
- <message key="ws.followed" value="GenericWhitespace ''{0}'' is followed by whitespace."/>
- <message key="ws.illegalFollow" value="GenericWhitespace ''{0}'' should followed by whitespace."/>
- <message key="ws.preceded" value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
- <message key="ws.notPreceded" value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="Indentation">
- <property name="severity" value="ignore"/>
- <property name="basicOffset" value="2"/>
- <property name="caseIndent" value="2"/>
- <property name="arrayInitIndent" value="2"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="MethodParamPad">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="OperatorWrap">
- <property name="severity" value="ignore"/>
- <property name="option" value="NL"/>
- <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="RedundantImport"/>
- <module name="RedundantModifier"/>
- <module name="ExplicitInitialization"/>
- <module name="ArrayTrailingComma"/>
- </module>
- <module name="FileTabCharacter">
- <property name="severity" value="ignore"/>
- <property name="eachLine" value="true"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="SuppressWithNearbyCommentFilter">
- <property name="commentFormat" value="CS IGNORE (\w+) FOR NEXT (\d+) LINES\. REASON\: \w+"/>
- <property name="checkFormat" value="$1"/>
- <property name="influenceFormat" value="$2"/>
- </module>
- <module name="SuppressionFilter">
- <property name="file" value="${samedir}/checkstyle_suppressions.xml"/>
- </module>
-</module>
diff --git a/tools/checkstyle_suppressions.xml b/tools/checkstyle_suppressions.xml
deleted file mode 100644
index 5f5d9ee..0000000
--- a/tools/checkstyle_suppressions.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0"?>
-
-<!DOCTYPE suppressions PUBLIC
- "-//Puppy Crawl//DTD Suppressions 1.1//EN"
- "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
-<suppressions>
- <suppress files="[/\\].apt_generated[/\\]" checks=".*"/>
-</suppressions>
diff --git a/tools/js/bower2bazel.py b/tools/js/bower2bazel.py
index 9e7895d..04d7c24 100755
--- a/tools/js/bower2bazel.py
+++ b/tools/js/bower2bazel.py
@@ -35,6 +35,7 @@
package_licenses = {
"es6-promise": "es6-promise",
"fetch": "fetch",
+ "font-roboto": "polymer",
"iron-a11y-announcer": "polymer",
"iron-a11y-keys-behavior": "polymer",
"iron-autogrow-textarea": "polymer",
@@ -44,6 +45,7 @@
"iron-flex-layout": "polymer",
"iron-form-element-behavior": "polymer",
"iron-input": "polymer",
+ "iron-menu-behavior": "polymer",
"iron-meta": "polymer",
"iron-overlay-behavior": "polymer",
"iron-resizable-behavior": "polymer",
@@ -52,6 +54,9 @@
"moment": "moment",
"neon-animation": "polymer",
"page": "page.js",
+ "paper-item": "polymer",
+ "paper-listbox": "polymer",
+ "paper-styles": "polymer",
"polymer": "polymer",
"polymer-resin": "polymer",
"promise-polyfill": "promise-polyfill",