// 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.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.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.Config;
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;

  @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) {
    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;
  }

  @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);
      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.repoConfig,
                  receiveEvent.revWalk,
                  receiveEvent.commit,
                  receiveEvent.user,
                  codeOwnerConfigValidationPolicy.isForced(),
                  receiveEvent.pushOptions);
        } catch (RuntimeException e) {
          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());
      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,
                  repository.getConfig(),
                  revWalk,
                  commit,
                  patchSetUploader,
                  codeOwnerConfigValidationPolicy.isForced(),
                  /* pushOptions= */ ImmutableListMultimap.of());
        } catch (RuntimeException e) {
          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());
        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 revWalk the rev walk that should be used to load revCommit
   * @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,
      Config repoConfig,
      RevWalk revWalk,
      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(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
              .compute(
                  branchNameKey.project(),
                  repoConfig,
                  revWalk,
                  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,
                              revWalk,
                              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(
          String.format(
              "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 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());
      logger.atSevere().withCause(e).log(errorMessage);
      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 revWalk the rev walk that should be used to load revCommit
   * @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,
      RevWalk revWalk,
      RevCommit revCommit) {
    requireNonNull(user, "user");
    requireNonNull(codeOwnerBackend, "codeOwnerBackend");
    requireNonNull(branchNameKey, "branchNameKey");
    requireNonNull(changedFile, "changedFile");
    requireNonNull(revWalk, "revWalk");
    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, revWalk, 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, revWalk, 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, revWalk, 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, revWalk, 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,
          revWalk,
          user,
          codeOwnerBackend,
          codeOwnerConfig,
          baseCodeOwnerConfig.get());
    }
    return validateCodeOwnerConfig(branchNameKey, revWalk, 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 revWalk rev walk that should be used to load the base code owner config
   * @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,
      RevWalk revWalk,
      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, revWalk, 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 revWalk rev walk that should be used to load 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,
      RevWalk revWalk,
      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, revWalk, 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 revWalk rev walk that should be used to load the code owner configs
   * @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,
      RevWalk revWalk,
      IdentifiedUser user,
      CodeOwnerBackend codeOwnerBackend,
      CodeOwnerConfig codeOwnerConfig,
      CodeOwnerConfig baseCodeOwnerConfig) {
    requireNonNull(codeOwnerConfig, "codeOwnerConfig");
    requireNonNull(baseCodeOwnerConfig, "baseCodeOwnerConfig");

    ImmutableSet<CommitValidationMessage> issuesInBaseVersion =
        validateCodeOwnerConfig(branchNameKey, revWalk, user, codeOwnerBackend, baseCodeOwnerConfig)
            .collect(toImmutableSet());
    return validateCodeOwnerConfig(branchNameKey, revWalk, 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 revWalk rev walk that should be used to load the code owner configs from {@code 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,
      RevWalk revWalk,
      IdentifiedUser user,
      CodeOwnerBackend codeOwnerBackend,
      CodeOwnerConfig codeOwnerConfig) {
    requireNonNull(codeOwnerConfig, "codeOwnerConfig");
    return Streams.concat(
        validateCodeOwnerReferences(
            branchNameKey,
            user,
            codeOwnerBackend.getFilePath(codeOwnerConfig.key()),
            codeOwnerConfig),
        validateImports(
            branchNameKey,
            revWalk,
            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 revWalk rev walk that should be used to load the code owner configs from {@code 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,
      RevWalk revWalk,
      Path codeOwnerConfigFilePath,
      CodeOwnerConfig codeOwnerConfig) {
    try {
      RevCommit codeOwnerConfigRevision = revWalk.parseCommit(codeOwnerConfig.revision());
      return Streams.concat(
              codeOwnerConfig.imports().stream()
                  .map(
                      codeOwnerConfigReference ->
                          validateCodeOwnerConfigReference(
                              branchNameKey,
                              revWalk,
                              codeOwnerConfigFilePath,
                              codeOwnerConfig.key(),
                              codeOwnerConfigRevision,
                              CodeOwnerConfigImportType.GLOBAL,
                              codeOwnerConfigReference)),
              codeOwnerConfig.codeOwnerSets().stream()
                  .flatMap(codeOwnerSet -> codeOwnerSet.imports().stream())
                  .map(
                      codeOwnerConfigReference ->
                          validateCodeOwnerConfigReference(
                              branchNameKey,
                              revWalk,
                              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 revWalk rev walk that should be used to load the code owner configs from {@code 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,
      RevWalk revWalk,
      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, revWalk, 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. */
    private 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());
    }
  }
}
