From ddfe7782f047f7180dd1f1d4dc949570162269c6 Mon Sep 17 00:00:00 2001 From: Nicolas Mattia Date: Thu, 24 May 2018 16:46:05 +0200 Subject: [PATCH] Add support for extra-dirs --- script/test | 8 ++ snack/default.nix | 115 +++++++++++++++----- tests/template-haskell-2/code/Main.hs | 9 ++ tests/template-haskell-2/code/snack.nix | 11 ++ tests/template-haskell-2/code/src/Foo.hs | 5 + tests/template-haskell-2/code/src/FooBar.hs | 9 ++ tests/template-haskell-2/foo.txt | 1 + tests/template-haskell-3/Main.hs | 9 ++ tests/template-haskell-3/assets/foo.txt | 1 + tests/template-haskell-3/snack.nix | 13 +++ tests/template-haskell-3/src/Foo.hs | 5 + tests/template-haskell-3/src/FooBar.hs | 9 ++ tests/template-haskell/snack.nix | 2 +- 13 files changed, 167 insertions(+), 30 deletions(-) create mode 100644 tests/template-haskell-2/code/Main.hs create mode 100644 tests/template-haskell-2/code/snack.nix create mode 100644 tests/template-haskell-2/code/src/Foo.hs create mode 100644 tests/template-haskell-2/code/src/FooBar.hs create mode 100644 tests/template-haskell-2/foo.txt create mode 100644 tests/template-haskell-3/Main.hs create mode 100644 tests/template-haskell-3/assets/foo.txt create mode 100644 tests/template-haskell-3/snack.nix create mode 100644 tests/template-haskell-3/src/Foo.hs create mode 100644 tests/template-haskell-3/src/FooBar.hs diff --git a/script/test b/script/test index 3d9b008..79aea68 100755 --- a/script/test +++ b/script/test @@ -14,3 +14,11 @@ popd pushd tests/template-haskell snack build popd + +pushd tests/template-haskell-2/code +snack build +popd + +pushd tests/template-haskell-3 +snack build +popd diff --git a/snack/default.nix b/snack/default.nix index c4e2be5..31d47d1 100644 --- a/snack/default.nix +++ b/snack/default.nix @@ -22,10 +22,13 @@ let (expected == actual) || (type == "directory" && (pkgs.lib.strings.hasPrefix actual expected)); mod = fileToModule file; + # TODO: even though we're doing a lot of cleaning, there's sitll some + # 'does-file-exist' happening + src0 = pkgs.lib.cleanSource base; in pkgs.stdenv.mkDerivation { name = mod; - src = builtins.filterSource (pred file) base; + src = pkgs.lib.cleanSourceWith { filter = (pred file); src = src0; }; builder = pkgs.writeScript (mod + "-builder") # TODO: make sure the file actually exists and that there's only one '' @@ -41,11 +44,12 @@ let ''; }; - makeModuleSpec = modName: deps: isMain: modFiles: + makeModuleSpec = modName: deps: isMain: modFiles: modDirs: { moduleName = modName; moduleIsMain = isMain; moduleDependencies = deps; moduleFiles = modFiles; + moduleDirectories = modDirs; }; moduleToFile = mod: @@ -65,7 +69,7 @@ let # Create a module spec by following the dependencies. This assumes that the # specified module is a "Main" module. - makeModuleSpecRec = base: filesByModuleName: + makeModuleSpecRec = base: filesByModuleName: dirsByModuleName: pkgs.lib.fix (f: isMain: modName: makeModuleSpec @@ -73,6 +77,7 @@ let (map (f false) (listModuleDependencies base modName)) isMain (filesByModuleName modName) + (dirsByModuleName modName) ) true; buildModule = ghc: base: mod: @@ -88,11 +93,42 @@ let makeSymModule = # TODO: symlink instead of copy "rsync -r ${singleOutModule base mod.moduleName}/ ."; + + + + + pred = file: path: type: + let + topLevel = (builtins.toString base) + "/"; + actual = (pkgs.lib.strings.removePrefix topLevel path); + expected = file; + in + (expected == actual) || + (type == "directory" && (pkgs.lib.strings.hasPrefix actual expected)); + + + + extraFiles = builtins.filterSource + (p: t: + pkgs.lib.lists.length + ( + let + topLevel = (builtins.toString base) + "/"; + actual = pkgs.lib.strings.removePrefix topLevel p; + in + pkgs.lib.filter (expected: + (expected == actual) || + (t == "directory" && (pkgs.lib.strings.hasPrefix actual expected)) + ) + mod.moduleFiles + ) >= 1 + ) base; in pkgs.stdenv.mkDerivation { name = objectName; - src = builtins.filterSource (p: t: - pkgs.lib.lists.elem p (map toString mod.moduleFiles) - ) base; + src = pkgs.symlinkJoin + { name = "extra-files"; + paths = [ extraFiles ] ++ mod.moduleDirectories; + }; phases = [ "unpackPhase" "buildPhase" ]; buildPhase = @@ -129,20 +165,19 @@ let doesFileExist = base: filename: builtins.fromJSON (builtins.readFile ( - pkgs.stdenv.mkDerivation - { name = "does-file-exist"; - src = null; + pkgs.runCommand "does-file-exist" {} + + '' + if [ ! -f ${base}/${filename} ]; then + echo -n "false" > $out + else + echo -n "true" > $out + fi + '' + ) + ); + - builder = pkgs.writeScript "does-file-exist" - '' - if [ ! -f ${base}/${filename} ]; then - echo -n "false" > $out - else - echo -n "true" > $out - fi - ''; - } - )); doesModuleExist = base: modName: doesFileExist base (moduleToFile modName); # TODO: if module doesn't exist locally, don't include it @@ -256,21 +291,43 @@ let if (builtins.hasAttr "ghc-options" descr) then descr.ghc-options else []; - base = descr.src; - foo = - if (builtins.hasAttr "extra-files" descr) - then - if builtins.isList descr.extra-files - then (_x: descr.extra-files) - else descr.extra-files - else (x: []); + base = descr.src ; # pkgs.lib.cleanSource descr.src; + extraFiles = + if (builtins.hasAttr "extra-files" descr) + then + if builtins.isList descr.extra-files + then (_x: descr.extra-files) + else descr.extra-files + else (x: []); + #if (builtins.hasAttr "extra-files" descr) + #then + #if builtins.isList descr.extra-files + #then (_x: descr.extra-files) + #else descr.extra-files + #else (x: []); + extraDirs = + if (builtins.hasAttr "extra-directories" descr) + then + if builtins.isList descr.extra-directories + then (_x: descr.extra-directories) + else descr.extra-directories + else (x: []); mainModName = descr.main; in { build = - linkModuleObjects ghc ghcOpts deps base (makeModuleSpecRec base foo mainModName); + linkModuleObjects + ghc + ghcOpts + deps + base + (makeModuleSpecRec base extraFiles extraDirs mainModName); ghci = - ghciExecutable ghc ghcOpts base (makeModuleSpecRec base foo mainModName); + ghciExecutable + ghc + ghcOpts + base + (makeModuleSpecRec base extraFiles extraDirs mainModName); }; in diff --git a/tests/template-haskell-2/code/Main.hs b/tests/template-haskell-2/code/Main.hs new file mode 100644 index 0000000..ded314b --- /dev/null +++ b/tests/template-haskell-2/code/Main.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE TemplateHaskell #-} + +module Main where + +import Data.FileEmbed +import qualified Data.ByteString.Char8 as BS8 + +main :: IO () +main = BS8.putStrLn $(embedFile "./foo.txt") diff --git a/tests/template-haskell-2/code/snack.nix b/tests/template-haskell-2/code/snack.nix new file mode 100644 index 0000000..508b905 --- /dev/null +++ b/tests/template-haskell-2/code/snack.nix @@ -0,0 +1,11 @@ +let + pkgs = import ../../../nix {}; + snack = pkgs.snack-lib; +in + snack.executable + { main = "Main"; + src = ./.; + dependencies = ["file-embed"]; + extra-directories = + (modName: if modName == "Main" then [ ../. ] else []); + } diff --git a/tests/template-haskell-2/code/src/Foo.hs b/tests/template-haskell-2/code/src/Foo.hs new file mode 100644 index 0000000..160e3a5 --- /dev/null +++ b/tests/template-haskell-2/code/src/Foo.hs @@ -0,0 +1,5 @@ +import Conduit +import FooBar + +main :: IO () +main = runConduit $ spitOut .| takeC 5 .| digest diff --git a/tests/template-haskell-2/code/src/FooBar.hs b/tests/template-haskell-2/code/src/FooBar.hs new file mode 100644 index 0000000..78abe00 --- /dev/null +++ b/tests/template-haskell-2/code/src/FooBar.hs @@ -0,0 +1,9 @@ +module FooBar where + +import Conduit + +spitOut :: ConduitT () Int IO () +spitOut = yieldMany [ 1 ..] + +digest :: ConduitT Int Void IO () +digest = mapM_C print diff --git a/tests/template-haskell-2/foo.txt b/tests/template-haskell-2/foo.txt new file mode 100644 index 0000000..8ab686e --- /dev/null +++ b/tests/template-haskell-2/foo.txt @@ -0,0 +1 @@ +Hello, World! diff --git a/tests/template-haskell-3/Main.hs b/tests/template-haskell-3/Main.hs new file mode 100644 index 0000000..82da641 --- /dev/null +++ b/tests/template-haskell-3/Main.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE TemplateHaskell #-} + +module Main where + +import Data.FileEmbed +import qualified Data.ByteString.Char8 as BS8 + +main :: IO () +main = BS8.putStrLn $(embedFile "assets/foo.txt") diff --git a/tests/template-haskell-3/assets/foo.txt b/tests/template-haskell-3/assets/foo.txt new file mode 100644 index 0000000..8ab686e --- /dev/null +++ b/tests/template-haskell-3/assets/foo.txt @@ -0,0 +1 @@ +Hello, World! diff --git a/tests/template-haskell-3/snack.nix b/tests/template-haskell-3/snack.nix new file mode 100644 index 0000000..668685c --- /dev/null +++ b/tests/template-haskell-3/snack.nix @@ -0,0 +1,13 @@ +let + pkgs = import ../../nix {}; + snack = pkgs.snack-lib; +in + snack.executable + { main = "Main"; + src = ./.; + dependencies = ["file-embed"]; + extra-files = + # "assets/foo.txt", which is just + # filterSource (p == "assets/foo.txt") ./. + (modName: if modName == "Main" then [ "assets/foo.txt" ] else []); + } diff --git a/tests/template-haskell-3/src/Foo.hs b/tests/template-haskell-3/src/Foo.hs new file mode 100644 index 0000000..160e3a5 --- /dev/null +++ b/tests/template-haskell-3/src/Foo.hs @@ -0,0 +1,5 @@ +import Conduit +import FooBar + +main :: IO () +main = runConduit $ spitOut .| takeC 5 .| digest diff --git a/tests/template-haskell-3/src/FooBar.hs b/tests/template-haskell-3/src/FooBar.hs new file mode 100644 index 0000000..78abe00 --- /dev/null +++ b/tests/template-haskell-3/src/FooBar.hs @@ -0,0 +1,9 @@ +module FooBar where + +import Conduit + +spitOut :: ConduitT () Int IO () +spitOut = yieldMany [ 1 ..] + +digest :: ConduitT Int Void IO () +digest = mapM_C print diff --git a/tests/template-haskell/snack.nix b/tests/template-haskell/snack.nix index 270472a..36418dc 100644 --- a/tests/template-haskell/snack.nix +++ b/tests/template-haskell/snack.nix @@ -7,5 +7,5 @@ in src = ./.; dependencies = ["file-embed"]; extra-files = - (modName: if modName == "Main" then [ ./foo.txt ] else []); + (modName: if modName == "Main" then [ "foo.txt" ] else []); }