mirror of
https://github.com/nmattia/snack.git
synced 2024-09-11 11:55:36 +03:00
Add rudimentary HPack support
This commit is contained in:
parent
a05c5655c8
commit
3c8ef4ec70
76
bin/Snack.hs
76
bin/Snack.hs
@ -32,13 +32,20 @@ import qualified Shelly as S
|
||||
|
||||
data Mode
|
||||
= Standalone SnackNix -- Reads a snack.nix file
|
||||
| HPack PackageYaml
|
||||
|
||||
-- | Like a FilePath, but Nix friendly
|
||||
newtype SnackNix = SnackNix { unSnackNix :: FilePath }
|
||||
|
||||
newtype PackageYaml = PackageYaml { unPackageYaml :: FilePath }
|
||||
|
||||
mkSnackNix :: FilePath -> SnackNix
|
||||
mkSnackNix = SnackNix -- XXX: this is not nix friendly, but it's ok, because
|
||||
-- it'll be gone soon
|
||||
--
|
||||
mkPackageYaml :: FilePath -> PackageYaml
|
||||
mkPackageYaml = PackageYaml -- XXX: this is not nix friendly, but it's ok, because
|
||||
-- it'll be gone soon
|
||||
|
||||
data Command
|
||||
= Build
|
||||
@ -66,16 +73,26 @@ instance Aeson.FromJSON Project where
|
||||
|
||||
parseMode :: Opts.Parser Mode
|
||||
parseMode =
|
||||
Opts.flag Standalone Standalone
|
||||
(Opts.long "--standalone")
|
||||
-- Opts.flag Standalone Standalone
|
||||
-- (Opts.long "standalone")
|
||||
|
||||
<*> (mkSnackNix <$>
|
||||
((Standalone . mkSnackNix) <$>
|
||||
Opts.strOption
|
||||
(Opts.long "--snack-nix"
|
||||
(Opts.long "snack-nix"
|
||||
<> Opts.short 's'
|
||||
<> Opts.value "./snack.nix"
|
||||
<> Opts.metavar "PATH")
|
||||
)
|
||||
<|>
|
||||
-- Opts.flag HPack HPack
|
||||
-- (Opts.long "hpack")
|
||||
|
||||
((HPack . mkPackageYaml) <$>
|
||||
Opts.strOption
|
||||
(Opts.long "package-yaml"
|
||||
<> Opts.value "./package.yaml"
|
||||
<> Opts.metavar "PATH")
|
||||
)
|
||||
|
||||
options :: Opts.Parser Options
|
||||
options = Options <$> parseMode <*> parseCommand
|
||||
@ -127,6 +144,49 @@ snackBuildGhci snackNix = do
|
||||
let Just proj = Aeson.decodeStrict' json
|
||||
pure proj
|
||||
|
||||
snackBuildHPack :: PackageYaml -> Sh Project
|
||||
snackBuildHPack packageYaml = do
|
||||
out <- runStdin1
|
||||
(T.pack [i|
|
||||
{ base, packageYaml, lib64, specJson }:
|
||||
let
|
||||
spec = builtins.fromJSON specJson;
|
||||
pkgs = import (builtins.fetchTarball
|
||||
{ url = "https://github.com/${spec.owner}/${spec.repo}/archive/${spec.rev}.tar.gz";
|
||||
sha256 = spec.sha256;
|
||||
}) {} ;
|
||||
libDir =
|
||||
let
|
||||
b64 = pkgs.writeTextFile { name = "lib-b64"; text = lib64; };
|
||||
in
|
||||
pkgs.runCommand "snack-lib" {}
|
||||
''
|
||||
cat ${b64} | base64 --decode > out.tar.gz
|
||||
mkdir -p $out
|
||||
tar -C $out -xzf out.tar.gz
|
||||
chmod +w $out
|
||||
'';
|
||||
snack = pkgs.callPackage libDir {};
|
||||
proj = snack.packageYaml packageYaml;
|
||||
in
|
||||
{ build = proj.library.build;
|
||||
ghci = proj.librayr.build;
|
||||
}
|
||||
|]
|
||||
)
|
||||
"nix-build"
|
||||
[ "-"
|
||||
, "--arg", "packageYaml", T.pack $ unPackageYaml packageYaml
|
||||
, "--argstr", "lib64", libb64
|
||||
, "--argstr", "specJson", specJson
|
||||
, "--arg", "base", "./app"
|
||||
, "--no-out-link"
|
||||
, "-A", "build.json"
|
||||
]
|
||||
json <- liftIO $ BS.readFile (T.unpack out)
|
||||
let Just proj = Aeson.decodeStrict' json
|
||||
pure proj
|
||||
|
||||
snackBuild :: SnackNix -> Sh Project
|
||||
snackBuild snackNix = do
|
||||
out <- runStdin1
|
||||
@ -178,6 +238,14 @@ runCommand (Standalone snackNix) = \case
|
||||
snackRun build = do
|
||||
fp <- S.shelly $ S.print_stdout False $ exePath <$> build snackNix
|
||||
executeFile fp True [] Nothing
|
||||
runCommand (HPack packageYaml) = \case
|
||||
Build -> S.shelly $ void $ snackBuildHPack packageYaml
|
||||
Run -> undefined -- snackRun snackBuild
|
||||
Ghci -> undefined -- snackRun snackBuildGhci
|
||||
-- where
|
||||
-- snackRun build = do
|
||||
-- fp <- S.shelly $ S.print_stdout False $ exePath <$> build packageYaml
|
||||
-- executeFile fp True [] Nothing
|
||||
|
||||
parseCommand :: Opts.Parser Command
|
||||
parseCommand =
|
||||
|
74
script/test
74
script/test
@ -1,15 +1,20 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
#!nix-shell -I nixpkgs=./nix
|
||||
#!nix-shell -p snack-exe
|
||||
#!nix-shell -p shfmt
|
||||
#!nix-shell -p git
|
||||
#!nix-shell -p jq
|
||||
#!nix-shell -p nix
|
||||
#!nix-shell -p shfmt
|
||||
#!nix-shell -p snack-exe
|
||||
#!nix-shell -p glibcLocales
|
||||
#!nix-shell --pure
|
||||
# vim: ft=sh sw=2 et
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
export LC_ALL="en_US.utf-8"
|
||||
export LANG="en_US.utf-8"
|
||||
|
||||
## Functions
|
||||
|
||||
banner() {
|
||||
@ -44,43 +49,48 @@ fail() {
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
banner "Test packages"
|
||||
pushd tests/packages
|
||||
./test
|
||||
popd
|
||||
#banner "Test packages"
|
||||
#pushd tests/packages
|
||||
#./test
|
||||
#popd
|
||||
|
||||
banner "Test Template Haskell"
|
||||
pushd tests/template-haskell
|
||||
./test
|
||||
popd
|
||||
#banner "Test Template Haskell"
|
||||
#pushd tests/template-haskell
|
||||
#./test
|
||||
#popd
|
||||
|
||||
banner "Test Template Haskell 2"
|
||||
pushd tests/template-haskell-2
|
||||
./test
|
||||
popd
|
||||
#banner "Test Template Haskell 2"
|
||||
#pushd tests/template-haskell-2
|
||||
#./test
|
||||
#popd
|
||||
|
||||
banner "Test Template Haskell 3"
|
||||
pushd tests/template-haskell-3
|
||||
./test
|
||||
popd
|
||||
#banner "Test Template Haskell 3"
|
||||
#pushd tests/template-haskell-3
|
||||
#./test
|
||||
#popd
|
||||
|
||||
banner "Test Template Haskell 4"
|
||||
pushd tests/template-haskell-4
|
||||
./test
|
||||
popd
|
||||
#banner "Test Template Haskell 4"
|
||||
#pushd tests/template-haskell-4
|
||||
#./test
|
||||
#popd
|
||||
|
||||
banner "Test library"
|
||||
pushd tests/library
|
||||
./test
|
||||
popd
|
||||
#banner "Test library"
|
||||
#pushd tests/library
|
||||
#./test
|
||||
#popd
|
||||
|
||||
banner "Test library-2"
|
||||
pushd tests/library-2
|
||||
./test
|
||||
popd
|
||||
#banner "Test library-2"
|
||||
#pushd tests/library-2
|
||||
#./test
|
||||
#popd
|
||||
|
||||
banner "Test extensions"
|
||||
pushd tests/extensions
|
||||
#banner "Test extensions"
|
||||
#pushd tests/extensions
|
||||
#./test
|
||||
#popd
|
||||
|
||||
banner "HPack"
|
||||
pushd tests/hpack
|
||||
./test
|
||||
popd
|
||||
|
||||
|
17
snack-lib/YamlToJson.hs
Normal file
17
snack-lib/YamlToJson.hs
Normal file
@ -0,0 +1,17 @@
|
||||
module Main where
|
||||
|
||||
import qualified Data.Aeson as Aeson
|
||||
import qualified Data.Yaml as Yaml
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Lazy as BL
|
||||
import qualified Data.ByteString.Lazy.Char8 as BL8
|
||||
import qualified Data.ByteString.Char8 as BS8
|
||||
import qualified Data.Text.Encoding as T
|
||||
import System.Environment (getArgs)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
[file] <- getArgs
|
||||
yaml <- BS8.readFile file
|
||||
let Just value = Yaml.decode yaml :: Maybe Aeson.Value
|
||||
BL8.putStrLn $ Aeson.encode value
|
@ -18,6 +18,7 @@ with (callPackage ./files.nix {});
|
||||
with (callPackage ./modules.nix { inherit singleOut; });
|
||||
with (callPackage ./module-spec.nix { inherit singleOut; });
|
||||
with (callPackage ./package-spec.nix { inherit singleOut; });
|
||||
with (callPackage ./hpack.nix { inherit singleOut; });
|
||||
with (callPackage ./lib.nix {});
|
||||
|
||||
let
|
||||
@ -312,9 +313,17 @@ let
|
||||
json = writeText "ghci_output" (builtins.toJSON json);
|
||||
};
|
||||
};
|
||||
packageYaml = pyam:
|
||||
let
|
||||
project = snackNixFromHPack pyam;
|
||||
in
|
||||
{ library = executable project.library;
|
||||
executables = lib.attrsets.mapAttrs (_: v: executable v) project.executables;
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit
|
||||
executable
|
||||
packageYaml
|
||||
;
|
||||
}
|
||||
|
73
snack-lib/hpack.nix
Normal file
73
snack-lib/hpack.nix
Normal file
@ -0,0 +1,73 @@
|
||||
{ lib, glibcLocales, callPackage, singleOut, writeText, runCommand, haskellPackages }:
|
||||
|
||||
with (callPackage ./modules.nix { inherit singleOut; });
|
||||
|
||||
let
|
||||
y2j = runCommand "yaml2json"
|
||||
|
||||
{ buildInputs =
|
||||
[ (haskellPackages.ghcWithPackages (ps: [ ps.aeson ps.yaml ])) glibcLocales ];
|
||||
}
|
||||
"ghc ${./YamlToJson.hs} -o $out";
|
||||
|
||||
fromYAML = text:
|
||||
let json =
|
||||
|
||||
builtins.readFile (runCommand "y2j"
|
||||
{ buildInputs = [ glibcLocales ]; }
|
||||
"${y2j} ${writeText "y2j" text} > $out"
|
||||
);
|
||||
in builtins.fromJSON json;
|
||||
|
||||
|
||||
in
|
||||
{
|
||||
snackNixFromHPack = packageYaml:
|
||||
let
|
||||
package = fromYAML (builtins.readFile packageYaml);
|
||||
topDeps =
|
||||
# this drops the version bounds
|
||||
map (x: lib.lists.head (lib.strings.splitString " " x))
|
||||
package.dependencies;
|
||||
extensions = package.default-extensions;
|
||||
packageLib =
|
||||
let component = package.library;
|
||||
in
|
||||
{ src =
|
||||
let base = builtins.dirOf packageYaml;
|
||||
in builtins.toPath "${builtins.toString base}/${component.source-dirs}";
|
||||
dependencies = topDeps ++
|
||||
(if builtins.hasAttr "dependencies" component
|
||||
then component.dependencies
|
||||
else []);
|
||||
|
||||
inherit extensions;
|
||||
};
|
||||
|
||||
exes =
|
||||
if builtins.hasAttr "executables" package
|
||||
then lib.mapAttrs (k: v: mkExe v) package.executables
|
||||
else {};
|
||||
mkExe = component:
|
||||
let
|
||||
depOrPack =
|
||||
lib.lists.partition
|
||||
(x: x == package.name)
|
||||
(if builtins.hasAttr "dependencies" component
|
||||
then component.dependencies
|
||||
else []);
|
||||
packages = map (_: packageLib) depOrPack.right;
|
||||
dependencies = topDeps ++ depOrPack.wrong;
|
||||
in
|
||||
{ main = fileToModule component.main;
|
||||
src =
|
||||
let
|
||||
base = builtins.dirOf packageYaml;
|
||||
in builtins.toPath "${builtins.toString base}/${component.source-dirs}";
|
||||
inherit packages dependencies extensions;
|
||||
};
|
||||
in
|
||||
{ library = packageLib;
|
||||
executables = exes;
|
||||
};
|
||||
}
|
13
tests/hpack/test
Executable file
13
tests/hpack/test
Executable file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
# vim: ft=sh sw=2 et
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
TMP_DIR=$(mktemp -d)
|
||||
|
||||
git clone http://github.com/2mol/pboy.git $TMP_DIR
|
||||
git -C $TMP_DIR reset --hard a2458d6984930a33a3b1972cb6d5c167d2511b06
|
||||
|
||||
snack build --package-yaml $TMP_DIR/package.yaml
|
||||
|
||||
rm -rf $TMP_DIR
|
Loading…
Reference in New Issue
Block a user