Replace AccountGeneralPreferences entity with git backend (phase 2)

Replace the usage of AccountGeneralPreferences with a different class
in extension API package.  Given that this is embedded entity in the
accounts table, only the columns are removed from the database, while
the accounts table itself is still preserved.

Bump database version, migrate the data from db to git and delete the
entity from the code.  As the consequence the following columns from
accounts table are removed:

size_bar_in_change_table
maximum_page_size
relative_date_in_change_table
use_flash_clipboard
legacycid_in_change_table
diff_view
mute_common_path_prefixes
email_strategy
show_site_header
download_command
download_url
date_format
time_format
review_category_strategy

Previously GET and PUT REST handlers for user preferences mixed db and
git operations because parts of the preferences (my menu entries and
URL aliases) were alreay stored in git backend. Now that the whole data
is stored in git backend, caching mechanism is needed to not degrade the
performance when retrieving the user preferences on the server side in
different use cases, like sending mail etc. Use Account entity for this
and extend AccountCache implementation to load general user preferences.

Download-commands plugin must be updated, as it references the old
entity.

Change-Id: I35311539f73e0f7baeaedff779bc44c2f5b133f8
This commit is contained in:
David Ostrovsky
2015-11-01 11:00:18 +01:00
committed by Saša Živkov
parent 25ffc14254
commit b06d2e33b2
15 changed files with 431 additions and 725 deletions

View File

