-
Notifications
You must be signed in to change notification settings - Fork 698
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Assertion failure with --package-db flag #9678
Comments
I have a patch which fixes things in the way described. I think it's clearer if the semantics of the flag don't allow you to remove the |
It seems there is also a potential bug with things in the |
Your analysis seems correct to me, and I agree with the proposed fix 👍 |
Duncan instead suggests that it would be better to extend the syntax of To me this seems like a worse way to go because the notion of a store is quite baked into cabal and it seems that allowing the user the control over which package database packages get installed into is too low-level for |
A package in the store depending on an effimeral package-db provided on the command line is basically broken, since there is no guarantee that the package-db will stay around. Note that the store does not work like a regular package-db. It's invibile to the solver and it is only used to replace configured packages with pre-built ones. This is done just by looking at the package hash so there is no consistency check in the store. |
I think it is up to the user to guarantee that package databases passed with The package hash contains the package db stack which was in place when the package was built, which I think guards against using packages built with What is your conceptual model of how the |
That's right, I worry that it could be fragile though; as soon as we see the same package-db, we will happy swap the configured package with the pre-installed one in the store without any extra checks. What if the package-db is still there but one package has been removed? or (perhaps worse) changed/rebuilt? What if the user wipes the package-db and rebuilds it (with whatever tool their are using to do so)? Packages built with that package-db might not work anymore. With the cabal store we can make assumptions on the meaning of the unit id (containing a digest of the package inputs) but with external package-dbs we cannot do that. I have plenty of experience with users build packages inside a nix shell; which I think it's similar. Packages in the cabal store will end up referencing dynamic libraries in the nix store; this was invibile to cabal so the only was to remove a package from the store, and then also delete everything that depended on it; at which point
I think I agree with your analysis. I haven't thought much about it but I think it is a mistake that package-db can explicitly mention the store. My only disagreement is about the order, IMHO extras package-db should be between the store db and the in-place db. Note that we customise how we install packages in the store already, so it would not be a problem adjusting/extending that custom logic. |
@andreabedini I think all your arguments apply to the global package database as well, there's no reason that couldn't be mutated, rebuilt, packages added, removed etc. (And that's what seems to happen in the nix case) Say that we put the
So it seems to me the OTOH, you are explaining that the flag is rightfully dangerous, you will end up with broken packages in your store if you modify or mutate the package database. Therefore I propose the following semantics for the flag.
The Thoughts? |
I need to think this through, and perhaps double check the code. For the moment I will leave a couple of comments to be sure we are on the same page. We use
which shows we use different a PackageDBStack dependending on the situation. I am pretty sure the solver has zero knowledge of the store, as I said before, the store should not be considered a packagedb. I need to check but I think
Note that
Well the short answer these days is: cabal does not install anything 😬 v2 commands do not really install packages as v1 commands did.
What is going to happen is that a pre-installed package fixes all its dependencies. There are two cases:
We need to understand the scenario we want to support. I am afraid that we do not support case 2 at the moment. PS: Perhaps my previous comments about the order were premature. Order in what list? The store is not passed as a packagedb to the solver, but it is passed as a packagedb to the compiler (along with PPS: I haven't looked at the assertion yet. |
To clarify @andreabedini I think we have a bit of a misunderstanding about my two questions:
I think that |
I realise now I have been following your chain of thoughts backward (the pr, the issue, the asertion). Thank for raising this up.
Yes, we do agree. If Let me swap the next two paragraphs around.
We really don't call In a typical -- | Given the 'InstalledPackageIndex' for a nix-style package store, and an
-- 'ElaboratedInstallPlan', replace configured source packages by installed
-- packages from the store whenever they exist.
improveInstallPlanWithInstalledPackages
:: Set UnitId
-> ElaboratedInstallPlan
-> ElaboratedInstallPlan
improveInstallPlanWithInstalledPackages installedPkgIdSet =
InstallPlan.installed canPackageBeImproved
where
canPackageBeImproved pkg =
installedUnitId pkg `Set.member` installedPkgIdSet Note that Now, I did check and in
Ok, I had to refresh on GHC's behaviour and I had neglected the hierarchy of packagedbs. This is what I think is the design (and the implementation, a part from bugs):
Therefore: [global packagedb, project packagedbs, store packagedb, in-place packagedb (when relevant)] This confirms that we cannot support the scenario 2 in my previous comment; i.e. you cannot ... and that, as you started with, corePackageDbs =
applyPackageDbFlags
(storePackageDBStack compiler)
(projectConfigPackageDBs sharedPackageConfig) must be wrong. |
Thank you for pointing that out about the store, so that confirms that indeed it is very special and shouldn't be overridden in this ad-hoc way by the user. So we are agreed on principle 1, About principle 2, the order the
And in that case, my patch in #9683 implements this proposal. |
Yes, I agree with all that. Thank you for taking on this. |
In this PR we make the `--package-db` flag apply only to the default immutable initial package stack rather than also applying to the store package database. There are two special package databases which cabal install knows about and treats specially. * The store directory, a global cache of installed packages where cabal builds and installs packages into. * The inplace directory, a local build folder for packages, where cabal builds local packages in. It is very important that cabal registers packages it builds into one of these two locations as there are many assumptions that packages will end up here. With the current design of the `--package-db` flag, you are apparently allowed to override the store location which should have the effect of making the last package database in the package stack the "store" directory. Perhaps this works out in theory but practically this behaviour was broken and things were always registered into the store directory that cabal knew about. (The assertion in `ProjectBuilding.UnpackedPackage` was failing (see added test)). With `--package-db` not being able to modify the location of the store directory then the interaction of `--package-db`, `--store-dir` and `--dist-dir` flags become easy to understand. * `--package-db` modify the initial package database stack, these package database will not be mutated by cabal and provide the initial package environment which is used by cabal. * `--store-dir` modify the location of the store directory * `--dist-dir` modify the location of the dist directory (and hence inplace package database) Treating the flags in this way also fix an assertion failure when building packages. Fixes haskell#9678
In this PR we make the `--package-db` flag apply only to the default immutable initial package stack rather than also applying to the store package database. There are two special package databases which cabal install knows about and treats specially. * The store directory, a global cache of installed packages where cabal builds and installs packages into. * The inplace directory, a local build folder for packages, where cabal builds local packages in. It is very important that cabal registers packages it builds into one of these two locations as there are many assumptions that packages will end up here. With the current design of the `--package-db` flag, you are apparently allowed to override the store location which should have the effect of making the last package database in the package stack the "store" directory. Perhaps this works out in theory but practically this behaviour was broken and things were always registered into the store directory that cabal knew about. (The assertion in `ProjectBuilding.UnpackedPackage` was failing (see added test)). With `--package-db` not being able to modify the location of the store directory then the interaction of `--package-db`, `--store-dir` and `--dist-dir` flags become easy to understand. * `--package-db` modify the initial package database stack, these package database will not be mutated by cabal and provide the initial package environment which is used by cabal. * `--store-dir` modify the location of the store directory * `--dist-dir` modify the location of the dist directory (and hence inplace package database) Treating the flags in this way also fix an assertion failure when building packages. Fixes haskell#9678
In this PR we make the `--package-db` flag apply only to the default immutable initial package stack rather than also applying to the store package database. There are two special package databases which cabal install knows about and treats specially. * The store directory, a global cache of installed packages where cabal builds and installs packages into. * The inplace directory, a local build folder for packages, where cabal builds local packages in. It is very important that cabal registers packages it builds into one of these two locations as there are many assumptions that packages will end up here. With the current design of the `--package-db` flag, you are apparently allowed to override the store location which should have the effect of making the last package database in the package stack the "store" directory. Perhaps this works out in theory but practically this behaviour was broken and things were always registered into the store directory that cabal knew about. (The assertion in `ProjectBuilding.UnpackedPackage` was failing (see added test)). With `--package-db` not being able to modify the location of the store directory then the interaction of `--package-db`, `--store-dir` and `--dist-dir` flags become easy to understand. * `--package-db` modify the initial package database stack, these package database will not be mutated by cabal and provide the initial package environment which is used by cabal. * `--store-dir` modify the location of the store directory * `--dist-dir` modify the location of the dist directory (and hence inplace package database) Treating the flags in this way also fix an assertion failure when building packages. Fixes haskell#9678
In this PR we make the `--package-db` flag apply only to the default immutable initial package stack rather than also applying to the store package database. There are two special package databases which cabal install knows about and treats specially. * The store directory, a global cache of installed packages where cabal builds and installs packages into. * The inplace directory, a local build folder for packages, where cabal builds local packages in. It is very important that cabal registers packages it builds into one of these two locations as there are many assumptions that packages will end up here. With the current design of the `--package-db` flag, you are apparently allowed to override the store location which should have the effect of making the last package database in the package stack the "store" directory. Perhaps this works out in theory but practically this behaviour was broken and things were always registered into the store directory that cabal knew about. (The assertion in `ProjectBuilding.UnpackedPackage` was failing (see added test)). With `--package-db` not being able to modify the location of the store directory then the interaction of `--package-db`, `--store-dir` and `--dist-dir` flags become easy to understand. * `--package-db` modify the initial package database stack, these package database will not be mutated by cabal and provide the initial package environment which is used by cabal. * `--store-dir` modify the location of the store directory * `--dist-dir` modify the location of the dist directory (and hence inplace package database) Treating the flags in this way also fix an assertion failure when building packages. Fixes haskell#9678
In this PR we make the `--package-db` flag apply only to the default immutable initial package stack rather than also applying to the store package database. There are two special package databases which cabal install knows about and treats specially. * The store directory, a global cache of installed packages where cabal builds and installs packages into. * The inplace directory, a local build folder for packages, where cabal builds local packages in. It is very important that cabal registers packages it builds into one of these two locations as there are many assumptions that packages will end up here. With the current design of the `--package-db` flag, you are apparently allowed to override the store location which should have the effect of making the last package database in the package stack the "store" directory. Perhaps this works out in theory but practically this behaviour was broken and things were always registered into the store directory that cabal knew about. (The assertion in `ProjectBuilding.UnpackedPackage` was failing (see added test)). With `--package-db` not being able to modify the location of the store directory then the interaction of `--package-db`, `--store-dir` and `--dist-dir` flags become easy to understand. * `--package-db` modify the initial package database stack, these package database will not be mutated by cabal and provide the initial package environment which is used by cabal. * `--store-dir` modify the location of the store directory * `--dist-dir` modify the location of the dist directory (and hence inplace package database) Treating the flags in this way also fix an assertion failure when building packages. Fixes haskell#9678
In this PR we make the `--package-db` flag apply only to the default immutable initial package stack rather than also applying to the store package database. There are two special package databases which cabal install knows about and treats specially. * The store directory, a global cache of installed packages where cabal builds and installs packages into. * The inplace directory, a local build folder for packages, where cabal builds local packages in. It is very important that cabal registers packages it builds into one of these two locations as there are many assumptions that packages will end up here. With the current design of the `--package-db` flag, you are apparently allowed to override the store location which should have the effect of making the last package database in the package stack the "store" directory. Perhaps this works out in theory but practically this behaviour was broken and things were always registered into the store directory that cabal knew about. (The assertion in `ProjectBuilding.UnpackedPackage` was failing (see added test)). With `--package-db` not being able to modify the location of the store directory then the interaction of `--package-db`, `--store-dir` and `--dist-dir` flags become easy to understand. * `--package-db` modify the initial package database stack, these package database will not be mutated by cabal and provide the initial package environment which is used by cabal. * `--store-dir` modify the location of the store directory * `--dist-dir` modify the location of the dist directory (and hence inplace package database) Treating the flags in this way also fix an assertion failure when building packages. Fixes haskell#9678
If you specify the
--package-db
flag then you get an assertion failure whenever cabal attempts to build a package which should end up in the store.Repro: https://github.com/mpickering/cautious-octo-spoon
The assertion checks whether the
elabRegisterPackageDBStack
is the same asstorePackageDBStack
, which they are not because theelabRegisterPackageDBStack
contains the--package-db
flag.The reason for this difference is that in
ProjectPlanning.hs
computescorePackageDbs
as follows:Notice that the project config package db flags are applied after the store package db paths (this seems wrong to me).
Things only don't go horribly wrong because in the next bit of code
storePackageDBStack
is used to decide where to register the package rather thanelabRegisterPackageDBStack
.In order to understand how to fix this assertion it's necessary to decide on the specification of the
--package-db
flag.My understanding of how I want it to work is that
--package-db
flag specifies an immutable package database which augments the global store with some additional packages. We do not under any circumstances want to register packages into a package database provided by--package-db
.cabal-install
mutates two package databases:Therefore these should always appear after the package database provided by
--package-db
so that when a package is registered it's registered into one of these two places rather than anything the user provides with--package-db
.This also has the consequence that packages in the store can depend on
--package-db
packages, but not vice-versa, which I believe is also the intention of the flag.Flag introduced in : #7676
In the documentation it states that the order is intentional but I don't think that makes much sense:
The text was updated successfully, but these errors were encountered: