diff options
Diffstat (limited to 't')
-rw-r--r-- | t/README | 22 | ||||
-rw-r--r-- | t/helper/test-date.c | 12 | ||||
-rwxr-xr-x | t/interop/i5700-protocol-transition.sh | 68 | ||||
-rw-r--r-- | t/lib-httpd/apache.conf | 7 | ||||
-rwxr-xr-x | t/lib-submodule-update.sh | 350 | ||||
-rwxr-xr-x | t/perf/aggregate.perl | 11 | ||||
-rw-r--r-- | t/perf/lib-pack.sh | 25 | ||||
-rwxr-xr-x | t/perf/p4211-line-log.sh | 4 | ||||
-rwxr-xr-x | t/perf/p5550-fetch-tags.sh | 25 | ||||
-rwxr-xr-x | t/perf/p5551-fetch-rescan.sh | 55 | ||||
-rw-r--r-- | t/perf/perf-lib.sh | 4 | ||||
-rwxr-xr-x | t/perf/run | 89 | ||||
-rw-r--r-- | t/t0021/rot13-filter.pl | 4 | ||||
-rwxr-xr-x | t/t1300-repo-config.sh | 30 | ||||
-rwxr-xr-x | t/t3903-stash.sh | 93 | ||||
-rwxr-xr-x | t/t4202-log.sh | 101 | ||||
-rwxr-xr-x | t/t5601-clone.sh | 78 | ||||
-rwxr-xr-x | t/t5603-clone-dirname.sh | 2 | ||||
-rwxr-xr-x | t/t5700-protocol-v1.sh | 294 | ||||
-rwxr-xr-x | t/t7810-grep.sh | 6 | ||||
-rw-r--r-- | t/test-lib.sh | 2 |
21 files changed, 1005 insertions, 277 deletions
@@ -332,13 +332,10 @@ Writing Tests ------------- The test script is written as a shell script. It should start -with the standard "#!/bin/sh" with copyright notices, and an +with the standard "#!/bin/sh", and an assignment to variable 'test_description', like this: #!/bin/sh - # - # Copyright (c) 2005 Junio C Hamano - # test_description='xxx test (option --frotz) @@ -677,6 +674,11 @@ library for your script to use. <expected> file. This behaves like "cmp" but produces more helpful output when the test is run with "-v" option. + - test_cmp_rev <expected> <actual> + + Check whether the <expected> rev points to the same commit as the + <actual> rev. + - test_line_count (= | -lt | -ge | ...) <length> <file> Check whether a file has the length it is expected to. @@ -808,6 +810,18 @@ use these, and "test_set_prereq" for how to define your own. Git was compiled with support for PCRE. Wrap any tests that use git-grep --perl-regexp or git-grep -P in these. + - LIBPCRE1 + + Git was compiled with PCRE v1 support via + USE_LIBPCRE1=YesPlease. Wrap any PCRE using tests that for some + reason need v1 of the PCRE library instead of v2 in these. + + - LIBPCRE2 + + Git was compiled with PCRE v2 support via + USE_LIBPCRE2=YesPlease. Wrap any PCRE using tests that for some + reason need v2 of the PCRE library instead of v1 in these. + - CASE_INSENSITIVE_FS Test is run on a case insensitive file system. diff --git a/t/helper/test-date.c b/t/helper/test-date.c index f414a3ac67..ac83687970 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -5,6 +5,7 @@ static const char *usage_msg = "\n" " test-date show:<format> [time_t]...\n" " test-date parse [date]...\n" " test-date approxidate [date]...\n" +" test-date timestamp [date]...\n" " test-date is64bit\n" " test-date time_t-is64bit\n"; @@ -71,6 +72,15 @@ static void parse_approxidate(const char **argv, struct timeval *now) } } +static void parse_approx_timestamp(const char **argv, struct timeval *now) +{ + for (; *argv; argv++) { + timestamp_t t; + t = approxidate_relative(*argv, now); + printf("%s -> %"PRItime"\n", *argv, t); + } +} + int cmd_main(int argc, const char **argv) { struct timeval now; @@ -95,6 +105,8 @@ int cmd_main(int argc, const char **argv) parse_dates(argv+1, &now); else if (!strcmp(*argv, "approxidate")) parse_approxidate(argv+1, &now); + else if (!strcmp(*argv, "timestamp")) + parse_approx_timestamp(argv+1, &now); else if (!strcmp(*argv, "is64bit")) return sizeof(timestamp_t) == 8 ? 0 : 1; else if (!strcmp(*argv, "time_t-is64bit")) diff --git a/t/interop/i5700-protocol-transition.sh b/t/interop/i5700-protocol-transition.sh new file mode 100755 index 0000000000..97e8e580ef --- /dev/null +++ b/t/interop/i5700-protocol-transition.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +VERSION_A=. +VERSION_B=v2.0.0 + +: ${LIB_GIT_DAEMON_PORT:=5700} +LIB_GIT_DAEMON_COMMAND='git.b daemon' + +test_description='clone and fetch by client who is trying to use a new protocol' +. ./interop-lib.sh +. "$TEST_DIRECTORY"/lib-git-daemon.sh + +start_git_daemon --export-all + +repo=$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo + +test_expect_success "create repo served by $VERSION_B" ' + git.b init "$repo" && + git.b -C "$repo" commit --allow-empty -m one +' + +test_expect_success "git:// clone with $VERSION_A and protocol v1" ' + GIT_TRACE_PACKET=1 git.a -c protocol.version=1 clone "$GIT_DAEMON_URL/repo" child 2>log && + git.a -C child log -1 --format=%s >actual && + git.b -C "$repo" log -1 --format=%s >expect && + test_cmp expect actual && + grep "version=1" log +' + +test_expect_success "git:// fetch with $VERSION_A and protocol v1" ' + git.b -C "$repo" commit --allow-empty -m two && + git.b -C "$repo" log -1 --format=%s >expect && + + GIT_TRACE_PACKET=1 git.a -C child -c protocol.version=1 fetch 2>log && + git.a -C child log -1 --format=%s FETCH_HEAD >actual && + + test_cmp expect actual && + grep "version=1" log && + ! grep "version 1" log +' + +stop_git_daemon + +test_expect_success "create repo served by $VERSION_B" ' + git.b init parent && + git.b -C parent commit --allow-empty -m one +' + +test_expect_success "file:// clone with $VERSION_A and protocol v1" ' + GIT_TRACE_PACKET=1 git.a -c protocol.version=1 clone --upload-pack="git.b upload-pack" parent child2 2>log && + git.a -C child2 log -1 --format=%s >actual && + git.b -C parent log -1 --format=%s >expect && + test_cmp expect actual && + ! grep "version 1" log +' + +test_expect_success "file:// fetch with $VERSION_A and protocol v1" ' + git.b -C parent commit --allow-empty -m two && + git.b -C parent log -1 --format=%s >expect && + + GIT_TRACE_PACKET=1 git.a -C child2 -c protocol.version=1 fetch --upload-pack="git.b upload-pack" 2>log && + git.a -C child2 log -1 --format=%s FETCH_HEAD >actual && + + test_cmp expect actual && + ! grep "version 1" log +' + +test_done diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 0642ae7e6e..df19436314 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -67,6 +67,9 @@ LockFile accept.lock <IfModule !mod_unixd.c> LoadModule unixd_module modules/mod_unixd.so </IfModule> +<IfModule !mod_setenvif.c> + LoadModule setenvif_module modules/mod_setenvif.so +</IfModule> </IfVersion> PassEnv GIT_VALGRIND @@ -76,6 +79,10 @@ PassEnv ASAN_OPTIONS PassEnv GIT_TRACE PassEnv GIT_CONFIG_NOSYSTEM +<IfVersion >= 2.4> + SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0 +</IfVersion> + Alias /dumb/ www/ Alias /auth/dumb/ www/auth/dumb/ diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh index bb94c23209..38dadd2c29 100755 --- a/t/lib-submodule-update.sh +++ b/t/lib-submodule-update.sh @@ -554,6 +554,10 @@ test_submodule_switch_common() { # - if succeeds, once "git submodule update" is invoked, the contents of # submodule directories are updated # +# If the command under test is known to not work with submodules in certain +# conditions, set the appropriate KNOWN_FAILURE_* variable used in the tests +# below to 1. +# # Use as follows: # # my_func () { @@ -622,19 +626,11 @@ test_submodule_forced_switch () { # - Removing a submodule with a git directory absorbs the submodules # git directory first into the superproject. -test_submodule_switch_recursing_with_args () { - cmd_args="$1" - command="git $cmd_args --recurse-submodules" - RESULTDS=success - if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 - then - RESULTDS=failure - fi - RESULTOI=success - if test "$KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED" = 1 - then - RESULTOI=failure - fi +# Internal function; use test_submodule_switch_recursing_with_args() or +# test_submodule_forced_switch_recursing_with_args() instead. +test_submodule_recursing_with_args_common() { + command="$1" + ######################### Appearing submodule ######################### # Switching to a commit letting a submodule appear checks it out ... test_expect_success "$command: added submodule is checked out" ' @@ -648,7 +644,7 @@ test_submodule_switch_recursing_with_args () { test_submodule_content sub1 origin/add_sub1 ) ' - # ... ignoring an empty existing directory ... + # ... ignoring an empty existing directory. test_expect_success "$command: added submodule is checked out in empty dir" ' prolog && reset_work_tree_to_interested no_submodule && @@ -661,34 +657,23 @@ test_submodule_switch_recursing_with_args () { test_submodule_content sub1 origin/add_sub1 ) ' - # ... unless there is an untracked file in its place. - test_expect_success "$command: added submodule doesn't remove untracked file with same name" ' - prolog && - reset_work_tree_to_interested no_submodule && - ( - cd submodule_update && - git branch -t add_sub1 origin/add_sub1 && - : >sub1 && - test_must_fail $command add_sub1 && - test_superproject_content origin/no_submodule && - test_must_be_empty sub1 - ) - ' - # ... but an ignored file is fine. - test_expect_$RESULTOI "$command: added submodule removes an untracked ignored file" ' - test_when_finished "rm submodule_update/.git/info/exclude" && + test_expect_success "$command: submodule branch is not changed, detach HEAD instead" ' prolog && - reset_work_tree_to_interested no_submodule && + reset_work_tree_to_interested add_sub1 && ( cd submodule_update && - git branch -t add_sub1 origin/add_sub1 && - : >sub1 && - echo sub1 >.git/info/exclude - $command add_sub1 && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 + git -C sub1 checkout -b keep_branch && + git -C sub1 rev-parse HEAD >expect && + git branch -t check-keep origin/modify_sub1 && + $command check-keep && + test_superproject_content origin/modify_sub1 && + test_submodule_content sub1 origin/modify_sub1 && + git -C sub1 rev-parse keep_branch >actual && + test_cmp expect actual && + test_must_fail git -C sub1 symbolic-ref HEAD ) ' + # Replacing a tracked file with a submodule produces a checked out submodule test_expect_success "$command: replace tracked file with submodule checks out submodule" ' prolog && @@ -742,33 +727,6 @@ test_submodule_switch_recursing_with_args () { test_git_directory_exists sub1 ) ' - # Replacing a submodule with files in a directory must succeeds - # when the submodule is clean - test_expect_$RESULTDS "$command: replace submodule with a directory" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && - $command replace_sub1_with_directory && - test_superproject_content origin/replace_sub1_with_directory && - test_submodule_content sub1 origin/replace_sub1_with_directory - ) - ' - # ... absorbing a .git directory. - test_expect_$RESULTDS "$command: replace submodule containing a .git directory with a directory must absorb the git dir" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && - replace_gitfile_with_git_dir sub1 && - rm -rf .git/modules && - $command replace_sub1_with_directory && - test_superproject_content origin/replace_sub1_with_directory && - test_git_directory_exists sub1 - ) - ' # Replacing it with a file ... test_expect_success "$command: replace submodule with a file" ' @@ -782,7 +740,11 @@ test_submodule_switch_recursing_with_args () { test -f sub1 ) ' - + RESULTDS=success + if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 + then + RESULTDS=failure + fi # ... must check its local work tree for untracked files test_expect_$RESULTDS "$command: replace submodule with a file must fail with untracked files" ' prolog && @@ -794,21 +756,7 @@ test_submodule_switch_recursing_with_args () { test_must_fail $command replace_sub1_with_file && test_superproject_content origin/add_sub1 && test_submodule_content sub1 origin/add_sub1 - ) - ' - - # ... and ignored files are ignored - test_expect_success "$command: replace submodule with a file works ignores ignored files in submodule" ' - test_when_finished "rm submodule_update/.git/modules/sub1/info/exclude" && - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t replace_sub1_with_file origin/replace_sub1_with_file && - : >sub1/ignored && - $command replace_sub1_with_file && - test_superproject_content origin/replace_sub1_with_file && - test -f sub1 + test -f sub1/untracked_file ) ' @@ -825,19 +773,6 @@ test_submodule_switch_recursing_with_args () { test_submodule_content sub1 origin/modify_sub1 ) ' - - test_expect_success "git -c submodule.recurse=true $cmd_args: modified submodule updates submodule work tree" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t modify_sub1 origin/modify_sub1 && - git -c submodule.recurse=true $cmd_args modify_sub1 && - test_superproject_content origin/modify_sub1 && - test_submodule_content sub1 origin/modify_sub1 - ) - ' - # Updating a submodule to an invalid sha1 doesn't update the # superproject nor the submodule's work tree. test_expect_success "$command: updating to a missing submodule commit fails" ' @@ -851,126 +786,166 @@ test_submodule_switch_recursing_with_args () { test_submodule_content sub1 origin/add_sub1 ) ' - - # recursing deeper than one level doesn't work yet. - test_expect_success "$command: modified submodule updates submodule recursively" ' - prolog && - reset_work_tree_to_interested add_nested_sub && - ( - cd submodule_update && - git branch -t modify_sub1_recursively origin/modify_sub1_recursively && - $command modify_sub1_recursively && - test_superproject_content origin/modify_sub1_recursively && - test_submodule_content sub1 origin/modify_sub1_recursively && - test_submodule_content -C sub1 sub2 origin/modify_sub1_recursively - ) - ' } -# Test that submodule contents are updated when switching between commits -# that change a submodule, but throwing away local changes in -# the superproject as well as the submodule is allowed. -test_submodule_forced_switch_recursing_with_args () { +# Declares and invokes several tests that, in various situations, checks that +# the provided Git command, when invoked with --recurse-submodules: +# - succeeds in updating the worktree and index of a superproject to a target +# commit, or fails atomically (depending on the test situation) +# - if succeeds, the contents of submodule directories are updated +# +# Specify the Git command so that "git $GIT_COMMAND --recurse-submodules" +# works. +# +# If the command under test is known to not work with submodules in certain +# conditions, set the appropriate KNOWN_FAILURE_* variable used in the tests +# below to 1. +# +# Use as follows: +# +# test_submodule_switch_recursing_with_args "$GIT_COMMAND" +test_submodule_switch_recursing_with_args () { cmd_args="$1" command="git $cmd_args --recurse-submodules" - RESULT=success + test_submodule_recursing_with_args_common "$command" + + RESULTDS=success if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 then - RESULT=failure + RESULTDS=failure fi - ######################### Appearing submodule ######################### - # Switching to a commit letting a submodule appear creates empty dir ... - test_expect_success "$command: added submodule is checked out" ' + RESULTOI=success + if test "$KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED" = 1 + then + RESULTOI=failure + fi + # Switching to a commit letting a submodule appear cannot override an + # untracked file. + test_expect_success "$command: added submodule doesn't remove untracked file with same name" ' prolog && reset_work_tree_to_interested no_submodule && ( cd submodule_update && git branch -t add_sub1 origin/add_sub1 && - $command add_sub1 && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 + : >sub1 && + test_must_fail $command add_sub1 && + test_superproject_content origin/no_submodule && + test_must_be_empty sub1 ) ' - # ... and doesn't care if it already exists ... - test_expect_success "$command: added submodule ignores empty directory" ' + # ... but an ignored file is fine. + test_expect_$RESULTOI "$command: added submodule removes an untracked ignored file" ' + test_when_finished "rm submodule_update/.git/info/exclude" && prolog && reset_work_tree_to_interested no_submodule && ( cd submodule_update && git branch -t add_sub1 origin/add_sub1 && - mkdir sub1 && + : >sub1 && + echo sub1 >.git/info/exclude $command add_sub1 && test_superproject_content origin/add_sub1 && test_submodule_content sub1 origin/add_sub1 ) ' - # ... not caring about an untracked file either - test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" ' + + # Replacing a submodule with files in a directory must succeeds + # when the submodule is clean + test_expect_$RESULTDS "$command: replace submodule with a directory" ' prolog && - reset_work_tree_to_interested no_submodule && + reset_work_tree_to_interested add_sub1 && ( cd submodule_update && - git branch -t add_sub1 origin/add_sub1 && - >sub1 && - $command add_sub1 && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 + git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && + $command replace_sub1_with_directory && + test_superproject_content origin/replace_sub1_with_directory && + test_submodule_content sub1 origin/replace_sub1_with_directory ) ' - # Replacing a tracked file with a submodule checks out the submodule - test_expect_success "$command: replace tracked file with submodule populates the submodule" ' + # ... absorbing a .git directory. + test_expect_$RESULTDS "$command: replace submodule containing a .git directory with a directory must absorb the git dir" ' prolog && - reset_work_tree_to_interested replace_sub1_with_file && + reset_work_tree_to_interested add_sub1 && ( cd submodule_update && - git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 && - $command replace_file_with_sub1 && - test_superproject_content origin/replace_file_with_sub1 && - test_submodule_content sub1 origin/replace_file_with_sub1 + git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory && + replace_gitfile_with_git_dir sub1 && + rm -rf .git/modules && + $command replace_sub1_with_directory && + test_superproject_content origin/replace_sub1_with_directory && + test_git_directory_exists sub1 ) ' - # ... as does removing a directory with tracked files with a - # submodule. - test_expect_success "$command: replace directory with submodule" ' + + # ... and ignored files are ignored + test_expect_success "$command: replace submodule with a file works ignores ignored files in submodule" ' + test_when_finished "rm submodule_update/.git/modules/sub1/info/exclude" && prolog && - reset_work_tree_to_interested replace_sub1_with_directory && + reset_work_tree_to_interested add_sub1 && ( cd submodule_update && - git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 && - $command replace_directory_with_sub1 && - test_superproject_content origin/replace_directory_with_sub1 && - test_submodule_content sub1 origin/replace_directory_with_sub1 + git branch -t replace_sub1_with_file origin/replace_sub1_with_file && + : >sub1/ignored && + $command replace_sub1_with_file && + test_superproject_content origin/replace_sub1_with_file && + test -f sub1 ) ' - ######################## Disappearing submodule ####################### - # Removing a submodule doesn't remove its work tree ... - test_expect_success "$command: removed submodule leaves submodule directory and its contents in place" ' + test_expect_success "git -c submodule.recurse=true $cmd_args: modified submodule updates submodule work tree" ' prolog && reset_work_tree_to_interested add_sub1 && ( cd submodule_update && - git branch -t remove_sub1 origin/remove_sub1 && - $command remove_sub1 && - test_superproject_content origin/remove_sub1 && - ! test -e sub1 + git branch -t modify_sub1 origin/modify_sub1 && + git -c submodule.recurse=true $cmd_args modify_sub1 && + test_superproject_content origin/modify_sub1 && + test_submodule_content sub1 origin/modify_sub1 ) ' - # ... especially when it contains a .git directory. - test_expect_success "$command: removed submodule leaves submodule containing a .git directory alone" ' + + # recursing deeper than one level doesn't work yet. + test_expect_success "$command: modified submodule updates submodule recursively" ' prolog && - reset_work_tree_to_interested add_sub1 && + reset_work_tree_to_interested add_nested_sub && ( cd submodule_update && - git branch -t remove_sub1 origin/remove_sub1 && - replace_gitfile_with_git_dir sub1 && - rm -rf .git/modules/sub1 && - $command remove_sub1 && - test_superproject_content origin/remove_sub1 && - test_git_directory_exists sub1 && - ! test -e sub1 + git branch -t modify_sub1_recursively origin/modify_sub1_recursively && + $command modify_sub1_recursively && + test_superproject_content origin/modify_sub1_recursively && + test_submodule_content sub1 origin/modify_sub1_recursively && + test_submodule_content -C sub1 sub2 origin/modify_sub1_recursively + ) + ' +} + +# Same as test_submodule_switch_recursing_with_args(), except that throwing +# away local changes in the superproject is allowed. +test_submodule_forced_switch_recursing_with_args () { + cmd_args="$1" + command="git $cmd_args --recurse-submodules" + test_submodule_recursing_with_args_common "$command" + + RESULT=success + if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 + then + RESULT=failure + fi + # Switching to a commit letting a submodule appear does not care about + # an untracked file. + test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" ' + prolog && + reset_work_tree_to_interested no_submodule && + ( + cd submodule_update && + git branch -t add_sub1 origin/add_sub1 && + >sub1 && + $command add_sub1 && + test_superproject_content origin/add_sub1 && + test_submodule_content sub1 origin/add_sub1 ) ' + # Replacing a submodule with files in a directory ... test_expect_success "$command: replace submodule with a directory" ' prolog && @@ -997,17 +972,6 @@ test_submodule_forced_switch_recursing_with_args () { test_git_directory_exists sub1 ) ' - # Replacing it with a file - test_expect_success "$command: replace submodule with a file" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t replace_sub1_with_file origin/replace_sub1_with_file && - $command replace_sub1_with_file && - test_superproject_content origin/replace_sub1_with_file - ) - ' # ... even if the submodule contains ignored files test_expect_success "$command: replace submodule with a file ignoring ignored files" ' @@ -1022,46 +986,6 @@ test_submodule_forced_switch_recursing_with_args () { ) ' - # ... but stops for untracked files that would be lost - test_expect_$RESULT "$command: replace submodule with a file stops for untracked files" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t replace_sub1_with_file origin/replace_sub1_with_file && - : >sub1/untracked_file && - test_must_fail $command replace_sub1_with_file && - test_superproject_content origin/add_sub1 && - test -f sub1/untracked_file - ) - ' - - ########################## Modified submodule ######################### - # Updating a submodule sha1 updates the submodule's work tree - test_expect_success "$command: modified submodule updates submodule work tree" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t modify_sub1 origin/modify_sub1 && - $command modify_sub1 && - test_superproject_content origin/modify_sub1 && - test_submodule_content sub1 origin/modify_sub1 - ) - ' - # Updating a submodule to an invalid sha1 doesn't update the - # submodule's work tree, subsequent update will fail - test_expect_success "$command: modified submodule does not update submodule work tree to invalid commit" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git branch -t invalid_sub1 origin/invalid_sub1 && - test_must_fail $command invalid_sub1 && - test_superproject_content origin/add_sub1 && - test_submodule_content sub1 origin/add_sub1 - ) - ' # Updating a submodule from an invalid sha1 updates test_expect_success "$command: modified submodule does update submodule work tree from invalid commit" ' prolog && diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl index 1dbc85b214..e401208488 100755 --- a/t/perf/aggregate.perl +++ b/t/perf/aggregate.perl @@ -69,12 +69,17 @@ if (not @tests) { @tests = glob "p????-*.sh"; } +my $resultsdir = "test-results"; +if ($ENV{GIT_PERF_SUBSECTION} ne "") { + $resultsdir .= "/" . $ENV{GIT_PERF_SUBSECTION}; +} + my @subtests; my %shorttests; for my $t (@tests) { $t =~ s{(?:.*/)?(p(\d+)-[^/]+)\.sh$}{$1} or die "bad test name: $t"; my $n = $2; - my $fname = "test-results/$t.subtests"; + my $fname = "$resultsdir/$t.subtests"; open my $fp, "<", $fname or die "cannot open $fname: $!"; for (<$fp>) { chomp; @@ -98,7 +103,7 @@ sub read_descr { my %descrs; my $descrlen = 4; # "Test" for my $t (@subtests) { - $descrs{$t} = $shorttests{$t}.": ".read_descr("test-results/$t.descr"); + $descrs{$t} = $shorttests{$t}.": ".read_descr("$resultsdir/$t.descr"); $descrlen = length $descrs{$t} if length $descrs{$t}>$descrlen; } @@ -138,7 +143,7 @@ for my $t (@subtests) { my $firstr; for my $i (0..$#dirs) { my $d = $dirs[$i]; - $times{$prefixes{$d}.$t} = [get_times("test-results/$prefixes{$d}$t.times")]; + $times{$prefixes{$d}.$t} = [get_times("$resultsdir/$prefixes{$d}$t.times")]; my ($r,$u,$s) = @{$times{$prefixes{$d}.$t}}; my $w = length format_times($r,$u,$s,$firstr); $colwidth[$i] = $w if $w > $colwidth[$i]; diff --git a/t/perf/lib-pack.sh b/t/perf/lib-pack.sh new file mode 100644 index 0000000000..d3865db286 --- /dev/null +++ b/t/perf/lib-pack.sh @@ -0,0 +1,25 @@ +# Helpers for dealing with large numbers of packs. + +# create $1 nonsense packs, each with a single blob +create_packs () { + perl -le ' + my ($n) = @ARGV; + for (1..$n) { + print "blob"; + print "data <<EOF"; + print "$_"; + print "EOF"; + print "checkpoint" + } + ' "$@" | + git fast-import +} + +# create a large number of packs, disabling any gc which might +# cause us to repack them +setup_many_packs () { + git config gc.auto 0 && + git config gc.autopacklimit 0 && + git config fastimport.unpacklimit 0 && + create_packs 500 +} diff --git a/t/perf/p4211-line-log.sh b/t/perf/p4211-line-log.sh index e0ed05907c..392bcc0e51 100755 --- a/t/perf/p4211-line-log.sh +++ b/t/perf/p4211-line-log.sh @@ -35,4 +35,8 @@ test_perf 'git log --oneline --raw --parents' ' git log --oneline --raw --parents >/dev/null ' +test_perf 'git log --oneline --raw --parents -1000' ' + git log --oneline --raw --parents -1000 >/dev/null +' + test_done diff --git a/t/perf/p5550-fetch-tags.sh b/t/perf/p5550-fetch-tags.sh index a5dc39f86a..d0e0e019ea 100755 --- a/t/perf/p5550-fetch-tags.sh +++ b/t/perf/p5550-fetch-tags.sh @@ -20,6 +20,7 @@ start to show a noticeable performance problem on my machine, but without taking too long to set up and run the tests. ' . ./perf-lib.sh +. "$TEST_DIRECTORY/perf/lib-pack.sh" # make a long nonsense history on branch $1, consisting of $2 commits, each # with a unique file pointing to the blob at $2. @@ -44,26 +45,6 @@ create_tags () { git update-ref --stdin } -# create $1 nonsense packs, each with a single blob -create_packs () { - perl -le ' - my ($n) = @ARGV; - for (1..$n) { - print "blob"; - print "data <<EOF"; - print "$_"; - print "EOF"; - } - ' "$@" | - git fast-import && - - git cat-file --batch-all-objects --batch-check='%(objectname)' | - while read sha1 - do - echo $sha1 | git pack-objects .git/objects/pack/pack - done -} - test_expect_success 'create parent and child' ' git init parent && git -C parent commit --allow-empty -m base && @@ -84,9 +65,7 @@ test_expect_success 'populate parent tags' ' test_expect_success 'create child packs' ' ( cd child && - git config gc.auto 0 && - git config gc.autopacklimit 0 && - create_packs 500 + setup_many_packs ) ' diff --git a/t/perf/p5551-fetch-rescan.sh b/t/perf/p5551-fetch-rescan.sh new file mode 100755 index 0000000000..b99dc23e32 --- /dev/null +++ b/t/perf/p5551-fetch-rescan.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +test_description='fetch performance with many packs + +It is common for fetch to consider objects that we might not have, and it is an +easy mistake for the code to use a function like `parse_object` that might +give the correct _answer_ on such an object, but do so slowly (due to +re-scanning the pack directory for lookup failures). + +The resulting performance drop can be hard to notice in a real repository, but +becomes quite large in a repository with a large number of packs. So this +test creates a more pathological case, since any mistakes would produce a more +noticeable slowdown. +' +. ./perf-lib.sh +. "$TEST_DIRECTORY"/perf/lib-pack.sh + +test_expect_success 'create parent and child' ' + git init parent && + git clone parent child +' + + +test_expect_success 'create refs in the parent' ' + ( + cd parent && + git commit --allow-empty -m foo && + head=$(git rev-parse HEAD) && + test_seq 1000 | + sed "s,.*,update refs/heads/& $head," | + $MODERN_GIT update-ref --stdin + ) +' + +test_expect_success 'create many packs in the child' ' + ( + cd child && + setup_many_packs + ) +' + +test_perf 'fetch' ' + # start at the same state for each iteration + obj=$($MODERN_GIT -C parent rev-parse HEAD) && + ( + cd child && + $MODERN_GIT for-each-ref --format="delete %(refname)" refs/remotes | + $MODERN_GIT update-ref --stdin && + rm -vf .git/objects/$(echo $obj | sed "s|^..|&/|") && + + git fetch + ) +' + +test_done diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index b50211b259..e4c343a6b7 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -56,12 +56,10 @@ MODERN_GIT=$GIT_BUILD_DIR/bin-wrappers/git export MODERN_GIT perf_results_dir=$TEST_OUTPUT_DIRECTORY/test-results +test -n "$GIT_PERF_SUBSECTION" && perf_results_dir="$perf_results_dir/$GIT_PERF_SUBSECTION" mkdir -p "$perf_results_dir" rm -f "$perf_results_dir"/$(basename "$0" .sh).subtests -if test -z "$GIT_PERF_REPEAT_COUNT"; then - GIT_PERF_REPEAT_COUNT=3 -fi die_if_build_dir_not_repo () { if ! ( cd "$TEST_DIRECTORY/.." && git rev-parse --build-dir >/dev/null 2>&1 ); then diff --git a/t/perf/run b/t/perf/run index beb4acc0e4..43e4de49ef 100755 --- a/t/perf/run +++ b/t/perf/run @@ -2,9 +2,14 @@ case "$1" in --help) - echo "usage: $0 [other_git_tree...] [--] [test_scripts]" + echo "usage: $0 [--config file] [other_git_tree...] [--] [test_scripts]" exit 0 ;; + --config) + shift + GIT_PERF_CONFIG_FILE=$(cd "$(dirname "$1")"; pwd)/$(basename "$1") + export GIT_PERF_CONFIG_FILE + shift ;; esac die () { @@ -29,8 +34,10 @@ unpack_git_rev () { (cd "$(git rev-parse --show-cdup)" && git archive --format=tar $rev) | (cd build/$rev && tar x) } + build_git_rev () { rev=$1 + name="$2" for config in config.mak config.mak.autogen config.status do if test -e "../../$config" @@ -38,7 +45,7 @@ build_git_rev () { cp "../../$config" "build/$rev/" fi done - echo "=== Building $rev ===" + echo "=== Building $rev ($name) ===" ( cd build/$rev && if test -n "$GIT_PERF_MAKE_COMMAND" @@ -65,7 +72,7 @@ run_dirs_helper () { if [ ! -d build/$rev ]; then unpack_git_rev $rev fi - build_git_rev $rev + build_git_rev $rev "$mydir" mydir=build/$rev fi if test "$mydir" = .; then @@ -87,14 +94,78 @@ run_dirs () { done } -GIT_PERF_AGGREGATING_LATER=t -export GIT_PERF_AGGREGATING_LATER +get_subsections () { + section="$1" + test -z "$GIT_PERF_CONFIG_FILE" && return + git config -f "$GIT_PERF_CONFIG_FILE" --name-only --get-regex "$section\..*\.[^.]+" | + sed -e "s/$section\.\(.*\)\..*/\1/" | sort | uniq +} + +get_var_from_env_or_config () { + env_var="$1" + conf_sec="$2" + conf_var="$3" + # $4 can be set to a default value + + # Do nothing if the env variable is already set + eval "test -z \"\${$env_var+x}\"" || return + + test -z "$GIT_PERF_CONFIG_FILE" && return + + # Check if the variable is in the config file + if test -n "$GIT_PERF_SUBSECTION" + then + var="$conf_sec.$GIT_PERF_SUBSECTION.$conf_var" + conf_value=$(git config -f "$GIT_PERF_CONFIG_FILE" "$var") && + eval "$env_var=\"$conf_value\"" && return + fi + var="$conf_sec.$conf_var" + conf_value=$(git config -f "$GIT_PERF_CONFIG_FILE" "$var") && + eval "$env_var=\"$conf_value\"" && return + + test -n "${4+x}" && eval "$env_var=\"$4\"" +} + +run_subsection () { + get_var_from_env_or_config "GIT_PERF_REPEAT_COUNT" "perf" "repeatCount" 3 + export GIT_PERF_REPEAT_COUNT + + get_var_from_env_or_config "GIT_PERF_DIRS_OR_REVS" "perf" "dirsOrRevs" + set -- $GIT_PERF_DIRS_OR_REVS "$@" + + get_var_from_env_or_config "GIT_PERF_MAKE_COMMAND" "perf" "makeCommand" + get_var_from_env_or_config "GIT_PERF_MAKE_OPTS" "perf" "makeOpts" + + GIT_PERF_AGGREGATING_LATER=t + export GIT_PERF_AGGREGATING_LATER + + if test $# = 0 -o "$1" = -- -o -f "$1"; then + set -- . "$@" + fi + + run_dirs "$@" + ./aggregate.perl "$@" +} cd "$(dirname $0)" . ../../GIT-BUILD-OPTIONS -if test $# = 0 -o "$1" = -- -o -f "$1"; then - set -- . "$@" +mkdir -p test-results +get_subsections "perf" >test-results/run_subsections.names + +if test $(wc -l <test-results/run_subsections.names) -eq 0 +then + ( + run_subsection "$@" + ) +else + while read -r subsec + do + ( + GIT_PERF_SUBSECTION="$subsec" + export GIT_PERF_SUBSECTION + echo "======== Run for subsection '$GIT_PERF_SUBSECTION' ========" + run_subsection "$@" + ) + done <test-results/run_subsections.names fi -run_dirs "$@" -./aggregate.perl "$@" diff --git a/t/t0021/rot13-filter.pl b/t/t0021/rot13-filter.pl index 6fd7fa476b..f1678851de 100644 --- a/t/t0021/rot13-filter.pl +++ b/t/t0021/rot13-filter.pl @@ -70,7 +70,7 @@ print $debug "init handshake complete\n"; $debug->flush(); while (1) { - my ( $res, $command ) = packet_required_key_val_read("command"); + my ( $res, $command ) = packet_key_val_read("command"); if ( $res == -1 ) { print $debug "STOP\n"; exit(); @@ -106,7 +106,7 @@ while (1) { packet_txt_write("status=success"); packet_flush(); } else { - my ( $res, $pathname ) = packet_required_key_val_read("pathname"); + my ( $res, $pathname ) = packet_key_val_read("pathname"); if ( $res == -1 ) { die "unexpected EOF while expecting pathname"; } diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 364a537000..cbeb9bebee 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -901,6 +901,36 @@ test_expect_success 'get --path barfs on boolean variable' ' test_must_fail git config --get --path path.bool ' +test_expect_success 'get --expiry-date' ' + rel="3.weeks.5.days.00:00" && + rel_out="$rel ->" && + cat >.git/config <<-\EOF && + [date] + valid1 = "3.weeks.5.days 00:00" + valid2 = "Fri Jun 4 15:46:55 2010" + valid3 = "2017/11/11 11:11:11PM" + valid4 = "2017/11/10 09:08:07 PM" + valid5 = "never" + invalid1 = "abc" + EOF + cat >expect <<-EOF && + $(test-date timestamp $rel) + 1275666415 + 1510441871 + 1510348087 + 0 + EOF + { + echo "$rel_out $(git config --expiry-date date.valid1)" + git config --expiry-date date.valid2 && + git config --expiry-date date.valid3 && + git config --expiry-date date.valid4 && + git config --expiry-date date.valid5 + } >actual && + test_cmp expect actual && + test_must_fail git config --expiry-date date.invalid1 +' + cat > expect << EOF [quote] leading = " test" diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 3b1ac1971a..39c7f2ebd7 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -804,6 +804,99 @@ test_expect_success 'push -m shows right message' ' test_cmp expect actual ' +test_expect_success 'push -m also works without space' ' + >foo && + git add foo && + git stash push -m"unspaced test message" && + echo "stash@{0}: On master: unspaced test message" >expect && + git stash list -1 >actual && + test_cmp expect actual +' + +test_expect_success 'store -m foo shows right message' ' + git stash clear && + git reset --hard && + echo quux >bazzy && + git add bazzy && + STASH_ID=$(git stash create) && + git stash store -m "store m" $STASH_ID && + echo "stash@{0}: store m" >expect && + git stash list -1 >actual && + test_cmp expect actual +' + +test_expect_success 'store -mfoo shows right message' ' + git stash clear && + git reset --hard && + echo quux >bazzy && + git add bazzy && + STASH_ID=$(git stash create) && + git stash store -m"store mfoo" $STASH_ID && + echo "stash@{0}: store mfoo" >expect && + git stash list -1 >actual && + test_cmp expect actual +' + +test_expect_success 'store --message=foo shows right message' ' + git stash clear && + git reset --hard && + echo quux >bazzy && + git add bazzy && + STASH_ID=$(git stash create) && + git stash store --message="store message=foo" $STASH_ID && + echo "stash@{0}: store message=foo" >expect && + git stash list -1 >actual && + test_cmp expect actual +' + +test_expect_success 'store --message foo shows right message' ' + git stash clear && + git reset --hard && + echo quux >bazzy && + git add bazzy && + STASH_ID=$(git stash create) && + git stash store --message "store message foo" $STASH_ID && + echo "stash@{0}: store message foo" >expect && + git stash list -1 >actual && + test_cmp expect actual +' + +test_expect_success 'push -mfoo uses right message' ' + >foo && + git add foo && + git stash push -m"test mfoo" && + echo "stash@{0}: On master: test mfoo" >expect && + git stash list -1 >actual && + test_cmp expect actual +' + +test_expect_success 'push --message foo is synonym for -mfoo' ' + >foo && + git add foo && + git stash push --message "test message foo" && + echo "stash@{0}: On master: test message foo" >expect && + git stash list -1 >actual && + test_cmp expect actual +' + +test_expect_success 'push --message=foo is synonym for -mfoo' ' + >foo && + git add foo && + git stash push --message="test message=foo" && + echo "stash@{0}: On master: test message=foo" >expect && + git stash list -1 >actual && + test_cmp expect actual +' + +test_expect_success 'push -m shows right message' ' + >foo && + git add foo && + git stash push -m "test m foo" && + echo "stash@{0}: On master: test m foo" >expect && + git stash list -1 >actual && + test_cmp expect actual +' + test_expect_success 'create stores correct message' ' >foo && git add foo && diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 8f155da7a5..25b1f8cc73 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -737,6 +737,107 @@ test_expect_success 'log.decorate configuration' ' ' +test_expect_success 'decorate-refs with glob' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach + Merge-tags-octopus-a-and-octopus-b + seventh + octopus-b (octopus-b) + octopus-a (octopus-a) + reach + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs="heads/octopus*" >actual && + test_cmp expect.decorate actual +' + +test_expect_success 'decorate-refs without globs' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach + Merge-tags-octopus-a-and-octopus-b + seventh + octopus-b + octopus-a + reach (tag: reach) + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs="tags/reach" >actual && + test_cmp expect.decorate actual +' + +test_expect_success 'multiple decorate-refs' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach + Merge-tags-octopus-a-and-octopus-b + seventh + octopus-b (octopus-b) + octopus-a (octopus-a) + reach (tag: reach) + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs="heads/octopus*" \ + --decorate-refs="tags/reach" >actual && + test_cmp expect.decorate actual +' + +test_expect_success 'decorate-refs-exclude with glob' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach (HEAD -> master) + Merge-tags-octopus-a-and-octopus-b + seventh (tag: seventh) + octopus-b (tag: octopus-b) + octopus-a (tag: octopus-a) + reach (tag: reach, reach) + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs-exclude="heads/octopus*" >actual && + test_cmp expect.decorate actual +' + +test_expect_success 'decorate-refs-exclude without globs' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach (HEAD -> master) + Merge-tags-octopus-a-and-octopus-b + seventh (tag: seventh) + octopus-b (tag: octopus-b, octopus-b) + octopus-a (tag: octopus-a, octopus-a) + reach (reach) + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs-exclude="tags/reach" >actual && + test_cmp expect.decorate actual +' + +test_expect_success 'multiple decorate-refs-exclude' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach (HEAD -> master) + Merge-tags-octopus-a-and-octopus-b + seventh (tag: seventh) + octopus-b (tag: octopus-b) + octopus-a (tag: octopus-a) + reach (reach) + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs-exclude="heads/octopus*" \ + --decorate-refs-exclude="tags/reach" >actual && + test_cmp expect.decorate actual +' + +test_expect_success 'decorate-refs and decorate-refs-exclude' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach (master) + Merge-tags-octopus-a-and-octopus-b + seventh + octopus-b + octopus-a + reach (reach) + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs="heads/*" \ + --decorate-refs-exclude="heads/oc*" >actual && + test_cmp expect.decorate actual +' + test_expect_success 'log.decorate config parsing' ' git log --oneline --decorate=full >expect.full && git log --oneline --decorate=short >expect.short && diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index 50e40abb11..0f895478f0 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -306,23 +306,21 @@ test_expect_success 'clone checking out a tag' ' test_cmp fetch.expected fetch.actual ' -setup_ssh_wrapper () { - test_expect_success 'setup ssh wrapper' ' - rm -f "$TRASH_DIRECTORY/ssh-wrapper$X" && - cp "$GIT_BUILD_DIR/t/helper/test-fake-ssh$X" \ - "$TRASH_DIRECTORY/ssh-wrapper$X" && - GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper$X" && - export GIT_SSH && - export TRASH_DIRECTORY && - >"$TRASH_DIRECTORY"/ssh-output - ' -} +test_expect_success 'set up ssh wrapper' ' + cp "$GIT_BUILD_DIR/t/helper/test-fake-ssh$X" \ + "$TRASH_DIRECTORY/ssh$X" && + GIT_SSH="$TRASH_DIRECTORY/ssh$X" && + export GIT_SSH && + export TRASH_DIRECTORY && + >"$TRASH_DIRECTORY"/ssh-output +' copy_ssh_wrapper_as () { rm -f "${1%$X}$X" && - cp "$TRASH_DIRECTORY/ssh-wrapper$X" "${1%$X}$X" && + cp "$TRASH_DIRECTORY/ssh$X" "${1%$X}$X" && + test_when_finished "rm $(git rev-parse --sq-quote "${1%$X}$X")" && GIT_SSH="${1%$X}$X" && - export GIT_SSH + test_when_finished "GIT_SSH=\"\$TRASH_DIRECTORY/ssh\$X\"" } expect_ssh () { @@ -346,8 +344,6 @@ expect_ssh () { (cd "$TRASH_DIRECTORY" && test_cmp ssh-expect ssh-output) } -setup_ssh_wrapper - test_expect_success 'clone myhost:src uses ssh' ' git clone myhost:src ssh-clone && expect_ssh myhost src @@ -364,9 +360,52 @@ test_expect_success 'bracketed hostnames are still ssh' ' expect_ssh "-p 123" myhost src ' -test_expect_success 'uplink is not treated as putty' ' +test_expect_success 'OpenSSH variant passes -4' ' + git clone -4 "[myhost:123]:src" ssh-ipv4-clone && + expect_ssh "-4 -p 123" myhost src +' + +test_expect_success 'variant can be overridden' ' + copy_ssh_wrapper_as "$TRASH_DIRECTORY/putty" && + git -c ssh.variant=putty clone -4 "[myhost:123]:src" ssh-putty-clone && + expect_ssh "-4 -P 123" myhost src +' + +test_expect_success 'variant=auto picks based on basename' ' + copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" && + git -c ssh.variant=auto clone -4 "[myhost:123]:src" ssh-auto-clone && + expect_ssh "-4 -P 123" myhost src +' + +test_expect_success 'simple does not support -4/-6' ' + copy_ssh_wrapper_as "$TRASH_DIRECTORY/simple" && + test_must_fail git clone -4 "myhost:src" ssh-4-clone-simple +' + +test_expect_success 'simple does not support port' ' + copy_ssh_wrapper_as "$TRASH_DIRECTORY/simple" && + test_must_fail git clone "[myhost:123]:src" ssh-bracket-clone-simple +' + +test_expect_success 'uplink is treated as simple' ' copy_ssh_wrapper_as "$TRASH_DIRECTORY/uplink" && - git clone "[myhost:123]:src" ssh-bracket-clone-uplink && + test_must_fail git clone "[myhost:123]:src" ssh-bracket-clone-uplink && + git clone "myhost:src" ssh-clone-uplink && + expect_ssh myhost src +' + +test_expect_success 'OpenSSH-like uplink is treated as ssh' ' + write_script "$TRASH_DIRECTORY/uplink" <<-EOF && + if test "\$1" = "-G" + then + exit 0 + fi && + exec "\$TRASH_DIRECTORY/ssh$X" "\$@" + EOF + test_when_finished "rm -f \"\$TRASH_DIRECTORY/uplink\"" && + GIT_SSH="$TRASH_DIRECTORY/uplink" && + test_when_finished "GIT_SSH=\"\$TRASH_DIRECTORY/ssh\$X\"" && + git clone "[myhost:123]:src" ssh-bracket-clone-sshlike-uplink && expect_ssh "-p 123" myhost src ' @@ -418,12 +457,14 @@ test_expect_success 'ssh.variant overrides plink detection' ' ' test_expect_success 'GIT_SSH_VARIANT overrides plink detection to plink' ' + copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" && GIT_SSH_VARIANT=plink \ git clone "[myhost:123]:src" ssh-bracket-clone-variant-3 && expect_ssh "-P 123" myhost src ' test_expect_success 'GIT_SSH_VARIANT overrides plink to tortoiseplink' ' + copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" && GIT_SSH_VARIANT=tortoiseplink \ git clone "[myhost:123]:src" ssh-bracket-clone-variant-4 && expect_ssh "-batch -P 123" myhost src @@ -435,9 +476,6 @@ test_expect_success 'clean failure on broken quoting' ' git clone "[myhost:123]:src" sq-failure ' -# Reset the GIT_SSH environment variable for clone tests. -setup_ssh_wrapper - counter=0 # $1 url # $2 none|host diff --git a/t/t5603-clone-dirname.sh b/t/t5603-clone-dirname.sh index d5af758129..13b5e5eb9b 100755 --- a/t/t5603-clone-dirname.sh +++ b/t/t5603-clone-dirname.sh @@ -11,7 +11,9 @@ test_expect_success 'setup ssh wrapper' ' git upload-pack "$TRASH_DIRECTORY" EOF GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper" && + GIT_SSH_VARIANT=ssh && export GIT_SSH && + export GIT_SSH_VARIANT && export TRASH_DIRECTORY ' diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh new file mode 100755 index 0000000000..ba86a44eb1 --- /dev/null +++ b/t/t5700-protocol-v1.sh @@ -0,0 +1,294 @@ +#!/bin/sh + +test_description='test git wire-protocol transition' + +TEST_NO_CREATE_REPO=1 + +. ./test-lib.sh + +# Test protocol v1 with 'git://' transport +# +. "$TEST_DIRECTORY"/lib-git-daemon.sh +start_git_daemon --export-all --enable=receive-pack +daemon_parent=$GIT_DAEMON_DOCUMENT_ROOT_PATH/parent + +test_expect_success 'create repo to be served by git-daemon' ' + git init "$daemon_parent" && + test_commit -C "$daemon_parent" one +' + +test_expect_success 'clone with git:// using protocol v1' ' + GIT_TRACE_PACKET=1 git -c protocol.version=1 \ + clone "$GIT_DAEMON_URL/parent" daemon_child 2>log && + + git -C daemon_child log -1 --format=%s >actual && + git -C "$daemon_parent" log -1 --format=%s >expect && + test_cmp expect actual && + + # Client requested to use protocol v1 + grep "clone> .*\\\0\\\0version=1\\\0$" log && + # Server responded using protocol v1 + grep "clone< version 1" log +' + +test_expect_success 'fetch with git:// using protocol v1' ' + test_commit -C "$daemon_parent" two && + + GIT_TRACE_PACKET=1 git -C daemon_child -c protocol.version=1 \ + fetch 2>log && + + git -C daemon_child log -1 --format=%s origin/master >actual && + git -C "$daemon_parent" log -1 --format=%s >expect && + test_cmp expect actual && + + # Client requested to use protocol v1 + grep "fetch> .*\\\0\\\0version=1\\\0$" log && + # Server responded using protocol v1 + grep "fetch< version 1" log +' + +test_expect_success 'pull with git:// using protocol v1' ' + GIT_TRACE_PACKET=1 git -C daemon_child -c protocol.version=1 \ + pull 2>log && + + git -C daemon_child log -1 --format=%s >actual && + git -C "$daemon_parent" log -1 --format=%s >expect && + test_cmp expect actual && + + # Client requested to use protocol v1 + grep "fetch> .*\\\0\\\0version=1\\\0$" log && + # Server responded using protocol v1 + grep "fetch< version 1" log +' + +test_expect_success 'push with git:// using protocol v1' ' + test_commit -C daemon_child three && + + # Push to another branch, as the target repository has the + # master branch checked out and we cannot push into it. + GIT_TRACE_PACKET=1 git -C daemon_child -c protocol.version=1 \ + push origin HEAD:client_branch 2>log && + + git -C daemon_child log -1 --format=%s >actual && + git -C "$daemon_parent" log -1 --format=%s client_branch >expect && + test_cmp expect actual && + + # Client requested to use protocol v1 + grep "push> .*\\\0\\\0version=1\\\0$" log && + # Server responded using protocol v1 + grep "push< version 1" log +' + +stop_git_daemon + +# Test protocol v1 with 'file://' transport +# +test_expect_success 'create repo to be served by file:// transport' ' + git init file_parent && + test_commit -C file_parent one +' + +test_expect_success 'clone with file:// using protocol v1' ' + GIT_TRACE_PACKET=1 git -c protocol.version=1 \ + clone "file://$(pwd)/file_parent" file_child 2>log && + + git -C file_child log -1 --format=%s >actual && + git -C file_parent log -1 --format=%s >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "clone< version 1" log +' + +test_expect_success 'fetch with file:// using protocol v1' ' + test_commit -C file_parent two && + + GIT_TRACE_PACKET=1 git -C file_child -c protocol.version=1 \ + fetch 2>log && + + git -C file_child log -1 --format=%s origin/master >actual && + git -C file_parent log -1 --format=%s >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "fetch< version 1" log +' + +test_expect_success 'pull with file:// using protocol v1' ' + GIT_TRACE_PACKET=1 git -C file_child -c protocol.version=1 \ + pull 2>log && + + git -C file_child log -1 --format=%s >actual && + git -C file_parent log -1 --format=%s >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "fetch< version 1" log +' + +test_expect_success 'push with file:// using protocol v1' ' + test_commit -C file_child three && + + # Push to another branch, as the target repository has the + # master branch checked out and we cannot push into it. + GIT_TRACE_PACKET=1 git -C file_child -c protocol.version=1 \ + push origin HEAD:client_branch 2>log && + + git -C file_child log -1 --format=%s >actual && + git -C file_parent log -1 --format=%s client_branch >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "push< version 1" log +' + +# Test protocol v1 with 'ssh://' transport +# +test_expect_success 'setup ssh wrapper' ' + GIT_SSH="$GIT_BUILD_DIR/t/helper/test-fake-ssh" && + export GIT_SSH && + GIT_SSH_VARIANT=ssh && + export GIT_SSH_VARIANT && + export TRASH_DIRECTORY && + >"$TRASH_DIRECTORY"/ssh-output +' + +expect_ssh () { + test_when_finished '(cd "$TRASH_DIRECTORY" && rm -f ssh-expect && >ssh-output)' && + echo "ssh: -o SendEnv=GIT_PROTOCOL myhost $1 '$PWD/ssh_parent'" >"$TRASH_DIRECTORY/ssh-expect" && + (cd "$TRASH_DIRECTORY" && test_cmp ssh-expect ssh-output) +} + +test_expect_success 'create repo to be served by ssh:// transport' ' + git init ssh_parent && + test_commit -C ssh_parent one +' + +test_expect_success 'clone with ssh:// using protocol v1' ' + GIT_TRACE_PACKET=1 git -c protocol.version=1 \ + clone "ssh://myhost:$(pwd)/ssh_parent" ssh_child 2>log && + expect_ssh git-upload-pack && + + git -C ssh_child log -1 --format=%s >actual && + git -C ssh_parent log -1 --format=%s >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "clone< version 1" log +' + +test_expect_success 'fetch with ssh:// using protocol v1' ' + test_commit -C ssh_parent two && + + GIT_TRACE_PACKET=1 git -C ssh_child -c protocol.version=1 \ + fetch 2>log && + expect_ssh git-upload-pack && + + git -C ssh_child log -1 --format=%s origin/master >actual && + git -C ssh_parent log -1 --format=%s >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "fetch< version 1" log +' + +test_expect_success 'pull with ssh:// using protocol v1' ' + GIT_TRACE_PACKET=1 git -C ssh_child -c protocol.version=1 \ + pull 2>log && + expect_ssh git-upload-pack && + + git -C ssh_child log -1 --format=%s >actual && + git -C ssh_parent log -1 --format=%s >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "fetch< version 1" log +' + +test_expect_success 'push with ssh:// using protocol v1' ' + test_commit -C ssh_child three && + + # Push to another branch, as the target repository has the + # master branch checked out and we cannot push into it. + GIT_TRACE_PACKET=1 git -C ssh_child -c protocol.version=1 \ + push origin HEAD:client_branch 2>log && + expect_ssh git-receive-pack && + + git -C ssh_child log -1 --format=%s >actual && + git -C ssh_parent log -1 --format=%s client_branch >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "push< version 1" log +' + +# Test protocol v1 with 'http://' transport +# +. "$TEST_DIRECTORY"/lib-httpd.sh +start_httpd + +test_expect_success 'create repo to be served by http:// transport' ' + git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" config http.receivepack true && + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one +' + +test_expect_success 'clone with http:// using protocol v1' ' + GIT_TRACE_PACKET=1 GIT_TRACE_CURL=1 git -c protocol.version=1 \ + clone "$HTTPD_URL/smart/http_parent" http_child 2>log && + + git -C http_child log -1 --format=%s >actual && + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s >expect && + test_cmp expect actual && + + # Client requested to use protocol v1 + grep "Git-Protocol: version=1" log && + # Server responded using protocol v1 + grep "git< version 1" log +' + +test_expect_success 'fetch with http:// using protocol v1' ' + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two && + + GIT_TRACE_PACKET=1 git -C http_child -c protocol.version=1 \ + fetch 2>log && + + git -C http_child log -1 --format=%s origin/master >actual && + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "git< version 1" log +' + +test_expect_success 'pull with http:// using protocol v1' ' + GIT_TRACE_PACKET=1 git -C http_child -c protocol.version=1 \ + pull 2>log && + + git -C http_child log -1 --format=%s >actual && + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "git< version 1" log +' + +test_expect_success 'push with http:// using protocol v1' ' + test_commit -C http_child three && + + # Push to another branch, as the target repository has the + # master branch checked out and we cannot push into it. + GIT_TRACE_PACKET=1 git -C http_child -c protocol.version=1 \ + push origin HEAD:client_branch && #2>log && + + git -C http_child log -1 --format=%s >actual && + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s client_branch >expect && + test_cmp expect actual && + + # Server responded using protocol v1 + grep "git< version 1" log +' + +stop_httpd + +test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index c02ca735b9..1797f632a3 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -1131,6 +1131,12 @@ test_expect_success PCRE 'grep -P pattern' ' test_cmp expected actual ' +test_expect_success LIBPCRE2 "grep -P with (*NO_JIT) doesn't error out" ' + git grep -P "(*NO_JIT)\p{Ps}.*?\p{Pe}" hello.c >actual && + test_cmp expected actual + +' + test_expect_success !PCRE 'grep -P pattern errors without PCRE' ' test_must_fail git grep -P "foo.*bar" ' diff --git a/t/test-lib.sh b/t/test-lib.sh index 116bd6a70c..e7065df2bb 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1028,6 +1028,8 @@ test -z "$NO_PERL" && test_set_prereq PERL test -z "$NO_PTHREADS" && test_set_prereq PTHREADS test -z "$NO_PYTHON" && test_set_prereq PYTHON test -n "$USE_LIBPCRE1$USE_LIBPCRE2" && test_set_prereq PCRE +test -n "$USE_LIBPCRE1" && test_set_prereq LIBPCRE1 +test -n "$USE_LIBPCRE2" && test_set_prereq LIBPCRE2 test -z "$NO_GETTEXT" && test_set_prereq GETTEXT # Can we rely on git's output in the C locale? |