From e87371e8cabacb29144c5763cc55105e3bf622eb Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 4 Oct 2024 17:31:58 -0400 Subject: Do not truncate test->name --- src/delivery.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/delivery.c b/src/delivery.c index a689db2..e8c3a28 100644 --- a/src/delivery.c +++ b/src/delivery.c @@ -220,7 +220,6 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { // Override test->version when a version is provided by the (pip|conda)_package list item guard_free(test->version); if (spec_begin && spec_end) { - *spec_begin = '\0'; test->version = strdup(spec_end); } else { // There are too many possible default branches nowadays: master, main, develop, xyz, etc. -- cgit From 4ea0e522551b8d77ed79df9e7edd6ec891019d19 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 4 Oct 2024 17:32:57 -0400 Subject: Record the package name in a separate variable --- src/delivery.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/delivery.c b/src/delivery.c index e8c3a28..dfe9209 100644 --- a/src/delivery.c +++ b/src/delivery.c @@ -191,19 +191,25 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { // no data continue; } - msg(STASIS_MSG_L3, "package '%s': ", name); // Compile a list of packages that are *also* to be tested. char *version; char *spec_begin = strpbrk(name, "@~=<>!"); char *spec_end = spec_begin; + char package_name[255] = {0}; + if (spec_end) { // A version is present in the package name. Jump past operator(s). while (*spec_end != '\0' && !isalnum(*spec_end)) { spec_end++; } + strncpy(package_name, name, spec_begin - name); + } else { + strncpy(package_name, name, sizeof(package_name) - 1); } + msg(STASIS_MSG_L3, "package '%s': ", package_name); + // When spec is present in name, set tests->version to the version detected in the name for (size_t x = 0; x < sizeof(ctx->tests) / sizeof(ctx->tests[0]) && ctx->tests[x].name != NULL; x++) { struct Test *test = &ctx->tests[x]; -- cgit From ace6fe586ff30be57e708f81489b120204d6dd62 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 4 Oct 2024 17:35:12 -0400 Subject: Use nametmp instead of test->name (i.e. name) --- src/delivery.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/delivery.c b/src/delivery.c index dfe9209..563ef8f 100644 --- a/src/delivery.c +++ b/src/delivery.c @@ -235,8 +235,8 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { version = test->version; // Is the list item a git+schema:// URL? - if (strstr(name, "git+") && strstr(name, "://")) { - char *xrepo = strstr(name, "+"); + if (strstr(nametmp, "git+") && strstr(nametmp, "://")) { + char *xrepo = strstr(nametmp, "+"); if (xrepo) { xrepo++; guard_free(test->repository); @@ -244,7 +244,7 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { xrepo = NULL; } // Extract the name of the package - char *xbasename = path_basename(name); + char *xbasename = path_basename(nametmp); if (xbasename) { // Replace the git+schema:// URL with the package name strlist_set(&dataptr, i, xbasename); @@ -252,9 +252,11 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { } } - if (DEFER_PIP == type && pip_index_provides(PYPI_INDEX_DEFAULT, name, version)) { - fprintf(stderr, "(%s present on index %s): ", version, PYPI_INDEX_DEFAULT); - ignore_pkg = 0; + ignore_pkg = 0; + if (DEFER_PIP == type && pip_index_provides(PYPI_INDEX_DEFAULT, nametmp, version)) { + fprintf(stderr, "(%s provided by index %s): ", version, PYPI_INDEX_DEFAULT); + } else if (DEFER_CONDA == type && conda_provides(nametmp)) { + fprintf(stderr, "(%s provided by conda channel): ", version); } else { ignore_pkg = 1; } @@ -263,12 +265,6 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { } if (ignore_pkg) { - char build_at[PATH_MAX]; - if (DEFER_CONDA == type) { - sprintf(build_at, "%s=%s", name, version); - name = build_at; - } - printf("BUILD FOR HOST\n"); strlist_append(&deferred, name); } else { -- cgit From 086187e9aa97b137188cf8a1fe872f3397b988e8 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 4 Oct 2024 17:52:24 -0400 Subject: Fix release environment removal message * Fix testing environment removal message * Fix tool installation error message --- src/stasis_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/stasis_main.c b/src/stasis_main.c index b5d43e3..88a1809 100644 --- a/src/stasis_main.c +++ b/src/stasis_main.c @@ -498,9 +498,10 @@ int main(int argc, char *argv[]) { msg(STASIS_MSG_L1, "Creating release environment(s)\n"); if (ctx.meta.based_on && strlen(ctx.meta.based_on)) { if (conda_env_remove(env_name)) { - msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "failed to remove release environment: %s\n", env_name_testing); - exit(1); + msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "failed to remove release environment: %s\n", env_name); + exit(1); } + msg(STASIS_MSG_L2, "Based on release: %s\n", ctx.meta.based_on); if (conda_env_create_from_uri(env_name, ctx.meta.based_on)) { msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "unable to install release environment using configuration file\n"); @@ -508,7 +509,7 @@ int main(int argc, char *argv[]) { } if (conda_env_remove(env_name_testing)) { - msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "failed to remove testing environment\n"); + msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "failed to remove testing environment %s\n", env_name_testing); exit(1); } if (conda_env_create_from_uri(env_name_testing, ctx.meta.based_on)) { @@ -544,9 +545,10 @@ int main(int argc, char *argv[]) { } if (pip_exec("install build")) { - msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "'build' tool installation failed"); + msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "'build' tool installation failed\n"); exit(1); } + } msg(STASIS_MSG_L1, "Filter deliverable packages\n"); delivery_defer_packages(&ctx, DEFER_CONDA); -- cgit From 3b1471e5003df6476273f6ebc515f98329f5b448 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 4 Oct 2024 17:53:02 -0400 Subject: Implement delivery_overylay_packages_from_env() --- src/stasis_main.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/stasis_main.c b/src/stasis_main.c index 88a1809..79277e0 100644 --- a/src/stasis_main.c +++ b/src/stasis_main.c @@ -548,6 +548,13 @@ int main(int argc, char *argv[]) { msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "'build' tool installation failed\n"); exit(1); } + + if (ctx.meta.based_on) { + msg(STASIS_MSG_L1, "Generating package overlay from environment: %s\n", env_name); + if (delivery_overlay_packages_from_env(&ctx, env_name)) { + msg(STASIS_MSG_L2 | STASIS_MSG_ERROR, "%s", "Failed to generate package overlay. Resulting environment integrity cannot be guaranteed.\n"); + exit(1); + } } msg(STASIS_MSG_L1, "Filter deliverable packages\n"); -- cgit From f48b4a533db35c0233cbfbc1a569cde134ecf689 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 4 Oct 2024 18:32:45 -0400 Subject: Use strcmp instead of strstr --- src/delivery_install.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/delivery_install.c b/src/delivery_install.c index 1ecedc5..a3faae4 100644 --- a/src/delivery_install.c +++ b/src/delivery_install.c @@ -5,7 +5,7 @@ static struct Test *requirement_from_test(struct Delivery *ctx, const char *name result = NULL; for (size_t i = 0; i < sizeof(ctx->tests) / sizeof(ctx->tests[0]); i++) { - if (ctx->tests[i].name && strstr(name, ctx->tests[i].name)) { + if (ctx->tests[i].name && !strcmp(name, ctx->tests[i].name)) { result = &ctx->tests[i]; break; } -- cgit From 64e91d99e8e391b1789f9cc326f21f0c52fd3ac6 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 4 Oct 2024 18:33:38 -0400 Subject: Initialize result --- src/delivery_install.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/delivery_install.c b/src/delivery_install.c index a3faae4..ae31cb9 100644 --- a/src/delivery_install.c +++ b/src/delivery_install.c @@ -1,9 +1,7 @@ #include "delivery.h" static struct Test *requirement_from_test(struct Delivery *ctx, const char *name) { - struct Test *result; - - result = NULL; + struct Test *result = NULL; for (size_t i = 0; i < sizeof(ctx->tests) / sizeof(ctx->tests[0]); i++) { if (ctx->tests[i].name && !strcmp(name, ctx->tests[i].name)) { result = &ctx->tests[i]; -- cgit From 3fa05b5a2f0cda51897162666fb300d2d063b22f Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 4 Oct 2024 18:35:04 -0400 Subject: Add function delivery_overlay_packages_from_env() * Add helper function have_spec_in_config() --- src/delivery_install.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) (limited to 'src') diff --git a/src/delivery_install.c b/src/delivery_install.c index ae31cb9..1fc6030 100644 --- a/src/delivery_install.c +++ b/src/delivery_install.c @@ -11,6 +11,101 @@ static struct Test *requirement_from_test(struct Delivery *ctx, const char *name return result; } +static char *have_spec_in_config(struct Delivery *ctx, const char *name) { + for (size_t x = 0; x < strlist_count(ctx->conda.pip_packages); x++) { + char *config_spec = strlist_item(ctx->conda.pip_packages, x); + char *op = find_version_spec(config_spec); + char package[255] = {0}; + if (op) { + strncpy(package, config_spec, op - config_spec); + } else { + strncpy(package, config_spec, sizeof(package) - 1); + } + if (strncmp(package, name, strlen(package)) == 0) { + return config_spec; + } + } + return NULL; +} + +int delivery_overlay_packages_from_env(struct Delivery *ctx, const char *env_name) { + char *current_env = conda_get_active_environment(); + int need_restore = current_env && strcmp(env_name, current_env) != 0; + + conda_activate(ctx->storage.conda_install_prefix, env_name); + // Retrieve a listing of python packages installed under "env_name" + int freeze_status = 0; + char *freeze_output = shell_output("python -m pip freeze", &freeze_status); + if (freeze_status) { + guard_free(freeze_output); + guard_free(current_env); + return -1; + } + + if (need_restore) { + // Restore the original conda environment + conda_activate(ctx->storage.conda_install_prefix, current_env); + } + guard_free(current_env); + + struct StrList *frozen_list = strlist_init(); + strlist_append_tokenize(frozen_list, freeze_output, LINE_SEP); + guard_free(freeze_output); + + struct StrList *new_list = strlist_init(); + + // - consume package specs that have no test blocks. + // - these will be third-party packages like numpy, scipy, etc. + // - and they need to be present at the head of the list so they + // get installed first. + for (size_t i = 0; i < strlist_count(ctx->conda.pip_packages); i++) { + char *spec = strlist_item(ctx->conda.pip_packages, i); + char spec_name[255] = {0}; + char *op = find_version_spec(spec); + if (op) { + strncpy(spec_name, spec, op - spec); + } else { + strncpy(spec_name, spec, sizeof(spec_name) - 1); + } + struct Test *test_block = requirement_from_test(ctx, spec_name); + if (!test_block) { + printf("using spec from config without test: %s\n", spec); + strlist_append(&new_list, spec); + } + } + + // now consume packages that have a test block + // if the ini provides a spec, override the environment's version. + // otherwise, use the spec derived from the environment + for (size_t i = 0; i < strlist_count(frozen_list); i++) { + char *frozen_spec = strlist_item(frozen_list, i); + char frozen_name[255] = {0}; + char *op = find_version_spec(frozen_spec); + // we only care about packages with specs here. if something else arrives, ignore it + if (op) { + strncpy(frozen_name, frozen_spec, op - frozen_spec); + } else { + strncpy(frozen_name, frozen_spec, sizeof(frozen_name) - 1); + } + struct Test *test = requirement_from_test(ctx, frozen_name); + if (test && strcmp(test->name, frozen_name) == 0) { + char *config_spec = have_spec_in_config(ctx, frozen_name); + if (config_spec) { + printf("using spec from config: %s\n", config_spec); + strlist_append(&new_list, config_spec); + } else { + printf("using spec from environment: %s\n", frozen_spec); + strlist_append(&new_list, frozen_spec); + } + } + } + guard_strlist_free(&ctx->conda.pip_packages); + ctx->conda.pip_packages = strlist_copy(new_list); + guard_strlist_free(&new_list); + guard_strlist_free(&frozen_list); + return 0; +} + int delivery_install_packages(struct Delivery *ctx, char *conda_install_dir, char *env_name, int type, struct StrList **manifest) { char cmd[PATH_MAX]; char pkgs[STASIS_BUFSIZ]; -- cgit From 5fd32e305baeb357bc1e23d3992014b641dff3a6 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 4 Oct 2024 19:01:04 -0400 Subject: Use isempty to see if we're using based_on --- src/stasis_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stasis_main.c b/src/stasis_main.c index 79277e0..737fafc 100644 --- a/src/stasis_main.c +++ b/src/stasis_main.c @@ -496,7 +496,7 @@ int main(int argc, char *argv[]) { } msg(STASIS_MSG_L1, "Creating release environment(s)\n"); - if (ctx.meta.based_on && strlen(ctx.meta.based_on)) { + if (!isempty(ctx.meta.based_on)) { if (conda_env_remove(env_name)) { msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "failed to remove release environment: %s\n", env_name); exit(1); @@ -549,7 +549,7 @@ int main(int argc, char *argv[]) { exit(1); } - if (ctx.meta.based_on) { + if (!isempty(ctx.meta.based_on)) { msg(STASIS_MSG_L1, "Generating package overlay from environment: %s\n", env_name); if (delivery_overlay_packages_from_env(&ctx, env_name)) { msg(STASIS_MSG_L2 | STASIS_MSG_ERROR, "%s", "Failed to generate package overlay. Resulting environment integrity cannot be guaranteed.\n"); -- cgit From 914b79370cec1e1a33acb21a14701dd70449f0d8 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 7 Oct 2024 12:45:32 -0400 Subject: Use msg() in delivery_overlay_packages_from_env() --- src/delivery_install.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/delivery_install.c b/src/delivery_install.c index 1fc6030..a7754e8 100644 --- a/src/delivery_install.c +++ b/src/delivery_install.c @@ -69,7 +69,7 @@ int delivery_overlay_packages_from_env(struct Delivery *ctx, const char *env_nam } struct Test *test_block = requirement_from_test(ctx, spec_name); if (!test_block) { - printf("using spec from config without test: %s\n", spec); + msg(STASIS_MSG_L2 | STASIS_MSG_WARN, "from config without test: %s\n", spec); strlist_append(&new_list, spec); } } @@ -91,10 +91,10 @@ int delivery_overlay_packages_from_env(struct Delivery *ctx, const char *env_nam if (test && strcmp(test->name, frozen_name) == 0) { char *config_spec = have_spec_in_config(ctx, frozen_name); if (config_spec) { - printf("using spec from config: %s\n", config_spec); + msg(STASIS_MSG_L2, "from config: %s\n", config_spec); strlist_append(&new_list, config_spec); } else { - printf("using spec from environment: %s\n", frozen_spec); + msg(STASIS_MSG_L2, "from environment: %s\n", frozen_spec); strlist_append(&new_list, frozen_spec); } } -- cgit From 82d3840534d10050bbcd70d42e13d2659251431d Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 7 Oct 2024 12:47:18 -0400 Subject: Fail immediately when an unknown package manager "type" is discovered --- src/delivery.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/delivery.c b/src/delivery.c index 563ef8f..b0918c8 100644 --- a/src/delivery.c +++ b/src/delivery.c @@ -178,6 +178,9 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { dataptr = ctx->conda.pip_packages; deferred = ctx->conda.pip_packages_defer; strcpy(mode, "pip"); + } else { + SYSERROR("BUG: type %d does not map to a supported package manager!\n", type); + exit(1); } msg(STASIS_MSG_L2, "Filtering %s packages by test definition...\n", mode); -- cgit From 54a4bd4ee9a608f8a8220db9e2954f33fc68ac5a Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 7 Oct 2024 12:47:53 -0400 Subject: Rename ignore_pkg variable to build_for_host because it was plain confusing to look at it --- src/delivery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/delivery.c b/src/delivery.c index b0918c8..6c7a675 100644 --- a/src/delivery.c +++ b/src/delivery.c @@ -187,7 +187,7 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { struct StrList *filtered = NULL; filtered = strlist_init(); for (size_t i = 0; i < strlist_count(dataptr); i++) { - int ignore_pkg = 0; + int build_for_host = 0; name = strlist_item(dataptr, i); if (!strlen(name) || isblank(*name) || isspace(*name)) { -- cgit From 4b6fd13d290f9de731589f936c304c7bc74e6b88 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 7 Oct 2024 12:50:30 -0400 Subject: Don't bother extracting the version from the spec --- src/delivery.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/delivery.c b/src/delivery.c index 6c7a675..e7dfece 100644 --- a/src/delivery.c +++ b/src/delivery.c @@ -196,7 +196,6 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { } // Compile a list of packages that are *also* to be tested. - char *version; char *spec_begin = strpbrk(name, "@~=<>!"); char *spec_end = spec_begin; char package_name[255] = {0}; @@ -216,9 +215,8 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { // When spec is present in name, set tests->version to the version detected in the name for (size_t x = 0; x < sizeof(ctx->tests) / sizeof(ctx->tests[0]) && ctx->tests[x].name != NULL; x++) { struct Test *test = &ctx->tests[x]; - version = NULL; - char nametmp[1024] = {0}; + if (spec_end != NULL && spec_begin != NULL) { strncpy(nametmp, name, spec_begin - name); } else { @@ -235,7 +233,6 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { // HEAD is a safe bet. test->version = strdup("HEAD"); } - version = test->version; // Is the list item a git+schema:// URL? if (strstr(nametmp, "git+") && strstr(nametmp, "://")) { -- cgit From 4d525473d1f2b4d02e29747a45d2a02ffcff4398 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 7 Oct 2024 12:52:03 -0400 Subject: Break down the existence check * These checks can fail due to external factors, so handle those first * Build the package for the host system the package isn't found in the index/channel * Change EXISTING to EXTERNAL to be more clear. The package exists... externally --- src/delivery.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/delivery.c b/src/delivery.c index e7dfece..07e04c8 100644 --- a/src/delivery.c +++ b/src/delivery.c @@ -252,23 +252,36 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { } } - ignore_pkg = 0; - if (DEFER_PIP == type && pip_index_provides(PYPI_INDEX_DEFAULT, nametmp, version)) { - fprintf(stderr, "(%s provided by index %s): ", version, PYPI_INDEX_DEFAULT); - } else if (DEFER_CONDA == type && conda_provides(nametmp)) { - fprintf(stderr, "(%s provided by conda channel): ", version); + int upstream_exists = 0; + if (DEFER_PIP == type) { + upstream_exists = pip_index_provides(PYPI_INDEX_DEFAULT, name); + } else if (DEFER_CONDA == type) { + upstream_exists = conda_provides(name); } else { - ignore_pkg = 1; + fprintf(stderr, "\nUnknown package type: %d\n", type); + exit(1); } + + if (upstream_exists < 0) { + fprintf(stderr, "%s's existence command failed for '%s'\n" + "(This may be due to a network/firewall issue!)\n", mode, name); + exit(1); + } + if (!upstream_exists) { + build_for_host = 1; + } else { + build_for_host = 0; + } + break; } } - if (ignore_pkg) { + if (build_for_host) { printf("BUILD FOR HOST\n"); strlist_append(&deferred, name); } else { - printf("USE EXISTING\n"); + printf("USE EXTERNAL\n"); strlist_append(&filtered, name); } } -- cgit From 2348de4365967a7cf18400213a5a84e4da7f0491 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 7 Oct 2024 12:53:35 -0400 Subject: pip_index_provides does not need a separate version * To be more aligned with conda_provides, the version spec has been consolidated into one argument --- src/conda.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/conda.c b/src/conda.c index 43b9001..e60abc7 100644 --- a/src/conda.c +++ b/src/conda.c @@ -79,37 +79,26 @@ int pip_exec(const char *args) { return system(command); } -int pip_index_provides(const char *index_url, const char *name, const char *version) { +int pip_index_provides(const char *index_url, const char *spec) { char cmd[PATH_MAX] = {0}; - char name_local[255]; - char version_local[255] = {0}; - char spec[255] = {0}; + char spec_local[255] = {0}; - if (isempty((char *) name) < 0) { - // no package name means nothing to do. + if (isempty((char *) spec)) { + // NULL or zero-length; no package spec means there's nothing to do. return -1; } - // Fix up the package name - strncpy(name_local, name, sizeof(name_local) - 1); - tolower_s(name_local); - lstrip(name_local); - strip(name_local); - - if (version) { - // Fix up the package version - strncpy(version_local, version, sizeof(version_local) - 1); - tolower_s(version_local); - lstrip(version_local); - strip(version_local); - sprintf(spec, "==%s", version); - } + // Normalize the local spec string + strncpy(spec_local, spec, sizeof(spec_local) - 1); + tolower_s(spec_local); + lstrip(spec_local); + strip(spec_local); char logfile[] = "/tmp/STASIS-package_exists.XXXXXX"; int logfd = mkstemp(logfile); if (logfd < 0) { perror(logfile); - remove(logfile); // fail harmlessly if not present + remove(logfile); // fail harmlessly if not present return -1; } @@ -121,7 +110,7 @@ int pip_index_provides(const char *index_url, const char *name, const char *vers strcpy(proc.f_stdout, logfile); // Do an installation in dry-run mode to see if the package exists in the given index. - snprintf(cmd, sizeof(cmd) - 1, "python -m pip install --dry-run --no-deps --index-url=%s %s%s", index_url, name_local, spec); + snprintf(cmd, sizeof(cmd) - 1, "python -m pip install --dry-run --no-deps --index-url=%s %s", index_url, spec_local); status = shell(&proc, cmd); // Print errors only when shell() itself throws one -- cgit