// Copyright (C) 2020 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.plugins.codeowners.validation;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.gerrit.plugins.codeowners.backend.CodeOwners.getInvalidCodeOwnerConfigCause;
import static java.util.Objects.requireNonNull;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.plugins.codeowners.backend.ChangedFiles;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigImportType;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigReference;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerReference;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerResolver;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnersInternalServerErrorException;
import com.google.gerrit.plugins.codeowners.backend.InvalidCodeOwnerConfigException;
import com.google.gerrit.plugins.codeowners.backend.PathCodeOwners;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginProjectConfigSnapshot;
import com.google.gerrit.plugins.codeowners.backend.config.InvalidPluginConfigurationException;
import com.google.gerrit.plugins.codeowners.common.ChangedFile;
import com.google.gerrit.plugins.codeowners.common.CodeOwnerConfigValidationPolicy;
import com.google.gerrit.plugins.codeowners.common.MergeCommitStrategy;
import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics;
import com.google.gerrit.plugins.codeowners.metrics.ValidationTrigger;
import com.google.gerrit.plugins.codeowners.util.JgitPath;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidationListener;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.git.validators.MergeValidationException;
import com.google.gerrit.server.git.validators.MergeValidationListener;
import com.google.gerrit.server.git.validators.ValidationMessage;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.DiffNotAvailableException;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.permissions.RefPermission;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * Validates modifications to the code owner config files.
 *
 * <p>The validations are best effort to prevent invalid code owner configs from entering the
 * repository, but we cannot prevent it in all cases. Still the validation is useful since it
 * prevents most issues and also gives quick feedback to uploaders about typos (e.g. if an email is
 * misspelled it's not breaking anything, but the intended change of the uploader is not working).
 *
 * <p>Code owner configs are not validated when:
 *
 * <ul>
 *   <li>the {@code code-owners} plugin is not installed (this means when the {@code code-owners}
 *       plugin gets installed it is possible that invalid code owner configs already exist in the
 *       repository)
 *   <li>the code owners functionality is disabled for the repository or branch (this means when the
 *       code owners functionality gets enabled it is possible that invalid code owner configs
 *       already exist in the repository)
 *   <li>the {@code code-owners} plugin configuration is invalid (in this case we don't know which
 *       files are code owner config files, so we allow all uploads rather than blocking all
 *       uploads, to reduce the risk of breaking the plugin configuration {@code
 *       com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfigValidator} takes care to
 *       validate modifications to the plugin configuration)
 *   <li>updates happen behind Gerrit's back (e.g. pushes that bypass Gerrit)
 * </ul>
 *
 * <p>In addition it is possible that code owner config files get invalid after they have been
 * submitted:
 *
 * <ul>
 *   <li>configuration parameters that are relevant for the validation are changed (e.g. the account
 *       visibility is changed, another code owners backend is configured which now uses a different
 *       syntax or different names for code owner config files, or the file extension for code owner
 *       config file is set/changed)
 *   <li>emails of user may change so that emails in code owner configs can no longer be resolved
 *   <li>imported code owner config files may get deleted or renamed so that the import references
 *       can no longer be resolved
 * </ul>
 */
@Singleton
public class CodeOwnerConfigValidator implements CommitValidationListener, MergeValidationListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final String pluginName;
  private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
  private final GitRepositoryManager repoManager;
  private final ChangedFiles changedFiles;
  private final Provider<CodeOwnerResolver> codeOwnerResolverProvider;
  private final PermissionBackend permissionBackend;
  private final ProjectCache projectCache;
  private final ChangeNotes.Factory changeNotesFactory;
  private final PatchSetUtil patchSetUtil;
  private final IdentifiedUser.GenericFactory userFactory;
  private final SkipCodeOwnerConfigValidationPushOption skipCodeOwnerConfigValidationPushOption;
  private final CodeOwnerMetrics codeOwnerMetrics;

  @Inject
  CodeOwnerConfigValidator(
      @PluginName String pluginName,
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration,
      GitRepositoryManager repoManager,
      ChangedFiles changedFiles,
      Provider<CodeOwnerResolver> codeOwnerResolver,
      PermissionBackend permissionBackend,
      ProjectCache projectCache,
      ChangeNotes.Factory changeNotesFactory,
      PatchSetUtil patchSetUtil,
      IdentifiedUser.GenericFactory userFactory,
      SkipCodeOwnerConfigValidationPushOption skipCodeOwnerConfigValidationPushOption,
      CodeOwnerMetrics codeOwnerMetrics) {
    this.pluginName = pluginName;
    this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
    this.repoManager = repoManager;
    this.changedFiles = changedFiles;
    this.codeOwnerResolverProvider = codeOwnerResolver;
    this.permissionBackend = permissionBackend;
    this.projectCache = projectCache;
    this.changeNotesFactory = changeNotesFactory;
    this.patchSetUtil = patchSetUtil;
    this.userFactory = userFactory;
    this.skipCodeOwnerConfigValidationPushOption = skipCodeOwnerConfigValidationPushOption;
    this.codeOwnerMetrics = codeOwnerMetrics;
  }

  @Override
  public List<CommitValidationMessage> onCommitReceived(CommitReceivedEvent receiveEvent)
      throws CommitValidationException {
    try (TraceTimer traceTimer =
        TraceContext.newTimer(
            "Validate code owner config files on commit received",
            Metadata.builder()
                .projectName(receiveEvent.project.getName())
                .commit(receiveEvent.commit.name())
                .branchName(receiveEvent.refName)
                .username(receiveEvent.user.getLoggableName())
                .build())) {
      CodeOwnerConfigValidationPolicy codeOwnerConfigValidationPolicy =
          codeOwnersPluginConfiguration
              .getProjectConfig(receiveEvent.getProjectNameKey())
              .getCodeOwnerConfigValidationPolicyForCommitReceived(receiveEvent.refName);
      logger.atFine().log("codeOwnerConfigValidationPolicy = %s", codeOwnerConfigValidationPolicy);
      boolean metricRecordingDone = false;
      Optional<ValidationResult> validationResult;
      if (!codeOwnerConfigValidationPolicy.runValidation()) {
        validationResult =
            Optional.of(
                ValidationResult.create(
                    pluginName,
                    "skipping validation of code owner config files",
                    new CommitValidationMessage(
                        "code owners config validation is disabled", ValidationMessage.Type.HINT)));
      } else {
        try {
          validationResult =
              validateCodeOwnerConfig(
                  receiveEvent.getBranchNameKey(),
                  receiveEvent.commit,
                  receiveEvent.user,
                  codeOwnerConfigValidationPolicy.isForced(),
                  receiveEvent.pushOptions);
        } catch (RuntimeException e) {
          codeOwnerMetrics.countCodeOwnerConfigValidations.increment(
              ValidationTrigger.COMMIT_RECEIVED,
              com.google.gerrit.plugins.codeowners.metrics.ValidationResult.FAILED,
              codeOwnerConfigValidationPolicy.isDryRun());
          metricRecordingDone = true;

          if (!codeOwnerConfigValidationPolicy.isDryRun()) {
            throw e;
          }

          // The validation was executed as dry-run and failures during the validation should not
          // cause an error. Hence we swallow the exception here.
          logger.atWarning().withCause(e).log(
              "ignoring failure during validation of code owner config files in revision %s"
                  + " (project = %s, branch = %s) because the validation was performed as dry-run",
              receiveEvent.commit.getName(),
              receiveEvent.getBranchNameKey().project(),
              receiveEvent.getBranchNameKey().branch());
          validationResult = Optional.empty();
        }
      }
      if (!validationResult.isPresent()) {
        return ImmutableList.of();
      }

      logger.atFine().log("validation result = %s", validationResult.get());
      if (!metricRecordingDone) {
        codeOwnerMetrics.countCodeOwnerConfigValidations.increment(
            ValidationTrigger.COMMIT_RECEIVED,
            validationResult.get().hasError()
                ? com.google.gerrit.plugins.codeowners.metrics.ValidationResult.REJECTED
                : com.google.gerrit.plugins.codeowners.metrics.ValidationResult.PASSED,
            codeOwnerConfigValidationPolicy.isDryRun());
      }
      return validationResult
          .get()
          .processForOnCommitReceived(codeOwnerConfigValidationPolicy.isDryRun());
    }
  }

  @Override
  public void onPreMerge(
      Repository repository,
      CodeReviewRevWalk revWalk,
      CodeReviewCommit commit,
      ProjectState projectState,
      BranchNameKey branchNameKey,
      PatchSet.Id patchSetId,
      IdentifiedUser caller)
      throws MergeValidationException {
    try (TraceTimer traceTimer =
        TraceContext.newTimer(
            "Validate code owner config files on pre merge",
            Metadata.builder()
                .projectName(branchNameKey.project().get())
                .commit(commit.name())
                .branchName(branchNameKey.branch())
                .username(caller.getLoggableName())
                .patchSetId(patchSetId.get())
                .build())) {
      CodeOwnerConfigValidationPolicy codeOwnerConfigValidationPolicy =
          codeOwnersPluginConfiguration
              .getProjectConfig(branchNameKey.project())
              .getCodeOwnerConfigValidationPolicyForSubmit(branchNameKey.branch());
      logger.atFine().log("codeOwnerConfigValidationPolicy = %s", codeOwnerConfigValidationPolicy);
      Optional<ValidationResult> validationResult;
      if (!codeOwnerConfigValidationPolicy.runValidation()) {
        validationResult =
            Optional.of(
                ValidationResult.create(
                    pluginName,
                    "skipping validation of code owner config files",
                    new CommitValidationMessage(
                        "code owners config validation is disabled", ValidationMessage.Type.HINT)));
      } else {
        try {
          ChangeNotes changeNotes =
              changeNotesFactory.create(projectState.getNameKey(), commit.change().getId());
          PatchSet patchSet = patchSetUtil.get(changeNotes, patchSetId);
          IdentifiedUser patchSetUploader = userFactory.create(patchSet.uploader());
          validationResult =
              validateCodeOwnerConfig(
                  branchNameKey,
                  commit,
                  patchSetUploader,
                  codeOwnerConfigValidationPolicy.isForced(),
                  /* pushOptions= */ ImmutableListMultimap.of());
        } catch (RuntimeException e) {
          codeOwnerMetrics.countCodeOwnerConfigValidations.increment(
              ValidationTrigger.PRE_MERGE,
              com.google.gerrit.plugins.codeowners.metrics.ValidationResult.FAILED,
              codeOwnerConfigValidationPolicy.isDryRun());

          if (!codeOwnerConfigValidationPolicy.isDryRun()) {
            throw e;
          }

          // The validation was executed as dry-run and failures during the validation should not
          // cause an error. Hence we swallow the exception here.
          logger.atFine().withCause(e).log(
              "ignoring failure during validation of code owner config files in revision %s"
                  + " (project = %s, branch = %s) because the validation was performed as dry-run",
              commit.name(), branchNameKey.project(), branchNameKey.branch());
          validationResult = Optional.empty();
        }
      }
      if (validationResult.isPresent()) {
        logger.atFine().log("validation result = %s", validationResult.get());
        codeOwnerMetrics.countCodeOwnerConfigValidations.increment(
            ValidationTrigger.PRE_MERGE,
            validationResult.get().hasError()
                ? com.google.gerrit.plugins.codeowners.metrics.ValidationResult.REJECTED
                : com.google.gerrit.plugins.codeowners.metrics.ValidationResult.PASSED,
            codeOwnerConfigValidationPolicy.isDryRun());
        validationResult.get().processForOnPreMerge(codeOwnerConfigValidationPolicy.isDryRun());
      }
    }
  }

  /**
   * Validates the code owner config files which are newly added or modified in the given commit.
   *
   * @param branchNameKey the project and branch that contains the provided commit or for which the
   *     commit is being pushed
   * @param revCommit the commit for which newly added and modified code owner configs should be
   *     validated
   * @param user user for which the code owner visibility checks should be performed
   * @param force whether the validation should be done even if the code owners functionality is
   *     disabled for the branch
   * @return the validation result, {@link Optional#empty()} if no validation is performed because
   *     the given commit doesn't contain newly added or modified code owner configs
   */
  private Optional<ValidationResult> validateCodeOwnerConfig(
      BranchNameKey branchNameKey,
      RevCommit revCommit,
      IdentifiedUser user,
      boolean force,
      ImmutableListMultimap<String, String> pushOptions) {
    CodeOwnersPluginProjectConfigSnapshot codeOwnersConfig =
        codeOwnersPluginConfiguration.getProjectConfig(branchNameKey.project());
    logger.atFine().log("force = %s", force);
    if (!force && codeOwnersConfig.isDisabled(branchNameKey.branch())) {
      return Optional.of(
          ValidationResult.create(
              pluginName,
              "skipping validation of code owner config files",
              new CommitValidationMessage(
                  "code-owners functionality is disabled", ValidationMessage.Type.HINT)));
    }

    try {
      if (skipCodeOwnerConfigValidationPushOption.skipValidation(pushOptions)) {
        logger.atFine().log("skip validation requested");
        return Optional.of(
            ValidationResult.create(
                pluginName,
                "skipping validation of code owner config files",
                new CommitValidationMessage(
                    String.format(
                        "the validation is skipped due to the --%s~%s push option",
                        pluginName, SkipCodeOwnerConfigValidationPushOption.NAME),
                    ValidationMessage.Type.HINT)));
      }
    } catch (AuthException e) {
      logger.atFine().withCause(e).log("Not allowed to skip code owner config validation");
      return Optional.of(
          ValidationResult.create(
              pluginName,
              "skipping code owner config validation not allowed",
              new CommitValidationMessage(e.getMessage(), ValidationMessage.Type.ERROR)));
    } catch (SkipCodeOwnerConfigValidationPushOption.InvalidValueException e) {
      logger.atFine().log("%s", e.getMessage());
      return Optional.of(
          ValidationResult.create(
              pluginName,
              "invalid push option",
              new CommitValidationMessage(e.getMessage(), ValidationMessage.Type.ERROR)));
    }

    if (codeOwnersConfig.areCodeOwnerConfigsReadOnly()) {
      return Optional.of(
          ValidationResult.create(
              pluginName,
              "modifying code owner config files not allowed",
              new CommitValidationMessage(
                  "code owner config files are configured to be read-only",
                  ValidationMessage.Type.ERROR)));
    }

    try {
      CodeOwnerBackend codeOwnerBackend = codeOwnersConfig.getBackend(branchNameKey.branch());

      // For merge commits, always do the comparison against the destination branch
      // (MergeCommitStrategy.ALL_CHANGED_FILES). Doing the comparison against the auto-merge
      // (MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION) is not possible because loading the
      // auto-merge cannot reuse the rev walk that can see newly created merge commits and hence
      // trying to get the auto merge would fail with a missing object exception. This is why we
      // use MergeCommitStrategy.ALL_CHANGED_FILES here even if
      // MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION is configured.
      ImmutableList<ChangedFile> modifiedCodeOwnerConfigFiles =
          changedFiles
              .getFromDiffCache(
                  branchNameKey.project(), revCommit, MergeCommitStrategy.ALL_CHANGED_FILES)
              .stream()
              // filter out deletions (files without new path)
              .filter(changedFile -> changedFile.newPath().isPresent())
              // filter out non code owner config files
              .filter(
                  changedFile ->
                      codeOwnerBackend.isCodeOwnerConfigFile(
                          branchNameKey.project(),
                          Paths.get(changedFile.newPath().get().toString())
                              .getFileName()
                              .toString()))
              .collect(toImmutableList());

      if (modifiedCodeOwnerConfigFiles.isEmpty()) {
        return Optional.empty();
      }

      // validate the code owner config files
      return Optional.of(
          ValidationResult.create(
              pluginName,
              modifiedCodeOwnerConfigFiles.stream()
                  .flatMap(
                      changedFile ->
                          validateCodeOwnerConfig(
                              user, codeOwnerBackend, branchNameKey, changedFile, revCommit))));
    } catch (InvalidPluginConfigurationException e) {
      // If the code-owners plugin configuration is invalid we cannot get the code owners backend
      // and hence we are not able to detect and validate code owner config files. Instead of
      // failing in this case (which would block all change uploads) we only log a warning and
      // accept that it's possible to add invalid code owner configs while the plugin configuration
      // is invalid.
      logger.atWarning().log(
          "cannot validate code owner config files due to invalid code-owners plugin"
              + " configuration: %s",
          e.getMessage());
      return Optional.of(
          ValidationResult.create(
              pluginName,
              "skipping validation of code owner config files",
              new CommitValidationMessage(
                  "code-owners plugin configuration is invalid,"
                      + " cannot validate code owner config files",
                  ValidationMessage.Type.WARNING)));
    } catch (IOException | DiffNotAvailableException e) {
      String errorMessage =
          String.format(
              "failed to validate code owner config files in revision %s"
                  + " (project = %s, branch = %s)",
              revCommit.getName(), branchNameKey.project(), branchNameKey.branch());
      throw new CodeOwnersInternalServerErrorException(errorMessage, e);
    }
  }

  /**
   * Validates the specified code owner config and returns a stream of validation messages.
   *
   * @param user user for which the code owner visibility checks should be performed
   * @param codeOwnerBackend the code owner backend from which the code owner config can be loaded
   * @param branchNameKey the project and branch of the code owner config
   * @param changedFile the changed file that represents the code owner config
   * @param revCommit the commit from which the code owner config should be loaded
   * @return a stream of validation messages that describe issues with the code owner config, an
   *     empty stream if there are no issues
   */
  public Stream<CommitValidationMessage> validateCodeOwnerConfig(
      IdentifiedUser user,
      CodeOwnerBackend codeOwnerBackend,
      BranchNameKey branchNameKey,
      ChangedFile changedFile,
      RevCommit revCommit) {
    requireNonNull(user, "user");
    requireNonNull(codeOwnerBackend, "codeOwnerBackend");
    requireNonNull(branchNameKey, "branchNameKey");
    requireNonNull(changedFile, "changedFile");
    requireNonNull(revCommit, "revCommit");

    if (!changedFile.newPath().isPresent()) {
      // The code owner config file was deleted. Hence we do not need to do any validation.
      return Stream.of();
    }

    CodeOwnerConfig codeOwnerConfig;
    try {
      // Load the code owner config. If the code owner config is not parsable this will fail with a
      // InvalidConfigException (wrapped in a CodeOwnersInternalServerErrorException) that we handle
      // below.
      CodeOwnerConfig.Key codeOwnerConfigKey =
          createCodeOwnerConfigKey(branchNameKey, changedFile.newPath().get());
      codeOwnerConfig =
          codeOwnerBackend
              .getCodeOwnerConfig(codeOwnerConfigKey, revCommit)
              // We already know that the path exists, so either the code owner config is
              // successfully loaded (this case) or the loading fails with an exception because the
              // code owner config is not parseable (catch block below), but it cannot happen that
              // the code owner config is not found and an empty Optional is returned.
              .orElseThrow(
                  () ->
                      new IllegalStateException(
                          String.format(
                              "code owner config %s not found in revision %s",
                              codeOwnerConfigKey, revCommit.name())));
    } catch (CodeOwnersInternalServerErrorException codeOwnersInternalServerErrorException) {
      // Loading the code owner config has failed.
      Optional<InvalidCodeOwnerConfigException> invalidCodeOwnerConfigException =
          getInvalidCodeOwnerConfigCause(codeOwnersInternalServerErrorException);
      if (!invalidCodeOwnerConfigException.isPresent()) {
        // Propagate any failure that is not related to the contents of the code owner config.
        throw codeOwnersInternalServerErrorException;
      }

      // The exception was caused by a ConfigInvalidException. This means loading the code owner
      // config failed because it is not parseable.

      // Convert the message from the InvalidConfigException into a validation message and return
      // it.
      return Stream.of(
          new CommitValidationMessage(
              invalidCodeOwnerConfigException.get().getMessage(),
              getValidationMessageTypeForParsingError(
                  codeOwnerBackend, branchNameKey, changedFile, revCommit)));
    }

    // The code owner config was successfully loaded and parsed.

    // We only report new issues as errors. If the same issues already existed in the base version
    // we just report them as warnings. To know which issues already existed in the base version
    // we must load it, what we do here, and then run the validation on it.
    Optional<CodeOwnerConfig> baseCodeOwnerConfig;
    try {
      baseCodeOwnerConfig =
          getBaseCodeOwnerConfig(codeOwnerBackend, branchNameKey, changedFile, revCommit);
    } catch (CodeOwnersInternalServerErrorException codeOwnersInternalServerErrorException) {
      if (getInvalidCodeOwnerConfigCause(codeOwnersInternalServerErrorException).isPresent()) {
        // The base code owner config is non-parseable. Since the update makes the code owner
        // config parseable, it is a good update even if the code owner config still contains
        // issues. Hence in this case we downgrade all validation errors in the new version to
        // warnings so that the update is not blocked.
        return validateCodeOwnerConfig(branchNameKey, user, codeOwnerBackend, codeOwnerConfig)
            .map(CodeOwnerConfigValidator::downgradeErrorToWarning);
      }

      // Propagate any exception that was not caused by the content of the code owner config.
      throw codeOwnersInternalServerErrorException;
    }

    // Validate the parsed code owner config.
    if (baseCodeOwnerConfig.isPresent()) {
      return validateCodeOwnerConfig(
          branchNameKey, user, codeOwnerBackend, codeOwnerConfig, baseCodeOwnerConfig.get());
    }
    return validateCodeOwnerConfig(branchNameKey, user, codeOwnerBackend, codeOwnerConfig);
  }

  /**
   * Create the key for a code owner config from a given file path.
   *
   * @param branchNameKey the project and branch of the code owner config
   * @param filePath the file path of the code owner config
   * @return the key of the code owner config
   */
  private CodeOwnerConfig.Key createCodeOwnerConfigKey(BranchNameKey branchNameKey, Path filePath) {
    Path folderPath =
        filePath.getParent() != null
            ? JgitPath.of(filePath.getParent()).getAsAbsolutePath()
            : Paths.get("/");
    String fileName = filePath.getFileName().toString();
    return CodeOwnerConfig.Key.create(branchNameKey, folderPath, fileName);
  }

  /**
   * Loads and returns the base code owner config if it exists.
   *
   * <p>Throws a {@link ConfigInvalidException} (wrapped in a {@link
   * CodeOwnersInternalServerErrorException} if the base code owner config exists, but is not
   * parseable.
   *
   * @param codeOwnerBackend the code owner backend from which the base code owner config can be
   *     loaded
   * @param branchNameKey the project and branch of the base code owner config
   * @param changedFile the changed file of the code owner config that contains the path of the base
   *     code owner config as old path
   * @param revCommit the commit of the code owner config for which the base code owner config
   *     should be loaded
   * @return the loaded base code owner config, {@link Optional#empty()} if no base code owner
   *     config exists (e.g. if the code owner config is newly created)
   */
  private Optional<CodeOwnerConfig> getBaseCodeOwnerConfig(
      CodeOwnerBackend codeOwnerBackend,
      BranchNameKey branchNameKey,
      ChangedFile changedFile,
      RevCommit revCommit) {
    if (changedFile.oldPath().isPresent()) {
      Optional<ObjectId> parentRevision = getParentRevision(branchNameKey.project(), revCommit);
      if (parentRevision.isPresent()) {
        CodeOwnerConfig.Key baseCodeOwnerConfigKey =
            createCodeOwnerConfigKey(branchNameKey, changedFile.oldPath().get());
        return codeOwnerBackend.getCodeOwnerConfig(baseCodeOwnerConfigKey, parentRevision.get());
      }
    }
    return Optional.empty();
  }

  /**
   * Returns the {@link com.google.gerrit.server.git.validators.ValidationMessage.Type} (FATAL or
   * WARNING) that should be used for a parsing error of the code owner config file (specified as
   * {@code changedFile}).
   *
   * <p>If {@link com.google.gerrit.server.git.validators.ValidationMessage.Type#FATAL} is returned
   * the upload will be blocked, if {@link
   * com.google.gerrit.server.git.validators.ValidationMessage.Type#WARNING} is returned the upload
   * can succeed and the parsing error will only be shown as warning.
   *
   * <p>If a previous version of the code owner config exists and the previous version was also
   * non-parseable, we want to allow the upload even if the new version is still non-parseable, as
   * it is not making anything worse. Hence in this case the parsing error should be returned as
   * {@link com.google.gerrit.server.git.validators.ValidationMessage.Type#WARNING}, whereas a new
   * parsing error should be returned as {@link
   * com.google.gerrit.server.git.validators.ValidationMessage.Type#FATAL}.
   *
   * @param codeOwnerBackend the code owner backend from which the code owner config can be loaded
   * @param branchNameKey the project and branch of the code owner config
   * @param changedFile the changed file that represents the code owner config
   * @param revCommit the commit from which the code owner config should be loaded
   * @return the {@link com.google.gerrit.server.git.validators.ValidationMessage.Type} (ERROR or
   *     WARNING) that should be used for parsing error of a code owner config file
   */
  private ValidationMessage.Type getValidationMessageTypeForParsingError(
      CodeOwnerBackend codeOwnerBackend,
      BranchNameKey branchNameKey,
      ChangedFile changedFile,
      RevCommit revCommit) {
    //
    if (changedFile.oldPath().isPresent()) {
      // A previous version of the code owner config exists.
      ObjectId parentRevision =
          getParentRevision(branchNameKey.project(), revCommit)
              // Since there is an old path a parent revision must exist.
              .orElseThrow(
                  () ->
                      new IllegalStateException(
                          String.format(
                              "parent revision for revision %s in project %s not found",
                              revCommit.name(), branchNameKey.project().get())));
      try {
        // Try to load the code owner config from the parent revision to see if it was parseable
        // there.
        CodeOwnerConfig.Key baseCodeOwnerConfigKey =
            createCodeOwnerConfigKey(branchNameKey, changedFile.oldPath().get());
        codeOwnerBackend.getCodeOwnerConfig(baseCodeOwnerConfigKey, parentRevision);
        // The code owner config at the parent revision is parseable. This means the parsing error
        // is introduced by the new commit and we should block uploading it, which we achieve by
        // setting the validation message type to fatal.
        return ValidationMessage.Type.FATAL;
      } catch (CodeOwnersInternalServerErrorException codeOwnersInternalServerErrorException) {
        // Loading the base code owner config has failed.
        if (getInvalidCodeOwnerConfigCause(codeOwnersInternalServerErrorException).isPresent()) {
          // The code owner config was already non-parseable before, hence we do not need to
          // block the upload if the code owner config is still non-parseable.
          // Using warning as type means that uploads are not blocked.
          return ValidationMessage.Type.WARNING;
        }
        // Propagate any failure that is not related to the contents of the code owner config.
        throw codeOwnersInternalServerErrorException;
      }
    }

    // The code owner config is newly created. Hence the parsing error comes from the commit
    // that is being pushed and we want to block it from uploading. To do this we set the
    // validation message type to fatal.
    return ValidationMessage.Type.FATAL;
  }

  /**
   * Returns the first parent of the given revision.
   *
   * @param project the project that contains the revision
   * @param revCommit the commit for which the first parent should be returned
   * @return the first parent of the given revision, {@link Optional#empty()} if the given revision
   *     has no parent
   */
  private Optional<ObjectId> getParentRevision(Project.NameKey project, RevCommit revCommit) {
    if (revCommit.getParentCount() == 0) {
      return Optional.empty();
    }
    RevCommit firstParent = revCommit.getParent(0);
    logger.atFine().log(
        "first parent of %s in %s is %s", revCommit.name(), project.get(), firstParent.name());
    return Optional.of(firstParent);
  }

  /**
   * Returns a copy of the given commit validation message with type warning if the type the given
   * commit validation message is fatal or error. Otherwise it returns the given commit validation
   * message unchanged.
   */
  private static CommitValidationMessage downgradeErrorToWarning(
      CommitValidationMessage commitValidationMessage) {
    if (CommitValidationMessage.Type.FATAL.equals(commitValidationMessage.getType())
        || CommitValidationMessage.Type.ERROR.equals(commitValidationMessage.getType())) {
      return new CommitValidationMessage(
          commitValidationMessage.getMessage(), ValidationMessage.Type.WARNING);
    }
    return commitValidationMessage;
  }

  /**
   * Validates the given code owner config and returns validation issues as stream.
   *
   * <p>Validation errors that exist in both code owner configs are returned as warning (because
   * they are not newly introduced by the given code owner config).
   *
   * @param branchNameKey the branch and the project
   * @param user user for which the code owner visibility checks should be performed
   * @param codeOwnerBackend the code owner backend from which the code owner configs were loaded
   * @param codeOwnerConfig the code owner config that should be validated
   * @param baseCodeOwnerConfig the base code owner config
   * @return a stream of validation messages that describe issues with the code owner config, an
   *     empty stream if there are no issues
   */
  private Stream<CommitValidationMessage> validateCodeOwnerConfig(
      BranchNameKey branchNameKey,
      IdentifiedUser user,
      CodeOwnerBackend codeOwnerBackend,
      CodeOwnerConfig codeOwnerConfig,
      CodeOwnerConfig baseCodeOwnerConfig) {
    requireNonNull(codeOwnerConfig, "codeOwnerConfig");
    requireNonNull(baseCodeOwnerConfig, "baseCodeOwnerConfig");

    ImmutableSet<CommitValidationMessage> issuesInBaseVersion =
        validateCodeOwnerConfig(branchNameKey, user, codeOwnerBackend, baseCodeOwnerConfig)
            .collect(toImmutableSet());
    return validateCodeOwnerConfig(branchNameKey, user, codeOwnerBackend, codeOwnerConfig)
        .map(
            commitValidationMessage ->
                issuesInBaseVersion.contains(commitValidationMessage)
                    ? downgradeErrorToWarning(commitValidationMessage)
                    : commitValidationMessage);
  }

  /**
   * Validates the given code owner config and returns validation issues as stream.
   *
   * @param branchNameKey the branch and the project
   * @param user user for which the code owner visibility checks should be performed
   * @param codeOwnerBackend the code owner backend from which the code owner config was loaded
   * @param codeOwnerConfig the code owner config that should be validated
   * @return a stream of validation messages that describe issues with the code owner config, an
   *     empty stream if there are no issues
   */
  public Stream<CommitValidationMessage> validateCodeOwnerConfig(
      BranchNameKey branchNameKey,
      IdentifiedUser user,
      CodeOwnerBackend codeOwnerBackend,
      CodeOwnerConfig codeOwnerConfig) {
    requireNonNull(codeOwnerConfig, "codeOwnerConfig");
    return Streams.concat(
        validateCodeOwnerReferences(
            branchNameKey,
            user,
            codeOwnerBackend.getFilePath(codeOwnerConfig.key()),
            codeOwnerConfig),
        validateImports(
            branchNameKey, codeOwnerBackend.getFilePath(codeOwnerConfig.key()), codeOwnerConfig));
  }

  /**
   * Validates the code owner references of the given code owner config.
   *
   * @param branchNameKey the branch and the project
   * @param user user for which the code owner visibility checks should be performed
   * @param codeOwnerConfigFilePath the path of the code owner config file which contains the code
   *     owner references
   * @param codeOwnerConfig the code owner config for which the code owner references should be
   *     validated
   * @return a stream of validation messages that describe issues with the code owner references, an
   *     empty stream if there are no issues
   */
  private Stream<CommitValidationMessage> validateCodeOwnerReferences(
      BranchNameKey branchNameKey,
      IdentifiedUser user,
      Path codeOwnerConfigFilePath,
      CodeOwnerConfig codeOwnerConfig) {
    return codeOwnerConfig.codeOwnerSets().stream()
        .flatMap(codeOwnerSet -> codeOwnerSet.codeOwners().stream())
        .map(
            codeOwnerReference ->
                validateCodeOwnerReference(
                    branchNameKey, user, codeOwnerConfigFilePath, codeOwnerReference))
        .filter(Optional::isPresent)
        .map(Optional::get);
  }

  /**
   * Validates a code owner reference.
   *
   * @param branchNameKey the branch and the project
   * @param user user for which the code owner visibility checks should be performed
   * @param codeOwnerConfigFilePath the path of the code owner config file which contains the code
   *     owner reference
   * @param codeOwnerReference the code owner reference that should be validated.
   * @return a validation message describing the issue with the code owner reference, {@link
   *     Optional#empty()} if there is no issue
   */
  private Optional<CommitValidationMessage> validateCodeOwnerReference(
      BranchNameKey branchNameKey,
      IdentifiedUser user,
      Path codeOwnerConfigFilePath,
      CodeOwnerReference codeOwnerReference) {
    CodeOwnerResolver codeOwnerResolver = codeOwnerResolverProvider.get().forUser(user);
    if (!codeOwnerResolver.isEmailDomainAllowed(codeOwnerReference.email()).get()) {
      return nonResolvableCodeOwner(
          branchNameKey,
          String.format(
              "the domain of the code owner email '%s' in '%s' is not allowed for code owners",
              codeOwnerReference.email(), codeOwnerConfigFilePath));
    }

    // Check if the code owner reference is resolvable.
    if (codeOwnerResolver.isResolvable(codeOwnerReference)) {
      // The code owner reference was successfully resolved to at least one code owner.
      return Optional.empty();
    }

    // It was not possible to resolve the code owner reference. Possible reasons: no such account
    // exists, the code owner is not visible, the email of the code owner is not visible (see
    // CodeOwerResolver for details). We intentionally return the same generic message in all these
    // cases so that uploaders cannot probe emails for existence (e.g. they cannot add an email and
    // conclude from the error message whether the email exists).
    return nonResolvableCodeOwner(
        branchNameKey,
        String.format(
            "code owner email '%s' in '%s' cannot be resolved for %s",
            codeOwnerReference.email(), codeOwnerConfigFilePath, user.getLoggableName()));
  }

  /**
   * Validates the imports of the given code owner config.
   *
   * @param branchNameKey the branch and the project
   * @param codeOwnerConfigFilePath the path of the code owner config file which contains the code
   *     owner config
   * @param codeOwnerConfig the code owner config for which the imports should be validated
   * @return a stream of validation messages that describe issues with the imports, an empty stream
   *     if there are no issues
   */
  private Stream<CommitValidationMessage> validateImports(
      BranchNameKey branchNameKey, Path codeOwnerConfigFilePath, CodeOwnerConfig codeOwnerConfig) {
    try {
      RevCommit codeOwnerConfigRevision;
      try (Repository repo = repoManager.openRepository(branchNameKey.project());
          RevWalk revWalk = new RevWalk(repo)) {
        codeOwnerConfigRevision = revWalk.parseCommit(codeOwnerConfig.revision());
      }
      return Streams.concat(
              codeOwnerConfig.imports().stream()
                  .map(
                      codeOwnerConfigReference ->
                          validateCodeOwnerConfigReference(
                              branchNameKey,
                              codeOwnerConfigFilePath,
                              codeOwnerConfig.key(),
                              codeOwnerConfigRevision,
                              CodeOwnerConfigImportType.GLOBAL,
                              codeOwnerConfigReference)),
              codeOwnerConfig.codeOwnerSets().stream()
                  .flatMap(codeOwnerSet -> codeOwnerSet.imports().stream())
                  .map(
                      codeOwnerConfigReference ->
                          validateCodeOwnerConfigReference(
                              branchNameKey,
                              codeOwnerConfigFilePath,
                              codeOwnerConfig.key(),
                              codeOwnerConfigRevision,
                              CodeOwnerConfigImportType.PER_FILE,
                              codeOwnerConfigReference)))
          .filter(Optional::isPresent)
          .map(Optional::get);
    } catch (IOException e) {
      throw new CodeOwnersInternalServerErrorException(
          String.format("Failed to validate imports for %s in ", codeOwnerConfig.key()), e);
    }
  }

  /**
   * Validates a code owner config reference.
   *
   * @param branchNameKey the branch and the project
   * @param codeOwnerConfigFilePath the path of the code owner config file which contains the code
   *     owner config reference
   * @param keyOfImportingCodeOwnerConfig key of the importing code owner config
   * @param codeOwnerConfigRevision the commit from which the code owner config which contains the
   *     code owner config reference was loaded
   * @param importType the type of the import
   * @param codeOwnerConfigReference the code owner config reference that should be validated.
   * @return a validation message describing the issue with the code owner config reference, {@link
   *     Optional#empty()} if there is no issue
   */
  private Optional<CommitValidationMessage> validateCodeOwnerConfigReference(
      BranchNameKey branchNameKey,
      Path codeOwnerConfigFilePath,
      CodeOwnerConfig.Key keyOfImportingCodeOwnerConfig,
      RevCommit codeOwnerConfigRevision,
      CodeOwnerConfigImportType importType,
      CodeOwnerConfigReference codeOwnerConfigReference) {
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        PathCodeOwners.createKeyForImportedCodeOwnerConfig(
            keyOfImportingCodeOwnerConfig, codeOwnerConfigReference);

    if (isSelfImport(keyOfImportingCodeOwnerConfig, keyOfImportedCodeOwnerConfig)) {
      return nonResolvableImport(
          importType,
          codeOwnerConfigFilePath,
          "code owner config imports itself",
          ValidationMessage.Type.WARNING);
    }

    Optional<ProjectState> projectState = projectCache.get(keyOfImportedCodeOwnerConfig.project());
    if (!projectState.isPresent() || !isProjectReadable(keyOfImportedCodeOwnerConfig)) {
      // we intentionally use the same error message for non-existing and non-readable projects so
      // that uploaders cannot probe for the existence of projects (e.g. deduce from the error
      // message whether a project exists)
      return nonResolvableImport(
          codeOwnerConfigRevision,
          branchNameKey,
          importType,
          codeOwnerConfigReference,
          codeOwnerConfigFilePath,
          String.format("project '%s' not found", keyOfImportedCodeOwnerConfig.project().get()));
    }

    if (!projectState.get().statePermitsRead()) {
      return nonResolvableImport(
          codeOwnerConfigRevision,
          branchNameKey,
          importType,
          codeOwnerConfigReference,
          codeOwnerConfigFilePath,
          String.format(
              "project '%s' has state '%s' that doesn't permit read",
              keyOfImportedCodeOwnerConfig.project().get(),
              projectState.get().getProject().getState().name()));
    }

    Optional<ObjectId> revision =
        getRevision(
            keyOfImportingCodeOwnerConfig, codeOwnerConfigRevision, keyOfImportedCodeOwnerConfig);
    if (!revision.isPresent() || !isBranchReadable(keyOfImportedCodeOwnerConfig)) {
      // we intentionally use the same error message for non-existing and non-readable branches so
      // that uploaders cannot probe for the existence of branches (e.g. deduce from the error
      // message whether a branch exists)
      return nonResolvableImport(
          codeOwnerConfigRevision,
          branchNameKey,
          importType,
          codeOwnerConfigReference,
          codeOwnerConfigFilePath,
          String.format(
              "branch '%s' not found in project '%s'",
              keyOfImportedCodeOwnerConfig.shortBranchName(),
              keyOfImportedCodeOwnerConfig.project().get()));
    }

    CodeOwnerBackend codeOwnerBackend =
        codeOwnersPluginConfiguration
            .getProjectConfig(keyOfImportedCodeOwnerConfig.project())
            .getBackend(keyOfImportedCodeOwnerConfig.branchNameKey().branch());
    if (!codeOwnerBackend.isCodeOwnerConfigFile(
        keyOfImportedCodeOwnerConfig.project(), codeOwnerConfigReference.fileName())) {
      return nonResolvableImport(
          codeOwnerConfigRevision,
          branchNameKey,
          importType,
          codeOwnerConfigReference,
          codeOwnerConfigFilePath,
          String.format(
              "'%s' is not a code owner config file", codeOwnerConfigReference.filePath()));
    }

    try {
      // If a code owner config is imported from the same project, we must use the provided rev
      // walk, otherwise the revision may not be visible yet and trying to load a code owner config
      // from it could fail with MissingObjectException.
      Optional<CodeOwnerConfig> importedCodeOwnerConfig =
          keyOfImportedCodeOwnerConfig.project().equals(branchNameKey.project())
              ? codeOwnerBackend.getCodeOwnerConfig(keyOfImportedCodeOwnerConfig, revision.get())
              : codeOwnerBackend.getCodeOwnerConfig(keyOfImportedCodeOwnerConfig, revision.get());
      if (!importedCodeOwnerConfig.isPresent()) {
        return nonResolvableImport(
            codeOwnerConfigRevision,
            branchNameKey,
            importType,
            codeOwnerConfigReference,
            codeOwnerConfigFilePath,
            String.format(
                "'%s' does not exist (project = %s, branch = %s, revision = %s)",
                codeOwnerConfigReference.filePath(),
                keyOfImportedCodeOwnerConfig.branchNameKey().project().get(),
                keyOfImportedCodeOwnerConfig.branchNameKey().shortName(),
                revision.get().name()));
      }
    } catch (CodeOwnersInternalServerErrorException codeOwnersInternalServerErrorException) {
      if (getInvalidCodeOwnerConfigCause(codeOwnersInternalServerErrorException).isPresent()) {
        // The imported code owner config is non-parseable.
        return nonResolvableImport(
            codeOwnerConfigRevision,
            branchNameKey,
            importType,
            codeOwnerConfigReference,
            codeOwnerConfigFilePath,
            String.format(
                "'%s' is not parseable (project = %s, branch = %s)",
                codeOwnerConfigReference.filePath(),
                keyOfImportedCodeOwnerConfig.branchNameKey().project().get(),
                keyOfImportedCodeOwnerConfig.branchNameKey().shortName()));
      }

      // Propagate any exception that was not caused by the content of the code owner config.
      throw codeOwnersInternalServerErrorException;
    }

    // no issue found
    return Optional.empty();
  }

  /** Whether the importing code owner config is the same as the imported code owner config. */
  private boolean isSelfImport(
      CodeOwnerConfig.Key keyOfImportingCodeOwnerConfig,
      CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig) {
    return keyOfImportingCodeOwnerConfig.project().equals(keyOfImportedCodeOwnerConfig.project())
        && keyOfImportingCodeOwnerConfig.ref().equals(keyOfImportedCodeOwnerConfig.ref())
        && codeOwnersPluginConfiguration
            .getProjectConfig(keyOfImportingCodeOwnerConfig.project())
            .getBackend(keyOfImportingCodeOwnerConfig.branchNameKey().branch())
            .getFilePath(keyOfImportingCodeOwnerConfig)
            .equals(
                codeOwnersPluginConfiguration
                    .getProjectConfig(keyOfImportedCodeOwnerConfig.project())
                    .getBackend(keyOfImportedCodeOwnerConfig.branchNameKey().branch())
                    .getFilePath(keyOfImportedCodeOwnerConfig));
  }

  private boolean isProjectReadable(CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig) {
    try {
      return permissionBackend
          .currentUser()
          .project(keyOfImportedCodeOwnerConfig.project())
          .test(ProjectPermission.ACCESS);
    } catch (PermissionBackendException e) {
      throw new CodeOwnersInternalServerErrorException(
          "failed to check read permission for project of imported code owner config", e);
    }
  }

  private boolean isBranchReadable(CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig) {
    try {
      return permissionBackend
          .currentUser()
          .project(keyOfImportedCodeOwnerConfig.project())
          .ref(keyOfImportedCodeOwnerConfig.ref())
          .test(RefPermission.READ);
    } catch (PermissionBackendException e) {
      throw new CodeOwnersInternalServerErrorException(
          "failed to check read permission for branch of imported code owner config", e);
    }
  }

  private Optional<ObjectId> getRevision(
      CodeOwnerConfig.Key keyOfImportingCodeOwnerConfig,
      ObjectId codeOwnerConfigRevision,
      CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig) {
    if (keyOfImportingCodeOwnerConfig
        .branchNameKey()
        .equals(keyOfImportedCodeOwnerConfig.branchNameKey())) {
      // load the imported code owner config from the same revision from which the importing code
      // owner config was loaded
      return Optional.of(codeOwnerConfigRevision);
    }

    try (Repository repo = repoManager.openRepository(keyOfImportedCodeOwnerConfig.project())) {
      return Optional.ofNullable(repo.exactRef(keyOfImportedCodeOwnerConfig.ref()))
          .map(Ref::getObjectId);
    } catch (IOException e) {
      throw new CodeOwnersInternalServerErrorException(
          "failed to read revision of import code owner config", e);
    }
  }

  private Optional<CommitValidationMessage> nonResolvableImport(
      RevCommit codeOwnerConfigRevision,
      BranchNameKey branchNameKey,
      CodeOwnerConfigImportType importType,
      CodeOwnerConfigReference codeOwnerConfigReference,
      Path codeOwnerConfigFilePath,
      String message) {
    ValidationMessage.Type validationMessageType;
    if (codeOwnerConfigRevision.getParentCount() > 1
        && !codeOwnerConfigReference.branch().isPresent()
        && codeOwnerConfigReference.project().isPresent()
        && !codeOwnerConfigReference.project().get().equals(branchNameKey.project())) {
      // For merge commits, imports from other projects, that implicitly assume the same branch as
      // the importing code owner config, should not be rejected if they cannot be resolved. Hence
      // issues with them are always reported as warnings (rather than errors which would cause a
      // rejection).
      //
      // We do not reject such non-resolvable imports because that can require landing merge
      // commits in a certain order or even make the landing of merge commits impossible.
      //
      // Example 1:
      // 1. project A adds foo/OWNERS
      // 2. project B imports A:foo/OWNERS
      // => If these changes should be merged into another branch (e.g. a release branch) the
      // validation of the code owner config files only succeeds if the merges are done in the
      // correct order (1. do merge for project A, 2. do merge for project B). If the merges are
      // done in the opposite order (1. do merge for project B, 2. do merge for project A) the code
      // owner config file validation for the merge in project B would fail since A:foo/OWNERS
      // doesn't exist in the target branch yet.
      //
      // Example 2:
      // 1. project A adds foo/OWNERS
      // 2. project B imports A:foo/OWNERS
      // 3. project B adds bar/OWNERS
      // 4. project A imports B:bar/OWNERS
      // => If the merge for project A is done first the code owner config file validation would
      // fail because B:bar/OWNERS doesn't exist yet. If the merge for project B is done first the
      // code owner config file validation would fail because A:foo/OWNERS doesn't exist yet.
      validationMessageType = ValidationMessage.Type.WARNING;
    } else {
      validationMessageType =
          codeOwnersPluginConfiguration
                  .getProjectConfig(branchNameKey.project())
                  .rejectNonResolvableImports(branchNameKey.branch())
              ? ValidationMessage.Type.ERROR
              : ValidationMessage.Type.WARNING;
    }

    return nonResolvableImport(importType, codeOwnerConfigFilePath, message, validationMessageType);
  }

  private Optional<CommitValidationMessage> nonResolvableImport(
      CodeOwnerConfigImportType importType,
      Path codeOwnerConfigFilePath,
      String message,
      ValidationMessage.Type validationMessageType) {
    return Optional.of(
        new CommitValidationMessage(
            String.format(
                "invalid %s import in '%s': %s",
                importType.getType(), codeOwnerConfigFilePath, message),
            validationMessageType));
  }

  private Optional<CommitValidationMessage> nonResolvableCodeOwner(
      BranchNameKey branchNameKey, String message) {
    return Optional.of(
        new CommitValidationMessage(
            message,
            codeOwnersPluginConfiguration
                    .getProjectConfig(branchNameKey.project())
                    .rejectNonResolvableCodeOwners(branchNameKey.branch())
                ? ValidationMessage.Type.ERROR
                : ValidationMessage.Type.WARNING));
  }

  /** The result of validating code owner config files. */
  @AutoValue
  public abstract static class ValidationResult {
    private static final String NO_ISSUES_MSG =
        "code owner config files validated, no issues found";
    private static final String INVALID_MSG = "invalid code owner config files";

    abstract String pluginName();

    abstract String summaryMessage();

    abstract ImmutableList<CommitValidationMessage> validationMessages();

    static ValidationResult create(
        String pluginName, String summaryMessage, CommitValidationMessage commitValidationMessage) {
      return new AutoValue_CodeOwnerConfigValidator_ValidationResult(
          pluginName, summaryMessage, ImmutableList.of(commitValidationMessage));
    }

    static ValidationResult create(
        String pluginName, Stream<CommitValidationMessage> validationMessagesStream) {
      ImmutableList<CommitValidationMessage> validationMessages =
          validationMessagesStream.collect(toImmutableList());
      return new AutoValue_CodeOwnerConfigValidator_ValidationResult(
          pluginName,
          validationMessages.isEmpty() ? NO_ISSUES_MSG : INVALID_MSG,
          validationMessages);
    }

    /**
     * Processes the validation messages for a validation that is done when a commit is received
     * (e.g. on push).
     *
     * <p>Throws a {@link CommitValidationException} if there are errors to make the upload fail.
     *
     * <p>If there are no errors the validation messages are returned so that they can be sent to
     * the client without causing the upload to fail.
     */
    List<CommitValidationMessage> processForOnCommitReceived(boolean dryRun)
        throws CommitValidationException {
      if (!dryRun && hasError()) {
        throw new CommitValidationException(
            withPluginName(summaryMessage()), withPluginName(validationMessages()));
      }

      return validationMessagesWithIncludedSummaryMessage();
    }

    /**
     * Processes the validation messages for a validation that is done on pre-merge (aka on submit).
     *
     * <p>Throws a {@link MergeValidationException} if there are errors to make the submit fail.
     *
     * <p>If there are no errors the validation messages are logged on fine level so that they show
     * up in a trace. Returning the message to the user without failing the submit is not possible.
     */
    void processForOnPreMerge(boolean dryRun) throws MergeValidationException {
      if (!dryRun && hasError()) {
        throw new MergeValidationException(getMessage(validationMessages()));
      }

      if (!validationMessages().isEmpty()) {
        logger.atFine().log(
            "submitting changes to code owner config files with the following messages: %s",
            validationMessagesWithIncludedSummaryMessage());
      } else {
        logger.atFine().log("submitting changes to code owner config files, no issues found");
      }
    }

    /** Checks whether any of the validation messages is an error. */
    public boolean hasError() {
      return validationMessages().stream()
          .anyMatch(
              validationMessage ->
                  ValidationMessage.Type.FATAL.equals(validationMessage.getType())
                      || ValidationMessage.Type.ERROR.equals(validationMessage.getType()));
    }

    private ImmutableList<CommitValidationMessage> validationMessagesWithIncludedSummaryMessage() {
      return ImmutableList.<CommitValidationMessage>builder()
          .add(
              new CommitValidationMessage(
                  withPluginName(summaryMessage()), getValidationMessageTypeForSummaryMessage()))
          .addAll(withPluginName(validationMessages()))
          .build();
    }

    /**
     * Gets the validation message type that should be used for the summary message.
     *
     * <p>The following validation message type will be returned:
     *
     * <ul>
     *   <li>FATAL: if any of the validation message has type fatal
     *   <li>ERROR: if any of the validation message has type error
     *   <li>WARNING: if any of the validation message has type warning and none has type error
     *   <li>HINT: otherwise
     * </ul>
     */
    private ValidationMessage.Type getValidationMessageTypeForSummaryMessage() {
      ValidationMessage.Type validationMessageType = ValidationMessage.Type.HINT;

      if (!validationMessages().isEmpty()) {
        for (CommitValidationMessage validationMessage : validationMessages()) {
          if (ValidationMessage.Type.FATAL.equals(validationMessage.getType())) {
            validationMessageType = ValidationMessage.Type.FATAL;
            break;
          }
          if (ValidationMessage.Type.ERROR.equals(validationMessage.getType())) {
            validationMessageType = ValidationMessage.Type.ERROR;
            break;
          }
          if (ValidationMessage.Type.WARNING.equals(validationMessage.getType())) {
            validationMessageType = ValidationMessage.Type.WARNING;
          }
        }
      }

      return validationMessageType;
    }

    /**
     * Composes a single message out of the given validation messages.
     *
     * <p>Expects that at least 1 validation message is provided.
     *
     * @param validationMessages the validation messages
     * @return the composed message
     */
    private String getMessage(List<CommitValidationMessage> validationMessages) {
      checkState(!validationMessages.isEmpty(), "expected at least 1 validation message");
      StringBuilder msgBuilder = new StringBuilder(withPluginName(summaryMessage())).append(":");
      for (CommitValidationMessage msg : validationMessages) {
        msgBuilder
            .append("\n  ")
            .append(msg.getType().name())
            .append(": ")
            .append(msg.getMessage());
      }
      return msgBuilder.toString();
    }

    private String withPluginName(String message) {
      return "[" + pluginName() + "] " + message;
    }

    private ImmutableList<CommitValidationMessage> withPluginName(
        ImmutableList<CommitValidationMessage> validationMessages) {
      return validationMessages.stream()
          .map(msg -> new CommitValidationMessage(withPluginName(msg.getMessage()), msg.getType()))
          .collect(toImmutableList());
    }
  }
}
