private void updateChangeStatus(OpenBranch ob, List<ChangeData> submitted, IdentifiedUser caller) throws ResourceConflictException { List<Change.Id> problemChanges = new ArrayList<>(submitted.size()); logDebug("Updating change status for {} changes", submitted.size()); for (ChangeData cd : submitted) { Change.Id id = cd.getId(); try { Change c = cd.change(); CodeReviewCommit commit = commits.get(id); CommitMergeStatus s = commit != null ? commit.getStatusCode() : null; logDebug("Status of change {} ({}) on {}: {}", id, commit.name(), c.getDest(), s); checkState(s != null, "status not set for change %s; expected to previously fail fast", id); setApproval(cd, caller); ObjectId mergeResultRev = ob.mergeTip != null ? ob.mergeTip.getMergeResults().get(commit) : null; String txt = s.getMessage(); // The change notes must be forcefully reloaded so that the SUBMIT // approval that we added earlier is visible commit.notes().reload(); if (s == CommitMergeStatus.CLEAN_MERGE) { setMerged(c, message(c, txt + getByAccountName(commit)), mergeResultRev); } else if (s == CommitMergeStatus.CLEAN_REBASE || s == CommitMergeStatus.CLEAN_PICK) { setMerged( c, message(c, txt + " as " + commit.name() + getByAccountName(commit)), mergeResultRev); } else if (s == CommitMergeStatus.ALREADY_MERGED) { setMerged(c, null, mergeResultRev); } else { throw new IllegalStateException( "unexpected status " + s + " for change " + c.getId() + "; expected to previously fail fast"); } } catch (OrmException | IOException err) { logWarn("Error updating change status for " + id, err); problemChanges.add(id); } } if (problemChanges.isEmpty()) { return; } StringBuilder msg = new StringBuilder("Error updating status of change"); if (problemChanges.size() == 1) { msg.append(' ').append(problemChanges.iterator().next()); } else { msg.append('s').append(Joiner.on(", ").join(problemChanges)); } throw new ResourceConflictException(msg.toString()); }
private void checkMergeStrategyResults(ChangeSet cs, Collection<BranchBatch> batches) throws ResourceConflictException { for (ChangeData cd : flattenBatches(batches)) { Change.Id id = cd.getId(); CodeReviewCommit commit = commits.get(id); CommitMergeStatus s = commit != null ? commit.getStatusCode() : null; if (s == null) { problems.put(id, "internal error: change not processed by merge strategy"); continue; } switch (s) { case CLEAN_MERGE: case CLEAN_REBASE: case CLEAN_PICK: case ALREADY_MERGED: break; // Merge strategy accepted this change. case PATH_CONFLICT: case REBASE_MERGE_CONFLICT: case MANUAL_RECURSIVE_MERGE: case CANNOT_CHERRY_PICK_ROOT: case NOT_FAST_FORWARD: // TODO(dborowitz): Reformat these messages to be more appropriate for // short problem descriptions. problems.put(id, CharMatcher.is('\n').collapseFrom(s.getMessage(), ' ')); break; case MISSING_DEPENDENCY: problems.put(id, "depends on change that was not submitted"); break; default: problems.put(id, "unspecified merge failure: " + s); break; } } failFast(cs); }