diff options
| author | Stefan Boberg <[email protected]> | 2026-04-27 15:05:16 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-04-27 15:05:16 +0200 |
| commit | 6804dc6ff62c477399183dc85d2ad387298aa49d (patch) | |
| tree | f4153a901c758b9e385627b43f1606f8c2129a04 /src/zencore/filesystem.cpp | |
| parent | 5.8.9-pre3 (diff) | |
| download | archived-zen-6804dc6ff62c477399183dc85d2ad387298aa49d.tar.xz archived-zen-6804dc6ff62c477399183dc85d2ad387298aa49d.zip | |
GetEnvVariable: return std::optional<std::string> (#1017)
- `GetEnvVariable` now returns `std::optional<std::string>` so callers can distinguish an unset variable from one set to an empty value.
- Windows path uses `SetLastError(ERROR_SUCCESS)` + `ERROR_ENVVAR_NOT_FOUND` to detect "not found"; POSIX path returns `nullopt` when `getenv` returns `nullptr`.
- All call sites migrated. Most use `.value_or("")` to preserve current empty-or-unset behavior. The diagnostic helpers in `zen-test/artifactprovider-tests.cpp` now report `<unset>` vs `<empty>` distinctly.
- Added a check in the `ExpandEnvironmentVariables` test confirming `nullopt` for an unset variable; PATH/HOME lookups in that test use `REQUIRE(has_value())` so a missing var fails cleanly instead of throwing `bad_optional_access`.
Diffstat (limited to 'src/zencore/filesystem.cpp')
| -rw-r--r-- | src/zencore/filesystem.cpp | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/src/zencore/filesystem.cpp b/src/zencore/filesystem.cpp index 281cb8e2e..e8ceac5c0 100644 --- a/src/zencore/filesystem.cpp +++ b/src/zencore/filesystem.cpp @@ -2936,41 +2936,52 @@ GetDirectoryContent(const std::filesystem::path& RootDir, Visitor.AsyncVisitDirectory(WrapperVisitor.RelativeRoot, std::move(WrapperVisitor.Content)); } -std::string +std::optional<std::string> GetEnvVariable(std::string_view VariableName) { ZEN_ASSERT(!VariableName.empty()); #if ZEN_PLATFORM_WINDOWS - + const std::string NameStr(VariableName); std::vector<CHAR> EnvVariableBuffer(1023 + 1); - DWORD RESULT = GetEnvironmentVariableA(std::string(VariableName).c_str(), EnvVariableBuffer.data(), (DWORD)EnvVariableBuffer.size()); + SetLastError(ERROR_SUCCESS); + DWORD RESULT = GetEnvironmentVariableA(NameStr.c_str(), EnvVariableBuffer.data(), (DWORD)EnvVariableBuffer.size()); if (RESULT == 0) { - return ""; + if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) + { + return std::nullopt; + } + return std::string{}; } if (RESULT <= EnvVariableBuffer.size()) { return std::string(EnvVariableBuffer.data(), size_t(RESULT)); } EnvVariableBuffer.resize(size_t(RESULT)); - RESULT = GetEnvironmentVariableA(std::string(VariableName).c_str(), EnvVariableBuffer.data(), (DWORD)EnvVariableBuffer.size()); + SetLastError(ERROR_SUCCESS); + RESULT = GetEnvironmentVariableA(NameStr.c_str(), EnvVariableBuffer.data(), (DWORD)EnvVariableBuffer.size()); if (RESULT == 0) { - return ""; + if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) + { + return std::nullopt; + } + return std::string{}; } if (RESULT <= EnvVariableBuffer.size()) { return std::string(EnvVariableBuffer.data(), size_t(RESULT)); } + return std::nullopt; #endif #if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC - char* EnvVariable = getenv(std::string(VariableName).c_str()); + const char* EnvVariable = getenv(std::string(VariableName).c_str()); if (EnvVariable) { return std::string(EnvVariable); } + return std::nullopt; #endif - return ""; } std::string @@ -2987,7 +2998,7 @@ ExpandEnvironmentVariables(std::string_view Input) if (End != std::string_view::npos && End > i + 1) { std::string_view VarName = Input.substr(i + 1, End - i - 1); - std::string Value = GetEnvVariable(VarName); + std::string Value = GetEnvVariable(VarName).value_or(""); if (!Value.empty()) { Result += Value; @@ -4242,12 +4253,16 @@ TEST_CASE("ExpandEnvironmentVariables") // Known variable # if ZEN_PLATFORM_WINDOWS // PATH is always set on Windows - std::string PathValue = GetEnvVariable("PATH"); + std::optional<std::string> PathOpt = GetEnvVariable("PATH"); + REQUIRE(PathOpt.has_value()); + const std::string& PathValue = *PathOpt; CHECK(!PathValue.empty()); CHECK_EQ(ExpandEnvironmentVariables("%PATH%"), PathValue); CHECK_EQ(ExpandEnvironmentVariables("prefix/%PATH%/suffix"), "prefix/" + PathValue + "/suffix"); # else - std::string HomeValue = GetEnvVariable("HOME"); + std::optional<std::string> HomeOpt = GetEnvVariable("HOME"); + REQUIRE(HomeOpt.has_value()); + const std::string& HomeValue = *HomeOpt; CHECK(!HomeValue.empty()); CHECK_EQ(ExpandEnvironmentVariables("%HOME%"), HomeValue); CHECK_EQ(ExpandEnvironmentVariables("prefix/%HOME%/suffix"), "prefix/" + HomeValue + "/suffix"); @@ -4255,13 +4270,14 @@ TEST_CASE("ExpandEnvironmentVariables") // Unknown variable is left unexpanded CHECK_EQ(ExpandEnvironmentVariables("%ZEN_UNLIKELY_SET_VAR_12345%"), "%ZEN_UNLIKELY_SET_VAR_12345%"); + CHECK_FALSE(GetEnvVariable("ZEN_UNLIKELY_SET_VAR_12345").has_value()); // Multiple variables # if ZEN_PLATFORM_WINDOWS - std::string OSValue = GetEnvVariable("OS"); - if (!OSValue.empty()) + std::optional<std::string> OSValue = GetEnvVariable("OS"); + if (OSValue && !OSValue->empty()) { - CHECK_EQ(ExpandEnvironmentVariables("%PATH%/%OS%"), PathValue + "/" + OSValue); + CHECK_EQ(ExpandEnvironmentVariables("%PATH%/%OS%"), PathValue + "/" + *OSValue); } # endif } |