From: Josh Rickmar Subject: Display GMT offset from got cat To: gameoftrees@openbsd.org Date: Wed, 16 Feb 2022 10:44:07 -0500 I understand that we prefer to use and display UTC for got commit, got log, tog, etc. but it seems that got cat should not lie about the GMT offset of commits created by Git. Some additional background: I'd like to eventually add tag signing using SSH keys to Got, and was trying to manually verify the output of 'got cat' using signed tags created by Git. These signatures were failing to verify due to the GMT offset not being printed correctly. With this fixed, I am able to manually verify GPG and SSH signatures after removing the messagelen from the output of got cat. ----------------------------------------------- commit f049cc2be5ab990f4fac3b5fbb7f3f3ee6ae5bf1 (cat_tz) from: Josh Rickmar date: Wed Feb 16 15:42:23 2022 UTC display GMT offset in cat command diff 03f44f51f7e8df35c47add87eb518b0a363d537b 2f99b84397ef3ff37ecae72d204264ca7dc206d3 blob - 7d8663fbddd35a7c2dca7773ddeda8f1c7abffa4 blob + 28723c7c52add5592515f140c9b53f57382ba049 --- got/got.c +++ got/got.c @@ -11466,6 +11466,23 @@ cat_tree(struct got_object_id *id, struct got_reposito return err; } +static void +format_gmtoff(char *buf, size_t sz, time_t gmtoff) +{ + long long h, m; + char sign = '+'; + + if (gmtoff < 0) { + sign = '-'; + gmtoff = -gmtoff; + } + + buf[0] = sign; + h = (long long)gmtoff / 3600; + m = ((long long)gmtoff - h*3600) / 60; + snprintf(buf, sz, "%c%02lld%02lld", sign, h, m); +} + static const struct got_error * cat_commit(struct got_object_id *id, struct got_repository *repo, FILE *outfile) { @@ -11475,6 +11492,7 @@ cat_commit(struct got_object_id *id, struct got_reposi struct got_object_qid *pid; char *id_str = NULL; const char *logmsg = NULL; + char gmtoff[6]; err = got_object_open_as_commit(&commit, repo, id); if (err) @@ -11496,13 +11514,19 @@ cat_commit(struct got_object_id *id, struct got_reposi fprintf(outfile, "%s%s\n", GOT_COMMIT_LABEL_PARENT, pid_str); free(pid_str); } - fprintf(outfile, "%s%s %lld +0000\n", GOT_COMMIT_LABEL_AUTHOR, + format_gmtoff(gmtoff, sizeof(gmtoff), + got_object_commit_get_author_gmtoff(commit)); + fprintf(outfile, "%s%s %lld %s\n", GOT_COMMIT_LABEL_AUTHOR, got_object_commit_get_author(commit), - (long long)got_object_commit_get_author_time(commit)); + (long long)got_object_commit_get_author_time(commit), + gmtoff); - fprintf(outfile, "%s%s %lld +0000\n", GOT_COMMIT_LABEL_COMMITTER, + format_gmtoff(gmtoff, sizeof(gmtoff), + got_object_commit_get_committer_gmtoff(commit)); + fprintf(outfile, "%s%s %lld %s\n", GOT_COMMIT_LABEL_COMMITTER, got_object_commit_get_author(commit), - (long long)got_object_commit_get_committer_time(commit)); + (long long)got_object_commit_get_committer_time(commit), + gmtoff); logmsg = got_object_commit_get_logmsg_raw(commit); fprintf(outfile, "messagelen %zd\n", strlen(logmsg)); @@ -11520,6 +11544,7 @@ cat_tag(struct got_object_id *id, struct got_repositor struct got_tag_object *tag; char *id_str = NULL; const char *tagmsg = NULL; + char gmtoff[6]; err = got_object_open_as_tag(&tag, repo, id); if (err) @@ -11555,9 +11580,12 @@ cat_tag(struct got_object_id *id, struct got_repositor fprintf(outfile, "%s%s\n", GOT_TAG_LABEL_TAG, got_object_tag_get_name(tag)); - fprintf(outfile, "%s%s %lld +0000\n", GOT_TAG_LABEL_TAGGER, + format_gmtoff(gmtoff, sizeof(gmtoff), + got_object_tag_get_tagger_gmtoff(tag)); + fprintf(outfile, "%s%s %lld %s\n", GOT_TAG_LABEL_TAGGER, got_object_tag_get_tagger(tag), - (long long)got_object_tag_get_tagger_time(tag)); + (long long)got_object_tag_get_tagger_time(tag), + gmtoff); tagmsg = got_object_tag_get_message(tag); fprintf(outfile, "messagelen %zd\n", strlen(tagmsg)); blob - 0c5c8ea1db1ca05c383570fdf3d063cbf5825f73 blob + 332aac7daf0b874612728683bc951e0b30605f86 --- regress/cmdline/cat.sh +++ regress/cmdline/cat.sh @@ -20,6 +20,7 @@ test_cat_basic() { local testroot=`test_init cat_basic` local commit_id=`git_show_head $testroot/repo` local author_time=`git_show_author_time $testroot/repo` + local gmtoff=`date +%z` local alpha_id=`got tree -r $testroot/repo -i | grep 'alpha$' | cut -d' ' -f 1` local gamma_id=`got tree -r $testroot/repo -i | grep 'gamma/$' | cut -d' ' -f 1` local delta_id=`got tree -r $testroot/repo -i gamma | grep 'delta$' | cut -d' ' -f 1` @@ -51,8 +52,8 @@ test_cat_basic() { git_show_tree $testroot/repo >> $testroot/stdout.expected echo >> $testroot/stdout.expected echo "numparents 0" >> $testroot/stdout.expected - echo "author $GOT_AUTHOR $author_time +0000" >> $testroot/stdout.expected - echo "committer $GOT_AUTHOR $author_time +0000" \ + echo "author $GOT_AUTHOR $author_time $gmtoff" >> $testroot/stdout.expected + echo "committer $GOT_AUTHOR $author_time $gmtoff" \ >> $testroot/stdout.expected echo "messagelen 22" >> $testroot/stdout.expected printf "\nadding the test tree\n" >> $testroot/stdout.expected @@ -234,6 +235,7 @@ test_cat_submodule_of_same_repo() { local testroot=`test_init cat_submodule_of_same_repo` local commit_id0=`git_show_head $testroot/repo` local author_time=`git_show_author_time $testroot/repo` + local gmtoff=`date +%z` (cd $testroot && git clone -q repo repo2 >/dev/null) (cd $testroot/repo && git submodule -q add ../repo2) @@ -243,8 +245,8 @@ test_cat_submodule_of_same_repo() { # because a commit with the same ID exists in the outer repository got cat -r $testroot/repo $commit_id0 | grep ^tree > $testroot/stdout.expected echo "numparents 0" >> $testroot/stdout.expected - echo "author $GOT_AUTHOR $author_time +0000" >> $testroot/stdout.expected - echo "committer $GOT_AUTHOR $author_time +0000" \ + echo "author $GOT_AUTHOR $author_time $gmtoff" >> $testroot/stdout.expected + echo "committer $GOT_AUTHOR $author_time $gmtoff" \ >> $testroot/stdout.expected echo "messagelen 22" >> $testroot/stdout.expected printf "\nadding the test tree\n" >> $testroot/stdout.expected