Skip to content

Commit e67a6ca

Browse files
Rename module to resolvePath, rename some constr/functions
1 parent a4c9d08 commit e67a6ca

2 files changed

Lines changed: 58 additions & 57 deletions

File tree

Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-- |
2-
-- Module : Streamly.Coreutils.RealPath
2+
-- Module : Streamly.Coreutils.ResolvePath
33
-- Copyright : (c) 2022 Composewell Technologies
44
-- License : BSD-3-Clause
55
-- Maintainer : streamly@composewell.com
@@ -10,15 +10,15 @@
1010
-- @.@ and @..@ segments, and follow every symbolic link along the way.
1111
-- Corresponds to the shell @realpath@ command.
1212
--
13-
-- Call 'realPath' with @id@ for the default behavior, or compose
13+
-- Call 'resolvePath' with @id@ for the default behavior, or compose
1414
-- modifiers with @(.)@ to customize:
1515
--
1616
-- * 'requireExistence' - control which path components must exist on
1717
-- disk: 'AllParents' (default, GNU @-E@), 'EntirePath' (GNU @-e@),
1818
-- or 'DontRequire' (GNU @-m@).
19-
-- * 'resolveSymlinks' - control when (and whether) symbolic links
19+
-- * 'resolutionMode' - control when (and whether) symbolic links
2020
-- are expanded: 'UseTargetParents' (default, GNU @-P@), 'UseOriginalParents'
21-
-- (GNU @-L@), or 'DontResolve' (GNU @-s@).
21+
-- (GNU @-L@), or 'DontResolveSymlinks' (GNU @-s@).
2222
-- * 'relativeTo' - produce a path relative to a given base directory
2323
-- (GNU @realpath --relative-to=DIR@).
2424
-- * 'relativeIfWithin' - produce a relative path only if it's under
@@ -38,25 +38,25 @@
3838
-- * 'relativeTo' falls back to returning the canonicalized absolute
3939
-- path unchanged when no common prefix exists with the base
4040
-- (e.g. different drives on Windows).
41-
-- * 'resolveSymlinks' 'DontResolve' combined with 'requireExistence'
41+
-- * 'resolutionMode' 'DontResolveSymlinks' combined with 'requireExistence'
4242
-- 'DontRequire' is the only configuration that performs no
4343
-- filesystem access on the path components (only
4444
-- 'System.Directory.getCurrentDirectory' when the path is
4545
-- relative). All other configurations involve some filesystem IO.
46-
-- * Because 'DontResolve' is lexical, it can give a different result
46+
-- * Because 'DontResolveSymlinks' is lexical, it can give a different result
4747
-- than the default mode when the path traverses through a symlink
4848
-- via @..@: @\/link\/..@ lexically resolves to @\/@, but physically
4949
-- resolves to the parent of the symlink's target.
5050

51-
module Streamly.Coreutils.RealPath
52-
( RealPathOptions
51+
module Streamly.Coreutils.ResolvePath
52+
( ResolvePathOptions
5353
, ExistenceCheck (..)
54-
, SymlinkResolution (..)
54+
, ResolutionMode (..)
5555
, requireExistence
56-
, resolveSymlinks
56+
, resolutionMode
5757
, relativeTo
5858
, relativeIfWithin
59-
, realPath
59+
, resolvePath
6060
)
6161
where
6262

@@ -77,10 +77,10 @@ import System.FilePath
7777
--
7878
-- * Thin wrapper over 'System.Directory.canonicalizePath' for the
7979
-- default 'UseTargetParents' (physical) mode; 'UseOriginalParents' and
80-
-- 'DontResolve' use 'makeAbsolute' plus a custom @..@-collapsing
80+
-- 'DontResolveSymlinks' use 'makeAbsolute' plus a custom @..@-collapsing
8181
-- walker ('lexicalCollapse').
8282
--
83-
-- * Why a single 'SymlinkResolution' enum instead of two flags.
83+
-- * Why a single 'ResolutionMode' enum instead of two flags.
8484
-- Symlink expansion is a three-way choice, not two orthogonal
8585
-- booleans. An earlier iteration exposed 'logical' and 'noSymlinks'
8686
-- as separate modifiers, which required a precedence rule for
@@ -135,7 +135,7 @@ import System.FilePath
135135
-- @realpath -e -s@ and @realpath -e -L@.
136136
--
137137
-- * 'relativeTo' always canonicalizes the base physically (following
138-
-- symlinks) regardless of the 'SymlinkResolution' mode. Otherwise
138+
-- symlinks) regardless of the 'ResolutionMode' mode. Otherwise
139139
-- @relativeTo "foo/../bar"@ with a lexical base would give
140140
-- surprising results. If a future use case needs a lexical base,
141141
-- add a separate modifier rather than overloading this one.
@@ -152,7 +152,7 @@ import System.FilePath
152152
-- failure is an exceptional condition, not a lookup miss - matches
153153
-- the error-handling guidance in the package design notes.
154154

