module Ecluse.Core.Package (
Scope,
mkScope,
unScope,
renderScope,
PackageName,
mkPackageName,
pkgEcosystem,
pkgNamespace,
pkgCanonical,
pkgBaseName,
renderPackageName,
unscopedName,
isAsciiNameComponent,
canonicalise,
CodeExecSignal (..),
Availability (..),
Artifact (..),
Hash,
hashAlg,
hashValue,
mkHash,
mkSriHashes,
HashAlg (..),
renderHashAlg,
parseHashAlg,
sriPrefix,
sriBody,
sriAlgorithm,
computeDigest,
isComputable,
PackageDetails (..),
PackageInfo (..),
InvalidEntry (invalidKind, invalidKey, invalidValue, invalidReason),
mkInvalidEntry,
InvalidEntryKind (..),
renderInvalidEntryKind,
dropCountsByKind,
) where
import Data.Char (isAscii, isControl)
import Data.Text qualified as T
import Data.Text.Short (ShortText)
import Data.Text.Short qualified as TS
import Data.Time (UTCTime)
import Ecluse.Core.Ecosystem (Ecosystem (..))
import Ecluse.Core.Package.Entry (EntryKey)
import Ecluse.Core.Package.Hash (
Hash,
HashAlg (..),
computeDigest,
hashAlg,
hashValue,
isComputable,
mkHash,
mkSriHashes,
parseHashAlg,
renderHashAlg,
sriAlgorithm,
sriBody,
sriPrefix,
)
import Ecluse.Core.Package.InvalidEntry (
InvalidEntry (invalidKey, invalidKind, invalidReason, invalidValue),
InvalidEntryKind (..),
dropCountsByKind,
mkInvalidEntry,
renderInvalidEntryKind,
)
import Ecluse.Core.Package.Pep503 (normalisePyPI)
import Ecluse.Core.Version (Version)
newtype Scope = Scope ShortText
deriving stock (Scope -> Scope -> Bool
(Scope -> Scope -> Bool) -> (Scope -> Scope -> Bool) -> Eq Scope
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Scope -> Scope -> Bool
== :: Scope -> Scope -> Bool
$c/= :: Scope -> Scope -> Bool
/= :: Scope -> Scope -> Bool
Eq, Eq Scope
Eq Scope =>
(Scope -> Scope -> Ordering)
-> (Scope -> Scope -> Bool)
-> (Scope -> Scope -> Bool)
-> (Scope -> Scope -> Bool)
-> (Scope -> Scope -> Bool)
-> (Scope -> Scope -> Scope)
-> (Scope -> Scope -> Scope)
-> Ord Scope
Scope -> Scope -> Bool
Scope -> Scope -> Ordering
Scope -> Scope -> Scope
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 :: Scope -> Scope -> Ordering
compare :: Scope -> Scope -> Ordering
$c< :: Scope -> Scope -> Bool
< :: Scope -> Scope -> Bool
$c<= :: Scope -> Scope -> Bool
<= :: Scope -> Scope -> Bool
$c> :: Scope -> Scope -> Bool
> :: Scope -> Scope -> Bool
$c>= :: Scope -> Scope -> Bool
>= :: Scope -> Scope -> Bool
$cmax :: Scope -> Scope -> Scope
max :: Scope -> Scope -> Scope
$cmin :: Scope -> Scope -> Scope
min :: Scope -> Scope -> Scope
Ord, Int -> Scope -> ShowS
[Scope] -> ShowS
Scope -> String
(Int -> Scope -> ShowS)
-> (Scope -> String) -> ([Scope] -> ShowS) -> Show Scope
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Scope -> ShowS
showsPrec :: Int -> Scope -> ShowS
$cshow :: Scope -> String
show :: Scope -> String
$cshowList :: [Scope] -> ShowS
showList :: [Scope] -> ShowS
Show)
mkScope :: Text -> Scope
mkScope :: Text -> Scope
mkScope Text
raw = ShortText -> Scope
Scope (Text -> ShortText
TS.fromText (Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
raw (Text -> Text -> Maybe Text
T.stripPrefix Text
"@" Text
raw)))
unScope :: Scope -> Text
unScope :: Scope -> Text
unScope (Scope ShortText
s) = ShortText -> Text
TS.toText ShortText
s
renderScope :: Scope -> Text
renderScope :: Scope -> Text
renderScope (Scope ShortText
s) = Text
"@" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ShortText -> Text
TS.toText ShortText
s
data PackageName = PackageName
{ PackageName -> Ecosystem
pkgEcosystem :: Ecosystem
, PackageName -> Maybe Scope
pkgNamespace :: Maybe Scope
, PackageName -> ShortText
pkgCanonical :: ShortText
, PackageName -> ShortText
pkgDisplay :: ShortText
, PackageName -> ShortText
pkgBaseName :: ShortText
}
deriving stock (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
$cshowsPrec :: Int -> PackageName -> ShowS
showsPrec :: Int -> PackageName -> ShowS
$cshow :: PackageName -> String
show :: PackageName -> String
$cshowList :: [PackageName] -> ShowS
showList :: [PackageName] -> ShowS
Show)
nameKey :: PackageName -> (Ecosystem, Maybe Scope, ShortText)
nameKey :: PackageName -> (Ecosystem, Maybe Scope, ShortText)
nameKey PackageName
n = (PackageName -> Ecosystem
pkgEcosystem PackageName
n, PackageName -> Maybe Scope
pkgNamespace PackageName
n, PackageName -> ShortText
pkgCanonical PackageName
n)
instance Eq PackageName where
PackageName
a == :: PackageName -> PackageName -> Bool
== PackageName
b = PackageName -> (Ecosystem, Maybe Scope, ShortText)
nameKey PackageName
a (Ecosystem, Maybe Scope, ShortText)
-> (Ecosystem, Maybe Scope, ShortText) -> Bool
forall a. Eq a => a -> a -> Bool
== PackageName -> (Ecosystem, Maybe Scope, ShortText)
nameKey PackageName
b
instance Ord PackageName where
compare :: PackageName -> PackageName -> Ordering
compare PackageName
a PackageName
b = (Ecosystem, Maybe Scope, ShortText)
-> (Ecosystem, Maybe Scope, ShortText) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (PackageName -> (Ecosystem, Maybe Scope, ShortText)
nameKey PackageName
a) (PackageName -> (Ecosystem, Maybe Scope, ShortText)
nameKey PackageName
b)
mkPackageName :: Ecosystem -> Maybe Scope -> Text -> PackageName
mkPackageName :: Ecosystem -> Maybe Scope -> Text -> PackageName
mkPackageName Ecosystem
eco Maybe Scope
ns Text
raw =
PackageName
{ pkgEcosystem :: Ecosystem
pkgEcosystem = Ecosystem
eco
, pkgNamespace :: Maybe Scope
pkgNamespace = Maybe Scope
ns
, pkgCanonical :: ShortText
pkgCanonical = Text -> ShortText
TS.fromText (Ecosystem -> Text -> Text
canonicalise Ecosystem
eco Text
display)
, pkgDisplay :: ShortText
pkgDisplay = Text -> ShortText
TS.fromText Text
display
, pkgBaseName :: ShortText
pkgBaseName = Text -> ShortText
TS.fromText Text
raw
}
where
display :: Text
display = case Maybe Scope
ns of
Just Scope
s -> Scope -> Text
renderScope Scope
s Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
raw
Maybe Scope
Nothing -> Text
raw
canonicalise :: Ecosystem -> Text -> Text
canonicalise :: Ecosystem -> Text -> Text
canonicalise = \case
Ecosystem
Npm -> Text -> Text
forall a. a -> a
id
Ecosystem
RubyGems -> Text -> Text
forall a. a -> a
id
Ecosystem
PyPI -> Text -> Text
normalisePyPI
renderPackageName :: PackageName -> Text
renderPackageName :: PackageName -> Text
renderPackageName = ShortText -> Text
TS.toText (ShortText -> Text)
-> (PackageName -> ShortText) -> PackageName -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> ShortText
pkgDisplay
unscopedName :: PackageName -> Text
unscopedName :: PackageName -> Text
unscopedName = ShortText -> Text
TS.toText (ShortText -> Text)
-> (PackageName -> ShortText) -> PackageName -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> ShortText
pkgBaseName
isAsciiNameComponent :: Text -> Bool
isAsciiNameComponent :: Text -> Bool
isAsciiNameComponent = (Char -> Bool) -> Text -> Bool
T.all (\Char
ch -> Char -> Bool
isAscii Char
ch Bool -> Bool -> Bool
&& Bool -> Bool
not (Char -> Bool
isControl Char
ch))
data CodeExecSignal
=
NoCodeOnInstall
|
RunsCodeOnInstall Text
|
CodeExecUnknown
deriving stock (CodeExecSignal -> CodeExecSignal -> Bool
(CodeExecSignal -> CodeExecSignal -> Bool)
-> (CodeExecSignal -> CodeExecSignal -> Bool) -> Eq CodeExecSignal
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CodeExecSignal -> CodeExecSignal -> Bool
== :: CodeExecSignal -> CodeExecSignal -> Bool
$c/= :: CodeExecSignal -> CodeExecSignal -> Bool
/= :: CodeExecSignal -> CodeExecSignal -> Bool
Eq, Int -> CodeExecSignal -> ShowS
[CodeExecSignal] -> ShowS
CodeExecSignal -> String
(Int -> CodeExecSignal -> ShowS)
-> (CodeExecSignal -> String)
-> ([CodeExecSignal] -> ShowS)
-> Show CodeExecSignal
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CodeExecSignal -> ShowS
showsPrec :: Int -> CodeExecSignal -> ShowS
$cshow :: CodeExecSignal -> String
show :: CodeExecSignal -> String
$cshowList :: [CodeExecSignal] -> ShowS
showList :: [CodeExecSignal] -> ShowS
Show)
data Availability
=
Available
|
Deprecated Text
|
Yanked (Maybe Text)
deriving stock (Availability -> Availability -> Bool
(Availability -> Availability -> Bool)
-> (Availability -> Availability -> Bool) -> Eq Availability
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Availability -> Availability -> Bool
== :: Availability -> Availability -> Bool
$c/= :: Availability -> Availability -> Bool
/= :: Availability -> Availability -> Bool
Eq, Int -> Availability -> ShowS
[Availability] -> ShowS
Availability -> String
(Int -> Availability -> ShowS)
-> (Availability -> String)
-> ([Availability] -> ShowS)
-> Show Availability
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Availability -> ShowS
showsPrec :: Int -> Availability -> ShowS
$cshow :: Availability -> String
show :: Availability -> String
$cshowList :: [Availability] -> ShowS
showList :: [Availability] -> ShowS
Show)
data Artifact = Artifact
{ Artifact -> EntryKey
artEntryKey :: EntryKey
, Artifact -> Text
artFilename :: Text
, Artifact -> Text
artUrl :: Text
, Artifact -> [Hash]
artHashes :: [Hash]
, Artifact -> Maybe Int
artSize :: Maybe Int
}
deriving stock (Artifact -> Artifact -> Bool
(Artifact -> Artifact -> Bool)
-> (Artifact -> Artifact -> Bool) -> Eq Artifact
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Artifact -> Artifact -> Bool
== :: Artifact -> Artifact -> Bool
$c/= :: Artifact -> Artifact -> Bool
/= :: Artifact -> Artifact -> Bool
Eq, Int -> Artifact -> ShowS
[Artifact] -> ShowS
Artifact -> String
(Int -> Artifact -> ShowS)
-> (Artifact -> String) -> ([Artifact] -> ShowS) -> Show Artifact
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Artifact -> ShowS
showsPrec :: Int -> Artifact -> ShowS
$cshow :: Artifact -> String
show :: Artifact -> String
$cshowList :: [Artifact] -> ShowS
showList :: [Artifact] -> ShowS
Show)
data PackageDetails = PackageDetails
{ PackageDetails -> PackageName
pkgName :: PackageName
, PackageDetails -> Version
pkgVersion :: Version
, PackageDetails -> Maybe UTCTime
pkgPublishedAt :: Maybe UTCTime
, PackageDetails -> CodeExecSignal
pkgInstallCode :: CodeExecSignal
, PackageDetails -> Availability
pkgAvailability :: Availability
, PackageDetails -> NonEmpty Artifact
pkgArtifacts :: NonEmpty Artifact
}
deriving stock (PackageDetails -> PackageDetails -> Bool
(PackageDetails -> PackageDetails -> Bool)
-> (PackageDetails -> PackageDetails -> Bool) -> Eq PackageDetails
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PackageDetails -> PackageDetails -> Bool
== :: PackageDetails -> PackageDetails -> Bool
$c/= :: PackageDetails -> PackageDetails -> Bool
/= :: PackageDetails -> PackageDetails -> Bool
Eq, Int -> PackageDetails -> ShowS
[PackageDetails] -> ShowS
PackageDetails -> String
(Int -> PackageDetails -> ShowS)
-> (PackageDetails -> String)
-> ([PackageDetails] -> ShowS)
-> Show PackageDetails
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PackageDetails -> ShowS
showsPrec :: Int -> PackageDetails -> ShowS
$cshow :: PackageDetails -> String
show :: PackageDetails -> String
$cshowList :: [PackageDetails] -> ShowS
showList :: [PackageDetails] -> ShowS
Show)
data PackageInfo = PackageInfo
{ PackageInfo -> PackageName
infoName :: PackageName
, PackageInfo -> Map Text PackageDetails
infoVersions :: Map Text PackageDetails
, PackageInfo -> Map Text Version
infoDistTags :: Map Text Version
, PackageInfo -> [InvalidEntry]
infoInvalidEntries :: [InvalidEntry]
}
deriving stock (PackageInfo -> PackageInfo -> Bool
(PackageInfo -> PackageInfo -> Bool)
-> (PackageInfo -> PackageInfo -> Bool) -> Eq PackageInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PackageInfo -> PackageInfo -> Bool
== :: PackageInfo -> PackageInfo -> Bool
$c/= :: PackageInfo -> PackageInfo -> Bool
/= :: PackageInfo -> PackageInfo -> Bool
Eq, Int -> PackageInfo -> ShowS
[PackageInfo] -> ShowS
PackageInfo -> String
(Int -> PackageInfo -> ShowS)
-> (PackageInfo -> String)
-> ([PackageInfo] -> ShowS)
-> Show PackageInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PackageInfo -> ShowS
showsPrec :: Int -> PackageInfo -> ShowS
$cshow :: PackageInfo -> String
show :: PackageInfo -> String
$cshowList :: [PackageInfo] -> ShowS
showList :: [PackageInfo] -> ShowS
Show)