Skip to content

Commit 529f850

Browse files
authored
Merge pull request #9125 from haskell/mergify/bp/3.10/pr-9002
Fix parsing of password-command option (#6268) (backport #9002)
2 parents 36a7f2f + 9939338 commit 529f850

File tree

6 files changed

+154
-66
lines changed

6 files changed

+154
-66
lines changed

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

Lines changed: 76 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ import Distribution.Client.IndexUtils.IndexState
7272
import qualified Distribution.Client.Init.Types as IT
7373
import qualified Distribution.Client.Init.Defaults as IT
7474
import Distribution.Client.Targets
75-
( UserConstraint, readUserConstraint )
75+
( UserConstraint
76+
, readUserConstraint
77+
)
78+
import Distribution.Deprecated.ParseUtils (parseSpaceList, parseTokenQ)
79+
import Distribution.Deprecated.ReadP (readP_to_E)
7680
import Distribution.Utils.NubList
7781
( NubList, toNubList, fromNubList)
7882

@@ -2004,51 +2008,77 @@ defaultUploadFlags = UploadFlags {
20042008
}
20052009

20062010
uploadCommand :: CommandUI UploadFlags
2007-
uploadCommand = CommandUI {
2008-
commandName = "upload",
2009-
commandSynopsis = "Uploads source packages or documentation to Hackage.",
2010-
commandDescription = Nothing,
2011-
commandNotes = Just $ \_ ->
2012-
"You can store your Hackage login in the ~/.config/cabal/config file\n"
2013-
++ relevantConfigValuesText ["username", "password", "password-command"],
2014-
commandUsage = \pname ->
2015-
"Usage: " ++ pname ++ " upload [FLAGS] TARFILES\n",
2016-
commandDefaultFlags = defaultUploadFlags,
2017-
commandOptions = \_ ->
2018-
[optionVerbosity uploadVerbosity
2019-
(\v flags -> flags { uploadVerbosity = v })
2020-
2021-
,option [] ["publish"]
2022-
"Publish the package instead of uploading it as a candidate."
2023-
uploadCandidate (\v flags -> flags { uploadCandidate = v })
2024-
(noArg (Flag IsPublished))
2025-
2026-
,option ['d'] ["documentation"]
2027-
("Upload documentation instead of a source package. "
2028-
++ "By default, this uploads documentation for a package candidate. "
2029-
++ "To upload documentation for "
2030-
++ "a published package, combine with --publish.")
2031-
uploadDoc (\v flags -> flags { uploadDoc = v })
2032-
trueArg
2033-
2034-
,option ['u'] ["username"]
2035-
"Hackage username."
2036-
uploadUsername (\v flags -> flags { uploadUsername = v })
2037-
(reqArg' "USERNAME" (toFlag . Username)
2038-
(flagToList . fmap unUsername))
2039-
2040-
,option ['p'] ["password"]
2041-
"Hackage password."
2042-
uploadPassword (\v flags -> flags { uploadPassword = v })
2043-
(reqArg' "PASSWORD" (toFlag . Password)
2044-
(flagToList . fmap unPassword))
2045-
2046-
,option ['P'] ["password-command"]
2047-
"Command to get Hackage password."
2048-
uploadPasswordCmd (\v flags -> flags { uploadPasswordCmd = v })
2049-
(reqArg' "PASSWORD" (Flag . words) (fromMaybe [] . flagToMaybe))
2050-
]
2051-
}
2011+
uploadCommand =
2012+
CommandUI
2013+
{ commandName = "upload"
2014+
, commandSynopsis = "Uploads source packages or documentation to Hackage."
2015+
, commandDescription = Nothing
2016+
, commandNotes = Just $ \_ ->
2017+
"You can store your Hackage login in the ~/.config/cabal/config file\n"
2018+
++ relevantConfigValuesText ["username", "password", "password-command"]
2019+
, commandUsage = \pname ->
2020+
"Usage: " ++ pname ++ " upload [FLAGS] TARFILES\n"
2021+
, commandDefaultFlags = defaultUploadFlags
2022+
, commandOptions = \_ ->
2023+
[ optionVerbosity
2024+
uploadVerbosity
2025+
(\v flags -> flags{uploadVerbosity = v})
2026+
, option
2027+
[]
2028+
["publish"]
2029+
"Publish the package instead of uploading it as a candidate."
2030+
uploadCandidate
2031+
(\v flags -> flags{uploadCandidate = v})
2032+
(noArg (Flag IsPublished))
2033+
, option
2034+
['d']
2035+
["documentation"]
2036+
( "Upload documentation instead of a source package. "
2037+
++ "By default, this uploads documentation for a package candidate. "
2038+
++ "To upload documentation for "
2039+
++ "a published package, combine with --publish."
2040+
)
2041+
uploadDoc
2042+
(\v flags -> flags{uploadDoc = v})
2043+
trueArg
2044+
, option
2045+
['u']
2046+
["username"]
2047+
"Hackage username."
2048+
uploadUsername
2049+
(\v flags -> flags{uploadUsername = v})
2050+
( reqArg'
2051+
"USERNAME"
2052+
(toFlag . Username)
2053+
(flagToList . fmap unUsername)
2054+
)
2055+
, option
2056+
['p']
2057+
["password"]
2058+
"Hackage password."
2059+
uploadPassword
2060+
(\v flags -> flags{uploadPassword = v})
2061+
( reqArg'
2062+
"PASSWORD"
2063+
(toFlag . Password)
2064+
(flagToList . fmap unPassword)
2065+
)
2066+
, option
2067+
['P']
2068+
["password-command"]
2069+
"Command to get Hackage password."
2070+
uploadPasswordCmd
2071+
(\v flags -> flags{uploadPasswordCmd = v})
2072+
( reqArg
2073+
"COMMAND"
2074+
( readP_to_E
2075+
("Cannot parse command: " ++)
2076+
(Flag <$> parseSpaceList parseTokenQ)
2077+
)
2078+
(flagElim [] (pure . unwords . fmap show))
2079+
)
2080+
]
2081+
}
20522082

20532083
instance Monoid UploadFlags where
20542084
mempty = gmempty

cabal-install/src/Distribution/Deprecated/ParseUtils.hs

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,43 @@
2121

2222
{-# OPTIONS_HADDOCK hide #-}
2323
{-# LANGUAGE Rank2Types #-}
24-
module Distribution.Deprecated.ParseUtils (
25-
LineNo, PError(..), PWarning(..), locatedErrorMsg, syntaxError, warning,
26-
runP, runE, ParseResult(..), parseFail, showPWarning,
27-
Field(..), lineNo,
28-
FieldDescr(..), readFields,
29-
parseHaskellString, parseTokenQ,
30-
parseOptCommaList,
31-
showFilePath, showToken, showFreeText,
32-
field, simpleField, listField, listFieldWithSep, spaceListField,
33-
newLineListField,
34-
liftField,
35-
readPToMaybe,
36-
37-
fieldParsec, simpleFieldParsec,
38-
listFieldParsec,
39-
commaListFieldParsec,
40-
commaNewLineListFieldParsec,
41-
42-
UnrecFieldParser,
24+
module Distribution.Deprecated.ParseUtils
25+
( LineNo
26+
, PError (..)
27+
, PWarning (..)
28+
, locatedErrorMsg
29+
, syntaxError
30+
, warning
31+
, runP
32+
, runE
33+
, ParseResult (..)
34+
, parseFail
35+
, showPWarning
36+
, Field (..)
37+
, lineNo
38+
, FieldDescr (..)
39+
, readFields
40+
, parseHaskellString
41+
, parseTokenQ
42+
, parseSpaceList
43+
, parseOptCommaList
44+
, showFilePath
45+
, showToken
46+
, showFreeText
47+
, field
48+
, simpleField
49+
, listField
50+
, listFieldWithSep
51+
, spaceListField
52+
, newLineListField
53+
, liftField
54+
, readPToMaybe
55+
, fieldParsec
56+
, simpleFieldParsec
57+
, listFieldParsec
58+
, commaListFieldParsec
59+
, commaNewLineListFieldParsec
60+
, UnrecFieldParser
4361
) where
4462

4563
import Distribution.Client.Compat.Prelude hiding (get)

cabal-testsuite/PackageTests/UserConfig/cabal.out

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ Writing merged config to <ROOT>/cabal.dist/cabal-config.
1212
# cabal user-config
1313
Renaming <ROOT>/cabal.dist/cabal-config to <ROOT>/cabal.dist/cabal-config.backup.
1414
Writing merged config to <ROOT>/cabal.dist/cabal-config.
15+
# cabal user-config
16+
Renaming <ROOT>/cabal.dist/cabal-config to <ROOT>/cabal.dist/cabal-config.backup.
17+
Writing merged config to <ROOT>/cabal.dist/cabal-config.

cabal-testsuite/PackageTests/UserConfig/cabal.test.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,9 @@ main = cabalTest $ do
1515
assertFileDoesContain conf "foo,bar"
1616
cabalG ["--config-file", conf] "user-config" ["update", "-f", "-a", "extra-prog-path: foo, bar"]
1717
assertFileDoesContain conf "foo,bar"
18+
19+
-- regression test for #6268 (password-command parsing)
20+
cabalG ["--config-file", conf]
21+
"user-config" ["update", "-f", "-a", "password-command: sh -c \"echo secret\""]
22+
-- non-quoted tokens do get quoted when writing, but this is expected
23+
assertFileDoesContain conf "password-command: \"sh\" \"-c\" \"echo secret\""

changelog.d/issue-6268

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
synopsis: Fix parsing of password-command option
2+
packages: cabal-install
3+
prs: #9002
4+
issuesa: #6268
5+
6+
description: {
7+
8+
The password-command option did not parse its value correctly.
9+
Quotes were ignored, making many kinds of commands impossible to
10+
express (e.g. `sh -c "foo | bar"`). Also, `cabal user-config`
11+
treated the argument list as a *list of option values*, rather than a
12+
*value that is a list*. As a consequence, `cabal user-config
13+
update` corrupted the value in the config file.
14+
15+
Fixed these issues by parsing the command as a space separated list
16+
of tokens (which may be enclosed in double quotes), and treating the
17+
parsed list-of-token as one value (not multiple).
18+
19+
}

doc/cabal-commands.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,19 @@ to Hackage.
10661066

10671067
.. option:: -P, --password-command
10681068

1069-
Command to get your Hackage password.
1069+
Command to get your Hackage password. Arguments with whitespace
1070+
must be quoted (double-quotes only). For example:
1071+
1072+
::
1073+
1074+
--password-command 'sh -c "grep hackage ~/secrets | cut -d : -f 2"'
1075+
1076+
Or in the config file:
1077+
1078+
::
1079+
1080+
password-command: sh -c "grep hackage ~/secrets | cut -d : -f 2"
1081+
10701082

10711083
cabal report
10721084
^^^^^^^^^^^^

0 commit comments

Comments
 (0)