-
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 16 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,42 +1,54 @@ | ||
{ 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 | ||
}: | ||
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 ]; | ||
|
||
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"; | ||
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)} | ||
installPhase = '' | ||
mkdir -p $out/share/doc | ||
|
||
\${lib.concatStrings (map (module: | ||
let fullmodule = sanitizePath module; | ||
modulename = sanitizePath (lib.removePrefix "./" module); | ||
in '' | ||
echo "compiling \${module}" | ||
elm make \${fullmodule}.elm --output $out/\${modulename}.html --docs $out/share/doc/\${modulename}.json | ||
'') targets)} | ||
''; | ||
}; | ||
in mkDerivation { | ||
name = "${name}"; | ||
srcs = ./elm-srcs.nix; | ||
src = ./.; | ||
targets = ["Main"]; | ||
srcs = ${srcs}; | ||
srcdir = "${srcdir}"; | ||
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 |
||
} |
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,40 @@ parseElmJsonDeps obj = | |
parseDeps (Object hm) = mapM (uncurry parseDep) (HM.toList hm) | ||
parseDeps v = Left (UnexpectedValue v) | ||
|
||
-- TODO: there is likely to be even better abstraction | ||
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 | ||
-- the `source-directories` part of elm.json is optional | ||
-- if user don't specified this value `src` directory is the default | ||
Left _ -> Right $ pure "./src" | ||
Right srcs -> | ||
case srcs of | ||
Array vec -> mapM extractSrcPath vec | ||
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 | ||
|
||
|
@@ -90,7 +120,17 @@ 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 | ||
|
@@ -102,8 +142,29 @@ initialize = runCLI $ | |
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 = | ||
case Vector.toList dirs of | ||
[] -> pure "./src" -- in theory redundant | ||
[ dir ] -> pure dir | ||
xs@(h:t) -> | ||
if "./." `elem` xs then do | ||
-- Nix creates dir named after current directory | ||
-- if `srcs` contains `./.` | ||
path <- liftIO System.Directory.getCurrentDirectory | ||
pure (lastDir path) | ||
else | ||
-- We can't really tell which one to choose | ||
-- so we guess it's the first one | ||
pure h | ||
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 |
||
-- TODO: Improve | ||
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 | ||
|
||
|
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