diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-12-11 09:30:07 -0500 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-12-11 09:45:04 -0500 |
commit | 4fd92ec6b203d6b94b9e9f9531fd60a65736e810 (patch) | |
tree | 2b5be989ca839bd97f55f40605e23d7019397be7 /include | |
parent | 1bec4776252cec88ec3336602c0c477c20a1292f (diff) | |
download | stasis-4fd92ec6b203d6b94b9e9f9531fd60a65736e810.tar.gz |
Restructure projectdelivery-lib
* Move headers to relevant include directories within the target tree(s)
* Adjust doxygen configuration to search correct paths
* Adjust CMake configuration to use new include paths
Diffstat (limited to 'include')
-rw-r--r-- | include/artifactory.h | 362 | ||||
-rw-r--r-- | include/conda.h | 234 | ||||
-rw-r--r-- | include/copy.h | 35 | ||||
-rw-r--r-- | include/core.h | 85 | ||||
-rw-r--r-- | include/core_mem.h | 18 | ||||
-rw-r--r-- | include/delivery.h | 448 | ||||
-rw-r--r-- | include/docker.h | 92 | ||||
-rw-r--r-- | include/download.h | 12 | ||||
-rw-r--r-- | include/envctl.h | 39 | ||||
-rw-r--r-- | include/environment.h | 23 | ||||
-rw-r--r-- | include/github.h | 11 | ||||
-rw-r--r-- | include/ini.h | 260 | ||||
-rw-r--r-- | include/junitxml.h | 135 | ||||
-rw-r--r-- | include/multiprocessing.h | 134 | ||||
-rw-r--r-- | include/os_darwin.h | 26 | ||||
-rw-r--r-- | include/os_linux.h | 10 | ||||
-rw-r--r-- | include/package.h | 30 | ||||
-rw-r--r-- | include/recipe.h | 72 | ||||
-rw-r--r-- | include/relocation.h | 24 | ||||
-rw-r--r-- | include/rules.h | 11 | ||||
-rw-r--r-- | include/str.h | 313 | ||||
-rw-r--r-- | include/strlist.h | 60 | ||||
-rw-r--r-- | include/system.h | 34 | ||||
-rw-r--r-- | include/template.h | 81 | ||||
-rw-r--r-- | include/template_func_proto.h | 13 | ||||
-rw-r--r-- | include/utils.h | 416 | ||||
-rw-r--r-- | include/wheel.h | 36 |
27 files changed, 0 insertions, 3014 deletions
diff --git a/include/artifactory.h b/include/artifactory.h deleted file mode 100644 index e580886..0000000 --- a/include/artifactory.h +++ /dev/null @@ -1,362 +0,0 @@ -//! @file artifactory.h -#ifndef STASIS_ARTIFACTORY_H -#define STASIS_ARTIFACTORY_H - -#include <stdio.h> -#include <stdlib.h> -#include "core.h" -#include "download.h" - -//! JFrog Artifactory Authentication struct -struct JFRT_Auth { - bool insecure_tls; //!< Disable TLS - char *access_token; //!< Generated access token - char *password; //!< Password - char *client_cert_key_path; //!< Path to where SSL key is stored - char *client_cert_path; //!< Path to where SSL cert is stored - char *ssh_key_path; //!< Path to SSH private key - char *ssh_passphrase; //!< Passphrase for SSH private key - char *user; //!< Account to authenticate as - char *server_id; //!< Artifactory server identification (unused) - char *url; //!< Artifactory server address -}; - -//! JFrog Artifactory Upload struct -struct JFRT_Upload { - bool quiet; //!< Enable quiet mode - char *project; //!< Destination project name - bool ant; //!< Enable Ant style regex - bool archive; //!< Generate a ZIP archive of the uploaded file(s) - char *build_name; //!< Build name - char *build_number; //!< Build number - bool deb; //!< Is Debian package? - bool detailed_summary; //!< Enable upload summary - bool dry_run; //!< Enable dry run (no-op) - char *exclusions; //!< Exclude patterns (separated by semicolons) - bool explode; //!< If uploaded file is an archive, extract it at the destination - bool fail_no_op; //!< Exit 2 when no file are affected - bool flat; //!< Upload with exact file system structure - bool include_dirs; //!< Enable to upload empty directories - char *module; //!< Build-info module name (optional) - bool recursive; //!< Upload files recursively - bool regexp; //!< Use regular expressions instead of wildcards - int retries; //!< Number of retries before giving up - int retry_wait_time; //!< Seconds between retries - char *spec; //!< Path to JSON upload spec - char *spec_vars; - bool symlinks; //!< Preserve symbolic links - bool sync_deletes; //!< Destination is replaced by uploaded files - char *target_props; //!< Properties (separated by semicolons) - int threads; //!< Thread count - bool workaround_parent_only; //!< Change directory to local parent directory before uploading files -}; - -struct JFRT_Download { - char *archive_entries; - char *build; - char *build_name; - char *build_number; - char *bundle; - bool detailed_summary; - bool dry_run; - char *exclude_artifacts; - char *exclude_props; - char *exclusions; - bool explode; - bool fail_no_op; - bool flat; - char *gpg_key; - char *include_deps; - char *include_dirs; - int limit; - int min_split; - char *module; - int offset; - char *project; - char *props; - bool quiet; - bool recursive; - int retries; - int retry_wait_time; - bool skip_checksum; - char *sort_by; - char *sort_order; - char *spec; - char *spec_vars; - int split_count; - bool sync_deletes; - int threads; - bool validate_symlinks; -}; - -struct JFRT_Search { - char *bundle; - bool count; - char *sort_by; - char *sort_order; - int limit; - int offset; - char *spec; - char *spec_vars; - char *props; - bool recursive; - char *build; - bool fail_no_op; - char *exclusions; - char *exclude_artifacts; - char *exclude_patterns; - char *exclude_props; - char *archive_entries; - char *include; - char *include_deps; - char *include_dirs; - char *project; - char *transitive; -}; - -/** - * Download the JFrog CLI tool from jfrog.com - * ```c - * if (artifactory_download_cli(".", - * "https://releases.jfrog.io/artifactory", - * "jfrog-cli", - * "v2-jf", - * "[RELEASE]", - * "Linux", - * "x86_64", - * "jf") { - * remove("./jf"); - * fprintf(stderr, "Failed to download JFrog CLI\n"); - * exit(1); - * } - * - * ``` - * - * @param dest Directory path - * @param jfrog_artifactory_base_url jfrog.com base URL - * @param jfrog_artifactory_product jfrog.com project (jfrog-cli) - * @param cli_major_ver Version series (v1, v2-jf, vX-jf) - * @param version Version to download. "[RELEASE]" will download the latest version available - * @param os Operating system name - * @param arch System CPU architecture - * @param remote_filename File to download (jf) - * @return - */ -int artifactory_download_cli(char *dest, - char *jfrog_artifactory_base_url, - char *jfrog_artifactory_product, - char *cli_major_ver, - char *version, - char *os, - char *arch, - char *remote_filename); - -/** - * JFrog CLI binding. Executes the "jf" tool with arguments. - * - * ```c - * struct JFRT_Auth auth_ctx; - * auth_ctx.user = strdup("myuser"); - * auth_ctx.password = strdup("mypassword"); - * auth_ctx.url = strdup("https://myserver.tld/artifactory"); - * jfrt_auth_init(&auth_ctx); - * - * if (jfrog_cli(&auth_ctx, "rt", "ping", NULL) { - * fprintf(stderr, "Failed to ping artifactory server: %s\n", auth_ctx.url); - * exit(1); - * } - * ``` - * - * @param auth JFRT_Auth structure - * @param subsystem "jf" tool subsystem (i.e. "rt") - * @param task "jf" tool task "upload", "download", etc - * @param args Command line arguments to pass to "jf" tool - * @return exit code from "jf" - */ -int jfrog_cli(struct JFRT_Auth *auth, const char *subsystem, const char *task, char *args); - -/** - * Issue an Artifactory server ping - * - * ```c - * struct JFRT_Auth auth_ctx; - * auth_ctx.user = strdup("myuser"); - * auth_ctx.password = strdup("mypassword"); - * auth_ctx.url = strdup("https://myserver.tld/artifactory"); - * jfrt_auth_init(&auth_ctx); - * - * if (jfrog_cli_ping(&auth_ctx)) { - * fprintf(stderr, "Failed to ping artifactory server: %s\n", auth_ctx.url); - * exit(1); - * } - * ``` - * - * @param auth JFRT_Auth structure - * @return exit code from "jf" - */ -int jfrog_cli_rt_ping(struct JFRT_Auth *auth); - -/** - * Upload files to an Artifactory repository - * - * ```c - * struct JFRT_Auth auth_ctx; - * auth_ctx.user = strdup("myuser"); - * auth_ctx.password = strdup("mypassword"); - * auth_ctx.url = strdup("https://myserver.tld/artifactory"); - * jfrt_auth_init(&auth_ctx); - * - * struct JFRT_Upload upload_ctx; - * jfrt_upload_init(&upload_ctx); - * - * if (jfrt_cli_rt_upload(&auth_ctx, &upload_ctx, - * "local/files_*.ext", "repo_name/ext_files/")) { - * fprintf(stderr, "Upload failed\n"); - * exit(1); - * } - * ``` - * - * @param auth JFRT_Auth structure - * @param ctx JFRT_Upload structure - * @param src local pattern to upload - * @param repo_path remote Artifactory destination path - * @return exit code from "jf" - */ -int jfrog_cli_rt_upload(struct JFRT_Auth *auth, struct JFRT_Upload *ctx, char *src, char *repo_path); - -/** - * Download a file from an Artifactory repository - * - * ```c - * struct JFRT_Auth auth_ctx; - * auth_ctx.user = strdup("myuser"); - * auth_ctx.password = strdup("mypassword"); - * auth_ctx.url = strdup("https://myserver.tld/artifactory"); - * jfrt_auth_init(&auth_ctx); - * - * struct JFRT_Download download_ctx; - * memset(download_ctx, 0, sizeof(download_ctx)); - * - * if (jfrt_cli_rt_download(&auth_ctx, &download_ctx, - * "repo_name/ext_files/", "local/files_*.ext")) { - * fprintf(stderr, "Upload failed\n"); - * exit(1); - * } - * ``` - * - * @param auth JFRT_Auth structure - * @param ctx JFRT_Download structure - * @param repo_path Remote repository w/ file pattern - * @param dest Local destination path - * @return exit code from "jf" - */ -int jfrog_cli_rt_download(struct JFRT_Auth *auth, struct JFRT_Download *ctx, char *repo_path, char *dest); - -/** - * Search for files in an Artifactory repository - * - * @param auth JFRT_Auth structure - * @param ctx JFRT_Search structure - * @param repo_path Remote repository w/ file pattern - * @param dest Local destination path - * @return exit code from "jf" - */ -int jfrog_cli_rt_search(struct JFRT_Auth *auth, struct JFRT_Search *ctx, char *repo_path, char *pattern); - -/** - * Collect runtime data for Artifactory build object. - * - * ```c - * struct JFRT_Auth auth_ctx; - * auth_ctx.user = strdup("myuser"); - * auth_ctx.password = strdup("mypassword"); - * auth_ctx.url = strdup("https://myserver.tld/artifactory"); - * jfrt_auth_init(&auth_ctx); - * - * if (jfrog_cli_rt_build_collect_env(&auth_ctx, "mybuildname", "1.2.3+gabcdef")) { - * fprintf(stderr, "Failed to collect runtime data for Artifactory build object\n"); - * exit(1); - * } - * ``` - * - * @param auth JFRT_Auth structure - * @param build_name Artifactory build name - * @param build_number Artifactory build number - * @return exit code from "jf" - */ -int jfrog_cli_rt_build_collect_env(struct JFRT_Auth *auth, char *build_name, char *build_number); - -/** - * Publish build object to Artifactory server - * - * ```c - * struct JFRT_Auth auth_ctx; - * auth_ctx.user = strdup("myuser"); - * auth_ctx.password = strdup("mypassword"); - * auth_ctx.url = strdup("https://myserver.tld/artifactory"); - * jfrt_auth_init(&auth_ctx); - * - * if (jfrog_cli_rt_build_collect_env(&auth_ctx, "mybuildname", "1.2.3+gabcdef")) { - * fprintf(stderr, "Failed to collect runtime data for Artifactory build object\n"); - * exit(1); - * } - * - * if (jfrog_cli_rt_build_publish(&auth_ctx, "mybuildname", "1.2.3+gabcdef")) { - * fprintf(stderr, "Failed to publish Artifactory build object\n"); - * exit(1); - * } - * ``` - * - * @param auth JFRT_Auth structure - * @param build_name Artifactory build name - * @param build_number Artifactory build number - * @return exit code from "jf" - */ -int jfrog_cli_rt_build_publish(struct JFRT_Auth *auth, char *build_name, char *build_number); - -/** - * Configure JFrog CLI authentication according to STASIS specs - * - * This function will use the STASIS_JF_* environment variables to configure the authentication - * context. With this in mind, if an STASIS_JF_* environment variable is not defined, the original value of - * the structure member will be used instead. - * - * Use STASIS_JF_* variables to configure context - * - * ```c - * struct JFRT_Auth auth_ctx; - * jfrt_auth_init(&ctx); - * ``` - * - * Use your own input, but let the environment take over when variables are defined - * - * ```c - * struct JFRT_Auth auth_ctx; - * auth_ctx.user = strdup("myuser"); - * auth_ctx.password = strdup("mypassword"); - * auth_ctx.url = strdup("https://myserver.tld/artifactory"); - * jfrt_auth_init(&auth_ctx); - * ``` - * - * Use your own input without STASIS's help. Purely an illustrative example. - * - * ```c - * struct JFRT_Auth auth_ctx; - * memset(auth_ctx, 0, sizeof(auth_ctx)); - * auth_ctx.user = strdup("myuser"); - * auth_ctx.password = strdup("mypassword"); - * auth_ctx.url = strdup("https://myserver.tld/artifactory"); - * ``` - * - * @param auth_ctx - * @return - */ -int jfrt_auth_init(struct JFRT_Auth *auth_ctx); - -/** - * Zero-out and apply likely defaults to a JFRT_Upload structure - * @param ctx JFRT_Upload structure - */ -void jfrt_upload_init(struct JFRT_Upload *ctx); - -#endif //STASIS_ARTIFACTORY_H
\ No newline at end of file diff --git a/include/conda.h b/include/conda.h deleted file mode 100644 index b8d0caa..0000000 --- a/include/conda.h +++ /dev/null @@ -1,234 +0,0 @@ -//! @file conda.h -#ifndef STASIS_CONDA_H -#define STASIS_CONDA_H - -#include <stdio.h> -#include <string.h> -#include <sys/utsname.h> -#include "core.h" -#include "download.h" - -#define CONDA_INSTALL_PREFIX "conda" -#define PYPI_INDEX_DEFAULT "https://pypi.org/simple" - -#define PKG_USE_PIP 0 -#define PKG_USE_CONDA 1 - -#define PKG_NOT_FOUND 0 -#define PKG_FOUND 1 - -#define PKG_INDEX_PROVIDES_ERROR_MESSAGE_OFFSET (-10) -#define PKG_E_SUCCESS (PKG_INDEX_PROVIDES_ERROR_MESSAGE_OFFSET + 0) -#define PKG_INDEX_PROVIDES_E_INTERNAL_MODE_UNKNOWN (PKG_INDEX_PROVIDES_ERROR_MESSAGE_OFFSET + 1) -#define PKG_INDEX_PROVIDES_E_INTERNAL_LOG_HANDLE (PKG_INDEX_PROVIDES_ERROR_MESSAGE_OFFSET + 2) -#define PKG_INDEX_PROVIDES_E_MANAGER_RUNTIME (PKG_INDEX_PROVIDES_ERROR_MESSAGE_OFFSET + 3) -#define PKG_INDEX_PROVIDES_E_MANAGER_SIGNALED (PKG_INDEX_PROVIDES_ERROR_MESSAGE_OFFSET + 4) -#define PKG_INDEX_PROVIDES_E_MANAGER_EXEC (PKG_INDEX_PROVIDES_ERROR_MESSAGE_OFFSET + 5) -#define PKG_INDEX_PROVIDES_FAILED(ECODE) (ECODE <= PKG_INDEX_PROVIDES_ERROR_MESSAGE_OFFSET) - -struct MicromambaInfo { - char *micromamba_prefix; //!< Path to write micromamba binary - char *conda_prefix; //!< Path to install conda base tree -}; - -/** - * Execute micromamba - * @param info MicromambaInfo data structure (must be populated before use) - * @param command printf-style formatter string - * @param ... variadic arguments - * @return exit code - */ -int micromamba(struct MicromambaInfo *info, char *command, ...); - -/** - * Execute Python - * Python interpreter is determined by PATH - * - * ```c - * if (python_exec("-c 'printf(\"Hello world\")'")) { - * fprintf(stderr, "Hello world failed\n"); - * exit(1); - * } - * ``` - * - * @param args arguments to pass to interpreter - * @return exit code from python interpreter - */ -int python_exec(const char *args); - -/** - * Execute Pip - * Pip is determined by PATH - * - * ```c - * if (pip_exec("freeze")) { - * fprintf(stderr, "pip freeze failed\n"); - * exit(1); - * } - * ``` - * - * @param args arguments to pass to Pip - * @return exit code from Pip - */ -int pip_exec(const char *args); - -/** - * Execute conda (or if possible, mamba) - * Conda/Mamba is determined by PATH - * - * ```c - * if (conda_exec("env list")) { - * fprintf(stderr, "Failed to list conda environments\n"); - * exit(1); - * } - * ``` - * - * @param args arguments to pass to Conda - * @return exit code from Conda - */ -int conda_exec(const char *args); - -/** - * Configure the runtime environment to use Conda/Mamba - * - * ```c - * if (conda_activate("/path/to/conda/installation", "base")) { - * fprintf(stderr, "Failed to activate conda's base environment\n"); - * exit(1); - * } - * ``` - * - * @param root directory where conda is installed - * @param env_name the conda environment to activate - * @return 0 on success, -1 on error - */ -int conda_activate(const char *root, const char *env_name); - -/** - * Configure the active conda installation for headless operation - */ -int conda_setup_headless(); - -/** - * Creates a Conda environment from a YAML config - * - * ```c - * if (conda_env_create_from_uri("myenv", "https://myserver.tld/environment.yml")) { - * fprintf(stderr, "Environment creation failed\n"); - * exit(1); - * } - * ``` - * - * @param name Name of new environment to create - * @param uri /path/to/environment.yml - * @param uri file:///path/to/environment.yml - * @param uri http://myserver.tld/environment.yml - * @param uri https://myserver.tld/environment.yml - * @param uri ftp://myserver.tld/environment.yml - * @return exit code from "conda" - */ -int conda_env_create_from_uri(char *name, char *uri); - -/** - * Create a Conda environment using generic package specs - * - * ```c - * // Create a basic environment without any conda packages - * if (conda_env_create("myenv", "3.11", NULL)) { - * fprintf(stderr, "Environment creation failed\n"); - * exit(1); - * } - * - * // Create a basic environment and install conda packages - * if (conda_env_create("myenv", "3.11", "hstcal fitsverify")) { - * fprintf(stderr, "Environment creation failed\n"); - * exit(1); - * } - * ``` - * - * @param name Environment name - * @param python_version Desired version of Python - * @param packages Packages to install (or NULL) - * @return exit code from "conda" - */ -int conda_env_create(char *name, char *python_version, char *packages); - -/** - * Remove a Conda environment - * - * ```c - * if (conda_env_remove("myenv")) { - * fprintf(stderr, "Unable to remove conda environment\n"); - * exit(1); - * } - * ``` - * - * @param name Environment name - * @return exit code from "conda" - */ -int conda_env_remove(char *name); - -/** - * Export a Conda environment in YAML format - * - * ```c - * if (conda_env_export("myenv", "./", "myenv.yml")) { - * fprintf(stderr, "Unable to export environment\n"); - * exit(1); - * } - * ``` - * - * @param name Environment name to export - * @param output_dir Destination directory - * @param output_filename Destination file name - * @return exit code from "conda" - */ -int conda_env_export(char *name, char *output_dir, char *output_filename); - -/** - * Run "conda index" on a local conda channel - * - * ```c - * if (conda_index("/path/to/channel")) { - * fprintf(stderr, "Unable to index requested path\n"); - * exit(1); - * } - * ``` - * - * @param path Top-level directory of conda channel - * @return exit code from "conda" - */ -int conda_index(const char *path); - -/** - * Determine whether a package index contains a package - * - * ```c - * int result = pkg_index_provides(USE_PIP, NULL, "numpy>1.26"); - * if (PKG_INDEX_PROVIDES_FAILED(result)) { - * fprintf(stderr, "failed: %s\n", pkg_index_provides_strerror(result)); - * exit(1); - * } else if (result == PKG_NOT_FOUND) { - * // package does not exist upstream - * } else { - * // package exists upstream - * } - * ``` - * - * @param mode USE_PIP - * @param mode USE_CONDA - * @param index a file system path or url pointing to a simple index or conda channel - * @param spec a pip package specification (e.g. `name==1.2.3`) - * @param spec a conda package specification (e.g. `name=1.2.3`) - * @return PKG_NOT_FOUND, if not found - * @return PKG_FOUND, if found - * @return PKG_E_INDEX_PROVIDES_{ERROR}, on error (see conda.h) - */ -int pkg_index_provides(int mode, const char *index, const char *spec); -const char *pkg_index_provides_strerror(int code); - -char *conda_get_active_environment(); - -int conda_env_exists(const char *root, const char *name); - -#endif //STASIS_CONDA_H diff --git a/include/copy.h b/include/copy.h deleted file mode 100644 index 0f92ddd..0000000 --- a/include/copy.h +++ /dev/null @@ -1,35 +0,0 @@ -//! @file copy.h -#ifndef STASIS_COPY_H - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <dirent.h> -#include <errno.h> -#include <sys/stat.h> -#include <unistd.h> -#include "core.h" - -#define CT_OWNER 1 << 1 -#define CT_PERM 1 << 2 - -/** - * Copy a single file - * - * ```c - * if (copy2("/source/path/example.txt", "/destination/path/example.txt", CT_PERM | CT_OWNER)) { - * fprintf(stderr, "Unable to copy file\n"); - * exit(1); - * } - * ``` - * - * - * @param src source file path - * @param dest destination file path - * @param op CT_OWNER (preserve ownership) - * @param op CT_PERM (preserve permission bits) - * @return 0 on success, -1 on error - */ -int copy2(const char *src, const char *dest, unsigned op); - -#endif // STASIS_COPY_H
\ No newline at end of file diff --git a/include/core.h b/include/core.h deleted file mode 100644 index 362ac8d..0000000 --- a/include/core.h +++ /dev/null @@ -1,85 +0,0 @@ -//! @file core.h -#ifndef STASIS_CORE_H -#define STASIS_CORE_H - -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <limits.h> -#include <unistd.h> -#include <time.h> -#include <sys/statvfs.h> - -#define SYSERROR(MSG, ...) do { \ - fprintf(stderr, "%s:%s:%d:%s - ", path_basename(__FILE__), __FUNCTION__, __LINE__, (errno > 0) ? strerror(errno) : "info"); \ - fprintf(stderr, MSG LINE_SEP, __VA_ARGS__); \ -} while (0) -#define STASIS_BUFSIZ 8192 -#define STASIS_NAME_MAX 255 -#define STASIS_DIRSTACK_MAX 1024 -#define STASIS_TIME_STR_MAX 128 -#define HTTP_ERROR(X) X >= 400 - -#include "config.h" -#include "core_mem.h" - -#define COE_CHECK_ABORT(COND, MSG) \ - do {\ - if (!globals.continue_on_error && COND) { \ - msg(STASIS_MSG_ERROR, MSG ": Aborting execution (--continue-on-error/-C is not enabled)\n"); \ - exit(1); \ - } \ - } while (0) - -struct STASIS_GLOBAL { - bool verbose; //!< Enable verbose output - bool always_update_base_environment; //!< Update base environment immediately after activation - bool continue_on_error; //!< Do not stop on test failures - bool conda_fresh_start; //!< Always install a new copy of Conda - bool enable_docker; //!< Enable docker image builds - bool enable_artifactory; //!< Enable artifactory uploads - bool enable_artifactory_build_info; //!< Enable build info (best disabled for pure test runs) - bool enable_artifactory_upload; //!< Enable artifactory file upload (dry-run when false) - bool enable_testing; //!< Enable package testing - bool enable_overwrite; //!< Enable release file clobbering - bool enable_rewrite_spec_stage_2; //!< Enable automatic @STR@ replacement in output files - bool enable_parallel; //!< Enable testing in parallel - long cpu_limit; //!< Limit parallel processing to n cores (default: max - 1) - long parallel_fail_fast; //!< Fail immediately on error - int pool_status_interval; //!< Report "Task is running" every n seconds - struct StrList *conda_packages; //!< Conda packages to install after initial activation - struct StrList *pip_packages; //!< Pip packages to install after initial activation - char *tmpdir; //!< Path to temporary storage directory - char *conda_install_prefix; //!< Path to install conda - char *sysconfdir; //!< Path where STASIS reads its configuration files (mission directory, etc) - struct { - char *tox_posargs; - char *conda_reactivate; - } workaround; - struct Jfrog { - char *jfrog_artifactory_base_url; - char *jfrog_artifactory_product; - char *cli_major_ver; - char *version; - char *os; - char *arch; - char *remote_filename; - char *repo; - char *url; - } jfrog; - struct EnvCtl *envctl; -}; -extern struct STASIS_GLOBAL globals; - -extern const char *VERSION; -extern const char *AUTHOR; -extern const char *BANNER; - - -/** - * Free memory allocated in global configuration structure - */ -void globals_free(); - -#endif //STASIS_CORE_H diff --git a/include/core_mem.h b/include/core_mem.h deleted file mode 100644 index bd50e9d..0000000 --- a/include/core_mem.h +++ /dev/null @@ -1,18 +0,0 @@ -//! @file core_mem.h -#ifndef STASIS_CORE_MEM_H -#define STASIS_CORE_MEM_H - -#include "environment.h" -#include "strlist.h" - -#define guard_runtime_free(X) do { if (X) { runtime_free(X); X = NULL; } } while (0) -#define guard_strlist_free(X) do { if ((*X)) { strlist_free(X); (*X) = NULL; } } while (0) -#define guard_free(X) do { if (X) { free(X); X = NULL; } } while (0) -#define GENERIC_ARRAY_FREE(ARR) do { \ - for (size_t ARR_I = 0; ARR && ARR[ARR_I] != NULL; ARR_I++) { \ - guard_free(ARR[ARR_I]); \ - } \ - guard_free(ARR); \ -} while (0) - -#endif //STASIS_CORE_MEM_H diff --git a/include/delivery.h b/include/delivery.h deleted file mode 100644 index 40ca3e6..0000000 --- a/include/delivery.h +++ /dev/null @@ -1,448 +0,0 @@ -/// @file delivery.h - -#ifndef STASIS_DELIVERY_H -#define STASIS_DELIVERY_H - -#include <string.h> -#include <stdbool.h> -#include <unistd.h> -#include <sys/utsname.h> -#include <fnmatch.h> -#include <sys/statvfs.h> -#include "core.h" -#include "copy.h" -#include "environment.h" -#include "conda.h" -#include "ini.h" -#include "artifactory.h" -#include "docker.h" -#include "wheel.h" -#include "multiprocessing.h" -#include "recipe.h" - -#define DELIVERY_PLATFORM_MAX 4 -#define DELIVERY_PLATFORM_MAXLEN 65 -#define DELIVERY_PLATFORM 0 -#define DELIVERY_PLATFORM_CONDA_SUBDIR 1 -#define DELIVERY_PLATFORM_CONDA_INSTALLER 2 -#define DELIVERY_PLATFORM_RELEASE 3 - -#define DELIVERY_REWRITE_SPEC_STAGE_1 0 -#define DELIVERY_REWRITE_SPEC_STAGE_2 1 - -#define INSTALL_PKG_CONDA 1 << 1 ///< Toggle conda package installation -#define INSTALL_PKG_CONDA_DEFERRED 1 << 2 ///< Toggle deferred conda package installation -#define INSTALL_PKG_PIP 1 << 3 ///< Toggle pip package installation -#define INSTALL_PKG_PIP_DEFERRED 1 << 4 ///< Toggle deferred package installation from source - -#define DEFER_CONDA 0 ///< Build conda packages -#define DEFER_PIP 1 ///< Build python packages - -struct Content { - unsigned type; - char *filename; - char *data; -}; - -/*! \struct Delivery - * \brief A structure describing a full delivery object - */ -struct Delivery { - /*! \struct STASIS_INI_FP - * \brief Container for INIFILE handles - */ - struct STASIS_INI_FP { - struct INIFILE *delivery; - struct INIFILE *cfg; - struct INIFILE *mission; - char *delivery_path; - char *cfg_path; - char *mission_path; - } _stasis_ini_fp; - - /*! \struct System - * \brief System information - */ - struct System { - char *arch; - ///< System CPU architecture ident - char **platform; - ///< System platform name - } system; - /*! \struct Storage - * \brief Storage paths - */ - struct Storage { - char *root; ///< Top-level storage area - char *tmpdir; ///< Temporary storage area (within root) - char *output_dir; ///< Base path to where all artifacts are stored - char *delivery_dir; ///< Delivery artifact output directory - char *cfgdump_dir; ///< Base path to where input configuration dumps are stored - char *tools_dir; ///< Tools storage - char *mission_dir; ///< Mission data storage - char *package_dir; ///< Base path to where all packages are stored - char *results_dir; ///< Base path to where test results are stored - char *meta_dir; ///< Base path to where metadata records are stored - char *conda_install_prefix; ///< Path to install Conda - char *conda_artifact_dir; ///< Base path to store compiled conda packages - char *conda_staging_dir; ///< Base path to copy compiled conda packages - char *conda_staging_url; ///< URL to access compiled conda packages - char *docker_artifact_dir; ///< Base path to store saved docker images - char *wheel_artifact_dir; ///< Base path to store compiled wheel packages (Unused) - char *wheel_staging_dir; ///< Base path to copy compiled wheel packages (Unused) - char *wheel_staging_url; ///< URL to access compiled wheel packages (Unused) - char *build_dir; ///< Base path to store source code and recipes - char *build_recipes_dir; ///< Path to store conda recipes - char *build_sources_dir; ///< Path to store source code - char *build_testing_dir; ///< Path to store test data (Unused) - char *build_docker_dir; ///< Path to store docker build script - } storage; - - /*! \struct Meta - * \brief Metadata related to the delivery - */ - struct Meta { - char *name; ///< delivery name - char *version; ///< delivery version - int rc; ///< build iteration - char *python; ///< version of python to use - char *python_compact; ///< shortened python identifier - char *based_on; ///< URL to previous final configuration - char *mission; ///< hst, jwst, roman - char *codename; ///< HST uses codenames - bool final; ///< is this a final release? - } meta; - - /*! \struct Info - * \brief Release information (name & datetime) - */ - struct Info { - char *release_name; ///< The fully combined release string - char *build_name; - char *build_number; - struct tm *time_info; ///< Delivery time structure - time_t time_now; ///< Time stamp for when STASIS execution started - char *time_str_epoch; ///< String representation of Unix epoch - } info; - - /*! \struct Conda - * \brief Conda configuration - * - * This includes lists describing packages to be delivered - */ - struct Conda { - char *installer_baseurl; ///< URL describing where Conda will be downloaded from - char *installer_name; ///< Name of installer (Miniconda3, Miniforge3, etc) - char *installer_version; ///< Version of installer - char *installer_platform; ///< Platform/OS target of installer - char *installer_arch; ///< CPU architecture target of installer - char *installer_path; ///< Absolute path of installer on-disk - char *tool_version; ///< Installed version of conda - char *tool_build_version; ///< Installed version of "build" package - struct StrList *conda_packages; ///< Conda packages to deliver - struct StrList *conda_packages_defer; ///< Conda recipes to be built for delivery - struct StrList *pip_packages; ///< Python packages to install (pip) - struct StrList *pip_packages_defer; ///< Python packages to be built for delivery - struct StrList *wheels_packages; ///< Wheel packages built for delivery - } conda; - - /*! \struct Runtime - * \brief Global runtime variables - */ - struct Runtime { - RuntimeEnv *environ; ///< Environment variables - } runtime; - - /*! \struct Test - * \brief Test information - */ - struct Test { - char *name; ///< Name of package - char *version; ///< Version of package - char *repository; ///< Git repository of package - char *script_setup; ///< Commands to execute before the main script - char *script; ///< Commands to execute - bool disable; ///< Toggle a test block - bool parallel; ///< Toggle parallel or serial execution - char *build_recipe; ///< Conda recipe to build (optional) - char *repository_info_ref; ///< Git commit hash - char *repository_info_tag; ///< Git tag (first parent) - struct StrList *repository_remove_tags; ///< Git tags to remove (to fix duplicate commit tags) - struct Runtime runtime; ///< Environment variables specific to the test context - } tests[1000]; ///< An array of tests - - struct Deploy { - struct JFRT_Auth jfrog_auth; - - struct JFrog { - struct StrList *files; - struct JFRT_Upload upload_ctx; - char *repo; - char *dest; - } jfrog[1000]; - - struct Docker { - struct DockerCapabilities capabilities; - char *image_compression; - char *dockerfile; - char *registry; - char *test_script; - struct StrList *build_args; - struct StrList *tags; - } docker; - } deploy; - - struct Rule { - struct INIFILE *_handle; - bool enable_final; ///< true=allow rc value replacement, false=keep rc value even if final release - char *release_fmt; ///< Release format string - char *build_name_fmt; ///< Build name format string - char *build_number_fmt; ///< Build number format string - struct Content content[1000]; - } rules; -}; - -/** - * Initializes a Deliver structure - * @param ctx pointer to Delivery context - * @param render_mode INI_READ_RAW or INI_READ_RENDER - * @return `0` on success - * @return Non-zero on error - */ -int delivery_init(struct Delivery *ctx, int render_mode); - -/** - * Free memory allocated by delivery_init() - * @param ctx pointer to Delivery context - */ -void delivery_free(struct Delivery *ctx); - -/** - * Print Delivery metadata - * @param ctx pointer to Delivery context - */ -void delivery_meta_show(struct Delivery *ctx); - -/** - * Print Delivery conda configuration - * @param ctx pointer to Delivery context - */ -void delivery_conda_show(struct Delivery *ctx); - -/** - * Print Delivery tests - * @param ctx pointer to Delivery context - */ -void delivery_tests_show(struct Delivery *ctx); - -/** - * Print Delivery initial runtime environment - * @param ctx pointner to Delivery context - */ -void delivery_runtime_show(struct Delivery *ctx); - -/** - * Build Conda recipes associated with the Delivery - * @param ctx pointer to Delivery context - * @return 0 on success - * @return Non-zero on error - */ -int delivery_build_recipes(struct Delivery *ctx); - -/** - * Produce a list of wheels built for the Delivery (Unused) - * @param ctx pointer to Delivery context - * @return pointer to StrList - * @return NULL on error - */ -struct StrList *delivery_build_wheels(struct Delivery *ctx); - -/** - * Copy wheel packages to artifact storage - * @param ctx pointer to Delivery context - * @return 0 on success - * @return Non-zero on error - */ -int delivery_index_wheel_artifacts(struct Delivery *ctx); - -/** - * Generate a header block that is applied to delivery artifacts - * @param ctx pointer to Delivery context - * @return header on success - * @return NULL on error - */ -char *delivery_get_release_header(struct Delivery *ctx); - -/** - * Finalizes a delivery artifact for distribution - * @param ctx poitner to Delivery context - * @param filename path to delivery artifact (Conda YAML file) - * @param stage DELIVERY_REWRITE_SPEC_STAGE_1 - Replacements for build - * @param stage DELIVERY_REWRITE_SPEC_STAGE_2 - Replacements for export - */ -void delivery_rewrite_spec(struct Delivery *ctx, char *filename, unsigned stage); - -/** - * Copy compiled wheels to artifact storage - * @param ctx pointer to Delivery context - * @return 0 on success - * @return Non-zero on error - */ -int delivery_copy_wheel_artifacts(struct Delivery *ctx); - -/** - * Copy built Conda packages to artifact storage - * @param ctx poitner to Delivery context - * @return 0 on success - * @return Non-zero on error - */ -int delivery_copy_conda_artifacts(struct Delivery *ctx); - -/** - * Retrieve Conda installer - * @param ctx pointer to Delivery context - * @param installer_url URL to installation script - */ -int delivery_get_conda_installer(struct Delivery *ctx, char *installer_url); - -/** - * Generate URL based on Delivery context - * @param ctx pointer to Delivery context - * @param result pointer to char - * @return in result - */ -void delivery_get_conda_installer_url(struct Delivery *ctx, char *result); - -/** - * Install packages based on Delivery context - * @param ctx pointer to Delivery context - * @param conda_install_dir path to install Conda - * @param env_name name of Conda environment to create - * @param type INSTALL_PKG_CONDA - * @param type INSTALL_PKG_CONDA_DEFERRED - * @param type INSTALL_PKG_PIP - * @param type INSTALL_PKG_PIP_DEFERRED - * @param manifest pointer to array of StrList (package list(s)) - */ -int delivery_install_packages(struct Delivery *ctx, char *conda_install_dir, char *env_name, int type, struct StrList *manifest[]); - -/** - * Update "conda index" on Conda artifact storage - * @param ctx pointer to Delivery context - * @return 0 on success - * @return Non-zero on error - */ -int delivery_index_conda_artifacts(struct Delivery *ctx); - -/** - * Execute Delivery test array - * @param ctx pointer to Delivery context - */ -void delivery_tests_run(struct Delivery *ctx); - -/** - * Determine which packages are to be installed directly from conda or pip, - * and which packages need to be built locally - * @param ctx pointer to Delivery context - * @param type DEFER_CONDA (filter conda packages) - * @param type DEFER_PIP (filter python packages) - */ -void delivery_defer_packages(struct Delivery *ctx, int type); - -/** - * Configure and activate a Conda installation based on Delivery context - * @param ctx pointer to Delivery context - * @param conda_install_dir path to Conda installation - */ -void delivery_conda_enable(struct Delivery *ctx, char *conda_install_dir); - -/** - * Install Conda - * @param install_script path to Conda installation script - * @param conda_install_dir path to install Conda - */ -void delivery_install_conda(char *install_script, char *conda_install_dir); - -/** - * Generate a formatted release string - * - * Formatters: - * - * - `%%n` = Delivery Name - * - `%%c` = Delivery Codename (HST mission, only) - * - `%%m` = Mission - * - `%%R` = Delivery Revision number (or "final") - * - `%%r` = Delivery Revision number - * - `%%v` = Delivery Version - * - `%%P` = Python version (i.e. 3.9.1) - * - `%%p` = Compact Python version (i.e. 3.9.1 -> 39) - * - `%%a` = System architecture name - * - `%%o` = System platform name - * - `%%t` = Delivery timestamp (Unix Epoch) - * - * @param ctx pointer to Delivery context - * @param dest NULL pointer to string, or initialized string - * @param fmt release format string - * @return 0 on success, -1 on error - */ -int delivery_format_str(struct Delivery *ctx, char **dest, const char *fmt); - -// helper function -int delivery_gather_tool_versions(struct Delivery *ctx); - -// helper function -int delivery_init_tmpdir(struct Delivery *ctx); - -void delivery_init_dirs_stage1(struct Delivery *ctx); - -void delivery_init_dirs_stage2(struct Delivery *ctx); - -int delivery_init_platform(struct Delivery *ctx); - -int delivery_init_artifactory(struct Delivery *ctx); - -int delivery_artifact_upload(struct Delivery *ctx); - -int delivery_mission_render_files(struct Delivery *ctx); - -int delivery_docker(struct Delivery *ctx); - -int delivery_fixup_test_results(struct Delivery *ctx); - -int bootstrap_build_info(struct Delivery *ctx); - -int delivery_dump_metadata(struct Delivery *ctx); - -int populate_info(struct Delivery *ctx); - -int populate_delivery_cfg(struct Delivery *ctx, int render_mode); - -int populate_delivery_ini(struct Delivery *ctx, int render_mode); - -int populate_mission_ini(struct Delivery **ctx, int render_mode); - -void validate_delivery_ini(struct INIFILE *ini); - -int filter_repo_tags(char *repo, struct StrList *patterns); - -#define DELIVERY_NOT_FOUND 0 -#define DELIVERY_FOUND 1 -/** - * Determine whether a release on-disk matches the release name in use - * @param ctx Delivery context - * @return 0=no, 1=yes - */ -int delivery_exists(struct Delivery *ctx); - -int delivery_overlay_packages_from_env(struct Delivery *ctx, const char *env_name); - -/** - * Retrieve remote deliveries associated with the current version series - * @param ctx Delivery context - * @return -1 on error - * @return 1 on failure - * @return 0 on success - */ -int delivery_series_sync(struct Delivery *ctx); - -#endif //STASIS_DELIVERY_H diff --git a/include/docker.h b/include/docker.h deleted file mode 100644 index 7585d86..0000000 --- a/include/docker.h +++ /dev/null @@ -1,92 +0,0 @@ -//! @file docker.h -#ifndef STASIS_DOCKER_H -#define STASIS_DOCKER_H - -#include "core.h" - -//! Flag to squelch output from docker_exec() -#define STASIS_DOCKER_QUIET 1 << 1 - -//! Flag for older style docker build -#define STASIS_DOCKER_BUILD 1 << 1 -//! Flag for docker buildx -#define STASIS_DOCKER_BUILD_X 1 << 2 - -//! Compress "docker save"ed images with a compression program -#define STASIS_DOCKER_IMAGE_COMPRESSION "zstd" - -struct DockerCapabilities { - int podman; //!< Is "docker" really podman? - int build; //!< Is a build plugin available? - int available; //!< Is a "docker" program available? - int usable; //!< Is docker in a usable state for the current user? -}; - -/** - * Determine the state of docker on the system - * - * ```c - * struct DockerCapabilities docker_is; - * if (!docker_capable(&docker_is)) { - * fprintf(stderr, "%s is %savailable, and %susable\n", - * docker_is.podman ? "Podman" : "Docker", - * docker_is.available ? "" : "not ", - * docker_is.usable ? "" : "not "); - * exit(1); - * } - * ``` - * - * @param result DockerCapabilities struct - * @return 1 on success, 0 on error - */ -int docker_capable(struct DockerCapabilities *result); - -/** - * Execute a docker command - * - * Use the `STASIS_DOCKER_QUIET` flag to suppress all output from stdout and stderr. - * - * ```c - * if (docker_exec("run --rm -t ubuntu:latest /bin/bash -c 'echo Hello world'", 0)) { - * fprintf(stderr, "Docker hello world failed\n"); - * exit(1); - * } - * ``` - * - * @param args arguments to pass to docker - * @param flags - * @return exit code from "docker" - */ -int docker_exec(const char *args, unsigned flags); - -/** - * Build a docker image - * - * ```c - * struct DockerCapabilities docker_is; - * docker_capable(&docker_is); - * - * if (docker_is.usable) { - * printf("Building docker image\n"); - * if (docker_build("path/to/Dockerfile/dir")) { - * fprintf("Docker build failed\n"); - * exit(1); - * } - * } else { - * fprintf(stderr, "No usable docker installation available\n"); - * } - * ``` - * - * @param dirpath - * @param args - * @param engine - * @return - */ -int docker_build(const char *dirpath, const char *args, int engine); -int docker_script(const char *image, char *data, unsigned flags); -int docker_save(const char *image, const char *destdir, const char *compression_program); -void docker_sanitize_tag(char *str); -int docker_validate_compression_program(char *prog); - - -#endif //STASIS_DOCKER_H diff --git a/include/download.h b/include/download.h deleted file mode 100644 index 0b6311e..0000000 --- a/include/download.h +++ /dev/null @@ -1,12 +0,0 @@ -//! @file download.h -#ifndef STASIS_DOWNLOAD_H -#define STASIS_DOWNLOAD_H - -#include <stdlib.h> -#include <string.h> -#include <curl/curl.h> - -size_t download_writer(void *fp, size_t size, size_t nmemb, void *stream); -long download(char *url, const char *filename, char **errmsg); - -#endif //STASIS_DOWNLOAD_H diff --git a/include/envctl.h b/include/envctl.h deleted file mode 100644 index 659cae3..0000000 --- a/include/envctl.h +++ /dev/null @@ -1,39 +0,0 @@ -//! @file envctl.h -#ifndef STASIS_ENVCTL_H -#define STASIS_ENVCTL_H - -#include <stdlib.h> -#include "core.h" - -#define STASIS_ENVCTL_PASSTHRU 0 -#define STASIS_ENVCTL_REQUIRED 1 << 1 -#define STASIS_ENVCTL_REDACT 1 << 2 -#define STASIS_ENVCTL_DEFAULT_ALLOC 100 - -#define STASIS_ENVCTL_RET_FAIL (-1) -#define STASIS_ENVCTL_RET_SUCCESS 1 -#define STASIS_ENVCTL_RET_IGNORE 2 -typedef int (envctl_except_fn)(const void *, const void *); - -struct EnvCtl_Item { - unsigned flags; //<! One or more STASIS_ENVCTL_* flags - const char *name; //<! Environment variable name - envctl_except_fn *callback; -}; - -struct EnvCtl { - size_t num_alloc; - size_t num_used; - struct EnvCtl_Item **item; -}; - -struct EnvCtl *envctl_init(); -int envctl_register(struct EnvCtl **envctl, unsigned flags, envctl_except_fn *callback, const char *name); -unsigned envctl_get_flags(const struct EnvCtl *envctl, const char *name); -unsigned envctl_check_required(unsigned flags); -unsigned envctl_check_redact(unsigned flags); -int envctl_check_present(const struct EnvCtl_Item *item, const char *name); -void envctl_do_required(const struct EnvCtl *envctl, int verbose); -void envctl_free(struct EnvCtl **envctl); - -#endif // STASIS_ENVCTL_H
\ No newline at end of file diff --git a/include/environment.h b/include/environment.h deleted file mode 100644 index 34bc600..0000000 --- a/include/environment.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file environment.h - */ -#ifndef STASIS_ENVIRONMENT_H -#define STASIS_ENVIRONMENT_H - -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> -#include "environment.h" - -typedef struct StrList RuntimeEnv; - -ssize_t runtime_contains(RuntimeEnv *env, const char *key); -RuntimeEnv *runtime_copy(char **env); -int runtime_replace(RuntimeEnv **dest, char **src); -char *runtime_get(RuntimeEnv *env, const char *key); -void runtime_set(RuntimeEnv *env, const char *_key, char *_value); -char *runtime_expand_var(RuntimeEnv *env, char *input); -void runtime_export(RuntimeEnv *env, char **keys); -void runtime_apply(RuntimeEnv *env); -void runtime_free(RuntimeEnv *env); -#endif //STASIS_ENVIRONMENT_H diff --git a/include/github.h b/include/github.h deleted file mode 100644 index f9b47a3..0000000 --- a/include/github.h +++ /dev/null @@ -1,11 +0,0 @@ -//! @file github.h -#ifndef STASIS_GITHUB_H -#define STASIS_GITHUB_H - -#include <curl/curl.h> - -#define STASIS_GITHUB_API_VERSION "2022-11-28" - -int get_github_release_notes(const char *api_token, const char *repo, const char *tag, const char *target_commitish, char **output); - -#endif //STASIS_GITHUB_H
\ No newline at end of file diff --git a/include/ini.h b/include/ini.h deleted file mode 100644 index 557f157..0000000 --- a/include/ini.h +++ /dev/null @@ -1,260 +0,0 @@ -/// @file ini.h - -#ifndef STASIS_INI_H -#define STASIS_INI_H -#include <stdio.h> -#include <stddef.h> -#include <stdbool.h> -#include "template.h" - -#define INI_WRITE_RAW 0 ///< Dump INI data. Contents are not modified. -#define INI_WRITE_PRESERVE 1 ///< Dump INI data. Template strings are -#define INI_READ_RAW 0 ///< Dump INI data. Contents are not modified. -#define INI_READ_RENDER 1 ///< Dump INI data. Template strings are -#define INI_SETVAL_APPEND 0 -#define INI_SETVAL_REPLACE 1 -#define INI_SEARCH_EXACT 0 -#define INI_SEARCH_BEGINS 1 -#define INI_SEARCH_SUBSTR 2 - ///< expanded to preserve runtime state. - -#define INIVAL_TYPE_CHAR 1 ///< Byte -#define INIVAL_TYPE_UCHAR 2 ///< Unsigned byte -#define INIVAL_TYPE_SHORT 3 ///< Short integer -#define INIVAL_TYPE_USHORT 4 ///< Unsigned short integer -#define INIVAL_TYPE_INT 5 ///< Integer -#define INIVAL_TYPE_UINT 6 ///< Unsigned integer -#define INIVAL_TYPE_LONG 7 ///< Long integer -#define INIVAL_TYPE_ULONG 8 ///< Unsigned long integer -#define INIVAL_TYPE_LLONG 9 ///< Long long integer -#define INIVAL_TYPE_ULLONG 10 ///< Unsigned long long integer -#define INIVAL_TYPE_DOUBLE 11 ///< Double precision float -#define INIVAL_TYPE_FLOAT 12 ///< Single precision float -#define INIVAL_TYPE_STR 13 ///< String -#define INIVAL_TYPE_STR_ARRAY 14 ///< String Array -#define INIVAL_TYPE_BOOL 15 ///< Boolean - -#define INIVAL_TO_LIST 1 << 1 - -/*! \union INIVal - * \brief Consolidate possible value types - */ -union INIVal { - char as_char; ///< Byte - unsigned char as_uchar; ///< Unsigned byte - short as_short; ///< Short integer - unsigned short as_ushort; ///< Unsigned short integer - int as_int; ///< Integer - unsigned as_uint; ///< Unsigned integer - long as_long; ///< Long integer - unsigned long as_ulong; ///< Unsigned long integer - long long as_llong; ///< Long long integer - unsigned long long as_ullong; ///< Unsigned long long integer - double as_double; ///< Double precision float - float as_float; ///< Single precision float - char *as_char_p; ///< String - char **as_char_array_p; ///< String Array - bool as_bool; ///< Boolean -}; - - -/*! \struct INIData - * \brief A structure to describe an INI data record - */ -struct INIData { - char *key; ///< INI variable name - char *value; ///< INI variable value - unsigned type_hint; -}; - -/*! \struct INISection - * \brief A structure to describe an INI section - */ -struct INISection { - size_t data_count; ///< Total INIData records - char *key; ///< INI section name - struct INIData **data; ///< Array of INIData records -}; - -/*! \struct INIFILE - * \brief A structure to describe an INI configuration file - */ -struct INIFILE { - size_t section_count; ///< Total INISection records - struct INISection **section; ///< Array of INISection records -}; - -/** - * Open and parse and INI configuration file - * - * ~~~.c - * #include "ini.h" - * int main(int argc, char *argv[]) { - * const char *filename = "example.ini" - * struct INIFILE *ini; - * ini = ini_open(filename); - * if (!ini) { - * perror(filename); - * exit(1); - * } - * } - * ~~~ - * - * @param filename path to INI file - * @return pointer to INIFILE - */ -struct INIFILE *ini_open(const char *filename); - -/** - * - * @param ini - * @param value - * @return - */ -struct INISection *ini_section_search(struct INIFILE **ini, unsigned mode, const char *value); - -/** - * - * @param ini - * @param key - * @return - */ -int ini_section_create(struct INIFILE **ini, char *key); - -/** - * - * @param ini - * @param section - * @param key - * @return - */ -int ini_has_key(struct INIFILE *ini, const char *section, const char *key); - -/** - * Assign value to a section key - * @param ini - * @param type INI_SETVAL_APPEND or INI_SETVAL_REPLACE - * @param section_name - * @param key - * @param value - * @return - */ -int ini_setval(struct INIFILE **ini, unsigned type, char *section_name, char *key, char *value); - -/** - * Retrieve all data records in an INI section - * - * `example.ini` - * ~~~.ini - * [example] - * key_1 = a string - * key_2 = 100 - * ~~~ - * - * `example.c` - * ~~~.c - * #include "ini.h" - * int main(int argc, char *argv[]) { - * const char *filename = "example.ini" - * struct INIData *data; - * struct INIFILE *ini; - * ini = ini_open(filename); - * if (!ini) { - * perror(filename); - * exit(1); - * } - * // Read all records in "example" section - * for (size_t i = 0; ((data = ini_getall(&ini, "example") != NULL); i++) { - * printf("key=%s, value=%s\n", data->key, data->value); - * } - * } - * ~~~ - * - * @param ini pointer to INIFILE - * @param section_name to read - * @return pointer to INIData - */ -struct INIData *ini_getall(struct INIFILE *ini, char *section_name); - -/** - * Retrieve a single record from a section key - * - * `example.ini` - * ~~~.ini - * [example] - * key_1 = a string - * key_2 = 100 - * ~~~ - * - * `example.c` - * ~~~.c - * #include "ini.h" - * int main(int argc, char *argv[]) { - * const char *filename = "example.ini" - * union INIVal *data; - * struct INIFILE *ini; - * ini = ini_open(filename); - * if (!ini) { - * perror(filename); - * exit(1); - * } - * data = ini_getval(&ini, "example", "key_1", INIVAL_TYPE_STR); - * puts(data.as_char_p); - * data = ini_getval(&ini, "example", "key_2", INIVAL_TYPE_INT); - * printf("%d\n", data.as_int); - * } - * ~~~ - * - * @param ini pointer to INIFILE - * @param section_name to read - * @param key to return - * @param type INIVAL_TYPE_INT - * @param type INIVAL_TYPE_UINT - * @param type INIVAL_TYPE_LONG - * @param type INIVAL_TYPE_ULONG - * @param type INIVAL_TYPE_LLONG - * @param type INIVAL_TYPE_ULLONG - * @param type INIVAL_TYPE_DOUBLE - * @param type INIVAL_TYPE_FLOAT - * @param type INIVAL_TYPE_STR - * @param type INIVAL_TYPE_STR_ARRAY - * @param type INIVAL_TYPE_BOOL - * @param result pointer to INIVal - * @return 0 on success - * @return Non-zero on error - */ -int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, int flags, union INIVal *result); - -/** - * Write INIFILE sections and data to a file stream - * @param ini pointer to INIFILE - * @param file pointer to address of file stream - * @return 0 on success, -1 on error - */ -int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode); - -/** - * Free memory allocated by ini_open() - * @param ini - */ -void ini_free(struct INIFILE **ini); - -int ini_getval_int(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -unsigned int ini_getval_uint(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -long ini_getval_long(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -unsigned long ini_getval_ulong(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -long long ini_getval_llong(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -unsigned long long ini_getval_ullong(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -float ini_getval_float(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -double ini_getval_double(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -bool ini_getval_bool(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -short ini_getval_short(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -unsigned short ini_getval_ushort(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -char ini_getval_char(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -unsigned char ini_getval_uchar(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -char *ini_getval_char_p(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -char *ini_getval_str(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -char *ini_getval_char_array_p(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -char *ini_getval_str_array(struct INIFILE *ini, char *section_name, char *key, int flags, int *state); -struct StrList *ini_getval_strlist(struct INIFILE *ini, char *section_name, char *key, char *tok, int flags, int *state); -#endif //STASIS_INI_H diff --git a/include/junitxml.h b/include/junitxml.h deleted file mode 100644 index 777ee27..0000000 --- a/include/junitxml.h +++ /dev/null @@ -1,135 +0,0 @@ -/// @file junitxml.h -#ifndef STASIS_JUNITXML_H -#define STASIS_JUNITXML_H -#include <libxml/xmlreader.h> - -#define JUNIT_RESULT_STATE_NONE 0 -#define JUNIT_RESULT_STATE_FAILURE 1 -#define JUNIT_RESULT_STATE_SKIPPED 2 -#define JUNIT_RESULT_STATE_ERROR 3 - -/** - * Represents a failed test case - */ -struct JUNIT_Failure { - /// Error text - char *message; -}; - -/** - * Represents a test case error - */ -struct JUNIT_Error { - /// Error text - char *message; -}; - -/** - * Represents a skipped test case - */ -struct JUNIT_Skipped { - /// Type of skip event - char *type; - /// Reason text - char *message; -}; - -/** - * Represents a junit test case - */ -struct JUNIT_Testcase { - /// Class name - char *classname; - /// Name of test - char *name; - /// Test duration in fractional seconds - float time; - /// Standard output message - char *message; - /// Result type - int tc_result_state_type; - /// Type container for result (there can only be one) - union tc_state_ptr { - struct JUNIT_Failure *failure; - struct JUNIT_Skipped *skipped; - struct JUNIT_Error *error; - } result_state; ///< Result data -}; - -/** - * Represents a junit test suite - */ -struct JUNIT_Testsuite { - /// Test suite name - char *name; - /// Total number of test terminated due to an error - int errors; - /// Total number of failed tests - int failures; - /// Total number of skipped tests - int skipped; - /// Total number of tests - int tests; - /// Total duration in fractional seconds - float time; - /// Timestamp - char *timestamp; - /// Test runner host name - char *hostname; - /// Array of test cases - struct JUNIT_Testcase **testcase; - /// Total number of test cases in use - size_t _tc_inuse; - /// Total number of test cases allocated - size_t _tc_alloc; -}; - -/** - * Extract information from a junit XML file - * - * ~~~{.c} - * struct JUNIT_Testsuite *testsuite; - * const char *filename = "/path/to/result.xml"; - * - * testsuite = junitxml_testsuite_read(filename); - * if (testsuite) { - * // Did any test cases fail? - * if (testsuite->failures) { - * printf("Test suite '%s' has %d failure(s)\n", testsuite->name, testsuite->failures - * // Scan test cases for failure data - * for (size_t i = 0; i < testsuite->_tc_inuse; i++) { - * // Check result state (one of) - * // JUNIT_RESULT_STATE_FAILURE - * // JUNIT_RESULT_STATE_ERROR - * // JUNIT_RESULT_STATE_SKIPPED - * struct JUNIT_Testcase *testcase = testsuite->testcase[i]; - * if (testcase->tc_result_state_type) { - * if (testcase->tc_result_state_type == JUNIT_RESULT_STATE_FAILURE) { - * // Display information from failed test case - * printf("[FAILED] %s::%s\nOutput:\n%s\n", - * testcase->classname, - * testcase->name, - * testcase->result_state.failure->message); - * } - * } - * } - * } - * // Release test suite resources - * junitxml_testsuite_free(&testsuite); - * } else { - * // handle error - * } - * ~~~ - * - * @param filename path to junit XML file - * @return pointer to JUNIT_Testsuite - */ -struct JUNIT_Testsuite *junitxml_testsuite_read(const char *filename); - -/** - * Free memory allocated by junitxml_testsuite_read - * @param testsuite pointer to JUNIT_Testsuite - */ -void junitxml_testsuite_free(struct JUNIT_Testsuite **testsuite); - -#endif //STASIS_JUNITXML_H diff --git a/include/multiprocessing.h b/include/multiprocessing.h deleted file mode 100644 index ec7c1ad..0000000 --- a/include/multiprocessing.h +++ /dev/null @@ -1,134 +0,0 @@ -/// @file multiprocessing.h -#ifndef STASIS_MULTIPROCESSING_H -#define STASIS_MULTIPROCESSING_H - -#include "core.h" -#include <signal.h> -#include <sys/wait.h> -#include <semaphore.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <sys/stat.h> - -struct MultiProcessingTask { - pid_t pid; ///< Program PID - pid_t parent_pid; ///< Program PID (parent process) - int status; ///< Child process exit status - int signaled_by; ///< Last signal received, if any - time_t _now; ///< Current time - time_t _seconds; ///< Time elapsed (used by MultiprocessingPool.status_interval) - char ident[255]; ///< Identity of the pool task - char *cmd; ///< Shell command(s) to be executed - size_t cmd_len; ///< Length of command string (for mmap/munmap) - char working_dir[PATH_MAX]; ///< Path to directory `cmd` should be executed in - char log_file[PATH_MAX]; ///< Full path to stdout/stderr log file - char parent_script[PATH_MAX]; ///< Path to temporary script executing the task - struct { - struct timespec t_start; - struct timespec t_stop; - } time_data; ///< Wall-time counters -}; - -struct MultiProcessingPool { - struct MultiProcessingTask *task; ///< Array of tasks to execute - size_t num_used; ///< Number of tasks populated in the task array - size_t num_alloc; ///< Number of tasks allocated by the task array - char ident[255]; ///< Identity of task pool - char log_root[PATH_MAX]; ///< Base directory to store stderr/stdout log files - int status_interval; ///< Report a pooled task is "running" every n seconds -}; - -/// A multiprocessing task's initial state (i.e. "FAIL") -#define MP_POOL_TASK_STATUS_INITIAL (-1) - -/// Maximum number of multiprocessing tasks STASIS can execute -#define MP_POOL_TASK_MAX 1000 - -/// Value signifies a process is unused or finished executing -#define MP_POOL_PID_UNUSED 0 - -/// Option flags for mp_pool_join() -#define MP_POOL_FAIL_FAST 1 << 1 - -/** - * Create a multiprocessing pool - * - * ```c - * #include "multiprocessing.h" - * #include "utils.h" // for get_cpu_count() - * - * int main(int argc, char *argv[]) { - * struct MultiProcessingPool *mp; - * mp = mp_pool_init("mypool", "/tmp/mypool_logs"); - * if (mp) { - * char *commands[] = { - * "/bin/echo hello world", - * "/bin/echo world hello", - * NULL - * } - * for (size_t i = 0; commands[i] != NULL); i++) { - * struct MultiProcessingTask *task; - * char task_name[100]; - * - * sprintf(task_name, "mytask%zu", i); - * task = mp_task(mp, task_name, commands[i]); - * if (!task) { - * // handle task creation error - * } - * } - * if (mp_pool_join(mp, get_cpu_count(), MP_POOL_FAIL_FAST)) { - * // handle pool execution error - * } - * mp_pool_free(&mp); - * } else { - * // handle pool initialization error - * } - * } - * ``` - * - * @param ident a name to identify the pool - * @param log_root the path to store program output - * @return pointer to initialized MultiProcessingPool - * @return NULL on error - */ -struct MultiProcessingPool *mp_pool_init(const char *ident, const char *log_root); - -/** - * Create a multiprocessing pool task - * - * @param pool a pointer to MultiProcessingPool - * @param ident a name to identify the task - * @param cmd a command to execute - * @return pointer to MultiProcessingTask structure - * @return NULL on error - */ -struct MultiProcessingTask *mp_pool_task(struct MultiProcessingPool *pool, const char *ident, char *working_dir, char *cmd); - -/** - * Execute all tasks in a pool - * - * @param pool a pointer to MultiProcessingPool - * @param jobs the number of processes to spawn at once (for serial execution use `1`) - * @param flags option to be OR'd (MP_POOL_FAIL_FAST) - * @return 0 on success - * @return >0 on failure - * @return <0 on error - */ -int mp_pool_join(struct MultiProcessingPool *pool, size_t jobs, size_t flags); - -/** - * Show summary of pool tasks - * - * @param pool a pointer to MultiProcessingPool - */ -void mp_pool_show_summary(struct MultiProcessingPool *pool); - -/** - * Release resources allocated by mp_pool_init() - * - * @param a pointer to MultiProcessingPool - */ -void mp_pool_free(struct MultiProcessingPool **pool); - - -#endif //STASIS_MULTIPROCESSING_H diff --git a/include/os_darwin.h b/include/os_darwin.h deleted file mode 100644 index e8513ff..0000000 --- a/include/os_darwin.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef STASIS_OS_DARWIN_H -#define STASIS_OS_DARWIN_H - -#include <sys/mount.h> - -#ifndef __DARWIN_64_BIT_INO_T -#define statvfs statfs - -#ifndef ST_RDONLY -#define ST_RDONLY MNT_RDONLY -#endif - -#define ST_NOEXEC MNT_NOEXEC -#define f_flag f_flags -#endif // __DARWIN_64_BIT_INO_T - -#include <limits.h> - -#ifndef PATH_MAX -#include <sys/syslimits.h> -#endif - -extern char **environ; -#define __environ environ - -#endif diff --git a/include/os_linux.h b/include/os_linux.h deleted file mode 100644 index d418090..0000000 --- a/include/os_linux.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef STASIS_OS_LINUX_H -#define STASIS_OS_LINUX_H - -#include <limits.h> - -#ifndef PATH_MAX -#include <linux/limits.h> -#endif - -#endif diff --git a/include/package.h b/include/package.h deleted file mode 100644 index eff1874..0000000 --- a/include/package.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef STASIS_PACKAGE_H -#define STASIS_PACKAGE_H - -struct Package { - struct { - const char *name; - const char *version_spec; - const char *version; - } meta; - struct { - const char *uri; - unsigned handler; - } source; - struct { - struct Test *test; - size_t pass; - size_t fail; - size_t skip; - }; - unsigned state; -}; - -struct Package *stasis_package_init(void); -void stasis_package_set_name(struct Package *pkg, const char *name); -void stasis_package_set_version(struct Package *pkg, const char *version); -void stasis_package_set_version_spec(struct Package *pkg, const char *version_spec); -void stasis_package_set_uri(struct Package *pkg, const char *uri); -void stasis_package_set_handler(struct Package *pkg, unsigned handler); - -#endif //STASIS_PACKAGE_H diff --git a/include/recipe.h b/include/recipe.h deleted file mode 100644 index 4dea248..0000000 --- a/include/recipe.h +++ /dev/null @@ -1,72 +0,0 @@ -//! @file recipe.h -#ifndef STASIS_RECIPE_H -#define STASIS_RECIPE_H - -#include "str.h" -#include "utils.h" - -//! Unable to determine recipe repo type -#define RECIPE_TYPE_UNKNOWN 0 -//! Recipe repo is from conda-forge -#define RECIPE_TYPE_CONDA_FORGE 1 -//! Recipe repo is from astroconda -#define RECIPE_TYPE_ASTROCONDA 2 -//! Recipe repo provides the required build configurations but doesn't match conda-forge or astroconda's signature -#define RECIPE_TYPE_GENERIC 3 - -/** - * Download a Conda package recipe - * - * ```c - * char *recipe = NULL; - * - * if (recipe_clone("base/dir", "https://github.com/example/repo", "branch", &recipe)) { - * fprintf(stderr, "Failed to clone conda recipe\n"); - * exit(1); - * } else { - * chdir(recipe); - * } - * ``` - * - * @param recipe_dir path to store repository - * @param url remote address of git repository - * @param gitref branch/tag/commit - * @param result absolute path to downloaded repository - * @return exit code from "git", -1 on error - */ -int recipe_clone(char *recipe_dir, char *url, char *gitref, char **result); - -/** - * Determine the layout/type of repository path - * - * ```c - * if (recipe_clone("base/dir", "https://github.com/example/repo", "branch", &recipe)) { - * fprintf(stderr, "Failed to clone conda recipe\n"); - * exit(1); - * } - * - * int recipe_type; - * recipe_type = recipe_get_type(recipe); - * switch (recipe_type) { - * case RECIPE_TYPE_CONDA_FORGE: - * // do something specific for conda-forge directory structure - * break; - * case RECIPE_TYPE_ASTROCONDA: - * // do something specific for astroconda directory structure - * break; - * case RECIPE_TYPE_GENERIC: - * // do something specific for a directory containing a meta.yaml config - * break; - * case RECIPE_TYPE_UNKNOWN: - * default: - * // the structure is foreign or the path doesn't contain a conda recipe - * break; - * } - * ``` - * - * @param repopath path to git repository containing conda recipe(s) - * @return One of RECIPE_TYPE_UNKNOWN, RECIPE_TYPE_CONDA_FORGE, RECIPE_TYPE_ASTROCONDA, RECIPE_TYPE_GENERIC - */ -int recipe_get_type(char *repopath); - -#endif //STASIS_RECIPE_H diff --git a/include/relocation.h b/include/relocation.h deleted file mode 100644 index 9a1f0f4..0000000 --- a/include/relocation.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @file relocation.h - */ -#ifndef STASIS_RELOCATION_H -#define STASIS_RELOCATION_H - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#if defined(STASIS_OS_DARWIN) -#include <limits.h> -# else -#include <linux/limits.h> -#endif -#include <unistd.h> - -#define REPLACE_TRUNCATE_AFTER_MATCH 1 - -int replace_text(char *original, const char *target, const char *replacement, unsigned flags); -int file_replace_text(const char* filename, const char* target, const char* replacement, unsigned flags); - -#endif //STASIS_RELOCATION_H diff --git a/include/rules.h b/include/rules.h deleted file mode 100644 index 666d331..0000000 --- a/include/rules.h +++ /dev/null @@ -1,11 +0,0 @@ -// -// Created by jhunk on 12/18/23. -// - -#ifndef STASIS_RULES_H -#define STASIS_RULES_H - -#include "core.h" - - -#endif //STASIS_RULES_H diff --git a/include/str.h b/include/str.h deleted file mode 100644 index bb96db0..0000000 --- a/include/str.h +++ /dev/null @@ -1,313 +0,0 @@ -/** - * @file str.h - */ -#ifndef STASIS_STR_H -#define STASIS_STR_H - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <ctype.h> -#include "relocation.h" -#include "core.h" - -#define STASIS_SORT_ALPHA 1 << 0 -#define STASIS_SORT_NUMERIC 1 << 1 -#define STASIS_SORT_LEN_ASCENDING 1 << 2 -#define STASIS_SORT_LEN_DESCENDING 1 << 3 - -/** - * Determine how many times the character `ch` appears in `sptr` string - * @param sptr string to scan - * @param ch character to find - * @return count of characters found - */ -int num_chars(const char *sptr, int ch); - -/** - * Scan for `pattern` string at the beginning of `sptr` - * - * @param sptr string to scan - * @param pattern string to search for - * @return 1 = found, 0 = not found / error - */ -int startswith(const char *sptr, const char *pattern); - -/** - * Scan for `pattern` string at the end of `sptr` - * - * @param sptr string to scan - * @param pattern string to search for - * @return 1 = found, 0 = not found / error - */ -int endswith(const char *sptr, const char *pattern); - -/** - * Deletes any characters matching `chars` from `sptr` string - * - * @param sptr string to be modified in-place - * @param chars a string containing characters (e.g. " \n" would delete whitespace and line feeds) - */ -void strchrdel(char *sptr, const char *chars); - -/** - * Split a string by every delimiter in `delim` string. - * - * Callee should free memory using `GENERIC_ARRAY_FREE()` - * - * @param sptr string to split - * @param delim characters to split on - * @return success=parts of string, failure=NULL - */ -char** split(char *sptr, const char* delim, size_t max); - -/** - * Create new a string from an array of strings - * - * ~~~{.c} - * char *array[] = { - * "this", - * "is", - * "a", - * "test", - * NULL, - * } - * - * char *test = join(array, " "); // "this is a test" - * char *test2 = join(array, "_"); // "this_is_a_test" - * char *test3 = join(array, ", "); // "this, is, a, test" - * - * free(test); - * free(test2); - * free(test3); - * ~~~ - * - * @param arr - * @param separator characters to insert between elements in string - * @return new joined string - */ -char *join(char **arr, const char *separator); - -/** - * Join two or more strings by a `separator` string - * @param separator - * @param ... - * @return string - */ -char *join_ex(char *separator, ...); - -/** - * Extract the string encapsulated by characters listed in `delims` - * - * ~~~{.c} - * char *str = "this is [some data] in a string"; - * char *data = substring_between(string, "[]"); - * // data = "some data"; - * ~~~ - * - * @param sptr string to parse - * @param delims two characters surrounding a string - * @return success=text between delimiters, failure=NULL - */ -char *substring_between(char *sptr, const char *delims); - -/** - * Sort an array of strings - * @param arr a NULL terminated array of strings - * @param sort_mode - * - STASIS_SORT_LEN_DESCENDING - * - STASIS_SORT_LEN_ASCENDING - * - STASIS_SORT_ALPHA - * - STASIS_SORT_NUMERIC - */ -void strsort(char **arr, unsigned int sort_mode); - -/** - * Determine whether the input character is a relational operator - * Note: `~` is non-standard - * @param ch - * @return 0=no, 1=yes - */ -int isrelational(char ch); - -/** - * Print characters in `s`, `len` times - * @param s - * @param len - */ -void print_banner(const char *s, int len); - -/** - * Search for string in an array of strings - * @param arr array of strings - * @param str string to search for - * @return yes=`pointer to string`, no=`NULL`, failure=`NULL` - */ -char *strstr_array(char **arr, const char *str); - -/** - * Remove duplicate strings from an array of strings - * @param arr - * @return success=array of unique strings, failure=NULL - */ -char **strdeldup(char **arr); - -/** Remove leading whitespace from a string - * - * ~~~{.c} - * char input[100]; - * - * strcpy(input, " I had leading spaces"); - * lstrip(input); - * // input is now "I had leading spaces" - * ~~~ - * @param sptr pointer to string - * @return pointer to first non-whitespace character in string - */ -char *lstrip(char *sptr); - -/** - * Strips trailing whitespace from a given string - * - * ~~~{.c} - * char input[100]; - * - * strcpy(input, "I had trailing spaces "); - * strip(input); - * // input is now "I had trailing spaces" - * ~~~ - * - * @param sptr input string - * @return truncated string - */ -char *strip(char *sptr); - -/** - * Check if a given string is "visibly" empty - * - * ~~~{.c} - * char visibly[100]; - * - * strcpy(visibly, "\t \t\n"); - * if (isempty(visibly)) { - * printf("string is 'empty'\n"); - * } else { - * printf("string is not 'empty'\n"); - * } - * ~~~ - * - * @param sptr pointer to string - * @return 0=not empty, 1=empty - */ -int isempty(char *sptr); - -/** - * Determine if a string is encapsulated by quotes - * @param sptr pointer to string - * @return 0=not quoted, 1=quoted - */ -int isquoted(char *sptr); - -/** - * Collapse whitespace in `s`. The string is modified in place. - * @param s - * @return pointer to `s` - */ -char *normalize_space(char *s); - -/** - * Duplicate an array of strings - * - * ~~~{.c} - * char **array_orig = calloc(10, sizeof(*orig)); - * orig[0] = strdup("one"); - * orig[1] = strdup("two"); - * orig[2] = strdup("three"); - * // ... - * char **array_orig_copy = strdup_array(orig); - * - * for (size_t i = 0; array_orig_copy[i] != NULL; i++) { - * printf("array_orig[%zu] = '%s'\narray_orig_copy[%zu] = '%s'\n\n", - * i, array_orig[i], - * i, array_orig_copy[i]); - * free(array_orig_copy[i]); - * free(array_orig[i]); - * } - * free(array_orig_copy); - * free(array_orig); - * - * ~~~ - * - * @param array - * @return - */ -char **strdup_array(char **array); - -/** - * Compare an array of strings - * - * ~~~{.c} - * const char *a[] = { - * "I", - * "like", - * "computers." - * }; - * const char *b[] = { - * "I", - * "like", - * "cars." - * }; - * if (!strcmp_array(a, b)) { - * printf("a and b are not equal\n"); - * } else { - * printf("a and b are equal\n"); - * } - * ~~~ - * - * @param a pointer to array - * @param b poitner to array - * @return 0 on identical, non-zero for different - */ -int strcmp_array(const char **a, const char **b); - -/** - * Determine whether a string is comprised of digits - * @param s - * @return 0=no, 1=yes - */ -int isdigit_s(const char *s); - -/** - * Convert input string to lowercase - * - * ~~~{.c} - * char *str = strdup("HELLO WORLD!"); - * tolower_s(str); - * // str is "hello world!" - * ~~~ - * - * @param s input string - * @return pointer to input string - */ -char *tolower_s(char *s); - -/** - * Return a copy of the input string with "." characters removed - * - * ~~~{.c} - * char *version = strdup("1.2.3"); - * char *version_short = to_short_version(str); - * // version_short is "123" - * free(version_short); - * - * ~~~ - * - * @param s input string - * @return pointer to new string - */ -char *to_short_version(const char *s); - -void unindent(char *s); - -#endif //STASIS_STR_H diff --git a/include/strlist.h b/include/strlist.h deleted file mode 100644 index cdbfc01..0000000 --- a/include/strlist.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * String array convenience functions - * @file strlist.h - */ -#ifndef STASIS_STRLIST_H -#define STASIS_STRLIST_H - -typedef int (ReaderFn)(size_t line, char **); - -#include <stdlib.h> -#include "core.h" -#include "utils.h" -#include "str.h" - - -struct StrList { - size_t num_alloc; - size_t num_inuse; - char **data; -}; - -struct StrList *strlist_init(); -void strlist_remove(struct StrList *pStrList, size_t index); -long double strlist_item_as_long_double(struct StrList *pStrList, size_t index); -double strlist_item_as_double(struct StrList *pStrList, size_t index); -float strlist_item_as_float(struct StrList *pStrList, size_t index); -unsigned long long strlist_item_as_ulong_long(struct StrList *pStrList, size_t index); -long long strlist_item_as_long_long(struct StrList *pStrList, size_t index); -unsigned long strlist_item_as_ulong(struct StrList *pStrList, size_t index); -long strlist_item_as_long(struct StrList *pStrList, size_t index); -unsigned int strlist_item_as_uint(struct StrList *pStrList, size_t index); -int strlist_item_as_int(struct StrList *pStrList, size_t index); -unsigned short strlist_item_as_ushort(struct StrList *pStrList, size_t index); -short strlist_item_as_short(struct StrList *pStrList, size_t index); -unsigned char strlist_item_as_uchar(struct StrList *pStrList, size_t index); -char strlist_item_as_char(struct StrList *pStrList, size_t index); -char *strlist_item_as_str(struct StrList *pStrList, size_t index); -char *strlist_item(struct StrList *pStrList, size_t index); -void strlist_set(struct StrList **pStrList, size_t index, char *value); -size_t strlist_count(struct StrList *pStrList); -void strlist_reverse(struct StrList *pStrList); -void strlist_sort(struct StrList *pStrList, unsigned int mode); -int strlist_append_file(struct StrList *pStrList, char *path, ReaderFn *readerFn); -void strlist_append_strlist(struct StrList *pStrList1, struct StrList *pStrList2); -void strlist_append(struct StrList **pStrList, char *str); -void strlist_append_array(struct StrList *pStrList, char **arr); -void strlist_append_tokenize(struct StrList *pStrList, char *str, char *delim); -struct StrList *strlist_copy(struct StrList *pStrList); -int strlist_cmp(struct StrList *a, struct StrList *b); -void strlist_free(struct StrList **pStrList); - -#define STRLIST_E_SUCCESS 0 -#define STRLIST_E_OUT_OF_RANGE 1 -#define STRLIST_E_INVALID_VALUE 2 -#define STRLIST_E_UNKNOWN 3 -extern int strlist_errno; -const char *strlist_get_error(int flag); - - -#endif //STASIS_STRLIST_H diff --git a/include/system.h b/include/system.h deleted file mode 100644 index 7019b92..0000000 --- a/include/system.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * System functions - * @file system.h - */ -#ifndef STASIS_SYSTEM_H -#define STASIS_SYSTEM_H - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <limits.h> -#include <sys/wait.h> -#include <sys/stat.h> - -#define STASIS_SHELL_SAFE_RESTRICT ";&|()" - -struct Process { - // Write stdout stream to file - char f_stdout[PATH_MAX]; - // Write stderr stream to file - char f_stderr[PATH_MAX]; - // Combine stderr and stdout (into stdout stream) - int redirect_stderr; - // Exit code from program - int returncode; -}; - -int shell(struct Process *proc, char *args); -int shell_safe(struct Process *proc, char *args); -char *shell_output(const char *command, int *status); - -#endif //STASIS_SYSTEM_H diff --git a/include/template.h b/include/template.h deleted file mode 100644 index e3d83fb..0000000 --- a/include/template.h +++ /dev/null @@ -1,81 +0,0 @@ -//! @file template.h -#ifndef STASIS_TEMPLATE_H -#define STASIS_TEMPLATE_H - -#include "core.h" - -/** - * Map a text value to a pointer in memory - * - * @param key in-text variable name - * @param ptr pointer to string - */ -void tpl_register(char *key, char **ptr); - -/** - * Free the template engine - */ -void tpl_free(); - -/** - * Retrieve the value of a key mapped by the template engine - * @param key string registered by `tpl_register` - * @return a pointer to value, or NULL if the key is not present - */ -char *tpl_getval(char *key); - -/** - * Replaces occurrences of all registered key value pairs in `str` - * @param str the text data to render - * @return a rendered copy of `str`, or NULL. - * The caller is responsible for free()ing memory allocated by this function - */ -char *tpl_render(char *str); - -/** - * Write tpl_render() output to a file - * @param str the text to render - * @param filename the output file name - * @return 0 on success, <0 on error - */ -int tpl_render_to_file(char *str, const char *filename); - -typedef int tplfunc(void *frame, void *data_out); - -struct tplfunc_frame { - char *key; ///< Name of the function - tplfunc *func; ///< Pointer to the function - void *data_in; ///< Pointer to internal data (can be NULL) - int argc; ///< Maximum number of arguments to accept - union { - char **t_char_refptr; ///< &pointer - char *t_char_ptr; ///< pointer - void *t_void_ptr; ///< pointer to void - int *t_int_ptr; ///< pointer to int - unsigned *t_uint_ptr; ///< pointer to unsigned int - float *t_float_ptr; ///< pointer to float - double *t_double_ptr; ///< pointer to double - char t_char; ///< type of char - int t_int; ///< type of int - unsigned t_uint; ///< type of unsigned int - float t_float; ///< type of float - double t_double; ///< type of double - } argv[10]; // accept up to 10 arguments -}; - -/** - * Register a template function - * @param key function name to expose to "func:" interface - * @param tplfunc_ptr pointer to function of type tplfunc - * @param argc number of function arguments to accept - */ -void tpl_register_func(char *key, void *tplfunc_ptr, int argc, void *data_in); - -/** - * Get the function frame associated with a template function - * @param key function name - * @return tplfunc_frame structure - */ -struct tplfunc_frame *tpl_getfunc(char *key); - -#endif //STASIS_TEMPLATE_H diff --git a/include/template_func_proto.h b/include/template_func_proto.h deleted file mode 100644 index 286ccfb..0000000 --- a/include/template_func_proto.h +++ /dev/null @@ -1,13 +0,0 @@ -//! @file template_func_proto.h -#ifndef TEMPLATE_FUNC_PROTO_H -#define TEMPLATE_FUNC_PROTO_H - -#include "template.h" - -int get_github_release_notes_tplfunc_entrypoint(void *frame, void *data_out); -int get_github_release_notes_auto_tplfunc_entrypoint(void *frame, void *data_out); -int get_junitxml_file_entrypoint(void *frame, void *data_out); -int get_basetemp_dir_entrypoint(void *frame, void *data_out); -int tox_run_entrypoint(void *frame, void *data_out); - -#endif //TEMPLATE_FUNC_PROTO_H
\ No newline at end of file diff --git a/include/utils.h b/include/utils.h deleted file mode 100644 index 87f28cc..0000000 --- a/include/utils.h +++ /dev/null @@ -1,416 +0,0 @@ -//! @file utils.h -#ifndef STASIS_UTILS_H -#define STASIS_UTILS_H -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> -#include <string.h> -#include <unistd.h> -#include <limits.h> -#include <errno.h> -#include "core.h" -#include "copy.h" -#include "system.h" -#include "strlist.h" -#include "utils.h" -#include "ini.h" - -#if defined(STASIS_OS_WINDOWS) -#define PATH_ENV_VAR "path" -#define DIR_SEP "\\" -#define PATH_SEP ";" -#define LINE_SEP "\r\n" -#else -#define PATH_ENV_VAR "PATH" -#define DIR_SEP "/" -#define PATH_SEP ":" -#define LINE_SEP "\n" -#endif - -#define STASIS_XML_PRETTY_PRINT_PROG "xmllint" -#define STASIS_XML_PRETTY_PRINT_ARGS "--format" - -/** - * Change directory. Push path on directory stack. - * - * ```c - * pushd("/somepath"); - * - * FILE fp = fopen("somefile", "w"); // i.e. /somepath/somefile - * fprintf(fp, "Hello world.\n"); - * fclose(fp); - * - * popd(); - * ``` - * - * @param path of directory - * @return 0 on success, -1 on error - */ -int pushd(const char *path); - -/** - * Return from directory. Pop last path from directory stack. - * - * @see pushd - * @return 0 on success, -1 if stack is empty - */ -int popd(void); - -/** - * Expand "~" to the user's home directory - * - * ```c - * char *home = expandpath("~"); // == /home/username - * char *config = expandpath("~/.config"); // == /home/username/.config - * char *nope = expandpath("/tmp/test"); // == /tmp/test - * char *nada = expandpath("/~/broken"); // == /~/broken - * - * free(home); - * free(config); - * free(nope); - * free(nada); - * ``` - * - * @param _path (Must start with a `~`) - * @return success=expanded path or original path, failure=NULL - */ -char *expandpath(const char *_path); - -/** - * Remove a directory tree recursively - * - * ```c - * mkdirs("a/b/c"); - * rmtree("a"); - * // a/b/c is removed - * ``` - * - * @param _path - * @return 0 on success, -1 on error - */ -int rmtree(char *_path); - - -char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn); - -/** - * Strip directory from file name - * Note: Caller is responsible for freeing memory - * - * @param _path - * @return success=file name, failure=NULL - */ -char *path_basename(char *path); - -/** - * Return parent directory of file, or the parent of a directory - * - * @param path - * @return success=directory, failure=empty string - */ -char *path_dirname(char *path); - -/** - * Scan PATH directories for a named program - * @param name program name - * @return path to program, or NULL on error - */ -char *find_program(const char *name); - -/** - * Create an empty file, or update modified timestamp on an existing file - * @param filename file to touch - * @return 0 on success, 1 on error - */ -int touch(const char *filename); - -/** - * Clone a git repository - * - * ```c - * struct Process proc; - * memset(proc, 0, sizeof(proc)); - * - * if (git_clone(&proc, "https://github.com/myuser/myrepo", "./repos", "unstable_branch")) { - * fprintf(stderr, "Failed to clone repository\n"); - * exit(1); - * } - * - * if (pushd("./repos/myrepo")) { - * fprintf(stderr, "Unable to enter repository directory\n"); - * } else { - * // do something with repository - * popd(); - * } - * ``` - * - * @see pushd - * - * @param proc Process struct - * @param url URL (or file system path) of repoistory to clone - * @param destdir destination directory - * @param gitref commit/branch/tag of checkout (NULL will use HEAD of default branch for repo) - * @return exit code from "git" - */ -int git_clone(struct Process *proc, char *url, char *destdir, char *gitref); - -/** - * Git describe wrapper - * @param path to repository - * @return output from "git describe", or NULL on error - */ -char *git_describe(const char *path); - -/** - * Git rev-parse wrapper - * @param path to repository - * @param args to pass to git rev-parse - * @return output from "git rev-parse", or NULL on error - */ -char *git_rev_parse(const char *path, char *args); - -/** - * Helper function to initialize simple STASIS internal path strings - * - * ```c - * char *mypath = NULL; - * - * if (path_store(&mypath, PATH_MAX, "/some", "path")) { - * fprintf(stderr, "Unable to allocate memory for path elements\n"); - * exit(1); - * } - * // mypath is allocated to size PATH_MAX and contains the string: /some/path - * // base+path will truncate at maxlen - 1 - * ``` - * - * @param destptr address of destination string pointer - * @param maxlen maximum length of the path - * @param base path - * @param path to append to base - * @return 0 on success, -1 on error - */ -int path_store(char **destptr, size_t maxlen, const char *base, const char *path); - -#if defined(STASIS_DUMB_TERMINAL) -#define STASIS_COLOR_RED "" -#define STASIS_COLOR_GREEN "" -#define STASIS_COLOR_YELLOW "" -#define STASIS_COLOR_BLUE "" -#define STASIS_COLOR_WHITE "" -#define STASIS_COLOR_RESET "" -#else -//! Set output color to red -#define STASIS_COLOR_RED "\e[1;91m" -//! Set output color to green -#define STASIS_COLOR_GREEN "\e[1;92m" -//! Set output color to yellow -#define STASIS_COLOR_YELLOW "\e[1;93m" -//! Set output color to blue -#define STASIS_COLOR_BLUE "\e[1;94m" -//! Set output color to white -#define STASIS_COLOR_WHITE "\e[1;97m" -//! Reset output color to terminal default -#define STASIS_COLOR_RESET "\e[0;37m\e[0m" -#endif - -#define STASIS_MSG_SUCCESS 0 -//! Suppress printing of the message text -#define STASIS_MSG_NOP 1 << 0 -//! The message is an error -#define STASIS_MSG_ERROR 1 << 1 -//! The message is a warning -#define STASIS_MSG_WARN 1 << 2 -//! The message will be indented once -#define STASIS_MSG_L1 1 << 3 -//! The message will be indented twice -#define STASIS_MSG_L2 1 << 4 -//! The message will be indented thrice -#define STASIS_MSG_L3 1 << 5 -//! The message will only be printed in verbose mode -#define STASIS_MSG_RESTRICT 1 << 6 - -void msg(unsigned type, char *fmt, ...); - -// Enter an interactive shell that ends the program on-exit -void debug_shell(); - -/** - * Creates a temporary file returning an open file pointer via @a fp, and the - * path to the file. The caller is responsible for closing @a fp and - * free()ing the returned file path. - * - * ```c - * FILE *fp = NULL; - * char *tempfile = xmkstemp(&fp, "r+"); - * if (!fp || !tempfile) { - * fprintf(stderr, "Failed to generate temporary file for read/write\n"); - * exit(1); - * } - * ``` - * - * @param fp pointer to FILE (to be initialized) - * @param mode fopen() style file mode string - * @return system path to the temporary file - * @return NULL on failure - */ -char *xmkstemp(FILE **fp, const char *mode); - -/** - * Is the path an empty directory structure? - * - * ```c - * if (isempty_dir("/some/path")) { - * fprintf(stderr, "The directory is is empty!\n"); - * } else { - * printf("The directory contains dirs/files\n"); - * } - * ``` - * - * @param path directory - * @return 0 = no, 1 = yes - */ -int isempty_dir(const char *path); - -/** - * Rewrite an XML file with a pretty printer command - * @param filename path to modify - * @param pretty_print_prog program to call - * @param pretty_print_args arguments to pass to program - * @return 0 on success, -1 on error - */ -int xml_pretty_print_in_place(const char *filename, const char *pretty_print_prog, const char *pretty_print_args); - -/** - * Applies STASIS fixups to a tox ini config - * @param filename path to tox.ini - * @param result path to processed configuration - * @return 0 on success, -1 on error - */ -int fix_tox_conf(const char *filename, char **result); - -char *collapse_whitespace(char **s); - -/** - * Write ***REDACTED*** in dest for each occurrence of to_redacted token present in src - * - * ```c - * char command[PATH_MAX] = {0}; - * char command_redacted[PATH_MAX] = {0}; - * const char *password = "abc123"; - * const char *host = "myhostname"; - * const char *to_redact_case1[] = {password, host, NULL}; - * const char *to_redact_case2[] = {password, "--host", NULL}; - * const char *to_redact_case3[] = {password, "--host", host, NULL}; - * - * sprintf(command, "echo %s | program --host=%s -", password, host); - * - * // CASE 1 - * redact_sensitive(to_redact_case1, command, command_redacted, sizeof(command_redacted) - 1); - * printf("executing: %s\n", command_redacted); - * // User sees: - * // executing: echo ***REDACTED*** | program --host=***REDACTED*** - - * system(command); - * - * // CASE 2 remove an entire argument - * redact_sensitive(to_redact_case2, command, command_redacted, sizeof(command_redacted) - 1); - * printf("executing: %s\n", command_redacted); - * // User sees: - * // executing: echo ***REDACTED*** | program ***REDACTED*** - - * system(command); - * - * // CASE 3 remove it all (noisy) - * redact_sensitive(to_redact_case3, command, command_redacted, sizeof(command_redacted) - 1); - * printf("executing: %s\n", command_redacted); - * // User sees: - * // executing: echo ***REDACTED*** | program ***REDACTED***=***REDACTED*** - - * system(command); - * ``` - * - * @param to_redact array of tokens to redact - * @param src input string - * @param dest output string - * @param maxlen maximum length of dest byte array - * @return 0 on success, -1 on error - */ -int redact_sensitive(const char **to_redact, size_t to_redact_size, char *src, char *dest, size_t maxlen); - -/** - * Given a directory path, return a list of files - * - * ~~~{.c} - * struct StrList *files; - * - * basepath = "."; - * files = listdir(basepath); - * for (size_t i = 0; i < strlist_count(files); i++) { - * char *filename = strlist_item(files, i); - * printf("%s/%s\n", basepath, filename); - * } - * guard_strlist_free(&files); - * ~~~ - * - * @param path of a directory - * @return a StrList containing file names - */ -struct StrList *listdir(const char *path); - -/** - * Get CPU count - * @return CPU count on success, zero on error - */ -long get_cpu_count(); - -/** - * Create all leafs in directory path - * @param _path directory path to create - * @param mode mode_t permissions - * @return - */ -int mkdirs(const char *_path, mode_t mode); - -/** - * Return pointer to a (possible) version specifier - * - * ```c - * char s[] = "abc==1.2.3"; - * char *spec_begin = find_version_spec(s); - * // spec_begin is "==1.2.3" - * - * char package_name[255]; - * char s[] = "abc"; - * char *spec_pos = find_version_spec(s); - * if (spec_pos) { - * strncpy(package_name, spec_pos - s); - * // use spec - * } else { - * // spec not found - * } - * - * @param str a pointer to a buffer containing a package spec (i.e. abc==1.2.3, abc>=1.2.3, abc) - * @return a pointer to the first occurrence of a version spec character - * @return NULL if not found - */ -char *find_version_spec(char *package_name); - -// mode flags for env_manipulate_pathstr -#define PM_APPEND 1 << 0 -#define PM_PREPEND 1 << 1 -#define PM_ONCE 1 << 2 - -/** -* Add paths to the head or tail of an environment variable. -* -* @param key environment variable to manipulate -* @param path to insert (does not need to exist) -* @param mode PM_APPEND `$path:$PATH` -* @param mode PM_PREPEND `$PATH:path` -* @param mode PM_ONCE do not manipulate if `path` is present in PATH variable -*/ -int env_manipulate_pathstr(const char *key, char *path, int mode); - -/** -* Append or replace a file extension -*/ -int gen_file_extension_str(char *filename, const char *extension); - -#endif //STASIS_UTILS_H diff --git a/include/wheel.h b/include/wheel.h deleted file mode 100644 index 1a689e9..0000000 --- a/include/wheel.h +++ /dev/null @@ -1,36 +0,0 @@ -//! @file wheel.h -#ifndef STASIS_WHEEL_H -#define STASIS_WHEEL_H - -#include <dirent.h> -#include <string.h> -#include <stdio.h> -#include "str.h" -#define WHEEL_MATCH_EXACT 0 ///< Match when all patterns are present -#define WHEEL_MATCH_ANY 1 ///< Match when any patterns are present - -struct Wheel { - char *distribution; ///< Package name - char *version; ///< Package version - char *build_tag; ///< Package build tag (optional) - char *python_tag; ///< Package Python tag (pyXY) - char *abi_tag; ///< Package ABI tag (cpXY, abiX, none) - char *platform_tag; ///< Package platform tag (linux_x86_64, any) - char *path_name; ///< Path to package on-disk - char *file_name; ///< Name of package on-disk -}; - -/** - * Extract metadata from a Python Wheel file name - * - * @param basepath directory containing a wheel file - * @param name of wheel file - * @param to_match a NULL terminated array of patterns (i.e. platform, arch, version, etc) - * @param match_mode WHEEL_MATCH_EXACT - * @param match_mode WHEEL_MATCH ANY - * @return pointer to populated Wheel on success - * @return NULL on error - */ -struct Wheel *get_wheel_info(const char *basepath, const char *name, char *to_match[], unsigned match_mode); -void wheel_free(struct Wheel **wheel); -#endif //STASIS_WHEEL_H |