Merge "Delete system config table" into stable-2.16
diff --git a/java/com/google/gerrit/server/config/ConfigUpdatedEvent.java b/java/com/google/gerrit/server/config/ConfigUpdatedEvent.java
index 66d6555..0bfe5fd 100644
--- a/java/com/google/gerrit/server/config/ConfigUpdatedEvent.java
+++ b/java/com/google/gerrit/server/config/ConfigUpdatedEvent.java
@@ -13,10 +13,11 @@
// limitations under the License.
package com.google.gerrit.server.config;
-import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Multimap;
import java.util.Collections;
import java.util.LinkedHashSet;
-import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
@@ -36,6 +37,8 @@
* (+ various overloaded versions of these)
*/
public class ConfigUpdatedEvent {
+ public static final Multimap<UpdateResult, ConfigUpdateEntry> NO_UPDATES =
+ new ImmutableMultimap.Builder<UpdateResult, ConfigUpdateEntry>().build();
private final Config oldConfig;
private final Config newConfig;
@@ -52,25 +55,29 @@
return this.newConfig;
}
- public Update accept(ConfigKey entry) {
+ private String getString(ConfigKey key, Config config) {
+ return config.getString(key.section(), key.subsection(), key.name());
+ }
+
+ public Multimap<UpdateResult, ConfigUpdateEntry> accept(ConfigKey entry) {
return accept(Collections.singleton(entry));
}
- public Update accept(Set<ConfigKey> entries) {
+ public Multimap<UpdateResult, ConfigUpdateEntry> accept(Set<ConfigKey> entries) {
return createUpdate(entries, UpdateResult.APPLIED);
}
- public Update accept(String section) {
+ public Multimap<UpdateResult, ConfigUpdateEntry> accept(String section) {
Set<ConfigKey> entries = getEntriesFromSection(oldConfig, section);
entries.addAll(getEntriesFromSection(newConfig, section));
return createUpdate(entries, UpdateResult.APPLIED);
}
- public Update reject(ConfigKey entry) {
+ public Multimap<UpdateResult, ConfigUpdateEntry> reject(ConfigKey entry) {
return reject(Collections.singleton(entry));
}
- public Update reject(Set<ConfigKey> entries) {
+ public Multimap<UpdateResult, ConfigUpdateEntry> reject(Set<ConfigKey> entries) {
return createUpdate(entries, UpdateResult.REJECTED);
}
@@ -87,20 +94,15 @@
return res;
}
- private Update createUpdate(Set<ConfigKey> entries, UpdateResult updateResult) {
- Update update = new Update(updateResult);
+ private Multimap<UpdateResult, ConfigUpdateEntry> createUpdate(
+ Set<ConfigKey> entries, UpdateResult updateResult) {
+ Multimap<UpdateResult, ConfigUpdateEntry> updates = ArrayListMultimap.create();
entries
.stream()
.filter(this::isValueUpdated)
- .forEach(
- key -> {
- update.addConfigUpdate(
- new ConfigUpdateEntry(
- key,
- oldConfig.getString(key.section(), key.subsection(), key.name()),
- newConfig.getString(key.section(), key.subsection(), key.name())));
- });
- return update;
+ .map(e -> new ConfigUpdateEntry(e, getString(e, oldConfig), getString(e, newConfig)))
+ .forEach(e -> updates.put(updateResult, e));
+ return updates;
}
public boolean isSectionUpdated(String section) {
@@ -142,31 +144,6 @@
}
}
- /**
- * One Accepted/Rejected Update have one or more config updates (ConfigUpdateEntry) tied to it.
- */
- public static class Update {
- private UpdateResult result;
- private final Set<ConfigUpdateEntry> configUpdates;
-
- public Update(UpdateResult result) {
- this.configUpdates = new LinkedHashSet<>();
- this.result = result;
- }
-
- public UpdateResult getResult() {
- return result;
- }
-
- public List<ConfigUpdateEntry> getConfigUpdates() {
- return ImmutableList.copyOf(configUpdates);
- }
-
- public void addConfigUpdate(ConfigUpdateEntry entry) {
- this.configUpdates.add(entry);
- }
- }
-
public enum ConfigEntryType {
ADDED,
REMOVED,
diff --git a/java/com/google/gerrit/server/config/GerritConfigListener.java b/java/com/google/gerrit/server/config/GerritConfigListener.java
index 337a962..f5b2976 100644
--- a/java/com/google/gerrit/server/config/GerritConfigListener.java
+++ b/java/com/google/gerrit/server/config/GerritConfigListener.java
@@ -14,9 +14,11 @@
package com.google.gerrit.server.config;
+import com.google.common.collect.Multimap;
import com.google.gerrit.extensions.annotations.ExtensionPoint;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
import java.util.EventListener;
-import java.util.List;
/**
* Implementations of the GerritConfigListener interface expects to react GerritServerConfig
@@ -24,5 +26,5 @@
*/
@ExtensionPoint
public interface GerritConfigListener extends EventListener {
- List<ConfigUpdatedEvent.Update> configUpdated(ConfigUpdatedEvent event);
+ Multimap<UpdateResult, ConfigUpdateEntry> configUpdated(ConfigUpdatedEvent event);
}
diff --git a/java/com/google/gerrit/server/config/GerritConfigListenerHelper.java b/java/com/google/gerrit/server/config/GerritConfigListenerHelper.java
index 1dfa3fc..d21e1c3 100644
--- a/java/com/google/gerrit/server/config/GerritConfigListenerHelper.java
+++ b/java/com/google/gerrit/server/config/GerritConfigListenerHelper.java
@@ -15,13 +15,12 @@
package com.google.gerrit.server.config;
import com.google.common.collect.ImmutableSet;
-import java.util.Collections;
public class GerritConfigListenerHelper {
public static GerritConfigListener acceptIfChanged(ConfigKey... keys) {
return e ->
e.isEntriesUpdated(ImmutableSet.copyOf(keys))
- ? Collections.singletonList(e.accept(ImmutableSet.copyOf(keys)))
- : Collections.emptyList();
+ ? e.accept(ImmutableSet.copyOf(keys))
+ : ConfigUpdatedEvent.NO_UPDATES;
}
}
diff --git a/java/com/google/gerrit/server/config/GerritServerConfigReloader.java b/java/com/google/gerrit/server/config/GerritServerConfigReloader.java
index 1890de8..09c10740 100644
--- a/java/com/google/gerrit/server/config/GerritServerConfigReloader.java
+++ b/java/com/google/gerrit/server/config/GerritServerConfigReloader.java
@@ -14,12 +14,14 @@
package com.google.gerrit.server.config;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import java.util.ArrayList;
-import java.util.List;
/** Issues a configuration reload from the GerritServerConfigProvider and notify all listeners. */
@Singleton
@@ -40,18 +42,20 @@
* Reloads the Gerrit Server Configuration from disk. Synchronized to ensure that one issued
* reload is fully completed before a new one starts.
*/
- public List<ConfigUpdatedEvent.Update> reloadConfig() {
+ public Multimap<UpdateResult, ConfigUpdateEntry> reloadConfig() {
logger.atInfo().log("Starting server configuration reload");
- List<ConfigUpdatedEvent.Update> updates = fireUpdatedConfigEvent(configProvider.updateConfig());
+ Multimap<UpdateResult, ConfigUpdateEntry> updates =
+ fireUpdatedConfigEvent(configProvider.updateConfig());
logger.atInfo().log("Server configuration reload completed succesfully");
return updates;
}
- public List<ConfigUpdatedEvent.Update> fireUpdatedConfigEvent(ConfigUpdatedEvent event) {
- ArrayList<ConfigUpdatedEvent.Update> result = new ArrayList<>();
+ public Multimap<UpdateResult, ConfigUpdateEntry> fireUpdatedConfigEvent(
+ ConfigUpdatedEvent event) {
+ Multimap<UpdateResult, ConfigUpdateEntry> updates = ArrayListMultimap.create();
for (GerritConfigListener configListener : configListeners) {
- result.addAll(configListener.configUpdated(event));
+ updates.putAll(configListener.configUpdated(event));
}
- return result;
+ return updates;
}
}
diff --git a/java/com/google/gerrit/server/project/CommentLinkProvider.java b/java/com/google/gerrit/server/project/CommentLinkProvider.java
index 56cf51e..4987d00 100644
--- a/java/com/google/gerrit/server/project/CommentLinkProvider.java
+++ b/java/com/google/gerrit/server/project/CommentLinkProvider.java
@@ -16,15 +16,17 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.api.projects.CommentLinkInfo;
import com.google.gerrit.server.config.ConfigUpdatedEvent;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
import com.google.gerrit.server.config.GerritConfigListener;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
-import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.jgit.lib.Config;
@@ -64,11 +66,11 @@
}
@Override
- public List<ConfigUpdatedEvent.Update> configUpdated(ConfigUpdatedEvent event) {
+ public Multimap<UpdateResult, ConfigUpdateEntry> configUpdated(ConfigUpdatedEvent event) {
if (event.isSectionUpdated(ProjectConfig.COMMENTLINK)) {
commentLinks = parseConfig(event.getNewConfig());
- return Collections.singletonList(event.accept(ProjectConfig.COMMENTLINK));
+ return event.accept(ProjectConfig.COMMENTLINK);
}
- return Collections.emptyList();
+ return ConfigUpdatedEvent.NO_UPDATES;
}
}
diff --git a/java/com/google/gerrit/server/restapi/config/ReloadConfig.java b/java/com/google/gerrit/server/restapi/config/ReloadConfig.java
index de3c3ee..cab07e3 100644
--- a/java/com/google/gerrit/server/restapi/config/ReloadConfig.java
+++ b/java/com/google/gerrit/server/restapi/config/ReloadConfig.java
@@ -16,12 +16,12 @@
import static com.google.common.collect.ImmutableList.toImmutableList;
+import com.google.common.collect.Multimap;
import com.google.gerrit.extensions.api.config.ConfigUpdateEntryInfo;
import com.google.gerrit.extensions.common.Input;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.config.ConfigResource;
-import com.google.gerrit.server.config.ConfigUpdatedEvent;
import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
import com.google.gerrit.server.config.GerritServerConfigReloader;
@@ -29,10 +29,11 @@
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.Inject;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
public class ReloadConfig implements RestModifyView<ConfigResource, Input> {
@@ -49,25 +50,22 @@
public Map<String, List<ConfigUpdateEntryInfo>> apply(ConfigResource resource, Input input)
throws RestApiException, PermissionBackendException {
permissions.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
-
- List<ConfigUpdatedEvent.Update> updates = config.reloadConfig();
-
- Map<String, List<ConfigUpdateEntryInfo>> reply = new HashMap<>();
- for (UpdateResult result : UpdateResult.values()) {
- reply.put(result.name().toLowerCase(), new ArrayList<>());
- }
+ Multimap<UpdateResult, ConfigUpdateEntry> updates = config.reloadConfig();
if (updates.isEmpty()) {
- return reply;
+ return Collections.emptyMap();
}
- updates
+ return updates
+ .asMap()
+ .entrySet()
.stream()
- .forEach(u -> reply.get(u.getResult().name().toLowerCase()).addAll(toEntryInfos(u)));
- return reply;
+ .collect(
+ Collectors.toMap(
+ e -> e.getKey().name().toLowerCase(), e -> toEntryInfos(e.getValue())));
}
- private static List<ConfigUpdateEntryInfo> toEntryInfos(ConfigUpdatedEvent.Update update) {
- return update
- .getConfigUpdates()
+ private static List<ConfigUpdateEntryInfo> toEntryInfos(
+ Collection<ConfigUpdateEntry> updateEntries) {
+ return updateEntries
.stream()
.map(ReloadConfig::toConfigUpdateEntryInfo)
.collect(toImmutableList());
diff --git a/java/com/google/gerrit/server/restapi/project/SetParent.java b/java/com/google/gerrit/server/restapi/project/SetParent.java
index ca7e7aa..d02d04a 100644
--- a/java/com/google/gerrit/server/restapi/project/SetParent.java
+++ b/java/com/google/gerrit/server/restapi/project/SetParent.java
@@ -19,6 +19,7 @@
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
import com.google.gerrit.extensions.api.projects.ParentInput;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -32,6 +33,8 @@
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.ConfigKey;
import com.google.gerrit.server.config.ConfigUpdatedEvent;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
import com.google.gerrit.server.config.GerritConfigListener;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
@@ -46,8 +49,6 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
@@ -172,18 +173,18 @@
}
@Override
- public List<ConfigUpdatedEvent.Update> configUpdated(ConfigUpdatedEvent event) {
+ public Multimap<UpdateResult, ConfigUpdateEntry> configUpdated(ConfigUpdatedEvent event) {
ConfigKey receiveSetParent = ConfigKey.create("receive", "allowProjectOwnersToChangeParent");
if (!event.isValueUpdated(receiveSetParent)) {
- return Collections.emptyList();
+ return ConfigUpdatedEvent.NO_UPDATES;
}
try {
boolean enabled =
event.getNewConfig().getBoolean("receive", "allowProjectOwnersToChangeParent", false);
this.allowProjectOwnersToChangeParent = enabled;
- return Collections.singletonList(event.accept(receiveSetParent));
} catch (IllegalArgumentException iae) {
- return Collections.singletonList(event.reject(receiveSetParent));
+ return event.reject(receiveSetParent);
}
+ return event.accept(receiveSetParent);
}
}
diff --git a/java/com/google/gerrit/sshd/SshLog.java b/java/com/google/gerrit/sshd/SshLog.java
index 0e34889..df3242c 100644
--- a/java/com/google/gerrit/sshd/SshLog.java
+++ b/java/com/google/gerrit/sshd/SshLog.java
@@ -15,6 +15,7 @@
package com.google.gerrit.sshd;
import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.server.CurrentUser;
@@ -24,6 +25,8 @@
import com.google.gerrit.server.audit.SshAuditEvent;
import com.google.gerrit.server.config.ConfigKey;
import com.google.gerrit.server.config.ConfigUpdatedEvent;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
import com.google.gerrit.server.config.GerritConfigListener;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.ioutil.HexFormat;
@@ -33,8 +36,6 @@
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
-import java.util.Collections;
-import java.util.List;
import org.apache.log4j.AsyncAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
@@ -318,25 +319,22 @@
}
@Override
- public List<ConfigUpdatedEvent.Update> configUpdated(ConfigUpdatedEvent event) {
+ public Multimap<UpdateResult, ConfigUpdateEntry> configUpdated(ConfigUpdatedEvent event) {
ConfigKey sshdRequestLog = ConfigKey.create("sshd", "requestLog");
if (!event.isValueUpdated(sshdRequestLog)) {
- return Collections.emptyList();
+ return ConfigUpdatedEvent.NO_UPDATES;
}
boolean stateUpdated;
try {
boolean enabled = event.getNewConfig().getBoolean("sshd", "requestLog", true);
-
if (enabled) {
stateUpdated = enableLogging();
} else {
stateUpdated = disableLogging();
}
- return stateUpdated
- ? Collections.singletonList(event.accept(sshdRequestLog))
- : Collections.emptyList();
+ return stateUpdated ? event.accept(sshdRequestLog) : ConfigUpdatedEvent.NO_UPDATES;
} catch (IllegalArgumentException iae) {
- return Collections.singletonList(event.reject(sshdRequestLog));
+ return event.reject(sshdRequestLog);
}
}
}
diff --git a/java/com/google/gerrit/sshd/commands/ReloadConfig.java b/java/com/google/gerrit/sshd/commands/ReloadConfig.java
index 1b21230..cbe3c57 100644
--- a/java/com/google/gerrit/sshd/commands/ReloadConfig.java
+++ b/java/com/google/gerrit/sshd/commands/ReloadConfig.java
@@ -16,16 +16,15 @@
import static com.google.gerrit.sshd.CommandMetaData.Mode.MASTER_OR_SLAVE;
+import com.google.common.collect.Multimap;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
-import com.google.gerrit.server.config.ConfigUpdatedEvent;
+import com.google.gerrit.server.config.ConfigUpdatedEvent.ConfigUpdateEntry;
import com.google.gerrit.server.config.ConfigUpdatedEvent.UpdateResult;
import com.google.gerrit.server.config.GerritServerConfigReloader;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;
-import java.util.List;
-import java.util.stream.Collectors;
/** Issues a reload of gerrit.config. */
@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
@@ -39,31 +38,16 @@
@Override
protected void run() throws Failure {
- List<ConfigUpdatedEvent.Update> updates = gerritServerConfigReloader.reloadConfig();
+ Multimap<UpdateResult, ConfigUpdateEntry> updates = gerritServerConfigReloader.reloadConfig();
if (updates.isEmpty()) {
stdout.println("No config entries updated!");
return;
}
// Print out UpdateResult.{ACCEPTED|REJECTED} entries grouped by their type
- for (UpdateResult updateResult : UpdateResult.values()) {
- List<ConfigUpdatedEvent.Update> filteredUpdates = filterUpdates(updates, updateResult);
- if (filteredUpdates.isEmpty()) {
- continue;
- }
- stdout.println(updateResult.toString() + " configuration changes:");
- filteredUpdates
- .stream()
- .flatMap(update -> update.getConfigUpdates().stream())
- .forEach(cfgEntry -> stdout.println(cfgEntry.toString()));
+ for (UpdateResult result : updates.keySet()) {
+ stdout.println(result.toString() + " configuration changes:");
+ updates.get(result).forEach(cfgEntry -> stdout.println(cfgEntry.toString()));
}
}
-
- public static List<ConfigUpdatedEvent.Update> filterUpdates(
- List<ConfigUpdatedEvent.Update> updates, UpdateResult result) {
- return updates
- .stream()
- .filter(update -> update.getResult() == result)
- .collect(Collectors.toList());
- }
}
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
index d1fdf2f..af982cf 100644
--- a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
@@ -165,6 +165,7 @@
PREV_FILE: 'PREV_FILE',
NEXT_FILE_WITH_COMMENTS: 'NEXT_FILE_WITH_COMMENTS',
PREV_FILE_WITH_COMMENTS: 'PREV_FILE_WITH_COMMENTS',
+ NEXT_UNREVIEWED_FILE: 'NEXT_UNREVIEWED_FILE',
CURSOR_NEXT_FILE: 'CURSOR_NEXT_FILE',
CURSOR_PREV_FILE: 'CURSOR_PREV_FILE',
OPEN_FILE: 'OPEN_FILE',
@@ -255,6 +256,8 @@
'Mark/unmark file as reviewed');
_describe(Shortcut.TOGGLE_DIFF_MODE, ShortcutSection.DIFFS,
'Toggle unified/side-by-side diff');
+ _describe(Shortcut.NEXT_UNREVIEWED_FILE, ShortcutSection.DIFFS,
+ 'Mark file as reviewed and go to next unreviewed file');
_describe(Shortcut.NEXT_FILE, ShortcutSection.NAVIGATION, 'Select next file');
_describe(Shortcut.PREV_FILE, ShortcutSection.NAVIGATION,
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.js b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.js
index 5a463be..4073798 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.js
+++ b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.js
@@ -128,8 +128,17 @@
});
},
+ _refreshGroupsList() {
+ this.$.restAPI.invalidateGroupsCache(this._filter,
+ this._groupsPerPage, this._offset);
+ return this._getGroups(this._filter, this._groupsPerPage,
+ this._offset);
+ },
+
_handleCreateGroup() {
- this.$.createNewModal.handleCreateGroup();
+ this.$.createNewModal.handleCreateGroup().then(() => {
+ this._refreshGroupsList();
+ });
},
_handleCloseCreate() {
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.html b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.html
index ad12a44..987b63d 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.html
@@ -55,7 +55,7 @@
padding: 0 .15em;
}
}
- .hideBranch {
+ .hide {
display: none;
}
</style>
@@ -108,7 +108,7 @@
</iron-autogrow-textarea>
</span>
</section>
- <section>
+ <section class$="[[_computePrivateSectionClass(_privateChangesEnabled)]]">
<label
class="title"
for="privateChangeCheckBox">Private change</label>
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.js b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.js
index 826a6dc..8e15755 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.js
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.js
@@ -44,6 +44,7 @@
notify: true,
value: false,
},
+ _privateChangesEnabled: Boolean,
},
behaviors: [
@@ -52,10 +53,23 @@
],
attached() {
- if (!this.repoName) { return; }
- this.$.restAPI.getProjectConfig(this.repoName).then(config => {
- this.privateByDefault = config.private_by_default;
- });
+ if (!this.repoName) { return Promise.resolve(); }
+
+ const promises = [];
+
+ promises.push(this.$.restAPI.getProjectConfig(this.repoName)
+ .then(config => {
+ this.privateByDefault = config.private_by_default;
+ }));
+
+ promises.push(this.$.restAPI.getConfig().then(config => {
+ if (!config) { return; }
+
+ this._privateConfig = config && config.change &&
+ config.change.disable_private_changes;
+ }));
+
+ return Promise.all(promises);
},
observers: [
@@ -63,7 +77,7 @@
],
_computeBranchClass(baseChange) {
- return baseChange ? 'hideBranch' : '';
+ return baseChange ? 'hide' : '';
},
_allowCreate(branch, subject) {
@@ -120,5 +134,9 @@
return false;
}
},
+
+ _computePrivateSectionClass(config) {
+ return config ? 'hide' : '';
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html
index 08c569c..aa4da68 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html
@@ -158,5 +158,15 @@
done();
});
});
+
+ test('_computeBranchClass', () => {
+ assert.equal(element._computeBranchClass(true), 'hide');
+ assert.equal(element._computeBranchClass(false), '');
+ });
+
+ test('_computePrivateSectionClass', () => {
+ assert.equal(element._computePrivateSectionClass(true), 'hide');
+ assert.equal(element._computePrivateSectionClass(false), '');
+ });
});
</script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.js b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.js
index 4b82e57..116f084 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.js
@@ -129,8 +129,17 @@
});
},
+ _refreshReposList() {
+ this.$.restAPI.invalidateReposCache(this._filter,
+ this._reposPerPage, this._offset);
+ return this._getRepos(this._filter, this._reposPerPage,
+ this._offset);
+ },
+
_handleCreateRepo() {
- this.$.createNewModal.handleCreateRepo();
+ this.$.createNewModal.handleCreateRepo().then(() => {
+ this._refreshReposList();
+ });
},
_handleCloseCreate() {
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
index 3c5adde..bec08a8 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
@@ -163,11 +163,28 @@
</template>
</span>
</section>
- <section class$="[[_computeShowUploaderHide(change)]]">
+ <section class$="[[_computeShowRoleClass(change, _CHANGE_ROLE.UPLOADER)]]">
<span class="title">Uploader</span>
<span class="value">
<gr-account-link
- account="[[_computeShowUploader(change)]]"></gr-account-link>
+ account="[[_getNonOwnerRole(change, _CHANGE_ROLE.UPLOADER)]]"
+ ></gr-account-link>
+ </span>
+ </section>
+ <section class$="[[_computeShowRoleClass(change, _CHANGE_ROLE.AUTHOR)]]">
+ <span class="title">Author</span>
+ <span class="value">
+ <gr-account-link
+ account="[[_getNonOwnerRole(change, _CHANGE_ROLE.AUTHOR)]]"
+ ></gr-account-link>
+ </span>
+ </section>
+ <section class$="[[_computeShowRoleClass(change, _CHANGE_ROLE.COMMITTER)]]">
+ <span class="title">Committer</span>
+ <span class="value">
+ <gr-account-link
+ account="[[_getNonOwnerRole(change, _CHANGE_ROLE.COMMITTER)]]"
+ ></gr-account-link>
</span>
</section>
<section class="assignee">
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
index 82af321..d3fc7e0 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
@@ -133,6 +133,18 @@
type: Array,
computed: '_computeParents(change)',
},
+
+ /** @type {?} */
+ _CHANGE_ROLE: {
+ type: Object,
+ readOnly: true,
+ value: {
+ OWNER: 'owner',
+ UPLOADER: 'uploader',
+ AUTHOR: 'author',
+ COMMITTER: 'committer',
+ },
+ },
},
behaviors: [
@@ -388,24 +400,45 @@
return !!change.work_in_progress;
},
- _computeShowUploaderHide(change) {
- return this._computeShowUploader(change) ? '' : 'hideDisplay';
+ _computeShowRoleClass(change, role) {
+ return this._getNonOwnerRole(change, role) ? '' : 'hideDisplay';
},
- _computeShowUploader(change) {
+ /**
+ * Get the user with the specified role on the change. Returns null if the
+ * user with that role is the same as the owner.
+ * @param {!Object} change
+ * @param {string} role One of the values from _CHANGE_ROLE
+ * @return {Object|null} either an accound or null.
+ */
+ _getNonOwnerRole(change, role) {
if (!change.current_revision ||
!change.revisions[change.current_revision]) {
return null;
}
const rev = change.revisions[change.current_revision];
+ if (!rev) { return null; }
- if (!rev || !rev.uploader ||
- change.owner._account_id === rev.uploader._account_id) {
- return null;
+ if (role === this._CHANGE_ROLE.UPLOADER &&
+ rev.uploader &&
+ change.owner._account_id !== rev.uploader._account_id) {
+ return rev.uploader;
}
- return rev.uploader;
+ if (role === this._CHANGE_ROLE.AUTHOR &&
+ rev.commit && rev.commit.author &&
+ change.owner.email !== rev.commit.author.email) {
+ return rev.commit.author;
+ }
+
+ if (role === this._CHANGE_ROLE.COMMITTER &&
+ rev.commit && rev.commit.committer &&
+ change.owner.email !== rev.commit.committer.email) {
+ return rev.commit.committer;
+ }
+
+ return null;
},
_computeParents(change) {
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
index 2884a68..c5a569e 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
@@ -185,115 +185,130 @@
assert.equal(element._computeWebLinks(element.commitInfo).length, 1);
});
- test('_computeShowUploader test for uploader', () => {
- const change = {
- change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
- owner: {
- _account_id: 1019328,
- },
- revisions: {
- rev1: {
- _number: 1,
- uploader: {
- _account_id: 1011123,
- },
- },
- },
- current_revision: 'rev1',
- status: 'NEW',
- labels: {},
- mergeable: true,
- };
- assert.deepEqual(element._computeShowUploader(change),
- {_account_id: 1011123});
- });
+ suite('_getNonOwnerRole', () => {
+ let change;
- test('_computeShowUploader test that it does not return uploader', () => {
- const change = {
- change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
- owner: {
- _account_id: 1011123,
- },
- revisions: {
- rev1: {
- _number: 1,
- uploader: {
- _account_id: 1011123,
+ setup(() => {
+ change = {
+ owner: {
+ email: 'abc@def',
+ _account_id: 1019328,
+ },
+ revisions: {
+ rev1: {
+ _number: 1,
+ uploader: {
+ email: 'ghi@def',
+ _account_id: 1011123,
+ },
+ commit: {
+ author: {email: 'jkl@def'},
+ committer: {email: 'ghi@def'},
+ },
},
},
- },
- current_revision: 'rev1',
- status: 'NEW',
- labels: {},
- mergeable: true,
- };
- assert.isNotOk(element._computeShowUploader(change));
- });
+ current_revision: 'rev1',
+ };
+ });
- test('no current_revision makes _computeShowUploader return null', () => {
- const change = {
- change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
- owner: {
- _account_id: 1011123,
- },
- revisions: {
- rev1: {
- _number: 1,
- uploader: {
- _account_id: 1011123,
- },
- },
- },
- status: 'NEW',
- labels: {},
- mergeable: true,
- };
- assert.isNotOk(element._computeShowUploader(change));
- });
+ suite('role=uploader', () => {
+ test('_getNonOwnerRole for uploader', () => {
+ assert.deepEqual(
+ element._getNonOwnerRole(change, element._CHANGE_ROLE.UPLOADER),
+ {email: 'ghi@def', _account_id: 1011123});
+ });
- test('_computeShowUploaderHide test for string which equals true', () => {
- const change = {
- change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
- owner: {
- _account_id: 1019328,
- },
- revisions: {
- rev1: {
- _number: 1,
- uploader: {
- _account_id: 1011123,
- },
- },
- },
- current_revision: 'rev1',
- status: 'NEW',
- labels: {},
- mergeable: true,
- };
- assert.equal(element._computeShowUploaderHide(change), '');
- });
+ test('_getNonOwnerRole that it does not return uploader', () => {
+ // Set the uploader email to be the same as the owner.
+ change.revisions.rev1.uploader._account_id = 1019328;
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.UPLOADER));
+ });
- test('_computeShowUploaderHide test for hideDisplay', () => {
- const change = {
- change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
- owner: {
- _account_id: 1011123,
- },
- revisions: {
- rev1: {
- _number: 1,
- uploader: {
- _account_id: 1011123,
- },
- },
- },
- current_revision: 'rev1',
- status: 'NEW',
- labels: {},
- mergeable: true,
- };
- assert.equal(
- element._computeShowUploaderHide(change), 'hideDisplay');
+ test('_getNonOwnerRole null for uploader with no current rev', () => {
+ delete change.current_revision;
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.UPLOADER));
+ });
+
+ test('_computeShowRoleClass show uploader', () => {
+ assert.equal(element._computeShowRoleClass(
+ change, element._CHANGE_ROLE.UPLOADER), '');
+ });
+
+ test('_computeShowRoleClass hide uploader', () => {
+ // Set the uploader email to be the same as the owner.
+ change.revisions.rev1.uploader._account_id = 1019328;
+ assert.equal(element._computeShowRoleClass(change,
+ element._CHANGE_ROLE.UPLOADER), 'hideDisplay');
+ });
+ });
+
+ suite('role=committer', () => {
+ test('_getNonOwnerRole for committer', () => {
+ assert.deepEqual(
+ element._getNonOwnerRole(change, element._CHANGE_ROLE.COMMITTER),
+ {email: 'ghi@def'});
+ });
+
+ test('_getNonOwnerRole that it does not return committer', () => {
+ // Set the committer email to be the same as the owner.
+ change.revisions.rev1.commit.committer.email = 'abc@def';
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.COMMITTER));
+ });
+
+ test('_getNonOwnerRole null for committer with no current rev', () => {
+ delete change.current_revision;
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.COMMITTER));
+ });
+
+ test('_getNonOwnerRole null for committer with no commit', () => {
+ delete change.revisions.rev1.commit;
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.COMMITTER));
+ });
+
+ test('_getNonOwnerRole null for committer with no committer', () => {
+ delete change.revisions.rev1.commit.committer;
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.COMMITTER));
+ });
+ });
+
+ suite('role=author', () => {
+ test('_getNonOwnerRole for author', () => {
+ assert.deepEqual(
+ element._getNonOwnerRole(change, element._CHANGE_ROLE.AUTHOR),
+ {email: 'jkl@def'});
+ });
+
+ test('_getNonOwnerRole that it does not return author', () => {
+ // Set the author email to be the same as the owner.
+ change.revisions.rev1.commit.author.email = 'abc@def';
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.AUTHOR));
+ });
+
+ test('_getNonOwnerRole null for author with no current rev', () => {
+ delete change.current_revision;
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.AUTHOR));
+ });
+
+ test('_getNonOwnerRole null for author with no commit', () => {
+ delete change.revisions.rev1.commit;
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.AUTHOR));
+ });
+
+ test('_getNonOwnerRole null for author with no author', () => {
+ delete change.revisions.rev1.commit.author;
+ assert.isNull(element._getNonOwnerRole(change,
+ element._CHANGE_ROLE.AUTHOR));
+ });
+ });
});
test('Push Certificate Validation test BAD', () => {
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 4296bd4..f6acef6 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
@@ -575,6 +575,7 @@
};
element._change = {
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
+ owner: {email: 'abc@def'},
revisions: {
rev2: {_number: 2, commit: {parents: []}},
rev1: {_number: 1, commit: {parents: []}},
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
index 6f361d8..cf8417a 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
@@ -161,6 +161,10 @@
type: Object,
computed: '_getRevisionInfo(_change)',
},
+ _reviewedFiles: {
+ type: Object,
+ value: () => new Set(),
+ },
},
behaviors: [
@@ -207,6 +211,7 @@
[this.Shortcut.TOGGLE_DIFF_MODE]: '_handleToggleDiffMode',
[this.Shortcut.TOGGLE_FILE_REVIEWED]: '_handleToggleFileReviewed',
[this.Shortcut.EXPAND_ALL_DIFF_CONTEXT]: '_handleExpandAllDiffContext',
+ [this.Shortcut.NEXT_UNREVIEWED_FILE]: '_handleNextUnreviewedFile',
// Final two are actually handled by gr-diff-comment-thread.
[this.Shortcut.EXPAND_ALL_COMMENT_THREADS]: null,
@@ -555,10 +560,18 @@
return {path: fileList[idx]};
},
+ _getReviewedFiles(changeNum, patchNum) {
+ return this.$.restAPI.getReviewedFiles(changeNum, patchNum)
+ .then(files => {
+ this._reviewedFiles = new Set(files);
+ return this._reviewedFiles;
+ });
+ },
+
_getReviewedStatus(editMode, changeNum, patchNum, path) {
if (editMode) { return Promise.resolve(false); }
- return this.$.restAPI.getReviewedFiles(changeNum, patchNum)
- .then(files => files.includes(path));
+ return this._getReviewedFiles(changeNum, patchNum)
+ .then(files => files.has(path));
},
_paramsChanged(value) {
@@ -1012,5 +1025,15 @@
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
this.$.diffHost.expandAllContext();
},
+
+ _handleNextUnreviewedFile(e) {
+ this._setReviewed(true);
+ // Ensure that the currently viewed file always appears in unreviewedFiles
+ // so we resolve the right "next" file.
+ const unreviewedFiles = this._fileList
+ .filter(file =>
+ (file === this._path || !this._reviewedFiles.has(file)));
+ this._navToFile(this._path, unreviewedFiles, 1);
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
index 431578b..958acdb 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
@@ -67,6 +67,7 @@
kb.bindShortcut(kb.Shortcut.EXPAND_ALL_DIFF_CONTEXT, 'shift+x');
kb.bindShortcut(kb.Shortcut.EXPAND_ALL_COMMENT_THREADS, 'e');
kb.bindShortcut(kb.Shortcut.COLLAPSE_ALL_COMMENT_THREADS, 'shift+e');
+ kb.bindShortcut(kb.Shortcut.NEXT_UNREVIEWED_FILE, 'shift+m');
let element;
let sandbox;
@@ -1106,5 +1107,22 @@
assert.isTrue(setStub.calledOnce);
assert.isTrue(setStub.calledWith(101, 'test-project'));
});
+
+ test('shift+m navigates to next unreviewed file', () => {
+ element._fileList = ['file1', 'file2', 'file3'];
+ element._reviewedFiles = new Set(['file1', 'file2']);
+ element._path = 'file1';
+ const reviewedStub = sandbox.stub(element, '_setReviewed');
+ const navStub = sandbox.stub(element, '_navToFile');
+ MockInteractions.pressAndReleaseKeyOn(element, 77, 'shift', 'm');
+ flushAsynchronousOperations();
+
+ assert.isTrue(reviewedStub.lastCall.args[0]);
+ assert.deepEqual(navStub.lastCall.args, [
+ 'file1',
+ ['file1', 'file3'],
+ 1,
+ ]);
+ });
});
</script>
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index 0cf517d..321dc58 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -275,6 +275,8 @@
this.bindShortcut(
this.Shortcut.TOGGLE_FILE_REVIEWED, 'r');
this.bindShortcut(
+ this.Shortcut.NEXT_UNREVIEWED_FILE, 'shift+m');
+ this.bindShortcut(
this.Shortcut.TOGGLE_ALL_INLINE_DIFFS, 'shift+i:keyup');
this.bindShortcut(
this.Shortcut.TOGGLE_INLINE_DIFF, 'i:keyup');
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index fd25908..d9b0cbf 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -169,6 +169,16 @@
delete(key) {
this._cache().delete(key);
}
+
+ invalidatePrefix(prefix) {
+ const newMap = new Map();
+ for (const [key, value] of this._cache().entries()) {
+ if (!key.startsWith(prefix)) {
+ newMap.set(key, value);
+ }
+ }
+ this._data.set(window.CANONICAL_PATH, newMap);
+ }
}
Polymer({
@@ -1207,6 +1217,20 @@
return this._sharedFetchPromises[req.url];
},
+ /**
+ * @param {string} prefix
+ */
+ _invalidateSharedFetchPromisesPrefix(prefix) {
+ const newObject = {};
+ Object.entries(this._sharedFetchPromises).forEach(([key, value]) => {
+ if (!key.startsWith(prefix)) {
+ newObject[key] = value;
+ }
+ });
+ this._sharedFetchPromises = newObject;
+ this._cache.invalidatePrefix(prefix);
+ },
+
_isNarrowScreen() {
return window.innerWidth < MAX_UNIFIED_DEFAULT_WINDOW_WIDTH_PX;
},
@@ -1533,25 +1557,20 @@
* @param {string} filter
* @param {number} groupsPerPage
* @param {number=} opt_offset
- * @return {!Promise<?Object>}
*/
- getGroups(filter, groupsPerPage, opt_offset) {
+ _getGroupsUrl(filter, groupsPerPage, opt_offset) {
const offset = opt_offset || 0;
- return this._fetchSharedCacheURL({
- url: `/groups/?n=${groupsPerPage + 1}&S=${offset}` +
- this._computeFilter(filter),
- anonymizedUrl: '/groups/?*',
- });
+ return `/groups/?n=${groupsPerPage + 1}&S=${offset}` +
+ this._computeFilter(filter);
},
/**
* @param {string} filter
* @param {number} reposPerPage
* @param {number=} opt_offset
- * @return {!Promise<?Object>}
*/
- getRepos(filter, reposPerPage, opt_offset) {
+ _getReposUrl(filter, reposPerPage, opt_offset) {
const defaultFilter = 'state:active OR state:read-only';
const namePartDelimiters = /[@.\-\s\/_]/g;
const offset = opt_offset || 0;
@@ -1578,11 +1597,46 @@
filter = filter.trim();
const encodedFilter = encodeURIComponent(filter);
+ return `/projects/?n=${reposPerPage + 1}&S=${offset}` +
+ `&query=${encodedFilter}`;
+ },
+
+ invalidateGroupsCache() {
+ this._invalidateSharedFetchPromisesPrefix('/groups/?');
+ },
+
+ invalidateReposCache(filter, reposPerPage, opt_offset) {
+ this._invalidateSharedFetchPromisesPrefix('/projects/?');
+ },
+
+ /**
+ * @param {string} filter
+ * @param {number} groupsPerPage
+ * @param {number=} opt_offset
+ * @return {!Promise<?Object>}
+ */
+ getGroups(filter, groupsPerPage, opt_offset) {
+ const url = this._getGroupsUrl(filter, groupsPerPage, opt_offset);
+
+ return this._fetchSharedCacheURL({
+ url,
+ anonymizedUrl: '/groups/?*',
+ });
+ },
+
+ /**
+ * @param {string} filter
+ * @param {number} reposPerPage
+ * @param {number=} opt_offset
+ * @return {!Promise<?Object>}
+ */
+ getRepos(filter, reposPerPage, opt_offset) {
+ const url = this._getReposUrl(filter, reposPerPage, opt_offset);
+
// TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
// supports it.
return this._fetchSharedCacheURL({
- url: `/projects/?n=${reposPerPage + 1}&S=${offset}` +
- `&query=${encodedFilter}`,
+ url,
anonymizedUrl: '/projects/?*',
});
},
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
index b3496ce..667f24c 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
@@ -96,6 +96,18 @@
});
});
+ test('cache invalidation', () => {
+ element._cache.set('/foo/bar', 1);
+ element._cache.set('/bar', 2);
+ element._sharedFetchPromises['/foo/bar'] = 3;
+ element._sharedFetchPromises['/bar'] = 4;
+ element._invalidateSharedFetchPromisesPrefix('/foo/');
+ assert.isFalse(element._cache.has('/foo/bar'));
+ assert.isTrue(element._cache.has('/bar'));
+ assert.isUndefined(element._sharedFetchPromises['/foo/bar']);
+ assert.strictEqual(4, element._sharedFetchPromises['/bar']);
+ });
+
test('params are properly encoded', () => {
let url = element._urlWithParams('/path/', {
sp: 'hola',
@@ -926,6 +938,31 @@
});
});
+ test('normal use', () => {
+ const defaultQuery = 'state%3Aactive%20OR%20state%3Aread-only';
+
+ assert.equal(element._getReposUrl('test', 25),
+ '/projects/?n=26&S=0&query=test');
+
+ assert.equal(element._getReposUrl(null, 25),
+ `/projects/?n=26&S=0&query=${defaultQuery}`);
+
+ assert.equal(element._getReposUrl('test', 25, 25),
+ '/projects/?n=26&S=25&query=test');
+ });
+
+ test('invalidateReposCache', () => {
+ const url = '/projects/?n=26&S=0&query=test';
+
+ element._cache.set(url, {});
+
+ element.invalidateReposCache('test', 25);
+
+ assert.isUndefined(element._sharedFetchPromises[url]);
+
+ assert.isFalse(element._cache.has(url));
+ });
+
suite('getRepos', () => {
const defaultQuery = 'state%3Aactive%20OR%20state%3Aread-only';
@@ -990,11 +1027,57 @@
});
});
- test('getGroups filter regex', () => {
- sandbox.stub(element, '_fetchSharedCacheURL');
- element.getGroups('^test.*', 25);
- assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url,
- '/groups/?n=26&S=0&r=%5Etest.*');
+ test('_getGroupsUrl normal use', () => {
+ assert.equal(element._getGroupsUrl('test', 25),
+ '/groups/?n=26&S=0&m=test');
+
+ assert.equal(element._getGroupsUrl(null, 25),
+ '/groups/?n=26&S=0');
+
+ assert.equal(element._getGroupsUrl('test', 25, 25),
+ '/groups/?n=26&S=25&m=test');
+ });
+
+ test('invalidateGroupsCache', () => {
+ const url = '/groups/?n=26&S=0&m=test';
+
+ element._cache.set(url, {});
+
+ element.invalidateGroupsCache('test', 25);
+
+ assert.isUndefined(element._sharedFetchPromises[url]);
+
+ assert.isFalse(element._cache.has(url));
+ });
+
+ suite('getGroups', () => {
+ setup(() => {
+ sandbox.stub(element, '_fetchSharedCacheURL');
+ });
+
+ test('normal use', () => {
+ element.getGroups('test', 25);
+ assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url,
+ '/groups/?n=26&S=0&m=test');
+
+ element.getGroups(null, 25);
+ assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url,
+ '/groups/?n=26&S=0');
+
+ element.getGroups('test', 25, 25);
+ assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url,
+ '/groups/?n=26&S=25&m=test');
+ });
+
+ test('regex', () => {
+ element.getGroups('^test.*', 25);
+ assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url,
+ '/groups/?n=26&S=0&r=%5Etest.*');
+
+ element.getGroups('^test.*', 25, 25);
+ assert.equal(element._fetchSharedCacheURL.lastCall.args[0].url,
+ '/groups/?n=26&S=25&r=%5Etest.*');
+ });
});
test('gerrit auth is used', () => {