From: tony.luck@intel.com Date: Sat, 30 Apr 2005 03:27:04 +0000 (-0700) Subject: [PATCH] Fix AUTHOR_DATE timezone confusion X-Git-Tag: v0.99~695 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=d167f147dc6995e452cdc374ffcd07f5d9abf0bc;p=git.git [PATCH] Fix AUTHOR_DATE timezone confusion This switches git-commit-tree to using curl_getdate() for the AUTHOR_DATE, and thus fixes the problem with "mktime()" parsing dates in the local timezone. It also ends up being more permissive about the format of the date. Signed-off-by: Tony Luck Signed-off-by: Linus Torvalds --- diff --git a/Makefile b/Makefile index fc104619..ef9a9fae 100644 --- a/Makefile +++ b/Makefile @@ -91,6 +91,7 @@ git-diff-tree-helper: diff-tree-helper.c git-tar-tree: tar-tree.c git-http-pull: LIBS += -lcurl +git-commit-tree: LIBS += -lcurl # Library objects.. blob.o: $(LIB_H) diff --git a/commit-tree.c b/commit-tree.c index 23de1336..7c23b9b5 100644 --- a/commit-tree.c +++ b/commit-tree.c @@ -10,6 +10,7 @@ #include #include #include +#include #define BLOCKING (1ul << 14) @@ -80,146 +81,22 @@ static void remove_special(char *p) } } -static const char *month_names[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static const char *weekday_names[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - - -static char *skipfws(char *str) -{ - while (isspace(*str)) - str++; - return str; -} - - /* 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. */ -static void parse_rfc2822_date(char *date, char *result, int maxlen) +static void parse_date(char *date, time_t *now, char *result, int maxlen) { - struct tm tm; char *p; - int i, offset; time_t then; - memset(&tm, 0, sizeof(tm)); - - /* Skip day-name */ - p = skipfws(date); - if (!isdigit(*p)) { - for (i=0; i<7; i++) { - if (!strncmp(p,weekday_names[i],3) && p[3] == ',') { - p = skipfws(p+4); - goto day; - } - } - return; - } - - /* day */ - day: - tm.tm_mday = strtoul(p, &p, 10); - - if (tm.tm_mday < 1 || tm.tm_mday > 31) - return; - - if (!isspace(*p)) - return; - - p = skipfws(p); - - /* month */ - - for (i=0; i<12; i++) { - if (!strncmp(p, month_names[i], 3) && isspace(p[3])) { - tm.tm_mon = i; - p = skipfws(p+strlen(month_names[i])); - goto year; - } - } - return; /* Error -- bad month */ - - /* year */ - year: - tm.tm_year = strtoul(p, &p, 10); - - if (!tm.tm_year && !isspace(*p)) - return; - - if (tm.tm_year > 1900) - tm.tm_year -= 1900; - - p=skipfws(p); - - /* hour */ - if (!isdigit(*p)) - return; - tm.tm_hour = strtoul(p, &p, 10); - - if (!tm.tm_hour > 23) - return; - - if (*p != ':') - return; /* Error -- bad time */ - p++; - - /* minute */ - if (!isdigit(*p)) - return; - tm.tm_min = strtoul(p, &p, 10); - - if (!tm.tm_min > 59) + if ((then = curl_getdate(date, now)) == 0) return; - if (isspace(*p)) - goto zone; - - if (*p != ':') - return; /* Error -- bad time */ - p++; - - /* second */ - if (!isdigit(*p)) - return; - tm.tm_sec = strtoul(p, &p, 10); - - if (!tm.tm_sec > 59) - return; - - if (!isspace(*p)) - return; - - zone: - p = skipfws(p); - - if (*p == '-') - offset = -60; - else if (*p == '+') - offset = 60; - else - return; - - if (!isdigit(p[1]) || !isdigit(p[2]) || !isdigit(p[3]) || !isdigit(p[4])) - return; - - i = strtoul(p+1, NULL, 10); - offset *= ((i % 100) + ((i / 100) * 60)); - - if (*(skipfws(p + 5))) - return; - - then = mktime(&tm); /* mktime appears to ignore the GMT offset, stupidly */ - if (then == -1) - return; - - then -= offset; - - snprintf(result, maxlen, "%lu %5.5s", then, p); + /* find the timezone at the end */ + p = date + strlen(date); + while (p > date && isdigit(*--p)) + ; + if ((*p == '+' || *p == '-') && strlen(p) == 5) + snprintf(result, maxlen, "%lu %5.5s", then, p); } static void check_valid(unsigned char *sha1, const char *expect) @@ -298,7 +175,7 @@ int main(int argc, char **argv) email = getenv("AUTHOR_EMAIL") ? : realemail; audate = getenv("AUTHOR_DATE"); if (audate) - parse_rfc2822_date(audate, date, sizeof(date)); + parse_date(audate, &now, date, sizeof(date)); remove_special(gecos); remove_special(realgecos); remove_special(commitgecos); remove_special(email); remove_special(realemail); remove_special(commitemail);