// Copyright (C) 2014 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.change;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.entities.RefNames.REFS_CHANGES;
import static com.google.gerrit.server.ChangeUtil.PS_ID_ORDER;
import static java.util.Comparator.comparing;
import static java.util.Objects.requireNonNull;

import com.google.auto.value.AutoValue;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.SetMultimap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmissionId;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.FixInput;
import com.google.gerrit.extensions.common.ProblemInfo;
import com.google.gerrit.extensions.common.ProblemInfo.Status;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.account.Accounts;
import com.google.gerrit.server.config.UrlFormatter;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.PatchSetState;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.plugincontext.PluginItemContext;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.RepoContext;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * Checks changes for various kinds of inconsistency and corruption.
 *
 * <p>A single instance may be reused for checking multiple changes, but not concurrently.
 */
public class ConsistencyChecker {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  @AutoValue
  public abstract static class Result {
    private static Result create(ChangeNotes notes, List<ProblemInfo> problems) {
      return new AutoValue_ConsistencyChecker_Result(
          notes.getChangeId(), notes.getChange(), ImmutableList.copyOf(problems));
    }

    public abstract Change.Id id();

    @Nullable
    public abstract Change change();

    public abstract ImmutableList<ProblemInfo> problems();
  }

  private final ChangeNotes.Factory notesFactory;
  private final Accounts accounts;
  private final PluginItemContext<AccountPatchReviewStore> accountPatchReviewStore;
  private final GitRepositoryManager repoManager;
  private final PatchSetInfoFactory patchSetInfoFactory;
  private final PatchSetInserter.Factory patchSetInserterFactory;
  private final PatchSetUtil psUtil;
  private final Provider<CurrentUser> user;
  private final Provider<PersonIdent> serverIdent;
  private final RetryHelper retryHelper;
  private final DynamicItem<UrlFormatter> urlFormatter;

  private BatchUpdate.Factory updateFactory;
  private FixInput fix;
  private ChangeNotes notes;
  private Repository repo;
  private RevWalk rw;
  private ObjectInserter oi;

  private RevCommit tip;
  private SetMultimap<ObjectId, PatchSet> patchSetsBySha;
  private PatchSet currPs;
  private RevCommit currPsCommit;

  private List<ProblemInfo> problems;

  @Inject
  ConsistencyChecker(
      @GerritPersonIdent Provider<PersonIdent> serverIdent,
      ChangeNotes.Factory notesFactory,
      Accounts accounts,
      PluginItemContext<AccountPatchReviewStore> accountPatchReviewStore,
      GitRepositoryManager repoManager,
      PatchSetInfoFactory patchSetInfoFactory,
      PatchSetInserter.Factory patchSetInserterFactory,
      PatchSetUtil psUtil,
      Provider<CurrentUser> user,
      RetryHelper retryHelper,
      DynamicItem<UrlFormatter> urlFormatter) {
    this.accounts = accounts;
    this.accountPatchReviewStore = accountPatchReviewStore;
    this.notesFactory = notesFactory;
    this.patchSetInfoFactory = patchSetInfoFactory;
    this.patchSetInserterFactory = patchSetInserterFactory;
    this.psUtil = psUtil;
    this.repoManager = repoManager;
    this.retryHelper = retryHelper;
    this.serverIdent = serverIdent;
    this.user = user;
    this.urlFormatter = urlFormatter;
    reset();
  }

  private void reset() {
    updateFactory = null;
    notes = null;
    repo = null;
    rw = null;
    problems = new ArrayList<>();
  }

  private Change change() {
    return notes.getChange();
  }

  public Result check(ChangeNotes notes, @Nullable FixInput f) {
    requireNonNull(notes);
    try {
      return retryHelper
          .changeUpdate(
              "checkChangeConsistency",
              buf -> {
                try {
                  reset();
                  this.updateFactory = buf;
                  this.notes = notes;
                  fix = f;
                  checkImpl();
                  return result();
                } finally {
                  if (rw != null) {
                    rw.getObjectReader().close();
                    rw.close();
                    oi.close();
                  }
                  if (repo != null) {
                    repo.close();
                  }
                }
              })
          .call();
    } catch (RestApiException e) {
      return logAndReturnOneProblem(e, notes, "Error checking change: " + e.getMessage());
    } catch (UpdateException e) {
      return logAndReturnOneProblem(e, notes, "Error checking change");
    }
  }

