Merge branch 'jk/commit-author-parsing'
Code clean-up. * jk/commit-author-parsing: determine_author_info(): copy getenv output determine_author_info(): reuse parsing functions date: use strbufs in date-formatting functions record_author_date(): use find_commit_header() record_author_date(): fix memory leak on malformed commit commit: provide a function to find a header in a buffer
This commit is contained in:
commit
9ff700ebac
@ -545,77 +545,80 @@ static int sane_ident_split(struct ident_split *person)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_force_date(const char *in, char *out, int len)
|
static int parse_force_date(const char *in, struct strbuf *out)
|
||||||
{
|
{
|
||||||
if (len < 1)
|
strbuf_addch(out, '@');
|
||||||
return -1;
|
|
||||||
*out++ = '@';
|
|
||||||
len--;
|
|
||||||
|
|
||||||
if (parse_date(in, out, len) < 0) {
|
if (parse_date(in, out) < 0) {
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
unsigned long t = approxidate_careful(in, &errors);
|
unsigned long t = approxidate_careful(in, &errors);
|
||||||
if (errors)
|
if (errors)
|
||||||
return -1;
|
return -1;
|
||||||
snprintf(out, len, "%lu", t);
|
strbuf_addf(out, "%lu", t);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_ident_var(char **buf, char *val)
|
||||||
|
{
|
||||||
|
free(*buf);
|
||||||
|
*buf = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *envdup(const char *var)
|
||||||
|
{
|
||||||
|
const char *val = getenv(var);
|
||||||
|
return val ? xstrdup(val) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void determine_author_info(struct strbuf *author_ident)
|
static void determine_author_info(struct strbuf *author_ident)
|
||||||
{
|
{
|
||||||
char *name, *email, *date;
|
char *name, *email, *date;
|
||||||
struct ident_split author;
|
struct ident_split author;
|
||||||
char date_buf[64];
|
|
||||||
|
|
||||||
name = getenv("GIT_AUTHOR_NAME");
|
name = envdup("GIT_AUTHOR_NAME");
|
||||||
email = getenv("GIT_AUTHOR_EMAIL");
|
email = envdup("GIT_AUTHOR_EMAIL");
|
||||||
date = getenv("GIT_AUTHOR_DATE");
|
date = envdup("GIT_AUTHOR_DATE");
|
||||||
|
|
||||||
if (author_message) {
|
if (author_message) {
|
||||||
const char *a, *lb, *rb, *eol;
|
struct ident_split ident;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
const char *a;
|
||||||
|
|
||||||
a = strstr(author_message_buffer, "\nauthor ");
|
a = find_commit_header(author_message_buffer, "author", &len);
|
||||||
if (!a)
|
if (!a)
|
||||||
die(_("invalid commit: %s"), author_message);
|
die(_("commit '%s' lacks author header"), author_message);
|
||||||
|
if (split_ident_line(&ident, a, len) < 0)
|
||||||
|
die(_("commit '%s' has malformed author line"), author_message);
|
||||||
|
|
||||||
lb = strchrnul(a + strlen("\nauthor "), '<');
|
set_ident_var(&name, xmemdupz(ident.name_begin, ident.name_end - ident.name_begin));
|
||||||
rb = strchrnul(lb, '>');
|
set_ident_var(&email, xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin));
|
||||||
eol = strchrnul(rb, '\n');
|
|
||||||
if (!*lb || !*rb || !*eol)
|
|
||||||
die(_("invalid commit: %s"), author_message);
|
|
||||||
|
|
||||||
if (lb == a + strlen("\nauthor "))
|
if (ident.date_begin) {
|
||||||
/* \nauthor <foo@example.com> */
|
struct strbuf date_buf = STRBUF_INIT;
|
||||||
name = xcalloc(1, 1);
|
strbuf_addch(&date_buf, '@');
|
||||||
else
|
strbuf_add(&date_buf, ident.date_begin, ident.date_end - ident.date_begin);
|
||||||
name = xmemdupz(a + strlen("\nauthor "),
|
strbuf_addch(&date_buf, ' ');
|
||||||
(lb - strlen(" ") -
|
strbuf_add(&date_buf, ident.tz_begin, ident.tz_end - ident.tz_begin);
|
||||||
(a + strlen("\nauthor "))));
|
set_ident_var(&date, strbuf_detach(&date_buf, NULL));
|
||||||
email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
|
}
|
||||||
len = eol - (rb + strlen("> "));
|
|
||||||
date = xmalloc(len + 2);
|
|
||||||
*date = '@';
|
|
||||||
memcpy(date + 1, rb + strlen("> "), len);
|
|
||||||
date[len + 1] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force_author) {
|
if (force_author) {
|
||||||
const char *lb = strstr(force_author, " <");
|
struct ident_split ident;
|
||||||
const char *rb = strchr(force_author, '>');
|
|
||||||
|
|
||||||
if (!lb || !rb)
|
if (split_ident_line(&ident, force_author, strlen(force_author)) < 0)
|
||||||
die(_("malformed --author parameter"));
|
die(_("malformed --author parameter"));
|
||||||
name = xstrndup(force_author, lb - force_author);
|
set_ident_var(&name, xmemdupz(ident.name_begin, ident.name_end - ident.name_begin));
|
||||||
email = xstrndup(lb + 2, rb - (lb + 2));
|
set_ident_var(&email, xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force_date) {
|
if (force_date) {
|
||||||
if (parse_force_date(force_date, date_buf, sizeof(date_buf)))
|
struct strbuf date_buf = STRBUF_INIT;
|
||||||
|
if (parse_force_date(force_date, &date_buf))
|
||||||
die(_("invalid date format: %s"), force_date);
|
die(_("invalid date format: %s"), force_date);
|
||||||
date = date_buf;
|
set_ident_var(&date, strbuf_detach(&date_buf, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
|
strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
|
||||||
@ -625,6 +628,10 @@ static void determine_author_info(struct strbuf *author_ident)
|
|||||||
export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
|
export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
|
||||||
export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
|
export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
free(email);
|
||||||
|
free(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)
|
static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)
|
||||||
|
4
cache.h
4
cache.h
@ -1047,10 +1047,10 @@ enum date_mode {
|
|||||||
const char *show_date(unsigned long time, int timezone, enum date_mode mode);
|
const char *show_date(unsigned long time, int timezone, enum date_mode mode);
|
||||||
void show_date_relative(unsigned long time, int tz, const struct timeval *now,
|
void show_date_relative(unsigned long time, int tz, const struct timeval *now,
|
||||||
struct strbuf *timebuf);
|
struct strbuf *timebuf);
|
||||||
int parse_date(const char *date, char *buf, int bufsize);
|
int parse_date(const char *date, struct strbuf *out);
|
||||||
int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
|
int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
|
||||||
int parse_expiry_date(const char *date, unsigned long *timestamp);
|
int parse_expiry_date(const char *date, unsigned long *timestamp);
|
||||||
void datestamp(char *buf, int bufsize);
|
void datestamp(struct strbuf *out);
|
||||||
#define approxidate(s) approxidate_careful((s), NULL)
|
#define approxidate(s) approxidate_careful((s), NULL)
|
||||||
unsigned long approxidate_careful(const char *, int *);
|
unsigned long approxidate_careful(const char *, int *);
|
||||||
unsigned long approxidate_relative(const char *date, const struct timeval *now);
|
unsigned long approxidate_relative(const char *date, const struct timeval *now);
|
||||||
|
44
commit.c
44
commit.c
@ -584,25 +584,19 @@ define_commit_slab(author_date_slab, unsigned long);
|
|||||||
static void record_author_date(struct author_date_slab *author_date,
|
static void record_author_date(struct author_date_slab *author_date,
|
||||||
struct commit *commit)
|
struct commit *commit)
|
||||||
{
|
{
|
||||||
const char *buf, *line_end, *ident_line;
|
|
||||||
const char *buffer = get_commit_buffer(commit, NULL);
|
const char *buffer = get_commit_buffer(commit, NULL);
|
||||||
struct ident_split ident;
|
struct ident_split ident;
|
||||||
|
const char *ident_line;
|
||||||
|
size_t ident_len;
|
||||||
char *date_end;
|
char *date_end;
|
||||||
unsigned long date;
|
unsigned long date;
|
||||||
|
|
||||||
for (buf = buffer; buf; buf = line_end + 1) {
|
ident_line = find_commit_header(buffer, "author", &ident_len);
|
||||||
line_end = strchrnul(buf, '\n');
|
if (!ident_line)
|
||||||
if (!skip_prefix(buf, "author ", &ident_line)) {
|
goto fail_exit; /* no author line */
|
||||||
if (!line_end[0] || line_end[1] == '\n')
|
if (split_ident_line(&ident, ident_line, ident_len) ||
|
||||||
return; /* end of header */
|
!ident.date_begin || !ident.date_end)
|
||||||
continue;
|
goto fail_exit; /* malformed "author" line */
|
||||||
}
|
|
||||||
if (split_ident_line(&ident,
|
|
||||||
ident_line, line_end - ident_line) ||
|
|
||||||
!ident.date_begin || !ident.date_end)
|
|
||||||
goto fail_exit; /* malformed "author" line */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
date = strtoul(ident.date_begin, &date_end, 10);
|
date = strtoul(ident.date_begin, &date_end, 10);
|
||||||
if (date_end != ident.date_end)
|
if (date_end != ident.date_end)
|
||||||
@ -1660,3 +1654,25 @@ void print_commit_list(struct commit_list *list,
|
|||||||
printf(format, sha1_to_hex(list->item->object.sha1));
|
printf(format, sha1_to_hex(list->item->object.sha1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *find_commit_header(const char *msg, const char *key, size_t *out_len)
|
||||||
|
{
|
||||||
|
int key_len = strlen(key);
|
||||||
|
const char *line = msg;
|
||||||
|
|
||||||
|
while (line) {
|
||||||
|
const char *eol = strchrnul(line, '\n');
|
||||||
|
|
||||||
|
if (line == eol)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (eol - line > key_len &&
|
||||||
|
!strncmp(line, key, key_len) &&
|
||||||
|
line[key_len] == ' ') {
|
||||||
|
*out_len = eol - line - key_len - 1;
|
||||||
|
return line + key_len + 1;
|
||||||
|
}
|
||||||
|
line = *eol ? eol + 1 : NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
11
commit.h
11
commit.h
@ -326,6 +326,17 @@ extern struct commit_extra_header *read_commit_extra_headers(struct commit *, co
|
|||||||
|
|
||||||
extern void free_commit_extra_headers(struct commit_extra_header *extra);
|
extern void free_commit_extra_headers(struct commit_extra_header *extra);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search the commit object contents given by "msg" for the header "key".
|
||||||
|
* Returns a pointer to the start of the header contents, or NULL. The length
|
||||||
|
* of the header, up to the first newline, is returned via out_len.
|
||||||
|
*
|
||||||
|
* Note that some headers (like mergetag) may be multi-line. It is the caller's
|
||||||
|
* responsibility to parse further in this case!
|
||||||
|
*/
|
||||||
|
extern const char *find_commit_header(const char *msg, const char *key,
|
||||||
|
size_t *out_len);
|
||||||
|
|
||||||
typedef void (*each_mergetag_fn)(struct commit *commit, struct commit_extra_header *extra,
|
typedef void (*each_mergetag_fn)(struct commit *commit, struct commit_extra_header *extra,
|
||||||
void *cb_data);
|
void *cb_data);
|
||||||
|
|
||||||
|
13
date.c
13
date.c
@ -614,7 +614,7 @@ static int match_tz(const char *date, int *offp)
|
|||||||
return end - date;
|
return end - date;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int date_string(unsigned long date, int offset, char *buf, int len)
|
static void date_string(unsigned long date, int offset, struct strbuf *buf)
|
||||||
{
|
{
|
||||||
int sign = '+';
|
int sign = '+';
|
||||||
|
|
||||||
@ -622,7 +622,7 @@ static int date_string(unsigned long date, int offset, char *buf, int len)
|
|||||||
offset = -offset;
|
offset = -offset;
|
||||||
sign = '-';
|
sign = '-';
|
||||||
}
|
}
|
||||||
return snprintf(buf, len, "%lu %c%02d%02d", date, sign, offset / 60, offset % 60);
|
strbuf_addf(buf, "%lu %c%02d%02d", date, sign, offset / 60, offset % 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -744,13 +744,14 @@ int parse_expiry_date(const char *date, unsigned long *timestamp)
|
|||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_date(const char *date, char *result, int maxlen)
|
int parse_date(const char *date, struct strbuf *result)
|
||||||
{
|
{
|
||||||
unsigned long timestamp;
|
unsigned long timestamp;
|
||||||
int offset;
|
int offset;
|
||||||
if (parse_date_basic(date, ×tamp, &offset))
|
if (parse_date_basic(date, ×tamp, &offset))
|
||||||
return -1;
|
return -1;
|
||||||
return date_string(timestamp, offset, result, maxlen);
|
date_string(timestamp, offset, result);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum date_mode parse_date_format(const char *format)
|
enum date_mode parse_date_format(const char *format)
|
||||||
@ -778,7 +779,7 @@ enum date_mode parse_date_format(const char *format)
|
|||||||
die("unknown date format %s", format);
|
die("unknown date format %s", format);
|
||||||
}
|
}
|
||||||
|
|
||||||
void datestamp(char *buf, int bufsize)
|
void datestamp(struct strbuf *out)
|
||||||
{
|
{
|
||||||
time_t now;
|
time_t now;
|
||||||
int offset;
|
int offset;
|
||||||
@ -788,7 +789,7 @@ void datestamp(char *buf, int bufsize)
|
|||||||
offset = tm_to_time_t(localtime(&now)) - now;
|
offset = tm_to_time_t(localtime(&now)) - now;
|
||||||
offset /= 60;
|
offset /= 60;
|
||||||
|
|
||||||
date_string(now, offset, buf, bufsize);
|
date_string(now, offset, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1996,7 +1996,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int validate_raw_date(const char *src, char *result, int maxlen)
|
static int validate_raw_date(const char *src, struct strbuf *result)
|
||||||
{
|
{
|
||||||
const char *orig_src = src;
|
const char *orig_src = src;
|
||||||
char *endp;
|
char *endp;
|
||||||
@ -2014,11 +2014,10 @@ static int validate_raw_date(const char *src, char *result, int maxlen)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
num = strtoul(src + 1, &endp, 10);
|
num = strtoul(src + 1, &endp, 10);
|
||||||
if (errno || endp == src + 1 || *endp || (endp - orig_src) >= maxlen ||
|
if (errno || endp == src + 1 || *endp || 1400 < num)
|
||||||
1400 < num)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
strcpy(result, orig_src);
|
strbuf_addstr(result, orig_src);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2026,7 +2025,7 @@ static char *parse_ident(const char *buf)
|
|||||||
{
|
{
|
||||||
const char *ltgt;
|
const char *ltgt;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
char *ident;
|
struct strbuf ident = STRBUF_INIT;
|
||||||
|
|
||||||
/* ensure there is a space delimiter even if there is no name */
|
/* ensure there is a space delimiter even if there is no name */
|
||||||
if (*buf == '<')
|
if (*buf == '<')
|
||||||
@ -2045,26 +2044,25 @@ static char *parse_ident(const char *buf)
|
|||||||
die("Missing space after > in ident string: %s", buf);
|
die("Missing space after > in ident string: %s", buf);
|
||||||
ltgt++;
|
ltgt++;
|
||||||
name_len = ltgt - buf;
|
name_len = ltgt - buf;
|
||||||
ident = xmalloc(name_len + 24);
|
strbuf_add(&ident, buf, name_len);
|
||||||
strncpy(ident, buf, name_len);
|
|
||||||
|
|
||||||
switch (whenspec) {
|
switch (whenspec) {
|
||||||
case WHENSPEC_RAW:
|
case WHENSPEC_RAW:
|
||||||
if (validate_raw_date(ltgt, ident + name_len, 24) < 0)
|
if (validate_raw_date(ltgt, &ident) < 0)
|
||||||
die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
|
die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
|
||||||
break;
|
break;
|
||||||
case WHENSPEC_RFC2822:
|
case WHENSPEC_RFC2822:
|
||||||
if (parse_date(ltgt, ident + name_len, 24) < 0)
|
if (parse_date(ltgt, &ident) < 0)
|
||||||
die("Invalid rfc2822 date \"%s\" in ident: %s", ltgt, buf);
|
die("Invalid rfc2822 date \"%s\" in ident: %s", ltgt, buf);
|
||||||
break;
|
break;
|
||||||
case WHENSPEC_NOW:
|
case WHENSPEC_NOW:
|
||||||
if (strcmp("now", ltgt))
|
if (strcmp("now", ltgt))
|
||||||
die("Date in ident must be 'now': %s", buf);
|
die("Date in ident must be 'now': %s", buf);
|
||||||
datestamp(ident + name_len, 24);
|
datestamp(&ident);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ident;
|
return strbuf_detach(&ident, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_and_store_blob(
|
static void parse_and_store_blob(
|
||||||
|
26
ident.c
26
ident.c
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
static struct strbuf git_default_name = STRBUF_INIT;
|
static struct strbuf git_default_name = STRBUF_INIT;
|
||||||
static struct strbuf git_default_email = STRBUF_INIT;
|
static struct strbuf git_default_email = STRBUF_INIT;
|
||||||
static char git_default_date[50];
|
static struct strbuf git_default_date = STRBUF_INIT;
|
||||||
|
|
||||||
#define IDENT_NAME_GIVEN 01
|
#define IDENT_NAME_GIVEN 01
|
||||||
#define IDENT_MAIL_GIVEN 02
|
#define IDENT_MAIL_GIVEN 02
|
||||||
@ -129,9 +129,9 @@ const char *ident_default_email(void)
|
|||||||
|
|
||||||
static const char *ident_default_date(void)
|
static const char *ident_default_date(void)
|
||||||
{
|
{
|
||||||
if (!git_default_date[0])
|
if (!git_default_date.len)
|
||||||
datestamp(git_default_date, sizeof(git_default_date));
|
datestamp(&git_default_date);
|
||||||
return git_default_date;
|
return git_default_date.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int crud(unsigned char c)
|
static int crud(unsigned char c)
|
||||||
@ -292,7 +292,6 @@ const char *fmt_ident(const char *name, const char *email,
|
|||||||
const char *date_str, int flag)
|
const char *date_str, int flag)
|
||||||
{
|
{
|
||||||
static struct strbuf ident = STRBUF_INIT;
|
static struct strbuf ident = STRBUF_INIT;
|
||||||
char date[50];
|
|
||||||
int strict = (flag & IDENT_STRICT);
|
int strict = (flag & IDENT_STRICT);
|
||||||
int want_date = !(flag & IDENT_NO_DATE);
|
int want_date = !(flag & IDENT_NO_DATE);
|
||||||
int want_name = !(flag & IDENT_NO_NAME);
|
int want_name = !(flag & IDENT_NO_NAME);
|
||||||
@ -320,15 +319,6 @@ const char *fmt_ident(const char *name, const char *email,
|
|||||||
die("unable to auto-detect email address (got '%s')", email);
|
die("unable to auto-detect email address (got '%s')", email);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (want_date) {
|
|
||||||
if (date_str && date_str[0]) {
|
|
||||||
if (parse_date(date_str, date, sizeof(date)) < 0)
|
|
||||||
die("invalid date format: %s", date_str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
strcpy(date, ident_default_date());
|
|
||||||
}
|
|
||||||
|
|
||||||
strbuf_reset(&ident);
|
strbuf_reset(&ident);
|
||||||
if (want_name) {
|
if (want_name) {
|
||||||
strbuf_addstr_without_crud(&ident, name);
|
strbuf_addstr_without_crud(&ident, name);
|
||||||
@ -339,8 +329,14 @@ const char *fmt_ident(const char *name, const char *email,
|
|||||||
strbuf_addch(&ident, '>');
|
strbuf_addch(&ident, '>');
|
||||||
if (want_date) {
|
if (want_date) {
|
||||||
strbuf_addch(&ident, ' ');
|
strbuf_addch(&ident, ' ');
|
||||||
strbuf_addstr_without_crud(&ident, date);
|
if (date_str && date_str[0]) {
|
||||||
|
if (parse_date(date_str, &ident) < 0)
|
||||||
|
die("invalid date format: %s", date_str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strbuf_addstr(&ident, ident_default_date());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ident.buf;
|
return ident.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
pretty.c
33
pretty.c
@ -554,31 +554,11 @@ static void add_merge_info(const struct pretty_print_context *pp,
|
|||||||
strbuf_addch(sb, '\n');
|
strbuf_addch(sb, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_header(const struct commit *commit, const char *msg,
|
static char *get_header(const char *msg, const char *key)
|
||||||
const char *key)
|
|
||||||
{
|
{
|
||||||
int key_len = strlen(key);
|
size_t len;
|
||||||
const char *line = msg;
|
const char *v = find_commit_header(msg, key, &len);
|
||||||
|
return v ? xmemdupz(v, len) : NULL;
|
||||||
while (line) {
|
|
||||||
const char *eol = strchrnul(line, '\n'), *next;
|
|
||||||
|
|
||||||
if (line == eol)
|
|
||||||
return NULL;
|
|
||||||
if (!*eol) {
|
|
||||||
warning("malformed commit (header is missing newline): %s",
|
|
||||||
sha1_to_hex(commit->object.sha1));
|
|
||||||
next = NULL;
|
|
||||||
} else
|
|
||||||
next = eol + 1;
|
|
||||||
if (eol - line > key_len &&
|
|
||||||
!strncmp(line, key, key_len) &&
|
|
||||||
line[key_len] == ' ') {
|
|
||||||
return xmemdupz(line + key_len + 1, eol - line - key_len - 1);
|
|
||||||
}
|
|
||||||
line = next;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *replace_encoding_header(char *buf, const char *encoding)
|
static char *replace_encoding_header(char *buf, const char *encoding)
|
||||||
@ -624,11 +604,10 @@ const char *logmsg_reencode(const struct commit *commit,
|
|||||||
|
|
||||||
if (!output_encoding || !*output_encoding) {
|
if (!output_encoding || !*output_encoding) {
|
||||||
if (commit_encoding)
|
if (commit_encoding)
|
||||||
*commit_encoding =
|
*commit_encoding = get_header(msg, "encoding");
|
||||||
get_header(commit, msg, "encoding");
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
encoding = get_header(commit, msg, "encoding");
|
encoding = get_header(msg, "encoding");
|
||||||
if (commit_encoding)
|
if (commit_encoding)
|
||||||
*commit_encoding = encoding;
|
*commit_encoding = encoding;
|
||||||
use_encoding = encoding ? encoding : utf8;
|
use_encoding = encoding ? encoding : utf8;
|
||||||
|
10
test-date.c
10
test-date.c
@ -19,19 +19,21 @@ static void show_dates(char **argv, struct timeval *now)
|
|||||||
|
|
||||||
static void parse_dates(char **argv, struct timeval *now)
|
static void parse_dates(char **argv, struct timeval *now)
|
||||||
{
|
{
|
||||||
|
struct strbuf result = STRBUF_INIT;
|
||||||
|
|
||||||
for (; *argv; argv++) {
|
for (; *argv; argv++) {
|
||||||
char result[100];
|
|
||||||
unsigned long t;
|
unsigned long t;
|
||||||
int tz;
|
int tz;
|
||||||
|
|
||||||
result[0] = 0;
|
strbuf_reset(&result);
|
||||||
parse_date(*argv, result, sizeof(result));
|
parse_date(*argv, &result);
|
||||||
if (sscanf(result, "%lu %d", &t, &tz) == 2)
|
if (sscanf(result.buf, "%lu %d", &t, &tz) == 2)
|
||||||
printf("%s -> %s\n",
|
printf("%s -> %s\n",
|
||||||
*argv, show_date(t, tz, DATE_ISO8601));
|
*argv, show_date(t, tz, DATE_ISO8601));
|
||||||
else
|
else
|
||||||
printf("%s -> bad\n", *argv);
|
printf("%s -> bad\n", *argv);
|
||||||
}
|
}
|
||||||
|
strbuf_release(&result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_approxidate(char **argv, struct timeval *now)
|
static void parse_approxidate(char **argv, struct timeval *now)
|
||||||
|
Loading…
Reference in New Issue
Block a user