gatoatigrado
gatoatigrado

Reputation: 16850

"cabal install ___" breaks previously installed packages

I find cabal's behavior when installing packages maddening. For example, running

cabal install funsat

installed old versions of array, time, random, quickcheck, and bitset, breaking packages like monadiccp, hoogle, heist, snap, etc.

It works to go back and cabal install monadiccp, etc., but how can I avoid the default behavior of cabal breaking installed packages? Any reasonable Linux package manager, like aptitude or zypper would ask whether I wanted to break already installed packages, when installing a new package.

Has anyone cooked up a workaround script? Thanks in advance.

Upvotes: 5

Views: 461

Answers (3)

Mikhail Glushenkov
Mikhail Glushenkov

Reputation: 15028

This is a known problem (see this slide deck, starting with slide 22). The Darcs version of cabal-install (darcs get http://darcs.haskell.org/cabal) now shows a warning when installing a package will break your system. Example:

$ cabal --version
cabal-install version 0.13.3
using version 1.13.3 of the Cabal library
$ cabal install monadiccp
[...]
$ cabal install funsat
Resolving dependencies...
In order, the following would be installed:
mtl-1.1.1.1 (new version)
syb-0.3.6 (new package)
array-0.2.0.0 (new version)
containers-0.2.0.1 (new version)
bimap-0.2.4 (new package)
deepseq-1.2.0.1 (reinstall) changes: array-0.3.0.2 -> 0.2.0.0
fgl-5.4.2.2 (new package)
text-0.11.1.12 (reinstall) changes: array-0.3.0.2 -> 0.2.0.0
parsec-3.1.2 (reinstall) changes: mtl-2.0.1.0 -> 1.1.1.1
parse-dimacs-1.2 (new package)
time-1.1.4 (new version)
random-1.0.0.3 (reinstall) changes: time-1.2.0.3 -> 1.1.4
QuickCheck-1.2.0.1 -base3 (new package)
bitset-0.6 (new package)
funsat-0.6.1 (new package)
cabal: The install plan contains reinstalls which can break your GHC
installation.
You can use the --avoid-reinstalls option to try to avoid this or try
to ghc-pkg unregister the version of the package version to see its effect
on reverse dependencies. If you know what you are doing you can use
the --override-reinstall-check option to override this reinstall check.

Upvotes: 2

ehird
ehird

Reputation: 40787

I recommend cabal-dev, which maintains a separate set of installed packages for each project you work on. That doesn't solve the bad behaviour of cabal-install in general, but means that such failures are more isolated than they would otherwise be, and allows you to fix them more easily by simply doing cabal-dev clean && cabal-dev install.

The added benefit of reproducible builds is also nice.

Admittedly, this isn't a workaround for your specific problem, but it lessens cabal-install pain in general.


Building on Daniel Fischer's answer, here's a wrapper for cabal that aborts an installation if it would reinstall a package:

cabal () {
  if [ "$1" = "install" ]; then
    local out=$(command cabal --dry-run -v2 "$@" 2>&1)
    if echo "$out" | egrep -c '\((reinstall|new version)\)' >/dev/null; then
      echo "$out"
      return 1
    fi
  fi
  command cabal "$@"
}

YMMV; I've only lightly tested this and it causes an annoying delay at start-up as all the dependencies have to be calculated twice. But it should relieve some tedium if you want to stay on the safe side.

Upvotes: 8

Daniel Fischer
Daniel Fischer

Reputation: 183873

Workaround: always check with --dry-run first. If cabal would reinstall any package, watch out.

Upvotes: 5

Related Questions