diff options
-rw-r--r-- | src/lib/core/include/utils.h | 3 | ||||
-rw-r--r-- | src/lib/core/utils.c | 84 | ||||
-rw-r--r-- | src/lib/delivery/delivery_build.c | 12 | ||||
-rw-r--r-- | src/lib/delivery/delivery_test.c | 12 |
4 files changed, 111 insertions, 0 deletions
diff --git a/src/lib/core/include/utils.h b/src/lib/core/include/utils.h index 1512285..a9bcd2f 100644 --- a/src/lib/core/include/utils.h +++ b/src/lib/core/include/utils.h @@ -461,4 +461,7 @@ int in_ascii_range(char c, char lower, char upper); #define GIT_HASH_LEN 40 int is_git_sha(char const *hash); + +int check_python_package_dependencies(const char *srcdir); + #endif //STASIS_UTILS_H diff --git a/src/lib/core/utils.c b/src/lib/core/utils.c index 3d9659d..62f3bec 100644 --- a/src/lib/core/utils.c +++ b/src/lib/core/utils.c @@ -994,3 +994,87 @@ int is_git_sha(char const *hash) { return 1; } +static int read_vcs_records(const size_t line, char **data) { + (void) line; // unused + const char *vcs_name[] = { + "git", + "svn", + "hg", + "bzr", + }; + for (size_t i = 0; i < sizeof(vcs_name) / sizeof(vcs_name[0]); i++) { + const char *vcs = vcs_name[i]; + char *data_local = strdup(*data); + if (!data_local) { + fprintf(stderr, "Out of memory\n"); + return -1; + } + + // Remove leading/trailing blanks + lstrip(data_local); + strip(data_local); + + // Ignore file comment(s) + if (startswith(data_local, "#") || startswith(data_local, ";")) { + // continue + return 1; + } + + // Begin matching VCS package syntax + const char *match_vcs = strstr(data_local,vcs); + if (match_vcs) { + const char *match_protocol_sep = strstr(match_vcs, "+"); + if (match_protocol_sep) { + const char *match_protocol = strstr(match_protocol_sep, "://"); + if (match_protocol) { + guard_free(data_local); + // match found + return 0; + } + } + } + guard_free(data_local); + } + + // no match, continue + return 1; +} +int check_python_package_dependencies(const char *srcdir) { + const char *configs[] = { + "pyproject.toml", + "setup.cfg", + "setup.py" + }; + + for (size_t i = 0; i < sizeof(configs) / sizeof(configs[0]); i++) { + char path[PATH_MAX] = {0}; + const char *configfile = configs[i]; + + snprintf(path, sizeof(path), "%s/%s", srcdir, configfile); + if (access(path, F_OK) < 0) { + continue; + } + + //char **data = file_readlines(path, 0, 0, NULL); + struct StrList *data = strlist_init(); + int err = 0; + if ((err = strlist_append_file(data, path, read_vcs_records))) { + guard_strlist_free(&data); + return -1; + } + const size_t count = strlist_count(data); + if (count) { + printf("\nERROR: VCS requirement(s) detected in %s:\n", configfile); + for (size_t j = 0; j < count; j++) { + char *record = strlist_item(data, j); + lstrip(record); + strip(record); + printf("[%zu] %s\n", j, record); + } + guard_strlist_free(&data); + return 1; + } + guard_strlist_free(&data); + } + return 0; +} diff --git a/src/lib/delivery/delivery_build.c b/src/lib/delivery/delivery_build.c index 2d891d2..c5093d4 100644 --- a/src/lib/delivery/delivery_build.c +++ b/src/lib/delivery/delivery_build.c @@ -173,6 +173,18 @@ struct StrList *delivery_build_wheels(struct Delivery *ctx) { memset(outdir, 0, sizeof(outdir)); memset(cmd, 0, sizeof(outdir)); + const int dep_status = check_python_package_dependencies("."); + if (dep_status) { + fprintf(stderr, "\nPlease replace all occurrences above with standard package specs:\n" + "\n" + " package==x.y.z\n" + " package>=x.y.z\n" + " package<=x.y.z\n" + " ...\n" + "\n"); + COE_CHECK_ABORT(dep_status, "Unreproducible delivery"); + } + strcpy(dname, ctx->tests[i].name); tolower_s(dname); sprintf(outdir, "%s/%s", ctx->storage.wheel_artifact_dir, dname); diff --git a/src/lib/delivery/delivery_test.c b/src/lib/delivery/delivery_test.c index e80e0ec..6e0a226 100644 --- a/src/lib/delivery/delivery_test.c +++ b/src/lib/delivery/delivery_test.c @@ -97,6 +97,18 @@ void delivery_tests_run(struct Delivery *ctx) { if (pushd(destdir)) { COE_CHECK_ABORT(1, "Unable to enter repository directory\n"); } else { + int dep_status = check_python_package_dependencies("."); + if (dep_status) { + fprintf(stderr, "\nPlease replace all occurrences above with standard package specs:\n" + "\n" + " package==x.y.z\n" + " package>=x.y.z\n" + " package<=x.y.z\n" + " ...\n" + "\n"); + COE_CHECK_ABORT(dep_status, "Unreproducible delivery"); + } + char *cmd = calloc(strlen(test->script) + STASIS_BUFSIZ, sizeof(*cmd)); if (!cmd) { SYSERROR("Unable to allocate test script buffer: %s", strerror(errno)); |