{"thread":{"id":"50200","subject":"[PATCH] log: add %S option (like --source) to log --format","startedAt":"2019-01-11T06:30:59Z","lastAt":"2019-01-11T06:30:59Z","messageCount":1,"participants":["issac.trotts@gmail.com"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"366554","messageId":"20190111063046.60771-1-issactrotts@google.com","threadId":"50200","inReplyTo":null,"subject":"[PATCH] log: add %S option (like --source) to log --format","fromName":"","fromEmail":"issac.trotts@gmail.com","sentAt":"2019-01-11T06:30:46Z","receivedAt":"2019-01-11T06:30:59Z","isPatch":true,"sender":{"key":"issac.trotts@gmail.com","avatar":"https://gravatar.com/avatar/44dd86aa2ea47c79d9b2a0a99b90e0ff18601855d2f05c6b84d6c432c5906721?d=mp&s=160"},"body":"From: Issac Trotts <issac.trotts@gmail.com>\n\nMake it possible to write for example\n\n        git log --format=\"%H,%S\"\n\nwhere the %S at the end is a new placeholder that prints out the ref\n(tag/branch) for each commit.\n\nUsing %d might seem like an alternative but it only shows the ref for the last\ncommit in the branch.\n\nSigned-off-by: Issac Trotts <issactrotts@google.com>\n\n---\n\nThis change is based on a question from Stack Overflow:\nhttps://stackoverflow.com/questions/12712775/git-get-source-information-in-format\n---\n Documentation/pretty-formats.txt |  2 ++\n builtin/log.c                    |  2 +-\n log-tree.c                       |  1 +\n pretty.c                         | 12 ++++++++\n pretty.h                         |  1 +\n t/t4205-log-pretty-formats.sh    | 50 ++++++++++++++++++++++++++++++++\n t/t6006-rev-list-format.sh       |  4 +++\n 7 files changed, 71 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex 417b638cd..de6953108 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -134,6 +134,8 @@ The placeholders are:\n - '%cI': committer date, strict ISO 8601 format\n - '%d': ref names, like the --decorate option of linkgit:git-log[1]\n - '%D': ref names without the \" (\", \")\" wrapping.\n+- '%S': ref name given on the command line by which the commit was reached\n+  (like `git log --source`), only works with `git log`\n - '%e': encoding\n - '%s': subject\n - '%f': sanitized subject line, suitable for a filename\ndiff --git a/builtin/log.c b/builtin/log.c\nindex e8e51068b..9deff32b8 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -203,7 +203,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t    rev->diffopt.filter || rev->diffopt.flags.follow_renames)\n \t\trev->always_show_header = 0;\n \n-\tif (source) {\n+\tif (source || w.source) {\n \t\tinit_revision_sources(&revision_sources);\n \t\trev->sources = &revision_sources;\n \t}\ndiff --git a/log-tree.c b/log-tree.c\nindex 10680c139..3cb14256e 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -700,6 +700,7 @@ void show_log(struct rev_info *opt)\n \tctx.color = opt->diffopt.use_color;\n \tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n \tctx.output_encoding = get_log_output_encoding();\n+\tctx.rev = opt;\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\n \tif (opt->graph)\ndiff --git a/pretty.c b/pretty.c\nindex b83a3ecd2..1b453fbb5 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1084,6 +1084,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */\n \tstruct commit_list *p;\n \tconst char *arg;\n \tint ch;\n+\tchar **slot;\n \n \t/* these are independent of the commit */\n \tswitch (placeholder[0]) {\n@@ -1194,6 +1195,14 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */\n \t\tload_ref_decorations(NULL, DECORATE_SHORT_REFS);\n \t\tformat_decorations_extended(sb, commit, c->auto_color, \"\", \", \", \"\");\n \t\treturn 1;\n+\tcase 'S':\t\t/* tag/branch like --source */\n+\t\tif (!(c->pretty_ctx->rev && c->pretty_ctx->rev->sources))\n+\t\t\treturn 0;\n+\t\tslot = revision_sources_at(c->pretty_ctx->rev->sources, commit);\n+\t\tif (!(slot && *slot))\n+\t\t\treturn 0;\n+\t\tstrbuf_addstr(sb, *slot);\n+\t\treturn 1;\n \tcase 'g':\t\t/* reflog info */\n \t\tswitch(placeholder[1]) {\n \t\tcase 'd':\t/* reflog selector */\n@@ -1498,6 +1507,9 @@ static size_t userformat_want_item(struct strbuf *sb, const char *placeholder,\n \tcase 'N':\n \t\tw->notes = 1;\n \t\tbreak;\n+\tcase 'S':\n+\t\tw->source = 1;\n+\t\tbreak;\n \t}\n \treturn 0;\n }\ndiff --git a/pretty.h b/pretty.h\nindex 7359d318a..87ca5dfcb 100644\n--- a/pretty.h\n+++ b/pretty.h\n@@ -60,6 +60,7 @@ static inline int cmit_fmt_is_mail(enum cmit_fmt fmt)\n \n struct userformat_want {\n \tunsigned notes:1;\n+\tunsigned source:1;\n };\n \n /* Set the flag \"w->notes\" if there is placeholder %N in \"fmt\". */\ndiff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh\nindex 978a8a66f..7df8c3d4e 100755\n--- a/t/t4205-log-pretty-formats.sh\n+++ b/t/t4205-log-pretty-formats.sh\n@@ -621,4 +621,54 @@ test_expect_success 'trailer parsing not fooled by --- line' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'set up %S tests' '\n+\tgit checkout --orphan source-a &&\n+\ttest_commit one &&\n+\ttest_commit two &&\n+\tgit checkout -b source-b HEAD^ &&\n+\ttest_commit three\n+'\n+\n+test_expect_success 'log --format=%S paints branch names' '\n+\tcat >expect <<-\\EOF &&\n+\tsource-b\n+\tsource-a\n+\tsource-b\n+\tEOF\n+\tgit log --format=%S source-a source-b >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'log --format=%S paints tag names' '\n+\tgit tag -m tagged source-tag &&\n+\tcat >expect <<-\\EOF &&\n+\tsource-tag\n+\tsource-a\n+\tsource-tag\n+\tEOF\n+\tgit log --format=%S source-tag source-a >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'log --format=%S paints symmetric ranges' '\n+\tcat >expect <<-\\EOF &&\n+\tsource-b\n+\tsource-a\n+\tEOF\n+\tgit log --format=%S source-a...source-b >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '%S in git log --format works with other placeholders (part 1)' '\n+\tgit log --format=\"source-b %h\" source-b >expect &&\n+\tgit log --format=\"%S %h\" source-b >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '%S in git log --format works with other placeholders (part 2)' '\n+\tgit log --format=\"%h source-b\" source-b >expect &&\n+\tgit log --format=\"%h %S\" source-b >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\ndiff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh\nindex ec42c2f77..da113d975 100755\n--- a/t/t6006-rev-list-format.sh\n+++ b/t/t6006-rev-list-format.sh\n@@ -185,6 +185,10 @@ test_expect_success 'basic colors' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success '%S is not a placeholder for rev-list yet' '\n+\tgit rev-list --format=\"%S\" -1 master | grep \"%S\"\n+'\n+\n test_expect_success 'advanced colors' '\n \tcat >expect <<-EOF &&\n \tcommit $head2\n-- \n2.19.1\n\n"}]}