  private Result logAndReturnOneProblem(Exception e, ChangeNotes notes, String problem) {
    logger.atWarning().withCause(e).log("Error checking change %s", notes.getChangeId());
    return Result.create(notes, ImmutableList.of(problem(problem)));
  }

  private void checkImpl() {
    checkOwner();
    checkCurrentPatchSetEntity();

    // All checks that require the repo.
    if (!openRepo()) {
      return;
    }
    if (!checkPatchSets()) {
      return;
    }
    checkMerged();
  }

  private void checkOwner() {
    try {
      if (!accounts.get(change().getOwner()).isPresent()) {
        problem("Missing change owner: " + change().getOwner());
      }
    } catch (IOException | ConfigInvalidException e) {
      ProblemInfo problem = problem("Failed to look up owner");
      logger.atWarning().withCause(e).log(
          "Error in consistency check of change %s: %s", notes.getChangeId(), problem);
    }
  }

  private void checkCurrentPatchSetEntity() {
    try {
      currPs = psUtil.current(notes);
      if (currPs == null) {
        problem(
            String.format("Current patch set %d not found", change().currentPatchSetId().get()));
      }
    } catch (StorageException e) {
      ProblemInfo problem = problem("Failed to look up current patch set");
      logger.atWarning().withCause(e).log(
          "Error in consistency check of change %s: %s", notes.getChangeId(), problem);
    }
  }

  private boolean openRepo() {
    Project.NameKey project = change().getDest().project();
    try {
      repo = repoManager.openRepository(project);
      oi = repo.newObjectInserter();
      rw = new RevWalk(oi.newReader());
      return true;
    } catch (RepositoryNotFoundException e) {
      ProblemInfo problem = problem("Destination repository not found: " + project);
      logger.atWarning().withCause(e).log(
          "Error in consistency check of change %s: %s", notes.getChangeId(), problem);
      return false;
    } catch (IOException e) {
      ProblemInfo problem = problem("Failed to open repository: " + project);
      logger.atWarning().withCause(e).log(
          "Error in consistency check of change %s: %s", notes.getChangeId(), problem);
      return false;
    }
  }

  private boolean checkPatchSets() {
    List<PatchSet> all;
    try {
      // Iterate in descending order.
      all = PS_ID_ORDER.sortedCopy(psUtil.byChange(notes));
    } catch (StorageException e) {
      ProblemInfo problem = problem("Failed to look up patch sets");
      logger.atWarning().withCause(e).log(
          "Error in consistency check of change %s: %s", notes.getChangeId(), problem);
      return false;
    }
    patchSetsBySha = MultimapBuilder.hashKeys(all.size()).treeSetValues(PS_ID_ORDER).build();

    Map<String, Ref> refs;
    try {
      refs =
          repo.getRefDatabase()
              .exactRef(all.stream().map(ps -> ps.id().toRefName()).toArray(String[]::new));
    } catch (IOException e) {
      ProblemInfo problem = problem("Error reading refs");
      logger.atWarning().withCause(e).log(
          "Error in consistency check of change %s: %s", notes.getChangeId(), problem);
      refs = Collections.emptyMap();
    }

    List<DeletePatchSetFromDbOp> deletePatchSetOps = new ArrayList<>();
    for (PatchSet ps : all) {
      // Check revision format.
      int psNum = ps.id().get();
      String refName = ps.id().toRefName();
      ObjectId objId = ps.commitId();
      patchSetsBySha.put(objId, ps);

      // Check ref existence.
      ProblemInfo refProblem = null;
      Ref ref = refs.get(refName);
      if (ref == null) {
        refProblem = problem("Ref missing: " + refName);
      } else if (!objId.equals(ref.getObjectId())) {
        String actual = ref.getObjectId() != null ? ref.getObjectId().name() : "null";
        refProblem =
            problem(
                String.format(
                    "Expected %s to point to %s, found %s", ref.getName(), objId.name(), actual));
      }

      // Check object existence.
      RevCommit psCommit = parseCommit(objId, String.format("patch set %d", psNum));
      if (psCommit == null) {
        if (fix != null && fix.deletePatchSetIfCommitMissing) {
          deletePatchSetOps.add(new DeletePatchSetFromDbOp(lastProblem(), ps.id()));
        }
        continue;
      } else if (refProblem != null && fix != null) {
        fixPatchSetRef(refProblem, ps);
      }
      if (ps.id().equals(change().currentPatchSetId())) {
        currPsCommit = psCommit;
      }
    }

    // Delete any bad patch sets found above, in a single update.
    deletePatchSets(deletePatchSetOps);

    // Check for duplicates.
    for (Map.Entry<ObjectId, Collection<PatchSet>> e : patchSetsBySha.asMap().entrySet()) {
      if (e.getValue().size() > 1) {
        problem(
            String.format(
                "Multiple patch sets pointing to %s: %s",
                e.getKey().name(), Collections2.transform(e.getValue(), PatchSet::number)));
      }
    }

    return currPs != null && currPsCommit != null;
  }