155-
-- | Which components of a path must exist on disk for 'realPath' to
155+
-- | Which components of a path must exist on disk for 'resolvePath' to
156156
-- succeed.
157157
--
158158
-- * 'EntirePath': every component - including the leaf - must exist.
@@ -184,37 +184,37 @@ data ExistenceCheck
184184
-- regardless of whether that segment was a symlink. Remaining
185185
-- symlinks in the surviving path are still expanded. Matches GNU
186186
-- @realpath -L@ / @--logical@.
187-
-- * 'DontResolve': no symlinks are expanded anywhere in the path.
187+
-- * 'DontResolveSymlinks': no symlinks are expanded anywhere in the path.
188188
-- @..@ is lexical (same as 'UseOriginalParents'), and symlinks in
189189
-- other components are preserved as-is. Matches GNU @realpath -s@
190190
-- / @--no-symlinks@.
191191
--
192192
-- The three modes produce the same result on paths that contain no
193193
-- symlinks. 'UseTargetParents' and 'UseOriginalParents' diverge when a
194-
-- symlink is followed by @..@; 'DontResolve' diverges from both
194+
-- symlink is followed by @..@; 'DontResolveSymlinks' diverges from both
195195
-- whenever the path contains any symlink.
196-
data SymlinkResolution
196+
data ResolutionMode
197197
= UseTargetParents
198198
| UseOriginalParents
199-
| DontResolve
199+
| DontResolveSymlinks
200200

201-
-- | Options for 'realPath'. Users don't construct 'RealPathOptions'
201+
-- | Options for 'resolvePath'. Users don't construct 'ResolvePathOptions'
202202
-- directly - instead, pass @id@ for the default behavior, or a
203-
-- modifier (or composition of modifiers with @(.)@) to 'realPath'.
204-
data RealPathOptions = RealPathOptions
203+
-- modifier (or composition of modifiers with @(.)@) to 'resolvePath'.
204+
data ResolvePathOptions = ResolvePathOptions
205205
{ _existenceCheck :: ExistenceCheck
206-
, _symlinkResolution :: SymlinkResolution
206+
, _resolutionMode :: ResolutionMode
207207
, _relativeTo :: Maybe FilePath
208208
, _relativeIfWithin :: Maybe FilePath
209209
}
210210

