diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ada2604..65cd07d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ # DO NOT MODIFY -# This file was generated by project.nix +# This file was generated by nix-pre-commit-hooks { "repos": [ { diff --git a/modules/formatters/nixpkgs-fmt.nix b/modules/formatters/nixpkgs-fmt.nix index 02b6fca..bba4202 100644 --- a/modules/formatters/nixpkgs-fmt.nix +++ b/modules/formatters/nixpkgs-fmt.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, options, pkgs, ... }: let @@ -32,12 +32,11 @@ in }; }; - config = { + config = lib.optionalAttrs (options ? pre-commit.hooks) { pre-commit.hooks.nixpkgs-fmt = { - inherit description; inherit (cfg) enable; - entry = "${cfg.package}/bin/nixpkgs-fmt"; - files = ''\.nix$''; + # TODO: upstream the update, remove this + entry = lib.mkForce "${cfg.package}/bin/nixpkgs-fmt"; }; }; } diff --git a/modules/niv.nix b/modules/niv.nix index 4097329..69ea143 100644 --- a/modules/niv.nix +++ b/modules/niv.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, options, pkgs, ... }: let inherit (lib) mkIf mkOption types; @@ -38,10 +38,13 @@ in }; - config = mkIf cfg.enable { - shell.packages = [ - cfg.package - ]; - pre-commit.hooks.nixpkgs-fmt.excludes = [ "nix/sources.nix$" ]; - }; + config = mkIf cfg.enable ( + { + shell.packages = [ + cfg.package + ]; + } // lib.optionalAttrs (options ? pre-commit.hooks) { + pre-commit.hooks.nixpkgs-fmt.excludes = [ "nix/sources.nix$" ]; + } + ); } diff --git a/modules/pre-commit.nix b/modules/pre-commit.nix index f7c4f7d..e57e0c8 100644 --- a/modules/pre-commit.nix +++ b/modules/pre-commit.nix @@ -3,160 +3,13 @@ let inherit (lib) - attrNames - concatStringsSep - filterAttrs - literalExample - mapAttrsToList mkIf mkOption types ; - inherit (pkgs) runCommand writeText git; - cfg = config.pre-commit; - hookType = types.submodule ( - { config, name, ... }: { - options = { - enable = mkOption { - type = types.bool; - description = '' - Whether to enable this pre-commit hook. - ''; - default = false; - }; - raw = mkOption { - type = types.attrsOf types.unspecified; - description = '' - Raw fields of a pre-commit hook. This is mostly for internal use but - exposed in case you need to work around something. - - Default: taken from the other hook options. - ''; - }; - name = mkOption { - type = types.str; - default = name; - defaultText = literalExample "internal name, same as id"; - description = '' - The name of the hook - shown during hook execution. - ''; - }; - entry = mkOption { - type = types.str; - description = '' - The entry point - the executable to run. entry can also contain arguments that will not be overridden such as entry: autopep8 -i. - ''; - }; - language = mkOption { - type = types.str; - description = '' - The language of the hook - tells pre-commit how to install the hook. - ''; - default = "system"; - }; - files = mkOption { - type = types.str; - description = '' - The pattern of files to run on. - ''; - default = ""; - }; - types = mkOption { - type = types.listOf types.str; - description = '' - List of file types to run on. See Filtering files with types (https://pre-commit.com/#plugins). - ''; - default = [ "file" ]; - }; - description = mkOption { - type = types.str; - description = '' - Description of the hook. used for metadata purposes only. - ''; - default = ""; - }; - excludes = mkOption { - type = types.listOf types.str; - description = '' - Exclude files that were matched by these patterns. - ''; - default = []; - }; - }; - config = { - raw = - { - inherit (config) name entry language files types; - id = name; - exclude = if config.excludes == [] then "^$" else - "(${concatStringsSep "|" config.excludes})"; - }; - }; - } - ); - - enabledHooks = filterAttrs (id: value: value.enable) cfg.hooks; - processedHooks = mapAttrsToList (id: value: value.raw // { inherit id; }) enabledHooks; - - precommitConfig = { - repos = [ - { - repo = ".pre-commit-hooks/"; - rev = "master"; - hooks = mapAttrsToList (id: _value: { inherit id; }) enabledHooks; - } - ]; - }; - - hooksFile = - writeText "pre-commit-hooks.json" (builtins.toJSON processedHooks); - configFile = - writeText "pre-commit-config.json" (builtins.toJSON precommitConfig); - - hooks = - runCommand "pre-commit-hooks-dir" { buildInputs = [ git ]; } '' - HOME=$PWD - mkdir -p $out - ln -s ${hooksFile} $out/.pre-commit-hooks.yaml - cd $out - git config --global user.email "you@example.com" - git config --global user.name "Your Name" - git init - git add . - git commit -m "init" - ''; - - run = - runCommand "pre-commit-run" { buildInputs = [ git ]; } '' - set +e - HOME=$PWD - cp --no-preserve=mode -R ${cfg.rootSrc} src - unlink src/.pre-commit-hooks || true - ln -fs ${hooks} src/.pre-commit-hooks - cd src - rm -rf src/.git - git init - git add . - git config --global user.email "you@example.com" - git config --global user.name "Your Name" - git commit -m "init" - echo "Running: $ pre-commit run --all-files" - ${cfg.package}/bin/pre-commit run --all-files - exitcode=$? - git --no-pager diff --color - touch $out - [ $? -eq 0 ] && exit $exitcode - ''; - - srcStr = toString (config.root.origSrc or config.root); - - # TODO: provide a default pin that the user may override - inherit (import (import ../nix/sources.nix).gitignore { inherit lib; }) - gitignoreSource - ; in { options.pre-commit = { @@ -177,47 +30,11 @@ in description = '' Whether to auto install pre-commit when invoking nix-shell in the project root. - ''; - }; - package = mkOption { - type = types.package; - description = '' - The pre-commit package to use. - ''; - default = pkgs.pre-commit; - defaultText = literalExample '' - pkgs.pre-commit + Unused if not pre-commit.enabled. ''; }; - hooks = mkOption { - type = types.attrsOf hookType; - description = '' - The hook definitions. - ''; - default = {}; - }; - - run = mkOption { - type = types.package; - description = '' - A derivation that tests whether the pre-commit hooks run cleanly on - the entire project. - ''; - readOnly = true; - default = run; - }; - - rootSrc = mkOption { - type = types.package; - description = '' - The source of the project to be checked. - ''; - defaultText = literalExample ''gitignoreSource config.root''; - default = gitignoreSource config.root; - }; - }; config = mkIf cfg.enable { @@ -225,44 +42,7 @@ in shell.packages = [ cfg.package ]; activation.hooks = mkIf cfg.enableAutoInstall [ - '' - export PATH=$PATH:${cfg.package}/bin - if ! type -t git >/dev/null; then - # This happens in pure shells, including lorri - echo 1>&2 "WARNING: nix-pre-commit-hooks: git command not found; skipping installation." - else - ( - # We use srcStr to protect against installing pre-commit hooks - # in the wrong places such as for example ./. when invoking - # nix-shell ../../other-project/shell.nix - cd ${lib.escapeShellArg srcStr} && { - # Avoid filesystem churn. We may be watched! - # This prevents lorri from looping after every interactive shell command. - if readlink .pre-commit-hooks >/dev/null \ - && [[ $(readlink .pre-commit-hooks) == ${hooks} ]]; then - echo 1>&2 "nix-pre-commit-hooks: hooks up to date" - else - echo 1>&2 "nix-pre-commit-hooks: updating" ${lib.escapeShellArg srcStr} - - [ -L .pre-commit-hooks ] && unlink .pre-commit-hooks - ln -s ${hooks} .pre-commit-hooks - - # This can't be a symlink because its path is not constant, - # thus can not be committed and is invisible to pre-commit. - unlink .pre-commit-config.yaml - { echo '# DO NOT MODIFY'; - echo '# This file was generated by project.nix'; - ${pkgs.jq}/bin/jq . <${configFile} - } >.pre-commit-config.yaml - - pre-commit install - # this is needed as the hook repo configuration is cached - pre-commit clean - fi - } - ) - fi - '' + config.pre-commit.installationScript ]; }; diff --git a/nix/project.nix b/nix/project.nix index 522034a..36d468b 100644 --- a/nix/project.nix +++ b/nix/project.nix @@ -1,4 +1,10 @@ { + # imports = scan "nix/project-module.nix" ./sources.nix; + + imports = [ + ((import ./sources.nix).nix-pre-commit-hooks + "/nix/project-module.nix") + ]; + root = ../.; pinning.niv.enable = true; pre-commit.enable = true; diff --git a/nix/sources.json b/nix/sources.json index dda854f..947cfe2 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -23,6 +23,18 @@ "url": "https://github.com/nmattia/niv/archive/efce82e4ba77a84835f9febefe3b2fe52a8c7ede.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, + "nix-pre-commit-hooks": { + "branch": "modular", + "description": "Seamless integration of https://pre-commit.com git hooks with Nix.", + "homepage": "", + "owner": "hercules-ci", + "repo": "nix-pre-commit-hooks", + "rev": "a1f5c165f3dba9ea2efab685ee6f6d1f06913a32", + "sha256": "11kypfzpkk6x1dxi5qdk28vgfyap05ccr7ahhnb8s7k22wx8dkxi", + "type": "tarball", + "url": "https://github.com/hercules-ci/nix-pre-commit-hooks/archive/a1f5c165f3dba9ea2efab685ee6f6d1f06913a32.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, "nixpkgs": { "branch": "nixos-19.09", "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to",