Allow to update accounts and project watches atomically
AccountsUpdate now also supports to update project watches. This means account properties and project watches can now be updated in the same transaction. WatchConfig.Accessor is removed so that project watch updates can only be done through AccountsUpdate. For reading project watches a new method is added to Accounts. In the future we would rather like to change the Accounts#get(Account.Id) method to return AccountState instead of Account so that this get method can be used to retrieve the account as well as the project watches. Once this is done the getProjectWatches method will be removed again. Reading and writing project watches is now done via AccountConfig. On load we always read the watch.config file, but parsing it is done lazily when the project watches are accessed for the first time. Most callers that load accounts are not interested in project watches and this avoids unneeded parsing effort for them. Change-Id: I8cd441eee3f65817a3653610c5d3bb62b0bfea5e Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
@@ -14,11 +14,14 @@
|
||||
|
||||
package com.google.gerrit.server.git.validators;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gerrit.common.Nullable;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.account.AccountConfig;
|
||||
import com.google.gerrit.server.git.ValidationError;
|
||||
import com.google.gerrit.server.mail.send.OutgoingEmailValidator;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
@@ -47,15 +50,16 @@ public class AccountValidator {
|
||||
Optional<Account> oldAccount = Optional.empty();
|
||||
if (oldId != null && !ObjectId.zeroId().equals(oldId)) {
|
||||
try {
|
||||
oldAccount = loadAccount(accountId, rw, oldId);
|
||||
oldAccount = loadAccount(accountId, rw, oldId, null);
|
||||
} catch (ConfigInvalidException e) {
|
||||
// ignore, maybe the new commit is repairing it now
|
||||
}
|
||||
}
|
||||
|
||||
List<String> messages = new ArrayList<>();
|
||||
Optional<Account> newAccount;
|
||||
try {
|
||||
newAccount = loadAccount(accountId, rw, newId);
|
||||
newAccount = loadAccount(accountId, rw, newId, messages);
|
||||
} catch (ConfigInvalidException e) {
|
||||
return ImmutableList.of(
|
||||
String.format(
|
||||
@@ -67,7 +71,6 @@ public class AccountValidator {
|
||||
return ImmutableList.of(String.format("account '%s' does not exist", accountId.get()));
|
||||
}
|
||||
|
||||
List<String> messages = new ArrayList<>();
|
||||
if (accountId.equals(self.get().getAccountId()) && !newAccount.get().isActive()) {
|
||||
messages.add("cannot deactivate own account");
|
||||
}
|
||||
@@ -87,11 +90,20 @@ public class AccountValidator {
|
||||
return ImmutableList.copyOf(messages);
|
||||
}
|
||||
|
||||
private Optional<Account> loadAccount(Account.Id accountId, RevWalk rw, ObjectId commit)
|
||||
private Optional<Account> loadAccount(
|
||||
Account.Id accountId, RevWalk rw, ObjectId commit, @Nullable List<String> messages)
|
||||
throws IOException, ConfigInvalidException {
|
||||
rw.reset();
|
||||
AccountConfig accountConfig = new AccountConfig(accountId);
|
||||
accountConfig.load(rw, commit);
|
||||
accountConfig.setEagerParsing(true).load(rw, commit);
|
||||
if (messages != null) {
|
||||
messages.addAll(
|
||||
accountConfig
|
||||
.getValidationErrors()
|
||||
.stream()
|
||||
.map(ValidationError::getMessage)
|
||||
.collect(toSet()));
|
||||
}
|
||||
return accountConfig.getLoadedAccount();
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,6 @@ import com.google.gerrit.reviewdb.client.RefNames;
|
||||
import com.google.gerrit.reviewdb.client.RevId;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.account.WatchConfig;
|
||||
import com.google.gerrit.server.account.externalids.ExternalIdsConsistencyChecker;
|
||||
import com.google.gerrit.server.config.AllProjectsName;
|
||||
import com.google.gerrit.server.config.AllUsersName;
|
||||
@@ -418,34 +417,6 @@ public class CommitValidators {
|
||||
}
|
||||
}
|
||||
|
||||
if (allUsers.equals(branch.getParentKey()) && RefNames.isRefsUsers(branch.get())) {
|
||||
List<CommitValidationMessage> messages = new ArrayList<>();
|
||||
Account.Id accountId = Account.Id.fromRef(branch.get());
|
||||
if (accountId != null) {
|
||||
try {
|
||||
WatchConfig wc = new WatchConfig(accountId);
|
||||
wc.load(rw, receiveEvent.command.getNewId());
|
||||
if (!wc.getValidationErrors().isEmpty()) {
|
||||
addError("Invalid project configuration:", messages);
|
||||
for (ValidationError err : wc.getValidationErrors()) {
|
||||
addError(" " + err.getMessage(), messages);
|
||||
}
|
||||
throw new ConfigInvalidException("invalid watch configuration");
|
||||
}
|
||||
} catch (IOException | ConfigInvalidException e) {
|
||||
log.error(
|
||||
"User "
|
||||
+ user.getUserName()
|
||||
+ " tried to push an invalid watch configuration "
|
||||
+ receiveEvent.command.getNewId().name()
|
||||
+ " for account "
|
||||
+ accountId.get(),
|
||||
e);
|
||||
throw new CommitValidationException("invalid watch configuration", messages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user