mirror of
https://github.com/nix-community/nixvim.git
synced 2025-12-13 04:21:10 +01:00
Instead of copying source files to the target, use a symlink. This reduces nix store redundancy and enables using entire directories as sources. To support this, additional validation is done on file targets to prevent unexpected conflicts.
231 lines
5.5 KiB
Nix
231 lines
5.5 KiB
Nix
let
|
||
checkExtraFiles =
|
||
pkgs:
|
||
{
|
||
name,
|
||
extraFilesDir,
|
||
expectedTargets,
|
||
}:
|
||
pkgs.runCommand name
|
||
{
|
||
inherit extraFilesDir expectedTargets;
|
||
__structuredAttrs = true;
|
||
}
|
||
''
|
||
set -euo pipefail
|
||
|
||
for target in "''${!expectedTargets[@]}"; do
|
||
file="$extraFilesDir/$target"
|
||
expected="''${expectedTargets["$target"]}"
|
||
|
||
if [ ! -e "$file" ]; then
|
||
echo "Missing target: $file"
|
||
exit 1
|
||
fi
|
||
|
||
if [ -n "$expected" ] && ! grep -qF "$expected" "$file"; then
|
||
echo "Content mismatch: $file"
|
||
exit 1
|
||
fi
|
||
done
|
||
|
||
touch $out
|
||
'';
|
||
in
|
||
{
|
||
# Example
|
||
query = {
|
||
extraFiles."queries/lua/injections.scm".text = ''
|
||
;; extends
|
||
'';
|
||
};
|
||
|
||
empty = {
|
||
extraFiles = { };
|
||
};
|
||
|
||
happy-path =
|
||
{ config, pkgs, ... }:
|
||
{
|
||
extraFiles = {
|
||
# Basic tests
|
||
"testing/test-case.nix".source = ./extra-files.nix;
|
||
"testing/123.txt".text = ''
|
||
One
|
||
Two
|
||
Three
|
||
'';
|
||
|
||
# Multiple files in the same directory
|
||
"foo/a".text = "A";
|
||
"foo/b".text = "B";
|
||
"foo/c".text = "C";
|
||
|
||
# Nested deep path
|
||
"a/b/c/d/e.txt".text = "deep";
|
||
|
||
# Directory source
|
||
"beta/dir".source = pkgs.emptyDirectory;
|
||
|
||
# Mixed: source file + hello source
|
||
"hello/source".source = pkgs.hello;
|
||
};
|
||
test.runNvim = false;
|
||
test.extraInputs = [
|
||
(checkExtraFiles pkgs {
|
||
name = "check-happy-path";
|
||
extraFilesDir = config.build.extraFiles;
|
||
expectedTargets = {
|
||
"testing/test-case.nix" = null;
|
||
"testing/123.txt" = "One\nTwo\nThree";
|
||
"foo/a" = "A";
|
||
"foo/b" = "B";
|
||
"foo/c" = "C";
|
||
"a/b/c/d/e.txt" = "deep";
|
||
"beta/dir" = null;
|
||
"hello/source" = null;
|
||
};
|
||
})
|
||
];
|
||
};
|
||
|
||
# Special content edge cases
|
||
special-files =
|
||
{ config, pkgs, ... }:
|
||
{
|
||
extraFiles = {
|
||
"empty.txt".text = "";
|
||
"whitespace.txt".text = " \n\t ";
|
||
"файл.txt".text = "unicode";
|
||
"目录/文件.txt".text = "chinese";
|
||
};
|
||
test.runNvim = false;
|
||
test.extraInputs = [
|
||
(checkExtraFiles pkgs {
|
||
name = "check-special-files";
|
||
extraFilesDir = config.build.extraFiles;
|
||
expectedTargets = {
|
||
"empty.txt" = "";
|
||
"whitespace.txt" = " ";
|
||
"файл.txt" = "unicode";
|
||
"目录/文件.txt" = "chinese";
|
||
};
|
||
})
|
||
];
|
||
};
|
||
|
||
identical-duplicates =
|
||
{ config, pkgs, ... }:
|
||
{
|
||
extraFiles.a = {
|
||
target = "hello.txt";
|
||
text = "hello";
|
||
};
|
||
extraFiles.b = {
|
||
target = "hello.txt";
|
||
text = "hello";
|
||
};
|
||
extraFiles.c = {
|
||
target = "empty.txt";
|
||
source = pkgs.emptyFile;
|
||
};
|
||
extraFiles.d = {
|
||
target = "empty.txt";
|
||
source = pkgs.emptyFile;
|
||
};
|
||
extraFiles.e = {
|
||
target = "emptyDir";
|
||
source = pkgs.emptyDirectory;
|
||
};
|
||
extraFiles.f = {
|
||
target = "emptyDir";
|
||
source = pkgs.emptyDirectory;
|
||
};
|
||
test.buildNixvim = false;
|
||
test.extraInputs = [
|
||
(checkExtraFiles pkgs {
|
||
name = "check-identical-duplicates";
|
||
extraFilesDir = config.build.extraFiles;
|
||
expectedTargets = {
|
||
"hello.txt" = "hello";
|
||
"empty.txt" = null;
|
||
"emptyDir" = null;
|
||
};
|
||
})
|
||
];
|
||
};
|
||
|
||
duplicate-mismatch =
|
||
{ config, pkgs, ... }:
|
||
{
|
||
extraFiles.a = {
|
||
target = "conflict.txt";
|
||
text = "abc";
|
||
};
|
||
extraFiles.b = {
|
||
target = "conflict.txt";
|
||
text = "xyz";
|
||
};
|
||
test.buildNixvim = false;
|
||
test.extraInputs = [
|
||
(pkgs.runCommand "expect-duplicate-failure"
|
||
{ failure = pkgs.testers.testBuildFailure config.build.extraFiles; }
|
||
''
|
||
exit_code=$(cat "$failure/testBuildFailure.exit")
|
||
(( exit_code == 1 )) || {
|
||
echo "Expected exit code 1"
|
||
exit 1
|
||
}
|
||
grep -q "target 'conflict.txt' defined multiple times with different sources:" "$failure/testBuildFailure.log"
|
||
drv_count=$(grep -c '/nix/store/.*-nvim-.' "$failure/testBuildFailure.log")
|
||
(( drv_count == 2 )) || {
|
||
echo "Expected 2 store path matches, got $drv_count"
|
||
exit 1
|
||
}
|
||
touch $out
|
||
''
|
||
)
|
||
];
|
||
};
|
||
|
||
prefix-conflicts = {
|
||
extraFiles = {
|
||
# 2-level conflict
|
||
"foo".text = "root";
|
||
"foo/bar.txt".text = "child";
|
||
|
||
# 3-level conflict
|
||
"baz".text = "parent";
|
||
"baz/qux".text = "child";
|
||
"baz/qux/quux.txt".text = "grandchild";
|
||
|
||
# 5-level conflict
|
||
"a".text = "1";
|
||
"a/b".text = "2";
|
||
"a/b/c".text = "3";
|
||
"a/b/c/d".text = "4";
|
||
"a/b/c/d/e.txt".text = "5";
|
||
|
||
# Non-conflicting paths
|
||
"abc".text = "solo";
|
||
"def/ghi.txt".text = "leaf";
|
||
"solo".text = "single";
|
||
"x/y.txt".text = "leaf";
|
||
};
|
||
|
||
test.assertions = expect: [
|
||
(expect "count" 1)
|
||
(expect "anyExact" ''
|
||
Nixvim (extraFiles): Conflicting target prefixes:
|
||
- a ↔ a/b
|
||
- a/b ↔ a/b/c
|
||
- a/b/c ↔ a/b/c/d
|
||
- a/b/c/d ↔ a/b/c/d/e.txt
|
||
- baz ↔ baz/qux
|
||
- baz/qux ↔ baz/qux/quux.txt
|
||
- foo ↔ foo/bar.txt'')
|
||
];
|
||
|
||
test.buildNixvim = false;
|
||
};
|
||
}
|