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
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/GeneralPreferencesIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/GeneralPreferencesIT.java index e81ee71..b9a984b 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/GeneralPreferencesIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/GeneralPreferencesIT.java
@@ -28,10 +28,8 @@ 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.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
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java index 2bb6702..08b9d23 100644 --- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java +++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
@@ -16,6 +16,7 @@ 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 @@ // 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 @@ /** <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 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 @@ return registeredOn; } - public AccountGeneralPreferences getGeneralPreferences() { + public GeneralPreferencesInfo getGeneralPreferencesInfo() { return generalPreferences; } - public void setGeneralPreferences(final AccountGeneralPreferences p) { + public void setGeneralPreferences(GeneralPreferencesInfo p) { generalPreferences = p; }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java deleted file mode 100644 index 83a6ca8..0000000 --- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java +++ /dev/null
@@ -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; - } -}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java index bedd9f1..1e06faa 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
@@ -19,6 +19,7 @@ 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.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 @@ 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 @@ } 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); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GeneralPreferencesLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GeneralPreferencesLoader.java new file mode 100644 index 0000000..a7dba1a --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GeneralPreferencesLoader.java
@@ -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; + } +}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetPreferences.java index facc2ec..064cb2f 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetPreferences.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetPreferences.java
@@ -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 @@ 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(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java index 3f1feb4..c077182 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
@@ -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.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.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 @@ 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 @@ 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 @@ 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 @@ 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; - } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadConfig.java index f435a2b..c1c5910 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadConfig.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadConfig.java
@@ -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;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetPreferences.java index 5158abd..615b4ca 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetPreferences.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetPreferences.java
@@ -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 @@ @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 @@ 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); } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/SetPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/SetPreferences.java index 12c0f8d..4c5ab65 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/SetPreferences.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/SetPreferences.java
@@ -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 @@ @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 @@ p.commit(md); GeneralPreferencesInfo a = new GeneralPreferencesInfo(); - return loadFromAllUsers(a, p, md.getRepository()); + return loader.loadFromAllUsers(a, p, md.getRepository()); } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/UserConfigSections.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/UserConfigSections.java index 78431ba..a09466d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/UserConfigSections.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/UserConfigSections.java
@@ -22,6 +22,13 @@ /** 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";
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java index 6d7b506..d29710e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java
@@ -19,8 +19,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 @@ 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 @@ // 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); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java index dc2a02b..310cae8 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
@@ -32,7 +32,7 @@ /** 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);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_119.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_119.java new file mode 100644 index 0000000..6fc7c83 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_119.java
@@ -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"); + } +}
diff --git a/plugins/download-commands b/plugins/download-commands index 8707513..1f743e5 160000 --- a/plugins/download-commands +++ b/plugins/download-commands
@@ -1 +1 @@ -Subproject commit 87075138f5b27e9aba91a3af56ddcf1cda3be6b1 +Subproject commit 1f743e5a877a8ef97b1f3a9e72933c0d87e11d6e