Repository: j178/prefligit (language: python)

Issue:
pre-commit validate-manifest



Discussion / hints:

Fix patch:
diff --git a/src/cli/mod.rs b/src/cli/mod.rs
index 8e23348..597613b 100644
--- a/src/cli/mod.rs
+++ b/src/cli/mod.rs
@@ -14,7 +14,7 @@ mod validate;
 pub(crate) use clean::clean;
 pub(crate) use install::install;
 pub(crate) use run::run;
-pub(crate) use validate::validate_configs;
+pub(crate) use validate::{validate_configs, validate_manifest};
 
 #[derive(Copy, Clone)]
 pub(crate) enum ExitStatus {
@@ -154,7 +154,7 @@ pub(crate) enum Command {
     /// Validate `.pre-commit-config.yaml` files.
     ValidateConfig(ValidateConfigArgs),
     /// Validate `.pre-commit-hooks.yaml` files.
-    ValidateManifest,
+    ValidateManifest(ValidateManifestArgs),
     /// Produce a sample `.pre-commit-config.yaml` file.
     SampleConfig,
     /// Auto-update pre-commit config to the latest repos' versions.
@@ -276,6 +276,13 @@ pub(crate) struct ValidateConfigArgs {
     pub(crate) configs: Vec<PathBuf>,
 }
 
+#[derive(Debug, Args)]
+pub(crate) struct ValidateManifestArgs {
+    /// The path to the manifest file.
+    #[arg(value_name = "MANIFEST")]
+    pub(crate) manifests: 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
index 81091bc..71fcd80 100644
--- a/src/cli/validate.rs
+++ b/src/cli/validate.rs
@@ -6,7 +6,7 @@ use anstream::eprintln;
 use owo_colors::OwoColorize;
 
 use crate::cli::ExitStatus;
-use crate::config::read_config;
+use crate::config::{read_config, read_manifest};
 
 pub(crate) fn validate_configs(configs: Vec<PathBuf>) -> ExitStatus {
     let mut status = ExitStatus::Success;
@@ -23,3 +23,19 @@ pub(crate) fn validate_configs(configs: Vec<PathBuf>) -> ExitStatus {
 
     status
 }
+
+pub(crate) fn validate_manifest(configs: Vec<PathBuf>) -> ExitStatus {
+    let mut status = ExitStatus::Success;
+
+    for config in configs {
+        if let Err(err) = read_manifest(&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 635d689..4fde276 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -192,6 +192,11 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
 
             Ok(cli::validate_configs(args.configs))
         }
+        Command::ValidateManifest(args) => {
+            show_settings!(args);
+
+            Ok(cli::validate_manifest(args.manifests))
+        }
         Command::GenerateShellCompletion(args) => {
             show_settings!(args);
 


Test patch:
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index e55e8c6..072c55d 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -129,6 +129,12 @@ impl TestContext {
         command
     }
 
+    pub fn validate_manifest(&self) -> Command {
+        let mut command = self.command();
+        command.arg("validate-manifest");
+        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
index 46f102c..f9ccf8b 100644
--- a/tests/validate.rs
+++ b/tests/validate.rs
@@ -59,3 +59,63 @@ fn validate_config() -> anyhow::Result<()> {
 
     Ok(())
 }
+
+#[test]
+fn validate_manifest() -> anyhow::Result<()> {
+    let context = TestContext::new();
+
+    // No files to validate.
+    cmd_snapshot!(context.filters(), context.validate_manifest(), @r#"
+    success: true
+    exit_code: 0
+    ----- stdout -----
+
+    ----- stderr -----
+    "#);
+
+    context
+        .workdir()
+        .child(".pre-commit-hooks.yaml")
+        .write_str(indoc::indoc! {r"
+            -   id: check-added-large-files
+                name: check for added large files
+                description: prevents giant files from being committed.
+                entry: check-added-large-files
+                language: python
+                stages: [pre-commit, pre-push, manual]
+                minimum_pre_commit_version: 3.2.0
+        "})?;
+    // Validate one file.
+    cmd_snapshot!(context.filters(), context.validate_manifest().arg(".pre-commit-hooks.yaml"), @r#"
+    success: true
+    exit_code: 0
+    ----- stdout -----
+
+    ----- stderr -----
+    "#);
+
+    context
+        .workdir()
+        .child("hooks-1.yaml")
+        .write_str(indoc::indoc! {r"
+            -   id: check-added-large-files
+                name: check for added large files
+                description: prevents giant files from being committed.
+                language: python
+                stages: [pre-commit, pre-push, manual]
+                minimum_pre_commit_version: 3.2.0
+        "})?;
+
+    // Validate multiple files.
+    cmd_snapshot!(context.filters(), context.validate_manifest().arg(".pre-commit-hooks.yaml").arg("hooks-1.yaml"), @r#"
+    success: false
+    exit_code: 1
+    ----- stdout -----
+
+    ----- stderr -----
+    error: Failed to parse `hooks-1.yaml`
+      caused by: .[0]: missing field `entry` at line 1 column 5
+    "#);
+
+    Ok(())
+}