private void updateChangeStatus( List<ChangeData> submitted, Branch.NameKey destBranch, boolean dryRun, IdentifiedUser caller) throws NoSuchChangeException, IntegrationException, ResourceConflictException, OrmException { if (!dryRun) { logDebug("Updating change status for {} changes", submitted.size()); } else { logDebug("Checking change state for {} changes in a dry run", submitted.size()); } MergeTip mergeTip = mergeTips.get(destBranch); for (ChangeData cd : submitted) { Change c = cd.change(); CodeReviewCommit commit = commits.get(c.getId()); CommitMergeStatus s = commit != null ? commit.getStatusCode() : null; if (s == null) { // Shouldn't ever happen, but leave the change alone. We'll pick // it up on the next pass. // logDebug( "Submitted change {} did not appear in set of new commits" + " produced by merge strategy", c.getId()); continue; } if (!dryRun) { try { setApproval(cd, caller); } catch (IOException e) { throw new OrmException(e); } } String txt = s.getMessage(); logDebug("Status of change {} ({}) on {}: {}", c.getId(), commit.name(), c.getDest(), s); // If mergeTip is null merge failed and mergeResultRev will not be read. ObjectId mergeResultRev = mergeTip != null ? mergeTip.getMergeResults().get(commit) : null; // The change notes must be forcefully reloaded so that the SUBMIT // approval that we added earlier is visible commit.notes().reload(); try { ChangeMessage msg; switch (s) { case CLEAN_MERGE: if (!dryRun) { setMerged(c, message(c, txt + getByAccountName(commit)), mergeResultRev); } break; case CLEAN_REBASE: case CLEAN_PICK: if (!dryRun) { setMerged( c, message(c, txt + " as " + commit.name() + getByAccountName(commit)), mergeResultRev); } break; case ALREADY_MERGED: if (!dryRun) { setMerged(c, null, mergeResultRev); } break; case PATH_CONFLICT: case REBASE_MERGE_CONFLICT: case MANUAL_RECURSIVE_MERGE: case CANNOT_CHERRY_PICK_ROOT: case NOT_FAST_FORWARD: case INVALID_PROJECT_CONFIGURATION: case INVALID_PROJECT_CONFIGURATION_PLUGIN_VALUE_NOT_PERMITTED: case INVALID_PROJECT_CONFIGURATION_PLUGIN_VALUE_NOT_EDITABLE: case INVALID_PROJECT_CONFIGURATION_PARENT_PROJECT_NOT_FOUND: case INVALID_PROJECT_CONFIGURATION_ROOT_PROJECT_CANNOT_HAVE_PARENT: case SETTING_PARENT_PROJECT_ONLY_ALLOWED_BY_ADMIN: setNew(commit.notes(), message(c, txt)); throw new ResourceConflictException( "Cannot merge " + commit.name() + "\n" + s.getMessage()); case MISSING_DEPENDENCY: logDebug("Change {} is missing dependency", c.getId()); throw new IntegrationException("Cannot merge " + commit.name() + "\n" + s.getMessage()); case REVISION_GONE: logDebug("Commit not found for change {}", c.getId()); msg = new ChangeMessage( new ChangeMessage.Key(c.getId(), ChangeUtil.messageUUID(db)), null, TimeUtil.nowTs(), c.currentPatchSetId()); msg.setMessage("Failed to read commit for this patch set"); setNew(commit.notes(), msg); throw new IntegrationException(msg.getMessage()); default: msg = message(c, "Unspecified merge failure: " + s.name()); setNew(commit.notes(), msg); throw new IntegrationException(msg.getMessage()); } } catch (OrmException | IOException err) { logWarn("Error updating change status for " + c.getId(), err); } } }
private void setNew(ChangeNotes notes, final ChangeMessage msg) throws NoSuchChangeException, IOException { Change c = notes.getChange(); Change change = null; ChangeUpdate update = null; try { db.changes().beginTransaction(c.getId()); try { change = db.changes() .atomicUpdate( c.getId(), new AtomicUpdate<Change>() { @Override public Change update(Change c) { if (c.getStatus().isOpen()) { c.setStatus(Change.Status.NEW); ChangeUtil.updated(c); } return c; } }); ChangeControl control = changeControl(change); // TODO(yyonas): atomic change is not propagated. update = updateFactory.create(control, c.getLastUpdatedOn()); if (msg != null) { cmUtil.addChangeMessage(db, update, msg); } db.commit(); } finally { db.rollback(); } } catch (OrmException err) { logWarn("Cannot record merge failure message", err); } if (update != null) { update.commit(); } indexer.index(db, change); PatchSetApproval submitter = null; try { submitter = approvalsUtil.getSubmitter(db, notes, notes.getChange().currentPatchSetId()); } catch (Exception e) { logError("Cannot get submitter for change " + notes.getChangeId(), e); } if (submitter != null) { try { hooks.doMergeFailedHook( c, accountCache.get(submitter.getAccountId()).getAccount(), db.patchSets().get(c.currentPatchSetId()), msg.getMessage(), db); } catch (OrmException ex) { logError("Cannot run hook for merge failed " + c.getId(), ex); } } }