diff --git a/find-files.nix b/find-files.nix index e52fc06..085edc7 100644 --- a/find-files.nix +++ b/find-files.nix @@ -242,7 +242,12 @@ rec { for (guard (toLower section == "core" && toLower key == "excludesfile")) (_: - resolveFile (home /.) value + # Paths with context can't be appended to other paths, so we have to + # remove the context here. + # SAFETY: gitignore.nix is not responsible for making sure the + # store paths pointed to in your global git config have been + # realised. + resolveFile (home /.) (builtins.unsafeDiscardStringContext value) ) ) ); @@ -290,7 +295,7 @@ rec { */ # TODO: get something like builtins.pathType or builtins.stat into Nix guardFile = p: if pathExists p then [p] else []; - guardNonEmptyString = s: if s == "" then [s] else []; + guardNonEmptyString = s: if s == "" then [] else [s]; guardNonNull = a: if a != null then a else []; diff --git a/tests/default.nix b/tests/default.nix index 18844be..b2258d8 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -3,6 +3,8 @@ let testdata = import ./testdata.nix { inherit pkgs; }; runner = import ./runner.nix { inherit pkgs; }; + gitignoreNix = (import ../. { inherit lib; }); + inherit (gitignoreNix) gitignoreSource; in { plain = runner.makeTest { name = "plain"; rootDir = testdata.sourceUnfiltered + "/test-tree"; }; @@ -10,10 +12,10 @@ in plain-with-testdata-dir = runner.makeTest { name = "plain"; rootDir = testdata.sourceUnfiltered; }; nested-with-testdata-dir = runner.makeTest { name = "nested"; rootDir = testdata.sourceUnfilteredRecursive; }; - + plain-with-testdata-subdir = runner.makeTest { name = "plain"; rootDir = testdata.sourceUnfiltered; subpath = "test-tree"; }; nested-with-testdata-subdir = runner.makeTest { name = "nested"; rootDir = testdata.sourceUnfilteredRecursive; subpath = "test-tree"; }; - + subdir-1 = runner.makeTest { name = "subdir-1"; rootDir = testdata.sourceUnfiltered + "/test-tree"; subpath = "1-simpl"; }; subdir-1x = runner.makeTest { name = "subdir-1x"; rootDir = testdata.sourceUnfiltered + "/test-tree"; subpath = "1-xxxxx"; }; subdir-2 = runner.makeTest { name = "subdir-2"; rootDir = testdata.sourceUnfiltered + "/test-tree"; subpath = "2-negation"; }; @@ -22,6 +24,87 @@ in subdir-9 = runner.makeTest { name = "subdir-9"; rootDir = testdata.sourceUnfiltered + "/test-tree"; subpath = "9-expected"; }; subdir-10 = runner.makeTest { name = "subdir-10"; rootDir = testdata.sourceUnfiltered + "/test-tree"; subpath = "10-subdir-ignoring-itself"; }; + # https://github.com/hercules-ci/gitignore.nix/pull/71 + regression-config-with-store-path = + pkgs.stdenv.mkDerivation { + name = "config-with-store-path"; + src = testdata.sourceUnfiltered + "/test-tree"; + buildInputs = [ pkgs.nix ]; + NIX_PATH="nixpkgs=${pkgs.path}"; + buildPhase = '' + # Set up an alternate nix store with a different store directory + export TEST_ROOT=$(pwd)/test-root + export NIX_BUILD_HOOK= + export NIX_CONF_DIR=$TEST_ROOT/etc + export NIX_LOCALSTATE_DIR=$TEST_ROOT/var + export NIX_LOG_DIR=$TEST_ROOT/var/log/nix + export NIX_STATE_DIR=$TEST_ROOT/var/nix + export NIX_STORE_DIR=$TEST_ROOT/store + export NIX_STORE=$TEST_ROOT/store + + mkdir -p $NIX_STORE_DIR $NIX_CONF_DIR + + # Write nix.conf - disable sandbox for nested builds + cat > $NIX_CONF_DIR/nix.conf < {}; + excludesfile = derivation { + name = \"excludesfile\"; + system = builtins.currentSystem; + builder = \"/bin/sh\"; + args = [\"-c\" \"echo -n \\\"\\\" > \\\$out\"]; + }; + in + derivation { + name = \"home-config\"; + system = builtins.currentSystem; + builder = \"${pkgs.bash}/bin/bash\"; + PATH = \"${pkgs.coreutils}/bin\"; + inherit excludesfile; + args = [\"-c\" \" + mkdir -p \\\$out/git + printf '[core]\\\\n excludesfile = %s\\\\n' \\\$excludesfile > \\\$out/git/config + \"]; + } + ") + + # Use XDG_CONFIG_HOME pointing directly to this store path (like home-manager does) + export XDG_CONFIG_HOME=$configdir + echo "XDG_CONFIG_HOME is now: $XDG_CONFIG_HOME" + echo "Config file contents:" + cat $XDG_CONFIG_HOME/git/config + + echo "---------------" + echo "Testing gitignoreSource with store path in git config:" + # This calls the real main code (gitignoreSource) which will naturally + # evaluate globalConfiguredExcludesFile when building the pattern tree + # Without the fix: fails with "a string that refers to a store path cannot be appended to a path" + # With the fix: succeeds (unsafeDiscardStringContext strips the context) + if nix-instantiate --eval --expr \ + '((import ${gitignoreSource ../.} {}).gitignoreSource ./.).outPath' + then touch $out + else + echo + echo "Failed to run with a global excludes file from the nix store." + echo "This may be because the store path gets misinterpreted as a string context." + echo "See https://github.com/hercules-ci/gitignore.nix/pull/71" + exit 1 + fi + ''; + preInstall = ""; + installPhase = ":"; + }; + # Make sure the files aren't added to the store before filtering. shortcircuit = runner.makeTest { name = "nested"; @@ -34,8 +117,7 @@ in }; unit-tests = - let gitignoreNix = import ../default.nix { inherit (pkgs) lib; }; - inherit (gitignoreNix) gitignoreFilterWith gitignoreSourceWith; + let inherit (gitignoreNix) gitignoreFilterWith gitignoreSourceWith; example = gitignoreFilterWith { basePath = ./.; extraRules = '' *.foo !*.bar