Skip to content

Commit

Permalink
Add the freeze --lock flag to promote a freeze f ile to a lock file
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurentRDC committed Feb 8, 2025
1 parent 595d023 commit 45a13b1
Showing 1 changed file with 41 additions and 9 deletions.
50 changes: 41 additions & 9 deletions cabal-install/src/Distribution/Client/CmdFreeze.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
module Distribution.Client.CmdFreeze
( freezeCommand
, freezeAction
, ClientFreezeFlags(..),
) where

import Distribution.Client.Compat.Prelude
Expand Down Expand Up @@ -38,7 +39,7 @@ import Distribution.Solver.Types.ConstraintSource
import Distribution.Solver.Types.PackageConstraint
( PackageProperty (..)
)

import Distribution.Solver.Types.Settings (OnlyConstrained(..))
import Distribution.Client.Setup
( CommonSetupFlags (setupVerbosity)
, ConfigFlags (..)
Expand All @@ -59,6 +60,7 @@ import Distribution.Simple.Utils
, notice
, wrapText
)
import Distribution.Simple.Setup (trueArg)
import Distribution.Verbosity
( normal
)
Expand All @@ -74,10 +76,16 @@ import qualified Data.Map as Map
import Distribution.Client.Errors
import Distribution.Simple.Command
( CommandUI (..)
, OptionField
, ShowOrParseArgs
, usageAlternatives
, option
, usageAlternatives
)

freezeCommand :: CommandUI (NixStyleFlags ())
newtype ClientFreezeFlags = ClientFreezeFlags {lockDependencies :: Flag Bool}

freezeCommand :: CommandUI (NixStyleFlags ClientFreezeFlags)
freezeCommand =
CommandUI
{ commandName = "v2-freeze"
Expand All @@ -99,7 +107,10 @@ freezeCommand =
++ "one approach is to try variations using 'v2-build --dry-run' with "
++ "solver flags such as '--constraint=\"pkg < 1.2\"' and once you have "
++ "a satisfactory solution to freeze it using the 'v2-freeze' command "
++ "with the same set of flags."
++ "with the same set of flags.\n\n"
++ "By default, a freeze file is a set of constaints; unconstrained packages "
++ "can still be included in the build plan. If you wish to restrict dependencies "
++ "to those included in the freeze file, use the '--lock' flag."
, commandNotes = Just $ \pname ->
"Examples:\n"
++ " "
Expand All @@ -108,23 +119,38 @@ freezeCommand =
++ " Freeze the configuration of the current project\n\n"
++ " "
++ pname
++ " v2-freeze --lock\n"
++ " Freeze the configuration of the current project and only allow frozen dependencies in future builds\n\n"
++ " "
++ pname
++ " v2-build --dry-run --constraint=\"aeson < 1\"\n"
++ " Check what a solution with the given constraints would look like\n"
++ " "
++ pname
++ " v2-freeze --constraint=\"aeson < 1\"\n"
++ " Freeze a solution using the given constraints\n"
, commandDefaultFlags = defaultNixStyleFlags ()
, commandOptions = nixStyleOptions (const [])
, commandDefaultFlags = defaultNixStyleFlags (ClientFreezeFlags (Flag False))
, commandOptions = nixStyleOptions freezeOptions
}

freezeOptions :: ShowOrParseArgs -> [OptionField ClientFreezeFlags]
freezeOptions _ =
[ option
[]
["lock"]
"Promote the resulting freeze file to a lock file"
lockDependencies
(\v f -> f{lockDependencies = v})
trueArg
]

-- | To a first approximation, the @freeze@ command runs the first phase of
-- the @build@ command where we bring the install plan up to date, and then
-- based on the install plan we write out a @cabal.project.freeze@ config file.
--
-- For more details on how this works, see the module
-- "Distribution.Client.ProjectOrchestration"
freezeAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()
freezeAction :: NixStyleFlags ClientFreezeFlags -> [String] -> GlobalFlags -> IO ()
freezeAction flags@NixStyleFlags{..} extraArgs globalFlags = do
unless (null extraArgs) $
dieWithException verbosity $
Expand All @@ -148,7 +174,7 @@ freezeAction flags@NixStyleFlags{..} extraArgs globalFlags = do
localPackages
Nothing

let freezeConfig = projectFreezeConfig elaboratedPlan totalIndexState activeRepos
let freezeConfig = projectFreezeConfig extraFlags elaboratedPlan totalIndexState activeRepos
dryRun =
buildSettingDryRun buildSettings
|| buildSettingOnlyDownload buildSettings
Expand All @@ -170,24 +196,30 @@ freezeAction flags@NixStyleFlags{..} extraArgs globalFlags = do
-- | Given the install plan, produce a config value with constraints that
-- freezes the versions of packages used in the plan.
projectFreezeConfig
:: ElaboratedInstallPlan
:: ClientFreezeFlags
-> ElaboratedInstallPlan
-> TotalIndexState
-> ActiveRepos
-> ProjectConfig
projectFreezeConfig elaboratedPlan totalIndexState activeRepos0 =
projectFreezeConfig freezeFlags elaboratedPlan totalIndexState activeRepos0 =
mempty
{ projectConfigShared =
mempty
{ projectConfigConstraints =
concat (Map.elems (projectFreezeConstraints elaboratedPlan))
, projectConfigIndexState = Flag totalIndexState
, projectConfigActiveRepos = Flag activeRepos
, projectConfigOnlyConstrained = onlyConstrainedFlag freezeFlags
}
}
where
activeRepos :: ActiveRepos
activeRepos = filterSkippedActiveRepos activeRepos0

onlyConstrainedFlag :: ClientFreezeFlags -> Flag OnlyConstrained
onlyConstrainedFlag ClientFreezeFlags{lockDependencies=Flag True} = Flag OnlyConstrainedAll
onlyConstrainedFlag ClientFreezeFlags{lockDependencies=_} = NoFlag

-- | Given the install plan, produce solver constraints that will ensure the
-- solver picks the same solution again in future in different environments.
projectFreezeConstraints
Expand Down

0 comments on commit 45a13b1

Please sign in to comment.