module Hix.Bootstrap where
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Reader (ask)
import Data.List.NonEmpty ((<|))
import qualified Data.Text as Text
import Distribution.Compiler (PerCompilerFlavor (PerCompilerFlavor))
import qualified Distribution.PackageDescription as Cabal
import Distribution.PackageDescription (
BuildInfo,
GenericPackageDescription,
PackageDescription,
UnqualComponentName,
buildType,
licenseFiles,
unPackageName,
unUnqualComponentName,
)
import Distribution.Pretty (Pretty, pretty)
import Distribution.Simple (Dependency (Dependency), depVerRange)
import Distribution.Types.PackageDescription (license)
import Distribution.Utils.ShortText (ShortText, fromShortText)
import qualified Distribution.Verbosity as Cabal
import Exon (exon)
import Path (Abs, Dir, File, Path, Rel, parent, parseRelFile, relfile, toFilePath, (</>))
import System.FilePattern.Directory (getDirectoryFilesIgnore)
import Hix.Compat (readGenericPackageDescription)
import qualified Hix.Data.BootstrapProjectConfig
import Hix.Data.BootstrapProjectConfig (BootstrapProjectConfig)
import qualified Hix.Data.ComponentConfig
import Hix.Data.ComponentConfig (PackageName (PackageName))
import Hix.Data.Error (pathText, tryIO)
import qualified Hix.Data.NewProjectConfig
import qualified Hix.Data.ProjectFile
import Hix.Data.ProjectFile (ProjectFile (ProjectFile), createFile)
import qualified Hix.Monad
import Hix.Monad (Env (Env), M, noteBootstrap)
import qualified Hix.Prelude
import Hix.Prelude (Prelude, findPrelude)
data ExprAttr =
ExprAttr {
ExprAttr -> Text
name :: Text,
ExprAttr -> Expr
value :: Expr
}
|
ExprAttrNil
deriving stock (ExprAttr -> ExprAttr -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ExprAttr -> ExprAttr -> Bool
$c/= :: ExprAttr -> ExprAttr -> Bool
== :: ExprAttr -> ExprAttr -> Bool
$c== :: ExprAttr -> ExprAttr -> Bool
Eq, Int -> ExprAttr -> ShowS
[ExprAttr] -> ShowS
ExprAttr -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExprAttr] -> ShowS
$cshowList :: [ExprAttr] -> ShowS
show :: ExprAttr -> String
$cshow :: ExprAttr -> String
showsPrec :: Int -> ExprAttr -> ShowS
$cshowsPrec :: Int -> ExprAttr -> ShowS
Show, forall x. Rep ExprAttr x -> ExprAttr
forall x. ExprAttr -> Rep ExprAttr x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ExprAttr x -> ExprAttr
$cfrom :: forall x. ExprAttr -> Rep ExprAttr x
Generic)
data Expr =
ExprString Text
|
ExprLit Text
|
ExprList [Expr]
|
ExprAttrs [ExprAttr]
|
ExprPrefix Text Expr
deriving stock (Expr -> Expr -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Expr -> Expr -> Bool
$c/= :: Expr -> Expr -> Bool
== :: Expr -> Expr -> Bool
$c== :: Expr -> Expr -> Bool
Eq, Int -> Expr -> ShowS
[Expr] -> ShowS
Expr -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Expr] -> ShowS
$cshowList :: [Expr] -> ShowS
show :: Expr -> String
$cshow :: Expr -> String
showsPrec :: Int -> Expr -> ShowS
$cshowsPrec :: Int -> Expr -> ShowS
Show, forall x. Rep Expr x -> Expr
forall x. Expr -> Rep Expr x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Expr x -> Expr
$cfrom :: forall x. Expr -> Rep Expr x
Generic)
exprStrings :: [Text] -> Expr
exprStrings :: [Text] -> Expr
exprStrings =
[Expr] -> Expr
ExprList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Expr
ExprString
data CabalInfo =
CabalInfo {
CabalInfo -> Path Rel Dir
path :: Path Rel Dir,
CabalInfo -> GenericPackageDescription
info :: GenericPackageDescription
}
deriving stock (CabalInfo -> CabalInfo -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CabalInfo -> CabalInfo -> Bool
$c/= :: CabalInfo -> CabalInfo -> Bool
== :: CabalInfo -> CabalInfo -> Bool
$c== :: CabalInfo -> CabalInfo -> Bool
Eq, Int -> CabalInfo -> ShowS
[CabalInfo] -> ShowS
CabalInfo -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CabalInfo] -> ShowS
$cshowList :: [CabalInfo] -> ShowS
show :: CabalInfo -> String
$cshow :: CabalInfo -> String
showsPrec :: Int -> CabalInfo -> ShowS
$cshowsPrec :: Int -> CabalInfo -> ShowS
Show, forall x. Rep CabalInfo x -> CabalInfo
forall x. CabalInfo -> Rep CabalInfo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CabalInfo x -> CabalInfo
$cfrom :: forall x. CabalInfo -> Rep CabalInfo x
Generic)
data ComponentType =
Library
|
Executable Text
|
Benchmark Text
|
Test Text
deriving stock (ComponentType -> ComponentType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ComponentType -> ComponentType -> Bool
$c/= :: ComponentType -> ComponentType -> Bool
== :: ComponentType -> ComponentType -> Bool
$c== :: ComponentType -> ComponentType -> Bool
Eq, Int -> ComponentType -> ShowS
[ComponentType] -> ShowS
ComponentType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ComponentType] -> ShowS
$cshowList :: [ComponentType] -> ShowS
show :: ComponentType -> String
$cshow :: ComponentType -> String
showsPrec :: Int -> ComponentType -> ShowS
$cshowsPrec :: Int -> ComponentType -> ShowS
Show, forall x. Rep ComponentType x -> ComponentType
forall x. ComponentType -> Rep ComponentType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ComponentType x -> ComponentType
$cfrom :: forall x. ComponentType -> Rep ComponentType x
Generic)
data PreludeWithVersion =
PreludeWithVersion {
PreludeWithVersion -> Prelude
prelude :: Prelude,
PreludeWithVersion -> Maybe Dependency
dep :: Maybe Dependency
}
deriving stock (PreludeWithVersion -> PreludeWithVersion -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PreludeWithVersion -> PreludeWithVersion -> Bool
$c/= :: PreludeWithVersion -> PreludeWithVersion -> Bool
== :: PreludeWithVersion -> PreludeWithVersion -> Bool
$c== :: PreludeWithVersion -> PreludeWithVersion -> Bool
Eq, Int -> PreludeWithVersion -> ShowS
[PreludeWithVersion] -> ShowS
PreludeWithVersion -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PreludeWithVersion] -> ShowS
$cshowList :: [PreludeWithVersion] -> ShowS
show :: PreludeWithVersion -> String
$cshow :: PreludeWithVersion -> String
showsPrec :: Int -> PreludeWithVersion -> ShowS
$cshowsPrec :: Int -> PreludeWithVersion -> ShowS
Show, forall x. Rep PreludeWithVersion x -> PreludeWithVersion
forall x. PreludeWithVersion -> Rep PreludeWithVersion x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PreludeWithVersion x -> PreludeWithVersion
$cfrom :: forall x. PreludeWithVersion -> Rep PreludeWithVersion x
Generic)
data HixComponent =
HixComponent {
HixComponent -> ComponentType
special :: ComponentType,
HixComponent -> [ExprAttr]
known :: [ExprAttr],
HixComponent -> Maybe PreludeWithVersion
prelude :: Maybe PreludeWithVersion
}
deriving stock (HixComponent -> HixComponent -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HixComponent -> HixComponent -> Bool
$c/= :: HixComponent -> HixComponent -> Bool
== :: HixComponent -> HixComponent -> Bool
$c== :: HixComponent -> HixComponent -> Bool
Eq, Int -> HixComponent -> ShowS
[HixComponent] -> ShowS
HixComponent -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HixComponent] -> ShowS
$cshowList :: [HixComponent] -> ShowS
show :: HixComponent -> String
$cshow :: HixComponent -> String
showsPrec :: Int -> HixComponent -> ShowS
$cshowsPrec :: Int -> HixComponent -> ShowS
Show, forall x. Rep HixComponent x -> HixComponent
forall x. HixComponent -> Rep HixComponent x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep HixComponent x -> HixComponent
$cfrom :: forall x. HixComponent -> Rep HixComponent x
Generic)
data HixPackage =
HixPackage {
HixPackage -> PackageName
name :: PackageName,
HixPackage -> Path Rel Dir
src :: Path Rel Dir,
HixPackage -> [ExprAttr]
known :: [ExprAttr],
HixPackage -> [ExprAttr]
meta :: [ExprAttr],
HixPackage -> ExprAttr
description :: ExprAttr,
HixPackage -> [HixComponent]
components :: [HixComponent]
}
deriving stock (HixPackage -> HixPackage -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HixPackage -> HixPackage -> Bool
$c/= :: HixPackage -> HixPackage -> Bool
== :: HixPackage -> HixPackage -> Bool
$c== :: HixPackage -> HixPackage -> Bool
Eq, Int -> HixPackage -> ShowS
[HixPackage] -> ShowS
HixPackage -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HixPackage] -> ShowS
$cshowList :: [HixPackage] -> ShowS
show :: HixPackage -> String
$cshow :: HixPackage -> String
showsPrec :: Int -> HixPackage -> ShowS
$cshowsPrec :: Int -> HixPackage -> ShowS
Show, forall x. Rep HixPackage x -> HixPackage
forall x. HixPackage -> Rep HixPackage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep HixPackage x -> HixPackage
$cfrom :: forall x. HixPackage -> Rep HixPackage x
Generic)
indent ::
Functor t =>
Int ->
t Text ->
t Text
indent :: forall (t :: * -> *). Functor t => Int -> t Text -> t Text
indent Int
n =
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> Text -> Text
Text.replicate Int
n Text
" " <>)
withSemicolon :: NonEmpty Text -> NonEmpty Text
withSemicolon :: NonEmpty Text -> NonEmpty Text
withSemicolon = \case
Text
e :| [] ->
[Text
e forall a. Semigroup a => a -> a -> a
<> Text
";"]
Text
h :| Text
h1 : [Text]
t -> Text
h forall a. a -> NonEmpty a -> NonEmpty a
<| NonEmpty Text -> NonEmpty Text
withSemicolon (Text
h1 forall a. a -> [a] -> NonEmpty a
:| [Text]
t)
renderAttrs :: Int -> [ExprAttr] -> [Text]
renderAttrs :: Int -> [ExprAttr] -> [Text]
renderAttrs Int
ind [ExprAttr]
attrs =
[ExprAttr]
attrs forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
ExprAttr Text
k Expr
v ->
case Int -> Expr -> NonEmpty Text
renderExpr Int
ind Expr
v of
Text
e :| [] -> [[exon|#{k} = #{e};|]]
Text
h :| (Text
h1 : [Text]
t) -> [exon|#{k} = #{h}|] forall a. a -> [a] -> [a]
: forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty Text -> NonEmpty Text
withSemicolon (Text
h1 forall a. a -> [a] -> NonEmpty a
:| [Text]
t))
ExprAttr
ExprAttrNil ->
[]
renderExpr :: Int -> Expr -> NonEmpty Text
renderExpr :: Int -> Expr -> NonEmpty Text
renderExpr Int
ind = \case
ExprString Text
s -> forall (t :: * -> *). Functor t => Int -> t Text -> t Text
indent Int
ind [[exon|"#{s}"|]]
ExprLit Text
e -> [Text
e]
ExprList [Expr]
l -> Text
"[" forall a. a -> [a] -> NonEmpty a
:| (forall (t :: * -> *). Functor t => Int -> t Text -> t Text
indent (Int
ind forall a. Num a => a -> a -> a
+ Int
2) (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> NonEmpty Text
renderExpr Int
ind forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [Expr]
l)) forall a. [a] -> [a] -> [a]
++ [Text
"]"]
ExprAttrs [ExprAttr]
a -> case Int -> [ExprAttr] -> [Text]
renderAttrs Int
ind [ExprAttr]
a of
[] -> [Text
"{};"]
[Text]
as -> Text
"{" forall a. a -> [a] -> NonEmpty a
:| forall (t :: * -> *). Functor t => Int -> t Text -> t Text
indent (Int
ind forall a. Num a => a -> a -> a
+ Int
2) [Text]
as forall a. [a] -> [a] -> [a]
++ [Text
"}"]
ExprPrefix Text
p (Int -> Expr -> NonEmpty Text
renderExpr Int
ind -> Text
h :| [Text]
t) ->
[exon|#{p} #{h}|] forall a. a -> [a] -> NonEmpty a
:| [Text]
t
renderRootExpr :: Expr -> Text
renderRootExpr :: Expr -> Text
renderRootExpr =
[Text] -> Text
Text.unlines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> [a]
toList forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> NonEmpty Text
renderExpr Int
0
readCabal ::
Path Abs Dir ->
Path Rel File ->
M CabalInfo
readCabal :: Path Abs Dir -> Path Rel File -> M CabalInfo
readCabal Path Abs Dir
root Path Rel File
path = do
GenericPackageDescription
info <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Verbosity -> String -> IO GenericPackageDescription
readGenericPackageDescription Verbosity
Cabal.verbose (forall b t. Path b t -> String
toFilePath (Path Abs Dir
root forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel File
path)))
pure CabalInfo {$sel:path:CabalInfo :: Path Rel Dir
path = Path Rel Dir
dir, GenericPackageDescription
info :: GenericPackageDescription
$sel:info:CabalInfo :: GenericPackageDescription
info}
where
dir :: Path Rel Dir
dir = forall b t. Path b t -> Path b Dir
parent Path Rel File
path
class RenderCabalOption a where
renderCabalOption :: a -> Text
instance {-# overlappable #-} Pretty a => RenderCabalOption a where
renderCabalOption :: a -> Text
renderCabalOption = forall b a. (Show a, IsString b) => a -> b
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Pretty a => a -> Doc
pretty
instance RenderCabalOption ShortText where
renderCabalOption :: ShortText -> Text
renderCabalOption = forall a. ToText a => a -> Text
toText forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortText -> String
fromShortText
instance RenderCabalOption String where
renderCabalOption :: String -> Text
renderCabalOption = forall a. ToText a => a -> Text
toText
checkEmpty ::
Text ->
Expr ->
ExprAttr
checkEmpty :: Text -> Expr -> ExprAttr
checkEmpty Text
key = \case
ExprString Text
value | Text -> Bool
Text.null Text
value ->
ExprAttr
ExprAttrNil
ExprList [Expr]
value | forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Expr]
value ->
ExprAttr
ExprAttrNil
Expr
value ->
Text -> Expr -> ExprAttr
ExprAttr Text
key Expr
value
singleOpt ::
RenderCabalOption a =>
Text ->
(e -> Maybe a) ->
e ->
ExprAttr
singleOpt :: forall a e.
RenderCabalOption a =>
Text -> (e -> Maybe a) -> e -> ExprAttr
singleOpt Text
key e -> Maybe a
get e
entity =
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ExprAttr
ExprAttrNil (Text -> Expr -> ExprAttr
checkEmpty Text
key forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Expr
ExprString) (forall a. RenderCabalOption a => a -> Text
renderCabalOption forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> e -> Maybe a
get e
entity)
single ::
RenderCabalOption a =>
Text ->
(e -> a) ->
e ->
ExprAttr
single :: forall a e.
RenderCabalOption a =>
Text -> (e -> a) -> e -> ExprAttr
single Text
key e -> a
get =
forall a e.
RenderCabalOption a =>
Text -> (e -> Maybe a) -> e -> ExprAttr
singleOpt Text
key (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> a
get)
multiOpt ::
RenderCabalOption a =>
Text ->
(e -> Maybe [a]) ->
e ->
ExprAttr
multiOpt :: forall a e.
RenderCabalOption a =>
Text -> (e -> Maybe [a]) -> e -> ExprAttr
multiOpt Text
key e -> Maybe [a]
get e
entity =
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ExprAttr
ExprAttrNil (Text -> Expr -> ExprAttr
checkEmpty Text
key forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Expr
exprStrings) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. RenderCabalOption a => a -> Text
renderCabalOption forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> e -> Maybe [a]
get e
entity)
multi ::
RenderCabalOption a =>
Text ->
(e -> [a]) ->
e ->
ExprAttr
multi :: forall a e.
RenderCabalOption a =>
Text -> (e -> [a]) -> e -> ExprAttr
multi Text
key e -> [a]
get =
forall a e.
RenderCabalOption a =>
Text -> (e -> Maybe [a]) -> e -> ExprAttr
multiOpt Text
key (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> [a]
get)
multiOrSingle ::
∀ a e .
RenderCabalOption a =>
Text ->
(e -> [a]) ->
e ->
ExprAttr
multiOrSingle :: forall a e.
RenderCabalOption a =>
Text -> (e -> [a]) -> e -> ExprAttr
multiOrSingle Text
key e -> [a]
get e
entity =
[Text] -> ExprAttr
check (forall a. RenderCabalOption a => a -> Text
renderCabalOption forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> e -> [a]
get e
entity)
where
check :: [Text] -> ExprAttr
check :: [Text] -> ExprAttr
check [] = ExprAttr
ExprAttrNil
check [Item [Text]
sing] = Text -> Expr -> ExprAttr
ExprAttr Text
key (Text -> Expr
ExprString Item [Text]
sing)
check [Text]
values = Text -> Expr -> ExprAttr
ExprAttr Text
key ([Text] -> Expr
exprStrings [Text]
values)
mkAttrs :: [e -> ExprAttr] -> e -> [ExprAttr]
mkAttrs :: forall e. [e -> ExprAttr] -> e -> [ExprAttr]
mkAttrs [e -> ExprAttr]
a e
e =
(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> a -> b
$ e
e) [e -> ExprAttr]
a)
knownPackageKeys :: PackageDescription -> [ExprAttr]
knownPackageKeys :: PackageDescription -> [ExprAttr]
knownPackageKeys =
forall e. [e -> ExprAttr] -> e -> [ExprAttr]
mkAttrs [
forall a e.
RenderCabalOption a =>
Text -> (e -> a) -> e -> ExprAttr
single Text
"author" (.author),
forall a e.
RenderCabalOption a =>
Text -> (e -> a) -> e -> ExprAttr
single Text
"build-type" PackageDescription -> BuildType
buildType,
forall a e.
RenderCabalOption a =>
Text -> (e -> a) -> e -> ExprAttr
single Text
"copyright" (.copyright),
forall a e.
RenderCabalOption a =>
Text -> (e -> a) -> e -> ExprAttr
single Text
"license" PackageDescription -> License
license,
forall a e.
RenderCabalOption a =>
Text -> (e -> Maybe a) -> e -> ExprAttr
singleOpt Text
"license-file" (forall a. [a] -> Maybe a
head forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageDescription -> [SymbolicPath PackageDir LicenseFile]
licenseFiles)
]
metaPackageKeys :: PackageDescription -> [ExprAttr]
metaPackageKeys :: PackageDescription -> [ExprAttr]
metaPackageKeys =
forall e. [e -> ExprAttr] -> e -> [ExprAttr]
mkAttrs [
forall a e.
RenderCabalOption a =>
Text -> (e -> a) -> e -> ExprAttr
single Text
"maintainer" (.maintainer),
forall a e.
RenderCabalOption a =>
Text -> (e -> a) -> e -> ExprAttr
single Text
"homepage" (.homepage),
forall a e.
RenderCabalOption a =>
Text -> (e -> a) -> e -> ExprAttr
single Text
"synopsis" (.synopsis)
]
ghcFlavour :: PerCompilerFlavor a -> a
ghcFlavour :: forall a. PerCompilerFlavor a -> a
ghcFlavour (PerCompilerFlavor a
a a
_) = a
a
notDefaultGhcOption :: String -> Bool
notDefaultGhcOption :: String -> Bool
notDefaultGhcOption = \case
String
"-threaded" -> Bool
False
String
"-rtsopts" -> Bool
False
String
"-with-rtsopts=-N" -> Bool
False
String
_ -> Bool
True
knownComponentKeys :: Maybe Prelude -> BuildInfo -> (Maybe PreludeWithVersion, [ExprAttr])
knownComponentKeys :: Maybe Prelude
-> BuildInfo -> (Maybe PreludeWithVersion, [ExprAttr])
knownComponentKeys Maybe Prelude
prelude BuildInfo
info =
(Maybe PreludeWithVersion
preludeWithVersion, [ExprAttr]
vals)
where
vals :: [ExprAttr]
vals =
forall e. [e -> ExprAttr] -> e -> [ExprAttr]
mkAttrs [
forall a e.
RenderCabalOption a =>
Text -> (e -> [a]) -> e -> ExprAttr
multi Text
"dependencies" (forall a b. a -> b -> a
const [Dependency]
deps),
forall a e.
RenderCabalOption a =>
Text -> (e -> [a]) -> e -> ExprAttr
multi Text
"default-extensions" (.defaultExtensions),
forall a e.
RenderCabalOption a =>
Text -> (e -> [a]) -> e -> ExprAttr
multiOrSingle Text
"source-dirs" (.hsSourceDirs),
forall a e.
RenderCabalOption a =>
Text -> (e -> Maybe a) -> e -> ExprAttr
singleOpt Text
"language" (.defaultLanguage),
forall a e.
RenderCabalOption a =>
Text -> (e -> [a]) -> e -> ExprAttr
multi Text
"ghc-options" (forall a. (a -> Bool) -> [a] -> [a]
filter String -> Bool
notDefaultGhcOption forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. PerCompilerFlavor a -> a
ghcFlavour forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.options))
] BuildInfo
info
(Maybe PreludeWithVersion
preludeWithVersion, [Dependency]
deps)
| Just Prelude
p <- Maybe Prelude
prelude =
let (Maybe Dependency
v, [Dependency]
res) = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (forall {r}.
HasField "preludePackage" r String =>
r
-> (Maybe Dependency, [Dependency])
-> Dependency
-> (Maybe Dependency, [Dependency])
amendPrelude Prelude
p) (forall a. Maybe a
Nothing, []) BuildInfo
info.targetBuildDepends
in (forall a. a -> Maybe a
Just (Prelude -> Maybe Dependency -> PreludeWithVersion
PreludeWithVersion Prelude
p Maybe Dependency
v), [Dependency]
res)
| Bool
otherwise =
(forall a. Maybe a
Nothing, forall a. (a -> Bool) -> [a] -> [a]
filter Dependency -> Bool
notBase (BuildInfo
info.targetBuildDepends))
amendPrelude :: r
-> (Maybe Dependency, [Dependency])
-> Dependency
-> (Maybe Dependency, [Dependency])
amendPrelude r
p (Maybe Dependency
Nothing, [Dependency]
ds) dep :: Dependency
dep@(Dependency (PackageName -> String
Cabal.unPackageName -> String
dname) VersionRange
_ NonEmptySet LibraryName
_) | String
dname forall a. Eq a => a -> a -> Bool
== r
p.preludePackage =
(forall a. a -> Maybe a
Just Dependency
dep, [Dependency]
ds)
amendPrelude r
_ (Maybe Dependency
v, [Dependency]
ds) Dependency
d = (Maybe Dependency
v, Dependency
d forall a. a -> [a] -> [a]
: [Dependency]
ds)
notBase :: Cabal.Dependency -> Bool
notBase :: Dependency -> Bool
notBase = \case
Cabal.Dependency PackageName
"base" VersionRange
_ NonEmptySet LibraryName
_ -> Bool
False
Dependency
_ -> Bool
True
convertComponent :: ComponentType -> BuildInfo -> HixComponent
convertComponent :: ComponentType -> BuildInfo -> HixComponent
convertComponent ComponentType
special BuildInfo
info =
HixComponent {[ExprAttr]
Maybe PreludeWithVersion
ComponentType
known :: [ExprAttr]
prelude :: Maybe PreludeWithVersion
special :: ComponentType
$sel:prelude:HixComponent :: Maybe PreludeWithVersion
$sel:known:HixComponent :: [ExprAttr]
$sel:special:HixComponent :: ComponentType
..}
where
(Maybe PreludeWithVersion
prelude, [ExprAttr]
known) = Maybe Prelude
-> BuildInfo -> (Maybe PreludeWithVersion, [ExprAttr])
knownComponentKeys Maybe Prelude
preludeBasic BuildInfo
info
preludeBasic :: Maybe Prelude
preludeBasic = [Mixin] -> Maybe Prelude
findPrelude BuildInfo
info.mixins
convertLibrary :: Cabal.Library -> HixComponent
convertLibrary :: Library -> HixComponent
convertLibrary Library
lib =
ComponentType -> BuildInfo -> HixComponent
convertComponent ComponentType
Library Library
lib.libBuildInfo
convertExecutable :: UnqualComponentName -> Cabal.Executable -> HixComponent
convertExecutable :: UnqualComponentName -> Executable -> HixComponent
convertExecutable UnqualComponentName
name Executable
exe =
ComponentType -> BuildInfo -> HixComponent
convertComponent (Text -> ComponentType
Executable (forall a. ToText a => a -> Text
toText (UnqualComponentName -> String
unUnqualComponentName UnqualComponentName
name))) Executable
exe.buildInfo
convertTestsuite :: UnqualComponentName -> Cabal.TestSuite -> HixComponent
convertTestsuite :: UnqualComponentName -> TestSuite -> HixComponent
convertTestsuite UnqualComponentName
name TestSuite
test =
ComponentType -> BuildInfo -> HixComponent
convertComponent (Text -> ComponentType
Test (forall a. ToText a => a -> Text
toText (UnqualComponentName -> String
unUnqualComponentName UnqualComponentName
name))) TestSuite
test.testBuildInfo
convertBenchmark :: UnqualComponentName -> Cabal.Benchmark -> HixComponent
convertBenchmark :: UnqualComponentName -> Benchmark -> HixComponent
convertBenchmark UnqualComponentName
name Benchmark
bench =
ComponentType -> BuildInfo -> HixComponent
convertComponent (Text -> ComponentType
Benchmark (forall a. ToText a => a -> Text
toText (UnqualComponentName -> String
unUnqualComponentName UnqualComponentName
name))) Benchmark
bench.benchmarkBuildInfo
convert :: CabalInfo -> HixPackage
convert :: CabalInfo -> HixPackage
convert CabalInfo
cinfo =
HixPackage {
$sel:name:HixPackage :: PackageName
name = Text -> PackageName
PackageName (forall a. ToText a => a -> Text
toText (PackageName -> String
unPackageName PackageDescription
pkg.package.pkgName)),
$sel:src:HixPackage :: Path Rel Dir
src = CabalInfo
cinfo.path,
$sel:known:HixPackage :: [ExprAttr]
known = PackageDescription -> [ExprAttr]
knownPackageKeys PackageDescription
pkg,
$sel:meta:HixPackage :: [ExprAttr]
meta = PackageDescription -> [ExprAttr]
metaPackageKeys PackageDescription
pkg,
$sel:description:HixPackage :: ExprAttr
description = forall a e.
RenderCabalOption a =>
Text -> (e -> a) -> e -> ExprAttr
single Text
"description" (.description) PackageDescription
pkg,
[HixComponent]
components :: [HixComponent]
$sel:components:HixPackage :: [HixComponent]
components
}
where
components :: [HixComponent]
components =
forall a. Maybe a -> [a]
maybeToList (Library -> HixComponent
convertLibrary forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.condTreeData) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericPackageDescription
info.condLibrary)
forall a. Semigroup a => a -> a -> a
<>
(forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry UnqualComponentName -> Executable -> HixComponent
convertExecutable forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (.condTreeData) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericPackageDescription
info.condExecutables)
forall a. Semigroup a => a -> a -> a
<>
(forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry UnqualComponentName -> TestSuite -> HixComponent
convertTestsuite forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (.condTreeData) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericPackageDescription
info.condTestSuites)
forall a. Semigroup a => a -> a -> a
<>
(forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry UnqualComponentName -> Benchmark -> HixComponent
convertBenchmark forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (.condTreeData) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericPackageDescription
info.condBenchmarks)
pkg :: PackageDescription
pkg = GenericPackageDescription
info.packageDescription
info :: GenericPackageDescription
info = CabalInfo
cinfo.info
renderComponent :: HixComponent -> ExprAttr
renderComponent :: HixComponent -> ExprAttr
renderComponent HixComponent {[ExprAttr]
Maybe PreludeWithVersion
ComponentType
prelude :: Maybe PreludeWithVersion
known :: [ExprAttr]
special :: ComponentType
$sel:prelude:HixComponent :: HixComponent -> Maybe PreludeWithVersion
$sel:known:HixComponent :: HixComponent -> [ExprAttr]
$sel:special:HixComponent :: HixComponent -> ComponentType
..} =
Text -> Expr -> ExprAttr
ExprAttr Text
key Expr
cabalConfig
where
cabalConfig :: Expr
cabalConfig = [ExprAttr] -> Expr
ExprAttrs ([ExprAttr]
known forall a. Semigroup a => a -> a -> a
<> forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap forall {l} {a} {a} {r} {r}.
(Item l ~ ExprAttr, ToText a, ToText a, IsList l,
HasField "prelude" r r, HasField "preludePackage" r a,
HasField "preludeModule" r a,
HasField "dep" r (Maybe Dependency)) =>
r -> l
preludeAttrs Maybe PreludeWithVersion
prelude)
preludeAttrs :: r -> l
preludeAttrs r
p =
[Text -> Expr -> ExprAttr
ExprAttr Text
"prelude" ([ExprAttr] -> Expr
ExprAttrs [
Text -> Expr -> ExprAttr
ExprAttr Text
"package" (forall {r} {r} {a}.
(HasField "prelude" r r, HasField "preludePackage" r a,
HasField "dep" r (Maybe Dependency), ToText a) =>
r -> Expr
preludePackageAttrs r
p),
Text -> Expr -> ExprAttr
ExprAttr Text
"module" (Text -> Expr
ExprString (forall a. ToText a => a -> Text
toText r
p.prelude.preludeModule))
])]
preludePackageAttrs :: r -> Expr
preludePackageAttrs r
p
| Just Dependency
dep <- r
p.dep =
[ExprAttr] -> Expr
ExprAttrs [
(Text -> Expr -> ExprAttr
ExprAttr Text
"name" (Text -> Expr
ExprString (forall a. ToText a => a -> Text
toText r
p.prelude.preludePackage))),
(Text -> Expr -> ExprAttr
ExprAttr Text
"version" (Text -> Expr
ExprString (forall b a. (Show a, IsString b) => a -> b
show (forall a. Pretty a => a -> Doc
pretty (Dependency -> VersionRange
depVerRange Dependency
dep)))))
]
| Bool
otherwise = Text -> Expr
ExprString (forall a. ToText a => a -> Text
toText r
p.prelude.preludePackage)
key :: Text
key = case ComponentType
special of
ComponentType
Library -> Text
"library"
Executable Text
name -> [exon|executables.#{name}|]
Test Text
name -> [exon|tests.#{name}|]
Benchmark Text
name -> [exon|benchmarks.#{name}|]
flakePackage :: HixPackage -> ExprAttr
flakePackage :: HixPackage -> ExprAttr
flakePackage HixPackage
pkg =
Text -> Expr -> ExprAttr
ExprAttr Text
name Expr
attrs
where
attrs :: Expr
attrs = [ExprAttr] -> Expr
ExprAttrs (ExprAttr
src forall a. a -> [a] -> [a]
: HixPackage
pkg.description forall a. a -> [a] -> [a]
: (Text -> Expr -> ExprAttr
ExprAttr Text
"cabal" Expr
cabalConfig forall a. a -> [a] -> [a]
: [ExprAttr]
comps))
name :: Text
name = HixPackage
pkg.name.unPackageName
src :: ExprAttr
src = Text -> Expr -> ExprAttr
ExprAttr Text
"src" (Text -> Expr
ExprLit [exon|./#{Text.dropWhileEnd ('/' ==) (pathText pkg.src)}|])
cabalConfig :: Expr
cabalConfig = [ExprAttr] -> Expr
ExprAttrs (HixPackage
pkg.known forall a. Semigroup a => a -> a -> a
<> (if forall (t :: * -> *) a. Foldable t => t a -> Bool
null HixPackage
pkg.meta then [] else [Text -> Expr -> ExprAttr
ExprAttr Text
"meta" ([ExprAttr] -> Expr
ExprAttrs HixPackage
pkg.meta)]))
comps :: [ExprAttr]
comps = HixComponent -> ExprAttr
renderComponent forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HixPackage
pkg.components
mainPackage :: [HixPackage] -> ExprAttr
mainPackage :: [HixPackage] -> ExprAttr
mainPackage = \case
HixPackage
pkg : HixPackage
_ : [HixPackage]
_ -> Text -> Expr -> ExprAttr
ExprAttr Text
"main" (Text -> Expr
ExprString HixPackage
pkg.name.unPackageName)
[HixPackage]
_ -> ExprAttr
ExprAttrNil
flake :: BootstrapProjectConfig -> [HixPackage] -> Expr
flake :: BootstrapProjectConfig -> [HixPackage] -> Expr
flake BootstrapProjectConfig
conf [HixPackage]
pkgs =
[ExprAttr] -> Expr
ExprAttrs [
(Text -> Expr -> ExprAttr
ExprAttr Text
"description" (Text -> Expr
ExprString Text
"A Haskell project")),
(Text -> Expr -> ExprAttr
ExprAttr Text
"inputs.hix.url" (Text -> Expr
ExprString BootstrapProjectConfig
conf.hixUrl.unHixUrl)),
(Text -> Expr -> ExprAttr
ExprAttr Text
"outputs" (Text -> Expr -> Expr
ExprPrefix Text
"{hix, ...}: hix.lib.flake" ([ExprAttr] -> Expr
ExprAttrs [
(Text -> Expr -> ExprAttr
ExprAttr Text
"packages" ([ExprAttr] -> Expr
ExprAttrs (HixPackage -> ExprAttr
flakePackage forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [HixPackage]
pkgs))),
[HixPackage] -> ExprAttr
mainPackage [HixPackage]
pkgs
])))
]
bootstrapFiles :: BootstrapProjectConfig -> M [ProjectFile]
bootstrapFiles :: BootstrapProjectConfig -> M [ProjectFile]
bootstrapFiles BootstrapProjectConfig
conf = do
Env {Path Abs Dir
$sel:root:Env :: Env -> Path Abs Dir
root :: Path Abs Dir
root} <- forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
[Path Rel File]
cabals <- [String] -> ReaderT Env (ExceptT Error IO) [Path Rel File]
paths forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (forall a. IO a -> ExceptT Error IO a
tryIO (String -> [String] -> [String] -> IO [String]
getDirectoryFilesIgnore (forall b t. Path b t -> String
toFilePath Path Abs Dir
root) [String
"**/*.cabal"] [String
"dist-newstyle/**"]))
[HixPackage]
pkgs <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CabalInfo -> HixPackage
convert forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Path Abs Dir -> Path Rel File -> M CabalInfo
readCabal Path Abs Dir
root) [Path Rel File]
cabals
pure [
ProjectFile {$sel:path:ProjectFile :: Path Rel File
path = [relfile|flake.nix|], $sel:content:ProjectFile :: Text
content = Expr -> Text
renderRootExpr (BootstrapProjectConfig -> [HixPackage] -> Expr
flake BootstrapProjectConfig
conf [HixPackage]
pkgs)}
]
where
paths :: [String] -> ReaderT Env (ExceptT Error IO) [Path Rel File]
paths = forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (forall a. Text -> Maybe a -> M a
noteBootstrap Text
"File path error" forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *). MonadThrow m => String -> m (Path Rel File)
parseRelFile)
bootstrapProject :: BootstrapProjectConfig -> M ()
bootstrapProject :: BootstrapProjectConfig -> M ()
bootstrapProject BootstrapProjectConfig
conf =
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ ProjectFile -> M ()
createFile forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< BootstrapProjectConfig -> M [ProjectFile]
bootstrapFiles BootstrapProjectConfig
conf