summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKaushal Modi <kaushal.modi@gmail.com>2019-06-15 05:32:26 -0400
committerAndreas Rumpf <rumpf_a@web.de>2019-06-15 11:32:26 +0200
commit71829226229287f4e1d38c9e4e91fb3d8b8fb648 (patch)
tree176418cf8ba5a6d1b400489978bdb96de7e07ecc
parenteadea343ef7ef49026eccbd9a5f4d5df5071ceb4 (diff)
downloadNim-71829226229287f4e1d38c9e4e91fb3d8b8fb648.tar.gz
[feature] Added os.delEnv; add delEnv support to nimscript too (#11466)
[feature] Fixes https://github.com/nim-lang/Nim/issues/11452.
-rw-r--r--changelog.md2
-rw-r--r--compiler/scriptconfig.nim2
-rw-r--r--lib/pure/includes/osenv.nim31
-rw-r--r--lib/system/nimscript.nim10
-rw-r--r--tests/newconfig/tfoo.nims5
-rw-r--r--tests/stdlib/tos.nim13
6 files changed, 59 insertions, 4 deletions
diff --git a/changelog.md b/changelog.md
index 6feec8c04..3024e8d52 100644
--- a/changelog.md
+++ b/changelog.md
@@ -22,7 +22,7 @@
 
 ### Library changes
 
-
+- Added `os.delEnv` and `nimscript.delEnv`.
 
 ### Language additions
 
diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim
index db60dafcc..6c3d0a122 100644
--- a/compiler/scriptconfig.nim
+++ b/compiler/scriptconfig.nim
@@ -96,6 +96,8 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
     setResult(a, os.existsEnv(a.getString 0))
   cbconf putEnv:
     os.putEnv(a.getString 0, a.getString 1)
+  cbconf delEnv:
+    os.delEnv(a.getString 0)
   cbconf dirExists:
     setResult(a, os.dirExists(a.getString 0))
   cbconf fileExists:
diff --git a/lib/pure/includes/osenv.nim b/lib/pure/includes/osenv.nim
index bc4750121..193efd4d4 100644
--- a/lib/pure/includes/osenv.nim
+++ b/lib/pure/includes/osenv.nim
@@ -9,6 +9,8 @@ proc c_getenv(env: cstring): cstring {.
   importc: "getenv", header: "<stdlib.h>".}
 proc c_putenv(env: cstring): cint {.
   importc: "putenv", header: "<stdlib.h>".}
+proc c_unsetenv(env: cstring): cint {.
+  importc: "unsetenv", header: "<stdlib.h>".}
 
 # Environment handling cannot be put into RTL, because the ``envPairs``
 # iterator depends on ``environment``.
@@ -109,6 +111,7 @@ proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].}
   ## See also:
   ## * `existsEnv proc <#existsEnv,string>`_
   ## * `putEnv proc <#putEnv,string,string>`_
+  ## * `delEnv proc <#delEnv,string>`_
   ## * `envPairs iterator <#envPairs.i>`_
   runnableExamples:
     assert getEnv("unknownEnv") == ""
@@ -132,6 +135,7 @@ proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
   ## See also:
   ## * `getEnv proc <#getEnv,string,string>`_
   ## * `putEnv proc <#putEnv,string,string>`_
+  ## * `delEnv proc <#delEnv,string>`_
   ## * `envPairs iterator <#envPairs.i>`_
   runnableExamples:
     assert not existsEnv("unknownEnv")
@@ -149,6 +153,7 @@ proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
   ## See also:
   ## * `getEnv proc <#getEnv,string,string>`_
   ## * `existsEnv proc <#existsEnv,string>`_
+  ## * `delEnv proc <#delEnv,string>`_
   ## * `envPairs iterator <#envPairs.i>`_
 
   # Note: by storing the string in the environment sequence,
@@ -175,6 +180,31 @@ proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
       if c_putenv(environment[indx]) != 0'i32:
         raiseOSError(osLastError())
 
