From: Junio C Hamano Date: Sun, 13 Jun 2010 18:21:00 +0000 (-0700) Subject: Merge branch 'wp/pretty-enhancement' X-Git-Tag: v1.7.2-rc0~85 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/ce987457ca3db0c78d5e720f753adf210fd3dd65?ds=inline;hp=-c 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 --- ce987457ca3db0c78d5e720f753adf210fd3dd65 diff --combined Documentation/config.txt index 85f763c4d0,b41f39de7c..7e2ae254b0 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@@ -481,8 -481,6 +481,8 @@@ core.whitespace: error (enabled by default). * `indent-with-non-tab` treats a line that is indented with 8 or more space characters as an error (not enabled by default). +* `tab-in-indent` treats a tab character in the initial indent part of + the line as an error (not enabled by default). * `blank-at-eof` treats blank lines added at the end of file as an error (enabled by default). * `trailing-space` is a short-hand to cover both `blank-at-eol` and @@@ -946,19 -944,13 +946,19 @@@ gc.pruneexpire: unreachable objects immediately. gc.reflogexpire:: +gc..reflogexpire:: 'git reflog expire' removes reflog entries older than - this time; defaults to 90 days. + this time; defaults to 90 days. With "" (e.g. + "refs/stash") in the middle the setting applies only to + the refs that match the . gc.reflogexpireunreachable:: +gc..reflogexpireunreachable:: 'git reflog expire' removes reflog entries older than this time and are not reachable from the current tip; - defaults to 30 days. + defaults to 30 days. With "" (e.g. "refs/stash") + in the middle, the setting applies only to the refs that + match the . gc.rerereresolved:: Records of conflicted merge you resolved earlier are @@@ -1276,13 -1268,6 +1276,13 @@@ log.date: following alternatives: {relative,local,default,iso,rfc,short}. See linkgit:git-log[1]. +log.decorate:: + Print out the ref names of any commits that are shown by the log + command. If 'short' is specified, the ref name prefixes 'refs/heads/', + 'refs/tags/' and 'refs/remotes/' will not be printed. If 'full' is + specified, the full ref name (including prefix) will be printed. + This is the same as the log commands '--decorate' option. + log.showroot:: If true, the initial commit will be shown as a big creation event. This is equivalent to a diff against an empty tree. @@@ -1374,6 -1359,10 +1374,6 @@@ notes.rewrite.: automatically copies your notes from the original to the rewritten commit. Defaults to `true`, but see "notes.rewriteRef" below. -+ -This setting can be overridden with the `GIT_NOTES_REWRITE_REF` -environment variable, which must be a colon separated list of refs or -globs. notes.rewriteMode:: When copying notes during a rewrite (see the @@@ -1393,10 -1382,6 +1393,10 @@@ notes.rewriteRef: + Does not have a default value; you must configure this variable to enable note rewriting. ++ +This setting can be overridden with the `GIT_NOTES_REWRITE_REF` +environment variable, which must be a colon separated list of refs or +globs. pack.window:: The size of the window used by linkgit:git-pack-objects[1] when no @@@ -1481,6 -1466,16 +1481,16 @@@ pager.: it takes precedence over this option. To disable pagination for all commands, set `core.pager` or `GIT_PAGER` to `cat`. + pretty.:: + 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. @@@ -1531,7 -1526,7 +1541,7 @@@ receive.denyDeletes: the ref. Use this to prevent such a ref deletion via a push. receive.denyCurrentBranch:: - If set to true or "refuse", receive-pack will deny a ref update + If set to true or "refuse", git-receive-pack will deny a ref update to the currently checked out branch of a non-bare repository. Such a push is potentially dangerous because it brings the HEAD out of sync with the index and working tree. If set to "warn", @@@ -1593,9 -1588,7 +1603,9 @@@ remote..uploadpack: remote..tagopt:: Setting this value to \--no-tags disables automatic tag following when - fetching from remote + fetching from remote . Setting it to \--tags will fetch every + tag from remote , even if they are not reachable from remote + branch heads. remote..vcs:: Setting this to a value will cause git to interact with @@@ -1659,7 -1652,6 +1669,7 @@@ sendemail.smtppass: sendemail.suppresscc:: sendemail.suppressfrom:: sendemail.to:: +sendemail.smtpdomain:: sendemail.smtpserver:: sendemail.smtpserverport:: sendemail.smtpuser:: @@@ -1699,13 -1691,6 +1709,13 @@@ If this variable is not specified, it d This variable can be overridden with the -u|--untracked-files option of linkgit:git-status[1] and linkgit:git-commit[1]. +status.submodulesummary:: + Defaults to false. + If this is set to a non zero number or true (identical to -1 or an + unlimited number), the submodule summary will be enabled and a + summary of commits for modified submodules will be shown (see + --summary-limit option of linkgit:git-submodule[1]). + tar.umask:: This variable can be used to restrict the permission bits of tar archive entries. The default is 0002, which turns off the diff --combined Documentation/pretty-formats.txt index b055a673d8,5e95df6ba3..8c68ce94f9 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@@ -11,7 -11,12 +11,12 @@@ have limited your view of history: for 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. + 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' @@@ -76,9 -81,9 +81,9 @@@ displayed in full, regardless of whethe true parent commits, without taking grafts nor history simplification into account. -* 'format:' +* 'format:' + -The 'format:' format allows you to specify which information +The 'format:' format allows you to specify which information you want to show. It works a little bit like printf format, with the notable exception that you get a newline with '%n' instead of '\n'. @@@ -123,7 -128,6 +128,7 @@@ The placeholders are - '%s': subject - '%f': sanitized subject line, suitable for a filename - '%b': body +- '%B': raw body (unwrapped subject and body) - '%N': commit notes - '%gD': reflog selector, e.g., `refs/stash@\{1\}` - '%gd': shortened reflog selector, e.g., `stash@\{1\}` diff --combined pretty.c index 74cda1b44e,4784f676fa..8b18efda9c --- a/pretty.c +++ b/pretty.c @@@ -11,6 -11,17 +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 +32,118 @@@ rev->commit_format = CMIT_FMT_USERFORMAT; } - void get_commit_format(const char *arg, struct rev_info *rev) + 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; - 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 }, + + 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) + { + struct cmt_fmt_map *commit_format; rev->use_terminator = 0; if (!arg || !*arg) { @@@ -47,21 -154,22 +154,22 @@@ 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); + } } /* @@@ -716,7 -824,7 +824,7 @@@ static size_t format_commit_one(struct 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 */ @@@ -726,7 -834,7 +834,7 @@@ 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 */ @@@ -743,8 -851,7 +851,8 @@@ 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; @@@ -801,10 -908,6 +909,10 @@@ 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. */