From 0917e1e3f3148e10ec48aecded2184d48578dbde Mon Sep 17 00:00:00 2001 From: j Date: Tue, 30 Dec 2025 09:04:06 +1300 Subject: [PATCH] Tidy --- source/src/commands/create-service.cpp | 20 ++-- source/src/commands/edit.cpp | 2 +- source/src/commands/install.cpp | 2 +- ...alidator.cpp => service_env_validator.cpp} | 94 ++++++++++++++++++- ...alidator.hpp => service_env_validator.hpp} | 26 ++++- 5 files changed, 130 insertions(+), 14 deletions(-) rename source/src/utils/{env_validator.cpp => service_env_validator.cpp} (65%) rename source/src/utils/{env_validator.hpp => service_env_validator.hpp} (53%) diff --git a/source/src/commands/create-service.cpp b/source/src/commands/create-service.cpp index 5f5407b..32969b2 100644 --- a/source/src/commands/create-service.cpp +++ b/source/src/commands/create-service.cpp @@ -5,6 +5,7 @@ #include #include "utils/utils.hpp" +#include "utils/service_env_validator.hpp" #include "services.hpp" #include @@ -156,14 +157,6 @@ namespace dropshell // copy the template config files to the service directory recursive_copy(tinfo.local_template_path() / "config", service_dir); - // append TEMPLATE to the service.env file - std::string service_env_file = localfile::service_env(server_name, service_name); - ASSERT(std::filesystem::exists(service_env_file),"service.env not found: "+ service_env_file); - std::ofstream ofs(service_env_file, std::ios::app); - ofs << std::endl << "# TEMPLATE set by dropshell on creation. Important this does not change." << std::endl; - ofs << "TEMPLATE=\"" << template_name <<"\"" << std::endl; - ofs.close(); - // modify the SSH_USER to be nice. // everything is created, so we can get the service info. LocalServiceInfo service_info = get_service_info(server_name, service_name); @@ -214,6 +207,17 @@ namespace dropshell service_env_file_out.close(); } + // set TEMPLATE in service.env (removes any existing definition first) + if (!set_env_variable( + localfile::service_env(server_name, service_name), + "TEMPLATE", + template_name, + "TEMPLATE set by dropshell on creation. Important this does not change.")) + { + error << "Failed to set TEMPLATE in service.env" << std::endl; + return false; + } + // check docker. if (service_info.requires_docker) { diff --git a/source/src/commands/edit.cpp b/source/src/commands/edit.cpp index 1d806d2..0f64b3f 100644 --- a/source/src/commands/edit.cpp +++ b/source/src/commands/edit.cpp @@ -2,7 +2,7 @@ #include "config.hpp" #include "utils/utils.hpp" #include "utils/directories.hpp" -#include "utils/env_validator.hpp" +#include "utils/service_env_validator.hpp" #include "shared_commands.hpp" #include "services.hpp" #include "templates.hpp" diff --git a/source/src/commands/install.cpp b/source/src/commands/install.cpp index 17f4d24..a1dc8e2 100644 --- a/source/src/commands/install.cpp +++ b/source/src/commands/install.cpp @@ -9,7 +9,7 @@ #include "autogen/_agent-remote.hpp" #include "services.hpp" #include "utils/output.hpp" -#include "utils/env_validator.hpp" +#include "utils/service_env_validator.hpp" #include #include diff --git a/source/src/utils/env_validator.cpp b/source/src/utils/service_env_validator.cpp similarity index 65% rename from source/src/utils/env_validator.cpp rename to source/src/utils/service_env_validator.cpp index 1f579ca..67c4561 100644 --- a/source/src/utils/env_validator.cpp +++ b/source/src/utils/service_env_validator.cpp @@ -1,4 +1,4 @@ -#include "env_validator.hpp" +#include "service_env_validator.hpp" #include "envmanager.hpp" #include "ordered_env.hpp" #include "utils.hpp" @@ -157,4 +157,96 @@ bool validate_and_fix_service_env( return false; } +bool set_env_variable( + const std::string& env_file_path, + const std::string& var_name, + const std::string& var_value, + const std::string& comment +) { + // Read existing file contents + std::vector lines; + + if (std::filesystem::exists(env_file_path)) { + std::ifstream infile(env_file_path); + if (!infile.is_open()) { + error << "Failed to open env file for reading: " << env_file_path << std::endl; + return false; + } + + std::string line; + while (std::getline(infile, line)) { + lines.push_back(line); + } + infile.close(); + } + + // Build the comment line we're looking for (if comment provided) + std::string comment_line; + if (!comment.empty()) { + comment_line = "# " + comment; + } + + // Build the pattern to match variable assignment: VAR_NAME= at start of line + std::string var_pattern = var_name + "="; + + // Filter out existing variable definition and matching comment + std::vector filtered_lines; + for (size_t i = 0; i < lines.size(); ++i) { + const std::string& line = lines[i]; + std::string trimmed = trim(line); + + // Check if this line is the exact comment we want to add + if (!comment_line.empty() && trimmed == comment_line) { + // Skip this comment line + continue; + } + + // Check if this line defines our variable + if (!trimmed.empty() && trimmed[0] != '#') { + size_t eq_pos = trimmed.find('='); + if (eq_pos != std::string::npos) { + std::string key = trim(trimmed.substr(0, eq_pos)); + if (key == var_name) { + // Skip this variable definition + continue; + } + } + } + + filtered_lines.push_back(line); + } + + // Remove trailing blank lines so we can control spacing + while (!filtered_lines.empty() && trim(filtered_lines.back()).empty()) { + filtered_lines.pop_back(); + } + + // Add exactly one blank line before our new content (if file is not empty) + if (!filtered_lines.empty()) { + filtered_lines.push_back(""); + } + + // Add the comment if provided + if (!comment_line.empty()) { + filtered_lines.push_back(comment_line); + } + + // Add the variable assignment + filtered_lines.push_back(var_name + "=\"" + var_value + "\""); + + // Write the file back + std::ofstream outfile(env_file_path); + if (!outfile.is_open()) { + error << "Failed to open env file for writing: " << env_file_path << std::endl; + return false; + } + + for (const auto& l : filtered_lines) { + outfile << l << std::endl; + } + outfile.close(); + + return true; +} + } // namespace dropshell diff --git a/source/src/utils/env_validator.hpp b/source/src/utils/service_env_validator.hpp similarity index 53% rename from source/src/utils/env_validator.hpp rename to source/src/utils/service_env_validator.hpp index 833adb1..72657bd 100644 --- a/source/src/utils/env_validator.hpp +++ b/source/src/utils/service_env_validator.hpp @@ -1,5 +1,5 @@ -#ifndef ENV_VALIDATOR_HPP -#define ENV_VALIDATOR_HPP +#ifndef SERVICE_ENV_VALIDATOR_HPP +#define SERVICE_ENV_VALIDATOR_HPP #include #include @@ -24,6 +24,26 @@ bool validate_and_fix_service_env( const std::string& template_info_env_path = "" ); +// Sets or updates a variable in an env file with an optional comment. +// - If the variable already exists, removes that line +// - If the comment already exists (exact match), removes that line too +// - Adds a single blank line, then the comment (if provided), then the variable assignment +// - The variable value is automatically quoted +// +// Parameters: +// env_file_path: Full path to the .env file +// var_name: Name of the variable to set +// var_value: Value to assign (will be quoted) +// comment: Optional comment to place before the variable (without # prefix) +// +// Returns true on success, false on failure +bool set_env_variable( + const std::string& env_file_path, + const std::string& var_name, + const std::string& var_value, + const std::string& comment = "" +); + } // namespace dropshell -#endif // ENV_VALIDATOR_HPP +#endif // SERVICE_ENV_VALIDATOR_HPP