hix 0.6.9 → 0.7.0
raw patch · 185 files changed
+12463/−586 lines, 185 filesdep +bytestringdep +cabal-installdep +cabal-install-solverdep ~hedgehogdep ~optparse-applicativePVP ok
version bump matches the API change (PVP)
Dependencies added: bytestring, cabal-install, cabal-install-solver, containers, exceptions, generics-sop, http-client, http-client-tls, http-types, pretty, these, time, typed-process
Dependency ranges changed: hedgehog, optparse-applicative
API changes (from Hackage documentation)
- Hix.Bootstrap: ExprAttr :: Text -> Expr -> ExprAttr
- Hix.Bootstrap: ExprAttrNil :: ExprAttr
- Hix.Bootstrap: ExprAttrs :: [ExprAttr] -> Expr
- Hix.Bootstrap: ExprList :: [Expr] -> Expr
- Hix.Bootstrap: ExprLit :: Text -> Expr
- Hix.Bootstrap: ExprPrefix :: Text -> Expr -> Expr
- Hix.Bootstrap: ExprString :: Text -> Expr
- Hix.Bootstrap: [$sel:name:ExprAttr] :: ExprAttr -> Text
- Hix.Bootstrap: [$sel:value:ExprAttr] :: ExprAttr -> Expr
- Hix.Bootstrap: checkEmpty :: Text -> Expr -> ExprAttr
- Hix.Bootstrap: class RenderCabalOption a
- Hix.Bootstrap: data Expr
- Hix.Bootstrap: data ExprAttr
- Hix.Bootstrap: exprStrings :: [Text] -> Expr
- Hix.Bootstrap: indent :: Functor t => Int -> t Text -> t Text
- Hix.Bootstrap: instance Distribution.Pretty.Pretty a => Hix.Bootstrap.RenderCabalOption a
- Hix.Bootstrap: instance GHC.Classes.Eq Hix.Bootstrap.Expr
- Hix.Bootstrap: instance GHC.Classes.Eq Hix.Bootstrap.ExprAttr
- Hix.Bootstrap: instance GHC.Generics.Generic Hix.Bootstrap.Expr
- Hix.Bootstrap: instance GHC.Generics.Generic Hix.Bootstrap.ExprAttr
- Hix.Bootstrap: instance GHC.Show.Show Hix.Bootstrap.Expr
- Hix.Bootstrap: instance GHC.Show.Show Hix.Bootstrap.ExprAttr
- Hix.Bootstrap: instance Hix.Bootstrap.RenderCabalOption Distribution.Utils.ShortText.ShortText
- Hix.Bootstrap: instance Hix.Bootstrap.RenderCabalOption GHC.Base.String
- Hix.Bootstrap: mkAttrs :: [e -> ExprAttr] -> e -> [ExprAttr]
- Hix.Bootstrap: multi :: RenderCabalOption a => Text -> (e -> [a]) -> e -> ExprAttr
- Hix.Bootstrap: multiOpt :: RenderCabalOption a => Text -> (e -> Maybe [a]) -> e -> ExprAttr
- Hix.Bootstrap: multiOrSingle :: forall a e. RenderCabalOption a => Text -> (e -> [a]) -> e -> ExprAttr
- Hix.Bootstrap: nonEmptyAttrs :: Text -> [ExprAttr] -> ExprAttr
- Hix.Bootstrap: notNil :: ExprAttr -> Bool
- Hix.Bootstrap: renderAttrs :: Int -> [ExprAttr] -> [Text]
- Hix.Bootstrap: renderCabalOption :: RenderCabalOption a => a -> Text
- Hix.Bootstrap: renderExpr :: Int -> Expr -> NonEmpty Text
- Hix.Bootstrap: renderRootExpr :: Expr -> Text
- Hix.Bootstrap: single :: RenderCabalOption a => Text -> (e -> a) -> e -> ExprAttr
- Hix.Bootstrap: singleOpt :: RenderCabalOption a => Text -> (e -> Maybe a) -> e -> ExprAttr
- Hix.Bootstrap: withSemicolon :: NonEmpty Text -> NonEmpty Text
- Hix.Data.ComponentConfig: EnvName :: Text -> EnvName
- Hix.Data.ComponentConfig: PackageName :: Text -> PackageName
- Hix.Data.ComponentConfig: [$sel:unEnvName:EnvName] :: EnvName -> Text
- Hix.Data.ComponentConfig: [$sel:unPackageName:PackageName] :: PackageName -> Text
- Hix.Data.ComponentConfig: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.ComponentConfig.EnvName
- Hix.Data.ComponentConfig: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.ComponentConfig.PackageName
- Hix.Data.ComponentConfig: instance Data.Aeson.Types.FromJSON.FromJSONKey Hix.Data.ComponentConfig.EnvName
- Hix.Data.ComponentConfig: instance Data.Aeson.Types.FromJSON.FromJSONKey Hix.Data.ComponentConfig.PackageName
- Hix.Data.ComponentConfig: instance Data.String.IsString Hix.Data.ComponentConfig.EnvName
- Hix.Data.ComponentConfig: instance Data.String.IsString Hix.Data.ComponentConfig.PackageName
- Hix.Data.ComponentConfig: instance GHC.Classes.Eq Hix.Data.ComponentConfig.EnvName
- Hix.Data.ComponentConfig: instance GHC.Classes.Eq Hix.Data.ComponentConfig.PackageName
- Hix.Data.ComponentConfig: instance GHC.Classes.Ord Hix.Data.ComponentConfig.EnvName
- Hix.Data.ComponentConfig: instance GHC.Classes.Ord Hix.Data.ComponentConfig.PackageName
- Hix.Data.ComponentConfig: instance GHC.Generics.Generic Hix.Data.ComponentConfig.EnvName
- Hix.Data.ComponentConfig: instance GHC.Generics.Generic Hix.Data.ComponentConfig.PackageName
- Hix.Data.ComponentConfig: instance GHC.Show.Show Hix.Data.ComponentConfig.EnvName
- Hix.Data.ComponentConfig: instance GHC.Show.Show Hix.Data.ComponentConfig.PackageName
- Hix.Data.ComponentConfig: newtype EnvName
- Hix.Data.ComponentConfig: newtype PackageName
- Hix.Data.Error: note :: Text -> Maybe a -> ExceptT Error IO a
- Hix.Data.Error: pathText :: Path b t -> Text
- Hix.Data.Error: printBootstrapError :: MonadIO m => Text -> m ()
- Hix.Data.Error: printEnvError :: MonadIO m => Text -> m ()
- Hix.Data.Error: printFatalError :: MonadIO m => Text -> m ()
- Hix.Data.Error: printGhciError :: MonadIO m => Text -> m ()
- Hix.Data.Error: printNewError :: MonadIO m => Text -> m ()
- Hix.Data.Error: printPreprocError :: MonadIO m => Text -> m ()
- Hix.Data.Error: sourceError :: Text -> Path b t -> Text
- Hix.Data.Error: tryIO :: IO a -> ExceptT Error IO a
- Hix.Monad: Env :: Path Abs Dir -> Env
- Hix.Monad: [$sel:cwd:Env] :: Env -> Path Abs Dir
- Hix.Monad: data Env
- Hix.Monad: instance GHC.Classes.Eq Hix.Monad.Env
- Hix.Monad: instance GHC.Generics.Generic Hix.Monad.Env
- Hix.Monad: instance GHC.Show.Show Hix.Monad.Env
- Hix.Monad: type M a = ReaderT Env (ExceptT Error IO) a
- Hix.Options: BootstrapCmd :: BootstrapOptions -> Command
- Hix.Options: BootstrapOptions :: BootstrapProjectConfig -> BootstrapOptions
- Hix.Options: ComponentCoords :: Maybe PackageSpec -> Maybe ComponentSpec -> ComponentCoords
- Hix.Options: ComponentSpec :: ComponentName -> Maybe SourceDir -> ComponentSpec
- Hix.Options: EnvRunner :: EnvRunnerCommandOptions -> Command
- Hix.Options: EnvRunnerCommandOptions :: EnvRunnerOptions -> TestOptions -> Maybe ExtraGhciOptions -> Maybe ExtraGhcidOptions -> EnvRunnerCommandOptions
- Hix.Options: EnvRunnerOptions :: Either EnvConfig JsonConfig -> Maybe (Path Abs Dir) -> Maybe TargetSpec -> EnvRunnerOptions
- Hix.Options: ExtraGhciOptions :: Text -> ExtraGhciOptions
- Hix.Options: ExtraGhcidOptions :: Text -> ExtraGhcidOptions
- Hix.Options: GhciCmd :: GhciOptions -> Command
- Hix.Options: GhciOptions :: Either GhciConfig JsonConfig -> Maybe (Path Abs Dir) -> TargetSpec -> TestOptions -> Maybe ExtraGhciOptions -> GhciOptions
- Hix.Options: GhcidCmd :: GhcidOptions -> Command
- Hix.Options: GhcidOptions :: GhciOptions -> Maybe ExtraGhcidOptions -> GhcidOptions
- Hix.Options: GlobalOptions :: Maybe Bool -> Path Abs Dir -> GlobalOptions
- Hix.Options: NewCmd :: NewOptions -> Command
- Hix.Options: NewOptions :: NewProjectConfig -> NewOptions
- Hix.Options: Options :: GlobalOptions -> Command -> Options
- Hix.Options: PackageSpec :: PackageName -> Maybe (SomeBase Dir) -> PackageSpec
- Hix.Options: Preproc :: PreprocOptions -> Command
- Hix.Options: PreprocOptions :: Maybe (Either PreprocConfig JsonConfig) -> Maybe (Path Abs Dir) -> Path Abs File -> Path Abs File -> Path Abs File -> PreprocOptions
- Hix.Options: TargetForComponent :: ComponentCoords -> TargetSpec
- Hix.Options: TargetForFile :: Path Abs File -> TargetSpec
- Hix.Options: TestOptions :: ModuleName -> Maybe Text -> Maybe RunnerName -> ChangeDir -> TestOptions
- Hix.Options: [$sel:cd:TestOptions] :: TestOptions -> ChangeDir
- Hix.Options: [$sel:cmd:Options] :: Options -> Command
- Hix.Options: [$sel:component:ComponentCoords] :: ComponentCoords -> Maybe ComponentSpec
- Hix.Options: [$sel:component:EnvRunnerOptions] :: EnvRunnerOptions -> Maybe TargetSpec
- Hix.Options: [$sel:component:GhciOptions] :: GhciOptions -> TargetSpec
- Hix.Options: [$sel:config:BootstrapOptions] :: BootstrapOptions -> BootstrapProjectConfig
- Hix.Options: [$sel:config:EnvRunnerOptions] :: EnvRunnerOptions -> Either EnvConfig JsonConfig
- Hix.Options: [$sel:config:GhciOptions] :: GhciOptions -> Either GhciConfig JsonConfig
- Hix.Options: [$sel:config:NewOptions] :: NewOptions -> NewProjectConfig
- Hix.Options: [$sel:config:PreprocOptions] :: PreprocOptions -> Maybe (Either PreprocConfig JsonConfig)
- Hix.Options: [$sel:cwd:GlobalOptions] :: GlobalOptions -> Path Abs Dir
- Hix.Options: [$sel:dir:ComponentSpec] :: ComponentSpec -> Maybe SourceDir
- Hix.Options: [$sel:dir:PackageSpec] :: PackageSpec -> Maybe (SomeBase Dir)
- Hix.Options: [$sel:extra:GhciOptions] :: GhciOptions -> Maybe ExtraGhciOptions
- Hix.Options: [$sel:extra:GhcidOptions] :: GhcidOptions -> Maybe ExtraGhcidOptions
- Hix.Options: [$sel:extraGhci:EnvRunnerCommandOptions] :: EnvRunnerCommandOptions -> Maybe ExtraGhciOptions
- Hix.Options: [$sel:extraGhcid:EnvRunnerCommandOptions] :: EnvRunnerCommandOptions -> Maybe ExtraGhcidOptions
- Hix.Options: [$sel:ghci:GhcidOptions] :: GhcidOptions -> GhciOptions
- Hix.Options: [$sel:global:Options] :: Options -> GlobalOptions
- Hix.Options: [$sel:inFile:PreprocOptions] :: PreprocOptions -> Path Abs File
- Hix.Options: [$sel:mod:TestOptions] :: TestOptions -> ModuleName
- Hix.Options: [$sel:name:ComponentSpec] :: ComponentSpec -> ComponentName
- Hix.Options: [$sel:name:PackageSpec] :: PackageSpec -> PackageName
- Hix.Options: [$sel:options:EnvRunnerCommandOptions] :: EnvRunnerCommandOptions -> EnvRunnerOptions
- Hix.Options: [$sel:outFile:PreprocOptions] :: PreprocOptions -> Path Abs File
- Hix.Options: [$sel:package:ComponentCoords] :: ComponentCoords -> Maybe PackageSpec
- Hix.Options: [$sel:root:EnvRunnerOptions] :: EnvRunnerOptions -> Maybe (Path Abs Dir)
- Hix.Options: [$sel:root:GhciOptions] :: GhciOptions -> Maybe (Path Abs Dir)
- Hix.Options: [$sel:root:PreprocOptions] :: PreprocOptions -> Maybe (Path Abs Dir)
- Hix.Options: [$sel:runner:TestOptions] :: TestOptions -> Maybe RunnerName
- Hix.Options: [$sel:source:PreprocOptions] :: PreprocOptions -> Path Abs File
- Hix.Options: [$sel:test:EnvRunnerCommandOptions] :: EnvRunnerCommandOptions -> TestOptions
- Hix.Options: [$sel:test:GhciOptions] :: GhciOptions -> TestOptions
- Hix.Options: [$sel:test:TestOptions] :: TestOptions -> Maybe Text
- Hix.Options: [$sel:verbose:GlobalOptions] :: GlobalOptions -> Maybe Bool
- Hix.Options: data BootstrapOptions
- Hix.Options: data Command
- Hix.Options: data ComponentCoords
- Hix.Options: data ComponentSpec
- Hix.Options: data EnvRunnerCommandOptions
- Hix.Options: data EnvRunnerOptions
- Hix.Options: data GhciOptions
- Hix.Options: data GhcidOptions
- Hix.Options: data GlobalOptions
- Hix.Options: data NewOptions
- Hix.Options: data Options
- Hix.Options: data PackageSpec
- Hix.Options: data PreprocOptions
- Hix.Options: data TargetSpec
- Hix.Options: data TestOptions
- Hix.Options: instance Data.String.IsString Hix.Options.ExtraGhciOptions
- Hix.Options: instance Data.String.IsString Hix.Options.ExtraGhcidOptions
- Hix.Options: instance GHC.Classes.Eq Hix.Options.BootstrapOptions
- Hix.Options: instance GHC.Classes.Eq Hix.Options.ComponentCoords
- Hix.Options: instance GHC.Classes.Eq Hix.Options.ComponentSpec
- Hix.Options: instance GHC.Classes.Eq Hix.Options.ExtraGhciOptions
- Hix.Options: instance GHC.Classes.Eq Hix.Options.ExtraGhcidOptions
- Hix.Options: instance GHC.Classes.Eq Hix.Options.GlobalOptions
- Hix.Options: instance GHC.Classes.Eq Hix.Options.NewOptions
- Hix.Options: instance GHC.Classes.Eq Hix.Options.PackageSpec
- Hix.Options: instance GHC.Classes.Eq Hix.Options.TargetSpec
- Hix.Options: instance GHC.Classes.Eq Hix.Options.TestOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.BootstrapOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.ComponentCoords
- Hix.Options: instance GHC.Generics.Generic Hix.Options.ComponentSpec
- Hix.Options: instance GHC.Generics.Generic Hix.Options.EnvRunnerCommandOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.EnvRunnerOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.ExtraGhciOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.ExtraGhcidOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.GhciOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.GhcidOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.GlobalOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.NewOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.PackageSpec
- Hix.Options: instance GHC.Generics.Generic Hix.Options.PreprocOptions
- Hix.Options: instance GHC.Generics.Generic Hix.Options.TargetSpec
- Hix.Options: instance GHC.Generics.Generic Hix.Options.TestOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.BootstrapOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.Command
- Hix.Options: instance GHC.Show.Show Hix.Options.ComponentCoords
- Hix.Options: instance GHC.Show.Show Hix.Options.ComponentSpec
- Hix.Options: instance GHC.Show.Show Hix.Options.EnvRunnerCommandOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.EnvRunnerOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.ExtraGhciOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.ExtraGhcidOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.GhciOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.GhcidOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.GlobalOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.NewOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.Options
- Hix.Options: instance GHC.Show.Show Hix.Options.PackageSpec
- Hix.Options: instance GHC.Show.Show Hix.Options.PreprocOptions
- Hix.Options: instance GHC.Show.Show Hix.Options.TargetSpec
- Hix.Options: instance GHC.Show.Show Hix.Options.TestOptions
- Hix.Options: newtype ExtraGhciOptions
- Hix.Options: newtype ExtraGhcidOptions
+ Hix.CabalParsec: eitherParsecFor :: Parsec b => ToString a => String -> a -> Either String b
+ Hix.CabalParsec: parsecM :: Parsec b => ToString a => String -> a -> M b
+ Hix.CabalParsec: unsafeParsec :: forall a b. Parsec b => Typeable b => ToString a => a -> b
+ Hix.CabalParsec: unsafeParsecFor :: Parsec b => ToString a => String -> a -> b
+ Hix.Class.EncodeNix: class EncodeField field
+ Hix.Class.EncodeNix: class EncodeNix a
+ Hix.Class.EncodeNix: class EncodeNixKey a
+ Hix.Class.EncodeNix: class EncodeProd a
+ Hix.Class.EncodeNix: encodeField :: EncodeField field => Field field -> ExprAttr
+ Hix.Class.EncodeNix: encodeNix :: (EncodeNix a, EncodeProd a) => a -> Expr
+ Hix.Class.EncodeNix: encodeNixKey :: EncodeNixKey a => a -> Text
+ Hix.Class.EncodeNix: encodeProd :: EncodeProd a => a -> Expr
+ Hix.Class.EncodeNix: instance (GHC.TypeLits.KnownSymbol name, Hix.Class.EncodeNix.EncodeNix a) => Hix.Class.EncodeNix.EncodeField ('Hix.Class.SOP.FieldK name a)
+ Hix.Class.EncodeNix: instance (Hix.Class.EncodeNix.EncodeNixKey k, Hix.Class.EncodeNix.EncodeNix v) => Hix.Class.EncodeNix.EncodeNix (Data.Map.Internal.Map k v)
+ Hix.Class.EncodeNix: instance (Hix.Class.SOP.ToFields a fields, Data.SOP.Constraint.All2 Hix.Class.EncodeNix.EncodeField fields, Data.SOP.Constraint.SListI2 fields) => Hix.Class.EncodeNix.EncodeProd a
+ Hix.Class.EncodeNix: instance Distribution.Pretty.Pretty a => Hix.Class.EncodeNix.EncodeNix (Hix.Data.NixExpr.ViaPretty a)
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix Data.Text.Internal.Text
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix Distribution.Types.Version.Version
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix Distribution.Types.VersionRange.Internal.VersionRange
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix Distribution.Utils.ShortText.ShortText
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix GHC.Types.Bool
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix GHC.Types.Int
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix Hix.Data.NixExpr.Expr
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix Text.PrettyPrint.HughesPJ.Doc
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix a => Hix.Class.EncodeNix.EncodeNix (GHC.Base.NonEmpty a)
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix a => Hix.Class.EncodeNix.EncodeNix (GHC.Maybe.Maybe a)
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNix a => Hix.Class.EncodeNix.EncodeNix [a]
+ Hix.Class.EncodeNix: instance Hix.Class.EncodeNix.EncodeNixKey Data.Text.Internal.Text
+ Hix.Class.Map: (!!) :: forall map k v sort l. NMap map k v sort => NLookup sort k v l => map -> k -> l
+ Hix.Class.Map: (!?) :: forall map k v sort. NMap map k v sort => map -> k -> Maybe v
+ Hix.Class.Map: class NLookup sort k v l | sort v -> l
+ Hix.Class.Map: class (Ord k, Coercible map (Map k v)) => NMap map k v sort | map -> k v sort
+ Hix.Class.Map: data LookupFatal
+ Hix.Class.Map: data LookupMaybe
+ Hix.Class.Map: data LookupMonoid
+ Hix.Class.Map: infixl 9 !!
+ Hix.Class.Map: instance GHC.Base.Monoid v => Hix.Class.Map.NLookup Hix.Class.Map.LookupMonoid k v v
+ Hix.Class.Map: instance GHC.Show.Show k => Hix.Class.Map.NLookup Hix.Class.Map.LookupFatal k v (Data.Text.Internal.Text -> Hix.Data.Monad.M v)
+ Hix.Class.Map: instance Hix.Class.Map.NLookup Hix.Class.Map.LookupMaybe k v (GHC.Maybe.Maybe v)
+ Hix.Class.Map: lookupError :: forall k v. Show k => Text -> k -> Maybe v -> M v
+ Hix.Class.Map: nAdjust :: forall map k v sort. NMap map k v sort => k -> map -> (v -> v) -> map
+ Hix.Class.Map: nAmend :: forall map1 map2 k v1 v2 s1 s2. NMap map1 k v1 s1 => NMap map2 k v2 s2 => (v1 -> v2 -> v2) -> map1 -> map2 -> map2
+ Hix.Class.Map: nAmend1 :: forall map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2'. NMap map1 k map1' s1 => NMap map2 k map2' s2 => NMap map1' k' v1 s1' => NMap map2' k' v2 s2' => (v1 -> v2 -> v2) -> map1 -> map2 -> map2
+ Hix.Class.Map: nAmendWithKey :: forall map1 map2 k v1 v2 s1 s2. NMap map1 k v1 s1 => NMap map2 k v2 s2 => (k -> v1 -> v2 -> v2) -> map1 -> map2 -> map2
+ Hix.Class.Map: nBy :: Foldable t => NMap map k v sort => t v -> (v -> k) -> map
+ Hix.Class.Map: nCatMaybes :: NMap map1 k (Maybe v) sort1 => NMap map2 k v sort2 => map1 -> map2
+ Hix.Class.Map: nConcat :: Monoid a => NMap map k v sort => map -> (k -> v -> a) -> a
+ Hix.Class.Map: nConcatWith :: Monoid a => NMap map k v sort => (k -> v -> a) -> map -> a
+ Hix.Class.Map: nElems :: forall map k v s. NMap map k v s => map -> [v]
+ Hix.Class.Map: nElems1 :: forall map1 map2 k1 k2 v s1 s2. NMap map1 k1 map2 s1 => NMap map2 k2 v s2 => map1 -> [v]
+ Hix.Class.Map: nFatal :: forall map k v sort. Show k => NMap map k v sort => Text -> k -> map -> M v
+ Hix.Class.Map: nFilter :: forall map k v sort. NMap map k v sort => (v -> Bool) -> map -> map
+ Hix.Class.Map: nFilter1 :: forall map map' k k' v s s'. NMap map k map' s => NMap map' k' v s' => (v -> Bool) -> map -> map
+ Hix.Class.Map: nFlatten :: forall map1 map2 map3 k1 k2 v1 v2 s1 s2. Monoid map2 => NMap map1 k1 map2 LookupMonoid => NMap map2 k2 v1 s1 => NMap map3 k2 v2 s2 => (v1 -> v2) -> map1 -> map3
+ Hix.Class.Map: nFor :: Applicative m => NMap map k v sort => [v] -> (v -> m k) -> m map
+ Hix.Class.Map: nForKeys :: Applicative m => NMap map k v sort => [k] -> (k -> m v) -> m map
+ Hix.Class.Map: nFromKeys :: Foldable t => NMap map k v sort => t k -> (k -> v) -> map
+ Hix.Class.Map: nFromKeysMaybe :: Foldable t => NMap map k v sort => t k -> (k -> Maybe v) -> map
+ Hix.Class.Map: nFromList :: NMap map k v sort => [(k, v)] -> map
+ Hix.Class.Map: nGen :: Foldable t => NMap map k v sort => t a -> (a -> (k, v)) -> map
+ Hix.Class.Map: nGenMaybe :: Foldable t => NMap map k v sort => t a -> (a -> Maybe (k, v)) -> map
+ Hix.Class.Map: nGenWith :: Foldable t => NMap map k v sort => (a -> (k, v)) -> t a -> map
+ Hix.Class.Map: nGet :: NMap map k v sort => map -> Map k v
+ Hix.Class.Map: nInsert :: forall map k v sort. NMap map k v sort => k -> v -> map -> map
+ Hix.Class.Map: nKeys :: NMap map k v sort => map -> [k]
+ Hix.Class.Map: nKeysSet :: NMap map k v sort => map -> Set k
+ Hix.Class.Map: nList :: NMap map k v sort => map -> [(k, v)]
+ Hix.Class.Map: nLookup :: NLookup sort k v l => k -> Maybe v -> l
+ Hix.Class.Map: nMap :: NMap map1 k v1 sort1 => NMap map2 k v2 sort2 => (v1 -> v2) -> map1 -> map2
+ Hix.Class.Map: nMap1 :: forall map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2'. NMap map1 k map1' s1 => NMap map2 k map2' s2 => NMap map1' k' v1 s1' => NMap map2' k' v2 s2' => (v1 -> v2) -> map1 -> map2
+ Hix.Class.Map: nMapKeys :: NMap map1 k1 v sort1 => NMap map2 k2 v sort2 => (k1 -> k2) -> map1 -> map2
+ Hix.Class.Map: nMapMaybe :: NMap map1 k v1 sort1 => NMap map2 k v2 sort2 => (v1 -> Maybe v2) -> map1 -> map2
+ Hix.Class.Map: nMapMaybe1 :: forall map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2'. NMap map1 k map1' s1 => NMap map2 k map2' s2 => NMap map1' k' v1 s1' => NMap map2' k' v2 s2' => (v1 -> Maybe v2) -> map1 -> map2
+ Hix.Class.Map: nMapMaybeWithKey :: NMap map1 k v1 sort1 => NMap map2 k v2 sort2 => (k -> v1 -> Maybe v2) -> map1 -> map2
+ Hix.Class.Map: nMapMaybeWithKey1 :: forall map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2'. NMap map1 k map1' s1 => NMap map2 k map2' s2 => NMap map1' k' v1 s1' => NMap map2' k' v2 s2' => (k' -> v1 -> Maybe v2) -> map1 -> map2
+ Hix.Class.Map: nMapWithKey :: NMap map1 k v1 sort1 => NMap map2 k v2 sort2 => (k -> v1 -> v2) -> map1 -> map2
+ Hix.Class.Map: nMapWithKey1 :: forall map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2'. NMap map1 k map1' s1 => NMap map2 k map2' s2 => NMap map1' k' v1 s1' => NMap map2' k' v2 s2' => (k -> k' -> v1 -> v2) -> map1 -> map2
+ Hix.Class.Map: nMerge :: forall map1 map2 map3 k v1 v2 v3 s1 s2 s3. NMap map1 k v1 s1 => NMap map2 k v2 s2 => NMap map3 k v3 s3 => SimpleWhenMissing k v1 v3 -> SimpleWhenMissing k v2 v3 -> SimpleWhenMatched k v1 v2 v3 -> map1 -> map2 -> map3
+ Hix.Class.Map: nMergeA :: forall map1 map2 map3 k v1 v2 v3 s1 s2 s3 m. Applicative m => NMap map1 k v1 s1 => NMap map2 k v2 s2 => NMap map3 k v3 s3 => WhenMissing m k v1 v3 -> WhenMissing m k v2 v3 -> WhenMatched m k v1 v2 v3 -> map1 -> map2 -> m map3
+ Hix.Class.Map: nPad :: forall map1 map2 k v1 v2 s1 s2. NMap map1 k v1 s1 => NMap map2 k v2 s2 => (v1 -> v2 -> v2) -> (v1 -> v2) -> map1 -> map2 -> map2
+ Hix.Class.Map: nPad1 :: forall map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2'. NMap map1 k map1' s1 => NMap map2 k map2' s2 => NMap map1' k' v1 s1' => NMap map2' k' v2 s2' => (v1 -> v2 -> v2) -> (v1 -> v2) -> map1 -> map2 -> map2
+ Hix.Class.Map: nPadKeep :: forall map1 map2 k v1 v2 s1 s2. NMap map1 k v1 s1 => NMap map2 k v2 s2 => (v1 -> v2) -> map1 -> map2 -> map2
+ Hix.Class.Map: nPadKeep1 :: forall map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2'. NMap map1 k map1' s1 => NMap map2 k map2' s2 => NMap map1' k' v1 s1' => NMap map2' k' v2 s2' => (v1 -> v2) -> map1 -> map2 -> map2
+ Hix.Class.Map: nPretty :: Pretty k => Pretty v => NMap map k v sort => map -> Doc
+ Hix.Class.Map: nPretty1 :: Pretty k => Pretty v => NMap map k v sort => map -> Doc
+ Hix.Class.Map: nPrettyWith :: Pretty k => NMap map k v sort => (v -> Doc) -> map -> Doc
+ Hix.Class.Map: nRestrictKeys :: NMap map k v sort => Set k -> map -> map
+ Hix.Class.Map: nTo :: NMap map k v sort => map -> (k -> v -> a) -> [a]
+ Hix.Class.Map: nTo1 :: forall map1 map2 k1 k2 v s1 s2 a. NMap map1 k1 map2 s1 => NMap map2 k2 v s2 => map1 -> (k1 -> k2 -> v -> a) -> [a]
+ Hix.Class.Map: nToMaybe :: NMap map k v sort => map -> (k -> v -> Maybe a) -> [a]
+ Hix.Class.Map: nToWith :: NMap map k v sort => (k -> v -> a) -> map -> [a]
+ Hix.Class.Map: nToWith1 :: forall map1 map2 k1 k2 v s1 s2 a. NMap map1 k1 map2 s1 => NMap map2 k2 v s2 => (k1 -> k2 -> v -> a) -> map1 -> [a]
+ Hix.Class.Map: nTransform :: NMap map1 k1 v1 sort1 => NMap map2 k2 v2 sort2 => (k1 -> v1 -> (k2, v2)) -> map1 -> map2
+ Hix.Class.Map: nTransformMaybe :: NMap map1 k1 v1 sort1 => NMap map2 k2 v2 sort2 => (k1 -> v1 -> Maybe (k2, v2)) -> map1 -> map2
+ Hix.Class.Map: nUpdate :: forall map k v sort l. NMap map k v sort => NLookup sort k v l => k -> map -> (l -> v) -> map
+ Hix.Class.Map: nUpdateWith :: forall map k v sort l. NMap map k v sort => NLookup sort k v l => k -> (l -> v) -> map -> map
+ Hix.Class.Map: nVia :: NMap map1 k1 v1 s1 => NMap map2 k2 v2 s2 => (Map k1 v1 -> Map k2 v2) -> map1 -> map2
+ Hix.Class.Map: nViaA :: Applicative m => NMap map1 k1 v1 s1 => NMap map2 k2 v2 s2 => (Map k1 v1 -> m (Map k2 v2)) -> map1 -> m map2
+ Hix.Class.Map: nWithoutKeys :: NMap map k v sort => Set k -> map -> map
+ Hix.Class.Map: nZip :: forall map1 map2 map3 k v1 v2 v3 s1 s2 s3. NMap map1 k v1 s1 => NMap map2 k v2 s2 => NMap map3 k v3 s3 => (v1 -> v2 -> v3) -> map1 -> map2 -> map3
+ Hix.Class.Map: nZipR :: forall map1 map2 map3 k v1 v2 v3 s1 s2 s3. NMap map1 k v1 s1 => NMap map2 k v2 s2 => NMap map3 k v3 s3 => (Maybe v1 -> v2 -> v3) -> map1 -> map2 -> map3
+ Hix.Class.Map: nZipWithKey :: forall map1 map2 map3 k v1 v2 v3 s1 s2 s3. NMap map1 k v1 s1 => NMap map2 k v2 s2 => NMap map3 k v3 s3 => (k -> v1 -> v2 -> v3) -> map1 -> map2 -> map3
+ Hix.Class.Map: nZipWithKeyR :: forall map1 map2 map3 k v1 v2 v3 s1 s2 s3. NMap map1 k v1 s1 => NMap map2 k v2 s2 => NMap map3 k v3 s3 => (k -> Maybe v1 -> v2 -> v3) -> map1 -> map2 -> map3
+ Hix.Class.SOP: FieldK :: Symbol -> Type -> FieldK
+ Hix.Class.SOP: [$sel:name:FieldK] :: FieldK -> Symbol
+ Hix.Class.SOP: [$sel:tpe:FieldK] :: FieldK -> Type
+ Hix.Class.SOP: [Field] :: a -> Field ('FieldK name a)
+ Hix.Class.SOP: class ProdFields info as fields | info as -> fields
+ Hix.Class.SOP: class SumFields cons ass fields | cons ass -> fields
+ Hix.Class.SOP: class ToFields a fields | a -> fields
+ Hix.Class.SOP: data Field k
+ Hix.Class.SOP: data FieldK
+ Hix.Class.SOP: instance (GHC.Generics.Generic a, Generics.SOP.GGP.GFrom a, 'Generics.SOP.Type.Metadata.ADT mod name cons sni GHC.Types.~ Generics.SOP.GGP.GDatatypeInfoOf a, ass GHC.Types.~ Generics.SOP.GGP.GCode a, Hix.Class.SOP.SumFields cons ass fields) => Hix.Class.SOP.ToFields a fields
+ Hix.Class.SOP: instance (Hix.Class.SOP.ProdFields info as conFields, Hix.Class.SOP.SumFields cons ass fields) => Hix.Class.SOP.SumFields ('Generics.SOP.Type.Metadata.Record con info : cons) (as : ass) (conFields : fields)
+ Hix.Class.SOP: instance Hix.Class.SOP.ProdFields '[] '[] '[]
+ Hix.Class.SOP: instance Hix.Class.SOP.ProdFields info as fields => Hix.Class.SOP.ProdFields ('Generics.SOP.Type.Metadata.FieldInfo name : info) (a : as) ('Hix.Class.SOP.FieldK name a : fields)
+ Hix.Class.SOP: instance Hix.Class.SOP.SumFields '[] '[] '[]
+ Hix.Class.SOP: prodFields :: ProdFields info as fields => NP I as -> NP Field fields
+ Hix.Class.SOP: sumFields :: SumFields cons ass fields => NS (NP I) ass -> NS (NP Field) fields
+ Hix.Class.SOP: toFields :: ToFields a fields => a -> SOP Field fields
+ Hix.Console: ColorOffsets :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> ColorOffsets
+ Hix.Console: [$sel:black:ColorOffsets] :: ColorOffsets -> Int
+ Hix.Console: [$sel:blue:ColorOffsets] :: ColorOffsets -> Int
+ Hix.Console: [$sel:cyan:ColorOffsets] :: ColorOffsets -> Int
+ Hix.Console: [$sel:green:ColorOffsets] :: ColorOffsets -> Int
+ Hix.Console: [$sel:magenta:ColorOffsets] :: ColorOffsets -> Int
+ Hix.Console: [$sel:red:ColorOffsets] :: ColorOffsets -> Int
+ Hix.Console: [$sel:white:ColorOffsets] :: ColorOffsets -> Int
+ Hix.Console: [$sel:yellow:ColorOffsets] :: ColorOffsets -> Int
+ Hix.Console: bytesErr :: MonadIO m => ByteString -> m ()
+ Hix.Console: bytesOut :: MonadIO m => ByteString -> m ()
+ Hix.Console: color :: Int -> Text -> Text
+ Hix.Console: colors :: ColorOffsets
+ Hix.Console: data ColorOffsets
+ Hix.Console: err :: MonadIO m => Text -> m ()
+ Hix.Console: errorMessage :: Text -> Text
+ Hix.Console: hPrint :: MonadIO m => Handle -> Text -> m ()
+ Hix.Console: hPrintBS :: MonadIO m => Handle -> ByteString -> m ()
+ Hix.Console: instance GHC.Classes.Eq Hix.Console.ColorOffsets
+ Hix.Console: instance GHC.Generics.Generic Hix.Console.ColorOffsets
+ Hix.Console: instance GHC.Show.Show Hix.Console.ColorOffsets
+ Hix.Console: out :: MonadIO m => Text -> m ()
+ Hix.Console: sgi :: Text -> Text
+ Hix.Console: sgis :: [Text] -> Text -> Text
+ Hix.Console: withChevrons :: Int -> Text -> Text
+ Hix.Data.Bounds: BoundExtensions :: Map PackageName BoundExtension -> BoundExtensions
+ Hix.Data.Bounds: Bounds :: Map PackageName VersionBounds -> Bounds
+ Hix.Data.Bounds: LowerBoundExtension :: Version -> BoundExtension
+ Hix.Data.Bounds: Ranges :: Map PackageName VersionRange -> Ranges
+ Hix.Data.Bounds: UpperBoundExtension :: Version -> BoundExtension
+ Hix.Data.Bounds: data BoundExtension
+ Hix.Data.Bounds: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.Bounds.Ranges
+ Hix.Data.Bounds: instance Data.Aeson.Types.ToJSON.ToJSON Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance Distribution.Pretty.Pretty Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance Distribution.Pretty.Pretty Hix.Data.Bounds.Ranges
+ Hix.Data.Bounds: instance GHC.Base.Monoid Hix.Data.Bounds.BoundExtensions
+ Hix.Data.Bounds: instance GHC.Base.Monoid Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance GHC.Base.Monoid Hix.Data.Bounds.Ranges
+ Hix.Data.Bounds: instance GHC.Base.Semigroup Hix.Data.Bounds.BoundExtensions
+ Hix.Data.Bounds: instance GHC.Base.Semigroup Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance GHC.Base.Semigroup Hix.Data.Bounds.Ranges
+ Hix.Data.Bounds: instance GHC.Classes.Eq Hix.Data.Bounds.BoundExtension
+ Hix.Data.Bounds: instance GHC.Classes.Eq Hix.Data.Bounds.BoundExtensions
+ Hix.Data.Bounds: instance GHC.Classes.Eq Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance GHC.Classes.Eq Hix.Data.Bounds.Ranges
+ Hix.Data.Bounds: instance GHC.Generics.Generic Hix.Data.Bounds.BoundExtension
+ Hix.Data.Bounds: instance GHC.Generics.Generic Hix.Data.Bounds.BoundExtensions
+ Hix.Data.Bounds: instance GHC.Generics.Generic Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance GHC.Generics.Generic Hix.Data.Bounds.Ranges
+ Hix.Data.Bounds: instance GHC.IsList.IsList Hix.Data.Bounds.BoundExtensions
+ Hix.Data.Bounds: instance GHC.IsList.IsList Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance GHC.IsList.IsList Hix.Data.Bounds.Ranges
+ Hix.Data.Bounds: instance GHC.Show.Show Hix.Data.Bounds.BoundExtension
+ Hix.Data.Bounds: instance GHC.Show.Show Hix.Data.Bounds.BoundExtensions
+ Hix.Data.Bounds: instance GHC.Show.Show Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance GHC.Show.Show Hix.Data.Bounds.Ranges
+ Hix.Data.Bounds: instance Hix.Class.EncodeNix.EncodeNix Hix.Data.Bounds.Bounds
+ Hix.Data.Bounds: instance Hix.Class.Map.NMap Hix.Data.Bounds.BoundExtensions Hix.Data.PackageName.PackageName Hix.Data.Bounds.BoundExtension Hix.Class.Map.LookupMaybe
+ Hix.Data.Bounds: instance Hix.Class.Map.NMap Hix.Data.Bounds.Bounds Hix.Data.PackageName.PackageName Hix.Data.VersionBounds.VersionBounds Hix.Class.Map.LookupMaybe
+ Hix.Data.Bounds: instance Hix.Class.Map.NMap Hix.Data.Bounds.Ranges Hix.Data.PackageName.PackageName Distribution.Types.VersionRange.Internal.VersionRange Hix.Class.Map.LookupMaybe
+ Hix.Data.Bounds: newtype BoundExtensions
+ Hix.Data.Bounds: newtype Bounds
+ Hix.Data.Bounds: newtype Ranges
+ Hix.Data.ComponentConfig: instance Distribution.Pretty.Pretty Hix.Data.ComponentConfig.ComponentName
+ Hix.Data.Dep: Dep :: PackageName -> VersionRange -> Dep
+ Hix.Data.Dep: [$sel:package:Dep] :: Dep -> PackageName
+ Hix.Data.Dep: [$sel:version:Dep] :: Dep -> VersionRange
+ Hix.Data.Dep: data Dep
+ Hix.Data.Dep: fromCabal :: Dependency -> Dep
+ Hix.Data.Dep: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.Dep.Dep
+ Hix.Data.Dep: instance Distribution.Pretty.Pretty Hix.Data.Dep.Dep
+ Hix.Data.Dep: instance GHC.Classes.Eq Hix.Data.Dep.Dep
+ Hix.Data.Dep: instance GHC.Generics.Generic Hix.Data.Dep.Dep
+ Hix.Data.Dep: instance GHC.Show.Show Hix.Data.Dep.Dep
+ Hix.Data.Dep: jsonParseCabal :: String -> Parser Dep
+ Hix.Data.Dep: mkDep :: PackageName -> VersionRange -> Dep
+ Hix.Data.Dep: renderDep :: Dep -> Text
+ Hix.Data.Dep: thisVersionDep :: PackageName -> Version -> Dep
+ Hix.Data.Dep: toCabal :: Dep -> Dependency
+ Hix.Data.Dep: withVersion :: VersionRange -> Dep -> Dep
+ Hix.Data.EnvName: EnvName :: Text -> EnvName
+ Hix.Data.EnvName: [$sel:unEnvName:EnvName] :: EnvName -> Text
+ Hix.Data.EnvName: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.EnvName.EnvName
+ Hix.Data.EnvName: instance Data.Aeson.Types.FromJSON.FromJSONKey Hix.Data.EnvName.EnvName
+ Hix.Data.EnvName: instance Data.String.IsString Hix.Data.EnvName.EnvName
+ Hix.Data.EnvName: instance Distribution.Pretty.Pretty Hix.Data.EnvName.EnvName
+ Hix.Data.EnvName: instance GHC.Classes.Eq Hix.Data.EnvName.EnvName
+ Hix.Data.EnvName: instance GHC.Classes.Ord Hix.Data.EnvName.EnvName
+ Hix.Data.EnvName: instance GHC.Generics.Generic Hix.Data.EnvName.EnvName
+ Hix.Data.EnvName: instance GHC.Show.Show Hix.Data.EnvName.EnvName
+ Hix.Data.EnvName: instance Hix.Class.EncodeNix.EncodeNixKey Hix.Data.EnvName.EnvName
+ Hix.Data.EnvName: newtype EnvName
+ Hix.Data.Error: Client :: Text -> Error
+ Hix.Data.GlobalOptions: GlobalOptions :: Bool -> Bool -> Bool -> Path Abs Dir -> OutputFormat -> OutputTarget -> GlobalOptions
+ Hix.Data.GlobalOptions: [$sel:cwd:GlobalOptions] :: GlobalOptions -> Path Abs Dir
+ Hix.Data.GlobalOptions: [$sel:debug:GlobalOptions] :: GlobalOptions -> Bool
+ Hix.Data.GlobalOptions: [$sel:output:GlobalOptions] :: GlobalOptions -> OutputFormat
+ Hix.Data.GlobalOptions: [$sel:quiet:GlobalOptions] :: GlobalOptions -> Bool
+ Hix.Data.GlobalOptions: [$sel:target:GlobalOptions] :: GlobalOptions -> OutputTarget
+ Hix.Data.GlobalOptions: [$sel:verbose:GlobalOptions] :: GlobalOptions -> Bool
+ Hix.Data.GlobalOptions: data GlobalOptions
+ Hix.Data.GlobalOptions: defaultGlobalOptions :: Path Abs Dir -> GlobalOptions
+ Hix.Data.GlobalOptions: instance GHC.Classes.Eq Hix.Data.GlobalOptions.GlobalOptions
+ Hix.Data.GlobalOptions: instance GHC.Generics.Generic Hix.Data.GlobalOptions.GlobalOptions
+ Hix.Data.GlobalOptions: instance GHC.Show.Show Hix.Data.GlobalOptions.GlobalOptions
+ Hix.Data.Json: JsonParsec :: a -> JsonParsec a
+ Hix.Data.Json: aesonParsec :: Parsec a => String -> Parser a
+ Hix.Data.Json: foldMissing :: Monoid a => FromJSON a => Object -> Key -> Parser a
+ Hix.Data.Json: instance Distribution.Parsec.Parsec a => Data.Aeson.Types.FromJSON.FromJSON (Hix.Data.Json.JsonParsec a)
+ Hix.Data.Json: instance GHC.Classes.Eq a => GHC.Classes.Eq (Hix.Data.Json.JsonParsec a)
+ Hix.Data.Json: instance GHC.Generics.Generic (Hix.Data.Json.JsonParsec a)
+ Hix.Data.Json: instance GHC.Show.Show a => GHC.Show.Show (Hix.Data.Json.JsonParsec a)
+ Hix.Data.Json: jsonParsec :: JsonParsec a -> a
+ Hix.Data.Json: newtype JsonParsec a
+ Hix.Data.Monad: AppResProxy :: AppResProxy
+ Hix.Data.Monad: AppResources :: Path Abs Dir -> Path Abs Dir -> Bool -> Bool -> Bool -> OutputFormat -> OutputTarget -> (LogLevel -> Text -> M ()) -> AppResources
+ Hix.Data.Monad: LogDebug :: LogLevel
+ Hix.Data.Monad: LogError :: LogLevel
+ Hix.Data.Monad: LogInfo :: LogLevel
+ Hix.Data.Monad: LogVerbose :: LogLevel
+ Hix.Data.Monad: LogWarn :: LogLevel
+ Hix.Data.Monad: M :: ReaderT AppResources (ExceptT Error IO) a -> M a
+ Hix.Data.Monad: [$sel:cwd:AppResources] :: AppResources -> Path Abs Dir
+ Hix.Data.Monad: [$sel:debug:AppResources] :: AppResources -> Bool
+ Hix.Data.Monad: [$sel:logger:AppResources] :: AppResources -> LogLevel -> Text -> M ()
+ Hix.Data.Monad: [$sel:output:AppResources] :: AppResources -> OutputFormat
+ Hix.Data.Monad: [$sel:quiet:AppResources] :: AppResources -> Bool
+ Hix.Data.Monad: [$sel:target:AppResources] :: AppResources -> OutputTarget
+ Hix.Data.Monad: [$sel:tmp:AppResources] :: AppResources -> Path Abs Dir
+ Hix.Data.Monad: [$sel:verbose:AppResources] :: AppResources -> Bool
+ Hix.Data.Monad: appRes :: AppResProxy
+ Hix.Data.Monad: data AppResProxy
+ Hix.Data.Monad: data AppResources
+ Hix.Data.Monad: data LogLevel
+ Hix.Data.Monad: instance Control.Monad.Catch.MonadCatch Hix.Data.Monad.M
+ Hix.Data.Monad: instance Control.Monad.Catch.MonadMask Hix.Data.Monad.M
+ Hix.Data.Monad: instance Control.Monad.Catch.MonadThrow Hix.Data.Monad.M
+ Hix.Data.Monad: instance Control.Monad.IO.Class.MonadIO Hix.Data.Monad.M
+ Hix.Data.Monad: instance GHC.Base.Applicative Hix.Data.Monad.M
+ Hix.Data.Monad: instance GHC.Base.Functor Hix.Data.Monad.M
+ Hix.Data.Monad: instance GHC.Base.Monad Hix.Data.Monad.M
+ Hix.Data.Monad: instance GHC.Classes.Eq Hix.Data.Monad.LogLevel
+ Hix.Data.Monad: instance GHC.Generics.Generic Hix.Data.Monad.LogLevel
+ Hix.Data.Monad: instance GHC.Show.Show Hix.Data.Monad.LogLevel
+ Hix.Data.Monad: instance forall k (name :: k) a. GHC.Records.HasField name Hix.Data.Monad.AppResources a => GHC.Records.HasField name Hix.Data.Monad.AppResProxy (Hix.Data.Monad.M a)
+ Hix.Data.Monad: liftE :: ExceptT Error IO a -> M a
+ Hix.Data.Monad: newtype M a
+ Hix.Data.NixExpr: ExprAttr :: Text -> Expr -> ExprAttr
+ Hix.Data.NixExpr: ExprAttrNil :: ExprAttr
+ Hix.Data.NixExpr: ExprAttrs :: [ExprAttr] -> Expr
+ Hix.Data.NixExpr: ExprList :: [Expr] -> Expr
+ Hix.Data.NixExpr: ExprLit :: Text -> Expr
+ Hix.Data.NixExpr: ExprNull :: Expr
+ Hix.Data.NixExpr: ExprPrefix :: Text -> Expr -> Expr
+ Hix.Data.NixExpr: ExprString :: Text -> Expr
+ Hix.Data.NixExpr: ViaPretty :: a -> ViaPretty a
+ Hix.Data.NixExpr: [$sel:name:ExprAttr] :: ExprAttr -> Text
+ Hix.Data.NixExpr: [$sel:value:ExprAttr] :: ExprAttr -> Expr
+ Hix.Data.NixExpr: data Expr
+ Hix.Data.NixExpr: data ExprAttr
+ Hix.Data.NixExpr: exprBool :: Bool -> Expr
+ Hix.Data.NixExpr: exprShow :: Show a => a -> Expr
+ Hix.Data.NixExpr: instance GHC.Classes.Eq Hix.Data.NixExpr.Expr
+ Hix.Data.NixExpr: instance GHC.Classes.Eq Hix.Data.NixExpr.ExprAttr
+ Hix.Data.NixExpr: instance GHC.Classes.Eq a => GHC.Classes.Eq (Hix.Data.NixExpr.ViaPretty a)
+ Hix.Data.NixExpr: instance GHC.Generics.Generic (Hix.Data.NixExpr.ViaPretty a)
+ Hix.Data.NixExpr: instance GHC.Generics.Generic Hix.Data.NixExpr.Expr
+ Hix.Data.NixExpr: instance GHC.Generics.Generic Hix.Data.NixExpr.ExprAttr
+ Hix.Data.NixExpr: instance GHC.Show.Show Hix.Data.NixExpr.Expr
+ Hix.Data.NixExpr: instance GHC.Show.Show Hix.Data.NixExpr.ExprAttr
+ Hix.Data.NixExpr: instance GHC.Show.Show a => GHC.Show.Show (Hix.Data.NixExpr.ViaPretty a)
+ Hix.Data.NixExpr: newtype ViaPretty a
+ Hix.Data.Options: BootstrapCmd :: BootstrapOptions -> Command
+ Hix.Data.Options: BootstrapOptions :: BootstrapProjectConfig -> BootstrapOptions
+ Hix.Data.Options: BumpCmd :: BumpOptions -> Command
+ Hix.Data.Options: BumpOptions :: ManagedOptions -> BumpOptions
+ Hix.Data.Options: ComponentCoords :: Maybe PackageSpec -> Maybe ComponentSpec -> ComponentCoords
+ Hix.Data.Options: ComponentSpec :: ComponentName -> Maybe SourceDir -> ComponentSpec
+ Hix.Data.Options: EnvRunner :: EnvRunnerCommandOptions -> Command
+ Hix.Data.Options: EnvRunnerCommandOptions :: EnvRunnerOptions -> TestOptions -> Maybe ExtraGhciOptions -> Maybe ExtraGhcidOptions -> EnvRunnerCommandOptions
+ Hix.Data.Options: EnvRunnerOptions :: Either EnvConfig JsonConfig -> Maybe (Path Abs Dir) -> Maybe TargetSpec -> EnvRunnerOptions
+ Hix.Data.Options: ExtraGhciOptions :: Text -> ExtraGhciOptions
+ Hix.Data.Options: ExtraGhcidOptions :: Text -> ExtraGhcidOptions
+ Hix.Data.Options: GhciCmd :: GhciOptions -> Command
+ Hix.Data.Options: GhciOptions :: Either GhciConfig JsonConfig -> Maybe (Path Abs Dir) -> TargetSpec -> TestOptions -> Maybe ExtraGhciOptions -> GhciOptions
+ Hix.Data.Options: GhcidCmd :: GhcidOptions -> Command
+ Hix.Data.Options: GhcidOptions :: GhciOptions -> Maybe ExtraGhcidOptions -> GhcidOptions
+ Hix.Data.Options: LowerAutoCmd :: LowerOptions -> LowerCommand
+ Hix.Data.Options: LowerCmd :: LowerCommand -> Command
+ Hix.Data.Options: LowerInitCmd :: LowerOptions -> LowerCommand
+ Hix.Data.Options: LowerOptimizeCmd :: LowerOptions -> LowerCommand
+ Hix.Data.Options: LowerOptions :: ManagedOptions -> Bool -> Bool -> Bool -> LowerOptions
+ Hix.Data.Options: LowerStabilizeCmd :: LowerOptions -> LowerCommand
+ Hix.Data.Options: ManagedOptions :: Either ProjectContextProto JsonConfig -> ProjectOptions -> StateFileConfig -> CabalConfig -> Maybe SpecialBuildHandlers -> ManagedOptions
+ Hix.Data.Options: NewCmd :: NewOptions -> Command
+ Hix.Data.Options: NewOptions :: NewProjectConfig -> NewOptions
+ Hix.Data.Options: Options :: GlobalOptions -> Command -> Options
+ Hix.Data.Options: PackageSpec :: PackageName -> Maybe (SomeBase Dir) -> PackageSpec
+ Hix.Data.Options: Preproc :: PreprocOptions -> Command
+ Hix.Data.Options: PreprocOptions :: Maybe (Either PreprocConfig JsonConfig) -> Maybe (Path Abs Dir) -> Path Abs File -> Path Abs File -> Path Abs File -> PreprocOptions
+ Hix.Data.Options: ProjectOptions :: BuildConfig -> [EnvName] -> RawQuery -> Bool -> Bool -> ProjectOptions
+ Hix.Data.Options: TargetForComponent :: ComponentCoords -> TargetSpec
+ Hix.Data.Options: TargetForFile :: Path Abs File -> TargetSpec
+ Hix.Data.Options: TestOptions :: ModuleName -> Maybe Text -> Maybe RunnerName -> ChangeDir -> TestOptions
+ Hix.Data.Options: [$sel:build:ProjectOptions] :: ProjectOptions -> BuildConfig
+ Hix.Data.Options: [$sel:cabal:ManagedOptions] :: ManagedOptions -> CabalConfig
+ Hix.Data.Options: [$sel:cd:TestOptions] :: TestOptions -> ChangeDir
+ Hix.Data.Options: [$sel:cmd:Options] :: Options -> Command
+ Hix.Data.Options: [$sel:common:BumpOptions] :: BumpOptions -> ManagedOptions
+ Hix.Data.Options: [$sel:common:LowerOptions] :: LowerOptions -> ManagedOptions
+ Hix.Data.Options: [$sel:component:ComponentCoords] :: ComponentCoords -> Maybe ComponentSpec
+ Hix.Data.Options: [$sel:component:EnvRunnerOptions] :: EnvRunnerOptions -> Maybe TargetSpec
+ Hix.Data.Options: [$sel:component:GhciOptions] :: GhciOptions -> TargetSpec
+ Hix.Data.Options: [$sel:config:BootstrapOptions] :: BootstrapOptions -> BootstrapProjectConfig
+ Hix.Data.Options: [$sel:config:EnvRunnerOptions] :: EnvRunnerOptions -> Either EnvConfig JsonConfig
+ Hix.Data.Options: [$sel:config:GhciOptions] :: GhciOptions -> Either GhciConfig JsonConfig
+ Hix.Data.Options: [$sel:config:NewOptions] :: NewOptions -> NewProjectConfig
+ Hix.Data.Options: [$sel:config:PreprocOptions] :: PreprocOptions -> Maybe (Either PreprocConfig JsonConfig)
+ Hix.Data.Options: [$sel:context:ManagedOptions] :: ManagedOptions -> Either ProjectContextProto JsonConfig
+ Hix.Data.Options: [$sel:dir:ComponentSpec] :: ComponentSpec -> Maybe SourceDir
+ Hix.Data.Options: [$sel:dir:PackageSpec] :: PackageSpec -> Maybe (SomeBase Dir)
+ Hix.Data.Options: [$sel:envs:ProjectOptions] :: ProjectOptions -> [EnvName]
+ Hix.Data.Options: [$sel:extra:GhciOptions] :: GhciOptions -> Maybe ExtraGhciOptions
+ Hix.Data.Options: [$sel:extra:GhcidOptions] :: GhcidOptions -> Maybe ExtraGhcidOptions
+ Hix.Data.Options: [$sel:extraGhci:EnvRunnerCommandOptions] :: EnvRunnerCommandOptions -> Maybe ExtraGhciOptions
+ Hix.Data.Options: [$sel:extraGhcid:EnvRunnerCommandOptions] :: EnvRunnerCommandOptions -> Maybe ExtraGhcidOptions
+ Hix.Data.Options: [$sel:ghci:GhcidOptions] :: GhcidOptions -> GhciOptions
+ Hix.Data.Options: [$sel:global:Options] :: Options -> GlobalOptions
+ Hix.Data.Options: [$sel:handlers:ManagedOptions] :: ManagedOptions -> Maybe SpecialBuildHandlers
+ Hix.Data.Options: [$sel:inFile:PreprocOptions] :: PreprocOptions -> Path Abs File
+ Hix.Data.Options: [$sel:initOnly:LowerOptions] :: LowerOptions -> Bool
+ Hix.Data.Options: [$sel:mergeBounds:ProjectOptions] :: ProjectOptions -> Bool
+ Hix.Data.Options: [$sel:mod:TestOptions] :: TestOptions -> ModuleName
+ Hix.Data.Options: [$sel:name:ComponentSpec] :: ComponentSpec -> ComponentName
+ Hix.Data.Options: [$sel:name:PackageSpec] :: PackageSpec -> PackageName
+ Hix.Data.Options: [$sel:options:EnvRunnerCommandOptions] :: EnvRunnerCommandOptions -> EnvRunnerOptions
+ Hix.Data.Options: [$sel:outFile:PreprocOptions] :: PreprocOptions -> Path Abs File
+ Hix.Data.Options: [$sel:package:ComponentCoords] :: ComponentCoords -> Maybe PackageSpec
+ Hix.Data.Options: [$sel:project:ManagedOptions] :: ManagedOptions -> ProjectOptions
+ Hix.Data.Options: [$sel:query:ProjectOptions] :: ProjectOptions -> RawQuery
+ Hix.Data.Options: [$sel:readUpperBounds:ProjectOptions] :: ProjectOptions -> Bool
+ Hix.Data.Options: [$sel:reset:LowerOptions] :: LowerOptions -> Bool
+ Hix.Data.Options: [$sel:root:EnvRunnerOptions] :: EnvRunnerOptions -> Maybe (Path Abs Dir)
+ Hix.Data.Options: [$sel:root:GhciOptions] :: GhciOptions -> Maybe (Path Abs Dir)
+ Hix.Data.Options: [$sel:root:PreprocOptions] :: PreprocOptions -> Maybe (Path Abs Dir)
+ Hix.Data.Options: [$sel:runner:TestOptions] :: TestOptions -> Maybe RunnerName
+ Hix.Data.Options: [$sel:source:PreprocOptions] :: PreprocOptions -> Path Abs File
+ Hix.Data.Options: [$sel:stabilize:LowerOptions] :: LowerOptions -> Bool
+ Hix.Data.Options: [$sel:stateFile:ManagedOptions] :: ManagedOptions -> StateFileConfig
+ Hix.Data.Options: [$sel:test:EnvRunnerCommandOptions] :: EnvRunnerCommandOptions -> TestOptions
+ Hix.Data.Options: [$sel:test:GhciOptions] :: GhciOptions -> TestOptions
+ Hix.Data.Options: [$sel:test:TestOptions] :: TestOptions -> Maybe Text
+ Hix.Data.Options: data BootstrapOptions
+ Hix.Data.Options: data BumpOptions
+ Hix.Data.Options: data Command
+ Hix.Data.Options: data ComponentCoords
+ Hix.Data.Options: data ComponentSpec
+ Hix.Data.Options: data EnvRunnerCommandOptions
+ Hix.Data.Options: data EnvRunnerOptions
+ Hix.Data.Options: data GhciOptions
+ Hix.Data.Options: data GhcidOptions
+ Hix.Data.Options: data LowerCommand
+ Hix.Data.Options: data LowerOptions
+ Hix.Data.Options: data ManagedOptions
+ Hix.Data.Options: data NewOptions
+ Hix.Data.Options: data Options
+ Hix.Data.Options: data PackageSpec
+ Hix.Data.Options: data PreprocOptions
+ Hix.Data.Options: data ProjectOptions
+ Hix.Data.Options: data TargetSpec
+ Hix.Data.Options: data TestOptions
+ Hix.Data.Options: instance Data.Default.Class.Default Hix.Data.Options.ProjectOptions
+ Hix.Data.Options: instance Data.String.IsString Hix.Data.Options.ExtraGhciOptions
+ Hix.Data.Options: instance Data.String.IsString Hix.Data.Options.ExtraGhcidOptions
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.BootstrapOptions
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.ComponentCoords
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.ComponentSpec
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.ExtraGhciOptions
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.ExtraGhcidOptions
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.NewOptions
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.PackageSpec
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.ProjectOptions
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.TargetSpec
+ Hix.Data.Options: instance GHC.Classes.Eq Hix.Data.Options.TestOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.BootstrapOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.BumpOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.ComponentCoords
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.ComponentSpec
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.EnvRunnerCommandOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.EnvRunnerOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.ExtraGhciOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.ExtraGhcidOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.GhciOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.GhcidOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.ManagedOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.NewOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.PackageSpec
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.PreprocOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.ProjectOptions
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.TargetSpec
+ Hix.Data.Options: instance GHC.Generics.Generic Hix.Data.Options.TestOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.BootstrapOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.BumpOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.Command
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.ComponentCoords
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.ComponentSpec
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.EnvRunnerCommandOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.EnvRunnerOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.ExtraGhciOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.ExtraGhcidOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.GhciOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.GhcidOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.LowerCommand
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.LowerOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.ManagedOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.NewOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.Options
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.PackageSpec
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.PreprocOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.ProjectOptions
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.TargetSpec
+ Hix.Data.Options: instance GHC.Show.Show Hix.Data.Options.TestOptions
+ Hix.Data.Options: newtype ExtraGhciOptions
+ Hix.Data.Options: newtype ExtraGhcidOptions
+ Hix.Data.Options: projectOptions :: [EnvName] -> ProjectOptions
+ Hix.Data.OutputFormat: OutputCommitMsg :: OutputFormat
+ Hix.Data.OutputFormat: OutputGaPr :: OutputFormat
+ Hix.Data.OutputFormat: OutputJson :: OutputFormat
+ Hix.Data.OutputFormat: OutputNone :: OutputFormat
+ Hix.Data.OutputFormat: data OutputFormat
+ Hix.Data.OutputFormat: instance GHC.Classes.Eq Hix.Data.OutputFormat.OutputFormat
+ Hix.Data.OutputFormat: instance GHC.Generics.Generic Hix.Data.OutputFormat.OutputFormat
+ Hix.Data.OutputFormat: instance GHC.Show.Show Hix.Data.OutputFormat.OutputFormat
+ Hix.Data.OutputTarget: OutputDefault :: OutputTarget
+ Hix.Data.OutputTarget: OutputFile :: Path Abs File -> OutputTarget
+ Hix.Data.OutputTarget: OutputStdout :: OutputTarget
+ Hix.Data.OutputTarget: data OutputTarget
+ Hix.Data.OutputTarget: instance GHC.Classes.Eq Hix.Data.OutputTarget.OutputTarget
+ Hix.Data.OutputTarget: instance GHC.Generics.Generic Hix.Data.OutputTarget.OutputTarget
+ Hix.Data.OutputTarget: instance GHC.Show.Show Hix.Data.OutputTarget.OutputTarget
+ Hix.Data.Overrides: Override :: Version -> SourceHash -> Override
+ Hix.Data.Overrides: Overrides :: Map PackageName Override -> Overrides
+ Hix.Data.Overrides: [$sel:hash:Override] :: Override -> SourceHash
+ Hix.Data.Overrides: [$sel:version:Override] :: Override -> Version
+ Hix.Data.Overrides: data Override
+ Hix.Data.Overrides: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.Overrides.Override
+ Hix.Data.Overrides: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.Overrides.Overrides
+ Hix.Data.Overrides: instance Distribution.Pretty.Pretty Hix.Data.Overrides.Override
+ Hix.Data.Overrides: instance Distribution.Pretty.Pretty Hix.Data.Overrides.Overrides
+ Hix.Data.Overrides: instance GHC.Base.Monoid Hix.Data.Overrides.Overrides
+ Hix.Data.Overrides: instance GHC.Base.Semigroup Hix.Data.Overrides.Overrides
+ Hix.Data.Overrides: instance GHC.Classes.Eq Hix.Data.Overrides.Override
+ Hix.Data.Overrides: instance GHC.Classes.Eq Hix.Data.Overrides.Overrides
+ Hix.Data.Overrides: instance GHC.Generics.Generic Hix.Data.Overrides.Override
+ Hix.Data.Overrides: instance GHC.Generics.Generic Hix.Data.Overrides.Overrides
+ Hix.Data.Overrides: instance GHC.IsList.IsList Hix.Data.Overrides.Overrides
+ Hix.Data.Overrides: instance GHC.Show.Show Hix.Data.Overrides.Override
+ Hix.Data.Overrides: instance GHC.Show.Show Hix.Data.Overrides.Overrides
+ Hix.Data.Overrides: instance Hix.Class.EncodeNix.EncodeNix Hix.Data.Overrides.Override
+ Hix.Data.Overrides: instance Hix.Class.EncodeNix.EncodeNix Hix.Data.Overrides.Overrides
+ Hix.Data.Overrides: instance Hix.Class.Map.NMap Hix.Data.Overrides.Overrides Hix.Data.PackageName.PackageName Hix.Data.Overrides.Override Hix.Class.Map.LookupMaybe
+ Hix.Data.Overrides: newtype Overrides
+ Hix.Data.PackageId: PackageId :: PackageName -> Version -> PackageId
+ Hix.Data.PackageId: [$sel:name:PackageId] :: PackageId -> PackageName
+ Hix.Data.PackageId: [$sel:version:PackageId] :: PackageId -> Version
+ Hix.Data.PackageId: data PackageId
+ Hix.Data.PackageId: fromCabal :: PackageIdentifier -> PackageId
+ Hix.Data.PackageId: instance Distribution.Pretty.Pretty Hix.Data.PackageId.PackageId
+ Hix.Data.PackageId: instance GHC.Classes.Eq Hix.Data.PackageId.PackageId
+ Hix.Data.PackageId: instance GHC.Generics.Generic Hix.Data.PackageId.PackageId
+ Hix.Data.PackageId: instance GHC.Show.Show Hix.Data.PackageId.PackageId
+ Hix.Data.PackageId: renderPackage :: PackageId -> Text
+ Hix.Data.PackageId: toCabal :: PackageId -> PackageIdentifier
+ Hix.Data.PackageName: LocalPackage :: PackageName -> LocalPackage
+ Hix.Data.PackageName: PackageName :: Text -> PackageName
+ Hix.Data.PackageName: depPackageName :: Dependency -> PackageName
+ Hix.Data.PackageName: fromCabal :: PackageName -> PackageName
+ Hix.Data.PackageName: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.PackageName.LocalPackage
+ Hix.Data.PackageName: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance Data.Aeson.Types.FromJSON.FromJSONKey Hix.Data.PackageName.LocalPackage
+ Hix.Data.PackageName: instance Data.Aeson.Types.FromJSON.FromJSONKey Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance Data.Aeson.Types.ToJSON.ToJSON Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance Data.Aeson.Types.ToJSON.ToJSONKey Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance Data.String.IsString Hix.Data.PackageName.LocalPackage
+ Hix.Data.PackageName: instance Data.String.IsString Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance Distribution.Pretty.Pretty Hix.Data.PackageName.LocalPackage
+ Hix.Data.PackageName: instance Distribution.Pretty.Pretty Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance GHC.Classes.Eq Hix.Data.PackageName.LocalPackage
+ Hix.Data.PackageName: instance GHC.Classes.Eq Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance GHC.Classes.Ord Hix.Data.PackageName.LocalPackage
+ Hix.Data.PackageName: instance GHC.Classes.Ord Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance GHC.Generics.Generic Hix.Data.PackageName.LocalPackage
+ Hix.Data.PackageName: instance GHC.Generics.Generic Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance GHC.Show.Show Hix.Data.PackageName.LocalPackage
+ Hix.Data.PackageName: instance GHC.Show.Show Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: instance Hix.Class.EncodeNix.EncodeNixKey Hix.Data.PackageName.LocalPackage
+ Hix.Data.PackageName: instance Hix.Class.EncodeNix.EncodeNixKey Hix.Data.PackageName.PackageName
+ Hix.Data.PackageName: isLocalPackage :: Set LocalPackage -> PackageName -> Bool
+ Hix.Data.PackageName: localPackageName :: LocalPackage -> PackageName
+ Hix.Data.PackageName: localPackageNames :: [LocalPackage] -> [PackageName]
+ Hix.Data.PackageName: newtype LocalPackage
+ Hix.Data.PackageName: newtype PackageName
+ Hix.Data.PackageName: sameLocalPackage :: LocalPackage -> PackageName -> Bool
+ Hix.Data.PackageName: toCabal :: PackageName -> PackageName
+ Hix.Data.PackageName: toLocalPackage :: Set LocalPackage -> PackageName -> Maybe LocalPackage
+ Hix.Data.Version: Major :: Version -> NonEmpty Version -> Major
+ Hix.Data.Version: SourceHash :: Text -> SourceHash
+ Hix.Data.Version: Versions :: Map PackageName Version -> Versions
+ Hix.Data.Version: [$sel:prefix:Major] :: Major -> Version
+ Hix.Data.Version: [$sel:versions:Major] :: Major -> NonEmpty Version
+ Hix.Data.Version: data Major
+ Hix.Data.Version: data () => Version
+ Hix.Data.Version: data () => VersionRange
+ Hix.Data.Version: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.Version.SourceHash
+ Hix.Data.Version: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.Version.Versions
+ Hix.Data.Version: instance Distribution.Pretty.Pretty Hix.Data.Version.SourceHash
+ Hix.Data.Version: instance Distribution.Pretty.Pretty Hix.Data.Version.Versions
+ Hix.Data.Version: instance GHC.Base.Monoid Hix.Data.Version.Versions
+ Hix.Data.Version: instance GHC.Base.Semigroup Hix.Data.Version.Versions
+ Hix.Data.Version: instance GHC.Classes.Eq Hix.Data.Version.Major
+ Hix.Data.Version: instance GHC.Classes.Eq Hix.Data.Version.SourceHash
+ Hix.Data.Version: instance GHC.Classes.Eq Hix.Data.Version.Versions
+ Hix.Data.Version: instance GHC.Classes.Ord Hix.Data.Version.SourceHash
+ Hix.Data.Version: instance GHC.Generics.Generic Hix.Data.Version.Major
+ Hix.Data.Version: instance GHC.Generics.Generic Hix.Data.Version.SourceHash
+ Hix.Data.Version: instance GHC.Generics.Generic Hix.Data.Version.Versions
+ Hix.Data.Version: instance GHC.IsList.IsList Hix.Data.Version.Versions
+ Hix.Data.Version: instance GHC.Show.Show Hix.Data.Version.Major
+ Hix.Data.Version: instance GHC.Show.Show Hix.Data.Version.SourceHash
+ Hix.Data.Version: instance GHC.Show.Show Hix.Data.Version.Versions
+ Hix.Data.Version: instance Hix.Class.EncodeNix.EncodeNix Hix.Data.Version.SourceHash
+ Hix.Data.Version: instance Hix.Class.EncodeNix.EncodeNix Hix.Data.Version.Versions
+ Hix.Data.Version: instance Hix.Class.Map.NMap Hix.Data.Version.Versions Hix.Data.PackageName.PackageName Distribution.Types.Version.Version Hix.Class.Map.LookupMaybe
+ Hix.Data.Version: newtype SourceHash
+ Hix.Data.Version: newtype Versions
+ Hix.Data.Version: packageIdVersions :: [PackageId] -> Versions
+ Hix.Data.Version: prettyMajors :: NonEmpty Major -> Doc
+ Hix.Data.Version: range0 :: VersionRange
+ Hix.Data.VersionBounds: BoundLower :: Bound
+ Hix.Data.VersionBounds: BoundUpper :: Bound
+ Hix.Data.VersionBounds: VersionBounds :: Maybe Version -> Maybe Version -> VersionBounds
+ Hix.Data.VersionBounds: [$sel:lower:VersionBounds] :: VersionBounds -> Maybe Version
+ Hix.Data.VersionBounds: [$sel:upper:VersionBounds] :: VersionBounds -> Maybe Version
+ Hix.Data.VersionBounds: anyBounds :: VersionBounds
+ Hix.Data.VersionBounds: data Bound
+ Hix.Data.VersionBounds: data VersionBounds
+ Hix.Data.VersionBounds: exactVersion :: Version -> VersionBounds
+ Hix.Data.VersionBounds: fromLower :: Version -> VersionBounds
+ Hix.Data.VersionBounds: fromUpper :: Version -> VersionBounds
+ Hix.Data.VersionBounds: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Data.VersionBounds.VersionBounds
+ Hix.Data.VersionBounds: instance Data.Aeson.Types.ToJSON.ToJSON Hix.Data.VersionBounds.VersionBounds
+ Hix.Data.VersionBounds: instance Distribution.Pretty.Pretty Hix.Data.VersionBounds.Bound
+ Hix.Data.VersionBounds: instance Distribution.Pretty.Pretty Hix.Data.VersionBounds.VersionBounds
+ Hix.Data.VersionBounds: instance GHC.Base.Monoid Hix.Data.VersionBounds.VersionBounds
+ Hix.Data.VersionBounds: instance GHC.Base.Semigroup Hix.Data.VersionBounds.VersionBounds
+ Hix.Data.VersionBounds: instance GHC.Classes.Eq Hix.Data.VersionBounds.Bound
+ Hix.Data.VersionBounds: instance GHC.Classes.Eq Hix.Data.VersionBounds.VersionBounds
+ Hix.Data.VersionBounds: instance GHC.Generics.Generic Hix.Data.VersionBounds.Bound
+ Hix.Data.VersionBounds: instance GHC.Generics.Generic Hix.Data.VersionBounds.VersionBounds
+ Hix.Data.VersionBounds: instance GHC.Show.Show Hix.Data.VersionBounds.Bound
+ Hix.Data.VersionBounds: instance GHC.Show.Show Hix.Data.VersionBounds.VersionBounds
+ Hix.Data.VersionBounds: instance Hix.Class.EncodeNix.EncodeNix Hix.Data.VersionBounds.VersionBounds
+ Hix.Data.VersionBounds: majorRange :: VersionBounds -> VersionRange
+ Hix.Data.VersionBounds: maybeMajorRange :: VersionBounds -> Maybe VersionRange
+ Hix.Data.VersionBounds: maybeRange :: (Bound -> Version -> VersionRange) -> VersionBounds -> Maybe VersionRange
+ Hix.Data.VersionBounds: unsafeVersionBoundsFromRange :: VersionRange -> VersionBounds
+ Hix.Data.VersionBounds: versionBounds :: Version -> Version -> VersionBounds
+ Hix.Data.VersionBounds: withLower :: Version -> VersionBounds -> VersionBounds
+ Hix.Data.VersionBounds: withUpper :: Version -> VersionBounds -> VersionBounds
+ Hix.Error: BootstrapError :: Text -> Error
+ Hix.Error: Client :: Text -> Error
+ Hix.Error: EnvError :: Text -> Error
+ Hix.Error: Fatal :: Text -> Error
+ Hix.Error: GhciError :: Text -> Error
+ Hix.Error: NewError :: Text -> Error
+ Hix.Error: NoMatch :: Text -> Error
+ Hix.Error: PreprocError :: Text -> Error
+ Hix.Error: catchIO :: (Text -> ExceptT Error IO a) -> IO a -> ExceptT Error IO a
+ Hix.Error: data Error
+ Hix.Error: note :: Text -> Maybe a -> ExceptT Error IO a
+ Hix.Error: pathText :: Path b t -> Text
+ Hix.Error: prefixedError :: MonadIO m => Text -> Text -> m ()
+ Hix.Error: printBootstrapError :: MonadIO m => Text -> m ()
+ Hix.Error: printEnvError :: MonadIO m => Text -> m ()
+ Hix.Error: printError :: MonadIO m => Bool -> Error -> m ()
+ Hix.Error: printFatalError :: MonadIO m => Text -> m ()
+ Hix.Error: printGhciError :: MonadIO m => Text -> m ()
+ Hix.Error: printNewError :: MonadIO m => Text -> m ()
+ Hix.Error: printPreprocError :: MonadIO m => Text -> m ()
+ Hix.Error: sourceError :: Text -> Path b t -> Text
+ Hix.Error: tryIO :: IO a -> ExceptT Error IO a
+ Hix.Error: tryIOWith :: (Text -> Error) -> IO a -> ExceptT Error IO a
+ Hix.Hackage: HackageVersions :: [String] -> HackageVersions
+ Hix.Hackage: [$sel:versions:HackageVersions] :: HackageVersions -> [String]
+ Hix.Hackage: data HackageVersions
+ Hix.Hackage: fetchHashHackage :: PackageId -> M SourceHash
+ Hix.Hackage: fetchHashHackageCached :: IORef (Map Text SourceHash) -> PackageId -> M SourceHash
+ Hix.Hackage: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Hackage.HackageVersions
+ Hix.Hackage: instance GHC.Classes.Eq Hix.Hackage.HackageVersions
+ Hix.Hackage: instance GHC.Generics.Generic Hix.Hackage.HackageVersions
+ Hix.Hackage: instance GHC.Show.Show Hix.Hackage.HackageVersions
+ Hix.Hackage: latestVersionHackage :: Manager -> PackageName -> M (Maybe Version)
+ Hix.Hackage: parseResult :: LByteString -> M (Either Text [Version])
+ Hix.Hackage: parseVersion :: String -> Either (String, String) Version
+ Hix.Hackage: versionsHackage :: Manager -> PackageName -> M [Version]
+ Hix.Json: jsonConfigE :: FromJSON a => (Text -> Error) -> Either a JsonConfig -> M a
+ Hix.Log: debug :: Text -> M ()
+ Hix.Log: debugP :: Doc -> M ()
+ Hix.Log: error :: Text -> M ()
+ Hix.Log: info :: Text -> M ()
+ Hix.Log: infoCont :: Text -> M ()
+ Hix.Log: infoPlain :: Text -> M ()
+ Hix.Log: log :: LogLevel -> Text -> M ()
+ Hix.Log: logWith :: (LogLevel -> Text -> IO ()) -> LogLevel -> Text -> M ()
+ Hix.Log: verbose :: Text -> M ()
+ Hix.Log: warn :: Text -> M ()
+ Hix.Managed.Build: buildConstraints :: EnvBuilder -> EnvContext -> Text -> SolverState -> M (Maybe (Versions, Overrides, BuildStatus))
+ Hix.Managed.Build: buildMutation :: EnvBuilder -> EnvContext -> MutationState -> BuildMutation -> M (Maybe MutationState)
+ Hix.Managed.Build: buildVersions :: EnvBuilder -> EnvContext -> Text -> Versions -> [PackageId] -> M (Overrides, BuildStatus)
+ Hix.Managed.Build: convergeMutations :: Pretty a => MutationHandlers a s -> BuildConfig -> EnvBuilder -> EnvContext -> StageState a s -> [DepMutation a] -> M (StageState a s)
+ Hix.Managed.Build: logBuildInputs :: EnvName -> Text -> [PackageId] -> M ()
+ Hix.Managed.Build: logBuildResult :: Text -> BuildStatus -> M ()
+ Hix.Managed.Build: logMutationResult :: MutableDep -> MutationResult s -> M ()
+ Hix.Managed.Build: processQuery :: Pretty a => (QueryDep -> M (Maybe (DepMutation a))) -> MutationHandlers a s -> BuildConfig -> StageContext -> s -> M (StageState a s)
+ Hix.Managed.Build: reinstallableCandidates :: (QueryDep -> M (Maybe (DepMutation a))) -> Query -> M [DepMutation a]
+ Hix.Managed.Build: updateMutationState :: (Version -> VersionBounds -> VersionBounds) -> Versions -> Overrides -> MutationState -> MutationState
+ Hix.Managed.Build: validateMutation :: EnvBuilder -> EnvContext -> MutationHandlers a s -> StageState a s -> DepMutation a -> M (StageState a s)
+ Hix.Managed.Build.Mutation: buildCandidate :: (BuildMutation -> M (Maybe MutationState)) -> (Version -> VersionBounds -> VersionBounds) -> (MutableId -> PackageId -> MutationConstraints -> MutationConstraints) -> SolverState -> MutableDep -> Version -> M (Maybe (MutableId, SolverState, MutationState))
+ Hix.Managed.Build.Mutation: candidateConstraints :: MutableId -> EnvConstraints -> EnvConstraints
+ Hix.Managed.Build.Mutation: candidateMutation :: SolverState -> MutableId -> (Version -> VersionBounds -> VersionBounds) -> BuildMutation
+ Hix.Managed.Build.Mutation: updateConstraints :: (MutableId -> PackageId -> MutationConstraints -> MutationConstraints) -> MutableId -> MutationState -> EnvConstraints -> EnvConstraints
+ Hix.Managed.Build.Single: buildVersions :: EnvBuilder -> EnvContext -> Text -> MutableVersions -> M BuildStatus
+ Hix.Managed.Build.Solve: logNonReinstallable :: NonEmpty PackageId -> M ()
+ Hix.Managed.Build.Solve: processSolverPlan :: EnvDeps -> SolverPlan -> M SolverChanges
+ Hix.Managed.Build.Solve: solveMutation :: CabalHandlers -> EnvDeps -> SolverState -> M (Maybe SolverChanges)
+ Hix.Managed.BuildOutput: buildOutput :: ProjectResult -> BuildOutput
+ Hix.Managed.BuildOutput: buildOutputFromLists :: [ModifiedId] -> [MutableDep] -> [MutableDep] -> BuildOutput
+ Hix.Managed.BuildOutput: modifiedId :: DepResult -> ModifiedId
+ Hix.Managed.BuildOutput: outputResult :: BuildOutput -> OutputTarget -> OutputFormat -> M ()
+ Hix.Managed.BuildOutput.CommitMsg: candidateList :: [ModifiedId] -> [Text]
+ Hix.Managed.BuildOutput.CommitMsg: commit :: BuildOutput -> Maybe (Text, [Text])
+ Hix.Managed.BuildOutput.CommitMsg: commitBody :: [ModifiedId] -> [Text]
+ Hix.Managed.BuildOutput.CommitMsg: commitMessage :: Int -> Text -> Text
+ Hix.Managed.BuildOutput.CommitMsg: formatCommit :: BuildOutput -> Maybe Text
+ Hix.Managed.BuildOutput.GithubActionsPr: envVarWriter :: M OutputWriter
+ Hix.Managed.BuildOutput.GithubActionsPr: formatOutput :: Text -> [Text] -> [Text]
+ Hix.Managed.BuildOutput.GithubActionsPr: formatOutputs :: Map Text [Text] -> [Text]
+ Hix.Managed.BuildOutput.GithubActionsPr: githubActionsPr :: BuildOutput -> OutputTarget -> M ()
+ Hix.Managed.BuildOutput.GithubActionsPr: modifiedOutputs :: Text -> Text -> [Text] -> Map Text [Text]
+ Hix.Managed.BuildOutput.GithubActionsPr: writeOutputs :: OutputWriter -> Map Text [Text] -> M ()
+ Hix.Managed.Bump.App: bumpCli :: BumpOptions -> M ()
+ Hix.Managed.Bump.Candidates: candidatesBump :: BuildHandlers -> QueryDep -> M (Maybe (DepMutation Bump))
+ Hix.Managed.Bump.Candidates: isBump :: Version -> Maybe Version -> Bool
+ Hix.Managed.Bump.Optimize: bumpBuild :: BuildHandlers -> BuildConfig -> StageContext -> M StageResult
+ Hix.Managed.Bump.Optimize: bumpBuildStage :: BuildHandlers -> BuildConfig -> Flow BuildStatus
+ Hix.Managed.Bump.Optimize: bumpOptimizeMain :: BuildHandlers -> ProjectContext -> M ProjectResult
+ Hix.Managed.Bump.Optimize: bumpReportStage :: BuildHandlers -> Flow BuildStatus
+ Hix.Managed.Bump.Optimize: bumpSolverParams :: EnvDeps -> CabalHandlers -> Initial MutationState -> EnvConstraints
+ Hix.Managed.Bump.Optimize: bumpStages :: BuildHandlers -> BuildConfig -> Flow BuildStatus
+ Hix.Managed.Bump.Optimize: failure :: Natural -> Text
+ Hix.Managed.Bump.Optimize: success :: Map MutableDep BuildSuccess -> Natural -> Text
+ Hix.Managed.Cabal.Changes: SolverChanges :: Versions -> [PackageId] -> Versions -> SolverChanges
+ Hix.Managed.Cabal.Changes: SolverPlan :: [PackageId] -> [PackageId] -> Maybe (NonEmpty PackageId) -> SolverPlan
+ Hix.Managed.Cabal.Changes: [$sel:changes:SolverPlan] :: SolverPlan -> [PackageId]
+ Hix.Managed.Cabal.Changes: [$sel:matching:SolverPlan] :: SolverPlan -> [PackageId]
+ Hix.Managed.Cabal.Changes: [$sel:nonReinstallable:SolverPlan] :: SolverPlan -> Maybe (NonEmpty PackageId)
+ Hix.Managed.Cabal.Changes: [$sel:overrides:SolverChanges] :: SolverChanges -> [PackageId]
+ Hix.Managed.Cabal.Changes: [$sel:projectDeps:SolverChanges] :: SolverChanges -> Versions
+ Hix.Managed.Cabal.Changes: [$sel:versions:SolverChanges] :: SolverChanges -> Versions
+ Hix.Managed.Cabal.Changes: data SolverChanges
+ Hix.Managed.Cabal.Changes: data SolverPlan
+ Hix.Managed.Cabal.Changes: instance Distribution.Pretty.Pretty Hix.Managed.Cabal.Changes.SolverChanges
+ Hix.Managed.Cabal.Changes: instance Distribution.Pretty.Pretty Hix.Managed.Cabal.Changes.SolverPlan
+ Hix.Managed.Cabal.Changes: instance GHC.Classes.Eq Hix.Managed.Cabal.Changes.SolverChanges
+ Hix.Managed.Cabal.Changes: instance GHC.Classes.Eq Hix.Managed.Cabal.Changes.SolverPlan
+ Hix.Managed.Cabal.Changes: instance GHC.Generics.Generic Hix.Managed.Cabal.Changes.SolverChanges
+ Hix.Managed.Cabal.Changes: instance GHC.Generics.Generic Hix.Managed.Cabal.Changes.SolverPlan
+ Hix.Managed.Cabal.Changes: instance GHC.Show.Show Hix.Managed.Cabal.Changes.SolverChanges
+ Hix.Managed.Cabal.Changes: instance GHC.Show.Show Hix.Managed.Cabal.Changes.SolverPlan
+ Hix.Managed.Cabal.Changes: solverPlan :: SolverInstallPlan -> SolverPlan
+ Hix.Managed.Cabal.Config: isNonReinstallable :: PackageName -> Bool
+ Hix.Managed.Cabal.Config: isNonReinstallableDep :: MutableDep -> Bool
+ Hix.Managed.Cabal.Config: isNonReinstallableId :: PackageId -> Bool
+ Hix.Managed.Cabal.Config: isReinstallable :: PackageName -> Bool
+ Hix.Managed.Cabal.Config: isReinstallableId :: PackageId -> Bool
+ Hix.Managed.Cabal.Config: nonReinstallableNames :: Set PackageName
+ Hix.Managed.Cabal.Data.Config: CabalConfig :: Maybe HackageIndexState -> CabalConfig
+ Hix.Managed.Cabal.Data.Config: GhcDbSynthetic :: GhcPackages -> GhcDb
+ Hix.Managed.Cabal.Data.Config: GhcDbSystem :: Maybe GhcPath -> GhcDb
+ Hix.Managed.Cabal.Data.Config: GhcPath :: Path Abs Dir -> GhcPath
+ Hix.Managed.Cabal.Data.Config: HackageIndexState :: Timestamp -> HackageIndexState
+ Hix.Managed.Cabal.Data.Config: HackageRepoName :: Text -> HackageRepoName
+ Hix.Managed.Cabal.Data.Config: SolveConfig :: HackageRepoName -> Verbosity -> Maybe GhcPath -> Bool -> CabalConfig -> SolveConfig
+ Hix.Managed.Cabal.Data.Config: [$sel:allowBoot:SolveConfig] :: SolveConfig -> Bool
+ Hix.Managed.Cabal.Data.Config: [$sel:cabal:SolveConfig] :: SolveConfig -> CabalConfig
+ Hix.Managed.Cabal.Data.Config: [$sel:ghc:SolveConfig] :: SolveConfig -> Maybe GhcPath
+ Hix.Managed.Cabal.Data.Config: [$sel:hackageRepoName:SolveConfig] :: SolveConfig -> HackageRepoName
+ Hix.Managed.Cabal.Data.Config: [$sel:indexState:CabalConfig] :: CabalConfig -> Maybe HackageIndexState
+ Hix.Managed.Cabal.Data.Config: [$sel:verbosity:SolveConfig] :: SolveConfig -> Verbosity
+ Hix.Managed.Cabal.Data.Config: data CabalConfig
+ Hix.Managed.Cabal.Data.Config: data GhcDb
+ Hix.Managed.Cabal.Data.Config: data SolveConfig
+ Hix.Managed.Cabal.Data.Config: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Managed.Cabal.Data.Config.GhcDb
+ Hix.Managed.Cabal.Data.Config: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Managed.Cabal.Data.Config.GhcPath
+ Hix.Managed.Cabal.Data.Config: instance Data.Default.Class.Default Hix.Managed.Cabal.Data.Config.CabalConfig
+ Hix.Managed.Cabal.Data.Config: instance Data.Default.Class.Default Hix.Managed.Cabal.Data.Config.HackageRepoName
+ Hix.Managed.Cabal.Data.Config: instance Data.Default.Class.Default Hix.Managed.Cabal.Data.Config.SolveConfig
+ Hix.Managed.Cabal.Data.Config: instance Data.String.IsString Hix.Managed.Cabal.Data.Config.HackageRepoName
+ Hix.Managed.Cabal.Data.Config: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.Config.CabalConfig
+ Hix.Managed.Cabal.Data.Config: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.Config.GhcDb
+ Hix.Managed.Cabal.Data.Config: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.Config.GhcPath
+ Hix.Managed.Cabal.Data.Config: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.Config.HackageIndexState
+ Hix.Managed.Cabal.Data.Config: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.Config.HackageRepoName
+ Hix.Managed.Cabal.Data.Config: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.Config.SolveConfig
+ Hix.Managed.Cabal.Data.Config: instance GHC.Classes.Ord Hix.Managed.Cabal.Data.Config.HackageRepoName
+ Hix.Managed.Cabal.Data.Config: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.Config.CabalConfig
+ Hix.Managed.Cabal.Data.Config: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.Config.GhcDb
+ Hix.Managed.Cabal.Data.Config: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.Config.GhcPath
+ Hix.Managed.Cabal.Data.Config: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.Config.HackageIndexState
+ Hix.Managed.Cabal.Data.Config: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.Config.HackageRepoName
+ Hix.Managed.Cabal.Data.Config: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.Config.SolveConfig
+ Hix.Managed.Cabal.Data.Config: instance GHC.Show.Show Hix.Managed.Cabal.Data.Config.CabalConfig
+ Hix.Managed.Cabal.Data.Config: instance GHC.Show.Show Hix.Managed.Cabal.Data.Config.GhcDb
+ Hix.Managed.Cabal.Data.Config: instance GHC.Show.Show Hix.Managed.Cabal.Data.Config.GhcPath
+ Hix.Managed.Cabal.Data.Config: instance GHC.Show.Show Hix.Managed.Cabal.Data.Config.HackageIndexState
+ Hix.Managed.Cabal.Data.Config: instance GHC.Show.Show Hix.Managed.Cabal.Data.Config.HackageRepoName
+ Hix.Managed.Cabal.Data.Config: instance GHC.Show.Show Hix.Managed.Cabal.Data.Config.SolveConfig
+ Hix.Managed.Cabal.Data.Config: newtype GhcPath
+ Hix.Managed.Cabal.Data.Config: newtype HackageIndexState
+ Hix.Managed.Cabal.Data.Config: newtype HackageRepoName
+ Hix.Managed.Cabal.Data.Packages: GhcPackages :: InstalledPackages -> SourcePackages -> GhcPackages
+ Hix.Managed.Cabal.Data.Packages: InstalledPackages :: [(PackageId, [PackageId])] -> InstalledPackages
+ Hix.Managed.Cabal.Data.Packages: [$sel:available:GhcPackages] :: GhcPackages -> SourcePackages
+ Hix.Managed.Cabal.Data.Packages: [$sel:installed:GhcPackages] :: GhcPackages -> InstalledPackages
+ Hix.Managed.Cabal.Data.Packages: data GhcPackages
+ Hix.Managed.Cabal.Data.Packages: instance GHC.Base.Monoid Hix.Managed.Cabal.Data.Packages.InstalledPackages
+ Hix.Managed.Cabal.Data.Packages: instance GHC.Base.Semigroup Hix.Managed.Cabal.Data.Packages.InstalledPackages
+ Hix.Managed.Cabal.Data.Packages: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.Packages.GhcPackages
+ Hix.Managed.Cabal.Data.Packages: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.Packages.InstalledPackages
+ Hix.Managed.Cabal.Data.Packages: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.Packages.GhcPackages
+ Hix.Managed.Cabal.Data.Packages: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.Packages.InstalledPackages
+ Hix.Managed.Cabal.Data.Packages: instance GHC.IsList.IsList Hix.Managed.Cabal.Data.Packages.InstalledPackages
+ Hix.Managed.Cabal.Data.Packages: instance GHC.Show.Show Hix.Managed.Cabal.Data.Packages.GhcPackages
+ Hix.Managed.Cabal.Data.Packages: instance GHC.Show.Show Hix.Managed.Cabal.Data.Packages.InstalledPackages
+ Hix.Managed.Cabal.Data.Packages: newtype InstalledPackages
+ Hix.Managed.Cabal.Data.SolveResources: SolveResources :: SolveConfig -> SolveFlags -> Platform -> CompilerInfo -> PkgConfigDb -> InstalledPackageIndex -> SourcePackageDb -> (DepResolverParams -> DepResolverParams) -> SolveResources
+ Hix.Managed.Cabal.Data.SolveResources: [$sel:compiler:SolveResources] :: SolveResources -> CompilerInfo
+ Hix.Managed.Cabal.Data.SolveResources: [$sel:conf:SolveResources] :: SolveResources -> SolveConfig
+ Hix.Managed.Cabal.Data.SolveResources: [$sel:flags:SolveResources] :: SolveResources -> SolveFlags
+ Hix.Managed.Cabal.Data.SolveResources: [$sel:installedPkgIndex:SolveResources] :: SolveResources -> InstalledPackageIndex
+ Hix.Managed.Cabal.Data.SolveResources: [$sel:pkgConfigDb:SolveResources] :: SolveResources -> PkgConfigDb
+ Hix.Managed.Cabal.Data.SolveResources: [$sel:platform:SolveResources] :: SolveResources -> Platform
+ Hix.Managed.Cabal.Data.SolveResources: [$sel:solverParams:SolveResources] :: SolveResources -> DepResolverParams -> DepResolverParams
+ Hix.Managed.Cabal.Data.SolveResources: [$sel:sourcePkgDb:SolveResources] :: SolveResources -> SourcePackageDb
+ Hix.Managed.Cabal.Data.SolveResources: data SolveResources
+ Hix.Managed.Cabal.Data.SolveTarget: SolveTarget :: PackageSpecifier UnresolvedSourcePackage -> [PackagePreference] -> SolveTarget
+ Hix.Managed.Cabal.Data.SolveTarget: [$sel:dep:SolveTarget] :: SolveTarget -> PackageSpecifier UnresolvedSourcePackage
+ Hix.Managed.Cabal.Data.SolveTarget: [$sel:prefs:SolveTarget] :: SolveTarget -> [PackagePreference]
+ Hix.Managed.Cabal.Data.SolveTarget: data SolveTarget
+ Hix.Managed.Cabal.Data.SolveTarget: instance Distribution.Pretty.Pretty Hix.Managed.Cabal.Data.SolveTarget.SolveTarget
+ Hix.Managed.Cabal.Data.SolveTarget: prettyPref :: PackagePreference -> Doc
+ Hix.Managed.Cabal.Data.SolveTarget: prettySpec :: PackageSpecifier UnresolvedSourcePackage -> Doc
+ Hix.Managed.Cabal.Data.SolverState: SolverFlags :: Bool -> SolverFlags
+ Hix.Managed.Cabal.Data.SolverState: [$sel:allowNewer:SolverFlags] :: SolverFlags -> Bool
+ Hix.Managed.Cabal.Data.SolverState: compileSolverFlags :: SolverFlags -> DepResolverParams -> DepResolverParams
+ Hix.Managed.Cabal.Data.SolverState: data SolverFlags
+ Hix.Managed.Cabal.Data.SolverState: data SolverState
+ Hix.Managed.Cabal.Data.SolverState: instance Data.Default.Class.Default Hix.Managed.Cabal.Data.SolverState.SolverFlags
+ Hix.Managed.Cabal.Data.SolverState: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.SolverState.SolverFlags
+ Hix.Managed.Cabal.Data.SolverState: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.SolverState.SolverState
+ Hix.Managed.Cabal.Data.SolverState: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.SolverState.SolverFlags
+ Hix.Managed.Cabal.Data.SolverState: instance GHC.Records.HasField "constraints" Hix.Managed.Cabal.Data.SolverState.SolverState Hix.Managed.Data.Constraints.EnvConstraints
+ Hix.Managed.Cabal.Data.SolverState: instance GHC.Records.HasField "flags" Hix.Managed.Cabal.Data.SolverState.SolverState Hix.Managed.Cabal.Data.SolverState.SolverFlags
+ Hix.Managed.Cabal.Data.SolverState: instance GHC.Show.Show Hix.Managed.Cabal.Data.SolverState.SolverFlags
+ Hix.Managed.Cabal.Data.SolverState: instance GHC.Show.Show Hix.Managed.Cabal.Data.SolverState.SolverState
+ Hix.Managed.Cabal.Data.SolverState: pattern SolverState :: EnvConstraints -> SolverFlags -> SolverState
+ Hix.Managed.Cabal.Data.SolverState: solverState :: Ranges -> EnvDeps -> EnvConstraints -> SolverFlags -> SolverState
+ Hix.Managed.Cabal.Data.SolverState: updateSolverState :: (EnvConstraints -> EnvConstraints) -> SolverState -> SolverState
+ Hix.Managed.Cabal.Data.SourcePackage: SourcePackageDeps :: Map Version [Dep] -> SourcePackageDeps
+ Hix.Managed.Cabal.Data.SourcePackage: SourcePackageVersions :: Map PackageName [Version] -> SourcePackageVersions
+ Hix.Managed.Cabal.Data.SourcePackage: SourcePackages :: Map PackageName SourcePackageDeps -> SourcePackages
+ Hix.Managed.Cabal.Data.SourcePackage: instance Distribution.Pretty.Pretty Hix.Managed.Cabal.Data.SourcePackage.SourcePackageDeps
+ Hix.Managed.Cabal.Data.SourcePackage: instance Distribution.Pretty.Pretty Hix.Managed.Cabal.Data.SourcePackage.SourcePackageVersions
+ Hix.Managed.Cabal.Data.SourcePackage: instance Distribution.Pretty.Pretty Hix.Managed.Cabal.Data.SourcePackage.SourcePackages
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Base.Monoid Hix.Managed.Cabal.Data.SourcePackage.SourcePackageDeps
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Base.Monoid Hix.Managed.Cabal.Data.SourcePackage.SourcePackageVersions
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Base.Monoid Hix.Managed.Cabal.Data.SourcePackage.SourcePackages
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Base.Semigroup Hix.Managed.Cabal.Data.SourcePackage.SourcePackageDeps
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Base.Semigroup Hix.Managed.Cabal.Data.SourcePackage.SourcePackageVersions
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Base.Semigroup Hix.Managed.Cabal.Data.SourcePackage.SourcePackages
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.SourcePackage.SourcePackageDeps
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.SourcePackage.SourcePackageVersions
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Classes.Eq Hix.Managed.Cabal.Data.SourcePackage.SourcePackages
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.SourcePackage.SourcePackageDeps
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.SourcePackage.SourcePackageVersions
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Generics.Generic Hix.Managed.Cabal.Data.SourcePackage.SourcePackages
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.IsList.IsList Hix.Managed.Cabal.Data.SourcePackage.SourcePackageDeps
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.IsList.IsList Hix.Managed.Cabal.Data.SourcePackage.SourcePackageVersions
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.IsList.IsList Hix.Managed.Cabal.Data.SourcePackage.SourcePackages
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Show.Show Hix.Managed.Cabal.Data.SourcePackage.SourcePackageDeps
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Show.Show Hix.Managed.Cabal.Data.SourcePackage.SourcePackageVersions
+ Hix.Managed.Cabal.Data.SourcePackage: instance GHC.Show.Show Hix.Managed.Cabal.Data.SourcePackage.SourcePackages
+ Hix.Managed.Cabal.Data.SourcePackage: instance Hix.Class.Map.NMap Hix.Managed.Cabal.Data.SourcePackage.SourcePackageDeps Distribution.Types.Version.Version [Hix.Data.Dep.Dep] Hix.Class.Map.LookupMonoid
+ Hix.Managed.Cabal.Data.SourcePackage: instance Hix.Class.Map.NMap Hix.Managed.Cabal.Data.SourcePackage.SourcePackageVersions Hix.Data.PackageName.PackageName [Distribution.Types.Version.Version] Hix.Class.Map.LookupMaybe
+ Hix.Managed.Cabal.Data.SourcePackage: instance Hix.Class.Map.NMap Hix.Managed.Cabal.Data.SourcePackage.SourcePackages Hix.Data.PackageName.PackageName Hix.Managed.Cabal.Data.SourcePackage.SourcePackageDeps Hix.Class.Map.LookupMaybe
+ Hix.Managed.Cabal.Data.SourcePackage: newtype SourcePackageDeps
+ Hix.Managed.Cabal.Data.SourcePackage: newtype SourcePackageVersions
+ Hix.Managed.Cabal.Data.SourcePackage: newtype SourcePackages
+ Hix.Managed.Cabal.Init: SolveFlags :: GlobalFlags -> NixStyleFlags () -> SolveFlags
+ Hix.Managed.Cabal.Init: [$sel:global:SolveFlags] :: SolveFlags -> GlobalFlags
+ Hix.Managed.Cabal.Init: [$sel:main:SolveFlags] :: SolveFlags -> NixStyleFlags ()
+ Hix.Managed.Cabal.Init: badCacheDir :: Text -> Error
+ Hix.Managed.Cabal.Init: data SolveFlags
+ Hix.Managed.Cabal.Init: emptySolveFlags :: SolveFlags
+ Hix.Managed.Cabal.Init: globalFlags :: RemoteRepo -> FilePath -> GlobalFlags
+ Hix.Managed.Cabal.Init: hackageRepo :: HackageRepoName -> M RemoteRepo
+ Hix.Managed.Cabal.Init: initialize :: SolveConfig -> M SolveFlags
+ Hix.Managed.Cabal.Init: mainFlags :: SolveConfig -> NixStyleFlags ()
+ Hix.Managed.Cabal.Installed: installedVersion :: InstalledPackageIndex -> PackageName -> Maybe Version
+ Hix.Managed.Cabal.Mock: mockSolveResources :: Packages ManagedPackage -> GhcPackages -> SolveResources
+ Hix.Managed.Cabal.Mock.InstalledPackage: installedPackageInfo :: PackageId -> [UnitId] -> InstalledPackageInfo
+ Hix.Managed.Cabal.Mock.InstalledPackage: mockInstalledPackageIndex :: InstalledPackages -> InstalledPackageIndex
+ Hix.Managed.Cabal.Mock.InstalledPackage: mockUnitId :: PackageId -> UnitId
+ Hix.Managed.Cabal.Mock.SourcePackage: allDep :: Dep -> SourcePackageDeps -> SourcePackageDeps
+ Hix.Managed.Cabal.Mock.SourcePackage: allDeps :: [Dep] -> SourcePackageDeps -> SourcePackageDeps
+ Hix.Managed.Cabal.Mock.SourcePackage: dbWithManaged :: Packages ManagedPackage -> SourcePackageDb -> SourcePackageDb
+ Hix.Managed.Cabal.Mock.SourcePackage: managedPackageIndex :: Packages ManagedPackage -> PackageIndex UnresolvedSourcePackage
+ Hix.Managed.Cabal.Mock.SourcePackage: managedSourcePackage :: ManagedPackage -> UnresolvedSourcePackage
+ Hix.Managed.Cabal.Mock.SourcePackage: managedSourcePackageVersions :: Packages ManagedPackage -> SourcePackageVersions
+ Hix.Managed.Cabal.Mock.SourcePackage: mockSourcePackage :: PackageName -> Version -> [Dep] -> UnresolvedSourcePackage
+ Hix.Managed.Cabal.Mock.SourcePackage: mockSourcePackageDb :: SourcePackages -> SourcePackageDb
+ Hix.Managed.Cabal.Mock.SourcePackage: queryPackages :: SourcePackages -> PackageName -> M [Version]
+ Hix.Managed.Cabal.Mock.SourcePackage: queryPackagesLatest :: SourcePackages -> PackageName -> M (Maybe Version)
+ Hix.Managed.Cabal.Mock.SourcePackage: queryVersions :: SourcePackageVersions -> PackageName -> M [Version]
+ Hix.Managed.Cabal.Mock.SourcePackage: queryVersionsLatest :: SourcePackageVersions -> PackageName -> M (Maybe Version)
+ Hix.Managed.Cabal.Mock.SourcePackage: sourcePackageVersions :: SourcePackages -> SourcePackageVersions
+ Hix.Managed.Cabal.Print: printPlan :: SolverInstallPlan -> M ()
+ Hix.Managed.Cabal.Print: showPackage :: SolverPlanPackage -> String
+ Hix.Managed.Cabal.Repo: IndexMismatch :: IndexProblem
+ Hix.Managed.Cabal.Repo: IndexMissing :: IndexProblem
+ Hix.Managed.Cabal.Repo: IndexOutdated :: IndexProblem
+ Hix.Managed.Cabal.Repo: data IndexProblem
+ Hix.Managed.Cabal.Repo: ensureHackageIndex :: SolveConfig -> GlobalFlags -> NixStyleFlags () -> M ()
+ Hix.Managed.Cabal.Repo: fullHackageRepo :: SolveConfig -> RepoContext -> M Repo
+ Hix.Managed.Cabal.Repo: indexOutdated :: Path Abs File -> IO Bool
+ Hix.Managed.Cabal.Repo: indexPath :: Repo -> M (Path Abs File)
+ Hix.Managed.Cabal.Repo: indexProblem :: SolveConfig -> RepoContext -> Repo -> Path Abs File -> M (Maybe IndexProblem)
+ Hix.Managed.Cabal.Repo: instance GHC.Classes.Eq Hix.Managed.Cabal.Repo.IndexProblem
+ Hix.Managed.Cabal.Repo: instance GHC.Generics.Generic Hix.Managed.Cabal.Repo.IndexProblem
+ Hix.Managed.Cabal.Repo: instance GHC.Show.Show Hix.Managed.Cabal.Repo.IndexProblem
+ Hix.Managed.Cabal.Repo: matchIndexState :: Verbosity -> RepoContext -> Repo -> HackageIndexState -> M (Maybe IndexProblem)
+ Hix.Managed.Cabal.Repo: updateIndex :: SolveConfig -> GlobalFlags -> NixStyleFlags () -> IndexProblem -> M ()
+ Hix.Managed.Cabal.Repo: updateRequest :: SolveConfig -> String
+ Hix.Managed.Cabal.Repo: withRepoContextM :: SolveConfig -> GlobalFlags -> (RepoContext -> M a) -> M a
+ Hix.Managed.Cabal.Resources: acquire :: Packages ManagedPackage -> CabalConfig -> GhcDb -> M SolveResources
+ Hix.Managed.Cabal.Resources: packageDbs :: PackageDBStack
+ Hix.Managed.Cabal.Resources: resources :: Packages ManagedPackage -> SolveConfig -> M SolveResources
+ Hix.Managed.Cabal.Solve: Unresolvable :: Text -> Unresolvable
+ Hix.Managed.Cabal.Solve: instance Data.String.IsString Hix.Managed.Cabal.Solve.Unresolvable
+ Hix.Managed.Cabal.Solve: instance GHC.Classes.Eq Hix.Managed.Cabal.Solve.Unresolvable
+ Hix.Managed.Cabal.Solve: instance GHC.Classes.Ord Hix.Managed.Cabal.Solve.Unresolvable
+ Hix.Managed.Cabal.Solve: instance GHC.Generics.Generic Hix.Managed.Cabal.Solve.Unresolvable
+ Hix.Managed.Cabal.Solve: instance GHC.Show.Show Hix.Managed.Cabal.Solve.Unresolvable
+ Hix.Managed.Cabal.Solve: logMsg :: Verbosity -> String -> IO a -> IO a
+ Hix.Managed.Cabal.Solve: newtype Unresolvable
+ Hix.Managed.Cabal.Solve: solveForTargets :: SolveResources -> (DepResolverParams -> DepResolverParams) -> [SolveTarget] -> M (Either Unresolvable SolverInstallPlan)
+ Hix.Managed.Cabal.Solve: solveSpecifiers :: SolveResources -> (DepResolverParams -> DepResolverParams) -> [PackageSpecifier UnresolvedSourcePackage] -> [PackagePreference] -> IO (Either String SolverInstallPlan)
+ Hix.Managed.Cabal.Solve: solveWithCabal :: SolveResources -> SolverState -> M (Maybe SolverPlan)
+ Hix.Managed.Cabal.Targets: reifyBounds :: VersionBounds -> Maybe VersionRange
+ Hix.Managed.Cabal.Targets: solveTarget :: PackageName -> MutationConstraints -> SolveTarget
+ Hix.Managed.Cabal.Targets: solveTargets :: EnvConstraints -> [SolveTarget]
+ Hix.Managed.Constraints: explicitBounds :: Ranges -> EnvConstraints
+ Hix.Managed.Constraints: forDeps :: (PackageName -> MutationConstraints) -> Set MutableDep -> EnvConstraints
+ Hix.Managed.Constraints: fromVersions :: (Version -> VersionBounds) -> MutableVersions -> EnvConstraints
+ Hix.Managed.Constraints: noBounds :: MutationConstraints
+ Hix.Managed.Constraints: preferInstalled :: Set MutableDep -> EnvConstraints
+ Hix.Managed.Constraints: preferRanges :: Ranges -> EnvConstraints
+ Hix.Managed.Constraints: preferVersions :: Versions -> EnvConstraints
+ Hix.Managed.Data.BuildConfig: BuildConfig :: Natural -> Natural -> Natural -> Bool -> Bool -> Bool -> BuildConfig
+ Hix.Managed.Data.BuildConfig: [$sel:buildOutput:BuildConfig] :: BuildConfig -> Bool
+ Hix.Managed.Data.BuildConfig: [$sel:lookup:BuildConfig] :: BuildConfig -> Bool
+ Hix.Managed.Data.BuildConfig: [$sel:maxFailedPost:BuildConfig] :: BuildConfig -> Natural
+ Hix.Managed.Data.BuildConfig: [$sel:maxFailedPre:BuildConfig] :: BuildConfig -> Natural
+ Hix.Managed.Data.BuildConfig: [$sel:maxIterations:BuildConfig] :: BuildConfig -> Natural
+ Hix.Managed.Data.BuildConfig: [$sel:validate:BuildConfig] :: BuildConfig -> Bool
+ Hix.Managed.Data.BuildConfig: data BuildConfig
+ Hix.Managed.Data.BuildConfig: instance Data.Default.Class.Default Hix.Managed.Data.BuildConfig.BuildConfig
+ Hix.Managed.Data.BuildConfig: instance GHC.Classes.Eq Hix.Managed.Data.BuildConfig.BuildConfig
+ Hix.Managed.Data.BuildConfig: instance GHC.Generics.Generic Hix.Managed.Data.BuildConfig.BuildConfig
+ Hix.Managed.Data.BuildConfig: instance GHC.Show.Show Hix.Managed.Data.BuildConfig.BuildConfig
+ Hix.Managed.Data.BuildOutput: BuildOutput :: [ModifiedId] -> [MutableDep] -> [MutableDep] -> Maybe Text -> Maybe Text -> Maybe Text -> BuildOutput
+ Hix.Managed.Data.BuildOutput: ModifiedId :: MutableDep -> Version -> Maybe VersionBounds -> ModifiedId
+ Hix.Managed.Data.BuildOutput: [$sel:failed:BuildOutput] :: BuildOutput -> [MutableDep]
+ Hix.Managed.Data.BuildOutput: [$sel:failedNames:BuildOutput] :: BuildOutput -> Maybe Text
+ Hix.Managed.Data.BuildOutput: [$sel:modified:BuildOutput] :: BuildOutput -> [ModifiedId]
+ Hix.Managed.Data.BuildOutput: [$sel:modifiedNames:BuildOutput] :: BuildOutput -> Maybe Text
+ Hix.Managed.Data.BuildOutput: [$sel:package:ModifiedId] :: ModifiedId -> MutableDep
+ Hix.Managed.Data.BuildOutput: [$sel:range:ModifiedId] :: ModifiedId -> Maybe VersionBounds
+ Hix.Managed.Data.BuildOutput: [$sel:unmodified:BuildOutput] :: BuildOutput -> [MutableDep]
+ Hix.Managed.Data.BuildOutput: [$sel:unmodifiedNames:BuildOutput] :: BuildOutput -> Maybe Text
+ Hix.Managed.Data.BuildOutput: [$sel:version:ModifiedId] :: ModifiedId -> Version
+ Hix.Managed.Data.BuildOutput: data BuildOutput
+ Hix.Managed.Data.BuildOutput: data ModifiedId
+ Hix.Managed.Data.BuildOutput: instance Data.Aeson.Types.ToJSON.ToJSON Hix.Managed.Data.BuildOutput.BuildOutput
+ Hix.Managed.Data.BuildOutput: instance Data.Aeson.Types.ToJSON.ToJSON Hix.Managed.Data.BuildOutput.ModifiedId
+ Hix.Managed.Data.BuildOutput: instance Distribution.Pretty.Pretty Hix.Managed.Data.BuildOutput.ModifiedId
+ Hix.Managed.Data.BuildOutput: instance GHC.Classes.Eq Hix.Managed.Data.BuildOutput.BuildOutput
+ Hix.Managed.Data.BuildOutput: instance GHC.Classes.Eq Hix.Managed.Data.BuildOutput.ModifiedId
+ Hix.Managed.Data.BuildOutput: instance GHC.Generics.Generic Hix.Managed.Data.BuildOutput.BuildOutput
+ Hix.Managed.Data.BuildOutput: instance GHC.Generics.Generic Hix.Managed.Data.BuildOutput.ModifiedId
+ Hix.Managed.Data.BuildOutput: instance GHC.Show.Show Hix.Managed.Data.BuildOutput.BuildOutput
+ Hix.Managed.Data.BuildOutput: instance GHC.Show.Show Hix.Managed.Data.BuildOutput.ModifiedId
+ Hix.Managed.Data.Bump: Bump :: Version -> Version -> Bool -> Bump
+ Hix.Managed.Data.Bump: [$sel:bound:Bump] :: Bump -> Version
+ Hix.Managed.Data.Bump: [$sel:changed:Bump] :: Bump -> Bool
+ Hix.Managed.Data.Bump: [$sel:version:Bump] :: Bump -> Version
+ Hix.Managed.Data.Bump: data Bump
+ Hix.Managed.Data.Bump: instance Distribution.Pretty.Pretty Hix.Managed.Data.Bump.Bump
+ Hix.Managed.Data.Bump: instance GHC.Classes.Eq Hix.Managed.Data.Bump.Bump
+ Hix.Managed.Data.Bump: instance GHC.Generics.Generic Hix.Managed.Data.Bump.Bump
+ Hix.Managed.Data.Bump: instance GHC.Show.Show Hix.Managed.Data.Bump.Bump
+ Hix.Managed.Data.Constraints: EnvConstraints :: Map PackageName MutationConstraints -> EnvConstraints
+ Hix.Managed.Data.Constraints: MutationConstraints :: VersionBounds -> Maybe Bool -> Maybe Bool -> Maybe VersionRange -> Maybe VersionRange -> MutationConstraints
+ Hix.Managed.Data.Constraints: [$sel:force:MutationConstraints] :: MutationConstraints -> Maybe VersionRange
+ Hix.Managed.Data.Constraints: [$sel:installed:MutationConstraints] :: MutationConstraints -> Maybe Bool
+ Hix.Managed.Data.Constraints: [$sel:mutation:MutationConstraints] :: MutationConstraints -> VersionBounds
+ Hix.Managed.Data.Constraints: [$sel:oldest:MutationConstraints] :: MutationConstraints -> Maybe Bool
+ Hix.Managed.Data.Constraints: [$sel:prefer:MutationConstraints] :: MutationConstraints -> Maybe VersionRange
+ Hix.Managed.Data.Constraints: data MutationConstraints
+ Hix.Managed.Data.Constraints: instance Distribution.Pretty.Pretty Hix.Managed.Data.Constraints.EnvConstraints
+ Hix.Managed.Data.Constraints: instance Distribution.Pretty.Pretty Hix.Managed.Data.Constraints.MutationConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Base.Monoid Hix.Managed.Data.Constraints.EnvConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Base.Monoid Hix.Managed.Data.Constraints.MutationConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Base.Semigroup Hix.Managed.Data.Constraints.EnvConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Base.Semigroup Hix.Managed.Data.Constraints.MutationConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Classes.Eq Hix.Managed.Data.Constraints.EnvConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Classes.Eq Hix.Managed.Data.Constraints.MutationConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Generics.Generic Hix.Managed.Data.Constraints.EnvConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Generics.Generic Hix.Managed.Data.Constraints.MutationConstraints
+ Hix.Managed.Data.Constraints: instance GHC.IsList.IsList Hix.Managed.Data.Constraints.EnvConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Show.Show Hix.Managed.Data.Constraints.EnvConstraints
+ Hix.Managed.Data.Constraints: instance GHC.Show.Show Hix.Managed.Data.Constraints.MutationConstraints
+ Hix.Managed.Data.Constraints: instance Hix.Class.Map.NMap Hix.Managed.Data.Constraints.EnvConstraints Hix.Data.PackageName.PackageName Hix.Managed.Data.Constraints.MutationConstraints Hix.Class.Map.LookupMaybe
+ Hix.Managed.Data.Constraints: newtype EnvConstraints
+ Hix.Managed.Data.CurrentBuild: CurrentBuild :: LocalPackage -> CurrentBuild
+ Hix.Managed.Data.CurrentBuild: [$sel:target:CurrentBuild] :: CurrentBuild -> LocalPackage
+ Hix.Managed.Data.CurrentBuild: data CurrentBuild
+ Hix.Managed.Data.CurrentBuild: instance GHC.Classes.Eq Hix.Managed.Data.CurrentBuild.CurrentBuild
+ Hix.Managed.Data.CurrentBuild: instance GHC.Generics.Generic Hix.Managed.Data.CurrentBuild.CurrentBuild
+ Hix.Managed.Data.CurrentBuild: instance GHC.Show.Show Hix.Managed.Data.CurrentBuild.CurrentBuild
+ Hix.Managed.Data.Diff: BoundsDiffDetail :: These VersionDiff VersionDiff -> BoundsDiffDetail
+ Hix.Managed.Data.Diff: Changed :: Diff d a -> Change d a
+ Hix.Managed.Data.Diff: DiffAdded :: a -> Diff d a
+ Hix.Managed.Data.Diff: DiffChanged :: a -> a -> d -> Diff d a
+ Hix.Managed.Data.Diff: Unchanged :: Maybe a -> Change d a
+ Hix.Managed.Data.Diff: [$sel:detail:DiffAdded] :: Diff d a -> d
+ Hix.Managed.Data.Diff: [$sel:new:DiffAdded] :: Diff d a -> a
+ Hix.Managed.Data.Diff: [$sel:original:DiffAdded] :: Diff d a -> a
+ Hix.Managed.Data.Diff: class PrettyDiffDetail a
+ Hix.Managed.Data.Diff: data Change d a
+ Hix.Managed.Data.Diff: data Diff d a
+ Hix.Managed.Data.Diff: instance (Distribution.Pretty.Pretty a, Hix.Managed.Data.Diff.PrettyDiffDetail d) => Distribution.Pretty.Pretty (Hix.Managed.Data.Diff.Change d a)
+ Hix.Managed.Data.Diff: instance (Distribution.Pretty.Pretty a, Hix.Managed.Data.Diff.PrettyDiffDetail d) => Distribution.Pretty.Pretty (Hix.Managed.Data.Diff.Diff d a)
+ Hix.Managed.Data.Diff: instance (GHC.Classes.Eq a, GHC.Classes.Eq d) => GHC.Classes.Eq (Hix.Managed.Data.Diff.Change d a)
+ Hix.Managed.Data.Diff: instance (GHC.Classes.Eq a, GHC.Classes.Eq d) => GHC.Classes.Eq (Hix.Managed.Data.Diff.Diff d a)
+ Hix.Managed.Data.Diff: instance (GHC.Show.Show a, GHC.Show.Show d) => GHC.Show.Show (Hix.Managed.Data.Diff.Change d a)
+ Hix.Managed.Data.Diff: instance (GHC.Show.Show a, GHC.Show.Show d) => GHC.Show.Show (Hix.Managed.Data.Diff.Diff d a)
+ Hix.Managed.Data.Diff: instance GHC.Base.Functor (Hix.Managed.Data.Diff.Change d)
+ Hix.Managed.Data.Diff: instance GHC.Base.Functor (Hix.Managed.Data.Diff.Diff d)
+ Hix.Managed.Data.Diff: instance GHC.Classes.Eq Hix.Managed.Data.Diff.BoundsDiffDetail
+ Hix.Managed.Data.Diff: instance GHC.Generics.Generic (Hix.Managed.Data.Diff.Change d a)
+ Hix.Managed.Data.Diff: instance GHC.Generics.Generic (Hix.Managed.Data.Diff.Diff d a)
+ Hix.Managed.Data.Diff: instance GHC.Generics.Generic Hix.Managed.Data.Diff.BoundsDiffDetail
+ Hix.Managed.Data.Diff: instance GHC.Show.Show Hix.Managed.Data.Diff.BoundsDiffDetail
+ Hix.Managed.Data.Diff: instance Hix.Managed.Data.Diff.PrettyDiffDetail ()
+ Hix.Managed.Data.Diff: instance Hix.Managed.Data.Diff.PrettyDiffDetail Hix.Managed.Data.Diff.BoundsDiffDetail
+ Hix.Managed.Data.Diff: newtype BoundsDiffDetail
+ Hix.Managed.Data.Diff: prettyDiffDetail :: PrettyDiffDetail a => a -> Maybe Doc
+ Hix.Managed.Data.Diff: type BoundsChange = Change BoundsDiffDetail VersionBounds
+ Hix.Managed.Data.Diff: type BoundsDiff = Diff BoundsDiffDetail VersionBounds
+ Hix.Managed.Data.Diff: type VersionChange = Change () Version
+ Hix.Managed.Data.Diff: type VersionDiff = Diff () Version
+ Hix.Managed.Data.EnvConfig: EnvConfig :: [LocalPackage] -> GhcDb -> EnvConfig
+ Hix.Managed.Data.EnvConfig: [$sel:ghc:EnvConfig] :: EnvConfig -> GhcDb
+ Hix.Managed.Data.EnvConfig: [$sel:targets:EnvConfig] :: EnvConfig -> [LocalPackage]
+ Hix.Managed.Data.EnvConfig: data EnvConfig
+ Hix.Managed.Data.EnvConfig: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Managed.Data.EnvConfig.EnvConfig
+ Hix.Managed.Data.EnvConfig: instance GHC.Classes.Eq Hix.Managed.Data.EnvConfig.EnvConfig
+ Hix.Managed.Data.EnvConfig: instance GHC.Generics.Generic Hix.Managed.Data.EnvConfig.EnvConfig
+ Hix.Managed.Data.EnvConfig: instance GHC.Show.Show Hix.Managed.Data.EnvConfig.EnvConfig
+ Hix.Managed.Data.EnvContext: EnvContext :: EnvName -> GhcDb -> Targets -> EnvDeps -> NonEmpty MutableDep -> Ranges -> EnvContext
+ Hix.Managed.Data.EnvContext: EnvDeps :: Set MutableDep -> Set LocalPackage -> EnvDeps
+ Hix.Managed.Data.EnvContext: [$sel:deps:EnvContext] :: EnvContext -> EnvDeps
+ Hix.Managed.Data.EnvContext: [$sel:env:EnvContext] :: EnvContext -> EnvName
+ Hix.Managed.Data.EnvContext: [$sel:ghc:EnvContext] :: EnvContext -> GhcDb
+ Hix.Managed.Data.EnvContext: [$sel:local:EnvDeps] :: EnvDeps -> Set LocalPackage
+ Hix.Managed.Data.EnvContext: [$sel:mutable:EnvDeps] :: EnvDeps -> Set MutableDep
+ Hix.Managed.Data.EnvContext: [$sel:query:EnvContext] :: EnvContext -> NonEmpty MutableDep
+ Hix.Managed.Data.EnvContext: [$sel:solverBounds:EnvContext] :: EnvContext -> Ranges
+ Hix.Managed.Data.EnvContext: [$sel:targets:EnvContext] :: EnvContext -> Targets
+ Hix.Managed.Data.EnvContext: data EnvContext
+ Hix.Managed.Data.EnvContext: data EnvDeps
+ Hix.Managed.Data.EnvContext: instance GHC.Base.Monoid Hix.Managed.Data.EnvContext.EnvDeps
+ Hix.Managed.Data.EnvContext: instance GHC.Base.Semigroup Hix.Managed.Data.EnvContext.EnvDeps
+ Hix.Managed.Data.EnvContext: instance GHC.Classes.Eq Hix.Managed.Data.EnvContext.EnvContext
+ Hix.Managed.Data.EnvContext: instance GHC.Classes.Eq Hix.Managed.Data.EnvContext.EnvDeps
+ Hix.Managed.Data.EnvContext: instance GHC.Generics.Generic Hix.Managed.Data.EnvContext.EnvContext
+ Hix.Managed.Data.EnvContext: instance GHC.Generics.Generic Hix.Managed.Data.EnvContext.EnvDeps
+ Hix.Managed.Data.EnvContext: instance GHC.Show.Show Hix.Managed.Data.EnvContext.EnvContext
+ Hix.Managed.Data.EnvContext: instance GHC.Show.Show Hix.Managed.Data.EnvContext.EnvDeps
+ Hix.Managed.Data.EnvRequest: EnvRequest :: EnvContext -> EnvBuilder -> Initial EnvState -> EnvRequest
+ Hix.Managed.Data.EnvRequest: [$sel:builder:EnvRequest] :: EnvRequest -> EnvBuilder
+ Hix.Managed.Data.EnvRequest: [$sel:context:EnvRequest] :: EnvRequest -> EnvContext
+ Hix.Managed.Data.EnvRequest: [$sel:state:EnvRequest] :: EnvRequest -> Initial EnvState
+ Hix.Managed.Data.EnvRequest: data EnvRequest
+ Hix.Managed.Data.EnvResult: EnvResult :: EnvName -> Maybe EnvState -> NonEmpty StageSummary -> EnvResult
+ Hix.Managed.Data.EnvResult: [$sel:env:EnvResult] :: EnvResult -> EnvName
+ Hix.Managed.Data.EnvResult: [$sel:state:EnvResult] :: EnvResult -> Maybe EnvState
+ Hix.Managed.Data.EnvResult: [$sel:summaries:EnvResult] :: EnvResult -> NonEmpty StageSummary
+ Hix.Managed.Data.EnvResult: data EnvResult
+ Hix.Managed.Data.EnvResult: instance GHC.Classes.Eq Hix.Managed.Data.EnvResult.EnvResult
+ Hix.Managed.Data.EnvResult: instance GHC.Generics.Generic Hix.Managed.Data.EnvResult.EnvResult
+ Hix.Managed.Data.EnvResult: instance GHC.Show.Show Hix.Managed.Data.EnvResult.EnvResult
+ Hix.Managed.Data.EnvState: EnvState :: MutableDeps BoundsChange -> MutableDeps VersionChange -> Overrides -> MutableDeps VersionChange -> EnvState
+ Hix.Managed.Data.EnvState: [$sel:bounds:EnvState] :: EnvState -> MutableDeps BoundsChange
+ Hix.Managed.Data.EnvState: [$sel:initial:EnvState] :: EnvState -> MutableDeps VersionChange
+ Hix.Managed.Data.EnvState: [$sel:overrides:EnvState] :: EnvState -> Overrides
+ Hix.Managed.Data.EnvState: [$sel:versions:EnvState] :: EnvState -> MutableDeps VersionChange
+ Hix.Managed.Data.EnvState: data EnvState
+ Hix.Managed.Data.EnvState: instance Distribution.Pretty.Pretty Hix.Managed.Data.EnvState.EnvState
+ Hix.Managed.Data.EnvState: instance GHC.Base.Monoid Hix.Managed.Data.EnvState.EnvState
+ Hix.Managed.Data.EnvState: instance GHC.Base.Semigroup Hix.Managed.Data.EnvState.EnvState
+ Hix.Managed.Data.EnvState: instance GHC.Classes.Eq Hix.Managed.Data.EnvState.EnvState
+ Hix.Managed.Data.EnvState: instance GHC.Generics.Generic Hix.Managed.Data.EnvState.EnvState
+ Hix.Managed.Data.EnvState: instance GHC.Show.Show Hix.Managed.Data.EnvState.EnvState
+ Hix.Managed.Data.Envs: Envs :: Map EnvName a -> Envs a
+ Hix.Managed.Data.Envs: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Hix.Managed.Data.Envs.Envs a)
+ Hix.Managed.Data.Envs: instance Distribution.Pretty.Pretty a => Distribution.Pretty.Pretty (Hix.Managed.Data.Envs.Envs a)
+ Hix.Managed.Data.Envs: instance GHC.Base.Monoid (Hix.Managed.Data.Envs.Envs a)
+ Hix.Managed.Data.Envs: instance GHC.Base.Semigroup (Hix.Managed.Data.Envs.Envs a)
+ Hix.Managed.Data.Envs: instance GHC.Classes.Eq a => GHC.Classes.Eq (Hix.Managed.Data.Envs.Envs a)
+ Hix.Managed.Data.Envs: instance GHC.Generics.Generic (Hix.Managed.Data.Envs.Envs a)
+ Hix.Managed.Data.Envs: instance GHC.IsList.IsList (Hix.Managed.Data.Envs.Envs a)
+ Hix.Managed.Data.Envs: instance GHC.Show.Show a => GHC.Show.Show (Hix.Managed.Data.Envs.Envs a)
+ Hix.Managed.Data.Envs: instance Hix.Class.EncodeNix.EncodeNix a => Hix.Class.EncodeNix.EncodeNix (Hix.Managed.Data.Envs.Envs a)
+ Hix.Managed.Data.Envs: instance Hix.Class.Map.NMap (Hix.Managed.Data.Envs.Envs a) Hix.Data.EnvName.EnvName a Hix.Class.Map.LookupMonoid
+ Hix.Managed.Data.Envs: newtype Envs a
+ Hix.Managed.Data.Initial: Initial :: a -> Initial a
+ Hix.Managed.Data.Initial: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Hix.Managed.Data.Initial.Initial a)
+ Hix.Managed.Data.Initial: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Hix.Managed.Data.Initial.Initial a)
+ Hix.Managed.Data.Initial: instance Distribution.Pretty.Pretty a => Distribution.Pretty.Pretty (Hix.Managed.Data.Initial.Initial a)
+ Hix.Managed.Data.Initial: instance GHC.Base.Functor Hix.Managed.Data.Initial.Initial
+ Hix.Managed.Data.Initial: instance GHC.Base.Monoid a => GHC.Base.Monoid (Hix.Managed.Data.Initial.Initial a)
+ Hix.Managed.Data.Initial: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Hix.Managed.Data.Initial.Initial a)
+ Hix.Managed.Data.Initial: instance GHC.Classes.Eq a => GHC.Classes.Eq (Hix.Managed.Data.Initial.Initial a)
+ Hix.Managed.Data.Initial: instance GHC.Generics.Generic (Hix.Managed.Data.Initial.Initial a)
+ Hix.Managed.Data.Initial: instance GHC.Show.Show a => GHC.Show.Show (Hix.Managed.Data.Initial.Initial a)
+ Hix.Managed.Data.Initial: instance Hix.Class.EncodeNix.EncodeNix a => Hix.Class.EncodeNix.EncodeNix (Hix.Managed.Data.Initial.Initial a)
+ Hix.Managed.Data.Initial: newtype Initial a
+ Hix.Managed.Data.Lower: Lower :: NonEmpty Major -> Lower
+ Hix.Managed.Data.Lower: [$sel:majors:Lower] :: Lower -> NonEmpty Major
+ Hix.Managed.Data.Lower: data Lower
+ Hix.Managed.Data.Lower: instance Distribution.Pretty.Pretty Hix.Managed.Data.Lower.Lower
+ Hix.Managed.Data.Lower: instance GHC.Classes.Eq Hix.Managed.Data.Lower.Lower
+ Hix.Managed.Data.Lower: instance GHC.Generics.Generic Hix.Managed.Data.Lower.Lower
+ Hix.Managed.Data.Lower: instance GHC.Show.Show Hix.Managed.Data.Lower.Lower
+ Hix.Managed.Data.LowerConfig: LowerConfig :: Bool -> Bool -> Bool -> LowerConfig
+ Hix.Managed.Data.LowerConfig: [$sel:initOnly:LowerConfig] :: LowerConfig -> Bool
+ Hix.Managed.Data.LowerConfig: [$sel:reset:LowerConfig] :: LowerConfig -> Bool
+ Hix.Managed.Data.LowerConfig: [$sel:stabilize:LowerConfig] :: LowerConfig -> Bool
+ Hix.Managed.Data.LowerConfig: data LowerConfig
+ Hix.Managed.Data.LowerConfig: instance Data.Default.Class.Default Hix.Managed.Data.LowerConfig.LowerConfig
+ Hix.Managed.Data.LowerConfig: instance GHC.Classes.Eq Hix.Managed.Data.LowerConfig.LowerConfig
+ Hix.Managed.Data.LowerConfig: instance GHC.Generics.Generic Hix.Managed.Data.LowerConfig.LowerConfig
+ Hix.Managed.Data.LowerConfig: instance GHC.Show.Show Hix.Managed.Data.LowerConfig.LowerConfig
+ Hix.Managed.Data.LowerConfig: lowerConfig :: LowerOptions -> LowerConfig
+ Hix.Managed.Data.ManagedPackage: ManagedPackage :: LocalPackage -> Version -> LocalRanges -> MutableRanges -> ManagedPackage
+ Hix.Managed.Data.ManagedPackage: [$sel:local:ManagedPackage] :: ManagedPackage -> LocalRanges
+ Hix.Managed.Data.ManagedPackage: [$sel:mutable:ManagedPackage] :: ManagedPackage -> MutableRanges
+ Hix.Managed.Data.ManagedPackage: [$sel:package:ManagedPackage] :: ManagedPackage -> LocalPackage
+ Hix.Managed.Data.ManagedPackage: [$sel:version:ManagedPackage] :: ManagedPackage -> Version
+ Hix.Managed.Data.ManagedPackage: data ManagedPackage
+ Hix.Managed.Data.ManagedPackage: deps :: ManagedPackage -> [Dep]
+ Hix.Managed.Data.ManagedPackage: instance Distribution.Pretty.Pretty Hix.Managed.Data.ManagedPackage.ManagedPackage
+ Hix.Managed.Data.ManagedPackage: instance GHC.Classes.Eq Hix.Managed.Data.ManagedPackage.ManagedPackage
+ Hix.Managed.Data.ManagedPackage: instance GHC.Generics.Generic Hix.Managed.Data.ManagedPackage.ManagedPackage
+ Hix.Managed.Data.ManagedPackage: instance GHC.Show.Show Hix.Managed.Data.ManagedPackage.ManagedPackage
+ Hix.Managed.Data.ManagedPackage: packageId :: ManagedPackage -> PackageId
+ Hix.Managed.Data.ManagedPackage: ranges :: ManagedPackage -> Ranges
+ Hix.Managed.Data.ManagedPackageProto: ManagedPackageProto :: LocalPackage -> Version -> [Dep] -> ManagedPackageProto
+ Hix.Managed.Data.ManagedPackageProto: [$sel:deps:ManagedPackageProto] :: ManagedPackageProto -> [Dep]
+ Hix.Managed.Data.ManagedPackageProto: [$sel:name:ManagedPackageProto] :: ManagedPackageProto -> LocalPackage
+ Hix.Managed.Data.ManagedPackageProto: [$sel:version:ManagedPackageProto] :: ManagedPackageProto -> Version
+ Hix.Managed.Data.ManagedPackageProto: data ManagedPackageProto
+ Hix.Managed.Data.ManagedPackageProto: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Managed.Data.ManagedPackageProto.ManagedPackageProto
+ Hix.Managed.Data.ManagedPackageProto: instance Distribution.Pretty.Pretty Hix.Managed.Data.ManagedPackageProto.ManagedPackageProto
+ Hix.Managed.Data.ManagedPackageProto: instance GHC.Classes.Eq Hix.Managed.Data.ManagedPackageProto.ManagedPackageProto
+ Hix.Managed.Data.ManagedPackageProto: instance GHC.Generics.Generic Hix.Managed.Data.ManagedPackageProto.ManagedPackageProto
+ Hix.Managed.Data.ManagedPackageProto: instance GHC.Show.Show Hix.Managed.Data.ManagedPackageProto.ManagedPackageProto
+ Hix.Managed.Data.ManagedPackageProto: managedPackages :: Map (LocalPackage, Version) [Dep] -> Packages ManagedPackageProto
+ Hix.Managed.Data.Mutable: addBuildVersions :: Versions -> MutableVersions -> MutableVersions
+ Hix.Managed.Data.Mutable: classifyPackageDep :: Set LocalPackage -> Dep -> Either (LocalPackage, VersionRange) (MutableDep, VersionRange)
+ Hix.Managed.Data.Mutable: data LocalRanges
+ Hix.Managed.Data.Mutable: data MutableBounds
+ Hix.Managed.Data.Mutable: data MutableDep
+ Hix.Managed.Data.Mutable: data MutableDeps a
+ Hix.Managed.Data.Mutable: data MutableRanges
+ Hix.Managed.Data.Mutable: data MutableVersions
+ Hix.Managed.Data.Mutable: depName :: MutableDep -> PackageName
+ Hix.Managed.Data.Mutable: instance Data.Aeson.Types.ToJSON.ToJSON Hix.Managed.Data.Mutable.MutableBounds
+ Hix.Managed.Data.Mutable: instance Data.Aeson.Types.ToJSON.ToJSON Hix.Managed.Data.Mutable.MutableDep
+ Hix.Managed.Data.Mutable: instance Data.Aeson.Types.ToJSON.ToJSONKey Hix.Managed.Data.Mutable.MutableDep
+ Hix.Managed.Data.Mutable: instance Data.String.IsString a => Exon.Class.ToSegment.ToSegment Hix.Managed.Data.Mutable.MutableDep a
+ Hix.Managed.Data.Mutable: instance Distribution.Pretty.Pretty Hix.Managed.Data.Mutable.LocalBounds
+ Hix.Managed.Data.Mutable: instance Distribution.Pretty.Pretty Hix.Managed.Data.Mutable.LocalRanges
+ Hix.Managed.Data.Mutable: instance Distribution.Pretty.Pretty Hix.Managed.Data.Mutable.MutableBounds
+ Hix.Managed.Data.Mutable: instance Distribution.Pretty.Pretty Hix.Managed.Data.Mutable.MutableDep
+ Hix.Managed.Data.Mutable: instance Distribution.Pretty.Pretty Hix.Managed.Data.Mutable.MutableRanges
+ Hix.Managed.Data.Mutable: instance Distribution.Pretty.Pretty Hix.Managed.Data.Mutable.MutableVersions
+ Hix.Managed.Data.Mutable: instance Distribution.Pretty.Pretty a => Distribution.Pretty.Pretty (Hix.Managed.Data.Mutable.MutableDeps a)
+ Hix.Managed.Data.Mutable: instance GHC.Base.Monoid (Hix.Managed.Data.Mutable.MutableDeps a)
+ Hix.Managed.Data.Mutable: instance GHC.Base.Monoid Hix.Managed.Data.Mutable.LocalBounds
+ Hix.Managed.Data.Mutable: instance GHC.Base.Monoid Hix.Managed.Data.Mutable.LocalRanges
+ Hix.Managed.Data.Mutable: instance GHC.Base.Monoid Hix.Managed.Data.Mutable.MutableBounds
+ Hix.Managed.Data.Mutable: instance GHC.Base.Monoid Hix.Managed.Data.Mutable.MutableRanges
+ Hix.Managed.Data.Mutable: instance GHC.Base.Monoid Hix.Managed.Data.Mutable.MutableVersions
+ Hix.Managed.Data.Mutable: instance GHC.Base.Semigroup (Hix.Managed.Data.Mutable.MutableDeps a)
+ Hix.Managed.Data.Mutable: instance GHC.Base.Semigroup Hix.Managed.Data.Mutable.LocalBounds
+ Hix.Managed.Data.Mutable: instance GHC.Base.Semigroup Hix.Managed.Data.Mutable.LocalRanges
+ Hix.Managed.Data.Mutable: instance GHC.Base.Semigroup Hix.Managed.Data.Mutable.MutableBounds
+ Hix.Managed.Data.Mutable: instance GHC.Base.Semigroup Hix.Managed.Data.Mutable.MutableRanges
+ Hix.Managed.Data.Mutable: instance GHC.Base.Semigroup Hix.Managed.Data.Mutable.MutableVersions
+ Hix.Managed.Data.Mutable: instance GHC.Classes.Eq Hix.Managed.Data.Mutable.LocalBounds
+ Hix.Managed.Data.Mutable: instance GHC.Classes.Eq Hix.Managed.Data.Mutable.LocalRanges
+ Hix.Managed.Data.Mutable: instance GHC.Classes.Eq Hix.Managed.Data.Mutable.MutableBounds
+ Hix.Managed.Data.Mutable: instance GHC.Classes.Eq Hix.Managed.Data.Mutable.MutableDep
+ Hix.Managed.Data.Mutable: instance GHC.Classes.Eq Hix.Managed.Data.Mutable.MutableRanges
+ Hix.Managed.Data.Mutable: instance GHC.Classes.Eq Hix.Managed.Data.Mutable.MutableVersions
+ Hix.Managed.Data.Mutable: instance GHC.Classes.Eq a => GHC.Classes.Eq (Hix.Managed.Data.Mutable.MutableDeps a)
+ Hix.Managed.Data.Mutable: instance GHC.Classes.Ord Hix.Managed.Data.Mutable.MutableDep
+ Hix.Managed.Data.Mutable: instance GHC.Generics.Generic (Hix.Managed.Data.Mutable.MutableDeps a)
+ Hix.Managed.Data.Mutable: instance GHC.Generics.Generic Hix.Managed.Data.Mutable.LocalBounds
+ Hix.Managed.Data.Mutable: instance GHC.Generics.Generic Hix.Managed.Data.Mutable.LocalRanges
+ Hix.Managed.Data.Mutable: instance GHC.Generics.Generic Hix.Managed.Data.Mutable.MutableBounds
+ Hix.Managed.Data.Mutable: instance GHC.Generics.Generic Hix.Managed.Data.Mutable.MutableRanges
+ Hix.Managed.Data.Mutable: instance GHC.Generics.Generic Hix.Managed.Data.Mutable.MutableVersions
+ Hix.Managed.Data.Mutable: instance GHC.IsList.IsList Hix.Managed.Data.Mutable.LocalBounds
+ Hix.Managed.Data.Mutable: instance GHC.IsList.IsList Hix.Managed.Data.Mutable.LocalRanges
+ Hix.Managed.Data.Mutable: instance GHC.IsList.IsList Hix.Managed.Data.Mutable.MutableBounds
+ Hix.Managed.Data.Mutable: instance GHC.IsList.IsList Hix.Managed.Data.Mutable.MutableRanges
+ Hix.Managed.Data.Mutable: instance GHC.IsList.IsList Hix.Managed.Data.Mutable.MutableVersions
+ Hix.Managed.Data.Mutable: instance GHC.Show.Show Hix.Managed.Data.Mutable.LocalBounds
+ Hix.Managed.Data.Mutable: instance GHC.Show.Show Hix.Managed.Data.Mutable.LocalRanges
+ Hix.Managed.Data.Mutable: instance GHC.Show.Show Hix.Managed.Data.Mutable.MutableBounds
+ Hix.Managed.Data.Mutable: instance GHC.Show.Show Hix.Managed.Data.Mutable.MutableDep
+ Hix.Managed.Data.Mutable: instance GHC.Show.Show Hix.Managed.Data.Mutable.MutableRanges
+ Hix.Managed.Data.Mutable: instance GHC.Show.Show Hix.Managed.Data.Mutable.MutableVersions
+ Hix.Managed.Data.Mutable: instance GHC.Show.Show a => GHC.Show.Show (Hix.Managed.Data.Mutable.MutableDeps a)
+ Hix.Managed.Data.Mutable: instance Hix.Class.EncodeNix.EncodeNix Hix.Managed.Data.Mutable.LocalBounds
+ Hix.Managed.Data.Mutable: instance Hix.Class.EncodeNix.EncodeNix Hix.Managed.Data.Mutable.MutableBounds
+ Hix.Managed.Data.Mutable: instance Hix.Class.EncodeNix.EncodeNix Hix.Managed.Data.Mutable.MutableVersions
+ Hix.Managed.Data.Mutable: instance Hix.Class.EncodeNix.EncodeNix a => Hix.Class.EncodeNix.EncodeNix (Hix.Managed.Data.Mutable.MutableDeps a)
+ Hix.Managed.Data.Mutable: instance Hix.Class.EncodeNix.EncodeNixKey Hix.Managed.Data.Mutable.MutableDep
+ Hix.Managed.Data.Mutable: instance Hix.Class.Map.NMap (Hix.Managed.Data.Mutable.MutableDeps a) Hix.Managed.Data.Mutable.MutableDep a Hix.Class.Map.LookupMaybe
+ Hix.Managed.Data.Mutable: instance Hix.Class.Map.NMap Hix.Managed.Data.Mutable.LocalBounds Hix.Data.PackageName.LocalPackage Hix.Data.VersionBounds.VersionBounds Hix.Class.Map.LookupMaybe
+ Hix.Managed.Data.Mutable: instance Hix.Class.Map.NMap Hix.Managed.Data.Mutable.LocalRanges Hix.Data.PackageName.LocalPackage Distribution.Types.VersionRange.Internal.VersionRange Hix.Class.Map.LookupMaybe
+ Hix.Managed.Data.Mutable: instance Hix.Class.Map.NMap Hix.Managed.Data.Mutable.MutableBounds Hix.Managed.Data.Mutable.MutableDep Hix.Data.VersionBounds.VersionBounds Hix.Class.Map.LookupMaybe
+ Hix.Managed.Data.Mutable: instance Hix.Class.Map.NMap Hix.Managed.Data.Mutable.MutableRanges Hix.Managed.Data.Mutable.MutableDep Distribution.Types.VersionRange.Internal.VersionRange Hix.Class.Map.LookupMaybe
+ Hix.Managed.Data.Mutable: instance Hix.Class.Map.NMap Hix.Managed.Data.Mutable.MutableVersions Hix.Managed.Data.Mutable.MutableDep (GHC.Maybe.Maybe Distribution.Types.Version.Version) Hix.Class.Map.LookupMaybe
+ Hix.Managed.Data.Mutable: isMutableDep :: Set MutableDep -> PackageName -> Bool
+ Hix.Managed.Data.Mutable: mutFromSet :: NMap map MutableDep v sort => Set MutableDep -> (MutableDep -> v) -> map
+ Hix.Managed.Data.Mutable: mutLookup :: NMap map MutableDep v sort => NLookup sort MutableDep v l => PackageName -> map -> l
+ Hix.Managed.Data.Mutable: mutRelax :: NMap map1 MutableDep v s1 => NMap map2 PackageName v s2 => map1 -> map2
+ Hix.Managed.Data.Mutable: mutRelaxVersions :: MutableVersions -> Versions
+ Hix.Managed.Data.Mutable: mutReplace :: NMap map MutableDep v sort => map -> map -> map
+ Hix.Managed.Data.Mutable: mutReplacePartial :: forall map1 map2 v1 s1 s2. NMap map1 PackageName v1 s1 => NMap map2 MutableDep v1 s2 => map1 -> map2 -> map2
+ Hix.Managed.Data.Mutable: mutReplaceTargets :: NMap map MutableDep v sort => Targets -> map -> Packages map -> Packages map
+ Hix.Managed.Data.Mutable: mutRestrictKeys :: NMap map MutableDep v sort => Set PackageName -> map -> map
+ Hix.Managed.Data.Mutable: mutUpdate :: NMap map1 MutableDep v1 s1 => NMap map2 MutableDep v2 s2 => (v1 -> v2 -> v2) -> map1 -> map2 -> map2
+ Hix.Managed.Data.Mutable: mutUpdatePartial :: forall map1 map2 v1 v2 s1 s2. NMap map1 PackageName v1 s1 => NMap map2 MutableDep v2 s2 => (v1 -> v2 -> v2) -> map1 -> map2 -> map2
+ Hix.Managed.Data.Mutable: mutUpdateTargets :: NMap map1 MutableDep v1 s1 => NMap map2 MutableDep v2 s2 => Targets -> (v1 -> v2 -> v2) -> map1 -> Packages map2 -> Packages map2
+ Hix.Managed.Data.Mutable: pattern MutableDep :: PackageName -> MutableDep
+ Hix.Managed.Data.Mutable: unsafeMutableDep :: PackageName -> MutableDep
+ Hix.Managed.Data.MutableId: MutableId :: MutableDep -> Version -> MutableId
+ Hix.Managed.Data.MutableId: [$sel:name:MutableId] :: MutableId -> MutableDep
+ Hix.Managed.Data.MutableId: [$sel:version:MutableId] :: MutableId -> Version
+ Hix.Managed.Data.MutableId: data MutableId
+ Hix.Managed.Data.MutableId: instance Data.Aeson.Types.ToJSON.ToJSON Hix.Managed.Data.MutableId.MutableId
+ Hix.Managed.Data.MutableId: instance Distribution.Pretty.Pretty Hix.Managed.Data.MutableId.MutableId
+ Hix.Managed.Data.MutableId: instance GHC.Classes.Eq Hix.Managed.Data.MutableId.MutableId
+ Hix.Managed.Data.MutableId: instance GHC.Generics.Generic Hix.Managed.Data.MutableId.MutableId
+ Hix.Managed.Data.MutableId: instance GHC.Show.Show Hix.Managed.Data.MutableId.MutableId
+ Hix.Managed.Data.MutableId: toPackageId :: MutableId -> PackageId
+ Hix.Managed.Data.Mutation: BuildMutation :: Text -> SolverState -> (Version -> VersionBounds -> VersionBounds) -> BuildMutation
+ Hix.Managed.Data.Mutation: DepMutation :: MutableDep -> Bool -> a -> DepMutation a
+ Hix.Managed.Data.Mutation: FailedMutation :: MutableDep -> Text -> FailedMutation
+ Hix.Managed.Data.Mutation: MutationFailed :: MutationResult s
+ Hix.Managed.Data.Mutation: MutationKeep :: MutationResult s
+ Hix.Managed.Data.Mutation: MutationSuccess :: MutableId -> Bool -> MutationState -> s -> MutationResult s
+ Hix.Managed.Data.Mutation: [$sel:candidate:MutationSuccess] :: MutationResult s -> MutableId
+ Hix.Managed.Data.Mutation: [$sel:changed:MutationSuccess] :: MutationResult s -> Bool
+ Hix.Managed.Data.Mutation: [$sel:description:BuildMutation] :: BuildMutation -> Text
+ Hix.Managed.Data.Mutation: [$sel:ext:MutationSuccess] :: MutationResult s -> s
+ Hix.Managed.Data.Mutation: [$sel:mutation:DepMutation] :: DepMutation a -> a
+ Hix.Managed.Data.Mutation: [$sel:mutation:FailedMutation] :: FailedMutation -> Text
+ Hix.Managed.Data.Mutation: [$sel:package:DepMutation] :: DepMutation a -> MutableDep
+ Hix.Managed.Data.Mutation: [$sel:package:FailedMutation] :: FailedMutation -> MutableDep
+ Hix.Managed.Data.Mutation: [$sel:retract:DepMutation] :: DepMutation a -> Bool
+ Hix.Managed.Data.Mutation: [$sel:solverState:BuildMutation] :: BuildMutation -> SolverState
+ Hix.Managed.Data.Mutation: [$sel:state:MutationSuccess] :: MutationResult s -> MutationState
+ Hix.Managed.Data.Mutation: [$sel:updateBound:BuildMutation] :: BuildMutation -> Version -> VersionBounds -> VersionBounds
+ Hix.Managed.Data.Mutation: data BuildMutation
+ Hix.Managed.Data.Mutation: data DepMutation a
+ Hix.Managed.Data.Mutation: data FailedMutation
+ Hix.Managed.Data.Mutation: data MutationResult s
+ Hix.Managed.Data.Mutation: failedMutation :: Pretty a => DepMutation a -> FailedMutation
+ Hix.Managed.Data.Mutation: instance Distribution.Pretty.Pretty Hix.Managed.Data.Mutation.FailedMutation
+ Hix.Managed.Data.Mutation: instance Distribution.Pretty.Pretty a => Distribution.Pretty.Pretty (Hix.Managed.Data.Mutation.DepMutation a)
+ Hix.Managed.Data.Mutation: instance GHC.Classes.Eq Hix.Managed.Data.Mutation.FailedMutation
+ Hix.Managed.Data.Mutation: instance GHC.Classes.Eq a => GHC.Classes.Eq (Hix.Managed.Data.Mutation.DepMutation a)
+ Hix.Managed.Data.Mutation: instance GHC.Classes.Eq s => GHC.Classes.Eq (Hix.Managed.Data.Mutation.MutationResult s)
+ Hix.Managed.Data.Mutation: instance GHC.Generics.Generic (Hix.Managed.Data.Mutation.DepMutation a)
+ Hix.Managed.Data.Mutation: instance GHC.Generics.Generic (Hix.Managed.Data.Mutation.MutationResult s)
+ Hix.Managed.Data.Mutation: instance GHC.Generics.Generic Hix.Managed.Data.Mutation.BuildMutation
+ Hix.Managed.Data.Mutation: instance GHC.Generics.Generic Hix.Managed.Data.Mutation.FailedMutation
+ Hix.Managed.Data.Mutation: instance GHC.Show.Show Hix.Managed.Data.Mutation.FailedMutation
+ Hix.Managed.Data.Mutation: instance GHC.Show.Show a => GHC.Show.Show (Hix.Managed.Data.Mutation.DepMutation a)
+ Hix.Managed.Data.Mutation: instance GHC.Show.Show s => GHC.Show.Show (Hix.Managed.Data.Mutation.MutationResult s)
+ Hix.Managed.Data.MutationMode: MutationMode :: Int -> MutationMode
+ Hix.Managed.Data.MutationMode: [$sel:foo:MutationMode] :: MutationMode -> Int
+ Hix.Managed.Data.MutationMode: data MutationMode
+ Hix.Managed.Data.MutationMode: instance GHC.Classes.Eq Hix.Managed.Data.MutationMode.MutationMode
+ Hix.Managed.Data.MutationMode: instance GHC.Generics.Generic Hix.Managed.Data.MutationMode.MutationMode
+ Hix.Managed.Data.MutationMode: instance GHC.Show.Show Hix.Managed.Data.MutationMode.MutationMode
+ Hix.Managed.Data.MutationState: MutationState :: MutableBounds -> MutableVersions -> Overrides -> MutableVersions -> MutationState
+ Hix.Managed.Data.MutationState: [$sel:bounds:MutationState] :: MutationState -> MutableBounds
+ Hix.Managed.Data.MutationState: [$sel:initial:MutationState] :: MutationState -> MutableVersions
+ Hix.Managed.Data.MutationState: [$sel:overrides:MutationState] :: MutationState -> Overrides
+ Hix.Managed.Data.MutationState: [$sel:versions:MutationState] :: MutationState -> MutableVersions
+ Hix.Managed.Data.MutationState: data MutationState
+ Hix.Managed.Data.MutationState: instance Distribution.Pretty.Pretty Hix.Managed.Data.MutationState.MutationState
+ Hix.Managed.Data.MutationState: instance GHC.Base.Monoid Hix.Managed.Data.MutationState.MutationState
+ Hix.Managed.Data.MutationState: instance GHC.Base.Semigroup Hix.Managed.Data.MutationState.MutationState
+ Hix.Managed.Data.MutationState: instance GHC.Classes.Eq Hix.Managed.Data.MutationState.MutationState
+ Hix.Managed.Data.MutationState: instance GHC.Generics.Generic Hix.Managed.Data.MutationState.MutationState
+ Hix.Managed.Data.MutationState: instance GHC.Show.Show Hix.Managed.Data.MutationState.MutationState
+ Hix.Managed.Data.MutationState: updateBoundsWith :: (Version -> VersionBounds -> VersionBounds) -> MutationState -> MutationState
+ Hix.Managed.Data.Packages: Deps :: Map PackageName a -> Deps a
+ Hix.Managed.Data.Packages: Packages :: Map LocalPackage a -> Packages a
+ Hix.Managed.Data.Packages: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Hix.Managed.Data.Packages.Deps a)
+ Hix.Managed.Data.Packages: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Hix.Managed.Data.Packages.Packages a)
+ Hix.Managed.Data.Packages: instance Distribution.Pretty.Pretty a => Distribution.Pretty.Pretty (Hix.Managed.Data.Packages.Deps a)
+ Hix.Managed.Data.Packages: instance Distribution.Pretty.Pretty a => Distribution.Pretty.Pretty (Hix.Managed.Data.Packages.Packages a)
+ Hix.Managed.Data.Packages: instance GHC.Base.Monoid (Hix.Managed.Data.Packages.Deps a)
+ Hix.Managed.Data.Packages: instance GHC.Base.Monoid (Hix.Managed.Data.Packages.Packages a)
+ Hix.Managed.Data.Packages: instance GHC.Base.Semigroup (Hix.Managed.Data.Packages.Deps a)
+ Hix.Managed.Data.Packages: instance GHC.Base.Semigroup (Hix.Managed.Data.Packages.Packages a)
+ Hix.Managed.Data.Packages: instance GHC.Classes.Eq a => GHC.Classes.Eq (Hix.Managed.Data.Packages.Deps a)
+ Hix.Managed.Data.Packages: instance GHC.Classes.Eq a => GHC.Classes.Eq (Hix.Managed.Data.Packages.Packages a)
+ Hix.Managed.Data.Packages: instance GHC.Generics.Generic (Hix.Managed.Data.Packages.Deps a)
+ Hix.Managed.Data.Packages: instance GHC.Generics.Generic (Hix.Managed.Data.Packages.Packages a)
+ Hix.Managed.Data.Packages: instance GHC.IsList.IsList (Hix.Managed.Data.Packages.Deps a)
+ Hix.Managed.Data.Packages: instance GHC.IsList.IsList (Hix.Managed.Data.Packages.Packages a)
+ Hix.Managed.Data.Packages: instance GHC.Show.Show a => GHC.Show.Show (Hix.Managed.Data.Packages.Deps a)
+ Hix.Managed.Data.Packages: instance GHC.Show.Show a => GHC.Show.Show (Hix.Managed.Data.Packages.Packages a)
+ Hix.Managed.Data.Packages: instance Hix.Class.EncodeNix.EncodeNix a => Hix.Class.EncodeNix.EncodeNix (Hix.Managed.Data.Packages.Deps a)
+ Hix.Managed.Data.Packages: instance Hix.Class.EncodeNix.EncodeNix a => Hix.Class.EncodeNix.EncodeNix (Hix.Managed.Data.Packages.Packages a)
+ Hix.Managed.Data.Packages: instance Hix.Class.Map.NMap (Hix.Managed.Data.Packages.Deps a) Hix.Data.PackageName.PackageName a Hix.Class.Map.LookupMaybe
+ Hix.Managed.Data.Packages: instance Hix.Class.Map.NMap (Hix.Managed.Data.Packages.Packages a) Hix.Data.PackageName.LocalPackage a Hix.Class.Map.LookupMonoid
+ Hix.Managed.Data.Packages: newtype Deps a
+ Hix.Managed.Data.Packages: newtype Packages a
+ Hix.Managed.Data.ProcessState: ProcessState :: Packages ManagedPackage -> ProjectState -> ProcessState
+ Hix.Managed.Data.ProcessState: [$sel:packages:ProcessState] :: ProcessState -> Packages ManagedPackage
+ Hix.Managed.Data.ProcessState: [$sel:state:ProcessState] :: ProcessState -> ProjectState
+ Hix.Managed.Data.ProcessState: data ProcessState
+ Hix.Managed.Data.ProcessState: initProcessState :: ProjectContext -> ProcessState
+ Hix.Managed.Data.ProcessState: instance Distribution.Pretty.Pretty Hix.Managed.Data.ProcessState.ProcessState
+ Hix.Managed.Data.ProcessState: instance GHC.Classes.Eq Hix.Managed.Data.ProcessState.ProcessState
+ Hix.Managed.Data.ProcessState: instance GHC.Generics.Generic Hix.Managed.Data.ProcessState.ProcessState
+ Hix.Managed.Data.ProcessState: instance GHC.Show.Show Hix.Managed.Data.ProcessState.ProcessState
+ Hix.Managed.Data.ProcessState: removeLowerBounds :: ManagedPackage -> ManagedPackage
+ Hix.Managed.Data.ProcessState: updateManagedPackages :: Packages MutableBounds -> Packages ManagedPackage -> Packages ManagedPackage
+ Hix.Managed.Data.ProjectContext: ProjectContext :: BuildConfig -> ProjectState -> Packages ManagedPackage -> NonEmpty (Either EnvName EnvContext) -> ProjectContext
+ Hix.Managed.Data.ProjectContext: [$sel:build:ProjectContext] :: ProjectContext -> BuildConfig
+ Hix.Managed.Data.ProjectContext: [$sel:envs:ProjectContext] :: ProjectContext -> NonEmpty (Either EnvName EnvContext)
+ Hix.Managed.Data.ProjectContext: [$sel:packages:ProjectContext] :: ProjectContext -> Packages ManagedPackage
+ Hix.Managed.Data.ProjectContext: [$sel:state:ProjectContext] :: ProjectContext -> ProjectState
+ Hix.Managed.Data.ProjectContext: data ProjectContext
+ Hix.Managed.Data.ProjectContext: instance GHC.Classes.Eq Hix.Managed.Data.ProjectContext.ProjectContext
+ Hix.Managed.Data.ProjectContext: instance GHC.Show.Show Hix.Managed.Data.ProjectContext.ProjectContext
+ Hix.Managed.Data.ProjectContextProto: ProjectContextProto :: Packages ManagedPackageProto -> ProjectStateProto -> Envs EnvConfig -> Maybe BuildOutputsPrefix -> ProjectContextProto
+ Hix.Managed.Data.ProjectContextProto: [$sel:buildOutputsPrefix:ProjectContextProto] :: ProjectContextProto -> Maybe BuildOutputsPrefix
+ Hix.Managed.Data.ProjectContextProto: [$sel:envs:ProjectContextProto] :: ProjectContextProto -> Envs EnvConfig
+ Hix.Managed.Data.ProjectContextProto: [$sel:packages:ProjectContextProto] :: ProjectContextProto -> Packages ManagedPackageProto
+ Hix.Managed.Data.ProjectContextProto: [$sel:state:ProjectContextProto] :: ProjectContextProto -> ProjectStateProto
+ Hix.Managed.Data.ProjectContextProto: data ProjectContextProto
+ Hix.Managed.Data.ProjectContextProto: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Managed.Data.ProjectContextProto.ProjectContextProto
+ Hix.Managed.Data.ProjectContextProto: instance Data.Default.Class.Default Hix.Managed.Data.ProjectContextProto.ProjectContextProto
+ Hix.Managed.Data.ProjectContextProto: instance GHC.Classes.Eq Hix.Managed.Data.ProjectContextProto.ProjectContextProto
+ Hix.Managed.Data.ProjectContextProto: instance GHC.Generics.Generic Hix.Managed.Data.ProjectContextProto.ProjectContextProto
+ Hix.Managed.Data.ProjectContextProto: instance GHC.Show.Show Hix.Managed.Data.ProjectContextProto.ProjectContextProto
+ Hix.Managed.Data.ProjectResult: ProjectResult :: NonEmpty EnvResult -> ProjectState -> ProjectResult
+ Hix.Managed.Data.ProjectResult: [$sel:envs:ProjectResult] :: ProjectResult -> NonEmpty EnvResult
+ Hix.Managed.Data.ProjectResult: [$sel:state:ProjectResult] :: ProjectResult -> ProjectState
+ Hix.Managed.Data.ProjectResult: data ProjectResult
+ Hix.Managed.Data.ProjectResult: instance GHC.Classes.Eq Hix.Managed.Data.ProjectResult.ProjectResult
+ Hix.Managed.Data.ProjectResult: instance GHC.Generics.Generic Hix.Managed.Data.ProjectResult.ProjectResult
+ Hix.Managed.Data.ProjectResult: instance GHC.Show.Show Hix.Managed.Data.ProjectResult.ProjectResult
+ Hix.Managed.Data.ProjectState: ProjectState :: Packages MutableBounds -> Envs MutableVersions -> Envs MutableVersions -> Envs Overrides -> Bool -> ProjectState
+ Hix.Managed.Data.ProjectState: [$sel:bounds:ProjectState] :: ProjectState -> Packages MutableBounds
+ Hix.Managed.Data.ProjectState: [$sel:initial:ProjectState] :: ProjectState -> Envs MutableVersions
+ Hix.Managed.Data.ProjectState: [$sel:overrides:ProjectState] :: ProjectState -> Envs Overrides
+ Hix.Managed.Data.ProjectState: [$sel:resolving:ProjectState] :: ProjectState -> Bool
+ Hix.Managed.Data.ProjectState: [$sel:versions:ProjectState] :: ProjectState -> Envs MutableVersions
+ Hix.Managed.Data.ProjectState: data ProjectState
+ Hix.Managed.Data.ProjectState: instance Data.Default.Class.Default Hix.Managed.Data.ProjectState.ProjectState
+ Hix.Managed.Data.ProjectState: instance Distribution.Pretty.Pretty Hix.Managed.Data.ProjectState.ProjectState
+ Hix.Managed.Data.ProjectState: instance GHC.Classes.Eq Hix.Managed.Data.ProjectState.ProjectState
+ Hix.Managed.Data.ProjectState: instance GHC.Generics.Generic Hix.Managed.Data.ProjectState.ProjectState
+ Hix.Managed.Data.ProjectState: instance GHC.Show.Show Hix.Managed.Data.ProjectState.ProjectState
+ Hix.Managed.Data.ProjectState: instance Hix.Class.EncodeNix.EncodeNix Hix.Managed.Data.ProjectState.ProjectState
+ Hix.Managed.Data.ProjectStateProto: ProjectStateProto :: Packages Bounds -> Envs Versions -> Envs Overrides -> Envs Versions -> Bool -> ProjectStateProto
+ Hix.Managed.Data.ProjectStateProto: [$sel:bounds:ProjectStateProto] :: ProjectStateProto -> Packages Bounds
+ Hix.Managed.Data.ProjectStateProto: [$sel:initial:ProjectStateProto] :: ProjectStateProto -> Envs Versions
+ Hix.Managed.Data.ProjectStateProto: [$sel:overrides:ProjectStateProto] :: ProjectStateProto -> Envs Overrides
+ Hix.Managed.Data.ProjectStateProto: [$sel:resolving:ProjectStateProto] :: ProjectStateProto -> Bool
+ Hix.Managed.Data.ProjectStateProto: [$sel:versions:ProjectStateProto] :: ProjectStateProto -> Envs Versions
+ Hix.Managed.Data.ProjectStateProto: data ProjectStateProto
+ Hix.Managed.Data.ProjectStateProto: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Managed.Data.ProjectStateProto.ProjectStateProto
+ Hix.Managed.Data.ProjectStateProto: instance Data.Default.Class.Default Hix.Managed.Data.ProjectStateProto.ProjectStateProto
+ Hix.Managed.Data.ProjectStateProto: instance Distribution.Pretty.Pretty Hix.Managed.Data.ProjectStateProto.ProjectStateProto
+ Hix.Managed.Data.ProjectStateProto: instance GHC.Classes.Eq Hix.Managed.Data.ProjectStateProto.ProjectStateProto
+ Hix.Managed.Data.ProjectStateProto: instance GHC.Generics.Generic Hix.Managed.Data.ProjectStateProto.ProjectStateProto
+ Hix.Managed.Data.ProjectStateProto: instance GHC.Show.Show Hix.Managed.Data.ProjectStateProto.ProjectStateProto
+ Hix.Managed.Data.ProjectStateProto: instance Hix.Class.EncodeNix.EncodeNix Hix.Managed.Data.ProjectStateProto.ProjectStateProto
+ Hix.Managed.Data.Query: Query :: NonEmpty QueryDep -> Query
+ Hix.Managed.Data.Query: RawQuery :: [PackageName] -> RawQuery
+ Hix.Managed.Data.Query: instance GHC.Classes.Eq Hix.Managed.Data.Query.Query
+ Hix.Managed.Data.Query: instance GHC.Classes.Eq Hix.Managed.Data.Query.RawQuery
+ Hix.Managed.Data.Query: instance GHC.Generics.Generic Hix.Managed.Data.Query.Query
+ Hix.Managed.Data.Query: instance GHC.Generics.Generic Hix.Managed.Data.Query.RawQuery
+ Hix.Managed.Data.Query: instance GHC.IsList.IsList Hix.Managed.Data.Query.RawQuery
+ Hix.Managed.Data.Query: instance GHC.Show.Show Hix.Managed.Data.Query.Query
+ Hix.Managed.Data.Query: instance GHC.Show.Show Hix.Managed.Data.Query.RawQuery
+ Hix.Managed.Data.Query: newtype Query
+ Hix.Managed.Data.Query: newtype RawQuery
+ Hix.Managed.Data.QueryDep: QueryDep :: MutableDep -> VersionBounds -> Maybe Version -> Maybe Version -> Maybe Version -> QueryDep
+ Hix.Managed.Data.QueryDep: [$sel:bounds:QueryDep] :: QueryDep -> VersionBounds
+ Hix.Managed.Data.QueryDep: [$sel:current:QueryDep] :: QueryDep -> Maybe Version
+ Hix.Managed.Data.QueryDep: [$sel:installed:QueryDep] :: QueryDep -> Maybe Version
+ Hix.Managed.Data.QueryDep: [$sel:override:QueryDep] :: QueryDep -> Maybe Version
+ Hix.Managed.Data.QueryDep: [$sel:package:QueryDep] :: QueryDep -> MutableDep
+ Hix.Managed.Data.QueryDep: data QueryDep
+ Hix.Managed.Data.QueryDep: instance GHC.Classes.Eq Hix.Managed.Data.QueryDep.QueryDep
+ Hix.Managed.Data.QueryDep: instance GHC.Generics.Generic Hix.Managed.Data.QueryDep.QueryDep
+ Hix.Managed.Data.QueryDep: instance GHC.Show.Show Hix.Managed.Data.QueryDep.QueryDep
+ Hix.Managed.Data.StageContext: StageContext :: EnvContext -> EnvBuilder -> Initial MutationState -> Query -> MutableVersions -> StageContext
+ Hix.Managed.Data.StageContext: [$sel:builder:StageContext] :: StageContext -> EnvBuilder
+ Hix.Managed.Data.StageContext: [$sel:env:StageContext] :: StageContext -> EnvContext
+ Hix.Managed.Data.StageContext: [$sel:initial:StageContext] :: StageContext -> MutableVersions
+ Hix.Managed.Data.StageContext: [$sel:query:StageContext] :: StageContext -> Query
+ Hix.Managed.Data.StageContext: [$sel:state:StageContext] :: StageContext -> Initial MutationState
+ Hix.Managed.Data.StageContext: data StageContext
+ Hix.Managed.Data.StageResult: FailedMutations :: Text -> NonEmpty FailedMutation -> StageFailure
+ Hix.Managed.Data.StageResult: FailedPrecondition :: NonEmpty Text -> StageFailure
+ Hix.Managed.Data.StageResult: StageFailure :: StageFailure -> StageSummary
+ Hix.Managed.Data.StageResult: StageNoAction :: Maybe Text -> StageSummary
+ Hix.Managed.Data.StageResult: StageReport :: Text -> NonEmpty MutableId -> StageSummary
+ Hix.Managed.Data.StageResult: StageResult :: StageSummary -> Maybe MutationState -> StageResult
+ Hix.Managed.Data.StageResult: StageSuccess :: Text -> StageSummary
+ Hix.Managed.Data.StageResult: [$sel:state:StageResult] :: StageResult -> Maybe MutationState
+ Hix.Managed.Data.StageResult: [$sel:summary:StageResult] :: StageResult -> StageSummary
+ Hix.Managed.Data.StageResult: data StageFailure
+ Hix.Managed.Data.StageResult: data StageResult
+ Hix.Managed.Data.StageResult: data StageSummary
+ Hix.Managed.Data.StageResult: instance GHC.Classes.Eq Hix.Managed.Data.StageResult.StageFailure
+ Hix.Managed.Data.StageResult: instance GHC.Classes.Eq Hix.Managed.Data.StageResult.StageResult
+ Hix.Managed.Data.StageResult: instance GHC.Classes.Eq Hix.Managed.Data.StageResult.StageSummary
+ Hix.Managed.Data.StageResult: instance GHC.Generics.Generic Hix.Managed.Data.StageResult.StageFailure
+ Hix.Managed.Data.StageResult: instance GHC.Generics.Generic Hix.Managed.Data.StageResult.StageResult
+ Hix.Managed.Data.StageResult: instance GHC.Generics.Generic Hix.Managed.Data.StageResult.StageSummary
+ Hix.Managed.Data.StageResult: instance GHC.Show.Show Hix.Managed.Data.StageResult.StageFailure
+ Hix.Managed.Data.StageResult: instance GHC.Show.Show Hix.Managed.Data.StageResult.StageResult
+ Hix.Managed.Data.StageResult: instance GHC.Show.Show Hix.Managed.Data.StageResult.StageSummary
+ Hix.Managed.Data.StageResult: stageFailures :: StageSummary -> [FailedMutation]
+ Hix.Managed.Data.StageState: CandidateBuilt :: MutableId -> BuildSuccess
+ Hix.Managed.Data.StageState: Failure :: BuildStatus
+ Hix.Managed.Data.StageState: StageState :: Map MutableDep BuildSuccess -> [DepMutation a] -> MutationState -> Natural -> s -> StageState a s
+ Hix.Managed.Data.StageState: Success :: BuildStatus
+ Hix.Managed.Data.StageState: Unmodified :: MutableDep -> BuildSuccess
+ Hix.Managed.Data.StageState: [$sel:ext:StageState] :: StageState a s -> s
+ Hix.Managed.Data.StageState: [$sel:failed:StageState] :: StageState a s -> [DepMutation a]
+ Hix.Managed.Data.StageState: [$sel:iterations:StageState] :: StageState a s -> Natural
+ Hix.Managed.Data.StageState: [$sel:state:StageState] :: StageState a s -> MutationState
+ Hix.Managed.Data.StageState: [$sel:success:StageState] :: StageState a s -> Map MutableDep BuildSuccess
+ Hix.Managed.Data.StageState: buildStatus :: Bool -> BuildStatus
+ Hix.Managed.Data.StageState: buildSuccessPackage :: BuildSuccess -> MutableDep
+ Hix.Managed.Data.StageState: data BuildStatus
+ Hix.Managed.Data.StageState: data BuildSuccess
+ Hix.Managed.Data.StageState: data StageState a s
+ Hix.Managed.Data.StageState: initStageState :: Initial MutationState -> s -> StageState a s
+ Hix.Managed.Data.StageState: instance (GHC.Classes.Eq a, GHC.Classes.Eq s) => GHC.Classes.Eq (Hix.Managed.Data.StageState.StageState a s)
+ Hix.Managed.Data.StageState: instance (GHC.Show.Show a, GHC.Show.Show s) => GHC.Show.Show (Hix.Managed.Data.StageState.StageState a s)
+ Hix.Managed.Data.StageState: instance GHC.Classes.Eq Hix.Managed.Data.StageState.BuildStatus
+ Hix.Managed.Data.StageState: instance GHC.Classes.Eq Hix.Managed.Data.StageState.BuildSuccess
+ Hix.Managed.Data.StageState: instance GHC.Generics.Generic Hix.Managed.Data.StageState.BuildStatus
+ Hix.Managed.Data.StageState: instance GHC.Generics.Generic Hix.Managed.Data.StageState.BuildSuccess
+ Hix.Managed.Data.StageState: instance GHC.Show.Show Hix.Managed.Data.StageState.BuildStatus
+ Hix.Managed.Data.StageState: instance GHC.Show.Show Hix.Managed.Data.StageState.BuildSuccess
+ Hix.Managed.Data.StageState: justSuccess :: a -> BuildStatus -> Maybe a
+ Hix.Managed.Data.StageState: modifiedCandidates :: [BuildSuccess] -> [MutableId]
+ Hix.Managed.Data.StateFileConfig: StateFileConfig :: Path Rel File -> Maybe (Path Abs Dir) -> StateFileConfig
+ Hix.Managed.Data.StateFileConfig: [$sel:file:StateFileConfig] :: StateFileConfig -> Path Rel File
+ Hix.Managed.Data.StateFileConfig: [$sel:projectRoot:StateFileConfig] :: StateFileConfig -> Maybe (Path Abs Dir)
+ Hix.Managed.Data.StateFileConfig: data StateFileConfig
+ Hix.Managed.Data.StateFileConfig: instance Data.Default.Class.Default Hix.Managed.Data.StateFileConfig.StateFileConfig
+ Hix.Managed.Data.StateFileConfig: instance GHC.Classes.Eq Hix.Managed.Data.StateFileConfig.StateFileConfig
+ Hix.Managed.Data.StateFileConfig: instance GHC.Generics.Generic Hix.Managed.Data.StateFileConfig.StateFileConfig
+ Hix.Managed.Data.StateFileConfig: instance GHC.Show.Show Hix.Managed.Data.StateFileConfig.StateFileConfig
+ Hix.Managed.Data.Targets: allMTargets :: Monad m => (LocalPackage -> m Bool) -> Targets -> m Bool
+ Hix.Managed.Data.Targets: data Targets
+ Hix.Managed.Data.Targets: getTargets :: Targets -> [LocalPackage]
+ Hix.Managed.Data.Targets: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Managed.Data.Targets.EnvMember
+ Hix.Managed.Data.Targets: instance Data.Aeson.Types.FromJSON.FromJSONKey Hix.Managed.Data.Targets.EnvMember
+ Hix.Managed.Data.Targets: instance Data.String.IsString Hix.Managed.Data.Targets.EnvMember
+ Hix.Managed.Data.Targets: instance Data.String.IsString Hix.Managed.Data.Targets.Targets
+ Hix.Managed.Data.Targets: instance Distribution.Pretty.Pretty Hix.Managed.Data.Targets.EnvMember
+ Hix.Managed.Data.Targets: instance GHC.Classes.Eq Hix.Managed.Data.Targets.EnvMember
+ Hix.Managed.Data.Targets: instance GHC.Classes.Eq Hix.Managed.Data.Targets.Targets
+ Hix.Managed.Data.Targets: instance GHC.Classes.Ord Hix.Managed.Data.Targets.EnvMember
+ Hix.Managed.Data.Targets: instance GHC.Generics.Generic Hix.Managed.Data.Targets.EnvMember
+ Hix.Managed.Data.Targets: instance GHC.Show.Show Hix.Managed.Data.Targets.EnvMember
+ Hix.Managed.Data.Targets: instance GHC.Show.Show Hix.Managed.Data.Targets.Targets
+ Hix.Managed.Data.Targets: instance Hix.Class.EncodeNix.EncodeNixKey Hix.Managed.Data.Targets.EnvMember
+ Hix.Managed.Data.Targets: overTargets :: Targets -> (a -> a) -> Packages a -> Packages a
+ Hix.Managed.Data.Targets: pattern Targets :: [LocalPackage] -> Targets
+ Hix.Managed.Data.Targets: singleTarget :: LocalPackage -> Targets
+ Hix.Managed.Data.Targets: sortTargets :: Packages [LocalPackage] -> [LocalPackage] -> Targets
+ Hix.Managed.Data.Targets: targetsSet :: Targets -> Set LocalPackage
+ Hix.Managed.Data.Targets: unsafeTargets :: [LocalPackage] -> Targets
+ Hix.Managed.Diff: applyBoundsChange :: BoundsChange -> VersionBounds -> VersionBounds
+ Hix.Managed.Diff: applyVersionChange :: VersionChange -> Maybe Version -> Maybe Version
+ Hix.Managed.Diff: boundsChange :: VersionBounds -> VersionBounds -> BoundsChange
+ Hix.Managed.Diff: boundsDiffDetail :: VersionBounds -> VersionBounds -> Maybe BoundsDiffDetail
+ Hix.Managed.Diff: changeOriginal :: Change d a -> Maybe a
+ Hix.Managed.Diff: diff :: (a -> a -> Maybe d) -> a -> a -> Change d a
+ Hix.Managed.Diff: diffMaybe :: (a -> a -> Maybe d) -> Maybe a -> Maybe a -> Change d a
+ Hix.Managed.Diff: diffOriginal :: Diff d a -> Maybe a
+ Hix.Managed.Diff: initChanges :: NMap map1 k (Maybe v1) s1 => NMap map2 k (Change d v1) s2 => map1 -> map2
+ Hix.Managed.Diff: reifyBoundsChange :: BoundsChange -> VersionBounds
+ Hix.Managed.Diff: reifyBoundsChangeMaybe :: BoundsChange -> Maybe VersionBounds
+ Hix.Managed.Diff: reifyBoundsChanges :: MutableDeps BoundsChange -> MutableBounds
+ Hix.Managed.Diff: reifyChange :: a -> Change d a -> a
+ Hix.Managed.Diff: reifyChangeMaybe :: Change d a -> Maybe a
+ Hix.Managed.Diff: reifyChangeWith :: b -> (a -> b) -> Change d a -> b
+ Hix.Managed.Diff: reifyVersionChange :: VersionChange -> Maybe Version
+ Hix.Managed.Diff: reifyVersionChanges :: MutableDeps VersionChange -> MutableVersions
+ Hix.Managed.Diff: updateBoundsChange :: VersionBounds -> BoundsChange -> BoundsChange
+ Hix.Managed.Diff: updateBoundsChanges :: NMap vmap MutableDep VersionBounds s1 => NMap map MutableDep BoundsChange s2 => vmap -> map -> map
+ Hix.Managed.Diff: updateVersionChange :: Version -> VersionChange -> VersionChange
+ Hix.Managed.Diff: updateVersionChanges :: NMap vmap MutableDep (Maybe Version) s1 => NMap map MutableDep VersionChange s2 => vmap -> map -> map
+ Hix.Managed.Diff: versionChange :: Maybe Version -> Maybe Version -> VersionChange
+ Hix.Managed.Diff: versionDiff :: Maybe Version -> Maybe Version -> Maybe (Diff () Version)
+ Hix.Managed.Diff: versionDiffDetail :: Version -> Version -> Maybe ()
+ Hix.Managed.EnvContext: envContext :: ProjectOptions -> Packages ManagedPackage -> Maybe (NonEmpty MutableDep) -> EnvName -> EnvConfig -> Either EnvDeps EnvContext
+ Hix.Managed.EnvContext: envContexts :: ProjectOptions -> Packages ManagedPackage -> Envs EnvConfig -> Maybe (NonEmpty MutableDep) -> M (Envs (Either EnvDeps EnvContext))
+ Hix.Managed.EnvContext: unknownTargets :: EnvName -> NonEmpty LocalPackage -> M ()
+ Hix.Managed.EnvRequest: initialEnvState :: EnvContext -> ProjectState -> Initial EnvState
+ Hix.Managed.EnvRequest: updateProcessState :: EnvContext -> Initial EnvState -> EnvResult -> ProcessState -> ProcessState
+ Hix.Managed.EnvRequest: withEnvRequest :: BuildHandlers -> ProcessState -> EnvContext -> Builder -> (EnvRequest -> M EnvResult) -> M (ProcessState, EnvResult)
+ Hix.Managed.EnvResult: BoundsModification :: These (Maybe Version) (Maybe Version) -> BoundsModification
+ Hix.Managed.EnvResult: DepAdded :: Maybe BoundsModification -> DepModification
+ Hix.Managed.EnvResult: DepModified :: DepModification -> DepResultDetail
+ Hix.Managed.EnvResult: DepResult :: MutableDep -> Version -> VersionBounds -> DepResultDetail -> DepResult
+ Hix.Managed.EnvResult: DepResults :: [DepResult] -> [DepResult] -> [DepResult] -> DepResults
+ Hix.Managed.EnvResult: DepUnmodified :: DepResultDetail
+ Hix.Managed.EnvResult: DepUpdated :: These Version BoundsModification -> DepModification
+ Hix.Managed.EnvResult: [$sel:added:DepResults] :: DepResults -> [DepResult]
+ Hix.Managed.EnvResult: [$sel:bounds:DepResult] :: DepResult -> VersionBounds
+ Hix.Managed.EnvResult: [$sel:detail:DepResult] :: DepResult -> DepResultDetail
+ Hix.Managed.EnvResult: [$sel:package:DepResult] :: DepResult -> MutableDep
+ Hix.Managed.EnvResult: [$sel:unmodified:DepResults] :: DepResults -> [DepResult]
+ Hix.Managed.EnvResult: [$sel:updated:DepResults] :: DepResults -> [DepResult]
+ Hix.Managed.EnvResult: [$sel:version:DepResult] :: DepResult -> Version
+ Hix.Managed.EnvResult: data DepModification
+ Hix.Managed.EnvResult: data DepResult
+ Hix.Managed.EnvResult: data DepResultDetail
+ Hix.Managed.EnvResult: data DepResults
+ Hix.Managed.EnvResult: depResult :: MutableDep -> VersionChange -> BoundsChange -> Maybe DepResult
+ Hix.Managed.EnvResult: depResultId :: DepResult -> MutableId
+ Hix.Managed.EnvResult: deps :: EnvResult -> [DepResult]
+ Hix.Managed.EnvResult: failures :: EnvResult -> [FailedMutation]
+ Hix.Managed.EnvResult: grouped :: EnvResult -> DepResults
+ Hix.Managed.EnvResult: instance GHC.Base.Monoid Hix.Managed.EnvResult.DepResults
+ Hix.Managed.EnvResult: instance GHC.Base.Semigroup Hix.Managed.EnvResult.DepResults
+ Hix.Managed.EnvResult: instance GHC.Classes.Eq Hix.Managed.EnvResult.BoundsModification
+ Hix.Managed.EnvResult: instance GHC.Classes.Eq Hix.Managed.EnvResult.DepModification
+ Hix.Managed.EnvResult: instance GHC.Classes.Eq Hix.Managed.EnvResult.DepResult
+ Hix.Managed.EnvResult: instance GHC.Classes.Eq Hix.Managed.EnvResult.DepResultDetail
+ Hix.Managed.EnvResult: instance GHC.Classes.Eq Hix.Managed.EnvResult.DepResults
+ Hix.Managed.EnvResult: instance GHC.Generics.Generic Hix.Managed.EnvResult.BoundsModification
+ Hix.Managed.EnvResult: instance GHC.Generics.Generic Hix.Managed.EnvResult.DepModification
+ Hix.Managed.EnvResult: instance GHC.Generics.Generic Hix.Managed.EnvResult.DepResult
+ Hix.Managed.EnvResult: instance GHC.Generics.Generic Hix.Managed.EnvResult.DepResultDetail
+ Hix.Managed.EnvResult: instance GHC.Generics.Generic Hix.Managed.EnvResult.DepResults
+ Hix.Managed.EnvResult: instance GHC.Show.Show Hix.Managed.EnvResult.BoundsModification
+ Hix.Managed.EnvResult: instance GHC.Show.Show Hix.Managed.EnvResult.DepModification
+ Hix.Managed.EnvResult: instance GHC.Show.Show Hix.Managed.EnvResult.DepResult
+ Hix.Managed.EnvResult: instance GHC.Show.Show Hix.Managed.EnvResult.DepResultDetail
+ Hix.Managed.EnvResult: instance GHC.Show.Show Hix.Managed.EnvResult.DepResults
+ Hix.Managed.EnvResult: newtype BoundsModification
+ Hix.Managed.EnvResult: normalizeDepResults :: DepResults -> DepResults
+ Hix.Managed.Flow: data Flow x
+ Hix.Managed.Flow: evalFlow :: EnvRequest -> Flow o -> M o
+ Hix.Managed.Flow: evalStage :: Text -> (StageContext -> M (StageResult, o)) -> Flow o
+ Hix.Managed.Flow: evalStageState :: (EnvState -> StageContext -> a) -> Flow a
+ Hix.Managed.Flow: execFlow :: EnvRequest -> Flow () -> M EnvResult
+ Hix.Managed.Flow: execStage :: Text -> (StageContext -> M StageResult) -> Flow BuildStatus
+ Hix.Managed.Flow: execStatelessStage :: Text -> (StageContext -> M StageSummary) -> Flow BuildStatus
+ Hix.Managed.Flow: instance GHC.Base.Applicative Hix.Managed.Flow.Flow
+ Hix.Managed.Flow: instance GHC.Base.Functor Hix.Managed.Flow.Flow
+ Hix.Managed.Flow: instance GHC.Base.Monad Hix.Managed.Flow.Flow
+ Hix.Managed.Flow: instance GHC.Generics.Generic Hix.Managed.Flow.FlowState
+ Hix.Managed.Flow: liftM :: M a -> Flow a
+ Hix.Managed.Flow: runFlow :: EnvRequest -> Flow o -> M (o, EnvResult)
+ Hix.Managed.Flow: runStage :: forall o. Text -> (StageContext -> M (StageResult, o)) -> Flow (BuildStatus, o)
+ Hix.Managed.Flow: runStage_ :: Text -> (StageContext -> M StageResult) -> Flow ()
+ Hix.Managed.Flow: stageError :: Text -> Flow ()
+ Hix.Managed.Handlers.Build: BuildHandlers :: StateFileHandlers -> ReportHandlers -> (Packages ManagedPackage -> GhcDb -> M CabalHandlers) -> (forall a. (Builder -> M a) -> M a) -> (PackageName -> M [Version]) -> (PackageName -> M (Maybe Version)) -> BuildHandlers
+ Hix.Managed.Handlers.Build: BuildOutputsPrefix :: Text -> BuildOutputsPrefix
+ Hix.Managed.Handlers.Build: Builder :: (forall a. CabalHandlers -> EnvContext -> Initial EnvState -> (EnvBuilder -> M a) -> M a) -> Builder
+ Hix.Managed.Handlers.Build: EnvBuilder :: CabalHandlers -> (Versions -> [PackageId] -> M (Overrides, BuildStatus)) -> EnvBuilder
+ Hix.Managed.Handlers.Build: TestBumpHandlers :: SpecialBuildHandlers
+ Hix.Managed.Handlers.Build: [$sel:buildWithState:EnvBuilder] :: EnvBuilder -> Versions -> [PackageId] -> M (Overrides, BuildStatus)
+ Hix.Managed.Handlers.Build: [$sel:cabal:BuildHandlers] :: BuildHandlers -> Packages ManagedPackage -> GhcDb -> M CabalHandlers
+ Hix.Managed.Handlers.Build: [$sel:cabal:EnvBuilder] :: EnvBuilder -> CabalHandlers
+ Hix.Managed.Handlers.Build: [$sel:latestVersion:BuildHandlers] :: BuildHandlers -> PackageName -> M (Maybe Version)
+ Hix.Managed.Handlers.Build: [$sel:report:BuildHandlers] :: BuildHandlers -> ReportHandlers
+ Hix.Managed.Handlers.Build: [$sel:stateFile:BuildHandlers] :: BuildHandlers -> StateFileHandlers
+ Hix.Managed.Handlers.Build: [$sel:versions:BuildHandlers] :: BuildHandlers -> PackageName -> M [Version]
+ Hix.Managed.Handlers.Build: [$sel:withBuilder:BuildHandlers] :: BuildHandlers -> forall a. (Builder -> M a) -> M a
+ Hix.Managed.Handlers.Build: [$sel:withEnvBuilder:Builder] :: Builder -> forall a. CabalHandlers -> EnvContext -> Initial EnvState -> (EnvBuilder -> M a) -> M a
+ Hix.Managed.Handlers.Build: data BuildHandlers
+ Hix.Managed.Handlers.Build: data Builder
+ Hix.Managed.Handlers.Build: data EnvBuilder
+ Hix.Managed.Handlers.Build: data SpecialBuildHandlers
+ Hix.Managed.Handlers.Build: handlersNull :: BuildHandlers
+ Hix.Managed.Handlers.Build: instance Data.Aeson.Types.FromJSON.FromJSON Hix.Managed.Handlers.Build.BuildOutputsPrefix
+ Hix.Managed.Handlers.Build: instance Data.String.IsString Hix.Managed.Handlers.Build.BuildOutputsPrefix
+ Hix.Managed.Handlers.Build: instance GHC.Classes.Eq Hix.Managed.Handlers.Build.BuildOutputsPrefix
+ Hix.Managed.Handlers.Build: instance GHC.Classes.Eq Hix.Managed.Handlers.Build.SpecialBuildHandlers
+ Hix.Managed.Handlers.Build: instance GHC.Classes.Ord Hix.Managed.Handlers.Build.BuildOutputsPrefix
+ Hix.Managed.Handlers.Build: instance GHC.Generics.Generic Hix.Managed.Handlers.Build.BuildOutputsPrefix
+ Hix.Managed.Handlers.Build: instance GHC.Show.Show Hix.Managed.Handlers.Build.BuildOutputsPrefix
+ Hix.Managed.Handlers.Build: instance GHC.Show.Show Hix.Managed.Handlers.Build.SpecialBuildHandlers
+ Hix.Managed.Handlers.Build: logCabal :: MonadIO m => BuildHandlers -> m (IORef [(EnvConstraints, Maybe SolverPlan)], BuildHandlers)
+ Hix.Managed.Handlers.Build: newtype BuildOutputsPrefix
+ Hix.Managed.Handlers.Build: runBuilder :: Builder -> CabalHandlers -> EnvContext -> Initial EnvState -> (EnvBuilder -> M a) -> M a
+ Hix.Managed.Handlers.Build: testBuilder :: (Versions -> [PackageId] -> M (Overrides, BuildStatus)) -> (Builder -> M a) -> M a
+ Hix.Managed.Handlers.Build: versionsBuilder :: HackageHandlers -> (Versions -> M BuildStatus) -> (Builder -> M a) -> M a
+ Hix.Managed.Handlers.Build: wrapCabal :: (CabalHandlers -> CabalHandlers) -> BuildHandlers -> BuildHandlers
+ Hix.Managed.Handlers.Build.Prod: BuilderResources :: HackageHandlers -> StateFileHandlers -> Envs EnvConfig -> Maybe BuildOutputsPrefix -> Path Abs Dir -> BuilderResources
+ Hix.Managed.Handlers.Build.Prod: EnvBuilderResources :: BuilderResources -> EnvContext -> EnvBuilderResources
+ Hix.Managed.Handlers.Build.Prod: [$sel:buildOutputsPrefix:BuilderResources] :: BuilderResources -> Maybe BuildOutputsPrefix
+ Hix.Managed.Handlers.Build.Prod: [$sel:context:EnvBuilderResources] :: EnvBuilderResources -> EnvContext
+ Hix.Managed.Handlers.Build.Prod: [$sel:envsConf:BuilderResources] :: BuilderResources -> Envs EnvConfig
+ Hix.Managed.Handlers.Build.Prod: [$sel:global:EnvBuilderResources] :: EnvBuilderResources -> BuilderResources
+ Hix.Managed.Handlers.Build.Prod: [$sel:hackage:BuilderResources] :: BuilderResources -> HackageHandlers
+ Hix.Managed.Handlers.Build.Prod: [$sel:root:BuilderResources] :: BuilderResources -> Path Abs Dir
+ Hix.Managed.Handlers.Build.Prod: [$sel:stateFileHandlers:BuilderResources] :: BuilderResources -> StateFileHandlers
+ Hix.Managed.Handlers.Build.Prod: buildPackage :: Path Abs Dir -> EnvName -> LocalPackage -> M Bool
+ Hix.Managed.Handlers.Build.Prod: buildWithState :: EnvBuilderResources -> Versions -> [PackageId] -> M (Overrides, BuildStatus)
+ Hix.Managed.Handlers.Build.Prod: data BuilderResources
+ Hix.Managed.Handlers.Build.Prod: data EnvBuilderResources
+ Hix.Managed.Handlers.Build.Prod: handlersProd :: MonadIO m => StateFileConfig -> Envs EnvConfig -> Maybe BuildOutputsPrefix -> CabalConfig -> Bool -> m BuildHandlers
+ Hix.Managed.Handlers.Build.Prod: nixProc :: Path Abs Dir -> [Text] -> Text -> [Text] -> M (ProcessConfig () () ())
+ Hix.Managed.Handlers.Build.Prod: withBuilder :: HackageHandlers -> StateFileHandlers -> StateFileConfig -> Envs EnvConfig -> Maybe BuildOutputsPrefix -> (Builder -> M a) -> M a
+ Hix.Managed.Handlers.Build.Prod: withEnvBuilder :: forall a. BuilderResources -> CabalHandlers -> EnvContext -> Initial EnvState -> (EnvBuilder -> M a) -> M a
+ Hix.Managed.Handlers.Build.Prod: withTempProject :: Maybe (Path Abs Dir) -> (Path Abs Dir -> M a) -> M a
+ Hix.Managed.Handlers.Build.Test: chooseHandlers :: MonadIO m => StateFileConfig -> Envs EnvConfig -> Maybe BuildOutputsPrefix -> CabalConfig -> Maybe SpecialBuildHandlers -> m BuildHandlers
+ Hix.Managed.Handlers.Build.Test: handlersBumpTest :: MonadIO m => StateFileConfig -> Envs EnvConfig -> Maybe BuildOutputsPrefix -> CabalConfig -> Bool -> m BuildHandlers
+ Hix.Managed.Handlers.Build.Test: handlersUnitTest :: MonadIO m => GhcPackages -> (Versions -> M BuildStatus) -> m (BuildHandlers, IORef [Expr], IORef [FailedMutation])
+ Hix.Managed.Handlers.Build.Test: latestVersionNixTestBump :: PackageName -> M (Maybe Version)
+ Hix.Managed.Handlers.Cabal: CabalHandlers :: (SolverState -> M (Maybe SolverPlan)) -> (PackageName -> Maybe Version) -> CabalHandlers
+ Hix.Managed.Handlers.Cabal: [$sel:installedVersion:CabalHandlers] :: CabalHandlers -> PackageName -> Maybe Version
+ Hix.Managed.Handlers.Cabal: [$sel:solveForVersion:CabalHandlers] :: CabalHandlers -> SolverState -> M (Maybe SolverPlan)
+ Hix.Managed.Handlers.Cabal: data CabalHandlers
+ Hix.Managed.Handlers.Cabal: handlersNull :: CabalHandlers
+ Hix.Managed.Handlers.Cabal: installedVersions :: CabalHandlers -> Set MutableDep -> MutableVersions
+ Hix.Managed.Handlers.Cabal: logCabal :: IORef [(EnvConstraints, Maybe SolverPlan)] -> CabalHandlers -> CabalHandlers
+ Hix.Managed.Handlers.Cabal.Prod: handlersProd :: CabalConfig -> Bool -> Packages ManagedPackage -> GhcDb -> M CabalHandlers
+ Hix.Managed.Handlers.Cabal.Prod: handlersTest :: CabalConfig -> Bool -> Packages ManagedPackage -> GhcDb -> M CabalHandlers
+ Hix.Managed.Handlers.Cabal.Prod: handlersWith :: (SolveResources -> SolveResources) -> CabalConfig -> Bool -> Packages ManagedPackage -> GhcDb -> M CabalHandlers
+ Hix.Managed.Handlers.Cabal.Prod: removeLaterVersions :: PackageId -> PackageIndex UnresolvedSourcePackage -> PackageIndex UnresolvedSourcePackage
+ Hix.Managed.Handlers.Cabal.Prod: testPackagesBump :: Map PackageName PackageId
+ Hix.Managed.Handlers.Cabal.Prod: testResources :: SolveResources -> SolveResources
+ Hix.Managed.Handlers.Hackage: HackageHandlers :: (PackageId -> M SourceHash) -> HackageHandlers
+ Hix.Managed.Handlers.Hackage: [$sel:fetchHash:HackageHandlers] :: HackageHandlers -> PackageId -> M SourceHash
+ Hix.Managed.Handlers.Hackage: data HackageHandlers
+ Hix.Managed.Handlers.Hackage: handlersNull :: HackageHandlers
+ Hix.Managed.Handlers.Hackage.Prod: handlersProd :: MonadIO m => m HackageHandlers
+ Hix.Managed.Handlers.Mutation: MutationHandlers :: (s -> DepMutation a -> (BuildMutation -> M (Maybe MutationState)) -> M (MutationResult s)) -> MutationHandlers a s
+ Hix.Managed.Handlers.Mutation: [$sel:process:MutationHandlers] :: MutationHandlers a s -> s -> DepMutation a -> (BuildMutation -> M (Maybe MutationState)) -> M (MutationResult s)
+ Hix.Managed.Handlers.Mutation: data MutationHandlers a s
+ Hix.Managed.Handlers.Mutation.Bump: handlersBump :: MutationHandlers Bump SolverState
+ Hix.Managed.Handlers.Mutation.Bump: processMutationBump :: SolverState -> DepMutation Bump -> (BuildMutation -> M (Maybe MutationState)) -> M (MutationResult SolverState)
+ Hix.Managed.Handlers.Mutation.Bump: updateBound :: Version -> VersionBounds -> VersionBounds
+ Hix.Managed.Handlers.Mutation.Bump: updateConstraintsBump :: MutableId -> PackageId -> MutationConstraints -> MutationConstraints
+ Hix.Managed.Handlers.Mutation.Lower: handlersLower :: BuildConfig -> LowerMode -> (Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints) -> MutationHandlers Lower SolverState
+ Hix.Managed.Handlers.Mutation.Lower: processMutationLower :: BuildConfig -> LowerMode -> (Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints) -> SolverState -> DepMutation Lower -> (BuildMutation -> M (Maybe MutationState)) -> M (MutationResult SolverState)
+ Hix.Managed.Handlers.Report: ReportHandlers :: (ProjectResult -> M ()) -> ReportHandlers
+ Hix.Managed.Handlers.Report: [$sel:mutations:ReportHandlers] :: ReportHandlers -> ProjectResult -> M ()
+ Hix.Managed.Handlers.Report: data ReportHandlers
+ Hix.Managed.Handlers.Report: handlersNull :: ReportHandlers
+ Hix.Managed.Handlers.Report.Prod: blankLine :: M ()
+ Hix.Managed.Handlers.Report.Prod: envResult :: EnvResult -> M ()
+ Hix.Managed.Handlers.Report.Prod: formatBoundsModification :: VersionBounds -> BoundsModification -> Text
+ Hix.Managed.Handlers.Report.Prod: formatDep :: MutableDep -> Version -> VersionBounds -> Maybe BoundsModification -> (Text, Text, Text)
+ Hix.Managed.Handlers.Report.Prod: formatDepLine :: MutableDep -> Text -> Text -> (Text, Text, Text)
+ Hix.Managed.Handlers.Report.Prod: formatDepResult :: DepResult -> Maybe (Text, Text, Text)
+ Hix.Managed.Handlers.Report.Prod: formatDepUpdate :: MutableDep -> Version -> VersionBounds -> These Version BoundsModification -> (Text, Text, Text)
+ Hix.Managed.Handlers.Report.Prod: handlersProd :: ReportHandlers
+ Hix.Managed.Handlers.Report.Prod: listFailed :: FailedMutation -> Text
+ Hix.Managed.Handlers.Report.Prod: mutations :: ProjectResult -> M ()
+ Hix.Managed.Handlers.Report.Prod: printAligned :: [(Text, Text, Text)] -> M ()
+ Hix.Managed.Handlers.Report.Prod: printBounds :: (Version -> Text) -> (Version -> Text) -> Maybe Version -> Maybe Version -> Text
+ Hix.Managed.Handlers.Report.Prod: printSummary :: StageSummary -> M ()
+ Hix.Managed.Handlers.Report.Prod: reportFailed :: NonEmpty FailedMutation -> M ()
+ Hix.Managed.Handlers.Report.Prod: reportNewVersions :: NonEmpty MutableId -> M ()
+ Hix.Managed.Handlers.Report.Test: handlersUnitTest :: MonadIO m => m (ReportHandlers, IORef [FailedMutation])
+ Hix.Managed.Handlers.Report.Test: reportMutationsIORef :: IORef [FailedMutation] -> ProjectResult -> M ()
+ Hix.Managed.Handlers.StateFile: StateFileHandlers :: (Maybe (Path Abs Dir) -> Expr -> M ()) -> StateFileHandlers
+ Hix.Managed.Handlers.StateFile: [$sel:writeFile:StateFileHandlers] :: StateFileHandlers -> Maybe (Path Abs Dir) -> Expr -> M ()
+ Hix.Managed.Handlers.StateFile: data StateFileHandlers
+ Hix.Managed.Handlers.StateFile: handlersNull :: StateFileHandlers
+ Hix.Managed.Handlers.StateFile.Prod: handlersProd :: StateFileConfig -> StateFileHandlers
+ Hix.Managed.Handlers.StateFile.Prod: initFile :: StateFileConfig -> Maybe (Path Abs Dir) -> M (Path Abs File)
+ Hix.Managed.Handlers.StateFile.Prod: setDepsFileWritable :: Path Abs File -> M ()
+ Hix.Managed.Handlers.StateFile.Prod: writeFile :: StateFileConfig -> Maybe (Path Abs Dir) -> Expr -> M ()
+ Hix.Managed.Handlers.StateFile.Test: handlersUnitTest :: MonadIO m => m (StateFileHandlers, IORef [Expr])
+ Hix.Managed.Handlers.StateFile.Test: writeFileIORef :: IORef [Expr] -> Maybe a -> Expr -> M ()
+ Hix.Managed.Lower.App: lowerAutoCli :: LowerOptions -> M ()
+ Hix.Managed.Lower.App: lowerCli :: (LowerConfig -> BuildHandlers -> ProjectContext -> M ProjectResult) -> LowerOptions -> M ()
+ Hix.Managed.Lower.App: lowerInitCli :: LowerOptions -> M ()
+ Hix.Managed.Lower.App: lowerOptimizeCli :: LowerOptions -> M ()
+ Hix.Managed.Lower.App: lowerStabilizeCli :: LowerOptions -> M ()
+ Hix.Managed.Lower.Auto: lowerAutoMain :: LowerConfig -> BuildHandlers -> ProjectContext -> M ProjectResult
+ Hix.Managed.Lower.Auto: lowerAutoStages :: BuildHandlers -> LowerConfig -> BuildConfig -> Flow ()
+ Hix.Managed.Lower.Auto: optimizePristineBounds :: BuildHandlers -> BuildConfig -> Flow ()
+ Hix.Managed.Lower.Auto: postInit :: BuildHandlers -> LowerConfig -> BuildConfig -> Flow ()
+ Hix.Managed.Lower.Auto: pristineBounds :: EnvState -> Query -> Maybe Query
+ Hix.Managed.Lower.Auto: pristineBoundsQuery :: Flow (Maybe Query)
+ Hix.Managed.Lower.Auto: stabilizeInitFailure :: BuildHandlers -> LowerConfig -> BuildConfig -> Flow ()
+ Hix.Managed.Lower.Auto: suggestStabilize :: Flow ()
+ Hix.Managed.Lower.Candidates: InitAll :: InitConfig
+ Hix.Managed.Lower.Candidates: InitBeforeUpper :: Int -> Int -> InitConfig
+ Hix.Managed.Lower.Candidates: OptimizeMajorsBefore :: Int -> Int -> OptimizeConfig
+ Hix.Managed.Lower.Candidates: OptimizeNoBound :: OptimizeConfig
+ Hix.Managed.Lower.Candidates: StabilizeFromVersion :: Version -> Maybe Version -> StabilizeConfig
+ Hix.Managed.Lower.Candidates: StabilizeNoBound :: InitConfig -> StabilizeConfig
+ Hix.Managed.Lower.Candidates: candidates :: (PackageName -> M [Version]) -> QueryDep -> Bool -> ([Version] -> Maybe (NonEmpty Major)) -> M (Maybe (DepMutation Lower))
+ Hix.Managed.Lower.Candidates: candidatesInit :: (PackageName -> M [Version]) -> Set MutableDep -> QueryDep -> M (Maybe (DepMutation Lower))
+ Hix.Managed.Lower.Candidates: candidatesOptimize :: (PackageName -> M [Version]) -> MutableVersions -> QueryDep -> M (Maybe (DepMutation Lower))
+ Hix.Managed.Lower.Candidates: candidatesStabilize :: (PackageName -> M [Version]) -> QueryDep -> Maybe Version -> M (Maybe (DepMutation Lower))
+ Hix.Managed.Lower.Candidates: data InitConfig
+ Hix.Managed.Lower.Candidates: data OptimizeConfig
+ Hix.Managed.Lower.Candidates: data StabilizeConfig
+ Hix.Managed.Lower.Candidates: initConfig :: VersionBounds -> InitConfig
+ Hix.Managed.Lower.Candidates: instance GHC.Classes.Eq Hix.Managed.Lower.Candidates.InitConfig
+ Hix.Managed.Lower.Candidates: instance GHC.Classes.Eq Hix.Managed.Lower.Candidates.OptimizeConfig
+ Hix.Managed.Lower.Candidates: instance GHC.Classes.Eq Hix.Managed.Lower.Candidates.StabilizeConfig
+ Hix.Managed.Lower.Candidates: instance GHC.Generics.Generic Hix.Managed.Lower.Candidates.InitConfig
+ Hix.Managed.Lower.Candidates: instance GHC.Generics.Generic Hix.Managed.Lower.Candidates.OptimizeConfig
+ Hix.Managed.Lower.Candidates: instance GHC.Generics.Generic Hix.Managed.Lower.Candidates.StabilizeConfig
+ Hix.Managed.Lower.Candidates: instance GHC.Show.Show Hix.Managed.Lower.Candidates.InitConfig
+ Hix.Managed.Lower.Candidates: instance GHC.Show.Show Hix.Managed.Lower.Candidates.OptimizeConfig
+ Hix.Managed.Lower.Candidates: instance GHC.Show.Show Hix.Managed.Lower.Candidates.StabilizeConfig
+ Hix.Managed.Lower.Candidates: logInitConfig :: MutableDep -> InitConfig -> M ()
+ Hix.Managed.Lower.Candidates: logNoVersions :: MutableDep -> [Version] -> Maybe a -> M (Maybe a)
+ Hix.Managed.Lower.Candidates: logOptimizeConfig :: MutableDep -> OptimizeConfig -> M ()
+ Hix.Managed.Lower.Candidates: logStabilizeConfig :: MutableDep -> StabilizeConfig -> M ()
+ Hix.Managed.Lower.Candidates: optimizeConfig :: Maybe Version -> VersionBounds -> OptimizeConfig
+ Hix.Managed.Lower.Candidates: prefix :: Int -> Int -> Text
+ Hix.Managed.Lower.Candidates: selectionInit :: InitConfig -> [Version] -> Maybe (NonEmpty Major)
+ Hix.Managed.Lower.Candidates: selectionOptimize :: OptimizeConfig -> [Version] -> Maybe (NonEmpty Major)
+ Hix.Managed.Lower.Candidates: selectionStabilize :: StabilizeConfig -> [Version] -> Maybe (NonEmpty Major)
+ Hix.Managed.Lower.Candidates: specifiedLower :: VersionBounds -> Maybe (Int, Int)
+ Hix.Managed.Lower.Candidates: specifiedUpper :: VersionBounds -> Maybe (Int, Int)
+ Hix.Managed.Lower.Candidates: stabilizeConfig :: VersionBounds -> Maybe Version -> StabilizeConfig
+ Hix.Managed.Lower.Data.LowerMode: LowerMode :: Bool -> MutationResult SolverState -> LowerMode
+ Hix.Managed.Lower.Data.LowerMode: [$sel:firstSuccess:LowerMode] :: LowerMode -> Bool
+ Hix.Managed.Lower.Data.LowerMode: [$sel:noSuccess:LowerMode] :: LowerMode -> MutationResult SolverState
+ Hix.Managed.Lower.Data.LowerMode: data LowerMode
+ Hix.Managed.Lower.Data.LowerMode: instance GHC.Classes.Eq Hix.Managed.Lower.Data.LowerMode.LowerMode
+ Hix.Managed.Lower.Data.LowerMode: instance GHC.Generics.Generic Hix.Managed.Lower.Data.LowerMode.LowerMode
+ Hix.Managed.Lower.Data.LowerMode: instance GHC.Show.Show Hix.Managed.Lower.Data.LowerMode.LowerMode
+ Hix.Managed.Lower.Data.LowerMode: lowerInitMode :: LowerMode
+ Hix.Managed.Lower.Data.LowerMode: lowerOptimizeMode :: LowerMode
+ Hix.Managed.Lower.Data.LowerMode: lowerStabilizeMode :: LowerMode
+ Hix.Managed.Lower.Init: failure :: Natural -> Text
+ Hix.Managed.Lower.Init: lowerInit :: BuildHandlers -> LowerConfig -> BuildConfig -> StageContext -> M StageResult
+ Hix.Managed.Lower.Init: lowerInitMain :: LowerConfig -> BuildHandlers -> ProjectContext -> M ProjectResult
+ Hix.Managed.Lower.Init: lowerInitStage :: BuildHandlers -> LowerConfig -> BuildConfig -> Flow BuildStatus
+ Hix.Managed.Lower.Init: lowerInitUpdate :: Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints
+ Hix.Managed.Lower.Init: success :: Map MutableDep BuildSuccess -> Natural -> Text
+ Hix.Managed.Lower.Optimize: failure :: Natural -> Text
+ Hix.Managed.Lower.Optimize: lowerOptimize :: BuildHandlers -> BuildConfig -> StageContext -> M StageResult
+ Hix.Managed.Lower.Optimize: lowerOptimizeMain :: BuildHandlers -> ProjectContext -> M ProjectResult
+ Hix.Managed.Lower.Optimize: lowerOptimizeStage :: BuildHandlers -> BuildConfig -> Flow ()
+ Hix.Managed.Lower.Optimize: lowerOptimizeUpdate :: Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints
+ Hix.Managed.Lower.Optimize: success :: Map MutableDep BuildSuccess -> Natural -> Text
+ Hix.Managed.Lower.Stabilize: buildLowerInit :: Flow BuildStatus
+ Hix.Managed.Lower.Stabilize: failure :: Natural -> Text
+ Hix.Managed.Lower.Stabilize: initialVersions :: MutableVersions -> [PackageId]
+ Hix.Managed.Lower.Stabilize: lowerStabilize :: BuildHandlers -> BuildConfig -> StageContext -> M StageResult
+ Hix.Managed.Lower.Stabilize: lowerStabilizeMain :: BuildHandlers -> ProjectContext -> M ProjectResult
+ Hix.Managed.Lower.Stabilize: lowerStabilizeStages :: BuildHandlers -> BuildConfig -> Flow ()
+ Hix.Managed.Lower.Stabilize: lowerStabilizeUpdate :: Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints
+ Hix.Managed.Lower.Stabilize: stabilizeIfPossible :: BuildHandlers -> BuildConfig -> Flow ()
+ Hix.Managed.Lower.Stabilize: stabilizeStage :: BuildHandlers -> BuildConfig -> Flow ()
+ Hix.Managed.Lower.Stabilize: success :: Map MutableDep BuildSuccess -> Natural -> Text
+ Hix.Managed.Lower.Stabilize: validateCurrent :: Flow BuildStatus
+ Hix.Managed.ManagedPackage: forTargets :: Packages ManagedPackage -> [LocalPackage] -> (Targets, LocalRanges, MutableRanges)
+ Hix.Managed.ManagedPackageProto: validate :: Packages ManagedPackageProto -> Packages ManagedPackage
+ Hix.Managed.Overrides: packageOverride :: HackageHandlers -> PackageId -> M (PackageName, Override)
+ Hix.Managed.Overrides: packageOverrides :: HackageHandlers -> [PackageId] -> M Overrides
+ Hix.Managed.Path: rootOrCwd :: Maybe (Path Abs Dir) -> M (Path Abs Dir)
+ Hix.Managed.Process: foldEnvs :: ProjectContext -> (ProcessState -> EnvContext -> M (ProcessState, EnvResult)) -> M ProjectResult
+ Hix.Managed.Process: processEnv :: BuildHandlers -> Flow () -> Builder -> ProcessState -> EnvContext -> M (ProcessState, EnvResult)
+ Hix.Managed.Process: processOrSkip :: (ProcessState -> EnvContext -> M (ProcessState, EnvResult)) -> ProcessState -> Either EnvName EnvContext -> M (ProcessState, EnvResult)
+ Hix.Managed.Process: processProject :: BuildHandlers -> ProjectContext -> Flow () -> M ProjectResult
+ Hix.Managed.Process: skipResult :: StageSummary
+ Hix.Managed.ProjectContext: processBuildResults :: BuildHandlers -> BuildConfig -> ProjectResult -> M ()
+ Hix.Managed.ProjectContext: updateProject :: BuildHandlers -> BuildConfig -> ProjectResult -> M ()
+ Hix.Managed.ProjectContext: withProjectContext :: BuildHandlers -> ProjectOptions -> ProjectContextProto -> (ProjectContext -> M ProjectResult) -> M ()
+ Hix.Managed.ProjectContextProto: noEnvs :: Text
+ Hix.Managed.ProjectContextProto: projectContext :: BuildConfig -> ProjectState -> Packages ManagedPackage -> NonEmpty (Either EnvName EnvContext) -> ProjectContext
+ Hix.Managed.ProjectContextProto: selectEnvs :: Envs (Either EnvDeps EnvContext) -> [EnvName] -> M (NonEmpty (Either EnvName EnvContext))
+ Hix.Managed.ProjectContextProto: unknownEnv :: EnvName -> Text
+ Hix.Managed.ProjectContextProto: validate :: ProjectOptions -> ProjectContextProto -> M ProjectContext
+ Hix.Managed.ProjectContextProto: validateQuery :: Packages ManagedPackage -> RawQuery -> M (Maybe (NonEmpty MutableDep))
+ Hix.Managed.ProjectResult: failures :: ProjectResult -> [FailedMutation]
+ Hix.Managed.ProjectResult: grouped :: ProjectResult -> DepResults
+ Hix.Managed.ProjectStateProto: emptyVersions :: NMap map MutableDep (Maybe Version) sort => Deps MutableDep -> map
+ Hix.Managed.ProjectStateProto: envDepsForMerge :: Envs EnvDeps -> Envs (Deps MutableDep)
+ Hix.Managed.ProjectStateProto: invalidBoundsPackage :: LocalPackage -> a -> M (Maybe b)
+ Hix.Managed.ProjectStateProto: invalidDep :: forall a b. LocalPackage -> PackageName -> a -> M (Maybe b)
+ Hix.Managed.ProjectStateProto: invalidStateDep :: Text -> EnvName -> PackageName -> a -> M (Maybe b)
+ Hix.Managed.ProjectStateProto: invalidVersions :: Text -> EnvName -> a -> M (Maybe b)
+ Hix.Managed.ProjectStateProto: packageDepsForMerge :: MutableRanges -> Deps (MutableDep, VersionRange)
+ Hix.Managed.ProjectStateProto: toMutable :: NMap map MutableDep a sort => Deps (MutableDep, a) -> map
+ Hix.Managed.ProjectStateProto: validateBounds :: Bool -> LocalPackage -> ManagedPackage -> Bounds -> M MutableBounds
+ Hix.Managed.ProjectStateProto: validateProjectBounds :: Bool -> Packages ManagedPackage -> Packages Bounds -> M (Packages MutableBounds)
+ Hix.Managed.ProjectStateProto: validateProjectState :: ProjectOptions -> Packages ManagedPackage -> Envs EnvDeps -> ProjectStateProto -> M ProjectState
+ Hix.Managed.ProjectStateProto: validateProjectVersions :: NMap map MutableDep (Maybe Version) sort => Text -> Envs (Deps MutableDep) -> Envs Versions -> M (Envs map)
+ Hix.Managed.ProjectStateProto: validateVersions :: NMap map MutableDep (Maybe Version) sort => Text -> EnvName -> Deps MutableDep -> Versions -> M map
+ Hix.Managed.QueryDep: queryDep :: CabalHandlers -> Initial MutationState -> MutableBounds -> MutableDep -> QueryDep
+ Hix.Managed.QueryDep: simpleQueryDep :: MutableDep -> VersionBounds -> QueryDep
+ Hix.Managed.Report: describeIterations :: Natural -> Text
+ Hix.Managed.Report: plural :: Eq a => Num a => a -> Text
+ Hix.Managed.StageContext: mutationState :: EnvState -> Initial MutationState
+ Hix.Managed.StageContext: stageContext :: EnvRequest -> EnvState -> StageContext
+ Hix.Managed.StageResult: stageResult :: Pretty a => (Map MutableDep BuildSuccess -> Natural -> Text) -> (Natural -> Text) -> StageState a s -> StageResult
+ Hix.Managed.StageResult: stageResultInit :: Pretty a => (Map MutableDep BuildSuccess -> Natural -> Text) -> (Natural -> Text) -> StageState a s -> StageResult
+ Hix.Managed.StageResult: stageResultWith :: Pretty a => (Map MutableDep BuildSuccess -> MutationState -> MutationState) -> (Map MutableDep BuildSuccess -> Natural -> Text) -> (Natural -> Text) -> StageState a s -> StageResult
+ Hix.Managed.StageState: updateStageState :: StageState a s -> DepMutation a -> MutationResult s -> StageState a s
+ Hix.Managed.StateFile: renderManaged' :: ProjectState -> Expr
+ Hix.Managed.StateFile: renderMap :: Coercible k Text => (v -> Expr) -> Map k v -> Expr
+ Hix.Managed.StateFile: writeBuildStateFor :: Text -> StateFileHandlers -> Path Abs Dir -> EnvContext -> Overrides -> M ()
+ Hix.Managed.StateFile: writeInitialEnvState :: StateFileHandlers -> Path Abs Dir -> EnvContext -> Initial EnvState -> M ()
+ Hix.Managed.StateFile: writeProjectState :: StateFileHandlers -> ProjectState -> M ()
+ Hix.Managed.StateFile: writeStateFile :: Text -> StateFileHandlers -> Maybe (Path Abs Dir) -> ProjectState -> M ()
+ Hix.Managed.UpdateState: envStateForBuild :: EnvContext -> Overrides -> ProjectState
+ Hix.Managed.UpdateState: envStateWithMutations :: MutationState -> EnvState -> EnvState
+ Hix.Managed.UpdateState: projectStateWithEnv :: EnvContext -> EnvState -> ProjectState -> ProjectState
+ Hix.Maybe: fromMaybeA :: Applicative m => m a -> Maybe a -> m a
+ Hix.Maybe: justIf :: Bool -> a -> Maybe a
+ Hix.Monad: AppResources :: Path Abs Dir -> Path Abs Dir -> Bool -> Bool -> Bool -> OutputFormat -> OutputTarget -> (LogLevel -> Text -> M ()) -> AppResources
+ Hix.Monad: [$sel:cwd:AppResources] :: AppResources -> Path Abs Dir
+ Hix.Monad: [$sel:debug:AppResources] :: AppResources -> Bool
+ Hix.Monad: [$sel:logger:AppResources] :: AppResources -> LogLevel -> Text -> M ()
+ Hix.Monad: [$sel:output:AppResources] :: AppResources -> OutputFormat
+ Hix.Monad: [$sel:quiet:AppResources] :: AppResources -> Bool
+ Hix.Monad: [$sel:target:AppResources] :: AppResources -> OutputTarget
+ Hix.Monad: [$sel:tmp:AppResources] :: AppResources -> Path Abs Dir
+ Hix.Monad: [$sel:verbose:AppResources] :: AppResources -> Bool
+ Hix.Monad: catchIOM :: IO a -> (Text -> M a) -> M a
+ Hix.Monad: clientError :: Text -> M a
+ Hix.Monad: data AppResources
+ Hix.Monad: data M a
+ Hix.Monad: eitherClient :: Either Text a -> M a
+ Hix.Monad: eitherFatal :: Either Text a -> M a
+ Hix.Monad: eitherFatalShow :: Show b => Text -> Either b a -> M a
+ Hix.Monad: fatalError :: Text -> M a
+ Hix.Monad: logIORef :: IORef [Text] -> LogLevel -> Text -> IO ()
+ Hix.Monad: mapAccumM :: Traversable t => Monad m => (s -> a -> m (s, b)) -> s -> t a -> m (s, t b)
+ Hix.Monad: note :: Error -> Maybe a -> M a
+ Hix.Monad: noteClient :: Text -> Maybe a -> M a
+ Hix.Monad: noteFatal :: Text -> Maybe a -> M a
+ Hix.Monad: runMDebug :: Path Abs Dir -> M a -> IO (Either Error a)
+ Hix.Monad: runMLog :: Path Abs Dir -> M a -> IO ([Text], Either Error a)
+ Hix.Monad: runMLogWith :: GlobalOptions -> M a -> IO ([Text], Either Error a)
+ Hix.Monad: runMLoggerWith :: (LogLevel -> Text -> IO ()) -> GlobalOptions -> M a -> IO (Either Error a)
+ Hix.Monad: runMWith :: GlobalOptions -> M a -> IO (Either Error a)
+ Hix.Monad: stateM :: Monad m => (s -> a -> m (s, b)) -> a -> StateT s m b
+ Hix.Monad: tryIOMAs :: Error -> IO a -> M a
+ Hix.Monad: tryIOMWith :: (Text -> Error) -> IO a -> M a
+ Hix.Monad: tryIOMWithM :: (Text -> M a) -> IO a -> M a
+ Hix.Monad: whenDebug :: M () -> M ()
+ Hix.Monad: withLogIORef :: ((LogLevel -> Text -> IO ()) -> IO a) -> IO ([Text], a)
+ Hix.Monad: withLower :: (forall b. (M a -> IO b) -> IO b) -> M a
+ Hix.Monad: withTempDir :: String -> (Path Abs Dir -> M a) -> M a
+ Hix.Monad: withTempFile :: String -> Maybe [Text] -> (Path Abs File -> M a) -> M a
+ Hix.NixExpr: checkEmpty :: Text -> Expr -> ExprAttr
+ Hix.NixExpr: indent :: Functor t => Int -> t Text -> t Text
+ Hix.NixExpr: mkAttrs :: [e -> ExprAttr] -> e -> [ExprAttr]
+ Hix.NixExpr: multi :: EncodeNix a => Text -> (e -> [a]) -> e -> ExprAttr
+ Hix.NixExpr: multiOpt :: EncodeNix a => Text -> (e -> Maybe [a]) -> e -> ExprAttr
+ Hix.NixExpr: multiOrSingle :: forall a e. EncodeNix a => Text -> (e -> [a]) -> e -> ExprAttr
+ Hix.NixExpr: nonEmptyAttrs :: Text -> [ExprAttr] -> ExprAttr
+ Hix.NixExpr: notNil :: ExprAttr -> Bool
+ Hix.NixExpr: renderAttrs :: Int -> [ExprAttr] -> [Text]
+ Hix.NixExpr: renderExpr :: Int -> Expr -> NonEmpty Text
+ Hix.NixExpr: renderRootExpr :: Expr -> Text
+ Hix.NixExpr: single :: EncodeNix a => Text -> (e -> a) -> e -> ExprAttr
+ Hix.NixExpr: singleOpt :: EncodeNix a => Text -> (e -> Maybe a) -> e -> ExprAttr
+ Hix.NixExpr: withSemicolon :: NonEmpty Text -> NonEmpty Text
+ Hix.Options: buildConfigParser :: Parser BuildConfig
+ Hix.Options: bumpParser :: Parser BumpOptions
+ Hix.Options: cabalConfigParser :: Parser CabalConfig
+ Hix.Options: lowerCommand :: Parser LowerCommand
+ Hix.Options: lowerCommands :: Mod CommandFields LowerCommand
+ Hix.Options: lowerParser :: Parser LowerOptions
+ Hix.Options: managedCommitMsgParser :: Parser (Path Abs File)
+ Hix.Options: managedGithubPrParser :: Parser (Path Abs File)
+ Hix.Options: managedOptionsParser :: Parser ManagedOptions
+ Hix.Options: projectOptionsParser :: Parser ProjectOptions
+ Hix.Options: stateFileConfigParser :: Parser StateFileConfig
+ Hix.Optparse: buildHandlersOption :: ReadM SpecialBuildHandlers
+ Hix.Optparse: indexStateOption :: ReadM HackageIndexState
+ Hix.Optparse: outputFormatOption :: ReadM OutputFormat
+ Hix.Optparse: outputTargetOption :: ReadM OutputTarget
+ Hix.Optparse: pathOption :: String -> (String -> Either e a) -> ReadM a
+ Hix.Orphans.Version: instance GHC.IsList.IsList Distribution.Types.Version.Version
+ Hix.Orphans.Version: instance GHC.IsList.IsList Distribution.Types.VersionRange.Internal.VersionRange
+ Hix.OutputWriter: OutputWriter :: (ByteString -> M ()) -> (Text -> M ()) -> (Text -> M ()) -> OutputWriter
+ Hix.OutputWriter: WriteError :: Text -> Path Abs File -> WriteError
+ Hix.OutputWriter: [$sel:bytes:OutputWriter] :: OutputWriter -> ByteString -> M ()
+ Hix.OutputWriter: [$sel:file:WriteError] :: WriteError -> Path Abs File
+ Hix.OutputWriter: [$sel:msg:WriteError] :: WriteError -> Text
+ Hix.OutputWriter: [$sel:text:OutputWriter] :: OutputWriter -> Text -> M ()
+ Hix.OutputWriter: [$sel:textAppend:OutputWriter] :: OutputWriter -> Text -> M ()
+ Hix.OutputWriter: data OutputWriter
+ Hix.OutputWriter: data WriteError
+ Hix.OutputWriter: fileWriter :: (WriteError -> M ()) -> Path Abs File -> OutputWriter
+ Hix.OutputWriter: instance GHC.Classes.Eq Hix.OutputWriter.WriteError
+ Hix.OutputWriter: instance GHC.Generics.Generic Hix.OutputWriter.WriteError
+ Hix.OutputWriter: instance GHC.Show.Show Hix.OutputWriter.WriteError
+ Hix.OutputWriter: outputWriter :: OutputWriter -> OutputTarget -> OutputWriter
+ Hix.OutputWriter: outputWriterGlobal :: OutputTarget -> OutputWriter
+ Hix.OutputWriter: outputWriterM :: M OutputWriter -> OutputTarget -> M OutputWriter
+ Hix.OutputWriter: stdoutWriter :: OutputWriter
+ Hix.OutputWriter: writeError :: WriteError -> M ()
+ Hix.Pretty: prettyL :: forall t a. Pretty a => Foldable t => t a -> Doc
+ Hix.Pretty: prettyText :: Text -> Doc
+ Hix.Pretty: showP :: forall b a. Pretty a => IsString b => a -> b
+ Hix.Pretty: showPL :: forall t b a. Pretty a => Foldable t => IsString b => t a -> b
+ Hix.Pretty: showPM :: forall b a. Pretty a => IsString b => Maybe a -> b
+ Hix.These: maybeThese :: Maybe a -> Maybe b -> Maybe (These a b)
+ Hix.Trace: trp :: forall b a. Pretty b => HasCallStack => b -> a -> a
+ Hix.Trace: trpi :: Pretty a => HasCallStack => a -> a
+ Hix.Version: allMajors :: [Version] -> [Major]
+ Hix.Version: beforeMajor :: Int -> Int -> Version -> Bool
+ Hix.Version: currentMajor :: Version -> Version
+ Hix.Version: exclusiveUpperVersion :: VersionRange -> Maybe Version
+ Hix.Version: hasMajor :: Int -> Int -> Version -> Bool
+ Hix.Version: isMajor :: Int -> Int -> Major -> Bool
+ Hix.Version: lastMajor :: [Version] -> [Version]
+ Hix.Version: lastMajorBefore :: Int -> Int -> [Version] -> [Version]
+ Hix.Version: lowerVersion :: VersionRange -> Maybe Version
+ Hix.Version: majorNewer :: Int -> Int -> Major -> Bool
+ Hix.Version: majorOlder :: Int -> Int -> Major -> Bool
+ Hix.Version: majorParts :: Version -> Maybe (Int, Int)
+ Hix.Version: majorPrefix :: Version -> Maybe [Int]
+ Hix.Version: majorsBefore :: Int -> Int -> [Version] -> [Major]
+ Hix.Version: majorsFrom :: Int -> Int -> [Version] -> [Major]
+ Hix.Version: minMajor :: Int -> Int -> Version -> Bool
+ Hix.Version: nextMajor :: Version -> Version
+ Hix.Version: onlyMajor :: Int -> Int -> [Version] -> Maybe Major
+ Hix.Version: prevMajor :: Version -> Version
+ Hix.Version: upperVersion :: VersionRange -> Maybe Version
+ Hix.Version: versionsBetween :: Version -> Version -> [Version] -> [Major]
+ Hix.Version: versionsFrom :: Version -> [Version] -> [Major]
+ Hix.Zip: zipApply :: (a -> b) -> [a] -> [(a, b)]
+ Hix.Zip: zipApplyA :: Traversable t => Applicative m => (a -> m b) -> t a -> m (t (a, b))
+ Hix.Zip: zipApplyL :: (a -> b) -> [a] -> [(b, a)]
- Hix.Json: jsonConfig :: FromJSON a => JsonConfig -> M a
+ Hix.Json: jsonConfig :: FromJSON a => (Text -> Error) -> JsonConfig -> M a
Files
- hix.cabal +186/−4
- lib/Hix.hs +26/−12
- lib/Hix/Bootstrap.hs +31/−186
- lib/Hix/Cabal.hs +2/−1
- lib/Hix/CabalParsec.hs +48/−0
- lib/Hix/Class/EncodeNix.hs +91/−0
- lib/Hix/Class/Map.hs +715/−0
- lib/Hix/Class/SOP.hs +54/−0
- lib/Hix/Component.hs +5/−9
- lib/Hix/Console.hs +84/−0
- lib/Hix/Data/Bounds.hs +49/−0
- lib/Hix/Data/ComponentConfig.hs +5/−9
- lib/Hix/Data/Dep.hs +59/−0
- lib/Hix/Data/EnvName.hs +15/−0
- lib/Hix/Data/Error.hs +2/−69
- lib/Hix/Data/GhciConfig.hs +2/−1
- lib/Hix/Data/GlobalOptions.hs +28/−0
- lib/Hix/Data/Json.hs +33/−0
- lib/Hix/Data/Monad.hs +51/−0
- lib/Hix/Data/NixExpr.hs +38/−0
- lib/Hix/Data/Options.hs +203/−0
- lib/Hix/Data/OutputFormat.hs +11/−0
- lib/Hix/Data/OutputTarget.hs +11/−0
- lib/Hix/Data/Overrides.hs +43/−0
- lib/Hix/Data/PackageId.hs +32/−0
- lib/Hix/Data/PackageName.hs +55/−0
- lib/Hix/Data/ProjectFile.hs +5/−5
- lib/Hix/Data/Version.hs +64/−0
- lib/Hix/Data/VersionBounds.hs +152/−0
- lib/Hix/Env.hs +8/−12
- lib/Hix/Error.hs +115/−0
- lib/Hix/Ghci.hs +12/−12
- lib/Hix/Hackage.hs +120/−0
- lib/Hix/Json.hs +14/−6
- lib/Hix/Log.hs +61/−0
- lib/Hix/Managed/Build.hs +216/−0
- lib/Hix/Managed/Build/Mutation.hs +77/−0
- lib/Hix/Managed/Build/Single.hs +25/−0
- lib/Hix/Managed/Build/Solve.hs +51/−0
- lib/Hix/Managed/BuildOutput.hs +67/−0
- lib/Hix/Managed/BuildOutput/CommitMsg.hs +32/−0
- lib/Hix/Managed/BuildOutput/GithubActionsPr.hs +58/−0
- lib/Hix/Managed/Bump/App.hs +17/−0
- lib/Hix/Managed/Bump/Candidates.hs +47/−0
- lib/Hix/Managed/Bump/Optimize.hs +126/−0
- lib/Hix/Managed/Cabal/Changes.hs +67/−0
- lib/Hix/Managed/Cabal/Config.hs +35/−0
- lib/Hix/Managed/Cabal/Data/Config.hs +64/−0
- lib/Hix/Managed/Cabal/Data/Packages.hs +23/−0
- lib/Hix/Managed/Cabal/Data/SolveResources.hs +23/−0
- lib/Hix/Managed/Cabal/Data/SolveTarget.hs +36/−0
- lib/Hix/Managed/Cabal/Data/SolverState.hs +83/−0
- lib/Hix/Managed/Cabal/Data/SourcePackage.hs +40/−0
- lib/Hix/Managed/Cabal/Init.hs +85/−0
- lib/Hix/Managed/Cabal/Installed.hs +14/−0
- lib/Hix/Managed/Cabal/Mock.hs +33/−0
- lib/Hix/Managed/Cabal/Mock/InstalledPackage.hs +28/−0
- lib/Hix/Managed/Cabal/Mock/SourcePackage.hs +111/−0
- lib/Hix/Managed/Cabal/Print.hs +26/−0
- lib/Hix/Managed/Cabal/Repo.hs +137/−0
- lib/Hix/Managed/Cabal/Resources.hs +76/−0
- lib/Hix/Managed/Cabal/Solve.hs +83/−0
- lib/Hix/Managed/Cabal/Targets.hs +50/−0
- lib/Hix/Managed/Constraints.hs +37/−0
- lib/Hix/Managed/Data/BuildConfig.hs +22/−0
- lib/Hix/Managed/Data/BuildOutput.hs +44/−0
- lib/Hix/Managed/Data/Bump.hs +18/−0
- lib/Hix/Managed/Data/Constraints.hs +89/−0
- lib/Hix/Managed/Data/CurrentBuild.hs +9/−0
- lib/Hix/Managed/Data/Diff.hs +66/−0
- lib/Hix/Managed/Data/EnvConfig.hs +14/−0
- lib/Hix/Managed/Data/EnvContext.hs +45/−0
- lib/Hix/Managed/Data/EnvRequest.hs +18/−0
- lib/Hix/Managed/Data/EnvResult.hs +14/−0
- lib/Hix/Managed/Data/EnvState.hs +36/−0
- lib/Hix/Managed/Data/Envs.hs +19/−0
- lib/Hix/Managed/Data/Initial.hs +14/−0
- lib/Hix/Managed/Data/Lower.hs +14/−0
- lib/Hix/Managed/Data/LowerConfig.hs +24/−0
- lib/Hix/Managed/Data/ManagedPackage.hs +40/−0
- lib/Hix/Managed/Data/ManagedPackageProto.hs +44/−0
- lib/Hix/Managed/Data/Mutable.hs +251/−0
- lib/Hix/Managed/Data/MutableId.hs +28/−0
- lib/Hix/Managed/Data/Mutation.hs +61/−0
- lib/Hix/Managed/Data/MutationMode.hs +7/−0
- lib/Hix/Managed/Data/MutationState.hs +40/−0
- lib/Hix/Managed/Data/Packages.hs +29/−0
- lib/Hix/Managed/Data/ProcessState.hs +52/−0
- lib/Hix/Managed/Data/ProjectContext.hs +17/−0
- lib/Hix/Managed/Data/ProjectContextProto.hs +29/−0
- lib/Hix/Managed/Data/ProjectResult.hs +11/−0
- lib/Hix/Managed/Data/ProjectState.hs +31/−0
- lib/Hix/Managed/Data/ProjectStateProto.hs +50/−0
- lib/Hix/Managed/Data/Query.hs +15/−0
- lib/Hix/Managed/Data/QueryDep.hs +18/−0
- lib/Hix/Managed/Data/StageContext.hs +17/−0
- lib/Hix/Managed/Data/StageResult.hs +33/−0
- lib/Hix/Managed/Data/StageState.hs +55/−0
- lib/Hix/Managed/Data/StateFileConfig.hs +17/−0
- lib/Hix/Managed/Data/Targets.hs +98/−0
- lib/Hix/Managed/Diff.hs +143/−0
- lib/Hix/Managed/EnvContext.hs +68/−0
- lib/Hix/Managed/EnvRequest.hs +77/−0
- lib/Hix/Managed/EnvResult.hs +122/−0
- lib/Hix/Managed/Flow.hs +144/−0
- lib/Hix/Managed/Handlers/Build.hs +95/−0
- lib/Hix/Managed/Handlers/Build/Prod.hs +188/−0
- lib/Hix/Managed/Handlers/Build/Test.hs +92/−0
- lib/Hix/Managed/Handlers/Cabal.hs +41/−0
- lib/Hix/Managed/Handlers/Cabal/Prod.hs +87/−0
- lib/Hix/Managed/Handlers/Hackage.hs +17/−0
- lib/Hix/Managed/Handlers/Hackage/Prod.hs +16/−0
- lib/Hix/Managed/Handlers/Mutation.hs +14/−0
- lib/Hix/Managed/Handlers/Mutation/Bump.hs +50/−0
- lib/Hix/Managed/Handlers/Mutation/Lower.hs +83/−0
- lib/Hix/Managed/Handlers/Report.hs +13/−0
- lib/Hix/Managed/Handlers/Report/Prod.hs +186/−0
- lib/Hix/Managed/Handlers/Report/Test.hs +27/−0
- lib/Hix/Managed/Handlers/StateFile.hs +15/−0
- lib/Hix/Managed/Handlers/StateFile/Prod.hs +54/−0
- lib/Hix/Managed/Handlers/StateFile/Test.hs +23/−0
- lib/Hix/Managed/Lower/App.hs +41/−0
- lib/Hix/Managed/Lower/Auto.hs +110/−0
- lib/Hix/Managed/Lower/Candidates.hs +196/−0
- lib/Hix/Managed/Lower/Data/LowerMode.hs +32/−0
- lib/Hix/Managed/Lower/Init.hs +94/−0
- lib/Hix/Managed/Lower/Optimize.hs +76/−0
- lib/Hix/Managed/Lower/Stabilize.hs +146/−0
- lib/Hix/Managed/ManagedPackage.hs +27/−0
- lib/Hix/Managed/ManagedPackageProto.hs +27/−0
- lib/Hix/Managed/Overrides.hs +26/−0
- lib/Hix/Managed/Path.hs +14/−0
- lib/Hix/Managed/Process.hs +70/−0
- lib/Hix/Managed/ProjectContext.hs +51/−0
- lib/Hix/Managed/ProjectContextProto.hs +89/−0
- lib/Hix/Managed/ProjectResult.hs +16/−0
- lib/Hix/Managed/ProjectStateProto.hs +141/−0
- lib/Hix/Managed/QueryDep.hs +36/−0
- lib/Hix/Managed/Report.hs +15/−0
- lib/Hix/Managed/StageContext.hs +39/−0
- lib/Hix/Managed/StageResult.hs +54/−0
- lib/Hix/Managed/StageState.hs +28/−0
- lib/Hix/Managed/StateFile.hs +70/−0
- lib/Hix/Managed/UpdateState.hs +67/−0
- lib/Hix/Maybe.hs +20/−0
- lib/Hix/Monad.hs +163/−22
- lib/Hix/New.hs +2/−2
- lib/Hix/NixExpr.hs +126/−0
- lib/Hix/Options.hs +155/−144
- lib/Hix/Optparse.hs +59/−25
- lib/Hix/Orphans/Version.hs +46/−0
- lib/Hix/OutputWriter.hs +64/−0
- lib/Hix/Path.hs +3/−3
- lib/Hix/Preproc.hs +11/−10
- lib/Hix/Pretty.hs +40/−0
- lib/Hix/These.hs +9/−0
- lib/Hix/Trace.hs +25/−0
- lib/Hix/Version.hs +151/−0
- lib/Hix/Zip.hs +15/−0
- test/Hix/Test/BootstrapTest.hs +6/−5
- test/Hix/Test/BoundsTest.hs +52/−0
- test/Hix/Test/CabalFile.hs +1/−0
- test/Hix/Test/CabalTest.hs +15/−10
- test/Hix/Test/GhciTest.hs +13/−12
- test/Hix/Test/Hedgehog.hs +57/−0
- test/Hix/Test/Managed/BuildOutputTest.hs +36/−0
- test/Hix/Test/Managed/Bump/CandidatesTest.hs +106/−0
- test/Hix/Test/Managed/Bump/MutationTest.hs +335/−0
- test/Hix/Test/Managed/DiffTest.hs +54/−0
- test/Hix/Test/Managed/LowerAuto/MutationOptimizeTest.hs +344/−0
- test/Hix/Test/Managed/LowerAuto/MutationStabilizeTest.hs +202/−0
- test/Hix/Test/Managed/LowerInit/MutationTest.hs +438/−0
- test/Hix/Test/Managed/LowerNativeTest.hs +268/−0
- test/Hix/Test/Managed/LowerOptimize/CandidatesTest.hs +99/−0
- test/Hix/Test/Managed/LowerOptimize/MutationTest.hs +154/−0
- test/Hix/Test/Managed/LowerStabilize/MutationTest.hs +141/−0
- test/Hix/Test/Managed/ProjectContextProtoTest.hs +287/−0
- test/Hix/Test/Managed/Run.hs +130/−0
- test/Hix/Test/Managed/UnsafeIsString.hs +73/−0
- test/Hix/Test/ManagedTest.hs +37/−0
- test/Hix/Test/NewTest.hs +4/−3
- test/Hix/Test/PreprocTest.hs +13/−11
- test/Hix/Test/Utils.hs +42/−0
- test/Hix/Test/VersionTest.hs +51/−0
- test/Main.hs +10/−13
hix.cabal view
@@ -1,11 +1,11 @@ cabal-version: 2.2 --- This file has been generated from package.yaml by hpack version 0.35.2.+-- This file has been generated from package.yaml by hpack version 0.36.0. -- -- see: https://github.com/sol/hpack name: hix-version: 0.6.9+version: 0.7.0 synopsis: Haskell/Nix development build tools description: See https://hackage.haskell.org/package/hix/docs/Hix.html category: Build@@ -27,29 +27,171 @@ Hix Hix.Bootstrap Hix.Cabal+ Hix.CabalParsec+ Hix.Class.EncodeNix+ Hix.Class.Map+ Hix.Class.SOP Hix.Compat Hix.Component+ Hix.Console Hix.Data.BootstrapProjectConfig+ Hix.Data.Bounds Hix.Data.ComponentConfig+ Hix.Data.Dep+ Hix.Data.EnvName Hix.Data.Error Hix.Data.GhciConfig Hix.Data.GhciTest+ Hix.Data.GlobalOptions+ Hix.Data.Json+ Hix.Data.Monad Hix.Data.NewProjectConfig+ Hix.Data.NixExpr+ Hix.Data.Options+ Hix.Data.OutputFormat+ Hix.Data.OutputTarget+ Hix.Data.Overrides+ Hix.Data.PackageId+ Hix.Data.PackageName Hix.Data.PreprocConfig Hix.Data.ProjectFile+ Hix.Data.Version+ Hix.Data.VersionBounds Hix.Env+ Hix.Error Hix.Ghci+ Hix.Hackage Hix.Json+ Hix.Log+ Hix.Managed.Build+ Hix.Managed.Build.Mutation+ Hix.Managed.Build.Single+ Hix.Managed.Build.Solve+ Hix.Managed.BuildOutput+ Hix.Managed.BuildOutput.CommitMsg+ Hix.Managed.BuildOutput.GithubActionsPr+ Hix.Managed.Bump.App+ Hix.Managed.Bump.Candidates+ Hix.Managed.Bump.Optimize+ Hix.Managed.Cabal.Changes+ Hix.Managed.Cabal.Config+ Hix.Managed.Cabal.Data.Config+ Hix.Managed.Cabal.Data.Packages+ Hix.Managed.Cabal.Data.SolveResources+ Hix.Managed.Cabal.Data.SolverState+ Hix.Managed.Cabal.Data.SolveTarget+ Hix.Managed.Cabal.Data.SourcePackage+ Hix.Managed.Cabal.Init+ Hix.Managed.Cabal.Installed+ Hix.Managed.Cabal.Mock+ Hix.Managed.Cabal.Mock.InstalledPackage+ Hix.Managed.Cabal.Mock.SourcePackage+ Hix.Managed.Cabal.Print+ Hix.Managed.Cabal.Repo+ Hix.Managed.Cabal.Resources+ Hix.Managed.Cabal.Solve+ Hix.Managed.Cabal.Targets+ Hix.Managed.Constraints+ Hix.Managed.Data.BuildConfig+ Hix.Managed.Data.BuildOutput+ Hix.Managed.Data.Bump+ Hix.Managed.Data.Constraints+ Hix.Managed.Data.CurrentBuild+ Hix.Managed.Data.Diff+ Hix.Managed.Data.EnvConfig+ Hix.Managed.Data.EnvContext+ Hix.Managed.Data.EnvRequest+ Hix.Managed.Data.EnvResult+ Hix.Managed.Data.Envs+ Hix.Managed.Data.EnvState+ Hix.Managed.Data.Initial+ Hix.Managed.Data.Lower+ Hix.Managed.Data.LowerConfig+ Hix.Managed.Data.ManagedPackage+ Hix.Managed.Data.ManagedPackageProto+ Hix.Managed.Data.Mutable+ Hix.Managed.Data.MutableId+ Hix.Managed.Data.Mutation+ Hix.Managed.Data.MutationMode+ Hix.Managed.Data.MutationState+ Hix.Managed.Data.Packages+ Hix.Managed.Data.ProcessState+ Hix.Managed.Data.ProjectContext+ Hix.Managed.Data.ProjectContextProto+ Hix.Managed.Data.ProjectResult+ Hix.Managed.Data.ProjectState+ Hix.Managed.Data.ProjectStateProto+ Hix.Managed.Data.Query+ Hix.Managed.Data.QueryDep+ Hix.Managed.Data.StageContext+ Hix.Managed.Data.StageResult+ Hix.Managed.Data.StageState+ Hix.Managed.Data.StateFileConfig+ Hix.Managed.Data.Targets+ Hix.Managed.Diff+ Hix.Managed.EnvContext+ Hix.Managed.EnvRequest+ Hix.Managed.EnvResult+ Hix.Managed.Flow+ Hix.Managed.Handlers.Build+ Hix.Managed.Handlers.Build.Prod+ Hix.Managed.Handlers.Build.Test+ Hix.Managed.Handlers.Cabal+ Hix.Managed.Handlers.Cabal.Prod+ Hix.Managed.Handlers.Hackage+ Hix.Managed.Handlers.Hackage.Prod+ Hix.Managed.Handlers.Mutation+ Hix.Managed.Handlers.Mutation.Bump+ Hix.Managed.Handlers.Mutation.Lower+ Hix.Managed.Handlers.Report+ Hix.Managed.Handlers.Report.Prod+ Hix.Managed.Handlers.Report.Test+ Hix.Managed.Handlers.StateFile+ Hix.Managed.Handlers.StateFile.Prod+ Hix.Managed.Handlers.StateFile.Test+ Hix.Managed.Lower.App+ Hix.Managed.Lower.Auto+ Hix.Managed.Lower.Candidates+ Hix.Managed.Lower.Data.LowerMode+ Hix.Managed.Lower.Init+ Hix.Managed.Lower.Optimize+ Hix.Managed.Lower.Stabilize+ Hix.Managed.ManagedPackage+ Hix.Managed.ManagedPackageProto+ Hix.Managed.Overrides+ Hix.Managed.Path+ Hix.Managed.Process+ Hix.Managed.ProjectContext+ Hix.Managed.ProjectContextProto+ Hix.Managed.ProjectResult+ Hix.Managed.ProjectStateProto+ Hix.Managed.QueryDep+ Hix.Managed.Report+ Hix.Managed.StageContext+ Hix.Managed.StageResult+ Hix.Managed.StageState+ Hix.Managed.StateFile+ Hix.Managed.UpdateState+ Hix.Maybe Hix.Monad Hix.New+ Hix.NixExpr Hix.Options Hix.Optparse+ Hix.Orphans.Version+ Hix.OutputWriter Hix.Path Hix.Prelude Hix.Preproc+ Hix.Pretty+ Hix.These+ Hix.Trace+ Hix.Version+ Hix.Zip hs-source-dirs: lib default-extensions:+ StrictData AllowAmbiguousTypes ApplicativeDo BlockArguments@@ -64,6 +206,7 @@ GADTs LambdaCase LiberalTypeSynonyms+ MonadComprehensions MultiWayIf OverloadedLabels OverloadedLists@@ -89,19 +232,32 @@ Cabal , aeson >=2.0 && <2.2 , base ==4.*+ , bytestring+ , cabal-install+ , cabal-install-solver , casing >=0.1.4 && <0.2+ , containers+ , exceptions ==0.10.* , exon >=1.4 && <1.7 , extra ==1.7.* , filepattern ==0.1.* , generic-lens ==2.2.*+ , generics-sop ==0.5.*+ , http-client ==0.7.*+ , http-client-tls ==0.3.*+ , http-types ==0.12.* , incipit-base ==0.5.* , lens >=5.1 && <5.3 , lens-regex-pcre ==1.1.*- , optparse-applicative ==0.17.*+ , optparse-applicative >=0.17 && <0.19 , path ==0.9.* , path-io >=1.7 && <1.9+ , pretty , random ==1.2.*+ , these ==1.2.*+ , time , transformers+ , typed-process ==0.2.* , unix mixins: base hiding (Prelude)@@ -114,6 +270,7 @@ hs-source-dirs: app default-extensions:+ StrictData AllowAmbiguousTypes ApplicativeDo BlockArguments@@ -128,6 +285,7 @@ GADTs LambdaCase LiberalTypeSynonyms+ MonadComprehensions MultiWayIf OverloadedLabels OverloadedLists@@ -164,14 +322,34 @@ main-is: Main.hs other-modules: Hix.Test.BootstrapTest+ Hix.Test.BoundsTest Hix.Test.CabalFile Hix.Test.CabalTest Hix.Test.GhciTest+ Hix.Test.Hedgehog+ Hix.Test.Managed.BuildOutputTest+ Hix.Test.Managed.Bump.CandidatesTest+ Hix.Test.Managed.Bump.MutationTest+ Hix.Test.Managed.DiffTest+ Hix.Test.Managed.LowerAuto.MutationOptimizeTest+ Hix.Test.Managed.LowerAuto.MutationStabilizeTest+ Hix.Test.Managed.LowerInit.MutationTest+ Hix.Test.Managed.LowerNativeTest+ Hix.Test.Managed.LowerOptimize.CandidatesTest+ Hix.Test.Managed.LowerOptimize.MutationTest+ Hix.Test.Managed.LowerStabilize.MutationTest+ Hix.Test.Managed.ProjectContextProtoTest+ Hix.Test.Managed.Run+ Hix.Test.Managed.UnsafeIsString+ Hix.Test.ManagedTest Hix.Test.NewTest Hix.Test.PreprocTest+ Hix.Test.Utils+ Hix.Test.VersionTest hs-source-dirs: test default-extensions:+ StrictData AllowAmbiguousTypes ApplicativeDo BlockArguments@@ -186,6 +364,7 @@ GADTs LambdaCase LiberalTypeSynonyms+ MonadComprehensions MultiWayIf OverloadedLabels OverloadedLists@@ -209,15 +388,18 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall -Widentities -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Wredundant-constraints -Wunused-type-patterns -Wunused-packages build-depends: Cabal+ , aeson >=2.0 && <2.2 , base ==4.* , exon >=1.4 && <1.7- , hedgehog >=1.1 && <1.3+ , extra ==1.7.*+ , hedgehog >=1.1 && <1.5 , hix , incipit-base ==0.5.* , path ==0.9.* , path-io >=1.7 && <1.9 , tasty ==1.4.* , tasty-hedgehog >=1.3 && <1.5+ , these ==1.2.* , transformers mixins: base hiding (Prelude)
lib/Hix.hs view
@@ -1,26 +1,33 @@ module Hix where import Hix.Bootstrap (bootstrapProject)-import Hix.Data.Error (+import qualified Hix.Console as Console+import Hix.Console (errorMessage)+import qualified Hix.Data.GlobalOptions+import Hix.Data.GlobalOptions (GlobalOptions (GlobalOptions))+import qualified Hix.Data.Options as Options+import Hix.Data.Options (+ Command (..),+ LowerCommand (LowerAutoCmd, LowerInitCmd, LowerOptimizeCmd, LowerStabilizeCmd),+ Options (Options),+ )+import Hix.Env (printEnvRunner)+import Hix.Error ( Error (..), printBootstrapError, printEnvError,+ printError, printFatalError, printGhciError, printNewError, printPreprocError, )-import Hix.Env (printEnvRunner) import Hix.Ghci (printGhciCmdline, printGhcidCmdline)-import Hix.Monad (M, runM)+import Hix.Managed.Bump.App (bumpCli)+import Hix.Managed.Lower.App (lowerAutoCli, lowerInitCli, lowerOptimizeCli, lowerStabilizeCli)+import Hix.Monad (M, runMWith) import Hix.New (newProject)-import qualified Hix.Options as Options-import Hix.Options (- Command (BootstrapCmd, EnvRunner, GhciCmd, GhcidCmd, NewCmd, Preproc),- GlobalOptions (GlobalOptions),- Options (Options),- parseCli,- )+import Hix.Options (parseCli) import Hix.Preproc (preprocess) handleError ::@@ -34,9 +41,10 @@ GhciError err -> printGhciError err NewError err -> printNewError err BootstrapError err -> printBootstrapError err- NoMatch msg | fromMaybe False verbose -> printPreprocError msg+ NoMatch msg | verbose -> printPreprocError msg NoMatch _ -> unit Fatal err -> printFatalError err+ Client err -> Console.err (errorMessage err) runCommand :: Command -> M () runCommand = \case@@ -46,8 +54,14 @@ GhciCmd opts -> printGhciCmdline opts NewCmd opts -> newProject opts.config BootstrapCmd opts -> bootstrapProject opts.config+ BumpCmd opts -> bumpCli opts+ LowerCmd sub -> case sub of+ LowerInitCmd opts -> lowerInitCli opts+ LowerOptimizeCmd opts -> lowerOptimizeCli opts+ LowerStabilizeCmd opts -> lowerStabilizeCli opts+ LowerAutoCmd opts -> lowerAutoCli opts main :: IO () main = do Options global cmd <- parseCli- leftA (handleError global) =<< runM global.cwd (runCommand cmd)+ leftA (printError global.verbose) =<< runMWith global (runCommand cmd)
lib/Hix/Bootstrap.hs view
@@ -2,7 +2,6 @@ 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@@ -16,10 +15,9 @@ unPackageName, unUnqualComponentName, )-import Distribution.Pretty (Pretty, pretty)+import Distribution.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, (</>))@@ -28,42 +26,19 @@ 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.Monad (AppResources (cwd))+import Hix.Data.Monad (M (M)) import qualified Hix.Data.NewProjectConfig+import Hix.Data.NixExpr (Expr (ExprAttrs, ExprLit, ExprPrefix, ExprString), ExprAttr (ExprAttr, ExprAttrNil))+import Hix.Data.PackageName (PackageName (PackageName)) import qualified Hix.Data.ProjectFile import Hix.Data.ProjectFile (ProjectFile (ProjectFile), createFile)-import qualified Hix.Monad-import Hix.Monad (Env (Env), M, noteBootstrap)+import Hix.Error (pathText, tryIO)+import Hix.Monad (AppResources (AppResources), noteBootstrap)+import Hix.NixExpr (mkAttrs, multi, multiOrSingle, nonEmptyAttrs, renderRootExpr, single, singleOpt) import qualified Hix.Prelude import Hix.Prelude (Prelude, findPrelude) -data ExprAttr =- ExprAttr {- name :: Text,- value :: Expr- }- |- ExprAttrNil- deriving stock (Eq, Show, Generic)--data Expr =- ExprString Text- |- ExprLit Text- |- ExprList [Expr]- |- ExprAttrs [ExprAttr]- |- ExprPrefix Text Expr- deriving stock (Eq, Show, Generic)--exprStrings :: [Text] -> Expr-exprStrings =- ExprList . fmap ExprString- data CabalInfo = CabalInfo { path :: Path Rel Dir,@@ -107,45 +82,6 @@ } deriving stock (Eq, Show, Generic) -indent ::- Functor t =>- Int ->- t Text ->- t Text-indent n =- fmap (Text.replicate n " " <>)--withSemicolon :: NonEmpty Text -> NonEmpty Text-withSemicolon = \case- e :| [] ->- [e <> ";"]- h :| h1 : t -> h <| withSemicolon (h1 :| t)--renderAttrs :: Int -> [ExprAttr] -> [Text]-renderAttrs ind attrs =- attrs >>= \case- ExprAttr k v ->- case renderExpr ind v of- e :| [] -> [[exon|#{k} = #{e};|]]- h :| (h1 : t) -> [exon|#{k} = #{h}|] : toList (withSemicolon (h1 :| t))- ExprAttrNil ->- []--renderExpr :: Int -> Expr -> NonEmpty Text-renderExpr ind = \case- ExprString s -> indent ind [[exon|"#{Text.replace "\"" "\\\"" s}"|]]- ExprLit e -> [e]- ExprList l -> "[" :| (indent (ind + 2) (toList . renderExpr ind =<< l)) ++ ["]"]- ExprAttrs a -> case renderAttrs ind a of- [] -> ["{}"]- as -> "{" :| indent (ind + 2) as ++ ["}"]- ExprPrefix p (renderExpr ind -> h :| t) ->- [exon|#{p} #{h}|] :| t--renderRootExpr :: Expr -> Text-renderRootExpr =- Text.unlines . toList . renderExpr 0- readCabal :: Path Abs Dir -> Path Rel File ->@@ -156,105 +92,15 @@ where dir = parent path -class RenderCabalOption a where- renderCabalOption :: a -> Text--instance {-# overlappable #-} Pretty a => RenderCabalOption a where- renderCabalOption = show . pretty--instance RenderCabalOption ShortText where- renderCabalOption = toText . fromShortText--instance RenderCabalOption String where- renderCabalOption = toText--checkEmpty ::- Text ->- Expr ->- ExprAttr-checkEmpty key = \case- ExprString value | Text.null value ->- ExprAttrNil- ExprList value | null value ->- ExprAttrNil- value ->- ExprAttr key value--singleOpt ::- RenderCabalOption a =>- Text ->- (e -> Maybe a) ->- e ->- ExprAttr-singleOpt key get entity =- maybe ExprAttrNil (checkEmpty key . ExprString) (renderCabalOption <$> get entity)--single ::- RenderCabalOption a =>- Text ->- (e -> a) ->- e ->- ExprAttr-single key get =- singleOpt key (Just . get)--multiOpt ::- RenderCabalOption a =>- Text ->- (e -> Maybe [a]) ->- e ->- ExprAttr-multiOpt key get entity =- maybe ExprAttrNil (checkEmpty key . exprStrings) (fmap renderCabalOption <$> get entity)--multi ::- RenderCabalOption a =>- Text ->- (e -> [a]) ->- e ->- ExprAttr-multi key get =- multiOpt key (Just . get)--multiOrSingle ::- ∀ a e .- RenderCabalOption a =>- Text ->- (e -> [a]) ->- e ->- ExprAttr-multiOrSingle key get entity =- check (renderCabalOption <$> get entity)- where- check :: [Text] -> ExprAttr- check [] = ExprAttrNil- check [sing] = ExprAttr key (ExprString sing)- check values = ExprAttr key (exprStrings values)--mkAttrs :: [e -> ExprAttr] -> e -> [ExprAttr]-mkAttrs a e =- (fmap ($ e) a)--notNil :: ExprAttr -> Bool-notNil = \case- ExprAttrNil -> False- _ -> True--nonEmptyAttrs :: Text -> [ExprAttr] -> ExprAttr-nonEmptyAttrs key =- filter notNil >>> \case- [] -> ExprAttrNil- as -> ExprAttr key (ExprAttrs as)- -- TODO extract version and put it in a file knownPackageKeys :: PackageDescription -> [ExprAttr] knownPackageKeys = mkAttrs [ single "author" (.author),- single "build-type" buildType,+ single "build-type" (pretty . buildType), single "copyright" (.copyright),- single "license" license,- singleOpt "license-file" (head . licenseFiles),+ single "license" (pretty . license),+ singleOpt "license-file" (fmap pretty . head . licenseFiles), single "version" (.package.pkgVersion) ] @@ -282,17 +128,17 @@ where vals = mkAttrs [- multi "dependencies" (const deps),- multi "default-extensions" (.defaultExtensions),- multiOrSingle "source-dirs" (.hsSourceDirs),- singleOpt "language" (.defaultLanguage),- multi "ghc-options" (filter notDefaultGhcOption . ghcFlavour . (.options)),+ multi "dependencies" (fmap pretty . const deps),+ multi "default-extensions" (fmap pretty . (.defaultExtensions)),+ multiOrSingle "source-dirs" (fmap pretty . (.hsSourceDirs)),+ singleOpt "language" (fmap pretty . (.defaultLanguage)),+ multi "ghc-options" (fmap (ExprString . toText) . filter notDefaultGhcOption . ghcFlavour . (.options)), misc ] info misc e = nonEmptyAttrs "component" (mkAttrs [- multi "other-modules" (.otherModules)+ multi "other-modules" (fmap pretty . (.otherModules)) ] e) (preludeWithVersion, deps)@@ -323,7 +169,7 @@ convertComponent Library lib.libBuildInfo extra where extra = mkAttrs [- multi "reexported-modules" (.reexportedModules)+ multi "reexported-modules" (fmap pretty . (.reexportedModules)) ] lib convertExecutable :: UnqualComponentName -> Cabal.Executable -> HixComponent@@ -373,8 +219,8 @@ preludePackageAttrs p | Just dep <- p.dep = ExprAttrs [- (ExprAttr "name" (ExprString (toText p.prelude.preludePackage))),- (ExprAttr "version" (ExprString (show (pretty (depVerRange dep)))))+ ExprAttr "name" (ExprString (toText p.prelude.preludePackage)),+ ExprAttr "version" (ExprString (show (pretty (depVerRange dep)))) ] | otherwise = ExprString (toText p.prelude.preludePackage) key = case special of@@ -388,34 +234,33 @@ flakePackage :: HixPackage -> ExprAttr flakePackage pkg =- ExprAttr name attrs+ ExprAttr (coerce pkg.name) attrs where- attrs = ExprAttrs (src : pkg.description : (ExprAttr "cabal" cabalConfig : comps))- name = pkg.name.unPackageName+ attrs = ExprAttrs (src : pkg.description : ExprAttr "cabal" cabalConfig : comps) src = ExprAttr "src" (ExprLit [exon|./#{Text.dropWhileEnd ('/' ==) (pathText pkg.src)}|])- cabalConfig = ExprAttrs (pkg.known <> (if null pkg.meta then [] else [ExprAttr "meta" (ExprAttrs pkg.meta)]))+ cabalConfig = ExprAttrs (pkg.known <> [ExprAttr "meta" (ExprAttrs pkg.meta) | not (null pkg.meta)]) comps = renderComponent <$> pkg.components mainPackage :: [HixPackage] -> ExprAttr mainPackage = \case- pkg : _ : _ -> ExprAttr "main" (ExprString pkg.name.unPackageName)+ pkg : _ : _ -> ExprAttr "main" (ExprString (coerce pkg.name)) _ -> ExprAttrNil flake :: BootstrapProjectConfig -> [HixPackage] -> Expr flake conf pkgs = ExprAttrs [- (ExprAttr "description" (ExprString "A Haskell project")),- (ExprAttr "inputs.hix.url" (ExprString conf.hixUrl.unHixUrl)),- (ExprAttr "outputs" (ExprPrefix "{hix, ...}: hix.lib.flake" (ExprAttrs [- (ExprAttr "packages" (ExprAttrs (flakePackage <$> pkgs))),+ ExprAttr "description" (ExprString "A Haskell project"),+ ExprAttr "inputs.hix.url" (ExprString conf.hixUrl.unHixUrl),+ ExprAttr "outputs" (ExprPrefix "{hix, ...}: hix.lib.flake" (ExprAttrs [+ ExprAttr "packages" (ExprAttrs (flakePackage <$> pkgs)), mainPackage pkgs- ])))+ ])) ] bootstrapFiles :: BootstrapProjectConfig -> M [ProjectFile] bootstrapFiles conf = do- Env {cwd} <- ask- cabals <- paths =<< lift (tryIO (getDirectoryFilesIgnore (toFilePath cwd) ["**/*.cabal"] ["dist-newstyle/**"]))+ AppResources {cwd} <- M ask+ cabals <- paths =<< M (lift (tryIO (getDirectoryFilesIgnore (toFilePath cwd) ["**/*.cabal"] ["dist-newstyle/**"]))) pkgs <- fmap convert <$> traverse (readCabal cwd) cabals pure [ ProjectFile {path = [relfile|flake.nix|], content = renderRootExpr (flake conf pkgs)}
lib/Hix/Cabal.hs view
@@ -29,7 +29,8 @@ import System.IO.Error (tryIOError) import Hix.Compat (readGenericPackageDescription)-import Hix.Data.Error (Error (..), pathText, sourceError)+import Hix.Data.Error (Error (..))+import Hix.Error (pathText, sourceError) noMatch :: Text -> Path b File -> ExceptT Error IO a noMatch reason source =
+ lib/Hix/CabalParsec.hs view
@@ -0,0 +1,48 @@+module Hix.CabalParsec where++import Distribution.Parsec (Parsec, eitherParsec)+import Exon (exon)+import Type.Reflection (typeRep)++import Hix.Data.Monad (M)+import Hix.Monad (eitherClient)++eitherParsecFor ::+ Parsec b =>+ ToString a =>+ String ->+ a ->+ Either String b+eitherParsecFor desc spec =+ first errorMessage (eitherParsec s)+ where+ errorMessage err = error [exon|parsing #{desc} "#{s}": #{err}|]+ s = toString spec++unsafeParsecFor ::+ Parsec b =>+ ToString a =>+ String ->+ a ->+ b+unsafeParsecFor desc spec =+ either error id (eitherParsecFor desc spec)++unsafeParsec ::+ ∀ a b .+ Parsec b =>+ Typeable b =>+ ToString a =>+ a ->+ b+unsafeParsec =+ unsafeParsecFor (show (typeRep @b))++parsecM ::+ Parsec b =>+ ToString a =>+ String ->+ a ->+ M b+parsecM desc spec =+ eitherClient (first toText (eitherParsecFor desc spec))
+ lib/Hix/Class/EncodeNix.hs view
@@ -0,0 +1,91 @@+module Hix.Class.EncodeNix where++import qualified Data.Map.Strict as Map+import Distribution.Pretty (Pretty (pretty))+import Distribution.Utils.ShortText (ShortText, fromShortText)+import Distribution.Version (Version, VersionRange, simplifyVersionRange)+import Generics.SOP (All2, K (K), SListI2, hcmap, hcollapse)+import Text.PrettyPrint (Doc)++import Hix.Class.SOP (Field (Field), FieldK (FieldK), ToFields (toFields))+import Hix.Data.NixExpr (Expr (..), ExprAttr (ExprAttr), ViaPretty (ViaPretty), exprBool, exprShow)++type EncodeField :: FieldK -> Constraint+class EncodeField field where+ encodeField :: Field field -> ExprAttr++instance (+ KnownSymbol name,+ EncodeNix a+ ) => EncodeField ('FieldK name a) where+ encodeField (Field a) =+ ExprAttr (toText (symbolVal (Proxy @name))) (encodeNix a)++class EncodeProd a where+ encodeProd :: a -> Expr++instance (+ ToFields a fields,+ All2 EncodeField fields,+ SListI2 fields+ ) => EncodeProd a where+ encodeProd =+ ExprAttrs .+ hcollapse .+ hcmap (Proxy @EncodeField) (K . encodeField) .+ toFields++class EncodeNixKey a where+ encodeNixKey :: a -> Text++instance EncodeNixKey Text where+ encodeNixKey = id++class EncodeNix a where+ encodeNix :: a -> Expr+ default encodeNix :: EncodeProd a => a -> Expr+ encodeNix = encodeProd++instance EncodeNix Expr where+ encodeNix = id++instance EncodeNix Bool where+ encodeNix = exprBool++instance EncodeNix Int where+ encodeNix = exprShow++instance EncodeNix Version where+ encodeNix = encodeNix . pretty++instance EncodeNix VersionRange where+ encodeNix = encodeNix . pretty . simplifyVersionRange++instance EncodeNix a => EncodeNix (Maybe a) where+ encodeNix = \case+ Just a -> encodeNix a+ Nothing -> ExprNull++instance EncodeNix a => EncodeNix [a] where+ encodeNix = ExprList . fmap encodeNix++instance EncodeNix a => EncodeNix (NonEmpty a) where+ encodeNix = ExprList . toList . fmap encodeNix++instance (+ EncodeNixKey k,+ EncodeNix v+ ) => EncodeNix (Map k v) where+ encodeNix = ExprAttrs . fmap (uncurry ExprAttr . bimap encodeNixKey encodeNix) . Map.toList++instance EncodeNix Doc where+ encodeNix = ExprString . show++instance EncodeNix Text where+ encodeNix = ExprString++instance EncodeNix ShortText where+ encodeNix = encodeNix . toText . fromShortText++instance Pretty a => EncodeNix (ViaPretty a) where+ encodeNix (ViaPretty a) = encodeNix (pretty a)
+ lib/Hix/Class/Map.hs view
@@ -0,0 +1,715 @@+module Hix.Class.Map where++import qualified Data.Map.Merge.Strict as Map+import Data.Map.Merge.Strict (+ SimpleWhenMatched,+ SimpleWhenMissing,+ WhenMatched,+ WhenMissing,+ dropMissing,+ mapMissing,+ preserveMissing,+ zipWithMatched,+ )+import qualified Data.Map.Strict as Map+import Distribution.Pretty (Pretty (pretty))+import Exon (exon)+import qualified Text.PrettyPrint as PrettyPrint+import Text.PrettyPrint (Doc, comma, hang, punctuate, sep, vcat, (<+>))++import Hix.Data.Monad (M)+import Hix.Monad (noteFatal)++data LookupMonoid+data LookupMaybe+data LookupFatal++type NMap :: Type -> Type -> Type -> Type -> Constraint+class (Ord k, Coercible map (Map k v)) => NMap map k v sort | map -> k v sort where+ nGet :: map -> Map k v+ nGet = coerce++lookupError ::+ ∀ k v .+ Show k =>+ Text ->+ k ->+ Maybe v ->+ M v+lookupError thing k =+ noteFatal [exon|No such #{thing}: #{show k}|]++nFatal ::+ ∀ map k v sort .+ Show k =>+ NMap map k v sort =>+ Text ->+ k ->+ map ->+ M v+nFatal thing k m =+ lookupError thing k (nGet m Map.!? k)++type NLookup :: Type -> Type -> Type -> Type -> Constraint+class NLookup sort k v l | sort v -> l where+ nLookup :: k -> Maybe v -> l++instance Monoid v => NLookup LookupMonoid k v v where+ nLookup _ = fold++instance NLookup LookupMaybe k v (Maybe v) where+ nLookup _ = id++instance Show k => NLookup LookupFatal k v (Text -> M v) where+ nLookup k v thing = lookupError thing k v++(!?) ::+ ∀ map k v sort .+ NMap map k v sort =>+ map ->+ k ->+ Maybe v+(!?) m k = nGet m Map.!? k++infixl !?++(!!) ::+ ∀ map k v sort l .+ NMap map k v sort =>+ NLookup sort k v l =>+ map ->+ k ->+ l+(!!) m k = nLookup @sort @k @v @l k (m !? k)++infixl !!++nInsert ::+ ∀ map k v sort .+ NMap map k v sort =>+ k ->+ v ->+ map ->+ map+nInsert k v m =+ coerce (Map.insert k v (nGet m))++nUpdate ::+ ∀ map k v sort l .+ NMap map k v sort =>+ NLookup sort k v l =>+ k ->+ map ->+ (l -> v) ->+ map+nUpdate k m f =+ nInsert k (f (m !! k)) m++nUpdateWith ::+ ∀ map k v sort l .+ NMap map k v sort =>+ NLookup sort k v l =>+ k ->+ (l -> v) ->+ map ->+ map+nUpdateWith k =+ flip (nUpdate k)++nAdjust ::+ ∀ map k v sort .+ NMap map k v sort =>+ k ->+ map ->+ (v -> v) ->+ map+nAdjust k m f =+ nVia (Map.adjust f k) m++nVia ::+ NMap map1 k1 v1 s1 =>+ NMap map2 k2 v2 s2 =>+ (Map k1 v1 -> Map k2 v2) ->+ map1 ->+ map2+nVia =+ coerce++nViaA ::+ Applicative m =>+ NMap map1 k1 v1 s1 =>+ NMap map2 k2 v2 s2 =>+ (Map k1 v1 -> m (Map k2 v2)) ->+ map1 ->+ m map2+nViaA f m =+ coerce <$> f (coerce m)++nMapKeys ::+ NMap map1 k1 v sort1 =>+ NMap map2 k2 v sort2 =>+ (k1 -> k2) ->+ map1 ->+ map2+nMapKeys f =+ nVia (Map.mapKeys f)++nMap ::+ NMap map1 k v1 sort1 =>+ NMap map2 k v2 sort2 =>+ (v1 -> v2) ->+ map1 ->+ map2+nMap f =+ coerce . fmap f . nGet++nMap1 ::+ ∀ map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2' .+ NMap map1 k map1' s1 =>+ NMap map2 k map2' s2 =>+ NMap map1' k' v1 s1' =>+ NMap map2' k' v2 s2' =>+ (v1 -> v2) ->+ map1 ->+ map2+nMap1 =+ nMap . nMap++nMapWithKey ::+ NMap map1 k v1 sort1 =>+ NMap map2 k v2 sort2 =>+ (k -> v1 -> v2) ->+ map1 ->+ map2+nMapWithKey f =+ coerce . Map.mapWithKey f . nGet++nMapWithKey1 ::+ ∀ map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2' .+ NMap map1 k map1' s1 =>+ NMap map2 k map2' s2 =>+ NMap map1' k' v1 s1' =>+ NMap map2' k' v2 s2' =>+ (k -> k' -> v1 -> v2) ->+ map1 ->+ map2+nMapWithKey1 f =+ nMapWithKey \ k -> nMapWithKey (f k)++nTransform ::+ NMap map1 k1 v1 sort1 =>+ NMap map2 k2 v2 sort2 =>+ (k1 -> v1 -> (k2, v2)) ->+ map1 ->+ map2+nTransform f =+ coerce .+ Map.fromList .+ fmap (uncurry f) .+ Map.toList .+ nGet++nTransformMaybe ::+ NMap map1 k1 v1 sort1 =>+ NMap map2 k2 v2 sort2 =>+ (k1 -> v1 -> Maybe (k2, v2)) ->+ map1 ->+ map2+nTransformMaybe f =+ coerce .+ Map.fromList .+ mapMaybe (uncurry f) .+ Map.toList .+ nGet++nMapMaybe ::+ NMap map1 k v1 sort1 =>+ NMap map2 k v2 sort2 =>+ (v1 -> Maybe v2) ->+ map1 ->+ map2+nMapMaybe f =+ coerce . Map.mapMaybeWithKey (const f) . nGet++nMapMaybe1 ::+ ∀ map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2' .+ NMap map1 k map1' s1 =>+ NMap map2 k map2' s2 =>+ NMap map1' k' v1 s1' =>+ NMap map2' k' v2 s2' =>+ (v1 -> Maybe v2) ->+ map1 ->+ map2+nMapMaybe1 =+ nMap . nMapMaybe++nMapMaybeWithKey ::+ NMap map1 k v1 sort1 =>+ NMap map2 k v2 sort2 =>+ (k -> v1 -> Maybe v2) ->+ map1 ->+ map2+nMapMaybeWithKey f =+ coerce .+ Map.mapMaybeWithKey f .+ nGet++nMapMaybeWithKey1 ::+ ∀ map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2' .+ NMap map1 k map1' s1 =>+ NMap map2 k map2' s2 =>+ NMap map1' k' v1 s1' =>+ NMap map2' k' v2 s2' =>+ (k' -> v1 -> Maybe v2) ->+ map1 ->+ map2+nMapMaybeWithKey1 =+ nMap . nMapMaybeWithKey++nCatMaybes ::+ NMap map1 k (Maybe v) sort1 =>+ NMap map2 k v sort2 =>+ map1 ->+ map2+nCatMaybes =+ nMapMaybe id++nFilter ::+ ∀ map k v sort .+ NMap map k v sort =>+ (v -> Bool) ->+ map ->+ map+nFilter =+ nVia . Map.filter++nFilter1 ::+ ∀ map map' k k' v s s' .+ NMap map k map' s =>+ NMap map' k' v s' =>+ (v -> Bool) ->+ map ->+ map+nFilter1 =+ nMap . nFilter++nPrettyWith ::+ Pretty k =>+ NMap map k v sort =>+ (v -> Doc) ->+ map ->+ Doc+nPrettyWith prettyV (nGet -> m) =+ sep (punctuate comma (assoc <$> Map.toList m))+ where+ assoc (k, v) = pretty k <+> "->" <+> prettyV v++nPretty ::+ Pretty k =>+ Pretty v =>+ NMap map k v sort =>+ map ->+ Doc+nPretty =+ nPrettyWith pretty++nPretty1 ::+ Pretty k =>+ Pretty v =>+ NMap map k v sort =>+ map ->+ Doc+nPretty1 (nGet -> m) =+ vcat (assoc <$> Map.toList m)+ where+ assoc (k, v) = hang (pretty k PrettyPrint.<> ":") 2 (pretty v)++nMergeA ::+ ∀ map1 map2 map3 k v1 v2 v3 s1 s2 s3 m .+ Applicative m =>+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ NMap map3 k v3 s3 =>+ WhenMissing m k v1 v3 ->+ WhenMissing m k v2 v3 ->+ WhenMatched m k v1 v2 v3 ->+ map1 ->+ map2 ->+ m map3+nMergeA missing1 missing2 matched map1 map2 =+ nViaA (Map.mergeA missing1 missing2 matched (nGet map1)) map2++nMerge ::+ ∀ map1 map2 map3 k v1 v2 v3 s1 s2 s3 .+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ NMap map3 k v3 s3 =>+ SimpleWhenMissing k v1 v3 ->+ SimpleWhenMissing k v2 v3 ->+ SimpleWhenMatched k v1 v2 v3 ->+ map1 ->+ map2 ->+ map3+nMerge missing1 missing2 matched map1 map2 =+ nVia (Map.merge missing1 missing2 matched (nGet map1)) map2++nAmendWithKey ::+ ∀ map1 map2 k v1 v2 s1 s2 .+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ (k -> v1 -> v2 -> v2) ->+ map1 ->+ map2 ->+ map2+nAmendWithKey matched =+ nMerge dropMissing preserveMissing (zipWithMatched matched)++-- | For each key that is present in both maps, replace the value by the result of the combining function.+-- For everything else, leave @map2@ unchanged.+nAmend ::+ ∀ map1 map2 k v1 v2 s1 s2 .+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ (v1 -> v2 -> v2) ->+ map1 ->+ map2 ->+ map2+nAmend matched =+ nAmendWithKey (const matched)++-- | For each key path that is present in both submaps, replace the value by the result of the combining function.+-- For everything else, leave @map2@ unchanged.+nAmend1 ::+ ∀ map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2' .+ NMap map1 k map1' s1 =>+ NMap map2 k map2' s2 =>+ NMap map1' k' v1 s1' =>+ NMap map2' k' v2 s2' =>+ (v1 -> v2 -> v2) ->+ map1 ->+ map2 ->+ map2+nAmend1 matched =+ nMerge dropMissing preserveMissing (zipWithMatched matched1)+ where+ matched1 _ map1' map2' = nAmend matched map1' map2'++-- | For each key that is present in both maps, replace the value by the result of the combining function.+-- For each key that is present in @map1@, insert the result of the conversion function.+-- Keep keys only present in @map2@.+nPad ::+ ∀ map1 map2 k v1 v2 s1 s2 .+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ (v1 -> v2 -> v2) ->+ (v1 -> v2) ->+ map1 ->+ map2 ->+ map2+nPad matched conv =+ nMerge (mapMissing (const conv)) preserveMissing (zipWithMatched (const matched))++-- | For each key path that is present in both submaps, replace the value by the result of the combining function.+-- For each key and key path that is present only in @map1@ and each submap, insert the result of the conversion+-- function.+-- Keep keys only present in @map2@ and each submap.+nPad1 ::+ ∀ map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2' .+ NMap map1 k map1' s1 =>+ NMap map2 k map2' s2 =>+ NMap map1' k' v1 s1' =>+ NMap map2' k' v2 s2' =>+ (v1 -> v2 -> v2) ->+ (v1 -> v2) ->+ map1 ->+ map2 ->+ map2+nPad1 matched conv =+ nMerge (mapMissing missing) preserveMissing (zipWithMatched matched1)+ where+ missing _ = nMap conv+ matched1 _ = nPad matched conv++-- | For each key that is present only in @map1@, insert the result of the conversion function.+-- For everything else, leave @map2@ unchanged.+nPadKeep ::+ ∀ map1 map2 k v1 v2 s1 s2 .+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ (v1 -> v2) ->+ map1 ->+ map2 ->+ map2+nPadKeep =+ nPad \ _ v2 -> v2++-- | For each key and key path that is present only in @map1@ and each submap, insert the result of the conversion+-- function.+-- For everything else, leave @map2@ and its submaps unchanged.+nPadKeep1 ::+ ∀ map1 map2 map1' map2' k k' v1 v2 s1 s2 s1' s2' .+ NMap map1 k map1' s1 =>+ NMap map2 k map2' s2 =>+ NMap map1' k' v1 s1' =>+ NMap map2' k' v2 s2' =>+ (v1 -> v2) ->+ map1 ->+ map2 ->+ map2+nPadKeep1 =+ nPad1 \ _ v2 -> v2++nZipWithKeyR ::+ ∀ map1 map2 map3 k v1 v2 v3 s1 s2 s3 .+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ NMap map3 k v3 s3 =>+ (k -> Maybe v1 -> v2 -> v3) ->+ map1 ->+ map2 ->+ map3+nZipWithKeyR f =+ nMerge dropMissing (mapMissing missing) (zipWithMatched matched)+ where+ missing k = f k Nothing+ matched k v = f k (Just v)++nZipR ::+ ∀ map1 map2 map3 k v1 v2 v3 s1 s2 s3 .+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ NMap map3 k v3 s3 =>+ (Maybe v1 -> v2 -> v3) ->+ map1 ->+ map2 ->+ map3+nZipR f = nZipWithKeyR (const f)++nZipWithKey ::+ ∀ map1 map2 map3 k v1 v2 v3 s1 s2 s3 .+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ NMap map3 k v3 s3 =>+ (k -> v1 -> v2 -> v3) ->+ map1 ->+ map2 ->+ map3+nZipWithKey f =+ nMerge dropMissing dropMissing (zipWithMatched f)++nZip ::+ ∀ map1 map2 map3 k v1 v2 v3 s1 s2 s3 .+ NMap map1 k v1 s1 =>+ NMap map2 k v2 s2 =>+ NMap map3 k v3 s3 =>+ (v1 -> v2 -> v3) ->+ map1 ->+ map2 ->+ map3+nZip f = nZipWithKey (const f)++nFromList ::+ NMap map k v sort =>+ [(k, v)] ->+ map+nFromList =+ coerce . Map.fromList++nList ::+ NMap map k v sort =>+ map ->+ [(k, v)]+nList =+ Map.toList . coerce++nTo ::+ NMap map k v sort =>+ map ->+ (k -> v -> a) ->+ [a]+nTo m f =+ fmap (uncurry f) (nList m)++nToWith ::+ NMap map k v sort =>+ (k -> v -> a) ->+ map ->+ [a]+nToWith = flip nTo++nConcat ::+ Monoid a =>+ NMap map k v sort =>+ map ->+ (k -> v -> a) ->+ a+nConcat m f =+ mconcat (uncurry f <$> nList m)++nConcatWith ::+ Monoid a =>+ NMap map k v sort =>+ (k -> v -> a) ->+ map ->+ a+nConcatWith =+ flip nConcat++nToMaybe ::+ NMap map k v sort =>+ map ->+ (k -> v -> Maybe a) ->+ [a]+nToMaybe m f =+ mapMaybe (uncurry f) (nList m)++nTo1 ::+ ∀ map1 map2 k1 k2 v s1 s2 a .+ NMap map1 k1 map2 s1 =>+ NMap map2 k2 v s2 =>+ map1 ->+ (k1 -> k2 -> v -> a) ->+ [a]+nTo1 m1 f =+ nConcat m1 (nToWith . f)++nToWith1 ::+ ∀ map1 map2 k1 k2 v s1 s2 a .+ NMap map1 k1 map2 s1 =>+ NMap map2 k2 v s2 =>+ (k1 -> k2 -> v -> a) ->+ map1 ->+ [a]+nToWith1 f =+ nConcatWith (nToWith . f)++nFromKeys ::+ Foldable t =>+ NMap map k v sort =>+ t k ->+ (k -> v) ->+ map+nFromKeys keys f =+ nFromList (toList keys <&> \ k -> (k, f k))++nFromKeysMaybe ::+ Foldable t =>+ NMap map k v sort =>+ t k ->+ (k -> Maybe v) ->+ map+nFromKeysMaybe keys f =+ nFromList (flip mapMaybe (toList keys) \ k -> (k,) <$> f k)++nBy ::+ Foldable t =>+ NMap map k v sort =>+ t v ->+ (v -> k) ->+ map+nBy values f =+ nFromList (toList values <&> \ v -> (f v, v))++nGen ::+ Foldable t =>+ NMap map k v sort =>+ t a ->+ (a -> (k, v)) ->+ map+nGen values f =+ nFromList (f <$> toList values)++nGenWith ::+ Foldable t =>+ NMap map k v sort =>+ (a -> (k, v)) ->+ t a ->+ map+nGenWith =+ flip nGen++nGenMaybe ::+ Foldable t =>+ NMap map k v sort =>+ t a ->+ (a -> Maybe (k, v)) ->+ map+nGenMaybe values f =+ nFromList (mapMaybe f (toList values))++nForKeys ::+ Applicative m =>+ NMap map k v sort =>+ [k] ->+ (k -> m v) ->+ m map+nForKeys keys f =+ nFromList <$> for keys \ k -> (k,) <$> f k++nFor ::+ Applicative m =>+ NMap map k v sort =>+ [v] ->+ (v -> m k) ->+ m map+nFor values f =+ nFromList <$> for values \ v -> (,v) <$> f v++nElems ::+ ∀ map k v s .+ NMap map k v s =>+ map ->+ [v]+nElems =+ Map.elems . nGet++nElems1 ::+ ∀ map1 map2 k1 k2 v s1 s2 .+ NMap map1 k1 map2 s1 =>+ NMap map2 k2 v s2 =>+ map1 ->+ [v]+nElems1 =+ nElems <=< nElems++nFlatten ::+ ∀ map1 map2 map3 k1 k2 v1 v2 s1 s2 .+ Monoid map2 =>+ NMap map1 k1 map2 LookupMonoid =>+ NMap map2 k2 v1 s1 =>+ NMap map3 k2 v2 s2 =>+ (v1 -> v2) ->+ map1 ->+ map3+nFlatten f =+ nMap f . mconcat . nElems++nKeys ::+ NMap map k v sort =>+ map ->+ [k]+nKeys =+ Map.keys . nGet++nKeysSet ::+ NMap map k v sort =>+ map ->+ Set k+nKeysSet =+ Map.keysSet . nGet++nRestrictKeys ::+ NMap map k v sort =>+ Set k ->+ map ->+ map+nRestrictKeys keys =+ nVia (`Map.restrictKeys` keys)++nWithoutKeys ::+ NMap map k v sort =>+ Set k ->+ map ->+ map+nWithoutKeys keys =+ nVia (`Map.withoutKeys` keys)
+ lib/Hix/Class/SOP.hs view
@@ -0,0 +1,54 @@+module Hix.Class.SOP where++import Generics.SOP (I (I), NP (Nil, (:*)), NS (S, Z), SOP (SOP))+import Generics.SOP.GGP (GCode, GDatatypeInfoOf, GFrom, gfrom)+import Generics.SOP.Type.Metadata (ConstructorInfo (Record), DatatypeInfo (..), FieldInfo (FieldInfo))++data FieldK =+ FieldK {+ name :: Symbol,+ tpe :: Type+ }++type Field :: FieldK -> Type+data Field k where+ Field :: a -> Field ('FieldK name a)++type ProdFields :: [FieldInfo] -> [Type] -> [FieldK] -> Constraint+class ProdFields info as fields | info as -> fields where+ prodFields :: NP I as -> NP Field fields++instance ProdFields '[] '[] '[] where+ prodFields Nil = Nil++instance (+ ProdFields info as fields+ ) => ProdFields ('FieldInfo name : info) (a : as) ('FieldK name a : fields) where+ prodFields (I a :* fields) = Field a :* prodFields @info fields++type SumFields :: [ConstructorInfo] -> [[Type]] -> [[FieldK]] -> Constraint+class SumFields cons ass fields | cons ass -> fields where+ sumFields :: NS (NP I) ass -> NS (NP Field) fields++instance SumFields '[] '[] '[] where+ sumFields = \case++instance (+ ProdFields info as conFields,+ SumFields cons ass fields+ ) => SumFields ('Record con info : cons) (as : ass) (conFields : fields) where+ sumFields = \case+ Z con -> Z (prodFields @info con)+ S cons -> S (sumFields @cons cons)++class ToFields a fields | a -> fields where+ toFields :: a -> SOP Field fields++instance (+ Generic a,+ GFrom a,+ 'ADT mod name cons sni ~ GDatatypeInfoOf a,+ ass ~ GCode a,+ SumFields cons ass fields+ ) => ToFields a fields where+ toFields (gfrom -> SOP fields) = SOP (sumFields @cons fields)
lib/Hix/Component.hs view
@@ -11,21 +11,17 @@ import Hix.Data.ComponentConfig ( ComponentConfig, PackageConfig (PackageConfig),- PackageName (PackageName), PackagesConfig, SourceDir (SourceDir), Target (Target), TargetOrDefault (DefaultTarget, ExplicitTarget, NoDefaultTarget), )-import Hix.Data.Error (Error (EnvError), pathText)+import Hix.Data.Error (Error (EnvError))+import qualified Hix.Data.Options as Options+import Hix.Data.Options (ComponentCoords, ComponentSpec (ComponentSpec), PackageSpec (PackageSpec), TargetSpec (..))+import Hix.Data.PackageName (PackageName (PackageName))+import Hix.Error (pathText) import Hix.Monad (M, noteEnv, throwM)-import qualified Hix.Options as Options-import Hix.Options (- ComponentCoords,- ComponentSpec (ComponentSpec),- PackageSpec (PackageSpec),- TargetSpec (TargetForComponent, TargetForFile),- ) import Hix.Path (rootDir) data ResolvedPackage =
+ lib/Hix/Console.hs view
@@ -0,0 +1,84 @@+module Hix.Console where++import qualified Data.ByteString.Char8 as ByteString+import qualified Data.Text.IO as Text+import Exon (exon)+import System.IO (Handle, stderr, stdout)++hPrint ::+ MonadIO m =>+ Handle ->+ Text ->+ m ()+hPrint h msg =+ liftIO (Text.hPutStrLn h msg)++hPrintBS ::+ MonadIO m =>+ Handle ->+ ByteString ->+ m ()+hPrintBS h msg =+ liftIO (ByteString.hPutStrLn h msg)++out :: MonadIO m => Text -> m ()+out = hPrint stdout++err :: MonadIO m => Text -> m ()+err = hPrint stderr++bytesOut :: MonadIO m => ByteString -> m ()+bytesOut = hPrintBS stdout++bytesErr :: MonadIO m => ByteString -> m ()+bytesErr = hPrintBS stderr++sgi :: Text -> Text+sgi param =+ [exon|#{esc}[#{param}m|]+ where+ esc = "\ESC"++sgis :: [Text] -> Text -> Text+sgis params chunk =+ [exon|#{seqs}#{chunk}#{sgi "0"}|]+ where+ seqs = mconcat (sgi <$> params)++color :: Int -> Text -> Text+color n =+ sgis [show (30 + n)]++data ColorOffsets =+ ColorOffsets {+ black :: Int,+ red :: Int,+ green :: Int,+ yellow :: Int,+ blue :: Int,+ magenta :: Int,+ cyan :: Int,+ white :: Int+ }+ deriving stock (Eq, Show, Generic)++colors :: ColorOffsets+colors =+ ColorOffsets {+ black = 0,+ red = 1,+ green = 2,+ yellow = 3,+ blue = 4,+ magenta = 5,+ cyan = 6,+ white = 7+ }++withChevrons :: Int -> Text -> Text+withChevrons col msg =+ [exon|#{sgis [show (30 + col), "1"] ">>>"} #{msg}|]++errorMessage :: Text -> Text+errorMessage msg =+ withChevrons 1 [exon|Error: #{msg}|]
+ lib/Hix/Data/Bounds.hs view
@@ -0,0 +1,49 @@+module Hix.Data.Bounds where++import Data.Aeson (FromJSON (parseJSON), ToJSON)+import Distribution.Pretty (Pretty (pretty))+import Distribution.Version (Version, VersionRange)+import GHC.Exts (IsList)++import Hix.Class.EncodeNix (EncodeNix)+import Hix.Class.Map (LookupMaybe, NMap, nPretty)+import Hix.Data.Json (jsonParsec)+import Hix.Data.PackageName (PackageName)+import Hix.Data.VersionBounds (VersionBounds)++newtype Bounds =+ Bounds (Map PackageName VersionBounds)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList, EncodeNix, FromJSON, ToJSON)++instance NMap Bounds PackageName VersionBounds LookupMaybe where++instance Pretty Bounds where+ pretty = nPretty++newtype Ranges =+ Ranges (Map PackageName VersionRange)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList)++instance NMap Ranges PackageName VersionRange LookupMaybe where++instance Pretty Ranges where+ pretty = nPretty++instance FromJSON Ranges where+ parseJSON v =+ Ranges . fmap jsonParsec <$> parseJSON v++data BoundExtension =+ LowerBoundExtension Version+ |+ UpperBoundExtension Version+ deriving stock (Eq, Show, Generic)++newtype BoundExtensions =+ BoundExtensions (Map PackageName BoundExtension)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList)++instance NMap BoundExtensions PackageName BoundExtension LookupMaybe where
lib/Hix/Data/ComponentConfig.hs view
@@ -1,8 +1,11 @@ module Hix.Data.ComponentConfig where import Data.Aeson (FromJSON (parseJSON), FromJSONKey, withObject, (.:))+import Distribution.Pretty (Pretty (pretty)) import Path (Abs, Dir, File, Path, Rel) +import Hix.Data.PackageName (PackageName)+ newtype PackagePath = PackagePath { unPackagePath :: Path Rel Dir } deriving stock (Eq, Show, Ord, Generic)@@ -23,11 +26,6 @@ <|> (SourceDirs . pure <$> parseJSON v) -newtype PackageName =- PackageName { unPackageName :: Text }- deriving stock (Eq, Show, Generic)- deriving newtype (IsString, Ord, FromJSON, FromJSONKey)- newtype ModuleName = ModuleName { unModuleName :: Text } deriving stock (Eq, Show, Generic)@@ -38,10 +36,8 @@ deriving stock (Eq, Show, Generic) deriving newtype (IsString, Ord, FromJSON, FromJSONKey) -newtype EnvName =- EnvName { unEnvName :: Text }- deriving stock (Eq, Show, Generic)- deriving newtype (IsString, Ord, FromJSON, FromJSONKey)+instance Pretty ComponentName where+ pretty (ComponentName n) = fromString (toString n) newtype EnvRunner = EnvRunner (Path Abs File)
+ lib/Hix/Data/Dep.hs view
@@ -0,0 +1,59 @@+module Hix.Data.Dep where++import Data.Aeson (FromJSON (parseJSON), Value (Object, String), (.:))+import Data.Aeson.Types (Parser)+import Distribution.Package (mainLibSet)+import Distribution.Pretty (Pretty, pretty)+import Distribution.Types.Dependency (Dependency (Dependency))+import Distribution.Version (VersionRange, thisVersion)+import Exon (exon)++import Hix.Data.Json (aesonParsec, jsonParsec)+import qualified Hix.Data.PackageName as PackageName+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (Version)++data Dep =+ Dep {+ package :: PackageName,+ version :: VersionRange+ }+ deriving stock (Eq, Show, Generic)++toCabal :: Dep -> Dependency+toCabal Dep {..} =+ Dependency (PackageName.toCabal package) version mainLibSet++fromCabal :: Dependency -> Dep+fromCabal (Dependency (PackageName.fromCabal -> package) version _) =+ Dep {package, version}++instance Pretty Dep where+ pretty = pretty . toCabal++mkDep :: PackageName -> VersionRange -> Dep+mkDep package version = Dep {..}++jsonParseCabal :: String -> Parser Dep+jsonParseCabal v = fromCabal <$> aesonParsec v++renderDep :: Dep -> Text+renderDep = show . pretty++thisVersionDep :: PackageName -> Version -> Dep+thisVersionDep package version =+ mkDep package (thisVersion version)++instance FromJSON Dep where+ parseJSON = \case+ String s ->+ jsonParseCabal (toString s)+ Object o -> do+ fromName <- jsonParseCabal =<< o .: "name"+ version <- (jsonParsec <$> o .: "version") <|> pure fromName.version+ pure fromName {version}+ v ->+ fail [exon|Invalid dependency format: #{show v}|]++withVersion :: VersionRange -> Dep -> Dep+withVersion version dep = dep {version}
+ lib/Hix/Data/EnvName.hs view
@@ -0,0 +1,15 @@+module Hix.Data.EnvName where++import Data.Aeson (FromJSON, FromJSONKey)+import Distribution.Pretty (Pretty (pretty))++import Hix.Class.EncodeNix (EncodeNixKey)+import Hix.Pretty (prettyText)++newtype EnvName =+ EnvName { unEnvName :: Text }+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsString, Ord, FromJSON, FromJSONKey, EncodeNixKey)++instance Pretty EnvName where+ pretty (EnvName n) = prettyText n
lib/Hix/Data/Error.hs view
@@ -1,12 +1,5 @@ module Hix.Data.Error where -import Control.Monad.Trans.Except (ExceptT, throwE)-import qualified Data.Text.IO as Text-import Exon (exon)-import Path (Path, toFilePath)-import System.IO (stderr)-import System.IO.Error (tryIOError)- data Error = PreprocError Text |@@ -21,66 +14,6 @@ NoMatch Text | Fatal Text+ |+ Client Text deriving stock (Eq, Show, Generic)--pathText :: Path b t -> Text-pathText =- toText . toFilePath--printPreprocError ::- MonadIO m =>- Text ->- m ()-printPreprocError msg =- liftIO (Text.hPutStrLn stderr [exon|>>> Preprocessor generator failed: #{msg}|])--printEnvError ::- MonadIO m =>- Text ->- m ()-printEnvError msg =- liftIO (Text.hPutStrLn stderr [exon|>>> Invalid env config: #{msg}|])--printGhciError ::- MonadIO m =>- Text ->- m ()-printGhciError msg =- liftIO (Text.hPutStrLn stderr [exon|>>> Invalid ghci config: #{msg}|])--printNewError ::- MonadIO m =>- Text ->- m ()-printNewError msg =- liftIO (Text.hPutStrLn stderr [exon|>>> Can't create new project: #{msg}|])--printBootstrapError ::- MonadIO m =>- Text ->- m ()-printBootstrapError msg =- liftIO (Text.hPutStrLn stderr [exon|>>> Can't bootstrap project: #{msg}|])--printFatalError ::- MonadIO m =>- Text ->- m ()-printFatalError msg =- liftIO (Text.hPutStrLn stderr [exon|>>> Fatal error: #{msg}|])--sourceError :: Text -> Path b t -> Text-sourceError reason source =- [exon|#{reason} the source file '#{pathText source}'|]--tryIO ::- IO a ->- ExceptT Error IO a-tryIO ma =- liftIO (tryIOError ma) >>= \case- Right a -> pure a- Left err -> throwE (Fatal (show err))--note :: Text -> Maybe a -> ExceptT Error IO a-note err =- maybe (throwE (GhciError err)) pure
lib/Hix/Data/GhciConfig.hs view
@@ -3,7 +3,8 @@ import Data.Aeson (FromJSON, FromJSONKey) import GHC.Exts (IsList) -import Hix.Data.ComponentConfig (EnvRunner, PackageName, PackagesConfig)+import Hix.Data.ComponentConfig (EnvRunner, PackagesConfig)+import Hix.Data.PackageName (PackageName) newtype RunnerName = RunnerName { unRunnerName :: Text }
+ lib/Hix/Data/GlobalOptions.hs view
@@ -0,0 +1,28 @@+module Hix.Data.GlobalOptions where++import Path (Abs, Dir, Path)++import Hix.Data.OutputFormat (OutputFormat (OutputNone))+import Hix.Data.OutputTarget (OutputTarget (OutputDefault))++data GlobalOptions =+ GlobalOptions {+ verbose :: Bool,+ debug :: Bool,+ quiet :: Bool,+ cwd :: Path Abs Dir,+ output :: OutputFormat,+ target :: OutputTarget+ }+ deriving stock (Eq, Show, Generic)++defaultGlobalOptions :: Path Abs Dir -> GlobalOptions+defaultGlobalOptions cwd =+ GlobalOptions {+ verbose = False,+ debug = False,+ quiet = False,+ cwd,+ output = OutputNone,+ target = OutputDefault+ }
+ lib/Hix/Data/Json.hs view
@@ -0,0 +1,33 @@+module Hix.Data.Json where++import Data.Aeson (FromJSON (parseJSON), Key, Object, (.:?))+import Data.Aeson.Types (Parser)+import Distribution.Parsec (Parsec, eitherParsec)++aesonParsec ::+ Parsec a =>+ String ->+ Parser a+aesonParsec =+ leftA fail . eitherParsec++newtype JsonParsec a =+ JsonParsec a+ deriving stock (Eq, Show, Generic)++instance Parsec a => FromJSON (JsonParsec a) where+ parseJSON v = do+ raw <- parseJSON v+ JsonParsec <$> aesonParsec raw++jsonParsec :: JsonParsec a -> a+jsonParsec = coerce++foldMissing ::+ Monoid a =>+ FromJSON a =>+ Object ->+ Key ->+ Parser a+foldMissing o k =+ fold <$> o .:? k
+ lib/Hix/Data/Monad.hs view
@@ -0,0 +1,51 @@+module Hix.Data.Monad where++import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Except (ExceptT)+import Control.Monad.Trans.Reader (ReaderT, asks)+import GHC.Records (HasField (getField))+import Path (Abs, Dir, Path)++import Hix.Data.Error (Error)+import Hix.Data.OutputFormat (OutputFormat)+import Hix.Data.OutputTarget (OutputTarget)++data LogLevel =+ LogError+ |+ LogWarn+ |+ LogInfo+ |+ LogVerbose+ |+ LogDebug+ deriving stock (Eq, Show, Generic)++data AppResources =+ AppResources {+ cwd :: Path Abs Dir,+ tmp :: Path Abs Dir,+ verbose :: Bool,+ debug :: Bool,+ quiet :: Bool,+ output :: OutputFormat,+ target :: OutputTarget,+ logger :: LogLevel -> Text -> M ()+ }++newtype M a =+ M (ReaderT AppResources (ExceptT Error IO) a)+ deriving newtype (Functor, Applicative, Monad, MonadIO, MonadThrow, MonadCatch, MonadMask)++liftE :: ExceptT Error IO a -> M a+liftE = M . lift++data AppResProxy = AppResProxy++instance HasField name AppResources a => HasField name AppResProxy (M a) where+ getField AppResProxy = M (asks (getField @name))++appRes :: AppResProxy+appRes = AppResProxy
+ lib/Hix/Data/NixExpr.hs view
@@ -0,0 +1,38 @@+module Hix.Data.NixExpr where++data ExprAttr =+ ExprAttr {+ name :: Text,+ value :: Expr+ }+ |+ ExprAttrNil+ deriving stock (Eq, Show, Generic)++data Expr =+ ExprNull+ |+ ExprString Text+ |+ ExprLit Text+ |+ ExprList [Expr]+ |+ ExprAttrs [ExprAttr]+ |+ ExprPrefix Text Expr+ deriving stock (Eq, Show, Generic)++exprShow :: Show a => a -> Expr+exprShow =+ ExprLit . show++exprBool :: Bool -> Expr+exprBool =+ ExprLit . \case+ True -> "true"+ False -> "false"++newtype ViaPretty a =+ ViaPretty a+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Data/Options.hs view
@@ -0,0 +1,203 @@+module Hix.Data.Options where++import Path (Abs, Dir, File, Path, SomeBase)++import Hix.Data.BootstrapProjectConfig (BootstrapProjectConfig)+import Hix.Data.ComponentConfig (ComponentName, ModuleName, SourceDir)+import Hix.Data.EnvName (EnvName)+import Hix.Data.GhciConfig (ChangeDir, EnvConfig, GhciConfig, RunnerName)+import Hix.Data.GlobalOptions (GlobalOptions)+import Hix.Data.NewProjectConfig (NewProjectConfig)+import Hix.Data.PackageName (PackageName)+import Hix.Data.PreprocConfig (PreprocConfig)+import Hix.Managed.Cabal.Data.Config (CabalConfig)+import Hix.Managed.Data.BuildConfig (BuildConfig)+import Hix.Managed.Data.ProjectContextProto (ProjectContextProto)+import Hix.Managed.Data.Query (RawQuery)+import Hix.Managed.Data.StateFileConfig (StateFileConfig)+import Hix.Managed.Handlers.Build (SpecialBuildHandlers)+import Hix.Optparse (JsonConfig)++data PreprocOptions =+ PreprocOptions {+ config :: Maybe (Either PreprocConfig JsonConfig),+ root :: Maybe (Path Abs Dir),+ source :: Path Abs File,+ inFile :: Path Abs File,+ outFile :: Path Abs File+ }+ deriving stock (Show, Generic)++data PackageSpec =+ PackageSpec {+ name :: PackageName,+ dir :: Maybe (SomeBase Dir)+ }+ deriving stock (Eq, Show, Generic)++data ComponentSpec =+ ComponentSpec {+ name :: ComponentName,+ dir :: Maybe SourceDir+ }+ deriving stock (Eq, Show, Generic)++data ComponentCoords =+ ComponentCoords {+ package :: Maybe PackageSpec,+ component :: Maybe ComponentSpec+ }+ deriving stock (Eq, Show, Generic)++data TargetSpec =+ TargetForFile (Path Abs File)+ |+ TargetForComponent ComponentCoords+ deriving stock (Eq, Show, Generic)++data TestOptions =+ TestOptions {+ mod :: ModuleName,+ test :: Maybe Text,+ runner :: Maybe RunnerName,+ cd :: ChangeDir+ }+ deriving stock (Eq, Show, Generic)++data EnvRunnerOptions =+ EnvRunnerOptions {+ config :: Either EnvConfig JsonConfig,+ root :: Maybe (Path Abs Dir),+ component :: Maybe TargetSpec+ }+ deriving stock (Show, Generic)++newtype ExtraGhciOptions =+ ExtraGhciOptions Text+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsString)++newtype ExtraGhcidOptions =+ ExtraGhcidOptions Text+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsString)++data GhciOptions =+ GhciOptions {+ config :: Either GhciConfig JsonConfig,+ root :: Maybe (Path Abs Dir),+ component :: TargetSpec,+ test :: TestOptions,+ extra :: Maybe ExtraGhciOptions+ }+ deriving stock (Show, Generic)++data GhcidOptions =+ GhcidOptions {+ ghci :: GhciOptions,+ extra :: Maybe ExtraGhcidOptions+ }+ deriving stock (Show, Generic)++data NewOptions =+ NewOptions {+ config :: NewProjectConfig+ }+ deriving stock (Eq, Show, Generic)++data BootstrapOptions =+ BootstrapOptions {+ config :: BootstrapProjectConfig+ }+ deriving stock (Eq, Show, Generic)++data EnvRunnerCommandOptions =+ EnvRunnerCommandOptions {+ options :: EnvRunnerOptions,+ test :: TestOptions,+ extraGhci :: Maybe ExtraGhciOptions,+ extraGhcid :: Maybe ExtraGhcidOptions+ }+ deriving stock (Show, Generic)++data ProjectOptions =+ ProjectOptions {+ build :: BuildConfig,+ envs :: [EnvName],+ query :: RawQuery,+ readUpperBounds :: Bool,+ mergeBounds :: Bool+ }+ deriving stock (Eq, Show, Generic)++instance Default ProjectOptions where+ def = ProjectOptions {+ build = def,+ envs = [],+ query = [],+ readUpperBounds = False,+ mergeBounds = False+ }++projectOptions :: [EnvName] -> ProjectOptions+projectOptions envs = def {envs}++data ManagedOptions =+ ManagedOptions {+ context :: Either ProjectContextProto JsonConfig,+ project :: ProjectOptions,+ stateFile :: StateFileConfig,+ cabal :: CabalConfig,+ handlers :: Maybe SpecialBuildHandlers+ }+ deriving stock (Show, Generic)++data BumpOptions =+ BumpOptions {+ common :: ManagedOptions+ }+ deriving stock (Show, Generic)++data LowerOptions =+ LowerOptions {+ common :: ManagedOptions,+ initOnly :: Bool,+ reset :: Bool,+ stabilize :: Bool+ }+ deriving stock (Show)++data LowerCommand =+ LowerInitCmd LowerOptions+ |+ LowerOptimizeCmd LowerOptions+ |+ LowerStabilizeCmd LowerOptions+ |+ LowerAutoCmd LowerOptions+ deriving stock (Show)++data Command =+ Preproc PreprocOptions+ |+ EnvRunner EnvRunnerCommandOptions+ |+ GhcidCmd GhcidOptions+ |+ GhciCmd GhciOptions+ |+ NewCmd NewOptions+ |+ BootstrapCmd BootstrapOptions+ |+ BumpCmd BumpOptions+ |+ LowerCmd LowerCommand+ deriving stock (Show)++data Options =+ Options {+ global :: GlobalOptions,+ cmd :: Command+ }+ deriving stock (Show)
+ lib/Hix/Data/OutputFormat.hs view
@@ -0,0 +1,11 @@+module Hix.Data.OutputFormat where++data OutputFormat =+ OutputNone+ |+ OutputJson+ |+ OutputCommitMsg+ |+ OutputGaPr+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Data/OutputTarget.hs view
@@ -0,0 +1,11 @@+module Hix.Data.OutputTarget where++import Path (Abs, File, Path)++data OutputTarget =+ OutputDefault+ |+ OutputStdout+ |+ OutputFile (Path Abs File)+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Data/Overrides.hs view
@@ -0,0 +1,43 @@+module Hix.Data.Overrides where++import Data.Aeson (FromJSON (parseJSON), withObject, (.:))+import Distribution.Pretty (Pretty (pretty))+import Distribution.Types.Version (Version)+import GHC.Exts (IsList)+import Text.PrettyPrint (brackets, (<+>))++import Hix.Class.EncodeNix (EncodeNix)+import Hix.Class.Map (LookupMaybe, NMap, nPretty)+import Hix.Data.Json (JsonParsec (JsonParsec))+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (SourceHash)++data Override =+ Override {+ version :: Version,+ hash :: SourceHash+ }+ deriving stock (Eq, Show, Generic)+ deriving anyclass (EncodeNix)++instance FromJSON Override where+ parseJSON =+ withObject "Override" \ o -> do+ JsonParsec version <- o .: "version"+ hash <- o .: "hash"+ pure Override {..}++instance Pretty Override where+ pretty Override {..} = pretty version <+> brackets (pretty hash)++-- | Overrides can be either for mutable (direct, nonlocal) deps, or for transitive deps, so they must use+-- 'PackageName'.+newtype Overrides =+ Overrides (Map PackageName Override)+ deriving stock (Eq, Show, Generic)+ deriving newtype (FromJSON, Semigroup, Monoid, IsList, EncodeNix)++instance NMap Overrides PackageName Override LookupMaybe where++instance Pretty Overrides where+ pretty = nPretty
+ lib/Hix/Data/PackageId.hs view
@@ -0,0 +1,32 @@+module Hix.Data.PackageId where++import Distribution.Package (PackageIdentifier (PackageIdentifier))+import Distribution.Pretty (Pretty (pretty))+import Distribution.Version (Version)+import Exon (exon)++import qualified Hix.Data.PackageName as PackageName+import Hix.Data.PackageName (PackageName (..))+import Hix.Pretty (prettyText, showP)++data PackageId =+ PackageId {+ name :: PackageName,+ version :: Version+ }+ deriving stock (Eq, Show, Generic)++renderPackage :: PackageId -> Text+renderPackage PackageId {..} =+ [exon|##{name}-#{showP version}|]++instance Pretty PackageId where+ pretty = prettyText . renderPackage++toCabal :: PackageId -> PackageIdentifier+toCabal PackageId {..} =+ PackageIdentifier (PackageName.toCabal name) version++fromCabal :: PackageIdentifier -> PackageId+fromCabal (PackageIdentifier (PackageName.fromCabal -> name) version) =+ PackageId {..}
+ lib/Hix/Data/PackageName.hs view
@@ -0,0 +1,55 @@+module Hix.Data.PackageName where++import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey)+import qualified Data.Set as Set+import qualified Distribution.Package as Cabal+import Distribution.Package (depPkgName, mkPackageName)+import Distribution.Pretty (Pretty (pretty))+import Distribution.Types.Dependency (Dependency)++import Hix.Class.EncodeNix (EncodeNixKey)+import Hix.Pretty (prettyText)++newtype PackageName =+ PackageName Text+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsString, Ord, FromJSON, FromJSONKey, ToJSON, ToJSONKey, EncodeNixKey)++instance Pretty PackageName where+ pretty (PackageName n) = prettyText n++fromCabal :: Cabal.PackageName -> PackageName+fromCabal =+ fromString . Cabal.unPackageName++toCabal :: PackageName -> Cabal.PackageName+toCabal (PackageName name) =+ mkPackageName (toString name)++depPackageName :: Dependency -> PackageName+depPackageName =+ fromCabal . depPkgName++newtype LocalPackage =+ LocalPackage PackageName+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsString, Ord, FromJSON, FromJSONKey, Pretty, EncodeNixKey)++localPackageName :: LocalPackage -> PackageName+localPackageName = coerce++localPackageNames :: [LocalPackage] -> [PackageName]+localPackageNames = coerce++sameLocalPackage :: LocalPackage -> PackageName -> Bool+sameLocalPackage (LocalPackage lp) p = lp == p++isLocalPackage :: Set LocalPackage -> PackageName -> Bool+isLocalPackage lps p = Set.member (LocalPackage p) lps++toLocalPackage :: Set LocalPackage -> PackageName -> Maybe LocalPackage+toLocalPackage lps p+ | isLocalPackage lps p+ = Just (LocalPackage p)+ | otherwise+ = Nothing
lib/Hix/Data/ProjectFile.hs view
@@ -6,9 +6,9 @@ import Path (File, Path, Rel, parent, toFilePath, (</>)) import Path.IO (createDirIfMissing) -import Hix.Data.Error (tryIO)-import qualified Hix.Monad-import Hix.Monad (Env (Env), M)+import qualified Hix.Data.Monad (AppResources (cwd))+import Hix.Data.Monad (AppResources (AppResources), M (M))+import Hix.Error (tryIO) data ProjectFile = ProjectFile {@@ -19,9 +19,9 @@ createFile :: ProjectFile -> M () createFile f = do- Env {cwd} <- ask+ AppResources {cwd} <- M ask let file = cwd </> f.path- lift $ tryIO do+ M $ lift $ tryIO do createDirIfMissing True (parent file) Text.writeFile (toFilePath file) f.content
+ lib/Hix/Data/Version.hs view
@@ -0,0 +1,64 @@+module Hix.Data.Version (+ module Hix.Data.Version,+ Version,+ VersionRange,+) where++import Data.Aeson (FromJSON (parseJSON))+import Data.Generics.Labels ()+import qualified Data.List.NonEmpty as NonEmpty+import Distribution.Pretty (Pretty (pretty))+import Distribution.Version (Version, VersionRange, anyVersion)+import Exon (exon)+import GHC.Exts (IsList)+import Text.PrettyPrint (Doc)++import Hix.Class.EncodeNix (EncodeNix)+import Hix.Class.Map (LookupMaybe, NMap, nGenWith, nPretty)+import Hix.Data.Json (jsonParsec)+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.PackageName (PackageName)+import Hix.Orphans.Version ()+import Hix.Pretty (prettyText)++range0 :: VersionRange+range0 = anyVersion++newtype SourceHash =+ SourceHash Text+ deriving stock (Eq, Show, Generic)+ deriving newtype (Ord, FromJSON, EncodeNix)++instance Pretty SourceHash where+ pretty (SourceHash h) = prettyText h++data Major =+ Major {+ prefix :: Version,+ versions :: NonEmpty Version+ }+ deriving stock (Eq, Show, Generic)++prettyMajors :: NonEmpty Major -> Doc+prettyMajors = \case+ [Major {prefix}] -> pretty prefix <> ".*"+ majors -> [exon|#{pretty (NonEmpty.head majors).prefix}–#{pretty (NonEmpty.last majors).prefix}|]++newtype Versions =+ Versions (Map PackageName Version)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList, EncodeNix)++instance NMap Versions PackageName Version LookupMaybe where++instance Pretty Versions where+ pretty = nPretty++instance FromJSON Versions where+ parseJSON v =+ Versions . fmap jsonParsec <$> parseJSON v++packageIdVersions :: [PackageId] -> Versions+packageIdVersions =+ nGenWith \ PackageId {name, version} -> (name, version)
+ lib/Hix/Data/VersionBounds.hs view
@@ -0,0 +1,152 @@+module Hix.Data.VersionBounds where++import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON), Value (Object, String), object, (.:?), (.=))+import Data.Aeson.Types (typeMismatch)+import Distribution.Pretty (Pretty (pretty))+import Distribution.Version (+ Version,+ VersionRange,+ earlierVersion,+ intersectVersionRanges,+ orLaterVersion,+ simplifyVersionRange,+ thisVersion,+ )++import Hix.Class.EncodeNix (EncodeNix)+import Hix.Data.Json (aesonParsec, jsonParsec)+import Hix.Data.Version (range0)+import Hix.Pretty (showP)+import Hix.Version (lowerVersion, upperVersion)++data Bound =+ BoundLower+ |+ BoundUpper+ deriving stock (Eq, Show, Generic)++instance Pretty Bound where+ pretty = \case+ BoundLower -> "lower"+ BoundUpper -> "upper"++data VersionBounds =+ VersionBounds {+ lower :: Maybe Version,+ upper :: Maybe Version+ }+ deriving stock (Eq, Show, Generic)+ deriving anyclass (EncodeNix)++instance Semigroup VersionBounds where+ left <> right = VersionBounds {lower = left.lower <|> right.lower, upper = left.upper <|> right.upper}++instance Monoid VersionBounds where+ mempty = VersionBounds {lower = Nothing, upper = Nothing}++unsafeVersionBoundsFromRange :: VersionRange -> VersionBounds+unsafeVersionBoundsFromRange range =+ VersionBounds {lower = lowerVersion range, upper = upperVersion range}++instance FromJSON VersionBounds where+ parseJSON = \case+ String s -> do+ range <- aesonParsec (toString s)+ pure (unsafeVersionBoundsFromRange range)+ Object o -> do+ lower <- fmap jsonParsec <$> o .:? "lower"+ upper <- fmap jsonParsec <$> o .:? "upper"+ pure VersionBounds {..}+ v -> do+ let+ expected =+ "a managed bound as either a string containing a Cabal-style range or an object with 'lower' and/or 'upper'"+ <>+ " as keys and simple versions as values"+ typeMismatch expected v++instance ToJSON VersionBounds where+ toJSON VersionBounds {..} =+ object [+ "lower" .= toJSON (showP @Text <$> lower),+ "upper" .= toJSON (showP @Text <$> upper)+ ]++maybeRange ::+ (Bound -> Version -> VersionRange) ->+ VersionBounds ->+ Maybe VersionRange+maybeRange mkRange bounds+ | Just l <- bounds.lower+ , Just u <- bounds.upper+ , u <= l+ = Just (thisVersion l)++ | Just l <- lower+ , Just u <- upper+ = Just (simplifyVersionRange (intersectVersionRanges l u))++ | Just l <- lower+ , Nothing <- upper+ = Just l++ | Nothing <- lower+ , Just u <- upper+ = Just u++ | Nothing <- lower+ , Nothing <- upper+ = Nothing+ where+ lower = mkRange BoundLower <$> bounds.lower+ upper = mkRange BoundUpper <$> bounds.upper++-- | Return a @==lower@ range for invalid bounds.+-- The constructors prevent this from happening, so it's maybe for tests?+-- Probably better to make the type abstract and crash.+maybeMajorRange ::+ VersionBounds ->+ Maybe VersionRange+maybeMajorRange =+ maybeRange \case+ BoundLower -> orLaterVersion+ BoundUpper -> earlierVersion++majorRange :: VersionBounds -> VersionRange+majorRange = fromMaybe range0 . maybeMajorRange++instance Pretty VersionBounds where+ pretty = pretty . majorRange++anyBounds :: VersionBounds+anyBounds =+ VersionBounds {lower = Nothing, upper = Nothing}++versionBounds :: Version -> Version -> VersionBounds+versionBounds lower upper =+ VersionBounds {lower = Just lower, upper = Just upper}++fromLower :: Version -> VersionBounds+fromLower lower =+ VersionBounds {lower = Just lower, upper = Nothing}++fromUpper :: Version -> VersionBounds+fromUpper upper =+ VersionBounds {lower = Nothing, upper = Just upper}++exactVersion :: Version -> VersionBounds+exactVersion version = versionBounds version version++withLower :: Version -> VersionBounds -> VersionBounds+withLower lower VersionBounds {upper} =+ VersionBounds {lower = Just lower, upper = clamp =<< upper}+ where+ clamp old | old < lower = Nothing+ | otherwise = Just old++withUpper :: Version -> VersionBounds -> VersionBounds+withUpper upper VersionBounds {lower} =+ VersionBounds {lower = clamp =<< lower, upper = Just upper}+ where+ clamp old | old > upper = Nothing+ | otherwise = Just old
lib/Hix/Env.hs view
@@ -5,18 +5,14 @@ import Hix.Component (targetComponent) import qualified Hix.Data.ComponentConfig-import Hix.Data.ComponentConfig (- EnvRunner (EnvRunner),- PackageName,- PackagesConfig,- TargetOrDefault (DefaultTarget, ExplicitTarget),- )-import Hix.Data.Error (pathText)+import Hix.Data.ComponentConfig (EnvRunner (EnvRunner), PackagesConfig, TargetOrDefault (DefaultTarget, ExplicitTarget))+import Hix.Error (Error (EnvError), pathText) import qualified Hix.Data.GhciConfig-import Hix.Json (jsonConfig)-import Hix.Monad (M)-import qualified Hix.Options as Options-import Hix.Options (EnvRunnerOptions, TargetSpec)+import qualified Hix.Data.Options as Options+import Hix.Data.Options (EnvRunnerOptions, TargetSpec)+import Hix.Data.PackageName (PackageName)+import Hix.Json (jsonConfigE)+import Hix.Data.Monad (M) -- TODO when there is a solution for default command env fallback configuration, the DefaultTarget case must return -- Nothing when the config requests it@@ -34,7 +30,7 @@ envRunner :: EnvRunnerOptions -> M EnvRunner envRunner opts = do- config <- either pure jsonConfig opts.config+ config <- jsonConfigE EnvError opts.config let runner = componentRunner opts.root config.mainPackage config.packages fromMaybe config.defaultEnv . join <$> traverse runner opts.component
+ lib/Hix/Error.hs view
@@ -0,0 +1,115 @@+module Hix.Error (+ module Hix.Data.Error,+ module Hix.Error,+) where++import Control.Monad.Trans.Except (ExceptT, throwE)+import Exon (exon)+import Path (Path, toFilePath)+import System.IO.Error (tryIOError)++import qualified Hix.Console as Console+import Hix.Console (errorMessage)+import Hix.Data.Error (Error (..))++pathText :: Path b t -> Text+pathText =+ toText . toFilePath++prefixedError ::+ MonadIO m =>+ Text ->+ Text ->+ m ()+prefixedError desc msg =+ Console.err (errorMessage [exon|#{desc}: #{msg}|])++printPreprocError ::+ MonadIO m =>+ Text ->+ m ()+printPreprocError =+ prefixedError "Preprocessor generator failed"++printEnvError ::+ MonadIO m =>+ Text ->+ m ()+printEnvError =+ prefixedError "Invalid env config"++printGhciError ::+ MonadIO m =>+ Text ->+ m ()+printGhciError =+ prefixedError "Invalid ghci config"++printNewError ::+ MonadIO m =>+ Text ->+ m ()+printNewError =+ prefixedError "Can't create new project"++printBootstrapError ::+ MonadIO m =>+ Text ->+ m ()+printBootstrapError =+ prefixedError "Can't bootstrap project"++printFatalError ::+ MonadIO m =>+ Text ->+ m ()+printFatalError =+ prefixedError "Fatal error"++sourceError :: Text -> Path b t -> Text+sourceError reason source =+ [exon|#{reason} the source file '#{pathText source}'|]++catchIO ::+ (Text -> ExceptT Error IO a) ->+ IO a ->+ ExceptT Error IO a+catchIO handleError ma =+ liftIO (tryIOError ma) >>= \case+ Right a -> pure a+ Left err -> handleError (show err)++tryIOWith ::+ (Text -> Error) ->+ IO a ->+ ExceptT Error IO a+tryIOWith mkErr ma =+ liftIO (tryIOError ma) >>= \case+ Right a -> pure a+ Left err -> throwE (mkErr (show err))++tryIO ::+ IO a ->+ ExceptT Error IO a+tryIO =+ tryIOWith Fatal++note :: Text -> Maybe a -> ExceptT Error IO a+note err =+ maybe (throwE (GhciError err)) pure++printError ::+ MonadIO m =>+ Bool ->+ Error ->+ m ()+printError verbose = \case+ PreprocError err -> printPreprocError err+ EnvError err -> printEnvError err+ GhciError err -> printGhciError err+ NewError err -> printNewError err+ BootstrapError err -> printBootstrapError err+ NoMatch msg | verbose -> printPreprocError msg+ NoMatch _ -> unit+ Fatal err -> printFatalError err+ Client err -> Console.err (errorMessage err)
lib/Hix/Ghci.hs view
@@ -1,6 +1,5 @@ module Hix.Ghci where -import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Except (ExceptT, catchE) import Data.List.Extra (nubOrd) import qualified Data.Map.Strict as Map@@ -19,19 +18,16 @@ ComponentConfig, ModuleName (ModuleName), PackageConfig,- PackageName, SourceDir (SourceDir), Target (Target), )-import Hix.Data.Error (Error, note, pathText, tryIO) import qualified Hix.Data.GhciConfig import Hix.Data.GhciConfig (GhciConfig, GhciRunExpr (GhciRunExpr), GhciSetupCode (GhciSetupCode)) import qualified Hix.Data.GhciTest as GhciTest import Hix.Data.GhciTest (GhciRun (GhciRun), GhciTest (GhciTest), GhcidRun (GhcidRun))-import Hix.Json (jsonConfig)-import Hix.Monad (M, noteGhci)-import qualified Hix.Options as Options-import Hix.Options (+import Hix.Data.Monad (liftE)+import qualified Hix.Data.Options as Options+import Hix.Data.Options ( ExtraGhciOptions (ExtraGhciOptions), ExtraGhcidOptions (ExtraGhcidOptions), GhciOptions (GhciOptions),@@ -39,6 +35,10 @@ TargetSpec (TargetForFile), TestOptions (TestOptions), )+import Hix.Data.PackageName (PackageName)+import Hix.Error (Error (GhciError), note, pathText, tryIO)+import Hix.Json (jsonConfigE)+import Hix.Monad (M, noteGhci) import Hix.Path (rootDir) relativeToComponent ::@@ -108,7 +108,7 @@ assemble :: GhciOptions -> M GhciTest assemble opt = do- config <- either pure jsonConfig opt.config+ config <- jsonConfigE GhciError opt.config root <- rootDir opt.root Target {..} <- targetComponentOrError opt.root config.mainPackage config.packages opt.component script <- ghciScript config package sourceDir opt@@ -175,8 +175,8 @@ M GhciRun ghciCmdlineFromOptions tmp opt = do conf <- assemble opt- shellScriptFile <- lift (ghciScriptFile tmp conf.script)- runScriptFile <- lift (traverse (ghciScriptFile tmp) conf.test)+ shellScriptFile <- liftE (ghciScriptFile tmp conf.script)+ runScriptFile <- liftE (traverse (ghciScriptFile tmp) conf.test) pure (ghciCmdline conf opt.extra shellScriptFile runScriptFile) ghcidCmdlineFromOptions ::@@ -195,7 +195,7 @@ GhciOptions -> M () printGhciCmdline opt = do- tmp <- lift hixTempDir+ tmp <- liftE hixTempDir cmd <- ghciCmdlineFromOptions tmp opt liftIO (Text.putStrLn [exon|ghci #{cmd.shell} #{fold cmd.run}|]) @@ -203,6 +203,6 @@ GhcidOptions -> M () printGhcidCmdline opt = do- tmp <- lift hixTempDir+ tmp <- liftE hixTempDir cmd <- ghcidCmdlineFromOptions tmp opt liftIO (Text.putStrLn cmd.cmdline)
+ lib/Hix/Hackage.hs view
@@ -0,0 +1,120 @@+module Hix.Hackage where++import Control.Monad.Extra (fromMaybeM)+import Data.Aeson (FromJSON (parseJSON), eitherDecodeStrict', withObject, (.:))+import Data.IORef (IORef, modifyIORef', readIORef)+import qualified Data.Map.Strict as Map+import Data.Map.Strict ((!?))+import qualified Data.Text as Text+import Distribution.Parsec (eitherParsec)+import Hix.Data.Version (Version)+import Exon (exon)+import Network.HTTP.Client (Manager, Request (..), Response (..), defaultRequest, httpLbs)+import Network.HTTP.Types (+ Status (statusCode, statusMessage),+ hAccept,+ statusIsClientError,+ statusIsServerError,+ statusIsSuccessful,+ )+import System.Exit (ExitCode (ExitFailure, ExitSuccess))+import System.Process.Typed (proc, readProcess)++import Hix.Data.Error (Error (Fatal))+import Hix.Data.PackageId (PackageId, renderPackage)+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (SourceHash (SourceHash))+import qualified Hix.Log as Log+import Hix.Monad (M, throwM, tryIOM)+import Hix.Pretty (showP)++data HackageVersions =+ HackageVersions {+ versions :: [String]+ }+ deriving stock (Eq, Show, Generic)++instance FromJSON HackageVersions where+ parseJSON = withObject "HackageVersions" \ o -> HackageVersions <$> o .: "normal-version"++parseVersion :: String -> Either (String, String) Version+parseVersion s = first (s,) (eitherParsec s)++parseResult :: LByteString -> M (Either Text [Version])+parseResult body =+ case eitherDecodeStrict' (toStrict body) of+ Left err ->+ noVersion [exon|Hackage response parse error: #{toText err}|]+ Right (HackageVersions []) ->+ noVersion "No versions on Hackage"+ Right (HackageVersions versions) ->+ case traverse parseVersion versions of+ Left (v, err) -> noVersion (toText [exon|Version '#{v}' has invalid format (#{err})|])+ Right vs -> pure (Right vs)+ where+ noVersion = pure . Left++versionsHackage :: Manager -> PackageName -> M [Version]+versionsHackage manager pkg = do+ res <- liftIO (httpLbs request manager)+ let+ body = responseBody res++ status = responseStatus res++ errorStatus category = noVersion [exon|#{category} (#{decodeUtf8 (statusMessage status)})|]++ if+ | statusIsSuccessful status -> leftA noVersion =<< parseResult body+ | statusCode status == 404 -> noVersion "PackageId does not exist"+ | statusIsClientError status -> errorStatus "Client error"+ | statusIsServerError status -> errorStatus "Server error"+ | otherwise -> errorStatus "Weird error"++ where+ request =+ defaultRequest {+ host = "hackage.haskell.org",+ secure = False,+ method = "GET",+ path = [exon|/package/##{pkg}/preferred|],+ requestHeaders = [(hAccept, "application/json")]+ }++ noVersion msg =+ [] <$ Log.error [exon|Hackage request for '##{pkg}' failed: #{msg}|]++latestVersionHackage :: Manager -> PackageName -> M (Maybe Version)+latestVersionHackage manager pkg =+ head <$> versionsHackage manager pkg++fetchHashHackage ::+ PackageId ->+ M SourceHash+fetchHashHackage package = do+ Log.debug [exon|Fetching hash for '##{slug}' from ##{url}|]+ tryIOM (readProcess conf) >>= \case+ (ExitFailure _, _, err) ->+ throwM (Fatal [exon|Prefetching source of '##{slug}' from hackage failed: #{decodeUtf8 err}|])+ (ExitSuccess, hash, _) ->+ pure (SourceHash (Text.stripEnd (decodeUtf8 hash)))+ where+ conf = proc "nix-prefetch-url" ["--unpack", url]+ url = [exon|https://hackage.haskell.org/package/#{slug}/#{slug}.tar.gz|]+ slug = showP package++fetchHashHackageCached ::+ IORef (Map Text SourceHash) ->+ PackageId ->+ M SourceHash+fetchHashHackageCached cacheRef package =+ liftIO (readIORef cacheRef) >>= \ cache ->+ fromMaybeM fetch (pure (cache !? cacheKey))+ where+ fetch = do+ hash <- fetchHashHackage package+ hash <$ addToCache hash++ addToCache hash = liftIO (modifyIORef' cacheRef (Map.insert cacheKey hash))++ cacheKey = renderPackage package
lib/Hix/Json.hs view
@@ -1,20 +1,20 @@ module Hix.Json where -import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.Except (throwE) import qualified Data.Aeson as Aeson import Data.Aeson (FromJSON, fromJSON) import Exon (exon) -import Hix.Data.Error (Error (GhciError))-import Hix.Monad (M)+import Hix.Data.Error (Error)+import Hix.Data.Monad (M)+import Hix.Monad (throwM) import Hix.Optparse (JsonConfig (JsonConfig)) jsonConfig :: FromJSON a =>+ (Text -> Error) -> JsonConfig -> M a-jsonConfig (JsonConfig mv) =+jsonConfig consError (JsonConfig mv) = liftIO mv >>= \case Left msg -> failure [exon|Invalid JSON: #{toText msg}|] Right v -> case fromJSON v of@@ -22,4 +22,12 @@ Aeson.Error err -> failure [exon|Invalid JSON: #{toText err} #{show v}|] where- failure = lift . throwE . GhciError+ failure = throwM . consError++jsonConfigE ::+ FromJSON a =>+ (Text -> Error) ->+ Either a JsonConfig ->+ M a+jsonConfigE consError =+ either pure (jsonConfig consError)
+ lib/Hix/Log.hs view
@@ -0,0 +1,61 @@+module Hix.Log where++import Control.Monad.Trans.Reader (ask)+import Exon (exon)+import Text.PrettyPrint (Doc)++import Hix.Console (color, withChevrons)+import qualified Hix.Data.Monad+import Hix.Data.Monad (LogLevel (..), M (M))++log :: LogLevel -> Text -> M ()+log level msg = do+ env <- M ask+ env.logger level msg++verbose :: Text -> M ()+verbose msg =+ log LogVerbose (withChevrons 4 msg)++debug :: Text -> M ()+debug msg =+ log LogDebug [exon|[#{color 6 "debug"}] #{msg}|]++debugP :: Doc -> M ()+debugP = debug . show++info :: Text -> M ()+info msg =+ log LogInfo (withChevrons 5 msg)++infoPlain :: Text -> M ()+infoPlain msg =+ log LogInfo msg++warn :: Text -> M ()+warn msg =+ log LogWarn (withChevrons 3 msg)++infoCont :: Text -> M ()+infoCont msg =+ log LogInfo [exon| #{msg}|]++error :: Text -> M ()+error msg =+ log LogError (withChevrons 1 [exon|Error: #{msg}|])++logWith :: (LogLevel -> Text -> IO ()) -> LogLevel -> Text -> M ()+logWith handler level msg = do+ env <- M ask+ let+ minVerbose = env.verbose || env.debug+ minInfo = minVerbose || not env.quiet+ case level of+ LogDebug | env.debug -> accept+ LogVerbose | minVerbose -> accept+ LogInfo | minInfo -> accept+ LogWarn | minInfo -> accept+ LogError -> accept+ _ -> unit+ where+ accept = liftIO (handler level msg)
+ lib/Hix/Managed/Build.hs view
@@ -0,0 +1,216 @@+module Hix.Managed.Build where++import Control.Monad (foldM)+import qualified Data.Map.Strict as Map+import Distribution.Pretty (Pretty)+import Exon (exon)+import Text.PrettyPrint (vcat)++import Hix.Data.EnvName (EnvName)+import Hix.Data.Monad (M)+import Hix.Data.Overrides (Overrides)+import Hix.Data.PackageId (PackageId)+import Hix.Data.Version (Version, Versions)+import Hix.Data.VersionBounds (VersionBounds)+import qualified Hix.Log as Log+import Hix.Managed.Build.Solve (solveMutation)+import qualified Hix.Managed.Cabal.Changes+import Hix.Managed.Cabal.Config (isNonReinstallableDep, isReinstallableId)+import Hix.Managed.Cabal.Data.SolverState (SolverState)+import qualified Hix.Managed.Data.BuildConfig+import Hix.Managed.Data.BuildConfig (BuildConfig)+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext)+import Hix.Managed.Data.Mutable (MutableDep, addBuildVersions)+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (BuildMutation (BuildMutation), DepMutation, MutationResult (..))+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState (MutationState), updateBoundsWith)+import Hix.Managed.Data.Query (Query (Query))+import qualified Hix.Managed.Data.QueryDep+import Hix.Managed.Data.QueryDep (QueryDep)+import qualified Hix.Managed.Data.StageContext+import Hix.Managed.Data.StageContext (StageContext (StageContext))+import qualified Hix.Managed.Data.StageState+import Hix.Managed.Data.StageState (+ BuildStatus (Failure, Success),+ StageState,+ failed,+ initStageState,+ iterations,+ justSuccess,+ )+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (EnvBuilder)+import qualified Hix.Managed.Handlers.Mutation+import Hix.Managed.Handlers.Mutation (MutationHandlers)+import Hix.Managed.StageState (updateStageState)+import Hix.Pretty (prettyL, showP, showPL)++logBuildInputs ::+ EnvName ->+ Text ->+ [PackageId] ->+ M ()+logBuildInputs env description overrides = do+ Log.info [exon|Building targets in '##{env}' with #{description}...|]+ Log.debugP (vcat ["Overrides:", prettyL overrides])++logBuildResult :: Text -> BuildStatus -> M ()+logBuildResult description status =+ Log.info [exon|Build with ##{description} #{result status}|]+ where+ result = \case+ Success -> "succeeded"+ Failure -> "failed"++updateMutationState ::+ (Version -> VersionBounds -> VersionBounds) ->+ Versions ->+ Overrides ->+ MutationState ->+ MutationState+updateMutationState updateBound newVersions overrides MutationState {bounds, versions, initial} =+ updateBoundsWith updateBound MutationState {+ bounds,+ versions = addBuildVersions newVersions versions,+ overrides,+ initial+ }++-- | /Note/: This quietly discards non-reinstallable packages.+--+-- TODO Discard installed versions, for builds with initial versions.+buildVersions ::+ EnvBuilder ->+ EnvContext ->+ Text ->+ Versions ->+ [PackageId] ->+ M (Overrides, BuildStatus)+buildVersions builder context description versions overrideVersions = do+ logBuildInputs context.env description reinstallable+ (overrides, status) <- builder.buildWithState versions reinstallable+ logBuildResult description status+ pure (overrides, status)+ where+ reinstallable = filter isReinstallableId overrideVersions++buildConstraints ::+ EnvBuilder ->+ EnvContext ->+ Text ->+ SolverState ->+ M (Maybe (Versions, Overrides, BuildStatus))+buildConstraints builder context description state =+ solveMutation builder.cabal context.deps state >>= traverse \ changes -> do+ (overrides, status) <- buildVersions builder context description changes.versions changes.overrides+ pure (changes.versions, overrides, status)++buildMutation ::+ EnvBuilder ->+ EnvContext ->+ MutationState ->+ BuildMutation ->+ M (Maybe MutationState)+buildMutation builder context state BuildMutation {description, solverState, updateBound} =+ result <$> buildConstraints builder context description solverState+ where+ result = \case+ Just (versions, overrides, status) ->+ justSuccess (updateMutationState updateBound versions overrides state) status+ Nothing -> Nothing++logMutationResult ::+ MutableDep ->+ MutationResult s ->+ M ()+logMutationResult package = \case+ MutationSuccess candidate True _ _ ->+ Log.verbose [exon|Build succeeded for #{showP candidate}|]+ MutationSuccess _ False _ _ ->+ Log.verbose [exon|Build is up to date for '##{package}'|]+ MutationKeep ->+ Log.verbose [exon|No better version found for '##{package}'|]+ MutationFailed ->+ Log.verbose [exon|Could not find a buildable version of '##{package}'|]++validateMutation ::+ EnvBuilder ->+ EnvContext ->+ MutationHandlers a s ->+ StageState a s ->+ DepMutation a ->+ M (StageState a s)+validateMutation envBuilder context handlers stageState mutation = do+ result <- processReinstallable+ logMutationResult mutation.package result+ pure (updateStageState stageState mutation result)+ where+ processReinstallable+ | isNonReinstallableDep mutation.package+ = pure MutationKeep+ | otherwise+ = handlers.process stageState.ext mutation build+ build = buildMutation envBuilder context stageState.state++convergeMutations ::+ Pretty a =>+ MutationHandlers a s ->+ BuildConfig ->+ EnvBuilder ->+ EnvContext ->+ StageState a s ->+ [DepMutation a] ->+ M (StageState a s)+convergeMutations handlers conf builder context state0 =+ spin state0 {iterations = 0}+ where+ spin state mutations++ | [] <- mutations+ = pure state++ | state.iterations >= conf.maxIterations+ = pure state++ | otherwise+ = do+ Log.debug [exon|Iteration #{show (state.iterations + 1)} for '##{context.env :: EnvName}'|]+ newState <- build state mutations+ if Map.size newState.success == Map.size state.success+ then pure newState+ -- reversing so the build order is consistent+ else spin newState (reverse newState.failed)++ build statePre mutations = do+ let state = statePre {failed = [], iterations = statePre.iterations + 1}+ Log.debug [exon|Building targets with mutations: #{showPL mutations}|]+ foldM (validateMutation builder context handlers) state mutations++reinstallableCandidates ::+ (QueryDep -> M (Maybe (DepMutation a))) ->+ Query ->+ M [DepMutation a]+reinstallableCandidates candidates (Query query) =+ catMaybes <$> traverse reinstallableOnly (toList query)+ where+ reinstallableOnly dep+ | isNonReinstallableDep dep.package+ = pure Nothing+ | otherwise+ = candidates dep++processQuery ::+ Pretty a =>+ (QueryDep -> M (Maybe (DepMutation a))) ->+ MutationHandlers a s ->+ BuildConfig ->+ StageContext ->+ s ->+ M (StageState a s)+processQuery candidates handlers conf StageContext {env, builder, state, query = query} ext = do+ mutations <- reinstallableCandidates candidates query+ convergeMutations handlers conf builder env stageState mutations+ where+ stageState = initStageState state ext
+ lib/Hix/Managed/Build/Mutation.hs view
@@ -0,0 +1,77 @@+module Hix.Managed.Build.Mutation where++import Control.Lens ((.~))+import Exon (exon)++import Hix.Class.Map (nAdjust, nAmendWithKey)+import Hix.Data.Monad (M)+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.Version (Version)+import Hix.Data.VersionBounds (VersionBounds, exactVersion)+import qualified Hix.Log as Log+import Hix.Managed.Cabal.Data.SolverState (SolverState, updateSolverState)+import Hix.Managed.Data.Constraints (EnvConstraints, MutationConstraints)+import Hix.Managed.Data.Mutable (MutableDep, depName, mutRelax)+import qualified Hix.Managed.Data.MutableId+import Hix.Managed.Data.MutableId (MutableId (MutableId))+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (BuildMutation (BuildMutation))+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState)+import Hix.Managed.Data.Packages (Deps)+import Hix.Pretty (showP)++candidateMutation ::+ SolverState ->+ MutableId ->+ (Version -> VersionBounds -> VersionBounds) ->+ BuildMutation+candidateMutation solverState candidate updateBound =+ BuildMutation {+ description = showP candidate,+ solverState,+ updateBound+ }++candidateConstraints :: MutableId -> EnvConstraints -> EnvConstraints+candidateConstraints MutableId {..} constraints =+ nAdjust (depName name) constraints (#mutation .~ exactVersion version)++updateConstraints ::+ (MutableId -> PackageId -> MutationConstraints -> MutationConstraints) ->+ MutableId ->+ MutationState ->+ EnvConstraints ->+ EnvConstraints+updateConstraints impl candidate state =+ nAmendWithKey update (mutRelax state.versions :: Deps (Maybe Version))+ where+ update name = \case+ Just version -> impl candidate PackageId {..}+ Nothing -> id++-- | Boilerplate for mutation handlers, could be better.+--+-- TODO If we'd use the @retract@ field from @DepMutation@ and the target bound here, we could probably use a universal+-- bounds updater without leaking implementation...investigate.+buildCandidate ::+ (BuildMutation -> M (Maybe MutationState)) ->+ (Version -> VersionBounds -> VersionBounds) ->+ (MutableId -> PackageId -> MutationConstraints -> MutationConstraints) ->+ SolverState ->+ MutableDep ->+ Version ->+ M (Maybe (MutableId, SolverState, MutationState))+buildCandidate build updateStateBound updateConstraintBound solverState package version = do+ Log.debug [exon|Mutation constraints for #{showP candidate}: #{showP mutationSolverState.constraints}|]+ fmap result <$> build (candidateMutation mutationSolverState candidate updateStateBound)+ where+ result newState = (candidate, newSolverState newState, newState)++ candidate = MutableId {name = package, version}++ mutationSolverState = updateSolverState (candidateConstraints candidate) solverState++ newSolverState newState =+ updateSolverState (updateConstraints updateConstraintBound candidate newState) solverState
+ lib/Hix/Managed/Build/Single.hs view
@@ -0,0 +1,25 @@+module Hix.Managed.Build.Single where++import Hix.Data.Monad (M)+import Hix.Data.VersionBounds (exactVersion)+import Hix.Managed.Build (buildConstraints)+import Hix.Managed.Cabal.Data.SolverState (solverState)+import Hix.Managed.Constraints (fromVersions)+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext)+import Hix.Managed.Data.Mutable (MutableVersions)+import Hix.Managed.Data.StageState (BuildStatus (Failure))+import Hix.Managed.Handlers.Build (EnvBuilder)++buildVersions ::+ EnvBuilder ->+ EnvContext ->+ Text ->+ MutableVersions ->+ M BuildStatus+buildVersions builder context description versions =+ buildConstraints builder context description solver <&> \case+ Just (_, _, status) -> status+ Nothing -> Failure+ where+ solver = solverState context.solverBounds context.deps (fromVersions exactVersion versions) def
+ lib/Hix/Managed/Build/Solve.hs view
@@ -0,0 +1,51 @@+module Hix.Managed.Build.Solve where++import qualified Data.Set as Set+import Distribution.Pretty (pretty)+import Exon (exon)+import Text.PrettyPrint (hang)++import Hix.Class.Map (nRestrictKeys)+import Hix.Data.Monad (M)+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.PackageName (isLocalPackage)+import Hix.Data.Version (packageIdVersions)+import qualified Hix.Log as Log+import qualified Hix.Managed.Cabal.Changes+import Hix.Managed.Cabal.Changes (SolverChanges (SolverChanges), SolverPlan (SolverPlan))+import Hix.Managed.Cabal.Data.SolverState (SolverState)+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvDeps)+import Hix.Managed.Data.Mutable (depName)+import qualified Hix.Managed.Handlers.Cabal+import Hix.Managed.Handlers.Cabal (CabalHandlers)+import Hix.Pretty (showPL)++logNonReinstallable :: NonEmpty PackageId -> M ()+logNonReinstallable ids =+ Log.verbose [exon|NOTE: Cabal solver suggested new versions for non-reinstallable packages: #{showPL ids}|]++-- TODO Do we need to filter locals out of @matching@ or can those not be in there?+processSolverPlan ::+ EnvDeps ->+ SolverPlan ->+ M SolverChanges+processSolverPlan deps SolverPlan {..} = do+ Log.debugP (hang "New project deps from solver:" 2 (pretty projectDeps))+ traverse_ logNonReinstallable nonReinstallable+ pure SolverChanges {versions, overrides, projectDeps}+ where+ projectDeps = nRestrictKeys mutablePIds versions+ versions = packageIdVersions (overrides ++ matching)+ overrides = filter notLocal changes+ notLocal PackageId {name} = not (isLocalPackage deps.local name)+ mutablePIds = Set.fromList (depName <$> Set.toList deps.mutable)++solveMutation ::+ CabalHandlers ->+ EnvDeps ->+ SolverState ->+ M (Maybe SolverChanges)+solveMutation cabal deps state =+ traverse (processSolverPlan deps) =<< cabal.solveForVersion state
+ lib/Hix/Managed/BuildOutput.hs view
@@ -0,0 +1,67 @@+module Hix.Managed.BuildOutput where++import qualified Data.Aeson as Aeson+import Data.List.Extra (nubSortOn)+import qualified Data.Text as Text+import Data.These.Combinators (justThere)++import Hix.Data.Monad (M)+import Hix.Data.OutputFormat (OutputFormat (..))+import Hix.Data.OutputTarget (OutputTarget (..))+import Hix.Data.PackageName (PackageName (PackageName))+import Hix.Managed.BuildOutput.CommitMsg (formatCommit)+import Hix.Managed.BuildOutput.GithubActionsPr (githubActionsPr)+import qualified Hix.Managed.Data.BuildOutput+import Hix.Managed.Data.BuildOutput (BuildOutput (BuildOutput), ModifiedId (ModifiedId))+import Hix.Managed.Data.Mutable (MutableDep, depName)+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.ProjectResult (ProjectResult)+import qualified Hix.Managed.EnvResult+import Hix.Managed.EnvResult (+ DepModification (DepAdded, DepUpdated),+ DepResult,+ DepResultDetail (DepModified),+ DepResults (DepResults),+ )+import qualified Hix.Managed.ProjectResult as ProjectResult+import qualified Hix.OutputWriter+import Hix.OutputWriter (outputWriterGlobal)++outputResult :: BuildOutput -> OutputTarget -> OutputFormat -> M ()+outputResult output target = \case+ OutputNone -> unit+ OutputJson -> writer.bytes (toStrict (Aeson.encode output))+ OutputCommitMsg -> traverse_ writer.text (formatCommit output)+ OutputGaPr -> githubActionsPr output target+ where+ writer = outputWriterGlobal target++buildOutputFromLists :: [ModifiedId] -> [MutableDep] -> [MutableDep] -> BuildOutput+buildOutputFromLists modified unmodified failed =+ BuildOutput {+ modified,+ unmodified,+ failed,+ modifiedNames = comma ((.package) <$> modified),+ unmodifiedNames = comma unmodified,+ failedNames = comma failed+ }+ where+ comma = fmap (Text.intercalate ", " . fmap (coerce . depName) . toList) . nonEmpty++modifiedId :: DepResult -> ModifiedId+modifiedId result =+ ModifiedId {package = result.package, version = result.version, range}+ where+ range = case result.detail of+ DepModified (DepUpdated (justThere -> Just _)) -> Just result.bounds+ DepModified (DepAdded _) -> Just result.bounds+ _ -> Nothing++buildOutput :: ProjectResult -> BuildOutput+buildOutput result =+ buildOutputFromLists modified ((.package) <$> unmodified) failed+ where+ modified = modifiedId <$> nubSortOn (.package) (added ++ updated)+ failed = (.package) <$> ProjectResult.failures result+ DepResults {..} = ProjectResult.grouped result
+ lib/Hix/Managed/BuildOutput/CommitMsg.hs view
@@ -0,0 +1,32 @@+module Hix.Managed.BuildOutput.CommitMsg where++import qualified Data.Text as Text+import Exon (exon)++import qualified Hix.Managed.Data.BuildOutput+import Hix.Managed.Data.BuildOutput (BuildOutput, ModifiedId)+import Hix.Pretty (showP)++commitMessage :: Int -> Text -> Text+commitMessage num names+ | num <= 3+ = [exon|Bump #{names}|]+ | otherwise+ = [exon|Bump #{show num} dependencies|]++candidateList :: [ModifiedId] -> [Text]+candidateList = fmap \ c -> [exon|* #{showP c}|]++commitBody :: [ModifiedId] -> [Text]+commitBody candidates =+ ["New versions:", ""] ++ candidateList candidates++commit :: BuildOutput -> Maybe (Text, [Text])+commit output =+ output.modifiedNames <&> \ names ->+ (commitMessage (length output.modified) names, commitBody output.modified)++formatCommit :: BuildOutput -> Maybe Text+formatCommit output =+ commit output <&> \ (msg, body) ->+ Text.intercalate "\n" ([msg, ""] ++ body)
+ lib/Hix/Managed/BuildOutput/GithubActionsPr.hs view
@@ -0,0 +1,58 @@+module Hix.Managed.BuildOutput.GithubActionsPr where++import qualified Data.Map.Strict as Map+import qualified Data.Text as Text+import Exon (exon)+import Path (parseAbsFile)+import System.Environment (getEnv)+import System.Posix (epochTime)++import Hix.Data.Error (Error (Client, Fatal))+import Hix.Data.Monad (M)+import Hix.Data.OutputTarget (OutputTarget)+import Hix.Managed.BuildOutput.CommitMsg (commit)+import Hix.Managed.Data.BuildOutput (BuildOutput)+import Hix.Monad (note, throwM, tryIOMAs)+import qualified Hix.OutputWriter+import Hix.OutputWriter (OutputWriter, fileWriter, outputWriterM)++envVarWriter :: M OutputWriter+envVarWriter = do+ var <- tryIOMAs envVarError (getEnv "GITHUB_OUTPUT")+ outFile <- note envVarError (parseAbsFile var)+ pure (fileWriter writeError outFile)+ where+ envVarError = Client "The variable $GITHUB_OUTPUT does not contain a file path"+ writeError err = throwM (Fatal [exon|Couldn't write to $GITHUB_OUTPUT: #{err.msg}|])++formatOutput :: Text -> [Text] -> [Text]+formatOutput key = \case+ [value] -> [[exon|#{key}=#{value}|]]+ value -> [exon|#{key}<<EOF|] : value ++ ["EOF"]++formatOutputs :: Map Text [Text] -> [Text]+formatOutputs =+ concatMap (uncurry formatOutput) . Map.toList++writeOutputs :: OutputWriter -> Map Text [Text] -> M ()+writeOutputs writer values =+ writer.textAppend (Text.unlines (formatOutputs values))++modifiedOutputs :: Text -> Text -> [Text] -> Map Text [Text]+modifiedOutputs date msg body =+ [+ ("branch", [[exon|hix-managed/bump-#{date}|]]),+ ("commit-message", [msg, ""] ++ body),+ ("title", [msg]),+ ("body", body),+ ("committer", ["hix <noreply@github.com>"]),+ ("signoff", ["false"]),+ ("delete-branch", ["true"])+ ]++githubActionsPr :: BuildOutput -> OutputTarget -> M ()+githubActionsPr output target =+ for_ (commit output) \ (msg, body) -> do+ date <- liftIO epochTime+ writer <- outputWriterM envVarWriter target+ writeOutputs writer (modifiedOutputs (show date) msg body)
+ lib/Hix/Managed/Bump/App.hs view
@@ -0,0 +1,17 @@+module Hix.Managed.Bump.App where++import Hix.Data.Error (Error (Client))+import Hix.Data.Monad (M)+import qualified Hix.Data.Options+import Hix.Data.Options (BumpOptions (BumpOptions))+import Hix.Json (jsonConfigE)+import Hix.Managed.Bump.Optimize (bumpOptimizeMain)+import qualified Hix.Managed.Data.ProjectContextProto+import Hix.Managed.Handlers.Build.Test (chooseHandlers)+import Hix.Managed.ProjectContext (withProjectContext)++bumpCli :: BumpOptions -> M ()+bumpCli BumpOptions {common = opts} = do+ context <- jsonConfigE Client opts.context+ handlers <- liftIO (chooseHandlers opts.stateFile context.envs context.buildOutputsPrefix opts.cabal opts.handlers)+ withProjectContext handlers opts.project context (bumpOptimizeMain handlers)
+ lib/Hix/Managed/Bump/Candidates.hs view
@@ -0,0 +1,47 @@+module Hix.Managed.Bump.Candidates where++import Distribution.Version (Version)++import Hix.Data.Monad (M)+import qualified Hix.Managed.Data.Bump+import Hix.Managed.Data.Bump (Bump (Bump))+import Hix.Managed.Data.Mutable (depName)+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (DepMutation (DepMutation))+import qualified Hix.Managed.Data.QueryDep+import Hix.Managed.Data.QueryDep (QueryDep (QueryDep))+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (BuildHandlers)+import Hix.Version (nextMajor)++-- | We only want to report a bump if the new version actually changes the build.+isBump :: Version -> Maybe Version -> Bool+isBump version = \case+ Just current -> version > current+ Nothing -> True++-- | Decide whether the latest version of a dependency requires changes to the currently specified bound.+--+-- If no latest version can be found, we return 'Nothing' to indicate that the dep should be skipped.+--+-- Otherwise, the range field of the 'DepMutation' is determined:+--+-- If the specified dependency has no upper bound (e.g. because the user has only entered the package name and ran the+-- app to resolve the bounds), or if the latest version is outside of the existing bounds, then we add a new bound to+-- the managed state, so we extend the version range by setting the upper bound to the major prefix of the next-highest+-- major of the latest version and return 'NewBounds'.+--+-- Otherwise, we return 'OldBounds'.+candidatesBump ::+ BuildHandlers ->+ QueryDep ->+ M (Maybe (DepMutation Bump))+candidatesBump handlers QueryDep {package, current} = do+ fmap mutation <$> handlers.latestVersion (depName package)+ where+ mutation version =+ DepMutation {+ package,+ retract = False,+ mutation = Bump {version, bound = nextMajor version, changed = isBump version current}+ }
+ lib/Hix/Managed/Bump/Optimize.hs view
@@ -0,0 +1,126 @@+module Hix.Managed.Bump.Optimize where++import Exon (exon)++import Hix.Class.Map (nMap)+import Hix.Data.Monad (M)+import qualified Hix.Data.Overrides+import Hix.Data.VersionBounds (fromLower)+import Hix.Managed.Build (processQuery)+import Hix.Managed.Bump.Candidates (candidatesBump)+import qualified Hix.Managed.Cabal.Data.SolverState+import Hix.Managed.Cabal.Data.SolverState (SolverFlags (SolverFlags), solverState)+import Hix.Managed.Constraints (fromVersions, preferInstalled, preferVersions)+import qualified Hix.Managed.Data.BuildConfig+import Hix.Managed.Data.BuildConfig (BuildConfig)+import Hix.Managed.Data.Bump (Bump (..))+import Hix.Managed.Data.Constraints (EnvConstraints)+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvDeps)+import Hix.Managed.Data.Initial (Initial (Initial))+import Hix.Managed.Data.Mutable (MutableDep)+import qualified Hix.Managed.Data.MutableId+import Hix.Managed.Data.MutableId (MutableId (MutableId))+import Hix.Managed.Data.Mutation (DepMutation (..))+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState)+import qualified Hix.Managed.Data.ProjectContext+import Hix.Managed.Data.ProjectContext (ProjectContext)+import Hix.Managed.Data.ProjectResult (ProjectResult)+import Hix.Managed.Data.Query (Query (Query))+import qualified Hix.Managed.Data.StageContext+import Hix.Managed.Data.StageContext (StageContext (StageContext))+import Hix.Managed.Data.StageResult (StageResult, StageSummary (StageNoAction, StageReport))+import Hix.Managed.Data.StageState (BuildStatus, BuildSuccess)+import Hix.Managed.Flow (Flow, execStage, execStatelessStage)+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (BuildHandlers)+import Hix.Managed.Handlers.Cabal (CabalHandlers, installedVersions)+import Hix.Managed.Handlers.Mutation.Bump (handlersBump)+import Hix.Managed.Process (processProject)+import Hix.Managed.Report (describeIterations)+import Hix.Managed.StageResult (stageResult)++-- | Solver params for Bump consist of, in decreasing order of precedence:+--+-- - User-specified bounds (added by the constructor 'solverState').+--+-- - The existing overrides from previous runs, used as preferred versions.+-- This ensures that the solver selects the same versions as in the last run while still allowing newer versions for+-- transitive dependencies that are later in the candidate list.+--+-- - Installed versions from the package db, used as lower bounds.+--+-- - The preference for using the installed version for mutable deps, which is a fallback for packages without overrides+-- (since their chosen versions are installed).+bumpSolverParams ::+ EnvDeps ->+ CabalHandlers ->+ Initial MutationState ->+ EnvConstraints+bumpSolverParams deps cabal (Initial state) =+ preferVersions (nMap (.version) state.overrides) <>+ fromVersions fromLower (installedVersions cabal deps.mutable) <>+ preferInstalled deps.mutable++success :: Map MutableDep BuildSuccess -> Natural -> Text+success _ iterations =+ [exon|Found working latest versions for all deps after #{iter}.|]+ where+ iter = describeIterations iterations++failure :: Natural -> Text+failure iterations =+ [exon|Couldn't find working latest versions for some deps after #{describeIterations iterations}.|]++bumpBuild ::+ BuildHandlers ->+ BuildConfig ->+ StageContext ->+ M StageResult+bumpBuild handlers conf stage@StageContext {env, builder, state} = do+ result <- processQuery (candidatesBump handlers) handlersBump conf stage ext+ pure (stageResult success failure result)+ where+ ext = solverState env.solverBounds env.deps (bumpSolverParams env.deps builder.cabal state) flags+ flags = SolverFlags {allowNewer = True}++bumpBuildStage ::+ BuildHandlers ->+ BuildConfig ->+ Flow BuildStatus+bumpBuildStage handlers conf =+ execStage "bump" (bumpBuild handlers conf)++bumpReportStage ::+ BuildHandlers ->+ Flow BuildStatus+bumpReportStage handlers =+ execStatelessStage "bump-report" \ StageContext {query = Query query} ->+ toSummary . toCandidates <$> traverse (candidatesBump handlers) (toList query)+ where+ toSummary = \case+ Just cs -> StageReport "Found new versions:" cs+ Nothing -> StageNoAction (Just "All dependencies are up to date.")++ toCandidates = nonEmpty . fmap toCandidate . catMaybes++ toCandidate DepMutation {package = name, mutation = Bump {version}} =+ MutableId {..}++bumpStages ::+ BuildHandlers ->+ BuildConfig ->+ Flow BuildStatus+bumpStages handlers conf+ | conf.lookup+ = bumpReportStage handlers+ | otherwise+ = bumpBuildStage handlers conf++bumpOptimizeMain ::+ BuildHandlers ->+ ProjectContext ->+ M ProjectResult+bumpOptimizeMain handlers project =+ processProject handlers project (void (bumpStages handlers project.build))
+ lib/Hix/Managed/Cabal/Changes.hs view
@@ -0,0 +1,67 @@+module Hix.Managed.Cabal.Changes where++import Data.List (partition)+import qualified Distribution.Client.SolverInstallPlan as SolverInstallPlan+import Distribution.Client.SolverInstallPlan (ResolverPackage (Configured, PreExisting), SolverInstallPlan)+import Distribution.InstalledPackageInfo (InstalledPackageInfo (..))+import Distribution.Pretty (Pretty, pretty)+import Distribution.Solver.Types.InstSolverPackage (InstSolverPackage (..))+import Distribution.Solver.Types.SolverPackage (SolverPackage (..))+import Distribution.Solver.Types.SourcePackage (SourcePackage (..))+import Text.PrettyPrint (hang, ($+$))++import qualified Hix.Data.PackageId as PackageId+import Hix.Data.PackageId (PackageId)+import Hix.Data.Version (Versions)+import Hix.Managed.Cabal.Config (isNonReinstallableId)+import Hix.Pretty (prettyL)++-- | Raw results from Cabal, which include local packages in the overrides.+data SolverPlan =+ SolverPlan {+ -- | Deps whose versions differ from those in the package db, i.e. where the GHC set from nixpkgs has a different+ -- version.+ -- We need to add Nix overrides for these.+ changes :: [PackageId],++ -- | Versions that match those in the package db.+ -- We don't need to add Nix overrides for these.+ matching :: [PackageId],++ -- | GHC boot packages that were selected for reinstallation, which is an error with the default settings.+ nonReinstallable :: Maybe (NonEmpty PackageId)+ }+ deriving stock (Eq, Show, Generic)++instance Pretty SolverPlan where+ pretty SolverPlan {changes, matching} =+ hang "changes:" 2 (prettyL changes) $+$ hang "matching:" 2 (prettyL matching)++solverPlan ::+ SolverInstallPlan ->+ SolverPlan+solverPlan plan =+ SolverPlan {..}+ where+ (nonEmpty -> nonReinstallable, changes) = partition isNonReinstallableId configured++ (configured, matching) = partitionEithers (mkVersion <$> SolverInstallPlan.toList plan)++ mkVersion = \case+ Configured SolverPackage {solverPkgSource = SourcePackage {srcpkgPackageId}} ->+ Left (PackageId.fromCabal srcpkgPackageId)+ PreExisting InstSolverPackage {instSolverPkgIPI = InstalledPackageInfo {sourcePackageId}} ->+ Right (PackageId.fromCabal sourcePackageId)++data SolverChanges =+ SolverChanges {+ versions :: Versions,+ overrides :: [PackageId],+ projectDeps :: Versions+ }+ deriving stock (Eq, Show, Generic)++instance Pretty SolverChanges where+ pretty SolverChanges {..} =+ hang "overrides:" 2 (prettyL overrides) $+$+ hang "projectDeps:" 2 (pretty projectDeps)
+ lib/Hix/Managed/Cabal/Config.hs view
@@ -0,0 +1,35 @@+module Hix.Managed.Cabal.Config where++import qualified Data.Set as Set++import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId)+import Hix.Data.PackageName (PackageName)+import Hix.Managed.Data.Mutable (MutableDep, depName)++nonReinstallableNames :: Set PackageName+nonReinstallableNames =+ [+ "base",+ "ghc-bignum",+ "ghc-prim",+ "ghc",+ "integer-gmp",+ "integer-simple",+ "template-haskell"+ ]++isNonReinstallable :: PackageName -> Bool+isNonReinstallable = flip Set.member nonReinstallableNames++isReinstallable :: PackageName -> Bool+isReinstallable = not . isNonReinstallable++isNonReinstallableId :: PackageId -> Bool+isNonReinstallableId package = isNonReinstallable package.name++isReinstallableId :: PackageId -> Bool+isReinstallableId package = isReinstallable package.name++isNonReinstallableDep :: MutableDep -> Bool+isNonReinstallableDep = isNonReinstallable . depName
+ lib/Hix/Managed/Cabal/Data/Config.hs view
@@ -0,0 +1,64 @@+module Hix.Managed.Cabal.Data.Config where++import Data.Aeson (FromJSON (parseJSON))+import Distribution.Client.IndexUtils.Timestamp (Timestamp)+import Distribution.Verbosity (Verbosity, verbose)+import Path (Abs, Dir, Path)++import Hix.Managed.Cabal.Data.Packages (GhcPackages)++newtype HackageRepoName =+ HackageRepoName Text+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsString, Ord)++instance Default HackageRepoName where+ def = "hackage.haskell.org"++newtype GhcPath =+ GhcPath (Path Abs Dir)+ deriving stock (Eq, Show, Generic)+ deriving newtype (FromJSON)++data GhcDb =+ GhcDbSystem (Maybe GhcPath)+ |+ GhcDbSynthetic GhcPackages+ deriving stock (Eq, Show, Generic)++instance FromJSON GhcDb where+ parseJSON = fmap GhcDbSystem . parseJSON++newtype HackageIndexState =+ HackageIndexState Timestamp+ deriving stock (Eq, Show, Generic)++data CabalConfig =+ CabalConfig {+ indexState :: Maybe HackageIndexState+ }+ deriving stock (Eq, Show, Generic)++instance Default CabalConfig where+ def =+ CabalConfig {indexState = Nothing}++data SolveConfig =+ SolveConfig {+ hackageRepoName :: HackageRepoName,+ verbosity :: Verbosity,+ ghc :: Maybe GhcPath,+ allowBoot :: Bool,+ cabal :: CabalConfig+ }+ deriving stock (Eq, Show, Generic)++instance Default SolveConfig where+ def =+ SolveConfig {+ hackageRepoName = def,+ verbosity = verbose,+ ghc = Nothing,+ allowBoot = False,+ cabal = def+ }
+ lib/Hix/Managed/Cabal/Data/Packages.hs view
@@ -0,0 +1,23 @@+module Hix.Managed.Cabal.Data.Packages where++import GHC.Exts (IsList)++import Hix.Data.PackageId (PackageId)+import Hix.Managed.Cabal.Data.SourcePackage (SourcePackages)++newtype InstalledPackages =+ InstalledPackages [(PackageId, [PackageId])]+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsList, Semigroup, Monoid)++-- | Mock data for package indexes for the solver.+--+-- Installed packages should not contain local packages, since they have fixed dependency versions.+-- Instead, they should be included in the available packages, but this is done automatically by the @SolveResources@+-- initializer, so these here correspond only to Hackage packages.+data GhcPackages =+ GhcPackages {+ installed :: InstalledPackages,+ available :: SourcePackages+ }+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Managed/Cabal/Data/SolveResources.hs view
@@ -0,0 +1,23 @@+module Hix.Managed.Cabal.Data.SolveResources where++import Distribution.Client.Dependency (DepResolverParams)+import Distribution.Client.Types (SourcePackageDb)+import Distribution.Simple (CompilerInfo)+import Distribution.Simple.PackageIndex (InstalledPackageIndex)+import Distribution.Solver.Types.PkgConfigDb (PkgConfigDb)+import Distribution.System (Platform)++import Hix.Managed.Cabal.Data.Config (SolveConfig (..))+import Hix.Managed.Cabal.Init (SolveFlags)++data SolveResources =+ SolveResources {+ conf :: SolveConfig,+ flags :: SolveFlags,+ platform :: Platform,+ compiler :: CompilerInfo,+ pkgConfigDb :: PkgConfigDb,+ installedPkgIndex :: InstalledPackageIndex,+ sourcePkgDb :: SourcePackageDb,+ solverParams :: DepResolverParams -> DepResolverParams+ }
+ lib/Hix/Managed/Cabal/Data/SolveTarget.hs view
@@ -0,0 +1,36 @@+module Hix.Managed.Cabal.Data.SolveTarget where++import Distribution.Client.Dependency (PackagePreference (..), PackageSpecifier (NamedPackage, SpecificSourcePackage))+import Distribution.Client.Types (UnresolvedSourcePackage)+import Distribution.Pretty (Pretty (pretty))+import Distribution.Solver.Types.PackageConstraint (dispPackageProperty)+import Distribution.Version (simplifyVersionRange)+import Text.PrettyPrint (Doc, (<+>))++import Hix.Pretty (prettyL)++data SolveTarget =+ SolveTarget {+ dep :: PackageSpecifier UnresolvedSourcePackage,+ prefs :: [PackagePreference]+ }++prettySpec :: PackageSpecifier UnresolvedSourcePackage -> Doc+prettySpec = \case+ NamedPackage name prop ->+ "Named:" <+> pretty name <+> prettyL (dispPackageProperty <$> prop)+ SpecificSourcePackage pkg ->+ "Source:" <+> show pkg++prettyPref :: PackagePreference -> Doc+prettyPref = \case+ PackageVersionPreference pn vr ->+ pretty pn <+> pretty (simplifyVersionRange vr)+ PackageInstalledPreference pn ip ->+ pretty pn <+> show ip+ PackageStanzasPreference pn st ->+ pretty pn <+> show st++instance Pretty SolveTarget where+ pretty SolveTarget {..} =+ prettySpec dep <+> prettyL (prettyPref <$> prefs)
+ lib/Hix/Managed/Cabal/Data/SolverState.hs view
@@ -0,0 +1,83 @@+module Hix.Managed.Cabal.Data.SolverState (+ SolverState (SolverState, constraints, flags),+ solverState,+ updateSolverState,+ SolverFlags (..),+ compileSolverFlags,+) where++import Distribution.Client.Dependency (DepResolverParams, removeUpperBounds)+import Distribution.Client.Types (RelaxDeps (RelaxDepsAll))+import Distribution.Client.Types.AllowNewer (AllowNewer (AllowNewer))+import GHC.Records (HasField (getField))++import Hix.Class.Map (nGenWith)+import Hix.Data.Bounds (Ranges)+import Hix.Data.PackageName (LocalPackage (LocalPackage))+import Hix.Managed.Constraints (explicitBounds, noBounds)+import Hix.Managed.Data.Constraints (EnvConstraints)+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvDeps)+import Hix.Managed.Data.Mutable (MutableDep, depName)++data SolverFlags =+ SolverFlags {+ allowNewer :: Bool+ }+ deriving stock (Eq, Show, Generic)++instance Default SolverFlags where+ def = SolverFlags {allowNewer = False}++flagAllowNewer :: DepResolverParams -> DepResolverParams+flagAllowNewer =+ removeUpperBounds (AllowNewer RelaxDepsAll)++compileSolverFlags :: SolverFlags -> DepResolverParams -> DepResolverParams+compileSolverFlags SolverFlags {..} =+ flag flagAllowNewer allowNewer+ where+ flag f v | v = f+ | otherwise = id++data SolverState =+ UnsafeSolverState EnvConstraints SolverFlags+ deriving stock (Eq, Show)++pattern SolverState :: EnvConstraints -> SolverFlags -> SolverState+pattern SolverState {constraints, flags} <- UnsafeSolverState constraints flags++{-# complete SolverState #-}++instance HasField "constraints" SolverState EnvConstraints where+ getField (UnsafeSolverState c _) = c++instance HasField "flags" SolverState SolverFlags where+ getField (UnsafeSolverState _ p) = p++-- TODO What's the point of this now that there's no @local@ flag in the constraints anymore?+localDepConstraints :: Set LocalPackage -> EnvConstraints+localDepConstraints =+ nGenWith \ (LocalPackage package) -> (package, noBounds)++mutableDepConstraints :: Set MutableDep -> EnvConstraints+mutableDepConstraints =+ nGenWith \ package -> (depName package, noBounds)++solverState ::+ Ranges ->+ EnvDeps ->+ EnvConstraints ->+ SolverFlags ->+ SolverState+solverState user deps modeConstraints flags =+ UnsafeSolverState constraints flags+ where+ constraints =+ modeConstraints <>+ explicitBounds user <>+ localDepConstraints deps.local <>+ mutableDepConstraints deps.mutable++updateSolverState :: (EnvConstraints -> EnvConstraints) -> SolverState -> SolverState+updateSolverState f (UnsafeSolverState c p) = UnsafeSolverState (f c) p
+ lib/Hix/Managed/Cabal/Data/SourcePackage.hs view
@@ -0,0 +1,40 @@+module Hix.Managed.Cabal.Data.SourcePackage where++import Distribution.Pretty (Pretty (pretty))+import Distribution.Simple (Version)+import GHC.Exts (IsList)++import Hix.Class.Map (LookupMaybe, LookupMonoid, NMap, nPretty1, nPrettyWith)+import Hix.Data.Dep (Dep)+import Hix.Data.PackageName (PackageName)+import Hix.Pretty (prettyL)++newtype SourcePackageDeps =+ SourcePackageDeps (Map Version [Dep])+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList)++instance NMap SourcePackageDeps Version [Dep] LookupMonoid where++instance Pretty SourcePackageDeps where+ pretty = nPrettyWith prettyL++newtype SourcePackages =+ SourcePackages (Map PackageName SourcePackageDeps)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList)++instance NMap SourcePackages PackageName SourcePackageDeps LookupMaybe where++instance Pretty SourcePackages where+ pretty = nPretty1++newtype SourcePackageVersions =+ SourcePackageVersions (Map PackageName [Version])+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList)++instance NMap SourcePackageVersions PackageName [Version] LookupMaybe where++instance Pretty SourcePackageVersions where+ pretty = nPrettyWith prettyL
+ lib/Hix/Managed/Cabal/Init.hs view
@@ -0,0 +1,85 @@+module Hix.Managed.Cabal.Init where++import Distribution.Client.Config (defaultCacheDir)+import Distribution.Client.GlobalFlags (GlobalFlags (..), defaultGlobalFlags)+import Distribution.Client.NixStyleOptions (NixStyleFlags (..), defaultNixStyleFlags)+import Distribution.Client.ProjectFlags (flagIgnoreProject)+import Distribution.Client.Types (RemoteRepo (..))+import Distribution.Parsec (eitherParsec)+import Distribution.Simple.Program (defaultProgramDb)+import Distribution.Simple.Setup (ConfigFlags (..), defaultConfigFlags, maybeToFlag, toFlag)+import Distribution.Utils.NubList (toNubList)+import Exon (exon)+import Path (reldir, relfile, toFilePath, (</>))++import Hix.Data.Error (Error (Fatal))+import qualified Hix.Managed.Cabal.Data.Config+import Hix.Managed.Cabal.Data.Config (GhcPath (GhcPath), HackageRepoName, SolveConfig)+import Hix.Managed.Cabal.Repo (ensureHackageIndex)+import Hix.Monad (M, throwM, tryIOMWith)++data SolveFlags =+ SolveFlags {+ global :: GlobalFlags,+ main :: NixStyleFlags ()+ }++emptySolveFlags :: SolveFlags+emptySolveFlags =+ SolveFlags {+ global = defaultGlobalFlags {globalConfigFile = toFlag "/dev/null"},+ main = defaultNixStyleFlags ()+ }++hackageRepo ::+ HackageRepoName ->+ M RemoteRepo+hackageRepo repoName =+ case eitherParsec [exon|##{repoName}:http://hackage.haskell.org/|] of+ Right repo -> pure repo {remoteRepoSecure = Just True}+ Left err -> throwM (Fatal [exon|Parse error: #{toText err}|])++globalFlags :: RemoteRepo -> FilePath -> GlobalFlags+globalFlags hackage cacheDir =+ defaultGlobalFlags {+ -- Cabal *always* reads ~/.cabal/config if no file is specified, and crashes if the file doesn't exist+ globalConfigFile = toFlag "/dev/null",+ globalCacheDir = toFlag cacheDir,+ globalRemoteRepos = toNubList [hackage]+ }++badCacheDir :: Text -> Error+badCacheDir err = Fatal [exon|Cannot access Cabal cache dir: #{err}|]++mainFlags ::+ SolveConfig ->+ NixStyleFlags ()+mainFlags conf =+ basic {+ configFlags,+ projectFlags = basic.projectFlags {flagIgnoreProject = toFlag True}+ }+ where+ basic = defaultNixStyleFlags ()++ configFlags =+ (defaultConfigFlags defaultProgramDb) {+ configHcPath = pathFlag [relfile|ghc|],+ configHcPkg = pathFlag [relfile|ghc-pkg|],+ configVerbosity = toFlag conf.verbosity+ }++ pathFlag exe = maybeToFlag (ghcPath exe <$> conf.ghc)++ ghcPath exe (GhcPath dir) = toFilePath (dir </> [reldir|bin|] </> exe)++initialize ::+ SolveConfig ->+ M SolveFlags+initialize conf = do+ hackage <- hackageRepo conf.hackageRepoName+ cacheDir <- tryIOMWith badCacheDir defaultCacheDir+ let global = globalFlags hackage cacheDir+ let main = mainFlags conf+ ensureHackageIndex conf global main+ pure SolveFlags {global, main}
+ lib/Hix/Managed/Cabal/Installed.hs view
@@ -0,0 +1,14 @@+module Hix.Managed.Cabal.Installed where++import Distribution.Simple.PackageIndex (InstalledPackageIndex, lookupPackageName)++import qualified Hix.Data.PackageName as PackageName+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (Version)++installedVersion ::+ InstalledPackageIndex ->+ PackageName ->+ Maybe Version+installedVersion index name =+ fst <$> head (lookupPackageName index (PackageName.toCabal name))
+ lib/Hix/Managed/Cabal/Mock.hs view
@@ -0,0 +1,33 @@+module Hix.Managed.Cabal.Mock where++import Distribution.Simple (buildCompilerId, unknownCompilerInfo)+import Distribution.Simple.Compiler (AbiTag (NoAbiTag))+import Distribution.Solver.Types.PkgConfigDb (PkgConfigDb (NoPkgConfigDb))+import Distribution.System (Arch (X86_64), OS (Linux), Platform (Platform))++import Hix.Managed.Data.ManagedPackage (ManagedPackage)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Cabal.Data.Packages+import Hix.Managed.Cabal.Data.Packages (GhcPackages (GhcPackages))+import qualified Hix.Managed.Cabal.Data.SolveResources+import Hix.Managed.Cabal.Data.SolveResources (SolveResources (SolveResources))+import Hix.Managed.Cabal.Init (emptySolveFlags)+import Hix.Managed.Cabal.Mock.InstalledPackage (mockInstalledPackageIndex)+import qualified Hix.Managed.Cabal.Mock.SourcePackage as SourcePackage+import Hix.Managed.Cabal.Mock.SourcePackage (mockSourcePackageDb)++mockSolveResources ::+ Packages ManagedPackage ->+ GhcPackages ->+ SolveResources+mockSolveResources packages GhcPackages {installed, available} = do+ SolveResources {+ conf = def,+ flags = emptySolveFlags,+ platform = Platform X86_64 Linux,+ compiler = unknownCompilerInfo buildCompilerId NoAbiTag,+ pkgConfigDb = NoPkgConfigDb,+ installedPkgIndex = mockInstalledPackageIndex installed,+ sourcePkgDb = SourcePackage.dbWithManaged packages (mockSourcePackageDb available),+ solverParams = id+ }
+ lib/Hix/Managed/Cabal/Mock/InstalledPackage.hs view
@@ -0,0 +1,28 @@+module Hix.Managed.Cabal.Mock.InstalledPackage where++import Distribution.InstalledPackageInfo (InstalledPackageInfo (..), emptyInstalledPackageInfo)+import Distribution.Package (UnitId, mkUnitId)+import qualified Distribution.Simple.PackageIndex as PackageIndex+import Distribution.Simple.PackageIndex (InstalledPackageIndex)++import qualified Hix.Data.PackageId as PackageId+import Hix.Data.PackageId (PackageId)+import Hix.Managed.Cabal.Data.Packages (InstalledPackages (InstalledPackages))+import Hix.Pretty (showP)++mockUnitId :: PackageId -> UnitId+mockUnitId = mkUnitId . showP++installedPackageInfo :: PackageId -> [UnitId] -> InstalledPackageInfo+installedPackageInfo package depends =+ emptyInstalledPackageInfo {+ sourcePackageId = PackageId.toCabal package,+ installedUnitId = mockUnitId package,+ depends+ }++mockInstalledPackageIndex :: InstalledPackages -> InstalledPackageIndex+mockInstalledPackageIndex =+ PackageIndex.fromList .+ fmap (uncurry installedPackageInfo . second (fmap mockUnitId)) .+ coerce
+ lib/Hix/Managed/Cabal/Mock/SourcePackage.hs view
@@ -0,0 +1,111 @@+module Hix.Managed.Cabal.Mock.SourcePackage where++import qualified Data.Map.Strict as Map+import Distribution.Client.Types (PackageLocation (LocalTarballPackage), SourcePackageDb (..), UnresolvedSourcePackage)+import Distribution.PackageDescription (+ CondTree (..),+ Library (libBuildInfo),+ LibraryVisibility (LibraryVisibilityPublic),+ PackageDescription (..),+ emptyLibrary,+ emptyPackageDescription, BuildInfo (targetBuildDepends),+ )+import Distribution.Simple (Version)+import qualified Distribution.Solver.Types.PackageIndex as PackageIndex+import Distribution.Solver.Types.PackageIndex (PackageIndex)+import Distribution.Solver.Types.SourcePackage (SourcePackage (..))+import Distribution.Types.GenericPackageDescription (GenericPackageDescription (..), emptyGenericPackageDescription)+import Distribution.Types.Library (libVisibility)+import Exon (exon)++import Hix.Class.Map (nGet, nKeys, nMap, nTo1, nTransform, nVia, (!!))+import qualified Hix.Data.Dep as Dep+import Hix.Data.Dep (Dep)+import Hix.Data.Monad (M)+import qualified Hix.Data.PackageId as PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.PackageName (LocalPackage (LocalPackage), PackageName, localPackageName)+import Hix.Managed.Cabal.Data.SourcePackage (SourcePackageDeps, SourcePackageVersions, SourcePackages)+import qualified Hix.Managed.Data.ManagedPackage as ManagedPackage+import Hix.Managed.Data.ManagedPackage (ManagedPackage)+import Hix.Managed.Data.Packages (Packages)+import Hix.Monad (noteClient)++allDeps :: [Dep] -> SourcePackageDeps -> SourcePackageDeps+allDeps deps = nVia (fmap (deps ++))++allDep :: Dep -> SourcePackageDeps -> SourcePackageDeps+allDep dep = nVia (fmap (dep :))++sourcePackageVersions :: SourcePackages -> SourcePackageVersions+sourcePackageVersions = nMap (sort . nKeys)++queryVersions :: SourcePackageVersions -> PackageName -> M [Version]+queryVersions packages query = noteClient [exon|No such package in the source db: ##{query}|] (packages !! query)++queryPackages :: SourcePackages -> PackageName -> M [Version]+queryPackages packages =+ queryVersions (sourcePackageVersions packages)++queryVersionsLatest :: SourcePackageVersions -> PackageName -> M (Maybe Version)+queryVersionsLatest packages query = last <$> queryVersions packages query++queryPackagesLatest :: SourcePackages -> PackageName -> M (Maybe Version)+queryPackagesLatest packages =+ queryVersionsLatest versions+ where+ versions = sourcePackageVersions packages++-- | This _must_ have the dependencies in both 'targetBuildDepends' and 'condTreeConstraints', otherwise they will be+-- ignored or deleted depending on what resolver params are used.+-- This is also evidenced by looking at a parsed Cabal file, see @CabalTest@.+mockSourcePackage :: PackageName -> Version -> [Dep] -> UnresolvedSourcePackage+mockSourcePackage name version deps =+ SourcePackage {+ srcpkgPackageId = cabalId,+ srcpkgDescription = emptyGenericPackageDescription {+ packageDescription = emptyPackageDescription {+ package = cabalId+ },+ condLibrary = Just library+ },+ srcpkgSource = LocalTarballPackage "/invalid",+ srcpkgDescrOverride = Nothing+ }+ where+ library =+ mempty {+ condTreeData = emptyLibrary {+ libVisibility = LibraryVisibilityPublic,+ libBuildInfo = mempty {targetBuildDepends = cabalDeps}+ },+ condTreeConstraints = cabalDeps+ }+ cabalId = PackageId.toCabal PackageId {..}+ cabalDeps = Dep.toCabal <$> deps++mockSourcePackageDb :: SourcePackages -> SourcePackageDb+mockSourcePackageDb packages =+ SourcePackageDb {+ packageIndex = PackageIndex.fromList (nTo1 packages mockSourcePackage),+ packagePreferences = []+ }++managedSourcePackageVersions :: Packages ManagedPackage -> SourcePackageVersions+managedSourcePackageVersions =+ nTransform \ (LocalPackage name) package -> (name, [package.version])++managedSourcePackage :: ManagedPackage -> UnresolvedSourcePackage+managedSourcePackage package =+ mockSourcePackage (localPackageName package.package) package.version (ManagedPackage.deps package)++managedPackageIndex :: Packages ManagedPackage -> PackageIndex UnresolvedSourcePackage+managedPackageIndex packages =+ PackageIndex.fromList (managedSourcePackage <$> Map.elems (nGet packages))++dbWithManaged :: Packages ManagedPackage -> SourcePackageDb -> SourcePackageDb+dbWithManaged packages SourcePackageDb {packageIndex, packagePreferences} =+ SourcePackageDb {+ packageIndex = PackageIndex.merge packageIndex (managedPackageIndex packages),+ packagePreferences+ }
+ lib/Hix/Managed/Cabal/Print.hs view
@@ -0,0 +1,26 @@+module Hix.Managed.Cabal.Print where++import qualified Distribution.Client.SolverInstallPlan as SolverInstallPlan+import Distribution.Client.SolverInstallPlan (ResolverPackage (..), SolverInstallPlan, SolverPlanPackage)+import Distribution.InstalledPackageInfo (InstalledPackageInfo (InstalledPackageInfo, sourcePackageId))+import Distribution.Pretty (pretty)+import Distribution.Solver.Types.InstSolverPackage (InstSolverPackage (InstSolverPackage, instSolverPkgIPI))+import Distribution.Solver.Types.SolverPackage (SolverPackage (..))+import Distribution.Solver.Types.SourcePackage (SourcePackage (..))+import Exon (exon)++import Hix.Data.Monad (M)+import qualified Hix.Log as Log++showPackage :: SolverPlanPackage -> String+showPackage = \case+ PreExisting InstSolverPackage {instSolverPkgIPI = InstalledPackageInfo {sourcePackageId}} ->+ "existing: " <> show (pretty sourcePackageId)+ Configured SolverPackage {solverPkgSource = SourcePackage {srcpkgPackageId}} ->+ "configured: " <> show (pretty srcpkgPackageId)++printPlan :: SolverInstallPlan -> M ()+printPlan plan = do+ Log.info "Plan:"+ for_ (SolverInstallPlan.toList plan) \ pkg ->+ Log.infoCont [exon|📦 #{toText (showPackage pkg)}|]
+ lib/Hix/Managed/Cabal/Repo.hs view
@@ -0,0 +1,137 @@+module Hix.Managed.Cabal.Repo where++import Data.Time (UTCTime (..), showGregorian, timeToTimeOfDay)+import Distribution.Client.CmdUpdate (updateAction)+import qualified Distribution.Client.GlobalFlags+import Distribution.Client.GlobalFlags (GlobalFlags (..))+import Distribution.Client.IndexUtils (currentIndexTimestamp, indexBaseName)+import Distribution.Client.IndexUtils.Timestamp (timestampToUTCTime)+import Distribution.Client.NixStyleOptions (NixStyleFlags (..))+import Distribution.Client.Setup (RepoContext, withRepoContext)+import Distribution.Client.Types (RemoteRepo (..), Repo (RepoSecure), RepoName (RepoName))+import qualified Distribution.Client.Types.Repo+import Distribution.Compat.Time (getFileAge)+import Distribution.Verbosity (Verbosity)+import Exon (exon)+import Path (Abs, File, Path, addExtension, parseAbsFile, toFilePath)+import Path.IO (doesFileExist)++import Hix.Data.Error (Error (Fatal))+import Hix.Error (pathText)+import qualified Hix.Log as Log+import qualified Hix.Managed.Cabal.Data.Config+import Hix.Managed.Cabal.Data.Config (+ CabalConfig (CabalConfig),+ HackageIndexState (HackageIndexState),+ HackageRepoName (HackageRepoName),+ SolveConfig (SolveConfig),+ )+import Hix.Maybe (justIf)+import Hix.Monad (M, catchIOM, eitherFatalShow, noteFatal, tryIOM, tryIOMWith, withLower)++withRepoContextM ::+ SolveConfig ->+ GlobalFlags ->+ (RepoContext -> M a) ->+ M a+withRepoContextM conf flags f =+ withLower \ lower -> withRepoContext conf.verbosity flags \ ctx -> lower (f ctx)++fullHackageRepo ::+ SolveConfig ->+ RepoContext ->+ M Repo+fullHackageRepo SolveConfig {hackageRepoName = HackageRepoName (toString -> hackage)} ctx =+ noteFatal err $ flip find ctx.repoContextRepos \case+ RepoSecure {repoRemote = RemoteRepo {remoteRepoName = RepoName name}} -> name == hackage+ _ -> False+ where+ err = "Bad Hackage repo config"++data IndexProblem =+ IndexMissing+ |+ IndexOutdated+ |+ IndexMismatch+ deriving stock (Eq, Show, Generic)++indexOutdated :: Path Abs File -> IO Bool+indexOutdated (toFilePath -> index) =+ (> 7) <$> getFileAge index++updateRequest ::+ SolveConfig ->+ String+updateRequest SolveConfig {hackageRepoName, cabal = CabalConfig {indexState}} =+ [exon|#{hackage}#{extra}|]+ where+ extra = foldMap stateField (timestampToUTCTime . coerce =<< indexState)++ stateField UTCTime {..} = [exon|,#{showGregorian utctDay}T#{show (timeToTimeOfDay utctDayTime)}Z|]++ HackageRepoName (toString -> hackage) = hackageRepoName++updateIndex ::+ SolveConfig ->+ GlobalFlags ->+ NixStyleFlags () ->+ IndexProblem ->+ M ()+updateIndex conf global main problem = do+ Log.verbose [exon|Hackage snapshot #{message}, fetching...|]+ tryIOMWith (\ err -> Fatal [exon|Fetching hackage snapshot failed: #{err}|]) do+ updateAction main [updateRequest conf] global+ where+ message = case problem of+ IndexMissing -> "doesn't exist"+ IndexOutdated -> "is older than 7 days"+ IndexMismatch -> "differs from requested index state"++indexPath :: Repo -> M (Path Abs File)+indexPath repo =+ eitherFatalShow err do+ base <- parseAbsFile (indexBaseName repo)+ addExtension ".tar" base+ where+ err = "Bad Hackage repo config"++matchIndexState ::+ Verbosity ->+ RepoContext ->+ Repo ->+ HackageIndexState ->+ M (Maybe IndexProblem)+matchIndexState verbosity ctx repo (HackageIndexState target) =+ catchIOM (match <$> currentIndexTimestamp verbosity ctx repo) (\ _ -> pure (Just IndexMissing))+ where+ match current | current == target = Nothing+ | otherwise = Just IndexMismatch++indexProblem ::+ SolveConfig ->+ RepoContext ->+ Repo ->+ Path Abs File ->+ M (Maybe IndexProblem)+indexProblem SolveConfig {verbosity, cabal} ctx repo path = do+ Log.debug [exon|Checking hackage snapshot at #{pathText path}|]+ tryIOM (doesFileExist path) >>= \case+ False -> pure (Just IndexMissing)+ True+ | Just target <- cabal.indexState+ -> matchIndexState verbosity ctx repo target+ | otherwise+ -> flip justIf IndexOutdated <$> tryIOM (indexOutdated path)++-- TODO currentIndexTimestamp has a different signature in later versions+ensureHackageIndex ::+ SolveConfig ->+ GlobalFlags ->+ NixStyleFlags () ->+ M ()+ensureHackageIndex conf global main =+ withRepoContextM conf global \ ctx -> do+ repo <- fullHackageRepo conf ctx+ path <- indexPath repo+ traverse_ (updateIndex conf global main) =<< indexProblem conf ctx repo path
+ lib/Hix/Managed/Cabal/Resources.hs view
@@ -0,0 +1,76 @@+module Hix.Managed.Cabal.Resources where++import Control.Monad.Trans.Reader (asks)+import Distribution.Client.IndexUtils (getInstalledPackages, getSourcePackages)+import qualified Distribution.Client.NixStyleOptions+import Distribution.Client.Setup (configCompilerAux', withRepoContext)+import Distribution.Simple (PackageDB (GlobalPackageDB), PackageDBStack, compilerInfo)+import Distribution.Solver.Types.PkgConfigDb (readPkgConfigDb)+import Distribution.Verbosity (lessVerbose, silent, verbose)++import qualified Hix.Data.Monad+import Hix.Data.Monad (M (M))+import qualified Hix.Log as Log+import Hix.Managed.Cabal.Data.Config (CabalConfig, GhcDb (GhcDbSynthetic, GhcDbSystem), SolveConfig (..))+import qualified Hix.Managed.Cabal.Data.SolveResources+import Hix.Managed.Cabal.Data.SolveResources (SolveResources (SolveResources))+import qualified Hix.Managed.Cabal.Init+import Hix.Managed.Cabal.Init (initialize)+import Hix.Managed.Cabal.Mock (mockSolveResources)+import qualified Hix.Managed.Cabal.Mock.SourcePackage as SourcePackage+import Hix.Managed.Data.ManagedPackage (ManagedPackage)+import Hix.Managed.Data.Packages (Packages)+import Hix.Monad (tryIOM)++packageDbs :: PackageDBStack+packageDbs = [GlobalPackageDB]++-- | This adds the 'ManagedPackage's to the source package DB, which is the set of available package IDs.+-- This means that the solver will find our local packages (for targets that depend on packages in other envs) like it+-- finds Hackage packages, and therefore local deps will be included in the plan.+--+-- Because we don't want local packages in the plan (as they are not mutable, but static in the Nix build), it would be+-- tempting to add 'ManagedPackage's to the installed package index instead, which would exclude them from the plan's+-- overrides.+-- However, their metadata must include concrete unit IDs for their dependencies with fixed versions, which would+-- require us to choose versions for them and might interfere with solving.+--+-- Maybe the basic installed package index could be queried to determine the dep versions.+-- Not sure this would be better than just filtering the plan.+resources ::+ Packages ManagedPackage ->+ SolveConfig ->+ M SolveResources+resources packages conf = do+ flags <- initialize conf+ Log.debug "Acquiring Cabal resources."+ tryIOM $ withRepoContext conf.verbosity flags.global \ repoContext -> do+ (compiler, platform, progdb) <- configCompilerAux' flags.main.configFlags+ pkgConfigDb <- readPkgConfigDb conf.verbosity progdb+ installedPkgIndex <- getInstalledPackages conf.verbosity compiler packageDbs progdb+ sourcePkgDb <- getSourcePackages conf.verbosity repoContext+ pure SolveResources {+ compiler = compilerInfo compiler,+ installedPkgIndex = installedPkgIndex,+ sourcePkgDb = SourcePackage.dbWithManaged packages sourcePkgDb,+ solverParams = id,+ ..+ }++-- TODO The Packages ManagedPackage are added in 'resources' as well as in 'mockSolveResources', which is probably ok since they+-- now come from @processProject@ and not from the tests, I think. still would be better to unify those+--+-- just add the managed packages to the result.+acquire ::+ Packages ManagedPackage ->+ CabalConfig ->+ GhcDb ->+ M SolveResources+acquire packages cabal = \case+ GhcDbSystem ghc -> do+ verbosity <- M (asks (.debug)) <&> \case+ True -> verbose+ False -> lessVerbose silent+ resources packages def {verbosity, ghc, cabal}+ GhcDbSynthetic db ->+ pure (mockSolveResources packages db)
+ lib/Hix/Managed/Cabal/Solve.hs view
@@ -0,0 +1,83 @@+module Hix.Managed.Cabal.Solve where++import Distribution.Client.Dependency (+ DepResolverParams,+ PackagePreference,+ PackageSpecifier,+ addPreferences,+ foldProgress,+ resolveDependencies,+ setAllowBootLibInstalls,+ standardInstallPolicy,+ )+import Distribution.Client.Dependency.Types (Solver (Modular))+import Distribution.Client.SolverInstallPlan (SolverInstallPlan)+import Distribution.Client.Types (UnresolvedSourcePackage)+import Distribution.Simple.Utils (debugNoWrap)+import Distribution.Solver.Types.Settings (AllowBootLibInstalls (AllowBootLibInstalls))+import Distribution.Verbosity (Verbosity)+import Exon (exon)++import Hix.Data.Error (Error (Fatal))+import qualified Hix.Log as Log+import Hix.Managed.Cabal.Changes (SolverPlan, solverPlan)+import qualified Hix.Managed.Cabal.Data.Config+import qualified Hix.Managed.Cabal.Data.SolveResources+import Hix.Managed.Cabal.Data.SolveResources (SolveResources)+import qualified Hix.Managed.Cabal.Data.SolveTarget+import Hix.Managed.Cabal.Data.SolveTarget (SolveTarget)+import qualified Hix.Managed.Cabal.Data.SolverState+import Hix.Managed.Cabal.Data.SolverState (SolverState (SolverState), compileSolverFlags)+import Hix.Managed.Cabal.Targets (solveTargets)+import Hix.Monad (M, tryIOMAs)++newtype Unresolvable =+ Unresolvable Text+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsString, Ord)++logMsg :: Verbosity -> String -> IO a -> IO a+logMsg verbosity message rest =+ debugNoWrap verbosity message *> rest++solveSpecifiers ::+ SolveResources ->+ (DepResolverParams -> DepResolverParams) ->+ [PackageSpecifier UnresolvedSourcePackage] ->+ [PackagePreference] ->+ IO (Either String SolverInstallPlan)+solveSpecifiers res mapParams pkgSpecifiers prefs =+ foldProgress (logMsg res.conf.verbosity) (pure . Left) (pure . Right) $+ resolveDependencies res.platform res.compiler res.pkgConfigDb Modular params+ where+ params =+ mapParams $+ res.solverParams $+ setAllowBootLibInstalls (AllowBootLibInstalls res.conf.allowBoot) $+ addPreferences prefs $+ standardInstallPolicy res.installedPkgIndex res.sourcePkgDb pkgSpecifiers++solveForTargets ::+ SolveResources ->+ (DepResolverParams -> DepResolverParams) ->+ [SolveTarget] ->+ M (Either Unresolvable SolverInstallPlan)+solveForTargets res mapParams targets =+ first fromString <$> tryIOMAs (Fatal "Cabal solver crashed.") (solveSpecifiers res mapParams pkgSpecifiers prefs)+ where+ pkgSpecifiers = (.dep) <$> targets+ prefs = (.prefs) =<< targets++solveWithCabal ::+ SolveResources ->+ SolverState ->+ M (Maybe SolverPlan)+solveWithCabal solveResources SolverState {constraints, flags} = do+ solveForTargets solveResources (compileSolverFlags flags) targets >>= \case+ Right plan ->+ pure (Just (solverPlan plan))+ Left err -> do+ Log.debug [exon|Solver found no plan: ##{err}|]+ pure Nothing+ where+ targets = solveTargets constraints
+ lib/Hix/Managed/Cabal/Targets.hs view
@@ -0,0 +1,50 @@+module Hix.Managed.Cabal.Targets where++import Distribution.Client.Dependency (+ PackagePreference (PackageInstalledPreference, PackageVersionPreference),+ PackageProperty (PackagePropertyVersion),+ PackageSpecifier (NamedPackage),+ )+import Distribution.Solver.Types.InstalledPreference (InstalledPreference (PreferInstalled, PreferOldest))+import Distribution.Version (orEarlierVersion, orLaterVersion)++import Hix.Class.Map (nToWith)+import qualified Hix.Data.PackageName as PackageName+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (VersionRange)+import Hix.Data.VersionBounds (Bound (BoundLower, BoundUpper), VersionBounds, maybeRange)+import Hix.Managed.Cabal.Data.SolveTarget (SolveTarget (..))+import qualified Hix.Managed.Data.Constraints+import Hix.Managed.Data.Constraints (EnvConstraints, MutationConstraints (MutationConstraints))++reifyBounds :: VersionBounds -> Maybe VersionRange+reifyBounds =+ maybeRange \case+ BoundLower -> orLaterVersion+ BoundUpper -> orEarlierVersion++solveTarget ::+ PackageName ->+ MutationConstraints ->+ SolveTarget+solveTarget package MutationConstraints {mutation, oldest, installed, prefer, force} =+ SolveTarget {dep, prefs}+ where+ dep = NamedPackage cabalName (PackagePropertyVersion <$> ranges)++ ranges = catMaybes [reifyBounds mutation, force]++ prefs = catMaybes [prefVersion <$> prefer, flag prefOldest oldest, flag prefInstalled installed]++ flag v = \case+ Just True -> Just v+ _ -> Nothing++ prefVersion = PackageVersionPreference cabalName+ prefOldest = PackageInstalledPreference cabalName PreferOldest+ prefInstalled = PackageInstalledPreference cabalName PreferInstalled++ cabalName = PackageName.toCabal package++solveTargets :: EnvConstraints -> [SolveTarget]+solveTargets = nToWith solveTarget
+ lib/Hix/Managed/Constraints.hs view
@@ -0,0 +1,37 @@+module Hix.Managed.Constraints where++import Distribution.Version (thisVersion)++import Hix.Class.Map (nGenWith, nMap, nTransform)+import Hix.Data.Bounds (Ranges)+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (Version, Versions)+import Hix.Data.VersionBounds (VersionBounds, anyBounds)+import Hix.Managed.Data.Constraints (EnvConstraints, MutationConstraints (..))+import Hix.Managed.Data.Mutable (MutableDep (MutableDep), MutableVersions)++noBounds :: MutationConstraints+noBounds = mempty {mutation = anyBounds}++forDeps :: (PackageName -> MutationConstraints) -> Set MutableDep -> EnvConstraints+forDeps f =+ nGenWith \ (MutableDep package) -> (package, f package)++fromVersions :: (Version -> VersionBounds) -> MutableVersions -> EnvConstraints+fromVersions bound =+ nTransform \ (MutableDep package) v -> (package, mempty {mutation = foldMap bound v})++preferRanges :: Ranges -> EnvConstraints+preferRanges =+ nMap \ range -> mempty {mutation = mempty, prefer = Just range}++preferVersions :: Versions -> EnvConstraints+preferVersions = preferRanges . nMap thisVersion++preferInstalled :: Set MutableDep -> EnvConstraints+preferInstalled =+ forDeps \ _ -> mempty {mutation = mempty, installed = Just True}++explicitBounds :: Ranges -> EnvConstraints+explicitBounds =+ nMap \ range -> mempty {mutation = mempty, force = Just range}
+ lib/Hix/Managed/Data/BuildConfig.hs view
@@ -0,0 +1,22 @@+module Hix.Managed.Data.BuildConfig where++data BuildConfig =+ BuildConfig {+ maxIterations :: Natural,+ maxFailedPre :: Natural,+ maxFailedPost :: Natural,+ lookup :: Bool,+ validate :: Bool,+ buildOutput :: Bool+ }+ deriving stock (Eq, Show, Generic)++instance Default BuildConfig where+ def = BuildConfig {+ maxIterations = 3,+ maxFailedPre = 99,+ maxFailedPost = 0,+ lookup = False,+ validate = False,+ buildOutput = False+ }
+ lib/Hix/Managed/Data/BuildOutput.hs view
@@ -0,0 +1,44 @@+module Hix.Managed.Data.BuildOutput where++import Data.Aeson (ToJSON (toJSON), object, (.=))+import Distribution.Pretty (Pretty (pretty))+import Text.PrettyPrint (brackets, (<+>))++import Hix.Data.Version (Version)+import Hix.Data.VersionBounds (VersionBounds)+import Hix.Managed.Data.Mutable (MutableDep)+import qualified Hix.Managed.Data.MutableId+import Hix.Managed.Data.MutableId (MutableId (MutableId))+import Hix.Pretty (showP)++data ModifiedId =+ ModifiedId {+ package :: MutableDep,+ version :: Version,+ range :: Maybe VersionBounds+ }+ deriving stock (Eq, Show, Generic)++instance Pretty ModifiedId where+ pretty ModifiedId {..} =+ pretty MutableId {name = package, version} <+> brackets (maybe "old range matches" pretty range)++instance ToJSON ModifiedId where+ toJSON ModifiedId {..} =+ object [+ "package" .= toJSON package,+ "version" .= toJSON (showP version :: Text),+ "range" .= toJSON (showP <$> range :: Maybe Text)+ ]++data BuildOutput =+ BuildOutput {+ modified :: [ModifiedId],+ unmodified :: [MutableDep],+ failed :: [MutableDep],+ modifiedNames :: Maybe Text,+ unmodifiedNames :: Maybe Text,+ failedNames :: Maybe Text+ }+ deriving stock (Eq, Show, Generic)+ deriving anyclass (ToJSON)
+ lib/Hix/Managed/Data/Bump.hs view
@@ -0,0 +1,18 @@+module Hix.Managed.Data.Bump where++import Distribution.Pretty (Pretty (pretty))+import Text.PrettyPrint (brackets, parens, (<+>))++import Hix.Data.Version (Version)++data Bump =+ Bump {+ version :: Version,+ bound :: Version,+ changed :: Bool+ }+ deriving stock (Eq, Show, Generic)++instance Pretty Bump where+ pretty Bump {version, bound, changed} =+ pretty version <+> parens ("<" <> pretty bound) <+> brackets (if changed then "x" else " ")
+ lib/Hix/Managed/Data/Constraints.hs view
@@ -0,0 +1,89 @@+module Hix.Managed.Data.Constraints where++import qualified Data.Map.Strict as Map+import Distribution.Pretty (Pretty (pretty))+import Distribution.Version (VersionRange)+import GHC.Exts (IsList)+import Text.PrettyPrint (Doc, parens, (<+>))++import Hix.Class.Map (LookupMaybe, NMap, nPretty)+import Hix.Data.PackageName (PackageName)+import Hix.Data.VersionBounds (VersionBounds, anyBounds)+import Hix.Pretty (prettyL)++-- | Left-biased semigroup op.+--+-- TODO it might be sensible to split the non-mutation deps out of this type so it can be keyed by @MutableDep@.+data MutationConstraints =+ MutationConstraints {+ -- | This used to be an abstraction, but there was no use case for it.+ -- Now it is hardcoded to use inclusive bounds for both, so a potential new mutation handler cannot customize that.+ -- All handlers only evolve one of the bounds, while this now allows both to be changed.+ mutation :: VersionBounds,++ -- | Prefer the oldest possible version.+ oldest :: Maybe Bool,++ -- | Prefer the installed version.+ installed :: Maybe Bool,++ -- | Concrete bounds overrides from user config.+ force :: Maybe VersionRange,++ -- | Prefer a concrete version range.+ prefer :: Maybe VersionRange+ }+ deriving stock (Eq, Show, Generic)++instance Pretty MutationConstraints where+ pretty MutationConstraints {mutation, oldest, installed, force, prefer} =+ pretty mutation <+>+ flags [("oldest", oldest), ("installed", installed)] <+>+ foldMap pref prefer <+>+ foldMap spec force+ where+ flags :: [(Doc, Maybe Bool)] -> Doc+ flags =+ mapMaybe flag >>> \case+ [] -> mempty+ fs -> parens (prettyL fs)++ flag = \case+ (desc, Just True) -> Just desc+ _ -> Nothing++ pref v = "~" <+> pretty v+ spec v = "+" <+> pretty v++instance Semigroup MutationConstraints where+ l <> r =+ MutationConstraints {+ mutation = l.mutation <> l.mutation,+ oldest = l.oldest <|> r.oldest,+ installed = l.installed <|> r.installed,+ force = l.force <|> r.force,+ prefer = l.prefer <|> r.prefer+ }++instance Monoid MutationConstraints where+ mempty =+ MutationConstraints {+ mutation = anyBounds,+ oldest = Nothing,+ installed = Nothing,+ force = Nothing,+ prefer = Nothing+ }++newtype EnvConstraints =+ EnvConstraints (Map PackageName MutationConstraints)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Monoid, IsList)++instance Semigroup EnvConstraints where+ EnvConstraints l <> EnvConstraints r = EnvConstraints (Map.unionWith (<>) l r)++instance NMap EnvConstraints PackageName MutationConstraints LookupMaybe where++instance Pretty EnvConstraints where+ pretty = nPretty
+ lib/Hix/Managed/Data/CurrentBuild.hs view
@@ -0,0 +1,9 @@+module Hix.Managed.Data.CurrentBuild where++import Hix.Data.PackageName (LocalPackage)++data CurrentBuild =+ CurrentBuild {+ target :: LocalPackage+ }+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Managed/Data/Diff.hs view
@@ -0,0 +1,66 @@+module Hix.Managed.Data.Diff where++import Data.These (These, mergeTheseWith)+import Distribution.Pretty (Pretty (pretty))+import Text.PrettyPrint (Doc, brackets, (<+>))++import Hix.Data.Version (Version)+import Hix.Data.VersionBounds (VersionBounds)+import Hix.Pretty (prettyL)++class PrettyDiffDetail a where+ prettyDiffDetail :: a -> Maybe Doc++instance PrettyDiffDetail () where+ prettyDiffDetail () = Nothing++data Diff d a =+ DiffAdded a+ |+ DiffChanged {+ original :: a,+ new :: a,+ detail :: d+ }+ deriving stock (Eq, Show, Generic, Functor)++instance (+ Pretty a,+ PrettyDiffDetail d+ ) => Pretty (Diff d a) where+ pretty = \case+ DiffAdded a -> "[+]" <+> pretty a+ DiffChanged {original, new, detail} -> pretty original <+> "->" <+> pretty new <+> fold (prettyDiffDetail detail)++type VersionDiff = Diff () Version++newtype BoundsDiffDetail =+ BoundsDiffDetail (These VersionDiff VersionDiff)+ deriving stock (Eq, Show, Generic)++type BoundsDiff = Diff BoundsDiffDetail VersionBounds++instance PrettyDiffDetail BoundsDiffDetail where+ prettyDiffDetail (BoundsDiffDetail detail) =+ Just (brackets (mergeTheseWith pretty pretty cat detail))+ where+ cat l u = prettyL @[] [l, u]++data Change d a =+ Changed (Diff d a)+ |+ Unchanged (Maybe a)+ deriving stock (Eq, Show, Generic, Functor)++instance (+ Pretty a,+ PrettyDiffDetail d+ ) => Pretty (Change d a) where+ pretty = \case+ Unchanged Nothing -> "[0]"+ Unchanged (Just a) -> "[=]" <+> pretty a+ Changed diff -> pretty diff++type VersionChange = Change () Version++type BoundsChange = Change BoundsDiffDetail VersionBounds
+ lib/Hix/Managed/Data/EnvConfig.hs view
@@ -0,0 +1,14 @@+module Hix.Managed.Data.EnvConfig where++import Data.Aeson (FromJSON)++import Hix.Data.PackageName (LocalPackage)+import Hix.Managed.Cabal.Data.Config (GhcDb)++data EnvConfig =+ EnvConfig {+ targets :: [LocalPackage],+ ghc :: GhcDb+ }+ deriving stock (Eq, Show, Generic)+ deriving anyclass (FromJSON)
+ lib/Hix/Managed/Data/EnvContext.hs view
@@ -0,0 +1,45 @@+module Hix.Managed.Data.EnvContext where++import GHC.Generics (Generically (Generically))++import Hix.Data.Bounds (Ranges)+import Hix.Data.EnvName (EnvName)+import Hix.Data.PackageName (LocalPackage)+import Hix.Managed.Cabal.Data.Config (GhcDb)+import Hix.Managed.Data.Mutable (MutableDep)+import Hix.Managed.Data.Targets (Targets)++data EnvDeps =+ EnvDeps {+ mutable :: Set MutableDep,+ local :: Set LocalPackage+ }+ deriving stock (Eq, Show, Generic)+ deriving (Semigroup, Monoid) via (Generically EnvDeps)++-- | Static data defining a managed bounds job for an environment.+data EnvContext =+ EnvContext {+ -- | The name of the Hix environment used to build this job.+ env :: EnvName,++ -- | The package database containing installed packages, corresponding to the set returned by @ghcWithPackages@ in+ -- Nix, with all nonlocal project dependencies.+ -- In production, this points to the dir containing the GHC executables in the Nix store, which Cabal executes to+ -- interact with the database.+ -- In tests, this is a pure set of manually constructed packages.+ ghc :: GhcDb,++ -- | The set of local packages associated with this environment.+ -- Sorted topologically by smart constructor.+ targets :: Targets,++ -- | The names of dependencies associated with this environment.+ deps :: EnvDeps,++ -- | The subset of this environment's remote dependencies whose bounds should be updated.+ query :: NonEmpty MutableDep,++ solverBounds :: Ranges+ }+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Managed/Data/EnvRequest.hs view
@@ -0,0 +1,18 @@+module Hix.Managed.Data.EnvRequest where++import Hix.Managed.Data.EnvContext (EnvContext)+import Hix.Managed.Data.EnvState (EnvState)+import Hix.Managed.Data.Initial (Initial)+import Hix.Managed.Handlers.Build (EnvBuilder)++-- | Resources for an env job.+data EnvRequest =+ EnvRequest {+ -- | For convenience.+ context :: EnvContext,++ builder :: EnvBuilder,++ -- | The state at the beginning of the processing step for this env.+ state :: Initial EnvState+ }
+ lib/Hix/Managed/Data/EnvResult.hs view
@@ -0,0 +1,14 @@+module Hix.Managed.Data.EnvResult where++import Hix.Data.EnvName (EnvName)+import Hix.Managed.Data.EnvState (EnvState)+import Hix.Managed.Data.StageResult (StageSummary)++data EnvResult =+ EnvResult {+ env :: EnvName,+ -- | The final state, which is 'Nothing' for stages that don't interact with it.+ state :: Maybe EnvState,+ summaries :: NonEmpty StageSummary+ }+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Managed/Data/EnvState.hs view
@@ -0,0 +1,36 @@+module Hix.Managed.Data.EnvState where++import Distribution.Pretty (Pretty (pretty))+import GHC.Generics (Generically (Generically))+import Text.PrettyPrint (hang, ($+$))++import Hix.Data.Overrides (Overrides)+import Hix.Managed.Data.Diff (BoundsChange, VersionChange)+import Hix.Managed.Data.Mutable (MutableDeps)++-- | All the @*Diff@ fields are initialized as @DiffAbsent@ if there is no entry in the managed state, using the flake+-- config's packages to determine the set of dependencies.+data EnvState =+ EnvState {+ -- | Bounds can differ from the lowest or highest version that was tested.+ -- As of now, this only matters for Bump, which uses the next-greater major version as upper bound.+ bounds :: MutableDeps BoundsChange,++ -- | The precise version determined to be working for the env's target bound.+ versions :: MutableDeps VersionChange,++ -- | Overrides from the persisted state may be empty initially.+ overrides :: Overrides,++ -- | Copied from 'versions' at the end of an env flow whenever the final value for a dep is @DiffAdded@.+ initial :: MutableDeps VersionChange+ }+ deriving stock (Eq, Show, Generic)+ deriving (Semigroup, Monoid) via (Generically EnvState)++instance Pretty EnvState where+ pretty EnvState {..} =+ hang "bounds:" 2 (pretty bounds) $+$+ hang "versions:" 2 (pretty versions) $+$+ hang "overrides:" 2 (pretty overrides) $+$+ hang "initial:" 2 (pretty initial)
+ lib/Hix/Managed/Data/Envs.hs view
@@ -0,0 +1,19 @@+module Hix.Managed.Data.Envs where++import Data.Aeson (FromJSON)+import Distribution.Pretty (Pretty (pretty))+import GHC.Exts (IsList)++import Hix.Class.EncodeNix (EncodeNix)+import Hix.Class.Map (LookupMonoid, NMap, nPretty1)+import Hix.Data.EnvName (EnvName)++newtype Envs a =+ Envs (Map EnvName a)+ deriving stock (Eq, Show, Generic)+ deriving newtype (FromJSON, Semigroup, Monoid, IsList, EncodeNix)++instance NMap (Envs a) EnvName a LookupMonoid where++instance Pretty a => Pretty (Envs a) where+ pretty = nPretty1
+ lib/Hix/Managed/Data/Initial.hs view
@@ -0,0 +1,14 @@+module Hix.Managed.Data.Initial where++import Data.Aeson (FromJSON, ToJSON)+import Distribution.Pretty (Pretty (pretty))++import Hix.Class.EncodeNix (EncodeNix)++newtype Initial a =+ Initial a+ deriving stock (Eq, Show, Generic, Functor)+ deriving newtype (Semigroup, Monoid, FromJSON, ToJSON, EncodeNix)++instance Pretty a => Pretty (Initial a) where+ pretty (Initial a) = pretty a
+ lib/Hix/Managed/Data/Lower.hs view
@@ -0,0 +1,14 @@+module Hix.Managed.Data.Lower where++import Distribution.Pretty (Pretty (pretty))++import Hix.Data.Version (Major, prettyMajors)++data Lower =+ Lower {+ majors :: NonEmpty Major+ }+ deriving stock (Eq, Show, Generic)++instance Pretty Lower where+ pretty Lower {majors} = prettyMajors majors
+ lib/Hix/Managed/Data/LowerConfig.hs view
@@ -0,0 +1,24 @@+module Hix.Managed.Data.LowerConfig where++import qualified Hix.Data.Options+import Hix.Data.Options (LowerOptions (LowerOptions))++data LowerConfig =+ LowerConfig {+ initOnly :: Bool,+ reset :: Bool,+ stabilize :: Bool+ }+ deriving stock (Eq, Show, Generic)++lowerConfig :: LowerOptions -> LowerConfig+lowerConfig LowerOptions {..} =+ LowerConfig {..}++instance Default LowerConfig where+ def =+ LowerConfig {+ initOnly = False,+ reset = False,+ stabilize = False+ }
+ lib/Hix/Managed/Data/ManagedPackage.hs view
@@ -0,0 +1,40 @@+module Hix.Managed.Data.ManagedPackage where++import Distribution.Pretty (Pretty (pretty))+import Text.PrettyPrint (hang, ($+$))++import Hix.Class.Map (nTo, nTransform)+import Hix.Data.Bounds (Ranges)+import qualified Hix.Data.Dep+import Hix.Data.Dep (Dep (Dep))+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.PackageName (LocalPackage (LocalPackage), localPackageName)+import Hix.Data.Version (Version)+import Hix.Managed.Data.Mutable (LocalRanges, MutableRanges, depName)++data ManagedPackage =+ ManagedPackage {+ package :: LocalPackage,+ version :: Version,+ local :: LocalRanges,+ mutable :: MutableRanges+ }+ deriving stock (Eq, Show, Generic)++instance Pretty ManagedPackage where+ pretty ManagedPackage {..} =+ hang (pretty package) 2 (pretty local $+$ pretty mutable)++ranges :: ManagedPackage -> Ranges+ranges ManagedPackage {local, mutable} =+ nTransform (\ k v -> (localPackageName k, v)) local <>+ nTransform (\ k v -> (depName k, v)) mutable++packageId :: ManagedPackage -> PackageId+packageId ManagedPackage {package = LocalPackage name, version} =+ PackageId {..}++deps :: ManagedPackage -> [Dep]+deps mp =+ nTo (ranges mp) \ package version -> Dep {..}
+ lib/Hix/Managed/Data/ManagedPackageProto.hs view
@@ -0,0 +1,44 @@+module Hix.Managed.Data.ManagedPackageProto where++import Data.Aeson (FromJSON (parseJSON), withObject, (.:))+import Data.List.Extra (nubOrdOn)+import qualified Data.Map.Strict as Map+import Distribution.Pretty (Pretty (pretty))+import Text.PrettyPrint (brackets, (<+>))++import Hix.Class.Map (nFromList)+import qualified Hix.Data.Dep+import Hix.Data.Dep (Dep)+import Hix.Data.Json (jsonParsec)+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.PackageName (LocalPackage (LocalPackage))+import Hix.Data.Version (Version)+import Hix.Managed.Data.Packages (Packages)+import Hix.Pretty (prettyL)++data ManagedPackageProto =+ ManagedPackageProto {+ name :: LocalPackage,+ version :: Version,+ deps :: [Dep]+ }+ deriving stock (Eq, Show, Generic)++instance Pretty ManagedPackageProto where+ pretty ManagedPackageProto {..} = pretty PackageId {name = coerce name, version} <+> brackets (prettyL deps)++instance FromJSON ManagedPackageProto where+ parseJSON =+ withObject "ManagedPackageProto" \ o -> do+ name <- o .: "name"+ version <- jsonParsec <$> o .: "version"+ deps <- nubOrdOn (.package) <$> o .: "deps"+ pure ManagedPackageProto {..}++managedPackages :: Map (LocalPackage, Version) [Dep] -> Packages ManagedPackageProto+managedPackages spec =+ nFromList (pkg <$> Map.toList spec)+ where+ pkg ((name, version), deps) =+ (name, ManagedPackageProto {name, version, deps})
+ lib/Hix/Managed/Data/Mutable.hs view
@@ -0,0 +1,251 @@+module Hix.Managed.Data.Mutable (+ MutableDep (MutableDep),+ MutableDeps,+ unsafeMutableDep,+ depName,+ isMutableDep,+ MutableVersions,+ MutableBounds,+ MutableRanges,+ LocalRanges,+ mutRestrictKeys,+ mutLookup,+ mutReplace,+ mutReplaceTargets,+ mutUpdate,+ mutUpdateTargets,+ classifyPackageDep,+ mutRelax,+ mutUpdatePartial,+ mutReplacePartial,+ addBuildVersions,+ mutFromSet,+ mutRelaxVersions,+) where++import Data.Aeson (ToJSON, ToJSONKey)+import qualified Data.Set as Set+import Distribution.Pretty (Pretty (pretty))+import Exon (ToSegment (toSegment))+import GHC.Exts (IsList)++import Hix.Class.EncodeNix (EncodeNix (encodeNix), EncodeNixKey)+import Hix.Class.Map (+ LookupMaybe,+ NLookup,+ NMap,+ nAmend,+ nFromKeys,+ nMap,+ nMapKeys,+ nPretty,+ nPrettyWith,+ nRestrictKeys,+ nTransformMaybe,+ (!!),+ )+import qualified Hix.Data.Dep+import Hix.Data.Dep (Dep (Dep))+import Hix.Data.PackageName (LocalPackage (LocalPackage), PackageName)+import Hix.Data.Version (Version, VersionRange, Versions)+import Hix.Data.VersionBounds (VersionBounds)+import Hix.Managed.Data.Packages (Deps, Packages)+import Hix.Managed.Data.Targets (Targets, overTargets)++newtype MutableDep =+ UnsafeMutableDep PackageName+ deriving stock (Eq, Show)+ deriving newtype (Ord, ToJSON, ToJSONKey, Pretty, EncodeNixKey)++pattern MutableDep :: PackageName -> MutableDep+pattern MutableDep name <- UnsafeMutableDep name++{-# complete MutableDep #-}++unsafeMutableDep :: PackageName -> MutableDep+unsafeMutableDep = UnsafeMutableDep++depName :: MutableDep -> PackageName+depName (UnsafeMutableDep name) = name++isMutableDep :: Set MutableDep -> PackageName -> Bool+isMutableDep mut p = Set.member (UnsafeMutableDep p) mut++instance IsString a => ToSegment MutableDep a where+ toSegment (UnsafeMutableDep name) = toSegment name++newtype MutableDeps a =+ MutableDeps (Map MutableDep a)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, EncodeNix)++instance NMap (MutableDeps a) MutableDep a LookupMaybe where++instance Pretty a => Pretty (MutableDeps a) where+ pretty = nPretty++newtype MutableVersions =+ MutableVersions (Map MutableDep (Maybe Version))+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList)++instance NMap MutableVersions MutableDep (Maybe Version) LookupMaybe where++instance Pretty MutableVersions where+ pretty = nPrettyWith (maybe "[missing]" pretty)++instance EncodeNix MutableVersions where+ encodeNix = encodeNix . mutRelaxVersions++newtype MutableBounds =+ MutableBounds (Map MutableDep VersionBounds)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList, EncodeNix, ToJSON)++instance NMap MutableBounds MutableDep VersionBounds LookupMaybe where++instance Pretty MutableBounds where+ pretty = nPretty++newtype LocalBounds =+ LocalBounds (Map LocalPackage VersionBounds)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList, EncodeNix)++instance NMap LocalBounds LocalPackage VersionBounds LookupMaybe where++instance Pretty LocalBounds where+ pretty = nPretty++newtype MutableRanges =+ MutableRanges (Map MutableDep VersionRange)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList)++instance NMap MutableRanges MutableDep VersionRange LookupMaybe where++instance Pretty MutableRanges where+ pretty = nPretty++newtype LocalRanges =+ LocalRanges (Map LocalPackage VersionRange)+ deriving stock (Eq, Show, Generic)+ deriving newtype (Semigroup, Monoid, IsList)++instance NMap LocalRanges LocalPackage VersionRange LookupMaybe where++instance Pretty LocalRanges where+ pretty = nPretty++mutLookup ::+ NMap map MutableDep v sort =>+ NLookup sort MutableDep v l =>+ PackageName ->+ map ->+ l+mutLookup k m =+ m !! (UnsafeMutableDep k)++mutRestrictKeys ::+ NMap map MutableDep v sort =>+ Set PackageName ->+ map ->+ map+mutRestrictKeys keys =+ nRestrictKeys (Set.fromList (UnsafeMutableDep <$> Set.toList keys))++mutReplace ::+ NMap map MutableDep v sort =>+ map ->+ map ->+ map+mutReplace =+ nAmend \ new _ -> new++mutReplaceTargets ::+ NMap map MutableDep v sort =>+ Targets ->+ map ->+ Packages map ->+ Packages map+mutReplaceTargets targets new =+ overTargets targets (mutReplace new)++mutUpdate ::+ NMap map1 MutableDep v1 s1 =>+ NMap map2 MutableDep v2 s2 =>+ (v1 -> v2 -> v2) ->+ map1 ->+ map2 ->+ map2+mutUpdate =+ nAmend++mutUpdateTargets ::+ NMap map1 MutableDep v1 s1 =>+ NMap map2 MutableDep v2 s2 =>+ Targets ->+ (v1 -> v2 -> v2) ->+ map1 ->+ Packages map2 ->+ Packages map2+mutUpdateTargets targets f new =+ overTargets targets (mutUpdate f new)++mutRelax ::+ NMap map1 MutableDep v s1 =>+ NMap map2 PackageName v s2 =>+ map1 ->+ map2+mutRelax =+ nMapKeys depName++mutRelaxVersions ::+ MutableVersions ->+ Versions+mutRelaxVersions =+ nTransformMaybe \ dep -> fmap (depName dep,)++-- | Update a MutableDep map with a PackageName map, only where the original is defined.+mutUpdatePartial ::+ ∀ map1 map2 v1 v2 s1 s2 .+ NMap map1 PackageName v1 s1 =>+ NMap map2 MutableDep v2 s2 =>+ (v1 -> v2 -> v2) ->+ map1 ->+ map2 ->+ map2+mutUpdatePartial f map1 map2 =+ nAmend f (nMapKeys UnsafeMutableDep map1 :: MutableDeps v1) map2++-- | Replace entries in a MutableDep map with those from a PackageName map, only where the original is defined.+mutReplacePartial ::+ ∀ map1 map2 v1 s1 s2 .+ NMap map1 PackageName v1 s1 =>+ NMap map2 MutableDep v1 s2 =>+ map1 ->+ map2 ->+ map2+mutReplacePartial =+ mutUpdatePartial const++addBuildVersions :: Versions -> MutableVersions -> MutableVersions+addBuildVersions versions =+ mutReplacePartial (nMap Just versions :: Deps (Maybe Version))++classifyPackageDep :: Set LocalPackage -> Dep -> Either (LocalPackage, VersionRange) (MutableDep, VersionRange)+classifyPackageDep locals Dep {package, version}+ | Set.member localName locals+ = Left (localName, version)+ | otherwise+ = Right (UnsafeMutableDep package, version)+ where+ localName = LocalPackage package++mutFromSet ::+ NMap map MutableDep v sort =>+ Set MutableDep ->+ (MutableDep -> v) ->+ map+mutFromSet =+ nFromKeys
+ lib/Hix/Managed/Data/MutableId.hs view
@@ -0,0 +1,28 @@+module Hix.Managed.Data.MutableId where++import Data.Aeson (ToJSON (toJSON), object, (.=))+import Distribution.Pretty (Pretty (pretty))+import Distribution.Version (Version)++import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Managed.Data.Mutable (MutableDep (MutableDep))+import Hix.Pretty (showP)++data MutableId =+ MutableId {+ name :: MutableDep,+ version :: Version+ }+ deriving stock (Eq, Show, Generic)++toPackageId :: MutableId -> PackageId+toPackageId MutableId {name = MutableDep name, version} =+ PackageId {name, version}++instance Pretty MutableId where+ pretty = pretty . toPackageId++instance ToJSON MutableId where+ toJSON MutableId {..} =+ object ["name" .= toJSON name, "version" .= toJSON (showP version :: Text)]
+ lib/Hix/Managed/Data/Mutation.hs view
@@ -0,0 +1,61 @@+module Hix.Managed.Data.Mutation where++import Distribution.Pretty (Pretty (pretty))+import qualified Text.PrettyPrint as PrettyPrint+import Text.PrettyPrint (parens, (<+>))++import Hix.Data.Version (Version)+import Hix.Data.VersionBounds (VersionBounds)+import Hix.Managed.Cabal.Data.SolverState (SolverState)+import Hix.Managed.Data.Mutable (MutableDep)+import Hix.Managed.Data.MutableId (MutableId)+import Hix.Managed.Data.MutationState (MutationState)+import Hix.Pretty (prettyText, showP)++data DepMutation a =+ DepMutation {+ package :: MutableDep,+ retract :: Bool,+ mutation :: a+ }+ deriving stock (Eq, Show, Generic)++instance Pretty a => Pretty (DepMutation a) where+ pretty DepMutation {package, mutation, retract} =+ pretty package PrettyPrint.<> ":" <+> pretty mutation <+> parens retext+ where+ retext | retract = "retract"+ | otherwise = "extend"++data BuildMutation =+ BuildMutation {+ description :: Text,+ solverState :: SolverState,+ updateBound :: Version -> VersionBounds -> VersionBounds+ }+ deriving stock (Generic)++data MutationResult s =+ MutationSuccess { candidate :: MutableId, changed :: Bool, state :: MutationState, ext :: s }+ |+ MutationKeep+ |+ MutationFailed+ deriving stock (Eq, Show, Generic)++data FailedMutation =+ FailedMutation {+ package :: MutableDep,+ mutation :: Text+ }+ deriving stock (Eq, Show, Generic)++instance Pretty FailedMutation where+ pretty FailedMutation {package, mutation} = pretty package <+> prettyText mutation++failedMutation ::+ Pretty a =>+ DepMutation a ->+ FailedMutation+failedMutation DepMutation {package, mutation} =+ FailedMutation {package, mutation = showP mutation}
+ lib/Hix/Managed/Data/MutationMode.hs view
@@ -0,0 +1,7 @@+module Hix.Managed.Data.MutationMode where++data MutationMode =+ MutationMode {+ foo :: Int+ }+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Managed/Data/MutationState.hs view
@@ -0,0 +1,40 @@+module Hix.Managed.Data.MutationState where++import Data.Map.Merge.Strict (dropMissing, mapMaybeMissing, zipWithMatched)+import Distribution.Pretty (Pretty (pretty))+import GHC.Generics (Generically (Generically))+import Text.PrettyPrint (hang, ($+$))++import Hix.Class.Map (nMerge)+import Hix.Data.Overrides (Overrides)+import Hix.Data.Version (Version)+import Hix.Data.VersionBounds (VersionBounds)+import Hix.Managed.Data.Mutable (MutableBounds, MutableVersions)++data MutationState =+ MutationState {+ bounds :: MutableBounds,+ versions :: MutableVersions,+ overrides :: Overrides,+ initial :: MutableVersions+ }+ deriving stock (Eq, Show, Generic)+ deriving (Semigroup, Monoid) via (Generically MutationState)++instance Pretty MutationState where+ pretty MutationState {..} =+ hang "bounds:" 2 (pretty bounds) $+$+ hang "versions:" 2 (pretty versions) $+$+ hang "overrides:" 2 (pretty overrides) $+$+ hang "initial:" 2 (pretty initial)++updateBoundsWith :: (Version -> VersionBounds -> VersionBounds) -> MutationState -> MutationState+updateBoundsWith update MutationState {bounds, versions, ..} =+ MutationState {+ bounds = nMerge addBound dropMissing updateBound versions bounds,+ versions,+ ..+ }+ where+ addBound = mapMaybeMissing \ _ -> fmap (flip update mempty)+ updateBound = zipWithMatched \ _ -> maybe id update
+ lib/Hix/Managed/Data/Packages.hs view
@@ -0,0 +1,29 @@+module Hix.Managed.Data.Packages where++import Data.Aeson (FromJSON)+import Distribution.Pretty (Pretty (pretty))+import GHC.Exts (IsList)++import Hix.Class.EncodeNix (EncodeNix)+import Hix.Class.Map (LookupMaybe, LookupMonoid, NMap, nPretty, nPretty1)+import Hix.Data.PackageName (LocalPackage, PackageName)++newtype Packages a =+ Packages (Map LocalPackage a)+ deriving stock (Eq, Show, Generic)+ deriving newtype (FromJSON, Semigroup, Monoid, IsList, EncodeNix)++instance NMap (Packages a) LocalPackage a LookupMonoid where++instance Pretty a => Pretty (Packages a) where+ pretty = nPretty1++newtype Deps a =+ Deps (Map PackageName a)+ deriving stock (Eq, Show, Generic)+ deriving newtype (FromJSON, Semigroup, Monoid, IsList, EncodeNix)++instance NMap (Deps a) PackageName a LookupMaybe where++instance Pretty a => Pretty (Deps a) where+ pretty = nPretty
+ lib/Hix/Managed/Data/ProcessState.hs view
@@ -0,0 +1,52 @@+module Hix.Managed.Data.ProcessState where++import Control.Lens ((%~))+import Data.Generics.Labels ()+import Distribution.Pretty (Pretty (pretty))+import Distribution.Version (removeLowerBound)+import Text.PrettyPrint (hang, ($+$))++import Hix.Class.Map (nAmend, nMap)+import Hix.Data.VersionBounds (majorRange)+import qualified Hix.Managed.Data.ManagedPackage+import Hix.Managed.Data.ManagedPackage (ManagedPackage (ManagedPackage))+import Hix.Managed.Data.Mutable (MutableBounds)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Data.ProjectContext+import Hix.Managed.Data.ProjectContext (ProjectContext)+import qualified Hix.Managed.Data.ProjectState+import Hix.Managed.Data.ProjectState (ProjectState)++data ProcessState =+ ProcessState {+ packages :: Packages ManagedPackage,+ state :: ProjectState+ }+ deriving stock (Eq, Show, Generic)++instance Pretty ProcessState where+ pretty ProcessState {..} =+ hang "packages:" 2 (pretty packages) $+$ hang "state:" 2 (pretty state)++-- TODO Check that this is sound.+-- We simply replace the deps in the packages with the updated bounds.+-- These are used only for the installed-package-db, so the solver can propagate bounds from local deps.+-- However, before conversion from ManagedPackageProto, these deps are completely unrelated, and supposed to be used as+-- additional solver bounds.+-- So we have to extract those into a separate bin at that point, and wipe the bounds when constructing ManagedPackage,+-- and then replacing them by the managed bounds if they already exist.+updateManagedPackages :: Packages MutableBounds -> Packages ManagedPackage -> Packages ManagedPackage+updateManagedPackages =+ nAmend \ bounds ManagedPackage {..} -> ManagedPackage {mutable = nMap majorRange bounds, ..}++removeLowerBounds :: ManagedPackage -> ManagedPackage+removeLowerBounds =+ #mutable %~ nMap removeLowerBound++-- | We remove lower bounds because they are likely to interfere with LowerInit, but upper bounds are useful.+initProcessState :: ProjectContext -> ProcessState+initProcessState context =+ ProcessState {+ packages = updateManagedPackages context.state.bounds (nMap removeLowerBounds context.packages),+ state = context.state+ }
+ lib/Hix/Managed/Data/ProjectContext.hs view
@@ -0,0 +1,17 @@+module Hix.Managed.Data.ProjectContext where++import Hix.Data.EnvName (EnvName)+import Hix.Managed.Data.BuildConfig (BuildConfig)+import Hix.Managed.Data.EnvContext (EnvContext)+import Hix.Managed.Data.ManagedPackage (ManagedPackage)+import Hix.Managed.Data.Packages (Packages)+import Hix.Managed.Data.ProjectState (ProjectState)++data ProjectContext =+ ProjectContext {+ build :: BuildConfig,+ state :: ProjectState,+ packages :: Packages ManagedPackage,+ envs :: NonEmpty (Either EnvName EnvContext)+ }+ deriving stock (Eq, Show)
+ lib/Hix/Managed/Data/ProjectContextProto.hs view
@@ -0,0 +1,29 @@+module Hix.Managed.Data.ProjectContextProto where++import Data.Aeson (FromJSON)++import Hix.Managed.Data.EnvConfig (EnvConfig)+import Hix.Managed.Data.Envs (Envs)+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto)+import Hix.Managed.Data.Packages (Packages)+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto)+import Hix.Managed.Handlers.Build (BuildOutputsPrefix)++data ProjectContextProto =+ ProjectContextProto {+ packages :: Packages ManagedPackageProto,+ state :: ProjectStateProto,+ envs :: Envs EnvConfig,+ buildOutputsPrefix :: Maybe BuildOutputsPrefix+ }+ deriving stock (Eq, Show, Generic)+ deriving anyclass (FromJSON)++instance Default ProjectContextProto where+ def =+ ProjectContextProto {+ packages = mempty,+ state = def,+ envs = mempty,+ buildOutputsPrefix = Nothing+ }
+ lib/Hix/Managed/Data/ProjectResult.hs view
@@ -0,0 +1,11 @@+module Hix.Managed.Data.ProjectResult where++import Hix.Managed.Data.EnvResult (EnvResult)+import Hix.Managed.Data.ProjectState (ProjectState)++data ProjectResult =+ ProjectResult {+ envs :: NonEmpty EnvResult,+ state :: ProjectState+ }+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Managed/Data/ProjectState.hs view
@@ -0,0 +1,31 @@+module Hix.Managed.Data.ProjectState where++import Distribution.Pretty (Pretty (pretty))+import Text.PrettyPrint (hang, ($+$))++import Hix.Class.EncodeNix (EncodeNix)+import Hix.Data.Overrides (Overrides)+import Hix.Managed.Data.Envs (Envs)+import Hix.Managed.Data.Mutable (MutableBounds, MutableVersions)+import Hix.Managed.Data.Packages (Packages)++data ProjectState =+ ProjectState {+ bounds :: Packages MutableBounds,+ versions :: Envs MutableVersions,+ initial :: Envs MutableVersions,+ overrides :: Envs Overrides,+ resolving :: Bool+ }+ deriving stock (Eq, Show, Generic)+ deriving anyclass (EncodeNix)++instance Pretty ProjectState where+ pretty ProjectState {..} =+ hang "bounds:" 2 (pretty bounds) $+$+ hang "versions:" 2 (pretty versions) $+$+ hang "initial:" 2 (pretty initial) $+$+ hang "overrides:" 2 (pretty overrides)++instance Default ProjectState where+ def = ProjectState {bounds = mempty, versions = mempty, overrides = mempty, initial = mempty, resolving = False}
+ lib/Hix/Managed/Data/ProjectStateProto.hs view
@@ -0,0 +1,50 @@+module Hix.Managed.Data.ProjectStateProto where++import Data.Aeson (FromJSON (parseJSON), withObject, (.:?))+import Distribution.Pretty (Pretty (pretty))+import Text.PrettyPrint (hang, ($+$))++import Hix.Class.EncodeNix (EncodeNix)+import Hix.Data.Bounds (Bounds)+import Hix.Data.Json (foldMissing)+import Hix.Data.Overrides (Overrides)+import Hix.Data.Version (Versions)+import Hix.Managed.Data.Envs (Envs)+import Hix.Managed.Data.Packages (Packages)++data ProjectStateProto =+ ProjectStateProto {+ bounds :: Packages Bounds,+ versions :: Envs Versions,+ overrides :: Envs Overrides,+ initial :: Envs Versions,+ resolving :: Bool+ }+ deriving stock (Eq, Show, Generic)+ deriving anyclass (EncodeNix)++instance Pretty ProjectStateProto where+ pretty ProjectStateProto {..} =+ hang "bounds:" 2 (pretty bounds) $+$+ hang "versions:" 2 (pretty versions) $+$+ hang "overrides:" 2 (pretty overrides) $+$+ hang "initial:" 2 (pretty initial)++instance FromJSON ProjectStateProto where+ parseJSON = withObject "ProjectStateProto" \ o -> do+ bounds <- foldMissing o "bounds"+ versions <- foldMissing o "versions"+ overrides <- foldMissing o "overrides"+ initial <- foldMissing o "initial"+ resolving <- fromMaybe False <$> o .:? "resolving"+ pure ProjectStateProto {..}++instance Default ProjectStateProto where+ def =+ ProjectStateProto {+ bounds = mempty,+ versions = mempty,+ overrides = mempty,+ initial = mempty,+ resolving = False+ }
+ lib/Hix/Managed/Data/Query.hs view
@@ -0,0 +1,15 @@+module Hix.Managed.Data.Query where++import GHC.Exts (IsList)++import Hix.Data.PackageName (PackageName)+import Hix.Managed.Data.QueryDep (QueryDep)++newtype RawQuery =+ RawQuery [PackageName]+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsList)++newtype Query =+ Query (NonEmpty QueryDep)+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Managed/Data/QueryDep.hs view
@@ -0,0 +1,18 @@+module Hix.Managed.Data.QueryDep where++import Hix.Data.Version (Version)+import Hix.Data.VersionBounds (VersionBounds)+import Hix.Managed.Data.Mutable (MutableDep)++-- | A dep that is eligible for being processed, which requires that it is not referring to a project-local package,+-- that it wasn't excluded by CLI options and arbitrary other conditions specific to individual stages.+data QueryDep =+ QueryDep {+ package :: MutableDep,+ -- | Used to constrain the spectrum of candidate versions in some modes.+ bounds :: VersionBounds,+ current :: Maybe Version,+ installed :: Maybe Version,+ override :: Maybe Version+ }+ deriving stock (Eq, Show, Generic)
+ lib/Hix/Managed/Data/StageContext.hs view
@@ -0,0 +1,17 @@+module Hix.Managed.Data.StageContext where++import Hix.Managed.Data.EnvContext (EnvContext)+import Hix.Managed.Data.Initial (Initial)+import Hix.Managed.Data.Mutable (MutableVersions)+import Hix.Managed.Data.MutationState (MutationState)+import Hix.Managed.Data.Query (Query)+import Hix.Managed.Handlers.Build (EnvBuilder)++data StageContext =+ StageContext {+ env :: EnvContext,+ builder :: EnvBuilder,+ state :: Initial MutationState,+ query :: Query,+ initial :: MutableVersions+ }
+ lib/Hix/Managed/Data/StageResult.hs view
@@ -0,0 +1,33 @@+module Hix.Managed.Data.StageResult where++import Hix.Managed.Data.MutableId (MutableId)+import Hix.Managed.Data.Mutation (FailedMutation)+import Hix.Managed.Data.MutationState (MutationState)++data StageFailure =+ FailedPrecondition (NonEmpty Text)+ |+ FailedMutations Text (NonEmpty FailedMutation)+ deriving stock (Eq, Show, Generic)++data StageSummary =+ StageFailure StageFailure+ |+ StageSuccess Text+ |+ StageNoAction (Maybe Text)+ |+ StageReport Text (NonEmpty MutableId)+ deriving stock (Eq, Show, Generic)++data StageResult =+ StageResult {+ summary :: StageSummary,+ state :: Maybe MutationState+ }+ deriving stock (Eq, Show, Generic)++stageFailures :: StageSummary -> [FailedMutation]+stageFailures = \case+ StageFailure (FailedMutations _ mutations) -> toList mutations+ _ -> []
+ lib/Hix/Managed/Data/StageState.hs view
@@ -0,0 +1,55 @@+module Hix.Managed.Data.StageState where++import Hix.Managed.Data.Initial (Initial (Initial))+import Hix.Managed.Data.Mutable (MutableDep)+import qualified Hix.Managed.Data.MutableId+import Hix.Managed.Data.MutableId (MutableId (MutableId))+import Hix.Managed.Data.Mutation (DepMutation)+import Hix.Managed.Data.MutationState (MutationState)++data BuildStatus =+ Success+ |+ Failure+ deriving stock (Eq, Show, Generic)++justSuccess :: a -> BuildStatus -> Maybe a+justSuccess a = \case+ Success -> Just a+ Failure -> Nothing++buildStatus :: Bool -> BuildStatus+buildStatus = \case+ True -> Success+ False -> Failure++data BuildSuccess =+ CandidateBuilt MutableId+ |+ Unmodified MutableDep+ deriving stock (Eq, Show, Generic)++buildSuccessPackage :: BuildSuccess -> MutableDep+buildSuccessPackage = \case+ CandidateBuilt MutableId {name} -> name+ Unmodified name -> name++modifiedCandidates :: [BuildSuccess] -> [MutableId]+modifiedCandidates =+ mapMaybe \case+ CandidateBuilt candidate -> Just candidate+ Unmodified _ -> Nothing++data StageState a s =+ StageState {+ success :: Map MutableDep BuildSuccess,+ failed :: [DepMutation a],+ state :: MutationState,+ iterations :: Natural,+ ext :: s+ }+ deriving stock (Eq, Show)++initStageState :: Initial MutationState -> s -> StageState a s+initStageState (Initial state) ext =+ StageState {success = [], failed = [], iterations = 0, ..}
+ lib/Hix/Managed/Data/StateFileConfig.hs view
@@ -0,0 +1,17 @@+module Hix.Managed.Data.StateFileConfig where++import Path (Abs, Dir, File, Path, Rel, relfile)++data StateFileConfig =+ StateFileConfig {+ file :: Path Rel File,+ projectRoot :: Maybe (Path Abs Dir)+ }+ deriving stock (Eq, Show, Generic)++instance Default StateFileConfig where+ def =+ StateFileConfig {+ file = [relfile|ops/managed.nix|],+ projectRoot = Nothing+ }
+ lib/Hix/Managed/Data/Targets.hs view
@@ -0,0 +1,98 @@+module Hix.Managed.Data.Targets (+ Targets (Targets),+ unsafeTargets,+ getTargets,+ targetsSet,+ singleTarget,+ sortTargets,+ allMTargets,+ overTargets,+) where++import Data.Aeson (FromJSON, FromJSONKey)+import Data.Foldable.Extra (allM)+import Data.Graph (Graph, Vertex, graphFromEdges, reverseTopSort)+import qualified Data.Map.Strict as Map+import qualified Data.Set as Set+import Distribution.Pretty (Pretty)++import Hix.Class.EncodeNix (EncodeNixKey)+import Hix.Class.Map (nGet, nMap, nMapWithKey, nRestrictKeys)+import Hix.Data.PackageName (LocalPackage (LocalPackage))+import Hix.Managed.Data.Packages (Packages)++newtype EnvMember =+ EnvMember LocalPackage+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsString, Ord, FromJSON, FromJSONKey, Pretty, EncodeNixKey)++newtype Targets =+ UnsafeTargets [LocalPackage]+ deriving stock (Eq, Show)++pattern Targets :: [LocalPackage] -> Targets+pattern Targets pkgs <- UnsafeTargets pkgs++{-# complete Targets #-}++unsafeTargets :: [LocalPackage] -> Targets+unsafeTargets = UnsafeTargets++singleTarget :: LocalPackage -> Targets+singleTarget = UnsafeTargets . pure++instance IsString Targets where+ fromString = singleTarget . fromString++getTargets :: Targets -> [LocalPackage]+getTargets (Targets pkgs) = pkgs++targetsSet :: Targets -> Set LocalPackage+targetsSet (Targets targets) =+ Set.fromList targets++graph ::+ Map LocalPackage [LocalPackage] ->+ (Graph, Vertex -> (LocalPackage, LocalPackage, [LocalPackage]), LocalPackage -> Maybe Vertex)+graph deps =+ graphFromEdges keyAssoc+ where+ keyAssoc = Map.toList deps <&> \ (p, ds) -> (p, p, ds)++onlyFrom :: Set LocalPackage -> [LocalPackage] -> [LocalPackage]+onlyFrom targets deps =+ mapMaybe isTarget deps+ where+ isTarget = \case+ dep | Set.member dep targets -> Just dep+ _ -> Nothing++sortTargets ::+ Packages [LocalPackage] ->+ [LocalPackage] ->+ Targets+sortTargets deps targets =+ UnsafeTargets (reverseTopSort g <&> \ v -> let (n, _, _) = get v in n)+ where+ (g, get, _) = graph (nGet simple)+ simple :: Packages [LocalPackage]+ simple = nMap (onlyFrom targetSet) (nRestrictKeys targetSet deps)+ targetSet = Set.fromList targets++allMTargets ::+ Monad m =>+ (LocalPackage -> m Bool) ->+ Targets ->+ m Bool+allMTargets f (Targets targets) =+ allM f targets++overTargets :: Targets -> (a -> a) -> Packages a -> Packages a+overTargets (targetsSet -> targets) f =+ nMapWithKey checked+ where+ checked package a+ | Set.member package targets+ = f a+ | otherwise+ = a
+ lib/Hix/Managed/Diff.hs view
@@ -0,0 +1,143 @@+module Hix.Managed.Diff where++import Hix.Class.Map (NMap, nAmend, nMap)+import Hix.Data.Version (Version)+import qualified Hix.Data.VersionBounds+import Hix.Data.VersionBounds (anyBounds, VersionBounds)+import Hix.Managed.Data.Diff (BoundsChange, BoundsDiffDetail (..), Change (..), Diff (..), VersionChange)+import Hix.Managed.Data.Mutable (MutableBounds, MutableDep, MutableDeps, MutableVersions)+import Hix.These (maybeThese)++diffOriginal :: Diff d a -> Maybe a+diffOriginal = \case+ DiffChanged original _ _ -> Just original+ _ -> Nothing++changeOriginal :: Change d a -> Maybe a+changeOriginal = \case+ Unchanged original -> original+ Changed d -> diffOriginal d++reifyChangeWith :: b -> (a -> b) -> Change d a -> b+reifyChangeWith absent f = \case+ Unchanged Nothing -> absent+ Unchanged (Just a) -> f a+ Changed (DiffAdded a) -> f a+ Changed (DiffChanged _ a _) -> f a++reifyChange :: a -> Change d a -> a+reifyChange absent = reifyChangeWith absent id++reifyChangeMaybe :: Change d a -> Maybe a+reifyChangeMaybe = reifyChangeWith Nothing Just++reifyBoundsChangeMaybe :: BoundsChange -> Maybe VersionBounds+reifyBoundsChangeMaybe = reifyChangeMaybe++reifyBoundsChange :: BoundsChange -> VersionBounds+reifyBoundsChange = reifyChange anyBounds++reifyBoundsChanges :: MutableDeps BoundsChange -> MutableBounds+reifyBoundsChanges = nMap reifyBoundsChange++reifyVersionChange :: VersionChange -> Maybe Version+reifyVersionChange = reifyChangeMaybe++reifyVersionChanges :: MutableDeps VersionChange -> MutableVersions+reifyVersionChanges = nMap reifyVersionChange++applyVersionChange :: VersionChange -> Maybe Version -> Maybe Version+applyVersionChange d _ = reifyVersionChange d++applyBoundsChange :: BoundsChange -> VersionBounds -> VersionBounds+applyBoundsChange d old =+ fromMaybe old (reifyBoundsChangeMaybe d)++diff ::+ (a -> a -> Maybe d) ->+ a ->+ a ->+ Change d a+diff mkDetail original new =+ case mkDetail original new of+ Just detail -> Changed (DiffChanged original new detail)+ Nothing -> Unchanged (Just original)++diffMaybe ::+ (a -> a -> Maybe d) ->+ Maybe a ->+ Maybe a ->+ Change d a+diffMaybe mkDetail original new =+ case (original, new) of+ (Just o, Just n) -> diff mkDetail o n+ (Just o, Nothing) -> Unchanged (Just o)+ (Nothing, Just n) -> Changed (DiffAdded n)+ (Nothing, Nothing) -> Unchanged Nothing++versionDiffDetail :: Version -> Version -> Maybe ()+versionDiffDetail original new+ | original == new+ = Nothing+ | otherwise+ = Just ()++versionChange :: Maybe Version -> Maybe Version -> VersionChange+versionChange = diffMaybe versionDiffDetail++versionDiff :: Maybe Version -> Maybe Version -> Maybe (Diff () Version)+versionDiff original new =+ case versionChange original new of+ Changed d -> Just d+ Unchanged _ -> Nothing++boundsDiffDetail :: VersionBounds -> VersionBounds -> Maybe BoundsDiffDetail+boundsDiffDetail original new =+ BoundsDiffDetail <$> maybeThese diffL diffU+ where+ diffL = versionDiff original.lower combined.lower+ diffU = versionDiff original.upper combined.upper+ combined = new <> original++boundsChange :: VersionBounds -> VersionBounds -> BoundsChange+boundsChange = diff boundsDiffDetail++updateVersionChange :: Version -> VersionChange -> VersionChange+updateVersionChange new d =+ diffMaybe versionDiffDetail (changeOriginal d) (Just new)++-- | We never want to remove any bounds, but mutations only return the bound they have targeted, so we need to fall back+-- to the original bounds when updating.+updateBoundsChange :: VersionBounds -> BoundsChange -> BoundsChange+updateBoundsChange new d =+ diffMaybe boundsDiffDetail original (Just combined)+ where+ (original, combined) = case changeOriginal d of+ Just o -> (Just o, new <> o)+ Nothing -> (Nothing, new)++updateVersionChanges ::+ NMap vmap MutableDep (Maybe Version) s1 =>+ NMap map MutableDep VersionChange s2 =>+ vmap ->+ map ->+ map+updateVersionChanges =+ nAmend (maybe id updateVersionChange)++updateBoundsChanges ::+ NMap vmap MutableDep VersionBounds s1 =>+ NMap map MutableDep BoundsChange s2 =>+ vmap ->+ map ->+ map+updateBoundsChanges =+ nAmend updateBoundsChange++initChanges ::+ NMap map1 k (Maybe v1) s1 =>+ NMap map2 k (Change d v1) s2 =>+ map1 ->+ map2+initChanges =+ nMap Unchanged
+ lib/Hix/Managed/EnvContext.hs view
@@ -0,0 +1,68 @@+module Hix.Managed.EnvContext where++import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Set as Set+import Exon (exon)++import Hix.Class.Map (nKeysSet, nMapWithKey)+import Hix.Data.EnvName (EnvName)+import Hix.Data.Monad (M)+import qualified Hix.Data.Options+import Hix.Data.Options (ProjectOptions)+import Hix.Data.PackageName (LocalPackage)+import qualified Hix.Managed.Data.EnvConfig+import Hix.Managed.Data.EnvConfig (EnvConfig)+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext (EnvContext), EnvDeps (EnvDeps))+import Hix.Managed.Data.Envs (Envs)+import Hix.Managed.Data.ManagedPackage (ManagedPackage)+import Hix.Managed.Data.Mutable (MutableDep, mutRelax)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.ManagedPackage as ManagedPackage+import Hix.Monad (clientError)+import Hix.Pretty (showPL)++unknownTargets :: EnvName -> NonEmpty LocalPackage -> M ()+unknownTargets env missing =+ clientError msg+ where+ msg =+ [exon|The flake config for '##{env}' references #{number} in its targets that #{verb} present|]+ <>+ [exon| in the configuration: #{showPL (toList missing)}|]+ (number, verb) | [_] <- missing = ("a package", "isn't")+ | otherwise = ("several packages", "aren't")++envContext ::+ ProjectOptions ->+ Packages ManagedPackage ->+ Maybe (NonEmpty MutableDep) ->+ EnvName ->+ EnvConfig ->+ Either EnvDeps EnvContext+envContext opts packages querySpec env envConfig =+ maybeToRight deps (create <$> nonEmpty envQuery)+ where+ create query = EnvContext {ghc = envConfig.ghc, query, deps, ..}++ deps = EnvDeps {local, mutable}++ solverBounds | opts.mergeBounds = mutRelax mutableDeps+ | otherwise = mempty++ envQuery = maybe (toList mutable) (NonEmpty.filter (flip Set.member mutable)) querySpec++ local = nKeysSet localDeps++ mutable = nKeysSet mutableDeps++ (targets, localDeps, mutableDeps) = ManagedPackage.forTargets packages envConfig.targets++envContexts ::+ ProjectOptions ->+ Packages ManagedPackage ->+ Envs EnvConfig ->+ Maybe (NonEmpty MutableDep) ->+ M (Envs (Either EnvDeps EnvContext))+envContexts opts packages envConfigs query = do+ pure (nMapWithKey (envContext opts packages query) envConfigs)
+ lib/Hix/Managed/EnvRequest.hs view
@@ -0,0 +1,77 @@+module Hix.Managed.EnvRequest where++import Control.Lens ((%~))+import Distribution.Pretty (pretty)+import Exon (exon)++import Hix.Class.Map (nFlatten, nMap, nRestrictKeys, (!!))+import Hix.Data.EnvName (EnvName)+import Hix.Data.Monad (M)+import Hix.Data.VersionBounds (majorRange)+import qualified Hix.Log as Log+import Hix.Managed.Data.Diff (Change (Unchanged))+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext)+import qualified Hix.Managed.Data.EnvRequest+import Hix.Managed.Data.EnvRequest (EnvRequest (EnvRequest))+import qualified Hix.Managed.Data.EnvResult+import Hix.Managed.Data.EnvResult (EnvResult)+import qualified Hix.Managed.Data.EnvState+import Hix.Managed.Data.EnvState (EnvState (EnvState))+import Hix.Managed.Data.Initial (Initial (Initial))+import Hix.Managed.Data.Mutable (mutReplace)+import qualified Hix.Managed.Data.ProcessState+import Hix.Managed.Data.ProcessState (ProcessState (ProcessState))+import qualified Hix.Managed.Data.ProjectState+import Hix.Managed.Data.ProjectState (ProjectState)+import Hix.Managed.Data.Targets (overTargets, targetsSet)+import Hix.Managed.Diff (initChanges, reifyBoundsChange)+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (BuildHandlers, Builder, runBuilder)+import Hix.Managed.UpdateState (projectStateWithEnv)++initialEnvState ::+ EnvContext ->+ ProjectState ->+ Initial EnvState+initialEnvState context projectState =+ Initial EnvState {..}+ where+ bounds = nFlatten (Unchanged . Just) (nRestrictKeys (targetsSet context.targets) projectState.bounds)+ versions = initChanges (projectState.versions !! context.env)+ overrides = projectState.overrides !! context.env+ initial = initChanges (projectState.initial !! context.env)++updateProcessState ::+ EnvContext ->+ Initial EnvState ->+ EnvResult ->+ ProcessState ->+ ProcessState+updateProcessState context (Initial initialState) envResult ProcessState {state = projectState, packages} = do+ ProcessState {+ packages = overTargets context.targets replaceBounds packages,+ state = projectStateWithEnv context final projectState+ }+ where+ replaceBounds = #mutable %~ mutReplace ranges+ ranges = nMap (majorRange . reifyBoundsChange) final.bounds+ final = fromMaybe initialState envResult.state++withEnvRequest ::+ BuildHandlers ->+ ProcessState ->+ EnvContext ->+ Builder ->+ (EnvRequest -> M EnvResult) ->+ M (ProcessState, EnvResult)+withEnvRequest build state context builder use = do+ cabal <- build.cabal state.packages context.ghc+ envResult <- runBuilder builder cabal context initialState \ envBuilder ->+ use EnvRequest {context, builder = envBuilder, state = initialState}+ let newState = updateProcessState context initialState envResult state+ Log.debug [exon|Finished '##{context.env :: EnvName}' with final state:|]+ Log.debugP (pretty newState)+ pure (newState, envResult)+ where+ initialState = initialEnvState context state.state
+ lib/Hix/Managed/EnvResult.hs view
@@ -0,0 +1,122 @@+module Hix.Managed.EnvResult where++import Data.List.Extra (nubSortOn)+import Data.These (These (That, These, This))+import Data.These.Combinators (justHere, justThere)+import GHC.Generics (Generically (Generically))++import Hix.Class.Map (nElems, nZipWithKey)+import Hix.Data.Version (Version)+import Hix.Data.VersionBounds (VersionBounds)+import Hix.Managed.Data.Diff (+ BoundsChange,+ BoundsDiffDetail (BoundsDiffDetail),+ Change (Changed, Unchanged),+ Diff (DiffAdded, DiffChanged),+ VersionChange,+ )+import Hix.Managed.Data.EnvResult (EnvResult (..))+import qualified Hix.Managed.Data.EnvState+import Hix.Managed.Data.Mutable (MutableDep, MutableDeps)+import qualified Hix.Managed.Data.MutableId+import Hix.Managed.Data.MutableId (MutableId (MutableId))+import Hix.Managed.Data.Mutation (FailedMutation)+import Hix.Managed.Data.StageResult (stageFailures)+import Hix.Managed.Diff (diffOriginal, reifyBoundsChange, reifyVersionChange)+import Hix.These (maybeThese)++newtype BoundsModification =+ BoundsModification (These (Maybe Version) (Maybe Version))+ deriving stock (Eq, Show, Generic)++data DepModification =+ DepAdded (Maybe BoundsModification)+ |+ DepUpdated (These Version BoundsModification)+ deriving stock (Eq, Show, Generic)++data DepResultDetail =+ DepModified DepModification+ |+ DepUnmodified+ deriving stock (Eq, Show, Generic)++data DepResult =+ DepResult {+ package :: MutableDep,+ version :: Version,+ bounds :: VersionBounds,+ detail :: DepResultDetail+ }+ deriving stock (Eq, Show, Generic)++depResultId :: DepResult -> MutableId+depResultId DepResult {package, version} =+ MutableId {name = package, version}++depResult :: MutableDep -> VersionChange -> BoundsChange -> Maybe DepResult+depResult package versionChange boundsChange = do+ version <- reifyVersionChange versionChange+ pure DepResult {+ package,+ version,+ bounds = reifyBoundsChange boundsChange,+ detail+ }+ where+ detail = case versionChange of+ Changed (DiffAdded _) -> DepModified (DepAdded boundsUpdate)+ Changed (DiffChanged original _ _) ->+ DepModified (DepUpdated (maybe This (flip These) boundsUpdate original))+ Unchanged _+ | Just b <- boundsUpdate+ -> DepModified (DepUpdated (That b))+ _ -> DepUnmodified++ boundsUpdate = case boundsChange of+ Changed (DiffChanged _ _ (BoundsDiffDetail det)) ->+ BoundsModification <$> maybeThese (diffOriginal <$> justHere det) (diffOriginal <$> justThere det)+ _ -> Nothing++deps :: EnvResult -> [DepResult]+deps EnvResult {state = Nothing} =+ []+deps EnvResult {state = Just state} =+ catMaybes (nElems dv)+ where+ dv :: MutableDeps (Maybe DepResult)+ dv = nZipWithKey depResult state.versions state.bounds++data DepResults =+ DepResults {+ added :: [DepResult],+ updated :: [DepResult],+ unmodified :: [DepResult]+ }+ deriving stock (Eq, Show, Generic)+ deriving (Semigroup, Monoid) via (Generically DepResults)++-- TODO When this is used after merging envs for a report, it should probably combine packages from different lists.+-- If one env updates a package, we don't want to report it as unmodified because there's another env with the same dep.+-- Most likely the output should be env-keyed though, but not sure this is always desirable.+normalizeDepResults :: DepResults -> DepResults+normalizeDepResults DepResults {..} =+ DepResults {added = normalize added, updated = normalize updated, unmodified = normalize unmodified}+ where+ normalize = nubSortOn (.package)++grouped :: EnvResult -> DepResults+grouped result =+ normalizeDepResults DepResults {..}+ where+ (added, updated, unmodified) = foldr (flip step) mempty (deps result)++ step (a, up, un) dep =+ case dep.detail of+ DepModified DepAdded {} -> (dep : a, up, un)+ DepModified DepUpdated {} -> (a, dep : up, un)+ DepUnmodified -> (a, up, dep : un)++failures :: EnvResult -> [FailedMutation]+failures EnvResult {summaries} =+ stageFailures =<< toList summaries
+ lib/Hix/Managed/Flow.hs view
@@ -0,0 +1,144 @@+module Hix.Managed.Flow (+ Flow,+ liftM,+ runStage,+ execStage,+ evalStage,+ runStage_,+ execStatelessStage,+ evalStageState,+ runFlow,+ execFlow,+ evalFlow,+ stageError,+) where++import Control.Lens ((%=))+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.State.Strict (StateT, get, gets, runStateT)+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Text as Text+import Exon (exon)++import Hix.Data.Error (Error (Fatal))+import Hix.Data.Monad (M)+import qualified Hix.Log as Log+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext (EnvContext))+import qualified Hix.Managed.Data.EnvRequest+import Hix.Managed.Data.EnvRequest (EnvRequest (EnvRequest))+import qualified Hix.Managed.Data.EnvResult+import Hix.Managed.Data.EnvResult (EnvResult (EnvResult))+import Hix.Managed.Data.EnvState (EnvState)+import Hix.Managed.Data.Initial (Initial (Initial))+import Hix.Managed.Data.StageContext (StageContext)+import Hix.Managed.Data.StageResult (StageFailure (FailedPrecondition), StageResult (..), StageSummary (StageFailure))+import Hix.Managed.Data.StageState (BuildStatus (Failure, Success))+import Hix.Managed.StageContext (stageContext)+import Hix.Managed.UpdateState (envStateWithMutations)+import Hix.Monad (throwM)++data FlowState =+ FlowState {+ env :: EnvRequest,+ current :: EnvState,+ summaries :: [StageSummary]+ }+ deriving stock (Generic)++type FlowM = StateT FlowState M++newtype Flow x =+ Flow (FlowM x)+ deriving newtype (Functor, Applicative, Monad)++liftM :: M a -> Flow a+liftM = Flow . lift++addResult ::+ StageResult ->+ Flow BuildStatus+addResult StageResult {state, summary} =+ Flow do+ #summaries %= (summary :)+ #current %= maybe id envStateWithMutations state+ pure status+ where+ status = case summary of+ StageFailure _ -> Failure+ _ -> Success++newContext :: Flow StageContext+newContext = do+ FlowState {env, current} <- Flow get+ pure (stageContext env current)++runStage ::+ ∀ o .+ Text ->+ (StageContext -> M (StageResult, o)) ->+ Flow (BuildStatus, o)+runStage description stage = do+ unless (Text.null description) do+ EnvRequest {context = EnvContext {env}} <- Flow (gets (.env))+ liftM (Log.debug [exon|Executing stage '#{description}' for '##{env}'|])+ context <- newContext+ (result, o) <- liftM (stage context)+ status <- addResult result+ pure (status, o)++execStage ::+ Text ->+ (StageContext -> M StageResult) ->+ Flow BuildStatus+execStage description stage =+ fst <$> runStage description (fmap (, ()) . stage)++evalStage ::+ Text ->+ (StageContext -> M (StageResult, o)) ->+ Flow o+evalStage description stage =+ snd <$> runStage description stage++runStage_ ::+ Text ->+ (StageContext -> M StageResult) ->+ Flow ()+runStage_ description stage =+ void (execStage description stage)++execStatelessStage ::+ Text ->+ (StageContext -> M StageSummary) ->+ Flow BuildStatus+execStatelessStage description f = do+ execStage description \ context -> do+ summary <- f context+ pure StageResult {state = Nothing, summary}++stageError :: Text -> Flow ()+stageError msg =+ void (execStatelessStage "" (const (pure (StageFailure (FailedPrecondition [msg])))))++evalStageState :: (EnvState -> StageContext -> a) -> Flow a+evalStageState f = do+ context <- newContext+ state <- Flow (gets (.current))+ pure (f state context)++runFlow :: EnvRequest -> Flow o -> M (o, EnvResult)+runFlow request@EnvRequest {context, state = (Initial initState)} (Flow m) =+ runStateT m FlowState {env = request, current = initState, summaries = []} >>= traverse \case+ FlowState {summaries = h : t, current = finalState} ->+ pure EnvResult {env = context.env, state = Just finalState, summaries = NonEmpty.reverse (h :| t)}+ FlowState {summaries = []} ->+ throwM (Fatal "Executed flow with no stages")++execFlow :: EnvRequest -> Flow () -> M EnvResult+execFlow env m =+ snd <$> runFlow env m++evalFlow :: EnvRequest -> Flow o -> M o+evalFlow env m =+ fst <$> runFlow env m
+ lib/Hix/Managed/Handlers/Build.hs view
@@ -0,0 +1,95 @@+module Hix.Managed.Handlers.Build where++import Data.Aeson (FromJSON)+import Data.IORef (IORef, newIORef)++import Hix.Data.Monad (M)+import Hix.Data.Overrides (Overrides)+import Hix.Data.PackageId (PackageId)+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (Version, Versions)+import Hix.Managed.Cabal.Changes (SolverPlan)+import Hix.Managed.Cabal.Data.Config (GhcDb)+import Hix.Managed.Data.Constraints (EnvConstraints)+import Hix.Managed.Data.EnvContext (EnvContext)+import Hix.Managed.Data.EnvState (EnvState)+import Hix.Managed.Data.Initial (Initial)+import Hix.Managed.Data.ManagedPackage (ManagedPackage)+import Hix.Managed.Data.Packages (Packages)+import Hix.Managed.Data.StageState (BuildStatus (Failure))+import qualified Hix.Managed.Handlers.Cabal as Solve+import qualified Hix.Managed.Handlers.Cabal as Cabal+import Hix.Managed.Handlers.Cabal (CabalHandlers)+import Hix.Managed.Handlers.Hackage (HackageHandlers)+import qualified Hix.Managed.Handlers.Report as Report+import Hix.Managed.Handlers.Report (ReportHandlers)+import qualified Hix.Managed.Handlers.StateFile as StateFileHandlers+import Hix.Managed.Handlers.StateFile (StateFileHandlers)+import Hix.Managed.Overrides (packageOverrides)++newtype BuildOutputsPrefix =+ BuildOutputsPrefix Text+ deriving stock (Eq, Show, Generic)+ deriving newtype (IsString, Ord, FromJSON)++data EnvBuilder =+ EnvBuilder {+ cabal :: CabalHandlers,+ buildWithState :: Versions -> [PackageId] -> M (Overrides, BuildStatus)+ }++data Builder =+ Builder {+ withEnvBuilder :: ∀ a . CabalHandlers -> EnvContext -> Initial EnvState -> (EnvBuilder -> M a) -> M a+ }++runBuilder :: Builder -> CabalHandlers -> EnvContext -> Initial EnvState -> (EnvBuilder -> M a) -> M a+runBuilder Builder {withEnvBuilder} = withEnvBuilder++data BuildHandlers =+ BuildHandlers {+ stateFile :: StateFileHandlers,+ report :: ReportHandlers,+ cabal :: Packages ManagedPackage -> GhcDb -> M CabalHandlers,+ withBuilder :: ∀ a . (Builder -> M a) -> M a,+ versions :: PackageName -> M [Version],+ latestVersion :: PackageName -> M (Maybe Version)+ }++testBuilder :: (Versions -> [PackageId] -> M (Overrides, BuildStatus)) -> (Builder -> M a) -> M a+testBuilder buildWithState use =+ use Builder {withEnvBuilder = \ cabal _ _ useE -> useE EnvBuilder {cabal, buildWithState}}++versionsBuilder :: HackageHandlers -> (Versions -> M BuildStatus) -> (Builder -> M a) -> M a+versionsBuilder hackage build =+ testBuilder \ versions overrideVersions -> do+ overrides <- packageOverrides hackage overrideVersions+ status <- build versions+ pure (overrides, status)++handlersNull :: BuildHandlers+handlersNull =+ BuildHandlers {+ stateFile = StateFileHandlers.handlersNull,+ report = Report.handlersNull,+ cabal = \ _ _ -> pure Solve.handlersNull,+ withBuilder = testBuilder \ _ _ -> pure (mempty, Failure),+ versions = \ _ -> pure [],+ latestVersion = \ _ -> pure Nothing+ }++wrapCabal :: (CabalHandlers -> CabalHandlers) -> BuildHandlers -> BuildHandlers+wrapCabal f BuildHandlers {..} =+ BuildHandlers {cabal = \ p d -> f <$> cabal p d, ..}++logCabal ::+ MonadIO m =>+ BuildHandlers ->+ m (IORef [(EnvConstraints, Maybe SolverPlan)], BuildHandlers)+logCabal handlers = do+ ref <- liftIO (newIORef [])+ pure (ref, wrapCabal (Cabal.logCabal ref) handlers)++data SpecialBuildHandlers =+ TestBumpHandlers+ deriving stock (Eq, Show)
+ lib/Hix/Managed/Handlers/Build/Prod.hs view
@@ -0,0 +1,188 @@+module Hix.Managed.Handlers.Build.Prod where++import Control.Monad.Catch (catch)+import Control.Monad.Trans.Reader (asks)+import Exon (exon)+import Network.HTTP.Client (newManager)+import Network.HTTP.Client.TLS (tlsManagerSettings)+import Path (Abs, Dir, Path, toFilePath)+import Path.IO (copyDirRecur')+import System.IO.Error (IOError)+import System.Process.Typed (+ ExitCode (ExitFailure, ExitSuccess),+ ProcessConfig,+ inherit,+ nullStream,+ proc,+ runProcess,+ setStderr,+ setStdout,+ setWorkingDir,+ )++import Hix.Data.EnvName (EnvName)+import Hix.Data.Error (Error (Fatal))+import qualified Hix.Data.Monad+import Hix.Data.Monad (M (M))+import Hix.Data.Overrides (Overrides)+import Hix.Data.PackageId (PackageId)+import Hix.Data.PackageName (LocalPackage)+import Hix.Data.Version (Versions)+import Hix.Error (pathText)+import Hix.Hackage (latestVersionHackage, versionsHackage)+import qualified Hix.Log as Log+import Hix.Managed.Cabal.Data.Config (CabalConfig)+import Hix.Managed.Data.EnvConfig (EnvConfig)+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext (EnvContext))+import Hix.Managed.Data.EnvState (EnvState)+import Hix.Managed.Data.Envs (Envs)+import Hix.Managed.Data.Initial (Initial)+import Hix.Managed.Data.StageState (BuildStatus, buildStatus)+import qualified Hix.Managed.Data.StateFileConfig+import Hix.Managed.Data.StateFileConfig (StateFileConfig)+import Hix.Managed.Data.Targets (allMTargets)+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (BuildHandlers (..), BuildOutputsPrefix, Builder (Builder), EnvBuilder (EnvBuilder))+import Hix.Managed.Handlers.Cabal (CabalHandlers)+import qualified Hix.Managed.Handlers.Cabal.Prod as CabalHandlers+import Hix.Managed.Handlers.Hackage (HackageHandlers)+import qualified Hix.Managed.Handlers.Hackage.Prod as HackageHandlers+import qualified Hix.Managed.Handlers.Report.Prod as ReportHandlers+import Hix.Managed.Handlers.StateFile (StateFileHandlers)+import qualified Hix.Managed.Handlers.StateFile.Prod as StateFileHandlers+import Hix.Managed.Overrides (packageOverrides)+import Hix.Managed.Path (rootOrCwd)+import Hix.Managed.StateFile (writeBuildStateFor, writeInitialEnvState)+import Hix.Monad (throwM, tryIOM, withTempDir)++data BuilderResources =+ BuilderResources {+ hackage :: HackageHandlers,+ stateFileHandlers :: StateFileHandlers,+ envsConf :: Envs EnvConfig,+ buildOutputsPrefix :: Maybe BuildOutputsPrefix,+ root :: Path Abs Dir+ }++data EnvBuilderResources =+ EnvBuilderResources {+ global :: BuilderResources,+ context :: EnvContext+ }++withTempProject ::+ Maybe (Path Abs Dir) ->+ (Path Abs Dir -> M a) ->+ M a+withTempProject rootOverride use = do+ projectRoot <- rootOrCwd rootOverride+ catch+ do+ withTempDir "managed-build" \ tmpRoot -> do+ copyDirRecur' projectRoot tmpRoot+ use tmpRoot+ \ (err :: IOError) -> throwM (Fatal (show err))++nixProc ::+ Path Abs Dir ->+ [Text] ->+ Text ->+ [Text] ->+ M (ProcessConfig () () ())+nixProc root cmd installable extra = do+ Log.debug [exon|Running nix at '#{pathText root}' with args #{show args}|]+ conf <$> M (asks (.debug))+ where+ conf debug = err debug (setWorkingDir (toFilePath root) (proc "nix" args))++ err = \case+ True -> setStderr inherit+ False -> setStderr nullStream++ args = toString <$> cmd ++ [exon|path:#{".#"}#{installable}|] : extra++buildPackage ::+ Path Abs Dir ->+ EnvName ->+ LocalPackage ->+ M Bool+buildPackage root env target = do+ debug <- M (asks (.debug))+ conf <- nixProc root ["-L", "build"] [exon|env.##{env}.##{target}|] []+ tryIOM (runProcess (err debug conf)) <&> \case+ ExitSuccess -> True+ ExitFailure _ -> False+ where+ err = \case+ True -> setStdout inherit+ False -> id++buildWithState ::+ EnvBuilderResources ->+ Versions ->+ [PackageId] ->+ M (Overrides, BuildStatus)+buildWithState EnvBuilderResources {global, context = context@EnvContext {env, targets}} _ overrideVersions = do+ overrides <- packageOverrides global.hackage overrideVersions+ writeBuildStateFor "current build" global.stateFileHandlers global.root context overrides+ status <- buildStatus <$> allMTargets (buildPackage global.root env) targets+ pure (overrides, status)++-- | This used to have the purpose of reading an updated GHC package db using the current managed state, but this has+-- become obsolete.+--+-- TODO Decide whether to keep this for abstraction purposes.+withEnvBuilder ::+ ∀ a .+ BuilderResources ->+ CabalHandlers ->+ EnvContext ->+ Initial EnvState ->+ (EnvBuilder -> M a) ->+ M a+withEnvBuilder global cabal context initialState use = do+ writeInitialEnvState global.stateFileHandlers global.root context initialState+ use builder+ where+ builder =+ EnvBuilder {+ cabal,+ buildWithState = buildWithState resources+ }++ resources = EnvBuilderResources {..}++withBuilder ::+ HackageHandlers ->+ StateFileHandlers ->+ StateFileConfig ->+ Envs EnvConfig ->+ Maybe BuildOutputsPrefix ->+ (Builder -> M a) ->+ M a+withBuilder hackage stateFileHandlers stateFileConf envsConf buildOutputsPrefix use =+ withTempProject stateFileConf.projectRoot \ root -> do+ let resources = BuilderResources {..}+ use Builder {withEnvBuilder = withEnvBuilder resources}++handlersProd ::+ MonadIO m =>+ StateFileConfig ->+ Envs EnvConfig ->+ Maybe BuildOutputsPrefix ->+ CabalConfig ->+ Bool ->+ m BuildHandlers+handlersProd stateFileConf envsConf buildOutputsPrefix cabalConf oldest = do+ manager <- liftIO (newManager tlsManagerSettings)+ hackage <- HackageHandlers.handlersProd+ let stateFile = StateFileHandlers.handlersProd stateFileConf+ pure BuildHandlers {+ stateFile,+ report = ReportHandlers.handlersProd,+ cabal = CabalHandlers.handlersProd cabalConf oldest,+ withBuilder = withBuilder hackage stateFile stateFileConf envsConf buildOutputsPrefix,+ versions = versionsHackage manager,+ latestVersion = latestVersionHackage manager+ }
+ lib/Hix/Managed/Handlers/Build/Test.hs view
@@ -0,0 +1,92 @@+module Hix.Managed.Handlers.Build.Test where++import Data.IORef (IORef)+import Data.Map.Strict ((!?))+import Exon (exon)++import Hix.Data.Monad (M)+import Hix.Data.NixExpr (Expr)+import qualified Hix.Data.PackageId+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (Version, Versions)+import Hix.Managed.Cabal.Data.Config (CabalConfig)+import qualified Hix.Managed.Cabal.Data.Packages+import Hix.Managed.Cabal.Data.Packages (GhcPackages)+import Hix.Managed.Cabal.Mock.SourcePackage (queryVersions, queryVersionsLatest, sourcePackageVersions)+import Hix.Managed.Data.EnvConfig (EnvConfig)+import Hix.Managed.Data.Envs (Envs)+import Hix.Managed.Data.Mutation (FailedMutation)+import Hix.Managed.Data.StageState (BuildStatus)+import Hix.Managed.Data.StateFileConfig (StateFileConfig)+import Hix.Managed.Handlers.Build (+ BuildHandlers (..),+ BuildOutputsPrefix,+ SpecialBuildHandlers (TestBumpHandlers),+ versionsBuilder,+ )+import Hix.Managed.Handlers.Build.Prod (handlersProd)+import qualified Hix.Managed.Handlers.Cabal.Prod as CabalHandlers+import Hix.Managed.Handlers.Cabal.Prod (testPackagesBump)+import qualified Hix.Managed.Handlers.Hackage as HackageHandlers+import qualified Hix.Managed.Handlers.Report.Test as ReportHandlers+import qualified Hix.Managed.Handlers.StateFile.Test as StateFile+import Hix.Monad (clientError)++handlersUnitTest ::+ MonadIO m =>+ GhcPackages ->+ (Versions -> M BuildStatus) ->+ m (BuildHandlers, IORef [Expr], IORef [FailedMutation])+handlersUnitTest ghcPackages builder = do+ (stateFile, stateFileRef) <- StateFile.handlersUnitTest+ (report, mutationsRef) <- ReportHandlers.handlersUnitTest+ let+ handlers =+ BuildHandlers {+ stateFile,+ report,+ cabal,+ withBuilder = versionsBuilder HackageHandlers.handlersNull builder,+ versions = queryVersions versions,+ latestVersion = queryVersionsLatest versions+ }+ pure (handlers, stateFileRef, mutationsRef)+ where+ cabal = CabalHandlers.handlersProd def False+ versions = sourcePackageVersions ghcPackages.available++latestVersionNixTestBump :: PackageName -> M (Maybe Version)+latestVersionNixTestBump name =+ maybe invalid found (testPackagesBump !? name)+ where+ invalid = clientError [exon|Invalid package for latestVersion: ##{name}|]+ found = pure . Just . (.version)++handlersBumpTest ::+ MonadIO m =>+ StateFileConfig ->+ Envs EnvConfig ->+ Maybe BuildOutputsPrefix ->+ CabalConfig ->+ Bool ->+ m BuildHandlers+handlersBumpTest stateFileConf envsConf buildOutputsPrefix cabalConf oldest = do+ handlers <- handlersProd stateFileConf envsConf buildOutputsPrefix cabalConf oldest+ pure handlers {+ cabal = CabalHandlers.handlersTest cabalConf oldest,+ latestVersion = latestVersionNixTestBump+ }++chooseHandlers ::+ MonadIO m =>+ StateFileConfig ->+ Envs EnvConfig ->+ Maybe BuildOutputsPrefix ->+ CabalConfig ->+ Maybe SpecialBuildHandlers ->+ m BuildHandlers+chooseHandlers stateFileConf envsConf buildOutputsPrefix cabalConf = \case+ Just TestBumpHandlers -> handlersBumpTest stateFileConf envsConf buildOutputsPrefix cabalConf oldest+ Nothing -> handlersProd stateFileConf envsConf buildOutputsPrefix cabalConf oldest+ where+ oldest = False
+ lib/Hix/Managed/Handlers/Cabal.hs view
@@ -0,0 +1,41 @@+module Hix.Managed.Handlers.Cabal where++import Data.IORef (IORef, modifyIORef')++import Hix.Class.Map (nFromKeys)+import Hix.Data.Monad (M)+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (Version)+import Hix.Managed.Cabal.Changes (SolverPlan)+import Hix.Managed.Cabal.Data.SolverState (SolverState)+import Hix.Managed.Data.Constraints (EnvConstraints)+import Hix.Managed.Data.Mutable (MutableDep, MutableVersions, depName)++data CabalHandlers =+ CabalHandlers {+ solveForVersion :: SolverState -> M (Maybe SolverPlan),+ installedVersion :: PackageName -> Maybe Version+ }++handlersNull :: CabalHandlers+handlersNull =+ CabalHandlers {+ solveForVersion = \ _ -> pure Nothing,+ installedVersion = const Nothing+ }++installedVersions ::+ CabalHandlers ->+ Set MutableDep ->+ MutableVersions+installedVersions cabal names =+ nFromKeys names (cabal.installedVersion . depName)++logCabal :: IORef [(EnvConstraints, Maybe SolverPlan)] -> CabalHandlers -> CabalHandlers+logCabal ref CabalHandlers {..} =+ CabalHandlers {solveForVersion = solve, ..}+ where+ solve state = do+ plan <- solveForVersion state+ liftIO (modifyIORef' ref ((state.constraints, plan) :))+ pure plan
+ lib/Hix/Managed/Handlers/Cabal/Prod.hs view
@@ -0,0 +1,87 @@+module Hix.Managed.Handlers.Cabal.Prod where++import qualified Data.Map.Strict as Map+import Distribution.Client.Dependency (PackagesPreferenceDefault (PreferAllOldest), setPreferenceDefault)+import qualified Distribution.Client.Types+import Distribution.Client.Types (SourcePackageDb (SourcePackageDb), UnresolvedSourcePackage)+import qualified Distribution.Solver.Types.PackageIndex as PackageIndex+import Distribution.Solver.Types.PackageIndex (PackageIndex)+import Distribution.Version (laterVersion)++import Hix.Data.Monad (M)+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import qualified Hix.Data.PackageName as PackageName+import Hix.Data.PackageName (PackageName)+import Hix.Managed.Cabal.Data.Config (GhcDb, CabalConfig)+import qualified Hix.Managed.Cabal.Data.SolveResources as SolveResources+import Hix.Managed.Cabal.Data.SolveResources (SolveResources (SolveResources), solverParams)+import Hix.Managed.Cabal.Installed (installedVersion)+import qualified Hix.Managed.Cabal.Resources as SolveResources+import Hix.Managed.Cabal.Solve (solveWithCabal)+import Hix.Managed.Data.ManagedPackage (ManagedPackage)+import Hix.Managed.Data.Packages (Packages)+import Hix.Managed.Handlers.Cabal (CabalHandlers (..))+import Hix.Zip (zipApplyL)++handlersWith ::+ (SolveResources -> SolveResources) ->+ CabalConfig ->+ Bool ->+ Packages ManagedPackage ->+ GhcDb ->+ M CabalHandlers+handlersWith trans cabalConf oldest packages ghc = do+ solveResources <- trans <$> SolveResources.acquire packages cabalConf ghc+ pure CabalHandlers {+ solveForVersion = solveWithCabal solveResources {solverParams},+ installedVersion = installedVersion solveResources.installedPkgIndex+ }+ where+ solverParams | oldest = setPreferenceDefault PreferAllOldest+ | otherwise = id++handlersProd ::+ CabalConfig ->+ Bool ->+ Packages ManagedPackage ->+ GhcDb ->+ M CabalHandlers+handlersProd =+ handlersWith id++testPackagesBump :: Map PackageName PackageId+testPackagesBump =+ Map.fromList $ zipApplyL (.name) [+ PackageId {name = "aeson", version = [2, 2, 0, 0]},+ PackageId {name = "base", version = [4, 17, 2, 0]},+ PackageId {name = "extra", version = [1, 7, 14]},+ PackageId {name = "th-abstraction", version = [0, 5, 0, 0]},+ PackageId {name = "path", version = [0, 9, 5]}+ ]++removeLaterVersions ::+ PackageId ->+ PackageIndex UnresolvedSourcePackage ->+ PackageIndex UnresolvedSourcePackage+removeLaterVersions PackageId {..} =+ PackageIndex.deleteDependency (PackageName.toCabal name) (laterVersion version)++testResources :: SolveResources -> SolveResources+testResources SolveResources {..} =+ SolveResources {sourcePkgDb = removeLaterTestPackageVersions sourcePkgDb, ..}+ where+ removeLaterTestPackageVersions SourcePackageDb {..} =+ SourcePackageDb {+ packageIndex = Map.foldr' removeLaterVersions packageIndex testPackagesBump,+ ..+ }++handlersTest ::+ CabalConfig ->+ Bool ->+ Packages ManagedPackage ->+ GhcDb ->+ M CabalHandlers+handlersTest =+ handlersWith testResources
+ lib/Hix/Managed/Handlers/Hackage.hs view
@@ -0,0 +1,17 @@+module Hix.Managed.Handlers.Hackage where++import Hix.Data.Monad (M)+import Hix.Data.PackageId (PackageId)+import Hix.Data.Version (SourceHash (SourceHash))+import Hix.Pretty (showP)++data HackageHandlers =+ HackageHandlers {+ fetchHash :: PackageId -> M SourceHash+ }++handlersNull :: HackageHandlers+handlersNull =+ HackageHandlers {+ fetchHash = \ package -> pure (SourceHash (showP package))+ }
+ lib/Hix/Managed/Handlers/Hackage/Prod.hs view
@@ -0,0 +1,16 @@+module Hix.Managed.Handlers.Hackage.Prod where++import Data.IORef (newIORef)++import Hix.Hackage (fetchHashHackageCached)+import qualified Hix.Managed.Handlers.Hackage+import Hix.Managed.Handlers.Hackage (HackageHandlers (HackageHandlers))++handlersProd ::+ MonadIO m =>+ m HackageHandlers+handlersProd = do+ hashCache <- liftIO (newIORef mempty)+ pure HackageHandlers {+ fetchHash = fetchHashHackageCached hashCache+ }
+ lib/Hix/Managed/Handlers/Mutation.hs view
@@ -0,0 +1,14 @@+module Hix.Managed.Handlers.Mutation where++import Hix.Data.Monad (M)+import Hix.Managed.Data.Mutation (BuildMutation, DepMutation, MutationResult)+import Hix.Managed.Data.MutationState (MutationState)++data MutationHandlers a s =+ MutationHandlers {+ process ::+ s ->+ DepMutation a ->+ (BuildMutation -> M (Maybe MutationState)) ->+ M (MutationResult s)+ }
+ lib/Hix/Managed/Handlers/Mutation/Bump.hs view
@@ -0,0 +1,50 @@+module Hix.Managed.Handlers.Mutation.Bump where++import Hix.Data.Monad (M)+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.Version (Version)+import qualified Hix.Data.VersionBounds as VersionBounds+import Hix.Data.VersionBounds (VersionBounds, fromLower)+import Hix.Managed.Build.Mutation (buildCandidate)+import Hix.Managed.Cabal.Data.SolverState (SolverState)+import qualified Hix.Managed.Data.Bump+import Hix.Managed.Data.Bump (Bump (Bump))+import qualified Hix.Managed.Data.Constraints+import Hix.Managed.Data.Constraints (MutationConstraints (MutationConstraints))+import Hix.Managed.Data.MutableId (MutableId)+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (+ BuildMutation,+ DepMutation (DepMutation),+ MutationResult (MutationFailed, MutationSuccess),+ )+import Hix.Managed.Data.MutationState (MutationState)+import qualified Hix.Managed.Handlers.Mutation+import Hix.Managed.Handlers.Mutation (MutationHandlers (MutationHandlers))+import Hix.Version (nextMajor)++updateConstraintsBump :: MutableId -> PackageId -> MutationConstraints -> MutationConstraints+updateConstraintsBump _ PackageId {version} MutationConstraints {..} =+ MutationConstraints {mutation = fromLower version, ..}++updateBound :: Version -> VersionBounds -> VersionBounds+updateBound = VersionBounds.withUpper . nextMajor++-- TODO Avoid building unchanged candidates after the first build of the same set of deps.+processMutationBump ::+ SolverState ->+ DepMutation Bump ->+ (BuildMutation -> M (Maybe MutationState)) ->+ M (MutationResult SolverState)+processMutationBump solver DepMutation {package, mutation = Bump {version, changed}} build =+ builder version <&> \case+ Just (candidate, ext, state) ->+ MutationSuccess {candidate, changed, state, ext}+ Nothing ->+ MutationFailed+ where+ builder = buildCandidate build updateBound updateConstraintsBump solver package++handlersBump :: MutationHandlers Bump SolverState+handlersBump = MutationHandlers {process = processMutationBump}
+ lib/Hix/Managed/Handlers/Mutation/Lower.hs view
@@ -0,0 +1,83 @@+module Hix.Managed.Handlers.Mutation.Lower where++import Control.Monad (foldM)+import Data.Foldable.Extra (firstJustM)+import Data.Generics.Labels ()+import Exon (exon)++import Hix.Data.Monad (M)+import Hix.Data.PackageId (PackageId)+import qualified Hix.Data.Version+import Hix.Data.Version (Major (Major))+import Hix.Data.VersionBounds (withLower)+import qualified Hix.Log as Log+import Hix.Managed.Build.Mutation (buildCandidate)+import Hix.Managed.Cabal.Data.SolverState (SolverState)+import qualified Hix.Managed.Data.BuildConfig+import Hix.Managed.Data.BuildConfig (BuildConfig)+import Hix.Managed.Data.Constraints (MutationConstraints)+import qualified Hix.Managed.Data.Lower+import Hix.Managed.Data.Lower (Lower (Lower))+import Hix.Managed.Data.MutableId (MutableId)+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (BuildMutation, DepMutation (DepMutation), MutationResult (MutationSuccess))+import Hix.Managed.Data.MutationState (MutationState)+import qualified Hix.Managed.Handlers.Mutation+import Hix.Managed.Handlers.Mutation (MutationHandlers (MutationHandlers))+import qualified Hix.Managed.Lower.Data.LowerMode+import Hix.Managed.Lower.Data.LowerMode (LowerMode)+import Hix.Pretty (showP)++-- TODO would be nice if the deps that succeed as transitive deps would have their candidates trimmed so that it+-- immediately returns success when the version is encountered that succeeded most recently that way.+--+-- TODO Can we get a sensible value for @changed@?+processMutationLower ::+ BuildConfig ->+ LowerMode ->+ (Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints) ->+ SolverState ->+ DepMutation Lower ->+ (BuildMutation -> M (Maybe MutationState)) ->+ M (MutationResult SolverState)+processMutationLower conf mode update solver DepMutation {package, retract, mutation = Lower {majors}} build = do+ foldM buildMajor (Right 0, Nothing) majors <&> \case+ (_, Just (candidate, ext, state)) ->+ MutationSuccess {candidate, changed = True, state, ext}+ (_, Nothing) ->+ mode.noSuccess+ where+ -- | We skip all remaining majors when the number of failed majors exceeds the configured limit.+ -- There are different values for failures before the first and after the last success.+ -- This avoid building the project tens of times for versions that cannot succeed.+ --+ -- We also skip all remaining majors when @firstSuccess@ is set, after a major succeeded.+ buildMajor (failed, prev) Major {prefix, versions}+ | Right n <- failed+ , n > conf.maxFailedPre+ = pure (failed, prev)++ | Left n <- failed+ , n > conf.maxFailedPost+ = pure (failed, prev)++ | mode.firstSuccess+ , Just _ <- prev+ = pure (failed, prev)++ | otherwise+ = do+ Log.debug [exon|Building major #{showP prefix} for '##{package}'|]+ firstJustM builder versions <&> \case+ Just result -> (Left 0, Just result)+ Nothing -> (bimap (+ 1) (+ 1) failed, prev)++ builder = buildCandidate build withLower (update retract) solver package++handlersLower ::+ BuildConfig ->+ LowerMode ->+ (Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints) ->+ MutationHandlers Lower SolverState+handlersLower conf mode updatePackageParams =+ MutationHandlers {process = processMutationLower conf mode updatePackageParams}
+ lib/Hix/Managed/Handlers/Report.hs view
@@ -0,0 +1,13 @@+module Hix.Managed.Handlers.Report where++import Hix.Data.Monad (M)+import Hix.Managed.Data.ProjectResult (ProjectResult)++data ReportHandlers =+ ReportHandlers {+ mutations :: ProjectResult -> M ()+ }++handlersNull :: ReportHandlers+handlersNull =+ ReportHandlers {mutations = \ _ -> unit}
+ lib/Hix/Managed/Handlers/Report/Prod.hs view
@@ -0,0 +1,186 @@+module Hix.Managed.Handlers.Report.Prod where++import qualified Data.Text as Text+import Data.These (These (..))+import Data.These.Combinators (justHere, justThere)+import Exon (exon)++import qualified Hix.Console+import Hix.Console (color, colors)+import Hix.Data.Monad (M)+import Hix.Data.Version (Version)+import qualified Hix.Data.VersionBounds+import Hix.Data.VersionBounds (VersionBounds (VersionBounds))+import qualified Hix.Log as Log+import qualified Hix.Managed.Data.EnvResult+import Hix.Managed.Data.EnvResult (EnvResult (EnvResult))+import Hix.Managed.Data.Mutable (MutableDep)+import qualified Hix.Managed.Data.MutableId+import Hix.Managed.Data.MutableId (MutableId (MutableId))+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (FailedMutation)+import qualified Hix.Managed.Data.ProjectResult as ProjectResult+import Hix.Managed.Data.ProjectResult (ProjectResult)+import Hix.Managed.Data.StageResult (StageFailure (FailedMutations, FailedPrecondition), StageSummary (..))+import qualified Hix.Managed.EnvResult+import qualified Hix.Managed.EnvResult as EnvResult+import Hix.Managed.EnvResult (+ BoundsModification (BoundsModification),+ DepModification (DepAdded, DepUpdated),+ DepResult (DepResult),+ DepResultDetail (..),+ DepResults (DepResults),+ )+import qualified Hix.Managed.Handlers.Report+import Hix.Managed.Handlers.Report (ReportHandlers (ReportHandlers))+import Hix.Pretty (showP)++blankLine :: M ()+blankLine = Log.infoPlain ""++listFailed ::+ FailedMutation ->+ Text+listFailed mutation = [exon|📦 #{showP mutation.package}|]++reportFailed ::+ NonEmpty FailedMutation ->+ M ()+reportFailed =+ traverse_ \ mut -> Log.infoCont (listFailed mut)++reportNewVersions ::+ NonEmpty MutableId ->+ M ()+reportNewVersions =+ traverse_ \ MutableId {name, version} ->+ Log.infoCont [exon|📦 '##{name}': #{showP version}|]++printSummary :: StageSummary -> M ()+printSummary = \case+ StageSuccess msg -> Log.info msg+ StageFailure (FailedMutations msg failed) -> do+ Log.info msg+ reportFailed failed+ StageFailure (FailedPrecondition msg) ->+ traverse_ Log.info msg+ StageNoAction msg -> traverse_ Log.info msg+ StageReport msg versions -> do+ Log.info msg+ reportNewVersions versions++printBounds ::+ (Version -> Text) ->+ (Version -> Text) ->+ Maybe Version ->+ Maybe Version ->+ Text+printBounds printL printU lower upper =+ case (lower, upper) of+ (Just l, Just u) -> [exon|[#{printL l}, #{printU u}]|]+ (Just l, Nothing) -> [exon|>=#{printL l}|]+ (Nothing, Just u) -> [exon|<#{printU u}|]+ (Nothing, Nothing) -> "[no bounds]"++formatDepLine :: MutableDep -> Text -> Text -> (Text, Text, Text)+formatDepLine package version bounds =+ ([exon|📦 #{color colors.blue (showP package)}|], version, [exon|↕ #{bounds}|])++formatBoundsModification :: VersionBounds -> BoundsModification -> Text+formatBoundsModification VersionBounds {lower = lowerNew, upper = upperNew} (BoundsModification bm) =+ [exon|#{original} -> #{new}|]+ where++ original = interval lowerOriginal upperOriginal colors.red lowerChanged upperChanged+ new = interval lowerNew upperNew colors.green lowerChanged upperChanged++ lowerOriginal = fromMaybe lowerNew lowerDiff+ upperOriginal = fromMaybe upperNew upperDiff++ lowerChanged = isJust lowerDiff+ upperChanged = isJust upperDiff++ lowerDiff = justHere bm+ upperDiff = justThere bm++ interval l u col colL colU =+ printBounds (bound col colL) (bound col colU) l u++ bound col useCol v+ | useCol+ = color col (showP v)+ | otherwise+ = showP v++formatDep :: MutableDep -> Version -> VersionBounds -> Maybe BoundsModification -> (Text, Text, Text)+formatDep package version bounds boundsMod =+ formatDepLine package (showP version) (maybe unchangedBounds changedBounds boundsMod)+ where+ changedBounds = formatBoundsModification bounds+ unchangedBounds = printBounds showP showP bounds.lower bounds.upper++formatDepUpdate ::+ MutableDep ->+ Version ->+ VersionBounds ->+ These Version BoundsModification ->+ (Text, Text, Text)+formatDepUpdate package version bounds update =+ formatDepLine package versionDesc boundsDesc+ where+ versionDesc = case justHere update of+ Just original -> versionUpdate original version+ Nothing -> showP version++ versionUpdate original new =+ [exon|#{color colors.red (showP original)} -> #{color colors.green (showP new)}|]++ boundsDesc = case justThere update of+ Just boundsMod -> formatBoundsModification bounds boundsMod+ Nothing -> showP bounds++printAligned :: [(Text, Text, Text)] -> M ()+printAligned deps =+ traverse_ printLine deps+ where+ printLine (p, v, b) = Log.infoCont (padded p maxP <> padded v maxV <> b)+ padded s maxlen = s <> Text.replicate (maxlen - Text.length s + 3) " "+ maxP = maxi ps+ maxV = maxi vs+ maxi = fromMaybe 0 . maximum . fmap Text.length+ (ps, vs, _) = unzip3 deps++formatDepResult :: DepResult -> Maybe (Text, Text, Text)+formatDepResult DepResult {..} =+ case detail of+ DepModified (DepAdded boundsMod) -> Just (formatDep package version bounds boundsMod)+ DepModified (DepUpdated update) -> Just (formatDepUpdate package version bounds update)+ DepUnmodified -> Nothing++-- TODO don't print the env name when using @sets = "all"@ (or even when only one env is processed?)+envResult ::+ EnvResult ->+ M ()+envResult result@EnvResult {env, summaries} = do+ Log.info envLabel+ traverse_ printSummary summaries+ for_ (nonEmpty added) \ deps -> do+ Log.info "Added new versions:"+ printAligned (mapMaybe formatDepResult (toList deps))+ for_ (nonEmpty updated) \ deps -> do+ Log.info "Updated versions:"+ printAligned (mapMaybe formatDepResult (toList deps))+ where+ DepResults {..} = EnvResult.grouped result+ envLabel = color colors.yellow (showP env)++mutations ::+ ProjectResult ->+ M ()+mutations results = do+ blankLine+ sequence_ (intersperse blankLine (envResult <$> toList results.envs))++handlersProd :: ReportHandlers+handlersProd =+ ReportHandlers {mutations}
+ lib/Hix/Managed/Handlers/Report/Test.hs view
@@ -0,0 +1,27 @@+module Hix.Managed.Handlers.Report.Test where++import Data.IORef (IORef, modifyIORef, newIORef)++import Hix.Data.Monad (M)+import Hix.Managed.Data.Mutation (FailedMutation)+import qualified Hix.Managed.Data.ProjectResult+import Hix.Managed.Data.ProjectResult (ProjectResult)+import qualified Hix.Managed.EnvResult as EnvResult+import Hix.Managed.Handlers.Report (ReportHandlers (..), handlersNull)++reportMutationsIORef ::+ IORef [FailedMutation] ->+ ProjectResult ->+ M ()+reportMutationsIORef out results =+ liftIO $ modifyIORef out \ old ->+ foldl' (flip (++)) old failed+ where+ failed = EnvResult.failures <$> toList results.envs++handlersUnitTest ::+ MonadIO m =>+ m (ReportHandlers, IORef [FailedMutation])+handlersUnitTest = do+ mutationsRef <- liftIO (newIORef [])+ pure (handlersNull {mutations = reportMutationsIORef mutationsRef}, mutationsRef)
+ lib/Hix/Managed/Handlers/StateFile.hs view
@@ -0,0 +1,15 @@+module Hix.Managed.Handlers.StateFile where++import Path (Abs, Dir, Path)++import Hix.Data.Monad (M)+import Hix.Data.NixExpr (Expr)++data StateFileHandlers =+ StateFileHandlers {+ writeFile :: Maybe (Path Abs Dir) -> Expr -> M ()+ }++handlersNull :: StateFileHandlers+handlersNull =+ StateFileHandlers {writeFile = \ _ _ -> unit}
+ lib/Hix/Managed/Handlers/StateFile/Prod.hs view
@@ -0,0 +1,54 @@+module Hix.Managed.Handlers.StateFile.Prod where++import qualified Data.Text.IO as Text+import Path (Abs, File, Path, parent, toFilePath, (</>), Dir)+import Path.IO (createDirIfMissing, doesDirExist, doesFileExist)+import System.Posix (fileMode, getFileStatus, ownerWriteMode, setFileMode, unionFileModes)++import Hix.Data.NixExpr (Expr)+import qualified Hix.Managed.Data.StateFileConfig+import Hix.Managed.Data.StateFileConfig (StateFileConfig)+import Hix.Managed.Handlers.StateFile (StateFileHandlers (..))+import Hix.Managed.Path (rootOrCwd)+import Hix.Monad (M, tryIOM)+import Hix.NixExpr (renderRootExpr)++setDepsFileWritable ::+ Path Abs File ->+ M ()+setDepsFileWritable file =+ tryIOM do+ whenM (doesDirExist dir) do+ whenM (doesFileExist file) do+ fileCur <- getFileStatus fileFp+ setWrite fileFp (fileMode fileCur)+ where+ setWrite path cur = setFileMode path (unionFileModes cur ownerWriteMode)+ fileFp = toFilePath file+ dir = parent file++initFile ::+ StateFileConfig ->+ Maybe (Path Abs Dir) ->+ M (Path Abs File)+initFile conf tmpRoot = do+ root <- maybe (rootOrCwd conf.projectRoot) pure tmpRoot+ let depsFile = root </> conf.file+ createDirIfMissing False (parent depsFile)+ setDepsFileWritable depsFile+ pure depsFile++writeFile ::+ StateFileConfig ->+ Maybe (Path Abs Dir) ->+ Expr ->+ M ()+writeFile conf tmpRoot nixExpr = do+ path <- initFile conf tmpRoot+ liftIO (Text.writeFile (toFilePath path) (renderRootExpr nixExpr))++handlersProd ::+ StateFileConfig ->+ StateFileHandlers+handlersProd conf =+ StateFileHandlers {writeFile = writeFile conf}
+ lib/Hix/Managed/Handlers/StateFile/Test.hs view
@@ -0,0 +1,23 @@+module Hix.Managed.Handlers.StateFile.Test where++import Data.IORef (IORef, modifyIORef, newIORef)++import Hix.Data.Monad (M)+import Hix.Data.NixExpr (Expr)+import Hix.Managed.Handlers.StateFile (StateFileHandlers (StateFileHandlers), writeFile)++writeFileIORef ::+ IORef [Expr] ->+ Maybe a ->+ Expr ->+ M ()+writeFileIORef out _ expr =+ liftIO $ modifyIORef out (expr :)++handlersUnitTest ::+ MonadIO m =>+ m (StateFileHandlers, IORef [Expr])+handlersUnitTest = do+ ref <- liftIO (newIORef [])+ let handlers = StateFileHandlers {writeFile = writeFileIORef ref}+ pure (handlers, ref)
+ lib/Hix/Managed/Lower/App.hs view
@@ -0,0 +1,41 @@+module Hix.Managed.Lower.App where++import Hix.Data.Error (Error (Client))+import Hix.Data.Monad (M)+import qualified Hix.Data.Options+import Hix.Data.Options (LowerOptions (LowerOptions))+import Hix.Json (jsonConfigE)+import Hix.Managed.Data.LowerConfig (LowerConfig, lowerConfig)+import Hix.Managed.Data.ProjectContext (ProjectContext)+import qualified Hix.Managed.Data.ProjectContextProto+import Hix.Managed.Data.ProjectResult (ProjectResult)+import Hix.Managed.Handlers.Build (BuildHandlers)+import Hix.Managed.Handlers.Build.Test (chooseHandlers)+import Hix.Managed.Lower.Auto (lowerAutoMain)+import Hix.Managed.Lower.Init (lowerInitMain)+import Hix.Managed.Lower.Optimize (lowerOptimizeMain)+import Hix.Managed.Lower.Stabilize (lowerStabilizeMain)+import Hix.Managed.ProjectContext (withProjectContext)++lowerCli ::+ (LowerConfig -> BuildHandlers -> ProjectContext -> M ProjectResult) ->+ LowerOptions ->+ M ()+lowerCli main opts@LowerOptions {common} = do+ context <- jsonConfigE Client common.context+ handlers <- chooseHandlers common.stateFile context.envs context.buildOutputsPrefix common.cabal common.handlers+ withProjectContext handlers common.project context (main conf handlers)+ where+ conf = lowerConfig opts++lowerInitCli :: LowerOptions -> M ()+lowerInitCli = lowerCli lowerInitMain++lowerOptimizeCli :: LowerOptions -> M ()+lowerOptimizeCli = lowerCli (const lowerOptimizeMain)++lowerStabilizeCli :: LowerOptions -> M ()+lowerStabilizeCli = lowerCli (const lowerStabilizeMain)++lowerAutoCli :: LowerOptions -> M ()+lowerAutoCli = lowerCli lowerAutoMain
+ lib/Hix/Managed/Lower/Auto.hs view
@@ -0,0 +1,110 @@+module Hix.Managed.Lower.Auto where++import qualified Data.Set as Set++import Hix.Class.Map (nToMaybe, nZipR)+import Hix.Data.Monad (M)+import Hix.Managed.Data.BuildConfig (BuildConfig)+import qualified Hix.Managed.Data.EnvState+import Hix.Managed.Data.EnvState (EnvState (EnvState))+import qualified Hix.Managed.Data.LowerConfig+import Hix.Managed.Data.LowerConfig (LowerConfig)+import Hix.Managed.Data.Mutable (MutableVersions)+import qualified Hix.Managed.Data.ProjectContext+import Hix.Managed.Data.ProjectContext (ProjectContext)+import Hix.Managed.Data.ProjectResult (ProjectResult)+import Hix.Managed.Data.Query (Query (Query))+import qualified Hix.Managed.Data.QueryDep+import Hix.Managed.Data.StageContext (StageContext (StageContext), query)+import Hix.Managed.Data.StageState (BuildStatus (Failure, Success))+import Hix.Managed.Diff (reifyVersionChanges)+import Hix.Managed.Flow (Flow, evalStageState, runStage_, stageError)+import Hix.Managed.Handlers.Build (BuildHandlers)+import Hix.Managed.Lower.Init (lowerInitStage)+import Hix.Managed.Lower.Optimize (lowerOptimize)+import Hix.Managed.Lower.Stabilize (stabilizeIfPossible, stabilizeStage, validateCurrent)+import Hix.Managed.Process (processProject)++suggestStabilize :: Flow ()+suggestStabilize = stageError "Re-run with --stabilize to attempt to fix the bounds."++-- | This skips building with initial bounds because it only runs after LowerInit failed, which means that we have no+-- initial bounds.+stabilizeInitFailure ::+ BuildHandlers ->+ LowerConfig ->+ BuildConfig ->+ Flow ()+stabilizeInitFailure handlers conf buildConf+ | conf.stabilize+ = stabilizeStage handlers buildConf+ | otherwise+ = suggestStabilize++-- TODO needs some more work+pristineBounds :: EnvState -> Query -> Maybe Query+pristineBounds EnvState {versions, initial} (Query query) =+ Query <$> nonEmpty (restrictQuery (nToMaybe pristine nameIfJust))+ where+ nameIfJust name = \case+ Just _ -> Just name+ Nothing -> Nothing++ restrictQuery (Set.fromList -> names) =+ filter (flip Set.member names . (.package)) (toList query)++ pristine :: MutableVersions+ pristine = nZipR justEqual (reifyVersionChanges initial) (reifyVersionChanges versions)++ justEqual (Just (Just ini)) (Just current) | ini == current = Just current+ justEqual _ _ = Nothing++-- | Return the current 'Query' without those deps whose current versions differ from their initial ones, i.e. that have+-- been optimized before.+pristineBoundsQuery :: Flow (Maybe Query)+pristineBoundsQuery =+ evalStageState \ env StageContext {query} -> pristineBounds env query++-- | Run Optimize, but only consider the deps that have not been optimized before.+--+-- TODO this could use a flag for forcing optimization of all (query) deps.+optimizePristineBounds ::+ BuildHandlers ->+ BuildConfig ->+ Flow ()+optimizePristineBounds handlers conf = do+ pristineBoundsQuery >>= \case+ Just newQuery ->+ runStage_ "auto-optimize" \ context ->+ lowerOptimize handlers conf context {query = newQuery}+ Nothing -> unit++postInit ::+ BuildHandlers ->+ LowerConfig ->+ BuildConfig ->+ Flow ()+postInit handlers conf buildConf =+ validateCurrent >>= \case+ Success -> optimizePristineBounds handlers buildConf+ Failure | conf.stabilize -> stabilizeIfPossible handlers buildConf+ | otherwise -> suggestStabilize++lowerAutoStages ::+ BuildHandlers ->+ LowerConfig ->+ BuildConfig ->+ Flow ()+lowerAutoStages handlers conf buildConf =+ lowerInitStage handlers conf buildConf >>= \case+ Success | conf.initOnly -> unit+ | otherwise -> postInit handlers conf buildConf+ Failure -> stabilizeInitFailure handlers conf buildConf++lowerAutoMain ::+ LowerConfig ->+ BuildHandlers ->+ ProjectContext ->+ M ProjectResult+lowerAutoMain conf handlers project =+ processProject handlers project (lowerAutoStages handlers conf project.build)
+ lib/Hix/Managed/Lower/Candidates.hs view
@@ -0,0 +1,196 @@+module Hix.Managed.Lower.Candidates where++import qualified Data.Set as Set+import qualified Data.Text as Text+import Distribution.Pretty (pretty)+import Distribution.Version (Version)+import Exon (exon)++import Hix.Class.Map ((!!))+import Hix.Data.Error (Error (Client))+import Hix.Data.Monad (M)+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (Major)+import qualified Hix.Data.VersionBounds+import Hix.Data.VersionBounds (VersionBounds)+import qualified Hix.Log as Log+import qualified Hix.Managed.Data.Lower+import Hix.Managed.Data.Lower (Lower (Lower))+import Hix.Managed.Data.Mutable (MutableDep, MutableVersions, depName)+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (DepMutation (DepMutation))+import qualified Hix.Managed.Data.QueryDep+import Hix.Managed.Data.QueryDep (QueryDep)+import Hix.Monad (throwM)+import Hix.Pretty (showP)+import Hix.Version (allMajors, majorParts, majorsBefore, versionsBetween, versionsFrom)++logNoVersions ::+ MutableDep ->+ [Version] ->+ Maybe a ->+ M (Maybe a)+logNoVersions package allVersions mutation = do+ when (isNothing mutation) do+ Log.debug [exon|Available versions: #{Text.intercalate ", " (show . pretty <$> allVersions)}|]+ Log.warn [exon|No suitable version found for '##{package}'.|]+ pure mutation++specifiedLower :: VersionBounds -> Maybe (Int, Int)+specifiedLower = majorParts <=< (.lower)++specifiedUpper :: VersionBounds -> Maybe (Int, Int)+specifiedUpper = majorParts <=< (.upper)++prefix :: Int -> Int -> Text+prefix s m = [exon|#{show s}.#{show m}|]++candidates ::+ (PackageName -> M [Version]) ->+ QueryDep ->+ Bool ->+ ([Version] -> Maybe (NonEmpty Major)) ->+ M (Maybe (DepMutation Lower))+candidates fetchVersions dep retract selection = do+ allVersions <- fetchVersions (depName package)+ let+ result = do+ majors <- selection (sort allVersions)+ pure DepMutation {package, retract, mutation = Lower {majors}}+ logNoVersions package allVersions result+ pure result+ where+ package = dep.package++data InitConfig =+ InitBeforeUpper Int Int+ |+ InitAll+ deriving stock (Eq, Show, Generic)++initConfig :: VersionBounds -> InitConfig+initConfig version =+ case specifiedUpper version of+ Just (s, m) -> InitBeforeUpper s m+ _ -> InitAll++logInitConfig :: MutableDep -> InitConfig -> M ()+logInitConfig package conf =+ Log.verbose [exon|Choosing versions for '##{package}' from #{msg conf}.|]+ where+ msg = \case+ InitBeforeUpper s m ->+ [exon|all majors before the specified upper bound #{prefix s m}|]+ InitAll ->+ "all majors"++selectionInit :: InitConfig -> [Version] -> Maybe (NonEmpty Major)+selectionInit = \case+ InitBeforeUpper s m ->+ nonEmpty . reverse . majorsBefore s m+ InitAll ->+ nonEmpty . reverse . allMajors++candidatesInit ::+ (PackageName -> M [Version]) ->+ Set MutableDep ->+ QueryDep ->+ M (Maybe (DepMutation Lower))+candidatesInit fetchVersions pre dep+ | Set.member dep.package pre+ = pure Nothing+ | otherwise+ = do+ logInitConfig dep.package conf+ candidates fetchVersions dep False (selectionInit conf)+ where+ conf = initConfig dep.bounds++data OptimizeConfig =+ OptimizeMajorsBefore Int Int+ |+ OptimizeNoBound+ deriving stock (Eq, Show, Generic)++optimizeConfig ::+ Maybe Version ->+ VersionBounds ->+ OptimizeConfig+optimizeConfig initial version =+ case majorParts =<< (version.lower <|> initial) of+ Just (s, m) -> OptimizeMajorsBefore s m+ Nothing -> OptimizeNoBound++logOptimizeConfig ::+ MutableDep ->+ OptimizeConfig ->+ M ()+logOptimizeConfig package = \case+ OptimizeMajorsBefore s m ->+ Log.verbose [exon|Choosing versions for '##{package}' from all majors before #{prefix s m}.|]+ OptimizeNoBound ->+ throwM (Client [exon|'##{package}' has no initial lower bound. Please run '.#lower.init' first.|])++selectionOptimize :: OptimizeConfig -> [Version] -> Maybe (NonEmpty Major)+selectionOptimize = \case+ OptimizeMajorsBefore s m -> do+ nonEmpty . reverse . majorsBefore s m+ OptimizeNoBound ->+ const Nothing++candidatesOptimize ::+ (PackageName -> M [Version]) ->+ MutableVersions ->+ QueryDep ->+ M (Maybe (DepMutation Lower))+candidatesOptimize fetchVersions initial dep = do+ logOptimizeConfig dep.package conf+ candidates fetchVersions dep False (selectionOptimize conf)+ where+ conf = optimizeConfig (join (initial !! dep.package)) dep.bounds++data StabilizeConfig =+ StabilizeFromVersion Version (Maybe Version)+ |+ StabilizeNoBound InitConfig+ deriving stock (Eq, Show, Generic)++stabilizeConfig :: VersionBounds -> Maybe Version -> StabilizeConfig+stabilizeConfig version initialBound =+ case version.lower of+ Just v -> StabilizeFromVersion v (initialBound <|> version.upper)+ Nothing | Just v <- initialBound -> StabilizeFromVersion v (initialBound <|> version.upper)+ Nothing -> StabilizeNoBound (initConfig version)++logStabilizeConfig :: MutableDep -> StabilizeConfig -> M ()+logStabilizeConfig package = \case+ StabilizeFromVersion v Nothing ->+ Log.verbose [exon|Choosing versions for '##{package}' after the current version #{showP v}.|]+ StabilizeFromVersion l (Just u) ->+ Log.verbose [exon|Choosing versions for '##{package}' between the current version #{showP l} and the initial version #{showP u}.|]+ StabilizeNoBound conf ->+ logInitConfig package conf++selectionStabilize :: StabilizeConfig -> [Version] -> Maybe (NonEmpty Major)+selectionStabilize = \case+ StabilizeFromVersion l Nothing ->+ nonEmpty . versionsFrom l+ StabilizeFromVersion l (Just u) ->+ nonEmpty . versionsBetween l u+ StabilizeNoBound conf ->+ selectionInit conf++candidatesStabilize ::+ (PackageName -> M [Version]) ->+ QueryDep ->+ Maybe Version ->+ M (Maybe (DepMutation Lower))+candidatesStabilize fetchVersions dep initialBound = do+ logStabilizeConfig dep.package conf+ candidates fetchVersions dep (isRetract conf) (selectionStabilize conf)+ where+ conf = stabilizeConfig dep.bounds initialBound++ isRetract = \case+ StabilizeFromVersion _ _ -> True+ StabilizeNoBound _ -> False
+ lib/Hix/Managed/Lower/Data/LowerMode.hs view
@@ -0,0 +1,32 @@+module Hix.Managed.Lower.Data.LowerMode where++import Hix.Managed.Cabal.Data.SolverState (SolverState)+import Hix.Managed.Data.Mutation (MutationResult (MutationFailed, MutationKeep))++data LowerMode =+ LowerMode {+ firstSuccess :: Bool,+ noSuccess :: MutationResult SolverState+ }+ deriving stock (Eq, Show, Generic)++lowerInitMode :: LowerMode+lowerInitMode =+ LowerMode {+ firstSuccess = True,+ noSuccess = MutationFailed+ }++lowerOptimizeMode :: LowerMode+lowerOptimizeMode =+ LowerMode {+ firstSuccess = False,+ noSuccess = MutationKeep+ }++lowerStabilizeMode :: LowerMode+lowerStabilizeMode =+ LowerMode {+ firstSuccess = True,+ noSuccess = MutationFailed+ }
+ lib/Hix/Managed/Lower/Init.hs view
@@ -0,0 +1,94 @@+module Hix.Managed.Lower.Init where++import Exon (exon)++import Hix.Class.Map (nCatMaybes, nKeysSet)+import Hix.Data.Monad (M)+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.Version (Version)+import Hix.Data.VersionBounds (fromUpper)+import Hix.Managed.Build (processQuery)+import Hix.Managed.Cabal.Data.SolverState (solverState)+import Hix.Managed.Constraints (fromVersions)+import Hix.Managed.Data.BuildConfig (BuildConfig)+import qualified Hix.Managed.Data.Constraints+import Hix.Managed.Data.Constraints (MutationConstraints (MutationConstraints))+import qualified Hix.Managed.Data.EnvContext+import qualified Hix.Managed.Data.LowerConfig+import Hix.Managed.Data.LowerConfig (LowerConfig)+import Hix.Managed.Data.Mutable (MutableDep, MutableDeps)+import Hix.Managed.Data.MutableId (MutableId)+import qualified Hix.Managed.Data.ProjectContext+import Hix.Managed.Data.ProjectContext (ProjectContext)+import Hix.Managed.Data.ProjectResult (ProjectResult)+import qualified Hix.Managed.Data.StageContext+import Hix.Managed.Data.StageContext (StageContext)+import Hix.Managed.Data.StageResult (StageResult)+import Hix.Managed.Data.StageState (BuildStatus, BuildSuccess)+import Hix.Managed.Flow (Flow, execStage)+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (BuildHandlers)+import qualified Hix.Managed.Handlers.Mutation.Lower as Mutation+import Hix.Managed.Lower.Candidates (candidatesInit)+import Hix.Managed.Lower.Data.LowerMode (lowerInitMode)+import Hix.Managed.Process (processProject)+import Hix.Managed.Report (describeIterations)+import Hix.Managed.StageResult (stageResultInit)++lowerInitUpdate :: Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints+lowerInitUpdate _ _ PackageId {version} MutationConstraints {..} =+ MutationConstraints {mutation = fromUpper version, ..}++success :: Map MutableDep BuildSuccess -> Natural -> Text+success _ iterations =+ [exon|Found initial lower bounds for all deps after #{iter}.|]+ where+ iter = describeIterations iterations++failure :: Natural -> Text+failure iterations =+ [exon|Couldn't find working initial lower bounds for some deps after #{describeIterations iterations}.|]++-- TODO This could instead only update the initial versions, so that a subsequent @lower.optimize@ can skip the versions+-- it elaborated before.+-- But it would require some nontrivial changes to the state update mechanisms.+--+-- | Determine initial lower bounds for the selected dependencies if they have none or @--reset@ was specified.+-- If none of the selected deps need to be processed, the state is not updated.+-- Otherwise, the lower bounds of _all_ deps are reset to the initial ones, requiring the user to run @lower.optimize@+-- again.+lowerInit ::+ BuildHandlers ->+ LowerConfig ->+ BuildConfig ->+ StageContext ->+ M StageResult+lowerInit handlers conf buildConf context = do+ result <- processQuery candidates mutationHandlers buildConf context ext+ pure (stageResultInit success failure result)+ where+ candidates = candidatesInit handlers.versions (nKeysSet (nCatMaybes keep :: MutableDeps Version))++ mutationHandlers = Mutation.handlersLower buildConf lowerInitMode lowerInitUpdate++ ext = solverState context.env.solverBounds context.env.deps (fromVersions fromUpper keep) def++ keep | conf.reset = mempty+ | otherwise = context.initial++lowerInitStage ::+ BuildHandlers ->+ LowerConfig ->+ BuildConfig ->+ Flow BuildStatus+lowerInitStage handlers conf buildConf =+ execStage "lower-init" (lowerInit handlers conf buildConf)++lowerInitMain ::+ LowerConfig ->+ BuildHandlers ->+ ProjectContext ->+ M ProjectResult+lowerInitMain conf handlers project =+ processProject handlers project (void (lowerInitStage handlers conf project.build))
+ lib/Hix/Managed/Lower/Optimize.hs view
@@ -0,0 +1,76 @@+module Hix.Managed.Lower.Optimize where++import Exon (exon)++import Hix.Data.Monad (M)+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.VersionBounds (fromUpper)+import Hix.Managed.Build (processQuery)+import Hix.Managed.Cabal.Data.SolverState (solverState)+import Hix.Managed.Constraints (fromVersions)+import Hix.Managed.Data.BuildConfig (BuildConfig)+import qualified Hix.Managed.Data.Constraints+import Hix.Managed.Data.Constraints (MutationConstraints (MutationConstraints))+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.Initial (Initial (Initial))+import Hix.Managed.Data.Mutable (MutableDep)+import Hix.Managed.Data.MutableId (MutableId)+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState (MutationState))+import qualified Hix.Managed.Data.ProjectContext+import Hix.Managed.Data.ProjectContext (ProjectContext)+import Hix.Managed.Data.ProjectResult (ProjectResult)+import qualified Hix.Managed.Data.StageContext+import Hix.Managed.Data.StageContext (StageContext (StageContext))+import Hix.Managed.Data.StageResult (StageResult)+import Hix.Managed.Data.StageState (BuildSuccess)+import Hix.Managed.Flow (Flow, runStage_)+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (BuildHandlers)+import qualified Hix.Managed.Handlers.Mutation.Lower as Mutation+import Hix.Managed.Lower.Candidates (candidatesOptimize)+import Hix.Managed.Lower.Data.LowerMode (lowerOptimizeMode)+import Hix.Managed.Process (processProject)+import Hix.Managed.Report (describeIterations)+import Hix.Managed.StageResult (stageResult)++lowerOptimizeUpdate :: Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints+lowerOptimizeUpdate _ _ PackageId {version} MutationConstraints {..} =+ MutationConstraints {mutation = fromUpper version, ..}++success :: Map MutableDep BuildSuccess -> Natural -> Text+success _ iterations =+ [exon|Found optimal lower bounds for all deps after #{describeIterations iterations}.|]++failure :: Natural -> Text+failure iterations =+ [exon|Couldn't find working lower bounds for some deps after #{describeIterations iterations}.|]++lowerOptimize ::+ BuildHandlers ->+ BuildConfig ->+ StageContext ->+ M StageResult+lowerOptimize handlers conf context@StageContext {env, state = Initial MutationState {versions}} =+ stageResult success failure <$> processQuery candidates mutationHandlers conf context ext+ where+ candidates = candidatesOptimize handlers.versions context.initial++ mutationHandlers = Mutation.handlersLower conf lowerOptimizeMode lowerOptimizeUpdate++ ext = solverState env.solverBounds env.deps (fromVersions fromUpper versions) def++lowerOptimizeStage ::+ BuildHandlers ->+ BuildConfig ->+ Flow ()+lowerOptimizeStage handlers conf =+ runStage_ "optimize" (lowerOptimize handlers conf)++lowerOptimizeMain ::+ BuildHandlers ->+ ProjectContext ->+ M ProjectResult+lowerOptimizeMain handlers project =+ processProject handlers project (lowerOptimizeStage handlers project.build)
+ lib/Hix/Managed/Lower/Stabilize.hs view
@@ -0,0 +1,146 @@+module Hix.Managed.Lower.Stabilize where++import Exon (exon)++import Hix.Class.Map (nToMaybe, (!!))+import Hix.Data.Monad (M)+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import qualified Hix.Data.VersionBounds+import Hix.Data.VersionBounds (VersionBounds (VersionBounds), fromLower, fromUpper)+import Hix.Managed.Build (processQuery)+import Hix.Managed.Build.Single (buildVersions)+import Hix.Managed.Cabal.Data.SolverState (solverState)+import Hix.Managed.Constraints (fromVersions)+import Hix.Managed.Data.BuildConfig (BuildConfig)+import qualified Hix.Managed.Data.Constraints+import Hix.Managed.Data.Constraints (MutationConstraints (MutationConstraints))+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.Initial (Initial (Initial))+import Hix.Managed.Data.Mutable (MutableDep, MutableVersions, depName)+import qualified Hix.Managed.Data.MutableId+import Hix.Managed.Data.MutableId (MutableId)+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState (MutationState))+import qualified Hix.Managed.Data.ProjectContext+import Hix.Managed.Data.ProjectContext (ProjectContext)+import Hix.Managed.Data.ProjectResult (ProjectResult)+import qualified Hix.Managed.Data.QueryDep+import qualified Hix.Managed.Data.StageContext+import Hix.Managed.Data.StageContext (StageContext (StageContext))+import Hix.Managed.Data.StageResult (+ StageFailure (FailedPrecondition),+ StageResult,+ StageSummary (StageFailure, StageNoAction),+ )+import Hix.Managed.Data.StageState (BuildStatus (Failure, Success), BuildSuccess)+import Hix.Managed.Flow (Flow, execStatelessStage, runStage_)+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (BuildHandlers)+import qualified Hix.Managed.Handlers.Mutation.Lower as Mutation+import Hix.Managed.Lower.Candidates (candidatesStabilize)+import Hix.Managed.Lower.Data.LowerMode (lowerStabilizeMode)+import Hix.Managed.Process (processProject)+import Hix.Managed.Report (describeIterations)+import Hix.Managed.StageResult (stageResult)++-- TODO When some initial versions are missing, e.g. because the user added deps and the project broke at the same time,+-- it is up to luck that the solver chooses working versions.+-- Unlikely that there's a useful heuristic though.+initialVersions ::+ MutableVersions ->+ [PackageId]+initialVersions state =+ nToMaybe state \ name -> fmap (initVersion name)+ where+ initVersion name version = PackageId {name = depName name, ..}++buildLowerInit :: Flow BuildStatus+buildLowerInit = do+ execStatelessStage "stabilize-initial" \ StageContext {env, initial, builder} ->+ buildVersions builder env "initial lower bounds" initial <&> \case+ Success -> StageNoAction (Just "Env builds successfully with the initial bounds.")+ Failure ->+ StageFailure (FailedPrecondition msg)+ where+ msg =+ [+ "Cannot stabilize since the build with initial bounds failed.",+ "Please run 'lower.init --reset' or fix the build manually."+ ]++lowerStabilizeUpdate :: Bool -> MutableId -> PackageId -> MutationConstraints -> MutationConstraints+lowerStabilizeUpdate retract candidate PackageId {name, version} MutationConstraints {..}+ | retract+ , depName candidate.name == name+ = MutationConstraints {mutation = fromLower version, oldest = Just True, ..}+ | VersionBounds {lower = Just _} <- mutation+ = MutationConstraints {mutation = fromLower version, ..}+ | otherwise+ = MutationConstraints {mutation = fromUpper version, ..}++success :: Map MutableDep BuildSuccess -> Natural -> Text+success _ iterations =+ [exon|Found stable lower bounds for all deps after #{iter}.|]+ where+ iter = describeIterations iterations++failure :: Natural -> Text+failure iterations =+ [exon|Couldn't find working lower bounds for some deps after #{describeIterations iterations}.|]++-- | This uses 'lowerInit' for the initial solver bounds, which gets translated to an extended bound treated as an+-- upper.+-- When a stable version was found, it will be set as a retracted bound, treated as a lower.+lowerStabilize ::+ BuildHandlers ->+ BuildConfig ->+ StageContext ->+ M StageResult+lowerStabilize handlers conf context =+ stageResult success failure <$> processQuery candidates mutationHandlers conf context ext+ where+ candidates query = candidatesStabilize handlers.versions query (join (context.initial !! query.package))++ mutationHandlers = Mutation.handlersLower conf lowerStabilizeMode lowerStabilizeUpdate++ ext = solverState context.env.solverBounds context.env.deps (fromVersions fromUpper context.initial) def++stabilizeStage ::+ BuildHandlers ->+ BuildConfig ->+ Flow ()+stabilizeStage handlers conf =+ runStage_ "stabilize" (lowerStabilize handlers conf)++stabilizeIfPossible ::+ BuildHandlers ->+ BuildConfig ->+ Flow ()+stabilizeIfPossible handlers conf =+ buildLowerInit >>= \case+ Success -> stabilizeStage handlers conf+ Failure -> unit++validateCurrent :: Flow BuildStatus+validateCurrent =+ execStatelessStage "stabilize-current" \ StageContext {env, state = Initial MutationState {versions}, builder} ->+ buildVersions builder env "current lower bounds" versions <&> \case+ Success -> StageNoAction (Just "Env builds successfully with the current bounds.")+ Failure -> StageFailure (FailedPrecondition ["Env does not build successfully with the current bounds."])++lowerStabilizeStages ::+ BuildHandlers ->+ BuildConfig ->+ Flow ()+lowerStabilizeStages handlers conf =+ validateCurrent >>= \case+ Success -> unit+ Failure -> stabilizeIfPossible handlers conf++lowerStabilizeMain ::+ BuildHandlers ->+ ProjectContext ->+ M ProjectResult+lowerStabilizeMain handlers project =+ processProject handlers project (lowerStabilizeStages handlers project.build)
+ lib/Hix/Managed/ManagedPackage.hs view
@@ -0,0 +1,27 @@+module Hix.Managed.ManagedPackage where++import Hix.Class.Map (nFlatten, nKeys, nMap, nRestrictKeys, nWithoutKeys)+import Hix.Data.PackageName (LocalPackage)+import qualified Hix.Managed.Data.ManagedPackage+import Hix.Managed.Data.ManagedPackage (ManagedPackage)+import Hix.Managed.Data.Mutable (LocalRanges, MutableRanges)+import Hix.Managed.Data.Packages (Packages)+import Hix.Managed.Data.Targets (Targets, sortTargets, targetsSet)++forTargets :: Packages ManagedPackage -> [LocalPackage] -> (Targets, LocalRanges, MutableRanges)+forTargets packages targetNames =+ (targets, local, mutable)+ where+ mutable = nFlatten id (nMap (.mutable) targetPackages :: Packages MutableRanges)++ -- Remove the targets from the local deps+ local = nWithoutKeys tset (nFlatten id (nMap (.local) targetPackages :: Packages LocalRanges))++ targetPackages = nRestrictKeys tset packages++ tset = targetsSet targets++ targets = sortTargets (nMap nKeys allLocal) targetNames++ allLocal :: Packages LocalRanges+ allLocal = nMap (.local) packages
+ lib/Hix/Managed/ManagedPackageProto.hs view
@@ -0,0 +1,27 @@+module Hix.Managed.ManagedPackageProto where++import Hix.Class.Map (nFromList, nKeysSet, nMap)+import qualified Hix.Managed.Data.ManagedPackage+import Hix.Managed.Data.ManagedPackage (ManagedPackage (ManagedPackage))+import qualified Hix.Managed.Data.ManagedPackageProto+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto (ManagedPackageProto))+import Hix.Managed.Data.Mutable (classifyPackageDep)+import Hix.Managed.Data.Packages (Packages)++validate ::+ Packages ManagedPackageProto ->+ Packages ManagedPackage+validate proto =+ nMap package proto+ where+ package ManagedPackageProto {..} =+ ManagedPackage {+ package = name,+ version,+ local = nFromList localDeps,+ mutable = nFromList mutableDeps+ }+ where+ (localDeps, mutableDeps) = partitionEithers (classifyPackageDep locals <$> deps)++ locals = nKeysSet proto
+ lib/Hix/Managed/Overrides.hs view
@@ -0,0 +1,26 @@+module Hix.Managed.Overrides where++import qualified Data.Map.Strict as Map++import Hix.Data.Monad (M)+import Hix.Data.Overrides (Override (..), Overrides (Overrides))+import qualified Hix.Data.PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.PackageName (PackageName)+import qualified Hix.Managed.Handlers.Hackage+import Hix.Managed.Handlers.Hackage (HackageHandlers)++packageOverride ::+ HackageHandlers ->+ PackageId ->+ M (PackageName, Override)+packageOverride handlers package@PackageId {name, version} = do+ hash <- handlers.fetchHash package+ pure (name, Override {..})++packageOverrides ::+ HackageHandlers ->+ [PackageId] ->+ M Overrides+packageOverrides handlers versions =+ Overrides . Map.fromList <$> traverse (packageOverride handlers) versions
+ lib/Hix/Managed/Path.hs view
@@ -0,0 +1,14 @@+module Hix.Managed.Path where++import Path (Abs, Dir, Path)+import Path.IO (getCurrentDir)++import Hix.Data.Monad (M)+import Hix.Monad (tryIOM)++-- TODO find better home+rootOrCwd ::+ Maybe (Path Abs Dir) ->+ M (Path Abs Dir)+rootOrCwd =+ maybe (tryIOM getCurrentDir) pure
+ lib/Hix/Managed/Process.hs view
@@ -0,0 +1,70 @@+module Hix.Managed.Process where++import Data.Generics.Labels ()+import Distribution.Pretty (pretty)+import Exon (exon)++import Hix.Data.EnvName (EnvName)+import Hix.Data.Monad (M)+import qualified Hix.Log as Log+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext)+import qualified Hix.Managed.Data.EnvRequest+import qualified Hix.Managed.Data.EnvResult+import Hix.Managed.Data.EnvResult (EnvResult (EnvResult))+import qualified Hix.Managed.Data.ProcessState+import Hix.Managed.Data.ProcessState (ProcessState, initProcessState)+import qualified Hix.Managed.Data.ProjectContext+import Hix.Managed.Data.ProjectContext (ProjectContext)+import qualified Hix.Managed.Data.ProjectResult+import Hix.Managed.Data.ProjectResult (ProjectResult (ProjectResult))+import Hix.Managed.Data.StageResult (StageSummary (StageNoAction))+import Hix.Managed.EnvRequest (withEnvRequest)+import Hix.Managed.Flow (Flow, execFlow)+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (BuildHandlers (BuildHandlers), Builder)+import Hix.Monad (mapAccumM)++processEnv ::+ BuildHandlers ->+ Flow () ->+ Builder ->+ ProcessState ->+ EnvContext ->+ M (ProcessState, EnvResult)+processEnv build process builder state context = do+ withEnvRequest build state context builder \ request -> do+ Log.debug [exon|Processing env '##{context.env :: EnvName}' with initial state:|]+ Log.debugP (pretty request.state)+ execFlow request process++skipResult :: StageSummary+skipResult =+ StageNoAction (Just "This environment has no manageable dependencies.")++processOrSkip ::+ (ProcessState -> EnvContext -> M (ProcessState, EnvResult)) ->+ ProcessState ->+ Either EnvName EnvContext ->+ M (ProcessState, EnvResult)+processOrSkip process state = \case+ Right context -> process state context+ Left env -> pure (state, EnvResult {env, state = Nothing, summaries = [skipResult]})++foldEnvs ::+ ProjectContext ->+ (ProcessState -> EnvContext -> M (ProcessState, EnvResult)) ->+ M ProjectResult+foldEnvs project process = do+ (final, envs) <- mapAccumM (processOrSkip process) (initProcessState project) project.envs+ pure ProjectResult {envs, state = final.state}++processProject ::+ BuildHandlers ->+ ProjectContext ->+ Flow () ->+ M ProjectResult+processProject build project process =+ withBuilder \ builder -> foldEnvs project (processEnv build process builder)+ where+ BuildHandlers {withBuilder} = build
+ lib/Hix/Managed/ProjectContext.hs view
@@ -0,0 +1,51 @@+module Hix.Managed.ProjectContext where++import Control.Monad.Trans.Reader (ask)++import qualified Hix.Data.Monad+import Hix.Data.Monad (AppResources (AppResources), M (M))+import qualified Hix.Data.Options+import Hix.Data.Options (ProjectOptions)+import Hix.Managed.BuildOutput (buildOutput, outputResult)+import qualified Hix.Managed.Data.BuildConfig+import Hix.Managed.Data.BuildConfig (BuildConfig)+import Hix.Managed.Data.ProjectContext (ProjectContext)+import Hix.Managed.Data.ProjectContextProto (ProjectContextProto)+import qualified Hix.Managed.Data.ProjectResult+import Hix.Managed.Data.ProjectResult (ProjectResult)+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.Handlers.Build (BuildHandlers)+import qualified Hix.Managed.Handlers.Report+import qualified Hix.Managed.ProjectContextProto as ProjectContextProto+import Hix.Managed.StateFile (writeProjectState)++updateProject ::+ BuildHandlers ->+ BuildConfig ->+ ProjectResult ->+ M ()+updateProject handlers buildConf results = do+ unless buildConf.validate do+ writeProjectState handlers.stateFile results.state+ handlers.report.mutations results++processBuildResults ::+ BuildHandlers ->+ BuildConfig ->+ ProjectResult ->+ M ()+processBuildResults handlers buildConf results = do+ updateProject handlers buildConf results+ AppResources {output = format, target} <- M ask+ outputResult (buildOutput results) target format++withProjectContext ::+ BuildHandlers ->+ ProjectOptions ->+ ProjectContextProto ->+ (ProjectContext -> M ProjectResult) ->+ M ()+withProjectContext handlers opts proto use = do+ project <- ProjectContextProto.validate opts proto+ result <- use project+ processBuildResults handlers opts.build result
+ lib/Hix/Managed/ProjectContextProto.hs view
@@ -0,0 +1,89 @@+module Hix.Managed.ProjectContextProto where++import Exon (exon)++import Hix.Class.Map (nBy, nKeys, nKeysSet, nMap, nTo, (!!), (!?))+import Hix.Data.EnvName (EnvName)+import Hix.Data.Monad (M)+import qualified Hix.Data.Options+import Hix.Data.Options (ProjectOptions)+import Hix.Managed.Data.BuildConfig (BuildConfig)+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext, EnvDeps)+import Hix.Managed.Data.Envs (Envs)+import qualified Hix.Managed.Data.ManagedPackage+import Hix.Managed.Data.ManagedPackage (ManagedPackage (ManagedPackage))+import Hix.Managed.Data.Mutable (MutableDep, depName)+import Hix.Managed.Data.Packages (Deps, Packages)+import qualified Hix.Managed.Data.ProjectContext+import Hix.Managed.Data.ProjectContext (ProjectContext (ProjectContext))+import qualified Hix.Managed.Data.ProjectContextProto+import Hix.Managed.Data.ProjectContextProto (ProjectContextProto)+import Hix.Managed.Data.ProjectState (ProjectState)+import Hix.Managed.Data.Query (RawQuery (RawQuery))+import Hix.Managed.EnvContext (envContexts)+import qualified Hix.Managed.ManagedPackageProto as ManagedPackageProto+import qualified Hix.Managed.ProjectStateProto as ProjectStateProto+import Hix.Monad (clientError, noteClient)++validateQuery ::+ Packages ManagedPackage ->+ RawQuery ->+ M (Maybe (NonEmpty MutableDep))+validateQuery packages (RawQuery deps) =+ nonEmpty <$> traverse check deps+ where+ check dep | Just m <- mutables !! dep = pure m+ | otherwise = clientError [exon|'##{dep}' is not a dependency of any package.|]++ mutables :: Deps MutableDep+ mutables = nBy mutablesSet depName+ mutablesSet = mconcat (nTo packages \ _ ManagedPackage {mutable} -> nKeysSet mutable)++noEnvs :: Text+noEnvs =+ [exon|The flake config contains no managed envs.+Most likely this means that you ran the CLI directly.+Please use one of the flake apps '.#bump', .#lower.init', '.#lower.optimize' or '.#lower.stabilize'.|]++unknownEnv :: EnvName -> Text+unknownEnv name =+ [exon|You requested to update the env '##{name}', but it is not present in the managed deps config.+Maybe this env is not enabled for managed dependencies.|]++selectEnvs ::+ Envs (Either EnvDeps EnvContext) ->+ [EnvName] ->+ M (NonEmpty (Either EnvName EnvContext))+selectEnvs envs specified =+ traverse valid =<< noteClient noEnvs (nonEmpty specified <|> nonEmpty (nKeys envs))+ where+ valid env = noteClient (unknownEnv env) (first (const env) <$> envs !? env)++projectContext ::+ BuildConfig ->+ ProjectState ->+ Packages ManagedPackage ->+ NonEmpty (Either EnvName EnvContext) ->+ ProjectContext+projectContext build state packages envs =+ ProjectContext {+ build,+ state,+ packages,+ envs+ }++validate ::+ ProjectOptions ->+ ProjectContextProto ->+ M ProjectContext+validate opts proto = do+ query <- validateQuery packages opts.query+ contexts <- envContexts opts packages proto.envs query+ let envDeps = nMap (either id (.deps)) contexts+ state <- ProjectStateProto.validateProjectState opts packages envDeps proto.state+ envTargets <- selectEnvs contexts opts.envs+ pure (projectContext opts.build state packages envTargets)+ where+ packages = ManagedPackageProto.validate proto.packages
+ lib/Hix/Managed/ProjectResult.hs view
@@ -0,0 +1,16 @@+module Hix.Managed.ProjectResult where++import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (FailedMutation)+import qualified Hix.Managed.Data.ProjectResult+import Hix.Managed.Data.ProjectResult (ProjectResult (ProjectResult))+import qualified Hix.Managed.EnvResult as EnvResult+import Hix.Managed.EnvResult (DepResults, normalizeDepResults)++grouped :: ProjectResult -> DepResults+grouped ProjectResult {envs} =+ normalizeDepResults (foldMap EnvResult.grouped envs)++failures :: ProjectResult -> [FailedMutation]+failures ProjectResult {envs} =+ sortOn (.package) (EnvResult.failures =<< toList envs)
+ lib/Hix/Managed/ProjectStateProto.hs view
@@ -0,0 +1,141 @@+module Hix.Managed.ProjectStateProto where++import Data.Map.Merge.Strict (mapMissing, traverseMaybeMissing, traverseMissing, zipWithAMatched, zipWithMatched)+import Exon (exon)++import Hix.Class.Map (NMap, nBy, nElems, nFromKeys, nMap, nMergeA, nTransform)+import Hix.Data.Bounds (Bounds)+import Hix.Data.EnvName (EnvName)+import Hix.Data.Monad (M)+import qualified Hix.Data.Options+import Hix.Data.Options (ProjectOptions)+import Hix.Data.PackageName (LocalPackage, PackageName)+import Hix.Data.Version (Version, VersionRange, Versions)+import Hix.Data.VersionBounds (anyBounds, withUpper)+import qualified Hix.Log as Log+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvDeps (EnvDeps))+import Hix.Managed.Data.Envs (Envs)+import qualified Hix.Managed.Data.ManagedPackage+import Hix.Managed.Data.ManagedPackage (ManagedPackage (ManagedPackage))+import Hix.Managed.Data.Mutable (MutableBounds, MutableDep, MutableRanges, depName)+import Hix.Managed.Data.Packages (Deps, Packages)+import qualified Hix.Managed.Data.ProjectState+import Hix.Managed.Data.ProjectState (ProjectState (ProjectState))+import qualified Hix.Managed.Data.ProjectStateProto+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto)+import Hix.Version (upperVersion)++invalidDep ::+ ∀ a b .+ LocalPackage ->+ PackageName ->+ a ->+ M (Maybe b)+invalidDep package dep _ =+ Nothing <$ Log.warn [exon|Discarding bound for invalid dep '##{dep}' of package '##{package}'|]++packageDepsForMerge :: MutableRanges -> Deps (MutableDep, VersionRange)+packageDepsForMerge =+ nTransform \ name range -> (depName name, (name, range))++envDepsForMerge :: Envs EnvDeps -> Envs (Deps MutableDep)+envDepsForMerge =+ nMap \ EnvDeps {mutable} -> nBy mutable depName++toMutable ::+ NMap map MutableDep a sort =>+ Deps (MutableDep, a) ->+ map+toMutable = nTransform \ _ -> id++validateBounds ::+ Bool ->+ LocalPackage ->+ ManagedPackage ->+ Bounds ->+ M MutableBounds+validateBounds readUpper package ManagedPackage {mutable} bounds =+ toMutable <$> nMergeA stateMissing depMissing convertBound deps bounds+ where+ deps = packageDepsForMerge mutable++ stateMissing = mapMissing \ _ (name, range) -> (name, handleUpper range anyBounds)++ depMissing = traverseMaybeMissing (invalidDep package)++ convertBound = zipWithMatched \ _ (name, range) bound -> (name, handleUpper range bound)++ handleUpper range | readUpper, Just u <- upperVersion range = withUpper u+ | otherwise = id++invalidBoundsPackage :: LocalPackage -> a -> M (Maybe b)+invalidBoundsPackage package _ =+ Nothing <$ Log.warn [exon|Discarding bounds for unknown local package '##{package}'|]++validateProjectBounds ::+ Bool ->+ Packages ManagedPackage ->+ Packages Bounds ->+ M (Packages MutableBounds)+validateProjectBounds readUpper =+ nMergeA boundsMissing (traverseMaybeMissing invalidBoundsPackage) (zipWithAMatched (validateBounds readUpper))+ where+ boundsMissing = traverseMissing \ name package -> validateBounds readUpper name package mempty++invalidStateDep :: Text -> EnvName -> PackageName -> a -> M (Maybe b)+invalidStateDep desc env package _ =+ Nothing <$ Log.warn [exon|Discarding #{desc} for unknown dep '##{package}' of env '##{env}'|]++validateVersions ::+ NMap map MutableDep (Maybe Version) sort =>+ Text ->+ EnvName ->+ Deps MutableDep ->+ Versions ->+ M map+validateVersions desc env deps bounds =+ toMutable <$> nMergeA stateMissing envMissing matching deps bounds+ where+ stateMissing = mapMissing \ _ dep -> (dep, Nothing)+ envMissing = traverseMaybeMissing (invalidStateDep desc env)+ matching = zipWithMatched \ _ dep version -> (dep, Just version)++-- TODO ugly+emptyVersions ::+ NMap map MutableDep (Maybe Version) sort =>+ Deps MutableDep ->+ map+emptyVersions deps =+ nFromKeys (nElems deps) (const Nothing)++invalidVersions :: Text -> EnvName -> a -> M (Maybe b)+invalidVersions desc env _ =+ Nothing <$ Log.warn [exon|Discarding #{desc} for unknown env '##{env}'|]++validateProjectVersions ::+ NMap map MutableDep (Maybe Version) sort =>+ Text ->+ Envs (Deps MutableDep) ->+ Envs Versions ->+ M (Envs map)+validateProjectVersions desc =+ nMergeA stateMissing envMissing matching+ where+ stateMissing = mapMissing (const emptyVersions)+ envMissing = traverseMaybeMissing (invalidVersions desc)+ matching = zipWithAMatched (validateVersions desc)++validateProjectState ::+ ProjectOptions ->+ Packages ManagedPackage ->+ Envs EnvDeps ->+ ProjectStateProto ->+ M ProjectState+validateProjectState opts packages envDeps proto = do+ bounds <- validateProjectBounds opts.readUpperBounds packages proto.bounds+ versions <- validateProjectVersions "bound versions" depSets proto.versions+ initial <- validateProjectVersions "initial versions" depSets proto.initial+ pure ProjectState {overrides = proto.overrides, resolving = False, ..}+ where+ depSets = envDepsForMerge envDeps
+ lib/Hix/Managed/QueryDep.hs view
@@ -0,0 +1,36 @@+module Hix.Managed.QueryDep where++import Hix.Class.Map ((!!))+import qualified Hix.Data.Overrides+import Hix.Data.VersionBounds (VersionBounds)+import Hix.Managed.Data.Initial (Initial (Initial))+import Hix.Managed.Data.Mutable (MutableBounds, MutableDep, depName)+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState)+import qualified Hix.Managed.Data.QueryDep+import Hix.Managed.Data.QueryDep (QueryDep (QueryDep))+import qualified Hix.Managed.Handlers.Cabal+import Hix.Managed.Handlers.Cabal (CabalHandlers)++-- | Add the current bounds to the queried deps.+-- This is used when determining candidates.+queryDep ::+ CabalHandlers ->+ Initial MutationState ->+ MutableBounds ->+ MutableDep ->+ QueryDep+queryDep cabal (Initial state) bounds package =+ QueryDep {+ package,+ installed = cabal.installedVersion name,+ current = join (state.versions !! package),+ override = (.version) <$> state.overrides !! name,+ bounds = fold (bounds !! package)+ }+ where+ name = depName package++simpleQueryDep :: MutableDep -> VersionBounds -> QueryDep+simpleQueryDep package bounds =+ QueryDep {installed = Nothing, current = Nothing, override = Nothing, ..}
+ lib/Hix/Managed/Report.hs view
@@ -0,0 +1,15 @@+module Hix.Managed.Report where++import Exon (exon)++plural ::+ Eq a =>+ Num a =>+ a ->+ Text+plural num | num == 1 = ""+ | otherwise = "s"++describeIterations :: Natural -> Text+describeIterations iterations =+ [exon|#{show iterations} iteration#{plural iterations}|]
+ lib/Hix/Managed/StageContext.hs view
@@ -0,0 +1,39 @@+module Hix.Managed.StageContext where++import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvRequest (EnvRequest (..))+import qualified Hix.Managed.Data.EnvState+import Hix.Managed.Data.EnvState (EnvState (EnvState))+import Hix.Managed.Data.Initial (Initial (Initial))+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState (MutationState))+import Hix.Managed.Data.Query (Query (Query))+import Hix.Managed.Data.StageContext (StageContext (..))+import Hix.Managed.Diff (reifyBoundsChanges, reifyVersionChanges)+import qualified Hix.Managed.Handlers.Build+import Hix.Managed.QueryDep (queryDep)++-- | Initialize the mutation versions from the persisted state, so the solver bounds are populated by the versions+-- determined in previous runs.+--+-- @bounds@ is initialized empty because it is used only for updating based on candidates, since upper bounds differ+-- from the tested versions.+mutationState :: EnvState -> Initial MutationState+mutationState EnvState {versions, overrides} =+ Initial MutationState {+ bounds = mempty,+ versions = reifyVersionChanges versions,+ overrides,+ initial = mempty+ }++stageContext :: EnvRequest -> EnvState -> StageContext+stageContext EnvRequest {context = env, builder} envState =+ StageContext {+ query = Query (queryDep builder.cabal state bounds <$> env.query),+ initial = reifyVersionChanges envState.initial,+ ..+ }+ where+ bounds = reifyBoundsChanges envState.bounds+ state = mutationState envState
+ lib/Hix/Managed/StageResult.hs view
@@ -0,0 +1,54 @@+module Hix.Managed.StageResult where++import qualified Data.Map.Strict as Map+import Distribution.Pretty (Pretty)++import Hix.Class.Map (nRestrictKeys)+import Hix.Managed.Data.Mutable (MutableDep)+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (failedMutation)+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState (MutationState))+import qualified Hix.Managed.Data.StageResult+import Hix.Managed.Data.StageResult (+ StageFailure (FailedMutations),+ StageResult (StageResult),+ StageSummary (StageFailure, StageNoAction, StageSuccess),+ )+import qualified Hix.Managed.Data.StageState+import Hix.Managed.Data.StageState (BuildSuccess, StageState (StageState))++stageResultWith ::+ Pretty a =>+ (Map MutableDep BuildSuccess -> MutationState -> MutationState) ->+ (Map MutableDep BuildSuccess -> Natural -> Text) ->+ (Natural -> Text) ->+ StageState a s ->+ StageResult+stageResultWith finalize successMessage failureMessage StageState {success, failed, state, iterations} =+ StageResult {state = Just (finalize success state), summary}+ where+ summary =+ case nonEmpty (sortOn (.package) failed) of+ Just failedNe -> StageFailure (FailedMutations (failureMessage iterations) (failedMutation <$> failedNe))+ Nothing | [] <- success -> StageNoAction (Just "All dependencies are up to date.")+ | otherwise -> StageSuccess (successMessage success iterations)++stageResult ::+ Pretty a =>+ (Map MutableDep BuildSuccess -> Natural -> Text) ->+ (Natural -> Text) ->+ StageState a s ->+ StageResult+stageResult =+ stageResultWith (const id)++stageResultInit ::+ Pretty a =>+ (Map MutableDep BuildSuccess -> Natural -> Text) ->+ (Natural -> Text) ->+ StageState a s ->+ StageResult+stageResultInit =+ stageResultWith \ success MutationState {..} ->+ MutationState {initial = nRestrictKeys (Map.keysSet success) versions, ..}
+ lib/Hix/Managed/StageState.hs view
@@ -0,0 +1,28 @@+module Hix.Managed.StageState where++import qualified Data.Map.Strict as Map++import qualified Hix.Managed.Data.MutableId+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (DepMutation, MutationResult (..))+import Hix.Managed.Data.StageState (BuildSuccess (CandidateBuilt, Unmodified), StageState (..))++updateStageState ::+ StageState a s ->+ DepMutation a ->+ MutationResult s ->+ StageState a s+updateStageState old mutation = \case+ MutationSuccess candidate changed state ext ->+ old {+ success = Map.insert candidate.name buildSuccess old.success,+ state,+ ext+ }+ where+ buildSuccess | changed = CandidateBuilt candidate+ | otherwise = Unmodified mutation.package+ MutationKeep ->+ old {success = Map.insert mutation.package (Unmodified mutation.package) old.success}+ MutationFailed ->+ old {failed = mutation : old.failed}
+ lib/Hix/Managed/StateFile.hs view
@@ -0,0 +1,70 @@+module Hix.Managed.StateFile where++import qualified Data.Map.Strict as Map+import Exon (exon)+import Path (Abs, Dir, Path)++import Hix.Class.EncodeNix (encodeNix)+import Hix.Data.Monad (M)+import Hix.Data.NixExpr (Expr (..), ExprAttr (..))+import Hix.Data.Overrides (Overrides)+import qualified Hix.Log as Log+import Hix.Managed.Data.EnvContext (EnvContext)+import qualified Hix.Managed.Data.EnvState+import Hix.Managed.Data.EnvState (EnvState)+import Hix.Managed.Data.Initial (Initial (Initial))+import Hix.Managed.Data.ProjectState (ProjectState)+import qualified Hix.Managed.Handlers.StateFile+import Hix.Managed.Handlers.StateFile (StateFileHandlers)+import Hix.Managed.UpdateState (envStateForBuild)+import Hix.NixExpr (renderRootExpr)++renderMap ::+ Coercible k Text =>+ (v -> Expr) ->+ Map k v ->+ Expr+renderMap v =+ ExprAttrs . fmap (uncurry ExprAttr . bimap coerce v) . Map.toList++renderManaged' :: ProjectState -> Expr+renderManaged' =+ encodeNix++writeStateFile ::+ Text ->+ StateFileHandlers ->+ Maybe (Path Abs Dir) ->+ ProjectState ->+ M ()+writeStateFile purpose handlers tmpRoot state = do+ Log.debug [exon|writing managed stated file for #{purpose}: #{renderRootExpr expr}|]+ handlers.writeFile tmpRoot expr+ where+ expr = encodeNix state++writeProjectState ::+ StateFileHandlers ->+ ProjectState ->+ M ()+writeProjectState handlers newState =+ writeStateFile "final result persistence" handlers Nothing newState++writeBuildStateFor ::+ Text ->+ StateFileHandlers ->+ Path Abs Dir ->+ EnvContext ->+ Overrides ->+ M ()+writeBuildStateFor purpose handlers tmpRoot context overrides =+ writeStateFile purpose handlers (Just tmpRoot) (envStateForBuild context overrides)++writeInitialEnvState ::+ StateFileHandlers ->+ Path Abs Dir ->+ EnvContext ->+ Initial EnvState ->+ M ()+writeInitialEnvState handlers tmpRoot context (Initial state) =+ writeBuildStateFor "env initialization" handlers tmpRoot context state.overrides
+ lib/Hix/Managed/UpdateState.hs view
@@ -0,0 +1,67 @@+module Hix.Managed.UpdateState where++import Hix.Class.Map (nAdjust, nAmend, nInsert)+import Hix.Data.Overrides (Overrides)+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext)+import qualified Hix.Managed.Data.EnvState+import Hix.Managed.Data.EnvState (EnvState (EnvState))+import Hix.Managed.Data.Mutable (mutUpdateTargets)+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState)+import qualified Hix.Managed.Data.ProjectState+import Hix.Managed.Data.ProjectState (ProjectState (ProjectState))+import Hix.Managed.Diff (applyBoundsChange, applyVersionChange, updateBoundsChanges, updateVersionChanges)++-- | Insert the transformed 'EnvState', which contains only the bounds for the current target set and the overrides+-- for the current env.+--+-- All data is stored as diffs in 'EnvState' (except for overrides), which are applied to the initial state.+--+-- Since the env is intended to be exclusively used with its associated target set, we simply overwrite the existing one+-- completely.+--+-- Bounds are supposed to be universally valid, since they qualify the source rather than a build configuration, so they+-- have to be updated in each of the env's target packages.+--+-- @initial@ is the set of bounds that is preserved from the first run for each dependency.+-- The 'EnvState' only contains updates for them if an update for @versions@ contains @DiffAdded@, which is handled+-- in 'envStateWithMutations'.+projectStateWithEnv ::+ EnvContext ->+ EnvState ->+ ProjectState ->+ ProjectState+projectStateWithEnv context new old =+ ProjectState {+ bounds = mutUpdateTargets context.targets applyBoundsChange new.bounds old.bounds,+ versions = nAdjust context.env old.versions (nAmend applyVersionChange new.versions),+ overrides = nInsert context.env new.overrides old.overrides,+ initial = nAdjust context.env old.initial (nAmend applyVersionChange new.initial),+ resolving = old.resolving+ }++envStateForBuild ::+ EnvContext ->+ Overrides ->+ ProjectState+envStateForBuild context overrides =+ ProjectState {+ bounds = mempty,+ versions = mempty,+ overrides = [(context.env, overrides)],+ initial = [],+ resolving = True+ }++envStateWithMutations ::+ MutationState ->+ EnvState ->+ EnvState+envStateWithMutations new EnvState {bounds, versions, initial} =+ EnvState {+ bounds = updateBoundsChanges new.bounds bounds,+ versions = updateVersionChanges new.versions versions,+ overrides = new.overrides,+ initial = updateVersionChanges new.initial initial+ }
+ lib/Hix/Maybe.hs view
@@ -0,0 +1,20 @@+module Hix.Maybe where++-- |Return 'Just' if the condition is 'True'.+justIf ::+ Bool ->+ a ->+ Maybe a+justIf cond a =+ if cond then Just a else Nothing+{-# inline justIf #-}++-- |Version of 'maybe' that takes an action as fallback.+fromMaybeA ::+ Applicative m =>+ m a ->+ Maybe a ->+ m a+fromMaybeA fallback =+ maybe fallback pure+{-# inline fromMaybeA #-}
lib/Hix/Monad.hs view
@@ -1,44 +1,185 @@-module Hix.Monad where+module Hix.Monad (+ module Hix.Monad,+ AppResources (..),+ M,+) where import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.Except (ExceptT, runExceptT, throwE)-import Control.Monad.Trans.Reader (ReaderT (runReaderT))-import Path (Abs, Dir, Path)+import Control.Monad.Trans.Except (runExceptT, throwE, ExceptT (ExceptT))+import Control.Monad.Trans.Reader (ReaderT (runReaderT), ask, asks)+import Control.Monad.Trans.State.Strict (StateT, get, put, runStateT)+import Data.IORef (IORef, modifyIORef', newIORef, readIORef)+import qualified Data.Text as Text+import qualified Data.Text.IO as Text+import Exon (exon)+import Path (Abs, Dir, File, Path)+import qualified Path.IO as Path+import Path.IO (withSystemTempDir)+import System.IO (hClose)+import System.IO.Error (tryIOError) -import Hix.Data.Error (Error (BootstrapError, EnvError, GhciError, NewError), tryIO)+import qualified Hix.Console as Console+import Hix.Data.Error (Error (BootstrapError, Client, EnvError, GhciError, NewError))+import qualified Hix.Data.GlobalOptions as GlobalOptions+import Hix.Data.GlobalOptions (GlobalOptions (GlobalOptions), defaultGlobalOptions)+import Hix.Data.Monad (AppResources (..), LogLevel, M (M), liftE)+import Hix.Error (Error (Fatal), tryIO, tryIOWith)+import qualified Hix.Log as Log+import Hix.Log (logWith) -data Env =- Env {- cwd :: Path Abs Dir- }- deriving stock (Eq, Show, Generic)+throwM :: Error -> M a+throwM = liftE . throwE -type M a = ReaderT Env (ExceptT Error IO) a+clientError :: Text -> M a+clientError msg = throwM (Client msg) -throwM :: Error -> M a-throwM =- lift . throwE+fatalError :: Text -> M a+fatalError msg = throwM (Fatal msg) +note :: Error -> Maybe a -> M a+note err =+ maybe (throwM err) pure+ noteEnv :: Text -> Maybe a -> M a noteEnv err =- maybe (throwM (EnvError err)) pure+ note (EnvError err) noteGhci :: Text -> Maybe a -> M a noteGhci err =- maybe (throwM (GhciError err)) pure+ note (GhciError err) noteNew :: Text -> Maybe a -> M a noteNew err =- maybe (throwM (NewError err)) pure+ note (NewError err) noteBootstrap :: Text -> Maybe a -> M a noteBootstrap err =- maybe (throwM (BootstrapError err)) pure+ note (BootstrapError err) +noteClient :: Text -> Maybe a -> M a+noteClient err =+ note (Client err)++noteFatal :: Text -> Maybe a -> M a+noteFatal err =+ note (Fatal err)++eitherClient :: Either Text a -> M a+eitherClient = leftA clientError++eitherFatal :: Either Text a -> M a+eitherFatal = leftA fatalError++eitherFatalShow ::+ Show b =>+ Text ->+ Either b a ->+ M a+eitherFatalShow msg =+ eitherFatal . first mkMsg+ where+ mkMsg err = [exon|#{msg}: #{show err}|]++whenDebug :: M () -> M ()+whenDebug m =+ whenM (M (asks (.debug))) do+ m++logIORef :: IORef [Text] -> LogLevel -> Text -> IO ()+logIORef ref _ msg =+ modifyIORef' ref (msg :)++withLogIORef :: ((LogLevel -> Text -> IO ()) -> IO a) -> IO ([Text], a)+withLogIORef use = do+ logRef <- newIORef []+ result <- use (logIORef logRef)+ log <- readIORef logRef+ pure (log, result)++runMLoggerWith :: (LogLevel -> Text -> IO ()) -> GlobalOptions -> M a -> IO (Either Error a)+runMLoggerWith logger GlobalOptions {..} (M ma) =+ withSystemTempDir "hix-cli" \ tmp ->+ runExceptT (runReaderT ma AppResources {logger = logWith logger, ..})++runMLogWith :: GlobalOptions -> M a -> IO ([Text], Either Error a)+runMLogWith opts ma =+ withLogIORef \ logger -> runMLoggerWith logger opts ma++runMLog :: Path Abs Dir -> M a -> IO ([Text], Either Error a)+runMLog = runMLogWith . defaultGlobalOptions++runMWith :: GlobalOptions -> M a -> IO (Either Error a)+runMWith = runMLoggerWith (const Console.err)+ runM :: Path Abs Dir -> M a -> IO (Either Error a)-runM root ma =- runExceptT (runReaderT ma (Env root))+runM = runMWith . defaultGlobalOptions +runMDebug :: Path Abs Dir -> M a -> IO (Either Error a)+runMDebug cwd =+ runMWith (defaultGlobalOptions cwd) {GlobalOptions.verbose = True, GlobalOptions.debug = True}++tryIOMWithM :: (Text -> M a) -> IO a -> M a+tryIOMWithM handleError ma =+ liftIO (tryIOError ma) >>= \case+ Right a -> pure a+ Left err -> handleError (show err)++tryIOMWith :: (Text -> Error) -> IO a -> M a+tryIOMWith mkErr ma = M (lift (tryIOWith mkErr ma))++tryIOMAs :: Error -> IO a -> M a+tryIOMAs err ma = do+ liftIO (tryIOError ma) >>= \case+ Right a -> pure a+ Left exc -> do+ whenDebug do+ Log.error [exon|Replaced exception: #{show exc}|]+ throwM err+ tryIOM :: IO a -> M a-tryIOM ma =- lift (tryIO ma)+tryIOM ma = M (lift (tryIO ma))++catchIOM :: IO a -> (Text -> M a) -> M a+catchIOM ma handle =+ liftIO (tryIOError ma) >>= \case+ Right a -> pure a+ Left err -> handle (show err)++withTempDir :: String -> (Path Abs Dir -> M a) -> M a+withTempDir name use = do+ AppResources {tmp} <- M ask+ Path.withTempDir tmp name use++withTempFile :: String -> Maybe [Text] -> (Path Abs File -> M a) -> M a+withTempFile name content use = do+ AppResources {tmp} <- M ask+ Path.withTempFile tmp name \ file handle -> do+ for_ content \ lns -> liftIO (Text.hPutStr handle (Text.unlines lns))+ liftIO (hClose handle)+ use file++stateM ::+ Monad m =>+ (s -> a -> m (s, b)) ->+ a ->+ StateT s m b+stateM f a = do+ s <- get+ (s', b) <- lift (f s a)+ put s'+ pure b++mapAccumM ::+ Traversable t =>+ Monad m =>+ (s -> a -> m (s, b)) ->+ s ->+ t a ->+ m (s, t b)+mapAccumM f s as =+ swap <$> runStateT (traverse (stateM f) as) s++withLower :: (∀ b . (M a -> IO b) -> IO b) -> M a+withLower f = do+ res <- M ask+ liftE (ExceptT (f \ (M ma) -> runExceptT (runReaderT ma res)))
lib/Hix/New.hs view
@@ -86,7 +86,7 @@ test = { enable = true; dependencies = [- "hedgehog >= 1.1 && < 1.3"+ "hedgehog >= 1.1 && < 1.5" "tasty ^>= 1.4" "tasty-hedgehog >= 1.3 && < 1.5" ];@@ -172,5 +172,5 @@ modNameS = pascal (toString conf.name.unProjectName) newProject :: NewProjectConfig -> M ()-newProject conf = do+newProject conf = traverse_ createFile =<< newProjectFiles conf
+ lib/Hix/NixExpr.hs view
@@ -0,0 +1,126 @@+module Hix.NixExpr where++import Data.List.NonEmpty ((<|))+import qualified Data.Text as Text+import Exon (exon)++import Hix.Class.EncodeNix (EncodeNix (encodeNix))+import Hix.Data.NixExpr (Expr (..), ExprAttr (ExprAttr, ExprAttrNil))++indent ::+ Functor t =>+ Int ->+ t Text ->+ t Text+indent n =+ fmap (Text.replicate n " " <>)++withSemicolon :: NonEmpty Text -> NonEmpty Text+withSemicolon = \case+ e :| [] ->+ [e <> ";"]+ h :| h1 : t -> h <| withSemicolon (h1 :| t)++renderAttrs :: Int -> [ExprAttr] -> [Text]+renderAttrs ind attrs =+ attrs >>= \case+ ExprAttr k v ->+ case renderExpr ind v of+ e :| [] -> [[exon|#{k} = #{e};|]]+ h :| (h1 : t) -> [exon|#{k} = #{h}|] : toList (withSemicolon (h1 :| t))+ ExprAttrNil ->+ []++renderExpr :: Int -> Expr -> NonEmpty Text+renderExpr ind = \case+ ExprNull -> ["null"]+ ExprString s -> indent ind [[exon|"#{Text.replace "\"" "\\\"" s}"|]]+ ExprLit e -> [e]+ ExprList l -> "[" :| (indent (ind + 2) (toList . renderExpr ind =<< l)) ++ ["]"]+ ExprAttrs a -> case renderAttrs ind a of+ [] -> ["{}"]+ as -> "{" :| indent (ind + 2) as ++ ["}"]+ ExprPrefix p (renderExpr ind -> h :| t) ->+ [exon|#{p} #{h}|] :| t++renderRootExpr :: Expr -> Text+renderRootExpr =+ Text.unlines . toList . renderExpr 0++checkEmpty ::+ Text ->+ Expr ->+ ExprAttr+checkEmpty key = \case+ ExprString value | Text.null value ->+ ExprAttrNil+ ExprList value | null value ->+ ExprAttrNil+ value ->+ ExprAttr key value++singleOpt ::+ EncodeNix a =>+ Text ->+ (e -> Maybe a) ->+ e ->+ ExprAttr+singleOpt key get entity =+ maybe ExprAttrNil (checkEmpty key . encodeNix) (get entity)++single ::+ EncodeNix a =>+ Text ->+ (e -> a) ->+ e ->+ ExprAttr+single key get =+ singleOpt key (Just . get)++multiOpt ::+ EncodeNix a =>+ Text ->+ (e -> Maybe [a]) ->+ e ->+ ExprAttr+multiOpt key get entity =+ maybe ExprAttrNil (checkEmpty key . encodeNix) (get entity)++multi ::+ EncodeNix a =>+ Text ->+ (e -> [a]) ->+ e ->+ ExprAttr+multi key get =+ multiOpt key (Just . get)++multiOrSingle ::+ ∀ a e .+ EncodeNix a =>+ Text ->+ (e -> [a]) ->+ e ->+ ExprAttr+multiOrSingle key get entity =+ check (get entity)+ where+ check :: [a] -> ExprAttr+ check [] = ExprAttrNil+ check [sing] = ExprAttr key (encodeNix sing)+ check values = ExprAttr key (encodeNix values)++mkAttrs :: [e -> ExprAttr] -> e -> [ExprAttr]+mkAttrs a e =+ (fmap ($ e) a)++notNil :: ExprAttr -> Bool+notNil = \case+ ExprAttrNil -> False+ _ -> True++nonEmptyAttrs :: Text -> [ExprAttr] -> ExprAttr+nonEmptyAttrs key =+ filter notNil >>> \case+ [] -> ExprAttrNil+ as -> ExprAttr key (ExprAttrs as)
lib/Hix/Options.hs view
@@ -1,9 +1,11 @@ module Hix.Options where +import Exon (exon) import Options.Applicative ( CommandFields, Mod, Parser,+ auto, bashCompleter, command, completer,@@ -15,164 +17,77 @@ hsubparser, info, long,+ metavar, option, prefs, progDesc, short,+ showDefault, showHelpOnEmpty, showHelpOnError,+ strArgument, strOption,+ subparserInline, switch, value, )-import Path (Abs, Dir, File, Path, SomeBase, parseRelDir, parseSomeDir)+import Path (Abs, Dir, File, Path, parseRelDir, parseSomeDir) import Path.IO (getCurrentDir) import Prelude hiding (Mod, mod) import qualified Hix.Data.BootstrapProjectConfig import Hix.Data.BootstrapProjectConfig (BootstrapProjectConfig (BootstrapProjectConfig))-import Hix.Data.ComponentConfig (- ComponentName (ComponentName),- EnvName,- ModuleName,- PackageName (PackageName),- SourceDir (SourceDir),- )-import Hix.Data.GhciConfig (ChangeDir (ChangeDir), EnvConfig, GhciConfig, RunnerName)+import Hix.Data.ComponentConfig (ComponentName (ComponentName), ModuleName, SourceDir (SourceDir))+import Hix.Data.EnvName (EnvName)+import Hix.Data.GhciConfig (ChangeDir (ChangeDir), RunnerName)+import Hix.Data.GlobalOptions (GlobalOptions (..)) import qualified Hix.Data.NewProjectConfig import Hix.Data.NewProjectConfig (NewProjectConfig (NewProjectConfig))-import Hix.Data.PreprocConfig (PreprocConfig)-import Hix.Optparse (JsonConfig, absDirOption, absFileOption, jsonOption)--data PreprocOptions =- PreprocOptions {- config :: Maybe (Either PreprocConfig JsonConfig),- root :: Maybe (Path Abs Dir),- source :: Path Abs File,- inFile :: Path Abs File,- outFile :: Path Abs File- }- deriving stock (Show, Generic)--data PackageSpec =- PackageSpec {- name :: PackageName,- dir :: Maybe (SomeBase Dir)- }- deriving stock (Eq, Show, Generic)--data ComponentSpec =- ComponentSpec {- name :: ComponentName,- dir :: Maybe SourceDir- }- deriving stock (Eq, Show, Generic)--data ComponentCoords =- ComponentCoords {- package :: Maybe PackageSpec,- component :: Maybe ComponentSpec- }- deriving stock (Eq, Show, Generic)--data TargetSpec =- TargetForFile (Path Abs File)- |- TargetForComponent ComponentCoords- deriving stock (Eq, Show, Generic)--data TestOptions =- TestOptions {- mod :: ModuleName,- test :: Maybe Text,- runner :: Maybe RunnerName,- cd :: ChangeDir- }- deriving stock (Eq, Show, Generic)--data EnvRunnerOptions =- EnvRunnerOptions {- config :: Either EnvConfig JsonConfig,- root :: Maybe (Path Abs Dir),- component :: Maybe TargetSpec- }- deriving stock (Show, Generic)--newtype ExtraGhciOptions =- ExtraGhciOptions Text- deriving stock (Eq, Show, Generic)- deriving newtype (IsString)--newtype ExtraGhcidOptions =- ExtraGhcidOptions Text- deriving stock (Eq, Show, Generic)- deriving newtype (IsString)--data GhciOptions =- GhciOptions {- config :: Either GhciConfig JsonConfig,- root :: Maybe (Path Abs Dir),- component :: TargetSpec,- test :: TestOptions,- extra :: Maybe ExtraGhciOptions- }- deriving stock (Show, Generic)--data GhcidOptions =- GhcidOptions {- ghci :: GhciOptions,- extra :: Maybe ExtraGhcidOptions- }- deriving stock (Show, Generic)--data NewOptions =- NewOptions {- config :: NewProjectConfig- }- deriving stock (Eq, Show, Generic)--data BootstrapOptions =- BootstrapOptions {- config :: BootstrapProjectConfig- }- deriving stock (Eq, Show, Generic)--data EnvRunnerCommandOptions =- EnvRunnerCommandOptions {- options :: EnvRunnerOptions,- test :: TestOptions,- extraGhci :: Maybe ExtraGhciOptions,- extraGhcid :: Maybe ExtraGhcidOptions- }- deriving stock (Show, Generic)--data Command =- Preproc PreprocOptions- |- EnvRunner EnvRunnerCommandOptions- |- GhcidCmd GhcidOptions- |- GhciCmd GhciOptions- |- NewCmd NewOptions- |- BootstrapCmd BootstrapOptions- deriving stock (Show)--data GlobalOptions =- GlobalOptions {- verbose :: Maybe Bool,- cwd :: Path Abs Dir- }- deriving stock (Eq, Show, Generic)--data Options =- Options {- global :: GlobalOptions,- cmd :: Command- }- deriving stock (Show)+import qualified Hix.Data.Options+import Hix.Data.Options (+ BootstrapOptions (..),+ BumpOptions (..),+ Command (..),+ ComponentCoords (ComponentCoords),+ ComponentSpec (..),+ EnvRunnerCommandOptions (..),+ EnvRunnerOptions (EnvRunnerOptions, component, config, root),+ ExtraGhciOptions,+ ExtraGhcidOptions,+ GhciOptions (..),+ GhcidOptions (..),+ LowerCommand (..),+ LowerOptions (LowerOptions),+ ManagedOptions (ManagedOptions),+ NewOptions (..),+ Options (Options),+ PackageSpec (..),+ PreprocOptions (PreprocOptions),+ ProjectOptions (ProjectOptions),+ TargetSpec (..),+ TestOptions (..),+ )+import Hix.Data.OutputFormat (OutputFormat (OutputNone))+import Hix.Data.OutputTarget (OutputTarget (OutputDefault))+import Hix.Data.PackageName (PackageName (PackageName))+import qualified Hix.Managed.Cabal.Data.Config+import Hix.Managed.Cabal.Data.Config (CabalConfig (CabalConfig))+import qualified Hix.Managed.Data.BuildConfig+import Hix.Managed.Data.BuildConfig (BuildConfig (BuildConfig))+import Hix.Managed.Data.Query (RawQuery (RawQuery))+import qualified Hix.Managed.Data.StateFileConfig+import Hix.Managed.Data.StateFileConfig (StateFileConfig (StateFileConfig))+import Hix.Optparse (+ JsonConfig,+ absDirOption,+ absFileOption,+ buildHandlersOption,+ indexStateOption,+ jsonOption,+ outputFormatOption,+ outputTargetOption,+ relFileOption,+ ) fileParser :: String ->@@ -318,6 +233,89 @@ hixUrl <- strOption (long "hix-url" <> help "The URL to the Hix repository" <> value def) pure BootstrapOptions {config = BootstrapProjectConfig {..}} +stateFileConfigParser :: Parser StateFileConfig+stateFileConfigParser = do+ file <- option relFileOption (long "file" <> short 'f' <> help "The relative path to the managed deps file")+ -- TODO this isn't nice. maybe there should be two options, since the user might want to build bumps without modifying+ -- the state.+ projectRoot <- optional (option absDirOption (long "root" <> help "The root directory of the project"))+ pure StateFileConfig {..}++cabalConfigParser :: Parser CabalConfig+cabalConfigParser = do+ indexState <- optional (option indexStateOption (long "index-state" <> help indexStateHelp))+ pure CabalConfig {..}+ where+ indexStateHelp = "The index state for Hackage, Unix stamp or date string"++buildConfigParser :: Parser BuildConfig+buildConfigParser = do+ maxIterations <- option auto (long "max-iterations" <> help maxIterationsHelp <> value 3 <> showDefault)+ maxFailedPre <- option auto (long "max-failed-majors-pre" <> help maxFailedPreHelp <> value 99 <> showDefault)+ maxFailedPost <- option auto (long "max-failed-majors-post" <> help maxFailedPostHelp <> value 0 <> showDefault)+ lookup <- switch (long "lookup" <> short 'n' <> help "Only print latest versions (bump)")+ validate <- switch (long "validate" <> help "Validate new versions, but don't update the project state")+ buildOutput <- switch (long "build-output" <> help "Show output from Nix builds")+ pure BuildConfig {..}+ where+ maxIterationsHelp = "Number of restarts when some dependencies fail"+ maxFailedPreHelp = maxFailedHelp "prior to the first"+ maxFailedPostHelp = maxFailedHelp "after the last"+ maxFailedHelp variant = [exon|Number of majors that may fail before aborting, #{variant} success|]++projectOptionsParser :: Parser ProjectOptions+projectOptionsParser = do+ build <- buildConfigParser+ query <- RawQuery <$> many (strArgument (help "Positional arguments select individual deps for processing"))+ envs <- some (strOption (long "env" <> short 'e' <> help "Environments whose packages should be updated"))+ readUpperBounds <- switch (long "read-upper-bounds" <> help "Use the upper bounds from the flake for the first run")+ mergeBounds <- switch (long "merge-bounds" <> help "Always add the flake bounds to the managed bounds")+ pure ProjectOptions {..}++managedOptionsParser :: Parser ManagedOptions+managedOptionsParser = do+ context <- Right <$> jsonConfigParser+ project <- projectOptionsParser+ stateFile <- stateFileConfigParser+ handlers <- optional (option buildHandlersOption (long "handlers" <> help "Internal: Handlers for tests"))+ cabal <- cabalConfigParser+ pure ManagedOptions {..}++bumpParser :: Parser BumpOptions+bumpParser = do+ common <- managedOptionsParser+ pure BumpOptions {..}++lowerParser :: Parser LowerOptions+lowerParser = do+ initOnly <- switch (long "init" <> help "Only initialize missing lower bounds")+ reset <- switch (long "reset" <> help "Reinitialize bounds of all deps rather than just new ones")+ stabilize <- switch (long "stabilize" <> help "Attempt to find working bounds if the current ones are broken")+ common <- managedOptionsParser+ pure LowerOptions {..}++lowerCommands :: Mod CommandFields LowerCommand+lowerCommands =+ command "init" (LowerInitCmd <$> info lowerParser (progDesc "Initialize the lower bounds"))+ <>+ command "optimize" (LowerOptimizeCmd <$> info lowerParser (progDesc "Optimize the lower bounds"))+ <>+ command "stabilize" (LowerStabilizeCmd <$> info lowerParser (progDesc "Stabilize the lower bounds"))+ <>+ command "auto" (LowerAutoCmd <$> info lowerParser (progDesc "Process the lower bounds"))++lowerCommand :: Parser LowerCommand+lowerCommand =+ hsubparser lowerCommands <|> (LowerAutoCmd <$> lowerParser)++managedCommitMsgParser :: Parser (Path Abs File)+managedCommitMsgParser =+ option absFileOption (long "file" <> help "The JSON file written by a managed deps app")++managedGithubPrParser :: Parser (Path Abs File)+managedGithubPrParser =+ option absFileOption (long "file" <> help "The JSON file written by a managed deps app")+ commands :: Mod CommandFields Command commands = command "preproc" (Preproc <$> info preprocParser (progDesc "Preprocess a source file for use with ghcid"))@@ -330,15 +328,28 @@ <> command "new" (NewCmd <$> info newParser (progDesc "Create a new Hix project in the current directory")) <>- command "bootstrap" (BootstrapCmd <$> info bootstrapParser (progDesc "Bootstrap an existing Cabal project in the current directory"))+ command "bootstrap" (BootstrapCmd <$> info bootstrapParser (progDesc bootstrapDesc))+ <>+ command "bump" (BumpCmd <$> info bumpParser (progDesc "Bump the deps of a package"))+ <>+ command "lower" (LowerCmd <$> info lowerCommand (progDesc "Modify the lower bounds of a package"))+ where+ bootstrapDesc = "Bootstrap an existing Cabal project in the current directory" globalParser :: Path Abs Dir -> Parser GlobalOptions globalParser realCwd = do- verbose <- optional (switch (long "verbose" <> short 'v' <> help "Verbose output"))+ verbose <- switch (long "verbose" <> short 'v' <> help "Verbose output")+ debug <- switch (long "debug" <> help "Debug output")+ quiet <- switch (long "quiet" <> help "Suppress info output") cwd <- option absDirOption (long "cwd" <> help "Force a different working directory" <> value realCwd)+ output <- option outputFormatOption (long "output" <> help formatHelp <> value OutputNone <> metavar "format")+ target <- option outputTargetOption (long "target" <> help targetHelp <> value OutputDefault <> metavar "target") pure GlobalOptions {..}+ where+ formatHelp = "Result output format, if commands support it"+ targetHelp = "Force output to a file or stdout" appParser :: Path Abs Dir ->@@ -353,6 +364,6 @@ customExecParser parserPrefs (info (appParser realCwd <**> helper) desc) where parserPrefs =- prefs (showHelpOnEmpty <> showHelpOnError)+ prefs (showHelpOnEmpty <> showHelpOnError <> subparserInline) desc = fullDesc <> header "Tools for maintaining Hix projects"
lib/Hix/Optparse.hs view
@@ -2,35 +2,40 @@ module Hix.Optparse where import Data.Aeson (Value, eitherDecodeFileStrict', eitherDecodeStrict')+import Distribution.Parsec (eitherParsec) import Exon (exon)-import Options.Applicative (ReadM, readerError)-import Options.Applicative.Types (readerAsk)+import Options.Applicative (ReadM, eitherReader) import Path (Abs, Dir, File, Path, Rel, parseAbsDir, parseAbsFile, parseRelDir, parseRelFile, toFilePath) import qualified Text.Show as Show --- |An absolute file path option for @optparse-applicative@.+import Hix.Data.OutputFormat (OutputFormat (..))+import Hix.Data.OutputTarget (OutputTarget (..))+import Hix.Managed.Cabal.Data.Config (HackageIndexState (HackageIndexState))+import Hix.Managed.Handlers.Build (SpecialBuildHandlers (TestBumpHandlers))++pathOption ::+ String ->+ (String -> Either e a) ->+ ReadM a+pathOption desc parse =+ eitherReader \ raw ->+ first (const [exon|not a valid #{desc} path: #{raw}|]) (parse raw)++-- | An absolute file path option for @optparse-applicative@. absFileOption :: ReadM (Path Abs File)-absFileOption = do- raw <- readerAsk- leftA (const (readerError [exon|not a valid absolute file path: #{raw}|])) (parseAbsFile raw)+absFileOption = pathOption "absolute file" parseAbsFile --- |A relative file path option for @optparse-applicative@.+-- | A relative file path option for @optparse-applicative@. relFileOption :: ReadM (Path Rel File)-relFileOption = do- raw <- readerAsk- leftA (const (readerError [exon|not a valid relative file path: #{raw}|])) (parseRelFile raw)+relFileOption = pathOption "relative file" parseRelFile --- |A relative dir path option for @optparse-applicative@.+-- | A relative dir path option for @optparse-applicative@. absDirOption :: ReadM (Path Abs Dir)-absDirOption = do- raw <- readerAsk- leftA (const (readerError [exon|not a valid absolute dir path: #{raw}|])) (parseAbsDir raw)+absDirOption = pathOption "absolute dir" parseAbsDir --- |A relative dir path option for @optparse-applicative@.+-- | A relative dir path option for @optparse-applicative@. relDirOption :: ReadM (Path Rel Dir)-relDirOption = do- raw <- readerAsk- leftA (const (readerError [exon|not a valid relative dir path: #{raw}|])) (parseRelDir raw)+relDirOption = pathOption "relative dir" parseRelDir newtype JsonConfig = JsonConfig { unJsonConfig :: IO (Either String Value) }@@ -39,10 +44,39 @@ instance Show JsonConfig where show (JsonConfig _) = "JsonConfig" -jsonOption ::- ReadM JsonConfig-jsonOption = do- raw <- readerAsk- pure $ JsonConfig $ case parseAbsFile raw of- Just f -> eitherDecodeFileStrict' (toFilePath f)- Nothing -> pure (eitherDecodeStrict' (encodeUtf8 raw))+jsonOption :: ReadM JsonConfig+jsonOption =+ eitherReader \ raw -> do+ pure $ JsonConfig $ case parseAbsFile raw of+ Just f -> eitherDecodeFileStrict' (toFilePath f)+ Nothing -> pure (eitherDecodeStrict' (encodeUtf8 raw))++buildHandlersOption :: ReadM SpecialBuildHandlers+buildHandlersOption =+ eitherReader \case+ "test" -> Right TestBumpHandlers+ h -> Left [exon|Invalid value for build handlers: #{h}|]++outputFormatOption :: ReadM OutputFormat+outputFormatOption =+ eitherReader \case+ "none" -> Right OutputNone+ "json" -> Right OutputJson+ "commit-msg" -> Right OutputCommitMsg+ "ga-pr" -> Right OutputGaPr+ fmt -> Left [exon|Invalid output format: #{fmt}|]++outputTargetOption :: ReadM OutputTarget+outputTargetOption =+ eitherReader \case+ "default" -> Right OutputDefault+ "stdout" -> Right OutputStdout+ other -> maybe (badFile other) (Right . OutputFile) (parseAbsFile other)+ where+ badFile f = Left [exon|Argument for --output is neither an absolute filepath nor 'default' or 'stdout': #{f}|]++indexStateOption :: ReadM HackageIndexState+indexStateOption =+ eitherReader \ raw -> bimap (err raw) HackageIndexState (eitherParsec raw)+ where+ err raw msg = [exon|Invalid index state string '#{raw}': #{msg}|]
+ lib/Hix/Orphans/Version.hs view
@@ -0,0 +1,46 @@+{-# options_ghc -Wno-orphans #-}++module Hix.Orphans.Version where++import Distribution.Version (+ LowerBound (LowerBound),+ UpperBound (NoUpperBound, UpperBound),+ Version,+ VersionInterval (VersionInterval),+ VersionRange,+ asVersionIntervals,+ earlierVersion,+ intersectVersionRanges,+ mkVersion,+ orLaterVersion,+ unionVersionRanges,+ version0,+ versionNumbers,+ )+import GHC.Exts (IsList (..))++instance IsList Version where+ type Item Version = Int++ fromList = mkVersion++ toList = versionNumbers++instance IsList VersionRange where+ type Item VersionRange = Version++ fromList = \case+ [] -> orLaterVersion version0+ [v] -> orLaterVersion v+ [l, u] -> range l u+ l : u : rest -> unionVersionRanges (range l u) (fromList rest)+ where+ range l u = intersectVersionRanges (orLaterVersion l) (earlierVersion u)++ toList range = do+ VersionInterval (LowerBound v _) upper <- asVersionIntervals range+ v : fromUpper upper+ where+ fromUpper = \case+ NoUpperBound -> []+ UpperBound v _ -> [v]
+ lib/Hix/OutputWriter.hs view
@@ -0,0 +1,64 @@+module Hix.OutputWriter where++import qualified Data.ByteString as ByteString+import qualified Data.Text.IO as Text+import Exon (exon)+import Path (Abs, File, Path, toFilePath)++import qualified Hix.Console as Console+import Hix.Data.Monad (M)+import Hix.Data.OutputTarget (OutputTarget (..))+import Hix.Error (Error (Fatal), pathText)+import Hix.Monad (throwM, tryIOMWithM)++data WriteError =+ WriteError {+ msg :: Text,+ file :: Path Abs File+ }+ deriving stock (Eq, Show, Generic)++data OutputWriter =+ OutputWriter {+ bytes :: ByteString -> M (),+ text :: Text -> M (),+ textAppend :: Text -> M ()+ }++fileWriter :: (WriteError -> M ()) -> Path Abs File -> OutputWriter+fileWriter errorHandler file =+ OutputWriter {+ bytes = handleError . ByteString.writeFile fp,+ text = handleError . Text.writeFile fp,+ textAppend = handleError . Text.appendFile fp+ }+ where+ handleError = tryIOMWithM \ err -> errorHandler WriteError {msg = show err, file}+ fp = toFilePath file++writeError :: WriteError -> M ()+writeError err =+ throwM (Fatal [exon|Couldn't write to #{pathText err.file}: #{err.msg}|])++stdoutWriter :: OutputWriter+stdoutWriter =+ OutputWriter {+ bytes = Console.bytesOut,+ text = Console.out,+ textAppend = Console.out+ }++outputWriterM :: M OutputWriter -> OutputTarget -> M OutputWriter+outputWriterM defaultWriter = \case+ OutputFile file -> pure (fileWriter writeError file)+ OutputStdout -> pure stdoutWriter+ OutputDefault -> defaultWriter++outputWriter :: OutputWriter -> OutputTarget -> OutputWriter+outputWriter defaultWriter = \case+ OutputFile file -> fileWriter writeError file+ OutputStdout -> stdoutWriter+ OutputDefault -> defaultWriter++outputWriterGlobal :: OutputTarget -> OutputWriter+outputWriterGlobal = outputWriter stdoutWriter
lib/Hix/Path.hs view
@@ -5,8 +5,8 @@ import System.FilePattern.Directory (getDirectoryFiles) import System.IO.Error (tryIOError) -import qualified Hix.Monad-import Hix.Monad (Env (Env), M)+import qualified Hix.Data.Monad+import Hix.Data.Monad (AppResources (AppResources), M (M)) findFlake :: Path Abs Dir -> IO (Maybe (Path Abs Dir)) findFlake cur =@@ -17,7 +17,7 @@ inferRoot :: M (Path Abs Dir) inferRoot = do- Env {cwd} <- ask+ AppResources {cwd} <- M ask fromMaybe cwd <$> liftIO (findFlake cwd) rootDir :: Maybe (Path Abs Dir) -> M (Path Abs Dir)
lib/Hix/Preproc.hs view
@@ -2,7 +2,6 @@ import Control.Lens (IndexedTraversal', has, index, ix, preview, (%~), (.~), (^..)) import Control.Lens.Regex.ByteString (Match, group, groups, match, regex)-import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Except (ExceptT, throwE) import qualified Data.ByteString as ByteString import Data.ByteString (elemIndex)@@ -26,12 +25,14 @@ import Hix.Component (targetComponentOrError) import qualified Hix.Data.ComponentConfig import Hix.Data.ComponentConfig (PreludeConfig, PreludePackage (PreludePackageName, PreludePackageSpec))-import Hix.Data.Error (Error (..), sourceError, tryIO)+import Hix.Data.Monad (M, liftE)+import Hix.Data.Options (PreprocOptions (..), TargetSpec (TargetForFile))+import Hix.Data.PackageName (PackageName (PackageName)) import qualified Hix.Data.PreprocConfig import Hix.Data.PreprocConfig (PreprocConfig)-import Hix.Json (jsonConfig)-import Hix.Monad (M)-import Hix.Options (PreprocOptions (..), TargetSpec (TargetForFile))+import Hix.Error (Error (..), sourceError)+import Hix.Json (jsonConfigE)+import Hix.Monad (tryIOM) import Hix.Optparse (JsonConfig) import qualified Hix.Prelude as Prelude import Hix.Prelude (Prelude (Prelude), findPrelude)@@ -43,7 +44,7 @@ fromPreludeConfig ppconf conf = Prelude (toString name) (toString conf.module_.unModuleName) local where- local = Map.member (coerce name) ppconf.packages+ local = Map.member (PackageName name) ppconf.packages name = case conf.package of PreludePackageName n -> n PreludePackageSpec n -> n@@ -448,11 +449,11 @@ preprocessWith :: PreprocOptions -> CabalConfig -> M () preprocessWith opt conf = do- inLines <- lift (tryIO (ByteString.readFile (toFilePath opt.inFile)))+ inLines <- tryIOM (ByteString.readFile (toFilePath opt.inFile)) dummyNumber :: Int <- randomRIO (10000, 10000000) let dummyExportName = DummyExportName [exon|Hix_Dummy_#{show dummyNumber}|] let result = preprocessModule opt.source conf dummyExportName inLines- lift (tryIO (ByteStringBuilder.writeFile (toFilePath opt.outFile) result))+ tryIOM (ByteStringBuilder.writeFile (toFilePath opt.outFile) result) fromConfig :: Maybe (Path Abs Dir) ->@@ -460,7 +461,7 @@ Either PreprocConfig JsonConfig -> M CabalConfig fromConfig cliRoot source pconf = do- conf <- either pure jsonConfig pconf+ conf <- jsonConfigE PreprocError pconf target <- targetComponentOrError cliRoot Nothing conf.packages (TargetForFile source) pure CabalConfig { extensions = stringUtf8 <$> target.component.language : target.component.extensions,@@ -483,7 +484,7 @@ fromCabalFile :: Path Abs File -> M CabalConfig fromCabalFile source =- fromCabal <$> lift (buildInfoForFile source)+ fromCabal <$> liftE (buildInfoForFile source) -- TODO add common stanzas preprocess :: PreprocOptions -> M ()
+ lib/Hix/Pretty.hs view
@@ -0,0 +1,40 @@+module Hix.Pretty where++import Distribution.Pretty (Pretty, pretty)+import Text.PrettyPrint (Doc, comma, punctuate, sep, text)++showP ::+ ∀ b a .+ Pretty a =>+ IsString b =>+ a ->+ b+showP = show . pretty++showPM ::+ ∀ b a .+ Pretty a =>+ IsString b =>+ Maybe a ->+ b+showPM = show . fmap pretty++prettyL ::+ ∀ t a .+ Pretty a =>+ Foldable t =>+ t a ->+ Doc+prettyL = sep . punctuate comma . fmap pretty . toList++showPL ::+ ∀ t b a .+ Pretty a =>+ Foldable t =>+ IsString b =>+ t a ->+ b+showPL = show . prettyL++prettyText :: Text -> Doc+prettyText = text . toString
+ lib/Hix/These.hs view
@@ -0,0 +1,9 @@+module Hix.These where++import Data.These (These (..))++maybeThese :: Maybe a -> Maybe b -> Maybe (These a b)+maybeThese (Just a) (Just b) = Just (These a b)+maybeThese (Just a) Nothing = Just (This a)+maybeThese Nothing (Just b) = Just (That b)+maybeThese Nothing Nothing = Nothing
+ lib/Hix/Trace.hs view
@@ -0,0 +1,25 @@+module Hix.Trace where++import Distribution.Pretty (Pretty)+import GHC.Stack (callStack)+import System.IO.Unsafe (unsafePerformIO)++import Hix.Pretty (showP)++trp ::+ ∀ b a .+ Pretty b =>+ HasCallStack =>+ b ->+ a ->+ a+trp b a =+ unsafePerformIO (a <$ debugPrint (srcLoc callStack) (showP b))++trpi ::+ Pretty a =>+ HasCallStack =>+ a ->+ a+trpi a =+ unsafePerformIO (a <$ debugPrint (srcLoc callStack) (showP a))
+ lib/Hix/Version.hs view
@@ -0,0 +1,151 @@+{-# language MonadComprehensions #-}++module Hix.Version where++import Data.List.Extra (groupOnKey)+import Distribution.Version (+ Bound (ExclusiveBound),+ LowerBound (LowerBound),+ UpperBound (UpperBound),+ Version,+ VersionInterval (VersionInterval),+ VersionRange,+ alterVersion,+ asVersionIntervals,+ version0,+ versionNumbers,+ )++import qualified Hix.Data.Version+import Hix.Data.Version (Major (Major))++lowerVersion :: VersionRange -> Maybe Version+lowerVersion range =+ [v | VersionInterval (LowerBound v _) _ <- head (asVersionIntervals range), v /= version0]++exclusiveUpperVersion :: VersionRange -> Maybe Version+exclusiveUpperVersion range =+ [v | VersionInterval _ (UpperBound v ExclusiveBound) <- last (asVersionIntervals range)]++upperVersion :: VersionRange -> Maybe Version+upperVersion range =+ [v | VersionInterval _ (UpperBound v _) <- last (asVersionIntervals range)]++majorParts :: Version -> Maybe (Int, Int)+majorParts =+ versionNumbers >>> \case+ [] -> Nothing+ [0] -> Nothing+ [s] -> Just (s, 0)+ s : m : _ -> Just (s, m)++majorPrefix :: Version -> Maybe [Int]+majorPrefix =+ majorParts >>> fmap \case+ (s, m) -> [s, m]++hasMajor :: Int -> Int -> Version -> Bool+hasMajor s m candidate =+ case take 2 (versionNumbers candidate) of+ [s'] -> s' == s && m == 0+ s' : m' : _ -> s' == s && m' == m+ _ -> False++minMajor :: Int -> Int -> Version -> Bool+minMajor s m candidate =+ case take 2 (versionNumbers candidate) of+ [s'] -> s' > s || (s' == s && m == 0)+ s' : m' : _ -> s' > s || (s' == s && m' >= m)+ _ -> False++beforeMajor :: Int -> Int -> Version -> Bool+beforeMajor s m candidate =+ case take 2 (versionNumbers candidate) of+ [s'] -> s' < s || (s' == s && m > 0)+ s' : m' : _ -> s' < s || (s' == s && m' < m)+ _ -> False++lastMajor :: [Version] -> [Version]+lastMajor =+ reverse . fst . foldl step ([], (0, 0))+ where+ step (z, cur) a+ | Just pre <- majorParts a+ , pre /= cur+ = ([a], pre)+ | otherwise+ = (a : z, cur)++lastMajorBefore :: Int -> Int -> [Version] -> [Version]+lastMajorBefore s m =+ reverse . fst . foldl step ([], (0, 0))+ where+ step (z, cur) a+ | Just (s', m') <- mp+ , s' > s || (s' == s && m' >= m)+ = (z, cur)+ | Just pre <- mp+ , pre /= cur+ = ([a], pre)+ | otherwise+ = (a : z, cur)+ where+ mp = majorParts a++nextMajor :: Version -> Version+nextMajor =+ alterVersion \case+ [] -> [0, 1]+ [s] -> [s, 1]+ s : m : _ -> [s, m + 1]++prevMajor :: Version -> Version+prevMajor =+ alterVersion \case+ [s] | s > 0 -> [s - 1, 99]+ s : 0 : _ | s > 0 -> [s - 1, 99]+ s : m : _ | s > 0, m > 0 -> [s, m - 1]+ _ -> [0]++currentMajor :: Version -> Version+currentMajor = alterVersion (take 2)++isMajor :: Int -> Int -> Major -> Bool+isMajor s m Major {prefix} =+ prefix == [s, m]++majorOlder :: Int -> Int -> Major -> Bool+majorOlder s m Major {prefix} =+ prefix < [s, m]++majorNewer :: Int -> Int -> Major -> Bool+majorNewer s m Major {prefix} =+ prefix > [s, m]++allMajors :: [Version] -> [Major]+allMajors =+ mapMaybe (uncurry cons) . groupOnKey currentMajor+ where+ cons prefix = \case+ (h : t) -> Just (Major {prefix, versions = h :| t})+ [] -> Nothing++majorsBefore :: Int -> Int -> [Version] -> [Major]+majorsBefore s m =+ takeWhile (majorOlder s m) . allMajors++majorsFrom :: Int -> Int -> [Version] -> [Major]+majorsFrom s m =+ dropWhile (majorOlder s m) . allMajors++onlyMajor :: Int -> Int -> [Version] -> Maybe Major+onlyMajor s m =+ find (isMajor s m) . allMajors++versionsFrom :: Version -> [Version] -> [Major]+versionsFrom start =+ allMajors . dropWhile (< start)++versionsBetween :: Version -> Version -> [Version] -> [Major]+versionsBetween l u =+ allMajors . takeWhile (< u) . dropWhile (< l)
+ lib/Hix/Zip.hs view
@@ -0,0 +1,15 @@+module Hix.Zip where++zipApply :: (a -> b) -> [a] -> [(a, b)]+zipApply f = fmap \ a -> (a, f a)++zipApplyA ::+ Traversable t =>+ Applicative m =>+ (a -> m b) ->+ t a ->+ m (t (a, b))+zipApplyA f = traverse \ a -> (a,) <$> f a++zipApplyL :: (a -> b) -> [a] -> [(b, a)]+zipApplyL f = fmap \ a -> (f a, a)
test/Hix/Test/BootstrapTest.hs view
@@ -1,8 +1,9 @@ module Hix.Test.BootstrapTest where +import qualified Data.Text as Text import qualified Data.Text.IO as Text import Exon (exon)-import Hedgehog (TestT, evalEither, (===))+import Hedgehog (evalEither, (===)) import Path (parent, reldir, relfile, toFilePath, (</>)) import Path.IO (createDirIfMissing, withSystemTempDir) @@ -11,7 +12,7 @@ import Hix.Data.BootstrapProjectConfig (BootstrapProjectConfig (BootstrapProjectConfig)) import qualified Hix.Data.ProjectFile as ProjectFile import Hix.Monad (runM)-import qualified Data.Text as Text+import Hix.Test.Utils (UnitTest) cabal :: Text cabal =@@ -74,7 +75,7 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall build-depends: base ==4.*- , hedgehog >=1.1 && <1.3+ , hedgehog >=1.1 && <1.5 , red-panda , tasty ==1.4.* , tasty-hedgehog >=1.3 && <1.5@@ -151,7 +152,7 @@ }; tests.red-panda-test = { dependencies = [- "hedgehog >=1.1 && <1.3"+ "hedgehog >=1.1 && <1.5" "red-panda" "tasty >=1.4 && <1.5" "tasty-hedgehog >=1.3 && <1.5"@@ -173,7 +174,7 @@ } |] -test_bootstrap :: TestT IO ()+test_bootstrap :: UnitTest test_bootstrap = do result <- liftIO $ withSystemTempDir "hix-unit" \ tmp -> do let
+ test/Hix/Test/BoundsTest.hs view
@@ -0,0 +1,52 @@+module Hix.Test.BoundsTest where++import Distribution.Version (orEarlierVersion, orLaterVersion)+import Hedgehog (Gen, Property, forAll, property, (===))+import qualified Hedgehog.Gen as Gen+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.Hedgehog (testProperty)++import Hix.Class.Map (nAmend1, nForKeys, nFromKeys, nMap1, nPadKeep1)+import Hix.Data.Bounds (Ranges)+import qualified Hix.Data.Dep+import Hix.Data.Dep (Dep, mkDep, withVersion)+import Hix.Data.PackageName (LocalPackage, PackageName)+import Hix.Managed.Data.Packages (Deps, Packages)++packages :: [PackageName]+packages = ["dep1", "dep2", "dep3"]++targets :: [LocalPackage]+targets = ["target1", "target2", "target3"]++genBounds :: Gen Ranges+genBounds = do+ keys <- Gen.subsequence packages+ pure (nFromKeys keys (const dep))+ where+ dep = orEarlierVersion [2, 5]++genTargetBounds :: Gen (Packages Ranges)+genTargetBounds = do+ keys <- Gen.subsequence targets+ nForKeys keys (const genBounds)++genDeps :: Deps Dep+genDeps =+ nFromKeys packages \ k -> mkDep k (orLaterVersion [1, 5])++deps :: Packages (Deps Dep)+deps =+ nFromKeys targets (const genDeps)++prop_amendBounds :: Property+prop_amendBounds =+ property do+ bounds <- forAll genTargetBounds+ nPadKeep1 (.version) deps bounds === nMap1 (.version) (nAmend1 withVersion bounds deps)++test_bounds :: TestTree+test_bounds =+ testGroup "bounds" [+ testProperty "pad a b === amend b a (for padded a)" prop_amendBounds+ ]
test/Hix/Test/CabalFile.hs view
@@ -27,6 +27,7 @@ build-depends: Cabal , base >=4.12 && <5+ , semigroups >=1 mixins: base hiding (Prelude) , incipit-base (IncipitBase as Prelude)
test/Hix/Test/CabalTest.hs view
@@ -2,14 +2,9 @@ import Control.Monad.Trans.Except (runExceptT) import qualified Data.ByteString as ByteString-import Distribution.PackageDescription (- BuildInfo (defaultExtensions),- CondTree (condTreeData),- GenericPackageDescription (condLibrary),- Library (libBuildInfo),- )-import Hedgehog (TestT, (===))-import Hix.Cabal (parseCabal)+import Distribution.Package (Dependency)+import qualified Distribution.PackageDescription+import Hedgehog ((===)) import Language.Haskell.Extension ( Extension (DisableExtension, EnableExtension), KnownExtension (AllowAmbiguousTypes, ApplicativeDo),@@ -17,16 +12,26 @@ import Path (relfile, toFilePath, (</>)) import Path.IO (withSystemTempDir) +import Hix.Cabal (parseCabal)+import qualified Hix.Data.Dep as Dep import Hix.Test.CabalFile (testCabal)+import Hix.Test.Utils (UnitTest) target :: [Extension] target = [EnableExtension AllowAmbiguousTypes, DisableExtension ApplicativeDo] -test_cabal :: TestT IO ()+deps :: [Dependency]+deps =+ Dep.toCabal <$> ["Cabal", "base >=4.12 && <5", "semigroups >=1"]++test_cabal :: UnitTest test_cabal = do Right pkg <- liftIO $ withSystemTempDir "hix-unit" \ tmp -> do let cabalFile = tmp </> [relfile|test.cabal|] ByteString.writeFile (toFilePath cabalFile) testCabal runExceptT (parseCabal cabalFile)- Just target === (pkg.condLibrary <&> \ l -> l.condTreeData.libBuildInfo.defaultExtensions)+ let lib = fold pkg.condLibrary+ deps === lib.condTreeData.libBuildInfo.targetBuildDepends+ deps === lib.condTreeConstraints+ target === lib.condTreeData.libBuildInfo.defaultExtensions
test/Hix/Test/GhciTest.hs view
@@ -2,7 +2,7 @@ import Control.Monad.Trans.Class (lift) import Exon (exon)-import Hedgehog (TestT, evalEither, (===))+import Hedgehog (evalEither, (===)) import Path (Abs, Dir, File, Path, Rel, SomeBase (Rel), absdir, absfile, reldir, relfile, (</>)) import Path.IO (withSystemTempDir) @@ -15,14 +15,11 @@ SourceDir (SourceDir), SourceDirs (SourceDirs), )-import Hix.Data.Error (pathText)+import Hix.Error (pathText) import Hix.Data.GhciConfig (ChangeDir (ChangeDir), EnvConfig (EnvConfig), GhciConfig (..)) import qualified Hix.Data.GhciTest as GhciTest-import Hix.Env (envRunner)-import Hix.Ghci (assemble, ghciCmdlineFromOptions, ghcidCmdlineFromOptions)-import Hix.Monad (runM)-import qualified Hix.Options as Options-import Hix.Options (+import qualified Hix.Data.Options as Options+import Hix.Data.Options ( ComponentCoords (ComponentCoords), ComponentSpec (ComponentSpec), EnvRunnerOptions (EnvRunnerOptions),@@ -32,6 +29,10 @@ TargetSpec (TargetForComponent, TargetForFile), TestOptions (TestOptions), )+import Hix.Env (envRunner)+import Hix.Ghci (assemble, ghciCmdlineFromOptions, ghcidCmdlineFromOptions)+import Hix.Monad (runM)+import Hix.Test.Utils (UnitTest) root :: Path Abs Dir root =@@ -126,7 +127,7 @@ path = [exon|#{dir}packages/api/test/:#{dir}packages/api/lib/:#{dir}packages/core/lib/|] dir = pathText cwd -test_ghcid :: TestT IO ()+test_ghcid :: UnitTest test_ghcid = do res <- lift $ withSystemTempDir "hix-test" \ tmp -> runM root (ghcidCmdlineFromOptions tmp options)@@ -164,7 +165,7 @@ path = [exon|#{dir}packages/core/test/:#{dir}packages/api/lib/:#{dir}packages/core/lib/|] dir = pathText cwd -test_mainPackage :: TestT IO ()+test_mainPackage :: UnitTest test_mainPackage = do res <- lift $ withSystemTempDir "hix-test" \ tmp -> runM root (ghciCmdlineFromOptions tmp mainOptions)@@ -182,14 +183,14 @@ component = Just (ComponentSpec "core-test" (Just (SourceDir [reldir|core-test|]))) } -runnerFor :: EnvRunner -> TargetSpec -> TestT IO ()+runnerFor :: EnvRunner -> TargetSpec -> UnitTest runnerFor target spec = do res <- evalEither =<< liftIO (runM root (envRunner conf)) target === res where conf = EnvRunnerOptions (Left (EnvConfig packages defaultRunner Nothing)) Nothing (Just spec) -test_componentEnv :: TestT IO ()+test_componentEnv :: UnitTest test_componentEnv = do runnerFor runner1 spec1 runnerFor runner2 spec2@@ -208,7 +209,7 @@ where m = "Core.Test.Main" -test_moduleName :: TestT IO ()+test_moduleName :: UnitTest test_moduleName = do conf <- evalEither =<< liftIO (runM root (assemble options.ghci { component = spec4 })) target_moduleName === conf.script
+ test/Hix/Test/Hedgehog.hs view
@@ -0,0 +1,57 @@+module Hix.Test.Hedgehog where++import Data.List.Extra (zipWithLongest)+import qualified Data.Text as Text+import Hedgehog (TestT, evalEither, (===))++eqLines ::+ ∀ m .+ Monad m =>+ HasCallStack =>+ Text ->+ Text ->+ TestT m ()+eqLines l r =+ withFrozenCallStack do+ take common linesL === take common linesR+ if ll > lr+ then trailing "missing lines: " linesL+ else if lr > ll+ then trailing "extra lines: " linesR+ else unit+ where+ trailing desc ls = fail (toString (desc <> Text.unlines (drop common ls)))+ common = min ll lr+ ll = length linesL+ lr = length linesR+ linesL = Text.lines l+ linesR = Text.lines r++assertRight ::+ ∀ a m e .+ Eq a =>+ Show e =>+ Show a =>+ Monad m =>+ HasCallStack =>+ a ->+ Either e a ->+ TestT m ()+assertRight a =+ withFrozenCallStack do+ (===) a <=< evalEither++listEqZip ::+ ∀ m a .+ Monad m =>+ HasCallStack =>+ Eq a =>+ Show a =>+ [a] ->+ [a] ->+ TestT m ()+listEqZip target log =+ for_ (zip [0 :: Natural ..] (zipWithLongest (,) target log)) \case+ (i, (Just t, Just l)) -> (i, t) === (i, l)+ _ | [] <- log -> fail "Result list is empty."+ _ -> target === log
+ test/Hix/Test/Managed/BuildOutputTest.hs view
@@ -0,0 +1,36 @@+module Hix.Test.Managed.BuildOutputTest where++import qualified Data.Aeson as Aeson+import Exon (exon)+import Hedgehog ((===))+import Test.Tasty (TestTree, testGroup)++import Hix.Managed.BuildOutput (buildOutputFromLists)+import qualified Hix.Managed.Data.BuildOutput+import Hix.Managed.Data.BuildOutput (BuildOutput, ModifiedId (ModifiedId))+import Hix.Test.Utils (UnitTest, unitTest)++output :: BuildOutput+output =+ buildOutputFromLists [+ ModifiedId {package = "direct1", version = [1, 0, 1], range = Just ">=1.1 && >0.8"},+ ModifiedId {package = "direct2", version = [1, 0, 1], range = Nothing}+ ] [+ "direct3", "direct4"+ ] [+ "direct5", "direct6"+ ]++target :: ByteString+target =+ [exon|{"failed":["direct5","direct6"],"failedNames":"direct5, direct6","modified":[{"package":"direct1","range":">=1.1","version":"1.0.1"},{"package":"direct2","range":null,"version":"1.0.1"}],"modifiedNames":"direct1, direct2","unmodified":["direct3","direct4"],"unmodifiedNames":"direct3, direct4"}|]++test_buildOutputJson :: UnitTest+test_buildOutputJson =+ target === toStrict (Aeson.encode output)++test_buildOutput :: TestTree+test_buildOutput =+ testGroup "build output formats" [+ unitTest "json" test_buildOutputJson+ ]
+ test/Hix/Test/Managed/Bump/CandidatesTest.hs view
@@ -0,0 +1,106 @@+module Hix.Test.Managed.Bump.CandidatesTest (test_candidatesBump) where++import Distribution.Version (Version)+import Hedgehog (evalEither, (===))++import Hix.Data.PackageName (PackageName)+import Hix.Data.VersionBounds (VersionBounds)+import Hix.Managed.Bump.Candidates (candidatesBump)+import qualified Hix.Managed.Data.Bump+import Hix.Managed.Data.Bump (Bump (Bump))+import Hix.Managed.Data.Mutable (MutableDep)+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (DepMutation (DepMutation))+import Hix.Managed.Handlers.Build (BuildHandlers (latestVersion), handlersNull)+import Hix.Managed.QueryDep (simpleQueryDep)+import Hix.Monad (M, clientError)+import Hix.Test.Utils (UnitTest, runMTest)++deps :: [(MutableDep, VersionBounds)]+deps =+ [+ ("dep1", "^>=2.0"),+ ("dep2", "<1.5"),+ ("dep3", ">=0"),+ ("dep5", "==1.0.1"),+ ("dep6", "<8.4"),+ ("dep7", "^>=1.1")+ ]++dep1Version :: Version+dep1Version = [2, 2, 0, 5]++dep2Version :: Version+dep2Version = [1, 7, 14]++dep3Version :: Version+dep3Version = [1, 0, 5]++dep4Version :: Version+dep4Version = [2, 4, 5]++dep5Version :: Version+dep5Version = [1, 9, 1, 0]++dep6Version :: Version+dep6Version = [7, 3]++dep7Version :: Version+dep7Version = [1, 1, 1]++latestVersion :: PackageName -> M (Maybe Version)+latestVersion =+ fmap Just . \case+ "dep1" -> pure dep1Version+ "dep2" -> pure dep2Version+ "dep3" -> pure dep3Version+ "dep4" -> pure dep4Version+ "dep5" -> pure dep5Version+ "dep6" -> pure dep6Version+ "dep7" -> pure dep7Version+ _ -> clientError "No such package"++handlersTest :: BuildHandlers+handlersTest =+ handlersNull {latestVersion}++target :: [DepMutation Bump]+target =+ [+ mkBump "dep6" dep6Bound dep6Version,+ mkBump "dep1" dep1Bound dep1Version,+ DepMutation {package = "dep7", retract = False, mutation = Bump {version = [1, 1, 1], bound = [1, 2], changed = True}},+ mkBump "dep2" dep2Bound dep2Version,+ mkBump "dep5" dep5Bound dep5Version,+ mkBump "dep3" dep3Bound dep3Version+ ]+ where+ mkBump name bound newVersion =+ DepMutation {+ package = fromString name,+ retract = False,+ mutation = Bump {+ version = newVersion,+ bound,+ changed = True+ }+ }++ dep1Bound = [2, 3]++ dep2Bound = [1, 8]++ dep3Bound = [1, 1]++ dep5Bound = [1, 10]++ dep6Bound = [7, 4]++test_candidatesBump :: UnitTest+test_candidatesBump = do+ mutations <- evalEither =<< liftIO do+ runMTest False do+ catMaybes <$> traverse (candidatesBump handlersTest) query+ sortOn (.package) target === sortOn (.package) (toList mutations)+ where+ query = uncurry simpleQueryDep <$> deps
+ test/Hix/Test/Managed/Bump/MutationTest.hs view
@@ -0,0 +1,335 @@+module Hix.Test.Managed.Bump.MutationTest where++import qualified Data.Text as Text+import Exon (exon)+import Hedgehog ((===))+import Test.Tasty (TestTree, testGroup)++import Hix.Data.Error (Error (Fatal))+import Hix.Data.Version (Versions)+import Hix.Managed.Bump.Optimize (bumpOptimizeMain)+import qualified Hix.Managed.Cabal.Data.Packages+import Hix.Managed.Cabal.Data.Packages (GhcPackages (GhcPackages), InstalledPackages)+import Hix.Managed.Cabal.Data.SourcePackage (SourcePackages)+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto, managedPackages)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Data.ProjectStateProto+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto (ProjectStateProto))+import Hix.Managed.Data.StageState (BuildStatus (Failure, Success))+import Hix.Monad (M, throwM)+import Hix.NixExpr (renderRootExpr)+import Hix.Pretty (showP)+import Hix.Test.Hedgehog (eqLines)+import qualified Hix.Test.Managed.Run+import Hix.Test.Managed.Run (Result (Result), TestParams (..), bumpTest, testParams)+import Hix.Test.Utils (UnitTest, unitTest)++packages :: Packages ManagedPackageProto+packages =+ managedPackages [(("local1", "1.0"), [+ "base",+ "direct1",+ "direct2",+ "direct3",+ "direct4",+ "direct5"+ ])]++installed :: InstalledPackages+installed =+ [+ ("base-4.12.0.0", []),+ ("direct1-1.0.1", []),+ ("direct2-1.0.1", []),+ ("direct3-1.0.1", []),+ ("direct4-1.0.1", []),+ ("direct5-1.0.1", [])+ ]++packageDb :: SourcePackages+packageDb =+ [+ ("base", [+ ([4, 11, 0, 0], []),+ ([4, 12, 0, 0], []),+ ([4, 13, 0, 0], [])+ ]),+ ("direct1", [+ ([1, 0, 1], []),+ ([1, 1, 1], []),+ ([1, 2, 1], ["direct2 ==1.2.1"])+ ]),+ ("direct2", [+ ([1, 0, 1], []),+ ([1, 1, 1], []),+ ([1, 2, 1], [])+ ]),+ ("direct3", [+ ([1, 0, 1], []),+ ([1, 1, 1], []),+ ([1, 2, 1], [])+ ]),+ ("direct4", [+ ([1, 0, 1], []),+ ([1, 1, 1], []),+ ([1, 2, 1], [])+ ]),+ ("direct5", [+ ([1, 0, 1], []),+ ([1, 1, 1], []),+ ([1, 2, 1], ["direct4 <1.2"])+ ])+ ]++ghcPackages :: GhcPackages+ghcPackages = GhcPackages {installed, available = packageDb}++build :: Versions -> M BuildStatus+build = \case+ [("base", [4, 12, 0, 0]), ("direct1", [1, 2, 1]), ("direct2", [1, 2, 1]), ("direct3", [1, 0, 1]), ("direct4", [1, 0, 1]), ("direct5", [1, 1, 1])] -> pure Success+ [("base", [4, 12, 0, 0]), ("direct1", [1, 2, 1]), ("direct2", [1, 2, 1]), ("direct3", [1, 2, 1]), ("direct4", [1, 0, 1]), ("direct5", [1, 1, 1])] -> pure Failure+ [("base", [4, 12, 0, 0]), ("direct1", [1, 2, 1]), ("direct2", [1, 2, 1]), ("direct3", [1, 0, 1]), ("direct4", [1, 2, 1]), ("direct5", [1, 1, 1])] -> pure Success+ [("base", [4, 12, 0, 0]), ("direct1", [1, 2, 1]), ("direct2", [1, 2, 1]), ("direct3", [1, 0, 1]), ("direct4", [1, 2, 1]), ("direct5", [1, 2, 1])] -> pure Success+ -- second iteration+ [("base", [4, 12, 0, 0]), ("direct1", [1, 2, 1]), ("direct2", [1, 2, 1]), ("direct3", [1, 2, 1]), ("direct4", [1, 2, 1]), ("direct5", [1, 2, 1])] -> pure Failure+ versions -> throwM (Fatal [exon|Unexpected build plan: #{showP versions}|])++state :: ProjectStateProto+state =+ ProjectStateProto {+ bounds = [+ ("local1", [+ ("direct1", ">=0.1"),+ ("direct2", ">=0.1"),+ ("direct4", "^>=1.0")+ ])+ ],+ versions = [("fancy", [("direct4", "1.0.1")])],+ overrides = [+ ("fancy", [("direct5", "direct5-1.1.1")])+ ],+ initial = [],+ resolving = False+ }++stateFileTarget :: Text+stateFileTarget =+ [exon|{+ bounds = {+ local1 = {+ base = {+ lower = null;+ upper = "4.13";+ };+ direct1 = {+ lower = "0.1";+ upper = "1.3";+ };+ direct2 = {+ lower = "0.1";+ upper = "1.3";+ };+ direct3 = {+ lower = null;+ upper = "1.1";+ };+ direct4 = {+ lower = "1.0";+ upper = "1.3";+ };+ direct5 = {+ lower = null;+ upper = "1.3";+ };+ };+ };+ versions = {+ fancy = {+ base = "4.12.0.0";+ direct1 = "1.2.1";+ direct2 = "1.2.1";+ direct3 = "1.0.1";+ direct4 = "1.2.1";+ direct5 = "1.2.1";+ };+ };+ initial = {+ fancy = {};+ };+ overrides = {+ fancy = {+ direct1 = {+ version = "1.2.1";+ hash = "direct1-1.2.1";+ };+ direct2 = {+ version = "1.2.1";+ hash = "direct2-1.2.1";+ };+ direct4 = {+ version = "1.2.1";+ hash = "direct4-1.2.1";+ };+ direct5 = {+ version = "1.2.1";+ hash = "direct5-1.2.1";+ };+ };+ };+ resolving = false;+}+|]++logTarget :: [Text]+logTarget =+ Text.lines [exon|+[35m[1m>>>[0m [33mfancy[0m+[35m[1m>>>[0m Couldn't find working latest versions for some deps after 2 iterations.+ 📦 direct3+[35m[1m>>>[0m Added new versions:+ 📦 [34mbase[0m 4.12.0.0 ↕ [no bounds] -> <[32m4.13[0m+ 📦 [34mdirect1[0m 1.2.1 ↕ >=0.1 -> [0.1, [32m1.3[0m]+ 📦 [34mdirect2[0m 1.2.1 ↕ >=0.1 -> [0.1, [32m1.3[0m]+ 📦 [34mdirect3[0m 1.0.1 ↕ [no bounds] -> <[32m1.1[0m+ 📦 [34mdirect5[0m 1.2.1 ↕ [no bounds] -> <[32m1.3[0m+[35m[1m>>>[0m Updated versions:+ 📦 [34mdirect4[0m [31m1.0.1[0m -> [32m1.2.1[0m ↕ [1.0, [31m1.1[0m] -> [1.0, [32m1.3[0m]+|]++-- | Goals for these deps:+--+-- Unless stated otherwise, packages have an installed version, 1.0.1, and a latest available version, 1.2.1, which will+-- be their candidate.+--+-- - @base@ is marked as non-reinstallable in Cabal, so it will never produce a plan that includes a different version+-- than its installed one, 4.12.0.0.+-- Its mutation is excluded from being built by matching its name, so it will only be in the solver bounds, and+-- therefore still get a managed bound, version and initial entry in the state file, but no override.+--+-- - @direct1@ The candidate has a dep on @direct2 ==1.2.1@, so the solver chooses 1.2.1 for both deps in the first+-- mutation, which succeeds.+--+-- - @direct2@ has been updated to the latest version by the mutation for @direct1@ and will try the same version again,+-- resulting in success.+--+-- - @direct3@ has the latest version 1.2.1, for which the build fails.+-- It will be tried again in the second iteration, where it will fail once more.+-- It will not be bumped, but an upper bound will be added based on its installed version, 1.0.1, as @<1.1@.+-- No override will be added to the state.+-- TODO We could use multiple condidates, between the latest version and the maximum of the prior upper bound and the+-- installed version.+-- Probably only the latest in each major.+--+-- - @direct4@ has preexisting managed bounds, @^>=1.0@.+-- The candidate succeeds, so the lower bound will be preserved, to yield the final bounds, @>=1.0 && <1.3@.+-- It has an existing entry in @initial@, which will be preserved.+--+-- - @direct5@ has an existing override for version 1.1.1, which will be replaced by the successful candidate 1.2.1.+-- It has a dependency on @direct4@ with an upper bound of <1.2, which would prevent it from being selected by the+-- solver if we didn't use @AllowNewer@.+test_bumpMutationBasic :: UnitTest+test_bumpMutationBasic = do+ Result {stateFile, log} <- bumpTest params bumpOptimizeMain+ eqLines stateFileTarget (renderRootExpr stateFile)+ logTarget === drop 12 (reverse log)+ where+ params = (testParams False packages) {+ log = True,+ envs = [("fancy", ["local1"])],+ ghcPackages,+ state,+ build+ }++packages_upToDate :: Packages ManagedPackageProto+packages_upToDate =+ managedPackages [(("local1", "1.0"), ["direct1"])]++installed_upToDate :: InstalledPackages+installed_upToDate =+ [("direct1-1.0.0", [])]++packageDb_upToDate :: SourcePackages+packageDb_upToDate =+ [("direct1", [([1, 0, 1], [])])]++ghcPackages_upToDate :: GhcPackages+ghcPackages_upToDate = GhcPackages {installed = installed_upToDate, available = packageDb_upToDate}++state_upToDate :: ProjectStateProto+state_upToDate =+ ProjectStateProto {+ bounds = [("local1", [("direct1", ">=0.1 && <1.1")])],+ versions = [],+ overrides = [("latest", [("direct1", "direct1-1.0.1")])],+ initial = [],+ resolving = False+ }++build_upToDate :: Versions -> M BuildStatus+build_upToDate = \case+ [("direct1", [1, 0, 1])] -> pure Success+ versions -> throwM (Fatal [exon|Unexpected build plan: #{showP versions}|])++stateFileTarget_upToDate :: Text+stateFileTarget_upToDate =+ [exon|{+ bounds = {+ local1 = {+ direct1 = {+ lower = "0.1";+ upper = "1.1";+ };+ };+ };+ versions = {+ latest = {+ direct1 = "1.0.1";+ };+ };+ initial = {+ latest = {};+ };+ overrides = {+ latest = {+ direct1 = {+ version = "1.0.1";+ hash = "direct1-1.0.1";+ };+ };+ };+ resolving = false;+}+|]++-- | This has a minimal configuration: Only one target with one dep with one version.+-- The version is already in the overrides and bounds.+-- The only thing missing is the entry in @versions@.+--+-- In the final state, the version should have been added.+--+-- This is a bugfix test, since at some point, the versions would not have been written back if _all_ candidates+-- resulted in @MutationKeep@ because they had been classified as up to date based on the comparison of the candidate+-- version and the preexisting override.+-- Comparing with the override was wrong to begin with, since that would fail to notice an up to date version if it was+-- installed.+-- But in general, versions from successful builds should be written to the mutation state even for @MutationKeep@.+-- However, this is only significant if the state has been tampered with between runs, since a preexisting override+-- should have a corresponding version entry.+test_bumpMutationUpToDate :: UnitTest+test_bumpMutationUpToDate = do+ Result {stateFile} <- bumpTest params bumpOptimizeMain+ eqLines stateFileTarget_upToDate (renderRootExpr stateFile)+ where+ params = (testParams False packages_upToDate) {+ ghcPackages = ghcPackages_upToDate,+ state = state_upToDate,+ build = build_upToDate+ }++test_bumpMutation :: TestTree+test_bumpMutation =+ testGroup "bump" [+ unitTest "basic" test_bumpMutationBasic,+ unitTest "up to date" test_bumpMutationUpToDate+ ]
+ test/Hix/Test/Managed/DiffTest.hs view
@@ -0,0 +1,54 @@+module Hix.Test.Managed.DiffTest where++import Data.These (These (These, This))+import Exon (exon)+import Hedgehog (evalMaybe, (===))+import Test.Tasty (TestTree, testGroup)++import Hix.Data.VersionBounds (versionBounds)+import Hix.Managed.Data.Diff (BoundsChange, VersionChange)+import Hix.Managed.Diff (boundsChange, versionChange)+import qualified Hix.Managed.EnvResult+import Hix.Managed.EnvResult (+ BoundsModification (BoundsModification),+ DepModification (DepUpdated),+ DepResult (DepResult),+ DepResultDetail (DepModified),+ depResult,+ )+import Hix.Managed.Handlers.Report.Prod (formatDepResult)+import Hix.Test.Utils (UnitTest, unitTest)++versionDiff1 :: VersionChange+versionDiff1 =+ versionChange (Just [1, 0]) (Just [1, 5])++boundsDiff1 :: BoundsChange+boundsDiff1 =+ boundsChange (versionBounds [1, 0] [2, 0]) (versionBounds [1, 5] [2, 0])++result1 :: Maybe DepResult+result1 =+ depResult "dep" versionDiff1 boundsDiff1++target1 :: DepResult+target1 =+ DepResult {+ package = "dep",+ version = [1, 5],+ bounds = versionBounds [1, 5] [2, 0],+ detail = DepModified (DepUpdated (These [1, 0] (BoundsModification (This (Just [1, 0])))))+ }++test_boundsDiffDepResult :: UnitTest+test_boundsDiffDepResult = do+ res <- evalMaybe result1+ target1 === res+ formatted <- evalMaybe (formatDepResult res)+ ([exon|📦 [34mdep[0m|], [exon|[31m1.0[0m -> [32m1.5[0m|], [exon|↕ [[31m1.0[0m, 2.0] -> [[32m1.5[0m, 2.0]|]) === formatted++test_diff :: TestTree+test_diff =+ testGroup "Bounds and version diffs" [+ unitTest "BoundsChange to DepResult" test_boundsDiffDepResult+ ]
+ test/Hix/Test/Managed/LowerAuto/MutationOptimizeTest.hs view
@@ -0,0 +1,344 @@+module Hix.Test.Managed.LowerAuto.MutationOptimizeTest where++import Exon (exon)+import Test.Tasty (TestTree, testGroup)++import Hix.Class.Map (nGen, (!!))+import Hix.Data.Error (Error (Fatal))+import qualified Hix.Data.Overrides+import Hix.Data.Overrides (Override (Override))+import Hix.Data.Version (SourceHash (SourceHash), Versions)+import qualified Hix.Managed.Cabal.Data.Packages+import Hix.Managed.Cabal.Data.Packages (GhcPackages (GhcPackages), InstalledPackages)+import Hix.Managed.Cabal.Data.SourcePackage (SourcePackages)+import Hix.Managed.Data.LowerConfig (reset)+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto, managedPackages)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Data.ProjectStateProto+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto (ProjectStateProto))+import Hix.Managed.Data.StageState (BuildStatus (Failure, Success))+import Hix.Managed.Lower.Auto (lowerAutoMain)+import Hix.Monad (M, throwM)+import Hix.NixExpr (renderRootExpr)+import Hix.Pretty (showP)+import Hix.Test.Hedgehog (eqLines)+import Hix.Test.Managed.Run (Result (..), TestParams (..), lowerTest, testParams)+import Hix.Test.Utils (UnitTest, unitTest)++packages :: Packages ManagedPackageProto+packages =+ managedPackages [+ (("local1", "1.0"), [+ "direct1",+ "direct2",+ "direct3 <1.9"+ ])+ ]++initialState :: ProjectStateProto+initialState =+ ProjectStateProto {+ bounds = [+ ("local1", [+ ("direct1", [[1, 0], [2, 0]]),+ ("direct2", [[1, 0], [2, 0]])+ ])+ ],+ versions = [+ ("lower", [+ ("direct1", [1, 0]),+ ("direct2", [1, 0])+ ])+ ],+ overrides = [+ ("lower", nGen @[] [1 .. 2] override)+ ],+ initial = [+ ("lower", [+ ("direct1", [1, 5]),+ ("direct2", [1, 5])+ ])+ ],+ resolving = False+ }+ where+ override (num :: Natural) =+ (+ fromString [exon|direct#{show num}|],+ Override {version = [1, 0], hash = SourceHash [exon|direct#{show num}-1.0|]}+ )++installed :: InstalledPackages+installed =+ [+ ("direct1-1.2", []),+ ("direct2-1.2", []),+ ("direct3-1.2", [])+ ]++packageDb :: SourcePackages+packageDb =+ [+ ("direct1", versions),+ ("direct2", versions),+ ("direct3", versions)+ ]+ where+ versions =+ [+ ([0, 9], []),+ ([1, 0], []),+ ([1, 2], []),+ ([1, 5], []),+ ([1, 9], [])+ ]++ghcPackages :: GhcPackages+ghcPackages = GhcPackages {installed, available = packageDb}++buildVersionsBasic :: Versions -> M BuildStatus+buildVersionsBasic = \case+ versions+ | Just v <- versions !! "direct2"+ , v <= [1, 0]+ -> pure Failure+ -- direct3 initialization works only at 1.2+ | Just v <- versions !! "direct3"+ , v >= [1, 5]+ -> pure Failure+ -- initialize direct3+ [+ ("direct1", [1, 5]),+ ("direct2", [1, 5]),+ ("direct3", [1, 2])+ ] -> pure Success+ -- optimize direct1+ [+ ("direct1", _),+ ("direct2", [1, 5]),+ ("direct3", [1, 2])+ ] -> pure Success+ -- optimize direct2+ [+ ("direct1", [0, 9]),+ ("direct2", [1, 2]),+ ("direct3", [1, 2])+ ] -> pure Success+ -- optimize direct3+ [+ ("direct1", [0, 9]),+ ("direct2", [1, 2]),+ ("direct3", [1, 0])+ ] -> pure Success+ -- optimize direct3+ [+ ("direct1", [0, 9]),+ ("direct2", [1, 2]),+ ("direct3", [0, 9])+ ] -> pure Success+ versions -> throwM (Fatal [exon|Unexpected build plan: #{showP versions}|])++stateFileTargetBasic :: Text+stateFileTargetBasic =+ [exon|{+ bounds = {+ local1 = {+ direct1 = {+ lower = "0.9";+ upper = "2.0";+ };+ direct2 = {+ lower = "1.2";+ upper = "2.0";+ };+ direct3 = {+ lower = "0.9";+ upper = null;+ };+ };+ };+ versions = {+ lower = {+ direct1 = "0.9";+ direct2 = "1.2";+ direct3 = "0.9";+ };+ };+ initial = {+ lower = {+ direct1 = "1.5";+ direct2 = "1.5";+ direct3 = "1.2";+ };+ };+ overrides = {+ lower = {+ direct1 = {+ version = "0.9";+ hash = "direct1-0.9";+ };+ direct3 = {+ version = "0.9";+ hash = "direct3-0.9";+ };+ };+ };+ resolving = false;+}+|]++-- | Goals for these deps:+--+-- A new dependency, @direct3@, has been added to the project, so Init resets all versions to initial and finds an+-- initial bound for the new dep.+-- Afterwards, Optimize successfully determines the best bounds.+--+-- - @direct1@ succeeds for all versions, so its optimized bound will be 0.9.+-- Its initial bound 1.5 will be preserved.+--+-- - @direct2@ succeeds for all versions above 1.0, so its optimized bound will be 1.2.+-- Its initial bound 1.5 will be preserved.+--+-- - @direct3@ succeeds for all versions below 1.5, so its initial bound will be 1.2 and its optimized bound will be+-- 0.9.+test_lowerAutoMutationOptimizeBasic :: UnitTest+test_lowerAutoMutationOptimizeBasic = do+ Result {stateFile} <- lowerTest params (lowerAutoMain def)+ eqLines stateFileTargetBasic (renderRootExpr stateFile)+ where+ params =+ (testParams False packages) {+ ghcPackages,+ state = initialState,+ build = buildVersionsBasic+ }++buildVersionsReset :: Versions -> M BuildStatus+buildVersionsReset = \case+ versions+ | Just v <- versions !! "direct2"+ , v <= [1, 0]+ -> pure Failure+ -- direct3 initialization works only at 1.2+ | Just v <- versions !! "direct3"+ , v >= [1, 5]+ -> pure Failure+ -- initialize all versions (latest versions build for direct1 and direct2, so only direct3 deviates)+ [+ ("direct1", [1, 9]),+ ("direct2", [1, 9]),+ ("direct3", [1, 2])+ ] -> pure Success+ -- optimize direct1+ [+ ("direct1", _),+ ("direct2", [1, 9]),+ ("direct3", [1, 2])+ ] -> pure Success+ -- optimize direct2, first major+ [+ ("direct1", [0, 9]),+ ("direct2", [1, 5]),+ ("direct3", [1, 2])+ ] -> pure Success+ -- optimize direct2, second major+ [+ ("direct1", [0, 9]),+ ("direct2", [1, 2]),+ ("direct3", [1, 2])+ ] -> pure Success+ -- optimize direct3, first major+ [+ ("direct1", [0, 9]),+ ("direct2", [1, 2]),+ ("direct3", [1, 0])+ ] -> pure Success+ -- optimize direct3, second major+ [+ ("direct1", [0, 9]),+ ("direct2", [1, 2]),+ ("direct3", [0, 9])+ ] -> pure Success+ versions -> throwM (Fatal [exon|Unexpected build plan: #{showP versions}|])++stateFileTargetReset :: Text+stateFileTargetReset =+ [exon|{+ bounds = {+ local1 = {+ direct1 = {+ lower = "0.9";+ upper = "2.0";+ };+ direct2 = {+ lower = "1.2";+ upper = "2.0";+ };+ direct3 = {+ lower = "0.9";+ upper = null;+ };+ };+ };+ versions = {+ lower = {+ direct1 = "0.9";+ direct2 = "1.2";+ direct3 = "0.9";+ };+ };+ initial = {+ lower = {+ direct1 = "1.9";+ direct2 = "1.9";+ direct3 = "1.2";+ };+ };+ overrides = {+ lower = {+ direct1 = {+ version = "0.9";+ hash = "direct1-0.9";+ };+ direct3 = {+ version = "0.9";+ hash = "direct3-0.9";+ };+ };+ };+ resolving = false;+}+|]++-- | Goals for these deps:+--+-- A new dependency, @direct3@, has been added to the project and @--reset@ was specified, so all deps are completely+-- recomputed from scratch.+-- Afterwards, Optimize successfully determines the best bounds.+--+-- - @direct1@ succeeds for all versions, so its optimized bound will be 0.9.+-- Its initial bound will be 1.9.+--+-- - @direct2@ succeeds for all versions above 1.0, so its optimized bound will be 1.2.+-- Its initial bound will be 1.9.+--+-- - @direct3@ succeeds for all versions below 1.5, so its initial bound will be 1.2 and its optimized bound will be+-- 0.9.+test_lowerAutoMutationOptimizeReset :: UnitTest+test_lowerAutoMutationOptimizeReset = do+ Result {stateFile} <- lowerTest params (lowerAutoMain def {reset = True})+ eqLines stateFileTargetReset (renderRootExpr stateFile)+ where+ params =+ (testParams False packages) {+ ghcPackages,+ state = initialState,+ build = buildVersionsReset+ }++test_lowerAutoMutationOptimize :: TestTree+test_lowerAutoMutationOptimize =+ testGroup "lower.auto optimize" [+ unitTest "basic" test_lowerAutoMutationOptimizeBasic,+ unitTest "reset initial" test_lowerAutoMutationOptimizeReset+ ]
+ test/Hix/Test/Managed/LowerAuto/MutationStabilizeTest.hs view
@@ -0,0 +1,202 @@+module Hix.Test.Managed.LowerAuto.MutationStabilizeTest where++import Exon (exon)++import Hix.Class.Map (nGen, (!!))+import Hix.Data.Error (Error (Fatal))+import qualified Hix.Data.Overrides+import Hix.Data.Overrides (Override (Override))+import Hix.Data.Version (SourceHash (SourceHash), Versions)+import qualified Hix.Managed.Cabal.Data.Packages+import Hix.Managed.Cabal.Data.Packages (GhcPackages (GhcPackages), InstalledPackages)+import Hix.Managed.Cabal.Data.SourcePackage (SourcePackages)+import Hix.Managed.Data.LowerConfig (stabilize)+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto, managedPackages)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Data.ProjectStateProto+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto (ProjectStateProto))+import Hix.Managed.Data.StageState (BuildStatus (Failure, Success))+import Hix.Managed.Lower.Auto (lowerAutoMain)+import Hix.Monad (M, throwM)+import Hix.NixExpr (renderRootExpr)+import Hix.Pretty (showP)+import Hix.Test.Hedgehog (eqLines)+import Hix.Test.Managed.Run (Result (..), TestParams (..), lowerTest, testParams)+import Hix.Test.Utils (UnitTest)++packages :: Packages ManagedPackageProto+packages =+ managedPackages [+ (("local1", "1.0"), [+ "direct1",+ "direct2",+ "direct3"+ ])+ ]++installed :: InstalledPackages+installed =+ [+ ("direct1-1.2", []),+ ("direct2-1.2", []),+ ("direct3-1.2", [])+ ]++packageDb :: SourcePackages+packageDb =+ [+ ("direct1", versions),+ ("direct2", versions),+ ("direct3", versions)+ ]+ where+ versions =+ [+ ([0, 9], []),+ ([1, 0], []),+ ([1, 2], []),+ ([1, 5], []),+ ([1, 9], [])+ ]++ghcPackages :: GhcPackages+ghcPackages = GhcPackages {installed, available = packageDb}++state :: ProjectStateProto+state =+ ProjectStateProto {+ bounds = [+ ("local1", [+ ("direct1", [[1, 0], [2, 0]]),+ ("direct2", [[1, 0], [2, 0]]),+ ("direct3", [[1, 0], [2, 0]])+ ])+ ],+ versions = [+ ("lower", [+ ("direct1", [1, 0]),+ ("direct2", [1, 0]),+ ("direct3", [1, 0])+ ])+ ],+ overrides = [+ ("lower", nGen @[] [1 .. 3] override)+ ],+ initial = [+ ("lower", [+ ("direct1", [1, 5]),+ ("direct2", [1, 5]),+ ("direct3", [1, 5])+ ])+ ],+ resolving = False+ }+ where+ override (num :: Natural) =+ (+ fromString [exon|direct#{show num}|],+ Override {version = [1, 0], hash = SourceHash [exon|direct#{show num}-1.0|]}+ )++build :: Versions -> M BuildStatus+build = \case+ versions+ | Just v <- versions !! "direct2"+ , v <= [1, 0]+ -> pure Failure+ | Just v <- versions !! "direct3"+ , v <= [1, 2]+ -> pure Failure+ -- initial bounds+ [+ ("direct1", [1, 5]),+ ("direct2", [1, 5]),+ ("direct3", [1, 5])+ ] -> pure Success+ -- stabilizing direct1+ [+ ("direct1", [1, 0]),+ ("direct2", [1, 5]),+ ("direct3", [1, 5])+ ] -> pure Success+ -- stabilizing direct2 and direct3+ [+ ("direct1", [1, 0]),+ ("direct2", [1, 2]),+ ("direct3", [1, 5])+ ] -> pure Success+ versions -> throwM (Fatal [exon|Unexpected build plan: #{showP versions}|])++stateFileTarget :: Text+stateFileTarget =+ [exon|{+ bounds = {+ local1 = {+ direct1 = {+ lower = "1.0";+ upper = "2.0";+ };+ direct2 = {+ lower = "1.2";+ upper = "2.0";+ };+ direct3 = {+ lower = "1.5";+ upper = "2.0";+ };+ };+ };+ versions = {+ lower = {+ direct1 = "1.0";+ direct2 = "1.2";+ direct3 = "1.5";+ };+ };+ initial = {+ lower = {+ direct1 = "1.5";+ direct2 = "1.5";+ direct3 = "1.5";+ };+ };+ overrides = {+ lower = {+ direct1 = {+ version = "1.0";+ hash = "direct1-1.0";+ };+ direct3 = {+ version = "1.5";+ hash = "direct3-1.5";+ };+ };+ };+ resolving = false;+}+|]++-- | Goals for these deps:+--+-- The project was changed and the lower bounds have been invalidated.+-- LowerInit does not process mutations since all deps have initial bounds.+-- LowerStabilize is executed because the config flag is enabled.+--+-- - @direct1@ is compatible in all versions.+--+-- - @direct2@ has become incompatible for all versions up to 1.0.+-- The mutation handler tries 1.0 and 1.2, the latter of which succeeds.+--+-- - @direct2@ has become incompatible for all versions up to 1.2.+-- The mutation handler tries 1.0, 1.2 and 1.5, the third of which succeeds.+test_lowerAutoMutationStabilize :: UnitTest+test_lowerAutoMutationStabilize = do+ Result {stateFile} <- lowerTest params (lowerAutoMain def {stabilize = True})+ eqLines stateFileTarget (renderRootExpr stateFile)+ where+ params =+ (testParams False packages) {+ ghcPackages,+ state,+ build+ }
+ test/Hix/Test/Managed/LowerInit/MutationTest.hs view
@@ -0,0 +1,438 @@+module Hix.Test.Managed.LowerInit.MutationTest where++import qualified Data.Text as Text+import Exon (exon)+import Hedgehog ((===))++import Hix.Class.Map ((!!))+import Hix.Data.Error (Error (Fatal))+import Hix.Data.Options (envs, readUpperBounds)+import qualified Hix.Data.Overrides+import Hix.Data.Overrides (Override (Override))+import Hix.Data.Version (SourceHash (SourceHash), Versions)+import qualified Hix.Managed.Cabal.Changes+import Hix.Managed.Cabal.Changes (SolverPlan (SolverPlan))+import qualified Hix.Managed.Cabal.Data.Packages+import Hix.Managed.Cabal.Data.Packages (GhcPackages (GhcPackages))+import Hix.Managed.Cabal.Data.SourcePackage (SourcePackages)+import Hix.Managed.Cabal.Mock.SourcePackage (allDep, allDeps)+import Hix.Managed.Data.Constraints (EnvConstraints)+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto, managedPackages)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Data.ProjectStateProto+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto (ProjectStateProto))+import Hix.Managed.Data.StageState (BuildStatus (Failure, Success))+import Hix.Managed.Lower.Init (lowerInitMain)+import Hix.Monad (M, throwM)+import Hix.NixExpr (renderRootExpr)+import Hix.Pretty (showP)+import Hix.Test.Hedgehog (eqLines, listEqZip)+import Hix.Test.Managed.Run (Result (..), TestParams (..), lowerTest, testParams)+import Hix.Test.Utils (UnitTest)++packages :: Packages ManagedPackageProto+packages =+ managedPackages [+ (("local1", "1.0"), [+ "direct1 >5.0",+ "direct2 <5.1",+ "direct3",+ "direct4"+ ]),+ (("local2", "1.0"), ["local1", "local3"]),+ (("local3", "1.0"), ["local1", "direct1"]),+ (("local4", "1.0"), ["direct4"]),+ (("local5", "1.0"), ["direct5"]),+ (("local6", "1.0"), ["direct3"]),+ (("local7", "1.0"), ["local6 <2", "direct2"]),+ (("local8", "1.0"), ["direct1", "direct6"])+ ]++packageDb :: SourcePackages+packageDb =+ [+ ("direct1", [+ ([1, 0, 3], ["transitive1 >=1"]),+ ([1, 0, 4], ["transitive1 >=1"]),+ ([1, 0, 5], ["transitive2 >=1"])+ ]),+ ("direct2", allDep "transitive3 >=1" [+ ([5, 0], []),+ ([5, 0, 5], [])+ ]),+ ("direct3", [+ ([0, 8], []),+ ([1, 0, 1], []),+ ([1, 3], []),+ ([1, 4], []),+ ([1, 5], [])+ ]),+ ("direct4", allDeps ["direct2 ==5.0.5", "transitive4 >=1"] [+ ([1, 0, 1], []),+ ([1, 0, 2], []),+ ([1, 0, 3], []),+ ([1, 0, 4], [])+ ]),+ ("direct5", [+ ([1, 5, 1], [])+ ]),+ ("direct6", [+ ([1, 0, 1], [])+ ]),+ ("transitive1", [([1, 0, 1], [])]),+ ("transitive2", [([1, 0, 1], [])]),+ ("transitive3", [([1, 0, 1], [])]),+ ("transitive4", [([1, 0, 1], [])])+ ]++ghcPackages :: GhcPackages+ghcPackages = GhcPackages {installed = [], available = packageDb}++state :: ProjectStateProto+state =+ ProjectStateProto {+ bounds = [+ ("local1", [+ ("direct2", [[4, 0], [4, 4]]),+ ("direct3", [[1, 0, 1], [1, 5]])+ ]),+ ("local5", [("direct5", [[1, 5], [1, 6]])])+ ],+ versions = [+ ("lower-main", [+ ("direct1", [1, 0, 1]),+ ("direct2", [4, 3, 1]),+ ("direct3", [1, 0, 1])+ ]),+ ("lower-unused", [+ ("direct1", [1, 0, 1]),+ ("direct6", [1, 0, 1])+ ])+ ],+ overrides = [+ ("latest", [("direct2", Override {version = [5, 0], hash = SourceHash "direct2-5.0"})]),+ ("lower-main", [("direct3", Override {version = [1, 0, 1], hash = SourceHash "direct3-1.0.1"})])+ ],+ initial = [("lower-main", [("direct3", [1, 0, 1])])],+ resolving = False+ }++build :: Versions -> M BuildStatus+build = \case+ versions+ | Just [1, 0, n] <- versions !! "direct1"+ , n /= 5+ -> pure Failure+ versions+ | Just [1, 0, n] <- versions !! "direct4"+ , n /= 3+ -> pure Failure+ [+ ("direct1", [1, 0, 5]),+ ("direct2", [5, 0, 5]),+ ("direct3", [1, 0, 1]),+ ("direct4", [1, 0, 3]),+ ("transitive2", [1, 0, 1]),+ ("transitive3", [1, 0, 1]),+ ("transitive4", [1, 0, 1])+ ] -> pure Success+ [+ ("direct2", [5, 0]),+ ("direct3", [1, 4]),+ ("transitive3", [1, 0, 1])+ ] -> pure Success+ [+ ("direct2", [5, 0]),+ ("transitive3", [1, 0, 1])+ ] -> pure Success+ versions -> throwM (Fatal [exon|Unexpected build plan: #{showP versions}|])++-- | This uses a very bespoke @IsString@ instance for @(PackageName, MutationConstraints)@ that parses a @Dep@ and uses+-- the bounds (inclusive or exclusive) to construct @VersionBounds@.+cabalTarget :: [(EnvConstraints, Maybe SolverPlan)]+cabalTarget =+ [+ item1 3 1,+ item1 4 1,+ item1 5 2,+ ([+ "direct1",+ "direct2 ==5.0",+ "direct3 <=1.0.1",+ "direct4"+ ], Nothing),+ ([+ "direct1",+ "direct2 ==5.0.5",+ "direct3 <=1.0.1",+ "direct4"+ ], plan ["direct1-1.0.5", "direct2-5.0.5", "direct3-1.0.1", "direct4-1.0.4", "transitive2-1.0.1", "transitive3-1.0.1", "transitive4-1.0.1"]),+ item2 1,+ item2 2,+ item2 3,+ -- Iteration 2+ item3 3 1,+ item3 4 1,+ item3 5 2,+ ([+ "direct1 <=1.0.5",+ "direct2 <=5.0.5 && ==5.0",+ "direct3 <=1.0.1",+ "direct4 <=1.0.3"+ ], Nothing),+ ([+ "direct1 <=1.0.5",+ "direct2 <=5.0.5 && ==5.0.5",+ "direct3 <=1.0.1",+ "direct4 <=1.0.3"+ ], plan ["direct1-1.0.5", "direct2-5.0.5", "direct3-1.0.1", "direct4-1.0.3", "transitive2-1.0.1", "transitive3-1.0.1", "transitive4-1.0.1"]),+ -- lower-special+ ([+ "direct2 ==5.0",+ "local6"+ ], plan ["direct2-5.0", "direct3-1.4", "local6-1.0", "transitive3-1.0.1"])+ ]+ where+ item1 (v1 :: Natural) (nt :: Natural) =+ ([+ fromString [exon|direct1 ==1.0.#{show v1}|],+ "direct2",+ "direct3 <=1.0.1",+ "direct4"+ ], plan [fromString [exon|direct1-1.0.#{show v1}|], "direct2-5.0.5", "direct3-1.0.1", "direct4-1.0.4", fromString [exon|transitive#{show nt}-1.0.1|], "transitive3-1.0.1", "transitive4-1.0.1"])++ item2 (v1 :: Natural) =+ ([+ "direct1",+ "direct2",+ "direct3 <=1.0.1",+ fromString [exon|direct4 ==1.0.#{show v1}|]+ ], plan ["direct1-1.0.5", "direct2-5.0.5", "direct3-1.0.1", fromString [exon|direct4-1.0.#{show v1}|], "transitive2-1.0.1", "transitive3-1.0.1", "transitive4-1.0.1"])++ item3 (v1 :: Natural) (nt :: Natural) =+ ([+ fromString [exon|direct1 <=1.0.5 && ==1.0.#{show v1}|],+ "direct2 <=5.0.5",+ "direct3 <=1.0.1",+ "direct4 <=1.0.3"+ ], plan [fromString [exon|direct1-1.0.#{show v1}|], "direct2-5.0.5", "direct3-1.0.1", "direct4-1.0.3", fromString [exon|transitive#{show nt}-1.0.1|], "transitive3-1.0.1", "transitive4-1.0.1"])++ plan changes = Just SolverPlan {changes, matching = [], nonReinstallable = Nothing}++stateFileTarget :: Text+stateFileTarget =+ [exon|{+ bounds = {+ local1 = {+ direct1 = {+ lower = "1.0.5";+ upper = null;+ };+ direct2 = {+ lower = "5.0.5";+ upper = "5.1";+ };+ direct3 = {+ lower = "1.0.1";+ upper = "1.5";+ };+ direct4 = {+ lower = "1.0.3";+ upper = null;+ };+ };+ local2 = {};+ local3 = {+ direct1 = {+ lower = "1.0.5";+ upper = null;+ };+ };+ local4 = {+ direct4 = {+ lower = "1.0.3";+ upper = null;+ };+ };+ local5 = {+ direct5 = {+ lower = "1.5";+ upper = "1.6";+ };+ };+ local6 = {+ direct3 = {+ lower = "1.0.1";+ upper = "1.5";+ };+ };+ local7 = {+ direct2 = {+ lower = "5.0";+ upper = null;+ };+ };+ local8 = {+ direct1 = {+ lower = null;+ upper = null;+ };+ direct6 = {+ lower = null;+ upper = null;+ };+ };+ };+ versions = {+ lower-main = {+ direct1 = "1.0.5";+ direct2 = "5.0.5";+ direct3 = "1.0.1";+ direct4 = "1.0.3";+ };+ lower-special = {+ direct2 = "5.0";+ };+ lower-unused = {+ direct1 = "1.0.1";+ direct6 = "1.0.1";+ };+ };+ initial = {+ lower-main = {+ direct1 = "1.0.5";+ direct2 = "5.0.5";+ direct3 = "1.0.1";+ direct4 = "1.0.3";+ };+ lower-special = {+ direct2 = "5.0";+ };+ lower-unused = {};+ };+ overrides = {+ latest = {+ direct2 = {+ version = "5.0";+ hash = "direct2-5.0";+ };+ };+ lower-main = {+ direct1 = {+ version = "1.0.5";+ hash = "direct1-1.0.5";+ };+ direct2 = {+ version = "5.0.5";+ hash = "direct2-5.0.5";+ };+ direct3 = {+ version = "1.0.1";+ hash = "direct3-1.0.1";+ };+ direct4 = {+ version = "1.0.3";+ hash = "direct4-1.0.3";+ };+ transitive2 = {+ version = "1.0.1";+ hash = "transitive2-1.0.1";+ };+ transitive3 = {+ version = "1.0.1";+ hash = "transitive3-1.0.1";+ };+ transitive4 = {+ version = "1.0.1";+ hash = "transitive4-1.0.1";+ };+ };+ lower-special = {+ direct2 = {+ version = "5.0";+ hash = "direct2-5.0";+ };+ direct3 = {+ version = "1.4";+ hash = "direct3-1.4";+ };+ transitive3 = {+ version = "1.0.1";+ hash = "transitive3-1.0.1";+ };+ };+ };+ resolving = false;+}+|]++logTarget :: [Text]+logTarget =+ Text.lines [exon|+[35m[1m>>>[0m [33mlower-main[0m+[35m[1m>>>[0m Found initial lower bounds for all deps after 2 iterations.+[35m[1m>>>[0m Added new versions:+ 📦 [34mdirect4[0m 1.0.3 ↕ [no bounds] -> >=[32m1.0.3[0m+[35m[1m>>>[0m Updated versions:+ 📦 [34mdirect1[0m [31m1.0.1[0m -> [32m1.0.5[0m ↕ [no bounds] -> >=[32m1.0.5[0m+ 📦 [34mdirect2[0m [31m4.3.1[0m -> [32m5.0.5[0m ↕ [[31m4.0[0m, 5.1] -> [[32m5.0.5[0m, 5.1]++[35m[1m>>>[0m [33mlower-special[0m+[35m[1m>>>[0m Found initial lower bounds for all deps after 1 iteration.+[35m[1m>>>[0m Added new versions:+ 📦 [34mdirect2[0m 5.0 ↕ [no bounds] -> >=[32m5.0[0m+|]++-- | Goals for these deps:+--+-- - @direct1@ will have three available versions and build successfully for the third one, 1.0.5, which will be added+-- to the overrides. Its bound will be @>=1.0.5@.+-- It also has a lower bound, 5.0, in the flake config, which is ignored.+--+-- - @direct2@ builds successfully with its lowest version 5.0, but @direct3@ restricts its version to 5.0.5, which+-- will be in the final state as lower bound and override.+-- It has preexisting managed bounds that will be printed as a diff.+-- Its upper bound from the user config will be retained, replacing the managed bound.+-- It also has a preexisting entry in the overrides of another env, @latest@, which will be retained.+--+-- - @direct3@ has a preexisting entry in `initial`, so it will be ignored completely as a candidate, since we want to+-- be able to run @lower.init@ after @lower.optimize@ without resetting all lower bounds to the initial states.+-- It has preexisting managed bounds that will be printed as a diff.+--+-- - @direct4@ is a dependency of two targets that have no dependency on each other, but one of them has a stricter+-- version requirement, so that the build fails for @<= direct4-1.0.2@ in @local1@ but only for @direct4-1.0.1@ in+-- @local4@.+--+-- - @direct5@ is a dependency of @local5@, which is not part of the target set.+-- The managed bounds for @local5@ in the initial file should be preserved and unchanged (save for version range+-- normalization), and @direct5@ should never appear in the solver and build deps.+--+-- - @local6@ is a cross-env dependency of @local7@ and should be omitted from the overrides in @lower-special@.+-- It has a dependency on @direct3@, which is not among the direct dependencies of @lower-special@, therefore being+-- excluded from the solver params when mutating @local7@.+-- Even though @direct3@ has a lower bound in @lower-main@, 1.0.1, it is treated as a regular transitive dep, and the+-- solver chooses the latest matching version for it.+-- Since the pre-existing, exclusive, upper bound in the deps of @local6@ is 1.5, the chosen version is the+-- next-lower, 1.4.+-- This version is written to the overrides for @lower-special@, like any non-installed transitive dep.+test_lowerInitMutation :: UnitTest+test_lowerInitMutation = do+ Result {..} <- lowerTest params (lowerInitMain def)+ listEqZip cabalTarget cabalLog+ eqLines stateFileTarget (renderRootExpr stateFile)+ logTarget === drop 24 (reverse log)+ where+ params =+ (testParams False packages) {+ envs = [+ ("lower-main", ["local1", "local2", "local3", "local4", "local6"]),+ ("lower-special", ["local7"]),+ ("lower-unused", ["local8"])+ ],+ cabalLog = True,+ log = True,+ ghcPackages,+ state,+ projectOptions = def {envs = ["lower-main", "lower-special"], readUpperBounds = True},+ build+ }
+ test/Hix/Test/Managed/LowerNativeTest.hs view
@@ -0,0 +1,268 @@+module Hix.Test.Managed.LowerNativeTest where++import Control.Monad.Trans.Reader (ask)+import qualified Data.Text.IO as Text+import Exon (exon)+import Hedgehog (evalEither)+import Path (Abs, Dir, File, Path, Rel, parent, reldir, relfile, toFilePath, (</>))+import Path.IO (createDirIfMissing, getCurrentDir)++import qualified Hix.Data.Monad+import Hix.Data.Monad (AppResources (AppResources), M (M))+import Hix.Data.Options (projectOptions)+import Hix.Error (pathText)+import Hix.Managed.Cabal.Data.Config (GhcDb (GhcDbSystem))+import qualified Hix.Managed.Data.EnvConfig+import Hix.Managed.Data.EnvConfig (EnvConfig (EnvConfig))+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto, managedPackages)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Data.ProjectContext+import qualified Hix.Managed.Data.ProjectContextProto+import Hix.Managed.Data.ProjectContextProto (ProjectContextProto (ProjectContextProto))+import qualified Hix.Managed.Data.ProjectResult+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto (ProjectStateProto))+import qualified Hix.Managed.Data.StateFileConfig+import Hix.Managed.Data.StateFileConfig (StateFileConfig (StateFileConfig))+import qualified Hix.Managed.Handlers.Build.Prod as Build+import Hix.Managed.Lower.Init (lowerInitMain)+import Hix.Managed.Lower.Optimize (lowerOptimizeMain)+import Hix.Managed.ProjectContext (updateProject)+import qualified Hix.Managed.ProjectContextProto as ProjectContextProto+import Hix.Managed.ProjectContextProto (projectContext)+import Hix.Test.Hedgehog (eqLines)+import Hix.Test.Utils (UnitTest, runMTest)++-- TODO when aeson's lower bound is set to 2.2 here, the build of 2.1.0.0 fails with an infinite recursion in nix when+-- reaching optimize.+-- But when it is set to 2.1, the build succeeds during init.+-- in the former case, there are a few more overrides added from the solver plan.+packages :: Packages ManagedPackageProto+packages =+ managedPackages [+ (("root", "1.0"), ["aeson >=2.2 && <2.3", "extra >=1.6 && <1.8"])+ ]++flake :: Path Abs Dir -> Text+flake hixRoot =+ [exon|{+ description = "hix test project";+ inputs.hix.url = "path:#{pathText hixRoot}";+ outputs = {self, hix, ...}: hix.lib.flake ({config, lib, ...}: {+ managed = {+ enable = true;+ lower.enable = true;+ };+ compat.enable = false;+ ghcVersions = [];+ packages = {+ root = {+ src = ./.;+ library = {+ enable = true;+ dependencies = ["aeson" "extra"];+ };+ };+ };+ envs.lower.localPackage = api: api.minimal;+ });+}|]++libMod :: Text+libMod =+ [exon|module Root where+import Data.Aeson+import Data.List.Extra+string :: String+string = "hello"+|]++addFile :: Path Abs Dir -> Path Rel File -> Text -> M ()+addFile root path content = do+ createDirIfMissing True (parent file)+ liftIO (Text.writeFile (toFilePath file) content)+ where+ file = root </> path++setupProject :: M (Path Abs Dir)+setupProject = do+ AppResources {tmp} <- M ask+ cwd <- getCurrentDir+ let projectRoot = tmp </> [reldir|project|]+ let hixRoot = parent (parent cwd)+ createDirIfMissing True projectRoot+ addFile projectRoot [relfile|flake.nix|] (flake hixRoot)+ addFile projectRoot [relfile|lib/Root.hs|] libMod+ pure projectRoot++targetStateFileInit :: Text+targetStateFileInit =+ [exon|{+ bounds = {+ root = {+ aeson = ">=2.2.0.0 && <2.3";+ extra = ">=1.7.7 && <1.8";+ };+ };+ overrides = {+ lower = {+ aeson = {+ version = "2.2.0.0";+ hash = "1rxbydr7mvchhlyz2111n70db90s1zd9h6miqbbqh2kyc2l0b3pd";+ };+ bifunctors = {+ version = "5.6.1";+ hash = "12k2v7334brn4v7yg3vjd6yv6sh4pzffc3d89qgc2llw7ncv4krw";+ };+ extra = {+ version = "1.7.7";+ hash = "0jgcd8gw6d22ngbi0lp3ak2ghzza59nb3vssrjldwxiim0nzf71v";+ };+ integer-conversion = {+ version = "0.1.0.1";+ hash = "1qy49ig5k8wcqsgjf2rkbv0dy9gpbdzg8yid1kcdn0s7vys59plj";+ };+ semialign = {+ version = "1.3";+ hash = "09147lz8z79ghnpr7z08y9dd0l6c9dz9hz85avfh6z330vl25r95";+ };+ semigroupoids = {+ version = "6.0.0.1";+ hash = "1fijnbfn29iwj567kdbhk67pn11ajm80p9d3hg48hppyx7yzpb2k";+ };+ text-iso8601 = {+ version = "0.1";+ hash = "0zsqjrks9spakiwhbc7xi4dqsx68lb2cd4rvrin3iclyrqg3a6xg";+ };+ th-abstraction = {+ version = "0.5.0.0";+ hash = "0dkilfrvk8zdn3gvyfv5zgjbwqhdf1yg90fk4byka0ib43kgkyvf";+ };+ };+ };+ initial = {+ lower = {+ aeson = "2.2.0.0";+ extra = "1.7.7";+ };+ };+ resolving = false;+}+|]++targetStateFileOptimize :: Text+targetStateFileOptimize =+ [exon|{+ bounds = {+ root = {+ aeson = ">=2.1.0.0 && <2.3";+ extra = ">=1.7.7 && <1.8";+ };+ };+ overrides = {+ lower = {+ OneTuple = {+ version = "0.3.1";+ hash = "0mb81j6zhvzq7h9yyhi9cszrq1g5d4lv3a8wpwimcvzbyg9bdd6p";+ };+ aeson = {+ version = "2.1.0.0";+ hash = "08s162yh716aaxd42k1kyv18p9nsyab42ns4340kvs6r0i8riwsi";+ };+ assoc = {+ version = "1.0.2";+ hash = "1sfc21z18sf8rpsbcr77kgw7qjpm5cm1d24n5ifsm2zid88v8fs9";+ };+ attoparsec = {+ version = "0.14.4";+ hash = "0y9dph5axyvr1bfcvmz6qh50bjcp50m2ljra14960anc6g74a3c8";+ };+ extra = {+ version = "1.7.7";+ hash = "0jgcd8gw6d22ngbi0lp3ak2ghzza59nb3vssrjldwxiim0nzf71v";+ };+ indexed-traversable-instances = {+ version = "0.1.1.2";+ hash = "1mmkklfpagv855p12dqq0r6xwg0v6dc1gj1n3nvzzy4b909ajgd0";+ };+ primitive = {+ version = "0.7.4.0";+ hash = "0n7r8al9wgz4r7jzizapn1dbnkqxwx2c4lqkgfm5q5bxj8fl7g1c";+ };+ scientific = {+ version = "0.3.7.0";+ hash = "09iwj0snmx7vj7x03l4vdcn76zylcgxd9pyz0yxkydgfnn3lvc08";+ };+ semialign = {+ version = "1.2.0.1";+ hash = "0mpw54c3s0x70k5l52a57yhnmbgrksb3dn0vjq4m37spyzsfl1v2";+ };+ strict = {+ version = "0.4.0.1";+ hash = "0xhr98m2632k2pic8q9bpnm3mp9098mmg4s66ds052b92494k49f";+ };+ these = {+ version = "1.1.1.1";+ hash = "1i1nfh41vflvqxi8w8n2s35ymx2z9119dg5zmd2r23ya7vwvaka1";+ };+ vector = {+ version = "0.13.1.0";+ hash = "0c1nw2sx14y29afdbwl40sk9vznx71rja5jcg14b8986778kl32d";+ };+ witherable = {+ version = "0.4.2";+ hash = "1ga4al351kwcfvsdr1ngyzj4aypvl46w357jflmgxacad8iqx4ik";+ };+ };+ };+ initial = {+ lower = {+ aeson = "2.2.0.0";+ extra = "1.7.7";+ };+ };+ resolving = false;+}+|]++lowerNativeTest :: M (Text, Text)+lowerNativeTest = do+ root <- setupProject+ let+ stateFileConf = StateFileConfig {+ file = [relfile|ops/managed.nix|],+ projectRoot = Just root+ }+ envsConfig = [("lower", EnvConfig {targets = ["root"], ghc = GhcDbSystem Nothing})]+ handlers <- Build.handlersProd stateFileConf envsConfig Nothing def False+ let+ opts = projectOptions ["lower"]++ proto0 =+ ProjectContextProto {+ packages,+ state = ProjectStateProto mempty mempty mempty mempty False,+ envs = envsConfig,+ buildOutputsPrefix = Nothing+ }++ stateFile = root </> [relfile|ops/managed.nix|]++ run context process = do+ result <- process handlers context+ updateProject handlers context.build result+ stateFileContent <- liftIO (Text.readFile (toFilePath stateFile))+ pure (result.state, stateFileContent)++ context0 <- ProjectContextProto.validate opts proto0+ (state1, stateFileContentInit) <- run context0 (lowerInitMain def)+ -- TODO the packages here aren't updated with the result from the first run+ let context1 = projectContext def state1 context0.packages context0.envs+ (_, stateFileContentOptimize) <- run context1 lowerOptimizeMain+ pure (stateFileContentInit, stateFileContentOptimize)++test_lowerNative :: UnitTest+test_lowerNative = do+ (stateFileContentInit, stateFileContentOptimize) <- evalEither =<< liftIO do+ runMTest True lowerNativeTest+ eqLines targetStateFileInit stateFileContentInit+ eqLines targetStateFileOptimize stateFileContentOptimize
+ test/Hix/Test/Managed/LowerOptimize/CandidatesTest.hs view
@@ -0,0 +1,99 @@+module Hix.Test.Managed.LowerOptimize.CandidatesTest where++import Data.IORef (IORef, modifyIORef', newIORef, readIORef)+import Distribution.Version (Version)+import Hedgehog (evalEither, (===))++import Hix.Data.PackageName (PackageName)+import qualified Hix.Data.VersionBounds+import Hix.Data.VersionBounds (fromLower, fromUpper)+import qualified Hix.Managed.Cabal.Data.SolverState+import Hix.Managed.Cabal.Data.SolverState (SolverState (SolverState), solverState, updateSolverState)+import Hix.Managed.Data.Constraints (MutationConstraints (MutationConstraints), mutation)+import Hix.Managed.Data.Mutable (MutableDep)+import qualified Hix.Managed.Data.MutableId+import Hix.Managed.Data.MutableId (MutableId (MutableId))+import qualified Hix.Managed.Data.Mutation+import Hix.Managed.Data.Mutation (BuildMutation (BuildMutation), MutationResult (MutationSuccess))+import qualified Hix.Managed.Data.MutationState+import Hix.Managed.Data.MutationState (MutationState (MutationState))+import Hix.Managed.Handlers.Mutation.Lower (processMutationLower)+import Hix.Managed.Lower.Candidates (candidatesOptimize)+import Hix.Managed.Lower.Data.LowerMode (lowerOptimizeMode)+import Hix.Managed.Lower.Optimize (lowerOptimizeUpdate)+import Hix.Managed.QueryDep (simpleQueryDep)+import Hix.Monad (M, clientError)+import Hix.Test.Utils (UnitTest, runMTest)++availableVersions :: PackageName -> M [Version]+availableVersions = \case+ "dep" -> pure versions+ _ -> clientError "No such package"+ where+ versions = s1 ++ s2+ s1 = [[1, m, n] | m <- [7 .. 9], n <- [1 .. 3]]+ s2 = [[2, m, n] | m <- [0 .. 4], n <- [1 .. 3]]++targets :: [Version]+targets =+ s1 ++ s2 ++ s3+ where+ s1 = [[1, 8, n] | n <- reverse [1 .. 3]]+ s2 = [[1, 9, n] | n <- reverse [1 .. 2]]+ s3 = [[2, m, n] | m <- [0 .. 3], n <- reverse [1 .. 3]]++candidateVersion :: Version+candidateVersion = [1, 9, 2]++build :: IORef [Maybe Version] -> BuildMutation -> M (Maybe MutationState)+build buildRef BuildMutation {solverState = SolverState {constraints = [("dep", MutationConstraints {mutation})]}} = do+ liftIO (modifyIORef' buildRef (mutation.lower :))+ pure (result =<< mutation.lower)+ where+ result version+ | candidateVersion == version+ = Just MutationState {+ bounds = [("dep", fromLower version)],+ versions = [("dep", Just version)],+ overrides = mempty,+ initial = []+ }+ | otherwise+ = Nothing+build _ _ = pure Nothing++test_candidatesOptimize :: UnitTest+test_candidatesOptimize = do+ buildRef <- liftIO (newIORef [])+ let+ result <- liftIO $ runMTest False do+ majors <- candidatesOptimize availableVersions mempty dep+ for majors \ mut ->+ processMutationLower def lowerOptimizeMode lowerOptimizeUpdate initialState mut (build buildRef)+ mutationResults <- evalEither result+ Just (MutationSuccess candidate True mstate (updateSolverState (const newConstraints) initialState)) === mutationResults+ triedVersions <- liftIO (readIORef buildRef)+ (Just <$> targets) === triedVersions+ where+ dep = simpleQueryDep mutable [[2, 4]]++ mstate =+ MutationState {+ bounds = [("dep", fromLower candidateVersion)],+ versions = [(mutable, Just candidateVersion)],+ overrides = mempty,+ initial = []+ }++ newConstraints = [(package, mempty {mutation = fromUpper candidateVersion})]++ initialState = solverState mempty mempty constraints def++ constraints = [(package, mempty)]++ candidate = MutableId {name = mutable, version = candidateVersion}++ mutable :: MutableDep+ mutable = "dep"++ package = "dep"
+ test/Hix/Test/Managed/LowerOptimize/MutationTest.hs view
@@ -0,0 +1,154 @@+module Hix.Test.Managed.LowerOptimize.MutationTest where++import Exon (exon)++import Hix.Data.Error (Error (Fatal))+import Hix.Data.Version (Versions)+import qualified Hix.Managed.Cabal.Data.Packages+import Hix.Managed.Cabal.Data.Packages (GhcPackages (GhcPackages))+import Hix.Managed.Cabal.Data.SourcePackage (SourcePackages)+import Hix.Managed.Cabal.Mock.SourcePackage (allDep)+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto, managedPackages)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Data.ProjectStateProto+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto (ProjectStateProto))+import Hix.Managed.Data.StageState (BuildStatus (Failure, Success))+import Hix.Managed.Lower.Optimize (lowerOptimizeMain)+import Hix.Monad (M, throwM)+import Hix.NixExpr (renderRootExpr)+import Hix.Pretty (showP)+import Hix.Test.Hedgehog (eqLines)+import Hix.Test.Managed.Run (TestParams (..), Result (..), testParams, lowerTest)+import Hix.Test.Utils (UnitTest)++packages :: Packages ManagedPackageProto+packages =+ managedPackages [(("local1", "1.0"), ["direct1", "direct2"])]++packageDb :: SourcePackages+packageDb =+ [+ ("direct1", allDep "transitive1 >=1.0" [+ ([1, 8, 1], []),+ ([1, 9, 1], []),+ ([2, 0, 1], [])+ ]),+ ("direct2", [+ ([1, 7, 1], []),+ ([1, 8, 1], []),+ ([1, 9, 1], []),+ ([1, 9, 2], []),+ ([2, 0, 1], [])+ ]),+ ("transitive1", [+ ([1, 0, 1], [])+ ])+ ]++ghcPackages :: GhcPackages+ghcPackages = GhcPackages {installed = [], available = packageDb}++state :: ProjectStateProto+state =+ ProjectStateProto {+ bounds = [+ ("local1", [+ ("direct1", [[2, 0, 1], [2, 1]]),+ ("direct2", [[2, 0, 1], [2, 1]])+ ])+ ],+ versions = [+ ("lower", [+ ("direct1", [2, 0, 1]),+ ("direct2", [2, 0, 1])+ ])+ ],+ overrides = [+ ("lower", [+ ("direct1", "direct1-2.0.1"),+ ("direct2", "direct2-2.0.1")+ ])+ ],+ initial = [+ ("lower", [+ ("direct1", [2, 0, 1]),+ ("direct2", [2, 0, 1])+ ])+ ],+ resolving = False+ }++build :: Versions -> M BuildStatus+build = \case+ [("direct1", [1, 9, 1]), ("direct2", [2, 0, 1]), ("transitive1", [1, 0, 1])] -> pure Success+ [("direct1", [1, 8, 1]), ("direct2", [2, 0, 1]), ("transitive1", [1, 0, 1])] -> pure Success+ [("direct1", [1, 8, 1]), ("direct2", [1, 9, 1]), ("transitive1", [1, 0, 1])] -> pure Failure+ [("direct1", [1, 8, 1]), ("direct2", [1, 9, 2]), ("transitive1", [1, 0, 1])] -> pure Success+ [("direct1", [1, 8, 1]), ("direct2", [1, 8, 1]), ("transitive1", [1, 0, 1])] -> pure Failure+ versions -> throwM (Fatal [exon|Unexpected build plan: #{showP versions}|])++stateFileTarget :: Text+stateFileTarget =+ [exon|{+ bounds = {+ local1 = {+ direct1 = {+ lower = "1.8.1";+ upper = "2.1";+ };+ direct2 = {+ lower = "1.9.2";+ upper = "2.1";+ };+ };+ };+ versions = {+ lower = {+ direct1 = "1.8.1";+ direct2 = "1.9.2";+ };+ };+ initial = {+ lower = {+ direct1 = "2.0.1";+ direct2 = "2.0.1";+ };+ };+ overrides = {+ lower = {+ direct1 = {+ version = "1.8.1";+ hash = "direct1-1.8.1";+ };+ direct2 = {+ version = "1.9.2";+ hash = "direct2-1.9.2";+ };+ transitive1 = {+ version = "1.0.1";+ hash = "transitive1-1.0.1";+ };+ };+ };+ resolving = false;+}+|]++-- | Goals for these deps:+--+-- - @direct1@ has two lower majors and all of them succeed, resulting in the lowest major (1.8.1) to become the bound.+--+-- - @direct2@ has three lower majors, the second of which fails, resulting in the highest major 1.9 to be the last one+-- tested.+-- The first version 1.9.1 also fails, resulting in 1.9.2 to become the bound.+test_lowerOptimizeMutation :: UnitTest+test_lowerOptimizeMutation = do+ Result {stateFile} <- lowerTest params lowerOptimizeMain+ eqLines stateFileTarget (renderRootExpr stateFile)+ where+ params =+ (testParams False packages) {+ ghcPackages,+ state,+ build+ }
+ test/Hix/Test/Managed/LowerStabilize/MutationTest.hs view
@@ -0,0 +1,141 @@+module Hix.Test.Managed.LowerStabilize.MutationTest where++import Exon (exon)++import Hix.Data.Error (Error (Fatal))+import qualified Hix.Data.Overrides+import Hix.Data.Overrides (Override (Override))+import Hix.Data.Version (SourceHash (SourceHash), Versions)+import qualified Hix.Managed.Cabal.Data.Packages+import Hix.Managed.Cabal.Data.Packages (GhcPackages (GhcPackages))+import Hix.Managed.Cabal.Data.SourcePackage (SourcePackages)+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto, managedPackages)+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Data.ProjectStateProto+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto (ProjectStateProto))+import Hix.Managed.Data.StageState (BuildStatus (Failure, Success))+import Hix.Managed.Lower.Stabilize (lowerStabilizeMain)+import Hix.Monad (M, throwM)+import Hix.NixExpr (renderRootExpr)+import Hix.Pretty (showP)+import Hix.Test.Hedgehog (eqLines)+import Hix.Test.Managed.Run (TestParams (..), Result (..), testParams, lowerTest)+import Hix.Test.Utils (UnitTest)++packageDb :: SourcePackages+packageDb =+ [+ ("direct1", [+ ([1, 8, 1], []),+ ([1, 9, 1], []),+ ([2, 0, 1], [])+ ]),+ ("direct2", [+ ([1, 8, 1], []),+ ([1, 9, 1], []),+ ([2, 0, 1], [])+ ])+ ]++ghcPackages :: GhcPackages+ghcPackages = GhcPackages {installed = [], available = packageDb}++packages :: Packages ManagedPackageProto+packages =+ managedPackages [(("local1", "1.0"), ["direct1", "direct2"])]++state :: ProjectStateProto+state =+ ProjectStateProto {+ bounds = [+ ("local1", [+ ("direct1", [[1, 8, 1], [2, 1]]),+ ("direct2", [[1, 8, 1], [2, 1]])+ ])+ ],+ versions = [+ ("lower", [+ ("direct1", [1, 8, 1]),+ ("direct2", [1, 8, 1])+ ])+ ],+ overrides = [+ ("lower", [+ ("direct1", Override {version = [1, 8, 1], hash = SourceHash "direct1-1.8.1"}),+ ("direct2", Override {version = [1, 8, 1], hash = SourceHash "direct2-1.8.1"})+ ])+ ],+ initial = [+ ("lower", [+ ("direct1", [2, 0, 1]),+ ("direct2", [2, 0, 1])+ ])+ ],+ resolving = False+ }++build :: Versions -> M BuildStatus+build = \case+ [("direct1", [2, 0, 1]), ("direct2", [2, 0, 1])] -> pure Success+ [("direct1", [1, 8, 1]), ("direct2", [1, 8, 1])] -> pure Failure+ [("direct1", [1, 8, 1]), ("direct2", [2, 0, 1])] -> pure Failure+ [("direct1", [1, 9, 1]), ("direct2", [2, 0, 1])] -> pure Success+ [("direct1", [1, 9, 1]), ("direct2", [1, 8, 1])] -> pure Failure+ [("direct1", [1, 9, 1]), ("direct2", [1, 9, 1])] -> pure Success+ [] -> throwM (Fatal "Build with no overrides")+ versions -> throwM (Fatal [exon|Unexpected build plan: #{showP versions}|])++stateFileTarget :: Text+stateFileTarget =+ [exon|{+ bounds = {+ local1 = {+ direct1 = {+ lower = "1.9.1";+ upper = "2.1";+ };+ direct2 = {+ lower = "1.9.1";+ upper = "2.1";+ };+ };+ };+ versions = {+ lower = {+ direct1 = "1.9.1";+ direct2 = "1.9.1";+ };+ };+ initial = {+ lower = {+ direct1 = "2.0.1";+ direct2 = "2.0.1";+ };+ };+ overrides = {+ lower = {+ direct1 = {+ version = "1.9.1";+ hash = "direct1-1.9.1";+ };+ direct2 = {+ version = "1.9.1";+ hash = "direct2-1.9.1";+ };+ };+ };+ resolving = false;+}+|]++test_lowerStabilizeMutation :: UnitTest+test_lowerStabilizeMutation = do+ Result {stateFile} <- lowerTest params lowerStabilizeMain+ eqLines stateFileTarget (renderRootExpr stateFile)+ where+ params =+ (testParams False packages) {+ ghcPackages,+ state,+ build+ }
+ test/Hix/Test/Managed/ProjectContextProtoTest.hs view
@@ -0,0 +1,287 @@+module Hix.Test.Managed.ProjectContextProtoTest where++import Data.Aeson (eitherDecodeStrict')+import Distribution.Version (earlierVersion, intersectVersionRanges, majorBoundVersion, orLaterVersion, thisVersion)+import Exon (exon)+import Hedgehog (evalEither, (===))+import Path (absdir)++import qualified Hix.Data.Dep+import Hix.Data.Dep (Dep (Dep), mkDep)+import Hix.Data.EnvName (EnvName)+import Hix.Data.Version (range0)+import Hix.Managed.Cabal.Data.Config (GhcDb (GhcDbSystem), GhcPath (GhcPath))+import qualified Hix.Managed.Data.EnvConfig+import Hix.Managed.Data.EnvConfig (EnvConfig (EnvConfig))+import qualified Hix.Managed.Data.EnvContext+import Hix.Managed.Data.EnvContext (EnvContext (EnvContext), EnvDeps (EnvDeps))+import qualified Hix.Managed.Data.ManagedPackage+import Hix.Managed.Data.ManagedPackage (ManagedPackage (ManagedPackage))+import qualified Hix.Managed.Data.ManagedPackageProto+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto (ManagedPackageProto))+import Hix.Managed.Data.Packages (Packages)+import qualified Hix.Managed.Data.ProjectContext+import Hix.Managed.Data.ProjectContext (ProjectContext (ProjectContext))+import qualified Hix.Managed.Data.ProjectContextProto+import Hix.Managed.Data.ProjectContextProto (ProjectContextProto (ProjectContextProto))+import qualified Hix.Managed.Data.ProjectState+import Hix.Managed.Data.ProjectState (ProjectState (ProjectState))+import qualified Hix.Managed.Data.ProjectStateProto+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto (ProjectStateProto))+import Hix.Managed.Data.Targets (unsafeTargets)+import qualified Hix.Managed.ProjectContextProto as ProjectContextProto+import Hix.Test.Hedgehog (assertRight)+import Hix.Test.Utils (UnitTest, runMTest)++json :: ByteString+json =+ [exon|{+ "packages": {+ "local1": {+ "name": "local1",+ "version": "1.2.1",+ "deps": [+ "direct1 ^>=2.0",+ {+ "name": "direct2",+ "version": "<1.5"+ },+ "direct3",+ "direct4:{internal,external} ==13.23",+ "direct5 >=5.0 && <5.1"+ ]+ },+ "local2": {+ "name": "local2",+ "version": "1.1.1",+ "deps": [+ "local1"+ ]+ },+ "local3": {+ "name": "local3",+ "version": "1.1.1",+ "deps": []+ },+ "local4": {+ "name": "local4",+ "version": "1.1.1",+ "deps": [+ "local2",+ "direct1",+ "direct2"+ ]+ },+ "local5": {+ "name": "local5",+ "version": "1.1.1",+ "deps": [+ "local4",+ "local3"+ ]+ }+ },+ "state": {+ "bounds": {+ "local1": {+ "direct1": {+ "lower": null,+ "upper": "2.3"+ },+ "direct2": {+ "upper": "1.5"+ }+ }+ }+ },+ "solverBounds": {+ "direct1": ">=2.0.2"+ },+ "envs": {+ "lower-main": {+ "targets": ["local1", "local2"],+ "ghc": "/ghc"+ },+ "lower-special": {+ "targets": ["local3", "local4"],+ "ghc": "/ghc"+ }+ }+ }|]++packages :: Packages ManagedPackageProto+packages =+ [+ ("local1", ManagedPackageProto {+ name = "local1",+ version = "1.2.1",+ deps = [+ mkDep "direct1" (majorBoundVersion [2, 0]),+ mkDep "direct2" (earlierVersion [1, 5]),+ mkDep "direct3" range0,+ Dep {+ package = "direct4",+ version = thisVersion [13, 23]+ },+ mkDep "direct5" (intersectVersionRanges (orLaterVersion [5, 0]) (earlierVersion [5, 1]))+ ]+ }),+ ("local2", ManagedPackageProto {+ name = "local2",+ version = "1.1.1",+ deps = ["local1"]+ }),+ ("local3", ManagedPackageProto {+ name = "local3",+ version = "1.1.1",+ deps = []+ }),+ ("local4", ManagedPackageProto {+ name = "local4",+ version = "1.1.1",+ deps = ["local2", "direct1", "direct2"]+ }),+ ("local5", ManagedPackageProto {+ name = "local5",+ version = "1.1.1",+ deps = ["local4", "local3"]+ })+ ]++ghc :: GhcDb+ghc =+ GhcDbSystem (Just (GhcPath [absdir|/ghc|]))++targetProto :: ProjectContextProto+targetProto =+ ProjectContextProto {+ packages,+ state = ProjectStateProto {+ bounds = [("local1", [("direct1", "<2.3"), ("direct2", "<1.5")])],+ versions = [],+ overrides = mempty,+ initial = mempty,+ resolving = False+ },+ envs = [+ ("lower-main", EnvConfig {targets = ["local1", "local2"], ghc}),+ ("lower-special", EnvConfig {targets = ["local3", "local4"], ghc})+ ],+ buildOutputsPrefix = Nothing+ }++targetEnvs :: NonEmpty (Either EnvName EnvContext)+targetEnvs =+ [+ Right EnvContext {+ env = "lower-main",+ ghc,+ targets = unsafeTargets ["local1", "local2"],+ deps = EnvDeps {mutable = ["direct1", "direct2", "direct3", "direct4", "direct5"], local = []},+ query = ["direct1", "direct2", "direct3", "direct4", "direct5"],+ solverBounds = mempty+ },+ Right EnvContext {+ env = "lower-special",+ ghc,+ targets = unsafeTargets ["local3", "local4"],+ deps = EnvDeps {mutable = ["direct1", "direct2"], local = ["local2"]},+ query = ["direct1", "direct2"],+ solverBounds = mempty+ }+ ]++targetProject :: ProjectContext+targetProject =+ ProjectContext {+ build = def,+ packages = [+ ("local1", ManagedPackage {+ package = "local1",+ version = [1, 2, 1],+ local = [],+ mutable = [+ ("direct1", "^>=2.0"),+ ("direct2", "<1.5"),+ ("direct3", ">=0"),+ ("direct4", "==13.23"),+ ("direct5", ">=5.0 && <5.1")+ ]+ }),+ ("local2", ManagedPackage {+ package = "local2",+ version = [1, 1, 1],+ local = [("local1", ">=0")],+ mutable = []+ }),+ ("local3", ManagedPackage {+ package = "local3",+ version = [1, 1, 1],+ local = [],+ mutable = []+ }),+ ("local4", ManagedPackage {+ package = "local4",+ version = [1, 1, 1],+ local = [("local2", ">=0")],+ mutable = [("direct1", ">=0"), ("direct2", ">=0")]+ }),+ ("local5", ManagedPackage {+ package = "local5",+ version = [1, 1, 1],+ local = [("local3", ">=0"), ("local4", ">=0")],+ mutable = []+ })+ ],+ state = ProjectState {+ bounds = [+ ("local1", [+ ("direct1", "<2.3"),+ ("direct2", "<1.5"),+ ("direct3", ">=0"),+ ("direct4", ">=0"),+ ("direct5", ">=0")+ ]),+ ("local2", []),+ ("local3", []),+ ("local4", [("direct1", ">=0"), ("direct2", ">=0")]),+ ("local5", [])+ ],+ versions = [+ ("lower-main", [+ ("direct1", Nothing),+ ("direct2", Nothing),+ ("direct3", Nothing),+ ("direct4", Nothing),+ ("direct5", Nothing)+ ]),+ ("lower-special", [+ ("direct1", Nothing),+ ("direct2", Nothing)+ ])+ ],+ overrides = [],+ initial = [+ ("lower-main", [+ ("direct1", Nothing),+ ("direct2", Nothing),+ ("direct3", Nothing),+ ("direct4", Nothing),+ ("direct5", Nothing)+ ]),+ ("lower-special", [+ ("direct1", Nothing),+ ("direct2", Nothing)+ ])+ ],+ resolving = False+ },+ envs = targetEnvs+ }++test_parseProjectContextProto :: UnitTest+test_parseProjectContextProto = do+ assertRight targetProto (eitherDecodeStrict' json)+ project <- evalEither =<< liftIO do+ runMTest False (ProjectContextProto.validate def targetProto)+ targetProject === project
+ test/Hix/Test/Managed/Run.hs view
@@ -0,0 +1,130 @@+module Hix.Test.Managed.Run where++import Data.IORef (readIORef)+import Hedgehog (TestT, evalEither, evalMaybe)++import Hix.Class.Map (nFromList, nKeys)+import Hix.Data.EnvName (EnvName)+import Hix.Data.Monad (M)+import Hix.Data.NixExpr (Expr)+import Hix.Data.Options (ProjectOptions)+import Hix.Data.PackageName (LocalPackage)+import Hix.Data.Version (Versions)+import Hix.Managed.Cabal.Changes (SolverPlan)+import Hix.Managed.Cabal.Data.Config (GhcDb (GhcDbSynthetic))+import qualified Hix.Managed.Cabal.Data.Packages+import Hix.Managed.Cabal.Data.Packages (GhcPackages (GhcPackages))+import Hix.Managed.Data.Constraints (EnvConstraints)+import qualified Hix.Managed.Data.EnvConfig+import Hix.Managed.Data.EnvConfig (EnvConfig (EnvConfig))+import Hix.Managed.Data.ManagedPackageProto (ManagedPackageProto)+import Hix.Managed.Data.Packages (Packages)+import Hix.Managed.Data.ProjectContext (ProjectContext)+import qualified Hix.Managed.Data.ProjectContextProto as ProjectContextProto+import Hix.Managed.Data.ProjectContextProto (ProjectContextProto (..))+import Hix.Managed.Data.ProjectResult (ProjectResult)+import Hix.Managed.Data.ProjectStateProto (ProjectStateProto)+import Hix.Managed.Data.StageState (BuildStatus (Failure))+import qualified Hix.Managed.Handlers.Build as BuildHandlers+import Hix.Managed.Handlers.Build (BuildHandlers (..))+import qualified Hix.Managed.Handlers.Build.Test as BuildHandlers+import qualified Hix.Managed.Handlers.Report.Prod as ReportHandlers+import Hix.Managed.ProjectContext (withProjectContext)+import Hix.Test.Utils (runMLogTest, runMTest)++data TestParams =+ TestParams {+ envs :: [(EnvName, [LocalPackage])],+ cabalLog :: Bool,+ log :: Bool,+ debug :: Bool,+ packages :: Packages ManagedPackageProto,+ ghcPackages :: GhcPackages,+ state :: ProjectStateProto,+ projectOptions :: ProjectOptions,+ build :: Versions -> M BuildStatus+ }++testParams ::+ Bool ->+ Packages ManagedPackageProto ->+ TestParams+testParams debug packages =+ TestParams {+ envs = [],+ cabalLog = False,+ log = False,+ debug,+ packages,+ ghcPackages = GhcPackages {installed = [], available = []},+ state = def,+ projectOptions = def,+ build = const (pure Failure)+ }++data Result =+ Result {+ stateFile :: Expr,+ cabalLog :: [(EnvConstraints, Maybe SolverPlan)],+ log :: [Text]+ }++testProjectContext ::+ EnvName ->+ TestParams ->+ ProjectContextProto+testProjectContext defaultEnvName params =+ ProjectContextProto {+ ProjectContextProto.packages = params.packages,+ state = params.state,+ envs = nFromList (second mkEnv <$> maybe defaultEnv toList (nonEmpty params.envs)),+ buildOutputsPrefix = Nothing+ }+ where+ mkEnv targets = EnvConfig {targets, ghc = GhcDbSynthetic params.ghcPackages}++ defaultEnv = [(defaultEnvName, nKeys params.packages)]++managedTest ::+ EnvName ->+ TestParams ->+ (BuildHandlers -> ProjectContext -> M ProjectResult) ->+ TestT IO Result+managedTest defaultEnvName params main =+ withFrozenCallStack do+ (handlers0, stateFileRef, _) <- BuildHandlers.handlersUnitTest params.ghcPackages params.build+ (cabalRef, handlers1) <-+ if params.cabalLog+ then first Just <$> BuildHandlers.logCabal handlers0+ else pure (Nothing, handlers0)+ let+ handlers =+ if params.log+ then handlers1 {report = ReportHandlers.handlersProd}+ else handlers1+ (log, result) <- liftIO (runner (withProjectContext handlers params.projectOptions context (main handlers)))+ evalEither result+ stateFile <- evalMaybe . head =<< liftIO (readIORef stateFileRef)+ cabalLog <- fold <$> for cabalRef \ ref -> reverse <$> liftIO (readIORef ref)+ pure Result {..}+ where+ runner | params.log = runMLogTest params.debug (not params.debug)+ | otherwise = fmap ([],) . runMTest params.debug++ context = testProjectContext defaultEnvName params++lowerTest ::+ TestParams ->+ (BuildHandlers -> ProjectContext -> M ProjectResult) ->+ TestT IO Result+lowerTest params main =+ withFrozenCallStack do+ managedTest "lower" params main++bumpTest ::+ TestParams ->+ (BuildHandlers -> ProjectContext -> M ProjectResult) ->+ TestT IO Result+bumpTest params main =+ withFrozenCallStack do+ managedTest "latest" params main
+ test/Hix/Test/Managed/UnsafeIsString.hs view
@@ -0,0 +1,73 @@+{-# options_ghc -Wno-orphans #-}++module Hix.Test.Managed.UnsafeIsString where++import Distribution.Version (VersionRange)+import Exon (exon)+import GHC.Exts (IsList (Item, fromList, toList))++import Hix.CabalParsec (unsafeParsec)+import qualified Hix.Data.Dep+import qualified Hix.Data.Dep as Dep+import Hix.Data.Dep (Dep (Dep))+import qualified Hix.Data.Overrides+import Hix.Data.Overrides (Override (Override))+import qualified Hix.Data.PackageId as PackageId+import Hix.Data.PackageId (PackageId (PackageId))+import Hix.Data.PackageName (PackageName)+import Hix.Data.Version (SourceHash (SourceHash), Version)+import qualified Hix.Data.VersionBounds+import Hix.Data.VersionBounds (VersionBounds (VersionBounds), fromLower, unsafeVersionBoundsFromRange, versionBounds)+import Hix.Managed.Data.Constraints (MutationConstraints (mutation))+import Hix.Managed.Data.Mutable (MutableDep, unsafeMutableDep)+import qualified Hix.Managed.Data.MutableId+import Hix.Managed.Data.MutableId (MutableId (MutableId))+import Hix.Pretty (showP)++instance IsString Version where+ fromString = unsafeParsec++instance IsString VersionRange where+ fromString = unsafeParsec++instance IsString VersionBounds where+ fromString =+ unsafeVersionBoundsFromRange . fromString++instance IsList VersionBounds where+ type Item VersionBounds = Version++ fromList = \case+ [] -> VersionBounds {lower = Nothing, upper = Nothing}+ [lower] -> fromLower lower+ [lower, upper] -> versionBounds lower upper+ l -> error [exon|IsList VersionBounds: not two elements or fewer: #{show l}|]++ toList VersionBounds {lower, upper} = maybeToList lower ++ maybeToList upper++instance IsString MutableDep where+ fromString = unsafeMutableDep . fromString++instance IsString PackageId where+ fromString = PackageId.fromCabal . unsafeParsec++instance IsString MutableId where+ fromString s =+ MutableId {name = unsafeMutableDep name, version}+ where+ PackageId {name, version} = fromString s++instance IsString Dep where+ fromString = Dep.fromCabal . unsafeParsec++instance IsString Override where+ fromString s =+ Override {hash = SourceHash (showP package), version = package.version}+ where+ package = fromString @PackageId s++instance IsString (PackageName, MutationConstraints) where+ fromString s =+ (package, mempty {mutation = unsafeVersionBoundsFromRange version})+ where+ Dep {package, version} = fromString s
+ test/Hix/Test/ManagedTest.hs view
@@ -0,0 +1,37 @@+module Hix.Test.ManagedTest where++import Test.Tasty (TestTree, testGroup)++import Hix.Test.Managed.BuildOutputTest (test_buildOutput)+import Hix.Test.Managed.Bump.CandidatesTest (test_candidatesBump)+import Hix.Test.Managed.Bump.MutationTest (test_bumpMutation)+import Hix.Test.Managed.DiffTest (test_diff)+import Hix.Test.Managed.LowerAuto.MutationOptimizeTest (test_lowerAutoMutationOptimize)+import Hix.Test.Managed.LowerAuto.MutationStabilizeTest (test_lowerAutoMutationStabilize)+import Hix.Test.Managed.LowerInit.MutationTest (test_lowerInitMutation)+import Hix.Test.Managed.LowerNativeTest ()+import Hix.Test.Managed.LowerOptimize.CandidatesTest (test_candidatesOptimize)+import Hix.Test.Managed.LowerOptimize.MutationTest (test_lowerOptimizeMutation)+import Hix.Test.Managed.LowerStabilize.MutationTest (test_lowerStabilizeMutation)+import Hix.Test.Managed.ProjectContextProtoTest (test_parseProjectContextProto)+import Hix.Test.Utils (unitTest)++test_managed :: TestTree+test_managed =+ testGroup "managed" [+ testGroup "candidates" [+ unitTest "bump" test_candidatesBump,+ unitTest "optimize" test_candidatesOptimize+ ],+ testGroup "mutation build" [+ test_bumpMutation,+ unitTest "lower.init" test_lowerInitMutation,+ unitTest "lower.optimize" test_lowerOptimizeMutation,+ unitTest "lower.stabilize" test_lowerStabilizeMutation,+ unitTest "lower.auto stabilize" test_lowerAutoMutationStabilize,+ test_lowerAutoMutationOptimize+ ],+ unitTest "parse ProjectContext" test_parseProjectContextProto,+ test_buildOutput,+ test_diff+ ]
test/Hix/Test/NewTest.hs view
@@ -1,7 +1,7 @@ module Hix.Test.NewTest where import Exon (exon)-import Hedgehog (TestT, evalEither, (===))+import Hedgehog (evalEither, (===)) import Path (absdir, relfile) import qualified Hix.Data.NewProjectConfig@@ -9,6 +9,7 @@ import Hix.Data.ProjectFile (ProjectFile (ProjectFile)) import Hix.Monad (runM) import Hix.New (license, newProjectFiles)+import Hix.Test.Utils (UnitTest) conf :: NewProjectConfig conf =@@ -47,7 +48,7 @@ test = { enable = true; dependencies = [- "hedgehog >= 1.1 && < 1.3"+ "hedgehog >= 1.1 && < 1.5" "tasty ^>= 1.4" "tasty-hedgehog >= 1.3 && < 1.5" ];@@ -119,7 +120,7 @@ ProjectFile [relfile|test/Spider/Test/NameTest.hs|] nameTestModule ] -test_new :: TestT IO ()+test_new :: UnitTest test_new = do res <- evalEither =<< liftIO (runM [absdir|/project|] (newProjectFiles conf)) target === res
test/Hix/Test/PreprocTest.hs view
@@ -8,10 +8,12 @@ Library (libBuildInfo), ) import Exon (exon)-import Hedgehog (TestT, evalMaybe, (===))+import Hedgehog (evalMaybe, (===))+import Path (absfile)+ import Hix.Preproc (fromCabal, preprocessModule) import Hix.Test.CabalFile (testPackage, testPackageNoPrelude)-import Path (absfile)+import Hix.Test.Utils (UnitTest) pragmas :: Text pragmas =@@ -28,7 +30,7 @@ HasCallStack => ByteString -> Text ->- TestT IO ()+ UnitTest preprocTestNoPrelude module_ target = withFrozenCallStack do pkg <- liftIO testPackageNoPrelude@@ -40,7 +42,7 @@ HasCallStack => ByteString -> Text ->- TestT IO ()+ UnitTest preprocTest module_ target = withFrozenCallStack do pkg <- liftIO testPackage@@ -85,7 +87,7 @@ f = 1 |] -test_preprocInsertPrelude :: TestT IO ()+test_preprocInsertPrelude :: UnitTest test_preprocInsertPrelude = preprocTest moduleInsert targetInsert @@ -134,7 +136,7 @@ f = 1 |] -test_preprocReplacePrelude :: TestT IO ()+test_preprocReplacePrelude :: UnitTest test_preprocReplacePrelude = preprocTest moduleReplace targetReplace @@ -159,7 +161,7 @@ f = 1 |] -test_preprocSingleLineModule :: TestT IO ()+test_preprocSingleLineModule :: UnitTest test_preprocSingleLineModule = preprocTest moduleSingleLineModule targetSingleLineModule @@ -184,7 +186,7 @@ f = 1 |] -test_preprocSelfExport :: TestT IO ()+test_preprocSelfExport :: UnitTest test_preprocSelfExport = preprocTest moduleSelfExport targetSelfExport @@ -217,7 +219,7 @@ f = 1 |] -test_preprocSelfExport2 :: TestT IO ()+test_preprocSelfExport2 :: UnitTest test_preprocSelfExport2 = preprocTest moduleSelfExport2 targetSelfExport2 @@ -235,7 +237,7 @@ import System.Exit (exitSuccess) |] -test_preprocNoPrelude :: TestT IO ()+test_preprocNoPrelude :: UnitTest test_preprocNoPrelude = preprocTestNoPrelude moduleNoPrelude targetNoPrelude @@ -258,6 +260,6 @@ {-# line 4 "/foo/bar/Foo.hs" #-} |] -test_preprocPreludePrefix :: TestT IO ()+test_preprocPreludePrefix :: UnitTest test_preprocPreludePrefix = preprocTest modulePreludePrefix targetPreludePrefix
+ test/Hix/Test/Utils.hs view
@@ -0,0 +1,42 @@+module Hix.Test.Utils where++import Hedgehog (TestT, property, test, withTests)+import Path (Abs, Dir, Path, absdir)+import Test.Tasty (TestName, TestTree)+import Test.Tasty.Hedgehog (testProperty)++import qualified Hix.Console as Console+import Hix.Data.Error (Error)+import Hix.Data.GlobalOptions (GlobalOptions (debug, quiet, verbose), defaultGlobalOptions)+import Hix.Monad (M, runMLoggerWith, runMWith, withLogIORef)+import Hix.Test.Managed.UnsafeIsString ()++type UnitTest = TestT IO ()++unitTest ::+ HasCallStack =>+ TestName ->+ TestT IO () ->+ TestTree+unitTest desc t =+ withFrozenCallStack do+ testProperty desc (withTests 1 (property (test t)))++testRoot :: Path Abs Dir+testRoot = [absdir|/project|]++runMTest :: Bool -> M a -> IO (Either Error a)+runMTest debug =+ runMWith (defaultGlobalOptions testRoot) {verbose = debug, debug, quiet = not debug}++runMLogTest :: Bool -> Bool -> M a -> IO ([Text], Either Error a)+runMLogTest debug onlyRef ma =+ withLogIORef \ logger -> do+ let+ fullLogger | onlyRef = logger+ | otherwise = \ level msg -> do+ logger level msg+ Console.err msg+ runMLoggerWith fullLogger opts ma+ where+ opts = (defaultGlobalOptions testRoot) {verbose = debug, debug}
+ test/Hix/Test/VersionTest.hs view
@@ -0,0 +1,51 @@+module Hix.Test.VersionTest where++import Distribution.Version (earlierVersion, intersectVersionRanges, laterVersion, orLaterVersion, unionVersionRanges)+import Hedgehog ((===))+import Test.Tasty (TestTree, testGroup)++import qualified Hix.Data.Version+import Hix.Data.Version (Major (Major))+import Hix.Test.Utils (UnitTest, unitTest)+import Hix.Version (exclusiveUpperVersion, lastMajorBefore, lowerVersion, majorsBefore, versionsFrom)++test_versionList :: UnitTest+test_versionList =+ intersectVersionRanges (orLaterVersion [1, 4]) (earlierVersion [2, 3]) === [[1, 4], [2, 3]]++test_rangeBounds :: UnitTest+test_rangeBounds = do+ Just [1, 1] === lowerVersion range1+ Just [2, 3] === exclusiveUpperVersion range2+ where+ range1 = intersectVersionRanges (laterVersion [0, 4]) (unionVersionRanges [[1, 1], [1, 3]] range2)+ range2 = [[2, 2], [2, 3]]++test_majors :: UnitTest+test_majors = do+ [[2, 2]] === lastMajorBefore 2 3 versions+ target1 === majorsBefore 2 3 versions+ target2 === versionsFrom [2, 1, 2] versions+ drop 1 target2 === versionsFrom [2, 1, 3] versions+ where+ target1 =+ [+ Major {prefix = [2, 1], versions = [[2, 1, 1], [2, 1, 2]]},+ Major {prefix = [2, 2], versions = [[2, 2]]}+ ]+ target2 =+ [+ Major {prefix = [2, 1], versions = [[2, 1, 2]]},+ Major {prefix = [2, 2], versions = [[2, 2]]},+ Major {prefix = [2, 3], versions = [[2, 3]]}+ ]++ versions = [[2, 1, 1], [2, 1, 2], [2, 2], [2, 3]]++test_version :: TestTree+test_version =+ testGroup "version" [+ unitTest "fromList" test_versionList,+ unitTest "bounds" test_rangeBounds,+ unitTest "majors" test_majors+ ]
test/Main.hs view
@@ -1,9 +1,11 @@ module Main where -import Hedgehog (TestT, property, test, withTests)+import Hix () import Hix.Test.BootstrapTest (test_bootstrap)+import Hix.Test.BoundsTest (test_bounds) import Hix.Test.CabalTest (test_cabal) import Hix.Test.GhciTest (test_componentEnv, test_ghcid, test_moduleName)+import Hix.Test.ManagedTest (test_managed) import Hix.Test.NewTest (test_new) import Hix.Test.PreprocTest ( test_preprocInsertPrelude,@@ -14,17 +16,9 @@ test_preprocSelfExport2, test_preprocSingleLineModule, )-import Test.Tasty (TestName, TestTree, defaultMain, testGroup)-import Test.Tasty.Hedgehog (testProperty)--unitTest ::- HasCallStack =>- TestName ->- TestT IO () ->- TestTree-unitTest desc t =- withFrozenCallStack do- testProperty desc (withTests 1 (property (test t)))+import Hix.Test.Utils (unitTest)+import Hix.Test.VersionTest (test_version)+import Test.Tasty (TestTree, defaultMain, testGroup) tests :: TestTree tests =@@ -43,7 +37,10 @@ unitTest "extract module name from path" test_moduleName, unitTest "generate a project" test_new, unitTest "bootstrap a project" test_bootstrap- ]+ ],+ test_version,+ test_bounds,+ test_managed ] main :: IO ()