{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}

-- | A library for pkgtreediff for comparing trees of rpm packages
module Distribution.RPM.PackageTreeDiff
  (RpmPackage(..),
   readRpmPkg,
   showRpmPkg,
   rpmPkgIdent,
   appendArch,
   dropRpmArch,
   rpmPkgVerRel,
   RpmPackageDiff(..),
   diffPkgs,
   diffPkg,
   Ignore(..),
   Mode(..),
  ) where

#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<$>))
#endif
import Data.Char
import Data.Maybe
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup ((<>))
#endif
import Data.Text (Text)
import qualified Data.Text as T

-- | Mode describes the kind of summary generated by compareDirs
data Mode = AutoSummary | NoSummary | ShowSummary | Added | Deleted | Updated | RST
  deriving Mode -> Mode -> Bool
(Mode -> Mode -> Bool) -> (Mode -> Mode -> Bool) -> Eq Mode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Mode -> Mode -> Bool
$c/= :: Mode -> Mode -> Bool
== :: Mode -> Mode -> Bool
$c== :: Mode -> Mode -> Bool
Eq

-- | Ignore describes how comparison is done
data Ignore = IgnoreNone    -- ^ do not ignore version or release
            | IgnoreRelease -- ^ ignore differences in release
            | IgnoreVersion -- ^ ignore differences in version
  deriving Ignore -> Ignore -> Bool
(Ignore -> Ignore -> Bool)
-> (Ignore -> Ignore -> Bool) -> Eq Ignore
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Ignore -> Ignore -> Bool
$c/= :: Ignore -> Ignore -> Bool
== :: Ignore -> Ignore -> Bool
$c== :: Ignore -> Ignore -> Bool
Eq

type Name = Text
type Arch = Text

data VersionRelease = VerRel Text Text
  deriving VersionRelease -> VersionRelease -> Bool
(VersionRelease -> VersionRelease -> Bool)
-> (VersionRelease -> VersionRelease -> Bool) -> Eq VersionRelease
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: VersionRelease -> VersionRelease -> Bool
$c/= :: VersionRelease -> VersionRelease -> Bool
== :: VersionRelease -> VersionRelease -> Bool
$c== :: VersionRelease -> VersionRelease -> Bool
Eq

instance Ord VersionRelease where
  compare :: VersionRelease -> VersionRelease -> Ordering
compare (VerRel Text
v1 Text
r1) (VerRel Text
v2 Text
r2) =
    case Text -> Text -> Ordering
rpmVerCompare Text
v1 Text
v2 of
      Ordering
EQ -> Text -> Text -> Ordering
rpmVerCompare Text
r1 Text
r2
      Ordering
o -> Ordering
o

data VerChunk = TildeChunk Int | CaretChunk Int | TxtChunk Text | IntChunk Int
  deriving (VerChunk -> VerChunk -> Bool
(VerChunk -> VerChunk -> Bool)
-> (VerChunk -> VerChunk -> Bool) -> Eq VerChunk
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: VerChunk -> VerChunk -> Bool
$c/= :: VerChunk -> VerChunk -> Bool
== :: VerChunk -> VerChunk -> Bool
$c== :: VerChunk -> VerChunk -> Bool
Eq,Eq VerChunk
Eq VerChunk
-> (VerChunk -> VerChunk -> Ordering)
-> (VerChunk -> VerChunk -> Bool)
-> (VerChunk -> VerChunk -> Bool)
-> (VerChunk -> VerChunk -> Bool)
-> (VerChunk -> VerChunk -> Bool)
-> (VerChunk -> VerChunk -> VerChunk)
-> (VerChunk -> VerChunk -> VerChunk)
-> Ord VerChunk
VerChunk -> VerChunk -> Bool
VerChunk -> VerChunk -> Ordering
VerChunk -> VerChunk -> VerChunk
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
min :: VerChunk -> VerChunk -> VerChunk
$cmin :: VerChunk -> VerChunk -> VerChunk
max :: VerChunk -> VerChunk -> VerChunk
$cmax :: VerChunk -> VerChunk -> VerChunk
>= :: VerChunk -> VerChunk -> Bool
$c>= :: VerChunk -> VerChunk -> Bool
> :: VerChunk -> VerChunk -> Bool
$c> :: VerChunk -> VerChunk -> Bool
<= :: VerChunk -> VerChunk -> Bool
$c<= :: VerChunk -> VerChunk -> Bool
< :: VerChunk -> VerChunk -> Bool
$c< :: VerChunk -> VerChunk -> Bool
compare :: VerChunk -> VerChunk -> Ordering
$ccompare :: VerChunk -> VerChunk -> Ordering
$cp1Ord :: Eq VerChunk
Ord,Int -> VerChunk -> ShowS
[VerChunk] -> ShowS
VerChunk -> String
(Int -> VerChunk -> ShowS)
-> (VerChunk -> String) -> ([VerChunk] -> ShowS) -> Show VerChunk
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [VerChunk] -> ShowS
$cshowList :: [VerChunk] -> ShowS
show :: VerChunk -> String
$cshow :: VerChunk -> String
showsPrec :: Int -> VerChunk -> ShowS
$cshowsPrec :: Int -> VerChunk -> ShowS
Show)

