diff options
Diffstat (limited to 'src/conda.c')
-rw-r--r-- | src/conda.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/conda.c b/src/conda.c new file mode 100644 index 0000000..41c03ee --- /dev/null +++ b/src/conda.c @@ -0,0 +1,176 @@ +// +// Created by jhunk on 5/14/23. +// + +#include <unistd.h> +#include "conda.h" + +int python_exec(const char *args) { + char command[PATH_MAX]; + memset(command, 0, sizeof(command)); + snprintf(command, sizeof(command) - 1, "python %s", args); + msg(OMC_MSG_L3, "Executing: %s\n", command); + return system(command); +} + +int pip_exec(const char *args) { + char command[PATH_MAX]; + memset(command, 0, sizeof(command)); + snprintf(command, sizeof(command) - 1, "python -m pip %s", args); + msg(OMC_MSG_L3, "Executing: %s\n", command); + return system(command); +} + +int conda_exec(const char *args) { + char command[PATH_MAX]; + const char *mamba_commands[] = { + "build", + "install", + "update", + "create", + "list", + "search", + "run", + "info", + "clean", + "activate", + "deactivate", + NULL + }; + char conda_as[6]; + memset(conda_as, 0, sizeof(conda_as)); + + strcpy(conda_as, "conda"); + for (size_t i = 0; mamba_commands[i] != NULL; i++) { + if (startswith(args, mamba_commands[i])) { + strcpy(conda_as, "mamba"); + break; + } + } + + snprintf(command, sizeof(command) - 1, "%s %s", conda_as, args); + msg(OMC_MSG_L3, "Executing: %s\n", command); + return system(command); +} + +int conda_activate(const char *root, const char *env_name) { + int fd = -1; + FILE *fp = NULL; + const char *init_script_conda = "/etc/profile.d/conda.sh"; + const char *init_script_mamba = "/etc/profile.d/mamba.sh"; + char path_conda[PATH_MAX] = {0}; + char path_mamba[PATH_MAX] = {0}; + char logfile[PATH_MAX] = {0}; + struct Process proc; + memset(&proc, 0, sizeof(proc)); + + // Where to find conda's init scripts + sprintf(path_conda, "%s%s", root, init_script_conda); + sprintf(path_mamba, "%s%s", root, init_script_mamba); + + // Set the path to our stdout log + // Emulate mktemp()'s behavior. Give us a unique file name, but don't use + // the file handle at all. We'll open it as a FILE stream soon enough. + strcpy(logfile, "/tmp/shell_XXXXXX"); + fd = mkstemp(logfile); + if (fd < 0) { + perror(logfile); + return -1; + } + close(fd); + + // Configure our process for output to a log file + strcpy(proc.stdout, logfile); + + // Verify conda's init scripts are available + if (access(path_conda, F_OK) < 0) { + perror(path_conda); + return -1; + } + + if (access(path_mamba, F_OK) < 0) { + perror(path_mamba); + return -1; + } + + // Fully activate conda and record its effect on the runtime environment + char command[PATH_MAX]; + snprintf(command, sizeof(command) - 1, "source %s; source %s; conda activate %s &>/dev/null; printenv", path_conda, path_mamba, env_name); + int retval = shell2(&proc, command); + if (retval) { + // it didn't work; drop out for cleanup + return retval; + } + + // Parse the log file: + // 1. Extract the environment keys and values from the sub-shell + // 2. Apply it to ohmycal's runtime environment + // 3. Now we're ready to execute conda commands anywhere + fp = fopen(proc.stdout, "r"); + if (!fp) { + perror(logfile); + return -1; + } + static char buf[1024]; + int i = 0; + while (fgets(buf, sizeof(buf) -1, fp) != NULL) { + buf[strlen(buf) - 1] = 0; + if (!strlen(buf)) { + continue; + } + //printf("[%d] %s\n", i, buf); + char *eq = strchr(buf, '='); + if (eq) { + *eq = '\0'; + } + char *key = buf; + char *val = &eq[1]; + setenv(key, val, 1); + i++; + } + fclose(fp); + remove(logfile); + return 0; +} + +void conda_env_create_from_uri(char *name, char *uri) { + char env_command[PATH_MAX]; + sprintf(env_command, "env create -n %s -f %s", name, uri); + if (conda_exec(env_command)) { + fprintf(stderr, "derived environment creation failed\n"); + exit(1); + } +} + +void conda_env_create(char *name, char *python_version, char *packages) { + char env_command[PATH_MAX]; + sprintf(env_command, "create -n %s python=%s %s", name, python_version, packages ? packages : ""); + if (conda_exec(env_command)) { + fprintf(stderr, "conda environment creation failed\n"); + exit(1); + } +} + +void conda_env_remove(char *name) { + char env_command[PATH_MAX]; + sprintf(env_command, "env remove -n %s", name); + if (conda_exec(env_command)) { + fprintf(stderr, "conda environment removal failed\n"); + exit(1); + } +} + +void conda_env_export(char *name, char *output_dir, char *output_filename) { + char env_command[PATH_MAX]; + sprintf(env_command, "env export -n %s -f %s/%s.yml", name, output_dir, output_filename); + if (conda_exec(env_command)) { + fprintf(stderr, "conda environment export failed\n"); + exit(1); + } +} + +int conda_index(const char *path) { + char command[PATH_MAX]; + sprintf(command, "index %s", path); + return conda_exec(command); +} |