- Notifications
You must be signed in to change notification settings - Fork 723
Description
This is causing problems for e.g. cabal-install-1.24 (and older versions as well), which fails to parse bleeding edge .cabal files.
So e.g.
cabal-1.24 info base-noprelude-4.10.0.0 succeeds, even though base-noprelude-4.10.0.0 would require cabal-2.0 to be properly decodable.
But there's more harmful cases, like e.g. for
cabal-1.24 info haddock-library cabal: internal error when reading package index: failed to parse .cabal file The package index or index cache is probably corrupt. Running cabal update might fix it. or even cabal-1.24 list which fails as soon as such a .cabal file is encountered.
Or even worse, cause breakages such as in jgm/pandoc#3814 which render cabal-1.24 unusable.
In the past this would have been mitigated by having cabal update remind users to update, e.g.
$ cabal-1.20 update Downloading the latest package list from hackage.haskell.org Skipping download: Local and remote files match. Note: there is a new version of cabal-install available. To upgrade, run: cabal install cabal-install How to fix (imho)
Quickfix
- ignore
.cabalfiles in the index we can't parse (i.e. which the parser currently fails with an "internal error") - possibly, for those
.cabalfiles we can parse but have a too-newcabal-version, ignore them as well
(see also #4624 (comment))
Proper fix
For packages that are newer than cabal-install supports, we can only know the package name & version, and possibly the specified cabal-version. Everything beyond that would require the parser to know how to parse and interpret the .cabal contents (note that semantics may change depending on the cabal-version, so we really cannot know what a .cabal files means if we don't actively support the declared cabal-version).
I've looked at the code in D.C.IndexUtils, and one way to go about this is to do something along the lines of
--- a/cabal-install/Distribution/Client/IndexUtils.hs +++ b/cabal-install/Distribution/Client/IndexUtils.hs @@ -56,7 +56,7 @@ import Distribution.Simple.Program import qualified Distribution.Simple.Configure as Configure ( getInstalledPackages, getInstalledPackagesMonitorFiles ) import Distribution.ParseUtils - ( ParseResult(..) ) + ( ParseResult(..), PError(FromString) ) import Distribution.Version ( Version(Version), intersectVersionRanges ) import Distribution.Text @@ -254,7 +254,7 @@ whenCacheOutOfDate index action = do -- | An index entry is either a normal package, or a local build tree reference. data PackageEntry = - NormalPackage PackageId GenericPackageDescription ByteString BlockNo + NormalPackage PackageId (Maybe GenericPackageDescription) ByteString BlockNo | BuildTreeRef BuildTreeRefType PackageId GenericPackageDescription FilePath BlockNo @@ -541,13 +542,16 @@ packageListFromCache mkPkg hnd Cache{..} mode = accum mempty [] cacheEntries -> return content _ -> interror "unexpected tar entry type" - readPackageDescription :: ByteString -> IO GenericPackageDescription + readPackageDescription :: ByteString -> IO (Maybe GenericPackageDescription) readPackageDescription content = case parsePackageDescription . ignoreBOM . fromUTF8 . BS.Char8.unpack $ content of - ParseOk _ d -> return d - _ -> interror "failed to parse .cabal file" + ParseOk _ d -> return (Just $! d) + ParseFailed (FromString e _) + | "This package requires at least Cabal version" `isPrefixOf` e + -> return Nothing + _ -> interror "failed to parse .cabal file"I.e. when a GenericPackageDescription cannot be parsed, turn it into a Nothing (or something with more information, providing more details about the minimum required version).
Then we could have the solver handle "future" packages by placing them into a blacklist
(as if they had an unconditional fail: this package requires a newer cabal version, see #393) - or we could just fake a minimal GenericPackageDescription which consists merely of an empty lib and exe with such a fail directive. Actually, would it work already now if we just faked a dummy GenericPackageDescription with a too-new spec-cabal-version?
Anyway, then the solver would avoid selecting such packages, and if forced to (freeze file, --constraints, or merely cabal install foo-1.2.3), would present the user with an informative error message which points to a possible resolution.
Commands like cabal info or cabal list would have to gracefully skip, ignore, or if forced to (cabal info foo-1.2.3), emit useful messages.
/cc @grayjay