Migrate accounts to NoteDb (part 2)

This is the second part of migrating accounts from ReviewDb to NoteDb.

This change:
* migrates the accounts from ReviewDb to NoteDb (for single instance
  Gerrit servers)
* adds a configuration parameter (user.readAccountsFromGit) that
  controls whether external IDs are read from ReviewDb or NoteDb

AccountIT is now loading external IDs of an account directly from NoteDb
instead of retrieving them via the account cache. This is because for
the test deleteUserBranchWithAccessDatabaseCapability() the admin
account gets deleted by deleting its user branch and then the @After
restoreExternalIds() method couldn't delete the external IDs of that
account anymore (because the account was deleted it couldn't be
retrieved via the account cache anymore).

Change-Id: I41fa3a6bdb76f497c79a05bdc76e97a7e73624a6
Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
Edwin Kempin
2017-06-20 16:19:29 +02:00
parent 8c9f329acd
commit e7e9fbbf23
40 changed files with 375 additions and 103 deletions

View File

@@ -93,7 +93,6 @@ import com.google.inject.Provider;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
@@ -166,8 +165,8 @@ public class AccountIT extends AbstractDaemonTest {
externalIdsUpdate = externalIdsUpdateFactory.create();
savedExternalIds = new ArrayList<>();
savedExternalIds.addAll(getExternalIds(admin));
savedExternalIds.addAll(getExternalIds(user));
savedExternalIds.addAll(externalIds.byAccount(admin.id));
savedExternalIds.addAll(externalIds.byAccount(user.id));
}
@After
@@ -176,8 +175,8 @@ public class AccountIT extends AbstractDaemonTest {
// savedExternalIds is null when we don't run SSH tests and the assume in
// @Before in AbstractDaemonTest prevents this class' @Before method from
// being executed.
externalIdsUpdate.delete(getExternalIds(admin));
externalIdsUpdate.delete(getExternalIds(user));
externalIdsUpdate.delete(externalIds.byAccount(admin.id));
externalIdsUpdate.delete(externalIds.byAccount(user.id));
externalIdsUpdate.insert(savedExternalIds);
}
}
@@ -194,10 +193,6 @@ public class AccountIT extends AbstractDaemonTest {
}
}
private Collection<ExternalId> getExternalIds(TestAccount account) throws Exception {
return accountCache.get(account.getId()).getExternalIds();
}
@After
public void deleteGpgKeys() throws Exception {
String ref = REFS_GPG_KEYS;

View File

@@ -42,6 +42,7 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -111,7 +112,7 @@ class RunAsFilter implements Filter {
Account target;
try {
target = accountResolver.find(db.get(), runas);
} catch (OrmException e) {
} catch (OrmException | IOException | ConfigInvalidException e) {
log.warn("cannot resolve account for " + RUN_AS, e);
replyError(req, res, SC_INTERNAL_SERVER_ERROR, "cannot resolve " + RUN_AS, e);
return;

View File

@@ -49,6 +49,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -231,7 +232,7 @@ class BecomeAnyAccountLoginServlet extends HttpServlet {
}
try (ReviewDb db = schema.open()) {
return auth(accounts.get(db, id));
} catch (OrmException e) {
} catch (OrmException | IOException | ConfigInvalidException e) {
getServletContext().log("cannot query database", e);
return null;
}

View File

@@ -44,6 +44,7 @@ import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
@@ -60,6 +61,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import org.apache.commons.lang.mutable.MutableDouble;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -73,7 +75,7 @@ public class ReviewerRecommender {
new double[] {
BASE_REVIEWER_WEIGHT, BASE_OWNER_WEIGHT, BASE_COMMENT_WEIGHT,
};
private static final long PLUGIN_QUERY_TIMEOUT = 500; //ms
private static final long PLUGIN_QUERY_TIMEOUT = 500; // ms
private final ChangeQueryBuilder changeQueryBuilder;
private final Config config;
@@ -108,7 +110,7 @@ public class ReviewerRecommender {
SuggestReviewers suggestReviewers,
ProjectControl projectControl,
List<Account.Id> candidateList)
throws OrmException {
throws OrmException, IOException, ConfigInvalidException {
String query = suggestReviewers.getQuery();
double baseWeight = config.getInt("addReviewer", "baseWeight", 1);
@@ -196,7 +198,7 @@ public class ReviewerRecommender {
}
private Map<Account.Id, MutableDouble> baseRankingForEmptyQuery(double baseWeight)
throws OrmException {
throws OrmException, IOException, ConfigInvalidException {
// Get the user's last 25 changes, check approvals
try {
List<ChangeData> result =
@@ -225,7 +227,7 @@ public class ReviewerRecommender {
private Map<Account.Id, MutableDouble> baseRankingForCandidateList(
List<Account.Id> candidates, ProjectControl projectControl, double baseWeight)
throws OrmException {
throws OrmException, IOException, ConfigInvalidException {
// Get each reviewer's activity based on number of applied labels
// (weighted 10d), number of comments (weighted 0.5d) and number of owned
// changes (weighted 1d).

View File

@@ -56,6 +56,7 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
public class ReviewersUtil {
@Singleton
@@ -146,7 +147,7 @@ public class ReviewersUtil {
ProjectControl projectControl,
VisibilityControl visibilityControl,
boolean excludeGroups)
throws IOException, OrmException {
throws IOException, OrmException, ConfigInvalidException {
String query = suggestReviewers.getQuery();
int limit = suggestReviewers.getLimit();
@@ -212,7 +213,7 @@ public class ReviewersUtil {
SuggestReviewers suggestReviewers,
ProjectControl projectControl,
List<Account.Id> candidateList)
throws OrmException {
throws OrmException, IOException, ConfigInvalidException {
try (Timer0.Context ctx = metrics.recommendAccountsLatency.start()) {
return reviewerRecommender.suggestReviewers(
changeNotes, suggestReviewers, projectControl, candidateList);

View File

@@ -193,7 +193,8 @@ public class AccountManager {
}
}
private Account load(Account toUpdate, Account.Id accountId, ReviewDb db) throws OrmException {
private Account load(Account toUpdate, Account.Id accountId, ReviewDb db)
throws OrmException, IOException, ConfigInvalidException {
if (toUpdate == null) {
toUpdate = accounts.get(db, accountId);
if (toUpdate == null) {

View File

@@ -23,12 +23,14 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class AccountResolver {
@@ -61,7 +63,8 @@ public class AccountResolver {
* @return the single account that matches; null if no account matches or there are multiple
* candidates.
*/
public Account find(ReviewDb db, String nameOrEmail) throws OrmException {
public Account find(ReviewDb db, String nameOrEmail)
throws OrmException, IOException, ConfigInvalidException {
Set<Account.Id> r = findAll(db, nameOrEmail);
if (r.size() == 1) {
return byId.get(r.iterator().next()).getAccount();
@@ -90,7 +93,8 @@ public class AccountResolver {
* name ("username").
* @return the accounts that match, empty collection if none. Never null.
*/
public Set<Account.Id> findAll(ReviewDb db, String nameOrEmail) throws OrmException {
public Set<Account.Id> findAll(ReviewDb db, String nameOrEmail)
throws OrmException, IOException, ConfigInvalidException {
Matcher m = Pattern.compile("^.* \\(([1-9][0-9]*)\\)$").matcher(nameOrEmail);
if (m.matches()) {
Account.Id id = Account.Id.parse(m.group(1));
@@ -118,7 +122,8 @@ public class AccountResolver {
return findAllByNameOrEmail(db, nameOrEmail);
}
private boolean exists(ReviewDb db, Account.Id id) throws OrmException {
private boolean exists(ReviewDb db, Account.Id id)
throws OrmException, IOException, ConfigInvalidException {
return accounts.get(db, id) != null;
}

View File

@@ -22,35 +22,70 @@ import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
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.mail.send.OutgoingEmailValidator;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Class to access accounts. */
@Singleton
public class Accounts {
private static final Logger log = LoggerFactory.getLogger(Accounts.class);
private final boolean readFromGit;
private final GitRepositoryManager repoManager;
private final AllUsersName allUsersName;
private final OutgoingEmailValidator emailValidator;
@Inject
Accounts(GitRepositoryManager repoManager, AllUsersName allUsersName) {
Accounts(
@GerritServerConfig Config cfg,
GitRepositoryManager repoManager,
AllUsersName allUsersName,
OutgoingEmailValidator emailValidator) {
this.readFromGit = cfg.getBoolean("user", null, "readAccountsFromGit", false);
this.repoManager = repoManager;
this.allUsersName = allUsersName;
this.emailValidator = emailValidator;
}
public Account get(ReviewDb db, Account.Id accountId) throws OrmException {
public Account get(ReviewDb db, Account.Id accountId)
throws OrmException, IOException, ConfigInvalidException {
if (readFromGit) {
try (Repository repo = repoManager.openRepository(allUsersName)) {
return read(repo, accountId);
}
}
return db.accounts().get(accountId);
}
public List<Account> get(ReviewDb db, Collection<Account.Id> accountIds) throws OrmException {
public List<Account> get(ReviewDb db, Collection<Account.Id> accountIds)
throws OrmException, IOException, ConfigInvalidException {
if (readFromGit) {
List<Account> accounts = new ArrayList<>(accountIds.size());
try (Repository repo = repoManager.openRepository(allUsersName)) {
for (Account.Id accountId : accountIds) {
accounts.add(read(repo, accountId));
}
}
return accounts;
}
return db.accounts().get(accountIds).toList();
}
@@ -59,7 +94,22 @@ public class Accounts {
*
* @return all accounts
*/
public List<Account> all(ReviewDb db) throws OrmException {
public List<Account> all(ReviewDb db) throws OrmException, IOException {
if (readFromGit) {
Set<Account.Id> accountIds = allIds();
List<Account> accounts = new ArrayList<>(accountIds.size());
try (Repository repo = repoManager.openRepository(allUsersName)) {
for (Account.Id accountId : accountIds) {
try {
accounts.add(read(repo, accountId));
} catch (Exception e) {
log.error(String.format("Ignoring invalid account %s", accountId.get()), e);
}
}
}
return accounts;
}
return db.accounts().all().toList();
}
@@ -103,6 +153,13 @@ public class Accounts {
}
}
private Account read(Repository allUsersRepository, Account.Id accountId)
throws IOException, ConfigInvalidException {
AccountConfig accountConfig = new AccountConfig(emailValidator, accountId);
accountConfig.load(allUsersRepository);
return accountConfig.getAccount();
}
private static Stream<Account.Id> readUserRefs(Repository repo) throws IOException {
return repo.getRefDatabase()
.getRefs(RefNames.REFS_USERS)

View File

@@ -33,6 +33,8 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class AccountsCollection
@@ -68,7 +70,8 @@ public class AccountsCollection
@Override
public AccountResource parse(TopLevelResource root, IdString id)
throws ResourceNotFoundException, AuthException, OrmException {
throws ResourceNotFoundException, AuthException, OrmException, IOException,
ConfigInvalidException {
IdentifiedUser user = parseId(id.get());
if (user == null) {
throw new ResourceNotFoundException(id);
@@ -89,7 +92,8 @@ public class AccountsCollection
* account is not visible to the calling user
*/
public IdentifiedUser parse(String id)
throws AuthException, UnprocessableEntityException, OrmException {
throws AuthException, UnprocessableEntityException, OrmException, IOException,
ConfigInvalidException {
return parseOnBehalfOf(null, id);
}
@@ -104,8 +108,11 @@ public class AccountsCollection
* @throws AuthException thrown if 'self' is used as account ID and the current user is not
* authenticated
* @throws OrmException
* @throws ConfigInvalidException
* @throws IOException
*/
public IdentifiedUser parseId(String id) throws AuthException, OrmException {
public IdentifiedUser parseId(String id)
throws AuthException, OrmException, IOException, ConfigInvalidException {
return parseIdOnBehalfOf(null, id);
}
@@ -113,7 +120,8 @@ public class AccountsCollection
* Like {@link #parse(String)}, but also sets the {@link CurrentUser#getRealUser()} on the result.
*/
public IdentifiedUser parseOnBehalfOf(@Nullable CurrentUser caller, String id)
throws AuthException, UnprocessableEntityException, OrmException {
throws AuthException, UnprocessableEntityException, OrmException, IOException,
ConfigInvalidException {
IdentifiedUser user = parseIdOnBehalfOf(caller, id);
if (user == null) {
throw new UnprocessableEntityException(String.format("Account Not Found: %s", id));
@@ -124,7 +132,7 @@ public class AccountsCollection
}
private IdentifiedUser parseIdOnBehalfOf(@Nullable CurrentUser caller, String id)
throws AuthException, OrmException {
throws AuthException, OrmException, IOException, ConfigInvalidException {
if (id.equals("self")) {
CurrentUser user = self.get();
if (user.isIdentifiedUser()) {

View File

@@ -27,6 +27,7 @@ import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.OptionDef;
@@ -82,8 +83,12 @@ public class AccountIdHandler extends OptionHandler<Account.Id> {
throw new CmdLineException(owner, "user \"" + token + "\" not found");
}
}
} catch (OrmException | IOException e) {
} catch (OrmException e) {
throw new CmdLineException(owner, "database is down");
} catch (IOException e) {
throw new CmdLineException(owner, "Failed to load account", e);
} catch (ConfigInvalidException e) {
throw new CmdLineException(owner, "Invalid account config", e);
}
setter.addValue(accountId);
return 1;

View File

@@ -41,7 +41,9 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class Abandon extends RetryingRestModifyView<ChangeResource, AbandonInput, ChangeInfo>
@@ -68,7 +70,8 @@ public class Abandon extends RetryingRestModifyView<ChangeResource, AbandonInput
@Override
protected ChangeInfo applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource req, AbandonInput input)
throws RestApiException, UpdateException, OrmException, PermissionBackendException {
throws RestApiException, UpdateException, OrmException, PermissionBackendException,
IOException, ConfigInvalidException {
req.permissions().database(dbProvider).check(ChangePermission.ABANDON);
NotifyHandling notify = input.notify == null ? defaultNotify(req.getControl()) : input.notify;

View File

@@ -39,6 +39,7 @@ import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class CherryPick
@@ -67,7 +68,7 @@ public class CherryPick
public ChangeInfo applyImpl(
BatchUpdate.Factory updateFactory, RevisionResource rsrc, CherryPickInput input)
throws OrmException, IOException, UpdateException, RestApiException,
PermissionBackendException {
PermissionBackendException, ConfigInvalidException {
input.parent = input.parent == null ? 1 : input.parent;
if (input.message == null || input.message.trim().isEmpty()) {
throw new BadRequestException("message must be non-empty");

View File

@@ -62,6 +62,7 @@ import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
import java.util.TimeZone;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.InvalidObjectIdException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
@@ -124,7 +125,7 @@ public class CherryPickChange {
CherryPickInput input,
RefControl refControl)
throws OrmException, IOException, InvalidChangeOperationException, IntegrationException,
UpdateException, RestApiException {
UpdateException, RestApiException, ConfigInvalidException {
return cherryPick(
batchUpdateFactory,
change.getId(),
@@ -148,7 +149,7 @@ public class CherryPickChange {
CherryPickInput input,
RefControl destRefControl)
throws OrmException, IOException, InvalidChangeOperationException, IntegrationException,
UpdateException, RestApiException {
UpdateException, RestApiException, ConfigInvalidException {
IdentifiedUser identifiedUser = user.get();
try (Repository git = gitManager.openRepository(project);
@@ -320,7 +321,7 @@ public class CherryPickChange {
ChangeControl destCtl,
CodeReviewCommit cherryPickCommit,
CherryPickInput input)
throws IOException, OrmException, BadRequestException {
throws IOException, OrmException, BadRequestException, ConfigInvalidException {
Change destChange = destCtl.getChange();
PatchSet.Id psId = ChangeUtil.nextPatchSetId(git, destChange.currentPatchSetId());
PatchSet current = psUtil.current(dbProvider.get(), destCtl.getNotes());
@@ -343,7 +344,7 @@ public class CherryPickChange {
Branch.NameKey sourceBranch,
ObjectId sourceCommit,
CherryPickInput input)
throws OrmException, IOException, BadRequestException {
throws OrmException, IOException, BadRequestException, ConfigInvalidException {
Change.Id changeId = new Change.Id(seq.nextChangeId());
ChangeInserter ins =
changeInserterFactory.create(changeId, cherryPickCommit, refName).setTopic(topic);

View File

@@ -39,6 +39,7 @@ import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.revwalk.RevCommit;
@Singleton
@@ -67,7 +68,7 @@ public class CherryPickCommit
public ChangeInfo applyImpl(
BatchUpdate.Factory updateFactory, CommitResource rsrc, CherryPickInput input)
throws OrmException, IOException, UpdateException, RestApiException,
PermissionBackendException {
PermissionBackendException, ConfigInvalidException {
RevCommit commit = rsrc.getCommit();
String message = Strings.nullToEmpty(input.message).trim();
input.message = message.isEmpty() ? commit.getFullMessage() : message;

View File

@@ -68,6 +68,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
@@ -226,7 +227,7 @@ public class ConsistencyChecker {
if (accounts.get(db.get(), change().getOwner()) == null) {
problem("Missing change owner: " + change().getOwner());
}
} catch (OrmException e) {
} catch (OrmException | IOException | ConfigInvalidException e) {
error("Failed to look up owner", e);
}
}

View File

@@ -74,6 +74,7 @@ import java.sql.Timestamp;
import java.util.Collections;
import java.util.List;
import java.util.TimeZone;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
@@ -151,7 +152,7 @@ public class CreateChange
protected Response<ChangeInfo> applyImpl(
BatchUpdate.Factory updateFactory, TopLevelResource parent, ChangeInput input)
throws OrmException, IOException, InvalidChangeOperationException, RestApiException,
UpdateException, PermissionBackendException {
UpdateException, PermissionBackendException, ConfigInvalidException {
if (Strings.isNullOrEmpty(input.project)) {
throw new BadRequestException("project must be non-empty");
}

View File

@@ -31,10 +31,12 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class NotifyUtil {
@@ -76,7 +78,7 @@ public class NotifyUtil {
public ListMultimap<RecipientType, Account.Id> resolveAccounts(
@Nullable Map<RecipientType, NotifyInfo> notifyDetails)
throws OrmException, BadRequestException {
throws OrmException, BadRequestException, IOException, ConfigInvalidException {
if (isNullOrEmpty(notifyDetails)) {
return ImmutableListMultimap.of();
}
@@ -96,7 +98,7 @@ public class NotifyUtil {
}
private List<Account.Id> find(ReviewDb db, List<String> nameOrEmails)
throws OrmException, BadRequestException {
throws OrmException, BadRequestException, IOException, ConfigInvalidException {
List<String> missing = new ArrayList<>(nameOrEmails.size());
List<Account.Id> r = new ArrayList<>(nameOrEmails.size());
for (String nameOrEmail : nameOrEmails) {

View File

@@ -126,6 +126,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
@Singleton
@@ -190,14 +191,14 @@ public class PostReview
protected Response<ReviewResult> applyImpl(
BatchUpdate.Factory updateFactory, RevisionResource revision, ReviewInput input)
throws RestApiException, UpdateException, OrmException, IOException,
PermissionBackendException {
PermissionBackendException, ConfigInvalidException {
return apply(updateFactory, revision, input, TimeUtil.nowTs());
}
public Response<ReviewResult> apply(
BatchUpdate.Factory updateFactory, RevisionResource revision, ReviewInput input, Timestamp ts)
throws RestApiException, UpdateException, OrmException, IOException,
PermissionBackendException {
PermissionBackendException, ConfigInvalidException {
// Respect timestamp, but truncate at change created-on time.
ts = Ordering.natural().max(ts, revision.getChange().getCreatedOn());
if (revision.getEdit().isPresent()) {
@@ -367,7 +368,7 @@ public class PostReview
private RevisionResource onBehalfOf(RevisionResource rev, ReviewInput in)
throws BadRequestException, AuthException, UnprocessableEntityException, OrmException,
PermissionBackendException {
PermissionBackendException, IOException, ConfigInvalidException {
if (in.labels == null || in.labels.isEmpty()) {
throw new AuthException(
String.format("label required to post review on behalf of \"%s\"", in.onBehalfOf));

View File

@@ -76,6 +76,7 @@ import java.text.MessageFormat;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
@Singleton
@@ -148,7 +149,7 @@ public class PostReviewers
protected AddReviewerResult applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, AddReviewerInput input)
throws IOException, OrmException, RestApiException, UpdateException,
PermissionBackendException {
PermissionBackendException, ConfigInvalidException {
if (input.reviewer == null) {
throw new BadRequestException("missing reviewer field");
}
@@ -170,7 +171,7 @@ public class PostReviewers
public Addition prepareApplication(
ChangeResource rsrc, AddReviewerInput input, boolean allowGroup)
throws OrmException, IOException, PermissionBackendException {
throws OrmException, IOException, PermissionBackendException, ConfigInvalidException {
String reviewer = input.reviewer;
ReviewerState state = input.state();
NotifyHandling notify = input.notify;
@@ -219,7 +220,7 @@ public class PostReviewers
ListMultimap<RecipientType, Account.Id> accountsToNotify,
boolean allowGroup,
boolean allowByEmail)
throws OrmException, PermissionBackendException {
throws OrmException, PermissionBackendException, IOException, ConfigInvalidException {
Account.Id accountId = null;
try {
accountId = accounts.parse(reviewer).getAccountId();

View File

@@ -45,6 +45,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
@@ -82,7 +83,7 @@ public class PreviewSubmit implements RestReadView<RevisionResource> {
@Override
public BinaryResult apply(RevisionResource rsrc)
throws OrmException, RestApiException, UpdateException {
throws OrmException, RestApiException, UpdateException, IOException, ConfigInvalidException {
if (Strings.isNullOrEmpty(format)) {
throw new BadRequestException("format is not specified");
}
@@ -110,7 +111,7 @@ public class PreviewSubmit implements RestReadView<RevisionResource> {
}
private BinaryResult getBundles(RevisionResource rsrc, ArchiveFormat f)
throws OrmException, RestApiException, UpdateException {
throws OrmException, RestApiException, UpdateException, IOException, ConfigInvalidException {
ReviewDb db = dbProvider.get();
ChangeControl control = rsrc.getControl();
IdentifiedUser caller = control.getUser().asIdentifiedUser();
@@ -125,7 +126,12 @@ public class PreviewSubmit implements RestReadView<RevisionResource> {
.setContentType(f.getMimeType())
.setAttachmentName("submit-preview-" + change.getChangeId() + "." + format);
return bin;
} catch (OrmException | RestApiException | UpdateException | RuntimeException e) {
} catch (OrmException
| RestApiException
| UpdateException
| IOException
| ConfigInvalidException
| RuntimeException e) {
op.close();
throw e;
}

View File

@@ -35,6 +35,7 @@ import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class PublishChangeEdit
@@ -85,7 +86,8 @@ public class PublishChangeEdit
@Override
protected Response<?> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, PublishChangeEditInput in)
throws IOException, OrmException, RestApiException, UpdateException {
throws IOException, OrmException, RestApiException, UpdateException,
ConfigInvalidException {
CreateChange.checkValidCLA(rsrc.getControl().getProjectControl());
Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getChange());
if (!edit.isPresent()) {

View File

@@ -42,6 +42,7 @@ import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class PutAssignee extends RetryingRestModifyView<ChangeResource, AssigneeInput, AccountInfo>
@@ -73,7 +74,7 @@ public class PutAssignee extends RetryingRestModifyView<ChangeResource, Assignee
protected AccountInfo applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, AssigneeInput input)
throws RestApiException, UpdateException, OrmException, IOException,
PermissionBackendException {
PermissionBackendException, ConfigInvalidException {
rsrc.permissions().check(ChangePermission.EDIT_ASSIGNEE);
input.assignee = Strings.nullToEmpty(input.assignee).trim();
@@ -109,7 +110,7 @@ public class PutAssignee extends RetryingRestModifyView<ChangeResource, Assignee
}
private Addition addAssigneeAsCC(ChangeResource rsrc, String assignee)
throws OrmException, IOException, PermissionBackendException {
throws OrmException, IOException, PermissionBackendException, ConfigInvalidException {
AddReviewerInput reviewerInput = new AddReviewerInput();
reviewerInput.reviewer = assignee;
reviewerInput.state = ReviewerState.CC;

View File

@@ -51,6 +51,7 @@ import java.util.TimeZone;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
@@ -107,7 +108,7 @@ public class PutMessage
protected Response<String> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource resource, Input input)
throws IOException, UnchangedCommitMessageException, RestApiException, UpdateException,
PermissionBackendException, OrmException {
PermissionBackendException, OrmException, ConfigInvalidException {
PatchSet ps = psUtil.current(db.get(), resource.getNotes());
if (ps == null) {
throw new ResourceConflictException("current revision is missing");

View File

@@ -30,7 +30,9 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class Reviewers implements ChildCollection<ChangeResource, ReviewerResource> {
@@ -69,7 +71,8 @@ public class Reviewers implements ChildCollection<ChangeResource, ReviewerResour
@Override
public ReviewerResource parse(ChangeResource rsrc, IdString id)
throws OrmException, ResourceNotFoundException, AuthException {
throws OrmException, ResourceNotFoundException, AuthException, IOException,
ConfigInvalidException {
Address address = Address.tryParse(id.get());
Account.Id accountId = null;

View File

@@ -31,7 +31,9 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class RevisionReviewers implements ChildCollection<RevisionResource, ReviewerResource> {
@@ -70,7 +72,8 @@ public class RevisionReviewers implements ChildCollection<RevisionResource, Revi
@Override
public ReviewerResource parse(RevisionResource rsrc, IdString id)
throws OrmException, ResourceNotFoundException, AuthException, MethodNotAllowedException {
throws OrmException, ResourceNotFoundException, AuthException, MethodNotAllowedException,
IOException, ConfigInvalidException {
if (!rsrc.isCurrent()) {
throw new MethodNotAllowedException("Cannot access on non-current patch set");
}

View File

@@ -73,6 +73,7 @@ import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
@@ -202,7 +203,7 @@ public class Submit
@Override
public Output apply(RevisionResource rsrc, SubmitInput input)
throws RestApiException, RepositoryNotFoundException, IOException, OrmException,
PermissionBackendException, UpdateException {
PermissionBackendException, UpdateException, ConfigInvalidException {
input.onBehalfOf = Strings.emptyToNull(input.onBehalfOf);
IdentifiedUser submitter;
if (input.onBehalfOf != null) {
@@ -216,7 +217,7 @@ public class Submit
}
public Change mergeChange(RevisionResource rsrc, IdentifiedUser submitter, SubmitInput input)
throws OrmException, RestApiException, IOException, UpdateException {
throws OrmException, RestApiException, IOException, UpdateException, ConfigInvalidException {
Change change = rsrc.getChange();
if (!change.getStatus().isOpen()) {
throw new ResourceConflictException("change is " + ChangeUtil.status(change));
@@ -249,7 +250,7 @@ public class Submit
if (msg != null) {
throw new ResourceConflictException(msg.getMessage());
}
//$FALL-THROUGH$
// $FALL-THROUGH$
case ABANDONED:
case DRAFT:
default:
@@ -478,7 +479,8 @@ public class Submit
}
private IdentifiedUser onBehalfOf(RevisionResource rsrc, SubmitInput in)
throws AuthException, UnprocessableEntityException, OrmException, PermissionBackendException {
throws AuthException, UnprocessableEntityException, OrmException, PermissionBackendException,
IOException, ConfigInvalidException {
PermissionBackend.ForChange perm = rsrc.permissions().database(dbProvider);
perm.check(ChangePermission.SUBMIT);
perm.check(ChangePermission.SUBMIT_AS);
@@ -527,7 +529,7 @@ public class Submit
@Override
public ChangeInfo apply(ChangeResource rsrc, SubmitInput input)
throws RestApiException, RepositoryNotFoundException, IOException, OrmException,
PermissionBackendException, UpdateException {
PermissionBackendException, UpdateException, ConfigInvalidException {
PatchSet ps = psUtil.current(dbProvider.get(), rsrc.getNotes());
if (ps == null) {
throw new ResourceConflictException("current revision is missing");

View File

@@ -34,6 +34,7 @@ import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.List;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.kohsuke.args4j.Option;
@@ -66,7 +67,7 @@ public class SuggestChangeReviewers extends SuggestReviewers
@Override
public List<SuggestedReviewerInfo> apply(ChangeResource rsrc)
throws AuthException, BadRequestException, OrmException, IOException {
throws AuthException, BadRequestException, OrmException, IOException, ConfigInvalidException {
if (!self.get().isIdentifiedUser()) {
throw new AuthException("Authentication required");
}

View File

@@ -39,6 +39,7 @@ import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class CheckAccess implements RestModifyView<ConfigResource, AccessCheckInput> {
@@ -67,7 +68,8 @@ public class CheckAccess implements RestModifyView<ConfigResource, AccessCheckIn
@Override
public AccessCheckInfo apply(ConfigResource unused, AccessCheckInput input)
throws OrmException, PermissionBackendException, RestApiException, IOException {
throws OrmException, PermissionBackendException, RestApiException, IOException,
ConfigInvalidException {
permissionBackend.user(currentUser.get()).check(GlobalPermission.ADMINISTRATE_SERVER);
if (input == null) {

View File

@@ -88,6 +88,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
@@ -430,7 +431,7 @@ public class MergeOp implements AutoCloseable {
boolean checkSubmitRules,
SubmitInput submitInput,
boolean dryrun)
throws OrmException, RestApiException, UpdateException {
throws OrmException, RestApiException, UpdateException, IOException, ConfigInvalidException {
this.submitInput = submitInput;
this.accountsToNotify = notifyUtil.resolveAccounts(submitInput.notifyDetails);
this.dryrun = dryrun;

View File

@@ -816,7 +816,11 @@ public class ReceiveCommits {
} catch (ResourceConflictException e) {
addMessage(e.getMessage());
reject(magicBranchCmd, "conflict");
} catch (RestApiException | OrmException | UpdateException e) {
} catch (RestApiException
| OrmException
| UpdateException
| IOException
| ConfigInvalidException e) {
logError("Error submitting changes to " + project.getName(), e);
reject(magicBranchCmd, "error during submit");
}
@@ -2259,7 +2263,7 @@ public class ReceiveCommits {
}
private void submit(Collection<CreateRequest> create, Collection<ReplaceRequest> replace)
throws OrmException, RestApiException, UpdateException {
throws OrmException, RestApiException, UpdateException, IOException, ConfigInvalidException {
Map<ObjectId, Change> bySha = Maps.newHashMapWithExpectedSize(create.size() + replace.size());
for (CreateRequest r : create) {
checkNotNull(r.change, "cannot submit new change %s; op may not have run", r.changeId);

View File

@@ -52,6 +52,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class AddMembers implements RestModifyView<GroupResource, Input> {
@@ -115,7 +116,7 @@ public class AddMembers implements RestModifyView<GroupResource, Input> {
@Override
public List<AccountInfo> apply(GroupResource resource, Input input)
throws AuthException, MethodNotAllowedException, UnprocessableEntityException, OrmException,
IOException {
IOException, ConfigInvalidException {
AccountGroup internalGroup = resource.toAccountGroup();
if (internalGroup == null) {
throw new MethodNotAllowedException();
@@ -143,7 +144,8 @@ public class AddMembers implements RestModifyView<GroupResource, Input> {
}
Account findAccount(String nameOrEmailOrId)
throws AuthException, UnprocessableEntityException, OrmException, IOException {
throws AuthException, UnprocessableEntityException, OrmException, IOException,
ConfigInvalidException {
try {
return accounts.parse(nameOrEmailOrId).getAccount();
} catch (UnprocessableEntityException e) {
@@ -235,7 +237,7 @@ public class AddMembers implements RestModifyView<GroupResource, Input> {
@Override
public AccountInfo apply(GroupResource resource, PutMember.Input input)
throws AuthException, MethodNotAllowedException, ResourceNotFoundException, OrmException,
IOException {
IOException, ConfigInvalidException {
AddMembers.Input in = new AddMembers.Input();
in._oneMember = id;
try {

View File

@@ -55,6 +55,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
@@ -115,7 +116,7 @@ public class CreateGroup implements RestModifyView<TopLevelResource, GroupInput>
@Override
public GroupInfo apply(TopLevelResource resource, GroupInput input)
throws AuthException, BadRequestException, UnprocessableEntityException,
ResourceConflictException, OrmException, IOException {
ResourceConflictException, OrmException, IOException, ConfigInvalidException {
if (input == null) {
input = new GroupInput();
}

View File

@@ -38,6 +38,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class DeleteMembers implements RestModifyView<GroupResource, Input> {
@@ -64,7 +65,7 @@ public class DeleteMembers implements RestModifyView<GroupResource, Input> {
@Override
public Response<?> apply(GroupResource resource, Input input)
throws AuthException, MethodNotAllowedException, UnprocessableEntityException, OrmException,
IOException {
IOException, ConfigInvalidException {
AccountGroup internalGroup = resource.toAccountGroup();
if (internalGroup == null) {
throw new MethodNotAllowedException();
@@ -125,7 +126,7 @@ public class DeleteMembers implements RestModifyView<GroupResource, Input> {
@Override
public Response<?> apply(MemberResource resource, Input input)
throws AuthException, MethodNotAllowedException, UnprocessableEntityException, OrmException,
IOException {
IOException, ConfigInvalidException {
AddMembers.Input in = new AddMembers.Input();
in._oneMember = resource.getMember().getAccountId().toString();
return delete.get().apply(resource, in);

View File

@@ -32,6 +32,8 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
public class MembersCollection
@@ -63,7 +65,8 @@ public class MembersCollection
@Override
public MemberResource parse(GroupResource parent, IdString id)
throws MethodNotAllowedException, AuthException, ResourceNotFoundException, OrmException {
throws MethodNotAllowedException, AuthException, ResourceNotFoundException, OrmException,
IOException, ConfigInvalidException {
if (parent.toAccountGroup() == null) {
throw new MethodNotAllowedException();
}

View File

@@ -732,7 +732,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> label(String name) throws QueryParseException, OrmException {
public Predicate<ChangeData> label(String name)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
Set<Account.Id> accounts = null;
AccountGroup.UUID group = null;
@@ -846,7 +847,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> starredby(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> starredby(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return starredby(parseAccount(who));
}
@@ -863,7 +865,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> watchedby(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> watchedby(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
Set<Account.Id> m = parseAccount(who);
List<IsWatchedByPredicate> p = Lists.newArrayListWithCapacity(m.size());
@@ -887,7 +890,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> draftby(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> draftby(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
Set<Account.Id> m = parseAccount(who);
List<Predicate<ChangeData>> p = Lists.newArrayListWithCapacity(m.size());
for (Account.Id id : m) {
@@ -905,7 +909,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> visibleto(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> visibleto(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
if (isSelf(who)) {
return is_visible();
}
@@ -942,12 +947,14 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> o(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> o(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return owner(who);
}
@Operator
public Predicate<ChangeData> owner(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> owner(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return owner(parseAccount(who));
}
@@ -960,7 +967,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
private Predicate<ChangeData> ownerDefaultField(String who)
throws QueryParseException, OrmException {
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
Set<Account.Id> accounts = parseAccount(who);
if (accounts.size() > MAX_ACCOUNTS_PER_DEFAULT_FIELD) {
return Predicate.any();
@@ -969,7 +976,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> assignee(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> assignee(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return assignee(parseAccount(who));
}
@@ -991,22 +999,24 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> r(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> r(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return reviewer(who);
}
@Operator
public Predicate<ChangeData> reviewer(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> reviewer(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return reviewer(who, false);
}
private Predicate<ChangeData> reviewerDefaultField(String who)
throws QueryParseException, OrmException {
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return reviewer(who, true);
}
private Predicate<ChangeData> reviewer(String who, boolean forDefaultField)
throws QueryParseException, OrmException {
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
Predicate<ChangeData> byState =
reviewerByState(who, ReviewerStateInternal.REVIEWER, forDefaultField);
if (Objects.equals(byState, Predicate.<ChangeData>any())) {
@@ -1020,7 +1030,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> cc(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> cc(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return reviewerByState(who, ReviewerStateInternal.CC, false);
}
@@ -1073,7 +1084,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> commentby(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> commentby(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return commentby(parseAccount(who));
}
@@ -1086,7 +1098,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> from(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> from(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
Set<Account.Id> ownerIds = parseAccount(who);
return Predicate.or(owner(ownerIds), commentby(ownerIds));
}
@@ -1110,7 +1123,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
}
@Operator
public Predicate<ChangeData> reviewedby(String who) throws QueryParseException, OrmException {
public Predicate<ChangeData> reviewedby(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
return IsReviewedPredicate.create(parseAccount(who));
}
@@ -1192,7 +1206,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
if (!Objects.equals(p, Predicate.<ChangeData>any())) {
predicates.add(p);
}
} catch (OrmException | QueryParseException e) {
} catch (OrmException | IOException | ConfigInvalidException | QueryParseException e) {
// Skip.
}
try {
@@ -1200,13 +1214,13 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
if (!Objects.equals(p, Predicate.<ChangeData>any())) {
predicates.add(p);
}
} catch (OrmException | QueryParseException e) {
} catch (OrmException | IOException | ConfigInvalidException | QueryParseException e) {
// Skip.
}
predicates.add(file(query));
try {
predicates.add(label(query));
} catch (OrmException | QueryParseException e) {
} catch (OrmException | IOException | ConfigInvalidException | QueryParseException e) {
// Skip.
}
predicates.add(commit(query));
@@ -1245,7 +1259,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
return Predicate.and(predicates);
}
private Set<Account.Id> parseAccount(String who) throws QueryParseException, OrmException {
private Set<Account.Id> parseAccount(String who)
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
if (isSelf(who)) {
return Collections.singleton(self());
}
@@ -1291,7 +1306,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
public Predicate<ChangeData> reviewerByState(
String who, ReviewerStateInternal state, boolean forDefaultField)
throws QueryParseException, OrmException {
throws QueryParseException, OrmException, IOException, ConfigInvalidException {
Predicate<ChangeData> reviewerByEmailPredicate = null;
if (args.index.getSchema().hasField(ChangeField.REVIEWER_BY_EMAIL)) {
Address address = Address.tryParse(who);

View File

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

View File

@@ -0,0 +1,105 @@
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.schema;
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.AccountConfig;
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.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
/** Migrate accounts to NoteDb. */
public class Schema_154 extends SchemaVersion {
private final GitRepositoryManager repoManager;
private final AllUsersName allUsersName;
private final Provider<PersonIdent> serverIdent;
@Inject
Schema_154(
Provider<Schema_153> prior,
GitRepositoryManager repoManager,
AllUsersName allUsersName,
@GerritPersonIdent Provider<PersonIdent> serverIdent) {
super(prior);
this.repoManager = repoManager;
this.allUsersName = allUsersName;
this.serverIdent = serverIdent;
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
try {
try (Repository repo = repoManager.openRepository(allUsersName)) {
for (Account account : scanAccounts(db)) {
updateAccountInNoteDb(repo, account);
}
}
} catch (IOException | ConfigInvalidException e) {
throw new OrmException("Migrating accounts to NoteDb failed", e);
}
}
private Set<Account> scanAccounts(ReviewDb db) throws SQLException {
try (Statement stmt = newStatement(db);
ResultSet rs =
stmt.executeQuery(
"SELECT account_id,"
+ " registered_on,"
+ " full_name, "
+ " preferred_email,"
+ " status,"
+ " inactive"
+ " FROM accounts")) {
Set<Account> s = new HashSet<>();
while (rs.next()) {
Account a = new Account(new Account.Id(rs.getInt(1)), rs.getTimestamp(2));
a.setFullName(rs.getString(3));
a.setPreferredEmail(rs.getString(4));
a.setStatus(rs.getString(5));
a.setActive(rs.getString(6).equals("N"));
s.add(a);
}
return s;
}
}
private void updateAccountInNoteDb(Repository allUsersRepo, Account account)
throws IOException, ConfigInvalidException {
MetaDataUpdate md =
new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, allUsersRepo);
PersonIdent ident = serverIdent.get();
md.getCommitBuilder().setAuthor(ident);
md.getCommitBuilder().setCommitter(ident);
AccountConfig accountConfig = new AccountConfig(null, account.getId());
accountConfig.load(allUsersRepo);
accountConfig.setAccount(account);
accountConfig.commit(md);
}
}

View File

@@ -33,14 +33,20 @@ import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountConfig;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.Accounts;
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.config.AllProjectsName;
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.schema.SchemaCreator;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
@@ -58,6 +64,8 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
@@ -82,6 +90,8 @@ public abstract class AbstractQueryAccountsTest extends GerritServerTests {
@Inject protected GerritApi gApi;
@Inject @GerritPersonIdent Provider<PersonIdent> serverIdent;
@Inject protected IdentifiedUser.GenericFactory userFactory;
@Inject private Provider<AnonymousUser> anonymousUser;
@@ -98,6 +108,10 @@ public abstract class AbstractQueryAccountsTest extends GerritServerTests {
@Inject protected AllProjectsName allProjects;
@Inject protected AllUsersName allUsers;
@Inject protected GitRepositoryManager repoManager;
protected LifecycleManager lifecycle;
protected Injector injector;
protected ReviewDb db;
@@ -383,12 +397,25 @@ public abstract class AbstractQueryAccountsTest extends GerritServerTests {
public void reindex() throws Exception {
AccountInfo user1 = newAccountWithFullName("tester", "Test Usre");
// update account in the database so that account index is stale
// update account in ReviewDb without reindex so that account index is stale
String newName = "Test User";
Account account = accounts.get(db, new Account.Id(user1._accountId));
Account.Id accountId = new Account.Id(user1._accountId);
Account account = accounts.get(db, accountId);
account.setFullName(newName);
db.accounts().update(ImmutableSet.of(account));
// update account in NoteDb without reindex so that account index is stale
try (Repository repo = repoManager.openRepository(allUsers)) {
MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsers, repo);
PersonIdent ident = serverIdent.get();
md.getCommitBuilder().setAuthor(ident);
md.getCommitBuilder().setCommitter(ident);
AccountConfig accountConfig = new AccountConfig(null, accountId);
accountConfig.load(repo);
accountConfig.getAccount().setFullName(newName);
accountConfig.commit(md);
}
assertQuery("name:" + quote(user1.name), user1);
assertQuery("name:" + quote(newName));

View File

@@ -37,6 +37,7 @@ import com.google.inject.Inject;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
@@ -103,7 +104,7 @@ final class CreateGroupCommand extends SshCommand {
@Inject private AddIncludedGroups addIncludedGroups;
@Override
protected void run() throws Failure, OrmException, IOException {
protected void run() throws Failure, OrmException, IOException, ConfigInvalidException {
try {
GroupResource rsrc = createGroup();
@@ -119,7 +120,8 @@ final class CreateGroupCommand extends SshCommand {
}
}
private GroupResource createGroup() throws RestApiException, OrmException, IOException {
private GroupResource createGroup()
throws RestApiException, OrmException, IOException, ConfigInvalidException {
GroupInput input = new GroupInput();
input.description = groupDescription;
input.visibleToAll = visibleToAll;
@@ -132,7 +134,8 @@ final class CreateGroupCommand extends SshCommand {
return groups.parse(TopLevelResource.INSTANCE, IdString.fromUrl(group.id));
}
private void addMembers(GroupResource rsrc) throws RestApiException, OrmException, IOException {
private void addMembers(GroupResource rsrc)
throws RestApiException, OrmException, IOException, ConfigInvalidException {
AddMembers.Input input =
AddMembers.Input.fromMembers(
initialMembers.stream().map(Object::toString).collect(toList()));

View File

@@ -35,6 +35,7 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.Map;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
@@ -79,7 +80,7 @@ public class LsUserRefs extends SshCommand {
Account userAccount;
try {
userAccount = accountResolver.find(db, userName);
} catch (OrmException e) {
} catch (OrmException | IOException | ConfigInvalidException e) {
throw die(e);
}
if (userAccount == null) {