mirror of
https://github.com/Kitware/CMake.git
synced 2026-08-03 06:10:28 +00:00
cmEnvironment: Add class for environment modification
This commit is contained in:
@@ -2,12 +2,16 @@
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmEnvironment.h"
|
||||
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include <cm/string_view>
|
||||
#include <cm/vector>
|
||||
#include <cmext/algorithm>
|
||||
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include "cmsys/String.h"
|
||||
#endif
|
||||
@@ -64,3 +68,138 @@ std::vector<std::string> cmEnvironment::GetVariables() const
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
auto const ValidOperators = std::set<cm::string_view>{
|
||||
"set",
|
||||
"unset",
|
||||
"string_append",
|
||||
"string_prepend",
|
||||
"path_list_append",
|
||||
"path_list_prepend",
|
||||
"cmake_list_append",
|
||||
"cmake_list_prepend",
|
||||
};
|
||||
|
||||
struct ListAppend
|
||||
{
|
||||
public:
|
||||
ListAppend(std::string val, char sep)
|
||||
: value(std::move(val))
|
||||
, separator(sep)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(std::string& output) const
|
||||
{
|
||||
if (!output.empty()) {
|
||||
output += separator;
|
||||
}
|
||||
output += value;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string value;
|
||||
char separator;
|
||||
};
|
||||
|
||||
struct ListPrepend
|
||||
{
|
||||
public:
|
||||
ListPrepend(std::string val, char sep)
|
||||
: value(std::move(val))
|
||||
, separator(sep)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(std::string& output) const
|
||||
{
|
||||
if (!output.empty()) {
|
||||
output.insert(output.begin(), separator);
|
||||
}
|
||||
output.insert(0, value);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string value;
|
||||
char separator;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool cmEnvironmentModification::Add(std::vector<std::string> const& envmod)
|
||||
{
|
||||
bool ok = true;
|
||||
for (auto const& entry : envmod) {
|
||||
ok &= this->Add(entry);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool cmEnvironmentModification::Add(std::string const& envmod)
|
||||
{
|
||||
// Split on `=`
|
||||
auto const eq_loc = envmod.find_first_of('=');
|
||||
if (eq_loc == std::string::npos) {
|
||||
cmSystemTools::Error(cmStrCat(
|
||||
"Error: Missing `=` after the variable name in: ", envmod, '\n'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Split operation on `:`
|
||||
auto const op_value_start = eq_loc + 1;
|
||||
auto const colon_loc = envmod.find_first_of(':', op_value_start);
|
||||
if (colon_loc == std::string::npos) {
|
||||
cmSystemTools::Error(
|
||||
cmStrCat("Error: Missing `:` after the operation in: ", envmod, '\n'));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto entry = Entry{};
|
||||
entry.Name = envmod.substr(0, eq_loc);
|
||||
entry.Op = envmod.substr(op_value_start, colon_loc - op_value_start);
|
||||
entry.Value = envmod.substr(colon_loc + 1);
|
||||
|
||||
if (entry.Op == "reset") {
|
||||
cm::erase_if(this->Entries,
|
||||
[&entry](Entry const& e) { return e.Name == entry.Name; });
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!cm::contains(ValidOperators, entry.Op)) {
|
||||
cmSystemTools::Error(cmStrCat(
|
||||
"Error: Unrecognized environment manipulation argument: ", entry.Op,
|
||||
'\n'));
|
||||
return false;
|
||||
}
|
||||
|
||||
this->Entries.push_back(std::move(entry));
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmEnvironmentModification::ApplyTo(cmEnvironment& env)
|
||||
{
|
||||
char const path_sep = cmSystemTools::GetSystemPathlistSeparator();
|
||||
|
||||
for (auto const& e : this->Entries) {
|
||||
if (e.Op == "set") {
|
||||
env.PutEnv(e.Name + "=" + e.Value);
|
||||
} else if (e.Op == "unset") {
|
||||
env.UnPutEnv(e.Name);
|
||||
} else if (e.Op == "string_append") {
|
||||
env.Modify(e.Name, [&e](std::string& output) { output += e.Value; });
|
||||
} else if (e.Op == "string_prepend") {
|
||||
env.Modify(e.Name,
|
||||
[&e](std::string& output) { output.insert(0, e.Value); });
|
||||
} else if (e.Op == "path_list_append") {
|
||||
env.Modify(e.Name, ListAppend(e.Value, path_sep));
|
||||
} else if (e.Op == "path_list_prepend") {
|
||||
env.Modify(e.Name, ListPrepend(e.Value, path_sep));
|
||||
} else if (e.Op == "cmake_list_append") {
|
||||
env.Modify(e.Name, ListAppend(e.Value, ';'));
|
||||
} else if (e.Op == "cmake_list_prepend") {
|
||||
env.Modify(e.Name, ListPrepend(e.Value, ';'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,3 +53,22 @@ protected:
|
||||
};
|
||||
std::map<std::string, cm::optional<std::string>, EnvNameLess> Map;
|
||||
};
|
||||
|
||||
class cmEnvironmentModification
|
||||
{
|
||||
public:
|
||||
bool Add(std::string const& envmod);
|
||||
bool Add(std::vector<std::string> const& envmod);
|
||||
|
||||
void ApplyTo(cmEnvironment& env);
|
||||
|
||||
private:
|
||||
struct Entry
|
||||
{
|
||||
std::string Name;
|
||||
std::string Value;
|
||||
std::string Op;
|
||||
};
|
||||
|
||||
std::vector<Entry> Entries;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user