@@ -15,6 +15,9 @@ module Distribution.Client.Types.Repo
1515 , repoName
1616 , isRepoRemote
1717 , maybeRepoRemote
18+
19+ -- * Windows
20+ , normaliseFileNoIndexURI
1821 ) where
1922
2023import Distribution.Client.Compat.Prelude
@@ -23,6 +26,7 @@ import Prelude ()
2326import Network.URI (URI (.. ), nullURI , parseAbsoluteURI , uriToString )
2427
2528import Distribution.Simple.Utils (toUTF8BS )
29+ import Distribution.System (OS (Windows ))
2630
2731import Distribution.Client.HashValue (hashValue , showHashValue , truncateHash )
2832
@@ -32,6 +36,9 @@ import qualified Text.PrettyPrint as Disp
3236
3337import 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
190197repoName (RepoLocalNoIndex r _) = localRepoName r
191198repoName (RepoRemote r _) = remoteRepoName r
192199repoName (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]
0 commit comments