]> pd.if.org Git - zpackage/blob - zpm-note.c
use unsigned longs for op counts
[zpackage] / zpm-note.c
1 #define _POSIX_C_SOURCE 200809L
2
3 #include <inttypes.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <ctype.h>
8 #include <unistd.h>
9
10 #include "zpm.h"
11
12 void usage(void) {
13         fprintf(stderr, "zpm-note [-I] [-s <status> ...] [-S <status>] [package]\n");
14 }
15
16 void show_note(struct zpm_note *n) {
17         printf("Note %" PRId64 " %s\n", n->id, n->ts);
18         if (n->pkgid) {
19                 printf("Package: %s\n", n->pkgid);
20         }
21         if (n->path) {
22                 printf("Path: %s\n", n->pkgid);
23         }
24         if (n->file) {
25                 printf("Hash: %s\n", n->file);
26         }
27
28         printf("%s\n", n->note);
29 }
30
31 void jstring(char *field, char *value, int indent, int final) {
32         while (indent--) {
33                 putchar('\t');
34         }
35         printf("\"%s\": ", field);
36         if (value) {
37                 while (*value) {
38                         if (strchr("\"\\\b\f\n\r\t", *value)) {
39                                 putchar('\\');
40                         }
41                         putchar(*value++);
42                 }
43         } else {
44                 printf("null");
45         }
46         if (!final) {
47                 printf(",");
48         }
49         putchar('\n');
50 }
51
52 void show_json(struct zpm_note *n) {
53         size_t len = 0;
54
55         if (n->pkgid) {
56                 len = strcspn(n->note, "\n\r");
57         }
58
59         printf("{\n\t\"id\": %" PRId64 ",\n", n->id);
60         jstring("package", n->pkgid, 1, 0);
61         jstring("hash", n->file, 1, 0);
62         jstring("path", n->path, 1, 0);
63
64         if (len) {
65                 printf("\t\"subject\": \"%.*s\",\n", (int)len, n->note);
66         } else {
67                 printf("\t\"subject\": null,\n");
68         }
69         jstring("note", n->note, 1, 1);
70         printf("}\n");
71 }
72
73 void print_note(struct zpm_note *n) {
74         size_t len;
75         size_t space = 66;
76         uint64_t id = n->id;
77
78         if (n->pkgid) {
79                 space -= strlen(n->pkgid);
80         } else {
81                 space -= 1;
82         }
83
84         do {
85                 space--;
86         } while (id /= 10);
87
88         len = strcspn(n->note, "\n\r");
89         if (len > space) {
90                 len = space;
91         }
92
93         printf("%" PRId64 " %.10s %s %.*s\n", n->id, n->ts,
94                 n->pkgid ? n->pkgid : "-", (int)len, n->note);
95 }
96
97 int main(int ac, char **av){
98         int opt;
99         struct zpm pkg;
100         char *dbfile;
101         int fail, echo = 0;
102         int64_t start = 0, end = INT64_MAX;
103         char *range = 0;
104
105         int select = 1;
106
107         struct zpm_note n = { 0 };
108         n.pkgid = 0;
109         n.hash = 0;
110         n.path = 0;
111         n.ts = 0;
112
113         dbfile = getenv("ZPMDB");
114         if (!dbfile) {
115                 dbfile = "/var/lib/zpm/local.db";
116         }
117
118         /* -l list
119          * -p packageid
120          * -A ack
121          * -n note id
122          * -D delete
123          * -H hash
124          * -m note message, otherwise EDITOR/vi to edit a text file
125          * -e echo note after creating
126          * zpm note -p pkgid -P path -H hash -m 'foo'
127          * zpm note -l
128          * zpm note -D <n>
129          * zpm note -A <n>
130          */
131         int list = 0, delete = 0, ack = 0, show = 0, json = 0;
132         char *notefrom = 0;
133         while ((opt = getopt(ac, av, "f:p:P:H:m:n:lDAauesjF:")) != -1) {
134                 switch (opt) {
135                         case 'f': dbfile = optarg; break;
136                         case 'p': n.pkgid = optarg; break;
137                         case 'P': n.path = optarg; break;
138                         case 'H': n.hash = optarg; break;
139                         case 'm': n.note = optarg; break;
140                         case 'F': notefrom = optarg; break;
141                         case 'n': range = optarg; break;
142                         case 'l': list = 1; break;
143                         case 'j': json = 1; break;
144                         case 's': show = 1; break;
145                         case 'e': echo = 1; break;
146                         case 'D': delete = 1; break;
147                         case 'A': ack = 1; break;
148                         case 'a': select |= 2; break;
149                         case 'u': select |= 6; break;
150
151                         default:
152                                   usage();
153                                   exit(EXIT_FAILURE);
154                                   break;
155                 }
156         }
157 /* 0x1 = next note,
158  * 0x2 = include acked
159  * 0x4 = suppress unack, implies 0x2
160  */
161
162         if (range) {
163                 if (*range == '-') {
164                         start = 0;
165                         end = strtoll(range+1, NULL, 10);
166                 } else if (isdigit(*range)) {
167                         char *next;
168                         start = strtoll(range, &next, 10);
169                         if (next && *next == '-') {
170                                 end = -1;
171                                 next++;
172                                 if (isdigit(*next)) {
173                                         end = strtoll(next, NULL, 10);
174                                 }
175                         } else {
176                                 end = start;
177                         }
178                 }
179         }
180
181         if (!dbfile) {
182                 fprintf(stderr, "must specify db\n");
183                 return 1;
184         }
185
186         /* given a package name, get the packages */
187         /* no package name, get all */
188         char *filenote = 0;
189         if (notefrom) {
190                 size_t in = 0;
191                 ssize_t cread = 0;
192                 FILE *input;
193
194                 if (strcmp(notefrom, "-")) {
195                         input = fopen(notefrom, "r");
196                 } else {
197                         input = stdin;
198                 }
199                 if (!input) {
200                         perror("can't read input file");
201                         exit(EXIT_FAILURE);
202                 }
203                 cread = getdelim(&filenote, &in, 0, input);
204                 if (cread == -1) {
205                         perror("error reading file");
206                         exit(EXIT_FAILURE);
207                 }
208                 n.note = filenote;
209         }
210
211         if (zpm_open(&pkg, dbfile)) {
212                 if (list || show || delete || ack) {
213                         n.id = start ? start - 1 : start;
214                         while (zpm_note(&pkg, &n, select)) {
215                                 if (n.id > end) {
216                                         break;
217                                 }
218                                 if (delete) {
219                                         zpm_note_del(&pkg, n.id);
220                                 } else if (ack) {
221                                         zpm_note_ack(&pkg, n.id);
222                                 } else if (show) {
223                                         if (json) {
224                                                 show_json(&n);
225                                         } else {
226                                                 show_note(&n);
227                                         }
228                                 } else {
229                                         print_note(&n);
230                                 }
231                                 zpm_note_free(&n);
232                         }
233                         zpm_note_free(&n);
234                 } else if (n.note) {
235                         n.id = zpm_note_add(&pkg, n.pkgid, n.path, n.hash, "%s", n.note);
236                         zpm_note(&pkg, &n, 2);
237                         if (n.id) {
238                                 if (echo) {
239                                         print_note(&n);
240                                 } else {
241                                         printf("%" PRId64 "\n", n.id);
242                                 }
243                         } else {
244                                 fprintf(stderr, "unable to create note\n");
245                                 pkg.error = 1;
246                         }
247                 }
248         } else {
249                 fprintf(stderr, "unable to open %s\n", dbfile);
250         }
251         fail = pkg.error;
252         zpm_close(&pkg);
253         free(filenote);
254         return fail ? EXIT_FAILURE : EXIT_SUCCESS;
255 }