From 368b751a63d5a9a1de4e43806531749230246730 Mon Sep 17 00:00:00 2001 From: Chris Punches Date: Tue, 11 Mar 2025 00:55:16 -0400 Subject: [PATCH] restructured the build module --- dpmdk/include/CommonModuleAPI.hpp | 7 +- modules/build/CMakeLists.txt | 8 +- modules/build/build.cpp | 5 +- .../{buildFuncs.hpp => cli_parsers.hpp} | 79 ++---- modules/build/include/commands.hpp | 27 ++ modules/build/include/helpers.hpp | 56 +++++ modules/build/src/buildFuncs.cpp | 234 ------------------ modules/build/src/cli_parsers.cpp | 193 +++++++++++++++ modules/build/src/commands.cpp | 90 +++++++ modules/build/src/helpers.cpp | 32 +++ 10 files changed, 428 insertions(+), 303 deletions(-) rename modules/build/include/{buildFuncs.hpp => cli_parsers.hpp} (63%) create mode 100644 modules/build/include/commands.hpp create mode 100644 modules/build/include/helpers.hpp delete mode 100644 modules/build/src/buildFuncs.cpp create mode 100644 modules/build/src/cli_parsers.cpp create mode 100644 modules/build/src/commands.cpp create mode 100644 modules/build/src/helpers.cpp diff --git a/dpmdk/include/CommonModuleAPI.hpp b/dpmdk/include/CommonModuleAPI.hpp index 6f4263a..9665f89 100644 --- a/dpmdk/include/CommonModuleAPI.hpp +++ b/dpmdk/include/CommonModuleAPI.hpp @@ -177,14 +177,13 @@ int main(int argc, char** argv) { \ /* If arguments are provided, use the first as command */ \ if (argc > 1) { \ command = argv[1]; \ - /* Shift the argument array for the command handler */ \ + /* Shift arguments for the command handler but keep the original argc count */ \ argv++; \ argc--; \ } \ \ std::cout << "Executing command: " << command << std::endl; \ - return dpm_module_execute(command, argc - 1, argv + 1); \ + return dpm_module_execute(command, argc, argv); \ } -#endif // BUILD_STANDALONE - +#endif // BUILD_STANDALONE \ No newline at end of file diff --git a/modules/build/CMakeLists.txt b/modules/build/CMakeLists.txt index 8729268..cc59507 100644 --- a/modules/build/CMakeLists.txt +++ b/modules/build/CMakeLists.txt @@ -13,7 +13,9 @@ endif() # Module version - used by DPM add_library(build MODULE build.cpp - src/buildFuncs.cpp + src/helpers.cpp + src/cli_parsers.cpp + src/commands.cpp ) # Set output properties @@ -35,7 +37,9 @@ target_link_libraries(build stdc++fs) # Standalone version - used for debugging add_executable(build_standalone build.cpp - src/buildFuncs.cpp + src/helpers.cpp + src/cli_parsers.cpp + src/commands.cpp ) # Define the BUILD_STANDALONE macro for the standalone build diff --git a/modules/build/build.cpp b/modules/build/build.cpp index 59d2a3f..65ef199 100644 --- a/modules/build/build.cpp +++ b/modules/build/build.cpp @@ -28,11 +28,12 @@ */ #include -#include #include #include -#include "include/buildFuncs.hpp" +#include "include/helpers.hpp" +#include "include/commands.hpp" +#include "include/cli_parsers.hpp" /** * @def MODULE_VERSION diff --git a/modules/build/include/buildFuncs.hpp b/modules/build/include/cli_parsers.hpp similarity index 63% rename from modules/build/include/buildFuncs.hpp rename to modules/build/include/cli_parsers.hpp index f277f5a..d0df52b 100644 --- a/modules/build/include/buildFuncs.hpp +++ b/modules/build/include/cli_parsers.hpp @@ -1,25 +1,14 @@ -/** - * @file buildFuncs.hpp - * @brief Header file for the build module support functions - * - * Defines functions and enumerations for the build module which creates - * DPM packages according to specification. - * - * @copyright Copyright (c) 2025 SILO GROUP LLC - * @author Chris Punches - * - * Part of the Dark Horse Linux Package Manager (DPM) - */ #pragma once +#include #include #include -#include #include -#include +#include +#include "helpers.hpp" /** - * @enum Command +* @enum Command * @brief Enumeration of supported commands for the build module */ enum Command { @@ -41,6 +30,7 @@ struct BuildOptions { std::string signature_key; /**< Path to the GPG key for signing the package */ bool force; /**< Flag to force package creation even if warnings occur */ bool verbose; /**< Flag for verbose output */ + bool show_help; /**< Flag to show help information */ // Constructor with default values BuildOptions() : @@ -51,54 +41,10 @@ struct BuildOptions { package_name(""), signature_key(""), force(false), - verbose(false) {} + verbose(false), + show_help(false) {} }; -/** - * @brief Handler for the help command - * - * Displays information about available commands in the build module. - * - * @param argc Number of arguments - * @param argv Array of arguments - * @return 0 on success, non-zero on failure - */ -int cmd_help(int argc, char** argv); - -/** - * @brief Handler for the create command - * - * Processes arguments and creates a DPM package. - * - * @param argc Number of arguments - * @param argv Array of arguments - * @return 0 on success, non-zero on failure - */ -int cmd_create(int argc, char** argv); - -/** - * @brief Handler for unknown commands - * - * Displays an error message for unrecognized commands. - * - * @param command The unrecognized command string - * @param argc Number of arguments - * @param argv Array of arguments - * @return 1 to indicate failure - */ -int cmd_unknown(const char* command, int argc, char** argv); - -/** - * @brief Parses a command string into a Command enum value - * - * Converts a command string to the appropriate Command enum value - * for internal routing. - * - * @param cmd_str The command string to parse - * @return The corresponding Command enum value - */ -Command parse_command(const char* cmd_str); - /** * @brief Parses command-line arguments for the create command * @@ -111,6 +57,17 @@ Command parse_command(const char* cmd_str); */ int parse_create_options(int argc, char** argv, BuildOptions& options); +/** + * @brief Parses a command string into a Command enum value + * + * Converts a command string to the appropriate Command enum value + * for internal routing. + * + * @param cmd_str The command string to parse + * @return The corresponding Command enum value + */ +Command parse_command(const char* cmd_str); + /** * @brief Validates the build options * diff --git a/modules/build/include/commands.hpp b/modules/build/include/commands.hpp new file mode 100644 index 0000000..8435a00 --- /dev/null +++ b/modules/build/include/commands.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "cli_parsers.hpp" +#include +#include + +/** + * @brief Handler for the create command + * + * Processes arguments and creates a DPM package. + * + * @param argc Number of arguments + * @param argv Array of arguments + * @return 0 on success, non-zero on failure + */ +int cmd_create(int argc, char** argv); + +/** + * @brief Handler for the help command + * + * Displays information about available commands in the build module. + * + * @param argc Number of arguments + * @param argv Array of arguments + * @return 0 on success, non-zero on failure + */ +int cmd_help(int argc, char** argv); \ No newline at end of file diff --git a/modules/build/include/helpers.hpp b/modules/build/include/helpers.hpp new file mode 100644 index 0000000..e31f35c --- /dev/null +++ b/modules/build/include/helpers.hpp @@ -0,0 +1,56 @@ +/** + * @file helpers.hpp + * @brief Header file for the build module support functions + * + * Defines functions and enumerations for the build module which creates + * DPM packages according to specification. + * + * @copyright Copyright (c) 2025 SILO GROUP LLC + * @author Chris Punches + * + * Part of the Dark Horse Linux Package Manager (DPM) + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief Expands environment variables and tildes in a path + * + * Uses wordexp to handle shell-like expansions in paths, + * including environment variables, tildes, and wildcards. + * + * @param path The path string to expand + * @return The expanded path, or the original path if expansion failed + */ +std::string expand_path(const std::string& path); + +/** + * @brief Handler for the help command + * + * Displays information about available commands in the build module. + * + * @param argc Number of arguments + * @param argv Array of arguments + * @return 0 on success, non-zero on failure + */ +int cmd_help(int argc, char** argv); + +/** + * @brief Handler for unknown commands + * + * Displays an error message for unrecognized commands. + * + * @param command The unrecognized command string + * @param argc Number of arguments + * @param argv Array of arguments + * @return 1 to indicate failure + */ +int cmd_unknown(const char* command, int argc, char** argv); + diff --git a/modules/build/src/buildFuncs.cpp b/modules/build/src/buildFuncs.cpp deleted file mode 100644 index 6cdda20..0000000 --- a/modules/build/src/buildFuncs.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/** - * @file buildFuncs.cpp - * @brief Implementation of the build module support functions - * - * Implements functions for the build module that create DPM packages - * according to the specification. - * - * @copyright Copyright (c) 2025 SILO GROUP LLC - * @author Chris Punches - * - * Part of the Dark Horse Linux Package Manager (DPM) - */ - -#include "buildFuncs.hpp" -#include -#include - -/** - * @brief Handler for the help command - */ -int cmd_help(int argc, char** argv) { - dpm_log(LOG_INFO, "DPM Build Module - Creates DPM packages according to specification"); - dpm_log(LOG_INFO, "Available commands:"); - dpm_log(LOG_INFO, " create - Create a new DPM package"); - dpm_log(LOG_INFO, " help - Display this help message"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Usage: dpm build create [options]"); - dpm_log(LOG_INFO, "Options:"); - dpm_log(LOG_INFO, " -o, --output-dir DIR Directory to save the built package (default: current directory)"); - dpm_log(LOG_INFO, " -c, --contents DIR Directory with package contents (required)"); - dpm_log(LOG_INFO, " -m, --metadata DIR Directory with package metadata (required)"); - dpm_log(LOG_INFO, " -H, --hooks DIR Directory with package hooks (optional)"); - dpm_log(LOG_INFO, " -n, --name NAME Package name (required if not in metadata)"); - dpm_log(LOG_INFO, " -s, --sign KEY Path to GPG key for signing the package (optional)"); - dpm_log(LOG_INFO, " -f, --force Force package creation even if warnings occur"); - dpm_log(LOG_INFO, " -v, --verbose Enable verbose output"); - dpm_log(LOG_INFO, " -h, --help Display this help message"); - return 0; -} - -/** - * @brief Handler for unknown commands - */ -int cmd_unknown(const char* command, int argc, char** argv) { - std::string msg = "Unknown command: "; - msg += (command ? command : ""); - dpm_log(LOG_WARN, msg.c_str()); - dpm_log(LOG_WARN, "Run 'dpm build help' for a list of available commands"); - return 1; -} - -/** - * @brief Parses a command string to Command enum - */ -Command parse_command(const char* cmd_str) { - if (cmd_str == nullptr || strlen(cmd_str) == 0) { - return CMD_HELP; - } - - if (strcmp(cmd_str, "help") == 0) { - return CMD_HELP; - } - else if (strcmp(cmd_str, "create") == 0) { - return CMD_CREATE; - } - - return CMD_UNKNOWN; -} - -/** - * @brief Handler for the create command - */ -int cmd_create(int argc, char** argv) { - BuildOptions options; - - // Parse command-line options - int parse_result = parse_create_options(argc, argv, options); - if (parse_result != 0) { - return parse_result; - } - - // Validate options - int validate_result = validate_build_options(options); - if (validate_result != 0) { - return validate_result; - } - - // Log the operation - if (options.verbose) { - dpm_log(LOG_INFO, "Creating DPM package with the following options:"); - dpm_log(LOG_INFO, (" Output directory: " + options.output_dir).c_str()); - dpm_log(LOG_INFO, (" Contents directory: " + options.contents_dir).c_str()); - dpm_log(LOG_INFO, (" Metadata directory: " + options.metadata_dir).c_str()); - - if (!options.hooks_dir.empty()) { - dpm_log(LOG_INFO, (" Hooks directory: " + options.hooks_dir).c_str()); - } - - if (!options.package_name.empty()) { - dpm_log(LOG_INFO, (" Package name: " + options.package_name).c_str()); - } - - if (!options.signature_key.empty()) { - dpm_log(LOG_INFO, (" Signature key: " + options.signature_key).c_str()); - } - - if (options.force) { - dpm_log(LOG_INFO, " Force: Yes"); - } - } - - // For now, just log that we would create the package - dpm_log(LOG_INFO, "Package creation functionality not yet implemented"); - dpm_log(LOG_INFO, "Would create package using the provided options"); - - return 0; -} - -/** - * @brief Parses command-line arguments for the create command - */ -int parse_create_options(int argc, char** argv, BuildOptions& options) { - static struct option long_options[] = { - {"output-dir", required_argument, 0, 'o'}, - {"contents", required_argument, 0, 'c'}, - {"metadata", required_argument, 0, 'm'}, - {"hooks", required_argument, 0, 'H'}, - {"name", required_argument, 0, 'n'}, - {"sign", required_argument, 0, 's'}, - {"force", no_argument, 0, 'f'}, - {"verbose", no_argument, 0, 'v'}, - {"help", no_argument, 0, 'h'}, - {0, 0, 0, 0} - }; - - // Skip program name and module name - int adjusted_argc = argc; - char** adjusted_argv = argv; - - // Reset getopt - optind = 0; - opterr = 1; - - int opt; - int option_index = 0; - - while ((opt = getopt_long(adjusted_argc, adjusted_argv, "o:c:m:H:n:s:fvh", long_options, &option_index)) != -1) { - switch (opt) { - case 'o': - options.output_dir = optarg; - break; - case 'c': - options.contents_dir = optarg; - break; - case 'm': - options.metadata_dir = optarg; - break; - case 'H': - options.hooks_dir = optarg; - break; - case 'n': - options.package_name = optarg; - break; - case 's': - options.signature_key = optarg; - break; - case 'f': - options.force = true; - break; - case 'v': - options.verbose = true; - break; - case 'h': - cmd_help(0, nullptr); - return 1; - case '?': - // Error message is printed by getopt - dpm_log(LOG_ERROR, "Run 'dpm build create --help' for usage information"); - return 1; - default: - dpm_log(LOG_ERROR, "Unknown option"); - return 1; - } - } - - return 0; -} - -/** - * @brief Validates the build options - */ -int validate_build_options(const BuildOptions& options) { - // Check if contents directory is provided and exists - if (options.contents_dir.empty()) { - dpm_log(LOG_ERROR, "Contents directory is required (--contents)"); - return 1; - } - - if (!std::filesystem::exists(options.contents_dir)) { - dpm_log(LOG_ERROR, ("Contents directory does not exist: " + options.contents_dir).c_str()); - return 1; - } - - // Check if metadata directory is provided and exists - if (options.metadata_dir.empty()) { - dpm_log(LOG_ERROR, "Metadata directory is required (--metadata)"); - return 1; - } - - if (!std::filesystem::exists(options.metadata_dir)) { - dpm_log(LOG_ERROR, ("Metadata directory does not exist: " + options.metadata_dir).c_str()); - return 1; - } - - // Check if hooks directory exists if provided - if (!options.hooks_dir.empty() && !std::filesystem::exists(options.hooks_dir)) { - dpm_log(LOG_ERROR, ("Hooks directory does not exist: " + options.hooks_dir).c_str()); - return 1; - } - - // Check if output directory exists - if (!std::filesystem::exists(options.output_dir)) { - dpm_log(LOG_ERROR, ("Output directory does not exist: " + options.output_dir).c_str()); - return 1; - } - - // Check if signature key exists if provided - if (!options.signature_key.empty() && !std::filesystem::exists(options.signature_key)) { - dpm_log(LOG_ERROR, ("Signature key file does not exist: " + options.signature_key).c_str()); - return 1; - } - - return 0; -} diff --git a/modules/build/src/cli_parsers.cpp b/modules/build/src/cli_parsers.cpp new file mode 100644 index 0000000..e717827 --- /dev/null +++ b/modules/build/src/cli_parsers.cpp @@ -0,0 +1,193 @@ +#include "cli_parsers.hpp" + +int parse_create_options(int argc, char** argv, BuildOptions& options) { + // For debugging + dpm_log(LOG_DEBUG, "Parsing command-line arguments"); + for (int i = 0; i < argc; i++) { + std::string arg_msg = "Arg " + std::to_string(i) + ": " + (argv[i] ? argv[i] : "(null)"); + dpm_log(LOG_DEBUG, arg_msg.c_str()); + } + + // First process any arguments in --option=value format + for (int i = 0; i < argc; i++) { + if (!argv[i] || strlen(argv[i]) == 0) continue; + + std::string arg(argv[i]); + size_t equals_pos = arg.find('='); + + if (equals_pos != std::string::npos && arg.length() > 3 && arg[0] == '-' && arg[1] == '-') { + // Extract option and value + std::string option = arg.substr(0, equals_pos); + std::string value = arg.substr(equals_pos + 1); + + if (option == "--output-dir") { + options.output_dir = value; + } else if (option == "--contents") { + options.contents_dir = value; + } else if (option == "--metadata") { + options.metadata_dir = value; + } else if (option == "--hooks") { + options.hooks_dir = value; + } else if (option == "--name") { + options.package_name = value; + } else if (option == "--sign") { + options.signature_key = value; + } else if (option == "--force") { + options.force = true; + } else if (option == "--verbose") { + options.verbose = true; + } else if (option == "--help") { + options.show_help = true; + } + + // Convert this argument to a dummy to prevent getopt from processing it + argv[i] = strdup("--dummy"); + } + } + + static struct option long_options[] = { + {"output-dir", required_argument, 0, 'o'}, + {"contents", required_argument, 0, 'c'}, + {"metadata", required_argument, 0, 'm'}, + {"hooks", required_argument, 0, 'H'}, + {"name", required_argument, 0, 'n'}, + {"sign", required_argument, 0, 's'}, + {"force", no_argument, 0, 'f'}, + {"verbose", no_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {"dummy", no_argument, 0, 0}, // Add dummy option to prevent getopt errors + {0, 0, 0, 0} + }; + + // Reset getopt + optind = 0; + opterr = 0; // Suppress getopt error messages + + int opt; + int option_index = 0; + + while ((opt = getopt_long(argc, argv, "o:c:m:H:n:s:fvh", long_options, &option_index)) != -1) { + switch (opt) { + case 'o': + options.output_dir = optarg; + break; + case 'c': + options.contents_dir = optarg; + break; + case 'm': + options.metadata_dir = optarg; + break; + case 'H': + options.hooks_dir = optarg; + break; + case 'n': + options.package_name = optarg; + break; + case 's': + options.signature_key = optarg; + break; + case 'f': + options.force = true; + break; + case 'v': + options.verbose = true; + break; + case 'h': + options.show_help = true; + break; + case '?': + // Ignore errors as we handle equals-format options separately + break; + default: + break; + } + } + + // Expand paths after all arguments have been processed + if (!options.output_dir.empty()) { + options.output_dir = expand_path(options.output_dir); + } + + if (!options.contents_dir.empty()) { + options.contents_dir = expand_path(options.contents_dir); + } + + if (!options.metadata_dir.empty()) { + options.metadata_dir = expand_path(options.metadata_dir); + } + + if (!options.hooks_dir.empty()) { + options.hooks_dir = expand_path(options.hooks_dir); + } + + if (!options.signature_key.empty()) { + options.signature_key = expand_path(options.signature_key); + } + + // Log the parsed options for debugging + dpm_log(LOG_DEBUG, ("Parsed options: contents_dir=" + options.contents_dir).c_str()); + + return 0; +} + +Command parse_command(const char* cmd_str) { + if (cmd_str == nullptr || strlen(cmd_str) == 0) { + return CMD_HELP; + } + + if (strcmp(cmd_str, "help") == 0) { + return CMD_HELP; + } + else if (strcmp(cmd_str, "create") == 0) { + return CMD_CREATE; + } + + return CMD_UNKNOWN; +} + +/** + * @brief Validates the build options + */ +int validate_build_options(const BuildOptions& options) { + // Check if contents directory is provided and exists + if (options.contents_dir.empty()) { + dpm_log(LOG_ERROR, "Contents directory is required (--contents)"); + return 1; + } + + if (!std::filesystem::exists(options.contents_dir)) { + dpm_log(LOG_ERROR, ("Contents directory does not exist: " + options.contents_dir).c_str()); + return 1; + } + + // Check if metadata directory is provided and exists + if (options.metadata_dir.empty()) { + dpm_log(LOG_ERROR, "Metadata directory is required (--metadata)"); + return 1; + } + + if (!std::filesystem::exists(options.metadata_dir)) { + dpm_log(LOG_ERROR, ("Metadata directory does not exist: " + options.metadata_dir).c_str()); + return 1; + } + + // Check if hooks directory exists if provided + if (!options.hooks_dir.empty() && !std::filesystem::exists(options.hooks_dir)) { + dpm_log(LOG_ERROR, ("Hooks directory does not exist: " + options.hooks_dir).c_str()); + return 1; + } + + // Check if output directory exists + if (!std::filesystem::exists(options.output_dir)) { + dpm_log(LOG_ERROR, ("Output directory does not exist: " + options.output_dir).c_str()); + return 1; + } + + // Check if signature key exists if provided + if (!options.signature_key.empty() && !std::filesystem::exists(options.signature_key)) { + dpm_log(LOG_ERROR, ("Signature key file does not exist: " + options.signature_key).c_str()); + return 1; + } + + return 0; +} diff --git a/modules/build/src/commands.cpp b/modules/build/src/commands.cpp new file mode 100644 index 0000000..83be705 --- /dev/null +++ b/modules/build/src/commands.cpp @@ -0,0 +1,90 @@ +#include "commands.hpp" + +int cmd_create(int argc, char** argv) { + // create a container for commandline options + BuildOptions options; + + // Parse command-line options + int parse_result = parse_create_options(argc, argv, options); + if (parse_result != 0) { + return parse_result; + } + + // If help was requested, show it and return + if (options.show_help) { + return cmd_help(argc, argv); + } + + // Validate options + int validate_result = validate_build_options(options); + if (validate_result != 0) { + return validate_result; + } + + // Log the operation + if (options.verbose) { + dpm_log(LOG_INFO, "Creating DPM package with the following options:"); + dpm_log(LOG_INFO, (" Output directory: " + options.output_dir).c_str()); + dpm_log(LOG_INFO, (" Contents directory: " + options.contents_dir).c_str()); + dpm_log(LOG_INFO, (" Metadata directory: " + options.metadata_dir).c_str()); + + if (!options.hooks_dir.empty()) { + dpm_log(LOG_INFO, (" Hooks directory: " + options.hooks_dir).c_str()); + } + + if (!options.package_name.empty()) { + dpm_log(LOG_INFO, (" Package name: " + options.package_name).c_str()); + } + + if (!options.signature_key.empty()) { + dpm_log(LOG_INFO, (" Signature key: " + options.signature_key).c_str()); + } + + if (options.force) { + dpm_log(LOG_INFO, " Force: Yes"); + } + } + + // For now, just log that we would create the package + dpm_log(LOG_INFO, "Package creation functionality not yet implemented"); + dpm_log(LOG_INFO, "Would create package using the provided options"); + + return 0; +} + +/** + * @brief Handler for the help command + */ +int cmd_help(int argc, char** argv) { + dpm_log(LOG_INFO, "DPM Build Module - Creates DPM packages according to specification"); + dpm_log(LOG_INFO, "Available commands:"); + dpm_log(LOG_INFO, " create - Create a new DPM package"); + dpm_log(LOG_INFO, " help - Display this help message"); + dpm_log(LOG_INFO, ""); + dpm_log(LOG_INFO, "Usage: dpm build create [options]"); + dpm_log(LOG_INFO, "Options:"); + dpm_log(LOG_INFO, " -o, --output-dir DIR Directory to save the built package (default: current directory)"); + dpm_log(LOG_INFO, " -c, --contents DIR Directory with package contents (required)"); + dpm_log(LOG_INFO, " -m, --metadata DIR Directory with package metadata (required)"); + dpm_log(LOG_INFO, " -H, --hooks DIR Directory with package hooks (optional)"); + dpm_log(LOG_INFO, " -n, --name NAME Package name (required if not in metadata)"); + dpm_log(LOG_INFO, " -s, --sign KEY Path to GPG key for signing the package (optional)"); + dpm_log(LOG_INFO, " -f, --force Force package creation even if warnings occur"); + dpm_log(LOG_INFO, " -v, --verbose Enable verbose output"); + dpm_log(LOG_INFO, " -h, --help Display this help message"); + return 0; +} + +/** + * @brief Handler for unknown commands + */ +int cmd_unknown(const char* command, int argc, char** argv) { + std::string msg = "Unknown command: "; + msg += (command ? command : ""); + dpm_log(LOG_WARN, msg.c_str()); + dpm_log(LOG_WARN, "Run 'dpm build help' for a list of available commands"); + return 1; +} + + + diff --git a/modules/build/src/helpers.cpp b/modules/build/src/helpers.cpp new file mode 100644 index 0000000..0a0f59a --- /dev/null +++ b/modules/build/src/helpers.cpp @@ -0,0 +1,32 @@ +/** + * @file buildFuncs.cpp + * @brief Implementation of the build module support functions + * + * Implements functions for the build module that create DPM packages + * according to the specification. + * + * @copyright Copyright (c) 2025 SILO GROUP LLC + * @author Chris Punches + * + * Part of the Dark Horse Linux Package Manager (DPM) + */ + +#include "helpers.hpp" + +/** + * @brief Expands environment variables and tildes in a path + */ +std::string expand_path(const std::string& path) { + wordexp_t exp_result; + std::string expanded_path = path; + + // Use wordexp to expand the path + if (wordexp(path.c_str(), &exp_result, 0) == 0) { + if (exp_result.we_wordc > 0) { + expanded_path = exp_result.we_wordv[0]; + } + wordfree(&exp_result); + } + + return expanded_path; +}