From f826a04257767e1c1b9912dc45f6c29f9f73b2dc Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Tue, 19 Mar 2024 12:45:11 +0100 Subject: [PATCH] typos: fix unexpected behaviour Enable typos.configPath to be of type path. This way, we can use excludes from .typos.toml when running `pre-commit run typos --all-files`. Otherwise, the execution differs from a normal invocation of typos, which is unexpected and leads to wrong results. To not break anything, and to be compliant with the existing API, I modified configPath to be either a Nix path or a string. The main motivation for this change is a repository on my machine where pre-commit ignores directory foobar (which is excluded by .typos.toml) but passes all 65,000 files of foobar as argument to typos. In these situation, typos goes nuts and often the system freezes. So with this change, I prevent that possibly tens of thousands of files that should not be checked in any case are passed to typos, which results in a smooth experience. [0]: https://github.com/cachix/pre-commit-hooks.nix/pull/387#issuecomment-1893600631 --- modules/hooks.nix | 57 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/modules/hooks.nix b/modules/hooks.nix index 9e64c0f0..f949390d 100644 --- a/modules/hooks.nix +++ b/modules/hooks.nix @@ -1436,7 +1436,7 @@ in configuration = mkOption { type = types.str; - description = lib.mdDoc "Multiline-string configuration passed as config file. If set, config set in `typos.settings.configPath` gets ignored."; + description = lib.mdDoc "Multiline-string configuration passed as config file. It is recommended to use `configPath` instead for a more natural experience of typos."; default = ""; example = '' [files] @@ -1450,11 +1450,14 @@ in ''; }; + # It is recommended to use a Nix path here as this way, the excludes + # from the config file can be taken into account by pre-commit when + # running `$ pre-commit run --all-files`. configPath = mkOption { - type = types.str; - description = lib.mdDoc "Path to a custom config file."; - default = ""; + type = types.nullOr (types.either types.str types.path); + description = lib.mdDoc "[Path](https://nixos.org/manual/nix/stable/language/values#type-path) to a typos config file (recommended) or a string (deprecated)"; + default = null; example = ".typos.toml"; }; @@ -3314,6 +3317,47 @@ lib.escapeShellArgs (lib.concatMap (ext: [ "--ghc-opt" "-X${ext}" ]) hooks.ormol entry = "${hooks.treefmt.package}/bin/treefmt --fail-on-change"; }; typos = + let + # Path to config file. May be in Nix store but can also be a relative + # path to a system-dependent file. + # + # After various upstream discussions [0]), the best solution is to + # provide the config file as Nix path but keep the string passing + # as fall-back. + # + # [0]: https://github.com/cachix/pre-commit-hooks.nix/pull/387#issuecomment-1893600631 + pathToConfigFile = + if hooks.typos.settings.configPath != null + # Important: If passed as typeOf == "path", this is in Nix store + # which we in fact encourage. + then hooks.typos.settings.configPath + else + builtins.toFile "config.toml" + # Concatenate config in config file with section for ignoring words + # generated from list of words to ignore + (hooks.typos.settings.configuration + + lib.strings.optionalString (hooks.typos.settings.ignored-words != [ ]) "\n\[default.extend-words\]" + + lib.strings.concatMapStrings (x: "\n${x} = \"${x}\"") hooks.typos.settings.ignored-words + ) + ; + # If the config file path is passed as string and not as path, we + # can't read it from Nix. + excludesFromConfig = + if builtins.typeOf hooks.typos.settings.configPath == "path" # passed directly or as Path + then + ( + let + toml = builtins.fromTOML (builtins.readFile pathToConfigFile); + in + /* + The "files.extend-exclude" key comes from + https://github.com/crate-ci/typos/blob/master/docs/reference.md + */ + (toml.files or { }).extend-exclude or [ ] + ) + else + [ ]; + in { name = "typos"; description = "Source code spell checker"; @@ -3328,8 +3372,8 @@ lib.escapeShellArgs (lib.concatMap (ext: [ "--ghc-opt" "-X${ext}" ]) hooks.ormol (with hooks.typos.settings; [ [ binary "--binary" ] [ (color != "auto") "--color ${color}" ] - [ (configuration != "") "--config ${configFile}" ] - [ (configPath != "" && configuration == "") "--config ${configPath}" ] + # Config file always exists (we generate one if not). + [ true "--config ${pathToConfigFile}" ] [ diff "--diff" ] [ (exclude != "") "--exclude ${exclude} --force-exclude" ] [ (format != "long") "--format ${format}" ] @@ -3345,6 +3389,7 @@ lib.escapeShellArgs (lib.concatMap (ext: [ "--ghc-opt" "-X${ext}" ]) hooks.ormol in "${hooks.typos.package}/bin/typos ${cmdArgs}"; types = [ "text" ]; + excludes = excludesFromConfig; }; typstfmt = { name = "typstfmt";