git.iko.soy/typeable/cabal2nix
on cabal2-support help sign in
71 lines 2.6 kB history raw
1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE TemplateHaskell #-}
4module HackageGit
5 ( Hackage, readHackage, readPackage, readPackageMeta
6 , SHA256Hash, hashes
7 )
8 where
10import Control.Lens hiding ( (<.>) )
11import Control.Monad
12import Data.Aeson
13import qualified Data.ByteString.Char8 as BS
14import Data.Map as Map
15import Data.Set as Set
16import Data.String
17import Distribution.Nixpkgs.Hashes
18import Distribution.Nixpkgs.Haskell.OrphanInstances ( )
19import Distribution.Package
20import Distribution.PackageDescription
21import Distribution.PackageDescription.Parsec ( parseGenericPackageDescriptionMaybe )
22import Distribution.Text
23import Distribution.Version
24import OpenSSL.Digest ( digest, digestByName )
25import System.Directory
26import System.FilePath
28type Hackage = Map PackageName (Set Version)
30readHackage :: FilePath -> IO Hackage
31readHackage path = getSubDirs path >>= foldM discoverPackageVersions mempty
32 where
33 discoverPackageVersions :: Hackage -> String -> IO Hackage
34 discoverPackageVersions db pkg = do
35 vs <- getSubDirs (path </> pkg)
36 return (Map.insert (mkPackageName pkg) (Set.fromList (Prelude.map fromString vs)) db)
38getSubDirs :: FilePath -> IO [FilePath]
39getSubDirs path = do
40 let isDirectory p = doesDirectoryExist (path </> p)
41 getDirectoryContents path >>= filterM isDirectory . Prelude.filter (\x -> head x /= '.')
43type SHA256Hash = String
45readPackage :: FilePath -> PackageIdentifier -> IO (GenericPackageDescription, SHA256Hash)
46readPackage dirPrefix (PackageIdentifier name version) = do
47 let cabalFile = dirPrefix </> unPackageName name </> display version </> unPackageName name <.> "cabal"
48 buf <- BS.readFile cabalFile
49 cabal <- case parseGenericPackageDescriptionMaybe buf of
50 Just a -> return a
51 Nothing -> fail ("cannot parse cabal file " ++ cabalFile)
52 return (cabal, printSHA256 (digest (digestByName "sha256") buf))
54declareLenses [d|
55 data Meta = Meta { hashes :: Map String String
56 }
57 deriving (Show)
58 |]
60instance FromJSON Meta where
61 parseJSON (Object v) = Meta
62 <$> v .: "package-hashes"
63 parseJSON o = fail ("invalid Cabal metadata: " ++ show o)
65readPackageMeta :: FilePath -> PackageIdentifier -> IO Meta
66readPackageMeta dirPrefix (PackageIdentifier name version) = do
67 let metaFile = dirPrefix </> unPackageName name </> display version </> unPackageName name <.> "json"
68 buf <- BS.readFile metaFile
69 case eitherDecodeStrict buf of
70 Left msg -> fail (metaFile ++ ": " ++ msg)
71 Right x -> return $ over (hashes . ix "SHA256") (printSHA256 . packHex) x