module Distribution.Nixpkgs.Haskell.Hackage
  ( HackageDB, PackageData, VersionData(..)
  , hackageTarball, readTarball, parsePackageData
  )
  where

import Data.Map as Map
import qualified Distribution.Hackage.DB.Parsed as P
import Distribution.Hackage.DB.Path
import qualified Distribution.Hackage.DB.Unparsed as U
import Distribution.Nixpkgs.Hashes
import Distribution.Package
import Distribution.PackageDescription
import Distribution.Version
import OpenSSL.Digest
import Data.Time

type HackageDB = Map PackageName PackageData

type PackageData = Map Version VersionData

data VersionData = VersionData
  { VersionData -> GenericPackageDescription
cabalFile :: !GenericPackageDescription
  , VersionData -> String
cabalFileSha256 :: !String
  , VersionData -> Maybe String
tarballSha256 :: !(Maybe String)
  }
  deriving (Int -> VersionData -> ShowS
[VersionData] -> ShowS
VersionData -> String
(Int -> VersionData -> ShowS)
-> (VersionData -> String)
-> ([VersionData] -> ShowS)
-> Show VersionData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [VersionData] -> ShowS
$cshowList :: [VersionData] -> ShowS
show :: VersionData -> String
$cshow :: VersionData -> String
showsPrec :: Int -> VersionData -> ShowS
$cshowsPrec :: Int -> VersionData -> ShowS
Show)

readTarball :: Maybe UTCTime -> FilePath -> IO HackageDB
readTarball :: Maybe UTCTime -> String -> IO HackageDB
readTarball Maybe UTCTime
ts String
p = do
  HackageDB
dbu <- Maybe UTCTime -> String -> IO HackageDB
U.readTarball Maybe UTCTime
ts String
p
  let dbp :: HackageDB
dbp = HackageDB -> HackageDB
P.parseDB HackageDB
dbu
  HackageDB -> IO HackageDB
forall (m :: * -> *) a. Monad m => a -> m a
return ((PackageName -> PackageData -> PackageData)
-> HackageDB -> HackageDB
forall k a b. (k -> a -> b) -> Map k a -> Map k b
mapWithKey (HackageDB -> PackageName -> PackageData -> PackageData
parsePackageData HackageDB
dbu) HackageDB
dbp)

parsePackageData :: U.HackageDB -> PackageName -> P.PackageData -> PackageData
parsePackageData :: HackageDB -> PackageName -> PackageData -> PackageData
parsePackageData HackageDB
dbu PackageName
pn = (Version -> VersionData -> VersionData)
-> PackageData -> PackageData
forall k a b. (k -> a -> b) -> Map k a -> Map k b
mapWithKey (PackageData -> Version -> VersionData -> VersionData
parseVersionData (HackageDB
dbu HackageDB -> PackageName -> PackageData
forall k a. Ord k => Map k a -> k -> a
! PackageName
pn))

parseVersionData :: U.PackageData -> Version -> P.VersionData -> VersionData
parseVersionData :: PackageData -> Version -> VersionData -> VersionData
parseVersionData PackageData
pdu Version
v VersionData
vd = VersionData :: GenericPackageDescription -> String -> Maybe String -> VersionData
VersionData
                            { cabalFile :: GenericPackageDescription
cabalFile = VersionData -> GenericPackageDescription
P.cabalFile VersionData
vd
                            , cabalFileSha256 :: String
cabalFileSha256 = ByteString -> String
printSHA256 (Algorithm -> ByteString -> ByteString
forall a. Digestable a => Algorithm -> a -> ByteString
digest (String -> Algorithm
digestByName String
"sha256") ByteString
file)
                            , tarballSha256 :: Maybe String
tarballSha256 = String -> Map String String -> Maybe String
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
"sha256" (VersionData -> Map String String
P.tarballHashes VersionData
vd)
                            }
  where
    file :: ByteString
file = VersionData -> ByteString
U.cabalFile (PackageData -> Map Version VersionData
U.versions PackageData
pdu Map Version VersionData -> Version -> VersionData
forall k a. Ord k => Map k a -> k -> a
! Version
v)