diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index 3e75cb0cbe..bd11e5acb0 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -4,6 +4,72 @@ test_description='wildmatch tests' . ./test-lib.sh +should_create_test_file() { + file=$1 + + case $file in + # `touch .` will succeed but obviously not do what we intend + # here. + ".") + return 1 + ;; + # We cannot create a file with an empty filename. + "") + return 1 + ;; + # The tests that are testing that e.g. foo//bar is matched by + # foo/*/bar can't be tested on filesystems since there's no + # way we're getting a double slash. + *//*) + return 1 + ;; + # When testing the difference between foo/bar and foo/bar/ we + # can't test the latter. + */) + return 1 + ;; + # On Windows, \ in paths is silently converted to /, which + # would result in the "touch" below working, but the test + # itself failing. See 6fd1106aa4 ("t3700: Skip a test with + # backslashes in pathspec", 2009-03-13) for prior art and + # details. + *\\*) + if ! test_have_prereq BSLASHPSPEC + then + return 1 + fi + # NOTE: The ;;& bash extension is not portable, so + # this test needs to be at the end of the pattern + # list. + # + # If we want to add more conditional returns we either + # need a new case statement, or turn this whole thing + # into a series of "if" tests. + ;; + esac + + + # On Windows proper (i.e. not Cygwin) many file names which + # under Cygwin would be emulated don't work. + if test_have_prereq MINGW + then + case $file in + " ") + # Files called " " are forbidden on Windows + return 1 + ;; + *\<*|*\>*|*:*|*\"*|*\|*|*\?*|*\**) + # Files with various special characters aren't + # allowed on Windows. Sourced from + # https://stackoverflow.com/a/31976060 + return 1 + ;; + esac + fi + + return 0 +} + match_with_function() { text=$1 pattern=$2 @@ -26,25 +92,133 @@ match_with_function() { } +match_with_ls_files() { + text=$1 + pattern=$2 + match_expect=$3 + match_function=$4 + ls_files_args=$5 + + match_stdout_stderr_cmp=" + tr -d '\0' actual && + >expect.err && + test_cmp expect.err actual.err && + test_cmp expect actual" + + if test "$match_expect" = 'E' + then + if test -e .git/created_test_file + then + test_expect_success "$match_function (via ls-files): match dies on '$pattern' '$text'" " + printf '%s' '$text' >expect && + test_must_fail git$ls_files_args ls-files -z -- '$pattern' + " + else + test_expect_failure "$match_function (via ls-files): match skip '$pattern' '$text'" 'false' + fi + elif test "$match_expect" = 1 + then + if test -e .git/created_test_file + then + test_expect_success "$match_function (via ls-files): match '$pattern' '$text'" " + printf '%s' '$text' >expect && + git$ls_files_args ls-files -z -- '$pattern' >actual.raw 2>actual.err && + $match_stdout_stderr_cmp + " + else + test_expect_failure "$match_function (via ls-files): match skip '$pattern' '$text'" 'false' + fi + elif test "$match_expect" = 0 + then + if test -e .git/created_test_file + then + test_expect_success "$match_function (via ls-files): no match '$pattern' '$text'" " + >expect && + git$ls_files_args ls-files -z -- '$pattern' >actual.raw 2>actual.err && + $match_stdout_stderr_cmp + " + else + test_expect_failure "$match_function (via ls-files): no match skip '$pattern' '$text'" 'false' + fi + else + test_expect_success "PANIC: Test framework error. Unknown matches value $match_expect" 'false' + fi +} + match() { - match_glob=$1 - match_iglob=$2 - match_pathmatch=$3 - match_pathmatchi=$4 - text=$5 - pattern=$6 + if test "$#" = 6 + then + # When test-wildmatch and git ls-files produce the same + # result. + match_glob=$1 + match_file_glob=$match_glob + match_iglob=$2 + match_file_iglob=$match_iglob + match_pathmatch=$3 + match_file_pathmatch=$match_pathmatch + match_pathmatchi=$4 + match_file_pathmatchi=$match_pathmatchi + text=$5 + pattern=$6 + elif test "$#" = 10 + then + match_glob=$1 + match_iglob=$2 + match_pathmatch=$3 + match_pathmatchi=$4 + match_file_glob=$5 + match_file_iglob=$6 + match_file_pathmatch=$7 + match_file_pathmatchi=$8 + text=$9 + pattern=${10} + fi + + test_expect_success 'cleanup after previous file test' ' + if test -e .git/created_test_file + then + git reset && + git clean -df + fi + ' + + printf '%s' "$text" >.git/expected_test_file + + test_expect_success "setup match file test for $text" ' + file=$(cat .git/expected_test_file) && + if should_create_test_file "$file" + then + dirs=${file%/*} + if test "$file" != "$dirs" + then + mkdir -p -- "$dirs" && + touch -- "./$text" + else + touch -- "./$file" + fi && + git add -A && + printf "%s" "$file" >.git/created_test_file + elif test -e .git/created_test_file + then + rm .git/created_test_file + fi + ' # $1: Case sensitive glob match: test-wildmatch & ls-files match_with_function "$text" "$pattern" $match_glob "wildmatch" + match_with_ls_files "$text" "$pattern" $match_file_glob "wildmatch" " --glob-pathspecs" # $2: Case insensitive glob match: test-wildmatch & ls-files match_with_function "$text" "$pattern" $match_iglob "iwildmatch" + match_with_ls_files "$text" "$pattern" $match_file_iglob "iwildmatch" " --glob-pathspecs --icase-pathspecs" # $3: Case sensitive path match: test-wildmatch & ls-files match_with_function "$text" "$pattern" $match_pathmatch "pathmatch" + match_with_ls_files "$text" "$pattern" $match_file_pathmatch "pathmatch" "" # $4: Case insensitive path match: test-wildmatch & ls-files match_with_function "$text" "$pattern" $match_pathmatchi "ipathmatch" + match_with_ls_files "$text" "$pattern" $match_file_pathmatchi "ipathmatch" " --icase-pathspecs" } # Basic wildmatch features @@ -113,7 +287,8 @@ match 1 1 1 1 'acrt' 'a[c-c]rt' match 0 0 0 0 ']' '[!]-]' match 1 1 1 1 'a' '[!]-]' match 0 0 0 0 '' '\' -match 0 0 0 0 '\' '\' +match 0 0 0 0 \ + 1 1 1 1 '\' '\' match 0 0 0 0 'XXX/\' '*/\' match 1 1 1 1 'XXX/\' '*/\\' match 1 1 1 1 'foo' 'foo' @@ -127,7 +302,8 @@ match 1 1 1 1 '[ab]' '[[:digit]ab]' match 1 1 1 1 '[ab]' '[\[:]ab]' match 1 1 1 1 '?a?b' '\??\?b' match 1 1 1 1 'abc' '\a\b\c' -match 0 0 0 0 'foo' '' +match 0 0 0 0 \ + E E E E 'foo' '' match 1 1 1 1 'foo/bar/baz/to' '**/t[o]' # Character class tests @@ -157,8 +333,10 @@ match 1 1 1 1 ']' '[\]]' match 0 0 0 0 '\]' '[\]]' match 0 0 0 0 '\' '[\]]' match 0 0 0 0 'ab' 'a[]b' -match 0 0 0 0 'a[]b' 'a[]b' -match 0 0 0 0 'ab[' 'ab[' +match 0 0 0 0 \ + 1 1 1 1 'a[]b' 'a[]b' +match 0 0 0 0 \ + 1 1 1 1 'ab[' 'ab[' match 0 0 0 0 'ab' '[!' match 0 0 0 0 'ab' '[-' match 1 1 1 1 '-' '[-]' @@ -226,7 +404,8 @@ match 1 1 1 1 foo/bar 'foo/*' match 0 0 1 1 foo/bba/arr 'foo/*' match 1 1 1 1 foo/bba/arr 'foo/**' match 0 0 1 1 foo/bba/arr 'foo*' -match 0 0 1 1 foo/bba/arr 'foo**' +match 0 0 1 1 \ + 1 1 1 1 foo/bba/arr 'foo**' match 0 0 1 1 foo/bba/arr 'foo/*arr' match 0 0 1 1 foo/bba/arr 'foo/**arr' match 0 0 0 0 foo/bba/arr 'foo/*z'