{-# LANGUAGE CPP #-}
module Portage.PackageId (
Category(..),
PackageName(..),
PackageId(..),
Portage.Version(..),
mkPackageName,
fromCabalPackageId,
toCabalPackageId,
parseFriendlyPackage,
normalizeCabalPackageName,
normalizeCabalPackageId,
filePathToPackageId,
packageIdToFilePath,
cabal_pn_to_PN
) where
import qualified Distribution.Compat.CharParsing as P
import qualified Distribution.Package as Cabal
import Distribution.Parsec (CabalParsing(..), Parsec(..), explicitEitherParsec)
import Distribution.Pretty (Pretty(..), prettyShow)
import qualified Portage.Version as Portage
import Control.DeepSeq (NFData(..))
import qualified Data.Char as Char
import qualified Text.PrettyPrint as Disp
import Text.PrettyPrint ((<>))
import System.FilePath ((</>))
#if MIN_VERSION_base(4,11,0)
import Prelude hiding ((<>))
#endif
newtype Category = Category { Category -> String
unCategory :: String }
deriving (Category -> Category -> Bool
(Category -> Category -> Bool)
-> (Category -> Category -> Bool) -> Eq Category
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Category -> Category -> Bool
$c/= :: Category -> Category -> Bool
== :: Category -> Category -> Bool
$c== :: Category -> Category -> Bool
Eq, Eq Category
Eq Category
-> (Category -> Category -> Ordering)
-> (Category -> Category -> Bool)
-> (Category -> Category -> Bool)
-> (Category -> Category -> Bool)
-> (Category -> Category -> Bool)
-> (Category -> Category -> Category)
-> (Category -> Category -> Category)
-> Ord Category
Category -> Category -> Bool
Category -> Category -> Ordering
Category -> Category -> Category
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 :: Category -> Category -> Category
$cmin :: Category -> Category -> Category
max :: Category -> Category -> Category
$cmax :: Category -> Category -> Category
>= :: Category -> Category -> Bool
$c>= :: Category -> Category -> Bool
> :: Category -> Category -> Bool
$c> :: Category -> Category -> Bool
<= :: Category -> Category -> Bool
$c<= :: Category -> Category -> Bool
< :: Category -> Category -> Bool
$c< :: Category -> Category -> Bool
compare :: Category -> Category -> Ordering
$ccompare :: Category -> Category -> Ordering
$cp1Ord :: Eq Category
Ord, Int -> Category -> ShowS
[Category] -> ShowS
Category -> String
(Int -> Category -> ShowS)
-> (Category -> String) -> ([Category] -> ShowS) -> Show Category
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Category] -> ShowS
$cshowList :: [Category] -> ShowS
show :: Category -> String
$cshow :: Category -> String
showsPrec :: Int -> Category -> ShowS
$cshowsPrec :: Int -> Category -> ShowS
Show, ReadPrec [Category]
ReadPrec Category
Int -> ReadS Category
ReadS [Category]
(Int -> ReadS Category)
-> ReadS [Category]
-> ReadPrec Category
-> ReadPrec [Category]
-> Read Category
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Category]
$creadListPrec :: ReadPrec [Category]
readPrec :: ReadPrec Category
$creadPrec :: ReadPrec Category
readList :: ReadS [Category]
$creadList :: ReadS [Category]
readsPrec :: Int -> ReadS Category
$creadsPrec :: Int -> ReadS Category
Read)
data PackageName = PackageName { PackageName -> Category
category :: Category, PackageName -> PackageName
cabalPkgName :: Cabal.PackageName }
deriving (PackageName -> PackageName -> Bool
(PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool) -> Eq PackageName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PackageName -> PackageName -> Bool
$c/= :: PackageName -> PackageName -> Bool
== :: PackageName -> PackageName -> Bool
$c== :: PackageName -> PackageName -> Bool
Eq, Eq PackageName
Eq PackageName
-> (PackageName -> PackageName -> Ordering)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> PackageName)
-> (PackageName -> PackageName -> PackageName)
-> Ord PackageName
PackageName -> PackageName -> Bool
PackageName -> PackageName -> Ordering
PackageName -> PackageName -> PackageName
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 :: PackageName -> PackageName -> PackageName
$cmin :: PackageName -> PackageName -> PackageName
max :: PackageName -> PackageName -> PackageName
$cmax :: PackageName -> PackageName -> PackageName
>= :: PackageName -> PackageName -> Bool
$c>= :: PackageName -> PackageName -> Bool
> :: PackageName -> PackageName -> Bool
$c> :: PackageName -> PackageName -> Bool
<= :: PackageName -> PackageName -> Bool
$c<= :: PackageName -> PackageName -> Bool
< :: PackageName -> PackageName -> Bool
$c< :: PackageName -> PackageName -> Bool
compare :: PackageName -> PackageName -> Ordering
$ccompare :: PackageName -> PackageName -> Ordering
$cp1Ord :: Eq PackageName
Ord, Int -> PackageName -> ShowS
[PackageName] -> ShowS
PackageName -> String
(Int -> PackageName -> ShowS)
-> (PackageName -> String)
-> ([PackageName] -> ShowS)
-> Show PackageName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PackageName] -> ShowS
$cshowList :: [PackageName] -> ShowS
show :: PackageName -> String
$cshow :: PackageName -> String
showsPrec :: Int -> PackageName -> ShowS
$cshowsPrec :: Int -> PackageName -> ShowS
Show, ReadPrec [PackageName]
ReadPrec PackageName
Int -> ReadS PackageName
ReadS [PackageName]
(Int -> ReadS PackageName)
-> ReadS [PackageName]
-> ReadPrec PackageName
-> ReadPrec [PackageName]
-> Read PackageName
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [PackageName]
$creadListPrec :: ReadPrec [PackageName]
readPrec :: ReadPrec PackageName
$creadPrec :: ReadPrec PackageName
readList :: ReadS [PackageName]
$creadList :: ReadS [PackageName]
readsPrec :: Int -> ReadS PackageName
$creadsPrec :: Int -> ReadS PackageName
Read)
data PackageId = PackageId { PackageId -> PackageName
packageId :: PackageName, PackageId -> Version
pkgVersion :: Portage.Version }
deriving (PackageId -> PackageId -> Bool
(PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> Bool) -> Eq PackageId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PackageId -> PackageId -> Bool
$c/= :: PackageId -> PackageId -> Bool
== :: PackageId -> PackageId -> Bool
$c== :: PackageId -> PackageId -> Bool
Eq, Eq PackageId
Eq PackageId
-> (PackageId -> PackageId -> Ordering)
-> (PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> Bool)
-> (PackageId -> PackageId -> PackageId)
-> (PackageId -> PackageId -> PackageId)
-> Ord PackageId
PackageId -> PackageId -> Bool
PackageId -> PackageId -> Ordering
PackageId -> PackageId -> PackageId
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 :: PackageId -> PackageId -> PackageId
$cmin :: PackageId -> PackageId -> PackageId
max :: PackageId -> PackageId -> PackageId
$cmax :: PackageId -> PackageId -> PackageId
>= :: PackageId -> PackageId -> Bool
$c>= :: PackageId -> PackageId -> Bool
> :: PackageId -> PackageId -> Bool
$c> :: PackageId -> PackageId -> Bool
<= :: PackageId -> PackageId -> Bool
$c<= :: PackageId -> PackageId -> Bool
< :: PackageId -> PackageId -> Bool
$c< :: PackageId -> PackageId -> Bool
compare :: PackageId -> PackageId -> Ordering
$ccompare :: PackageId -> PackageId -> Ordering
$cp1Ord :: Eq PackageId
Ord, Int -> PackageId -> ShowS
[PackageId] -> ShowS
PackageId -> String
(Int -> PackageId -> ShowS)
-> (PackageId -> String)
-> ([PackageId] -> ShowS)
-> Show PackageId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PackageId] -> ShowS
$cshowList :: [PackageId] -> ShowS
show :: PackageId -> String
$cshow :: PackageId -> String
showsPrec :: Int -> PackageId -> ShowS
$cshowsPrec :: Int -> PackageId -> ShowS
Show, ReadPrec [PackageId]
ReadPrec PackageId
Int -> ReadS PackageId
ReadS [PackageId]
(Int -> ReadS PackageId)
-> ReadS [PackageId]
-> ReadPrec PackageId
-> ReadPrec [PackageId]
-> Read PackageId
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [PackageId]
$creadListPrec :: ReadPrec [PackageId]
readPrec :: ReadPrec PackageId
$creadPrec :: ReadPrec PackageId
readList :: ReadS [PackageId]
$creadList :: ReadS [PackageId]
readsPrec :: Int -> ReadS PackageId
$creadsPrec :: Int -> ReadS PackageId
Read)
instance NFData Category where
rnf :: Category -> ()
rnf (Category String
c) = String -> ()
forall a. NFData a => a -> ()
rnf String
c
instance Pretty Category where
pretty :: Category -> Doc
pretty (Category String
c) = String -> Doc
Disp.text String
c
instance Parsec Category where
parsec :: m Category
parsec = String -> Category
Category (String -> Category) -> m String -> m Category
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> m String
forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m String
P.munch1 Char -> Bool
categoryChar
where
categoryChar :: Char -> Bool
categoryChar Char
c = Char -> Bool
Char.isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'
instance NFData PackageName where
rnf :: PackageName -> ()
rnf (PackageName Category
c PackageName
pn) = Category -> ()
forall a. NFData a => a -> ()
rnf Category
c () -> () -> ()
`seq` PackageName -> ()
forall a. NFData a => a -> ()
rnf PackageName
pn
instance Pretty PackageName where
pretty :: PackageName -> Doc
pretty (PackageName Category
cat PackageName
name) =
Category -> Doc
forall a. Pretty a => a -> Doc
pretty Category
cat Doc -> Doc -> Doc
<> Char -> Doc
Disp.char Char
'/' Doc -> Doc -> Doc
<> PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
name
instance Parsec PackageName where
parsec :: m PackageName
parsec = do
Category
cat <- m Category
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
Char
_ <- Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'/'
PackageName
name <- m PackageName
forall (m :: * -> *). CabalParsing m => m PackageName
parseCabalPackageName
PackageName -> m PackageName
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageName -> m PackageName) -> PackageName -> m PackageName
forall a b. (a -> b) -> a -> b
$ Category -> PackageName -> PackageName
PackageName Category
cat PackageName
name
instance NFData PackageId where
rnf :: PackageId -> ()
rnf (PackageId PackageName
pId Version
pv) = PackageName -> ()
forall a. NFData a => a -> ()
rnf PackageName
pId () -> () -> ()
`seq` Version -> ()
forall a. NFData a => a -> ()
rnf Version
pv
instance Pretty PackageId where
pretty :: PackageId -> Doc
pretty (PackageId PackageName
name Version
version) =
PackageName -> Doc
forall a. Pretty a => a -> Doc
pretty PackageName
name Doc -> Doc -> Doc
<> Char -> Doc
Disp.char Char
'-' Doc -> Doc -> Doc
<> Version -> Doc
forall a. Pretty a => a -> Doc
pretty Version
version
instance Parsec PackageId where
parsec :: m PackageId
parsec = do
PackageName
name <- m PackageName
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
Char
_ <- Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-'
Version
version <- m Version
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
PackageId -> m PackageId
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageId -> m PackageId) -> PackageId -> m PackageId
forall a b. (a -> b) -> a -> b
$ PackageName -> Version -> PackageId
PackageId PackageName
name Version
version
packageIdToFilePath :: PackageId -> FilePath
packageIdToFilePath :: PackageId -> String
packageIdToFilePath (PackageId (PackageName Category
cat PackageName
pn) Version
version) =
Category -> String
forall a. Pretty a => a -> String
prettyShow Category
cat String -> ShowS
</> PackageName -> String
forall a. Pretty a => a -> String
prettyShow PackageName
pn String -> ShowS
</> PackageName -> String
forall a. Pretty a => a -> String
prettyShow PackageName
pn String -> ShowS
<-> Version -> String
forall a. Pretty a => a -> String
prettyShow Version
version String -> ShowS
<.> String
"ebuild"
where
String
a <-> :: String -> ShowS
<-> String
b = String
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Char
'-'Char -> ShowS
forall a. a -> [a] -> [a]
:String
b
String
a <.> :: String -> ShowS
<.> String
b = String
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Char
'.'Char -> ShowS
forall a. a -> [a] -> [a]
:String
b
filePathToPackageId :: Category -> FilePath -> Maybe PackageId
filePathToPackageId :: Category -> String -> Maybe PackageId
filePathToPackageId Category
cat String
fp =
case ParsecParser PackageId -> String -> Either String PackageId
forall a. ParsecParser a -> String -> Either String a
explicitEitherParsec ParsecParser PackageId
parser String
fp of
Right PackageId
x -> PackageId -> Maybe PackageId
forall a. a -> Maybe a
Just PackageId
x
Either String PackageId
_ -> Maybe PackageId
forall a. Maybe a
Nothing
where
parser :: ParsecParser PackageId
parser = do
PackageName
pn <- ParsecParser PackageName
forall (m :: * -> *). CabalParsing m => m PackageName
parseCabalPackageName
Char
_ <- Char -> ParsecParser Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-'
Version
v <- ParsecParser Version
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
PackageId -> ParsecParser PackageId
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageId -> ParsecParser PackageId)
-> PackageId -> ParsecParser PackageId
forall a b. (a -> b) -> a -> b
$ PackageName -> Version -> PackageId
PackageId (Category -> PackageName -> PackageName
PackageName Category
cat PackageName
pn) Version
v
mkPackageName :: String -> String -> PackageName
mkPackageName :: String -> String -> PackageName
mkPackageName String
cat String
package = Category -> PackageName -> PackageName
PackageName (String -> Category
Category String
cat) (String -> PackageName
Cabal.mkPackageName String
package)
fromCabalPackageId :: Category -> Cabal.PackageIdentifier -> PackageId
fromCabalPackageId :: Category -> PackageIdentifier -> PackageId
fromCabalPackageId Category
cat (Cabal.PackageIdentifier PackageName
name Version
version) =
PackageName -> Version -> PackageId
PackageId (Category -> PackageName -> PackageName
PackageName Category
cat (PackageName -> PackageName
normalizeCabalPackageName PackageName
name))
(Version -> Version
Portage.fromCabalVersion Version
version)
normalizeCabalPackageName :: Cabal.PackageName -> Cabal.PackageName
normalizeCabalPackageName :: PackageName -> PackageName
normalizeCabalPackageName =
String -> PackageName
Cabal.mkPackageName (String -> PackageName)
-> (PackageName -> String) -> PackageName -> PackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> String
cabal_pn_to_PN
normalizeCabalPackageId :: Cabal.PackageIdentifier -> Cabal.PackageIdentifier
normalizeCabalPackageId :: PackageIdentifier -> PackageIdentifier
normalizeCabalPackageId (Cabal.PackageIdentifier PackageName
name Version
version) =
PackageName -> Version -> PackageIdentifier
Cabal.PackageIdentifier (PackageName -> PackageName
normalizeCabalPackageName PackageName
name) Version
version
toCabalPackageId :: PackageId -> Maybe Cabal.PackageIdentifier
toCabalPackageId :: PackageId -> Maybe PackageIdentifier
toCabalPackageId (PackageId (PackageName Category
_cat PackageName
name) Version
version) =
(Version -> PackageIdentifier)
-> Maybe Version -> Maybe PackageIdentifier
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (PackageName -> Version -> PackageIdentifier
Cabal.PackageIdentifier PackageName
name)
(Version -> Maybe Version
Portage.toCabalVersion Version
version)
parseFriendlyPackage :: String -> Either String (Maybe Category, Cabal.PackageName, Maybe Portage.Version)
parseFriendlyPackage :: String
-> Either String (Maybe Category, PackageName, Maybe Version)
parseFriendlyPackage String
str = ParsecParser (Maybe Category, PackageName, Maybe Version)
-> String
-> Either String (Maybe Category, PackageName, Maybe Version)
forall a. ParsecParser a -> String -> Either String a
explicitEitherParsec ParsecParser (Maybe Category, PackageName, Maybe Version)
parser String
str
where
parser :: ParsecParser (Maybe Category, PackageName, Maybe Version)
parser = do
Maybe Category
mc <- ParsecParser Category -> ParsecParser (Maybe Category)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
P.optional (ParsecParser Category -> ParsecParser (Maybe Category))
-> (ParsecParser Category -> ParsecParser Category)
-> ParsecParser Category
-> ParsecParser (Maybe Category)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParsecParser Category -> ParsecParser Category
forall (m :: * -> *) a. Parsing m => m a -> m a
P.try (ParsecParser Category -> ParsecParser (Maybe Category))
-> ParsecParser Category -> ParsecParser (Maybe Category)
forall a b. (a -> b) -> a -> b
$ do
Category
c <- ParsecParser Category
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
Char
_ <- Char -> ParsecParser Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'/'
Category -> ParsecParser Category
forall (m :: * -> *) a. Monad m => a -> m a
return Category
c
PackageName
p <- ParsecParser PackageName
forall (m :: * -> *). CabalParsing m => m PackageName
parseCabalPackageName
Maybe Version
mv <- ParsecParser Version -> ParsecParser (Maybe Version)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
P.optional (ParsecParser Version -> ParsecParser (Maybe Version))
-> ParsecParser Version -> ParsecParser (Maybe Version)
forall a b. (a -> b) -> a -> b
$ do
Char
_ <- Char -> ParsecParser Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-'
Version
v <- ParsecParser Version
forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
Version -> ParsecParser Version
forall (m :: * -> *) a. Monad m => a -> m a
return Version
v
(Maybe Category, PackageName, Maybe Version)
-> ParsecParser (Maybe Category, PackageName, Maybe Version)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Category
mc, PackageName
p, Maybe Version
mv)
parseCabalPackageName :: CabalParsing m => m Cabal.PackageName
parseCabalPackageName :: m PackageName
parseCabalPackageName = do
String
pn <- m Char -> m String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
P.some (m Char -> m String) -> (m Char -> m Char) -> m Char -> m String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
P.try (m Char -> m String) -> m Char -> m String
forall a b. (a -> b) -> a -> b
$
[m Char] -> m Char
forall (m :: * -> *) a. Alternative m => [m a] -> m a
P.choice
[ m Char
forall (m :: * -> *). CharParsing m => m Char
P.alphaNum
, Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'+'
, Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-' m Char -> m () -> m Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m String -> m ()
forall (m :: * -> *) a. (Parsing m, Show a) => m a -> m ()
P.notFollowedBy (m Char -> m String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
P.some m Char
forall (m :: * -> *). CharParsing m => m Char
P.digit m String -> m () -> m String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m Char -> m ()
forall (m :: * -> *) a. (Parsing m, Show a) => m a -> m ()
P.notFollowedBy m Char
forall (m :: * -> *). CharParsing m => m Char
P.letter)
]
PackageName -> m PackageName
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageName -> m PackageName) -> PackageName -> m PackageName
forall a b. (a -> b) -> a -> b
$ String -> PackageName
Cabal.mkPackageName String
pn
cabal_pn_to_PN :: Cabal.PackageName -> String
cabal_pn_to_PN :: PackageName -> String
cabal_pn_to_PN = (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
Char.toLower ShowS -> (PackageName -> String) -> PackageName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> String
forall a. Pretty a => a -> String
prettyShow