use of com.google.gerrit.server.update.UpdateException in project gerrit by GerritCodeReview.
the class ChangeEditUtil method publish.
/**
* Promote change edit to patch set, by squashing the edit into its parent.
*
* @param updateFactory factory for creating updates.
* @param ctl the {@code ChangeControl} of the change to which the change edit belongs
* @param edit change edit to publish
* @param notify Notify handling that defines to whom email notifications should be sent after the
* change edit is published.
* @param accountsToNotify Accounts that should be notified after the change edit is published.
* @throws IOException
* @throws OrmException
* @throws UpdateException
* @throws RestApiException
*/
public void publish(BatchUpdate.Factory updateFactory, ChangeControl ctl, final ChangeEdit edit, NotifyHandling notify, ListMultimap<RecipientType, Account.Id> accountsToNotify) throws IOException, OrmException, RestApiException, UpdateException {
Change change = edit.getChange();
try (Repository repo = gitManager.openRepository(change.getProject());
ObjectInserter oi = repo.newObjectInserter();
ObjectReader reader = oi.newReader();
RevWalk rw = new RevWalk(reader)) {
PatchSet basePatchSet = edit.getBasePatchSet();
if (!basePatchSet.getId().equals(change.currentPatchSetId())) {
throw new ResourceConflictException("only edit for current patch set can be published");
}
RevCommit squashed = squashEdit(rw, oi, edit.getEditCommit(), basePatchSet);
PatchSet.Id psId = ChangeUtil.nextPatchSetId(repo, change.currentPatchSetId());
PatchSetInserter inserter = patchSetInserterFactory.create(ctl, psId, squashed).setNotify(notify).setAccountsToNotify(accountsToNotify);
StringBuilder message = new StringBuilder("Patch Set ").append(inserter.getPatchSetId().get()).append(": ");
// Previously checked that the base patch set is the current patch set.
ObjectId prior = ObjectId.fromString(basePatchSet.getRevision().get());
ChangeKind kind = changeKindCache.getChangeKind(change.getProject(), rw, repo.getConfig(), prior, squashed);
if (kind == ChangeKind.NO_CODE_CHANGE) {
message.append("Commit message was updated.");
inserter.setDescription("Edit commit message");
} else {
message.append("Published edit on patch set ").append(basePatchSet.getPatchSetId()).append(".");
}
try (BatchUpdate bu = updateFactory.create(db.get(), change.getProject(), ctl.getUser(), TimeUtil.nowTs())) {
bu.setRepository(repo, rw, oi);
bu.addOp(change.getId(), inserter.setDraft(change.getStatus() == Status.DRAFT || basePatchSet.isDraft()).setMessage(message.toString()));
bu.addOp(change.getId(), new BatchUpdateOp() {
@Override
public void updateRepo(RepoContext ctx) throws Exception {
ctx.addRefUpdate(edit.getEditCommit().copy(), ObjectId.zeroId(), edit.getRefName());
}
});
bu.execute();
}
indexer.index(db.get(), inserter.getChange());
}
}
use of com.google.gerrit.server.update.UpdateException in project gerrit by GerritCodeReview.
the class DeleteComment method applyImpl.
@Override
public CommentInfo applyImpl(BatchUpdate.Factory batchUpdateFactory, CommentResource rsrc, DeleteCommentInput input) throws RestApiException, IOException, ConfigInvalidException, OrmException, PermissionBackendException, UpdateException {
CurrentUser user = userProvider.get();
permissionBackend.user(user).check(GlobalPermission.ADMINISTRATE_SERVER);
String newMessage = getCommentNewMessage(user.asIdentifiedUser().getName(), input.reason);
DeleteCommentOp deleteCommentOp = new DeleteCommentOp(rsrc, newMessage);
try (BatchUpdate batchUpdate = batchUpdateFactory.create(dbProvider.get(), rsrc.getRevisionResource().getProject(), user, TimeUtil.nowTs())) {
batchUpdate.addOp(rsrc.getRevisionResource().getChange().getId(), deleteCommentOp).execute();
}
ChangeNotes updatedNotes = notesFactory.createChecked(rsrc.getRevisionResource().getChange().getId());
List<Comment> changeComments = commentsUtil.publishedByChange(dbProvider.get(), updatedNotes);
Optional<Comment> updatedComment = changeComments.stream().filter(c -> c.key.equals(rsrc.getComment().key)).findFirst();
if (!updatedComment.isPresent()) {
// This should not happen as this endpoint should not remove the whole comment.
throw new ResourceNotFoundException("comment not found: " + rsrc.getComment().key);
}
return commentJson.get().newCommentFormatter().format(updatedComment.get());
}
use of com.google.gerrit.server.update.UpdateException in project gerrit by GerritCodeReview.
the class ReceiveCommits method insertChangesAndPatchSets.
private void insertChangesAndPatchSets() {
ReceiveCommand magicBranchCmd = magicBranch != null ? magicBranch.cmd : null;
if (magicBranchCmd != null && magicBranchCmd.getResult() != NOT_ATTEMPTED) {
logWarn(String.format("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(db, project.getNameKey(), user.materializedCopy(), TimeUtil.nowTs());
ObjectInserter ins = repo.newObjectInserter();
ObjectReader reader = ins.newReader();
RevWalk rw = new RevWalk(reader)) {
bu.setRepository(repo, rw, ins).updateChangesInParallel();
bu.setRequestId(receiveId);
bu.setRefLogMessage("push");
logDebug("Adding {} replace requests", newChanges.size());
for (ReplaceRequest replace : replaceByChange.values()) {
replace.addOps(bu, replaceProgress);
}
logDebug("Adding {} create requests", newChanges.size());
for (CreateRequest create : newChanges) {
create.addOps(bu);
}
logDebug("Adding {} group update requests", newChanges.size());
updateGroups.forEach(r -> r.addOps(bu));
logDebug("Adding {} additional ref updates", actualCommands.size());
actualCommands.forEach(c -> bu.addRepoOnlyOp(new UpdateOneRefOp(c)));
logDebug("Executing batch");
try {
bu.execute();
} catch (UpdateException e) {
throw INSERT_EXCEPTION.apply(e);
}
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 {
logDebug("Rejecting due to message from ReplaceOp");
reject(replace.inputCommand, rejectMessage);
}
}
} catch (ResourceConflictException e) {
addMessage(e.getMessage());
reject(magicBranchCmd, "conflict");
} catch (RestApiException | IOException err) {
logError("Can't insert change/patch set for " + project.getName(), err);
reject(magicBranchCmd, "internal server error: " + err.getMessage());
}
if (magicBranch != null && magicBranch.submit) {
try {
submit(newChanges, replaceByChange.values());
} catch (ResourceConflictException e) {
addMessage(e.getMessage());
reject(magicBranchCmd, "conflict");
} catch (RestApiException | OrmException e) {
logError("Error submitting changes to " + project.getName(), e);
reject(magicBranchCmd, "error during submit");
}
}
}
use of com.google.gerrit.server.update.UpdateException in project gerrit by GerritCodeReview.
the class ReceiveCommits method autoCloseChanges.
private void autoCloseChanges(final ReceiveCommand cmd) {
logDebug("Starting auto-closing of changes");
String refName = cmd.getRefName();
checkState(!MagicBranch.isMagicBranch(refName), "shouldn't be auto-closing changes on magic branch %s", refName);
// insertChangesAndPatchSets.
try (BatchUpdate bu = batchUpdateFactory.create(db, projectControl.getProject().getNameKey(), user, TimeUtil.nowTs());
ObjectInserter ins = repo.newObjectInserter();
ObjectReader reader = ins.newReader();
RevWalk rw = new RevWalk(reader)) {
bu.setRepository(repo, rw, ins).updateChangesInParallel();
bu.setRequestId(receiveId);
// TODO(dborowitz): Teach BatchUpdate to ignore missing changes.
RevCommit newTip = rw.parseCommit(cmd.getNewId());
Branch.NameKey branch = new Branch.NameKey(project.getNameKey(), refName);
rw.reset();
rw.markStart(newTip);
if (!ObjectId.zeroId().equals(cmd.getOldId())) {
rw.markUninteresting(rw.parseCommit(cmd.getOldId()));
}
ListMultimap<ObjectId, Ref> byCommit = changeRefsById();
Map<Change.Key, ChangeNotes> byKey = null;
List<ReplaceRequest> replaceAndClose = new ArrayList<>();
int existingPatchSets = 0;
int newPatchSets = 0;
COMMIT: for (RevCommit c; (c = rw.next()) != null; ) {
rw.parseBody(c);
for (Ref ref : byCommit.get(c.copy())) {
existingPatchSets++;
PatchSet.Id psId = PatchSet.Id.fromRef(ref.getName());
bu.addOp(psId.getParentKey(), mergedByPushOpFactory.create(requestScopePropagator, psId, refName));
continue COMMIT;
}
for (String changeId : c.getFooterLines(CHANGE_ID)) {
if (byKey == null) {
byKey = openChangesByBranch(branch);
}
ChangeNotes onto = byKey.get(new 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 (final ReplaceRequest req : replaceAndClose) {
Change.Id id = req.notes.getChangeId();
if (!req.validate(true)) {
logDebug("Not closing {} because validation failed", id);
continue;
}
req.addOps(bu, null);
bu.addOp(id, mergedByPushOpFactory.create(requestScopePropagator, req.psId, refName).setPatchSetProvider(new Provider<PatchSet>() {
@Override
public PatchSet get() {
return req.replaceOp.getPatchSet();
}
}));
bu.addOp(id, new ChangeProgressOp(closeProgress));
}
logDebug("Auto-closing {} changes with existing patch sets and {} with new patch sets", existingPatchSets, newPatchSets);
bu.execute();
} catch (RestApiException e) {
logError("Can't insert patchset", e);
} catch (IOException | OrmException | UpdateException | PermissionBackendException e) {
logError("Can't scan for changes to close", e);
}
}
use of com.google.gerrit.server.update.UpdateException in project gerrit by GerritCodeReview.
the class MergeOp method integrateIntoHistory.
private void integrateIntoHistory(ChangeSet cs) throws IntegrationException, RestApiException {
checkArgument(!cs.furtherHiddenChanges(), "cannot integrate hidden changes into history");
logDebug("Beginning merge attempt on {}", cs);
Map<Branch.NameKey, BranchBatch> toSubmit = new HashMap<>();
ListMultimap<Branch.NameKey, ChangeData> cbb;
try {
cbb = cs.changesByBranch();
} catch (OrmException e) {
throw new IntegrationException("Error reading changes to submit", e);
}
Set<Branch.NameKey> branches = cbb.keySet();
for (Branch.NameKey branch : branches) {
OpenRepo or = openRepo(branch.getParentKey());
if (or != null) {
toSubmit.put(branch, validateChangeList(or, cbb.get(branch)));
}
}
// Done checks that don't involve running submit strategies.
commitStatus.maybeFailVerbose();
try {
SubmoduleOp submoduleOp = subOpFactory.create(branches, orm);
List<SubmitStrategy> strategies = getSubmitStrategies(toSubmit, submoduleOp, dryrun);
this.allProjects = submoduleOp.getProjectsInOrder();
batchUpdateFactory.execute(orm.batchUpdates(batchUpdateFactory, allProjects), new SubmitStrategyListener(submitInput, strategies, commitStatus), submissionId, dryrun);
} catch (NoSuchProjectException e) {
throw new ResourceNotFoundException(e.getMessage());
} catch (IOException | SubmoduleException e) {
throw new IntegrationException(e);
} catch (UpdateException e) {
// BatchUpdate may have inadvertently wrapped an IntegrationException
// thrown by some legacy SubmitStrategyOp code that intended the error
// message to be user-visible. Copy the message from the wrapped
// exception.
//
// If you happen across one of these, the correct fix is to convert the
// inner IntegrationException to a ResourceConflictException.
String msg;
if (e.getCause() instanceof IntegrationException) {
msg = e.getCause().getMessage();
} else {
msg = "Error submitting change" + (cs.size() != 1 ? "s" : "");
}
throw new IntegrationException(msg, e);
}
}
Aggregations