]> pd.if.org Git - zpackage/blobdiff - src/note.c
move C source files into src
[zpackage] / src / note.c
diff --git a/src/note.c b/src/note.c
new file mode 100644 (file)
index 0000000..d6c9df1
--- /dev/null
@@ -0,0 +1,255 @@
+#define _POSIX_C_SOURCE 200809L
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include "zpm.h"
+
+void usage(void) {
+       fprintf(stderr, "zpm-note [-I] [-s <status> ...] [-S <status>] [package]\n");
+}
+
+void show_note(struct zpm_note *n) {
+       printf("Note %" PRId64 " %s\n", n->id, n->ts);
+       if (n->pkgid) {
+               printf("Package: %s\n", n->pkgid);
+       }
+       if (n->path) {
+               printf("Path: %s\n", n->pkgid);
+       }
+       if (n->file) {
+               printf("Hash: %s\n", n->file);
+       }
+
+       printf("%s\n", n->note);
+}
+
+void jstring(char *field, char *value, int indent, int final) {
+       while (indent--) {
+               putchar('\t');
+       }
+       printf("\"%s\": ", field);
+       if (value) {
+               while (*value) {
+                       if (strchr("\"\\\b\f\n\r\t", *value)) {
+                               putchar('\\');
+                       }
+                       putchar(*value++);
+               }
+       } else {
+               printf("null");
+       }
+       if (!final) {
+               printf(",");
+       }
+       putchar('\n');
+}
+
+void show_json(struct zpm_note *n) {
+       size_t len = 0;
+
+       if (n->pkgid) {
+               len = strcspn(n->note, "\n\r");
+       }
+
+       printf("{\n\t\"id\": %" PRId64 ",\n", n->id);
+       jstring("package", n->pkgid, 1, 0);
+       jstring("hash", n->file, 1, 0);
+       jstring("path", n->path, 1, 0);
+
+       if (len) {
+               printf("\t\"subject\": \"%.*s\",\n", (int)len, n->note);
+       } else {
+               printf("\t\"subject\": null,\n");
+       }
+       jstring("note", n->note, 1, 1);
+       printf("}\n");
+}
+
+void print_note(struct zpm_note *n) {
+       size_t len;
+       size_t space = 66;
+       uint64_t id = n->id;
+
+       if (n->pkgid) {
+               space -= strlen(n->pkgid);
+       } else {
+               space -= 1;
+       }
+
+       do {
+               space--;
+       } while (id /= 10);
+
+       len = strcspn(n->note, "\n\r");
+       if (len > space) {
+               len = space;
+       }
+
+       printf("%" PRId64 " %.10s %s %.*s\n", n->id, n->ts,
+               n->pkgid ? n->pkgid : "-", (int)len, n->note);
+}
+
+int main(int ac, char **av){
+       int opt;
+       struct zpm pkg;
+       char *dbfile;
+       int fail, echo = 0;
+       int64_t start = 0, end = INT64_MAX;
+       char *range = 0;
+
+       int select = 1;
+
+       struct zpm_note n = { 0 };
+       n.pkgid = 0;
+       n.hash = 0;
+       n.path = 0;
+       n.ts = 0;
+
+       dbfile = getenv("ZPMDB");
+       if (!dbfile) {
+               dbfile = "/var/lib/zpm/local.db";
+       }
+
+       /* -l list
+        * -p packageid
+        * -A ack
+        * -n note id
+        * -D delete
+        * -H hash
+        * -m note message, otherwise EDITOR/vi to edit a text file
+        * -e echo note after creating
+        * zpm note -p pkgid -P path -H hash -m 'foo'
+        * zpm note -l
+        * zpm note -D <n>
+        * zpm note -A <n>
+        */
+       int list = 0, delete = 0, ack = 0, show = 0, json = 0;
+       char *notefrom = 0;
+       while ((opt = getopt(ac, av, "f:p:P:H:m:n:lDAauesjF:")) != -1) {
+               switch (opt) {
+                       case 'f': dbfile = optarg; break;
+                       case 'p': n.pkgid = optarg; break;
+                       case 'P': n.path = optarg; break;
+                       case 'H': n.hash = optarg; break;
+                       case 'm': n.note = optarg; break;
+                       case 'F': notefrom = optarg; break;
+                       case 'n': range = optarg; break;
+                       case 'l': list = 1; break;
+                       case 'j': json = 1; break;
+                       case 's': show = 1; break;
+                       case 'e': echo = 1; break;
+                       case 'D': delete = 1; break;
+                       case 'A': ack = 1; break;
+                       case 'a': select |= 2; break;
+                       case 'u': select |= 6; break;
+
+                       default:
+                                 usage();
+                                 exit(EXIT_FAILURE);
+                                 break;
+               }
+       }
+/* 0x1 = next note,
+ * 0x2 = include acked
+ * 0x4 = suppress unack, implies 0x2
+ */
+
+       if (range) {
+               if (*range == '-') {
+                       start = 0;
+                       end = strtoll(range+1, NULL, 10);
+               } else if (isdigit(*range)) {
+                       char *next;
+                       start = strtoll(range, &next, 10);
+                       if (next && *next == '-') {
+                               end = -1;
+                               next++;
+                               if (isdigit(*next)) {
+                                       end = strtoll(next, NULL, 10);
+                               }
+                       } else {
+                               end = start;
+                       }
+               }
+       }
+
+       if (!dbfile) {
+               fprintf(stderr, "must specify db\n");
+               return 1;
+       }
+
+       /* given a package name, get the packages */
+       /* no package name, get all */
+       char *filenote = 0;
+       if (notefrom) {
+               size_t in = 0;
+               ssize_t cread = 0;
+               FILE *input;
+
+               if (strcmp(notefrom, "-")) {
+                       input = fopen(notefrom, "r");
+               } else {
+                       input = stdin;
+               }
+               if (!input) {
+                       perror("can't read input file");
+                       exit(EXIT_FAILURE);
+               }
+               cread = getdelim(&filenote, &in, 0, input);
+               if (cread == -1) {
+                       perror("error reading file");
+                       exit(EXIT_FAILURE);
+               }
+               n.note = filenote;
+       }
+
+       if (zpm_open(&pkg, dbfile)) {
+               if (list || show || delete || ack) {
+                       n.id = start ? start - 1 : start;
+                       while (zpm_note(&pkg, &n, select)) {
+                               if (n.id > end) {
+                                       break;
+                               }
+                               if (delete) {
+                                       zpm_note_del(&pkg, n.id);
+                               } else if (ack) {
+                                       zpm_note_ack(&pkg, n.id);
+                               } else if (show) {
+                                       if (json) {
+                                               show_json(&n);
+                                       } else {
+                                               show_note(&n);
+                                       }
+                               } else {
+                                       print_note(&n);
+                               }
+                               zpm_note_free(&n);
+                       }
+                       zpm_note_free(&n);
+               } else if (n.note) {
+                       n.id = zpm_note_add(&pkg, n.pkgid, n.path, n.hash, "%s", n.note);
+                       zpm_note(&pkg, &n, 2);
+                       if (n.id) {
+                               if (echo) {
+                                       print_note(&n);
+                               } else {
+                                       printf("%" PRId64 "\n", n.id);
+                               }
+                       } else {
+                               fprintf(stderr, "unable to create note\n");
+                               pkg.error = 1;
+                       }
+               }
+       } else {
+               fprintf(stderr, "unable to open %s\n", dbfile);
+       }
+       fail = pkg.error;
+       zpm_close(&pkg);
+       free(filenote);
+       return fail ? EXIT_FAILURE : EXIT_SUCCESS;
+}