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 +30/−0
- Setup.hs +6/−0
- hackage-db.cabal +51/−0
- src/Distribution/Hackage/DB.hs +80/−0
+ 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)