* Re: [PATCH] allow pathspec to end with a slash
@ 2005-05-31 15:32 Linus Torvalds
2005-05-31 20:08 ` Junio C Hamano
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Linus Torvalds @ 2005-05-31 15:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
Junio,
pathspec is still subtly broken.
Just removing the slash at the end is not the right thing to do, since
that means that
git-diff-files drivers/char/
will trigger on a _file_ "drivers/char", even though the spec makes it
unambiguous that the user only wants to see stuff under that directory.
Again, git-diff-tree gets this right (not to say that it always did - I
had to fix "interesting()" several times, exactly because it's not that
simple).
Linus
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH] allow pathspec to end with a slash 2005-05-31 15:32 [PATCH] allow pathspec to end with a slash Linus Torvalds @ 2005-05-31 20:08 ` Junio C Hamano 2005-05-31 21:47 ` [PATCH 1/2] diff: consolidate test helper script pieces Junio C Hamano ` (2 subsequent siblings) 3 siblings, 0 replies; 12+ messages in thread From: Junio C Hamano @ 2005-05-31 20:08 UTC (permalink / raw) To: Linus Torvalds; +Cc: Git Mailing List Do you want the same for git-ls-tree as well? That is, when you have drivers/char as a blob in the tree, should git-ls-tree $tree drivers/char/ show nothing? ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] diff: consolidate test helper script pieces. 2005-05-31 15:32 [PATCH] allow pathspec to end with a slash Linus Torvalds 2005-05-31 20:08 ` Junio C Hamano @ 2005-05-31 21:47 ` Junio C Hamano 2005-05-31 21:48 ` [PATCH 2/2] diff: Fix trailing slash handling Junio C Hamano 2005-05-31 21:49 ` [PATCH] ls-tree: remove trailing slashes properly Junio C Hamano 3 siblings, 0 replies; 12+ messages in thread From: Junio C Hamano @ 2005-05-31 21:47 UTC (permalink / raw) To: Linus Torvalds; +Cc: Git Mailing List There were duplicate script pieces to help comparing diff output, which this patch consolidates into the t/diff-lib.sh library. Signed-off-by: Junio C Hamano <junkio@cox.net> --- *** The next one is to fix the pathspec, whose test relies on *** this cleanup. t/diff-lib.sh | 35 +++++++++++++++++++++++++++++++++++ t/t4003-diff-rename-1.sh | 9 +-------- t/t4005-diff-rename-2.sh | 23 +---------------------- t/t4007-rename-3.sh | 15 +-------------- t/t4008-diff-break-rewrite.sh | 15 +-------------- t/t4009-diff-rename-4.sh | 29 ++++------------------------- 6 files changed, 43 insertions(+), 83 deletions(-) diff --git a/t/diff-lib.sh b/t/diff-lib.sh new file mode 100644 --- /dev/null +++ b/t/diff-lib.sh @@ -0,0 +1,35 @@ +: + +_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' +_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" +sanitize_diff_raw='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]* / X X \1# /' +compare_diff_raw () { + # When heuristics are improved, the score numbers would change. + # Ignore them while comparing. + # Also we do not check SHA1 hash generation in this test, which + # is a job for t0000-basic.sh + + sed -e "$sanitize_diff_raw" <"$1" >.tmp-1 + sed -e "$sanitize_diff_raw" <"$2" >.tmp-2 + diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 +} + +sanitize_diff_raw_z='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]*$/ X X \1#/' +compare_diff_raw_z () { + # When heuristics are improved, the score numbers would change. + # Ignore them while comparing. + # Also we do not check SHA1 hash generation in this test, which + # is a job for t0000-basic.sh + + tr '\0' '\012' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1 + tr '\0' '\012' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2 + diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 +} + +compare_diff_patch () { + # When heuristics are improved, the score numbers would change. + # Ignore them while comparing. + sed -e '/^[dis]*imilarity index [0-9]*%$/d' <"$1" >.tmp-1 + sed -e '/^[dis]*imilarity index [0-9]*%$/d' <"$2" >.tmp-2 + diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 +} diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh --- a/t/t4003-diff-rename-1.sh +++ b/t/t4003-diff-rename-1.sh @@ -7,14 +7,7 @@ test_description='More rename detection ' . ./test-lib.sh - -compare_diff_patch () { - # When heuristics are improved, the score numbers would change. - # Ignore them while comparing. - sed -e '/^similarity index [0-9]*%$/d' <"$1" >.tmp-1 - sed -e '/^similarity index [0-9]*%$/d' <"$2" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 -} +. ../diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ 'prepare reference tree' \ diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh --- a/t/t4005-diff-rename-2.sh +++ b/t/t4005-diff-rename-2.sh @@ -7,28 +7,7 @@ test_description='Same rename detection ' . ./test-lib.sh - -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" -sanitize_diff_raw='s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]* / X X \1# /' -compare_diff_raw () { - # When heuristics are improved, the score numbers would change. - # Ignore them while comparing. - # Also we do not check SHA1 hash generation in this test, which - # is a job for t0000-basic.sh - - sed -e "$sanitize_diff_raw" <"$1" >.tmp-1 - sed -e "$sanitize_diff_raw" <"$2" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 -} - -compare_diff_patch () { - # When heuristics are improved, the score numbers would change. - # Ignore them while comparing. - sed -e '/^similarity index [0-9]*%$/d' <"$1" >.tmp-1 - sed -e '/^similarity index [0-9]*%$/d' <"$2" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 -} +. ../diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ 'prepare reference tree' \ diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh --- a/t/t4007-rename-3.sh +++ b/t/t4007-rename-3.sh @@ -7,20 +7,7 @@ test_description='Rename interaction wit ' . ./test-lib.sh - -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" -sanitize_diff_raw='s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]* / X X \1# /' -compare_diff_raw () { - # When heuristics are improved, the score numbers would change. - # Ignore them while comparing. - # Also we do not check SHA1 hash generation in this test, which - # is a job for t0000-basic.sh - - sed -e "$sanitize_diff_raw" <"$1" >.tmp-1 - sed -e "$sanitize_diff_raw" <"$2" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 -} +. ../diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ 'prepare reference tree' \ diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh --- a/t/t4008-diff-break-rewrite.sh +++ b/t/t4008-diff-break-rewrite.sh @@ -22,20 +22,7 @@ four changes in total. Further, with -B and -M together, these should turn into two renames. ' . ./test-lib.sh - -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" -sanitize_diff_raw='s/ '"$_x40"' '"$_x40"' \([CDNR]\)[0-9]* / X X \1# /' -compare_diff_raw () { - # When heuristics are improved, the score numbers would change. - # Ignore them while comparing. - # Also we do not check SHA1 hash generation in this test, which - # is a job for t0000-basic.sh - - sed -e "$sanitize_diff_raw" <"$1" >.tmp-1 - sed -e "$sanitize_diff_raw" <"$2" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 -} +. ../diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ setup \ diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh --- a/t/t4009-diff-rename-4.sh +++ b/t/t4009-diff-rename-4.sh @@ -7,28 +7,7 @@ test_description='Same rename detection ' . ./test-lib.sh - -_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" -sanitize_diff_raw='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]*$/ X X \1#/' -compare_diff_raw () { - # When heuristics are improved, the score numbers would change. - # Ignore them while comparing. - # Also we do not check SHA1 hash generation in this test, which - # is a job for t0000-basic.sh - - tr '\0' '\012' <"$1" | sed -e "$sanitize_diff_raw" >.tmp-1 - tr '\0' '\012' <"$2" | sed -e "$sanitize_diff_raw" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 -} - -compare_diff_patch () { - # When heuristics are improved, the score numbers would change. - # Ignore them while comparing. - sed -e '/^similarity index [0-9]*%$/d' <"$1" >.tmp-1 - sed -e '/^similarity index [0-9]*%$/d' <"$2" >.tmp-2 - diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 -} +. ../diff-lib.sh ;# test-lib chdir's into trash test_expect_success \ 'prepare reference tree' \ @@ -63,7 +42,7 @@ EOF test_expect_success \ 'validate output from rename/copy detection (#1)' \ - 'compare_diff_raw current expected' + 'compare_diff_raw_z current expected' # make sure diff-helper can grok it. mv current diff-raw @@ -120,7 +99,7 @@ EOF test_expect_success \ 'validate output from rename/copy detection (#2)' \ - 'compare_diff_raw current expected' + 'compare_diff_raw_z current expected' # make sure diff-helper can grok it. mv current diff-raw @@ -173,7 +152,7 @@ EOF test_expect_success \ 'validate output from rename/copy detection (#3)' \ - 'compare_diff_raw current expected' + 'compare_diff_raw_z current expected' # make sure diff-helper can grok it. mv current diff-raw ------------ ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/2] diff: Fix trailing slash handling. 2005-05-31 15:32 [PATCH] allow pathspec to end with a slash Linus Torvalds 2005-05-31 20:08 ` Junio C Hamano 2005-05-31 21:47 ` [PATCH 1/2] diff: consolidate test helper script pieces Junio C Hamano @ 2005-05-31 21:48 ` Junio C Hamano 2005-05-31 21:49 ` [PATCH] ls-tree: remove trailing slashes properly Junio C Hamano 3 siblings, 0 replies; 12+ messages in thread From: Junio C Hamano @ 2005-05-31 21:48 UTC (permalink / raw) To: Linus Torvalds; +Cc: Git Mailing List When limiting the world to "drivers/char/", we should not consider "drivers/char" which is not a directory. Signed-off-by: Junio C Hamano <junkio@cox.net> --- t/t4010-diff-pathspec.sh | 65 ++++++++++++++++++++++++++++++++++++++++++++++ diffcore-pathspec.c | 60 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 117 insertions(+), 8 deletions(-) diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh new file mode 100644 --- /dev/null +++ b/t/t4010-diff-pathspec.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Pathspec restrictions + +Prepare: + file0 + path1/file1 +' +. ./test-lib.sh +. ../diff-lib.sh ;# test-lib chdir's into trash + +test_expect_success \ + setup \ + 'echo frotz >file0 && + mkdir path1 && + echo rezrov >path1/file1 && + git-update-cache --add file0 path1/file1 && + tree=`git-write-tree` && + echo "$tree" && + echo nitfol >file0 && + echo yomin >path1/file1 && + git-update-cache file0 path1/file1' + +cat >expected <<\EOF +EOF +test_expect_success \ + 'limit to path should show nothing' \ + 'git-diff-cache --cached $tree path >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +EOF +test_expect_success \ + 'limit to path1 should show path1/file1' \ + 'git-diff-cache --cached $tree path1 >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +EOF +test_expect_success \ + 'limit to path1/ should show path1/file1' \ + 'git-diff-cache --cached $tree path1/ >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M file0 +EOF +test_expect_success \ + 'limit to file0 should show file0' \ + 'git-diff-cache --cached $tree file0 >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +EOF +test_expect_success \ + 'limit to file0/ should emit nothing.' \ + 'git-diff-cache --cached $tree file0/ >current && + compare_diff_raw current expected' + +test_done diff --git a/diffcore-pathspec.c b/diffcore-pathspec.c --- a/diffcore-pathspec.c +++ b/diffcore-pathspec.c @@ -8,9 +8,13 @@ struct path_spec { const char *spec; int len; + int reject_non_tree; }; -static int matches_pathspec(const char *name, struct path_spec *s, int cnt) +static int matches_pathspec(const char *name, + int obviously_non_tree, + struct path_spec *s, + int cnt) { int i; int namelen; @@ -21,10 +25,25 @@ static int matches_pathspec(const char * namelen = strlen(name); for (i = 0; i < cnt; i++) { int len = s[i].len; - if (! strncmp(s[i].spec, name, len) && - len <= namelen && - (name[len] == 0 || name[len] == '/')) - return 1; + if (!strncmp(s[i].spec, name, len)) { + /* Leading part matches. */ + if (len == namelen) { + /* Exact match: spec "drivers/char/" + * should not match against path + * "drivers/char". + */ + if (s[i].reject_non_tree && obviously_non_tree) + continue; + return 1; + } + else if ((len < namelen) && name[len] == '/') { + /* Spec is leading path */ + return 1; + } + /* otherwise, it is a false match of spec "abc" + * against path "abcdefg", so we continue. + */ + } } return 0; } @@ -47,14 +66,39 @@ void diffcore_pathspec(const char **path int l; spec[i].spec = pathspec[i]; l = strlen(pathspec[i]); - while (l > 0 && pathspec[i][l-1] == '/') - l--; + if (l > 0 && pathspec[i][l-1] == '/') { + spec[i].reject_non_tree = 1; + while (l > 0 && pathspec[i][l-1] == '/') + l--; + } spec[i].len = l; } for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; - if (matches_pathspec(p->two->path, spec, speccnt)) + int obviously_non_tree; +#ifndef DIFF_TREE_CALLS_PATHSPEC + /* + * NOTE: This relies on the current behaviour of + * diff-tree which does not use diffcore-pathspec + * and we would not ever see "tree" objects + * in our input. + */ + obviously_non_tree = 1; +#else + if (DIFF_FILE_VALID(p->two)) + obviously_non_tree = !S_ISDIR(p->two->mode); + else if (DIFF_FILE_VALID(p->one)) + /* path is being deleted. is it a tree? */ + obviously_non_tree = !S_ISDIR(p->one->mode); + else + /* path is unmerged, which comes from cache + * so it cannot be a tree + */ + obviously_non_tree = 1; +#endif + if (matches_pathspec(p->two->path, obviously_non_tree, + spec, speccnt)) diff_q(&outq, p); else diff_free_filepair(p); ------------ ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] ls-tree: remove trailing slashes properly. 2005-05-31 15:32 [PATCH] allow pathspec to end with a slash Linus Torvalds ` (2 preceding siblings ...) 2005-05-31 21:48 ` [PATCH 2/2] diff: Fix trailing slash handling Junio C Hamano @ 2005-05-31 21:49 ` Junio C Hamano 2005-05-31 22:19 ` Linus Torvalds 3 siblings, 1 reply; 12+ messages in thread From: Junio C Hamano @ 2005-05-31 21:49 UTC (permalink / raw) To: Linus Torvalds; +Cc: Git Mailing List A typo prevented trailing slashes from being removed properly. This fixes the problem that "drivers/char" which is a tree was not shown when "drivers/char/" is given. Signed-off-by: Junio C Hamano <junkio@cox.net> --- t/t3100-ls-tree-restrict.sh | 32 +++++++++++++++++++++++++++----- ls-tree.c | 2 +- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -14,7 +14,7 @@ This test runs git-ls-tree with the foll path2/baz/b - a file in a directory in a directory The new path restriction code should do the right thing for path2 and -path2/baz +path2/baz. Also path0/ should snow nothing. ' . ./test-lib.sh @@ -63,7 +63,7 @@ EOF test_output' test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path' \ 'git-ls-tree $tree path >current && cat >expected <<\EOF && EOF @@ -71,7 +71,7 @@ EOF test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path1 path0' \ 'git-ls-tree $tree path1 path0 >current && cat >expected <<\EOF && 120000 blob X path1 @@ -80,7 +80,7 @@ EOF test_output' test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path2' \ 'git-ls-tree $tree path2 >current && cat >expected <<\EOF && 040000 tree X path2 @@ -91,7 +91,7 @@ EOF test_output' test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path2/baz' \ 'git-ls-tree $tree path2/baz >current && cat >expected <<\EOF && 040000 tree X path2/baz @@ -99,4 +99,26 @@ test_expect_success \ EOF test_output' +test_expect_success \ + 'ls-tree filtered with path2' \ + 'git-ls-tree $tree path2 >current && + cat >expected <<\EOF && +040000 tree X path2 +040000 tree X path2/baz +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path2/' \ + 'git-ls-tree $tree path2/ >current && + cat >expected <<\EOF && +040000 tree X path2 +040000 tree X path2/baz +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + test_done diff --git a/ls-tree.c b/ls-tree.c --- a/ls-tree.c +++ b/ls-tree.c @@ -201,7 +201,7 @@ static int list(char **path) int err = 0; for (i = 0; path[i]; i++) { int len = strlen(path[i]); - while (0 <= len && path[i][len] == '/') + while (0 < len && path[i][len-1] == '/') len--; err = err | list_one(path[i], path[i] + len); } ------------ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] ls-tree: remove trailing slashes properly. 2005-05-31 21:49 ` [PATCH] ls-tree: remove trailing slashes properly Junio C Hamano @ 2005-05-31 22:19 ` Linus Torvalds 2005-05-31 22:35 ` Junio C Hamano ` (2 more replies) 0 siblings, 3 replies; 12+ messages in thread From: Linus Torvalds @ 2005-05-31 22:19 UTC (permalink / raw) To: Junio C Hamano; +Cc: Git Mailing List On Tue, 31 May 2005, Junio C Hamano wrote: > > A typo prevented trailing slashes from being removed properly. This is still wrong. > This fixes the problem that "drivers/char" which is a tree was > not shown when "drivers/char/" is given. I sent an earlier email pointing out that removing trailing slashes is _incorrect_, because it means that "drivers/char/" will match the _file_ "drivers/char", which is wrong. IOW, the trailing slash should not be removed, it's the _test_ that is wrong. I just checked in a fix for this in diffcore-patchspec.c, I'd hope that ls-tree could get it right too. Removing trailing slashes is a bandaid that hides one bug by making it appear as a different bug. Linus ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] ls-tree: remove trailing slashes properly. 2005-05-31 22:19 ` Linus Torvalds @ 2005-05-31 22:35 ` Junio C Hamano 2005-05-31 23:18 ` [PATCH] ls-tree: handle trailing slashes in the pathspec properly Junio C Hamano 2005-05-31 23:22 ` [PATCH] ls-tree: remove trailing slashes properly Junio C Hamano 2 siblings, 0 replies; 12+ messages in thread From: Junio C Hamano @ 2005-05-31 22:35 UTC (permalink / raw) To: Linus Torvalds; +Cc: Git Mailing List >>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes: LT> I just checked in a fix for this in diffcore-patchspec.c, LT> I'd hope that ls-tree could get it right too. Removing LT> trailing slashes is a bandaid that hides one bug by making LT> it appear as a different bug. Yes, I am aware of that problem but have not touched it; I sent an earlier email about this to you. While I was waiting for your response, I found that drivers/char/ does not even match drivers/char tree, which is what the patch you are responding to is about. Will look into it later. ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] ls-tree: handle trailing slashes in the pathspec properly. 2005-05-31 22:19 ` Linus Torvalds 2005-05-31 22:35 ` Junio C Hamano @ 2005-05-31 23:18 ` Junio C Hamano 2005-05-31 23:48 ` Linus Torvalds 2005-05-31 23:22 ` [PATCH] ls-tree: remove trailing slashes properly Junio C Hamano 2 siblings, 1 reply; 12+ messages in thread From: Junio C Hamano @ 2005-05-31 23:18 UTC (permalink / raw) To: Linus Torvalds; +Cc: Git Mailing List >>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes: LT> I just checked in a fix for this in diffcore-patchspec.c, I'd hope that LT> ls-tree could get it right too. Removing trailing slashes is a bandaid LT> that hides one bug by making it appear as a different bug. I take it to mean that you took my other patch for diffcore-pathspec. Here is a fixed ls-tree, with a couple of new tests in an existing test script, to catch this bug. ------------ This fixes one problem while avoiding the same mistake earlier diffcore-pathspec had: - "drivers/char" which is a tree was not shown given "drivers/char/". - "drivers/char" which is not a tree is not shown given "drivers/char/". Signed-off-by: Junio C Hamano <junkio@cox.net> --- ls-tree.c | 57 ++++++++++++++++++++++++++----------------- t/t3100-ls-tree-restrict.sh | 39 ++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/ls-tree.c b/ls-tree.c --- a/ls-tree.c +++ b/ls-tree.c @@ -54,13 +54,22 @@ static int prepare_children(struct tree_ return 0; } -static struct tree_entry_list *find_entry_0(struct tree_entry_list *elem, - const char *path, - const char *path_end) +static struct tree_entry_list *find_entry(const char *path, + const char *path_end, + int require_tree) { - const char *ep; int len; + struct tree_entry_list *elem = &root_entry; + const char *ep; + if (path == path_end) + /* Special. This is the root level */ + return elem; + + /* Find tree element, descending from root, that + * corresponds to the named path, lazily expanding + * the tree if possible. + */ while (path < path_end) { if (prepare_children(elem)) return NULL; @@ -81,27 +90,25 @@ static struct tree_entry_list *find_entr break; elem = elem->next; } - if (path_end <= ep || !elem) + if (!elem) + return NULL; + if (path_end <= ep) { + /* elem matches the specified path. However, + * if the user said "drivers/char/" and + * elem is "drivers/char", _and_ it is not + * a tree, then we should reject, just like + * "/bin/ls -a ls-tree.c/" says "Not a directory". + */ + if (require_tree && !elem->directory) + return NULL; return elem; + } while (*ep == '/' && ep < path_end) ep++; path = ep; } return NULL; -} -static struct tree_entry_list *find_entry(const char *path, - const char *path_end) -{ - /* Find tree element, descending from root, that - * corresponds to the named path, lazily expanding - * the tree if possible. - */ - if (path == path_end) { - /* Special. This is the root level */ - return &root_entry; - } - return find_entry_0(&root_entry, path, path_end); } static void show_entry_name(struct tree_entry_list *e) @@ -180,10 +187,10 @@ static int show_entry(struct tree_entry_ return err; } -static int list_one(const char *path, const char *path_end) +static int list_one(const char *path, const char *path_end, int require_tree) { int err = 0; - struct tree_entry_list *e = find_entry(path, path_end); + struct tree_entry_list *e = find_entry(path, path_end, require_tree); if (!e) { /* traditionally ls-tree does not complain about * missing path. We may change this later to match @@ -201,9 +208,13 @@ static int list(char **path) int err = 0; for (i = 0; path[i]; i++) { int len = strlen(path[i]); - while (0 <= len && path[i][len] == '/') - len--; - err = err | list_one(path[i], path[i] + len); + int require_tree = 0; + if (0 < len && path[i][len-1] == '/') { + require_tree = 1; + while (0 < len && path[i][len-1] == '/') + len--; + } + err = err | list_one(path[i], path[i] + len, require_tree); } return err; } diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -14,7 +14,7 @@ This test runs git-ls-tree with the foll path2/baz/b - a file in a directory in a directory The new path restriction code should do the right thing for path2 and -path2/baz +path2/baz. Also path0/ should snow nothing. ' . ./test-lib.sh @@ -63,7 +63,7 @@ EOF test_output' test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path' \ 'git-ls-tree $tree path >current && cat >expected <<\EOF && EOF @@ -71,7 +71,7 @@ EOF test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path1 path0' \ 'git-ls-tree $tree path1 path0 >current && cat >expected <<\EOF && 120000 blob X path1 @@ -80,7 +80,14 @@ EOF test_output' test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path0/' \ + 'git-ls-tree $tree path0/ >current && + cat >expected <<\EOF && +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path2' \ 'git-ls-tree $tree path2 >current && cat >expected <<\EOF && 040000 tree X path2 @@ -91,7 +98,7 @@ EOF test_output' test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path2/baz' \ 'git-ls-tree $tree path2/baz >current && cat >expected <<\EOF && 040000 tree X path2/baz @@ -99,4 +106,26 @@ test_expect_success \ EOF test_output' +test_expect_success \ + 'ls-tree filtered with path2' \ + 'git-ls-tree $tree path2 >current && + cat >expected <<\EOF && +040000 tree X path2 +040000 tree X path2/baz +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path2/' \ + 'git-ls-tree $tree path2/ >current && + cat >expected <<\EOF && +040000 tree X path2 +040000 tree X path2/baz +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + test_done ------------ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] ls-tree: handle trailing slashes in the pathspec properly. 2005-05-31 23:18 ` [PATCH] ls-tree: handle trailing slashes in the pathspec properly Junio C Hamano @ 2005-05-31 23:48 ` Linus Torvalds 2005-06-01 1:46 ` Junio C Hamano 0 siblings, 1 reply; 12+ messages in thread From: Linus Torvalds @ 2005-05-31 23:48 UTC (permalink / raw) To: Junio C Hamano; +Cc: Git Mailing List On Tue, 31 May 2005, Junio C Hamano wrote: > > I take it to mean that you took my other patch for diffcore-pathspec. No, I did my own. Rather than add more code to handle '/' as a special case, I just removed it all, and fixed the compare logic. > Here is a fixed ls-tree, with a couple of new tests in an > existing test script, to catch this bug. You seem to think that '/' at the end is a special case, and it really shouldn't be. It should just fall out as a natural special case of a zero-sized name (which is, btw, the same natural special case that the path of "" should have in &root_dir). For some reason your ls-tree.c logic seems to think that zero-sized names means "root entry", when the _natural_ thing to do is to pass in the "base directory", and then a zero-sized name is that base. IOW, it would make much more sense to have list_one(struct tree_entry_list *tree, const char *name) { const char *slash = strchr(name, '/'); const char *next; int len; for (;;) { if (!slash) { len = strlen(name); next = NULL; } else { len = slash - name; next = slash+1; } newtree = tree; if (len) newtree = lookup(tree, name, len); if (!next) break; tree = newtree; name = next; } /* Ok, "newtree" is the last component */ show_entry(newtree); } and then call it with list_one(&root_entry, full_path) and notice how the cases of an empty path "" and "xxx//yy" and "xx/" just fall out from the exact same logic - a zero-sized name is the same as the directory it is in. No special cases for slashes or empty names. Linus ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] ls-tree: handle trailing slashes in the pathspec properly. 2005-05-31 23:48 ` Linus Torvalds @ 2005-06-01 1:46 ` Junio C Hamano 2005-06-01 3:51 ` Linus Torvalds 0 siblings, 1 reply; 12+ messages in thread From: Junio C Hamano @ 2005-06-01 1:46 UTC (permalink / raw) To: Linus Torvalds; +Cc: Git Mailing List This fixes the problem with ls-tree which failed to show "drivers/char" directory when the user asked for "drivers/char/" from the command line. At the same time, if "drivers/char" were a non directory, "drivers/char/" would not show it. This is consistent with the way diffcore-pathspec has been recently fixed. This adds back the diffcore-pathspec test,dropped when my earlier diffcore-pathspec fix was rejected. Signed-off-by: Junio C Hamano <junkio@cox.net> --- *** OK, this is the third try (2 1/2nd to be exact). I love how *** you always turn out to be right ;-). BTW could you limit *** git-apply --stat output to 79 cols not 80? ls-tree.c | 94 ++++++++++++++++++++++---------------------- t/t3100-ls-tree-restrict.sh | 39 ++++++++++++++++-- t/t4010-diff-pathspec.sh | 65 ++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 52 deletions(-) diff --git a/ls-tree.c b/ls-tree.c --- a/ls-tree.c +++ b/ls-tree.c @@ -54,54 +54,58 @@ static int prepare_children(struct tree_ return 0; } -static struct tree_entry_list *find_entry_0(struct tree_entry_list *elem, - const char *path, - const char *path_end) +static struct tree_entry_list *find_entry(const char *path) { - const char *ep; + const char *next, *slash; int len; + struct tree_entry_list *elem = &root_entry; - while (path < path_end) { - if (prepare_children(elem)) - return NULL; + /* Find tree element, descending from root, that + * corresponds to the named path, lazily expanding + * the tree if possible. + */ - /* In elem->tree->entries, find the one that has name - * that matches what is between path and ep. + while (path) { + /* The fact we still have path means that the caller + * wants us to make sure that elem at this point is a + * directory, and possibly descend into it. Even what + * is left is just trailing slashes, we loop back to + * here, and this call to prepare_children() will + * catch elem not being a tree. Nice. */ - elem = elem->item.tree->entries; + if (prepare_children(elem)) + return NULL; - ep = strchr(path, '/'); - if (!ep || path_end <= ep) - ep = path_end; - len = ep - path; - - while (elem) { - if ((strlen(elem->name) == len) && - !strncmp(elem->name, path, len)) - break; - elem = elem->next; + slash = strchr(path, '/'); + if (!slash) { + len = strlen(path); + next = 0; + } + else { + next = slash + 1; + len = slash - path; } - if (path_end <= ep || !elem) - return elem; - while (*ep == '/' && ep < path_end) - ep++; - path = ep; + if (len) { + /* (len == 0) if the original path was "drivers/char/" + * and we have run already two rounds, having elem + * pointing at the drivers/char directory. + */ + elem = elem->item.tree->entries; + while (elem) { + if ((strlen(elem->name) == len) && + !strncmp(elem->name, path, len)) { + /* found */ + break; + } + elem = elem->next; + } + if (!elem) + return NULL; + } + path = next; } - return NULL; -} -static struct tree_entry_list *find_entry(const char *path, - const char *path_end) -{ - /* Find tree element, descending from root, that - * corresponds to the named path, lazily expanding - * the tree if possible. - */ - if (path == path_end) { - /* Special. This is the root level */ - return &root_entry; - } - return find_entry_0(&root_entry, path, path_end); + return elem; } static void show_entry_name(struct tree_entry_list *e) @@ -180,10 +184,10 @@ static int show_entry(struct tree_entry_ return err; } -static int list_one(const char *path, const char *path_end) +static int list_one(const char *path) { int err = 0; - struct tree_entry_list *e = find_entry(path, path_end); + struct tree_entry_list *e = find_entry(path); if (!e) { /* traditionally ls-tree does not complain about * missing path. We may change this later to match @@ -199,12 +203,8 @@ static int list(char **path) { int i; int err = 0; - for (i = 0; path[i]; i++) { - int len = strlen(path[i]); - while (0 <= len && path[i][len] == '/') - len--; - err = err | list_one(path[i], path[i] + len); - } + for (i = 0; path[i]; i++) + err = err | list_one(path[i]); return err; } diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -14,7 +14,7 @@ This test runs git-ls-tree with the foll path2/baz/b - a file in a directory in a directory The new path restriction code should do the right thing for path2 and -path2/baz +path2/baz. Also path0/ should snow nothing. ' . ./test-lib.sh @@ -63,7 +63,7 @@ EOF test_output' test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path' \ 'git-ls-tree $tree path >current && cat >expected <<\EOF && EOF @@ -71,7 +71,7 @@ EOF test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path1 path0' \ 'git-ls-tree $tree path1 path0 >current && cat >expected <<\EOF && 120000 blob X path1 @@ -80,7 +80,14 @@ EOF test_output' test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path0/' \ + 'git-ls-tree $tree path0/ >current && + cat >expected <<\EOF && +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path2' \ 'git-ls-tree $tree path2 >current && cat >expected <<\EOF && 040000 tree X path2 @@ -91,7 +98,7 @@ EOF test_output' test_expect_success \ - 'ls-tree filtered' \ + 'ls-tree filtered with path2/baz' \ 'git-ls-tree $tree path2/baz >current && cat >expected <<\EOF && 040000 tree X path2/baz @@ -99,4 +106,26 @@ test_expect_success \ EOF test_output' +test_expect_success \ + 'ls-tree filtered with path2' \ + 'git-ls-tree $tree path2 >current && + cat >expected <<\EOF && +040000 tree X path2 +040000 tree X path2/baz +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + +test_expect_success \ + 'ls-tree filtered with path2/' \ + 'git-ls-tree $tree path2/ >current && + cat >expected <<\EOF && +040000 tree X path2 +040000 tree X path2/baz +120000 blob X path2/bazbo +100644 blob X path2/foo +EOF + test_output' + test_done diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh new file mode 100644 --- /dev/null +++ b/t/t4010-diff-pathspec.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Pathspec restrictions + +Prepare: + file0 + path1/file1 +' +. ./test-lib.sh +. ../diff-lib.sh ;# test-lib chdir's into trash + +test_expect_success \ + setup \ + 'echo frotz >file0 && + mkdir path1 && + echo rezrov >path1/file1 && + git-update-cache --add file0 path1/file1 && + tree=`git-write-tree` && + echo "$tree" && + echo nitfol >file0 && + echo yomin >path1/file1 && + git-update-cache file0 path1/file1' + +cat >expected <<\EOF +EOF +test_expect_success \ + 'limit to path should show nothing' \ + 'git-diff-cache --cached $tree path >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +EOF +test_expect_success \ + 'limit to path1 should show path1/file1' \ + 'git-diff-cache --cached $tree path1 >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +EOF +test_expect_success \ + 'limit to path1/ should show path1/file1' \ + 'git-diff-cache --cached $tree path1/ >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M file0 +EOF +test_expect_success \ + 'limit to file0 should show file0' \ + 'git-diff-cache --cached $tree file0 >current && + compare_diff_raw current expected' + +cat >expected <<\EOF +EOF +test_expect_success \ + 'limit to file0/ should emit nothing.' \ + 'git-diff-cache --cached $tree file0/ >current && + compare_diff_raw current expected' + +test_done ------------ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] ls-tree: handle trailing slashes in the pathspec properly. 2005-06-01 1:46 ` Junio C Hamano @ 2005-06-01 3:51 ` Linus Torvalds 0 siblings, 0 replies; 12+ messages in thread From: Linus Torvalds @ 2005-06-01 3:51 UTC (permalink / raw) To: Junio C Hamano; +Cc: Git Mailing List On Tue, 31 May 2005, Junio C Hamano wrote: > > BTW could you limit git-apply --stat output to 79 cols not 80? Hmm, I thought I already did, but it turns out it could round up both add/del, causing my 79 to be 80. I think I fixed it. Linus ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] ls-tree: remove trailing slashes properly. 2005-05-31 22:19 ` Linus Torvalds 2005-05-31 22:35 ` Junio C Hamano 2005-05-31 23:18 ` [PATCH] ls-tree: handle trailing slashes in the pathspec properly Junio C Hamano @ 2005-05-31 23:22 ` Junio C Hamano 2 siblings, 0 replies; 12+ messages in thread From: Junio C Hamano @ 2005-05-31 23:22 UTC (permalink / raw) To: Linus Torvalds; +Cc: Git Mailing List Should we do the same for git-ls-files? ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2005-06-01 3:46 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-05-31 15:32 [PATCH] allow pathspec to end with a slash Linus Torvalds 2005-05-31 20:08 ` Junio C Hamano 2005-05-31 21:47 ` [PATCH 1/2] diff: consolidate test helper script pieces Junio C Hamano 2005-05-31 21:48 ` [PATCH 2/2] diff: Fix trailing slash handling Junio C Hamano 2005-05-31 21:49 ` [PATCH] ls-tree: remove trailing slashes properly Junio C Hamano 2005-05-31 22:19 ` Linus Torvalds 2005-05-31 22:35 ` Junio C Hamano 2005-05-31 23:18 ` [PATCH] ls-tree: handle trailing slashes in the pathspec properly Junio C Hamano 2005-05-31 23:48 ` Linus Torvalds 2005-06-01 1:46 ` Junio C Hamano 2005-06-01 3:51 ` Linus Torvalds 2005-05-31 23:22 ` [PATCH] ls-tree: remove trailing slashes properly Junio C Hamano
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox