packages feed

hackage-db (empty) → 1.0

raw patch · 4 files changed

+167/−0 lines, 4 filesdep +Cabaldep +basedep +bytestringsetup-changed

Dependencies added: Cabal, base, bytestring, containers, directory, filepath, tar

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Redistribution and use in source and binary forms, with or+without modification, are permitted provided that the+following conditions are met:++  * Redistributions of source code must retain the above+    copyright notice, this list of conditions and the+    following disclaimer.++  * Redistributions in binary form must reproduce the above+    copyright notice, this list of conditions and the+    following disclaimer in the documentation and/or other+    materials provided with the distribution.++  * The names of its contributors may not be used to endorse+    or promote products derived from this software without+    specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,6 @@+module Main ( main ) where++import Distribution.Simple++main :: IO ()+main = defaultMain
+ hackage-db.cabal view
@@ -0,0 +1,51 @@+Name:                   hackage-db+Version:                1.0+Copyright:              Peter Simons+License:                BSD3+License-File:           LICENSE+Author:                 Peter Simons <simons@cryp.to>+Maintainer:             Peter Simons <simons@cryp.to>+Homepage:               http://github.com/peti/hackage-db+Category:               Distribution+Synopsis:               provide access to the Hackage database via Data.Map+Cabal-Version:          >= 1.8+Build-Type:             Simple+Tested-With:            GHC == 6.12.3, GHC == 7.0.4, GHC == 7.2.1+Description:+   This module provides simple access to the Hackage database by means+   of @Data.Map@. Suppose you wanted to implement a utility that queries+   the set of available versions for a given package, the following+   program would do the trick:+   .+   > import qualified Distribution.Hackage.DB as DB+   > import Distribution.Text ( display )+   > import System.Environment ( getArgs )+   >+   > main :: IO ()+   > main = do+   >   pkgs <- getArgs+   >   db <- DB.readHackage+   >   let getVersions name = maybe [] DB.keys (DB.lookup name db)+   >   mapM_ (putStrLn . unwords . map display . getVersions) pkgs+   .+   When run, it would produce the following output:+   .+   > ./a.out containers deepseq cabal-install+   > 0.1.0.0 0.1.0.1 0.2.0.0 0.2.0.1 0.3.0.0 0.4.0.0+   > 1.0.0.0 1.1.0.0 1.1.0.1 1.1.0.2+   > 0.4.0 0.5.0 0.5.1 0.5.2 0.6.0 0.6.2 0.6.4 0.8.0 0.8.2 0.10.0 0.10.2+   .+   Note that once the database has been parsed, it can be accessed+   quickly, but the inital cost of reading @00-index.tar@ is fairly+   high.++Source-Repository head+  Type:                 git+  Location:             git://github.com/peti/hackage-db.git++Library+  Build-Depends:        base >= 3 && < 5, tar, Cabal, containers,+                        directory, filepath, bytestring+  hs-source-dirs:       src+  Ghc-Options:          -Wall+  Exposed-Modules:      Distribution.Hackage.DB
+ src/Distribution/Hackage/DB.hs view
@@ -0,0 +1,80 @@+{- |+   Module      :  Distribution.Hackage.DB+   License     :  BSD3++   Maintainer  :  simons@cryp.to+   Stability   :  provisional+   Portability :  portable++   This module provides simple access to the Hackage database by means+   of 'Map'. Note that once the database has been parsed, it can be+   accessed quickly, but the inital cost of reading @00-index.tar@ is+   fairly high.+ -}++module Distribution.Hackage.DB+  ( Hackage, readHackage, readHackage', parseHackage+  , module Data.Map+  , module Data.Version+  , module Distribution.Package+  , module Distribution.PackageDescription+  )+  where++import qualified Codec.Archive.Tar as Tar+import Data.ByteString.Lazy.Char8 ( ByteString )+import qualified Data.ByteString.Lazy.Char8 as BS+import Data.Map+import Data.Maybe+import Data.Version+import System.Directory+import System.FilePath+import Distribution.Package+import Distribution.Text+import Distribution.PackageDescription+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+-- @$HOME\/.cabal\/packages\/hackage.haskell.org\/00-index.tar@ and+-- return a 'Map' that provides fast access to its contents. That @tar@+-- file is typically created by running the command @\"cabal update\"@.++readHackage :: IO Hackage+readHackage = do+  homedir <- getHomeDirectory+  readHackage' (joinPath [ homedir, ".cabal", "packages", "hackage.haskell.org", "00-index.tar" ])++-- | 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 . BS.readFile++-- | Parse the contents of Hackage's @00-index.tar@ into a 'Hackage' map.++parseHackage :: ByteString -> Hackage+parseHackage = Tar.foldEntries addEntry empty error . Tar.read+  where+    addEntry :: Tar.Entry -> Hackage -> Hackage+    addEntry e db = case splitDirectories (Tar.entryPath e) of+                        path@[name,vers,_] -> case Tar.entryContent e of+                                                Tar.NormalFile buf _ -> add name vers buf db+                                                _                    -> error ("unexpected content of " ++ 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 (BS.unpack buf) of+                          ParseOk _ a     -> a+                          ParseFailed err -> error ("cannot parse cabal file " ++ show name ++ ": " ++ show err)++    pVersion :: String -> Version+    pVersion str = fromMaybe (error $ "cannot parse version " ++ show str) (simpleParse str)