Dependencies from .cabal files

Hi all, I hope this is the right list to ask this. Please direct me to the right place if not. Anyway, I'm using functionality in the Distribution.* namespace to parse .cabal files retrieved from Hackage. The problem is that after using flattenPackageDescription, the buildDepends of the PackageDescription structure seems to be a flat list which seems to lose information that was in the original .cabal file. For instance, the cabal file for hoogle, contains: build-depends: parsec, filepath, safe, uniplate, mtl, time if flag(splitBase) build-depends: base >= 3, directory, process, containers, array, bytestring else build-depends: base < 3 while the buildDepends list looks like this: Dependency (PackageName "base") (EarlierVersion (Version {versionBranch = [3], versionTags = []})), Dependency (PackageName "bytestring") AnyVersion, Dependency (PackageName "array") AnyVersion, Dependency (PackageName "containers") AnyVersion, Dependency (PackageName "process") AnyVersion, Dependency (PackageName "directory") AnyVersion, Dependency (PackageName "base") (UnionVersionRanges (ThisVersion (Version {versionBranch = [3], versionTags = []})) (LaterVersion (Version {versionBranch = [3], versionTags = []}))), Dependency (PackageName "time") AnyVersion, Dependency (PackageName "mtl") AnyVersion, Dependency (PackageName "uniplate") AnyVersion, Dependency (PackageName "safe") AnyVersion, Dependency (PackageName "filepath") AnyVersion, Dependency (PackageName "parsec") AnyVersion Should the conversion from .cabal file to Dependency list be lossy? I look forward to enlightenment. Cheers, Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/

On Tue, 2009-06-30 at 21:41 +1000, Erik de Castro Lopo wrote:
Hi all,
I hope this is the right list to ask this. Please direct me to the right place if not.
Anyway, I'm using functionality in the Distribution.* namespace to parse .cabal files retrieved from Hackage. The problem is that after using flattenPackageDescription, the buildDepends of the PackageDescription structure seems to be a flat list which seems to lose information that was in the original .cabal file.
Yes, that's what flatten does.
From the docs:
flattenPackageDescription :: GenericPackageDescription -> PackageDescription Flatten a generic package description by ignoring all conditions and just join the field descriptors into on package description. Note, however, that this may lead to inconsistent field values, since all values are joined into one field, which may not be possible in the original package description, due to the use of exclusive choices (if ... else ...). It sounds like you want to select a particular valid configuration in which case you should use finalizePackageDescription. http://www.haskell.org/ghc/docs/latest/html/libraries/Cabal/Distribution-Pac...
Should the conversion from .cabal file to Dependency list be lossy?
The conversion from GenericPackageDescription to PackageDescription is necessarily lossy because the latter is simply a smaller data type. GenericPackageDescription represents a .cabal file, conditionals and all. A PackageDescription represents a specific configuration that you could actually build on a specific machine (ie all conditionals resolved). So the conversion is necessarily lossy, the question is what you loose. When you use flattenPackageDescription you smash everything together so all the field values are there but you don't know which configurations they came from and the overall result can be inconsistent. When you use finalizePackageDescription you are selecting a particular configuration for a specific set of flags. You then get a valid configuration but of course you loose any values that were for other configurations. The only way not to loose information is not to convert to a PackageDescription but stick with a GenericPackageDescription. So you are trying to extract dependencies. So you need to decide what you really mean. You give the example:
build-depends: parsec, filepath, safe, uniplate, mtl, time if flag(splitBase) build-depends: base >= 3, directory, process, containers, array, bytestring else build-depends: base < 3
If you flatten then as you found you get both base >= 3 and base < 3. If you use finalizePackageDescription and select splitBase then you get base >= 3 and directory etc. Conversely if you select -splitBase you'd get base < 3. In both you of course get parsec, filepath etc. So you need to decide what you mean by getting dependencies. The method you use depends crucially on your purpose with the data. Duncan

I'm subscribed, so please reply to the list. Duncan Coutts wrote:
It sounds like you want to select a particular valid configuration in which case you should use finalizePackageDescription.
I actually did try finalizePackageDescription before flattenPackageDescription but I couldn't get it to typecheck. My attempt looked like this: import qualified Distribution.System as DS import qualified Distribution.Compiler as DC finalize :: GenericPackageDescription -> PackageDescription finalize generic = do let compiler = DC.CompilerId DC.GHC (Version [6, 10, 3] []) let flags = [(FlagName "splitBase", True)] let r = finalizePackageDescription flags Nothing DS.Linux DS.I386 compiler [] generic case r of Left _ -> error $ show r Right (d, _) -> d which resulted in: Ambiguous type variable `pkg' in the constraint: `Package pkg' arising from a use of `finalizePackageDescription' at cabal2debian.hs:91:12-88 Probable fix: add a type signature that fixes these type variable(s) and unfortunately, my Haskell foo is not yet strong enough to figure this one out.
So you need to decide what you mean by getting dependencies. The method you use depends crucially on your purpose with the data.
Ok, since I'm trying to generate a Debian package metadata from the Cabal metadata, finalize is definitely what I want. That just leaves me with this type checking problem. Cheers, Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/

Erik de Castro Lopo wrote:
I actually did try finalizePackageDescription before flattenPackageDescription but I couldn't get it to typecheck.
Thanks to Peaker and Saizan on IRC helped me fix it: finalize :: GenericPackageDescription -> PackageDescription finalize generic = either (error . show) fst r where compiler = DC.CompilerId DC.GHC (Version [6, 10, 3] []) flags = [(FlagName "splitBase", True)] packageIndex = Nothing :: Maybe (PackageIndex PackageIdentifier) r = finalizePackageDescription flags packageIndex DS.Linux DS.I386 compiler [] generic Cheers, Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/
participants (2)
-
Duncan Coutts
-
Erik de Castro Lopo