{"thread":{"id":"776","subject":"Re: [PATCH] allow pathspec to end with a slash","startedAt":"2005-05-31T15:32:15Z","lastAt":"2005-06-01T03:51:18Z","messageCount":12,"participants":["Linus Torvalds","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"4307","messageId":"Pine.LNX.4.58.0505310827330.1876@ppc970.osdl.org","threadId":"776","inReplyTo":null,"subject":"Re: [PATCH] allow pathspec to end with a slash","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-05-31T15:32:15Z","receivedAt":"2005-05-31T15:32:15Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nJunio, \n pathspec is still subtly broken.\n\nJust removing the slash at the end is not the right thing to do, since \nthat means that\n\n\tgit-diff-files drivers/char/\n\nwill trigger on a _file_ \"drivers/char\", even though the spec makes it \nunambiguous that the user only wants to see stuff under that directory.\n\nAgain, git-diff-tree gets this right (not to say that it always did - I\nhad to fix \"interesting()\" several times, exactly because it's not that \nsimple).\n\n\t\tLinus\n"},{"id":"4317","messageId":"7vll5vxinu.fsf@assigned-by-dhcp.cox.net","threadId":"776","inReplyTo":"Pine.LNX.4.58.0505310827330.1876@ppc970.osdl.org","subject":"Re: [PATCH] allow pathspec to end with a slash","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-31T20:08:37Z","receivedAt":"2005-05-31T20:08:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Do you want the same for git-ls-tree as well?  That is, when\nyou have drivers/char as a blob in the tree, should\n\n\tgit-ls-tree $tree drivers/char/\n\nshow nothing?\n\n\n"},{"id":"4321","messageId":"7vbr6rxe36.fsf@assigned-by-dhcp.cox.net","threadId":"776","inReplyTo":"Pine.LNX.4.58.0505310827330.1876@ppc970.osdl.org","subject":"[PATCH 1/2] diff: consolidate test helper script pieces.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-31T21:47:25Z","receivedAt":"2005-05-31T21:47:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"There were duplicate script pieces to help comparing diff\noutput, which this patch consolidates into the t/diff-lib.sh\nlibrary.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n*** The next one is to fix the pathspec, whose test relies on\n*** this cleanup.\n\n t/diff-lib.sh                 |   35 +++++++++++++++++++++++++++++++++++\n t/t4003-diff-rename-1.sh      |    9 +--------\n t/t4005-diff-rename-2.sh      |   23 +----------------------\n t/t4007-rename-3.sh           |   15 +--------------\n t/t4008-diff-break-rewrite.sh |   15 +--------------\n t/t4009-diff-rename-4.sh      |   29 ++++-------------------------\n 6 files changed, 43 insertions(+), 83 deletions(-)\n\ndiff --git a/t/diff-lib.sh b/t/diff-lib.sh\nnew file mode 100644\n--- /dev/null\n+++ b/t/diff-lib.sh\n@@ -0,0 +1,35 @@\n+:\n+\n+_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'\n+_x40=\"$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40\"\n+sanitize_diff_raw='/^:/s/ '\"$_x40\"' '\"$_x40\"' \\([A-Z]\\)[0-9]*\t/ X X \\1#\t/'\n+compare_diff_raw () {\n+    # When heuristics are improved, the score numbers would change.\n+    # Ignore them while comparing.\n+    # Also we do not check SHA1 hash generation in this test, which\n+    # is a job for t0000-basic.sh\n+\n+    sed -e \"$sanitize_diff_raw\" <\"$1\" >.tmp-1\n+    sed -e \"$sanitize_diff_raw\" <\"$2\" >.tmp-2\n+    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n+}\n+\n+sanitize_diff_raw_z='/^:/s/ '\"$_x40\"' '\"$_x40\"' \\([A-Z]\\)[0-9]*$/ X X \\1#/'\n+compare_diff_raw_z () {\n+    # When heuristics are improved, the score numbers would change.\n+    # Ignore them while comparing.\n+    # Also we do not check SHA1 hash generation in this test, which\n+    # is a job for t0000-basic.sh\n+\n+    tr '\\0' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n+    tr '\\0' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n+    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n+}\n+\n+compare_diff_patch () {\n+    # When heuristics are improved, the score numbers would change.\n+    # Ignore them while comparing.\n+    sed -e '/^[dis]*imilarity index [0-9]*%$/d' <\"$1\" >.tmp-1\n+    sed -e '/^[dis]*imilarity index [0-9]*%$/d' <\"$2\" >.tmp-2\n+    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n+}\ndiff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh\n--- a/t/t4003-diff-rename-1.sh\n+++ b/t/t4003-diff-rename-1.sh\n@@ -7,14 +7,7 @@ test_description='More rename detection\n \n '\n . ./test-lib.sh\n-\n-compare_diff_patch () {\n-    # When heuristics are improved, the score numbers would change.\n-    # Ignore them while comparing.\n-    sed -e '/^similarity index [0-9]*%$/d' <\"$1\" >.tmp-1\n-    sed -e '/^similarity index [0-9]*%$/d' <\"$2\" >.tmp-2\n-    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n-}\n+. ../diff-lib.sh ;# test-lib chdir's into trash\n \n test_expect_success \\\n     'prepare reference tree' \\\ndiff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh\n--- a/t/t4005-diff-rename-2.sh\n+++ b/t/t4005-diff-rename-2.sh\n@@ -7,28 +7,7 @@ test_description='Same rename detection \n \n '\n . ./test-lib.sh\n-\n-_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'\n-_x40=\"$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40\"\n-sanitize_diff_raw='s/ '\"$_x40\"' '\"$_x40\"' \\([A-Z]\\)[0-9]*\t/ X X \\1#\t/'\n-compare_diff_raw () {\n-    # When heuristics are improved, the score numbers would change.\n-    # Ignore them while comparing.\n-    # Also we do not check SHA1 hash generation in this test, which\n-    # is a job for t0000-basic.sh\n-\n-    sed -e \"$sanitize_diff_raw\" <\"$1\" >.tmp-1\n-    sed -e \"$sanitize_diff_raw\" <\"$2\" >.tmp-2\n-    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n-}\n-\n-compare_diff_patch () {\n-    # When heuristics are improved, the score numbers would change.\n-    # Ignore them while comparing.\n-    sed -e '/^similarity index [0-9]*%$/d' <\"$1\" >.tmp-1\n-    sed -e '/^similarity index [0-9]*%$/d' <\"$2\" >.tmp-2\n-    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n-}\n+. ../diff-lib.sh ;# test-lib chdir's into trash\n \n test_expect_success \\\n     'prepare reference tree' \\\ndiff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh\n--- a/t/t4007-rename-3.sh\n+++ b/t/t4007-rename-3.sh\n@@ -7,20 +7,7 @@ test_description='Rename interaction wit\n \n '\n . ./test-lib.sh\n-\n-_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'\n-_x40=\"$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40\"\n-sanitize_diff_raw='s/ '\"$_x40\"' '\"$_x40\"' \\([A-Z]\\)[0-9]*\t/ X X \\1#\t/'\n-compare_diff_raw () {\n-    # When heuristics are improved, the score numbers would change.\n-    # Ignore them while comparing.\n-    # Also we do not check SHA1 hash generation in this test, which\n-    # is a job for t0000-basic.sh\n-\n-    sed -e \"$sanitize_diff_raw\" <\"$1\" >.tmp-1\n-    sed -e \"$sanitize_diff_raw\" <\"$2\" >.tmp-2\n-    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n-}\n+. ../diff-lib.sh ;# test-lib chdir's into trash\n \n test_expect_success \\\n     'prepare reference tree' \\\ndiff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh\n--- a/t/t4008-diff-break-rewrite.sh\n+++ b/t/t4008-diff-break-rewrite.sh\n@@ -22,20 +22,7 @@ four changes in total.\n Further, with -B and -M together, these should turn into two renames.\n '\n . ./test-lib.sh\n-\n-_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'\n-_x40=\"$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40\"\n-sanitize_diff_raw='s/ '\"$_x40\"' '\"$_x40\"' \\([CDNR]\\)[0-9]*\t/ X X \\1#\t/'\n-compare_diff_raw () {\n-    # When heuristics are improved, the score numbers would change.\n-    # Ignore them while comparing.\n-    # Also we do not check SHA1 hash generation in this test, which\n-    # is a job for t0000-basic.sh\n-\n-    sed -e \"$sanitize_diff_raw\" <\"$1\" >.tmp-1\n-    sed -e \"$sanitize_diff_raw\" <\"$2\" >.tmp-2\n-    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n-}\n+. ../diff-lib.sh ;# test-lib chdir's into trash\n \n test_expect_success \\\n     setup \\\ndiff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh\n--- a/t/t4009-diff-rename-4.sh\n+++ b/t/t4009-diff-rename-4.sh\n@@ -7,28 +7,7 @@ test_description='Same rename detection \n \n '\n . ./test-lib.sh\n-\n-_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'\n-_x40=\"$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40\"\n-sanitize_diff_raw='/^:/s/ '\"$_x40\"' '\"$_x40\"' \\([A-Z]\\)[0-9]*$/ X X \\1#/'\n-compare_diff_raw () {\n-    # When heuristics are improved, the score numbers would change.\n-    # Ignore them while comparing.\n-    # Also we do not check SHA1 hash generation in this test, which\n-    # is a job for t0000-basic.sh\n-\n-    tr '\\0' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw\" >.tmp-1\n-    tr '\\0' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw\" >.tmp-2\n-    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n-}\n-\n-compare_diff_patch () {\n-    # When heuristics are improved, the score numbers would change.\n-    # Ignore them while comparing.\n-    sed -e '/^similarity index [0-9]*%$/d' <\"$1\" >.tmp-1\n-    sed -e '/^similarity index [0-9]*%$/d' <\"$2\" >.tmp-2\n-    diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n-}\n+. ../diff-lib.sh ;# test-lib chdir's into trash\n \n test_expect_success \\\n     'prepare reference tree' \\\n@@ -63,7 +42,7 @@ EOF\n \n test_expect_success \\\n     'validate output from rename/copy detection (#1)' \\\n-    'compare_diff_raw current expected'\n+    'compare_diff_raw_z current expected'\n \n # make sure diff-helper can grok it.\n mv current diff-raw\n@@ -120,7 +99,7 @@ EOF\n \n test_expect_success \\\n     'validate output from rename/copy detection (#2)' \\\n-    'compare_diff_raw current expected'\n+    'compare_diff_raw_z current expected'\n \n # make sure diff-helper can grok it.\n mv current diff-raw\n@@ -173,7 +152,7 @@ EOF\n \n test_expect_success \\\n     'validate output from rename/copy detection (#3)' \\\n-    'compare_diff_raw current expected'\n+    'compare_diff_raw_z current expected'\n \n # make sure diff-helper can grok it.\n mv current diff-raw\n------------\n\n"},{"id":"4324","messageId":"7v64wzxe25.fsf@assigned-by-dhcp.cox.net","threadId":"776","inReplyTo":"Pine.LNX.4.58.0505310827330.1876@ppc970.osdl.org","subject":"[PATCH 2/2] diff: Fix trailing slash handling.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-31T21:48:02Z","receivedAt":"2005-05-31T21:48:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When limiting the world to \"drivers/char/\", we should not\nconsider \"drivers/char\" which is not a directory.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n t/t4010-diff-pathspec.sh |   65 ++++++++++++++++++++++++++++++++++++++++++++++\n diffcore-pathspec.c      |   60 +++++++++++++++++++++++++++++++++++++------\n 2 files changed, 117 insertions(+), 8 deletions(-)\n\ndiff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh\nnew file mode 100644\n--- /dev/null\n+++ b/t/t4010-diff-pathspec.sh\n@@ -0,0 +1,65 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005 Junio C Hamano\n+#\n+\n+test_description='Pathspec restrictions\n+\n+Prepare:\n+        file0\n+        path1/file1\n+'\n+. ./test-lib.sh\n+. ../diff-lib.sh ;# test-lib chdir's into trash\n+\n+test_expect_success \\\n+    setup \\\n+    'echo frotz >file0 &&\n+     mkdir path1 &&\n+     echo rezrov >path1/file1 &&\n+     git-update-cache --add file0 path1/file1 &&\n+     tree=`git-write-tree` &&\n+     echo \"$tree\" &&\n+     echo nitfol >file0 &&\n+     echo yomin >path1/file1 &&\n+     git-update-cache file0 path1/file1' \n+\n+cat >expected <<\\EOF\n+EOF\n+test_expect_success \\\n+    'limit to path should show nothing' \\\n+    'git-diff-cache --cached $tree path >current &&\n+     compare_diff_raw current expected'\n+\n+cat >expected <<\\EOF\n+:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M\tpath1/file1\n+EOF\n+test_expect_success \\\n+    'limit to path1 should show path1/file1' \\\n+    'git-diff-cache --cached $tree path1 >current &&\n+     compare_diff_raw current expected'\n+\n+cat >expected <<\\EOF\n+:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M\tpath1/file1\n+EOF\n+test_expect_success \\\n+    'limit to path1/ should show path1/file1' \\\n+    'git-diff-cache --cached $tree path1/ >current &&\n+     compare_diff_raw current expected'\n+\n+cat >expected <<\\EOF\n+:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M\tfile0\n+EOF\n+test_expect_success \\\n+    'limit to file0 should show file0' \\\n+    'git-diff-cache --cached $tree file0 >current &&\n+     compare_diff_raw current expected'\n+\n+cat >expected <<\\EOF\n+EOF\n+test_expect_success \\\n+    'limit to file0/ should emit nothing.' \\\n+    'git-diff-cache --cached $tree file0/ >current &&\n+     compare_diff_raw current expected'\n+\n+test_done\ndiff --git a/diffcore-pathspec.c b/diffcore-pathspec.c\n--- a/diffcore-pathspec.c\n+++ b/diffcore-pathspec.c\n@@ -8,9 +8,13 @@\n struct path_spec {\n \tconst char *spec;\n \tint len;\n+\tint reject_non_tree;\n };\n \n-static int matches_pathspec(const char *name, struct path_spec *s, int cnt)\n+static int matches_pathspec(const char *name,\n+\t\t\t    int obviously_non_tree,\n+\t\t\t    struct path_spec *s,\n+\t\t\t    int cnt)\n {\n \tint i;\n \tint namelen;\n@@ -21,10 +25,25 @@ static int matches_pathspec(const char *\n \tnamelen = strlen(name);\n \tfor (i = 0; i < cnt; i++) {\n \t\tint len = s[i].len;\n-\t\tif (! strncmp(s[i].spec, name, len) &&\n-\t\t    len <= namelen &&\n-\t\t    (name[len] == 0 || name[len] == '/'))\n-\t\t\treturn 1;\n+\t\tif (!strncmp(s[i].spec, name, len)) {\n+\t\t\t/* Leading part matches. */\n+\t\t\tif (len == namelen) {\n+\t\t\t\t/* Exact match: spec \"drivers/char/\"\n+\t\t\t\t * should not match against path\n+\t\t\t\t * \"drivers/char\".\n+\t\t\t\t */\n+\t\t\t\tif (s[i].reject_non_tree && obviously_non_tree)\n+\t\t\t\t\tcontinue;\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\telse if ((len < namelen) && name[len] == '/') {\n+\t\t\t\t/* Spec is leading path */\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\t/* otherwise, it is a false match of spec \"abc\"\n+\t\t\t * against path \"abcdefg\", so we continue.\n+\t\t\t */\n+\t\t}\n \t}\n \treturn 0;\n }\n@@ -47,14 +66,39 @@ void diffcore_pathspec(const char **path\n \t\tint l;\n \t\tspec[i].spec = pathspec[i];\n \t\tl = strlen(pathspec[i]);\n-\t\twhile (l > 0 && pathspec[i][l-1] == '/')\n-\t\t\tl--;\n+\t\tif (l > 0 && pathspec[i][l-1] == '/') {\n+\t\t\tspec[i].reject_non_tree = 1;\n+\t\t\twhile (l > 0 && pathspec[i][l-1] == '/')\n+\t\t\t\tl--;\n+\t\t}\n \t\tspec[i].len = l;\n \t}\n \n \tfor (i = 0; i < q->nr; i++) {\n \t\tstruct diff_filepair *p = q->queue[i];\n-\t\tif (matches_pathspec(p->two->path, spec, speccnt))\n+\t\tint obviously_non_tree;\n+#ifndef DIFF_TREE_CALLS_PATHSPEC\n+\t\t/*\n+\t\t * NOTE: This relies on the current behaviour of\n+\t\t * diff-tree which does not use diffcore-pathspec\n+\t\t * and we would not ever see \"tree\" objects\n+\t\t * in our input.\n+\t\t */\n+\t\tobviously_non_tree = 1;\n+#else\n+\t\tif (DIFF_FILE_VALID(p->two))\n+\t\t\tobviously_non_tree = !S_ISDIR(p->two->mode);\n+\t\telse if (DIFF_FILE_VALID(p->one))\n+\t\t\t/* path is being deleted.  is it a tree? */\n+\t\t\tobviously_non_tree = !S_ISDIR(p->one->mode);\n+\t\telse\n+\t\t\t/* path is unmerged, which comes from cache\n+\t\t\t * so it cannot be a tree\n+\t\t\t */\n+\t\t\tobviously_non_tree = 1;\n+#endif\n+\t\tif (matches_pathspec(p->two->path, obviously_non_tree,\n+\t\t\t\t     spec, speccnt))\n \t\t\tdiff_q(&outq, p);\n \t\telse\n \t\t\tdiff_free_filepair(p);\n------------\n\n"},{"id":"4322","messageId":"7vvf4zvzfw.fsf@assigned-by-dhcp.cox.net","threadId":"776","inReplyTo":"Pine.LNX.4.58.0505310827330.1876@ppc970.osdl.org","subject":"[PATCH] ls-tree: remove trailing slashes properly.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-31T21:49:07Z","receivedAt":"2005-05-31T21:49:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"A typo prevented trailing slashes from being removed properly.\n\nThis fixes the problem that \"drivers/char\" which is a tree was\nnot shown when \"drivers/char/\" is given.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n t/t3100-ls-tree-restrict.sh |   32 +++++++++++++++++++++++++++-----\n ls-tree.c                   |    2 +-\n 2 files changed, 28 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh\n--- a/t/t3100-ls-tree-restrict.sh\n+++ b/t/t3100-ls-tree-restrict.sh\n@@ -14,7 +14,7 @@ This test runs git-ls-tree with the foll\n     path2/baz/b - a file in a directory in a directory\n \n The new path restriction code should do the right thing for path2 and\n-path2/baz\n+path2/baz.  Also path0/ should snow nothing.\n '\n . ./test-lib.sh\n \n@@ -63,7 +63,7 @@ EOF\n      test_output'\n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path' \\\n     'git-ls-tree $tree path >current &&\n      cat >expected <<\\EOF &&\n EOF\n@@ -71,7 +71,7 @@ EOF\n \n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path1 path0' \\\n     'git-ls-tree $tree path1 path0 >current &&\n      cat >expected <<\\EOF &&\n 120000 blob X\tpath1\n@@ -80,7 +80,7 @@ EOF\n      test_output'\n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path2' \\\n     'git-ls-tree $tree path2 >current &&\n      cat >expected <<\\EOF &&\n 040000 tree X\tpath2\n@@ -91,7 +91,7 @@ EOF\n      test_output'\n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path2/baz' \\\n     'git-ls-tree $tree path2/baz >current &&\n      cat >expected <<\\EOF &&\n 040000 tree X\tpath2/baz\n@@ -99,4 +99,26 @@ test_expect_success \\\n EOF\n      test_output'\n \n+test_expect_success \\\n+    'ls-tree filtered with path2' \\\n+    'git-ls-tree $tree path2 >current &&\n+     cat >expected <<\\EOF &&\n+040000 tree X\tpath2\n+040000 tree X\tpath2/baz\n+120000 blob X\tpath2/bazbo\n+100644 blob X\tpath2/foo\n+EOF\n+     test_output'\n+\n+test_expect_success \\\n+    'ls-tree filtered with path2/' \\\n+    'git-ls-tree $tree path2/ >current &&\n+     cat >expected <<\\EOF &&\n+040000 tree X\tpath2\n+040000 tree X\tpath2/baz\n+120000 blob X\tpath2/bazbo\n+100644 blob X\tpath2/foo\n+EOF\n+     test_output'\n+\n test_done\ndiff --git a/ls-tree.c b/ls-tree.c\n--- a/ls-tree.c\n+++ b/ls-tree.c\n@@ -201,7 +201,7 @@ static int list(char **path)\n \tint err = 0;\n \tfor (i = 0; path[i]; i++) {\n \t\tint len = strlen(path[i]);\n-\t\twhile (0 <= len && path[i][len] == '/')\n+\t\twhile (0 < len && path[i][len-1] == '/')\n \t\t\tlen--;\n \t\terr = err | list_one(path[i], path[i] + len);\n \t}\n------------\n\n"},{"id":"4326","messageId":"Pine.LNX.4.58.0505311507010.1876@ppc970.osdl.org","threadId":"776","inReplyTo":"7vvf4zvzfw.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] ls-tree: remove trailing slashes properly.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-05-31T22:19:13Z","receivedAt":"2005-05-31T22:19:13Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 31 May 2005, Junio C Hamano wrote:\n>\n> A typo prevented trailing slashes from being removed properly.\n\nThis is still wrong.\n\n> This fixes the problem that \"drivers/char\" which is a tree was\n> not shown when \"drivers/char/\" is given.\n\nI sent an earlier email pointing out that removing trailing slashes is \n_incorrect_, because it means that \"drivers/char/\" will match the _file_ \n\"drivers/char\", which is wrong.\n\nIOW, the trailing slash should not be removed, it's the _test_ that is \nwrong.\n\nI just checked in a fix for this in diffcore-patchspec.c, I'd hope that \nls-tree could get it right too. Removing trailing slashes is a bandaid \nthat hides one bug by making it appear as a different bug.\n\n\t\tLinus\n"},{"id":"4327","messageId":"7vhdgjvxaz.fsf@assigned-by-dhcp.cox.net","threadId":"776","inReplyTo":"Pine.LNX.4.58.0505311507010.1876@ppc970.osdl.org","subject":"Re: [PATCH] ls-tree: remove trailing slashes properly.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-31T22:35:16Z","receivedAt":"2005-05-31T22:35:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> I just checked in a fix for this in diffcore-patchspec.c,\nLT> I'd hope that ls-tree could get it right too. Removing\nLT> trailing slashes is a bandaid that hides one bug by making\nLT> it appear as a different bug.\n\nYes, I am aware of that problem but have not touched it; I sent\nan earlier email about this to you.  While I was waiting for\nyour response, I found that drivers/char/ does not even match\ndrivers/char tree, which is what the patch you are responding to\nis about.  Will look into it later.\n\n\n"},{"id":"4329","messageId":"7v8y1vvvaa.fsf_-_@assigned-by-dhcp.cox.net","threadId":"776","inReplyTo":"Pine.LNX.4.58.0505311507010.1876@ppc970.osdl.org","subject":"[PATCH] ls-tree: handle trailing slashes in the pathspec properly.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-31T23:18:53Z","receivedAt":"2005-05-31T23:18:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> I just checked in a fix for this in diffcore-patchspec.c, I'd hope that \nLT> ls-tree could get it right too. Removing trailing slashes is a bandaid \nLT> that hides one bug by making it appear as a different bug.\n\nI take it to mean that you took my other patch for diffcore-pathspec.\n\nHere is a fixed ls-tree, with a couple of new tests in an\nexisting test script, to catch this bug.\n\n------------\nThis fixes one problem while avoiding the same mistake earlier\ndiffcore-pathspec had:\n\n - \"drivers/char\" which is a tree was not shown given\n   \"drivers/char/\".\n\n - \"drivers/char\" which is not a tree is not shown given\n   \"drivers/char/\".\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n ls-tree.c                   |   57 ++++++++++++++++++++++++++-----------------\n t/t3100-ls-tree-restrict.sh |   39 ++++++++++++++++++++++++++----\n 2 files changed, 68 insertions(+), 28 deletions(-)\n\ndiff --git a/ls-tree.c b/ls-tree.c\n--- a/ls-tree.c\n+++ b/ls-tree.c\n@@ -54,13 +54,22 @@ static int prepare_children(struct tree_\n \treturn 0;\n }\n \n-static struct tree_entry_list *find_entry_0(struct tree_entry_list *elem,\n-\t\t\t\t\t    const char *path,\n-\t\t\t\t\t    const char *path_end)\n+static struct tree_entry_list *find_entry(const char *path,\n+\t\t\t\t\t  const char *path_end,\n+\t\t\t\t\t  int require_tree)\n {\n-\tconst char *ep;\n \tint len;\n+\tstruct tree_entry_list *elem = &root_entry;\n+\tconst char *ep;\n \n+\tif (path == path_end)\n+\t\t/* Special.  This is the root level */\n+\t\treturn elem;\n+\n+\t/* Find tree element, descending from root, that\n+\t * corresponds to the named path, lazily expanding\n+\t * the tree if possible.\n+\t */\n \twhile (path < path_end) {\n \t\tif (prepare_children(elem))\n \t\t\treturn NULL;\n@@ -81,27 +90,25 @@ static struct tree_entry_list *find_entr\n \t\t\t\tbreak;\n \t\t\telem = elem->next;\n \t\t}\n-\t\tif (path_end <= ep || !elem)\n+\t\tif (!elem)\n+\t\t\treturn NULL;\n+\t\tif (path_end <= ep) {\n+\t\t\t/* elem matches the specified path.  However,\n+\t\t\t * if the user said \"drivers/char/\" and\n+\t\t\t * elem is \"drivers/char\", _and_ it is not\n+\t\t\t * a tree, then we should reject, just like\n+\t\t\t * \"/bin/ls -a ls-tree.c/\" says \"Not a directory\".\n+\t\t\t */\n+\t\t\tif (require_tree && !elem->directory)\n+\t\t\t\treturn NULL;\n \t\t\treturn elem;\n+\t\t}\n \t\twhile (*ep == '/' && ep < path_end)\n \t\t\tep++;\n \t\tpath = ep;\n \t}\n \treturn NULL;\n-}\n \n-static struct tree_entry_list *find_entry(const char *path,\n-\t\t\t\t\t  const char *path_end)\n-{\n-\t/* Find tree element, descending from root, that\n-\t * corresponds to the named path, lazily expanding\n-\t * the tree if possible.\n-\t */\n-\tif (path == path_end) {\n-\t\t/* Special.  This is the root level */\n-\t\treturn &root_entry;\n-\t}\n-\treturn find_entry_0(&root_entry, path, path_end);\n }\n \n static void show_entry_name(struct tree_entry_list *e)\n@@ -180,10 +187,10 @@ static int show_entry(struct tree_entry_\n \treturn err;\n }\n \n-static int list_one(const char *path, const char *path_end)\n+static int list_one(const char *path, const char *path_end, int require_tree)\n {\n \tint err = 0;\n-\tstruct tree_entry_list *e = find_entry(path, path_end);\n+\tstruct tree_entry_list *e = find_entry(path, path_end, require_tree);\n \tif (!e) {\n \t\t/* traditionally ls-tree does not complain about\n \t\t * missing path.  We may change this later to match\n@@ -201,9 +208,13 @@ static int list(char **path)\n \tint err = 0;\n \tfor (i = 0; path[i]; i++) {\n \t\tint len = strlen(path[i]);\n-\t\twhile (0 <= len && path[i][len] == '/')\n-\t\t\tlen--;\n-\t\terr = err | list_one(path[i], path[i] + len);\n+\t\tint require_tree = 0;\n+\t\tif (0 < len && path[i][len-1] == '/') {\n+\t\t\trequire_tree = 1;\n+\t\t\twhile (0 < len && path[i][len-1] == '/')\n+\t\t\t\tlen--;\n+\t\t}\n+\t\terr = err | list_one(path[i], path[i] + len, require_tree);\n \t}\n \treturn err;\n }\ndiff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh\n--- a/t/t3100-ls-tree-restrict.sh\n+++ b/t/t3100-ls-tree-restrict.sh\n@@ -14,7 +14,7 @@ This test runs git-ls-tree with the foll\n     path2/baz/b - a file in a directory in a directory\n \n The new path restriction code should do the right thing for path2 and\n-path2/baz\n+path2/baz.  Also path0/ should snow nothing.\n '\n . ./test-lib.sh\n \n@@ -63,7 +63,7 @@ EOF\n      test_output'\n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path' \\\n     'git-ls-tree $tree path >current &&\n      cat >expected <<\\EOF &&\n EOF\n@@ -71,7 +71,7 @@ EOF\n \n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path1 path0' \\\n     'git-ls-tree $tree path1 path0 >current &&\n      cat >expected <<\\EOF &&\n 120000 blob X\tpath1\n@@ -80,7 +80,14 @@ EOF\n      test_output'\n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path0/' \\\n+    'git-ls-tree $tree path0/ >current &&\n+     cat >expected <<\\EOF &&\n+EOF\n+     test_output'\n+\n+test_expect_success \\\n+    'ls-tree filtered with path2' \\\n     'git-ls-tree $tree path2 >current &&\n      cat >expected <<\\EOF &&\n 040000 tree X\tpath2\n@@ -91,7 +98,7 @@ EOF\n      test_output'\n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path2/baz' \\\n     'git-ls-tree $tree path2/baz >current &&\n      cat >expected <<\\EOF &&\n 040000 tree X\tpath2/baz\n@@ -99,4 +106,26 @@ test_expect_success \\\n EOF\n      test_output'\n \n+test_expect_success \\\n+    'ls-tree filtered with path2' \\\n+    'git-ls-tree $tree path2 >current &&\n+     cat >expected <<\\EOF &&\n+040000 tree X\tpath2\n+040000 tree X\tpath2/baz\n+120000 blob X\tpath2/bazbo\n+100644 blob X\tpath2/foo\n+EOF\n+     test_output'\n+\n+test_expect_success \\\n+    'ls-tree filtered with path2/' \\\n+    'git-ls-tree $tree path2/ >current &&\n+     cat >expected <<\\EOF &&\n+040000 tree X\tpath2\n+040000 tree X\tpath2/baz\n+120000 blob X\tpath2/bazbo\n+100644 blob X\tpath2/foo\n+EOF\n+     test_output'\n+\n test_done\n------------\n\n"},{"id":"4330","messageId":"7v4qcjvv4u.fsf@assigned-by-dhcp.cox.net","threadId":"776","inReplyTo":"Pine.LNX.4.58.0505311507010.1876@ppc970.osdl.org","subject":"Re: [PATCH] ls-tree: remove trailing slashes properly.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-31T23:22:09Z","receivedAt":"2005-05-31T23:22:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Should we do the same for git-ls-files?\n\n"},{"id":"4331","messageId":"Pine.LNX.4.58.0505311636260.1876@ppc970.osdl.org","threadId":"776","inReplyTo":"7v8y1vvvaa.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] ls-tree: handle trailing slashes in the pathspec properly.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-05-31T23:48:42Z","receivedAt":"2005-05-31T23:48:42Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 31 May 2005, Junio C Hamano wrote:\n> \n> I take it to mean that you took my other patch for diffcore-pathspec.\n\nNo, I did my own. Rather than add more code to handle '/' as a special \ncase, I just removed it all, and fixed the compare logic.\n\n> Here is a fixed ls-tree, with a couple of new tests in an\n> existing test script, to catch this bug.\n\nYou seem to think that '/' at the end is a special case, and it really \nshouldn't be. It should just fall out as a natural special case of a \nzero-sized name (which is, btw, the same natural special case that the \npath of \"\" should have in &root_dir).\n\nFor some reason your ls-tree.c logic seems to think that zero-sized names\nmeans \"root entry\", when the _natural_ thing to do is to pass in the \"base\ndirectory\", and then a zero-sized name is that base.\n\nIOW, it would make much more sense to have\n\n\tlist_one(struct tree_entry_list *tree, const char *name)\n\t{\n\t\tconst char *slash = strchr(name, '/');\n\t\tconst char *next;\n\t\tint len;\n\n\t\tfor (;;) {\n\t\t\tif (!slash) {\n\t\t\t\tlen = strlen(name);\n\t\t\t\tnext = NULL;\n\t\t\t} else {\n\t\t\t\tlen = slash - name;\n\t\t\t\tnext = slash+1;\n\t\t\t}\n\t\t\tnewtree = tree;\n\t\t\tif (len)\n\t\t\t\tnewtree = lookup(tree, name, len);\n\t\t\tif (!next)\n\t\t\t\tbreak;\n\t\t\ttree = newtree;\n\t\t\tname = next;\n\t\t}\n\n\t\t/* Ok, \"newtree\" is the last component */\n\t\tshow_entry(newtree);\n\t}\n\nand then call it with\n\n\tlist_one(&root_entry, full_path)\n\nand notice how the cases of an empty path \"\" and \"xxx//yy\" and \"xx/\"  \njust fall out from the exact same logic - a zero-sized name is the same as\nthe directory it is in. No special cases for slashes or empty names.\n\n\t\tLinus\n"},{"id":"4334","messageId":"7vy89uu9vc.fsf@assigned-by-dhcp.cox.net","threadId":"776","inReplyTo":"Pine.LNX.4.58.0505311636260.1876@ppc970.osdl.org","subject":"[PATCH] ls-tree: handle trailing slashes in the pathspec properly.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-01T01:46:47Z","receivedAt":"2005-06-01T01:46:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This fixes the problem with ls-tree which failed to show\n\"drivers/char\" directory when the user asked for \"drivers/char/\"\nfrom the command line.  At the same time, if \"drivers/char\" were\na non directory, \"drivers/char/\" would not show it.  This is\nconsistent with the way diffcore-pathspec has been recently\nfixed.\n\nThis adds back the diffcore-pathspec test,dropped when my\nearlier diffcore-pathspec fix was rejected. \n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n*** OK, this is the third try (2 1/2nd to be exact).  I love how\n*** you always turn out to be right ;-).  BTW could you limit\n*** git-apply --stat output to 79 cols not 80?\n\n ls-tree.c                   |   94 ++++++++++++++++++++++----------------------\n t/t3100-ls-tree-restrict.sh |   39 ++++++++++++++++--\n t/t4010-diff-pathspec.sh    |   65 ++++++++++++++++++++++++++++++\n3 files changed, 146 insertions(+), 52 deletions(-)\n\ndiff --git a/ls-tree.c b/ls-tree.c\n--- a/ls-tree.c\n+++ b/ls-tree.c\n@@ -54,54 +54,58 @@ static int prepare_children(struct tree_\n \treturn 0;\n }\n \n-static struct tree_entry_list *find_entry_0(struct tree_entry_list *elem,\n-\t\t\t\t\t    const char *path,\n-\t\t\t\t\t    const char *path_end)\n+static struct tree_entry_list *find_entry(const char *path)\n {\n-\tconst char *ep;\n+\tconst char *next, *slash;\n \tint len;\n+\tstruct tree_entry_list *elem = &root_entry;\n \n-\twhile (path < path_end) {\n-\t\tif (prepare_children(elem))\n-\t\t\treturn NULL;\n+\t/* Find tree element, descending from root, that\n+\t * corresponds to the named path, lazily expanding\n+\t * the tree if possible.\n+\t */\n \n-\t\t/* In elem->tree->entries, find the one that has name\n-\t\t * that matches what is between path and ep.\n+\twhile (path) {\n+\t\t/* The fact we still have path means that the caller\n+\t\t * wants us to make sure that elem at this point is a\n+\t\t * directory, and possibly descend into it.  Even what\n+\t\t * is left is just trailing slashes, we loop back to\n+\t\t * here, and this call to prepare_children() will\n+\t\t * catch elem not being a tree.  Nice.\n \t\t */\n-\t\telem = elem->item.tree->entries;\n+\t\tif (prepare_children(elem))\n+\t\t\treturn NULL;\n \n-\t\tep = strchr(path, '/');\n-\t\tif (!ep || path_end <= ep)\n-\t\t\tep = path_end;\n-\t\tlen = ep - path;\n-\n-\t\twhile (elem) {\n-\t\t\tif ((strlen(elem->name) == len) &&\n-\t\t\t    !strncmp(elem->name, path, len))\n-\t\t\t\tbreak;\n-\t\t\telem = elem->next;\n+\t\tslash = strchr(path, '/');\n+\t\tif (!slash) {\n+\t\t\tlen = strlen(path);\n+\t\t\tnext = 0;\n+\t\t}\n+\t\telse {\n+\t\t\tnext = slash + 1;\n+\t\t\tlen = slash - path;\n \t\t}\n-\t\tif (path_end <= ep || !elem)\n-\t\t\treturn elem;\n-\t\twhile (*ep == '/' && ep < path_end)\n-\t\t\tep++;\n-\t\tpath = ep;\n+\t\tif (len) {\n+\t\t\t/* (len == 0) if the original path was \"drivers/char/\"\n+\t\t\t * and we have run already two rounds, having elem\n+\t\t\t * pointing at the drivers/char directory.\n+\t\t\t */\n+\t\t\telem = elem->item.tree->entries;\n+\t\t\twhile (elem) {\n+\t\t\t\tif ((strlen(elem->name) == len) &&\n+\t\t\t\t    !strncmp(elem->name, path, len)) {\n+\t\t\t\t\t/* found */\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t\telem = elem->next;\n+\t\t\t}\n+\t\t\tif (!elem)\n+\t\t\t\treturn NULL;\n+\t\t}\n+\t\tpath = next;\n \t}\n-\treturn NULL;\n-}\n \n-static struct tree_entry_list *find_entry(const char *path,\n-\t\t\t\t\t  const char *path_end)\n-{\n-\t/* Find tree element, descending from root, that\n-\t * corresponds to the named path, lazily expanding\n-\t * the tree if possible.\n-\t */\n-\tif (path == path_end) {\n-\t\t/* Special.  This is the root level */\n-\t\treturn &root_entry;\n-\t}\n-\treturn find_entry_0(&root_entry, path, path_end);\n+\treturn elem;\n }\n \n static void show_entry_name(struct tree_entry_list *e)\n@@ -180,10 +184,10 @@ static int show_entry(struct tree_entry_\n \treturn err;\n }\n \n-static int list_one(const char *path, const char *path_end)\n+static int list_one(const char *path)\n {\n \tint err = 0;\n-\tstruct tree_entry_list *e = find_entry(path, path_end);\n+\tstruct tree_entry_list *e = find_entry(path);\n \tif (!e) {\n \t\t/* traditionally ls-tree does not complain about\n \t\t * missing path.  We may change this later to match\n@@ -199,12 +203,8 @@ static int list(char **path)\n {\n \tint i;\n \tint err = 0;\n-\tfor (i = 0; path[i]; i++) {\n-\t\tint len = strlen(path[i]);\n-\t\twhile (0 <= len && path[i][len] == '/')\n-\t\t\tlen--;\n-\t\terr = err | list_one(path[i], path[i] + len);\n-\t}\n+\tfor (i = 0; path[i]; i++)\n+\t\terr = err | list_one(path[i]);\n \treturn err;\n }\n \ndiff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh\n--- a/t/t3100-ls-tree-restrict.sh\n+++ b/t/t3100-ls-tree-restrict.sh\n@@ -14,7 +14,7 @@ This test runs git-ls-tree with the foll\n     path2/baz/b - a file in a directory in a directory\n \n The new path restriction code should do the right thing for path2 and\n-path2/baz\n+path2/baz.  Also path0/ should snow nothing.\n '\n . ./test-lib.sh\n \n@@ -63,7 +63,7 @@ EOF\n      test_output'\n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path' \\\n     'git-ls-tree $tree path >current &&\n      cat >expected <<\\EOF &&\n EOF\n@@ -71,7 +71,7 @@ EOF\n \n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path1 path0' \\\n     'git-ls-tree $tree path1 path0 >current &&\n      cat >expected <<\\EOF &&\n 120000 blob X\tpath1\n@@ -80,7 +80,14 @@ EOF\n      test_output'\n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path0/' \\\n+    'git-ls-tree $tree path0/ >current &&\n+     cat >expected <<\\EOF &&\n+EOF\n+     test_output'\n+\n+test_expect_success \\\n+    'ls-tree filtered with path2' \\\n     'git-ls-tree $tree path2 >current &&\n      cat >expected <<\\EOF &&\n 040000 tree X\tpath2\n@@ -91,7 +98,7 @@ EOF\n      test_output'\n \n test_expect_success \\\n-    'ls-tree filtered' \\\n+    'ls-tree filtered with path2/baz' \\\n     'git-ls-tree $tree path2/baz >current &&\n      cat >expected <<\\EOF &&\n 040000 tree X\tpath2/baz\n@@ -99,4 +106,26 @@ test_expect_success \\\n EOF\n      test_output'\n \n+test_expect_success \\\n+    'ls-tree filtered with path2' \\\n+    'git-ls-tree $tree path2 >current &&\n+     cat >expected <<\\EOF &&\n+040000 tree X\tpath2\n+040000 tree X\tpath2/baz\n+120000 blob X\tpath2/bazbo\n+100644 blob X\tpath2/foo\n+EOF\n+     test_output'\n+\n+test_expect_success \\\n+    'ls-tree filtered with path2/' \\\n+    'git-ls-tree $tree path2/ >current &&\n+     cat >expected <<\\EOF &&\n+040000 tree X\tpath2\n+040000 tree X\tpath2/baz\n+120000 blob X\tpath2/bazbo\n+100644 blob X\tpath2/foo\n+EOF\n+     test_output'\n+\n test_done\ndiff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh\nnew file mode 100644\n--- /dev/null\n+++ b/t/t4010-diff-pathspec.sh\n@@ -0,0 +1,65 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005 Junio C Hamano\n+#\n+\n+test_description='Pathspec restrictions\n+\n+Prepare:\n+        file0\n+        path1/file1\n+'\n+. ./test-lib.sh\n+. ../diff-lib.sh ;# test-lib chdir's into trash\n+\n+test_expect_success \\\n+    setup \\\n+    'echo frotz >file0 &&\n+     mkdir path1 &&\n+     echo rezrov >path1/file1 &&\n+     git-update-cache --add file0 path1/file1 &&\n+     tree=`git-write-tree` &&\n+     echo \"$tree\" &&\n+     echo nitfol >file0 &&\n+     echo yomin >path1/file1 &&\n+     git-update-cache file0 path1/file1' \n+\n+cat >expected <<\\EOF\n+EOF\n+test_expect_success \\\n+    'limit to path should show nothing' \\\n+    'git-diff-cache --cached $tree path >current &&\n+     compare_diff_raw current expected'\n+\n+cat >expected <<\\EOF\n+:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M\tpath1/file1\n+EOF\n+test_expect_success \\\n+    'limit to path1 should show path1/file1' \\\n+    'git-diff-cache --cached $tree path1 >current &&\n+     compare_diff_raw current expected'\n+\n+cat >expected <<\\EOF\n+:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M\tpath1/file1\n+EOF\n+test_expect_success \\\n+    'limit to path1/ should show path1/file1' \\\n+    'git-diff-cache --cached $tree path1/ >current &&\n+     compare_diff_raw current expected'\n+\n+cat >expected <<\\EOF\n+:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M\tfile0\n+EOF\n+test_expect_success \\\n+    'limit to file0 should show file0' \\\n+    'git-diff-cache --cached $tree file0 >current &&\n+     compare_diff_raw current expected'\n+\n+cat >expected <<\\EOF\n+EOF\n+test_expect_success \\\n+    'limit to file0/ should emit nothing.' \\\n+    'git-diff-cache --cached $tree file0/ >current &&\n+     compare_diff_raw current expected'\n+\n+test_done\n------------\n\n"},{"id":"4340","messageId":"Pine.LNX.4.58.0505312048350.1876@ppc970.osdl.org","threadId":"776","inReplyTo":"7vy89uu9vc.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] ls-tree: handle trailing slashes in the pathspec properly.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-01T03:51:18Z","receivedAt":"2005-06-01T03:51:18Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 31 May 2005, Junio C Hamano wrote:\n> \n> BTW could you limit git-apply --stat output to 79 cols not 80?\n\nHmm, I thought I already did, but it turns out it could round up both \nadd/del, causing my 79 to be 80.\n\nI think I fixed it.\n\n\t\tLinus\n"}]}