From ce72f63b6565e692727d21f0a987d92dd67b14db Mon Sep 17 00:00:00 2001
From: Rodrigo Mesquita <rodrigo.m.mesquita@gmail.com>
Date: Mon, 11 Mar 2024 12:23:34 +0000
Subject: [PATCH] backport: Find build-tool installed programs before programs
 in path (#9767)

* Find build-tool installed programs before programs in path (BP)

A backport of 443c8906581e4a985185a9a32de2e6c7cc63dde1 (#9762)

---------

Co-authored-by: brandon s allbery kf8nh <allbery.b@gmail.com>
Co-authored-by: Gershom Bazerman <gershom@arista.com>
---
 Cabal/src/Distribution/Simple/Configure.hs    |  6 +++--
 .../Distribution/Client/ProjectPlanning.hs    |  5 +++-
 .../PackageTests/Regression/T9756/OK.hs       | 14 ++++++++++
 .../T9756/cabal-bug-build-tool.cabal          | 10 +++++++
 .../PackageTests/Regression/T9756/cabal.out   | 27 +++++++++++++++++++
 .../Regression/T9756/cabal.project            |  1 +
 .../Regression/T9756/cabal.test.hs            | 13 +++++++++
 .../T9756/repo/mybuilder-0.1.0.0/CHANGELOG.md |  5 ++++
 .../T9756/repo/mybuilder-0.1.0.0/app/Main.hs  |  4 +++
 .../repo/mybuilder-0.1.0.0/mybuilder.cabal    | 18 +++++++++++++
 .../T9756/repo/mybuilder-0.2.0.0/CHANGELOG.md |  5 ++++
 .../T9756/repo/mybuilder-0.2.0.0/app/Main.hs  |  4 +++
 .../repo/mybuilder-0.2.0.0/mybuilder.cabal    | 18 +++++++++++++
 13 files changed, 127 insertions(+), 3 deletions(-)
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/OK.hs
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/cabal-bug-build-tool.cabal
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/cabal.out
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/cabal.project
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/cabal.test.hs
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/CHANGELOG.md
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/app/Main.hs
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/mybuilder.cabal
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/CHANGELOG.md
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/app/Main.hs
 create mode 100644 cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/mybuilder.cabal

diff --git a/Cabal/src/Distribution/Simple/Configure.hs b/Cabal/src/Distribution/Simple/Configure.hs
index 35f38a75a8..74daa6660a 100644
--- a/Cabal/src/Distribution/Simple/Configure.hs
+++ b/Cabal/src/Distribution/Simple/Configure.hs
@@ -76,7 +76,7 @@ import Distribution.Simple.Program
 import Distribution.Simple.Setup as Setup
 import Distribution.Simple.BuildTarget
 import Distribution.Simple.LocalBuildInfo
-import Distribution.Simple.Program.Db (appendProgramSearchPath)
+import Distribution.Simple.Program.Db (appendProgramSearchPath, modifyProgramSearchPath)
 import Distribution.Simple.Utils
 import Distribution.System
 import Distribution.Types.PackageVersionConstraint
@@ -850,7 +850,9 @@ configure (pkg_descr0, pbi) cfg = do
 -- arguments.
 mkProgramDb :: ConfigFlags -> ProgramDb -> IO ProgramDb
 mkProgramDb cfg initialProgramDb = do
-  programDb <- appendProgramSearchPath (fromFlagOrDefault normal (configVerbosity cfg)) searchpath initialProgramDb
+  programDb <-
+    modifyProgramSearchPath (getProgramSearchPath initialProgramDb ++)
+      <$> appendProgramSearchPath (fromFlagOrDefault normal (configVerbosity cfg)) searchpath initialProgramDb
   pure
     . userSpecifyArgss (configProgramArgs cfg)
     . userSpecifyPaths (configProgramPaths cfg)
diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs
index 2126c94280..395e5e9dcb 100644
--- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs
+++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs
@@ -3394,7 +3394,10 @@ setupHsScriptOptions (ReadyPackage elab@ElaboratedConfiguredPackage{..})
       useDistPref              = builddir,
       useLoggingHandle         = Nothing, -- this gets set later
       useWorkingDir            = Just srcdir,
-      useExtraPathEnv          = elabExeDependencyPaths elab,
+      useExtraPathEnv = elabExeDependencyPaths elab ++ elabProgramPathExtra,
+        -- note that the above adds the extra-prog-path directly following the elaborated
+        -- dep paths, so that it overrides the normal path, but _not_ the elaborated extensions
+        -- for build-tools-depends.
       useExtraEnvOverrides     = dataDirsEnvironmentForPlan distdir plan,
       useWin32CleanHack        = False,   --TODO: [required eventually]
       forceExternalSetupMethod = isParallelBuild,
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/OK.hs b/cabal-testsuite/PackageTests/Regression/T9756/OK.hs
new file mode 100644
index 0000000000..1846f8c9d0
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/OK.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE TemplateHaskell #-}
+module OK where
+
+import Data.List
+import System.Process
+import Language.Haskell.TH
+
+$(do
+    out <- runIO $ readProcess "mybuilder" [] ""
+    if "0.2.0.0" `isInfixOf` out then
+       [d| x = () |]
+    else
+      error ("Expecting Version 0.2.0.0, but got: " ++ out)
+ )
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/cabal-bug-build-tool.cabal b/cabal-testsuite/PackageTests/Regression/T9756/cabal-bug-build-tool.cabal
new file mode 100644
index 0000000000..941ac8fbca
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/cabal-bug-build-tool.cabal
@@ -0,0 +1,10 @@
+cabal-version:  1.12
+name:           cabal-bug-build-tool
+version:        0
+build-type:     Simple
+
+library
+  exposed-modules:  OK
+  default-language: Haskell2010
+  build-depends:    base, template-haskell, process
+  build-tool-depends: mybuilder:mybuilder >=0.2.0.0
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/cabal.out b/cabal-testsuite/PackageTests/Regression/T9756/cabal.out
new file mode 100644
index 0000000000..e00a710594
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/cabal.out
@@ -0,0 +1,27 @@
+# cabal v2-update
+Downloading the latest package list from test-local-repo
+# cabal v2-install
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - mybuilder-0.1.0.0 (exe:mybuilder) (requires build)
+Configuring executable 'mybuilder' for mybuilder-0.1.0.0..
+Preprocessing executable 'mybuilder' for mybuilder-0.1.0.0..
+Building executable 'mybuilder' for mybuilder-0.1.0.0..
+Installing executable mybuilder in <PATH>
+Warning: The directory <ROOT>/cabal.dist/home/.cabal/store/ghc-<GHCVER>/incoming/new-<RAND><ROOT>/cabal.dist/home/.cabal/store/ghc-<GHCVER>/<PACKAGE>-<HASH>/bin is not in the system search path.
+Symlinking 'mybuilder' to '<ROOT>/cabal.dist/install/mybuilder'
+# cabal v2-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - mybuilder-0.2.0.0 (exe:mybuilder) (requires build)
+ - cabal-bug-build-tool-0 (lib) (first run)
+Configuring executable 'mybuilder' for mybuilder-0.2.0.0..
+Preprocessing executable 'mybuilder' for mybuilder-0.2.0.0..
+Building executable 'mybuilder' for mybuilder-0.2.0.0..
+Installing executable mybuilder in <PATH>
+Warning: The directory <ROOT>/cabal.dist/home/.cabal/store/ghc-<GHCVER>/incoming/new-<RAND><ROOT>/cabal.dist/home/.cabal/store/ghc-<GHCVER>/<PACKAGE>-<HASH>/bin is not in the system search path.
+Configuring library for cabal-bug-build-tool-0..
+Preprocessing library for cabal-bug-build-tool-0..
+Building library for cabal-bug-build-tool-0..
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/cabal.project b/cabal-testsuite/PackageTests/Regression/T9756/cabal.project
new file mode 100644
index 0000000000..e6fdbadb43
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/cabal.project
@@ -0,0 +1 @@
+packages: .
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/cabal.test.hs b/cabal-testsuite/PackageTests/Regression/T9756/cabal.test.hs
new file mode 100644
index 0000000000..65b1acb5b7
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/cabal.test.hs
@@ -0,0 +1,13 @@
+import Test.Cabal.Prelude
+
+-- We are testing if the build-tools program is found in path before programs e.g. in extra-prog-path or the system path
+-- For that, we need
+--  * A repo with a build tool that is up to date
+--  * An older version of the build tool in the extra-prog-path
+--  * A project that requires the more up-to-date version of the build-tool
+
+main = cabalTest $ withRepo "repo" $ do
+  dir <- testWorkDir <$> getTestEnv
+  cabal "v2-install" ["mybuilder-0.1.0.0", "--installdir=" ++ dir ++ "/install", "--overwrite-policy=always"]
+  cabal "v2-build" ["cabal-bug-build-tool", "--extra-prog-path=" ++ dir ++ "/install"]
+
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/CHANGELOG.md b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/CHANGELOG.md
new file mode 100644
index 0000000000..60a3351b16
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for mybuilder0100
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/app/Main.hs b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/app/Main.hs
new file mode 100644
index 0000000000..7de3bfe00b
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/app/Main.hs
@@ -0,0 +1,4 @@
+module Main where
+
+main :: IO ()
+main = putStrLn "0.1.0.0"
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/mybuilder.cabal b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/mybuilder.cabal
new file mode 100644
index 0000000000..0649d81c4e
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.1.0.0/mybuilder.cabal
@@ -0,0 +1,18 @@
+cabal-version:   3.0
+name:            mybuilder
+version:         0.1.0.0
+license:         NONE
+author:          Rodrigo Mesquita
+maintainer:      rodrigo.m.mesquita@gmail.com
+build-type:      Simple
+extra-doc-files: CHANGELOG.md
+
+common warnings
+    ghc-options: -Wall
+
+executable mybuilder
+    import:           warnings
+    main-is:          Main.hs
+    build-depends:    base
+    hs-source-dirs:   app
+    default-language: Haskell2010
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/CHANGELOG.md b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/CHANGELOG.md
new file mode 100644
index 0000000000..60a3351b16
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for mybuilder0100
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/app/Main.hs b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/app/Main.hs
new file mode 100644
index 0000000000..3550f30bd2
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/app/Main.hs
@@ -0,0 +1,4 @@
+module Main where
+
+main :: IO ()
+main = putStrLn "0.2.0.0"
diff --git a/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/mybuilder.cabal b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/mybuilder.cabal
new file mode 100644
index 0000000000..c98f493aa1
--- /dev/null
+++ b/cabal-testsuite/PackageTests/Regression/T9756/repo/mybuilder-0.2.0.0/mybuilder.cabal
@@ -0,0 +1,18 @@
+cabal-version:   3.0
+name:            mybuilder
+version:         0.2.0.0
+license:         NONE
+author:          Rodrigo Mesquita
+maintainer:      rodrigo.m.mesquita@gmail.com
+build-type:      Simple
+extra-doc-files: CHANGELOG.md
+
+common warnings
+    ghc-options: -Wall
+
+executable mybuilder
+    import:           warnings
+    main-is:          Main.hs
+    build-depends:    base
+    hs-source-dirs:   app
+    default-language: Haskell2010
-- 
GitLab