packages feed

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 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 ()