From: Shengfa Lin <shengfa@google.com>
To: gitster@pobox.com
Cc: git@vger.kernel.org, jrnieder@gmail.com, nathaniel@google.com,
rsbecker@nexbridge.com, sandals@crustytoothpaste.net,
santiago@nyu.edu, shengfa@google.com
Subject: Re: [WIP v2 1/2] Adding a record-time-zone command option for commit
Date: Wed, 21 Oct 2020 05:01:46 +0000 [thread overview]
Message-ID: <20201021050146.3001222-1-shengfa@google.com> (raw)
In-Reply-To: <xmqqk0vtki66.fsf@gitster.c.googlers.com>
Junio C Hamano <gitster@pobox.com> writes:
>> Many places in Git record the timezone of actor when a
>> timestamp is recorded, including the commiter and author
>> timestamps in a commit object and the tagger timestamp in a tag
>> object. Some people however prefer not to share where they
>> actually are.
>>
>> They _could_ just say "export TZ=UTC" and be done with it,
>> but the method would not easily allow them to pretend to be
>> in the UTC timezone only with Git, while revealing their true
>> timezone to other activities (e.g. sending e-emails?).
>>
>> Introduce --[no-]record-time-zone for commit command, which can be
>> specified to disallow Git to record time zone. Timezone will be
>> recorded by default.
>>
>> Note that this is a WIP and the test is failing.
>
> And there is no outline of the design decision made so far, so it is
> hard to give useful review comments.
Thanks for the comments and sorry for not describing the design.
I will add it here.
First, I would like to use a "global" variable to keep track of whether
record-time-zone is set and default to true. Then in various places such
as commit, pull, merge and rebase; we can add command option that can
modify this value.
Then in datestamp in date.c, we can check this value; offset would be
initialized to 0 and only be set if record_time_zone is true. Additionally,
date_string from the same file would take an extra argument to indicate if
we want to use nagative sign for zero offset. Then the timestamp along with
sign and 4 digits offset would be stored in "git_default_date" as buf
"1603255519 -0000". I think of this as the "encoding" step.
Initially, I thought this would be sufficient to show "-0000" in commit log
message. However, I found that the show_date function is used for "decoding";
converting timestamp and tz to more readable format. Then I realize the
function won't distinguish between +0 and -0 as it only takes in a tz as
argument. As a result, I added the sign pointer as an argument; the reason for
pointer being there are many call sites for the show_date function but I am not sure
if they all need to display in the new format(-0000). I used NULL to denote
not sure and just do whatever they were doing before. For show_ident_date in
pretty.c, I have extracted the sign in ident tz and pass it into show_date.
Then added helper functions in date.c to print either %+05d or -%04d depending
on tz and sign pointer.
In fmt_ident(ident.c), we are calling parse_date which calls parse_date_basic
and used the parameters it parsed to call date_string again, so I modified
parse_date_basic to parse the sign as well.
> It does not help that the patch is distracting by turning tabs to
> spaces and breaking alingment X-<.
I was assuming 1 HT is 8 spaces. Then after doing :set list in vim, I think
1 HT is actually ctrl + I. Is this correct?
>> diff --git a/builtin/am.c b/builtin/am.c
>> index 2c7673f74e..059cc5fce7 100644
>> --- a/builtin/am.c
>> +++ b/builtin/am.c
>> @@ -884,7 +884,7 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
>> if (tz > 0)
>> tz2 = -tz2;
>>
>> - fprintf(out, "Date: %s\n", show_date(timestamp, tz2, DATE_MODE(RFC2822)));
>> + fprintf(out, "Date: %s\n", show_date(timestamp, tz2, NULL, DATE_MODE(RFC2822)));
>
> For example, it appears that tweaking "show_date()" API function
> seems to be a central part of the design, as there are so many
> instances like this change in the patch. If the proposed log
> message mentioned, even briefly, what the extra parameter added to
> the API function meant (especially what NULL means there) upfront,
> then readers can coast the part that added NULL there, like these
> ones, and concentrate on the parts of this patch that matter, which
> presumably uses something more interesting than NULL instead.
Added above, the extra parameter is the decoded sign if not NULL.
>> diff --git a/builtin/commit.c b/builtin/commit.c
>> index 1dfd799ec5..ee3ca2c7ac 100644
>> --- a/builtin/commit.c
>> +++ b/builtin/commit.c
>> @@ -1547,7 +1547,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
>> N_("ok to record an empty change")),
>> OPT_HIDDEN_BOOL(0, "allow-empty-message", &allow_empty_message,
>> N_("ok to record a change with an empty message")),
>> -
>> + OPT_BOOL(0, "record-time-zone", &record_time_zone, N_("record user timezone")),
>
> Our code indents with HT; get used to the style early and your
> patches won't distract reviewers as much, leading to more quality
> reviews and suggestions.
My bad, I didn't realize I was doing it wrong all along, I was thinking that I was
sometimes missing spaces.
I use vim, is there any easy way to ensure that indent is with HT?
I was using 4 tabs since each tab is 2 spaces. Should I type in ctrl + I
instead?
> Likewise. The record_time_zone global variable seems to play a
> crucial role in this change, but without preparing readers by
> mentioning where it is defined, what normal/default value it takes,
> and who potentially touches it, in the proposed log message, it
> makes reading the change harder than necessary.
>
> A system-wide global like this is usually defined in environment.c,
> by the way. Look for say trust_executable_bit and mimic where it
> is defined and declared.
Will move to environment.c.
>> OPT_END()
>> };
>>
>> @@ -1580,6 +1580,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
>> argc = parse_and_validate_options(argc, argv, builtin_commit_options,
>> builtin_commit_usage,
>> prefix, current_head, &s);
>> +
>> if (verbose == -1)
>> verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
>>
>
> Distraction.
Will remove.
>> +static int negative_zero(int tz, int *sign)
>> +{
>> + return !tz && sign && (*sign) == '-';
>> +}
>> +
>> +static const char *tz_fmt(int tz, int *sign)
>> +{
>> + if (!negative_zero(tz, sign))
>> + return " %+05d";
>> + else
>> + return " -%04d";
>> +}
>> +
>> +
>> +static void show_date_normal(struct strbuf *buf, timestamp_t time, struct tm *tm, int tz, int *sign, struct tm *human_tm, int human_tz, int local)
>> {
>> struct {
>> unsigned int year:1,
>> @@ -277,10 +293,10 @@ static void show_date_normal(struct strbuf *buf, timestamp_t time, struct tm *tm
>> strbuf_addf(buf, " %d", tm->tm_year + 1900);
>>
>> if (!hide.tz)
>> - strbuf_addf(buf, " %+05d", tz);
>> + strbuf_addf(buf, tz_fmt(tz, sign), tz);
>> }
>>
>> -const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
>> +const char *show_date(timestamp_t time, int tz, int *signp, const struct date_mode *mode)
>
> With its type, we can tell easily that sign is a pointer, so no need
> for 'p' (we do not have modep, either, next door). More important
> is if 'sign' is a good name that conveys what the parameter (which
> is almost always NULL) means. Without any introductory text, it is
> hard to tell and offer recommendations.
The reason I used signp instead of sign here is because there is a variable with
name sign used in the function. Regarding "good name", maybe sign_hint is more appropriate.
>> @@ -826,17 +849,21 @@ static int match_object_header_date(const char *date, timestamp_t *timestamp, in
>>
>> /* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
>> (i.e. English) day/month names, and it doesn't work correctly with %z. */
>> -int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
>> +int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset, int *zero_offset_negative_sign)
>> {
>> struct tm tm;
>> int tm_gmt;
>> timestamp_t dummy_timestamp;
>> int dummy_offset;
>> + int dummy_zero_offset_negative_sign;
>> + int negative_sign;
>> if (!timestamp)
>> timestamp = &dummy_timestamp;
>> if (!offset)
>> offset = &dummy_offset;
>
> I see no need for the extra dummy_zero_offset_negative_sign variable.
> I can guess this mimics "if (!offset) offset = &dummy_offset" without
> much thought---a big difference is that after calling match_tz() to
> fill *offset, the code needs to obtain the value match_tz() parsed
> to decide if it needs to do the mktime() dance to guess the current
> zone offset, and also needs to read *offset to adjust *timestamp
> the function returns.
>
> The zero_offset_negative_sign pointer that specifies the location to
> optionally return a bit of info is *ONLY* used once at the very end
> of the function, so
>> + if (!zero_offset_negative_sign)
>> + zero_offset_negative_sign = &dummy_zero_offset_negative_sign;
>
> there is absolutely no need for the dummy variable or this
> assignment, especially since the patch adds negative_sign variable
> that always exists, and ...
>
>> memset(&tm, 0, sizeof(tm));
>> tm.tm_year = -1;
>> @@ -848,6 +875,7 @@ int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
>> tm.tm_sec = -1;
>> *offset = -1;
>> tm_gmt = 0;
>> + negative_sign = 0;
>>
>> if (*date == '@' &&
>> !match_object_header_date(date + 1, timestamp, offset))
>> @@ -864,9 +892,11 @@ int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
>> match = match_alpha(date, &tm, offset);
>> else if (isdigit(c))
>> match = match_digit(date, &tm, offset, &tm_gmt);
>> - else if ((c == '-' || c == '+') && isdigit(date[1]))
>> + else if ((c == '-' || c == '+') && isdigit(date[1])) {
>> match = match_tz(date, offset);
>> -
>> + if (c == '-')
>> + negative_sign = 1;
>> + }
>
>... is usable.
Got it, thanks for pointing out.
>> if (!match) {
>> /* BAD CRAP */
>> match = 1;
>> @@ -895,6 +925,9 @@ int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
>>
>> if (!tm_gmt)
>> *timestamp -= *offset * 60;
>> +
>> + *zero_offset_negative_sign = (!(*offset) && negative_sign);
>> +
>
> The only change needed for this optional extra bit return is to
> make sure that the assignment happens only when it was requested by
> the caller, i.e.
>
> if (zero_offset_negative_sign)
> *zero_offset_negative_sign = ...
>
> Having said all that, quite honestly, I do not know if this is going
> in the right direction. Specifically, I do not offhand see why we
> need such a huge surgery to date.c just to touch datestamp() and
> date_string().
>
> I may be totally off, partly due to lack of explanation of how the
> patch attempts to achieve its goal, but wouldn't it be just the
> matter of touching the single callsite of datestamp() in ident.c, so
> that after it gets git_default_date string filled, null out the last
> 5 bytes in it with "-0000" if record_tz is off?
>
Changing parse_date_basic because it's called by parse_date in fmt_ident(ident.c).
next prev parent reply other threads:[~2020-10-21 5:01 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-05 17:14 [ISSUE] Stop accessing, storing, and sharing the user's time zone Nathaniel Manista
2019-12-05 17:31 ` Junio C Hamano
2019-12-05 17:33 ` Randall S. Becker
2019-12-05 17:43 ` Junio C Hamano
2019-12-05 17:53 ` Santiago Torres Arias
2019-12-05 18:00 ` Randall S. Becker
2020-09-30 23:21 ` [RFC PATCH 0/1] adding user.hideTimezone for setting UTC timezone Shengfa Lin
2020-09-30 23:21 ` [RFC PATCH 1/1] hideTimezone: add a user.hideTimezone config Shengfa Lin
2020-09-30 23:41 ` Junio C Hamano
2020-10-01 0:17 ` Junio C Hamano
2020-10-02 6:07 ` Shengfa Lin
2020-10-01 0:31 ` Junio C Hamano
2020-10-01 0:35 ` Junio C Hamano
2020-10-02 6:41 ` Shengfa Lin
2020-10-02 6:46 ` Shengfa Lin
2020-10-02 6:37 ` Shengfa Lin
2020-10-02 6:02 ` Shengfa Lin
2020-10-02 6:15 ` Jonathan Nieder
2020-10-02 22:32 ` Shengfa Lin
2020-10-03 4:57 ` Junio C Hamano
2020-09-30 23:55 ` Junio C Hamano
2020-10-02 6:51 ` Shengfa Lin
2020-10-01 0:05 ` Junio C Hamano
2020-10-01 2:44 ` Jonathan Nieder
2020-10-02 21:17 ` Shengfa Lin
2020-09-30 23:53 ` [RFC PATCH 0/1] adding user.hideTimezone for setting UTC timezone Junio C Hamano
2020-10-01 2:17 ` Junio C Hamano
2020-10-01 3:43 ` Jonathan Nieder
2020-10-01 15:48 ` Junio C Hamano
2020-10-08 19:49 ` Junio C Hamano
[not found] ` <CAEOYnASgxCE5NjhoSgDwyQyAmdLhw5UyFq_Fu==8q7y6uXGz6w@mail.gmail.com>
2020-10-09 16:48 ` Junio C Hamano
2020-10-02 21:56 ` Shengfa Lin
2020-10-02 22:06 ` Junio C Hamano
2020-10-03 3:50 ` Shengfa Lin
2020-10-03 4:42 ` Junio C Hamano
2020-10-03 19:53 ` brian m. carlson
2020-10-03 22:14 ` Junio C Hamano
2020-10-02 21:42 ` Shengfa Lin
2020-10-02 21:23 ` Shengfa Lin
2020-10-13 5:28 ` [WIP v2 0/2] experiment with commit option record-time-zone Shengfa Lin
2020-10-13 5:28 ` [WIP v2 1/2] Adding a record-time-zone command option for commit Shengfa Lin
2020-10-13 20:03 ` Junio C Hamano
2020-10-21 5:01 ` Shengfa Lin [this message]
2020-10-21 18:55 ` Junio C Hamano
2020-10-22 16:27 ` Junio C Hamano
2020-10-26 4:14 ` Shengfa Lin
2020-10-13 5:28 ` [WIP v2 2/2] Demonstrate failing and passing tests Shengfa Lin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201021050146.3001222-1-shengfa@google.com \
--to=shengfa@google.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jrnieder@gmail.com \
--cc=nathaniel@google.com \
--cc=rsbecker@nexbridge.com \
--cc=sandals@crustytoothpaste.net \
--cc=santiago@nyu.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.