summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md4
-rw-r--r--compiler/commands.nim2
-rw-r--r--lib/pure/os.nim17
-rw-r--r--tests/js/tos.nim7
-rw-r--r--tests/stdlib/tos.nim12
-rw-r--r--tests/test_nimscript.nims3
6 files changed, 37 insertions, 8 deletions
diff --git a/changelog.md b/changelog.md
index 0e0b6ce3d..d929ea0d9 100644
--- a/changelog.md
+++ b/changelog.md
@@ -27,7 +27,9 @@
   It was an oversight to be included in v1.0.
 - `options` now treats `proc` like other pointer types, meaning `nil` proc variables
   are converted to `None`.
-
+- `relativePath("foo", "foo")` is now `"."`, not `""`, as `""` means invalid path
+  and shouldn't be conflated with `"."`; use -d:nimOldRelativePathBehavior to restore the old
+  behavioe
 
 ### Breaking changes in the compiler
 
diff --git a/compiler/commands.nim b/compiler/commands.nim
index ca6ef5d94..cecb07386 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -865,6 +865,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
       defineSymbol(conf.symbols, "NimMinor", "0")
       # always be compatible with 1.0.2 for now:
       defineSymbol(conf.symbols, "NimPatch", "2")
+      # old behaviors go here:
+      defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
     else:
       localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
   of "benchmarkvm":
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 452c856a6..aff91fccb 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -65,6 +65,8 @@ when weirdTarget and defined(nimErrorProcCanHaveBody):
 else:
   {.pragma: noNimScript.}
 
+proc normalizePathAux(path: var string){.inline, raises: [], noSideEffect.}
+
 type
   ReadEnvEffect* = object of ReadIOEffect   ## Effect that denotes a read
                                             ## from an environment variable.
@@ -359,9 +361,13 @@ proc relativePath*(path, base: string; sep = DirSep): string {.
     assert relativePath("/Users/me/bar/z.nim", "/Users/me", '/') == "bar/z.nim"
     assert relativePath("", "/users/moo", '/') == ""
     assert relativePath("foo", ".", '/') == "foo"
+    assert relativePath("foo", "foo", '/') == "."
 
   if path.len == 0: return ""
-  let base = if base == ".": "" else: base
+  var base = if base == ".": "" else: base
+  var path = path
+  path.normalizePathAux
+  base.normalizePathAux
 
   when doslikeFileSystem:
     if isAbsolute(path) and isAbsolute(base):
@@ -411,6 +417,9 @@ proc relativePath*(path, base: string; sep = DirSep): string {.
     if not f.hasNext(path): break
     ff = f.next(path)
 
+  when not defined(nimOldRelativePathBehavior):
+    if result.len == 0: result.add "."
+
 proc isRelativeTo*(path: string, base: string): bool {.since: (1, 1).} =
   ## Returns true if `path` is relative to `base`.
   runnableExamples:
@@ -1353,7 +1362,7 @@ when not weirdTarget:
         raise newException(ValueError, "The specified root is not absolute: " & root)
       joinPath(root, path)
 
-proc normalizePath*(path: var string) {.rtl, extern: "nos$1", tags: [], noNimScript.} =
+proc normalizePath*(path: var string) {.rtl, extern: "nos$1", tags: [].} =
   ## Normalize a path.
   ##
   ## Consecutive directory separators are collapsed, including an initial double slash.
@@ -1402,7 +1411,9 @@ proc normalizePath*(path: var string) {.rtl, extern: "nos$1", tags: [], noNimScr
     else:
       path = "."
 
-proc normalizedPath*(path: string): string {.rtl, extern: "nos$1", tags: [], noNimScript.} =
+proc normalizePathAux(path: var string) = normalizePath(path)
+
+proc normalizedPath*(path: string): string {.rtl, extern: "nos$1", tags: [].} =
   ## Returns a normalized path for the current OS.
   ##
   ## See also:
diff --git a/tests/js/tos.nim b/tests/js/tos.nim
new file mode 100644
index 000000000..7395a0ad7
--- /dev/null
+++ b/tests/js/tos.nim
@@ -0,0 +1,7 @@
+static: doAssert defined(nodejs)
+
+import os
+
+block:
+  doAssert "./foo//./bar/".normalizedPath == "foo/bar"
+  doAssert relativePath(".//foo/bar", "foo") == "bar"
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim
index 03fc1f1e9..02a449b8c 100644
--- a/tests/stdlib/tos.nim
+++ b/tests/stdlib/tos.nim
@@ -329,15 +329,19 @@ block ospaths:
   doAssert relativePath("/Users/me/bar/z.nim", "/Users/me", '/') == "bar/z.nim"
   doAssert relativePath("", "/users/moo", '/') == ""
   doAssert relativePath("foo", "", '/') == "foo"
-  doAssert relativePath("/foo", "/Foo", '/') == (when FileSystemCaseSensitive: "../foo" else: "")
-  doAssert relativePath("/Foo", "/foo", '/') == (when FileSystemCaseSensitive: "../Foo" else: "")
-  doAssert relativePath("/foo", "/fOO", '/') == (when FileSystemCaseSensitive: "../foo" else: "")
-  doAssert relativePath("/foO", "/foo", '/') == (when FileSystemCaseSensitive: "../foO" else: "")
+  doAssert relativePath("/foo", "/Foo", '/') == (when FileSystemCaseSensitive: "../foo" else: ".")
+  doAssert relativePath("/Foo", "/foo", '/') == (when FileSystemCaseSensitive: "../Foo" else: ".")
+  doAssert relativePath("/foo", "/fOO", '/') == (when FileSystemCaseSensitive: "../foo" else: ".")
+  doAssert relativePath("/foO", "/foo", '/') == (when FileSystemCaseSensitive: "../foO" else: ".")
 
   doAssert relativePath("foo", ".", '/') == "foo"
   doAssert relativePath(".", ".", '/') == "."
   doAssert relativePath("..", ".", '/') == ".."
 
+  doAssert relativePath("foo", "foo") == "."
+  doAssert relativePath("", "foo") == ""
+  doAssert relativePath("././/foo", "foo//./") == "."
+
   when doslikeFileSystem:
     doAssert relativePath(r"c:\foo.nim", r"C:\") == r"foo.nim"
     doAssert relativePath(r"c:\foo\bar\baz.nim", r"c:\foo") == r"bar\baz.nim"
diff --git a/tests/test_nimscript.nims b/tests/test_nimscript.nims
index 3efbb0a4c..91b23efbf 100644
--- a/tests/test_nimscript.nims
+++ b/tests/test_nimscript.nims
@@ -22,4 +22,7 @@ import unicode
 import uri
 import macros
 
+block:
+  doAssert "./foo//./bar/".normalizedPath == "foo/bar".unixToNativePath
+
 echo "Nimscript imports are successful."