mirror of
https://github.com/commercialhaskell/stackage.git
synced 2026-01-22 04:01:56 +01:00
getLatestDescriptions
This commit is contained in:
parent
658a52b635
commit
a97335fbc5
@ -7,6 +7,8 @@
|
|||||||
-- | Dealing with the 00-index file and all its cabal files.
|
-- | Dealing with the 00-index file and all its cabal files.
|
||||||
module Stackage2.PackageIndex
|
module Stackage2.PackageIndex
|
||||||
( sourcePackageIndex
|
( sourcePackageIndex
|
||||||
|
, UnparsedCabalFile (..)
|
||||||
|
, getLatestDescriptions
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Codec.Archive.Tar as Tar
|
import qualified Codec.Archive.Tar as Tar
|
||||||
@ -14,7 +16,7 @@ import qualified Codec.Archive.Tar.Entry as TarEntry
|
|||||||
import Data.Conduit.Lazy (MonadActive,
|
import Data.Conduit.Lazy (MonadActive,
|
||||||
lazyConsume)
|
lazyConsume)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Distribution.PackageDescription (GenericPackageDescription)
|
import Distribution.PackageDescription (GenericPackageDescription, packageDescription, package)
|
||||||
import Distribution.PackageDescription.Parse (ParseResult (..),
|
import Distribution.PackageDescription.Parse (ParseResult (..),
|
||||||
parsePackageDescription)
|
parsePackageDescription)
|
||||||
import Distribution.ParseUtils (PError)
|
import Distribution.ParseUtils (PError)
|
||||||
@ -42,12 +44,16 @@ getPackageIndexPath = liftIO $ do
|
|||||||
("remote-repo-cache", stripPrefix ":" -> Just v) <- Just $ break (== ':') s
|
("remote-repo-cache", stripPrefix ":" -> Just v) <- Just $ break (== ':') s
|
||||||
Just $ fpFromText $ T.strip v
|
Just $ fpFromText $ T.strip v
|
||||||
|
|
||||||
|
-- | A cabal file with name and version parsed from the filepath, and the
|
||||||
|
-- package description itself ready to be parsed. It's left in unparsed form
|
||||||
|
-- for efficiency.
|
||||||
data UnparsedCabalFile = UnparsedCabalFile
|
data UnparsedCabalFile = UnparsedCabalFile
|
||||||
{ ucfName :: PackageName
|
{ ucfName :: PackageName
|
||||||
, ucfVersion :: Version
|
, ucfVersion :: Version
|
||||||
, ucfParse :: forall m. MonadThrow m => m GenericPackageDescription
|
, ucfParse :: forall m. MonadThrow m => m GenericPackageDescription
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- | Stream all of the cabal files from the 00-index tar file.
|
||||||
sourcePackageIndex :: (MonadThrow m, MonadResource m, MonadActive m, MonadBaseControl IO m)
|
sourcePackageIndex :: (MonadThrow m, MonadResource m, MonadActive m, MonadBaseControl IO m)
|
||||||
=> Producer m UnparsedCabalFile
|
=> Producer m UnparsedCabalFile
|
||||||
sourcePackageIndex = do
|
sourcePackageIndex = do
|
||||||
@ -68,14 +74,20 @@ sourcePackageIndex = do
|
|||||||
yield UnparsedCabalFile
|
yield UnparsedCabalFile
|
||||||
{ ucfName = name
|
{ ucfName = name
|
||||||
, ucfVersion = version
|
, ucfVersion = version
|
||||||
, ucfParse = goContent (Tar.entryPath e) lbs
|
, ucfParse = goContent (Tar.entryPath e) name version lbs
|
||||||
}
|
}
|
||||||
| otherwise = return ()
|
| otherwise = return ()
|
||||||
|
|
||||||
goContent fp lbs =
|
goContent fp name version lbs =
|
||||||
case parsePackageDescription $ unpack $ decodeUtf8 lbs of
|
case parsePackageDescription $ unpack $ decodeUtf8 lbs of
|
||||||
ParseFailed e -> throwM $ CabalParseException (fpFromString fp) e
|
ParseFailed e -> throwM $ CabalParseException (fpFromString fp) e
|
||||||
ParseOk _warnings gpd -> return gpd
|
ParseOk _warnings gpd -> do
|
||||||
|
let pd = packageDescription gpd
|
||||||
|
PackageIdentifier name' version' = package pd
|
||||||
|
when (name /= name' || version /= version') $
|
||||||
|
throwM $ MismatchedNameVersion (fpFromString fp)
|
||||||
|
name name' version version'
|
||||||
|
return gpd
|
||||||
|
|
||||||
parseNameVersion t1 = do
|
parseNameVersion t1 = do
|
||||||
let (p', t2) = break (== '/') t1
|
let (p', t2) = break (== '/') t1
|
||||||
@ -92,5 +104,25 @@ data InvalidCabalPath = InvalidCabalPath Text Text
|
|||||||
instance Exception InvalidCabalPath
|
instance Exception InvalidCabalPath
|
||||||
|
|
||||||
data CabalParseException = CabalParseException FilePath PError
|
data CabalParseException = CabalParseException FilePath PError
|
||||||
|
| MismatchedNameVersion FilePath PackageName PackageName Version Version
|
||||||
deriving (Show, Typeable)
|
deriving (Show, Typeable)
|
||||||
instance Exception CabalParseException
|
instance Exception CabalParseException
|
||||||
|
|
||||||
|
-- | Get all of the latest descriptions for name/version pairs matching the
|
||||||
|
-- given criterion.
|
||||||
|
getLatestDescriptions :: MonadIO m
|
||||||
|
=> (PackageName -> Version -> Bool)
|
||||||
|
-> m (Map PackageName (Version, GenericPackageDescription))
|
||||||
|
getLatestDescriptions f = liftIO $ do
|
||||||
|
m <- runResourceT $ sourcePackageIndex $$ filterC f' =$ foldlC add mempty
|
||||||
|
forM m $ \ucf -> do
|
||||||
|
gpd <- ucfParse ucf
|
||||||
|
return (ucfVersion ucf, gpd)
|
||||||
|
where
|
||||||
|
f' ucf = f (ucfName ucf) (ucfVersion ucf)
|
||||||
|
add m ucf =
|
||||||
|
case lookup name m of
|
||||||
|
Just ucf' | ucfVersion ucf < ucfVersion ucf' -> m
|
||||||
|
_ -> insertMap name ucf m
|
||||||
|
where
|
||||||
|
name = ucfName ucf
|
||||||
|
|||||||
@ -10,7 +10,8 @@ module Stackage2.Prelude
|
|||||||
import ClassyPrelude.Conduit as X
|
import ClassyPrelude.Conduit as X
|
||||||
import Data.Conduit.Process as X
|
import Data.Conduit.Process as X
|
||||||
import Data.Typeable (TypeRep, typeOf)
|
import Data.Typeable (TypeRep, typeOf)
|
||||||
import Distribution.Package as X (PackageName (PackageName))
|
import Distribution.Package as X (PackageIdentifier (..),
|
||||||
|
PackageName (PackageName))
|
||||||
import qualified Distribution.Text as DT
|
import qualified Distribution.Text as DT
|
||||||
import Distribution.Version as X (Version (..), VersionRange)
|
import Distribution.Version as X (Version (..), VersionRange)
|
||||||
import System.Exit (ExitCode (ExitSuccess))
|
import System.Exit (ExitCode (ExitSuccess))
|
||||||
|
|||||||
@ -6,4 +6,15 @@ import Stackage2.Prelude
|
|||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
|
|
||||||
spec :: Spec
|
spec :: Spec
|
||||||
spec = it "works" $ (runResourceT $ sourcePackageIndex $$ sinkNull :: IO ())
|
spec = do
|
||||||
|
it "works" $ (runResourceT $ sourcePackageIndex $$ sinkNull :: IO ())
|
||||||
|
it "getLatestDescriptions gives reasonable results" $ do
|
||||||
|
let f x y = (display x, display y) `member` asSet (setFromList
|
||||||
|
[ (asText "base", asText "4.5.0.0")
|
||||||
|
, ("does-not-exist", "9999999999999999999")
|
||||||
|
])
|
||||||
|
m <- getLatestDescriptions f
|
||||||
|
length m `shouldBe` 1
|
||||||
|
p <- simpleParse $ asText "base"
|
||||||
|
v <- simpleParse $ asText "4.5.0.0"
|
||||||
|
(fst <$> m) `shouldBe` singletonMap p v
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user