@@ -28,10 +28,8 @@ import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.ReviewCategoryStrategy;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.TimeFormat;
import com.google.gerrit.extensions.client.MenuItem;
import com.google.gerrit.testutil.ConfigSuite;
import org.apache.http.HttpStatus;
import org.eclipse.jgit.lib.Config;
import org.junit.Before;
import org.junit.Test;
@@ -39,13 +37,6 @@ import java.util.ArrayList;
import java.util.HashMap;
public class GeneralPreferencesIT extends AbstractDaemonTest {
@ConfigSuite.Config
public static Config readFromGitConfig() {
Config cfg = new Config();
cfg.setBoolean("user", null, "readPrefsFromGit", true);
return cfg;
}
private TestAccount user42;
@Before

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.reviewdb.client;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_USERS;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gwtorm.client.Column;
import com.google.gwtorm.client.IntKey;
@@ -185,9 +186,7 @@ public final class Account {
// DELETED: id = 5 (contactFiledOn)
/** This user's preferences */
@Column(id = 6, name = Column.NONE)
protected AccountGeneralPreferences generalPreferences;
// DELETED: id = 6 (generalPreferences)
/** Is this user active */
@Column(id = 7)
@@ -196,6 +195,9 @@ public final class Account {
/** <i>computed</i> the username selected from the identities. */
protected String userName;
/** <i>stored in git, used for caching</i> the user's preferences. */
private GeneralPreferencesInfo generalPreferences;
protected Account() {
}
@@ -209,9 +211,6 @@ public final class Account {
public Account(Account.Id newId, Timestamp registeredOn) {
this.accountId = newId;
this.registeredOn = registeredOn;
generalPreferences = new AccountGeneralPreferences();
generalPreferences.resetToDefaults();
}
/** Get local id of this account, to link with in other entities */
@@ -291,11 +290,11 @@ public final class Account {
return registeredOn;
}
public AccountGeneralPreferences getGeneralPreferences() {
public GeneralPreferencesInfo getGeneralPreferencesInfo() {
return generalPreferences;
}
public void setGeneralPreferences(final AccountGeneralPreferences p) {
public void setGeneralPreferences(GeneralPreferencesInfo p) {
generalPreferences = p;
}

View File

@@ -1,361 +0,0 @@
// Copyright (C) 2008 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.reviewdb.client;
import com.google.gwtorm.client.Column;
/** Preferences about a single user. */
public final class AccountGeneralPreferences {
/** Default number of items to display per page. */
public static final short DEFAULT_PAGESIZE = 25;
/** Valid choices for the page size. */
public static final short[] PAGESIZE_CHOICES = {10, 25, 50, 100};
/** Preferred method to download a change. */
public static enum DownloadCommand {
REPO_DOWNLOAD, PULL, CHECKOUT, CHERRY_PICK, FORMAT_PATCH
}
public static enum DateFormat {
/** US style dates: Apr 27, Feb 14, 2010 */
STD("MMM d", "MMM d, yyyy"),
/** US style dates: 04/27, 02/14/10 */
US("MM/dd", "MM/dd/yy"),
/** ISO style dates: 2010-02-14 */
ISO("MM-dd", "yyyy-MM-dd"),
/** European style dates: 27. Apr, 27.04.2010 */
EURO("d. MMM", "dd.MM.yyyy"),
/** UK style dates: 27/04, 27/04/2010 */
UK("dd/MM", "dd/MM/yyyy");
private final String shortFormat;
private final String longFormat;
DateFormat(String shortFormat, String longFormat) {
this.shortFormat = shortFormat;
this.longFormat = longFormat;
}
public String getShortFormat() {
return shortFormat;
}
public String getLongFormat() {
return longFormat;
}
}
public static enum ReviewCategoryStrategy {
NONE,
NAME,
EMAIL,
USERNAME,
ABBREV
}
public static enum DiffView {
SIDE_BY_SIDE,
UNIFIED_DIFF
}
public static enum EmailStrategy {
ENABLED,
CC_ON_OWN_COMMENTS,
DISABLED
}
public static enum TimeFormat {
/** 12-hour clock: 1:15 am, 2:13 pm */
HHMM_12("h:mm a"),
/** 24-hour clock: 01:15, 14:13 */
HHMM_24("HH:mm");
private final String format;
TimeFormat(String format) {
this.format = format;
}
public String getFormat() {
return format;
}
}
public static AccountGeneralPreferences createDefault() {
AccountGeneralPreferences p = new AccountGeneralPreferences();
p.resetToDefaults();
return p;
}
/** Number of changes to show in a screen. */
@Column(id = 2)
protected short maximumPageSize;
/** Should the site header be displayed when logged in ? */
@Column(id = 3)
protected boolean showSiteHeader;
/** Should the Flash helper movie be used to copy text to the clipboard? */
@Column(id = 4)
protected boolean useFlashClipboard;
/** Type of download URL the user prefers to use. */
@Column(id = 5, length = 20, notNull = false)
protected String downloadUrl;
/** Type of download command the user prefers to use. */
@Column(id = 6, length = 20, notNull = false)
protected String downloadCommand;
// DELETED: id = 7 (copySelfOnEmail)
@Column(id = 8, length = 10, notNull = false)
protected String dateFormat;
@Column(id = 9, length = 10, notNull = false)
protected String timeFormat;
// DELETED: id = 10 (reversePatchSetOrder)
// DELETED: id = 11 (showUserInReview)
@Column(id = 12)
protected boolean relativeDateInChangeTable;
// DELETED: id = 13 (commentVisibilityStrategy)
@Column(id = 14, length = 20, notNull = false)
protected String diffView;
// DELETED: id = 15 (changeScreen)
@Column(id = 16)
protected boolean sizeBarInChangeTable;
@Column(id = 17)
protected boolean legacycidInChangeTable;
@Column(id = 18, length = 20, notNull = false)
protected String reviewCategoryStrategy;
@Column(id = 19)
protected boolean muteCommonPathPrefixes;
@Column(id = 20, length = 30, notNull = false)
protected String emailStrategy;
public AccountGeneralPreferences() {
}
public short getMaximumPageSize() {
return maximumPageSize;
}
public void setMaximumPageSize(final short s) {
maximumPageSize = s;
}
public boolean isShowSiteHeader() {
return showSiteHeader;
}
public void setShowSiteHeader(final boolean b) {
showSiteHeader = b;
}
public boolean isUseFlashClipboard() {
return useFlashClipboard;
}
public void setUseFlashClipboard(final boolean b) {
useFlashClipboard = b;
}
public String getDownloadUrl() {
// Translate from legacy enum names to modern display names. (May be removed
// if accompanied by a 2-phase schema upgrade.)
if (downloadUrl != null) {
switch (downloadUrl) {
case "ANON_GIT":
return CoreDownloadSchemes.ANON_GIT;
case "ANON_HTTP":
return CoreDownloadSchemes.ANON_HTTP;
case "HTTP":
return CoreDownloadSchemes.HTTP;
case "SSH":
return CoreDownloadSchemes.SSH;
case "REPO_DOWNLOAD":
return CoreDownloadSchemes.REPO_DOWNLOAD;
}
}
return downloadUrl;
}
public void setDownloadUrl(String url) {
// Translate from modern display names to legacy enum names. (May be removed
// if accompanied by a 2-phase schema upgrade.)
if (downloadUrl != null) {
switch (url) {
case CoreDownloadSchemes.ANON_GIT:
url = "ANON_GIT";
break;
case CoreDownloadSchemes.ANON_HTTP:
url = "ANON_HTTP";
break;
case CoreDownloadSchemes.HTTP:
url = "HTTP";
break;
case CoreDownloadSchemes.SSH:
url = "SSH";
break;
case CoreDownloadSchemes.REPO_DOWNLOAD:
url = "REPO_DOWNLOAD";
break;
}
}
downloadUrl = url;
}
public DownloadCommand getDownloadCommand() {
if (downloadCommand == null) {
return null;
}
return DownloadCommand.valueOf(downloadCommand);
}
public void setDownloadCommand(DownloadCommand cmd) {
if (cmd != null) {
downloadCommand = cmd.name();
} else {
downloadCommand = null;
}
}
public boolean isShowInfoInReviewCategory() {
return getReviewCategoryStrategy() != ReviewCategoryStrategy.NONE;
}
public DateFormat getDateFormat() {
if (dateFormat == null) {
return DateFormat.STD;
}
return DateFormat.valueOf(dateFormat);
}
public void setDateFormat(DateFormat fmt) {
dateFormat = fmt.name();
}
public TimeFormat getTimeFormat() {
if (timeFormat == null) {
return TimeFormat.HHMM_12;
}
return TimeFormat.valueOf(timeFormat);
}
public void setTimeFormat(TimeFormat fmt) {
timeFormat = fmt.name();
}
public boolean isRelativeDateInChangeTable() {
return relativeDateInChangeTable;
}
public void setRelativeDateInChangeTable(final boolean relativeDateInChangeTable) {
this.relativeDateInChangeTable = relativeDateInChangeTable;
}
public ReviewCategoryStrategy getReviewCategoryStrategy() {
if (reviewCategoryStrategy == null) {
return ReviewCategoryStrategy.NONE;
}
return ReviewCategoryStrategy.valueOf(reviewCategoryStrategy);
}
public void setReviewCategoryStrategy(
ReviewCategoryStrategy strategy) {
reviewCategoryStrategy = strategy.name();
}
public DiffView getDiffView() {
if (diffView == null) {
return DiffView.SIDE_BY_SIDE;
}
return DiffView.valueOf(diffView);
}
public void setDiffView(DiffView diffView) {
this.diffView = diffView.name();
}
public EmailStrategy getEmailStrategy() {
if (emailStrategy == null) {
return EmailStrategy.ENABLED;
}
return EmailStrategy.valueOf(emailStrategy);
}
public void setEmailStrategy(EmailStrategy strategy) {
this.emailStrategy = strategy.name();
}
public boolean isSizeBarInChangeTable() {
return sizeBarInChangeTable;
}
public void setSizeBarInChangeTable(boolean sizeBarInChangeTable) {
this.sizeBarInChangeTable = sizeBarInChangeTable;
}
public boolean isLegacycidInChangeTable() {
return legacycidInChangeTable;
}
public void setLegacycidInChangeTable(boolean legacycidInChangeTable) {
this.legacycidInChangeTable = legacycidInChangeTable;
}
public boolean isMuteCommonPathPrefixes() {
return muteCommonPathPrefixes;
}
public void setMuteCommonPathPrefixes(
boolean muteCommonPathPrefixes) {
this.muteCommonPathPrefixes = muteCommonPathPrefixes;
}
public void resetToDefaults() {
maximumPageSize = DEFAULT_PAGESIZE;
showSiteHeader = true;
useFlashClipboard = true;
reviewCategoryStrategy = null;
downloadUrl = null;
downloadCommand = null;
dateFormat = null;
timeFormat = null;
relativeDateInChangeTable = false;
diffView = null;
sizeBarInChangeTable = true;
legacycidInChangeTable = false;
muteCommonPathPrefixes = true;
emailStrategy = null;
}
}

View File

@@ -19,6 +19,7 @@ import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountExternalId;
import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -33,9 +34,11 @@ import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -130,13 +133,18 @@ public class AccountCacheImpl implements AccountCache {
static class ByIdLoader extends CacheLoader<Account.Id, AccountState> {
private final SchemaFactory<ReviewDb> schema;
private final GroupCache groupCache;
private final GeneralPreferencesLoader loader;
private final LoadingCache<String, Optional<Account.Id>> byName;
@Inject
ByIdLoader(SchemaFactory<ReviewDb> sf, GroupCache groupCache,
@Named(BYUSER_NAME) LoadingCache<String, Optional<Account.Id>> byUsername) {
ByIdLoader(SchemaFactory<ReviewDb> sf,
GroupCache groupCache,
GeneralPreferencesLoader loader,
@Named(BYUSER_NAME) LoadingCache<String,
Optional<Account.Id>> byUsername) {
this.schema = sf;
this.groupCache = groupCache;
this.loader = loader;
this.byName = byUsername;
}
@@ -175,6 +183,14 @@ public class AccountCacheImpl implements AccountCache {
}
internalGroups = Collections.unmodifiableSet(internalGroups);
try {
account.setGeneralPreferences(loader.load(who));
} catch (IOException | ConfigInvalidException e) {
log.warn("Cannot load GeneralPreferences for " + who +
" (using default)", e);
account.setGeneralPreferences(GeneralPreferencesInfo.defaults());
}
return new AccountState(account, internalGroups, externalIds);
}
}

View File

@@ -0,0 +1,148 @@
// Copyright (C) 2015 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.account;
import static com.google.gerrit.server.config.ConfigUtil.loadSection;
import static com.google.gerrit.server.git.UserConfigSections.KEY_ID;
import static com.google.gerrit.server.git.UserConfigSections.KEY_MATCH;
import static com.google.gerrit.server.git.UserConfigSections.KEY_TARGET;
import static com.google.gerrit.server.git.UserConfigSections.KEY_TOKEN;
import static com.google.gerrit.server.git.UserConfigSections.KEY_URL;
import static com.google.gerrit.server.git.UserConfigSections.URL_ALIAS;
import com.google.common.base.Strings;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.client.MenuItem;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.UserConfigSections;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Singleton
public class GeneralPreferencesLoader {
private static final Logger log =
LoggerFactory.getLogger(GeneralPreferencesLoader.class);
private final GitRepositoryManager gitMgr;
private final AllUsersName allUsersName;
@Inject
public GeneralPreferencesLoader(GitRepositoryManager gitMgr,
AllUsersName allUsersName) {
this.gitMgr = gitMgr;
this.allUsersName = allUsersName;
}
public GeneralPreferencesInfo load(Account.Id id)
throws IOException, ConfigInvalidException, RepositoryNotFoundException {
return read(id, null);
}
public GeneralPreferencesInfo merge(Account.Id id,
GeneralPreferencesInfo in) throws IOException,
ConfigInvalidException, RepositoryNotFoundException {
return read(id, in);
}
private GeneralPreferencesInfo read(Account.Id id,
GeneralPreferencesInfo in) throws IOException,
ConfigInvalidException, RepositoryNotFoundException {
try (Repository allUsers = gitMgr.openRepository(allUsersName)) {
VersionedAccountPreferences p =
VersionedAccountPreferences.forUser(id);
p.load(allUsers);
GeneralPreferencesInfo r =
loadSection(p.getConfig(), UserConfigSections.GENERAL, null,
new GeneralPreferencesInfo(),
GeneralPreferencesInfo.defaults(), in);
return loadFromAllUsers(r, p, allUsers);
}
}
public GeneralPreferencesInfo loadFromAllUsers(
GeneralPreferencesInfo r, VersionedAccountPreferences v,
Repository allUsers) {
r.my = my(v);
if (r.my.isEmpty() && !v.isDefaults()) {
try {
VersionedAccountPreferences d = VersionedAccountPreferences.forDefault();
d.load(allUsers);
r.my = my(d);
} catch (ConfigInvalidException | IOException e) {
log.warn("cannot read default preferences", e);
}
}
if (r.my.isEmpty()) {
r.my.add(new MenuItem("Changes", "#/dashboard/self", null));
r.my.add(new MenuItem("Drafts", "#/q/owner:self+is:draft", null));
r.my.add(new MenuItem("Draft Comments", "#/q/has:draft", null));
r.my.add(new MenuItem("Edits", "#/q/has:edit", null));
r.my.add(new MenuItem("Watched Changes", "#/q/is:watched+is:open",
null));
r.my.add(new MenuItem("Starred Changes", "#/q/is:starred", null));
r.my.add(new MenuItem("Groups", "#/groups/self", null));
}
r.urlAliases = urlAliases(v);
return r;
}
private static List<MenuItem> my(VersionedAccountPreferences v) {
List<MenuItem> my = new ArrayList<>();
Config cfg = v.getConfig();
for (String subsection : cfg.getSubsections(UserConfigSections.MY)) {
String url = my(cfg, subsection, KEY_URL, "#/");
String target = my(cfg, subsection, KEY_TARGET,
url.startsWith("#") ? null : "_blank");
my.add(new MenuItem(
subsection, url, target,
my(cfg, subsection, KEY_ID, null)));
}
return my;
}
private static String my(Config cfg, String subsection, String key,
String defaultValue) {
String val = cfg.getString(UserConfigSections.MY, subsection, key);
return !Strings.isNullOrEmpty(val) ? val : defaultValue;
}
private static Map<String, String> urlAliases(VersionedAccountPreferences v) {
HashMap<String, String> urlAliases = new HashMap<>();
Config cfg = v.getConfig();
for (String subsection : cfg.getSubsections(URL_ALIAS)) {
urlAliases.put(cfg.getString(URL_ALIAS, subsection, KEY_MATCH),
cfg.getString(URL_ALIAS, subsection, KEY_TOKEN));
}
return !urlAliases.isEmpty() ? urlAliases : null;
}
}

View File

@@ -14,74 +14,31 @@
package com.google.gerrit.server.account;
import static com.google.gerrit.server.config.ConfigUtil.loadSection;
import com.google.common.base.Strings;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DateFormat;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DownloadCommand;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.ReviewCategoryStrategy;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.TimeFormat;
import com.google.gerrit.extensions.client.MenuItem;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.UserConfigSections;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Singleton
public class GetPreferences implements RestReadView<AccountResource> {
private static final Logger log = LoggerFactory.getLogger(GetPreferences.class);
public static final String KEY_URL = "url";
public static final String KEY_TARGET = "target";
public static final String KEY_ID = "id";
public static final String URL_ALIAS = "urlAlias";
public static final String KEY_MATCH = "match";
public static final String KEY_TOKEN = "token";
private final Provider<CurrentUser> self;
private final Provider<ReviewDb> db;
private final AllUsersName allUsersName;
private final GitRepositoryManager gitMgr;
private final boolean readFromGit;
private final AccountCache accountCache;
@Inject
GetPreferences(Provider<CurrentUser> self,
@GerritServerConfig Config cfg,
Provider<ReviewDb> db,
AllUsersName allUsersName,
GitRepositoryManager gitMgr) {
AccountCache accountCache) {
this.self = self;
this.db = db;
this.allUsersName = allUsersName;
this.gitMgr = gitMgr;
readFromGit = cfg.getBoolean("user", null, "readPrefsFromGit", false);
this.accountCache = accountCache;
}
@Override
@@ -93,145 +50,7 @@ public class GetPreferences implements RestReadView<AccountResource> {
throw new AuthException("requires Modify Account capability");
}
Account.Id accountId = rsrc.getUser().getAccountId();
return readFromGit
? readFromGit(accountId, gitMgr, allUsersName, null)
: readFromDb(accountId);
}
private GeneralPreferencesInfo readFromDb(Account.Id accountId)
throws IOException, ConfigInvalidException, RepositoryNotFoundException,
OrmException {
Account a = db.get().accounts().get(accountId);
GeneralPreferencesInfo r = nullify(initFromDb(
a.getGeneralPreferences()));
try (Repository allUsers = gitMgr.openRepository(allUsersName)) {
VersionedAccountPreferences p =
VersionedAccountPreferences.forUser(accountId);
p.load(allUsers);
return loadFromAllUsers(r, p, allUsers);
}
}
public static GeneralPreferencesInfo readFromGit(Account.Id id,
GitRepositoryManager gitMgr, AllUsersName allUsersName,
GeneralPreferencesInfo in) throws IOException,
ConfigInvalidException, RepositoryNotFoundException {
try (Repository allUsers = gitMgr.openRepository(allUsersName)) {
VersionedAccountPreferences p =
VersionedAccountPreferences.forUser(id);
p.load(allUsers);
GeneralPreferencesInfo r =
loadSection(p.getConfig(), UserConfigSections.GENERAL, null,
new GeneralPreferencesInfo(),
GeneralPreferencesInfo.defaults(), in);
return loadFromAllUsers(r, p, allUsers);
}
}
public static GeneralPreferencesInfo loadFromAllUsers(
GeneralPreferencesInfo r, VersionedAccountPreferences v,
Repository allUsers) {
r.my = my(v);
if (r.my.isEmpty() && !v.isDefaults()) {
try {
VersionedAccountPreferences d = VersionedAccountPreferences.forDefault();
d.load(allUsers);
r.my = my(d);
} catch (ConfigInvalidException | IOException e) {
log.warn("cannot read default preferences", e);
}
}
if (r.my.isEmpty()) {
r.my.add(new MenuItem("Changes", "#/dashboard/self", null));
r.my.add(new MenuItem("Drafts", "#/q/owner:self+is:draft", null));
r.my.add(new MenuItem("Draft Comments", "#/q/has:draft", null));
r.my.add(new MenuItem("Edits", "#/q/has:edit", null));
r.my.add(new MenuItem("Watched Changes", "#/q/is:watched+is:open",
null));
r.my.add(new MenuItem("Starred Changes", "#/q/is:starred", null));
r.my.add(new MenuItem("Groups", "#/groups/self", null));
}
r.urlAliases = urlAliases(v);
return r;
}
private static List<MenuItem> my(VersionedAccountPreferences v) {
List<MenuItem> my = new ArrayList<>();
Config cfg = v.getConfig();
for (String subsection : cfg.getSubsections(UserConfigSections.MY)) {
String url = my(cfg, subsection, KEY_URL, "#/");
String target = my(cfg, subsection, KEY_TARGET,
url.startsWith("#") ? null : "_blank");
my.add(new MenuItem(
subsection, url, target,
my(cfg, subsection, KEY_ID, null)));
}
return my;
}
private static String my(Config cfg, String subsection, String key,
String defaultValue) {
String val = cfg.getString(UserConfigSections.MY, subsection, key);
return !Strings.isNullOrEmpty(val) ? val : defaultValue;
}
private static Map<String, String> urlAliases(VersionedAccountPreferences v) {
HashMap<String, String> urlAliases = new HashMap<>();
Config cfg = v.getConfig();
for (String subsection : cfg.getSubsections(URL_ALIAS)) {
urlAliases.put(cfg.getString(URL_ALIAS, subsection, KEY_MATCH),
cfg.getString(URL_ALIAS, subsection, KEY_TOKEN));
}
return !urlAliases.isEmpty() ? urlAliases : null;
}
static GeneralPreferencesInfo initFromDb(AccountGeneralPreferences a) {
GeneralPreferencesInfo p = GeneralPreferencesInfo.defaults();
if (a != null) {
p.changesPerPage = (int)a.getMaximumPageSize();
p.showSiteHeader = a.isShowSiteHeader();
p.useFlashClipboard = a.isUseFlashClipboard();
p.downloadScheme = a.getDownloadUrl();
if (a.getDownloadCommand() != null) {
p.downloadCommand = DownloadCommand.valueOf(
a.getDownloadCommand().name());
}
p.emailStrategy = EmailStrategy.valueOf(a.getEmailStrategy().name());
p.dateFormat = DateFormat.valueOf(a.getDateFormat().name());
p.timeFormat = TimeFormat.valueOf(a.getTimeFormat().name());
p.relativeDateInChangeTable = a.isRelativeDateInChangeTable();
p.sizeBarInChangeTable = a.isSizeBarInChangeTable();
p.legacycidInChangeTable = a.isLegacycidInChangeTable();
p.muteCommonPathPrefixes = a.isMuteCommonPathPrefixes();
p.reviewCategoryStrategy = ReviewCategoryStrategy.valueOf(
a.getReviewCategoryStrategy().name());
p.diffView = DiffView.valueOf(a.getDiffView().name());
}
return p;
}
private static GeneralPreferencesInfo nullify(
GeneralPreferencesInfo p) {
p.showSiteHeader = b(p.showSiteHeader);
p.useFlashClipboard = b(p.useFlashClipboard);
p.relativeDateInChangeTable = b(p.relativeDateInChangeTable);
p.legacycidInChangeTable = b(p.legacycidInChangeTable);
p.muteCommonPathPrefixes = b(p.muteCommonPathPrefixes);
p.sizeBarInChangeTable = b(p.sizeBarInChangeTable);
return p;
}
private static Boolean b(Boolean b) {
if (b == null) {
return null;
}
return b ? Boolean.TRUE : null;
Account.Id id = rsrc.getUser().getAccountId();
return accountCache.get(id).getAccount().getGeneralPreferencesInfo();
}
}

View File

@@ -14,15 +14,13 @@
package com.google.gerrit.server.account;
import static com.google.gerrit.server.account.GetPreferences.KEY_ID;
import static com.google.gerrit.server.account.GetPreferences.KEY_MATCH;
import static com.google.gerrit.server.account.GetPreferences.KEY_TARGET;
import static com.google.gerrit.server.account.GetPreferences.KEY_TOKEN;
import static com.google.gerrit.server.account.GetPreferences.KEY_URL;
import static com.google.gerrit.server.account.GetPreferences.URL_ALIAS;
import static com.google.gerrit.server.account.GetPreferences.initFromDb;
import static com.google.gerrit.server.account.GetPreferences.readFromGit;
import static com.google.gerrit.server.config.ConfigUtil.storeSection;
import static com.google.gerrit.server.git.UserConfigSections.KEY_ID;
import static com.google.gerrit.server.git.UserConfigSections.KEY_MATCH;
import static com.google.gerrit.server.git.UserConfigSections.KEY_TARGET;
import static com.google.gerrit.server.git.UserConfigSections.KEY_TOKEN;
import static com.google.gerrit.server.git.UserConfigSections.KEY_URL;
import static com.google.gerrit.server.git.UserConfigSections.URL_ALIAS;
import com.google.common.base.Strings;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
@@ -34,18 +32,8 @@ import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DateFormat;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DiffView;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.EmailStrategy;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.ReviewCategoryStrategy;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.TimeFormat;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.UserConfigSections;
import com.google.gwtorm.server.OrmException;
@@ -58,7 +46,6 @@ import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -68,30 +55,24 @@ public class SetPreferences implements
RestModifyView<AccountResource, GeneralPreferencesInfo> {
private final Provider<CurrentUser> self;
private final AccountCache cache;
private final GitRepositoryManager gitMgr;
private final Provider<ReviewDb> db;
private final GeneralPreferencesLoader loader;
private final Provider<MetaDataUpdate.User> metaDataUpdateFactory;
private final AllUsersName allUsersName;
private final DynamicMap<DownloadScheme> downloadSchemes;
private final boolean readFromGit;
@Inject
SetPreferences(Provider<CurrentUser> self,
AccountCache cache,
@GerritServerConfig Config cfg,
GitRepositoryManager gitMgr,
Provider<ReviewDb> db,
GeneralPreferencesLoader loader,
Provider<MetaDataUpdate.User> metaDataUpdateFactory,
AllUsersName allUsersName,
DynamicMap<DownloadScheme> downloadSchemes) {
this.self = self;
this.loader = loader;
this.cache = cache;
this.gitMgr = gitMgr;
this.db = db;
this.metaDataUpdateFactory = metaDataUpdateFactory;
this.allUsersName = allUsersName;
this.downloadSchemes = downloadSchemes;
readFromGit = cfg.getBoolean("user", null, "readPrefsFromGit", false);
}
@Override
@@ -106,19 +87,14 @@ public class SetPreferences implements
checkDownloadScheme(i.downloadScheme);
Account.Id id = rsrc.getUser().getAccountId();
GeneralPreferencesInfo n = readFromGit
? readFromGit(id, gitMgr, allUsersName, i)
: merge(initFromDb(
db.get().accounts().get(id).getGeneralPreferences()), i);
GeneralPreferencesInfo n = loader.merge(id, i);
n.my = i.my;
n.urlAliases = i.urlAliases;
writeToGit(id, n);
writeToDb(id, n);
cache.evict(id);
return GetPreferences.readFromGit(id, gitMgr, allUsersName, null);
return cache.get(id).getAccount().getGeneralPreferencesInfo();
}
private void writeToGit(Account.Id id, GeneralPreferencesInfo i)
@@ -134,36 +110,7 @@ public class SetPreferences implements
storeMyMenus(prefs, i.my);
storeUrlAliases(prefs, i.urlAliases);
prefs.commit(md);
}
}
private void writeToDb(Account.Id id, GeneralPreferencesInfo i)
throws RepositoryNotFoundException, IOException, OrmException,
ConfigInvalidException {
MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsersName);
db.get().accounts().beginTransaction(id);
try {
Account a = db.get().accounts().get(id);
VersionedAccountPreferences versionedPrefs =
VersionedAccountPreferences.forUser(id);
versionedPrefs.load(md);
AccountGeneralPreferences p = a.getGeneralPreferences();
if (p == null) {
p = new AccountGeneralPreferences();
a.setGeneralPreferences(p);
}
initAccountGeneralPreferences(p, i);
db.get().accounts().update(Collections.singleton(a));
db.get().commit();
storeMyMenus(versionedPrefs, i.my);
storeUrlAliases(versionedPrefs, i.urlAliases);
versionedPrefs.commit(md);
} finally {
db.get().rollback();
cache.evict(id);
}
}
@@ -227,81 +174,4 @@ public class SetPreferences implements
throw new BadRequestException(
"Unsupported download scheme: " + downloadScheme);
}
private GeneralPreferencesInfo merge(GeneralPreferencesInfo p,
GeneralPreferencesInfo i) {
if (i.changesPerPage != null) {
p.changesPerPage = i.changesPerPage;
}
if (i.showSiteHeader != null) {
p.showSiteHeader = i.showSiteHeader;
}
if (i.useFlashClipboard != null) {
p.useFlashClipboard = i.useFlashClipboard;
}
if (i.downloadScheme != null) {
p.downloadScheme = i.downloadScheme;
}
if (i.downloadCommand != null) {
p.downloadCommand = i.downloadCommand;
}
if (i.dateFormat != null) {
p.dateFormat = i.dateFormat;
}
if (i.timeFormat != null) {
p.timeFormat = i.timeFormat;
}
if (i.relativeDateInChangeTable != null) {
p.relativeDateInChangeTable = i.relativeDateInChangeTable;
}
if (i.sizeBarInChangeTable != null) {
p.sizeBarInChangeTable = i.sizeBarInChangeTable;
}
if (i.legacycidInChangeTable != null) {
p.legacycidInChangeTable = i.legacycidInChangeTable;
}
if (i.muteCommonPathPrefixes != null) {
p.muteCommonPathPrefixes = i.muteCommonPathPrefixes;
}
if (i.reviewCategoryStrategy != null) {
p.reviewCategoryStrategy = i.reviewCategoryStrategy;
}
if (i.diffView != null) {
p.diffView = i.diffView;
}
if (i.emailStrategy != null) {
p.emailStrategy = i.emailStrategy;
}
return p;
}
private static void initAccountGeneralPreferences(
AccountGeneralPreferences a, GeneralPreferencesInfo i) {
if (a == null) {
a = AccountGeneralPreferences.createDefault();
}
a.setMaximumPageSize((short)(int)i.changesPerPage);
a.setShowSiteHeader(b(i.showSiteHeader));
a.setUseFlashClipboard(b(i.useFlashClipboard));
a.setDownloadUrl(i.downloadScheme);
if (i.downloadCommand != null) {
a.setDownloadCommand(DownloadCommand.valueOf(i.downloadCommand.name()));
}
a.setEmailStrategy(EmailStrategy.valueOf(i.getEmailStrategy().name()));
a.setDateFormat(DateFormat.valueOf(i.getDateFormat().name()));
a.setTimeFormat(TimeFormat.valueOf(i.getTimeFormat().name()));
a.setRelativeDateInChangeTable(b(i.relativeDateInChangeTable));
a.setSizeBarInChangeTable(b(i.sizeBarInChangeTable));
a.setLegacycidInChangeTable(b(i.legacycidInChangeTable));
a.setMuteCommonPathPrefixes(b(i.muteCommonPathPrefixes));
a.setReviewCategoryStrategy(ReviewCategoryStrategy.valueOf(
i.getReviewCategoryStrategy().name()));
a.setDiffView(DiffView.valueOf(i.getDiffView().name()));
}
private static boolean b(Boolean b) {
return b == null ? false : b;
}
}

View File

@@ -15,7 +15,7 @@
package com.google.gerrit.server.config;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DownloadCommand;
import com.google.gerrit.reviewdb.client.CoreDownloadSchemes;
import com.google.gerrit.server.change.ArchiveFormat;
import com.google.inject.Inject;

View File

@@ -14,10 +14,9 @@
package com.google.gerrit.server.config;
import static com.google.gerrit.server.account.GetPreferences.loadFromAllUsers;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.account.GeneralPreferencesLoader;
import com.google.gerrit.server.account.VersionedAccountPreferences;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
@@ -30,14 +29,17 @@ import java.io.IOException;
@Singleton
public class GetPreferences implements RestReadView<ConfigResource> {
private final AllUsersName allUsersName;
private GeneralPreferencesLoader loader;
private final GitRepositoryManager gitMgr;
private final AllUsersName allUsersName;
@Inject
public GetPreferences(AllUsersName allUsersName,
GitRepositoryManager gitMgr) {
this.allUsersName = allUsersName;
public GetPreferences(GeneralPreferencesLoader loader,
GitRepositoryManager gitMgr,
AllUsersName allUsersName) {
this.loader = loader;
this.gitMgr = gitMgr;
this.allUsersName = allUsersName;
}
@Override
@@ -49,7 +51,8 @@ public class GetPreferences implements RestReadView<ConfigResource> {
p.load(git);
GeneralPreferencesInfo a = new GeneralPreferencesInfo();
return loadFromAllUsers(a, p, git);
// TODO(davido): Maintain cache of default values in AllUsers repository
return loader.loadFromAllUsers(a, p, git);
}
}
}

View File

@@ -14,13 +14,12 @@
package com.google.gerrit.server.config;
import static com.google.gerrit.server.account.GetPreferences.loadFromAllUsers;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.account.GeneralPreferencesLoader;
import com.google.gerrit.server.account.VersionedAccountPreferences;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.inject.Inject;
@@ -35,12 +34,15 @@ import java.io.IOException;
@Singleton
public class SetPreferences implements
RestModifyView<ConfigResource, GeneralPreferencesInfo> {
private final GeneralPreferencesLoader loader;
private final Provider<MetaDataUpdate.User> metaDataUpdateFactory;
private final AllUsersName allUsersName;
@Inject
SetPreferences(Provider<MetaDataUpdate.User> metaDataUpdateFactory,
SetPreferences(GeneralPreferencesLoader loader,
Provider<MetaDataUpdate.User> metaDataUpdateFactory,
AllUsersName allUsersName) {
this.loader = loader;
this.metaDataUpdateFactory = metaDataUpdateFactory;
this.allUsersName = allUsersName;
}
@@ -70,7 +72,7 @@ public class SetPreferences implements
p.commit(md);
GeneralPreferencesInfo a = new GeneralPreferencesInfo();
return loadFromAllUsers(a, p, md.getRepository());
return loader.loadFromAllUsers(a, p, md.getRepository());
}
}
}

