gitignore.nix

repository·master·Indexed 43 days ago

https://github.com/hercules-ci/gitignore.nix

A Nix library that emulates gitignore behavior to allow Nix projects to include local sources while respecting .gitignore rules. It provides functions such as gitignoreSource for filtering local paths and gitignoreFilter for creating custom path predicates compatible with cleanSourceWith.

Tokens
1.8K
Snippets
6
Records
8
Agent score
5%

What's inside gitignore.nix

  1. Memoize gitignore filters for performance

    master

    When implementing custom filters (for example, when using cleanSourceWith), do not call gitignoreFilterWith inside the inner path-checking function. Instead, use a let binding to initialize the filter with the basePath once. This ensures that information about the git directory structure is memoized and reused across all path evaluations.

    let
      # CORRECT: Initialize the filter once in a let binding
      srcIgnored = gitignoreFilterWith { basePath = src; extraRules = "..."; };
    in
      # The inner function uses the pre-initialized 'srcIgnored'
      path: type: srcIgnored path type
  2. Install gitignore.nix with Flakes

    master

    You can use gitignore.nix within a Flake to filter sources outside of the flake (e.g., when loading expressions via builtins.getFlake). Add gitignore.nix as an input and use gitignore.lib.gitignoreSource to create a filtered source path.

    Note: When using Flakes, it is recommended to use inputs.nixpkgs.follows = "nixpkgs" to ensure the same nixpkgs instance is used.

    # // flake.nix
    {
      inputs.gitignore = {
        url = "github:hercules-ci/gitignore.nix";
        # Use the same nixpkgs
        inputs.nixpkgs.follows = "nixpkgs";
      };
      outputs = { self, /* other, inputs, */ gitignore }:
      let
        inherit (gitignore.lib) gitignoreSource;
      in {
        packages.x86_64.hello = mkDerivation {
          name = "hello";
          src = gitignoreSource ./vendored/hello;
        };
      };
    }
  3. Install gitignore.nix using the Plain Nix way

    master

    If you are not using Niv or Flakes, you can import the library directly using pkgs.fetchFromGitHub or via builtins.fetchTarball.

    Using fetchFromGitHub

    Use this method to fetch the repository and import the library, passing your existing pkgs.lib to it.

    Using builtins.fetchTarball (Evaluation-time fetching)

    This method uses only nixpkgs/lib and performs fetching during evaluation. This is useful if you want to avoid Import From Derivation (IFD) issues or if you are working in a restricted environment.

    Note: You must replace the placeholder rev and sha256 with the actual values from the latest commit.

    # Method 1: fetchFromGitHub
    let
      gitignoreSrc = pkgs.fetchFromGitHub {
        owner = "hercules-ci";
        repo = "gitignore.nix";
        rev = "<latest-commit-sha>";
        sha256 = "<sha256>";
      };
      inherit (import gitignoreSrc { inherit (pkgs) lib; }) gitignoreSource;
    in
      <your nix expression>
    
    # Method 2: builtins.fetchTarball
    import (builtins.fetchTarball "https://github.com/hercules-ci/gitignore.nix/archive/<commit-sha>.tar.gz") {
      lib = import (builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/<commit-sha>.tar.gz" + "/lib");
    }
  4. Security considerations for gitignore.nix

    master

    Unmatched Files

    Files that are not matched by gitignore rules will be included in the Nix store. Since the Nix store is readable by any process on the system, ensure that sensitive files are correctly covered by your .gitignore files.

    git-crypt

    gitignore.nix does not currently understand git-crypt metadata. Do not call gitignoreSource on directories containing git-crypt secrets (or their parent directories), as the secrets may be inadvertently included in the Nix store. This warning applies to all related Nix functions like path, filterSource, and cleanSource.

  5. Use gitignoreFilter for custom path filtering

    master

    The gitignoreFilter function provides a way to create a predicate function that identifies files to be ignored based on gitignore rules.

    Signature: gitignoreFilter :: path -> (path -> type -> bool)

    Parameters:

    • path: The root or a subdirectory of a local git repository.
    • f: The resulting function. When applied to a path, it returns false for files that should be ignored according to gitignore rules (only for paths at or below the initial path).

    Note: Partial application of gitignoreFilter memoizes the git metadata for performance.

    You can compose this filter with Nixpkgs' cleanSourceWith using logical AND operations.

  6. Use gitignoreSource to filter local paths

    master

    The gitignoreSource function allows you to provide a local path as a source while automatically excluding files matched by .gitignore rules.

    Signature: gitignoreSource :: path -> path

    It returns a result compatible with cleanSourceWith, which can be used as a path or composed with other filters.

    mkDerivation {
      name = "hello";
      src = gitignoreSource ./vendored/hello;
    }
  7. Use the `gitignoreFilter` function directly

    master

    The gitignoreFilter function (or gitignoreFilterWith) allows you to use gitignore-style filtering logic in Nix.

    Performance Warning: This function is curried to allow for memoization. To avoid significant performance penalties, you should call the function once with the root path of your source to create a memoized function, and then reuse that resulting function for all subsequent path checks.

    Constraint: The resulting function must only be invoked for paths that are at or below the root path provided in the first argument.

    let
      # 1. Import the library
      gitignore = (import (import ./nix/sources.nix) { inherit lib; }).gitignore;
      
      # 2. Create a memoized filter by applying the root path (src)
      # Use gitignoreFilterWith to provide extra rules
      srcIgnored = gitignoreFilterWith { 
        basePath = src; 
        extraRules = "*.xml\n!i-need-this.xml"; 
      };
    in
      # 3. Use the memoized function for path checks
      srcIgnored path type