ident.c: add split_ident_line() to parse formatted ident line
The commit formatting logic format_person_part() in pretty.c implements the logic to split an author/committer ident line into its parts, intermixed with logic to compute its output using these piece it computes. Separate the former out to a helper function split_ident_line() so that other codepath can use the same logic, and rewrite the function using the helper function. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
0dbe6592cc
commit
4b340cfab9
16
cache.h
16
cache.h
@ -928,6 +928,22 @@ extern const char *fmt_name(const char *name, const char *email);
|
|||||||
extern const char *git_editor(void);
|
extern const char *git_editor(void);
|
||||||
extern const char *git_pager(int stdout_is_tty);
|
extern const char *git_pager(int stdout_is_tty);
|
||||||
|
|
||||||
|
struct ident_split {
|
||||||
|
const char *name_begin;
|
||||||
|
const char *name_end;
|
||||||
|
const char *mail_begin;
|
||||||
|
const char *mail_end;
|
||||||
|
const char *date_begin;
|
||||||
|
const char *date_end;
|
||||||
|
const char *tz_begin;
|
||||||
|
const char *tz_end;
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Signals an success with 0, but time part of the result may be NULL
|
||||||
|
* if the input lacks timestamp and zone
|
||||||
|
*/
|
||||||
|
extern int split_ident_line(struct ident_split *, const char *, int);
|
||||||
|
|
||||||
struct checkout {
|
struct checkout {
|
||||||
const char *base_dir;
|
const char *base_dir;
|
||||||
int base_dir_len;
|
int base_dir_len;
|
||||||
|
68
ident.c
68
ident.c
@ -220,6 +220,74 @@ static int copy(char *buf, size_t size, int offset, const char *src)
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reverse of fmt_ident(); given an ident line, split the fields
|
||||||
|
* to allow the caller to parse it.
|
||||||
|
* Signal a success by returning 0, but date/tz fields of the result
|
||||||
|
* can still be NULL if the input line only has the name/email part
|
||||||
|
* (e.g. reading from a reflog entry).
|
||||||
|
*/
|
||||||
|
int split_ident_line(struct ident_split *split, const char *line, int len)
|
||||||
|
{
|
||||||
|
const char *cp;
|
||||||
|
size_t span;
|
||||||
|
int status = -1;
|
||||||
|
|
||||||
|
memset(split, 0, sizeof(*split));
|
||||||
|
|
||||||
|
split->name_begin = line;
|
||||||
|
for (cp = line; *cp && cp < line + len; cp++)
|
||||||
|
if (*cp == '<') {
|
||||||
|
split->mail_begin = cp + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!split->mail_begin)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
for (cp = split->mail_begin - 2; line < cp; cp--)
|
||||||
|
if (!isspace(*cp)) {
|
||||||
|
split->name_end = cp + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!split->name_end)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
for (cp = split->mail_begin; cp < line + len; cp++)
|
||||||
|
if (*cp == '>') {
|
||||||
|
split->mail_end = cp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!split->mail_end)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
for (cp = split->mail_end + 1; cp < line + len && isspace(*cp); cp++)
|
||||||
|
;
|
||||||
|
if (line + len <= cp)
|
||||||
|
goto person_only;
|
||||||
|
split->date_begin = cp;
|
||||||
|
span = strspn(cp, "0123456789");
|
||||||
|
if (!span)
|
||||||
|
goto person_only;
|
||||||
|
split->date_end = split->date_begin + span;
|
||||||
|
for (cp = split->date_end; cp < line + len && isspace(*cp); cp++)
|
||||||
|
;
|
||||||
|
if (line + len <= cp || (*cp != '+' && *cp != '-'))
|
||||||
|
goto person_only;
|
||||||
|
split->tz_begin = cp;
|
||||||
|
span = strspn(cp + 1, "0123456789");
|
||||||
|
if (!span)
|
||||||
|
goto person_only;
|
||||||
|
split->tz_end = split->tz_begin + 1 + span;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
person_only:
|
||||||
|
split->date_begin = NULL;
|
||||||
|
split->date_end = NULL;
|
||||||
|
split->tz_begin = NULL;
|
||||||
|
split->tz_end = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *env_hint =
|
static const char *env_hint =
|
||||||
"\n"
|
"\n"
|
||||||
"*** Please tell me who you are.\n"
|
"*** Please tell me who you are.\n"
|
||||||
|
64
pretty.c
64
pretty.c
@ -531,41 +531,24 @@ static size_t format_person_part(struct strbuf *sb, char part,
|
|||||||
{
|
{
|
||||||
/* currently all placeholders have same length */
|
/* currently all placeholders have same length */
|
||||||
const int placeholder_len = 2;
|
const int placeholder_len = 2;
|
||||||
int start, end, tz = 0;
|
int tz;
|
||||||
unsigned long date = 0;
|
unsigned long date = 0;
|
||||||
char *ep;
|
|
||||||
const char *name_start, *name_end, *mail_start, *mail_end, *msg_end = msg+len;
|
|
||||||
char person_name[1024];
|
char person_name[1024];
|
||||||
char person_mail[1024];
|
char person_mail[1024];
|
||||||
|
struct ident_split s;
|
||||||
|
const char *name_start, *name_end, *mail_start, *mail_end;
|
||||||
|
|
||||||
/* advance 'end' to point to email start delimiter */
|
if (split_ident_line(&s, msg, len) < 0)
|
||||||
for (end = 0; end < len && msg[end] != '<'; end++)
|
|
||||||
; /* do nothing */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When end points at the '<' that we found, it should have
|
|
||||||
* matching '>' later, which means 'end' must be strictly
|
|
||||||
* below len - 1.
|
|
||||||
*/
|
|
||||||
if (end >= len - 2)
|
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
/* Seek for both name and email part */
|
name_start = s.name_begin;
|
||||||
name_start = msg;
|
name_end = s.name_end;
|
||||||
name_end = msg+end;
|
mail_start = s.mail_begin;
|
||||||
while (name_end > name_start && isspace(*(name_end-1)))
|
mail_end = s.mail_end;
|
||||||
name_end--;
|
|
||||||
mail_start = msg+end+1;
|
|
||||||
mail_end = mail_start;
|
|
||||||
while (mail_end < msg_end && *mail_end != '>')
|
|
||||||
mail_end++;
|
|
||||||
if (mail_end == msg_end)
|
|
||||||
goto skip;
|
|
||||||
end = mail_end-msg;
|
|
||||||
|
|
||||||
if (part == 'N' || part == 'E') { /* mailmap lookup */
|
if (part == 'N' || part == 'E') { /* mailmap lookup */
|
||||||
strlcpy(person_name, name_start, name_end-name_start+1);
|
strlcpy(person_name, name_start, name_end - name_start + 1);
|
||||||
strlcpy(person_mail, mail_start, mail_end-mail_start+1);
|
strlcpy(person_mail, mail_start, mail_end - mail_start + 1);
|
||||||
mailmap_name(person_mail, sizeof(person_mail), person_name, sizeof(person_name));
|
mailmap_name(person_mail, sizeof(person_mail), person_name, sizeof(person_name));
|
||||||
name_start = person_name;
|
name_start = person_name;
|
||||||
name_end = name_start + strlen(person_name);
|
name_end = name_start + strlen(person_name);
|
||||||
@ -581,28 +564,20 @@ static size_t format_person_part(struct strbuf *sb, char part,
|
|||||||
return placeholder_len;
|
return placeholder_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* advance 'start' to point to date start delimiter */
|
if (!s.date_begin)
|
||||||
for (start = end + 1; start < len && isspace(msg[start]); start++)
|
|
||||||
; /* do nothing */
|
|
||||||
if (start >= len)
|
|
||||||
goto skip;
|
|
||||||
date = strtoul(msg + start, &ep, 10);
|
|
||||||
if (msg + start == ep)
|
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
|
date = strtoul(s.date_begin, NULL, 10);
|
||||||
|
|
||||||
if (part == 't') { /* date, UNIX timestamp */
|
if (part == 't') { /* date, UNIX timestamp */
|
||||||
strbuf_add(sb, msg + start, ep - (msg + start));
|
strbuf_add(sb, s.date_begin, s.date_end - s.date_begin);
|
||||||
return placeholder_len;
|
return placeholder_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse tz */
|
/* parse tz */
|
||||||
for (start = ep - msg + 1; start < len && isspace(msg[start]); start++)
|
tz = strtoul(s.tz_begin + 1, NULL, 10);
|
||||||
; /* do nothing */
|
if (*s.tz_begin == '-')
|
||||||
if (start + 1 < len) {
|
tz = -tz;
|
||||||
tz = strtoul(msg + start + 1, NULL, 10);
|
|
||||||
if (msg[start] == '-')
|
|
||||||
tz = -tz;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (part) {
|
switch (part) {
|
||||||
case 'd': /* date */
|
case 'd': /* date */
|
||||||
@ -621,8 +596,9 @@ static size_t format_person_part(struct strbuf *sb, char part,
|
|||||||
|
|
||||||
skip:
|
skip:
|
||||||
/*
|
/*
|
||||||
* bogus commit, 'sb' cannot be updated, but we still need to
|
* reading from either a bogus commit, or a reflog entry with
|
||||||
* compute a valid return value.
|
* %gn, %ge, etc.; 'sb' cannot be updated, but we still need
|
||||||
|
* to compute a valid return value.
|
||||||
*/
|
*/
|
||||||
if (part == 'n' || part == 'e' || part == 't' || part == 'd'
|
if (part == 'n' || part == 'e' || part == 't' || part == 'd'
|
||||||
|| part == 'D' || part == 'r' || part == 'i')
|
|| part == 'D' || part == 'r' || part == 'i')
|
||||||
|
Loading…
Reference in New Issue
Block a user