summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/00compile.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/add_path_to_url.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/can_compress.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/canonicalize_url.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/collapse_dotdot.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/fatal.t0
-rwxr-xr-x[-rw-r--r--]t/Git-SVN/Utils/join_paths.t0
-rw-r--r--t/Makefile9
-rw-r--r--t/README112
-rw-r--r--t/annotate-tests.sh12
-rwxr-xr-xt/check-non-portable-shell.pl8
-rw-r--r--t/gitweb-lib.sh3
-rw-r--r--t/lib-bash.sh7
-rwxr-xr-xt/lib-credential.sh6
-rw-r--r--t/lib-cvs.sh4
-rw-r--r--t/lib-diff-alternative.sh3
-rw-r--r--t/lib-gettext.sh3
-rw-r--r--t/lib-git-daemon.sh28
-rw-r--r--t/lib-git-p4.sh23
-rwxr-xr-xt/lib-gpg.sh3
-rw-r--r--t/lib-httpd.sh82
-rw-r--r--t/lib-httpd/apache.conf5
-rw-r--r--[-rwxr-xr-x]t/lib-httpd/broken-smart-http.sh1
-rwxr-xr-xt/lib-httpd/error.sh31
-rw-r--r--t/lib-httpd/passwd2
-rw-r--r--t/lib-pack.sh2
-rw-r--r--t/lib-pager.sh2
-rw-r--r--t/lib-prereq-FILEMODE.sh11
-rw-r--r--t/lib-read-tree.sh2
-rw-r--r--t/lib-rebase.sh2
-rwxr-xr-xt/lib-submodule-update.sh680
-rw-r--r--t/lib-terminal.sh39
-rwxr-xr-xt/perf/p0001-rev-list.sh12
-rwxr-xr-xt/perf/p4001-diff-no-index.sh22
-rwxr-xr-xt/perf/p5302-pack-index.sh2
-rwxr-xr-xt/perf/p5310-pack-bitmaps.sh60
-rw-r--r--t/perf/perf-lib.sh4
-rwxr-xr-xt/t0000-basic.sh444
-rwxr-xr-xt/t0001-init.sh227
-rwxr-xr-xt/t0002-gitfile.sh3
-rwxr-xr-xt/t0003-attributes.sh63
-rwxr-xr-xt/t0005-signals.sh22
-rwxr-xr-xt/t0008-ignores.sh56
-rwxr-xr-xt/t0010-racy-git.sh4
-rwxr-xr-xt/t0011-hashmap.sh253
-rwxr-xr-xt/t0020-crlf.sh42
-rwxr-xr-xt/t0021-conversion.sh24
-rwxr-xr-xt/t0025-crlf-auto.sh122
-rwxr-xr-xt/t0026-eol-config.sh48
-rwxr-xr-xt/t0027-auto-crlf.sh285
-rwxr-xr-xt/t0030-stripspace.sh20
-rwxr-xr-xt/t0040-parse-options.sh7
-rwxr-xr-xt/t0060-path-utils.sh21
-rwxr-xr-xt/t0064-sha1-array.sh94
-rwxr-xr-xt/t0081-line-buffer.sh2
-rwxr-xr-xt/t0090-cache-tree.sh162
-rwxr-xr-xt/t0110-urlmatch-normalization.sh7
-rwxr-xr-x[-rw-r--r--]t/t0202/test.pl0
-rwxr-xr-xt/t0300-credentials.sh2
-rwxr-xr-xt/t1000-read-tree-m-3way.sh4
-rwxr-xr-xt/t1001-read-tree-m-2way.sh20
-rwxr-xr-xt/t1002-read-tree-m-u-2way.sh10
-rwxr-xr-xt/t1003-read-tree-prefix.sh2
-rwxr-xr-xt/t1004-read-tree-m-u-wf.sh8
-rwxr-xr-xt/t1006-cat-file.sh34
-rwxr-xr-xt/t1013-loose-object-format.sh66
-rwxr-xr-xt/t1013-read-tree-submodule.sh12
-rw-r--r--t/t1013/objects/14/9cedb5c46929d18e0f118e9fa31927487af3b6bin117 -> 0 bytes
-rw-r--r--t/t1013/objects/16/56f9233d999f61ef23ef390b9c71d75399f435bin17 -> 0 bytes
-rw-r--r--t/t1013/objects/1e/72a6b2c4a577ab0338860fa9fe87f761fc9bbdbin18 -> 0 bytes
-rw-r--r--t/t1013/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99bin19 -> 0 bytes
-rw-r--r--t/t1013/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752ebin10 -> 0 bytes
-rw-r--r--t/t1013/objects/6b/aee0540ea990d9761a3eb9ab183003a71c3696bin181 -> 0 bytes
-rw-r--r--t/t1013/objects/70/e6a83d8dcb26fc8bc0cf702e2ddeb6adca18fdbin26 -> 0 bytes
-rw-r--r--t/t1013/objects/76/e7fa9941f4d5f97f64fea65a2cba436bc79cbb2
-rw-r--r--t/t1013/objects/78/75c6237d3fcdd0ac2f0decc7d3fa6a50b66c09bin139 -> 0 bytes
-rw-r--r--t/t1013/objects/7a/37b887a73791d12d26c0d3e39568a8fb0fa6e8bin54 -> 0 bytes
-rw-r--r--t/t1013/objects/85/df50785d62d3b05ab03d9cbf7e4a0b49449730bin13 -> 0 bytes
-rw-r--r--t/t1013/objects/8d/4e360d6c70fbd72411991c02a09c442cf7a9fabin156 -> 0 bytes
-rw-r--r--t/t1013/objects/95/b1625de3ba8b2214d1e0d0591138aea733f64fbin252 -> 0 bytes
-rw-r--r--t/t1013/objects/9a/e9e86b7bd6cb1472d9373702d8249973da0832bin11 -> 0 bytes
-rw-r--r--t/t1013/objects/bd/15045f6ce8ff75747562173640456a394412c8bin34 -> 0 bytes
-rw-r--r--t/t1013/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391bin9 -> 0 bytes
-rw-r--r--t/t1013/objects/f8/16d5255855ac160652ee5253b06cd8ee14165a1
-rwxr-xr-xt/t1020-subdirectory.sh26
-rwxr-xr-xt/t1050-large.sh26
-rwxr-xr-xt/t1300-repo-config.sh81
-rwxr-xr-xt/t1302-repo-version.sh2
-rwxr-xr-xt/t1303-wacky-config.sh84
-rwxr-xr-xt/t1304-default-acl.sh2
-rwxr-xr-xt/t1305-config-include.sh32
-rwxr-xr-xt/t1308-config-set.sh221
-rwxr-xr-xt/t1400-update-ref.sh169
-rwxr-xr-xt/t1402-check-ref-format.sh41
-rwxr-xr-xt/t1410-reflog.sh42
-rwxr-xr-xt/t1413-reflog-detach.sh70
-rwxr-xr-xt/t1430-bad-ref-name.sh207
-rwxr-xr-xt/t1450-fsck.sh138
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh126
-rwxr-xr-xt/t1503-rev-parse-verify.sh37
-rwxr-xr-xt/t1507-rev-parse-upstream.sh2
-rwxr-xr-xt/t1510-repo-setup.sh4
-rwxr-xr-xt/t1600-index.sh76
-rwxr-xr-xt/t1700-split-index.sh194
-rwxr-xr-xt/t2013-checkout-submodule.sh5
-rwxr-xr-xt/t2104-update-index-skip-worktree.sh4
-rwxr-xr-xt/t2107-update-index-basic.sh17
-rwxr-xr-xt/t2200-add-update.sh9
-rwxr-xr-xt/t3004-ls-files-basic.sh17
-rwxr-xr-xt/t3030-merge-recursive.sh47
-rwxr-xr-xt/t3032-merge-recursive-options.sh6
-rwxr-xr-xt/t3070-wildmatch.sh13
-rwxr-xr-xt/t3200-branch.sh31
-rwxr-xr-xt/t3201-branch-contains.sh29
-rwxr-xr-xt/t3210-pack-refs.sh38
-rwxr-xr-xt/t3301-notes.sh49
-rwxr-xr-xt/t3302-notes-index-expensive.sh130
-rwxr-xr-xt/t3400-rebase.sh56
-rwxr-xr-xt/t3402-rebase-merge.sh15
-rwxr-xr-xt/t3404-rebase-interactive.sh77
-rwxr-xr-xt/t3413-rebase-hook.sh6
-rwxr-xr-xt/t3419-rebase-patch-id.sh25
-rwxr-xr-xt/t3420-rebase-autostash.sh15
-rwxr-xr-xt/t3426-rebase-submodule.sh46
-rwxr-xr-xt/t3508-cherry-pick-many-commits.sh6
-rwxr-xr-xt/t3512-cherry-pick-submodule.sh13
-rwxr-xr-xt/t3513-revert-submodule.sh32
-rwxr-xr-xt/t3600-rm.sh15
-rwxr-xr-xt/t3701-add-interactive.sh1
-rwxr-xr-xt/t3901-i18n-patch.sh19
-rwxr-xr-xt/t3903-stash.sh42
-rwxr-xr-xt/t3905-stash-include-untracked.sh4
-rwxr-xr-xt/t3906-stash-submodule.sh24
-rwxr-xr-xt/t3910-mac-os-precompose.sh26
-rwxr-xr-xt/t4005-diff-rename-2.sh2
-rwxr-xr-xt/t4006-diff-mode.sh2
-rwxr-xr-xt/t4009-diff-rename-4.sh2
-rwxr-xr-xt/t4010-diff-pathspec.sh27
-rwxr-xr-xt/t4012-diff-binary.sh16
-rwxr-xr-xt/t4013-diff-various.sh16
-rwxr-xr-xt/t4014-format-patch.sh85
-rwxr-xr-xt/t4018-diff-funcname.sh230
-rw-r--r--t/t4018/README18
-rw-r--r--t/t4018/cpp-c++-function4
-rw-r--r--t/t4018/cpp-class-constructor4
-rw-r--r--t/t4018/cpp-class-constructor-mem-init5
-rw-r--r--t/t4018/cpp-class-definition4
-rw-r--r--t/t4018/cpp-class-definition-derived5
-rw-r--r--t/t4018/cpp-class-destructor4
-rw-r--r--t/t4018/cpp-function-returning-global-type4
-rw-r--r--t/t4018/cpp-function-returning-nested5
-rw-r--r--t/t4018/cpp-function-returning-pointer4
-rw-r--r--t/t4018/cpp-function-returning-reference4
-rw-r--r--t/t4018/cpp-gnu-style-function5
-rw-r--r--t/t4018/cpp-namespace-definition4
-rw-r--r--t/t4018/cpp-operator-definition4
-rw-r--r--t/t4018/cpp-skip-access-specifiers8
-rw-r--r--t/t4018/cpp-skip-comment-block9
-rw-r--r--t/t4018/cpp-skip-labels8
-rw-r--r--t/t4018/cpp-struct-definition9
-rw-r--r--t/t4018/cpp-struct-single-line7
-rw-r--r--t/t4018/cpp-template-function-definition4
-rw-r--r--t/t4018/cpp-union-definition4
-rw-r--r--t/t4018/cpp-void-c-function4
-rw-r--r--t/t4018/custom1-pattern17
-rw-r--r--t/t4018/custom2-match-to-end-of-line8
-rw-r--r--t/t4018/custom3-alternation-in-pattern17
-rw-r--r--t/t4018/java-class-member-function8
-rw-r--r--t/t4018/perl-skip-end-of-heredoc8
-rw-r--r--t/t4018/perl-skip-forward-decl10
-rw-r--r--t/t4018/perl-skip-sub-in-pod18
-rw-r--r--t/t4018/perl-sub-definition4
-rw-r--r--t/t4018/perl-sub-definition-kr-brace4
-rwxr-xr-xt/t4020-diff-external.sh43
-rw-r--r--t/t4034/ada/expect2
-rwxr-xr-xt/t4035-diff-quiet.sh6
-rwxr-xr-xt/t4036-format-patch-signer-mime.sh2
-rwxr-xr-xt/t4038-diff-combined.sh36
-rwxr-xr-xt/t4039-diff-assume-unchanged.sh11
-rwxr-xr-xt/t4041-diff-submodule-option.sh9
-rwxr-xr-xt/t4053-diff-no-index.sh26
-rwxr-xr-xt/t4055-diff-context.sh2
-rwxr-xr-xt/t4056-diff-order.sh121
-rwxr-xr-xt/t4057-diff-combined-paths.sh106
-rwxr-xr-xt/t4102-apply-rename.sh3
-rwxr-xr-xt/t4107-apply-ignore-whitespace.sh12
-rwxr-xr-xt/t4116-apply-reverse.sh16
-rwxr-xr-xt/t4119-apply-config.sh19
-rwxr-xr-xt/t4120-apply-popt.sh1
-rwxr-xr-xt/t4124-apply-ws-rule.sh11
-rwxr-xr-xt/t4129-apply-samemode.sh1
-rwxr-xr-xt/t4137-apply-submodule.sh20
-rwxr-xr-xt/t4201-shortlog.sh12
-rwxr-xr-xt/t4202-log.sh31
-rwxr-xr-xt/t4204-patch-id.sh106
-rwxr-xr-xt/t4205-log-pretty-formats.sh243
-rwxr-xr-xt/t4209-log-pickaxe.sh166
-rwxr-xr-xt/t4210-log-i18n.sh4
-rwxr-xr-xt/t4211-line-log.sh5
-rwxr-xr-xt/t4212-log-corrupt.sh45
-rwxr-xr-xt/t4255-am-submodule.sh21
-rwxr-xr-xt/t5000-tar-tree.sh109
-rwxr-xr-xt/t5001-archive-attr.sh12
-rwxr-xr-xt/t5003-archive-zip.sh18
-rwxr-xr-xt/t5004-archive-corner-cases.sh2
-rwxr-xr-xt/t5100-mailinfo.sh18
-rw-r--r--t/t5100/embed-from.expect5
-rw-r--r--t/t5100/embed-from.in13
-rw-r--r--t/t5100/quoted-from.expect3
-rw-r--r--t/t5100/quoted-from.in10
-rwxr-xr-xt/t5150-request-pull.sh30
-rwxr-xr-xt/t5302-pack-index.sh23
-rwxr-xr-xt/t5304-prune.sh92
-rwxr-xr-xt/t5305-include-tag.sh4
-rwxr-xr-xt/t5310-pack-bitmaps.sh182
-rwxr-xr-xt/t5311-pack-bitmaps-shallow.sh39
-rwxr-xr-xt/t5400-send-pack.sh1
-rwxr-xr-xt/t5401-update-hooks.sh13
-rwxr-xr-xt/t5403-post-checkout-hook.sh8
-rwxr-xr-xt/t5408-send-pack-stdin.sh92
-rwxr-xr-xt/t5510-fetch.sh125
-rwxr-xr-xt/t5511-refspec.sh6
-rw-r--r--t/t5515/fetch.br-unconfig_--tags_.._.git1
-rw-r--r--t/t5515/fetch.master_--tags_.._.git1
-rwxr-xr-xt/t5516-fetch-push.sh141
-rwxr-xr-xt/t5525-fetch-tagopt.sh23
-rwxr-xr-xt/t5529-push-errors.sh48
-rwxr-xr-xt/t5531-deep-submodule-push.sh1
-rwxr-xr-xt/t5534-push-signed.sh171
-rwxr-xr-xt/t5536-fetch-conflicts.sh100
-rwxr-xr-xt/t5537-fetch-shallow.sh189
-rwxr-xr-xt/t5538-push-shallow.sh123
-rwxr-xr-xt/t5539-fetch-http-shallow.sh83
-rwxr-xr-xt/t5540-http-push-webdav.sh (renamed from t/t5540-http-push.sh)5
-rwxr-xr-xt/t5541-http-push-smart.sh (renamed from t/t5541-http-push.sh)63
-rwxr-xr-xt/t5542-push-http-shallow.sh100
-rwxr-xr-xt/t5550-http-fetch-dumb.sh (renamed from t/t5550-http-fetch.sh)36
-rwxr-xr-xt/t5551-http-fetch-smart.sh (renamed from t/t5551-http-fetch.sh)12
-rwxr-xr-xt/t5560-http-backend-noserver.sh10
-rwxr-xr-xt/t5561-http-backend.sh1
-rwxr-xr-xt/t5570-git-daemon.sh1
-rwxr-xr-xt/t5572-pull-submodule.sh45
-rwxr-xr-xt/t5601-clone.sh11
-rwxr-xr-xt/t5602-clone-remote-exec.sh13
-rwxr-xr-xt/t5701-clone-local.sh6
-rwxr-xr-xt/t5704-bundle.sh5
-rwxr-xr-xt/t5705-clone-2gb.sh2
-rwxr-xr-xt/t5801-remote-helpers.sh66
-rwxr-xr-xt/t6000-rev-list-misc.sh23
-rwxr-xr-xt/t6006-rev-list-format.sh129
-rwxr-xr-xt/t6010-merge-base.sh28
-rwxr-xr-xt/t6018-rev-list-glob.sh54
-rwxr-xr-xt/t6023-merge-file.sh91
-rwxr-xr-xt/t6031-merge-recursive.sh2
-rwxr-xr-xt/t6036-recursive-corner-cases.sh2
-rwxr-xr-xt/t6038-merge-text-auto.sh54
-rwxr-xr-xt/t6039-merge-ignorecase.sh53
-rwxr-xr-xt/t6041-bisect-submodule.sh32
-rwxr-xr-xt/t6050-replace.sh204
-rwxr-xr-xt/t6131-pathspec-icase.sh6
-rwxr-xr-xt/t6132-pathspec-exclude.sh184
-rwxr-xr-xt/t6300-for-each-ref.sh69
-rwxr-xr-xt/t6501-freshen-objects.sh132
-rwxr-xr-xt/t7001-mv.sh52
-rwxr-xr-xt/t7003-filter-branch.sh11
-rwxr-xr-xt/t7004-tag.sh105
-rwxr-xr-xt/t7006-pager.sh30
-rwxr-xr-xt/t7007-show.sh10
-rwxr-xr-xt/t7060-wtstatus.sh14
-rwxr-xr-xt/t7101-reset-empty-subdirs.sh (renamed from t/t7101-reset.sh)0
-rwxr-xr-xt/t7102-reset.sh43
-rwxr-xr-xt/t7104-reset-hard.sh (renamed from t/t7104-reset.sh)2
-rwxr-xr-xt/t7112-reset-submodule.sh14
-rwxr-xr-xt/t7201-co.sh17
-rwxr-xr-xt/t7300-clean.sh16
-rwxr-xr-xt/t7400-submodule-basic.sh5
-rwxr-xr-xt/t7406-submodule-update.sh10
-rwxr-xr-xt/t7407-submodule-foreach.sh9
-rwxr-xr-xt/t7500-commit.sh11
-rwxr-xr-xt/t7501-commit.sh54
-rwxr-xr-xt/t7502-commit.sh49
-rwxr-xr-xt/t7505-prepare-commit-msg-hook.sh33
-rwxr-xr-xt/t7508-status.sh77
-rwxr-xr-xt/t7509-commit.sh1
-rwxr-xr-xt/t7510-signed-commit.sh114
-rwxr-xr-xt/t7512-status-help.sh12
-rwxr-xr-xt/t7513-interpret-trailers.sh863
-rwxr-xr-xt/t7514-commit-patch.sh34
-rwxr-xr-xt/t7515-status-symlinks.sh43
-rwxr-xr-xt/t7600-merge.sh11
-rwxr-xr-xt/t7601-merge-pull-config.sh21
-rwxr-xr-xt/t7610-mergetool.sh933
-rwxr-xr-xt/t7613-merge-submodule.sh19
-rwxr-xr-xt/t7700-repack.sh34
-rwxr-xr-xt/t7701-repack-unpack-unreachable.sh13
-rwxr-xr-xt/t7702-repack-cyclic-alternate.sh24
-rwxr-xr-xt/t7800-difftool.sh72
-rwxr-xr-xt/t7810-grep.sh169
-rwxr-xr-xt/t8003-blame-corner-cases.sh9
-rwxr-xr-xt/t8005-blame-i18n.sh8
-rwxr-xr-xt/t9001-send-email.sh47
-rwxr-xr-xt/t9107-git-svn-migrate.sh54
-rwxr-xr-xt/t9114-git-svn-dcommit-merge.sh4
-rwxr-xr-xt/t9116-git-svn-log.sh46
-rwxr-xr-xt/t9117-git-svn-init-clone.sh20
-rwxr-xr-xt/t9118-git-svn-funky-branch-names.sh20
-rwxr-xr-xt/t9119-git-svn-info.sh30
-rwxr-xr-xt/t9120-git-svn-clone-with-percent-escapes.sh14
-rwxr-xr-xt/t9125-git-svn-multi-glob-branch-names.sh6
-rwxr-xr-xt/t9128-git-svn-cmd-branch.sh18
-rwxr-xr-xt/t9130-git-svn-authors-file.sh3
-rwxr-xr-xt/t9135-git-svn-moved-branch-empty-file.sh2
-rwxr-xr-xt/t9138-git-svn-authors-prog.sh35
-rwxr-xr-xt/t9141-git-svn-multiple-branches.sh28
-rwxr-xr-xt/t9145-git-svn-master-branch.sh2
-rwxr-xr-x[-rw-r--r--]t/t9150/make-svk-dump0
-rwxr-xr-x[-rw-r--r--]t/t9151/make-svnmerge-dump0
-rwxr-xr-xt/t9154-git-svn-fancy-glob.sh6
-rwxr-xr-xt/t9155-git-svn-fetch-deleted-tag.sh4
-rwxr-xr-xt/t9156-git-svn-fetch-deleted-tag-2.sh6
-rwxr-xr-xt/t9161-git-svn-mergeinfo-push.sh22
-rwxr-xr-xt/t9163-git-svn-reset-clears-caches.sh4
-rwxr-xr-xt/t9165-git-svn-fetch-merge-branch-of-branch.sh2
-rwxr-xr-xt/t9166-git-svn-fetch-merge-branch-of-branch2.sh2
-rwxr-xr-xt/t9167-git-svn-cmd-branch-subproject.sh2
-rwxr-xr-xt/t9200-git-cvsexportcommit.sh1
-rwxr-xr-xt/t9300-fast-import.sh164
-rwxr-xr-xt/t9350-fast-export.sh18
-rwxr-xr-xt/t9351-fast-export-anonymize.sh112
-rwxr-xr-xt/t9400-git-cvsserver-server.sh3
-rwxr-xr-xt/t9800-git-p4-basic.sh2
-rwxr-xr-xt/t9802-git-p4-filetype.sh83
-rwxr-xr-xt/t9805-git-p4-skip-submit-edit.sh6
-rwxr-xr-xt/t9807-git-p4-submit.sh5
-rwxr-xr-xt/t9809-git-p4-client-view.sh20
-rwxr-xr-xt/t9812-git-p4-wildcards.sh64
-rwxr-xr-xt/t9813-git-p4-preserve-users.sh38
-rwxr-xr-xt/t9814-git-p4-rename.sh10
-rwxr-xr-xt/t9815-git-p4-submit-fail.sh2
-rwxr-xr-xt/t9816-git-p4-locked.sh145
-rwxr-xr-xt/t9902-completion.sh44
-rwxr-xr-xt/t9903-bash-prompt.sh42
-rw-r--r--t/test-lib-functions.sh131
-rw-r--r--t/test-lib.sh211
344 files changed, 12406 insertions, 2464 deletions
diff --git a/t/Git-SVN/00compile.t b/t/Git-SVN/00compile.t
index c92fee453f..c92fee453f 100644..100755
--- a/t/Git-SVN/00compile.t
+++ b/t/Git-SVN/00compile.t
diff --git a/t/Git-SVN/Utils/add_path_to_url.t b/t/Git-SVN/Utils/add_path_to_url.t
index bfbd87845f..bfbd87845f 100644..100755
--- a/t/Git-SVN/Utils/add_path_to_url.t
+++ b/t/Git-SVN/Utils/add_path_to_url.t
diff --git a/t/Git-SVN/Utils/can_compress.t b/t/Git-SVN/Utils/can_compress.t
index d7b49b8d54..d7b49b8d54 100644..100755
--- a/t/Git-SVN/Utils/can_compress.t
+++ b/t/Git-SVN/Utils/can_compress.t
diff --git a/t/Git-SVN/Utils/canonicalize_url.t b/t/Git-SVN/Utils/canonicalize_url.t
index 05795ab636..05795ab636 100644..100755
--- a/t/Git-SVN/Utils/canonicalize_url.t
+++ b/t/Git-SVN/Utils/canonicalize_url.t
diff --git a/t/Git-SVN/Utils/collapse_dotdot.t b/t/Git-SVN/Utils/collapse_dotdot.t
index 1da1cce156..1da1cce156 100644..100755
--- a/t/Git-SVN/Utils/collapse_dotdot.t
+++ b/t/Git-SVN/Utils/collapse_dotdot.t
diff --git a/t/Git-SVN/Utils/fatal.t b/t/Git-SVN/Utils/fatal.t
index 49e1438295..49e1438295 100644..100755
--- a/t/Git-SVN/Utils/fatal.t
+++ b/t/Git-SVN/Utils/fatal.t
diff --git a/t/Git-SVN/Utils/join_paths.t b/t/Git-SVN/Utils/join_paths.t
index d4488e7162..d4488e7162 100644..100755
--- a/t/Git-SVN/Utils/join_paths.t
+++ b/t/Git-SVN/Utils/join_paths.t
diff --git a/t/Makefile b/t/Makefile
index 2373a04f7a..43b15e36ae 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -13,7 +13,7 @@ TAR ?= $(TAR)
RM ?= rm -f
PROVE ?= prove
DEFAULT_TEST_TARGET ?= test
-TEST_LINT ?= test-lint-duplicates test-lint-executable
+TEST_LINT ?= test-lint
ifdef TEST_OUTPUT_DIRECTORY
TEST_RESULTS_DIRECTORY = $(TEST_OUTPUT_DIRECTORY)/test-results
@@ -29,6 +29,7 @@ TEST_RESULTS_DIRECTORY_SQ = $(subst ','\'',$(TEST_RESULTS_DIRECTORY))
T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh))
TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh))
+THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
all: $(DEFAULT_TEST_TARGET)
@@ -36,11 +37,11 @@ test: pre-clean $(TEST_LINT)
$(MAKE) aggregate-results-and-cleanup
prove: pre-clean $(TEST_LINT)
- @echo "*** prove ***"; GIT_CONFIG=.git/config $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
+ @echo "*** prove ***"; $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
$(MAKE) clean-except-prove-cache
$(T):
- @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
+ @echo "*** $@ ***"; '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
pre-clean:
$(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
@@ -65,7 +66,7 @@ test-lint-executable:
echo >&2 "non-executable tests:" $$bad; exit 1; }
test-lint-shell-syntax:
- @'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T)
+ @'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS)
aggregate-results-and-cleanup: $(T)
$(MAKE) aggregate-results
diff --git a/t/README b/t/README
index caeeb9dedc..9952261299 100644
--- a/t/README
+++ b/t/README
@@ -71,6 +71,7 @@ You can pass --verbose (or -v), --debug (or -d), and --immediate
(or -i) command line argument to the test, or by setting GIT_TEST_OPTS
appropriately before running "make".
+-v::
--verbose::
This makes the test more verbose. Specifically, the
command being run and their output if any are also
@@ -81,6 +82,13 @@ appropriately before running "make".
numbers matching <pattern>. The number matched against is
simply the running count of the test within the file.
+-x::
+ Turn on shell tracing (i.e., `set -x`) during the tests
+ themselves. Implies `--verbose`. Note that this can cause
+ failures in some tests which redirect and test the
+ output of shell functions. Use with caution.
+
+-d::
--debug::
This may help the person who is developing a new test.
It causes the command defined with test_debug to run.
@@ -89,6 +97,7 @@ appropriately before running "make".
failed tests so that you can inspect its contents after
the test finished.
+-i::
--immediate::
This causes the test to immediately exit upon the first
failed test. Cleanup commands requested with
@@ -96,10 +105,17 @@ appropriately before running "make".
in order to keep the state for inspection by the tester
to diagnose the bug.
+-l::
--long-tests::
This causes additional long-running tests to be run (where
available), for more exhaustive testing.
+-r::
+--run=<test-selector>::
+ Run only the subset of tests indicated by
+ <test-selector>. See section "Skipping Tests" below for
+ <test-selector> syntax.
+
--valgrind=<tool>::
Execute all Git binaries under valgrind tool <tool> and exit
with status 126 on errors (just like regular tests, this will
@@ -187,10 +203,77 @@ and either can match the "t[0-9]{4}" part to skip the whole
test, or t[0-9]{4} followed by ".$number" to say which
particular test to skip.
-Note that some tests in the existing test suite rely on previous
-test item, so you cannot arbitrarily disable one and expect the
-remainder of test to check what the test originally was intended
-to check.
+For an individual test suite --run could be used to specify that
+only some tests should be run or that some tests should be
+excluded from a run.
+
+The argument for --run is a list of individual test numbers or
+ranges with an optional negation prefix that define what tests in
+a test suite to include in the run. A range is two numbers
+separated with a dash and matches a range of tests with both ends
+been included. You may omit the first or the second number to
+mean "from the first test" or "up to the very last test"
+respectively.
+
+Optional prefix of '!' means that the test or a range of tests
+should be excluded from the run.
+
+If --run starts with an unprefixed number or range the initial
+set of tests to run is empty. If the first item starts with '!'
+all the tests are added to the initial set. After initial set is
+determined every test number or range is added or excluded from
+the set one by one, from left to right.
+
+Individual numbers or ranges could be separated either by a space
+or a comma.
+
+For example, to run only tests up to a specific test (21), one
+could do this:
+
+ $ sh ./t9200-git-cvsexport-commit.sh --run='1-21'
+
+or this:
+
+ $ sh ./t9200-git-cvsexport-commit.sh --run='-21'
+
+Common case is to run several setup tests (1, 2, 3) and then a
+specific test (21) that relies on that setup:
+
+ $ sh ./t9200-git-cvsexport-commit.sh --run='1 2 3 21'
+
+or:
+
+ $ sh ./t9200-git-cvsexport-commit.sh --run=1,2,3,21
+
+or:
+
+ $ sh ./t9200-git-cvsexport-commit.sh --run='-3 21'
+
+As noted above, the test set is built going though items left to
+right, so this:
+
+ $ sh ./t9200-git-cvsexport-commit.sh --run='1-4 !3'
+
+will run tests 1, 2, and 4. Items that comes later have higher
+precendence. It means that this:
+
+ $ sh ./t9200-git-cvsexport-commit.sh --run='!3 1-4'
+
+would just run tests from 1 to 4, including 3.
+
+You may use negation with ranges. The following will run all
+test in the test suite except from 7 up to 11:
+
+ $ sh ./t9200-git-cvsexport-commit.sh --run='!7-11'
+
+Some tests in a test suite rely on the previous tests performing
+certain actions, specifically some tests are designated as
+"setup" test, so you cannot _arbitrarily_ disable one test and
+expect the rest to function correctly.
+
+--run is mostly useful when you want to focus on a specific test
+and know what setup is needed for it. Or when you want to run
+everything up to a certain test.
Naming Tests
@@ -596,6 +679,27 @@ library for your script to use.
...
'
+ - test_write_lines <lines>
+
+ Write <lines> on standard output, one line per argument.
+ Useful to prepare multi-line files in a compact form.
+
+ Example:
+
+ test_write_lines a b c d e f g >foo
+
+ Is a more compact equivalent of:
+ cat >foo <<-EOF
+ a
+ b
+ c
+ d
+ e
+ f
+ g
+ EOF
+
+
- test_pause
This command is useful for writing and debugging tests and must be
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index 304c7b7d87..071e4d7d3e 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -1,6 +1,17 @@
# This file isn't used as a test script directly, instead it is
# sourced from t8001-annotate.sh and t8002-blame.sh.
+if test_have_prereq MINGW
+then
+ sanitize_L () {
+ echo "$1" | sed 'sX\(^-L\|,\)\^\?/X&\\;*Xg'
+ }
+else
+ sanitize_L () {
+ echo "$1"
+ }
+fi
+
check_count () {
head= &&
file='file' &&
@@ -10,6 +21,7 @@ check_count () {
case "$1" in
-h) head="$2"; shift; shift ;;
-f) file="$2"; shift; shift ;;
+ -L*) options="$options $(sanitize_L "$1")"; shift ;;
-*) options="$options $1"; shift ;;
*) break ;;
esac
diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl
index 45971f43b7..b170cbc045 100755
--- a/t/check-non-portable-shell.pl
+++ b/t/check-non-portable-shell.pl
@@ -16,12 +16,12 @@ sub err {
while (<>) {
chomp;
- /^\s*sed\s+-i/ and err 'sed -i is not portable';
- /^\s*echo\s+-n/ and err 'echo -n is not portable (please use printf)';
+ /\bsed\s+-i/ and err 'sed -i is not portable';
+ /\becho\s+-n/ and err 'echo -n is not portable (please use printf)';
/^\s*declare\s+/ and err 'arrays/declare not portable';
/^\s*[^#]\s*which\s/ and err 'which is not portable (please use type)';
- /test\s+[^=]*==/ and err '"test a == b" is not portable (please use =)';
- /^\s*export\s+[^=]*=/ and err '"export FOO=bar" is not portable (please use FOO=bar && export FOO)';
+ /\btest\s+[^=]*==/ and err '"test a == b" is not portable (please use =)';
+ /\bexport\s+[A-Za-z0-9_]*=/ and err '"export FOO=bar" is not portable (please use FOO=bar && export FOO)';
# this resets our $. for each file
close ARGV if eof;
}
diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh
index 8cf909a6c5..d5dab5a94f 100644
--- a/t/gitweb-lib.sh
+++ b/t/gitweb-lib.sh
@@ -1,4 +1,5 @@
-#!/bin/sh
+# Initialization and helpers for Gitweb tests, which source this
+# shell library instead of test-lib.sh.
#
# Copyright (c) 2007 Jakub Narebski
#
diff --git a/t/lib-bash.sh b/t/lib-bash.sh
index 11397f747b..2be955fafb 100644
--- a/t/lib-bash.sh
+++ b/t/lib-bash.sh
@@ -1,7 +1,6 @@
-#!/bin/sh
-#
-# Ensures that tests are run under Bash; primarily intended for running tests
-# of the completion script.
+# Shell library sourced instead of ./test-lib.sh by tests that need
+# to run under Bash; primarily intended for tests of the completion
+# script.
if test -n "$BASH" && test -z "$POSIXLY_CORRECT"; then
# we are in full-on bash mode
diff --git a/t/lib-credential.sh b/t/lib-credential.sh
index 957ae936e8..d8e41f7ddd 100755
--- a/t/lib-credential.sh
+++ b/t/lib-credential.sh
@@ -278,12 +278,10 @@ helper_test_timeout() {
'
}
-cat >askpass <<\EOF
-#!/bin/sh
+write_script askpass <<\EOF
echo >&2 askpass: $*
-what=`echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z`
+what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z)
echo "askpass-$what"
EOF
-chmod +x askpass
GIT_ASKPASS="$PWD/askpass"
export GIT_ASKPASS
diff --git a/t/lib-cvs.sh b/t/lib-cvs.sh
index 44263ade25..9b2bcfb1b0 100644
--- a/t/lib-cvs.sh
+++ b/t/lib-cvs.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+# Shell library sourced instead of ./test-lib.sh by cvsimport tests.
. ./test-lib.sh
@@ -13,7 +13,7 @@ fi
CVS="cvs -f"
export CVS
-cvsps_version=`cvsps -h 2>&1 | sed -ne 's/cvsps version //p'`
+cvsps_version=$(cvsps -h 2>&1 | sed -ne 's/cvsps version //p')
case "$cvsps_version" in
2.1 | 2.2*)
;;
diff --git a/t/lib-diff-alternative.sh b/t/lib-diff-alternative.sh
index 75ffd9174f..8b4dbf22d2 100644
--- a/t/lib-diff-alternative.sh
+++ b/t/lib-diff-alternative.sh
@@ -1,4 +1,5 @@
-#!/bin/sh
+# Helpers shared by the test scripts for diff algorithms (patience,
+# histogram, etc).
test_diff_frobnitz() {
cat >file1 <<\EOF
diff --git a/t/lib-gettext.sh b/t/lib-gettext.sh
index ae8883a075..eec757f104 100644
--- a/t/lib-gettext.sh
+++ b/t/lib-gettext.sh
@@ -1,4 +1,5 @@
-#!/bin/sh
+# Initialization and Icelandic locale for basic git i18n tests,
+# which source this scriptlet instead of ./test-lib.sh.
#
# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
#
diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh
index 87f0ad8f41..bc4b3412fb 100644
--- a/t/lib-git-daemon.sh
+++ b/t/lib-git-daemon.sh
@@ -1,12 +1,29 @@
-#!/bin/sh
+# Shell library to run git-daemon in tests. Ends the test early if
+# GIT_TEST_GIT_DAEMON is not set.
+#
+# Usage:
+#
+# . ./test-lib.sh
+# . "$TEST_DIRECTORY"/lib-git-daemon.sh
+# start_git_daemon
+#
+# test_expect_success '...' '
+# ...
+# '
+#
+# test_expect_success ...
+#
+# stop_git_daemon
+# test_done
-if test -z "$GIT_TEST_GIT_DAEMON"
+test_tristate GIT_TEST_GIT_DAEMON
+if test "$GIT_TEST_GIT_DAEMON" = false
then
- skip_all="git-daemon testing disabled (define GIT_TEST_GIT_DAEMON to enable)"
+ skip_all="git-daemon testing disabled (unset GIT_TEST_GIT_DAEMON to enable)"
test_done
fi
-LIB_GIT_DAEMON_PORT=${LIB_GIT_DAEMON_PORT-'8121'}
+LIB_GIT_DAEMON_PORT=${LIB_GIT_DAEMON_PORT-${this_test#t}}
GIT_DAEMON_PID=
GIT_DAEMON_DOCUMENT_ROOT_PATH="$PWD"/repo
@@ -42,7 +59,8 @@ start_git_daemon() {
kill "$GIT_DAEMON_PID"
wait "$GIT_DAEMON_PID"
trap 'die' EXIT
- error "git daemon failed to start"
+ test_skip_or_die $GIT_TEST_GIT_DAEMON \
+ "git daemon failed to start"
fi
}
diff --git a/t/lib-git-p4.sh b/t/lib-git-p4.sh
index ccd918e79e..5aa8adcf9c 100644
--- a/t/lib-git-p4.sh
+++ b/t/lib-git-p4.sh
@@ -47,15 +47,22 @@ P4DPORT=$((10669 + ($testid - $git_p4_test_start)))
P4PORT=localhost:$P4DPORT
P4CLIENT=client
-P4EDITOR=:
+P4USER=author
+P4EDITOR=true
unset P4CHARSET
-export P4PORT P4CLIENT P4EDITOR P4CHARSET
+export P4PORT P4CLIENT P4USER P4EDITOR P4CHARSET
db="$TRASH_DIRECTORY/db"
cli="$TRASH_DIRECTORY/cli"
git="$TRASH_DIRECTORY/git"
pidfile="$TRASH_DIRECTORY/p4d.pid"
+# git p4 submit generates a temp file, which will
+# not get cleaned up if the submission fails. Don't
+# clutter up /tmp on the test machine.
+TMPDIR="$TRASH_DIRECTORY"
+export TMPDIR
+
start_p4d() {
mkdir -p "$db" "$cli" "$git" &&
rm -f "$pidfile" &&
@@ -96,12 +103,24 @@ start_p4d() {
return 1
fi
+ # build a p4 user so author@example.com has an entry
+ p4_add_user author
+
# build a client
client_view "//depot/... //client/..." &&
return 0
}
+p4_add_user() {
+ name=$1 &&
+ p4 user -f -i <<-EOF
+ User: $name
+ Email: $name@example.com
+ FullName: Dr. $name
+ EOF
+}
+
kill_p4d() {
pid=$(cat "$pidfile")
# it had better exist for the first kill
diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh
index 05824fa8e4..cd2baef383 100755
--- a/t/lib-gpg.sh
+++ b/t/lib-gpg.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-gpg_version=`gpg --version 2>&1`
+gpg_version=$(gpg --version 2>&1)
if test $? = 127; then
say "You do not seem to have gpg installed"
else
@@ -18,6 +18,7 @@ else
# No password given, to enable non-interactive operation.
cp -R "$TEST_DIRECTORY"/lib-gpg ./gpghome
chmod 0700 gpghome
+ chmod 0600 gpghome/*
GNUPGHOME="$(pwd)/gpghome"
export GNUPGHOME
test_set_prereq GPG
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index ad8f1ef71e..fd53b57187 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -1,14 +1,47 @@
-#!/bin/sh
+# Shell library to run an HTTP server for use in tests.
+# Ends the test early if httpd tests should not be run,
+# for example because the user has not enabled them.
+#
+# Usage:
+#
+# . ./test-lib.sh
+# . "$TEST_DIRECTORY"/lib-httpd.sh
+# start_httpd
+#
+# test_expect_success '...' '
+# ...
+# '
+#
+# test_expect_success ...
+#
+# stop_httpd
+# test_done
+#
+# Can be configured using the following variables.
+#
+# GIT_TEST_HTTPD enable HTTPD tests
+# LIB_HTTPD_PATH web server path
+# LIB_HTTPD_MODULE_PATH web server modules path
+# LIB_HTTPD_PORT listening port
+# LIB_HTTPD_DAV enable DAV
+# LIB_HTTPD_SVN enable SVN
+# LIB_HTTPD_SSL enable SSL
#
# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
#
-if test -z "$GIT_TEST_HTTPD"
+test_tristate GIT_TEST_HTTPD
+if test "$GIT_TEST_HTTPD" = false
then
- skip_all="Network testing disabled (define GIT_TEST_HTTPD to enable)"
+ skip_all="Network testing disabled (unset GIT_TEST_HTTPD to enable)"
test_done
fi
+if ! test_have_prereq SANITY; then
+ test_skip_or_die $GIT_TEST_HTTPD \
+ "Cannot run httpd tests as root"
+fi
+
HTTPD_PARA=""
for DEFAULT_HTTPD_PATH in '/usr/sbin/httpd' '/usr/sbin/apache2'
@@ -37,7 +70,7 @@ case $(uname) in
esac
LIB_HTTPD_PATH=${LIB_HTTPD_PATH-"$DEFAULT_HTTPD_PATH"}
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'8111'}
+LIB_HTTPD_PORT=${LIB_HTTPD_PORT-${this_test#t}}
TEST_PATH="$TEST_DIRECTORY"/lib-httpd
HTTPD_ROOT_PATH="$PWD"/httpd
@@ -49,8 +82,7 @@ GIT_VALGRIND_OPTIONS=$GIT_VALGRIND_OPTIONS; export GIT_VALGRIND_OPTIONS
if ! test -x "$LIB_HTTPD_PATH"
then
- skip_all="skipping test, no web server found at '$LIB_HTTPD_PATH'"
- test_done
+ test_skip_or_die $GIT_TEST_HTTPD "no web server found at '$LIB_HTTPD_PATH'"
fi
HTTPD_VERSION=`$LIB_HTTPD_PATH -v | \
@@ -62,25 +94,31 @@ then
then
if ! test $HTTPD_VERSION -ge 2
then
- skip_all="skipping test, at least Apache version 2 is required"
- test_done
+ test_skip_or_die $GIT_TEST_HTTPD \
+ "at least Apache version 2 is required"
fi
if ! test -d "$DEFAULT_HTTPD_MODULE_PATH"
then
- skip_all="Apache module directory not found. Skipping tests."
- test_done
+ test_skip_or_die $GIT_TEST_HTTPD \
+ "Apache module directory not found"
fi
LIB_HTTPD_MODULE_PATH="$DEFAULT_HTTPD_MODULE_PATH"
fi
else
- error "Could not identify web server at '$LIB_HTTPD_PATH'"
+ test_skip_or_die $GIT_TEST_HTTPD \
+ "Could not identify web server at '$LIB_HTTPD_PATH'"
fi
+install_script () {
+ write_script "$HTTPD_ROOT_PATH/$1" <"$TEST_PATH/$1"
+}
+
prepare_httpd() {
mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH"
cp "$TEST_PATH"/passwd "$HTTPD_ROOT_PATH"
- cp "$TEST_PATH"/broken-smart-http.sh "$HTTPD_ROOT_PATH"
+ install_script broken-smart-http.sh
+ install_script error.sh
ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
@@ -102,9 +140,9 @@ prepare_httpd() {
HTTPD_DEST=127.0.0.1:$LIB_HTTPD_PORT
HTTPD_URL=$HTTPD_PROTO://$HTTPD_DEST
HTTPD_URL_USER=$HTTPD_PROTO://user%40host@$HTTPD_DEST
- HTTPD_URL_USER_PASS=$HTTPD_PROTO://user%40host:user%40host@$HTTPD_DEST
+ HTTPD_URL_USER_PASS=$HTTPD_PROTO://user%40host:pass%40host@$HTTPD_DEST
- if test -n "$LIB_HTTPD_DAV" -o -n "$LIB_HTTPD_SVN"
+ if test -n "$LIB_HTTPD_DAV" || test -n "$LIB_HTTPD_SVN"
then
HTTPD_PARA="$HTTPD_PARA -DDAV"
@@ -128,9 +166,8 @@ start_httpd() {
>&3 2>&4
if test $? -ne 0
then
- skip_all="skipping test, web server setup failed"
trap 'die' EXIT
- test_done
+ test_skip_or_die $GIT_TEST_HTTPD "web server setup failed"
fi
}
@@ -190,7 +227,15 @@ setup_askpass_helper() {
test_expect_success 'setup askpass helper' '
write_script "$TRASH_DIRECTORY/askpass" <<-\EOF &&
echo >>"$TRASH_DIRECTORY/askpass-query" "askpass: $*" &&
- cat "$TRASH_DIRECTORY/askpass-response"
+ case "$*" in
+ *Username*)
+ what=user
+ ;;
+ *Password*)
+ what=pass
+ ;;
+ esac &&
+ cat "$TRASH_DIRECTORY/askpass-$what"
EOF
GIT_ASKPASS="$TRASH_DIRECTORY/askpass" &&
export GIT_ASKPASS &&
@@ -200,7 +245,8 @@ setup_askpass_helper() {
set_askpass() {
>"$TRASH_DIRECTORY/askpass-query" &&
- echo "$*" >"$TRASH_DIRECTORY/askpass-response"
+ echo "$1" >"$TRASH_DIRECTORY/askpass-user" &&
+ echo "$2" >"$TRASH_DIRECTORY/askpass-pass"
}
expect_askpass() {
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 3a03e8263d..7713dd2609 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -68,6 +68,7 @@ LockFile accept.lock
PassEnv GIT_VALGRIND
PassEnv GIT_VALGRIND_OPTIONS
+PassEnv GNUPGHOME
Alias /dumb/ www/
Alias /auth/dumb/ www/auth/dumb/
@@ -97,12 +98,16 @@ Alias /auth/dumb/ www/auth/dumb/
</LocationMatch>
ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
ScriptAlias /broken_smart/ broken-smart-http.sh/
+ScriptAlias /error/ error.sh/
<Directory ${GIT_EXEC_PATH}>
Options FollowSymlinks
</Directory>
<Files broken-smart-http.sh>
Options ExecCGI
</Files>
+<Files error.sh>
+ Options ExecCGI
+</Files>
<Files ${GIT_EXEC_PATH}/git-http-backend>
Options ExecCGI
</Files>
diff --git a/t/lib-httpd/broken-smart-http.sh b/t/lib-httpd/broken-smart-http.sh
index f7ebfffa80..82cc610b0a 100755..100644
--- a/t/lib-httpd/broken-smart-http.sh
+++ b/t/lib-httpd/broken-smart-http.sh
@@ -1,4 +1,3 @@
-#!/bin/sh
printf "Content-Type: text/%s\n" "html"
echo
printf "%s\n" "001e# service=git-upload-pack"
diff --git a/t/lib-httpd/error.sh b/t/lib-httpd/error.sh
new file mode 100755
index 0000000000..a77b8e5469
--- /dev/null
+++ b/t/lib-httpd/error.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+printf "Status: 500 Intentional Breakage\n"
+
+printf "Content-Type: "
+charset=iso-8859-1
+case "$PATH_INFO" in
+*html*)
+ printf "text/html"
+ ;;
+*text*)
+ printf "text/plain"
+ ;;
+*charset*)
+ printf "text/plain; charset=utf-8"
+ charset=utf-8
+ ;;
+*utf16*)
+ printf "text/plain; charset=utf-16"
+ charset=utf-16
+ ;;
+*odd-spacing*)
+ printf "text/plain; foo=bar ;charset=utf-16; other=nonsense"
+ charset=utf-16
+ ;;
+esac
+printf "\n"
+
+printf "\n"
+printf "this is the error message\n" |
+iconv -f us-ascii -t $charset
diff --git a/t/lib-httpd/passwd b/t/lib-httpd/passwd
index f2fbcad33e..99a34d6487 100644
--- a/t/lib-httpd/passwd
+++ b/t/lib-httpd/passwd
@@ -1 +1 @@
-user@host:nKpa8pZUHx/ic
+user@host:xb4E8pqD81KQs
diff --git a/t/lib-pack.sh b/t/lib-pack.sh
index b96e1254dd..7509846571 100644
--- a/t/lib-pack.sh
+++ b/t/lib-pack.sh
@@ -1,5 +1,3 @@
-#!/bin/sh
-#
# Support routines for hand-crafting weird or malicious packs.
#
# You can make a complete pack like:
diff --git a/t/lib-pager.sh b/t/lib-pager.sh
index ba03eab14f..3aa7a3ffd8 100644
--- a/t/lib-pager.sh
+++ b/t/lib-pager.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+# Helpers for tests of git's choice of pager.
test_expect_success 'determine default pager' '
test_might_fail git config --unset core.pager &&
diff --git a/t/lib-prereq-FILEMODE.sh b/t/lib-prereq-FILEMODE.sh
deleted file mode 100644
index bce5a4c8bd..0000000000
--- a/t/lib-prereq-FILEMODE.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2010 Ævar Arnfjörð Bjarmason
-#
-
-if test "$(git config --bool core.filemode)" = false
-then
- say 'filemode disabled on the filesystem'
-else
- test_set_prereq FILEMODE
-fi
diff --git a/t/lib-read-tree.sh b/t/lib-read-tree.sh
index ef079afc46..b95f485606 100644
--- a/t/lib-read-tree.sh
+++ b/t/lib-read-tree.sh
@@ -1,5 +1,3 @@
-#!/bin/sh
-#
# Helper functions to check if read-tree would succeed/fail as expected with
# and without the dry-run option. They also test that the dry-run does not
# write the index and that together with -u it doesn't touch the work tree.
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index 8ff87fb3f9..6bd252212a 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+# Helper functions used by interactive rebase tests.
# After setting the fake editor with this function, you can
#
diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh
new file mode 100755
index 0000000000..79cdd34a54
--- /dev/null
+++ b/t/lib-submodule-update.sh
@@ -0,0 +1,680 @@
+# Create a submodule layout used for all tests below.
+#
+# The following use cases are covered:
+# - New submodule (no_submodule => add_sub1)
+# - Removed submodule (add_sub1 => remove_sub1)
+# - Updated submodule (add_sub1 => modify_sub1)
+# - Submodule updated to invalid commit (add_sub1 => invalid_sub1)
+# - Submodule updated from invalid commit (invalid_sub1 => valid_sub1)
+# - Submodule replaced by tracked files in directory (add_sub1 =>
+# replace_sub1_with_directory)
+# - Directory containing tracked files replaced by submodule
+# (replace_sub1_with_directory => replace_directory_with_sub1)
+# - Submodule replaced by tracked file with the same name (add_sub1 =>
+# replace_sub1_with_file)
+# - Tracked file replaced by submodule (replace_sub1_with_file =>
+# replace_file_with_sub1)
+#
+# --O-----O
+# / ^ replace_directory_with_sub1
+# / replace_sub1_with_directory
+# /----O
+# / ^
+# / modify_sub1
+# O------O-------O
+# ^ ^\ ^
+# | | \ remove_sub1
+# | | -----O-----O
+# | | \ ^ replace_file_with_sub1
+# | | \ replace_sub1_with_file
+# | add_sub1 --O-----O
+# no_submodule ^ valid_sub1
+# invalid_sub1
+#
+create_lib_submodule_repo () {
+ git init submodule_update_repo &&
+ (
+ cd submodule_update_repo &&
+ echo "expect" >>.gitignore &&
+ echo "actual" >>.gitignore &&
+ echo "x" >file1 &&
+ echo "y" >file2 &&
+ git add .gitignore file1 file2 &&
+ git commit -m "Base" &&
+ git branch "no_submodule" &&
+
+ git checkout -b "add_sub1" &&
+ git submodule add ./. sub1 &&
+ git config -f .gitmodules submodule.sub1.ignore all &&
+ git config submodule.sub1.ignore all &&
+ git add .gitmodules &&
+ git commit -m "Add sub1" &&
+ git checkout -b remove_sub1 &&
+ git revert HEAD &&
+
+ git checkout -b "modify_sub1" "add_sub1" &&
+ git submodule update &&
+ (
+ cd sub1 &&
+ git fetch &&
+ git checkout -b "modifications" &&
+ echo "z" >file2 &&
+ echo "x" >file3 &&
+ git add file2 file3 &&
+ git commit -m "modified file2 and added file3" &&
+ git push origin modifications
+ ) &&
+ git add sub1 &&
+ git commit -m "Modify sub1" &&
+
+ git checkout -b "replace_sub1_with_directory" "add_sub1" &&
+ git submodule update &&
+ (
+ cd sub1 &&
+ git checkout modifications
+ ) &&
+ git rm --cached sub1 &&
+ rm sub1/.git* &&
+ git config -f .gitmodules --remove-section "submodule.sub1" &&
+ git add .gitmodules sub1/* &&
+ git commit -m "Replace sub1 with directory" &&
+ git checkout -b replace_directory_with_sub1 &&
+ git revert HEAD &&
+
+ git checkout -b "replace_sub1_with_file" "add_sub1" &&
+ git rm sub1 &&
+ echo "content" >sub1 &&
+ git add sub1 &&
+ git commit -m "Replace sub1 with file" &&
+ git checkout -b replace_file_with_sub1 &&
+ git revert HEAD &&
+
+ git checkout -b "invalid_sub1" "add_sub1" &&
+ git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 sub1 &&
+ git commit -m "Invalid sub1 commit" &&
+ git checkout -b valid_sub1 &&
+ git revert HEAD &&
+ git checkout master
+ )
+}
+
+# Helper function to replace gitfile with .git directory
+replace_gitfile_with_git_dir () {
+ (
+ cd "$1" &&
+ git_dir="$(git rev-parse --git-dir)" &&
+ rm -f .git &&
+ cp -R "$git_dir" .git &&
+ GIT_WORK_TREE=. git config --unset core.worktree
+ )
+}
+
+# Test that the .git directory in the submodule is unchanged (except for the
+# core.worktree setting, which appears only in $GIT_DIR/modules/$1/config).
+# Call this function before test_submodule_content as the latter might
+# write the index file leading to false positive index differences.
+#
+# Note that this only supports submodules at the root level of the
+# superproject, with the default name, i.e. same as its path.
+test_git_directory_is_unchanged () {
+ (
+ cd ".git/modules/$1" &&
+ # does core.worktree point at the right place?
+ test "$(git config core.worktree)" = "../../../$1" &&
+ # remove it temporarily before comparing, as
+ # "$1/.git/config" lacks it...
+ git config --unset core.worktree
+ ) &&
+ diff -r ".git/modules/$1" "$1/.git" &&
+ (
+ # ... and then restore.
+ cd ".git/modules/$1" &&
+ git config core.worktree "../../../$1"
+ )
+}
+
+# Helper function to be executed at the start of every test below, it sets up
+# the submodule repo if it doesn't exist and configures the most problematic
+# settings for diff.ignoreSubmodules.
+prolog () {
+ (test -d submodule_update_repo || create_lib_submodule_repo) &&
+ test_config_global diff.ignoreSubmodules all &&
+ test_config diff.ignoreSubmodules all
+}
+
+# Helper function to bring work tree back into the state given by the
+# commit. This includes trying to populate sub1 accordingly if it exists and
+# should be updated to an existing commit.
+reset_work_tree_to () {
+ rm -rf submodule_update &&
+ git clone submodule_update_repo submodule_update &&
+ (
+ cd submodule_update &&
+ rm -rf sub1 &&
+ git checkout -f "$1" &&
+ git status -u -s >actual &&
+ test_must_be_empty actual &&
+ sha1=$(git rev-parse --revs-only HEAD:sub1) &&
+ if test -n "$sha1" &&
+ test $(cd "sub1" && git rev-parse --verify "$sha1^{commit}")
+ then
+ git submodule update --init --recursive "sub1"
+ fi
+ )
+}
+
+# Test that the superproject contains the content according to commit "$1"
+# (the work tree must match the index for everything but submodules but the
+# index must exactly match the given commit including any submodule SHA-1s).
+test_superproject_content () {
+ git diff-index --cached "$1" >actual &&
+ test_must_be_empty actual &&
+ git diff-files --ignore-submodules >actual &&
+ test_must_be_empty actual
+}
+
+# Test that the given submodule at path "$1" contains the content according
+# to the submodule commit recorded in the superproject's commit "$2"
+test_submodule_content () {
+ if test $# != 2
+ then
+ echo "test_submodule_content needs two arguments"
+ return 1
+ fi &&
+ submodule="$1" &&
+ commit="$2" &&
+ test -d "$submodule"/ &&
+ if ! test -f "$submodule"/.git && ! test -d "$submodule"/.git
+ then
+ echo "Submodule $submodule is not populated"
+ return 1
+ fi &&
+ sha1=$(git rev-parse --verify "$commit:$submodule") &&
+ if test -z "$sha1"
+ then
+ echo "Couldn't retrieve SHA-1 of $submodule for $commit"
+ return 1
+ fi &&
+ (
+ cd "$submodule" &&
+ git status -u -s >actual &&
+ test_must_be_empty actual &&
+ git diff "$sha1" >actual &&
+ test_must_be_empty actual
+ )
+}
+
+# Test that the following transitions are correctly handled:
+# - Updated submodule
+# - New submodule
+# - Removed submodule
+# - Directory containing tracked files replaced by submodule
+# - Submodule replaced by tracked files in directory
+# - Submodule replaced by tracked file with the same name
+# - tracked file replaced by submodule
+#
+# The default is that submodule contents aren't changed until "git submodule
+# update" is run. And even then that command doesn't delete the work tree of
+# a removed submodule.
+#
+# Removing a submodule containing a .git directory must fail even when forced
+# to protect the history!
+#
+
+# Test that submodule contents are currently not updated when switching
+# between commits that change a submodule.
+test_submodule_switch () {
+ command="$1"
+ ######################### Appearing submodule #########################
+ # Switching to a commit letting a submodule appear creates empty dir ...
+ if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1
+ then
+ # Restoring stash fails to restore submodule index entry
+ RESULT="failure"
+ else
+ RESULT="success"
+ fi
+ test_expect_$RESULT "$command: added submodule creates empty directory" '
+ prolog &&
+ reset_work_tree_to no_submodule &&
+ (
+ cd submodule_update &&
+ git branch -t add_sub1 origin/add_sub1 &&
+ $command add_sub1 &&
+ test_superproject_content origin/add_sub1 &&
+ test_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # ... and doesn't care if it already exists ...
+ test_expect_$RESULT "$command: added submodule leaves existing empty directory alone" '
+ prolog &&
+ reset_work_tree_to no_submodule &&
+ (
+ cd submodule_update &&
+ mkdir sub1 &&
+ git branch -t add_sub1 origin/add_sub1 &&
+ $command add_sub1 &&
+ test_superproject_content origin/add_sub1 &&
+ test_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ 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 unignored file with same name" '
+ prolog &&
+ reset_work_tree_to 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
+ )
+ '
+ # Replacing a tracked file with a submodule produces an empty
+ # directory ...
+ test_expect_$RESULT "$command: replace tracked file with submodule creates empty directory" '
+ prolog &&
+ reset_work_tree_to replace_sub1_with_file &&
+ (
+ 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_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ test_submodule_content sub1 origin/replace_file_with_sub1
+ )
+ '
+ # ... as does removing a directory with tracked files with a
+ # submodule.
+ if test "$KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR" = 1
+ then
+ # Non fast-forward merges fail with "Directory sub1 doesn't
+ # exist. sub1" because the empty submodule directory is not
+ # created
+ RESULT="failure"
+ else
+ RESULT="success"
+ fi
+ test_expect_$RESULT "$command: replace directory with submodule" '
+ prolog &&
+ reset_work_tree_to replace_sub1_with_directory &&
+ (
+ 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_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ test_submodule_content sub1 origin/replace_directory_with_sub1
+ )
+ '
+
+ ######################## Disappearing submodule #######################
+ # Removing a submodule doesn't remove its work tree ...
+ if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1
+ then
+ RESULT="failure"
+ else
+ RESULT="success"
+ fi
+ test_expect_$RESULT "$command: removed submodule leaves submodule directory and its contents in place" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t remove_sub1 origin/remove_sub1 &&
+ $command remove_sub1 &&
+ test_superproject_content origin/remove_sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # ... especially when it contains a .git directory.
+ test_expect_$RESULT "$command: removed submodule leaves submodule containing a .git directory alone" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t remove_sub1 origin/remove_sub1 &&
+ replace_gitfile_with_git_dir sub1 &&
+ $command remove_sub1 &&
+ test_superproject_content origin/remove_sub1 &&
+ test_git_directory_is_unchanged sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # Replacing a submodule with files in a directory must fail as the
+ # submodule work tree isn't removed ...
+ if test "$KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES" = 1
+ then
+ # Non fast-forward merges attempt to merge the former
+ # submodule files with the newly checked out ones in the
+ # directory of the same name while it shouldn't.
+ RESULT="failure"
+ else
+ RESULT="success"
+ fi
+ test_expect_$RESULT "$command: replace submodule with a directory must fail" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
+ test_must_fail $command replace_sub1_with_directory &&
+ test_superproject_content origin/add_sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # ... especially when it contains a .git directory.
+ test_expect_$RESULT "$command: replace submodule containing a .git directory with a directory must fail" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
+ replace_gitfile_with_git_dir sub1 &&
+ test_must_fail $command replace_sub1_with_directory &&
+ test_superproject_content origin/add_sub1 &&
+ test_git_directory_is_unchanged sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # Replacing it with a file must fail as it could throw away any local
+ # work tree changes ...
+ test_expect_failure "$command: replace submodule with a file must fail" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
+ test_must_fail $command replace_sub1_with_file &&
+ test_superproject_content origin/add_sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # ... or even destroy unpushed parts of submodule history if that
+ # still uses a .git directory.
+ test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
+ replace_gitfile_with_git_dir sub1 &&
+ test_must_fail $command replace_sub1_with_file &&
+ test_superproject_content origin/add_sub1 &&
+ test_git_directory_is_unchanged sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+
+ ########################## Modified submodule #########################
+ # Updating a submodule sha1 doesn't update the submodule's work tree
+ if test "$KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT" = 1
+ then
+ # When cherry picking a SHA-1 update for an ignored submodule
+ # the commit incorrectly fails with "The previous cherry-pick
+ # is now empty, possibly due to conflict resolution."
+ RESULT="failure"
+ else
+ RESULT="success"
+ fi
+ test_expect_$RESULT "$command: modified submodule does not update submodule work tree" '
+ prolog &&
+ reset_work_tree_to 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/add_sub1 &&
+ git submodule update &&
+ 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_$RESULT "$command: modified submodule does not update submodule work tree to invalid commit" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t invalid_sub1 origin/invalid_sub1 &&
+ $command invalid_sub1 &&
+ test_superproject_content origin/invalid_sub1 &&
+ test_submodule_content sub1 origin/add_sub1 &&
+ test_must_fail git submodule update &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # Updating a submodule from an invalid sha1 doesn't update the
+ # submodule's work tree, subsequent update will succeed
+ test_expect_$RESULT "$command: modified submodule does not update submodule work tree from invalid commit" '
+ prolog &&
+ reset_work_tree_to invalid_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t valid_sub1 origin/valid_sub1 &&
+ $command valid_sub1 &&
+ test_superproject_content origin/valid_sub1 &&
+ test_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ test_submodule_content sub1 origin/valid_sub1
+ )
+ '
+}
+
+# Test that submodule contents are currently not updated when switching
+# between commits that change a submodule, but throwing away local changes in
+# the superproject is allowed.
+test_submodule_forced_switch () {
+ command="$1"
+ ######################### Appearing submodule #########################
+ # Switching to a commit letting a submodule appear creates empty dir ...
+ test_expect_success "$command: added submodule creates empty directory" '
+ prolog &&
+ reset_work_tree_to no_submodule &&
+ (
+ cd submodule_update &&
+ git branch -t add_sub1 origin/add_sub1 &&
+ $command add_sub1 &&
+ test_superproject_content origin/add_sub1 &&
+ test_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # ... and doesn't care if it already exists ...
+ test_expect_success "$command: added submodule leaves existing empty directory alone" '
+ prolog &&
+ reset_work_tree_to no_submodule &&
+ (
+ cd submodule_update &&
+ git branch -t add_sub1 origin/add_sub1 &&
+ mkdir sub1 &&
+ $command add_sub1 &&
+ test_superproject_content origin/add_sub1 &&
+ test_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # ... unless there is an untracked file in its place.
+ test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" '
+ prolog &&
+ reset_work_tree_to no_submodule &&
+ (
+ cd submodule_update &&
+ git branch -t add_sub1 origin/add_sub1 &&
+ >sub1 &&
+ $command add_sub1 &&
+ test_superproject_content origin/add_sub1 &&
+ test_dir_is_empty sub1
+ )
+ '
+ # Replacing a tracked file with a submodule produces an empty
+ # directory ...
+ test_expect_success "$command: replace tracked file with submodule creates empty directory" '
+ prolog &&
+ reset_work_tree_to replace_sub1_with_file &&
+ (
+ 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_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ test_submodule_content sub1 origin/replace_file_with_sub1
+ )
+ '
+ # ... as does removing a directory with tracked files with a
+ # submodule.
+ test_expect_success "$command: replace directory with submodule" '
+ prolog &&
+ reset_work_tree_to replace_sub1_with_directory &&
+ (
+ 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_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ test_submodule_content sub1 origin/replace_directory_with_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" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t remove_sub1 origin/remove_sub1 &&
+ $command remove_sub1 &&
+ test_superproject_content origin/remove_sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # ... especially when it contains a .git directory.
+ test_expect_success "$command: removed submodule leaves submodule containing a .git directory alone" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t remove_sub1 origin/remove_sub1 &&
+ replace_gitfile_with_git_dir sub1 &&
+ $command remove_sub1 &&
+ test_superproject_content origin/remove_sub1 &&
+ test_git_directory_is_unchanged sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # Replacing a submodule with files in a directory must fail as the
+ # submodule work tree isn't removed ...
+ test_expect_failure "$command: replace submodule with a directory must fail" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
+ test_must_fail $command replace_sub1_with_directory &&
+ test_superproject_content origin/add_sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # ... especially when it contains a .git directory.
+ test_expect_failure "$command: replace submodule containing a .git directory with a directory must fail" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
+ replace_gitfile_with_git_dir sub1 &&
+ test_must_fail $command replace_sub1_with_directory &&
+ test_superproject_content origin/add_sub1 &&
+ test_git_directory_is_unchanged sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # Replacing it with a file must fail as it could throw away any local
+ # work tree changes ...
+ test_expect_failure "$command: replace submodule with a file must fail" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
+ test_must_fail $command replace_sub1_with_file &&
+ test_superproject_content origin/add_sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # ... or even destroy unpushed parts of submodule history if that
+ # still uses a .git directory.
+ test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" '
+ prolog &&
+ reset_work_tree_to add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
+ replace_gitfile_with_git_dir sub1 &&
+ test_must_fail $command replace_sub1_with_file &&
+ test_superproject_content origin/add_sub1 &&
+ test_git_directory_is_unchanged sub1 &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+
+ ########################## Modified submodule #########################
+ # Updating a submodule sha1 doesn't update the submodule's work tree
+ test_expect_success "$command: modified submodule does not update submodule work tree" '
+ prolog &&
+ reset_work_tree_to 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/add_sub1 &&
+ git submodule update &&
+ 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 add_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t invalid_sub1 origin/invalid_sub1 &&
+ $command invalid_sub1 &&
+ test_superproject_content origin/invalid_sub1 &&
+ test_submodule_content sub1 origin/add_sub1 &&
+ test_must_fail git submodule update &&
+ test_submodule_content sub1 origin/add_sub1
+ )
+ '
+ # Updating a submodule from an invalid sha1 doesn't update the
+ # submodule's work tree, subsequent update will succeed
+ test_expect_success "$command: modified submodule does not update submodule work tree from invalid commit" '
+ prolog &&
+ reset_work_tree_to invalid_sub1 &&
+ (
+ cd submodule_update &&
+ git branch -t valid_sub1 origin/valid_sub1 &&
+ $command valid_sub1 &&
+ test_superproject_content origin/valid_sub1 &&
+ test_dir_is_empty sub1 &&
+ git submodule update --init --recursive &&
+ test_submodule_content sub1 origin/valid_sub1
+ )
+ '
+}
diff --git a/t/lib-terminal.sh b/t/lib-terminal.sh
index 737df289a1..51845491bb 100644
--- a/t/lib-terminal.sh
+++ b/t/lib-terminal.sh
@@ -1,6 +1,20 @@
-#!/bin/sh
+# Helpers for terminal output tests.
+
+# Catch tests which should depend on TTY but forgot to. There's no need
+# to aditionally check that the TTY prereq is set here. If the test declared
+# it and we are running the test, then it must have been set.
+test_terminal () {
+ if ! test_declared_prereq TTY
+ then
+ echo >&4 "test_terminal: need to declare TTY prerequisite"
+ return 127
+ fi
+ perl "$TEST_DIRECTORY"/test-terminal.perl "$@"
+}
+
+test_lazy_prereq TTY '
+ test_have_prereq PERL &&
-test_expect_success PERL 'set up terminal for tests' '
# Reading from the pty master seems to get stuck _sometimes_
# on Mac OS X 10.5.0, using Perl 5.10.0 or 5.8.9.
#
@@ -15,21 +29,8 @@ test_expect_success PERL 'set up terminal for tests' '
# After 2000 iterations or so it hangs.
# https://rt.cpan.org/Ticket/Display.html?id=65692
#
- if test "$(uname -s)" = Darwin
- then
- :
- elif
- perl "$TEST_DIRECTORY"/test-terminal.perl \
- sh -c "test -t 1 && test -t 2"
- then
- test_set_prereq TTY &&
- test_terminal () {
- if ! test_declared_prereq TTY
- then
- echo >&4 "test_terminal: need to declare TTY prerequisite"
- return 127
- fi
- perl "$TEST_DIRECTORY"/test-terminal.perl "$@"
- }
- fi
+ test "$(uname -s)" != Darwin &&
+
+ perl "$TEST_DIRECTORY"/test-terminal.perl \
+ sh -c "test -t 1 && test -t 2"
'
diff --git a/t/perf/p0001-rev-list.sh b/t/perf/p0001-rev-list.sh
index 4f71a63b0a..16359d51ae 100755
--- a/t/perf/p0001-rev-list.sh
+++ b/t/perf/p0001-rev-list.sh
@@ -14,4 +14,16 @@ test_perf 'rev-list --all --objects' '
git rev-list --all --objects >/dev/null
'
+test_expect_success 'create new unreferenced commit' '
+ commit=$(git commit-tree HEAD^{tree} -p HEAD)
+'
+
+test_perf 'rev-list $commit --not --all' '
+ git rev-list $commit --not --all >/dev/null
+'
+
+test_perf 'rev-list --objects $commit --not --all' '
+ git rev-list --objects $commit --not --all >/dev/null
+'
+
test_done
diff --git a/t/perf/p4001-diff-no-index.sh b/t/perf/p4001-diff-no-index.sh
new file mode 100755
index 0000000000..683be6984f
--- /dev/null
+++ b/t/perf/p4001-diff-no-index.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description="Test diff --no-index performance"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+test_checkout_worktree
+
+file1=$(git ls-files | tail -n 2 | head -1)
+file2=$(git ls-files | tail -n 1 | head -1)
+
+test_expect_success "empty files, so they take no time to diff" "
+ echo >$file1 &&
+ echo >$file2
+"
+
+test_perf "diff --no-index" "
+ git diff --no-index $file1 $file2 >/dev/null
+"
+
+test_done
diff --git a/t/perf/p5302-pack-index.sh b/t/perf/p5302-pack-index.sh
index 6cb5b0d55b..5ee9211f98 100755
--- a/t/perf/p5302-pack-index.sh
+++ b/t/perf/p5302-pack-index.sh
@@ -8,7 +8,7 @@ test_perf_large_repo
test_expect_success 'repack' '
git repack -ad &&
- PACK=`ls .git/objects/pack/*.pack | head -n1` &&
+ PACK=$(ls .git/objects/pack/*.pack | head -n1) &&
test -f "$PACK" &&
export PACK
'
diff --git a/t/perf/p5310-pack-bitmaps.sh b/t/perf/p5310-pack-bitmaps.sh
new file mode 100755
index 0000000000..f8ed8573b7
--- /dev/null
+++ b/t/perf/p5310-pack-bitmaps.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='Tests pack performance using bitmaps'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+# note that we do everything through config,
+# since we want to be able to compare bitmap-aware
+# git versus non-bitmap git
+#
+# We intentionally use the deprecated pack.writebitmaps
+# config so that we can test against older versions of git.
+test_expect_success 'setup bitmap config' '
+ git config pack.writebitmaps true &&
+ git config pack.writebitmaphashcache true
+'
+
+test_perf 'repack to disk' '
+ git repack -ad
+'
+
+test_perf 'simulated clone' '
+ git pack-objects --stdout --all </dev/null >/dev/null
+'
+
+test_perf 'simulated fetch' '
+ have=$(git rev-list HEAD~100 -1) &&
+ {
+ echo HEAD &&
+ echo ^$have
+ } | git pack-objects --revs --stdout >/dev/null
+'
+
+test_expect_success 'create partial bitmap state' '
+ # pick a commit to represent the repo tip in the past
+ cutoff=$(git rev-list HEAD~100 -1) &&
+ orig_tip=$(git rev-parse HEAD) &&
+
+ # now kill off all of the refs and pretend we had
+ # just the one tip
+ rm -rf .git/logs .git/refs/* .git/packed-refs
+ git update-ref HEAD $cutoff
+
+ # and then repack, which will leave us with a nice
+ # big bitmap pack of the "old" history, and all of
+ # the new history will be loose, as if it had been pushed
+ # up incrementally and exploded via unpack-objects
+ git repack -Ad
+
+ # and now restore our original tip, as if the pushes
+ # had happened
+ git update-ref HEAD $orig_tip
+'
+
+test_perf 'partial bitmap' '
+ git pack-objects --stdout --all </dev/null >/dev/null
+'
+
+test_done
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index f4eecaa171..a8c9574291 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -1,4 +1,6 @@
-#!/bin/sh
+# Performance testing framework. Each perf script starts much like
+# a normal test script, except it sources this library instead of
+# test-lib.sh. See t/perf/README for documentation.
#
# Copyright (c) 2011 Thomas Rast
#
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 10be52beed..f10ba4a01e 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -41,20 +41,17 @@ test_expect_success '.git/objects should have 3 subdirectories' '
test_expect_success 'success is reported like this' '
:
'
-test_expect_failure 'pretend we have a known breakage' '
- false
-'
-run_sub_test_lib_test () {
- name="$1" descr="$2" # stdin is the body of the test code
- shift 2
+_run_sub_test_lib_test_common () {
+ neg="$1" name="$2" descr="$3" # stdin is the body of the test code
+ shift 3
mkdir "$name" &&
(
- # Pretend we're a test harness. This prevents
- # test-lib from writing the counts to a file that will
- # later be summarized, showing spurious "failed" tests
- HARNESS_ACTIVE=t &&
- export HARNESS_ACTIVE &&
+ # Pretend we're not running under a test harness, whether we
+ # are or not. The test-lib output depends on the setting of
+ # this variable, so we need a stable setting under which to run
+ # the sub-test.
+ sane_unset HARNESS_ACTIVE &&
cd "$name" &&
cat >"$name.sh" <<-EOF &&
#!$SHELL_PATH
@@ -71,10 +68,25 @@ run_sub_test_lib_test () {
cat >>"$name.sh" &&
chmod +x "$name.sh" &&
export TEST_DIRECTORY &&
- ./"$name.sh" "$@" >out 2>err
+ TEST_OUTPUT_DIRECTORY=$(pwd) &&
+ export TEST_OUTPUT_DIRECTORY &&
+ if test -z "$neg"
+ then
+ ./"$name.sh" "$@" >out 2>err
+ else
+ ! ./"$name.sh" "$@" >out 2>err
+ fi
)
}
+run_sub_test_lib_test () {
+ _run_sub_test_lib_test_common '' "$@"
+}
+
+run_sub_test_lib_test_err () {
+ _run_sub_test_lib_test_common '!' "$@"
+}
+
check_sub_test_lib_test () {
name="$1" # stdin is the expected output from the test
(
@@ -85,6 +97,18 @@ check_sub_test_lib_test () {
)
}
+check_sub_test_lib_test_err () {
+ name="$1" # stdin is the expected output output from the test
+ # expected error output is in descriptior 3
+ (
+ cd "$name" &&
+ sed -e 's/^> //' -e 's/Z$//' >expect.out &&
+ test_cmp expect.out out &&
+ sed -e 's/^> //' -e 's/Z$//' <&3 >expect.err &&
+ test_cmp expect.err err
+ )
+}
+
test_expect_success 'pretend we have a fully passing test suite' "
run_sub_test_lib_test full-pass '3 passing tests' <<-\\EOF &&
for i in 1 2 3
@@ -233,16 +257,13 @@ test_expect_success 'test --verbose' '
grep -v "^Initialized empty" test-verbose/out+ >test-verbose/out &&
check_sub_test_lib_test test-verbose <<-\EOF
> expecting success: true
- > Z
> ok 1 - passing test
> Z
> expecting success: echo foo
> foo
- > Z
> ok 2 - test with output
> Z
> expecting success: false
- > Z
> not ok 3 - failing test
> # false
> Z
@@ -265,7 +286,6 @@ test_expect_success 'test --verbose-only' '
> Z
> expecting success: echo foo
> foo
- > Z
> ok 2 - test with output
> Z
> not ok 3 - failing test
@@ -275,6 +295,398 @@ test_expect_success 'test --verbose-only' '
EOF
'
+test_expect_success 'GIT_SKIP_TESTS' "
+ (
+ GIT_SKIP_TESTS='git.2' && export GIT_SKIP_TESTS &&
+ run_sub_test_lib_test git-skip-tests-basic \
+ 'GIT_SKIP_TESTS' <<-\\EOF &&
+ for i in 1 2 3
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test git-skip-tests-basic <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 # skip passing test #2 (GIT_SKIP_TESTS)
+ > ok 3 - passing test #3
+ > # passed all 3 test(s)
+ > 1..3
+ EOF
+ )
+"
+
+test_expect_success 'GIT_SKIP_TESTS several tests' "
+ (
+ GIT_SKIP_TESTS='git.2 git.5' && export GIT_SKIP_TESTS &&
+ run_sub_test_lib_test git-skip-tests-several \
+ 'GIT_SKIP_TESTS several tests' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test git-skip-tests-several <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 # skip passing test #2 (GIT_SKIP_TESTS)
+ > ok 3 - passing test #3
+ > ok 4 - passing test #4
+ > ok 5 # skip passing test #5 (GIT_SKIP_TESTS)
+ > ok 6 - passing test #6
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+ )
+"
+
+test_expect_success 'GIT_SKIP_TESTS sh pattern' "
+ (
+ GIT_SKIP_TESTS='git.[2-5]' && export GIT_SKIP_TESTS &&
+ run_sub_test_lib_test git-skip-tests-sh-pattern \
+ 'GIT_SKIP_TESTS sh pattern' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test git-skip-tests-sh-pattern <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 # skip passing test #2 (GIT_SKIP_TESTS)
+ > ok 3 # skip passing test #3 (GIT_SKIP_TESTS)
+ > ok 4 # skip passing test #4 (GIT_SKIP_TESTS)
+ > ok 5 # skip passing test #5 (GIT_SKIP_TESTS)
+ > ok 6 - passing test #6
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+ )
+"
+
+test_expect_success '--run basic' "
+ run_sub_test_lib_test run-basic \
+ '--run basic' --run='1 3 5' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-basic <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 # skip passing test #2 (--run)
+ > ok 3 - passing test #3
+ > ok 4 # skip passing test #4 (--run)
+ > ok 5 - passing test #5
+ > ok 6 # skip passing test #6 (--run)
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run with a range' "
+ run_sub_test_lib_test run-range \
+ '--run with a range' --run='1-3' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-range <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 - passing test #2
+ > ok 3 - passing test #3
+ > ok 4 # skip passing test #4 (--run)
+ > ok 5 # skip passing test #5 (--run)
+ > ok 6 # skip passing test #6 (--run)
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run with two ranges' "
+ run_sub_test_lib_test run-two-ranges \
+ '--run with two ranges' --run='1-2 5-6' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-two-ranges <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 - passing test #2
+ > ok 3 # skip passing test #3 (--run)
+ > ok 4 # skip passing test #4 (--run)
+ > ok 5 - passing test #5
+ > ok 6 - passing test #6
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run with a left open range' "
+ run_sub_test_lib_test run-left-open-range \
+ '--run with a left open range' --run='-3' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-left-open-range <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 - passing test #2
+ > ok 3 - passing test #3
+ > ok 4 # skip passing test #4 (--run)
+ > ok 5 # skip passing test #5 (--run)
+ > ok 6 # skip passing test #6 (--run)
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run with a right open range' "
+ run_sub_test_lib_test run-right-open-range \
+ '--run with a right open range' --run='4-' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-right-open-range <<-\\EOF
+ > ok 1 # skip passing test #1 (--run)
+ > ok 2 # skip passing test #2 (--run)
+ > ok 3 # skip passing test #3 (--run)
+ > ok 4 - passing test #4
+ > ok 5 - passing test #5
+ > ok 6 - passing test #6
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run with basic negation' "
+ run_sub_test_lib_test run-basic-neg \
+ '--run with basic negation' --run='"'!3'"' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-basic-neg <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 - passing test #2
+ > ok 3 # skip passing test #3 (--run)
+ > ok 4 - passing test #4
+ > ok 5 - passing test #5
+ > ok 6 - passing test #6
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run with two negations' "
+ run_sub_test_lib_test run-two-neg \
+ '--run with two negations' --run='"'!3 !6'"' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-two-neg <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 - passing test #2
+ > ok 3 # skip passing test #3 (--run)
+ > ok 4 - passing test #4
+ > ok 5 - passing test #5
+ > ok 6 # skip passing test #6 (--run)
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run a range and negation' "
+ run_sub_test_lib_test run-range-and-neg \
+ '--run a range and negation' --run='"'-4 !2'"' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-range-and-neg <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 # skip passing test #2 (--run)
+ > ok 3 - passing test #3
+ > ok 4 - passing test #4
+ > ok 5 # skip passing test #5 (--run)
+ > ok 6 # skip passing test #6 (--run)
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run range negation' "
+ run_sub_test_lib_test run-range-neg \
+ '--run range negation' --run='"'!1-3'"' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-range-neg <<-\\EOF
+ > ok 1 # skip passing test #1 (--run)
+ > ok 2 # skip passing test #2 (--run)
+ > ok 3 # skip passing test #3 (--run)
+ > ok 4 - passing test #4
+ > ok 5 - passing test #5
+ > ok 6 - passing test #6
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run include, exclude and include' "
+ run_sub_test_lib_test run-inc-neg-inc \
+ '--run include, exclude and include' \
+ --run='"'1-5 !1-3 2'"' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-inc-neg-inc <<-\\EOF
+ > ok 1 # skip passing test #1 (--run)
+ > ok 2 - passing test #2
+ > ok 3 # skip passing test #3 (--run)
+ > ok 4 - passing test #4
+ > ok 5 - passing test #5
+ > ok 6 # skip passing test #6 (--run)
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run include, exclude and include, comma separated' "
+ run_sub_test_lib_test run-inc-neg-inc-comma \
+ '--run include, exclude and include, comma separated' \
+ --run=1-5,\!1-3,2 <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-inc-neg-inc-comma <<-\\EOF
+ > ok 1 # skip passing test #1 (--run)
+ > ok 2 - passing test #2
+ > ok 3 # skip passing test #3 (--run)
+ > ok 4 - passing test #4
+ > ok 5 - passing test #5
+ > ok 6 # skip passing test #6 (--run)
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run exclude and include' "
+ run_sub_test_lib_test run-neg-inc \
+ '--run exclude and include' \
+ --run='"'!3- 5'"' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-neg-inc <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 - passing test #2
+ > ok 3 # skip passing test #3 (--run)
+ > ok 4 # skip passing test #4 (--run)
+ > ok 5 - passing test #5
+ > ok 6 # skip passing test #6 (--run)
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run empty selectors' "
+ run_sub_test_lib_test run-empty-sel \
+ '--run empty selectors' \
+ --run='1,,3,,,5' <<-\\EOF &&
+ for i in 1 2 3 4 5 6
+ do
+ test_expect_success \"passing test #\$i\" 'true'
+ done
+ test_done
+ EOF
+ check_sub_test_lib_test run-empty-sel <<-\\EOF
+ > ok 1 - passing test #1
+ > ok 2 # skip passing test #2 (--run)
+ > ok 3 - passing test #3
+ > ok 4 # skip passing test #4 (--run)
+ > ok 5 - passing test #5
+ > ok 6 # skip passing test #6 (--run)
+ > # passed all 6 test(s)
+ > 1..6
+ EOF
+"
+
+test_expect_success '--run invalid range start' "
+ run_sub_test_lib_test_err run-inv-range-start \
+ '--run invalid range start' \
+ --run='a-5' <<-\\EOF &&
+ test_expect_success \"passing test #1\" 'true'
+ test_done
+ EOF
+ check_sub_test_lib_test_err run-inv-range-start \
+ <<-\\EOF_OUT 3<<-\\EOF_ERR
+ > FATAL: Unexpected exit with code 1
+ EOF_OUT
+ > error: --run: invalid non-numeric in range start: 'a-5'
+ EOF_ERR
+"
+
+test_expect_success '--run invalid range end' "
+ run_sub_test_lib_test_err run-inv-range-end \
+ '--run invalid range end' \
+ --run='1-z' <<-\\EOF &&
+ test_expect_success \"passing test #1\" 'true'
+ test_done
+ EOF
+ check_sub_test_lib_test_err run-inv-range-end \
+ <<-\\EOF_OUT 3<<-\\EOF_ERR
+ > FATAL: Unexpected exit with code 1
+ EOF_OUT
+ > error: --run: invalid non-numeric in range end: '1-z'
+ EOF_ERR
+"
+
+test_expect_success '--run invalid selector' "
+ run_sub_test_lib_test_err run-inv-selector \
+ '--run invalid selector' \
+ --run='1?' <<-\\EOF &&
+ test_expect_success \"passing test #1\" 'true'
+ test_done
+ EOF
+ check_sub_test_lib_test_err run-inv-selector \
+ <<-\\EOF_OUT 3<<-\\EOF_ERR
+ > FATAL: Unexpected exit with code 1
+ EOF_OUT
+ > error: --run: invalid non-numeric in test selector: '1?'
+ EOF_ERR
+"
+
+
test_set_prereq HAVEIT
haveit=no
test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 9fb582b192..e62c0ffbc2 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -12,8 +12,8 @@ check_config () {
echo "expected a directory $1, a file $1/config and $1/refs"
return 1
fi
- bare=$(GIT_CONFIG="$1/config" git config --bool core.bare)
- worktree=$(GIT_CONFIG="$1/config" git config core.worktree) ||
+ bare=$(cd "$1" && git config --bool core.bare)
+ worktree=$(cd "$1" && git config core.worktree) ||
worktree=unset
test "$bare" = "$2" && test "$worktree" = "$3" || {
@@ -24,18 +24,12 @@ check_config () {
}
test_expect_success 'plain' '
- (
- sane_unset GIT_DIR GIT_WORK_TREE &&
- mkdir plain &&
- cd plain &&
- git init
- ) &&
+ git init plain &&
check_config plain/.git false unset
'
test_expect_success 'plain nested in bare' '
(
- sane_unset GIT_DIR GIT_WORK_TREE &&
git init --bare bare-ancestor.git &&
cd bare-ancestor.git &&
mkdir plain-nested &&
@@ -47,7 +41,6 @@ test_expect_success 'plain nested in bare' '
test_expect_success 'plain through aliased command, outside any git repo' '
(
- sane_unset GIT_DIR GIT_WORK_TREE &&
HOME=$(pwd)/alias-config &&
export HOME &&
mkdir alias-config &&
@@ -63,9 +56,8 @@ test_expect_success 'plain through aliased command, outside any git repo' '
check_config plain-aliased/.git false unset
'
-test_expect_failure 'plain nested through aliased command' '
+test_expect_success 'plain nested through aliased command' '
(
- sane_unset GIT_DIR GIT_WORK_TREE &&
git init plain-ancestor-aliased &&
cd plain-ancestor-aliased &&
echo "[alias] aliasedinit = init" >>.git/config &&
@@ -76,9 +68,8 @@ test_expect_failure 'plain nested through aliased command' '
check_config plain-ancestor-aliased/plain-nested/.git false unset
'
-test_expect_failure 'plain nested in bare through aliased command' '
+test_expect_success 'plain nested in bare through aliased command' '
(
- sane_unset GIT_DIR GIT_WORK_TREE &&
git init --bare bare-ancestor-aliased.git &&
cd bare-ancestor-aliased.git &&
echo "[alias] aliasedinit = init" >>config &&
@@ -90,66 +81,36 @@ test_expect_failure 'plain nested in bare through aliased command' '
'
test_expect_success 'plain with GIT_WORK_TREE' '
- if (
- sane_unset GIT_DIR &&
- mkdir plain-wt &&
- cd plain-wt &&
- GIT_WORK_TREE=$(pwd) git init
- )
- then
- echo Should have failed -- GIT_WORK_TREE should not be used
- false
- fi
+ mkdir plain-wt &&
+ test_must_fail env GIT_WORK_TREE="$(pwd)/plain-wt" git init plain-wt
'
test_expect_success 'plain bare' '
- (
- sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG &&
- mkdir plain-bare-1 &&
- cd plain-bare-1 &&
- git --bare init
- ) &&
+ git --bare init plain-bare-1 &&
check_config plain-bare-1 true unset
'
test_expect_success 'plain bare with GIT_WORK_TREE' '
- if (
- sane_unset GIT_DIR GIT_CONFIG &&
- mkdir plain-bare-2 &&
- cd plain-bare-2 &&
- GIT_WORK_TREE=$(pwd) git --bare init
- )
- then
- echo Should have failed -- GIT_WORK_TREE should not be used
- false
- fi
+ mkdir plain-bare-2 &&
+ test_must_fail \
+ env GIT_WORK_TREE="$(pwd)/plain-bare-2" \
+ git --bare init plain-bare-2
'
test_expect_success 'GIT_DIR bare' '
-
- (
- sane_unset GIT_CONFIG &&
- mkdir git-dir-bare.git &&
- GIT_DIR=git-dir-bare.git git init
- ) &&
+ mkdir git-dir-bare.git &&
+ GIT_DIR=git-dir-bare.git git init &&
check_config git-dir-bare.git true unset
'
test_expect_success 'init --bare' '
-
- (
- sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG &&
- mkdir init-bare.git &&
- cd init-bare.git &&
- git init --bare
- ) &&
+ git init --bare init-bare.git &&
check_config init-bare.git true unset
'
test_expect_success 'GIT_DIR non-bare' '
(
- sane_unset GIT_CONFIG &&
mkdir non-bare &&
cd non-bare &&
GIT_DIR=.git git init
@@ -160,7 +121,6 @@ test_expect_success 'GIT_DIR non-bare' '
test_expect_success 'GIT_DIR & GIT_WORK_TREE (1)' '
(
- sane_unset GIT_CONFIG &&
mkdir git-dir-wt-1.git &&
GIT_WORK_TREE=$(pwd) GIT_DIR=git-dir-wt-1.git git init
) &&
@@ -168,23 +128,16 @@ test_expect_success 'GIT_DIR & GIT_WORK_TREE (1)' '
'
test_expect_success 'GIT_DIR & GIT_WORK_TREE (2)' '
-
- if (
- sane_unset GIT_CONFIG &&
- mkdir git-dir-wt-2.git &&
- GIT_WORK_TREE=$(pwd) GIT_DIR=git-dir-wt-2.git git --bare init
- )
- then
- echo Should have failed -- --bare should not be used
- false
- fi
+ mkdir git-dir-wt-2.git &&
+ test_must_fail env \
+ GIT_WORK_TREE="$(pwd)" \
+ GIT_DIR=git-dir-wt-2.git \
+ git --bare init
'
test_expect_success 'reinit' '
(
- sane_unset GIT_CONFIG GIT_WORK_TREE GIT_CONFIG &&
-
mkdir again &&
cd again &&
git init >out1 2>err1 &&
@@ -200,35 +153,22 @@ test_expect_success 'reinit' '
test_expect_success 'init with --template' '
mkdir template-source &&
echo content >template-source/file &&
- (
- mkdir template-custom &&
- cd template-custom &&
- git init --template=../template-source
- ) &&
+ git init --template=../template-source template-custom &&
test_cmp template-source/file template-custom/.git/file
'
test_expect_success 'init with --template (blank)' '
- (
- mkdir template-plain &&
- cd template-plain &&
- git init
- ) &&
- test -f template-plain/.git/info/exclude &&
- (
- mkdir template-blank &&
- cd template-blank &&
- git init --template=
- ) &&
- ! test -f template-blank/.git/info/exclude
+ git init template-plain &&
+ test_path_is_file template-plain/.git/info/exclude &&
+ git init --template= template-blank &&
+ test_path_is_missing template-blank/.git/info/exclude
'
test_expect_success 'init with init.templatedir set' '
mkdir templatedir-source &&
echo Content >templatedir-source/file &&
+ test_config_global init.templatedir "${HOME}/templatedir-source" &&
(
- test_config="${HOME}/.gitconfig" &&
- git config -f "$test_config" init.templatedir "${HOME}/templatedir-source" &&
mkdir templatedir-set &&
cd templatedir-set &&
sane_unset GIT_TEMPLATE_DIR &&
@@ -240,78 +180,55 @@ test_expect_success 'init with init.templatedir set' '
'
test_expect_success 'init --bare/--shared overrides system/global config' '
- (
- test_config="$HOME"/.gitconfig &&
- git config -f "$test_config" core.bare false &&
- git config -f "$test_config" core.sharedRepository 0640 &&
- mkdir init-bare-shared-override &&
- cd init-bare-shared-override &&
- git init --bare --shared=0666
- ) &&
+ test_config_global core.bare false &&
+ test_config_global core.sharedRepository 0640 &&
+ git init --bare --shared=0666 init-bare-shared-override &&
check_config init-bare-shared-override true unset &&
test x0666 = \
- x`git config -f init-bare-shared-override/config core.sharedRepository`
+ x$(git config -f init-bare-shared-override/config core.sharedRepository)
'
test_expect_success 'init honors global core.sharedRepository' '
- (
- test_config="$HOME"/.gitconfig &&
- git config -f "$test_config" core.sharedRepository 0666 &&
- mkdir shared-honor-global &&
- cd shared-honor-global &&
- git init
- ) &&
+ test_config_global core.sharedRepository 0666 &&
+ git init shared-honor-global &&
test x0666 = \
- x`git config -f shared-honor-global/.git/config core.sharedRepository`
+ x$(git config -f shared-honor-global/.git/config core.sharedRepository)
'
test_expect_success 'init rejects insanely long --template' '
- (
- insane=$(printf "x%09999dx" 1) &&
- mkdir test &&
- cd test &&
- test_must_fail git init --template=$insane
- )
+ test_must_fail git init --template=$(printf "x%09999dx" 1) test
'
test_expect_success 'init creates a new directory' '
rm -fr newdir &&
- (
- git init newdir &&
- test -d newdir/.git/refs
- )
+ git init newdir &&
+ test_path_is_dir newdir/.git/refs
'
test_expect_success 'init creates a new bare directory' '
rm -fr newdir &&
- (
- git init --bare newdir &&
- test -d newdir/refs
- )
+ git init --bare newdir &&
+ test_path_is_dir newdir/refs
'
test_expect_success 'init recreates a directory' '
rm -fr newdir &&
- (
- mkdir newdir &&
- git init newdir &&
- test -d newdir/.git/refs
- )
+ mkdir newdir &&
+ git init newdir &&
+ test_path_is_dir newdir/.git/refs
'
test_expect_success 'init recreates a new bare directory' '
rm -fr newdir &&
- (
- mkdir newdir &&
- git init --bare newdir &&
- test -d newdir/refs
- )
+ mkdir newdir &&
+ git init --bare newdir &&
+ test_path_is_dir newdir/refs
'
test_expect_success 'init creates a new deep directory' '
rm -fr newdir &&
git init newdir/a/b/c &&
- test -d newdir/a/b/c/.git/refs
+ test_path_is_dir newdir/a/b/c/.git/refs
'
test_expect_success POSIXPERM 'init creates a new deep directory (umask vs. shared)' '
@@ -321,7 +238,7 @@ test_expect_success POSIXPERM 'init creates a new deep directory (umask vs. shar
# the repository itself should follow "shared"
umask 002 &&
git init --bare --shared=0660 newdir/a/b/c &&
- test -d newdir/a/b/c/refs &&
+ test_path_is_dir newdir/a/b/c/refs &&
ls -ld newdir/a newdir/a/b > lsab.out &&
! grep -v "^drwxrw[sx]r-x" lsab.out &&
ls -ld newdir/a/b/c > lsc.out &&
@@ -331,52 +248,46 @@ test_expect_success POSIXPERM 'init creates a new deep directory (umask vs. shar
test_expect_success 'init notices EEXIST (1)' '
rm -fr newdir &&
- (
- >newdir &&
- test_must_fail git init newdir &&
- test -f newdir
- )
+ >newdir &&
+ test_must_fail git init newdir &&
+ test_path_is_file newdir
'
test_expect_success 'init notices EEXIST (2)' '
rm -fr newdir &&
- (
- mkdir newdir &&
- >newdir/a
- test_must_fail git init newdir/a/b &&
- test -f newdir/a
- )
+ mkdir newdir &&
+ >newdir/a &&
+ test_must_fail git init newdir/a/b &&
+ test_path_is_file newdir/a
'
test_expect_success POSIXPERM,SANITY 'init notices EPERM' '
rm -fr newdir &&
- (
- mkdir newdir &&
- chmod -w newdir &&
- test_must_fail git init newdir/a/b
- )
+ mkdir newdir &&
+ chmod -w newdir &&
+ test_must_fail git init newdir/a/b
'
test_expect_success 'init creates a new bare directory with global --bare' '
rm -rf newdir &&
git --bare init newdir &&
- test -d newdir/refs
+ test_path_is_dir newdir/refs
'
test_expect_success 'init prefers command line to GIT_DIR' '
rm -rf newdir &&
mkdir otherdir &&
GIT_DIR=otherdir git --bare init newdir &&
- test -d newdir/refs &&
- ! test -d otherdir/refs
+ test_path_is_dir newdir/refs &&
+ test_path_is_missing otherdir/refs
'
test_expect_success 'init with separate gitdir' '
rm -rf newdir &&
git init --separate-git-dir realgitdir newdir &&
- echo "gitdir: `pwd`/realgitdir" >expected &&
+ echo "gitdir: $(pwd)/realgitdir" >expected &&
test_cmp expected newdir/.git &&
- test -d realgitdir/refs
+ test_path_is_dir realgitdir/refs
'
test_expect_success 're-init on .git file' '
@@ -388,10 +299,10 @@ test_expect_success 're-init to update git link' '
cd newdir &&
git init --separate-git-dir ../surrealgitdir
) &&
- echo "gitdir: `pwd`/surrealgitdir" >expected &&
+ echo "gitdir: $(pwd)/surrealgitdir" >expected &&
test_cmp expected newdir/.git &&
- test -d surrealgitdir/refs &&
- ! test -d realgitdir/refs
+ test_path_is_dir surrealgitdir/refs &&
+ test_path_is_missing realgitdir/refs
'
test_expect_success 're-init to move gitdir' '
@@ -401,9 +312,9 @@ test_expect_success 're-init to move gitdir' '
cd newdir &&
git init --separate-git-dir ../realgitdir
) &&
- echo "gitdir: `pwd`/realgitdir" >expected &&
+ echo "gitdir: $(pwd)/realgitdir" >expected &&
test_cmp expected newdir/.git &&
- test -d realgitdir/refs
+ test_path_is_dir realgitdir/refs
'
test_expect_success SYMLINKS 're-init to move gitdir symlink' '
@@ -415,10 +326,10 @@ test_expect_success SYMLINKS 're-init to move gitdir symlink' '
ln -s here .git &&
git init --separate-git-dir ../realgitdir
) &&
- echo "gitdir: `pwd`/realgitdir" >expected &&
+ echo "gitdir: $(pwd)/realgitdir" >expected &&
test_cmp expected newdir/.git &&
- test -d realgitdir/refs &&
- ! test -d newdir/here
+ test_cmp expected newdir/here &&
+ test_path_is_dir realgitdir/refs
'
test_done
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
index cb144258cc..37e9396e5d 100755
--- a/t/t0002-gitfile.sh
+++ b/t/t0002-gitfile.sh
@@ -7,7 +7,7 @@ Verify that plumbing commands work when .git is a file
. ./test-lib.sh
objpath() {
- echo "$1" | sed -e 's|\(..\)|\1/|'
+ echo "$1" | sed -e 's|\(..\)|\1/|'
}
objck() {
@@ -19,7 +19,6 @@ objck() {
fi
}
-
test_expect_success 'initial setup' '
REAL="$(pwd)/.real" &&
mv .git "$REAL"
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 0b98b6f8d0..f0fbb42554 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -13,7 +13,6 @@ attr_check () {
test_line_count = 0 err
}
-
test_expect_success 'setup' '
mkdir -p a/b/d a/c b &&
(
@@ -244,40 +243,58 @@ EOF
test_line_count = 0 err
'
+test_expect_success 'using --git-dir and --work-tree' '
+ mkdir unreal real &&
+ git init real &&
+ echo "file test=in-real" >real/.gitattributes &&
+ (
+ cd unreal &&
+ attr_check file in-real "--git-dir ../real/.git --work-tree ../real"
+ )
+'
+
test_expect_success 'setup bare' '
- git clone --bare . bare.git &&
- cd bare.git
+ git clone --bare . bare.git
'
test_expect_success 'bare repository: check that .gitattribute is ignored' '
(
- echo "f test=f"
- echo "a/i test=a/i"
- ) >.gitattributes &&
- attr_check f unspecified &&
- attr_check a/f unspecified &&
- attr_check a/c/f unspecified &&
- attr_check a/i unspecified &&
- attr_check subdir/a/i unspecified
+ cd bare.git &&
+ (
+ echo "f test=f"
+ echo "a/i test=a/i"
+ ) >.gitattributes &&
+ attr_check f unspecified &&
+ attr_check a/f unspecified &&
+ attr_check a/c/f unspecified &&
+ attr_check a/i unspecified &&
+ attr_check subdir/a/i unspecified
+ )
'
test_expect_success 'bare repository: check that --cached honors index' '
- GIT_INDEX_FILE=../.git/index \
- git check-attr --cached --stdin --all <../stdin-all |
- sort >actual &&
- test_cmp ../specified-all actual
+ (
+ cd bare.git &&
+ GIT_INDEX_FILE=../.git/index \
+ git check-attr --cached --stdin --all <../stdin-all |
+ sort >actual &&
+ test_cmp ../specified-all actual
+ )
'
test_expect_success 'bare repository: test info/attributes' '
(
- echo "f test=f"
- echo "a/i test=a/i"
- ) >info/attributes &&
- attr_check f f &&
- attr_check a/f f &&
- attr_check a/c/f f &&
- attr_check a/i a/i &&
- attr_check subdir/a/i unspecified
+ cd bare.git &&
+ (
+ echo "f test=f"
+ echo "a/i test=a/i"
+ ) >info/attributes &&
+ attr_check f f &&
+ attr_check a/f f &&
+ attr_check a/c/f f &&
+ attr_check a/i a/i &&
+ attr_check subdir/a/i unspecified
+ )
'
test_done
diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh
index 981437b3a8..aeea50c633 100755
--- a/t/t0005-signals.sh
+++ b/t/t0005-signals.sh
@@ -27,4 +27,26 @@ test_expect_success !MINGW 'signals are propagated using shell convention' '
test_expect_code 143 git sigterm
'
+large_git () {
+ for i in $(test_seq 1 100)
+ do
+ git diff --cached --binary || return
+ done
+}
+
+test_expect_success 'create blob' '
+ test-genrandom foo 16384 >file &&
+ git add file
+'
+
+test_expect_success !MINGW 'a constipated git dies with SIGPIPE' '
+ OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 )
+ test "$OUT" -eq 141
+'
+
+test_expect_success !MINGW 'a constipated git dies with SIGPIPE even if parent ignores it' '
+ OUT=$( ((trap "" PIPE; large_git; echo $? 1>&3) | :) 3>&1 )
+ test "$OUT" -eq 141
+'
+
test_done
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index b4d98e602f..8dc6939b90 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -775,4 +775,60 @@ test_expect_success PIPE 'streaming support for --stdin' '
echo "$response" | grep "^:: two"
'
+############################################################################
+#
+# test whitespace handling
+
+test_expect_success 'trailing whitespace is ignored' '
+ mkdir whitespace &&
+ >whitespace/trailing &&
+ >whitespace/untracked &&
+ echo "whitespace/trailing " >ignore &&
+ cat >expect <<EOF &&
+whitespace/untracked
+EOF
+ : >err.expect &&
+ git ls-files -o -X ignore whitespace >actual 2>err &&
+ test_cmp expect actual &&
+ test_cmp err.expect err
+'
+
+test_expect_success !MINGW 'quoting allows trailing whitespace' '
+ rm -rf whitespace &&
+ mkdir whitespace &&
+ >"whitespace/trailing " &&
+ >whitespace/untracked &&
+ echo "whitespace/trailing\\ \\ " >ignore &&
+ echo whitespace/untracked >expect &&
+ : >err.expect &&
+ git ls-files -o -X ignore whitespace >actual 2>err &&
+ test_cmp expect actual &&
+ test_cmp err.expect err
+'
+
+test_expect_success !MINGW,!CYGWIN 'correct handling of backslashes' '
+ rm -rf whitespace &&
+ mkdir whitespace &&
+ >"whitespace/trailing 1 " &&
+ >"whitespace/trailing 2 \\\\" &&
+ >"whitespace/trailing 3 \\\\" &&
+ >"whitespace/trailing 4 \\ " &&
+ >"whitespace/trailing 5 \\ \\ " &&
+ >"whitespace/trailing 6 \\a\\" &&
+ >whitespace/untracked &&
+ sed -e "s/Z$//" >ignore <<-\EOF &&
+ whitespace/trailing 1 \ Z
+ whitespace/trailing 2 \\\\Z
+ whitespace/trailing 3 \\\\ Z
+ whitespace/trailing 4 \\\ Z
+ whitespace/trailing 5 \\ \\\ Z
+ whitespace/trailing 6 \\a\\Z
+ EOF
+ echo whitespace/untracked >expect &&
+ >err.expect &&
+ git ls-files -o -X ignore whitespace >actual 2>err &&
+ test_cmp expect actual &&
+ test_cmp err.expect err
+'
+
test_done
diff --git a/t/t0010-racy-git.sh b/t/t0010-racy-git.sh
index e45a9e40e4..5657c5a87b 100755
--- a/t/t0010-racy-git.sh
+++ b/t/t0010-racy-git.sh
@@ -14,7 +14,7 @@ do
git update-index --add infocom
echo xyzzy >infocom
- files=`git diff-files -p`
+ files=$(git diff-files -p)
test_expect_success \
"Racy GIT trial #$trial part A" \
'test "" != "$files"'
@@ -23,7 +23,7 @@ do
echo xyzzy >cornerstone
git update-index --add cornerstone
- files=`git diff-files -p`
+ files=$(git diff-files -p)
test_expect_success \
"Racy GIT trial #$trial part B" \
'test "" != "$files"'
diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh
new file mode 100755
index 0000000000..f97c80556f
--- /dev/null
+++ b/t/t0011-hashmap.sh
@@ -0,0 +1,253 @@
+#!/bin/sh
+
+test_description='test hashmap and string hash functions'
+. ./test-lib.sh
+
+test_hashmap() {
+ echo "$1" | test-hashmap $3 > actual &&
+ echo "$2" > expect &&
+ test_cmp expect actual
+}
+
+test_expect_success 'hash functions' '
+
+test_hashmap "hash key1" "2215982743 2215982743 116372151 116372151" &&
+test_hashmap "hash key2" "2215982740 2215982740 116372148 116372148" &&
+test_hashmap "hash fooBarFrotz" "1383912807 1383912807 3189766727 3189766727" &&
+test_hashmap "hash foobarfrotz" "2862305959 2862305959 3189766727 3189766727"
+
+'
+
+test_expect_success 'put' '
+
+test_hashmap "put key1 value1
+put key2 value2
+put fooBarFrotz value3
+put foobarfrotz value4
+size" "NULL
+NULL
+NULL
+NULL
+64 4"
+
+'
+
+test_expect_success 'put (case insensitive)' '
+
+test_hashmap "put key1 value1
+put key2 value2
+put fooBarFrotz value3
+size" "NULL
+NULL
+NULL
+64 3" ignorecase
+
+'
+
+test_expect_success 'replace' '
+
+test_hashmap "put key1 value1
+put key1 value2
+put fooBarFrotz value3
+put fooBarFrotz value4
+size" "NULL
+value1
+NULL
+value3
+64 2"
+
+'
+
+test_expect_success 'replace (case insensitive)' '
+
+test_hashmap "put key1 value1
+put Key1 value2
+put fooBarFrotz value3
+put foobarfrotz value4
+size" "NULL
+value1
+NULL
+value3
+64 2" ignorecase
+
+'
+
+test_expect_success 'get' '
+
+test_hashmap "put key1 value1
+put key2 value2
+put fooBarFrotz value3
+put foobarfrotz value4
+get key1
+get key2
+get fooBarFrotz
+get notInMap" "NULL
+NULL
+NULL
+NULL
+value1
+value2
+value3
+NULL"
+
+'
+
+test_expect_success 'get (case insensitive)' '
+
+test_hashmap "put key1 value1
+put key2 value2
+put fooBarFrotz value3
+get Key1
+get keY2
+get foobarfrotz
+get notInMap" "NULL
+NULL
+NULL
+value1
+value2
+value3
+NULL" ignorecase
+
+'
+
+test_expect_success 'add' '
+
+test_hashmap "add key1 value1
+add key1 value2
+add fooBarFrotz value3
+add fooBarFrotz value4
+get key1
+get fooBarFrotz
+get notInMap" "value2
+value1
+value4
+value3
+NULL"
+
+'
+
+test_expect_success 'add (case insensitive)' '
+
+test_hashmap "add key1 value1
+add Key1 value2
+add fooBarFrotz value3
+add foobarfrotz value4
+get key1
+get Foobarfrotz
+get notInMap" "value2
+value1
+value4
+value3
+NULL" ignorecase
+
+'
+
+test_expect_success 'remove' '
+
+test_hashmap "put key1 value1
+put key2 value2
+put fooBarFrotz value3
+remove key1
+remove key2
+remove notInMap
+size" "NULL
+NULL
+NULL
+value1
+value2
+NULL
+64 1"
+
+'
+
+test_expect_success 'remove (case insensitive)' '
+
+test_hashmap "put key1 value1
+put key2 value2
+put fooBarFrotz value3
+remove Key1
+remove keY2
+remove notInMap
+size" "NULL
+NULL
+NULL
+value1
+value2
+NULL
+64 1" ignorecase
+
+'
+
+test_expect_success 'iterate' '
+
+test_hashmap "put key1 value1
+put key2 value2
+put fooBarFrotz value3
+iterate" "NULL
+NULL
+NULL
+key2 value2
+key1 value1
+fooBarFrotz value3"
+
+'
+
+test_expect_success 'iterate (case insensitive)' '
+
+test_hashmap "put key1 value1
+put key2 value2
+put fooBarFrotz value3
+iterate" "NULL
+NULL
+NULL
+fooBarFrotz value3
+key2 value2
+key1 value1" ignorecase
+
+'
+
+test_expect_success 'grow / shrink' '
+
+ rm -f in &&
+ rm -f expect &&
+ for n in $(test_seq 51)
+ do
+ echo put key$n value$n >> in &&
+ echo NULL >> expect
+ done &&
+ echo size >> in &&
+ echo 64 51 >> expect &&
+ echo put key52 value52 >> in &&
+ echo NULL >> expect
+ echo size >> in &&
+ echo 256 52 >> expect &&
+ for n in $(test_seq 12)
+ do
+ echo remove key$n >> in &&
+ echo value$n >> expect
+ done &&
+ echo size >> in &&
+ echo 256 40 >> expect &&
+ echo remove key40 >> in &&
+ echo value40 >> expect &&
+ echo size >> in &&
+ echo 64 39 >> expect &&
+ cat in | test-hashmap > out &&
+ test_cmp expect out
+
+'
+
+test_expect_success 'string interning' '
+
+test_hashmap "intern value1
+intern Value1
+intern value2
+intern value2
+" "value1
+Value1
+value2
+value2"
+
+'
+
+test_done
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index e526184a0b..d2e51a81bc 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -20,14 +20,14 @@ test_expect_success setup '
git commit -m initial &&
- one=`git rev-parse HEAD:one` &&
- dir=`git rev-parse HEAD:dir` &&
- two=`git rev-parse HEAD:dir/two` &&
- three=`git rev-parse HEAD:three` &&
+ one=$(git rev-parse HEAD:one) &&
+ dir=$(git rev-parse HEAD:dir) &&
+ two=$(git rev-parse HEAD:dir/two) &&
+ three=$(git rev-parse HEAD:three) &&
for w in Some extra lines here; do echo $w; done >>one &&
git diff >patch.file &&
- patched=`git hash-object --stdin <one` &&
+ patched=$(git hash-object --stdin <one) &&
git read-tree --reset -u HEAD &&
echo happy.
@@ -111,7 +111,7 @@ test_expect_success 'update with autocrlf=input' '
}
done &&
- differs=`git diff-index --cached HEAD` &&
+ differs=$(git diff-index --cached HEAD) &&
test -z "$differs" || {
echo Oops "$differs"
false
@@ -135,7 +135,7 @@ test_expect_success 'update with autocrlf=true' '
}
done &&
- differs=`git diff-index --cached HEAD` &&
+ differs=$(git diff-index --cached HEAD) &&
test -z "$differs" || {
echo Oops "$differs"
false
@@ -158,9 +158,9 @@ test_expect_success 'checkout with autocrlf=true' '
break
}
done &&
- test "$one" = `git hash-object --stdin <one` &&
- test "$two" = `git hash-object --stdin <dir/two` &&
- differs=`git diff-index --cached HEAD` &&
+ test "$one" = $(git hash-object --stdin <one) &&
+ test "$two" = $(git hash-object --stdin <dir/two) &&
+ differs=$(git diff-index --cached HEAD) &&
test -z "$differs" || {
echo Oops "$differs"
false
@@ -184,9 +184,9 @@ test_expect_success 'checkout with autocrlf=input' '
git update-index -- $f
fi
done &&
- test "$one" = `git hash-object --stdin <one` &&
- test "$two" = `git hash-object --stdin <dir/two` &&
- differs=`git diff-index --cached HEAD` &&
+ test "$one" = $(git hash-object --stdin <one) &&
+ test "$two" = $(git hash-object --stdin <dir/two) &&
+ differs=$(git diff-index --cached HEAD) &&
test -z "$differs" || {
echo Oops "$differs"
false
@@ -200,7 +200,7 @@ test_expect_success 'apply patch (autocrlf=input)' '
git read-tree --reset -u HEAD &&
git apply patch.file &&
- test "$patched" = "`git hash-object --stdin <one`" || {
+ test "$patched" = "$(git hash-object --stdin <one)" || {
echo "Eh? apply without index"
false
}
@@ -213,7 +213,7 @@ test_expect_success 'apply patch --cached (autocrlf=input)' '
git read-tree --reset -u HEAD &&
git apply --cached patch.file &&
- test "$patched" = `git rev-parse :one` || {
+ test "$patched" = $(git rev-parse :one) || {
echo "Eh? apply with --cached"
false
}
@@ -226,8 +226,8 @@ test_expect_success 'apply patch --index (autocrlf=input)' '
git read-tree --reset -u HEAD &&
git apply --index patch.file &&
- test "$patched" = `git rev-parse :one` &&
- test "$patched" = `git hash-object --stdin <one` || {
+ test "$patched" = $(git rev-parse :one) &&
+ test "$patched" = $(git hash-object --stdin <one) || {
echo "Eh? apply with --index"
false
}
@@ -240,7 +240,7 @@ test_expect_success 'apply patch (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply patch.file &&
- test "$patched" = "`remove_cr <one | git hash-object --stdin`" || {
+ test "$patched" = "$(remove_cr <one | git hash-object --stdin)" || {
echo "Eh? apply without index"
false
}
@@ -253,7 +253,7 @@ test_expect_success 'apply patch --cached (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply --cached patch.file &&
- test "$patched" = `git rev-parse :one` || {
+ test "$patched" = $(git rev-parse :one) || {
echo "Eh? apply without index"
false
}
@@ -266,8 +266,8 @@ test_expect_success 'apply patch --index (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply --index patch.file &&
- test "$patched" = `git rev-parse :one` &&
- test "$patched" = "`remove_cr <one | git hash-object --stdin`" || {
+ test "$patched" = $(git rev-parse :one) &&
+ test "$patched" = "$(remove_cr <one | git hash-object --stdin)" || {
echo "Eh? apply with --index"
false
}
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index b92e6cb046..ca7d2a630a 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -153,17 +153,23 @@ test_expect_success 'filter shell-escaped filenames' '
:
'
-test_expect_success 'required filter success' '
- git config filter.required.smudge cat &&
- git config filter.required.clean cat &&
+test_expect_success 'required filter should filter data' '
+ git config filter.required.smudge ./rot13.sh &&
+ git config filter.required.clean ./rot13.sh &&
git config filter.required.required true &&
echo "*.r filter=required" >.gitattributes &&
- echo test >test.r &&
+ cat test.o >test.r &&
git add test.r &&
+
rm -f test.r &&
- git checkout -- test.r
+ git checkout -- test.r &&
+ cmp test.o test.r &&
+
+ ./rot13.sh <test.o >expected &&
+ git cat-file blob :test.r >actual &&
+ cmp expected actual
'
test_expect_success 'required filter smudge failure' '
@@ -190,7 +196,13 @@ test_expect_success 'required filter clean failure' '
test_must_fail git add test.fc
'
-test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
+test_expect_success 'filtering large input to small output should use little memory' '
+ git config filter.devnull.clean "cat >/dev/null" &&
+ git config filter.devnull.required true &&
+ for i in $(test_seq 1 30); do printf "%1048576d" 1; done >30MB &&
+ echo "30MB filter=devnull" >.gitattributes &&
+ GIT_MMAP_LIMIT=1m GIT_ALLOC_LIMIT=1m git add 30MB
+'
test_expect_success EXPENSIVE 'filter large file' '
git config filter.largefile.smudge cat &&
diff --git a/t/t0025-crlf-auto.sh b/t/t0025-crlf-auto.sh
index f5f67a6337..c164b4662a 100755
--- a/t/t0025-crlf-auto.sh
+++ b/t/t0025-crlf-auto.sh
@@ -12,144 +12,144 @@ test_expect_success setup '
git config core.autocrlf false &&
- for w in Hello world how are you; do echo $w; done >one &&
- for w in I am very very fine thank you; do echo ${w}Q; done | q_to_cr >two &&
- for w in Oh here is a QNUL byte how alarming; do echo ${w}; done | q_to_nul >three &&
+ for w in Hello world how are you; do echo $w; done >LFonly &&
+ for w in I am very very fine thank you; do echo ${w}Q; done | q_to_cr >CRLFonly &&
+ for w in Oh here is a QNUL byte how alarming; do echo ${w}; done | q_to_nul >LFwithNUL &&
git add . &&
git commit -m initial &&
- one=`git rev-parse HEAD:one` &&
- two=`git rev-parse HEAD:two` &&
- three=`git rev-parse HEAD:three` &&
+ LFonly=$(git rev-parse HEAD:LFonly) &&
+ CRLFonly=$(git rev-parse HEAD:CRLFonly) &&
+ LFwithNUL=$(git rev-parse HEAD:LFwithNUL) &&
echo happy.
'
test_expect_success 'default settings cause no changes' '
- rm -f .gitattributes tmp one two three &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
git read-tree --reset -u HEAD &&
- ! has_cr one &&
- has_cr two &&
- onediff=`git diff one` &&
- twodiff=`git diff two` &&
- threediff=`git diff three` &&
- test -z "$onediff" -a -z "$twodiff" -a -z "$threediff"
+ ! has_cr LFonly &&
+ has_cr CRLFonly &&
+ LFonlydiff=$(git diff LFonly) &&
+ CRLFonlydiff=$(git diff CRLFonly) &&
+ LFwithNULdiff=$(git diff LFwithNUL) &&
+ test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff"
'
test_expect_success 'crlf=true causes a CRLF file to be normalized' '
# Backwards compatibility check
- rm -f .gitattributes tmp one two three &&
- echo "two crlf" > .gitattributes &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
+ echo "CRLFonly crlf" > .gitattributes &&
git read-tree --reset -u HEAD &&
# Note, "normalized" means that git will normalize it if added
- has_cr two &&
- twodiff=`git diff two` &&
- test -n "$twodiff"
+ has_cr CRLFonly &&
+ CRLFonlydiff=$(git diff CRLFonly) &&
+ test -n "$CRLFonlydiff"
'
test_expect_success 'text=true causes a CRLF file to be normalized' '
- rm -f .gitattributes tmp one two three &&
- echo "two text" > .gitattributes &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
+ echo "CRLFonly text" > .gitattributes &&
git read-tree --reset -u HEAD &&
# Note, "normalized" means that git will normalize it if added
- has_cr two &&
- twodiff=`git diff two` &&
- test -n "$twodiff"
+ has_cr CRLFonly &&
+ CRLFonlydiff=$(git diff CRLFonly) &&
+ test -n "$CRLFonlydiff"
'
test_expect_success 'eol=crlf gives a normalized file CRLFs with autocrlf=false' '
- rm -f .gitattributes tmp one two three &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
git config core.autocrlf false &&
- echo "one eol=crlf" > .gitattributes &&
+ echo "LFonly eol=crlf" > .gitattributes &&
git read-tree --reset -u HEAD &&
- has_cr one &&
- onediff=`git diff one` &&
- test -z "$onediff"
+ has_cr LFonly &&
+ LFonlydiff=$(git diff LFonly) &&
+ test -z "$LFonlydiff"
'
test_expect_success 'eol=crlf gives a normalized file CRLFs with autocrlf=input' '
- rm -f .gitattributes tmp one two three &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
git config core.autocrlf input &&
- echo "one eol=crlf" > .gitattributes &&
+ echo "LFonly eol=crlf" > .gitattributes &&
git read-tree --reset -u HEAD &&
- has_cr one &&
- onediff=`git diff one` &&
- test -z "$onediff"
+ has_cr LFonly &&
+ LFonlydiff=$(git diff LFonly) &&
+ test -z "$LFonlydiff"
'
test_expect_success 'eol=lf gives a normalized file LFs with autocrlf=true' '
- rm -f .gitattributes tmp one two three &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
git config core.autocrlf true &&
- echo "one eol=lf" > .gitattributes &&
+ echo "LFonly eol=lf" > .gitattributes &&
git read-tree --reset -u HEAD &&
- ! has_cr one &&
- onediff=`git diff one` &&
- test -z "$onediff"
+ ! has_cr LFonly &&
+ LFonlydiff=$(git diff LFonly) &&
+ test -z "$LFonlydiff"
'
test_expect_success 'autocrlf=true does not normalize CRLF files' '
- rm -f .gitattributes tmp one two three &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
git config core.autocrlf true &&
git read-tree --reset -u HEAD &&
- has_cr one &&
- has_cr two &&
- onediff=`git diff one` &&
- twodiff=`git diff two` &&
- threediff=`git diff three` &&
- test -z "$onediff" -a -z "$twodiff" -a -z "$threediff"
+ has_cr LFonly &&
+ has_cr CRLFonly &&
+ LFonlydiff=$(git diff LFonly) &&
+ CRLFonlydiff=$(git diff CRLFonly) &&
+ LFwithNULdiff=$(git diff LFwithNUL) &&
+ test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff"
'
test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' '
- rm -f .gitattributes tmp one two three &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
git config core.autocrlf true &&
echo "* text=auto" > .gitattributes &&
git read-tree --reset -u HEAD &&
- has_cr one &&
- has_cr two &&
- onediff=`git diff one` &&
- twodiff=`git diff two` &&
- threediff=`git diff three` &&
- test -z "$onediff" -a -n "$twodiff" -a -z "$threediff"
+ has_cr LFonly &&
+ has_cr CRLFonly &&
+ LFonlydiff=$(git diff LFonly) &&
+ CRLFonlydiff=$(git diff CRLFonly) &&
+ LFwithNULdiff=$(git diff LFwithNUL) &&
+ test -z "$LFonlydiff" -a -n "$CRLFonlydiff" -a -z "$LFwithNULdiff"
'
test_expect_success 'text=auto, autocrlf=true does not normalize binary files' '
- rm -f .gitattributes tmp one two three &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
git config core.autocrlf true &&
echo "* text=auto" > .gitattributes &&
git read-tree --reset -u HEAD &&
- ! has_cr three &&
- threediff=`git diff three` &&
- test -z "$threediff"
+ ! has_cr LFwithNUL &&
+ LFwithNULdiff=$(git diff LFwithNUL) &&
+ test -z "$LFwithNULdiff"
'
test_expect_success 'eol=crlf _does_ normalize binary files' '
- rm -f .gitattributes tmp one two three &&
- echo "three eol=crlf" > .gitattributes &&
+ rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
+ echo "LFwithNUL eol=crlf" > .gitattributes &&
git read-tree --reset -u HEAD &&
- has_cr three &&
- threediff=`git diff three` &&
- test -z "$threediff"
+ has_cr LFwithNUL &&
+ LFwithNULdiff=$(git diff LFwithNUL) &&
+ test -z "$LFwithNULdiff"
'
test_done
diff --git a/t/t0026-eol-config.sh b/t/t0026-eol-config.sh
index fe0164be62..c5203e232c 100755
--- a/t/t0026-eol-config.sh
+++ b/t/t0026-eol-config.sh
@@ -20,8 +20,8 @@ test_expect_success setup '
git commit -m initial &&
- one=`git rev-parse HEAD:one` &&
- two=`git rev-parse HEAD:two` &&
+ one=$(git rev-parse HEAD:one) &&
+ two=$(git rev-parse HEAD:two) &&
echo happy.
'
@@ -34,9 +34,9 @@ test_expect_success 'eol=lf puts LFs in normalized file' '
! has_cr one &&
! has_cr two &&
- onediff=`git diff one` &&
- twodiff=`git diff two` &&
- test -z "$onediff" -a -z "$twodiff"
+ onediff=$(git diff one) &&
+ twodiff=$(git diff two) &&
+ test -z "$onediff" && test -z "$twodiff"
'
test_expect_success 'eol=crlf puts CRLFs in normalized file' '
@@ -47,9 +47,9 @@ test_expect_success 'eol=crlf puts CRLFs in normalized file' '
has_cr one &&
! has_cr two &&
- onediff=`git diff one` &&
- twodiff=`git diff two` &&
- test -z "$onediff" -a -z "$twodiff"
+ onediff=$(git diff one) &&
+ twodiff=$(git diff two) &&
+ test -z "$onediff" && test -z "$twodiff"
'
test_expect_success 'autocrlf=true overrides eol=lf' '
@@ -61,9 +61,9 @@ test_expect_success 'autocrlf=true overrides eol=lf' '
has_cr one &&
has_cr two &&
- onediff=`git diff one` &&
- twodiff=`git diff two` &&
- test -z "$onediff" -a -z "$twodiff"
+ onediff=$(git diff one) &&
+ twodiff=$(git diff two) &&
+ test -z "$onediff" && test -z "$twodiff"
'
test_expect_success 'autocrlf=true overrides unset eol' '
@@ -75,9 +75,29 @@ test_expect_success 'autocrlf=true overrides unset eol' '
has_cr one &&
has_cr two &&
- onediff=`git diff one` &&
- twodiff=`git diff two` &&
- test -z "$onediff" -a -z "$twodiff"
+ onediff=$(git diff one) &&
+ twodiff=$(git diff two) &&
+ test -z "$onediff" && test -z "$twodiff"
+'
+
+test_expect_success NATIVE_CRLF 'eol native is crlf' '
+
+ rm -rf native_eol && mkdir native_eol &&
+ (
+ cd native_eol &&
+ printf "*.txt text\n" >.gitattributes &&
+ printf "one\r\ntwo\r\nthree\r\n" >filedos.txt &&
+ printf "one\ntwo\nthree\n" >fileunix.txt &&
+ git init &&
+ git config core.autocrlf false &&
+ git config core.eol native &&
+ git add filedos.txt fileunix.txt &&
+ git commit -m "first" &&
+ rm file*.txt &&
+ git reset --hard HEAD &&
+ has_cr filedos.txt &&
+ has_cr fileunix.txt
+ )
'
test_done
diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh
new file mode 100755
index 0000000000..2a4a6c1226
--- /dev/null
+++ b/t/t0027-auto-crlf.sh
@@ -0,0 +1,285 @@
+#!/bin/sh
+
+test_description='CRLF conversion all combinations'
+
+. ./test-lib.sh
+
+if ! test_have_prereq EXPENSIVE
+then
+ skip_all="EXPENSIVE not set"
+ test_done
+fi
+
+compare_files () {
+ tr '\015\000' QN <"$1" >"$1".expect &&
+ tr '\015\000' QN <"$2" >"$2".actual &&
+ test_cmp "$1".expect "$2".actual &&
+ rm "$1".expect "$2".actual
+}
+
+compare_ws_file () {
+ pfx=$1
+ exp=$2.expect
+ act=$pfx.actual.$3
+ tr '\015\000' QN <"$2" >"$exp" &&
+ tr '\015\000' QN <"$3" >"$act" &&
+ test_cmp $exp $act &&
+ rm $exp $act
+}
+
+create_gitattributes () {
+ attr=$1
+ case "$attr" in
+ auto)
+ echo "*.txt text=auto" >.gitattributes
+ ;;
+ text)
+ echo "*.txt text" >.gitattributes
+ ;;
+ -text)
+ echo "*.txt -text" >.gitattributes
+ ;;
+ crlf)
+ echo "*.txt eol=crlf" >.gitattributes
+ ;;
+ lf)
+ echo "*.txt eol=lf" >.gitattributes
+ ;;
+ "")
+ echo >.gitattributes
+ ;;
+ *)
+ echo >&2 invalid attribute: $attr
+ exit 1
+ ;;
+ esac
+}
+
+create_file_in_repo () {
+ crlf=$1
+ attr=$2
+ create_gitattributes "$attr" &&
+ for f in LF CRLF LF_mix_CR CRLF_mix_LF CRLF_nul
+ do
+ pfx=crlf_${crlf}_attr_${attr}_$f.txt &&
+ cp $f $pfx && git -c core.autocrlf=$crlf add $pfx
+ done &&
+ git commit -m "core.autocrlf $crlf"
+}
+
+check_files_in_repo () {
+ crlf=$1
+ attr=$2
+ lfname=$3
+ crlfname=$4
+ lfmixcrlf=$5
+ lfmixcr=$6
+ crlfnul=$7
+ pfx=crlf_${crlf}_attr_${attr}_ &&
+ compare_files $lfname ${pfx}LF.txt &&
+ compare_files $crlfname ${pfx}CRLF.txt &&
+ compare_files $lfmixcrlf ${pfx}CRLF_mix_LF.txt &&
+ compare_files $lfmixcr ${pfx}LF_mix_CR.txt &&
+ compare_files $crlfnul ${pfx}CRLF_nul.txt
+}
+
+
+check_files_in_ws () {
+ eol=$1
+ crlf=$2
+ attr=$3
+ lfname=$4
+ crlfname=$5
+ lfmixcrlf=$6
+ lfmixcr=$7
+ crlfnul=$8
+ create_gitattributes $attr &&
+ git config core.autocrlf $crlf &&
+ pfx=eol_${eol}_crlf_${crlf}_attr_${attr}_ &&
+ src=crlf_false_attr__ &&
+ for f in LF CRLF LF_mix_CR CRLF_mix_LF CRLF_nul
+ do
+ rm $src$f.txt &&
+ if test -z "$eol"; then
+ git checkout $src$f.txt
+ else
+ git -c core.eol=$eol checkout $src$f.txt
+ fi
+ done
+
+ test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=LF" "
+ compare_ws_file $pfx $lfname ${src}LF.txt
+ "
+ test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=CRLF" "
+ compare_ws_file $pfx $crlfname ${src}CRLF.txt
+ "
+ test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=CRLF_mix_LF" "
+ compare_ws_file $pfx $lfmixcrlf ${src}CRLF_mix_LF.txt
+ "
+ test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=LF_mix_CR" "
+ compare_ws_file $pfx $lfmixcr ${src}LF_mix_CR.txt
+ "
+ test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=CRLF_nul" "
+ compare_ws_file $pfx $crlfnul ${src}CRLF_nul.txt
+ "
+}
+
+#######
+test_expect_success 'setup master' '
+ echo >.gitattributes &&
+ git checkout -b master &&
+ git add .gitattributes &&
+ git commit -m "add .gitattributes" "" &&
+ printf "line1\nline2\nline3" >LF &&
+ printf "line1\r\nline2\r\nline3" >CRLF &&
+ printf "line1\r\nline2\nline3" >CRLF_mix_LF &&
+ printf "line1\nline2\rline3" >LF_mix_CR &&
+ printf "line1\r\nline2\rline3" >CRLF_mix_CR &&
+ printf "line1Q\r\nline2\r\nline3" | q_to_nul >CRLF_nul &&
+ printf "line1Q\nline2\nline3" | q_to_nul >LF_nul
+'
+
+
+test_expect_success 'create files' '
+ create_file_in_repo false "" &&
+ create_file_in_repo true "" &&
+ create_file_in_repo input "" &&
+
+ create_file_in_repo false "auto" &&
+ create_file_in_repo true "auto" &&
+ create_file_in_repo input "auto" &&
+
+ create_file_in_repo false "text" &&
+ create_file_in_repo true "text" &&
+ create_file_in_repo input "text" &&
+
+ create_file_in_repo false "-text" &&
+ create_file_in_repo true "-text" &&
+ create_file_in_repo input "-text" &&
+ rm -f *.txt &&
+ git reset --hard
+'
+
+test_expect_success 'commit empty gitattribues' '
+ check_files_in_repo false "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul &&
+ check_files_in_repo true "" LF LF LF LF_mix_CR CRLF_nul &&
+ check_files_in_repo input "" LF LF LF LF_mix_CR CRLF_nul
+'
+
+test_expect_success 'commit text=auto' '
+ check_files_in_repo false "auto" LF LF LF LF_mix_CR CRLF_nul &&
+ check_files_in_repo true "auto" LF LF LF LF_mix_CR CRLF_nul &&
+ check_files_in_repo input "auto" LF LF LF LF_mix_CR CRLF_nul
+'
+
+test_expect_success 'commit text' '
+ check_files_in_repo false "text" LF LF LF LF_mix_CR LF_nul &&
+ check_files_in_repo true "text" LF LF LF LF_mix_CR LF_nul &&
+ check_files_in_repo input "text" LF LF LF LF_mix_CR LF_nul
+'
+
+test_expect_success 'commit -text' '
+ check_files_in_repo false "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul &&
+ check_files_in_repo true "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul &&
+ check_files_in_repo input "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+'
+
+################################################################################
+# Check how files in the repo are changed when they are checked out
+# How to read the table below:
+# - check_files_in_ws will check multiple files with a combination of settings
+# and attributes (core.autocrlf=input is forbidden with core.eol=crlf)
+# - parameter $1 : core.eol lf | crlf
+# - parameter $2 : core.autocrlf false | true | input
+# - parameter $3 : text in .gitattributs "" (empty) | auto | text | -text
+# - parameter $4 : reference for a file with only LF in the repo
+# - parameter $5 : reference for a file with only CRLF in the repo
+# - parameter $6 : reference for a file with mixed LF and CRLF in the repo
+# - parameter $7 : reference for a file with LF and CR in the repo (does somebody uses this ?)
+# - parameter $8 : reference for a file with CRLF and a NUL (should be handled as binary when auto)
+
+# What we have in the repo:
+# ----------------- EOL in repo ----------------
+# LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+# settings with checkout:
+# core. core. .gitattr
+# eol acrlf
+# ----------------------------------------------
+# What we want to have in the working tree:
+if test_have_prereq MINGW
+then
+MIX_CRLF_LF=CRLF
+MIX_LF_CR=CRLF_mix_CR
+NL=CRLF
+else
+MIX_CRLF_LF=CRLF_mix_LF
+MIX_LF_CR=LF_mix_CR
+NL=LF
+fi
+export CRLF_MIX_LF_CR MIX NL
+
+check_files_in_ws lf false "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf true "" CRLF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf input "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf false "auto" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf true "auto" CRLF CRLF CRLF LF_mix_CR CRLF_nul
+check_files_in_ws lf input "auto" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf false "text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf true "text" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws lf input "text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf false "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf true "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf input "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf false "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf true "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf input "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws lf false "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws lf true "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws lf input "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+
+check_files_in_ws crlf false "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws crlf true "" CRLF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws crlf false "auto" CRLF CRLF CRLF LF_mix_CR CRLF_nul
+check_files_in_ws crlf true "auto" CRLF CRLF CRLF LF_mix_CR CRLF_nul
+check_files_in_ws crlf false "text" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws crlf true "text" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws crlf false "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws crlf true "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws crlf false "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws crlf true "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws crlf false "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws crlf true "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+
+check_files_in_ws "" false "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" true "" CRLF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" input "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" false "auto" $NL CRLF $MIX_CRLF_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" true "auto" CRLF CRLF CRLF LF_mix_CR CRLF_nul
+check_files_in_ws "" input "auto" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" false "text" $NL CRLF $MIX_CRLF_LF $MIX_LF_CR CRLF_nul
+check_files_in_ws "" true "text" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws "" input "text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" false "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" true "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" input "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" false "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" true "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" input "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws "" false "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws "" true "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws "" input "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+
+check_files_in_ws native false "" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws native true "" CRLF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws native false "auto" $NL CRLF $MIX_CRLF_LF LF_mix_CR CRLF_nul
+check_files_in_ws native true "auto" CRLF CRLF CRLF LF_mix_CR CRLF_nul
+check_files_in_ws native false "text" $NL CRLF $MIX_CRLF_LF $MIX_LF_CR CRLF_nul
+check_files_in_ws native true "text" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws native false "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws native true "-text" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws native false "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws native true "lf" LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul
+check_files_in_ws native false "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+check_files_in_ws native true "crlf" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+
+test_done
diff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh
index a8e84d8546..0333dd9875 100755
--- a/t/t0030-stripspace.sh
+++ b/t/t0030-stripspace.sh
@@ -225,22 +225,22 @@ test_expect_success \
test_expect_success \
'text without newline at end should end with newline' '
- test `printf "$ttt" | git stripspace | wc -l` -gt 0 &&
- test `printf "$ttt$ttt" | git stripspace | wc -l` -gt 0 &&
- test `printf "$ttt$ttt$ttt" | git stripspace | wc -l` -gt 0 &&
- test `printf "$ttt$ttt$ttt$ttt" | git stripspace | wc -l` -gt 0
+ test $(printf "$ttt" | git stripspace | wc -l) -gt 0 &&
+ test $(printf "$ttt$ttt" | git stripspace | wc -l) -gt 0 &&
+ test $(printf "$ttt$ttt$ttt" | git stripspace | wc -l) -gt 0 &&
+ test $(printf "$ttt$ttt$ttt$ttt" | git stripspace | wc -l) -gt 0
'
# text plus spaces at the end:
test_expect_success \
'text plus spaces without newline at end should end with newline' '
- test `printf "$ttt$sss" | git stripspace | wc -l` -gt 0 &&
- test `printf "$ttt$ttt$sss" | git stripspace | wc -l` -gt 0 &&
- test `printf "$ttt$ttt$ttt$sss" | git stripspace | wc -l` -gt 0 &&
- test `printf "$ttt$sss$sss" | git stripspace | wc -l` -gt 0 &&
- test `printf "$ttt$ttt$sss$sss" | git stripspace | wc -l` -gt 0 &&
- test `printf "$ttt$sss$sss$sss" | git stripspace | wc -l` -gt 0
+ test $(printf "$ttt$sss" | git stripspace | wc -l) -gt 0 &&
+ test $(printf "$ttt$ttt$sss" | git stripspace | wc -l) -gt 0 &&
+ test $(printf "$ttt$ttt$ttt$sss" | git stripspace | wc -l) -gt 0 &&
+ test $(printf "$ttt$sss$sss" | git stripspace | wc -l) -gt 0 &&
+ test $(printf "$ttt$ttt$sss$sss" | git stripspace | wc -l) -gt 0 &&
+ test $(printf "$ttt$sss$sss$sss" | git stripspace | wc -l) -gt 0
'
test_expect_success \
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 65606df3ed..a90c86bfa3 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -30,7 +30,6 @@ String options
--string2 <str> get another string
--st <st> get another string (pervert ordering)
-o <str> get another string
- --default-string set string to default
--list <str> add str to list
Magic arguments
@@ -293,7 +292,7 @@ cat > expect <<EOF
boolean: 0
integer: 0
timestamp: 1
-string: default
+string: (not set)
abbrev: 7
verbose: 0
quiet: yes
@@ -302,8 +301,8 @@ file: (not set)
arg 00: foo
EOF
-test_expect_success 'OPT_DATE() and OPT_SET_PTR() work' '
- test-parse-options -t "1970-01-01 00:00:01 +0000" --default-string \
+test_expect_success 'OPT_DATE() works' '
+ test-parse-options -t "1970-01-01 00:00:01 +0000" \
foo -q > output 2> output.err &&
test_must_be_empty output.err &&
test_cmp expect output
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 07c10c8dca..c0143a0a70 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -190,6 +190,27 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
'
+test_expect_success SYMLINKS 'prefix_path works with absolute paths to work tree symlinks' '
+ ln -s target symlink &&
+ test "$(test-path-utils prefix_path prefix "$(pwd)/symlink")" = "symlink"
+'
+
+test_expect_success 'prefix_path works with only absolute path to work tree' '
+ echo "" >expected &&
+ test-path-utils prefix_path prefix "$(pwd)" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'prefix_path rejects absolute path to dir with same beginning as work tree' '
+ test_must_fail test-path-utils prefix_path prefix "$(pwd)a"
+'
+
+test_expect_success SYMLINKS 'prefix_path works with absolute path to a symlink to work tree having same beginning as work tree' '
+ git init repo &&
+ ln -s repo repolink &&
+ test "a" = "$(cd repo && test-path-utils prefix_path prefix "$(pwd)/../repolink/a")"
+'
+
relative_path /foo/a/b/c/ /foo/a/b/ c/
relative_path /foo/a/b/c/ /foo/a/b c/
relative_path /foo/a//b//c/ ///foo/a/b// c/ POSIX
diff --git a/t/t0064-sha1-array.sh b/t/t0064-sha1-array.sh
new file mode 100755
index 0000000000..50b31ffe75
--- /dev/null
+++ b/t/t0064-sha1-array.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+
+test_description='basic tests for the SHA1 array implementation'
+. ./test-lib.sh
+
+echo20 () {
+ prefix="${1:+$1 }"
+ shift
+ while test $# -gt 0
+ do
+ echo "$prefix$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1"
+ shift
+ done
+}
+
+test_expect_success 'ordered enumeration' '
+ echo20 "" 44 55 88 aa >expect &&
+ {
+ echo20 append 88 44 aa 55 &&
+ echo for_each_unique
+ } | test-sha1-array >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'ordered enumeration with duplicate suppression' '
+ echo20 "" 44 55 88 aa >expect &&
+ {
+ echo20 append 88 44 aa 55 &&
+ echo20 append 88 44 aa 55 &&
+ echo for_each_unique
+ } | test-sha1-array >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'lookup' '
+ {
+ echo20 append 88 44 aa 55 &&
+ echo20 lookup 55
+ } | test-sha1-array >actual &&
+ n=$(cat actual) &&
+ test "$n" -eq 1
+'
+
+test_expect_success 'lookup non-existing entry' '
+ {
+ echo20 append 88 44 aa 55 &&
+ echo20 lookup 33
+ } | test-sha1-array >actual &&
+ n=$(cat actual) &&
+ test "$n" -lt 0
+'
+
+test_expect_success 'lookup with duplicates' '
+ {
+ echo20 append 88 44 aa 55 &&
+ echo20 append 88 44 aa 55 &&
+ echo20 lookup 55
+ } | test-sha1-array >actual &&
+ n=$(cat actual) &&
+ test "$n" -ge 2 &&
+ test "$n" -le 3
+'
+
+test_expect_success 'lookup non-existing entry with duplicates' '
+ {
+ echo20 append 88 44 aa 55 &&
+ echo20 append 88 44 aa 55 &&
+ echo20 lookup 66
+ } | test-sha1-array >actual &&
+ n=$(cat actual) &&
+ test "$n" -lt 0
+'
+
+test_expect_success 'lookup with almost duplicate values' '
+ {
+ echo "append 5555555555555555555555555555555555555555" &&
+ echo "append 555555555555555555555555555555555555555f" &&
+ echo20 lookup 55
+ } | test-sha1-array >actual &&
+ n=$(cat actual) &&
+ test "$n" -eq 0
+'
+
+test_expect_success 'lookup with single duplicate value' '
+ {
+ echo20 append 55 55 &&
+ echo20 lookup 55
+ } | test-sha1-array >actual &&
+ n=$(cat actual) &&
+ test "$n" -ge 0 &&
+ test "$n" -le 1
+'
+
+test_done
diff --git a/t/t0081-line-buffer.sh b/t/t0081-line-buffer.sh
index bd83ed371a..ce92e6acad 100755
--- a/t/t0081-line-buffer.sh
+++ b/t/t0081-line-buffer.sh
@@ -29,7 +29,7 @@ test_expect_success '0-length read, send along greeting' '
test_cmp expect actual
'
-test_expect_success 'read from file descriptor' '
+test_expect_success !MINGW 'read from file descriptor' '
rm -f input &&
echo hello >expect &&
echo hello >input &&
diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 6c33e28ee8..158cf4f03b 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -8,7 +8,7 @@ cache-tree extension.
. ./test-lib.sh
cmp_cache_tree () {
- test-dump-cache-tree >actual &&
+ test-dump-cache-tree | sed -e '/#(ref)/d' >actual &&
sed "s/$_x40/SHA/" <actual >filtered &&
test_cmp "$1" filtered
}
@@ -16,15 +16,40 @@ cmp_cache_tree () {
# We don't bother with actually checking the SHA1:
# test-dump-cache-tree already verifies that all existing data is
# correct.
-test_shallow_cache_tree () {
- printf "SHA (%d entries, 0 subtrees)\n" $(git ls-files|wc -l) >expect &&
+generate_expected_cache_tree_rec () {
+ dir="$1${1:+/}" &&
+ parent="$2" &&
+ # ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux
+ # We want to count only foo because it's the only direct child
+ subtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) &&
+ subtree_count=$(echo "$subtrees"|awk -v c=0 '$1 {++c} END {print c}') &&
+ entries=$(git ls-files|wc -l) &&
+ printf "SHA $dir (%d entries, %d subtrees)\n" "$entries" "$subtree_count" &&
+ for subtree in $subtrees
+ do
+ cd "$subtree"
+ generate_expected_cache_tree_rec "$dir$subtree" "$dir" || return 1
+ cd ..
+ done &&
+ dir=$parent
+}
+
+generate_expected_cache_tree () {
+ (
+ generate_expected_cache_tree_rec
+ )
+}
+
+test_cache_tree () {
+ generate_expected_cache_tree >expect &&
cmp_cache_tree expect
}
test_invalid_cache_tree () {
- echo "invalid (0 subtrees)" >expect &&
- printf "SHA #(ref) (%d entries, 0 subtrees)\n" $(git ls-files|wc -l) >>expect &&
- cmp_cache_tree expect
+ printf "invalid %s ()\n" "" "$@" >expect &&
+ test-dump-cache-tree |
+ sed -n -e "s/[0-9]* subtrees//" -e '/#(ref)/d' -e '/^invalid /p' >actual &&
+ test_cmp expect actual
}
test_no_cache_tree () {
@@ -32,26 +57,59 @@ test_no_cache_tree () {
cmp_cache_tree expect
}
-test_expect_failure 'initial commit has cache-tree' '
+test_expect_success 'initial commit has cache-tree' '
test_commit foo &&
- test_shallow_cache_tree
+ test_cache_tree
'
test_expect_success 'read-tree HEAD establishes cache-tree' '
git read-tree HEAD &&
- test_shallow_cache_tree
+ test_cache_tree
'
test_expect_success 'git-add invalidates cache-tree' '
test_when_finished "git reset --hard; git read-tree HEAD" &&
- echo "I changed this file" > foo &&
+ echo "I changed this file" >foo &&
git add foo &&
test_invalid_cache_tree
'
+test_expect_success 'git-add in subdir invalidates cache-tree' '
+ test_when_finished "git reset --hard; git read-tree HEAD" &&
+ mkdir dirx &&
+ echo "I changed this file" >dirx/foo &&
+ git add dirx/foo &&
+ test_invalid_cache_tree
+'
+
+cat >before <<\EOF
+SHA (3 entries, 2 subtrees)
+SHA dir1/ (1 entries, 0 subtrees)
+SHA dir2/ (1 entries, 0 subtrees)
+EOF
+
+cat >expect <<\EOF
+invalid (2 subtrees)
+invalid dir1/ (0 subtrees)
+SHA dir2/ (1 entries, 0 subtrees)
+EOF
+
+test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' '
+ git tag no-children &&
+ test_when_finished "git reset --hard no-children; git read-tree HEAD" &&
+ mkdir dir1 dir2 &&
+ test_commit dir1/a &&
+ test_commit dir2/b &&
+ echo "I changed this file" >dir1/a &&
+ cmp_cache_tree before &&
+ echo "I changed this file" >dir1/a &&
+ git add dir1/a &&
+ cmp_cache_tree expect
+'
+
test_expect_success 'update-index invalidates cache-tree' '
test_when_finished "git reset --hard; git read-tree HEAD" &&
- echo "I changed this file" > foo &&
+ echo "I changed this file" >foo &&
git update-index --add foo &&
test_invalid_cache_tree
'
@@ -59,7 +117,7 @@ test_expect_success 'update-index invalidates cache-tree' '
test_expect_success 'write-tree establishes cache-tree' '
test-scrap-cache-tree &&
git write-tree &&
- test_shallow_cache_tree
+ test_cache_tree
'
test_expect_success 'test-scrap-cache-tree works' '
@@ -70,24 +128,94 @@ test_expect_success 'test-scrap-cache-tree works' '
test_expect_success 'second commit has cache-tree' '
test_commit bar &&
- test_shallow_cache_tree
+ test_cache_tree
+'
+
+test_expect_success 'commit --interactive gives cache-tree on partial commit' '
+ cat <<-\EOT >foo.c &&
+ int foo()
+ {
+ return 42;
+ }
+ int bar()
+ {
+ return 42;
+ }
+ EOT
+ git add foo.c &&
+ test_invalid_cache_tree &&
+ git commit -m "add a file" &&
+ test_cache_tree &&
+ cat <<-\EOT >foo.c &&
+ int foo()
+ {
+ return 43;
+ }
+ int bar()
+ {
+ return 44;
+ }
+ EOT
+ (echo p; echo 1; echo; echo s; echo n; echo y; echo q) |
+ git commit --interactive -m foo &&
+ test_cache_tree
+'
+
+test_expect_success 'commit in child dir has cache-tree' '
+ mkdir dir &&
+ >dir/child.t &&
+ git add dir/child.t &&
+ git commit -m dir/child.t &&
+ test_cache_tree
'
test_expect_success 'reset --hard gives cache-tree' '
test-scrap-cache-tree &&
git reset --hard &&
- test_shallow_cache_tree
+ test_cache_tree
'
test_expect_success 'reset --hard without index gives cache-tree' '
rm -f .git/index &&
git reset --hard &&
- test_shallow_cache_tree
+ test_cache_tree
'
-test_expect_failure 'checkout gives cache-tree' '
+test_expect_success 'checkout gives cache-tree' '
+ git tag current &&
git checkout HEAD^ &&
- test_shallow_cache_tree
+ test_cache_tree
+'
+
+test_expect_success 'checkout -b gives cache-tree' '
+ git checkout current &&
+ git checkout -b prev HEAD^ &&
+ test_cache_tree
+'
+
+test_expect_success 'checkout -B gives cache-tree' '
+ git checkout current &&
+ git checkout -B prev HEAD^ &&
+ test_cache_tree
+'
+
+test_expect_success 'partial commit gives cache-tree' '
+ git checkout -b partial no-children &&
+ test_commit one &&
+ test_commit two &&
+ echo "some change" >one.t &&
+ git add one.t &&
+ echo "some other change" >two.t &&
+ git commit two.t -m partial &&
+ test_cache_tree
+'
+
+test_expect_success 'no phantom error when switching trees' '
+ mkdir newdir &&
+ >newdir/one &&
+ git add newdir/one &&
+ git checkout 2>errors &&
+ ! test -s errors
'
test_done
diff --git a/t/t0110-urlmatch-normalization.sh b/t/t0110-urlmatch-normalization.sh
index 8d6096d4d1..410d5768ca 100755
--- a/t/t0110-urlmatch-normalization.sh
+++ b/t/t0110-urlmatch-normalization.sh
@@ -117,7 +117,7 @@ test_expect_success 'url general escapes' '
test "$(test-urlmatch-normalization -p "X://W?'\!'")" = "x://w/?'\!'"
'
-test_expect_success 'url high-bit escapes' '
+test_expect_success !MINGW 'url high-bit escapes' '
test "$(test-urlmatch-normalization -p "$(cat "$tu-1")")" = "x://q/%01%02%03%04%05%06%07%08%0E%0F%10%11%12" &&
test "$(test-urlmatch-normalization -p "$(cat "$tu-2")")" = "x://q/%13%14%15%16%17%18%19%1B%1C%1D%1E%1F%7F" &&
test "$(test-urlmatch-normalization -p "$(cat "$tu-3")")" = "x://q/%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F" &&
@@ -127,7 +127,10 @@ test_expect_success 'url high-bit escapes' '
test "$(test-urlmatch-normalization -p "$(cat "$tu-7")")" = "x://q/%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF" &&
test "$(test-urlmatch-normalization -p "$(cat "$tu-8")")" = "x://q/%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF" &&
test "$(test-urlmatch-normalization -p "$(cat "$tu-9")")" = "x://q/%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" &&
- test "$(test-urlmatch-normalization -p "$(cat "$tu-10")")" = "x://q/%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF" &&
+ test "$(test-urlmatch-normalization -p "$(cat "$tu-10")")" = "x://q/%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
+'
+
+test_expect_success 'url utf-8 escapes' '
test "$(test-urlmatch-normalization -p "$(cat "$tu-11")")" = "x://q/%C2%80%DF%BF%E0%A0%80%EF%BF%BD%F0%90%80%80%F0%AF%BF%BD"
'
diff --git a/t/t0202/test.pl b/t/t0202/test.pl
index 2c10cb4693..2c10cb4693 100644..100755
--- a/t/t0202/test.pl
+++ b/t/t0202/test.pl
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 538ea5fb1c..57ea5a10c5 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -6,7 +6,7 @@ test_description='basic credential helper tests'
test_expect_success 'setup helper scripts' '
cat >dump <<-\EOF &&
- whoami=`echo $0 | sed s/.*git-credential-//`
+ whoami=$(echo $0 | sed s/.*git-credential-//)
echo >&2 "$whoami: $*"
OIFS=$IFS
IFS==
diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh
index babcdd2343..a0b79b4839 100755
--- a/t/t1000-read-tree-m-3way.sh
+++ b/t/t1000-read-tree-m-3way.sh
@@ -519,10 +519,10 @@ test_expect_success \
'rm -f .git/index F16 &&
echo F16 >F16 &&
git update-index --add F16 &&
- tree0=`git write-tree` &&
+ tree0=$(git write-tree) &&
echo E16 >F16 &&
git update-index F16 &&
- tree1=`git write-tree` &&
+ tree1=$(git write-tree) &&
read_tree_must_succeed -m $tree0 $tree1 $tree1 $tree0 &&
git ls-files --stage'
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index acaab07fac..db1b6f5cf4 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -18,7 +18,7 @@ In the test, these paths are used:
frotz - not in H added in M
nitfol - in H, stays in M unmodified
rezrov - in H, deleted in M
- yomin - not in H nor M
+ yomin - not in H or M
'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree.sh
@@ -36,7 +36,7 @@ compare_change () {
}
check_cache_at () {
- clean_if_empty=`git diff-files -- "$1"`
+ clean_if_empty=$(git diff-files -- "$1")
case "$clean_if_empty" in
'') echo "$1: clean" ;;
?*) echo "$1: dirty" ;;
@@ -68,14 +68,14 @@ test_expect_success \
echo rezrov >rezrov &&
echo yomin >yomin &&
git update-index --add nitfol bozbar rezrov &&
- treeH=`git write-tree` &&
+ treeH=$(git write-tree) &&
echo treeH $treeH &&
git ls-tree $treeH &&
cat bozbar-new >bozbar &&
git update-index --add frotz bozbar --force-remove rezrov &&
git ls-files --stage >M.out &&
- treeM=`git write-tree` &&
+ treeM=$(git write-tree) &&
echo treeM $treeM &&
git ls-tree $treeM &&
git diff-tree $treeH $treeM'
@@ -315,7 +315,7 @@ test_expect_success \
'rm -f .git/index &&
echo DF >DF &&
git update-index --add DF &&
- treeDF=`git write-tree` &&
+ treeDF=$(git write-tree) &&
echo treeDF $treeDF &&
git ls-tree $treeDF &&
@@ -323,7 +323,7 @@ test_expect_success \
mkdir DF &&
echo DF/DF >DF/DF &&
git update-index --add --remove DF DF/DF &&
- treeDFDF=`git write-tree` &&
+ treeDFDF=$(git write-tree) &&
echo treeDFDF $treeDFDF &&
git ls-tree $treeDFDF &&
git ls-files --stage >DFDF.out'
@@ -345,7 +345,7 @@ test_expect_success \
'rm -f .git/index &&
: >a &&
git update-index --add a &&
- treeM=`git write-tree` &&
+ treeM=$(git write-tree) &&
echo treeM $treeM &&
git ls-tree $treeM &&
git ls-files --stage >treeM.out &&
@@ -354,7 +354,7 @@ test_expect_success \
git update-index --remove a &&
mkdir a &&
: >a/b &&
- treeH=`git write-tree` &&
+ treeH=$(git write-tree) &&
echo treeH $treeH &&
git ls-tree $treeH'
@@ -372,7 +372,7 @@ test_expect_success \
mkdir c &&
: >c/d &&
git update-index --add a c/d &&
- treeM=`git write-tree` &&
+ treeM=$(git write-tree) &&
echo treeM $treeM &&
git ls-tree $treeM &&
git ls-files --stage >treeM.out &&
@@ -381,7 +381,7 @@ test_expect_success \
mkdir a &&
: >a/b &&
git update-index --add --remove a a/b &&
- treeH=`git write-tree` &&
+ treeH=$(git write-tree) &&
echo treeH $treeH &&
git ls-tree $treeH'
diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh
index a847709a13..fed877b20f 100755
--- a/t/t1002-read-tree-m-u-2way.sh
+++ b/t/t1002-read-tree-m-u-2way.sh
@@ -21,7 +21,7 @@ compare_change () {
}
check_cache_at () {
- clean_if_empty=`git diff-files -- "$1"`
+ clean_if_empty=$(git diff-files -- "$1")
case "$clean_if_empty" in
'') echo "$1: clean" ;;
?*) echo "$1: dirty" ;;
@@ -41,14 +41,14 @@ test_expect_success \
echo bozbar >bozbar &&
echo rezrov >rezrov &&
git update-index --add nitfol bozbar rezrov &&
- treeH=`git write-tree` &&
+ treeH=$(git write-tree) &&
echo treeH $treeH &&
git ls-tree $treeH &&
echo gnusto >bozbar &&
git update-index --add frotz bozbar --force-remove rezrov &&
git ls-files --stage >M.out &&
- treeM=`git write-tree` &&
+ treeM=$(git write-tree) &&
echo treeM $treeM &&
git ls-tree $treeM &&
sum bozbar frotz nitfol >M.sum &&
@@ -318,7 +318,7 @@ test_expect_success \
'rm -f .git/index &&
echo DF >DF &&
git update-index --add DF &&
- treeDF=`git write-tree` &&
+ treeDF=$(git write-tree) &&
echo treeDF $treeDF &&
git ls-tree $treeDF &&
@@ -326,7 +326,7 @@ test_expect_success \
mkdir DF &&
echo DF/DF >DF/DF &&
git update-index --add --remove DF DF/DF &&
- treeDFDF=`git write-tree` &&
+ treeDFDF=$(git write-tree) &&
echo treeDFDF $treeDFDF &&
git ls-tree $treeDFDF &&
git ls-files --stage >DFDF.out'
diff --git a/t/t1003-read-tree-prefix.sh b/t/t1003-read-tree-prefix.sh
index 8c6d67edda..b6111cd150 100755
--- a/t/t1003-read-tree-prefix.sh
+++ b/t/t1003-read-tree-prefix.sh
@@ -11,7 +11,7 @@ test_description='git read-tree --prefix test.
test_expect_success setup '
echo hello >one &&
git update-index --add one &&
- tree=`git write-tree` &&
+ tree=$(git write-tree) &&
echo tree is $tree
'
diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh
index 3e72aff470..c70cf42300 100755
--- a/t/t1004-read-tree-m-u-wf.sh
+++ b/t/t1004-read-tree-m-u-wf.sh
@@ -30,7 +30,7 @@ test_expect_success 'two-way not clobbering' '
echo >file2 master creates untracked file2 &&
echo >subdir/file2 master creates untracked subdir/file2 &&
- if err=`read_tree_u_must_succeed -m -u master side 2>&1`
+ if err=$(read_tree_u_must_succeed -m -u master side 2>&1)
then
echo should have complained
false
@@ -43,7 +43,7 @@ echo file2 >.gitignore
test_expect_success 'two-way with incorrect --exclude-per-directory (1)' '
- if err=`read_tree_u_must_succeed -m --exclude-per-directory=.gitignore master side 2>&1`
+ if err=$(read_tree_u_must_succeed -m --exclude-per-directory=.gitignore master side 2>&1)
then
echo should have complained
false
@@ -54,7 +54,7 @@ test_expect_success 'two-way with incorrect --exclude-per-directory (1)' '
test_expect_success 'two-way with incorrect --exclude-per-directory (2)' '
- if err=`read_tree_u_must_succeed -m -u --exclude-per-directory=foo --exclude-per-directory=.gitignore master side 2>&1`
+ if err=$(read_tree_u_must_succeed -m -u --exclude-per-directory=foo --exclude-per-directory=.gitignore master side 2>&1)
then
echo should have complained
false
@@ -95,7 +95,7 @@ test_expect_success 'three-way not clobbering a working tree file' '
git checkout master &&
echo >file3 file three created in master, untracked &&
echo >subdir/file3 file three created in master, untracked &&
- if err=`read_tree_u_must_succeed -m -u branch-point master side 2>&1`
+ if err=$(read_tree_u_must_succeed -m -u branch-point master side 2>&1)
then
echo should have complained
false
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 1687098355..a72e700ae4 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -262,4 +262,38 @@ test_expect_success "--batch-check with multiple sha1s gives correct format" '
"$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)"
'
+test_expect_success 'setup blobs which are likely to delta' '
+ test-genrandom foo 10240 >foo &&
+ { cat foo; echo plus; } >foo-plus &&
+ git add foo foo-plus &&
+ git commit -m foo &&
+ cat >blobs <<-\EOF
+ HEAD:foo
+ HEAD:foo-plus
+ EOF
+'
+
+test_expect_success 'confirm that neither loose blob is a delta' '
+ cat >expect <<-EOF
+ $_z40
+ $_z40
+ EOF
+ git cat-file --batch-check="%(deltabase)" <blobs >actual &&
+ test_cmp expect actual
+'
+
+# To avoid relying too much on the current delta heuristics,
+# we will check only that one of the two objects is a delta
+# against the other, but not the order. We can do so by just
+# asking for the base of both, and checking whether either
+# sha1 appears in the output.
+test_expect_success '%(deltabase) reports packed delta bases' '
+ git repack -ad &&
+ git cat-file --batch-check="%(deltabase)" <blobs >actual &&
+ {
+ grep "$(git rev-parse HEAD:foo)" actual ||
+ grep "$(git rev-parse HEAD:foo-plus)" actual
+ }
+'
+
test_done
diff --git a/t/t1013-loose-object-format.sh b/t/t1013-loose-object-format.sh
deleted file mode 100755
index fbf5f2fc00..0000000000
--- a/t/t1013-loose-object-format.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2011 Roberto Tyley
-#
-
-test_description='Correctly identify and parse loose object headers
-
-There are two file formats for loose objects - the original standard
-format, and the experimental format introduced with Git v1.4.3, later
-deprecated with v1.5.3. Although Git no longer writes the
-experimental format, objects in both formats must be read, with the
-format for a given file being determined by the header.
-
-Detecting file format based on header is not entirely trivial, not
-least because the first byte of a zlib-deflated stream will vary
-depending on how much memory was allocated for the deflation window
-buffer when the object was written out (for example 4KB on Android,
-rather that 32KB on a normal PC).
-
-The loose objects used as test vectors have been generated with the
-following Git versions:
-
-standard format: Git v1.7.4.1
-experimental format: Git v1.4.3 (legacyheaders=false)
-standard format, deflated with 4KB window size: Agit/JGit on Android
-'
-
-. ./test-lib.sh
-
-assert_blob_equals() {
- printf "%s" "$2" >expected &&
- git cat-file -p "$1" >actual &&
- test_cmp expected actual
-}
-
-test_expect_success setup '
- cp -R "$TEST_DIRECTORY/t1013/objects" .git/ &&
- git --version
-'
-
-test_expect_success 'read standard-format loose objects' '
- git cat-file tag 8d4e360d6c70fbd72411991c02a09c442cf7a9fa &&
- git cat-file commit 6baee0540ea990d9761a3eb9ab183003a71c3696 &&
- git ls-tree 7a37b887a73791d12d26c0d3e39568a8fb0fa6e8 &&
- assert_blob_equals "257cc5642cb1a054f08cc83f2d943e56fd3ebe99" "foo$LF"
-'
-
-test_expect_success 'read experimental-format loose objects' '
- git cat-file tag 76e7fa9941f4d5f97f64fea65a2cba436bc79cbb &&
- git cat-file commit 7875c6237d3fcdd0ac2f0decc7d3fa6a50b66c09 &&
- git ls-tree 95b1625de3ba8b2214d1e0d0591138aea733f64f &&
- assert_blob_equals "2e65efe2a145dda7ee51d1741299f848e5bf752e" "a" &&
- assert_blob_equals "9ae9e86b7bd6cb1472d9373702d8249973da0832" "ab" &&
- assert_blob_equals "85df50785d62d3b05ab03d9cbf7e4a0b49449730" "abcd" &&
- assert_blob_equals "1656f9233d999f61ef23ef390b9c71d75399f435" "abcdefgh" &&
- assert_blob_equals "1e72a6b2c4a577ab0338860fa9fe87f761fc9bbd" "abcdefghi" &&
- assert_blob_equals "70e6a83d8dcb26fc8bc0cf702e2ddeb6adca18fd" "abcdefghijklmnop" &&
- assert_blob_equals "bd15045f6ce8ff75747562173640456a394412c8" "abcdefghijklmnopqrstuvwx"
-'
-
-test_expect_success 'read standard-format objects deflated with smaller window buffer' '
- git cat-file tag f816d5255855ac160652ee5253b06cd8ee14165a &&
- git cat-file tag 149cedb5c46929d18e0f118e9fa31927487af3b6
-'
-
-test_done
diff --git a/t/t1013-read-tree-submodule.sh b/t/t1013-read-tree-submodule.sh
new file mode 100755
index 0000000000..20526aed34
--- /dev/null
+++ b/t/t1013-read-tree-submodule.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+test_description='read-tree can handle submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+test_submodule_switch "git read-tree -u -m"
+
+test_submodule_forced_switch "git read-tree -u --reset"
+
+test_done
diff --git a/t/t1013/objects/14/9cedb5c46929d18e0f118e9fa31927487af3b6 b/t/t1013/objects/14/9cedb5c46929d18e0f118e9fa31927487af3b6
deleted file mode 100644
index 472fd1458e..0000000000
--- a/t/t1013/objects/14/9cedb5c46929d18e0f118e9fa31927487af3b6
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/16/56f9233d999f61ef23ef390b9c71d75399f435 b/t/t1013/objects/16/56f9233d999f61ef23ef390b9c71d75399f435
deleted file mode 100644
index c379d74ae2..0000000000
--- a/t/t1013/objects/16/56f9233d999f61ef23ef390b9c71d75399f435
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/1e/72a6b2c4a577ab0338860fa9fe87f761fc9bbd b/t/t1013/objects/1e/72a6b2c4a577ab0338860fa9fe87f761fc9bbd
deleted file mode 100644
index 93706305bc..0000000000
--- a/t/t1013/objects/1e/72a6b2c4a577ab0338860fa9fe87f761fc9bbd
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 b/t/t1013/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99
deleted file mode 100644
index bdcf704c9e..0000000000
--- a/t/t1013/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752e b/t/t1013/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752e
deleted file mode 100644
index ad62c43e41..0000000000
--- a/t/t1013/objects/2e/65efe2a145dda7ee51d1741299f848e5bf752e
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/6b/aee0540ea990d9761a3eb9ab183003a71c3696 b/t/t1013/objects/6b/aee0540ea990d9761a3eb9ab183003a71c3696
deleted file mode 100644
index 3d2f0337db..0000000000
--- a/t/t1013/objects/6b/aee0540ea990d9761a3eb9ab183003a71c3696
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/70/e6a83d8dcb26fc8bc0cf702e2ddeb6adca18fd b/t/t1013/objects/70/e6a83d8dcb26fc8bc0cf702e2ddeb6adca18fd
deleted file mode 100644
index b3f71a6ee5..0000000000
--- a/t/t1013/objects/70/e6a83d8dcb26fc8bc0cf702e2ddeb6adca18fd
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/76/e7fa9941f4d5f97f64fea65a2cba436bc79cbb b/t/t1013/objects/76/e7fa9941f4d5f97f64fea65a2cba436bc79cbb
deleted file mode 100644
index af4e9a7b0c..0000000000
--- a/t/t1013/objects/76/e7fa9941f4d5f97f64fea65a2cba436bc79cbb
+++ /dev/null
@@ -1,2 +0,0 @@
- xœ%ÌA‚0@Ñ}O1{cSZ(˜ãνáÃthª”’ZŒÜÞ Ëÿ? ¦m×6dµiÉ9…¤Gå˜h´Ø¨ÁZR'Q¶…RŒ¡ˆ‚ø³p‘ç‚ÓqL9âÏ=g¸§sIÐoopÎÿ”eÏ«_1»€³¤$×ç*Si«ëNwpP•RBôûÅÁú
-³‡[(ð®d-øÁL9á \ No newline at end of file
diff --git a/t/t1013/objects/78/75c6237d3fcdd0ac2f0decc7d3fa6a50b66c09 b/t/t1013/objects/78/75c6237d3fcdd0ac2f0decc7d3fa6a50b66c09
deleted file mode 100644
index 3dd28be5c6..0000000000
--- a/t/t1013/objects/78/75c6237d3fcdd0ac2f0decc7d3fa6a50b66c09
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/7a/37b887a73791d12d26c0d3e39568a8fb0fa6e8 b/t/t1013/objects/7a/37b887a73791d12d26c0d3e39568a8fb0fa6e8
deleted file mode 100644
index 2b97b264c3..0000000000
--- a/t/t1013/objects/7a/37b887a73791d12d26c0d3e39568a8fb0fa6e8
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/85/df50785d62d3b05ab03d9cbf7e4a0b49449730 b/t/t1013/objects/85/df50785d62d3b05ab03d9cbf7e4a0b49449730
deleted file mode 100644
index 6dff746876..0000000000
--- a/t/t1013/objects/85/df50785d62d3b05ab03d9cbf7e4a0b49449730
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/8d/4e360d6c70fbd72411991c02a09c442cf7a9fa b/t/t1013/objects/8d/4e360d6c70fbd72411991c02a09c442cf7a9fa
deleted file mode 100644
index cb41e92d07..0000000000
--- a/t/t1013/objects/8d/4e360d6c70fbd72411991c02a09c442cf7a9fa
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/95/b1625de3ba8b2214d1e0d0591138aea733f64f b/t/t1013/objects/95/b1625de3ba8b2214d1e0d0591138aea733f64f
deleted file mode 100644
index 7ac46b4f70..0000000000
--- a/t/t1013/objects/95/b1625de3ba8b2214d1e0d0591138aea733f64f
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/9a/e9e86b7bd6cb1472d9373702d8249973da0832 b/t/t1013/objects/9a/e9e86b7bd6cb1472d9373702d8249973da0832
deleted file mode 100644
index 9d8316d4e5..0000000000
--- a/t/t1013/objects/9a/e9e86b7bd6cb1472d9373702d8249973da0832
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/bd/15045f6ce8ff75747562173640456a394412c8 b/t/t1013/objects/bd/15045f6ce8ff75747562173640456a394412c8
deleted file mode 100644
index eebf23956e..0000000000
--- a/t/t1013/objects/bd/15045f6ce8ff75747562173640456a394412c8
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/t/t1013/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
deleted file mode 100644
index 134cf19379..0000000000
--- a/t/t1013/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
+++ /dev/null
Binary files differ
diff --git a/t/t1013/objects/f8/16d5255855ac160652ee5253b06cd8ee14165a b/t/t1013/objects/f8/16d5255855ac160652ee5253b06cd8ee14165a
deleted file mode 100644
index 26b75aec56..0000000000
--- a/t/t1013/objects/f8/16d5255855ac160652ee5253b06cd8ee14165a
+++ /dev/null
@@ -1 +0,0 @@
-H‰ÌÁ‚0 €aÏ{ŠÞ I»e&Æø*¥ˆG°ß^¸ýù¿ËDåÒ†wU‡Ò—¬S±4ªŠÆ­ªž ,fÅ[ðßVAÛºÎüxÈÇö6[wtG§Lu¸?—¦²¼Ú×@‰"gì{†+by¾%M \ No newline at end of file
diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh
index 1e2945ec7e..2edb4f2de5 100755
--- a/t/t1020-subdirectory.sh
+++ b/t/t1020-subdirectory.sh
@@ -20,27 +20,27 @@ test_expect_success setup '
test_expect_success 'update-index and ls-files' '
git update-index --add one &&
- case "`git ls-files`" in
+ case "$(git ls-files)" in
one) echo pass one ;;
*) echo bad one; exit 1 ;;
esac &&
(
cd dir &&
git update-index --add two &&
- case "`git ls-files`" in
+ case "$(git ls-files)" in
two) echo pass two ;;
*) echo bad two; exit 1 ;;
esac
) &&
- case "`git ls-files`" in
+ case "$(git ls-files)" in
dir/two"$LF"one) echo pass both ;;
*) echo bad; exit 1 ;;
esac
'
test_expect_success 'cat-file' '
- two=`git ls-files -s dir/two` &&
- two=`expr "$two" : "[0-7]* \\([0-9a-f]*\\)"` &&
+ two=$(git ls-files -s dir/two) &&
+ two=$(expr "$two" : "[0-7]* \\([0-9a-f]*\\)") &&
echo "$two" &&
git cat-file -p "$two" >actual &&
cmp dir/two actual &&
@@ -55,18 +55,18 @@ rm -f actual dir/actual
test_expect_success 'diff-files' '
echo a >>one &&
echo d >>dir/two &&
- case "`git diff-files --name-only`" in
+ case "$(git diff-files --name-only)" in
dir/two"$LF"one) echo pass top ;;
*) echo bad top; exit 1 ;;
esac &&
# diff should not omit leading paths
(
cd dir &&
- case "`git diff-files --name-only`" in
+ case "$(git diff-files --name-only)" in
dir/two"$LF"one) echo pass subdir ;;
*) echo bad subdir; exit 1 ;;
esac &&
- case "`git diff-files --name-only .`" in
+ case "$(git diff-files --name-only .)" in
dir/two) echo pass subdir limited ;;
*) echo bad subdir limited; exit 1 ;;
esac
@@ -74,11 +74,11 @@ test_expect_success 'diff-files' '
'
test_expect_success 'write-tree' '
- top=`git write-tree` &&
+ top=$(git write-tree) &&
echo $top &&
(
cd dir &&
- sub=`git write-tree` &&
+ sub=$(git write-tree) &&
echo $sub &&
test "z$top" = "z$sub"
)
@@ -96,7 +96,7 @@ test_expect_success 'checkout-index' '
test_expect_success 'read-tree' '
rm -f one dir/two &&
- tree=`git write-tree` &&
+ tree=$(git write-tree) &&
read_tree_u_must_succeed --reset -u "$tree" &&
cmp one original.one &&
cmp dir/two original.two &&
@@ -118,7 +118,7 @@ test_expect_success 'alias expansion' '
)
'
-test_expect_success NOT_MINGW '!alias expansion' '
+test_expect_success !MINGW '!alias expansion' '
pwd >expect &&
(
git config alias.test-alias-directory !pwd &&
@@ -148,7 +148,7 @@ test_expect_success 'GIT_PREFIX for built-ins' '
(
cd dir &&
printf "change" >two &&
- env GIT_EXTERNAL_DIFF=./diff git diff >../actual
+ GIT_EXTERNAL_DIFF=./diff git diff >../actual
git checkout -- two
) &&
test_cmp expect actual
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index fd10528009..f5a9119290 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -13,7 +13,7 @@ test_expect_success setup '
echo X | dd of=large2 bs=1k seek=2000 &&
echo X | dd of=large3 bs=1k seek=2000 &&
echo Y | dd of=huge bs=1k seek=2500 &&
- GIT_ALLOC_LIMIT=1500 &&
+ GIT_ALLOC_LIMIT=1500k &&
export GIT_ALLOC_LIMIT
'
@@ -112,6 +112,20 @@ test_expect_success 'diff --raw' '
git diff --raw HEAD^
'
+test_expect_success 'diff --stat' '
+ git diff --stat HEAD^ HEAD
+'
+
+test_expect_success 'diff' '
+ git diff HEAD^ HEAD >actual &&
+ grep "Binary files.*differ" actual
+'
+
+test_expect_success 'diff --cached' '
+ git diff --cached HEAD^ >actual &&
+ grep "Binary files.*differ" actual
+'
+
test_expect_success 'hash-object' '
git hash-object large1
'
@@ -131,7 +145,7 @@ test_expect_success 'git-show a large file' '
'
test_expect_success 'index-pack' '
- git clone file://"`pwd`"/.git foo &&
+ git clone file://"$(pwd)"/.git foo &&
GIT_DIR=non-existent git index-pack --strict --verify foo/.git/objects/pack/*.pack
'
@@ -140,7 +154,7 @@ test_expect_success 'repack' '
'
test_expect_success 'pack-objects with large loose object' '
- SHA1=`git hash-object huge` &&
+ SHA1=$(git hash-object huge) &&
test_create_repo loose &&
echo $SHA1 | git pack-objects --stdout |
GIT_ALLOC_LIMIT=0 GIT_DIR=loose/.git git unpack-objects &&
@@ -163,4 +177,10 @@ test_expect_success 'zip achiving, deflate' '
git archive --format=zip HEAD >/dev/null
'
+test_expect_success 'fsck' '
+ test_must_fail git fsck 2>err &&
+ n=$(grep "error: attempting to allocate .* over limit" err | wc -l) &&
+ test "$n" -gt 1
+'
+
test_done
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 967359344d..938fc8bfd7 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -461,7 +461,7 @@ test_expect_success 'new variable inserts into proper section' '
test_cmp expect .git/config
'
-test_expect_success 'alternative GIT_CONFIG (non-existing file should fail)' '
+test_expect_success 'alternative --file (non-existing file should fail)' '
test_must_fail git config --file non-existing-config -l
'
@@ -475,15 +475,28 @@ ein.bahn=strasse
EOF
test_expect_success 'alternative GIT_CONFIG' '
- GIT_CONFIG=other-config git config -l >output &&
+ GIT_CONFIG=other-config git config --list >output &&
test_cmp expect output
'
test_expect_success 'alternative GIT_CONFIG (--file)' '
- git config --file other-config -l > output &&
+ git config --file other-config --list >output &&
test_cmp expect output
'
+test_expect_success 'alternative GIT_CONFIG (--file=-)' '
+ git config --file - --list <other-config >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'setting a value in stdin is an error' '
+ test_must_fail git config --file - some.value foo
+'
+
+test_expect_success 'editing stdin is an error' '
+ test_must_fail git config --file - --edit
+'
+
test_expect_success 'refer config from subdirectory' '
mkdir x &&
(
@@ -495,10 +508,10 @@ test_expect_success 'refer config from subdirectory' '
'
-test_expect_success 'refer config from subdirectory via GIT_CONFIG' '
+test_expect_success 'refer config from subdirectory via --file' '
(
cd x &&
- GIT_CONFIG=../other-config git config --get ein.bahn >actual &&
+ git config --file=../other-config --get ein.bahn >actual &&
test_cmp expect actual
)
'
@@ -510,8 +523,8 @@ cat > expect << EOF
park = ausweis
EOF
-test_expect_success '--set in alternative GIT_CONFIG' '
- GIT_CONFIG=other-config git config anwohner.park ausweis &&
+test_expect_success '--set in alternative file' '
+ git config --file=other-config anwohner.park ausweis &&
test_cmp expect other-config
'
@@ -811,14 +824,14 @@ cat >expect <<\EOF
trailingtilde = foo~
EOF
-test_expect_success NOT_MINGW 'set --path' '
+test_expect_success !MINGW 'set --path' '
rm -f .git/config &&
git config --path path.home "~/" &&
git config --path path.normal "/dev/null" &&
git config --path path.trailingtilde "foo~" &&
test_cmp expect .git/config'
-if test_have_prereq NOT_MINGW && test "${HOME+set}"
+if test_have_prereq !MINGW && test "${HOME+set}"
then
test_set_prereq HOMEVAR
fi
@@ -841,7 +854,7 @@ cat >expect <<\EOF
foo~
EOF
-test_expect_success NOT_MINGW 'get --path copes with unset $HOME' '
+test_expect_success !MINGW 'get --path copes with unset $HOME' '
(
unset HOME;
test_must_fail git config --get --path path.home \
@@ -942,11 +955,11 @@ test_expect_success 'inner whitespace kept verbatim' '
test_expect_success SYMLINKS 'symlinked configuration' '
ln -s notyet myconfig &&
- GIT_CONFIG=myconfig git config test.frotz nitfol &&
+ git config --file=myconfig test.frotz nitfol &&
test -h myconfig &&
test -f notyet &&
- test "z$(GIT_CONFIG=notyet git config test.frotz)" = znitfol &&
- GIT_CONFIG=myconfig git config test.xyzzy rezrov &&
+ test "z$(git config --file=notyet test.frotz)" = znitfol &&
+ git config --file=myconfig test.xyzzy rezrov &&
test -h myconfig &&
test -f notyet &&
cat >expect <<-\EOF &&
@@ -954,31 +967,22 @@ test_expect_success SYMLINKS 'symlinked configuration' '
rezrov
EOF
{
- GIT_CONFIG=notyet git config test.frotz &&
- GIT_CONFIG=notyet git config test.xyzzy
+ git config --file=notyet test.frotz &&
+ git config --file=notyet test.xyzzy
} >actual &&
test_cmp expect actual
'
test_expect_success 'nonexistent configuration' '
- (
- GIT_CONFIG=doesnotexist &&
- export GIT_CONFIG &&
- test_must_fail git config --list &&
- test_must_fail git config test.xyzzy
- )
+ test_must_fail git config --file=doesnotexist --list &&
+ test_must_fail git config --file=doesnotexist test.xyzzy
'
test_expect_success SYMLINKS 'symlink to nonexistent configuration' '
ln -s doesnotexist linktonada &&
ln -s linktonada linktolinktonada &&
- (
- GIT_CONFIG=linktonada &&
- export GIT_CONFIG &&
- test_must_fail git config --list &&
- GIT_CONFIG=linktolinktonada &&
- test_must_fail git config --list
- )
+ test_must_fail git config --file=linktonada --list &&
+ test_must_fail git config --file=linktolinktonada --list
'
test_expect_success 'check split_cmdline return' "
@@ -1006,6 +1010,17 @@ test_expect_success 'git -c "key=value" support' '
test_must_fail git -c name=value config core.name
'
+# We just need a type-specifier here that cares about the
+# distinction internally between a NULL boolean and a real
+# string (because most of git's internal parsers do care).
+# Using "--path" works, but we do not otherwise care about
+# its semantics.
+test_expect_success 'git -c can represent empty string' '
+ echo >expect &&
+ git -c foo.empty= config --path foo.empty >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'key sanity-checking' '
test_must_fail git config foo=bar &&
test_must_fail git config foo=.bar &&
@@ -1154,4 +1169,14 @@ test_expect_failure 'adding a key into an empty section reuses header' '
test_cmp expect .git/config
'
+test_expect_success POSIXPERM,PERL 'preserves existing permissions' '
+ chmod 0600 .git/config &&
+ git config imap.pass Hunter2 &&
+ perl -e \
+ "die q(badset) if ((stat(q(.git/config)))[2] & 07777) != 0600" &&
+ git config --rename-section imap pop &&
+ perl -e \
+ "die q(badrename) if ((stat(q(.git/config)))[2] & 07777) != 0600"
+'
+
test_done
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 0e47662406..0d9388afc4 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -19,7 +19,7 @@ test_expect_success 'setup' '
test_create_repo "test" &&
test_create_repo "test2" &&
- GIT_CONFIG=test2/.git/config git config core.repositoryformatversion 99
+ git config --file=test2/.git/config core.repositoryformatversion 99
'
test_expect_success 'gitdir selection on normal repos' '
diff --git a/t/t1303-wacky-config.sh b/t/t1303-wacky-config.sh
index 46103a1591..3b92083e19 100755
--- a/t/t1303-wacky-config.sh
+++ b/t/t1303-wacky-config.sh
@@ -3,17 +3,28 @@
test_description='Test wacky input to git config'
. ./test-lib.sh
+# Leaving off the newline is intentional!
setup() {
(printf "[section]\n" &&
printf " key = foo") >.git/config
}
+# 'check section.key value' verifies that the entry for section.key is
+# 'value'
check() {
echo "$2" >expected
git config --get "$1" >actual 2>&1
test_cmp actual expected
}
+# 'check section.key regex value' verifies that the entry for
+# section.key *that matches 'regex'* is 'value'
+check_regex() {
+ echo "$3" >expected
+ git config --get "$1" "$2" >actual 2>&1
+ test_cmp actual expected
+}
+
test_expect_success 'modify same key' '
setup &&
git config section.key bar &&
@@ -47,4 +58,77 @@ test_expect_success 'do not crash on special long config line' '
check section.key "$LONG_VALUE"
'
+setup_many() {
+ setup &&
+ # This time we want the newline so that we can tack on more
+ # entries.
+ echo >>.git/config &&
+ # Semi-efficient way of concatenating 5^5 = 3125 lines. Note
+ # that because 'setup' already put one line, this means 3126
+ # entries for section.key in the config file.
+ cat >5to1 <<-\EOF &&
+ key = foo
+ key = foo
+ key = foo
+ key = foo
+ key = foo
+ EOF
+ cat 5to1 5to1 5to1 5to1 5to1 >5to2 && # 25
+ cat 5to2 5to2 5to2 5to2 5to2 >5to3 && # 125
+ cat 5to3 5to3 5to3 5to3 5to3 >5to4 && # 635
+ cat 5to4 5to4 5to4 5to4 5to4 >>.git/config # 3125
+}
+
+test_expect_success 'get many entries' '
+ setup_many &&
+ git config --get-all section.key >actual &&
+ test_line_count = 3126 actual
+'
+
+test_expect_success 'get many entries by regex' '
+ setup_many &&
+ git config --get-regexp "sec.*ke." >actual &&
+ test_line_count = 3126 actual
+'
+
+test_expect_success 'add and replace one of many entries' '
+ setup_many &&
+ git config --add section.key bar &&
+ check_regex section.key "b.*r" bar &&
+ git config section.key beer "b.*r" &&
+ check_regex section.key "b.*r" beer
+'
+
+test_expect_success 'replace many entries' '
+ setup_many &&
+ git config --replace-all section.key bar &&
+ check section.key bar
+'
+
+test_expect_success 'unset many entries' '
+ setup_many &&
+ git config --unset-all section.key &&
+ test_must_fail git config section.key
+'
+
+test_expect_success '--add appends new value after existing empty value' '
+ cat >expect <<-\EOF &&
+
+
+ fool
+ roll
+ EOF
+ cp .git/config .git/config.old &&
+ test_when_finished "mv .git/config.old .git/config" &&
+ cat >.git/config <<-\EOF &&
+ [foo]
+ baz
+ baz =
+ baz = fool
+ EOF
+ git config --add foo.baz roll &&
+ git config --get-all foo.baz >output &&
+ test_cmp expect output
+'
+
test_done
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index 79045abb51..f5422f1d33 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -26,7 +26,7 @@ test_expect_success 'checking for a working acl setup' '
if test -z "$LOGNAME"
then
- LOGNAME=$USER
+ LOGNAME="${USER:-$(id -u -n)}"
fi
check_perms_and_acl () {
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index a70707620f..9ba2ba11c3 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -113,7 +113,7 @@ test_expect_success 'missing include files are ignored' '
test_expect_success 'absolute includes from command line work' '
echo "[test]one = 1" >one &&
echo 1 >expect &&
- git -c include.path="$PWD/one" config test.one >actual &&
+ git -c include.path="$(pwd)/one" config test.one >actual &&
test_cmp expect actual
'
@@ -122,6 +122,36 @@ test_expect_success 'relative includes from command line fail' '
test_must_fail git -c include.path=one config test.one
'
+test_expect_success 'absolute includes from blobs work' '
+ echo "[test]one = 1" >one &&
+ echo "[include]path=$(pwd)/one" >blob &&
+ blob=$(git hash-object -w blob) &&
+ echo 1 >expect &&
+ git config --blob=$blob test.one >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'relative includes from blobs fail' '
+ echo "[test]one = 1" >one &&
+ echo "[include]path=one" >blob &&
+ blob=$(git hash-object -w blob) &&
+ test_must_fail git config --blob=$blob test.one
+'
+
+test_expect_success 'absolute includes from stdin work' '
+ echo "[test]one = 1" >one &&
+ echo 1 >expect &&
+ echo "[include]path=\"$(pwd)/one\"" |
+ git config --file - test.one >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'relative includes from stdin line fail' '
+ echo "[test]one = 1" >one &&
+ echo "[include]path=one" |
+ test_must_fail git config --file - test.one
+'
+
test_expect_success 'include cycles are detected' '
cat >.gitconfig <<-\EOF &&
[test]value = gitconfig
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
new file mode 100755
index 0000000000..91235b76ba
--- /dev/null
+++ b/t/t1308-config-set.sh
@@ -0,0 +1,221 @@
+#!/bin/sh
+
+test_description='Test git config-set API in different settings'
+
+. ./test-lib.sh
+
+# 'check_config get_* section.key value' verifies that the entry for
+# section.key is 'value'
+check_config () {
+ if test "$1" = expect_code
+ then
+ expect_code="$2" && shift && shift
+ else
+ expect_code=0
+ fi &&
+ op=$1 key=$2 && shift && shift &&
+ if test $# != 0
+ then
+ printf "%s\n" "$@"
+ fi >expect &&
+ test_expect_code $expect_code test-config "$op" "$key" >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'setup default config' '
+ cat >.git/config <<-\EOF
+ [case]
+ penguin = very blue
+ Movie = BadPhysics
+ UPPERCASE = true
+ MixedCase = true
+ my =
+ foo
+ baz = sam
+ [Cores]
+ WhatEver = Second
+ baz = bar
+ [cores]
+ baz = bat
+ [CORES]
+ baz = ball
+ [my "Foo bAr"]
+ hi = mixed-case
+ [my "FOO BAR"]
+ hi = upper-case
+ [my "foo bar"]
+ hi = lower-case
+ [case]
+ baz = bat
+ baz = hask
+ [lamb]
+ chop = 65
+ head = none
+ [goat]
+ legs = 4
+ head = true
+ skin = false
+ nose = 1
+ horns
+ EOF
+'
+
+test_expect_success 'get value for a simple key' '
+ check_config get_value case.penguin "very blue"
+'
+
+test_expect_success 'get value for a key with value as an empty string' '
+ check_config get_value case.my ""
+'
+
+test_expect_success 'get value for a key with value as NULL' '
+ check_config get_value case.foo "(NULL)"
+'
+
+test_expect_success 'upper case key' '
+ check_config get_value case.UPPERCASE "true" &&
+ check_config get_value case.uppercase "true"
+'
+
+test_expect_success 'mixed case key' '
+ check_config get_value case.MixedCase "true" &&
+ check_config get_value case.MIXEDCASE "true" &&
+ check_config get_value case.mixedcase "true"
+'
+
+test_expect_success 'key and value with mixed case' '
+ check_config get_value case.Movie "BadPhysics"
+'
+
+test_expect_success 'key with case sensitive subsection' '
+ check_config get_value "my.Foo bAr.hi" "mixed-case" &&
+ check_config get_value "my.FOO BAR.hi" "upper-case" &&
+ check_config get_value "my.foo bar.hi" "lower-case"
+'
+
+test_expect_success 'key with case insensitive section header' '
+ check_config get_value cores.baz "ball" &&
+ check_config get_value Cores.baz "ball" &&
+ check_config get_value CORES.baz "ball" &&
+ check_config get_value coreS.baz "ball"
+'
+
+test_expect_success 'key with case insensitive section header & variable' '
+ check_config get_value CORES.BAZ "ball" &&
+ check_config get_value cores.baz "ball" &&
+ check_config get_value cores.BaZ "ball" &&
+ check_config get_value cOreS.bAz "ball"
+'
+
+test_expect_success 'find value with misspelled key' '
+ check_config expect_code 1 get_value "my.fOo Bar.hi" "Value not found for \"my.fOo Bar.hi\""
+'
+
+test_expect_success 'find value with the highest priority' '
+ check_config get_value case.baz "hask"
+'
+
+test_expect_success 'find integer value for a key' '
+ check_config get_int lamb.chop 65
+'
+
+test_expect_success 'find string value for a key' '
+ check_config get_string case.baz hask &&
+ check_config expect_code 1 get_string case.ba "Value not found for \"case.ba\""
+'
+
+test_expect_success 'check line error when NULL string is queried' '
+ test_expect_code 128 test-config get_string case.foo 2>result &&
+ test_i18ngrep "fatal: .*case\.foo.*\.git/config.*line 7" result
+'
+
+test_expect_success 'find integer if value is non parse-able' '
+ check_config expect_code 128 get_int lamb.head
+'
+
+test_expect_success 'find bool value for the entered key' '
+ check_config get_bool goat.head 1 &&
+ check_config get_bool goat.skin 0 &&
+ check_config get_bool goat.nose 1 &&
+ check_config get_bool goat.horns 1 &&
+ check_config get_bool goat.legs 1
+'
+
+test_expect_success 'find multiple values' '
+ check_config get_value_multi case.baz sam bat hask
+'
+
+test_expect_success 'find value from a configset' '
+ cat >config2 <<-\EOF &&
+ [case]
+ baz = lama
+ [my]
+ new = silk
+ [case]
+ baz = ball
+ EOF
+ echo silk >expect &&
+ test-config configset_get_value my.new config2 .git/config >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'find value with highest priority from a configset' '
+ echo hask >expect &&
+ test-config configset_get_value case.baz config2 .git/config >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'find value_list for a key from a configset' '
+ cat >except <<-\EOF &&
+ sam
+ bat
+ hask
+ lama
+ ball
+ EOF
+ test-config configset_get_value case.baz config2 .git/config >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'proper error on non-existent files' '
+ echo "Error (-1) reading configuration file non-existent-file." >expect &&
+ test_expect_code 2 test-config configset_get_value foo.bar non-existent-file 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success POSIXPERM,SANITY 'proper error on non-accessible files' '
+ chmod -r .git/config &&
+ test_when_finished "chmod +r .git/config" &&
+ echo "Error (-1) reading configuration file .git/config." >expect &&
+ test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'proper error on error in default config files' '
+ cp .git/config .git/config.old &&
+ test_when_finished "mv .git/config.old .git/config" &&
+ echo "[" >>.git/config &&
+ echo "fatal: bad config file line 34 in .git/config" >expect &&
+ test_expect_code 128 test-config get_value foo.bar 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'proper error on error in custom config files' '
+ echo "[" >>syntax-error &&
+ echo "fatal: bad config file line 1 in syntax-error" >expect &&
+ test_expect_code 128 test-config configset_get_value foo.bar syntax-error 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check line errors for malformed values' '
+ mv .git/config .git/config.old &&
+ test_when_finished "mv .git/config.old .git/config" &&
+ cat >.git/config <<-\EOF &&
+ [alias]
+ br
+ EOF
+ test_expect_code 128 git br 2>result &&
+ test_i18ngrep "fatal: .*alias\.br.*\.git/config.*line 2" result
+'
+
+test_done
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 6ffd82fe32..7b4707b776 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -110,6 +110,32 @@ test_expect_success "delete symref without dereference when the referred ref is
cp -f .git/HEAD.orig .git/HEAD
git update-ref -d $m
+test_expect_success 'update-ref -d is not confused by self-reference' '
+ git symbolic-ref refs/heads/self refs/heads/self &&
+ test_when_finished "rm -f .git/refs/heads/self" &&
+ test_path_is_file .git/refs/heads/self &&
+ test_must_fail git update-ref -d refs/heads/self &&
+ test_path_is_file .git/refs/heads/self
+'
+
+test_expect_success 'update-ref --no-deref -d can delete self-reference' '
+ git symbolic-ref refs/heads/self refs/heads/self &&
+ test_when_finished "rm -f .git/refs/heads/self" &&
+ test_path_is_file .git/refs/heads/self &&
+ git update-ref --no-deref -d refs/heads/self &&
+ test_path_is_missing .git/refs/heads/self
+'
+
+test_expect_success 'update-ref --no-deref -d can delete reference to bad ref' '
+ >.git/refs/heads/bad &&
+ test_when_finished "rm -f .git/refs/heads/bad" &&
+ git symbolic-ref refs/heads/ref-to-bad refs/heads/bad &&
+ test_when_finished "rm -f .git/refs/heads/ref-to-bad" &&
+ test_path_is_file .git/refs/heads/ref-to-bad &&
+ git update-ref --no-deref -d refs/heads/ref-to-bad &&
+ test_path_is_missing .git/refs/heads/ref-to-bad
+'
+
test_expect_success '(not) create HEAD with old sha1' "
test_must_fail git update-ref HEAD $A $B
"
@@ -235,7 +261,7 @@ test_expect_success \
'rm -f o e &&
git rev-parse --verify "master@{2005-05-26 23:33:01}" >o 2>e &&
test '"$B"' = $(cat o) &&
- test "warning: Log .git/logs/'"$m has gap after $gd"'." = "$(cat e)"'
+ test "warning: Log for ref '"$m has gap after $gd"'." = "$(cat e)"'
test_expect_success \
'Query "master@{2005-05-26 23:38:00}" (middle of history)' \
'rm -f o e &&
@@ -253,7 +279,7 @@ test_expect_success \
'rm -f o e &&
git rev-parse --verify "master@{2005-05-28}" >o 2>e &&
test '"$D"' = $(cat o) &&
- test "warning: Log .git/logs/'"$m unexpectedly ended on $ld"'." = "$(cat e)"'
+ test "warning: Log for ref '"$m unexpectedly ended on $ld"'." = "$(cat e)"'
rm -f .git/$m .git/logs/$m expect
@@ -350,88 +376,76 @@ test_expect_success 'stdin fails on unknown command' '
grep "fatal: unknown command: unknown $a" err
'
-test_expect_success 'stdin fails on badly quoted input' '
+test_expect_success 'stdin fails on unbalanced quotes' '
echo "create $a \"master" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
grep "fatal: badly quoted argument: \\\"master" err
'
-test_expect_success 'stdin fails on arguments not separated by space' '
- echo "create \"$a\"master" >stdin &&
+test_expect_success 'stdin fails on invalid escape' '
+ echo "create $a \"ma\zter\"" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: expected SP but got: master" err
+ grep "fatal: badly quoted argument: \\\"ma\\\\zter\\\"" err
'
-test_expect_success 'stdin fails create with no ref' '
- echo "create " >stdin &&
+test_expect_success 'stdin fails on junk after quoted argument' '
+ echo "create \"$a\"master" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: create line missing <ref>" err
+ grep "fatal: unexpected character after quoted argument: \\\"$a\\\"master" err
'
-test_expect_success 'stdin fails create with bad ref name' '
- echo "create ~a $m" >stdin &&
+test_expect_success 'stdin fails create with no ref' '
+ echo "create " >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: invalid ref format: ~a" err
+ grep "fatal: create: missing <ref>" err
'
test_expect_success 'stdin fails create with no new value' '
echo "create $a" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: create $a missing <newvalue>" err
+ grep "fatal: create $a: missing <newvalue>" err
'
test_expect_success 'stdin fails create with too many arguments' '
echo "create $a $m $m" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: create $a has extra input: $m" err
+ grep "fatal: create $a: extra input: $m" err
'
test_expect_success 'stdin fails update with no ref' '
echo "update " >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: update line missing <ref>" err
-'
-
-test_expect_success 'stdin fails update with bad ref name' '
- echo "update ~a $m" >stdin &&
- test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: invalid ref format: ~a" err
+ grep "fatal: update: missing <ref>" err
'
test_expect_success 'stdin fails update with no new value' '
echo "update $a" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: update $a missing <newvalue>" err
+ grep "fatal: update $a: missing <newvalue>" err
'
test_expect_success 'stdin fails update with too many arguments' '
echo "update $a $m $m $m" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: update $a has extra input: $m" err
+ grep "fatal: update $a: extra input: $m" err
'
test_expect_success 'stdin fails delete with no ref' '
echo "delete " >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: delete line missing <ref>" err
-'
-
-test_expect_success 'stdin fails delete with bad ref name' '
- echo "delete ~a $m" >stdin &&
- test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: invalid ref format: ~a" err
+ grep "fatal: delete: missing <ref>" err
'
test_expect_success 'stdin fails delete with too many arguments' '
echo "delete $a $m $m" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: delete $a has extra input: $m" err
+ grep "fatal: delete $a: extra input: $m" err
'
test_expect_success 'stdin fails verify with too many arguments' '
echo "verify $a $m $m" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: verify $a has extra input: $m" err
+ grep "fatal: verify $a: extra input: $m" err
'
test_expect_success 'stdin fails option with unknown name' '
@@ -458,6 +472,24 @@ test_expect_success 'stdin create ref works' '
test_cmp expect actual
'
+test_expect_success 'stdin succeeds with quoted argument' '
+ git update-ref -d $a &&
+ echo "create $a \"$m\"" >stdin &&
+ git update-ref --stdin <stdin &&
+ git rev-parse $m >expect &&
+ git rev-parse $a >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stdin succeeds with escaped character' '
+ git update-ref -d $a &&
+ echo "create $a \"ma\\163ter\"" >stdin &&
+ git update-ref --stdin <stdin &&
+ git rev-parse $m >expect &&
+ git rev-parse $a >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'stdin update ref creates with zero old value' '
echo "update $b $m $Z" >stdin &&
git update-ref --stdin <stdin &&
@@ -494,21 +526,21 @@ test_expect_success 'stdin update ref fails with wrong old value' '
test_expect_success 'stdin update ref fails with bad old value' '
echo "update $c $m does-not-exist" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: invalid old value for ref $c: does-not-exist" err &&
+ grep "fatal: update $c: invalid <oldvalue>: does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
'
test_expect_success 'stdin create ref fails with bad new value' '
echo "create $c does-not-exist" >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: invalid new value for ref $c: does-not-exist" err &&
+ grep "fatal: create $c: invalid <newvalue>: does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
'
test_expect_success 'stdin create ref fails with zero new value' '
echo "create $c " >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: create $c given zero new value" err &&
+ grep "fatal: create $c: zero <newvalue>" err &&
test_must_fail git rev-parse --verify -q $c
'
@@ -532,7 +564,7 @@ test_expect_success 'stdin delete ref fails with wrong old value' '
test_expect_success 'stdin delete ref fails with zero old value' '
echo "delete $a " >stdin &&
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: delete $a given zero old value" err &&
+ grep "fatal: delete $a: zero <oldvalue>" err &&
git rev-parse $m >expect &&
git rev-parse $a >actual &&
test_cmp expect actual
@@ -673,19 +705,13 @@ test_expect_success 'stdin -z fails on unknown command' '
test_expect_success 'stdin -z fails create with no ref' '
printf $F "create " >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: create line missing <ref>" err
-'
-
-test_expect_success 'stdin -z fails create with bad ref name' '
- printf $F "create ~a " "$m" >stdin &&
- test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: invalid ref format: ~a " err
+ grep "fatal: create: missing <ref>" err
'
test_expect_success 'stdin -z fails create with no new value' '
printf $F "create $a" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: create $a missing <newvalue>" err
+ grep "fatal: create $a: unexpected end of input when reading <newvalue>" err
'
test_expect_success 'stdin -z fails create with too many arguments' '
@@ -697,25 +723,33 @@ test_expect_success 'stdin -z fails create with too many arguments' '
test_expect_success 'stdin -z fails update with no ref' '
printf $F "update " >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: update line missing <ref>" err
+ grep "fatal: update: missing <ref>" err
'
-test_expect_success 'stdin -z fails update with bad ref name' '
- printf $F "update ~a" "$m" >stdin &&
+test_expect_success 'stdin -z fails update with too few args' '
+ printf $F "update $a" "$m" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: invalid ref format: ~a" err
+ grep "fatal: update $a: unexpected end of input when reading <oldvalue>" err
+'
+
+test_expect_success 'stdin -z emits warning with empty new value' '
+ git update-ref $a $m &&
+ printf $F "update $a" "" "" >stdin &&
+ git update-ref -z --stdin <stdin 2>err &&
+ grep "warning: update $a: missing <newvalue>, treating as zero" err &&
+ test_must_fail git rev-parse --verify -q $a
'
test_expect_success 'stdin -z fails update with no new value' '
printf $F "update $a" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: update $a missing <newvalue>" err
+ grep "fatal: update $a: unexpected end of input when reading <newvalue>" err
'
test_expect_success 'stdin -z fails update with no old value' '
printf $F "update $a" "$m" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: update $a missing \\[<oldvalue>\\] NUL" err
+ grep "fatal: update $a: unexpected end of input when reading <oldvalue>" err
'
test_expect_success 'stdin -z fails update with too many arguments' '
@@ -727,19 +761,13 @@ test_expect_success 'stdin -z fails update with too many arguments' '
test_expect_success 'stdin -z fails delete with no ref' '
printf $F "delete " >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: delete line missing <ref>" err
-'
-
-test_expect_success 'stdin -z fails delete with bad ref name' '
- printf $F "delete ~a" "$m" >stdin &&
- test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: invalid ref format: ~a" err
+ grep "fatal: delete: missing <ref>" err
'
test_expect_success 'stdin -z fails delete with no old value' '
printf $F "delete $a" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: delete $a missing \\[<oldvalue>\\] NUL" err
+ grep "fatal: delete $a: unexpected end of input when reading <oldvalue>" err
'
test_expect_success 'stdin -z fails delete with too many arguments' '
@@ -757,7 +785,7 @@ test_expect_success 'stdin -z fails verify with too many arguments' '
test_expect_success 'stdin -z fails verify with no old value' '
printf $F "verify $a" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: verify $a missing \\[<oldvalue>\\] NUL" err
+ grep "fatal: verify $a: unexpected end of input when reading <oldvalue>" err
'
test_expect_success 'stdin -z fails option with unknown name' '
@@ -816,21 +844,32 @@ test_expect_success 'stdin -z update ref fails with wrong old value' '
test_expect_success 'stdin -z update ref fails with bad old value' '
printf $F "update $c" "$m" "does-not-exist" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: invalid old value for ref $c: does-not-exist" err &&
+ grep "fatal: update $c: invalid <oldvalue>: does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
'
+test_expect_success 'stdin -z create ref fails when ref exists' '
+ git update-ref $c $m &&
+ git rev-parse "$c" >expect &&
+ printf $F "create $c" "$m~1" >stdin &&
+ test_must_fail git update-ref -z --stdin <stdin 2>err &&
+ grep "fatal: Cannot lock the ref '"'"'$c'"'"'" err &&
+ git rev-parse "$c" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'stdin -z create ref fails with bad new value' '
+ git update-ref -d "$c" &&
printf $F "create $c" "does-not-exist" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: invalid new value for ref $c: does-not-exist" err &&
+ grep "fatal: create $c: invalid <newvalue>: does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
'
-test_expect_success 'stdin -z create ref fails with zero new value' '
+test_expect_success 'stdin -z create ref fails with empty new value' '
printf $F "create $c" "" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: create $c given zero new value" err &&
+ grep "fatal: create $c: missing <newvalue>" err &&
test_must_fail git rev-parse --verify -q $c
'
@@ -854,7 +893,7 @@ test_expect_success 'stdin -z delete ref fails with wrong old value' '
test_expect_success 'stdin -z delete ref fails with zero old value' '
printf $F "delete $a" "$Z" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: delete $a given zero old value" err &&
+ grep "fatal: delete $a: zero <oldvalue>" err &&
git rev-parse $m >expect &&
git rev-parse $a >actual &&
test_cmp expect actual
@@ -912,7 +951,7 @@ test_expect_success 'stdin -z update refs works with identity updates' '
test_expect_success 'stdin -z update refs fails with wrong old value' '
git update-ref $c $m &&
- printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "" "$Z" >stdin &&
+ printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "$m" "$Z" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
grep "fatal: Cannot lock the ref '"'"'$c'"'"'" err &&
git rev-parse $m >expect &&
diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh
index 1a5a5f39fd..e5dc62e9ef 100755
--- a/t/t1402-check-ref-format.sh
+++ b/t/t1402-check-ref-format.sh
@@ -7,7 +7,7 @@ test_description='Test git check-ref-format'
valid_ref() {
prereq=
case $1 in
- [A-Z]*)
+ [A-Z!]*)
prereq=$1
shift
esac
@@ -19,7 +19,7 @@ valid_ref() {
invalid_ref() {
prereq=
case $1 in
- [A-Z]*)
+ [A-Z!]*)
prereq=$1
shift
esac
@@ -30,17 +30,17 @@ invalid_ref() {
}
invalid_ref ''
-invalid_ref NOT_MINGW '/'
-invalid_ref NOT_MINGW '/' --allow-onelevel
-invalid_ref NOT_MINGW '/' --normalize
-invalid_ref NOT_MINGW '/' '--allow-onelevel --normalize'
+invalid_ref !MINGW '/'
+invalid_ref !MINGW '/' --allow-onelevel
+invalid_ref !MINGW '/' --normalize
+invalid_ref !MINGW '/' '--allow-onelevel --normalize'
valid_ref 'foo/bar/baz'
valid_ref 'foo/bar/baz' --normalize
invalid_ref 'refs///heads/foo'
valid_ref 'refs///heads/foo' --normalize
invalid_ref 'heads/foo/'
-invalid_ref NOT_MINGW '/heads/foo'
-valid_ref NOT_MINGW '/heads/foo' --normalize
+invalid_ref !MINGW '/heads/foo'
+valid_ref !MINGW '/heads/foo' --normalize
invalid_ref '///heads/foo'
valid_ref '///heads/foo' --normalize
invalid_ref './foo'
@@ -48,6 +48,7 @@ invalid_ref './foo/bar'
invalid_ref 'foo/./bar'
invalid_ref 'foo/bar/.'
invalid_ref '.refs/foo'
+invalid_ref 'refs/heads/foo.'
invalid_ref 'heads/foo..bar'
invalid_ref 'heads/foo?bar'
valid_ref 'foo./bar'
@@ -119,14 +120,14 @@ invalid_ref "$ref" --refspec-pattern
invalid_ref "$ref" '--refspec-pattern --allow-onelevel'
ref='/foo'
-invalid_ref NOT_MINGW "$ref"
-invalid_ref NOT_MINGW "$ref" --allow-onelevel
-invalid_ref NOT_MINGW "$ref" --refspec-pattern
-invalid_ref NOT_MINGW "$ref" '--refspec-pattern --allow-onelevel'
-invalid_ref NOT_MINGW "$ref" --normalize
-valid_ref NOT_MINGW "$ref" '--allow-onelevel --normalize'
-invalid_ref NOT_MINGW "$ref" '--refspec-pattern --normalize'
-valid_ref NOT_MINGW "$ref" '--refspec-pattern --allow-onelevel --normalize'
+invalid_ref !MINGW "$ref"
+invalid_ref !MINGW "$ref" --allow-onelevel
+invalid_ref !MINGW "$ref" --refspec-pattern
+invalid_ref !MINGW "$ref" '--refspec-pattern --allow-onelevel'
+invalid_ref !MINGW "$ref" --normalize
+valid_ref !MINGW "$ref" '--allow-onelevel --normalize'
+invalid_ref !MINGW "$ref" '--refspec-pattern --normalize'
+valid_ref !MINGW "$ref" '--refspec-pattern --allow-onelevel --normalize'
test_expect_success "check-ref-format --branch @{-1}" '
T=$(git write-tree) &&
@@ -161,7 +162,7 @@ test_expect_success 'check-ref-format --branch from subdir' '
valid_ref_normalized() {
prereq=
case $1 in
- [A-Z]*)
+ [A-Z!]*)
prereq=$1
shift
esac
@@ -173,7 +174,7 @@ valid_ref_normalized() {
invalid_ref_normalized() {
prereq=
case $1 in
- [A-Z]*)
+ [A-Z!]*)
prereq=$1
shift
esac
@@ -184,10 +185,10 @@ invalid_ref_normalized() {
valid_ref_normalized 'heads/foo' 'heads/foo'
valid_ref_normalized 'refs///heads/foo' 'refs/heads/foo'
-valid_ref_normalized NOT_MINGW '/heads/foo' 'heads/foo'
+valid_ref_normalized !MINGW '/heads/foo' 'heads/foo'
valid_ref_normalized '///heads/foo' 'heads/foo'
invalid_ref_normalized 'foo'
-invalid_ref_normalized NOT_MINGW '/foo'
+invalid_ref_normalized !MINGW '/foo'
invalid_ref_normalized 'heads/foo/../bar'
invalid_ref_normalized 'heads/./foo'
invalid_ref_normalized 'heads\foo'
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 236b13a3ab..8cf446165e 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -245,4 +245,46 @@ test_expect_success 'gc.reflogexpire=false' '
'
+test_expect_success 'checkout should not delete log for packed ref' '
+ test $(git reflog master | wc -l) = 4 &&
+ git branch foo &&
+ git pack-refs --all &&
+ git checkout foo &&
+ test $(git reflog master | wc -l) = 4
+'
+
+test_expect_success 'stale dirs do not cause d/f conflicts (reflogs on)' '
+ test_when_finished "git branch -d one || git branch -d one/two" &&
+
+ git branch one/two master &&
+ echo "one/two@{0} branch: Created from master" >expect &&
+ git log -g --format="%gd %gs" one/two >actual &&
+ test_cmp expect actual &&
+ git branch -d one/two &&
+
+ # now logs/refs/heads/one is a stale directory, but
+ # we should move it out of the way to create "one" reflog
+ git branch one master &&
+ echo "one@{0} branch: Created from master" >expect &&
+ git log -g --format="%gd %gs" one >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stale dirs do not cause d/f conflicts (reflogs off)' '
+ test_when_finished "git branch -d one || git branch -d one/two" &&
+
+ git branch one/two master &&
+ echo "one/two@{0} branch: Created from master" >expect &&
+ git log -g --format="%gd %gs" one/two >actual &&
+ test_cmp expect actual &&
+ git branch -d one/two &&
+
+ # same as before, but we only create a reflog for "one" if
+ # it already exists, which it does not
+ git -c core.logallrefupdates=false branch one master &&
+ : >expect &&
+ git log -g --format="%gd %gs" one >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1413-reflog-detach.sh b/t/t1413-reflog-detach.sh
new file mode 100755
index 0000000000..c730600d8a
--- /dev/null
+++ b/t/t1413-reflog-detach.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+test_description='Test reflog interaction with detached HEAD'
+. ./test-lib.sh
+
+reset_state () {
+ git checkout master &&
+ cp saved_reflog .git/logs/HEAD
+}
+
+test_expect_success setup '
+ test_tick &&
+ git commit --allow-empty -m initial &&
+ git branch side &&
+ test_tick &&
+ git commit --allow-empty -m second &&
+ cat .git/logs/HEAD >saved_reflog
+'
+
+test_expect_success baseline '
+ reset_state &&
+ git rev-parse master master^ >expect &&
+ git log -g --format=%H >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'switch to branch' '
+ reset_state &&
+ git rev-parse side master master^ >expect &&
+ git checkout side &&
+ git log -g --format=%H >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'detach to other' '
+ reset_state &&
+ git rev-parse master side master master^ >expect &&
+ git checkout side &&
+ git checkout master^0 &&
+ git log -g --format=%H >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'detach to self' '
+ reset_state &&
+ git rev-parse master master master^ >expect &&
+ git checkout master^0 &&
+ git log -g --format=%H >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'attach to self' '
+ reset_state &&
+ git rev-parse master master master master^ >expect &&
+ git checkout master^0 &&
+ git checkout master &&
+ git log -g --format=%H >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'attach to other' '
+ reset_state &&
+ git rev-parse side master master master^ >expect &&
+ git checkout master^0 &&
+ git checkout side &&
+ git log -g --format=%H >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh
new file mode 100755
index 0000000000..468e85621a
--- /dev/null
+++ b/t/t1430-bad-ref-name.sh
@@ -0,0 +1,207 @@
+#!/bin/sh
+
+test_description='Test handling of ref names that check-ref-format rejects'
+. ./test-lib.sh
+
+test_expect_success setup '
+ test_commit one &&
+ test_commit two
+'
+
+test_expect_success 'fast-import: fail on invalid branch name ".badbranchname"' '
+ test_when_finished "rm -f .git/objects/pack_* .git/objects/index_*" &&
+ cat >input <<-INPUT_END &&
+ commit .badbranchname
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ corrupt
+ COMMIT
+
+ from refs/heads/master
+
+ INPUT_END
+ test_must_fail git fast-import <input
+'
+
+test_expect_success 'fast-import: fail on invalid branch name "bad[branch]name"' '
+ test_when_finished "rm -f .git/objects/pack_* .git/objects/index_*" &&
+ cat >input <<-INPUT_END &&
+ commit bad[branch]name
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ corrupt
+ COMMIT
+
+ from refs/heads/master
+
+ INPUT_END
+ test_must_fail git fast-import <input
+'
+
+test_expect_success 'git branch shows badly named ref' '
+ cp .git/refs/heads/master .git/refs/heads/broken...ref &&
+ test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+ git branch >output &&
+ grep -e "broken\.\.\.ref" output
+'
+
+test_expect_success 'branch -d can delete badly named ref' '
+ cp .git/refs/heads/master .git/refs/heads/broken...ref &&
+ test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+ git branch -d broken...ref &&
+ git branch >output &&
+ ! grep -e "broken\.\.\.ref" output
+'
+
+test_expect_success 'branch -D can delete badly named ref' '
+ cp .git/refs/heads/master .git/refs/heads/broken...ref &&
+ test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+ git branch -D broken...ref &&
+ git branch >output &&
+ ! grep -e "broken\.\.\.ref" output
+'
+
+test_expect_success 'branch -D cannot delete non-ref in .git dir' '
+ echo precious >.git/my-private-file &&
+ echo precious >expect &&
+ test_must_fail git branch -D ../../my-private-file &&
+ test_cmp expect .git/my-private-file
+'
+
+test_expect_success 'branch -D cannot delete absolute path' '
+ git branch -f extra &&
+ test_must_fail git branch -D "$(pwd)/.git/refs/heads/extra" &&
+ test_cmp_rev HEAD extra
+'
+
+test_expect_success 'git branch cannot create a badly named ref' '
+ test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+ test_must_fail git branch broken...ref &&
+ git branch >output &&
+ ! grep -e "broken\.\.\.ref" output
+'
+
+test_expect_success 'branch -m cannot rename to a bad ref name' '
+ test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+ test_might_fail git branch -D goodref &&
+ git branch goodref &&
+ test_must_fail git branch -m goodref broken...ref &&
+ test_cmp_rev master goodref &&
+ git branch >output &&
+ ! grep -e "broken\.\.\.ref" output
+'
+
+test_expect_failure 'branch -m can rename from a bad ref name' '
+ cp .git/refs/heads/master .git/refs/heads/broken...ref &&
+ test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+ git branch -m broken...ref renamed &&
+ test_cmp_rev master renamed &&
+ git branch >output &&
+ ! grep -e "broken\.\.\.ref" output
+'
+
+test_expect_success 'push cannot create a badly named ref' '
+ test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+ test_must_fail git push "file://$(pwd)" HEAD:refs/heads/broken...ref &&
+ git branch >output &&
+ ! grep -e "broken\.\.\.ref" output
+'
+
+test_expect_failure 'push --mirror can delete badly named ref' '
+ top=$(pwd) &&
+ git init src &&
+ git init dest &&
+
+ (
+ cd src &&
+ test_commit one
+ ) &&
+ (
+ cd dest &&
+ test_commit two &&
+ git checkout --detach &&
+ cp .git/refs/heads/master .git/refs/heads/broken...ref
+ ) &&
+ git -C src push --mirror "file://$top/dest" &&
+ git -C dest branch >output &&
+ ! grep -e "broken\.\.\.ref" output
+'
+
+test_expect_success 'rev-parse skips symref pointing to broken name' '
+ test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+ git branch shadow one &&
+ cp .git/refs/heads/master .git/refs/heads/broken...ref &&
+ git symbolic-ref refs/tags/shadow refs/heads/broken...ref &&
+
+ git rev-parse --verify one >expect &&
+ git rev-parse --verify shadow >actual 2>err &&
+ test_cmp expect actual &&
+ test_i18ngrep "ignoring.*refs/tags/shadow" err
+'
+
+test_expect_success 'update-ref --no-deref -d can delete reference to broken name' '
+ git symbolic-ref refs/heads/badname refs/heads/broken...ref &&
+ test_when_finished "rm -f .git/refs/heads/badname" &&
+ test_path_is_file .git/refs/heads/badname &&
+ git update-ref --no-deref -d refs/heads/badname &&
+ test_path_is_missing .git/refs/heads/badname
+'
+
+test_expect_success 'update-ref -d can delete broken name' '
+ cp .git/refs/heads/master .git/refs/heads/broken...ref &&
+ test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+ git update-ref -d refs/heads/broken...ref &&
+ git branch >output &&
+ ! grep -e "broken\.\.\.ref" output
+'
+
+test_expect_success 'update-ref -d cannot delete non-ref in .git dir' '
+ echo precious >.git/my-private-file &&
+ echo precious >expect &&
+ test_must_fail git update-ref -d my-private-file &&
+ test_cmp expect .git/my-private-file
+'
+
+test_expect_success 'update-ref -d cannot delete absolute path' '
+ git branch -f extra &&
+ test_must_fail git update-ref -d "$(pwd)/.git/refs/heads/extra" &&
+ test_cmp_rev HEAD extra
+'
+
+test_expect_success 'update-ref --stdin fails create with bad ref name' '
+ echo "create ~a refs/heads/master" >stdin &&
+ test_must_fail git update-ref --stdin <stdin 2>err &&
+ grep "fatal: invalid ref format: ~a" err
+'
+
+test_expect_success 'update-ref --stdin fails update with bad ref name' '
+ echo "update ~a refs/heads/master" >stdin &&
+ test_must_fail git update-ref --stdin <stdin 2>err &&
+ grep "fatal: invalid ref format: ~a" err
+'
+
+test_expect_success 'update-ref --stdin fails delete with bad ref name' '
+ echo "delete ~a refs/heads/master" >stdin &&
+ test_must_fail git update-ref --stdin <stdin 2>err &&
+ grep "fatal: invalid ref format: ~a" err
+'
+
+test_expect_success 'update-ref --stdin -z fails create with bad ref name' '
+ printf "%s\0" "create ~a " refs/heads/master >stdin &&
+ test_must_fail git update-ref -z --stdin <stdin 2>err &&
+ grep "fatal: invalid ref format: ~a " err
+'
+
+test_expect_success 'update-ref --stdin -z fails update with bad ref name' '
+ printf "%s\0" "update ~a" refs/heads/master "" >stdin &&
+ test_must_fail git update-ref -z --stdin <stdin 2>err &&
+ grep "fatal: invalid ref format: ~a" err
+'
+
+test_expect_success 'update-ref --stdin -z fails delete with bad ref name' '
+ printf "%s\0" "delete ~a" refs/heads/master >stdin &&
+ test_must_fail git update-ref -z --stdin <stdin 2>err &&
+ grep "fatal: invalid ref format: ~a" err
+'
+
+test_done
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index d730734fde..019fddd4e8 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -69,7 +69,7 @@ test_expect_success 'object with bad sha1' '
git update-ref refs/heads/bogus $cmt &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
- test_might_fail git fsck 2>out &&
+ test_must_fail git fsck 2>out &&
cat out &&
grep "$sha.*corrupt" out
'
@@ -101,7 +101,7 @@ test_expect_success 'email with embedded > is not okay' '
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
- git fsck 2>out &&
+ test_must_fail git fsck 2>out &&
cat out &&
grep "error in commit $new" out
'
@@ -113,7 +113,7 @@ test_expect_success 'missing < email delimiter is reported nicely' '
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
- git fsck 2>out &&
+ test_must_fail git fsck 2>out &&
cat out &&
grep "error in commit $new.* - bad name" out
'
@@ -125,7 +125,7 @@ test_expect_success 'missing email is reported nicely' '
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
- git fsck 2>out &&
+ test_must_fail git fsck 2>out &&
cat out &&
grep "error in commit $new.* - missing email" out
'
@@ -137,11 +137,45 @@ test_expect_success '> in name is reported' '
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
- git fsck 2>out &&
+ test_must_fail git fsck 2>out &&
cat out &&
grep "error in commit $new" out
'
+# date is 2^64 + 1
+test_expect_success 'integer overflow in timestamps is reported' '
+ git cat-file commit HEAD >basis &&
+ sed "s/^\\(author .*>\\) [0-9]*/\\1 18446744073709551617/" \
+ <basis >bad-timestamp &&
+ new=$(git hash-object -t commit -w --stdin <bad-timestamp) &&
+ test_when_finished "remove_object $new" &&
+ git update-ref refs/heads/bogus "$new" &&
+ test_when_finished "git update-ref -d refs/heads/bogus" &&
+ test_must_fail git fsck 2>out &&
+ cat out &&
+ grep "error in commit $new.*integer overflow" out
+'
+
+test_expect_success 'malformatted tree object' '
+ test_when_finished "git update-ref -d refs/tags/wrong" &&
+ test_when_finished "remove_object \$T" &&
+ T=$(
+ GIT_INDEX_FILE=test-index &&
+ export GIT_INDEX_FILE &&
+ rm -f test-index &&
+ >x &&
+ git add x &&
+ T=$(git write-tree) &&
+ (
+ git cat-file tree $T &&
+ git cat-file tree $T
+ ) |
+ git hash-object -w -t tree --stdin
+ ) &&
+ test_must_fail git fsck 2>out &&
+ grep "error in tree .*contains duplicate file entries" out
+'
+
test_expect_success 'tag pointing to nonexistent' '
cat >invalid-tag <<-\EOF &&
object ffffffffffffffffffffffffffffffffffffffff
@@ -180,6 +214,44 @@ test_expect_success 'tag pointing to something else than its type' '
test_must_fail git fsck --tags
'
+test_expect_success 'tag with incorrect tag name & missing tagger' '
+ sha=$(git rev-parse HEAD) &&
+ cat >wrong-tag <<-EOF &&
+ object $sha
+ type commit
+ tag wrong name format
+
+ This is an invalid tag.
+ EOF
+
+ tag=$(git hash-object -t tag -w --stdin <wrong-tag) &&
+ test_when_finished "remove_object $tag" &&
+ echo $tag >.git/refs/tags/wrong &&
+ test_when_finished "git update-ref -d refs/tags/wrong" &&
+ git fsck --tags 2>out &&
+ grep "invalid .tag. name" out &&
+ grep "expected .tagger. line" out
+'
+
+test_expect_success 'tag with bad tagger' '
+ sha=$(git rev-parse HEAD) &&
+ cat >wrong-tag <<-EOF &&
+ object $sha
+ type commit
+ tag not-quite-wrong
+ tagger Bad Tagger Name
+
+ This is an invalid tag.
+ EOF
+
+ tag=$(git hash-object --literally -t tag -w --stdin <wrong-tag) &&
+ test_when_finished "remove_object $tag" &&
+ echo $tag >.git/refs/tags/wrong &&
+ test_when_finished "git update-ref -d refs/tags/wrong" &&
+ test_must_fail git fsck --tags 2>out &&
+ grep "error in tag .*: invalid author/committer" out
+'
+
test_expect_success 'cleaned up' '
git fsck >actual 2>&1 &&
test_cmp empty actual
@@ -268,4 +340,60 @@ test_expect_success 'fsck notices ".git" in trees' '
)
'
+# create a static test repo which is broken by omitting
+# one particular object ($1, which is looked up via rev-parse
+# in the new repository).
+create_repo_missing () {
+ rm -rf missing &&
+ git init missing &&
+ (
+ cd missing &&
+ git commit -m one --allow-empty &&
+ mkdir subdir &&
+ echo content >subdir/file &&
+ git add subdir/file &&
+ git commit -m two &&
+ unrelated=$(echo unrelated | git hash-object --stdin -w) &&
+ git tag -m foo tag $unrelated &&
+ sha1=$(git rev-parse --verify "$1") &&
+ path=$(echo $sha1 | sed 's|..|&/|') &&
+ rm .git/objects/$path
+ )
+}
+
+test_expect_success 'fsck notices missing blob' '
+ create_repo_missing HEAD:subdir/file &&
+ test_must_fail git -C missing fsck
+'
+
+test_expect_success 'fsck notices missing subtree' '
+ create_repo_missing HEAD:subdir &&
+ test_must_fail git -C missing fsck
+'
+
+test_expect_success 'fsck notices missing root tree' '
+ create_repo_missing HEAD^{tree} &&
+ test_must_fail git -C missing fsck
+'
+
+test_expect_success 'fsck notices missing parent' '
+ create_repo_missing HEAD^ &&
+ test_must_fail git -C missing fsck
+'
+
+test_expect_success 'fsck notices missing tagged object' '
+ create_repo_missing tag^{blob} &&
+ test_must_fail git -C missing fsck
+'
+
+test_expect_success 'fsck notices ref pointing to missing commit' '
+ create_repo_missing HEAD &&
+ test_must_fail git -C missing fsck
+'
+
+test_expect_success 'fsck notices ref pointing to missing tag' '
+ create_repo_missing tag &&
+ test_must_fail git -C missing fsck
+'
+
test_done
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index 13c88c9aae..ebe7c3b87c 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -3,40 +3,64 @@
test_description='test git rev-parse --parseopt'
. ./test-lib.sh
-cat > expect <<\END_EXPECT
-cat <<\EOF
-usage: some-command [options] <args>...
-
- some-command does foo and bar!
-
- -h, --help show the help
- --foo some nifty option --foo
- --bar ... some cool option --bar with an argument
-
-An option group Header
- -C[...] option C with an optional argument
-
-Extras
- --extra1 line above used to cause a segfault but no longer does
-
-EOF
+sed -e 's/^|//' >expect <<\END_EXPECT
+|cat <<\EOF
+|usage: some-command [options] <args>...
+|
+| some-command does foo and bar!
+|
+| -h, --help show the help
+| --foo some nifty option --foo
+| --bar ... some cool option --bar with an argument
+| -b, --baz a short and long option
+|
+|An option group Header
+| -C[...] option C with an optional argument
+| -d, --data[=...] short and long option with an optional argument
+|
+|Argument hints
+| -B <arg> short option required argument
+| --bar2 <arg> long option required argument
+| -e, --fuz <with-space>
+| short and long option required argument
+| -s[<some>] short option optional argument
+| --long[=<data>] long option optional argument
+| -g, --fluf[=<path>] short and long option optional argument
+| --longest <very-long-argument-hint>
+| a very long argument hint
+|
+|Extras
+| --extra1 line above used to cause a segfault but no longer does
+|
+|EOF
END_EXPECT
-cat > optionspec << EOF
-some-command [options] <args>...
-
-some-command does foo and bar!
---
-h,help show the help
-
-foo some nifty option --foo
-bar= some cool option --bar with an argument
-
- An option group Header
-C? option C with an optional argument
-
-Extras
-extra1 line above used to cause a segfault but no longer does
+sed -e 's/^|//' >optionspec <<\EOF
+|some-command [options] <args>...
+|
+|some-command does foo and bar!
+|--
+|h,help show the help
+|
+|foo some nifty option --foo
+|bar= some cool option --bar with an argument
+|b,baz a short and long option
+|
+| An option group Header
+|C? option C with an optional argument
+|d,data? short and long option with an optional argument
+|
+| Argument hints
+|B=arg short option required argument
+|bar2=arg long option required argument
+|e,fuz=with-space short and long option required argument
+|s?some short option optional argument
+|long?data long option optional argument
+|g,fluf?path short and long option optional argument
+|longest=very-long-argument-hint a very long argument hint
+|
+|Extras
+|extra1 line above used to cause a segfault but no longer does
EOF
test_expect_success 'test --parseopt help output' '
@@ -45,16 +69,16 @@ test_expect_success 'test --parseopt help output' '
'
cat > expect <<EOF
-set -- --foo --bar 'ham' -- 'arg'
+set -- --foo --bar 'ham' -b -- 'arg'
EOF
test_expect_success 'test --parseopt' '
- git rev-parse --parseopt -- --foo --bar=ham arg < optionspec > output &&
+ git rev-parse --parseopt -- --foo --bar=ham --baz arg < optionspec > output &&
test_cmp expect output
'
test_expect_success 'test --parseopt with mixed options and arguments' '
- git rev-parse --parseopt -- --foo arg --bar=ham < optionspec > output &&
+ git rev-parse --parseopt -- --foo arg --bar=ham --baz < optionspec > output &&
test_cmp expect output
'
@@ -99,4 +123,36 @@ test_expect_success 'test --parseopt --keep-dashdash --stop-at-non-option withou
test_cmp expect output
'
+cat > expect <<EOF
+set -- --foo --bar='z' --baz -C'Z' --data='A' -- 'arg'
+EOF
+
+test_expect_success 'test --parseopt --stuck-long' '
+ git rev-parse --parseopt --stuck-long -- --foo --bar=z -b arg -CZ -dA <optionspec >output &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+set -- --data='' -C --baz -- 'arg'
+EOF
+
+test_expect_success 'test --parseopt --stuck-long and empty optional argument' '
+ git rev-parse --parseopt --stuck-long -- --data= arg -C -b <optionspec >output &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+set -- --data --baz -- 'arg'
+EOF
+
+test_expect_success 'test --parseopt --stuck-long and long option with unset optional argument' '
+ git rev-parse --parseopt --stuck-long -- --data arg -b <optionspec >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'test --parseopt --stuck-long and short option with unset optional argument' '
+ git rev-parse --parseopt --stuck-long -- -d arg -b <optionspec >output &&
+ test_cmp expect output
+'
+
test_done
diff --git a/t/t1503-rev-parse-verify.sh b/t/t1503-rev-parse-verify.sh
index 813cc1b3e2..823fe1d799 100755
--- a/t/t1503-rev-parse-verify.sh
+++ b/t/t1503-rev-parse-verify.sh
@@ -72,15 +72,42 @@ test_expect_success 'fails with any bad rev or many good revs' '
test_expect_success 'fails silently when using -q' '
test_must_fail git rev-parse --verify --quiet 2>error &&
- test -z "$(cat error)" &&
+ test_must_be_empty error &&
test_must_fail git rev-parse -q --verify foo 2>error &&
- test -z "$(cat error)" &&
+ test_must_be_empty error &&
test_must_fail git rev-parse --verify -q HEAD bar 2>error &&
- test -z "$(cat error)" &&
+ test_must_be_empty error &&
test_must_fail git rev-parse --quiet --verify baz HEAD 2>error &&
- test -z "$(cat error)" &&
+ test_must_be_empty error &&
test_must_fail git rev-parse -q --verify $HASH2 HEAD 2>error &&
- test -z "$(cat error)"
+ test_must_be_empty error
+'
+
+test_expect_success 'fails silently when using -q with deleted reflogs' '
+ ref=$(git rev-parse HEAD) &&
+ : >.git/logs/refs/test &&
+ git update-ref -m "message for refs/test" refs/test "$ref" &&
+ git reflog delete --updateref --rewrite refs/test@{0} &&
+ test_must_fail git rev-parse -q --verify refs/test@{0} >error 2>&1 &&
+ test_must_be_empty error
+'
+
+test_expect_success 'fails silently when using -q with not enough reflogs' '
+ ref=$(git rev-parse HEAD) &&
+ : >.git/logs/refs/test2 &&
+ git update-ref -m "message for refs/test2" refs/test2 "$ref" &&
+ test_must_fail git rev-parse -q --verify refs/test2@{999} >error 2>&1 &&
+ test_must_be_empty error
+'
+
+test_expect_success 'succeeds silently with -q and reflogs that do not go far back enough in time' '
+ ref=$(git rev-parse HEAD) &&
+ : >.git/logs/refs/test3 &&
+ git update-ref -m "message for refs/test3" refs/test3 "$ref" &&
+ git rev-parse -q --verify refs/test3@{1.year.ago} >actual 2>error &&
+ test_must_be_empty error &&
+ echo "$ref" >expect &&
+ test_cmp expect actual
'
test_expect_success 'no stdout output on error' '
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index 178694ee63..1978947c41 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -121,7 +121,7 @@ test_expect_success 'merge my-side@{u} records the correct name' '
git branch -D new ;# can fail but is ok
git branch -t new my-side@{u} &&
git merge -s ours new@{u} &&
- git show -s --pretty=format:%s >actual &&
+ git show -s --pretty=tformat:%s >actual &&
echo "Merge remote-tracking branch ${sq}origin/side${sq}" >expect &&
test_cmp expect actual
)
diff --git a/t/t1510-repo-setup.sh b/t/t1510-repo-setup.sh
index cf2ee7885a..e1b2a99f10 100755
--- a/t/t1510-repo-setup.sh
+++ b/t/t1510-repo-setup.sh
@@ -777,9 +777,7 @@ test_expect_success '#30: core.worktree and core.bare conflict (gitfile version)
setup_repo 30 "$here/30" gitfile true &&
(
cd 30 &&
- GIT_DIR=.git &&
- export GIT_DIR &&
- test_must_fail git symbolic-ref HEAD 2>result
+ test_must_fail env GIT_DIR=.git git symbolic-ref HEAD 2>result
) &&
grep "core.bare and core.worktree" 30/result
'
diff --git a/t/t1600-index.sh b/t/t1600-index.sh
new file mode 100755
index 0000000000..079d241145
--- /dev/null
+++ b/t/t1600-index.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+test_description='index file specific tests'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo 1 >a
+'
+
+test_expect_success 'bogus GIT_INDEX_VERSION issues warning' '
+ (
+ rm -f .git/index &&
+ GIT_INDEX_VERSION=2bogus &&
+ export GIT_INDEX_VERSION &&
+ git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
+ warning: GIT_INDEX_VERSION set, but the value is invalid.
+ Using version Z
+ EOF
+ test_i18ncmp expect.err actual.err
+ )
+'
+
+test_expect_success 'out of bounds GIT_INDEX_VERSION issues warning' '
+ (
+ rm -f .git/index &&
+ GIT_INDEX_VERSION=1 &&
+ export GIT_INDEX_VERSION &&
+ git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
+ warning: GIT_INDEX_VERSION set, but the value is invalid.
+ Using version Z
+ EOF
+ test_i18ncmp expect.err actual.err
+ )
+'
+
+test_expect_success 'no warning with bogus GIT_INDEX_VERSION and existing index' '
+ (
+ GIT_INDEX_VERSION=1 &&
+ export GIT_INDEX_VERSION &&
+ git add a 2>actual.err &&
+ >expect.err &&
+ test_i18ncmp expect.err actual.err
+ )
+'
+
+test_expect_success 'out of bounds index.version issues warning' '
+ (
+ sane_unset GIT_INDEX_VERSION &&
+ rm -f .git/index &&
+ git config --add index.version 1 &&
+ git add a 2>&1 | sed "s/[0-9]//" >actual.err &&
+ sed -e "s/ Z$/ /" <<-\EOF >expect.err &&
+ warning: index.version set, but the value is invalid.
+ Using version Z
+ EOF
+ test_i18ncmp expect.err actual.err
+ )
+'
+
+test_expect_success 'GIT_INDEX_VERSION takes precedence over config' '
+ (
+ rm -f .git/index &&
+ GIT_INDEX_VERSION=4 &&
+ export GIT_INDEX_VERSION &&
+ git config --add index.version 2 &&
+ git add a 2>&1 &&
+ echo 4 >expect &&
+ test-index-version <.git/index >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_done
diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh
new file mode 100755
index 0000000000..94fb473e7c
--- /dev/null
+++ b/t/t1700-split-index.sh
@@ -0,0 +1,194 @@
+#!/bin/sh
+
+test_description='split index mode tests'
+
+. ./test-lib.sh
+
+# We need total control of index splitting here
+sane_unset GIT_TEST_SPLIT_INDEX
+
+test_expect_success 'enable split index' '
+ git update-index --split-index &&
+ test-dump-split-index .git/index >actual &&
+ cat >expect <<EOF &&
+own 8299b0bcd1ac364e5f1d7768efb62fa2da79a339
+base 39d890139ee5356c7ef572216cebcd27aa41f9df
+replacements:
+deletions:
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'add one file' '
+ : >one &&
+ git update-index --add one &&
+ git ls-files --stage >ls-files.actual &&
+ cat >ls-files.expect <<EOF &&
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
+EOF
+ test_cmp ls-files.expect ls-files.actual &&
+
+ test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ cat >expect <<EOF &&
+base 39d890139ee5356c7ef572216cebcd27aa41f9df
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
+replacements:
+deletions:
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'disable split index' '
+ git update-index --no-split-index &&
+ git ls-files --stage >ls-files.actual &&
+ cat >ls-files.expect <<EOF &&
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
+EOF
+ test_cmp ls-files.expect ls-files.actual &&
+
+ BASE=`test-dump-split-index .git/index | grep "^own" | sed "s/own/base/"` &&
+ test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ cat >expect <<EOF &&
+not a split index
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'enable split index again, "one" now belongs to base index"' '
+ git update-index --split-index &&
+ git ls-files --stage >ls-files.actual &&
+ cat >ls-files.expect <<EOF &&
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
+EOF
+ test_cmp ls-files.expect ls-files.actual &&
+
+ test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ cat >expect <<EOF &&
+$BASE
+replacements:
+deletions:
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'modify original file, base index untouched' '
+ echo modified >one &&
+ git update-index one &&
+ git ls-files --stage >ls-files.actual &&
+ cat >ls-files.expect <<EOF &&
+100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one
+EOF
+ test_cmp ls-files.expect ls-files.actual &&
+
+ test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ q_to_tab >expect <<EOF &&
+$BASE
+100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
+replacements: 0
+deletions:
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'add another file, which stays index' '
+ : >two &&
+ git update-index --add two &&
+ git ls-files --stage >ls-files.actual &&
+ cat >ls-files.expect <<EOF &&
+100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two
+EOF
+ test_cmp ls-files.expect ls-files.actual &&
+
+ test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ q_to_tab >expect <<EOF &&
+$BASE
+100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two
+replacements: 0
+deletions:
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'remove file not in base index' '
+ git update-index --force-remove two &&
+ git ls-files --stage >ls-files.actual &&
+ cat >ls-files.expect <<EOF &&
+100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one
+EOF
+ test_cmp ls-files.expect ls-files.actual &&
+
+ test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ q_to_tab >expect <<EOF &&
+$BASE
+100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q
+replacements: 0
+deletions:
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'remove file in base index' '
+ git update-index --force-remove one &&
+ git ls-files --stage >ls-files.actual &&
+ cat >ls-files.expect <<EOF &&
+EOF
+ test_cmp ls-files.expect ls-files.actual &&
+
+ test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ cat >expect <<EOF &&
+$BASE
+replacements:
+deletions: 0
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'add original file back' '
+ : >one &&
+ git update-index --add one &&
+ git ls-files --stage >ls-files.actual &&
+ cat >ls-files.expect <<EOF &&
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
+EOF
+ test_cmp ls-files.expect ls-files.actual &&
+
+ test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ cat >expect <<EOF &&
+$BASE
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
+replacements:
+deletions: 0
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'add new file' '
+ : >two &&
+ git update-index --add two &&
+ git ls-files --stage >actual &&
+ cat >expect <<EOF &&
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'unify index, two files remain' '
+ git update-index --no-split-index &&
+ git ls-files --stage >ls-files.actual &&
+ cat >ls-files.expect <<EOF &&
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two
+EOF
+ test_cmp ls-files.expect ls-files.actual
+
+ test-dump-split-index .git/index | sed "/^own/d" >actual &&
+ cat >expect <<EOF &&
+not a split index
+EOF
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t2013-checkout-submodule.sh b/t/t2013-checkout-submodule.sh
index 06b18f8bc1..6847f75822 100755
--- a/t/t2013-checkout-submodule.sh
+++ b/t/t2013-checkout-submodule.sh
@@ -3,6 +3,7 @@
test_description='checkout can handle submodules'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
test_expect_success 'setup' '
mkdir submodule &&
@@ -62,4 +63,8 @@ test_expect_success '"checkout <submodule>" honors submodule.*.ignore from .git/
! test -s actual
'
+test_submodule_switch "git checkout"
+
+test_submodule_forced_switch "git checkout -f"
+
test_done
diff --git a/t/t2104-update-index-skip-worktree.sh b/t/t2104-update-index-skip-worktree.sh
index 1d0879be06..cc830da58d 100755
--- a/t/t2104-update-index-skip-worktree.sh
+++ b/t/t2104-update-index-skip-worktree.sh
@@ -7,6 +7,10 @@ test_description='skip-worktree bit test'
. ./test-lib.sh
+sane_unset GIT_TEST_SPLIT_INDEX
+
+test_set_index_version 3
+
cat >expect.full <<EOF
H 1
H 2
diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh
index a6405d318d..1bafb9098c 100755
--- a/t/t2107-update-index-basic.sh
+++ b/t/t2107-update-index-basic.sh
@@ -29,6 +29,10 @@ test_expect_success 'update-index -h with corrupt index' '
test_i18ngrep "[Uu]sage: git update-index" broken/usage
'
+test_expect_success '--cacheinfo complains of missing arguments' '
+ test_must_fail git update-index --cacheinfo
+'
+
test_expect_success '--cacheinfo does not accept blob null sha1' '
echo content >file &&
git add file &&
@@ -48,4 +52,17 @@ test_expect_success '--cacheinfo does not accept gitlink null sha1' '
test_cmp expect actual
'
+test_expect_success '--cacheinfo mode,sha1,path (new syntax)' '
+ echo content >file &&
+ git hash-object -w --stdin <file >expect &&
+
+ git update-index --add --cacheinfo 100644 "$(cat expect)" file &&
+ git rev-parse :file >actual &&
+ test_cmp expect actual &&
+
+ git update-index --add --cacheinfo "100644,$(cat expect),elif" &&
+ git rev-parse :elif >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index 9bf2bdffd2..e16b15d3e5 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -80,18 +80,13 @@ test_expect_success 'change gets noticed' '
'
-# Note that this is scheduled to change in Git 2.0, when
-# "git add -u" will become full-tree by default.
-test_expect_success 'non-limited update in subdir leaves root alone' '
+test_expect_success 'non-qualified update in subdir updates from the root' '
(
cd dir1 &&
echo even more >>sub2 &&
git add -u
) &&
- cat >expect <<-\EOF &&
- check
- top
- EOF
+ : >expect &&
git diff-files --name-only >actual &&
test_cmp expect actual
'
diff --git a/t/t3004-ls-files-basic.sh b/t/t3004-ls-files-basic.sh
index 8d9bc3c2af..9c7adbdbe1 100755
--- a/t/t3004-ls-files-basic.sh
+++ b/t/t3004-ls-files-basic.sh
@@ -36,4 +36,21 @@ test_expect_success 'ls-files -h in corrupt repository' '
test_i18ngrep "[Uu]sage: git ls-files " broken/usage
'
+test_expect_success SYMLINKS 'ls-files with absolute paths to symlinks' '
+ mkdir subs &&
+ ln -s nosuch link &&
+ ln -s ../nosuch subs/link &&
+ git add link subs/link &&
+ git ls-files -s link subs/link >expect &&
+ git ls-files -s "$(pwd)/link" "$(pwd)/subs/link" >actual &&
+ test_cmp expect actual &&
+
+ (
+ cd subs &&
+ git ls-files -s link >../expect &&
+ git ls-files -s "$(pwd)/link" >../actual
+ ) &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index 2f96100a5f..82e18548c3 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -257,6 +257,7 @@ test_expect_success 'setup 8' '
git add e &&
test_tick &&
git commit -m "rename a->e" &&
+ c7=$(git rev-parse --verify HEAD) &&
git checkout rename-ln &&
git mv a e &&
test_ln_s_add e a &&
@@ -517,6 +518,52 @@ test_expect_success 'reset and bind merge' '
'
+test_expect_success 'merge-recursive w/ empty work tree - ours has rename' '
+ (
+ GIT_WORK_TREE="$PWD/ours-has-rename-work" &&
+ export GIT_WORK_TREE &&
+ GIT_INDEX_FILE="$PWD/ours-has-rename-index" &&
+ export GIT_INDEX_FILE &&
+ mkdir "$GIT_WORK_TREE" &&
+ git read-tree -i -m $c7 &&
+ git update-index --ignore-missing --refresh &&
+ git merge-recursive $c0 -- $c7 $c3 &&
+ git ls-files -s >actual-files
+ ) 2>actual-err &&
+ >expected-err &&
+ cat >expected-files <<-EOF &&
+ 100644 $o3 0 b/c
+ 100644 $o0 0 c
+ 100644 $o0 0 d/e
+ 100644 $o0 0 e
+ EOF
+ test_cmp expected-files actual-files &&
+ test_cmp expected-err actual-err
+'
+
+test_expect_success 'merge-recursive w/ empty work tree - theirs has rename' '
+ (
+ GIT_WORK_TREE="$PWD/theirs-has-rename-work" &&
+ export GIT_WORK_TREE &&
+ GIT_INDEX_FILE="$PWD/theirs-has-rename-index" &&
+ export GIT_INDEX_FILE &&
+ mkdir "$GIT_WORK_TREE" &&
+ git read-tree -i -m $c3 &&
+ git update-index --ignore-missing --refresh &&
+ git merge-recursive $c0 -- $c3 $c7 &&
+ git ls-files -s >actual-files
+ ) 2>actual-err &&
+ >expected-err &&
+ cat >expected-files <<-EOF &&
+ 100644 $o3 0 b/c
+ 100644 $o0 0 c
+ 100644 $o0 0 d/e
+ 100644 $o0 0 e
+ EOF
+ test_cmp expected-files actual-files &&
+ test_cmp expected-err actual-err
+'
+
test_expect_success 'merge removes empty directories' '
git reset --hard master &&
diff --git a/t/t3032-merge-recursive-options.sh b/t/t3032-merge-recursive-options.sh
index 5fd7bbb652..4029c9c8c0 100755
--- a/t/t3032-merge-recursive-options.sh
+++ b/t/t3032-merge-recursive-options.sh
@@ -14,7 +14,11 @@ test_description='merge-recursive options
. ./test-lib.sh
test_have_prereq SED_STRIPS_CR && SED_OPTIONS=-b
-test_have_prereq GREP_STRIPS_CR && export GREP_OPTIONS=-U
+if test_have_prereq GREP_STRIPS_CR
+then
+ GREP_OPTIONS=-U
+ export GREP_OPTIONS
+fi
test_expect_success 'setup' '
conflict_hunks () {
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 38446a0e87..ef509df351 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -14,19 +14,6 @@ match() {
! test-wildmatch wildmatch '$3' '$4'
"
fi
- if [ $2 = 1 ]; then
- test_expect_success "fnmatch: match '$3' '$4'" "
- test-wildmatch fnmatch '$3' '$4'
- "
- elif [ $2 = 0 ]; then
- test_expect_success "fnmatch: no match '$3' '$4'" "
- ! test-wildmatch fnmatch '$3' '$4'
- "
-# else
-# test_expect_success BROKEN_FNMATCH "fnmatch: '$3' '$4'" "
-# ! test-wildmatch fnmatch '$3' '$4'
-# "
- fi
}
imatch() {
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index fcdb867748..432921b6b8 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -285,6 +285,15 @@ test_expect_success 'deleting a dangling symref' '
test_i18ncmp expect actual
'
+test_expect_success 'deleting a self-referential symref' '
+ git symbolic-ref refs/heads/self-reference refs/heads/self-reference &&
+ test_path_is_file .git/refs/heads/self-reference &&
+ echo "Deleted branch self-reference (was refs/heads/self-reference)." >expect &&
+ git branch -d self-reference >actual &&
+ test_path_is_missing .git/refs/heads/self-reference &&
+ test_i18ncmp expect actual
+'
+
test_expect_success 'renaming a symref is not allowed' '
git symbolic-ref refs/heads/master2 refs/heads/master &&
test_must_fail git branch -m master2 master3 &&
@@ -507,6 +516,16 @@ EOF
test_cmp expected actual
'
+test_expect_success '--set-upstream-to notices an error to set branch as own upstream' '
+ git branch --set-upstream-to refs/heads/my13 my13 2>actual &&
+ cat >expected <<-\EOF &&
+ warning: Not setting branch my13 as its own upstream.
+ EOF
+ test_expect_code 1 git config branch.my13.remote &&
+ test_expect_code 1 git config branch.my13.merge &&
+ test_i18ncmp expected actual
+'
+
# Keep this test last, as it changes the current branch
cat >expect <<EOF
$_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master
@@ -849,11 +868,7 @@ test_expect_success 'detect typo in branch name when using --edit-description' '
write_script editor <<-\EOF &&
echo "New contents" >"$1"
EOF
- (
- EDITOR=./editor &&
- export EDITOR &&
- test_must_fail git branch --edit-description no-such-branch
- )
+ test_must_fail env EDITOR=./editor git branch --edit-description no-such-branch
'
test_expect_success 'refuse --edit-description on unborn branch for now' '
@@ -861,11 +876,7 @@ test_expect_success 'refuse --edit-description on unborn branch for now' '
echo "New contents" >"$1"
EOF
git checkout --orphan unborn &&
- (
- EDITOR=./editor &&
- export EDITOR &&
- test_must_fail git branch --edit-description
- )
+ test_must_fail env EDITOR=./editor git branch --edit-description
'
test_expect_success '--merged catches invalid object names' '
diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh
index 141b0611ea..912a6635a8 100755
--- a/t/t3201-branch-contains.sh
+++ b/t/t3201-branch-contains.sh
@@ -130,4 +130,33 @@ test_expect_success 'implicit --list conflicts with modification options' '
'
+# We want to set up a case where the walk for the tracking info
+# of one branch crosses the tip of another branch (and make sure
+# that the latter walk does not mess up our flag to see if it was
+# merged).
+#
+# Here "topic" tracks "master" with one extra commit, and "zzz" points to the
+# same tip as master The name "zzz" must come alphabetically after "topic"
+# as we process them in that order.
+test_expect_success 'branch --merged with --verbose' '
+ git branch --track topic master &&
+ git branch zzz topic &&
+ git checkout topic &&
+ test_commit foo &&
+ git branch --merged topic >actual &&
+ cat >expect <<-\EOF &&
+ master
+ * topic
+ zzz
+ EOF
+ test_cmp expect actual &&
+ git branch --verbose --merged topic >actual &&
+ cat >expect <<-\EOF &&
+ master c77a0a9 second on master
+ * topic 2c939f4 [ahead 1] foo
+ zzz c77a0a9 second on master
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 1a2080e3dc..aa9eb3a3e5 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -11,7 +11,9 @@ semantic is still the same.
'
. ./test-lib.sh
-echo '[core] logallrefupdates = true' >>.git/config
+test_expect_success 'enable reflogs' '
+ git config core.logallrefupdates true
+'
test_expect_success \
'prepare a trivial repository' \
@@ -151,4 +153,38 @@ test_expect_success 'delete ref while another dangling packed ref' '
test_cmp /dev/null result
'
+test_expect_success 'pack ref directly below refs/' '
+ git update-ref refs/top HEAD &&
+ git pack-refs --all --prune &&
+ grep refs/top .git/packed-refs &&
+ test_path_is_missing .git/refs/top
+'
+
+test_expect_success 'disable reflogs' '
+ git config core.logallrefupdates false &&
+ rm -rf .git/logs
+'
+
+test_expect_success 'create packed foo/bar/baz branch' '
+ git branch foo/bar/baz &&
+ git pack-refs --all --prune &&
+ test_path_is_missing .git/refs/heads/foo/bar/baz &&
+ test_path_is_missing .git/logs/refs/heads/foo/bar/baz
+'
+
+test_expect_success 'notice d/f conflict with existing directory' '
+ test_must_fail git branch foo &&
+ test_must_fail git branch foo/bar
+'
+
+test_expect_success 'existing directory reports concrete ref' '
+ test_must_fail git branch foo 2>stderr &&
+ grep refs/heads/foo/bar/baz stderr
+'
+
+test_expect_success 'notice d/f conflict with existing ref' '
+ test_must_fail git branch foo/bar/baz/extra &&
+ test_must_fail git branch foo/bar/baz/lots/of/extra/components
+'
+
test_done
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 16de05aff9..cfd67ff3df 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -17,7 +17,7 @@ GIT_EDITOR=./fake_editor.sh
export GIT_EDITOR
test_expect_success 'cannot annotate non-existing HEAD' '
- (MSG=3 && export MSG && test_must_fail git notes add)
+ test_must_fail env MSG=3 git notes add
'
test_expect_success setup '
@@ -32,22 +32,16 @@ test_expect_success setup '
'
test_expect_success 'need valid notes ref' '
- (MSG=1 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF &&
- test_must_fail git notes add) &&
- (MSG=2 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF &&
- test_must_fail git notes show)
+ test_must_fail env MSG=1 GIT_NOTES_REF=/ git notes show &&
+ test_must_fail env MSG=2 GIT_NOTES_REF=/ git notes show
'
test_expect_success 'refusing to add notes in refs/heads/' '
- (MSG=1 GIT_NOTES_REF=refs/heads/bogus &&
- export MSG GIT_NOTES_REF &&
- test_must_fail git notes add)
+ test_must_fail env MSG=1 GIT_NOTES_REF=refs/heads/bogus git notes add
'
test_expect_success 'refusing to edit notes in refs/remotes/' '
- (MSG=1 GIT_NOTES_REF=refs/remotes/bogus &&
- export MSG GIT_NOTES_REF &&
- test_must_fail git notes edit)
+ test_must_fail env MSG=1 GIT_NOTES_REF=refs/heads/bogus git notes edit
'
# 1 indicates caught gracefully by die, 128 means git-show barked
@@ -812,6 +806,33 @@ test_expect_success 'create note from non-existing note with "git notes add -C"
test_must_fail git notes list HEAD
'
+test_expect_success 'create note from non-blob with "git notes add -C" fails' '
+ commit=$(git rev-parse --verify HEAD) &&
+ tree=$(git rev-parse --verify HEAD:) &&
+ test_must_fail git notes add -C $commit &&
+ test_must_fail git notes add -C $tree &&
+ test_must_fail git notes list HEAD
+'
+
+cat > expect << EOF
+commit 80d796defacd5db327b7a4e50099663902fbdc5c
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:20:13 2005 -0700
+
+ 8th
+
+Notes (other):
+ This is a blob object
+EOF
+
+test_expect_success 'create note from blob with "git notes add -C" reuses blob id' '
+ blob=$(echo "This is a blob object" | git hash-object -w --stdin) &&
+ git notes add -C $blob &&
+ git log -1 > actual &&
+ test_cmp expect actual &&
+ test "$(git notes list HEAD)" = "$blob"
+'
+
cat > expect << EOF
commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b
Author: A U Thor <author@example.com>
@@ -838,11 +859,7 @@ test_expect_success 'create note from non-existing note with "git notes add -c"
git add a10 &&
test_tick &&
git commit -m 10th &&
- (
- MSG="yet another note" &&
- export MSG &&
- test_must_fail git notes add -c deadbeef
- ) &&
+ test_must_fail env MSG="yet another note" git notes add -c deadbeef &&
test_must_fail git notes list HEAD
'
diff --git a/t/t3302-notes-index-expensive.sh b/t/t3302-notes-index-expensive.sh
index e35d7811ac..7217c5e222 100755
--- a/t/t3302-notes-index-expensive.sh
+++ b/t/t3302-notes-index-expensive.sh
@@ -7,53 +7,49 @@ test_description='Test commit notes index (expensive!)'
. ./test-lib.sh
-test_set_prereq NOT_EXPENSIVE
-test -n "$GIT_NOTES_TIMING_TESTS" && test_set_prereq EXPENSIVE
-test -x /usr/bin/time && test_set_prereq USR_BIN_TIME
-
create_repo () {
number_of_commits=$1
nr=0
test -d .git || {
git init &&
(
- while [ $nr -lt $number_of_commits ]; do
+ while test $nr -lt $number_of_commits
+ do
nr=$(($nr+1))
mark=$(($nr+$nr))
notemark=$(($mark+1))
test_tick &&
- cat <<INPUT_END &&
-commit refs/heads/master
-mark :$mark
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-commit #$nr
-COMMIT
-
-M 644 inline file
-data <<EOF
-file in commit #$nr
-EOF
-
-blob
-mark :$notemark
-data <<EOF
-note for commit #$nr
-EOF
-
-INPUT_END
-
- echo "N :$notemark :$mark" >> note_commit
+ cat <<-INPUT_END &&
+ commit refs/heads/master
+ mark :$mark
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit #$nr
+ COMMIT
+
+ M 644 inline file
+ data <<EOF
+ file in commit #$nr
+ EOF
+
+ blob
+ mark :$notemark
+ data <<EOF
+ note for commit #$nr
+ EOF
+
+ INPUT_END
+ echo "N :$notemark :$mark" >>note_commit
done &&
test_tick &&
- cat <<INPUT_END &&
-commit refs/notes/commits
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-notes
-COMMIT
+ cat <<-INPUT_END &&
+ commit refs/notes/commits
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ notes
+ COMMIT
-INPUT_END
+ INPUT_END
cat note_commit
) |
@@ -65,62 +61,74 @@ INPUT_END
test_notes () {
count=$1 &&
git config core.notesRef refs/notes/commits &&
- git log | grep "^ " > output &&
+ git log | grep "^ " >output &&
i=$count &&
- while [ $i -gt 0 ]; do
+ while test $i -gt 0
+ do
echo " commit #$i" &&
echo " note for commit #$i" &&
- i=$(($i-1));
- done > expect &&
+ i=$(($i-1))
+ done >expect &&
test_cmp expect output
}
-cat > time_notes << \EOF
+write_script time_notes <<\EOF
mode=$1
i=1
- while [ $i -lt $2 ]; do
+ while test $i -lt $2
+ do
case $1 in
no-notes)
- GIT_NOTES_REF=non-existing; export GIT_NOTES_REF
- ;;
+ GIT_NOTES_REF=non-existing
+ export GIT_NOTES_REF
+ ;;
notes)
unset GIT_NOTES_REF
- ;;
+ ;;
esac
- git log >/dev/null
+ git log
i=$(($i+1))
- done
+ done >/dev/null
EOF
time_notes () {
for mode in no-notes notes
do
echo $mode
- /usr/bin/time "$SHELL_PATH" ../time_notes $mode $1
+ /usr/bin/time ../time_notes $mode $1
done
}
do_tests () {
- pr=$1
- count=$2
-
- test_expect_success $pr 'setup / mkdir' '
- mkdir $count &&
- cd $count
+ count=$1 pr=${2-}
+
+ test_expect_success $pr "setup $count" '
+ mkdir "$count" &&
+ (
+ cd "$count" &&
+ create_repo "$count"
+ )
'
- test_expect_success $pr "setup $count" "create_repo $count"
-
- test_expect_success $pr 'notes work' "test_notes $count"
-
- test_expect_success USR_BIN_TIME,$pr 'notes timing with /usr/bin/time' "time_notes 100"
+ test_expect_success $pr 'notes work' '
+ (
+ cd "$count" &&
+ test_notes "$count"
+ )
+ '
- test_expect_success $pr 'teardown / cd ..' 'cd ..'
+ test_expect_success "USR_BIN_TIME${pr:+,$pr}" 'notes timing with /usr/bin/time' '
+ (
+ cd "$count" &&
+ time_notes 100
+ )
+ '
}
-do_tests NOT_EXPENSIVE 10
-for count in 100 1000 10000; do
- do_tests EXPENSIVE $count
+do_tests 10
+for count in 100 1000 10000
+do
+ do_tests "$count" EXPENSIVE
done
test_done
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index ebf93b0695..47b5682662 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -88,6 +88,23 @@ test_expect_success 'rebase from ambiguous branch name' '
git rebase master
'
+test_expect_success 'rebase off of the previous branch using "-"' '
+ git checkout master &&
+ git checkout HEAD^ &&
+ git rebase @{-1} >expect.messages &&
+ git merge-base master HEAD >expect.forkpoint &&
+
+ git checkout master &&
+ git checkout HEAD^ &&
+ git rebase - >actual.messages &&
+ git merge-base master HEAD >actual.forkpoint &&
+
+ test_cmp expect.forkpoint actual.forkpoint &&
+ # the next one is dubious---we may want to say "-",
+ # instead of @{-1}, in the message
+ test_i18ncmp expect.messages actual.messages
+'
+
test_expect_success 'rebase a single mode change' '
git checkout master &&
git branch -D topic &&
@@ -134,12 +151,45 @@ test_expect_success 'fail when upstream arg is missing and not configured' '
test_must_fail git rebase
'
-test_expect_success 'default to @{upstream} when upstream arg is missing' '
+test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg' '
+ git checkout -b default-base master &&
git checkout -b default topic &&
git config branch.default.remote . &&
- git config branch.default.merge refs/heads/master &&
+ git config branch.default.merge refs/heads/default-base &&
+ git rebase &&
+ git rev-parse --verify default-base >expect &&
+ git rev-parse default~1 >actual &&
+ test_cmp expect actual &&
+ git checkout default-base &&
+ git reset --hard HEAD^ &&
+ git checkout default &&
+ git rebase &&
+ git rev-parse --verify default-base >expect &&
+ git rev-parse default~1 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'cherry-picked commits and fork-point work together' '
+ git checkout default-base &&
+ echo Amended >A &&
+ git commit -a --no-edit --amend &&
+ test_commit B B &&
+ test_commit new_B B "New B" &&
+ test_commit C C &&
+ git checkout default &&
+ git reset --hard default-base@{4} &&
+ test_commit D D &&
+ git cherry-pick -2 default-base^ &&
+ test_commit final_B B "Final B" &&
git rebase &&
- test "$(git rev-parse default~1)" = "$(git rev-parse master)"
+ echo Amended >expect &&
+ test_cmp A expect &&
+ echo "Final B" >expect &&
+ test_cmp B expect &&
+ echo C >expect &&
+ test_cmp C expect &&
+ echo D >expect &&
+ test_cmp D expect
'
test_expect_success 'rebase -q is quiet' '
diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh
index be8c1d5ef9..5a27ec9b5e 100755
--- a/t/t3402-rebase-merge.sh
+++ b/t/t3402-rebase-merge.sh
@@ -33,6 +33,7 @@ test_expect_success setup '
tr "[a-z]" "[A-Z]" <original >newfile &&
git add newfile &&
git commit -a -m"side edits further." &&
+ git branch second-side &&
tr "[a-m]" "[A-M]" <original >newfile &&
rm -f original &&
@@ -41,6 +42,7 @@ test_expect_success setup '
git branch test-rebase side &&
git branch test-rebase-pick side &&
git branch test-reference-pick side &&
+ git branch test-conflicts side &&
git checkout -b test-merge side
'
@@ -138,4 +140,17 @@ test_expect_success 'rebase -s funny -Xopt' '
test -f funny.was.run
'
+test_expect_success 'rebase --skip works with two conflicts in a row' '
+ git checkout second-side &&
+ tr "[A-Z]" "[a-z]" <newfile >tmp &&
+ mv tmp newfile &&
+ git commit -a -m"edit conflicting with side" &&
+ tr "[d-f]" "[D-F]" <newfile >tmp &&
+ mv tmp newfile &&
+ git commit -a -m"another edit conflicting with side" &&
+ test_must_fail git rebase --merge test-conflicts &&
+ test_must_fail git rebase --skip &&
+ git rebase --skip
+'
+
test_done
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 50e22b1cad..8197ed29a9 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -67,6 +67,14 @@ test_expect_success 'setup' '
SHELL=
export SHELL
+test_expect_success 'rebase --keep-empty' '
+ git checkout -b emptybranch master &&
+ git commit --allow-empty -m "empty" &&
+ git rebase --keep-empty -i HEAD~2 &&
+ git log --oneline >actual &&
+ test_line_count = 6 actual
+'
+
test_expect_success 'rebase -i with the exec command' '
git checkout master &&
(
@@ -102,12 +110,8 @@ test_expect_success 'rebase -i with the exec command runs from tree root' '
test_expect_success 'rebase -i with the exec command checks tree cleanness' '
git checkout master &&
- (
set_fake_editor &&
- FAKE_LINES="exec_echo_foo_>file1 1" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD^
- ) &&
+ test_must_fail env FAKE_LINES="exec_echo_foo_>file1 1" git rebase -i HEAD^ &&
test_cmp_rev master^ HEAD &&
git reset --hard &&
git rebase --continue
@@ -116,12 +120,9 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '
test_expect_success 'rebase -i with exec of inexistent command' '
git checkout master &&
test_when_finished "git rebase --abort" &&
- (
set_fake_editor &&
- FAKE_LINES="exec_this-command-does-not-exist 1" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD^ >actual 2>&1
- ) &&
+ test_must_fail env FAKE_LINES="exec_this-command-does-not-exist 1" \
+ git rebase -i HEAD^ >actual 2>&1 &&
! grep "Maybe git-rebase is broken" actual
'
@@ -375,11 +376,7 @@ test_expect_success 'commit message used after conflict' '
git checkout -b conflict-fixup conflict-branch &&
base=$(git rev-parse HEAD~4) &&
set_fake_editor &&
- (
- FAKE_LINES="1 fixup 3 fixup 4" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i $base
- ) &&
+ test_must_fail env FAKE_LINES="1 fixup 3 fixup 4" git rebase -i $base &&
echo three > conflict &&
git add conflict &&
FAKE_COMMIT_AMEND="ONCE" EXPECT_HEADER_COUNT=2 \
@@ -394,11 +391,7 @@ test_expect_success 'commit message retained after conflict' '
git checkout -b conflict-squash conflict-branch &&
base=$(git rev-parse HEAD~4) &&
set_fake_editor &&
- (
- FAKE_LINES="1 fixup 3 squash 4" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i $base
- ) &&
+ test_must_fail env FAKE_LINES="1 fixup 3 squash 4" git rebase -i $base &&
echo three > conflict &&
git add conflict &&
FAKE_COMMIT_AMEND="TWICE" EXPECT_HEADER_COUNT=2 \
@@ -469,11 +462,7 @@ test_expect_success 'interrupted squash works as expected' '
git checkout -b interrupted-squash conflict-branch &&
one=$(git rev-parse HEAD~3) &&
set_fake_editor &&
- (
- FAKE_LINES="1 squash 3 2" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD~3
- ) &&
+ test_must_fail env FAKE_LINES="1 squash 3 2" git rebase -i HEAD~3 &&
(echo one; echo two; echo four) > conflict &&
git add conflict &&
test_must_fail git rebase --continue &&
@@ -487,11 +476,7 @@ test_expect_success 'interrupted squash works as expected (case 2)' '
git checkout -b interrupted-squash2 conflict-branch &&
one=$(git rev-parse HEAD~3) &&
set_fake_editor &&
- (
- FAKE_LINES="3 squash 1 2" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD~3
- ) &&
+ test_must_fail env FAKE_LINES="3 squash 1 2" git rebase -i HEAD~3 &&
(echo one; echo four) > conflict &&
git add conflict &&
test_must_fail git rebase --continue &&
@@ -528,11 +513,7 @@ test_expect_success 'aborted --continue does not squash commits after "edit"' '
FAKE_LINES="edit 1" git rebase -i HEAD^ &&
echo "edited again" > file7 &&
git add file7 &&
- (
- FAKE_COMMIT_MESSAGE=" " &&
- export FAKE_COMMIT_MESSAGE &&
- test_must_fail git rebase --continue
- ) &&
+ test_must_fail env FAKE_COMMIT_MESSAGE=" " git rebase --continue &&
test $old = $(git rev-parse HEAD) &&
git rebase --abort
'
@@ -547,11 +528,7 @@ test_expect_success 'auto-amend only edited commits after "edit"' '
echo "and again" > file7 &&
git add file7 &&
test_tick &&
- (
- FAKE_COMMIT_MESSAGE="and again" &&
- export FAKE_COMMIT_MESSAGE &&
- test_must_fail git rebase --continue
- ) &&
+ test_must_fail env FAKE_COMMIT_MESSAGE="and again" git rebase --continue &&
git rebase --abort
'
@@ -559,11 +536,7 @@ test_expect_success 'clean error after failed "exec"' '
test_tick &&
test_when_finished "git rebase --abort || :" &&
set_fake_editor &&
- (
- FAKE_LINES="1 exec_false" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i HEAD^
- ) &&
+ test_must_fail env FAKE_LINES="1 exec_false" git rebase -i HEAD^ &&
echo "edited again" > file7 &&
git add file7 &&
test_must_fail git rebase --continue 2>error &&
@@ -947,12 +920,8 @@ test_expect_success 'rebase -i --root retain root commit author and message' '
test_expect_success 'rebase -i --root temporary sentinel commit' '
git checkout B &&
- (
- set_fake_editor &&
- FAKE_LINES="2" &&
- export FAKE_LINES &&
- test_must_fail git rebase -i --root
- ) &&
+ set_fake_editor &&
+ test_must_fail env FAKE_LINES="2" git rebase -i --root &&
git cat-file commit HEAD | grep "^tree 4b825dc642cb" &&
git rebase --abort
'
@@ -1042,11 +1011,7 @@ test_expect_success 'rebase -i error on commits with \ in message' '
test_when_finished "git rebase --abort; git reset --hard $current_head; rm -f error" &&
test_commit TO-REMOVE will-conflict old-content &&
test_commit "\temp" will-conflict new-content dummy &&
- (
- EDITOR=true &&
- export EDITOR &&
- test_must_fail git rebase -i HEAD^ --onto HEAD^^ 2>error
- ) &&
+ test_must_fail env EDITOR=true git rebase -i HEAD^ --onto HEAD^^ 2>error &&
test_expect_code 1 grep " emp" error
'
diff --git a/t/t3413-rebase-hook.sh b/t/t3413-rebase-hook.sh
index 098b75507b..b6833e9a5f 100755
--- a/t/t3413-rebase-hook.sh
+++ b/t/t3413-rebase-hook.sh
@@ -118,11 +118,7 @@ test_expect_success 'pre-rebase hook stops rebase (1)' '
test_expect_success 'pre-rebase hook stops rebase (2)' '
git checkout test &&
git reset --hard side &&
- (
- EDITOR=:
- export EDITOR
- test_must_fail git rebase -i master
- ) &&
+ test_must_fail env EDITOR=: git rebase -i master &&
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
test 0 = $(git rev-list HEAD...side | wc -l)
'
diff --git a/t/t3419-rebase-patch-id.sh b/t/t3419-rebase-patch-id.sh
index e70ac10a0c..217dd79b2e 100755
--- a/t/t3419-rebase-patch-id.sh
+++ b/t/t3419-rebase-patch-id.sh
@@ -4,12 +4,7 @@ test_description='git rebase - test patch id computation'
. ./test-lib.sh
-test_set_prereq NOT_EXPENSIVE
-test -n "$GIT_PATCHID_TIMING_TESTS" && test_set_prereq EXPENSIVE
-test -x /usr/bin/time && test_set_prereq USR_BIN_TIME
-
-count()
-{
+count () {
i=0
while test $i -lt $1
do
@@ -18,8 +13,7 @@ count()
done
}
-scramble()
-{
+scramble () {
i=0
while read x
do
@@ -28,12 +22,11 @@ scramble()
echo "$x"
fi
i=$((($i+1) % 10))
- done < "$1" > "$1.new"
+ done <"$1" >"$1.new"
mv -f "$1.new" "$1"
}
-run()
-{
+run () {
echo \$ "$@"
/usr/bin/time "$@" >/dev/null
}
@@ -43,10 +36,8 @@ test_expect_success 'setup' '
git tag root
'
-do_tests()
-{
- pr=$1
- nlines=$2
+do_tests () {
+ nlines=$1 pr=${2-}
test_expect_success $pr "setup: $nlines lines" "
rm -f .gitattributes &&
@@ -103,7 +94,7 @@ do_tests()
"
}
-do_tests NOT_EXPENSIVE 500
-do_tests EXPENSIVE 50000
+do_tests 500
+do_tests 50000 EXPENSIVE
test_done
diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh
index 90eb26493c..d783f03d3f 100755
--- a/t/t3420-rebase-autostash.sh
+++ b/t/t3420-rebase-autostash.sh
@@ -167,4 +167,19 @@ testrebase "" .git/rebase-apply
testrebase " --merge" .git/rebase-merge
testrebase " --interactive" .git/rebase-merge
+test_expect_success 'abort rebase -i with --autostash' '
+ test_when_finished "git reset --hard" &&
+ echo uncommited-content >file0 &&
+ (
+ write_script abort-editor.sh <<-\EOF &&
+ echo >"$1"
+ EOF
+ test_set_editor "$(pwd)/abort-editor.sh" &&
+ test_must_fail git rebase -i --autostash HEAD^ &&
+ rm -f abort-editor.sh
+ ) &&
+ echo uncommited-content >expected &&
+ test_cmp expected file0
+'
+
test_done
diff --git a/t/t3426-rebase-submodule.sh b/t/t3426-rebase-submodule.sh
new file mode 100755
index 0000000000..d5b896d445
--- /dev/null
+++ b/t/t3426-rebase-submodule.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+test_description='rebase can handle submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+git_rebase () {
+ git status -su >expect &&
+ ls -1pR * >>expect &&
+ git checkout -b ours HEAD &&
+ echo x >>file1 &&
+ git add file1 &&
+ git commit -m add_x &&
+ git revert HEAD &&
+ git status -su >actual &&
+ ls -1pR * >>actual &&
+ test_cmp expect actual &&
+ git rebase "$1"
+}
+
+test_submodule_switch "git_rebase"
+
+git_rebase_interactive () {
+ git status -su >expect &&
+ ls -1pR * >>expect &&
+ git checkout -b ours HEAD &&
+ echo x >>file1 &&
+ git add file1 &&
+ git commit -m add_x &&
+ git revert HEAD &&
+ git status -su >actual &&
+ ls -1pR * >>actual &&
+ test_cmp expect actual &&
+ set_fake_editor &&
+ echo "fake-editor.sh" >.git/info/exclude &&
+ git rebase -i "$1"
+}
+
+KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1
+# The real reason "replace directory with submodule" fails is because a
+# directory "sub1" exists, but we reuse the suppression added for merge here
+test_submodule_switch "git_rebase_interactive"
+
+test_done
diff --git a/t/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh
index 19c99d7ef1..b457333e18 100755
--- a/t/t3508-cherry-pick-many-commits.sh
+++ b/t/t3508-cherry-pick-many-commits.sh
@@ -65,12 +65,15 @@ test_expect_success 'output to keep user entertained during multi-pick' '
cat <<-\EOF >expected &&
[master OBJID] second
Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:14:13 2005 -0700
1 file changed, 1 insertion(+)
[master OBJID] third
Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:15:13 2005 -0700
1 file changed, 1 insertion(+)
[master OBJID] fourth
Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:16:13 2005 -0700
1 file changed, 1 insertion(+)
EOF
@@ -98,14 +101,17 @@ test_expect_success 'output during multi-pick indicates merge strategy' '
Trying simple merge.
[master OBJID] second
Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:14:13 2005 -0700
1 file changed, 1 insertion(+)
Trying simple merge.
[master OBJID] third
Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:15:13 2005 -0700
1 file changed, 1 insertion(+)
Trying simple merge.
[master OBJID] fourth
Author: A U Thor <author@example.com>
+ Date: Thu Apr 7 15:16:13 2005 -0700
1 file changed, 1 insertion(+)
EOF
diff --git a/t/t3512-cherry-pick-submodule.sh b/t/t3512-cherry-pick-submodule.sh
new file mode 100755
index 0000000000..6863b7bb6f
--- /dev/null
+++ b/t/t3512-cherry-pick-submodule.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+test_description='cherry-pick can handle submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT=1
+KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1
+KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1
+test_submodule_switch "git cherry-pick"
+
+test_done
diff --git a/t/t3513-revert-submodule.sh b/t/t3513-revert-submodule.sh
new file mode 100755
index 0000000000..a1c4e0216f
--- /dev/null
+++ b/t/t3513-revert-submodule.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+test_description='revert can handle submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+# Create a revert that moves from HEAD (including any test modifications to
+# the work tree) to $1 by first checking out $1 and reverting it. Reverting
+# the revert is the transition we test for. We tar the current work tree
+# first so we can restore the work tree test setup after doing the checkout
+# and revert. We test here that the restored work tree content is identical
+# to that at the beginning. The last revert is then tested by the framework.
+git_revert () {
+ git status -su >expect &&
+ ls -1pR * >>expect &&
+ tar czf "$TRASH_DIRECTORY/tmp.tgz" * &&
+ git checkout "$1" &&
+ git revert HEAD &&
+ rm -rf * &&
+ tar xzf "$TRASH_DIRECTORY/tmp.tgz" &&
+ git status -su >actual &&
+ ls -1pR * >>actual &&
+ test_cmp expect actual &&
+ git revert HEAD
+}
+
+KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT=1
+KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1
+test_submodule_switch "git_revert"
+
+test_done
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 540c49bab6..e00d7d2b61 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -705,6 +705,21 @@ test_expect_success 'rm of a populated nested submodule with a nested .git direc
rm -rf submod
'
+test_expect_success 'checking out a commit after submodule removal needs manual updates' '
+ git commit -m "submodule removal" submod &&
+ git checkout HEAD^ &&
+ git submodule update &&
+ git checkout -q HEAD^ 2>actual &&
+ git checkout -q master 2>actual &&
+ test_i18ngrep "^warning: unable to rmdir submod:" actual &&
+ git status -s submod >actual &&
+ echo "?? submod/" >expected &&
+ test_cmp expected actual &&
+ rm -rf submod &&
+ git status -s -uno --ignore-submodules=none > actual &&
+ ! test -s actual
+'
+
test_expect_success 'rm of d/f when d has become a non-directory' '
rm -rf d &&
mkdir d &&
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 9dc91d09d7..24ddd8a704 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -2,7 +2,6 @@
test_description='add -i basic tests'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
if ! test_have_prereq PERL
then
diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh
index 31a5770b34..a392f3d1d6 100755
--- a/t/t3901-i18n-patch.sh
+++ b/t/t3901-i18n-patch.sh
@@ -54,10 +54,13 @@ test_expect_success setup '
git add yours &&
git commit -s -m "Second on side" &&
- # the second one on the side branch is ISO-8859-1
- git config i18n.commitencoding ISO8859-1 &&
- # use author and committer name in ISO-8859-1 to match it.
- . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
+ if test_have_prereq !MINGW
+ then
+ # the second one on the side branch is ISO-8859-1
+ git config i18n.commitencoding ISO8859-1 &&
+ # use author and committer name in ISO-8859-1 to match it.
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt
+ fi &&
test_tick &&
echo Yet another >theirs &&
git add theirs &&
@@ -119,7 +122,7 @@ test_expect_success 'rebase (U/L)' '
check_encoding 2
'
-test_expect_success 'rebase (L/L)' '
+test_expect_success !MINGW 'rebase (L/L)' '
# In this test we want ISO-8859-1 encoded commits as the result
git config i18n.commitencoding ISO8859-1 &&
git config i18n.logoutputencoding ISO8859-1 &&
@@ -131,7 +134,7 @@ test_expect_success 'rebase (L/L)' '
check_encoding 2 8859
'
-test_expect_success 'rebase (L/U)' '
+test_expect_success !MINGW 'rebase (L/U)' '
# This is pathological -- use UTF-8 as intermediate form
# to get ISO-8859-1 results.
git config i18n.commitencoding ISO8859-1 &&
@@ -159,7 +162,7 @@ test_expect_success 'cherry-pick(U/U)' '
check_encoding 3
'
-test_expect_success 'cherry-pick(L/L)' '
+test_expect_success !MINGW 'cherry-pick(L/L)' '
# Both the commitencoding and logoutputencoding is set to ISO-8859-1
git config i18n.commitencoding ISO8859-1 &&
@@ -189,7 +192,7 @@ test_expect_success 'cherry-pick(U/L)' '
check_encoding 3
'
-test_expect_success 'cherry-pick(L/U)' '
+test_expect_success !MINGW 'cherry-pick(L/U)' '
# Again, the commitencoding is set to ISO-8859-1 but
# logoutputencoding is set to UTF-8.
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 5b79b216e2..1e29962fad 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -685,4 +685,46 @@ test_expect_success 'handle stash specification with spaces' '
grep pig file
'
+test_expect_success 'setup stash with index and worktree changes' '
+ git stash clear &&
+ git reset --hard &&
+ echo index >file &&
+ git add file &&
+ echo working >file &&
+ git stash
+'
+
+test_expect_success 'stash list implies --first-parent -m' '
+ cat >expect <<-\EOF &&
+ stash@{0}: WIP on master: b27a2bc subdir
+
+ diff --git a/file b/file
+ index 257cc56..d26b33d 100644
+ --- a/file
+ +++ b/file
+ @@ -1 +1 @@
+ -foo
+ +working
+ EOF
+ git stash list -p >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stash list --cc shows combined diff' '
+ cat >expect <<-\EOF &&
+ stash@{0}: WIP on master: b27a2bc subdir
+
+ diff --cc file
+ index 257cc56,9015a7a..d26b33d
+ --- a/file
+ +++ b/file
+ @@@ -1,1 -1,1 +1,1 @@@
+ - foo
+ -index
+ ++working
+ EOF
+ git stash list -p --cc >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index a5e7e6b2ba..f372fc8ca8 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -96,8 +96,8 @@ test_expect_success 'stash pop after save --include-untracked leaves files untra
git stash pop &&
git status --porcelain >actual &&
test_cmp expect actual &&
- test "1" = "`cat file2`" &&
- test untracked = "`cat untracked/untracked`"
+ test "1" = "$(cat file2)" &&
+ test untracked = "$(cat untracked/untracked)"
'
git clean --force --quiet -d
diff --git a/t/t3906-stash-submodule.sh b/t/t3906-stash-submodule.sh
new file mode 100755
index 0000000000..d7219d6f8f
--- /dev/null
+++ b/t/t3906-stash-submodule.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+test_description='stash apply can handle submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+git_stash () {
+ git status -su >expect &&
+ ls -1pR * >>expect &&
+ git read-tree -u -m "$1" &&
+ git stash &&
+ git status -su >actual &&
+ ls -1pR * >>actual &&
+ test_cmp expect actual &&
+ git stash apply
+}
+
+KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES=1
+KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT=1
+KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1
+test_submodule_switch "git_stash"
+
+test_done
diff --git a/t/t3910-mac-os-precompose.sh b/t/t3910-mac-os-precompose.sh
index e4ba6013e4..831935665e 100755
--- a/t/t3910-mac-os-precompose.sh
+++ b/t/t3910-mac-os-precompose.sh
@@ -14,13 +14,13 @@ then
fi
# create utf-8 variables
-Adiarnfc=`printf '\303\204'`
-Adiarnfd=`printf 'A\314\210'`
+Adiarnfc=$(printf '\303\204')
+Adiarnfd=$(printf 'A\314\210')
-Odiarnfc=`printf '\303\226'`
-Odiarnfd=`printf 'O\314\210'`
-AEligatu=`printf '\303\206'`
-Invalidu=`printf '\303\377'`
+Odiarnfc=$(printf '\303\226')
+Odiarnfd=$(printf 'O\314\210')
+AEligatu=$(printf '\303\206')
+Invalidu=$(printf '\303\377')
#Create a string with 255 bytes (decomposed)
@@ -35,7 +35,7 @@ Alongc=$Alongc$Alongc$Alongc$Alongc$Alongc #250 Byte
Alongc=$Alongc$AEligatu$AEligatu #254 Byte
test_expect_success "detect if nfd needed" '
- precomposeunicode=`git config core.precomposeunicode` &&
+ precomposeunicode=$(git config core.precomposeunicode) &&
test "$precomposeunicode" = true &&
git config core.precomposeunicode true
'
@@ -140,13 +140,23 @@ test_expect_success "Add long precomposed filename" '
git add * &&
git commit -m "Long filename"
'
+
+test_expect_failure 'handle existing decomposed filenames' '
+ echo content >"verbatim.$Adiarnfd" &&
+ git -c core.precomposeunicode=false add "verbatim.$Adiarnfd" &&
+ git commit -m "existing decomposed file" &&
+ >expect &&
+ git ls-files --exclude-standard -o "verbatim*" >untracked &&
+ test_cmp expect untracked
+'
+
# Test if the global core.precomposeunicode stops autosensing
# Must be the last test case
test_expect_success "respect git config --global core.precomposeunicode" '
git config --global core.precomposeunicode true &&
rm -rf .git &&
git init &&
- precomposeunicode=`git config core.precomposeunicode` &&
+ precomposeunicode=$(git config core.precomposeunicode) &&
test "$precomposeunicode" = "true"
'
diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh
index 77d7f4946f..7d2c6e13a2 100755
--- a/t/t4005-diff-rename-2.sh
+++ b/t/t4005-diff-rename-2.sh
@@ -66,7 +66,7 @@ test_expect_success \
# tree has COPYING and rezrov. work tree has the same COPYING and
# copy-edited COPYING.1, and unchanged rezrov. We should not say
-# anything about rezrov nor COPYING, since the revised again diff-raw
+# anything about rezrov or COPYING, since the revised again diff-raw
# nows how to say Copy.
test_expect_success \
diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh
index 05911492ca..76f643b2c2 100755
--- a/t/t4006-diff-mode.sh
+++ b/t/t4006-diff-mode.sh
@@ -13,7 +13,7 @@ sed_script='s/\(:100644 100755\) \('"$_x40"'\) \2 /\1 X X /'
test_expect_success 'setup' '
echo frotz >rezrov &&
git update-index --add rezrov &&
- tree=`git write-tree` &&
+ tree=$(git write-tree) &&
echo $tree
'
diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh
index f22c8e3dba..57c094fdce 100755
--- a/t/t4009-diff-rename-4.sh
+++ b/t/t4009-diff-rename-4.sh
@@ -73,7 +73,7 @@ test_expect_success \
# tree has COPYING and rezrov. work tree has the same COPYING and
# copy-edited COPYING.1, and unchanged rezrov. We should not say
-# anything about rezrov nor COPYING, since the revised again diff-raw
+# anything about rezrov or COPYING, since the revised again diff-raw
# nows how to say Copy.
test_expect_success \
diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh
index 589bc6bfb4..bf07841866 100755
--- a/t/t4010-diff-pathspec.sh
+++ b/t/t4010-diff-pathspec.sh
@@ -18,7 +18,7 @@ test_expect_success \
mkdir path1 &&
echo rezrov >path1/file1 &&
git update-index --add file0 path1/file1 &&
- tree=`git write-tree` &&
+ tree=$(git write-tree) &&
echo "$tree" &&
echo nitfol >file0 &&
echo yomin >path1/file1 &&
@@ -110,11 +110,28 @@ test_expect_success 'diff-tree -r with wildcard' '
test_cmp expected result
'
+test_expect_success 'setup submodules' '
+ test_tick &&
+ git init submod &&
+ ( cd submod && test_commit first; ) &&
+ git add submod &&
+ git commit -m first &&
+ ( cd submod && test_commit second; ) &&
+ git add submod &&
+ git commit -m second
+'
+
+test_expect_success 'diff-tree ignores trailing slash on submodule path' '
+ git diff --name-only HEAD^ HEAD submod >expect &&
+ git diff --name-only HEAD^ HEAD submod/ >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'diff multiple wildcard pathspecs' '
mkdir path2 &&
echo rezrov >path2/file1 &&
git update-index --add path2/file1 &&
- tree3=`git write-tree` &&
+ tree3=$(git write-tree) &&
git diff --name-only $tree $tree3 -- "path2*1" "path1*1" >actual &&
cat <<-\EOF >expect &&
path1/file1
@@ -123,4 +140,10 @@ test_expect_success 'diff multiple wildcard pathspecs' '
test_cmp expect actual
'
+test_expect_success 'diff-cache ignores trailing slash on submodule path' '
+ git diff --name-only HEAD^ submod >expect &&
+ git diff --name-only HEAD^ submod/ >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index 1215ae544b..643d729157 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -67,18 +67,18 @@ test_expect_success C_LOCALE_OUTPUT 'apply detecting corrupt patch correctly' '
git diff >output &&
sed -e "s/-CIT/xCIT/" <output >broken &&
test_must_fail git apply --stat --summary broken 2>detected &&
- detected=`cat detected` &&
- detected=`expr "$detected" : "fatal.*at line \\([0-9]*\\)\$"` &&
- detected=`sed -ne "${detected}p" broken` &&
+ detected=$(cat detected) &&
+ detected=$(expr "$detected" : "fatal.*at line \\([0-9]*\\)\$") &&
+ detected=$(sed -ne "${detected}p" broken) &&
test "$detected" = xCIT
'
test_expect_success C_LOCALE_OUTPUT 'apply detecting corrupt patch correctly' '
git diff --binary | sed -e "s/-CIT/xCIT/" >broken &&
test_must_fail git apply --stat --summary broken 2>detected &&
- detected=`cat detected` &&
- detected=`expr "$detected" : "fatal.*at line \\([0-9]*\\)\$"` &&
- detected=`sed -ne "${detected}p" broken` &&
+ detected=$(cat detected) &&
+ detected=$(expr "$detected" : "fatal.*at line \\([0-9]*\\)\$") &&
+ detected=$(sed -ne "${detected}p" broken) &&
test "$detected" = xCIT
'
@@ -88,7 +88,7 @@ test_expect_success 'initial commit' 'git commit -a -m initial'
test_expect_success 'diff-index with --binary' '
echo AIT >a && mv b e && echo CIT >c && cat e >d &&
git update-index --add --remove a b c d e &&
- tree0=`git write-tree` &&
+ tree0=$(git write-tree) &&
git diff --cached --binary >current &&
git apply --stat --summary current
'
@@ -96,7 +96,7 @@ test_expect_success 'diff-index with --binary' '
test_expect_success 'apply binary patch' '
git reset --hard &&
git apply --binary --index <current &&
- tree1=`git write-tree` &&
+ tree1=$(git write-tree) &&
test "$tree1" = "$tree0"
'
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index e77c09c37e..6ec6072118 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -107,14 +107,14 @@ test_expect_success setup '
+*++ [initial] Initial
EOF
-V=`git version | sed -e 's/^git version //' -e 's/\./\\./g'`
+V=$(git version | sed -e 's/^git version //' -e 's/\./\\./g')
while read cmd
do
case "$cmd" in
'' | '#'*) continue ;;
esac
- test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'`
- pfx=`printf "%04d" $test_count`
+ test=$(echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g')
+ pfx=$(printf "%04d" $test_count)
expect="$TEST_DIRECTORY/t4013/diff.$test"
actual="$pfx-diff.$test"
@@ -324,4 +324,14 @@ test_expect_success 'diff --cached -- file on unborn branch' '
test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result
'
+test_expect_success 'diff-tree --stdin with log formatting' '
+ cat >expect <<-\EOF &&
+ Side
+ Third
+ Second
+ EOF
+ git rev-list master | git diff-tree --stdin --format=%s -s >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 73194b2c3d..256affce89 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -43,7 +43,7 @@ test_expect_success setup '
test_expect_success "format-patch --ignore-if-in-upstream" '
git format-patch --stdout master..side >patch0 &&
- cnt=`grep "^From " patch0 | wc -l` &&
+ cnt=$(grep "^From " patch0 | wc -l) &&
test $cnt = 3
'
@@ -52,7 +52,7 @@ test_expect_success "format-patch --ignore-if-in-upstream" '
git format-patch --stdout \
--ignore-if-in-upstream master..side >patch1 &&
- cnt=`grep "^From " patch1 | wc -l` &&
+ cnt=$(grep "^From " patch1 | wc -l) &&
test $cnt = 2
'
@@ -69,7 +69,7 @@ test_expect_success "format-patch doesn't consider merge commits" '
git checkout -b merger master &&
test_tick &&
git merge --no-ff slave &&
- cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` &&
+ cnt=$(git format-patch -3 --stdout | grep "^From " | wc -l) &&
test $cnt = 3
'
@@ -77,7 +77,7 @@ test_expect_success "format-patch result applies" '
git checkout -b rebuild-0 master &&
git am -3 patch0 &&
- cnt=`git rev-list master.. | wc -l` &&
+ cnt=$(git rev-list master.. | wc -l) &&
test $cnt = 2
'
@@ -85,7 +85,7 @@ test_expect_success "format-patch --ignore-if-in-upstream result applies" '
git checkout -b rebuild-1 master &&
git am -3 patch1 &&
- cnt=`git rev-list master.. | wc -l` &&
+ cnt=$(git rev-list master.. | wc -l) &&
test $cnt = 2
'
@@ -762,24 +762,77 @@ test_expect_success 'format-patch --signature="" suppresses signatures' '
! grep "^-- \$" output
'
+test_expect_success 'prepare mail-signature input' '
+ cat >mail-signature <<-\EOF
+
+ Test User <test.email@kernel.org>
+ http://git.kernel.org/cgit/git/git.git
+
+ git.kernel.org/?p=git/git.git;a=summary
+
+ EOF
+'
+
+test_expect_success '--signature-file=file works' '
+ git format-patch --stdout --signature-file=mail-signature -1 >output &&
+ check_patch output &&
+ sed -e "1,/^-- \$/d" <output >actual &&
+ {
+ cat mail-signature && echo
+ } >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'format.signaturefile works' '
+ test_config format.signaturefile mail-signature &&
+ git format-patch --stdout -1 >output &&
+ check_patch output &&
+ sed -e "1,/^-- \$/d" <output >actual &&
+ {
+ cat mail-signature && echo
+ } >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success '--no-signature suppresses format.signaturefile ' '
+ test_config format.signaturefile mail-signature &&
+ git format-patch --stdout --no-signature -1 >output &&
+ check_patch output &&
+ ! grep "^-- \$" output
+'
+
+test_expect_success '--signature-file overrides format.signaturefile' '
+ cat >other-mail-signature <<-\EOF
+ Use this other signature instead of mail-signature.
+ EOF
+ test_config format.signaturefile mail-signature &&
+ git format-patch --stdout \
+ --signature-file=other-mail-signature -1 >output &&
+ check_patch output &&
+ sed -e "1,/^-- \$/d" <output >actual &&
+ {
+ cat other-mail-signature && echo
+ } >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success '--signature overrides format.signaturefile' '
+ test_config format.signaturefile mail-signature &&
+ git format-patch --stdout --signature="my sig" -1 >output &&
+ check_patch output &&
+ grep "my sig" output
+'
+
test_expect_success TTY 'format-patch --stdout paginates' '
rm -f pager_used &&
- (
- GIT_PAGER="wc >pager_used" &&
- export GIT_PAGER &&
- test_terminal git format-patch --stdout --all
- ) &&
+ test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
test_path_is_file pager_used
'
test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
rm -f pager_used &&
- (
- GIT_PAGER="wc >pager_used" &&
- export GIT_PAGER &&
- test_terminal git --no-pager format-patch --stdout --all &&
- test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
- ) &&
+ test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
+ test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
test_path_is_missing pager_used &&
test_path_is_missing .git/pager_used
'
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 38a092a0da..1dbaa3864a 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -7,179 +7,103 @@ test_description='Test custom diff function name patterns'
. ./test-lib.sh
-LF='
-'
-cat >Beer.java <<\EOF
-public class Beer
-{
- int special;
- public static void main(String args[])
- {
- String s=" ";
- for(int x = 99; x > 0; x--)
- {
- System.out.print(x + " bottles of beer on the wall "
- + x + " bottles of beer\n"
- + "Take one down, pass it around, " + (x - 1)
- + " bottles of beer on the wall.\n");
- }
- System.out.print("Go to the store, buy some more,\n"
- + "99 bottles of beer on the wall.\n");
- }
-}
-EOF
-sed 's/beer\\/beer,\\/' <Beer.java >Beer-correct.java
-cat >Beer.perl <<\EOT
-package Beer;
-
-use strict;
-use warnings;
-use parent qw(Exporter);
-our @EXPORT_OK = qw(round finalround);
-
-sub other; # forward declaration
-
-# hello
-
-sub round {
- my ($n) = @_;
- print "$n bottles of beer on the wall ";
- print "$n bottles of beer\n";
- print "Take one down, pass it around, ";
- $n = $n - 1;
- print "$n bottles of beer on the wall.\n";
-}
-
-sub finalround
-{
- print "Go to the store, buy some more\n";
- print "99 bottles of beer on the wall.\n");
-}
-
-sub withheredocument {
- print <<"EOF"
-decoy here-doc
-EOF
- # some lines of context
- # to pad it out
- print "hello\n";
-}
-
-__END__
-
-=head1 NAME
-
-Beer - subroutine to output fragment of a drinking song
-
-=head1 SYNOPSIS
-
- use Beer qw(round finalround);
-
- sub song {
- for (my $i = 99; $i > 0; $i--) {
- round $i;
- }
- finalround;
- }
+test_expect_success 'setup' '
+ # a non-trivial custom pattern
+ git config diff.custom1.funcname "!static
+!String
+[^ ].*s.*" &&
- song;
+ # a custom pattern which matches to end of line
+ git config diff.custom2.funcname "......Beer\$" &&
-=cut
-EOT
-sed -e '
- s/hello/goodbye/
- s/beer\\/beer,\\/
- s/more\\/more,\\/
- s/song;/song();/
-' <Beer.perl >Beer-correct.perl
+ # alternation in pattern
+ git config diff.custom3.funcname "Beer$" &&
+ git config diff.custom3.xfuncname "^[ ]*((public|static).*)$" &&
-test_expect_funcname () {
- lang=${2-java}
- test_expect_code 1 git diff --no-index -U1 \
- "Beer.$lang" "Beer-correct.$lang" >diff &&
- grep "^@@.*@@ $1" diff
-}
+ # for regexp compilation tests
+ echo A >A.java &&
+ echo B >B.java
+'
-for p in ada bibtex cpp csharp fortran html java matlab objc pascal perl php python ruby tex
+diffpatterns="
+ ada
+ bibtex
+ cpp
+ csharp
+ fortran
+ html
+ java
+ matlab
+ objc
+ pascal
+ perl
+ php
+ python
+ ruby
+ tex
+ custom1
+ custom2
+ custom3
+"
+
+for p in $diffpatterns
do
test_expect_success "builtin $p pattern compiles" '
echo "*.java diff=$p" >.gitattributes &&
test_expect_code 1 git diff --no-index \
- Beer.java Beer-correct.java 2>msg &&
- ! grep fatal msg &&
- ! grep error msg
+ A.java B.java 2>msg &&
+ test_i18ngrep ! fatal msg &&
+ test_i18ngrep ! error msg
'
test_expect_success "builtin $p wordRegex pattern compiles" '
echo "*.java diff=$p" >.gitattributes &&
test_expect_code 1 git diff --no-index --word-diff \
- Beer.java Beer-correct.java 2>msg &&
- ! grep fatal msg &&
- ! grep error msg
+ A.java B.java 2>msg &&
+ test_i18ngrep ! fatal msg &&
+ test_i18ngrep ! error msg
'
done
-test_expect_success 'default behaviour' '
- rm -f .gitattributes &&
- test_expect_funcname "public class Beer\$"
-'
-
-test_expect_success 'set up .gitattributes declaring drivers to test' '
- cat >.gitattributes <<-\EOF
- *.java diff=java
- *.perl diff=perl
- EOF
-'
-
-test_expect_success 'preset java pattern' '
- test_expect_funcname "public static void main("
-'
-
-test_expect_success 'preset perl pattern' '
- test_expect_funcname "sub round {\$" perl
-'
-
-test_expect_success 'perl pattern accepts K&R style brace placement, too' '
- test_expect_funcname "sub finalround\$" perl
-'
-
-test_expect_success 'but is not distracted by end of <<here document' '
- test_expect_funcname "sub withheredocument {\$" perl
-'
-
-test_expect_success 'perl pattern is not distracted by sub within POD' '
- test_expect_funcname "=head" perl
-'
-
-test_expect_success 'perl pattern gets full line of POD header' '
- test_expect_funcname "=head1 SYNOPSIS\$" perl
-'
-
-test_expect_success 'perl pattern is not distracted by forward declaration' '
- test_expect_funcname "package Beer;\$" perl
-'
-
-test_expect_success 'custom pattern' '
- test_config diff.java.funcname "!static
-!String
-[^ ].*s.*" &&
- test_expect_funcname "int special;\$"
-'
-
test_expect_success 'last regexp must not be negated' '
+ echo "*.java diff=java" >.gitattributes &&
test_config diff.java.funcname "!static" &&
- test_expect_code 128 git diff --no-index Beer.java Beer-correct.java 2>msg &&
- grep ": Last expression must not be negated:" msg
+ test_expect_code 128 git diff --no-index A.java B.java 2>msg &&
+ test_i18ngrep ": Last expression must not be negated:" msg
'
-test_expect_success 'pattern which matches to end of line' '
- test_config diff.java.funcname "Beer\$" &&
- test_expect_funcname "Beer\$"
+test_expect_success 'setup hunk header tests' '
+ for i in $diffpatterns
+ do
+ echo "$i-* diff=$i"
+ done > .gitattributes &&
+
+ # add all test files to the index
+ (
+ cd "$TEST_DIRECTORY"/t4018 &&
+ git --git-dir="$TRASH_DIRECTORY/.git" add .
+ ) &&
+
+ # place modified files in the worktree
+ for i in $(git ls-files)
+ do
+ sed -e "s/ChangeMe/IWasChanged/" <"$TEST_DIRECTORY/t4018/$i" >"$i" || return 1
+ done
'
-test_expect_success 'alternation in pattern' '
- test_config diff.java.funcname "Beer$" &&
- test_config diff.java.xfuncname "^[ ]*((public|static).*)$" &&
- test_expect_funcname "public static void main("
-'
+# check each individual file
+for i in $(git ls-files)
+do
+ if grep broken "$i" >/dev/null 2>&1
+ then
+ result=failure
+ else
+ result=success
+ fi
+ test_expect_$result "hunk header: $i" "
+ test_when_finished 'cat actual' && # for debugging only
+ git diff -U1 $i >actual &&
+ grep '@@ .* @@.*RIGHT' actual
+ "
+done
test_done
diff --git a/t/t4018/README b/t/t4018/README
new file mode 100644
index 0000000000..283e01cca1
--- /dev/null
+++ b/t/t4018/README
@@ -0,0 +1,18 @@
+How to write RIGHT test cases
+=============================
+
+Insert the word "ChangeMe" (exactly this form) at a distance of
+at least two lines from the line that must appear in the hunk header.
+
+The text that must appear in the hunk header must contain the word
+"right", but in all upper-case, like in the title above.
+
+To mark a test case that highlights a malfunction, insert the word
+BROKEN in all lower-case somewhere in the file.
+
+This text is a bit twisted and out of order, but it is itself a
+test case for the default hunk header pattern. Know what you are doing
+if you change it.
+
+BTW, this tests that the head line goes to the hunk header, not the line
+of equal signs.
diff --git a/t/t4018/cpp-c++-function b/t/t4018/cpp-c++-function
new file mode 100644
index 0000000000..9ee6bbef55
--- /dev/null
+++ b/t/t4018/cpp-c++-function
@@ -0,0 +1,4 @@
+Item RIGHT::DoSomething( Args with_spaces )
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-class-constructor b/t/t4018/cpp-class-constructor
new file mode 100644
index 0000000000..ec4f115c25
--- /dev/null
+++ b/t/t4018/cpp-class-constructor
@@ -0,0 +1,4 @@
+Item::Item(int RIGHT)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-class-constructor-mem-init b/t/t4018/cpp-class-constructor-mem-init
new file mode 100644
index 0000000000..49a69f37e1
--- /dev/null
+++ b/t/t4018/cpp-class-constructor-mem-init
@@ -0,0 +1,5 @@
+Item::Item(int RIGHT) :
+ member(0)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-class-definition b/t/t4018/cpp-class-definition
new file mode 100644
index 0000000000..11b61da3b7
--- /dev/null
+++ b/t/t4018/cpp-class-definition
@@ -0,0 +1,4 @@
+class RIGHT
+{
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-class-definition-derived b/t/t4018/cpp-class-definition-derived
new file mode 100644
index 0000000000..3b98cd09ab
--- /dev/null
+++ b/t/t4018/cpp-class-definition-derived
@@ -0,0 +1,5 @@
+class RIGHT :
+ public Baseclass
+{
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-class-destructor b/t/t4018/cpp-class-destructor
new file mode 100644
index 0000000000..5487665096
--- /dev/null
+++ b/t/t4018/cpp-class-destructor
@@ -0,0 +1,4 @@
+RIGHT::~RIGHT()
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-function-returning-global-type b/t/t4018/cpp-function-returning-global-type
new file mode 100644
index 0000000000..1084d5990e
--- /dev/null
+++ b/t/t4018/cpp-function-returning-global-type
@@ -0,0 +1,4 @@
+::Item get::it::RIGHT()
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-function-returning-nested b/t/t4018/cpp-function-returning-nested
new file mode 100644
index 0000000000..d9750aa61a
--- /dev/null
+++ b/t/t4018/cpp-function-returning-nested
@@ -0,0 +1,5 @@
+get::Item get::it::RIGHT()
+{
+ ChangeMe;
+}
+
diff --git a/t/t4018/cpp-function-returning-pointer b/t/t4018/cpp-function-returning-pointer
new file mode 100644
index 0000000000..ef15657ea8
--- /dev/null
+++ b/t/t4018/cpp-function-returning-pointer
@@ -0,0 +1,4 @@
+const char *get_it_RIGHT(char *ptr)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-function-returning-reference b/t/t4018/cpp-function-returning-reference
new file mode 100644
index 0000000000..01b051df70
--- /dev/null
+++ b/t/t4018/cpp-function-returning-reference
@@ -0,0 +1,4 @@
+string& get::it::RIGHT(char *ptr)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-gnu-style-function b/t/t4018/cpp-gnu-style-function
new file mode 100644
index 0000000000..08c7c7565a
--- /dev/null
+++ b/t/t4018/cpp-gnu-style-function
@@ -0,0 +1,5 @@
+const char *
+RIGHT(int arg)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-namespace-definition b/t/t4018/cpp-namespace-definition
new file mode 100644
index 0000000000..6749980241
--- /dev/null
+++ b/t/t4018/cpp-namespace-definition
@@ -0,0 +1,4 @@
+namespace RIGHT
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-operator-definition b/t/t4018/cpp-operator-definition
new file mode 100644
index 0000000000..1acd827159
--- /dev/null
+++ b/t/t4018/cpp-operator-definition
@@ -0,0 +1,4 @@
+Value operator+(Value LEFT, Value RIGHT)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-skip-access-specifiers b/t/t4018/cpp-skip-access-specifiers
new file mode 100644
index 0000000000..4d4a9dbb9d
--- /dev/null
+++ b/t/t4018/cpp-skip-access-specifiers
@@ -0,0 +1,8 @@
+class RIGHT : public Baseclass
+{
+public:
+protected:
+private:
+ void DoSomething();
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-skip-comment-block b/t/t4018/cpp-skip-comment-block
new file mode 100644
index 0000000000..3800b9967a
--- /dev/null
+++ b/t/t4018/cpp-skip-comment-block
@@ -0,0 +1,9 @@
+struct item RIGHT(int i)
+// Do not
+// pick up
+/* these
+** comments.
+*/
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-skip-labels b/t/t4018/cpp-skip-labels
new file mode 100644
index 0000000000..b9c10aba22
--- /dev/null
+++ b/t/t4018/cpp-skip-labels
@@ -0,0 +1,8 @@
+void RIGHT (void)
+{
+repeat: // C++ comment
+next: /* C comment */
+ do_something();
+
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-struct-definition b/t/t4018/cpp-struct-definition
new file mode 100644
index 0000000000..521c59fd15
--- /dev/null
+++ b/t/t4018/cpp-struct-definition
@@ -0,0 +1,9 @@
+struct RIGHT {
+ unsigned
+ /* this bit field looks like a label and should not be picked up */
+ decoy_bitfield: 2,
+ more : 1;
+ int filler;
+
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-struct-single-line b/t/t4018/cpp-struct-single-line
new file mode 100644
index 0000000000..a0de5fb800
--- /dev/null
+++ b/t/t4018/cpp-struct-single-line
@@ -0,0 +1,7 @@
+void wrong()
+{
+}
+
+struct RIGHT_iterator_tag {};
+
+int ChangeMe;
diff --git a/t/t4018/cpp-template-function-definition b/t/t4018/cpp-template-function-definition
new file mode 100644
index 0000000000..0cdf5ba5bd
--- /dev/null
+++ b/t/t4018/cpp-template-function-definition
@@ -0,0 +1,4 @@
+template<class T> int RIGHT(T arg)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/cpp-union-definition b/t/t4018/cpp-union-definition
new file mode 100644
index 0000000000..7ec94df697
--- /dev/null
+++ b/t/t4018/cpp-union-definition
@@ -0,0 +1,4 @@
+union RIGHT {
+ double v;
+ int ChangeMe;
+};
diff --git a/t/t4018/cpp-void-c-function b/t/t4018/cpp-void-c-function
new file mode 100644
index 0000000000..153081e872
--- /dev/null
+++ b/t/t4018/cpp-void-c-function
@@ -0,0 +1,4 @@
+void RIGHT (void)
+{
+ ChangeMe;
+}
diff --git a/t/t4018/custom1-pattern b/t/t4018/custom1-pattern
new file mode 100644
index 0000000000..e8fd59f884
--- /dev/null
+++ b/t/t4018/custom1-pattern
@@ -0,0 +1,17 @@
+public class Beer
+{
+ int special, RIGHT;
+ public static void main(String args[])
+ {
+ String s=" ";
+ for(int x = 99; x > 0; x--)
+ {
+ System.out.print(x + " bottles of beer on the wall "
+ + x + " bottles of beer\n" // ChangeMe
+ + "Take one down, pass it around, " + (x - 1)
+ + " bottles of beer on the wall.\n");
+ }
+ System.out.print("Go to the store, buy some more,\n"
+ + "99 bottles of beer on the wall.\n");
+ }
+}
diff --git a/t/t4018/custom2-match-to-end-of-line b/t/t4018/custom2-match-to-end-of-line
new file mode 100644
index 0000000000..f88ac318b7
--- /dev/null
+++ b/t/t4018/custom2-match-to-end-of-line
@@ -0,0 +1,8 @@
+public class RIGHT_Beer
+{
+ int special;
+ public static void main(String args[])
+ {
+ System.out.print("ChangeMe");
+ }
+}
diff --git a/t/t4018/custom3-alternation-in-pattern b/t/t4018/custom3-alternation-in-pattern
new file mode 100644
index 0000000000..5f3769c64f
--- /dev/null
+++ b/t/t4018/custom3-alternation-in-pattern
@@ -0,0 +1,17 @@
+public class Beer
+{
+ int special;
+ public static void main(String RIGHT[])
+ {
+ String s=" ";
+ for(int x = 99; x > 0; x--)
+ {
+ System.out.print(x + " bottles of beer on the wall "
+ + x + " bottles of beer\n" // ChangeMe
+ + "Take one down, pass it around, " + (x - 1)
+ + " bottles of beer on the wall.\n");
+ }
+ System.out.print("Go to the store, buy some more,\n"
+ + "99 bottles of beer on the wall.\n");
+ }
+}
diff --git a/t/t4018/java-class-member-function b/t/t4018/java-class-member-function
new file mode 100644
index 0000000000..298bc7a71b
--- /dev/null
+++ b/t/t4018/java-class-member-function
@@ -0,0 +1,8 @@
+public class Beer
+{
+ int special;
+ public static void main(String RIGHT[])
+ {
+ System.out.print("ChangeMe");
+ }
+}
diff --git a/t/t4018/perl-skip-end-of-heredoc b/t/t4018/perl-skip-end-of-heredoc
new file mode 100644
index 0000000000..c22d39b256
--- /dev/null
+++ b/t/t4018/perl-skip-end-of-heredoc
@@ -0,0 +1,8 @@
+sub RIGHTwithheredocument {
+ print <<"EOF"
+decoy here-doc
+EOF
+ # some lines of context
+ # to pad it out
+ print "ChangeMe\n";
+}
diff --git a/t/t4018/perl-skip-forward-decl b/t/t4018/perl-skip-forward-decl
new file mode 100644
index 0000000000..a98cb8bdad
--- /dev/null
+++ b/t/t4018/perl-skip-forward-decl
@@ -0,0 +1,10 @@
+package RIGHT;
+
+use strict;
+use warnings;
+use parent qw(Exporter);
+our @EXPORT_OK = qw(round finalround);
+
+sub other; # forward declaration
+
+# ChangeMe
diff --git a/t/t4018/perl-skip-sub-in-pod b/t/t4018/perl-skip-sub-in-pod
new file mode 100644
index 0000000000..e39f02462e
--- /dev/null
+++ b/t/t4018/perl-skip-sub-in-pod
@@ -0,0 +1,18 @@
+=head1 NAME
+
+Beer - subroutine to output fragment of a drinking song
+
+=head1 SYNOPSIS_RIGHT
+
+ use Beer qw(round finalround);
+
+ sub song {
+ for (my $i = 99; $i > 0; $i--) {
+ round $i;
+ }
+ finalround;
+ }
+
+ ChangeMe;
+
+=cut
diff --git a/t/t4018/perl-sub-definition b/t/t4018/perl-sub-definition
new file mode 100644
index 0000000000..a507d1f645
--- /dev/null
+++ b/t/t4018/perl-sub-definition
@@ -0,0 +1,4 @@
+sub RIGHT {
+ my ($n) = @_;
+ print "ChangeMe";
+}
diff --git a/t/t4018/perl-sub-definition-kr-brace b/t/t4018/perl-sub-definition-kr-brace
new file mode 100644
index 0000000000..330b3df114
--- /dev/null
+++ b/t/t4018/perl-sub-definition-kr-brace
@@ -0,0 +1,4 @@
+sub RIGHT
+{
+ print "ChangeMe\n";
+}
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index 8a309795c9..044620186d 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -193,6 +193,19 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
GIT_EXTERNAL_DIFF=echo git diff
'
+test_expect_success 'GIT_EXTERNAL_DIFF path counter/total' '
+ write_script external-diff.sh <<-\EOF &&
+ echo $GIT_DIFF_PATH_COUNTER of $GIT_DIFF_PATH_TOTAL >>counter.txt
+ EOF
+ >counter.txt &&
+ cat >expect <<-\EOF &&
+ 1 of 2
+ 2 of 2
+ EOF
+ GIT_EXTERNAL_DIFF=./external-diff.sh git diff &&
+ test_cmp expect counter.txt
+'
+
test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' '
touch file.ext &&
git add file.ext &&
@@ -213,12 +226,13 @@ keep_only_cr () {
}
test_expect_success 'external diff with autocrlf = true' '
- git config core.autocrlf true &&
+ test_config core.autocrlf true &&
GIT_EXTERNAL_DIFF=./fake-diff.sh git diff &&
test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c)
'
test_expect_success 'diff --cached' '
+ test_config core.autocrlf true &&
git add file &&
git update-index --assume-unchanged file &&
echo second >file &&
@@ -226,4 +240,31 @@ test_expect_success 'diff --cached' '
test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual
'
+test_expect_success 'clean up crlf leftovers' '
+ git update-index --no-assume-unchanged file &&
+ rm -f file* &&
+ git reset --hard
+'
+
+test_expect_success 'submodule diff' '
+ git init sub &&
+ ( cd sub && test_commit sub1 ) &&
+ git add sub &&
+ test_tick &&
+ git commit -m "add submodule" &&
+ ( cd sub && test_commit sub2 ) &&
+ write_script gather_pre_post.sh <<-\EOF &&
+ echo "$1 $4" # path, mode
+ cat "$2" # old file
+ cat "$5" # new file
+ EOF
+ GIT_EXTERNAL_DIFF=./gather_pre_post.sh git diff >actual &&
+ cat >expected <<-EOF &&
+ sub 160000
+ Subproject commit $(git rev-parse HEAD:sub)
+ Subproject commit $(cd sub && git rev-parse HEAD)
+ EOF
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t4034/ada/expect b/t/t4034/ada/expect
index be2376e904..a682d288b2 100644
--- a/t/t4034/ada/expect
+++ b/t/t4034/ada/expect
@@ -4,7 +4,7 @@
<BOLD>+++ b/post<RESET>
<CYAN>@@ -1,13 +1,13 @@<RESET>
Ada.Text_IO.Put_Line("Hello World<RED>!<RESET><GREEN>?<RESET>");
-1 1e<RED>-<RESET>10 16#FE12#E2 3.141_592 '<RED>x<RESET><GREEN>y<RESET>'
+1 <RED>1e-10<RESET><GREEN>1e10<RESET> 16#FE12#E2 3.141_592 '<RED>x<RESET><GREEN>y<RESET>'
<RED>a<RESET><GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET>
<RED>a<RESET><GREEN>y<RESET>
<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b<RESET>
diff --git a/t/t4035-diff-quiet.sh b/t/t4035-diff-quiet.sh
index 231412d100..e8ae2a03fd 100755
--- a/t/t4035-diff-quiet.sh
+++ b/t/t4035-diff-quiet.sh
@@ -148,4 +148,10 @@ test_expect_success 'git diff --ignore-all-space, both files outside repo' '
)
'
+test_expect_success 'git diff --quiet ignores stat-change only entries' '
+ test-chmtime +10 a &&
+ echo modified >>b &&
+ test_expect_code 1 git diff --quiet
+'
+
test_done
diff --git a/t/t4036-format-patch-signer-mime.sh b/t/t4036-format-patch-signer-mime.sh
index ba43f18549..98d9713d8b 100755
--- a/t/t4036-format-patch-signer-mime.sh
+++ b/t/t4036-format-patch-signer-mime.sh
@@ -42,7 +42,7 @@ test_expect_success 'attach and signoff do not duplicate mime headers' '
GIT_COMMITTER_NAME="ã¯ã¾ã® ãµã«ãŠã†" \
git format-patch -s --stdout -1 --attach >output &&
- test `grep -ci ^MIME-Version: output` = 1
+ test $(grep -ci ^MIME-Version: output) = 1
'
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index 1019d7b35f..0b4f7dfdc6 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -94,7 +94,7 @@ test_expect_success 'setup for --cc --raw' '
blob=$(echo file | git hash-object --stdin -w) &&
base_tree=$(echo "100644 blob $blob file" | git mktree) &&
trees= &&
- for i in `test_seq 1 40`
+ for i in $(test_seq 1 40)
do
blob=$(echo file$i | git hash-object --stdin -w) &&
trees="$trees$(echo "100644 blob $blob file" | git mktree)$LF"
@@ -401,4 +401,38 @@ test_expect_success 'combine diff missing delete bug' '
compare_diff_patch expected actual
'
+test_expect_success 'combine diff gets tree sorting right' '
+ # create a directory and a file that sort differently in trees
+ # versus byte-wise (implied "/" sorts after ".")
+ git checkout -f master &&
+ mkdir foo &&
+ echo base >foo/one &&
+ echo base >foo/two &&
+ echo base >foo.ext &&
+ git add foo foo.ext &&
+ git commit -m base &&
+
+ # one side modifies a file in the directory, along with the root
+ # file...
+ echo master >foo/one &&
+ echo master >foo.ext &&
+ git commit -a -m master &&
+
+ # the other side modifies the other file in the directory
+ git checkout -b other HEAD^ &&
+ echo other >foo/two &&
+ git commit -a -m other &&
+
+ # And now we merge. The files in the subdirectory will resolve cleanly,
+ # meaning that a combined diff will not find them interesting. But it
+ # will find the tree itself interesting, because it had to be merged.
+ git checkout master &&
+ git merge other &&
+
+ printf "MM\tfoo\n" >expect &&
+ git diff-tree -c --name-status -t HEAD >actual.tmp &&
+ sed 1d <actual.tmp >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4039-diff-assume-unchanged.sh b/t/t4039-diff-assume-unchanged.sh
index 9d9498bd95..23c0e357a7 100755
--- a/t/t4039-diff-assume-unchanged.sh
+++ b/t/t4039-diff-assume-unchanged.sh
@@ -28,4 +28,15 @@ test_expect_success 'diff-files does not examine assume-unchanged entries' '
test -z "$(git diff-files -- one)"
'
+test_expect_success POSIXPERM 'find-copies-harder is not confused by mode bits' '
+ echo content >exec &&
+ chmod +x exec &&
+ git add exec &&
+ git commit -m exec &&
+ git update-index --assume-unchanged exec &&
+ >expect &&
+ git diff-files --find-copies-harder -- exec >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh
index 1751c83307..e4328964a7 100755
--- a/t/t4041-diff-submodule-option.sh
+++ b/t/t4041-diff-submodule-option.sh
@@ -11,6 +11,9 @@ This test tries to verify the sanity of the --submodule option of git diff.
. ./test-lib.sh
+# Tested non-UTF-8 encoding
+test_encoding="ISO8859-1"
+
# String "added" in German (translated with Google Translate), encoded in UTF-8,
# used in sample commit log messages in add_file() function below.
added=$(printf "hinzugef\303\274gt")
@@ -23,8 +26,10 @@ add_file () {
echo "$name" >"$name" &&
git add "$name" &&
test_tick &&
- msg_added_iso88591=$(echo "Add $name ($added $name)" | iconv -f utf-8 -t iso8859-1) &&
- git -c 'i18n.commitEncoding=iso8859-1' commit -m "$msg_added_iso88591"
+ # "git commit -m" would break MinGW, as Windows refuse to pass
+ # $test_encoding encoded parameter to git.
+ echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding |
+ git -c "i18n.commitEncoding=$test_encoding" commit -F -
done >/dev/null &&
git rev-parse --short --verify HEAD
)
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 979e98398b..2ab3c48734 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -29,4 +29,30 @@ test_expect_success 'git diff --no-index relative path outside repo' '
)
'
+test_expect_success 'git diff --no-index with broken index' '
+ (
+ cd repo &&
+ echo broken >.git/index &&
+ git diff --no-index a ../non/git/a
+ )
+'
+
+test_expect_success 'git diff outside repo with broken index' '
+ (
+ cd repo &&
+ git diff ../non/git/a ../non/git/b
+ )
+'
+
+test_expect_success 'git diff --no-index executed outside repo gives correct error message' '
+ (
+ GIT_CEILING_DIRECTORIES=$TRASH_DIRECTORY/non &&
+ export GIT_CEILING_DIRECTORIES &&
+ cd non/git &&
+ test_must_fail git diff --no-index a 2>actual.err &&
+ echo "usage: git diff --no-index <path> <path>" >expect.err &&
+ test_cmp expect.err actual.err
+ )
+'
+
test_done
diff --git a/t/t4055-diff-context.sh b/t/t4055-diff-context.sh
index cd0454356a..741e0803c1 100755
--- a/t/t4055-diff-context.sh
+++ b/t/t4055-diff-context.sh
@@ -79,7 +79,7 @@ test_expect_success 'non-integer config parsing' '
test_expect_success 'negative integer config parsing' '
git config diff.context -1 &&
test_must_fail git diff 2>output &&
- test_i18ngrep "bad config file" output
+ test_i18ngrep "bad config variable" output
'
test_expect_success '-U0 is valid, so is diff.context=0' '
diff --git a/t/t4056-diff-order.sh b/t/t4056-diff-order.sh
new file mode 100755
index 0000000000..c0460bb0e5
--- /dev/null
+++ b/t/t4056-diff-order.sh
@@ -0,0 +1,121 @@
+#!/bin/sh
+
+test_description='diff order'
+
+. ./test-lib.sh
+
+create_files () {
+ echo "$1" >a.h &&
+ echo "$1" >b.c &&
+ echo "$1" >c/Makefile &&
+ echo "$1" >d.txt &&
+ git add a.h b.c c/Makefile d.txt &&
+ git commit -m"$1"
+}
+
+test_expect_success 'setup' '
+ mkdir c &&
+ create_files 1 &&
+ create_files 2 &&
+
+ cat >order_file_1 <<-\EOF &&
+ *Makefile
+ *.txt
+ *.h
+ EOF
+
+ cat >order_file_2 <<-\EOF &&
+ *Makefile
+ *.h
+ *.c
+ EOF
+
+ cat >expect_none <<-\EOF &&
+ a.h
+ b.c
+ c/Makefile
+ d.txt
+ EOF
+
+ cat >expect_1 <<-\EOF &&
+ c/Makefile
+ d.txt
+ a.h
+ b.c
+ EOF
+
+ cat >expect_2 <<-\EOF
+ c/Makefile
+ a.h
+ b.c
+ d.txt
+ EOF
+'
+
+test_expect_success "no order (=tree object order)" '
+ git diff --name-only HEAD^..HEAD >actual &&
+ test_cmp expect_none actual
+'
+
+test_expect_success 'missing orderfile' '
+ rm -f bogus_file &&
+ test_must_fail git diff -Obogus_file --name-only HEAD^..HEAD
+'
+
+test_expect_success POSIXPERM,SANITY 'unreadable orderfile' '
+ >unreadable_file &&
+ chmod -r unreadable_file &&
+ test_must_fail git diff -Ounreadable_file --name-only HEAD^..HEAD
+'
+
+for i in 1 2
+do
+ test_expect_success "orderfile using option ($i)" '
+ git diff -Oorder_file_$i --name-only HEAD^..HEAD >actual &&
+ test_cmp expect_$i actual
+ '
+
+ test_expect_success PIPE "orderfile is fifo ($i)" '
+ rm -f order_fifo &&
+ mkfifo order_fifo &&
+ {
+ cat order_file_$i >order_fifo &
+ } &&
+ git diff -O order_fifo --name-only HEAD^..HEAD >actual &&
+ wait &&
+ test_cmp expect_$i actual
+ '
+
+ test_expect_success "orderfile using config ($i)" '
+ git -c diff.orderfile=order_file_$i diff --name-only HEAD^..HEAD >actual &&
+ test_cmp expect_$i actual
+ '
+
+ test_expect_success "cancelling configured orderfile ($i)" '
+ git -c diff.orderfile=order_file_$i diff -O/dev/null --name-only HEAD^..HEAD >actual &&
+ test_cmp expect_none actual
+ '
+done
+
+test_expect_success 'setup for testing combine-diff order' '
+ git checkout -b tmp HEAD~ &&
+ create_files 3 &&
+ git checkout master &&
+ git merge --no-commit -s ours tmp &&
+ create_files 5
+'
+
+test_expect_success "combine-diff: no order (=tree object order)" '
+ git diff --name-only HEAD HEAD^ HEAD^2 >actual &&
+ test_cmp expect_none actual
+'
+
+for i in 1 2
+do
+ test_expect_success "combine-diff: orderfile using option ($i)" '
+ git diff -Oorder_file_$i --name-only HEAD HEAD^ HEAD^2 >actual &&
+ test_cmp expect_$i actual
+ '
+done
+
+test_done
diff --git a/t/t4057-diff-combined-paths.sh b/t/t4057-diff-combined-paths.sh
new file mode 100755
index 0000000000..dff36b77ec
--- /dev/null
+++ b/t/t4057-diff-combined-paths.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+test_description='combined diff show only paths that are different to all parents'
+
+. ./test-lib.sh
+
+# verify that diffc.expect matches output of
+# $(git diff -c --name-only HEAD HEAD^ HEAD^2)
+diffc_verify () {
+ git diff -c --name-only HEAD HEAD^ HEAD^2 >diffc.actual &&
+ test_cmp diffc.expect diffc.actual
+}
+
+test_expect_success 'trivial merge - combine-diff empty' '
+ for i in $(test_seq 1 9)
+ do
+ echo $i >$i.txt &&
+ git add $i.txt
+ done &&
+ git commit -m "init" &&
+ git checkout -b side &&
+ for i in $(test_seq 2 9)
+ do
+ echo $i/2 >>$i.txt
+ done &&
+ git commit -a -m "side 2-9" &&
+ git checkout master &&
+ echo 1/2 >1.txt &&
+ git commit -a -m "master 1" &&
+ git merge side &&
+ >diffc.expect &&
+ diffc_verify
+'
+
+
+test_expect_success 'only one trully conflicting path' '
+ git checkout side &&
+ for i in $(test_seq 2 9)
+ do
+ echo $i/3 >>$i.txt
+ done &&
+ echo "4side" >>4.txt &&
+ git commit -a -m "side 2-9 +4" &&
+ git checkout master &&
+ for i in $(test_seq 1 9)
+ do
+ echo $i/3 >>$i.txt
+ done &&
+ echo "4master" >>4.txt &&
+ git commit -a -m "master 1-9 +4" &&
+ test_must_fail git merge side &&
+ cat <<-\EOF >4.txt &&
+ 4
+ 4/2
+ 4/3
+ 4master
+ 4side
+ EOF
+ git add 4.txt &&
+ git commit -m "merge side (2)" &&
+ echo 4.txt >diffc.expect &&
+ diffc_verify
+'
+
+test_expect_success 'merge introduces new file' '
+ git checkout side &&
+ for i in $(test_seq 5 9)
+ do
+ echo $i/4 >>$i.txt
+ done &&
+ git commit -a -m "side 5-9" &&
+ git checkout master &&
+ for i in $(test_seq 1 3)
+ do
+ echo $i/4 >>$i.txt
+ done &&
+ git commit -a -m "master 1-3 +4hello" &&
+ git merge side &&
+ echo "Hello World" >4hello.txt &&
+ git add 4hello.txt &&
+ git commit --amend &&
+ echo 4hello.txt >diffc.expect &&
+ diffc_verify
+'
+
+test_expect_success 'merge removed a file' '
+ git checkout side &&
+ for i in $(test_seq 5 9)
+ do
+ echo $i/5 >>$i.txt
+ done &&
+ git commit -a -m "side 5-9" &&
+ git checkout master &&
+ for i in $(test_seq 1 3)
+ do
+ echo $i/4 >>$i.txt
+ done &&
+ git commit -a -m "master 1-3" &&
+ git merge side &&
+ git rm 4.txt &&
+ git commit --amend &&
+ echo 4.txt >diffc.expect &&
+ diffc_verify
+'
+
+test_done
diff --git a/t/t4102-apply-rename.sh b/t/t4102-apply-rename.sh
index e3ea3d5114..fae305979a 100755
--- a/t/t4102-apply-rename.sh
+++ b/t/t4102-apply-rename.sh
@@ -7,7 +7,6 @@ test_description='git apply handling copy/rename patch.
'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
# setup
@@ -53,6 +52,6 @@ EOF
test_expect_success 'apply copy' \
'git apply --index --stat --summary --apply test-patch &&
- test "$(cat bar)" = "This is bar" -a "$(cat foo)" = "This is foo"'
+ test "$(cat bar)" = "This is bar" && test "$(cat foo)" = "This is foo"'
test_done
diff --git a/t/t4107-apply-ignore-whitespace.sh b/t/t4107-apply-ignore-whitespace.sh
index b04fc8fc12..9e29b5262d 100755
--- a/t/t4107-apply-ignore-whitespace.sh
+++ b/t/t4107-apply-ignore-whitespace.sh
@@ -111,7 +111,6 @@ sed -e 's/T/ /g' > main.c.final <<\EOF
#include <stdio.h>
void print_int(int num);
-T/* a comment */
int func(int num);
int main() {
@@ -154,7 +153,8 @@ test_expect_success 'patch2 reverse applies with --ignore-space-change' '
git config apply.ignorewhitespace change
test_expect_success 'patch2 applies (apply.ignorewhitespace = change)' '
- git apply patch2.patch
+ git apply patch2.patch &&
+ test_cmp main.c.final main.c
'
test_expect_success 'patch3 fails (missing string at EOL)' '
@@ -165,12 +165,8 @@ test_expect_success 'patch4 fails (missing EOL at EOF)' '
test_must_fail git apply patch4.patch
'
-test_expect_success 'patch5 applies (leading whitespace)' '
- git apply patch5.patch
-'
-
-test_expect_success 'patches do not mangle whitespace' '
- test_cmp main.c main.c.final
+test_expect_success 'patch5 fails (leading whitespace differences matter)' '
+ test_must_fail git apply patch5.patch
'
test_expect_success 're-create file (with --ignore-whitespace)' '
diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh
index 2298ece801..ce8567f496 100755
--- a/t/t4116-apply-reverse.sh
+++ b/t/t4116-apply-reverse.sh
@@ -30,10 +30,10 @@ test_expect_success setup '
test_expect_success 'apply in forward' '
- T0=`git rev-parse "second^{tree}"` &&
+ T0=$(git rev-parse "second^{tree}") &&
git reset --hard initial &&
git apply --index --binary patch &&
- T1=`git write-tree` &&
+ T1=$(git write-tree) &&
test "$T0" = "$T1"
'
@@ -48,12 +48,12 @@ test_expect_success 'apply in reverse' '
test_expect_success 'setup separate repository lacking postimage' '
- git tar-tree initial initial | $TAR xf - &&
+ git archive --format=tar --prefix=initial/ initial | $TAR xf - &&
(
cd initial && git init && git add .
) &&
- git tar-tree second second | $TAR xf - &&
+ git archive --format=tar --prefix=second/ second | $TAR xf - &&
(
cd second && git init && git add .
)
@@ -62,22 +62,22 @@ test_expect_success 'setup separate repository lacking postimage' '
test_expect_success 'apply in forward without postimage' '
- T0=`git rev-parse "second^{tree}"` &&
+ T0=$(git rev-parse "second^{tree}") &&
(
cd initial &&
git apply --index --binary ../patch &&
- T1=`git write-tree` &&
+ T1=$(git write-tree) &&
test "$T0" = "$T1"
)
'
test_expect_success 'apply in reverse without postimage' '
- T0=`git rev-parse "initial^{tree}"` &&
+ T0=$(git rev-parse "initial^{tree}") &&
(
cd second &&
git apply --index --binary --reverse ../patch &&
- T1=`git write-tree` &&
+ T1=$(git write-tree) &&
test "$T0" = "$T1"
)
'
diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh
index 3d0384daa8..a9a0583811 100755
--- a/t/t4119-apply-config.sh
+++ b/t/t4119-apply-config.sh
@@ -68,7 +68,7 @@ test_expect_success 'apply --whitespace=strip from config' '
check_result sub/file1
'
-D=`pwd`
+D=$(pwd)
test_expect_success 'apply --whitespace=strip in subdir' '
@@ -159,4 +159,21 @@ test_expect_success 'same but with traditional patch input of depth 2' '
check_result sub/file1
'
+test_expect_success 'in subdir with traditional patch input' '
+ cd "$D" &&
+ git config apply.whitespace strip &&
+ cat >.gitattributes <<-EOF &&
+ /* whitespace=blank-at-eol
+ sub/* whitespace=-blank-at-eol
+ EOF
+ rm -f sub/file1 &&
+ cp saved sub/file1 &&
+ git update-index --refresh &&
+
+ cd sub &&
+ git apply ../gpatch.file &&
+ echo "B " >expect &&
+ test_cmp expect file1
+'
+
test_done
diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh
index c5fecdfed4..497b62868d 100755
--- a/t/t4120-apply-popt.sh
+++ b/t/t4120-apply-popt.sh
@@ -6,7 +6,6 @@
test_description='git apply -p handling.'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
test_expect_success setup '
mkdir sub &&
diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh
index 5d0c598338..c6474de4c8 100755
--- a/t/t4124-apply-ws-rule.sh
+++ b/t/t4124-apply-ws-rule.sh
@@ -512,4 +512,15 @@ test_expect_success 'whitespace=fix to expand' '
git -c core.whitespace=tab-in-indent apply --whitespace=fix patch
'
+test_expect_success 'whitespace check skipped for excluded paths' '
+ git config core.whitespace blank-at-eol &&
+ >used &&
+ >unused &&
+ git add used unused &&
+ echo "used" >used &&
+ echo "unused " >unused &&
+ git diff-files -p used unused >patch &&
+ git apply --include=used --stat --whitespace=error <patch
+'
+
test_done
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
index 0d36ebdc86..c268298eaf 100755
--- a/t/t4129-apply-samemode.sh
+++ b/t/t4129-apply-samemode.sh
@@ -3,7 +3,6 @@
test_description='applying patch with mode bits'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
test_expect_success setup '
echo original >file &&
diff --git a/t/t4137-apply-submodule.sh b/t/t4137-apply-submodule.sh
new file mode 100755
index 0000000000..a9bd40a6d0
--- /dev/null
+++ b/t/t4137-apply-submodule.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='git apply handling submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+apply_index () {
+ git diff --ignore-submodules=dirty "..$1" | git apply --index -
+}
+
+test_submodule_switch "apply_index"
+
+apply_3way () {
+ git diff --ignore-submodules=dirty "..$1" | git apply --3way -
+}
+
+test_submodule_switch "apply_3way"
+
+test_done
diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh
index 42866992cf..7600a3e3e8 100755
--- a/t/t4201-shortlog.sh
+++ b/t/t4201-shortlog.sh
@@ -93,7 +93,7 @@ test_expect_success 'output from user-defined format is re-wrapped' '
test_cmp expect log.predictable
'
-test_expect_success 'shortlog wrapping' '
+test_expect_success !MINGW 'shortlog wrapping' '
cat >expect <<\EOF &&
A U Thor (5):
Test
@@ -114,7 +114,7 @@ EOF
test_cmp expect out
'
-test_expect_success 'shortlog from non-git directory' '
+test_expect_success !MINGW 'shortlog from non-git directory' '
git log HEAD >log &&
GIT_DIR=non-existing git shortlog -w <log >out &&
test_cmp expect out
@@ -159,7 +159,7 @@ $DSCHO (2):
EOF
-test_expect_success 'shortlog encoding' '
+test_expect_success !MINGW 'shortlog encoding' '
git reset --hard "$commit" &&
git config --unset i18n.commitencoding &&
echo 2 > a1 &&
@@ -188,4 +188,10 @@ test_expect_success 'shortlog ignores commits with missing authors' '
test_cmp expect actual
'
+test_expect_success 'shortlog with revision pseudo options' '
+ git shortlog --all &&
+ git shortlog --branches &&
+ git shortlog --exclude=refs/heads/m* --all
+'
+
test_done
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index cb03d28769..99ab7ca21f 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -3,6 +3,7 @@
test_description='git log'
. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
test_expect_success setup '
@@ -841,4 +842,34 @@ test_expect_success 'dotdot is a parent directory' '
test_cmp expect actual
'
+test_expect_success GPG 'log --graph --show-signature' '
+ test_when_finished "git reset --hard && git checkout master" &&
+ git checkout -b signed master &&
+ echo foo >foo &&
+ git add foo &&
+ git commit -S -m signed_commit &&
+ git log --graph --show-signature -n1 signed >actual &&
+ grep "^| gpg: Signature made" actual &&
+ grep "^| gpg: Good signature" actual
+'
+
+test_expect_success GPG 'log --graph --show-signature for merged tag' '
+ test_when_finished "git reset --hard && git checkout master" &&
+ git checkout -b plain master &&
+ echo aaa >bar &&
+ git add bar &&
+ git commit -m bar_commit &&
+ git checkout -b tagged master &&
+ echo bbb >baz &&
+ git add baz &&
+ git commit -m baz_commit &&
+ git tag -s -m signed_tag_msg signed_tag &&
+ git checkout plain &&
+ git merge --no-ff -m msg signed_tag &&
+ git log --graph --show-signature -n1 plain >actual &&
+ grep "^|\\\ merged tag" actual &&
+ grep "^| | gpg: Signature made" actual &&
+ grep "^| | gpg: Good signature" actual
+'
+
test_done
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
index d2c930de87..baa9d3c82e 100755
--- a/t/t4204-patch-id.sh
+++ b/t/t4204-patch-id.sh
@@ -5,27 +5,44 @@ test_description='git patch-id'
. ./test-lib.sh
test_expect_success 'setup' '
- test_commit initial foo a &&
- test_commit first foo b &&
- git checkout -b same HEAD^ &&
- test_commit same-msg foo b &&
- git checkout -b notsame HEAD^ &&
- test_commit notsame-msg foo c
+ as="a a a a a a a a" && # eight a
+ test_write_lines $as >foo &&
+ test_write_lines $as >bar &&
+ git add foo bar &&
+ git commit -a -m initial &&
+ test_write_lines $as b >foo &&
+ test_write_lines $as b >bar &&
+ git commit -a -m first &&
+ git checkout -b same master &&
+ git commit --amend -m same-msg &&
+ git checkout -b notsame master &&
+ echo c >foo &&
+ echo c >bar &&
+ git commit --amend -a -m notsame-msg &&
+ test_write_lines bar foo >bar-then-foo &&
+ test_write_lines foo bar >foo-then-bar
'
test_expect_success 'patch-id output is well-formed' '
- git log -p -1 | git patch-id > output &&
+ git log -p -1 | git patch-id >output &&
grep "^[a-f0-9]\{40\} $(git rev-parse HEAD)$" output
'
+#calculate patch id. Make sure output is not empty.
calc_patch_id () {
- git patch-id |
- sed "s# .*##" > patch-id_"$1"
+ name="$1"
+ shift
+ git patch-id "$@" |
+ sed "s/ .*//" >patch-id_"$name" &&
+ test_line_count -gt 0 patch-id_"$name"
+}
+
+get_top_diff () {
+ git log -p -1 "$@" -O bar-then-foo --
}
get_patch_id () {
- git log -p -1 "$1" | git patch-id |
- sed "s# .*##" > patch-id_"$1"
+ get_top_diff "$1" | calc_patch_id "$@"
}
test_expect_success 'patch-id detects equality' '
@@ -45,8 +62,8 @@ test_expect_success 'patch-id supports git-format-patch output' '
git checkout same &&
git format-patch -1 --stdout | calc_patch_id same &&
test_cmp patch-id_master patch-id_same &&
- set `git format-patch -1 --stdout | git patch-id` &&
- test "$2" = `git rev-parse HEAD`
+ set $(git format-patch -1 --stdout | git patch-id) &&
+ test "$2" = $(git rev-parse HEAD)
'
test_expect_success 'whitespace is irrelevant in footer' '
@@ -56,6 +73,69 @@ test_expect_success 'whitespace is irrelevant in footer' '
test_cmp patch-id_master patch-id_same
'
+cmp_patch_id () {
+ if
+ test "$1" = "relevant"
+ then
+ ! test_cmp patch-id_"$2" patch-id_"$3"
+ else
+ test_cmp patch-id_"$2" patch-id_"$3"
+ fi
+}
+
+test_patch_id_file_order () {
+ relevant="$1"
+ shift
+ name="order-${1}-$relevant"
+ shift
+ get_top_diff "master" | calc_patch_id "$name" "$@" &&
+ git checkout same &&
+ git format-patch -1 --stdout -O foo-then-bar |
+ calc_patch_id "ordered-$name" "$@" &&
+ cmp_patch_id $relevant "$name" "ordered-$name"
+
+}
+
+# combined test for options: add more tests here to make them
+# run with all options
+test_patch_id () {
+ test_patch_id_file_order "$@"
+}
+
+# small tests with detailed diagnostic for basic options.
+test_expect_success 'file order is irrelevant with --stable' '
+ test_patch_id_file_order irrelevant --stable --stable
+'
+
+test_expect_success 'file order is relevant with --unstable' '
+ test_patch_id_file_order relevant --unstable --unstable
+'
+
+#Now test various option combinations.
+test_expect_success 'default is unstable' '
+ test_patch_id relevant default
+'
+
+test_expect_success 'patchid.stable = true is stable' '
+ test_config patchid.stable true &&
+ test_patch_id irrelevant patchid.stable=true
+'
+
+test_expect_success 'patchid.stable = false is unstable' '
+ test_config patchid.stable false &&
+ test_patch_id relevant patchid.stable=false
+'
+
+test_expect_success '--unstable overrides patchid.stable = true' '
+ test_config patchid.stable true &&
+ test_patch_id relevant patchid.stable=true--unstable --unstable
+'
+
+test_expect_success '--stable overrides patchid.stable = false' '
+ test_config patchid.stable false &&
+ test_patch_id irrelevant patchid.stable=false--stable --stable
+'
+
test_expect_success 'patch-id supports git-format-patch MIME output' '
get_patch_id master &&
git checkout same &&
diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
index 2a6278bb33..7398605e7b 100755
--- a/t/t4205-log-pretty-formats.sh
+++ b/t/t4205-log-pretty-formats.sh
@@ -7,6 +7,9 @@
test_description='Test pretty formats'
. ./test-lib.sh
+# Tested non-UTF-8 encoding
+test_encoding="ISO8859-1"
+
sample_utf8_part=$(printf "f\303\244ng")
commit_msg () {
@@ -27,8 +30,8 @@ test_expect_success 'set up basic repos' '
>bar &&
git add foo &&
test_tick &&
- git config i18n.commitEncoding iso8859-1 &&
- git commit -m "$(commit_msg iso8859-1)" &&
+ git config i18n.commitEncoding $test_encoding &&
+ commit_msg $test_encoding | git commit -F - &&
git add bar &&
test_tick &&
git commit -m "add bar" &&
@@ -56,8 +59,8 @@ test_expect_success 'alias user-defined format' '
test_cmp expected actual
'
-test_expect_success 'alias user-defined tformat with %s (iso8859-1 encoding)' '
- git config i18n.logOutputEncoding iso8859-1 &&
+test_expect_success 'alias user-defined tformat with %s (ISO8859-1 encoding)' '
+ git config i18n.logOutputEncoding $test_encoding &&
git log --oneline >expected-s &&
git log --pretty="tformat:%h %s" >actual-s &&
git config --unset i18n.logOutputEncoding &&
@@ -141,9 +144,7 @@ test_expect_success 'setup more commits' '
'
test_expect_success 'left alignment formatting' '
- git log --pretty="format:%<(40)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%<(40)%s" >actual &&
qz_to_tab_space <<EOF >expected &&
message two Z
message one Z
@@ -153,10 +154,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'left alignment formatting. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(40)%s" >actual &&
+ qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+message two Z
+message one Z
+add bar Z
+$(commit_msg) Z
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'left alignment formatting at the nth column' '
- git log --pretty="format:%h %<|(40)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%h %<|(40)%s" >actual &&
qz_to_tab_space <<EOF >expected &&
$head1 message two Z
$head2 message one Z
@@ -166,10 +176,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'left alignment formatting at the nth column. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%h %<|(40)%s" >actual &&
+ qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+$head1 message two Z
+$head2 message one Z
+$head3 add bar Z
+$head4 $(commit_msg) Z
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'left alignment formatting with no padding' '
- git log --pretty="format:%<(1)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%<(1)%s" >actual &&
cat <<EOF >expected &&
message two
message one
@@ -179,10 +198,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'left alignment formatting with no padding. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(1)%s" >actual &&
+ cat <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+message two
+message one
+add bar
+$(commit_msg)
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'left alignment formatting with trunc' '
- git log --pretty="format:%<(10,trunc)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%<(10,trunc)%s" >actual &&
qz_to_tab_space <<EOF >expected &&
message ..
message ..
@@ -192,10 +220,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'left alignment formatting with trunc. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,trunc)%s" >actual &&
+ qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+message ..
+message ..
+add bar Z
+initial...
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'left alignment formatting with ltrunc' '
- git log --pretty="format:%<(10,ltrunc)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%<(10,ltrunc)%s" >actual &&
qz_to_tab_space <<EOF >expected &&
..sage two
..sage one
@@ -205,10 +242,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'left alignment formatting with ltrunc. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,ltrunc)%s" >actual &&
+ qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+..sage two
+..sage one
+add bar Z
+..${sample_utf8_part}lich
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'left alignment formatting with mtrunc' '
- git log --pretty="format:%<(10,mtrunc)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%<(10,mtrunc)%s" >actual &&
qz_to_tab_space <<EOF >expected &&
mess.. two
mess.. one
@@ -218,10 +264,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'left alignment formatting with mtrunc. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,mtrunc)%s" >actual &&
+ qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+mess.. two
+mess.. one
+add bar Z
+init..lich
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'right alignment formatting' '
- git log --pretty="format:%>(40)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%>(40)%s" >actual &&
qz_to_tab_space <<EOF >expected &&
Z message two
Z message one
@@ -231,10 +286,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'right alignment formatting. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%>(40)%s" >actual &&
+ qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+Z message two
+Z message one
+Z add bar
+Z $(commit_msg)
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'right alignment formatting at the nth column' '
- git log --pretty="format:%h %>|(40)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%h %>|(40)%s" >actual &&
qz_to_tab_space <<EOF >expected &&
$head1 message two
$head2 message one
@@ -244,10 +308,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'right alignment formatting at the nth column. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%h %>|(40)%s" >actual &&
+ qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+$head1 message two
+$head2 message one
+$head3 add bar
+$head4 $(commit_msg)
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'right alignment formatting with no padding' '
- git log --pretty="format:%>(1)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%>(1)%s" >actual &&
cat <<EOF >expected &&
message two
message one
@@ -257,10 +330,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'right alignment formatting with no padding. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%>(1)%s" >actual &&
+ cat <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+message two
+message one
+add bar
+$(commit_msg)
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'center alignment formatting' '
- git log --pretty="format:%><(40)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%><(40)%s" >actual &&
qz_to_tab_space <<EOF >expected &&
Z message two Z
Z message one Z
@@ -270,10 +352,18 @@ EOF
test_cmp expected actual
'
+test_expect_success 'center alignment formatting. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%><(40)%s" >actual &&
+ qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+Z message two Z
+Z message one Z
+Z add bar Z
+Z $(commit_msg) Z
+EOF
+ test_cmp expected actual
+'
test_expect_success 'center alignment formatting at the nth column' '
- git log --pretty="format:%h %><|(40)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%h %><|(40)%s" >actual &&
qz_to_tab_space <<EOF >expected &&
$head1 message two Z
$head2 message one Z
@@ -283,10 +373,19 @@ EOF
test_cmp expected actual
'
+test_expect_success 'center alignment formatting at the nth column. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%h %><|(40)%s" >actual &&
+ qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+$head1 message two Z
+$head2 message one Z
+$head3 add bar Z
+$head4 $(commit_msg) Z
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'center alignment formatting with no padding' '
- git log --pretty="format:%><(1)%s" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%><(1)%s" >actual &&
cat <<EOF >expected &&
message two
message one
@@ -296,11 +395,23 @@ EOF
test_cmp expected actual
'
+# save HEAD's SHA-1 digest (with no abbreviations) to use it below
+# as far as the next test amends HEAD
+old_head1=$(git rev-parse --verify HEAD~0)
+test_expect_success 'center alignment formatting with no padding. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%><(1)%s" >actual &&
+ cat <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+message two
+message one
+add bar
+$(commit_msg)
+EOF
+ test_cmp expected actual
+'
+
test_expect_success 'left/right alignment formatting with stealing' '
git commit --amend -m short --author "long long long <long@me.com>" &&
- git log --pretty="format:%<(10,trunc)%s%>>(10,ltrunc)% an" >actual &&
- # complete the incomplete line at the end
- echo >>actual &&
+ git log --pretty="tformat:%<(10,trunc)%s%>>(10,ltrunc)% an" >actual &&
cat <<EOF >expected &&
short long long long
message .. A U Thor
@@ -309,6 +420,35 @@ initial... A U Thor
EOF
test_cmp expected actual
'
+test_expect_success 'left/right alignment formatting with stealing. i18n.logOutputEncoding' '
+ git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,trunc)%s%>>(10,ltrunc)% an" >actual &&
+ cat <<EOF | iconv -f utf-8 -t $test_encoding >expected &&
+short long long long
+message .. A U Thor
+add bar A U Thor
+initial... A U Thor
+EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'strbuf_utf8_replace() not producing NUL' '
+ git log --color --pretty="tformat:%<(10,trunc)%s%>>(10,ltrunc)%C(auto)%d" |
+ test_decode_color |
+ nul_to_q >actual &&
+ ! grep Q actual
+'
+
+# ISO strict date format
+test_expect_success 'ISO and ISO-strict date formats display the same values' '
+ git log --format=%ai%n%ci |
+ sed -e "s/ /T/; s/ //; s/..\$/:&/" >expected &&
+ git log --format=%aI%n%cI >actual &&
+ test_cmp expected actual
+'
+
+# get new digests (with no abbreviations)
+head1=$(git rev-parse --verify HEAD~0) &&
+head2=$(git rev-parse --verify HEAD~1) &&
test_expect_success 'log decoration properly follows tag chain' '
git tag -a tag1 -m tag1 &&
@@ -317,9 +457,20 @@ test_expect_success 'log decoration properly follows tag chain' '
git commit --amend -m shorter &&
git log --no-walk --tags --pretty="%H %d" --decorate=full >actual &&
cat <<EOF >expected &&
-6a908c10688b2503073c39c9ba26322c73902bb5 (tag: refs/tags/tag2)
-9f716384d92283fb915a4eee5073f030638e05f9 (tag: refs/tags/message-one)
-b87e4cccdb77336ea79d89224737be7ea8e95367 (tag: refs/tags/message-two)
+$head1 (tag: refs/tags/tag2)
+$head2 (tag: refs/tags/message-one)
+$old_head1 (tag: refs/tags/message-two)
+EOF
+ sort actual >actual1 &&
+ test_cmp expected actual1
+'
+
+test_expect_success 'clean log decoration' '
+ git log --no-walk --tags --pretty="%H %D" --decorate=full >actual &&
+ cat >expected <<EOF &&
+$head1 tag: refs/tags/tag2
+$head2 tag: refs/tags/message-one
+$old_head1 tag: refs/tags/message-two
EOF
sort actual >actual1 &&
test_cmp expected actual1
diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh
index 38fb80f643..844df760f7 100755
--- a/t/t4209-log-pickaxe.sh
+++ b/t/t4209-log-pickaxe.sh
@@ -3,82 +3,72 @@
test_description='log --grep/--author/--regexp-ignore-case/-S/-G'
. ./test-lib.sh
+test_log () {
+ expect=$1
+ kind=$2
+ needle=$3
+ shift 3
+ rest=$@
+
+ case $kind in
+ --*)
+ opt=$kind=$needle
+ ;;
+ *)
+ opt=$kind$needle
+ ;;
+ esac
+ case $expect in
+ expect_nomatch)
+ match=nomatch
+ ;;
+ *)
+ match=match
+ ;;
+ esac
+
+ test_expect_success "log $kind${rest:+ $rest} ($match)" "
+ git log $rest $opt --format=%H >actual &&
+ test_cmp $expect actual
+ "
+}
+
+# test -i and --regexp-ignore-case and expect both to behave the same way
+test_log_icase () {
+ test_log $@ --regexp-ignore-case
+ test_log $@ -i
+}
+
test_expect_success setup '
+ >expect_nomatch &&
+
>file &&
git add file &&
test_tick &&
git commit -m initial &&
+ git rev-parse --verify HEAD >expect_initial &&
echo Picked >file &&
+ git add file &&
test_tick &&
- git commit -a --author="Another Person <another@example.com>" -m second
-'
-
-test_expect_success 'log --grep' '
- git log --grep=initial --format=%H >actual &&
- git rev-parse --verify HEAD^ >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log --grep --regexp-ignore-case' '
- git log --regexp-ignore-case --grep=InItial --format=%H >actual &&
- git rev-parse --verify HEAD^ >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log --grep -i' '
- git log -i --grep=InItial --format=%H >actual &&
- git rev-parse --verify HEAD^ >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log --author --regexp-ignore-case' '
- git log --regexp-ignore-case --author=person --format=%H >actual &&
- git rev-parse --verify HEAD >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log --author -i' '
- git log -i --author=person --format=%H >actual &&
- git rev-parse --verify HEAD >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log -G (nomatch)' '
- git log -Gpicked --format=%H >actual &&
- >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log -G (match)' '
- git log -GPicked --format=%H >actual &&
- git rev-parse --verify HEAD >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log -G --regexp-ignore-case (nomatch)' '
- git log --regexp-ignore-case -Gpickle --format=%H >actual &&
- >expect &&
- test_cmp expect actual
+ git commit --author="Another Person <another@example.com>" -m second &&
+ git rev-parse --verify HEAD >expect_second
'
-test_expect_success 'log -G -i (nomatch)' '
- git log -i -Gpickle --format=%H >actual &&
- >expect &&
- test_cmp expect actual
-'
+test_log expect_initial --grep initial
+test_log expect_nomatch --grep InItial
+test_log_icase expect_initial --grep InItial
+test_log_icase expect_nomatch --grep initail
-test_expect_success 'log -G --regexp-ignore-case (match)' '
- git log --regexp-ignore-case -Gpicked --format=%H >actual &&
- git rev-parse --verify HEAD >expect &&
- test_cmp expect actual
-'
+test_log expect_second --author Person
+test_log expect_nomatch --author person
+test_log_icase expect_second --author person
+test_log_icase expect_nomatch --author spreon
-test_expect_success 'log -G -i (match)' '
- git log -i -Gpicked --format=%H >actual &&
- git rev-parse --verify HEAD >expect &&
- test_cmp expect actual
-'
+test_log expect_nomatch -G picked
+test_log expect_second -G Picked
+test_log_icase expect_nomatch -G pickle
+test_log_icase expect_second -G picked
test_expect_success 'log -G --textconv (missing textconv tool)' '
echo "* diff=test" >.gitattributes &&
@@ -89,46 +79,19 @@ test_expect_success 'log -G --textconv (missing textconv tool)' '
test_expect_success 'log -G --no-textconv (missing textconv tool)' '
echo "* diff=test" >.gitattributes &&
git -c diff.test.textconv=missing log -Gfoo --no-textconv >actual &&
- >expect &&
- test_cmp expect actual &&
+ test_cmp expect_nomatch actual &&
rm .gitattributes
'
-test_expect_success 'log -S (nomatch)' '
- git log -Spicked --format=%H >actual &&
- >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log -S (match)' '
- git log -SPicked --format=%H >actual &&
- git rev-parse --verify HEAD >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log -S --regexp-ignore-case (match)' '
- git log --regexp-ignore-case -Spicked --format=%H >actual &&
- git rev-parse --verify HEAD >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log -S -i (match)' '
- git log -i -Spicked --format=%H >actual &&
- git rev-parse --verify HEAD >expect &&
- test_cmp expect actual
-'
-
-test_expect_success 'log -S --regexp-ignore-case (nomatch)' '
- git log --regexp-ignore-case -Spickle --format=%H >actual &&
- >expect &&
- test_cmp expect actual
-'
+test_log expect_nomatch -S picked
+test_log expect_second -S Picked
+test_log_icase expect_second -S picked
+test_log_icase expect_nomatch -S pickle
-test_expect_success 'log -S -i (nomatch)' '
- git log -i -Spickle --format=%H >actual &&
- >expect &&
- test_cmp expect actual
-'
+test_log expect_nomatch -S p.cked --pickaxe-regex
+test_log expect_second -S P.cked --pickaxe-regex
+test_log_icase expect_second -S p.cked --pickaxe-regex
+test_log_icase expect_nomatch -S p.ckle --pickaxe-regex
test_expect_success 'log -S --textconv (missing textconv tool)' '
echo "* diff=test" >.gitattributes &&
@@ -139,8 +102,7 @@ test_expect_success 'log -S --textconv (missing textconv tool)' '
test_expect_success 'log -S --no-textconv (missing textconv tool)' '
echo "* diff=test" >.gitattributes &&
git -c diff.test.textconv=missing log -Sfoo --no-textconv >actual &&
- >expect &&
- test_cmp expect actual &&
+ test_cmp expect_nomatch actual &&
rm .gitattributes
'
diff --git a/t/t4210-log-i18n.sh b/t/t4210-log-i18n.sh
index 52a74729ba..e585fe6129 100755
--- a/t/t4210-log-i18n.sh
+++ b/t/t4210-log-i18n.sh
@@ -34,7 +34,7 @@ test_expect_success 'log --grep searches in log output encoding (utf8)' '
test_cmp expect actual
'
-test_expect_success 'log --grep searches in log output encoding (latin1)' '
+test_expect_success !MINGW 'log --grep searches in log output encoding (latin1)' '
cat >expect <<-\EOF &&
latin1
utf8
@@ -43,7 +43,7 @@ test_expect_success 'log --grep searches in log output encoding (latin1)' '
test_cmp expect actual
'
-test_expect_success 'log --grep does not find non-reencoded values (utf8)' '
+test_expect_success !MINGW 'log --grep does not find non-reencoded values (utf8)' '
>expect &&
git log --encoding=utf8 --format=%s --grep=$latin1_e >actual &&
test_cmp expect actual
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 7369d3c517..0901b30982 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -94,4 +94,9 @@ test_expect_success '-L ,Y (Y == nlines + 2)' '
test_must_fail git log -L ,$n:b.c
'
+test_expect_success '-L with --first-parent and a merge' '
+ git checkout parallel-change &&
+ git log --first-parent -L 1,1:b.c
+'
+
test_done
diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh
index 93c7c366cf..67bd8ec020 100755
--- a/t/t4212-log-corrupt.sh
+++ b/t/t4212-log-corrupt.sh
@@ -14,7 +14,7 @@ test_expect_success 'setup' '
'
test_expect_success 'fsck notices broken commit' '
- git fsck 2>actual &&
+ test_must_fail git fsck 2>actual &&
test_i18ngrep invalid.author actual
'
@@ -44,4 +44,47 @@ test_expect_success 'git log --format with broken author email' '
test_cmp expect.err actual.err
'
+munge_author_date () {
+ git cat-file commit "$1" >commit.orig &&
+ sed "s/^\(author .*>\) [0-9]*/\1 $2/" <commit.orig >commit.munge &&
+ git hash-object -w -t commit commit.munge
+}
+
+test_expect_success 'unparsable dates produce sentinel value' '
+ commit=$(munge_author_date HEAD totally_bogus) &&
+ echo "Date: Thu Jan 1 00:00:00 1970 +0000" >expect &&
+ git log -1 $commit >actual.full &&
+ grep Date <actual.full >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'unparsable dates produce sentinel value (%ad)' '
+ commit=$(munge_author_date HEAD totally_bogus) &&
+ echo >expect &&
+ git log -1 --format=%ad $commit >actual
+ test_cmp expect actual
+'
+
+# date is 2^64 + 1
+test_expect_success 'date parser recognizes integer overflow' '
+ commit=$(munge_author_date HEAD 18446744073709551617) &&
+ echo "Thu Jan 1 00:00:00 1970 +0000" >expect &&
+ git log -1 --format=%ad $commit >actual &&
+ test_cmp expect actual
+'
+
+# date is 2^64 - 2
+test_expect_success 'date parser recognizes time_t overflow' '
+ commit=$(munge_author_date HEAD 18446744073709551614) &&
+ echo "Thu Jan 1 00:00:00 1970 +0000" >expect &&
+ git log -1 --format=%ad $commit >actual &&
+ test_cmp expect actual
+'
+
+# date is within 2^63-1, but enough to choke glibc's gmtime
+test_expect_success 'absurdly far-in-future date' '
+ commit=$(munge_author_date HEAD 999999999999999999) &&
+ git log -1 --format=%ad $commit
+'
+
test_done
diff --git a/t/t4255-am-submodule.sh b/t/t4255-am-submodule.sh
new file mode 100755
index 0000000000..8bde7dbb6d
--- /dev/null
+++ b/t/t4255-am-submodule.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+test_description='git am handling submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+am () {
+ git format-patch --stdout --ignore-submodules=dirty "..$1" | git am -
+}
+
+test_submodule_switch "am"
+
+am_3way () {
+ git format-patch --stdout --ignore-submodules=dirty "..$1" | git am --3way -
+}
+
+KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1
+test_submodule_switch "am_3way"
+
+test_done
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index c2023b1a3d..d01bbdc968 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -3,7 +3,7 @@
# Copyright (C) 2005 Rene Scharfe
#
-test_description='git tar-tree and git get-tar-commit-id test
+test_description='git archive and git get-tar-commit-id test
This test covers the topics of file contents, commit date handling and
commit id embedding:
@@ -13,11 +13,11 @@ commit id embedding:
binary file (/bin/sh). Only paths shorter than 99 characters are
used.
- git tar-tree applies the commit date to every file in the archive it
+ git archive applies the commit date to every file in the archive it
creates. The test sets the commit date to a specific value and checks
if the tar archive contains that value.
- When giving git tar-tree a commit id (in contrast to a tree id) it
+ When giving git archive a commit id (in contrast to a tree id) it
embeds this commit id into the tar archive as a comment. The test
checks the ability of git get-tar-commit-id to figure it out from the
tar file.
@@ -25,8 +25,6 @@ commit id embedding:
'
. ./test-lib.sh
-GZIP=${GZIP:-gzip}
-GUNZIP=${GUNZIP:-gzip -d}
SUBSTFORMAT=%H%n
@@ -39,6 +37,8 @@ test_lazy_prereq TAR_NEEDS_PAX_FALLBACK '
)
'
+test_lazy_prereq GZIP 'gzip --version'
+
get_pax_header() {
file=$1
header=$2=
@@ -72,7 +72,7 @@ check_tar() {
for header in *.paxheader
do
data=${header%.paxheader}.data &&
- if test -h $data -o -e $data
+ if test -h $data || test -e $data
then
path=$(get_pax_header $header path) &&
if test -n "$path"
@@ -119,14 +119,10 @@ test_expect_success \
'echo ignore me >a/ignored &&
echo ignored export-ignore >.git/info/attributes'
-test_expect_success \
- 'add files to repository' \
- 'find a -type f | xargs git update-index --add &&
- find a -type l | xargs git update-index --add &&
- treeid=`git write-tree` &&
- echo $treeid >treeid &&
- git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \
- git commit-tree $treeid </dev/null)'
+test_expect_success 'add files to repository' '
+ git add a &&
+ GIT_COMMITTER_DATE="2005-05-27 22:00" git commit -m initial
+'
test_expect_success 'setup export-subst' '
echo "substfile?" export-subst >>.git/info/attributes &&
@@ -164,7 +160,7 @@ check_tar with_olde-prefix olde-
test_expect_success 'git archive on large files' '
test_config core.bigfilethreshold 1 &&
git archive HEAD >b3.tar &&
- test_cmp b.tar b3.tar
+ test_cmp_bin b.tar b3.tar
'
test_expect_success \
@@ -173,15 +169,15 @@ test_expect_success \
test_expect_success \
'git archive vs. the same in a bare repo' \
- 'test_cmp b.tar b3.tar'
+ 'test_cmp_bin b.tar b3.tar'
test_expect_success 'git archive with --output' \
'git archive --output=b4.tar HEAD &&
- test_cmp b.tar b4.tar'
+ test_cmp_bin b.tar b4.tar'
test_expect_success 'git archive --remote' \
'git archive --remote=. HEAD >b5.tar &&
- test_cmp b.tar b5.tar'
+ test_cmp_bin b.tar b5.tar'
test_expect_success \
'validate file modification time' \
@@ -196,19 +192,9 @@ test_expect_success \
'git get-tar-commit-id <b.tar >b.commitid &&
test_cmp .git/$(git symbolic-ref HEAD) b.commitid'
-test_expect_success 'git tar-tree' '
- git tar-tree HEAD >tar-tree.tar &&
- test_cmp b.tar tar-tree.tar
-'
-
-test_expect_success 'git tar-tree with prefix' '
- git tar-tree HEAD prefix >tar-tree_with_prefix.tar &&
- test_cmp with_prefix.tar tar-tree_with_prefix.tar
-'
-
test_expect_success 'git archive with --output, override inferred format' '
git archive --format=tar --output=d4.zip HEAD &&
- test_cmp b.tar d4.zip
+ test_cmp_bin b.tar d4.zip
'
test_expect_success \
@@ -217,12 +203,21 @@ test_expect_success \
test_expect_success 'clients cannot access unreachable commits' '
test_commit unreachable &&
- sha1=`git rev-parse HEAD` &&
+ sha1=$(git rev-parse HEAD) &&
git reset --hard HEAD^ &&
git archive $sha1 >remote.tar &&
test_must_fail git archive --remote=. $sha1 >remote.tar
'
+test_expect_success 'upload-archive can allow unreachable commits' '
+ test_commit unreachable1 &&
+ sha1=$(git rev-parse HEAD) &&
+ git reset --hard HEAD^ &&
+ git archive $sha1 >remote.tar &&
+ test_config uploadarchive.allowUnreachable true &&
+ git archive --remote=. $sha1 >remote.tar
+'
+
test_expect_success 'setup tar filters' '
git config tar.tar.foo.command "tr ab ba" &&
git config tar.bar.command "tr ab ba" &&
@@ -245,75 +240,63 @@ test_expect_success 'archive --list shows only enabled remote filters' '
test_expect_success 'invoke tar filter by format' '
git archive --format=tar.foo HEAD >config.tar.foo &&
tr ab ba <config.tar.foo >config.tar &&
- test_cmp b.tar config.tar &&
+ test_cmp_bin b.tar config.tar &&
git archive --format=bar HEAD >config.bar &&
tr ab ba <config.bar >config.tar &&
- test_cmp b.tar config.tar
+ test_cmp_bin b.tar config.tar
'
test_expect_success 'invoke tar filter by extension' '
git archive -o config-implicit.tar.foo HEAD &&
- test_cmp config.tar.foo config-implicit.tar.foo &&
+ test_cmp_bin config.tar.foo config-implicit.tar.foo &&
git archive -o config-implicit.bar HEAD &&
- test_cmp config.tar.foo config-implicit.bar
+ test_cmp_bin config.tar.foo config-implicit.bar
'
test_expect_success 'default output format remains tar' '
git archive -o config-implicit.baz HEAD &&
- test_cmp b.tar config-implicit.baz
+ test_cmp_bin b.tar config-implicit.baz
'
test_expect_success 'extension matching requires dot' '
git archive -o config-implicittar.foo HEAD &&
- test_cmp b.tar config-implicittar.foo
+ test_cmp_bin b.tar config-implicittar.foo
'
test_expect_success 'only enabled filters are available remotely' '
test_must_fail git archive --remote=. --format=tar.foo HEAD \
>remote.tar.foo &&
git archive --remote=. --format=bar >remote.bar HEAD &&
- test_cmp remote.bar config.bar
+ test_cmp_bin remote.bar config.bar
'
-if $GZIP --version >/dev/null 2>&1; then
- test_set_prereq GZIP
-else
- say "Skipping some tar.gz tests because gzip not found"
-fi
-
test_expect_success GZIP 'git archive --format=tgz' '
git archive --format=tgz HEAD >j.tgz
'
test_expect_success GZIP 'git archive --format=tar.gz' '
git archive --format=tar.gz HEAD >j1.tar.gz &&
- test_cmp j.tgz j1.tar.gz
+ test_cmp_bin j.tgz j1.tar.gz
'
test_expect_success GZIP 'infer tgz from .tgz filename' '
git archive --output=j2.tgz HEAD &&
- test_cmp j.tgz j2.tgz
+ test_cmp_bin j.tgz j2.tgz
'
test_expect_success GZIP 'infer tgz from .tar.gz filename' '
git archive --output=j3.tar.gz HEAD &&
- test_cmp j.tgz j3.tar.gz
+ test_cmp_bin j.tgz j3.tar.gz
'
-if $GUNZIP --version >/dev/null 2>&1; then
- test_set_prereq GUNZIP
-else
- say "Skipping some tar.gz tests because gunzip was not found"
-fi
-
-test_expect_success GZIP,GUNZIP 'extract tgz file' '
- $GUNZIP -c <j.tgz >j.tar &&
- test_cmp b.tar j.tar
+test_expect_success GZIP 'extract tgz file' '
+ gzip -d -c <j.tgz >j.tar &&
+ test_cmp_bin b.tar j.tar
'
test_expect_success GZIP 'remote tar.gz is allowed by default' '
git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
- test_cmp j.tgz remote.tar.gz
+ test_cmp_bin j.tgz remote.tar.gz
'
test_expect_success GZIP 'remote tar.gz can be disabled' '
@@ -322,4 +305,18 @@ test_expect_success GZIP 'remote tar.gz can be disabled' '
>remote.tar.gz
'
+test_expect_success 'archive and :(glob)' '
+ git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual &&
+ cat >expect <<EOF &&
+a/
+a/bin/
+a/bin/sh
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'catch non-matching pathspec' '
+ test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
+'
+
test_done
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index f47d8717fd..b04d955bfa 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -68,7 +68,7 @@ test_expect_missing worktree2/ignored-by-worktree
test_expect_success 'git archive vs. bare' '
(cd bare && git archive HEAD) >bare-archive.tar &&
- test_cmp archive.tar bare-archive.tar
+ test_cmp_bin archive.tar bare-archive.tar
'
test_expect_success 'git archive with worktree attributes, bare' '
@@ -87,14 +87,4 @@ test_expect_success 'export-subst' '
test_cmp substfile2 archive/substfile2
'
-test_expect_success 'git tar-tree vs. git archive with worktree attributes' '
- git tar-tree HEAD >tar-tree.tar &&
- test_cmp worktree.tar tar-tree.tar
-'
-
-test_expect_success 'git tar-tree vs. git archive with worktree attrs, bare' '
- (cd bare && git tar-tree HEAD) >bare-tar-tree.tar &&
- test_cmp bare-worktree.tar bare-tar-tree.tar
-'
-
test_done
diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh
index c72f71eb18..c929db5633 100755
--- a/t/t5003-archive-zip.sh
+++ b/t/t5003-archive-zip.sh
@@ -61,14 +61,10 @@ test_expect_success \
'echo ignore me >a/ignored &&
echo ignored export-ignore >.git/info/attributes'
-test_expect_success \
- 'add files to repository' \
- 'find a -type f | xargs git update-index --add &&
- find a -type l | xargs git update-index --add &&
- treeid=`git write-tree` &&
- echo $treeid >treeid &&
- git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \
- git commit-tree $treeid </dev/null)'
+test_expect_success 'add files to repository' '
+ git add a &&
+ GIT_COMMITTER_DATE="2005-05-27 22:00" git commit -m initial
+'
test_expect_success 'setup export-subst' '
echo "substfile?" export-subst >>.git/info/attributes &&
@@ -97,15 +93,15 @@ test_expect_success \
test_expect_success \
'git archive --format=zip vs. the same in a bare repo' \
- 'test_cmp d.zip d1.zip'
+ 'test_cmp_bin d.zip d1.zip'
test_expect_success 'git archive --format=zip with --output' \
'git archive --format=zip --output=d2.zip HEAD &&
- test_cmp d.zip d2.zip'
+ test_cmp_bin d.zip d2.zip'
test_expect_success 'git archive with --output, inferring format' '
git archive --output=d3.zip HEAD &&
- test_cmp d.zip d3.zip
+ test_cmp_bin d.zip d3.zip
'
test_expect_success \
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index 67f3b54bed..305bcac6b7 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -45,7 +45,7 @@ test_expect_success HEADER_ONLY_TAR_OK 'tar archive of commit with empty tree' '
test_expect_success 'tar archive of empty tree is empty' '
git archive --format=tar HEAD: >empty.tar &&
perl -e "print \"\\0\" x 10240" >10knuls.tar &&
- test_cmp 10knuls.tar empty.tar
+ test_cmp_bin 10knuls.tar empty.tar
'
test_expect_success 'tar archive of empty tree with prefix' '
diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh
index 3e64a7a65d..9e1ad1ca21 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -89,4 +89,22 @@ test_expect_success 'mailinfo on from header without name works' '
'
+test_expect_success 'mailinfo finds headers after embedded From line' '
+ mkdir embed-from &&
+ git mailsplit -oembed-from "$TEST_DIRECTORY"/t5100/embed-from.in &&
+ test_cmp "$TEST_DIRECTORY"/t5100/embed-from.in embed-from/0001 &&
+ git mailinfo embed-from/msg embed-from/patch \
+ <embed-from/0001 >embed-from/out &&
+ test_cmp "$TEST_DIRECTORY"/t5100/embed-from.expect embed-from/out
+'
+
+test_expect_success 'mailinfo on message with quoted >From' '
+ mkdir quoted-from &&
+ git mailsplit -oquoted-from "$TEST_DIRECTORY"/t5100/quoted-from.in &&
+ test_cmp "$TEST_DIRECTORY"/t5100/quoted-from.in quoted-from/0001 &&
+ git mailinfo quoted-from/msg quoted-from/patch \
+ <quoted-from/0001 >quoted-from/out &&
+ test_cmp "$TEST_DIRECTORY"/t5100/quoted-from.expect quoted-from/msg
+'
+
test_done
diff --git a/t/t5100/embed-from.expect b/t/t5100/embed-from.expect
new file mode 100644
index 0000000000..06a3a3859a
--- /dev/null
+++ b/t/t5100/embed-from.expect
@@ -0,0 +1,5 @@
+Author: Commit Author
+Email: commit@example.com
+Subject: patch subject
+Date: Sat, 13 Sep 2014 21:13:23 -0400
+
diff --git a/t/t5100/embed-from.in b/t/t5100/embed-from.in
new file mode 100644
index 0000000000..5f3f84e508
--- /dev/null
+++ b/t/t5100/embed-from.in
@@ -0,0 +1,13 @@
+From 1234567890123456789012345678901234567890 Mon Sep 17 00:00:00 2001
+From: Email Author <email@example.com>
+Date: Sun, 25 May 2008 00:38:18 -0700
+Subject: [PATCH] email subject
+
+>From 1234567890123456789012345678901234567890 Mon Sep 17 00:00:00 2001
+From: Commit Author <commit@example.com>
+Date: Sat, 13 Sep 2014 21:13:23 -0400
+Subject: patch subject
+
+patch body
+---
+patch
diff --git a/t/t5100/quoted-from.expect b/t/t5100/quoted-from.expect
new file mode 100644
index 0000000000..8c9d48c852
--- /dev/null
+++ b/t/t5100/quoted-from.expect
@@ -0,0 +1,3 @@
+>From the depths of history, we are stuck with the
+flaky mbox format.
+
diff --git a/t/t5100/quoted-from.in b/t/t5100/quoted-from.in
new file mode 100644
index 0000000000..847e1c4d3e
--- /dev/null
+++ b/t/t5100/quoted-from.in
@@ -0,0 +1,10 @@
+From 1234567890123456789012345678901234567890 Mon Sep 17 00:00:00 2001
+From: Author Name <somebody@example.com>
+Date: Sun, 25 May 2008 00:38:18 -0700
+Subject: [PATCH] testing quoted >From
+
+>From the depths of history, we are stuck with the
+flaky mbox format.
+
+---
+patch
diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh
index 1afa0d5c44..82c33b88e7 100755
--- a/t/t5150-request-pull.sh
+++ b/t/t5150-request-pull.sh
@@ -86,7 +86,7 @@ test_expect_success 'setup: two scripts for reading pull requests' '
s/[-0-9]\{10\} [:0-9]\{8\} [-+][0-9]\{4\}/DATE/g
s/ [^ ].*/ SUBJECT/g
s/ [^ ].* (DATE)/ SUBJECT (DATE)/g
- s/for-upstream/BRANCH/g
+ s|tags/full|BRANCH|g
s/mnemonic.txt/FILENAME/g
s/^version [0-9]/VERSION/
/^ FILENAME | *[0-9]* [-+]*\$/ b diffstat
@@ -127,7 +127,7 @@ test_expect_success 'pull request when forgot to push' '
test_must_fail git request-pull initial "$downstream_url" \
2>../err
) &&
- grep "No branch of.*is at:\$" err &&
+ grep "No match for commit .*" err &&
grep "Are you sure you pushed" err
'
@@ -141,7 +141,7 @@ test_expect_success 'pull request after push' '
git checkout initial &&
git merge --ff-only master &&
git push origin master:for-upstream &&
- git request-pull initial origin >../request
+ git request-pull initial origin master:for-upstream >../request
) &&
sed -nf read-request.sed <request >digest &&
cat digest &&
@@ -160,7 +160,7 @@ test_expect_success 'pull request after push' '
'
-test_expect_success 'request names an appropriate branch' '
+test_expect_success 'request asks HEAD to be pulled' '
rm -fr downstream.git &&
git init --bare downstream.git &&
@@ -179,7 +179,7 @@ test_expect_success 'request names an appropriate branch' '
read repository &&
read branch
} <digest &&
- test "$branch" = tags/full
+ test -z "$branch"
'
@@ -212,12 +212,24 @@ test_expect_success 'pull request format' '
cd local &&
git checkout initial &&
git merge --ff-only master &&
- git push origin master:for-upstream &&
- git request-pull initial "$downstream_url" >../request
+ git push origin tags/full &&
+ git request-pull initial "$downstream_url" tags/full >../request
) &&
<request sed -nf fuzz.sed >request.fuzzy &&
- test_i18ncmp expect request.fuzzy
+ test_i18ncmp expect request.fuzzy &&
+ (
+ cd local &&
+ git request-pull initial "$downstream_url" tags/full:refs/tags/full
+ ) >request &&
+ sed -nf fuzz.sed <request >request.fuzzy &&
+ test_i18ncmp expect request.fuzzy &&
+
+ (
+ cd local &&
+ git request-pull initial "$downstream_url" full
+ ) >request &&
+ grep " tags/full\$" request
'
test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' '
@@ -229,7 +241,7 @@ test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' '
git checkout initial &&
git merge --ff-only master &&
git push origin master:for-upstream &&
- git request-pull -- initial "$downstream_url" >../request
+ git request-pull -- initial "$downstream_url" master:for-upstream >../request
)
'
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index fe82025d4a..61bc8da560 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -174,11 +174,11 @@ test_expect_success \
test_expect_success \
'[index v1] 5) pack-objects happily reuses corrupted data' \
'pack4=$(git pack-objects test-4 <obj-list) &&
- test -f "test-4-${pack1}.pack"'
+ test -f "test-4-${pack4}.pack"'
test_expect_success \
'[index v1] 6) newly created pack is BAD !' \
- 'test_must_fail git verify-pack -v "test-4-${pack1}.pack"'
+ 'test_must_fail git verify-pack -v "test-4-${pack4}.pack"'
test_expect_success \
'[index v2] 1) stream pack to repository' \
@@ -243,4 +243,23 @@ test_expect_success 'running index-pack in the object store' '
test -f .git/objects/pack/pack-${pack1}.idx
'
+test_expect_success 'index-pack --strict warns upon missing tagger in tag' '
+ sha=$(git rev-parse HEAD) &&
+ cat >wrong-tag <<EOF &&
+object $sha
+type commit
+tag guten tag
+
+This is an invalid tag.
+EOF
+
+ tag=$(git hash-object -t tag -w --stdin <wrong-tag) &&
+ pack1=$(echo $tag $sha | git pack-objects tag-test) &&
+ echo remove tag object &&
+ thirtyeight=${tag#??} &&
+ rm -f .git/objects/${tag%$thirtyeight}/$thirtyeight &&
+ git index-pack --strict tag-test-${pack1}.pack 2>err &&
+ grep "^error:.* expected .tagger. line" err
+'
+
test_done
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index e4bb3a1457..e32e46dee1 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -13,8 +13,8 @@ add_blob() {
before=$(git count-objects | sed "s/ .*//") &&
BLOB=$(echo aleph_0 | git hash-object -w --stdin) &&
BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
- test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
- test -f $BLOB_FILE &&
+ verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ test_path_is_file $BLOB_FILE &&
test-chmtime =+0 $BLOB_FILE
}
@@ -35,9 +35,9 @@ test_expect_success 'prune stale packs' '
: > .git/objects/tmp_2.pack &&
test-chmtime =-86501 .git/objects/tmp_1.pack &&
git prune --expire 1.day &&
- test -f $orig_pack &&
- test -f .git/objects/tmp_2.pack &&
- ! test -f .git/objects/tmp_1.pack
+ test_path_is_file $orig_pack &&
+ test_path_is_file .git/objects/tmp_2.pack &&
+ test_path_is_missing .git/objects/tmp_1.pack
'
@@ -45,12 +45,12 @@ test_expect_success 'prune --expire' '
add_blob &&
git prune --expire=1.hour.ago &&
- test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
- test -f $BLOB_FILE &&
+ verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ test_path_is_file $BLOB_FILE &&
test-chmtime =-86500 $BLOB_FILE &&
git prune --expire 1.day &&
- test $before = $(git count-objects | sed "s/ .*//") &&
- ! test -f $BLOB_FILE
+ verbose test $before = $(git count-objects | sed "s/ .*//") &&
+ test_path_is_missing $BLOB_FILE
'
@@ -59,12 +59,12 @@ test_expect_success 'gc: implicit prune --expire' '
add_blob &&
test-chmtime =-$((2*$week-30)) $BLOB_FILE &&
git gc &&
- test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
- test -f $BLOB_FILE &&
+ verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+ test_path_is_file $BLOB_FILE &&
test-chmtime =-$((2*$week+1)) $BLOB_FILE &&
git gc &&
- test $before = $(git count-objects | sed "s/ .*//") &&
- ! test -f $BLOB_FILE
+ verbose test $before = $(git count-objects | sed "s/ .*//") &&
+ test_path_is_missing $BLOB_FILE
'
@@ -104,6 +104,28 @@ test_expect_success 'prune: prune unreachable heads' '
'
+test_expect_success 'prune: do not prune detached HEAD with no reflog' '
+
+ git checkout --detach --quiet &&
+ git commit --allow-empty -m "detached commit" &&
+ # verify that there is no reflogs
+ # (should be removed and disabled by previous test)
+ test_path_is_missing .git/logs &&
+ git prune -n >prune_actual &&
+ : >prune_expected &&
+ test_cmp prune_actual prune_expected
+
+'
+
+test_expect_success 'prune: prune former HEAD after checking out branch' '
+
+ head_sha1=$(git rev-parse HEAD) &&
+ git checkout --quiet master &&
+ git prune -v >prune_actual &&
+ grep "$head_sha1" prune_actual
+
+'
+
test_expect_success 'prune: do not prune heads listed as an argument' '
: > file2 &&
@@ -122,8 +144,8 @@ test_expect_success 'gc --no-prune' '
test-chmtime =-$((5001*$day)) $BLOB_FILE &&
git config gc.pruneExpire 2.days.ago &&
git gc --no-prune &&
- test 1 = $(git count-objects | sed "s/ .*//") &&
- test -f $BLOB_FILE
+ verbose test 1 = $(git count-objects | sed "s/ .*//") &&
+ test_path_is_file $BLOB_FILE
'
@@ -131,10 +153,10 @@ test_expect_success 'gc respects gc.pruneExpire' '
git config gc.pruneExpire 5002.days.ago &&
git gc &&
- test -f $BLOB_FILE &&
+ test_path_is_file $BLOB_FILE &&
git config gc.pruneExpire 5000.days.ago &&
git gc &&
- test ! -f $BLOB_FILE
+ test_path_is_missing $BLOB_FILE
'
@@ -143,9 +165,9 @@ test_expect_success 'gc --prune=<date>' '
add_blob &&
test-chmtime =-$((5001*$day)) $BLOB_FILE &&
git gc --prune=5002.days.ago &&
- test -f $BLOB_FILE &&
+ test_path_is_file $BLOB_FILE &&
git gc --prune=5000.days.ago &&
- test ! -f $BLOB_FILE
+ test_path_is_missing $BLOB_FILE
'
@@ -153,9 +175,9 @@ test_expect_success 'gc --prune=never' '
add_blob &&
git gc --prune=never &&
- test -f $BLOB_FILE &&
+ test_path_is_file $BLOB_FILE &&
git gc --prune=now &&
- test ! -f $BLOB_FILE
+ test_path_is_missing $BLOB_FILE
'
@@ -164,10 +186,10 @@ test_expect_success 'gc respects gc.pruneExpire=never' '
git config gc.pruneExpire never &&
add_blob &&
git gc &&
- test -f $BLOB_FILE &&
+ test_path_is_file $BLOB_FILE &&
git config gc.pruneExpire now &&
git gc &&
- test ! -f $BLOB_FILE
+ test_path_is_missing $BLOB_FILE
'
@@ -175,9 +197,9 @@ test_expect_success 'prune --expire=never' '
add_blob &&
git prune --expire=never &&
- test -f $BLOB_FILE &&
+ test_path_is_file $BLOB_FILE &&
git prune &&
- test ! -f $BLOB_FILE
+ test_path_is_missing $BLOB_FILE
'
@@ -187,11 +209,11 @@ test_expect_success 'gc: prune old objects after local clone' '
git clone --no-hardlinks . aclone &&
(
cd aclone &&
- test 1 = $(git count-objects | sed "s/ .*//") &&
- test -f $BLOB_FILE &&
+ verbose test 1 = $(git count-objects | sed "s/ .*//") &&
+ test_path_is_file $BLOB_FILE &&
git gc --prune &&
- test 0 = $(git count-objects | sed "s/ .*//") &&
- ! test -f $BLOB_FILE
+ verbose test 0 = $(git count-objects | sed "s/ .*//") &&
+ test_path_is_missing $BLOB_FILE
)
'
@@ -213,7 +235,7 @@ test_expect_success 'garbage report in count-objects -v' '
warning: garbage found: .git/objects/pack/fake.bar
warning: garbage found: .git/objects/pack/foo
warning: garbage found: .git/objects/pack/foo.bar
-warning: no corresponding .idx nor .pack: .git/objects/pack/fake2.keep
+warning: no corresponding .idx or .pack: .git/objects/pack/fake2.keep
warning: no corresponding .idx: .git/objects/pack/foo.keep
warning: no corresponding .idx: .git/objects/pack/foo.pack
warning: no corresponding .pack: .git/objects/pack/fake3.idx
@@ -221,4 +243,14 @@ EOF
test_cmp expected actual
'
+test_expect_success 'prune .git/shallow' '
+ SHA1=`echo hi|git commit-tree HEAD^{tree}` &&
+ echo $SHA1 >.git/shallow &&
+ git prune --dry-run >out &&
+ grep $SHA1 .git/shallow &&
+ grep $SHA1 out &&
+ git prune &&
+ test_path_is_missing .git/shallow
+'
+
test_done
diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index b061864a87..21517c70cd 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -45,9 +45,7 @@ test_expect_success 'unpack objects' '
test_expect_success 'check unpacked result (have commit, no tag)' '
git rev-list --objects $commit >list.expect &&
(
- GIT_DIR=clone.git &&
- export GIT_DIR &&
- test_must_fail git cat-file -e $tag &&
+ test_must_fail env GIT_DIR=clone.git git cat-file -e $tag &&
git rev-list --objects $commit
) >list.actual &&
test_cmp list.expect list.actual
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
new file mode 100755
index 0000000000..6003490192
--- /dev/null
+++ b/t/t5310-pack-bitmaps.sh
@@ -0,0 +1,182 @@
+#!/bin/sh
+
+test_description='exercise basic bitmap functionality'
+. ./test-lib.sh
+
+objpath () {
+ echo ".git/objects/$(echo "$1" | sed -e 's|\(..\)|\1/|')"
+}
+
+test_expect_success 'setup repo with moderate-sized history' '
+ for i in $(test_seq 1 10); do
+ test_commit $i
+ done &&
+ git checkout -b other HEAD~5 &&
+ for i in $(test_seq 1 10); do
+ test_commit side-$i
+ done &&
+ git checkout master &&
+ blob=$(echo tagged-blob | git hash-object -w --stdin) &&
+ git tag tagged-blob $blob &&
+ git config repack.writebitmaps true &&
+ git config pack.writebitmaphashcache true
+'
+
+test_expect_success 'full repack creates bitmaps' '
+ git repack -ad &&
+ ls .git/objects/pack/ | grep bitmap >output &&
+ test_line_count = 1 output
+'
+
+test_expect_success 'rev-list --test-bitmap verifies bitmaps' '
+ git rev-list --test-bitmap HEAD
+'
+
+rev_list_tests() {
+ state=$1
+
+ test_expect_success "counting commits via bitmap ($state)" '
+ git rev-list --count HEAD >expect &&
+ git rev-list --use-bitmap-index --count HEAD >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "counting partial commits via bitmap ($state)" '
+ git rev-list --count HEAD~5..HEAD >expect &&
+ git rev-list --use-bitmap-index --count HEAD~5..HEAD >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "counting non-linear history ($state)" '
+ git rev-list --count other...master >expect &&
+ git rev-list --use-bitmap-index --count other...master >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "enumerate --objects ($state)" '
+ git rev-list --objects --use-bitmap-index HEAD >tmp &&
+ cut -d" " -f1 <tmp >tmp2 &&
+ sort <tmp2 >actual &&
+ git rev-list --objects HEAD >tmp &&
+ cut -d" " -f1 <tmp >tmp2 &&
+ sort <tmp2 >expect &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "bitmap --objects handles non-commit objects ($state)" '
+ git rev-list --objects --use-bitmap-index HEAD tagged-blob >actual &&
+ grep $blob actual
+ '
+}
+
+rev_list_tests 'full bitmap'
+
+test_expect_success 'clone from bitmapped repository' '
+ git clone --no-local --bare . clone.git &&
+ git rev-parse HEAD >expect &&
+ git --git-dir=clone.git rev-parse HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'setup further non-bitmapped commits' '
+ for i in $(test_seq 1 10); do
+ test_commit further-$i
+ done
+'
+
+rev_list_tests 'partial bitmap'
+
+test_expect_success 'fetch (partial bitmap)' '
+ git --git-dir=clone.git fetch origin master:master &&
+ git rev-parse HEAD >expect &&
+ git --git-dir=clone.git rev-parse HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'incremental repack cannot create bitmaps' '
+ test_commit more-1 &&
+ find .git/objects/pack -name "*.bitmap" >expect &&
+ git repack -d &&
+ find .git/objects/pack -name "*.bitmap" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'incremental repack can disable bitmaps' '
+ test_commit more-2 &&
+ git repack -d --no-write-bitmap-index
+'
+
+test_expect_success 'full repack, reusing previous bitmaps' '
+ git repack -ad &&
+ ls .git/objects/pack/ | grep bitmap >output &&
+ test_line_count = 1 output
+'
+
+test_expect_success 'fetch (full bitmap)' '
+ git --git-dir=clone.git fetch origin master:master &&
+ git rev-parse HEAD >expect &&
+ git --git-dir=clone.git rev-parse HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'create objects for missing-HAVE tests' '
+ blob=$(echo "missing have" | git hash-object -w --stdin) &&
+ tree=$(printf "100644 blob $blob\tfile\n" | git mktree) &&
+ parent=$(echo parent | git commit-tree $tree) &&
+ commit=$(echo commit | git commit-tree $tree -p $parent) &&
+ cat >revs <<-EOF
+ HEAD
+ ^HEAD^
+ ^$commit
+ EOF
+'
+
+test_expect_success 'pack with missing blob' '
+ rm $(objpath $blob) &&
+ git pack-objects --stdout --revs <revs >/dev/null
+'
+
+test_expect_success 'pack with missing tree' '
+ rm $(objpath $tree) &&
+ git pack-objects --stdout --revs <revs >/dev/null
+'
+
+test_expect_success 'pack with missing parent' '
+ rm $(objpath $parent) &&
+ git pack-objects --stdout --revs <revs >/dev/null
+'
+
+test_lazy_prereq JGIT '
+ type jgit
+'
+
+test_expect_success JGIT 'we can read jgit bitmaps' '
+ git clone . compat-jgit &&
+ (
+ cd compat-jgit &&
+ rm -f .git/objects/pack/*.bitmap &&
+ jgit gc &&
+ git rev-list --test-bitmap HEAD
+ )
+'
+
+test_expect_success JGIT 'jgit can read our bitmaps' '
+ git clone . compat-us &&
+ (
+ cd compat-us &&
+ git repack -adb &&
+ # jgit gc will barf if it does not like our bitmaps
+ jgit gc
+ )
+'
+
+test_expect_success 'splitting packs does not generate bogus bitmaps' '
+ test-genrandom foo $((1024 * 1024)) >rand &&
+ git add rand &&
+ git commit -m "commit with big file" &&
+ git -c pack.packSizeLimit=500k repack -adb &&
+ git init --bare no-bitmaps.git &&
+ git -C no-bitmaps.git fetch .. HEAD
+'
+
+test_done
diff --git a/t/t5311-pack-bitmaps-shallow.sh b/t/t5311-pack-bitmaps-shallow.sh
new file mode 100755
index 0000000000..872a95df33
--- /dev/null
+++ b/t/t5311-pack-bitmaps-shallow.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+test_description='check bitmap operation with shallow repositories'
+. ./test-lib.sh
+
+# We want to create a situation where the shallow, grafted
+# view of reachability does not match reality in a way that
+# might cause us to send insufficient objects.
+#
+# We do this with a history that repeats a state, like:
+#
+# A -- B -- C
+# file=1 file=2 file=1
+#
+# and then create a shallow clone to the second commit, B.
+# In a non-shallow clone, that would mean we already have
+# the tree for A. But in a shallow one, we've grafted away
+# A, and fetching A to B requires that the other side send
+# us the tree for file=1.
+test_expect_success 'setup shallow repo' '
+ echo 1 >file &&
+ git add file &&
+ git commit -m orig &&
+ echo 2 >file &&
+ git commit -a -m update &&
+ git clone --no-local --bare --depth=1 . shallow.git &&
+ echo 1 >file &&
+ git commit -a -m repeat
+'
+
+test_expect_success 'turn on bitmaps in the parent' '
+ git repack -adb
+'
+
+test_expect_success 'shallow fetch from bitmapped repo' '
+ (cd shallow.git && git fetch)
+'
+
+test_done
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index 129fc88bd2..0736bcbcd5 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -164,6 +164,7 @@ test_expect_success 'receive-pack runs auto-gc in remote repo' '
# Set the child to auto-pack if more than one pack exists
cd child &&
git config gc.autopacklimit 1 &&
+ git config gc.autodetach false &&
git branch test_auto_gc &&
# And create a file that follows the temporary object naming
# convention for the auto-gc to remove
diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh
index 17bcb0b040..7f278d8ce9 100755
--- a/t/t5401-update-hooks.sh
+++ b/t/t5401-update-hooks.sh
@@ -135,4 +135,17 @@ test_expect_success 'send-pack stderr contains hook messages' '
test_cmp expect actual
'
+test_expect_success 'pre-receive hook that forgets to read its input' '
+ write_script victim.git/hooks/pre-receive <<-\EOF &&
+ exit 0
+ EOF
+ rm -f victim.git/hooks/update victim.git/hooks/post-update &&
+
+ for v in $(test_seq 100 999)
+ do
+ git branch branch_$v master || return
+ done &&
+ git push ./victim.git "+refs/heads/*:refs/heads/*"
+'
+
test_done
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 1753ef2b91..fc898c9eac 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -39,7 +39,7 @@ test_expect_success 'post-checkout receives the right arguments with HEAD unchan
old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
- test $old = $new -a $flag = 1
+ test $old = $new && test $flag = 1
'
test_expect_success 'post-checkout runs as expected ' '
@@ -52,7 +52,7 @@ test_expect_success 'post-checkout args are correct with git checkout -b ' '
old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
- test $old = $new -a $flag = 1
+ test $old = $new && test $flag = 1
'
test_expect_success 'post-checkout receives the right args with HEAD changed ' '
@@ -60,7 +60,7 @@ test_expect_success 'post-checkout receives the right args with HEAD changed ' '
old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
- test $old != $new -a $flag = 1
+ test $old != $new && test $flag = 1
'
test_expect_success 'post-checkout receives the right args when not switching branches ' '
@@ -68,7 +68,7 @@ test_expect_success 'post-checkout receives the right args when not switching br
old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
- test $old = $new -a $flag = 0
+ test $old = $new && test $flag = 0
'
if test "$(git config --bool core.filemode)" = true; then
diff --git a/t/t5408-send-pack-stdin.sh b/t/t5408-send-pack-stdin.sh
new file mode 100755
index 0000000000..e8737df6f9
--- /dev/null
+++ b/t/t5408-send-pack-stdin.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+test_description='send-pack --stdin tests'
+. ./test-lib.sh
+
+create_ref () {
+ tree=$(git write-tree) &&
+ test_tick &&
+ commit=$(echo "$1" | git commit-tree $tree) &&
+ git update-ref "$1" $commit
+}
+
+clear_remote () {
+ rm -rf remote.git &&
+ git init --bare remote.git
+}
+
+verify_push () {
+ git rev-parse "$1" >expect &&
+ git --git-dir=remote.git rev-parse "${2:-$1}" >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'setup refs' '
+ cat >refs <<-\EOF &&
+ refs/heads/A
+ refs/heads/C
+ refs/tags/D
+ refs/heads/B
+ refs/tags/E
+ EOF
+ for i in $(cat refs); do
+ create_ref $i || return 1
+ done
+'
+
+# sanity check our setup
+test_expect_success 'refs on cmdline' '
+ clear_remote &&
+ git send-pack remote.git $(cat refs) &&
+ for i in $(cat refs); do
+ verify_push $i || return 1
+ done
+'
+
+test_expect_success 'refs over stdin' '
+ clear_remote &&
+ git send-pack remote.git --stdin <refs &&
+ for i in $(cat refs); do
+ verify_push $i || return 1
+ done
+'
+
+test_expect_success 'stdin lines are full refspecs' '
+ clear_remote &&
+ echo "A:other" >input &&
+ git send-pack remote.git --stdin <input &&
+ verify_push refs/heads/A refs/heads/other
+'
+
+test_expect_success 'stdin mixed with cmdline' '
+ clear_remote &&
+ echo A >input &&
+ git send-pack remote.git --stdin B <input &&
+ verify_push A &&
+ verify_push B
+'
+
+test_expect_success 'cmdline refs written in order' '
+ clear_remote &&
+ test_must_fail git send-pack remote.git A:foo B:foo &&
+ verify_push A foo
+'
+
+test_expect_success '--stdin refs come after cmdline' '
+ clear_remote &&
+ echo A:foo >input &&
+ test_must_fail git send-pack remote.git --stdin B:foo <input &&
+ verify_push B foo
+'
+
+test_expect_success 'refspecs and --mirror do not mix (cmdline)' '
+ clear_remote &&
+ test_must_fail git send-pack remote.git --mirror $(cat refs)
+'
+
+test_expect_success 'refspecs and --mirror do not mix (stdin)' '
+ clear_remote &&
+ test_must_fail git send-pack remote.git --mirror --stdin <refs
+'
+
+test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 07986d94bd..d78f3201f4 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -88,7 +88,7 @@ test_expect_success 'fetch --prune on its own works as expected' '
cd "$D" &&
git clone . prune &&
cd prune &&
- git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+ git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune origin &&
test_must_fail git rev-parse origin/extrabranch
@@ -98,7 +98,7 @@ test_expect_success 'fetch --prune with a branch name keeps branches' '
cd "$D" &&
git clone . prune-branch &&
cd prune-branch &&
- git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+ git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune origin master &&
git rev-parse origin/extrabranch
@@ -113,25 +113,65 @@ test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
git rev-parse origin/master
'
-test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' '
+test_expect_success 'fetch --prune handles overlapping refspecs' '
+ cd "$D" &&
+ git update-ref refs/pull/42/head master &&
+ git clone . prune-overlapping &&
+ cd prune-overlapping &&
+ git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+
+ git fetch --prune origin &&
+ git rev-parse origin/master &&
+ git rev-parse origin/pr/42 &&
+
+ git config --unset-all remote.origin.fetch
+ git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+ git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
+
+ git fetch --prune origin &&
+ git rev-parse origin/master &&
+ git rev-parse origin/pr/42
+'
+
+test_expect_success 'fetch --prune --tags prunes branches but not tags' '
cd "$D" &&
git clone . prune-tags &&
cd prune-tags &&
- git fetch origin refs/heads/master:refs/tags/sometag &&
+ git tag sometag master &&
+ # Create what looks like a remote-tracking branch from an earlier
+ # fetch that has since been deleted from the remote:
+ git update-ref refs/remotes/origin/fake-remote master &&
git fetch --prune --tags origin &&
git rev-parse origin/master &&
- test_must_fail git rev-parse somebranch
+ test_must_fail git rev-parse origin/fake-remote &&
+ git rev-parse sometag
'
-test_expect_success 'fetch --prune --tags with branch does not delete other remote-tracking branches' '
+test_expect_success 'fetch --prune --tags with branch does not prune other things' '
cd "$D" &&
git clone . prune-tags-branch &&
cd prune-tags-branch &&
- git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+ git tag sometag master &&
+ git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune --tags origin master &&
- git rev-parse origin/extrabranch
+ git rev-parse origin/extrabranch &&
+ git rev-parse sometag
+'
+
+test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '
+ cd "$D" &&
+ git clone . prune-tags-refspec &&
+ cd prune-tags-refspec &&
+ git tag sometag master &&
+ git update-ref refs/remotes/origin/foo/otherbranch master &&
+ git update-ref refs/remotes/origin/extrabranch master &&
+
+ git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
+ test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
+ git rev-parse origin/extrabranch &&
+ git rev-parse sometag
'
test_expect_success 'fetch tags when there is no tags' '
@@ -281,7 +321,7 @@ test_expect_success 'fetch via rsync' '
mkdir rsynced &&
(cd rsynced &&
git init --bare &&
- git fetch "rsync:$(pwd)/../.git" master:refs/heads/master &&
+ git fetch "rsync:../.git" master:refs/heads/master &&
git gc --prune &&
test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
git fsck --full)
@@ -292,7 +332,7 @@ test_expect_success 'push via rsync' '
(cd rsynced2 &&
git init) &&
(cd rsynced &&
- git push "rsync:$(pwd)/../rsynced2/.git" master) &&
+ git push "rsync:../rsynced2/.git" master) &&
(cd rsynced2 &&
git gc --prune &&
test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
@@ -303,7 +343,7 @@ test_expect_success 'push via rsync' '
mkdir rsynced3 &&
(cd rsynced3 &&
git init) &&
- git push --all "rsync:$(pwd)/rsynced3/.git" &&
+ git push --all "rsync:rsynced3/.git" &&
(cd rsynced3 &&
test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
git fsck --full)
@@ -407,6 +447,43 @@ test_expect_success 'explicit pull should update tracking' '
)
'
+test_expect_success 'explicit --refmap is allowed only with command-line refspec' '
+ cd "$D" &&
+ (
+ cd three &&
+ test_must_fail git fetch --refmap="*:refs/remotes/none/*"
+ )
+'
+
+test_expect_success 'explicit --refmap option overrides remote.*.fetch' '
+ cd "$D" &&
+ git branch -f side &&
+ (
+ cd three &&
+ git update-ref refs/remotes/origin/master base-origin-master &&
+ o=$(git rev-parse --verify refs/remotes/origin/master) &&
+ git fetch --refmap="refs/heads/*:refs/remotes/other/*" origin master &&
+ n=$(git rev-parse --verify refs/remotes/origin/master) &&
+ test "$o" = "$n" &&
+ test_must_fail git rev-parse --verify refs/remotes/origin/side &&
+ git rev-parse --verify refs/remotes/other/master
+ )
+'
+
+test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '
+ cd "$D" &&
+ git branch -f side &&
+ (
+ cd three &&
+ git update-ref refs/remotes/origin/master base-origin-master &&
+ o=$(git rev-parse --verify refs/remotes/origin/master) &&
+ git fetch --refmap="" origin master &&
+ n=$(git rev-parse --verify refs/remotes/origin/master) &&
+ test "$o" = "$n" &&
+ test_must_fail git rev-parse --verify refs/remotes/origin/side
+ )
+'
+
test_expect_success 'configured fetch updates tracking' '
cd "$D" &&
@@ -594,6 +671,32 @@ test_expect_success 'all boundary commits are excluded' '
test_bundle_object_count .git/objects/pack/pack-${pack##pack }.pack 3
'
+test_expect_success 'fetch --prune prints the remotes url' '
+ git branch goodbye &&
+ git clone . only-prunes &&
+ git branch -D goodbye &&
+ (
+ cd only-prunes &&
+ git fetch --prune origin 2>&1 | head -n1 >../actual
+ ) &&
+ echo "From ${D}/." >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'branchname D/F conflict resolved by --prune' '
+ git branch dir/file &&
+ git clone . prune-df-conflict &&
+ git branch -D dir/file &&
+ git branch dir &&
+ (
+ cd prune-df-conflict &&
+ git fetch --prune &&
+ git rev-parse origin/dir >../actual
+ ) &&
+ git rev-parse dir >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'fetching a one-level ref works' '
test_commit extra &&
git reset --hard HEAD^ &&
diff --git a/t/t5511-refspec.sh b/t/t5511-refspec.sh
index c28932216b..de6db86ccf 100755
--- a/t/t5511-refspec.sh
+++ b/t/t5511-refspec.sh
@@ -5,7 +5,6 @@ test_description='refspec parsing'
. ./test-lib.sh
test_refspec () {
-
kind=$1 refspec=$2 expect=$3
git config remote.frotz.url "." &&
git config --remove-section remote.frotz &&
@@ -84,4 +83,9 @@ test_refspec push 'refs/heads/*/*/for-linus:refs/remotes/mine/*' invalid
test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*'
test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*'
+good=$(printf '\303\204')
+test_refspec fetch "refs/heads/${good}"
+bad=$(printf '\011tab')
+test_refspec fetch "refs/heads/${bad}" invalid
+
test_done
diff --git a/t/t5515/fetch.br-unconfig_--tags_.._.git b/t/t5515/fetch.br-unconfig_--tags_.._.git
index 1669cc4af0..0f70f66c70 100644
--- a/t/t5515/fetch.br-unconfig_--tags_.._.git
+++ b/t/t5515/fetch.br-unconfig_--tags_.._.git
@@ -1,4 +1,5 @@
# br-unconfig --tags ../.git
+0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../
diff --git a/t/t5515/fetch.master_--tags_.._.git b/t/t5515/fetch.master_--tags_.._.git
index 8a7493537b..ab473a6e1f 100644
--- a/t/t5515/fetch.master_--tags_.._.git
+++ b/t/t5515/fetch.master_--tags_.._.git
@@ -1,4 +1,5 @@
# master --tags ../.git
+0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 99c32d7539..f4da20aa9b 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -11,6 +11,7 @@ This test checks the following functionality:
* hooks
* --porcelain output format
* hiderefs
+* reflogs
'
. ./test-lib.sh
@@ -536,6 +537,19 @@ test_expect_success 'push with config branch.*.pushremote' '
check_push_result down_repo $the_commit heads/master
'
+test_expect_success 'branch.*.pushremote config order is irrelevant' '
+ mk_test one_repo heads/master &&
+ mk_test two_repo heads/master &&
+ test_config remote.one.url one_repo &&
+ test_config remote.two.url two_repo &&
+ test_config branch.master.pushremote two_repo &&
+ test_config remote.pushdefault one_repo &&
+ test_config push.default matching &&
+ git push &&
+ check_push_result one_repo $the_first_commit heads/master &&
+ check_push_result two_repo $the_commit heads/master
+'
+
test_expect_success 'push with dry-run' '
mk_test testrepo heads/master &&
@@ -1126,6 +1140,81 @@ test_expect_success 'fetch follows tags by default' '
test_cmp expect actual
'
+test_expect_success 'pushing a specific ref applies remote.$name.push as refmap' '
+ mk_test testrepo heads/master &&
+ rm -fr src dst &&
+ git init src &&
+ git init --bare dst &&
+ (
+ cd src &&
+ git pull ../testrepo master &&
+ git branch next &&
+ git config remote.dst.url ../dst &&
+ git config remote.dst.push "+refs/heads/*:refs/remotes/src/*" &&
+ git push dst master &&
+ git show-ref refs/heads/master |
+ sed -e "s|refs/heads/|refs/remotes/src/|" >../dst/expect
+ ) &&
+ (
+ cd dst &&
+ test_must_fail git show-ref refs/heads/next &&
+ test_must_fail git show-ref refs/heads/master &&
+ git show-ref refs/remotes/src/master >actual
+ ) &&
+ test_cmp dst/expect dst/actual
+'
+
+test_expect_success 'with no remote.$name.push, it is not used as refmap' '
+ mk_test testrepo heads/master &&
+ rm -fr src dst &&
+ git init src &&
+ git init --bare dst &&
+ (
+ cd src &&
+ git pull ../testrepo master &&
+ git branch next &&
+ git config remote.dst.url ../dst &&
+ git config push.default matching &&
+ git push dst master &&
+ git show-ref refs/heads/master >../dst/expect
+ ) &&
+ (
+ cd dst &&
+ test_must_fail git show-ref refs/heads/next &&
+ git show-ref refs/heads/master >actual
+ ) &&
+ test_cmp dst/expect dst/actual
+'
+
+test_expect_success 'with no remote.$name.push, upstream mapping is used' '
+ mk_test testrepo heads/master &&
+ rm -fr src dst &&
+ git init src &&
+ git init --bare dst &&
+ (
+ cd src &&
+ git pull ../testrepo master &&
+ git branch next &&
+ git config remote.dst.url ../dst &&
+ git config remote.dst.fetch "+refs/heads/*:refs/remotes/dst/*" &&
+ git config push.default upstream &&
+
+ git config branch.master.merge refs/heads/trunk &&
+ git config branch.master.remote dst &&
+
+ git push dst master &&
+ git show-ref refs/heads/master |
+ sed -e "s|refs/heads/master|refs/heads/trunk|" >../dst/expect
+ ) &&
+ (
+ cd dst &&
+ test_must_fail git show-ref refs/heads/master &&
+ test_must_fail git show-ref refs/heads/next &&
+ git show-ref refs/heads/trunk >actual
+ ) &&
+ test_cmp dst/expect dst/actual
+'
+
test_expect_success 'push does not follow tags by default' '
mk_test testrepo heads/master &&
rm -fr src dst &&
@@ -1189,4 +1278,56 @@ EOF
git push --no-thin --receive-pack="$rcvpck" no-thin/.git refs/heads/master:refs/heads/foo
'
+test_expect_success 'pushing a tag pushes the tagged object' '
+ rm -rf dst.git &&
+ blob=$(echo unreferenced | git hash-object -w --stdin) &&
+ git tag -m foo tag-of-blob $blob &&
+ git init --bare dst.git &&
+ git push dst.git tag-of-blob &&
+ # the receiving index-pack should have noticed
+ # any problems, but we double check
+ echo unreferenced >expect &&
+ git --git-dir=dst.git cat-file blob tag-of-blob >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'push into bare respects core.logallrefupdates' '
+ rm -rf dst.git &&
+ git init --bare dst.git &&
+ git -C dst.git config core.logallrefupdates true &&
+
+ # double push to test both with and without
+ # the actual pack transfer
+ git push dst.git master:one &&
+ echo "one@{0} push" >expect &&
+ git -C dst.git log -g --format="%gd %gs" one >actual &&
+ test_cmp expect actual &&
+
+ git push dst.git master:two &&
+ echo "two@{0} push" >expect &&
+ git -C dst.git log -g --format="%gd %gs" two >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'fetch into bare respects core.logallrefupdates' '
+ rm -rf dst.git &&
+ git init --bare dst.git &&
+ (
+ cd dst.git &&
+ git config core.logallrefupdates true &&
+
+ # as above, we double-fetch to test both
+ # with and without pack transfer
+ git fetch .. master:one &&
+ echo "one@{0} fetch .. master:one: storing head" >expect &&
+ git log -g --format="%gd %gs" one >actual &&
+ test_cmp expect actual &&
+
+ git fetch .. master:two &&
+ echo "two@{0} fetch .. master:two: storing head" >expect &&
+ git log -g --format="%gd %gs" two >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t5525-fetch-tagopt.sh b/t/t5525-fetch-tagopt.sh
index 4fbf7a120f..45815f7378 100755
--- a/t/t5525-fetch-tagopt.sh
+++ b/t/t5525-fetch-tagopt.sh
@@ -8,7 +8,8 @@ setup_clone () {
git clone --mirror . $1 &&
git remote add remote_$1 $1 &&
(cd $1 &&
- git tag tag_$1)
+ git tag tag_$1 &&
+ git branch branch_$1)
}
test_expect_success setup '
@@ -21,21 +22,33 @@ test_expect_success setup '
test_expect_success "fetch with tagopt=--no-tags does not get tag" '
git fetch remote_one &&
- test_must_fail git show-ref tag_one
+ test_must_fail git show-ref tag_one &&
+ git show-ref remote_one/branch_one
'
test_expect_success "fetch --tags with tagopt=--no-tags gets tag" '
+ (
+ cd one &&
+ git branch second_branch_one
+ ) &&
git fetch --tags remote_one &&
- git show-ref tag_one
+ git show-ref tag_one &&
+ git show-ref remote_one/second_branch_one
'
test_expect_success "fetch --no-tags with tagopt=--tags does not get tag" '
git fetch --no-tags remote_two &&
- test_must_fail git show-ref tag_two
+ test_must_fail git show-ref tag_two &&
+ git show-ref remote_two/branch_two
'
test_expect_success "fetch with tagopt=--tags gets tag" '
+ (
+ cd two &&
+ git branch second_branch_two
+ ) &&
git fetch remote_two &&
- git show-ref tag_two
+ git show-ref tag_two &&
+ git show-ref remote_two/second_branch_two
'
test_done
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
new file mode 100755
index 0000000000..9871307fd4
--- /dev/null
+++ b/t/t5529-push-errors.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+test_description='detect some push errors early (before contacting remote)'
+. ./test-lib.sh
+
+test_expect_success 'setup commits' '
+ test_commit one
+'
+
+test_expect_success 'setup remote' '
+ git init --bare remote.git &&
+ git remote add origin remote.git
+'
+
+test_expect_success 'setup fake receive-pack' '
+ FAKE_RP_ROOT=$(pwd) &&
+ export FAKE_RP_ROOT &&
+ write_script fake-rp <<-\EOF &&
+ echo yes >"$FAKE_RP_ROOT"/rp-ran
+ exit 1
+ EOF
+ git config remote.origin.receivepack "\"\$FAKE_RP_ROOT/fake-rp\""
+'
+
+test_expect_success 'detect missing branches early' '
+ echo no >rp-ran &&
+ echo no >expect &&
+ test_must_fail git push origin missing &&
+ test_cmp expect rp-ran
+'
+
+test_expect_success 'detect missing sha1 expressions early' '
+ echo no >rp-ran &&
+ echo no >expect &&
+ test_must_fail git push origin master~2:master &&
+ test_cmp expect rp-ran
+'
+
+test_expect_success 'detect ambiguous refs early' '
+ git branch foo &&
+ git tag foo &&
+ echo no >rp-ran &&
+ echo no >expect &&
+ test_must_fail git push origin foo &&
+ test_cmp expect rp-ran
+'
+
+test_done
diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh
index 8c16e045a0..445bb5fe26 100755
--- a/t/t5531-deep-submodule-push.sh
+++ b/t/t5531-deep-submodule-push.sh
@@ -12,6 +12,7 @@ test_expect_success setup '
(
cd work &&
git init &&
+ git config push.default matching &&
mkdir -p gar/bage &&
(
cd gar/bage &&
diff --git a/t/t5534-push-signed.sh b/t/t5534-push-signed.sh
new file mode 100755
index 0000000000..ecb8d446a5
--- /dev/null
+++ b/t/t5534-push-signed.sh
@@ -0,0 +1,171 @@
+#!/bin/sh
+
+test_description='signed push'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-gpg.sh
+
+prepare_dst () {
+ rm -fr dst &&
+ test_create_repo dst &&
+
+ git push dst master:noop master:ff master:noff
+}
+
+test_expect_success setup '
+ # master, ff and noff branches pointing at the same commit
+ test_tick &&
+ git commit --allow-empty -m initial &&
+
+ git checkout -b noop &&
+ git checkout -b ff &&
+ git checkout -b noff &&
+
+ # noop stays the same, ff advances, noff rewrites
+ test_tick &&
+ git commit --allow-empty --amend -m rewritten &&
+ git checkout ff &&
+
+ test_tick &&
+ git commit --allow-empty -m second
+'
+
+test_expect_success 'unsigned push does not send push certificate' '
+ prepare_dst &&
+ mkdir -p dst/.git/hooks &&
+ write_script dst/.git/hooks/post-receive <<-\EOF &&
+ # discard the update list
+ cat >/dev/null
+ # record the push certificate
+ if test -n "${GIT_PUSH_CERT-}"
+ then
+ git cat-file blob $GIT_PUSH_CERT >../push-cert
+ fi
+ EOF
+
+ git push dst noop ff +noff &&
+ ! test -f dst/push-cert
+'
+
+test_expect_success 'talking with a receiver without push certificate support' '
+ prepare_dst &&
+ mkdir -p dst/.git/hooks &&
+ write_script dst/.git/hooks/post-receive <<-\EOF &&
+ # discard the update list
+ cat >/dev/null
+ # record the push certificate
+ if test -n "${GIT_PUSH_CERT-}"
+ then
+ git cat-file blob $GIT_PUSH_CERT >../push-cert
+ fi
+ EOF
+
+ git push dst noop ff +noff &&
+ ! test -f dst/push-cert
+'
+
+test_expect_success 'push --signed fails with a receiver without push certificate support' '
+ prepare_dst &&
+ mkdir -p dst/.git/hooks &&
+ test_must_fail git push --signed dst noop ff +noff 2>err &&
+ test_i18ngrep "the receiving end does not support" err
+'
+
+test_expect_success GPG 'no certificate for a signed push with no update' '
+ prepare_dst &&
+ mkdir -p dst/.git/hooks &&
+ write_script dst/.git/hooks/post-receive <<-\EOF &&
+ if test -n "${GIT_PUSH_CERT-}"
+ then
+ git cat-file blob $GIT_PUSH_CERT >../push-cert
+ fi
+ EOF
+ git push dst noop &&
+ ! test -f dst/push-cert
+'
+
+test_expect_success GPG 'signed push sends push certificate' '
+ prepare_dst &&
+ mkdir -p dst/.git/hooks &&
+ git -C dst config receive.certnonceseed sekrit &&
+ write_script dst/.git/hooks/post-receive <<-\EOF &&
+ # discard the update list
+ cat >/dev/null
+ # record the push certificate
+ if test -n "${GIT_PUSH_CERT-}"
+ then
+ git cat-file blob $GIT_PUSH_CERT >../push-cert
+ fi &&
+
+ cat >../push-cert-status <<E_O_F
+ SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
+ KEY=${GIT_PUSH_CERT_KEY-nokey}
+ STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
+ NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
+ NONCE=${GIT_PUSH_CERT_NONCE-nononce}
+ E_O_F
+
+ EOF
+
+ git push --signed dst noop ff +noff &&
+
+ (
+ cat <<-\EOF &&
+ SIGNER=C O Mitter <committer@example.com>
+ KEY=13B6F51ECDDE430D
+ STATUS=G
+ NONCE_STATUS=OK
+ EOF
+ sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
+ ) >expect &&
+
+ grep "$(git rev-parse noop ff) refs/heads/ff" dst/push-cert &&
+ grep "$(git rev-parse noop noff) refs/heads/noff" dst/push-cert &&
+ test_cmp expect dst/push-cert-status
+'
+
+test_expect_success GPG 'fail without key and heed user.signingkey' '
+ prepare_dst &&
+ mkdir -p dst/.git/hooks &&
+ git -C dst config receive.certnonceseed sekrit &&
+ write_script dst/.git/hooks/post-receive <<-\EOF &&
+ # discard the update list
+ cat >/dev/null
+ # record the push certificate
+ if test -n "${GIT_PUSH_CERT-}"
+ then
+ git cat-file blob $GIT_PUSH_CERT >../push-cert
+ fi &&
+
+ cat >../push-cert-status <<E_O_F
+ SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
+ KEY=${GIT_PUSH_CERT_KEY-nokey}
+ STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
+ NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
+ NONCE=${GIT_PUSH_CERT_NONCE-nononce}
+ E_O_F
+
+ EOF
+
+ unset GIT_COMMITTER_EMAIL &&
+ git config user.email hasnokey@nowhere.com &&
+ test_must_fail git push --signed dst noop ff +noff &&
+ git config user.signingkey committer@example.com &&
+ git push --signed dst noop ff +noff &&
+
+ (
+ cat <<-\EOF &&
+ SIGNER=C O Mitter <committer@example.com>
+ KEY=13B6F51ECDDE430D
+ STATUS=G
+ NONCE_STATUS=OK
+ EOF
+ sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
+ ) >expect &&
+
+ grep "$(git rev-parse noop ff) refs/heads/ff" dst/push-cert &&
+ grep "$(git rev-parse noop noff) refs/heads/noff" dst/push-cert &&
+ test_cmp expect dst/push-cert-status
+'
+
+test_done
diff --git a/t/t5536-fetch-conflicts.sh b/t/t5536-fetch-conflicts.sh
new file mode 100755
index 0000000000..6c5d3a4ce0
--- /dev/null
+++ b/t/t5536-fetch-conflicts.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+test_description='fetch handles conflicting refspecs correctly'
+
+. ./test-lib.sh
+
+D=$(pwd)
+
+setup_repository () {
+ git init "$1" && (
+ cd "$1" &&
+ git config remote.origin.url "$D" &&
+ shift &&
+ for refspec in "$@"
+ do
+ git config --add remote.origin.fetch "$refspec"
+ done
+ )
+}
+
+verify_stderr () {
+ cat >expected &&
+ # We're not interested in the error
+ # "fatal: The remote end hung up unexpectedly":
+ grep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort &&
+ test_cmp expected actual
+}
+
+test_expect_success 'setup' '
+ git commit --allow-empty -m "Initial" &&
+ git branch branch1 &&
+ git tag tag1 &&
+ git commit --allow-empty -m "First" &&
+ git branch branch2 &&
+ git tag tag2
+'
+
+test_expect_success 'fetch with no conflict' '
+ setup_repository ok "+refs/heads/*:refs/remotes/origin/*" && (
+ cd ok &&
+ git fetch origin
+ )
+'
+
+test_expect_success 'fetch conflict: config vs. config' '
+ setup_repository ccc \
+ "+refs/heads/branch1:refs/remotes/origin/branch1" \
+ "+refs/heads/branch2:refs/remotes/origin/branch1" && (
+ cd ccc &&
+ test_must_fail git fetch origin 2>error &&
+ verify_stderr <<-\EOF
+ fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1
+ EOF
+ )
+'
+
+test_expect_success 'fetch duplicate: config vs. config' '
+ setup_repository dcc \
+ "+refs/heads/*:refs/remotes/origin/*" \
+ "+refs/heads/branch1:refs/remotes/origin/branch1" && (
+ cd dcc &&
+ git fetch origin
+ )
+'
+
+test_expect_success 'fetch conflict: arg overrides config' '
+ setup_repository aoc \
+ "+refs/heads/*:refs/remotes/origin/*" && (
+ cd aoc &&
+ git fetch origin refs/heads/branch2:refs/remotes/origin/branch1
+ )
+'
+
+test_expect_success 'fetch conflict: arg vs. arg' '
+ setup_repository caa && (
+ cd caa &&
+ test_must_fail git fetch origin \
+ refs/heads/*:refs/remotes/origin/* \
+ refs/heads/branch2:refs/remotes/origin/branch1 2>error &&
+ verify_stderr <<-\EOF
+ fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1
+ EOF
+ )
+'
+
+test_expect_success 'fetch conflict: criss-cross args' '
+ setup_repository xaa \
+ "+refs/heads/*:refs/remotes/origin/*" && (
+ cd xaa &&
+ git fetch origin \
+ refs/heads/branch1:refs/remotes/origin/branch2 \
+ refs/heads/branch2:refs/remotes/origin/branch1 2>error &&
+ verify_stderr <<-\EOF
+ warning: refs/remotes/origin/branch1 usually tracks refs/heads/branch1, not refs/heads/branch2
+ warning: refs/remotes/origin/branch2 usually tracks refs/heads/branch2, not refs/heads/branch1
+ EOF
+ )
+'
+
+test_done
diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh
new file mode 100755
index 0000000000..a980574682
--- /dev/null
+++ b/t/t5537-fetch-shallow.sh
@@ -0,0 +1,189 @@
+#!/bin/sh
+
+test_description='fetch/clone from a shallow clone'
+
+. ./test-lib.sh
+
+commit() {
+ echo "$1" >tracked &&
+ git add tracked &&
+ git commit -m "$1"
+}
+
+test_expect_success 'setup' '
+ commit 1 &&
+ commit 2 &&
+ commit 3 &&
+ commit 4 &&
+ git config --global transfer.fsckObjects true
+'
+
+test_expect_success 'setup shallow clone' '
+ git clone --no-local --depth=2 .git shallow &&
+ git --git-dir=shallow/.git log --format=%s >actual &&
+ cat <<EOF >expect &&
+4
+3
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'clone from shallow clone' '
+ git clone --no-local shallow shallow2 &&
+ (
+ cd shallow2 &&
+ git fsck &&
+ git log --format=%s >actual &&
+ cat <<EOF >expect &&
+4
+3
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'fetch from shallow clone' '
+ (
+ cd shallow &&
+ commit 5
+ ) &&
+ (
+ cd shallow2 &&
+ git fetch &&
+ git fsck &&
+ git log --format=%s origin/master >actual &&
+ cat <<EOF >expect &&
+5
+4
+3
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'fetch --depth from shallow clone' '
+ (
+ cd shallow &&
+ commit 6
+ ) &&
+ (
+ cd shallow2 &&
+ git fetch --depth=2 &&
+ git fsck &&
+ git log --format=%s origin/master >actual &&
+ cat <<EOF >expect &&
+6
+5
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'fetch --unshallow from shallow clone' '
+ (
+ cd shallow2 &&
+ git fetch --unshallow &&
+ git fsck &&
+ git log --format=%s origin/master >actual &&
+ cat <<EOF >expect &&
+6
+5
+4
+3
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'fetch something upstream has but hidden by clients shallow boundaries' '
+ # the blob "1" is available in .git but hidden by the
+ # shallow2/.git/shallow and it should be resent
+ ! git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` >/dev/null &&
+ echo 1 >1.t &&
+ git add 1.t &&
+ git commit -m add-1-back &&
+ (
+ cd shallow2 &&
+ git fetch ../.git +refs/heads/master:refs/remotes/top/master &&
+ git fsck &&
+ git log --format=%s top/master >actual &&
+ cat <<EOF >expect &&
+add-1-back
+4
+3
+EOF
+ test_cmp expect actual
+ ) &&
+ git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` >/dev/null
+
+'
+
+test_expect_success 'fetch that requires changes in .git/shallow is filtered' '
+ (
+ cd shallow &&
+ git checkout --orphan no-shallow &&
+ commit no-shallow
+ ) &&
+ git init notshallow &&
+ (
+ cd notshallow &&
+ git fetch ../shallow/.git refs/heads/*:refs/remotes/shallow/*&&
+ git for-each-ref --format="%(refname)" >actual.refs &&
+ cat <<EOF >expect.refs &&
+refs/remotes/shallow/no-shallow
+EOF
+ test_cmp expect.refs actual.refs &&
+ git log --format=%s shallow/no-shallow >actual &&
+ cat <<EOF >expect &&
+no-shallow
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'fetch --update-shallow' '
+ (
+ cd shallow &&
+ git checkout master &&
+ commit 7 &&
+ git tag -m foo heavy-tag HEAD^ &&
+ git tag light-tag HEAD^:tracked
+ ) &&
+ (
+ cd notshallow &&
+ git fetch --update-shallow ../shallow/.git refs/heads/*:refs/remotes/shallow/* &&
+ git fsck &&
+ git for-each-ref --sort=refname --format="%(refname)" >actual.refs &&
+ cat <<EOF >expect.refs &&
+refs/remotes/shallow/master
+refs/remotes/shallow/no-shallow
+refs/tags/heavy-tag
+refs/tags/light-tag
+EOF
+ test_cmp expect.refs actual.refs &&
+ git log --format=%s shallow/master >actual &&
+ cat <<EOF >expect &&
+7
+6
+5
+4
+3
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success POSIXPERM,SANITY 'shallow fetch from a read-only repo' '
+ cp -R .git read-only.git &&
+ find read-only.git -print | xargs chmod -w &&
+ test_when_finished "find read-only.git -type d -print | xargs chmod +w" &&
+ git clone --no-local --depth=2 read-only.git from-read-only &&
+ git --git-dir=from-read-only/.git log --format=%s >actual &&
+ cat >expect <<EOF &&
+add-1-back
+4
+EOF
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t5538-push-shallow.sh b/t/t5538-push-shallow.sh
new file mode 100755
index 0000000000..ceee95b8a4
--- /dev/null
+++ b/t/t5538-push-shallow.sh
@@ -0,0 +1,123 @@
+#!/bin/sh
+
+test_description='push from/to a shallow clone'
+
+. ./test-lib.sh
+
+commit() {
+ echo "$1" >tracked &&
+ git add tracked &&
+ git commit -m "$1"
+}
+
+test_expect_success 'setup' '
+ git config --global transfer.fsckObjects true &&
+ commit 1 &&
+ commit 2 &&
+ commit 3 &&
+ commit 4 &&
+ git clone . full &&
+ (
+ git init full-abc &&
+ cd full-abc &&
+ commit a &&
+ commit b &&
+ commit c
+ ) &&
+ git clone --no-local --depth=2 .git shallow &&
+ git --git-dir=shallow/.git log --format=%s >actual &&
+ cat <<EOF >expect &&
+4
+3
+EOF
+ test_cmp expect actual &&
+ git clone --no-local --depth=2 full-abc/.git shallow2 &&
+ git --git-dir=shallow2/.git log --format=%s >actual &&
+ cat <<EOF >expect &&
+c
+b
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'push from shallow clone' '
+ (
+ cd shallow &&
+ commit 5 &&
+ git push ../.git +master:refs/remotes/shallow/master
+ ) &&
+ git log --format=%s shallow/master >actual &&
+ git fsck &&
+ cat <<EOF >expect &&
+5
+4
+3
+2
+1
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'push from shallow clone, with grafted roots' '
+ (
+ cd shallow2 &&
+ test_must_fail git push ../.git +master:refs/remotes/shallow2/master 2>err &&
+ grep "shallow2/master.*shallow update not allowed" err
+ ) &&
+ test_must_fail git rev-parse shallow2/master &&
+ git fsck
+'
+
+test_expect_success 'add new shallow root with receive.updateshallow on' '
+ test_config receive.shallowupdate true &&
+ (
+ cd shallow2 &&
+ git push ../.git +master:refs/remotes/shallow2/master
+ ) &&
+ git log --format=%s shallow2/master >actual &&
+ git fsck &&
+ cat <<EOF >expect &&
+c
+b
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'push from shallow to shallow' '
+ (
+ cd shallow &&
+ git --git-dir=../shallow2/.git config receive.shallowupdate true &&
+ git push ../shallow2/.git +master:refs/remotes/shallow/master &&
+ git --git-dir=../shallow2/.git config receive.shallowupdate false
+ ) &&
+ (
+ cd shallow2 &&
+ git log --format=%s shallow/master >actual &&
+ git fsck &&
+ cat <<EOF >expect &&
+5
+4
+3
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'push from full to shallow' '
+ ! git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` &&
+ commit 1 &&
+ git push shallow2/.git +master:refs/remotes/top/master &&
+ (
+ cd shallow2 &&
+ git log --format=%s top/master >actual &&
+ git fsck &&
+ cat <<EOF >expect &&
+1
+4
+3
+EOF
+ test_cmp expect actual &&
+ git cat-file blob `echo 1|git hash-object --stdin` >/dev/null
+ )
+'
+test_done
diff --git a/t/t5539-fetch-http-shallow.sh b/t/t5539-fetch-http-shallow.sh
new file mode 100755
index 0000000000..b46118846c
--- /dev/null
+++ b/t/t5539-fetch-http-shallow.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+test_description='fetch/clone from a shallow clone over http'
+
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+ skip_all='skipping test, git built without http support'
+ test_done
+fi
+
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+commit() {
+ echo "$1" >tracked &&
+ git add tracked &&
+ git commit -m "$1"
+}
+
+test_expect_success 'setup shallow clone' '
+ commit 1 &&
+ commit 2 &&
+ commit 3 &&
+ commit 4 &&
+ commit 5 &&
+ commit 6 &&
+ commit 7 &&
+ git clone --no-local --depth=5 .git shallow &&
+ git config --global transfer.fsckObjects true
+'
+
+test_expect_success 'clone http repository' '
+ git clone --bare --no-local shallow "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git clone $HTTPD_URL/smart/repo.git clone &&
+ (
+ cd clone &&
+ git fsck &&
+ git log --format=%s origin/master >actual &&
+ cat <<EOF >expect &&
+7
+6
+5
+4
+3
+EOF
+ test_cmp expect actual
+ )
+'
+
+# This test is tricky. We need large enough "have"s that fetch-pack
+# will put pkt-flush in between. Then we need a "have" the server
+# does not have, it'll send "ACK %s ready"
+test_expect_success 'no shallow lines after receiving ACK ready' '
+ (
+ cd shallow &&
+ test_tick &&
+ for i in $(test_seq 15)
+ do
+ git checkout --orphan unrelated$i &&
+ test_commit unrelated$i &&
+ git push -q "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
+ refs/heads/unrelated$i:refs/heads/unrelated$i &&
+ git push -q ../clone/.git \
+ refs/heads/unrelated$i:refs/heads/unrelated$i ||
+ exit 1
+ done &&
+ git checkout master &&
+ test_commit new &&
+ git push "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" master
+ ) &&
+ (
+ cd clone &&
+ git checkout --orphan newnew &&
+ test_commit new-too &&
+ GIT_TRACE_PACKET="$TRASH_DIRECTORY/trace" git fetch --depth=2 &&
+ grep "fetch-pack< ACK .* ready" ../trace &&
+ ! grep "fetch-pack> done" ../trace
+ )
+'
+
+stop_httpd
+test_done
diff --git a/t/t5540-http-push.sh b/t/t5540-http-push-webdav.sh
index 01d0d95b4d..8d7b3c57e3 100755
--- a/t/t5540-http-push.sh
+++ b/t/t5540-http-push-webdav.sh
@@ -16,7 +16,6 @@ then
fi
LIB_HTTPD_DAV=t
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5540'}
. "$TEST_DIRECTORY"/lib-httpd.sh
ROOT_PATH="$PWD"
start_httpd
@@ -154,7 +153,7 @@ test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
test_expect_success 'push to password-protected repository (user in URL)' '
test_commit pw-user &&
- set_askpass user@host &&
+ set_askpass user@host pass@host &&
git push "$HTTPD_URL_USER/auth/dumb/test_repo.git" HEAD &&
git rev-parse --verify HEAD >expect &&
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \
@@ -168,7 +167,7 @@ test_expect_failure 'user was prompted only once for password' '
test_expect_failure 'push to password-protected repository (no user in URL)' '
test_commit pw-nouser &&
- set_askpass user@host &&
+ set_askpass user@host pass@host &&
git push "$HTTPD_URL/auth/dumb/test_repo.git" HEAD &&
expect_askpass both user@host
git rev-parse --verify HEAD >expect &&
diff --git a/t/t5541-http-push.sh b/t/t5541-http-push-smart.sh
index 470ac54295..d2c681ebfd 100755
--- a/t/t5541-http-push.sh
+++ b/t/t5541-http-push-smart.sh
@@ -12,7 +12,7 @@ if test -n "$NO_CURL"; then
fi
ROOT_PATH="$PWD"
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5541'}
+. "$TEST_DIRECTORY"/lib-gpg.sh
. "$TEST_DIRECTORY"/lib-httpd.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
start_httpd
@@ -274,7 +274,7 @@ test_expect_success 'push over smart http with auth' '
cd "$ROOT_PATH/test_repo_clone" &&
echo push-auth-test >expect &&
test_commit push-auth-test &&
- set_askpass user@host &&
+ set_askpass user@host pass@host &&
git push "$HTTPD_URL"/auth/smart/test_repo.git &&
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
log -1 --format=%s >actual &&
@@ -286,7 +286,7 @@ test_expect_success 'push to auth-only-for-push repo' '
cd "$ROOT_PATH/test_repo_clone" &&
echo push-half-auth >expect &&
test_commit push-half-auth &&
- set_askpass user@host &&
+ set_askpass user@host pass@host &&
git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
log -1 --format=%s >actual &&
@@ -316,7 +316,7 @@ test_expect_success 'push into half-auth-complete requires password' '
cd "$ROOT_PATH/half-auth-clone" &&
echo two >expect &&
test_commit two &&
- set_askpass user@host &&
+ set_askpass user@host pass@host &&
git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
log -1 --format=%s >actual &&
@@ -324,5 +324,60 @@ test_expect_success 'push into half-auth-complete requires password' '
test_cmp expect actual
'
+run_with_limited_cmdline () {
+ (ulimit -s 128 && "$@")
+}
+
+test_lazy_prereq CMDLINE_LIMIT 'run_with_limited_cmdline true'
+
+test_expect_success CMDLINE_LIMIT 'push 2000 tags over http' '
+ sha1=$(git rev-parse HEAD) &&
+ test_seq 2000 |
+ sort |
+ sed "s|.*|$sha1 refs/tags/really-long-tag-name-&|" \
+ >.git/packed-refs &&
+ run_with_limited_cmdline git push --mirror
+'
+
+test_expect_success GPG 'push with post-receive to inspect certificate' '
+ (
+ cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+ mkdir -p hooks &&
+ write_script hooks/post-receive <<-\EOF &&
+ # discard the update list
+ cat >/dev/null
+ # record the push certificate
+ if test -n "${GIT_PUSH_CERT-}"
+ then
+ git cat-file blob $GIT_PUSH_CERT >../push-cert
+ fi &&
+ cat >../push-cert-status <<E_O_F
+ SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
+ KEY=${GIT_PUSH_CERT_KEY-nokey}
+ STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
+ NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
+ NONCE=${GIT_PUSH_CERT_NONCE-nononce}
+ E_O_F
+ EOF
+
+ git config receive.certnonceseed sekrit &&
+ git config receive.certnonceslop 30
+ ) &&
+ cd "$ROOT_PATH/test_repo_clone" &&
+ test_commit cert-test &&
+ git push --signed "$HTTPD_URL/smart/test_repo.git" &&
+ (
+ cd "$HTTPD_DOCUMENT_ROOT_PATH" &&
+ cat <<-\EOF &&
+ SIGNER=C O Mitter <committer@example.com>
+ KEY=13B6F51ECDDE430D
+ STATUS=G
+ NONCE_STATUS=OK
+ EOF
+ sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" push-cert
+ ) >expect &&
+ test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH/push-cert-status"
+'
+
stop_httpd
test_done
diff --git a/t/t5542-push-http-shallow.sh b/t/t5542-push-http-shallow.sh
new file mode 100755
index 0000000000..2a691e09eb
--- /dev/null
+++ b/t/t5542-push-http-shallow.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+test_description='push from/to a shallow clone over http'
+
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+ say 'skipping test, git built without http support'
+ test_done
+fi
+
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+commit() {
+ echo "$1" >tracked &&
+ git add tracked &&
+ git commit -m "$1"
+}
+
+test_expect_success 'setup' '
+ git config --global transfer.fsckObjects true &&
+ commit 1 &&
+ commit 2 &&
+ commit 3 &&
+ commit 4 &&
+ git clone . full &&
+ (
+ git init full-abc &&
+ cd full-abc &&
+ commit a &&
+ commit b &&
+ commit c
+ ) &&
+ git clone --no-local --depth=2 .git shallow &&
+ git --git-dir=shallow/.git log --format=%s >actual &&
+ cat <<EOF >expect &&
+4
+3
+EOF
+ test_cmp expect actual &&
+ git clone --no-local --depth=2 full-abc/.git shallow2 &&
+ git --git-dir=shallow2/.git log --format=%s >actual &&
+ cat <<EOF >expect &&
+c
+b
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'push to shallow repo via http' '
+ git clone --bare --no-local shallow "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ (
+ cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git config http.receivepack true
+ ) &&
+ (
+ cd full &&
+ commit 9 &&
+ git push $HTTPD_URL/smart/repo.git +master:refs/remotes/top/master
+ ) &&
+ (
+ cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git fsck &&
+ git log --format=%s top/master >actual &&
+ cat <<EOF >expect &&
+9
+4
+3
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'push from shallow repo via http' '
+ mv "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" shallow-upstream.git &&
+ git clone --bare --no-local full "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ (
+ cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git config http.receivepack true
+ ) &&
+ commit 10 &&
+ git push $HTTPD_URL/smart/repo.git +master:refs/remotes/top/master &&
+ (
+ cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git fsck &&
+ git log --format=%s top/master >actual &&
+ cat <<EOF >expect &&
+10
+4
+3
+2
+1
+EOF
+ test_cmp expect actual
+ )
+'
+
+stop_httpd
+test_done
diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch-dumb.sh
index f7d0f146f0..ac71418a1b 100755
--- a/t/t5550-http-fetch.sh
+++ b/t/t5550-http-fetch-dumb.sh
@@ -8,7 +8,6 @@ if test -n "$NO_CURL"; then
test_done
fi
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5550'}
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
@@ -62,13 +61,13 @@ test_expect_success 'http auth can use user/pass in URL' '
'
test_expect_success 'http auth can use just user in URL' '
- set_askpass user@host &&
+ set_askpass wrong pass@host &&
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-pass &&
expect_askpass pass user@host
'
test_expect_success 'http auth can request both user and pass' '
- set_askpass user@host &&
+ set_askpass user@host pass@host &&
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-both &&
expect_askpass both user@host
'
@@ -77,7 +76,7 @@ test_expect_success 'http auth respects credential helper config' '
test_config_global credential.helper "!f() {
cat >/dev/null
echo username=user@host
- echo password=user@host
+ echo password=pass@host
}; f" &&
set_askpass wrong &&
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-helper &&
@@ -86,14 +85,14 @@ test_expect_success 'http auth respects credential helper config' '
test_expect_success 'http auth can get username from config' '
test_config_global "credential.$HTTPD_URL.username" user@host &&
- set_askpass user@host &&
+ set_askpass wrong pass@host &&
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-user &&
expect_askpass pass user@host
'
test_expect_success 'configured username does not override URL' '
test_config_global "credential.$HTTPD_URL.username" wrong &&
- set_askpass user@host &&
+ set_askpass wrong pass@host &&
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-user2 &&
expect_askpass pass user@host
'
@@ -172,5 +171,30 @@ test_expect_success 'did not use upload-pack service' '
test_cmp exp act
'
+test_expect_success 'git client shows text/plain errors' '
+ test_must_fail git clone "$HTTPD_URL/error/text" 2>stderr &&
+ grep "this is the error message" stderr
+'
+
+test_expect_success 'git client does not show html errors' '
+ test_must_fail git clone "$HTTPD_URL/error/html" 2>stderr &&
+ ! grep "this is the error message" stderr
+'
+
+test_expect_success 'git client shows text/plain with a charset' '
+ test_must_fail git clone "$HTTPD_URL/error/charset" 2>stderr &&
+ grep "this is the error message" stderr
+'
+
+test_expect_success 'http error messages are reencoded' '
+ test_must_fail git clone "$HTTPD_URL/error/utf16" 2>stderr &&
+ grep "this is the error message" stderr
+'
+
+test_expect_success 'reencoding is robust to whitespace oddities' '
+ test_must_fail git clone "$HTTPD_URL/error/odd-spacing" 2>stderr &&
+ grep "this is the error message" stderr
+'
+
stop_httpd
test_done
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch-smart.sh
index afb439e09c..6cbc12d9a7 100755
--- a/t/t5551-http-fetch.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -8,7 +8,6 @@ if test -n "$NO_CURL"; then
test_done
fi
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5551'}
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
@@ -119,7 +118,7 @@ test_expect_success 'redirects re-root further requests' '
test_expect_success 'clone from password-protected repository' '
echo two >expect &&
- set_askpass user@host &&
+ set_askpass user@host pass@host &&
git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth &&
expect_askpass both user@host &&
git --git-dir=smart-auth log -1 --format=%s >actual &&
@@ -137,7 +136,7 @@ test_expect_success 'clone from auth-only-for-push repository' '
test_expect_success 'clone from auth-only-for-objects repository' '
echo two >expect &&
- set_askpass user@host &&
+ set_askpass user@host pass@host &&
git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
expect_askpass both user@host &&
git --git-dir=half-auth log -1 --format=%s >actual &&
@@ -151,7 +150,7 @@ test_expect_success 'no-op half-auth fetch does not require a password' '
'
test_expect_success 'redirects send auth to new location' '
- set_askpass user@host &&
+ set_askpass user@host pass@host &&
git -c credential.useHttpPath=true \
clone $HTTPD_URL/smart-redir-auth/repo.git repo-redir-auth &&
expect_askpass both user@host auth/smart/repo.git
@@ -214,8 +213,6 @@ test_expect_success 'cookies stored in http.cookiefile when http.savecookies set
test_cmp expect_cookies.txt cookies_tail.txt
'
-test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
-
test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
(
cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
@@ -241,8 +238,7 @@ test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
'
test_expect_success EXPENSIVE 'clone the 50,000 tag repo to check OS command line overflow' '
- git clone $HTTPD_URL/smart/repo.git too-many-refs 2>err &&
- test_line_count = 0 err &&
+ git clone $HTTPD_URL/smart/repo.git too-many-refs &&
(
cd too-many-refs &&
test $(git for-each-ref refs/tags | wc -l) = 50000
diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh
index 9be9ae3436..aa73eeaef8 100755
--- a/t/t5560-http-backend-noserver.sh
+++ b/t/t5560-http-backend-noserver.sh
@@ -5,12 +5,16 @@ test_description='test git-http-backend-noserver'
HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
-test_have_prereq GREP_STRIPS_CR && export GREP_OPTIONS=-U
+if test_have_prereq GREP_STRIPS_CR
+then
+ GREP_OPTIONS=-U
+ export GREP_OPTIONS
+fi
run_backend() {
echo "$2" |
- QUERY_STRING="${1#*\?}" \
- PATH_TRANSLATED="$HTTPD_DOCUMENT_ROOT_PATH/${1%%\?*}" \
+ QUERY_STRING="${1#*[?]}" \
+ PATH_TRANSLATED="$HTTPD_DOCUMENT_ROOT_PATH/${1%%[?]*}" \
git http-backend >act.out 2>act.err
}
diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh
index b5d7fbc381..d23fb02384 100755
--- a/t/t5561-http-backend.sh
+++ b/t/t5561-http-backend.sh
@@ -8,7 +8,6 @@ if test -n "$NO_CURL"; then
test_done
fi
-LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5561'}
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh
index e06146835c..6b16379951 100755
--- a/t/t5570-git-daemon.sh
+++ b/t/t5570-git-daemon.sh
@@ -3,7 +3,6 @@
test_description='test fetching over git protocol'
. ./test-lib.sh
-LIB_GIT_DAEMON_PORT=${LIB_GIT_DAEMON_PORT-5570}
. "$TEST_DIRECTORY"/lib-git-daemon.sh
start_git_daemon
diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh
new file mode 100755
index 0000000000..accfa5cc0c
--- /dev/null
+++ b/t/t5572-pull-submodule.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+test_description='pull can handle submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+reset_branch_to_HEAD () {
+ git branch -D "$1" &&
+ git checkout -b "$1" HEAD &&
+ git branch --set-upstream-to="origin/$1" "$1"
+}
+
+git_pull () {
+ reset_branch_to_HEAD "$1" &&
+ git pull
+}
+
+# pulls without conflicts
+test_submodule_switch "git_pull"
+
+git_pull_ff () {
+ reset_branch_to_HEAD "$1" &&
+ git pull --ff
+}
+
+test_submodule_switch "git_pull_ff"
+
+git_pull_ff_only () {
+ reset_branch_to_HEAD "$1" &&
+ git pull --ff-only
+}
+
+test_submodule_switch "git_pull_ff_only"
+
+git_pull_noff () {
+ reset_branch_to_HEAD "$1" &&
+ git pull --no-ff
+}
+
+KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1
+KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1
+test_submodule_switch "git_pull_noff"
+
+test_done
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 62fbd7e664..e4f10c0f68 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -318,7 +318,7 @@ test_expect_success 'clone myhost:src uses ssh' '
expect_ssh myhost src
'
-test_expect_success NOT_MINGW,NOT_CYGWIN 'clone local path foo:bar' '
+test_expect_success !MINGW,!CYGWIN 'clone local path foo:bar' '
cp -R src "foo:bar" &&
git clone "foo:bar" foobar &&
expect_ssh none
@@ -339,7 +339,7 @@ test_clone_url () {
expect_ssh "$2" "$3"
}
-test_expect_success NOT_MINGW 'clone c:temp is ssl' '
+test_expect_success !MINGW 'clone c:temp is ssl' '
test_clone_url c:temp c temp
'
@@ -430,4 +430,11 @@ test_expect_success 'clone from a repository with two identical branches' '
'
+test_expect_success 'shallow clone locally' '
+ git clone --depth=1 --no-local src ssrrcc &&
+ git clone ssrrcc ddsstt &&
+ test_cmp ssrrcc/.git/shallow ddsstt/.git/shallow &&
+ ( cd ddsstt && git fsck )
+'
+
test_done
diff --git a/t/t5602-clone-remote-exec.sh b/t/t5602-clone-remote-exec.sh
index 3f353d99e8..cbcceab9d5 100755
--- a/t/t5602-clone-remote-exec.sh
+++ b/t/t5602-clone-remote-exec.sh
@@ -12,21 +12,14 @@ test_expect_success setup '
'
test_expect_success 'clone calls git upload-pack unqualified with no -u option' '
- (
- GIT_SSH=./not_ssh &&
- export GIT_SSH &&
- test_must_fail git clone localhost:/path/to/repo junk
- ) &&
+ test_must_fail env GIT_SSH=./not_ssh git clone localhost:/path/to/repo junk &&
echo "localhost git-upload-pack '\''/path/to/repo'\''" >expected &&
test_cmp expected not_ssh_output
'
test_expect_success 'clone calls specified git upload-pack with -u option' '
- (
- GIT_SSH=./not_ssh &&
- export GIT_SSH &&
- test_must_fail git clone -u ./something/bin/git-upload-pack localhost:/path/to/repo junk
- ) &&
+ test_must_fail env GIT_SSH=./not_ssh \
+ git clone -u ./something/bin/git-upload-pack localhost:/path/to/repo junk &&
echo "localhost ./something/bin/git-upload-pack '\''/path/to/repo'\''" >expected &&
test_cmp expected not_ssh_output
'
diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh
index c4903687fb..3c087e907c 100755
--- a/t/t5701-clone-local.sh
+++ b/t/t5701-clone-local.sh
@@ -12,8 +12,8 @@ test_expect_success 'preparing origin repository' '
: >file && git add . && git commit -m1 &&
git clone --bare . a.git &&
git clone --bare . x &&
- test "$(GIT_CONFIG=a.git/config git config --bool core.bare)" = true &&
- test "$(GIT_CONFIG=x/config git config --bool core.bare)" = true &&
+ test "$(cd a.git && git config --bool core.bare)" = true &&
+ test "$(cd x && git config --bool core.bare)" = true &&
git bundle create b1.bundle --all &&
git bundle create b2.bundle master &&
mkdir dir &&
@@ -24,7 +24,7 @@ test_expect_success 'preparing origin repository' '
test_expect_success 'local clone without .git suffix' '
git clone -l -s a b &&
(cd b &&
- test "$(GIT_CONFIG=.git/config git config --bool core.bare)" = false &&
+ test "$(git config --bool core.bare)" = false &&
git fetch)
'
diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh
index a45c31692e..348d9b3bc7 100755
--- a/t/t5704-bundle.sh
+++ b/t/t5704-bundle.sh
@@ -14,7 +14,10 @@ test_expect_success 'setup' '
git tag -d third
'
-test_expect_success 'tags can be excluded by rev-list options' '
+test_expect_success 'annotated tags can be excluded by rev-list options' '
+ git bundle create bundle --all --since=7.Apr.2005.15:14:00.-0700 &&
+ git ls-remote bundle > output &&
+ grep tag output &&
git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 &&
git ls-remote bundle > output &&
! grep tag output
diff --git a/t/t5705-clone-2gb.sh b/t/t5705-clone-2gb.sh
index e9783c341a..191d6d3a78 100755
--- a/t/t5705-clone-2gb.sh
+++ b/t/t5705-clone-2gb.sh
@@ -46,7 +46,7 @@ test_expect_success CLONE_2GB 'clone - bare' '
test_expect_success CLONE_2GB 'clone - with worktree, file:// protocol' '
- git clone file://. clone-wt
+ git clone "file://$(pwd)" clone-wt
'
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index 613f69a254..2419407546 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -87,13 +87,42 @@ test_expect_success 'push new branch by name' '
compare_refs local HEAD server refs/heads/new-name
'
-test_expect_failure 'push new branch with old:new refspec' '
+test_expect_success 'push new branch with old:new refspec' '
(cd local &&
git push origin new-name:new-refspec
) &&
compare_refs local HEAD server refs/heads/new-refspec
'
+test_expect_success 'push new branch with HEAD:new refspec' '
+ (cd local &&
+ git checkout new-name
+ git push origin HEAD:new-refspec-2
+ ) &&
+ compare_refs local HEAD server refs/heads/new-refspec-2
+'
+
+test_expect_success 'push delete branch' '
+ (cd local &&
+ git push origin :new-name
+ ) &&
+ test_must_fail git --git-dir="server/.git" \
+ rev-parse --verify refs/heads/new-name
+'
+
+test_expect_success 'forced push' '
+ (cd local &&
+ git checkout -b force-test &&
+ echo content >> file &&
+ git commit -a -m eight &&
+ git push origin force-test &&
+ echo content >> file &&
+ git commit -a --amend -m eight-modified &&
+ git push --force origin force-test
+ ) &&
+ compare_refs local refs/heads/force-test server refs/heads/force-test
+'
+
test_expect_success 'cloning without refspec' '
GIT_REMOTE_TESTGIT_REFSPEC="" \
git clone "testgit::${PWD}/server" local2 2>error &&
@@ -199,29 +228,42 @@ test_expect_success 'push update refs failure' '
echo "update fail" >>file &&
git commit -a -m "update fail" &&
git rev-parse --verify testgit/origin/heads/update >expect &&
- GIT_REMOTE_TESTGIT_PUSH_ERROR="non-fast forward" &&
- export GIT_REMOTE_TESTGIT_PUSH_ERROR &&
- test_expect_code 1 git push origin update &&
+ test_expect_code 1 env GIT_REMOTE_TESTGIT_FAILURE="non-fast forward" \
+ git push origin update &&
git rev-parse --verify testgit/origin/heads/update >actual &&
test_cmp expect actual
)
'
+clean_mark () {
+ cut -f 2 -d ' ' "$1" |
+ git cat-file --batch-check |
+ grep commit |
+ sort >$(basename "$1")
+}
+
+cmp_marks () {
+ test_when_finished "rm -rf git.marks testgit.marks" &&
+ clean_mark ".git/testgit/$1/git.marks" &&
+ clean_mark ".git/testgit/$1/testgit.marks" &&
+ test_cmp git.marks testgit.marks
+}
+
test_expect_success 'proper failure checks for fetching' '
- (GIT_REMOTE_TESTGIT_FAILURE=1 &&
- export GIT_REMOTE_TESTGIT_FAILURE &&
- cd local &&
- test_must_fail git fetch 2> error &&
+ (cd local &&
+ test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git fetch 2>error &&
cat error &&
grep -q "Error while running fast-import" error
)
'
test_expect_success 'proper failure checks for pushing' '
- (GIT_REMOTE_TESTGIT_FAILURE=1 &&
- export GIT_REMOTE_TESTGIT_FAILURE &&
- cd local &&
- test_must_fail git push --all
+ (cd local &&
+ git checkout -b crash master &&
+ echo crash >>file &&
+ git commit -a -m crash &&
+ test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git push --all &&
+ cmp_marks origin
)
'
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
index 3794e4ceaf..2602086303 100755
--- a/t/t6000-rev-list-misc.sh
+++ b/t/t6000-rev-list-misc.sh
@@ -73,4 +73,27 @@ test_expect_success 'symleft flag bit is propagated down from tag' '
test_cmp expect actual
'
+test_expect_success 'rev-list can show index objects' '
+ # Of the blobs and trees in the index, note:
+ #
+ # - we do not show two/three, because it is the
+ # same blob as "one", and we show objects only once
+ #
+ # - we do show the tree "two", because it has a valid cache tree
+ # from the last commit
+ #
+ # - we do not show the root tree; since we updated the index, it
+ # does not have a valid cache tree
+ #
+ cat >expect <<-\EOF
+ 8e4020bb5a8d8c873b25de15933e75cc0fc275df one
+ d9d3a7417b9605cfd88ee6306b28dadc29e6ab08 only-in-index
+ 9200b628cf9dc883a85a7abc8d6e6730baee589c two
+ EOF
+ echo only-in-index >only-in-index &&
+ git add only-in-index &&
+ git rev-list --objects --indexed-objects >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 98744038ec..a02a45afd2 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -9,26 +9,39 @@ test_description='git rev-list --pretty=format test'
. "$TEST_DIRECTORY"/lib-terminal.sh
test_tick
+# Tested non-UTF-8 encoding
+test_encoding="ISO8859-1"
+
# String "added" in German
# (translated with Google Translate),
# encoded in UTF-8, used as a commit log message below.
-added=$(printf "added (hinzugef\303\274gt) foo")
-added_iso88591=$(echo "$added" | iconv -f utf-8 -t iso8859-1)
+added_utf8_part=$(printf "\303\274")
+added_utf8_part_iso88591=$(echo "$added_utf8_part" | iconv -f utf-8 -t $test_encoding)
+added=$(printf "added (hinzugef${added_utf8_part}gt) foo")
+added_iso88591=$(echo "$added" | iconv -f utf-8 -t $test_encoding)
# same but "changed"
-changed=$(printf "changed (ge\303\244ndert) foo")
-changed_iso88591=$(echo "$changed" | iconv -f utf-8 -t iso8859-1)
+changed_utf8_part=$(printf "\303\244")
+changed_utf8_part_iso88591=$(echo "$changed_utf8_part" | iconv -f utf-8 -t $test_encoding)
+changed=$(printf "changed (ge${changed_utf8_part}ndert) foo")
+changed_iso88591=$(echo "$changed" | iconv -f utf-8 -t $test_encoding)
+
+# Count of char to truncate
+# Number is chosen so, that non-ACSII characters
+# (see $added_utf8_part and $changed_utf8_part)
+# fall into truncated parts of appropriate words both from left and right
+truncate_count=20
test_expect_success 'setup' '
: >foo &&
git add foo &&
- git config i18n.commitEncoding iso8859-1 &&
- git commit -m "$added_iso88591" &&
+ git config i18n.commitEncoding $test_encoding &&
+ echo "$added_iso88591" | git commit -F - &&
head1=$(git rev-parse --verify HEAD) &&
head1_short=$(git rev-parse --verify --short $head1) &&
tree1=$(git rev-parse --verify HEAD:) &&
tree1_short=$(git rev-parse --verify --short $tree1) &&
echo "$changed" > foo &&
- git commit -a -m "$changed_iso88591" &&
+ echo "$changed_iso88591" | git commit -a -F - &&
head2=$(git rev-parse --verify HEAD) &&
head2_short=$(git rev-parse --verify --short $head2) &&
tree2=$(git rev-parse --verify HEAD:) &&
@@ -124,9 +137,9 @@ EOF
test_format encoding %e <<EOF
commit $head2
-iso8859-1
+$test_encoding
commit $head1
-iso8859-1
+$test_encoding
EOF
test_format subject %s <<EOF
@@ -136,6 +149,13 @@ commit $head1
$added
EOF
+test_format subject-truncated "%<($truncate_count,trunc)%s" <<EOF
+commit $head2
+changed (ge${changed_utf8_part}ndert)..
+commit $head1
+added (hinzugef${added_utf8_part}gt..
+EOF
+
test_format body %b <<EOF
commit $head2
commit $head1
@@ -190,12 +210,9 @@ test_expect_success '%C(auto) respects --no-color' '
'
test_expect_success TTY '%C(auto) respects --color=auto (stdout is tty)' '
- (
- TERM=vt100 && export TERM &&
- test_terminal \
- git log --format=$AUTO_COLOR -1 --color=auto >actual &&
- has_color actual
- )
+ test_terminal env TERM=vt100 \
+ git log --format=$AUTO_COLOR -1 --color=auto >actual &&
+ has_color actual
'
test_expect_success '%C(auto) respects --color=auto (stdout not tty)' '
@@ -206,16 +223,16 @@ test_expect_success '%C(auto) respects --color=auto (stdout not tty)' '
)
'
-iconv -f utf-8 -t iso8859-1 > commit-msg <<EOF
+iconv -f utf-8 -t $test_encoding > commit-msg <<EOF
Test printing of complex bodies
This commit message is much longer than the others,
-and it will be encoded in iso8859-1. We should therefore
-include an iso8859 character: ¡bueno!
+and it will be encoded in $test_encoding. We should therefore
+include an ISO8859 character: ¡bueno!
EOF
test_expect_success 'setup complex body' '
- git config i18n.commitencoding iso8859-1 &&
+ git config i18n.commitencoding $test_encoding &&
echo change2 >foo && git commit -a -F commit-msg &&
head3=$(git rev-parse --verify HEAD) &&
head3_short=$(git rev-parse --short $head3)
@@ -223,11 +240,11 @@ test_expect_success 'setup complex body' '
test_format complex-encoding %e <<EOF
commit $head3
-iso8859-1
+$test_encoding
commit $head2
-iso8859-1
+$test_encoding
commit $head1
-iso8859-1
+$test_encoding
EOF
test_format complex-subject %s <<EOF
@@ -239,20 +256,47 @@ commit $head1
$added_iso88591
EOF
+test_format complex-subject-trunc "%<($truncate_count,trunc)%s" <<EOF
+commit $head3
+Test printing of c..
+commit $head2
+changed (ge${changed_utf8_part_iso88591}ndert)..
+commit $head1
+added (hinzugef${added_utf8_part_iso88591}gt..
+EOF
+
+test_format complex-subject-mtrunc "%<($truncate_count,mtrunc)%s" <<EOF
+commit $head3
+Test prin..ex bodies
+commit $head2
+changed (..dert) foo
+commit $head1
+added (hi..f${added_utf8_part_iso88591}gt) foo
+EOF
+
+test_format complex-subject-ltrunc "%<($truncate_count,ltrunc)%s" <<EOF
+commit $head3
+.. of complex bodies
+commit $head2
+..ged (ge${changed_utf8_part_iso88591}ndert) foo
+commit $head1
+.. (hinzugef${added_utf8_part_iso88591}gt) foo
+EOF
+
test_expect_success 'prepare expected messages (for test %b)' '
cat <<-EOF >expected.utf-8 &&
commit $head3
This commit message is much longer than the others,
- and it will be encoded in iso8859-1. We should therefore
- include an iso8859 character: ¡bueno!
+ and it will be encoded in $test_encoding. We should therefore
+ include an ISO8859 character: ¡bueno!
commit $head2
commit $head1
EOF
- iconv -f utf-8 -t iso8859-1 expected.utf-8 >expected.iso8859-1
+ iconv -f utf-8 -t $test_encoding expected.utf-8 >expected.ISO8859-1
'
-test_format complex-body %b <expected.iso8859-1
+test_format complex-body %b <expected.ISO8859-1
# Git uses i18n.commitEncoding if no i18n.logOutputEncoding set
# so unset i18n.commitEncoding to test encoding conversion
@@ -267,6 +311,33 @@ commit $head1
$added
EOF
+test_format complex-subject-commitencoding-unset-trunc "%<($truncate_count,trunc)%s" <<EOF
+commit $head3
+Test printing of c..
+commit $head2
+changed (ge${changed_utf8_part}ndert)..
+commit $head1
+added (hinzugef${added_utf8_part}gt..
+EOF
+
+test_format complex-subject-commitencoding-unset-mtrunc "%<($truncate_count,mtrunc)%s" <<EOF
+commit $head3
+Test prin..ex bodies
+commit $head2
+changed (..dert) foo
+commit $head1
+added (hi..f${added_utf8_part}gt) foo
+EOF
+
+test_format complex-subject-commitencoding-unset-ltrunc "%<($truncate_count,ltrunc)%s" <<EOF
+commit $head3
+.. of complex bodies
+commit $head2
+..ged (ge${changed_utf8_part}ndert) foo
+commit $head1
+.. (hinzugef${added_utf8_part}gt) foo
+EOF
+
test_format complex-body-commitencoding-unset %b <expected.utf-8
test_expect_success '%x00 shows NUL' '
@@ -397,4 +468,10 @@ test_expect_success 'single-character name is parsed correctly' '
test_cmp expect actual
'
+test_expect_success 'unused %G placeholders are passed through' '
+ echo "%GX %G" >expect &&
+ git log -1 --format="%GX %G" >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh
index abb5728b34..39b3238da2 100755
--- a/t/t6010-merge-base.sh
+++ b/t/t6010-merge-base.sh
@@ -230,6 +230,34 @@ test_expect_success 'criss-cross merge-base for octopus-step' '
test_cmp expected.sorted actual.sorted
'
+test_expect_success 'using reflog to find the fork point' '
+ git reset --hard &&
+ git checkout -b base $E &&
+
+ (
+ for count in 1 2 3
+ do
+ git commit --allow-empty -m "Base commit #$count" &&
+ git rev-parse HEAD >expect$count &&
+ git checkout -B derived &&
+ git commit --allow-empty -m "Derived #$count" &&
+ git rev-parse HEAD >derived$count &&
+ git checkout -B base $E || exit 1
+ done
+
+ for count in 1 2 3
+ do
+ git merge-base --fork-point base $(cat derived$count) >actual &&
+ test_cmp expect$count actual || exit 1
+ done
+
+ ) &&
+ # check that we correctly default to HEAD
+ git checkout derived &&
+ git merge-base --fork-point base >actual &&
+ test_cmp expect3 actual
+'
+
test_expect_success 'merge-base --octopus --all for complex tree' '
# Best common ancestor for JE, JAA and JDD is JC
# JE
diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh
index f00cebff3e..d00f7db868 100755
--- a/t/t6018-rev-list-glob.sh
+++ b/t/t6018-rev-list-glob.sh
@@ -129,6 +129,18 @@ test_expect_success 'rev-parse --remotes=foo' '
'
+test_expect_success 'rev-parse --exclude with --branches' '
+ compare rev-parse "--exclude=*/* --branches" "master someref subspace-x"
+'
+
+test_expect_success 'rev-parse --exclude with --all' '
+ compare rev-parse "--exclude=refs/remotes/* --all" "--branches --tags"
+'
+
+test_expect_success 'rev-parse accumulates multiple --exclude' '
+ compare rev-parse "--exclude=refs/remotes/* --exclude=refs/tags/* --all" --branches
+'
+
test_expect_success 'rev-list --glob=refs/heads/subspace/*' '
compare rev-list "subspace/one subspace/two" "--glob=refs/heads/subspace/*"
@@ -231,6 +243,48 @@ test_expect_success 'rev-list --remotes=foo' '
'
+test_expect_success 'rev-list --exclude with --branches' '
+ compare rev-list "--exclude=*/* --branches" "master someref subspace-x"
+'
+
+test_expect_success 'rev-list --exclude with --all' '
+ compare rev-list "--exclude=refs/remotes/* --all" "--branches --tags"
+'
+
+test_expect_success 'rev-list accumulates multiple --exclude' '
+ compare rev-list "--exclude=refs/remotes/* --exclude=refs/tags/* --all" --branches
+'
+
+
+# "git rev-list<ENTER>" is likely to be a bug in the calling script and may
+# deserve an error message, but do cases where set of refs programatically
+# given using globbing and/or --stdin need to fail with the same error, or
+# are we better off reporting a success with no output? The following few
+# tests document the current behaviour to remind us that we might want to
+# think about this issue.
+
+test_expect_failure 'rev-list may want to succeed with empty output on no input (1)' '
+ >expect &&
+ git rev-list --stdin <expect >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'rev-list may want to succeed with empty output on no input (2)' '
+ >expect &&
+ git rev-list --exclude=* --all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_failure 'rev-list may want to succeed with empty output on no input (3)' '
+ (
+ test_create_repo empty &&
+ cd empty &&
+ >expect &&
+ git rev-list --all >actual &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'shortlog accepts --glob/--tags/--remotes' '
compare shortlog "subspace/one subspace/two" --branches=subspace &&
diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh
index 432f086c06..3758961765 100755
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
@@ -77,12 +77,29 @@ test_expect_success "merge without conflict (--quiet)" \
"git merge-file --quiet test.txt orig.txt new2.txt"
cp new1.txt test2.txt
-test_expect_success "merge without conflict (missing LF at EOF)" \
- "git merge-file test2.txt orig.txt new2.txt"
+test_expect_failure "merge without conflict (missing LF at EOF)" \
+ "git merge-file test2.txt orig.txt new4.txt"
-test_expect_success "merge result added missing LF" \
+test_expect_failure "merge result added missing LF" \
"test_cmp test.txt test2.txt"
+cp new4.txt test3.txt
+test_expect_success "merge without conflict (missing LF at EOF, away from change in the other file)" \
+ "git merge-file --quiet test3.txt new2.txt new3.txt"
+
+cat > expect.txt << EOF
+DOMINUS regit me,
+et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
+EOF
+printf "propter nomen suum." >> expect.txt
+
+test_expect_success "merge does not add LF away of change" \
+ "test_cmp test3.txt expect.txt"
+
cp test.txt backup.txt
test_expect_success "merge with conflicts" \
"test_must_fail git merge-file test.txt orig.txt new3.txt"
@@ -107,6 +124,55 @@ EOF
test_expect_success "expected conflict markers" "test_cmp test.txt expect.txt"
cp backup.txt test.txt
+
+cat > expect.txt << EOF
+Dominus regit me, et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
+propter nomen suum.
+Nam et si ambulavero in medio umbrae mortis,
+non timebo mala, quoniam tu mecum es:
+virga tua et baculus tuus ipsa me consolata sunt.
+EOF
+test_expect_success "merge conflicting with --ours" \
+ "git merge-file --ours test.txt orig.txt new3.txt && test_cmp test.txt expect.txt"
+cp backup.txt test.txt
+
+cat > expect.txt << EOF
+DOMINUS regit me,
+et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
+propter nomen suum.
+Nam et si ambulavero in medio umbrae mortis,
+non timebo mala, quoniam tu mecum es:
+virga tua et baculus tuus ipsa me consolata sunt.
+EOF
+test_expect_success "merge conflicting with --theirs" \
+ "git merge-file --theirs test.txt orig.txt new3.txt && test_cmp test.txt expect.txt"
+cp backup.txt test.txt
+
+cat > expect.txt << EOF
+Dominus regit me, et nihil mihi deerit.
+DOMINUS regit me,
+et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+animam meam convertit,
+deduxit me super semitas jusitiae,
+propter nomen suum.
+Nam et si ambulavero in medio umbrae mortis,
+non timebo mala, quoniam tu mecum es:
+virga tua et baculus tuus ipsa me consolata sunt.
+EOF
+test_expect_success "merge conflicting with --union" \
+ "git merge-file --union test.txt orig.txt new3.txt && test_cmp test.txt expect.txt"
+cp backup.txt test.txt
+
test_expect_success "merge with conflicts, using -L" \
"test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
@@ -260,4 +326,23 @@ test_expect_success 'marker size' '
test_cmp expect actual
'
+printf "line1\nline2\nline3" >nolf-orig.txt
+printf "line1\nline2\nline3x" >nolf-diff1.txt
+printf "line1\nline2\nline3y" >nolf-diff2.txt
+
+test_expect_success 'conflict at EOF without LF resolved by --ours' \
+ 'git merge-file -p --ours nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
+ printf "line1\nline2\nline3x" >expect.txt &&
+ test_cmp expect.txt output.txt'
+
+test_expect_success 'conflict at EOF without LF resolved by --theirs' \
+ 'git merge-file -p --theirs nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
+ printf "line1\nline2\nline3y" >expect.txt &&
+ test_cmp expect.txt output.txt'
+
+test_expect_success 'conflict at EOF without LF resolved by --union' \
+ 'git merge-file -p --union nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
+ printf "line1\nline2\nline3x\nline3y" >expect.txt &&
+ test_cmp expect.txt output.txt'
+
test_done
diff --git a/t/t6031-merge-recursive.sh b/t/t6031-merge-recursive.sh
index 1cd649e245..6464a16a19 100755
--- a/t/t6031-merge-recursive.sh
+++ b/t/t6031-merge-recursive.sh
@@ -2,7 +2,6 @@
test_description='merge-recursive: handle file mode'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
test_expect_success 'mode change in one branch: keep changed version' '
: >file1 &&
@@ -14,6 +13,7 @@ test_expect_success 'mode change in one branch: keep changed version' '
git commit -m a &&
git checkout -b b1 master &&
test_chmod +x file1 &&
+ git add file1 &&
git commit -m b1 &&
git checkout a1 &&
git merge-recursive master -- a1 b1 &&
diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh
index dfee7d159b..a86087be95 100755
--- a/t/t6036-recursive-corner-cases.sh
+++ b/t/t6036-recursive-corner-cases.sh
@@ -388,7 +388,7 @@ test_expect_failure 'git detects conflict w/ criss-cross+contrived resolution' '
#
# criss-cross + d/f conflict via add/add:
-# Commit A: Neither file 'a' nor directory 'a/' exist.
+# Commit A: Neither file 'a' nor directory 'a/' exists.
# Commit B: Introduce 'a'
# Commit C: Introduce 'a/file'
# Commit D: Merge B & C, keeping 'a' and deleting 'a/'
diff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh
index d9c2d386dd..85c10b0940 100755
--- a/t/t6038-merge-text-auto.sh
+++ b/t/t6038-merge-text-auto.sh
@@ -72,6 +72,10 @@ test_expect_success 'Merge after setting text=auto' '
same line
EOF
+ if test_have_prereq NATIVE_CRLF; then
+ append_cr <expected >expected.temp &&
+ mv expected.temp expected
+ fi &&
git config merge.renormalize true &&
git rm -fr . &&
rm -f .gitattributes &&
@@ -86,6 +90,10 @@ test_expect_success 'Merge addition of text=auto' '
same line
EOF
+ if test_have_prereq NATIVE_CRLF; then
+ append_cr <expected >expected.temp &&
+ mv expected.temp expected
+ fi &&
git config merge.renormalize true &&
git rm -fr . &&
rm -f .gitattributes &&
@@ -95,16 +103,19 @@ test_expect_success 'Merge addition of text=auto' '
'
test_expect_success 'Detect CRLF/LF conflict after setting text=auto' '
- q_to_cr <<-\EOF >expected &&
- <<<<<<<
- first line
- same line
- =======
- first lineQ
- same lineQ
- >>>>>>>
- EOF
-
+ echo "<<<<<<<" >expected &&
+ if test_have_prereq NATIVE_CRLF; then
+ echo first line | append_cr >>expected &&
+ echo same line | append_cr >>expected &&
+ echo ======= | append_cr >>expected
+ else
+ echo first line >>expected &&
+ echo same line >>expected &&
+ echo ======= >>expected
+ fi &&
+ echo first line | append_cr >>expected &&
+ echo same line | append_cr >>expected &&
+ echo ">>>>>>>" >>expected &&
git config merge.renormalize false &&
rm -f .gitattributes &&
git reset --hard a &&
@@ -114,16 +125,19 @@ test_expect_success 'Detect CRLF/LF conflict after setting text=auto' '
'
test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' '
- q_to_cr <<-\EOF >expected &&
- <<<<<<<
- first lineQ
- same lineQ
- =======
- first line
- same line
- >>>>>>>
- EOF
-
+ echo "<<<<<<<" >expected &&
+ echo first line | append_cr >>expected &&
+ echo same line | append_cr >>expected &&
+ if test_have_prereq NATIVE_CRLF; then
+ echo ======= | append_cr >>expected &&
+ echo first line | append_cr >>expected &&
+ echo same line | append_cr >>expected
+ else
+ echo ======= >>expected &&
+ echo first line >>expected &&
+ echo same line >>expected
+ fi &&
+ echo ">>>>>>>" >>expected &&
git config merge.renormalize false &&
rm -f .gitattributes &&
git reset --hard b &&
diff --git a/t/t6039-merge-ignorecase.sh b/t/t6039-merge-ignorecase.sh
new file mode 100755
index 0000000000..a977653147
--- /dev/null
+++ b/t/t6039-merge-ignorecase.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+test_description='git-merge with case-changing rename on case-insensitive file system'
+
+. ./test-lib.sh
+
+if ! test_have_prereq CASE_INSENSITIVE_FS
+then
+ skip_all='skipping case insensitive tests - case sensitive file system'
+ test_done
+fi
+
+test_expect_success 'merge with case-changing rename' '
+ test $(git config core.ignorecase) = true &&
+ >TestCase &&
+ git add TestCase &&
+ git commit -m "add TestCase" &&
+ git tag baseline
+ git checkout -b with-camel &&
+ >foo &&
+ git add foo &&
+ git commit -m "intervening commit" &&
+ git checkout master &&
+ git rm TestCase &&
+ >testcase &&
+ git add testcase &&
+ git commit -m "rename to testcase" &&
+ git checkout with-camel &&
+ git merge master -m "merge" &&
+ test_path_is_file testcase
+'
+
+test_expect_success 'merge with case-changing rename on both sides' '
+ git checkout master &&
+ git reset --hard baseline &&
+ git branch -D with-camel &&
+ git checkout -b with-camel &&
+ git mv TestCase testcase &&
+ git commit -m "recase on branch" &&
+ >foo &&
+ git add foo &&
+ git commit -m "intervening commit" &&
+ git checkout master &&
+ git rm TestCase &&
+ >testcase &&
+ git add testcase &&
+ git commit -m "rename to testcase" &&
+ git checkout with-camel &&
+ git merge master -m "merge" &&
+ test_path_is_file testcase
+'
+
+test_done
diff --git a/t/t6041-bisect-submodule.sh b/t/t6041-bisect-submodule.sh
new file mode 100755
index 0000000000..c6b7aa6977
--- /dev/null
+++ b/t/t6041-bisect-submodule.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+test_description='bisect can handle submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+git_bisect () {
+ git status -su >expect &&
+ ls -1pR * >>expect &&
+ tar czf "$TRASH_DIRECTORY/tmp.tgz" * &&
+ GOOD=$(git rev-parse --verify HEAD) &&
+ git checkout "$1" &&
+ echo "foo" >bar &&
+ git add bar &&
+ git commit -m "bisect bad" &&
+ BAD=$(git rev-parse --verify HEAD) &&
+ git reset --hard HEAD^^ &&
+ git submodule update &&
+ git bisect start &&
+ git bisect good $GOOD &&
+ rm -rf * &&
+ tar xzf "$TRASH_DIRECTORY/tmp.tgz" &&
+ git status -su >actual &&
+ ls -1pR * >>actual &&
+ test_cmp expect actual &&
+ git bisect bad $BAD
+}
+
+test_submodule_switch "git_bisect"
+
+test_done
diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh
index 7d47984352..4d5a25eedf 100755
--- a/t/t6050-replace.sh
+++ b/t/t6050-replace.sh
@@ -7,8 +7,9 @@ test_description='Tests replace refs functionality'
exec </dev/null
. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
-add_and_commit_file()
+add_and_commit_file ()
{
_file="$1"
_msg="$2"
@@ -18,6 +19,38 @@ add_and_commit_file()
git commit --quiet -m "$_file: $_msg"
}
+commit_buffer_contains_parents ()
+{
+ git cat-file commit "$1" >payload &&
+ sed -n -e '/^$/q' -e '/^parent /p' <payload >actual &&
+ shift &&
+ for _parent
+ do
+ echo "parent $_parent"
+ done >expected &&
+ test_cmp expected actual
+}
+
+commit_peeling_shows_parents ()
+{
+ _parent_number=1
+ _commit="$1"
+ shift &&
+ for _parent
+ do
+ _found=$(git rev-parse --verify $_commit^$_parent_number) || return 1
+ test "$_found" = "$_parent" || return 1
+ _parent_number=$(( $_parent_number + 1 ))
+ done &&
+ test_must_fail git rev-parse --verify $_commit^$_parent_number
+}
+
+commit_has_parents ()
+{
+ commit_buffer_contains_parents "$@" &&
+ commit_peeling_shows_parents "$@"
+}
+
HASH1=
HASH2=
HASH3=
@@ -27,36 +60,36 @@ HASH6=
HASH7=
test_expect_success 'set up buggy branch' '
- echo "line 1" >> hello &&
- echo "line 2" >> hello &&
- echo "line 3" >> hello &&
- echo "line 4" >> hello &&
+ echo "line 1" >>hello &&
+ echo "line 2" >>hello &&
+ echo "line 3" >>hello &&
+ echo "line 4" >>hello &&
add_and_commit_file hello "4 lines" &&
HASH1=$(git rev-parse --verify HEAD) &&
- echo "line BUG" >> hello &&
- echo "line 6" >> hello &&
- echo "line 7" >> hello &&
- echo "line 8" >> hello &&
+ echo "line BUG" >>hello &&
+ echo "line 6" >>hello &&
+ echo "line 7" >>hello &&
+ echo "line 8" >>hello &&
add_and_commit_file hello "4 more lines with a BUG" &&
HASH2=$(git rev-parse --verify HEAD) &&
- echo "line 9" >> hello &&
- echo "line 10" >> hello &&
+ echo "line 9" >>hello &&
+ echo "line 10" >>hello &&
add_and_commit_file hello "2 more lines" &&
HASH3=$(git rev-parse --verify HEAD) &&
- echo "line 11" >> hello &&
+ echo "line 11" >>hello &&
add_and_commit_file hello "1 more line" &&
HASH4=$(git rev-parse --verify HEAD) &&
- sed -e "s/BUG/5/" hello > hello.new &&
+ sed -e "s/BUG/5/" hello >hello.new &&
mv hello.new hello &&
add_and_commit_file hello "BUG fixed" &&
HASH5=$(git rev-parse --verify HEAD) &&
- echo "line 12" >> hello &&
- echo "line 13" >> hello &&
+ echo "line 12" >>hello &&
+ echo "line 13" >>hello &&
add_and_commit_file hello "2 more lines" &&
HASH6=$(git rev-parse --verify HEAD) &&
- echo "line 14" >> hello &&
- echo "line 15" >> hello &&
- echo "line 16" >> hello &&
+ echo "line 14" >>hello &&
+ echo "line 15" >>hello &&
+ echo "line 16" >>hello &&
add_and_commit_file hello "again 3 more lines" &&
HASH7=$(git rev-parse --verify HEAD)
'
@@ -95,7 +128,7 @@ test_expect_success 'tag replaced commit' '
'
test_expect_success '"git fsck" works' '
- git fsck master > fsck_master.out &&
+ git fsck master >fsck_master.out &&
grep "dangling commit $R" fsck_master.out &&
grep "dangling tag $(cat .git/refs/tags/mytag)" fsck_master.out &&
test -z "$(git fsck)"
@@ -217,14 +250,14 @@ test_expect_success 'fetch branch with replacement' '
(
cd clone_dir &&
git fetch origin refs/heads/tofetch:refs/heads/parallel3 &&
- git log --pretty=oneline parallel3 > output.txt &&
+ git log --pretty=oneline parallel3 >output.txt &&
! grep $PARA3 output.txt &&
- git show $PARA3 > para3.txt &&
+ git show $PARA3 >para3.txt &&
grep "A U Thor" para3.txt &&
git fetch origin "refs/replace/*:refs/replace/*" &&
- git log --pretty=oneline parallel3 > output.txt &&
+ git log --pretty=oneline parallel3 >output.txt &&
grep $PARA3 output.txt &&
- git show $PARA3 > para3.txt &&
+ git show $PARA3 >para3.txt &&
grep "O Thor" para3.txt
)
'
@@ -276,10 +309,135 @@ test_expect_success '-f option bypasses the type check' '
git replace -f HEAD^ $BLOB
'
+test_expect_success 'git cat-file --batch works on replace objects' '
+ git replace | grep $PARA3 &&
+ echo $PARA3 | git cat-file --batch
+'
+
+test_expect_success 'test --format bogus' '
+ test_must_fail git replace --format bogus >/dev/null 2>&1
+'
+
+test_expect_success 'test --format short' '
+ git replace --format=short >actual &&
+ git replace >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'test --format medium' '
+ H1=$(git --no-replace-objects rev-parse HEAD~1) &&
+ HT=$(git --no-replace-objects rev-parse HEAD^{tree}) &&
+ MYTAG=$(git --no-replace-objects rev-parse mytag) &&
+ {
+ echo "$H1 -> $BLOB" &&
+ echo "$BLOB -> $REPLACED" &&
+ echo "$HT -> $H1" &&
+ echo "$PARA3 -> $S" &&
+ echo "$MYTAG -> $HASH1"
+ } | sort >expected &&
+ git replace -l --format medium | sort >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'test --format long' '
+ {
+ echo "$H1 (commit) -> $BLOB (blob)" &&
+ echo "$BLOB (blob) -> $REPLACED (blob)" &&
+ echo "$HT (tree) -> $H1 (commit)" &&
+ echo "$PARA3 (commit) -> $S (commit)" &&
+ echo "$MYTAG (tag) -> $HASH1 (commit)"
+ } | sort >expected &&
+ git replace --format=long | sort >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'setup a fake editor' '
+ write_script fakeeditor <<-\EOF
+ sed -e "s/A U Thor/A fake Thor/" "$1" >"$1.new"
+ mv "$1.new" "$1"
+ EOF
+'
+
+test_expect_success '--edit with and without already replaced object' '
+ test_must_fail env GIT_EDITOR=./fakeeditor git replace --edit "$PARA3" &&
+ GIT_EDITOR=./fakeeditor git replace --force --edit "$PARA3" &&
+ git replace -l | grep "$PARA3" &&
+ git cat-file commit "$PARA3" | grep "A fake Thor" &&
+ git replace -d "$PARA3" &&
+ GIT_EDITOR=./fakeeditor git replace --edit "$PARA3" &&
+ git replace -l | grep "$PARA3" &&
+ git cat-file commit "$PARA3" | grep "A fake Thor"
+'
+
+test_expect_success '--edit and change nothing or command failed' '
+ git replace -d "$PARA3" &&
+ test_must_fail env GIT_EDITOR=true git replace --edit "$PARA3" &&
+ test_must_fail env GIT_EDITOR="./fakeeditor;false" git replace --edit "$PARA3" &&
+ GIT_EDITOR=./fakeeditor git replace --edit "$PARA3" &&
+ git replace -l | grep "$PARA3" &&
+ git cat-file commit "$PARA3" | grep "A fake Thor"
+'
+
test_expect_success 'replace ref cleanup' '
test -n "$(git replace)" &&
git replace -d $(git replace) &&
test -z "$(git replace)"
'
+test_expect_success '--graft with and without already replaced object' '
+ test $(git log --oneline | wc -l) = 7 &&
+ git replace --graft $HASH5 &&
+ test $(git log --oneline | wc -l) = 3 &&
+ commit_has_parents $HASH5 &&
+ test_must_fail git replace --graft $HASH5 $HASH4 $HASH3 &&
+ git replace --force -g $HASH5 $HASH4 $HASH3 &&
+ commit_has_parents $HASH5 $HASH4 $HASH3 &&
+ git replace -d $HASH5
+'
+
+test_expect_success GPG 'set up a signed commit' '
+ echo "line 17" >>hello &&
+ echo "line 18" >>hello &&
+ git add hello &&
+ test_tick &&
+ git commit --quiet -S -m "hello: 2 more lines in a signed commit" &&
+ HASH8=$(git rev-parse --verify HEAD) &&
+ git verify-commit $HASH8
+'
+
+test_expect_success GPG '--graft with a signed commit' '
+ git cat-file commit $HASH8 >orig &&
+ git replace --graft $HASH8 &&
+ git cat-file commit $HASH8 >repl &&
+ commit_has_parents $HASH8 &&
+ test_must_fail git verify-commit $HASH8 &&
+ sed -n -e "/^tree /p" -e "/^author /p" -e "/^committer /p" orig >expected &&
+ echo >>expected &&
+ sed -e "/^$/q" repl >actual &&
+ test_cmp expected actual &&
+ git replace -d $HASH8
+'
+
+test_expect_success GPG 'set up a merge commit with a mergetag' '
+ git reset --hard HEAD &&
+ git checkout -b test_branch HEAD~2 &&
+ echo "line 1 from test branch" >>hello &&
+ echo "line 2 from test branch" >>hello &&
+ git add hello &&
+ test_tick &&
+ git commit -m "hello: 2 more lines from a test branch" &&
+ HASH9=$(git rev-parse --verify HEAD) &&
+ git tag -s -m "tag for testing with a mergetag" test_tag HEAD &&
+ git checkout master &&
+ git merge -s ours test_tag &&
+ HASH10=$(git rev-parse --verify HEAD) &&
+ git cat-file commit $HASH10 | grep "^mergetag object"
+'
+
+test_expect_success GPG '--graft on a commit with a mergetag' '
+ test_must_fail git replace --graft $HASH10 $HASH8^1 &&
+ git replace --graft $HASH10 $HASH8^1 $HASH9 &&
+ git replace -d $HASH10
+'
+
test_done
diff --git a/t/t6131-pathspec-icase.sh b/t/t6131-pathspec-icase.sh
index a7c7ff5f49..39fc3f6769 100755
--- a/t/t6131-pathspec-icase.sh
+++ b/t/t6131-pathspec-icase.sh
@@ -69,7 +69,7 @@ test_expect_success 'tree_entry_interesting matches :(icase)bar with empty prefi
test_cmp expect actual
'
-test_expect_success 'match_pathspec_depth matches :(icase)bar' '
+test_expect_success 'match_pathspec matches :(icase)bar' '
cat <<-EOF >expect &&
BAR
bAr
@@ -79,7 +79,7 @@ test_expect_success 'match_pathspec_depth matches :(icase)bar' '
test_cmp expect actual
'
-test_expect_success 'match_pathspec_depth matches :(icase)bar with prefix' '
+test_expect_success 'match_pathspec matches :(icase)bar with prefix' '
cat <<-EOF >expect &&
fOo/BAR
fOo/bAr
@@ -89,7 +89,7 @@ test_expect_success 'match_pathspec_depth matches :(icase)bar with prefix' '
test_cmp expect actual
'
-test_expect_success 'match_pathspec_depth matches :(icase)bar with empty prefix' '
+test_expect_success 'match_pathspec matches :(icase)bar with empty prefix' '
cat <<-EOF >expect &&
bar
fOo/BAR
diff --git a/t/t6132-pathspec-exclude.sh b/t/t6132-pathspec-exclude.sh
new file mode 100755
index 0000000000..62049be0c7
--- /dev/null
+++ b/t/t6132-pathspec-exclude.sh
@@ -0,0 +1,184 @@
+#!/bin/sh
+
+test_description='test case exclude pathspec'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ for p in file sub/file sub/sub/file sub/file2 sub/sub/sub/file sub2/file; do
+ if echo $p | grep /; then
+ mkdir -p `dirname $p`
+ fi &&
+ : >$p &&
+ git add $p &&
+ git commit -m $p
+ done &&
+ git log --oneline --format=%s >actual &&
+ cat <<EOF >expect &&
+sub2/file
+sub/sub/sub/file
+sub/file2
+sub/sub/file
+sub/file
+file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'exclude only should error out' '
+ test_must_fail git log --oneline --format=%s -- ":(exclude)sub"
+'
+
+test_expect_success 't_e_i() exclude sub' '
+ git log --oneline --format=%s -- . ":(exclude)sub" >actual
+ cat <<EOF >expect &&
+sub2/file
+file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 't_e_i() exclude sub/sub/file' '
+ git log --oneline --format=%s -- . ":(exclude)sub/sub/file" >actual
+ cat <<EOF >expect &&
+sub2/file
+sub/sub/sub/file
+sub/file2
+sub/file
+file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 't_e_i() exclude sub using mnemonic' '
+ git log --oneline --format=%s -- . ":!sub" >actual
+ cat <<EOF >expect &&
+sub2/file
+file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 't_e_i() exclude :(icase)SUB' '
+ git log --oneline --format=%s -- . ":(exclude,icase)SUB" >actual
+ cat <<EOF >expect &&
+sub2/file
+file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 't_e_i() exclude sub2 from sub' '
+ (
+ cd sub &&
+ git log --oneline --format=%s -- :/ ":/!sub2" >actual
+ cat <<EOF >expect &&
+sub/sub/sub/file
+sub/file2
+sub/sub/file
+sub/file
+file
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 't_e_i() exclude sub/*file' '
+ git log --oneline --format=%s -- . ":(exclude)sub/*file" >actual
+ cat <<EOF >expect &&
+sub2/file
+sub/file2
+file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 't_e_i() exclude :(glob)sub/*/file' '
+ git log --oneline --format=%s -- . ":(exclude,glob)sub/*/file" >actual
+ cat <<EOF >expect &&
+sub2/file
+sub/sub/sub/file
+sub/file2
+sub/file
+file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'm_p_d() exclude sub' '
+ git ls-files -- . ":(exclude)sub" >actual
+ cat <<EOF >expect &&
+file
+sub2/file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'm_p_d() exclude sub/sub/file' '
+ git ls-files -- . ":(exclude)sub/sub/file" >actual
+ cat <<EOF >expect &&
+file
+sub/file
+sub/file2
+sub/sub/sub/file
+sub2/file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'm_p_d() exclude sub using mnemonic' '
+ git ls-files -- . ":!sub" >actual
+ cat <<EOF >expect &&
+file
+sub2/file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'm_p_d() exclude :(icase)SUB' '
+ git ls-files -- . ":(exclude,icase)SUB" >actual
+ cat <<EOF >expect &&
+file
+sub2/file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'm_p_d() exclude sub2 from sub' '
+ (
+ cd sub &&
+ git ls-files -- :/ ":/!sub2" >actual
+ cat <<EOF >expect &&
+../file
+file
+file2
+sub/file
+sub/sub/file
+EOF
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'm_p_d() exclude sub/*file' '
+ git ls-files -- . ":(exclude)sub/*file" >actual
+ cat <<EOF >expect &&
+file
+sub/file2
+sub2/file
+EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'm_p_d() exclude :(glob)sub/*/file' '
+ git ls-files -- . ":(exclude,glob)sub/*/file" >actual
+ cat <<EOF >expect &&
+file
+sub/file
+sub/file2
+sub/sub/sub/file
+sub2/file
+EOF
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index da5fb6c917..bda354c1c4 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -18,16 +18,13 @@ setdate_and_increment () {
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
}
-test_expect_success 'Create sample commit with known timestamp' '
+test_expect_success setup '
setdate_and_increment &&
echo "Using $datestamp" > one &&
git add one &&
git commit -m "Initial" &&
setdate_and_increment &&
- git tag -a -m "Tagging at $datestamp" testtag
-'
-
-test_expect_success 'Create upstream config' '
+ git tag -a -m "Tagging at $datestamp" testtag &&
git update-ref refs/remotes/origin/master master &&
git remote add origin nowhere &&
git config branch.master.remote origin &&
@@ -52,8 +49,8 @@ test_atom head refname refs/heads/master
test_atom head upstream refs/remotes/origin/master
test_atom head objecttype commit
test_atom head objectsize 171
-test_atom head objectname 67a36f10722846e891fbada1ba48ed035de75581
-test_atom head tree 0e51c00fcb93dffc755546f27593d511e1bdb46f
+test_atom head objectname $(git rev-parse refs/heads/master)
+test_atom head tree $(git rev-parse refs/heads/master^{tree})
test_atom head parent ''
test_atom head numparent 0
test_atom head object ''
@@ -82,16 +79,17 @@ test_atom head contents:body ''
test_atom head contents:signature ''
test_atom head contents 'Initial
'
+test_atom head HEAD '*'
test_atom tag refname refs/tags/testtag
test_atom tag upstream ''
test_atom tag objecttype tag
test_atom tag objectsize 154
-test_atom tag objectname 98b46b1d36e5b07909de1b3886224e3e81e87322
+test_atom tag objectname $(git rev-parse refs/tags/testtag)
test_atom tag tree ''
test_atom tag parent ''
test_atom tag numparent ''
-test_atom tag object '67a36f10722846e891fbada1ba48ed035de75581'
+test_atom tag object $(git rev-parse refs/tags/testtag^0)
test_atom tag type 'commit'
test_atom tag '*objectname' '67a36f10722846e891fbada1ba48ed035de75581'
test_atom tag '*objecttype' 'commit'
@@ -117,6 +115,7 @@ test_atom tag contents:body ''
test_atom tag contents:signature ''
test_atom tag contents 'Tagging at 1151939927
'
+test_atom tag HEAD ' '
test_expect_success 'Check invalid atoms names are errors' '
test_must_fail git for-each-ref --format="%(INVALID)" refs/heads
@@ -308,8 +307,35 @@ test_expect_success 'Check short upstream format' '
test_cmp expected actual
'
+test_expect_success 'setup for upstream:track[short]' '
+ test_commit two
+'
+
+cat >expected <<EOF
+[ahead 1]
+EOF
+
+test_expect_success 'Check upstream:track format' '
+ git for-each-ref --format="%(upstream:track)" refs/heads >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+>
+EOF
+
+test_expect_success 'Check upstream:trackshort format' '
+ git for-each-ref --format="%(upstream:trackshort)" refs/heads >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'Check that :track[short] cannot be used with other atoms' '
+ test_must_fail git for-each-ref --format="%(refname:track)" 2>/dev/null &&
+ test_must_fail git for-each-ref --format="%(refname:trackshort)" 2>/dev/null
+'
+
cat >expected <<EOF
-67a36f1
+$(git rev-parse --short HEAD)
EOF
test_expect_success 'Check short objectname format' '
@@ -321,6 +347,23 @@ test_expect_success 'Check for invalid refname format' '
test_must_fail git for-each-ref --format="%(refname:INVALID)"
'
+get_color ()
+{
+ git config --get-color no.such.slot "$1"
+}
+
+cat >expected <<EOF
+$(git rev-parse --short refs/heads/master) $(get_color green)master$(get_color reset)
+$(git rev-parse --short refs/remotes/origin/master) $(get_color green)origin/master$(get_color reset)
+$(git rev-parse --short refs/tags/testtag) $(get_color green)testtag$(get_color reset)
+$(git rev-parse --short refs/tags/two) $(get_color green)two$(get_color reset)
+EOF
+
+test_expect_success 'Check %(color:...) ' '
+ git for-each-ref --format="%(objectname:short) %(color:green)%(refname:short)" >actual &&
+ test_cmp expected actual
+'
+
cat >expected <<\EOF
heads/master
tags/master
@@ -460,9 +503,9 @@ test_atom refs/tags/signed-long contents "subject line
body contents
$sig"
-cat >expected <<\EOF
-408fe76d02a785a006c2e9c669b7be5589ede96d <committer@example.com> refs/tags/master
-90b5ebede4899eda64893bc2a4c8f1d6fb6dfc40 <committer@example.com> refs/tags/bogo
+cat >expected <<EOF
+$(git rev-parse refs/tags/master) <committer@example.com> refs/tags/master
+$(git rev-parse refs/tags/bogo) <committer@example.com> refs/tags/bogo
EOF
test_expect_success 'Verify sort with multiple keys' '
diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh
new file mode 100755
index 0000000000..157f3f91db
--- /dev/null
+++ b/t/t6501-freshen-objects.sh
@@ -0,0 +1,132 @@
+#!/bin/sh
+#
+# This test covers the handling of objects which might have old
+# mtimes in the filesystem (because they were used previously)
+# and are just now becoming referenced again.
+#
+# We're going to do two things that are a little bit "fake" to
+# help make our simulation easier:
+#
+# 1. We'll turn off reflogs. You can still run into
+# problems with reflogs on, but your objects
+# don't get pruned until both the reflog expiration
+# has passed on their references, _and_ they are out
+# of prune's expiration period. Dropping reflogs
+# means we only have to deal with one variable in our tests,
+# but the results generalize.
+#
+# 2. We'll use a temporary index file to create our
+# works-in-progress. Most workflows would mention
+# referenced objects in the index, which prune takes
+# into account. However, many operations don't. For
+# example, a partial commit with "git commit foo"
+# will use a temporary index. Or they may not need
+# an index at all (e.g., creating a new commit
+# to refer to an existing tree).
+
+test_description='check pruning of dependent objects'
+. ./test-lib.sh
+
+# We care about reachability, so we do not want to use
+# the normal test_commit, which creates extra tags.
+add () {
+ echo "$1" >"$1" &&
+ git add "$1"
+}
+commit () {
+ test_tick &&
+ add "$1" &&
+ git commit -m "$1"
+}
+
+maybe_repack () {
+ if test -n "$repack"; then
+ git repack -ad
+ fi
+}
+
+for repack in '' true; do
+ title=${repack:+repack}
+ title=${title:-loose}
+
+ test_expect_success "make repo completely empty ($title)" '
+ rm -rf .git &&
+ git init
+ '
+
+ test_expect_success "disable reflogs ($title)" '
+ git config core.logallrefupdates false &&
+ rm -rf .git/logs
+ '
+
+ test_expect_success "setup basic history ($title)" '
+ commit base
+ '
+
+ test_expect_success "create and abandon some objects ($title)" '
+ git checkout -b experiment &&
+ commit abandon &&
+ maybe_repack &&
+ git checkout master &&
+ git branch -D experiment
+ '
+
+ test_expect_success "simulate time passing ($title)" '
+ find .git/objects -type f |
+ xargs test-chmtime -v -86400
+ '
+
+ test_expect_success "start writing new commit with old blob ($title)" '
+ tree=$(
+ GIT_INDEX_FILE=index.tmp &&
+ export GIT_INDEX_FILE &&
+ git read-tree HEAD &&
+ add unrelated &&
+ add abandon &&
+ git write-tree
+ )
+ '
+
+ test_expect_success "simultaneous gc ($title)" '
+ git gc --prune=12.hours.ago
+ '
+
+ test_expect_success "finish writing out commit ($title)" '
+ commit=$(echo foo | git commit-tree -p HEAD $tree) &&
+ git update-ref HEAD $commit
+ '
+
+ # "abandon" blob should have been rescued by reference from new tree
+ test_expect_success "repository passes fsck ($title)" '
+ git fsck
+ '
+
+ test_expect_success "abandon objects again ($title)" '
+ git reset --hard HEAD^ &&
+ find .git/objects -type f |
+ xargs test-chmtime -v -86400
+ '
+
+ test_expect_success "start writing new commit with same tree ($title)" '
+ tree=$(
+ GIT_INDEX_FILE=index.tmp &&
+ export GIT_INDEX_FILE &&
+ git read-tree HEAD &&
+ add abandon &&
+ add unrelated &&
+ git write-tree
+ )
+ '
+
+ test_expect_success "simultaneous gc ($title)" '
+ git gc --prune=12.hours.ago
+ '
+
+ # tree should have been refreshed by write-tree
+ test_expect_success "finish writing out commit ($title)" '
+ commit=$(echo foo | git commit-tree -p HEAD $tree) &&
+ git update-ref HEAD $commit
+ '
+done
+
+test_done
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 3bfdfed1f7..69f11bd40d 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -294,7 +294,8 @@ test_expect_success 'setup submodule' '
git submodule add ./. sub &&
echo content >file &&
git add file &&
- git commit -m "added sub and file"
+ git commit -m "added sub and file" &&
+ git branch submodule
'
test_expect_success 'git mv cannot move a submodule in a file' '
@@ -307,7 +308,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and no .gitm
(
cd sub &&
rm -f .git &&
- cp -a ../.git/modules/sub .git &&
+ cp -R -P -p ../.git/modules/sub .git &&
GIT_WORK_TREE=. git config --unset core.worktree
) &&
mkdir mod &&
@@ -330,7 +331,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu
(
cd sub &&
rm -f .git &&
- cp -a ../.git/modules/sub .git &&
+ cp -R -P -p ../.git/modules/sub .git &&
GIT_WORK_TREE=. git config --unset core.worktree
) &&
mkdir mod &&
@@ -349,10 +350,11 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu
'
test_expect_success 'git mv moves a submodule with gitfile' '
- rm -rf mod/sub &&
+ rm -rf mod &&
git reset --hard &&
git submodule update &&
entry="$(git ls-files --stage sub | cut -f 1)" &&
+ mkdir mod &&
(
cd mod &&
git mv ../sub/ .
@@ -371,11 +373,12 @@ test_expect_success 'git mv moves a submodule with gitfile' '
'
test_expect_success 'mv does not complain when no .gitmodules file is found' '
- rm -rf mod/sub &&
+ rm -rf mod &&
git reset --hard &&
git submodule update &&
git rm .gitmodules &&
entry="$(git ls-files --stage sub | cut -f 1)" &&
+ mkdir mod &&
git mv sub mod/sub 2>actual.err &&
! test -s actual.err &&
! test -e sub &&
@@ -389,11 +392,12 @@ test_expect_success 'mv does not complain when no .gitmodules file is found' '
'
test_expect_success 'mv will error out on a modified .gitmodules file unless staged' '
- rm -rf mod/sub &&
+ rm -rf mod &&
git reset --hard &&
git submodule update &&
git config -f .gitmodules foo.bar true &&
entry="$(git ls-files --stage sub | cut -f 1)" &&
+ mkdir mod &&
test_must_fail git mv sub mod/sub 2>actual.err &&
test -s actual.err &&
test -e sub &&
@@ -412,13 +416,14 @@ test_expect_success 'mv will error out on a modified .gitmodules file unless sta
'
test_expect_success 'mv issues a warning when section is not found in .gitmodules' '
- rm -rf mod/sub &&
+ rm -rf mod &&
git reset --hard &&
git submodule update &&
git config -f .gitmodules --remove-section submodule.sub &&
git add .gitmodules &&
entry="$(git ls-files --stage sub | cut -f 1)" &&
echo "warning: Could not find section in .gitmodules where path=sub" >expect.err &&
+ mkdir mod &&
git mv sub mod/sub 2>actual.err &&
test_i18ncmp expect.err actual.err &&
! test -e sub &&
@@ -432,9 +437,10 @@ test_expect_success 'mv issues a warning when section is not found in .gitmodule
'
test_expect_success 'mv --dry-run does not touch the submodule or .gitmodules' '
- rm -rf mod/sub &&
+ rm -rf mod &&
git reset --hard &&
git submodule update &&
+ mkdir mod &&
git mv -n sub mod/sub 2>actual.err &&
test -f sub/.git &&
git diff-index --exit-code HEAD &&
@@ -442,4 +448,34 @@ test_expect_success 'mv --dry-run does not touch the submodule or .gitmodules' '
git diff-files --quiet -- sub .gitmodules
'
+test_expect_success 'checking out a commit before submodule moved needs manual updates' '
+ git mv sub sub2 &&
+ git commit -m "moved sub to sub2" &&
+ git checkout -q HEAD^ 2>actual &&
+ test_i18ngrep "^warning: unable to rmdir sub2:" actual &&
+ git status -s sub2 >actual &&
+ echo "?? sub2/" >expected &&
+ test_cmp expected actual &&
+ ! test -f sub/.git &&
+ test -f sub2/.git &&
+ git submodule update &&
+ test -f sub/.git &&
+ rm -rf sub2 &&
+ git diff-index --exit-code HEAD &&
+ git update-index --refresh &&
+ git diff-files --quiet -- sub .gitmodules &&
+ git status -s sub2 >actual &&
+ ! test -s actual
+'
+
+test_expect_success 'mv -k does not accidentally destroy submodules' '
+ git checkout submodule &&
+ mkdir dummy dest &&
+ git mv -k dummy sub dest &&
+ git status --porcelain >actual &&
+ grep "^R sub -> dest/sub" actual &&
+ git reset --hard &&
+ git checkout .
+'
+
test_done
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index 9496736a89..66643e4bd7 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -308,6 +308,17 @@ test_expect_success 'Prune empty commits' '
test_cmp expect actual
'
+test_expect_success 'prune empty collapsed merges' '
+ test_config merge.ff false &&
+ git rev-list HEAD >expect &&
+ test_commit to_remove_2 &&
+ git reset --hard HEAD^ &&
+ test_merge non-ff to_remove_2 &&
+ git filter-branch -f --index-filter "git update-index --remove to_remove_2.t" --prune-empty HEAD &&
+ git rev-list HEAD >actual &&
+ test_cmp expect actual
+'
+
test_expect_success '--remap-to-ancestor with filename filters' '
git checkout master &&
git reset --hard A &&
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index c8d6e9f88c..796e9f79ea 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -1380,4 +1380,109 @@ test_expect_success 'multiple --points-at are OR-ed together' '
test_cmp expect actual
'
+test_expect_success 'lexical sort' '
+ git tag foo1.3 &&
+ git tag foo1.6 &&
+ git tag foo1.10 &&
+ git tag -l --sort=refname "foo*" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.10
+ foo1.3
+ foo1.6
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'version sort' '
+ git tag -l --sort=version:refname "foo*" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.3
+ foo1.6
+ foo1.10
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'reverse version sort' '
+ git tag -l --sort=-version:refname "foo*" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.10
+ foo1.6
+ foo1.3
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'reverse lexical sort' '
+ git tag -l --sort=-refname "foo*" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.6
+ foo1.3
+ foo1.10
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'configured lexical sort' '
+ git config tag.sort "v:refname" &&
+ git tag -l "foo*" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.3
+ foo1.6
+ foo1.10
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'option override configured sort' '
+ git tag -l --sort=-refname "foo*" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.6
+ foo1.3
+ foo1.10
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'invalid sort parameter on command line' '
+ test_must_fail git tag -l --sort=notvalid "foo*" >actual
+'
+
+test_expect_success 'invalid sort parameter in configuratoin' '
+ git config tag.sort "v:notvalid" &&
+ git tag -l "foo*" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.10
+ foo1.3
+ foo1.6
+ EOF
+ test_cmp expect actual
+'
+
+run_with_limited_stack () {
+ (ulimit -s 128 && "$@")
+}
+
+test_lazy_prereq ULIMIT 'run_with_limited_stack true'
+
+# we require ulimit, this excludes Windows
+test_expect_success ULIMIT '--contains works in a deep repo' '
+ >expect &&
+ i=1 &&
+ while test $i -lt 8000
+ do
+ echo "commit refs/heads/master
+committer A U Thor <author@example.com> $((1000000000 + $i * 100)) +0200
+data <<EOF
+commit #$i
+EOF"
+ test $i = 1 && echo "from refs/heads/master^0"
+ i=$(($i + 1))
+ done | git fast-import &&
+ git checkout master &&
+ git tag far-far-away HEAD^ &&
+ run_with_limited_stack git tag --contains HEAD >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index ff2590849d..da958a8b56 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -37,6 +37,18 @@ test_expect_failure TTY 'pager runs from subdir' '
test_cmp expected actual
'
+test_expect_success TTY 'LESS and LV envvars are set for pagination' '
+ (
+ sane_unset LESS LV &&
+ PAGER="env >pager-env.out; wc" &&
+ export PAGER &&
+
+ test_terminal git log
+ ) &&
+ grep ^LESS= pager-env.out &&
+ grep ^LV= pager-env.out
+'
+
test_expect_success TTY 'some commands do not use a pager' '
rm -f paginated.out &&
test_terminal git rev-list HEAD &&
@@ -134,11 +146,7 @@ test_expect_success 'no color when stdout is a regular file' '
test_expect_success TTY 'color when writing to a pager' '
rm -f paginated.out &&
test_config color.ui auto &&
- (
- TERM=vt100 &&
- export TERM &&
- test_terminal git log
- ) &&
+ test_terminal env TERM=vt100 git log &&
colorful paginated.out
'
@@ -146,11 +154,7 @@ test_expect_success TTY 'colors are suppressed by color.pager' '
rm -f paginated.out &&
test_config color.ui auto &&
test_config color.pager false &&
- (
- TERM=vt100 &&
- export TERM &&
- test_terminal git log
- ) &&
+ test_terminal env TERM=vt100 git log &&
! colorful paginated.out
'
@@ -169,11 +173,7 @@ test_expect_success 'color when writing to a file intended for a pager' '
test_expect_success TTY 'colors are sent to pager for external commands' '
test_config alias.externallog "!git log" &&
test_config color.ui auto &&
- (
- TERM=vt100 &&
- export TERM &&
- test_terminal git -p externallog
- ) &&
+ test_terminal env TERM=vt100 git -p externallog &&
colorful paginated.out
'
diff --git a/t/t7007-show.sh b/t/t7007-show.sh
index e41fa00b80..1b824fe5ed 100755
--- a/t/t7007-show.sh
+++ b/t/t7007-show.sh
@@ -24,7 +24,8 @@ test_expect_success 'set up a bit of history' '
git tag -m "annotated tag" annotated &&
git checkout -b side HEAD^^ &&
test_commit side2 &&
- test_commit side3
+ test_commit side3 &&
+ test_merge merge main3
'
test_expect_success 'showing two commits' '
@@ -109,8 +110,11 @@ test_expect_success 'showing range' '
'
test_expect_success '-s suppresses diff' '
- echo main3 >expect &&
- git show -s --format=%s main3 >actual &&
+ cat >expect <<-\EOF &&
+ merge
+ main3
+ EOF
+ git show -s --format=%s merge main3 >actual &&
test_cmp expect actual
'
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index 7d467c034a..741ec08576 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -38,7 +38,7 @@ You have unmerged paths.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
- deleted by us: foo
+ deleted by us: foo
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -142,8 +142,8 @@ You have unmerged paths.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
- both added: conflict.txt
- deleted by them: main.txt
+ both added: conflict.txt
+ deleted by them: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -175,9 +175,9 @@ You have unmerged paths.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
- both deleted: main.txt
- added by them: sub_master.txt
- added by us: sub_second.txt
+ both deleted: main.txt
+ added by them: sub_master.txt
+ added by us: sub_second.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -203,7 +203,7 @@ Changes to be committed:
Unmerged paths:
(use "git rm <file>..." to mark resolution)
- both deleted: main.txt
+ both deleted: main.txt
Untracked files not listed (use -u option to show untracked files)
EOF
diff --git a/t/t7101-reset.sh b/t/t7101-reset-empty-subdirs.sh
index 96e163f084..96e163f084 100755
--- a/t/t7101-reset.sh
+++ b/t/t7101-reset-empty-subdirs.sh
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 8d4b50d1b5..98bcfe21aa 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -22,6 +22,9 @@ commit_msg () {
fi
}
+# Tested non-UTF-8 encoding
+test_encoding="ISO8859-1"
+
test_expect_success 'creating initial files and commits' '
test_tick &&
echo "1st file" >first &&
@@ -41,7 +44,9 @@ test_expect_success 'creating initial files and commits' '
echo "1st line 2nd file" >secondfile &&
echo "2nd line 2nd file" >>secondfile &&
- git -c "i18n.commitEncoding=iso8859-1" commit -a -m "$(commit_msg iso8859-1)" &&
+ # "git commit -m" would break MinGW, as Windows refuse to pass
+ # $test_encoding encoded parameter to git.
+ commit_msg $test_encoding | git -c "i18n.commitEncoding=$test_encoding" commit -a -F - &&
head5=$(git rev-parse --verify HEAD)
'
# git log --pretty=oneline # to see those SHA1 involved
@@ -64,10 +69,10 @@ test_expect_success 'reset --hard message' '
test_cmp .expected .actual
'
-test_expect_success 'reset --hard message (iso8859-1 logoutputencoding)' '
+test_expect_success 'reset --hard message (ISO8859-1 logoutputencoding)' '
hex=$(git log -1 --format="%h") &&
- git -c "i18n.logOutputEncoding=iso8859-1" reset --hard > .actual &&
- echo HEAD is now at $hex $(commit_msg iso8859-1) > .expected &&
+ git -c "i18n.logOutputEncoding=$test_encoding" reset --hard > .actual &&
+ echo HEAD is now at $hex $(commit_msg $test_encoding) > .expected &&
test_cmp .expected .actual
'
@@ -331,7 +336,9 @@ test_expect_success 'redoing the last two commits should succeed' '
echo "1st line 2nd file" >secondfile &&
echo "2nd line 2nd file" >>secondfile &&
- git -c "i18n.commitEncoding=iso8859-1" commit -a -m "$(commit_msg iso8859-1)" &&
+ # "git commit -m" would break MinGW, as Windows refuse to pass
+ # $test_encoding encoded parameter to git.
+ commit_msg $test_encoding | git -c "i18n.commitEncoding=$test_encoding" commit -a -F - &&
check_changes $head5
'
@@ -535,4 +542,30 @@ test_expect_success 'reset with paths accepts tree' '
git diff HEAD --exit-code
'
+test_expect_success 'reset -N keeps removed files as intent-to-add' '
+ echo new-file >new-file &&
+ git add new-file &&
+ git reset -N HEAD &&
+
+ tree=$(git write-tree) &&
+ git ls-tree $tree new-file >actual &&
+ >expect &&
+ test_cmp expect actual &&
+
+ git diff --name-only >actual &&
+ echo new-file >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'reset --mixed sets up work tree' '
+ git init mixed_worktree &&
+ (
+ cd mixed_worktree &&
+ test_commit dummy
+ ) &&
+ : >expect &&
+ git --git-dir=mixed_worktree/.git --work-tree=mixed_worktree reset >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7104-reset.sh b/t/t7104-reset-hard.sh
index f136ee7bb5..16faa07813 100755
--- a/t/t7104-reset.sh
+++ b/t/t7104-reset-hard.sh
@@ -33,7 +33,7 @@ test_expect_success 'reset --hard should restore unmerged ones' '
'
-test_expect_success 'reset --hard did not corrupt index nor cached-tree' '
+test_expect_success 'reset --hard did not corrupt index or cached-tree' '
T=$(git write-tree) &&
rm -f .git/index &&
diff --git a/t/t7112-reset-submodule.sh b/t/t7112-reset-submodule.sh
new file mode 100755
index 0000000000..2eda6adeb1
--- /dev/null
+++ b/t/t7112-reset-submodule.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+test_description='reset can handle submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+test_submodule_switch "git reset --keep"
+
+test_submodule_switch "git reset --merge"
+
+test_submodule_forced_switch "git reset --hard"
+
+test_done
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 0c9ec0ad44..eae9e5a937 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -223,6 +223,23 @@ test_expect_success 'checkout --merge --conflict=diff3 <branch>' '
test_cmp two expect
'
+test_expect_success 'switch to another branch while carrying a deletion' '
+
+ git checkout -f master && git reset --hard && git clean -f &&
+ git rm two &&
+
+ test_must_fail git checkout simple 2>errs &&
+ test_i18ngrep overwritten errs &&
+
+ git checkout --merge simple 2>errs &&
+ test_i18ngrep ! overwritten errs &&
+ git ls-files -u &&
+ test_must_fail git cat-file -t :0:two &&
+ test "$(git cat-file -t :1:two)" = blob &&
+ test "$(git cat-file -t :2:two)" = blob &&
+ test_must_fail git cat-file -t :3:two
+'
+
test_expect_success 'checkout to detach HEAD (with advice declined)' '
git config advice.detachedHead false &&
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 8dbe950bb0..04118ad75b 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -511,4 +511,20 @@ test_expect_success SANITY 'git clean -d with an unreadable empty directory' '
! test -d foo
'
+test_expect_success 'git clean -d respects pathspecs (dir is prefix of pathspec)' '
+ mkdir -p foo &&
+ mkdir -p foobar &&
+ git clean -df foobar &&
+ test_path_is_dir foo &&
+ test_path_is_missing foobar
+'
+
+test_expect_success 'git clean -d respects pathspecs (pathspec is prefix of dir)' '
+ mkdir -p foo &&
+ mkdir -p foobar &&
+ git clean -df foo &&
+ test_path_is_missing foo &&
+ test_path_is_dir foobar
+'
+
test_done
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index c28e8d8ada..7c88245031 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -249,8 +249,7 @@ test_expect_success 'submodule add in subdirectory with relative path should fai
'
test_expect_success 'setup - add an example entry to .gitmodules' '
- GIT_CONFIG=.gitmodules \
- git config submodule.example.url git://example.com/init.git
+ git config --file=.gitmodules submodule.example.url git://example.com/init.git
'
test_expect_success 'status should fail for unmapped paths' '
@@ -264,7 +263,7 @@ test_expect_success 'setup - map path in .gitmodules' '
path = init
EOF
- GIT_CONFIG=.gitmodules git config submodule.example.path init &&
+ git config --file=.gitmodules submodule.example.path init &&
test_cmp expect .gitmodules
'
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 0825a928df..29d3d2cca0 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -762,6 +762,16 @@ test_expect_success 'submodule update clone shallow submodule' '
(cd submodule &&
test 1 = $(git log --oneline | wc -l)
)
+)
+'
+
+test_expect_success 'submodule update --recursive drops module name before recursing' '
+ (cd super2 &&
+ (cd deeper/submodule/subsubmodule &&
+ git checkout HEAD^
+ ) &&
+ git submodule update --recursive deeper/submodule >actual &&
+ test_i18ngrep "Submodule path .deeper/submodule/subsubmodule.: checked out" actual
)
'
test_done
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index b64c9ed8e7..7ca10b8606 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -325,4 +325,13 @@ test_expect_success 'command passed to foreach --recursive retains notion of std
test_cmp expected actual
'
+test_expect_success 'multi-argument command passed to foreach is not shell-evaluated twice' '
+ (
+ cd super &&
+ git submodule foreach "echo \\\"quoted\\\"" > ../expected &&
+ git submodule foreach echo \"quoted\" > ../actual
+ ) &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index bdc1f29503..116885a260 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -223,7 +223,8 @@ test_expect_success 'Commit without message is allowed with --allow-empty-messag
git add foo &&
>empty &&
git commit --allow-empty-message <empty &&
- commit_msg_is ""
+ commit_msg_is "" &&
+ git tag empty-message-commit
'
test_expect_success 'Commit without message is no-no without --allow-empty-message' '
@@ -240,6 +241,14 @@ test_expect_success 'Commit a message with --allow-empty-message' '
commit_msg_is "hello there"
'
+test_expect_success 'commit -C empty respects --allow-empty-message' '
+ echo more >>foo &&
+ git add foo &&
+ test_must_fail git commit -C empty-message-commit &&
+ git commit -C empty-message-commit --allow-empty-message &&
+ commit_msg_is ""
+'
+
commit_for_rebase_autosquash_setup () {
echo "first content line" >>foo &&
git add foo &&
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index f04798f872..63e04277f9 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -57,14 +57,51 @@ test_expect_success 'using invalid commit with -C' '
'
test_expect_success 'nothing to commit' '
+ git reset --hard &&
test_must_fail git commit -m initial
'
+test_expect_success '--dry-run fails with nothing to commit' '
+ test_must_fail git commit -m initial --dry-run
+'
+
+test_expect_success '--short fails with nothing to commit' '
+ test_must_fail git commit -m initial --short
+'
+
+test_expect_success '--porcelain fails with nothing to commit' '
+ test_must_fail git commit -m initial --porcelain
+'
+
+test_expect_success '--long fails with nothing to commit' '
+ test_must_fail git commit -m initial --long
+'
+
test_expect_success 'setup: non-initial commit' '
echo bongo bongo bongo >file &&
git commit -m next -a
'
+test_expect_success '--dry-run with stuff to commit returns ok' '
+ echo bongo bongo bongo >>file &&
+ git commit -m next -a --dry-run
+'
+
+test_expect_failure '--short with stuff to commit returns ok' '
+ echo bongo bongo bongo >>file &&
+ git commit -m next -a --short
+'
+
+test_expect_failure '--porcelain with stuff to commit returns ok' '
+ echo bongo bongo bongo >>file &&
+ git commit -m next -a --porcelain
+'
+
+test_expect_success '--long with stuff to commit returns ok' '
+ echo bongo bongo bongo >>file &&
+ git commit -m next -a --long
+'
+
test_expect_success 'commit message from non-existing file' '
echo more bongo: bongo bongo bongo bongo >file &&
test_must_fail git commit -F gah -a
@@ -309,8 +346,21 @@ test_expect_success 'amend commit to fix date' '
'
-test_expect_success 'commit complains about bogus date' '
- test_must_fail git commit --amend --date=10.11.2010
+test_expect_success 'commit mentions forced date in output' '
+ git commit --amend --date=2010-01-02T03:04:05 >output &&
+ grep "Date: *Sat Jan 2 03:04:05 2010" output
+'
+
+test_expect_success 'commit complains about completely bogus dates' '
+ test_must_fail git commit --amend --date=seventeen
+'
+
+test_expect_success 'commit --date allows approxidate' '
+ git commit --amend \
+ --date="midnight the 12th of october, anno domini 1979" &&
+ echo "Fri Oct 12 00:00:00 1979 +0000" >expect &&
+ git log -1 --format=%ad >actual &&
+ test_cmp expect actual
'
test_expect_success 'sign off (1)' '
diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index 6313da2cdd..051489ea33 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -223,6 +223,22 @@ test_expect_success 'cleanup commit messages (whitespace option,-F)' '
'
+test_expect_success 'cleanup commit messages (scissors option,-F,-e)' '
+
+ echo >>negative &&
+ cat >text <<EOF &&
+
+# to be kept
+# ------------------------ >8 ------------------------
+to be removed
+EOF
+ echo "# to be kept" >expect &&
+ git commit --cleanup=scissors -e -F text -a &&
+ git cat-file -p HEAD |sed -e "1,/^\$/d">actual &&
+ test_cmp expect actual
+
+'
+
test_expect_success 'cleanup commit messages (strip option,-F)' '
echo >>negative &&
@@ -328,6 +344,13 @@ test_expect_success 'message shows author when it is not equal to committer' '
.git/COMMIT_EDITMSG
'
+test_expect_success 'message shows date when it is explicitly set' '
+ git commit --allow-empty -e -m foo --date="2010-01-02T03:04:05" &&
+ test_i18ngrep \
+ "^# Date: *Sat Jan 2 03:04:05 2010 +0000" \
+ .git/COMMIT_EDITMSG
+'
+
test_expect_success AUTOIDENT 'message shows committer when it is automatic' '
echo >>negative &&
@@ -547,4 +570,30 @@ test_expect_success 'commit --status with custom comment character' '
test_i18ngrep "^; Changes to be committed:" .git/COMMIT_EDITMSG
'
+test_expect_success 'switch core.commentchar' '
+ test_commit "#foo" foo &&
+ GIT_EDITOR=.git/FAKE_EDITOR git -c core.commentChar=auto commit --amend &&
+ test_i18ngrep "^; Changes to be committed:" .git/COMMIT_EDITMSG
+'
+
+test_expect_success 'switch core.commentchar but out of options' '
+ cat >text <<\EOF &&
+# 1
+; 2
+@ 3
+! 4
+$ 5
+% 6
+^ 7
+& 8
+| 9
+: 10
+EOF
+ git commit --amend -F text &&
+ (
+ test_set_editor .git/FAKE_EDITOR &&
+ test_must_fail git -c core.commentChar=auto commit --amend
+ )
+'
+
test_done
diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh
index 357375151d..03dce09cfe 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -134,14 +134,26 @@ test_expect_success 'with hook (-c)' '
test_expect_success 'with hook (merge)' '
- head=`git rev-parse HEAD` &&
- git checkout -b other HEAD@{1} &&
- echo "more" >> file &&
+ test_when_finished "git checkout -f master" &&
+ git checkout -B other HEAD@{1} &&
+ echo "more" >>file &&
+ git add file &&
+ git commit -m other &&
+ git checkout - &&
+ git merge --no-ff other &&
+ test "`git log -1 --pretty=format:%s`" = "merge (no editor)"
+'
+
+test_expect_success 'with hook and editor (merge)' '
+
+ test_when_finished "git checkout -f master" &&
+ git checkout -B other HEAD@{1} &&
+ echo "more" >>file &&
git add file &&
git commit -m other &&
git checkout - &&
- git merge other &&
- test "`git log -1 --pretty=format:%s`" = merge
+ env GIT_EDITOR="\"\$FAKE_EDITOR\"" git merge --no-ff -e other &&
+ test "`git log -1 --pretty=format:%s`" = "merge"
'
cat > "$HOOK" <<'EOF'
@@ -151,34 +163,37 @@ EOF
test_expect_success 'with failing hook' '
+ test_when_finished "git checkout -f master" &&
head=`git rev-parse HEAD` &&
echo "more" >> file &&
git add file &&
- ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
+ test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
'
test_expect_success 'with failing hook (--no-verify)' '
+ test_when_finished "git checkout -f master" &&
head=`git rev-parse HEAD` &&
echo "more" >> file &&
git add file &&
- ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
+ test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
'
test_expect_success 'with failing hook (merge)' '
+ test_when_finished "git checkout -f master" &&
git checkout -B other HEAD@{1} &&
echo "more" >> file &&
git add file &&
rm -f "$HOOK" &&
git commit -m other &&
- write_script "$HOOK" <<-EOF
+ write_script "$HOOK" <<-EOF &&
exit 1
EOF
git checkout - &&
- test_must_fail git merge other
+ test_must_fail git merge --no-ff other
'
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index c987b5ed65..8ed5788808 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -1350,8 +1350,7 @@ test_expect_success "status (core.commentchar with submodule summary)" '
test_expect_success "status (core.commentchar with two chars with submodule summary)" '
test_config core.commentchar ";;" &&
- git -c status.displayCommentPrefix=true status >output &&
- test_i18ncmp expect output
+ test_must_fail git -c status.displayCommentPrefix=true status
'
test_expect_success "--ignore-submodules=all suppresses submodule summary" '
@@ -1380,7 +1379,32 @@ EOF
test_i18ncmp expect output
'
-test_expect_success '.gitmodules ignore=all suppresses submodule summary' '
+test_expect_success '.gitmodules ignore=all suppresses unstaged submodule summary' '
+ cat > expect << EOF &&
+On branch master
+Changes to be committed:
+ (use "git reset HEAD <file>..." to unstage)
+
+ modified: sm
+
+Changes not staged for commit:
+ (use "git add <file>..." to update what will be committed)
+ (use "git checkout -- <file>..." to discard changes in working directory)
+
+ modified: dir1/modified
+
+Untracked files:
+ (use "git add <file>..." to include in what will be committed)
+
+ .gitmodules
+ dir1/untracked
+ dir2/modified
+ dir2/untracked
+ expect
+ output
+ untracked
+
+EOF
git config --add -f .gitmodules submodule.subname.ignore all &&
git config --add -f .gitmodules submodule.subname.path sm &&
git status > output &&
@@ -1388,7 +1412,7 @@ test_expect_success '.gitmodules ignore=all suppresses submodule summary' '
git config -f .gitmodules --remove-section submodule.subname
'
-test_expect_success '.git/config ignore=all suppresses submodule summary' '
+test_expect_success '.git/config ignore=all suppresses unstaged submodule summary' '
git config --add -f .gitmodules submodule.subname.ignore none &&
git config --add -f .gitmodules submodule.subname.path sm &&
git config --add submodule.subname.ignore all &&
@@ -1461,4 +1485,49 @@ test_expect_success 'Restore default test environment' '
git config --unset status.showUntrackedFiles
'
+test_expect_success 'git commit will commit a staged but ignored submodule' '
+ git config --add -f .gitmodules submodule.subname.ignore all &&
+ git config --add -f .gitmodules submodule.subname.path sm &&
+ git config --add submodule.subname.ignore all &&
+ git status -s --ignore-submodules=dirty >output &&
+ test_i18ngrep "^M. sm" output &&
+ GIT_EDITOR="echo hello >>\"\$1\"" &&
+ export GIT_EDITOR &&
+ git commit -uno &&
+ git status -s --ignore-submodules=dirty >output &&
+ test_i18ngrep ! "^M. sm" output
+'
+
+test_expect_success 'git commit --dry-run will show a staged but ignored submodule' '
+ git reset HEAD^ &&
+ git add sm &&
+ cat >expect << EOF &&
+On branch master
+Changes to be committed:
+ (use "git reset HEAD <file>..." to unstage)
+
+ modified: sm
+
+Changes not staged for commit:
+ (use "git add <file>..." to update what will be committed)
+ (use "git checkout -- <file>..." to discard changes in working directory)
+
+ modified: dir1/modified
+
+Untracked files not listed (use -u option to show untracked files)
+EOF
+ git commit -uno --dry-run >output &&
+ test_i18ncmp expect output &&
+ git status -s --ignore-submodules=dirty >output &&
+ test_i18ngrep "^M. sm" output
+'
+
+test_expect_success 'git commit -m will commit a staged but ignored submodule' '
+ git commit -uno -m message &&
+ git status -s --ignore-submodules=dirty >output &&
+ test_i18ngrep ! "^M. sm" output &&
+ git config --remove-section submodule.subname &&
+ git config -f .gitmodules --remove-section submodule.subname
+'
+
test_done
diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh
index b61fd3c3c4..9ac794052d 100755
--- a/t/t7509-commit.sh
+++ b/t/t7509-commit.sh
@@ -77,6 +77,7 @@ test_expect_success '--amend option copies authorship' '
git commit -a --amend -m "amend test" &&
author_header Initial >expect &&
author_header HEAD >actual &&
+ test_cmp expect actual &&
echo "amend test" >expect &&
message_body HEAD >actual &&
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 1d3c56fe61..474dab381a 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -5,6 +5,8 @@ test_description='signed commit tests'
. "$TEST_DIRECTORY/lib-gpg.sh"
test_expect_success GPG 'create signed commits' '
+ test_when_finished "test_unconfig commit.gpgsign" &&
+
echo 1 >file && git add file &&
test_tick && git commit -S -m initial &&
git tag initial &&
@@ -25,45 +27,90 @@ test_expect_success GPG 'create signed commits' '
git tag fourth-unsigned &&
test_tick && git commit --amend -S -m "fourth signed" &&
- git tag fourth-signed
+ git tag fourth-signed &&
+
+ git config commit.gpgsign true &&
+ echo 5 >file && test_tick && git commit -a -m "fifth signed" &&
+ git tag fifth-signed &&
+
+ git config commit.gpgsign false &&
+ echo 6 >file && test_tick && git commit -a -m "sixth" &&
+ git tag sixth-unsigned &&
+
+ git config commit.gpgsign true &&
+ echo 7 >file && test_tick && git commit -a -m "seventh" --no-gpg-sign &&
+ git tag seventh-unsigned &&
+
+ test_tick && git rebase -f HEAD^^ && git tag sixth-signed HEAD^ &&
+ git tag seventh-signed
+
+ echo 8 >file && test_tick && git commit -a -m eighth -SB7227189 &&
+ git tag eighth-signed-alt
'
-test_expect_success GPG 'show signatures' '
+test_expect_success GPG 'verify and show signatures' '
(
- for commit in initial second merge master
+ for commit in initial second merge fourth-signed fifth-signed sixth-signed seventh-signed
do
+ git verify-commit $commit &&
git show --pretty=short --show-signature $commit >actual &&
- grep "Good signature from" actual || exit 1
- ! grep "BAD signature from" actual || exit 1
- echo $commit OK
+ grep "Good signature from" actual &&
+ ! grep "BAD signature from" actual &&
+ echo $commit OK || exit 1
done
) &&
(
- for commit in merge^2 fourth-unsigned
+ for commit in merge^2 fourth-unsigned sixth-unsigned seventh-unsigned
do
+ test_must_fail git verify-commit $commit &&
git show --pretty=short --show-signature $commit >actual &&
- grep "Good signature from" actual && exit 1
- ! grep "BAD signature from" actual || exit 1
- echo $commit OK
+ ! grep "Good signature from" actual &&
+ ! grep "BAD signature from" actual &&
+ echo $commit OK || exit 1
+ done
+ ) &&
+ (
+ for commit in eighth-signed-alt
+ do
+ git show --pretty=short --show-signature $commit >actual &&
+ grep "Good signature from" actual &&
+ ! grep "BAD signature from" actual &&
+ grep "not certified" actual &&
+ echo $commit OK || exit 1
done
)
'
+test_expect_success GPG 'show signed commit with signature' '
+ git show -s initial >commit &&
+ git show -s --show-signature initial >show &&
+ git verify-commit -v initial >verify.1 2>verify.2 &&
+ git cat-file commit initial >cat &&
+ grep -v "gpg: " show >show.commit &&
+ grep "gpg: " show >show.gpg &&
+ grep -v "^ " cat | grep -v "^gpgsig " >cat.commit &&
+ test_cmp show.commit commit &&
+ test_cmp show.gpg verify.2 &&
+ test_cmp cat.commit verify.1
+'
+
test_expect_success GPG 'detect fudged signature' '
- git cat-file commit master >raw &&
+ git cat-file commit seventh-signed >raw &&
- sed -e "s/fourth signed/4th forged/" raw >forged1 &&
+ sed -e "s/seventh/7th forged/" raw >forged1 &&
git hash-object -w -t commit forged1 >forged1.commit &&
+ ! git verify-commit $(cat forged1.commit) &&
git show --pretty=short --show-signature $(cat forged1.commit) >actual1 &&
grep "BAD signature from" actual1 &&
! grep "Good signature from" actual1
'
test_expect_success GPG 'detect fudged signature with NUL' '
- git cat-file commit master >raw &&
+ git cat-file commit seventh-signed >raw &&
cat raw >forged2 &&
echo Qwik | tr "Q" "\000" >>forged2 &&
git hash-object -w -t commit forged2 >forged2.commit &&
+ ! git verify-commit $(cat forged2.commit) &&
git show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&
grep "BAD signature from" actual2 &&
! grep "Good signature from" actual2
@@ -72,9 +119,50 @@ test_expect_success GPG 'detect fudged signature with NUL' '
test_expect_success GPG 'amending already signed commit' '
git checkout fourth-signed^0 &&
git commit --amend -S --no-edit &&
+ git verify-commit HEAD &&
git show -s --show-signature HEAD >actual &&
grep "Good signature from" actual &&
! grep "BAD signature from" actual
'
+test_expect_success GPG 'show good signature with custom format' '
+ cat >expect <<-\EOF &&
+ G
+ 13B6F51ECDDE430D
+ C O Mitter <committer@example.com>
+ EOF
+ git log -1 --format="%G?%n%GK%n%GS" sixth-signed >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'show bad signature with custom format' '
+ cat >expect <<-\EOF &&
+ B
+ 13B6F51ECDDE430D
+ C O Mitter <committer@example.com>
+ EOF
+ git log -1 --format="%G?%n%GK%n%GS" $(cat forged1.commit) >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'show unknown signature with custom format' '
+ cat >expect <<-\EOF &&
+ U
+ 61092E85B7227189
+ Eris Discordia <discord@example.net>
+ EOF
+ git log -1 --format="%G?%n%GK%n%GS" eighth-signed-alt >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG 'show lack of signature with custom format' '
+ cat >expect <<-\EOF &&
+ N
+
+
+ EOF
+ git log -1 --format="%G?%n%GK%n%GS" seventh-unsigned >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 3cec57af1e..68ad2d7454 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -33,7 +33,7 @@ You have unmerged paths.
Unmerged paths:
(use "git add <file>..." to mark resolution)
- both modified: main.txt
+ both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -87,7 +87,7 @@ Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)
- both modified: main.txt
+ both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -146,7 +146,7 @@ Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)
- both modified: main.txt
+ both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -602,7 +602,7 @@ rebase in progress; onto $ONTO
You are currently rebasing branch '\''statushints_disabled'\'' on '\''$ONTO'\''.
Unmerged paths:
- both modified: main.txt
+ both modified: main.txt
no changes added to commit
EOF
@@ -636,7 +636,7 @@ You are currently cherry-picking commit $TO_CHERRY_PICK.
Unmerged paths:
(use "git add <file>..." to mark resolution)
- both modified: main.txt
+ both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
@@ -707,7 +707,7 @@ Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)
- both modified: to-revert.txt
+ both modified: to-revert.txt
no changes added to commit (use "git add" and/or "git commit -a")
EOF
diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
new file mode 100755
index 0000000000..1efb88051a
--- /dev/null
+++ b/t/t7513-interpret-trailers.sh
@@ -0,0 +1,863 @@
+#!/bin/sh
+#
+# Copyright (c) 2013, 2014 Christian Couder
+#
+
+test_description='git interpret-trailers'
+
+. ./test-lib.sh
+
+# When we want one trailing space at the end of each line, let's use sed
+# to make sure that these spaces are not removed by any automatic tool.
+
+test_expect_success 'setup' '
+ : >empty &&
+ cat >basic_message <<-\EOF &&
+ subject
+
+ body
+ EOF
+ cat >complex_message_body <<-\EOF &&
+ my subject
+
+ my body which is long
+ and contains some special
+ chars like : = ? !
+
+ EOF
+ sed -e "s/ Z\$/ /" >complex_message_trailers <<-\EOF &&
+ Fixes: Z
+ Acked-by: Z
+ Reviewed-by: Z
+ Signed-off-by: Z
+ EOF
+ cat >basic_patch <<-\EOF
+ ---
+ foo.txt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+ diff --git a/foo.txt b/foo.txt
+ index 0353767..1d91aa1 100644
+ --- a/foo.txt
+ +++ b/foo.txt
+ @@ -1,3 +1,3 @@
+
+ -bar
+ +baz
+
+ --
+ 1.9.rc0.11.ga562ddc
+
+ EOF
+'
+
+test_expect_success 'without config' '
+ sed -e "s/ Z\$/ /" >expected <<-\EOF &&
+
+ ack: Peff
+ Reviewed-by: Z
+ Acked-by: Johan
+ EOF
+ git interpret-trailers --trailer "ack = Peff" --trailer "Reviewed-by" \
+ --trailer "Acked-by: Johan" empty >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'without config in another order' '
+ sed -e "s/ Z\$/ /" >expected <<-\EOF &&
+
+ Acked-by: Johan
+ Reviewed-by: Z
+ ack: Peff
+ EOF
+ git interpret-trailers --trailer "Acked-by: Johan" --trailer "Reviewed-by" \
+ --trailer "ack = Peff" empty >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '--trim-empty without config' '
+ cat >expected <<-\EOF &&
+
+ ack: Peff
+ Acked-by: Johan
+ EOF
+ git interpret-trailers --trim-empty --trailer ack=Peff \
+ --trailer "Reviewed-by" --trailer "Acked-by: Johan" \
+ --trailer "sob:" empty >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with config option on the command line' '
+ cat >expected <<-\EOF &&
+
+ Acked-by: Johan
+ Reviewed-by: Peff
+ EOF
+ echo "Acked-by: Johan" |
+ git -c "trailer.Acked-by.ifexists=addifdifferent" interpret-trailers \
+ --trailer "Reviewed-by: Peff" --trailer "Acked-by: Johan" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with config setup' '
+ git config trailer.ack.key "Acked-by: " &&
+ cat >expected <<-\EOF &&
+
+ Acked-by: Peff
+ EOF
+ git interpret-trailers --trim-empty --trailer "ack = Peff" empty >actual &&
+ test_cmp expected actual &&
+ git interpret-trailers --trim-empty --trailer "Acked-by = Peff" empty >actual &&
+ test_cmp expected actual &&
+ git interpret-trailers --trim-empty --trailer "Acked-by :Peff" empty >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with config setup and ":=" as separators' '
+ git config trailer.separators ":=" &&
+ git config trailer.ack.key "Acked-by= " &&
+ cat >expected <<-\EOF &&
+
+ Acked-by= Peff
+ EOF
+ git interpret-trailers --trim-empty --trailer "ack = Peff" empty >actual &&
+ test_cmp expected actual &&
+ git interpret-trailers --trim-empty --trailer "Acked-by= Peff" empty >actual &&
+ test_cmp expected actual &&
+ git interpret-trailers --trim-empty --trailer "Acked-by : Peff" empty >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with config setup and "%" as separators' '
+ git config trailer.separators "%" &&
+ cat >expected <<-\EOF &&
+
+ bug% 42
+ count% 10
+ bug% 422
+ EOF
+ git interpret-trailers --trim-empty --trailer "bug = 42" \
+ --trailer count%10 --trailer "test: stuff" \
+ --trailer "bug % 422" empty >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with "%" as separators and a message with trailers' '
+ cat >special_message <<-\EOF &&
+ Special Message
+
+ bug% 42
+ count% 10
+ bug% 422
+ EOF
+ cat >expected <<-\EOF &&
+ Special Message
+
+ bug% 42
+ count% 10
+ bug% 422
+ count% 100
+ EOF
+ git interpret-trailers --trailer count%100 \
+ special_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with config setup and ":=#" as separators' '
+ git config trailer.separators ":=#" &&
+ git config trailer.bug.key "Bug #" &&
+ cat >expected <<-\EOF &&
+
+ Bug #42
+ EOF
+ git interpret-trailers --trim-empty --trailer "bug = 42" empty >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with commit basic message' '
+ cat basic_message >expected &&
+ echo >>expected &&
+ git interpret-trailers <basic_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with basic patch' '
+ cat basic_message >input &&
+ cat basic_patch >>input &&
+ cat basic_message >expected &&
+ echo >>expected &&
+ cat basic_patch >>expected &&
+ git interpret-trailers <input >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with commit complex message as argument' '
+ cat complex_message_body complex_message_trailers >complex_message &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by: Z
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with 2 files arguments' '
+ cat basic_message >>expected &&
+ echo >>expected &&
+ cat basic_patch >>expected &&
+ git interpret-trailers complex_message input >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with message that has comments' '
+ cat basic_message >>message_with_comments &&
+ sed -e "s/ Z\$/ /" >>message_with_comments <<-\EOF &&
+ # comment
+
+ # other comment
+ Cc: Z
+ # yet another comment
+ Reviewed-by: Johan
+ Reviewed-by: Z
+ # last comment
+
+ EOF
+ cat basic_patch >>message_with_comments &&
+ cat basic_message >expected &&
+ cat >>expected <<-\EOF &&
+ # comment
+
+ Reviewed-by: Johan
+ Cc: Peff
+ EOF
+ cat basic_patch >>expected &&
+ git interpret-trailers --trim-empty --trailer "Cc: Peff" message_with_comments >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with commit complex message and trailer args' '
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by: Z
+ Signed-off-by: Z
+ Acked-by= Peff
+ Bug #42
+ EOF
+ git interpret-trailers --trailer "ack: Peff" \
+ --trailer "bug: 42" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with complex patch, args and --trim-empty' '
+ cat complex_message >complex_patch &&
+ cat basic_patch >>complex_patch &&
+ cat complex_message_body >expected &&
+ cat >>expected <<-\EOF &&
+ Acked-by= Peff
+ Bug #42
+ EOF
+ cat basic_patch >>expected &&
+ git interpret-trailers --trim-empty --trailer "ack: Peff" \
+ --trailer "bug: 42" <complex_patch >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "where = before"' '
+ git config trailer.bug.where "before" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by: Z
+ Signed-off-by: Z
+ Acked-by= Peff
+ EOF
+ git interpret-trailers --trailer "ack: Peff" \
+ --trailer "bug: 42" complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "where = after"' '
+ git config trailer.ack.where "after" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Peff
+ Reviewed-by: Z
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "ack: Peff" \
+ --trailer "bug: 42" complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "where = end"' '
+ git config trailer.review.key "Reviewed-by" &&
+ git config trailer.review.where "end" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Peff
+ Reviewed-by: Z
+ Signed-off-by: Z
+ Reviewed-by: Junio
+ Reviewed-by: Johannes
+ EOF
+ git interpret-trailers --trailer "ack: Peff" \
+ --trailer "Reviewed-by: Junio" --trailer "Reviewed-by: Johannes" \
+ complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "where = start"' '
+ git config trailer.review.key "Reviewed-by" &&
+ git config trailer.review.where "start" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Reviewed-by: Johannes
+ Reviewed-by: Junio
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Peff
+ Reviewed-by: Z
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "ack: Peff" \
+ --trailer "Reviewed-by: Junio" --trailer "Reviewed-by: Johannes" \
+ complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "where = before" for a token in the middle of the message' '
+ git config trailer.review.key "Reviewed-by:" &&
+ git config trailer.review.where "before" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Peff
+ Reviewed-by:Johan
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "ack: Peff" --trailer "bug: 42" \
+ --trailer "review: Johan" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "where = before" and --trim-empty' '
+ cat complex_message_body >expected &&
+ cat >>expected <<-\EOF &&
+ Bug #46
+ Bug #42
+ Acked-by= Peff
+ Reviewed-by:Johan
+ EOF
+ git interpret-trailers --trim-empty --trailer "ack: Peff" \
+ --trailer "bug: 42" --trailer "review: Johan" \
+ --trailer "Bug: 46" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'the default is "ifExists = addIfDifferentNeighbor"' '
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Peff
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "ack: Peff" --trailer "review:" \
+ --trailer "ack: Junio" --trailer "bug: 42" --trailer "ack: Peff" \
+ --trailer "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'default "ifExists" is now "addIfDifferent"' '
+ git config trailer.ifexists "addIfDifferent" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Peff
+ Acked-by= Junio
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "ack: Peff" --trailer "review:" \
+ --trailer "ack: Junio" --trailer "bug: 42" --trailer "ack: Peff" \
+ --trailer "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = addIfDifferent" with "where = end"' '
+ git config trailer.ack.ifExists "addIfDifferent" &&
+ git config trailer.ack.where "end" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by:
+ Signed-off-by: Z
+ Acked-by= Peff
+ EOF
+ git interpret-trailers --trailer "ack: Peff" --trailer "review:" \
+ --trailer "bug: 42" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = addIfDifferent" with "where = before"' '
+ git config trailer.ack.ifExists "addIfDifferent" &&
+ git config trailer.ack.where "before" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Peff
+ Acked-by= Z
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "ack: Peff" --trailer "review:" \
+ --trailer "bug: 42" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = addIfDifferentNeighbor" with "where = end"' '
+ git config trailer.ack.ifExists "addIfDifferentNeighbor" &&
+ git config trailer.ack.where "end" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by:
+ Signed-off-by: Z
+ Acked-by= Peff
+ Acked-by= Junio
+ Tested-by: Jakub
+ Acked-by= Junio
+ Acked-by= Peff
+ EOF
+ git interpret-trailers --trailer "ack: Peff" --trailer "review:" \
+ --trailer "ack: Junio" --trailer "bug: 42" \
+ --trailer "Tested-by: Jakub" --trailer "ack: Junio" \
+ --trailer "ack: Junio" --trailer "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = addIfDifferentNeighbor" with "where = after"' '
+ git config trailer.ack.ifExists "addIfDifferentNeighbor" &&
+ git config trailer.ack.where "after" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Peff
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ Tested-by: Jakub
+ EOF
+ git interpret-trailers --trailer "ack: Peff" --trailer "review:" \
+ --trailer "ack: Junio" --trailer "bug: 42" \
+ --trailer "Tested-by: Jakub" --trailer "ack: Junio" \
+ --trailer "ack: Junio" --trailer "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = addIfDifferentNeighbor" and --trim-empty' '
+ git config trailer.ack.ifExists "addIfDifferentNeighbor" &&
+ cat complex_message_body >expected &&
+ cat >>expected <<-\EOF &&
+ Bug #42
+ Acked-by= Peff
+ Acked-by= Junio
+ Acked-by= Peff
+ EOF
+ git interpret-trailers --trim-empty --trailer "ack: Peff" \
+ --trailer "Acked-by= Peff" --trailer "review:" \
+ --trailer "ack: Junio" --trailer "bug: 42" \
+ --trailer "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = add" with "where = end"' '
+ git config trailer.ack.ifExists "add" &&
+ git config trailer.ack.where "end" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by:
+ Signed-off-by: Z
+ Acked-by= Peff
+ Acked-by= Peff
+ Tested-by: Jakub
+ Acked-by= Junio
+ Tested-by: Johannes
+ Acked-by= Peff
+ EOF
+ git interpret-trailers --trailer "ack: Peff" \
+ --trailer "Acked-by= Peff" --trailer "review:" \
+ --trailer "Tested-by: Jakub" --trailer "ack: Junio" \
+ --trailer "bug: 42" --trailer "Tested-by: Johannes" \
+ --trailer "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = add" with "where = after"' '
+ git config trailer.ack.ifExists "add" &&
+ git config trailer.ack.where "after" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Peff
+ Acked-by= Peff
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "ack: Peff" \
+ --trailer "Acked-by= Peff" --trailer "review:" \
+ --trailer "ack: Junio" --trailer "bug: 42" \
+ --trailer "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = replace"' '
+ git config trailer.fix.key "Fixes: " &&
+ git config trailer.fix.ifExists "replace" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Acked-by= Z
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ Fixes: 22
+ EOF
+ git interpret-trailers --trailer "review:" \
+ --trailer "fix=53" --trailer "ack: Junio" --trailer "fix=22" \
+ --trailer "bug: 42" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = replace" with "where = after"' '
+ git config trailer.fix.where "after" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: 22
+ Acked-by= Z
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "review:" \
+ --trailer "fix=53" --trailer "ack: Junio" --trailer "fix=22" \
+ --trailer "bug: 42" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifExists = doNothing"' '
+ git config trailer.fix.ifExists "doNothing" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=53" \
+ --trailer "ack: Junio" --trailer "fix=22" \
+ --trailer "bug: 42" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'the default is "ifMissing = add"' '
+ git config trailer.cc.key "Cc: " &&
+ git config trailer.cc.where "before" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Cc: Linus
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=53" \
+ --trailer "cc=Linus" --trailer "ack: Junio" \
+ --trailer "fix=22" --trailer "bug: 42" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'when default "ifMissing" is "doNothing"' '
+ git config trailer.ifmissing "doNothing" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=53" \
+ --trailer "cc=Linus" --trailer "ack: Junio" \
+ --trailer "fix=22" --trailer "bug: 42" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual &&
+ git config trailer.ifmissing "add"
+'
+
+test_expect_success 'using "ifMissing = add" with "where = end"' '
+ git config trailer.cc.key "Cc: " &&
+ git config trailer.cc.where "end" &&
+ git config trailer.cc.ifMissing "add" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ Cc: Linus
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=53" \
+ --trailer "ack: Junio" --trailer "fix=22" \
+ --trailer "bug: 42" --trailer "cc=Linus" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifMissing = add" with "where = before"' '
+ git config trailer.cc.key "Cc: " &&
+ git config trailer.cc.where "before" &&
+ git config trailer.cc.ifMissing "add" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Cc: Linus
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=53" \
+ --trailer "ack: Junio" --trailer "fix=22" \
+ --trailer "bug: 42" --trailer "cc=Linus" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'using "ifMissing = doNothing"' '
+ git config trailer.cc.ifMissing "doNothing" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=53" \
+ --trailer "cc=Linus" --trailer "ack: Junio" \
+ --trailer "fix=22" --trailer "bug: 42" --trailer "ack: Peff" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'default "where" is now "after"' '
+ git config trailer.where "after" &&
+ git config --unset trailer.ack.where &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Bug #42
+ Fixes: Z
+ Acked-by= Z
+ Acked-by= Peff
+ Acked-by= Peff
+ Acked-by= Junio
+ Acked-by= Peff
+ Reviewed-by:
+ Signed-off-by: Z
+ Tested-by: Jakub
+ Tested-by: Johannes
+ EOF
+ git interpret-trailers --trailer "ack: Peff" \
+ --trailer "Acked-by= Peff" --trailer "review:" \
+ --trailer "Tested-by: Jakub" --trailer "ack: Junio" \
+ --trailer "bug: 42" --trailer "Tested-by: Johannes" \
+ --trailer "ack: Peff" <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with simple command' '
+ git config trailer.sign.key "Signed-off-by: " &&
+ git config trailer.sign.where "after" &&
+ git config trailer.sign.ifExists "addIfDifferentNeighbor" &&
+ git config trailer.sign.command "echo \"A U Thor <author@example.com>\"" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by:
+ Signed-off-by: Z
+ Signed-off-by: A U Thor <author@example.com>
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=22" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with command using commiter information' '
+ git config trailer.sign.ifExists "addIfDifferent" &&
+ git config trailer.sign.command "echo \"\$GIT_COMMITTER_NAME <\$GIT_COMMITTER_EMAIL>\"" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by:
+ Signed-off-by: Z
+ Signed-off-by: C O Mitter <committer@example.com>
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=22" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with command using author information' '
+ git config trailer.sign.key "Signed-off-by: " &&
+ git config trailer.sign.where "after" &&
+ git config trailer.sign.ifExists "addIfDifferentNeighbor" &&
+ git config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by:
+ Signed-off-by: Z
+ Signed-off-by: A U Thor <author@example.com>
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=22" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'setup a commit' '
+ echo "Content of the first commit." > a.txt &&
+ git add a.txt &&
+ git commit -m "Add file a.txt"
+'
+
+test_expect_success 'with command using $ARG' '
+ git config trailer.fix.ifExists "replace" &&
+ git config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 \$ARG" &&
+ FIXED=$(git log -1 --oneline --format="%h (%s)" --abbrev-commit --abbrev=14 HEAD) &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-EOF &&
+ Fixes: $FIXED
+ Acked-by= Z
+ Reviewed-by:
+ Signed-off-by: Z
+ Signed-off-by: A U Thor <author@example.com>
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=HEAD" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with failing command using $ARG' '
+ git config trailer.fix.ifExists "replace" &&
+ git config trailer.fix.command "false \$ARG" &&
+ cat complex_message_body >expected &&
+ sed -e "s/ Z\$/ /" >>expected <<-EOF &&
+ Fixes: Z
+ Acked-by= Z
+ Reviewed-by:
+ Signed-off-by: Z
+ Signed-off-by: A U Thor <author@example.com>
+ EOF
+ git interpret-trailers --trailer "review:" --trailer "fix=HEAD" \
+ <complex_message >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with empty tokens' '
+ git config --unset trailer.fix.command &&
+ cat >expected <<-EOF &&
+
+ Signed-off-by: A U Thor <author@example.com>
+ EOF
+ git interpret-trailers --trailer ":" --trailer ":test" >actual <<-EOF &&
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'with command but no key' '
+ git config --unset trailer.sign.key &&
+ cat >expected <<-EOF &&
+
+ sign: A U Thor <author@example.com>
+ EOF
+ git interpret-trailers >actual <<-EOF &&
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'with no command and no key' '
+ git config --unset trailer.review.key &&
+ cat >expected <<-EOF &&
+
+ review: Junio
+ sign: A U Thor <author@example.com>
+ EOF
+ git interpret-trailers --trailer "review:Junio" >actual <<-EOF &&
+ EOF
+ test_cmp expected actual
+'
+
+test_done
diff --git a/t/t7514-commit-patch.sh b/t/t7514-commit-patch.sh
new file mode 100755
index 0000000000..998a2103c7
--- /dev/null
+++ b/t/t7514-commit-patch.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='hunk edit with "commit -p -m"'
+. ./test-lib.sh
+
+if ! test_have_prereq PERL
+then
+ skip_all="skipping '$test_description' tests, perl not available"
+ test_done
+fi
+
+test_expect_success 'setup (initial)' '
+ echo line1 >file &&
+ git add file &&
+ git commit -m commit1
+'
+
+test_expect_success 'edit hunk "commit -p -m message"' '
+ test_when_finished "rm -f editor_was_started" &&
+ rm -f editor_was_started &&
+ echo more >>file &&
+ echo e | env GIT_EDITOR=": >editor_was_started" git commit -p -m commit2 file &&
+ test -r editor_was_started
+'
+
+test_expect_success 'edit hunk "commit --dry-run -p -m message"' '
+ test_when_finished "rm -f editor_was_started" &&
+ rm -f editor_was_started &&
+ echo more >>file &&
+ echo e | env GIT_EDITOR=": >editor_was_started" git commit -p -m commit3 file &&
+ test -r editor_was_started
+'
+
+test_done
diff --git a/t/t7515-status-symlinks.sh b/t/t7515-status-symlinks.sh
new file mode 100755
index 0000000000..9f989be01b
--- /dev/null
+++ b/t/t7515-status-symlinks.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+test_description='git status and symlinks'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo .gitignore >.gitignore &&
+ echo actual >>.gitignore &&
+ echo expect >>.gitignore &&
+ mkdir dir &&
+ echo x >dir/file1 &&
+ echo y >dir/file2 &&
+ git add dir &&
+ git commit -m initial &&
+ git tag initial
+'
+
+test_expect_success SYMLINKS 'symlink to a directory' '
+ test_when_finished "rm symlink" &&
+ ln -s dir symlink &&
+ echo "?? symlink" >expect &&
+ git status --porcelain >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success SYMLINKS 'symlink replacing a directory' '
+ test_when_finished "rm -rf copy && git reset --hard initial" &&
+ mkdir copy &&
+ cp dir/file1 copy/file1 &&
+ echo "changed in copy" >copy/file2 &&
+ git add copy &&
+ git commit -m second &&
+ rm -rf copy &&
+ ln -s dir copy &&
+ echo " D copy/file1" >expect &&
+ echo " D copy/file2" >>expect &&
+ echo "?? copy" >>expect &&
+ git status --porcelain >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 10aa028017..b16462132f 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -57,11 +57,10 @@ create_merge_msgs () {
git log --no-merges ^HEAD c2 c3
} >squash.1-5-9 &&
: >msg.nologff &&
- echo >msg.nolognoff &&
+ : >msg.nolognoff &&
{
echo "* tag 'c3':" &&
- echo " commit 3" &&
- echo
+ echo " commit 3"
} >msg.log
}
@@ -71,7 +70,7 @@ verify_merge () {
git diff --exit-code &&
if test -n "$3"
then
- git show -s --pretty=format:%s HEAD >msg.act &&
+ git show -s --pretty=tformat:%s HEAD >msg.act &&
test_cmp "$3" msg.act
fi
}
@@ -620,10 +619,10 @@ test_expect_success 'merge early part of c2' '
git tag c6 &&
git branch -f c5-branch c5 &&
git merge c5-branch~1 &&
- git show -s --pretty=format:%s HEAD >actual.branch &&
+ git show -s --pretty=tformat:%s HEAD >actual.branch &&
git reset --keep HEAD^ &&
git merge c5~1 &&
- git show -s --pretty=format:%s HEAD >actual.tag &&
+ git show -s --pretty=tformat:%s HEAD >actual.tag &&
test_cmp expected.branch actual.branch &&
test_cmp expected.tag actual.tag
'
diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh
index 830a4c3e9d..f768c900ab 100755
--- a/t/t7601-merge-pull-config.sh
+++ b/t/t7601-merge-pull-config.sh
@@ -38,6 +38,27 @@ test_expect_success 'merge c1 with c2' '
test -f c2.c
'
+test_expect_success 'fast-forward pull succeeds with "true" in pull.ff' '
+ git reset --hard c0 &&
+ test_config pull.ff true &&
+ git pull . c1 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
+'
+
+test_expect_success 'fast-forward pull creates merge with "false" in pull.ff' '
+ git reset --hard c0 &&
+ test_config pull.ff false &&
+ git pull . c1 &&
+ test "$(git rev-parse HEAD^1)" = "$(git rev-parse c0)" &&
+ test "$(git rev-parse HEAD^2)" = "$(git rev-parse c1)"
+'
+
+test_expect_success 'pull prevents non-fast-forward with "only" in pull.ff' '
+ git reset --hard c1 &&
+ test_config pull.ff only &&
+ test_must_fail git pull . c3
+'
+
test_expect_success 'merge c1 with c2 (ours in pull.twohead)' '
git reset --hard c1 &&
git config pull.twohead ours &&
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 05d9db090d..7eeb207b32 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -14,512 +14,527 @@ Testing basic merge tool invocation'
# running mergetool
test_expect_success 'setup' '
- git config rerere.enabled true &&
- echo master >file1 &&
- echo master spaced >"spaced name" &&
- echo master file11 >file11 &&
- echo master file12 >file12 &&
- echo master file13 >file13 &&
- echo master file14 >file14 &&
- mkdir subdir &&
- echo master sub >subdir/file3 &&
- test_create_repo submod &&
- (
- cd submod &&
- : >foo &&
- git add foo &&
- git commit -m "Add foo"
- ) &&
- git submodule add git://example.com/submod submod &&
- git add file1 "spaced name" file1[1-4] subdir/file3 .gitmodules submod &&
- git commit -m "add initial versions" &&
-
- git checkout -b branch1 master &&
- git submodule update -N &&
- echo branch1 change >file1 &&
- echo branch1 newfile >file2 &&
- echo branch1 spaced >"spaced name" &&
- echo branch1 both added >both &&
- echo branch1 change file11 >file11 &&
- echo branch1 change file13 >file13 &&
- echo branch1 sub >subdir/file3 &&
- (
- cd submod &&
- echo branch1 submodule >bar &&
- git add bar &&
- git commit -m "Add bar on branch1" &&
- git checkout -b submod-branch1
- ) &&
- git add file1 "spaced name" file11 file13 file2 subdir/file3 submod &&
- git add both &&
- git rm file12 &&
- git commit -m "branch1 changes" &&
-
- git checkout -b stash1 master &&
- echo stash1 change file11 >file11 &&
- git add file11 &&
- git commit -m "stash1 changes" &&
-
- git checkout -b stash2 master &&
- echo stash2 change file11 >file11 &&
- git add file11 &&
- git commit -m "stash2 changes" &&
-
- git checkout master &&
- git submodule update -N &&
- echo master updated >file1 &&
- echo master new >file2 &&
- echo master updated spaced >"spaced name" &&
- echo master both added >both &&
- echo master updated file12 >file12 &&
- echo master updated file14 >file14 &&
- echo master new sub >subdir/file3 &&
- (
- cd submod &&
- echo master submodule >bar &&
- git add bar &&
- git commit -m "Add bar on master" &&
- git checkout -b submod-master
- ) &&
- git add file1 "spaced name" file12 file14 file2 subdir/file3 submod &&
- git add both &&
- git rm file11 &&
- git commit -m "master updates" &&
-
- git config merge.tool mytool &&
- git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" &&
- git config mergetool.mytool.trustExitCode true &&
- git config mergetool.mybase.cmd "cat \"\$BASE\" >\"\$MERGED\"" &&
- git config mergetool.mybase.trustExitCode true
+ test_config rerere.enabled true &&
+ echo master >file1 &&
+ echo master spaced >"spaced name" &&
+ echo master file11 >file11 &&
+ echo master file12 >file12 &&
+ echo master file13 >file13 &&
+ echo master file14 >file14 &&
+ mkdir subdir &&
+ echo master sub >subdir/file3 &&
+ test_create_repo submod &&
+ (
+ cd submod &&
+ : >foo &&
+ git add foo &&
+ git commit -m "Add foo"
+ ) &&
+ git submodule add git://example.com/submod submod &&
+ git add file1 "spaced name" file1[1-4] subdir/file3 .gitmodules submod &&
+ git commit -m "add initial versions" &&
+
+ git checkout -b branch1 master &&
+ git submodule update -N &&
+ echo branch1 change >file1 &&
+ echo branch1 newfile >file2 &&
+ echo branch1 spaced >"spaced name" &&
+ echo branch1 both added >both &&
+ echo branch1 change file11 >file11 &&
+ echo branch1 change file13 >file13 &&
+ echo branch1 sub >subdir/file3 &&
+ (
+ cd submod &&
+ echo branch1 submodule >bar &&
+ git add bar &&
+ git commit -m "Add bar on branch1" &&
+ git checkout -b submod-branch1
+ ) &&
+ git add file1 "spaced name" file11 file13 file2 subdir/file3 submod &&
+ git add both &&
+ git rm file12 &&
+ git commit -m "branch1 changes" &&
+
+ git checkout -b stash1 master &&
+ echo stash1 change file11 >file11 &&
+ git add file11 &&
+ git commit -m "stash1 changes" &&
+
+ git checkout -b stash2 master &&
+ echo stash2 change file11 >file11 &&
+ git add file11 &&
+ git commit -m "stash2 changes" &&
+
+ git checkout master &&
+ git submodule update -N &&
+ echo master updated >file1 &&
+ echo master new >file2 &&
+ echo master updated spaced >"spaced name" &&
+ echo master both added >both &&
+ echo master updated file12 >file12 &&
+ echo master updated file14 >file14 &&
+ echo master new sub >subdir/file3 &&
+ (
+ cd submod &&
+ echo master submodule >bar &&
+ git add bar &&
+ git commit -m "Add bar on master" &&
+ git checkout -b submod-master
+ ) &&
+ git add file1 "spaced name" file12 file14 file2 subdir/file3 submod &&
+ git add both &&
+ git rm file11 &&
+ git commit -m "master updates" &&
+
+ git config merge.tool mytool &&
+ git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" &&
+ git config mergetool.mytool.trustExitCode true &&
+ git config mergetool.mybase.cmd "cat \"\$BASE\" >\"\$MERGED\"" &&
+ git config mergetool.mybase.trustExitCode true
'
test_expect_success 'custom mergetool' '
- git checkout -b test1 branch1 &&
- git submodule update -N &&
- test_must_fail git merge master >/dev/null 2>&1 &&
- ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool file1 file1 ) &&
- ( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
- ( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
- test "$(cat file1)" = "master updated" &&
- test "$(cat file2)" = "master new" &&
- test "$(cat subdir/file3)" = "master new sub" &&
- test "$(cat submod/bar)" = "branch1 submodule" &&
- git commit -m "branch1 resolved with mergetool"
+ git checkout -b test1 branch1 &&
+ git submodule update -N &&
+ test_must_fail git merge master >/dev/null 2>&1 &&
+ ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool file1 file1 ) &&
+ ( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
+ ( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
+ test "$(cat file1)" = "master updated" &&
+ test "$(cat file2)" = "master new" &&
+ test "$(cat subdir/file3)" = "master new sub" &&
+ test "$(cat submod/bar)" = "branch1 submodule" &&
+ git commit -m "branch1 resolved with mergetool"
'
test_expect_success 'mergetool crlf' '
- git config core.autocrlf true &&
- git checkout -b test2 branch1 &&
- test_must_fail git merge master >/dev/null 2>&1 &&
- ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool "spaced name" >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
- ( yes "r" | git mergetool submod >/dev/null 2>&1 ) &&
- test "$(printf x | cat file1 -)" = "$(printf "master updated\r\nx")" &&
- test "$(printf x | cat file2 -)" = "$(printf "master new\r\nx")" &&
- test "$(printf x | cat subdir/file3 -)" = "$(printf "master new sub\r\nx")" &&
- git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
- git commit -m "branch1 resolved with mergetool - autocrlf" &&
- git config core.autocrlf false &&
- git reset --hard
+ test_config core.autocrlf true &&
+ git checkout -b test2 branch1 &&
+ test_must_fail git merge master >/dev/null 2>&1 &&
+ ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool "spaced name" >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
+ ( yes "r" | git mergetool submod >/dev/null 2>&1 ) &&
+ test "$(printf x | cat file1 -)" = "$(printf "master updated\r\nx")" &&
+ test "$(printf x | cat file2 -)" = "$(printf "master new\r\nx")" &&
+ test "$(printf x | cat subdir/file3 -)" = "$(printf "master new sub\r\nx")" &&
+ git submodule update -N &&
+ test "$(cat submod/bar)" = "master submodule" &&
+ git commit -m "branch1 resolved with mergetool - autocrlf" &&
+ test_config core.autocrlf false &&
+ git reset --hard
'
test_expect_success 'mergetool in subdir' '
- git checkout -b test3 branch1 &&
- git submodule update -N &&
- (
- cd subdir &&
- test_must_fail git merge master >/dev/null 2>&1 &&
- ( yes "" | git mergetool file3 >/dev/null 2>&1 ) &&
- test "$(cat file3)" = "master new sub"
- )
+ git checkout -b test3 branch1 &&
+ git submodule update -N &&
+ (
+ cd subdir &&
+ test_must_fail git merge master >/dev/null 2>&1 &&
+ ( yes "" | git mergetool file3 >/dev/null 2>&1 ) &&
+ test "$(cat file3)" = "master new sub"
+ )
'
test_expect_success 'mergetool on file in parent dir' '
- (
- cd subdir &&
- ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool ../file2 ../spaced\ name >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool ../both >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) &&
- ( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) &&
- test "$(cat ../file1)" = "master updated" &&
- test "$(cat ../file2)" = "master new" &&
- test "$(cat ../submod/bar)" = "branch1 submodule" &&
- git commit -m "branch1 resolved with mergetool - subdir"
- )
+ (
+ cd subdir &&
+ ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool ../file2 ../spaced\ name >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool ../both >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) &&
+ ( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) &&
+ test "$(cat ../file1)" = "master updated" &&
+ test "$(cat ../file2)" = "master new" &&
+ test "$(cat ../submod/bar)" = "branch1 submodule" &&
+ git commit -m "branch1 resolved with mergetool - subdir"
+ )
'
test_expect_success 'mergetool skips autoresolved' '
- git checkout -b test4 branch1 &&
- git submodule update -N &&
- test_must_fail git merge master &&
- test -n "$(git ls-files -u)" &&
- ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
- ( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git reset --hard
+ git checkout -b test4 branch1 &&
+ git submodule update -N &&
+ test_must_fail git merge master &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
+ ( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git reset --hard
'
test_expect_success 'mergetool merges all from subdir' '
- (
- cd subdir &&
- git config rerere.enabled false &&
- test_must_fail git merge master &&
- ( yes "r" | git mergetool ../submod ) &&
- ( yes "d" "d" | git mergetool --no-prompt ) &&
- test "$(cat ../file1)" = "master updated" &&
- test "$(cat ../file2)" = "master new" &&
- test "$(cat file3)" = "master new sub" &&
- ( cd .. && git submodule update -N ) &&
- test "$(cat ../submod/bar)" = "master submodule" &&
- git commit -m "branch2 resolved by mergetool from subdir"
- )
+ (
+ cd subdir &&
+ test_config rerere.enabled false &&
+ test_must_fail git merge master &&
+ ( yes "r" | git mergetool ../submod ) &&
+ ( yes "d" "d" | git mergetool --no-prompt ) &&
+ test "$(cat ../file1)" = "master updated" &&
+ test "$(cat ../file2)" = "master new" &&
+ test "$(cat file3)" = "master new sub" &&
+ ( cd .. && git submodule update -N ) &&
+ test "$(cat ../submod/bar)" = "master submodule" &&
+ git commit -m "branch2 resolved by mergetool from subdir"
+ )
'
test_expect_success 'mergetool skips resolved paths when rerere is active' '
- git config rerere.enabled true &&
- rm -rf .git/rr-cache &&
- git checkout -b test5 branch1
- git submodule update -N &&
- test_must_fail git merge master >/dev/null 2>&1 &&
- ( yes "l" | git mergetool --no-prompt submod >/dev/null 2>&1 ) &&
- ( yes "d" "d" | git mergetool --no-prompt >/dev/null 2>&1 ) &&
- git submodule update -N &&
- output="$(yes "n" | git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git reset --hard
+ test_config rerere.enabled true &&
+ rm -rf .git/rr-cache &&
+ git checkout -b test5 branch1 &&
+ git submodule update -N &&
+ test_must_fail git merge master >/dev/null 2>&1 &&
+ ( yes "l" | git mergetool --no-prompt submod >/dev/null 2>&1 ) &&
+ ( yes "d" "d" | git mergetool --no-prompt >/dev/null 2>&1 ) &&
+ git submodule update -N &&
+ output="$(yes "n" | git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git reset --hard
'
test_expect_success 'conflicted stash sets up rerere' '
- git config rerere.enabled true &&
- git checkout stash1 &&
- echo "Conflicting stash content" >file11 &&
- git stash &&
-
- git checkout --detach stash2 &&
- test_must_fail git stash apply &&
-
- test -n "$(git ls-files -u)" &&
- conflicts="$(git rerere remaining)" &&
- test "$conflicts" = "file11" &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" != "No files need merging" &&
-
- git commit -am "save the stash resolution" &&
-
- git reset --hard stash2 &&
- test_must_fail git stash apply &&
-
- test -n "$(git ls-files -u)" &&
- conflicts="$(git rerere remaining)" &&
- test -z "$conflicts" &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging"
+ test_config rerere.enabled true &&
+ git checkout stash1 &&
+ echo "Conflicting stash content" >file11 &&
+ git stash &&
+
+ git checkout --detach stash2 &&
+ test_must_fail git stash apply &&
+
+ test -n "$(git ls-files -u)" &&
+ conflicts="$(git rerere remaining)" &&
+ test "$conflicts" = "file11" &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" != "No files need merging" &&
+
+ git commit -am "save the stash resolution" &&
+
+ git reset --hard stash2 &&
+ test_must_fail git stash apply &&
+
+ test -n "$(git ls-files -u)" &&
+ conflicts="$(git rerere remaining)" &&
+ test -z "$conflicts" &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging"
'
test_expect_success 'mergetool takes partial path' '
- git reset --hard
- git config rerere.enabled false &&
- git checkout -b test12 branch1 &&
- git submodule update -N &&
- test_must_fail git merge master &&
-
- #should not need these lines
- #( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
- #( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
- #( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
- #( yes "" | git mergetool file1 file2 >/dev/null 2>&1 ) &&
-
- ( yes "" | git mergetool subdir ) &&
-
- test "$(cat subdir/file3)" = "master new sub" &&
- git reset --hard
+ git reset --hard &&
+ test_config rerere.enabled false &&
+ git checkout -b test12 branch1 &&
+ git submodule update -N &&
+ test_must_fail git merge master &&
+
+ ( yes "" | git mergetool subdir ) &&
+
+ test "$(cat subdir/file3)" = "master new sub" &&
+ git reset --hard
'
test_expect_success 'deleted vs modified submodule' '
- git checkout -b test6 branch1 &&
- git submodule update -N &&
- mv submod submod-movedaside &&
- git rm --cached submod &&
- git commit -m "Submodule deleted from branch" &&
- git checkout -b test6.a test6 &&
- test_must_fail git merge master &&
- test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
- ( yes "r" | git mergetool submod ) &&
- rmdir submod && mv submod-movedaside submod &&
- test "$(cat submod/bar)" = "branch1 submodule" &&
- git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git commit -m "Merge resolved by keeping module" &&
-
- mv submod submod-movedaside &&
- git checkout -b test6.b test6 &&
- git submodule update -N &&
- test_must_fail git merge master &&
- test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
- ( yes "l" | git mergetool submod ) &&
- test ! -e submod &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git commit -m "Merge resolved by deleting module" &&
-
- mv submod-movedaside submod &&
- git checkout -b test6.c master &&
- git submodule update -N &&
- test_must_fail git merge test6 &&
- test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
- ( yes "r" | git mergetool submod ) &&
- test ! -e submod &&
- test -d submod.orig &&
- git submodule update -N &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git commit -m "Merge resolved by deleting module" &&
- mv submod.orig submod &&
-
- git checkout -b test6.d master &&
- git submodule update -N &&
- test_must_fail git merge test6 &&
- test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
- ( yes "l" | git mergetool submod ) &&
- test "$(cat submod/bar)" = "master submodule" &&
- git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git commit -m "Merge resolved by keeping module" &&
- git reset --hard HEAD
+ git checkout -b test6 branch1 &&
+ git submodule update -N &&
+ mv submod submod-movedaside &&
+ git rm --cached submod &&
+ git commit -m "Submodule deleted from branch" &&
+ git checkout -b test6.a test6 &&
+ test_must_fail git merge master &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+ ( yes "r" | git mergetool submod ) &&
+ rmdir submod && mv submod-movedaside submod &&
+ test "$(cat submod/bar)" = "branch1 submodule" &&
+ git submodule update -N &&
+ test "$(cat submod/bar)" = "master submodule" &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git commit -m "Merge resolved by keeping module" &&
+
+ mv submod submod-movedaside &&
+ git checkout -b test6.b test6 &&
+ git submodule update -N &&
+ test_must_fail git merge master &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+ ( yes "l" | git mergetool submod ) &&
+ test ! -e submod &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git commit -m "Merge resolved by deleting module" &&
+
+ mv submod-movedaside submod &&
+ git checkout -b test6.c master &&
+ git submodule update -N &&
+ test_must_fail git merge test6 &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+ ( yes "r" | git mergetool submod ) &&
+ test ! -e submod &&
+ test -d submod.orig &&
+ git submodule update -N &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git commit -m "Merge resolved by deleting module" &&
+ mv submod.orig submod &&
+
+ git checkout -b test6.d master &&
+ git submodule update -N &&
+ test_must_fail git merge test6 &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+ ( yes "l" | git mergetool submod ) &&
+ test "$(cat submod/bar)" = "master submodule" &&
+ git submodule update -N &&
+ test "$(cat submod/bar)" = "master submodule" &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git commit -m "Merge resolved by keeping module" &&
+ git reset --hard HEAD
'
test_expect_success 'file vs modified submodule' '
- git checkout -b test7 branch1 &&
- git submodule update -N &&
- mv submod submod-movedaside &&
- git rm --cached submod &&
- echo not a submodule >submod &&
- git add submod &&
- git commit -m "Submodule path becomes file" &&
- git checkout -b test7.a branch1 &&
- test_must_fail git merge master &&
- test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
- ( yes "r" | git mergetool submod ) &&
- rmdir submod && mv submod-movedaside submod &&
- test "$(cat submod/bar)" = "branch1 submodule" &&
- git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git commit -m "Merge resolved by keeping module" &&
-
- mv submod submod-movedaside &&
- git checkout -b test7.b test7 &&
- test_must_fail git merge master &&
- test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
- ( yes "l" | git mergetool submod ) &&
- git submodule update -N &&
- test "$(cat submod)" = "not a submodule" &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git commit -m "Merge resolved by keeping file" &&
-
- git checkout -b test7.c master &&
- rmdir submod && mv submod-movedaside submod &&
- test ! -e submod.orig &&
- git submodule update -N &&
- test_must_fail git merge test7 &&
- test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
- ( yes "r" | git mergetool submod ) &&
- test -d submod.orig &&
- git submodule update -N &&
- test "$(cat submod)" = "not a submodule" &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git commit -m "Merge resolved by keeping file" &&
-
- git checkout -b test7.d master &&
- rmdir submod && mv submod.orig submod &&
- git submodule update -N &&
- test_must_fail git merge test7 &&
- test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
- ( yes "" | git mergetool both>/dev/null 2>&1 ) &&
- ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
- ( yes "l" | git mergetool submod ) &&
- test "$(cat submod/bar)" = "master submodule" &&
- git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
- output="$(git mergetool --no-prompt)" &&
- test "$output" = "No files need merging" &&
- git commit -m "Merge resolved by keeping module"
+ git checkout -b test7 branch1 &&
+ git submodule update -N &&
+ mv submod submod-movedaside &&
+ git rm --cached submod &&
+ echo not a submodule >submod &&
+ git add submod &&
+ git commit -m "Submodule path becomes file" &&
+ git checkout -b test7.a branch1 &&
+ test_must_fail git merge master &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+ ( yes "r" | git mergetool submod ) &&
+ rmdir submod && mv submod-movedaside submod &&
+ test "$(cat submod/bar)" = "branch1 submodule" &&
+ git submodule update -N &&
+ test "$(cat submod/bar)" = "master submodule" &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git commit -m "Merge resolved by keeping module" &&
+
+ mv submod submod-movedaside &&
+ git checkout -b test7.b test7 &&
+ test_must_fail git merge master &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+ ( yes "l" | git mergetool submod ) &&
+ git submodule update -N &&
+ test "$(cat submod)" = "not a submodule" &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git commit -m "Merge resolved by keeping file" &&
+
+ git checkout -b test7.c master &&
+ rmdir submod && mv submod-movedaside submod &&
+ test ! -e submod.orig &&
+ git submodule update -N &&
+ test_must_fail git merge test7 &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool both >/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+ ( yes "r" | git mergetool submod ) &&
+ test -d submod.orig &&
+ git submodule update -N &&
+ test "$(cat submod)" = "not a submodule" &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git commit -m "Merge resolved by keeping file" &&
+
+ git checkout -b test7.d master &&
+ rmdir submod && mv submod.orig submod &&
+ git submodule update -N &&
+ test_must_fail git merge test7 &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
+ ( yes "" | git mergetool both>/dev/null 2>&1 ) &&
+ ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
+ ( yes "l" | git mergetool submod ) &&
+ test "$(cat submod/bar)" = "master submodule" &&
+ git submodule update -N &&
+ test "$(cat submod/bar)" = "master submodule" &&
+ output="$(git mergetool --no-prompt)" &&
+ test "$output" = "No files need merging" &&
+ git commit -m "Merge resolved by keeping module"
'
test_expect_success 'submodule in subdirectory' '
- git checkout -b test10 branch1 &&
- git submodule update -N &&
- (
- cd subdir &&
- test_create_repo subdir_module &&
+ git checkout -b test10 branch1 &&
+ git submodule update -N &&
+ (
+ cd subdir &&
+ test_create_repo subdir_module &&
+ (
+ cd subdir_module &&
+ : >file15 &&
+ git add file15 &&
+ git commit -m "add initial versions"
+ )
+ ) &&
+ git submodule add git://example.com/subsubmodule subdir/subdir_module &&
+ git add subdir/subdir_module &&
+ git commit -m "add submodule in subdirectory" &&
+
+ git checkout -b test10.a test10 &&
+ git submodule update -N &&
(
- cd subdir_module &&
- : >file15 &&
- git add file15 &&
- git commit -m "add initial versions"
- )
- ) &&
- git submodule add git://example.com/subsubmodule subdir/subdir_module &&
- git add subdir/subdir_module &&
- git commit -m "add submodule in subdirectory" &&
-
- git checkout -b test10.a test10 &&
- git submodule update -N &&
- (
- cd subdir/subdir_module &&
- git checkout -b super10.a &&
- echo test10.a >file15 &&
- git add file15 &&
- git commit -m "on branch 10.a"
- ) &&
- git add subdir/subdir_module &&
- git commit -m "change submodule in subdirectory on test10.a" &&
-
- git checkout -b test10.b test10 &&
- git submodule update -N &&
- (
cd subdir/subdir_module &&
- git checkout -b super10.b &&
- echo test10.b >file15 &&
- git add file15 &&
- git commit -m "on branch 10.b"
- ) &&
- git add subdir/subdir_module &&
- git commit -m "change submodule in subdirectory on test10.b" &&
-
- test_must_fail git merge test10.a >/dev/null 2>&1 &&
- (
- cd subdir &&
- ( yes "l" | git mergetool subdir_module )
- ) &&
- test "$(cat subdir/subdir_module/file15)" = "test10.b" &&
- git submodule update -N &&
- test "$(cat subdir/subdir_module/file15)" = "test10.b" &&
- git reset --hard &&
- git submodule update -N &&
-
- test_must_fail git merge test10.a >/dev/null 2>&1 &&
- ( yes "r" | git mergetool subdir/subdir_module ) &&
- test "$(cat subdir/subdir_module/file15)" = "test10.b" &&
- git submodule update -N &&
- test "$(cat subdir/subdir_module/file15)" = "test10.a" &&
- git commit -m "branch1 resolved with mergetool" &&
- rm -rf subdir/subdir_module
+ git checkout -b super10.a &&
+ echo test10.a >file15 &&
+ git add file15 &&
+ git commit -m "on branch 10.a"
+ ) &&
+ git add subdir/subdir_module &&
+ git commit -m "change submodule in subdirectory on test10.a" &&
+
+ git checkout -b test10.b test10 &&
+ git submodule update -N &&
+ (
+ cd subdir/subdir_module &&
+ git checkout -b super10.b &&
+ echo test10.b >file15 &&
+ git add file15 &&
+ git commit -m "on branch 10.b"
+ ) &&
+ git add subdir/subdir_module &&
+ git commit -m "change submodule in subdirectory on test10.b" &&
+
+ test_must_fail git merge test10.a >/dev/null 2>&1 &&
+ (
+ cd subdir &&
+ ( yes "l" | git mergetool subdir_module )
+ ) &&
+ test "$(cat subdir/subdir_module/file15)" = "test10.b" &&
+ git submodule update -N &&
+ test "$(cat subdir/subdir_module/file15)" = "test10.b" &&
+ git reset --hard &&
+ git submodule update -N &&
+
+ test_must_fail git merge test10.a >/dev/null 2>&1 &&
+ ( yes "r" | git mergetool subdir/subdir_module ) &&
+ test "$(cat subdir/subdir_module/file15)" = "test10.b" &&
+ git submodule update -N &&
+ test "$(cat subdir/subdir_module/file15)" = "test10.a" &&
+ git commit -m "branch1 resolved with mergetool" &&
+ rm -rf subdir/subdir_module
'
test_expect_success 'directory vs modified submodule' '
- git checkout -b test11 branch1 &&
- mv submod submod-movedaside &&
- git rm --cached submod &&
- mkdir submod &&
- echo not a submodule >submod/file16 &&
- git add submod/file16 &&
- git commit -m "Submodule path becomes directory" &&
-
- test_must_fail git merge master &&
- test -n "$(git ls-files -u)" &&
- ( yes "l" | git mergetool submod ) &&
- test "$(cat submod/file16)" = "not a submodule" &&
- rm -rf submod.orig &&
-
- git reset --hard >/dev/null 2>&1 &&
- test_must_fail git merge master &&
- test -n "$(git ls-files -u)" &&
- test ! -e submod.orig &&
- ( yes "r" | git mergetool submod ) &&
- test -d submod.orig &&
- test "$(cat submod.orig/file16)" = "not a submodule" &&
- rm -r submod.orig &&
- mv submod-movedaside/.git submod &&
- ( cd submod && git clean -f && git reset --hard ) &&
- git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
- git reset --hard >/dev/null 2>&1 && rm -rf submod-movedaside &&
-
- git checkout -b test11.c master &&
- git submodule update -N &&
- test_must_fail git merge test11 &&
- test -n "$(git ls-files -u)" &&
- ( yes "l" | git mergetool submod ) &&
- git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
-
- git reset --hard >/dev/null 2>&1 &&
- git submodule update -N &&
- test_must_fail git merge test11 &&
- test -n "$(git ls-files -u)" &&
- test ! -e submod.orig &&
- ( yes "r" | git mergetool submod ) &&
- test "$(cat submod/file16)" = "not a submodule" &&
-
- git reset --hard master >/dev/null 2>&1 &&
- ( cd submod && git clean -f && git reset --hard ) &&
- git submodule update -N
+ git checkout -b test11 branch1 &&
+ mv submod submod-movedaside &&
+ git rm --cached submod &&
+ mkdir submod &&
+ echo not a submodule >submod/file16 &&
+ git add submod/file16 &&
+ git commit -m "Submodule path becomes directory" &&
+
+ test_must_fail git merge master &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "l" | git mergetool submod ) &&
+ test "$(cat submod/file16)" = "not a submodule" &&
+ rm -rf submod.orig &&
+
+ git reset --hard >/dev/null 2>&1 &&
+ test_must_fail git merge master &&
+ test -n "$(git ls-files -u)" &&
+ test ! -e submod.orig &&
+ ( yes "r" | git mergetool submod ) &&
+ test -d submod.orig &&
+ test "$(cat submod.orig/file16)" = "not a submodule" &&
+ rm -r submod.orig &&
+ mv submod-movedaside/.git submod &&
+ ( cd submod && git clean -f && git reset --hard ) &&
+ git submodule update -N &&
+ test "$(cat submod/bar)" = "master submodule" &&
+ git reset --hard >/dev/null 2>&1 && rm -rf submod-movedaside &&
+
+ git checkout -b test11.c master &&
+ git submodule update -N &&
+ test_must_fail git merge test11 &&
+ test -n "$(git ls-files -u)" &&
+ ( yes "l" | git mergetool submod ) &&
+ git submodule update -N &&
+ test "$(cat submod/bar)" = "master submodule" &&
+
+ git reset --hard >/dev/null 2>&1 &&
+ git submodule update -N &&
+ test_must_fail git merge test11 &&
+ test -n "$(git ls-files -u)" &&
+ test ! -e submod.orig &&
+ ( yes "r" | git mergetool submod ) &&
+ test "$(cat submod/file16)" = "not a submodule" &&
+
+ git reset --hard master >/dev/null 2>&1 &&
+ ( cd submod && git clean -f && git reset --hard ) &&
+ git submodule update -N
'
test_expect_success 'file with no base' '
- git checkout -b test13 branch1 &&
- test_must_fail git merge master &&
- git mergetool --no-prompt --tool mybase -- both &&
- >expected &&
- test_cmp both expected &&
- git reset --hard master >/dev/null 2>&1
+ git checkout -b test13 branch1 &&
+ test_must_fail git merge master &&
+ git mergetool --no-prompt --tool mybase -- both &&
+ >expected &&
+ test_cmp both expected &&
+ git reset --hard master >/dev/null 2>&1
'
test_expect_success 'custom commands override built-ins' '
- git checkout -b test14 branch1 &&
- git config mergetool.defaults.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" &&
- git config mergetool.defaults.trustExitCode true &&
- test_must_fail git merge master &&
- git mergetool --no-prompt --tool defaults -- both &&
- echo master both added >expected &&
- test_cmp both expected &&
- git config --unset mergetool.defaults.cmd &&
- git config --unset mergetool.defaults.trustExitCode &&
- git reset --hard master >/dev/null 2>&1
+ git checkout -b test14 branch1 &&
+ test_config mergetool.defaults.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" &&
+ test_config mergetool.defaults.trustExitCode true &&
+ test_must_fail git merge master &&
+ git mergetool --no-prompt --tool defaults -- both &&
+ echo master both added >expected &&
+ test_cmp both expected &&
+ git reset --hard master >/dev/null 2>&1
+'
+
+test_expect_success 'filenames seen by tools start with ./' '
+ git checkout -b test15 branch1 &&
+ test_config mergetool.writeToTemp false &&
+ test_config mergetool.myecho.cmd "echo \"\$LOCAL\"" &&
+ test_config mergetool.myecho.trustExitCode true &&
+ test_must_fail git merge master &&
+ git mergetool --no-prompt --tool myecho -- both >actual &&
+ grep ^\./both_LOCAL_ actual >/dev/null &&
+ git reset --hard master >/dev/null 2>&1
+'
+
+test_expect_success 'temporary filenames are used with mergetool.writeToTemp' '
+ git checkout -b test16 branch1 &&
+ test_config mergetool.writeToTemp true &&
+ test_config mergetool.myecho.cmd "echo \"\$LOCAL\"" &&
+ test_config mergetool.myecho.trustExitCode true &&
+ test_must_fail git merge master &&
+ git mergetool --no-prompt --tool myecho -- both >actual &&
+ test_must_fail grep ^\./both_LOCAL_ actual >/dev/null &&
+ grep /both_LOCAL_ actual >/dev/null &&
+ git reset --hard master >/dev/null 2>&1
'
test_done
diff --git a/t/t7613-merge-submodule.sh b/t/t7613-merge-submodule.sh
new file mode 100755
index 0000000000..d1e9fcc781
--- /dev/null
+++ b/t/t7613-merge-submodule.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+test_description='merge can handle submodules'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-submodule-update.sh
+
+# merges without conflicts
+test_submodule_switch "git merge"
+
+test_submodule_switch "git merge --ff"
+
+test_submodule_switch "git merge --ff-only"
+
+KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1
+KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1
+test_submodule_switch "git merge --no-ff"
+
+test_done
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index d954b846a1..021c5479bd 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -17,7 +17,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
# The second pack will contain the excluded object
packsha1=$(git rev-list --objects --all | grep file2 |
git pack-objects pack) &&
- touch -r pack-$packsha1.pack pack-$packsha1.keep &&
+ >pack-$packsha1.keep &&
objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |
sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") &&
mv pack-* .git/objects/pack/ &&
@@ -35,6 +35,38 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
test -z "$found_duplicate_object"
'
+test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '
+ # build on $objsha1, $packsha1, and .keep state from previous
+ git repack -Adbl &&
+ test_when_finished "found_duplicate_object=" &&
+ for p in .git/objects/pack/*.idx; do
+ idx=$(basename $p)
+ test "pack-$packsha1.idx" = "$idx" && continue
+ if git verify-pack -v $p | egrep "^$objsha1"; then
+ found_duplicate_object=1
+ echo "DUPLICATE OBJECT FOUND"
+ break
+ fi
+ done &&
+ test "$found_duplicate_object" = 1
+'
+
+test_expect_success 'writing bitmaps via config can duplicate .keep objects' '
+ # build on $objsha1, $packsha1, and .keep state from previous
+ git -c repack.writebitmaps=true repack -Adl &&
+ test_when_finished "found_duplicate_object=" &&
+ for p in .git/objects/pack/*.idx; do
+ idx=$(basename $p)
+ test "pack-$packsha1.idx" = "$idx" && continue
+ if git verify-pack -v $p | egrep "^$objsha1"; then
+ found_duplicate_object=1
+ echo "DUPLICATE OBJECT FOUND"
+ break
+ fi
+ done &&
+ test "$found_duplicate_object" = 1
+'
+
test_expect_success 'loose objects in alternate ODB are not repacked' '
mkdir alt_objects &&
echo `pwd`/alt_objects > .git/objects/info/alternates &&
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b8d4cdea8c..aad8a9c64d 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -109,4 +109,17 @@ test_expect_success 'do not bother loosening old objects' '
test_must_fail git cat-file -p $obj2
'
+test_expect_success 'keep packed objects found only in index' '
+ echo my-unique-content >file &&
+ git add file &&
+ git commit -m "make it reachable" &&
+ git gc &&
+ git reset HEAD^ &&
+ git reflog expire --expire=now --all &&
+ git add file &&
+ test-chmtime =-86400 .git/objects/pack/* &&
+ git gc --prune=1.hour.ago &&
+ git cat-file blob :file
+'
+
test_done
diff --git a/t/t7702-repack-cyclic-alternate.sh b/t/t7702-repack-cyclic-alternate.sh
new file mode 100755
index 0000000000..93b74867ac
--- /dev/null
+++ b/t/t7702-repack-cyclic-alternate.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Ephrim Khong
+#
+
+test_description='repack involving cyclic alternate'
+. ./test-lib.sh
+
+test_expect_success setup '
+ GIT_OBJECT_DIRECTORY=.git//../.git/objects &&
+ export GIT_OBJECT_DIRECTORY &&
+ touch a &&
+ git add a &&
+ git commit -m 1 &&
+ git repack -adl &&
+ echo "$(pwd)"/.git/objects/../objects >.git/objects/info/alternates
+'
+
+test_expect_success 're-packing repository with itsself as alternate' '
+ git repack -adl &&
+ git fsck
+'
+
+test_done
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 2418528487..ea35a0241c 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -58,7 +58,7 @@ test_expect_success PERL 'custom tool commands override built-ins' '
test_expect_success PERL 'difftool ignores bad --tool values' '
: >expect &&
- test_expect_code 1 \
+ test_must_fail \
git difftool --no-prompt --tool=bad-tool branch >actual &&
test_cmp expect actual
'
@@ -76,6 +76,54 @@ test_expect_success PERL 'difftool forwards arguments to diff' '
rm for-diff
'
+test_expect_success PERL 'difftool ignores exit code' '
+ test_config difftool.error.cmd false &&
+ git difftool -y -t error branch
+'
+
+test_expect_success PERL 'difftool forwards exit code with --trust-exit-code' '
+ test_config difftool.error.cmd false &&
+ test_must_fail git difftool -y --trust-exit-code -t error branch
+'
+
+test_expect_success PERL 'difftool forwards exit code with --trust-exit-code for built-ins' '
+ test_config difftool.vimdiff.path false &&
+ test_must_fail git difftool -y --trust-exit-code -t vimdiff branch
+'
+
+test_expect_success PERL 'difftool honors difftool.trustExitCode = true' '
+ test_config difftool.error.cmd false &&
+ test_config difftool.trustExitCode true &&
+ test_must_fail git difftool -y -t error branch
+'
+
+test_expect_success PERL 'difftool honors difftool.trustExitCode = false' '
+ test_config difftool.error.cmd false &&
+ test_config difftool.trustExitCode false &&
+ git difftool -y -t error branch
+'
+
+test_expect_success PERL 'difftool ignores exit code with --no-trust-exit-code' '
+ test_config difftool.error.cmd false &&
+ test_config difftool.trustExitCode true &&
+ git difftool -y --no-trust-exit-code -t error branch
+'
+
+test_expect_success PERL 'difftool stops on error with --trust-exit-code' '
+ test_when_finished "rm -f for-diff .git/fail-right-file" &&
+ test_when_finished "git reset -- for-diff" &&
+ write_script .git/fail-right-file <<-\EOF &&
+ echo "$2"
+ exit 1
+ EOF
+ >for-diff &&
+ git add for-diff &&
+ echo file >expect &&
+ test_must_fail git difftool -y --trust-exit-code \
+ --extcmd .git/fail-right-file branch >actual &&
+ test_cmp expect actual
+'
+
test_expect_success PERL 'difftool honors --gui' '
difftool_test_setup &&
test_config merge.tool bogus-tool &&
@@ -301,6 +349,14 @@ test_expect_success PERL 'say no to the second file' '
! grep br2 output
'
+test_expect_success PERL 'ending prompt input with EOF' '
+ git difftool -x cat branch </dev/null >output &&
+ ! grep master output &&
+ ! grep branch output &&
+ ! grep m2 output &&
+ ! grep br2 output
+'
+
test_expect_success PERL 'difftool --tool-help' '
git difftool --tool-help >output &&
grep tool output
@@ -434,4 +490,18 @@ test_expect_success PERL 'difftool --no-symlinks detects conflict ' '
)
'
+test_expect_success PERL 'difftool properly honors gitlink and core.worktree' '
+ git submodule add ./. submod/ule &&
+ (
+ cd submod/ule &&
+ test_config diff.tool checktrees &&
+ test_config difftool.checktrees.cmd '\''
+ test -d "$LOCAL" && test -d "$REMOTE" && echo good
+ '\'' &&
+ echo good >expect &&
+ git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index f698001c99..028ffe4a05 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -105,7 +105,7 @@ do
test_expect_success "grep -w $L (w)" '
: >expected &&
- test_must_fail git grep -n -w -e "^w" >actual &&
+ test_must_fail git grep -n -w -e "^w" $H >actual &&
test_cmp expected actual
'
@@ -240,92 +240,104 @@ do
test_cmp expected actual
'
test_expect_success "grep $L with grep.extendedRegexp=false" '
- echo "ab:a+bc" >expected &&
- git -c grep.extendedRegexp=false grep "a+b*c" ab >actual &&
+ echo "${HC}ab:a+bc" >expected &&
+ git -c grep.extendedRegexp=false grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.extendedRegexp=true" '
- echo "ab:abc" >expected &&
- git -c grep.extendedRegexp=true grep "a+b*c" ab >actual &&
+ echo "${HC}ab:abc" >expected &&
+ git -c grep.extendedRegexp=true grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.patterntype=basic" '
- echo "ab:a+bc" >expected &&
- git -c grep.patterntype=basic grep "a+b*c" ab >actual &&
+ echo "${HC}ab:a+bc" >expected &&
+ git -c grep.patterntype=basic grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.patterntype=extended" '
- echo "ab:abc" >expected &&
- git -c grep.patterntype=extended grep "a+b*c" ab >actual &&
+ echo "${HC}ab:abc" >expected &&
+ git -c grep.patterntype=extended grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.patterntype=fixed" '
- echo "ab:a+b*c" >expected &&
- git -c grep.patterntype=fixed grep "a+b*c" ab >actual &&
+ echo "${HC}ab:a+b*c" >expected &&
+ git -c grep.patterntype=fixed grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success LIBPCRE "grep $L with grep.patterntype=perl" '
- echo "ab:a+b*c" >expected &&
- git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" ab >actual &&
+ echo "${HC}ab:a+b*c" >expected &&
+ git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.patternType=default and grep.extendedRegexp=true" '
- echo "ab:abc" >expected &&
+ echo "${HC}ab:abc" >expected &&
git \
-c grep.patternType=default \
-c grep.extendedRegexp=true \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
test_expect_success "grep $L with grep.extendedRegexp=true and grep.patternType=default" '
- echo "ab:abc" >expected &&
+ echo "${HC}ab:abc" >expected &&
git \
-c grep.extendedRegexp=true \
-c grep.patternType=default \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
- test_expect_success 'grep $L with grep.patternType=extended and grep.extendedRegexp=false' '
- echo "ab:abc" >expected &&
+ test_expect_success "grep $L with grep.patternType=extended and grep.extendedRegexp=false" '
+ echo "${HC}ab:abc" >expected &&
git \
-c grep.patternType=extended \
-c grep.extendedRegexp=false \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
- test_expect_success 'grep $L with grep.patternType=basic and grep.extendedRegexp=true' '
- echo "ab:a+bc" >expected &&
+ test_expect_success "grep $L with grep.patternType=basic and grep.extendedRegexp=true" '
+ echo "${HC}ab:a+bc" >expected &&
git \
-c grep.patternType=basic \
-c grep.extendedRegexp=true \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
- test_expect_success 'grep $L with grep.extendedRegexp=false and grep.patternType=extended' '
- echo "ab:abc" >expected &&
+ test_expect_success "grep $L with grep.extendedRegexp=false and grep.patternType=extended" '
+ echo "${HC}ab:abc" >expected &&
git \
-c grep.extendedRegexp=false \
-c grep.patternType=extended \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
test_cmp expected actual
'
- test_expect_success 'grep $L with grep.extendedRegexp=true and grep.patternType=basic' '
- echo "ab:a+bc" >expected &&
+ test_expect_success "grep $L with grep.extendedRegexp=true and grep.patternType=basic" '
+ echo "${HC}ab:a+bc" >expected &&
git \
-c grep.extendedRegexp=true \
-c grep.patternType=basic \
- grep "a+b*c" ab >actual &&
+ grep "a+b*c" $H ab >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "grep --count $L" '
+ echo ${HC}ab:3 >expected &&
+ git grep --count -e b $H -- ab >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "grep --count -h $L" '
+ echo 3 >expected &&
+ git grep --count -h -e b $H -- ab >actual &&
test_cmp expected actual
'
done
@@ -1084,11 +1096,6 @@ test_expect_success 'grep -E pattern with grep.patternType=fixed' '
test_cmp expected actual
'
-test_config() {
- git config "$1" "$2" &&
- test_when_finished "git config --unset $1"
-}
-
cat >expected <<EOF
hello.c<RED>:<RESET>int main(int argc, const char **argv)
hello.c<RED>-<RESET>{
@@ -1195,4 +1202,98 @@ test_expect_success LIBPCRE 'grep -P "^ "' '
test_cmp expected actual
'
+cat >expected <<EOF
+space-line without leading space1
+space: line <RED>with <RESET>leading space1
+space: line <RED>with <RESET>leading <RED>space2<RESET>
+space: line <RED>with <RESET>leading space3
+space:line without leading <RED>space2<RESET>
+EOF
+
+test_expect_success 'grep --color -e A -e B with context' '
+ test_config color.grep.context normal &&
+ test_config color.grep.filename normal &&
+ test_config color.grep.function normal &&
+ test_config color.grep.linenumber normal &&
+ test_config color.grep.matchContext normal &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+space-line without leading space1
+space- line with leading space1
+space: line <RED>with <RESET>leading <RED>space2<RESET>
+space- line with leading space3
+space-line without leading space2
+EOF
+
+test_expect_success 'grep --color -e A --and -e B with context' '
+ test_config color.grep.context normal &&
+ test_config color.grep.filename normal &&
+ test_config color.grep.function normal &&
+ test_config color.grep.linenumber normal &&
+ test_config color.grep.matchContext normal &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " --and -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+space-line without leading space1
+space: line <RED>with <RESET>leading space1
+space- line with leading space2
+space: line <RED>with <RESET>leading space3
+space-line without leading space2
+EOF
+
+test_expect_success 'grep --color -e A --and --not -e B with context' '
+ test_config color.grep.context normal &&
+ test_config color.grep.filename normal &&
+ test_config color.grep.function normal &&
+ test_config color.grep.linenumber normal &&
+ test_config color.grep.matchContext normal &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " --and --not -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c-#include <stdio.h>
+hello.c=int main(int argc, const char **argv)
+hello.c-{
+hello.c: pr<RED>int<RESET>f("<RED>Hello<RESET> world.\n");
+hello.c- return 0;
+hello.c- /* char ?? */
+hello.c-}
+EOF
+
+test_expect_success 'grep --color -e A --and -e B -p with context' '
+ test_config color.grep.context normal &&
+ test_config color.grep.filename normal &&
+ test_config color.grep.function normal &&
+ test_config color.grep.linenumber normal &&
+ test_config color.grep.matchContext normal &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -p -C3 -e int --and -e Hello --no-index hello.c |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh
index e7cac1db55..2a3469bcbe 100755
--- a/t/t8003-blame-corner-cases.sh
+++ b/t/t8003-blame-corner-cases.sh
@@ -191,4 +191,13 @@ test_expect_success 'indent of line numbers, ten lines' '
test $(grep -c " " actual) = 9
'
+test_expect_success 'blaming files with CRLF newlines' '
+ git config core.autocrlf false &&
+ printf "testcase\r\n" >crlffile &&
+ git add crlffile &&
+ git commit -m testcase &&
+ git -c core.autocrlf=input blame crlffile >actual &&
+ grep "A U Thor" actual
+'
+
test_done
diff --git a/t/t8005-blame-i18n.sh b/t/t8005-blame-i18n.sh
index cb390559f9..847d098c09 100755
--- a/t/t8005-blame-i18n.sh
+++ b/t/t8005-blame-i18n.sh
@@ -33,7 +33,7 @@ author $SJIS_NAME
summary $SJIS_MSG
EOF
-test_expect_success \
+test_expect_success !MINGW \
'blame respects i18n.commitencoding' '
git blame --incremental file | \
egrep "^(author|summary) " > actual &&
@@ -49,7 +49,7 @@ author $EUC_JAPAN_NAME
summary $EUC_JAPAN_MSG
EOF
-test_expect_success \
+test_expect_success !MINGW \
'blame respects i18n.logoutputencoding' '
git config i18n.logoutputencoding eucJP &&
git blame --incremental file | \
@@ -66,7 +66,7 @@ author $UTF8_NAME
summary $UTF8_MSG
EOF
-test_expect_success \
+test_expect_success !MINGW \
'blame respects --encoding=UTF-8' '
git blame --incremental --encoding=UTF-8 file | \
egrep "^(author|summary) " > actual &&
@@ -82,7 +82,7 @@ author $UTF8_NAME
summary $UTF8_MSG
EOF
-test_expect_success \
+test_expect_success !MINGW \
'blame respects --encoding=none' '
git blame --incremental --encoding=none file | \
egrep "^(author|summary) " > actual &&
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 3119c8c523..19a3ced600 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -409,7 +409,7 @@ test_expect_success $PREREQ 'Valid In-Reply-To when prompting' '
(echo "From Example <from@example.com>"
echo "To Example <to@example.com>"
echo ""
- ) | env GIT_SEND_EMAIL_NOTTY=1 git send-email \
+ ) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
--smtp-server="$(pwd)/fake.sendmail" \
$patches 2>errors &&
! grep "^In-Reply-To: < *>" msgtxt1
@@ -1334,6 +1334,51 @@ test_expect_success $PREREQ '--force sends cover letter template anyway' '
test -n "$(ls msgtxt*)"
'
+test_cover_addresses () {
+ header="$1"
+ shift
+ clean_fake_sendmail &&
+ rm -fr outdir &&
+ git format-patch --cover-letter -2 -o outdir &&
+ cover=`echo outdir/0000-*.patch` &&
+ mv $cover cover-to-edit.patch &&
+ perl -pe "s/^From:/$header: extra\@address.com\nFrom:/" cover-to-edit.patch >"$cover" &&
+ git send-email \
+ --force \
+ --from="Example <nobody@example.com>" \
+ --no-to --no-cc \
+ "$@" \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ outdir/0000-*.patch \
+ outdir/0001-*.patch \
+ outdir/0002-*.patch \
+ 2>errors >out &&
+ grep "^$header: extra@address.com" msgtxt1 >to1 &&
+ grep "^$header: extra@address.com" msgtxt2 >to2 &&
+ grep "^$header: extra@address.com" msgtxt3 >to3 &&
+ test_line_count = 1 to1 &&
+ test_line_count = 1 to2 &&
+ test_line_count = 1 to3
+}
+
+test_expect_success $PREREQ 'to-cover adds To to all mail' '
+ test_cover_addresses "To" --to-cover
+'
+
+test_expect_success $PREREQ 'cc-cover adds Cc to all mail' '
+ test_cover_addresses "Cc" --cc-cover
+'
+
+test_expect_success $PREREQ 'tocover adds To to all mail' '
+ test_config sendemail.tocover true &&
+ test_cover_addresses "To"
+'
+
+test_expect_success $PREREQ 'cccover adds Cc to all mail' '
+ test_config sendemail.cccover true &&
+ test_cover_addresses "Cc"
+'
+
test_expect_success $PREREQ 'sendemail.aliasfiletype=mailrc' '
clean_fake_sendmail &&
echo "alias sbd somebody@example.org" >.mailrc &&
diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh
index ee73013eed..6e69fc4c65 100755
--- a/t/t9107-git-svn-migrate.sh
+++ b/t/t9107-git-svn-migrate.sh
@@ -45,27 +45,27 @@ test_expect_success 'initialize old-style (v0) git svn layout' '
test_expect_success 'initialize a multi-repository repo' '
git svn init "$svnrepo" -T trunk -t tags -b branches &&
git config --get-all svn-remote.svn.fetch > fetch.out &&
- grep "^trunk:refs/remotes/trunk$" fetch.out &&
+ grep "^trunk:refs/remotes/origin/trunk$" fetch.out &&
test -n "`git config --get svn-remote.svn.branches \
- "^branches/\*:refs/remotes/\*$"`" &&
+ "^branches/\*:refs/remotes/origin/\*$"`" &&
test -n "`git config --get svn-remote.svn.tags \
- "^tags/\*:refs/remotes/tags/\*$"`" &&
+ "^tags/\*:refs/remotes/origin/tags/\*$"`" &&
git config --unset svn-remote.svn.branches \
- "^branches/\*:refs/remotes/\*$" &&
+ "^branches/\*:refs/remotes/origin/\*$" &&
git config --unset svn-remote.svn.tags \
- "^tags/\*:refs/remotes/tags/\*$" &&
- git config --add svn-remote.svn.fetch "branches/a:refs/remotes/a" &&
- git config --add svn-remote.svn.fetch "branches/b:refs/remotes/b" &&
+ "^tags/\*:refs/remotes/origin/tags/\*$" &&
+ git config --add svn-remote.svn.fetch "branches/a:refs/remotes/origin/a" &&
+ git config --add svn-remote.svn.fetch "branches/b:refs/remotes/origin/b" &&
for i in tags/0.1 tags/0.2 tags/0.3; do
git config --add svn-remote.svn.fetch \
- $i:refs/remotes/$i || exit 1; done &&
+ $i:refs/remotes/origin/$i || exit 1; done &&
git config --get-all svn-remote.svn.fetch > fetch.out &&
- grep "^trunk:refs/remotes/trunk$" fetch.out &&
- grep "^branches/a:refs/remotes/a$" fetch.out &&
- grep "^branches/b:refs/remotes/b$" fetch.out &&
- grep "^tags/0\.1:refs/remotes/tags/0\.1$" fetch.out &&
- grep "^tags/0\.2:refs/remotes/tags/0\.2$" fetch.out &&
- grep "^tags/0\.3:refs/remotes/tags/0\.3$" fetch.out &&
+ grep "^trunk:refs/remotes/origin/trunk$" fetch.out &&
+ grep "^branches/a:refs/remotes/origin/a$" fetch.out &&
+ grep "^branches/b:refs/remotes/origin/b$" fetch.out &&
+ grep "^tags/0\.1:refs/remotes/origin/tags/0\.1$" fetch.out &&
+ grep "^tags/0\.2:refs/remotes/origin/tags/0\.2$" fetch.out &&
+ grep "^tags/0\.3:refs/remotes/origin/tags/0\.3$" fetch.out &&
grep "^:refs/${remotes_git_svn}" fetch.out
'
@@ -73,14 +73,14 @@ test_expect_success 'initialize a multi-repository repo' '
test_expect_success 'multi-fetch works on partial urls + paths' "
git svn multi-fetch &&
for i in trunk a b tags/0.1 tags/0.2 tags/0.3; do
- git rev-parse --verify refs/remotes/\$i^0 >> refs.out || exit 1;
+ git rev-parse --verify refs/remotes/origin/\$i^0 >> refs.out || exit 1;
done &&
test -z \"\`sort < refs.out | uniq -d\`\" &&
for i in trunk a b tags/0.1 tags/0.2 tags/0.3; do
for j in trunk a b tags/0.1 tags/0.2 tags/0.3; do
if test \$j != \$i; then continue; fi
- test -z \"\`git diff refs/remotes/\$i \
- refs/remotes/\$j\`\" ||exit 1; done; done
+ test -z \"\`git diff refs/remotes/origin/\$i \
+ refs/remotes/origin/\$j\`\" ||exit 1; done; done
"
test_expect_success 'migrate --minimize on old inited layout' '
@@ -98,27 +98,27 @@ test_expect_success 'migrate --minimize on old inited layout' '
git svn migrate --minimize &&
test -z "`git config -l | grep "^svn-remote\.git-svn\."`" &&
git config --get-all svn-remote.svn.fetch > fetch.out &&
- grep "^trunk:refs/remotes/trunk$" fetch.out &&
- grep "^branches/a:refs/remotes/a$" fetch.out &&
- grep "^branches/b:refs/remotes/b$" fetch.out &&
- grep "^tags/0\.1:refs/remotes/tags/0\.1$" fetch.out &&
- grep "^tags/0\.2:refs/remotes/tags/0\.2$" fetch.out &&
- grep "^tags/0\.3:refs/remotes/tags/0\.3$" fetch.out &&
+ grep "^trunk:refs/remotes/origin/trunk$" fetch.out &&
+ grep "^branches/a:refs/remotes/origin/a$" fetch.out &&
+ grep "^branches/b:refs/remotes/origin/b$" fetch.out &&
+ grep "^tags/0\.1:refs/remotes/origin/tags/0\.1$" fetch.out &&
+ grep "^tags/0\.2:refs/remotes/origin/tags/0\.2$" fetch.out &&
+ grep "^tags/0\.3:refs/remotes/origin/tags/0\.3$" fetch.out &&
grep "^:refs/${remotes_git_svn}" fetch.out
'
test_expect_success ".rev_db auto-converted to .rev_map.UUID" '
git svn fetch -i trunk &&
- test -z "$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db.* 2>/dev/null)" &&
- expect="$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_map.*)" &&
+ test -z "$(ls "$GIT_DIR"/svn/refs/remotes/origin/trunk/.rev_db.* 2>/dev/null)" &&
+ expect="$(ls "$GIT_DIR"/svn/refs/remotes/origin/trunk/.rev_map.*)" &&
test -n "$expect" &&
rev_db="$(echo $expect | sed -e "s,_map,_db,")" &&
convert_to_rev_db "$expect" "$rev_db" &&
rm -f "$expect" &&
test -f "$rev_db" &&
git svn fetch -i trunk &&
- test -z "$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db.* 2>/dev/null)" &&
- test ! -e "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db &&
+ test -z "$(ls "$GIT_DIR"/svn/refs/remotes/origin/trunk/.rev_db.* 2>/dev/null)" &&
+ test ! -e "$GIT_DIR"/svn/refs/remotes/origin/trunk/.rev_db &&
test -f "$expect"
'
diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh
index d33d714006..fb41876677 100755
--- a/t/t9114-git-svn-dcommit-merge.sh
+++ b/t/t9114-git-svn-dcommit-merge.sh
@@ -48,7 +48,7 @@ test_expect_success 'setup svn repository' '
test_expect_success 'setup git mirror and merge' '
git svn init "$svnrepo" -t tags -T trunk -b branches &&
git svn fetch &&
- git checkout -b svn remotes/trunk &&
+ git checkout -b svn remotes/origin/trunk &&
git checkout -b merge &&
echo new file > new_file &&
git add new_file &&
@@ -81,7 +81,7 @@ test_debug 'gitk --all & sleep 1'
test_expect_success 'verify post-merge ancestry' "
test x\`git rev-parse --verify refs/heads/svn\` = \
- x\`git rev-parse --verify refs/remotes/trunk \` &&
+ x\`git rev-parse --verify refs/remotes/origin/trunk \` &&
test x\`git rev-parse --verify refs/heads/svn^2\` = \
x\`git rev-parse --verify refs/heads/merge\` &&
git cat-file commit refs/heads/svn^ | grep '^friend$'
diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh
index cf4c05261b..45773ee560 100755
--- a/t/t9116-git-svn-log.sh
+++ b/t/t9116-git-svn-log.sh
@@ -20,20 +20,20 @@ test_expect_success 'setup repository and import' '
) &&
git svn init "$svnrepo" -T trunk -b branches -t tags &&
git svn fetch &&
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
echo bye >> README &&
git commit -a -m bye &&
git svn dcommit &&
- git reset --hard a &&
+ git reset --hard origin/a &&
echo why >> FEEDME &&
git update-index --add FEEDME &&
git commit -m feedme &&
git svn dcommit &&
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
echo aye >> README &&
git commit -a -m aye &&
git svn dcommit &&
- git reset --hard b &&
+ git reset --hard origin/b &&
echo spy >> README &&
git commit -a -m spy &&
echo try >> README &&
@@ -42,26 +42,26 @@ test_expect_success 'setup repository and import' '
'
test_expect_success 'run log' "
- git reset --hard a &&
- git svn log -r2 trunk | grep ^r2 &&
- git svn log -r4 trunk | grep ^r4 &&
+ git reset --hard origin/a &&
+ git svn log -r2 origin/trunk | grep ^r2 &&
+ git svn log -r4 origin/trunk | grep ^r4 &&
git svn log -r3 | grep ^r3
"
test_expect_success 'run log against a from trunk' "
- git reset --hard trunk &&
- git svn log -r3 a | grep ^r3
+ git reset --hard origin/trunk &&
+ git svn log -r3 origin/a | grep ^r3
"
printf 'r1 \nr2 \nr4 \n' > expected-range-r1-r2-r4
test_expect_success 'test ascending revision range' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r1-r2-r4 -
"
test_expect_success 'test ascending revision range with --show-commit' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log --show-commit -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r1-r2-r4 -
"
@@ -69,7 +69,7 @@ test_expect_success 'test ascending revision range with --show-commit (sha1)' "
git svn find-rev r1 >expected-range-r1-r2-r4-sha1 &&
git svn find-rev r2 >>expected-range-r1-r2-r4-sha1 &&
git svn find-rev r4 >>expected-range-r1-r2-r4-sha1 &&
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log --show-commit -r 1:4 | grep '^r[0-9]' | cut -d'|' -f2 >out &&
git rev-parse \$(cat out) >actual &&
test_cmp expected-range-r1-r2-r4-sha1 actual
@@ -78,67 +78,67 @@ test_expect_success 'test ascending revision range with --show-commit (sha1)' "
printf 'r4 \nr2 \nr1 \n' > expected-range-r4-r2-r1
test_expect_success 'test descending revision range' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 4:1 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4-r2-r1 -
"
printf 'r1 \nr2 \n' > expected-range-r1-r2
test_expect_success 'test ascending revision range with unreachable revision' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 1:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r1-r2 -
"
printf 'r2 \nr1 \n' > expected-range-r2-r1
test_expect_success 'test descending revision range with unreachable revision' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 3:1 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r2-r1 -
"
printf 'r2 \n' > expected-range-r2
test_expect_success 'test ascending revision range with unreachable upper boundary revision and 1 commit' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 2:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r2 -
"
test_expect_success 'test descending revision range with unreachable upper boundary revision and 1 commit' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 3:2 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r2 -
"
printf 'r4 \n' > expected-range-r4
test_expect_success 'test ascending revision range with unreachable lower boundary revision and 1 commit' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 3:4 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 -
"
test_expect_success 'test descending revision range with unreachable lower boundary revision and 1 commit' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 4:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 -
"
printf -- '------------------------------------------------------------------------\n' > expected-separator
test_expect_success 'test ascending revision range with unreachable boundary revisions and no commits' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 5:6 | test_cmp expected-separator -
"
test_expect_success 'test descending revision range with unreachable boundary revisions and no commits' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 6:5 | test_cmp expected-separator -
"
test_expect_success 'test ascending revision range with unreachable boundary revisions and 1 commit' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 3:5 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 -
"
test_expect_success 'test descending revision range with unreachable boundary revisions and 1 commit' "
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn log -r 5:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 -
"
diff --git a/t/t9117-git-svn-init-clone.sh b/t/t9117-git-svn-init-clone.sh
index 69e9c0db5d..a66f43c6b1 100755
--- a/t/t9117-git-svn-init-clone.sh
+++ b/t/t9117-git-svn-init-clone.sh
@@ -83,36 +83,36 @@ EOF
rm -f expect actual
}
-test_expect_success 'init with -s/-T/-b/-t without --prefix warns' '
+test_expect_success 'init with -s/-T/-b/-t assumes --prefix=origin/' '
test ! -d project &&
git svn init -s "$svnrepo"/project project 2>warning &&
- grep -q prefix warning &&
- test_svn_configured_prefix "" &&
+ test_must_fail grep -q prefix warning &&
+ test_svn_configured_prefix "origin/" &&
rm -rf project &&
rm -f warning
'
-test_expect_success 'clone with -s/-T/-b/-t without --prefix warns' '
+test_expect_success 'clone with -s/-T/-b/-t assumes --prefix=origin/' '
test ! -d project &&
git svn clone -s "$svnrepo"/project 2>warning &&
- grep -q prefix warning &&
- test_svn_configured_prefix "" &&
+ test_must_fail grep -q prefix warning &&
+ test_svn_configured_prefix "origin/" &&
rm -rf project &&
rm -f warning
'
-test_expect_success 'init with -s/-T/-b/-t and --prefix does not warn' '
+test_expect_success 'init with -s/-T/-b/-t and --prefix "" still works' '
test ! -d project &&
- git svn init -s "$svnrepo"/project project --prefix="" 2>warning &&
+ git svn init -s "$svnrepo"/project project --prefix "" 2>warning &&
test_must_fail grep -q prefix warning &&
test_svn_configured_prefix "" &&
rm -rf project &&
rm -f warning
'
-test_expect_success 'clone with -s/-T/-b/-t and --prefix does not warn' '
+test_expect_success 'clone with -s/-T/-b/-t and --prefix "" still works' '
test ! -d project &&
- git svn clone -s "$svnrepo"/project --prefix="" 2>warning &&
+ git svn clone -s "$svnrepo"/project --prefix "" 2>warning &&
test_must_fail grep -q prefix warning &&
test_svn_configured_prefix "" &&
rm -rf project &&
diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
index 15f93b4c28..ed4d1369cc 100755
--- a/t/t9118-git-svn-funky-branch-names.sh
+++ b/t/t9118-git-svn-funky-branch-names.sh
@@ -41,20 +41,20 @@ test_expect_success 'test clone with funky branch names' '
git svn clone -s "$svnrepo/pr ject" project &&
(
cd project &&
- git rev-parse "refs/remotes/fun%20plugin" &&
- git rev-parse "refs/remotes/more%20fun%20plugin!" &&
- git rev-parse "refs/remotes/$scary_ref" &&
- git rev-parse "refs/remotes/%2Eleading_dot" &&
- git rev-parse "refs/remotes/trailing_dot%2E" &&
- git rev-parse "refs/remotes/trailing_dotlock%2Elock" &&
- git rev-parse "refs/remotes/$non_reflog"
+ git rev-parse "refs/remotes/origin/fun%20plugin" &&
+ git rev-parse "refs/remotes/origin/more%20fun%20plugin!" &&
+ git rev-parse "refs/remotes/origin/$scary_ref" &&
+ git rev-parse "refs/remotes/origin/%2Eleading_dot" &&
+ git rev-parse "refs/remotes/origin/trailing_dot%2E" &&
+ git rev-parse "refs/remotes/origin/trailing_dotlock%2Elock" &&
+ git rev-parse "refs/remotes/origin/$non_reflog"
)
'
test_expect_success 'test dcommit to funky branch' "
(
cd project &&
- git reset --hard 'refs/remotes/more%20fun%20plugin!' &&
+ git reset --hard 'refs/remotes/origin/more%20fun%20plugin!' &&
echo hello >> foo &&
git commit -m 'hello' -- foo &&
git svn dcommit
@@ -64,7 +64,7 @@ test_expect_success 'test dcommit to funky branch' "
test_expect_success 'test dcommit to scary branch' '
(
cd project &&
- git reset --hard "refs/remotes/$scary_ref" &&
+ git reset --hard "refs/remotes/origin/$scary_ref" &&
echo urls are scary >> foo &&
git commit -m "eep" -- foo &&
git svn dcommit
@@ -74,7 +74,7 @@ test_expect_success 'test dcommit to scary branch' '
test_expect_success 'test dcommit to trailing_dotlock branch' '
(
cd project &&
- git reset --hard "refs/remotes/trailing_dotlock%2Elock" &&
+ git reset --hard "refs/remotes/origin/trailing_dotlock%2Elock" &&
echo who names branches like this anyway? >> foo &&
git commit -m "bar" -- foo &&
git svn dcommit
diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh
index ff19695e77..f16f3234a1 100755
--- a/t/t9119-git-svn-info.sh
+++ b/t/t9119-git-svn-info.sh
@@ -74,6 +74,36 @@ test_expect_success 'info .' "
test_cmp_info expected.info-dot actual.info-dot
"
+test_expect_success 'info $(pwd)' '
+ (cd svnwc; svn info "$(pwd)") >expected.info-pwd &&
+ (cd gitwc; git svn info "$(pwd)") >actual.info-pwd &&
+ grep -v ^Path: <expected.info-pwd >expected.info-np &&
+ grep -v ^Path: <actual.info-pwd >actual.info-np &&
+ test_cmp_info expected.info-np actual.info-np &&
+ test "$(sed -ne \"/^Path:/ s!/svnwc!!\" <expected.info-pwd)" = \
+ "$(sed -ne \"/^Path:/ s!/gitwc!!\" <actual.info-pwd)"
+ '
+
+test_expect_success 'info $(pwd)/../___wc' '
+ (cd svnwc; svn info "$(pwd)/../svnwc") >expected.info-pwd &&
+ (cd gitwc; git svn info "$(pwd)/../gitwc") >actual.info-pwd &&
+ grep -v ^Path: <expected.info-pwd >expected.info-np &&
+ grep -v ^Path: <actual.info-pwd >actual.info-np &&
+ test_cmp_info expected.info-np actual.info-np &&
+ test "$(sed -ne \"/^Path:/ s!/svnwc!!\" <expected.info-pwd)" = \
+ "$(sed -ne \"/^Path:/ s!/gitwc!!\" <actual.info-pwd)"
+ '
+
+test_expect_success 'info $(pwd)/../___wc//file' '
+ (cd svnwc; svn info "$(pwd)/../svnwc//file") >expected.info-pwd &&
+ (cd gitwc; git svn info "$(pwd)/../gitwc//file") >actual.info-pwd &&
+ grep -v ^Path: <expected.info-pwd >expected.info-np &&
+ grep -v ^Path: <actual.info-pwd >actual.info-np &&
+ test_cmp_info expected.info-np actual.info-np &&
+ test "$(sed -ne \"/^Path:/ s!/svnwc!!\" <expected.info-pwd)" = \
+ "$(sed -ne \"/^Path:/ s!/gitwc!!\" <actual.info-pwd)"
+ '
+
test_expect_success 'info --url .' '
test "$(cd gitwc; git svn info --url .)" = "$quoted_svnrepo"
'
diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh
index 1d92c05035..1c84ce1023 100755
--- a/t/t9120-git-svn-clone-with-percent-escapes.sh
+++ b/t/t9120-git-svn-clone-with-percent-escapes.sh
@@ -58,19 +58,19 @@ test_expect_success 'test clone --stdlayout with percent escapes' '
git svn clone --stdlayout "$svnrepo/pr%20ject" percent &&
(
cd percent &&
- git rev-parse refs/remotes/trunk^0 &&
- git rev-parse refs/remotes/b^0 &&
- git rev-parse refs/remotes/tags/v1^0
+ git rev-parse refs/remotes/origin/trunk^0 &&
+ git rev-parse refs/remotes/origin/b^0 &&
+ git rev-parse refs/remotes/origin/tags/v1^0
)
'
test_expect_success 'test clone -s with unescaped space' '
- git svn clone -s "$svnrepo/pr ject" space &&
+ git svn clone -s "$svnrepo/pr ject" --prefix origin/ space &&
(
cd space &&
- git rev-parse refs/remotes/trunk^0 &&
- git rev-parse refs/remotes/b^0 &&
- git rev-parse refs/remotes/tags/v1^0
+ git rev-parse refs/remotes/origin/trunk^0 &&
+ git rev-parse refs/remotes/origin/b^0 &&
+ git rev-parse refs/remotes/origin/tags/v1^0
)
'
diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh
index 096abd1fe5..0d53fc9014 100755
--- a/t/t9125-git-svn-multi-glob-branch-names.sh
+++ b/t/t9125-git-svn-multi-glob-branch-names.sh
@@ -20,14 +20,14 @@ test_expect_success 'test clone with multi-glob in branch names' '
git svn clone -T trunk -b branches/*/* -t tags \
"$svnrepo/project" project &&
(cd project &&
- git rev-parse "refs/remotes/v14.1/beta" &&
- git rev-parse "refs/remotes/v14.1/gold"
+ git rev-parse "refs/remotes/origin/v14.1/beta" &&
+ git rev-parse "refs/remotes/origin/v14.1/gold"
)
'
test_expect_success 'test dcommit to multi-globbed branch' "
(cd project &&
- git reset --hard 'refs/remotes/v14.1/gold' &&
+ git reset --hard 'refs/remotes/origin/v14.1/gold' &&
echo hello >> foo &&
git commit -m 'hello' -- foo &&
git svn dcommit
diff --git a/t/t9128-git-svn-cmd-branch.sh b/t/t9128-git-svn-cmd-branch.sh
index 4b034a67f3..4e95f791db 100755
--- a/t/t9128-git-svn-cmd-branch.sh
+++ b/t/t9128-git-svn-cmd-branch.sh
@@ -29,30 +29,30 @@ test_expect_success 'initialize svnrepo' '
test_expect_success 'import into git' '
git svn init --stdlayout "$svnrepo" &&
git svn fetch &&
- git checkout remotes/trunk
+ git checkout remotes/origin/trunk
'
test_expect_success 'git svn branch tests' '
git svn branch a &&
base=$(git rev-parse HEAD:) &&
- test $base = $(git rev-parse remotes/a:) &&
+ test $base = $(git rev-parse remotes/origin/a:) &&
git svn branch -m "created branch b blah" b &&
- test $base = $(git rev-parse remotes/b:) &&
+ test $base = $(git rev-parse remotes/origin/b:) &&
test_must_fail git branch -m "no branchname" &&
git svn branch -n c &&
- test_must_fail git rev-parse remotes/c &&
+ test_must_fail git rev-parse remotes/origin/c &&
test_must_fail git svn branch a &&
git svn branch -t tag1 &&
- test $base = $(git rev-parse remotes/tags/tag1:) &&
+ test $base = $(git rev-parse remotes/origin/tags/tag1:) &&
git svn branch --tag tag2 &&
- test $base = $(git rev-parse remotes/tags/tag2:) &&
+ test $base = $(git rev-parse remotes/origin/tags/tag2:) &&
git svn tag tag3 &&
- test $base = $(git rev-parse remotes/tags/tag3:) &&
+ test $base = $(git rev-parse remotes/origin/tags/tag3:) &&
git svn tag -m "created tag4 foo" tag4 &&
- test $base = $(git rev-parse remotes/tags/tag4:) &&
+ test $base = $(git rev-parse remotes/origin/tags/tag4:) &&
test_must_fail git svn tag -m "no tagname" &&
git svn tag -n tag5 &&
- test_must_fail git rev-parse remotes/tags/tag5 &&
+ test_must_fail git rev-parse remotes/origin/tags/tag5 &&
test_must_fail git svn tag tag1
'
diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh
index c3443ceb25..c44de267a1 100755
--- a/t/t9130-git-svn-authors-file.sh
+++ b/t/t9130-git-svn-authors-file.sh
@@ -67,7 +67,7 @@ test_expect_success 'fetch fails on ee' '
'
tmp_config_get () {
- GIT_CONFIG=.git/svn/.metadata git config --get "$1"
+ git config --file=.git/svn/.metadata --get "$1"
}
test_expect_success 'failure happened without negative side effects' '
@@ -97,7 +97,6 @@ test_expect_success 'fresh clone with svn.authors-file in config' '
test x = x"$(git config svn.authorsfile)" &&
test_config="$HOME"/.gitconfig &&
sane_unset GIT_DIR &&
- sane_unset GIT_CONFIG &&
git config --global \
svn.authorsfile "$HOME"/svn-authors &&
test x"$HOME"/svn-authors = x"$(git config svn.authorsfile)" &&
diff --git a/t/t9135-git-svn-moved-branch-empty-file.sh b/t/t9135-git-svn-moved-branch-empty-file.sh
index 5280e5f1e4..93db45db7d 100755
--- a/t/t9135-git-svn-moved-branch-empty-file.sh
+++ b/t/t9135-git-svn-moved-branch-empty-file.sh
@@ -12,7 +12,7 @@ test_expect_success 'clone using git svn' 'git svn clone -s "$svnrepo" x'
test_expect_success 'test that b1 exists and is empty' '
(
cd x &&
- git reset --hard branch-c &&
+ git reset --hard origin/branch-c &&
test -f b1 &&
! test -s b1
)
diff --git a/t/t9138-git-svn-authors-prog.sh b/t/t9138-git-svn-authors-prog.sh
index 83cc5fc9d1..2937f4c265 100755
--- a/t/t9138-git-svn-authors-prog.sh
+++ b/t/t9138-git-svn-authors-prog.sh
@@ -7,40 +7,39 @@ test_description='git svn authors prog tests'
. ./lib-git-svn.sh
-cat > svn-authors-prog <<'EOF'
-#!/usr/bin/perl
-$_ = shift;
-if (s/-sub$//) {
- print "$_ <$_\@sub.example.com>\n";
-}
-else {
- print "$_ <$_\@example.com>\n";
-}
+write_script svn-authors-prog "$PERL_PATH" <<-\EOF
+ $_ = shift;
+ if (s/-sub$//) {
+ print "$_ <$_\@sub.example.com>\n";
+ } else {
+ print "$_ <$_\@example.com>\n";
+ }
EOF
-chmod +x svn-authors-prog
-cat > svn-authors <<'EOF'
-ff = FFFFFFF FFFFFFF <fFf@other.example.com>
-EOF
+test_expect_success 'svn-authors setup' '
+ cat >svn-authors <<-\EOF
+ ff = FFFFFFF FFFFFFF <fFf@other.example.com>
+ EOF
+'
test_expect_success 'setup svnrepo' '
for i in aa bb cc-sub dd-sub ee-foo ff
do
svn mkdir -m $i --username $i "$svnrepo"/$i
done
- '
+'
test_expect_success 'import authors with prog and file' '
git svn clone --authors-prog=./svn-authors-prog \
--authors-file=svn-authors "$svnrepo" x
- '
+'
test_expect_success 'imported 6 revisions successfully' '
(
cd x
test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 6
)
- '
+'
test_expect_success 'authors-prog ran correctly' '
(
@@ -56,7 +55,7 @@ test_expect_success 'authors-prog ran correctly' '
git rev-list -1 --pretty=raw refs/remotes/git-svn~5 | \
grep "^author aa <aa@example\.com> "
)
- '
+'
test_expect_success 'authors-file overrode authors-prog' '
(
@@ -64,7 +63,7 @@ test_expect_success 'authors-file overrode authors-prog' '
git rev-list -1 --pretty=raw refs/remotes/git-svn | \
grep "^author FFFFFFF FFFFFFF <fFf@other\.example\.com> "
)
- '
+'
git --git-dir=x/.git config --unset svn.authorsfile
git --git-dir=x/.git config --unset svn.authorsprog
diff --git a/t/t9141-git-svn-multiple-branches.sh b/t/t9141-git-svn-multiple-branches.sh
index 3cd06718eb..8e7f7d68b7 100755
--- a/t/t9141-git-svn-multiple-branches.sh
+++ b/t/t9141-git-svn-multiple-branches.sh
@@ -66,18 +66,18 @@ test_expect_success 'clone multiple branch and tag paths' '
-t tags_A/* --tags tags_B \
"$svnrepo/project" git_project &&
( cd git_project &&
- git rev-parse refs/remotes/first &&
- git rev-parse refs/remotes/second &&
- git rev-parse refs/remotes/1 &&
- git rev-parse refs/remotes/2 &&
- git rev-parse refs/remotes/tags/1.0 &&
- git rev-parse refs/remotes/tags/2.0 &&
- git rev-parse refs/remotes/tags/3.0 &&
- git rev-parse refs/remotes/tags/4.0 &&
- git rev-parse refs/remotes/tags/v5 &&
- git rev-parse refs/remotes/tags/v6 &&
- git rev-parse refs/remotes/tags/v7 &&
- git rev-parse refs/remotes/tags/v8
+ git rev-parse refs/remotes/origin/first &&
+ git rev-parse refs/remotes/origin/second &&
+ git rev-parse refs/remotes/origin/1 &&
+ git rev-parse refs/remotes/origin/2 &&
+ git rev-parse refs/remotes/origin/tags/1.0 &&
+ git rev-parse refs/remotes/origin/tags/2.0 &&
+ git rev-parse refs/remotes/origin/tags/3.0 &&
+ git rev-parse refs/remotes/origin/tags/4.0 &&
+ git rev-parse refs/remotes/origin/tags/v5 &&
+ git rev-parse refs/remotes/origin/tags/v6 &&
+ git rev-parse refs/remotes/origin/tags/v7 &&
+ git rev-parse refs/remotes/origin/tags/v8
)
'
@@ -85,8 +85,8 @@ test_expect_success 'Multiple branch or tag paths require -d' '
( cd git_project &&
test_must_fail git svn branch -m "No new branch" Nope &&
test_must_fail git svn tag -m "No new tag" Tagless &&
- test_must_fail git rev-parse refs/remotes/Nope &&
- test_must_fail git rev-parse refs/remotes/tags/Tagless
+ test_must_fail git rev-parse refs/remotes/origin/Nope &&
+ test_must_fail git rev-parse refs/remotes/origin/tags/Tagless
) &&
( cd svn_project &&
svn_cmd up &&
diff --git a/t/t9145-git-svn-master-branch.sh b/t/t9145-git-svn-master-branch.sh
index 16852d26ae..6559137493 100755
--- a/t/t9145-git-svn-master-branch.sh
+++ b/t/t9145-git-svn-master-branch.sh
@@ -17,7 +17,7 @@ test_expect_success 'git svn clone --stdlayout sets up trunk as master' '
git svn clone -s "$svnrepo" g &&
(
cd g &&
- test x`git rev-parse --verify refs/remotes/trunk^0` = \
+ test x`git rev-parse --verify refs/remotes/origin/trunk^0` = \
x`git rev-parse --verify refs/heads/master^0`
)
'
diff --git a/t/t9150/make-svk-dump b/t/t9150/make-svk-dump
index 2242f14ebe..2242f14ebe 100644..100755
--- a/t/t9150/make-svk-dump
+++ b/t/t9150/make-svk-dump
diff --git a/t/t9151/make-svnmerge-dump b/t/t9151/make-svnmerge-dump
index e1e138cb1a..e1e138cb1a 100644..100755
--- a/t/t9151/make-svnmerge-dump
+++ b/t/t9151/make-svnmerge-dump
diff --git a/t/t9154-git-svn-fancy-glob.sh b/t/t9154-git-svn-fancy-glob.sh
index b780e0efe3..a0150f057d 100755
--- a/t/t9154-git-svn-fancy-glob.sh
+++ b/t/t9154-git-svn-fancy-glob.sh
@@ -22,7 +22,7 @@ test_expect_success 'add red branch' "
"
test_expect_success 'add gre branch' "
- GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
+ git config --file=.git/svn/.metadata --unset svn-remote.svn.branches-maxRev &&
git config svn-remote.svn.branches 'branches/{red,gre}:refs/remotes/*' &&
git svn fetch &&
git rev-parse refs/remotes/red &&
@@ -31,7 +31,7 @@ test_expect_success 'add gre branch' "
"
test_expect_success 'add green branch' "
- GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
+ git config --file=.git/svn/.metadata --unset svn-remote.svn.branches-maxRev &&
git config svn-remote.svn.branches 'branches/{red,green}:refs/remotes/*' &&
git svn fetch &&
git rev-parse refs/remotes/red &&
@@ -40,7 +40,7 @@ test_expect_success 'add green branch' "
"
test_expect_success 'add all branches' "
- GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
+ git config --file=.git/svn/.metadata --unset svn-remote.svn.branches-maxRev &&
git config svn-remote.svn.branches 'branches/*:refs/remotes/*' &&
git svn fetch &&
git rev-parse refs/remotes/red &&
diff --git a/t/t9155-git-svn-fetch-deleted-tag.sh b/t/t9155-git-svn-fetch-deleted-tag.sh
index a486a98f84..184336f346 100755
--- a/t/t9155-git-svn-fetch-deleted-tag.sh
+++ b/t/t9155-git-svn-fetch-deleted-tag.sh
@@ -35,8 +35,8 @@ test_expect_success 'fetch deleted tags from same revision with checksum error'
cd git_project &&
git svn fetch &&
- git diff --exit-code mybranch:trunk/subdir/file tags/mytag:file &&
- git diff --exit-code master:subdir/file tags/mytag^:file
+ git diff --exit-code origin/mybranch:trunk/subdir/file origin/tags/mytag:file &&
+ git diff --exit-code master:subdir/file origin/tags/mytag^:file
'
test_done
diff --git a/t/t9156-git-svn-fetch-deleted-tag-2.sh b/t/t9156-git-svn-fetch-deleted-tag-2.sh
index 5ce7e2f3b0..7a6e33ba3c 100755
--- a/t/t9156-git-svn-fetch-deleted-tag-2.sh
+++ b/t/t9156-git-svn-fetch-deleted-tag-2.sh
@@ -36,9 +36,9 @@ test_expect_success 'fetch deleted tags from same revision with no checksum erro
cd git_project &&
git svn fetch &&
- git diff --exit-code master:subdir3/file tags/mytag:file &&
- git diff --exit-code master:subdir2/file tags/mytag^:file &&
- git diff --exit-code master:subdir1/file tags/mytag^^:file
+ git diff --exit-code master:subdir3/file origin/tags/mytag:file &&
+ git diff --exit-code master:subdir2/file origin/tags/mytag^:file &&
+ git diff --exit-code master:subdir1/file origin/tags/mytag^^:file
'
test_done
diff --git a/t/t9161-git-svn-mergeinfo-push.sh b/t/t9161-git-svn-mergeinfo-push.sh
index 1eab7015c7..6cb0909afe 100755
--- a/t/t9161-git-svn-mergeinfo-push.sh
+++ b/t/t9161-git-svn-mergeinfo-push.sh
@@ -18,8 +18,8 @@ test_expect_success 'load svn dump' "
test_expect_success 'propagate merge information' '
git config svn.pushmergeinfo yes &&
- git checkout svnb1 &&
- git merge --no-ff svnb2 &&
+ git checkout origin/svnb1 &&
+ git merge --no-ff origin/svnb2 &&
git svn dcommit
'
@@ -29,7 +29,7 @@ test_expect_success 'check svn:mergeinfo' '
'
test_expect_success 'merge another branch' '
- git merge --no-ff svnb3 &&
+ git merge --no-ff origin/svnb3 &&
git svn dcommit
'
@@ -40,7 +40,7 @@ test_expect_success 'check primary parent mergeinfo respected' '
'
test_expect_success 'merge existing merge' '
- git merge --no-ff svnb4 &&
+ git merge --no-ff origin/svnb4 &&
git svn dcommit
'
@@ -53,7 +53,7 @@ test_expect_success "check both parents' mergeinfo respected" '
'
test_expect_success 'make further commits to branch' '
- git checkout svnb2 &&
+ git checkout origin/svnb2 &&
touch newb2file &&
git add newb2file &&
git commit -m "later b2 commit" &&
@@ -64,8 +64,8 @@ test_expect_success 'make further commits to branch' '
'
test_expect_success 'second forward merge' '
- git checkout svnb1 &&
- git merge --no-ff svnb2 &&
+ git checkout origin/svnb1 &&
+ git merge --no-ff origin/svnb2 &&
git svn dcommit
'
@@ -78,8 +78,8 @@ test_expect_success 'check new mergeinfo added' '
'
test_expect_success 'reintegration merge' '
- git checkout svnb4 &&
- git merge --no-ff svnb1 &&
+ git checkout origin/svnb4 &&
+ git merge --no-ff origin/svnb1 &&
git svn dcommit
'
@@ -92,11 +92,11 @@ test_expect_success 'check reintegration mergeinfo' '
'
test_expect_success 'dcommit a merge at the top of a stack' '
- git checkout svnb1 &&
+ git checkout origin/svnb1 &&
touch anotherfile &&
git add anotherfile &&
git commit -m "a commit" &&
- git merge svnb4 &&
+ git merge origin/svnb4 &&
git svn dcommit
'
diff --git a/t/t9163-git-svn-reset-clears-caches.sh b/t/t9163-git-svn-reset-clears-caches.sh
index cd4c662ba2..d6245cee08 100755
--- a/t/t9163-git-svn-reset-clears-caches.sh
+++ b/t/t9163-git-svn-reset-clears-caches.sh
@@ -70,9 +70,9 @@ test_expect_success 'rebase looses SVN merge (m)' '
#
test_expect_success 'reset and fetch gets the SVN merge (m) correctly' '
git svn reset -r 3 &&
- git reset --hard trunk &&
+ git reset --hard origin/trunk &&
git svn fetch &&
- test 2 = $(git cat-file -p trunk|grep parent|wc -l)
+ test 2 = $(git cat-file -p origin/trunk|grep parent|wc -l)
'
test_done
diff --git a/t/t9165-git-svn-fetch-merge-branch-of-branch.sh b/t/t9165-git-svn-fetch-merge-branch-of-branch.sh
index 13ae7e33f9..fa3ef3b1f7 100755
--- a/t/t9165-git-svn-fetch-merge-branch-of-branch.sh
+++ b/t/t9165-git-svn-fetch-merge-branch-of-branch.sh
@@ -53,7 +53,7 @@ test_expect_success 'clone svn repo' '
'
test_expect_success 'verify merge commit' 'x=$(git rev-parse HEAD^2) &&
- y=$(git rev-parse branch2) &&
+ y=$(git rev-parse origin/branch2) &&
test "x$x" = "x$y"
'
diff --git a/t/t9166-git-svn-fetch-merge-branch-of-branch2.sh b/t/t9166-git-svn-fetch-merge-branch-of-branch2.sh
index af0ec0e2e3..52f2e46a5b 100755
--- a/t/t9166-git-svn-fetch-merge-branch-of-branch2.sh
+++ b/t/t9166-git-svn-fetch-merge-branch-of-branch2.sh
@@ -46,7 +46,7 @@ test_expect_success 'clone svn repo' '
'
test_expect_success 'verify merge commit' 'x=$(git rev-parse HEAD^2) &&
- y=$(git rev-parse branch2) &&
+ y=$(git rev-parse origin/branch2) &&
test "x$x" = "x$y"
'
diff --git a/t/t9167-git-svn-cmd-branch-subproject.sh b/t/t9167-git-svn-cmd-branch-subproject.sh
index 53def876ed..ba35fc06fc 100755
--- a/t/t9167-git-svn-cmd-branch-subproject.sh
+++ b/t/t9167-git-svn-cmd-branch-subproject.sh
@@ -31,7 +31,7 @@ test_expect_success 'import into git' '
git svn init --trunk=trunk/project --branches=branches/*/project \
--tags=tags/*/project "$svnrepo" &&
git svn fetch &&
- git checkout remotes/trunk
+ git checkout remotes/origin/trunk
'
test_expect_success 'git svn branch tests' '
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index 3fb3368903..812c9cd462 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -5,7 +5,6 @@
test_description='Test export of commits to CVS'
. ./test-lib.sh
-. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
if ! test_have_prereq PERL; then
skip_all='skipping git cvsexportcommit tests, perl not available'
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 27263dfb80..37c2d633f0 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -347,36 +347,6 @@ test_expect_success 'B: fail on invalid blob sha1' '
rm -f .git/objects/pack_* .git/objects/index_*
cat >input <<INPUT_END
-commit .badbranchname
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-corrupt
-COMMIT
-
-from refs/heads/master
-
-INPUT_END
-test_expect_success 'B: fail on invalid branch name ".badbranchname"' '
- test_must_fail git fast-import <input
-'
-rm -f .git/objects/pack_* .git/objects/index_*
-
-cat >input <<INPUT_END
-commit bad[branch]name
-committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-data <<COMMIT
-corrupt
-COMMIT
-
-from refs/heads/master
-
-INPUT_END
-test_expect_success 'B: fail on invalid branch name "bad[branch]name"' '
- test_must_fail git fast-import <input
-'
-rm -f .git/objects/pack_* .git/objects/index_*
-
-cat >input <<INPUT_END
commit TEMP_TAG
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
@@ -2336,7 +2306,7 @@ test_expect_success 'R: cat-blob-fd must be a nonnegative integer' '
test_must_fail git fast-import --cat-blob-fd=-1 </dev/null
'
-test_expect_success NOT_MINGW 'R: print old blob' '
+test_expect_success !MINGW 'R: print old blob' '
blob=$(echo "yes it can" | git hash-object -w --stdin) &&
cat >expect <<-EOF &&
${blob} blob 11
@@ -2348,7 +2318,7 @@ test_expect_success NOT_MINGW 'R: print old blob' '
test_cmp expect actual
'
-test_expect_success NOT_MINGW 'R: in-stream cat-blob-fd not respected' '
+test_expect_success !MINGW 'R: in-stream cat-blob-fd not respected' '
echo hello >greeting &&
blob=$(git hash-object -w greeting) &&
cat >expect <<-EOF &&
@@ -2369,7 +2339,7 @@ test_expect_success NOT_MINGW 'R: in-stream cat-blob-fd not respected' '
test_cmp expect actual.1
'
-test_expect_success NOT_MINGW 'R: print new blob' '
+test_expect_success !MINGW 'R: print new blob' '
blob=$(echo "yep yep yep" | git hash-object --stdin) &&
cat >expect <<-EOF &&
${blob} blob 12
@@ -2387,7 +2357,7 @@ test_expect_success NOT_MINGW 'R: print new blob' '
test_cmp expect actual
'
-test_expect_success NOT_MINGW 'R: print new blob by sha1' '
+test_expect_success !MINGW 'R: print new blob by sha1' '
blob=$(echo "a new blob named by sha1" | git hash-object --stdin) &&
cat >expect <<-EOF &&
${blob} blob 25
@@ -2687,7 +2657,7 @@ test_expect_success 'R: verify created pack' '
test_expect_success \
'R: verify written objects' \
'git --git-dir=R/.git cat-file blob big-file:big1 >actual &&
- test_cmp expect actual &&
+ test_cmp_bin expect actual &&
a=$(git --git-dir=R/.git rev-parse big-file:big1) &&
b=$(git --git-dir=R/.git rev-parse big-file:big2) &&
test $a = $b'
@@ -2866,7 +2836,7 @@ test_expect_success 'S: notemodify with garbage after sha1 dataref must fail' '
#
# notemodify, mark in commit-ish
#
-test_expect_success 'S: notemodify with garbarge after mark commit-ish must fail' '
+test_expect_success 'S: notemodify with garbage after mark commit-ish must fail' '
test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
commit refs/heads/Snotes
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
@@ -2999,4 +2969,126 @@ test_expect_success 'T: ls root tree' '
test_cmp expect actual
'
+test_expect_success 'T: delete branch' '
+ git branch to-delete &&
+ git fast-import <<-EOF &&
+ reset refs/heads/to-delete
+ from 0000000000000000000000000000000000000000
+ EOF
+ test_must_fail git rev-parse --verify refs/heads/to-delete
+'
+
+test_expect_success 'T: empty reset doesnt delete branch' '
+ git branch not-to-delete &&
+ git fast-import <<-EOF &&
+ reset refs/heads/not-to-delete
+ EOF
+ git show-ref &&
+ git rev-parse --verify refs/heads/not-to-delete
+'
+
+###
+### series U (filedelete)
+###
+
+cat >input <<INPUT_END
+commit refs/heads/U
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+test setup
+COMMIT
+M 100644 inline hello.c
+data <<BLOB
+blob 1
+BLOB
+M 100644 inline good/night.txt
+data <<BLOB
+sleep well
+BLOB
+M 100644 inline good/bye.txt
+data <<BLOB
+au revoir
+BLOB
+
+INPUT_END
+
+test_expect_success 'U: initialize for U tests' '
+ git fast-import <input
+'
+
+cat >input <<INPUT_END
+commit refs/heads/U
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+delete good/night.txt
+COMMIT
+from refs/heads/U^0
+D good/night.txt
+
+INPUT_END
+
+test_expect_success 'U: filedelete file succeeds' '
+ git fast-import <input
+'
+
+cat >expect <<EOF
+:100644 000000 2907ebb4bf85d91bf0716bb3bd8a68ef48d6da76 0000000000000000000000000000000000000000 D good/night.txt
+EOF
+
+git diff-tree -M -r U^1 U >actual
+
+test_expect_success 'U: validate file delete result' '
+ compare_diff_raw expect actual
+'
+
+cat >input <<INPUT_END
+commit refs/heads/U
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+delete good dir
+COMMIT
+from refs/heads/U^0
+D good
+
+INPUT_END
+
+test_expect_success 'U: filedelete directory succeeds' '
+ git fast-import <input
+'
+
+cat >expect <<EOF
+:100644 000000 69cb75792f55123d8389c156b0b41c2ff00ed507 0000000000000000000000000000000000000000 D good/bye.txt
+EOF
+
+git diff-tree -M -r U^1 U >actual
+
+test_expect_success 'U: validate directory delete result' '
+ compare_diff_raw expect actual
+'
+
+cat >input <<INPUT_END
+commit refs/heads/U
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+must succeed
+COMMIT
+from refs/heads/U^0
+D ""
+
+INPUT_END
+
+test_expect_success 'U: filedelete root succeeds' '
+ git fast-import <input
+'
+
+cat >expect <<EOF
+:100644 000000 c18147dc648481eeb65dc5e66628429a64843327 0000000000000000000000000000000000000000 D hello.c
+EOF
+
+git diff-tree -M -r U^1 U >actual
+
+test_expect_success 'U: validate root delete result' '
+ compare_diff_raw expect actual
+'
+
test_done
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 2312dec8f0..66c8b0a371 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -504,4 +504,22 @@ test_expect_success 'refs are updated even if no commits need to be exported' '
test_cmp expected actual
'
+test_expect_success 'use refspec' '
+ git fast-export --refspec refs/heads/master:refs/heads/foobar master | \
+ grep "^commit " | sort | uniq > actual &&
+ echo "commit refs/heads/foobar" > expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'delete refspec' '
+ git branch to-delete &&
+ git fast-export --refspec :refs/heads/to-delete to-delete ^to-delete > actual &&
+ cat > expected <<-EOF &&
+ reset refs/heads/to-delete
+ from 0000000000000000000000000000000000000000
+
+ EOF
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh
new file mode 100755
index 0000000000..897dc50907
--- /dev/null
+++ b/t/t9351-fast-export-anonymize.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+
+test_description='basic tests for fast-export --anonymize'
+. ./test-lib.sh
+
+test_expect_success 'setup simple repo' '
+ test_commit base &&
+ test_commit foo &&
+ git checkout -b other HEAD^ &&
+ mkdir subdir &&
+ test_commit subdir/bar &&
+ test_commit subdir/xyzzy &&
+ git tag -m "annotated tag" mytag
+'
+
+test_expect_success 'export anonymized stream' '
+ git fast-export --anonymize --all >stream
+'
+
+# this also covers commit messages
+test_expect_success 'stream omits path names' '
+ ! grep base stream &&
+ ! grep foo stream &&
+ ! grep subdir stream &&
+ ! grep bar stream &&
+ ! grep xyzzy stream
+'
+
+test_expect_success 'stream allows master as refname' '
+ grep master stream
+'
+
+test_expect_success 'stream omits other refnames' '
+ ! grep other stream &&
+ ! grep mytag stream
+'
+
+test_expect_success 'stream omits identities' '
+ ! grep "$GIT_COMMITTER_NAME" stream &&
+ ! grep "$GIT_COMMITTER_EMAIL" stream &&
+ ! grep "$GIT_AUTHOR_NAME" stream &&
+ ! grep "$GIT_AUTHOR_EMAIL" stream
+'
+
+test_expect_success 'stream omits tag message' '
+ ! grep "annotated tag" stream
+'
+
+# NOTE: we chdir to the new, anonymized repository
+# after this. All further tests should assume this.
+test_expect_success 'import stream to new repository' '
+ git init new &&
+ cd new &&
+ git fast-import <../stream
+'
+
+test_expect_success 'result has two branches' '
+ git for-each-ref --format="%(refname)" refs/heads >branches &&
+ test_line_count = 2 branches &&
+ other_branch=$(grep -v refs/heads/master branches)
+'
+
+test_expect_success 'repo has original shape and timestamps' '
+ shape () {
+ git log --format="%m %ct" --left-right --boundary "$@"
+ } &&
+ (cd .. && shape master...other) >expect &&
+ shape master...$other_branch >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'root tree has original shape' '
+ # the output entries are not necessarily in the same
+ # order, but we know at least that we will have one tree
+ # and one blob, so just check the sorted order
+ cat >expect <<-\EOF &&
+ blob
+ tree
+ EOF
+ git ls-tree $other_branch >root &&
+ cut -d" " -f2 <root | sort >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'paths in subdir ended up in one tree' '
+ cat >expect <<-\EOF &&
+ blob
+ blob
+ EOF
+ tree=$(grep tree root | cut -f2) &&
+ git ls-tree $other_branch:$tree >tree &&
+ cut -d" " -f2 <tree >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'tag points to branch tip' '
+ git rev-parse $other_branch >expect &&
+ git for-each-ref --format="%(*objectname)" | grep . >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'idents are shared' '
+ git log --all --format="%an <%ae>" >authors &&
+ sort -u authors >unique &&
+ test_line_count = 1 unique &&
+ git log --all --format="%cn <%ce>" >committers &&
+ sort -u committers >unique &&
+ test_line_count = 1 unique &&
+ ! test_cmp authors committers
+'
+
+test_done
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index 3edc4086d8..6146c3fec2 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -25,7 +25,6 @@ perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
test_done
}
-unset GIT_DIR GIT_CONFIG
WORKDIR=$(pwd)
SERVERDIR=$(pwd)/gitcvs.git
git_config="$SERVERDIR/config"
@@ -512,7 +511,7 @@ test_expect_success 'cvs co -c (shows module database)' '
# Known issues with git-cvsserver current log output:
# - Hard coded "lines: +2 -3" placeholder, instead of real numbers.
# - CVS normally does not internally add a blank first line
-# nor a last line with nothing but a space to log messages.
+# or a last line with nothing but a space to log messages.
# - The latest cvs 1.12.x server sends +0000 timezone (with some hidden "MT"
# tagging in the protocol), and if cvs 1.12.x client sees the MT tags,
# it converts to local time zone. git-cvsserver doesn't do the +0000
diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh
index 665607c9cb..5b562122a1 100755
--- a/t/t9800-git-p4-basic.sh
+++ b/t/t9800-git-p4-basic.sh
@@ -145,7 +145,7 @@ test_expect_success 'exit when p4 fails to produce marshaled output' '
test_expect_code 1 git p4 clone --dest="$git" //depot >errs 2>&1
) &&
cat errs &&
- ! test_i18ngrep Traceback errs
+ test_i18ngrep ! Traceback errs
'
# Hide a file from p4d, make sure we catch its complaint. This won't fail in
diff --git a/t/t9802-git-p4-filetype.sh b/t/t9802-git-p4-filetype.sh
index a82744bab0..66d3fc91a7 100755
--- a/t/t9802-git-p4-filetype.sh
+++ b/t/t9802-git-p4-filetype.sh
@@ -250,6 +250,89 @@ test_expect_success 'ignore apple' '
)
'
+test_expect_success SYMLINKS 'create p4 symlink' '
+ cd "$cli" &&
+ ln -s symlink-target symlink &&
+ p4 add symlink &&
+ p4 submit -d "add symlink"
+'
+
+test_expect_success SYMLINKS 'ensure p4 symlink parsed correctly' '
+ test_when_finished cleanup_git &&
+ git p4 clone --dest="$git" //depot@all &&
+ (
+ cd "$git" &&
+ test -L symlink &&
+ test $(readlink symlink) = symlink-target
+ )
+'
+
+test_expect_success SYMLINKS 'empty symlink target' '
+ (
+ # first create the file as a file
+ cd "$cli" &&
+ >empty-symlink &&
+ p4 add empty-symlink &&
+ p4 submit -d "add empty-symlink as a file"
+ ) &&
+ (
+ # now change it to be a symlink to "target1"
+ cd "$cli" &&
+ p4 edit empty-symlink &&
+ p4 reopen -t symlink empty-symlink &&
+ rm empty-symlink &&
+ ln -s target1 empty-symlink &&
+ p4 add empty-symlink &&
+ p4 submit -d "make empty-symlink point to target1"
+ ) &&
+ (
+ # Hack the p4 depot to make the symlink point to nothing;
+ # this should not happen in reality, but shows up
+ # in p4 repos in the wild.
+ #
+ # The sed expression changes this:
+ # @@
+ # text
+ # @target1
+ # @
+ # to this:
+ # @@
+ # text
+ # @@
+ #
+ cd "$db/depot" &&
+ sed "/@target1/{; s/target1/@/; n; d; }" \
+ empty-symlink,v >empty-symlink,v.tmp &&
+ mv empty-symlink,v.tmp empty-symlink,v
+ ) &&
+ (
+ # Make sure symlink really is empty. Asking
+ # p4 to sync here will make it generate errors.
+ cd "$cli" &&
+ p4 print -q //depot/empty-symlink#2 >out &&
+ test ! -s out
+ ) &&
+ test_when_finished cleanup_git &&
+
+ # make sure git p4 handles it without error
+ git p4 clone --dest="$git" //depot@all &&
+
+ # fix the symlink, make it point to "target2"
+ (
+ cd "$cli" &&
+ p4 open empty-symlink &&
+ rm empty-symlink &&
+ ln -s target2 empty-symlink &&
+ p4 submit -d "make empty-symlink point to target2"
+ ) &&
+ cleanup_git &&
+ git p4 clone --dest="$git" //depot@all &&
+ (
+ cd "$git" &&
+ test $(readlink empty-symlink) = target2
+ )
+'
+
test_expect_success 'kill p4d' '
kill_p4d
'
diff --git a/t/t9805-git-p4-skip-submit-edit.sh b/t/t9805-git-p4-skip-submit-edit.sh
index ff2cc79701..89311886db 100755
--- a/t/t9805-git-p4-skip-submit-edit.sh
+++ b/t/t9805-git-p4-skip-submit-edit.sh
@@ -17,7 +17,7 @@ test_expect_success 'init depot' '
)
'
-# this works because EDITOR is set to :
+# this works because P4EDITOR is set to true
test_expect_success 'no config, unedited, say yes' '
git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
@@ -90,7 +90,9 @@ test_expect_success 'no config, edited' '
cd "$git" &&
echo line >>file1 &&
git commit -a -m "change 5" &&
- P4EDITOR="" EDITOR="\"$TRASH_DIRECTORY/ed.sh\"" git p4 submit &&
+ P4EDITOR="$TRASH_DIRECTORY/ed.sh" &&
+ export P4EDITOR &&
+ git p4 submit &&
p4 changes //depot/... >wc &&
test_line_count = 5 wc
)
diff --git a/t/t9807-git-p4-submit.sh b/t/t9807-git-p4-submit.sh
index 1fb7bc7cf9..1f74a88385 100755
--- a/t/t9807-git-p4-submit.sh
+++ b/t/t9807-git-p4-submit.sh
@@ -17,7 +17,7 @@ test_expect_success 'init depot' '
)
'
-test_expect_failure 'is_cli_file_writeable function' '
+test_expect_success 'is_cli_file_writeable function' '
(
cd "$cli" &&
echo a >a &&
@@ -403,7 +403,8 @@ test_expect_success 'submit --prepare-p4-only' '
git commit -m "prep only add" &&
git p4 submit --prepare-p4-only >out &&
test_i18ngrep "prepared for submission" out &&
- test_i18ngrep "must be deleted" out
+ test_i18ngrep "must be deleted" out &&
+ test_i18ngrep ! "everything below this line is just the diff" out
) &&
(
cd "$cli" &&
diff --git a/t/t9809-git-p4-client-view.sh b/t/t9809-git-p4-client-view.sh
index 77f63492d9..897b3c3034 100755
--- a/t/t9809-git-p4-client-view.sh
+++ b/t/t9809-git-p4-client-view.sh
@@ -76,28 +76,28 @@ test_expect_success 'init depot' '
'
# double % for printf
-test_expect_success 'unsupported view wildcard %%n' '
+test_expect_success 'view wildcard %%n' '
client_view "//depot/%%%%1/sub/... //client/sub/%%%%1/..." &&
test_when_finished cleanup_git &&
- test_must_fail git p4 clone --use-client-spec --dest="$git" //depot
+ git p4 clone --use-client-spec --dest="$git" //depot
'
-test_expect_success 'unsupported view wildcard *' '
+test_expect_success 'view wildcard *' '
client_view "//depot/*/bar/... //client/*/bar/..." &&
test_when_finished cleanup_git &&
- test_must_fail git p4 clone --use-client-spec --dest="$git" //depot
+ git p4 clone --use-client-spec --dest="$git" //depot
'
-test_expect_success 'wildcard ... only supported at end of spec 1' '
+test_expect_success 'wildcard ... in the middle' '
client_view "//depot/.../file11 //client/.../file11" &&
test_when_finished cleanup_git &&
- test_must_fail git p4 clone --use-client-spec --dest="$git" //depot
+ git p4 clone --use-client-spec --dest="$git" //depot
'
-test_expect_success 'wildcard ... only supported at end of spec 2' '
+test_expect_success 'wildcard ... in the middle and at the end' '
client_view "//depot/.../a/... //client/.../a/..." &&
test_when_finished cleanup_git &&
- test_must_fail git p4 clone --use-client-spec --dest="$git" //depot
+ git p4 clone --use-client-spec --dest="$git" //depot
'
test_expect_success 'basic map' '
@@ -365,7 +365,7 @@ test_expect_success 'wildcard files submit back to p4, client-spec case' '
(
cd "$git" &&
echo git-wild-hash >dir1/git-wild#hash &&
- if test_have_prereq NOT_MINGW NOT_CYGWIN
+ if test_have_prereq !MINGW,!CYGWIN
then
echo git-wild-star >dir1/git-wild\*star
fi &&
@@ -379,7 +379,7 @@ test_expect_success 'wildcard files submit back to p4, client-spec case' '
(
cd "$cli" &&
test_path_is_file dir1/git-wild#hash &&
- if test_have_prereq NOT_MINGW NOT_CYGWIN
+ if test_have_prereq !MINGW,!CYGWIN
then
test_path_is_file dir1/git-wild\*star
fi &&
diff --git a/t/t9812-git-p4-wildcards.sh b/t/t9812-git-p4-wildcards.sh
index 67633257f3..0206771fbb 100755
--- a/t/t9812-git-p4-wildcards.sh
+++ b/t/t9812-git-p4-wildcards.sh
@@ -14,7 +14,7 @@ test_expect_success 'add p4 files with wildcards in the names' '
printf "file2\nhas\nsome\nrandom\ntext\n" >file2 &&
p4 add file2 &&
echo file-wild-hash >file-wild#hash &&
- if test_have_prereq NOT_MINGW NOT_CYGWIN
+ if test_have_prereq !MINGW,!CYGWIN
then
echo file-wild-star >file-wild\*star
fi &&
@@ -31,7 +31,7 @@ test_expect_success 'wildcard files git p4 clone' '
(
cd "$git" &&
test -f file-wild#hash &&
- if test_have_prereq NOT_MINGW NOT_CYGWIN
+ if test_have_prereq !MINGW,!CYGWIN
then
test -f file-wild\*star
fi &&
@@ -46,7 +46,7 @@ test_expect_success 'wildcard files submit back to p4, add' '
(
cd "$git" &&
echo git-wild-hash >git-wild#hash &&
- if test_have_prereq NOT_MINGW NOT_CYGWIN
+ if test_have_prereq !MINGW,!CYGWIN
then
echo git-wild-star >git-wild\*star
fi &&
@@ -60,7 +60,7 @@ test_expect_success 'wildcard files submit back to p4, add' '
(
cd "$cli" &&
test_path_is_file git-wild#hash &&
- if test_have_prereq NOT_MINGW NOT_CYGWIN
+ if test_have_prereq !MINGW,!CYGWIN
then
test_path_is_file git-wild\*star
fi &&
@@ -75,7 +75,7 @@ test_expect_success 'wildcard files submit back to p4, modify' '
(
cd "$git" &&
echo new-line >>git-wild#hash &&
- if test_have_prereq NOT_MINGW NOT_CYGWIN
+ if test_have_prereq !MINGW,!CYGWIN
then
echo new-line >>git-wild\*star
fi &&
@@ -89,7 +89,7 @@ test_expect_success 'wildcard files submit back to p4, modify' '
(
cd "$cli" &&
test_line_count = 2 git-wild#hash &&
- if test_have_prereq NOT_MINGW NOT_CYGWIN
+ if test_have_prereq !MINGW,!CYGWIN
then
test_line_count = 2 git-wild\*star
fi &&
@@ -152,7 +152,7 @@ test_expect_success 'wildcard files submit back to p4, delete' '
(
cd "$cli" &&
test_path_is_missing git-wild#hash &&
- if test_have_prereq NOT_MINGW NOT_CYGWIN
+ if test_have_prereq !MINGW,!CYGWIN
then
test_path_is_missing git-wild\*star
fi &&
@@ -161,6 +161,56 @@ test_expect_success 'wildcard files submit back to p4, delete' '
)
'
+test_expect_success 'p4 deleted a wildcard file' '
+ (
+ cd "$cli" &&
+ echo "wild delete test" >wild@delete &&
+ p4 add -f wild@delete &&
+ p4 submit -d "add wild@delete"
+ ) &&
+ test_when_finished cleanup_git &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ test_path_is_file wild@delete
+ ) &&
+ (
+ cd "$cli" &&
+ # must use its encoded name
+ p4 delete wild%40delete &&
+ p4 submit -d "delete wild@delete"
+ ) &&
+ (
+ cd "$git" &&
+ git p4 sync &&
+ git merge --ff-only p4/master &&
+ test_path_is_missing wild@delete
+ )
+'
+
+test_expect_success 'wildcard files requiring keyword scrub' '
+ (
+ cd "$cli" &&
+ cat <<-\EOF >scrub@wild &&
+ $Id$
+ line2
+ EOF
+ p4 add -t text+k -f scrub@wild &&
+ p4 submit -d "scrub at wild"
+ ) &&
+ test_when_finished cleanup_git &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ git config git-p4.skipSubmitEdit true &&
+ git config git-p4.attemptRCSCleanup true &&
+ sed "s/^line2/line2 edit/" <scrub@wild >scrub@wild.tmp &&
+ mv -f scrub@wild.tmp scrub@wild &&
+ git commit -m "scrub at wild line2 edit" scrub@wild &&
+ git p4 submit
+ )
+'
+
test_expect_success 'kill p4d' '
kill_p4d
'
diff --git a/t/t9813-git-p4-preserve-users.sh b/t/t9813-git-p4-preserve-users.sh
index f2e85e518b..166b840bfa 100755
--- a/t/t9813-git-p4-preserve-users.sh
+++ b/t/t9813-git-p4-preserve-users.sh
@@ -19,16 +19,6 @@ test_expect_success 'create files' '
)
'
-p4_add_user() {
- name=$1 fullname=$2 &&
- p4 user -f -i <<-EOF &&
- User: $name
- Email: $name@localhost
- FullName: $fullname
- EOF
- p4 passwd -P secret $name
-}
-
p4_grant_admin() {
name=$1 &&
{
@@ -51,8 +41,8 @@ make_change_by_user() {
# Test username support, submitting as user 'alice'
test_expect_success 'preserve users' '
- p4_add_user alice Alice &&
- p4_add_user bob Bob &&
+ p4_add_user alice &&
+ p4_add_user bob &&
p4_grant_admin alice &&
git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
@@ -60,8 +50,8 @@ test_expect_success 'preserve users' '
cd "$git" &&
echo "username: a change by alice" >>file1 &&
echo "username: a change by bob" >>file2 &&
- git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 &&
- git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 &&
+ git commit --author "Alice <alice@example.com>" -m "a change by alice" file1 &&
+ git commit --author "Bob <bob@example.com>" -m "a change by bob" file2 &&
git config git-p4.skipSubmitEditCheck true &&
P4EDITOR=touch P4USER=alice P4PASSWD=secret git p4 commit --preserve-user &&
p4_check_commit_author file1 alice &&
@@ -78,7 +68,7 @@ test_expect_success 'refuse to preserve users without perms' '
cd "$git" &&
git config git-p4.skipSubmitEditCheck true &&
echo "username-noperms: a change by alice" >>file1 &&
- git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 &&
+ git commit --author "Alice <alice@example.com>" -m "perms: a change by alice" file1 &&
P4EDITOR=touch P4USER=bob P4PASSWD=secret &&
export P4EDITOR P4USER P4PASSWD &&
test_must_fail git p4 commit --preserve-user &&
@@ -94,9 +84,9 @@ test_expect_success 'preserve user where author is unknown to p4' '
cd "$git" &&
git config git-p4.skipSubmitEditCheck true &&
echo "username-bob: a change by bob" >>file1 &&
- git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 &&
+ git commit --author "Bob <bob@example.com>" -m "preserve: a change by bob" file1 &&
echo "username-unknown: a change by charlie" >>file1 &&
- git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 &&
+ git commit --author "Charlie <charlie@example.com>" -m "preserve: a change by charlie" file1 &&
P4EDITOR=touch P4USER=alice P4PASSWD=secret &&
export P4EDITOR P4USER P4PASSWD &&
test_must_fail git p4 commit --preserve-user &&
@@ -121,24 +111,24 @@ test_expect_success 'not preserving user with mixed authorship' '
(
cd "$git" &&
git config git-p4.skipSubmitEditCheck true &&
- p4_add_user derek Derek &&
+ p4_add_user derek &&
- make_change_by_user usernamefile3 Derek derek@localhost &&
+ make_change_by_user usernamefile3 Derek derek@example.com &&
P4EDITOR=cat P4USER=alice P4PASSWD=secret &&
export P4EDITOR P4USER P4PASSWD &&
git p4 commit |\
- grep "git author derek@localhost does not match" &&
+ grep "git author derek@example.com does not match" &&
- make_change_by_user usernamefile3 Charlie charlie@localhost &&
+ make_change_by_user usernamefile3 Charlie charlie@example.com &&
git p4 commit |\
- grep "git author charlie@localhost does not match" &&
+ grep "git author charlie@example.com does not match" &&
- make_change_by_user usernamefile3 alice alice@localhost &&
+ make_change_by_user usernamefile3 alice alice@example.com &&
git p4 commit |\
test_must_fail grep "git author.*does not match" &&
git config git-p4.skipUserNameCheck true &&
- make_change_by_user usernamefile3 Charlie charlie@localhost &&
+ make_change_by_user usernamefile3 Charlie charlie@example.com &&
git p4 commit |\
test_must_fail grep "git author.*does not match" &&
diff --git a/t/t9814-git-p4-rename.sh b/t/t9814-git-p4-rename.sh
index be802e0e16..95f4421f71 100755
--- a/t/t9814-git-p4-rename.sh
+++ b/t/t9814-git-p4-rename.sh
@@ -177,7 +177,10 @@ test_expect_success 'detect copies' '
level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
- test "$src" = file10 -o "$src" = file11 &&
+ case "$src" in
+ file10 | file11) : ;; # happy
+ *) false ;; # not
+ &&
git config git-p4.detectCopies $(($level + 2)) &&
git p4 submit &&
p4 filelog //depot/file12 &&
@@ -191,7 +194,10 @@ test_expect_success 'detect copies' '
level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
- test "$src" = file10 -o "$src" = file11 -o "$src" = file12 &&
+ case "$src" in
+ file10 | file11 | file12) : ;; # happy
+ *) false ;; # not
+ &&
git config git-p4.detectCopies $(($level - 2)) &&
git p4 submit &&
p4 filelog //depot/file13 &&
diff --git a/t/t9815-git-p4-submit-fail.sh b/t/t9815-git-p4-submit-fail.sh
index 1243d96092..4cff6a760f 100755
--- a/t/t9815-git-p4-submit-fail.sh
+++ b/t/t9815-git-p4-submit-fail.sh
@@ -417,7 +417,7 @@ test_expect_success 'cleanup chmod after submit cancel' '
! p4 fstat -T action text &&
test_path_is_file text+x &&
! p4 fstat -T action text+x &&
- if test_have_prereq NOT_CYGWIN
+ if test_have_prereq !CYGWIN
then
stat --format=%A text | egrep ^-r-- &&
stat --format=%A text+x | egrep ^-r-x
diff --git a/t/t9816-git-p4-locked.sh b/t/t9816-git-p4-locked.sh
new file mode 100755
index 0000000000..e71e543343
--- /dev/null
+++ b/t/t9816-git-p4-locked.sh
@@ -0,0 +1,145 @@
+#!/bin/sh
+
+test_description='git p4 locked file behavior'
+
+. ./lib-git-p4.sh
+
+test_expect_success 'start p4d' '
+ start_p4d
+'
+
+# See
+# http://www.perforce.com/perforce/doc.current/manuals/p4sag/03_superuser.html#1088563
+# for suggestions on how to configure "sitewide pessimistic locking"
+# where only one person can have a file open for edit at a time.
+test_expect_success 'init depot' '
+ (
+ cd "$cli" &&
+ echo "TypeMap: +l //depot/..." | p4 typemap -i &&
+ echo file1 >file1 &&
+ p4 add file1 &&
+ p4 submit -d "add file1"
+ )
+'
+
+test_expect_success 'edit with lock not taken' '
+ test_when_finished cleanup_git &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ echo line2 >>file1 &&
+ git add file1 &&
+ git commit -m "line2 in file1" &&
+ git config git-p4.skipSubmitEdit true &&
+ git p4 submit
+ )
+'
+
+test_expect_failure 'add with lock not taken' '
+ test_when_finished cleanup_git &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ echo line1 >>add-lock-not-taken &&
+ git add file2 &&
+ git commit -m "add add-lock-not-taken" &&
+ git config git-p4.skipSubmitEdit true &&
+ git p4 submit --verbose
+ )
+'
+
+lock_in_another_client() {
+ # build a different client
+ cli2="$TRASH_DIRECTORY/cli2" &&
+ mkdir -p "$cli2" &&
+ test_when_finished "p4 client -f -d client2 && rm -rf \"$cli2\"" &&
+ (
+ cd "$cli2" &&
+ P4CLIENT=client2 &&
+ cli="$cli2" &&
+ client_view "//depot/... //client2/..." &&
+ p4 sync &&
+ p4 open file1
+ )
+}
+
+test_expect_failure 'edit with lock taken' '
+ lock_in_another_client &&
+ test_when_finished cleanup_git &&
+ test_when_finished "cd \"$cli\" && p4 sync -f file1" &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ echo line3 >>file1 &&
+ git add file1 &&
+ git commit -m "line3 in file1" &&
+ git config git-p4.skipSubmitEdit true &&
+ git p4 submit --verbose
+ )
+'
+
+test_expect_failure 'delete with lock taken' '
+ lock_in_another_client &&
+ test_when_finished cleanup_git &&
+ test_when_finished "cd \"$cli\" && p4 sync -f file1" &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ git rm file1 &&
+ git commit -m "delete file1" &&
+ git config git-p4.skipSubmitEdit true &&
+ git p4 submit --verbose
+ )
+'
+
+test_expect_failure 'chmod with lock taken' '
+ lock_in_another_client &&
+ test_when_finished cleanup_git &&
+ test_when_finished "cd \"$cli\" && p4 sync -f file1" &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ chmod +x file1 &&
+ git add file1 &&
+ git commit -m "chmod +x file1" &&
+ git config git-p4.skipSubmitEdit true &&
+ git p4 submit --verbose
+ )
+'
+
+test_expect_failure 'copy with lock taken' '
+ lock_in_another_client &&
+ test_when_finished cleanup_git &&
+ test_when_finished "cd \"$cli\" && p4 revert file2 && rm -f file2" &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ cp file1 file2 &&
+ git add file2 &&
+ git commit -m "cp file1 to file2" &&
+ git config git-p4.skipSubmitEdit true &&
+ git config git-p4.detectCopies true &&
+ git p4 submit --verbose
+ )
+'
+
+test_expect_failure 'move with lock taken' '
+ lock_in_another_client &&
+ test_when_finished cleanup_git &&
+ test_when_finished "cd \"$cli\" && p4 sync file1 && rm -f file2" &&
+ git p4 clone --dest="$git" //depot &&
+ (
+ cd "$git" &&
+ git mv file1 file2 &&
+ git commit -m "mv file1 to file2" &&
+ git config git-p4.skipSubmitEdit true &&
+ git config git-p4.detectRenames true &&
+ git p4 submit --verbose
+ )
+'
+
+test_expect_success 'kill p4d' '
+ kill_p4d
+'
+
+test_done
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 2d4beb5e50..f10a75290e 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -212,9 +212,18 @@ test_expect_success '__gitdir - non-existing $GIT_DIR' '
)
'
+function pwd_P_W () {
+ if test_have_prereq MINGW
+ then
+ pwd -W
+ else
+ pwd -P
+ fi
+}
+
test_expect_success '__gitdir - gitfile in cwd' '
- echo "$(pwd -P)/otherrepo/.git" >expected &&
- echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
+ echo "$(pwd_P_W)/otherrepo/.git" >expected &&
+ echo "gitdir: $(pwd_P_W)/otherrepo/.git" >subdir/.git &&
test_when_finished "rm -f subdir/.git" &&
(
cd subdir &&
@@ -224,8 +233,8 @@ test_expect_success '__gitdir - gitfile in cwd' '
'
test_expect_success '__gitdir - gitfile in parent' '
- echo "$(pwd -P)/otherrepo/.git" >expected &&
- echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
+ echo "$(pwd_P_W)/otherrepo/.git" >expected &&
+ echo "gitdir: $(pwd_P_W)/otherrepo/.git" >subdir/.git &&
test_when_finished "rm -f subdir/.git" &&
(
cd subdir/subsubdir &&
@@ -550,6 +559,33 @@ test_expect_success 'complete files' '
test_completion "git add mom" "momified"
'
+test_expect_success "completion uses <cmd> completion for alias: !sh -c 'git <cmd> ...'" '
+ test_config alias.co "!sh -c '"'"'git checkout ...'"'"'" &&
+ test_completion "git co m" <<-\EOF
+ master Z
+ mybranch Z
+ mytag Z
+ EOF
+'
+
+test_expect_success 'completion uses <cmd> completion for alias: !f () { VAR=val git <cmd> ... }' '
+ test_config alias.co "!f () { VAR=val git checkout ... ; } f" &&
+ test_completion "git co m" <<-\EOF
+ master Z
+ mybranch Z
+ mytag Z
+ EOF
+'
+
+test_expect_success 'completion used <cmd> completion for alias: !f() { : git <cmd> ; ... }' '
+ test_config alias.co "!f() { : git checkout ; if ... } f" &&
+ test_completion "git co m" <<-\EOF
+ master Z
+ mybranch Z
+ mytag Z
+ EOF
+'
+
test_expect_failure 'complete with tilde expansion' '
git init tmp && cd tmp &&
test_when_finished "cd .. && rm -rf tmp" &&
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 59f875e830..9150984184 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -452,53 +452,53 @@ test_expect_success 'prompt - format string starting with dash' '
'
test_expect_success 'prompt - pc mode' '
- printf "BEFORE: (master):AFTER" >expected &&
+ printf "BEFORE: (\${__git_ps1_branch_name}):AFTER\\nmaster" >expected &&
printf "" >expected_output &&
(
__git_ps1 "BEFORE:" ":AFTER" >"$actual" &&
test_cmp expected_output "$actual" &&
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'prompt - bash color pc mode - branch name' '
- printf "BEFORE: (${c_green}master${c_clear}):AFTER" >expected &&
+ printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear}):AFTER\\nmaster" >expected &&
(
GIT_PS1_SHOWCOLORHINTS=y &&
__git_ps1 "BEFORE:" ":AFTER" >"$actual"
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'prompt - bash color pc mode - detached head' '
- printf "BEFORE: (${c_red}(%s...)${c_clear}):AFTER" $(git log -1 --format="%h" b1^) >expected &&
+ printf "BEFORE: (${c_red}\${__git_ps1_branch_name}${c_clear}):AFTER\\n(%s...)" $(git log -1 --format="%h" b1^) >expected &&
git checkout b1^ &&
test_when_finished "git checkout master" &&
(
GIT_PS1_SHOWCOLORHINTS=y &&
__git_ps1 "BEFORE:" ":AFTER" &&
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty worktree' '
- printf "BEFORE: (${c_green}master${c_clear} ${c_red}*${c_clear}):AFTER" >expected &&
+ printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_red}*${c_clear}):AFTER\\nmaster" >expected &&
echo "dirty" >file &&
test_when_finished "git reset --hard" &&
(
GIT_PS1_SHOWDIRTYSTATE=y &&
GIT_PS1_SHOWCOLORHINTS=y &&
__git_ps1 "BEFORE:" ":AFTER" &&
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty index' '
- printf "BEFORE: (${c_green}master${c_clear} ${c_green}+${c_clear}):AFTER" >expected &&
+ printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_green}+${c_clear}):AFTER\\nmaster" >expected &&
echo "dirty" >file &&
test_when_finished "git reset --hard" &&
git add -u &&
@@ -506,13 +506,13 @@ test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirt
GIT_PS1_SHOWDIRTYSTATE=y &&
GIT_PS1_SHOWCOLORHINTS=y &&
__git_ps1 "BEFORE:" ":AFTER" &&
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty index and worktree' '
- printf "BEFORE: (${c_green}master${c_clear} ${c_red}*${c_green}+${c_clear}):AFTER" >expected &&
+ printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_red}*${c_green}+${c_clear}):AFTER\\nmaster" >expected &&
echo "dirty index" >file &&
test_when_finished "git reset --hard" &&
git add -u &&
@@ -521,25 +521,25 @@ test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirt
GIT_PS1_SHOWCOLORHINTS=y &&
GIT_PS1_SHOWDIRTYSTATE=y &&
__git_ps1 "BEFORE:" ":AFTER" &&
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'prompt - bash color pc mode - dirty status indicator - before root commit' '
- printf "BEFORE: (${c_green}master${c_clear} ${c_green}#${c_clear}):AFTER" >expected &&
+ printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_green}#${c_clear}):AFTER\\nmaster" >expected &&
(
GIT_PS1_SHOWDIRTYSTATE=y &&
GIT_PS1_SHOWCOLORHINTS=y &&
cd otherrepo &&
__git_ps1 "BEFORE:" ":AFTER" &&
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'prompt - bash color pc mode - inside .git directory' '
- printf "BEFORE: (${c_green}GIT_DIR!${c_clear}):AFTER" >expected &&
+ printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear}):AFTER\\nGIT_DIR!" >expected &&
echo "dirty" >file &&
test_when_finished "git reset --hard" &&
(
@@ -547,13 +547,13 @@ test_expect_success 'prompt - bash color pc mode - inside .git directory' '
GIT_PS1_SHOWCOLORHINTS=y &&
cd .git &&
__git_ps1 "BEFORE:" ":AFTER" &&
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'prompt - bash color pc mode - stash status indicator' '
- printf "BEFORE: (${c_green}master${c_clear} ${c_lblue}\$${c_clear}):AFTER" >expected &&
+ printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_lblue}\$${c_clear}):AFTER\\nmaster" >expected &&
echo 2 >file &&
git stash &&
test_when_finished "git stash drop" &&
@@ -561,18 +561,18 @@ test_expect_success 'prompt - bash color pc mode - stash status indicator' '
GIT_PS1_SHOWSTASHSTATE=y &&
GIT_PS1_SHOWCOLORHINTS=y &&
__git_ps1 "BEFORE:" ":AFTER" &&
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'prompt - bash color pc mode - untracked files status indicator' '
- printf "BEFORE: (${c_green}master${c_clear} ${c_red}%%${c_clear}):AFTER" >expected &&
+ printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_red}%%${c_clear}):AFTER\\nmaster" >expected &&
(
GIT_PS1_SHOWUNTRACKEDFILES=y &&
GIT_PS1_SHOWCOLORHINTS=y &&
__git_ps1 "BEFORE:" ":AFTER" &&
- printf "%s" "$PS1" >"$actual"
+ printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
) &&
test_cmp expected "$actual"
'
@@ -582,7 +582,7 @@ test_expect_success 'prompt - zsh color pc mode' '
(
ZSH_VERSION=5.0.0 &&
GIT_PS1_SHOWCOLORHINTS=y &&
- __git_ps1 "BEFORE:" ":AFTER" >"$actual"
+ __git_ps1 "BEFORE:" ":AFTER" &&
printf "%s" "$PS1" >"$actual"
) &&
test_cmp expected "$actual"
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 2f79146e6c..0d93e33de4 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1,4 +1,5 @@
-#!/bin/sh
+# Library of functions shared by all tests scripts, included by
+# test-lib.sh.
#
# Copyright (c) 2005 Junio C Hamano
#
@@ -31,6 +32,11 @@ test_set_editor () {
export EDITOR
}
+test_set_index_version () {
+ GIT_INDEX_VERSION="$1"
+ export GIT_INDEX_VERSION
+}
+
test_decode_color () {
awk '
function name(n) {
@@ -407,7 +413,7 @@ test_external () {
# test_run_, but keep its stdout on our stdout even in
# non-verbose mode.
"$@" 2>&4
- if [ "$?" = 0 ]
+ if test "$?" = 0
then
if test $test_external_has_tap -eq 0; then
test_ok_ "$descr"
@@ -434,11 +440,12 @@ test_external_without_stderr () {
tmp=${TMPDIR:-/tmp}
stderr="$tmp/git-external-stderr.$$.tmp"
test_external "$@" 4> "$stderr"
- [ -f "$stderr" ] || error "Internal error: $stderr disappeared."
+ test -f "$stderr" || error "Internal error: $stderr disappeared."
descr="no stderr: $1"
shift
say >&3 "# expecting no stderr from previous command"
- if [ ! -s "$stderr" ]; then
+ if test ! -s "$stderr"
+ then
rm "$stderr"
if test $test_external_has_tap -eq 0; then
@@ -448,8 +455,9 @@ test_external_without_stderr () {
test_success=$(($test_success + 1))
fi
else
- if [ "$verbose" = t ]; then
- output=`echo; echo "# Stderr is:"; cat "$stderr"`
+ if test "$verbose" = t
+ then
+ output=$(echo; echo "# Stderr is:"; cat "$stderr")
else
output=
fi
@@ -468,7 +476,7 @@ test_external_without_stderr () {
# The commands test the existence or non-existence of $1. $2 can be
# given to provide a more precise diagnosis.
test_path_is_file () {
- if ! [ -f "$1" ]
+ if ! test -f "$1"
then
echo "File $1 doesn't exist. $*"
false
@@ -476,19 +484,31 @@ test_path_is_file () {
}
test_path_is_dir () {
- if ! [ -d "$1" ]
+ if ! test -d "$1"
then
echo "Directory $1 doesn't exist. $*"
false
fi
}
+# Check if the directory exists and is empty as expected, barf otherwise.
+test_dir_is_empty () {
+ test_path_is_dir "$1" &&
+ if test -n "$(ls -a1 "$1" | egrep -v '^\.\.?$')"
+ then
+ echo "Directory '$1' is not empty, it contains:"
+ ls -la "$1"
+ return 1
+ fi
+}
+
test_path_is_missing () {
- if [ -e "$1" ]
+ if test -e "$1"
then
echo "Path exists:"
ls -ld "$1"
- if [ $# -ge 1 ]; then
+ if test $# -ge 1
+ then
echo "$*"
fi
false
@@ -536,7 +556,7 @@ test_must_fail () {
if test $exit_code = 0; then
echo >&2 "test_must_fail: command succeeded: $*"
return 1
- elif test $exit_code -gt 129 -a $exit_code -le 192; then
+ elif test $exit_code -gt 129 && test $exit_code -le 192; then
echo >&2 "test_must_fail: died by signal: $*"
return 1
elif test $exit_code = 127; then
@@ -563,7 +583,7 @@ test_must_fail () {
test_might_fail () {
"$@"
exit_code=$?
- if test $exit_code -gt 129 -a $exit_code -le 192; then
+ if test $exit_code -gt 129 && test $exit_code -le 192; then
echo >&2 "test_might_fail: died by signal: $*"
return 1
elif test $exit_code = 127; then
@@ -611,6 +631,21 @@ test_cmp() {
$GIT_TEST_CMP "$@"
}
+# test_cmp_bin - helper to compare binary files
+
+test_cmp_bin() {
+ cmp "$@"
+}
+
+# Call any command "$@" but be more verbose about its
+# failure. This is handy for commands like "test" which do
+# not output anything when they fail.
+verbose () {
+ "$@" && return 0
+ echo >&2 "command failed: $(git rev-parse --sq-quote "$@")"
+ return 1
+}
+
# Check if the file expected to be empty is indeed empty, and barfs
# otherwise.
@@ -634,9 +669,12 @@ test_cmp_rev () {
# similar to GNU seq(1), but the latter might not be available
# everywhere (and does not do letters). It may be used like:
#
-# for i in `test_seq 100`; do
-# for j in `test_seq 10 20`; do
-# for k in `test_seq a z`; do
+# for i in $(test_seq 100)
+# do
+# for j in $(test_seq 10 20)
+# do
+# for k in $(test_seq a z)
+# do
# echo $i-$j-$k
# done
# done
@@ -711,10 +749,73 @@ test_ln_s_add () {
fi
}
+# This function writes out its parameters, one per line
+test_write_lines () {
+ printf "%s\n" "$@"
+}
+
perl () {
command "$PERL_PATH" "$@"
}
+# Is the value one of the various ways to spell a boolean true/false?
+test_normalize_bool () {
+ git -c magic.variable="$1" config --bool magic.variable 2>/dev/null
+}
+
+# Given a variable $1, normalize the value of it to one of "true",
+# "false", or "auto" and store the result to it.
+#
+# test_tristate GIT_TEST_HTTPD
+#
+# A variable set to an empty string is set to 'false'.
+# A variable set to 'false' or 'auto' keeps its value.
+# Anything else is set to 'true'.
+# An unset variable defaults to 'auto'.
+#
+# The last rule is to allow people to set the variable to an empty
+# string and export it to decline testing the particular feature
+# for versions both before and after this change. We used to treat
+# both unset and empty variable as a signal for "do not test" and
+# took any non-empty string as "please test".
+
+test_tristate () {
+ if eval "test x\"\${$1+isset}\" = xisset"
+ then
+ # explicitly set
+ eval "
+ case \"\$$1\" in
+ '') $1=false ;;
+ auto) ;;
+ *) $1=\$(test_normalize_bool \$$1 || echo true) ;;
+ esac
+ "
+ else
+ eval "$1=auto"
+ fi
+}
+
+# Exit the test suite, either by skipping all remaining tests or by
+# exiting with an error. If "$1" is "auto", we then we assume we were
+# opportunistically trying to set up some tests and we skip. If it is
+# "true", then we report a failure.
+#
+# The error/skip message should be given by $2.
+#
+test_skip_or_die () {
+ case "$1" in
+ auto)
+ skip_all=$2
+ test_done
+ ;;
+ true)
+ error "$2"
+ ;;
+ *)
+ error "BUG: test tristate is '$1' (real error: $2)"
+ esac
+}
+
# The following mingw_* functions obey POSIX shell syntax, but are actually
# bash scripts, and are meant to be used only with bash on Windows.
diff --git a/t/test-lib.sh b/t/test-lib.sh
index b25249ec4c..cf19339cce 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+# Test framework for git. See t/README for usage.
#
# Copyright (c) 2005 Junio C Hamano
#
@@ -26,6 +26,10 @@ then
# outside of t/, e.g. for running tests on the test library
# itself.
TEST_DIRECTORY=$(pwd)
+else
+ # ensure that TEST_DIRECTORY is an absolute path so that it
+ # is valid even if the current working directory is changed
+ TEST_DIRECTORY=$(cd "$TEST_DIRECTORY" && pwd) || exit 1
fi
if test -z "$TEST_OUTPUT_DIRECTORY"
then
@@ -87,6 +91,7 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
VALGRIND
UNZIP
PERF_
+ CURL_VERBOSE
));
my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env);
print join("\n", @vars);
@@ -104,6 +109,16 @@ export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
export EDITOR
+# Tests using GIT_TRACE typically don't want <timestamp> <file>:<line> output
+GIT_TRACE_BARE=1
+export GIT_TRACE_BARE
+
+if test -n "${TEST_GIT_INDEX_VERSION:+isset}"
+then
+ GIT_INDEX_VERSION="$TEST_GIT_INDEX_VERSION"
+ export GIT_INDEX_VERSION
+fi
+
# Add libc MALLOC and MALLOC_PERTURB test
# only if we are not executing the test with valgrind
if expr " $GIT_TEST_OPTS " : ".* --valgrind " >/dev/null ||
@@ -181,6 +196,14 @@ do
immediate=t; shift ;;
-l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
GIT_TEST_LONG=t; export GIT_TEST_LONG; shift ;;
+ -r)
+ shift; test "$#" -ne 0 || {
+ echo 'error: -r requires an argument' >&2;
+ exit 1;
+ }
+ run_list=$1; shift ;;
+ --run=*)
+ run_list=$(expr "z$1" : 'z[^=]*=\(.*\)'); shift ;;
-h|--h|--he|--hel|--help)
help=t; shift ;;
-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
@@ -210,6 +233,10 @@ do
--root=*)
root=$(expr "z$1" : 'z[^=]*=\(.*\)')
shift ;;
+ -x)
+ trace=t
+ verbose=t
+ shift ;;
*)
echo "error: unknown test option '$1'" >&2; exit 1 ;;
esac
@@ -273,7 +300,7 @@ error "Test script did not set test_description."
if test "$help" = "t"
then
- echo "$test_description"
+ printf '%s\n' "$test_description"
exit 0
fi
@@ -324,7 +351,7 @@ test_failure_ () {
test_failure=$(($test_failure + 1))
say_color error "not ok $test_count - $1"
shift
- echo "$@" | sed -e 's/^/# /'
+ printf '%s\n' "$*" | sed -e 's/^/# /'
test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
}
@@ -356,6 +383,99 @@ match_pattern_list () {
return 1
}
+match_test_selector_list () {
+ title="$1"
+ shift
+ arg="$1"
+ shift
+ test -z "$1" && return 0
+
+ # Both commas and whitespace are accepted as separators.
+ OLDIFS=$IFS
+ IFS=' ,'
+ set -- $1
+ IFS=$OLDIFS
+
+ # If the first selector is negative we include by default.
+ include=
+ case "$1" in
+ !*) include=t ;;
+ esac
+
+ for selector
+ do
+ orig_selector=$selector
+
+ positive=t
+ case "$selector" in
+ !*)
+ positive=
+ selector=${selector##?}
+ ;;
+ esac
+
+ test -z "$selector" && continue
+
+ case "$selector" in
+ *-*)
+ if expr "z${selector%%-*}" : "z[0-9]*[^0-9]" >/dev/null
+ then
+ echo "error: $title: invalid non-numeric in range" \
+ "start: '$orig_selector'" >&2
+ exit 1
+ fi
+ if expr "z${selector#*-}" : "z[0-9]*[^0-9]" >/dev/null
+ then
+ echo "error: $title: invalid non-numeric in range" \
+ "end: '$orig_selector'" >&2
+ exit 1
+ fi
+ ;;
+ *)
+ if expr "z$selector" : "z[0-9]*[^0-9]" >/dev/null
+ then
+ echo "error: $title: invalid non-numeric in test" \
+ "selector: '$orig_selector'" >&2
+ exit 1
+ fi
+ esac
+
+ # Short cut for "obvious" cases
+ test -z "$include" && test -z "$positive" && continue
+ test -n "$include" && test -n "$positive" && continue
+
+ case "$selector" in
+ -*)
+ if test $arg -le ${selector#-}
+ then
+ include=$positive
+ fi
+ ;;
+ *-)
+ if test $arg -ge ${selector%-}
+ then
+ include=$positive
+ fi
+ ;;
+ *-*)
+ if test ${selector%%-*} -le $arg \
+ && test $arg -le ${selector#*-}
+ then
+ include=$positive
+ fi
+ ;;
+ *)
+ if test $arg -eq $selector
+ then
+ include=$positive
+ fi
+ ;;
+ esac
+ done
+
+ test -n "$include"
+}
+
maybe_teardown_verbose () {
test -z "$verbose_only" && return
exec 4>/dev/null 3>/dev/null
@@ -401,10 +521,39 @@ maybe_setup_valgrind () {
fi
}
+# This is a separate function because some tests use
+# "return" to end a test_expect_success block early
+# (and we want to make sure we run any cleanup like
+# "set +x").
+test_eval_inner_ () {
+ # Do not add anything extra (including LF) after '$*'
+ eval "
+ test \"$trace\" = t && set -x
+ $*"
+}
+
test_eval_ () {
- # This is a separate function because some tests use
- # "return" to end a test_expect_success block early.
- eval </dev/null >&3 2>&4 "$*"
+ # We run this block with stderr redirected to avoid extra cruft
+ # during a "-x" trace. Once in "set -x" mode, we cannot prevent
+ # the shell from printing the "set +x" to turn it off (nor the saving
+ # of $? before that). But we can make sure that the output goes to
+ # /dev/null.
+ #
+ # The test itself is run with stderr put back to &4 (so either to
+ # /dev/null, or to the original stderr if --verbose was used).
+ {
+ test_eval_inner_ "$@" </dev/null >&3 2>&4
+ test_eval_ret_=$?
+ if test "$trace" = t
+ then
+ set +x
+ if test "$test_eval_ret_" != 0
+ then
+ say_color error >&4 "error: last command exited with \$?=$test_eval_ret_"
+ fi
+ fi
+ } 2>/dev/null
+ return $test_eval_ret_
}
test_run_ () {
@@ -415,7 +564,8 @@ test_run_ () {
eval_ret=$?
teardown_malloc_check
- if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure"
+ if test -z "$immediate" || test $eval_ret = 0 ||
+ test -n "$expecting_failure" && test "$test_cleanup" != ":"
then
setup_malloc_check
test_eval_ "$test_cleanup"
@@ -442,25 +592,35 @@ test_finish_ () {
test_skip () {
to_skip=
+ skipped_reason=
if match_pattern_list $this_test.$test_count $GIT_SKIP_TESTS
then
to_skip=t
+ skipped_reason="GIT_SKIP_TESTS"
fi
if test -z "$to_skip" && test -n "$test_prereq" &&
! test_have_prereq "$test_prereq"
then
to_skip=t
- fi
- case "$to_skip" in
- t)
+
of_prereq=
if test "$missing_prereq" != "$test_prereq"
then
of_prereq=" of $test_prereq"
fi
+ skipped_reason="missing $missing_prereq${of_prereq}"
+ fi
+ if test -z "$to_skip" && test -n "$run_list" &&
+ ! match_test_selector_list '--run' $test_count "$run_list"
+ then
+ to_skip=t
+ skipped_reason="--run"
+ fi
+ case "$to_skip" in
+ t)
say_color skip >&3 "skipping test: $@"
- say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})"
+ say_color skip "ok $test_count # skip $1 ($skipped_reason)"
: true
;;
*)
@@ -477,8 +637,6 @@ test_at_end_hook_ () {
test_done () {
GIT_EXIT_OK=t
- # Note: t0000 relies on $HARNESS_ACTIVE disabling the .counts
- # output file
if test -z "$HARNESS_ACTIVE"
then
test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
@@ -573,11 +731,9 @@ then
make_valgrind_symlink () {
# handle only executables, unless they are shell libraries that
- # need to be in the exec-path. We will just use "#!" as a
- # guess for a shell-script, since we have no idea what the user
- # may have configured as the shell path.
+ # need to be in the exec-path.
test -x "$1" ||
- test "#!" = "$(head -c 2 <"$1")" ||
+ test "# " = "$(head -c 2 <"$1")" ||
return;
base=$(basename "$1")
@@ -649,7 +805,6 @@ else # normal case, use ../bin-wrappers only unless $with_dashes:
fi
fi
GIT_TEMPLATE_DIR="$GIT_BUILD_DIR"/templates/blt
-unset GIT_CONFIG
GIT_CONFIG_NOSYSTEM=1
GIT_ATTR_NOSYSTEM=1
export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM
@@ -692,7 +847,8 @@ rm -fr "$TRASH_DIRECTORY" || {
}
HOME="$TRASH_DIRECTORY"
-export HOME
+GNUPGHOME="$HOME/gnupg-home-not-used"
+export HOME GNUPGHOME
if test -z "$TEST_NO_CREATE_REPO"
then
@@ -749,7 +905,7 @@ case $(uname -s) in
# backslashes in pathspec are converted to '/'
# exec does not inherit the PID
test_set_prereq MINGW
- test_set_prereq NOT_CYGWIN
+ test_set_prereq NATIVE_CRLF
test_set_prereq SED_STRIPS_CR
test_set_prereq GREP_STRIPS_CR
GIT_TEST_CMP=mingw_test_cmp
@@ -757,7 +913,6 @@ case $(uname -s) in
*CYGWIN*)
test_set_prereq POSIXPERM
test_set_prereq EXECKEEPSPID
- test_set_prereq NOT_MINGW
test_set_prereq CYGWIN
test_set_prereq SED_STRIPS_CR
test_set_prereq GREP_STRIPS_CR
@@ -766,8 +921,6 @@ case $(uname -s) in
test_set_prereq POSIXPERM
test_set_prereq BSLASHPSPEC
test_set_prereq EXECKEEPSPID
- test_set_prereq NOT_MINGW
- test_set_prereq NOT_CYGWIN
;;
esac
@@ -830,6 +983,10 @@ test_lazy_prereq SYMLINKS '
ln -s x y && test -h y
'
+test_lazy_prereq FILEMODE '
+ test "$(git config --bool core.filemode)" = true
+'
+
test_lazy_prereq CASE_INSENSITIVE_FS '
echo good >CamelCase &&
echo bad >camelcase &&
@@ -855,6 +1012,14 @@ test_lazy_prereq AUTOIDENT '
git var GIT_AUTHOR_IDENT
'
+test_lazy_prereq EXPENSIVE '
+ test -n "$GIT_TEST_LONG"
+'
+
+test_lazy_prereq USR_BIN_TIME '
+ test -x /usr/bin/time
+'
+
# When the tests are run as root, permission tests will report that
# things are writable when they shouldn't be.
test -w / || test_set_prereq SANITY