summaryrefslogtreecommitdiff
path: root/pretty.c
diff options
context:
space:
mode:
Diffstat (limited to 'pretty.c')
-rw-r--r--pretty.c129
1 files changed, 104 insertions, 25 deletions
diff --git a/pretty.c b/pretty.c
index 0ab45d10d7..ced0485257 100644
--- a/pretty.c
+++ b/pretty.c
@@ -98,6 +98,10 @@ static void setup_commit_formats(void)
{ "fuller", CMIT_FMT_FULLER, 0, 8 },
{ "full", CMIT_FMT_FULL, 0, 8 },
{ "oneline", CMIT_FMT_ONELINE, 1, 0 }
+ /*
+ * Please update $__git_log_pretty_formats in
+ * git-completion.bash when you add new formats.
+ */
};
commit_formats_len = ARRAY_SIZE(builtin_formats);
builtin_formats_len = commit_formats_len;
@@ -339,8 +343,7 @@ static int is_rfc2047_special(char ch, enum rfc2047_type type)
return !(isalnum(ch) || ch == '!' || ch == '*' || ch == '+' || ch == '-' || ch == '/');
}
-static int needs_rfc2047_encoding(const char *line, int len,
- enum rfc2047_type type)
+static int needs_rfc2047_encoding(const char *line, int len)
{
int i;
@@ -466,7 +469,7 @@ void pp_user_info(struct pretty_print_context *pp,
}
strbuf_addstr(sb, "From: ");
- if (needs_rfc2047_encoding(namebuf, namelen, RFC2047_ADDRESS)) {
+ if (needs_rfc2047_encoding(namebuf, namelen)) {
add_rfc2047(sb, namebuf, namelen,
encoding, RFC2047_ADDRESS);
max_length = 76; /* per rfc2047 */
@@ -985,8 +988,7 @@ static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
return rest - placeholder;
}
-static size_t parse_padding_placeholder(struct strbuf *sb,
- const char *placeholder,
+static size_t parse_padding_placeholder(const char *placeholder,
struct format_commit_context *c)
{
const char *ch = placeholder;
@@ -1057,13 +1059,26 @@ static size_t parse_padding_placeholder(struct strbuf *sb,
return 0;
}
-static int match_placeholder_arg(const char *to_parse, const char *candidate,
- const char **end)
+static int match_placeholder_arg_value(const char *to_parse, const char *candidate,
+ const char **end, const char **valuestart,
+ size_t *valuelen)
{
const char *p;
if (!(skip_prefix(to_parse, candidate, &p)))
return 0;
+ if (valuestart) {
+ if (*p == '=') {
+ *valuestart = p + 1;
+ *valuelen = strcspn(*valuestart, ",)");
+ p = *valuestart + *valuelen;
+ } else {
+ if (*p != ',' && *p != ')')
+ return 0;
+ *valuestart = NULL;
+ *valuelen = 0;
+ }
+ }
if (*p == ',') {
*end = p + 1;
return 1;
@@ -1075,6 +1090,47 @@ static int match_placeholder_arg(const char *to_parse, const char *candidate,
return 0;
}
+static int match_placeholder_bool_arg(const char *to_parse, const char *candidate,
+ const char **end, int *val)
+{
+ const char *argval;
+ char *strval;
+ size_t arglen;
+ int v;
+
+ if (!match_placeholder_arg_value(to_parse, candidate, end, &argval, &arglen))
+ return 0;
+
+ if (!argval) {
+ *val = 1;
+ return 1;
+ }
+
+ strval = xstrndup(argval, arglen);
+ v = git_parse_maybe_bool(strval);
+ free(strval);
+
+ if (v == -1)
+ return 0;
+
+ *val = v;
+
+ return 1;
+}
+
+static int format_trailer_match_cb(const struct strbuf *key, void *ud)
+{
+ const struct string_list *list = ud;
+ const struct string_list_item *item;
+
+ for_each_string_list_item (item, list) {
+ if (key->len == (uintptr_t)item->util &&
+ !strncasecmp(item->string, key->buf, key->len))
+ return 1;
+ }
+ return 0;
+}
+
static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
const char *placeholder,
void *context)
@@ -1084,10 +1140,14 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
const char *msg = c->message;
struct commit_list *p;
const char *arg;
- int ch;
+ size_t res;
char **slot;
/* these are independent of the commit */
+ res = strbuf_expand_literal_cb(sb, placeholder, NULL);
+ if (res)
+ return res;
+
switch (placeholder[0]) {
case 'C':
if (starts_with(placeholder + 1, "(auto)")) {
@@ -1106,16 +1166,6 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
*/
return ret;
}
- case 'n': /* newline */
- strbuf_addch(sb, '\n');
- return 1;
- case 'x':
- /* %x00 == NUL, %x0a == LF, etc. */
- ch = hex2chr(placeholder + 1);
- if (ch < 0)
- return 0;
- strbuf_addch(sb, ch);
- return 3;
case 'w':
if (placeholder[1] == '(') {
unsigned long width = 0, indent1 = 0, indent2 = 0;
@@ -1143,7 +1193,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
case '<':
case '>':
- return parse_padding_placeholder(sb, placeholder, c);
+ return parse_padding_placeholder(placeholder, c);
}
/* these depend on the commit */
@@ -1322,24 +1372,53 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
if (skip_prefix(placeholder, "(trailers", &arg)) {
struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
+ struct string_list filter_list = STRING_LIST_INIT_NODUP;
+ struct strbuf sepbuf = STRBUF_INIT;
+ size_t ret = 0;
opts.no_divider = 1;
if (*arg == ':') {
arg++;
for (;;) {
- if (match_placeholder_arg(arg, "only", &arg))
+ const char *argval;
+ size_t arglen;
+
+ if (match_placeholder_arg_value(arg, "key", &arg, &argval, &arglen)) {
+ uintptr_t len = arglen;
+
+ if (!argval)
+ goto trailer_out;
+
+ if (len && argval[len - 1] == ':')
+ len--;
+ string_list_append(&filter_list, argval)->util = (char *)len;
+
+ opts.filter = format_trailer_match_cb;
+ opts.filter_data = &filter_list;
opts.only_trailers = 1;
- else if (match_placeholder_arg(arg, "unfold", &arg))
- opts.unfold = 1;
- else
+ } else if (match_placeholder_arg_value(arg, "separator", &arg, &argval, &arglen)) {
+ char *fmt;
+
+ strbuf_reset(&sepbuf);
+ fmt = xstrndup(argval, arglen);
+ strbuf_expand(&sepbuf, fmt, strbuf_expand_literal_cb, NULL);
+ free(fmt);
+ opts.separator = &sepbuf;
+ } else if (!match_placeholder_bool_arg(arg, "only", &arg, &opts.only_trailers) &&
+ !match_placeholder_bool_arg(arg, "unfold", &arg, &opts.unfold) &&
+ !match_placeholder_bool_arg(arg, "valueonly", &arg, &opts.value_only))
break;
}
}
if (*arg == ')') {
format_trailers_from_commit(sb, msg + c->subject_off, &opts);
- return arg - placeholder + 1;
+ ret = arg - placeholder + 1;
}
+ trailer_out:
+ string_list_clear(&filter_list, 0);
+ strbuf_release(&sepbuf);
+ return ret;
}
return 0; /* unknown placeholder */
@@ -1647,7 +1726,7 @@ void pp_title_line(struct pretty_print_context *pp,
if (pp->print_email_subject) {
if (pp->rev)
fmt_output_email_subject(sb, pp->rev);
- if (needs_rfc2047_encoding(title.buf, title.len, RFC2047_SUBJECT))
+ if (needs_rfc2047_encoding(title.buf, title.len))
add_rfc2047(sb, title.buf, title.len,
encoding, RFC2047_SUBJECT);
else