Merge "Add paper-listbox and paper-item to bower dependencies"
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/Documentation/user-search.txt b/Documentation/user-search.txt
index bbca364..d5b1e26 100644
--- a/Documentation/user-search.txt
+++ b/Documentation/user-search.txt
@@ -530,7 +530,7 @@
A label name must be followed by either a score with optional operator,
or a label status. The easiest way to explain this is by example.
-+
+
First, some examples of scores with operators:
`label:Code-Review=2`::
diff --git a/WORKSPACE b/WORKSPACE
index b16e65f..444339b 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",
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 18e373f..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;
@@ -647,11 +653,11 @@
return result;
}
- private boolean submittable(ChangeData cd) throws OrmException {
+ private boolean submittable(ChangeData cd) {
return SubmitRecord.findOkRecord(cd.submitRecords(SUBMIT_RULE_OPTIONS_STRICT)).isPresent();
}
- private List<SubmitRecord> submitRecords(ChangeData cd) throws OrmException {
+ private List<SubmitRecord> submitRecords(ChangeData cd) {
return cd.submitRecords(SUBMIT_RULE_OPTIONS_LENIENT);
}
@@ -703,7 +709,7 @@
}
private Map<String, LabelWithStatus> initLabels(
- ChangeData cd, LabelTypes labelTypes, boolean standard) throws OrmException {
+ ChangeData cd, LabelTypes labelTypes, boolean standard) {
Map<String, LabelWithStatus> labels = new TreeMap<>(labelTypes.nameComparator());
for (SubmitRecord rec : submitRecords(cd)) {
if (rec.labels == null) {
@@ -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/edit/ChangeEditModifier.java b/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditModifier.java
index 79176e4..82fa596 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditModifier.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditModifier.java
@@ -566,7 +566,13 @@
try (RevWalk revWalk = new RevWalk(repository)) {
RefUpdate.Result res = ru.update(revWalk);
if (res != RefUpdate.Result.NEW && res != RefUpdate.Result.FORCED) {
- throw new IOException("update failed: " + ru);
+ throw new IOException(
+ "cannot update "
+ + ru.getName()
+ + " in "
+ + repository.getDirectory()
+ + ": "
+ + ru.getResult());
}
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
index 730bc10..73a3bc2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -327,8 +327,7 @@
return allowClosed ? SUBMIT_RULE_OPTIONS_ALLOW_CLOSED : SUBMIT_RULE_OPTIONS;
}
- private static List<SubmitRecord> getSubmitRecords(ChangeData cd, boolean allowClosed)
- throws OrmException {
+ private static List<SubmitRecord> getSubmitRecords(ChangeData cd, boolean allowClosed) {
return cd.submitRecords(submitRuleOptions(allowClosed));
}
@@ -396,13 +395,7 @@
checkArgument(
!cs.furtherHiddenChanges(), "cannot bypass submit rules for topic with hidden change");
for (ChangeData cd : cs.changes()) {
- List<SubmitRecord> records;
- try {
- records = new ArrayList<>(getSubmitRecords(cd, allowClosed));
- } catch (OrmException e) {
- log.warn("Error checking submit rules for change " + cd.getId(), e);
- records = new ArrayList<>(1);
- }
+ List<SubmitRecord> records = new ArrayList<>(getSubmitRecords(cd, allowClosed));
SubmitRecord forced = new SubmitRecord();
forced.status = SubmitRecord.Status.FORCED;
records.add(forced);
@@ -836,13 +829,8 @@
}
private SubmitType getSubmitType(ChangeData cd) {
- try {
- SubmitTypeRecord str = cd.submitTypeRecord();
- return str.isOk() ? str.type : null;
- } catch (OrmException e) {
- logError("Failed to get submit type for " + cd.getId(), e);
- return null;
- }
+ SubmitTypeRecord str = cd.submitTypeRecord();
+ return str.isOk() ? str.type : null;
}
private OpenRepo openRepo(Project.NameKey project) throws IntegrationException {
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 85e5d06..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
@@ -38,8 +38,9 @@
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchProjectException;
+import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
@@ -105,6 +106,8 @@
private final Map<QueryKey, List<ChangeData>> queryCache;
private final Map<Branch.NameKey, Optional<RevCommit>> heads;
private final SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory;
+ private final ChangeControl.GenericFactory changeControlFactory;
+ private final ProjectCache projectCache;
private MergeOpRepoManager orm;
private boolean closeOrm;
@@ -116,13 +119,17 @@
Provider<InternalChangeQuery> queryProvider,
Provider<MergeOpRepoManager> repoManagerProvider,
PermissionBackend permissionBackend,
- SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory) {
+ SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory,
+ ChangeControl.GenericFactory changeControlFactory,
+ ProjectCache projectCache) {
this.cfg = cfg;
this.changeDataFactory = changeDataFactory;
this.queryProvider = queryProvider;
this.repoManagerProvider = repoManagerProvider;
this.permissionBackend = permissionBackend;
this.submitRuleEvaluatorFactory = submitRuleEvaluatorFactory;
+ this.changeControlFactory = changeControlFactory;
+ this.projectCache = projectCache;
queryCache = new HashMap<>();
heads = new HashMap<>();
}
@@ -138,7 +145,6 @@
throws IOException, OrmException, PermissionBackendException {
try {
ChangeData cd = changeDataFactory.create(db, change.getProject(), change.getId());
- cd.changeControl(user);
ChangeSet cs =
new ChangeSet(
cd, permissionBackend.user(user).change(cd).database(db).test(ChangePermission.READ));
@@ -154,7 +160,8 @@
}
}
- private SubmitType submitType(ChangeData cd, PatchSet ps, boolean visible) throws OrmException {
+ private SubmitType submitType(ChangeData cd, PatchSet ps, boolean visible)
+ throws OrmException, IOException {
// Submit type prolog rules mean that the submit type can depend on the
// submitting user and the content of the change.
//
@@ -166,7 +173,7 @@
// misleading (but still nonzero) count of the non visible changes that
// would be submitted together with the visible ones.
if (!visible) {
- return cd.changeControl().getProject().getSubmitType();
+ return projectCache.checkedGet(cd.project()).getProject().getSubmitType();
}
SubmitTypeRecord str =
@@ -228,11 +235,6 @@
List<RevCommit> visibleCommits = new ArrayList<>();
List<RevCommit> nonVisibleCommits = new ArrayList<>();
for (ChangeData cd : bc.get(b)) {
- checkState(
- cd.hasChangeControl(),
- "completeChangeSet forgot to set changeControl for current user"
- + " at ChangeData creation time");
-
boolean visible = changes.ids().contains(cd.getId());
if (visible && !canRead(db, user, cd)) {
// We thought the change was visible, but it isn't.
@@ -240,15 +242,15 @@
// 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
// patch set.
PatchSet ps = cd.currentPatchSet();
boolean visiblePatchSet = visible;
- if (!cd.changeControl().isPatchVisible(ps, cd)) {
- Iterable<PatchSet> visiblePatchSets = cd.visiblePatchSets();
+ ChangeControl ctl = changeControlFactory.controlFor(cd.notes(), user);
+ if (!ctl.isPatchVisible(ps, cd)) {
+ Iterable<PatchSet> visiblePatchSets = ctl.getVisiblePatchSets(cd.patchSets(), db);
if (Iterables.isEmpty(visiblePatchSets)) {
visiblePatchSet = false;
} else {
@@ -273,21 +275,19 @@
// 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, user, b, visibleHashes);
- for (ChangeData chd : cds) {
- chd.changeControl(user);
- 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, user, b, nonVisibleHashes));
+ Iterables.addAll(nonVisibleChanges, byCommitsOnBranchNotMerged(or, db, b, nonVisibleHashes));
}
return new ChangeSet(visibleChanges, nonVisibleChanges);
@@ -320,7 +320,7 @@
}
private List<ChangeData> byCommitsOnBranchNotMerged(
- OpenRepo or, ReviewDb db, CurrentUser user, Branch.NameKey branch, Set<String> hashes)
+ OpenRepo or, ReviewDb db, Branch.NameKey branch, Set<String> hashes)
throws OrmException, IOException {
if (hashes.isEmpty()) {
return ImmutableList.of();
@@ -335,7 +335,6 @@
Iterable<ChangeData> destChanges =
query().byCommitsOnBranchNotMerged(or.repo, db, branch, hashes);
for (ChangeData chd : destChanges) {
- chd.changeControl(user);
result.add(chd);
}
queryCache.put(k, result);
@@ -371,19 +370,10 @@
continue;
}
for (ChangeData topicCd : query().byTopicOpen(topic)) {
- try {
- topicCd.changeControl(user);
- if (canRead(db, user, topicCd)) {
- visibleChanges.add(topicCd);
- } else {
- nonVisibleChanges.add(topicCd);
- }
- } catch (OrmException e) {
- if (e.getCause() instanceof NoSuchChangeException) {
- // Ignore and skip this change
- } else {
- throw e;
- }
+ if (canRead(db, user, topicCd)) {
+ visibleChanges.add(topicCd);
+ } else {
+ nonVisibleChanges.add(topicCd);
}
}
topicsSeen.add(topic);
@@ -396,7 +386,6 @@
continue;
}
for (ChangeData topicCd : query().byTopicOpen(topic)) {
- topicCd.changeControl(user);
nonVisibleChanges.add(topicCd);
}
topicsSeen.add(topic);
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 804d3e2..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;
@@ -175,17 +176,16 @@
private AccountGroup createGroup(CreateGroupArgs createGroupArgs)
throws OrmException, ResourceConflictException, IOException {
- // Do not allow creating groups with the same name as system groups
+ String nameLower = createGroupArgs.getGroupName().toLowerCase(Locale.US);
+
for (String name : systemGroupBackend.getNames()) {
- if (name.toLowerCase(Locale.US)
- .equals(createGroupArgs.getGroupName().toLowerCase(Locale.US))) {
+ if (name.toLowerCase(Locale.US).equals(nameLower)) {
throw new ResourceConflictException("group '" + name + "' already exists");
}
}
for (String name : systemGroupBackend.getReservedNames()) {
- if (name.toLowerCase(Locale.US)
- .equals(createGroupArgs.getGroupName().toLowerCase(Locale.US))) {
+ if (name.toLowerCase(Locale.US).equals(nameLower)) {
throw new ResourceConflictException("group name '" + name + "' is reserved");
}
}
@@ -199,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/group/SystemGroupBackend.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/SystemGroupBackend.java
index 56c0208..f0421a5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/SystemGroupBackend.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/SystemGroupBackend.java
@@ -84,7 +84,8 @@
}
private final ImmutableSet<String> reservedNames;
- private final SortedMap<String, GroupReference> names;
+ private final SortedMap<String, GroupReference> namesToGroups;
+ private final ImmutableSet<String> names;
private final ImmutableMap<AccountGroup.UUID, GroupReference> uuids;
@Inject
@@ -105,7 +106,9 @@
u.put(ref.getUUID(), ref);
}
reservedNames = reservedNamesBuilder.build();
- names = Collections.unmodifiableSortedMap(n);
+ namesToGroups = Collections.unmodifiableSortedMap(n);
+ names =
+ ImmutableSet.copyOf(namesToGroups.values().stream().map(r -> r.getName()).collect(toSet()));
uuids = u.build();
}
@@ -114,7 +117,7 @@
}
public Set<String> getNames() {
- return names.values().stream().map(r -> r.getName()).collect(toSet());
+ return names;
}
public Set<String> getReservedNames() {
@@ -158,7 +161,7 @@
@Override
public Collection<GroupReference> suggest(String name, ProjectState project) {
String nameLC = name.toLowerCase(Locale.US);
- SortedMap<String, GroupReference> matches = names.tailMap(nameLC);
+ SortedMap<String, GroupReference> matches = namesToGroups.tailMap(nameLC);
if (matches.isEmpty()) {
return Collections.emptyList();
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeField.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeField.java
index a1c7f14..db71ef5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeField.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeField.java
@@ -658,8 +658,7 @@
return Lists.transform(records, r -> GSON.toJson(new StoredSubmitRecord(r)).getBytes(UTF_8));
}
- private static Iterable<byte[]> storedSubmitRecords(ChangeData cd, SubmitRuleOptions opts)
- throws OrmException {
+ private static Iterable<byte[]> storedSubmitRecords(ChangeData cd, SubmitRuleOptions opts) {
return storedSubmitRecords(cd.submitRecords(opts));
}
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/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
index 13fc362..b5a3d25 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
@@ -17,6 +17,7 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.permissions.LabelPermission.ForUser.ON_BEHALF_OF;
+import static java.util.stream.Collectors.toList;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -50,6 +51,7 @@
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
+import java.util.function.Predicate;
/** Access control management for a user accessing a single change. */
public class ChangeControl {
@@ -214,6 +216,24 @@
return isVisible(cd.db());
}
+ /**
+ * @return patches for the change visible to the current user.
+ * @throws OrmException an error occurred reading the database.
+ */
+ public Collection<PatchSet> getVisiblePatchSets(Collection<PatchSet> patchSets, ReviewDb db)
+ throws OrmException {
+ // TODO(hiesel) These don't need to be migrated, just remove after support for drafts is removed
+ Predicate<? super PatchSet> predicate =
+ ps -> {
+ try {
+ return isPatchVisible(ps, db);
+ } catch (OrmException e) {
+ return false;
+ }
+ };
+ return patchSets.stream().filter(predicate).collect(toList());
+ }
+
/** Can this user abandon this change? */
private boolean canAbandon(ReviewDb db) throws OrmException {
return (isOwner() // owner (aka creator) of the change can abandon
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardsCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardsCollection.java
index 70271b7..ea2935d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardsCollection.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DashboardsCollection.java
@@ -111,17 +111,17 @@
return DashboardResource.projectDefault(myCtl);
}
- List<String> parts = Lists.newArrayList(Splitter.on(':').limit(2).split(id.get()));
- if (parts.size() != 2) {
+ DashboardInfo info;
+ try {
+ info = newDashboardInfo(id.get());
+ } catch (InvalidDashboardId e) {
throw new ResourceNotFoundException(id);
}
CurrentUser user = myCtl.getUser();
- String ref = parts.get(0);
- String path = parts.get(1);
for (ProjectState ps : myCtl.getProjectState().tree()) {
try {
- return parse(ps.controlFor(user), ref, path, myCtl);
+ return parse(ps.controlFor(user), info, myCtl);
} catch (AmbiguousObjectException | ConfigInvalidException | IncorrectObjectTypeException e) {
throw new ResourceNotFoundException(id);
} catch (ResourceNotFoundException e) {
@@ -131,13 +131,17 @@
throw new ResourceNotFoundException(id);
}
- private DashboardResource parse(ProjectControl ctl, String ref, String path, ProjectControl myCtl)
+ public static String normalizeDashboardRef(String ref) {
+ if (!ref.startsWith(REFS_DASHBOARDS)) {
+ return REFS_DASHBOARDS + ref;
+ }
+ return ref;
+ }
+
+ private DashboardResource parse(ProjectControl ctl, DashboardInfo info, ProjectControl myCtl)
throws ResourceNotFoundException, IOException, AmbiguousObjectException,
IncorrectObjectTypeException, ConfigInvalidException, PermissionBackendException {
- String id = ref + ":" + path;
- if (!ref.startsWith(REFS_DASHBOARDS)) {
- ref = REFS_DASHBOARDS + ref;
- }
+ String ref = normalizeDashboardRef(info.ref);
try {
permissionBackend
.user(ctl.getUser())
@@ -146,21 +150,21 @@
.check(RefPermission.READ);
} catch (AuthException e) {
// Don't leak the project's existence
- throw new ResourceNotFoundException(id);
+ throw new ResourceNotFoundException(info.id);
}
if (!Repository.isValidRefName(ref)) {
- throw new ResourceNotFoundException(id);
+ throw new ResourceNotFoundException(info.id);
}
try (Repository git = gitManager.openRepository(ctl.getProject().getNameKey())) {
- ObjectId objId = git.resolve(ref + ":" + path);
+ ObjectId objId = git.resolve(ref + ":" + info.path);
if (objId == null) {
- throw new ResourceNotFoundException(id);
+ throw new ResourceNotFoundException(info.id);
}
BlobBasedConfig cfg = new BlobBasedConfig(null, git, objId);
- return new DashboardResource(myCtl, ref, path, cfg, false);
+ return new DashboardResource(myCtl, ref, info.path, cfg, false);
} catch (RepositoryNotFoundException e) {
- throw new ResourceNotFoundException(id);
+ throw new ResourceNotFoundException(info.id);
}
}
@@ -177,6 +181,26 @@
return info;
}
+ public static class InvalidDashboardId extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidDashboardId(String id) {
+ super(id);
+ }
+ }
+
+ static DashboardInfo newDashboardInfo(String id) throws InvalidDashboardId {
+ DashboardInfo info = new DashboardInfo();
+ List<String> parts = Lists.newArrayList(Splitter.on(':').limit(2).split(id));
+ if (parts.size() != 2) {
+ throw new InvalidDashboardId(id);
+ }
+ info.id = id;
+ info.ref = parts.get(0);
+ info.path = parts.get(1);
+ return info;
+ }
+
static DashboardInfo parse(
Project definingProject,
String refName,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
index 2a3ff45..e3ee265 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -47,7 +47,6 @@
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.RobotComment;
import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.CommentsUtil;
@@ -93,7 +92,6 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.function.Predicate;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
@@ -603,10 +601,6 @@
return visibleTo == user;
}
- public boolean hasChangeControl() {
- return changeControl != null;
- }
-
public ChangeControl changeControl() throws OrmException {
if (changeControl == null) {
Change c = change();
@@ -619,36 +613,6 @@
return changeControl;
}
- public ChangeControl changeControl(CurrentUser user) throws OrmException {
- if (changeControl != null) {
- CurrentUser oldUser = user;
- if (sameUser(user, oldUser)) {
- return changeControl;
- }
- throw new IllegalStateException("user already specified: " + changeControl.getUser());
- }
-
- if (change != null) {
- changeControl = changeControlFactory.controlFor(db, change, user);
- } else {
- changeControl = changeControlFactory.controlFor(db, project(), legacyId, user);
- }
- return changeControl;
- }
-
- private static boolean sameUser(CurrentUser a, CurrentUser b) {
- // TODO(dborowitz): This is a hack; general CurrentUser equality would be
- // better.
- if (a.isInternalUser() && b.isInternalUser()) {
- return true;
- } else if (a instanceof AnonymousUser && b instanceof AnonymousUser) {
- return true;
- } else if (a.isIdentifiedUser() && b.isIdentifiedUser()) {
- return a.getAccountId().equals(b.getAccountId());
- }
- return false;
- }
-
void cacheVisibleTo(ChangeControl ctl) {
visibleTo = ctl.getUser();
changeControl = ctl;
@@ -816,22 +780,6 @@
return patchSets;
}
- /**
- * @return patches for the change visible to the current user.
- * @throws OrmException an error occurred reading the database.
- */
- public Collection<PatchSet> visiblePatchSets() throws OrmException {
- Predicate<? super PatchSet> predicate =
- ps -> {
- try {
- return changeControl().isPatchVisible(ps, db);
- } catch (OrmException e) {
- return false;
- }
- };
- return patchSets().stream().filter(predicate).collect(toList());
- }
-
public void setPatchSets(Collection<PatchSet> patchSets) {
this.currentPatchSet = null;
this.patchSets = patchSets;
@@ -1017,7 +965,7 @@
return messages;
}
- public List<SubmitRecord> submitRecords(SubmitRuleOptions options) throws OrmException {
+ public List<SubmitRecord> submitRecords(SubmitRuleOptions options) {
List<SubmitRecord> records = submitRecords.get(options);
if (records == null) {
if (!lazyLoad) {
@@ -1038,7 +986,7 @@
submitRecords.put(options, records);
}
- public SubmitTypeRecord submitTypeRecord() throws OrmException {
+ public SubmitTypeRecord submitTypeRecord() {
if (submitTypeRecord == null) {
submitTypeRecord = submitRuleEvaluatorFactory.create(this).getSubmitType();
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OutputStreamQuery.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
index 1fe982f..7e7d456 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
@@ -275,7 +275,7 @@
db,
rw,
c,
- d.visiblePatchSets(),
+ d.changeControl().getVisiblePatchSets(d.patchSets(), db),
includeApprovals ? d.approvals().asMap() : null,
includeFiles,
d.change(),
@@ -304,7 +304,7 @@
db,
rw,
c,
- d.visiblePatchSets(),
+ d.changeControl().getVisiblePatchSets(d.patchSets(), db),
includeApprovals ? d.approvals().asMap() : null,
includeFiles,
d.change(),
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/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/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index a59075b..31faa54 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -926,6 +926,12 @@
change.current_revision === edit.base_revision) {
change.current_revision = edit.commit.commit;
this._patchRange.patchNum = this.EDIT_NAME;
+ // Because edits are fibbed as revisions and added to the revisions
+ // array, and revision actions are always derived from the 'latest'
+ // patch set, we must copy over actions from the patch set base.
+ // Context: Issue 7243
+ change.revisions[edit.commit.commit].actions =
+ change.revisions[edit.base_revision].actions;
}
},
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
index 1b2c34e..c1b1a90 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
@@ -1139,7 +1139,7 @@
element._patchRange = {};
const change = {
current_revision: 'foo',
- revisions: {foo: {commit: {}}},
+ revisions: {foo: {commit: {}, actions: {cherrypick: {enabled: true}}}},
};
let mockChange;
@@ -1159,17 +1159,21 @@
assert.equal(mockChange.revisions.bar._number, element.EDIT_NAME);
assert.equal(mockChange.current_revision, change.current_revision);
assert.deepEqual(mockChange.revisions.bar.commit, {commit: 'bar'});
+ assert.notOk(mockChange.revisions.bar.actions);
edit.base_revision = 'foo';
element._processEdit(mockChange = _.cloneDeep(change), edit);
assert.notDeepEqual(mockChange, change);
assert.equal(mockChange.current_revision, 'bar');
+ assert.deepEqual(mockChange.revisions.bar.actions,
+ mockChange.revisions.foo.actions);
// If _patchRange.patchNum is defined, do not load edit.
element._patchRange.patchNum = 'baz';
change.current_revision = 'baz';
element._processEdit(mockChange = _.cloneDeep(change), edit);
assert.equal(element._patchRange.patchNum, 'baz');
+ assert.notOk(mockChange.revisions.bar.actions);
});
test('_editLoaded set when patchNum is an edit', () => {
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/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>