From 409578912cb21bdad4a75f34af7c0a815ac9d06b Mon Sep 17 00:00:00 2001 From: Will Palmer Date: Sun, 2 May 2010 12:00:42 +0100 Subject: pretty: make it easier to add new formats As the first step towards creating aliases, we make it easier to add new formats to the list of builtin formats. To do this, we move the initialization of the formats array into a new function, setup_commit_formats(), which we can easily extend later. Then, rather than looping through only the list of known formats, we make a more generic find_commit_format function, which will return the commit format whose name is the shortest which is prefixed with the passed-in sought format, the same rules which were more-or-less hard-coded in before. Signed-off-by: Will Palmer Reviewed-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- pretty.c | 81 +++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 24 deletions(-) (limited to 'pretty.c') diff --git a/pretty.c b/pretty.c index 7cb3a2af50..f795a9a18d 100644 --- a/pretty.c +++ b/pretty.c @@ -11,6 +11,13 @@ #include "reflog-walk.h" static char *user_format; +static struct cmt_fmt_map { + const char *name; + enum cmit_fmt format; + int is_tformat; +} *commit_formats; +static size_t commit_formats_len; +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) { @@ -21,22 +28,51 @@ static void save_user_format(struct rev_info *rev, const char *cp, int is_tforma rev->commit_format = CMIT_FMT_USERFORMAT; } -void get_commit_format(const char *arg, struct rev_info *rev) +static void setup_commit_formats(void) { - int i; - static struct cmt_fmt_map { - const char *n; - size_t cmp_len; - enum cmit_fmt v; - } cmt_fmts[] = { - { "raw", 1, CMIT_FMT_RAW }, - { "medium", 1, CMIT_FMT_MEDIUM }, - { "short", 1, CMIT_FMT_SHORT }, - { "email", 1, CMIT_FMT_EMAIL }, - { "full", 5, CMIT_FMT_FULL }, - { "fuller", 5, CMIT_FMT_FULLER }, - { "oneline", 1, CMIT_FMT_ONELINE }, + struct cmt_fmt_map builtin_formats[] = { + { "raw", CMIT_FMT_RAW, 0 }, + { "medium", CMIT_FMT_MEDIUM, 0 }, + { "short", CMIT_FMT_SHORT, 0 }, + { "email", CMIT_FMT_EMAIL, 0 }, + { "fuller", CMIT_FMT_FULLER, 0 }, + { "full", CMIT_FMT_FULL, 0 }, + { "oneline", CMIT_FMT_ONELINE, 1 } }; + commit_formats_len = ARRAY_SIZE(builtin_formats); + commit_formats = xmalloc(commit_formats_len * + sizeof(*builtin_formats)); + memcpy(commit_formats, builtin_formats, + sizeof(*builtin_formats)*ARRAY_SIZE(builtin_formats)); +} + +static struct cmt_fmt_map *find_commit_format(const char *sought) +{ + struct cmt_fmt_map *found = NULL; + size_t found_match_len = 0; + int i; + + if (!commit_formats) + setup_commit_formats(); + + for (i = 0; i < commit_formats_len; i++) { + size_t match_len; + + if (prefixcmp(commit_formats[i].name, sought)) + continue; + + match_len = strlen(commit_formats[i].name); + if (found == NULL || found_match_len > match_len) { + found = &commit_formats[i]; + found_match_len = match_len; + } + } + return found; +} + +void get_commit_format(const char *arg, struct rev_info *rev) +{ + struct cmt_fmt_map *commit_format; rev->use_terminator = 0; if (!arg || !*arg) { @@ -47,21 +83,18 @@ void get_commit_format(const char *arg, struct rev_info *rev) save_user_format(rev, strchr(arg, ':') + 1, arg[0] == 't'); return; } - for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) { - if (!strncmp(arg, cmt_fmts[i].n, cmt_fmts[i].cmp_len) && - !strncmp(arg, cmt_fmts[i].n, strlen(arg))) { - if (cmt_fmts[i].v == CMIT_FMT_ONELINE) - rev->use_terminator = 1; - rev->commit_format = cmt_fmts[i].v; - return; - } - } + if (strchr(arg, '%')) { save_user_format(rev, arg, 1); return; } - die("invalid --pretty format: %s", arg); + commit_format = find_commit_format(arg); + if (!commit_format) + die("invalid --pretty format: %s", arg); + + rev->commit_format = commit_format->format; + rev->use_terminator = commit_format->is_tformat; } /* -- cgit v1.2.3 From 2d7671ef43946cdfce140e6e9c3ca1eeea361676 Mon Sep 17 00:00:00 2001 From: Will Palmer Date: Sun, 2 May 2010 12:00:43 +0100 Subject: pretty: add infrastructure for commit format aliases Allow named commit formats to alias one another; find_commit_format() will recursively dereference aliases when they are specified. At this point, there are no aliases specified and there is no way to specify an alias, but the support is there for any which are added. If an alias loop is detected, the function die()s. Signed-off-by: Will Palmer Reviewed-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- pretty.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'pretty.c') diff --git a/pretty.c b/pretty.c index f795a9a18d..c2c8901f8f 100644 --- a/pretty.c +++ b/pretty.c @@ -15,6 +15,8 @@ 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 commit_formats_len; static struct cmt_fmt_map *find_commit_format(const char *sought); @@ -46,14 +48,18 @@ static void setup_commit_formats(void) sizeof(*builtin_formats)*ARRAY_SIZE(builtin_formats)); } -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 +73,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; -- cgit v1.2.3 From 8028184eecf1051e4b39b308a3ad909eed1371c4 Mon Sep 17 00:00:00 2001 From: Will Palmer Date: Sun, 2 May 2010 12:00:44 +0100 Subject: pretty: add aliases for pretty formats previously the only ways to alias a --pretty format within git were either to set the format as your default format (via the format.pretty configuration variable), or by using a regular git alias. This left the definition of more complicated formats to the realm of "builtin or nothing", with user-defined formats usually being reserved for quick one-offs. Here we allow user-defined formats to enjoy more or less the same benefits of builtins. By defining pretty.myalias, "myalias" can be used in place of whatever would normally come after --pretty=. This can be a format:, tformat:, raw (ie, defaulting to tformat), or the name of another builtin or user-defined pretty format. Signed-off-by: Will Palmer Reviewed-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- pretty.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'pretty.c') diff --git a/pretty.c b/pretty.c index c2c8901f8f..aaf80207c9 100644 --- a/pretty.c +++ b/pretty.c @@ -18,7 +18,9 @@ static struct cmt_fmt_map { 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) @@ -30,6 +32,51 @@ 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]; + 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[] = { @@ -42,10 +89,12 @@ 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_recursive(const char *sought, @@ -116,6 +165,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); + } } /* -- cgit v1.2.3 From 95a2618f60a61fae8097695255419f257f74dff9 Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Sat, 8 May 2010 16:07:39 -0500 Subject: pretty: initialize new cmt_fmt_map to 0 Without this change, is_alias is likely to happen to be nonzero, resulting in "fatal: invalid --pretty format" when the fake alias cannot be resolved. Use memset instead of initializing the members one by one to make it easier to expand the struct in the future if needed. t4205 (log --pretty) does not pass for me without this fix. Cc: Will Palmer Signed-off-by: Jonathan Nieder Signed-off-by: Junio C Hamano --- pretty.c | 1 + 1 file changed, 1 insertion(+) (limited to 'pretty.c') diff --git a/pretty.c b/pretty.c index aaf80207c9..4784f676fa 100644 --- a/pretty.c +++ b/pretty.c @@ -59,6 +59,7 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c 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++; } -- cgit v1.2.3