Skip to content

Commit 4edd5c4

Browse files
authored
Merge pull request #10746 from jasagredo/js/local-noindex-2
Fix file+noindex URI usage on Windows
2 parents 9b8540d + 9a0e8a4 commit 4edd5c4

File tree

10 files changed

+65
-79
lines changed

10 files changed

+65
-79
lines changed

Cabal-syntax/src/Distribution/Utils/Path.hs

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ module Distribution.Utils.Path
6767

6868
-- ** Module names
6969
, moduleNameSymbolicPath
70-
71-
-- * Windows
72-
, asPosixPath
7370
) where
7471

7572
import Distribution.Compat.Prelude
@@ -89,8 +86,6 @@ import qualified Distribution.Compat.CharParsing as P
8986

9087
import qualified System.Directory as Directory
9188
import qualified System.FilePath as FilePath
92-
import qualified System.FilePath.Posix as Posix
93-
import qualified System.FilePath.Windows as Windows
9489

9590
import Data.Kind
9691
( Type
@@ -536,38 +531,3 @@ data Response
536531
--
537532
-- See Note [Symbolic paths] in Distribution.Utils.Path.
538533
data PkgConf
539-
540-
-------------------------------------------------------------------------------
541-
542-
-- * Windows utils
543-
544-
-------------------------------------------------------------------------------
545-
546-
-- | Sometimes we need to represent a Windows path (that might have been
547-
-- normalized) as a POSIX path, for example in URIs, as that is what
548-
-- @network-uri@ understands. Furthermore they need to use the @\\\\.\\@ DOS
549-
-- device syntax or otherwise the filepath will be unusable.
550-
--
551-
-- >>> import Network.URI
552-
-- >>> uriPath <$> parseURI "file+noindex://C:/foo.txt"
553-
-- Just "/foo.txt"
554-
-- >>> parseURI "file+noindex://C:\foo.txt"
555-
-- Nothing
556-
-- >>> uriPath <$> parseURI "file+noindex:///C:/foo.txt"
557-
-- Just "/C:/foo.txt"
558-
-- >>> uriPath <$> parseURI "file+noindex:////./C:/foo.txt"
559-
-- Just "//./C:/foo.txt"
560-
--
561-
-- Out of the ones above, only the last one can be used from anywhere in the
562-
-- system, after normalization into @"\\\\.\\C:/foo.txt"@ (see filepath#247 for
563-
-- why there is a forward slash there):
564-
--
565-
-- >>> import Network.URI
566-
-- >>> import qualified System.FilePath.Windows as Windows
567-
-- >>> Windows.normalise . uriPath <$> parseURI "file+noindex:////./C:/foo.txt"
568-
-- Just "\\\\.\\C:/foo.txt"
569-
asPosixPath :: FilePath -> FilePath
570-
asPosixPath p =
571-
-- We don't use 'isPathSeparator' because @Windows.isPathSeparator
572-
-- Posix.pathSeparator == True@.
573-
[if x == Windows.pathSeparator then Posix.pathSeparator else x | x <- p]

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ ghcid-cli: ## Run ghcid for the cabal-install executable.
125125

126126
.PHONY: doctest
127127
doctest: ## Run doctests.
128-
cd Cabal-syntax && $(DOCTEST) --build-depends=network-uri
128+
cd Cabal-syntax && $(DOCTEST)
129129
cd Cabal-described && $(DOCTEST)
130130
cd Cabal && $(DOCTEST)
131131
cd cabal-install-solver && $(DOCTEST)

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,8 +1698,6 @@ postProcessRepo lineno reponameStr repo0 = do
16981698
Left $
16991699
LocalRepo
17001700
reponame
1701-
-- Normalization of Windows paths that use @//./@ does not fully
1702-
-- normalize the path (see filepath#247), but it is still usable.
17031701
(normalise (uriPath uri))
17041702
(uriFragment uri == "#shared-cache")
17051703
_ -> do

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

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import Distribution.Types.Flag (FlagName, parsecFlagAssignment)
3939

4040
import Distribution.Client.ProjectConfig.Types
4141
import Distribution.Client.Types.AllowNewer (AllowNewer (..), AllowOlder (..))
42-
import Distribution.Client.Types.Repo (LocalRepo (..), RemoteRepo (..), emptyRemoteRepo)
42+
import Distribution.Client.Types.Repo (LocalRepo (..), RemoteRepo (..), emptyRemoteRepo, normaliseFileNoIndexURI)
4343
import Distribution.Client.Types.RepoName (RepoName (..), unRepoName)
4444
import Distribution.Client.Types.SourceRepo (SourceRepoList, sourceRepositoryPackageGrammar)
4545

@@ -175,7 +175,7 @@ import Distribution.Simple.Command
175175
, option
176176
, reqArg'
177177
)
178-
import Distribution.System (Arch, OS (Windows), buildOS)
178+
import Distribution.System (Arch, OS, buildOS)
179179
import Distribution.Types.PackageVersionConstraint
180180
( PackageVersionConstraint
181181
)
@@ -2050,20 +2050,6 @@ remoteRepoSectionDescr =
20502050
(if sharedCache then "#shared-cache" else "")
20512051
}
20522052

