X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=pretty.c;h=8b18efda9cd6eb615900687c0205daa832794c92;hb=6339f67fedfec454294dc33ebc3dcec6eeb70e02;hp=f795a9a18d735b9385ded29bb55ae6ae5e9ac046;hpb=409578912cb21bdad4a75f34af7c0a815ac9d06b;p=git.git diff --git a/pretty.c b/pretty.c index f795a9a18..8b18efda9 100644 --- a/pretty.c +++ b/pretty.c @@ -15,8 +15,12 @@ static struct cmt_fmt_map { const char *name; enum cmit_fmt format; int is_tformat; + int is_alias; + const char *user_format; } *commit_formats; +static size_t builtin_formats_len; static size_t commit_formats_len; +static size_t commit_formats_alloc; static struct cmt_fmt_map *find_commit_format(const char *sought); static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat) @@ -28,6 +32,52 @@ static void save_user_format(struct rev_info *rev, const char *cp, int is_tforma rev->commit_format = CMIT_FMT_USERFORMAT; } +static int git_pretty_formats_config(const char *var, const char *value, void *cb) +{ + struct cmt_fmt_map *commit_format = NULL; + const char *name; + const char *fmt; + int i; + + if (prefixcmp(var, "pretty.")) + return 0; + + name = var + strlen("pretty."); + for (i = 0; i < builtin_formats_len; i++) { + if (!strcmp(commit_formats[i].name, name)) + return 0; + } + + for (i = builtin_formats_len; i < commit_formats_len; i++) { + if (!strcmp(commit_formats[i].name, name)) { + commit_format = &commit_formats[i]; + break; + } + } + + if (!commit_format) { + ALLOC_GROW(commit_formats, commit_formats_len+1, + commit_formats_alloc); + commit_format = &commit_formats[commit_formats_len]; + memset(commit_format, 0, sizeof(*commit_format)); + commit_formats_len++; + } + + commit_format->name = xstrdup(name); + commit_format->format = CMIT_FMT_USERFORMAT; + git_config_string(&fmt, var, value); + if (!prefixcmp(fmt, "format:") || !prefixcmp(fmt, "tformat:")) { + commit_format->is_tformat = fmt[0] == 't'; + fmt = strchr(fmt, ':') + 1; + } else if (strchr(fmt, '%')) + commit_format->is_tformat = 1; + else + commit_format->is_alias = 1; + commit_format->user_format = fmt; + + return 0; +} + static void setup_commit_formats(void) { struct cmt_fmt_map builtin_formats[] = { @@ -40,20 +90,26 @@ static void setup_commit_formats(void) { "oneline", CMIT_FMT_ONELINE, 1 } }; commit_formats_len = ARRAY_SIZE(builtin_formats); - commit_formats = xmalloc(commit_formats_len * - sizeof(*builtin_formats)); + builtin_formats_len = commit_formats_len; + ALLOC_GROW(commit_formats, commit_formats_len, commit_formats_alloc); memcpy(commit_formats, builtin_formats, sizeof(*builtin_formats)*ARRAY_SIZE(builtin_formats)); + + git_config(git_pretty_formats_config, NULL); } -static struct cmt_fmt_map *find_commit_format(const char *sought) +static struct cmt_fmt_map *find_commit_format_recursive(const char *sought, + const char *original, + int num_redirections) { struct cmt_fmt_map *found = NULL; size_t found_match_len = 0; int i; - if (!commit_formats) - setup_commit_formats(); + if (num_redirections >= commit_formats_len) + die("invalid --pretty format: " + "'%s' references an alias which points to itself", + original); for (i = 0; i < commit_formats_len; i++) { size_t match_len; @@ -67,9 +123,24 @@ static struct cmt_fmt_map *find_commit_format(const char *sought) found_match_len = match_len; } } + + if (found && found->is_alias) { + found = find_commit_format_recursive(found->user_format, + original, + num_redirections+1); + } + return found; } +static struct cmt_fmt_map *find_commit_format(const char *sought) +{ + if (!commit_formats) + setup_commit_formats(); + + return find_commit_format_recursive(sought, sought, 0); +} + void get_commit_format(const char *arg, struct rev_info *rev) { struct cmt_fmt_map *commit_format; @@ -95,6 +166,10 @@ void get_commit_format(const char *arg, struct rev_info *rev) rev->commit_format = commit_format->format; rev->use_terminator = commit_format->is_tformat; + if (commit_format->format == CMIT_FMT_USERFORMAT) { + save_user_format(rev, commit_format->user_format, + commit_format->is_tformat); + } } /* @@ -749,7 +824,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder, if (add_again(sb, &c->abbrev_commit_hash)) return 1; strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1, - DEFAULT_ABBREV)); + c->pretty_ctx->abbrev)); c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off; return 1; case 'T': /* tree hash */ @@ -759,7 +834,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder, if (add_again(sb, &c->abbrev_tree_hash)) return 1; strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.sha1, - DEFAULT_ABBREV)); + c->pretty_ctx->abbrev)); c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off; return 1; case 'P': /* parent hashes */ @@ -776,7 +851,8 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder, if (p != commit->parents) strbuf_addch(sb, ' '); strbuf_addstr(sb, find_unique_abbrev( - p->item->object.sha1, DEFAULT_ABBREV)); + p->item->object.sha1, + c->pretty_ctx->abbrev)); } c->abbrev_parent_hashes.len = sb->len - c->abbrev_parent_hashes.off; @@ -833,6 +909,10 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder, case 'e': /* encoding */ strbuf_add(sb, msg + c->encoding.off, c->encoding.len); return 1; + case 'B': /* raw body */ + /* message_off is always left at the initial newline */ + strbuf_addstr(sb, msg + c->message_off + 1); + return 1; } /* Now we need to parse the commit message. */