module Ecluse.Core.Package.Merge (
Provenance (..),
SourceId,
MergePlan (..),
Divergence (..),
IntegrityFingerprint,
integrityHashes,
mergePackuments,
Merge,
contribute,
planFrom,
) where
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import Data.Time (UTCTime)
import Ecluse.Core.Package (
Artifact (..),
Hash,
HashAlg (SRI),
PackageDetails (..),
PackageInfo (..),
PackageName,
hashAlg,
hashValue,
sriBody,
)
import Ecluse.Core.Package.Integrity (assertedAlg)
import Ecluse.Core.Version (Version, selectLatest, unVersion)
data Provenance
=
TrustedSource
|
GatedSource
deriving stock (Provenance -> Provenance -> Bool
(Provenance -> Provenance -> Bool)
-> (Provenance -> Provenance -> Bool) -> Eq Provenance
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Provenance -> Provenance -> Bool
== :: Provenance -> Provenance -> Bool
$c/= :: Provenance -> Provenance -> Bool
/= :: Provenance -> Provenance -> Bool
Eq, Eq Provenance
Eq Provenance =>
(Provenance -> Provenance -> Ordering)
-> (Provenance -> Provenance -> Bool)
-> (Provenance -> Provenance -> Bool)
-> (Provenance -> Provenance -> Bool)
-> (Provenance -> Provenance -> Bool)
-> (Provenance -> Provenance -> Provenance)
-> (Provenance -> Provenance -> Provenance)
-> Ord Provenance
Provenance -> Provenance -> Bool
Provenance -> Provenance -> Ordering
Provenance -> Provenance -> Provenance
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Provenance -> Provenance -> Ordering
compare :: Provenance -> Provenance -> Ordering
$c< :: Provenance -> Provenance -> Bool
< :: Provenance -> Provenance -> Bool
$c<= :: Provenance -> Provenance -> Bool
<= :: Provenance -> Provenance -> Bool
$c> :: Provenance -> Provenance -> Bool
> :: Provenance -> Provenance -> Bool
$c>= :: Provenance -> Provenance -> Bool
>= :: Provenance -> Provenance -> Bool
$cmax :: Provenance -> Provenance -> Provenance
max :: Provenance -> Provenance -> Provenance
$cmin :: Provenance -> Provenance -> Provenance
min :: Provenance -> Provenance -> Provenance
Ord, Int -> Provenance -> ShowS
[Provenance] -> ShowS
Provenance -> String
(Int -> Provenance -> ShowS)
-> (Provenance -> String)
-> ([Provenance] -> ShowS)
-> Show Provenance
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Provenance -> ShowS
showsPrec :: Int -> Provenance -> ShowS
$cshow :: Provenance -> String
show :: Provenance -> String
$cshowList :: [Provenance] -> ShowS
showList :: [Provenance] -> ShowS
Show)
type SourceId = Int
data Divergence = Divergence
{ Divergence -> Text
divVersion :: Text
, Divergence -> IntegrityFingerprint
divWinning :: IntegrityFingerprint
, Divergence -> IntegrityFingerprint
divLosing :: IntegrityFingerprint
}
deriving stock (Divergence -> Divergence -> Bool
(Divergence -> Divergence -> Bool)
-> (Divergence -> Divergence -> Bool) -> Eq Divergence
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Divergence -> Divergence -> Bool
== :: Divergence -> Divergence -> Bool
$c/= :: Divergence -> Divergence -> Bool
/= :: Divergence -> Divergence -> Bool
Eq, Eq Divergence
Eq Divergence =>
(Divergence -> Divergence -> Ordering)
-> (Divergence -> Divergence -> Bool)
-> (Divergence -> Divergence -> Bool)
-> (Divergence -> Divergence -> Bool)
-> (Divergence -> Divergence -> Bool)
-> (Divergence -> Divergence -> Divergence)
-> (Divergence -> Divergence -> Divergence)
-> Ord Divergence
Divergence -> Divergence -> Bool
Divergence -> Divergence -> Ordering
Divergence -> Divergence -> Divergence
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Divergence -> Divergence -> Ordering
compare :: Divergence -> Divergence -> Ordering
$c< :: Divergence -> Divergence -> Bool
< :: Divergence -> Divergence -> Bool
$c<= :: Divergence -> Divergence -> Bool
<= :: Divergence -> Divergence -> Bool
$c> :: Divergence -> Divergence -> Bool
> :: Divergence -> Divergence -> Bool
$c>= :: Divergence -> Divergence -> Bool
>= :: Divergence -> Divergence -> Bool
$cmax :: Divergence -> Divergence -> Divergence
max :: Divergence -> Divergence -> Divergence
$cmin :: Divergence -> Divergence -> Divergence
min :: Divergence -> Divergence -> Divergence
Ord, Int -> Divergence -> ShowS
[Divergence] -> ShowS
Divergence -> String
(Int -> Divergence -> ShowS)
-> (Divergence -> String)
-> ([Divergence] -> ShowS)
-> Show Divergence
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Divergence -> ShowS
showsPrec :: Int -> Divergence -> ShowS
$cshow :: Divergence -> String
show :: Divergence -> String
$cshowList :: [Divergence] -> ShowS
showList :: [Divergence] -> ShowS
Show)
data MergePlan = MergePlan
{ MergePlan -> PackageName
mpName :: PackageName
, MergePlan -> Map Text Int
mpSurvivors :: Map Text SourceId
, MergePlan -> Map Text Version
mpDistTags :: Map Text Version
, MergePlan -> Map Text UTCTime
mpTime :: Map Text UTCTime
, MergePlan -> Set Divergence
mpDivergences :: Set Divergence
}
deriving stock (MergePlan -> MergePlan -> Bool
(MergePlan -> MergePlan -> Bool)
-> (MergePlan -> MergePlan -> Bool) -> Eq MergePlan
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MergePlan -> MergePlan -> Bool
== :: MergePlan -> MergePlan -> Bool
$c/= :: MergePlan -> MergePlan -> Bool
/= :: MergePlan -> MergePlan -> Bool
Eq, Int -> MergePlan -> ShowS
[MergePlan] -> ShowS
MergePlan -> String
(Int -> MergePlan -> ShowS)
-> (MergePlan -> String)
-> ([MergePlan] -> ShowS)
-> Show MergePlan
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MergePlan -> ShowS
showsPrec :: Int -> MergePlan -> ShowS
$cshow :: MergePlan -> String
show :: MergePlan -> String
$cshowList :: [MergePlan] -> ShowS
showList :: [MergePlan] -> ShowS
Show)
newtype IntegrityFingerprint = IntegrityFingerprint [(Maybe HashAlg, Text)]
deriving stock (IntegrityFingerprint -> IntegrityFingerprint -> Bool
(IntegrityFingerprint -> IntegrityFingerprint -> Bool)
-> (IntegrityFingerprint -> IntegrityFingerprint -> Bool)
-> Eq IntegrityFingerprint
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
== :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
$c/= :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
/= :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
Eq, Eq IntegrityFingerprint
Eq IntegrityFingerprint =>
(IntegrityFingerprint -> IntegrityFingerprint -> Ordering)
-> (IntegrityFingerprint -> IntegrityFingerprint -> Bool)
-> (IntegrityFingerprint -> IntegrityFingerprint -> Bool)
-> (IntegrityFingerprint -> IntegrityFingerprint -> Bool)
-> (IntegrityFingerprint -> IntegrityFingerprint -> Bool)
-> (IntegrityFingerprint
-> IntegrityFingerprint -> IntegrityFingerprint)
-> (IntegrityFingerprint
-> IntegrityFingerprint -> IntegrityFingerprint)
-> Ord IntegrityFingerprint
IntegrityFingerprint -> IntegrityFingerprint -> Bool
IntegrityFingerprint -> IntegrityFingerprint -> Ordering
IntegrityFingerprint
-> IntegrityFingerprint -> IntegrityFingerprint
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: IntegrityFingerprint -> IntegrityFingerprint -> Ordering
compare :: IntegrityFingerprint -> IntegrityFingerprint -> Ordering
$c< :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
< :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
$c<= :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
<= :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
$c> :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
> :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
$c>= :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
>= :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
$cmax :: IntegrityFingerprint
-> IntegrityFingerprint -> IntegrityFingerprint
max :: IntegrityFingerprint
-> IntegrityFingerprint -> IntegrityFingerprint
$cmin :: IntegrityFingerprint
-> IntegrityFingerprint -> IntegrityFingerprint
min :: IntegrityFingerprint
-> IntegrityFingerprint -> IntegrityFingerprint
Ord, Int -> IntegrityFingerprint -> ShowS
[IntegrityFingerprint] -> ShowS
IntegrityFingerprint -> String
(Int -> IntegrityFingerprint -> ShowS)
-> (IntegrityFingerprint -> String)
-> ([IntegrityFingerprint] -> ShowS)
-> Show IntegrityFingerprint
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> IntegrityFingerprint -> ShowS
showsPrec :: Int -> IntegrityFingerprint -> ShowS
$cshow :: IntegrityFingerprint -> String
show :: IntegrityFingerprint -> String
$cshowList :: [IntegrityFingerprint] -> ShowS
showList :: [IntegrityFingerprint] -> ShowS
Show)
integrityHashes :: IntegrityFingerprint -> [(Maybe HashAlg, Text)]
integrityHashes :: IntegrityFingerprint -> [(Maybe HashAlg, Text)]
integrityHashes (IntegrityFingerprint [(Maybe HashAlg, Text)]
hs) = [(Maybe HashAlg, Text)]
hs
rank :: Provenance -> SourceId -> (Provenance, SourceId)
rank :: Provenance -> Int -> (Provenance, Int)
rank Provenance
prov Int
sid = (Provenance
prov, Int
sid)
data Candidate = Candidate
{ Candidate -> Provenance
candProvenance :: Provenance
, Candidate -> Int
candSourceId :: SourceId
, Candidate -> IntegrityFingerprint
candFingerprint :: ~IntegrityFingerprint
, Candidate -> PackageDetails
candDetails :: PackageDetails
}
deriving stock (Int -> Candidate -> ShowS
[Candidate] -> ShowS
Candidate -> String
(Int -> Candidate -> ShowS)
-> (Candidate -> String)
-> ([Candidate] -> ShowS)
-> Show Candidate
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Candidate -> ShowS
showsPrec :: Int -> Candidate -> ShowS
$cshow :: Candidate -> String
show :: Candidate -> String
$cshowList :: [Candidate] -> ShowS
showList :: [Candidate] -> ShowS
Show)
candKey :: Candidate -> ((Provenance, SourceId), IntegrityFingerprint)
candKey :: Candidate -> ((Provenance, Int), IntegrityFingerprint)
candKey Candidate
c = (Provenance -> Int -> (Provenance, Int)
rank (Candidate -> Provenance
candProvenance Candidate
c) (Candidate -> Int
candSourceId Candidate
c), Candidate -> IntegrityFingerprint
candFingerprint Candidate
c)
instance Eq Candidate where
Candidate
a == :: Candidate -> Candidate -> Bool
== Candidate
b = Candidate -> ((Provenance, Int), IntegrityFingerprint)
candKey Candidate
a ((Provenance, Int), IntegrityFingerprint)
-> ((Provenance, Int), IntegrityFingerprint) -> Bool
forall a. Eq a => a -> a -> Bool
== Candidate -> ((Provenance, Int), IntegrityFingerprint)
candKey Candidate
b
instance Ord Candidate where
compare :: Candidate -> Candidate -> Ordering
compare Candidate
a Candidate
b = ((Provenance, Int), IntegrityFingerprint)
-> ((Provenance, Int), IntegrityFingerprint) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Candidate -> ((Provenance, Int), IntegrityFingerprint)
candKey Candidate
a) (Candidate -> ((Provenance, Int), IntegrityFingerprint)
candKey Candidate
b)
data Ranked a = Ranked
{ forall a. Ranked a -> (Provenance, Int)
rankedRank :: (Provenance, SourceId)
, forall a. Ranked a -> a
rankedValue :: a
}
deriving stock (Ranked a -> Ranked a -> Bool
(Ranked a -> Ranked a -> Bool)
-> (Ranked a -> Ranked a -> Bool) -> Eq (Ranked a)
forall a. Eq a => Ranked a -> Ranked a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Ranked a -> Ranked a -> Bool
== :: Ranked a -> Ranked a -> Bool
$c/= :: forall a. Eq a => Ranked a -> Ranked a -> Bool
/= :: Ranked a -> Ranked a -> Bool
Eq, Int -> Ranked a -> ShowS
[Ranked a] -> ShowS
Ranked a -> String
(Int -> Ranked a -> ShowS)
-> (Ranked a -> String) -> ([Ranked a] -> ShowS) -> Show (Ranked a)
forall a. Show a => Int -> Ranked a -> ShowS
forall a. Show a => [Ranked a] -> ShowS
forall a. Show a => Ranked a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Ranked a -> ShowS
showsPrec :: Int -> Ranked a -> ShowS
$cshow :: forall a. Show a => Ranked a -> String
show :: Ranked a -> String
$cshowList :: forall a. Show a => [Ranked a] -> ShowS
showList :: [Ranked a] -> ShowS
Show)
instance (Eq a) => Ord (Ranked a) where
compare :: Ranked a -> Ranked a -> Ordering
compare Ranked a
a Ranked a
b = (Provenance, Int) -> (Provenance, Int) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Ranked a -> (Provenance, Int)
forall a. Ranked a -> (Provenance, Int)
rankedRank Ranked a
a) (Ranked a -> (Provenance, Int)
forall a. Ranked a -> (Provenance, Int)
rankedRank Ranked a
b)
keepBetter :: Ranked a -> Ranked a -> Ranked a
keepBetter :: forall a. Ranked a -> Ranked a -> Ranked a
keepBetter Ranked a
x Ranked a
y = if Ranked a -> (Provenance, Int)
forall a. Ranked a -> (Provenance, Int)
rankedRank Ranked a
x (Provenance, Int) -> (Provenance, Int) -> Bool
forall a. Ord a => a -> a -> Bool
<= Ranked a -> (Provenance, Int)
forall a. Ranked a -> (Provenance, Int)
rankedRank Ranked a
y then Ranked a
x else Ranked a
y
data Merge = Merge
{ Merge -> Int
mergeCount :: Int
, Merge -> Map Text (Set Candidate)
mergeVersions :: Map Text (Set Candidate)
, Merge -> Map Text (Ranked Version)
mergeDistTags :: Map Text (Ranked Version)
, Merge -> Maybe PackageName
mergeName :: Maybe PackageName
}
deriving stock (Merge -> Merge -> Bool
(Merge -> Merge -> Bool) -> (Merge -> Merge -> Bool) -> Eq Merge
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Merge -> Merge -> Bool
== :: Merge -> Merge -> Bool
$c/= :: Merge -> Merge -> Bool
/= :: Merge -> Merge -> Bool
Eq, Int -> Merge -> ShowS
[Merge] -> ShowS
Merge -> String
(Int -> Merge -> ShowS)
-> (Merge -> String) -> ([Merge] -> ShowS) -> Show Merge
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Merge -> ShowS
showsPrec :: Int -> Merge -> ShowS
$cshow :: Merge -> String
show :: Merge -> String
$cshowList :: [Merge] -> ShowS
showList :: [Merge] -> ShowS
Show)
instance Semigroup Merge where
Merge
a <> :: Merge -> Merge -> Merge
<> Merge
b =
Merge
{ mergeCount :: Int
mergeCount = Merge -> Int
mergeCount Merge
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Merge -> Int
mergeCount Merge
b
, mergeVersions :: Map Text (Set Candidate)
mergeVersions =
(Set Candidate -> Set Candidate -> Set Candidate)
-> Map Text (Set Candidate)
-> Map Text (Set Candidate)
-> Map Text (Set Candidate)
forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
Map.unionWith Set Candidate -> Set Candidate -> Set Candidate
forall a. Ord a => Set a -> Set a -> Set a
Set.union (Merge -> Map Text (Set Candidate)
mergeVersions Merge
a) (Map Text (Set Candidate) -> Map Text (Set Candidate)
shiftVersions (Merge -> Map Text (Set Candidate)
mergeVersions Merge
b))
, mergeDistTags :: Map Text (Ranked Version)
mergeDistTags =
(Ranked Version -> Ranked Version -> Ranked Version)
-> Map Text (Ranked Version)
-> Map Text (Ranked Version)
-> Map Text (Ranked Version)
forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
Map.unionWith Ranked Version -> Ranked Version -> Ranked Version
forall a. Ranked a -> Ranked a -> Ranked a
keepBetter (Merge -> Map Text (Ranked Version)
mergeDistTags Merge
a) (Ranked Version -> Ranked Version
forall {a}. Ranked a -> Ranked a
shiftRanked (Ranked Version -> Ranked Version)
-> Map Text (Ranked Version) -> Map Text (Ranked Version)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Merge -> Map Text (Ranked Version)
mergeDistTags Merge
b)
, mergeName :: Maybe PackageName
mergeName = Merge -> Maybe PackageName
mergeName Merge
a Maybe PackageName -> Maybe PackageName -> Maybe PackageName
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Merge -> Maybe PackageName
mergeName Merge
b
}
where
offset :: Int
offset = Merge -> Int
mergeCount Merge
a
shiftVersions :: Map Text (Set Candidate) -> Map Text (Set Candidate)
shiftVersions = (Set Candidate -> Set Candidate)
-> Map Text (Set Candidate) -> Map Text (Set Candidate)
forall a b. (a -> b) -> Map Text a -> Map Text b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Candidate -> Candidate) -> Set Candidate -> Set Candidate
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map Candidate -> Candidate
shiftCandidate)
shiftCandidate :: Candidate -> Candidate
shiftCandidate Candidate
c = Candidate
c{candSourceId = candSourceId c + offset}
shiftRanked :: Ranked a -> Ranked a
shiftRanked (Ranked (Provenance
prov, Int
sid) a
v) = (Provenance, Int) -> a -> Ranked a
forall a. (Provenance, Int) -> a -> Ranked a
Ranked (Provenance
prov, Int
sid Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
offset) a
v
instance Monoid Merge where
mempty :: Merge
mempty =
Merge
{ mergeCount :: Int
mergeCount = Int
0
, mergeVersions :: Map Text (Set Candidate)
mergeVersions = Map Text (Set Candidate)
forall k a. Map k a
Map.empty
, mergeDistTags :: Map Text (Ranked Version)
mergeDistTags = Map Text (Ranked Version)
forall k a. Map k a
Map.empty
, mergeName :: Maybe PackageName
mergeName = Maybe PackageName
forall a. Maybe a
Nothing
}
contribute :: Provenance -> PackageInfo -> Merge
contribute :: Provenance -> PackageInfo -> Merge
contribute Provenance
prov PackageInfo
info =
Merge
{ mergeCount :: Int
mergeCount = Int
1
, mergeVersions :: Map Text (Set Candidate)
mergeVersions = (PackageDetails -> Set Candidate)
-> Map Text PackageDetails -> Map Text (Set Candidate)
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map PackageDetails -> Set Candidate
candidateFor (PackageInfo -> Map Text PackageDetails
infoVersions PackageInfo
info)
, mergeDistTags :: Map Text (Ranked Version)
mergeDistTags = (Version -> Ranked Version)
-> Map Text Version -> Map Text (Ranked Version)
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map ((Provenance, Int) -> Version -> Ranked Version
forall a. (Provenance, Int) -> a -> Ranked a
Ranked (Provenance, Int)
here) (PackageInfo -> Map Text Version
infoDistTags PackageInfo
info)
, mergeName :: Maybe PackageName
mergeName = PackageName -> Maybe PackageName
forall a. a -> Maybe a
Just (PackageInfo -> PackageName
infoName PackageInfo
info)
}
where
here :: (Provenance, Int)
here = (Provenance
prov, Int
0)
candidateFor :: PackageDetails -> Set Candidate
candidateFor PackageDetails
details =
Candidate -> Set Candidate
forall a. a -> Set a
Set.singleton
Candidate
{ candProvenance :: Provenance
candProvenance = Provenance
prov
, candSourceId :: Int
candSourceId = Int
0
, candFingerprint :: IntegrityFingerprint
candFingerprint = PackageDetails -> IntegrityFingerprint
fingerprint PackageDetails
details
, candDetails :: PackageDetails
candDetails = PackageDetails
details
}
mergePackuments :: [(Provenance, PackageInfo)] -> Maybe MergePlan
mergePackuments :: [(Provenance, PackageInfo)] -> Maybe MergePlan
mergePackuments [] = Maybe MergePlan
forall a. Maybe a
Nothing
mergePackuments [(Provenance, PackageInfo)]
inputs = Merge -> Maybe MergePlan
planFrom (((Provenance, PackageInfo) -> Merge)
-> [(Provenance, PackageInfo)] -> Merge
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ((Provenance -> PackageInfo -> Merge)
-> (Provenance, PackageInfo) -> Merge
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Provenance -> PackageInfo -> Merge
contribute) [(Provenance, PackageInfo)]
inputs)
planFrom :: Merge -> Maybe MergePlan
planFrom :: Merge -> Maybe MergePlan
planFrom Merge
acc = do
name <- Merge -> Maybe PackageName
mergeName Merge
acc
pure
MergePlan
{ mpName = name
, mpSurvivors = Map.map (candSourceId . winnerOf) (mergeVersions acc)
, mpDistTags = reconciledTags
, mpTime = reconciledTimes
, mpDivergences = divergences
}
where
winnerOf :: Set Candidate -> Candidate
winnerOf :: Set Candidate -> Candidate
winnerOf = Set Candidate -> Candidate
forall a. Set a -> a
Set.findMin
survives :: Text -> Bool
survives :: Text -> Bool
survives Text
key = Text -> Map Text (Set Candidate) -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member Text
key (Merge -> Map Text (Set Candidate)
mergeVersions Merge
acc)
survivingDetails :: [PackageDetails]
survivingDetails :: [PackageDetails]
survivingDetails =
[Candidate -> PackageDetails
candDetails (Set Candidate -> Candidate
winnerOf Set Candidate
cs) | Set Candidate
cs <- Map Text (Set Candidate) -> [Set Candidate]
forall k a. Map k a -> [a]
Map.elems (Merge -> Map Text (Set Candidate)
mergeVersions Merge
acc)]
divergences :: Set Divergence
divergences :: Set Divergence
divergences =
[Divergence] -> Set Divergence
forall a. Ord a => [a] -> Set a
Set.fromList
[ Divergence{divVersion :: Text
divVersion = Text
key, divWinning :: IntegrityFingerprint
divWinning = IntegrityFingerprint
win, divLosing :: IntegrityFingerprint
divLosing = IntegrityFingerprint
lose}
| (Text
key, Set Candidate
cs) <- Map Text (Set Candidate) -> [(Text, Set Candidate)]
forall k a. Map k a -> [(k, a)]
Map.toList (Merge -> Map Text (Set Candidate)
mergeVersions Merge
acc)
,
Set Candidate -> Int
forall a. Set a -> Int
Set.size Set Candidate
cs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
, let win :: IntegrityFingerprint
win = Candidate -> IntegrityFingerprint
candFingerprint (Set Candidate -> Candidate
winnerOf Set Candidate
cs)
, let distinct :: Set IntegrityFingerprint
distinct = [IntegrityFingerprint] -> Set IntegrityFingerprint
forall a. Ord a => [a] -> Set a
Set.fromList [Candidate -> IntegrityFingerprint
candFingerprint Candidate
c | Candidate
c <- Set Candidate -> [Candidate]
forall a. Set a -> [a]
Set.toList Set Candidate
cs]
, IntegrityFingerprint
lose <- Set IntegrityFingerprint -> [IntegrityFingerprint]
forall a. Set a -> [a]
Set.toList Set IntegrityFingerprint
distinct
, IntegrityFingerprint -> IntegrityFingerprint -> Bool
contradicts IntegrityFingerprint
win IntegrityFingerprint
lose
]
reconciledTags :: Map Text Version
reconciledTags :: Map Text Version
reconciledTags =
let carried :: Map Text Version
carried = (Version -> Bool) -> Map Text Version -> Map Text Version
forall a k. (a -> Bool) -> Map k a -> Map k a
Map.filter (Text -> Bool
survives (Text -> Bool) -> (Version -> Text) -> Version -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Version -> Text
unVersion) ((Ranked Version -> Version)
-> Map Text (Ranked Version) -> Map Text Version
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map Ranked Version -> Version
forall a. Ranked a -> a
rankedValue (Merge -> Map Text (Ranked Version)
mergeDistTags Merge
acc))
in case Maybe Version
resolvedLatest of
Maybe Version
Nothing -> Text -> Map Text Version -> Map Text Version
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete Text
"latest" Map Text Version
carried
Just Version
v -> Text -> Version -> Map Text Version -> Map Text Version
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Text
"latest" Version
v Map Text Version
carried
resolvedLatest :: Maybe Version
resolvedLatest :: Maybe Version
resolvedLatest =
Maybe Version -> [Version] -> Maybe Version
selectLatest Maybe Version
chosenLatest ((PackageDetails -> Version) -> [PackageDetails] -> [Version]
forall a b. (a -> b) -> [a] -> [b]
map PackageDetails -> Version
pkgVersion [PackageDetails]
survivingDetails)
chosenLatest :: Maybe Version
chosenLatest :: Maybe Version
chosenLatest = Ranked Version -> Version
forall a. Ranked a -> a
rankedValue (Ranked Version -> Version)
-> Maybe (Ranked Version) -> Maybe Version
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Map Text (Ranked Version) -> Maybe (Ranked Version)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
"latest" (Merge -> Map Text (Ranked Version)
mergeDistTags Merge
acc)
reconciledTimes :: Map Text UTCTime
reconciledTimes :: Map Text UTCTime
reconciledTimes =
(Set Candidate -> Maybe UTCTime)
-> Map Text (Set Candidate) -> Map Text UTCTime
forall a b k. (a -> Maybe b) -> Map k a -> Map k b
Map.mapMaybe (PackageDetails -> Maybe UTCTime
pkgPublishedAt (PackageDetails -> Maybe UTCTime)
-> (Set Candidate -> PackageDetails)
-> Set Candidate
-> Maybe UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Candidate -> PackageDetails
candDetails (Candidate -> PackageDetails)
-> (Set Candidate -> Candidate) -> Set Candidate -> PackageDetails
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set Candidate -> Candidate
winnerOf) (Merge -> Map Text (Set Candidate)
mergeVersions Merge
acc)
fingerprint :: PackageDetails -> IntegrityFingerprint
fingerprint :: PackageDetails -> IntegrityFingerprint
fingerprint =
[(Maybe HashAlg, Text)] -> IntegrityFingerprint
IntegrityFingerprint
([(Maybe HashAlg, Text)] -> IntegrityFingerprint)
-> (PackageDetails -> [(Maybe HashAlg, Text)])
-> PackageDetails
-> IntegrityFingerprint
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Maybe HashAlg, Text)] -> [(Maybe HashAlg, Text)]
forall a. Ord a => [a] -> [a]
sort
([(Maybe HashAlg, Text)] -> [(Maybe HashAlg, Text)])
-> (PackageDetails -> [(Maybe HashAlg, Text)])
-> PackageDetails
-> [(Maybe HashAlg, Text)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Artifact -> [(Maybe HashAlg, Text)])
-> [Artifact] -> [(Maybe HashAlg, Text)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Artifact -> [(Maybe HashAlg, Text)]
artHashPairs
([Artifact] -> [(Maybe HashAlg, Text)])
-> (PackageDetails -> [Artifact])
-> PackageDetails
-> [(Maybe HashAlg, Text)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty Artifact -> [Artifact]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList
(NonEmpty Artifact -> [Artifact])
-> (PackageDetails -> NonEmpty Artifact)
-> PackageDetails
-> [Artifact]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageDetails -> NonEmpty Artifact
pkgArtifacts
where
artHashPairs :: Artifact -> [(Maybe HashAlg, Text)]
artHashPairs Artifact
art = [(Hash -> Maybe HashAlg
assertedAlg Hash
h, Hash -> Text
comparableBody Hash
h) | Hash
h <- Artifact -> [Hash]
artHashes Artifact
art]
comparableBody :: Hash -> Text
comparableBody :: Hash -> Text
comparableBody Hash
h = case Hash -> HashAlg
hashAlg Hash
h of
HashAlg
SRI -> Text -> Text
sriBody (Hash -> Text
hashValue Hash
h)
HashAlg
_ -> Hash -> Text
hashValue Hash
h
contradicts :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
contradicts :: IntegrityFingerprint -> IntegrityFingerprint -> Bool
contradicts IntegrityFingerprint
a IntegrityFingerprint
b =
Map (Maybe HashAlg) Bool -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ((Set Text -> Set Text -> Bool)
-> Map (Maybe HashAlg) (Set Text)
-> Map (Maybe HashAlg) (Set Text)
-> Map (Maybe HashAlg) Bool
forall k a b c.
Ord k =>
(a -> b -> c) -> Map k a -> Map k b -> Map k c
Map.intersectionWith Set Text -> Set Text -> Bool
forall a. Eq a => a -> a -> Bool
(/=) (IntegrityFingerprint -> Map (Maybe HashAlg) (Set Text)
digestsByAlg IntegrityFingerprint
a) (IntegrityFingerprint -> Map (Maybe HashAlg) (Set Text)
digestsByAlg IntegrityFingerprint
b))
where
digestsByAlg :: IntegrityFingerprint -> Map (Maybe HashAlg) (Set Text)
digestsByAlg :: IntegrityFingerprint -> Map (Maybe HashAlg) (Set Text)
digestsByAlg (IntegrityFingerprint [(Maybe HashAlg, Text)]
pairs) =
(Set Text -> Set Text -> Set Text)
-> [(Maybe HashAlg, Set Text)] -> Map (Maybe HashAlg) (Set Text)
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith Set Text -> Set Text -> Set Text
forall a. Ord a => Set a -> Set a -> Set a
Set.union [(Maybe HashAlg
alg, Text -> Set Text
forall a. a -> Set a
Set.singleton Text
digest) | (Maybe HashAlg
alg, Text
digest) <- [(Maybe HashAlg, Text)]
pairs]