  private void checkMerged() {
    String refName = change().getDest().branch();
    Ref dest;
    try {
      dest = repo.getRefDatabase().exactRef(refName);
    } catch (IOException e) {
      problem("Failed to look up destination ref: " + refName);
      return;
    }
    if (dest == null) {
      problem("Destination ref not found (may be new branch): " + refName);
      return;
    }
    tip = parseCommit(dest.getObjectId(), "destination ref " + refName);
    if (tip == null) {
      return;
    }

    if (fix != null && fix.expectMergedAs != null) {
      checkExpectMergedAs();
    } else {
      boolean merged;
      try {
        merged = rw.isMergedInto(currPsCommit, tip);
      } catch (IOException e) {
        problem("Error checking whether patch set " + currPs.id().get() + " is merged");
        return;
      }
      checkMergedBitMatchesStatus(currPs.id(), currPsCommit, merged);
    }
  }

  private ProblemInfo wrongChangeStatus(PatchSet.Id psId, RevCommit commit) {
    String refName = change().getDest().branch();
    return problem(
        formatProblemMessage(
            "Patch set %d (%s) is merged into destination ref %s (%s), but change"
                + " status is %s",
            psId.get(), commit.name(), refName, tip.name()));
  }

  private void checkMergedBitMatchesStatus(PatchSet.Id psId, RevCommit commit, boolean merged) {
    String refName = change().getDest().branch();
    if (merged && !change().isMerged()) {
      ProblemInfo p = wrongChangeStatus(psId, commit);
      if (fix != null) {
        fixMerged(p);
      }
    } else if (!merged && change().isMerged()) {
      problem(
          formatProblemMessage(
              "Patch set %d (%s) is not merged into"
                  + " destination ref %s (%s), but change status is %s",
              currPs.id().get(), commit.name(), refName, tip.name()));
    }
  }

  private String formatProblemMessage(
      String message, int psId, String commitName, String refName, String tipName) {
    return String.format(
        message,
        psId,
        commitName,
        refName,
        tipName,
        ChangeUtil.status(change()).toUpperCase(Locale.US));
  }

