commit c50aaf5dd08bf5e85ffcd1083eea671131c02cf9 from: Omar Polo via: Thomas Adam date: Thu Apr 25 14:57:52 2024 UTC got-notify-http: use a UNIX timestamp for the date Was suggested by Lucas some time ago. ok stsp@ with a tweak in the manual. commit - 507e51543a1bead6c8b3d28a06e2d9a42128a497 commit + c50aaf5dd08bf5e85ffcd1083eea671131c02cf9 blob - a346ab5981dac6f616103dfdb281f5c2785c60a2 blob + c23b8863b3184121b8c368dd247b965685f04711 --- gotd/gotd.conf.5 +++ gotd/gotd.conf.5 @@ -402,14 +402,7 @@ Has the same fields as the .Dv committer but may be unset. .It Dv date -String representation of the date as -.Xr strftime 3 -.Sq %G-%m-%d -if -.Dv short -is set or -.Sq %a %b %e %X %Y UTC -otherwise. +Number, representing the number of seconds since the Epoch in UTC. .It Dv short_message The first line of the commit message. This field is always set. @@ -474,7 +467,7 @@ field for the .Dv commit notification but with all the field guaranteed to be set. .It Dv date -The tag date. +Number, representing the number of seconds since the Epoch in UTC. .It Dv object The object being tagged. It contains the fields blob - cae8aab327ffe2e551a8ed1e0c483d8184b464ca blob + 75f0a71a993d2d1312fd6de84f8337b38bae0eb5 --- gotd/libexec/got-notify-email/got-notify-email.c +++ gotd/libexec/got-notify-email/got-notify-email.c @@ -19,12 +19,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -213,6 +215,39 @@ get_datestr(time_t *time, char *datebuf) if (p) *p = '\0'; return s; +} + +static const struct got_error * +print_date(int s, char *date, int shortfmt) +{ + const struct got_error *error; + struct tm tm; + char *t, datebuf[26]; + const char *errstr; + time_t ts; + + date[strcspn(date, " \n")] = '\0'; + + ts = strtonum(date, INT64_MIN, INT64_MAX, &errstr); + if (errstr) + return got_error_set_errno(EINVAL, errstr); + if (gmtime_r(&ts, &tm) == NULL) + return got_error_set_errno(EINVAL, "gmtime_r"); + + if (!shortfmt) { + t = asctime_r(&tm, datebuf); + if (t == NULL) + return got_error_set_errno(EINVAL, "invalid timestamp"); + t[strcspn(t, "\n")] = '\0'; + error = got_poll_write_full(s, t, strlen(t)); + if (error) + return error; + return got_poll_write_full(s, " UTC\n", 5); + } + + if (strftime(datebuf, sizeof(datebuf), "%G-%m-%d ", &tm) == 0) + return got_error_set_errno(EINVAL, "invalid timestamp"); + return got_poll_write_full(s, datebuf, strlen(datebuf)); } static void @@ -225,6 +260,7 @@ send_email(int s, const char *myfromaddr, const char * size_t linesize = 0; ssize_t linelen; time_t now; + int firstline = 1, shortfmt = 0; char datebuf[26]; char *datestr; @@ -272,11 +308,39 @@ send_email(int s, const char *myfromaddr, const char * fatalx("could not send body delimiter"); while ((linelen = getline(&line, &linesize, stdin)) != -1) { + if (firstline && isdigit((unsigned char)line[0])) + shortfmt = 1; + firstline = 0; + if (line[0] == '.') { /* dot stuffing */ error = got_poll_write_full(s, ".", 1); if (error) fatalx("write: %s", error->msg); } + + if (shortfmt) { + char *t; + t = strchr(line, ' '); + if (t != NULL) { + *t++ = '\0'; + error = print_date(s, line, shortfmt); + if (error) + fatalx("write: %s", error->msg); + error = got_poll_write_full(s, t, strlen(t)); + continue; + } + } + + if (!shortfmt && !strncmp(line, "date: ", 6)) { + error = got_poll_write_full(s, line, 6); + if (error) + fatalx("write: %s", error->msg); + error = print_date(s, line + 6, shortfmt); + if (error) + fatalx("write: %s", error->msg); + continue; + } + error = got_poll_write_full(s, line, linelen); if (error) fatalx("write: %s", error->msg); blob - 6e6ae09721ee923cf1a1ccdf2f923c827ddf6515 blob + dd22bd86ae1dcd235e42d96a4df407c3dd81bbf1 --- gotd/libexec/got-notify-http/got-notify-http.c +++ gotd/libexec/got-notify-http/got-notify-http.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "got_opentemp.h" @@ -155,6 +156,12 @@ json_field(FILE *fp, const char *key, const char *val, } static void +json_date(FILE *fp, const char *key, const char *date, int comma) +{ + fprintf(fp, "\"%s\":%s%s", key, date, comma ? "," : ""); +} + +static void json_author(FILE *fp, const char *type, char *address, int comma) { char *gt, *lt, *at, *email, *endname; @@ -249,7 +256,7 @@ jsonify_commit_short(FILE *fp, char *line, const char json_field(fp, "repo", repo, 1); json_field(fp, "id", id, 1); json_author(fp, "committer", author, 1); - json_field(fp, "date", date, 1); + json_date(fp, "date", date, 1); json_field(fp, "short_message", message, 0); fprintf(fp, "}"); @@ -333,7 +340,7 @@ jsonify_commit(FILE *fp, const char *repo, char **line /* optional */ if (!strncmp(l, "date: ", 6)) { l += 6; - json_field(fp, "date", l, 1); + json_date(fp, "date", l, 1); phase = P_PARENT; break; } @@ -600,7 +607,7 @@ jsonify_tag(FILE *fp, const char *repo, char **line, s /* optional */ if (!strncmp(l, "date: ", 6)) { l += 6; - json_field(fp, "date", l, 1); + json_date(fp, "date", l, 1); phase = P_OBJECT; break; } blob - b18824c78210f17cdbdf61418796a33c9c625dab blob + 2a988d038319e56cbdae6ff83f7b219568c799c5 --- gotd/notify.c +++ gotd/notify.c @@ -240,7 +240,7 @@ notify_email(struct gotd_notification_target *target, argv[i++] = "-h"; argv[i++] = target->conf.email.hostname; } - + if (target->conf.email.port) { argv[i++] = "-p"; argv[i++] = target->conf.email.port; blob - a3d6e136d6d6177e9d7b51fc442a887b6e2b37c2 blob + 957cb87ecdef45c6b44c8a009eb5acf4501eef09 --- gotd/repo_write.c +++ gotd/repo_write.c @@ -1626,25 +1626,7 @@ receive_pack_idx(struct imsg *imsg, struct gotd_imsgev return NULL; } - -static char * -get_datestr(time_t *time, char *datebuf) -{ - struct tm mytm, *tm; - char *p, *s; - tm = gmtime_r(time, &mytm); - if (tm == NULL) - return NULL; - s = asctime_r(tm, datebuf); - if (s == NULL) - return NULL; - p = strchr(s, '\n'); - if (p) - *p = '\0'; - return s; -} - static const struct got_error * notify_removed_ref(const char *refname, uint8_t *sha1, struct gotd_imsgev *iev, int fd) @@ -1686,8 +1668,6 @@ print_commit_oneline(struct got_commit_object *commit, char *id_str = NULL, *logmsg0 = NULL; char *s, *nl; char *committer = NULL, *author = NULL; - char datebuf[12]; /* YYYY-MM-DD + SPACE + NUL */ - struct tm tm; time_t committer_time; err = got_object_id_str(&id_str, id); @@ -1695,14 +1675,6 @@ print_commit_oneline(struct got_commit_object *commit, return err; committer_time = got_object_commit_get_committer_time(commit); - if (gmtime_r(&committer_time, &tm) == NULL) { - err = got_error_from_errno("gmtime_r"); - goto done; - } - if (strftime(datebuf, sizeof(datebuf), "%G-%m-%d ", &tm) == 0) { - err = got_error(GOT_ERR_NO_SPACE); - goto done; - } err = got_object_commit_get_logmsg(&logmsg0, commit); if (err) @@ -1724,16 +1696,12 @@ print_commit_oneline(struct got_commit_object *commit, err = got_error_from_errno("strdup"); goto done; } - dprintf(fd, "%s%.7s %.8s %s\n", datebuf, id_str, - format_author(author), s); + dprintf(fd, "%lld %.7s %.8s %s\n", (long long)committer_time, + id_str, format_author(author), s); } else { committer = strdup(got_object_commit_get_committer(commit)); - if (committer == NULL) { - err = got_error_from_errno("strdup"); - goto done; - } - dprintf(fd, "%s%.7s %.8s %s\n", datebuf, id_str, - format_author(committer), s); + dprintf(fd, "%lld %.7s %.8s %s\n", (long long)committer_time, + id_str, format_author(committer), s); } if (fsync(fd) == -1 && err == NULL) @@ -1773,8 +1741,7 @@ print_commit(struct got_commit_object *commit, struct struct got_diffstat_cb_arg *diffstat, int fd) { const struct got_error *err = NULL; - char *id_str, *datestr, *logmsg0, *logmsg, *line; - char datebuf[26]; + char *id_str, *logmsg0, *logmsg, *line; time_t committer_time; const char *author, *committer; @@ -1791,9 +1758,7 @@ print_commit(struct got_commit_object *commit, struct if (strcmp(author, committer) != 0) dprintf(fd, "via: %s\n", committer); committer_time = got_object_commit_get_committer_time(commit); - datestr = get_datestr(&committer_time, datebuf); - if (datestr) - dprintf(fd, "date: %s UTC\n", datestr); + dprintf(fd, "date: %lld\n", (long long)committer_time); if (got_object_commit_get_nparents(commit) > 1) { const struct got_object_id_queue *parent_ids; struct got_object_qid *qid; @@ -2002,8 +1967,7 @@ print_tag(struct got_object_id *id, const struct got_error *err = NULL; struct got_tag_object *tag = NULL; const char *tagger = NULL; - char *id_str = NULL, *tagmsg0 = NULL, *tagmsg, *line, *datestr; - char datebuf[26]; + char *id_str = NULL, *tagmsg0 = NULL, *tagmsg, *line; time_t tagger_time; err = got_object_open_as_tag(&tag, repo, id); @@ -2019,9 +1983,7 @@ print_tag(struct got_object_id *id, dprintf(fd, "tag %s\n", refname); dprintf(fd, "from: %s\n", tagger); - datestr = get_datestr(&tagger_time, datebuf); - if (datestr) - dprintf(fd, "date: %s UTC\n", datestr); + dprintf(fd, "date: %lld\n", (long long)tagger_time); switch (got_object_tag_get_object_type(tag)) { case GOT_OBJ_TYPE_BLOB: blob - 18726da0df985a0e71d65fb2408032c6677ffe00 blob + 23a8d91f145b36a4fca7522f147af43bd6c98956 --- regress/gotd/http_notification.sh +++ regress/gotd/http_notification.sh @@ -57,8 +57,6 @@ test_file_changed() { wait %1 # wait for the http "server" - d=`date -u -r $author_time +"%a %b %e %X %Y UTC"` - touch "$testroot/stdout.expected" ed -s "$testroot/stdout.expected" <<-EOF a @@ -79,7 +77,7 @@ test_file_changed() { "mail":"$GIT_AUTHOR_EMAIL", "user":"$GOT_AUTHOR_11" }, - "date":"$d", + "date":$author_time, "short_message":"make changes", "message":"make changes\n", "diffstat":{ @@ -150,8 +148,6 @@ test_bad_utf8() { wait %1 # wait for the http "server" - d=`date -u -r $author_time +"%a %b %e %X %Y UTC"` - touch "$testroot/stdout.expected" ed -s "$testroot/stdout.expected" <<-EOF a @@ -172,7 +168,7 @@ test_bad_utf8() { "mail":"$GIT_AUTHOR_EMAIL", "user":"$GOT_AUTHOR_11" }, - "date":"$d", + "date":$author_time, "short_message":"make\uFFFD\uFFFDchanges", "message":"make\uFFFD\uFFFDchanges\n", "diffstat":{ @@ -228,8 +224,7 @@ test_many_commits_not_summarized() { (cd $testroot/wt && got commit -m 'make changes' > /dev/null) local commit_id=`git_show_head $testroot/repo-clone` local author_time=`git_show_author_time $testroot/repo-clone` - d=`date -u -r $author_time +"%a %b %e %X %Y UTC"` - set -- "$@" "$commit_id $d" + set -- "$@" "$commit_id $author_time" done timeout 5 ./http-server -a $AUTH -p "$GOTD_TEST_HTTP_PORT" \ @@ -273,7 +268,7 @@ test_many_commits_not_summarized() { "mail":"$GIT_AUTHOR_EMAIL", "user":"$GOT_AUTHOR_11" }, - "date":"$commit_time", + "date":$commit_time, "short_message":"make changes", "message":"make changes\n", "diffstat":{ @@ -333,8 +328,7 @@ test_many_commits_summarized() { local commit_id=`git_show_head $testroot/repo-clone` local short_commit_id=`trim_obj_id 33 $commit_id` local author_time=`git_show_author_time $testroot/repo-clone` - d=`date -u -r $author_time +"%G-%m-%d"` - set -- "$@" "$short_commit_id $d" + set -- "$@" "$short_commit_id $author_time" done timeout 5 ./http-server -a $AUTH -p "$GOTD_TEST_HTTP_PORT" \ @@ -355,7 +349,7 @@ test_many_commits_summarized() { for i in `seq 1 51`; do s=`pop_idx $i "$@"` commit_id=$(echo $s | cut -d' ' -f1) - commit_time=$(echo "$s" | sed -e "s/^$commit_id //g") + commit_time=$(echo "$s" | cut -d' ' -f2) echo "$comma" comma=',' @@ -369,7 +363,7 @@ test_many_commits_summarized() { "committer":{ "user":"$GOT_AUTHOR_8" }, - "date":"$commit_time", + "date":$commit_time, "short_message":"make changes" } EOF @@ -430,8 +424,6 @@ test_branch_created() { wait %1 # wait for the http "server" - d=`date -u -r $author_time +"%a %b %e %X %Y UTC"` - # in the future it should contain something like this too # { # "type":"new-branch", @@ -460,7 +452,7 @@ test_branch_created() { "mail":"$GIT_AUTHOR_EMAIL", "user":"$GOT_AUTHOR_11" }, - "date":"$d", + "date":$author_time, "short_message":"newbranch", "message":"newbranch\n", "diffstat":{ @@ -572,8 +564,6 @@ test_tag_created() { wait %1 # wait for the http "server" - d=`date -u -r $tagger_time +"%a %b %e %X %Y UTC"` - touch "$testroot/stdout.expected" ed -s "$testroot/stdout.expected" <<-EOF a @@ -587,7 +577,7 @@ test_tag_created() { "mail":"$GIT_AUTHOR_EMAIL", "user":"$GOT_AUTHOR_11" }, - "date":"$d", + "date":$tagger_time, "object":{ "type":"commit", "id":"$commit_id" @@ -650,8 +640,6 @@ test_tag_changed() { wait %1 # wait for the http "server" - d=`date -u -r $tagger_time +"%a %b %e %X %Y UTC"` - # XXX: at the moment this is exactly the same as the "new tag" # notification @@ -668,7 +656,7 @@ test_tag_changed() { "mail":"$GIT_AUTHOR_EMAIL", "user":"$GOT_AUTHOR_11" }, - "date":"$d", + "date":$tagger_time, "object":{ "type":"commit", "id":"$commit_id"