diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2019-12-21 01:12:51 -0500 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2019-12-21 01:12:51 -0500 |
commit | 6a4aa30406b19cd4c0bac04cb9bd27996b6380db (patch) | |
tree | 57fac4c9f85f2be9dacef65aeef018cfe341ecdc /src | |
parent | 7f455d3bd1030b6fb48b5e8431b08d40eead2b2e (diff) | |
download | spmc-6a4aa30406b19cd4c0bac04cb9bd27996b6380db.tar.gz |
Implement basic package manifest
Diffstat (limited to 'src')
-rw-r--r-- | src/config_global.c | 43 | ||||
-rw-r--r-- | src/manifest.c | 157 | ||||
-rw-r--r-- | src/spm.c | 28 |
3 files changed, 181 insertions, 47 deletions
diff --git a/src/config_global.c b/src/config_global.c index bbce6ef..d4e7e69 100644 --- a/src/config_global.c +++ b/src/config_global.c @@ -42,7 +42,7 @@ char *get_user_config_file(void) { char *get_user_tmp_dir(void) { char template[PATH_MAX]; char *ucd = get_user_conf_dir(); - sprintf(template, "%s%ctmp", ucd, DIRSEP); + sprintf(template, "%s%c%s", ucd, DIRSEP, "tmp"); if (access(template, F_OK) != 0) { if (mkdirs(template, 0755) != 0) { @@ -57,7 +57,7 @@ char *get_user_tmp_dir(void) { char *get_user_package_dir(void) { char template[PATH_MAX]; char *ucd = get_user_conf_dir(); - sprintf(template, "%s%cpkgs", ucd, DIRSEP); + sprintf(template, "%s%c%s", ucd, DIRSEP, "pkgs"); if (access(template, F_OK) != 0) { if (mkdirs(template, 0755) != 0) { @@ -69,6 +69,23 @@ char *get_user_package_dir(void) { return strdup(template); } +char *get_package_manifest(void) { + char template[PATH_MAX]; + char *ucd = get_user_conf_dir(); + + sprintf(template, "%s%c%s", ucd, DIRSEP, "manifest.dat"); + char *wtf = template; + + if (access(template, F_OK) != 0) { + fprintf(stderr, "Package manifest not found: %s\n", template); + Manifest *manifest = manifest_from(PKG_DIR); + manifest_write(manifest); + manifest_free(manifest); + } + + free(ucd); + return strdup(template); +} /** * Check whether SPM has access to external programs it needs */ @@ -95,13 +112,12 @@ void check_runtime_environment(void) { } } - - void init_config_global(void) { SPM_GLOBAL.user_config_basedir = NULL; SPM_GLOBAL.user_config_file = NULL; SPM_GLOBAL.package_dir = NULL; SPM_GLOBAL.tmp_dir = NULL; + SPM_GLOBAL.package_manifest = NULL; SPM_GLOBAL.config = NULL; SPM_GLOBAL.verbose = 0; @@ -149,6 +165,21 @@ void init_config_global(void) { else { SPM_GLOBAL.package_dir = get_user_package_dir(); } + + // Initialize package manifest + item = config_get(SPM_GLOBAL.config, "package_manifest"); + if (item) { + SPM_GLOBAL.package_manifest = item->value; + if (access(SPM_GLOBAL.package_manifest, F_OK) != 0) { + fprintf(stderr, "Package manifest not found: %s\n", SPM_GLOBAL.package_manifest); + Manifest *manifest = manifest_from(PKG_DIR); + manifest_write(manifest); + manifest_free(manifest); + } + } + else { + SPM_GLOBAL.package_manifest = get_package_manifest(); + } } void free_global_config(void) { @@ -158,6 +189,9 @@ void free_global_config(void) { if (SPM_GLOBAL.tmp_dir) { free(SPM_GLOBAL.tmp_dir); } + if (SPM_GLOBAL.package_manifest) { + free(SPM_GLOBAL.package_manifest); + } if (SPM_GLOBAL.user_config_basedir) { free(SPM_GLOBAL.user_config_basedir); } @@ -183,5 +217,6 @@ void show_global_config(void) { } printf("# package storage: %s\n", SPM_GLOBAL.package_dir); printf("# temp storage: %s\n", SPM_GLOBAL.tmp_dir); + printf("# package manifest: %s\n", SPM_GLOBAL.package_manifest); printf("\n"); } diff --git a/src/manifest.c b/src/manifest.c index 5193c3d..e60599d 100644 --- a/src/manifest.c +++ b/src/manifest.c @@ -2,20 +2,16 @@ // Created by jhunk on 12/20/19. // #include "spm.h" +#include <fnmatch.h> -int manifest_create(const char *package_dir) { - const char *filename = "manifest.dat"; - char path[PATH_MAX]; - int total_records = 0; +Manifest *manifest_from(const char *package_dir) { FSTree *fsdata = NULL; fsdata = fstree(package_dir); - ManifestPackage **info = (ManifestPackage **)calloc(fsdata->files_length + 1, sizeof(ManifestPackage *)); - - memset(path, '\0', sizeof(path)); - memset(info, '\0', sizeof(ManifestPackage *)); - sprintf(path, "%s%c%s", SPM_GLOBAL.user_config_basedir, DIRSEP, filename); + Manifest *info = (Manifest *)calloc(1, sizeof(Manifest)); + info->records = fsdata->files_length; + info->packages = (ManifestPackage **) calloc(info->records + 1, sizeof(ManifestPackage *)); - printf("Gathering package data:\n"); + printf("Initializing package manifest:\n"); for (int i = 0; i < fsdata->files_length && i < 0xffff; i++) { float percent = (((float)i + 1) / fsdata->files_length) * 100; printf("[%3.0f%%] %s\n", percent, basename(fsdata->files[i])); @@ -26,71 +22,156 @@ int manifest_create(const char *package_dir) { } // Initialize package record - info[i] = (ManifestPackage *)calloc(1, sizeof(ManifestPackage)); + info->packages[i] = (ManifestPackage *) calloc(1, sizeof(ManifestPackage)); // Copy dependencies if (deps->records) { - info[i]->requirements = (char **) calloc(deps->__size, sizeof(char *)); + info->packages[i]->requirements = (char **) calloc(deps->__size, sizeof(char *)); for (int j = 0; j < deps->records; j++) { - info[i]->requirements[j] = (char *) calloc(strlen(deps->list[j]) + 1, sizeof(char)); - strncpy(info[i]->requirements[j], deps->list[j], strlen(deps->list[j])); + info->packages[i]->requirements[j] = (char *) calloc(strlen(deps->list[j]) + 1, sizeof(char)); + strncpy(info->packages[i]->requirements[j], deps->list[j], strlen(deps->list[j])); } } dep_free(&deps); char **parts = split(fsdata->files[i], "-"); - info[i]->size = get_file_size(fsdata->files[i]); - strncpy(info[i]->archive, basename(fsdata->files[i]), PACKAGE_MEMBER_SIZE); - strncpy(info[i]->name, basename(parts[0]), PACKAGE_MEMBER_SIZE); - strncpy(info[i]->version, parts[1], PACKAGE_MEMBER_SIZE); - strncpy(info[i]->revision, parts[2], PACKAGE_MEMBER_SIZE); - strdelsuffix(info[i]->revision, SPM_PACKAGE_EXTENSION); + info->packages[i]->size = get_file_size(fsdata->files[i]); + strncpy(info->packages[i]->archive, basename(fsdata->files[i]), PACKAGE_MEMBER_SIZE); + strncpy(info->packages[i]->name, basename(parts[0]), PACKAGE_MEMBER_SIZE); + strncpy(info->packages[i]->version, parts[1], PACKAGE_MEMBER_SIZE); + strncpy(info->packages[i]->revision, parts[2], PACKAGE_MEMBER_SIZE); + strdelsuffix(info->packages[i]->revision, SPM_PACKAGE_EXTENSION); split_free(parts); - total_records++; } - printf("\n"); + //printf("\n"); + return info; +} + +void manifest_free(Manifest *info) { + for (int i = 0; i < info->records; i++) { + if (info->packages[i]->requirements) { + for (int j = 0; info->packages[i]->requirements[j] != NULL; j++) { + free(info->packages[i]->requirements[j]); + } + free(info->packages[i]->requirements); + } + free(info->packages[i]); + } + free(info->packages); + free(info); +} +int manifest_write(Manifest *info) { + const char *filename = "manifest.dat"; + char path[PATH_MAX]; + memset(path, '\0', sizeof(path)); + sprintf(path, "%s%c%s", SPM_GLOBAL.user_config_basedir, DIRSEP, filename); FILE *fp = fopen(path, "w+"); - char *reqs; - for (int i = 0; i < total_records; i++) { - if (SPM_GLOBAL.verbose) { + char *reqs = NULL; + + if (SPM_GLOBAL.verbose) { + for (int i = 0; i < info->records; i++) { printf("%-20s: %s\n" "%-20s: %lu\n" "%-20s: %s\n" "%-20s: %s\n" "%-20s: %s\n", - "archive", info[i]->archive, - "size", info[i]->size, - "name", info[i]->name, - "version", info[i]->version, - "revision", info[i]->revision + "archive", info->packages[i]->archive, + "size", info->packages[i]->size, + "name", info->packages[i]->name, + "version", info->packages[i]->version, + "revision", info->packages[i]->revision ); - reqs = join(info[i]->requirements, ", "); + reqs = join(info->packages[i]->requirements, ", "); printf("%-20s: %s\n", "requirements", reqs ? reqs : "NONE"); free(reqs); printf("\n"); } - } - printf("Generating manifest: %s\n", path); - for (int i = 0; i < total_records; i++) { + printf("Generating manifest file: %s\n", path); + for (int i = 0; i < info->records; i++) { // write CSV-like manifest char data[BUFSIZ]; memset(data, '\0', BUFSIZ); char *dptr = data; - float percent = (((float)i + 1) / total_records) * 100; - printf("[%3.0f%%] %s\n", percent, info[i]->archive); - reqs = join(info[i]->requirements, ","); + float percent = (((float)i + 1) / info->records) * 100; + printf("[%3.0f%%] %s\n", percent, info->packages[i]->archive); + reqs = join(info->packages[i]->requirements, ","); sprintf(dptr, "%s|" // archive "%lu|" // size "%s|" // name "%s|" // version "%s|" // revision "%s" // requirements - , info[i]->archive, info[i]->size, info[i]->name, info[i]->version, info[i]->revision, reqs ? reqs : "*"); + , info->packages[i]->archive, info->packages[i]->size, info->packages[i]->name, info->packages[i]->version, info->packages[i]->revision, reqs ? reqs : "*"); fprintf(fp, "%s\n", dptr); free(reqs); } fclose(fp); + return 0; +} + +Manifest *manifest_read(void) { + const char *filename = "manifest.dat"; + char path[PATH_MAX]; + memset(path, '\0', sizeof(path)); + sprintf(path, "%s%c%s", SPM_GLOBAL.user_config_basedir, DIRSEP, filename); + FILE *fp = fopen(path, "r+"); + if (!fp) { + perror(filename); + return NULL; + } + int total_records = 0; + char data[BUFSIZ]; + char *dptr = data; + memset(dptr, '\0', BUFSIZ); + + while (fgets(dptr, BUFSIZ, fp) != NULL) { + total_records++; + } + rewind(fp); + + Manifest *info = (Manifest *)calloc(1, sizeof(Manifest)); + info->packages = (ManifestPackage **)calloc(total_records + 1, sizeof(ManifestPackage *)); + + int i = 0; + while (fgets(dptr, BUFSIZ, fp) != NULL) { + dptr = strip(dptr); + char *garbage; + char **parts = split(dptr, "|"); + + info->packages[i] = (ManifestPackage *)calloc(1, sizeof(ManifestPackage)); + strncpy(info->packages[i]->archive, parts[0], strlen(parts[0])); + info->packages[i]->size = strtoul(parts[1], &garbage, 10); + strncpy(info->packages[i]->name, parts[2], strlen(parts[2])); + strncpy(info->packages[i]->version, parts[3], strlen(parts[3])); + strncpy(info->packages[i]->revision, parts[4], strlen(parts[4])); + + info->packages[i]->requirements = NULL; + if (strncmp(parts[5], "*", 2) != 0) { + info->packages[i]->requirements = split(parts[5], ","); + } + split_free(parts); + info->records = i; + i++; + } + + fclose(fp); + return info; } + +ManifestPackage *manifest_search(Manifest *info, const char *_package) { + char package[PATH_MAX]; + + memset(package, '\0', PATH_MAX); + strncpy(package, _package, PATH_MAX); + strcat(package, "*"); + + for (int i = 0; i < info->records; i++) { + if (fnmatch(package, info->packages[i]->archive, FNM_PATHNAME) == 0) { + return info->packages[i]; + } + } + return NULL; +}
\ No newline at end of file @@ -64,7 +64,9 @@ int main(int argc, char *argv[]) { SPM_GLOBAL.verbose = 1; } else if (strcmp(arg, "--reindex") == 0) { - manifest_create(SPM_GLOBAL.package_dir); + Manifest *info = manifest_from(SPM_GLOBAL.package_dir); + manifest_write(info); + manifest_free(info); exit(0); } else if (strcmp(arg, "-r") == 0 || strcmp(arg, "--root") == 0) { @@ -115,6 +117,14 @@ int main(int argc, char *argv[]) { Dependencies *deps = NULL; dep_init(&deps); + printf("Reading package manifest... "); + Manifest *manifest = manifest_read(); + if (!manifest) { + fprintf(stderr, "Package manifest is missing or corrupt\n"); + exit(1); + } + printf("done\n"); + if (isempty(root)) { printf("Using default installation root\n"); sprintf(root, "%s%c%s", getenv("HOME"), DIRSEP, "spm_root"); @@ -132,13 +142,20 @@ int main(int argc, char *argv[]) { printf("Resolving package requirements...\n"); for (int i = 0; i < PACKAGE_MAX; i++) { - char *match = NULL; - char *package = NULL; - + ManifestPackage *package = NULL; if (packages[i] == NULL) { break; } + package = manifest_search(manifest, packages[i]); + + // If the package has dependencies listed, append them to `deps` now + if (package && package->requirements) { + for (int p = 0; package->requirements[p] != NULL; p++) { + dep_append(&deps, package->requirements[p]); + } + } + /* if ((match = find_package(packages[i])) == NULL) { fprintf(SYSERROR); exit(1); @@ -148,8 +165,9 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Unable to derive package name from package path:\n\t-> %s\n", match); exit(1); } + */ - if (dep_all(&deps, package) < 0) { + if (dep_all(&deps, package->archive) < 0) { dep_free(&deps); free_global_config(); exit(1); |