commit ac0a4dfc3547f38c3fe0544f329f3c7bded24010 from: Omar Polo date: Thu Mar 28 11:08:18 2024 UTC got-notify-http: change the layout of the json Split the author/committer in sub-fields, rename author -> committer in the short format parser and cache the author for the long format in case it's the same user as the committer. Put a copy of the first line of the commit message in the "short_message" field. There's some redundancy now, but it's to make consuming easier. ok stsp@ commit - 909ef56bac18cdc0d889412542697be574acfe6b commit + ac0a4dfc3547f38c3fe0544f329f3c7bded24010 blob - e1dd226bd532d7adaf1e4712e8c13bf3cc29ffba blob + 65830ea27b3c8094af7418498500f922ed75ecee --- gotd/libexec/got-notify-http/got-notify-http.c +++ gotd/libexec/got-notify-http/got-notify-http.c @@ -149,6 +149,46 @@ json_field(FILE *fp, const char *key, const char *val, fprintf(fp, "\"%s", comma ? "," : ""); } +static void +json_author(FILE *fp, const char *type, char *address, int comma) +{ + char *gt, *lt, *at, *email, *endname; + + fprintf(fp, "\"%s\":{", type); + + gt = strchr(address, '<'); + if (gt != NULL) { + /* long format, e.g. "Omar Polo " */ + + json_field(fp, "full", address, 1); + + endname = gt; + while (endname > address && endname[-1] == ' ') + endname--; + + *endname = '\0'; + json_field(fp, "name", address, 1); + + email = gt + 1; + lt = strchr(email, '>'); + if (lt) + *lt = '\0'; + + json_field(fp, "mail", email, 1); + + at = strchr(email, '@'); + if (at) + *at = '\0'; + + json_field(fp, "user", email, 0); + } else { + /* short format only shows the username */ + json_field(fp, "user", address, 0); + } + + fprintf(fp, "}%s", comma ? "," : ""); +} + static int jsonify_short(FILE *fp) { @@ -187,9 +227,9 @@ jsonify_short(FILE *fp) fprintf(fp, "{\"short\":true,"); json_field(fp, "id", id, 1); - json_field(fp, "author", author, 1); + json_author(fp, "committer", author, 1); json_field(fp, "date", date, 1); - json_field(fp, "message", message, 0); + json_field(fp, "short_message", message, 0); fprintf(fp, "}"); } @@ -206,6 +246,7 @@ static int jsonify(FILE *fp) { const char *errstr; + char *author = NULL; char *l; char *line = NULL; size_t linesize = 0; @@ -254,7 +295,13 @@ jsonify(FILE *fp) if (strncmp(l, "from: ", 6) != 0) errx(1, "unexpected from line"); l += 6; - json_field(fp, "author", l, 1); + + author = strdup(l); + if (author == NULL) + err(1, "strdup"); + + json_author(fp, "author", l, 1); + phase = P_VIA; break; @@ -262,10 +309,17 @@ jsonify(FILE *fp) /* optional */ if (!strncmp(l, "via: ", 5)) { l += 5; - json_field(fp, "via", l, 1); + json_author(fp, "committer", l, 1); phase = P_DATE; break; } + + if (author == NULL) /* impossible */ + err(1, "from not specified"); + json_author(fp, "committer", author, 1); + free(author); + author = NULL; + phase = P_DATE; /* fallthrough */ @@ -313,7 +367,6 @@ jsonify(FILE *fp) if (errstr) errx(1, "message len is %s: %s", errstr, l); - fprintf(fp, "\"message\":\""); phase = P_MSG; break; @@ -329,14 +382,21 @@ jsonify(FILE *fp) * tolerate one byte less than advertised. */ if (*l == ' ') { - escape(fp, l + 1); /* skip leading space */ + l++; /* skip leading space */ + linelen--; - /* avoid pre-pending \n to the commit msg */ - msgwrote += linelen - 1; - if (msgwrote != 0) + if (msgwrote == 0 && linelen != 0) { + json_field(fp, "short_message", l, 1); + fprintf(fp, "\"message\":\""); + escape(fp, l); + escape(fp, "\n"); + msgwrote += linelen; + } else if (msgwrote != 0) { + escape(fp, l); escape(fp, "\n"); + } } - msglen -= linelen; + msglen -= linelen + 1; if (msglen <= 1) { fprintf(fp, "\","); msgwrote = 0; blob - f52fcec4add98bdb2e991b6ef2ce5efd55a54784 blob + 51fc31fca5b661529114910cf87eed04f5611301 --- regress/gotd/http_notification.sh +++ regress/gotd/http_notification.sh @@ -62,8 +62,20 @@ test_file_changed() { {"notifications":[{ "short":false, "id":"$commit_id", - "author":"$GOT_AUTHOR", + "author":{ + "full":"$GOT_AUTHOR", + "name":"$GIT_AUTHOR_NAME", + "mail":"$GIT_AUTHOR_EMAIL", + "user":"$GOT_AUTHOR_11" + }, + "committer":{ + "full":"$GOT_AUTHOR", + "name":"$GIT_AUTHOR_NAME", + "mail":"$GIT_AUTHOR_EMAIL", + "user":"$GOT_AUTHOR_11" + }, "date":"$d", + "short_message":"make changes", "message":"make changes\n", "diffstat":{}, "changes":{} @@ -131,8 +143,20 @@ test_bad_utf8() { {"notifications":[{ "short":false, "id":"$commit_id", - "author":"$GOT_AUTHOR", + "author":{ + "full":"$GOT_AUTHOR", + "name":"$GIT_AUTHOR_NAME", + "mail":"$GIT_AUTHOR_EMAIL", + "user":"$GOT_AUTHOR_11" + }, + "committer":{ + "full":"$GOT_AUTHOR", + "name":"$GIT_AUTHOR_NAME", + "mail":"$GIT_AUTHOR_EMAIL", + "user":"$GOT_AUTHOR_11" + }, "date":"$d", + "short_message":"make\uFFFD\uFFFDchanges", "message":"make\uFFFD\uFFFDchanges\n", "diffstat":{}, "changes":{} @@ -208,8 +232,20 @@ test_many_commits_not_summarized() { { "short":false, "id":"$commit_id", - "author":"$GOT_AUTHOR", + "author":{ + "full":"$GOT_AUTHOR", + "name":"$GIT_AUTHOR_NAME", + "mail":"$GIT_AUTHOR_EMAIL", + "user":"$GOT_AUTHOR_11" + }, + "committer":{ + "full":"$GOT_AUTHOR", + "name":"$GIT_AUTHOR_NAME", + "mail":"$GIT_AUTHOR_EMAIL", + "user":"$GOT_AUTHOR_11" + }, "date":"$commit_time", + "short_message":"make changes", "message":"make changes\n", "diffstat":{}, "changes":{} @@ -289,9 +325,11 @@ test_many_commits_summarized() { { "short":true, "id":"$commit_id", - "author":"$GOT_AUTHOR_8", + "committer":{ + "user":"$GOT_AUTHOR_8" + }, "date":"$commit_time", - "message":"make changes" + "short_message":"make changes" } EOF done >> $testroot/stdout.expected