Cabal-3.4.0.0: Distribution/Types/PackageId.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Distribution.Types.PackageId
( PackageIdentifier(..)
, PackageId
) where
import Distribution.Compat.Prelude
import Prelude ()
import Distribution.Parsec (Parsec (..), simpleParsec)
import Distribution.Pretty
import Distribution.Types.PackageName
import Distribution.Version (Version, nullVersion)
import qualified Data.List.NonEmpty as NE
import qualified Distribution.Compat.CharParsing as P
import qualified Text.PrettyPrint as Disp
-- | Type alias so we can use the shorter name PackageId.
type PackageId = PackageIdentifier
-- | The name and version of a package.
data PackageIdentifier
= PackageIdentifier {
pkgName :: PackageName, -- ^The name of this package, eg. foo
pkgVersion :: Version -- ^the version of this package, eg 1.2
}
deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)
instance Binary PackageIdentifier
instance Structured PackageIdentifier
instance Pretty PackageIdentifier where
pretty (PackageIdentifier n v)
| v == nullVersion = pretty n -- if no version, don't show version.
| otherwise = pretty n <<>> Disp.char '-' <<>> pretty v
-- |
--
-- >>> simpleParsec "foo-bar-0" :: Maybe PackageIdentifier
-- Just (PackageIdentifier {pkgName = PackageName "foo-bar", pkgVersion = mkVersion [0]})
--
-- >>> simpleParsec "foo-bar" :: Maybe PackageIdentifier
-- Just (PackageIdentifier {pkgName = PackageName "foo-bar", pkgVersion = mkVersion []})
--
-- /Note:/ Stricter than 'Text' instance
--
-- >>> simpleParsec "foo-bar-0-0" :: Maybe PackageIdentifier
-- Nothing
--
-- >>> simpleParsec "foo-bar.0" :: Maybe PackageIdentifier
-- Nothing
--
-- >>> simpleParsec "foo-bar.4-2" :: Maybe PackageIdentifier
-- Nothing
--
-- >>> simpleParsec "1.2.3" :: Maybe PackageIdentifier
-- Nothing
--
instance Parsec PackageIdentifier where
parsec = do
xs' <- P.sepByNonEmpty component (P.char '-')
(v, xs) <- case simpleParsec (NE.last xs') of
Nothing -> return (nullVersion, toList xs') -- all components are version
Just v -> return (v, NE.init xs')
if not (null xs) && all (\c -> all (/= '.') c && not (all isDigit c)) xs
then return $ PackageIdentifier (mkPackageName (intercalate "-" xs)) v
else fail "all digits or a dot in a portion of package name"
where
component = P.munch1 (\c -> isAlphaNum c || c == '.')
instance NFData PackageIdentifier where
rnf (PackageIdentifier name version) = rnf name `seq` rnf version