From dd8952be8547a5f2488dd644ee65a50317a47140 Mon Sep 17 00:00:00 2001 From: Michael Raitza Date: Tue, 16 Feb 2021 20:32:15 +0100 Subject: [PATCH] Add nixredo-whichdo; Put do file discovery into nix --- builder.nix | 58 +++++++++++++++++++++++++++++-------------------- default.nix | 5 ++++- lib.nix | 54 +++++++++++++++++++++++++++++++++++++++++++++ nixredo | 37 +++++++++++++------------------ nixredo-whichdo | 3 +++ 5 files changed, 110 insertions(+), 47 deletions(-) create mode 100644 lib.nix create mode 100644 nixredo-whichdo diff --git a/builder.nix b/builder.nix index 5faf22d..1a2dd90 100644 --- a/builder.nix +++ b/builder.nix @@ -1,32 +1,42 @@ -builderArgs: +buildArgs@{ lib ? import ./lib.nix {}, nixpkgs ? , pkgs ? import nixpkgs {} }: let + inherit (lib) searchPath whichdo d1 d2; - myself = { nixpkgs ? , pkgs ? import nixpkgs {}, rargs, cwd }: - builder: + resolve = path: let + builder = (whichdo path); + in if builder == "" then throw "No rule to build ${path}" + else runBuilder (d1 path builder) (d2 path builder) builder; + + runBuilder = d1: d2: builder: + with pkgs.lib; with builtins; let - resolveLocal = arg: let - fullPath = cwd + "/" + arg + ".nix"; - recurse = myself { rargs = [ (toString arg) (toString arg) ]; inherit cwd; }; - in recurse fullPath; - funcPkgs = { __functor = self: arg: resolveLocal arg; } // pkgs; + # Funktionalise pkgs; our main entry point to resolve default*nix build scripts. + funcPkgs = { __functor = self: arg: resolve arg; } // pkgs; - _builder = if (tryEval (import builder)).success - then import builder - else '' - #!/bin/sh - ${builder} $1 $2 $out >$out - ''; + _builder = if (tryEval (let + # Needs to be done as nix chokes on empty files rn. + content = readFile builder; + in assert content != "" && (! (hasPrefix "#!" content)); import builder)).success + then import builder + else '' + #!/bin/sh + ${/. + builder} $d1 $d2 $out >$out + ''; __builder = if isFunction _builder then _builder funcPkgs else _builder; + args = { stdenv = pkgs.stdenvNoCC; } // (if isString __builder - then { builder = __builder; } - else __builder); - in (args.deriver or args.stdenv.mkDerivation) ({ - name = pkgs.lib.strings.sanitizeDerivationName (builtins.elemAt rargs 0); - buildCommand = args.builder; - passAsFile = [ "buildCommand" ]; - preferLocalBuild = true; - allowSubstitutes = false; - } // (removeAttrs args [ "builder" "system" "deriver" "stdenv" ])); # myself -in myself builderArgs + then { builder = __builder; } + else __builder); + + drv = (args.deriver or args.stdenv.mkDerivation) ({ + name = pkgs.lib.strings.sanitizeDerivationName d1; + buildCommand = args.builder; + passAsFile = [ "buildCommand" ]; + preferLocalBuild = true; + allowSubstitutes = false; + inherit d1 d2; + } // (removeAttrs args [ "builder" "system" "deriver" "stdenv" ])); + in drv; # myself +in resolve diff --git a/default.nix b/default.nix index 7dd53fe..f2b9387 100644 --- a/default.nix +++ b/default.nix @@ -5,10 +5,13 @@ stdenv.mkDerivation { phases = [ "installPhase" "fixupPhase" ]; jq = "${jq}/bin/jq"; buildernix = ./builder.nix; + libnix = ./lib.nix; + + files = [ ./nixredo ./nixredo-deps ./nixredo-whichdo ]; installPhase = '' mkdir -p $out/bin - for f in ${./nixredo} ${./nixredo-deps}; do + for f in $files; do _f=$out/bin/nixredo''${f##*-nixredo} cp $f $_f substituteAllInPlace $_f diff --git a/lib.nix b/lib.nix new file mode 100644 index 0000000..35532d8 --- /dev/null +++ b/lib.nix @@ -0,0 +1,54 @@ +{ lib ? import }: +let + inherit (builtins) length genList pathExists; + inherit (lib) take splitString concatStringsSep last foldl foldr head + tail singleton removePrefix hasSuffix removeSuffix flatten crossLists reverseList; + butlast = list: take (length list - 1) list; + dirname = path: let _p = (butlast (splitString "/" path)); in if _p != [] then concatStringsSep "/" _p else "./"; + basename = path: (last (splitString "/" path)); + + doFileSuffix = "do"; + + genPatterns = path: let + fn = basename path; + in (map (x: "default." + x) + (foldr (a: b: let x = (head b); in [ (a + "." + x) ] ++ b) + [ doFileSuffix ] + (tail (splitString "." fn)))); + + searchPath = path: + let + pathlist = (splitString "/" path); + pat = (last pathlist); + doFile = path + "." + doFileSuffix; + patlist = genPatterns pat; + foldedpaths = foldr (a: b: + let + h = if length b == 0 then "" else head b; + in [ (h + a + "/") ] ++ b) [] (tail (reverseList pathlist)); + pths = crossLists (p: pat: p + pat) [ foldedpaths patlist ]; + in [ doFile ] ++ pths; + + cwd = "/home/spacefrogg/tmp"; + path = cwd + "/foo/bar/baz.def.c"; + + whichdo = path: let + pathlist = searchPath path; + in foldl (res: p: if res == "" then if pathExists p then p else res else res) "" pathlist; + + d1 = path: pat: let + dir = (dirname pat) + "/"; + in removePrefix dir path; + + d2 = path: pat: let + dir = (dirname pat) + "/"; + _path = removePrefix dir path; + _pat = removeSuffix ".${doFileSuffix}" (removePrefix "${dir}default" pat); + _out = removeSuffix _pat _path; + in if _out == "" then _path else _out; + + self = { + inherit dirname basename searchPath cwd path doFileSuffix whichdo d1 d2; + }; + +in self diff --git a/nixredo b/nixredo index 6581723..2e5285b 100644 --- a/nixredo +++ b/nixredo @@ -2,25 +2,18 @@ exec >&2 [ "${NIXREDO_ROOT-x}" != x ] || { printf "Set NIXREDO_ROOT. Set empty to use global nix store\n"; exit 127; } if [ $# -eq 0 ]; then set -- all; fi -if [ -e "$1.nix" ]; then - set -e - set -- "$1" "$1" "$1.redo.tmp" - f=$(realpath "$1.nix") - out=$(nix -vL --show-trace build ${NIXREDO_ROOT:+--store "$NIXREDO_ROOT"} \ - --option auto-optimise-store true --option substituters daemon \ - --impure --json --no-link \ - --expr "import @buildernix@ { cwd = \"$PWD/\"; rargs = [ \"$1\" \"$1\" ];} \"$f\"" | - @jq@ -r '.[0].outputs.out') - [ -n "$out" ] || exit 127 - rm -rf "$3" - ln -s "${NIXREDO_ROOT+$NIXREDO_ROOT}$out" "$3" - # ln "${NIXREDO_ROOT+$NIXREDO_ROOT/}$out" "$3" - # chmod +w "$3" - # touch "$3" - mv "$3" "$1" -elif [ -e "$1" ]; then - : -else - printf "Error: No rule to build %s\n" "$1" - exit 127 -fi +set -e +set -- "$1" "$1" "$1.redo.tmp" +f=$(realpath -s "$1") +out=$(nix -vL --show-trace build ${NIXREDO_ROOT:+--store "$NIXREDO_ROOT"} \ + --option auto-optimise-store true --option substituters daemon \ + --impure --json --no-link \ + --expr " import @buildernix@ { lib = import @libnix@ {}; } \"$f\"" | + @jq@ -r '.[0].outputs.out') +[ -n "$out" ] || exit 127 +rm -rf "$3" +ln -s "${NIXREDO_ROOT+$NIXREDO_ROOT}$out" "$3" +# ln "${NIXREDO_ROOT+$NIXREDO_ROOT/}$out" "$3" +# chmod +w "$3" +# touch "$3" +mv "$3" "$1" diff --git a/nixredo-whichdo b/nixredo-whichdo new file mode 100644 index 0000000..a702d56 --- /dev/null +++ b/nixredo-whichdo @@ -0,0 +1,3 @@ +#!/bin/sh +f=$(realpath -s "$1") +nix eval --impure --expr "with import @libnix@ {}; /. + (whichdo \"$f\")"