{"thread":{"id":"21265","subject":"[PATCH v3.1 3/5] Introduce new pretty formats %g[sdD] for reflog information","startedAt":"2009-10-17T14:39:53Z","lastAt":"2009-10-17T14:39:53Z","messageCount":1,"participants":["Thomas Rast"],"isPatch":true,"patchVersion":3,"patchTotal":5},"messages":[{"id":"125237","messageId":"e0ab6923eb4057bcbc8e97980dad5e4a37e53067.1255789678.git.trast@student.ethz.ch","threadId":"21265","inReplyTo":"cover.1255789678.git.trast@student.ethz.ch","subject":"[PATCH v3.1 3/5] Introduce new pretty formats %g[sdD] for reflog information","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2009-10-17T14:39:53Z","receivedAt":"2009-10-17T14:39:53Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Add three new --pretty=format escapes:\n\n  %gD  long  reflog descriptor (e.g. refs/stash@{0})\n  %gd  short reflog descriptor (e.g. stash@{0})\n  %gs  reflog message\n\nThis is achieved by passing down the reflog info, if any, inside the\npretty_print_context struct.\n\nWe use the newly refactored get_reflog_selector(), and give it some\nextra functionality to extract a shortened ref.  The shortening is\ncached inside the commit_reflogs struct; the only allocation of it\nhappens in read_complete_reflog(), where it is initialised to 0.  Also\nadd another helper get_reflog_message() for the message extraction.\n\nNote that the --format=\"%h %gD: %gs\" tests may not work in real\nrepositories, as the --pretty formatter doesn't know to leave away the\n\": \" on the last commit in an incomplete (because git-gc removed the\nold part) reflog.  This equivalence is nevertheless the main goal of\nthis patch.\n\nThanks to Jeff King for reviews, the %gd testcase and documentation.\n\nSigned-off-by: Thomas Rast <trast@student.ethz.ch>\n---\n\n[Tacking this on the corresponding v3 patch, but the text below is\nfrom <20091017011801.GA31443@coredump.intra.peff.net>.]\n\nJeff King wrote:\n> I am tempted to do a note like the one below, but maybe the behavior is\n> obvious enough to users that it isn't necessary.\n[...]\n> +NOTE: Some placeholders may depend on other options given to the\n> +revision traversal engine. For example, the `%g*` reflog options will\n> +insert an empty string unless we are traversing reflog entries (e.g., by\n> +`git log -g`). The `%d` placeholder will use the \"short\" decoration\n> +format if `--decorate` was not already provided on the command line.\n\nSure.  I figured it was obvious enough, but since you already went to\nthe lengths of documenting the exact behaviour of %d, I squashed it\nand adjusted the acknowledgement in the commit message accordingly.\n\n\n Documentation/pretty-formats.txt |    9 +++++++++\n commit.h                         |    1 +\n log-tree.c                       |    1 +\n pretty.c                         |   17 +++++++++++++++++\n reflog-walk.c                    |   35 ++++++++++++++++++++++++++++++++---\n reflog-walk.h                    |    8 ++++++++\n t/t6006-rev-list-format.sh       |   18 ++++++++++++++++++\n 7 files changed, 86 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 2a845b1..38b9904 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -123,6 +123,9 @@ The placeholders are:\n - '%s': subject\n - '%f': sanitized subject line, suitable for a filename\n - '%b': body\n+- '%gD': reflog selector, e.g., `refs/stash@\\{1\\}`\n+- '%gd': shortened reflog selector, e.g., `stash@\\{1\\}`\n+- '%gs': reflog subject\n - '%Cred': switch color to red\n - '%Cgreen': switch color to green\n - '%Cblue': switch color to blue\n@@ -132,6 +135,12 @@ The placeholders are:\n - '%n': newline\n - '%x00': print a byte from a hex code\n \n+NOTE: Some placeholders may depend on other options given to the\n+revision traversal engine. For example, the `%g*` reflog options will\n+insert an empty string unless we are traversing reflog entries (e.g., by\n+`git log -g`). The `%d` placeholder will use the \"short\" decoration\n+format if `--decorate` was not already provided on the command line.\n+\n * 'tformat:'\n +\n The 'tformat:' format works exactly like 'format:', except that it\ndiff --git a/commit.h b/commit.h\nindex 011766d..15cb649 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -70,6 +70,7 @@ struct pretty_print_context\n \tconst char *after_subject;\n \tenum date_mode date_mode;\n \tint need_8bit_cte;\n+\tstruct reflog_walk_info *reflog_info;\n };\n \n extern int non_ascii(int);\ndiff --git a/log-tree.c b/log-tree.c\nindex f57487f..8e782fc 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -409,6 +409,7 @@ void show_log(struct rev_info *opt)\n \tctx.date_mode = opt->date_mode;\n \tctx.abbrev = opt->diffopt.abbrev;\n \tctx.after_subject = extra_headers;\n+\tctx.reflog_info = opt->reflog_info;\n \tpretty_print_commit(opt->commit_format, commit, &msgbuf, &ctx);\n \n \tif (opt->add_signoff)\ndiff --git a/pretty.c b/pretty.c\nindex d6d57eb..fc65fca 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -7,6 +7,7 @@\n #include \"mailmap.h\"\n #include \"log-tree.h\"\n #include \"color.h\"\n+#include \"reflog-walk.h\"\n \n static char *user_format;\n \n@@ -701,6 +702,22 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,\n \tcase 'd':\n \t\tformat_decoration(sb, commit);\n \t\treturn 1;\n+\tcase 'g':\t\t/* reflog info */\n+\t\tswitch(placeholder[1]) {\n+\t\tcase 'd':\t/* reflog selector */\n+\t\tcase 'D':\n+\t\t\tif (c->pretty_ctx->reflog_info)\n+\t\t\t\tget_reflog_selector(sb,\n+\t\t\t\t\t\t    c->pretty_ctx->reflog_info,\n+\t\t\t\t\t\t    c->pretty_ctx->date_mode,\n+\t\t\t\t\t\t    (placeholder[1] == 'd'));\n+\t\t\treturn 2;\n+\t\tcase 's':\t/* reflog message */\n+\t\t\tif (c->pretty_ctx->reflog_info)\n+\t\t\t\tget_reflog_message(sb, c->pretty_ctx->reflog_info);\n+\t\t\treturn 2;\n+\t\t}\n+\t\treturn 0;\t/* unknown %g placeholder */\n \t}\n \n \t/* For the rest we have to parse the commit header. */\ndiff --git a/reflog-walk.c b/reflog-walk.c\nindex 596bafe..caba4f7 100644\n--- a/reflog-walk.c\n+++ b/reflog-walk.c\n@@ -8,6 +8,7 @@\n \n struct complete_reflogs {\n \tchar *ref;\n+\tconst char *short_ref;\n \tstruct reflog_info {\n \t\tunsigned char osha1[20], nsha1[20];\n \t\tchar *email;\n@@ -243,15 +244,26 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)\n \n void get_reflog_selector(struct strbuf *sb,\n \t\t\t struct reflog_walk_info *reflog_info,\n-\t\t\t enum date_mode dmode)\n+\t\t\t enum date_mode dmode,\n+\t\t\t int shorten)\n {\n \tstruct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;\n \tstruct reflog_info *info;\n+\tconst char *printed_ref;\n \n \tif (!commit_reflog)\n \t\treturn;\n \n-\tstrbuf_addf(sb, \"%s@{\", commit_reflog->reflogs->ref);\n+\tif (shorten) {\n+\t\tif (!commit_reflog->reflogs->short_ref)\n+\t\t\tcommit_reflog->reflogs->short_ref\n+\t\t\t\t= shorten_unambiguous_ref(commit_reflog->reflogs->ref, 0);\n+\t\tprinted_ref = commit_reflog->reflogs->short_ref;\n+\t} else {\n+\t\tprinted_ref = commit_reflog->reflogs->ref;\n+\t}\n+\n+\tstrbuf_addf(sb, \"%s@{\", printed_ref);\n \tif (commit_reflog->flag || dmode) {\n \t\tinfo = &commit_reflog->reflogs->items[commit_reflog->recno+1];\n \t\tstrbuf_addstr(sb, show_date(info->timestamp, info->tz, dmode));\n@@ -263,6 +275,23 @@ void get_reflog_selector(struct strbuf *sb,\n \tstrbuf_addch(sb, '}');\n }\n \n+void get_reflog_message(struct strbuf *sb,\n+\t\t\tstruct reflog_walk_info *reflog_info)\n+{\n+\tstruct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;\n+\tstruct reflog_info *info;\n+\tsize_t len;\n+\n+\tif (!commit_reflog)\n+\t\treturn;\n+\n+\tinfo = &commit_reflog->reflogs->items[commit_reflog->recno+1];\n+\tlen = strlen(info->message);\n+\tif (len > 0)\n+\t\tlen--; /* strip away trailing newline */\n+\tstrbuf_add(sb, info->message, len);\n+}\n+\n void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,\n \tenum date_mode dmode)\n {\n@@ -272,7 +301,7 @@ void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,\n \t\tstruct strbuf selector = STRBUF_INIT;\n \n \t\tinfo = &commit_reflog->reflogs->items[commit_reflog->recno+1];\n-\t\tget_reflog_selector(&selector, reflog_info, dmode);\n+\t\tget_reflog_selector(&selector, reflog_info, dmode, 0);\n \t\tif (oneline) {\n \t\t\tprintf(\"%s: %s\", selector.buf, info->message);\n \t\t}\ndiff --git a/reflog-walk.h b/reflog-walk.h\nindex 74c9096..7bd2cd4 100644\n--- a/reflog-walk.h\n+++ b/reflog-walk.h\n@@ -3,6 +3,8 @@\n \n #include \"cache.h\"\n \n+struct reflog_walk_info;\n+\n extern void init_reflog_walk(struct reflog_walk_info** info);\n extern int add_reflog_for_walk(struct reflog_walk_info *info,\n \t\tstruct commit *commit, const char *name);\n@@ -10,5 +12,11 @@ extern void fake_reflog_parent(struct reflog_walk_info *info,\n \t\tstruct commit *commit);\n extern void show_reflog_message(struct reflog_walk_info *info, int,\n \t\tenum date_mode);\n+extern void get_reflog_message(struct strbuf *sb,\n+\t\tstruct reflog_walk_info *reflog_info);\n+extern void get_reflog_selector(struct strbuf *sb,\n+\t\tstruct reflog_walk_info *reflog_info,\n+\t\tenum date_mode dmode,\n+\t\tint shorten);\n \n #endif\ndiff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh\nindex 59d1f62..7f61ab0 100755\n--- a/t/t6006-rev-list-format.sh\n+++ b/t/t6006-rev-list-format.sh\n@@ -162,4 +162,22 @@ test_expect_success 'empty email' '\n \t}\n '\n \n+test_expect_success '\"%h %gD: %gs\" is same as git-reflog' '\n+\tgit reflog >expect &&\n+\tgit log -g --format=\"%h %gD: %gs\" >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '\"%h %gD: %gs\" is same as git-reflog (with date)' '\n+\tgit reflog --date=raw >expect &&\n+\tgit log -g --format=\"%h %gD: %gs\" --date=raw >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '%gd shortens ref name' '\n+\techo \"master@{0}\" >expect.gd-short &&\n+\tgit log -g -1 --format=%gd refs/heads/master >actual.gd-short &&\n+\ttest_cmp expect.gd-short actual.gd-short\n+'\n+\n test_done\n-- \n1.6.5.116.g4aaa3\n"}]}