{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE NoFieldSelectors #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
module Stack.Lock
( lockCachedWanted
, LockedLocation (..)
, Locked (..)
) where
import Data.Aeson.Types ( FromJSON (..), ToJSON, Value, (.=), object )
import Data.Aeson.WarningParser
( WithJSONWarnings (..), (..:), jsonSubWarnings
, jsonSubWarningsT, logJSONWarnings, withObjectWarnings
)
import Data.ByteString.Builder ( byteString )
import qualified Data.Map as Map
import qualified Data.Text as T
import qualified Data.Yaml as Yaml
import qualified RIO.NonEmpty as NE
import Path ( addExtension, parent )
import Path.IO ( doesFileExist )
import Stack.Prelude
import Stack.SourceMap ( snapToDepPackage )
import Stack.Types.Config.Exception ( ConfigPrettyException (..) )
import Stack.Types.LockFileBehavior ( LockFileBehavior (..) )
import Stack.Types.Runner ( HasRunner, lockFileBehaviorL, rslInLogL )
import Stack.Types.SourceMap ( DepPackage, SMWanted )
data LockPrettyException
= WritingLockFileError (Path Abs File) Locked
deriving Int -> LockPrettyException -> ShowS
[LockPrettyException] -> ShowS
LockPrettyException -> String
(Int -> LockPrettyException -> ShowS)
-> (LockPrettyException -> String)
-> ([LockPrettyException] -> ShowS)
-> Show LockPrettyException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LockPrettyException -> ShowS
showsPrec :: Int -> LockPrettyException -> ShowS
$cshow :: LockPrettyException -> String
show :: LockPrettyException -> String
$cshowList :: [LockPrettyException] -> ShowS
showList :: [LockPrettyException] -> ShowS
Show
instance Pretty LockPrettyException where
pretty :: LockPrettyException -> StyleDoc
pretty (WritingLockFileError Path Abs File
lockFile Locked
newLocked) =
StyleDoc
"[S-1353]"
StyleDoc -> StyleDoc -> StyleDoc
forall a. Semigroup a => a -> a -> a
<> StyleDoc
line
StyleDoc -> StyleDoc -> StyleDoc
forall a. Semigroup a => a -> a -> a
<> String -> StyleDoc
flow String
"Stack is configured to report an error on writing a lock file."
StyleDoc -> StyleDoc -> StyleDoc
forall a. Semigroup a => a -> a -> a
<> StyleDoc
blankLine
StyleDoc -> StyleDoc -> StyleDoc
forall a. Semigroup a => a -> a -> a
<> [StyleDoc] -> StyleDoc
fillSep
[ String -> StyleDoc
flow String
"Stack just tried to write the following lock file content to"
, Path Abs File -> StyleDoc
forall a. Pretty a => a -> StyleDoc
pretty Path Abs File
lockFile StyleDoc -> StyleDoc -> StyleDoc
forall a. Semigroup a => a -> a -> a
<> StyleDoc
":"
]
StyleDoc -> StyleDoc -> StyleDoc
forall a. Semigroup a => a -> a -> a
<> StyleDoc
blankLine
StyleDoc -> StyleDoc -> StyleDoc
forall a. Semigroup a => a -> a -> a
<> String -> StyleDoc
string String
newLocked'
where
newLocked' :: String
newLocked' = Text -> String
T.unpack (Text -> String) -> (ByteString -> Text) -> ByteString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OnDecodeError -> ByteString -> Text
decodeUtf8With OnDecodeError
lenientDecode (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ Locked -> ByteString
forall a. ToJSON a => a -> ByteString
Yaml.encode Locked
newLocked
instance Exception LockPrettyException
data LockedLocation a b = LockedLocation
{ forall a b. LockedLocation a b -> a
original :: a
, forall a b. LockedLocation a b -> b
completed :: b
}
deriving (LockedLocation a b -> LockedLocation a b -> Bool
(LockedLocation a b -> LockedLocation a b -> Bool)
-> (LockedLocation a b -> LockedLocation a b -> Bool)
-> Eq (LockedLocation a b)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall a b.
(Eq a, Eq b) =>
LockedLocation a b -> LockedLocation a b -> Bool
$c== :: forall a b.
(Eq a, Eq b) =>
LockedLocation a b -> LockedLocation a b -> Bool
== :: LockedLocation a b -> LockedLocation a b -> Bool
$c/= :: forall a b.
(Eq a, Eq b) =>
LockedLocation a b -> LockedLocation a b -> Bool
/= :: LockedLocation a b -> LockedLocation a b -> Bool
Eq, Int -> LockedLocation a b -> ShowS
[LockedLocation a b] -> ShowS
LockedLocation a b -> String
(Int -> LockedLocation a b -> ShowS)
-> (LockedLocation a b -> String)
-> ([LockedLocation a b] -> ShowS)
-> Show (LockedLocation a b)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall a b. (Show a, Show b) => Int -> LockedLocation a b -> ShowS
forall a b. (Show a, Show b) => [LockedLocation a b] -> ShowS
forall a b. (Show a, Show b) => LockedLocation a b -> String
$cshowsPrec :: forall a b. (Show a, Show b) => Int -> LockedLocation a b -> ShowS
showsPrec :: Int -> LockedLocation a b -> ShowS
$cshow :: forall a b. (Show a, Show b) => LockedLocation a b -> String
show :: LockedLocation a b -> String
$cshowList :: forall a b. (Show a, Show b) => [LockedLocation a b] -> ShowS
showList :: [LockedLocation a b] -> ShowS
Show)
instance (ToJSON a, ToJSON b) => ToJSON (LockedLocation a b) where
toJSON :: LockedLocation a b -> Value
toJSON LockedLocation a b
ll =
[Pair] -> Value
object [ Key
"original" Key -> a -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= LockedLocation a b
ll.original, Key
"completed" Key -> b -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= LockedLocation a b
ll.completed ]
instance ( FromJSON (WithJSONWarnings (Unresolved a))
, FromJSON (WithJSONWarnings (Unresolved b))
) =>
FromJSON (WithJSONWarnings (Unresolved (LockedLocation a b))) where
parseJSON :: Value
-> Parser (WithJSONWarnings (Unresolved (LockedLocation a b)))
parseJSON =
String
-> (Object -> WarningParser (Unresolved (LockedLocation a b)))
-> Value
-> Parser (WithJSONWarnings (Unresolved (LockedLocation a b)))
forall a.
String
-> (Object -> WarningParser a)
-> Value
-> Parser (WithJSONWarnings a)
withObjectWarnings String
"LockedLocation" ((Object -> WarningParser (Unresolved (LockedLocation a b)))
-> Value
-> Parser (WithJSONWarnings (Unresolved (LockedLocation a b))))
-> (Object -> WarningParser (Unresolved (LockedLocation a b)))
-> Value
-> Parser (WithJSONWarnings (Unresolved (LockedLocation a b)))
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
original <- WarningParser (WithJSONWarnings (Unresolved a))
-> WarningParser (Unresolved a)
forall a. WarningParser (WithJSONWarnings a) -> WarningParser a
jsonSubWarnings (WarningParser (WithJSONWarnings (Unresolved a))
-> WarningParser (Unresolved a))
-> WarningParser (WithJSONWarnings (Unresolved a))
-> WarningParser (Unresolved a)
forall a b. (a -> b) -> a -> b
$ Object
o Object -> Text -> WarningParser (WithJSONWarnings (Unresolved a))
forall a. FromJSON a => Object -> Text -> WarningParser a
..: Text
"original"
completed <- jsonSubWarnings $ o ..: "completed"
pure $ LockedLocation <$> original <*> completed
newtype SingleRPLI
= SingleRPLI { SingleRPLI -> RawPackageLocationImmutable
singleRPLI :: RawPackageLocationImmutable}
instance FromJSON (WithJSONWarnings (Unresolved SingleRPLI)) where
parseJSON :: Value -> Parser (WithJSONWarnings (Unresolved SingleRPLI))
parseJSON Value
v =
do
WithJSONWarnings unresolvedRPLIs ws <- Value
-> Parser
(WithJSONWarnings
(Unresolved (NonEmpty RawPackageLocationImmutable)))
forall a. FromJSON a => Value -> Parser a
parseJSON Value
v
let withWarnings Unresolved SingleRPLI
x = Unresolved SingleRPLI
-> [JSONWarning] -> WithJSONWarnings (Unresolved SingleRPLI)
forall a. a -> [JSONWarning] -> WithJSONWarnings a
WithJSONWarnings Unresolved SingleRPLI
x [JSONWarning]
ws
pure $ withWarnings $ SingleRPLI . NE.head <$> unresolvedRPLIs
data Locked = Locked
{ Locked -> [LockedLocation RawSnapshotLocation SnapshotLocation]
snapshotLocations :: [LockedLocation RawSnapshotLocation SnapshotLocation]
, Locked
-> [LockedLocation
RawPackageLocationImmutable PackageLocationImmutable]
pkgImmutableLocations :: [LockedLocation RawPackageLocationImmutable PackageLocationImmutable]
}
deriving (Locked -> Locked -> Bool
(Locked -> Locked -> Bool)
-> (Locked -> Locked -> Bool) -> Eq Locked
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Locked -> Locked -> Bool
== :: Locked -> Locked -> Bool
$c/= :: Locked -> Locked -> Bool
/= :: Locked -> Locked -> Bool
Eq, Int -> Locked -> ShowS
[Locked] -> ShowS
Locked -> String
(Int -> Locked -> ShowS)
-> (Locked -> String) -> ([Locked] -> ShowS) -> Show Locked
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Locked -> ShowS
showsPrec :: Int -> Locked -> ShowS
$cshow :: Locked -> String
show :: Locked -> String
$cshowList :: [Locked] -> ShowS
showList :: [Locked] -> ShowS
Show)
instance ToJSON Locked where
toJSON :: Locked -> Value
toJSON Locked
lck =
[Pair] -> Value
object
[ Key
"snapshots" Key
-> [LockedLocation RawSnapshotLocation SnapshotLocation] -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Locked
lck.snapshotLocations
, Key
"packages" Key
-> [LockedLocation
RawPackageLocationImmutable PackageLocationImmutable]
-> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Locked
lck.pkgImmutableLocations
]
instance FromJSON (WithJSONWarnings (Unresolved Locked)) where
parseJSON :: Value -> Parser (WithJSONWarnings (Unresolved Locked))
parseJSON = String
-> (Object -> WarningParser (Unresolved Locked))
-> Value
-> Parser (WithJSONWarnings (Unresolved Locked))
forall a.
String
-> (Object -> WarningParser a)
-> Value
-> Parser (WithJSONWarnings a)
withObjectWarnings String
"Locked" ((Object -> WarningParser (Unresolved Locked))
-> Value -> Parser (WithJSONWarnings (Unresolved Locked)))
-> (Object -> WarningParser (Unresolved Locked))
-> Value
-> Parser (WithJSONWarnings (Unresolved Locked))
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
snapshots <- WarningParser
[WithJSONWarnings
(Unresolved (LockedLocation RawSnapshotLocation SnapshotLocation))]
-> WarningParser
[Unresolved (LockedLocation RawSnapshotLocation SnapshotLocation)]
forall (t :: * -> *) a.
Traversable t =>
WarningParser (t (WithJSONWarnings a)) -> WarningParser (t a)
jsonSubWarningsT (WarningParser
[WithJSONWarnings
(Unresolved (LockedLocation RawSnapshotLocation SnapshotLocation))]
-> WarningParser
[Unresolved (LockedLocation RawSnapshotLocation SnapshotLocation)])
-> WarningParser
[WithJSONWarnings
(Unresolved (LockedLocation RawSnapshotLocation SnapshotLocation))]
-> WarningParser
[Unresolved (LockedLocation RawSnapshotLocation SnapshotLocation)]
forall a b. (a -> b) -> a -> b
$ Object
o Object
-> Text
-> WarningParser
[WithJSONWarnings
(Unresolved (LockedLocation RawSnapshotLocation SnapshotLocation))]
forall a. FromJSON a => Object -> Text -> WarningParser a
..: Text
"snapshots"
packages <- jsonSubWarningsT $ o ..: "packages"
let unwrap :: LockedLocation SingleRPLI b -> LockedLocation RawPackageLocationImmutable b
unwrap LockedLocation SingleRPLI b
ll = LockedLocation SingleRPLI b
ll { original = ll.original.singleRPLI }
pure $ Locked <$> sequenceA snapshots <*> (map unwrap <$> sequenceA packages)
loadYamlThrow ::
HasLogFunc env
=> (Value -> Yaml.Parser (WithJSONWarnings a))
-> Path Abs File
-> RIO env a
loadYamlThrow :: forall env a.
HasLogFunc env =>
(Value -> Parser (WithJSONWarnings a))
-> Path Abs File -> RIO env a
loadYamlThrow Value -> Parser (WithJSONWarnings a)
parser Path Abs File
path =
IO (Either ParseException Value)
-> RIO env (Either ParseException Value)
forall a. IO a -> RIO env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO (Either ParseException Value)
forall a. FromJSON a => String -> IO (Either ParseException a)
Yaml.decodeFileEither (Path Abs File -> String
forall b t. Path b t -> String
toFilePath Path Abs File
path)) RIO env (Either ParseException Value)
-> (Either ParseException Value -> RIO env a) -> RIO env a
forall a b. RIO env a -> (a -> RIO env b) -> RIO env b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left ParseException
parseException -> ConfigPrettyException -> RIO env a
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO (ConfigPrettyException -> RIO env a)
-> ConfigPrettyException -> RIO env a
forall a b. (a -> b) -> a -> b
$
Path Abs File -> ParseException -> ConfigPrettyException
ParseConfigFileException Path Abs File
path ParseException
parseException
Right Value
val -> case (Value -> Parser (WithJSONWarnings a))
-> Value -> Either String (WithJSONWarnings a)
forall a b. (a -> Parser b) -> a -> Either String b
Yaml.parseEither Value -> Parser (WithJSONWarnings a)
parser Value
val of
Left String
err -> ParseException -> RIO env a
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO (ParseException -> RIO env a) -> ParseException -> RIO env a
forall a b. (a -> b) -> a -> b
$ String -> ParseException
Yaml.AesonException String
err
Right (WithJSONWarnings a
res [JSONWarning]
warnings) -> do
String -> [JSONWarning] -> RIO env ()
forall env (m :: * -> *).
(MonadReader env m, HasLogFunc env, HasCallStack, MonadIO m) =>
String -> [JSONWarning] -> m ()
logJSONWarnings (Path Abs File -> String
forall b t. Path b t -> String
toFilePath Path Abs File
path) [JSONWarning]
warnings
a -> RIO env a
forall a. a -> RIO env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
res
lockCachedWanted ::
(HasPantryConfig env, HasRunner env)
=> Path Abs File
-> RawSnapshotLocation
-> ( Map RawPackageLocationImmutable PackageLocationImmutable
-> WantedCompiler
-> Map PackageName (Bool -> RIO env DepPackage)
-> RIO env ( SMWanted, [CompletedPLI])
)
-> RIO env SMWanted
lockCachedWanted :: forall env.
(HasPantryConfig env, HasRunner env) =>
Path Abs File
-> RawSnapshotLocation
-> (Map RawPackageLocationImmutable PackageLocationImmutable
-> WantedCompiler
-> Map PackageName (Bool -> RIO env DepPackage)
-> RIO env (SMWanted, [CompletedPLI]))
-> RIO env SMWanted
lockCachedWanted Path Abs File
stackFile RawSnapshotLocation
snapshot Map RawPackageLocationImmutable PackageLocationImmutable
-> WantedCompiler
-> Map PackageName (Bool -> RIO env DepPackage)
-> RIO env (SMWanted, [CompletedPLI])
fillWanted = do
lockFile <- IO (Path Abs File) -> RIO env (Path Abs File)
forall a. IO a -> RIO env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Path Abs File) -> RIO env (Path Abs File))
-> IO (Path Abs File) -> RIO env (Path Abs File)
forall a b. (a -> b) -> a -> b
$ String -> Path Abs File -> IO (Path Abs File)
forall (m :: * -> *) b.
MonadThrow m =>
String -> Path b File -> m (Path b File)
addExtension String
".lock" Path Abs File
stackFile
let getLockExists = Path Abs File -> RIO env Bool
forall (m :: * -> *) b. MonadIO m => Path b File -> m Bool
doesFileExist Path Abs File
lockFile
lfb <- view lockFileBehaviorL
readLockFile <-
case lfb of
LockFileBehavior
LFBIgnore -> Bool -> RIO env Bool
forall a. a -> RIO env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
LockFileBehavior
LFBReadWrite -> RIO env Bool
getLockExists
LockFileBehavior
LFBReadOnly -> RIO env Bool
getLockExists
LockFileBehavior
LFBErrorOnWrite -> RIO env Bool
getLockExists
locked <-
if readLockFile
then do
logDebug "Using package location completions from a lock file"
unresolvedLocked <- loadYamlThrow parseJSON lockFile
resolvePaths (Just $ parent stackFile) unresolvedLocked
else do
logDebug "Not reading lock file"
pure $ Locked [] []
let toMap :: Ord a => [LockedLocation a b] -> Map a b
toMap = [(a, b)] -> Map a b
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(a, b)] -> Map a b)
-> ([LockedLocation a b] -> [(a, b)])
-> [LockedLocation a b]
-> Map a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LockedLocation a b -> (a, b)) -> [LockedLocation a b] -> [(a, b)]
forall a b. (a -> b) -> [a] -> [b]
map ((.original) (LockedLocation a b -> a)
-> (LockedLocation a b -> b) -> LockedLocation a b -> (a, b)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& (.completed))
slocCache = [LockedLocation RawSnapshotLocation SnapshotLocation]
-> Map RawSnapshotLocation SnapshotLocation
forall a b. Ord a => [LockedLocation a b] -> Map a b
toMap Locked
locked.snapshotLocations
pkgLocCache = [LockedLocation
RawPackageLocationImmutable PackageLocationImmutable]
-> Map RawPackageLocationImmutable PackageLocationImmutable
forall a b. Ord a => [LockedLocation a b] -> Map a b
toMap Locked
locked.pkgImmutableLocations
debugRSL <- view rslInLogL
(snap, slocCompleted, pliCompleted) <-
loadAndCompleteSnapshotRaw' debugRSL snapshot slocCache pkgLocCache
let compiler = Snapshot -> WantedCompiler
snapshotCompiler Snapshot
snap
snPkgs = (PackageName -> SnapshotPackage -> Bool -> RIO env DepPackage)
-> Map PackageName SnapshotPackage
-> Map PackageName (Bool -> RIO env DepPackage)
forall k a b. (k -> a -> b) -> Map k a -> Map k b
Map.mapWithKey
(\PackageName
n SnapshotPackage
p Bool
h -> Bool -> PackageName -> SnapshotPackage -> RIO env DepPackage
forall env.
(HasPantryConfig env, HasLogFunc env, HasProcessContext env) =>
Bool -> PackageName -> SnapshotPackage -> RIO env DepPackage
snapToDepPackage Bool
h PackageName
n SnapshotPackage
p)
(Snapshot -> Map PackageName SnapshotPackage
snapshotPackages Snapshot
snap)
(wanted, prjCompleted) <- fillWanted pkgLocCache compiler snPkgs
let lockLocations = (CompletedPLI
-> LockedLocation
RawPackageLocationImmutable PackageLocationImmutable)
-> [CompletedPLI]
-> [LockedLocation
RawPackageLocationImmutable PackageLocationImmutable]
forall a b. (a -> b) -> [a] -> [b]
map (\(CompletedPLI RawPackageLocationImmutable
r PackageLocationImmutable
c) -> RawPackageLocationImmutable
-> PackageLocationImmutable
-> LockedLocation
RawPackageLocationImmutable PackageLocationImmutable
forall a b. a -> b -> LockedLocation a b
LockedLocation RawPackageLocationImmutable
r PackageLocationImmutable
c)
differentSnapLocs (CompletedSL RawSnapshotLocation
raw SnapshotLocation
complete)
| RawSnapshotLocation
raw RawSnapshotLocation -> RawSnapshotLocation -> Bool
forall a. Eq a => a -> a -> Bool
== SnapshotLocation -> RawSnapshotLocation
toRawSL SnapshotLocation
complete = Maybe (LockedLocation RawSnapshotLocation SnapshotLocation)
forall a. Maybe a
Nothing
| Bool
otherwise = LockedLocation RawSnapshotLocation SnapshotLocation
-> Maybe (LockedLocation RawSnapshotLocation SnapshotLocation)
forall a. a -> Maybe a
Just (LockedLocation RawSnapshotLocation SnapshotLocation
-> Maybe (LockedLocation RawSnapshotLocation SnapshotLocation))
-> LockedLocation RawSnapshotLocation SnapshotLocation
-> Maybe (LockedLocation RawSnapshotLocation SnapshotLocation)
forall a b. (a -> b) -> a -> b
$ RawSnapshotLocation
-> SnapshotLocation
-> LockedLocation RawSnapshotLocation SnapshotLocation
forall a b. a -> b -> LockedLocation a b
LockedLocation RawSnapshotLocation
raw SnapshotLocation
complete
newLocked = Locked
{ snapshotLocations :: [LockedLocation RawSnapshotLocation SnapshotLocation]
snapshotLocations = (CompletedSL
-> Maybe (LockedLocation RawSnapshotLocation SnapshotLocation))
-> [CompletedSL]
-> [LockedLocation RawSnapshotLocation SnapshotLocation]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe CompletedSL
-> Maybe (LockedLocation RawSnapshotLocation SnapshotLocation)
differentSnapLocs [CompletedSL]
slocCompleted
, pkgImmutableLocations :: [LockedLocation
RawPackageLocationImmutable PackageLocationImmutable]
pkgImmutableLocations =
[CompletedPLI]
-> [LockedLocation
RawPackageLocationImmutable PackageLocationImmutable]
lockLocations ([CompletedPLI]
-> [LockedLocation
RawPackageLocationImmutable PackageLocationImmutable])
-> [CompletedPLI]
-> [LockedLocation
RawPackageLocationImmutable PackageLocationImmutable]
forall a b. (a -> b) -> a -> b
$ [CompletedPLI]
pliCompleted [CompletedPLI] -> [CompletedPLI] -> [CompletedPLI]
forall a. Semigroup a => a -> a -> a
<> [CompletedPLI]
prjCompleted
}
when (newLocked /= locked) $
case lfb of
LockFileBehavior
LFBReadWrite ->
Path Abs File -> Builder -> RIO env ()
forall (m :: * -> *) absrel.
MonadIO m =>
Path absrel File -> Builder -> m ()
writeBinaryFileAtomic Path Abs File
lockFile (Builder -> RIO env ()) -> Builder -> RIO env ()
forall a b. (a -> b) -> a -> b
$
Builder
header Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
ByteString -> Builder
byteString (Locked -> ByteString
forall a. ToJSON a => a -> ByteString
Yaml.encode Locked
newLocked)
LockFileBehavior
LFBErrorOnWrite ->
LockPrettyException -> RIO env ()
forall e (m :: * -> *) a.
(Exception e, MonadIO m, Pretty e) =>
e -> m a
prettyThrowIO (LockPrettyException -> RIO env ())
-> LockPrettyException -> RIO env ()
forall a b. (a -> b) -> a -> b
$ Path Abs File -> Locked -> LockPrettyException
WritingLockFileError Path Abs File
lockFile Locked
newLocked
LockFileBehavior
LFBIgnore -> () -> RIO env ()
forall a. a -> RIO env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
LockFileBehavior
LFBReadOnly -> () -> RIO env ()
forall a. a -> RIO env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
pure wanted
where
header :: Builder
header =
Builder
"# This file was autogenerated by Stack.\n\
\# You should not edit this file by hand.\n\
\# For more information, please see the documentation at:\n\
\# https://docs.haskellstack.org/en/stable/topics/lock_files\n\n"