mirror of https://github.com/linuxdeepin/linglong
refactor: use RAII for env vars in hooks
1. Replaces the custom `EnvVarGuard` class with the `command::EnvironmentVariableGuard` class, which is a RAII wrapper for setting and unsetting environment variables. 2. Changes the `envVarGuards` vector from holding instances of `EnvVarGuard` to holding `unique_ptr`s to `command::EnvironmentVariableGuard`. This ensures that the environment variables are properly cleaned up when the vector goes out of scope, even if exceptions are thrown. 3. Marks the `stringEqual` and `splitString` functions as inline to potentially improve performance by allowing the compiler to inline these functions. Influence: 1. Verify hook scripts that rely on environment variables are still functioning correctly after the change. 2. Confirm that environment variables set by hook scripts are properly cleaned up after the script execution, even in cases where the script throws an exception. 重构: 在hooks中使用RAII管理环境变量 1. 将自定义的 `EnvVarGuard` 类替换为 `command::EnvironmentVariableGuard` 类,后者是一个 RAII 包装器,用于设置和取消设置环境变量。 2. 将 `envVarGuards` 向量从保存 `EnvVarGuard` 的实例更改为保存指向 `command::EnvironmentVariableGuard` 的 `unique_ptr`。 这确保了即使抛出异 常,环境变量在向量超出范围时也能正确清理。 3. 将 `stringEqual` 和 `splitString` 函数标记为内联,以通过允许编译器内 联这些函数来潜在地提高性能。 Influence: 1. 验证在更改后,依赖环境变量的 hook 脚本仍然可以正常运行。 2. 确认 hook 脚本设置的环境变量在脚本执行后能够正确清理,即使在脚本抛出 异常的情况下。
This commit is contained in:
parent
d6e0931419
commit
6992340ffc
|
|
@ -8,14 +8,13 @@
|
|||
|
||||
#include "configure.h"
|
||||
#include "linglong/utils/error/error.h"
|
||||
#include "linglong/utils/command/env.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -29,62 +28,6 @@ static const std::string PRE_INSTALL_ACTION_PREFIX = "ll-pre-install=";
|
|||
static const std::string POST_INSTALL_ACTION_PREFIX = "ll-post-install=";
|
||||
static const std::string POST_UNINSTALL_ACTION_PREFIX = "ll-post-uninstall=";
|
||||
|
||||
// Ensures variables are cleaned up even on early returns or exceptions.
|
||||
class EnvVarGuard
|
||||
{
|
||||
public:
|
||||
EnvVarGuard(const std::string &name, const std::string &value)
|
||||
: name(name)
|
||||
, setOK(false)
|
||||
{
|
||||
if (setenv(name.c_str(), value.c_str(), 1) == 0) {
|
||||
setOK = true;
|
||||
} else {
|
||||
qWarning() << "Failed to set environment variable" << name.c_str() << ":" << errno;
|
||||
}
|
||||
}
|
||||
|
||||
EnvVarGuard(const EnvVarGuard &) = delete;
|
||||
EnvVarGuard &operator=(const EnvVarGuard &) = delete;
|
||||
|
||||
EnvVarGuard(EnvVarGuard &&other) noexcept
|
||||
: name(std::move(other.name))
|
||||
, setOK(other.setOK)
|
||||
{
|
||||
other.setOK = false;
|
||||
}
|
||||
|
||||
EnvVarGuard &operator=(EnvVarGuard &&other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
if (setOK && ::getenv(name.c_str()) != nullptr) {
|
||||
if (unsetenv(name.c_str()) != 0) {
|
||||
qWarning() << "Failed to unset old environment variable" << name.c_str() << ":"
|
||||
<< errno;
|
||||
}
|
||||
}
|
||||
name = std::move(other.name);
|
||||
setOK = other.setOK;
|
||||
other.setOK = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~EnvVarGuard()
|
||||
{
|
||||
if (setOK && ::getenv(name.c_str()) != nullptr) {
|
||||
if (unsetenv(name.c_str()) != 0) {
|
||||
qWarning() << "Failed to unset environment variable" << name.c_str() << ":"
|
||||
<< errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string name; // Name of the environment variable
|
||||
bool setOK;
|
||||
};
|
||||
|
||||
// This function ensures the command string is safely wrapped for 'sh -c'.
|
||||
static std::string escapeAndWrapCommandForShell(const std::string &command)
|
||||
{
|
||||
|
|
@ -106,10 +49,10 @@ utils::error::Result<void> executeHookCommands(
|
|||
{
|
||||
LINGLONG_TRACE("Executing command");
|
||||
|
||||
std::vector<EnvVarGuard> envVarGuards;
|
||||
std::vector<std::unique_ptr<command::EnvironmentVariableGuard>> envVarGuards;
|
||||
envVarGuards.reserve(envVars.size());
|
||||
for (const auto &pair : envVars) {
|
||||
envVarGuards.emplace_back(pair.first, pair.second);
|
||||
envVarGuards.emplace_back(std::make_unique<command::EnvironmentVariableGuard>(pair.first, pair.second));
|
||||
}
|
||||
|
||||
for (const auto &command_raw : commands) {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
namespace linglong::utils {
|
||||
|
||||
bool stringEqual(std::string_view str1, std::string_view str2, bool caseSensitive = false)
|
||||
inline bool stringEqual(std::string_view str1, std::string_view str2, bool caseSensitive = false)
|
||||
{
|
||||
if (caseSensitive) {
|
||||
return str1 == str2;
|
||||
|
|
@ -22,7 +22,7 @@ bool stringEqual(std::string_view str1, std::string_view str2, bool caseSensitiv
|
|||
});
|
||||
}
|
||||
|
||||
std::vector<std::string> splitString(std::string_view str, char delimiter)
|
||||
inline std::vector<std::string> splitString(std::string_view str, char delimiter)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::string token;
|
||||
|
|
|
|||
Loading…
Reference in New Issue