diff options
Diffstat (limited to 't')
36 files changed, 1231 insertions, 54 deletions
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index 09e86f9..cc01d89 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -56,6 +56,10 @@ check_count () { ' "$@" <actual } +get_progress_result () { + tr '\015' '\012' | tail -n 1 +} + test_expect_success 'setup A lines' ' echo "1A quick brown fox jumps over the" >file && echo "lazy dog" >>file && @@ -604,3 +608,39 @@ test_expect_success 'blame -L X,-N (non-numeric N)' ' test_expect_success 'blame -L ,^/RE/' ' test_must_fail $PROG -L1,^/99/ file ' + +test_expect_success 'blame progress on a full file' ' + cat >expect <<-\EOF && + Blaming lines: 100% (10/10), done. + EOF + + GIT_PROGRESS_DELAY=0 \ + git blame --progress hello.c 2>stderr && + + get_progress_result <stderr >actual && + test_cmp expect actual +' + +test_expect_success 'blame progress on a single range' ' + cat >expect <<-\EOF && + Blaming lines: 100% (4/4), done. + EOF + + GIT_PROGRESS_DELAY=0 \ + git blame --progress -L 3,6 hello.c 2>stderr && + + get_progress_result <stderr >actual && + test_cmp expect actual +' + +test_expect_success 'blame progress on multiple ranges' ' + cat >expect <<-\EOF && + Blaming lines: 100% (7/7), done. + EOF + + GIT_PROGRESS_DELAY=0 \ + git blame --progress -L 3,6 -L 8,10 hello.c 2>stderr && + + get_progress_result <stderr >actual && + test_cmp expect actual +' diff --git a/t/lib-git-p4.sh b/t/lib-git-p4.sh index 5aff2ab..2a5b873 100644 --- a/t/lib-git-p4.sh +++ b/t/lib-git-p4.sh @@ -142,10 +142,11 @@ start_p4d () { p4_add_user () { name=$1 && + fullname="${2:-Dr. $1}" p4 user -f -i <<-EOF User: $name Email: $name@example.com - FullName: Dr. $name + FullName: $fullname EOF } diff --git a/t/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh index 382716c..76710cb 100755 --- a/t/perf/p2000-sparse-operations.sh +++ b/t/perf/p2000-sparse-operations.sh @@ -106,6 +106,8 @@ test_perf_on_all () { } test_perf_on_all git status +test_perf_on_all 'git stash && git stash pop' +test_perf_on_all 'echo >>new && git stash -u && git stash pop' test_perf_on_all git add -A test_perf_on_all git add . test_perf_on_all git commit -a -m A diff --git a/t/t0012-help.sh b/t/t0012-help.sh index 6c3e1f7..6c33a43 100755 --- a/t/t0012-help.sh +++ b/t/t0012-help.sh @@ -181,7 +181,7 @@ for cmd in git "git help" do test_expect_success "'$cmd' section spacing" ' test_section_spacing_trailer git help <<-\EOF && - usage: git [--version] [--help] [-C <path>] [-c <name>=<value>] + usage: git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>] These are common Git commands used in various situations: diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh index 0feb41a..7f80f46 100755 --- a/t/t0027-auto-crlf.sh +++ b/t/t0027-auto-crlf.sh @@ -77,12 +77,12 @@ create_NNO_MIX_files () { check_warning () { case "$1" in - LF_CRLF) echo "warning: LF will be replaced by CRLF" >"$2".expect ;; - CRLF_LF) echo "warning: CRLF will be replaced by LF" >"$2".expect ;; - '') >"$2".expect ;; + LF_CRLF) echo "LF will be replaced by CRLF" >"$2".expect ;; + CRLF_LF) echo "CRLF will be replaced by LF" >"$2".expect ;; + '') >"$2".expect ;; *) echo >&2 "Illegal 1": "$1" ; return false ;; esac - grep "will be replaced by" "$2" | sed -e "s/\(.*\) in [^ ]*$/\1/" | uniq >"$2".actual + sed -e "s/^.* \([^ ]* will be replaced by [^ ]*\) .*$/\1/" "$2" | uniq >"$2".actual test_cmp "$2".expect "$2".actual } diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh index 239d93f..238b25f 100755 --- a/t/t0033-safe-directory.sh +++ b/t/t0033-safe-directory.sh @@ -9,13 +9,41 @@ export GIT_TEST_ASSUME_DIFFERENT_OWNER expect_rejected_dir () { test_must_fail git status 2>err && - grep "safe.directory" err + grep "unsafe repository" err } test_expect_success 'safe.directory is not set' ' expect_rejected_dir ' +test_expect_success 'ignoring safe.directory on the command line' ' + test_must_fail git -c safe.directory="$(pwd)" status 2>err && + grep "unsafe repository" err +' + +test_expect_success 'ignoring safe.directory in the environment' ' + test_must_fail env GIT_CONFIG_COUNT=1 \ + GIT_CONFIG_KEY_0="safe.directory" \ + GIT_CONFIG_VALUE_0="$(pwd)" \ + git status 2>err && + grep "unsafe repository" err +' + +test_expect_success 'ignoring safe.directory in GIT_CONFIG_PARAMETERS' ' + test_must_fail env \ + GIT_CONFIG_PARAMETERS="${SQ}safe.directory${SQ}=${SQ}$(pwd)${SQ}" \ + git status 2>err && + grep "unsafe repository" err +' + +test_expect_success 'ignoring safe.directory in repo config' ' + ( + unset GIT_TEST_ASSUME_DIFFERENT_OWNER && + git config safe.directory "$(pwd)" + ) && + expect_rejected_dir +' + test_expect_success 'safe.directory does not match' ' git config --global safe.directory bogus && expect_rejected_dir diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index 2fe6ae6..aa35350 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -542,7 +542,7 @@ test_lazy_prereq CAN_EXEC_IN_PWD ' ./git rev-parse ' -test_expect_success RUNTIME_PREFIX,CAN_EXEC_IN_PWD 'RUNTIME_PREFIX works' ' +test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD 'RUNTIME_PREFIX works' ' mkdir -p pretend/bin pretend/libexec/git-core && echo "echo HERE" | write_script pretend/libexec/git-core/git-here && cp "$GIT_EXEC_PATH"/git$X pretend/bin/ && @@ -550,7 +550,7 @@ test_expect_success RUNTIME_PREFIX,CAN_EXEC_IN_PWD 'RUNTIME_PREFIX works' ' echo HERE >expect && test_cmp expect actual' -test_expect_success RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works' ' +test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works' ' mkdir -p pretend/bin && cp "$GIT_EXEC_PATH"/git$X pretend/bin/ && git config yes.path "%(prefix)/yes" && diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index 1b85207..dadf3b1 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -681,7 +681,7 @@ test_expect_success 'cat-file -t and -s on corrupt loose object' ' # Setup and create the empty blob and its path empty_path=$(git rev-parse --git-path objects/$(test_oid_to_path "$EMPTY_BLOB")) && - git hash-object -w --stdin </dev/null && + empty_blob=$(git hash-object -w --stdin </dev/null) && # Create another blob and its path echo other >other.blob && @@ -722,7 +722,13 @@ test_expect_success 'cat-file -t and -s on corrupt loose object' ' # content out as-is. Try to make it zlib-invalid. mv -f other.blob "$empty_path" && test_must_fail git fsck 2>err.fsck && - grep "^error: inflate: data stream error (" err.fsck + cat >expect <<-EOF && + error: inflate: data stream error (incorrect header check) + error: unable to unpack header of ./$empty_path + error: $empty_blob: object corrupt or missing: ./$empty_path + EOF + grep "^error: " err.fsck >actual && + test_cmp expect actual ) ' diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index dd957be..63a553d 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -57,8 +57,8 @@ test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' ' read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt result && - test -f init.t && - test -f sub/added + test_path_is_file init.t && + test_path_is_file sub/added ' test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-checkout and enabled' ' @@ -67,8 +67,8 @@ test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse- read_tree_u_must_succeed --no-sparse-checkout -m -u HEAD && git ls-files -t >result && test_cmp expected.swt result && - test -f init.t && - test -f sub/added + test_path_is_file init.t && + test_path_is_file sub/added ' test_expect_success 'read-tree with empty .git/info/sparse-checkout' ' @@ -85,8 +85,8 @@ test_expect_success 'read-tree with empty .git/info/sparse-checkout' ' S subsub/added EOF test_cmp expected.swt result && - ! test -f init.t && - ! test -f sub/added + test_path_is_missing init.t && + test_path_is_missing sub/added ' test_expect_success 'match directories with trailing slash' ' @@ -101,8 +101,8 @@ test_expect_success 'match directories with trailing slash' ' read_tree_u_must_succeed -m -u HEAD && git ls-files -t > result && test_cmp expected.swt-noinit result && - test ! -f init.t && - test -f sub/added + test_path_is_missing init.t && + test_path_is_file sub/added ' test_expect_success 'match directories without trailing slash' ' @@ -110,8 +110,8 @@ test_expect_success 'match directories without trailing slash' ' read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-noinit result && - test ! -f init.t && - test -f sub/added + test_path_is_missing init.t && + test_path_is_file sub/added ' test_expect_success 'match directories with negated patterns' ' @@ -129,9 +129,9 @@ EOF git read-tree -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-negation result && - test ! -f init.t && - test ! -f sub/added && - test -f sub/addedtoo + test_path_is_missing init.t && + test_path_is_missing sub/added && + test_path_is_file sub/addedtoo ' test_expect_success 'match directories with negated patterns (2)' ' @@ -150,9 +150,9 @@ EOF git read-tree -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-negation2 result && - test -f init.t && - test -f sub/added && - test ! -f sub/addedtoo + test_path_is_file init.t && + test_path_is_file sub/added && + test_path_is_missing sub/addedtoo ' test_expect_success 'match directory pattern' ' @@ -160,8 +160,8 @@ test_expect_success 'match directory pattern' ' read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-noinit result && - test ! -f init.t && - test -f sub/added + test_path_is_missing init.t && + test_path_is_file sub/added ' test_expect_success 'checkout area changes' ' @@ -176,15 +176,15 @@ test_expect_success 'checkout area changes' ' read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && test_cmp expected.swt-nosub result && - test -f init.t && - test ! -f sub/added + test_path_is_file init.t && + test_path_is_missing sub/added ' test_expect_success 'read-tree updates worktree, absent case' ' echo sub/added >.git/info/sparse-checkout && git checkout -f top && read_tree_u_must_succeed -m -u HEAD^ && - test ! -f init.t + test_path_is_missing init.t ' test_expect_success 'read-tree will not throw away dirty changes, non-sparse' ' @@ -229,7 +229,7 @@ test_expect_success 'read-tree adds to worktree, absent case' ' echo init.t >.git/info/sparse-checkout && git checkout -f removed && read_tree_u_must_succeed -u -m HEAD^ && - test ! -f sub/added + test_path_is_missing sub/added ' test_expect_success 'read-tree adds to worktree, dirty case' ' @@ -248,7 +248,7 @@ test_expect_success 'index removal and worktree narrowing at the same time' ' echo init.t >.git/info/sparse-checkout && git checkout removed && git ls-files sub/added >result && - test ! -f sub/added && + test_path_is_missing sub/added && test_must_be_empty result ' diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 236ab53..6f778cf 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1034,6 +1034,55 @@ test_expect_success 'cherry-pick with conflicts' ' test_all_match test_must_fail git cherry-pick to-cherry-pick ' +test_expect_success 'stash' ' + init_repos && + + write_script edit-contents <<-\EOF && + echo text >>$1 + EOF + + # Stash a sparse directory (folder1) + test_all_match git checkout -b test-branch rename-base && + test_all_match git reset --soft rename-out-to-out && + test_all_match git stash && + test_all_match git status --porcelain=v2 && + + # Apply the sparse directory stash without reinstating the index + test_all_match git stash apply -q && + test_all_match git status --porcelain=v2 && + + # Reset to state where stash can be applied + test_sparse_match git sparse-checkout reapply && + test_all_match git reset --hard rename-out-to-out && + + # Apply the sparse directory stash *with* reinstating the index + test_all_match git stash apply --index -q && + test_all_match git status --porcelain=v2 && + + # Reset to state where we will get a conflict applying the stash + test_sparse_match git sparse-checkout reapply && + test_all_match git reset --hard update-folder1 && + + # Apply the sparse directory stash with conflicts + test_all_match test_must_fail git stash apply --index -q && + test_all_match test_must_fail git stash apply -q && + test_all_match git status --porcelain=v2 && + + # Reset to base branch + test_sparse_match git sparse-checkout reapply && + test_all_match git reset --hard base && + + # Stash & unstash an untracked file outside of the sparse checkout + # definition. + run_on_sparse mkdir -p folder1 && + run_on_all ../edit-contents folder1/new && + test_all_match git stash -u && + test_all_match git status --porcelain=v2 && + + test_all_match git stash pop -q && + test_all_match git status --porcelain=v2 +' + test_expect_success 'checkout-index inside sparse definition' ' init_repos && @@ -1151,6 +1200,33 @@ test_expect_success 'clean' ' test_sparse_match test_path_is_dir folder1 ' +for builtin in show rev-parse +do + test_expect_success "$builtin (cached blobs/trees)" " + init_repos && + + test_all_match git $builtin :a && + test_all_match git $builtin :deep/a && + test_sparse_match git $builtin :folder1/a && + + # The error message differs depending on whether + # the directory exists in the worktree. + test_all_match test_must_fail git $builtin :deep/ && + test_must_fail git -C full-checkout $builtin :folder1/ && + test_sparse_match test_must_fail git $builtin :folder1/ && + + # Change the sparse cone for an extra case: + run_on_sparse git sparse-checkout set deep/deeper1 && + + # deep/deeper2 is a sparse directory in the sparse index. + test_sparse_match test_must_fail git $builtin :deep/deeper2/ && + + # deep/deeper2/deepest is not in the sparse index, but + # will trigger an index expansion. + test_sparse_match test_must_fail git $builtin :deep/deeper2/deepest/ + " +done + test_expect_success 'submodule handling' ' init_repos && @@ -1222,7 +1298,10 @@ test_expect_success 'index.sparse disabled inline uses full index' ' ensure_not_expanded () { rm -f trace2.txt && - echo >>sparse-index/untracked.txt && + if test -z "$WITHOUT_UNTRACKED_TXT" + then + echo >>sparse-index/untracked.txt + fi && if test "$1" = "!" then @@ -1326,6 +1405,30 @@ test_expect_success 'sparse-index is not expanded: merge conflict in cone' ' ) ' +test_expect_success 'sparse-index is not expanded: stash' ' + init_repos && + + echo >>sparse-index/a && + ensure_not_expanded stash && + ensure_not_expanded stash list && + ensure_not_expanded stash show stash@{0} && + ensure_not_expanded stash apply stash@{0} && + ensure_not_expanded stash drop stash@{0} && + + echo >>sparse-index/deep/new && + ensure_not_expanded stash -u && + ( + WITHOUT_UNTRACKED_TXT=1 && + ensure_not_expanded stash pop + ) && + + ensure_not_expanded stash create && + oid=$(git -C sparse-index stash create) && + ensure_not_expanded stash store -m "test" $oid && + ensure_not_expanded reset --hard && + ensure_not_expanded stash pop +' + test_expect_success 'sparse index is not expanded: diff' ' init_repos && @@ -1372,6 +1475,15 @@ test_expect_success 'sparse index is not expanded: diff' ' ensure_not_expanded diff --cached ' +test_expect_success 'sparse index is not expanded: show and rev-parse' ' + init_repos && + + ensure_not_expanded show :a && + ensure_not_expanded show :deep/a && + ensure_not_expanded rev-parse :a && + ensure_not_expanded rev-parse :deep/a +' + test_expect_success 'sparse index is not expanded: update-index' ' init_repos && diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index de50c0e..ab7f31f 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -774,10 +774,19 @@ test_expect_success 'fsck finds problems in duplicate loose objects' ' # no "-d" here, so we end up with duplicates git repack && # now corrupt the loose copy - file=$(sha1_file "$(git rev-parse HEAD)") && + oid="$(git rev-parse HEAD)" && + file=$(sha1_file "$oid") && rm "$file" && echo broken >"$file" && - test_must_fail git fsck + test_must_fail git fsck 2>err && + + cat >expect <<-EOF && + error: inflate: data stream error (incorrect header check) + error: unable to unpack header of $file + error: $oid: object corrupt or missing: $file + EOF + grep "^error: " err >actual && + test_cmp expect actual ) ' diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh index db7ca55..ebf58db 100755 --- a/t/t2203-add-intent.sh +++ b/t/t2203-add-intent.sh @@ -2,6 +2,7 @@ test_description='Intent to add' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'intent to add' ' diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh index 7a1be73..f2b9199 100755 --- a/t/t3202-show-branch.sh +++ b/t/t3202-show-branch.sh @@ -161,4 +161,18 @@ test_expect_success 'show branch --reflog=2' ' test_cmp actual expect ' +# incompatible options +while read combo +do + test_expect_success "show-branch $combo (should fail)" ' + test_must_fail git show-branch $combo 2>error && + grep -e "cannot be used together" -e "usage:" error + ' +done <<\EOF +--all --reflog +--merge-base --reflog +--list --merge-base +--reflog --current +EOF + test_done diff --git a/t/t3416-rebase-onto-threedots.sh b/t/t3416-rebase-onto-threedots.sh index 3716a42..3e04802 100755 --- a/t/t3416-rebase-onto-threedots.sh +++ b/t/t3416-rebase-onto-threedots.sh @@ -129,6 +129,20 @@ test_expect_success 'rebase --keep-base main from topic' ' test_cmp expect actual ' +test_expect_success 'rebase --keep-base main topic from main' ' + git checkout main && + git branch -f topic G && + + git rebase --keep-base main topic && + git rev-parse C >base.expect && + git merge-base main HEAD >base.actual && + test_cmp base.expect base.actual && + + git rev-parse HEAD~2 >actual && + git rev-parse C^0 >expect && + test_cmp expect actual +' + test_expect_success 'rebase --keep-base main from side' ' git reset --hard && git checkout side && @@ -153,6 +167,21 @@ test_expect_success 'rebase -i --keep-base main from topic' ' test_cmp expect actual ' +test_expect_success 'rebase -i --keep-base main topic from main' ' + git checkout main && + git branch -f topic G && + + set_fake_editor && + EXPECT_COUNT=2 git rebase -i --keep-base main topic && + git rev-parse C >base.expect && + git merge-base main HEAD >base.actual && + test_cmp base.expect base.actual && + + git rev-parse HEAD~2 >actual && + git rev-parse C^0 >expect && + test_cmp expect actual +' + test_expect_success 'rebase -i --keep-base main from side' ' git reset --hard && git checkout side && diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index 8617efa..9eb1920 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -66,8 +66,7 @@ test_expect_success 'cherry-pick after renaming branch' ' git checkout rename2 && git cherry-pick added && - test $(git rev-parse HEAD^) = $(git rev-parse rename2) && - test -f opos && + test_cmp_rev rename2 HEAD^ && grep "Add extra line at the end" opos && git reflog -1 | grep cherry-pick @@ -77,9 +76,9 @@ test_expect_success 'revert after renaming branch' ' git checkout rename1 && git revert added && - test $(git rev-parse HEAD^) = $(git rev-parse rename1) && - test -f spoo && - ! grep "Add extra line at the end" spoo && + test_cmp_rev rename1 HEAD^ && + test_path_is_file spoo && + test_cmp_rev initial:oops HEAD:spoo && git reflog -1 | grep revert ' diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 750aee1..056e922 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -542,6 +542,39 @@ test_expect_success 'diff-tree --stdin with log formatting' ' test_cmp expect actual ' +test_expect_success 'diff-tree --stdin with pathspec' ' + cat >expect <<-EOF && + Third + + dir/sub + Second + + dir/sub + EOF + git rev-list master^ | + git diff-tree -r --stdin --name-only --format=%s dir >actual && + test_cmp expect actual +' + +test_expect_success 'show A B ... -- <pathspec>' ' + # side touches dir/sub, file0, and file3 + # master^ touches dir/sub, and file1 + # master^^ touches dir/sub, file0, and file2 + git show --name-only --format="<%s>" side master^ master^^ -- dir >actual && + cat >expect <<-\EOF && + <Side> + + dir/sub + <Third> + + dir/sub + <Second> + + dir/sub + EOF + test_cmp expect actual +' + test_expect_success 'diff -I<regex>: setup' ' git checkout master && test_seq 50 >file0 && diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 7dc5a5c..fbec8ad 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -926,11 +926,40 @@ test_expect_success 'format-patch --numstat should produce a patch' ' ' test_expect_success 'format-patch -- <path>' ' - git format-patch main..side -- file 2>error && - ! grep "Use .--" error + rm -f *.patch && + git checkout -b pathspec main && + + echo file_a 1 >file_a && + echo file_b 1 >file_b && + git add file_a file_b && + git commit -m pathspec_initial && + + echo file_a 2 >>file_a && + git add file_a && + git commit -m pathspec_a && + + echo file_b 2 >>file_b && + git add file_b && + git commit -m pathspec_b && + + echo file_a 3 >>file_a && + echo file_b 3 >>file_b && + git add file_a file_b && + git commit -m pathspec_ab && + + cat >expect <<-\EOF && + 0001-pathspec_initial.patch + 0002-pathspec_a.patch + 0003-pathspec_ab.patch + EOF + + git format-patch main..pathspec -- file_a >output && + test_cmp expect output && + ! grep file_b *.patch ' test_expect_success 'format-patch --ignore-if-in-upstream HEAD' ' + git checkout side && git format-patch --ignore-if-in-upstream HEAD ' diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index 1219f8b..858a552 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -206,17 +206,17 @@ test_expect_success 'GIT_EXTERNAL_DIFF path counter/total' ' ' test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' ' + test_when_finished "git rm -f file.ext" && touch file.ext && git add file.ext && echo with extension > file.ext && cat >expect <<-EOF && - file.ext file $(git rev-parse --verify HEAD:file) 100644 file.ext $(test_oid zero) 100644 + file.ext EOF GIT_EXTERNAL_DIFF=echo git diff file.ext >out && - cut -d" " -f1,3- <out >actual && - git update-index --force-remove file.ext && - rm file.ext + basename $(cut -d" " -f2 <out) >actual && + test_cmp expect actual ' echo "#!$SHELL_PATH" >fake-diff.sh diff --git a/t/t4202-log.sh b/t/t4202-log.sh index be07407..6e66352 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -1992,10 +1992,13 @@ test_expect_success GPG 'log --show-signature for merged tag with GPG failure' ' git tag -s -m signed_tag_msg signed_tag_fail && git checkout plain-fail && git merge --no-ff -m msg signed_tag_fail && - TMPDIR="$(pwd)/bogus" git log --show-signature -n1 plain-fail >actual && - grep "^merged tag" actual && - grep "^No signature" actual && - ! grep "^gpg: Signature made" actual + if ! test_have_prereq VALGRIND + then + TMPDIR="$(pwd)/bogus" git log --show-signature -n1 plain-fail >actual && + grep "^merged tag" actual && + grep "^No signature" actual && + ! grep "^gpg: Signature made" actual + fi ' test_expect_success GPGSM 'log --graph --show-signature for merged tag x509' ' diff --git a/t/t4217-log-limit.sh b/t/t4217-log-limit.sh new file mode 100755 index 0000000..6e01e26 --- /dev/null +++ b/t/t4217-log-limit.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +test_description='git log with filter options limiting the output' + +. ./test-lib.sh + +test_expect_success 'setup test' ' + git init && + echo a >file && + git add file && + GIT_COMMITTER_DATE="2021-02-01 00:00" git commit -m init && + echo a >>file && + git add file && + GIT_COMMITTER_DATE="2022-02-01 00:00" git commit -m first && + echo a >>file && + git add file && + GIT_COMMITTER_DATE="2021-03-01 00:00" git commit -m second && + echo a >>file && + git add file && + GIT_COMMITTER_DATE="2022-03-01 00:00" git commit -m third +' + +test_expect_success 'git log --since-as-filter=...' ' + git log --since-as-filter="2022-01-01" --format=%s >actual && + cat >expect <<-\EOF && + third + first + EOF + test_cmp expect actual +' + +test_expect_success 'git log --children --since-as-filter=...' ' + git log --children --since-as-filter="2022-01-01" --format=%s >actual && + cat >expect <<-\EOF && + third + first + EOF + test_cmp expect actual +' + +test_done diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh index fa6b4cc..a35396f 100755 --- a/t/t5572-pull-submodule.sh +++ b/t/t5572-pull-submodule.sh @@ -107,6 +107,32 @@ test_expect_success " --[no-]recurse-submodule and submodule.recurse" ' test_path_is_file super/sub/merge_strategy_4.t ' +test_expect_success "fetch.recurseSubmodules option triggers recursive fetch (but not recursive update)" ' + test_commit -C child merge_strategy_5 && + # Omit the parent commit, otherwise this passes with the + # default "pull" behavior. + + git -C super -c fetch.recursesubmodules=true pull --no-rebase && + # Check that the submodule commit was fetched + sub_oid=$(git -C child rev-parse HEAD) && + git -C super/sub cat-file -e $sub_oid && + # Check that the submodule worktree did not update + ! test_path_is_file super/sub/merge_strategy_5.t +' + +test_expect_success "fetch.recurseSubmodules takes precedence over submodule.recurse" ' + test_commit -C child merge_strategy_6 && + # Omit the parent commit, otherwise this passes with the + # default "pull" behavior. + + git -C super -c submodule.recurse=false -c fetch.recursesubmodules=true pull --no-rebase && + # Check that the submodule commit was fetched + sub_oid=$(git -C child rev-parse HEAD) && + git -C super/sub cat-file -e $sub_oid && + # Check that the submodule worktree did not update + ! test_path_is_file super/sub/merge_strategy_6.t +' + test_expect_success 'pull --rebase --recurse-submodules (remote superproject submodule changes, local submodule changes)' ' # This tests the following scenario : # - local submodule has new commits diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh index 7d63365..21ab619 100755 --- a/t/t5605-clone-local.sh +++ b/t/t5605-clone-local.sh @@ -141,4 +141,13 @@ test_expect_success 'cloning locally respects "-u" for fetching refs' ' test_must_fail git clone --bare -u false a should_not_work.git ' +test_expect_success 'local clone from repo with corrupt refs fails gracefully' ' + git init corrupt && + test_commit -C corrupt one && + echo a >corrupt/.git/refs/heads/topic && + + test_must_fail git clone corrupt working 2>err && + grep "has a null OID" err +' + test_done diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 5382e5d..83931d4 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -1025,4 +1025,32 @@ test_expect_success 'bisect visualize with a filename with dash and space' ' git bisect visualize -p -- "-hello 2" ' +test_expect_success 'bisect state output with multiple good commits' ' + git bisect reset && + git bisect start >output && + grep "waiting for both good and bad commits" output && + git bisect log >output && + grep "waiting for both good and bad commits" output && + git bisect good "$HASH1" >output && + grep "waiting for bad commit, 1 good commit known" output && + git bisect log >output && + grep "waiting for bad commit, 1 good commit known" output && + git bisect good "$HASH2" >output && + grep "waiting for bad commit, 2 good commits known" output && + git bisect log >output && + grep "waiting for bad commit, 2 good commits known" output +' + +test_expect_success 'bisect state output with bad commit' ' + git bisect reset && + git bisect start >output && + grep "waiting for both good and bad commits" output && + git bisect log >output && + grep "waiting for both good and bad commits" output && + git bisect bad "$HASH4" >output && + grep -F "waiting for good commit(s), bad commit known" output && + git bisect log >output && + grep -F "waiting for good commit(s), bad commit known" output +' + test_done diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh index 1761a2b..4adac5a 100755 --- a/t/t7011-skip-worktree-reading.sh +++ b/t/t7011-skip-worktree-reading.sh @@ -5,6 +5,7 @@ test_description='skip-worktree bit test' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >expect.full <<EOF diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index ca90ee8..9936cc3 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -190,6 +190,119 @@ test_expect_success 'untracked cache after second status' ' test_cmp ../dump.expect ../actual ' +cat >../status_uall.expect <<EOF && +A done/one +A one +A two +?? dthree/three +?? dtwo/two +?? three +EOF + +# Bypassing the untracked cache here is not desirable from an +# end-user perspective, but is expected in the current design. +# The untracked cache data stored for a -unormal run cannot be +# correctly used in a -uall run - it would yield incorrect output. +test_expect_success 'untracked cache is bypassed with -uall' ' + : >../trace.output && + GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \ + git status -uall --porcelain >../actual && + iuc status -uall --porcelain >../status.iuc && + test_cmp ../status_uall.expect ../status.iuc && + test_cmp ../status_uall.expect ../actual && + get_relevant_traces ../trace.output ../trace.relevant && + cat >../trace.expect <<EOF && + ....path: +EOF + test_cmp ../trace.expect ../trace.relevant +' + +test_expect_success 'untracked cache remains after bypass' ' + test-tool dump-untracked-cache >../actual && + test_cmp ../dump.expect ../actual +' + +test_expect_success 'if -uall is configured, untracked cache gets populated by default' ' + test_config status.showuntrackedfiles all && + : >../trace.output && + GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \ + git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && + test_cmp ../status_uall.expect ../status.iuc && + test_cmp ../status_uall.expect ../actual && + get_relevant_traces ../trace.output ../trace.relevant && + cat >../trace.expect <<EOF && + ....path: + ....node-creation:3 + ....gitignore-invalidation:1 + ....directory-invalidation:0 + ....opendir:4 +EOF + test_cmp ../trace.expect ../trace.relevant +' + +cat >../dump_uall.expect <<EOF && +info/exclude $EMPTY_BLOB +core.excludesfile $ZERO_OID +exclude_per_dir .gitignore +flags 00000000 +/ $ZERO_OID recurse valid +three +/done/ $ZERO_OID recurse valid +/dthree/ $ZERO_OID recurse valid +three +/dtwo/ $ZERO_OID recurse valid +two +EOF + +test_expect_success 'if -uall was configured, untracked cache is populated' ' + test-tool dump-untracked-cache >../actual && + test_cmp ../dump_uall.expect ../actual +' + +test_expect_success 'if -uall is configured, untracked cache is used by default' ' + test_config status.showuntrackedfiles all && + : >../trace.output && + GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \ + git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && + test_cmp ../status_uall.expect ../status.iuc && + test_cmp ../status_uall.expect ../actual && + get_relevant_traces ../trace.output ../trace.relevant && + cat >../trace.expect <<EOF && + ....path: + ....node-creation:0 + ....gitignore-invalidation:0 + ....directory-invalidation:0 + ....opendir:0 +EOF + test_cmp ../trace.expect ../trace.relevant +' + +# Bypassing the untracked cache here is not desirable from an +# end-user perspective, but is expected in the current design. +# The untracked cache data stored for a -all run cannot be +# correctly used in a -unormal run - it would yield incorrect +# output. +test_expect_success 'if -uall is configured, untracked cache is bypassed with -unormal' ' + test_config status.showuntrackedfiles all && + : >../trace.output && + GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.output" \ + git status -unormal --porcelain >../actual && + iuc status -unormal --porcelain >../status.iuc && + test_cmp ../status.expect ../status.iuc && + test_cmp ../status.expect ../actual && + get_relevant_traces ../trace.output ../trace.relevant && + cat >../trace.expect <<EOF && + ....path: +EOF + test_cmp ../trace.expect ../trace.relevant +' + +test_expect_success 'repopulate untracked cache for -unormal' ' + git status --porcelain +' + test_expect_success 'modify in root directory, one dir invalidation' ' : >four && test-tool chmtime =-240 four && diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 000e055..43f779d 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -670,6 +670,39 @@ test_expect_success 'submodule update --init skips submodule with update=none' ' ) ' +test_expect_success 'submodule update with pathspec warns against uninitialized ones' ' + test_when_finished "rm -fr selective" && + git clone super selective && + ( + cd selective && + git submodule init submodule && + + git submodule update submodule 2>err && + ! grep "Submodule path .* not initialized" err && + + git submodule update rebasing 2>err && + grep "Submodule path .rebasing. not initialized" err && + + test_path_exists submodule/.git && + test_path_is_missing rebasing/.git + ) + +' + +test_expect_success 'submodule update without pathspec updates only initialized ones' ' + test_when_finished "rm -fr selective" && + git clone super selective && + ( + cd selective && + git submodule init submodule && + git submodule update 2>err && + test_path_exists submodule/.git && + test_path_is_missing rebasing/.git && + ! grep "Submodule path .* not initialized" err + ) + +' + test_expect_success 'submodule update continues after checkout error' ' (cd super && git reset --hard HEAD && diff --git a/t/t7524-commit-summary.sh b/t/t7524-commit-summary.sh new file mode 100755 index 0000000..47b2f1d --- /dev/null +++ b/t/t7524-commit-summary.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +test_description='git commit summary' +. ./test-lib.sh + +test_expect_success 'setup' ' + test_seq 101 200 >file && + git add file && + git commit -m initial && + git tag initial +' + +test_expect_success 'commit summary ignores rewrites' ' + git reset --hard initial && + test_seq 200 300 >file && + + git diff --stat >diffstat && + git diff --stat --break-rewrites >diffstatrewrite && + + # make sure this scenario is a detectable rewrite + ! test_cmp_bin diffstat diffstatrewrite && + + git add file && + git commit -m second >actual && + + grep "1 file" <actual >actual.total && + grep "1 file" <diffstat >diffstat.total && + test_cmp diffstat.total actual.total +' + +test_done diff --git a/t/t7609-mergetool--lib.sh b/t/t7609-mergetool--lib.sh new file mode 100755 index 0000000..d848fe6 --- /dev/null +++ b/t/t7609-mergetool--lib.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +test_description='git mergetool + +Testing basic merge tools options' + +. ./test-lib.sh + +test_expect_success 'mergetool --tool=vimdiff creates the expected layout' ' + . $GIT_BUILD_DIR/mergetools/vimdiff && + run_unit_tests +' + +test_done diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh index 9047d66..ac7be54 100755 --- a/t/t7812-grep-icase-non-ascii.sh +++ b/t/t7812-grep-icase-non-ascii.sh @@ -4,6 +4,10 @@ test_description='grep icase on non-English locales' . ./lib-gettext.sh +doalarm () { + perl -e 'alarm shift; exec @ARGV' -- "$@" +} + test_expect_success GETTEXT_LOCALE 'setup' ' test_write_lines "TILRAUN: Halló Heimur!" >file && git add file && @@ -139,4 +143,10 @@ test_expect_success GETTEXT_LOCALE,LIBPCRE2 'PCRE v2: grep non-literal ASCII fro test_cmp expected actual ' +test_expect_success GETTEXT_LOCALE,LIBPCRE2 'PCRE v2: grep avoid endless loop bug' ' + echo " Halló" >leading-whitespace && + git add leading-whitespace && + doalarm 1 git grep --perl-regexp "^\s" leading-whitespace +' + test_done diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 7b7a18d..fc99703 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -500,6 +500,13 @@ test_expect_success 'path limiting with import-marks does not lose unmodified fi grep file0 actual ' +test_expect_success 'path limiting works' ' + git fast-export simple -- file >actual && + sed -ne "s/^M .* //p" <actual | sort -u >actual.files && + echo file >expect && + test_cmp expect actual.files +' + test_expect_success 'avoid corrupt stream with non-existent mark' ' test_create_repo avoid_non_existent_mark && ( diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh index 8b30062..dc88d0e 100755 --- a/t/t9800-git-p4-basic.sh +++ b/t/t9800-git-p4-basic.sh @@ -74,6 +74,91 @@ test_expect_success 'git p4 sync new branch' ' ) ' +# +# Setup as before, and then explicitly sync imported branch, using a +# different ref format. +# +test_expect_success 'git p4 sync existing branch without changes' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_commit head && + git p4 sync --branch=depot //depot@all && + git p4 sync --branch=refs/remotes/p4/depot >out && + test_i18ngrep "No changes to import!" out + ) +' + +# +# Same as before, relative branch name. +# +test_expect_success 'git p4 sync existing branch with relative name' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_commit head && + git p4 sync --branch=branch1 //depot@all && + git p4 sync --branch=p4/branch1 >out && + test_i18ngrep "No changes to import!" out + ) +' + +# +# Same as before, with a nested branch path, referenced different ways. +# +test_expect_success 'git p4 sync existing branch with nested path' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_commit head && + git p4 sync --branch=p4/some/path //depot@all && + git p4 sync --branch=some/path >out && + test_i18ngrep "No changes to import!" out + ) +' + +# +# Same as before, with a full ref path outside the p4/* namespace. +# +test_expect_success 'git p4 sync branch explicit ref without p4 in path' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_commit head && + git p4 sync --branch=refs/remotes/someremote/depot //depot@all && + git p4 sync --branch=refs/remotes/someremote/depot >out && + test_i18ngrep "No changes to import!" out + ) +' + +test_expect_success 'git p4 sync nonexistent ref' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_commit head && + git p4 sync --branch=depot //depot@all && + test_must_fail git p4 sync --branch=depot2 2>errs && + test_i18ngrep "Perhaps you never did" errs + ) +' + +test_expect_success 'git p4 sync existing non-p4-imported ref' ' + test_create_repo "$git" && + test_when_finished cleanup_git && + ( + cd "$git" && + test_commit head && + git p4 sync --branch=depot //depot@all && + test_must_fail git p4 sync --branch=refs/heads/master 2>errs && + test_i18ngrep "Perhaps you never did" errs + ) +' + test_expect_success 'clone two dirs' ' ( cd "$cli" && diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh index 50a6f8b..759a14f 100755 --- a/t/t9801-git-p4-branch.sh +++ b/t/t9801-git-p4-branch.sh @@ -129,6 +129,16 @@ test_expect_success 'import depot, branch detection' ' ) ' +test_expect_success 'sync specific detected branch' ' + test_when_finished cleanup_git && + git p4 clone --dest="$git" --detect-branches //depot@all && + ( + cd "$git" && + git p4 sync --branch=depot/branch2 >out && + test_i18ngrep "No changes to import!" out + ) +' + test_expect_success 'import depot, branch detection, branchList branch definition' ' test_when_finished cleanup_git && test_create_repo "$git" && diff --git a/t/t9802-git-p4-filetype.sh b/t/t9802-git-p4-filetype.sh index 19073c6..2a6ee2a 100755 --- a/t/t9802-git-p4-filetype.sh +++ b/t/t9802-git-p4-filetype.sh @@ -333,4 +333,38 @@ test_expect_success SYMLINKS 'empty symlink target' ' ) ' +test_expect_success SYMLINKS 'utf-8 with and without BOM in text file' ' + ( + cd "$cli" && + + # some utf8 content + echo some tǣxt >utf8-nobom-test && + + # same utf8 content as before but with bom + echo some tǣxt | sed '\''s/^/\xef\xbb\xbf/'\'' >utf8-bom-test && + + # bom only + dd bs=1 count=3 if=utf8-bom-test of=utf8-bom-empty-test && + + p4 add utf8-nobom-test utf8-bom-test utf8-bom-empty-test && + p4 submit -d "add utf8 test files" + ) && + test_when_finished cleanup_git && + + git p4 clone --dest="$git" //depot@all && + ( + cd "$git" && + git checkout refs/remotes/p4/master && + + echo some tǣxt >utf8-nobom-check && + test_cmp utf8-nobom-check utf8-nobom-test && + + echo some tǣxt | sed '\''s/^/\xef\xbb\xbf/'\'' >utf8-bom-check && + test_cmp utf8-bom-check utf8-bom-test && + + dd bs=1 count=3 if=utf8-bom-check of=utf8-bom-empty-check && + test_cmp utf8-bom-empty-check utf8-bom-empty-test + ) +' + test_done diff --git a/t/t9835-git-p4-metadata-encoding-python2.sh b/t/t9835-git-p4-metadata-encoding-python2.sh new file mode 100755 index 0000000..036bf79 --- /dev/null +++ b/t/t9835-git-p4-metadata-encoding-python2.sh @@ -0,0 +1,213 @@ +#!/bin/sh + +test_description='git p4 metadata encoding + +This test checks that the import process handles inconsistent text +encoding in p4 metadata (author names, commit messages, etc) without +failing, and produces maximally sane output in git.' + +. ./lib-git-p4.sh + +python_target_version='2' + +############################### +## SECTION REPEATED IN t9836 ## +############################### + +# Please note: this test calls "git-p4.py" rather than "git-p4", because the +# latter references a specific path so we can't easily force it to run under +# the python version we need to. + +python_major_version=$(python -V 2>&1 | cut -c 8) +python_target_binary=$(which python$python_target_version) +if ! test "$python_major_version" = "$python_target_version" && test "$python_target_binary" +then + mkdir temp_python + PATH="$(pwd)/temp_python:$PATH" && export PATH + ln -s $python_target_binary temp_python/python +fi + +python_major_version=$(python -V 2>&1 | cut -c 8) +if ! test "$python_major_version" = "$python_target_version" +then + skip_all="skipping python$python_target_version-specific git p4 tests; python$python_target_version not available" + test_done +fi + +remove_user_cache () { + rm "$HOME/.gitp4-usercache.txt" || true +} + +test_expect_success 'start p4d' ' + start_p4d +' + +test_expect_success 'init depot' ' + ( + cd "$cli" && + + p4_add_user "utf8_author" "ǣuthor" && + P4USER=utf8_author && + touch file1 && + p4 add file1 && + p4 submit -d "first CL has some utf-8 tǣxt" && + + p4_add_user "latin1_author" "$(echo æuthor | + iconv -f utf8 -t latin1)" && + P4USER=latin1_author && + touch file2 && + p4 add file2 && + p4 submit -d "$(echo second CL has some latin-1 tæxt | + iconv -f utf8 -t latin1)" && + + p4_add_user "cp1252_author" "$(echo æuthœr | + iconv -f utf8 -t cp1252)" && + P4USER=cp1252_author && + touch file3 && + p4 add file3 && + p4 submit -d "$(echo third CL has sœme cp-1252 tæxt | + iconv -f utf8 -t cp1252)" && + + p4_add_user "cp850_author" "$(echo Åuthor | + iconv -f utf8 -t cp850)" && + P4USER=cp850_author && + touch file4 && + p4 add file4 && + p4 submit -d "$(echo fourth CL hÅs some cp850 text | + iconv -f utf8 -t cp850)" + ) +' + +test_expect_success 'clone non-utf8 repo with strict encoding' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + test_must_fail git -c git-p4.metadataDecodingStrategy=strict p4.py clone --dest="$git" //depot@all 2>err && + grep "Decoding perforce metadata failed!" err +' + +test_expect_success 'check utf-8 contents with passthrough strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=passthrough p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "some utf-8 tǣxt" actual && + grep "ǣuthor" actual + ) +' + +test_expect_success 'check latin-1 contents corrupted in git with passthrough strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=passthrough p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + badly_encoded_in_git=$(echo "some latin-1 tæxt" | iconv -f utf8 -t latin1) && + grep "$badly_encoded_in_git" actual && + bad_author_in_git="$(echo æuthor | iconv -f utf8 -t latin1)" && + grep "$bad_author_in_git" actual + ) +' + +test_expect_success 'check utf-8 contents with fallback strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "some utf-8 tǣxt" actual && + grep "ǣuthor" actual + ) +' + +test_expect_success 'check latin-1 contents with fallback strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "some latin-1 tæxt" actual && + grep "æuthor" actual + ) +' + +test_expect_success 'check cp-1252 contents with fallback strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "sœme cp-1252 tæxt" actual && + grep "æuthœr" actual + ) +' + +test_expect_success 'check cp850 contents parsed with correct fallback' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback -c git-p4.metadataFallbackEncoding=cp850 p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "hÅs some cp850 text" actual && + grep "Åuthor" actual + ) +' + +test_expect_success 'check cp850-only contents escaped when cp1252 is fallback' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "h%8Fs some cp850 text" actual && + grep "%8Futhor" actual + ) +' + +test_expect_success 'check cp-1252 contents on later sync after clone with fallback strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$cli" && + P4USER=cp1252_author && + touch file10 && + p4 add file10 && + p4 submit -d "$(echo later CL has sœme more cp-1252 tæxt | + iconv -f utf8 -t cp1252)" + ) && + ( + cd "$git" && + + git p4.py sync --branch=master && + + git log p4/master >actual && + grep "sœme more cp-1252 tæxt" actual && + grep "æuthœr" actual + ) +' + +############################ +## / END REPEATED SECTION ## +############################ + +test_expect_success 'passthrough (latin-1 contents corrupted in git) is the default with python2' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=passthrough p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + badly_encoded_in_git=$(echo "some latin-1 tæxt" | iconv -f utf8 -t latin1) && + grep "$badly_encoded_in_git" actual + ) +' + +test_done diff --git a/t/t9836-git-p4-metadata-encoding-python3.sh b/t/t9836-git-p4-metadata-encoding-python3.sh new file mode 100755 index 0000000..63350dc --- /dev/null +++ b/t/t9836-git-p4-metadata-encoding-python3.sh @@ -0,0 +1,214 @@ +#!/bin/sh + +test_description='git p4 metadata encoding + +This test checks that the import process handles inconsistent text +encoding in p4 metadata (author names, commit messages, etc) without +failing, and produces maximally sane output in git.' + +. ./lib-git-p4.sh + +python_target_version='3' + +############################### +## SECTION REPEATED IN t9835 ## +############################### + +# Please note: this test calls "git-p4.py" rather than "git-p4", because the +# latter references a specific path so we can't easily force it to run under +# the python version we need to. + +python_major_version=$(python -V 2>&1 | cut -c 8) +python_target_binary=$(which python$python_target_version) +if ! test "$python_major_version" = "$python_target_version" && test "$python_target_binary" +then + mkdir temp_python + PATH="$(pwd)/temp_python:$PATH" && export PATH + ln -s $python_target_binary temp_python/python +fi + +python_major_version=$(python -V 2>&1 | cut -c 8) +if ! test "$python_major_version" = "$python_target_version" +then + skip_all="skipping python$python_target_version-specific git p4 tests; python$python_target_version not available" + test_done +fi + +remove_user_cache () { + rm "$HOME/.gitp4-usercache.txt" || true +} + +test_expect_success 'start p4d' ' + start_p4d +' + +test_expect_success 'init depot' ' + ( + cd "$cli" && + + p4_add_user "utf8_author" "ǣuthor" && + P4USER=utf8_author && + touch file1 && + p4 add file1 && + p4 submit -d "first CL has some utf-8 tǣxt" && + + p4_add_user "latin1_author" "$(echo æuthor | + iconv -f utf8 -t latin1)" && + P4USER=latin1_author && + touch file2 && + p4 add file2 && + p4 submit -d "$(echo second CL has some latin-1 tæxt | + iconv -f utf8 -t latin1)" && + + p4_add_user "cp1252_author" "$(echo æuthœr | + iconv -f utf8 -t cp1252)" && + P4USER=cp1252_author && + touch file3 && + p4 add file3 && + p4 submit -d "$(echo third CL has sœme cp-1252 tæxt | + iconv -f utf8 -t cp1252)" && + + p4_add_user "cp850_author" "$(echo Åuthor | + iconv -f utf8 -t cp850)" && + P4USER=cp850_author && + touch file4 && + p4 add file4 && + p4 submit -d "$(echo fourth CL hÅs some cp850 text | + iconv -f utf8 -t cp850)" + ) +' + +test_expect_success 'clone non-utf8 repo with strict encoding' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + test_must_fail git -c git-p4.metadataDecodingStrategy=strict p4.py clone --dest="$git" //depot@all 2>err && + grep "Decoding perforce metadata failed!" err +' + +test_expect_success 'check utf-8 contents with passthrough strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=passthrough p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "some utf-8 tǣxt" actual && + grep "ǣuthor" actual + ) +' + +test_expect_success 'check latin-1 contents corrupted in git with passthrough strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=passthrough p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + badly_encoded_in_git=$(echo "some latin-1 tæxt" | iconv -f utf8 -t latin1) && + grep "$badly_encoded_in_git" actual && + bad_author_in_git="$(echo æuthor | iconv -f utf8 -t latin1)" && + grep "$bad_author_in_git" actual + ) +' + +test_expect_success 'check utf-8 contents with fallback strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "some utf-8 tǣxt" actual && + grep "ǣuthor" actual + ) +' + +test_expect_success 'check latin-1 contents with fallback strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "some latin-1 tæxt" actual && + grep "æuthor" actual + ) +' + +test_expect_success 'check cp-1252 contents with fallback strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "sœme cp-1252 tæxt" actual && + grep "æuthœr" actual + ) +' + +test_expect_success 'check cp850 contents parsed with correct fallback' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback -c git-p4.metadataFallbackEncoding=cp850 p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "hÅs some cp850 text" actual && + grep "Åuthor" actual + ) +' + +test_expect_success 'check cp850-only contents escaped when cp1252 is fallback' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "h%8Fs some cp850 text" actual && + grep "%8Futhor" actual + ) +' + +test_expect_success 'check cp-1252 contents on later sync after clone with fallback strategy' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git -c git-p4.metadataDecodingStrategy=fallback p4.py clone --dest="$git" //depot@all && + ( + cd "$cli" && + P4USER=cp1252_author && + touch file10 && + p4 add file10 && + p4 submit -d "$(echo later CL has sœme more cp-1252 tæxt | + iconv -f utf8 -t cp1252)" + ) && + ( + cd "$git" && + + git p4.py sync --branch=master && + + git log p4/master >actual && + grep "sœme more cp-1252 tæxt" actual && + grep "æuthœr" actual + ) +' + +############################ +## / END REPEATED SECTION ## +############################ + + +test_expect_success 'fallback (both utf-8 and cp-1252 contents handled) is the default with python3' ' + test_when_finished cleanup_git && + test_when_finished remove_user_cache && + git p4.py clone --dest="$git" //depot@all && + ( + cd "$git" && + git log >actual && + grep "sœme cp-1252 tæxt" actual && + grep "æuthœr" actual + ) +' + +test_done diff --git a/t/test-lib.sh b/t/test-lib.sh index 531cef0..8ba5ca1 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -535,9 +535,10 @@ case $GIT_TEST_FSYNC in ;; esac -# Add libc MALLOC and MALLOC_PERTURB test -# only if we are not executing the test with valgrind +# Add libc MALLOC and MALLOC_PERTURB test only if we are not executing +# the test with valgrind and have not compiled with SANITIZE=address. if test -n "$valgrind" || + test -n "$SANITIZE_ADDRESS" || test -n "$TEST_NO_MALLOC_CHECK" then setup_malloc_check () { @@ -1666,6 +1667,7 @@ test -n "$USE_LIBPCRE2" && test_set_prereq PCRE test -n "$USE_LIBPCRE2" && test_set_prereq LIBPCRE2 test -z "$NO_GETTEXT" && test_set_prereq GETTEXT test -n "$SANITIZE_LEAK" && test_set_prereq SANITIZE_LEAK +test -n "$GIT_VALGRIND_ENABLED" && test_set_prereq VALGRIND if test -z "$GIT_TEST_CHECK_CACHE_TREE" then |