diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2019-12-18 21:57:51 -0500 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2019-12-18 21:57:51 -0500 |
commit | 534657dd6fc2ee98159e41d2700554fed0da2c4e (patch) | |
tree | d9316757b060d68e5640ea9ecb56b29c62adedfc /src/deps.c | |
parent | 3166627f1485e2f05421fe874b2236852fe5d017 (diff) | |
download | spmc-534657dd6fc2ee98159e41d2700554fed0da2c4e.tar.gz |
Refactor project structure
Diffstat (limited to 'src/deps.c')
-rw-r--r-- | src/deps.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/src/deps.c b/src/deps.c new file mode 100644 index 0000000..99f6148 --- /dev/null +++ b/src/deps.c @@ -0,0 +1,188 @@ +// +// Created by jhunk on 12/16/19. +// +#include "spm.h" + +int exists(const char *filename) { + return access(filename, F_OK); +} + +int dep_seen(Dependencies **deps, const char *name) { + if (!deps) { + return -1; + } + for (int i = 0; i != (*deps)->records; i++) { + if (strstr((*deps)->list[i], name) != NULL) { + return 1; + } + } + return 0; +} + +int dep_init(Dependencies **deps) { + (*deps) = (Dependencies *)calloc(1, sizeof(Dependencies)); + (*deps)->__size = 2; + (*deps)->records = 0; + (*deps)->list = (char **)calloc((*deps)->__size, sizeof(char *)); + if (!(*deps)->list) { + return -1; + } + return 0; +} + +void dep_free(Dependencies **deps) { + if ((*deps) != NULL) { + return; + } + for (int i = 0; i < (*deps)->__size; i++) { + if ((*deps)->list[i] != NULL) { + free((*deps)->list[i]); + } + } + free((*deps)); +} + +int dep_append(Dependencies **deps, char *_name) { + char *name = NULL; + char *bname = NULL; + + if (!(*deps)) { + return -1; + } + + name = find_package(_name); + if (!name) { + perror(_name); + fprintf(SYSERROR); + return -1; + } + + bname = basename(name); + if (!bname) { + perror(name); + fprintf(SYSERROR); + return -1; + } + + (*deps)->__size++; + (*deps)->list = (char **)realloc((*deps)->list, sizeof(char *) * (*deps)->__size); + if (!(*deps)->list) { + free(name); + return -1; + } + + (*deps)->list[(*deps)->records] = (char *)calloc(strlen(bname) + 1, sizeof(char)); + if (!(*deps)->list[(*deps)->records]) { + free(name); + return -1; + } + + strcpy((*deps)->list[(*deps)->records], bname); + (*deps)->records++; + + free(name); + return 0; +} + +int dep_solve(Dependencies **deps, const char *filename) { + if (!(*deps)) { + return -1; + } + if (exists(filename) != 0) { + return -1; + } + FILE *fp = fopen(filename, "r"); + if (!fp) { + perror(filename); + return -1; + } + + char data[BUFSIZ]; + memset(data, '\0', sizeof(data)); + + char *line = data; + int line_count = 0; + while (fgets(line, BUFSIZ, fp) != NULL) { + size_t line_length = strlen(line); + if (line_length > 1 && strstr(line, "\r\n")) { + line[line_length - 2] = '\0'; + } + if (line_length > 1 && line[line_length - 1] == '\n') { + line[line_length - 1] = '\0'; + } + if (strcmp(line, "") == 0) { + continue; + } + line_count++; + if (dep_seen(deps, line) > 0) { + // Already seen this dependency. Skip it. + continue; + } + else { + // Have not seen this dependency before + if (dep_append(deps, line) == 0) { + dep_solve(deps, line); + } + } + } + fclose(fp); + return line_count; +} + +int dep_all(Dependencies **deps, const char *_package) { + static int next = 0; + char *package = NULL; + char depfile[PATH_MAX]; + char template[PATH_MAX]; + char suffix[PATH_MAX] = "spm_depends_all_XXXXXX"; + + // Verify the requested package pattern exists + package = find_package(_package); + if (!package) { + perror(_package); + fprintf(SYSERROR); + return -1; + } + + // Create a new temporary directory and extract the requested package into it + sprintf(template, "%s%c%s", TMP_DIR, DIRSEP, suffix); + char *tmpdir = mkdtemp(template); + if (!tmpdir) { + perror(template); + fprintf(SYSERROR); + return -1; + } + if (tar_extract_file(package, ".SPM_DEPENDS", tmpdir) < 0) { + perror(package); + fprintf(SYSERROR); + return -1; + } + + // Scan depencency tree + sprintf(depfile, "%s%c%s", tmpdir, DIRSEP, ".SPM_DEPENDS"); + int resolved = dep_solve(deps, depfile); + + // NOTE: + // 1. `resolved` is the number of dependencies for the package we're scanning + // 2. `next` permits us to converge on `resolved`, otherwise `i` would reset to `0` each time `dep_all` is called + for (int i = next; i < resolved; i++) { + next++; + if (dep_seen(deps, (*deps)->list[i])) { + dep_all(deps, (*deps)->list[i]); + } + } + + // Remove temporary data + unlink(depfile); + unlink(tmpdir); + return 0; +} + +void dep_show(Dependencies **deps) { + if ((*deps) == NULL) { + return; + } + for (int i = 0; i < (*deps)->records; i++) { + printf("%d: %s\n", i, (*deps)->list[i]); + } +} |