{"thread":{"id":"48248","subject":"[RFC PATCH] Add \"git show --follow-symlinks HEAD:symlink\"","startedAt":"2018-04-09T09:00:57Z","lastAt":"2018-04-16T23:05:23Z","messageCount":12,"participants":["Michael Vogt","Ævar Arnfjörð Bjarmason","Stefan Beller","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"344184","messageId":"20180409090047.lfru2ul5fbnggfg7@bod","threadId":"48248","inReplyTo":null,"subject":"[RFC PATCH] Add \"git show --follow-symlinks HEAD:symlink\"","fromName":"Michael Vogt","fromEmail":"mvo@ubuntu.com","sentAt":"2018-04-09T09:00:47Z","receivedAt":"2018-04-09T09:00:57Z","isPatch":true,"sender":{"key":"mvo@ubuntu.com","avatar":"https://gravatar.com/avatar/8c3aed66a64c58eafced3802188a573f5a14143215cfe334e77d3ed4d6948acf?d=mp&s=160"},"body":"Hi,\n\nI noticed that `git show HEAD:path-to-symlink` does not work and\nreturns an error like:\n\"fatal: Path 'debian/changelog' exists on disk, but not in 'HEAD'.\"\n\nLooking at `git show` it seems there is no way right now to make\ngit-show show blobs if they are symlinks [1].\n\nIt would be nice to have this ability. Attached is a draft patch to\nallow to write: `git show --follow-symlinks HEAD:path-to-symlink`.\nTests are missing in the patch, I'm happy to add those if there is a\nchance for the feature to get in.\n\nCheers,\n Michael\n\n[1] Using `git cat-file --follow-symlinks --batch < input` works but\n    feels a bit less elegant compared to supporting it directly in\n    git-show.\n\n\nFrom 616b7f21c057656960cb6b8a266095bbef734122 Mon Sep 17 00:00:00 2001\nFrom: Michael Vogt <mvo@ubuntu.com>\nDate: Mon, 9 Apr 2018 10:38:13 +0200\nSubject: [PATCH] support: git show --follow-symlinks HEAD:symlink\n\nAdd support for the `--follow-symlinks` options to git-show. This\nallows to write:\n\n    git show --follow-symlink HEAD:path-a-symlink\n\nto get the content of the symlinked file.\n---\n builtin/log.c | 7 +++++--\n revision.c    | 2 ++\n revision.h    | 1 +\n 3 files changed, 8 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 94ee177d5..e92af4fc7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -142,7 +142,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t struct rev_info *rev, struct setup_revision_opt *opt)\n {\n \tstruct userformat_want w;\n-\tint quiet = 0, source = 0, mailmap = 0;\n+\tint quiet = 0, source = 0, mailmap = 0, follow_symlinks = 0;\n \tstatic struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};\n \tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n@@ -162,6 +162,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\tOPT_CALLBACK('L', NULL, &line_cb, \"n,m:file\",\n \t\t\t     N_(\"Process line range n,m in file, counting from 1\"),\n \t\t\t     log_line_range_callback),\n+\t\tOPT_BOOL(0, \"follow-symlinks\", &follow_symlinks,\n+\t\t\t N_(\"follow in-tree symlinks (used when showing file content)\")),\n \t\tOPT_END()\n \t};\n \n@@ -173,9 +175,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t     builtin_log_options, builtin_log_usage,\n \t\t\t     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n-\n \tif (quiet)\n \t\trev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;\n+\tif (follow_symlinks)\n+\t\trev->follow_symlinks = 1;\n \targc = setup_revisions(argc, argv, rev, opt);\n \n \t/* Any arguments at this point are not recognized */\ndiff --git a/revision.c b/revision.c\nindex b42c836d7..4ab22313f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1678,6 +1678,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi\n \n \tif (revarg_opt & REVARG_COMMITTISH)\n \t\tget_sha1_flags |= GET_OID_COMMITTISH;\n+\tif (revs && revs->follow_symlinks)\n+\t\tget_sha1_flags |= GET_OID_FOLLOW_SYMLINKS;\n \n \tif (get_oid_with_context(arg, get_sha1_flags, &oid, &oc))\n \t\treturn revs->ignore_missing ? 0 : -1;\ndiff --git a/revision.h b/revision.h\nindex b8c47b98e..060f1038a 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -122,6 +122,7 @@ struct rev_info {\n \t\t\tfirst_parent_only:1,\n \t\t\tline_level_traverse:1,\n \t\t\ttree_blobs_in_commit_order:1,\n+\t\t\tfollow_symlinks:1,\n \n \t\t\t/* for internal use only */\n \t\t\texclude_promisor_objects:1;\n-- \n2.14.1\n\n"},{"id":"344185","messageId":"87in90zq2a.fsf@evledraar.gmail.com","threadId":"48248","inReplyTo":"20180409090047.lfru2ul5fbnggfg7@bod","subject":"Re: [RFC PATCH] Add \"git show --follow-symlinks HEAD:symlink\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2018-04-09T09:28:45Z","receivedAt":"2018-04-09T09:28:53Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Mon, Apr 09 2018, Michael Vogt wrote:\n\n> I noticed that `git show HEAD:path-to-symlink` does not work and\n> returns an error like:\n> \"fatal: Path 'debian/changelog' exists on disk, but not in 'HEAD'.\"\n>\n> Looking at `git show` it seems there is no way right now to make\n> git-show show blobs if they are symlinks [1].\n>\n> It would be nice to have this ability. Attached is a draft patch to\n> allow to write: `git show --follow-symlinks HEAD:path-to-symlink`.\n> Tests are missing in the patch, I'm happy to add those if there is a\n> chance for the feature to get in.\n>\n> Cheers,\n>  Michael\n>\n> [1] Using `git cat-file --follow-symlinks --batch < input` works but\n>     feels a bit less elegant compared to supporting it directly in\n>     git-show.\n> From 616b7f21c057656960cb6b8a266095bbef734122 Mon Sep 17 00:00:00 2001\n> From: Michael Vogt <mvo@ubuntu.com>\n> Date: Mon, 9 Apr 2018 10:38:13 +0200\n> Subject: [PATCH] support: git show --follow-symlinks HEAD:symlink\n>\n> Add support for the `--follow-symlinks` options to git-show. This\n> allows to write:\n>\n>     git show --follow-symlink HEAD:path-a-symlink\n\nThe patch looks reasonable, but please submit it as described in\nDocumentation/SubmittingPatches, i.e. inline instead of as an\nattachment, and with a signed-off-by line etc. We'd also need some tests\nfor this.\n"},{"id":"344595","messageId":"20180413094314.GA2404@bod","threadId":"48248","inReplyTo":"87in90zq2a.fsf@evledraar.gmail.com","subject":"Re: [RFC PATCH] Add \"git show --follow-symlinks HEAD:symlink\"","fromName":"Michael Vogt","fromEmail":"mvo@ubuntu.com","sentAt":"2018-04-13T09:43:14Z","receivedAt":"2018-04-13T09:43:23Z","isPatch":true,"sender":{"key":"mvo@ubuntu.com","avatar":"https://gravatar.com/avatar/8c3aed66a64c58eafced3802188a573f5a14143215cfe334e77d3ed4d6948acf?d=mp&s=160"},"body":"Hi Ævar,\n\nthanks for your quick reply!\n\nOn Mon, Apr 09, 2018 at 11:28:45AM +0200, Ævar Arnfjörð Bjarmason wrote:\n> On Mon, Apr 09 2018, Michael Vogt wrote:\n[..]\n> > Subject: [PATCH] support: git show --follow-symlinks HEAD:symlink\n> >\n> > Add support for the `--follow-symlinks` options to git-show. This\n> > allows to write:\n> >\n> >     git show --follow-symlink HEAD:path-a-symlink\n> \n> The patch looks reasonable, but please submit it as described in\n> Documentation/SubmittingPatches, i.e. inline instead of as an\n> attachment, and with a signed-off-by line etc. We'd also need some tests\n> for this.\n\nThanks for the intial reivew. I updated the patch with a test and\ndocumentation for the new option. Happy to merge the test into one of\nthe existing test files, I read t/README and greping around I did not\nfind a place that looked like a good fit. \n\nI added the updated patch as an mutt inline attachment now.\n\nCheers,\n Michael\n\n\nFrom 5a9faa9eff00f316fc654c8e3bc85c3ba56ea659 Mon Sep 17 00:00:00 2001\nFrom: Michael Vogt <mvo@ubuntu.com>\nDate: Mon, 9 Apr 2018 10:38:13 +0200\nSubject: [PATCH] support: git show --follow-symlinks HEAD:symlink\n\nAdd support for the `--follow-symlinks` options to git-show. This\nallows to write:\n\n    git show --follow-symlink HEAD:path-a-symlink\n\nto get the content of the symlinked file.\n\nSigned-off-by: Michael Vogt <mvo@ubuntu.com>\n---\n Documentation/git-show.txt |  6 ++++++\n builtin/log.c              |  7 +++++--\n revision.c                 |  2 ++\n revision.h                 |  1 +\n t/t1800-git-show.sh        | 41 ++++++++++++++++++++++++++++++++++++++\n 5 files changed, 55 insertions(+), 2 deletions(-)\n create mode 100755 t/t1800-git-show.sh\n\ndiff --git a/Documentation/git-show.txt b/Documentation/git-show.txt\nindex e73ef5401..fa751c35d 100644\n--- a/Documentation/git-show.txt\n+++ b/Documentation/git-show.txt\n@@ -39,6 +39,12 @@ OPTIONS\n \tFor a more complete list of ways to spell object names, see\n \t\"SPECIFYING REVISIONS\" section in linkgit:gitrevisions[7].\n \n+--follow-symlinks::\n+\tFollow symlinks inside the repository when requesting objects\n+\twith extended SHA-1 expressions of the form tree-ish:path-in-tree.\n+\tInstead of output about the link itself, provide output about\n+\tthe linked-to object.\n+\n include::pretty-options.txt[]\n \n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 94ee177d5..e92af4fc7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -142,7 +142,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t struct rev_info *rev, struct setup_revision_opt *opt)\n {\n \tstruct userformat_want w;\n-\tint quiet = 0, source = 0, mailmap = 0;\n+\tint quiet = 0, source = 0, mailmap = 0, follow_symlinks = 0;\n \tstatic struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};\n \tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n@@ -162,6 +162,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\tOPT_CALLBACK('L', NULL, &line_cb, \"n,m:file\",\n \t\t\t     N_(\"Process line range n,m in file, counting from 1\"),\n \t\t\t     log_line_range_callback),\n+\t\tOPT_BOOL(0, \"follow-symlinks\", &follow_symlinks,\n+\t\t\t N_(\"follow in-tree symlinks (used when showing file content)\")),\n \t\tOPT_END()\n \t};\n \n@@ -173,9 +175,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t     builtin_log_options, builtin_log_usage,\n \t\t\t     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n-\n \tif (quiet)\n \t\trev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;\n+\tif (follow_symlinks)\n+\t\trev->follow_symlinks = 1;\n \targc = setup_revisions(argc, argv, rev, opt);\n \n \t/* Any arguments at this point are not recognized */\ndiff --git a/revision.c b/revision.c\nindex b42c836d7..4ab22313f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1678,6 +1678,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi\n \n \tif (revarg_opt & REVARG_COMMITTISH)\n \t\tget_sha1_flags |= GET_OID_COMMITTISH;\n+\tif (revs && revs->follow_symlinks)\n+\t\tget_sha1_flags |= GET_OID_FOLLOW_SYMLINKS;\n \n \tif (get_oid_with_context(arg, get_sha1_flags, &oid, &oc))\n \t\treturn revs->ignore_missing ? 0 : -1;\ndiff --git a/revision.h b/revision.h\nindex b8c47b98e..060f1038a 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -122,6 +122,7 @@ struct rev_info {\n \t\t\tfirst_parent_only:1,\n \t\t\tline_level_traverse:1,\n \t\t\ttree_blobs_in_commit_order:1,\n+\t\t\tfollow_symlinks:1,\n \n \t\t\t/* for internal use only */\n \t\t\texclude_promisor_objects:1;\ndiff --git a/t/t1800-git-show.sh b/t/t1800-git-show.sh\nnew file mode 100755\nindex 000000000..86fe8ee02\n--- /dev/null\n+++ b/t/t1800-git-show.sh\n@@ -0,0 +1,41 @@\n+#!/bin/sh\n+\n+test_description='Test git show works'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'verify git show HEAD:foo works' '\n+    echo \"foo content\" > foo &&\n+    git add foo &&\n+    git commit -m \"added foo\" &&\n+    content=$(git show HEAD:foo) &&\n+    test \"$content\" = \"foo content\"\n+'\n+\n+test_expect_success 'verify git show HEAD:symlink shows symlink points to foo' '\n+    echo \"foo content\" > foo &&\n+    ln -s foo symlink &&\n+    git add foo symlink &&\n+    git commit -m \"added foo and a symlink to foo\" &&\n+    content=$(git show HEAD:foo) &&\n+    test \"$content\" = \"foo content\" &&\n+    symlink=$(git show HEAD:symlink) &e& \n+    test \"$symlink\" = \"foo\"\n+'\n+\n+test_expect_success 'verify git show --follow-symlinks HEAD:symlink shows foo' '\n+    content=$(git show --follow-symlinks HEAD:symlink) &&\n+    test \"$content\" = \"foo content\"\n+'\n+\n+test_expect_success 'verify git show --follow-symlinks HEAD:symlink works with subdirs' '\n+    mkdir dir &&\n+    ln -s dir symlink-to-dir &&\n+    echo \"bar content\" > dir/bar &&\n+    git add dir symlink-to-dir &&\n+    git commit -m \"add dir and symlink-to-dir\" &&\n+    content=$(git show --follow-symlinks HEAD:symlink-to-dir/bar) &&\n+    test \"$content\" = \"bar content\"\n+'\n+\n+test_done\n-- \n2.17.0\n\n"},{"id":"344618","messageId":"CAGZ79kZDUnxkKfqRnZiLhweJ4HNO5sSGUfxkEvJPGagV4wmtkg@mail.gmail.com","threadId":"48248","inReplyTo":"20180413094314.GA2404@bod","subject":"Re: [RFC PATCH] Add \"git show --follow-symlinks HEAD:symlink\"","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2018-04-13T17:28:13Z","receivedAt":"2018-04-13T17:28:20Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"Hi Michael,\n\nthanks for the patch,\n\n> Thanks for the intial reivew. I updated the patch with a test and\n> documentation for the new option. Happy to merge the test into one of\n> the existing test files, I read t/README and greping around I did not\n> find a place that looked like a good fit.\n\nI think keeping tests as separate as possible is a good idea.\nLooking at the patch https://public-inbox.org/git/20180413094314.GA2404@bod/\n\nThe patch seems reasonable, apart from minor nits:\nIn the test we'd prefer no whitespace on the right side of the redirection,\ni.e. echo content >foo\n\nInstead of evaluating git commands in shell and assigning it to a variable,\nwe'd prefer to dump it to files:\n\n  git show HEAD:symlink >actual &&\n  echo foo >expect &&\n  test_cmp expect actual\n\n(instead of content=$(git show HEAD:foo) && test $content == ...)\n\nThe reason for this is that the &&-chain will inspect the return code\nof the git command.\n\nThere is a typo &e&.\n\nCan we reword the documentation, such that we do not have\nan occurrence of \"extended SHA-1\" ?\n(By now the Git community came up with a plan to migrate\naway from SHA-1, hence we'd not want to introduce more\ndependencies even in the form of documentation for that)\n\nMaybe\n\nFollow symlinks inside the repository when requesting\nobjects in extended revision syntax of the form tree-ish:path-in-tree.\n\nThanks,\nStefan\n"},{"id":"344621","messageId":"20180413174819.GA19030@bod","threadId":"48248","inReplyTo":"CAGZ79kZDUnxkKfqRnZiLhweJ4HNO5sSGUfxkEvJPGagV4wmtkg@mail.gmail.com","subject":"Re: [RFC PATCH] Add \"git show --follow-symlinks HEAD:symlink\"","fromName":"Michael Vogt","fromEmail":"mvo@ubuntu.com","sentAt":"2018-04-13T17:48:19Z","receivedAt":"2018-04-13T17:48:27Z","isPatch":true,"sender":{"key":"mvo@ubuntu.com","avatar":"https://gravatar.com/avatar/8c3aed66a64c58eafced3802188a573f5a14143215cfe334e77d3ed4d6948acf?d=mp&s=160"},"body":"On Fri, Apr 13, 2018 at 10:28:13AM -0700, Stefan Beller wrote:\n> Hi Michael,\nHi Stefan,\n\n> thanks for the patch,\nThanks for the review.\n\n[..]\n> The patch seems reasonable, apart from minor nits:\n> In the test we'd prefer no whitespace on the right side of the redirection,\n> i.e. echo content >foo\n\nSure, updated.\n\n> Instead of evaluating git commands in shell and assigning it to a variable,\n> we'd prefer to dump it to files:\n[..]\n\nMakes sense, updated.\n\n> There is a typo &e&.\n\nUps, sorry! Fixed.\n\n> Can we reword the documentation, such that we do not have\n> an occurrence of \"extended SHA-1\" ?\n[..]\n> Maybe\n> \n> Follow symlinks inside the repository when requesting\n> objects in extended revision syntax of the form tree-ish:path-in-tree.\n\nThis looks very reasonable, I updated the documentation accordingly.\n\nThe update patch is attached as an inline attachement.\n\nCheers,\n Michael\n\n\nFrom dab10f5e5aea8a31cbee0ab1d5a78204c8c9832a Mon Sep 17 00:00:00 2001\nFrom: Michael Vogt <mvo@ubuntu.com>\nDate: Mon, 9 Apr 2018 10:38:13 +0200\nSubject: [PATCH] support: git show --follow-symlinks HEAD:symlink\n\nAdd support for the `--follow-symlinks` options to git-show. This\nallows to write:\n\n    git show --follow-symlink HEAD:path-a-symlink\n\nto get the content of the symlinked file.\n\nSigned-off-by: Michael Vogt <mvo@ubuntu.com>\n---\n Documentation/git-show.txt |  6 +++++\n builtin/log.c              |  7 ++++--\n revision.c                 |  2 ++\n revision.h                 |  1 +\n t/t1800-git-show.sh        | 46 ++++++++++++++++++++++++++++++++++++++\n 5 files changed, 60 insertions(+), 2 deletions(-)\n create mode 100755 t/t1800-git-show.sh\n\ndiff --git a/Documentation/git-show.txt b/Documentation/git-show.txt\nindex e73ef5401..d9f7fd90c 100644\n--- a/Documentation/git-show.txt\n+++ b/Documentation/git-show.txt\n@@ -39,6 +39,12 @@ OPTIONS\n \tFor a more complete list of ways to spell object names, see\n \t\"SPECIFYING REVISIONS\" section in linkgit:gitrevisions[7].\n \n+--follow-symlinks::\n+\tFollow symlinks inside the repository when requesting objects\n+\tin extended revision syntax of the form tree-ish:path-in-tree.\n+\tInstead of output about the link itself, provide output about\n+\tthe linked-to object.\n+\n include::pretty-options.txt[]\n \n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 94ee177d5..e92af4fc7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -142,7 +142,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t struct rev_info *rev, struct setup_revision_opt *opt)\n {\n \tstruct userformat_want w;\n-\tint quiet = 0, source = 0, mailmap = 0;\n+\tint quiet = 0, source = 0, mailmap = 0, follow_symlinks = 0;\n \tstatic struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};\n \tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n@@ -162,6 +162,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\tOPT_CALLBACK('L', NULL, &line_cb, \"n,m:file\",\n \t\t\t     N_(\"Process line range n,m in file, counting from 1\"),\n \t\t\t     log_line_range_callback),\n+\t\tOPT_BOOL(0, \"follow-symlinks\", &follow_symlinks,\n+\t\t\t N_(\"follow in-tree symlinks (used when showing file content)\")),\n \t\tOPT_END()\n \t};\n \n@@ -173,9 +175,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t     builtin_log_options, builtin_log_usage,\n \t\t\t     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n-\n \tif (quiet)\n \t\trev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;\n+\tif (follow_symlinks)\n+\t\trev->follow_symlinks = 1;\n \targc = setup_revisions(argc, argv, rev, opt);\n \n \t/* Any arguments at this point are not recognized */\ndiff --git a/revision.c b/revision.c\nindex b42c836d7..4ab22313f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1678,6 +1678,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi\n \n \tif (revarg_opt & REVARG_COMMITTISH)\n \t\tget_sha1_flags |= GET_OID_COMMITTISH;\n+\tif (revs && revs->follow_symlinks)\n+\t\tget_sha1_flags |= GET_OID_FOLLOW_SYMLINKS;\n \n \tif (get_oid_with_context(arg, get_sha1_flags, &oid, &oc))\n \t\treturn revs->ignore_missing ? 0 : -1;\ndiff --git a/revision.h b/revision.h\nindex b8c47b98e..060f1038a 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -122,6 +122,7 @@ struct rev_info {\n \t\t\tfirst_parent_only:1,\n \t\t\tline_level_traverse:1,\n \t\t\ttree_blobs_in_commit_order:1,\n+\t\t\tfollow_symlinks:1,\n \n \t\t\t/* for internal use only */\n \t\t\texclude_promisor_objects:1;\ndiff --git a/t/t1800-git-show.sh b/t/t1800-git-show.sh\nnew file mode 100755\nindex 000000000..85541b4db\n--- /dev/null\n+++ b/t/t1800-git-show.sh\n@@ -0,0 +1,46 @@\n+#!/bin/sh\n+\n+test_description='Test git show works'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'verify git show HEAD:foo works' '\n+    printf \"foo content\\n\" >foo &&\n+    git add foo &&\n+    git commit -m \"added foo\" &&\n+    git show HEAD:foo >actual &&\n+    printf \"foo content\\n\" >expected &&\n+    test_cmp expected actual\n+'\n+\n+test_expect_success 'verify git show HEAD:symlink shows symlink points to foo' '\n+    printf \"foo content\\n\" >foo &&\n+    ln -s foo symlink &&\n+    git add foo symlink &&\n+    git commit -m \"added foo and a symlink to foo\" &&\n+    git show HEAD:foo >actual &&\n+    printf \"foo content\\n\" >expected &&\n+    test_cmp expected actual &&\n+    git show HEAD:symlink >actual &&\n+    printf \"foo\" >expected &&\n+    test_cmp expected actual\n+'\n+\n+test_expect_success 'verify git show --follow-symlinks HEAD:symlink shows foo' '\n+    git show --follow-symlinks HEAD:symlink >actual &&\n+    printf \"foo content\\n\" >expected &&\n+    test_cmp expected actual\n+'\n+\n+test_expect_success 'verify git show --follow-symlinks HEAD:symlink works with subdirs' '\n+    mkdir dir &&\n+    ln -s dir symlink-to-dir &&\n+    printf \"bar content\\n\" >dir/bar &&\n+    git add dir symlink-to-dir &&\n+    git commit -m \"add dir and symlink-to-dir\" &&\n+    git show --follow-symlinks HEAD:symlink-to-dir/bar >actual &&\n+    printf \"bar content\\n\" >expected &&\n+    test_cmp expected actual\n+'\n+\n+test_done\n-- \n2.17.0\n\n"},{"id":"344626","messageId":"87h8oegavn.fsf@evledraar.gmail.com","threadId":"48248","inReplyTo":"20180413174819.GA19030@bod","subject":"Re: [RFC PATCH] Add \"git show --follow-symlinks HEAD:symlink\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2018-04-13T19:33:00Z","receivedAt":"2018-04-13T19:33:07Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Apr 13 2018, Michael Vogt wrote:\n\n> The update patch is attached as an inline attachement.\n\nYour patch still just shows up as a straight-up attachment in many\nE-Mail clients. Note the difference between what your patch\n(https://public-inbox.org/git/20180413174819.GA19030@bod/raw) and a\npatch that's not an attachment\n(https://public-inbox.org/git/0f0942043678fe76f8d654306482ee26fac643f0.1523617836.git.johannes.schindelin@gmx.de/raw)\nlook like.\n\nTry to \"wget\" both of those and apply them with \"git am\" on top of\nmaster, and note how what you're doing results in a broken patch.\n\nThis is why Documentation/SubmittingPatches suggests using format-patch\n& send-email. You don't *have* to use those tools, and can use something\nthat's compatible with what's expected on-list, but what you're doing\nisn't that.\n"},{"id":"344628","messageId":"20180413194829.23990-1-mvo@ubuntu.com","threadId":"48248","inReplyTo":"87h8oegavn.fsf@evledraar.gmail.com","subject":"[PATCH] support: git show --follow-symlinks HEAD:symlink","fromName":"Michael Vogt","fromEmail":"mvo@ubuntu.com","sentAt":"2018-04-13T19:48:29Z","receivedAt":"2018-04-13T19:50:50Z","isPatch":true,"sender":{"key":"mvo@ubuntu.com","avatar":"https://gravatar.com/avatar/8c3aed66a64c58eafced3802188a573f5a14143215cfe334e77d3ed4d6948acf?d=mp&s=160"},"body":"Add support for the `--follow-symlinks` options to git-show. This\nallows to write:\n\n    git show --follow-symlink HEAD:path-a-symlink\n\nto get the content of the symlinked file.\n\nSigned-off-by: Michael Vogt <mvo@ubuntu.com>\n---\n Documentation/git-show.txt |  6 +++++\n builtin/log.c              |  7 ++++--\n revision.c                 |  2 ++\n revision.h                 |  1 +\n t/t1800-git-show.sh        | 46 ++++++++++++++++++++++++++++++++++++++\n 5 files changed, 60 insertions(+), 2 deletions(-)\n create mode 100755 t/t1800-git-show.sh\n\ndiff --git a/Documentation/git-show.txt b/Documentation/git-show.txt\nindex e73ef5401..d9f7fd90c 100644\n--- a/Documentation/git-show.txt\n+++ b/Documentation/git-show.txt\n@@ -39,6 +39,12 @@ OPTIONS\n \tFor a more complete list of ways to spell object names, see\n \t\"SPECIFYING REVISIONS\" section in linkgit:gitrevisions[7].\n \n+--follow-symlinks::\n+\tFollow symlinks inside the repository when requesting objects\n+\tin extended revision syntax of the form tree-ish:path-in-tree.\n+\tInstead of output about the link itself, provide output about\n+\tthe linked-to object.\n+\n include::pretty-options.txt[]\n \n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 94ee177d5..e92af4fc7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -142,7 +142,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t struct rev_info *rev, struct setup_revision_opt *opt)\n {\n \tstruct userformat_want w;\n-\tint quiet = 0, source = 0, mailmap = 0;\n+\tint quiet = 0, source = 0, mailmap = 0, follow_symlinks = 0;\n \tstatic struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};\n \tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n@@ -162,6 +162,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\tOPT_CALLBACK('L', NULL, &line_cb, \"n,m:file\",\n \t\t\t     N_(\"Process line range n,m in file, counting from 1\"),\n \t\t\t     log_line_range_callback),\n+\t\tOPT_BOOL(0, \"follow-symlinks\", &follow_symlinks,\n+\t\t\t N_(\"follow in-tree symlinks (used when showing file content)\")),\n \t\tOPT_END()\n \t};\n \n@@ -173,9 +175,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t     builtin_log_options, builtin_log_usage,\n \t\t\t     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n-\n \tif (quiet)\n \t\trev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;\n+\tif (follow_symlinks)\n+\t\trev->follow_symlinks = 1;\n \targc = setup_revisions(argc, argv, rev, opt);\n \n \t/* Any arguments at this point are not recognized */\ndiff --git a/revision.c b/revision.c\nindex b42c836d7..4ab22313f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1678,6 +1678,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi\n \n \tif (revarg_opt & REVARG_COMMITTISH)\n \t\tget_sha1_flags |= GET_OID_COMMITTISH;\n+\tif (revs && revs->follow_symlinks)\n+\t\tget_sha1_flags |= GET_OID_FOLLOW_SYMLINKS;\n \n \tif (get_oid_with_context(arg, get_sha1_flags, &oid, &oc))\n \t\treturn revs->ignore_missing ? 0 : -1;\ndiff --git a/revision.h b/revision.h\nindex b8c47b98e..060f1038a 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -122,6 +122,7 @@ struct rev_info {\n \t\t\tfirst_parent_only:1,\n \t\t\tline_level_traverse:1,\n \t\t\ttree_blobs_in_commit_order:1,\n+\t\t\tfollow_symlinks:1,\n \n \t\t\t/* for internal use only */\n \t\t\texclude_promisor_objects:1;\ndiff --git a/t/t1800-git-show.sh b/t/t1800-git-show.sh\nnew file mode 100755\nindex 000000000..85541b4db\n--- /dev/null\n+++ b/t/t1800-git-show.sh\n@@ -0,0 +1,46 @@\n+#!/bin/sh\n+\n+test_description='Test git show works'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'verify git show HEAD:foo works' '\n+    printf \"foo content\\n\" >foo &&\n+    git add foo &&\n+    git commit -m \"added foo\" &&\n+    git show HEAD:foo >actual &&\n+    printf \"foo content\\n\" >expected &&\n+    test_cmp expected actual\n+'\n+\n+test_expect_success 'verify git show HEAD:symlink shows symlink points to foo' '\n+    printf \"foo content\\n\" >foo &&\n+    ln -s foo symlink &&\n+    git add foo symlink &&\n+    git commit -m \"added foo and a symlink to foo\" &&\n+    git show HEAD:foo >actual &&\n+    printf \"foo content\\n\" >expected &&\n+    test_cmp expected actual &&\n+    git show HEAD:symlink >actual &&\n+    printf \"foo\" >expected &&\n+    test_cmp expected actual\n+'\n+\n+test_expect_success 'verify git show --follow-symlinks HEAD:symlink shows foo' '\n+    git show --follow-symlinks HEAD:symlink >actual &&\n+    printf \"foo content\\n\" >expected &&\n+    test_cmp expected actual\n+'\n+\n+test_expect_success 'verify git show --follow-symlinks HEAD:symlink works with subdirs' '\n+    mkdir dir &&\n+    ln -s dir symlink-to-dir &&\n+    printf \"bar content\\n\" >dir/bar &&\n+    git add dir symlink-to-dir &&\n+    git commit -m \"add dir and symlink-to-dir\" &&\n+    git show --follow-symlinks HEAD:symlink-to-dir/bar >actual &&\n+    printf \"bar content\\n\" >expected &&\n+    test_cmp expected actual\n+'\n+\n+test_done\n-- \n2.17.0\n\n"},{"id":"344629","messageId":"20180413195509.GB19030@bod","threadId":"48248","inReplyTo":"87h8oegavn.fsf@evledraar.gmail.com","subject":"Re: [RFC PATCH] Add \"git show --follow-symlinks HEAD:symlink\"","fromName":"Michael Vogt","fromEmail":"mvo@ubuntu.com","sentAt":"2018-04-13T19:55:09Z","receivedAt":"2018-04-13T19:55:16Z","isPatch":true,"sender":{"key":"mvo@ubuntu.com","avatar":"https://gravatar.com/avatar/8c3aed66a64c58eafced3802188a573f5a14143215cfe334e77d3ed4d6948acf?d=mp&s=160"},"body":"On Fri, Apr 13, 2018 at 09:33:00PM +0200, Ævar Arnfjörð Bjarmason wrote:\n> \n> On Fri, Apr 13 2018, Michael Vogt wrote:\n> \n> > The update patch is attached as an inline attachement.\n> \n> Your patch still just shows up as a straight-up attachment in many\n> E-Mail clients. Note the difference between what your patch\n[..]\n> This is why Documentation/SubmittingPatches suggests using format-patch\n> & send-email. You don't *have* to use those tools, and can use something\n> that's compatible with what's expected on-list, but what you're doing\n> isn't that.\n\nMy apologizes, I resend it using \"git send-email\".\n\nCheers,\n Michael\n"},{"id":"344638","messageId":"87fu3yg6od.fsf@evledraar.gmail.com","threadId":"48248","inReplyTo":"20180413194829.23990-1-mvo@ubuntu.com","subject":"Re: [PATCH] support: git show --follow-symlinks HEAD:symlink","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2018-04-13T21:03:46Z","receivedAt":"2018-04-13T21:03:55Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Apr 13 2018, Michael Vogt wrote:\n\n> Add support for the `--follow-symlinks` options to git-show. This\n> allows to write:\n>\n>     git show --follow-symlink HEAD:path-a-symlink\n>\n> to get the content of the symlinked file.\n\nThanks. Commit message would be better as something like:\n\n    show: add --follow-symlinks option for <rev>:<path>\n\n    Add a --follow-symlinks option that'll resolve symlinks to their\n    targets when the target is of the form <rev>:<path>.\n\n    Without it, git will show the path of the link itself if the symlink\n    is the leaf node of <path>, or otherwise an error if some component\n    of <path> is a symlink to another location in the repository. With\n    the new --follow-symlinks option both will be resolved to their\n    target, and its content shown instead.\n\nI.e. start with \"<command>: \" (\"show\" in this case), and explain how it\nimpacts the dirlink case.\n\n> Signed-off-by: Michael Vogt <mvo@ubuntu.com>\n> ---\n>  Documentation/git-show.txt |  6 +++++\n>  builtin/log.c              |  7 ++++--\n>  revision.c                 |  2 ++\n>  revision.h                 |  1 +\n>  t/t1800-git-show.sh        | 46 ++++++++++++++++++++++++++++++++++++++\n>  5 files changed, 60 insertions(+), 2 deletions(-)\n>  create mode 100755 t/t1800-git-show.sh\n>\n> diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt\n> index e73ef5401..d9f7fd90c 100644\n> --- a/Documentation/git-show.txt\n> +++ b/Documentation/git-show.txt\n> @@ -39,6 +39,12 @@ OPTIONS\n>  \tFor a more complete list of ways to spell object names, see\n>  \t\"SPECIFYING REVISIONS\" section in linkgit:gitrevisions[7].\n>\n> +--follow-symlinks::\n> +\tFollow symlinks inside the repository when requesting objects\n> +\tin extended revision syntax of the form tree-ish:path-in-tree.\n> +\tInstead of output about the link itself, provide output about\n> +\tthe linked-to object.\n> +\n>  include::pretty-options.txt[]\n\nThis needs to document the dirlink case I noted above.\n\n> diff --git a/builtin/log.c b/builtin/log.c\n> index 94ee177d5..e92af4fc7 100644\n> --- a/builtin/log.c\n> +++ b/builtin/log.c\n> @@ -142,7 +142,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n>  \t\t\t struct rev_info *rev, struct setup_revision_opt *opt)\n>  {\n>  \tstruct userformat_want w;\n> -\tint quiet = 0, source = 0, mailmap = 0;\n> +\tint quiet = 0, source = 0, mailmap = 0, follow_symlinks = 0;\n>  \tstatic struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};\n>  \tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n>  \tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n> @@ -162,6 +162,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n>  \t\tOPT_CALLBACK('L', NULL, &line_cb, \"n,m:file\",\n>  \t\t\t     N_(\"Process line range n,m in file, counting from 1\"),\n>  \t\t\t     log_line_range_callback),\n> +\t\tOPT_BOOL(0, \"follow-symlinks\", &follow_symlinks,\n> +\t\t\t N_(\"follow in-tree symlinks (used when showing file content)\")),\n>  \t\tOPT_END()\n>  \t};\n>\n> @@ -173,9 +175,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n>  \t\t\t     builtin_log_options, builtin_log_usage,\n>  \t\t\t     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |\n>  \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n> -\n\nStray line deletion here.\n\n>  \tif (quiet)\n>  \t\trev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;\n> +\tif (follow_symlinks)\n> +\t\trev->follow_symlinks = 1;\n>  \targc = setup_revisions(argc, argv, rev, opt);\n>\n>  \t/* Any arguments at this point are not recognized */\n> diff --git a/revision.c b/revision.c\n> index b42c836d7..4ab22313f 100644\n> --- a/revision.c\n> +++ b/revision.c\n> @@ -1678,6 +1678,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi\n>\n>  \tif (revarg_opt & REVARG_COMMITTISH)\n>  \t\tget_sha1_flags |= GET_OID_COMMITTISH;\n> +\tif (revs && revs->follow_symlinks)\n> +\t\tget_sha1_flags |= GET_OID_FOLLOW_SYMLINKS;\n>\n>  \tif (get_oid_with_context(arg, get_sha1_flags, &oid, &oc))\n>  \t\treturn revs->ignore_missing ? 0 : -1;\n> diff --git a/revision.h b/revision.h\n> index b8c47b98e..060f1038a 100644\n> --- a/revision.h\n> +++ b/revision.h\n> @@ -122,6 +122,7 @@ struct rev_info {\n>  \t\t\tfirst_parent_only:1,\n>  \t\t\tline_level_traverse:1,\n>  \t\t\ttree_blobs_in_commit_order:1,\n> +\t\t\tfollow_symlinks:1,\n>\n>  \t\t\t/* for internal use only */\n>  \t\t\texclude_promisor_objects:1;\n> diff --git a/t/t1800-git-show.sh b/t/t1800-git-show.sh\n> new file mode 100755\n> index 000000000..85541b4db\n> --- /dev/null\n> +++ b/t/t1800-git-show.sh\n> @@ -0,0 +1,46 @@\n> +#!/bin/sh\n> +\n> +test_description='Test git show works'\n> +\n> +. ./test-lib.sh\n> +\n> +test_expect_success 'verify git show HEAD:foo works' '\n> +    printf \"foo content\\n\" >foo &&\n> +    git add foo &&\n> +    git commit -m \"added foo\" &&\n> +    git show HEAD:foo >actual &&\n> +    printf \"foo content\\n\" >expected &&\n> +    test_cmp expected actual\n> +'\n> +\n> +test_expect_success 'verify git show HEAD:symlink shows symlink points to foo' '\n> +    printf \"foo content\\n\" >foo &&\n> +    ln -s foo symlink &&\n> +    git add foo symlink &&\n> +    git commit -m \"added foo and a symlink to foo\" &&\n> +    git show HEAD:foo >actual &&\n> +    printf \"foo content\\n\" >expected &&\n> +    test_cmp expected actual &&\n> +    git show HEAD:symlink >actual &&\n> +    printf \"foo\" >expected &&\n> +    test_cmp expected actual\n> +'\n> +\n> +test_expect_success 'verify git show --follow-symlinks HEAD:symlink shows foo' '\n> +    git show --follow-symlinks HEAD:symlink >actual &&\n> +    printf \"foo content\\n\" >expected &&\n> +    test_cmp expected actual\n> +'\n> +\n> +test_expect_success 'verify git show --follow-symlinks HEAD:symlink works with subdirs' '\n> +    mkdir dir &&\n> +    ln -s dir symlink-to-dir &&\n> +    printf \"bar content\\n\" >dir/bar &&\n> +    git add dir symlink-to-dir &&\n> +    git commit -m \"add dir and symlink-to-dir\" &&\n> +    git show --follow-symlinks HEAD:symlink-to-dir/bar >actual &&\n> +    printf \"bar content\\n\" >expected &&\n> +    test_cmp expected actual\n> +'\n> +\n> +test_done\n\nThere's a few issues with this test code I noticed:\n\n 1) Doesn't indent with tabs\n 2) Doesn't use the test_commit helper, less verbose\n 3) Your 2nd test is just repeating the setup of the 1st test, which is\n    not needed\n 4) You don't test without --follow-symlinks in the dirlink case\n 5) You don't guard with the SYMLINKS prereq (this test will fail on Windows et al)\n 6) printf \"foo\\n\" instead of just \"echo foo\"\n\nBelow is a local fixup for this that I came up with (also for that line\ndeletion above), should be squash-able into a v2.\n\nIt would also be worth testing for the case where we don't have SYMLINKS\nbut *do* clone a repo that has symlinks, but I have no idea what git\ndoes in that case, just copy the file?\n\n builtin/log.c       |  1 +\n t/t1800-git-show.sh | 55 ++++++++++++++++++++++++-----------------------------\n 2 files changed, 26 insertions(+), 30 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 2990f9b1b9..5d920a893a 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -175,6 +175,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t     builtin_log_options, builtin_log_usage,\n \t\t\t     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n+\n \tif (quiet)\n \t\trev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;\n \tif (follow_symlinks)\ndiff --git a/t/t1800-git-show.sh b/t/t1800-git-show.sh\nindex 85541b4db3..7a02438ecf 100755\n--- a/t/t1800-git-show.sh\n+++ b/t/t1800-git-show.sh\n@@ -5,42 +5,37 @@ test_description='Test git show works'\n . ./test-lib.sh\n\n test_expect_success 'verify git show HEAD:foo works' '\n-    printf \"foo content\\n\" >foo &&\n-    git add foo &&\n-    git commit -m \"added foo\" &&\n-    git show HEAD:foo >actual &&\n-    printf \"foo content\\n\" >expected &&\n-    test_cmp expected actual\n+\ttest_commit A &&\n+\tgit show HEAD:A.t >actual &&\n+\techo A >expected &&\n+\ttest_cmp expected actual\n '\n\n-test_expect_success 'verify git show HEAD:symlink shows symlink points to foo' '\n-    printf \"foo content\\n\" >foo &&\n-    ln -s foo symlink &&\n-    git add foo symlink &&\n-    git commit -m \"added foo and a symlink to foo\" &&\n-    git show HEAD:foo >actual &&\n-    printf \"foo content\\n\" >expected &&\n-    test_cmp expected actual &&\n-    git show HEAD:symlink >actual &&\n-    printf \"foo\" >expected &&\n-    test_cmp expected actual\n+test_expect_success SYMLINKS 'verify git show HEAD:symlink shows symlink points to foo' '\n+\tln -s A.t A.link &&\n+\tgit add A.link &&\n+\tgit commit -m\"Added symlink to A.t\" &&\n+\tgit show HEAD:A.link >actual &&\n+\tprintf \"%s\" A.t >expected &&\n+\ttest_cmp expected actual\n '\n\n-test_expect_success 'verify git show --follow-symlinks HEAD:symlink shows foo' '\n-    git show --follow-symlinks HEAD:symlink >actual &&\n-    printf \"foo content\\n\" >expected &&\n-    test_cmp expected actual\n+test_expect_success SYMLINKS 'verify git show --follow-symlinks HEAD:symlink shows foo' '\n+\tgit show --follow-symlinks HEAD:A.link >actual &&\n+\techo A >expected &&\n+\ttest_cmp expected actual\n '\n\n-test_expect_success 'verify git show --follow-symlinks HEAD:symlink works with subdirs' '\n-    mkdir dir &&\n-    ln -s dir symlink-to-dir &&\n-    printf \"bar content\\n\" >dir/bar &&\n-    git add dir symlink-to-dir &&\n-    git commit -m \"add dir and symlink-to-dir\" &&\n-    git show --follow-symlinks HEAD:symlink-to-dir/bar >actual &&\n-    printf \"bar content\\n\" >expected &&\n-    test_cmp expected actual\n+test_expect_success SYMLINKS 'verify git show --follow-symlinks HEAD:symlink works with subdirs' '\n+\tmkdir dir &&\n+\tln -s dir symlink-to-dir &&\n+\ttest_commit dir/B &&\n+\tgit add dir symlink-to-dir &&\n+\tgit commit -m \"add dir and symlink-to-dir\" &&\n+\ttest_must_fail git show HEAD:symlink-to-dir/B.t >actual &&\n+\tgit show --follow-symlinks HEAD:symlink-to-dir/B.t >actual &&\n+\techo dir/B >expected &&\n+\ttest_cmp expected actual\n '\n\n test_done\n"},{"id":"344779","messageId":"20180416093625.15752-1-mvo@ubuntu.com","threadId":"48248","inReplyTo":"87fu3yg6od.fsf@evledraar.gmail.com","subject":"[PATCH v2] show: add --follow-symlinks option for <rev>:<path>","fromName":"Michael Vogt","fromEmail":"mvo@ubuntu.com","sentAt":"2018-04-16T09:36:24Z","receivedAt":"2018-04-16T09:39:22Z","isPatch":true,"sender":{"key":"mvo@ubuntu.com","avatar":"https://gravatar.com/avatar/8c3aed66a64c58eafced3802188a573f5a14143215cfe334e77d3ed4d6948acf?d=mp&s=160"},"body":"Updated version of the `git show --follow-symlink` patch. This version\nincludes the feedback from Ævar Arnfjörð Bjarmason and Stefan Beller:\n\n- commit message updated\n- test fixes merged from Ævar (thanks!)\n- Documentation/git-show.txt clarified\n\nIt does not include a test for --follow-symlinks in the dirlink case\nwhen a file is behind a dirlink symlink. This this currently fails with\na non-descriptive error message. I hope to find time to improve this\nerror message at some point and then a test for this will be added.\n\nIt also does not include a test for a repo with symlinks when running\non a system without SYMLINKS. I don't have access to such a system,\nsorry.\n\n\n\n"},{"id":"344780","messageId":"20180416093625.15752-2-mvo@ubuntu.com","threadId":"48248","inReplyTo":"20180416093625.15752-1-mvo@ubuntu.com","subject":"[PATCH] show: add --follow-symlinks option for <rev>:<path>","fromName":"Michael Vogt","fromEmail":"mvo@ubuntu.com","sentAt":"2018-04-16T09:36:25Z","receivedAt":"2018-04-16T09:41:32Z","isPatch":true,"sender":{"key":"mvo@ubuntu.com","avatar":"https://gravatar.com/avatar/8c3aed66a64c58eafced3802188a573f5a14143215cfe334e77d3ed4d6948acf?d=mp&s=160"},"body":"Add a --follow-symlinks option that'll resolve symlinks to their\ntargets when the target is of the form <rev>:<path>.\n\nWithout it, git will show the path of the link itself if the symlink\nis the leaf node of <path>, or otherwise an error if some component\nof <path> is a symlink to another location in the repository. With\nthe new --follow-symlinks option both will be resolved to their\ntarget, and its content shown instead.\n\nSigned-off-by: Michael Vogt <mvo@ubuntu.com>\n---\n Documentation/git-show.txt |  7 +++++++\n builtin/log.c              |  6 +++++-\n revision.c                 |  2 ++\n revision.h                 |  1 +\n t/t1800-git-show.sh        | 41 ++++++++++++++++++++++++++++++++++++++\n 5 files changed, 56 insertions(+), 1 deletion(-)\n create mode 100755 t/t1800-git-show.sh\n\ndiff --git a/Documentation/git-show.txt b/Documentation/git-show.txt\nindex e73ef5401..e2634b27e 100644\n--- a/Documentation/git-show.txt\n+++ b/Documentation/git-show.txt\n@@ -39,6 +39,13 @@ OPTIONS\n \tFor a more complete list of ways to spell object names, see\n \t\"SPECIFYING REVISIONS\" section in linkgit:gitrevisions[7].\n \n+--follow-symlinks::\n+\tFollow symlinks inside the repository when requesting objects\n+\tin extended revision syntax of the form tree-ish:path-in-tree.\n+\tIt will resolve any symlinks in <path-in-tree> and shows the\n+\tcontent\tof the link if the symlink is the leaf node of\n+\t<path-in-tree>.\n+\n include::pretty-options.txt[]\n \n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 94ee177d5..7d815b8ea 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -142,7 +142,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t struct rev_info *rev, struct setup_revision_opt *opt)\n {\n \tstruct userformat_want w;\n-\tint quiet = 0, source = 0, mailmap = 0;\n+\tint quiet = 0, source = 0, mailmap = 0, follow_symlinks = 0;\n \tstatic struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};\n \tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n@@ -162,6 +162,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\tOPT_CALLBACK('L', NULL, &line_cb, \"n,m:file\",\n \t\t\t     N_(\"Process line range n,m in file, counting from 1\"),\n \t\t\t     log_line_range_callback),\n+\t\tOPT_BOOL(0, \"follow-symlinks\", &follow_symlinks,\n+\t\t\t N_(\"follow in-tree symlinks (used when showing file content)\")),\n \t\tOPT_END()\n \t};\n \n@@ -176,6 +178,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \n \tif (quiet)\n \t\trev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;\n+\tif (follow_symlinks)\n+\t\trev->follow_symlinks = 1;\n \targc = setup_revisions(argc, argv, rev, opt);\n \n \t/* Any arguments at this point are not recognized */\ndiff --git a/revision.c b/revision.c\nindex b42c836d7..4ab22313f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1678,6 +1678,8 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi\n \n \tif (revarg_opt & REVARG_COMMITTISH)\n \t\tget_sha1_flags |= GET_OID_COMMITTISH;\n+\tif (revs && revs->follow_symlinks)\n+\t\tget_sha1_flags |= GET_OID_FOLLOW_SYMLINKS;\n \n \tif (get_oid_with_context(arg, get_sha1_flags, &oid, &oc))\n \t\treturn revs->ignore_missing ? 0 : -1;\ndiff --git a/revision.h b/revision.h\nindex b8c47b98e..060f1038a 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -122,6 +122,7 @@ struct rev_info {\n \t\t\tfirst_parent_only:1,\n \t\t\tline_level_traverse:1,\n \t\t\ttree_blobs_in_commit_order:1,\n+\t\t\tfollow_symlinks:1,\n \n \t\t\t/* for internal use only */\n \t\t\texclude_promisor_objects:1;\ndiff --git a/t/t1800-git-show.sh b/t/t1800-git-show.sh\nnew file mode 100755\nindex 000000000..7a02438ec\n--- /dev/null\n+++ b/t/t1800-git-show.sh\n@@ -0,0 +1,41 @@\n+#!/bin/sh\n+\n+test_description='Test git show works'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'verify git show HEAD:foo works' '\n+\ttest_commit A &&\n+\tgit show HEAD:A.t >actual &&\n+\techo A >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success SYMLINKS 'verify git show HEAD:symlink shows symlink points to foo' '\n+\tln -s A.t A.link &&\n+\tgit add A.link &&\n+\tgit commit -m\"Added symlink to A.t\" &&\n+\tgit show HEAD:A.link >actual &&\n+\tprintf \"%s\" A.t >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success SYMLINKS 'verify git show --follow-symlinks HEAD:symlink shows foo' '\n+\tgit show --follow-symlinks HEAD:A.link >actual &&\n+\techo A >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success SYMLINKS 'verify git show --follow-symlinks HEAD:symlink works with subdirs' '\n+\tmkdir dir &&\n+\tln -s dir symlink-to-dir &&\n+\ttest_commit dir/B &&\n+\tgit add dir symlink-to-dir &&\n+\tgit commit -m \"add dir and symlink-to-dir\" &&\n+\ttest_must_fail git show HEAD:symlink-to-dir/B.t >actual &&\n+\tgit show --follow-symlinks HEAD:symlink-to-dir/B.t >actual &&\n+\techo dir/B >expected &&\n+\ttest_cmp expected actual\n+'\n+\n+test_done\n-- \n2.17.0\n\n"},{"id":"344846","messageId":"xmqqin8qwy4z.fsf@gitster-ct.c.googlers.com","threadId":"48248","inReplyTo":"20180416093625.15752-2-mvo@ubuntu.com","subject":"Re: [PATCH] show: add --follow-symlinks option for <rev>:<path>","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-04-16T23:05:16Z","receivedAt":"2018-04-16T23:05:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael Vogt <mvo@ubuntu.com> writes:\n\n> Add a --follow-symlinks option that'll resolve symlinks to their\n> targets when the target is of the form <rev>:<path>.\n\nThis not only affects \"show\" but all in the \"log\" family of\ncommands, because the change is made to revision.[ch] that is shared\nby them.  I doubt that is desirable.\n\nI offhand do not think of any command other than \"show\", to which\nthis feature makes any sense [*1*].  And I certainly do not mind if\nthe feature is limited to \"show\" and nothing else for that reason.\n\nBut I do mind the implementation that seeps through to other\ncommands (because \"log_init_finish()\" is shared with commands in the\nfamily other than \"show\", and because \"struct rev_info\" is shared\nacross all the commands in the \"log\" famil) and not limited to\n\"show\", which is a sign of typical end-user confusion waiting to\nhappen.\n\nThanks.\n\n\n[Footnote]\n\nFor example, \"git log\" is affected by this patch but I am not sure\nwhat it even means that we can ask this question:\n\n\t$ git log -p --follow-symlinks -- RelNotes\n\nCan we see how each update to Documentation/RelNotes/2.17.0.txt as\nwell as change of RelNotes symlink from 2.17.0.txt to 2.18.0.txt in\nthe patch form?  If that were the case, it might make some sense to\nallow the feature to be triggered by \"git log\" like your change to\nbuiltin/log.c did, but I somehow do not think that is what your\npatch does.\n\n"}]}