+proc delEnv*(key: string) {.tags: [WriteEnvEffect].} =
+  ## Deletes the `environment variable`:idx: named `key`.
+  ## If an error occurs, `OSError` is raised.
+  ##
+  ## See also:ven
+  ## * `getEnv proc <#getEnv,string,string>`_
+  ## * `existsEnv proc <#existsEnv,string>`_
+  ## * `putEnv proc <#putEnv,string,string>`_
+  ## * `envPairs iterator <#envPairs.i>`_
+  when nimvm:
+    discard "built into the compiler"
+  else:
+    var indx = findEnvVar(key)
+    if indx < 0: return # Do nothing if the env var is not already set
+    when defined(windows) and not defined(nimscript):
+      when useWinUnicode:
+        var k = newWideCString(key)
+        if setEnvironmentVariableW(k, nil) == 0'i32: raiseOSError(osLastError())
+      else:
+        if setEnvironmentVariableA(key, nil) == 0'i32: raiseOSError(osLastError())
+    else:
+      if c_unsetenv(key) != 0'i32:
+        raiseOSError(osLastError())
+    environment.delete(indx)
+
 iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
   ## Iterate over all `environments variables`:idx:.
   ##
@@ -185,6 +215,7 @@ iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].}
   ## * `getEnv proc <#getEnv,string,string>`_
   ## * `existsEnv proc <#existsEnv,string>`_
   ## * `putEnv proc <#putEnv,string,string>`_
+  ## * `delEnv proc <#delEnv,string>`_
   getEnvVarsC()
   for i in 0..high(environment):
     var p = find(environment[i], '=')
diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim
index 1c4986aa4..3411f1e6e 100644
--- a/lib/system/nimscript.nim
+++ b/lib/system/nimscript.nim
@@ -114,15 +114,19 @@ proc cmpic*(a, b: string): int =
   cmpIgnoreCase(a, b)
 
 proc getEnv*(key: string; default = ""): string {.tags: [ReadIOEffect].} =
-  ## Retrieves the environment variable of name `key`.
+  ## Retrieves the environment variable of name ``key``.
   builtin
 
 proc existsEnv*(key: string): bool {.tags: [ReadIOEffect].} =
-  ## Checks for the existence of an environment variable named `key`.
+  ## Checks for the existence of an environment variable named ``key``.
   builtin
 
 proc putEnv*(key, val: string) {.tags: [WriteIOEffect].} =
-  ## Sets the value of the environment variable named key to val.
+  ## Sets the value of the environment variable named ``key`` to ``val``.
+  builtin
+
+proc delEnv*(key: string) {.tags: [WriteIOEffect].} =
+  ## Deletes the environment variable named ``key``.
   builtin
 
 proc fileExists*(filename: string): bool {.tags: [ReadIOEffect].} =
diff --git a/tests/newconfig/tfoo.nims b/tests/newconfig/tfoo.nims
index a9e40956e..8dcc7d6f1 100644
--- a/tests/newconfig/tfoo.nims
+++ b/tests/newconfig/tfoo.nims
@@ -81,3 +81,8 @@ when false:
 
 rmDir("tempXYZ")
 assert dirExists("tempXYZ") == false
+
+putEnv("dummy", "myval")
+doAssert(existsEnv("dummy") == true)
+delEnv("dummy")
+doAssert(existsEnv("dummy") == false)
diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim
index 2d69332fc..3a25079ec 100644
--- a/tests/stdlib/tos.nim
+++ b/tests/stdlib/tos.nim
@@ -342,6 +342,19 @@ block getTempDir:
         let origTmpDir = getEnv("TMPDIR")
         putEnv("TMPDIR", "/mytmp")
         doAssert getTempDir() == "/mytmp/"
+        delEnv("TMPDIR")
+        doAssert getTempDir() == "/tmp/"
         putEnv("TMPDIR", origTmpDir)
       else:
         doAssert getTempDir() == "/tmp/"
+
+block osenv:
+  block delEnv:
+    const dummyEnvVar = "DUMMY_ENV_VAR" # This env var wouldn't be likely to exist to begin with
+    doAssert existsEnv(dummyEnvVar) == false
+    putEnv(dummyEnvVar, "1")
+    doAssert existsEnv(dummyEnvVar) == true
+    delEnv(dummyEnvVar)
+    doAssert existsEnv(dummyEnvVar) == false
+    delEnv(dummyEnvVar)         # deleting an already deleted env var
+    doAssert existsEnv(dummyEnvVar) == false