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