Skip to content

Commit 11f91fd

Browse files
committed
Don't do any file path manipulations for URLs
- Trim before isURI check for canonicalizeConfigPath - Show path quoted if not already trimmed - Trim before checking with parseURI
1 parent 56594bd commit 11f91fd

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

cabal-install-solver/src/Distribution/Solver/Types/ProjectConfigPath.hs

+26-7
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import System.FilePath
3434
import qualified Data.List.NonEmpty as NE
3535
import Distribution.Solver.Modular.Version (VR)
3636
import Distribution.Pretty (prettyShow)
37+
import Distribution.Utils.String (trim)
3738
import Text.PrettyPrint
3839
import Distribution.Simple.Utils (ordNub)
3940

@@ -98,9 +99,13 @@ instance Structured ProjectConfigPath
9899
-- >>> render . docProjectConfigPath $ ProjectConfigPath $ "D.config" :| ["C.config", "B.config", "A.project"]
99100
-- "D.config\n imported by: C.config\n imported by: B.config\n imported by: A.project"
100101
docProjectConfigPath :: ProjectConfigPath -> Doc
101-
docProjectConfigPath (ProjectConfigPath (p :| [])) = text p
102-
docProjectConfigPath (ProjectConfigPath (p :| ps)) = vcat $
103-
text p : [ text " " <+> text "imported by:" <+> text l | l <- ps ]
102+
docProjectConfigPath (ProjectConfigPath (p :| [])) = quoteUntrimmed p
103+
docProjectConfigPath (ProjectConfigPath (p :| ps)) = vcat $ quoteUntrimmed p :
104+
[ text " " <+> text "imported by:" <+> quoteUntrimmed l | l <- ps ]
105+
106+
-- | If the path has leading or trailing spaces then show it quoted.
107+
quoteUntrimmed :: FilePath -> Doc
108+
quoteUntrimmed s = if trim s /= s then quotes (text s) else text s
104109

105110
-- | Renders the paths as a list without showing which path imports another,
106111
-- like this;
@@ -196,7 +201,7 @@ unconsProjectConfigPath ps = fmap ProjectConfigPath <$> NE.uncons (coerce ps)
196201
makeRelativeConfigPath :: FilePath -> ProjectConfigPath -> ProjectConfigPath
197202
makeRelativeConfigPath dir (ProjectConfigPath p) =
198203
ProjectConfigPath
199-
$ (\segment -> (if isURI segment then segment else makeRelative dir segment))
204+
$ (\segment@(trim -> trimSegment) -> (if isURI trimSegment then trimSegment else makeRelative dir segment))
200205
<$> p
201206

202207
-- | Normalizes and canonicalizes a path removing '.' and '..' indirections.
@@ -273,11 +278,25 @@ makeRelativeConfigPath dir (ProjectConfigPath p) =
273278
-- return $ expected == render (docProjectConfigPath p) ++ "\n"
274279
-- :}
275280
-- True
281+
--
282+
-- "A string is a valid URL potentially surrounded by spaces if, after stripping leading and trailing whitespace from it, it is a valid URL."
283+
-- [W3C/HTML5/URLs](https://www.w3.org/TR/2010/WD-html5-20100624/urls.html)
284+
--
285+
-- Trailing spaces for @ProjectConfigPath@ URLs are trimmed.
286+
--
287+
-- >>> p <- canonicalizeConfigPath "" (ProjectConfigPath $ ("https://www.stackage.org/nightly-2024-12-05/cabal.config ") :| [])
288+
-- >>> render $ docProjectConfigPath p
289+
-- "https://www.stackage.org/nightly-2024-12-05/cabal.config"
290+
--
291+
-- >>> let d = testDir
292+
-- >>> p <- canonicalizeConfigPath d (ProjectConfigPath $ ("https://www.stackage.org/nightly-2024-12-05/cabal.config ") :| [d </> "cabal.project"])
293+
-- >>> render $ docProjectConfigPath p
294+
-- "https://www.stackage.org/nightly-2024-12-05/cabal.config\n imported by: cabal.project"
276295
canonicalizeConfigPath :: FilePath -> ProjectConfigPath -> IO ProjectConfigPath
277296
canonicalizeConfigPath d (ProjectConfigPath p) = do
278-
xs <- sequence $ NE.scanr (\importee -> (>>= \importer ->
279-
if isURI importee
280-
then pure importee
297+
xs <- sequence $ NE.scanr (\importee@(trim -> trimImportee) -> (>>= \importer@(trim -> trimImporter) ->
298+
if isURI trimImportee || isURI trimImporter
299+
then pure trimImportee
281300
else canonicalizePath $ d </> takeDirectory importer </> importee))
282301
(pure ".") p
283302
return . makeRelativeConfigPath d . ProjectConfigPath . NE.fromList $ NE.init xs

cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs

+2-1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ import Distribution.Utils.NubList
141141
, overNubList
142142
, toNubList
143143
)
144+
import Distribution.Utils.String (trim)
144145

145146
import Distribution.Client.HttpUtils
146147
import Distribution.Client.ParseUtils
@@ -342,7 +343,7 @@ parseProjectSkeleton cacheDir httpTransport verbosity projectDir source (Project
342343
fetch pci
343344

344345
fetch :: FilePath -> IO BS.ByteString
345-
fetch pci = case parseURI pci of
346+
fetch pci = case parseURI $ trim pci of
346347
Just uri -> do
347348
let fp = cacheDir </> map (\x -> if isPathSeparator x then '_' else x) (makeValid $ show uri)
348349
createDirectoryIfMissing True cacheDir

0 commit comments

Comments
 (0)