-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[POC] Elm json "source-directories" support #27
base: master
Are you sure you want to change the base?
Changes from 22 commits
05901cd
bec0af0
9f0e44e
d293a82
aaebde0
505750c
f7b8cc8
256138e
58a2a19
1c7ab69
b562bee
bb5bcc1
b65e410
e1c290e
7d67711
571cac6
2f46543
9bd289e
7786955
0b86e5d
0a26a19
56be5d7
f9511bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,69 @@ | ||
{ nixpkgs ? <nixpkgs> | ||
, config ? {} | ||
}: | ||
|
||
with (import nixpkgs config); | ||
|
||
let | ||
mkDerivation = | ||
{ srcs ? ./elm-srcs.nix | ||
, src | ||
{ elmsrcs ? ./elm-srcs.nix | ||
, srcs | ||
, srcdir ? "src" | ||
, name | ||
, srcdir ? "./src" | ||
, targets ? [] | ||
, versionsDat ? ./versions.dat | ||
, outputJavaScript ? false | ||
}: | ||
stdenv.mkDerivation { | ||
inherit name src; | ||
let sanitizePath = str: | ||
let path = builtins.filter (p: p != "..") (lib.splitString "/" str); | ||
in lib.concatStringsSep "/" (map (p: if p == "." then srcdir else p) path); | ||
in stdenv.mkDerivation { | ||
inherit name srcs; | ||
sourceRoot = "."; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this can be hardcoded - we place generated elm.json with correct paths and the prefix |
||
|
||
buildInputs = [ elmPackages.elm ] | ||
++ lib.optional outputJavaScript nodePackages_10_x.uglify-js; | ||
|
||
patchPhase = let | ||
elmjson = let json = (lib.importJSON ./elm.json) // { source-directories = map sanitizePath srcs; }; | ||
in writeText "elm.json" (builtins.toJSON json); | ||
in '' | ||
echo "Generating elm.json" | ||
cp \${elmjson} ./elm.json | ||
cat elm.json | ||
''; | ||
|
||
buildPhase = pkgs.elmPackages.fetchElmDeps { | ||
elmPackages = import srcs; | ||
elmPackages = import elmsrcs; | ||
inherit versionsDat; | ||
}; | ||
|
||
installPhase = let | ||
elmfile = module: "\${srcdir}/\${builtins.replaceStrings ["."] ["/"] module}.elm"; | ||
extension = if outputJavaScript then "js" else "html"; | ||
installPhase = | ||
let extension = if outputJavaScript then "js" else "html"; | ||
in '' | ||
mkdir -p \$out/share/doc | ||
\${lib.concatStrings (map (module: '' | ||
echo "compiling \${elmfile module}" | ||
elm make \${elmfile module} --output \$out/\${module}.\${extension} --docs \$out/share/doc/\${module}.json | ||
\${lib.concatStrings (map (module: | ||
let fullmodule = sanitizePath module; | ||
modulename = sanitizePath (lib.removePrefix "./" module); | ||
in '' | ||
echo "compiling \${modulename}" | ||
elm make \${fullmodule}.elm --output \$out/\${modulename}.\${extension} --docs \$out/share/doc/\${modulename}.json | ||
\${lib.optionalString outputJavaScript '' | ||
echo "minifying \${elmfile module}" | ||
uglifyjs $out/\${module}.\${extension} --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \\ | ||
| uglifyjs --mangle --output=$out/\${module}.min.\${extension} | ||
echo "minifying \${modulename}" | ||
uglifyjs $out/\${modulename}.\${extension} --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \\ | ||
| uglifyjs --mangle --output=$out/\${modulename}.min.\${extension} | ||
''} | ||
'') targets)} | ||
''; | ||
}; | ||
in mkDerivation { | ||
name = "${name}"; | ||
srcs = ./elm-srcs.nix; | ||
src = ./.; | ||
targets = ["Main"]; | ||
elmsrcs = ./elm-srcs.nix; | ||
srcs = ${srcs}; | ||
# Generated by elm2nix | ||
# should be *name* of current directory is used to find sources | ||
srcdir = "${srcdir}"; | ||
# Please configure this line | ||
# Should be relative path as a string to modules you want to compile | ||
# excluding `.elm` extension | ||
targets = ["./Main"]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BREAKING change: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we revert this then? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unfortunetely this is still required. Imagine you have
Now when you set Another issue is that with current dir. Imagine having this
since I've used
this is why Main is prefixed with I wonder if there is any builtin helper that would help to resolve paths in a way nix does it when |
||
outputJavaScript = false; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,13 +17,16 @@ import Data.List (intercalate) | |
import Data.HashMap.Strict (HashMap) | ||
import Data.String.Here | ||
import Data.Text (Text) | ||
import Data.Vector (Vector) | ||
import System.Exit (exitFailure) | ||
import System.IO (hPutStrLn, stderr) | ||
|
||
import qualified System.Directory | ||
import qualified Data.HashMap.Strict as HM | ||
import qualified Data.ByteString.Lazy as LBS | ||
import qualified Data.Aeson as Json | ||
import qualified Data.Text as Text | ||
import qualified Data.Vector as Vector | ||
|
||
import Elm2Nix.FixedOutput (FixedDerivation(..), prefetch) | ||
import Elm2Nix.PackagesSnapshot (snapshot) | ||
|
@@ -67,13 +70,35 @@ parseElmJsonDeps depsKey obj = | |
parseDeps (Object hm) = mapM (uncurry parseDep) (HM.toList hm) | ||
parseDeps v = Left (UnexpectedValue v) | ||
|
||
tryLookup :: HashMap Text Value -> Text -> Either Elm2NixError Value | ||
tryLookup hm key = maybeToRight (KeyNotFound key) (HM.lookup key hm) | ||
where | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. reused between |
||
maybeToRight :: b -> Maybe a -> Either b a | ||
maybeToRight _ (Just x) = Right x | ||
maybeToRight y Nothing = Left y | ||
|
||
tryLookup :: HashMap Text Value -> Text -> Either Elm2NixError Value | ||
tryLookup hm key = | ||
maybeToRight (KeyNotFound key) (HM.lookup key hm) | ||
parseElmJsonSrcs :: Value -> Either Elm2NixError (Vector FilePath) | ||
parseElmJsonSrcs obj = | ||
case obj of | ||
Object hm -> do | ||
case tryLookup hm "source-directories" of | ||
Left _ -> Right Vector.empty | ||
Right (Array vec) -> mapM extractSrcPath vec | ||
Right v -> Left (UnexpectedValue v) | ||
v -> Left $ UnexpectedValue v | ||
where | ||
extractSrcPath :: Value -> Either Elm2NixError String | ||
extractSrcPath val = | ||
case val of | ||
String text -> Right (toNixPath (Text.unpack text)) | ||
v -> Left (UnexpectedValue v) | ||
|
||
toNixPath :: FilePath -> FilePath | ||
toNixPath path = | ||
case path of | ||
"." -> "./." | ||
p@('.':_) -> p | ||
p -> "./" <> p | ||
|
||
-- CMDs | ||
|
||
|
@@ -91,20 +116,50 @@ convert = runCLI $ do | |
liftIO (putStrLn (generateNixSources sources)) | ||
|
||
initialize :: IO () | ||
initialize = runCLI $ | ||
initialize = runCLI $ do | ||
liftIO (hPutStrLn stderr "Resolving elm.json source directories into Nix paths...") | ||
res <- liftIO (fmap Json.eitherDecode (LBS.readFile "elm.json")) | ||
elmJson <- either (throwErr . ElmJsonReadError) return res | ||
|
||
srcs' <- either throwErr return (parseElmJsonSrcs elmJson) | ||
liftIO (hPutStrLn stderr $ "Using source directories:") | ||
liftIO (mapM (hPutStrLn stderr) srcs') | ||
let srcs = stringifySrcs srcs' | ||
srcdir <- liftIO (getSrcDir srcs') | ||
|
||
liftIO (putStrLn [template|data/default.nix|]) | ||
where | ||
-- | Converts Package.Name to Nix friendly name | ||
baseName :: Text | ||
baseName = "elm-app" | ||
|
||
version :: Text | ||
version = "0.1.0" | ||
|
||
toNixName :: Text -> Text | ||
toNixName = Text.replace "/" "-" | ||
|
||
name :: String | ||
name = Text.unpack (toNixName baseName <> "-" <> version) | ||
srcdir :: String | ||
srcdir = "./src" -- TODO: get from elm.json | ||
|
||
getSrcDir :: Vector FilePath -> IO FilePath | ||
getSrcDir dirs | ||
| Vector.null dirs = pure "./src" | ||
| "./." `Vector.elem` dirs || "." `Vector.elem` dirs = | ||
-- Nix creates dir named after current directory if `srcs` contains `./.` | ||
lastDir <$> liftIO System.Directory.getCurrentDirectory | ||
| otherwise = | ||
-- Can't fail as there is case for Vec.null! | ||
pure (Vector.head dirs) | ||
|
||
lastDir :: FilePath -> FilePath | ||
lastDir = foldl (\path c -> if c == '/' then "" else path <> [c]) "" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not the most efficient way to implement this but quite concise |
||
|
||
stringifySrcs :: Vector FilePath -> String | ||
stringifySrcs xs = | ||
"[\n" | ||
<> foldr (\i acc -> " " <> i <> "\n" <> acc) "" xs | ||
<> " ]" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. todo: use QuasiQuotes |
||
|
||
-- Utils | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.nix | ||
*.dat |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ nixpkgs ? <nixpkgs> | ||
, config ? {} | ||
}: | ||
|
||
with (import nixpkgs config); | ||
|
||
let | ||
mkDerivation = | ||
{ srcs ? ./elm-srcs.nix | ||
, src | ||
, name | ||
, srcdir ? "./src" | ||
, targets ? [] | ||
, versionsDat ? ./versions.dat | ||
}: | ||
stdenv.mkDerivation { | ||
inherit name src; | ||
|
||
buildInputs = [ elmPackages.elm ]; | ||
|
||
buildPhase = pkgs.elmPackages.fetchElmDeps { | ||
elmPackages = import srcs; | ||
inherit versionsDat; | ||
}; | ||
|
||
installPhase = let | ||
elmfile = module: "${srcdir}/${builtins.replaceStrings ["."] ["/"] module}.elm"; | ||
in '' | ||
mkdir -p $out/share/doc | ||
${lib.concatStrings (map (module: '' | ||
echo "compiling ${elmfile module}" | ||
elm make ${elmfile module} --output $out/${module}.html --docs $out/share/doc/${module}.json | ||
'') targets)} | ||
''; | ||
}; | ||
in mkDerivation { | ||
name = "elm-app-0.1.0"; | ||
srcs = ./elm-srcs.nix; | ||
src = ./.; | ||
targets = ["Main"]; | ||
srcdir = "./src"; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
|
||
"elm/core" = { | ||
sha256 = "1l0qdbczw91kzz8sx5d5zwz9x662bspy7p21dsr3f2rigxiix2as"; | ||
version = "1.0.2"; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module Main exposing (main) | ||
|
||
import Html exposing (..) | ||
import Text | ||
|
||
main = text Text.hello |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"type": "application", | ||
"source-directories": [ | ||
".", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tests #19 |
||
"../b-src/src" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tests #6 |
||
], | ||
"elm-version": "0.19.0", | ||
"dependencies": { | ||
"direct": { | ||
"elm/browser": "1.0.1", | ||
"elm/core": "1.0.2", | ||
"elm/html": "1.0.0" | ||
}, | ||
"indirect": { | ||
"elm/json": "1.1.3", | ||
"elm/time": "1.0.0", | ||
"elm/url": "1.0.0", | ||
"elm/virtual-dom": "1.0.2" | ||
} | ||
}, | ||
"test-dependencies": { | ||
"direct": {}, | ||
"indirect": {} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module Text exposing (hello) | ||
|
||
hello = "Hello world!" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replaced by
srcs