Skip to content

Commit 16c3c38

Browse files
authored
Pick the latest version when the same package is in plan.json twice (#109)
Currently haskell.nix assums that each package will occur only once in the plan.json file. It turns out this is not always the case. If a package is included as a dependency of a `setup` component or `build-tool-dependencies` then it may be listed more than once. Currently we pick the first one in the `plan.json` file (via `Map.fromList`). This is not ideal as it is often an old version included to satisfy one of the `setup` or `build-tool-dependencies`. In particular `cabal-doctest` often results in picking an old version of `Win32` when cross compiling for windows. It can be difficult to get rid of the duplicates in the `plan.json` file itself (as a work around), because constraints cannot be added to the build time dependencies in `cabal.project`. The correct fix is to add support for multiple versions of the same package in haskell.nix, but this will require a lot of refactoring. This PR will help improve the situation by picking the newest version with `Map.fromListWith`, rather than just the first in the file.
1 parent 4bca7bb commit 16c3c38

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

plan2nix/Plan2Nix.hs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{-# LANGUAGE LambdaCase, OverloadedStrings, NamedFieldPuns, RecordWildCards #-}
1+
{-# LANGUAGE LambdaCase, OverloadedStrings, NamedFieldPuns, RecordWildCards, TupleSections #-}
22

33
module Plan2Nix
44
( doPlan2Nix
@@ -33,6 +33,8 @@ import Data.Text.Prettyprint.Doc.Render.Text (hPutDoc)
3333
import Distribution.Types.PackageId (PackageIdentifier(..))
3434
import Distribution.Nixpkgs.Fetch (DerivationSource(..), Source(..), Hash(..), fetch)
3535
import Distribution.Simple.Utils (shortRelativePath)
36+
import Distribution.Types.Version (Version)
37+
import Distribution.Parsec (simpleParsec)
3638

3739
import Control.Monad.Trans.Maybe
3840
import Control.Monad.IO.Class (liftIO)
@@ -241,11 +243,15 @@ value2plan plan = Plan { packages, components, extras, compilerVersion, compiler
241243
else Just $ pkg ^. key "pkg-version" . _String
242244

243245
filterInstallPlan :: (Value -> Maybe b) -> HashMap Text b
244-
filterInstallPlan f =
245-
Map.fromList
246-
$ mapMaybe (\pkg -> (,) (pkg ^. key "pkg-name" . _String) <$> f pkg)
246+
filterInstallPlan f = fmap snd .
247+
-- If the same package occurs more than once, choose the latest
248+
Map.fromListWith (\a b -> if parseVersion (fst a) > parseVersion (fst b) then a else b)
249+
$ mapMaybe (\pkg -> (,) (pkg ^. key "pkg-name" . _String) . (pkg ^. key "pkg-version" . _String,) <$> f pkg)
247250
$ Vector.toList (plan ^. key "install-plan" . _Array)
248251

252+
parseVersion :: Text -> Version
253+
parseVersion s = fromMaybe (error $ "Unable to parse version " <> show s) . simpleParsec $ Text.unpack s
254+
249255
-- Set of components that are included in the plan.
250256
components :: HashSet Text
251257
components =

0 commit comments

Comments
 (0)