fix env variable load and subst order
This commit is contained in:
@@ -83,10 +83,10 @@ namespace dropshell
|
|||||||
if (!std::filesystem::exists(readme_path))
|
if (!std::filesystem::exists(readme_path))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::map<std::string, std::string> all_env_vars;
|
ordered_env_vars all_env_vars;
|
||||||
get_all_service_env_vars(server, service, all_env_vars);
|
get_all_service_env_vars(server, service, all_env_vars);
|
||||||
all_env_vars["LOCAL_CONFIG_PATH"] = localpath::service(server, service);
|
set_var(all_env_vars, "LOCAL_CONFIG_PATH", localpath::service(server, service));
|
||||||
all_env_vars["LOCAL_TEMPLATE_PATH"] = tinfo.local_template_path().string();
|
set_var(all_env_vars, "LOCAL_TEMPLATE_PATH", tinfo.local_template_path().string());
|
||||||
|
|
||||||
info << std::endl;
|
info << std::endl;
|
||||||
std::ifstream readme_file(readme_path);
|
std::ifstream readme_file(readme_path);
|
||||||
|
@@ -89,7 +89,7 @@ namespace dropshell
|
|||||||
std::string user = server_env.get_user_for_service(service);
|
std::string user = server_env.get_user_for_service(service);
|
||||||
|
|
||||||
// Get all service environment variables
|
// Get all service environment variables
|
||||||
std::map<std::string, std::string> env_vars;
|
ordered_env_vars env_vars;
|
||||||
if (!get_all_service_env_vars(server, service, env_vars))
|
if (!get_all_service_env_vars(server, service, env_vars))
|
||||||
{
|
{
|
||||||
error << "Failed to get environment variables for service " << service << std::endl;
|
error << "Failed to get environment variables for service " << service << std::endl;
|
||||||
@@ -97,7 +97,7 @@ namespace dropshell
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add HOST_NAME like other commands do
|
// Add HOST_NAME like other commands do
|
||||||
env_vars["HOST_NAME"] = server_env.get_SSH_HOST();
|
set_var(env_vars, "HOST_NAME", server_env.get_SSH_HOST());
|
||||||
|
|
||||||
// Get the remote service template path for working directory
|
// Get the remote service template path for working directory
|
||||||
std::string remote_service_template_path = remotepath(server, user).service_template(service);
|
std::string remote_service_template_path = remotepath(server, user).service_template(service);
|
||||||
|
@@ -347,14 +347,14 @@ namespace dropshell
|
|||||||
std::string remote_service_template_path = remotepath(mServerName, user).service_template(service_name);
|
std::string remote_service_template_path = remotepath(mServerName, user).service_template(service_name);
|
||||||
std::string script_path = remote_service_template_path + "/" + command + ".sh";
|
std::string script_path = remote_service_template_path + "/" + command + ".sh";
|
||||||
|
|
||||||
std::map<std::string, std::string> env_vars;
|
ordered_env_vars env_vars;
|
||||||
if (!get_all_service_env_vars(mServerName, service_name, env_vars))
|
if (!get_all_service_env_vars(mServerName, service_name, env_vars))
|
||||||
{
|
{
|
||||||
error << "Failed to get all service env vars for " << service_name << std::endl;
|
error << "Failed to get all service env vars for " << service_name << std::endl;
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
env_vars["HOST_NAME"] = get_SSH_HOST();
|
set_var(env_vars, "HOST_NAME", get_SSH_HOST());
|
||||||
|
|
||||||
std::string argstr = "";
|
std::string argstr = "";
|
||||||
for (const auto &arg : args)
|
for (const auto &arg : args)
|
||||||
|
@@ -62,9 +62,9 @@ namespace dropshell
|
|||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_bool_variable(const std::map<std::string, std::string> &variables, const std::string &variable_name)
|
bool get_bool_variable(const ordered_env_vars &variables, const std::string &variable_name)
|
||||||
{
|
{
|
||||||
auto it = variables.find(variable_name);
|
auto it = find_var(variables, variable_name);
|
||||||
if (it == variables.end())
|
if (it == variables.end())
|
||||||
{
|
{
|
||||||
error << "Variable " << variable_name << " not found in the service " << filenames::template_info_env << std::endl;
|
error << "Variable " << variable_name << " not found in the service " << filenames::template_info_env << std::endl;
|
||||||
@@ -97,12 +97,12 @@ namespace dropshell
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now set the template name and path.
|
// now set the template name and path.
|
||||||
std::map<std::string, std::string> variables;
|
ordered_env_vars variables;
|
||||||
if (!get_all_service_env_vars(server_name, service_name, variables))
|
if (!get_all_service_env_vars(server_name, service_name, variables))
|
||||||
return LocalServiceInfo();
|
return LocalServiceInfo();
|
||||||
|
|
||||||
{ // confirm TEMPLATE is defined.
|
{ // confirm TEMPLATE is defined.
|
||||||
auto it = variables.find("TEMPLATE");
|
auto it = find_var(variables, "TEMPLATE");
|
||||||
if (it == variables.end())
|
if (it == variables.end())
|
||||||
{
|
{
|
||||||
error << "TEMPLATE variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
error << "TEMPLATE variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
||||||
@@ -123,7 +123,7 @@ namespace dropshell
|
|||||||
service.local_template_path = tinfo.local_template_path();
|
service.local_template_path = tinfo.local_template_path();
|
||||||
|
|
||||||
{ // set the user.
|
{ // set the user.
|
||||||
auto it = variables.find("SSH_USER");
|
auto it = find_var(variables, "SSH_USER");
|
||||||
if (it == variables.end())
|
if (it == variables.end())
|
||||||
{
|
{
|
||||||
error << "SSH_USER variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
error << "SSH_USER variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
||||||
@@ -138,7 +138,7 @@ namespace dropshell
|
|||||||
service.requires_docker_root = get_bool_variable(variables, "REQUIRES_DOCKER_ROOT");
|
service.requires_docker_root = get_bool_variable(variables, "REQUIRES_DOCKER_ROOT");
|
||||||
|
|
||||||
{ // determine if the service template hash matches the template hash.
|
{ // determine if the service template hash matches the template hash.
|
||||||
auto it = variables.find("TEMPLATE_HASH");
|
auto it = find_var(variables, "TEMPLATE_HASH");
|
||||||
service.service_template_hash_match = false;
|
service.service_template_hash_match = false;
|
||||||
|
|
||||||
if (it == variables.end())
|
if (it == variables.end())
|
||||||
@@ -221,9 +221,9 @@ namespace dropshell
|
|||||||
return backups;
|
return backups;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_all_service_env_vars(const std::string &server_name, const std::string &service_name, std::map<std::string, std::string> &all_env_vars)
|
bool get_all_service_env_vars(const std::string &server_name, const std::string &service_name, ordered_env_vars &all_env_vars)
|
||||||
{
|
{
|
||||||
all_env_vars.clear();
|
clear_vars(all_env_vars);
|
||||||
|
|
||||||
if (localpath::service(server_name, service_name).empty() || !fs::exists(localpath::service(server_name, service_name)))
|
if (localpath::service(server_name, service_name).empty() || !fs::exists(localpath::service(server_name, service_name)))
|
||||||
{
|
{
|
||||||
@@ -236,11 +236,11 @@ namespace dropshell
|
|||||||
{
|
{
|
||||||
if (!file.empty() && std::filesystem::exists(file))
|
if (!file.empty() && std::filesystem::exists(file))
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string> env_vars;
|
ordered_env_vars env_vars;
|
||||||
envmanager env_manager(file);
|
envmanager env_manager(file);
|
||||||
env_manager.load();
|
env_manager.load();
|
||||||
env_manager.get_all_variables(env_vars);
|
env_manager.get_all_variables(env_vars);
|
||||||
all_env_vars.merge(env_vars);
|
merge_vars(all_env_vars, env_vars);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
warning << "Expected environment file not found: " << file << std::endl;
|
warning << "Expected environment file not found: " << file << std::endl;
|
||||||
@@ -248,15 +248,15 @@ namespace dropshell
|
|||||||
|
|
||||||
|
|
||||||
// add in some simple variables first, as others below may depend on/use these in bash.
|
// add in some simple variables first, as others below may depend on/use these in bash.
|
||||||
all_env_vars["SERVER"] = server_name;
|
set_var(all_env_vars, "SERVER", server_name);
|
||||||
all_env_vars["SERVICE"] = service_name;
|
set_var(all_env_vars, "SERVICE", service_name);
|
||||||
all_env_vars["DOCKER_CLI_HINTS"] = "false"; // turn off docker junk.
|
set_var(all_env_vars, "DOCKER_CLI_HINTS", "false"); // turn off docker junk.
|
||||||
|
|
||||||
// Load environment files
|
// Load environment files
|
||||||
load_env_file(localfile::service_env(server_name, service_name));
|
load_env_file(localfile::service_env(server_name, service_name));
|
||||||
load_env_file(localfile::template_info_env(server_name, service_name));
|
load_env_file(localfile::template_info_env(server_name, service_name));
|
||||||
|
|
||||||
std::string user = all_env_vars["SSH_USER"];
|
std::string user = get_var(all_env_vars, "SSH_USER");
|
||||||
if (user.empty())
|
if (user.empty())
|
||||||
{
|
{
|
||||||
error << "SSH_USER variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
error << "SSH_USER variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
||||||
@@ -266,12 +266,12 @@ namespace dropshell
|
|||||||
}
|
}
|
||||||
|
|
||||||
// more additional, these depend on others above.
|
// more additional, these depend on others above.
|
||||||
all_env_vars["CONFIG_PATH"] = remotepath(server_name, user).service_config(service_name);
|
set_var(all_env_vars, "CONFIG_PATH", remotepath(server_name, user).service_config(service_name));
|
||||||
all_env_vars["AGENT_PATH"] = remotepath(server_name, user).agent();
|
set_var(all_env_vars, "AGENT_PATH", remotepath(server_name, user).agent());
|
||||||
|
|
||||||
|
|
||||||
// determine template name.
|
// determine template name.
|
||||||
auto it = all_env_vars.find("TEMPLATE");
|
auto it = find_var(all_env_vars, "TEMPLATE");
|
||||||
if (it == all_env_vars.end())
|
if (it == all_env_vars.end())
|
||||||
{
|
{
|
||||||
error << "TEMPLATE variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
error << "TEMPLATE variable not defined in service " << service_name << " on server " << server_name << std::endl;
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include "utils/ordered_env.hpp"
|
||||||
|
|
||||||
namespace dropshell {
|
namespace dropshell {
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ namespace dropshell {
|
|||||||
std::set<std::string> get_used_commands(const std::string& server_name, const std::string& service_name);
|
std::set<std::string> get_used_commands(const std::string& server_name, const std::string& service_name);
|
||||||
|
|
||||||
// get all env vars for a given service
|
// get all env vars for a given service
|
||||||
bool get_all_service_env_vars(const std::string& server_name, const std::string& service_name, std::map<std::string, std::string> & all_env_vars);
|
bool get_all_service_env_vars(const std::string& server_name, const std::string& service_name, ordered_env_vars& all_env_vars);
|
||||||
|
|
||||||
// list all backups for a given service (across all servers)
|
// list all backups for a given service (across all servers)
|
||||||
std::set<std::string> list_backups(const std::string& server_name, const std::string& service_name);
|
std::set<std::string> list_backups(const std::string& server_name, const std::string& service_name);
|
||||||
|
@@ -665,23 +665,23 @@
|
|||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
// check TEMPLATE= line.
|
// check TEMPLATE= line.
|
||||||
std::map<std::string, std::string> all_env_vars;
|
ordered_env_vars all_env_vars;
|
||||||
std::vector<std::string> env_files = {
|
std::vector<std::string> env_files = {
|
||||||
"config/" + filenames::service_env,
|
"config/" + filenames::service_env,
|
||||||
"config/" + filenames::template_info_env
|
"config/" + filenames::template_info_env
|
||||||
};
|
};
|
||||||
for (const auto& file : env_files) {
|
for (const auto& file : env_files) {
|
||||||
{ // load service.env from the service on this machine.
|
{ // load service.env from the service on this machine.
|
||||||
std::map<std::string, std::string> env_vars;
|
ordered_env_vars env_vars;
|
||||||
envmanager env_manager(template_path + "/" + file);
|
envmanager env_manager(template_path + "/" + file);
|
||||||
env_manager.load();
|
env_manager.load();
|
||||||
env_manager.get_all_variables(env_vars);
|
env_manager.get_all_variables(env_vars);
|
||||||
all_env_vars.merge(env_vars);
|
merge_vars(all_env_vars, env_vars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine template name.
|
// determine template name.
|
||||||
auto it = all_env_vars.find("TEMPLATE");
|
auto it = find_var(all_env_vars, "TEMPLATE");
|
||||||
if (it == all_env_vars.end()) {
|
if (it == all_env_vars.end()) {
|
||||||
error << "TEMPLATE variable not found in " << template_path << std::endl;
|
error << "TEMPLATE variable not found in " << template_path << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
@@ -56,7 +56,7 @@ bool envmanager::load() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// trim whitespace from the key and value
|
// trim whitespace from the key and value
|
||||||
m_variables[dequote(trim(key))] = dequote(trim(value));
|
set_var(m_variables, dequote(trim(key)), dequote(trim(value)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
@@ -77,29 +77,21 @@ void envmanager::save() {
|
|||||||
|
|
||||||
std::string envmanager::get_variable(std::string key) const {
|
std::string envmanager::get_variable(std::string key) const {
|
||||||
key = dequote(trim(key));
|
key = dequote(trim(key));
|
||||||
|
return get_var(m_variables, key);
|
||||||
// Use case-insensitive comparison to find the key
|
|
||||||
for (const auto& pair : m_variables) {
|
|
||||||
if (pair.first == key) {
|
|
||||||
return pair.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void envmanager::get_all_variables(std::map<std::string, std::string>& variables) const {
|
void envmanager::get_all_variables(ordered_env_vars& variables) const {
|
||||||
variables = m_variables;
|
variables = m_variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
void envmanager::add_variables(std::map<std::string, std::string> variables) {
|
void envmanager::add_variables(const ordered_env_vars& variables) {
|
||||||
for (auto& pair : variables) {
|
for (const auto& pair : variables) {
|
||||||
set_variable(pair.first, pair.second);
|
set_variable(pair.first, pair.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void envmanager::set_variable(std::string key, std::string value) {
|
void envmanager::set_variable(std::string key, std::string value) {
|
||||||
m_variables[dequote(trim(key))] = dequote(trim(value));
|
set_var(m_variables, dequote(trim(key)), dequote(trim(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void envmanager::clear_variables() {
|
void envmanager::clear_variables() {
|
||||||
|
@@ -4,6 +4,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "ordered_env.hpp"
|
||||||
|
|
||||||
namespace dropshell {
|
namespace dropshell {
|
||||||
|
|
||||||
// envmanager is a class that manages the environment files for the application.
|
// envmanager is a class that manages the environment files for the application.
|
||||||
@@ -23,17 +25,17 @@ class envmanager {
|
|||||||
// get variables from the environment files. Trim whitespace from the values.
|
// get variables from the environment files. Trim whitespace from the values.
|
||||||
// keys are case-sensitive.
|
// keys are case-sensitive.
|
||||||
std::string get_variable(std::string key) const;
|
std::string get_variable(std::string key) const;
|
||||||
void get_all_variables(std::map<std::string, std::string>& variables) const;
|
void get_all_variables(ordered_env_vars& variables) const;
|
||||||
|
|
||||||
// add variables to the environment files.
|
// add variables to the environment files.
|
||||||
// trim whitespace from the values.
|
// trim whitespace from the values.
|
||||||
void add_variables(std::map<std::string, std::string> variables);
|
void add_variables(const ordered_env_vars& variables);
|
||||||
void set_variable(std::string key, std::string value);
|
void set_variable(std::string key, std::string value);
|
||||||
void clear_variables();
|
void clear_variables();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
std::map<std::string, std::string> m_variables;
|
ordered_env_vars m_variables;
|
||||||
};
|
};
|
||||||
|
|
||||||
// utility functions
|
// utility functions
|
||||||
|
@@ -113,7 +113,7 @@ namespace dropshell
|
|||||||
sColour currentColour_;
|
sColour currentColour_;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool execute_local_command(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> &env_vars, std::string *output, cMode mode)
|
bool execute_local_command(std::string directory_to_run_in, std::string command_to_run, const ordered_env_vars& env_vars, std::string *output, cMode mode)
|
||||||
{
|
{
|
||||||
sCommand command(directory_to_run_in, command_to_run, env_vars);
|
sCommand command(directory_to_run_in, command_to_run, env_vars);
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include "ordered_env.hpp"
|
||||||
|
|
||||||
namespace dropshell {
|
namespace dropshell {
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ class sSSHInfo {
|
|||||||
std::string user_dir; // dropshell directory for the user.
|
std::string user_dir; // dropshell directory for the user.
|
||||||
};
|
};
|
||||||
|
|
||||||
bool execute_local_command(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> & env_vars, std::string * output = nullptr, cMode mode = cMode::Defaults);
|
bool execute_local_command(std::string directory_to_run_in, std::string command_to_run, const ordered_env_vars& env_vars, std::string * output = nullptr, cMode mode = cMode::Defaults);
|
||||||
bool execute_ssh_command(const sSSHInfo & ssh_info, const sCommand & remote_command, cMode mode = cMode::Defaults, std::string * output = nullptr);
|
bool execute_ssh_command(const sSSHInfo & ssh_info, const sCommand & remote_command, cMode mode = cMode::Defaults, std::string * output = nullptr);
|
||||||
|
|
||||||
|
|
||||||
@@ -54,14 +55,14 @@ bool execute_ssh_command(const sSSHInfo & ssh_info, const sCommand & remote_comm
|
|||||||
// class to hold a command to run on the remote server.
|
// class to hold a command to run on the remote server.
|
||||||
class sCommand {
|
class sCommand {
|
||||||
public:
|
public:
|
||||||
sCommand(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> & env_vars) :
|
sCommand(std::string directory_to_run_in, std::string command_to_run, const ordered_env_vars& env_vars) :
|
||||||
mDir(directory_to_run_in), mCmd(command_to_run), mVars(env_vars) {}
|
mDir(directory_to_run_in), mCmd(command_to_run), mVars(env_vars) {}
|
||||||
|
|
||||||
std::string get_directory_to_run_in() const { return mDir; }
|
std::string get_directory_to_run_in() const { return mDir; }
|
||||||
std::string get_command_to_run() const { return mCmd; }
|
std::string get_command_to_run() const { return mCmd; }
|
||||||
const std::map<std::string, std::string>& get_env_vars() const { return mVars; }
|
const ordered_env_vars& get_env_vars() const { return mVars; }
|
||||||
|
|
||||||
void add_env_var(const std::string& key, const std::string& value) { mVars[key] = value; }
|
void add_env_var(const std::string& key, const std::string& value) { mVars.emplace_back(key, value); }
|
||||||
|
|
||||||
bool empty() const { return mCmd.empty(); }
|
bool empty() const { return mCmd.empty(); }
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ class sCommand {
|
|||||||
private:
|
private:
|
||||||
std::string mDir;
|
std::string mDir;
|
||||||
std::string mCmd;
|
std::string mCmd;
|
||||||
std::map<std::string, std::string> mVars;
|
ordered_env_vars mVars;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool EXITSTATUSCHECK(int ret);
|
bool EXITSTATUSCHECK(int ret);
|
||||||
|
64
source/src/utils/ordered_env.hpp
Normal file
64
source/src/utils/ordered_env.hpp
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#ifndef ORDERED_ENV_HPP
|
||||||
|
#define ORDERED_ENV_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
// Type alias for insertion-ordered environment variables
|
||||||
|
using ordered_env_vars = std::vector<std::pair<std::string, std::string>>;
|
||||||
|
|
||||||
|
// Helper functions for working with ordered_env_vars like a map
|
||||||
|
|
||||||
|
// Find a variable by key (returns iterator)
|
||||||
|
inline auto find_var(ordered_env_vars& vars, const std::string& key) {
|
||||||
|
return std::find_if(vars.begin(), vars.end(),
|
||||||
|
[&](const auto& p) { return p.first == key; });
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto find_var(const ordered_env_vars& vars, const std::string& key) {
|
||||||
|
return std::find_if(vars.begin(), vars.end(),
|
||||||
|
[&](const auto& p) { return p.first == key; });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a variable value (returns empty string if not found)
|
||||||
|
inline std::string get_var(const ordered_env_vars& vars, const std::string& key) {
|
||||||
|
auto it = find_var(vars, key);
|
||||||
|
return (it != vars.end()) ? it->second : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a variable (updates if exists, appends if new)
|
||||||
|
inline void set_var(ordered_env_vars& vars, const std::string& key, const std::string& value) {
|
||||||
|
auto it = find_var(vars, key);
|
||||||
|
if (it != vars.end()) {
|
||||||
|
it->second = value;
|
||||||
|
} else {
|
||||||
|
vars.emplace_back(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a variable exists
|
||||||
|
inline bool has_var(const ordered_env_vars& vars, const std::string& key) {
|
||||||
|
return find_var(vars, key) != vars.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge variables from another ordered_env_vars (appends new, skips existing)
|
||||||
|
inline void merge_vars(ordered_env_vars& dest, const ordered_env_vars& src) {
|
||||||
|
for (const auto& [key, value] : src) {
|
||||||
|
if (!has_var(dest, key)) {
|
||||||
|
dest.emplace_back(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all variables
|
||||||
|
inline void clear_vars(ordered_env_vars& vars) {
|
||||||
|
vars.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dropshell
|
||||||
|
|
||||||
|
#endif
|
@@ -376,7 +376,7 @@ std::string replace_with_environment_variables_like_bash(std::string str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string substitute_provided_key_value_pairs(std::string str, const std::map<std::string, std::string> &env_vars)
|
std::string substitute_provided_key_value_pairs(std::string str, const ordered_env_vars& env_vars)
|
||||||
{
|
{
|
||||||
// Combined regex pattern for both ${var} and $var formats
|
// Combined regex pattern for both ${var} and $var formats
|
||||||
std::regex var_pattern("\\$(?:\\{([^}]+)\\}|([a-zA-Z0-9_]+))");
|
std::regex var_pattern("\\$(?:\\{([^}]+)\\}|([a-zA-Z0-9_]+))");
|
||||||
@@ -388,9 +388,8 @@ std::string substitute_provided_key_value_pairs(std::string str, const std::map<
|
|||||||
// match[2] will contain capture from $var format
|
// match[2] will contain capture from $var format
|
||||||
std::string var_name = match[1].matched ? match[1].str() : match[2].str();
|
std::string var_name = match[1].matched ? match[1].str() : match[2].str();
|
||||||
|
|
||||||
// Get value from environment variables map
|
// Get value from environment variables
|
||||||
auto it = env_vars.find(var_name);
|
std::string value = get_var(env_vars, var_name);
|
||||||
std::string value = (it != env_vars.end()) ? it->second : "";
|
|
||||||
|
|
||||||
result = result.replace(match.position(), match.length(), value);
|
result = result.replace(match.position(), match.length(), value);
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "output.hpp"
|
#include "output.hpp"
|
||||||
|
#include "ordered_env.hpp"
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
namespace dropshell {
|
namespace dropshell {
|
||||||
@@ -54,7 +55,7 @@ std::string right_align(const std::string & str, int width);
|
|||||||
std::string center_align(const std::string & str, int width);
|
std::string center_align(const std::string & str, int width);
|
||||||
|
|
||||||
std::string replace_with_environment_variables_like_bash(std::string str);
|
std::string replace_with_environment_variables_like_bash(std::string str);
|
||||||
std::string substitute_provided_key_value_pairs(std::string str, const std::map<std::string, std::string> & env_vars);
|
std::string substitute_provided_key_value_pairs(std::string str, const ordered_env_vars& env_vars);
|
||||||
|
|
||||||
int get_console_width();
|
int get_console_width();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user