Merge branch 'wp/pretty-enhancement'
* wp/pretty-enhancement: pretty: initialize new cmt_fmt_map to 0 pretty: add aliases for pretty formats pretty: add infrastructure for commit format aliases pretty: make it easier to add new formats
This commit is contained in:
commit
ce987457ca
@ -1481,6 +1481,16 @@ pager.<cmd>::
|
||||
it takes precedence over this option. To disable pagination for
|
||||
all commands, set `core.pager` or `GIT_PAGER` to `cat`.
|
||||
|
||||
pretty.<name>::
|
||||
Alias for a --pretty= format string, as specified in
|
||||
linkgit:git-log[1]. Any aliases defined here can be used just
|
||||
as the built-in pretty formats could. For example,
|
||||
running `git config pretty.changelog "format:{asterisk} %H %s"`
|
||||
would cause the invocation `git log --pretty=changelog`
|
||||
to be equivalent to running `git log "--pretty=format:{asterisk} %H %s"`.
|
||||
Note that an alias with the same name as a built-in format
|
||||
will be silently ignored.
|
||||
|
||||
pull.octopus::
|
||||
The default merge strategy to use when pulling multiple branches
|
||||
at once.
|
||||
|
@ -11,7 +11,12 @@ have limited your view of history: for example, if you are
|
||||
only interested in changes related to a certain directory or
|
||||
file.
|
||||
|
||||
Here are some additional details for each format:
|
||||
There are several built-in formats, and you can define
|
||||
additional formats by setting a pretty.<name>
|
||||
config option to either another format name, or a
|
||||
'format:' string, as described below (see
|
||||
linkgit:git-config[1]). Here are the details of the
|
||||
built-in formats:
|
||||
|
||||
* 'oneline'
|
||||
|
||||
|
156
pretty.c
156
pretty.c
@ -11,6 +11,17 @@
|
||||
#include "reflog-walk.h"
|
||||
|
||||
static char *user_format;
|
||||
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)
|
||||
{
|
||||
@ -21,22 +32,118 @@ 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[] = {
|
||||
{ "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);
|
||||
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,
|
||||
const char *original,
|
||||
int num_redirections)
|
||||
{
|
||||
struct cmt_fmt_map *found = NULL;
|
||||
size_t found_match_len = 0;
|
||||
int i;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 *commit_format;
|
||||
|
||||
rev->use_terminator = 0;
|
||||
if (!arg || !*arg) {
|
||||
@ -47,21 +154,22 @@ 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;
|
||||
if (commit_format->format == CMIT_FMT_USERFORMAT) {
|
||||
save_user_format(rev, commit_format->user_format,
|
||||
commit_format->is_tformat);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
74
t/t4205-log-pretty-formats.sh
Executable file
74
t/t4205-log-pretty-formats.sh
Executable file
@ -0,0 +1,74 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2010, Will Palmer
|
||||
#
|
||||
|
||||
test_description='Test pretty formats'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'set up basic repos' '
|
||||
>foo &&
|
||||
>bar &&
|
||||
git add foo &&
|
||||
test_tick &&
|
||||
git commit -m initial &&
|
||||
git add bar &&
|
||||
test_tick &&
|
||||
git commit -m "add bar"
|
||||
'
|
||||
|
||||
test_expect_success 'alias builtin format' '
|
||||
git log --pretty=oneline >expected &&
|
||||
git config pretty.test-alias oneline &&
|
||||
git log --pretty=test-alias >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'alias masking builtin format' '
|
||||
git log --pretty=oneline >expected &&
|
||||
git config pretty.oneline "%H" &&
|
||||
git log --pretty=oneline >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'alias user-defined format' '
|
||||
git log --pretty="format:%h" >expected &&
|
||||
git config pretty.test-alias "format:%h" &&
|
||||
git log --pretty=test-alias >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'alias user-defined tformat' '
|
||||
git log --pretty="tformat:%h" >expected &&
|
||||
git config pretty.test-alias "tformat:%h" &&
|
||||
git log --pretty=test-alias >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'alias non-existant format' '
|
||||
git config pretty.test-alias format-that-will-never-exist &&
|
||||
test_must_fail git log --pretty=test-alias
|
||||
'
|
||||
|
||||
test_expect_success 'alias of an alias' '
|
||||
git log --pretty="tformat:%h" >expected &&
|
||||
git config pretty.test-foo "tformat:%h" &&
|
||||
git config pretty.test-bar test-foo &&
|
||||
git log --pretty=test-bar >actual && test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'alias masking an alias' '
|
||||
git log --pretty=format:"Two %H" >expected &&
|
||||
git config pretty.duplicate "format:One %H" &&
|
||||
git config --add pretty.duplicate "format:Two %H" &&
|
||||
git log --pretty=duplicate >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'alias loop' '
|
||||
git config pretty.test-foo test-bar &&
|
||||
git config pretty.test-bar test-foo &&
|
||||
test_must_fail git log --pretty=test-foo
|
||||
'
|
||||
|
||||
test_done
|
Loading…
Reference in New Issue
Block a user