module Yarn.Lock.Helpers
( decycle
) where
import qualified Data.List as L
import GHC.Stack (HasCallStack)
import qualified Data.MultiKeyedMap as MKM
import Yarn.Lock.Types
import Data.Foldable (foldl')
decycle :: HasCallStack => Lockfile -> Lockfile
decycle :: Lockfile -> Lockfile
decycle Lockfile
lf = [PackageKey] -> Lockfile -> [PackageKey] -> Lockfile
forall (t :: * -> *).
Foldable t =>
[PackageKey] -> Lockfile -> t PackageKey -> Lockfile
goFold [] Lockfile
lf (Lockfile -> [PackageKey]
forall k v. Ord k => MKMap k v -> [k]
MKM.keys Lockfile
lf)
where
goFold :: [PackageKey] -> Lockfile -> t PackageKey -> Lockfile
goFold [PackageKey]
seen Lockfile
lf' t PackageKey
pkeys =
(Lockfile -> PackageKey -> Lockfile)
-> Lockfile -> t PackageKey -> Lockfile
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Lockfile
lf'' PackageKey
pkey -> [PackageKey] -> Lockfile -> Lockfile
go (PackageKey
pkeyPackageKey -> [PackageKey] -> [PackageKey]
forall a. a -> [a] -> [a]
:[PackageKey]
seen) Lockfile
lf'') Lockfile
lf' t PackageKey
pkeys
go :: [PackageKey] -> Lockfile -> Lockfile
go :: [PackageKey] -> Lockfile -> Lockfile
go seen :: [PackageKey]
seen@(PackageKey
we:[PackageKey]
_) Lockfile
lf' =
let ourPkg :: Package
ourPkg = Lockfile
lf' Lockfile -> PackageKey -> Package
forall k v. (HasCallStack, Ord k) => MKMap k v -> k -> v
MKM.! PackageKey
we
newDeps :: [PackageKey]
newDeps = Package -> [PackageKey]
dependencies Package
ourPkg [PackageKey] -> [PackageKey] -> [PackageKey]
forall a. Eq a => [a] -> [a] -> [a]
L.\\ [PackageKey]
seen
newOptDeps :: [PackageKey]
newOptDeps = Package -> [PackageKey]
optionalDependencies Package
ourPkg [PackageKey] -> [PackageKey] -> [PackageKey]
forall a. Eq a => [a] -> [a] -> [a]
L.\\ [PackageKey]
seen
lf'' :: Lockfile
lf'' = PackageKey -> Package -> Lockfile -> Lockfile
forall k v. Ord k => k -> v -> MKMap k v -> MKMap k v
MKM.insert PackageKey
we (Package
ourPkg { dependencies :: [PackageKey]
dependencies = [PackageKey]
newDeps
, optionalDependencies :: [PackageKey]
optionalDependencies = [PackageKey]
newOptDeps }) Lockfile
lf'
in [PackageKey] -> Lockfile -> [PackageKey] -> Lockfile
forall (t :: * -> *).
Foldable t =>
[PackageKey] -> Lockfile -> t PackageKey -> Lockfile
goFold [PackageKey]
seen Lockfile
lf'' ([PackageKey] -> Lockfile) -> [PackageKey] -> Lockfile
forall a b. (a -> b) -> a -> b
$ [PackageKey]
newDeps [PackageKey] -> [PackageKey] -> [PackageKey]
forall a. [a] -> [a] -> [a]
++ [PackageKey]
newOptDeps
go [] Lockfile
_ = [Char] -> Lockfile
forall a. HasCallStack => [Char] -> a
error [Char]
"should not happen!"