Repository: j178/prefligit (language: python)

Issue:
pre-commit validate-config



Discussion / hints:

Fix patch:
diff --git a/src/cli/mod.rs b/src/cli/mod.rs
index 467ef5b..8e23348 100644
--- a/src/cli/mod.rs
+++ b/src/cli/mod.rs
@@ -9,10 +9,12 @@ use crate::config::Stage;
 mod clean;
 mod install;
 mod run;
+mod validate;
 
 pub(crate) use clean::clean;
 pub(crate) use install::install;
 pub(crate) use run::run;
+pub(crate) use validate::validate_configs;
 
 #[derive(Copy, Clone)]
 pub(crate) enum ExitStatus {
@@ -150,7 +152,7 @@ pub(crate) enum Command {
     /// Uninstall the pre-commit script.
     Uninstall,
     /// Validate `.pre-commit-config.yaml` files.
-    ValidateConfig,
+    ValidateConfig(ValidateConfigArgs),
     /// Validate `.pre-commit-hooks.yaml` files.
     ValidateManifest,
     /// Produce a sample `.pre-commit-config.yaml` file.
@@ -267,6 +269,13 @@ pub(crate) struct RunArgs {
     pub(crate) extra: RunExtraArgs,
 }
 
+#[derive(Debug, Args)]
+pub(crate) struct ValidateConfigArgs {
+    /// The path to the configuration file.
+    #[arg(value_name = "CONFIG")]
+    pub(crate) configs: Vec<PathBuf>,
+}
+
 #[derive(Debug, Args)]
 pub(crate) struct AutoUpdateArgs {
     #[arg(long, default_value_t = true)]
diff --git a/src/cli/validate.rs b/src/cli/validate.rs
new file mode 100644
index 0000000..81091bc
--- /dev/null
+++ b/src/cli/validate.rs
@@ -0,0 +1,25 @@
+use std::error::Error;
+use std::iter;
+use std::path::PathBuf;
+
+use anstream::eprintln;
+use owo_colors::OwoColorize;
+
+use crate::cli::ExitStatus;
+use crate::config::read_config;
+
+pub(crate) fn validate_configs(configs: Vec<PathBuf>) -> ExitStatus {
+    let mut status = ExitStatus::Success;
+
+    for config in configs {
+        if let Err(err) = read_config(&config) {
+            eprintln!("{}: {}", "error".red().bold(), err);
+            for source in iter::successors(err.source(), |&err| err.source()) {
+                eprintln!("  {}: {}", "caused by".red().bold(), source);
+            }
+            status = ExitStatus::Failure;
+        }
+    }
+
+    status
+}
diff --git a/src/main.rs b/src/main.rs
index e96f99d..635d689 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -187,6 +187,11 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
             .await
         }
         Command::Clean => cli::clean(printer),
+        Command::ValidateConfig(args) => {
+            show_settings!(args);
+
+            Ok(cli::validate_configs(args.configs))
+        }
         Command::GenerateShellCompletion(args) => {
             show_settings!(args);
 


Test patch:
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index 5b17f24..e55e8c6 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -123,6 +123,12 @@ impl TestContext {
         command
     }
 
+    pub fn validate_config(&self) -> Command {
+        let mut command = self.command();
+        command.arg("validate-config");
+        command
+    }
+
     /// Standard snapshot filters _plus_ those for this test context.
     pub fn filters(&self) -> Vec<(&str, &str)> {
         // Put test context snapshots before the default filters
diff --git a/tests/validate.rs b/tests/validate.rs
new file mode 100644
index 0000000..46f102c
--- /dev/null
+++ b/tests/validate.rs
@@ -0,0 +1,61 @@
+use assert_fs::fixture::{FileWriteStr, PathChild};
+
+use crate::common::{cmd_snapshot, TestContext};
+
+mod common;
+
+#[test]
+fn validate_config() -> anyhow::Result<()> {
+    let context = TestContext::new();
+
+    // No files to validate.
+    cmd_snapshot!(context.filters(), context.validate_config(), @r#"
+    success: true
+    exit_code: 0
+    ----- stdout -----
+
+    ----- stderr -----
+    "#);
+
+    context
+        .workdir()
+        .child(".pre-commit-config.yaml")
+        .write_str(indoc::indoc! {r"
+            repos:
+              - repo: https://github.com/pre-commit/pre-commit-hooks
+                rev: v5.0.0
+                hooks:
+                  - id: trailing-whitespace
+                  - id: end-of-file-fixer
+                  - id: check-json
+        "})?;
+    // Validate one file.
+    cmd_snapshot!(context.filters(), context.validate_config().arg(".pre-commit-config.yaml"), @r#"
+    success: true
+    exit_code: 0
+    ----- stdout -----
+
+    ----- stderr -----
+    "#);
+
+    context
+        .workdir()
+        .child("config-1.yaml")
+        .write_str(indoc::indoc! {r"
+            repos:
+              - repo: https://github.com/pre-commit/pre-commit-hooks
+        "})?;
+
+    // Validate multiple files.
+    cmd_snapshot!(context.filters(), context.validate_config().arg(".pre-commit-config.yaml").arg("config-1.yaml"), @r#"
+    success: false
+    exit_code: 1
+    ----- stdout -----
+
+    ----- stderr -----
+    error: Failed to parse `config-1.yaml`
+      caused by: repos: Invalid remote repo: missing field `rev` at line 2 column 3
+    "#);
+
+    Ok(())
+}