211211
-- Default configuration: the seed value that modifiers are composed
212212
-- onto. Users supply @id@ (or a modifier chain) at the call site
213213
-- rather than referring to this directly.
214-
defaultConfig :: RealPathOptions
215-
defaultConfig = RealPathOptions
214+
defaultConfig :: ResolvePathOptions
215+
defaultConfig = ResolvePathOptions
216216
{ _existenceCheck = AllParents
217-
, _symlinkResolution = UseTargetParents
217+
, _resolutionMode = UseTargetParents
218218
, _relativeTo = Nothing
219219
, _relativeIfWithin = Nothing
220220
}
@@ -229,12 +229,12 @@ defaultConfig = RealPathOptions
229229
-- 'EntirePath' rejects a path whose leaf does not exist:
230230
--
231231
-- >>> cwd <- getCurrentDirectory
232-
-- >>> r1 <- realPath (requireExistence EntirePath) cwd
233-
-- >>> r2 <- realPath (requireExistence EntirePath) r1
232+
-- >>> r1 <- resolvePath (requireExistence EntirePath) cwd
233+
-- >>> r2 <- resolvePath (requireExistence EntirePath) r1
234234
-- >>> r1 == r2
235235
-- True
236236
--
237-
-- >>> result <- try (realPath (requireExistence EntirePath) "/definitely/does/not/exist/xyzzy") :: IO (Either SomeException FilePath)
237+
-- >>> result <- try (resolvePath (requireExistence EntirePath) "/definitely/does/not/exist/xyzzy") :: IO (Either SomeException FilePath)
238238
-- >>> either (const True) (const False) result
239239
-- True
240240
--
@@ -244,27 +244,28 @@ defaultConfig = RealPathOptions
244244
-- the existing prefix):
245245
--
246246
-- >>> tmp <- getTemporaryDirectory
247-
-- >>> r1 <- realPath id (tmp </> "missing-leaf")
247+
-- >>> r1 <- resolvePath id (tmp </> "missing-leaf")
248248
-- >>> r2 <- canonicalizePath (tmp </> "missing-leaf")
249249
-- >>> r1 == r2
250250
-- True
251251
--
252252
-- 'AllParents' rejects a path whose parent does not exist:
253253
--
254-
-- >>> result <- try (realPath id "/definitely/does/not/exist/child") :: IO (Either SomeException FilePath)
254+
-- >>> result <- try (resolvePath id "/definitely/does/not/exist/child") :: IO (Either SomeException FilePath)
255255
-- >>> either (const True) (const False) result
256256
-- True
257257
--
258258
-- 'DontRequire' accepts any path, existent or not:
259259
--
260-
-- >>> r <- realPath (requireExistence DontRequire) "/definitely/does/not/exist/child"
260+
-- >>> r <- resolvePath (requireExistence DontRequire) "/definitely/does/not/exist/child"
261261
-- >>> null r
262262
-- False
263-
requireExistence :: ExistenceCheck -> RealPathOptions -> RealPathOptions
263+
requireExistence :: ExistenceCheck -> ResolvePathOptions -> ResolvePathOptions
264264
requireExistence check opts = opts { _existenceCheck = check }
265265

266-
-- | Choose how @..@ and symbolic links interact. See
267-
-- 'SymlinkResolution' for the three modes and a full explanation.
266+
-- | Set the resolution mode - how @..@ segments and symbolic links
267+
-- are handled. See 'ResolutionMode' for the three modes and a full
268+
-- explanation.
268269
--
269270
-- Default (without this modifier): 'UseTargetParents' - @..@ ascends
270271
-- from the symlink's target (GNU @realpath@'s physical mode, @-P@).
@@ -277,24 +278,24 @@ requireExistence check opts = opts { _existenceCheck = check }
277278
-- base):
278279
--
279280
-- >>> tmp <- getTemporaryDirectory
280-
-- >>> let opts m = resolveSymlinks m . requireExistence DontRequire
281-
-- >>> r1 <- realPath (opts UseOriginalParents) (tmp </> "a" </> ".." </> "b")
282-
-- >>> r2 <- realPath (requireExistence DontRequire) (tmp </> "b")
281+
-- >>> let opts m = resolutionMode m . requireExistence DontRequire
282+
-- >>> r1 <- resolvePath (opts UseOriginalParents) (tmp </> "a" </> ".." </> "b")
283+
-- >>> r2 <- resolvePath (requireExistence DontRequire) (tmp </> "b")
283284
-- >>> r1 == r2
284285
-- True
285286
--
286-
-- 'DontResolve' collapses @..@ and @.@ textually and performs no
287+
-- 'DontResolveSymlinks' collapses @..@ and @.@ textually and performs no
287288
-- symlink resolution (so the base is not canonicalized - the result
288289
-- may differ from 'UseTargetParents' when the base contains symlinks):
289290
--
290-
-- >>> r <- realPath (opts DontResolve) (tmp </> "a" </> ".." </> "b")
291+
-- >>> r <- resolvePath (opts DontResolveSymlinks) (tmp </> "a" </> ".." </> "b")
291292
-- >>> r == tmp </> "b"
292293
-- True
293-
-- >>> r <- realPath (opts DontResolve) (tmp </> "." </> "x")
294+
-- >>> r <- resolvePath (opts DontResolveSymlinks) (tmp </> "." </> "x")
294295
-- >>> r == tmp </> "x"
295296
-- True
296-
resolveSymlinks :: SymlinkResolution -> RealPathOptions -> RealPathOptions
297-
resolveSymlinks mode opts = opts { _symlinkResolution = mode }
297+
resolutionMode :: ResolutionMode -> ResolvePathOptions -> ResolvePathOptions
298+
resolutionMode mode opts = opts { _resolutionMode = mode }
298299