View File

@@ -22,6 +22,13 @@ public class UserConfigSections {
/** The my menu user preferences. */
public static final String MY = "my";
public static final String KEY_URL = "url";
public static final String KEY_TARGET = "target";
public static final String KEY_ID = "id";
public static final String URL_ALIAS = "urlAlias";
public static final String KEY_MATCH = "match";
public static final String KEY_TOKEN = "token";
/** The edit user preferences. */
public static final String EDIT = "edit";

View File

@@ -19,8 +19,8 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.Sets;
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.EmailStrategy;
import com.google.gerrit.reviewdb.client.UserIdentity;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.mail.EmailHeader.AddressList;
@@ -107,7 +107,7 @@ public abstract class OutgoingEmail {
if (fromId != null) {
final Account fromUser = args.accountCache.get(fromId).getAccount();
EmailStrategy strategy =
fromUser.getGeneralPreferences().getEmailStrategy();
fromUser.getGeneralPreferencesInfo().getEmailStrategy();
if (strategy == EmailStrategy.CC_ON_OWN_COMMENTS) {
// If we are impersonating a user, make sure they receive a CC of
@@ -126,7 +126,7 @@ public abstract class OutgoingEmail {
// his email notifications then drop him from recipients' list
for (Account.Id id : rcptTo) {
Account thisUser = args.accountCache.get(id).getAccount();
if (thisUser.getGeneralPreferences().getEmailStrategy()
if (thisUser.getGeneralPreferencesInfo().getEmailStrategy()
== EmailStrategy.DISABLED) {
removeUser(thisUser);
}

View File

@@ -32,7 +32,7 @@ import java.util.List;
/** A version of the database schema. */
public abstract class SchemaVersion {
/** The current schema version. */
public static final Class<Schema_118> C = Schema_118.class;
public static final Class<Schema_119> C = Schema_119.class;
public static int getBinaryVersion() {
return guessVersion(C);

View File

@@ -0,0 +1,212 @@
// Copyright (C) 2015 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.schema;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.ANON_GIT;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.ANON_HTTP;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.HTTP;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.REPO_DOWNLOAD;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.SSH;
import static com.google.gerrit.server.config.ConfigUtil.storeSection;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DateFormat;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DownloadCommand;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.ReviewCategoryStrategy;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.TimeFormat;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.VersionedAccountPreferences;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.UserConfigSections;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
public class Schema_119 extends SchemaVersion {
private static final Map<String, String> LEGACY_DISPLAYNAME_MAP =
ImmutableMap.<String, String> of(
"ANON_GIT", ANON_GIT,
"ANON_HTTP", ANON_HTTP,
"HTTP", HTTP,
"SSH", SSH,
"REPO_DOWNLOAD", REPO_DOWNLOAD);
private final GitRepositoryManager mgr;
private final AllUsersName allUsersName;
private final PersonIdent serverUser;
@Inject
Schema_119(Provider<Schema_118> prior,
GitRepositoryManager mgr,
AllUsersName allUsersName,
@GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.mgr = mgr;
this.allUsersName = allUsersName;
this.serverUser = serverUser;
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui)
throws OrmException, SQLException {
Map<Account.Id, GeneralPreferencesInfo> imports = new HashMap<>();
try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
ResultSet rs = stmt.executeQuery(
"select "
+ "account_id, "
+ "maximum_page_size, "
+ "show_site_header, "
+ "use_flash_clipboard, "
+ "download_url, "
+ "download_command, "
+ "email_strategy, "
+ "date_format, "
+ "time_format, "
+ "relative_date_in_change_table, "
+ "diff_view, "
+ "size_bar_in_change_table, "
+ "legacycid_in_change_table, "
+ "review_category_strategy, "
+ "mute_common_path_prefixes "
+ "from accounts")) {
while (rs.next()) {
GeneralPreferencesInfo p =
new GeneralPreferencesInfo();
Account.Id accountId = new Account.Id(rs.getInt(1));
p.changesPerPage = (int)rs.getShort(2);
p.showSiteHeader = toBoolean(rs.getString(3));
p.useFlashClipboard = toBoolean(rs.getString(4));
p.downloadScheme = convertToModernNames(rs.getString(5));
p.downloadCommand = toDownloadCommand(rs.getString(6));
p.emailStrategy = toEmailStrategy(rs.getString(7));
p.dateFormat = toDateFormat(rs.getString(8));
p.timeFormat = toTimeFormat(rs.getString(9));
p.relativeDateInChangeTable = toBoolean(rs.getString(10));
p.diffView = toDiffView(rs.getString(11));
p.sizeBarInChangeTable = toBoolean(rs.getString(12));
p.legacycidInChangeTable = toBoolean(rs.getString(13));
p.reviewCategoryStrategy =
toReviewCategoryStrategy(rs.getString(14));
p.muteCommonPathPrefixes = toBoolean(rs.getString(15));
imports.put(accountId, p);
}
}
if (imports.isEmpty()) {
return;
}
try (Repository git = mgr.openRepository(allUsersName);
RevWalk rw = new RevWalk(git)) {
BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
for (Map.Entry<Account.Id, GeneralPreferencesInfo> e
: imports.entrySet()) {
try(MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED,
allUsersName, git, bru)) {
md.getCommitBuilder().setAuthor(serverUser);
md.getCommitBuilder().setCommitter(serverUser);
VersionedAccountPreferences p =
VersionedAccountPreferences.forUser(e.getKey());
p.load(md);
storeSection(p.getConfig(), UserConfigSections.GENERAL, null,
e.getValue(), GeneralPreferencesInfo.defaults());
p.commit(md);
}
}
bru.execute(rw, NullProgressMonitor.INSTANCE);
} catch (ConfigInvalidException | IOException ex) {
throw new OrmException(ex);
}
}
private String convertToModernNames(String s) {
return !Strings.isNullOrEmpty(s) && LEGACY_DISPLAYNAME_MAP.containsKey(s)
? LEGACY_DISPLAYNAME_MAP.get(s)
: s;
}
private static DownloadCommand toDownloadCommand(String v) {
if (v == null) {
return DownloadCommand.CHECKOUT;
}
return DownloadCommand.valueOf(v);
}
private static DateFormat toDateFormat(String v) {
if (v == null) {
return DateFormat.STD;
}
return DateFormat.valueOf(v);
}
private static TimeFormat toTimeFormat(String v) {
if (v == null) {
return TimeFormat.HHMM_12;
}
return TimeFormat.valueOf(v);
}
private static DiffView toDiffView(String v) {
if (v == null) {
return DiffView.SIDE_BY_SIDE;
}
return DiffView.valueOf(v);
}
private static EmailStrategy toEmailStrategy(String v) {
if (v == null) {
return EmailStrategy.ENABLED;
}
return EmailStrategy.valueOf(v);
}
private static ReviewCategoryStrategy toReviewCategoryStrategy(String v) {
if (v == null) {
return ReviewCategoryStrategy.NONE;
}
return ReviewCategoryStrategy.valueOf(v);
}
private static boolean toBoolean(String v) {
Preconditions.checkState(!Strings.isNullOrEmpty(v));
return v.equals("Y");
}
}