aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@users.noreply.github.com>2020-06-08 16:41:55 -0400
committerGitHub <noreply@github.com>2020-06-08 16:41:55 -0400
commitc8ec7fd47c65fdda5d2c32002173789d7381d0d1 (patch)
treea23ab1b0a90f19ad6807687923b99d1ac3173e09
parenta9163234b166945a6d62efedf35940455ef6e138 (diff)
parentcca2365909b3c61c8bb9e83439a7a184c4802b4e (diff)
downloadspmc-c8ec7fd47c65fdda5d2c32002173789d7381d0d1.tar.gz
Merge pull request #46 from jhunkeler/package-info
Package info
-rw-r--r--include/install.h5
-rw-r--r--lib/install.c189
-rw-r--r--src/spm.c72
-rw-r--r--tests/test_spm_get_package_info_str.c38
4 files changed, 240 insertions, 64 deletions
diff --git a/include/install.h b/include/install.h
index bc1fe19..08fe5d8 100644
--- a/include/install.h
+++ b/include/install.h
@@ -6,7 +6,10 @@
int spm_hierarchy_is_root(SPM_Hierarchy *fs);
int spm_hierarchy_make_root(SPM_Hierarchy *fs);
-void spm_install_show_package(ManifestPackage *package);
+char *spm_get_package_info_str(ManifestPackage *package, const char *fmt);
+void spm_show_package(ManifestPackage *package);
+void spm_show_package_manifest(Manifest *info);
+void spm_show_packages(ManifestList *info);
int spm_install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package);
int spm_install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name);
int spm_check_installed(SPM_Hierarchy *fs, char *package_name);
diff --git a/lib/install.c b/lib/install.c
index a2fdf9f..8930362 100644
--- a/lib/install.c
+++ b/lib/install.c
@@ -35,12 +35,191 @@ int spm_hierarchy_make_root(SPM_Hierarchy *fs) {
return 0;
}
-void spm_install_show_package(ManifestPackage *package) {
+/**
+ * Generates a formatted string containing package information
+ *
+ * `%n` = Package name
+ * `%v` = Package version
+ * `%V` = Package version and revision (separated by a hyphen (`-`))
+ * `%r` = Package revision
+ * `%o` = Package origin
+ * `%a` = Package filename on disk
+ * `%c` = Package checksum (sha256)
+ * `%s` = Package size (byte)
+ * `%S` = Package size (human readable)
+ *
+ * @param package Pointer to `ManifestPackage`
+ * @param fmt Format string
+ * @return `malloc()`ed string
+ */
+char *spm_get_package_info_str(ManifestPackage *package, const char *fmt) {
+ // Allocate at least enough space for the character arrays in ManifestPackage (there are several)
+ char *output = calloc(1, sizeof(ManifestPackage));
+
+ // Stores raw record data
+ char tmp[SPM_PACKAGE_MEMBER_SIZE];
+
+ // Stores width string (i.e. '%-12n' is parsed as '12')
+ char str_width[10];
+
+ // Record the maximum number of bytes to read
+ size_t len_fmt = strlen(fmt);
+
+ // Begin reading format string
+ for (size_t i = 0; i < len_fmt; i++) {
+ size_t width = 0; // Default string padding amount
+ int when = -1; // When string padding is applied (-1 = none, 0 = before, 1 = after)
+ char *hrs = NULL; // Buffer for human_readable_size
+
+ // Truncate temporary strings
+ tmp[0] = '\0';
+ str_width[0] = '\0';
+
+ // Begin parsing formatter
+ if (fmt[i] == '%') {
+ // Advance to next character
+ i++;
+
+ // When the next character is a hyphen write string padding after the requested value
+ if (fmt[i] == '-') {
+ when = 1;
+ i++;
+ }
+
+ // Is the next character a number?
+ if (isdigit(fmt[i])) {
+ if (when != 1) { // read as: "if padding not altered already"
+ when = 0; // got no '-' but landed on some digits, so pad "before"
+ }
+
+ // Consume the numerical string and convert it to an integer
+ int j = 0;
+ while (isdigit(fmt[i])) {
+ memcpy(&str_width[j], &fmt[i], 1);
+ j++;
+ i++;
+ }
+ str_width[j] = 0;
+ width = strtoul(str_width, NULL, 10);
+ }
+
+ // Retrieve information based on requested format character'
+ switch (fmt[i]) {
+ case 'n':
+ strcpy(tmp, package->name);
+ break;
+ case 'v':
+ strcpy(tmp, package->version);
+ break;
+ case 'V':
+ strcpy(tmp, package->version);
+ strcat(tmp, "-");
+ strcat(tmp, package->revision);
+ break;
+ case 'r':
+ strcpy(tmp, package->revision);
+ break;
+ case 'o':
+ strcpy(tmp, package->origin);
+ break;
+ case 'a':
+ strcpy(tmp, package->archive);
+ break;
+ case 'c':
+ strcpy(tmp, package->checksum_sha256);
+ break;
+ case 's':
+ sprintf(tmp, "%zu", package->size);
+ break;
+ case 'S':
+ hrs = human_readable_size(package->size);
+ strcpy(tmp, hrs);
+ free(hrs);
+ break;
+ default:
+ // Formatter is not registered above. Oh well.
+ continue;
+ }
+
+ // Pad the string up to the length of the length of `tmp`
+ int width_final = ((int)width - (int)strlen(tmp));
+
+ // When `tmp` is longer than the requested width, use the original width
+ if (width_final < 0) {
+ width_final = width;
+ }
+
+ // Write padding "before" appending `tmp` to the output string
+ if (when == 0) {
+ for (size_t m = 0; m < width_final; m++) {
+ strcat(output, " ");
+ }
+ }
+
+ // Append data to output string
+ strcat(output, tmp);
+
+ // Write padding "after" appending `tmp` to the output string
+ if (when == 1) {
+ for (size_t m = 0; m < width_final; m++) {
+ strcat(output, " ");
+ }
+ }
+ } else {
+ // Data was not parsed as a formatter, so append it to the output string as-is
+ strncat(output, &fmt[i], 1);
+ }
+ }
+
+ return output;
+}
+
+void spm_show_package(ManifestPackage *package) {
+ char *output = NULL;
+
if (package == NULL) {
- fprintf(stderr, "ERROR: package was NULL\n");
+ spmerrno = SPM_ERR_MANIFEST_INVALID;
+ spmerrno_cause("ManifestPackage was NULL\n");
+ return;
+ }
+
+ output = spm_get_package_info_str(package, "%-20n %-10V %8S %4o");
+
+ if (output == NULL) {
+ spmerrno = SPM_ERR_PKG_INVALID;
+ spmerrno_cause("spm_get_package_info_str did not succeed");
return;
}
- printf(" -> %-20s %-10s (origin: %s)\n", package->name, package->version, package->origin);
+ puts(output);
+ free(output);
+}
+
+void spm_show_package_manifest(Manifest *info) {
+ char *output = NULL;
+
+ if (info == NULL) {
+ spmerrno = SPM_ERR_MANIFEST_INVALID;
+ spmerrno_cause("Manifest was NULL\n");
+ return;
+ }
+
+ for (size_t m = 0; m < info->records; m++) {
+ spm_show_package(info->packages[m]);
+ }
+
+}
+void spm_show_packages(ManifestList *info) {
+ char *output = NULL;
+
+ if (info == NULL) {
+ spmerrno = SPM_ERR_MANIFEST_INVALID;
+ spmerrno_cause("ManifestList was NULL");
+ return;
+ }
+
+ for (size_t i = 0; i < manifestlist_count(info); i++) {
+ spm_show_package_manifest(manifestlist_item(info, i));
+ }
}
/**
@@ -249,7 +428,7 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) {
// Install packages
printf("Requested package(s):\n");
for (size_t i = 0; requirements !=NULL && requirements[i] != NULL; i++) {
- spm_install_show_package(requirements[i]);
+ spm_show_package(requirements[i]);
}
if (SPM_GLOBAL.prompt_user) {
@@ -333,7 +512,7 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) {
continue;
}
- spm_install_show_package(requirements[i]);
+ spm_show_package(requirements[i]);
spm_install(fs, tmpdir, package_path);
// Relocate installation root
diff --git a/src/spm.c b/src/spm.c
index 265986e..bb03094 100644
--- a/src/spm.c
+++ b/src/spm.c
@@ -288,74 +288,30 @@ int main(int argc, char *argv[], char *arge[]) {
}
if (RUNTIME_SEARCH || RUNTIME_LIST) {
- char name[255];
- char op[25];
- char ver[255];
- memset(name, '\0', sizeof(name));
- memset(op, '\0', sizeof(op));
- memset(ver, '\0', sizeof(ver));
-
- // Parse the argument string
- int c = 0;
-
- // Populate name
- for (int j = 0; package_search_str[c] != '\0'; j++, c++) {
- if (isrelational(package_search_str[c])) {
- break;
- }
- name[j] = package_search_str[c];
- }
-
- if (RUNTIME_SEARCH) {
- // Populate op
- for (int j = 0; package_search_str[c] != '\0'; j++, c++) {
- if (!isrelational(package_search_str[c])) {
- break;
- }
- op[j] = package_search_str[c];
- }
-
- if (strlen(op)) {
- // Populate version
- for (int j = 0; package_search_str[c] != '\0'; j++, c++) {
- ver[j] = package_search_str[c];
- }
- } else {
- // No operator, so find all versions instead
- strcpy(op, ">=");
- ver[0] = '0';
- }
-
- }
-
int banner_size = 79;
putchar('#');
print_banner("-", banner_size);
- printf("# %-20s %-10s %-10s %-10s %-20s\n", "name", "version", "revision", "size", "origin");
+ printf("# %-18s %s %11s %10s\n", "name", "version", "size", "origin");
putchar('#');
print_banner("-", banner_size);
- for (size_t m = 0; m < manifestlist_count(mf); m++) {
- Manifest *info = manifestlist_item(mf, m);
- if (RUNTIME_SEARCH) {
- ManifestPackage **package = find_by_spec(info, name, op, ver);
- for (int p = 0; package[p] != NULL; p++) {
- char *package_hsize = human_readable_size(package[p]->size);
- printf(" %-20s %-10s %-10s %-10s %20s\n", package[p]->name, package[p]->version, package[p]->revision,
- package_hsize, info->packages[p]->origin);
- free(package_hsize);
- }
- } else if (RUNTIME_LIST) {
- for (size_t p = 0; p < info->records; p++) {
- char *package_hsize = human_readable_size(info->packages[p]->size);
- printf(" %-20s %-10s %-10s %-10s %20s\n", info->packages[p]->name, info->packages[p]->version,
- info->packages[p]->revision, package_hsize, info->packages[p]->origin);
- free(package_hsize);
- }
+ if (RUNTIME_SEARCH) {
+ // Search all known packages
+ for (size_t m = 0; m < manifestlist_count(mf); m++) {
+ Manifest *info = manifestlist_item(mf, m);
+ ManifestPackage *package = find_by_strspec(info, package_search_str);
+ spm_show_package(package);
}
+ } else if (RUNTIME_LIST) {
+ // List all known packages
+ spm_show_packages(mf);
}
}
+ if (spmerrno != 0) {
+ spm_perror("Last error");
+ }
+
runtime_free(rt);
free_global_config();
strlist_free(packages);
diff --git a/tests/test_spm_get_package_info_str.c b/tests/test_spm_get_package_info_str.c
new file mode 100644
index 0000000..c228ccb
--- /dev/null
+++ b/tests/test_spm_get_package_info_str.c
@@ -0,0 +1,38 @@
+#include "spm.h"
+#include "framework.h"
+
+ManifestPackage TESTPKG = {.name = "test", .version = "1.0.0", .revision = "1", .archive = "test-1.0.0-1.tar.gz", .origin = "test_land", .size = 1234};
+const char *testFmt = "returned '%s', expected '%s'\n";
+char *truth[] = {
+ "test 1.0.0 1 test-1.0.0-1.tar.gz test_land 1234 1.21K",
+ " test 1.0.0 1 test-1.0.0-1.tar.gz test_land 1234 1.21K",
+ "test 1.0.0 1 test-1.0.0-1.tar.gz test_land 1234 1.21K",
+ "test 1.0.0-1 ",
+ " test 1.0.0-1",
+};
+size_t numCases = 0;
+
+int main(int argc, char *argv[]) {
+ ManifestPackage *package = &TESTPKG;
+ char *data[] = {
+ spm_get_package_info_str(package, "%n %v %r %a %o %s %S"),
+ spm_get_package_info_str(package, "%10n %v %r %a %o %s %S"),
+ spm_get_package_info_str(package, "%-10n %v %r %a %o %s %S"),
+ spm_get_package_info_str(package, "%-10n %-10V"),
+ spm_get_package_info_str(package, "%10n %10V"),
+ };
+ numCases = sizeof(data) / sizeof(char *);
+
+ if (numCases != (sizeof(truth) / sizeof(char *))) {
+ fprintf(stderr, "Number of test cases does not match number of truth cases\n");
+ return 1;
+ }
+
+ for (size_t i = 0; i < numCases; i++) {
+ puts(data[i]);
+ myassert(strcmp(data[i], truth[i]) == 0, testFmt, data[i], truth[i]);
+ free(data[i]);
+ }
+
+ return 0;
+} \ No newline at end of file