mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
[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:
committed by
Andreas Rumpf
parent
96d44fdd0a
commit
b4edfa613b
@@ -449,6 +449,31 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
|
||||
elif defined(posix):
|
||||
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 {.
|
||||
noSideEffect, rtl, extern: "nos$1".} =
|
||||
## Converts an UNIX-like path to a native one.
|
||||
@@ -530,12 +555,12 @@ proc getConfigDir*(): string {.rtl, extern: "nos$1",
|
||||
## "~/.config/", otherwise.
|
||||
##
|
||||
## 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):
|
||||
result = string(getEnv("APPDATA")) & "\\"
|
||||
result = getEnv("APPDATA").string
|
||||
else:
|
||||
result = string(getEnv("XDG_CONFIG_HOME", "")) & "/"
|
||||
if result == "/": result = string(getEnv("HOME")) & "/.config/"
|
||||
result = getEnv("XDG_CONFIG_HOME", getEnv("HOME").string / ".config").string
|
||||
result.normalizePathEnd(trailingSep = true)
|
||||
|
||||
proc getTempDir*(): string {.rtl, extern: "nos$1",
|
||||
tags: [ReadEnvEffect, ReadIOEffect].} =
|
||||
@@ -649,3 +674,24 @@ when isMainModule:
|
||||
|
||||
when defined(posix):
|
||||
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"\"
|
||||
|
||||
Reference in New Issue
Block a user