{"thread":{"id":"2923","subject":"[PATCH] ls-tree: chomp leading directories when run from a subdirectory","startedAt":"2005-12-24T09:44:59Z","lastAt":"2005-12-24T09:44:59Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"14000","messageId":"7voe36u8v8.fsf@assigned-by-dhcp.cox.net","threadId":"2923","inReplyTo":null,"subject":"[PATCH] ls-tree: chomp leading directories when run from a subdirectory","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-24T09:44:59Z","receivedAt":"2005-12-24T09:44:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When run from a subdirectory, even though we filtered the output\nbased on where we were using pathspec, we wrote out the\nrepository relative paths, not subtree relative paths.  This\nchanges things so that it shows only the current subdirectory\nrelative paths.\n\nFor example, in Documentation subdirectory of git itself, this\nused to be the case:\n\n    $ git-ls-tree --name-only HEAD | grep how\n    Documentation/git-show-branch.txt\n    Documentation/git-show-index.txt\n    Documentation/howto-index.sh\n    Documentation/howto\n\nBut now it does this instead:\n\n    $ git-ls-tree --name-only HEAD | grep how\n    git-show-branch.txt\n    git-show-index.txt\n    howto-index.sh\n    howto\n\nThere are two things to keep in mind.\n\n1. This shows nothing.\n\n   $ git-ls-tree --name-only HEAD ../ppc/\n\n   This is to make things consistent with ls-files, which\n   refuses relative path that goes uplevel.\n\n2. These show things in full repository relative paths.  In this\n   case, paths outside the current subdirectory are also shown.\n\n   $ git-ls-tree --name-only --full-name HEAD | grep how\n   Documentation/git-show-branch.txt\n   Documentation/git-show-index.txt\n   Documentation/howto-index.sh\n   Documentation/howto\n\n   $ git-ls-tree --name-only --full-name HEAD ../ppc/\n   ppc/sha1.c\n   ppc/sha1.h\n   ppc/sha1ppc.S\n\nThe flag --full-name gives the same behaviour as 1.0, so it\nought to be the default if we really care about the backward\ncompatibility, but in practice no Porcelain runs ls-tree from a\nsubdirectory yet, and without --full-name is more human\nfriendly, so hopefully the default being not --full-name would\nbe acceptable.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n * This should be the same as what Linus did earlier, only that\n   I lost the patch X-<.  My vague recollection says that that\n   one did not have --full-name to match what ls-files does,\n   though.\n\n   Obviously the \"'checkout [--|tree] path' from subdirectory\"\n   patch needs to pass --full-name to ls-tree if we are going to\n   do this.\n\n ls-tree.c |   22 ++++++++++++++++++----\n 1 files changed, 18 insertions(+), 4 deletions(-)\n\na69dd585fca9ab7fc4a07f7563f6cdb106e3ffed\ndiff --git a/ls-tree.c b/ls-tree.c\nindex dae377d..d585b6f 100644\n--- a/ls-tree.c\n+++ b/ls-tree.c\n@@ -15,9 +15,11 @@ static int line_termination = '\\n';\n #define LS_NAME_ONLY 8\n static int ls_options = 0;\n const char **pathspec;\n+static int chomp_prefix = 0;\n+static const char *prefix;\n \n static const char ls_tree_usage[] =\n-\t\"git-ls-tree [-d] [-r] [-t] [-z] [--name-only] [--name-status] <tree-ish> [path...]\";\n+\t\"git-ls-tree [-d] [-r] [-t] [-z] [--name-only] [--name-status] [--full-name] <tree-ish> [path...]\";\n \n static int show_recursive(const char *base, int baselen, const char *pathname)\n {\n@@ -49,7 +51,8 @@ static int show_recursive(const char *ba\n \t}\n }\n \n-static int show_tree(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)\n+static int show_tree(unsigned char *sha1, const char *base, int baselen,\n+\t\t     const char *pathname, unsigned mode, int stage)\n {\n \tint retval = 0;\n \tconst char *type = \"blob\";\n@@ -65,21 +68,28 @@ static int show_tree(unsigned char *sha1\n \telse if (ls_options & LS_TREE_ONLY)\n \t\treturn 0;\n \n+\tif (chomp_prefix &&\n+\t    (baselen < chomp_prefix || memcmp(prefix, base, chomp_prefix)))\n+\t\treturn 0;\n+\n \tif (!(ls_options & LS_NAME_ONLY))\n \t\tprintf(\"%06o %s %s\\t\", mode, type, sha1_to_hex(sha1));\n-\twrite_name_quoted(base, baselen, pathname, line_termination, stdout);\n+\twrite_name_quoted(base + chomp_prefix, baselen - chomp_prefix,\n+\t\t\t  pathname,\n+\t\t\t  line_termination, stdout);\n \tputchar(line_termination);\n \treturn retval;\n }\n \n int main(int argc, const char **argv)\n {\n-\tconst char *prefix;\n \tunsigned char sha1[20];\n \tchar *buf;\n \tunsigned long size;\n \n \tprefix = setup_git_directory();\n+\tif (prefix && *prefix)\n+\t\tchomp_prefix = strlen(prefix);\n \twhile (1 < argc && argv[1][0] == '-') {\n \t\tswitch (argv[1][1]) {\n \t\tcase 'z':\n@@ -100,6 +110,10 @@ int main(int argc, const char **argv)\n \t\t\t\tls_options |= LS_NAME_ONLY;\n \t\t\t\tbreak;\n \t\t\t}\n+\t\t\tif (!strcmp(argv[1]+2, \"full-name\")) {\n+\t\t\t\tchomp_prefix = 0;\n+\t\t\t\tbreak;\n+\t\t\t}\n \t\t\t/* otherwise fallthru */\n \t\tdefault:\n \t\t\tusage(ls_tree_usage);\n-- \n1.0.GIT\n"}]}