Browse Source

ScopedEnv: add a RAII helper to temporarily manipulate the environment

John Drouhard 3 months ago
parent
commit
fe0e2fcaff
2 changed files with 58 additions and 0 deletions
  1. 35 0
      Source/cmSystemTools.cxx
  2. 23 0
      Source/cmSystemTools.h

+ 35 - 0
Source/cmSystemTools.cxx

@@ -2310,6 +2310,41 @@ cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
 }
 #endif
 
+cmSystemTools::ScopedEnv::ScopedEnv(cm::string_view var)
+{
+  std::string::size_type pos = var.find('=');
+  if (pos != std::string::npos) {
+    this->Key = std::string{ var.substr(0, pos) };
+    this->Original = cmSystemTools::GetEnvVar(this->Key);
+
+    cm::string_view value = var.substr(pos + 1);
+
+    if (!this->Original && value.empty()) {
+      // nothing to do if the environment variable wasn't already set and the
+      // new value is also empty. clear the Key member so the destructor also
+      // does nothing.
+      this->Key.clear();
+    } else {
+      if (value.empty()) {
+        cmSystemTools::UnPutEnv(this->Key);
+      } else {
+        cmSystemTools::PutEnv(cmStrCat(this->Key, '=', value));
+      }
+    }
+  }
+}
+
+cmSystemTools::ScopedEnv::~ScopedEnv()
+{
+  if (!this->Key.empty()) {
+    if (this->Original) {
+      cmSystemTools::PutEnv(cmStrCat(this->Key, '=', *this->Original));
+    } else {
+      cmSystemTools::UnPutEnv(Key);
+    }
+  }
+}
+
 void cmSystemTools::EnableVSConsoleOutput()
 {
 #ifdef _WIN32

+ 23 - 0
Source/cmSystemTools.h

@@ -517,6 +517,29 @@ public:
   };
 #endif
 
+  /** \class ScopedEnv
+   * \brief An RAII class to temporarily set/unset an environment variable.
+   *
+   * The value passed to the constructor is put into the environment. This
+   * variable is of the form "var=value" and the original value of the "var"
+   * environment variable is saved. When the object is destroyed, the original
+   * value for the environment variable is restored. If the variable didn't
+   * exist, it will be unset.
+   */
+  class ScopedEnv
+  {
+  public:
+    ScopedEnv(cm::string_view val);
+    ~ScopedEnv();
+
+    ScopedEnv(ScopedEnv const&) = delete;
+    ScopedEnv& operator=(ScopedEnv const&) = delete;
+
+  private:
+    std::string Key;
+    cm::optional<std::string> Original;
+  };
+
   /** Setup the environment to enable VS 8 IDE output.  */
   static void EnableVSConsoleOutput();