aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@users.noreply.github.com>2024-08-07 13:52:10 -0400
committerGitHub <noreply@github.com>2024-08-07 13:52:10 -0400
commit1d5e5f26014ceefd824382acec732f326d8d6ce2 (patch)
tree2d329c1a76e1bb5a13a84659465a60d2c6e99cd2
parent202e69c8951a38187489c66e994dd593755d62cb (diff)
downloadstasis-1d5e5f26014ceefd824382acec732f326d8d6ce2.tar.gz
Refactor ini getter and setter usage (#19)
* Add handler for space-delimited lists * This needs attention, however. The INI writer has no way to know a list with spaces is a list; this happens in the value conversion functions. * Add type_hint member to INIData structure. At some point support with be added for all INIVAL_TYPE_* defines. Right now it's only used with arrays. * Zero out line buffer in ini_open after each iteration * Do not strip raw INI data. Let the conversion functions handle it * Add spaces to key value pairs in rendered INI output. * Add ini_getvar_TYPE() functions * These replace the functionality of static conv_TYPE() functions in delivery.c * Add support for missing types: U/CHAR, U/SHORT, STRLIST * ini_getval: expand template variables immediately before processing the output * Strip leading space to avoid issues with string comparisons against the result * ini_getval: Return copies, not the original. * This forces one to use ini_setval to replace/append values to the data array(s). It's safer this way. * fix_tox_conf(): Use ini_getval and ini_setval instead of modifying the original pointers directly * Tests: Free resources * Replace ini_getval(), ini_getval_required() and conv_*() usage * Now using ini_getval_TYPE() functions and ini_setval() * Remove unused helper functions and variables * download() returns long, not int * actions: update apt cache
-rw-r--r--.github/workflows/cmake-multi-platform.yml5
-rw-r--r--include/ini.h52
-rw-r--r--src/delivery.c315
-rw-r--r--src/ini.c164
-rw-r--r--src/utils.c30
-rw-r--r--tests/test_utils.c2
6 files changed, 324 insertions, 244 deletions
diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml
index e7d4b33..0a30f4c 100644
--- a/.github/workflows/cmake-multi-platform.yml
+++ b/.github/workflows/cmake-multi-platform.yml
@@ -37,6 +37,11 @@ jobs:
run: |
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
+ - name: Update apt
+ if: matrix.os == 'ubuntu-latest'
+ run: >
+ sudo apt update
+
- name: Install Linux dependencies
if: matrix.os == 'ubuntu-latest'
run: >
diff --git a/include/ini.h b/include/ini.h
index 7167cad..5c840f5 100644
--- a/include/ini.h
+++ b/include/ini.h
@@ -14,24 +14,32 @@
#define INI_SEARCH_SUBSTR 2
///< expanded to preserve runtime state.
-#define INIVAL_TYPE_INT 1 ///< Integer
-#define INIVAL_TYPE_UINT 2 ///< Unsigned integer
-#define INIVAL_TYPE_LONG 3 ///< Long integer
-#define INIVAL_TYPE_ULONG 4 ///< Unsigned long integer
-#define INIVAL_TYPE_LLONG 5 ///< Long long integer
-#define INIVAL_TYPE_ULLONG 6 ///< Unsigned long long integer
-#define INIVAL_TYPE_DOUBLE 7 ///< Double precision float
-#define INIVAL_TYPE_FLOAT 8 ///< Single precision float
-#define INIVAL_TYPE_STR 9 ///< String
-#define INIVAL_TYPE_STR_ARRAY 10 ///< String Array
-#define INIVAL_TYPE_BOOL 11 ///< Boolean
+#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 Consolidation possible value types
+ * \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
@@ -52,6 +60,7 @@ union INIVal {
struct INIData {
char *key; ///< INI variable name
char *value; ///< INI variable value
+ unsigned type_hint;
};
/*! \struct INISection
@@ -225,4 +234,23 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode);
* @param ini
*/
void ini_free(struct INIFILE **ini);
+
+int ini_getval_int(struct INIFILE *ini, char *section_name, char *key, int *state);
+unsigned int ini_getval_uint(struct INIFILE *ini, char *section_name, char *key, int *state);
+long ini_getval_long(struct INIFILE *ini, char *section_name, char *key, int *state);
+unsigned long ini_getval_ulong(struct INIFILE *ini, char *section_name, char *key, int *state);
+long long ini_getval_llong(struct INIFILE *ini, char *section_name, char *key, int *state);
+unsigned long long ini_getval_ullong(struct INIFILE *ini, char *section_name, char *key, int *state);
+float ini_getval_float(struct INIFILE *ini, char *section_name, char *key, int *state);
+double ini_getval_double(struct INIFILE *ini, char *section_name, char *key, int *state);
+bool ini_getval_bool(struct INIFILE *ini, char *section_name, char *key, int *state);
+short ini_getval_short(struct INIFILE *ini, char *section_name, char *key, int *state);
+unsigned short ini_getval_ushort(struct INIFILE *ini, char *section_name, char *key, int *state);
+char ini_getval_char(struct INIFILE *ini, char *section_name, char *key, int *state);
+unsigned char ini_getval_uchar(struct INIFILE *ini, char *section_name, char *key, int *state);
+char *ini_getval_char_p(struct INIFILE *ini, char *section_name, char *key, int *state);
+char *ini_getval_str(struct INIFILE *ini, char *section_name, char *key, int *state);
+char **ini_getval_char_array_p(struct INIFILE *ini, char *section_name, char *key, int *state);
+char **ini_getval_str_array(struct INIFILE *ini, char *section_name, char *key, int *state);
+struct StrList *ini_getval_strlist(struct INIFILE *ini, char *section_name, char *key, char *tok, int *state);
#endif //STASIS_INI_H
diff --git a/src/delivery.c b/src/delivery.c
index b1997f6..1b16f39 100644
--- a/src/delivery.c
+++ b/src/delivery.c
@@ -13,18 +13,6 @@ static void ini_has_key_required(struct INIFILE *ini, const char *section_name,
}
}
-static void ini_getval_required(struct INIFILE *ini, char *section_name, char *key, unsigned type, union INIVal *val) {
- int status = ini_getval(ini, section_name, key, type, val);
- if (status || isempty(val->as_char_p)) {
- SYSERROR("%s:%s value is required but not defined", section_name, key);
- exit(1);
- }
-}
-
-static void conv_int(int *x, union INIVal val) {
- *x = val.as_int;
-}
-
static void conv_str(char **x, union INIVal val) {
if (*x) {
guard_free(*x);
@@ -41,30 +29,6 @@ static void conv_str(char **x, union INIVal val) {
}
}
-static void conv_str_noexpand(char **x, union INIVal val) {
- if (*x) {
- guard_free(*x);
- }
- *x = strdup(val.as_char_p);
-}
-
-static void conv_strlist(struct StrList **x, char *tok, union INIVal val) {
- if (!(*x))
- (*x) = strlist_init();
- if (val.as_char_p) {
- char *tplop = tpl_render(val.as_char_p);
- if (tplop) {
- strip(tplop);
- strlist_append_tokenize((*x), tplop, tok);
- guard_free(tplop);
- }
- }
-}
-
-static void conv_bool(bool *x, union INIVal val) {
- *x = val.as_bool;
-}
-
int delivery_init_tmpdir(struct Delivery *ctx) {
char *tmpdir = NULL;
char *x = NULL;
@@ -380,7 +344,7 @@ int delivery_init_platform(struct Delivery *ctx) {
}
static int populate_mission_ini(struct Delivery **ctx) {
- union INIVal val;
+ int err = 0;
struct INIFILE *ini;
if ((*ctx)->_stasis_ini_fp.mission) {
@@ -406,16 +370,13 @@ static int populate_mission_ini(struct Delivery **ctx) {
}
(*ctx)->_stasis_ini_fp.mission_path = strdup(missionfile);
- ini_getval_required(ini, "meta", "release_fmt", INIVAL_TYPE_STR, &val);
- conv_str(&(*ctx)->rules.release_fmt, val);
+ (*ctx)->rules.release_fmt = ini_getval_str(ini, "meta", "release_fmt", &err);
// Used for setting artifactory build info
- ini_getval_required(ini, "meta", "build_name_fmt", INIVAL_TYPE_STR, &val);
- conv_str(&(*ctx)->rules.build_name_fmt, val);
+ (*ctx)->rules.build_name_fmt = ini_getval_str(ini, "meta", "build_name_fmt", &err);
// Used for setting artifactory build info
- ini_getval_required(ini, "meta", "build_number_fmt", INIVAL_TYPE_STR, &val);
- conv_str(&(*ctx)->rules.build_number_fmt, val);
+ (*ctx)->rules.build_number_fmt = ini_getval_str(ini, "meta", "build_number_fmt", &err);
return 0;
}
@@ -489,80 +450,67 @@ static int populate_delivery_ini(struct Delivery *ctx) {
runtime_apply(rt);
ctx->runtime.environ = rt;
- ini_getval_required(ini, "meta", "mission", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->meta.mission, val);
+ int err = 0;
+ ctx->meta.mission = ini_getval_str(ini, "meta", "mission", &err);
if (!strcasecmp(ctx->meta.mission, "hst")) {
- ini_getval(ini, "meta", "codename", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->meta.codename, val);
+ ctx->meta.codename = ini_getval_str(ini, "meta", "codename", &err);
} else {
ctx->meta.codename = NULL;
}
- /*
- if (!strcasecmp(ctx->meta.mission, "jwst")) {
- ini_getval(ini, "meta", "version", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->meta.version, val);
-
- } else {
- ctx->meta.version = NULL;
- }
- */
- ini_getval(ini, "meta", "version", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->meta.version, val);
-
- ini_getval_required(ini, "meta", "name", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->meta.name, val);
-
- ini_getval(ini, "meta", "rc", INIVAL_TYPE_INT, &val);
- conv_int(&ctx->meta.rc, val);
-
- ini_getval(ini, "meta", "final", INIVAL_TYPE_BOOL, &val);
- conv_bool(&ctx->meta.final, val);
-
- ini_getval(ini, "meta", "based_on", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->meta.based_on, val);
+ ctx->meta.version = ini_getval_str(ini, "meta", "version", &err);
+ ctx->meta.name = ini_getval_str(ini, "meta", "name", &err);
+ ctx->meta.rc = ini_getval_int(ini, "meta", "rc", &err);
+ ctx->meta.final = ini_getval_bool(ini, "meta", "final", &err);
+ ctx->meta.based_on = ini_getval_str(ini, "meta", "based_on", &err);
if (!ctx->meta.python) {
- ini_getval(ini, "meta", "python", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->meta.python, val);
+ ctx->meta.python = ini_getval_str(ini, "meta", "python", &err);
guard_free(ctx->meta.python_compact);
ctx->meta.python_compact = to_short_version(ctx->meta.python);
} else {
ini_setval(&ini, INI_SETVAL_REPLACE, "meta", "python", ctx->meta.python);
}
- ini_getval_required(ini, "conda", "installer_name", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->conda.installer_name, val);
-
- ini_getval_required(ini, "conda", "installer_version", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->conda.installer_version, val);
-
- ini_getval_required(ini, "conda", "installer_platform", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->conda.installer_platform, val);
+ ctx->conda.installer_name = ini_getval_str(ini, "conda", "installer_name", &err);
+ ctx->conda.installer_version = ini_getval_str(ini, "conda", "installer_version", &err);
+ ctx->conda.installer_platform = ini_getval_str(ini, "conda", "installer_platform", &err);
+ ctx->conda.installer_arch = ini_getval_str(ini, "conda", "installer_arch", &err);
+ ctx->conda.installer_baseurl = ini_getval_str(ini, "conda", "installer_baseurl", &err);
+ ctx->conda.conda_packages = ini_getval_strlist(ini, "conda", "conda_packages", " "LINE_SEP, &err);
- ini_getval_required(ini, "conda", "installer_arch", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->conda.installer_arch, val);
-
- ini_getval_required(ini, "conda", "installer_baseurl", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->conda.installer_baseurl, val);
-
- ini_getval(ini, "conda", "conda_packages", INIVAL_TYPE_STR_ARRAY, &val);
- conv_strlist(&ctx->conda.conda_packages, LINE_SEP, val);
+ if (ctx->conda.conda_packages->data && ctx->conda.conda_packages->data[0] && strpbrk(ctx->conda.conda_packages->data[0], " \t")) {
+ normalize_space(ctx->conda.conda_packages->data[0]);
+ replace_text(ctx->conda.conda_packages->data[0], " ", LINE_SEP, 0);
+ char *pip_packages_replacement = join(ctx->conda.conda_packages->data, LINE_SEP);
+ ini_setval(&ini, INI_SETVAL_REPLACE, "conda", "conda_packages", pip_packages_replacement);
+ guard_free(pip_packages_replacement);
+ guard_strlist_free(&ctx->conda.conda_packages);
+ ctx->conda.conda_packages = ini_getval_strlist(ini, "conda", "conda_packages", LINE_SEP, &err);
+ }
for (size_t i = 0; i < strlist_count(ctx->conda.conda_packages); i++) {
char *pkg = strlist_item(ctx->conda.conda_packages, i);
- if (strpbrk(pkg, ";#")) {
+ if (strpbrk(pkg, ";#") || isempty(pkg)) {
strlist_remove(ctx->conda.conda_packages, i);
}
}
- ini_getval(ini, "conda", "pip_packages", INIVAL_TYPE_STR_ARRAY, &val);
- conv_strlist(&ctx->conda.pip_packages, LINE_SEP, val);
+ ctx->conda.pip_packages = ini_getval_strlist(ini, "conda", "pip_packages", LINE_SEP, &err);
+ if (ctx->conda.pip_packages->data && ctx->conda.pip_packages->data[0] && strpbrk(ctx->conda.pip_packages->data[0], " \t")) {
+ normalize_space(ctx->conda.pip_packages->data[0]);
+ replace_text(ctx->conda.pip_packages->data[0], " ", LINE_SEP, 0);
+ char *pip_packages_replacement = join(ctx->conda.pip_packages->data, LINE_SEP);
+ ini_setval(&ini, INI_SETVAL_REPLACE, "conda", "pip_packages", pip_packages_replacement);
+ guard_free(pip_packages_replacement);
+ guard_strlist_free(&ctx->conda.pip_packages);
+ ctx->conda.pip_packages = ini_getval_strlist(ini, "conda", "pip_packages", LINE_SEP, &err);
+ }
for (size_t i = 0; i < strlist_count(ctx->conda.pip_packages); i++) {
char *pkg = strlist_item(ctx->conda.pip_packages, i);
- if (strpbrk(pkg, ";#")) {
+ if (strpbrk(pkg, ";#") || isempty(pkg)) {
strlist_remove(ctx->conda.pip_packages, i);
}
}
@@ -599,150 +547,95 @@ static int populate_delivery_ini(struct Delivery *ctx) {
}
for (size_t z = 0, i = 0; i < ini->section_count; i++) {
- if (startswith(ini->section[i]->key, "test:")) {
+ char *section_name = ini->section[i]->key;
+ if (startswith(section_name, "test:")) {
+ struct Test *test = &ctx->tests[z];
val.as_char_p = strchr(ini->section[i]->key, ':') + 1;
if (val.as_char_p && isempty(val.as_char_p)) {
return 1;
}
- conv_str(&ctx->tests[z].name, val);
-
- ini_getval(ini, ini->section[i]->key, "version", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->tests[z].version, val);
-
- ini_getval_required(ini, ini->section[i]->key, "repository", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->tests[z].repository, val);
-
- ini_getval_required(ini, ini->section[i]->key, "script", INIVAL_TYPE_STR, &val);
- conv_str_noexpand(&ctx->tests[z].script, val);
-
- ini_getval(ini, ini->section[i]->key, "repository_remove_tags", INIVAL_TYPE_STR_ARRAY, &val);
- conv_strlist(&ctx->tests[z].repository_remove_tags, LINE_SEP, val);
-
- ini_getval(ini, ini->section[i]->key, "build_recipe", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->tests[z].build_recipe, val);
-
- ini_getval(ini, ini->section[i]->key, "runtime", INIVAL_TO_LIST, &val);
- conv_strlist(&ctx->tests[z].runtime.environ, LINE_SEP, val);
+ conv_str(&test->name, val);
+
+ test->version = ini_getval_str(ini, section_name, "version", &err);
+ test->repository = ini_getval_str(ini, section_name, "repository", &err);
+ test->script = ini_getval_str(ini, section_name, "script", &err);
+ test->repository_remove_tags = ini_getval_strlist(ini, section_name, "repository_remove_tags", LINE_SEP, &err);
+ test->build_recipe = ini_getval_str(ini, section_name, "build_recipe", &err);
+ test->runtime.environ = ini_getval_strlist(ini, section_name, "runtime", LINE_SEP, &err);
z++;
}
}
for (size_t z = 0, i = 0; i < ini->section_count; i++) {
- if (startswith(ini->section[i]->key, "deploy:artifactory")) {
+ char *section_name = ini->section[i]->key;
+ struct Deploy *deploy = &ctx->deploy;
+ if (startswith(section_name, "deploy:artifactory")) {
+ struct JFrog *jfrog = &deploy->jfrog[z];
// Artifactory base configuration
- ini_getval(ini, ini->section[i]->key, "workaround_parent_only", INIVAL_TYPE_BOOL, &val);
- conv_bool(&ctx->deploy.jfrog[z].upload_ctx.workaround_parent_only, val);
-
- ini_getval(ini, ini->section[i]->key, "exclusions", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->deploy.jfrog[z].upload_ctx.exclusions, val);
-
- ini_getval(ini, ini->section[i]->key, "explode", INIVAL_TYPE_BOOL, &val);
- conv_bool(&ctx->deploy.jfrog[z].upload_ctx.explode, val);
-
- ini_getval(ini, ini->section[i]->key, "recursive", INIVAL_TYPE_BOOL, &val);
- conv_bool(&ctx->deploy.jfrog[z].upload_ctx.recursive, val);
-
- ini_getval(ini, ini->section[i]->key, "retries", INIVAL_TYPE_INT, &val);
- conv_int(&ctx->deploy.jfrog[z].upload_ctx.retries, val);
-
- ini_getval(ini, ini->section[i]->key, "retry_wait_time", INIVAL_TYPE_INT, &val);
- conv_int(&ctx->deploy.jfrog[z].upload_ctx.retry_wait_time, val);
- ini_getval(ini, ini->section[i]->key, "detailed_summary", INIVAL_TYPE_BOOL, &val);
- conv_bool(&ctx->deploy.jfrog[z].upload_ctx.detailed_summary, val);
-
- ini_getval(ini, ini->section[i]->key, "quiet", INIVAL_TYPE_BOOL, &val);
- conv_bool(&ctx->deploy.jfrog[z].upload_ctx.quiet, val);
-
- ini_getval(ini, ini->section[i]->key, "regexp", INIVAL_TYPE_BOOL, &val);
- conv_bool(&ctx->deploy.jfrog[z].upload_ctx.regexp, val);
-
- ini_getval(ini, ini->section[i]->key, "spec", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->deploy.jfrog[z].upload_ctx.spec, val);
-
- ini_getval(ini, ini->section[i]->key, "flat", INIVAL_TYPE_BOOL, &val);
- conv_bool(&ctx->deploy.jfrog[z].upload_ctx.flat, val);
-
- ini_getval(ini, ini->section[i]->key, "repo", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->deploy.jfrog[z].repo, val);
-
- ini_getval(ini, ini->section[i]->key, "dest", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->deploy.jfrog[z].dest, val);
-
- ini_getval(ini, ini->section[i]->key, "files", INIVAL_TYPE_STR_ARRAY, &val);
- conv_strlist(&ctx->deploy.jfrog[z].files, LINE_SEP, val);
+ jfrog->upload_ctx.workaround_parent_only = ini_getval_bool(ini, section_name, "workaround_parent_only", &err);
+ jfrog->upload_ctx.exclusions = ini_getval_str(ini, section_name, "exclusions", &err);
+ jfrog->upload_ctx.explode = ini_getval_bool(ini, section_name, "explode", &err);
+ jfrog->upload_ctx.recursive = ini_getval_bool(ini, section_name, "recursive", &err);
+ jfrog->upload_ctx.retries = ini_getval_int(ini, section_name, "retries", &err);
+ jfrog->upload_ctx.retry_wait_time = ini_getval_int(ini, section_name, "retry_wait_time", &err);
+ jfrog->upload_ctx.detailed_summary = ini_getval_bool(ini, section_name, "detailed_summary", &err);
+ jfrog->upload_ctx.quiet = ini_getval_bool(ini, section_name, "quiet", &err);
+ jfrog->upload_ctx.regexp = ini_getval_bool(ini, section_name, "regexp", &err);
+ jfrog->upload_ctx.spec = ini_getval_str(ini, section_name, "spec", &err);
+ jfrog->upload_ctx.flat = ini_getval_bool(ini, section_name, "flat", &err);
+ jfrog->repo = ini_getval_str(ini, section_name, "repo", &err);
+ jfrog->dest = ini_getval_str(ini, section_name, "dest", &err);
+ jfrog->files = ini_getval_strlist(ini, section_name, "dest", LINE_SEP, &err);
z++;
}
}
for (size_t i = 0; i < ini->section_count; i++) {
+ char *section_name = ini->section[i]->key;
+ struct Deploy *deploy = &ctx->deploy;
if (startswith(ini->section[i]->key, "deploy:docker")) {
- ini_getval(ini, ini->section[i]->key, "registry", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->deploy.docker.registry, val);
-
- ini_getval(ini, ini->section[i]->key, "image_compression", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->deploy.docker.image_compression, val);
+ struct Docker *docker = &deploy->docker;
- ini_getval(ini, ini->section[i]->key, "test_script", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->deploy.docker.test_script, val);
-
- ini_getval(ini, ini->section[i]->key, "build_args", INIVAL_TYPE_STR_ARRAY, &val);
- conv_strlist(&ctx->deploy.docker.build_args, LINE_SEP, val);
-
- ini_getval(ini, ini->section[i]->key, "tags", INIVAL_TYPE_STR_ARRAY, &val);
- conv_strlist(&ctx->deploy.docker.tags, LINE_SEP, val);
+ docker->registry = ini_getval_str(ini, section_name, "registry", &err);
+ docker->image_compression = ini_getval_str(ini, section_name, "image_compression", &err);
+ docker->test_script = ini_getval_str(ini, section_name, "test_script", &err);
+ docker->build_args = ini_getval_strlist(ini, section_name, "build_args", LINE_SEP, &err);
+ docker->tags = ini_getval_strlist(ini, section_name, "tags", LINE_SEP, &err);
}
}
return 0;
}
static int populate_delivery_cfg(struct Delivery *ctx) {
- union INIVal val;
struct INIFILE *cfg = ctx->_stasis_ini_fp.cfg;
if (!cfg) {
return -1;
}
- ini_getval(cfg, "default", "conda_staging_dir", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->storage.conda_staging_dir, val);
- ini_getval(cfg, "default", "conda_staging_url", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->storage.conda_staging_url, val);
- ini_getval(cfg, "default", "wheel_staging_dir", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->storage.wheel_staging_dir, val);
- ini_getval(cfg, "default", "wheel_staging_url", INIVAL_TYPE_STR, &val);
- conv_str(&ctx->storage.wheel_staging_url, val);
- ini_getval(cfg, "default", "conda_fresh_start", INIVAL_TYPE_BOOL, &val);
- conv_bool(&globals.conda_fresh_start, val);
- // Below can also be toggled by command-line arguments
+ int err = 0;
+ ctx->storage.conda_staging_dir = ini_getval_str(cfg, "default", "conda_staging_dir", &err);
+ ctx->storage.conda_staging_url = ini_getval_str(cfg, "default", "conda_staging_url", &err);
+ ctx->storage.wheel_staging_dir = ini_getval_str(cfg, "default", "wheel_staging_dir", &err);
+ ctx->storage.wheel_staging_url = ini_getval_str(cfg, "default", "wheel_staging_url", &err);
+ globals.conda_fresh_start = ini_getval_bool(cfg, "default", "conda_fresh_start", &err);
if (!globals.continue_on_error) {
- ini_getval(cfg, "default", "continue_on_error", INIVAL_TYPE_BOOL, &val);
- conv_bool(&globals.continue_on_error, val);
- }
- // Below can also be toggled by command-line arguments
- if (!globals.always_update_base_environment) {
- ini_getval(cfg, "default", "always_update_base_environment", INIVAL_TYPE_BOOL, &val);
- conv_bool(&globals.always_update_base_environment, val);
- }
- ini_getval(cfg, "default", "conda_install_prefix", INIVAL_TYPE_STR, &val);
- conv_str(&globals.conda_install_prefix, val);
- ini_getval(cfg, "default", "conda_packages", INIVAL_TYPE_STR_ARRAY, &val);
- conv_strlist(&globals.conda_packages, LINE_SEP, val);
- ini_getval(cfg, "default", "pip_packages", INIVAL_TYPE_STR_ARRAY, &val);
- conv_strlist(&globals.pip_packages, LINE_SEP, val);
- // Configure jfrog cli downloader
- ini_getval(cfg, "jfrog_cli_download", "url", INIVAL_TYPE_STR, &val);
- conv_str(&globals.jfrog.jfrog_artifactory_base_url, val);
- ini_getval(cfg, "jfrog_cli_download", "product", INIVAL_TYPE_STR, &val);
- conv_str(&globals.jfrog.jfrog_artifactory_product, val);
- ini_getval(cfg, "jfrog_cli_download", "version_series", INIVAL_TYPE_STR, &val);
- conv_str(&globals.jfrog.cli_major_ver, val);
- ini_getval(cfg, "jfrog_cli_download", "version", INIVAL_TYPE_STR, &val);
- conv_str(&globals.jfrog.version, val);
- ini_getval(cfg, "jfrog_cli_download", "filename", INIVAL_TYPE_STR, &val);
- conv_str(&globals.jfrog.remote_filename, val);
- ini_getval(cfg, "deploy:artifactory", "url", INIVAL_TYPE_STR, &val);
- conv_str(&globals.jfrog.url, val);
- ini_getval(cfg, "deploy:artifactory", "repo", INIVAL_TYPE_STR, &val);
- conv_str(&globals.jfrog.repo, val);
+ globals.continue_on_error = ini_getval_bool(cfg, "default", "continue_on_error", &err);
+ }
+ if (globals.always_update_base_environment) {
+ globals.always_update_base_environment = ini_getval_bool(cfg, "default", "always_update_base_environment", &err);
+ }
+ globals.conda_install_prefix = ini_getval_str(cfg, "default", "conda_install_prefix", &err);
+ globals.conda_packages = ini_getval_strlist(cfg, "default", "conda_packages", LINE_SEP, &err);
+ globals.pip_packages = ini_getval_strlist(cfg, "default", "pip_packages", LINE_SEP, &err);
+
+ globals.jfrog.jfrog_artifactory_base_url = ini_getval_str(cfg, "jfrog_cli_download", "url", &err);
+ globals.jfrog.jfrog_artifactory_product = ini_getval_str(cfg, "jfrog_cli_download", "product", &err);
+ globals.jfrog.cli_major_ver = ini_getval_str(cfg, "jfrog_cli_download", "version_series", &err);
+ globals.jfrog.version = ini_getval_str(cfg, "jfrog_cli_download", "version", &err);
+ globals.jfrog.remote_filename = ini_getval_str(cfg, "jfrog_cli_download", "filename", &err);
+ globals.jfrog.url = ini_getval_str(cfg, "deploy:artifactory", "url", &err);
+ globals.jfrog.repo = ini_getval_str(cfg, "deploy:artifactory", "repo", &err);
+
return 0;
}
@@ -1201,7 +1094,7 @@ static const struct Test *requirement_from_test(struct Delivery *ctx, const char
result = NULL;
for (size_t i = 0; i < sizeof(ctx->tests) / sizeof(ctx->tests[0]); i++) {
- if (strstr(name, ctx->tests[i].name)) {
+ if (ctx->tests[i].name && strstr(name, ctx->tests[i].name)) {
result = &ctx->tests[i];
break;
}
@@ -1336,7 +1229,7 @@ int delivery_get_installer(struct Delivery *ctx, char *installer_url) {
sprintf(script_path, "%s/%s", ctx->storage.tmpdir, installer);
if (access(script_path, F_OK)) {
// Script doesn't exist
- int fetch_status = download(installer_url, script_path, NULL);
+ long fetch_status = download(installer_url, script_path, NULL);
if (HTTP_ERROR(fetch_status) || fetch_status < 0) {
// download failed
return -1;
@@ -2046,8 +1939,8 @@ int delivery_mission_render_files(struct Delivery *ctx) {
sprintf(data.src, "%s/%s/%s", ctx->storage.mission_dir, ctx->meta.mission, val.as_char_p);
msg(STASIS_MSG_L2, "%s\n", data.src);
- ini_getval_required(cfg, section_name, "destination", INIVAL_TYPE_STR, &val);
- conv_str(&data.dest, val);
+ int err = 0;
+ data.dest = ini_getval_str(cfg, section_name, "destination", &err);
char *contents;
struct stat st;
diff --git a/src/ini.c b/src/ini.c
index 6ce54ac..bddfdcd 100644
--- a/src/ini.c
+++ b/src/ini.c
@@ -122,7 +122,27 @@ int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, uni
result->as_char_p = NULL;
return -1;
}
+
+ char *render = tpl_render(data->value);
+ if (render) {
+ guard_free(data->value);
+ data->value = render;
+ }
+ lstrip(data->value);
+
switch (type) {
+ case INIVAL_TYPE_CHAR:
+ result->as_char = (char) strtol(data->value, NULL, 10);
+ break;
+ case INIVAL_TYPE_UCHAR:
+ result->as_uchar = (unsigned char) strtoul(data->value, NULL, 10);
+ break;
+ case INIVAL_TYPE_SHORT:
+ result->as_short = (short) strtol(data->value, NULL, 10);
+ break;
+ case INIVAL_TYPE_USHORT:
+ result->as_ushort = (unsigned short) strtoul(data->value, NULL, 10);
+ break;
case INIVAL_TYPE_INT:
result->as_int = (int) strtol(data->value, NULL, 10);
break;
@@ -148,17 +168,26 @@ int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, uni
result->as_float = (float) strtod(data->value, NULL);
break;
case INIVAL_TYPE_STR:
- result->as_char_p = lstrip(data->value);
+ result->as_char_p = strdup(data->value);
+ if (!result->as_char_p) {
+ return -1;
+ }
+ lstrip(result->as_char_p);
break;
case INIVAL_TYPE_STR_ARRAY:
strcpy(tbufp, data->value);
- *data->value = '\0';
+ char *value = NULL;
+ size_t lines = num_chars(tbufp, '\n');
+ value = calloc(strlen(tbufp) + lines + 1, sizeof(*value));
+ if (!value) {
+ return -1;
+ }
while ((token = strsep(&tbufp, "\n")) != NULL) {
lstrip(token);
- strcat(data->value, token);
- strcat(data->value, "\n");
+ strcat(value, token);
+ strcat(value, "\n");
}
- result->as_char_p = data->value;
+ result->as_char_p = value;
break;
case INIVAL_TYPE_BOOL:
result->as_bool = false;
@@ -175,6 +204,107 @@ int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, uni
return 0;
}
+#define getval_returns(t) return result.t
+#define getval_setup(t) \
+ union INIVal result; \
+ int state_local = 0; \
+ state_local = ini_getval(ini, section_name, key, t, &result); \
+ if (state != NULL) { \
+ *state = state_local; \
+ }
+
+int ini_getval_int(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_INT)
+ getval_returns(as_int);
+}
+
+unsigned int ini_getval_uint(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_UINT)
+ getval_returns(as_uint);
+}
+
+long ini_getval_long(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_LONG)
+ getval_returns(as_long);
+}
+
+unsigned long ini_getval_ulong(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_ULONG)
+ getval_returns(as_ulong);
+}
+
+long long ini_getval_llong(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_LLONG)
+ getval_returns(as_llong);
+}
+
+unsigned long long ini_getval_ullong(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_ULLONG)
+ getval_returns(as_ullong);
+}
+
+float ini_getval_float(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_FLOAT)
+ getval_returns(as_float);
+}
+
+double ini_getval_double(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_DOUBLE)
+ getval_returns(as_double);
+}
+
+bool ini_getval_bool(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_BOOL)
+ getval_returns(as_bool);
+}
+
+short ini_getval_short(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_SHORT)
+ getval_returns(as_short);
+}
+
+unsigned short ini_getval_ushort(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_USHORT)
+ getval_returns(as_ushort);
+}
+
+char ini_getval_char(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_CHAR)
+ getval_returns(as_char);
+}
+
+unsigned char ini_getval_uchar(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_UCHAR)
+ getval_returns(as_uchar);
+}
+
+char *ini_getval_char_p(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_STR)
+ getval_returns(as_char_p);
+}
+
+char *ini_getval_str(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ return ini_getval_char_p(ini, section_name, key, state);
+}
+
+char **ini_getval_char_array_p(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_STR_ARRAY)
+ getval_returns(as_char_array_p);
+}
+
+char **ini_getval_str_array(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ return ini_getval_char_array_p(ini, section_name, key, state);
+}
+
+struct StrList *ini_getval_strlist(struct INIFILE *ini, char *section_name, char *key, char *tok, int *state) {
+ getval_setup(INIVAL_TYPE_STR_ARRAY)
+ struct StrList *list;
+ list = strlist_init();
+ strlist_append_tokenize(list, result.as_char_p, tok);
+ guard_free(result.as_char_p);
+ return list;
+}
+
int ini_data_append(struct INIFILE **ini, char *section_name, char *key, char *value) {
struct INISection *section = ini_section_search(ini, INI_SEARCH_EXACT, section_name);
if (section == NULL) {
@@ -292,13 +422,18 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) {
char *render = NULL;
if (mode == INI_WRITE_PRESERVE) {
render = tpl_render(parts[p]);
+ replace_text(render, "\n", "\n ", 0);
} else {
render = parts[p];
}
if (p == 0) {
sprintf(outvalue, "%s" LINE_SEP, render);
} else {
- sprintf(outvalue + strlen(outvalue), " %s" LINE_SEP, render);
+ if (!isspace(render[0])) {
+ sprintf(outvalue + strlen(outvalue), " %s" LINE_SEP, render);
+ } else {
+ sprintf(outvalue + strlen(outvalue), "%s" LINE_SEP, render);
+ }
}
if (mode == INI_WRITE_PRESERVE) {
guard_free(render);
@@ -307,9 +442,9 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) {
GENERIC_ARRAY_FREE(parts);
strip(outvalue);
strcat(outvalue, LINE_SEP);
- fprintf(*stream, "%s=%s%s", ini->section[x]->data[y]->key, parts_total > 1 ? LINE_SEP " " : "", outvalue);
+ fprintf(*stream, "%s = %s%s", ini->section[x]->data[y]->key, ini->section[x]->data[y]->type_hint || parts_total > 1 ? LINE_SEP " " : "", outvalue);
} else {
- fprintf(*stream, "%s=%s", ini->section[x]->data[y]->key, ini->section[x]->data[y]->value);
+ fprintf(*stream, "%s = %s", ini->section[x]->data[y]->key, ini->section[x]->data[y]->value);
}
}
fprintf(*stream, LINE_SEP);
@@ -352,6 +487,13 @@ void ini_free(struct INIFILE **ini) {
guard_free((*ini));
}
+static void ini_data_set_hint(struct INIFILE **ini, char *section_name, char *key, int hint) {
+ struct INIData *data = ini_data_get(*ini, section_name, key);
+ if (data) {
+ data->type_hint = hint;
+ }
+}
+
struct INIFILE *ini_open(const char *filename) {
FILE *fp;
char line[STASIS_BUFSIZ] = {0};
@@ -440,8 +582,10 @@ struct INIFILE *ini_open(const char *filename) {
ini_section_create(&ini, section_name);
// Record the name of the section. This is used until another section is found.
+ memset(current_section, 0, sizeof(current_section));
strcpy(current_section, section_name);
guard_free(section_name);
+ memset(line, 0, sizeof(line));
continue;
}
@@ -473,6 +617,7 @@ struct INIFILE *ini_open(const char *filename) {
}
if (isempty(value)) {
//printf("%s is probably long raw data\n", key);
+ ini_data_set_hint(&ini, current_section, key, INIVAL_TYPE_STR_ARRAY);
multiline_data = 1;
no_data = 1;
} else {
@@ -484,15 +629,14 @@ struct INIFILE *ini_open(const char *filename) {
strcpy(key, key_last);
strcpy(value, line);
}
+ memset(line, 0, sizeof(line));
// Store key value pair in section's data array
if (strlen(key)) {
lstrip(key);
strip(key);
unquote(value);
- lstrip(value);
if (!multiline_data) {
- strip(value);
reading_value = 0;
ini_data_append(&ini, current_section, key, value);
continue;
diff --git a/src/utils.c b/src/utils.c
index 2143c52..f721581 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -579,6 +579,7 @@ int xml_pretty_print_in_place(const char *filename, const char *pretty_print_pro
goto pretty_print_failed;
}
+ fclose(fp);
guard_free(tempfile);
guard_free(result);
return 0;
@@ -638,24 +639,31 @@ int fix_tox_conf(const char *filename, char **result) {
for (size_t i = 0; i < toxini->section_count; i++) {
struct INISection *section = toxini->section[i];
if (section) {
- if (startswith(section->key, "testenv")) {
- for (size_t k = 0; k < section->data_count; k++) {
- struct INIData *data = section->data[k];
- if (data) {
- if (!strcmp(data->key, "commands") && (startswith(data->value, "pytest") && !strstr(data->value, "{posargs}"))) {
- strip(data->value);
+ char *section_name = section->key;
+ for (size_t k = 0; k < section->data_count; k++) {
+ struct INIData *data = section->data[k];
+ if (data) {
+ int err = 0;
+ char *key = data->key;
+ char *value = ini_getval_str(toxini, section->key, data->key, &err);
+ if (key && value) {
+ if (startswith(value, "pytest") && !strstr(value, "{posargs}")) {
+ strip(value);
char *tmp;
- tmp = realloc(data->value, strlen(data->value) + strlen(with_posargs) + 1);
+ tmp = realloc(value, strlen(value) + strlen(with_posargs) + 1);
if (!tmp) {
- SYSERROR("failed to increase data->value size to +%zu bytes", strlen(data->value) + strlen(with_posargs) + 1);
+ SYSERROR("failed to increase size to +%zu bytes",
+ strlen(value) + strlen(with_posargs) + 1);
guard_free(*result);
return -1;
- } else if (tmp != data->value) {
- data->value = tmp;
+ } else if (tmp != value) {
+ value = tmp;
}
- strcat(data->value, with_posargs);
+ strcat(value, with_posargs);
+ ini_setval(&toxini, INI_SETVAL_REPLACE, section_name, key, value);
}
}
+ guard_free(value);
}
}
}
diff --git a/tests/test_utils.c b/tests/test_utils.c
index 4b19604..9090b05 100644
--- a/tests/test_utils.c
+++ b/tests/test_utils.c
@@ -71,6 +71,7 @@ void test_fix_tox_conf() {
char **lines = file_readlines(result, 0, 0, NULL);
STASIS_ASSERT(strstr_array(lines, expected) != NULL, "{posargs} not found in result");
+ GENERIC_ARRAY_FREE(lines);
remove(result);
guard_free(result);
@@ -106,6 +107,7 @@ void test_xml_pretty_print_in_place() {
STASIS_ASSERT(false, "failed to consume formatted xml file contents");
}
STASIS_ASSERT(strcmp(expected, buf) == 0, "xml file was not reformatted");
+ fclose(fp);
}
void test_path_store() {