private Optional validateCodeOwnerConfigReference()

in java/com/google/gerrit/plugins/codeowners/validation/CodeOwnerConfigValidator.java [913:1038]


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