use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.
the class ConsistencyChecker method deletePatchSets.
private void deletePatchSets(List<DeletePatchSetFromDbOp> ops) {
try (BatchUpdate bu = newBatchUpdate()) {
bu.setRepository(repo, rw, oi);
for (DeletePatchSetFromDbOp op : ops) {
checkArgument(op.psId.changeId().equals(notes.getChangeId()));
bu.addOp(notes.getChangeId(), op);
}
bu.addOp(notes.getChangeId(), new UpdateCurrentPatchSetOp(ops));
bu.execute();
} catch (NoPatchSetsWouldRemainException e) {
for (DeletePatchSetFromDbOp op : ops) {
op.p.status = Status.FIX_FAILED;
op.p.outcome = e.getMessage();
}
} catch (UpdateException | RestApiException e) {
String msg = "Error deleting patch set";
logger.atWarning().withCause(e).log("%s of change %s", msg, ops.get(0).psId.changeId());
for (DeletePatchSetFromDbOp op : ops) {
// Overwrite existing statuses that were set before the transaction was
// rolled back.
op.p.status = Status.FIX_FAILED;
op.p.outcome = msg;
}
}
}
use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.
the class ConsistencyChecker method fixMerged.
private void fixMerged(ProblemInfo p) {
try (BatchUpdate bu = newBatchUpdate()) {
bu.setRepository(repo, rw, oi);
bu.addOp(notes.getChangeId(), new FixMergedOp(p));
bu.execute();
} catch (UpdateException | RestApiException e) {
logger.atWarning().withCause(e).log("Error marking %s as merged", notes.getChangeId());
p.status = Status.FIX_FAILED;
p.outcome = "Error updating status to merged";
}
}
use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.
the class ConsistencyChecker method insertMergedPatchSet.
private void insertMergedPatchSet(final RevCommit commit, @Nullable PatchSet.Id psIdToDelete, boolean reuseOldPsId) {
ProblemInfo notFound = problem("No patch set found for merged commit " + commit.name());
if (!user.get().isIdentifiedUser()) {
notFound.status = Status.FIX_FAILED;
notFound.outcome = "Must be called by an identified user to insert new patch set";
return;
}
ProblemInfo insertPatchSetProblem;
ProblemInfo deleteOldPatchSetProblem;
if (psIdToDelete == null) {
insertPatchSetProblem = problem(String.format("Expected merged commit %s has no associated patch set", commit.name()));
deleteOldPatchSetProblem = null;
} else {
String msg = String.format("Expected merge commit %s corresponds to patch set %s," + " not the current patch set %s", commit.name(), psIdToDelete.get(), change().currentPatchSetId().get());
// Maybe an identical problem, but different fix.
deleteOldPatchSetProblem = reuseOldPsId ? null : problem(msg);
insertPatchSetProblem = problem(msg);
}
List<ProblemInfo> currProblems = new ArrayList<>(3);
currProblems.add(notFound);
if (deleteOldPatchSetProblem != null) {
currProblems.add(deleteOldPatchSetProblem);
}
currProblems.add(insertPatchSetProblem);
try {
PatchSet.Id psId = (psIdToDelete != null && reuseOldPsId) ? psIdToDelete : ChangeUtil.nextPatchSetId(repo, change().currentPatchSetId());
PatchSetInserter inserter = patchSetInserterFactory.create(notes, psId, commit);
try (BatchUpdate bu = newBatchUpdate()) {
bu.setRepository(repo, rw, oi);
if (psIdToDelete != null) {
// Delete the given patch set ref. If reuseOldPsId is true,
// PatchSetInserter will reinsert the same ref, making it a no-op.
bu.addOp(notes.getChangeId(), new BatchUpdateOp() {
@Override
public void updateRepo(RepoContext ctx) throws IOException {
ctx.addRefUpdate(commit, ObjectId.zeroId(), psIdToDelete.toRefName());
}
});
if (!reuseOldPsId) {
bu.addOp(notes.getChangeId(), new DeletePatchSetFromDbOp(requireNonNull(deleteOldPatchSetProblem), psIdToDelete));
}
}
bu.setNotify(NotifyResolver.Result.none());
bu.addOp(notes.getChangeId(), inserter.setValidate(false).setFireRevisionCreated(false).setAllowClosed(true).setMessage("Patch set for merged commit inserted by consistency checker"));
bu.addOp(notes.getChangeId(), new FixMergedOp(notFound));
bu.execute();
}
notes = notesFactory.createChecked(inserter.getChange());
insertPatchSetProblem.status = Status.FIXED;
insertPatchSetProblem.outcome = "Inserted as patch set " + psId.get();
} catch (StorageException | IOException | UpdateException | RestApiException e) {
logger.atWarning().withCause(e).log("Error in consistency check of change %s", notes.getChangeId());
for (ProblemInfo pi : currProblems) {
pi.status = Status.FIX_FAILED;
pi.outcome = "Error inserting merged patch set";
}
return;
}
}
use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.
the class ReceiveCommits method autoCloseChanges.
private void autoCloseChanges(ReceiveCommand cmd, Task progress) {
try (TraceTimer traceTimer = newTimer("autoCloseChanges")) {
logger.atFine().log("Starting auto-closing of changes");
String refName = cmd.getRefName();
Set<Change.Id> ids = new HashSet<>();
// handleRegularCommands
try {
retryHelper.changeUpdate("autoCloseChanges", updateFactory -> {
try (BatchUpdate bu = updateFactory.create(projectState.getNameKey(), user, TimeUtil.now());
ObjectInserter ins = repo.newObjectInserter();
ObjectReader reader = ins.newReader();
RevWalk rw = new RevWalk(reader)) {
if (ObjectId.zeroId().equals(cmd.getOldId())) {
// potentially expensive computation that loop over all commits.
return null;
}
bu.setRepository(repo, rw, ins);
// TODO(dborowitz): Teach BatchUpdate to ignore missing changes.
RevCommit newTip = rw.parseCommit(cmd.getNewId());
BranchNameKey branch = BranchNameKey.create(project.getNameKey(), refName);
rw.reset();
rw.sort(RevSort.REVERSE);
rw.markStart(newTip);
rw.markUninteresting(rw.parseCommit(cmd.getOldId()));
Map<Change.Key, ChangeNotes> byKey = null;
List<ReplaceRequest> replaceAndClose = new ArrayList<>();
int existingPatchSets = 0;
int newPatchSets = 0;
SubmissionId submissionId = null;
COMMIT: for (RevCommit c; (c = rw.next()) != null; ) {
rw.parseBody(c);
// refs pointing to this commit.
for (PatchSet.Id psId : receivePackRefCache.patchSetIdsFromObjectId(c.copy())) {
Optional<ChangeNotes> notes = getChangeNotes(psId.changeId());
if (notes.isPresent() && notes.get().getChange().getDest().equals(branch)) {
if (submissionId == null) {
submissionId = new SubmissionId(notes.get().getChange());
}
existingPatchSets++;
bu.addOp(notes.get().getChangeId(), setPrivateOpFactory.create(false, null));
bu.addOp(psId.changeId(), mergedByPushOpFactory.create(requestScopePropagator, psId, submissionId, refName, newTip.getId().getName()));
continue COMMIT;
}
}
for (String changeId : ChangeUtil.getChangeIdsFromFooter(c, urlFormatter.get())) {
if (byKey == null) {
byKey = retryHelper.changeIndexQuery("queryOpenChangesByKeyByBranch", q -> openChangesByKeyByBranch(q, branch)).call();
}
ChangeNotes onto = byKey.get(Change.key(changeId.trim()));
if (onto != null) {
newPatchSets++;
// Hold onto this until we're done with the walk, as the call to
// req.validate below calls isMergedInto which resets the walk.
ReplaceRequest req = new ReplaceRequest(onto.getChangeId(), c, cmd, false);
req.notes = onto;
replaceAndClose.add(req);
continue COMMIT;
}
}
}
for (ReplaceRequest req : replaceAndClose) {
Change.Id id = req.notes.getChangeId();
if (!req.validateNewPatchSetForAutoClose()) {
logger.atFine().log("Not closing %s because validation failed", id);
continue;
}
if (submissionId == null) {
submissionId = new SubmissionId(req.notes.getChange());
}
req.addOps(bu, null);
bu.addOp(id, setPrivateOpFactory.create(false, null));
bu.addOp(id, mergedByPushOpFactory.create(requestScopePropagator, req.psId, submissionId, refName, newTip.getId().getName()).setPatchSetProvider(req.replaceOp::getPatchSet));
bu.addOp(id, new ChangeProgressOp(progress));
ids.add(id);
}
logger.atFine().log("Auto-closing %d changes with existing patch sets and %d with new patch" + " sets", existingPatchSets, newPatchSets);
bu.execute();
} catch (IOException | StorageException | PermissionBackendException e) {
throw new StorageException("Failed to auto-close changes", e);
}
// If we are here, we didn't throw UpdateException. Record the result.
// The ordering is indeterminate due to the HashSet; unfortunately, Change.Id
// doesn't
// fit into TreeSet.
ids.stream().forEach(id -> result.addChange(ReceiveCommitsResult.ChangeStatus.AUTOCLOSED, id));
return null;
}).defaultTimeoutMultiplier(5).call();
} catch (RestApiException e) {
logger.atSevere().withCause(e).log("Can't insert patchset");
} catch (UpdateException e) {
logger.atSevere().withCause(e).log("Failed to auto-close changes");
} finally {
logger.atFine().log("Done auto-closing changes");
}
}
}
use of com.google.gerrit.extensions.restapi.RestApiException in project gerrit by GerritCodeReview.
the class ReceiveCommits method insertChangesAndPatchSets.
private void insertChangesAndPatchSets(ImmutableList<CreateRequest> newChanges, Task replaceProgress) {
try (TraceTimer traceTimer = newTimer("insertChangesAndPatchSets", Metadata.builder().resourceCount(newChanges.size()))) {
ReceiveCommand magicBranchCmd = magicBranch != null ? magicBranch.cmd : null;
if (magicBranchCmd != null && magicBranchCmd.getResult() != NOT_ATTEMPTED) {
logger.atWarning().log("Skipping change updates on %s because ref update failed: %s %s", project.getName(), magicBranchCmd.getResult(), Strings.nullToEmpty(magicBranchCmd.getMessage()));
return;
}
try (BatchUpdate bu = batchUpdateFactory.create(project.getNameKey(), user.materializedCopy(), TimeUtil.now());
ObjectInserter ins = repo.newObjectInserter();
ObjectReader reader = ins.newReader();
RevWalk rw = new RevWalk(reader)) {
bu.setRepository(repo, rw, ins);
bu.setRefLogMessage("push");
if (magicBranch != null) {
bu.setNotify(magicBranch.getNotifyForNewChange());
}
logger.atFine().log("Adding %d replace requests", newChanges.size());
for (ReplaceRequest replace : replaceByChange.values()) {
replace.addOps(bu, replaceProgress);
if (magicBranch != null) {
bu.setNotifyHandling(replace.ontoChange, magicBranch.getNotifyHandling(replace.notes));
if (magicBranch.shouldPublishComments()) {
bu.addOp(replace.notes.getChangeId(), publishCommentsOp.create(replace.psId, project.getNameKey()));
Optional<ChangeNotes> changeNotes = getChangeNotes(replace.notes.getChangeId());
if (!changeNotes.isPresent()) {
// If not present, no need to update attention set here since this is a new change.
continue;
}
List<HumanComment> drafts = commentsUtil.draftByChangeAuthor(changeNotes.get(), user.getAccountId());
if (drafts.isEmpty()) {
// If no comments, attention set shouldn't update since the user didn't reply.
continue;
}
replyAttentionSetUpdates.processAutomaticAttentionSetRulesOnReply(bu, changeNotes.get(), isReadyForReview(changeNotes.get()), user, drafts);
}
}
}
logger.atFine().log("Adding %d create requests", newChanges.size());
for (CreateRequest create : newChanges) {
create.addOps(bu);
}
logger.atFine().log("Adding %d group update requests", newChanges.size());
updateGroups.forEach(r -> r.addOps(bu));
logger.atFine().log("Executing batch");
try {
bu.execute();
} catch (UpdateException e) {
throw asRestApiException(e);
}
replaceByChange.values().stream().forEach(req -> result.addChange(ReceiveCommitsResult.ChangeStatus.REPLACED, req.ontoChange));
newChanges.stream().forEach(req -> result.addChange(ReceiveCommitsResult.ChangeStatus.CREATED, req.changeId));
if (magicBranchCmd != null) {
magicBranchCmd.setResult(OK);
}
for (ReplaceRequest replace : replaceByChange.values()) {
String rejectMessage = replace.getRejectMessage();
if (rejectMessage == null) {
if (replace.inputCommand.getResult() == NOT_ATTEMPTED) {
// Not necessarily the magic branch, so need to set OK on the original value.
replace.inputCommand.setResult(OK);
}
} else {
logger.atFine().log("Rejecting due to message from ReplaceOp");
reject(replace.inputCommand, rejectMessage);
}
}
} catch (ResourceConflictException e) {
addError(e.getMessage());
reject(magicBranchCmd, "conflict");
} catch (BadRequestException | UnprocessableEntityException | AuthException e) {
logger.atFine().withCause(e).log("Rejecting due to client error");
reject(magicBranchCmd, e.getMessage());
} catch (RestApiException | IOException e) {
throw new StorageException("Can't insert change/patch set for " + project.getName(), e);
}
if (magicBranch != null && magicBranch.submit) {
try {
submit(newChanges, replaceByChange.values());
} catch (ResourceConflictException e) {
addError(e.getMessage());
reject(magicBranchCmd, "conflict");
} catch (RestApiException | StorageException | UpdateException | IOException | ConfigInvalidException | PermissionBackendException e) {
logger.atSevere().withCause(e).log("Error submitting changes to %s", project.getName());
reject(magicBranchCmd, "error during submit");
}
}
}
}
Aggregations