299300
-- | Return the canonical path relative to the given base directory.
300301
-- Corresponds to GNU @realpath --relative-to=DIR@.
@@ -312,9 +313,9 @@ resolveSymlinks mode opts = opts { _symlinkResolution = mode }
312313
-- A path relative to itself is @\".\"@:
313314
--
314315
-- >>> cwd <- getCurrentDirectory
315-
-- >>> realPath (relativeTo cwd) cwd
316+
-- >>> resolvePath (relativeTo cwd) cwd
316317
-- "."
317-
relativeTo :: FilePath -> RealPathOptions -> RealPathOptions
318+
relativeTo :: FilePath -> ResolvePathOptions -> ResolvePathOptions
318319
relativeTo base opts = opts { _relativeTo = Just base }
319320

320321
-- | Return a relative path only when the resolved path lies within
@@ -334,16 +335,16 @@ relativeTo base opts = opts { _relativeTo = Just base }
334335
--
335336
-- >>> tmp <- getTemporaryDirectory
336337
-- >>> let child = tmp </> "missing-leaf"
337-
-- >>> realPath (relativeIfWithin tmp) child
338+
-- >>> resolvePath (relativeIfWithin tmp) child
338339
-- "missing-leaf"
339340
--
340341
-- Outside the boundary, the absolute path is returned unchanged:
341342
--
342-
-- >>> r1 <- realPath (relativeIfWithin tmp) "/"
343+
-- >>> r1 <- resolvePath (relativeIfWithin tmp) "/"
343344
-- >>> r2 <- canonicalizePath "/"
344345
-- >>> r1 == r2
345346
-- True
346-
relativeIfWithin :: FilePath -> RealPathOptions -> RealPathOptions
347+
relativeIfWithin :: FilePath -> ResolvePathOptions -> ResolvePathOptions
347348
relativeIfWithin dir opts = opts { _relativeIfWithin = Just dir }
348349

349350
-- Collapse @.@ and @..@ segments lexically. On absolute paths, @..@
@@ -384,14 +385,14 @@ checkExistence check path = case check of
384385
exists <- doesPathExist path
385386
when (not exists) $
386387
ioError
387-
(userError ("realPath: path does not exist: " ++ path))
388+
(userError ("resolvePath: path does not exist: " ++ path))
388389
AllParents -> do
389390
let parent = takeDirectory path
390391
parentExists <- doesDirectoryExist parent
391392
when (not parentExists) $
392393
ioError
393394
(userError
394-
("realPath: parent directory does not exist: "
395+
("resolvePath: parent directory does not exist: "
395396
++ parent))
396397

397398
-- Is the second path a descendant of (or equal to) the first?
@@ -415,21 +416,21 @@ isPathUnder dir p = splitDirectories dir `isPrefixOf` splitDirectories p
415416
-- The default-mode result on an existing directory is absolute:
416417
--
417418
-- >>> cwd <- getCurrentDirectory
418-
-- >>> r <- realPath id cwd
419+
-- >>> r <- resolvePath id cwd
419420
-- >>> isAbsolute r
420421
-- True
421-
realPath
422-
:: (RealPathOptions -> RealPathOptions)
422+
resolvePath
423+
:: (ResolvePathOptions -> ResolvePathOptions)
423424
-> FilePath
424425
-> IO FilePath
425-
realPath modifier path = do
426+
resolvePath modifier path = do
426427
let opts = modifier defaultConfig
427428
checkExistence (_existenceCheck opts) path
428-
resolved <- case _symlinkResolution opts of
429+
resolved <- case _resolutionMode opts of
429430
UseTargetParents -> canonicalizePath path
430431
UseOriginalParents ->
431432
fmap lexicalCollapse (makeAbsolute path) >>= canonicalizePath
432-
DontResolve -> fmap lexicalCollapse (makeAbsolute path)
433+
DontResolveSymlinks -> fmap lexicalCollapse (makeAbsolute path)
433434
-- Relativization and containment logic:
434435
-- * _relativeTo chooses the target to relativize against.
435436
-- * _relativeIfWithin gates whether relativization fires: if

streamly-coreutils.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ library
130130
, Streamly.Coreutils.Mkdir
131131
, Streamly.Coreutils.Mv
132132
, Streamly.Coreutils.ReadLink
133-
, Streamly.Coreutils.RealPath
133+
, Streamly.Coreutils.ResolvePath
134134
, Streamly.Coreutils.Rm
135135
, Streamly.Coreutils.Sh
136136
, Streamly.Coreutils.Sleep

0 commit comments

Comments
 (0)