Skip to content

Commit 5625274

Browse files
ulysses4everfendor
authored andcommitted
fix cabal install --program-suffix/prefix (fix #10290 and #10476) (#10483)
* fix cabal install --program-suffix/prefix (fix #10290 and #10476) When checking for existing installations, cabal would not account for an affix (suffix or prefix). So, if you had a `hello` binary installed, installing a second one with a non-empty affix (a perfectly legal operation) would fail. The reason seemed to be a typo in 09c04e9, which passed the arguments to the Symlink structure in a wrong order. When failing to install a binary because of an existing one, cabal would report suffix-less existing target even if a suffix was set. * Add regression tests for overwrite policies and porgram-affixes Add regression tests for the `program-prefix` and `program-suffix` flags combined with the overwrite-policy. In short, the overwrite-policy needs to take potential program affixes into account when deciding whether it will need to overwrite a program path during installation. --------- Co-authored-by: Fendor <[email protected]> (cherry picked from commit ee3c313)
1 parent 90c6c21 commit 5625274

File tree

3 files changed

+231
-2
lines changed

3 files changed

+231
-2
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1123,8 +1123,8 @@ symlink
11231123
overwritePolicy
11241124
installDir
11251125
(mkSourceBinDir unit)
1126-
(mkExeName exe)
11271126
(mkFinalExeName exe)
1127+
(mkExeName exe)
11281128

11291129
-- |
11301130
-- -- * When 'InstallCheckOnly', warn if install would fail overwrite policy
@@ -1169,7 +1169,7 @@ installCheckUnitExes
11691169
errorMessage installdir exe = case overwritePolicy of
11701170
NeverOverwrite ->
11711171
"Path '"
1172-
<> (installdir </> prettyShow exe)
1172+
<> (installdir </> mkFinalExeName exe)
11731173
<> "' already exists. "
11741174
<> "Use --overwrite-policy=always to overwrite."
11751175
-- This shouldn't even be possible, but we keep it in case symlinking or
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# cabal install
2+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
3+
Resolving dependencies...
4+
Build profile: -w ghc-<GHCVER> -O1
5+
In order, the following will be built:
6+
- p-1.0 (exe:p) (requires build)
7+
Configuring p-1.0...
8+
Preprocessing executable 'p' for p-1.0...
9+
Building executable 'p' for p-1.0...
10+
Installing executable p in <PATH>
11+
Warning: The directory <ROOT>/overwrite-policy.dist/home/.cabal/store/ghc-<GHCVER>/incoming/new-<RAND><ROOT>/overwrite-policy.dist/home/.cabal/store/ghc-<GHCVER>/<PACKAGE>-<HASH>/bin is not in the system search path.
12+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
13+
# cabal install
14+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
15+
Resolving dependencies...
16+
Error: [Cabal-7149]
17+
Path '<ROOT>/overwrite-policy.dist/usr/bin/p' already exists. Use --overwrite-policy=always to overwrite.
18+
# cabal install
19+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
20+
Resolving dependencies...
21+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
22+
# cabal install
23+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
24+
Resolving dependencies...
25+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
26+
# cabal install
27+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
28+
Resolving dependencies...
29+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p-my-suffix'
30+
# cabal install
31+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
32+
Resolving dependencies...
33+
Error: [Cabal-7149]
34+
Path '<ROOT>/overwrite-policy.dist/usr/bin/p-my-suffix' already exists. Use --overwrite-policy=always to overwrite.
35+
# cabal install
36+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
37+
Resolving dependencies...
38+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p-my-suffix'
39+
# cabal install
40+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
41+
Resolving dependencies...
42+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
43+
# cabal install
44+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
45+
Resolving dependencies...
46+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
47+
# cabal install
48+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
49+
Resolving dependencies...
50+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p'
51+
# cabal install
52+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
53+
Resolving dependencies...
54+
Error: [Cabal-7149]
55+
Path '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p' already exists. Use --overwrite-policy=always to overwrite.
56+
# cabal install
57+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
58+
Resolving dependencies...
59+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p'
60+
# cabal install
61+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
62+
Resolving dependencies...
63+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
64+
# cabal install
65+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
66+
Resolving dependencies...
67+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
68+
# cabal install
69+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
70+
Resolving dependencies...
71+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p-my-suffix'
72+
# cabal install
73+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
74+
Resolving dependencies...
75+
Error: [Cabal-7149]
76+
Path '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p-my-suffix' already exists. Use --overwrite-policy=always to overwrite.
77+
# cabal install
78+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
79+
Resolving dependencies...
80+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p-my-suffix'
81+
# cabal install
82+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
83+
Resolving dependencies...
84+
Symlinking 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
85+
# cabal install
86+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
87+
Resolving dependencies...
88+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
89+
# cabal install
90+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
91+
Resolving dependencies...
92+
Error: [Cabal-7149]
93+
Path '<ROOT>/overwrite-policy.dist/usr/bin/p' already exists. Use --overwrite-policy=always to overwrite.
94+
# cabal install
95+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
96+
Resolving dependencies...
97+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
98+
# cabal install
99+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
100+
Resolving dependencies...
101+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
102+
# cabal install
103+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
104+
Resolving dependencies...
105+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p-my-suffix'
106+
# cabal install
107+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
108+
Resolving dependencies...
109+
Error: [Cabal-7149]
110+
Path '<ROOT>/overwrite-policy.dist/usr/bin/p-my-suffix' already exists. Use --overwrite-policy=always to overwrite.
111+
# cabal install
112+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
113+
Resolving dependencies...
114+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p-my-suffix'
115+
# cabal install
116+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
117+
Resolving dependencies...
118+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
119+
# cabal install
120+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
121+
Resolving dependencies...
122+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
123+
# cabal install
124+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
125+
Resolving dependencies...
126+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p'
127+
# cabal install
128+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
129+
Resolving dependencies...
130+
Error: [Cabal-7149]
131+
Path '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p' already exists. Use --overwrite-policy=always to overwrite.
132+
# cabal install
133+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
134+
Resolving dependencies...
135+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p'
136+
# cabal install
137+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
138+
Resolving dependencies...
139+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
140+
# cabal install
141+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
142+
Resolving dependencies...
143+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
144+
# cabal install
145+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
146+
Resolving dependencies...
147+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p-my-suffix'
148+
# cabal install
149+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
150+
Resolving dependencies...
151+
Error: [Cabal-7149]
152+
Path '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p-my-suffix' already exists. Use --overwrite-policy=always to overwrite.
153+
# cabal install
154+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
155+
Resolving dependencies...
156+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/my-prefix-p-my-suffix'
157+
# cabal install
158+
Wrote tarball sdist to <ROOT>/overwrite-policy.dist/work/./dist/sdist/p-1.0.tar.gz
159+
Resolving dependencies...
160+
Copying 'p' to '<ROOT>/overwrite-policy.dist/usr/bin/p'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import Test.Cabal.Prelude
2+
import Data.Bool (bool)
3+
import System.FilePath ((</>))
4+
import System.Directory (removeFile)
5+
6+
main = cabalTest $ do
7+
runTestForInstallMethod "symlink"
8+
runTestForInstallMethod "copy"
9+
10+
runTestForInstallMethod :: String -> TestM ()
11+
runTestForInstallMethod method = do
12+
env <- getTestEnv
13+
let installdir = testPrefixDir env </> "bin"
14+
15+
-- install the binary, don't overwrite anything
16+
cabal "install"
17+
["p", "--installdir", installdir, "--install-method", method, "--overwrite-policy", "never"]
18+
-- install the binary, don't overwrite anything
19+
fails $ cabal "install"
20+
["p", "--installdir", installdir, "--install-method", method, "--overwrite-policy", "never"]
21+
-- install the binary again, forcing an overwrite, should succeed.
22+
cabal "install"
23+
["p", "--installdir", installdir, "--install-method", method, "--overwrite-policy", "always"]
24+
-- remove the installed binary.
25+
ext <- exeExt
26+
liftIO $ removeFile (installdir </> "p" <.> ext)
27+
28+
testPolicyForAffix installdir method ["--program-suffix", "-my-suffix"]
29+
testPolicyForAffix installdir method ["--program-prefix", "my-prefix-"]
30+
testPolicyForAffix installdir method ["--program-prefix", "my-prefix-", "--program-suffix", "-my-suffix"]
31+
-- remove the installed binaries.
32+
liftIO $ removeFile (installdir </> "p" <.> ext)
33+
liftIO $ removeFile (installdir </> "p-my-suffix" <.> ext)
34+
liftIO $ removeFile (installdir </> "my-prefix-p" <.> ext)
35+
liftIO $ removeFile (installdir </> "my-prefix-p-my-suffix" <.> ext)
36+
37+
-- | Run a policy test for a given 'install-method' and program-affix
38+
-- (i.e., '--program-suffix' or '--program-prefix').
39+
--
40+
-- When a program affix is given, the installation should not be affected
41+
-- by installing the binary with no affix and vice-versa.
42+
-- So, installing the program without any affix is not affected by installations with
43+
-- some program affix.
44+
testPolicyForAffix :: FilePath -> String -> [String] -> TestM ()
45+
testPolicyForAffix installdir method affixArgs = do
46+
-- install the binary again, forcing an overwrite, must succeed.
47+
-- The rest of this test assumes the binary has been installed before.
48+
cabal "install"
49+
["p", "--installdir", installdir, "--install-method", method, "--overwrite-policy", "always"]
50+
51+
-- Install the binary with some program affix, don't need overwrite anything
52+
cabal "install"
53+
(["p", "--installdir", installdir, "--install-method", method, "--overwrite-policy", "never"] ++ affixArgs)
54+
-- Once the binary is installed, we can't overwrite it unless we are told so.
55+
fails $ cabal "install"
56+
(["p", "--installdir", installdir, "--install-method", method, "--overwrite-policy", "never"] ++ affixArgs)
57+
-- Successfully overwrite the binary if told so.
58+
cabal "install"
59+
(["p", "--installdir", installdir, "--install-method", method, "--overwrite-policy", "always"] ++ affixArgs)
60+
61+
-- remove the installed binary.
62+
ext <- exeExt
63+
liftIO $ removeFile (installdir </> "p" <.> ext)
64+
-- Make sure we can still install the original program with no program affix without overwriting,
65+
-- even though, the program is already installed with some affix.
66+
cabal "install"
67+
["p", "--installdir", installdir, "--install-method", method, "--overwrite-policy", "never"]
68+
69+
exeExt = isWindows >>= pure . bool "" "exe"

0 commit comments

Comments
 (0)