Skip to content

Commit 50e1bfa

Browse files
committed
cabal-install: don't pass exe name to external commands
Previously the executable name of the external command was passed to external commands as the first argument. This behaviour was adapated from cargo which does this because of reasons that are internal to rust that do not affect GHC Haskell, and are even orthogonal to patterns that see common use in Haskell. Additionally, it complicates the 'simple' case which is what we should optimize for when building such a feature. The previous use case (one executable that serves multiple external subcommands) is still possible by the following means: - using a wrapper around the executable - using a symlink and check argv[0] in the executable Resolves #10275
1 parent 1e3c355 commit 50e1bfa

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,17 +372,20 @@ mainWorker args = do
372372
-> [String]
373373
-> IO (CommandParse Action)
374374
delegateToExternal commands' name cmdArgs = do
375+
-- we rely on cabal's implementation of findProgramOnSearchPath not following
376+
-- symlinks here. If that ever happens, then the argv[0] of the called executable
377+
-- will be different to the intended one and will breakt tools that work by reading it.
375378
mCommand <- findProgramOnSearchPath normal defaultProgramSearchPath ("cabal-" <> name)
376379
case mCommand of
377-
Just (exec, _) -> return (CommandReadyToGo $ \_ -> callExternal exec name cmdArgs)
380+
Just (exec, _) -> return (CommandReadyToGo $ \_ -> callExternal exec cmdArgs)
378381
Nothing -> defaultCommandFallback commands' name cmdArgs
379382

380-
callExternal :: String -> String -> [String] -> IO ()
381-
callExternal exec name cmdArgs = do
383+
callExternal :: String -> [String] -> IO ()
384+
callExternal exec cmdArgs = do
382385
cur_env <- getEnvironment
383386
cabal_exe <- getExecutablePath
384387
let new_env = ("CABAL", cabal_exe) : cur_env
385-
result <- try $ createProcess ((proc exec (name : cmdArgs)){env = Just new_env})
388+
result <- try $ createProcess ((proc exec cmdArgs){env = Just new_env})
386389
case result of
387390
Left ex -> printErrors ["Error executing external command: " ++ show (ex :: SomeException)]
388391
Right (_, _, _, ph) -> waitForProcess ph >>= exitWith

changelog.d/pr-11232.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
synopsis: don't pass exe name to external commands
3+
packages: [cabal-install]
4+
prs: 11232
5+
issues: [10275]
6+
significance: significant
7+
---
8+
9+
Previously the executable name of the external command was passed to external commands as the first argument.
10+
11+
This behaviour was adapated from cargo which does this because of reasons that are internal to rust that do not affect GHC Haskell, and are even orthogonal to patterns that see common use in Haskell.
12+
13+
Additionally, it complicates the 'simple' case which is what we should optimize for when building such a feature - with this change, for any executable `cabal-foo` in your search-path, `cabal foo` will be a valid invocation of that command.
14+
15+
The previous use case (one executable that serves multiple external subcommands) is still possible by the following means:
16+
17+
- using a wrapper around the executable
18+
- using a symlink and check argv\[0\] in the executable
19+

0 commit comments

Comments
 (0)