Approxidate: use libgit2 naming/calling conventions. Also use git_time_t (64-bit integer) for time values, although the 2038 problem is still present on 32-bit machines.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
diff --git a/src/date.c b/src/date.c
index 90f2f14..a2f3698 100644
--- a/src/date.c
+++ b/src/date.c
@@ -30,7 +30,7 @@ typedef enum {
/*
* This is like mktime, but without normalization of tm_wday and tm_yday.
*/
-static time_t tm_to_time_t(const struct tm *tm)
+static git_time_t tm_to_time_t(const struct tm *tm)
{
static const int mdays[] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
@@ -454,7 +454,7 @@ static int match_tz(const char *date, int *offp)
* Parse a string like "0 +0000" as ancient timestamp near epoch, but
* only when it appears not as part of any other string.
*/
-static int match_object_header_date(const char *date, unsigned long *timestamp, int *offset)
+static int match_object_header_date(const char *date, git_time_t *timestamp, int *offset)
{
char *end;
unsigned long stamp;
@@ -479,11 +479,11 @@ static int match_object_header_date(const char *date, unsigned long *timestamp,
/* 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 int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
+static int parse_date_basic(const char *date, git_time_t *timestamp, int *offset)
{
struct tm tm;
int tm_gmt;
- unsigned long dummy_timestamp;
+ git_time_t dummy_timestamp;
int dummy_offset;
if (!timestamp)
@@ -533,7 +533,7 @@ static int parse_date_basic(const char *date, unsigned long *timestamp, int *off
if (*offset == -1)
*offset = ((time_t)*timestamp - mktime(&tm)) / 60;
- if (*timestamp == (unsigned long)-1)
+ if (*timestamp == (git_time_t)-1)
return -1;
if (!tm_gmt)
@@ -546,7 +546,7 @@ static int parse_date_basic(const char *date, unsigned long *timestamp, int *off
* Relative time update (eg "2 days ago"). If we haven't set the time
* yet, we need to set it from current time.
*/
-static unsigned long update_tm(struct tm *tm, struct tm *now, unsigned long sec)
+static git_time_t update_tm(struct tm *tm, struct tm *now, unsigned long sec)
{
time_t n;
@@ -822,9 +822,9 @@ static void pending_number(struct tm *tm, int *num)
}
}
-static unsigned long approxidate_str(const char *date,
- const struct timeval *tv,
- int *error_ret)
+static git_time_t approxidate_str(const char *date,
+ const struct timeval *tv,
+ int *error_ret)
{
int number = 0;
int touched = 0;
@@ -859,20 +859,18 @@ static unsigned long approxidate_str(const char *date,
return update_tm(&tm, &now, 0);
}
-unsigned long approxidate_careful(const char *date, int *error_ret)
+int git__date_parse(git_time_t *out, const char *date)
{
struct timeval tv;
- unsigned long timestamp;
- int offset;
- int dummy = 0;
- if (!error_ret)
- error_ret = &dummy;
+ git_time_t timestamp;
+ int offset, error_ret=0;
if (!parse_date_basic(date, ×tamp, &offset)) {
- *error_ret = 0;
- return timestamp;
+ *out = timestamp;
+ return 0;
}
gettimeofday(&tv, NULL);
- return approxidate_str(date, &tv, error_ret);
+ *out = approxidate_str(date, &tv, &error_ret);
+ return error_ret;
}
diff --git a/src/date.h b/src/date.h
index 80df47a..6859ee5 100644
--- a/src/date.h
+++ b/src/date.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_date_h__
#define INCLUDE_date_h__
-unsigned long approxidate_careful(const char *date, int *error_ret);
+#include "git2/types.h"
+
+int git__date_parse(git_time_t *out, const char *date);
#endif
diff --git a/src/revparse.c b/src/revparse.c
index 8eb5c11..3615ac5 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -200,11 +200,11 @@ static int walk_ref_history(git_object **out, git_repository *repo, const char *
}
} else {
int date_error = 0;
- time_t timestamp;
+ git_time_t timestamp;
git_buf datebuf = GIT_BUF_INIT;
git_buf_put(&datebuf, reflogspec+2, reflogspeclen-3);
- timestamp = approxidate_careful(git_buf_cstr(&datebuf), &date_error);
+ date_error = git__date_parse(×tamp, git_buf_cstr(&datebuf));
/* @{u} or @{upstream} -> upstream branch, for a tracking branch. This is stored in the config. */
if (!strcmp(reflogspec, "@{u}") || !strcmp(reflogspec, "@{upstream}")) {
diff --git a/tests-clar/date/date.c b/tests-clar/date/date.c
new file mode 100644
index 0000000..1018a13
--- /dev/null
+++ b/tests-clar/date/date.c
@@ -0,0 +1,13 @@
+#include "clar_libgit2.h"
+
+#include "date.h"
+
+void test_date_date__overflow(void)
+{
+ git_time_t d2038, d2039;
+
+ /* This fails on a 32-bit machine. */
+ cl_git_pass(git__date_parse(&d2038, "2038-1-1"));
+ cl_git_pass(git__date_parse(&d2039, "2039-1-1"));
+ cl_assert(d2038 < d2039);
+}