2053-
-- | When on Windows, we need to convert the path to be POSIX-style.
2054-
--
2055-
-- >>> normaliseFileNoIndexURI Windows (URI "file+noindex:" (Just nullURIAuth) "\\\\.\\C:\\dev\\foo" "" "")
2056-
-- file+noindex:////./C:/dev/foo
2057-
--
2058-
-- See haddocks of 'asPosixPath' for some examples of why this is needed for
2059-
-- @network-uri@.
2060-
normaliseFileNoIndexURI :: OS -> URI -> URI
2061-
normaliseFileNoIndexURI os uri@(URI scheme auth path query fragment)
2062-
| "file+noindex:" <- scheme
2063-
, Windows <- os =
2064-
URI scheme auth (asPosixPath path) query fragment
2065-
| otherwise = uri
2066-
20672053
-------------------------------
20682054
-- Local field utils
20692055
--

cabal-install/src/Distribution/Client/Types/Repo.hs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ module Distribution.Client.Types.Repo
1515
, repoName
1616
, isRepoRemote
1717
, maybeRepoRemote
18+
19+
-- * Windows
20+
, normaliseFileNoIndexURI
1821
) where
1922

2023
import Distribution.Client.Compat.Prelude
@@ -23,6 +26,7 @@ import Prelude ()
2326
import Network.URI (URI (..), nullURI, parseAbsoluteURI, uriToString)
2427

2528
import Distribution.Simple.Utils (toUTF8BS)
29+
import Distribution.System (OS (Windows))
2630

2731
import Distribution.Client.HashValue (hashValue, showHashValue, truncateHash)
2832

@@ -32,6 +36,9 @@ import qualified Text.PrettyPrint as Disp
3236

3337
import Distribution.Client.Types.RepoName
3438

39+
import qualified System.FilePath.Posix as Posix
40+
import qualified System.FilePath.Windows as Windows
41+
3542
-------------------------------------------------------------------------------
3643
-- Remote repository
3744
-------------------------------------------------------------------------------
@@ -190,3 +197,41 @@ repoName :: Repo -> RepoName
190197
repoName (RepoLocalNoIndex r _) = localRepoName r
191198
repoName (RepoRemote r _) = remoteRepoName r
192199
repoName (RepoSecure r _) = remoteRepoName r
200+
201+
-------------------------------------------------------------------------------
202+
203+
-- * Windows utils
204+
205+
-------------------------------------------------------------------------------
206+
207+
-- | When on Windows, we need to convert the paths in URIs to be POSIX-style.
208+
--
209+
-- >>> import Network.URI
210+
-- >>> normaliseFileNoIndexURI Windows (URI "file+noindex:" (Just nullURIAuth) "C:\\dev\\foo" "" "")
211+
-- file+noindex:C:/dev/foo
212+
--
213+
-- Other formats of file paths are not understood by @network-uri@:
214+
--
215+
-- >>> import Network.URI
216+
-- >>> uriPath <$> parseURI "file+noindex://C:/foo.txt"
217+
-- Just "/foo.txt"
218+
-- >>> parseURI "file+noindex://C:\foo.txt"
219+
-- Nothing
220+
-- >>> uriPath <$> parseURI "file+noindex:///C:/foo.txt"
221+
-- Just "/C:/foo.txt"
222+
-- >>> uriPath <$> parseURI "file+noindex:C:/foo.txt"
223+
-- Just "C:/foo.txt"
224+
--
225+
-- Out of the ones above, only the last one can be used from anywhere in the
226+
-- system.
227+
normaliseFileNoIndexURI :: OS -> URI -> URI
228+
normaliseFileNoIndexURI os uri@(URI scheme _auth path query fragment)
229+
| "file+noindex:" <- scheme
230+
, Windows <- os =
231+
URI scheme Nothing (asPosixPath path) query fragment
232+
| otherwise = uri
233+
where
234+
asPosixPath p =
235+
-- We don't use 'isPathSeparator' because @Windows.isPathSeparator
236+
-- Posix.pathSeparator == True@.
237+
[if x == Windows.pathSeparator then Posix.pathSeparator else x | x <- p]

cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ instance Arbitrary LocalRepo where
10181018
LocalRepo
10191019
<$> arbitrary
10201020
<*> elements
1021-
( (if buildOS == Windows then map (normalise . ("//./C:" ++)) else id)
1021+
( (if buildOS == Windows then map (normalise . ("C:" ++)) else id)
10221022
["/tmp/foo", "/tmp/bar"]
10231023
) -- TODO: generate valid absolute paths
10241024
<*> arbitrary

cabal-testsuite/src/Test/Cabal/OutputNormalizer.hs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,6 @@ normalizeOutput nenv =
7878
else id)
7979
. normalizeBuildInfoJson
8080
. maybe id normalizePathCmdOutput (normalizerCabalInstallVersion nenv)
81-
-- Munge away \\.\C:/ prefix on paths (Windows). We convert @\\.\C:/@ to
82-
-- @\@. We need to do this before the step above as that one would convert
83-
-- @\\.\@ to @\.\@.
84-
--
85-
-- These paths might come up in file+noindex URIs due to @filepath@
86-
-- normalizing @//./C:/foo.txt@ paths to @\\.\C:/foo.txt@, see
87-
-- (filepath#247).
88-
. (if buildOS == Windows then resub "\\\\\\\\\\.\\\\([A-Z]):/" "\\\\" else id)
8981
-- hackage-security locks occur non-deterministically
9082
. resub "(Released|Acquired|Waiting) .*hackage-security-lock\n" ""
9183
. resub "installed: [0-9]+(\\.[0-9]+)*" "installed: <VERSION>"

cabal-testsuite/src/Test/Cabal/Prelude.hs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import Distribution.PackageDescription
4848
import Test.Utils.TempTestDir (withTestDir)
4949
import Distribution.Verbosity (normal)
5050
import Distribution.Utils.Path
51-
( asPosixPath, makeSymbolicPath, relativeSymbolicPath, interpretSymbolicPathCWD )
51+
( makeSymbolicPath, relativeSymbolicPath, interpretSymbolicPathCWD )
5252

5353
import Distribution.Compat.Stack
5454

@@ -77,6 +77,8 @@ import System.Environment
7777
import qualified System.FilePath.Glob as Glob (globDir1, compile)
7878
import System.Process
7979
import System.IO
80+
import qualified System.FilePath.Posix as Posix
81+
import qualified System.FilePath.Windows as Windows
8082

8183
#ifndef mingw32_HOST_OS
8284
import System.Posix.Resource
@@ -612,9 +614,12 @@ withRepoNoUpdate repo_dir m = do
612614
withReaderT (\env' -> env' { testHaveRepo = True }) m
613615
-- TODO: Arguably should undo everything when we're done...
614616
where
615-
repoUri env ="file+noindex://" ++ (if isWindows
616-
then joinDrive "//./" . asPosixPath
617-
else id) (testRepoDir env)
617+
repoUri env ="file+noindex:" ++ (if isWindows
618+
then map (\x -> if x == Windows.pathSeparator
619+
then Posix.pathSeparator
620+
else x
621+
)
622+
else ("//" ++)) (testRepoDir env)
618623

619624
-- | Given a directory (relative to the 'testCurrentDir') containing
620625
-- a series of directories representing packages, generate an

changelog.d/pr-10728

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
synopsis: Fix `file+noindex` URI usage on Windows
22
packages: cabal-install
3-
prs: #10728
3+
prs: #10728 #10746
44
issues: #10703
55
significance:
66

77
description: {
88

9-
- `file+noindex` repositories in Windows systems must use the format `file+noindex:////./C:/path/to/repo`.
10-
This syntax comes from https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths,
11-
and is the only syntax for DOS paths fully supported by the `network-uri` package, which Cabal uses to
12-
interpret URIs in repository stanzas.
9+
- `file+noindex` repositories in Windows systems must use the format
10+
`file+noindex:C:/path/to/repo`. This is the only syntax for DOS paths fully
11+
supported by the `network-uri` package, which Cabal uses to interpret URIs in
12+
repository stanzas.
1313

1414
}

doc/config.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ repository.
201201
corresponding ``package-name-version.cabal`` files as new revisions.
202202

203203
.. note::
204-
On Windows systems, the path has to be prefixed by ``//./`` as in
205-
``url: file+noindex:////./C:/absolute/path/to/directory``.
204+
On Windows systems, the URL must start directly with the absolute path as in
205+
``url: file+noindex:C:/absolute/path/to/directory``.
206206

207207
For example, if ``/absolute/path/to/directory`` looks like
208208
::

0 commit comments

Comments
 (0)