[ospaths] simplify getConfigDir and introduce normalizePathEnd to make (#8680)
sure path endings are normalized with 0 or 1 trailing sep, taking care of edge cases
This commit is contained in:
parent
96d44fdd0a
commit
b4edfa613b
1 changed files with 50 additions and 4 deletions
|
|
@ -449,6 +449,31 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
|
||||||
elif defined(posix):
|
elif defined(posix):
|
||||||
result = path[0] == '/'
|
result = path[0] == '/'
|
||||||
|
|
||||||
|
|
||||||
|
proc normalizePathEnd(path: var string, trailingSep = false) =
|
||||||
|
## ensures ``path`` has exactly 0 or 1 trailing `DirSep`, depending on
|
||||||
|
## ``trailingSep``, and taking care of edge cases: it preservers whether
|
||||||
|
## a path is absolute or relative, and makes sure trailing sep is `DirSep`,
|
||||||
|
## not `AltSep`.
|
||||||
|
if path.len == 0: return
|
||||||
|
var i = path.len
|
||||||
|
while i >= 1 and path[i-1] in {DirSep, AltSep}: dec(i)
|
||||||
|
if trailingSep:
|
||||||
|
# foo// => foo
|
||||||
|
path.setLen(i)
|
||||||
|
# foo => foo/
|
||||||
|
path.add DirSep
|
||||||
|
elif i>0:
|
||||||
|
# foo// => foo
|
||||||
|
path.setLen(i)
|
||||||
|
else:
|
||||||
|
# // => / (empty case was already taken care of)
|
||||||
|
path = $DirSep
|
||||||
|
|
||||||
|
proc normalizePathEnd(path: string, trailingSep = false): string =
|
||||||
|
result = path
|
||||||
|
result.normalizePathEnd(trailingSep)
|
||||||
|
|
||||||
proc unixToNativePath*(path: string, drive=""): string {.
|
proc unixToNativePath*(path: string, drive=""): string {.
|
||||||
noSideEffect, rtl, extern: "nos$1".} =
|
noSideEffect, rtl, extern: "nos$1".} =
|
||||||
## Converts an UNIX-like path to a native one.
|
## Converts an UNIX-like path to a native one.
|
||||||
|
|
@ -530,12 +555,12 @@ proc getConfigDir*(): string {.rtl, extern: "nos$1",
|
||||||
## "~/.config/", otherwise.
|
## "~/.config/", otherwise.
|
||||||
##
|
##
|
||||||
## An OS-dependent trailing slash is always present at the end of the
|
## An OS-dependent trailing slash is always present at the end of the
|
||||||
## returned string; `\\` on Windows and `/` on all other OSs.
|
## returned string; `\` on Windows and `/` on all other OSs.
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
result = string(getEnv("APPDATA")) & "\\"
|
result = getEnv("APPDATA").string
|
||||||
else:
|
else:
|
||||||
result = string(getEnv("XDG_CONFIG_HOME", "")) & "/"
|
result = getEnv("XDG_CONFIG_HOME", getEnv("HOME").string / ".config").string
|
||||||
if result == "/": result = string(getEnv("HOME")) & "/.config/"
|
result.normalizePathEnd(trailingSep = true)
|
||||||
|
|
||||||
proc getTempDir*(): string {.rtl, extern: "nos$1",
|
proc getTempDir*(): string {.rtl, extern: "nos$1",
|
||||||
tags: [ReadEnvEffect, ReadIOEffect].} =
|
tags: [ReadEnvEffect, ReadIOEffect].} =
|
||||||
|
|
@ -649,3 +674,24 @@ when isMainModule:
|
||||||
|
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
assert quoteShell("") == "''"
|
assert quoteShell("") == "''"
|
||||||
|
|
||||||
|
block normalizePathEndTest:
|
||||||
|
# handle edge cases correctly: shouldn't affect whether path is
|
||||||
|
# absolute/relative
|
||||||
|
doAssert "".normalizePathEnd(true) == ""
|
||||||
|
doAssert "".normalizePathEnd(false) == ""
|
||||||
|
doAssert "/".normalizePathEnd(true) == $DirSep
|
||||||
|
doAssert "/".normalizePathEnd(false) == $DirSep
|
||||||
|
|
||||||
|
when defined(posix):
|
||||||
|
doAssert "//".normalizePathEnd(false) == "/"
|
||||||
|
doAssert "foo.bar//".normalizePathEnd == "foo.bar"
|
||||||
|
doAssert "bar//".normalizePathEnd(trailingSep = true) == "bar/"
|
||||||
|
when defined(Windows):
|
||||||
|
doAssert r"C:\foo\\".normalizePathEnd == r"C:\foo"
|
||||||
|
doAssert r"C:\foo".normalizePathEnd(trailingSep = true) == r"C:\foo\"
|
||||||
|
# this one is controversial: we could argue for returning `D:\` instead,
|
||||||
|
# but this is simplest.
|
||||||
|
doAssert r"D:\".normalizePathEnd == r"D:"
|
||||||
|
doAssert r"E:/".normalizePathEnd(trailingSep = true) == r"E:\"
|
||||||
|
doAssert "/".normalizePathEnd == r"\"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue