1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE TemplateHaskell #-}
7import Control.Lens hiding ( (<.>) )
9import Data.ByteString.Char8 ( ByteString )
10import qualified Data.ByteString.Char8 as BS
11import Data.ByteString.Lazy.Char8 ( fromStrict )
12import Data.Digest.Pure.SHA ( sha256, showDigest )
16import Data.String.UTF8 ( toString, fromRep )
17import Distribution.Nixpkgs.Haskell.OrphanInstances ( )
18import Distribution.Package
19import Distribution.PackageDescription
20import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )
21import Distribution.Text
22import Distribution.Version
23import System.Directory
26type Hackage = Map PackageName (Set Version)
28readHackage :: FilePath -> IO Hackage
29readHackage path = getSubDirs path >>= foldM discoverPackageVersions mempty
31 discoverPackageVersions :: Hackage -> String -> IO Hackage
32 discoverPackageVersions db pkg = do
33 vs <- getSubDirs (path </> pkg)
34 return (Map.insert (PackageName pkg) (Set.fromList (Prelude.map fromString vs)) db)
36getSubDirs :: FilePath -> IO [FilePath]
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 parsePackageDescription (decodeUTF8 buf) of
51 ParseOk _ a -> return a
52 ParseFailed err -> fail (cabalFile ++ ": " ++ show err)
53 return (cabal, mkSHA256 buf)
55mkSHA256 :: ByteString -> SHA256Hash
56mkSHA256 = showDigest . sha256 . fromStrict
59 data Meta = Meta { hashes :: Map String String
60 , locations :: [String]
66instance FromJSON Meta where
67 parseJSON (Object v) = Meta
68 <$> v .: "package-hashes"
69 <*> v .: "package-locations"
70 <*> v .: "package-size"
71 parseJSON o = fail ("invalid Cabal metadata: " ++ show o)
73readPackageMeta :: FilePath -> PackageIdentifier -> IO Meta
74readPackageMeta dirPrefix (PackageIdentifier name version) = do
75 let metaFile = dirPrefix </> unPackageName name </> display version </> unPackageName name <.> "json"
76 buf <- BS.readFile metaFile
77 case eitherDecodeStrict buf of
78 Left msg -> fail (metaFile ++ ": " ++ msg)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list