  private void checkExpectMergedAs() {
    if (!ObjectId.isId(fix.expectMergedAs)) {
      problem("Invalid revision on expected merged commit: " + fix.expectMergedAs);
      return;
    }
    ObjectId objId = ObjectId.fromString(fix.expectMergedAs);
    RevCommit commit = parseCommit(objId, "expected merged commit");
    if (commit == null) {
      return;
    }

    try {
      if (!rw.isMergedInto(commit, tip)) {
        problem(
            String.format(
                "Expected merged commit %s is not merged into destination ref %s (%s)",
                commit.name(), change().getDest().branch(), tip.name()));
        return;
      }

      List<PatchSet.Id> thisCommitPsIds = new ArrayList<>();
      for (Ref ref : repo.getRefDatabase().getRefsByPrefix(REFS_CHANGES)) {
        if (!ref.getObjectId().equals(commit)) {
          continue;
        }
        PatchSet.Id psId = PatchSet.Id.fromRef(ref.getName());
        if (psId == null) {
          continue;
        }
        try {
          Change c = notesFactory.createChecked(change().getProject(), psId.changeId()).getChange();
          if (!c.getDest().equals(change().getDest())) {
            continue;
          }
        } catch (StorageException e) {
          logger.atWarning().withCause(e).log(
              "Error in consistency check of change %s", notes.getChangeId());
          // Include this patch set; should cause an error below, which is good.
        }
        thisCommitPsIds.add(psId);
      }
      switch (thisCommitPsIds.size()) {
        case 0:
          // No patch set for this commit; insert one.
          rw.parseBody(commit);
          String changeId =
              Iterables.getFirst(
                  ChangeUtil.getChangeIdsFromFooter(commit, urlFormatter.get()), null);
          // Missing Change-Id footer is ok, but mismatched is not.
          if (changeId != null && !changeId.equals(change().getKey().get())) {
            problem(
                String.format(
                    "Expected merged commit %s has Change-Id: %s, but expected %s",
                    commit.name(), changeId, change().getKey().get()));
            return;
          }
          insertMergedPatchSet(commit, null, false);
          break;

        case 1:
          // Existing patch set ref pointing to this commit.
          PatchSet.Id id = thisCommitPsIds.get(0);
          if (id.equals(change().currentPatchSetId())) {
            // If it's the current patch set, we can just fix the status.
            fixMerged(wrongChangeStatus(id, commit));
          } else if (id.get() > change().currentPatchSetId().get()) {
            // If it's newer than the current patch set, reuse this patch set
            // ID when inserting a new merged patch set.
            insertMergedPatchSet(commit, id, true);
          } else {
            // If it's older than the current patch set, just delete the old
            // ref, and use a new ID when inserting a new merged patch set.
            insertMergedPatchSet(commit, id, false);
          }
          break;

        default:
          problem(
              String.format(
                  "Multiple patch sets for expected merged commit %s: %s",
                  commit.name(),
                  thisCommitPsIds.stream()
                      .sorted(comparing(PatchSet.Id::get))
                      .collect(toImmutableList())));
          break;
      }
    } catch (IOException e) {
      ProblemInfo problem =
          problem("Error looking up expected merged commit " + fix.expectMergedAs);
      logger.atWarning().withCause(e).log(
          "Error in consistency check of change %s: %s", notes.getChangeId(), problem);
    }
  }

  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;
    }
  }

  private static class FixMergedOp implements BatchUpdateOp {
    private final ProblemInfo p;

    private FixMergedOp(ProblemInfo p) {
      this.p = p;
    }

    @Override
    public boolean updateChange(ChangeContext ctx) {
      ctx.getChange().setStatus(Change.Status.MERGED);
      ctx.getUpdate(ctx.getChange().currentPatchSetId())
          .fixStatusToMerged(new SubmissionId(ctx.getChange()));
      p.status = Status.FIXED;
      p.outcome = "Marked change as merged";
      return true;
    }
  }

  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";
    }
  }

  private BatchUpdate newBatchUpdate() {
    return updateFactory.create(change().getProject(), user.get(), TimeUtil.now());
  }

  private void fixPatchSetRef(ProblemInfo p, PatchSet ps) {
    try {
      RefUpdate ru = repo.updateRef(ps.id().toRefName());
      ru.setForceUpdate(true);
      ru.setNewObjectId(ps.commitId());
      ru.setRefLogIdent(newRefLogIdent());
      ru.setRefLogMessage("Repair patch set ref", true);
      RefUpdate.Result result = ru.update();
      switch (result) {
        case NEW:
        case FORCED:
        case FAST_FORWARD:
        case NO_CHANGE:
          p.status = Status.FIXED;
          p.outcome = "Repaired patch set ref";
          return;
        case IO_FAILURE:
        case LOCK_FAILURE:
        case NOT_ATTEMPTED:
        case REJECTED:
        case REJECTED_CURRENT_BRANCH:
        case RENAMED:
        case REJECTED_MISSING_OBJECT:
        case REJECTED_OTHER_REASON:
        default:
          p.status = Status.FIX_FAILED;
          p.outcome = "Failed to update patch set ref: " + result;
          return;
      }
    } catch (IOException e) {
      String msg = "Error fixing patch set ref";
      logger.atWarning().withCause(e).log("%s %s", msg, ps.id().toRefName());
      p.status = Status.FIX_FAILED;
      p.outcome = msg;
    }
  }

  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;
      }
    }
  }

  private class DeletePatchSetFromDbOp implements BatchUpdateOp {
    private final ProblemInfo p;
    private final PatchSet.Id psId;

    private DeletePatchSetFromDbOp(ProblemInfo p, PatchSet.Id psId) {
      this.p = p;
      this.psId = psId;
    }

    @Override
    public boolean updateChange(ChangeContext ctx) throws PatchSetInfoNotAvailableException {
      // Delete dangling key references.
      accountPatchReviewStore.run(s -> s.clearReviewed(psId));

      // For NoteDb setting the state to deleted is sufficient to filter everything out.
      ctx.getUpdate(psId).setPatchSetState(PatchSetState.DELETED);

      p.status = Status.FIXED;
      p.outcome = "Deleted patch set";
      return true;
    }
  }

  private static class NoPatchSetsWouldRemainException extends RestApiException {
    private static final long serialVersionUID = 1L;

    private NoPatchSetsWouldRemainException() {
      super("Cannot delete patch set; no patch sets would remain");
    }
  }

  private class UpdateCurrentPatchSetOp implements BatchUpdateOp {
    private final Set<PatchSet.Id> toDelete;

    private UpdateCurrentPatchSetOp(List<DeletePatchSetFromDbOp> deleteOps) {
      toDelete = new HashSet<>();
      for (DeletePatchSetFromDbOp op : deleteOps) {
        toDelete.add(op.psId);
      }
    }

    @Override
    public boolean updateChange(ChangeContext ctx)
        throws PatchSetInfoNotAvailableException, NoPatchSetsWouldRemainException {
      if (!toDelete.contains(ctx.getChange().currentPatchSetId())) {
        return false;
      }
      TreeSet<PatchSet.Id> all = new TreeSet<>(comparing(PatchSet.Id::get));
      // Doesn't make any assumptions about the order in which deletes happen
      // and whether they are seen by this op; we are already given the full set
      // of patch sets that will eventually be deleted in this update.
      for (PatchSet ps : psUtil.byChange(ctx.getNotes())) {
        if (!toDelete.contains(ps.id())) {
          all.add(ps.id());
        }
      }
      if (all.isEmpty()) {
        throw new NoPatchSetsWouldRemainException();
      }
      ctx.getChange().setCurrentPatchSet(patchSetInfoFactory.get(ctx.getNotes(), all.last()));
      return true;
    }
  }

  private PersonIdent newRefLogIdent() {
    CurrentUser u = user.get();
    if (u.isIdentifiedUser()) {
      return u.asIdentifiedUser().newRefLogIdent();
    }
    return serverIdent.get();
  }

  private RevCommit parseCommit(ObjectId objId, String desc) {
    try {
      return rw.parseCommit(objId);
    } catch (MissingObjectException e) {
      problem(String.format("Object missing: %s: %s", desc, objId.name()));
    } catch (IncorrectObjectTypeException e) {
      problem(String.format("Not a commit: %s: %s", desc, objId.name()));
    } catch (IOException e) {
      problem(String.format("Failed to look up: %s: %s", desc, objId.name()));
    }
    return null;
  }

  private ProblemInfo problem(String msg) {
    ProblemInfo p = new ProblemInfo();
    p.message = requireNonNull(msg);
    problems.add(p);
    return p;
  }

  private ProblemInfo lastProblem() {
    return problems.get(problems.size() - 1);
  }

  private Result result() {
    return Result.create(notes, problems);
  }
}
