1module Stackage.LoadDatabase where
3import qualified Codec.Archive.Tar as Tar
4import qualified Codec.Archive.Tar.Entry as TarEntry
5import Control.Exception (throwIO)
6import Control.Monad (guard)
7import qualified Data.ByteString.Lazy as L
8import qualified Data.ByteString.Lazy.Char8 as L8
9import Data.List (stripPrefix)
10import qualified Data.Map as Map
11import Data.Monoid (Monoid (..))
12import Data.Set (member)
13import qualified Data.Set as Set
14import Distribution.Package (Dependency (Dependency))
15import Distribution.PackageDescription (condBenchmarks,
20import Distribution.PackageDescription.Parse (ParseResult (ParseOk),
21 parsePackageDescription)
22import Distribution.Text (simpleParse)
23import Distribution.Version (withinRange)
25import System.Directory (getAppUserDataDirectory)
26import System.FilePath ((</>))
28-- | Load the raw package database.
30-- We want to put in some restrictions:
32-- * Drop all core packages. We never want to install a new version of
33-- those, nor include them in the package list.
35-- * For packages with a specific version bound, find the maximum matching
38-- * For other packages, select the maximum version number.
39loadPackageDB :: Set PackageName -- ^ core packages
40 -> Map PackageName VersionRange -- ^ additional deps
42loadPackageDB core deps = do
43 c <- getAppUserDataDirectory "cabal"
44 let tarName = c </> "packages" </> "hackage.haskell.org" </> "00-index.tar"
45 lbs <- L.readFile tarName
46 addEntries mempty $ Tar.read lbs
48 addEntries :: PackageDB -> Tar.Entries Tar.FormatError -> IO PackageDB
49 addEntries _ (Tar.Fail e) = throwIO e
50 addEntries db Tar.Done = return db
51 addEntries db (Tar.Next e es) = addEntry db e >>= flip addEntries es
53 addEntry :: PackageDB -> Tar.Entry -> IO PackageDB
55 case getPackageVersion $ TarEntry.fromTarPathToPosixPath (TarEntry.entryTarPath e) of
58 | p `member` core -> return pdb
60 case Map.lookup p deps of
62 | not $ withinRange v vrange -> return pdb
64 case Tar.entryContent e of
65 Tar.NormalFile bs _ -> return $ mappend pdb $ PackageDB $ Map.singleton p PackageInfo
67 , piDeps = parseDeps bs
72 case parsePackageDescription $ L8.unpack lbs of
73 ParseOk _ gpd -> mconcat
74 [ maybe mempty go $ condLibrary gpd
75 , mconcat $ map (go . snd) $ condExecutables gpd
76 , mconcat $ map (go . snd) $ condTestSuites gpd
77 -- , mconcat $ map (go . snd) $ condBenchmarks gpd
81 go = Set.fromList . map (\(Dependency p _) -> p) . condTreeConstraints
83 getPackageVersion :: FilePath -> Maybe (PackageName, Version)
84 getPackageVersion fp = do
85 let (package', s1) = break (== '/') fp
86 package = PackageName package'
87 s2 <- stripPrefix "/" s1
88 let (version', s3) = break (== '/') s2
89 version <- simpleParse version'
90 s4 <- stripPrefix "/" s3
91 guard $ s4 == package' ++ ".cabal"
92 Just (package, version)
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