packages feed

hackage-db 1.8 → 1.9

raw patch · 4 files changed

+145/−69 lines, 4 filesdep ~base

Dependency ranges changed: base

Files

hackage-db.cabal view
@@ -1,5 +1,5 @@ Name:                   hackage-db-Version:                1.8+Version:                1.9 Copyright:              Peter Simons License:                BSD3 License-File:           LICENSE@@ -39,7 +39,9 @@    quickly, but the inital cost of reading @00-index.tar@ is fairly    high.    .-   This package is known to work on Linux and Mac OS X, but not Windows.+   This package is known to work on Linux and Mac OS X, but it's+   probably not going to work on Windows (because no-one tested it, as+   far as I know).  Source-Repository head   Type:                 git@@ -49,5 +51,6 @@   Build-Depends:        base >= 3 && < 5, tar >= 0.4, Cabal, containers,                         directory, filepath, bytestring, utf8-string   hs-source-dirs:       src-  Ghc-Options:          -Wall-  Exposed-Modules:      Distribution.Hackage.DB+  Exposed-Modules:      Distribution.Hackage.DB.Unparsed+                        Distribution.Hackage.DB.Parsed+                        Distribution.Hackage.DB
src/Distribution/Hackage/DB.hs view
@@ -20,70 +20,7 @@  import Data.Map import Data.Version+import Distribution.Hackage.DB.Parsed+import Distribution.Hackage.DB.Path import Distribution.Package import Distribution.PackageDescription--import qualified Codec.Archive.Tar as Tar-import Data.ByteString.Lazy.Char8 ( ByteString )-import qualified Data.ByteString.Lazy.Char8 as BS8 ( readFile )-import qualified Data.ByteString.Lazy as BSC ( unpack )-import Data.String.UTF8 ( toString, fromRep )-import Data.Maybe ( fromMaybe )-import System.Directory ( getHomeDirectory )-import System.FilePath ( joinPath, splitDirectories )-import Distribution.Text ( simpleParse )-import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )---- | A 'Map' representation of the Hackage database. For sake of--- simplicity, we use 'String' rather than 'PackageName' to represent--- the name of a package.--type Hackage = Map String (Map Version GenericPackageDescription)---- | Read the Hackage database from the location determined by 'hackagePath'--- and return a 'Map' that provides fast access to its contents.--readHackage :: IO Hackage-readHackage = hackagePath >>= readHackage'---- | Read the Hackage database from the given 'FilePath' and return a--- 'Hackage' map that provides fast access to its contents.--readHackage' :: FilePath -> IO Hackage-readHackage' = fmap parseHackage . BS8.readFile---- | Parse the contents of Hackage's @00-index.tar@ into a 'Hackage' map.--parseHackage :: ByteString -> Hackage-parseHackage = Tar.foldEntries addEntry empty (error . show) . Tar.read-  where-    decodeUTF8 :: ByteString -> String-    decodeUTF8 = toString . fromRep . BSC.unpack--    addEntry :: Tar.Entry -> Hackage -> Hackage-    addEntry e db = case splitDirectories (Tar.entryPath e) of-                        [".",".","@LongLink"] -> db-                        path@[name,vers,_] -> case Tar.entryContent e of-                                                Tar.NormalFile buf _ -> add name vers buf db-                                                _                    -> error ("Hackage.DB.parseHackage: unexpected content type for " ++ show path)-                        _                  -> db--    add :: String -> String -> ByteString -> Hackage -> Hackage-    add name version pkg = insertWith union name (singleton (pVersion version) (pPackage name pkg))--    pPackage :: String -> ByteString -> GenericPackageDescription-    pPackage name buf = case parsePackageDescription (decodeUTF8 buf) of-                          ParseOk _ a     -> a-                          ParseFailed err -> error ("Hackage.DB.parseHackage: cannot parse cabal file " ++ show name ++ ": " ++ show err)--    pVersion :: String -> Version-    pVersion str = fromMaybe (error $ "Hackage.DB.parseHackage: cannot parse version " ++ show str) (simpleParse str)---- | Determine the default path of the Hackage database, which typically--- resides at @"$HOME\/.cabal\/packages\/hackage.haskell.org\/00-index.tar"@.--- Running the command @"cabal update"@ will keep that file up-to-date.--hackagePath :: IO FilePath-hackagePath = do-  homedir <- getHomeDirectory-  return $ joinPath [homedir, ".cabal", "packages", "hackage.haskell.org", "00-index.tar"]
+ src/Distribution/Hackage/DB/Parsed.hs view
@@ -0,0 +1,65 @@+{- |+   Module      :  Distribution.Hackage.DB.Parsed+   License     :  BSD3+   Maintainer  :  simons@cryp.to+   Stability   :  provisional+   Portability :  portable++   This module provides simple access to the Hackage database by means+   of 'Map'.+ -}++module Distribution.Hackage.DB.Parsed+  ( Hackage, readHackage, readHackage', parseHackage+  , parseUnparsedHackage+  )+  where++import qualified Data.ByteString.Lazy as BSC ( unpack )+import Data.ByteString.Lazy.Char8 ( ByteString )+import Data.Map+import Data.String.UTF8 ( toString, fromRep )+import Data.Version+import qualified Distribution.Hackage.DB.Unparsed as Unparsed+import Distribution.PackageDescription+import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )+import Distribution.Text ( display )++-- | A 'Map' representation of the Hackage database. For sake of+-- simplicity, we use 'String' rather than 'PackageName' to represent+-- the name of a package.++type Hackage = Map String (Map Version GenericPackageDescription)++-- | Read the Hackage database from the location determined by 'hackagePath'+-- and return a 'Map' that provides fast access to its contents.++readHackage :: IO Hackage+readHackage = fmap parseUnparsedHackage Unparsed.readHackage++-- | Read the Hackage database from the given 'FilePath' and return a+-- 'Hackage' map that provides fast access to its contents.++readHackage' :: FilePath -> IO Hackage+readHackage' = fmap parseUnparsedHackage . Unparsed.readHackage'++-- | Parse the contents of Hackage's @00-index.tar@ into a 'Hackage' map.++parseHackage :: ByteString -> Hackage+parseHackage = parseUnparsedHackage . Unparsed.parseHackage++-- | Convert an 'Unparsed.Hackage' map into a parsed 'Hackage' map.++parseUnparsedHackage :: Unparsed.Hackage -> Hackage+parseUnparsedHackage = Data.Map.mapWithKey parsePackages+  where+    parsePackages :: String -> Map Version ByteString -> Map Version GenericPackageDescription+    parsePackages name = Data.Map.mapWithKey (parsePackage name)++    parsePackage :: String -> Version -> ByteString -> GenericPackageDescription+    parsePackage name version buf = case parsePackageDescription (decodeUTF8 buf) of+      ParseOk _ a     -> a+      ParseFailed err -> error ("Hackage.DB.parseHackage: cannot parse cabal file " ++ show name ++ "-" ++ display version ++ ": " ++ show err)++    decodeUTF8 :: ByteString -> String+    decodeUTF8 = toString . fromRep . BSC.unpack
+ src/Distribution/Hackage/DB/Unparsed.hs view
@@ -0,0 +1,71 @@+{- |+   Module      :  Distribution.Hackage.DB.Unparsed+   License     :  BSD3+   Maintainer  :  simons@cryp.to+   Stability   :  provisional+   Portability :  portable++   This module provides simple access to the Hackage database by means+   of 'Map'.+ -}++module Distribution.Hackage.DB.Unparsed+  ( Hackage, readHackage, readHackage', parseHackage, hackagePath+  )+  where++import qualified Codec.Archive.Tar as Tar+import Data.ByteString.Lazy.Char8 ( ByteString )+import qualified Data.ByteString.Lazy.Char8 as BS8 ( readFile )+import Data.Map+import Data.Maybe ( fromMaybe )+import Data.Version+import Distribution.Text ( simpleParse )+import System.Directory ( getHomeDirectory )+import System.FilePath ( joinPath, splitDirectories )++-- | A 'Map' representation of the Hackage database. Every package name+-- maps to a non-empty set of version, and for every version there is a+-- Cabal file stored as a (lazy) 'ByteString'.++type Hackage = Map String (Map Version ByteString)++-- | Read the Hackage database from the location determined by 'hackagePath'+-- and return a 'Map' that provides fast access to its contents.++readHackage :: IO Hackage+readHackage = hackagePath >>= readHackage'++-- | Read the Hackage database from the given 'FilePath' and return a+-- 'Hackage' map that provides fast access to its contents.++readHackage' :: FilePath -> IO Hackage+readHackage' = fmap parseHackage . BS8.readFile++-- | Parse the contents of Hackage's @00-index.tar@ into a 'Hackage' map.++parseHackage :: ByteString -> Hackage+parseHackage = Tar.foldEntries addEntry empty (error . show) . Tar.read+  where+    addEntry :: Tar.Entry -> Hackage -> Hackage+    addEntry e db = case splitDirectories (Tar.entryPath e) of+                        [".",".","@LongLink"] -> db+                        path@[name,vers,_] -> case Tar.entryContent e of+                                                Tar.NormalFile buf _ -> add name vers buf db+                                                _                    -> error ("Hackage.DB.parseHackage: unexpected content type for " ++ show path)+                        _                  -> db++    add :: String -> String -> ByteString -> Hackage -> Hackage+    add name version pkg = insertWith union name (singleton (pVersion version) pkg)++    pVersion :: String -> Version+    pVersion str = fromMaybe (error $ "Hackage.DB.parseHackage: cannot parse version " ++ show str) (simpleParse str)++-- | Determine the default path of the Hackage database, which typically+-- resides at @"$HOME\/.cabal\/packages\/hackage.haskell.org\/00-index.tar"@.+-- Running the command @"cabal update"@ will keep that file up-to-date.++hackagePath :: IO FilePath+hackagePath = do+  homedir <- getHomeDirectory+  return $ joinPath [homedir, ".cabal", "packages", "hackage.haskell.org", "00-index.tar"]