data RpmCharCategory = RpmTilde | RpmCaret | RpmOther | RpmLatin | RpmDigit
  deriving RpmCharCategory -> RpmCharCategory -> Bool
(RpmCharCategory -> RpmCharCategory -> Bool)
-> (RpmCharCategory -> RpmCharCategory -> Bool)
-> Eq RpmCharCategory
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RpmCharCategory -> RpmCharCategory -> Bool
$c/= :: RpmCharCategory -> RpmCharCategory -> Bool
== :: RpmCharCategory -> RpmCharCategory -> Bool
$c== :: RpmCharCategory -> RpmCharCategory -> Bool
Eq

verChunk :: Text -> VerChunk
verChunk :: Text -> VerChunk
verChunk Text
t | (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isDigit Text
t = (Int -> VerChunk
IntChunk (Int -> VerChunk) -> (Text -> Int) -> Text -> VerChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
forall a. Read a => String -> a
read (String -> Int) -> (Text -> String) -> Text -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack) Text
t
verChunk Text
t | (Char -> Bool) -> Text -> Bool
T.all (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'~') Text
t = (Int -> VerChunk
TildeChunk (Int -> VerChunk) -> (Text -> Int) -> Text -> VerChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Int
T.length) Text
t
verChunk Text
t | (Char -> Bool) -> Text -> Bool
T.all (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'^') Text
t = (Int -> VerChunk
CaretChunk (Int -> VerChunk) -> (Text -> Int) -> Text -> VerChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Int
T.length) Text
t
verChunk Text
t = Text -> VerChunk
TxtChunk Text
t

rpmVerCompare :: Text -> Text -> Ordering
rpmVerCompare :: Text -> Text -> Ordering
rpmVerCompare Text
v1 Text
v2 | Text
v1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
v2 = Ordering
EQ
rpmVerCompare Text
v1 Text
v2 =
  [VerChunk] -> [VerChunk] -> Ordering
compareChunks (Text -> [VerChunk]
verList Text
v1) (Text -> [VerChunk]
verList Text
v2)
  where
    compareChunks :: [VerChunk] -> [VerChunk] -> Ordering
compareChunks [] [] = Ordering
EQ
    compareChunks (VerChunk
c:[VerChunk]
cs) (VerChunk
c':[VerChunk]
cs') | VerChunk
c VerChunk -> VerChunk -> Bool
forall a. Eq a => a -> a -> Bool
== VerChunk
c' = [VerChunk] -> [VerChunk] -> Ordering
compareChunks [VerChunk]
cs [VerChunk]
cs'
    compareChunks ((TildeChunk Int
n):[VerChunk]
_) ((TildeChunk Int
n'):[VerChunk]
_) = Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
n' Int
n
    compareChunks ((CaretChunk Int
n):[VerChunk]
_) ((CaretChunk Int
n'):[VerChunk]
_) = Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
n' Int
n
    compareChunks ((TildeChunk Int
_):[VerChunk]
_) [VerChunk]
_ = Ordering
LT
    compareChunks [VerChunk]
_ ((TildeChunk Int
_):[VerChunk]
_) = Ordering
GT
    compareChunks ((CaretChunk Int
_):[VerChunk]
_) [VerChunk]
_ = Ordering
LT
    compareChunks [VerChunk]
_ ((CaretChunk Int
_):[VerChunk]
_) = Ordering
GT
    compareChunks [VerChunk]
_ [] = Ordering
GT
    compareChunks [] [VerChunk]
_ = Ordering
LT
    compareChunks (VerChunk
c:[VerChunk]
_) (VerChunk
c':[VerChunk]
_) = VerChunk -> VerChunk -> Ordering
forall a. Ord a => a -> a -> Ordering
compare VerChunk
c VerChunk
c'

verList :: Text -> [VerChunk]
verList :: Text -> [VerChunk]
verList = (Text -> VerChunk) -> [Text] -> [VerChunk]
forall a b. (a -> b) -> [a] -> [b]
map Text -> VerChunk
verChunk ([Text] -> [VerChunk]) -> (Text -> [Text]) -> Text -> [VerChunk]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Char -> Bool) -> Text -> Bool
T.all (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.')) ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char -> Bool) -> Text -> [Text]
T.groupBy (\ Char
c1 Char
c2 -> Char -> RpmCharCategory
rpmCategory Char
c1 RpmCharCategory -> RpmCharCategory -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> RpmCharCategory
rpmCategory Char
c2)

latinChars :: [Char]
latinChars :: String
latinChars = [Char
'A'..Char
'Z'] String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
'a'..Char
'z']

rpmCategory :: Char -> RpmCharCategory
rpmCategory :: Char -> RpmCharCategory
rpmCategory Char
c | Char -> Bool
isDigit Char
c = RpmCharCategory
RpmDigit
rpmCategory Char
c | Char
c Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
latinChars = RpmCharCategory
RpmLatin
rpmCategory Char
'~' = RpmCharCategory
RpmTilde
rpmCategory Char
'^' = RpmCharCategory
RpmCaret
rpmCategory Char
_ = RpmCharCategory
RpmOther

-- eqVR True ignore release
eqVR :: Ignore -> VersionRelease -> VersionRelease -> Bool
eqVR :: Ignore -> VersionRelease -> VersionRelease -> Bool
eqVR Ignore
IgnoreNone VersionRelease
vr VersionRelease
vr' = VersionRelease
vr VersionRelease -> VersionRelease -> Bool
forall a. Eq a => a -> a -> Bool
== VersionRelease
vr'
eqVR Ignore
IgnoreRelease (VerRel Text
v Text
_) (VerRel Text
v' Text
_) = Text
v Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
v'
eqVR Ignore
IgnoreVersion VersionRelease
_ VersionRelease
_ = Bool
True

-- | Text for the version-release of an RpmPackage
rpmPkgVerRel :: RpmPackage -> Text
rpmPkgVerRel :: RpmPackage -> Text
rpmPkgVerRel = VersionRelease -> Text
txtVerRel (VersionRelease -> Text)
-> (RpmPackage -> VersionRelease) -> RpmPackage -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RpmPackage -> VersionRelease
rpmVerRel
  where
    txtVerRel :: VersionRelease -> Text
txtVerRel (VerRel Text
v Text
r) = Text
v Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Char -> Text
T.singleton Char
'-' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
r

-- | RPM package with name, version-release, and maybe architecture
data RpmPackage = RpmPkg {RpmPackage -> Text
rpmName :: Name, RpmPackage -> VersionRelease
rpmVerRel :: VersionRelease, RpmPackage -> Maybe Text
rpmMArch :: Maybe Arch}
  deriving (RpmPackage -> RpmPackage -> Bool
(RpmPackage -> RpmPackage -> Bool)
-> (RpmPackage -> RpmPackage -> Bool) -> Eq RpmPackage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RpmPackage -> RpmPackage -> Bool
$c/= :: RpmPackage -> RpmPackage -> Bool
== :: RpmPackage -> RpmPackage -> Bool
$c== :: RpmPackage -> RpmPackage -> Bool
Eq, Eq RpmPackage
Eq RpmPackage
-> (RpmPackage -> RpmPackage -> Ordering)
-> (RpmPackage -> RpmPackage -> Bool)
-> (RpmPackage -> RpmPackage -> Bool)
-> (RpmPackage -> RpmPackage -> Bool)
-> (RpmPackage -> RpmPackage -> Bool)
-> (RpmPackage -> RpmPackage -> RpmPackage)
-> (RpmPackage -> RpmPackage -> RpmPackage)
-> Ord RpmPackage
RpmPackage -> RpmPackage -> Bool
RpmPackage -> RpmPackage -> Ordering
RpmPackage -> RpmPackage -> RpmPackage
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
min :: RpmPackage -> RpmPackage -> RpmPackage
$cmin :: RpmPackage -> RpmPackage -> RpmPackage
max :: RpmPackage -> RpmPackage -> RpmPackage
$cmax :: RpmPackage -> RpmPackage -> RpmPackage
>= :: RpmPackage -> RpmPackage -> Bool
$c>= :: RpmPackage -> RpmPackage -> Bool
> :: RpmPackage -> RpmPackage -> Bool
$c> :: RpmPackage -> RpmPackage -> Bool
<= :: RpmPackage -> RpmPackage -> Bool
$c<= :: RpmPackage -> RpmPackage -> Bool
< :: RpmPackage -> RpmPackage -> Bool
$c< :: RpmPackage -> RpmPackage -> Bool
compare :: RpmPackage -> RpmPackage -> Ordering
$ccompare :: RpmPackage -> RpmPackage -> Ordering
$cp1Ord :: Eq RpmPackage
Ord)

-- | Text identifier for an RPM package identified by name and arch
rpmPkgIdent :: RpmPackage -> Text
rpmPkgIdent :: RpmPackage -> Text
rpmPkgIdent RpmPackage
p  = RpmPackage -> Text
rpmName RpmPackage
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> RpmPackage -> Text
appendArch RpmPackage
p

-- | Helper to add an arch suffix
appendArch :: RpmPackage -> Text
appendArch :: RpmPackage -> Text
appendArch RpmPackage
p = Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) (RpmPackage -> Maybe Text
rpmMArch RpmPackage
p)

-- | drop arch from RpmPackage
dropRpmArch :: RpmPackage -> RpmPackage
dropRpmArch :: RpmPackage -> RpmPackage
dropRpmArch (RpmPkg Text
n VersionRelease
vr Maybe Text
_) = Text -> VersionRelease -> Maybe Text -> RpmPackage
RpmPkg Text
n VersionRelease
vr Maybe Text
forall a. Maybe a
Nothing

-- | Render an RpmPackage
showRpmPkg :: RpmPackage -> Text
showRpmPkg :: RpmPackage -> Text
showRpmPkg RpmPackage
p = RpmPackage -> Text
rpmPkgIdent RpmPackage
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
"  " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> RpmPackage -> Text
rpmPkgVerRel RpmPackage
p

-- | Parse an RpmPackage
readRpmPkg :: Text -> RpmPackage
readRpmPkg :: Text -> RpmPackage
readRpmPkg Text
t =
  if Int
compnts Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
3 then String -> RpmPackage
forall a. HasCallStack => String -> a
error (String -> RpmPackage) -> String -> RpmPackage
forall a b. (a -> b) -> a -> b
$ String
"Malformed rpm package name: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
t
  else Text -> VersionRelease -> Maybe Text -> RpmPackage
RpmPkg Text
name (Text -> Text -> VersionRelease
VerRel Text
ver Text
rel) (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
arch)
  where
    compnts :: Int
compnts = [Text] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
pieces
    (Text
nvr',Text
arch) = Text -> Text -> (Text, Text)
T.breakOnEnd Text
"." (Text -> (Text, Text)) -> Text -> (Text, Text)
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
t (Maybe Text -> Text) -> Maybe Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Maybe Text
T.stripSuffix Text
".rpm" Text
t
    pieces :: [Text]
pieces = [Text] -> [Text]
forall a. [a] -> [a]
reverse ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> Text -> [Text]
T.splitOn Text
"-" (Text -> [Text]) -> Text -> [Text]
forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
T.dropEnd Int
1 Text
nvr'
    (Text
rel:Text
ver:[Text]
emaN) = [Text]
pieces
    name :: Text
name = Text -> [Text] -> Text
T.intercalate Text
"-" ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. [a] -> [a]
reverse [Text]
emaN

-- | RpmPackageDiff type encodes how a particular rpm package differs between trees
data RpmPackageDiff = PkgUpdate RpmPackage RpmPackage
                 | PkgAdd RpmPackage
                 | PkgDel RpmPackage
                 | PkgArch RpmPackage RpmPackage
  deriving RpmPackageDiff -> RpmPackageDiff -> Bool
(RpmPackageDiff -> RpmPackageDiff -> Bool)
-> (RpmPackageDiff -> RpmPackageDiff -> Bool) -> Eq RpmPackageDiff
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RpmPackageDiff -> RpmPackageDiff -> Bool
$c/= :: RpmPackageDiff -> RpmPackageDiff -> Bool
== :: RpmPackageDiff -> RpmPackageDiff -> Bool
$c== :: RpmPackageDiff -> RpmPackageDiff -> Bool
Eq

-- | Compare two lists of packages NVRs
diffPkgs :: Ignore -> [RpmPackage] -> [RpmPackage] -> [RpmPackageDiff]
diffPkgs :: Ignore -> [RpmPackage] -> [RpmPackage] -> [RpmPackageDiff]
diffPkgs Ignore
_ [] [] = []
diffPkgs Ignore
ignore (RpmPackage
p:[RpmPackage]
ps) [] = RpmPackage -> RpmPackageDiff
PkgDel RpmPackage
p RpmPackageDiff -> [RpmPackageDiff] -> [RpmPackageDiff]
forall a. a -> [a] -> [a]
: Ignore -> [RpmPackage] -> [RpmPackage] -> [RpmPackageDiff]
diffPkgs Ignore
ignore [RpmPackage]
ps []
diffPkgs Ignore
ignore [] (RpmPackage
p:[RpmPackage]
ps) = RpmPackage -> RpmPackageDiff
PkgAdd RpmPackage
p RpmPackageDiff -> [RpmPackageDiff] -> [RpmPackageDiff]
forall a. a -> [a] -> [a]
: Ignore -> [RpmPackage] -> [RpmPackage] -> [RpmPackageDiff]
diffPkgs Ignore
ignore [] [RpmPackage]
ps
diffPkgs Ignore
ignore (RpmPackage
p1:[RpmPackage]
ps1) (RpmPackage
p2:[RpmPackage]
ps2) =
  case RpmPackage -> RpmPackage -> Ordering
compareNames RpmPackage
p1 RpmPackage
p2 of
    Ordering
LT -> RpmPackage -> RpmPackageDiff
PkgDel RpmPackage
p1 RpmPackageDiff -> [RpmPackageDiff] -> [RpmPackageDiff]
forall a. a -> [a] -> [a]
: Ignore -> [RpmPackage] -> [RpmPackage] -> [RpmPackageDiff]
diffPkgs Ignore
ignore [RpmPackage]
ps1 (RpmPackage
p2RpmPackage -> [RpmPackage] -> [RpmPackage]
forall a. a -> [a] -> [a]
:[RpmPackage]
ps2)
    Ordering
EQ -> let diff :: Maybe RpmPackageDiff
diff = Ignore -> RpmPackage -> RpmPackage -> Maybe RpmPackageDiff
diffPkg Ignore
ignore RpmPackage
p1 RpmPackage
p2
              diffs :: [RpmPackageDiff]
diffs = Ignore -> [RpmPackage] -> [RpmPackage] -> [RpmPackageDiff]
diffPkgs Ignore
ignore [RpmPackage]
ps1 [RpmPackage]
ps2
          in if Maybe RpmPackageDiff -> Bool
forall a. Maybe a -> Bool
isJust Maybe RpmPackageDiff
diff then Maybe RpmPackageDiff -> RpmPackageDiff
forall a. HasCallStack => Maybe a -> a
fromJust Maybe RpmPackageDiff
diff RpmPackageDiff -> [RpmPackageDiff] -> [RpmPackageDiff]
forall a. a -> [a] -> [a]
: [RpmPackageDiff]
diffs else [RpmPackageDiff]
diffs
    Ordering
GT -> RpmPackage -> RpmPackageDiff
PkgAdd RpmPackage
p2 RpmPackageDiff -> [RpmPackageDiff] -> [RpmPackageDiff]
forall a. a -> [a] -> [a]
: Ignore -> [RpmPackage] -> [RpmPackage] -> [RpmPackageDiff]
diffPkgs Ignore
ignore (RpmPackage
p1RpmPackage -> [RpmPackage] -> [RpmPackage]
forall a. a -> [a] -> [a]
:[RpmPackage]
ps1) [RpmPackage]
ps2

-- | Compare two rpms of a package
diffPkg :: Ignore -> RpmPackage-> RpmPackage-> Maybe RpmPackageDiff
diffPkg :: Ignore -> RpmPackage -> RpmPackage -> Maybe RpmPackageDiff
diffPkg Ignore
ignore RpmPackage
p1 RpmPackage
p2 | RpmPackage -> Text
rpmPkgIdent RpmPackage
p1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== RpmPackage -> Text
rpmPkgIdent RpmPackage
p2 =
                           if Ignore -> VersionRelease -> VersionRelease -> Bool
eqVR Ignore
ignore (RpmPackage -> VersionRelease
rpmVerRel RpmPackage
p1) (RpmPackage -> VersionRelease
rpmVerRel RpmPackage
p2)
                           then Maybe RpmPackageDiff
forall a. Maybe a
Nothing
                           else RpmPackageDiff -> Maybe RpmPackageDiff
forall a. a -> Maybe a
Just (RpmPackageDiff -> Maybe RpmPackageDiff)
-> RpmPackageDiff -> Maybe RpmPackageDiff
forall a b. (a -> b) -> a -> b
$ RpmPackage -> RpmPackage -> RpmPackageDiff
PkgUpdate RpmPackage
p1 RpmPackage
p2
--diffPkg ignore p1 p2 | rpmName p1 == rpmName p2 =
--                            diffPkg ignore True (RpmPkg n1 v1) (RpmPkg n2 v2)
diffPkg Ignore
_ RpmPackage
p1 RpmPackage
p2 | RpmPackage -> Text
rpmName RpmPackage
p1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== RpmPackage -> Text
rpmName RpmPackage
p2 Bool -> Bool -> Bool
&& RpmPackage -> Text
rpmPkgIdent RpmPackage
p1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= RpmPackage -> Text
rpmPkgIdent RpmPackage
p2 = RpmPackageDiff -> Maybe RpmPackageDiff
forall a. a -> Maybe a
Just (RpmPackageDiff -> Maybe RpmPackageDiff)
-> RpmPackageDiff -> Maybe RpmPackageDiff
forall a b. (a -> b) -> a -> b
$ RpmPackage -> RpmPackage -> RpmPackageDiff
PkgArch RpmPackage
p1 RpmPackage
p2
diffPkg Ignore
_ RpmPackage
_ RpmPackage
_ = Maybe RpmPackageDiff
forall a. Maybe a
Nothing

compareNames :: RpmPackage -> RpmPackage -> Ordering
compareNames :: RpmPackage -> RpmPackage -> Ordering
compareNames RpmPackage
p1 RpmPackage
p2 = Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (RpmPackage -> Text
rpmName RpmPackage
p1) (RpmPackage -> Text
rpmName RpmPackage
p2)