summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md1
-rw-r--r--lib/pure/os.nim16
-rw-r--r--testament/testament.nim11
-rw-r--r--tests/stdlib/tos.nim10
4 files changed, 28 insertions, 10 deletions
diff --git a/changelog.md b/changelog.md
index 623b3f6bc..b9fb48117 100644
--- a/changelog.md
+++ b/changelog.md
@@ -112,6 +112,7 @@
 
 - new proc `heapqueue.find[T](heap: HeapQueue[T], x: T): int` to get index of element ``x``.
 - Add `rstgen.rstToLatex` convenience proc for `renderRstToOut` and `initRstGenerator` with `outLatex` output.
+- Add `os.normalizeExe`, eg: `koch` => `./koch`.
 
 
 ## Language changes
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 97e414d44..79cd27e10 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1407,6 +1407,18 @@ proc absolutePath*(path: string, root = getCurrentDir()): string =
 proc absolutePathInternal(path: string): string =
   absolutePath(path, getCurrentDir())
 
+proc normalizeExe*(file: var string) {.since: (1, 3, 5).} =
+  ## on posix, prepends `./` if `file` doesn't contain `/` and is not `"", ".", ".."`.
+  runnableExamples:
+    import sugar
+    when defined(posix):
+      doAssert "foo".dup(normalizeExe) == "./foo"
+      doAssert "foo/../bar".dup(normalizeExe) == "foo/../bar"
+    doAssert "".dup(normalizeExe) == ""
+  when defined(posix):
+    if file.len > 0 and DirSep notin file and file != "." and file != "..":
+      file = "./" & file
+
 proc normalizePath*(path: var string) {.rtl, extern: "nos$1", tags: [].} =
   ## Normalize a path.
   ##
@@ -1420,8 +1432,8 @@ proc normalizePath*(path: var string) {.rtl, extern: "nos$1", tags: [].} =
   ##
   ## See also:
   ## * `absolutePath proc <#absolutePath,string>`_
-  ## * `normalizedPath proc <#normalizedPath,string>`_ for a version which returns
-  ##   a new string
+  ## * `normalizedPath proc <#normalizedPath,string>`_ for outplace version
+  ## * `normalizeExe proc <#normalizeExe,string>`_
   runnableExamples:
     when defined(posix):
       var a = "a///b//..//c///d"
diff --git a/testament/testament.nim b/testament/testament.nim
index f83b244c2..69b7e322e 100644
--- a/testament/testament.nim
+++ b/testament/testament.nim
@@ -13,8 +13,8 @@ import
   strutils, pegs, os, osproc, streams, json,
   backend, parseopt, specs, htmlgen, browsers, terminal,
   algorithm, times, md5, sequtils, azure
-
-include compiler/nodejs
+from std/sugar import dup
+import compiler/nodejs
 
 var useColors = true
 var backendLogging = true
@@ -450,12 +450,7 @@ proc testSpecHelper(r: var TResults, test: TTest, expected: TSpec,
             exeCmd = nodejs
             args = concat(@[exeFile], args)
           else:
-            if defined(posix) and not exeFile.contains('/'):
-              # "security" in Posix is actually just a euphemism
-              # for "unproductive arbitrary shit"
-              exeCmd = "./" & exeFile
-            else:
-              exeCmd = exeFile
+            exeCmd = exeFile.dup(normalizeExe)
             if expected.useValgrind:
               args = @["--error-exitcode=1"] & exeCmd & args
               exeCmd = "valgrind"
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim
index a440d86d8..814ff103d 100644
--- a/tests/stdlib/tos.nim
+++ b/tests/stdlib/tos.nim
@@ -510,3 +510,13 @@ block: # isValidFilename
   doAssert isValidFilename("ux.bat")
   doAssert isValidFilename("nim.nim")
   doAssert isValidFilename("foo.log")
+
+import sugar
+
+block: # normalizeExe
+  doAssert "".dup(normalizeExe) == ""
+  when defined(posix):
+    doAssert "foo".dup(normalizeExe) == "./foo"
+    doAssert "foo/../bar".dup(normalizeExe) == "foo/../bar"
+  when defined(windows):
+    doAssert "foo".dup(normalizeExe) == "foo"