Skip to content

Commit 530f1f8

Browse files
committed
Fix PATH changes not triggering REPL reconfiguration (#2015)
When a user's PATH environment variable changes between Cabal commands, the environment in the REPL becomes incorrect. This occurs because during initial package configuration, the current PATH is captured via `programSearchPathAsPATHVar` and then stored in the `programOverrideEnv` field of a ConfiguredProgram. These `ConfiguredProgram`s are subsequently serialized into the setup-config file, effectively baking in the PATH environment from the time of configuration. The issue manifests when `PATH` is updated after initial configuration. Although the solver re-runs when detecting `PATH` changes, the `dryRunLocalPkg` function examines `ElaboratedConfiguredPackage` and incorrectly determines that nothing has changed that would require reconfiguration. This decision is incorrect because `setup-config` now contains a stale reference to the original `PATH` value, which no longer matches the current environment. To fix this problem, we need to store the `ConfiguredProgram`s directly in `ElaboratedConfiguredPackage`. This approach will ensure that when `PATH` changes, the `ConfiguredProgram`s will also change, properly triggering reconfiguration. While this solution will cause more recompilations when `PATH` changes, it guarantees that the correct environment is always used during builds and REPL sessions. An alternative approach would be to stop baking the `PATH` variable into the environment of programs, but this would require more substantial changes to how Cabal manages environment variables. Fixes #2015
1 parent 44086db commit 530f1f8

File tree

7 files changed

+63
-0
lines changed

7 files changed

+63
-0
lines changed

cabal-install/src/Distribution/Client/ProjectPlanning.hs

+1
Original file line numberDiff line numberDiff line change
@@ -2327,6 +2327,7 @@ elaborateInstallPlan
23272327
]
23282328
<> perPkgOptionMapMappend pkgid packageConfigProgramArgs
23292329
elabProgramPathExtra = perPkgOptionNubList pkgid packageConfigProgramPathExtra
2330+
elabConfiguredPrograms = configuredPrograms compilerprogdb
23302331
elabConfigureScriptArgs = perPkgOptionList pkgid packageConfigConfigureArgs
23312332
elabExtraLibDirs = perPkgOptionList pkgid packageConfigExtraLibDirs
23322333
elabExtraLibDirsStatic = perPkgOptionList pkgid packageConfigExtraLibDirsStatic

cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs

+1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ data ElaboratedConfiguredPackage = ElaboratedConfiguredPackage
274274
, elabProgramPaths :: Map String FilePath
275275
, elabProgramArgs :: Map String [String]
276276
, elabProgramPathExtra :: [FilePath]
277+
, elabConfiguredPrograms :: [ConfiguredProgram]
277278
, elabConfigureScriptArgs :: [String]
278279
, elabExtraLibDirs :: [FilePath]
279280
, elabExtraLibDirsStatic :: [FilePath]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: PathRecomp
2+
version: 0.1.0.0
3+
license: BSD3
4+
author: Test Author
5+
maintainer: [email protected]
6+
build-type: Simple
7+
cabal-version: >=1.10
8+
9+
library
10+
exposed-modules: Lib
11+
hs-source-dirs: src
12+
build-depends: base
13+
default-language: Haskell2010
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Test.Cabal.Prelude
2+
import qualified Data.Map as Map
3+
import qualified Control.Monad.IO.Class as IO
4+
import System.Environment (getEnvironment)
5+
6+
main = cabalTest $ recordMode DoNotRecord $ do
7+
-- First run cabal repl with the normal PATH
8+
env <- IO.liftIO getEnvironment
9+
let originalPath = maybe "" id (lookup "PATH" env)
10+
11+
-- Run repl with original PATH
12+
cabal' "repl" ["lib:PathRecomp"] >>= assertOutputContains "module loaded"
13+
14+
-- Now modify the PATH by prefixing with a dummy directory
15+
-- This simulates a user modifying their PATH between cabal commands
16+
let modifiedPath = "/dummy/path:" ++ originalPath
17+
withEnv [("PATH", Just modifiedPath)] $ do
18+
-- Run repl with modified PATH - this should still work
19+
r <- cabalWithStdin "repl" ["lib:PathRecomp"] "(Prelude.fmap . Prelude.fmap) (\"/dummy/path\" `Data.List.isInfixOf`) (System.Environment.lookupEnv \"PATH\")"
20+
assertOutputContains "module loaded" r
21+
assertOutputContains "Just True" r
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Lib
2+
( someFunc
3+
) where
4+
5+
someFunc :: IO ()
6+
someFunc = putStrLn "someFunc"

changelog.d/pr-10817

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
synopsis: Fix PATH changes not triggering REPL reconfiguration
2+
packages: cabal-install
3+
prs: #10817
4+
issues: #2015
5+
6+
When a user's PATH environment variable changes between Cabal commands, the REPL
7+
environment would become incorrect. This happens because during initial package
8+
configuration, the current PATH value is captured and stored in the
9+
`programOverrideEnv` field of ConfiguredPrograms, which gets serialized into
10+
setup-config.
11+
12+
If PATH is updated after configuration, the solver re-runs but `dryRunLocalPkg`
13+
doesn't detect the need for reconfiguration, leaving the REPL with stale PATH
14+
references.
15+
16+
This fix stores ConfiguredPrograms directly in ElaboratedConfiguredPackage,
17+
ensuring that when PATH changes, the ConfiguredPrograms also change, properly
18+
triggering reconfiguration. While this causes more rebuilds when PATH changes,
19+
it guarantees that the correct environment is always used during REPL sessions.

0 commit comments

Comments
 (0)