From 859347426ec5a4b4577d8a4c9fa38e877167d525 Mon Sep 17 00:00:00 2001 From: Pierre Le Marre Date: Sat, 25 May 2024 15:46:55 +0200 Subject: [PATCH] Fix --program-{prefix,suffix} resulting in invalid installation Currently the options `--program-{prefix,suffix}` for cabal install affects the name of the file in the install directory *and* the executable name in the store. The installation fails: - If using `--install-method=symlink`, the *target* of the symlink is not affected by the affix options and it results in an invalid symlink. - If using `--install-method=copy`, the copy fails because the source is not found. Another issue is that it affects the computation of the hash of the build directory in the store, resulting in needless rebuild when using successively different affix options. Fixed by making the name of the executable in the store canonical, i.e. always ignoring the program affix options. Added a test for all the combinations of `--install-method` and program affixes options. --- .../src/Distribution/Client/CmdInstall.hs | 14 +++++++++- .../Install/ProgramAffixes/Main.hs | 1 + .../Install/ProgramAffixes/cabal.project | 1 + .../Install/ProgramAffixes/cabal.test.hs | 27 +++++++++++++++++++ .../Install/ProgramAffixes/p.cabal | 8 ++++++ changelog.d/issue-9919 | 4 +++ 6 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 cabal-testsuite/PackageTests/Install/ProgramAffixes/Main.hs create mode 100644 cabal-testsuite/PackageTests/Install/ProgramAffixes/cabal.project create mode 100644 cabal-testsuite/PackageTests/Install/ProgramAffixes/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/Install/ProgramAffixes/p.cabal create mode 100644 changelog.d/issue-9919 diff --git a/cabal-install/src/Distribution/Client/CmdInstall.hs b/cabal-install/src/Distribution/Client/CmdInstall.hs index a154eff3ce9..1144ff79613 100644 --- a/cabal-install/src/Distribution/Client/CmdInstall.hs +++ b/cabal-install/src/Distribution/Client/CmdInstall.hs @@ -540,7 +540,7 @@ installAction flags@NixStyleFlags{extraFlags, configFlags, installFlags, project -- BuildOutcomes because we also need the component names traverseInstall (installCheckUnitExes InstallCheckInstall) installCfg where - configFlags' = disableTestsBenchsByDefault configFlags + configFlags' = disableTestsBenchsByDefault . ignoreProgramAffixes $ configFlags verbosity = fromFlagOrDefault normal (setupVerbosity $ configCommonFlags configFlags') ignoreProject = flagIgnoreProject projectFlags cliConfig = @@ -1101,6 +1101,18 @@ disableTestsBenchsByDefault configFlags = , configBenchmarks = Flag False <> configBenchmarks configFlags } +-- | Disables program prefix and suffix, in order to get the /canonical/ +-- executable name in the store and thus: +-- +-- * avoid making the package hash depend on these options and needless rebuild; +-- * provide the correct executable path to the install methods (copy, symlink). +ignoreProgramAffixes :: ConfigFlags -> ConfigFlags +ignoreProgramAffixes configFlags = + configFlags + { configProgPrefix = NoFlag + , configProgSuffix = NoFlag + } + -- | Prepares a record containing the information needed to either symlink or -- copy an executable. symlink :: OverwritePolicy -> InstallExe -> UnitId -> UnqualComponentName -> Symlink diff --git a/cabal-testsuite/PackageTests/Install/ProgramAffixes/Main.hs b/cabal-testsuite/PackageTests/Install/ProgramAffixes/Main.hs new file mode 100644 index 00000000000..76a9bdb5d48 --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/ProgramAffixes/Main.hs @@ -0,0 +1 @@ +main = pure () diff --git a/cabal-testsuite/PackageTests/Install/ProgramAffixes/cabal.project b/cabal-testsuite/PackageTests/Install/ProgramAffixes/cabal.project new file mode 100644 index 00000000000..e6fdbadb439 --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/ProgramAffixes/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/cabal-testsuite/PackageTests/Install/ProgramAffixes/cabal.test.hs b/cabal-testsuite/PackageTests/Install/ProgramAffixes/cabal.test.hs new file mode 100644 index 00000000000..c02eda531f6 --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/ProgramAffixes/cabal.test.hs @@ -0,0 +1,27 @@ +import Test.Cabal.Prelude +import Data.Foldable (traverse_) + +-- Test that program affixes options result in successful installation: +-- • Valid symlinks (--install-method=symlink) +-- • Valid copy of executables (--install-method=copy) +main = cabalTest $ do + env <- getTestEnv + recordMode DoNotRecord $ do + let installdir = testPrefixDir env "bin" + commonOpts = ["p", "--installdir", installdir, "--overwrite-policy=always"] + testAllAffixes installMethod = do + let testAffixes' = testAffixes + (commonOpts ++ ["--install-method", installMethod]) + testAffixes' Nothing Nothing + testAffixes' (Just "a-") Nothing + testAffixes' Nothing (Just "-z") + testAffixes' (Just "a-") (Just "-z") + traverse_ testAllAffixes ["symlink", "copy"] + where + mkAffixOption option = maybe [] (\a -> ["--program-" ++ option, a]) + mkProgramName p s = maybe [] id p ++ "p" ++ maybe [] id s + testAffixes commonOpts prefix suffix = do + cabal "install" ( commonOpts + ++ mkAffixOption "prefix" prefix + ++ mkAffixOption "suffix" suffix) + runInstalledExe (mkProgramName prefix suffix) [] diff --git a/cabal-testsuite/PackageTests/Install/ProgramAffixes/p.cabal b/cabal-testsuite/PackageTests/Install/ProgramAffixes/p.cabal new file mode 100644 index 00000000000..30428ef4ac3 --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/ProgramAffixes/p.cabal @@ -0,0 +1,8 @@ +name: p +version: 1.0 +build-type: Simple +cabal-version: >= 1.2 + +executable p + main-is: Main.hs + build-depends: base diff --git a/changelog.d/issue-9919 b/changelog.d/issue-9919 new file mode 100644 index 00000000000..a4fe32bbdef --- /dev/null +++ b/changelog.d/issue-9919 @@ -0,0 +1,4 @@ +synopsis: Fix --program-suffix resulting in invalid installation +packages: cabal-install +issues: #8823 #9919 +prs: #10056