{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts, OverloadedStrings, ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-orphans #-}
module Debian.Apt.Index
( update
, Fetcher
, CheckSums(..)
, Compression(..)
, FileTuple
, Size
, controlFromIndex
, controlFromIndex'
, findContentsFiles
, findIndexes
, indexesInRelease
, tupleFromFilePath
) where
import qualified Codec.Compression.GZip as GZip
import qualified Codec.Compression.BZip as BZip
import Control.Lens (over, to, view)
import Control.Monad
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as L
import qualified Data.Digest.Pure.MD5 as MD5
import qualified Data.Digest.Pure.SHA as SHA
import Data.Either (partitionEithers)
import Data.Function
import Data.List as List (null, intercalate, sortBy, isSuffixOf, isPrefixOf)
import qualified Data.Map as M
import Data.Monoid ((<>))
import Data.Text as Text (Text, unpack, concat, lines, words)
import Data.Time
import Debian.Apt.Methods
import Debian.Codename (Codename, codename)
import Debian.Control (formatControl)
import Debian.Control.ByteString
import Debian.Control.Text (decodeControl)
import Debian.Release
import Debian.Sources
import Debian.URI (uriPathLens, uriToString')
import Debian.VendorURI (VendorURI, vendorURI)
import Network.URI
import System.Directory
import System.FilePath ((</>))
import System.Posix.Files
import System.FilePath (takeBaseName)
import Text.ParserCombinators.Parsec.Error
import Text.PrettyPrint (render)
import Distribution.Pretty (pretty)
import Text.Read (readMaybe)
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative (pure, (<$>), (<*>))
#endif
data Compression
= BZ2 | GZ | Uncompressed
deriving (ReadPrec [Compression]
ReadPrec Compression
Int -> ReadS Compression
ReadS [Compression]
(Int -> ReadS Compression)
-> ReadS [Compression]
-> ReadPrec Compression
-> ReadPrec [Compression]
-> Read Compression
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Compression
readsPrec :: Int -> ReadS Compression
$creadList :: ReadS [Compression]
readList :: ReadS [Compression]
$creadPrec :: ReadPrec Compression
readPrec :: ReadPrec Compression
$creadListPrec :: ReadPrec [Compression]
readListPrec :: ReadPrec [Compression]
Read, Int -> Compression -> ShowS
[Compression] -> ShowS
Compression -> [Char]
(Int -> Compression -> ShowS)
-> (Compression -> [Char])
-> ([Compression] -> ShowS)
-> Show Compression
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Compression -> ShowS
showsPrec :: Int -> Compression -> ShowS
$cshow :: Compression -> [Char]
show :: Compression -> [Char]
$cshowList :: [Compression] -> ShowS
showList :: [Compression] -> ShowS
Show, Compression -> Compression -> Bool
(Compression -> Compression -> Bool)
-> (Compression -> Compression -> Bool) -> Eq Compression
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Compression -> Compression -> Bool
== :: Compression -> Compression -> Bool
$c/= :: Compression -> Compression -> Bool
/= :: Compression -> Compression -> Bool
Eq, Eq Compression
Eq Compression
-> (Compression -> Compression -> Ordering)
-> (Compression -> Compression -> Bool)
-> (Compression -> Compression -> Bool)
-> (Compression -> Compression -> Bool)
-> (Compression -> Compression -> Bool)
-> (Compression -> Compression -> Compression)
-> (Compression -> Compression -> Compression)
-> Ord Compression
Compression -> Compression -> Bool
Compression -> Compression -> Ordering
Compression -> Compression -> Compression
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 :: Compression -> Compression -> Ordering
compare :: Compression -> Compression -> Ordering
$c< :: Compression -> Compression -> Bool
< :: Compression -> Compression -> Bool
$c<= :: Compression -> Compression -> Bool
<= :: Compression -> Compression -> Bool
$c> :: Compression -> Compression -> Bool
> :: Compression -> Compression -> Bool
$c>= :: Compression -> Compression -> Bool
>= :: Compression -> Compression -> Bool
$cmax :: Compression -> Compression -> Compression
max :: Compression -> Compression -> Compression
$cmin :: Compression -> Compression -> Compression
min :: Compression -> Compression -> Compression
Ord, Int -> Compression
Compression -> Int
Compression -> [Compression]
Compression -> Compression
Compression -> Compression -> [Compression]
Compression -> Compression -> Compression -> [Compression]
(Compression -> Compression)
-> (Compression -> Compression)
-> (Int -> Compression)
-> (Compression -> Int)
-> (Compression -> [Compression])
-> (Compression -> Compression -> [Compression])
-> (Compression -> Compression -> [Compression])
-> (Compression -> Compression -> Compression -> [Compression])
-> Enum Compression
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Compression -> Compression
succ :: Compression -> Compression
$cpred :: Compression -> Compression
pred :: Compression -> Compression
$ctoEnum :: Int -> Compression
toEnum :: Int -> Compression
$cfromEnum :: Compression -> Int
fromEnum :: Compression -> Int
$cenumFrom :: Compression -> [Compression]
enumFrom :: Compression -> [Compression]
$cenumFromThen :: Compression -> Compression -> [Compression]
enumFromThen :: Compression -> Compression -> [Compression]
$cenumFromTo :: Compression -> Compression -> [Compression]
enumFromTo :: Compression -> Compression -> [Compression]
$cenumFromThenTo :: Compression -> Compression -> Compression -> [Compression]
enumFromThenTo :: Compression -> Compression -> Compression -> [Compression]
Enum, Compression
Compression -> Compression -> Bounded Compression
forall a. a -> a -> Bounded a
$cminBound :: Compression
minBound :: Compression
$cmaxBound :: Compression
maxBound :: Compression
Bounded)
data CheckSums
= CheckSums { CheckSums -> Maybe [Char]
md5sum :: Maybe String
, CheckSums -> Maybe [Char]
sha1 :: Maybe String
, CheckSums -> Maybe [Char]
sha256 :: Maybe String
}
deriving (ReadPrec [CheckSums]
ReadPrec CheckSums
Int -> ReadS CheckSums
ReadS [CheckSums]
(Int -> ReadS CheckSums)
-> ReadS [CheckSums]
-> ReadPrec CheckSums
-> ReadPrec [CheckSums]
-> Read CheckSums
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS CheckSums
readsPrec :: Int -> ReadS CheckSums
$creadList :: ReadS [CheckSums]
readList :: ReadS [CheckSums]
$creadPrec :: ReadPrec CheckSums
readPrec :: ReadPrec CheckSums
$creadListPrec :: ReadPrec [CheckSums]
readListPrec :: ReadPrec [CheckSums]
Read, Int -> CheckSums -> ShowS
[CheckSums] -> ShowS
CheckSums -> [Char]
(Int -> CheckSums -> ShowS)
-> (CheckSums -> [Char])
-> ([CheckSums] -> ShowS)
-> Show CheckSums
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CheckSums -> ShowS
showsPrec :: Int -> CheckSums -> ShowS
$cshow :: CheckSums -> [Char]
show :: CheckSums -> [Char]
$cshowList :: [CheckSums] -> ShowS
showList :: [CheckSums] -> ShowS
Show, CheckSums -> CheckSums -> Bool
(CheckSums -> CheckSums -> Bool)
-> (CheckSums -> CheckSums -> Bool) -> Eq CheckSums
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CheckSums -> CheckSums -> Bool
== :: CheckSums -> CheckSums -> Bool
$c/= :: CheckSums -> CheckSums -> Bool
/= :: CheckSums -> CheckSums -> Bool
Eq)
type Fetcher =
URI ->
FilePath ->
Maybe UTCTime ->
IO Bool
update :: Fetcher
-> FilePath
-> String
-> [DebSource]
-> IO [Maybe (FilePath, Compression)]
update :: Fetcher
-> [Char]
-> [Char]
-> [DebSource]
-> IO [Maybe ([Char], Compression)]
update Fetcher
fetcher [Char]
basePath [Char]
arch [DebSource]
sourcesList =
((URI, [Char]) -> IO (Maybe ([Char], Compression)))
-> [(URI, [Char])] -> IO [Maybe ([Char], Compression)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ((URI -> [Char] -> IO (Maybe ([Char], Compression)))
-> (URI, [Char]) -> IO (Maybe ([Char], Compression))
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((URI -> [Char] -> IO (Maybe ([Char], Compression)))
-> (URI, [Char]) -> IO (Maybe ([Char], Compression)))
-> (URI -> [Char] -> IO (Maybe ([Char], Compression)))
-> (URI, [Char])
-> IO (Maybe ([Char], Compression))
forall a b. (a -> b) -> a -> b
$ Fetcher -> URI -> [Char] -> IO (Maybe ([Char], Compression))
fetchIndex Fetcher
fetcher) (((URI, [Char], DebSource) -> (URI, [Char]))
-> [(URI, [Char], DebSource)] -> [(URI, [Char])]
forall a b. (a -> b) -> [a] -> [b]
map (\(URI
uri, [Char]
fp, DebSource
_) -> (URI
uri, ([Char]
basePath [Char] -> ShowS
</> [Char]
fp))) ((DebSource -> [(URI, [Char], DebSource)])
-> [DebSource] -> [(URI, [Char], DebSource)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Char] -> DebSource -> [(URI, [Char], DebSource)]
indexURIs [Char]
arch) [DebSource]
sourcesList))
fetchIndex :: Fetcher
-> URI
-> FilePath
-> IO (Maybe (FilePath, Compression))
fetchIndex :: Fetcher -> URI -> [Char] -> IO (Maybe ([Char], Compression))
fetchIndex Fetcher
fetcher URI
uri [Char]
localPath =
do let localPath' :: [Char]
localPath' = [Char]
localPath [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
".bz2"
Bool
res <- Fetcher
fetcher (URI
uri { uriPath :: [Char]
uriPath = (URI -> [Char]
uriPath URI
uri) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
".bz2" }) [Char]
localPath' Maybe UTCTime
forall a. Maybe a
Nothing
if Bool
res
then Maybe ([Char], Compression) -> IO (Maybe ([Char], Compression))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ([Char], Compression) -> IO (Maybe ([Char], Compression)))
-> Maybe ([Char], Compression) -> IO (Maybe ([Char], Compression))
forall a b. (a -> b) -> a -> b
$ ([Char], Compression) -> Maybe ([Char], Compression)
forall a. a -> Maybe a
Just ([Char]
localPath', Compression
BZ2)
else do let localPath' :: [Char]
localPath' = [Char]
localPath [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
".gz"
Maybe UTCTime
lm <- [Char] -> IO (Maybe UTCTime)
getLastModified [Char]
localPath'
Bool
res <- Fetcher
fetcher (URI
uri { uriPath :: [Char]
uriPath = (URI -> [Char]
uriPath URI
uri) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
".gz" }) [Char]
localPath' Maybe UTCTime
lm
if Bool
res
then Maybe ([Char], Compression) -> IO (Maybe ([Char], Compression))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ([Char], Compression) -> IO (Maybe ([Char], Compression)))
-> Maybe ([Char], Compression) -> IO (Maybe ([Char], Compression))
forall a b. (a -> b) -> a -> b
$ ([Char], Compression) -> Maybe ([Char], Compression)
forall a. a -> Maybe a
Just ([Char]
localPath', Compression
GZ)
else do Maybe UTCTime
lm <- [Char] -> IO (Maybe UTCTime)
getLastModified [Char]
localPath
Bool
res <- Fetcher
fetcher (URI
uri { uriPath :: [Char]
uriPath = (URI -> [Char]
uriPath URI
uri) }) [Char]
localPath Maybe UTCTime
lm
if Bool
res
then Maybe ([Char], Compression) -> IO (Maybe ([Char], Compression))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (([Char], Compression) -> Maybe ([Char], Compression)
forall a. a -> Maybe a
Just ([Char]
localPath, Compression
Uncompressed))
else Maybe ([Char], Compression) -> IO (Maybe ([Char], Compression))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ([Char], Compression)
forall a. Maybe a
Nothing
indexURIs :: String
-> DebSource
-> [(URI, FilePath, DebSource)]
indexURIs :: [Char] -> DebSource -> [(URI, [Char], DebSource)]
indexURIs [Char]
arch DebSource
debSource =
(Section -> (URI, [Char], DebSource))
-> [Section] -> [(URI, [Char], DebSource)]
forall a b. (a -> b) -> [a] -> [b]
map (\ Section
section -> let (URI
uri, [Char]
fp) = SourceType
-> [Char] -> VendorURI -> Codename -> Section -> (URI, [Char])
calcPath (Getting SourceType DebSource SourceType -> DebSource -> SourceType
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting SourceType DebSource SourceType
Lens' DebSource SourceType
sourceType DebSource
debSource) [Char]
arch VendorURI
baseURI Codename
release Section
section
in (URI
uri,[Char]
fp, DebSource
debSource { _sourceDist :: Either [Char] (Codename, [Section])
_sourceDist = ((Codename, [Section]) -> Either [Char] (Codename, [Section])
forall a b. b -> Either a b
Right (Codename
release, [Section
section])) }) ) [Section]
sections
where
baseURI :: VendorURI
baseURI = Getting VendorURI DebSource VendorURI -> DebSource -> VendorURI
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting VendorURI DebSource VendorURI
Lens' DebSource VendorURI
sourceUri DebSource
debSource
(Codename
release, [Section]
sections) =
([Char] -> (Codename, [Section]))
-> ((Codename, [Section]) -> (Codename, [Section]))
-> Either [Char] (Codename, [Section])
-> (Codename, [Section])
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ([Char] -> [Char] -> (Codename, [Section])
forall a. HasCallStack => [Char] -> a
error ([Char] -> [Char] -> (Codename, [Section]))
-> [Char] -> [Char] -> (Codename, [Section])
forall a b. (a -> b) -> a -> b
$ [Char]
"indexURIs: support not implemented for exact path: " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Doc -> [Char]
render (DebSource -> Doc
forall a. Pretty a => a -> Doc
pretty DebSource
debSource)) (Codename, [Section]) -> (Codename, [Section])
forall a. a -> a
id (Getting
(Either [Char] (Codename, [Section]))
DebSource
(Either [Char] (Codename, [Section]))
-> DebSource -> Either [Char] (Codename, [Section])
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting
(Either [Char] (Codename, [Section]))
DebSource
(Either [Char] (Codename, [Section]))
Lens' DebSource (Either [Char] (Codename, [Section]))
sourceDist DebSource
debSource)
calcPath :: SourceType
-> String
-> VendorURI
-> Codename
-> Section
-> (URI, [Char])
calcPath :: SourceType
-> [Char] -> VendorURI -> Codename -> Section -> (URI, [Char])
calcPath SourceType
srcType [Char]
arch VendorURI
baseURI Codename
release Section
section =
let indexPath :: [Char]
indexPath = case SourceType
srcType of
SourceType
DebSrc -> [Char]
"source/Sources"
SourceType
Deb -> [Char]
"binary-" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
arch [Char] -> ShowS
</> [Char]
"Packages"
uri' :: URI
uri' = ASetter URI URI [Char] [Char] -> ShowS -> URI -> URI
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter URI URI [Char] [Char]
Lens' URI [Char]
uriPathLens (\[Char]
path -> [Char]
path [Char] -> ShowS
</> [Char]
"dists" [Char] -> ShowS
</> Codename -> [Char]
codename Codename
release [Char] -> ShowS
</> Section -> [Char]
sectionName' Section
section [Char] -> ShowS
</> [Char]
indexPath) (Getting URI VendorURI URI -> VendorURI -> URI
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting URI VendorURI URI
Iso' VendorURI URI
vendorURI VendorURI
baseURI)
path :: [Char]
path = Getting [Char] URI [Char] -> URI -> [Char]
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting [Char] URI [Char]
Lens' URI [Char]
uriPathLens URI
uri'
in (URI
uri', ShowS
addPrefix (ShowS
escapePath [Char]
path))
where
addPrefix :: ShowS
addPrefix [Char]
s = [Char] -> Maybe [Char] -> Maybe [Char] -> Maybe [Char] -> ShowS
forall {a} {a}.
(Eq a, IsString a) =>
a -> Maybe [Char] -> Maybe a -> Maybe [Char] -> ShowS
prefix [Char]
scheme Maybe [Char]
user' Maybe [Char]
pass' Maybe [Char]
reg [Char]
port [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
s
prefix :: a -> Maybe [Char] -> Maybe a -> Maybe [Char] -> ShowS
prefix a
"http:" (Just [Char]
user) Maybe a
Nothing (Just [Char]
host) [Char]
port = [Char]
user [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
host [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
port
prefix a
"http:" Maybe [Char]
_ Maybe a
_ (Just [Char]
host) [Char]
port = [Char]
host [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
port
prefix a
"ftp:" Maybe [Char]
_ Maybe a
_ (Just [Char]
host) [Char]
_ = [Char]
host
prefix a
"file:" Maybe [Char]
Nothing Maybe a
Nothing Maybe [Char]
Nothing [Char]
"" = [Char]
""
prefix a
"ssh:" (Just [Char]
user) Maybe a
Nothing (Just [Char]
host) [Char]
port = [Char]
user [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
host [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
port
prefix a
"ssh:" Maybe [Char]
_ Maybe a
_ (Just [Char]
host) [Char]
port = [Char]
host [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
port
prefix a
_ Maybe [Char]
_ Maybe a
_ Maybe [Char]
_ [Char]
_ = ShowS
forall a. HasCallStack => [Char] -> a
error ([Char]
"calcPath: unsupported uri: " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Getting [Char] VendorURI [Char] -> VendorURI -> [Char]
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((URI -> Const [Char] URI) -> VendorURI -> Const [Char] VendorURI
Iso' VendorURI URI
vendorURI ((URI -> Const [Char] URI) -> VendorURI -> Const [Char] VendorURI)
-> Getting [Char] URI [Char] -> Getting [Char] VendorURI [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (URI -> [Char]) -> Getting [Char] URI [Char]
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to URI -> [Char]
uriToString') VendorURI
baseURI)
user' :: Maybe [Char]
user' = [Char] -> Maybe [Char]
maybeOfString [Char]
user
pass' :: Maybe [Char]
pass' = [Char] -> Maybe [Char]
maybeOfString [Char]
pass
([Char]
user, [Char]
pass) = (Char -> Bool) -> [Char] -> ([Char], [Char])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
':') [Char]
userpass
userpass :: [Char]
userpass = [Char] -> (URIAuth -> [Char]) -> Maybe URIAuth -> [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Char]
"" URIAuth -> [Char]
uriUserInfo Maybe URIAuth
auth
reg :: Maybe [Char]
reg = [Char] -> Maybe [Char]
maybeOfString ([Char] -> Maybe [Char]) -> [Char] -> Maybe [Char]
forall a b. (a -> b) -> a -> b
$ [Char] -> (URIAuth -> [Char]) -> Maybe URIAuth -> [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Char]
"" URIAuth -> [Char]
uriRegName Maybe URIAuth
auth
port :: [Char]
port = [Char] -> (URIAuth -> [Char]) -> Maybe URIAuth -> [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Char]
"" URIAuth -> [Char]
uriPort Maybe URIAuth
auth
scheme :: [Char]
scheme = Getting [Char] VendorURI [Char] -> VendorURI -> [Char]
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((URI -> Const [Char] URI) -> VendorURI -> Const [Char] VendorURI
Iso' VendorURI URI
vendorURI ((URI -> Const [Char] URI) -> VendorURI -> Const [Char] VendorURI)
-> Getting [Char] URI [Char] -> Getting [Char] VendorURI [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (URI -> [Char]) -> Getting [Char] URI [Char]
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to URI -> [Char]
uriScheme) VendorURI
baseURI
auth :: Maybe URIAuth
auth = Getting (Maybe URIAuth) VendorURI (Maybe URIAuth)
-> VendorURI -> Maybe URIAuth
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((URI -> Const (Maybe URIAuth) URI)
-> VendorURI -> Const (Maybe URIAuth) VendorURI
Iso' VendorURI URI
vendorURI ((URI -> Const (Maybe URIAuth) URI)
-> VendorURI -> Const (Maybe URIAuth) VendorURI)
-> ((Maybe URIAuth -> Const (Maybe URIAuth) (Maybe URIAuth))
-> URI -> Const (Maybe URIAuth) URI)
-> Getting (Maybe URIAuth) VendorURI (Maybe URIAuth)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (URI -> Maybe URIAuth)
-> (Maybe URIAuth -> Const (Maybe URIAuth) (Maybe URIAuth))
-> URI
-> Const (Maybe URIAuth) URI
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to URI -> Maybe URIAuth
uriAuthority) VendorURI
baseURI
escapePath :: String -> String
escapePath :: ShowS
escapePath [Char]
s = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"_" ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> [Char] -> [[Char]]
forall a. Eq a => (a -> Bool) -> [a] -> [[a]]
wordsBy (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/') [Char]
s
maybeOfString :: String -> Maybe String
maybeOfString :: [Char] -> Maybe [Char]
maybeOfString [Char]
"" = Maybe [Char]
forall a. Maybe a
Nothing
maybeOfString [Char]
s = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
s
wordsBy :: Eq a => (a -> Bool) -> [a] -> [[a]]
wordsBy :: forall a. Eq a => (a -> Bool) -> [a] -> [[a]]
wordsBy a -> Bool
p [a]
s =
case ((a -> Bool) -> [a] -> ([a], [a])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break a -> Bool
p [a]
s) of
([a]
s, []) -> [[a]
s]
([a]
h, [a]
t) -> [a]
h [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: (a -> Bool) -> [a] -> [[a]]
forall a. Eq a => (a -> Bool) -> [a] -> [[a]]
wordsBy a -> Bool
p (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
1 [a]
t)
controlFromIndex :: Compression -> FilePath -> L.ByteString -> Either ParseError (Control' Text)
controlFromIndex :: Compression
-> [Char] -> ByteString -> Either ParseError (Control' Text)
controlFromIndex Compression
GZ [Char]
path ByteString
s = (ParseError -> Either ParseError (Control' Text))
-> (Control -> Either ParseError (Control' Text))
-> Either ParseError Control
-> Either ParseError (Control' Text)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ParseError -> Either ParseError (Control' Text)
forall a b. a -> Either a b
Left (Control' Text -> Either ParseError (Control' Text)
forall a b. b -> Either a b
Right (Control' Text -> Either ParseError (Control' Text))
-> (Control -> Control' Text)
-> Control
-> Either ParseError (Control' Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Control -> Control' Text
decodeControl) (Either ParseError Control -> Either ParseError (Control' Text))
-> (ByteString -> Either ParseError Control)
-> ByteString
-> Either ParseError (Control' Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ByteString -> Either ParseError Control
forall a.
ControlFunctions a =>
[Char] -> a -> Either ParseError (Control' a)
parseControl [Char]
path (ByteString -> Either ParseError Control)
-> (ByteString -> ByteString)
-> ByteString
-> Either ParseError Control
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
B.concat ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks (ByteString -> [ByteString])
-> (ByteString -> ByteString) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
GZip.decompress (ByteString -> Either ParseError (Control' Text))
-> ByteString -> Either ParseError (Control' Text)
forall a b. (a -> b) -> a -> b
$ ByteString
s
controlFromIndex Compression
BZ2 [Char]
path ByteString
s = (ParseError -> Either ParseError (Control' Text))
-> (Control -> Either ParseError (Control' Text))
-> Either ParseError Control
-> Either ParseError (Control' Text)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ParseError -> Either ParseError (Control' Text)
forall a b. a -> Either a b
Left (Control' Text -> Either ParseError (Control' Text)
forall a b. b -> Either a b
Right (Control' Text -> Either ParseError (Control' Text))
-> (Control -> Control' Text)
-> Control
-> Either ParseError (Control' Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Control -> Control' Text
decodeControl) (Either ParseError Control -> Either ParseError (Control' Text))
-> (ByteString -> Either ParseError Control)
-> ByteString
-> Either ParseError (Control' Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ByteString -> Either ParseError Control
forall a.
ControlFunctions a =>
[Char] -> a -> Either ParseError (Control' a)
parseControl [Char]
path (ByteString -> Either ParseError Control)
-> (ByteString -> ByteString)
-> ByteString
-> Either ParseError Control
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
B.concat ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks (ByteString -> [ByteString])
-> (ByteString -> ByteString) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
BZip.decompress (ByteString -> Either ParseError (Control' Text))
-> ByteString -> Either ParseError (Control' Text)
forall a b. (a -> b) -> a -> b
$ ByteString
s
controlFromIndex Compression
Uncompressed [Char]
path ByteString
s = (ParseError -> Either ParseError (Control' Text))
-> (Control -> Either ParseError (Control' Text))
-> Either ParseError Control
-> Either ParseError (Control' Text)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ParseError -> Either ParseError (Control' Text)
forall a b. a -> Either a b
Left (Control' Text -> Either ParseError (Control' Text)
forall a b. b -> Either a b
Right (Control' Text -> Either ParseError (Control' Text))
-> (Control -> Control' Text)
-> Control
-> Either ParseError (Control' Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Control -> Control' Text
decodeControl) (Either ParseError Control -> Either ParseError (Control' Text))
-> (ByteString -> Either ParseError Control)
-> ByteString
-> Either ParseError (Control' Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ByteString -> Either ParseError Control
forall a.
ControlFunctions a =>
[Char] -> a -> Either ParseError (Control' a)
parseControl [Char]
path (ByteString -> Either ParseError Control)
-> (ByteString -> ByteString)
-> ByteString
-> Either ParseError Control
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
B.concat ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
L.toChunks (ByteString -> Either ParseError (Control' Text))
-> ByteString -> Either ParseError (Control' Text)
forall a b. (a -> b) -> a -> b
$ ByteString
s
controlFromIndex' :: Compression -> FilePath -> IO (Either ParseError (Control' Text))
controlFromIndex' :: Compression -> [Char] -> IO (Either ParseError (Control' Text))
controlFromIndex' Compression
compression [Char]
path = [Char] -> IO ByteString
L.readFile [Char]
path IO ByteString
-> (ByteString -> IO (Either ParseError (Control' Text)))
-> IO (Either ParseError (Control' Text))
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either ParseError (Control' Text)
-> IO (Either ParseError (Control' Text))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either ParseError (Control' Text)
-> IO (Either ParseError (Control' Text)))
-> (ByteString -> Either ParseError (Control' Text))
-> ByteString
-> IO (Either ParseError (Control' Text))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Compression
-> [Char] -> ByteString -> Either ParseError (Control' Text)
controlFromIndex Compression
compression [Char]
path
type Size = Integer
type FileTuple = (CheckSums, Size, FilePath)
groupIndexes :: [FileTuple] -> [(FilePath, [(FileTuple, Compression)])]
groupIndexes :: [FileTuple] -> [([Char], [(FileTuple, Compression)])]
groupIndexes [FileTuple]
indexFiles =
Map [Char] [(FileTuple, Compression)]
-> [([Char], [(FileTuple, Compression)])]
forall k a. Map k a -> [(k, a)]
M.toList (Map [Char] [(FileTuple, Compression)]
-> [([Char], [(FileTuple, Compression)])])
-> Map [Char] [(FileTuple, Compression)]
-> [([Char], [(FileTuple, Compression)])]
forall a b. (a -> b) -> a -> b
$ ([(FileTuple, Compression)]
-> [(FileTuple, Compression)] -> [(FileTuple, Compression)])
-> [([Char], [(FileTuple, Compression)])]
-> Map [Char] [(FileTuple, Compression)]
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
M.fromListWith [(FileTuple, Compression)]
-> [(FileTuple, Compression)] -> [(FileTuple, Compression)]
forall {a}.
[(a, Compression)] -> [(a, Compression)] -> [(a, Compression)]
combine ([([Char], [(FileTuple, Compression)])]
-> Map [Char] [(FileTuple, Compression)])
-> [([Char], [(FileTuple, Compression)])]
-> Map [Char] [(FileTuple, Compression)]
forall a b. (a -> b) -> a -> b
$ (FileTuple -> ([Char], [(FileTuple, Compression)]))
-> [FileTuple] -> [([Char], [(FileTuple, Compression)])]
forall a b. (a -> b) -> [a] -> [b]
map FileTuple -> ([Char], [(FileTuple, Compression)])
forall {a} {b}.
(a, b, [Char]) -> ([Char], [((a, b, [Char]), Compression)])
makeKV [FileTuple]
indexFiles
where
makeKV :: (a, b, [Char]) -> ([Char], [((a, b, [Char]), Compression)])
makeKV fileTuple :: (a, b, [Char])
fileTuple@(a
_,b
_,[Char]
fp) =
let ([Char]
name, Compression
compressionMethod) = [Char] -> ([Char], Compression)
uncompressedName [Char]
fp
in
([Char]
name, [((a, b, [Char])
fileTuple, Compression
compressionMethod)])
combine :: [(a, Compression)] -> [(a, Compression)] -> [(a, Compression)]
combine = (\[(a, Compression)]
x [(a, Compression)]
y -> ((a, Compression) -> (a, Compression) -> Ordering)
-> [(a, Compression)] -> [(a, Compression)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Compression -> Compression -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Compression -> Compression -> Ordering)
-> ((a, Compression) -> Compression)
-> (a, Compression)
-> (a, Compression)
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (a, Compression) -> Compression
forall a b. (a, b) -> b
snd) ([(a, Compression)]
x [(a, Compression)] -> [(a, Compression)] -> [(a, Compression)]
forall a. [a] -> [a] -> [a]
++ [(a, Compression)]
y))
filterExists :: FilePath -> (FilePath, [(FileTuple, Compression)]) -> IO (FilePath, [(FileTuple, Compression)])
filterExists :: [Char]
-> ([Char], [(FileTuple, Compression)])
-> IO ([Char], [(FileTuple, Compression)])
filterExists [Char]
distDir ([Char]
fp, [(FileTuple, Compression)]
alternatives) =
do [(FileTuple, Compression)]
e <- ((FileTuple, Compression) -> IO Bool)
-> [(FileTuple, Compression)] -> IO [(FileTuple, Compression)]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM ( \((CheckSums
_,Size
_,[Char]
fp),Compression
_) -> [Char] -> IO Bool
fileExist ([Char]
distDir [Char] -> ShowS
</> [Char]
fp)) [(FileTuple, Compression)]
alternatives
([Char], [(FileTuple, Compression)])
-> IO ([Char], [(FileTuple, Compression)])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char]
fp, [(FileTuple, Compression)]
e)
findIndexes :: FilePath -> String -> [FileTuple] -> IO [(FileTuple, Compression)]
findIndexes :: [Char] -> [Char] -> [FileTuple] -> IO [(FileTuple, Compression)]
findIndexes [Char]
distDir [Char]
iType [FileTuple]
controlFiles =
let indexes :: [([Char], [(FileTuple, Compression)])]
indexes = [FileTuple] -> [([Char], [(FileTuple, Compression)])]
groupIndexes [FileTuple]
controlFiles
in
do [([Char], [(FileTuple, Compression)])]
indexes' <- (([Char], [(FileTuple, Compression)])
-> IO ([Char], [(FileTuple, Compression)]))
-> [([Char], [(FileTuple, Compression)])]
-> IO [([Char], [(FileTuple, Compression)])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ([Char]
-> ([Char], [(FileTuple, Compression)])
-> IO ([Char], [(FileTuple, Compression)])
filterExists [Char]
distDir) ((([Char], [(FileTuple, Compression)]) -> Bool)
-> [([Char], [(FileTuple, Compression)])]
-> [([Char], [(FileTuple, Compression)])]
forall a. (a -> Bool) -> [a] -> [a]
filter ([Char] -> ([Char], [(FileTuple, Compression)]) -> Bool
forall {a} {b}. Eq a => [a] -> ([a], b) -> Bool
isType [Char]
iType) [([Char], [(FileTuple, Compression)])]
indexes)
[(FileTuple, Compression)] -> IO [(FileTuple, Compression)]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(FileTuple, Compression)] -> IO [(FileTuple, Compression)])
-> [(FileTuple, Compression)] -> IO [(FileTuple, Compression)]
forall a b. (a -> b) -> a -> b
$ (([Char], [(FileTuple, Compression)]) -> (FileTuple, Compression))
-> [([Char], [(FileTuple, Compression)])]
-> [(FileTuple, Compression)]
forall a b. (a -> b) -> [a] -> [b]
map ([(FileTuple, Compression)] -> (FileTuple, Compression)
forall a. HasCallStack => [a] -> a
head ([(FileTuple, Compression)] -> (FileTuple, Compression))
-> (([Char], [(FileTuple, Compression)])
-> [(FileTuple, Compression)])
-> ([Char], [(FileTuple, Compression)])
-> (FileTuple, Compression)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [(FileTuple, Compression)]) -> [(FileTuple, Compression)]
forall a b. (a, b) -> b
snd) ((([Char], [(FileTuple, Compression)]) -> Bool)
-> [([Char], [(FileTuple, Compression)])]
-> [([Char], [(FileTuple, Compression)])]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (([Char], [(FileTuple, Compression)]) -> Bool)
-> ([Char], [(FileTuple, Compression)])
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(FileTuple, Compression)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
List.null ([(FileTuple, Compression)] -> Bool)
-> (([Char], [(FileTuple, Compression)])
-> [(FileTuple, Compression)])
-> ([Char], [(FileTuple, Compression)])
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [(FileTuple, Compression)]) -> [(FileTuple, Compression)]
forall a b. (a, b) -> b
snd) [([Char], [(FileTuple, Compression)])]
indexes')
where
isType :: [a] -> ([a], b) -> Bool
isType [a]
iType ([a]
fp, b
_) = [a]
iType [a] -> [a] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf` [a]
fp
uncompressedName :: FilePath -> (FilePath, Compression)
uncompressedName :: [Char] -> ([Char], Compression)
uncompressedName [Char]
fp
| [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf [Char]
".gz" [Char]
fp = (ShowS
forall a. [a] -> [a]
reverse ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> ShowS
forall a. Int -> [a] -> [a]
drop Int
3) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
reverse ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ [Char]
fp, Compression
GZ)
| [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf [Char]
".bz2" [Char]
fp = (ShowS
forall a. [a] -> [a]
reverse ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> ShowS
forall a. Int -> [a] -> [a]
drop Int
4) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
reverse ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ [Char]
fp, Compression
BZ2)
| Bool
otherwise = ([Char]
fp, Compression
Uncompressed)
indexesInRelease :: (FilePath -> Bool)
-> Control' Text
-> [(CheckSums, Integer, FilePath)]
indexesInRelease :: ([Char] -> Bool) -> Control' Text -> [FileTuple]
indexesInRelease [Char] -> Bool
filterp (Control [Paragraph' Text
p]) =
case ([[Char]], [[FileTuple]])
attempts of
([[Char]]
_, [FileTuple]
fps:[[FileTuple]]
_) -> (FileTuple -> Bool) -> [FileTuple] -> [FileTuple]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(CheckSums
_,Size
_,[Char]
fp) -> [Char] -> Bool
filterp [Char]
fp) [FileTuple]
fps
([[Char]]
errs, [[FileTuple]]
_) -> [Char] -> [FileTuple]
forall a. HasCallStack => [Char] -> a
error ([Char] -> [FileTuple]) -> [Char] -> [FileTuple]
forall a b. (a -> b) -> a -> b
$ [Char]
"No indexes in release: " [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
", " [[Char]]
errs
where
attempts :: ([[Char]], [[FileTuple]])
attempts = [Either [Char] [FileTuple]] -> ([[Char]], [[FileTuple]])
forall a b. [Either a b] -> ([a], [b])
partitionEithers
[ ([Char] -> CheckSums) -> [Char] -> Either [Char] [FileTuple]
attempt [Char] -> CheckSums
makeSHA256 [Char]
"SHA256"
, ([Char] -> CheckSums) -> [Char] -> Either [Char] [FileTuple]
attempt [Char] -> CheckSums
makeSHA1 [Char]
"SHA1"
, ([Char] -> CheckSums) -> [Char] -> Either [Char] [FileTuple]
attempt [Char] -> CheckSums
makeMD5 [Char]
"MD5Sum" ]
attempt :: ([Char] -> CheckSums) -> [Char] -> Either [Char] [FileTuple]
attempt [Char] -> CheckSums
mksum [Char]
fn = ([Char] -> CheckSums)
-> [(Text, Text, Text)] -> Either [Char] [FileTuple]
makeTuples [Char] -> CheckSums
mksum ([(Text, Text, Text)] -> Either [Char] [FileTuple])
-> Either [Char] [(Text, Text, Text)] -> Either [Char] [FileTuple]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Text -> Either [Char] [(Text, Text, Text)]
makeTriples (Text -> Either [Char] [(Text, Text, Text)])
-> Either [Char] Text -> Either [Char] [(Text, Text, Text)]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<
Either [Char] Text
-> (Text -> Either [Char] Text) -> Maybe Text -> Either [Char] Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([Char] -> Either [Char] Text
forall a b. a -> Either a b
Left ([Char] -> Either [Char] Text) -> [Char] -> Either [Char] Text
forall a b. (a -> b) -> a -> b
$ [Char]
"No " [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char]
fn [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char]
" Field") Text -> Either [Char] Text
forall a b. b -> Either a b
Right ([Char] -> Paragraph' Text -> Maybe Text
forall a. ControlFunctions a => [Char] -> Paragraph' a -> Maybe a
fieldValue [Char]
fn Paragraph' Text
p)
makeSHA256 :: [Char] -> CheckSums
makeSHA256 [Char]
s = CheckSums {md5sum :: Maybe [Char]
md5sum = Maybe [Char]
forall a. Maybe a
Nothing, sha1 :: Maybe [Char]
sha1 = Maybe [Char]
forall a. Maybe a
Nothing, sha256 :: Maybe [Char]
sha256 = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
s}
makeSHA1 :: [Char] -> CheckSums
makeSHA1 [Char]
s = CheckSums {md5sum :: Maybe [Char]
md5sum = Maybe [Char]
forall a. Maybe a
Nothing, sha1 :: Maybe [Char]
sha1 = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
s, sha256 :: Maybe [Char]
sha256 = Maybe [Char]
forall a. Maybe a
Nothing}
makeMD5 :: [Char] -> CheckSums
makeMD5 [Char]
s = CheckSums {md5sum :: Maybe [Char]
md5sum = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
s, sha1 :: Maybe [Char]
sha1 = Maybe [Char]
forall a. Maybe a
Nothing, sha256 :: Maybe [Char]
sha256 = Maybe [Char]
forall a. Maybe a
Nothing}
makeTuples :: (String -> CheckSums) -> [(Text, Text, Text)] -> Either String [(CheckSums, Integer, FilePath)]
makeTuples :: ([Char] -> CheckSums)
-> [(Text, Text, Text)] -> Either [Char] [FileTuple]
makeTuples [Char] -> CheckSums
mk [(Text, Text, Text)]
triples =
case [Either [Char] FileTuple] -> ([[Char]], [FileTuple])
forall a b. [Either a b] -> ([a], [b])
partitionEithers (((Text, Text, Text) -> Either [Char] FileTuple)
-> [(Text, Text, Text)] -> [Either [Char] FileTuple]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (([Char] -> CheckSums)
-> (Text, Text, Text) -> Either [Char] FileTuple
makeTuple [Char] -> CheckSums
mk) [(Text, Text, Text)]
triples) of
([], [FileTuple]
tuples) -> [FileTuple] -> Either [Char] [FileTuple]
forall a b. b -> Either a b
Right [FileTuple]
tuples
([Char]
s : [[Char]]
_, [FileTuple]
_) -> [Char] -> Either [Char] [FileTuple]
forall a b. a -> Either a b
Left [Char]
s
makeTuple :: (String -> CheckSums) -> (Text, Text, Text) -> Either String (CheckSums, Integer, FilePath)
makeTuple :: ([Char] -> CheckSums)
-> (Text, Text, Text) -> Either [Char] FileTuple
makeTuple [Char] -> CheckSums
mk (Text
sum, Text
size, Text
fp) =
(,,) (CheckSums -> Size -> [Char] -> FileTuple)
-> Either [Char] CheckSums
-> Either [Char] (Size -> [Char] -> FileTuple)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CheckSums -> Either [Char] CheckSums
forall a. a -> Either [Char] a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Char] -> CheckSums
mk (Text -> [Char]
Text.unpack Text
sum))
Either [Char] (Size -> [Char] -> FileTuple)
-> Either [Char] Size -> Either [Char] ([Char] -> FileTuple)
forall a b.
Either [Char] (a -> b) -> Either [Char] a -> Either [Char] b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Either [Char] Size
-> (Size -> Either [Char] Size) -> Maybe Size -> Either [Char] Size
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([Char] -> Either [Char] Size
forall a b. a -> Either a b
Left ([Char]
"Invalid size field: " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
forall a. Show a => a -> [Char]
show Text
size)) Size -> Either [Char] Size
forall a b. b -> Either a b
Right ([Char] -> Maybe Size
forall a. Read a => [Char] -> Maybe a
readMaybe (Text -> [Char]
Text.unpack Text
size))
Either [Char] ([Char] -> FileTuple)
-> Either [Char] [Char] -> Either [Char] FileTuple
forall a b.
Either [Char] (a -> b) -> Either [Char] a -> Either [Char] b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Char] -> Either [Char] [Char]
forall a. a -> Either [Char] a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> [Char]
Text.unpack Text
fp)
makeTriples :: Text -> Either String [(Text, Text, Text)]
makeTriples :: Text -> Either [Char] [(Text, Text, Text)]
makeTriples Text
t = case [Either [Char] (Text, Text, Text)]
-> ([[Char]], [(Text, Text, Text)])
forall a b. [Either a b] -> ([a], [b])
partitionEithers ((Text -> Either [Char] (Text, Text, Text))
-> [Text] -> [Either [Char] (Text, Text, Text)]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Either [Char] (Text, Text, Text)
makeTriple (Text -> [Text]
Text.lines Text
t)) of
([], [(Text, Text, Text)]
xs) -> [(Text, Text, Text)] -> Either [Char] [(Text, Text, Text)]
forall a b. b -> Either a b
Right [(Text, Text, Text)]
xs
([Char]
s : [[Char]]
_, [(Text, Text, Text)]
_) -> [Char] -> Either [Char] [(Text, Text, Text)]
forall a b. a -> Either a b
Left [Char]
s
makeTriple :: Text -> Either String (Text, Text, Text)
makeTriple :: Text -> Either [Char] (Text, Text, Text)
makeTriple Text
t = case Text -> [Text]
Text.words Text
t of
[Text
a, Text
b, Text
c] -> (Text, Text, Text) -> Either [Char] (Text, Text, Text)
forall a b. b -> Either a b
Right (Text
a, Text
b, Text
c)
[Text]
_ -> [Char] -> Either [Char] (Text, Text, Text)
forall a b. a -> Either a b
Left ([Char]
"Invalid checksum line: " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
forall a. Show a => a -> [Char]
show Text
t)
indexesInRelease [Char] -> Bool
_ Control' Text
x = [Char] -> [FileTuple]
forall a. HasCallStack => [Char] -> a
error ([Char] -> [FileTuple]) -> [Char] -> [FileTuple]
forall a b. (a -> b) -> a -> b
$ [Char]
"Invalid release file: " [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> [Char]
Text.unpack ([Text] -> Text
Text.concat (Control' Text -> [Text]
formatControl Control' Text
x))
tupleFromFilePath :: FilePath -> FilePath -> IO (Maybe FileTuple)
tupleFromFilePath :: [Char] -> [Char] -> IO (Maybe FileTuple)
tupleFromFilePath [Char]
basePath [Char]
fp =
do Bool
e <- [Char] -> IO Bool
fileExist ([Char]
basePath [Char] -> ShowS
</> [Char]
fp)
if Bool -> Bool
not Bool
e
then Maybe FileTuple -> IO (Maybe FileTuple)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe FileTuple
forall a. Maybe a
Nothing
else do Size
size <- [Char] -> IO FileStatus
getFileStatus ([Char]
basePath [Char] -> ShowS
</> [Char]
fp) IO FileStatus -> (FileStatus -> IO Size) -> IO Size
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Size -> IO Size
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Size -> IO Size) -> (FileStatus -> Size) -> FileStatus -> IO Size
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileOffset -> Size
forall a b. (Integral a, Num b) => a -> b
fromIntegral (FileOffset -> Size)
-> (FileStatus -> FileOffset) -> FileStatus -> Size
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileStatus -> FileOffset
fileSize
[Char]
md5 <- [Char] -> IO ByteString
L.readFile ([Char]
basePath [Char] -> ShowS
</> [Char]
fp) IO ByteString -> (ByteString -> IO [Char]) -> IO [Char]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [Char] -> IO [Char]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> IO [Char])
-> (ByteString -> [Char]) -> ByteString -> IO [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MD5Digest -> [Char]
forall a. Show a => a -> [Char]
show (MD5Digest -> [Char])
-> (ByteString -> MD5Digest) -> ByteString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> MD5Digest
MD5.md5
[Char]
sha1 <- [Char] -> IO ByteString
L.readFile ([Char]
basePath [Char] -> ShowS
</> [Char]
fp) IO ByteString -> (ByteString -> IO [Char]) -> IO [Char]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [Char] -> IO [Char]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> IO [Char])
-> (ByteString -> [Char]) -> ByteString -> IO [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest SHA1State -> [Char]
forall a. Show a => a -> [Char]
show (Digest SHA1State -> [Char])
-> (ByteString -> Digest SHA1State) -> ByteString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Digest SHA1State
SHA.sha1
[Char]
sha256 <- [Char] -> IO ByteString
L.readFile ([Char]
basePath [Char] -> ShowS
</> [Char]
fp) IO ByteString -> (ByteString -> IO [Char]) -> IO [Char]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [Char] -> IO [Char]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> IO [Char])
-> (ByteString -> [Char]) -> ByteString -> IO [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest SHA256State -> [Char]
forall a. Show a => a -> [Char]
show (Digest SHA256State -> [Char])
-> (ByteString -> Digest SHA256State) -> ByteString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Digest SHA256State
SHA.sha256
Maybe FileTuple -> IO (Maybe FileTuple)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe FileTuple -> IO (Maybe FileTuple))
-> Maybe FileTuple -> IO (Maybe FileTuple)
forall a b. (a -> b) -> a -> b
$ FileTuple -> Maybe FileTuple
forall a. a -> Maybe a
Just (CheckSums { md5sum :: Maybe [Char]
md5sum = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
md5, sha1 :: Maybe [Char]
sha1 = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
sha1, sha256 :: Maybe [Char]
sha256 = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
sha256 }, Size
size, [Char]
fp)
findContentsFiles :: (FilePath -> Bool) -> FilePath -> IO [FilePath]
findContentsFiles :: ([Char] -> Bool) -> [Char] -> IO [[Char]]
findContentsFiles [Char] -> Bool
filterP [Char]
distDir =
do [[Char]]
files <- [Char] -> IO [[Char]]
getDirectoryContents [Char]
distDir
[[Char]] -> IO [[Char]]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([[Char]] -> IO [[Char]]) -> [[Char]] -> IO [[Char]]
forall a b. (a -> b) -> a -> b
$ ([Char] -> Bool) -> [[Char]] -> [[Char]]
forall a. (a -> Bool) -> [a] -> [a]
filter [Char] -> Bool
filterP ([[Char]] -> [[Char]]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ ([Char] -> Bool) -> [[Char]] -> [[Char]]
forall a. (a -> Bool) -> [a] -> [a]
filter ([Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isPrefixOf [Char]
"Contents-" ([Char] -> Bool) -> ShowS -> [Char] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
takeBaseName) [[Char]]
files