Merge branch 'jc/maint-reflog-bad-timestamp'

* jc/maint-reflog-bad-timestamp:
  t0101: use a fixed timestamp when searching in the reflog
  Update @{bogus.timestamp} fix not to die()
  approxidate_careful() reports errorneous date string
This commit is contained in:
Junio C Hamano 2010-01-27 14:57:37 -08:00
Родитель 68186857a9 6c647af306
Коммит 103209c678
4 изменённых файлов: 86 добавлений и 10 удалений

Просмотреть файл

@ -762,7 +762,8 @@ const char *show_date_relative(unsigned long time, int tz,
size_t timebuf_size);
int parse_date(const char *date, char *buf, int bufsize);
void datestamp(char *buf, int bufsize);
unsigned long approxidate(const char *);
#define approxidate(s) approxidate_careful((s), NULL)
unsigned long approxidate_careful(const char *, int *);
unsigned long approxidate_relative(const char *date, const struct timeval *now);
enum date_mode parse_date_format(const char *format);

43
date.c
Просмотреть файл

@ -696,6 +696,11 @@ static unsigned long update_tm(struct tm *tm, struct tm *now, unsigned long sec)
return n;
}
static void date_now(struct tm *tm, struct tm *now, int *num)
{
update_tm(tm, now, 0);
}
static void date_yesterday(struct tm *tm, struct tm *now, int *num)
{
update_tm(tm, now, 24*60*60);
@ -770,6 +775,7 @@ static const struct special {
{ "PM", date_pm },
{ "AM", date_am },
{ "never", date_never },
{ "now", date_now },
{ NULL }
};
@ -790,7 +796,7 @@ static const struct typelen {
{ NULL }
};
static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm *now, int *num)
static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm *now, int *num, int *touched)
{
const struct typelen *tl;
const struct special *s;
@ -804,6 +810,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
int match = match_string(date, month_names[i]);
if (match >= 3) {
tm->tm_mon = i;
*touched = 1;
return end;
}
}
@ -812,6 +819,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
int len = strlen(s->name);
if (match_string(date, s->name) == len) {
s->fn(tm, now, num);
*touched = 1;
return end;
}
}
@ -821,11 +829,14 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
int len = strlen(number_name[i]);
if (match_string(date, number_name[i]) == len) {
*num = i;
*touched = 1;
return end;
}
}
if (match_string(date, "last") == 4)
if (match_string(date, "last") == 4) {
*num = 1;
*touched = 1;
}
return end;
}
@ -835,6 +846,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
if (match_string(date, tl->type) >= len-1) {
update_tm(tm, now, tl->length * *num);
*num = 0;
*touched = 1;
return end;
}
tl++;
@ -852,6 +864,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
diff += 7*n;
update_tm(tm, now, diff * 24 * 60 * 60);
*touched = 1;
return end;
}
}
@ -866,6 +879,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
tm->tm_year--;
}
tm->tm_mon = n;
*touched = 1;
return end;
}
@ -873,6 +887,7 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
update_tm(tm, now, 0); /* fill in date fields if needed */
tm->tm_year -= *num;
*num = 0;
*touched = 1;
return end;
}
@ -929,9 +944,12 @@ static void pending_number(struct tm *tm, int *num)
}
}
static unsigned long approxidate_str(const char *date, const struct timeval *tv)
static unsigned long approxidate_str(const char *date,
const struct timeval *tv,
int *error_ret)
{
int number = 0;
int touched = 0;
struct tm tm, now;
time_t time_sec;
@ -951,33 +969,42 @@ static unsigned long approxidate_str(const char *date, const struct timeval *tv)
if (isdigit(c)) {
pending_number(&tm, &number);
date = approxidate_digit(date-1, &tm, &number);
touched = 1;
continue;
}
if (isalpha(c))
date = approxidate_alpha(date-1, &tm, &now, &number);
date = approxidate_alpha(date-1, &tm, &now, &number, &touched);
}
pending_number(&tm, &number);
if (!touched)
*error_ret = 1;
return update_tm(&tm, &now, 0);
}
unsigned long approxidate_relative(const char *date, const struct timeval *tv)
{
char buffer[50];
int errors = 0;
if (parse_date(date, buffer, sizeof(buffer)) > 0)
return strtoul(buffer, NULL, 0);
return approxidate_str(date, tv);
return approxidate_str(date, tv, &errors);
}
unsigned long approxidate(const char *date)
unsigned long approxidate_careful(const char *date, int *error_ret)
{
struct timeval tv;
char buffer[50];
int dummy = 0;
if (!error_ret)
error_ret = &dummy;
if (parse_date(date, buffer, sizeof(buffer)) > 0)
if (parse_date(date, buffer, sizeof(buffer)) > 0) {
*error_ret = 0;
return strtoul(buffer, NULL, 0);
}
gettimeofday(&tv, NULL);
return approxidate_str(date, &tv);
return approxidate_str(date, &tv, error_ret);
}

Просмотреть файл

@ -413,9 +413,12 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
} else if (0 <= nth)
at_time = 0;
else {
int errors = 0;
char *tmp = xstrndup(str + at + 2, reflog_len);
at_time = approxidate(tmp);
at_time = approxidate_careful(tmp, &errors);
free(tmp);
if (errors)
return -1;
}
if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
&co_time, &co_tz, &co_cnt)) {

45
t/t0101-at-syntax.sh Executable file
Просмотреть файл

@ -0,0 +1,45 @@
#!/bin/sh
test_description='various @{whatever} syntax tests'
. ./test-lib.sh
test_expect_success 'setup' '
test_commit one &&
test_commit two
'
check_at() {
echo "$2" >expect &&
git log -1 --format=%s "$1" >actual &&
test_cmp expect actual
}
test_expect_success '@{0} shows current' '
check_at @{0} two
'
test_expect_success '@{1} shows old' '
check_at @{1} one
'
test_expect_success '@{now} shows current' '
check_at @{now} two
'
test_expect_success '@{2001-09-17} (before the first commit) shows old' '
check_at @{2001-09-17} one
'
test_expect_success 'silly approxidates work' '
check_at @{3.hot.dogs.and.30.years.ago} one
'
test_expect_success 'notice misspelled upstream' '
test_must_fail git log -1 --format=%s @{usptream}
'
test_expect_success 'complain about total nonsense' '
test_must_fail git log -1 --format=%s @{utter.bogosity}
'
test_done