diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-03-04 08:48:28 -0500 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-03-04 08:48:28 -0500 |
commit | 239330330a8fc49c6806cccdc17a910d23d22952 (patch) | |
tree | 0e2a3e2e852cafd718556bb31ab58ffc0968504c | |
parent | 39861d1872731119795f954acc0412af64cd539d (diff) | |
download | stasis-239330330a8fc49c6806cccdc17a910d23d22952.tar.gz |
Prototypes documentation
Includes minor changes:
* Rename jfrt_upload_set_defaults to jfrt_upload_init
* Move jfrt_auth_init to artifactory.c
* Adds missing error handling to git_describe and git_rev_parse
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | docs/Doxyfile | 16 | ||||
-rw-r--r-- | include/artifactory.h | 55 | ||||
-rw-r--r-- | include/copy.h | 42 | ||||
-rw-r--r-- | include/deliverable.h | 23 | ||||
-rw-r--r-- | include/docker.h | 70 | ||||
-rw-r--r-- | include/download.h | 5 | ||||
-rw-r--r-- | include/recipe.h | 62 | ||||
-rw-r--r-- | include/template.h | 5 | ||||
-rw-r--r-- | include/utils.h | 172 | ||||
-rw-r--r-- | src/artifactory.c | 55 | ||||
-rw-r--r-- | src/deliverable.c | 55 | ||||
-rw-r--r-- | src/utils.c | 56 |
13 files changed, 479 insertions, 139 deletions
@@ -1,5 +1,3 @@ -# OH MY CAL - OMC aims to consolidate the steps required to build, test, and deploy calibration pipelines and other software suites maintained by engineers at the Space Telescope Science Institute. # Requirements diff --git a/docs/Doxyfile b/docs/Doxyfile index bef5a97..d6509e6 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -124,7 +124,7 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = src include +INPUT = README.md src include INPUT_ENCODING = UTF-8 INPUT_FILE_ENCODING = FILE_PATTERNS = *.c \ @@ -190,7 +190,7 @@ INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = README.md FORTRAN_COMMENT_AFTER = 72 #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -308,7 +308,7 @@ RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- -GENERATE_MAN = NO +GENERATE_MAN = YES MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_SUBDIR = @@ -346,7 +346,7 @@ PERLMOD_MAKEVAR_PREFIX = # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = @@ -366,14 +366,14 @@ EXTERNAL_PAGES = YES # Configuration options related to diagram generator tools #--------------------------------------------------------------------------- HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = NO +HAVE_DOT = YES DOT_NUM_THREADS = 0 DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" DOT_FONTPATH = CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES +COLLABORATION_GRAPH = NO GROUP_GRAPHS = YES UML_LOOK = NO UML_LIMIT_NUM_FIELDS = 10 @@ -381,8 +381,8 @@ DOT_UML_DETAILS = NO DOT_WRAP_THRESHOLD = 17 TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = YES CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES diff --git a/include/artifactory.h b/include/artifactory.h index c8ce6d3..0883eef 100644 --- a/include/artifactory.h +++ b/include/artifactory.h @@ -130,10 +130,10 @@ int artifactory_download_cli(char *dest, * * ```c * struct JFRT_Auth auth_ctx; - * memset(auth_ctx, 0, sizeof(auth_context); * 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, "ping") { * fprintf(stderr, "Failed to ping artifactory server: %s\n", auth_ctx.url); @@ -152,10 +152,10 @@ int jfrog_cli(struct JFRT_Auth *auth, char *args); * * ```c * struct JFRT_Auth auth_ctx; - * memset(auth_ctx, 0, sizeof(auth_context); * 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); @@ -173,13 +173,13 @@ int jfrog_cli_rt_ping(struct JFRT_Auth *auth); * * ```c * struct JFRT_Auth auth_ctx; - * memset(auth_ctx, 0, sizeof(auth_context); * 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_set_defaults(&upload_ctx); + * jfrt_upload_init(&upload_ctx); * * if (jfrt_cli_rt_upload(&auth_ctx, &upload_ctx, * "local/files_*.ext", "repo_name/ext_files/")) { @@ -201,10 +201,10 @@ int jfrog_cli_rt_upload(struct JFRT_Auth *auth, struct JFRT_Upload *ctx, char *s * * ```c * struct JFRT_Auth auth_ctx; - * memset(auth_ctx, 0, sizeof(auth_context); * 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)); @@ -229,10 +229,10 @@ int jfrog_cli_rt_download(struct JFRT_Auth *auth, struct JFRT_Download *ctx, cha * * ```c * struct JFRT_Auth auth_ctx; - * memset(auth_ctx, 0, sizeof(auth_context); * 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"); @@ -252,10 +252,10 @@ int jfrog_cli_rt_build_collect_env(struct JFRT_Auth *auth, char *build_name, cha * * ```c * struct JFRT_Auth auth_ctx; - * memset(auth_ctx, 0, sizeof(auth_context); * 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"); @@ -276,9 +276,48 @@ int jfrog_cli_rt_build_collect_env(struct JFRT_Auth *auth, char *build_name, cha int jfrog_cli_rt_build_publish(struct JFRT_Auth *auth, char *build_name, char *build_number); /** + * Configure JFrog CLI authentication according to OMC specs + * + * This function will use the OMC_JF_* environment variables to configure the authentication + * context. With this in mind, if an OMC_JF_* environment variable is not defined, the original value of + * the structure member will be used instead. + * + * Use OMC_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 OMC'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_set_defaults(struct JFRT_Upload *ctx); +void jfrt_upload_init(struct JFRT_Upload *ctx); #endif //OMC_ARTIFACTORY_H
\ No newline at end of file diff --git a/include/copy.h b/include/copy.h index 9e8bc11..5a53d7d 100644 --- a/include/copy.h +++ b/include/copy.h @@ -1,3 +1,4 @@ +//! @file copy.h #ifndef OMC_COPY_H #include <stdio.h> @@ -12,8 +13,49 @@ #define CT_OWNER 1 << 1 #define CT_PERM 1 << 2 +/** + * Recursively copy a directory, or a single file + * + * ```c + * if (copytree("/source/path", "/destination/path", CT_PERM | CT_OWNER)) { + * fprintf(stderr, "Unable to copy files\n"); + * exit(1); + * } + * ``` + * + * @param srcdir source file or directory path + * @param destdir destination directory + * @param op CT_OWNER (preserve ownership) + * @param op CT_PERM (preserve permission bits) + * @return 0 on success, -1 on error + */ int copytree(const char *srcdir, const char *destdir, unsigned op); + +/** + * 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); + +/** + * 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 // OMC_COPY_H
\ No newline at end of file diff --git a/include/deliverable.h b/include/deliverable.h index 63adef1..1fbbd54 100644 --- a/include/deliverable.h +++ b/include/deliverable.h @@ -323,17 +323,18 @@ 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) + * + * - `%%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 diff --git a/include/docker.h b/include/docker.h index 03f5d0d..3c7dff6 100644 --- a/include/docker.h +++ b/include/docker.h @@ -1,20 +1,82 @@ +//! @file docker.h #ifndef OMC_DOCKER_H #define OMC_DOCKER_H +//! Flag to squelch output from docker_exec() #define OMC_DOCKER_QUIET 1 << 1 +//! Flag for older style docker build #define OMC_DOCKER_BUILD 1 << 1 +//! Flag for docker buildx #define OMC_DOCKER_BUILD_X 1 << 2 struct DockerCapabilities { - int podman; - int build; - int available; - int usable; + 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 `OMC_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); diff --git a/include/download.h b/include/download.h index 440c749..568809e 100644 --- a/include/download.h +++ b/include/download.h @@ -1,7 +1,4 @@ -// -// Created by jhunk on 10/5/23. -// - +//! @file download.h #ifndef OMC_DOWNLOAD_H #define OMC_DOWNLOAD_H diff --git a/include/recipe.h b/include/recipe.h index f4c63c1..f1b4df1 100644 --- a/include/recipe.h +++ b/include/recipe.h @@ -1,20 +1,72 @@ -// -// Created by jhunk on 10/7/23. -// - +//! @file recipe.h #ifndef OMC_RECIPE_H #define OMC_RECIPE_H #include "str.h" #include "utils.h" -#define RECIPE_DIR "recipes" +//! 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 //OMC_RECIPE_H diff --git a/include/template.h b/include/template.h index b12208f..116960f 100644 --- a/include/template.h +++ b/include/template.h @@ -1,7 +1,4 @@ -// -// Created by jhunk on 12/17/23. -// - +//! @file template.h #ifndef OMC_TEMPLATE_H #define OMC_TEMPLATE_H diff --git a/include/utils.h b/include/utils.h index 52f4f2d..71d3f8b 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,3 +1,4 @@ +//! @file utils.h #ifndef OMC_UTILS_H #define OMC_UTILS_H #include <stdio.h> @@ -23,35 +24,204 @@ typedef int (ReaderFn)(size_t line, char **); +/** + * 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 OMC 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); #define OMC_MSG_SUCCESS 0 +//! Suppress printing of the message text #define OMC_MSG_NOP 1 << 0 +//! The message is an error #define OMC_MSG_ERROR 1 << 1 +//! The message is a warning #define OMC_MSG_WARN 1 << 2 +//! The message will be indented once #define OMC_MSG_L1 1 << 3 +//! The message will be indented twice #define OMC_MSG_L2 1 << 4 +//! The message will be indented thrice #define OMC_MSG_L3 1 << 5 -#define OMC_MSG_RESTRICT 1 << 6 ///< Restrict to verbose mode +//! The message will only be printed in verbose mode +#define OMC_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 */ diff --git a/src/artifactory.c b/src/artifactory.c index 55cb7dd..39a662d 100644 --- a/src/artifactory.c +++ b/src/artifactory.c @@ -115,7 +115,7 @@ void jfrt_register_opt_long(long jfrt_val, const char *opt_name, struct StrList strlist_append(*opt_map, data); } -void jfrt_upload_set_defaults(struct JFRT_Upload *ctx) { +void jfrt_upload_init(struct JFRT_Upload *ctx) { memset(ctx, 0, sizeof(*ctx)); ctx->recursive = true; ctx->threads = 3; @@ -135,6 +135,59 @@ static int auth_required(char *cmd) { return 0; } +int jfrt_auth_init(struct JFRT_Auth *auth_ctx) { + char *url = getenv("OMC_JF_ARTIFACTORY_URL"); + char *user = getenv("OMC_JF_USER"); + char *access_token = getenv("OMC_JF_ACCESS_TOKEN"); + char *password = getenv("OMC_JF_PASSWORD"); + char *ssh_key_path = getenv("OMC_JF_SSH_KEY_PATH"); + char *ssh_passphrase = getenv("OMC_JF_SSH_PASSPHRASE"); + char *client_cert_key_path = getenv("OMC_JF_CLIENT_CERT_KEY_PATH"); + char *client_cert_path = getenv("OMC_JF_CLIENT_CERT_PATH"); + + if (!url) { + fprintf(stderr, "Artifactory URL is not configured:\n"); + fprintf(stderr, "please set OMC_JF_ARTIFACTORY_URL\n"); + return -1; + } + auth_ctx->url = url; + + if (access_token) { + auth_ctx->user = NULL; + auth_ctx->access_token = access_token; + auth_ctx->password = NULL; + auth_ctx->ssh_key_path = NULL; + } else if (user && password) { + auth_ctx->user = user; + auth_ctx->password = password; + auth_ctx->access_token = NULL; + auth_ctx->ssh_key_path = NULL; + } else if (ssh_key_path) { + auth_ctx->user = NULL; + auth_ctx->ssh_key_path = ssh_key_path; + if (ssh_passphrase) { + auth_ctx->ssh_passphrase = ssh_passphrase; + } + auth_ctx->password = NULL; + auth_ctx->access_token = NULL; + } else if (client_cert_key_path && client_cert_path) { + auth_ctx->user = NULL; + auth_ctx->password = NULL; + auth_ctx->access_token = NULL; + auth_ctx->ssh_key_path = NULL; + auth_ctx->client_cert_key_path = client_cert_key_path; + auth_ctx->client_cert_path = client_cert_path; + } else { + fprintf(stderr, "Artifactory authentication is not configured:\n"); + fprintf(stderr, "set OMC_JF_USER and OMC_JF_PASSWORD\n"); + fprintf(stderr, "or, set OMC_JF_ACCESS_TOKEN\n"); + fprintf(stderr, "or, set OMC_JF_SSH_KEY_PATH and OMC_JF_SSH_KEY_PASSPHRASE\n"); + fprintf(stderr, "or, set OMC_JF_CLIENT_CERT_KEY_PATH and OMC_JF_CLIENT_CERT_PATH\n"); + return -1; + } + return 0; +} + int jfrog_cli(struct JFRT_Auth *auth, char *args) { struct Process proc; char cmd[OMC_BUFSIZ]; diff --git a/src/deliverable.c b/src/deliverable.c index b935b64..f9c53ba 100644 --- a/src/deliverable.c +++ b/src/deliverable.c @@ -1433,59 +1433,6 @@ int delivery_init_artifactory(struct Delivery *ctx) { return status; } -int jfrt_auth_init(struct JFRT_Auth *auth_ctx) { - char *url = getenv("OMC_JF_ARTIFACTORY_URL"); - char *user = getenv("OMC_JF_USER"); - char *access_token = getenv("OMC_JF_ACCESS_TOKEN"); - char *password = getenv("OMC_JF_PASSWORD"); - char *ssh_key_path = getenv("OMC_JF_SSH_KEY_PATH"); - char *ssh_passphrase = getenv("OMC_JF_SSH_PASSPHRASE"); - char *client_cert_key_path = getenv("OMC_JF_CLIENT_CERT_KEY_PATH"); - char *client_cert_path = getenv("OMC_JF_CLIENT_CERT_PATH"); - - if (!url) { - fprintf(stderr, "Artifactory URL is not configured:\n"); - fprintf(stderr, "please set OMC_JF_ARTIFACTORY_URL\n"); - return -1; - } - auth_ctx->url = url; - - if (access_token) { - auth_ctx->user = NULL; - auth_ctx->access_token = access_token; - auth_ctx->password = NULL; - auth_ctx->ssh_key_path = NULL; - } else if (user && password) { - auth_ctx->user = user; - auth_ctx->password = password; - auth_ctx->access_token = NULL; - auth_ctx->ssh_key_path = NULL; - } else if (ssh_key_path) { - auth_ctx->user = NULL; - auth_ctx->ssh_key_path = ssh_key_path; - if (ssh_passphrase) { - auth_ctx->ssh_passphrase = ssh_passphrase; - } - auth_ctx->password = NULL; - auth_ctx->access_token = NULL; - } else if (client_cert_key_path && client_cert_path) { - auth_ctx->user = NULL; - auth_ctx->password = NULL; - auth_ctx->access_token = NULL; - auth_ctx->ssh_key_path = NULL; - auth_ctx->client_cert_key_path = client_cert_key_path; - auth_ctx->client_cert_path = client_cert_path; - } else { - fprintf(stderr, "Artifactory authentication is not configured:\n"); - fprintf(stderr, "set OMC_JF_USER and OMC_JF_PASSWORD\n"); - fprintf(stderr, "or, set OMC_JF_ACCESS_TOKEN\n"); - fprintf(stderr, "or, set OMC_JF_SSH_KEY_PATH and OMC_JF_SSH_KEY_PASSPHRASE\n"); - fprintf(stderr, "or, set OMC_JF_CLIENT_CERT_KEY_PATH and OMC_JF_CLIENT_CERT_PATH\n"); - return -1; - } - return 0; -} - int delivery_artifact_upload(struct Delivery *ctx) { int status = 0; @@ -1493,7 +1440,7 @@ int delivery_artifact_upload(struct Delivery *ctx) { if (!ctx->deploy[i].files || !ctx->deploy[i].dest) { break; } - jfrt_upload_set_defaults(&ctx->deploy[i].upload_ctx); + jfrt_upload_init(&ctx->deploy[i].upload_ctx); char *repo = getenv("OMC_JF_REPO"); if (repo) { diff --git a/src/utils.c b/src/utils.c index 2b4d275..b669e1c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -69,25 +69,6 @@ int rmtree(char *_path) { return status; } -/** - * Expand "~" to the user's home directory - * - * Example: - * ~~~{.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) { if (_path == NULL) { return NULL; @@ -146,13 +127,6 @@ char *expandpath(const char *_path) { return strdup(result); } -/** - * 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) { char *result = NULL; char *last = NULL; @@ -168,12 +142,6 @@ char *path_basename(char *path) { return result; } -/** - * Return parent directory of file, or the parent of a directory - * - * @param path - * @return success=directory, failure=empty string - */ char *path_dirname(char *path) { if (!path) { return ""; @@ -374,11 +342,18 @@ int git_clone(struct Process *proc, char *url, char *destdir, char *gitref) { char *git_describe(const char *path) { - pushd(path); static char version[NAME_MAX]; FILE *pp; - pp = popen("git describe --first-parent --always --tags", "r"); + memset(version, 0, sizeof(version)); + if (pushd(path)) { + return NULL; + } + + pp = popen("git describe --first-parent --always --tags", "r"); + if (!pp) { + return NULL; + } fgets(version, sizeof(version) - 1, pp); strip(version); pclose(pp); @@ -387,18 +362,25 @@ char *git_describe(const char *path) { } char *git_rev_parse(const char *path, char *args) { - pushd(path); static char version[NAME_MAX]; char cmd[PATH_MAX]; FILE *pp; + memset(version, 0, sizeof(version)); if (isempty(args)) { - fprintf(stderr, "git_rev_parse args cannot be empty"); + fprintf(stderr, "git_rev_parse args cannot be empty\n"); + return NULL; + } + + if (pushd(path)) { return NULL; } + sprintf(cmd, "git rev-parse %s", args); pp = popen(cmd, "r"); - memset(version, 0, sizeof(version)); + if (!pp) { + return NULL; + } fgets(version, sizeof(version) - 1, pp); strip(version); pclose(pp); |