aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@users.noreply.github.com>2024-06-24 11:23:26 -0400
committerGitHub <noreply@github.com>2024-06-24 11:23:26 -0400
commitabe87056faa6ed02aff3bbf77c1fd78b713a0864 (patch)
treee97960b2393979e6c05bab40c610083e5925cd0a
parent27c475ccd857ca6f75605938ee0d83e13973672d (diff)
downloadstasis-abe87056faa6ed02aff3bbf77c1fd78b713a0864.tar.gz
Pass .ci_support/plat_arch_.yaml to conda-build (#8)
* Pass .ci_support/plat_arch_.yaml to conda-build * Fixes a few outstanding leaks in delivery context * Move micromamba function out of stasis_indexer.c * Adjust code in the indexer to accommodate the move. The function now expects a MicromambaInfo structure as its first argument. * Add missing warning message * User is informed when pandoc is not available for HTML page generation * Initialize workdir_template string to zero * Add micromamba program to runtime PATH * Expose storage.tools_dir to template engine * Remove dead code * Fix wording in comment * Fix conda-forge builds * Pass their .ci_support configurations to conda-build in order to fully set up their build runtime environment * Add get_cpu_count() * Exposes STASIS_CPU_COUNT and CPU_COUNT to the runtime environment * Implements conda reactivation template string * {{ workaround.conda_reactivate }} * This is useful to call after installing any conda packages within a test.script * Fix conda runtime inside of test.script * This ensures conda and mamba are fully initialized. * Previous behavior only placed the commands on the PATH but didn't provide any shell macros (i.e. undefined behavior) * Document CPU_COUNT and workaround.conda_reactivate
-rw-r--r--README.md88
-rw-r--r--include/conda.h14
-rw-r--r--include/core.h1
-rw-r--r--include/utils.h6
-rw-r--r--src/conda.c62
-rw-r--r--src/delivery.c77
-rw-r--r--src/globals.c1
-rw-r--r--src/stasis_indexer.c80
-rw-r--r--src/stasis_main.c2
-rw-r--r--src/utils.c7
10 files changed, 226 insertions, 112 deletions
diff --git a/README.md b/README.md
index b1d6d25..c3e9db6 100644
--- a/README.md
+++ b/README.md
@@ -143,20 +143,21 @@ stasis mydelivery.ini
## Environment variables
-| Name | Purpose |
-|------------------------------|-------------------------------------------------------|
-| TMPDIR | Change default path to store temporary data |
-| STASIS_ROOT | Change default path to write STASIS's data |
-| STASIS_SYSCONFDIR | Change default path to search for configuration files |
-| STASIS_JF_ARTIFACTORY_URL | Artifactory service URL (ending in `/artifactory`) |
-| STASIS_JF_ACCESS_TOKEN | Artifactory Access Token |
-| STASIS_JF_USER | Artifactory username |
-| STASIS_JF_PASSWORD | Artifactory password |
-| STASIS_JF_SSH_KEY_PATH | Path to SSH public key file |
-| STASIS_JF_SSH_PASSPHRASE | Password associated with SSH public key file |
-| STASIS_JF_CLIENT_CERT_CERT_PATH | Path to OpenSSL cert files |
-| STASIS_JF_CLIENT_CERT_KEY_PATH | OpenSSL key file (in cert path) |
-| STASIS_JF_REPO | Artifactory "generic" repository to write to |
+| Name | Purpose |
+|-------------------------------------|-------------------------------------------------------|
+| TMPDIR | Change default path to store temporary data |
+| STASIS_ROOT | Change default path to write STASIS's data |
+| STASIS_SYSCONFDIR | Change default path to search for configuration files |
+| STASIS_CPU_COUNT (alias: CPU_COUNT) | Number of available CPUS |
+| STASIS_JF_ARTIFACTORY_URL | Artifactory service URL (ending in `/artifactory`) |
+| STASIS_JF_ACCESS_TOKEN | Artifactory Access Token |
+| STASIS_JF_USER | Artifactory username |
+| STASIS_JF_PASSWORD | Artifactory password |
+| STASIS_JF_SSH_KEY_PATH | Path to SSH public key file |
+| STASIS_JF_SSH_PASSPHRASE | Password associated with SSH public key file |
+| STASIS_JF_CLIENT_CERT_CERT_PATH | Path to OpenSSL cert files |
+| STASIS_JF_CLIENT_CERT_KEY_PATH | OpenSSL key file (in cert path) |
+| STASIS_JF_REPO | Artifactory "generic" repository to write to |
# Variable expansion
@@ -164,35 +165,36 @@ stasis mydelivery.ini
Template strings can be accessed using the `{{ subject.key }}` notation in any STASIS configuration file.
-| Name | Purpose |
-|----------------------------|------------------------------------------------------------------------------------------------------------------------|
-| meta.name | Delivery name |
-| meta.version | Delivery version |
-| meta.codename | Delivery codename |
-| meta.mission | Delivery mission |
-| meta.python | Python version (e.g. 3.11) |
-| meta.python_compact | Python (e.g. 311) |
-| info.time_str_epoch | UNIX Epoch timestamp |
-| info.release_name | Rendered delivery release name |
-| info.build_name | Rendered delivery build name |
-| info.build_number | Rendered delivery build number |
-| storage.tmpdir | Ohymcal temp directory |
-| storage.delivery_dir | STASIS delivery output directory |
-| storage.results_dir | STASIS test results directory |
-| storage.conda_artifact_dir | STASIS conda package directory |
-| storage.wheel_artifact_dir | STASIS wheel package directory |
-| storage.build_sources_dir | STASIS sources directory |
-| storage.build_docker_dir | STASIS docker directory |
-| conda.installer_name | Conda distribution name |
-| conda.installer_version | Conda distribution version |
-| conda.installer_platform | Conda target platform |
-| conda.installer_arch | Conda target architecture |
-| conda.installer_baseurl | Conda installer URL |
-| system.arch | System CPU Architecture |
-| system.platform | System Platform (OS) |
-| deploy.docker.registry | Docker registry |
-| deploy.jfrog.repo | Artifactory destination repository |
-| workaround.tox_posargs | Return populated `-c` and `--root` tox arguments.<br/>Force-enables positional arguments in tox's command line parser. |
+| Name | Purpose |
+|-----------------------------|-------------------------------------------------------------------------------------------------------------------------|
+| meta.name | Delivery name |
+| meta.version | Delivery version |
+| meta.codename | Delivery codename |
+| meta.mission | Delivery mission |
+| meta.python | Python version (e.g. 3.11) |
+| meta.python_compact | Python (e.g. 311) |
+| info.time_str_epoch | UNIX Epoch timestamp |
+| info.release_name | Rendered delivery release name |
+| info.build_name | Rendered delivery build name |
+| info.build_number | Rendered delivery build number |
+| storage.tmpdir | Ohymcal temp directory |
+| storage.delivery_dir | STASIS delivery output directory |
+| storage.results_dir | STASIS test results directory |
+| storage.conda_artifact_dir | STASIS conda package directory |
+| storage.wheel_artifact_dir | STASIS wheel package directory |
+| storage.build_sources_dir | STASIS sources directory |
+| storage.build_docker_dir | STASIS docker directory |
+| conda.installer_name | Conda distribution name |
+| conda.installer_version | Conda distribution version |
+| conda.installer_platform | Conda target platform |
+| conda.installer_arch | Conda target architecture |
+| conda.installer_baseurl | Conda installer URL |
+| system.arch | System CPU Architecture |
+| system.platform | System Platform (OS) |
+| deploy.docker.registry | Docker registry |
+| deploy.jfrog.repo | Artifactory destination repository |
+| workaround.tox_posargs | Return populated `-c` and `--root` tox arguments.<br/>Force-enables positional arguments in tox's command line parser. |
+| workaround.conda_reactivate | Reinitialize the conda runtime environment.<br/>Use this after calling `conda install` from within a `[test:*].script`. |
The template engine also provides an interface to environment variables using the `{{ env:VARIABLE_NAME }}` notation.
diff --git a/include/conda.h b/include/conda.h
index 086a842..cea3f02 100644
--- a/include/conda.h
+++ b/include/conda.h
@@ -8,6 +8,20 @@
#define CONDA_INSTALL_PREFIX "conda"
+struct MicromambaInfo {
+ char *micromamba_prefix;
+ char *conda_prefix;
+};
+
+/**
+ * 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
diff --git a/include/core.h b/include/core.h
index 1a7ddea..ac9ae2f 100644
--- a/include/core.h
+++ b/include/core.h
@@ -72,6 +72,7 @@ struct STASIS_GLOBAL {
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;
diff --git a/include/utils.h b/include/utils.h
index 2c80e77..eee2e30 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -351,4 +351,10 @@ int redact_sensitive(const char **to_redact, size_t to_redact_size, char *src, c
*/
struct StrList *listdir(const char *path);
+/**
+ * Get CPU count
+ * @return CPU count on success, zero on error
+ */
+long get_cpu_count();
+
#endif //STASIS_UTILS_H
diff --git a/src/conda.c b/src/conda.c
index 342b6af..1e8b03f 100644
--- a/src/conda.c
+++ b/src/conda.c
@@ -5,6 +5,61 @@
#include <unistd.h>
#include "conda.h"
+int micromamba(struct MicromambaInfo *info, char *command, ...) {
+ struct utsname sys;
+ uname(&sys);
+
+ tolower_s(sys.sysname);
+ if (!strcmp(sys.sysname, "darwin")) {
+ strcpy(sys.sysname, "osx");
+ }
+
+ if (!strcmp(sys.machine, "x86_64")) {
+ strcpy(sys.machine, "64");
+ }
+
+ char url[PATH_MAX];
+ sprintf(url, "https://micro.mamba.pm/api/micromamba/%s-%s/latest", sys.sysname, sys.machine);
+
+ char installer_path[PATH_MAX];
+ sprintf(installer_path, "%s/latest", getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
+
+ if (access(installer_path, F_OK)) {
+ download(url, installer_path, NULL);
+ }
+
+ char mmbin[PATH_MAX];
+ sprintf(mmbin, "%s/micromamba", info->micromamba_prefix);
+
+ if (access(mmbin, F_OK)) {
+ char untarcmd[PATH_MAX];
+ mkdirs(info->micromamba_prefix, 0755);
+ sprintf(untarcmd, "tar -xvf %s -C %s --strip-components=1 bin/micromamba 1>/dev/null", installer_path, info->micromamba_prefix);
+ system(untarcmd);
+ }
+
+ char cmd[STASIS_BUFSIZ];
+ memset(cmd, 0, sizeof(cmd));
+ sprintf(cmd, "%s -r %s -p %s ", mmbin, info->conda_prefix, info->conda_prefix);
+ va_list args;
+ va_start(args, command);
+ vsprintf(cmd + strlen(cmd), command, args);
+ va_end(args);
+
+ mkdirs(info->conda_prefix, 0755);
+
+ char rcpath[PATH_MAX];
+ sprintf(rcpath, "%s/.condarc", info->conda_prefix);
+ touch(rcpath);
+
+ setenv("CONDARC", rcpath, 1);
+ setenv("MAMBA_ROOT_PREFIX", info->conda_prefix, 1);
+ int status = system(cmd);
+ unsetenv("MAMBA_ROOT_PREFIX");
+
+ return status;
+}
+
int python_exec(const char *args) {
char command[PATH_MAX];
memset(command, 0, sizeof(command));
@@ -114,12 +169,12 @@ int conda_activate(const char *root, const char *env_name) {
perror(logfile);
return -1;
}
- int i = 0;
+
while (!feof(fp)) {
char buf[STASIS_BUFSIZ] = {0};
int ch = 0;
size_t z = 0;
- // We are ingesting output from "env -0", can't use fgets()
+ // We are ingesting output from "env -0" and can't use fgets()
// Copy each character into the buffer until we encounter '\0' or EOF
while (z < sizeof(buf) && (ch = (int) fgetc(fp)) != 0) {
if (ch == EOF) {
@@ -141,15 +196,12 @@ int conda_activate(const char *root, const char *env_name) {
}
if (!part[0]) {
msg(STASIS_MSG_WARN | STASIS_MSG_L1, "Invalid environment variable key ignored: '%s'\n", buf);
- i++;
} else if (!part[1]) {
msg(STASIS_MSG_WARN | STASIS_MSG_L1, "Invalid environment variable value ignored: '%s'\n", buf);
- i++;
} else {
setenv(part[0], part[1], 1);
}
GENERIC_ARRAY_FREE(part);
- i++;
}
fclose(fp);
remove(logfile);
diff --git a/src/delivery.c b/src/delivery.c
index e77d41c..278647c 100644
--- a/src/delivery.c
+++ b/src/delivery.c
@@ -162,6 +162,9 @@ void delivery_free(struct Delivery *ctx) {
guard_free(ctx->storage.build_docker_dir);
guard_free(ctx->storage.mission_dir);
guard_free(ctx->storage.docker_artifact_dir);
+ guard_free(ctx->storage.meta_dir);
+ guard_free(ctx->storage.package_dir);
+ guard_free(ctx->storage.cfgdump_dir);
guard_free(ctx->info.time_str_epoch);
guard_free(ctx->info.build_name);
guard_free(ctx->info.build_number);
@@ -186,6 +189,7 @@ void delivery_free(struct Delivery *ctx) {
guard_free(ctx->tests[i].repository);
guard_free(ctx->tests[i].repository_info_ref);
guard_free(ctx->tests[i].repository_info_tag);
+ guard_strlist_free(&ctx->tests[i].repository_remove_tags);
guard_free(ctx->tests[i].script);
guard_free(ctx->tests[i].build_recipe);
// test-specific runtime variables
@@ -349,7 +353,17 @@ int delivery_init_platform(struct Delivery *ctx) {
tolower_s(ctx->system.platform[DELIVERY_PLATFORM_RELEASE]);
}
+ long cpu_count = get_cpu_count();
+ if (!cpu_count) {
+ fprintf(stderr, "Unable to determine CPU count. Falling back to 1.\n");
+ cpu_count = 1;
+ }
+ char ncpus[100] = {0};
+ sprintf(ncpus, "%ld", cpu_count);
+
// Declare some important bits as environment variables
+ setenv("CPU_COUNT", ncpus, 1);
+ setenv("STASIS_CPU_COUNT", ncpus, 1);
setenv("STASIS_ARCH", ctx->system.arch, 1);
setenv("STASIS_PLATFORM", ctx->system.platform[DELIVERY_PLATFORM], 1);
setenv("STASIS_CONDA_ARCH", ctx->system.arch, 1);
@@ -1031,7 +1045,30 @@ int delivery_build_recipes(struct Delivery *ctx) {
}
char command[PATH_MAX];
- sprintf(command, "mambabuild --python=%s .", ctx->meta.python);
+ if (RECIPE_TYPE_CONDA_FORGE == recipe_type) {
+ char arch[STASIS_NAME_MAX] = {0};
+ char platform[STASIS_NAME_MAX] = {0};
+
+ strcpy(platform, ctx->system.platform[DELIVERY_PLATFORM]);
+ if (strstr(platform, "Darwin")) {
+ memset(platform, 0, sizeof(platform));
+ strcpy(platform, "osx");
+ }
+ tolower_s(platform);
+ if (strstr(ctx->system.arch, "arm64")) {
+ strcpy(arch, "arm64");
+ } else if (strstr(ctx->system.arch, "64")) {
+ strcpy(arch, "64");
+ } else {
+ strcat(arch, "32"); // blind guess
+ }
+ tolower_s(arch);
+
+ sprintf(command, "mambabuild --python=%s -m ../.ci_support/%s_%s_.yaml .",
+ ctx->meta.python, platform, arch);
+ } else {
+ sprintf(command, "mambabuild --python=%s .", ctx->meta.python);
+ }
status = conda_exec(command);
if (status) {
return -1;
@@ -1650,6 +1687,13 @@ void delivery_tests_run(struct Delivery *ctx) {
struct Process proc;
memset(&proc, 0, sizeof(proc));
+ if (!globals.workaround.conda_reactivate) {
+ globals.workaround.conda_reactivate = calloc(PATH_MAX, sizeof(*globals.workaround.conda_reactivate));
+ } else {
+ memset(globals.workaround.conda_reactivate, 0, PATH_MAX);
+ }
+ snprintf(globals.workaround.conda_reactivate, PATH_MAX - 1, "\nset +x\neval `conda shell.posix reactivate`\nset -x\n");
+
if (!ctx->tests[0].name) {
msg(STASIS_MSG_WARN | STASIS_MSG_L2, "no tests are defined!\n");
} else {
@@ -1691,7 +1735,7 @@ void delivery_tests_run(struct Delivery *ctx) {
} else {
#if 1
int status;
- char cmd[PATH_MAX];
+ char *cmd = calloc(strlen(ctx->tests[i].script) + STASIS_BUFSIZ, sizeof(*cmd));
msg(STASIS_MSG_L3, "Testing %s\n", ctx->tests[i].name);
memset(&proc, 0, sizeof(proc));
@@ -1711,22 +1755,45 @@ void delivery_tests_run(struct Delivery *ctx) {
}
// enable trace mode before executing each test script
- memset(cmd, 0, sizeof(cmd));
- sprintf(cmd, "set -x ; %s", ctx->tests[i].script);
+ strcpy(cmd, ctx->tests[i].script);
char *cmd_rendered = tpl_render(cmd);
if (cmd_rendered) {
if (strcmp(cmd_rendered, cmd) != 0) {
strcpy(cmd, cmd_rendered);
+ cmd[strlen(cmd_rendered) ? strlen(cmd_rendered) - 1 : 0] = 0;
}
guard_free(cmd_rendered);
}
- status = shell(&proc, cmd);
+ FILE *runner_fp;
+ char *runner_filename = xmkstemp(&runner_fp, "w");
+
+ fprintf(runner_fp, "#!/bin/bash\n"
+ "eval `conda shell.posix reactivate`\n"
+ "set -x\n"
+ "%s\n",
+ cmd);
+ fclose(runner_fp);
+ chmod(runner_filename, 0755);
+
+ puts(cmd);
+ char runner_cmd[PATH_MAX] = {0};
+ sprintf(runner_cmd, "%s", runner_filename);
+ status = shell(&proc, runner_cmd);
if (status) {
msg(STASIS_MSG_ERROR, "Script failure: %s\n%s\n\nExit code: %d\n", ctx->tests[i].name, ctx->tests[i].script, status);
+ remove(runner_filename);
+ popd();
+ guard_free(cmd);
+ tpl_free();
+ delivery_free(ctx);
+ globals_free();
COE_CHECK_ABORT(1, "Test failure");
}
+ guard_free(cmd);
+ remove(runner_filename);
+ guard_free(runner_filename);
if (toxconf) {
remove(toxconf);
diff --git a/src/globals.c b/src/globals.c
index 7ed7c3c..297598f 100644
--- a/src/globals.c
+++ b/src/globals.c
@@ -54,4 +54,5 @@ void globals_free() {
guard_free(globals.jfrog.jfrog_artifactory_product);
guard_free(globals.jfrog.remote_filename);
guard_free(globals.workaround.tox_posargs);
+ guard_free(globals.workaround.conda_reactivate);
}
diff --git a/src/stasis_indexer.c b/src/stasis_indexer.c
index fb231e0..a7b0fce 100644
--- a/src/stasis_indexer.c
+++ b/src/stasis_indexer.c
@@ -200,57 +200,6 @@ struct Delivery **get_latest_deliveries(struct Delivery ctx[], size_t nelem) {
return result;
}
-int micromamba(const char *write_to, const char *prefix, char *command, ...) {
- struct utsname sys;
- uname(&sys);
-
- tolower_s(sys.sysname);
- if (!strcmp(sys.sysname, "darwin")) {
- strcpy(sys.sysname, "osx");
- }
-
- if (!strcmp(sys.machine, "x86_64")) {
- strcpy(sys.machine, "64");
- }
-
- char url[PATH_MAX];
- sprintf(url, "https://micro.mamba.pm/api/micromamba/%s-%s/latest", sys.sysname, sys.machine);
- if (access("latest", F_OK)) {
- download(url, "latest", NULL);
- }
-
- char mmbin[PATH_MAX];
- sprintf(mmbin, "%s/micromamba", write_to);
-
- if (access(mmbin, F_OK)) {
- char untarcmd[PATH_MAX];
- mkdirs(write_to, 0755);
- sprintf(untarcmd, "tar -xvf latest -C %s --strip-components=1 bin/micromamba 1>/dev/null", write_to);
- system(untarcmd);
- }
-
- char cmd[STASIS_BUFSIZ];
- memset(cmd, 0, sizeof(cmd));
- sprintf(cmd, "%s -r %s -p %s ", mmbin, prefix, prefix);
- va_list args;
- va_start(args, command);
- vsprintf(cmd + strlen(cmd), command, args);
- va_end(args);
-
- mkdirs(prefix, 0755);
-
- char rcpath[PATH_MAX];
- sprintf(rcpath, "%s/.condarc", prefix);
- touch(rcpath);
-
- setenv("CONDARC", rcpath, 1);
- setenv("MAMBA_ROOT_PREFIX", prefix, 1);
- int status = system(cmd);
- unsetenv("MAMBA_ROOT_PREFIX");
-
- return status;
-}
-
int indexer_make_website(struct Delivery *ctx) {
char cmd[PATH_MAX];
char *inputs[] = {
@@ -259,6 +208,7 @@ int indexer_make_website(struct Delivery *ctx) {
};
if (!find_program("pandoc")) {
+ fprintf(stderr, "pandoc is not installed: unable to generate HTML indexes\n");
return 0;
}
@@ -291,16 +241,17 @@ int indexer_make_website(struct Delivery *ctx) {
int indexer_conda(struct Delivery *ctx) {
int status = 0;
- char prefix[PATH_MAX];
- sprintf(prefix, "%s/%s", ctx->storage.tmpdir, "indexer");
+ char micromamba_prefix[PATH_MAX] = {0};
+ sprintf(micromamba_prefix, "%s/bin", ctx->storage.tools_dir);
+ struct MicromambaInfo m = {.conda_prefix = globals.conda_install_prefix, .micromamba_prefix = micromamba_prefix};
- status += micromamba(ctx->storage.tmpdir, prefix, "config prepend --env channels conda-forge");
+ status += micromamba(&m, "config prepend --env channels conda-forge");
if (!globals.verbose) {
- status += micromamba(ctx->storage.tmpdir, prefix, "config set --env quiet true");
+ status += micromamba(&m, "config set --env quiet true");
}
- status += micromamba(ctx->storage.tmpdir, prefix, "config set --env always_yes true");
- status += micromamba(ctx->storage.tmpdir, prefix, "install conda-build");
- status += micromamba(ctx->storage.tmpdir, prefix, "run conda index %s", ctx->storage.conda_artifact_dir);
+ status += micromamba(&m, "config set --env always_yes true");
+ status += micromamba(&m, "install conda-build");
+ status += micromamba(&m, "run conda index %s", ctx->storage.conda_artifact_dir);
return status;
}
@@ -558,6 +509,8 @@ void indexer_init_dirs(struct Delivery *ctx, const char *workdir) {
exit(1);
}
path_store(&ctx->storage.output_dir, PATH_MAX, ctx->storage.root, "output");
+ path_store(&ctx->storage.tools_dir, PATH_MAX, ctx->storage.output_dir, "tools");
+ path_store(&globals.conda_install_prefix, PATH_MAX, ctx->storage.tools_dir, "conda");
path_store(&ctx->storage.cfgdump_dir, PATH_MAX, ctx->storage.output_dir, "config");
path_store(&ctx->storage.meta_dir, PATH_MAX, ctx->storage.output_dir, "meta");
path_store(&ctx->storage.delivery_dir, PATH_MAX, ctx->storage.output_dir, "delivery");
@@ -565,6 +518,15 @@ void indexer_init_dirs(struct Delivery *ctx, const char *workdir) {
path_store(&ctx->storage.results_dir, PATH_MAX, ctx->storage.output_dir, "results");
path_store(&ctx->storage.wheel_artifact_dir, PATH_MAX, ctx->storage.package_dir, "wheels");
path_store(&ctx->storage.conda_artifact_dir, PATH_MAX, ctx->storage.package_dir, "conda");
+
+ char newpath[PATH_MAX] = {0};
+ if (getenv("PATH")) {
+ sprintf(newpath, "%s/bin:%s", ctx->storage.tools_dir, getenv("PATH"));
+ setenv("PATH", newpath, 1);
+ } else {
+ SYSERROR("%s", "environment variable PATH is undefined. Unable to continue.");
+ exit(1);
+ }
}
int main(int argc, char *argv[]) {
@@ -627,7 +589,7 @@ int main(int argc, char *argv[]) {
}
char *workdir;
- char workdir_template[PATH_MAX];
+ char workdir_template[PATH_MAX] = {0};
char *system_tmp = getenv("TMPDIR");
if (system_tmp) {
strcat(workdir_template, system_tmp);
diff --git a/src/stasis_main.c b/src/stasis_main.c
index 8b13b98..c550982 100644
--- a/src/stasis_main.c
+++ b/src/stasis_main.c
@@ -248,6 +248,7 @@ int main(int argc, char *argv[]) {
tpl_register("storage.build_sources_dir", &ctx.storage.build_sources_dir);
tpl_register("storage.build_docker_dir", &ctx.storage.build_docker_dir);
tpl_register("storage.results_dir", &ctx.storage.results_dir);
+ tpl_register("storage.tools_dir", &ctx.storage.tools_dir);
tpl_register("conda.installer_baseurl", &ctx.conda.installer_baseurl);
tpl_register("conda.installer_name", &ctx.conda.installer_name);
tpl_register("conda.installer_version", &ctx.conda.installer_version);
@@ -257,6 +258,7 @@ int main(int argc, char *argv[]) {
tpl_register("deploy.jfrog.url", &globals.jfrog.url);
tpl_register("deploy.docker.registry", &ctx.deploy.docker.registry);
tpl_register("workaround.tox_posargs", &globals.workaround.tox_posargs);
+ tpl_register("workaround.conda_reactivate", &globals.workaround.conda_reactivate);
// Set up PREFIX/etc directory information
// The user may manipulate the base directory path with STASIS_SYSCONFDIR
diff --git a/src/utils.c b/src/utils.c
index fb22f59..2143c52 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -758,3 +758,10 @@ struct StrList *listdir(const char *path) {
return node;
}
+long get_cpu_count() {
+#if defined(STASIS_OS_LINUX) || defined(STASIS_OS_DARWIN)
+ return sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ return 0;
+#endif
+} \ No newline at end of file