summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/.gitattributes2
-rw-r--r--t/.gitignore3
-rw-r--r--t/Makefile23
-rw-r--r--t/README83
-rwxr-xr-xt/aggregate-results.sh34
-rw-r--r--t/annotate-tests.sh5
-rw-r--r--t/diff-lib.sh6
-rw-r--r--t/gitweb-lib.sh87
-rw-r--r--t/lib-cvs.sh75
-rw-r--r--t/lib-git-svn.sh70
-rw-r--r--t/lib-httpd.sh63
-rw-r--r--t/lib-httpd/apache.conf31
-rwxr-xr-xt/lib-patch-mode.sh41
-rw-r--r--t/lib-rebase.sh48
-rwxr-xr-xt/t0000-basic.sh80
-rwxr-xr-xt/t0001-init.sh161
-rwxr-xr-xt/t0002-gitfile.sh6
-rwxr-xr-xt/t0003-attributes.sh52
-rwxr-xr-xt/t0004-unwritable.sh27
-rwxr-xr-xt/t0005-signals.sh22
-rwxr-xr-xt/t0006-date.sh76
-rwxr-xr-xt/t0020-crlf.sh39
-rwxr-xr-xt/t0022-crlf-rename.sh4
-rwxr-xr-xt/t0023-crlf-am.sh2
-rwxr-xr-xt/t0024-crlf-archive.sh46
-rwxr-xr-xt/t0030-stripspace.sh156
-rwxr-xr-xt/t0040-parse-options.sh235
-rwxr-xr-xt/t0050-filesystem.sh66
-rwxr-xr-xt/t0055-beyond-symlinks.sh25
-rwxr-xr-xt/t0060-path-utils.sh142
-rwxr-xr-xt/t0070-fundamental.sh15
-rwxr-xr-xt/t0100-previous.sh49
-rwxr-xr-xt/t1000-read-tree-m-3way.sh4
-rwxr-xr-xt/t1001-read-tree-m-2way.sh83
-rwxr-xr-xt/t1002-read-tree-m-u-2way.sh24
-rwxr-xr-xt/t1004-read-tree-m-u-wf.sh6
-rwxr-xr-xt/t1005-read-tree-reset.sh60
-rwxr-xr-xt/t1006-cat-file.sh244
-rwxr-xr-xt/t1007-hash-object.sh181
-rwxr-xr-xt/t1008-read-tree-overlay.sh31
-rwxr-xr-xt/t1009-read-tree-new-index.sh25
-rwxr-xr-xt/t1010-mktree.sh71
-rwxr-xr-xt/t1020-subdirectory.sh24
-rwxr-xr-xt/t1100-commit-tree-options.sh2
-rwxr-xr-xt/t1200-tutorial.sh226
-rwxr-xr-xt/t1300-repo-config.sh85
-rwxr-xr-xt/t1301-shared-repo.sh98
-rwxr-xr-xt/t1302-repo-version.sh2
-rwxr-xr-xt/t1303-wacky-config.sh17
-rwxr-xr-xt/t1400-update-ref.sh71
-rwxr-xr-xt/t1401-symbolic-ref.sh36
-rwxr-xr-xt/t1402-check-ref-format.sh61
-rwxr-xr-xt/t1410-reflog.sh24
-rwxr-xr-xt/t1411-reflog-show.sh67
-rwxr-xr-xt/t1450-fsck.sh98
-rwxr-xr-xt/t1500-rev-parse.sh26
-rwxr-xr-xt/t1501-worktree.sh119
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh49
-rwxr-xr-xt/t1503-rev-parse-verify.sh107
-rwxr-xr-xt/t1504-ceiling-dirs.sh163
-rwxr-xr-xt/t1505-rev-parse-last.sh69
-rwxr-xr-xt/t2000-checkout-cache-clash.sh11
-rwxr-xr-xt/t2001-checkout-cache-clash.sh6
-rwxr-xr-xt/t2003-checkout-cache-mkdir.sh8
-rwxr-xr-xt/t2004-checkout-cache-temp.sh2
-rwxr-xr-xt/t2005-checkout-index-symlinks.sh4
-rwxr-xr-xt/t2007-checkout-symlink.sh6
-rwxr-xr-xt/t2010-checkout-ambiguous.sh50
-rwxr-xr-xt/t2011-checkout-invalid-head.sh22
-rwxr-xr-xt/t2012-checkout-last.sh94
-rwxr-xr-xt/t2013-checkout-submodule.sh42
-rwxr-xr-xt/t2014-switch.sh28
-rwxr-xr-xt/t2015-checkout-unborn.sh40
-rwxr-xr-xt/t2016-checkout-patch.sh107
-rwxr-xr-xt/t2050-git-dir-relative.sh4
-rwxr-xr-xt/t2100-update-cache-badpath.sh16
-rwxr-xr-xt/t2101-update-index-reupdate.sh2
-rwxr-xr-xt/t2102-update-index-symlinks.sh4
-rwxr-xr-xt/t2103-update-index-ignore-missing.sh89
-rwxr-xr-xt/t2200-add-update.sh81
-rwxr-xr-xt/t2201-add-update-typechange.sh26
-rwxr-xr-xt/t2202-add-addremove.sh44
-rwxr-xr-xt/t2203-add-intent.sh64
-rwxr-xr-xt/t2300-cd-to-toplevel.sh37
-rwxr-xr-xt/t3000-ls-files-others.sh25
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh21
-rwxr-xr-xt/t3002-ls-files-dashpath.sh10
-rwxr-xr-xt/t3003-ls-files-exclude.sh40
-rwxr-xr-xt/t3010-ls-files-killed-modified.sh21
-rwxr-xr-xt/t3020-ls-files-error-unmatch.sh4
-rwxr-xr-xt/t3030-merge-recursive.sh81
-rwxr-xr-xt/t3031-merge-criscross.sh95
-rwxr-xr-xt/t3040-subprojects-basic.sh4
-rwxr-xr-xt/t3050-subprojects-fetch.sh2
-rwxr-xr-xt/t3100-ls-tree-restrict.sh42
-rwxr-xr-xt/t3101-ls-tree-dirname.sh97
-rwxr-xr-xt/t3200-branch.sh276
-rwxr-xr-xt/t3202-show-branch-octopus.sh67
-rwxr-xr-xt/t3203-branch-output.sh81
-rwxr-xr-xt/t3210-pack-refs.sh15
-rwxr-xr-xt/t3300-funny-names.sh32
-rwxr-xr-xt/t3301-notes.sh209
-rwxr-xr-xt/t3302-notes-index-expensive.sh118
-rwxr-xr-xt/t3303-notes-subtrees.sh188
-rwxr-xr-xt/t3304-notes-mixed.sh172
-rwxr-xr-xt/t3400-rebase.sh94
-rwxr-xr-xt/t3401-rebase-partial.sh24
-rwxr-xr-xt/t3403-rebase-skip.sh10
-rwxr-xr-xt/t3404-rebase-interactive.sh231
-rwxr-xr-xt/t3406-rebase-message.sh23
-rwxr-xr-xt/t3407-rebase-abort.sh39
-rwxr-xr-xt/t3409-rebase-preserve-merges.sh95
-rwxr-xr-xt/t3410-rebase-preserve-dropped-merges.sh85
-rwxr-xr-xt/t3411-rebase-preserve-around-merges.sh74
-rwxr-xr-xt/t3412-rebase-root.sh280
-rwxr-xr-xt/t3413-rebase-hook.sh146
-rwxr-xr-xt/t3414-rebase-preserve-onto.sh80
-rwxr-xr-xt/t3500-cherry.sh15
-rwxr-xr-xt/t3501-revert-cherry-pick.sh2
-rwxr-xr-xt/t3502-cherry-pick-merge.sh12
-rwxr-xr-xt/t3503-cherry-pick-root.sh30
-rwxr-xr-xt/t3504-cherry-pick-rerere.sh45
-rwxr-xr-xt/t3505-cherry-pick-empty.sh33
-rwxr-xr-xt/t3600-rm.sh134
-rwxr-xr-xt/t3700-add.sh92
-rwxr-xr-xt/t3701-add-interactive.sh184
-rwxr-xr-xt/t3702-add-edit.sh121
-rwxr-xr-xt/t3800-mktag.sh16
-rwxr-xr-xt/t3900-i18n-commit.sh62
-rw-r--r--t/t3900/ISO8859-1.txt (renamed from t/t3900/ISO-8859-1.txt)0
-rw-r--r--t/t3900/eucJP.txt (renamed from t/t3900/EUCJP.txt)0
-rwxr-xr-xt/t3901-i18n-patch.sh84
-rwxr-xr-xt/t3902-quoted.sh8
-rwxr-xr-xt/t3903-stash.sh106
-rwxr-xr-xt/t3904-stash-patch.sh55
-rwxr-xr-xt/t4000-diff-format.sh2
-rwxr-xr-xt/t4001-diff-rename.sh2
-rwxr-xr-xt/t4002-diff-basic.sh24
-rwxr-xr-xt/t4003-diff-rename-1.sh6
-rwxr-xr-xt/t4004-diff-rename-symlink.sh8
-rwxr-xr-xt/t4005-diff-rename-2.sh6
-rwxr-xr-xt/t4006-diff-mode.sh21
-rwxr-xr-xt/t4007-rename-3.sh76
-rwxr-xr-xt/t4008-diff-break-rewrite.sh14
-rwxr-xr-xt/t4009-diff-rename-4.sh6
-rwxr-xr-xt/t4010-diff-pathspec.sh10
-rwxr-xr-xt/t4011-diff-symlink.sh15
-rwxr-xr-xt/t4012-diff-binary.sh31
-rwxr-xr-xt/t4013-diff-various.sh25
-rw-r--r--t/t4013/diff.diff_--dirstat_master~1_master~23
-rw-r--r--t/t4013/diff.diff_--name-status_dir2_dir1
-rw-r--r--t/t4013/diff.diff_--no-index_--name-status_--_dir2_dir3
-rw-r--r--t/t4013/diff.diff_--no-index_--name-status_dir2_dir3
-rw-r--r--t/t4013/diff.diff_--no-index_dir_dir32
-rw-r--r--t/t4013/diff.diff_master_master^_side29
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side61
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..master24
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..master^16
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..side6
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master170
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master24
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..master24
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..master^16
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..master^^6
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..side6
-rw-r--r--t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master127
-rw-r--r--t/t4013/diff.format-patch_--stdout_--numbered_initial..master127
-rw-r--r--t/t4013/diff.format-patch_--stdout_initial..master6
-rw-r--r--t/t4013/diff.format-patch_--stdout_initial..master^4
-rw-r--r--t/t4013/diff.log_--decorate=full_--all34
-rw-r--r--t/t4013/diff.log_--decorate_--all34
-rw-r--r--t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_2
-rw-r--r--t/t4013/diff.log_--patch-with-stat_master2
-rw-r--r--t/t4013/diff.log_--patch-with-stat_master_--_dir_2
-rw-r--r--t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master2
-rw-r--r--t/t4013/diff.log_--root_--patch-with-stat_--summary_master2
-rw-r--r--t/t4013/diff.log_--root_--patch-with-stat_master2
-rw-r--r--t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master2
-rw-r--r--t/t4013/diff.log_--root_-p_master2
-rw-r--r--t/t4013/diff.log_--root_master2
-rw-r--r--t/t4013/diff.log_-p_master2
-rw-r--r--t/t4013/diff.log_master2
-rw-r--r--t/t4013/diff.rev-list_--children_HEAD7
-rw-r--r--t/t4013/diff.rev-list_--parents_HEAD7
-rw-r--r--t/t4013/diff.show_master2
-rw-r--r--t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master2
-rw-r--r--t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master2
-rwxr-xr-xt/t4014-format-patch.sh417
-rwxr-xr-xt/t4015-diff-whitespace.sh117
-rwxr-xr-xt/t4016-diff-quote.sh22
-rwxr-xr-xt/t4017-diff-retval.sh22
-rwxr-xr-xt/t4018-diff-funcname.sh32
-rwxr-xr-xt/t4019-diff-wserror.sh95
-rwxr-xr-xt/t4020-diff-external.sh64
-rwxr-xr-xt/t4021-format-patch-numbered.sh28
-rwxr-xr-xt/t4022-diff-rewrite.sh4
-rwxr-xr-xt/t4023-diff-rename-typechange.sh20
-rwxr-xr-xt/t4026-color.sh17
-rwxr-xr-xt/t4027-diff-submodule.sh48
-rwxr-xr-xt/t4029-diff-trailing-space.sh39
-rwxr-xr-xt/t4030-diff-textconv.sh126
-rwxr-xr-xt/t4031-diff-rewrite-binary.sh67
-rwxr-xr-xt/t4032-diff-inter-hunk-context.sh92
-rwxr-xr-xt/t4033-diff-patience.sh168
-rwxr-xr-xt/t4034-diff-words.sh222
-rwxr-xr-xt/t4035-diff-quiet.sh (renamed from t/t4017-quiet.sh)0
-rwxr-xr-xt/t4036-format-patch-signer-mime.sh (renamed from t/t4021-format-patch-signer-mime.sh)0
-rwxr-xr-xt/t4037-diff-r-t-dirs.sh53
-rwxr-xr-xt/t4038-diff-combined.sh84
-rwxr-xr-xt/t4039-diff-assume-unchanged.sh31
-rwxr-xr-xt/t4041-diff-submodule.sh260
-rwxr-xr-xt/t4100-apply-stat.sh64
-rw-r--r--t/t4100/t-apply-8.expect2
-rw-r--r--t/t4100/t-apply-8.patch11
-rw-r--r--t/t4100/t-apply-9.expect2
-rw-r--r--t/t4100/t-apply-9.patch11
-rwxr-xr-xt/t4101-apply-nonl.sh7
-rwxr-xr-xt/t4102-apply-rename.sh8
-rwxr-xr-xt/t4103-apply-binary.sh42
-rwxr-xr-xt/t4104-apply-boundary.sh19
-rwxr-xr-xt/t4106-apply-stdin.sh26
-rwxr-xr-xt/t4107-apply-ignore-whitespace.sh185
-rwxr-xr-xt/t4109-apply-multifrag.sh179
-rw-r--r--t/t4109/expect-131
-rw-r--r--t/t4109/expect-223
-rw-r--r--t/t4109/expect-324
-rw-r--r--t/t4109/patch1.patch28
-rw-r--r--t/t4109/patch2.patch30
-rw-r--r--t/t4109/patch3.patch31
-rw-r--r--t/t4109/patch4.patch30
-rwxr-xr-xt/t4110-apply-scan.sh96
-rw-r--r--t/t4110/expect20
-rw-r--r--t/t4110/patch1.patch17
-rw-r--r--t/t4110/patch2.patch11
-rw-r--r--t/t4110/patch3.patch14
-rw-r--r--t/t4110/patch4.patch11
-rw-r--r--t/t4110/patch5.patch11
-rwxr-xr-xt/t4112-apply-renames.sh20
-rwxr-xr-xt/t4113-apply-ending.sh4
-rwxr-xr-xt/t4114-apply-typechange.sh24
-rwxr-xr-xt/t4115-apply-symlink.sh10
-rwxr-xr-xt/t4116-apply-reverse.sh6
-rwxr-xr-xt/t4117-apply-reject.sh12
-rwxr-xr-xt/t4118-apply-empty-context.sh10
-rwxr-xr-xt/t4119-apply-config.sh4
-rwxr-xr-xt/t4122-apply-symlink-inside.sh6
-rwxr-xr-xt/t4124-apply-ws-rule.sh115
-rwxr-xr-xt/t4126-apply-empty.sh57
-rwxr-xr-xt/t4127-apply-same-fn.sh90
-rwxr-xr-xt/t4128-apply-root.sh112
-rwxr-xr-xt/t4129-apply-samemode.sh69
-rwxr-xr-xt/t4130-apply-criss-cross-rename.sh66
-rwxr-xr-xt/t4131-apply-fake-ancestor.sh42
-rwxr-xr-xt/t4132-apply-removal.sh95
-rwxr-xr-xt/t4150-am-subdir.sh72
-rwxr-xr-xt/t4150-am.sh349
-rwxr-xr-xt/t4151-am-abort.sh65
-rwxr-xr-xt/t4200-rerere.sh64
-rwxr-xr-xt/t4201-shortlog.sh28
-rwxr-xr-xt/t4202-log.sh337
-rwxr-xr-xt/t4203-mailmap.sh215
-rwxr-xr-xt/t4204-patch-id.sh38
-rwxr-xr-xt/t4252-am-options.sh78
-rw-r--r--t/t4252/am-test-1-119
-rw-r--r--t/t4252/am-test-1-221
-rw-r--r--t/t4252/am-test-2-119
-rw-r--r--t/t4252/am-test-2-221
-rw-r--r--t/t4252/am-test-3-119
-rw-r--r--t/t4252/am-test-3-221
-rw-r--r--t/t4252/am-test-4-119
-rw-r--r--t/t4252/am-test-4-222
-rw-r--r--t/t4252/am-test-5-120
-rw-r--r--t/t4252/am-test-5-215
-rw-r--r--t/t4252/am-test-6-121
-rw-r--r--t/t4252/file-1-07
-rw-r--r--t/t4252/file-2-07
-rwxr-xr-xt/t5000-tar-tree.sh132
-rwxr-xr-xt/t5001-archive-attr.sh91
-rwxr-xr-xt/t5100-mailinfo.sh78
-rw-r--r--t/t5100/.gitattributes4
-rw-r--r--t/t5100/empty0
-rw-r--r--t/t5100/info-from.expect5
-rw-r--r--t/t5100/info-from.in8
-rw-r--r--t/t5100/info00012
-rw-r--r--t/t5100/info00105
-rw-r--r--t/t5100/info00115
-rw-r--r--t/t5100/info00125
-rw-r--r--t/t5100/info00135
-rw-r--r--t/t5100/info00145
-rw-r--r--t/t5100/info0014--scissors5
-rw-r--r--t/t5100/info00155
-rw-r--r--t/t5100/info0015--no-inbody-headers5
-rw-r--r--t/t5100/info00165
-rw-r--r--t/t5100/info0016--no-inbody-headers5
-rw-r--r--t/t5100/msg00105
-rw-r--r--t/t5100/msg00112
-rw-r--r--t/t5100/msg00127
-rw-r--r--t/t5100/msg00130
-rw-r--r--t/t5100/msg001418
-rw-r--r--t/t5100/msg0014--scissors4
-rw-r--r--t/t5100/msg00152
-rw-r--r--t/t5100/msg0015--no-inbody-headers3
-rw-r--r--t/t5100/msg00162
-rw-r--r--t/t5100/msg0016--no-inbody-headers4
-rw-r--r--t/t5100/nul-b64.expectbin0 -> 1672 bytes
-rw-r--r--t/t5100/nul-b64.in37
-rw-r--r--t/t5100/nul-plainbin0 -> 91 bytes
-rw-r--r--t/t5100/patch001020
-rw-r--r--t/t5100/patch001122
-rw-r--r--t/t5100/patch001230
-rw-r--r--t/t5100/patch00130
-rw-r--r--t/t5100/patch001464
-rw-r--r--t/t5100/patch0014--scissors64
-rw-r--r--t/t5100/patch00158
-rw-r--r--t/t5100/patch0015--no-inbody-headers8
-rw-r--r--t/t5100/patch00168
-rw-r--r--t/t5100/patch0016--no-inbody-headers8
-rw-r--r--t/t5100/rfc2047-info-00014
-rw-r--r--t/t5100/rfc2047-info-00024
-rw-r--r--t/t5100/rfc2047-info-00034
-rw-r--r--t/t5100/rfc2047-info-00044
-rw-r--r--t/t5100/rfc2047-info-00052
-rw-r--r--t/t5100/rfc2047-info-00062
-rw-r--r--t/t5100/rfc2047-info-00072
-rw-r--r--t/t5100/rfc2047-info-00082
-rw-r--r--t/t5100/rfc2047-info-00092
-rw-r--r--t/t5100/rfc2047-info-00102
-rw-r--r--t/t5100/rfc2047-info-00112
-rw-r--r--t/t5100/rfc2047-samples.mbox48
-rw-r--r--t/t5100/sample.mbox261
-rwxr-xr-xt/t5300-pack-object.sh63
-rwxr-xr-xt/t5301-sliding-window.sh4
-rwxr-xr-xt/t5302-pack-index.sh152
-rwxr-xr-xt/t5303-hash-object.sh35
-rwxr-xr-xt/t5303-pack-corruption-resilience.sh287
-rwxr-xr-x[-rw-r--r--]t/t5304-prune.sh78
-rwxr-xr-xt/t5305-include-tag.sh6
-rwxr-xr-xt/t5306-pack-nobase.sh80
-rwxr-xr-xt/t5307-pack-missing-commit.sh39
-rwxr-xr-xt/t5400-send-pack.sh186
-rwxr-xr-xt/t5401-update-hooks.sh15
-rwxr-xr-xt/t5402-post-merge-hook.sh4
-rwxr-xr-xt/t5403-post-checkout-hook.sh40
-rwxr-xr-xt/t5404-tracking-branches.sh11
-rwxr-xr-xt/t5405-send-pack-rewind.sh2
-rwxr-xr-xt/t5406-remote-rejects.sh2
-rwxr-xr-xt/t5500-fetch-pack.sh315
-rwxr-xr-xt/t5502-quickfetch.sh20
-rwxr-xr-xt/t5503-tagfollow.sh14
-rwxr-xr-xt/t5505-remote.sh319
-rwxr-xr-xt/t5506-remote-groups.sh98
-rwxr-xr-xt/t5510-fetch.sh117
-rwxr-xr-xt/t5511-refspec.sh17
-rwxr-xr-xt/t5512-ls-remote.sh2
-rwxr-xr-xt/t5513-fetch-track.sh30
-rwxr-xr-xt/t5514-fetch-multiple.sh154
-rwxr-xr-xt/t5515-fetch-merge-logic.sh20
-rwxr-xr-xt/t5516-fetch-push.sh253
-rwxr-xr-xt/t5518-fetch-exit-status.sh37
-rwxr-xr-xt/t5519-push-alternates.sh143
-rwxr-xr-xt/t5520-pull.sh68
-rwxr-xr-xt/t5521-pull-options.sh60
-rwxr-xr-xt/t5522-pull-symlink.sh84
-rwxr-xr-xt/t5530-upload-pack-error.sh27
-rwxr-xr-xt/t5531-deep-submodule-push.sh35
-rwxr-xr-xt/t5540-http-push.sh105
-rwxr-xr-xt/t5541-http-push.sh92
-rwxr-xr-xt/t5550-http-fetch.sh71
-rwxr-xr-xt/t5551-http-fetch.sh105
-rwxr-xr-xt/t5560-http-backend.sh260
-rwxr-xr-xt/t5600-clone-fail-cleanup.sh12
-rwxr-xr-xt/t5601-clone.sh155
-rwxr-xr-xt/t5602-clone-remote-exec.sh26
-rwxr-xr-xt/t5700-clone-reference.sh35
-rwxr-xr-xt/t5701-clone-local.sh30
-rwxr-xr-xt/t5702-clone-options.sh13
-rwxr-xr-xt/t5704-bundle.sh33
-rwxr-xr-xt/t5705-clone-2gb.sh45
-rwxr-xr-xt/t5706-clone-branch.sh68
-rwxr-xr-xt/t5710-info-alternate.sh4
-rwxr-xr-xt/t6000lib.sh9
-rwxr-xr-xt/t6002-rev-list-bisect.sh2
-rwxr-xr-xt/t6003-rev-list-topo-order.sh2
-rwxr-xr-xt/t6006-rev-list-format.sh63
-rwxr-xr-xt/t6008-rev-list-submodule.sh2
-rwxr-xr-xt/t6010-merge-base.sh75
-rwxr-xr-xt/t6011-rev-list-with-bad-commit.sh60
-rwxr-xr-xt/t6012-rev-list-simplify.sh93
-rwxr-xr-xt/t6013-rev-list-reverse-parents.sh42
-rwxr-xr-xt/t6014-rev-list-all.sh38
-rwxr-xr-xt/t6015-rev-list-show-all-parents.sh31
-rwxr-xr-xt/t6016-rev-list-graph-simplify-history.sh276
-rwxr-xr-xt/t6017-rev-list-stdin.sh61
-rwxr-xr-xt/t6020-merge-df.sh23
-rwxr-xr-xt/t6021-merge-criss-cross.sh4
-rwxr-xr-xt/t6023-merge-file.sh76
-rwxr-xr-xt/t6024-recursive-merge.sh42
-rwxr-xr-xt/t6025-merge-symlinks.sh32
-rwxr-xr-xt/t6026-merge-attr.sh34
-rwxr-xr-xt/t6027-merge-binary.sh2
-rwxr-xr-xt/t6028-merge-up-to-date.sh2
-rwxr-xr-xt/t6029-merge-subtree.sh4
-rwxr-xr-xt/t6030-bisect-porcelain.sh303
-rwxr-xr-xt/t6031-merge-recursive.sh19
-rwxr-xr-xt/t6032-merge-large-rename.sh73
-rwxr-xr-xt/t6033-merge-crlf.sh52
-rwxr-xr-xt/t6034-merge-rename-nocruft.sh (renamed from t/t6023-merge-rename-nocruft.sh)0
-rwxr-xr-xt/t6035-merge-dir-to-symlink.sh93
-rwxr-xr-xt/t6036-recursive-corner-cases.sh55
-rwxr-xr-xt/t6040-tracking-info.sh92
-rwxr-xr-xt/t6050-replace.sh224
-rwxr-xr-xt/t6101-rev-parse-parents.sh6
-rwxr-xr-xt/t6120-describe.sh92
-rwxr-xr-xt/t6200-fmt-merge-msg.sh102
-rwxr-xr-xt/t6300-for-each-ref.sh223
-rwxr-xr-xt/t7001-mv.sh107
-rwxr-xr-xt/t7002-grep.sh317
-rwxr-xr-xt/t7003-filter-branch.sh105
-rwxr-xr-xt/t7004-tag.sh804
-rwxr-xr-xt/t7005-editor.sh76
-rwxr-xr-xt/t7007-show.sh20
-rwxr-xr-xt/t7010-setup.sh2
-rwxr-xr-xt/t7060-wtstatus.sh58
-rwxr-xr-xt/t7101-reset.sh18
-rwxr-xr-xt/t7102-reset.sh128
-rwxr-xr-xt/t7103-reset-bare.sh40
-rwxr-xr-xt/t7105-reset-patch.sh69
-rwxr-xr-xt/t7201-co.sh219
-rwxr-xr-xt/t7300-clean.sh123
-rwxr-xr-xt/t7400-submodule-basic.sh176
-rwxr-xr-xt/t7401-submodule-summary.sh24
-rwxr-xr-xt/t7402-submodule-rebase.sh92
-rwxr-xr-xt/t7403-submodule-sync.sh64
-rwxr-xr-xt/t7405-submodule-merge.sh74
-rwxr-xr-xt/t7406-submodule-update.sh198
-rwxr-xr-xt/t7407-submodule-foreach.sh237
-rwxr-xr-xt/t7408-submodule-reference.sh81
-rwxr-xr-xt/t7500-commit.sh87
-rwxr-xr-xt/t7501-commit.sh133
-rwxr-xr-xt/t7502-commit.sh122
-rwxr-xr-xt/t7503-pre-commit-hook.sh6
-rwxr-xr-xt/t7504-commit-msg-hook.sh33
-rwxr-xr-xt/t7505-prepare-commit-msg-hook.sh19
-rwxr-xr-xt/t7506-status-submodule.sh38
-rwxr-xr-xt/t7507-commit-verbose.sh73
-rwxr-xr-xt/t7508-status.sh (renamed from t/t7502-status.sh)122
-rwxr-xr-xt/t7509-commit.sh114
-rwxr-xr-xt/t7600-merge.sh232
-rwxr-xr-xt/t7601-merge-pull-config.sh156
-rwxr-xr-xt/t7602-merge-octopus-many.sh103
-rwxr-xr-xt/t7603-merge-reduce-heads.sh116
-rwxr-xr-xt/t7604-merge-custom-message.sh34
-rwxr-xr-xt/t7605-merge-resolve.sh48
-rwxr-xr-xt/t7606-merge-custom.sh49
-rwxr-xr-xt/t7607-merge-overwrite.sh87
-rwxr-xr-xt/t7608-merge-messages.sh60
-rwxr-xr-x[-rw-r--r--]t/t7610-mergetool.sh79
-rwxr-xr-xt/t7700-repack.sh165
-rwxr-xr-xt/t7701-repack-unpack-unreachable.sh93
-rwxr-xr-xt/t7800-difftool.sh216
-rwxr-xr-xt/t8001-annotate.sh2
-rwxr-xr-xt/t8002-blame.sh2
-rwxr-xr-xt/t8003-blame.sh28
-rwxr-xr-xt/t8005-blame-i18n.sh92
-rw-r--r--t/t8005/euc-japan.txt2
-rw-r--r--t/t8005/sjis.txt2
-rw-r--r--t/t8005/utf8.txt2
-rwxr-xr-xt/t9001-send-email.sh724
-rwxr-xr-xt/t9100-git-svn-basic.sh257
-rwxr-xr-xt/t9101-git-svn-props.sh113
-rwxr-xr-xt/t9102-git-svn-deep-rmdir.sh28
-rwxr-xr-xt/t9103-git-svn-tracked-directory-removed.sh22
-rwxr-xr-xt/t9104-git-svn-follow-parent.sh256
-rwxr-xr-xt/t9105-git-svn-commit-diff.sh36
-rwxr-xr-xt/t9106-git-svn-commit-diff-clobber.sh78
-rwxr-xr-xt/t9107-git-svn-migrate.sh152
-rwxr-xr-xt/t9108-git-svn-glob.sh129
-rwxr-xr-xt/t9109-git-svn-multi-glob.sh160
-rwxr-xr-xt/t9110-git-svn-use-svm-props.sh45
-rwxr-xr-xt/t9111-git-svn-use-svnsync-props.sh34
-rwxr-xr-xt/t9112-git-svn-md5less-file.sh6
-rwxr-xr-xt/t9113-git-svn-dcommit-new-file.sh19
-rwxr-xr-xt/t9114-git-svn-dcommit-merge.sh26
-rwxr-xr-xt/t9115-git-svn-dcommit-funky-renames.sh53
-rwxr-xr-xt/t9116-git-svn-log.sh16
-rwxr-xr-xt/t9117-git-svn-init-clone.sh32
-rwxr-xr-xt/t9118-git-svn-funky-branch-names.sh42
-rwxr-xr-xt/t9119-git-svn-info.sh257
-rwxr-xr-xt/t9120-git-svn-clone-with-percent-escapes.sh79
-rwxr-xr-xt/t9121-git-svn-fetch-renamed-dir.sh14
-rwxr-xr-xt/t9122-git-svn-author.sh84
-rwxr-xr-xt/t9123-git-svn-rebuild-with-rewriteroot.sh32
-rwxr-xr-xt/t9124-git-svn-dcommit-auto-props.sh101
-rwxr-xr-xt/t9125-git-svn-multi-glob-branch-names.sh37
-rwxr-xr-xt/t9126-git-svn-follow-deleted-readded-directory.sh22
-rw-r--r--t/t9126/follow-deleted-readded.dump201
-rwxr-xr-xt/t9127-git-svn-partial-rebuild.sh59
-rwxr-xr-xt/t9128-git-svn-cmd-branch.sh78
-rwxr-xr-xt/t9129-git-svn-i18n-commitencoding.sh95
-rwxr-xr-xt/t9130-git-svn-authors-file.sh117
-rwxr-xr-xt/t9131-git-svn-empty-symlink.sh110
-rwxr-xr-xt/t9132-git-svn-broken-symlink.sh102
-rwxr-xr-xt/t9133-git-svn-nested-git-repo.sh101
-rwxr-xr-xt/t9134-git-svn-ignore-paths.sh147
-rwxr-xr-xt/t9135-git-svn-moved-branch-empty-file.sh21
-rw-r--r--t/t9135/svn.dump192
-rwxr-xr-xt/t9136-git-svn-recreated-branch-empty-file.sh12
-rw-r--r--t/t9136/svn.dump192
-rwxr-xr-xt/t9137-git-svn-dcommit-clobber-series.sh (renamed from t/t9106-git-svn-dcommit-clobber-series.sh)40
-rwxr-xr-xt/t9138-git-svn-authors-prog.sh83
-rwxr-xr-xt/t9139-git-svn-non-utf8-commitencoding.sh47
-rwxr-xr-xt/t9140-git-svn-reset.sh66
-rwxr-xr-xt/t9141-git-svn-multiple-branches.sh122
-rwxr-xr-xt/t9142-git-svn-shallow-clone.sh32
-rwxr-xr-xt/t9143-git-svn-gc.sh53
-rwxr-xr-xt/t9144-git-svn-old-rev_map.sh31
-rwxr-xr-xt/t9145-git-svn-master-branch.sh25
-rwxr-xr-xt/t9146-git-svn-empty-dirs.sh142
-rwxr-xr-xt/t9150-svk-mergetickets.sh24
-rw-r--r--t/t9150/make-svk-dump57
-rw-r--r--t/t9150/svk-merge.dump616
-rwxr-xr-xt/t9151-svn-mergeinfo.sh41
-rw-r--r--t/t9151/.gitignore2
-rw-r--r--t/t9151/make-svnmerge-dump161
-rw-r--r--t/t9151/svn-mergeinfo.dump1625
-rwxr-xr-xt/t9152-svn-empty-dirs-after-gc.sh40
-rwxr-xr-xt/t9200-git-cvsexportcommit.sh91
-rwxr-xr-xt/t9300-fast-import.sh438
-rwxr-xr-xt/t9301-fast-export.sh265
-rwxr-xr-xt/t9400-git-cvsserver-server.sh65
-rwxr-xr-xt/t9401-git-cvsserver-crlf.sh340
-rwxr-xr-xt/t9500-gitweb-standalone-no-errors.sh174
-rwxr-xr-xt/t9501-gitweb-standalone-http-status.sh117
-rwxr-xr-xt/t9502-gitweb-standalone-parse-output.sh115
-rwxr-xr-xt/t9600-cvsimport.sh61
-rwxr-xr-xt/t9601-cvsimport-vendor-branch.sh86
-rw-r--r--t/t9601/cvsroot/.gitattributes1
-rw-r--r--t/t9601/cvsroot/CVSROOT/.gitignore2
-rw-r--r--t/t9601/cvsroot/module/added-imported.txt,v44
-rw-r--r--t/t9601/cvsroot/module/imported-anonymously.txt,v42
-rw-r--r--t/t9601/cvsroot/module/imported-modified-imported.txt,v76
-rw-r--r--t/t9601/cvsroot/module/imported-modified.txt,v59
-rw-r--r--t/t9601/cvsroot/module/imported-once.txt,v43
-rw-r--r--t/t9601/cvsroot/module/imported-twice.txt,v60
-rwxr-xr-xt/t9602-cvsimport-branches-tags.sh79
-rw-r--r--t/t9602/README62
-rw-r--r--t/t9602/cvsroot/.gitattributes1
-rw-r--r--t/t9602/cvsroot/CVSROOT/.gitignore2
-rw-r--r--t/t9602/cvsroot/module/default,v102
-rw-r--r--t/t9602/cvsroot/module/sub1/default,v102
-rw-r--r--t/t9602/cvsroot/module/sub1/subsubA/default,v101
-rw-r--r--t/t9602/cvsroot/module/sub1/subsubB/default,v107
-rw-r--r--t/t9602/cvsroot/module/sub2/Attic/branch_B_MIXED_only,v59
-rw-r--r--t/t9602/cvsroot/module/sub2/default,v102
-rw-r--r--t/t9602/cvsroot/module/sub2/subsubA/default,v102
-rw-r--r--t/t9602/cvsroot/module/sub3/default,v102
-rwxr-xr-xt/t9603-cvsimport-patchsets.sh40
-rw-r--r--t/t9603/cvsroot/.gitattributes1
-rw-r--r--t/t9603/cvsroot/CVSROOT/.gitignore2
-rw-r--r--t/t9603/cvsroot/module/a,v74
-rw-r--r--t/t9603/cvsroot/module/b,v90
-rwxr-xr-xt/t9700-perl-git.sh53
-rwxr-xr-xt/t9700/test.pl107
-rw-r--r--t/test-lib.sh396
-rw-r--r--t/valgrind/.gitignore2
-rwxr-xr-xt/valgrind/analyze.sh123
-rw-r--r--t/valgrind/default.supp45
-rwxr-xr-xt/valgrind/valgrind.sh22
568 files changed, 34736 insertions, 3865 deletions
diff --git a/t/.gitattributes b/t/.gitattributes
index 562b12e16e..1b97c5465b 100644
--- a/t/.gitattributes
+++ b/t/.gitattributes
@@ -1 +1 @@
-* -whitespace
+t[0-9][0-9][0-9][0-9]/* -whitespace
diff --git a/t/.gitignore b/t/.gitignore
index fad67c097b..7dcbb232cd 100644
--- a/t/.gitignore
+++ b/t/.gitignore
@@ -1 +1,2 @@
-trash
+/trash directory*
+/test-results
diff --git a/t/Makefile b/t/Makefile
index 72d7884232..bd09390d32 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -3,6 +3,8 @@
# Copyright (c) 2005 Junio C Hamano
#
+-include ../config.mak
+
#GIT_TEST_OPTS=--verbose --debug
SHELL_PATH ?= $(SHELL)
TAR ?= $(TAR)
@@ -14,18 +16,31 @@ SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
TSVN = $(wildcard t91[0-9][0-9]-*.sh)
-all: $(T) clean
+all: pre-clean
+ $(MAKE) aggregate-results-and-cleanup
$(T):
@echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
+pre-clean:
+ $(RM) -r test-results
+
clean:
- $(RM) -r trash
+ $(RM) -r 'trash directory'.* test-results
+
+aggregate-results-and-cleanup: $(T)
+ $(MAKE) aggregate-results
+ $(MAKE) clean
+
+aggregate-results:
+ '$(SHELL_PATH_SQ)' ./aggregate-results.sh test-results/t*-*
# we can test NO_OPTIMIZE_COMMITS independently of LC_ALL
full-svn-test:
$(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=1 LC_ALL=C
$(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=0 LC_ALL=en_US.UTF-8
-.PHONY: $(T) clean
-.NOTPARALLEL:
+valgrind:
+ GIT_TEST_OPTS=--valgrind $(MAKE)
+
+.PHONY: pre-clean $(T) aggregate-results clean valgrind
diff --git a/t/README b/t/README
index 73ed11bfe2..4e1d7dd183 100644
--- a/t/README
+++ b/t/README
@@ -39,7 +39,8 @@ this:
* passed all 3 test(s)
You can pass --verbose (or -v), --debug (or -d), and --immediate
-(or -i) command line argument to the test.
+(or -i) command line argument to the test, or by setting GIT_TEST_OPTS
+appropriately before running "make".
--verbose::
This makes the test more verbose. Specifically, the
@@ -54,6 +55,66 @@ You can pass --verbose (or -v), --debug (or -d), and --immediate
This causes the test to immediately exit upon the first
failed test.
+--long-tests::
+ This causes additional long-running tests to be run (where
+ available), for more exhaustive testing.
+
+--valgrind::
+ Execute all Git binaries with valgrind and exit with status
+ 126 on errors (just like regular tests, this will only stop
+ the test script when running under -i). Valgrind errors
+ go to stderr, so you might want to pass the -v option, too.
+
+ Since it makes no sense to run the tests with --valgrind and
+ not see any output, this option implies --verbose. For
+ convenience, it also implies --tee.
+
+--tee::
+ In addition to printing the test output to the terminal,
+ write it to files named 't/test-results/$TEST_NAME.out'.
+ As the names depend on the tests' file names, it is safe to
+ run the tests with this option in parallel.
+
+You can also set the GIT_TEST_INSTALLED environment variable to
+the bindir of an existing git installation to test that installation.
+You still need to have built this git sandbox, from which various
+test-* support programs, templates, and perl libraries are used.
+If your installed git is incomplete, it will silently test parts of
+your built version instead.
+
+When using GIT_TEST_INSTALLED, you can also set GIT_TEST_EXEC_PATH to
+override the location of the dashed-form subcommands (what
+GIT_EXEC_PATH would be used for during normal operation).
+GIT_TEST_EXEC_PATH defaults to `$GIT_TEST_INSTALLED/git --exec-path`.
+
+
+Skipping Tests
+--------------
+
+In some environments, certain tests have no way of succeeding
+due to platform limitation, such as lack of 'unzip' program, or
+filesystem that do not allow arbitrary sequence of non-NUL bytes
+as pathnames.
+
+You should be able to say something like
+
+ $ GIT_SKIP_TESTS=t9200.8 sh ./t9200-git-cvsexport-commit.sh
+
+and even:
+
+ $ GIT_SKIP_TESTS='t[0-4]??? t91?? t9200.8' make
+
+to omit such tests. The value of the environment variable is a
+SP separated list of patterns that tells which tests to skip,
+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.
+
Naming Tests
------------
@@ -123,7 +184,7 @@ This test harness library does the following things:
(or -h), it shows the test_description and exits.
- Creates an empty test directory with an empty .git/objects
- database and chdir(2) into it. This directory is 't/trash'
+ database and chdir(2) into it. This directory is 't/trash directory'
if you must know, but I do not think you care.
- Defines standard test helper functions for your scripts to
@@ -180,6 +241,24 @@ library for your script to use.
is to summarize successes and failures in the test script and
exit with an appropriate error code.
+ - test_tick
+
+ Make commit and tag names consistent by setting the author and
+ committer times to defined stated. Subsequent calls will
+ advance the times by a fixed amount.
+
+ - test_commit <message> [<filename> [<contents>]]
+
+ Creates a commit with the given message, committing the given
+ file with the given contents (default for both is to reuse the
+ message string), and adds a tag (again reusing the message
+ string as name). Calls test_tick to make the SHA-1s
+ reproducible.
+
+ - test_merge <message> <commit-or-tag>
+
+ Merges the given rev using the given message. Like test_commit,
+ creates a tag and calls test_tick before committing.
Tips for Writing Tests
----------------------
diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh
new file mode 100755
index 0000000000..d5bab75d7d
--- /dev/null
+++ b/t/aggregate-results.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+fixed=0
+success=0
+failed=0
+broken=0
+total=0
+
+for file
+do
+ while read type value
+ do
+ case $type in
+ '')
+ continue ;;
+ fixed)
+ fixed=$(($fixed + $value)) ;;
+ success)
+ success=$(($success + $value)) ;;
+ failed)
+ failed=$(($failed + $value)) ;;
+ broken)
+ broken=$(($broken + $value)) ;;
+ total)
+ total=$(($total + $value)) ;;
+ esac
+ done <"$file"
+done
+
+printf "%-8s%d\n" fixed $fixed
+printf "%-8s%d\n" success $success
+printf "%-8s%d\n" failed $failed
+printf "%-8s%d\n" broken $broken
+printf "%-8s%d\n" total $total
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index cacb273aff..396b9653a3 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -114,7 +114,10 @@ test_expect_success \
test_expect_success \
'some edit' \
'mv file file.orig &&
- sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/d" < file.orig > file &&
+ {
+ cat file.orig &&
+ echo
+ } | sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/d" > file &&
echo "incomplete" | tr -d "\\012" >>file &&
GIT_AUTHOR_NAME="D" git commit -a -m "edit"'
diff --git a/t/diff-lib.sh b/t/diff-lib.sh
index 28b941c493..4bddeb591e 100644
--- a/t/diff-lib.sh
+++ b/t/diff-lib.sh
@@ -11,7 +11,7 @@ compare_diff_raw () {
sed -e "$sanitize_diff_raw" <"$1" >.tmp-1
sed -e "$sanitize_diff_raw" <"$2" >.tmp-2
- git diff .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
+ test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
}
sanitize_diff_raw_z='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]*$/ X X \1#/'
@@ -23,7 +23,7 @@ compare_diff_raw_z () {
perl -pe 'y/\000/\012/' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1
perl -pe 'y/\000/\012/' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2
- git diff .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
+ test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
}
compare_diff_patch () {
@@ -37,5 +37,5 @@ compare_diff_patch () {
/^[dis]*imilarity index [0-9]*%$/d
/^index [0-9a-f]*\.\.[0-9a-f]/d
' <"$2" >.tmp-2
- git diff .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
+ test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
}
diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh
new file mode 100644
index 0000000000..76d8b7b803
--- /dev/null
+++ b/t/gitweb-lib.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Jakub Narebski
+#
+
+gitweb_init () {
+ safe_pwd="$(perl -MPOSIX=getcwd -e 'print quotemeta(getcwd)')"
+ cat >gitweb_config.perl <<EOF
+#!/usr/bin/perl
+
+# gitweb configuration for tests
+
+our \$version = 'current';
+our \$GIT = 'git';
+our \$projectroot = "$safe_pwd";
+our \$project_maxdepth = 8;
+our \$home_link_str = 'projects';
+our \$site_name = '[localhost]';
+our \$site_header = '';
+our \$site_footer = '';
+our \$home_text = 'indextext.html';
+our @stylesheets = ('file:///$TEST_DIRECTORY/../gitweb/gitweb.css');
+our \$logo = 'file:///$TEST_DIRECTORY/../gitweb/git-logo.png';
+our \$favicon = 'file:///$TEST_DIRECTORY/../gitweb/git-favicon.png';
+our \$projects_list = '';
+our \$export_ok = '';
+our \$strict_export = '';
+
+EOF
+
+ cat >.git/description <<EOF
+$0 test repository
+EOF
+}
+
+gitweb_run () {
+ GATEWAY_INTERFACE='CGI/1.1'
+ HTTP_ACCEPT='*/*'
+ REQUEST_METHOD='GET'
+ SCRIPT_NAME="$TEST_DIRECTORY/../gitweb/gitweb.perl"
+ QUERY_STRING=""$1""
+ PATH_INFO=""$2""
+ export GATEWAY_INTERFACE HTTP_ACCEPT REQUEST_METHOD \
+ SCRIPT_NAME QUERY_STRING PATH_INFO
+
+ GITWEB_CONFIG=$(pwd)/gitweb_config.perl
+ export GITWEB_CONFIG
+
+ # some of git commands write to STDERR on error, but this is not
+ # written to web server logs, so we are not interested in that:
+ # we are interested only in properly formatted errors/warnings
+ rm -f gitweb.log &&
+ perl -- "$SCRIPT_NAME" \
+ >gitweb.output 2>gitweb.log &&
+ perl -w -e '
+ open O, ">gitweb.headers";
+ while (<>) {
+ print O;
+ last if (/^\r$/ || /^$/);
+ }
+ open O, ">gitweb.body";
+ while (<>) {
+ print O;
+ }
+ close O;
+ ' gitweb.output &&
+ if grep '^[[]' gitweb.log >/dev/null 2>&1; then false; else true; fi
+
+ # gitweb.log is left for debugging
+ # gitweb.output is used to parse HTTP output
+ # gitweb.headers contains only HTTP headers
+ # gitweb.body contains body of message, without headers
+}
+
+. ./test-lib.sh
+
+if ! test_have_prereq PERL; then
+ say 'skipping gitweb tests, perl not available'
+ test_done
+fi
+
+perl -MEncode -e 'decode_utf8("", Encode::FB_CROAK)' >/dev/null 2>&1 || {
+ say 'skipping gitweb tests, perl version is too old'
+ test_done
+}
+
+gitweb_init
diff --git a/t/lib-cvs.sh b/t/lib-cvs.sh
new file mode 100644
index 0000000000..4b3b793730
--- /dev/null
+++ b/t/lib-cvs.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+. ./test-lib.sh
+
+unset CVS_SERVER
+# for clean cvsps cache
+HOME=$(pwd)
+export HOME
+
+if ! type cvs >/dev/null 2>&1
+then
+ say 'skipping cvsimport tests, cvs not found'
+ test_done
+fi
+
+CVS="cvs -f"
+export CVS
+
+cvsps_version=`cvsps -h 2>&1 | sed -ne 's/cvsps version //p'`
+case "$cvsps_version" in
+2.1 | 2.2*)
+ ;;
+'')
+ say 'skipping cvsimport tests, cvsps not found'
+ test_done
+ ;;
+*)
+ say 'skipping cvsimport tests, unsupported cvsps version'
+ test_done
+ ;;
+esac
+
+test_cvs_co () {
+ # Usage: test_cvs_co BRANCH_NAME
+ rm -rf module-cvs-"$1"
+ if [ "$1" = "master" ]
+ then
+ $CVS co -P -d module-cvs-"$1" -A module
+ else
+ $CVS co -P -d module-cvs-"$1" -r "$1" module
+ fi
+}
+
+test_git_co () {
+ # Usage: test_git_co BRANCH_NAME
+ (cd module-git && git checkout "$1")
+}
+
+test_cmp_branch_file () {
+ # Usage: test_cmp_branch_file BRANCH_NAME PATH
+ # The branch must already be checked out of CVS and git.
+ test_cmp module-cvs-"$1"/"$2" module-git/"$2"
+}
+
+test_cmp_branch_tree () {
+ # Usage: test_cmp_branch_tree BRANCH_NAME
+ # Check BRANCH_NAME out of CVS and git and make sure that all
+ # of the files and directories are identical.
+
+ test_cvs_co "$1" &&
+ test_git_co "$1" &&
+ (
+ cd module-cvs-"$1"
+ find . -type d -name CVS -prune -o -type f -print
+ ) | sort >module-cvs-"$1".list &&
+ (
+ cd module-git
+ find . -type d -name .git -prune -o -type f -print
+ ) | sort >module-git-"$1".list &&
+ test_cmp module-cvs-"$1".list module-git-"$1".list &&
+ cat module-cvs-"$1".list | while read f
+ do
+ test_cmp_branch_file "$1" "$f" || return 1
+ done
+}
diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh
index 9decd2e1e8..0f7f35ccc9 100644
--- a/t/lib-git-svn.sh
+++ b/t/lib-git-svn.sh
@@ -1,31 +1,40 @@
. ./test-lib.sh
+remotes_git_svn=remotes/git""-svn
+git_svn_id=git""-svn-id
+
if test -n "$NO_SVN_TESTS"
then
- test_expect_success 'skipping git-svn tests, NO_SVN_TESTS defined' :
+ say 'skipping git svn tests, NO_SVN_TESTS defined'
+ test_done
+fi
+if ! test_have_prereq PERL; then
+ say 'skipping git svn tests, perl not available'
test_done
- exit
fi
GIT_DIR=$PWD/.git
-GIT_SVN_DIR=$GIT_DIR/svn/git-svn
+GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn
SVN_TREE=$GIT_SVN_DIR/svn-tree
+PERL=${PERL:-perl}
svn >/dev/null 2>&1
if test $? -ne 1
then
- test_expect_success 'skipping git-svn tests, svn not found' :
+ say 'skipping git svn tests, svn not found'
test_done
- exit
fi
svnrepo=$PWD/svnrepo
+export svnrepo
+svnconf=$PWD/svnconf
+export svnconf
-perl -w -e "
+$PERL -w -e "
use SVN::Core;
use SVN::Repos;
\$SVN::Core::VERSION gt '1.1.0' or exit(42);
-system(qw/svnadmin create --fs-type fsfs/, '$svnrepo') == 0 or exit(41);
+system(qw/svnadmin create --fs-type fsfs/, \$ENV{svnrepo}) == 0 or exit(41);
" >&3 2>&4
x=$?
if test $x -ne 0
@@ -37,9 +46,8 @@ then
else
err='Perl SVN libraries not found or unusable, skipping test'
fi
- test_expect_success "$err" :
+ say "$err"
test_done
- exit
fi
rawsvnrepo="$svnrepo"
@@ -49,6 +57,19 @@ poke() {
test-chmtime +1 "$1"
}
+# We need this, because we should pass empty configuration directory to
+# the 'svn commit' to avoid automated property changes and other stuff
+# that could be set from user's configuration files in ~/.subversion.
+svn_cmd () {
+ [ -d "$svnconf" ] || mkdir "$svnconf"
+ orig_svncmd="$1"; shift
+ if [ -z "$orig_svncmd" ]; then
+ svn
+ return
+ fi
+ svn "$orig_svncmd" --config-dir "$svnconf" "$@"
+}
+
for d in \
"$SVN_HTTPD_PATH" \
/usr/sbin/apache2 \
@@ -73,16 +94,21 @@ for d in \
done
start_httpd () {
+ repo_base_path="$1"
if test -z "$SVN_HTTPD_PORT"
then
echo >&2 'SVN_HTTPD_PORT is not defined!'
return
fi
+ if test -z "$repo_base_path"
+ then
+ repo_base_path=svn
+ fi
mkdir "$GIT_DIR"/logs
cat > "$GIT_DIR/httpd.conf" <<EOF
-ServerName "git-svn test"
+ServerName "git svn test"
ServerRoot "$GIT_DIR"
DocumentRoot "$GIT_DIR"
PidFile "$GIT_DIR/httpd.pid"
@@ -90,13 +116,13 @@ LockFile logs/accept.lock
Listen 127.0.0.1:$SVN_HTTPD_PORT
LoadModule dav_module $SVN_HTTPD_MODULE_PATH/mod_dav.so
LoadModule dav_svn_module $SVN_HTTPD_MODULE_PATH/mod_dav_svn.so
-<Location /svn>
+<Location /$repo_base_path>
DAV svn
- SVNPath $rawsvnrepo
+ SVNPath "$rawsvnrepo"
</Location>
EOF
"$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k start
- svnrepo=http://127.0.0.1:$SVN_HTTPD_PORT/svn
+ svnrepo="http://127.0.0.1:$SVN_HTTPD_PORT/$repo_base_path"
}
stop_httpd () {
@@ -105,7 +131,7 @@ stop_httpd () {
}
convert_to_rev_db () {
- perl -w -- - "$@" <<\EOF
+ $PERL -w -- - "$@" <<\EOF
use strict;
@ARGV == 2 or die "Usage: convert_to_rev_db <input> <output>";
open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]";
@@ -129,3 +155,19 @@ close $wr or die $!;
close $rd or die $!;
EOF
}
+
+require_svnserve () {
+ if test -z "$SVNSERVE_PORT"
+ then
+ say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)'
+ test_done
+ fi
+}
+
+start_svnserve () {
+ svnserve --listen-port $SVNSERVE_PORT \
+ --root "$rawsvnrepo" \
+ --listen-once \
+ --listen-host 127.0.0.1 &
+}
+
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index 7f206c56cf..6765b08065 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -8,21 +8,33 @@ then
say "skipping test, network testing disabled by default"
say "(define GIT_TEST_HTTPD to enable)"
test_done
- exit
fi
-LIB_HTTPD_PATH=${LIB_HTTPD_PATH-'/usr/sbin/apache2'}
+HTTPD_PARA=""
+
+case $(uname) in
+ Darwin)
+ DEFAULT_HTTPD_PATH='/usr/sbin/httpd'
+ DEFAULT_HTTPD_MODULE_PATH='/usr/libexec/apache2'
+ HTTPD_PARA="$HTTPD_PARA -DDarwin"
+ ;;
+ *)
+ DEFAULT_HTTPD_PATH='/usr/sbin/apache2'
+ DEFAULT_HTTPD_MODULE_PATH='/usr/lib/apache2/modules'
+ ;;
+esac
+
+LIB_HTTPD_PATH=${LIB_HTTPD_PATH-"$DEFAULT_HTTPD_PATH"}
LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'8111'}
-TEST_PATH="$PWD"/../lib-httpd
+TEST_PATH="$TEST_DIRECTORY"/lib-httpd
HTTPD_ROOT_PATH="$PWD"/httpd
HTTPD_DOCUMENT_ROOT_PATH=$HTTPD_ROOT_PATH/www
if ! test -x "$LIB_HTTPD_PATH"
then
- say "skipping test, no web server found at '$LIB_HTTPD_PATH'"
- test_done
- exit
+ say "skipping test, no web server found at '$LIB_HTTPD_PATH'"
+ test_done
fi
HTTPD_VERSION=`$LIB_HTTPD_PATH -v | \
@@ -36,32 +48,30 @@ then
then
say "skipping test, at least Apache version 2 is required"
test_done
- exit
fi
- LIB_HTTPD_MODULE_PATH='/usr/lib/apache2/modules'
+ LIB_HTTPD_MODULE_PATH="$DEFAULT_HTTPD_MODULE_PATH"
fi
else
error "Could not identify web server at '$LIB_HTTPD_PATH'"
fi
-HTTPD_PARA="-d $HTTPD_ROOT_PATH -f $TEST_PATH/apache.conf"
-
prepare_httpd() {
- mkdir -p $HTTPD_DOCUMENT_ROOT_PATH
+ mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH"
- ln -s $LIB_HTTPD_MODULE_PATH $HTTPD_ROOT_PATH/modules
+ ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
if test -n "$LIB_HTTPD_SSL"
then
HTTPD_URL=https://127.0.0.1:$LIB_HTTPD_PORT
RANDFILE_PATH="$HTTPD_ROOT_PATH"/.rnd openssl req \
- -config $TEST_PATH/ssl.cnf \
+ -config "$TEST_PATH/ssl.cnf" \
-new -x509 -nodes \
- -out $HTTPD_ROOT_PATH/httpd.pem \
- -keyout $HTTPD_ROOT_PATH/httpd.pem
- export GIT_SSL_NO_VERIFY=t
+ -out "$HTTPD_ROOT_PATH/httpd.pem" \
+ -keyout "$HTTPD_ROOT_PATH/httpd.pem"
+ GIT_SSL_NO_VERIFY=t
+ export GIT_SSL_NO_VERIFY
HTTPD_PARA="$HTTPD_PARA -DSSL"
else
HTTPD_URL=http://127.0.0.1:$LIB_HTTPD_PORT
@@ -81,16 +91,25 @@ prepare_httpd() {
}
start_httpd() {
- prepare_httpd
+ prepare_httpd >&3 2>&4
- trap 'stop_httpd; die' exit
+ trap 'code=$?; stop_httpd; (exit $code); die' EXIT
- "$LIB_HTTPD_PATH" $HTTPD_PARA \
- -c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start
+ "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \
+ -f "$TEST_PATH/apache.conf" $HTTPD_PARA \
+ -c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start \
+ >&3 2>&4
+ if test $? -ne 0
+ then
+ say "skipping test, web server setup failed"
+ trap 'die' EXIT
+ test_done
+ fi
}
stop_httpd() {
- trap 'die' exit
+ trap 'die' EXIT
- "$LIB_HTTPD_PATH" $HTTPD_PARA -k stop
+ "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \
+ -f "$TEST_PATH/apache.conf" $HTTPD_PARA -k stop
}
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index a4473462d1..0fe3fd0d01 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -1,6 +1,35 @@
+ServerName dummy
+LockFile accept.lock
PidFile httpd.pid
DocumentRoot www
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+CustomLog access.log common
ErrorLog error.log
+<IfModule !mod_log_config.c>
+ LoadModule log_config_module modules/mod_log_config.so
+</IfModule>
+<IfModule !mod_alias.c>
+ LoadModule alias_module modules/mod_alias.so
+</IfModule>
+<IfModule !mod_cgi.c>
+ LoadModule cgi_module modules/mod_cgi.so
+</IfModule>
+<IfModule !mod_env.c>
+ LoadModule env_module modules/mod_env.so
+</IfModule>
+
+Alias /dumb/ www/
+
+<Location /smart/>
+ SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
+</Location>
+ScriptAlias /smart/ ${GIT_EXEC_PATH}/git-http-backend/
+<Directory ${GIT_EXEC_PATH}>
+ Options None
+</Directory>
+<Files ${GIT_EXEC_PATH}/git-http-backend>
+ Options ExecCGI
+</Files>
<IfDefine SSL>
LoadModule ssl_module modules/mod_ssl.so
@@ -19,7 +48,7 @@ SSLEngine On
LoadModule dav_fs_module modules/mod_dav_fs.so
DAVLockDB DAVLock
- <Location />
+ <Location /dumb/>
Dav on
</Location>
</IfDefine>
diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh
new file mode 100755
index 0000000000..75a3ee283d
--- /dev/null
+++ b/t/lib-patch-mode.sh
@@ -0,0 +1,41 @@
+. ./test-lib.sh
+
+if ! test_have_prereq PERL; then
+ say 'skipping --patch tests, perl not available'
+ test_done
+fi
+
+set_state () {
+ echo "$3" > "$1" &&
+ git add "$1" &&
+ echo "$2" > "$1"
+}
+
+save_state () {
+ noslash="$(echo "$1" | tr / _)" &&
+ cat "$1" > _worktree_"$noslash" &&
+ git show :"$1" > _index_"$noslash"
+}
+
+set_and_save_state () {
+ set_state "$@" &&
+ save_state "$1"
+}
+
+verify_state () {
+ test "$(cat "$1")" = "$2" &&
+ test "$(git show :"$1")" = "$3"
+}
+
+verify_saved_state () {
+ noslash="$(echo "$1" | tr / _)" &&
+ verify_state "$1" "$(cat _worktree_"$noslash")" "$(cat _index_"$noslash")"
+}
+
+save_head () {
+ git rev-parse HEAD > _head
+}
+
+verify_saved_head () {
+ test "$(cat _head)" = "$(git rev-parse HEAD)"
+}
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
new file mode 100644
index 0000000000..62f452c8ea
--- /dev/null
+++ b/t/lib-rebase.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# After setting the fake editor with this function, you can
+#
+# - override the commit message with $FAKE_COMMIT_MESSAGE,
+# - amend the commit message with $FAKE_COMMIT_AMEND
+# - check that non-commit messages have a certain line count with $EXPECT_COUNT
+# - rewrite a rebase -i script with $FAKE_LINES in the form
+#
+# "[<lineno1>] [<lineno2>]..."
+#
+# If a line number is prefixed with "squash", "edit", or "reword", the
+# respective line's command will be replaced with the specified one.
+
+set_fake_editor () {
+ echo "#!$SHELL_PATH" >fake-editor.sh
+ cat >> fake-editor.sh <<\EOF
+case "$1" in
+*/COMMIT_EDITMSG)
+ test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
+ test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
+ exit
+ ;;
+esac
+test -z "$EXPECT_COUNT" ||
+ test "$EXPECT_COUNT" = $(sed -e '/^#/d' -e '/^$/d' < "$1" | wc -l) ||
+ exit
+test -z "$FAKE_LINES" && exit
+grep -v '^#' < "$1" > "$1".tmp
+rm -f "$1"
+cat "$1".tmp
+action=pick
+for line in $FAKE_LINES; do
+ case $line in
+ squash|edit|reword)
+ action="$line";;
+ *)
+ echo sed -n "${line}s/^pick/$action/p"
+ sed -n "${line}p" < "$1".tmp
+ sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
+ action=pick;;
+ esac
+done
+EOF
+
+ test_set_editor "$(pwd)/fake-editor.sh"
+ chmod a+x fake-editor.sh
+}
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 27b54cbb12..f4ca4fc85c 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -57,13 +57,28 @@ test_expect_failure 'pretend we have a known breakage' '
test_expect_failure 'pretend we have fixed a known breakage' '
:
'
+test_set_prereq HAVEIT
+haveit=no
+test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
+ test_have_prereq HAVEIT &&
+ haveit=yes
+'
+donthaveit=yes
+test_expect_success DONTHAVEIT 'unmet prerequisite causes test to be skipped' '
+ donthaveit=no
+'
+if test $haveit$donthaveit != yesyes
+then
+ say "bug in test framework: prerequisite tags do not work reliably"
+ exit 1
+fi
################################################################
# Basics of the basics
# updating a new file without --add should fail.
test_expect_success 'git update-index without --add should fail adding.' '
- ! git update-index should-be-empty
+ test_must_fail git update-index should-be-empty
'
# and with --add it should succeed, even if it is empty (it used to fail).
@@ -83,7 +98,7 @@ test_expect_success \
# Removing paths.
rm -f should-be-empty full-of-directories
test_expect_success 'git update-index without --remove should fail removing.' '
- ! git update-index should-be-empty
+ test_must_fail git update-index should-be-empty
'
test_expect_success \
@@ -100,12 +115,31 @@ test_expect_success \
'test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904'
# Various types of objects
+# Some filesystems do not support symblic links; on such systems
+# some expected values are different
mkdir path2 path3 path3/subp3
-for p in path0 path2/file2 path3/file3 path3/subp3/file3
+paths='path0 path2/file2 path3/file3 path3/subp3/file3'
+for p in $paths
do
echo "hello $p" >$p
- ln -s "hello $p" ${p}sym
done
+if test_have_prereq SYMLINKS
+then
+ for p in $paths
+ do
+ ln -s "hello $p" ${p}sym
+ done
+ expectfilter=cat
+ expectedtree=087704a96baf1c2d1c869a8b084481e121c88b5b
+ expectedptree1=21ae8269cacbe57ae09138dcc3a2887f904d02b3
+ expectedptree2=3c5e5399f3a333eddecce7a9b9465b63f65f51e2
+else
+ expectfilter='grep -v sym'
+ expectedtree=8e18edf7d7edcf4371a3ac6ae5f07c2641db7c46
+ expectedptree1=cfb8591b2f65de8b8cc1020cd7d9e67e7793b325
+ expectedptree2=ce580448f0148b985a513b693fdf7d802cacb44f
+fi
+
test_expect_success \
'adding various types of objects with git update-index --add.' \
'find path* ! -type d -print | xargs git update-index --add'
@@ -115,7 +149,7 @@ test_expect_success \
'showing stage with git ls-files --stage' \
'git ls-files --stage >current'
-cat >expected <<\EOF
+$expectfilter >expected <<\EOF
100644 f87290f8eb2cbbea7857214459a0739927eab154 0 path0
120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0 path0sym
100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0 path2/file2
@@ -127,14 +161,14 @@ cat >expected <<\EOF
EOF
test_expect_success \
'validate git ls-files output for a known tree.' \
- 'diff current expected'
+ 'test_cmp expected current'
test_expect_success \
'writing tree out with git write-tree.' \
'tree=$(git write-tree)'
test_expect_success \
'validate object ID for a known tree.' \
- 'test "$tree" = 087704a96baf1c2d1c869a8b084481e121c88b5b'
+ 'test "$tree" = "$expectedtree"'
test_expect_success \
'showing tree with git ls-tree' \
@@ -145,16 +179,16 @@ cat >expected <<\EOF
040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2
040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3
EOF
-test_expect_success \
+test_expect_success SYMLINKS \
'git ls-tree output for a known tree.' \
- 'diff current expected'
+ 'test_cmp expected current'
# This changed in ls-tree pathspec change -- recursive does
# not show tree nodes anymore.
test_expect_success \
'showing tree with git ls-tree -r' \
'git ls-tree -r $tree >current'
-cat >expected <<\EOF
+$expectfilter >expected <<\EOF
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2
@@ -166,7 +200,7 @@ cat >expected <<\EOF
EOF
test_expect_success \
'git ls-tree -r output for a known tree.' \
- 'diff current expected'
+ 'test_cmp expected current'
# But with -r -t we can have both.
test_expect_success \
@@ -185,23 +219,23 @@ cat >expected <<\EOF
100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3
120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym
EOF
-test_expect_success \
+test_expect_success SYMLINKS \
'git ls-tree -r output for a known tree.' \
- 'diff current expected'
+ 'test_cmp expected current'
test_expect_success \
'writing partial tree out with git write-tree --prefix.' \
'ptree=$(git write-tree --prefix=path3)'
test_expect_success \
'validate object ID for a known tree.' \
- 'test "$ptree" = 21ae8269cacbe57ae09138dcc3a2887f904d02b3'
+ 'test "$ptree" = "$expectedptree1"'
test_expect_success \
'writing partial tree out with git write-tree --prefix.' \
'ptree=$(git write-tree --prefix=path3/subp3)'
test_expect_success \
'validate object ID for a known tree.' \
- 'test "$ptree" = 3c5e5399f3a333eddecce7a9b9465b63f65f51e2'
+ 'test "$ptree" = "$expectedptree2"'
cat >badobjects <<EOF
100644 blob 1000000000000000000000000000000000000000 dir/file1
@@ -217,7 +251,7 @@ test_expect_success \
'git update-index --index-info < badobjects'
test_expect_success 'writing this tree without --missing-ok.' '
- ! git write-tree
+ test_must_fail git write-tree
'
test_expect_success \
@@ -234,7 +268,7 @@ test_expect_success \
newtree=$(git write-tree) &&
test "$newtree" = "$tree"'
-cat >expected <<\EOF
+$expectfilter >expected <<\EOF
:100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M path0
:120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M path0sym
:100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M path2/file2
@@ -257,7 +291,7 @@ test_expect_success \
'git diff-files >current && cmp -s current /dev/null'
################################################################
-P=087704a96baf1c2d1c869a8b084481e121c88b5b
+P=$expectedtree
test_expect_success \
'git commit-tree records the correct tree in a commit.' \
'commit0=$(echo NO | git commit-tree $P) &&
@@ -293,7 +327,7 @@ test_expect_success 'update-index D/F conflict' '
test $numpath0 = 1
'
-test_expect_success 'absolute path works as expected' '
+test_expect_success SYMLINKS 'absolute path works as expected' '
mkdir first &&
ln -s ../.git first/.git &&
mkdir second &&
@@ -301,14 +335,14 @@ test_expect_success 'absolute path works as expected' '
mkdir third &&
dir="$(cd .git; pwd -P)" &&
dir2=third/../second/other/.git &&
- test "$dir" = "$(test-absolute-path $dir2)" &&
+ test "$dir" = "$(test-path-utils make_absolute_path $dir2)" &&
file="$dir"/index &&
- test "$file" = "$(test-absolute-path $dir2/index)" &&
+ test "$file" = "$(test-path-utils make_absolute_path $dir2/index)" &&
basename=blub &&
- test "$dir/$basename" = $(cd .git && test-absolute-path $basename) &&
+ test "$dir/$basename" = "$(cd .git && test-path-utils make_absolute_path "$basename")" &&
ln -s ../first/file .git/syml &&
sym="$(cd first; pwd -P)"/file &&
- test "$sym" = "$(test-absolute-path $dir2/syml)"
+ test "$sym" = "$(test-path-utils make_absolute_path "$dir2/syml")"
'
test_expect_success 'very long name in the index handled sanely' '
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index b0289e397a..5386504790 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -79,6 +79,17 @@ test_expect_success 'GIT_DIR bare' '
check_config git-dir-bare.git true unset
'
+test_expect_success 'init --bare' '
+
+ (
+ unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
+ mkdir init-bare.git &&
+ cd init-bare.git &&
+ git init --bare
+ ) &&
+ check_config init-bare.git true unset
+'
+
test_expect_success 'GIT_DIR non-bare' '
(
@@ -130,4 +141,154 @@ test_expect_success 'reinit' '
test_cmp again/empty again/err2
'
+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
+ ) &&
+ 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
+'
+
+test_expect_success 'init --bare/--shared overrides system/global config' '
+ (
+ HOME="`pwd`" &&
+ export HOME &&
+ test_config="$HOME"/.gitconfig &&
+ unset GIT_CONFIG_NOGLOBAL &&
+ 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
+ ) &&
+ check_config init-bare-shared-override true unset &&
+ test x0666 = \
+ x`git config -f init-bare-shared-override/config core.sharedRepository`
+'
+
+test_expect_success 'init honors global core.sharedRepository' '
+ (
+ HOME="`pwd`" &&
+ export HOME &&
+ test_config="$HOME"/.gitconfig &&
+ unset GIT_CONFIG_NOGLOBAL &&
+ git config -f "$test_config" core.sharedRepository 0666 &&
+ mkdir shared-honor-global &&
+ cd shared-honor-global &&
+ git init
+ ) &&
+ test x0666 = \
+ 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_expect_success 'init creates a new directory' '
+ rm -fr newdir &&
+ (
+ git init newdir &&
+ test -d newdir/.git/refs
+ )
+'
+
+test_expect_success 'init creates a new bare directory' '
+ rm -fr newdir &&
+ (
+ git init --bare newdir &&
+ test -d newdir/refs
+ )
+'
+
+test_expect_success 'init recreates a directory' '
+ rm -fr newdir &&
+ (
+ mkdir newdir &&
+ git init newdir &&
+ test -d 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
+ )
+'
+
+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_expect_success POSIXPERM 'init creates a new deep directory (umask vs. shared)' '
+ rm -fr newdir &&
+ (
+ # Leading directories should honor umask while
+ # the repository itself should follow "shared"
+ umask 002 &&
+ git init --bare --shared=0660 newdir/a/b/c &&
+ test -d 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 &&
+ ! grep -v "^drwxrw[sx]---" lsc.out
+ )
+'
+
+test_expect_success 'init notices EEXIST (1)' '
+ rm -fr newdir &&
+ (
+ >newdir &&
+ test_must_fail git init newdir &&
+ test -f 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
+ )
+'
+
+test_expect_success POSIXPERM 'init notices EPERM' '
+ rm -fr newdir &&
+ (
+ mkdir newdir &&
+ chmod -w newdir &&
+ test_must_fail git init newdir/a/b
+ )
+'
+
test_done
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
index c5dbc724b6..cb144258cc 100755
--- a/t/t0002-gitfile.sh
+++ b/t/t0002-gitfile.sh
@@ -32,7 +32,7 @@ test_expect_success 'bad setup: invalid .git file format' '
echo "git rev-parse accepted an invalid .git file"
false
fi &&
- if ! grep -qe "Invalid gitfile format" .err
+ if ! grep "Invalid gitfile format" .err
then
echo "git rev-parse returned wrong error"
false
@@ -46,7 +46,7 @@ test_expect_success 'bad setup: invalid .git file path' '
echo "git rev-parse accepted an invalid .git file path"
false
fi &&
- if ! grep -qe "Not a git repository" .err
+ if ! grep "Not a git repository" .err
then
echo "git rev-parse returned wrong error"
false
@@ -66,7 +66,7 @@ test_expect_success 'check hash-object' '
test_expect_success 'check cat-file' '
git cat-file blob $SHA >actual &&
- diff -u bar actual
+ test_cmp bar actual
'
test_expect_success 'check update-index' '
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index c56d2fbaba..1c77192eb3 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -47,6 +47,23 @@ test_expect_success 'attribute test' '
'
+test_expect_success 'attribute test: read paths from stdin' '
+
+ cat <<EOF > expect
+f: test: f
+a/f: test: f
+a/c/f: test: f
+a/g: test: a/g
+a/b/g: test: a/b/g
+b/g: test: unspecified
+a/b/h: test: a/b/h
+a/b/d/g: test: a/b/d/*
+EOF
+
+ sed -e "s/:.*//" < expect | git check-attr --stdin test > actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'root subdir attribute test' '
attr_check a/i a/i &&
@@ -54,4 +71,39 @@ test_expect_success 'root subdir attribute test' '
'
+test_expect_success 'setup bare' '
+
+ git clone --bare . bare.git &&
+ cd 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
+
+'
+
+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
+
+'
+
test_done
diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh
index 9255c63c08..2342ac5788 100755
--- a/t/t0004-unwritable.sh
+++ b/t/t0004-unwritable.sh
@@ -8,58 +8,59 @@ test_expect_success setup '
>file &&
git add file &&
+ test_tick &&
git commit -m initial &&
echo >file &&
git add file
'
-test_expect_success 'write-tree should notice unwritable repository' '
+test_expect_success POSIXPERM 'write-tree should notice unwritable repository' '
(
- chmod a-w .git/objects
+ chmod a-w .git/objects .git/objects/?? &&
test_must_fail git write-tree
)
status=$?
- chmod 775 .git/objects
+ chmod 775 .git/objects .git/objects/??
(exit $status)
'
-test_expect_success 'commit should notice unwritable repository' '
+test_expect_success POSIXPERM 'commit should notice unwritable repository' '
(
- chmod a-w .git/objects
+ chmod a-w .git/objects .git/objects/?? &&
test_must_fail git commit -m second
)
status=$?
- chmod 775 .git/objects
+ chmod 775 .git/objects .git/objects/??
(exit $status)
'
-test_expect_success 'update-index should notice unwritable repository' '
+test_expect_success POSIXPERM 'update-index should notice unwritable repository' '
(
- echo a >file &&
- chmod a-w .git/objects
+ echo 6O >file &&
+ chmod a-w .git/objects .git/objects/?? &&
test_must_fail git update-index file
)
status=$?
- chmod 775 .git/objects
+ chmod 775 .git/objects .git/objects/??
(exit $status)
'
-test_expect_success 'add should notice unwritable repository' '
+test_expect_success POSIXPERM 'add should notice unwritable repository' '
(
echo b >file &&
- chmod a-w .git/objects
+ chmod a-w .git/objects .git/objects/?? &&
test_must_fail git add file
)
status=$?
- chmod 775 .git/objects
+ chmod 775 .git/objects .git/objects/??
(exit $status)
'
diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh
new file mode 100755
index 0000000000..09f855af3e
--- /dev/null
+++ b/t/t0005-signals.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='signals work as we expect'
+. ./test-lib.sh
+
+cat >expect <<EOF
+three
+two
+one
+EOF
+
+test_expect_success 'sigchain works' '
+ test-sigchain >actual
+ case "$?" in
+ 143) true ;; # POSIX w/ SIGTERM=15
+ 3) true ;; # Windows
+ *) false ;;
+ esac &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
new file mode 100755
index 0000000000..75b02af86d
--- /dev/null
+++ b/t/t0006-date.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+test_description='test date parsing and printing'
+. ./test-lib.sh
+
+# arbitrary reference time: 2009-08-30 19:20:00
+TEST_DATE_NOW=1251660000; export TEST_DATE_NOW
+
+check_show() {
+ t=$(($TEST_DATE_NOW - $1))
+ echo "$t -> $2" >expect
+ test_expect_${3:-success} "relative date ($2)" "
+ test-date show $t >actual &&
+ test_cmp expect actual
+ "
+}
+
+check_show 5 '5 seconds ago'
+check_show 300 '5 minutes ago'
+check_show 18000 '5 hours ago'
+check_show 432000 '5 days ago'
+check_show 1728000 '3 weeks ago'
+check_show 13000000 '5 months ago'
+check_show 37500000 '1 year, 2 months ago'
+check_show 55188000 '1 year, 9 months ago'
+check_show 630000000 '20 years ago'
+check_show 31449600 '12 months ago'
+
+check_parse() {
+ echo "$1 -> $2" >expect
+ test_expect_${3:-success} "parse date ($1)" "
+ test-date parse '$1' >actual &&
+ test_cmp expect actual
+ "
+}
+
+check_parse 2008 bad
+check_parse 2008-02 bad
+check_parse 2008-02-14 bad
+check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000'
+
+check_approxidate() {
+ echo "$1 -> $2 +0000" >expect
+ test_expect_${3:-success} "parse approxidate ($1)" "
+ test-date approxidate '$1' >actual &&
+ test_cmp expect actual
+ "
+}
+
+check_approxidate now '2009-08-30 19:20:00'
+check_approxidate '5 seconds ago' '2009-08-30 19:19:55'
+check_approxidate 5.seconds.ago '2009-08-30 19:19:55'
+check_approxidate 10.minutes.ago '2009-08-30 19:10:00'
+check_approxidate yesterday '2009-08-29 19:20:00'
+check_approxidate 3.days.ago '2009-08-27 19:20:00'
+check_approxidate 3.weeks.ago '2009-08-09 19:20:00'
+check_approxidate 3.months.ago '2009-05-30 19:20:00'
+check_approxidate 2.years.3.months.ago '2007-05-30 19:20:00'
+
+check_approxidate '6am yesterday' '2009-08-29 06:00:00'
+check_approxidate '6pm yesterday' '2009-08-29 18:00:00'
+check_approxidate '3:00' '2009-08-30 03:00:00'
+check_approxidate '15:00' '2009-08-30 15:00:00'
+check_approxidate 'noon today' '2009-08-30 12:00:00'
+check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
+
+check_approxidate 'last tuesday' '2009-08-25 19:20:00'
+check_approxidate 'July 5th' '2009-07-05 19:20:00'
+check_approxidate '06/05/2009' '2009-06-05 19:20:00'
+check_approxidate '06.05.2009' '2009-05-06 19:20:00'
+
+check_approxidate 'Jun 6, 5AM' '2009-06-06 05:00:00'
+check_approxidate '5AM Jun 6' '2009-06-06 05:00:00'
+check_approxidate '6AM, June 7, 2009' '2009-06-07 06:00:00'
+
+test_done
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 2bfeac986e..4e72b53140 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -52,7 +52,7 @@ test_expect_success 'safecrlf: autocrlf=input, all CRLF' '
git config core.safecrlf true &&
for w in I am all CRLF; do echo $w; done | append_cr >allcrlf &&
- ! git add allcrlf
+ test_must_fail git add allcrlf
'
test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' '
@@ -61,7 +61,7 @@ test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' '
git config core.safecrlf true &&
for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
- ! git add mixed
+ test_must_fail git add mixed
'
test_expect_success 'safecrlf: autocrlf=true, all LF' '
@@ -70,7 +70,7 @@ test_expect_success 'safecrlf: autocrlf=true, all LF' '
git config core.safecrlf true &&
for w in I am all LF; do echo $w; done >alllf &&
- ! git add alllf
+ test_must_fail git add alllf
'
test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' '
@@ -79,7 +79,7 @@ test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' '
git config core.safecrlf true &&
for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
- ! git add mixed
+ test_must_fail git add mixed
'
test_expect_success 'safecrlf: print warning only once' '
@@ -429,6 +429,37 @@ test_expect_success 'in-tree .gitattributes (4)' '
}
'
+test_expect_success 'checkout with existing .gitattributes' '
+
+ git config core.autocrlf true &&
+ git config --unset core.safecrlf &&
+ echo ".file2 -crlfQ" | q_to_cr >> .gitattributes &&
+ git add .gitattributes &&
+ git commit -m initial &&
+ echo ".file -crlfQ" | q_to_cr >> .gitattributes &&
+ echo "contents" > .file &&
+ git add .gitattributes .file &&
+ git commit -m second &&
+
+ git checkout master~1 &&
+ git checkout master &&
+ test "$(git diff-files --raw)" = ""
+
+'
+
+test_expect_success 'checkout when deleting .gitattributes' '
+
+ git rm .gitattributes &&
+ echo "contentsQ" | q_to_cr > .file2 &&
+ git add .file2 &&
+ git commit -m third
+
+ git checkout master~1 &&
+ git checkout master &&
+ remove_cr .file2 >/dev/null
+
+'
+
test_expect_success 'invalid .gitattributes (must not crash)' '
echo "three +crlf" >>.gitattributes &&
diff --git a/t/t0022-crlf-rename.sh b/t/t0022-crlf-rename.sh
index 7d1ce2d056..f1e1d48869 100755
--- a/t/t0022-crlf-rename.sh
+++ b/t/t0022-crlf-rename.sh
@@ -6,13 +6,13 @@ test_description='ignore CR in CRLF sequence while computing similiarity'
test_expect_success setup '
- cat ../t0022-crlf-rename.sh >sample &&
+ cat "$TEST_DIRECTORY"/t0022-crlf-rename.sh >sample &&
git add sample &&
test_tick &&
git commit -m Initial &&
- sed -e "s/\$/ /" ../t0022-crlf-rename.sh >elpmas &&
+ sed -e "s/\$/ /" "$TEST_DIRECTORY"/t0022-crlf-rename.sh >elpmas &&
git add elpmas &&
rm -f sample &&
diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index 6f8a4347d5..aaed725402 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -36,7 +36,7 @@ test_expect_success 'setup' '
test_expect_success 'am' '
- git am --binary -3 <patchfile &&
+ git am -3 <patchfile &&
git diff-files --name-status --exit-code
'
diff --git a/t/t0024-crlf-archive.sh b/t/t0024-crlf-archive.sh
new file mode 100755
index 0000000000..c7d0324374
--- /dev/null
+++ b/t/t0024-crlf-archive.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+test_description='respect crlf in git archive'
+
+. ./test-lib.sh
+UNZIP=${UNZIP:-unzip}
+
+test_expect_success setup '
+
+ git config core.autocrlf true
+
+ printf "CRLF line ending\r\nAnd another\r\n" > sample &&
+ git add sample &&
+
+ test_tick &&
+ git commit -m Initial
+
+'
+
+test_expect_success 'tar archive' '
+
+ git archive --format=tar HEAD |
+ ( mkdir untarred && cd untarred && "$TAR" -xf - )
+
+ test_cmp sample untarred/sample
+
+'
+
+"$UNZIP" -v >/dev/null 2>&1
+if [ $? -eq 127 ]; then
+ say "Skipping ZIP test, because unzip was not found"
+else
+ test_set_prereq UNZIP
+fi
+
+test_expect_success UNZIP 'zip archive' '
+
+ git archive --format=zip HEAD >test.zip &&
+
+ ( mkdir unzipped && cd unzipped && unzip ../test.zip ) &&
+
+ test_cmp sample unzipped/sample
+
+'
+
+test_done
diff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh
index 3ecdd6626a..ccb0a3cb61 100755
--- a/t/t0030-stripspace.sh
+++ b/t/t0030-stripspace.sh
@@ -16,96 +16,96 @@ test_expect_success \
'long lines without spaces should be unchanged' '
echo "$ttt" >expect &&
git stripspace <expect >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$ttt$ttt" >expect &&
git stripspace <expect >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$ttt$ttt$ttt" >expect &&
git stripspace <expect >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$ttt$ttt$ttt$ttt" >expect &&
git stripspace <expect >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
'lines with spaces at the beginning should be unchanged' '
echo "$sss$ttt" >expect &&
git stripspace <expect >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$sss$sss$ttt" >expect &&
git stripspace <expect >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$sss$sss$sss$ttt" >expect &&
git stripspace <expect >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
'lines with intermediate spaces should be unchanged' '
echo "$ttt$sss$ttt" >expect &&
git stripspace <expect >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$ttt$sss$sss$ttt" >expect &&
git stripspace <expect >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
'consecutive blank lines should be unified' '
printf "$ttt\n\n$ttt\n" > expect &&
printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt\n\n$ttt\n" > expect &&
printf "$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt$ttt\n\n$ttt\n" > expect &&
printf "$ttt$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n$ttt\n" > expect &&
printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n$ttt$ttt\n" > expect &&
printf "$ttt\n\n\n\n\n$ttt$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n$ttt$ttt$ttt\n" > expect &&
printf "$ttt\n\n\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n$ttt\n" > expect &&
printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt\n\n$ttt\n" > expect &&
printf "$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt$ttt\n\n$ttt\n" > expect &&
printf "$ttt$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n$ttt\n" > expect &&
printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n$ttt$ttt\n" > expect &&
printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n$ttt$ttt$ttt\n" > expect &&
printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt$ttt\n" | git stripspace >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
@@ -113,114 +113,114 @@ test_expect_success \
> expect &&
printf "\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "\n\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$sss\n$sss\n$sss\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$sss$sss\n$sss\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "\n$sss\n$sss$sss\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$sss$sss$sss$sss\n\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "\n$sss$sss$sss$sss\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "\n\n$sss$sss$sss$sss\n" | git stripspace >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
'consecutive blank lines at the beginning should be removed' '
printf "$ttt\n" > expect &&
printf "\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n" > expect &&
printf "\n\n\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt\n" > expect &&
printf "\n\n\n$ttt$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt$ttt\n" > expect &&
printf "\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt$ttt$ttt\n" > expect &&
printf "\n\n\n$ttt$ttt$ttt$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n" > expect &&
printf "$sss\n$sss\n$sss\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "\n$sss\n$sss$sss\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$sss$sss\n$sss\n\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$sss$sss$sss\n\n\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "\n$sss$sss$sss\n\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "\n\n$sss$sss$sss\n$ttt\n" | git stripspace >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
'consecutive blank lines at the end should be removed' '
printf "$ttt\n" > expect &&
printf "$ttt\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n" > expect &&
printf "$ttt\n\n\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt\n" > expect &&
printf "$ttt$ttt\n\n\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt$ttt\n" > expect &&
printf "$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt$ttt$ttt\n" > expect &&
printf "$ttt$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n" > expect &&
printf "$ttt\n$sss\n$sss\n$sss\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n$sss\n$sss$sss\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n$sss$sss\n$sss\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n$sss$sss$sss\n\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n$sss$sss$sss\n\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n\n\n$sss$sss$sss\n" | git stripspace >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
@@ -257,27 +257,27 @@ test_expect_success \
'text plus spaces without newline should show the correct lines' '
printf "$ttt\n" >expect &&
printf "$ttt$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n" >expect &&
printf "$ttt$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n" >expect &&
printf "$ttt$sss$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt\n" >expect &&
printf "$ttt$ttt$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt\n" >expect &&
printf "$ttt$ttt$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt$ttt\n" >expect &&
printf "$ttt$ttt$ttt$sss" | git stripspace >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
@@ -294,27 +294,27 @@ test_expect_success \
'text plus spaces at end should be cleaned and newline must remain' '
echo "$ttt" >expect &&
echo "$ttt$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$ttt" >expect &&
echo "$ttt$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$ttt" >expect &&
echo "$ttt$sss$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$ttt$ttt" >expect &&
echo "$ttt$ttt$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$ttt$ttt" >expect &&
echo "$ttt$ttt$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$ttt$ttt$ttt" >expect &&
echo "$ttt$ttt$ttt$sss" | git stripspace >actual &&
- git diff expect actual
+ test_cmp expect actual
'
# spaces only:
@@ -324,19 +324,19 @@ test_expect_success \
printf "" >expect &&
echo | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$sss$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
echo "$sss$sss$sss$sss" | git stripspace >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
@@ -353,43 +353,43 @@ test_expect_success \
printf "" >expect &&
printf "" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$sss$sss$sss" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$sss$sss$sss$sss" | git stripspace >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
'consecutive text lines should be unchanged' '
printf "$ttt$ttt\n$ttt\n" >expect &&
printf "$ttt$ttt\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n$ttt$ttt\n$ttt\n" >expect &&
printf "$ttt\n$ttt$ttt\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" >expect &&
printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" >expect &&
printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" >expect &&
printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" | git stripspace >actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
printf "$ttt\n$ttt$ttt\n\n$ttt\n" >expect &&
printf "$ttt\n$ttt$ttt\n\n$ttt\n" | git stripspace >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success 'strip comments, too' '
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index c23f0ace85..3d450ed379 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -11,55 +11,103 @@ cat > expect.err << EOF
usage: test-parse-options <options>
-b, --boolean get a boolean
+ -4, --or4 bitwise-or boolean with ...0100
+ --neg-or4 same as --no-or4
+
-i, --integer <n> get a integer
-j <n> get a integer, too
+ --set23 set integer to 23
+ -t <time> get timestamp of <time>
+ -L, --length <str> get length of <str>
+ -F, --file <FILE> set file to <FILE>
-string options
+String options
-s, --string <string>
get a string
--string2 <str> get another string
--st <st> get another string (pervert ordering)
-o <str> get another string
+ --default-string set string to default
-magic arguments
+Magic arguments
--quux means --quux
+ -NUM set integer to NUM
+ + same as -b
+ --ambiguous positive ambiguity
+ --no-ambiguous negative ambiguity
+
+Standard options
+ --abbrev[=<n>] use <n> digits to display SHA-1s
+ -v, --verbose be verbose
+ -n, --dry-run dry run
+ -q, --quiet be quiet
EOF
test_expect_success 'test help' '
- ! test-parse-options -h > output 2> output.err &&
+ test_must_fail test-parse-options -h > output 2> output.err &&
test ! -s output &&
- git diff expect.err output.err
+ test_cmp expect.err output.err
'
cat > expect << EOF
boolean: 2
integer: 1729
+timestamp: 0
string: 123
+abbrev: 7
+verbose: 2
+quiet: no
+dry run: yes
+file: prefix/my.file
EOF
test_expect_success 'short options' '
- test-parse-options -s123 -b -i 1729 -b > output 2> output.err &&
- git diff expect output &&
+ test-parse-options -s123 -b -i 1729 -b -vv -n -F my.file \
+ > output 2> output.err &&
+ test_cmp expect output &&
test ! -s output.err
'
+
cat > expect << EOF
boolean: 2
integer: 1729
+timestamp: 0
string: 321
+abbrev: 10
+verbose: 2
+quiet: no
+dry run: no
+file: prefix/fi.le
EOF
test_expect_success 'long options' '
test-parse-options --boolean --integer 1729 --boolean --string2=321 \
+ --verbose --verbose --no-dry-run --abbrev=10 --file fi.le\
> output 2> output.err &&
test ! -s output.err &&
- git diff expect output
+ test_cmp expect output
+'
+
+test_expect_success 'missing required value' '
+ test-parse-options -s;
+ test $? = 129 &&
+ test-parse-options --string;
+ test $? = 129 &&
+ test-parse-options --file;
+ test $? = 129
'
cat > expect << EOF
boolean: 1
integer: 13
+timestamp: 0
string: 123
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
arg 00: a1
arg 01: b1
arg 02: --boolean
@@ -69,25 +117,31 @@ test_expect_success 'intermingled arguments' '
test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
> output 2> output.err &&
test ! -s output.err &&
- git diff expect output
+ test_cmp expect output
'
cat > expect << EOF
boolean: 0
integer: 2
+timestamp: 0
string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
EOF
test_expect_success 'unambiguously abbreviated option' '
test-parse-options --int 2 --boolean --no-bo > output 2> output.err &&
test ! -s output.err &&
- git diff expect output
+ test_cmp expect output
'
test_expect_success 'unambiguously abbreviated option with "="' '
test-parse-options --int=2 > output 2> output.err &&
test ! -s output.err &&
- git diff expect output
+ test_cmp expect output
'
test_expect_success 'ambiguously abbreviated option' '
@@ -98,36 +152,187 @@ test_expect_success 'ambiguously abbreviated option' '
cat > expect << EOF
boolean: 0
integer: 0
+timestamp: 0
string: 123
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
EOF
test_expect_success 'non ambiguous option (after two options it abbreviates)' '
test-parse-options --st 123 > output 2> output.err &&
test ! -s output.err &&
- git diff expect output
+ test_cmp expect output
'
-cat > expect.err << EOF
+cat > typo.err << EOF
error: did you mean \`--boolean\` (with two dashes ?)
EOF
test_expect_success 'detect possible typos' '
- ! test-parse-options -boolean > output 2> output.err &&
+ test_must_fail test-parse-options -boolean > output 2> output.err &&
test ! -s output &&
- git diff expect.err output.err
+ test_cmp typo.err output.err
'
cat > expect <<EOF
boolean: 0
integer: 0
+timestamp: 0
string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
arg 00: --quux
EOF
test_expect_success 'keep some options as arguments' '
test-parse-options --quux > output 2> output.err &&
test ! -s output.err &&
- git diff expect output
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+boolean: 0
+integer: 0
+timestamp: 1
+string: default
+abbrev: 7
+verbose: 0
+quiet: yes
+dry run: no
+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 \
+ foo -q > output 2> output.err &&
+ test ! -s output.err &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+Callback: "four", 0
+boolean: 5
+integer: 4
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
+ test-parse-options --length=four -b -4 > output 2> output.err &&
+ test ! -s output.err &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+Callback: "not set", 1
+EOF
+
+test_expect_success 'OPT_CALLBACK() and callback errors work' '
+ test_must_fail test-parse-options --no-length > output 2> output.err &&
+ test_cmp expect output &&
+ test_cmp expect.err output.err
+'
+
+cat > expect <<EOF
+boolean: 1
+integer: 23
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
+ test-parse-options --set23 -bbbbb --no-or4 > output 2> output.err &&
+ test ! -s output.err &&
+ test_cmp expect output
+'
+
+test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
+ test-parse-options --set23 -bbbbb --neg-or4 > output 2> output.err &&
+ test ! -s output.err &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+boolean: 6
+integer: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success 'OPT_BIT() works' '
+ test-parse-options -bb --or4 > output 2> output.err &&
+ test ! -s output.err &&
+ test_cmp expect output
+'
+
+test_expect_success 'OPT_NEGBIT() works' '
+ test-parse-options -bb --no-neg-or4 > output 2> output.err &&
+ test ! -s output.err &&
+ test_cmp expect output
+'
+
+test_expect_success 'OPT_BOOLEAN() with PARSE_OPT_NODASH works' '
+ test-parse-options + + + + + + > output 2> output.err &&
+ test ! -s output.err &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+boolean: 0
+integer: 12345
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success 'OPT_NUMBER_CALLBACK() works' '
+ test-parse-options -12345 > output 2> output.err &&
+ test ! -s output.err &&
+ test_cmp expect output
+'
+
+cat >expect <<EOF
+boolean: 0
+integer: 0
+timestamp: 0
+string: (not set)
+abbrev: 7
+verbose: 0
+quiet: no
+dry run: no
+file: (not set)
+EOF
+
+test_expect_success 'negation of OPT_NONEG flags is not ambiguous' '
+ test-parse-options --no-ambig >output 2>output.err &&
+ test ! -s output.err &&
+ test_cmp expect output
'
test_done
diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh
index 3fbad77811..89282ccf7a 100755
--- a/t/t0050-filesystem.sh
+++ b/t/t0050-filesystem.sh
@@ -7,7 +7,10 @@ test_description='Various filesystem issues'
auml=`printf '\xc3\xa4'`
aumlcdiar=`printf '\x61\xcc\x88'`
-test_expect_success 'see if we expect ' '
+case_insensitive=
+unibad=
+no_symlinks=
+test_expect_success 'see what we expect' '
test_case=test_expect_success
test_unicode=test_expect_success
@@ -17,7 +20,7 @@ test_expect_success 'see if we expect ' '
if test "$(cat junk/CamelCase)" != good
then
test_case=test_expect_failure
- say "will test on a case insensitive filesystem"
+ case_insensitive=t
fi &&
rm -fr junk &&
mkdir junk &&
@@ -25,15 +28,58 @@ test_expect_success 'see if we expect ' '
case "$(cd junk && echo *)" in
"$aumlcdiar")
test_unicode=test_expect_failure
- say "will test on a unicode corrupting filesystem"
+ unibad=t
;;
*) ;;
esac &&
- rm -fr junk
+ rm -fr junk &&
+ {
+ ln -s x y 2> /dev/null &&
+ test -h y 2> /dev/null ||
+ no_symlinks=1
+ rm -f y
+ }
+'
+
+test "$case_insensitive" &&
+ say "will test on a case insensitive filesystem"
+test "$unibad" &&
+ say "will test on a unicode corrupting filesystem"
+test "$no_symlinks" &&
+ say "will test on a filesystem lacking symbolic links"
+
+if test "$case_insensitive"
+then
+test_expect_success "detection of case insensitive filesystem during repo init" '
+
+ test $(git config --bool core.ignorecase) = true
'
+else
+test_expect_success "detection of case insensitive filesystem during repo init" '
+
+ test_must_fail git config --bool core.ignorecase >/dev/null ||
+ test $(git config --bool core.ignorecase) = false
+'
+fi
+
+if test "$no_symlinks"
+then
+test_expect_success "detection of filesystem w/o symlink support during repo init" '
+
+ v=$(git config --bool core.symlinks) &&
+ test "$v" = false
+'
+else
+test_expect_success "detection of filesystem w/o symlink support during repo init" '
+
+ test_must_fail git config --bool core.symlinks ||
+ test "$(git config --bool core.symlinks)" = true
+'
+fi
test_expect_success "setup case tests" '
+ git config core.ignorecase true &&
touch camelcase &&
git add camelcase &&
git commit -m "initial" &&
@@ -55,11 +101,23 @@ $test_case 'rename (case change)' '
$test_case 'merge (case change)' '
+ rm -f CamelCase &&
+ rm -f camelcase &&
git reset --hard initial &&
git merge topic
'
+$test_case 'add (with different case)' '
+
+ git reset --hard initial &&
+ rm camelcase &&
+ echo 1 >CamelCase &&
+ git add CamelCase &&
+ test $(git ls-files | grep -i camelcase | wc -l) = 1
+
+'
+
test_expect_success "setup unicode normalization tests" '
test_create_repo unicode &&
diff --git a/t/t0055-beyond-symlinks.sh b/t/t0055-beyond-symlinks.sh
new file mode 100755
index 0000000000..0c6ff567a1
--- /dev/null
+++ b/t/t0055-beyond-symlinks.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+test_description='update-index and add refuse to add beyond symlinks'
+
+. ./test-lib.sh
+
+test_expect_success SYMLINKS setup '
+ >a &&
+ mkdir b &&
+ ln -s b c &&
+ >c/d &&
+ git update-index --add a b/d
+'
+
+test_expect_success SYMLINKS 'update-index --add beyond symlinks' '
+ test_must_fail git update-index --add c/d &&
+ ! ( git ls-files | grep c/d )
+'
+
+test_expect_success SYMLINKS 'add beyond symlinks' '
+ test_must_fail git add c/d &&
+ ! ( git ls-files | grep c/d )
+'
+
+test_done
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
new file mode 100755
index 0000000000..53cf1f8dc4
--- /dev/null
+++ b/t/t0060-path-utils.sh
@@ -0,0 +1,142 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 David Reiss
+#
+
+test_description='Test various path utilities'
+
+. ./test-lib.sh
+
+norm_path() {
+ test_expect_success $3 "normalize path: $1 => $2" \
+ "test \"\$(test-path-utils normalize_path_copy '$1')\" = '$2'"
+}
+
+# On Windows, we are using MSYS's bash, which mangles the paths.
+# Absolute paths are anchored at the MSYS installation directory,
+# which means that the path / accounts for this many characters:
+rootoff=$(test-path-utils normalize_path_copy / | wc -c)
+# Account for the trailing LF:
+if test $rootoff = 2; then
+ rootoff= # we are on Unix
+else
+ rootoff=$(($rootoff-1))
+fi
+
+ancestor() {
+ # We do some math with the expected ancestor length.
+ expected=$3
+ if test -n "$rootoff" && test "x$expected" != x-1; then
+ expected=$(($expected+$rootoff))
+ fi
+ test_expect_success "longest ancestor: $1 $2 => $expected" \
+ "actual=\$(test-path-utils longest_ancestor_length '$1' '$2') &&
+ test \"\$actual\" = '$expected'"
+}
+
+# Absolute path tests must be skipped on Windows because due to path mangling
+# the test program never sees a POSIX-style absolute path
+case $(uname -s) in
+*MINGW*)
+ ;;
+*)
+ test_set_prereq POSIX
+ ;;
+esac
+
+norm_path "" ""
+norm_path . ""
+norm_path ./ ""
+norm_path ./. ""
+norm_path ./.. ++failed++
+norm_path ../. ++failed++
+norm_path ./../.// ++failed++
+norm_path dir/.. ""
+norm_path dir/sub/../.. ""
+norm_path dir/sub/../../.. ++failed++
+norm_path dir dir
+norm_path dir// dir/
+norm_path ./dir dir
+norm_path dir/. dir/
+norm_path dir///./ dir/
+norm_path dir//sub/.. dir/
+norm_path dir/sub/../ dir/
+norm_path dir/sub/../. dir/
+norm_path dir/s1/../s2/ dir/s2/
+norm_path d1/s1///s2/..//../s3/ d1/s3/
+norm_path d1/s1//../s2/../../d2 d2
+norm_path d1/.../d2 d1/.../d2
+norm_path d1/..././../d2 d1/d2
+
+norm_path / / POSIX
+norm_path // / POSIX
+norm_path /// / POSIX
+norm_path /. / POSIX
+norm_path /./ / POSIX
+norm_path /./.. ++failed++ POSIX
+norm_path /../. ++failed++ POSIX
+norm_path /./../.// ++failed++ POSIX
+norm_path /dir/.. / POSIX
+norm_path /dir/sub/../.. / POSIX
+norm_path /dir/sub/../../.. ++failed++ POSIX
+norm_path /dir /dir POSIX
+norm_path /dir// /dir/ POSIX
+norm_path /./dir /dir POSIX
+norm_path /dir/. /dir/ POSIX
+norm_path /dir///./ /dir/ POSIX
+norm_path /dir//sub/.. /dir/ POSIX
+norm_path /dir/sub/../ /dir/ POSIX
+norm_path //dir/sub/../. /dir/ POSIX
+norm_path /dir/s1/../s2/ /dir/s2/ POSIX
+norm_path /d1/s1///s2/..//../s3/ /d1/s3/ POSIX
+norm_path /d1/s1//../s2/../../d2 /d2 POSIX
+norm_path /d1/.../d2 /d1/.../d2 POSIX
+norm_path /d1/..././../d2 /d1/d2 POSIX
+
+ancestor / "" -1
+ancestor / / -1
+ancestor /foo "" -1
+ancestor /foo : -1
+ancestor /foo ::. -1
+ancestor /foo ::..:: -1
+ancestor /foo / 0
+ancestor /foo /fo -1
+ancestor /foo /foo -1
+ancestor /foo /foo/ -1
+ancestor /foo /bar -1
+ancestor /foo /bar/ -1
+ancestor /foo /foo/bar -1
+ancestor /foo /foo:/bar/ -1
+ancestor /foo /foo/:/bar/ -1
+ancestor /foo /foo::/bar/ -1
+ancestor /foo /:/foo:/bar/ 0
+ancestor /foo /foo:/:/bar/ 0
+ancestor /foo /:/bar/:/foo 0
+ancestor /foo/bar "" -1
+ancestor /foo/bar / 0
+ancestor /foo/bar /fo -1
+ancestor /foo/bar foo -1
+ancestor /foo/bar /foo 4
+ancestor /foo/bar /foo/ 4
+ancestor /foo/bar /foo/ba -1
+ancestor /foo/bar /:/fo 0
+ancestor /foo/bar /foo:/foo/ba 4
+ancestor /foo/bar /bar -1
+ancestor /foo/bar /bar/ -1
+ancestor /foo/bar /fo: -1
+ancestor /foo/bar :/fo -1
+ancestor /foo/bar /foo:/bar/ 4
+ancestor /foo/bar /:/foo:/bar/ 4
+ancestor /foo/bar /foo:/:/bar/ 4
+ancestor /foo/bar /:/bar/:/fo 0
+ancestor /foo/bar /:/bar/ 0
+ancestor /foo/bar .:/foo/. 4
+ancestor /foo/bar .:/foo/.:.: 4
+ancestor /foo/bar /foo/./:.:/bar 4
+ancestor /foo/bar .:/bar -1
+
+test_expect_success 'strip_path_suffix' '
+ test c:/msysgit = $(test-path-utils strip_path_suffix \
+ c:/msysgit/libexec//git-core libexec/git-core)
+'
+test_done
diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh
new file mode 100755
index 0000000000..680d7d6861
--- /dev/null
+++ b/t/t0070-fundamental.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+test_description='check that the most basic functions work
+
+
+Verify wrappers and compatibility functions.
+'
+
+. ./test-lib.sh
+
+test_expect_success 'character classes (isspace, isalpha etc.)' '
+ test-ctype
+'
+
+test_done
diff --git a/t/t0100-previous.sh b/t/t0100-previous.sh
new file mode 100755
index 0000000000..315b9b3f10
--- /dev/null
+++ b/t/t0100-previous.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+test_description='previous branch syntax @{-n}'
+
+. ./test-lib.sh
+
+test_expect_success 'branch -d @{-1}' '
+ test_commit A &&
+ git checkout -b junk &&
+ git checkout - &&
+ test "$(git symbolic-ref HEAD)" = refs/heads/master &&
+ git branch -d @{-1} &&
+ test_must_fail git rev-parse --verify refs/heads/junk
+'
+
+test_expect_success 'branch -d @{-12} when there is not enough switches yet' '
+ git reflog expire --expire=now &&
+ git checkout -b junk2 &&
+ git checkout - &&
+ test "$(git symbolic-ref HEAD)" = refs/heads/master &&
+ test_must_fail git branch -d @{-12} &&
+ git rev-parse --verify refs/heads/master
+'
+
+test_expect_success 'merge @{-1}' '
+ git checkout A &&
+ test_commit B &&
+ git checkout A &&
+ test_commit C &&
+ git branch -f master B &&
+ git branch -f other &&
+ git checkout other &&
+ git checkout master &&
+ git merge @{-1} &&
+ git cat-file commit HEAD | grep "Merge branch '\''other'\''"
+'
+
+test_expect_success 'merge @{-1} when there is not enough switches yet' '
+ git reflog expire --expire=now &&
+ git checkout -f master &&
+ git reset --hard B &&
+ git branch -f other C &&
+ git checkout other &&
+ git checkout master &&
+ test_must_fail git merge @{-12}
+'
+
+test_done
+
diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh
index 17f519f547..22ba7a5442 100755
--- a/t/t1000-read-tree-m-3way.sh
+++ b/t/t1000-read-tree-m-3way.sh
@@ -72,7 +72,7 @@ In addition:
'
. ./test-lib.sh
-. ../lib-read-tree-m-3way.sh
+. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
################################################################
# Trivial "majority when 3 stages exist" merge plus #2ALT, #3ALT
@@ -131,7 +131,7 @@ _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
check_result () {
git ls-files --stage | sed -e 's/ '"$_x40"' / X /' >current &&
- git diff expected current
+ test_cmp expected current
}
# This is done on an empty work directory, which is the normal
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index b01b0037a0..c2d408b461 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -5,7 +5,7 @@
test_description='Two way merge with read-tree -m $H $M
-This test tries two-way merge (aka fast forward with carry forward).
+This test tries two-way merge (aka fast-forward with carry forward).
There is the head (called H) and another commit (called M), which is
simply ahead of H. The index and the work tree contains a state that
@@ -33,7 +33,7 @@ compare_change () {
-e '/^--- /d; /^+++ /d; /^@@ /d;' \
-e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
"$1"
- git diff expected current
+ test_cmp expected current
}
check_cache_at () {
@@ -51,7 +51,7 @@ check_cache_at () {
}
cat >bozbar-old <<\EOF
-This is a sample file used in two-way fast forward merge
+This is a sample file used in two-way fast-forward merge
tests. Its second line ends with a magic word bozbar
which will be modified by the merged head to gnusto.
It has some extra lines so that external tools can
@@ -86,7 +86,7 @@ test_expect_success \
'rm -f .git/index &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >1-3.out &&
- git diff M.out 1-3.out &&
+ test_cmp M.out 1-3.out &&
check_cache_at bozbar dirty &&
check_cache_at frotz dirty &&
check_cache_at nitfol dirty'
@@ -101,7 +101,7 @@ test_expect_success \
git update-index --add yomin &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >4.out || return 1
- git diff M.out 4.out >4diff.out
+ git diff --no-index M.out 4.out >4diff.out
compare_change 4diff.out expected &&
check_cache_at yomin clean'
@@ -115,7 +115,7 @@ test_expect_success \
echo yomin yomin >yomin &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >5.out || return 1
- git diff M.out 5.out >5diff.out
+ git diff --no-index M.out 5.out >5diff.out
compare_change 5diff.out expected &&
check_cache_at yomin dirty'
@@ -127,7 +127,7 @@ test_expect_success \
git update-index --add frotz &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >6.out &&
- git diff M.out 6.out &&
+ test_cmp M.out 6.out &&
check_cache_at frotz clean'
test_expect_success \
@@ -140,7 +140,7 @@ test_expect_success \
echo frotz frotz >frotz &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >7.out &&
- git diff M.out 7.out &&
+ test_cmp M.out 7.out &&
check_cache_at frotz dirty'
test_expect_success \
@@ -171,7 +171,7 @@ test_expect_success \
git update-index --add rezrov &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >10.out &&
- git diff M.out 10.out'
+ test_cmp M.out 10.out'
test_expect_success \
'11 - dirty path removed.' \
@@ -216,7 +216,7 @@ test_expect_success \
git update-index --add nitfol &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >14.out || return 1
- git diff M.out 14.out >14diff.out
+ git diff --no-index M.out 14.out >14diff.out
compare_change 14diff.out expected &&
check_cache_at nitfol clean'
@@ -230,7 +230,7 @@ test_expect_success \
echo nitfol nitfol nitfol >nitfol &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >15.out || return 1
- git diff M.out 15.out >15diff.out
+ git diff --no-index M.out 15.out >15diff.out
compare_change 15diff.out expected &&
check_cache_at nitfol dirty'
@@ -262,7 +262,7 @@ test_expect_success \
git update-index --add bozbar &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >18.out &&
- git diff M.out 18.out &&
+ test_cmp M.out 18.out &&
check_cache_at bozbar clean'
test_expect_success \
@@ -275,7 +275,7 @@ test_expect_success \
echo gnusto gnusto >bozbar &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >19.out &&
- git diff M.out 19.out &&
+ test_cmp M.out 19.out &&
check_cache_at bozbar dirty'
test_expect_success \
@@ -287,7 +287,7 @@ test_expect_success \
git update-index --add bozbar &&
read_tree_twoway $treeH $treeM &&
git ls-files --stage >20.out &&
- git diff M.out 20.out &&
+ test_cmp M.out 20.out &&
check_cache_at bozbar dirty'
test_expect_success \
@@ -300,7 +300,7 @@ test_expect_success \
echo gnusto gnusto >bozbar &&
if read_tree_twoway $treeH $treeM; then false; else :; fi'
-# This fails with straight two-way fast forward.
+# This fails with straight two-way fast-forward.
test_expect_success \
'22 - local change cache updated.' \
'rm -f .git/index &&
@@ -337,8 +337,59 @@ test_expect_success \
git update-index --add DF &&
read_tree_twoway $treeDF $treeDFDF &&
git ls-files --stage >DFDFcheck.out &&
- git diff DFDF.out DFDFcheck.out &&
+ test_cmp DFDF.out DFDFcheck.out &&
check_cache_at DF/DF dirty &&
:'
+test_expect_success \
+ 'a/b (untracked) vs a case setup.' \
+ 'rm -f .git/index &&
+ : >a &&
+ git update-index --add a &&
+ treeM=`git write-tree` &&
+ echo treeM $treeM &&
+ git ls-tree $treeM &&
+ git ls-files --stage >treeM.out &&
+
+ rm -f a &&
+ git update-index --remove a &&
+ mkdir a &&
+ : >a/b &&
+ treeH=`git write-tree` &&
+ echo treeH $treeH &&
+ git ls-tree $treeH'
+
+test_expect_success \
+ 'a/b (untracked) vs a, plus c/d case test.' \
+ '! git read-tree -u -m "$treeH" "$treeM" &&
+ git ls-files --stage &&
+ test -f a/b'
+
+test_expect_success \
+ 'a/b vs a, plus c/d case setup.' \
+ 'rm -f .git/index &&
+ rm -fr a &&
+ : >a &&
+ mkdir c &&
+ : >c/d &&
+ git update-index --add a c/d &&
+ treeM=`git write-tree` &&
+ echo treeM $treeM &&
+ git ls-tree $treeM &&
+ git ls-files --stage >treeM.out &&
+
+ rm -f a &&
+ mkdir a
+ : >a/b &&
+ git update-index --add --remove a a/b &&
+ treeH=`git write-tree` &&
+ echo treeH $treeH &&
+ git ls-tree $treeH'
+
+test_expect_success \
+ 'a/b vs a, plus c/d case test.' \
+ 'git read-tree -u -m "$treeH" "$treeM" &&
+ git ls-files --stage | tee >treeMcheck.out &&
+ test_cmp treeM.out treeMcheck.out'
+
test_done
diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh
index 42e5cf8181..5e40cec530 100755
--- a/t/t1002-read-tree-m-u-2way.sh
+++ b/t/t1002-read-tree-m-u-2way.sh
@@ -14,9 +14,11 @@ _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
compare_change () {
sed >current \
+ -e '1{/^diff --git /d;}' \
+ -e '2{/^index /d;}' \
-e '/^--- /d; /^+++ /d; /^@@ /d;' \
-e 's/^\(.[0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /' "$1"
- git diff expected current
+ test_cmp expected current
}
check_cache_at () {
@@ -75,7 +77,7 @@ test_expect_success \
git update-index --add yomin &&
git read-tree -m -u $treeH $treeM &&
git ls-files --stage >4.out || return 1
- diff -U0 M.out 4.out >4diff.out
+ git diff -U0 --no-index M.out 4.out >4diff.out
compare_change 4diff.out expected &&
check_cache_at yomin clean &&
sum bozbar frotz nitfol >actual4.sum &&
@@ -94,7 +96,7 @@ test_expect_success \
echo yomin yomin >yomin &&
git read-tree -m -u $treeH $treeM &&
git ls-files --stage >5.out || return 1
- diff -U0 M.out 5.out >5diff.out
+ git diff -U0 --no-index M.out 5.out >5diff.out
compare_change 5diff.out expected &&
check_cache_at yomin dirty &&
sum bozbar frotz nitfol >actual5.sum &&
@@ -112,7 +114,7 @@ test_expect_success \
git update-index --add frotz &&
git read-tree -m -u $treeH $treeM &&
git ls-files --stage >6.out &&
- diff -U0 M.out 6.out &&
+ test_cmp M.out 6.out &&
check_cache_at frotz clean &&
sum bozbar frotz nitfol >actual3.sum &&
cmp M.sum actual3.sum &&
@@ -129,7 +131,7 @@ test_expect_success \
echo frotz frotz >frotz &&
git read-tree -m -u $treeH $treeM &&
git ls-files --stage >7.out &&
- diff -U0 M.out 7.out &&
+ test_cmp M.out 7.out &&
check_cache_at frotz dirty &&
sum bozbar frotz nitfol >actual7.sum &&
if cmp M.sum actual7.sum; then false; else :; fi &&
@@ -206,7 +208,7 @@ test_expect_success \
git update-index --add nitfol &&
git read-tree -m -u $treeH $treeM &&
git ls-files --stage >14.out || return 1
- diff -U0 M.out 14.out >14diff.out
+ git diff -U0 --no-index M.out 14.out >14diff.out
compare_change 14diff.out expected &&
sum bozbar frotz >actual14.sum &&
grep -v nitfol M.sum > expected14.sum &&
@@ -227,7 +229,7 @@ test_expect_success \
echo nitfol nitfol nitfol >nitfol &&
git read-tree -m -u $treeH $treeM &&
git ls-files --stage >15.out || return 1
- diff -U0 M.out 15.out >15diff.out
+ git diff -U0 --no-index M.out 15.out >15diff.out
compare_change 15diff.out expected &&
check_cache_at nitfol dirty &&
sum bozbar frotz >actual15.sum &&
@@ -264,7 +266,7 @@ test_expect_success \
git update-index --add bozbar &&
git read-tree -m -u $treeH $treeM &&
git ls-files --stage >18.out &&
- diff -U0 M.out 18.out &&
+ test_cmp M.out 18.out &&
check_cache_at bozbar clean &&
sum bozbar frotz nitfol >actual18.sum &&
cmp M.sum actual18.sum'
@@ -278,7 +280,7 @@ test_expect_success \
echo gnusto gnusto >bozbar &&
git read-tree -m -u $treeH $treeM &&
git ls-files --stage >19.out &&
- diff -U0 M.out 19.out &&
+ test_cmp M.out 19.out &&
check_cache_at bozbar dirty &&
sum frotz nitfol >actual19.sum &&
grep -v bozbar M.sum > expected19.sum &&
@@ -297,7 +299,7 @@ test_expect_success \
git update-index --add bozbar &&
git read-tree -m -u $treeH $treeM &&
git ls-files --stage >20.out &&
- diff -U0 M.out 20.out &&
+ test_cmp M.out 20.out &&
check_cache_at bozbar clean &&
sum bozbar frotz nitfol >actual20.sum &&
cmp M.sum actual20.sum'
@@ -338,7 +340,7 @@ test_expect_success \
git update-index --add DF &&
git read-tree -m -u $treeDF $treeDFDF &&
git ls-files --stage >DFDFcheck.out &&
- diff -U0 DFDF.out DFDFcheck.out &&
+ test_cmp DFDF.out DFDFcheck.out &&
check_cache_at DF/DF clean'
test_done
diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh
index 570d3729bd..f19b4a2a4a 100755
--- a/t/t1004-read-tree-m-u-wf.sh
+++ b/t/t1004-read-tree-m-u-wf.sh
@@ -157,7 +157,7 @@ test_expect_success '3-way not overwriting local changes (their side)' '
'
-test_expect_success 'funny symlink in work tree' '
+test_expect_success SYMLINKS 'funny symlink in work tree' '
git reset --hard &&
git checkout -b sym-b side-b &&
@@ -177,7 +177,7 @@ test_expect_success 'funny symlink in work tree' '
'
-test_expect_success 'funny symlink in work tree, un-unlink-able' '
+test_expect_success SYMLINKS 'funny symlink in work tree, un-unlink-able' '
rm -fr a b &&
git reset --hard &&
@@ -189,7 +189,7 @@ test_expect_success 'funny symlink in work tree, un-unlink-able' '
'
# clean-up from the above test
-chmod a+w a
+chmod a+w a 2>/dev/null
rm -fr a b
test_expect_success 'D/F setup' '
diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh
index b0d31f5a9b..849911683a 100755
--- a/t/t1005-read-tree-reset.sh
+++ b/t/t1005-read-tree-reset.sh
@@ -27,4 +27,64 @@ test_expect_success 'reset should work' '
test_cmp expect actual
'
+test_expect_success 'reset should remove remnants from a failed merge' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
+test_expect_success 'Porcelain reset should remove remnants too' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git reset --hard &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
+test_expect_success 'Porcelain checkout -f should remove remnants too' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git checkout -f &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
+test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git checkout -f HEAD &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
test_done
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
new file mode 100755
index 0000000000..d8b7f2ffbc
--- /dev/null
+++ b/t/t1006-cat-file.sh
@@ -0,0 +1,244 @@
+#!/bin/sh
+
+test_description='git cat-file'
+
+. ./test-lib.sh
+
+echo_without_newline () {
+ printf '%s' "$*"
+}
+
+strlen () {
+ echo_without_newline "$1" | wc -c | sed -e 's/^ *//'
+}
+
+maybe_remove_timestamp () {
+ if test -z "$2"; then
+ echo_without_newline "$1"
+ else
+ echo_without_newline "$(printf '%s\n' "$1" | sed -e 's/ [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$//')"
+ fi
+}
+
+run_tests () {
+ type=$1
+ sha1=$2
+ size=$3
+ content=$4
+ pretty_content=$5
+ no_ts=$6
+
+ batch_output="$sha1 $type $size
+$content"
+
+ test_expect_success "$type exists" '
+ git cat-file -e $sha1
+ '
+
+ test_expect_success "Type of $type is correct" '
+ test $type = "$(git cat-file -t $sha1)"
+ '
+
+ test_expect_success "Size of $type is correct" '
+ test $size = "$(git cat-file -s $sha1)"
+ '
+
+ test -z "$content" ||
+ test_expect_success "Content of $type is correct" '
+ expect="$(maybe_remove_timestamp "$content" $no_ts)"
+ actual="$(maybe_remove_timestamp "$(git cat-file $type $sha1)" $no_ts)"
+
+ if test "z$expect" = "z$actual"
+ then
+ : happy
+ else
+ echo "Oops: expected $expect"
+ echo "but got $actual"
+ false
+ fi
+ '
+
+ test_expect_success "Pretty content of $type is correct" '
+ expect="$(maybe_remove_timestamp "$pretty_content" $no_ts)"
+ actual="$(maybe_remove_timestamp "$(git cat-file -p $sha1)" $no_ts)"
+ if test "z$expect" = "z$actual"
+ then
+ : happy
+ else
+ echo "Oops: expected $expect"
+ echo "but got $actual"
+ false
+ fi
+ '
+
+ test -z "$content" ||
+ test_expect_success "--batch output of $type is correct" '
+ expect="$(maybe_remove_timestamp "$batch_output" $no_ts)"
+ actual="$(maybe_remove_timestamp "$(echo $sha1 | git cat-file --batch)" $no_ts)"
+ if test "z$expect" = "z$actual"
+ then
+ : happy
+ else
+ echo "Oops: expected $expect"
+ echo "but got $actual"
+ false
+ fi
+ '
+
+ test_expect_success "--batch-check output of $type is correct" '
+ expect="$sha1 $type $size"
+ actual="$(echo_without_newline $sha1 | git cat-file --batch-check)"
+ if test "z$expect" = "z$actual"
+ then
+ : happy
+ else
+ echo "Oops: expected $expect"
+ echo "but got $actual"
+ false
+ fi
+ '
+}
+
+hello_content="Hello World"
+hello_size=$(strlen "$hello_content")
+hello_sha1=$(echo_without_newline "$hello_content" | git hash-object --stdin)
+
+test_expect_success "setup" '
+ echo_without_newline "$hello_content" > hello &&
+ git update-index --add hello
+'
+
+run_tests 'blob' $hello_sha1 $hello_size "$hello_content" "$hello_content"
+
+tree_sha1=$(git write-tree)
+tree_size=33
+tree_pretty_content="100644 blob $hello_sha1 hello"
+
+run_tests 'tree' $tree_sha1 $tree_size "" "$tree_pretty_content"
+
+commit_message="Intial commit"
+commit_sha1=$(echo_without_newline "$commit_message" | git commit-tree $tree_sha1)
+commit_size=176
+commit_content="tree $tree_sha1
+author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0000000000 +0000
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0000000000 +0000
+
+$commit_message"
+
+run_tests 'commit' $commit_sha1 $commit_size "$commit_content" "$commit_content" 1
+
+tag_header_without_timestamp="object $hello_sha1
+type blob
+tag hellotag
+tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+tag_description="This is a tag"
+tag_content="$tag_header_without_timestamp 0000000000 +0000
+
+$tag_description"
+tag_pretty_content="$tag_header_without_timestamp Thu Jan 1 00:00:00 1970 +0000
+
+$tag_description"
+
+tag_sha1=$(echo_without_newline "$tag_content" | git mktag)
+tag_size=$(strlen "$tag_content")
+
+run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_pretty_content" 1
+
+test_expect_success \
+ "Reach a blob from a tag pointing to it" \
+ "test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""
+
+for batch in batch batch-check
+do
+ for opt in t s e p
+ do
+ test_expect_success "Passing -$opt with --$batch fails" '
+ test_must_fail git cat-file --$batch -$opt $hello_sha1
+ '
+
+ test_expect_success "Passing --$batch with -$opt fails" '
+ test_must_fail git cat-file -$opt --$batch $hello_sha1
+ '
+ done
+
+ test_expect_success "Passing <type> with --$batch fails" '
+ test_must_fail git cat-file --$batch blob $hello_sha1
+ '
+
+ test_expect_success "Passing --$batch with <type> fails" '
+ test_must_fail git cat-file blob --$batch $hello_sha1
+ '
+
+ test_expect_success "Passing sha1 with --$batch fails" '
+ test_must_fail git cat-file --$batch $hello_sha1
+ '
+done
+
+test_expect_success "--batch-check for a non-existent named object" '
+ test "foobar42 missing
+foobar84 missing" = \
+ "$( ( echo foobar42; echo_without_newline foobar84; ) | git cat-file --batch-check)"
+'
+
+test_expect_success "--batch-check for a non-existent hash" '
+ test "0000000000000000000000000000000000000042 missing
+0000000000000000000000000000000000000084 missing" = \
+ "$( ( echo 0000000000000000000000000000000000000042;
+ echo_without_newline 0000000000000000000000000000000000000084; ) \
+ | git cat-file --batch-check)"
+'
+
+test_expect_success "--batch for an existent and a non-existent hash" '
+ test "$tag_sha1 tag $tag_size
+$tag_content
+0000000000000000000000000000000000000000 missing" = \
+ "$( ( echo $tag_sha1;
+ echo_without_newline 0000000000000000000000000000000000000000; ) \
+ | git cat-file --batch)"
+'
+
+test_expect_success "--batch-check for an emtpy line" '
+ test " missing" = "$(echo | git cat-file --batch-check)"
+'
+
+batch_input="$hello_sha1
+$commit_sha1
+$tag_sha1
+deadbeef
+
+"
+
+batch_output="$hello_sha1 blob $hello_size
+$hello_content
+$commit_sha1 commit $commit_size
+$commit_content
+$tag_sha1 tag $tag_size
+$tag_content
+deadbeef missing
+ missing"
+
+test_expect_success '--batch with multiple sha1s gives correct format' '
+ test "$(maybe_remove_timestamp "$batch_output" 1)" = "$(maybe_remove_timestamp "$(echo_without_newline "$batch_input" | git cat-file --batch)" 1)"
+'
+
+batch_check_input="$hello_sha1
+$tree_sha1
+$commit_sha1
+$tag_sha1
+deadbeef
+
+"
+
+batch_check_output="$hello_sha1 blob $hello_size
+$tree_sha1 tree $tree_size
+$commit_sha1 commit $commit_size
+$tag_sha1 tag $tag_size
+deadbeef missing
+ missing"
+
+test_expect_success "--batch-check with multiple sha1s gives correct format" '
+ test "$batch_check_output" = \
+ "$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)"
+'
+
+test_done
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
new file mode 100755
index 0000000000..fd98e445bf
--- /dev/null
+++ b/t/t1007-hash-object.sh
@@ -0,0 +1,181 @@
+#!/bin/sh
+
+test_description="git hash-object"
+
+. ./test-lib.sh
+
+echo_without_newline() {
+ printf '%s' "$*"
+}
+
+test_blob_does_not_exist() {
+ test_expect_success 'blob does not exist in database' "
+ test_must_fail git cat-file blob $1
+ "
+}
+
+test_blob_exists() {
+ test_expect_success 'blob exists in database' "
+ git cat-file blob $1
+ "
+}
+
+hello_content="Hello World"
+hello_sha1=5e1c309dae7f45e0f39b1bf3ac3cd9db12e7d689
+
+example_content="This is an example"
+example_sha1=ddd3f836d3e3fbb7ae289aa9ae83536f76956399
+
+setup_repo() {
+ echo_without_newline "$hello_content" > hello
+ echo_without_newline "$example_content" > example
+}
+
+test_repo=test
+push_repo() {
+ test_create_repo $test_repo
+ cd $test_repo
+
+ setup_repo
+}
+
+pop_repo() {
+ cd ..
+ rm -rf $test_repo
+}
+
+setup_repo
+
+# Argument checking
+
+test_expect_success "multiple '--stdin's are rejected" '
+ echo example | test_must_fail git hash-object --stdin --stdin
+'
+
+test_expect_success "Can't use --stdin and --stdin-paths together" '
+ echo example | test_must_fail git hash-object --stdin --stdin-paths &&
+ echo example | test_must_fail git hash-object --stdin-paths --stdin
+'
+
+test_expect_success "Can't pass filenames as arguments with --stdin-paths" '
+ echo example | test_must_fail git hash-object --stdin-paths hello
+'
+
+test_expect_success "Can't use --path with --stdin-paths" '
+ echo example | test_must_fail git hash-object --stdin-paths --path=foo
+'
+
+test_expect_success "Can't use --stdin-paths with --no-filters" '
+ echo example | test_must_fail git hash-object --stdin-paths --no-filters
+'
+
+test_expect_success "Can't use --path with --no-filters" '
+ test_must_fail git hash-object --no-filters --path=foo
+'
+
+# Behavior
+
+push_repo
+
+test_expect_success 'hash a file' '
+ test $hello_sha1 = $(git hash-object hello)
+'
+
+test_blob_does_not_exist $hello_sha1
+
+test_expect_success 'hash from stdin' '
+ test $example_sha1 = $(git hash-object --stdin < example)
+'
+
+test_blob_does_not_exist $example_sha1
+
+test_expect_success 'hash a file and write to database' '
+ test $hello_sha1 = $(git hash-object -w hello)
+'
+
+test_blob_exists $hello_sha1
+
+test_expect_success 'git hash-object --stdin file1 <file0 first operates on file0, then file1' '
+ echo foo > file1 &&
+ obname0=$(echo bar | git hash-object --stdin) &&
+ obname1=$(git hash-object file1) &&
+ obname0new=$(echo bar | git hash-object --stdin file1 | sed -n -e 1p) &&
+ obname1new=$(echo bar | git hash-object --stdin file1 | sed -n -e 2p) &&
+ test "$obname0" = "$obname0new" &&
+ test "$obname1" = "$obname1new"
+'
+
+test_expect_success 'check that appropriate filter is invoke when --path is used' '
+ echo fooQ | tr Q "\\015" >file0 &&
+ cp file0 file1 &&
+ echo "file0 -crlf" >.gitattributes &&
+ echo "file1 crlf" >>.gitattributes &&
+ git config core.autocrlf true &&
+ file0_sha=$(git hash-object file0) &&
+ file1_sha=$(git hash-object file1) &&
+ test "$file0_sha" != "$file1_sha" &&
+ path1_sha=$(git hash-object --path=file1 file0) &&
+ path0_sha=$(git hash-object --path=file0 file1) &&
+ test "$file0_sha" = "$path0_sha" &&
+ test "$file1_sha" = "$path1_sha" &&
+ path1_sha=$(cat file0 | git hash-object --path=file1 --stdin) &&
+ path0_sha=$(cat file1 | git hash-object --path=file0 --stdin) &&
+ test "$file0_sha" = "$path0_sha" &&
+ test "$file1_sha" = "$path1_sha" &&
+ git config --unset core.autocrlf
+'
+
+test_expect_success 'check that --no-filters option works' '
+ echo fooQ | tr Q "\\015" >file0 &&
+ cp file0 file1 &&
+ echo "file0 -crlf" >.gitattributes &&
+ echo "file1 crlf" >>.gitattributes &&
+ git config core.autocrlf true &&
+ file0_sha=$(git hash-object file0) &&
+ file1_sha=$(git hash-object file1) &&
+ test "$file0_sha" != "$file1_sha" &&
+ nofilters_file1=$(git hash-object --no-filters file1) &&
+ test "$file0_sha" = "$nofilters_file1" &&
+ nofilters_file1=$(cat file1 | git hash-object --stdin) &&
+ test "$file0_sha" = "$nofilters_file1" &&
+ git config --unset core.autocrlf
+'
+
+pop_repo
+
+for args in "-w --stdin" "--stdin -w"; do
+ push_repo
+
+ test_expect_success "hash from stdin and write to database ($args)" '
+ test $example_sha1 = $(git hash-object $args < example)
+ '
+
+ test_blob_exists $example_sha1
+
+ pop_repo
+done
+
+filenames="hello
+example"
+
+sha1s="$hello_sha1
+$example_sha1"
+
+test_expect_success "hash two files with names on stdin" '
+ test "$sha1s" = "$(echo_without_newline "$filenames" | git hash-object --stdin-paths)"
+'
+
+for args in "-w --stdin-paths" "--stdin-paths -w"; do
+ push_repo
+
+ test_expect_success "hash two files with names on stdin and write to database ($args)" '
+ test "$sha1s" = "$(echo_without_newline "$filenames" | git hash-object $args)"
+ '
+
+ test_blob_exists $hello_sha1
+ test_blob_exists $example_sha1
+
+ pop_repo
+done
+
+test_done
diff --git a/t/t1008-read-tree-overlay.sh b/t/t1008-read-tree-overlay.sh
new file mode 100755
index 0000000000..f9e00285db
--- /dev/null
+++ b/t/t1008-read-tree-overlay.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+test_description='test multi-tree read-tree without merging'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo one >a &&
+ git add a &&
+ git commit -m initial &&
+ git tag initial &&
+ echo two >b &&
+ git add b &&
+ git commit -m second &&
+ git checkout -b side initial &&
+ echo three >a &&
+ mkdir b &&
+ echo four >b/c &&
+ git add b/c &&
+ git commit -m third
+'
+
+test_expect_success 'multi-read' '
+ git read-tree initial master side &&
+ (echo a; echo b/c) >expect &&
+ git ls-files >actual &&
+ test_cmp expect actual
+'
+
+test_done
+
diff --git a/t/t1009-read-tree-new-index.sh b/t/t1009-read-tree-new-index.sh
new file mode 100755
index 0000000000..59b3aa4bc4
--- /dev/null
+++ b/t/t1009-read-tree-new-index.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+test_description='test read-tree into a fresh index file'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo one >a &&
+ git add a &&
+ git commit -m initial
+'
+
+test_expect_success 'non-existent index file' '
+ rm -f new-index &&
+ GIT_INDEX_FILE=new-index git read-tree master
+'
+
+test_expect_success 'empty index file' '
+ rm -f new-index &&
+ > new-index &&
+ GIT_INDEX_FILE=new-index git read-tree master
+'
+
+test_done
+
diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh
new file mode 100755
index 0000000000..9956e3ad62
--- /dev/null
+++ b/t/t1010-mktree.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+test_description='git mktree'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ for d in a a. a0
+ do
+ mkdir "$d" && echo "$d/one" >"$d/one" &&
+ git add "$d"
+ done &&
+ echo zero >one &&
+ git update-index --add --info-only one &&
+ git write-tree --missing-ok >tree.missing &&
+ git ls-tree $(cat tree.missing) >top.missing &&
+ git ls-tree -r $(cat tree.missing) >all.missing &&
+ echo one >one &&
+ git add one &&
+ git write-tree >tree &&
+ git ls-tree $(cat tree) >top &&
+ git ls-tree -r $(cat tree) >all &&
+ test_tick &&
+ git commit -q -m one &&
+ H=$(git rev-parse HEAD) &&
+ git update-index --add --cacheinfo 160000 $H sub &&
+ test_tick &&
+ git commit -q -m two &&
+ git rev-parse HEAD^{tree} >tree.withsub &&
+ git ls-tree HEAD >top.withsub &&
+ git ls-tree -r HEAD >all.withsub
+'
+
+test_expect_success 'ls-tree piped to mktree (1)' '
+ git mktree <top >actual &&
+ test_cmp tree actual
+'
+
+test_expect_success 'ls-tree piped to mktree (2)' '
+ git mktree <top.withsub >actual &&
+ test_cmp tree.withsub actual
+'
+
+test_expect_success 'ls-tree output in wrong order given to mktree (1)' '
+ perl -e "print reverse <>" <top |
+ git mktree >actual &&
+ test_cmp tree actual
+'
+
+test_expect_success 'ls-tree output in wrong order given to mktree (2)' '
+ perl -e "print reverse <>" <top.withsub |
+ git mktree >actual &&
+ test_cmp tree.withsub actual
+'
+
+test_expect_success 'allow missing object with --missing' '
+ git mktree --missing <top.missing >actual &&
+ test_cmp tree.missing actual
+'
+
+test_expect_failure 'mktree reads ls-tree -r output (1)' '
+ git mktree <all >actual &&
+ test_cmp tree actual
+'
+
+test_expect_failure 'mktree reads ls-tree -r output (2)' '
+ git mktree <all.withsub >actual &&
+ test_cmp tree.withsub actual
+'
+
+test_done
diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh
index b9cef3422c..210e594f6f 100755
--- a/t/t1020-subdirectory.sh
+++ b/t/t1020-subdirectory.sh
@@ -21,7 +21,7 @@ LF='
'
test_expect_success 'update-index and ls-files' '
- cd $HERE &&
+ cd "$HERE" &&
git update-index --add one &&
case "`git ls-files`" in
one) echo ok one ;;
@@ -41,7 +41,7 @@ test_expect_success 'update-index and ls-files' '
'
test_expect_success 'cat-file' '
- cd $HERE &&
+ cd "$HERE" &&
two=`git ls-files -s dir/two` &&
two=`expr "$two" : "[0-7]* \\([0-9a-f]*\\)"` &&
echo "$two" &&
@@ -54,7 +54,7 @@ test_expect_success 'cat-file' '
rm -f actual dir/actual
test_expect_success 'diff-files' '
- cd $HERE &&
+ cd "$HERE" &&
echo a >>one &&
echo d >>dir/two &&
case "`git diff-files --name-only`" in
@@ -74,7 +74,7 @@ test_expect_success 'diff-files' '
'
test_expect_success 'write-tree' '
- cd $HERE &&
+ cd "$HERE" &&
top=`git write-tree` &&
echo $top &&
cd dir &&
@@ -84,7 +84,7 @@ test_expect_success 'write-tree' '
'
test_expect_success 'checkout-index' '
- cd $HERE &&
+ cd "$HERE" &&
git checkout-index -f -u one &&
cmp one original.one &&
cd dir &&
@@ -93,7 +93,7 @@ test_expect_success 'checkout-index' '
'
test_expect_success 'read-tree' '
- cd $HERE &&
+ cd "$HERE" &&
rm -f one dir/two &&
tree=`git write-tree` &&
git read-tree --reset -u "$tree" &&
@@ -107,27 +107,27 @@ test_expect_success 'read-tree' '
'
test_expect_success 'no file/rev ambiguity check inside .git' '
- cd $HERE &&
+ cd "$HERE" &&
git commit -a -m 1 &&
- cd $HERE/.git &&
+ cd "$HERE"/.git &&
git show -s HEAD
'
test_expect_success 'no file/rev ambiguity check inside a bare repo' '
- cd $HERE &&
+ cd "$HERE" &&
git clone -s --bare .git foo.git &&
cd foo.git && GIT_DIR=. git show -s HEAD
'
# This still does not work as it should...
: test_expect_success 'no file/rev ambiguity check inside a bare repo' '
- cd $HERE &&
+ cd "$HERE" &&
git clone -s --bare .git foo.git &&
cd foo.git && git show -s HEAD
'
-test_expect_success 'detection should not be fooled by a symlink' '
- cd $HERE &&
+test_expect_success SYMLINKS 'detection should not be fooled by a symlink' '
+ cd "$HERE" &&
rm -fr foo.git &&
git clone -s .git another &&
ln -s another yetanother &&
diff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh
index 7f7fc36734..c4414ff576 100755
--- a/t/t1100-commit-tree-options.sh
+++ b/t/t1100-commit-tree-options.sh
@@ -40,6 +40,6 @@ test_expect_success \
test_expect_success \
'compare commit' \
- 'diff expected commit'
+ 'test_cmp expected commit'
test_done
diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh
index dcb3108c29..ab55eda158 100755
--- a/t/t1200-tutorial.sh
+++ b/t/t1200-tutorial.sh
@@ -7,14 +7,18 @@ test_description='A simple turial in the form of a test case'
. ./test-lib.sh
-echo "Hello World" > hello
-echo "Silly example" > example
+test_expect_success 'blob' '
+ echo "Hello World" > hello &&
+ echo "Silly example" > example &&
-git update-index --add hello example
+ git update-index --add hello example &&
-test_expect_success 'blob' "test blob = \"$(git cat-file -t 557db03)\""
+ test blob = "$(git cat-file -t 557db03)"
+'
-test_expect_success 'blob 557db03' "test \"Hello World\" = \"$(git cat-file blob 557db03)\""
+test_expect_success 'blob 557db03' '
+ test "Hello World" = "$(git cat-file blob 557db03)"
+'
echo "It's a new day for git" >>hello
cat > diff.expect << EOF
@@ -26,25 +30,35 @@ index 557db03..263414f 100644
Hello World
+It's a new day for git
EOF
-git diff-files -p > diff.output
-test_expect_success 'git diff-files -p' 'cmp diff.expect diff.output'
-git diff > diff.output
-test_expect_success 'git diff' 'cmp diff.expect diff.output'
-
-tree=$(git write-tree 2>/dev/null)
-test_expect_success 'tree' "test 8988da15d077d4829fc51d8544c097def6644dbb = $tree"
+test_expect_success 'git diff-files -p' '
+ git diff-files -p > diff.output &&
+ test_cmp diff.expect diff.output
+'
-output="$(echo "Initial commit" | git commit-tree $(git write-tree) 2>&1 > .git/refs/heads/master)"
+test_expect_success 'git diff' '
+ git diff > diff.output &&
+ test_cmp diff.expect diff.output
+'
-git diff-index -p HEAD > diff.output
-test_expect_success 'git diff-index -p HEAD' 'cmp diff.expect diff.output'
+test_expect_success 'tree' '
+ tree=$(git write-tree 2>/dev/null)
+ test 8988da15d077d4829fc51d8544c097def6644dbb = $tree
+'
-git diff HEAD > diff.output
-test_expect_success 'git diff HEAD' 'cmp diff.expect diff.output'
+test_expect_success 'git diff-index -p HEAD' '
+ test_tick &&
+ tree=$(git write-tree) &&
+ commit=$(echo "Initial commit" | git commit-tree $tree) &&
+ git update-ref HEAD $commit &&
+ git diff-index -p HEAD > diff.output &&
+ test_cmp diff.expect diff.output
+'
-#rm hello
-#test_expect_success 'git read-tree --reset HEAD' "git read-tree --reset HEAD ; test \"hello: needs update\" = \"$(git update-index --refresh)\""
+test_expect_success 'git diff HEAD' '
+ git diff HEAD > diff.output &&
+ test_cmp diff.expect diff.output
+'
cat > whatchanged.expect << EOF
commit VARIABLE
@@ -69,40 +83,48 @@ index 0000000..557db03
+Hello World
EOF
-git whatchanged -p --root | \
- sed -e "1s/^\(.\{7\}\).\{40\}/\1VARIABLE/" \
+test_expect_success 'git whatchanged -p --root' '
+ git whatchanged -p --root |
+ sed -e "1s/^\(.\{7\}\).\{40\}/\1VARIABLE/" \
-e "2,3s/^\(.\{8\}\).*$/\1VARIABLE/" \
-> whatchanged.output
-test_expect_success 'git whatchanged -p --root' 'cmp whatchanged.expect whatchanged.output'
-
-git tag my-first-tag
-test_expect_success 'git tag my-first-tag' 'cmp .git/refs/heads/master .git/refs/tags/my-first-tag'
+ > whatchanged.output &&
+ test_cmp whatchanged.expect whatchanged.output
+'
-# TODO: test git-clone
+test_expect_success 'git tag my-first-tag' '
+ git tag my-first-tag &&
+ test_cmp .git/refs/heads/master .git/refs/tags/my-first-tag
+'
-git checkout -b mybranch
-test_expect_success 'git checkout -b mybranch' 'cmp .git/refs/heads/master .git/refs/heads/mybranch'
+test_expect_success 'git checkout -b mybranch' '
+ git checkout -b mybranch &&
+ test_cmp .git/refs/heads/master .git/refs/heads/mybranch
+'
cat > branch.expect <<EOF
master
* mybranch
EOF
-git branch > branch.output
-test_expect_success 'git branch' 'cmp branch.expect branch.output'
+test_expect_success 'git branch' '
+ git branch > branch.output &&
+ test_cmp branch.expect branch.output
+'
-git checkout mybranch
-echo "Work, work, work" >>hello
-git commit -m 'Some work.' -i hello
+test_expect_success 'git resolve now fails' '
+ git checkout mybranch &&
+ echo "Work, work, work" >>hello &&
+ test_tick &&
+ git commit -m "Some work." -i hello &&
-git checkout master
+ git checkout master &&
-echo "Play, play, play" >>hello
-echo "Lots of fun" >>example
-git commit -m 'Some fun.' -i hello example
+ echo "Play, play, play" >>hello &&
+ echo "Lots of fun" >>example &&
+ test_tick &&
+ git commit -m "Some fun." -i hello example &&
-test_expect_success 'git resolve now fails' '
- ! git merge -m "Merge work in mybranch" mybranch
+ test_must_fail git merge -m "Merge work in mybranch" mybranch
'
cat > hello << EOF
@@ -112,52 +134,132 @@ Play, play, play
Work, work, work
EOF
-git commit -m 'Merged "mybranch" changes.' -i hello
-
-test_done
-
cat > show-branch.expect << EOF
-* [master] Merged "mybranch" changes.
+* [master] Merge work in mybranch
! [mybranch] Some work.
--
-- [master] Merged "mybranch" changes.
+- [master] Merge work in mybranch
*+ [mybranch] Some work.
+* [master^] Some fun.
EOF
-git show-branch --topo-order master mybranch > show-branch.output
-test_expect_success 'git show-branch' 'cmp show-branch.expect show-branch.output'
-
-git checkout mybranch
+test_expect_success 'git show-branch' '
+ test_tick &&
+ git commit -m "Merge work in mybranch" -i hello &&
+ git show-branch --topo-order --more=1 master mybranch \
+ > show-branch.output &&
+ test_cmp show-branch.expect show-branch.output
+'
cat > resolve.expect << EOF
-Updating from VARIABLE to VARIABLE
+Updating VARIABLE..VARIABLE
+FASTFORWARD (no commit created; -m option ignored)
example | 1 +
hello | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
EOF
-git merge -s "Merge upstream changes." master | \
- sed -e "1s/[0-9a-f]\{40\}/VARIABLE/g" >resolve.output
-test_expect_success 'git resolve' 'cmp resolve.expect resolve.output'
+test_expect_success 'git resolve' '
+ git checkout mybranch &&
+ git merge -m "Merge upstream changes." master |
+ sed -e "1s/[0-9a-f]\{7\}/VARIABLE/g" \
+ -e "s/^Fast[- ]forward /FASTFORWARD /" >resolve.output &&
+ test_cmp resolve.expect resolve.output
+'
cat > show-branch2.expect << EOF
-! [master] Merged "mybranch" changes.
- * [mybranch] Merged "mybranch" changes.
+! [master] Merge work in mybranch
+ * [mybranch] Merge work in mybranch
+--
+-- [master] Merge work in mybranch
+EOF
+
+test_expect_success 'git show-branch (part 2)' '
+ git show-branch --topo-order master mybranch > show-branch2.output &&
+ test_cmp show-branch2.expect show-branch2.output
+'
+
+cat > show-branch3.expect << EOF
+! [master] Merge work in mybranch
+ * [mybranch] Merge work in mybranch
+--
+-- [master] Merge work in mybranch
++* [master^2] Some work.
++* [master^] Some fun.
+EOF
+
+test_expect_success 'git show-branch (part 3)' '
+ git show-branch --topo-order --more=2 master mybranch \
+ > show-branch3.output &&
+ test_cmp show-branch3.expect show-branch3.output
+'
+
+test_expect_success 'rewind to "Some fun." and "Some work."' '
+ git checkout mybranch &&
+ git reset --hard master^2 &&
+ git checkout master &&
+ git reset --hard master^
+'
+
+cat > show-branch4.expect << EOF
+* [master] Some fun.
+ ! [mybranch] Some work.
--
--- [master] Merged "mybranch" changes.
+* [master] Some fun.
+ + [mybranch] Some work.
+*+ [master^] Initial commit
+EOF
+
+test_expect_success 'git show-branch (part 4)' '
+ git show-branch --topo-order > show-branch4.output &&
+ test_cmp show-branch4.expect show-branch4.output
+'
+
+test_expect_success 'manual merge' '
+ mb=$(git merge-base HEAD mybranch) &&
+ git name-rev --name-only --tags $mb > name-rev.output &&
+ test "my-first-tag" = $(cat name-rev.output) &&
+
+ git read-tree -m -u $mb HEAD mybranch
+'
+
+cat > ls-files.expect << EOF
+100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example
+100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1 hello
+100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2 hello
+100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello
+EOF
+
+test_expect_success 'git ls-files --stage' '
+ git ls-files --stage > ls-files.output &&
+ test_cmp ls-files.expect ls-files.output
+'
+
+cat > ls-files-unmerged.expect << EOF
+100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1 hello
+100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2 hello
+100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello
EOF
-git show-branch --topo-order master mybranch > show-branch2.output
-test_expect_success 'git show-branch' 'cmp show-branch2.expect show-branch2.output'
+test_expect_success 'git ls-files --unmerged' '
+ git ls-files --unmerged > ls-files-unmerged.output &&
+ test_cmp ls-files-unmerged.expect ls-files-unmerged.output
+'
-# TODO: test git fetch
+test_expect_success 'git-merge-index' '
+ test_must_fail git merge-index git-merge-one-file hello
+'
-# TODO: test git push
+test_expect_success 'git ls-files --stage (part 2)' '
+ git ls-files --stage > ls-files.output2 &&
+ test_cmp ls-files.expect ls-files.output2
+'
test_expect_success 'git repack' 'git repack'
test_expect_success 'git prune-packed' 'git prune-packed'
test_expect_success '-> only packed objects' '
- ! find -type f .git/objects/[0-9a-f][0-9a-f]
+ git prune && # Remove conflict marked blobs
+ test $(find .git/objects/[0-9a-f][0-9a-f] -type f -print 2>/dev/null | wc -l) = 0
'
test_done
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index a675cbb51b..83b7294010 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -118,7 +118,14 @@ EOF
test_expect_success 'multiple unset is correct' 'cmp .git/config expect'
-mv .git/config2 .git/config
+cp .git/config2 .git/config
+
+test_expect_success '--replace-all missing value' '
+ test_must_fail git config --replace-all beta.haha &&
+ test_cmp .git/config2 .git/config
+'
+
+rm .git/config2
test_expect_success '--replace-all' \
'git config --replace-all beta.haha gamma'
@@ -201,7 +208,7 @@ test_expect_success 'non-match value' \
'test wow = $(git config --get nextsection.nonewline !for)'
test_expect_success 'ambiguous get' '
- ! git config --get nextsection.nonewline
+ test_must_fail git config --get nextsection.nonewline
'
test_expect_success 'get multivar' \
@@ -223,15 +230,15 @@ EOF
test_expect_success 'multivar replace' 'cmp .git/config expect'
test_expect_success 'ambiguous value' '
- ! git config nextsection.nonewline
+ test_must_fail git config nextsection.nonewline
'
test_expect_success 'ambiguous unset' '
- ! git config --unset nextsection.nonewline
+ test_must_fail git config --unset nextsection.nonewline
'
test_expect_success 'invalid unset' '
- ! git config --unset somesection.nonewline
+ test_must_fail git config --unset somesection.nonewline
'
git config --unset nextsection.nonewline "wow3$"
@@ -248,7 +255,7 @@ EOF
test_expect_success 'multivar unset' 'cmp .git/config expect'
-test_expect_success 'invalid key' '! git config inval.2key blabla'
+test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla'
test_expect_success 'correct key' 'git config 123456.a123 987'
@@ -336,10 +343,10 @@ test_expect_success 'get bool variable with empty value' \
'git config --bool emptyvalue.variable > output &&
cmp output expect'
-git config > output 2>&1
-
-test_expect_success 'no arguments, but no crash' \
- "test $? = 129 && grep usage output"
+test_expect_success 'no arguments, but no crash' '
+ test_must_fail git config >output 2>&1 &&
+ grep usage output
+'
cat > .git/config << EOF
[a.b]
@@ -373,7 +380,7 @@ EOF
test_expect_success 'new variable inserts into proper section' 'cmp .git/config expect'
test_expect_success 'alternative GIT_CONFIG (non-existing file should fail)' \
- 'git config --file non-existing-config -l; test $? != 0'
+ 'test_must_fail git config --file non-existing-config -l'
cat > other-config << EOF
[ein]
@@ -427,13 +434,14 @@ cat > expect << EOF
weird
EOF
-test_expect_success "rename succeeded" "git diff expect .git/config"
+test_expect_success "rename succeeded" "test_cmp expect .git/config"
test_expect_success "rename non-existing section" '
- ! git config --rename-section branch."world domination" branch.drei
+ test_must_fail git config --rename-section \
+ branch."world domination" branch.drei
'
-test_expect_success "rename succeeded" "git diff expect .git/config"
+test_expect_success "rename succeeded" "test_cmp expect .git/config"
test_expect_success "rename another section" \
'git config --rename-section branch."1 234 blabl/a" branch.drei'
@@ -449,7 +457,29 @@ cat > expect << EOF
weird
EOF
-test_expect_success "rename succeeded" "git diff expect .git/config"
+test_expect_success "rename succeeded" "test_cmp expect .git/config"
+
+cat >> .git/config << EOF
+[branch "vier"] z = 1
+EOF
+
+test_expect_success "rename a section with a var on the same line" \
+ 'git config --rename-section branch.vier branch.zwei'
+
+cat > expect << EOF
+# Hallo
+ #Bello
+[branch "zwei"]
+ x = 1
+[branch "zwei"]
+ y = 1
+[branch "drei"]
+weird
+[branch "zwei"]
+ z = 1
+EOF
+
+test_expect_success "rename succeeded" "test_cmp expect .git/config"
cat >> .git/config << EOF
[branch "zwei"] a = 1 [branch "vier"]
@@ -465,7 +495,7 @@ weird
EOF
test_expect_success "section was removed properly" \
- "git diff -u expect .git/config"
+ "test_cmp expect .git/config"
rm .git/config
@@ -545,11 +575,11 @@ test_expect_success bool '
test_expect_success 'invalid bool (--get)' '
git config bool.nobool foobar &&
- ! git config --bool --get bool.nobool'
+ test_must_fail git config --bool --get bool.nobool'
test_expect_success 'invalid bool (set)' '
- ! git config --bool bool.nobool foobar'
+ test_must_fail git config --bool bool.nobool foobar'
rm .git/config
@@ -669,7 +699,7 @@ EOF
test_expect_success 'quoting' 'cmp .git/config expect'
test_expect_success 'key with newline' '
- ! git config "key.with
+ test_must_fail git config "key.with
newline" 123'
test_expect_success 'value with newline' 'git config key.sub value.with\\\
@@ -725,7 +755,12 @@ echo >>result
test_expect_success '--null --get-regexp' 'cmp result expect'
-test_expect_success 'symlinked configuration' '
+test_expect_success 'inner whitespace kept verbatim' '
+ git config section.val "foo bar" &&
+ test "z$(git config section.val)" = "zfoo bar"
+'
+
+test_expect_success SYMLINKS 'symlinked configuration' '
ln -s notyet myconfig &&
GIT_CONFIG=myconfig git config test.frotz nitfol &&
@@ -740,4 +775,14 @@ test_expect_success 'symlinked configuration' '
'
+test_expect_success 'check split_cmdline return' "
+ git config alias.split-cmdline-fix 'echo \"' &&
+ test_must_fail git split-cmdline-fix &&
+ echo foo > foo &&
+ git add foo &&
+ git commit -m 'initial commit' &&
+ git config branch.master.mergeoptions 'echo \"' &&
+ test_must_fail git merge master
+ "
+
test_done
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 5e4252a320..de42d21c92 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -7,6 +7,9 @@ test_description='Test shared repository initialization'
. ./test-lib.sh
+# Remove a default ACL from the test dir if possible.
+setfacl -k . 2>/dev/null
+
# User must have read permissions to the repo -> failure on --shared=0400
test_expect_success 'shared = 0400 (faulty permission u-w)' '
mkdir sub && (
@@ -17,6 +20,33 @@ test_expect_success 'shared = 0400 (faulty permission u-w)' '
test $ret != "0"
'
+modebits () {
+ ls -l "$1" | sed -e 's|^\(..........\).*|\1|'
+}
+
+for u in 002 022
+do
+ test_expect_success POSIXPERM "shared=1 does not clear bits preset by umask $u" '
+ mkdir sub && (
+ cd sub &&
+ umask $u &&
+ git init --shared=1 &&
+ test 1 = "$(git config core.sharedrepository)"
+ ) &&
+ actual=$(ls -l sub/.git/HEAD)
+ case "$actual" in
+ -rw-rw-r--*)
+ : happy
+ ;;
+ *)
+ echo Oops, .git/HEAD is not 0664 but $actual
+ false
+ ;;
+ esac
+ '
+ rm -rf sub
+done
+
test_expect_success 'shared=all' '
mkdir sub &&
cd sub &&
@@ -24,7 +54,7 @@ test_expect_success 'shared=all' '
test 2 = $(git config core.sharedrepository)
'
-test_expect_success 'update-server-info honors core.sharedRepository' '
+test_expect_success POSIXPERM 'update-server-info honors core.sharedRepository' '
: > a1 &&
git add a1 &&
test_tick &&
@@ -55,12 +85,11 @@ do
git config core.sharedrepository "$u" &&
umask 0277 &&
- test_expect_success "shared = $u ($y) ro" '
+ test_expect_success POSIXPERM "shared = $u ($y) ro" '
rm -f .git/info/refs &&
git update-server-info &&
- actual="$(ls -l .git/info/refs)" &&
- actual=${actual%% *} &&
+ actual="$(modebits .git/info/refs)" &&
test "x$actual" = "x-$y" || {
ls -lt .git/info
false
@@ -68,12 +97,11 @@ do
'
umask 077 &&
- test_expect_success "shared = $u ($x) rw" '
+ test_expect_success POSIXPERM "shared = $u ($x) rw" '
rm -f .git/info/refs &&
git update-server-info &&
- actual="$(ls -l .git/info/refs)" &&
- actual=${actual%% *} &&
+ actual="$(modebits .git/info/refs)" &&
test "x$actual" = "x-$x" || {
ls -lt .git/info
false
@@ -83,4 +111,60 @@ do
done
+test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' '
+ git config core.sharedRepository group &&
+ git reflog expire --all &&
+ actual="$(ls -l .git/logs/refs/heads/master)" &&
+ case "$actual" in
+ -rw-rw-*)
+ : happy
+ ;;
+ *)
+ echo Ooops, .git/logs/refs/heads/master is not 0662 [$actual]
+ false
+ ;;
+ esac
+'
+
+test_expect_success POSIXPERM 'forced modes' '
+ mkdir -p templates/hooks &&
+ echo update-server-info >templates/hooks/post-update &&
+ chmod +x templates/hooks/post-update &&
+ echo : >random-file &&
+ mkdir new &&
+ (
+ cd new &&
+ umask 002 &&
+ git init --shared=0660 --template=../templates &&
+ >frotz &&
+ git add frotz &&
+ git commit -a -m initial &&
+ git repack
+ ) &&
+ # List repository files meant to be protected; note that
+ # COMMIT_EDITMSG does not matter---0mode is not about a
+ # repository with a work tree.
+ find new/.git -type f -name COMMIT_EDITMSG -prune -o -print |
+ xargs ls -ld >actual &&
+
+ # Everything must be unaccessible to others
+ test -z "$(sed -e "/^.......---/d" actual)" &&
+
+ # All directories must have either 2770 or 770
+ test -z "$(sed -n -e "/^drwxrw[sx]---/d" -e "/^d/p" actual)" &&
+
+ # post-update hook must be 0770
+ test -z "$(sed -n -e "/post-update/{
+ /^-rwxrwx---/d
+ p
+ }" actual)" &&
+
+ # All files inside objects must be accessible by us
+ test -z "$(sed -n -e "/objects\//{
+ /^d/d
+ /^-r.-r.----/d
+ p
+ }" actual)"
+'
+
test_done
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 9be0770e76..8d305b4372 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -41,7 +41,7 @@ test_expect_success 'gitdir required mode on normal repos' '
cd test && git apply --check --index ../test.patch)'
test_expect_success 'gitdir required mode on unsupported repo' '
- (cd test2 && ! git apply --check --index ../test.patch)
+ (cd test2 && test_must_fail git apply --check --index ../test.patch)
'
test_done
diff --git a/t/t1303-wacky-config.sh b/t/t1303-wacky-config.sh
index 99985dcd79..080117c6bc 100755
--- a/t/t1303-wacky-config.sh
+++ b/t/t1303-wacky-config.sh
@@ -10,8 +10,8 @@ setup() {
check() {
echo "$2" >expected
- git config --get "$1" >actual
- git diff actual expected
+ git config --get "$1" >actual 2>&1
+ test_cmp actual expected
}
test_expect_success 'modify same key' '
@@ -34,4 +34,17 @@ test_expect_success 'add key in different section' '
check section2.key bar
'
+SECTION="test.q\"s\\sq'sp e.key"
+test_expect_success 'make sure git config escapes section names properly' '
+ git config "$SECTION" bar &&
+ check "$SECTION" bar
+'
+
+LONG_VALUE=$(printf "x%01021dx a" 7)
+test_expect_success 'do not crash on special long config line' '
+ setup &&
+ git config section.key "$LONG_VALUE" &&
+ check section.key "fatal: bad config file line 2 in .git/config"
+'
+
test_done
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 78cd41245b..54ba3df95f 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -32,6 +32,22 @@ test_expect_success \
"create $m" \
"git update-ref $m $B $A &&
test $B"' = $(cat .git/'"$m"')'
+test_expect_success "fail to delete $m with stale ref" '
+ test_must_fail git update-ref -d $m $A &&
+ test $B = "$(cat .git/$m)"
+'
+test_expect_success "delete $m" '
+ git update-ref -d $m $B &&
+ ! test -f .git/$m
+'
+rm -f .git/$m
+
+test_expect_success "delete $m without oldvalue verification" "
+ git update-ref $m $A &&
+ test $A = \$(cat .git/$m) &&
+ git update-ref -d $m &&
+ ! test -f .git/$m
+"
rm -f .git/$m
test_expect_success \
@@ -49,10 +65,36 @@ test_expect_success \
"create $m (by HEAD)" \
"git update-ref HEAD $B $A &&
test $B"' = $(cat .git/'"$m"')'
+test_expect_success "fail to delete $m (by HEAD) with stale ref" '
+ test_must_fail git update-ref -d HEAD $A &&
+ test $B = $(cat .git/$m)
+'
+test_expect_success "delete $m (by HEAD)" '
+ git update-ref -d HEAD $B &&
+ ! test -f .git/$m
+'
rm -f .git/$m
+cp -f .git/HEAD .git/HEAD.orig
+test_expect_success "delete symref without dereference" '
+ git update-ref --no-deref -d HEAD &&
+ ! test -f .git/HEAD
+'
+cp -f .git/HEAD.orig .git/HEAD
+
+test_expect_success "delete symref without dereference when the referred ref is packed" '
+ echo foo >foo.c &&
+ git add foo.c &&
+ git commit -m foo &&
+ git pack-refs --all &&
+ git update-ref --no-deref -d HEAD &&
+ ! test -f .git/HEAD
+'
+cp -f .git/HEAD.orig .git/HEAD
+git update-ref -d $m
+
test_expect_success '(not) create HEAD with old sha1' "
- ! git update-ref HEAD $A $B
+ test_must_fail git update-ref HEAD $A $B
"
test_expect_success "(not) prior created .git/$m" "
! test -f .git/$m
@@ -63,7 +105,7 @@ test_expect_success \
"create HEAD" \
"git update-ref HEAD $A"
test_expect_success '(not) change HEAD with wrong SHA1' "
- ! git update-ref HEAD $B $Z
+ test_must_fail git update-ref HEAD $B $Z
"
test_expect_success "(not) changed .git/$m" "
! test $B"' = $(cat .git/'"$m"')
@@ -95,7 +137,7 @@ $B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150860 +0000
EOF
test_expect_success \
"verifying $m's log" \
- "diff expect .git/logs/$m"
+ "test_cmp expect .git/logs/$m"
rm -rf .git/$m .git/logs expect
test_expect_success \
@@ -126,12 +168,13 @@ $B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 +0000
EOF
test_expect_success \
"verifying $m's log" \
- 'diff expect .git/logs/$m'
+ 'test_cmp expect .git/logs/$m'
rm -f .git/$m .git/logs/$m expect
git update-ref $m $D
cat >.git/logs/$m <<EOF
-$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+0000000000000000000000000000000000000000 $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500
$A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500
$F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500
$Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500
@@ -162,6 +205,12 @@ test_expect_success \
'Query "master@{May 26 2005 23:32:00}" (exactly history start)' \
'rm -f o e
git rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e &&
+ test '"$C"' = $(cat o) &&
+ test "" = "$(cat e)"'
+test_expect_success \
+ 'Query "master@{May 26 2005 23:32:30}" (first non-creation change)' \
+ 'rm -f o e
+ git rev-parse --verify "master@{May 26 2005 23:32:30}" >o 2>e &&
test '"$A"' = $(cat o) &&
test "" = "$(cat e)"'
test_expect_success \
@@ -197,21 +246,21 @@ test_expect_success \
'echo TEST >F &&
git add F &&
GIT_AUTHOR_DATE="2005-05-26 23:30" \
- GIT_COMMITTER_DATE="2005-05-26 23:30" git-commit -m add -a &&
+ GIT_COMMITTER_DATE="2005-05-26 23:30" git commit -m add -a &&
h_TEST=$(git rev-parse --verify HEAD)
echo The other day this did not work. >M &&
echo And then Bob told me how to fix it. >>M &&
echo OTHER >F &&
GIT_AUTHOR_DATE="2005-05-26 23:41" \
- GIT_COMMITTER_DATE="2005-05-26 23:41" git-commit -F M -a &&
+ GIT_COMMITTER_DATE="2005-05-26 23:41" git commit -F M -a &&
h_OTHER=$(git rev-parse --verify HEAD) &&
GIT_AUTHOR_DATE="2005-05-26 23:44" \
- GIT_COMMITTER_DATE="2005-05-26 23:44" git-commit --amend &&
+ GIT_COMMITTER_DATE="2005-05-26 23:44" git commit --amend &&
h_FIXED=$(git rev-parse --verify HEAD) &&
echo Merged initial commit and a later commit. >M &&
echo $h_TEST >.git/MERGE_HEAD &&
GIT_AUTHOR_DATE="2005-05-26 23:45" \
- GIT_COMMITTER_DATE="2005-05-26 23:45" git-commit -F M &&
+ GIT_COMMITTER_DATE="2005-05-26 23:45" git commit -F M &&
h_MERGED=$(git rev-parse --verify HEAD) &&
rm -f M'
@@ -222,8 +271,8 @@ $h_OTHER $h_FIXED $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117151040 +0000 co
$h_FIXED $h_MERGED $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117151100 +0000 commit (merge): Merged initial commit and a later commit.
EOF
test_expect_success \
- 'git-commit logged updates' \
- "diff expect .git/logs/$m"
+ 'git commit logged updates' \
+ "test_cmp expect .git/logs/$m"
unset h_TEST h_OTHER h_FIXED h_MERGED
test_expect_success \
diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh
new file mode 100755
index 0000000000..7fa5f5b22a
--- /dev/null
+++ b/t/t1401-symbolic-ref.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+test_description='basic symbolic-ref tests'
+. ./test-lib.sh
+
+# If the tests munging HEAD fail, they can break detection of
+# the git repo, meaning that further tests will operate on
+# the surrounding git repo instead of the trash directory.
+reset_to_sane() {
+ echo ref: refs/heads/foo >.git/HEAD
+}
+
+test_expect_success 'symbolic-ref writes HEAD' '
+ git symbolic-ref HEAD refs/heads/foo &&
+ echo ref: refs/heads/foo >expect &&
+ test_cmp expect .git/HEAD
+'
+
+test_expect_success 'symbolic-ref reads HEAD' '
+ echo refs/heads/foo >expect &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'symbolic-ref refuses non-ref for HEAD' '
+ test_must_fail git symbolic-ref HEAD foo
+'
+reset_to_sane
+
+test_expect_success 'symbolic-ref refuses bare sha1' '
+ echo content >file && git add file && git commit -m one
+ test_must_fail git symbolic-ref HEAD `git rev-parse HEAD`
+'
+reset_to_sane
+
+test_done
diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh
new file mode 100755
index 0000000000..eb45afb018
--- /dev/null
+++ b/t/t1402-check-ref-format.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+test_description='Test git check-ref-format'
+
+. ./test-lib.sh
+
+valid_ref() {
+ test_expect_success "ref name '$1' is valid" \
+ "git check-ref-format '$1'"
+}
+invalid_ref() {
+ test_expect_success "ref name '$1' is not valid" \
+ "test_must_fail git check-ref-format '$1'"
+}
+
+valid_ref 'heads/foo'
+invalid_ref 'foo'
+valid_ref 'foo/bar/baz'
+valid_ref 'refs///heads/foo'
+invalid_ref 'heads/foo/'
+invalid_ref './foo'
+invalid_ref '.refs/foo'
+invalid_ref 'heads/foo..bar'
+invalid_ref 'heads/foo?bar'
+valid_ref 'foo./bar'
+invalid_ref 'heads/foo.lock'
+valid_ref 'heads/foo@bar'
+invalid_ref 'heads/v@{ation'
+invalid_ref 'heads/foo\bar'
+
+test_expect_success "check-ref-format --branch @{-1}" '
+ T=$(git write-tree) &&
+ sha1=$(echo A | git commit-tree $T) &&
+ git update-ref refs/heads/master $sha1 &&
+ git update-ref refs/remotes/origin/master $sha1
+ git checkout master &&
+ git checkout origin/master &&
+ git checkout master &&
+ refname=$(git check-ref-format --branch @{-1}) &&
+ test "$refname" = "$sha1" &&
+ refname2=$(git check-ref-format --branch @{-2}) &&
+ test "$refname2" = master'
+
+valid_ref_normalized() {
+ test_expect_success "ref name '$1' simplifies to '$2'" "
+ refname=\$(git check-ref-format --print '$1') &&
+ test \"\$refname\" = '$2'"
+}
+invalid_ref_normalized() {
+ test_expect_success "check-ref-format --print rejects '$1'" "
+ test_must_fail git check-ref-format --print '$1'"
+}
+
+valid_ref_normalized 'heads/foo' 'heads/foo'
+valid_ref_normalized 'refs///heads/foo' 'refs/heads/foo'
+invalid_ref_normalized 'foo'
+invalid_ref_normalized 'heads/foo/../bar'
+invalid_ref_normalized 'heads/./foo'
+invalid_ref_normalized 'heads\foo'
+
+test_done
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 73f830db23..80af6b9b7e 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -70,9 +70,7 @@ test_expect_success setup '
E=`git rev-parse --verify HEAD:A/B/E` &&
check_fsck &&
- chmod +x C &&
- ( test "`git config --bool core.filemode`" != false ||
- echo executable >>C ) &&
+ test_chmod +x C &&
git add C &&
test_tick && git commit -m dragon &&
L=`git rev-parse --verify HEAD` &&
@@ -188,16 +186,30 @@ test_expect_success 'delete' '
test_tick &&
git commit -m tiger C &&
- test 5 = $(git reflog | wc -l) &&
+ HEAD_entry_count=$(git reflog | wc -l)
+ master_entry_count=$(git reflog show master | wc -l)
+
+ test $HEAD_entry_count = 5 &&
+ test $master_entry_count = 5 &&
+
git reflog delete master@{1} &&
git reflog show master > output &&
- test 4 = $(wc -l < output) &&
+ test $(($master_entry_count - 1)) = $(wc -l < output) &&
+ test $HEAD_entry_count = $(git reflog | wc -l) &&
! grep ox < output &&
+ master_entry_count=$(wc -l < output)
+
+ git reflog delete HEAD@{1} &&
+ test $(($HEAD_entry_count -1)) = $(git reflog | wc -l) &&
+ test $master_entry_count = $(git reflog show master | wc -l) &&
+
+ HEAD_entry_count=$(git reflog | wc -l)
+
git reflog delete master@{07.04.2005.15:15:00.-0700} &&
git reflog show master > output &&
- test 3 = $(wc -l < output) &&
+ test $(($master_entry_count - 1)) = $(wc -l < output) &&
! grep dragon < output
'
diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh
new file mode 100755
index 0000000000..c18ed8edf9
--- /dev/null
+++ b/t/t1411-reflog-show.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+test_description='Test reflog display routines'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo content >file &&
+ git add file &&
+ test_tick &&
+ git commit -m one
+'
+
+cat >expect <<'EOF'
+Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
+Reflog message: commit (initial): one
+EOF
+test_expect_success 'log -g shows reflog headers' '
+ git log -g -1 >tmp &&
+ grep ^Reflog <tmp >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+e46513e HEAD@{0}: commit (initial): one
+EOF
+test_expect_success 'oneline reflog format' '
+ git log -g -1 --oneline >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter <committer@example.com>)
+Reflog message: commit (initial): one
+EOF
+test_expect_success 'using @{now} syntax shows reflog date (multiline)' '
+ git log -g -1 HEAD@{now} >tmp &&
+ grep ^Reflog <tmp >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
+EOF
+test_expect_success 'using @{now} syntax shows reflog date (oneline)' '
+ git log -g -1 --oneline HEAD@{now} >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+Reflog: HEAD@{1112911993 -0700} (C O Mitter <committer@example.com>)
+Reflog message: commit (initial): one
+EOF
+test_expect_success 'using --date= shows reflog date (multiline)' '
+ git log -g -1 --date=raw >tmp &&
+ grep ^Reflog <tmp >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+e46513e HEAD@{1112911993 -0700}: commit (initial): one
+EOF
+test_expect_success 'using --date= shows reflog date (oneline)' '
+ git log -g -1 --oneline --date=raw >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
new file mode 100755
index 0000000000..a22632f483
--- /dev/null
+++ b/t/t1450-fsck.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+test_description='git fsck random collection of tests'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ test_commit A fileA one &&
+ git checkout HEAD^0 &&
+ test_commit B fileB two &&
+ git tag -d A B &&
+ git reflog expire --expire=now --all
+'
+
+test_expect_success 'HEAD is part of refs' '
+ test 0 = $(git fsck | wc -l)
+'
+
+test_expect_success 'loose objects borrowed from alternate are not missing' '
+ mkdir another &&
+ (
+ cd another &&
+ git init &&
+ echo ../../../.git/objects >.git/objects/info/alternates &&
+ test_commit C fileC one &&
+ git fsck >out &&
+ ! grep "missing blob" out
+ )
+'
+
+# Corruption tests follow. Make sure to remove all traces of the
+# specific corruption you test afterwards, lest a later test trip over
+# it.
+
+test_expect_success 'object with bad sha1' '
+ sha=$(echo blob | git hash-object -w --stdin) &&
+ echo $sha &&
+ old=$(echo $sha | sed "s+^..+&/+") &&
+ new=$(dirname $old)/ffffffffffffffffffffffffffffffffffffff &&
+ sha="$(dirname $new)$(basename $new)"
+ mv .git/objects/$old .git/objects/$new &&
+ git update-index --add --cacheinfo 100644 $sha foo &&
+ tree=$(git write-tree) &&
+ cmt=$(echo bogus | git commit-tree $tree) &&
+ git update-ref refs/heads/bogus $cmt &&
+ (git fsck 2>out; true) &&
+ grep "$sha.*corrupt" out &&
+ rm -f .git/objects/$new &&
+ git update-ref -d refs/heads/bogus &&
+ git read-tree -u --reset HEAD
+'
+
+test_expect_success 'branch pointing to non-commit' '
+ git rev-parse HEAD^{tree} > .git/refs/heads/invalid &&
+ git fsck 2>out &&
+ grep "not a commit" out &&
+ git update-ref -d refs/heads/invalid
+'
+
+cat > invalid-tag <<EOF
+object ffffffffffffffffffffffffffffffffffffffff
+type commit
+tag invalid
+tagger T A Gger <tagger@example.com> 1234567890 -0000
+
+This is an invalid tag.
+EOF
+
+test_expect_failure 'tag pointing to nonexistent' '
+ tag=$(git hash-object -w --stdin < invalid-tag) &&
+ echo $tag > .git/refs/tags/invalid &&
+ git fsck --tags 2>out &&
+ cat out &&
+ grep "could not load tagged object" out &&
+ rm .git/refs/tags/invalid
+'
+
+cat > wrong-tag <<EOF
+object $(echo blob | git hash-object -w --stdin)
+type commit
+tag wrong
+tagger T A Gger <tagger@example.com> 1234567890 -0000
+
+This is an invalid tag.
+EOF
+
+test_expect_failure 'tag pointing to something else than its type' '
+ tag=$(git hash-object -w --stdin < wrong-tag) &&
+ echo $tag > .git/refs/tags/wrong &&
+ git fsck --tags 2>out &&
+ cat out &&
+ grep "some sane error message" out &&
+ rm .git/refs/tags/wrong
+'
+
+
+
+test_done
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 38a2bf09af..48ee07779d 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -26,21 +26,28 @@ test_rev_parse() {
"test '$1' = \"\$(git rev-parse --show-prefix)\""
shift
[ $# -eq 0 ] && return
+
+ test_expect_success "$name: git-dir" \
+ "test '$1' = \"\$(git rev-parse --git-dir)\""
+ shift
+ [ $# -eq 0 ] && return
}
-# label is-bare is-inside-git is-inside-work prefix
+# label is-bare is-inside-git is-inside-work prefix git-dir
+
+ROOT=$(pwd)
-test_rev_parse toplevel false false true ''
+test_rev_parse toplevel false false true '' .git
cd .git || exit 1
-test_rev_parse .git/ false true false ''
+test_rev_parse .git/ false true false '' .
cd objects || exit 1
-test_rev_parse .git/objects/ false true false ''
+test_rev_parse .git/objects/ false true false '' "$ROOT/.git"
cd ../.. || exit 1
mkdir -p sub/dir || exit 1
cd sub/dir || exit 1
-test_rev_parse subdirectory false false true sub/dir/
+test_rev_parse subdirectory false false true sub/dir/ "$ROOT/.git"
cd ../.. || exit 1
git config core.bare true
@@ -51,8 +58,9 @@ test_rev_parse 'core.bare undefined' false false true
mkdir work || exit 1
cd work || exit 1
-export GIT_DIR=../.git
-export GIT_CONFIG="$(pwd)"/../.git/config
+GIT_DIR=../.git
+GIT_CONFIG="$(pwd)"/../.git/config
+export GIT_DIR GIT_CONFIG
git config core.bare false
test_rev_parse 'GIT_DIR=../.git, core.bare = false' false false true ''
@@ -64,8 +72,8 @@ git config --unset core.bare
test_rev_parse 'GIT_DIR=../.git, core.bare undefined' false false true ''
mv ../.git ../repo.git || exit 1
-export GIT_DIR=../repo.git
-export GIT_CONFIG="$(pwd)"/../repo.git/config
+GIT_DIR=../repo.git
+GIT_CONFIG="$(pwd)"/../repo.git/config
git config core.bare false
test_rev_parse 'GIT_DIR=../repo.git, core.bare = false' false false true ''
diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh
index 7ee3820ce9..9df301211c 100755
--- a/t/t1501-worktree.sh
+++ b/t/t1501-worktree.sh
@@ -28,28 +28,30 @@ test_rev_parse() {
[ $# -eq 0 ] && return
}
+EMPTY_TREE=$(git write-tree)
mkdir -p work/sub/dir || exit 1
mv .git repo.git || exit 1
say "core.worktree = relative path"
-export GIT_DIR=repo.git
-export GIT_CONFIG="$(pwd)"/$GIT_DIR/config
+GIT_DIR=repo.git
+GIT_CONFIG="$(pwd)"/$GIT_DIR/config
+export GIT_DIR GIT_CONFIG
unset GIT_WORK_TREE
git config core.worktree ../work
test_rev_parse 'outside' false false false
cd work || exit 1
-export GIT_DIR=../repo.git
-export GIT_CONFIG="$(pwd)"/$GIT_DIR/config
+GIT_DIR=../repo.git
+GIT_CONFIG="$(pwd)"/$GIT_DIR/config
test_rev_parse 'inside' false false true ''
cd sub/dir || exit 1
-export GIT_DIR=../../../repo.git
-export GIT_CONFIG="$(pwd)"/$GIT_DIR/config
+GIT_DIR=../../../repo.git
+GIT_CONFIG="$(pwd)"/$GIT_DIR/config
test_rev_parse 'subdirectory' false false true sub/dir/
cd ../../.. || exit 1
say "core.worktree = absolute path"
-export GIT_DIR=$(pwd)/repo.git
-export GIT_CONFIG=$GIT_DIR/config
+GIT_DIR=$(pwd)/repo.git
+GIT_CONFIG=$GIT_DIR/config
git config core.worktree "$(pwd)/work"
test_rev_parse 'outside' false false false
cd work || exit 1
@@ -59,25 +61,26 @@ test_rev_parse 'subdirectory' false false true sub/dir/
cd ../../.. || exit 1
say "GIT_WORK_TREE=relative path (override core.worktree)"
-export GIT_DIR=$(pwd)/repo.git
-export GIT_CONFIG=$GIT_DIR/config
+GIT_DIR=$(pwd)/repo.git
+GIT_CONFIG=$GIT_DIR/config
git config core.worktree non-existent
-export GIT_WORK_TREE=work
+GIT_WORK_TREE=work
+export GIT_WORK_TREE
test_rev_parse 'outside' false false false
cd work || exit 1
-export GIT_WORK_TREE=.
+GIT_WORK_TREE=.
test_rev_parse 'inside' false false true ''
cd sub/dir || exit 1
-export GIT_WORK_TREE=../..
+GIT_WORK_TREE=../..
test_rev_parse 'subdirectory' false false true sub/dir/
cd ../../.. || exit 1
mv work repo.git/work
say "GIT_WORK_TREE=absolute path, work tree below git dir"
-export GIT_DIR=$(pwd)/repo.git
-export GIT_CONFIG=$GIT_DIR/config
-export GIT_WORK_TREE=$(pwd)/repo.git/work
+GIT_DIR=$(pwd)/repo.git
+GIT_CONFIG=$GIT_DIR/config
+GIT_WORK_TREE=$(pwd)/repo.git/work
test_rev_parse 'outside' false false false
cd repo.git || exit 1
test_rev_parse 'in repo.git' false true false
@@ -104,12 +107,92 @@ test_expect_success 'repo finds its work tree from work tree, too' '
'
test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '
- cd repo.git/work/sub/dir &&
+ (cd repo.git/work/sub/dir &&
GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \
git diff --exit-code tracked &&
echo changed > tracked &&
! GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \
- git diff --exit-code tracked
+ git diff --exit-code tracked)
+'
+cat > diff-index-cached.expected <<\EOF
+:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A sub/dir/tracked
+EOF
+cat > diff-index.expected <<\EOF
+:000000 100644 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 A sub/dir/tracked
+EOF
+
+
+test_expect_success 'git diff-index' '
+ GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-index $EMPTY_TREE > result &&
+ test_cmp diff-index.expected result &&
+ GIT_DIR=repo.git git diff-index --cached $EMPTY_TREE > result &&
+ test_cmp diff-index-cached.expected result
+'
+cat >diff-files.expected <<\EOF
+:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M sub/dir/tracked
+EOF
+
+test_expect_success 'git diff-files' '
+ GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-files > result &&
+ test_cmp diff-files.expected result
+'
+
+cat >diff-TREE.expected <<\EOF
+diff --git a/sub/dir/tracked b/sub/dir/tracked
+new file mode 100644
+index 0000000..5ea2ed4
+--- /dev/null
++++ b/sub/dir/tracked
+@@ -0,0 +1 @@
++changed
+EOF
+cat >diff-TREE-cached.expected <<\EOF
+diff --git a/sub/dir/tracked b/sub/dir/tracked
+new file mode 100644
+index 0000000..e69de29
+EOF
+cat >diff-FILES.expected <<\EOF
+diff --git a/sub/dir/tracked b/sub/dir/tracked
+index e69de29..5ea2ed4 100644
+--- a/sub/dir/tracked
++++ b/sub/dir/tracked
+@@ -0,0 +1 @@
++changed
+EOF
+
+test_expect_success 'git diff' '
+ GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff $EMPTY_TREE > result &&
+ test_cmp diff-TREE.expected result &&
+ GIT_DIR=repo.git git diff --cached $EMPTY_TREE > result &&
+ test_cmp diff-TREE-cached.expected result &&
+ GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff > result &&
+ test_cmp diff-FILES.expected result
+'
+
+test_expect_success 'git grep' '
+ (cd repo.git/work/sub &&
+ GIT_DIR=../.. GIT_WORK_TREE=.. git grep -l changed | grep dir/tracked)
+'
+
+test_expect_success 'git commit' '
+ (
+ cd repo.git &&
+ GIT_DIR=. GIT_WORK_TREE=work git commit -a -m done
+ )
+'
+
+test_expect_success 'absolute pathspec should fail gracefully' '
+ (
+ cd repo.git || exit 1
+ git config --unset core.worktree
+ test_must_fail git log HEAD -- /home
+ )
+'
+
+test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '
+ : > dummy_file
+ echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file &&
+ git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file
'
test_done
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index 762af5faf7..e504058062 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -5,7 +5,7 @@ test_description='test git rev-parse --parseopt'
cat > expect.err <<EOF
usage: some-command [options] <args>...
-
+
some-command does foo and bar!
-h, --help show the help
@@ -13,15 +13,14 @@ usage: some-command [options] <args>...
--bar ... some cool option --bar with an argument
An option group Header
- -C [...] option C with an optional argument
+ -C[...] option C with an optional argument
Extras
--extra1 line above used to cause a segfault but no longer does
EOF
-test_expect_success 'test --parseopt help output' '
- git rev-parse --parseopt -- -h 2> output.err <<EOF
+cat > optionspec << EOF
some-command [options] <args>...
some-command does foo and bar!
@@ -37,7 +36,47 @@ C? option C with an optional argument
Extras
extra1 line above used to cause a segfault but no longer does
EOF
- git diff expect.err output.err
+
+test_expect_success 'test --parseopt help output' '
+ git rev-parse --parseopt -- -h 2> output.err < optionspec
+ test_cmp expect.err output.err
+'
+
+cat > expect <<EOF
+set -- --foo --bar 'ham' -- 'arg'
+EOF
+
+test_expect_success 'test --parseopt' '
+ git rev-parse --parseopt -- --foo --bar=ham 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 &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+set -- --foo -- 'arg' '--bar=ham'
+EOF
+
+test_expect_success 'test --parseopt with --' '
+ git rev-parse --parseopt -- --foo -- arg --bar=ham < optionspec > output &&
+ test_cmp expect output
+'
+
+test_expect_success 'test --parseopt --stop-at-non-option' '
+ git rev-parse --parseopt --stop-at-non-option -- --foo arg --bar=ham < optionspec > output &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+set -- --foo -- '--' 'arg' '--bar=ham'
+EOF
+
+test_expect_success 'test --parseopt --keep-dashdash' '
+ git rev-parse --parseopt --keep-dashdash -- --foo -- arg --bar=ham < optionspec > output &&
+ test_cmp expect output
'
test_done
diff --git a/t/t1503-rev-parse-verify.sh b/t/t1503-rev-parse-verify.sh
new file mode 100755
index 0000000000..cc65394947
--- /dev/null
+++ b/t/t1503-rev-parse-verify.sh
@@ -0,0 +1,107 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Christian Couder
+#
+test_description='test git rev-parse --verify'
+
+exec </dev/null
+
+. ./test-lib.sh
+
+add_line_into_file()
+{
+ _line=$1
+ _file=$2
+
+ if [ -f "$_file" ]; then
+ echo "$_line" >> $_file || return $?
+ MSG="Add <$_line> into <$_file>."
+ else
+ echo "$_line" > $_file || return $?
+ git add $_file || return $?
+ MSG="Create file <$_file> with <$_line> inside."
+ fi
+
+ test_tick
+ git commit --quiet -m "$MSG" $_file
+}
+
+HASH1=
+HASH2=
+HASH3=
+HASH4=
+
+test_expect_success 'set up basic repo with 1 file (hello) and 4 commits' '
+ add_line_into_file "1: Hello World" hello &&
+ HASH1=$(git rev-parse --verify HEAD) &&
+ add_line_into_file "2: A new day for git" hello &&
+ HASH2=$(git rev-parse --verify HEAD) &&
+ add_line_into_file "3: Another new day for git" hello &&
+ HASH3=$(git rev-parse --verify HEAD) &&
+ add_line_into_file "4: Ciao for now" hello &&
+ HASH4=$(git rev-parse --verify HEAD)
+'
+
+test_expect_success 'works with one good rev' '
+ rev_hash1=$(git rev-parse --verify $HASH1) &&
+ test "$rev_hash1" = "$HASH1" &&
+ rev_hash2=$(git rev-parse --verify $HASH2) &&
+ test "$rev_hash2" = "$HASH2" &&
+ rev_hash3=$(git rev-parse --verify $HASH3) &&
+ test "$rev_hash3" = "$HASH3" &&
+ rev_hash4=$(git rev-parse --verify $HASH4) &&
+ test "$rev_hash4" = "$HASH4" &&
+ rev_master=$(git rev-parse --verify master) &&
+ test "$rev_master" = "$HASH4" &&
+ rev_head=$(git rev-parse --verify HEAD) &&
+ test "$rev_head" = "$HASH4"
+'
+
+test_expect_success 'fails with any bad rev or many good revs' '
+ test_must_fail git rev-parse --verify 2>error &&
+ grep "single revision" error &&
+ test_must_fail git rev-parse --verify foo 2>error &&
+ grep "single revision" error &&
+ test_must_fail git rev-parse --verify HEAD bar 2>error &&
+ grep "single revision" error &&
+ test_must_fail git rev-parse --verify baz HEAD 2>error &&
+ grep "single revision" error &&
+ test_must_fail git rev-parse --verify $HASH2 HEAD 2>error &&
+ grep "single revision" error
+'
+
+test_expect_success 'fails silently when using -q' '
+ test_must_fail git rev-parse --verify --quiet 2>error &&
+ test -z "$(cat error)" &&
+ test_must_fail git rev-parse -q --verify foo 2>error &&
+ test -z "$(cat error)" &&
+ test_must_fail git rev-parse --verify -q HEAD bar 2>error &&
+ test -z "$(cat error)" &&
+ test_must_fail git rev-parse --quiet --verify baz HEAD 2>error &&
+ test -z "$(cat error)" &&
+ test_must_fail git rev-parse -q --verify $HASH2 HEAD 2>error &&
+ test -z "$(cat error)"
+'
+
+test_expect_success 'no stdout output on error' '
+ test -z "$(git rev-parse --verify)" &&
+ test -z "$(git rev-parse --verify foo)" &&
+ test -z "$(git rev-parse --verify baz HEAD)" &&
+ test -z "$(git rev-parse --verify HEAD bar)" &&
+ test -z "$(git rev-parse --verify $HASH2 HEAD)"
+'
+
+test_expect_success 'use --default' '
+ git rev-parse --verify --default master &&
+ git rev-parse --verify --default master HEAD &&
+ git rev-parse --default master --verify &&
+ git rev-parse --default master --verify HEAD &&
+ git rev-parse --verify HEAD --default master &&
+ test_must_fail git rev-parse --verify foo --default master &&
+ test_must_fail git rev-parse --default HEAD --verify bar &&
+ test_must_fail git rev-parse --verify --default HEAD baz &&
+ test_must_fail git rev-parse --default foo --verify &&
+ test_must_fail git rev-parse --verify --default bar
+'
+
+test_done
diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh
new file mode 100755
index 0000000000..df5ad8c686
--- /dev/null
+++ b/t/t1504-ceiling-dirs.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+test_description='test GIT_CEILING_DIRECTORIES'
+. ./test-lib.sh
+
+test_prefix() {
+ test_expect_success "$1" \
+ "test '$2' = \"\$(git rev-parse --show-prefix)\""
+}
+
+test_fail() {
+ test_expect_code 128 "$1: prefix" \
+ "git rev-parse --show-prefix"
+}
+
+TRASH_ROOT="$PWD"
+ROOT_PARENT=$(dirname "$TRASH_ROOT")
+
+
+unset GIT_CEILING_DIRECTORIES
+test_prefix no_ceil ""
+
+export GIT_CEILING_DIRECTORIES
+
+GIT_CEILING_DIRECTORIES=""
+test_prefix ceil_empty ""
+
+GIT_CEILING_DIRECTORIES="$ROOT_PARENT"
+test_prefix ceil_at_parent ""
+
+GIT_CEILING_DIRECTORIES="$ROOT_PARENT/"
+test_prefix ceil_at_parent_slash ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
+test_prefix ceil_at_trash ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
+test_prefix ceil_at_trash_slash ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
+test_prefix ceil_at_sub ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
+test_prefix ceil_at_sub_slash ""
+
+
+mkdir -p sub/dir || exit 1
+cd sub/dir || exit 1
+
+unset GIT_CEILING_DIRECTORIES
+test_prefix subdir_no_ceil "sub/dir/"
+
+export GIT_CEILING_DIRECTORIES
+
+GIT_CEILING_DIRECTORIES=""
+test_prefix subdir_ceil_empty "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
+test_fail subdir_ceil_at_trash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
+test_fail subdir_ceil_at_trash_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
+test_fail subdir_ceil_at_sub
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
+test_fail subdir_ceil_at_sub_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir"
+test_prefix subdir_ceil_at_subdir "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir/"
+test_prefix subdir_ceil_at_subdir_slash "sub/dir/"
+
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su"
+test_prefix subdir_ceil_at_su "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/"
+test_prefix subdir_ceil_at_su_slash "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di"
+test_prefix subdir_ceil_at_sub_di "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di"
+test_prefix subdir_ceil_at_sub_di_slash "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi"
+test_prefix subdir_ceil_at_subdi "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi"
+test_prefix subdir_ceil_at_subdi_slash "sub/dir/"
+
+
+GIT_CEILING_DIRECTORIES="/foo:$TRASH_ROOT/sub"
+test_fail second_of_two
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub:/bar"
+test_fail first_of_two
+
+GIT_CEILING_DIRECTORIES="/foo:$TRASH_ROOT/sub:/bar"
+test_fail second_of_three
+
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
+GIT_DIR=../../.git
+export GIT_DIR
+test_prefix git_dir_specified ""
+unset GIT_DIR
+
+
+cd ../.. || exit 1
+mkdir -p s/d || exit 1
+cd s/d || exit 1
+
+unset GIT_CEILING_DIRECTORIES
+test_prefix sd_no_ceil "s/d/"
+
+export GIT_CEILING_DIRECTORIES
+
+GIT_CEILING_DIRECTORIES=""
+test_prefix sd_ceil_empty "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
+test_fail sd_ceil_at_trash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
+test_fail sd_ceil_at_trash_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s"
+test_fail sd_ceil_at_s
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/"
+test_fail sd_ceil_at_s_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d"
+test_prefix sd_ceil_at_sd "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d/"
+test_prefix sd_ceil_at_sd_slash "s/d/"
+
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su"
+test_prefix sd_ceil_at_su "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/"
+test_prefix sd_ceil_at_su_slash "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di"
+test_prefix sd_ceil_at_s_di "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di"
+test_prefix sd_ceil_at_s_di_slash "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi"
+test_prefix sd_ceil_at_sdi "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi"
+test_prefix sd_ceil_at_sdi_slash "s/d/"
+
+
+test_done
diff --git a/t/t1505-rev-parse-last.sh b/t/t1505-rev-parse-last.sh
new file mode 100755
index 0000000000..d709ecf8df
--- /dev/null
+++ b/t/t1505-rev-parse-last.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+test_description='test @{-N} syntax'
+
+. ./test-lib.sh
+
+
+make_commit () {
+ echo "$1" > "$1" &&
+ git add "$1" &&
+ git commit -m "$1"
+}
+
+
+test_expect_success 'setup' '
+
+ make_commit 1 &&
+ git branch side &&
+ make_commit 2 &&
+ make_commit 3 &&
+ git checkout side &&
+ make_commit 4 &&
+ git merge master &&
+ git checkout master
+
+'
+
+# 1 -- 2 -- 3 master
+# \ \
+# \ \
+# --- 4 --- 5 side
+#
+# and 'side' should be the last branch
+
+test_rev_equivalent () {
+
+ git rev-parse "$1" > expect &&
+ git rev-parse "$2" > output &&
+ test_cmp expect output
+
+}
+
+test_expect_success '@{-1} works' '
+ test_rev_equivalent side @{-1}
+'
+
+test_expect_success '@{-1}~2 works' '
+ test_rev_equivalent side~2 @{-1}~2
+'
+
+test_expect_success '@{-1}^2 works' '
+ test_rev_equivalent side^2 @{-1}^2
+'
+
+test_expect_success '@{-1}@{1} works' '
+ test_rev_equivalent side@{1} @{-1}@{1}
+'
+
+test_expect_success '@{-2} works' '
+ test_rev_equivalent master @{-2}
+'
+
+test_expect_success '@{-3} fails' '
+ test_must_fail git rev-parse @{-3}
+'
+
+test_done
+
+
diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh
index 5141fab7cf..de3edb5d57 100755
--- a/t/t2000-checkout-cache-clash.sh
+++ b/t/t2000-checkout-cache-clash.sh
@@ -38,7 +38,7 @@ date >path1
test_expect_success \
'git checkout-index without -f should fail on conflicting work tree.' \
- '! git checkout-index -a'
+ 'test_must_fail git checkout-index -a'
test_expect_success \
'git checkout-index with -f should succeed.' \
@@ -48,4 +48,13 @@ test_expect_success \
'git checkout-index conflicting paths.' \
'test -f path0 && test -d path1 && test -f path1/file1'
+test_expect_success SYMLINKS 'checkout-index -f twice with --prefix' '
+ mkdir -p tar/get &&
+ ln -s tar/get there &&
+ echo first &&
+ git checkout-index -a -f --prefix=there/ &&
+ echo second &&
+ git checkout-index -a -f --prefix=there/
+'
+
test_done
diff --git a/t/t2001-checkout-cache-clash.sh b/t/t2001-checkout-cache-clash.sh
index ef007532b1..98aa73e823 100755
--- a/t/t2001-checkout-cache-clash.sh
+++ b/t/t2001-checkout-cache-clash.sh
@@ -59,10 +59,10 @@ test_expect_success \
'git read-tree -m $tree1 && git checkout-index -f -a'
test_debug 'show_files $tree1'
-ln -s path0 path1
-test_expect_success \
+test_expect_success SYMLINKS \
'git update-index --add a symlink.' \
- 'git update-index --add path1'
+ 'ln -s path0 path1 &&
+ git update-index --add path1'
test_expect_success \
'writing tree out with git write-tree' \
'tree3=$(git write-tree)'
diff --git a/t/t2003-checkout-cache-mkdir.sh b/t/t2003-checkout-cache-mkdir.sh
index 71894b3743..02a4fc5d36 100755
--- a/t/t2003-checkout-cache-mkdir.sh
+++ b/t/t2003-checkout-cache-mkdir.sh
@@ -19,7 +19,7 @@ test_expect_success \
echo rezrov >path1/file1 &&
git update-index --add path0 path1/file1'
-test_expect_success \
+test_expect_success SYMLINKS \
'have symlink in place where dir is expected.' \
'rm -fr path0 path1 &&
mkdir path2 &&
@@ -59,7 +59,7 @@ test_expect_success \
test ! -f path1/file1'
# Linus fix #1
-test_expect_success \
+test_expect_success SYMLINKS \
'use --prefix=tmp/orary/ where tmp is a symlink' \
'rm -fr path0 path1 path2 tmp* &&
mkdir tmp1 tmp1/orary &&
@@ -71,7 +71,7 @@ test_expect_success \
test -h tmp'
# Linus fix #2
-test_expect_success \
+test_expect_success SYMLINKS \
'use --prefix=tmp/orary- where tmp is a symlink' \
'rm -fr path0 path1 path2 tmp* &&
mkdir tmp1 &&
@@ -82,7 +82,7 @@ test_expect_success \
test -h tmp'
# Linus fix #3
-test_expect_success \
+test_expect_success SYMLINKS \
'use --prefix=tmp- where tmp-path1 is a symlink' \
'rm -fr path0 path1 path2 tmp* &&
mkdir tmp1 &&
diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh
index 39133b8c7a..36cca14d95 100755
--- a/t/t2004-checkout-cache-temp.sh
+++ b/t/t2004-checkout-cache-temp.sh
@@ -194,7 +194,7 @@ test_expect_success \
test $(cat ../$s1) = tree1asubdir/path5)
)'
-test_expect_success \
+test_expect_success SYMLINKS \
'checkout --temp symlink' '
rm -f path* .merge_* out .git/index &&
ln -s b a &&
diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh
index a84c5a6af9..9fa5610474 100755
--- a/t/t2005-checkout-index-symlinks.sh
+++ b/t/t2005-checkout-index-symlinks.sh
@@ -13,7 +13,7 @@ file if core.symlinks is false.'
test_expect_success \
'preparation' '
git config core.symlinks false &&
-l=$(echo -n file | git-hash-object -t blob -w --stdin) &&
+l=$(printf file | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info'
test_expect_success \
@@ -23,6 +23,6 @@ test -f symlink'
test_expect_success \
'the file must be the blob we added during the setup' '
-test "$(git-hash-object -t blob symlink)" = $l'
+test "$(git hash-object -t blob symlink)" = $l'
test_done
diff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh
index 0526fce163..20f33436d0 100755
--- a/t/t2007-checkout-symlink.sh
+++ b/t/t2007-checkout-symlink.sh
@@ -6,6 +6,12 @@ test_description='git checkout to switch between branches with symlink<->dir'
. ./test-lib.sh
+if ! test_have_prereq SYMLINKS
+then
+ say "symbolic links not supported - skipping tests"
+ test_done
+fi
+
test_expect_success setup '
mkdir frotz &&
diff --git a/t/t2010-checkout-ambiguous.sh b/t/t2010-checkout-ambiguous.sh
new file mode 100755
index 0000000000..7cc0a3582e
--- /dev/null
+++ b/t/t2010-checkout-ambiguous.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='checkout and pathspecs/refspecs ambiguities'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo hello >world &&
+ echo hello >all &&
+ git add all world &&
+ git commit -m initial &&
+ git branch world
+'
+
+test_expect_success 'reference must be a tree' '
+ test_must_fail git checkout $(git hash-object ./all) --
+'
+
+test_expect_success 'branch switching' '
+ test "refs/heads/master" = "$(git symbolic-ref HEAD)" &&
+ git checkout world -- &&
+ test "refs/heads/world" = "$(git symbolic-ref HEAD)"
+'
+
+test_expect_success 'checkout world from the index' '
+ echo bye > world &&
+ git checkout -- world &&
+ git diff --exit-code --quiet
+'
+
+test_expect_success 'non ambiguous call' '
+ git checkout all
+'
+
+test_expect_success 'allow the most common case' '
+ git checkout world &&
+ test "refs/heads/world" = "$(git symbolic-ref HEAD)"
+'
+
+test_expect_success 'check ambiguity' '
+ test_must_fail git checkout world all
+'
+
+test_expect_success 'disambiguate checking out from a tree-ish' '
+ echo bye > world &&
+ git checkout world -- world &&
+ git diff --exit-code --quiet
+'
+
+test_done
diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh
new file mode 100755
index 0000000000..15ebdc26eb
--- /dev/null
+++ b/t/t2011-checkout-invalid-head.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='checkout switching away from an invalid branch'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo hello >world &&
+ git add world &&
+ git commit -m initial
+'
+
+test_expect_success 'checkout should not start branch from a tree' '
+ test_must_fail git checkout -b newbranch master^{tree}
+'
+
+test_expect_success 'checkout master from invalid HEAD' '
+ echo 0000000000000000000000000000000000000000 >.git/HEAD &&
+ git checkout master --
+'
+
+test_done
diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh
new file mode 100755
index 0000000000..87b30a268c
--- /dev/null
+++ b/t/t2012-checkout-last.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+
+test_description='checkout can switch to last branch'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo hello >world &&
+ git add world &&
+ git commit -m initial &&
+ git branch other &&
+ echo "hello again" >>world &&
+ git add world &&
+ git commit -m second
+'
+
+test_expect_success '"checkout -" does not work initially' '
+ test_must_fail git checkout -
+'
+
+test_expect_success 'first branch switch' '
+ git checkout other
+'
+
+test_expect_success '"checkout -" switches back' '
+ git checkout - &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
+test_expect_success '"checkout -" switches forth' '
+ git checkout - &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/other"
+'
+
+test_expect_success 'detach HEAD' '
+ git checkout $(git rev-parse HEAD)
+'
+
+test_expect_success '"checkout -" attaches again' '
+ git checkout - &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/other"
+'
+
+test_expect_success '"checkout -" detaches again' '
+ git checkout - &&
+ test "z$(git rev-parse HEAD)" = "z$(git rev-parse other)" &&
+ test_must_fail git symbolic-ref HEAD
+'
+
+test_expect_success 'more switches' '
+ for i in 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
+ do
+ git checkout -b branch$i
+ done
+'
+
+more_switches () {
+ for i in 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
+ do
+ git checkout branch$i
+ done
+}
+
+test_expect_success 'switch to the last' '
+ more_switches &&
+ git checkout @{-1} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch2"
+'
+
+test_expect_success 'switch to second from the last' '
+ more_switches &&
+ git checkout @{-2} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch3"
+'
+
+test_expect_success 'switch to third from the last' '
+ more_switches &&
+ git checkout @{-3} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch4"
+'
+
+test_expect_success 'switch to fourth from the last' '
+ more_switches &&
+ git checkout @{-4} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch5"
+'
+
+test_expect_success 'switch to twelfth from the last' '
+ more_switches &&
+ git checkout @{-12} &&
+ test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch13"
+'
+
+test_done
diff --git a/t/t2013-checkout-submodule.sh b/t/t2013-checkout-submodule.sh
new file mode 100755
index 0000000000..fda3f0af7e
--- /dev/null
+++ b/t/t2013-checkout-submodule.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+test_description='checkout can handle submodules'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ mkdir submodule &&
+ (cd submodule &&
+ git init &&
+ test_commit first) &&
+ git add submodule &&
+ test_tick &&
+ git commit -m superproject &&
+ (cd submodule &&
+ test_commit second) &&
+ git add submodule &&
+ test_tick &&
+ git commit -m updated.superproject
+'
+
+test_expect_success '"reset <submodule>" updates the index' '
+ git update-index --refresh &&
+ git diff-files --quiet &&
+ git diff-index --quiet --cached HEAD &&
+ test_must_fail git reset HEAD^ submodule &&
+ test_must_fail git diff-files --quiet &&
+ git reset submodule &&
+ git diff-files --quiet
+'
+
+test_expect_success '"checkout <submodule>" updates the index only' '
+ git update-index --refresh &&
+ git diff-files --quiet &&
+ git diff-index --quiet --cached HEAD &&
+ git checkout HEAD^ submodule &&
+ test_must_fail git diff-files --quiet &&
+ git checkout HEAD submodule &&
+ git diff-files --quiet
+'
+
+test_done
diff --git a/t/t2014-switch.sh b/t/t2014-switch.sh
new file mode 100755
index 0000000000..ccfb147113
--- /dev/null
+++ b/t/t2014-switch.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+test_description='Peter MacMillan'
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo Hello >file &&
+ git add file &&
+ test_tick &&
+ git commit -m V1 &&
+ echo Hello world >file &&
+ git add file &&
+ git checkout -b other
+'
+
+test_expect_success 'check all changes are staged' '
+ git diff --exit-code
+'
+
+test_expect_success 'second commit' '
+ git commit -m V2
+'
+
+test_expect_success 'check' '
+ git diff --cached --exit-code
+'
+
+test_done
diff --git a/t/t2015-checkout-unborn.sh b/t/t2015-checkout-unborn.sh
new file mode 100755
index 0000000000..c551d39a66
--- /dev/null
+++ b/t/t2015-checkout-unborn.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+test_description='checkout from unborn branch protects contents'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ mkdir parent &&
+ (cd parent &&
+ git init &&
+ echo content >file &&
+ git add file &&
+ git commit -m base
+ ) &&
+ git fetch parent master:origin
+'
+
+test_expect_success 'checkout from unborn preserves untracked files' '
+ echo precious >expect &&
+ echo precious >file &&
+ test_must_fail git checkout -b new origin &&
+ test_cmp expect file
+'
+
+test_expect_success 'checkout from unborn preserves index contents' '
+ echo precious >expect &&
+ echo precious >file &&
+ git add file &&
+ test_must_fail git checkout -b new origin &&
+ test_cmp expect file &&
+ git show :file >file &&
+ test_cmp expect file
+'
+
+test_expect_success 'checkout from unborn merges identical index contents' '
+ echo content >file &&
+ git add file &&
+ git checkout -b new origin
+'
+
+test_done
diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh
new file mode 100755
index 0000000000..4d1c2e9e09
--- /dev/null
+++ b/t/t2016-checkout-patch.sh
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+test_description='git checkout --patch'
+
+. ./lib-patch-mode.sh
+
+test_expect_success 'setup' '
+ mkdir dir &&
+ echo parent > dir/foo &&
+ echo dummy > bar &&
+ git add bar dir/foo &&
+ git commit -m initial &&
+ test_tick &&
+ test_commit second dir/foo head &&
+ set_and_save_state bar bar_work bar_index &&
+ save_head
+'
+
+# note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar'
+
+test_expect_success 'saying "n" does nothing' '
+ set_and_save_state dir/foo work head &&
+ (echo n; echo n) | git checkout -p &&
+ verify_saved_state bar &&
+ verify_saved_state dir/foo
+'
+
+test_expect_success 'git checkout -p' '
+ (echo n; echo y) | git checkout -p &&
+ verify_saved_state bar &&
+ verify_state dir/foo head head
+'
+
+test_expect_success 'git checkout -p with staged changes' '
+ set_state dir/foo work index
+ (echo n; echo y) | git checkout -p &&
+ verify_saved_state bar &&
+ verify_state dir/foo index index
+'
+
+test_expect_success 'git checkout -p HEAD with NO staged changes: abort' '
+ set_and_save_state dir/foo work head &&
+ (echo n; echo y; echo n) | git checkout -p HEAD &&
+ verify_saved_state bar &&
+ verify_saved_state dir/foo
+'
+
+test_expect_success 'git checkout -p HEAD with NO staged changes: apply' '
+ (echo n; echo y; echo y) | git checkout -p HEAD &&
+ verify_saved_state bar &&
+ verify_state dir/foo head head
+'
+
+test_expect_success 'git checkout -p HEAD with change already staged' '
+ set_state dir/foo index index
+ # the third n is to get out in case it mistakenly does not apply
+ (echo n; echo y; echo n) | git checkout -p HEAD &&
+ verify_saved_state bar &&
+ verify_state dir/foo head head
+'
+
+test_expect_success 'git checkout -p HEAD^' '
+ # the third n is to get out in case it mistakenly does not apply
+ (echo n; echo y; echo n) | git checkout -p HEAD^ &&
+ verify_saved_state bar &&
+ verify_state dir/foo parent parent
+'
+
+# The idea in the rest is that bar sorts first, so we always say 'y'
+# first and if the path limiter fails it'll apply to bar instead of
+# dir/foo. There's always an extra 'n' to reject edits to dir/foo in
+# the failure case (and thus get out of the loop).
+
+test_expect_success 'path limiting works: dir' '
+ set_state dir/foo work head &&
+ (echo y; echo n) | git checkout -p dir &&
+ verify_saved_state bar &&
+ verify_state dir/foo head head
+'
+
+test_expect_success 'path limiting works: -- dir' '
+ set_state dir/foo work head &&
+ (echo y; echo n) | git checkout -p -- dir &&
+ verify_saved_state bar &&
+ verify_state dir/foo head head
+'
+
+test_expect_success 'path limiting works: HEAD^ -- dir' '
+ # the third n is to get out in case it mistakenly does not apply
+ (echo y; echo n; echo n) | git checkout -p HEAD^ -- dir &&
+ verify_saved_state bar &&
+ verify_state dir/foo parent parent
+'
+
+test_expect_success 'path limiting works: foo inside dir' '
+ set_state dir/foo work head &&
+ # the third n is to get out in case it mistakenly does not apply
+ (echo y; echo n; echo n) | (cd dir && git checkout -p foo) &&
+ verify_saved_state bar &&
+ verify_state dir/foo head head
+'
+
+test_expect_success 'none of this moved HEAD' '
+ verify_saved_head
+'
+
+test_done
diff --git a/t/t2050-git-dir-relative.sh b/t/t2050-git-dir-relative.sh
index 88f268b9d7..b7131d8c08 100755
--- a/t/t2050-git-dir-relative.sh
+++ b/t/t2050-git-dir-relative.sh
@@ -26,8 +26,8 @@ chmod +x .git/hooks/post-commit'
test_expect_success 'post-commit hook used ordinarily' '
echo initial >top &&
-git-add top
-git-commit -m initial &&
+git add top
+git commit -m initial &&
test -r "${COMMIT_FILE}"
'
diff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh
index 9beaecd18b..2df3fdde8b 100755
--- a/t/t2100-update-cache-badpath.sh
+++ b/t/t2100-update-cache-badpath.sh
@@ -26,7 +26,12 @@ All of the attempts should fail.
mkdir path2 path3
date >path0
-ln -s xyzzy path1
+if test_have_prereq SYMLINKS
+then
+ ln -s xyzzy path1
+else
+ date > path1
+fi
date >path2/file2
date >path3/file3
@@ -38,7 +43,12 @@ rm -fr path?
mkdir path0 path1
date >path2
-ln -s frotz path3
+if test_have_prereq SYMLINKS
+then
+ ln -s frotz path3
+else
+ date > path3
+fi
date >path0/file0
date >path1/file1
@@ -46,6 +56,6 @@ for p in path0/file0 path1/file1 path2 path3
do
test_expect_success \
"git update-index to add conflicting path $p should fail." \
- "! git update-index --add -- $p"
+ "test_must_fail git update-index --add -- $p"
done
test_done
diff --git a/t/t2101-update-index-reupdate.sh b/t/t2101-update-index-reupdate.sh
index 59b560bfdf..648184fd98 100755
--- a/t/t2101-update-index-reupdate.sh
+++ b/t/t2101-update-index-reupdate.sh
@@ -40,7 +40,7 @@ test_expect_success 'update-index --remove --again' \
git ls-files -s >current &&
cmp current expected'
-test_expect_success 'first commit' 'git-commit -m initial'
+test_expect_success 'first commit' 'git commit -m initial'
cat > expected <<\EOF
100644 53ab446c3f4e42ce9bb728a0ccb283a101be4979 0 dir1/file3
diff --git a/t/t2102-update-index-symlinks.sh b/t/t2102-update-index-symlinks.sh
index 19d0894d26..1ed44ee503 100755
--- a/t/t2102-update-index-symlinks.sh
+++ b/t/t2102-update-index-symlinks.sh
@@ -13,12 +13,12 @@ even if a plain file is in the working tree if core.symlinks is false.'
test_expect_success \
'preparation' '
git config core.symlinks false &&
-l=$(echo -n file | git-hash-object -t blob -w --stdin) &&
+l=$(printf file | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info'
test_expect_success \
'modify the symbolic link' '
-echo -n new-file > symlink &&
+printf new-file > symlink &&
git update-index symlink'
test_expect_success \
diff --git a/t/t2103-update-index-ignore-missing.sh b/t/t2103-update-index-ignore-missing.sh
new file mode 100755
index 0000000000..332694e7d3
--- /dev/null
+++ b/t/t2103-update-index-ignore-missing.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+test_description='update-index with options'
+
+. ./test-lib.sh
+
+test_expect_success basics '
+ >one &&
+ >two &&
+ >three &&
+
+ # need --add when adding
+ test_must_fail git update-index one &&
+ test -z "$(git ls-files)" &&
+ git update-index --add one &&
+ test zone = "z$(git ls-files)" &&
+
+ # update-index is atomic
+ echo 1 >one &&
+ test_must_fail git update-index one two &&
+ echo "M one" >expect &&
+ git diff-files --name-status >actual &&
+ test_cmp expect actual &&
+
+ git update-index --add one two three &&
+ for i in one three two; do echo $i; done >expect &&
+ git ls-files >actual &&
+ test_cmp expect actual &&
+
+ test_tick &&
+ (
+ test_create_repo xyzzy &&
+ cd xyzzy &&
+ >file &&
+ git add file
+ git commit -m "sub initial"
+ ) &&
+ git add xyzzy &&
+
+ test_tick &&
+ git commit -m initial &&
+ git tag initial
+'
+
+test_expect_success '--ignore-missing --refresh' '
+ git reset --hard initial &&
+ echo 2 >one &&
+ test_must_fail git update-index --refresh &&
+ echo 1 >one &&
+ git update-index --refresh &&
+ rm -f two &&
+ test_must_fail git update-index --refresh &&
+ git update-index --ignore-missing --refresh
+
+'
+
+test_expect_success '--unmerged --refresh' '
+ git reset --hard initial &&
+ info=$(git ls-files -s one | sed -e "s/ 0 / 1 /") &&
+ git rm --cached one &&
+ echo "$info" | git update-index --index-info &&
+ test_must_fail git update-index --refresh &&
+ git update-index --unmerged --refresh &&
+ echo 2 >two &&
+ test_must_fail git update-index --unmerged --refresh >actual &&
+ grep two actual &&
+ ! grep one actual &&
+ ! grep three actual
+'
+
+test_expect_success '--ignore-submodules --refresh (1)' '
+ git reset --hard initial &&
+ rm -f two &&
+ test_must_fail git update-index --ignore-submodules --refresh
+'
+
+test_expect_success '--ignore-submodules --refresh (2)' '
+ git reset --hard initial &&
+ test_tick &&
+ (
+ cd xyzzy &&
+ git commit -m "sub second" --allow-empty
+ ) &&
+ test_must_fail git update-index --refresh &&
+ test_must_fail git update-index --ignore-missing --refresh &&
+ git update-index --ignore-submodules --refresh
+'
+
+test_done
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index b664341926..912075063b 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -12,7 +12,7 @@ and issues a git add -u with path limiting on "dir" to add
only the updates to dir/sub.
Also tested are "git add -u" without limiting, and "git add -u"
-without contents changes.'
+without contents changes, and other conditions'
. ./test-lib.sh
@@ -26,7 +26,7 @@ test_expect_success setup '
echo initial >dir2/sub3 &&
git add check dir1 dir2 top foo &&
test_tick
- git-commit -m initial &&
+ git commit -m initial &&
echo changed >check &&
echo changed >top &&
@@ -40,20 +40,20 @@ test_expect_success update '
'
test_expect_success 'update noticed a removal' '
- test "$(git-ls-files dir1/sub1)" = ""
+ test "$(git ls-files dir1/sub1)" = ""
'
test_expect_success 'update touched correct path' '
- test "$(git-diff-files --name-status dir2/sub3)" = ""
+ test "$(git diff-files --name-status dir2/sub3)" = ""
'
test_expect_success 'update did not touch other tracked files' '
- test "$(git-diff-files --name-status check)" = "M check" &&
- test "$(git-diff-files --name-status top)" = "M top"
+ test "$(git diff-files --name-status check)" = "M check" &&
+ test "$(git diff-files --name-status top)" = "M top"
'
test_expect_success 'update did not touch untracked files' '
- test "$(git-ls-files dir2/other)" = ""
+ test "$(git ls-files dir2/other)" = ""
'
test_expect_success 'cache tree has not been corrupted' '
@@ -80,7 +80,7 @@ test_expect_success 'change gets noticed' '
'
-test_expect_success 'replace a file with a symlink' '
+test_expect_success SYMLINKS 'replace a file with a symlink' '
rm foo &&
ln -s top foo &&
@@ -111,4 +111,69 @@ test_expect_success 'touch and then add explicitly' '
'
+test_expect_success 'add -n -u should not add but just report' '
+
+ (
+ echo "add '\''check'\''" &&
+ echo "remove '\''top'\''"
+ ) >expect &&
+ before=$(git ls-files -s check top) &&
+ echo changed >>check &&
+ rm -f top &&
+ git add -n -u >actual &&
+ after=$(git ls-files -s check top) &&
+
+ test "$before" = "$after" &&
+ test_cmp expect actual
+
+'
+
+test_expect_success 'add -u resolves unmerged paths' '
+ git reset --hard &&
+ one=$(echo 1 | git hash-object -w --stdin) &&
+ two=$(echo 2 | git hash-object -w --stdin) &&
+ three=$(echo 3 | git hash-object -w --stdin) &&
+ {
+ for path in path1 path2
+ do
+ echo "100644 $one 1 $path"
+ echo "100644 $two 2 $path"
+ echo "100644 $three 3 $path"
+ done
+ echo "100644 $one 1 path3"
+ echo "100644 $one 1 path4"
+ echo "100644 $one 3 path5"
+ echo "100644 $one 3 path6"
+ } |
+ git update-index --index-info &&
+ echo 3 >path1 &&
+ echo 2 >path3 &&
+ echo 2 >path5 &&
+ git add -u &&
+ git ls-files -s path1 path2 path3 path4 path5 path6 >actual &&
+ {
+ echo "100644 $three 0 path1"
+ echo "100644 $one 1 path3"
+ echo "100644 $one 1 path4"
+ echo "100644 $one 3 path5"
+ echo "100644 $one 3 path6"
+ } >expect &&
+ test_cmp expect actual &&
+
+ # Bonus tests. Explicit resolving
+ git add path3 path5 &&
+ test_must_fail git add path4 &&
+ test_must_fail git add path6 &&
+ git rm path4 &&
+ git rm path6 &&
+
+ git ls-files -s "path?" >actual &&
+ {
+ echo "100644 $three 0 path1"
+ echo "100644 $two 0 path3"
+ echo "100644 $two 0 path5"
+ } >expect
+
+'
+
test_done
diff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh
index e15e3eb81b..2e8f702452 100755
--- a/t/t2201-add-update-typechange.sh
+++ b/t/t2201-add-update-typechange.sh
@@ -11,7 +11,13 @@ test_expect_success setup '
_empty=$(git hash-object --stdin <xyzzy) &&
>yomin &&
>caskly &&
- ln -s frotz nitfol &&
+ if test_have_prereq SYMLINKS; then
+ ln -s frotz nitfol &&
+ T_letter=T
+ else
+ printf %s frotz > nitfol &&
+ T_letter=M
+ fi &&
mkdir rezrov &&
>rezrov/bozbar &&
git add caskly xyzzy yomin nitfol rezrov/bozbar &&
@@ -29,7 +35,11 @@ test_expect_success modify '
>nitfol &&
# rezrov/bozbar disappears
rm -fr rezrov &&
- ln -s xyzzy rezrov &&
+ if test_have_prereq SYMLINKS; then
+ ln -s xyzzy rezrov
+ else
+ printf %s xyzzy > rezrov
+ fi &&
# xyzzy disappears (not a submodule)
mkdir xyzzy &&
echo gnusto >xyzzy/bozbar &&
@@ -71,7 +81,7 @@ test_expect_success modify '
s/blob/000000/
}
/ nitfol/{
- s/ nitfol/ $_z40 T&/
+ s/ nitfol/ $_z40 $T_letter&/
s/blob/100644/
}
/ rezrov.bozbar/{
@@ -106,12 +116,12 @@ test_expect_success modify '
test_expect_success diff-files '
git diff-files --raw >actual &&
- diff -u expect-files actual
+ test_cmp expect-files actual
'
test_expect_success diff-index '
git diff-index --raw HEAD -- >actual &&
- diff -u expect-index actual
+ test_cmp expect-index actual
'
test_expect_success 'add -u' '
@@ -119,7 +129,7 @@ test_expect_success 'add -u' '
cp -p ".git/index" ".git/saved-index" &&
git add -u &&
git ls-files -s >actual &&
- diff -u expect-final actual
+ test_cmp expect-final actual
'
test_expect_success 'commit -a' '
@@ -130,11 +140,11 @@ test_expect_success 'commit -a' '
fi &&
git commit -m "second" -a &&
git ls-files -s >actual &&
- diff -u expect-final actual &&
+ test_cmp expect-final actual &&
rm -f .git/index &&
git read-tree HEAD &&
git ls-files -s >actual &&
- diff -u expect-final actual
+ test_cmp expect-final actual
'
test_done
diff --git a/t/t2202-add-addremove.sh b/t/t2202-add-addremove.sh
new file mode 100755
index 0000000000..6a8151064c
--- /dev/null
+++ b/t/t2202-add-addremove.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+test_description='git add --all'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ (
+ echo .gitignore
+ echo will-remove
+ ) >expect &&
+ (
+ echo actual
+ echo expect
+ echo ignored
+ ) >.gitignore &&
+ >will-remove &&
+ git add --all &&
+ test_tick &&
+ git commit -m initial &&
+ git ls-files >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git add --all' '
+ (
+ echo .gitignore
+ echo not-ignored
+ echo "M .gitignore"
+ echo "A not-ignored"
+ echo "D will-remove"
+ ) >expect &&
+ >ignored &&
+ >not-ignored &&
+ echo modification >>.gitignore &&
+ rm -f will-remove &&
+ git add --all &&
+ git update-index --refresh &&
+ git ls-files >actual &&
+ git diff-index --name-status --cached HEAD >>actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
new file mode 100755
index 0000000000..58a329961e
--- /dev/null
+++ b/t/t2203-add-intent.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+test_description='Intent to add'
+
+. ./test-lib.sh
+
+test_expect_success 'intent to add' '
+ echo hello >file &&
+ echo hello >elif &&
+ git add -N file &&
+ git add elif
+'
+
+test_expect_success 'check result of "add -N"' '
+ git ls-files -s file >actual &&
+ empty=$(git hash-object --stdin </dev/null) &&
+ echo "100644 $empty 0 file" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'intent to add is just an ordinary empty blob' '
+ git add -u &&
+ git ls-files -s file >actual &&
+ git ls-files -s elif | sed -e "s/elif/file/" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'intent to add does not clobber existing paths' '
+ git add -N file elif &&
+ empty=$(git hash-object --stdin </dev/null) &&
+ git ls-files -s >actual &&
+ ! grep "$empty" actual
+'
+
+test_expect_success 'cannot commit with i-t-a entry' '
+ test_tick &&
+ git commit -a -m initial &&
+ git reset --hard &&
+
+ echo xyzzy >rezrov &&
+ echo frotz >nitfol &&
+ git add rezrov &&
+ git add -N nitfol &&
+ test_must_fail git commit
+'
+
+test_expect_success 'can commit with an unrelated i-t-a entry in index' '
+ git reset --hard &&
+ echo xyzzy >rezrov &&
+ echo frotz >nitfol &&
+ git add rezrov &&
+ git add -N nitfol &&
+ git commit -m partial rezrov
+'
+
+test_expect_success 'can "commit -a" with an i-t-a entry' '
+ git reset --hard &&
+ : >nitfol &&
+ git add -N nitfol &&
+ git commit -a -m all
+'
+
+test_done
+
diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh
new file mode 100755
index 0000000000..9965bc5c92
--- /dev/null
+++ b/t/t2300-cd-to-toplevel.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='cd_to_toplevel'
+
+. ./test-lib.sh
+
+test_cd_to_toplevel () {
+ test_expect_success $3 "$2" '
+ (
+ cd '"'$1'"' &&
+ . "$(git --exec-path)"/git-sh-setup &&
+ cd_to_toplevel &&
+ [ "$(pwd -P)" = "$TOPLEVEL" ]
+ )
+ '
+}
+
+TOPLEVEL="$(pwd -P)/repo"
+mkdir -p repo/sub/dir
+mv .git repo/
+SUBDIRECTORY_OK=1
+
+test_cd_to_toplevel repo 'at physical root'
+
+test_cd_to_toplevel repo/sub/dir 'at physical subdir'
+
+ln -s repo symrepo 2>/dev/null
+test_cd_to_toplevel symrepo 'at symbolic root' SYMLINKS
+
+ln -s repo/sub/dir subdir-link 2>/dev/null
+test_cd_to_toplevel subdir-link 'at symbolic subdir' SYMLINKS
+
+cd repo
+ln -s sub/dir internal-link 2>/dev/null
+test_cd_to_toplevel internal-link 'at internal symbolic subdir' SYMLINKS
+
+test_done
diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh
index bc0a351392..86291e8399 100755
--- a/t/t3000-ls-files-others.sh
+++ b/t/t3000-ls-files-others.sh
@@ -13,12 +13,18 @@ filesystem.
path2/file2 - a file in a directory
path3-junk - a file to confuse things
path3/file3 - a file in a directory
+ path4 - an empty directory
'
. ./test-lib.sh
date >path0
-ln -s xyzzy path1
-mkdir path2 path3
+if test_have_prereq SYMLINKS
+then
+ ln -s xyzzy path1
+else
+ date > path1
+fi
+mkdir path2 path3 path4
date >path2/file2
date >path2-junk
date >path3/file3
@@ -28,6 +34,7 @@ git update-index --add path3-junk path3/file3
cat >expected1 <<EOF
expected1
expected2
+expected3
output
path0
path1
@@ -35,6 +42,8 @@ path2-junk
path2/file2
EOF
sed -e 's|path2/file2|path2/|' <expected1 >expected2
+cat <expected2 >expected3
+echo path4/ >>expected2
test_expect_success \
'git ls-files --others to show output.' \
@@ -42,7 +51,7 @@ test_expect_success \
test_expect_success \
'git ls-files --others should pick up symlinks.' \
- 'diff output expected1'
+ 'test_cmp expected1 output'
test_expect_success \
'git ls-files --others --directory to show output.' \
@@ -51,6 +60,14 @@ test_expect_success \
test_expect_success \
'git ls-files --others --directory should not get confused.' \
- 'diff output expected2'
+ 'test_cmp expected2 output'
+
+test_expect_success \
+ 'git ls-files --others --directory --no-empty-directory to show output.' \
+ 'git ls-files --others --directory --no-empty-directory >output'
+
+test_expect_success \
+ '--no-empty-directory hides empty directory' \
+ 'test_cmp expected3 output'
test_done
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index 55f057cebe..c65bca8388 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -19,6 +19,9 @@ do
>$dir/a.$i
done
done
+>"#ignore1"
+>"#ignore2"
+>"#hidden"
cat >expect <<EOF
a.2
@@ -42,6 +45,9 @@ three/a.8
EOF
echo '.gitignore
+\#ignore1
+\#ignore2*
+\#hid*n
output
expect
.gitignore
@@ -65,7 +71,7 @@ test_expect_success \
--exclude-per-directory=.gitignore \
--exclude-from=.git/ignore \
>output &&
- git diff expect output'
+ test_cmp expect output'
# Test \r\n (MSDOS-like systems)
printf '*.1\r\n/*.3\r\n!*.6\r\n' >.gitignore
@@ -77,11 +83,12 @@ test_expect_success \
--exclude-per-directory=.gitignore \
--exclude-from=.git/ignore \
>output &&
- git diff expect output'
+ test_cmp expect output'
-cat > excludes-file << EOF
+cat > excludes-file <<\EOF
*.[1-8]
e*
+\#*
EOF
git config core.excludesFile excludes-file
@@ -96,7 +103,7 @@ cat > expect << EOF
# three/
EOF
-test_expect_success 'git-status honours core.excludesfile' \
+test_expect_success 'git status honors core.excludesfile' \
'test_cmp expect output'
test_expect_success 'trailing slash in exclude allows directory match(1)' '
@@ -140,4 +147,10 @@ test_expect_success 'trailing slash in exclude forces directory match (2)' '
'
+test_expect_success 'negated exclude matches can override previous ones' '
+
+ git ls-files --others --exclude="a.*" --exclude="!a.1" >output &&
+ grep "^a.1" output
+'
+
test_done
diff --git a/t/t3002-ls-files-dashpath.sh b/t/t3002-ls-files-dashpath.sh
index 8687a01d2b..8704b04e1b 100755
--- a/t/t3002-ls-files-dashpath.sh
+++ b/t/t3002-ls-files-dashpath.sh
@@ -23,7 +23,7 @@ test_expect_success \
test_expect_success \
'git ls-files without path restriction.' \
'git ls-files --others >output &&
- git diff output - <<EOF
+ test_cmp output - <<EOF
--
-foo
output
@@ -34,7 +34,7 @@ EOF
test_expect_success \
'git ls-files with path restriction.' \
'git ls-files --others path0 >output &&
- git diff output - <<EOF
+ test_cmp output - <<EOF
path0
EOF
'
@@ -42,7 +42,7 @@ EOF
test_expect_success \
'git ls-files with path restriction with --.' \
'git ls-files --others -- path0 >output &&
- git diff output - <<EOF
+ test_cmp output - <<EOF
path0
EOF
'
@@ -50,7 +50,7 @@ EOF
test_expect_success \
'git ls-files with path restriction with -- --.' \
'git ls-files --others -- -- >output &&
- git diff output - <<EOF
+ test_cmp output - <<EOF
--
EOF
'
@@ -58,7 +58,7 @@ EOF
test_expect_success \
'git ls-files with no path restriction.' \
'git ls-files --others -- >output &&
- git diff output - <<EOF
+ test_cmp output - <<EOF
--
-foo
output
diff --git a/t/t3003-ls-files-exclude.sh b/t/t3003-ls-files-exclude.sh
new file mode 100755
index 0000000000..d5ec333131
--- /dev/null
+++ b/t/t3003-ls-files-exclude.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+test_description='ls-files --exclude does not affect index files'
+. ./test-lib.sh
+
+test_expect_success 'create repo with file' '
+ echo content >file &&
+ git add file &&
+ git commit -m file &&
+ echo modification >file
+'
+
+check_output() {
+test_expect_success "ls-files output contains file ($1)" "
+ echo '$2' >expect &&
+ git ls-files --exclude-standard --$1 >output &&
+ test_cmp expect output
+"
+}
+
+check_all_output() {
+ check_output 'cached' 'file'
+ check_output 'modified' 'file'
+}
+
+check_all_output
+test_expect_success 'add file to gitignore' '
+ echo file >.gitignore
+'
+check_all_output
+
+test_expect_success 'ls-files -i lists only tracked-but-ignored files' '
+ echo content >other-file &&
+ git add other-file &&
+ echo file >expect &&
+ git ls-files -i --exclude-standard >output &&
+ test_cmp expect output
+'
+
+test_done
diff --git a/t/t3010-ls-files-killed-modified.sh b/t/t3010-ls-files-killed-modified.sh
index ec14040637..95671c2053 100755
--- a/t/t3010-ls-files-killed-modified.sh
+++ b/t/t3010-ls-files-killed-modified.sh
@@ -38,7 +38,12 @@ modified without reporting path9 and path10.
. ./test-lib.sh
date >path0
-ln -s xyzzy path1
+if test_have_prereq SYMLINKS
+then
+ ln -s xyzzy path1
+else
+ date > path1
+fi
mkdir path2 path3
date >path2/file2
date >path3/file3
@@ -52,8 +57,14 @@ test_expect_success \
rm -fr path? ;# leave path10 alone
date >path2
-ln -s frotz path3
-ln -s nitfol path5
+if test_have_prereq SYMLINKS
+then
+ ln -s frotz path3
+ ln -s nitfol path5
+else
+ date > path3
+ date > path5
+fi
mkdir path0 path1 path6
date >path0/file0
date >path1/file1
@@ -75,7 +86,7 @@ EOF
test_expect_success \
'validate git ls-files -k output.' \
- 'diff .output .expected'
+ 'test_cmp .expected .output'
test_expect_success \
'git ls-files -m to show modified files.' \
@@ -91,6 +102,6 @@ EOF
test_expect_success \
'validate git ls-files -m output.' \
- 'diff .output .expected'
+ 'test_cmp .expected .output'
test_done
diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh
index f4da869932..f4066cbc09 100755
--- a/t/t3020-ls-files-error-unmatch.sh
+++ b/t/t3020-ls-files-error-unmatch.sh
@@ -13,11 +13,11 @@ line.
touch foo bar
git update-index --add foo bar
-git-commit -m "add foo bar"
+git commit -m "add foo bar"
test_expect_success \
'git ls-files --error-unmatch should fail with unmatched path.' \
- '! git ls-files --error-unmatch foo bar-does-not-match'
+ 'test_must_fail git ls-files --error-unmatch foo bar-does-not-match'
test_expect_success \
'git ls-files --error-unmatch should succeed eith matched paths.' \
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index 607f57ff94..9b3fa2bdcd 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -43,7 +43,7 @@ test_expect_success 'setup 1' '
echo "100644 $o0 0 c"
echo "100644 $o1 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
test_expect_success 'setup 2' '
@@ -61,7 +61,7 @@ test_expect_success 'setup 2' '
echo "100644 $o0 0 c"
echo "100644 $o0 0 d/e"
) >expected &&
- git diff -u expected actual &&
+ test_cmp expected actual &&
echo goodbye >>a &&
o2=$(git hash-object a) &&
@@ -82,7 +82,7 @@ test_expect_success 'setup 2' '
echo "100644 $o0 0 c"
echo "100644 $o0 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
test_expect_success 'setup 3' '
@@ -100,7 +100,7 @@ test_expect_success 'setup 3' '
echo "100644 $o0 0 c"
echo "100644 $o0 0 d/e"
) >expected &&
- git diff -u expected actual &&
+ test_cmp expected actual &&
rm -f b && mkdir b && echo df-1 >b/c && git add b/c &&
o3=$(git hash-object b/c) &&
@@ -119,7 +119,7 @@ test_expect_success 'setup 3' '
echo "100644 $o0 0 c"
echo "100644 $o0 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
test_expect_success 'setup 4' '
@@ -137,7 +137,7 @@ test_expect_success 'setup 4' '
echo "100644 $o0 0 c"
echo "100644 $o0 0 d/e"
) >expected &&
- git diff -u expected actual &&
+ test_cmp expected actual &&
rm -f a && mkdir a && echo df-2 >a/c && git add a/c &&
o4=$(git hash-object a/c) &&
@@ -156,7 +156,7 @@ test_expect_success 'setup 4' '
echo "100644 $o0 0 c"
echo "100644 $o0 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
test_expect_success 'setup 5' '
@@ -174,7 +174,7 @@ test_expect_success 'setup 5' '
echo "100644 $o0 0 c"
echo "100644 $o0 0 d/e"
) >expected &&
- git diff -u expected actual &&
+ test_cmp expected actual &&
rm -f b &&
echo remove-conflict >a &&
@@ -195,7 +195,7 @@ test_expect_success 'setup 5' '
echo "100644 $o0 0 c"
echo "100644 $o0 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
@@ -214,7 +214,7 @@ test_expect_success 'setup 6' '
echo "100644 $o0 0 c"
echo "100644 $o0 0 d/e"
) >expected &&
- git diff -u expected actual &&
+ test_cmp expected actual &&
rm -fr d && echo df-3 >d && git add d &&
o6=$(git hash-object d) &&
@@ -233,7 +233,7 @@ test_expect_success 'setup 6' '
echo "100644 $o0 0 c"
echo "100644 $o6 0 d"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
test_expect_success 'merge-recursive simple' '
@@ -241,7 +241,7 @@ test_expect_success 'merge-recursive simple' '
rm -fr [abcd] &&
git checkout -f "$c2" &&
- git-merge-recursive "$c0" -- "$c2" "$c1"
+ git merge-recursive "$c0" -- "$c2" "$c1"
status=$?
case "$status" in
1)
@@ -265,7 +265,21 @@ test_expect_success 'merge-recursive result' '
echo "100644 $o0 0 c"
echo "100644 $o1 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
+
+'
+
+test_expect_success 'fail if the index has unresolved entries' '
+
+ rm -fr [abcd] &&
+ git checkout -f "$c1" &&
+
+ test_must_fail git merge "$c5" &&
+ test_must_fail git merge "$c5" 2> out &&
+ grep "You have not concluded your merge" out &&
+ rm -f .git/MERGE_HEAD &&
+ test_must_fail git merge "$c5" 2> out &&
+ grep "You are in the middle of a conflicted merge" out
'
@@ -274,7 +288,7 @@ test_expect_success 'merge-recursive remove conflict' '
rm -fr [abcd] &&
git checkout -f "$c1" &&
- git-merge-recursive "$c0" -- "$c1" "$c5"
+ git merge-recursive "$c0" -- "$c1" "$c5"
status=$?
case "$status" in
1)
@@ -297,7 +311,7 @@ test_expect_success 'merge-recursive remove conflict' '
echo "100644 $o0 0 c"
echo "100644 $o1 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
@@ -306,7 +320,7 @@ test_expect_success 'merge-recursive d/f simple' '
git reset --hard &&
git checkout -f "$c1" &&
- git-merge-recursive "$c0" -- "$c1" "$c3"
+ git merge-recursive "$c0" -- "$c1" "$c3"
'
test_expect_success 'merge-recursive result' '
@@ -318,7 +332,7 @@ test_expect_success 'merge-recursive result' '
echo "100644 $o0 0 c"
echo "100644 $o1 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
@@ -328,7 +342,7 @@ test_expect_success 'merge-recursive d/f conflict' '
git reset --hard &&
git checkout -f "$c1" &&
- git-merge-recursive "$c0" -- "$c1" "$c4"
+ git merge-recursive "$c0" -- "$c1" "$c4"
status=$?
case "$status" in
1)
@@ -352,7 +366,7 @@ test_expect_success 'merge-recursive d/f conflict result' '
echo "100644 $o0 0 c"
echo "100644 $o1 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
@@ -362,7 +376,7 @@ test_expect_success 'merge-recursive d/f conflict the other way' '
git reset --hard &&
git checkout -f "$c4" &&
- git-merge-recursive "$c0" -- "$c4" "$c1"
+ git merge-recursive "$c0" -- "$c4" "$c1"
status=$?
case "$status" in
1)
@@ -386,7 +400,7 @@ test_expect_success 'merge-recursive d/f conflict result the other way' '
echo "100644 $o0 0 c"
echo "100644 $o1 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
@@ -396,7 +410,7 @@ test_expect_success 'merge-recursive d/f conflict' '
git reset --hard &&
git checkout -f "$c1" &&
- git-merge-recursive "$c0" -- "$c1" "$c6"
+ git merge-recursive "$c0" -- "$c1" "$c6"
status=$?
case "$status" in
1)
@@ -420,7 +434,7 @@ test_expect_success 'merge-recursive d/f conflict result' '
echo "100644 $o0 1 d/e"
echo "100644 $o1 2 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
@@ -430,7 +444,7 @@ test_expect_success 'merge-recursive d/f conflict' '
git reset --hard &&
git checkout -f "$c6" &&
- git-merge-recursive "$c0" -- "$c6" "$c1"
+ git merge-recursive "$c0" -- "$c6" "$c1"
status=$?
case "$status" in
1)
@@ -454,7 +468,7 @@ test_expect_success 'merge-recursive d/f conflict result' '
echo "100644 $o0 1 d/e"
echo "100644 $o1 3 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
@@ -480,7 +494,7 @@ test_expect_success 'reset and bind merge' '
echo "100644 $o0 0 c"
echo "100644 $o1 0 d/e"
) >expected &&
- git diff -u expected actual &&
+ test_cmp expected actual &&
git read-tree --prefix=a1/ master &&
git ls-files -s >actual &&
@@ -498,7 +512,7 @@ test_expect_success 'reset and bind merge' '
echo "100644 $o0 0 c"
echo "100644 $o1 0 d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
git read-tree --prefix=z/ master &&
git ls-files -s >actual &&
@@ -520,8 +534,19 @@ test_expect_success 'reset and bind merge' '
echo "100644 $o0 0 z/c"
echo "100644 $o1 0 z/d/e"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
+
+'
+test_expect_success 'merge removes empty directories' '
+
+ git reset --hard master &&
+ git checkout -b rm &&
+ git rm d/e &&
+ git commit -mremoved-d/e &&
+ git checkout master &&
+ git merge -s recursive rm &&
+ test_must_fail test -d d
'
test_done
diff --git a/t/t3031-merge-criscross.sh b/t/t3031-merge-criscross.sh
new file mode 100755
index 0000000000..7f41607c56
--- /dev/null
+++ b/t/t3031-merge-criscross.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+test_description='merge-recursive backend test'
+
+. ./test-lib.sh
+
+# A <- create some files
+# / \
+# B C <- cause rename/delete conflicts between B and C
+# / \
+# |\ /|
+# | D E |
+# | \ / |
+# | X |
+# | / \ |
+# | / \ |
+# |/ \|
+# F G <- merge E into B, D into C
+# \ /
+# \ /
+# \ /
+# H <- recursive merge crashes
+#
+
+# initialize
+test_expect_success 'setup repo with criss-cross history' '
+ mkdir data &&
+
+ # create a bunch of files
+ n=1 &&
+ while test $n -le 10
+ do
+ echo $n > data/$n &&
+ n=$(($n+1)) ||
+ break
+ done &&
+
+ # check them in
+ git add data &&
+ git commit -m A &&
+ git branch A &&
+
+ # a file in one branch
+ git checkout -b B A &&
+ git rm data/9 &&
+ git add data &&
+ git commit -m B &&
+
+ # with a branch off of it
+ git branch D &&
+
+ # put some commits on D
+ git checkout D &&
+ echo testD > data/testD &&
+ git add data &&
+ git commit -m D &&
+
+ # back up to the top, create another branch and cause
+ # a rename conflict with the file we deleted earlier
+ git checkout -b C A &&
+ git mv data/9 data/new-9 &&
+ git add data &&
+ git commit -m C &&
+
+ # with a branch off of it
+ git branch E &&
+
+ # put a commit on E
+ git checkout E &&
+ echo testE > data/testE &&
+ git add data &&
+ git commit -m E &&
+
+ # now, merge E into B
+ git checkout B &&
+ test_must_fail git merge E &&
+ # force-resolve
+ git add data &&
+ git commit -m F &&
+ git branch F &&
+
+ # and merge D into C
+ git checkout C &&
+ test_must_fail git merge D &&
+ # force-resolve
+ git add data &&
+ git commit -m G &&
+ git branch G
+'
+
+test_expect_success 'recursive merge between F and G, causes segfault' '
+ git merge F
+'
+
+test_done
diff --git a/t/t3040-subprojects-basic.sh b/t/t3040-subprojects-basic.sh
index 79b9f23654..f6973e96a5 100755
--- a/t/t3040-subprojects-basic.sh
+++ b/t/t3040-subprojects-basic.sh
@@ -24,7 +24,7 @@ test_expect_success 'create subprojects' \
git add sub2 &&
git commit -q -m "subprojects added" &&
git diff-tree --abbrev=5 HEAD^ HEAD |cut -d" " -f-3,5- >current &&
- git diff expected current'
+ test_cmp expected current'
git branch save HEAD
@@ -62,7 +62,7 @@ test_expect_success 'check if clone works' \
'git ls-files -s >expected &&
git clone -l -s . cloned &&
( cd cloned && git ls-files -s ) >current &&
- git diff expected current'
+ test_cmp expected current'
test_expect_success 'removing and adding subproject' \
'git update-index --force-remove -- sub2 &&
diff --git a/t/t3050-subprojects-fetch.sh b/t/t3050-subprojects-fetch.sh
index 2b21b1070d..4261e9641e 100755
--- a/t/t3050-subprojects-fetch.sh
+++ b/t/t3050-subprojects-fetch.sh
@@ -20,7 +20,7 @@ test_expect_success setup '
'
test_expect_success clone '
- git clone file://`pwd`/.git cloned &&
+ git clone "file://$(pwd)/.git" cloned &&
(git rev-parse HEAD; git ls-files -s) >expected &&
(
cd cloned &&
diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh
index 46427e3f36..ee60d03fe8 100755
--- a/t/t3100-ls-tree-restrict.sh
+++ b/t/t3100-ls-tree-restrict.sh
@@ -22,9 +22,21 @@ test_expect_success \
'setup' \
'mkdir path2 path2/baz &&
echo Hi >path0 &&
- ln -s path0 path1 &&
+ if test_have_prereq SYMLINKS
+ then
+ ln -s path0 path1 &&
+ ln -s ../path1 path2/bazbo
+ make_expected () {
+ cat >expected
+ }
+ else
+ printf path0 > path1 &&
+ printf ../path1 > path2/bazbo
+ make_expected () {
+ sed -e "s/120000 /100644 /" >expected
+ }
+ fi &&
echo Lo >path2/foo &&
- ln -s ../path1 path2/bazbo &&
echo Mi >path2/baz/b &&
find path? \( -type f -o -type l \) -print |
xargs git update-index --add &&
@@ -35,13 +47,13 @@ _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
test_output () {
sed -e "s/ $_x40 / X /" <current >check
- git diff expected check
+ test_cmp expected check
}
test_expect_success \
'ls-tree plain' \
'git ls-tree $tree >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
100644 blob X path0
120000 blob X path1
040000 tree X path2
@@ -51,7 +63,7 @@ EOF
test_expect_success \
'ls-tree recursive' \
'git ls-tree -r $tree >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
100644 blob X path0
120000 blob X path1
100644 blob X path2/baz/b
@@ -63,7 +75,7 @@ EOF
test_expect_success \
'ls-tree recursive with -t' \
'git ls-tree -r -t $tree >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
100644 blob X path0
120000 blob X path1
040000 tree X path2
@@ -77,7 +89,7 @@ EOF
test_expect_success \
'ls-tree recursive with -d' \
'git ls-tree -r -d $tree >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
040000 tree X path2
040000 tree X path2/baz
EOF
@@ -86,7 +98,7 @@ EOF
test_expect_success \
'ls-tree filtered with path' \
'git ls-tree $tree path >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
EOF
test_output'
@@ -96,7 +108,7 @@ EOF
test_expect_success \
'ls-tree filtered with path1 path0' \
'git ls-tree $tree path1 path0 >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
100644 blob X path0
120000 blob X path1
EOF
@@ -105,7 +117,7 @@ EOF
test_expect_success \
'ls-tree filtered with path0/' \
'git ls-tree $tree path0/ >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
EOF
test_output'
@@ -114,7 +126,7 @@ EOF
test_expect_success \
'ls-tree filtered with path2' \
'git ls-tree $tree path2 >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
040000 tree X path2
EOF
test_output'
@@ -123,7 +135,7 @@ EOF
test_expect_success \
'ls-tree filtered with path2/' \
'git ls-tree $tree path2/ >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
040000 tree X path2/baz
120000 blob X path2/bazbo
100644 blob X path2/foo
@@ -135,7 +147,7 @@ EOF
test_expect_success \
'ls-tree filtered with path2/baz' \
'git ls-tree $tree path2/baz >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
040000 tree X path2/baz
EOF
test_output'
@@ -143,14 +155,14 @@ EOF
test_expect_success \
'ls-tree filtered with path2/bak' \
'git ls-tree $tree path2/bak >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
EOF
test_output'
test_expect_success \
'ls-tree -t filtered with path2/bak' \
'git ls-tree -t $tree path2/bak >current &&
- cat >expected <<\EOF &&
+ make_expected <<\EOF &&
040000 tree X path2
EOF
test_output'
diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh
index 70f9ce9d52..8be9fb4112 100755
--- a/t/t3101-ls-tree-dirname.sh
+++ b/t/t3101-ls-tree-dirname.sh
@@ -39,11 +39,11 @@ test_expect_success \
tree=`git write-tree` &&
echo $tree'
-_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
-_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
+_x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05"
test_output () {
sed -e "s/ $_x40 / X /" <current >check
- git diff expected check
+ test_cmp expected check
}
test_expect_success \
@@ -135,4 +135,95 @@ test_expect_success \
EOF
test_output'
+test_expect_success 'ls-tree filter is leading path match' '
+ git ls-tree $tree pa path3/a >current &&
+ >expected &&
+ test_output
+'
+
+test_expect_success 'ls-tree --full-name' '
+ (
+ cd path0 &&
+ git ls-tree --full-name $tree a
+ ) >current &&
+ cat >expected <<\EOF &&
+040000 tree X path0/a
+EOF
+ test_output
+'
+
+test_expect_success 'ls-tree --full-tree' '
+ (
+ cd path1/b/c &&
+ git ls-tree --full-tree $tree
+ ) >current &&
+ cat >expected <<\EOF &&
+100644 blob X 1.txt
+100644 blob X 2.txt
+040000 tree X path0
+040000 tree X path1
+040000 tree X path2
+040000 tree X path3
+EOF
+ test_output
+'
+
+test_expect_success 'ls-tree --full-tree -r' '
+ (
+ cd path3/ &&
+ git ls-tree --full-tree -r $tree
+ ) >current &&
+ cat >expected <<\EOF &&
+100644 blob X 1.txt
+100644 blob X 2.txt
+100644 blob X path0/a/b/c/1.txt
+100644 blob X path1/b/c/1.txt
+100644 blob X path2/1.txt
+100644 blob X path3/1.txt
+100644 blob X path3/2.txt
+EOF
+ test_output
+'
+
+test_expect_success 'ls-tree --abbrev=5' '
+ git ls-tree --abbrev=5 $tree >current &&
+ sed -e "s/ $_x05[0-9a-f]* / X /" <current >check &&
+ cat >expected <<\EOF &&
+100644 blob X 1.txt
+100644 blob X 2.txt
+040000 tree X path0
+040000 tree X path1
+040000 tree X path2
+040000 tree X path3
+EOF
+ test_cmp expected check
+'
+
+test_expect_success 'ls-tree --name-only' '
+ git ls-tree --name-only $tree >current
+ cat >expected <<\EOF &&
+1.txt
+2.txt
+path0
+path1
+path2
+path3
+EOF
+ test_output
+'
+
+test_expect_success 'ls-tree --name-only -r' '
+ git ls-tree --name-only -r $tree >current
+ cat >expected <<\EOF &&
+1.txt
+2.txt
+path0/a/b/c/1.txt
+path1/b/c/1.txt
+path2/1.txt
+path3/1.txt
+path3/2.txt
+EOF
+ test_output
+'
+
test_done
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index cb5f7a4441..d59a9b4aef 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -14,10 +14,10 @@ test_expect_success \
'prepare a trivial repository' \
'echo Hello > A &&
git update-index --add A &&
- git-commit -m "Initial commit." &&
+ git commit -m "Initial commit." &&
echo World >> A &&
git update-index --add A &&
- git-commit -m "Second commit." &&
+ git commit -m "Second commit." &&
HEAD=$(git rev-parse --verify HEAD)'
test_expect_success \
@@ -78,13 +78,13 @@ test_expect_success \
test_expect_success 'git branch -m o/o o should fail when o/p exists' '
git branch o/o &&
git branch o/p &&
- ! git branch -m o/o o
+ test_must_fail git branch -m o/o o
'
test_expect_success 'git branch -m q r/q should fail when r exists' '
git branch q &&
git branch r &&
- ! git branch -m q r/q
+ test_must_fail git branch -m q r/q
'
mv .git/config .git/config-saved
@@ -110,20 +110,29 @@ test_expect_success \
test_expect_success 'config information was renamed, too' \
"test $(git config branch.s.dummy) = Hello &&
- ! git config branch.s/s/dummy"
+ test_must_fail git config branch.s/s/dummy"
-test_expect_success \
+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 &&
+ git symbolic-ref refs/heads/master2 &&
+ test -f .git/refs/heads/master &&
+ ! test -f .git/refs/heads/master3
+'
+
+test_expect_success SYMLINKS \
'git branch -m u v should fail when the reflog for u is a symlink' '
git branch -l u &&
mv .git/logs/refs/heads/u real-u &&
ln -s real-u .git/logs/refs/heads/u &&
- ! git branch -m u v
+ test_must_fail git branch -m u v
'
test_expect_success 'test tracking setup via --track' \
'git config remote.local.url . &&
git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
- (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
git branch --track my1 local/master &&
test $(git config branch.my1.remote) = local &&
test $(git config branch.my1.merge) = refs/heads/master'
@@ -131,7 +140,7 @@ test_expect_success 'test tracking setup via --track' \
test_expect_success 'test tracking setup (non-wildcard, matching)' \
'git config remote.local.url . &&
git config remote.local.fetch refs/heads/master:refs/remotes/local/master &&
- (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
git branch --track my4 local/master &&
test $(git config branch.my4.remote) = local &&
test $(git config branch.my4.merge) = refs/heads/master'
@@ -139,7 +148,7 @@ test_expect_success 'test tracking setup (non-wildcard, matching)' \
test_expect_success 'test tracking setup (non-wildcard, not matching)' \
'git config remote.local.url . &&
git config remote.local.fetch refs/heads/s:refs/remotes/local/s &&
- (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
git branch --track my5 local/master &&
! test "$(git config branch.my5.remote)" = local &&
! test "$(git config branch.my5.merge)" = refs/heads/master'
@@ -148,7 +157,7 @@ test_expect_success 'test tracking setup via config' \
'git config branch.autosetupmerge true &&
git config remote.local.url . &&
git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
- (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
git branch my3 local/master &&
test $(git config branch.my3.remote) = local &&
test $(git config branch.my3.merge) = refs/heads/master'
@@ -157,7 +166,7 @@ test_expect_success 'test overriding tracking setup via --no-track' \
'git config branch.autosetupmerge true &&
git config remote.local.url . &&
git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
- (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
git branch --no-track my2 local/master &&
git config branch.autosetupmerge false &&
! test "$(git config branch.my2.remote)" = local &&
@@ -173,7 +182,7 @@ test_expect_success 'no tracking without .fetch entries' \
test_expect_success 'test tracking setup via --track but deeper' \
'git config remote.local.url . &&
git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
- (git show-ref -q refs/remotes/local/o/o || git-fetch local) &&
+ (git show-ref -q refs/remotes/local/o/o || git fetch local) &&
git branch --track my7 local/o/o &&
test "$(git config branch.my7.remote)" = local &&
test "$(git config branch.my7.merge)" = refs/heads/o/o'
@@ -185,7 +194,8 @@ test_expect_success 'test deleting branch deletes branch config' \
test_expect_success 'test deleting branch without config' \
'git branch my7 s &&
- test "$(git branch -d my7 2>&1)" = "Deleted branch my7."'
+ sha1=$(git rev-parse my7 | cut -c 1-7) &&
+ test "$(git branch -d my7 2>&1)" = "Deleted branch my7 (was $sha1)."'
test_expect_success 'test --track without .fetch entries' \
'git branch --track my8 &&
@@ -200,7 +210,7 @@ test_expect_success \
test_expect_success \
'branch from non-branch HEAD w/--track causes failure' \
- '!(git branch --track my10 HEAD^)'
+ 'test_must_fail git branch --track my10 HEAD^'
# Keep this test last, as it changes the current branch
cat >expect <<EOF
@@ -209,7 +219,7 @@ EOF
test_expect_success \
'git checkout -b g/h/i -l should create a branch and a log' \
'GIT_COMMITTER_DATE="2005-05-26 23:30" \
- git-checkout -b g/h/i -l master &&
+ git checkout -b g/h/i -l master &&
test -f .git/refs/heads/g/h/i &&
test -f .git/logs/refs/heads/g/h/i &&
diff expect .git/logs/refs/heads/g/h/i'
@@ -224,4 +234,238 @@ test_expect_success 'avoid ambiguous track' '
test -z "$(git config branch.all1.merge)"
'
+test_expect_success 'autosetuprebase local on a tracked local branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ git config branch.autosetuprebase local &&
+ (git show-ref -q refs/remotes/local/o || git fetch local) &&
+ git branch mybase &&
+ git branch --track myr1 mybase &&
+ test "$(git config branch.myr1.remote)" = . &&
+ test "$(git config branch.myr1.merge)" = refs/heads/mybase &&
+ test "$(git config branch.myr1.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase always on a tracked local branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ git config branch.autosetuprebase always &&
+ (git show-ref -q refs/remotes/local/o || git fetch local) &&
+ git branch mybase2 &&
+ git branch --track myr2 mybase &&
+ test "$(git config branch.myr2.remote)" = . &&
+ test "$(git config branch.myr2.merge)" = refs/heads/mybase &&
+ test "$(git config branch.myr2.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase remote on a tracked local branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ git config branch.autosetuprebase remote &&
+ (git show-ref -q refs/remotes/local/o || git fetch local) &&
+ git branch mybase3 &&
+ git branch --track myr3 mybase2 &&
+ test "$(git config branch.myr3.remote)" = . &&
+ test "$(git config branch.myr3.merge)" = refs/heads/mybase2 &&
+ ! test "$(git config branch.myr3.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase never on a tracked local branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ git config branch.autosetuprebase never &&
+ (git show-ref -q refs/remotes/local/o || git fetch local) &&
+ git branch mybase4 &&
+ git branch --track myr4 mybase2 &&
+ test "$(git config branch.myr4.remote)" = . &&
+ test "$(git config branch.myr4.merge)" = refs/heads/mybase2 &&
+ ! test "$(git config branch.myr4.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase local on a tracked remote branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ git config branch.autosetuprebase local &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --track myr5 local/master &&
+ test "$(git config branch.myr5.remote)" = local &&
+ test "$(git config branch.myr5.merge)" = refs/heads/master &&
+ ! test "$(git config branch.myr5.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase never on a tracked remote branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ git config branch.autosetuprebase never &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --track myr6 local/master &&
+ test "$(git config branch.myr6.remote)" = local &&
+ test "$(git config branch.myr6.merge)" = refs/heads/master &&
+ ! test "$(git config branch.myr6.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase remote on a tracked remote branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ git config branch.autosetuprebase remote &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --track myr7 local/master &&
+ test "$(git config branch.myr7.remote)" = local &&
+ test "$(git config branch.myr7.merge)" = refs/heads/master &&
+ test "$(git config branch.myr7.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase always on a tracked remote branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ git config branch.autosetuprebase remote &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --track myr8 local/master &&
+ test "$(git config branch.myr8.remote)" = local &&
+ test "$(git config branch.myr8.merge)" = refs/heads/master &&
+ test "$(git config branch.myr8.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase unconfigured on a tracked remote branch' '
+ git config --unset branch.autosetuprebase &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --track myr9 local/master &&
+ test "$(git config branch.myr9.remote)" = local &&
+ test "$(git config branch.myr9.merge)" = refs/heads/master &&
+ test "z$(git config branch.myr9.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase unconfigured on a tracked local branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/o || git fetch local) &&
+ git branch mybase10 &&
+ git branch --track myr10 mybase2 &&
+ test "$(git config branch.myr10.remote)" = . &&
+ test "$(git config branch.myr10.merge)" = refs/heads/mybase2 &&
+ test "z$(git config branch.myr10.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase unconfigured on untracked local branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr11 mybase2 &&
+ test "z$(git config branch.myr11.remote)" = z &&
+ test "z$(git config branch.myr11.merge)" = z &&
+ test "z$(git config branch.myr11.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase unconfigured on untracked remote branch' '
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr12 local/master &&
+ test "z$(git config branch.myr12.remote)" = z &&
+ test "z$(git config branch.myr12.merge)" = z &&
+ test "z$(git config branch.myr12.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase never on an untracked local branch' '
+ git config branch.autosetuprebase never &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr13 mybase2 &&
+ test "z$(git config branch.myr13.remote)" = z &&
+ test "z$(git config branch.myr13.merge)" = z &&
+ test "z$(git config branch.myr13.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase local on an untracked local branch' '
+ git config branch.autosetuprebase local &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr14 mybase2 &&
+ test "z$(git config branch.myr14.remote)" = z &&
+ test "z$(git config branch.myr14.merge)" = z &&
+ test "z$(git config branch.myr14.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase remote on an untracked local branch' '
+ git config branch.autosetuprebase remote &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr15 mybase2 &&
+ test "z$(git config branch.myr15.remote)" = z &&
+ test "z$(git config branch.myr15.merge)" = z &&
+ test "z$(git config branch.myr15.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase always on an untracked local branch' '
+ git config branch.autosetuprebase always &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr16 mybase2 &&
+ test "z$(git config branch.myr16.remote)" = z &&
+ test "z$(git config branch.myr16.merge)" = z &&
+ test "z$(git config branch.myr16.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase never on an untracked remote branch' '
+ git config branch.autosetuprebase never &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr17 local/master &&
+ test "z$(git config branch.myr17.remote)" = z &&
+ test "z$(git config branch.myr17.merge)" = z &&
+ test "z$(git config branch.myr17.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase local on an untracked remote branch' '
+ git config branch.autosetuprebase local &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr18 local/master &&
+ test "z$(git config branch.myr18.remote)" = z &&
+ test "z$(git config branch.myr18.merge)" = z &&
+ test "z$(git config branch.myr18.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase remote on an untracked remote branch' '
+ git config branch.autosetuprebase remote &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr19 local/master &&
+ test "z$(git config branch.myr19.remote)" = z &&
+ test "z$(git config branch.myr19.merge)" = z &&
+ test "z$(git config branch.myr19.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase always on an untracked remote branch' '
+ git config branch.autosetuprebase always &&
+ git config remote.local.url . &&
+ git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git show-ref -q refs/remotes/local/master || git fetch local) &&
+ git branch --no-track myr20 local/master &&
+ test "z$(git config branch.myr20.remote)" = z &&
+ test "z$(git config branch.myr20.merge)" = z &&
+ test "z$(git config branch.myr20.rebase)" = z
+'
+
+test_expect_success 'detect misconfigured autosetuprebase (bad value)' '
+ git config branch.autosetuprebase garbage &&
+ test_must_fail git branch
+'
+
+test_expect_success 'detect misconfigured autosetuprebase (no value)' '
+ git config --unset branch.autosetuprebase &&
+ echo "[branch] autosetuprebase" >> .git/config &&
+ test_must_fail git branch &&
+ git config --unset branch.autosetuprebase
+'
+
test_done
diff --git a/t/t3202-show-branch-octopus.sh b/t/t3202-show-branch-octopus.sh
new file mode 100755
index 0000000000..0a5d5e669f
--- /dev/null
+++ b/t/t3202-show-branch-octopus.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+test_description='test show-branch with more than 8 heads'
+
+. ./test-lib.sh
+
+numbers="1 2 3 4 5 6 7 8 9 10"
+
+test_expect_success 'setup' '
+
+ > file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+
+ for i in $numbers
+ do
+ git checkout -b branch$i master &&
+ > file$i &&
+ git add file$i &&
+ test_tick &&
+ git commit -m branch$i || break
+ done
+
+'
+
+cat > expect << EOF
+! [branch1] branch1
+ ! [branch2] branch2
+ ! [branch3] branch3
+ ! [branch4] branch4
+ ! [branch5] branch5
+ ! [branch6] branch6
+ ! [branch7] branch7
+ ! [branch8] branch8
+ ! [branch9] branch9
+ * [branch10] branch10
+----------
+ * [branch10] branch10
+ + [branch9] branch9
+ + [branch8] branch8
+ + [branch7] branch7
+ + [branch6] branch6
+ + [branch5] branch5
+ + [branch4] branch4
+ + [branch3] branch3
+ + [branch2] branch2
++ [branch1] branch1
++++++++++* [branch10^] initial
+EOF
+
+test_expect_success 'show-branch with more than 8 branches' '
+
+ git show-branch $(for i in $numbers; do echo branch$i; done) > out &&
+ test_cmp expect out
+
+'
+
+test_expect_success 'show-branch with showbranch.default' '
+ for i in $numbers; do
+ git config --add showbranch.default branch$i
+ done &&
+ git show-branch >out &&
+ test_cmp expect out
+'
+
+test_done
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
new file mode 100755
index 0000000000..809d1c4ed4
--- /dev/null
+++ b/t/t3203-branch-output.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+test_description='git branch display tests'
+. ./test-lib.sh
+
+test_expect_success 'make commits' '
+ echo content >file &&
+ git add file &&
+ git commit -m one &&
+ echo content >>file &&
+ git commit -a -m two
+'
+
+test_expect_success 'make branches' '
+ git branch branch-one
+ git branch branch-two HEAD^
+'
+
+test_expect_success 'make remote branches' '
+ git update-ref refs/remotes/origin/branch-one branch-one
+ git update-ref refs/remotes/origin/branch-two branch-two
+ git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/branch-one
+'
+
+cat >expect <<'EOF'
+ branch-one
+ branch-two
+* master
+EOF
+test_expect_success 'git branch shows local branches' '
+ git branch >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+ origin/HEAD -> origin/branch-one
+ origin/branch-one
+ origin/branch-two
+EOF
+test_expect_success 'git branch -r shows remote branches' '
+ git branch -r >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+ branch-one
+ branch-two
+* master
+ remotes/origin/HEAD -> origin/branch-one
+ remotes/origin/branch-one
+ remotes/origin/branch-two
+EOF
+test_expect_success 'git branch -a shows local and remote branches' '
+ git branch -a >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+two
+one
+two
+EOF
+test_expect_success 'git branch -v shows branch summaries' '
+ git branch -v >tmp &&
+ awk "{print \$NF}" <tmp >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+* (no branch)
+ branch-one
+ branch-two
+ master
+EOF
+test_expect_success 'git branch shows detached HEAD properly' '
+ git checkout HEAD^0 &&
+ git branch >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index b64ccfbc5b..413019acaf 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -17,7 +17,7 @@ test_expect_success \
'prepare a trivial repository' \
'echo Hello > A &&
git update-index --add A &&
- git-commit -m "Initial commit." &&
+ git commit -m "Initial commit." &&
HEAD=$(git rev-parse --verify HEAD)'
SHA1=
@@ -43,7 +43,7 @@ test_expect_success 'git branch c/d should barf if branch c exists' '
git branch c &&
git pack-refs --all &&
rm -f .git/refs/heads/c &&
- ! git branch c/d
+ test_must_fail git branch c/d
'
test_expect_success \
@@ -72,7 +72,7 @@ test_expect_success \
test_expect_success 'git branch i/j/k should barf if branch i exists' '
git branch i &&
git pack-refs --all --prune &&
- ! git branch i/j/k
+ test_must_fail git branch i/j/k
'
test_expect_success \
@@ -96,8 +96,15 @@ test_expect_success \
git branch -d n/o/p &&
git branch n'
+test_expect_success \
+ 'see if up-to-date packed refs are preserved' \
+ 'git branch q &&
+ git pack-refs --all --prune &&
+ git update-ref refs/heads/q refs/heads/q &&
+ ! test -f .git/refs/heads/q'
+
test_expect_success 'pack, prune and repack' '
- git-tag foo &&
+ git tag foo &&
git pack-refs --all --prune &&
git show-ref >all-of-them &&
git pack-refs &&
diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh
index 24a00a9df1..db46d53e82 100755
--- a/t/t3300-funny-names.sh
+++ b/t/t3300-funny-names.sh
@@ -21,7 +21,7 @@ cat >"$p0" <<\EOF
3. A quick brown fox jumps over the lazy cat, oops dog.
EOF
-cat >"$p1" "$p0"
+cat 2>/dev/null >"$p1" "$p0"
echo 'Foo Bar Baz' >"$p2"
test -f "$p1" && cmp "$p0" "$p1" || {
@@ -35,7 +35,7 @@ no-funny' >expected
test_expect_success 'git ls-files no-funny' \
'git update-index --add "$p0" "$p2" &&
git ls-files >current &&
- git diff expected current'
+ test_cmp expected current'
t0=`git write-tree`
echo "$t0" >t0
@@ -48,14 +48,14 @@ EOF
test_expect_success 'git ls-files with-funny' \
'git update-index --add "$p1" &&
git ls-files >current &&
- git diff expected current'
+ test_cmp expected current'
echo 'just space
no-funny
tabs ," (dq) and spaces' >expected
test_expect_success 'git ls-files -z with-funny' \
'git ls-files -z | perl -pe y/\\000/\\012/ >current &&
- git diff expected current'
+ test_cmp expected current'
t1=`git write-tree`
echo "$t1" >t1
@@ -67,28 +67,28 @@ no-funny
EOF
test_expect_success 'git ls-tree with funny' \
'git ls-tree -r $t1 | sed -e "s/^[^ ]* //" >current &&
- git diff expected current'
+ test_cmp expected current'
cat > expected <<\EOF
A "tabs\t,\" (dq) and spaces"
EOF
test_expect_success 'git diff-index with-funny' \
'git diff-index --name-status $t0 >current &&
- git diff expected current'
+ test_cmp expected current'
test_expect_success 'git diff-tree with-funny' \
'git diff-tree --name-status $t0 $t1 >current &&
- git diff expected current'
+ test_cmp expected current'
echo 'A
tabs ," (dq) and spaces' >expected
test_expect_success 'git diff-index -z with-funny' \
'git diff-index -z --name-status $t0 | perl -pe y/\\000/\\012/ >current &&
- git diff expected current'
+ test_cmp expected current'
test_expect_success 'git diff-tree -z with-funny' \
'git diff-tree -z --name-status $t0 $t1 | perl -pe y/\\000/\\012/ >current &&
- git diff expected current'
+ test_cmp expected current'
cat > expected <<\EOF
CNUM no-funny "tabs\t,\" (dq) and spaces"
@@ -96,7 +96,7 @@ EOF
test_expect_success 'git diff-tree -C with-funny' \
'git diff-tree -C --find-copies-harder --name-status \
$t0 $t1 | sed -e 's/^C[0-9]*/CNUM/' >current &&
- git diff expected current'
+ test_cmp expected current'
cat > expected <<\EOF
RNUM no-funny "tabs\t,\" (dq) and spaces"
@@ -105,7 +105,7 @@ test_expect_success 'git diff-tree delete with-funny' \
'git update-index --force-remove "$p0" &&
git diff-index -M --name-status \
$t0 | sed -e 's/^R[0-9]*/RNUM/' >current &&
- git diff expected current'
+ test_cmp expected current'
cat > expected <<\EOF
diff --git a/no-funny "b/tabs\t,\" (dq) and spaces"
@@ -116,7 +116,7 @@ EOF
test_expect_success 'git diff-tree delete with-funny' \
'git diff-index -M -p $t0 |
sed -e "s/index [0-9]*%/index NUM%/" >current &&
- git diff expected current'
+ test_cmp expected current'
chmod +x "$p1"
cat > expected <<\EOF
@@ -130,7 +130,7 @@ EOF
test_expect_success 'git diff-tree delete with-funny' \
'git diff-index -M -p $t0 |
sed -e "s/index [0-9]*%/index NUM%/" >current &&
- git diff expected current'
+ test_cmp expected current'
cat >expected <<\EOF
"tabs\t,\" (dq) and spaces"
@@ -139,7 +139,7 @@ EOF
test_expect_success 'git diff-tree rename with-funny applied' \
'git diff-index -M -p $t0 |
git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current &&
- git diff expected current'
+ test_cmp expected current'
cat > expected <<\EOF
no-funny
@@ -149,12 +149,12 @@ EOF
test_expect_success 'git diff-tree delete with-funny applied' \
'git diff-index -p $t0 |
git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current &&
- git diff expected current'
+ test_cmp expected current'
test_expect_success 'git apply non-git diff' \
'git diff-index -p $t0 |
sed -ne "/^[-+@]/p" |
git apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current &&
- git diff expected current'
+ test_cmp expected current'
test_done
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
new file mode 100755
index 0000000000..5d9604b815
--- /dev/null
+++ b/t/t3301-notes.sh
@@ -0,0 +1,209 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='Test commit notes'
+
+. ./test-lib.sh
+
+cat > fake_editor.sh << \EOF
+echo "$MSG" > "$1"
+echo "$MSG" >& 2
+EOF
+chmod a+x fake_editor.sh
+VISUAL=./fake_editor.sh
+export VISUAL
+
+test_expect_success 'cannot annotate non-existing HEAD' '
+ (MSG=3 && export MSG && test_must_fail git notes edit)
+'
+
+test_expect_success setup '
+ : > a1 &&
+ git add a1 &&
+ test_tick &&
+ git commit -m 1st &&
+ : > a2 &&
+ git add a2 &&
+ test_tick &&
+ git commit -m 2nd
+'
+
+test_expect_success 'need valid notes ref' '
+ (MSG=1 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF &&
+ test_must_fail git notes edit) &&
+ (MSG=2 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF &&
+ test_must_fail git notes show)
+'
+
+test_expect_success 'refusing to edit in refs/heads/' '
+ (MSG=1 GIT_NOTES_REF=refs/heads/bogus &&
+ export MSG GIT_NOTES_REF &&
+ test_must_fail git notes edit)
+'
+
+test_expect_success 'refusing to edit in refs/remotes/' '
+ (MSG=1 GIT_NOTES_REF=refs/remotes/bogus &&
+ export MSG GIT_NOTES_REF &&
+ test_must_fail git notes edit)
+'
+
+# 1 indicates caught gracefully by die, 128 means git-show barked
+test_expect_success 'handle empty notes gracefully' '
+ git notes show ; test 1 = $?
+'
+
+test_expect_success 'create notes' '
+ git config core.notesRef refs/notes/commits &&
+ MSG=b1 git notes edit &&
+ test ! -f .git/new-notes &&
+ test 1 = $(git ls-tree refs/notes/commits | wc -l) &&
+ test b1 = $(git notes show) &&
+ git show HEAD^ &&
+ test_must_fail git notes show HEAD^
+'
+
+cat > expect << EOF
+commit 268048bfb8a1fb38e703baceb8ab235421bf80c5
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:14:13 2005 -0700
+
+ 2nd
+
+Notes:
+ b1
+EOF
+
+test_expect_success 'show notes' '
+ ! (git cat-file commit HEAD | grep b1) &&
+ git log -1 > output &&
+ test_cmp expect output
+'
+test_expect_success 'create multi-line notes (setup)' '
+ : > a3 &&
+ git add a3 &&
+ test_tick &&
+ git commit -m 3rd &&
+ MSG="b3
+c3c3c3c3
+d3d3d3" git notes edit
+'
+
+cat > expect-multiline << EOF
+commit 1584215f1d29c65e99c6c6848626553fdd07fd75
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:15:13 2005 -0700
+
+ 3rd
+
+Notes:
+ b3
+ c3c3c3c3
+ d3d3d3
+EOF
+
+printf "\n" >> expect-multiline
+cat expect >> expect-multiline
+
+test_expect_success 'show multi-line notes' '
+ git log -2 > output &&
+ test_cmp expect-multiline output
+'
+test_expect_success 'create -m and -F notes (setup)' '
+ : > a4 &&
+ git add a4 &&
+ test_tick &&
+ git commit -m 4th &&
+ echo "xyzzy" > note5 &&
+ git notes edit -m spam -F note5 -m "foo
+bar
+baz"
+'
+
+whitespace=" "
+cat > expect-m-and-F << EOF
+commit 15023535574ded8b1a89052b32673f84cf9582b8
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:16:13 2005 -0700
+
+ 4th
+
+Notes:
+ spam
+$whitespace
+ xyzzy
+$whitespace
+ foo
+ bar
+ baz
+EOF
+
+printf "\n" >> expect-m-and-F
+cat expect-multiline >> expect-m-and-F
+
+test_expect_success 'show -m and -F notes' '
+ git log -3 > output &&
+ test_cmp expect-m-and-F output
+'
+
+cat >expect << EOF
+commit 15023535574ded8b1a89052b32673f84cf9582b8
+tree e070e3af51011e47b183c33adf9736736a525709
+parent 1584215f1d29c65e99c6c6848626553fdd07fd75
+author A U Thor <author@example.com> 1112912173 -0700
+committer C O Mitter <committer@example.com> 1112912173 -0700
+
+ 4th
+EOF
+test_expect_success 'git log --pretty=raw does not show notes' '
+ git log -1 --pretty=raw >output &&
+ test_cmp expect output
+'
+
+cat >>expect <<EOF
+
+Notes:
+ spam
+$whitespace
+ xyzzy
+$whitespace
+ foo
+ bar
+ baz
+EOF
+test_expect_success 'git log --show-notes' '
+ git log -1 --pretty=raw --show-notes >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'git log --no-notes' '
+ git log -1 --no-notes >output &&
+ ! grep spam output
+'
+
+test_expect_success 'git format-patch does not show notes' '
+ git format-patch -1 --stdout >output &&
+ ! grep spam output
+'
+
+test_expect_success 'git format-patch --show-notes does show notes' '
+ git format-patch --show-notes -1 --stdout >output &&
+ grep spam output
+'
+
+for pretty in \
+ "" --pretty --pretty=raw --pretty=short --pretty=medium \
+ --pretty=full --pretty=fuller --pretty=format:%s --oneline
+do
+ case "$pretty" in
+ "") p= not= negate="" ;;
+ ?*) p="$pretty" not=" not" negate="!" ;;
+ esac
+ test_expect_success "git show $pretty does$not show notes" '
+ git show $p >output &&
+ eval "$negate grep spam output"
+ '
+done
+
+test_done
diff --git a/t/t3302-notes-index-expensive.sh b/t/t3302-notes-index-expensive.sh
new file mode 100755
index 0000000000..ee84fc4884
--- /dev/null
+++ b/t/t3302-notes-index-expensive.sh
@@ -0,0 +1,118 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='Test commit notes index (expensive!)'
+
+. ./test-lib.sh
+
+test -z "$GIT_NOTES_TIMING_TESTS" && {
+ say Skipping timing tests
+ test_done
+ exit
+}
+
+create_repo () {
+ number_of_commits=$1
+ nr=0
+ test -d .git || {
+ git init &&
+ (
+ while [ $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
+ done &&
+ test_tick &&
+ cat <<INPUT_END &&
+commit refs/notes/commits
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes
+COMMIT
+
+INPUT_END
+
+ cat note_commit
+ ) |
+ git fast-import --quiet &&
+ git config core.notesRef refs/notes/commits
+ }
+}
+
+test_notes () {
+ count=$1 &&
+ git config core.notesRef refs/notes/commits &&
+ git log | grep "^ " > output &&
+ i=$count &&
+ while [ $i -gt 0 ]; do
+ echo " commit #$i" &&
+ echo " note for commit #$i" &&
+ i=$(($i-1));
+ done > expect &&
+ test_cmp expect output
+}
+
+cat > time_notes << \EOF
+ mode=$1
+ i=1
+ while [ $i -lt $2 ]; do
+ case $1 in
+ no-notes)
+ GIT_NOTES_REF=non-existing; export GIT_NOTES_REF
+ ;;
+ notes)
+ unset GIT_NOTES_REF
+ ;;
+ esac
+ git log >/dev/null
+ i=$(($i+1))
+ done
+EOF
+
+time_notes () {
+ for mode in no-notes notes
+ do
+ echo $mode
+ /usr/bin/time sh ../time_notes $mode $1
+ done
+}
+
+for count in 10 100 1000 10000; do
+
+ mkdir $count
+ (cd $count;
+
+ test_expect_success "setup $count" "create_repo $count"
+
+ test_expect_success 'notes work' "test_notes $count"
+
+ test_expect_success 'notes timing' "time_notes 100"
+ )
+done
+
+test_done
diff --git a/t/t3303-notes-subtrees.sh b/t/t3303-notes-subtrees.sh
new file mode 100755
index 0000000000..edc4bc8841
--- /dev/null
+++ b/t/t3303-notes-subtrees.sh
@@ -0,0 +1,188 @@
+#!/bin/sh
+
+test_description='Test commit notes organized in subtrees'
+
+. ./test-lib.sh
+
+number_of_commits=100
+
+start_note_commit () {
+ test_tick &&
+ cat <<INPUT_END
+commit refs/notes/commits
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes
+COMMIT
+
+from refs/notes/commits^0
+deleteall
+INPUT_END
+
+}
+
+verify_notes () {
+ git log | grep "^ " > output &&
+ i=$number_of_commits &&
+ while [ $i -gt 0 ]; do
+ echo " commit #$i" &&
+ echo " note for commit #$i" &&
+ i=$(($i-1));
+ done > expect &&
+ test_cmp expect output
+}
+
+test_expect_success "setup: create $number_of_commits commits" '
+
+ (
+ nr=0 &&
+ while [ $nr -lt $number_of_commits ]; do
+ nr=$(($nr+1)) &&
+ test_tick &&
+ cat <<INPUT_END
+commit refs/heads/master
+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
+
+INPUT_END
+
+ done &&
+ test_tick &&
+ cat <<INPUT_END
+commit refs/notes/commits
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+no notes
+COMMIT
+
+deleteall
+
+INPUT_END
+
+ ) |
+ git fast-import --quiet &&
+ git config core.notesRef refs/notes/commits
+'
+
+test_sha1_based () {
+ (
+ start_note_commit &&
+ nr=$number_of_commits &&
+ git rev-list refs/heads/master |
+ while read sha1; do
+ note_path=$(echo "$sha1" | sed "$1")
+ cat <<INPUT_END &&
+M 100644 inline $note_path
+data <<EOF
+note for commit #$nr
+EOF
+
+INPUT_END
+
+ nr=$(($nr-1))
+ done
+ ) |
+ git fast-import --quiet
+}
+
+test_expect_success 'test notes in 2/38-fanout' 'test_sha1_based "s|^..|&/|"'
+test_expect_success 'verify notes in 2/38-fanout' 'verify_notes'
+
+test_expect_success 'test notes in 4/36-fanout' 'test_sha1_based "s|^....|&/|"'
+test_expect_success 'verify notes in 4/36-fanout' 'verify_notes'
+
+test_expect_success 'test notes in 2/2/36-fanout' 'test_sha1_based "s|^\(..\)\(..\)|\1/\2/|"'
+test_expect_success 'verify notes in 2/2/36-fanout' 'verify_notes'
+
+test_same_notes () {
+ (
+ start_note_commit &&
+ nr=$number_of_commits &&
+ git rev-list refs/heads/master |
+ while read sha1; do
+ first_note_path=$(echo "$sha1" | sed "$1")
+ second_note_path=$(echo "$sha1" | sed "$2")
+ cat <<INPUT_END &&
+M 100644 inline $second_note_path
+data <<EOF
+note for commit #$nr
+EOF
+
+M 100644 inline $first_note_path
+data <<EOF
+note for commit #$nr
+EOF
+
+INPUT_END
+
+ nr=$(($nr-1))
+ done
+ ) |
+ git fast-import --quiet
+}
+
+test_expect_success 'test same notes in 4/36-fanout and 2/38-fanout' 'test_same_notes "s|^..|&/|" "s|^....|&/|"'
+test_expect_success 'verify same notes in 4/36-fanout and 2/38-fanout' 'verify_notes'
+
+test_expect_success 'test same notes in 2/38-fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^..|&/|"'
+test_expect_success 'verify same notes in 2/38-fanout and 2/2/36-fanout' 'verify_notes'
+
+test_expect_success 'test same notes in 4/36-fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^....|&/|"'
+test_expect_success 'verify same notes in 4/36-fanout and 2/2/36-fanout' 'verify_notes'
+
+test_concatenated_notes () {
+ (
+ start_note_commit &&
+ nr=$number_of_commits &&
+ git rev-list refs/heads/master |
+ while read sha1; do
+ first_note_path=$(echo "$sha1" | sed "$1")
+ second_note_path=$(echo "$sha1" | sed "$2")
+ cat <<INPUT_END &&
+M 100644 inline $second_note_path
+data <<EOF
+second note for commit #$nr
+EOF
+
+M 100644 inline $first_note_path
+data <<EOF
+first note for commit #$nr
+EOF
+
+INPUT_END
+
+ nr=$(($nr-1))
+ done
+ ) |
+ git fast-import --quiet
+}
+
+verify_concatenated_notes () {
+ git log | grep "^ " > output &&
+ i=$number_of_commits &&
+ while [ $i -gt 0 ]; do
+ echo " commit #$i" &&
+ echo " first note for commit #$i" &&
+ echo " second note for commit #$i" &&
+ i=$(($i-1));
+ done > expect &&
+ test_cmp expect output
+}
+
+test_expect_success 'test notes in 4/36-fanout concatenated with 2/38-fanout' 'test_concatenated_notes "s|^..|&/|" "s|^....|&/|"'
+test_expect_success 'verify notes in 4/36-fanout concatenated with 2/38-fanout' 'verify_concatenated_notes'
+
+test_expect_success 'test notes in 2/38-fanout concatenated with 2/2/36-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^..|&/|"'
+test_expect_success 'verify notes in 2/38-fanout concatenated with 2/2/36-fanout' 'verify_concatenated_notes'
+
+test_expect_success 'test notes in 4/36-fanout concatenated with 2/2/36-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^....|&/|"'
+test_expect_success 'verify notes in 4/36-fanout concatenated with 2/2/36-fanout' 'verify_concatenated_notes'
+
+test_done
diff --git a/t/t3304-notes-mixed.sh b/t/t3304-notes-mixed.sh
new file mode 100755
index 0000000000..256687ffb5
--- /dev/null
+++ b/t/t3304-notes-mixed.sh
@@ -0,0 +1,172 @@
+#!/bin/sh
+
+test_description='Test notes trees that also contain non-notes'
+
+. ./test-lib.sh
+
+number_of_commits=100
+
+start_note_commit () {
+ test_tick &&
+ cat <<INPUT_END
+commit refs/notes/commits
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes
+COMMIT
+
+from refs/notes/commits^0
+deleteall
+INPUT_END
+
+}
+
+verify_notes () {
+ git log | grep "^ " > output &&
+ i=$number_of_commits &&
+ while [ $i -gt 0 ]; do
+ echo " commit #$i" &&
+ echo " note for commit #$i" &&
+ i=$(($i-1));
+ done > expect &&
+ test_cmp expect output
+}
+
+test_expect_success "setup: create a couple of commits" '
+
+ test_tick &&
+ cat <<INPUT_END >input &&
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+commit #1
+COMMIT
+
+M 644 inline file
+data <<EOF
+file in commit #1
+EOF
+
+INPUT_END
+
+ test_tick &&
+ cat <<INPUT_END >>input &&
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+commit #2
+COMMIT
+
+M 644 inline file
+data <<EOF
+file in commit #2
+EOF
+
+INPUT_END
+ git fast-import --quiet <input
+'
+
+test_expect_success "create a notes tree with both notes and non-notes" '
+
+ commit1=$(git rev-parse refs/heads/master^) &&
+ commit2=$(git rev-parse refs/heads/master) &&
+ test_tick &&
+ cat <<INPUT_END >input &&
+commit refs/notes/commits
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes commit #1
+COMMIT
+
+N inline $commit1
+data <<EOF
+note for commit #1
+EOF
+
+N inline $commit2
+data <<EOF
+note for commit #2
+EOF
+
+INPUT_END
+ test_tick &&
+ cat <<INPUT_END >>input &&
+commit refs/notes/commits
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes commit #2
+COMMIT
+
+M 644 inline foobar/non-note.txt
+data <<EOF
+A non-note in a notes tree
+EOF
+
+N inline $commit2
+data <<EOF
+edited note for commit #2
+EOF
+
+INPUT_END
+ test_tick &&
+ cat <<INPUT_END >>input &&
+commit refs/notes/commits
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes commit #3
+COMMIT
+
+N inline $commit1
+data <<EOF
+edited note for commit #1
+EOF
+
+M 644 inline deadbeef
+data <<EOF
+non-note with SHA1-like name
+EOF
+
+M 644 inline de/adbeef
+data <<EOF
+another non-note with SHA1-like name
+EOF
+
+INPUT_END
+ git fast-import --quiet <input &&
+ git config core.notesRef refs/notes/commits
+'
+
+cat >expect <<EXPECT_END
+ commit #2
+ edited note for commit #2
+ commit #1
+ edited note for commit #1
+EXPECT_END
+
+test_expect_success "verify contents of notes" '
+
+ git log | grep "^ " > actual &&
+ test_cmp expect actual
+'
+
+cat >expect_nn1 <<EXPECT_END
+A non-note in a notes tree
+EXPECT_END
+cat >expect_nn2 <<EXPECT_END
+non-note with SHA1-like name
+EXPECT_END
+cat >expect_nn3 <<EXPECT_END
+another non-note with SHA1-like name
+EXPECT_END
+
+test_expect_success "verify contents of non-notes" '
+
+ git cat-file -p refs/notes/commits:foobar/non-note.txt > actual_nn1 &&
+ test_cmp expect_nn1 actual_nn1 &&
+ git cat-file -p refs/notes/commits:deadbeef > actual_nn2 &&
+ test_cmp expect_nn2 actual_nn2 &&
+ git cat-file -p refs/notes/commits:de/adbeef > actual_nn3 &&
+ test_cmp expect_nn3 actual_nn3
+'
+
+test_done
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 496f4ec172..4e6a44b623 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -3,27 +3,30 @@
# Copyright (c) 2005 Amos Waterland
#
-test_description='git rebase should not destroy author information
+test_description='git rebase assorted tests
-This test runs git rebase and checks that the author information is not lost.
+This test runs git rebase and checks that the author information is not lost
+among other things.
'
. ./test-lib.sh
-export GIT_AUTHOR_EMAIL=bogus_email_address
+GIT_AUTHOR_EMAIL=bogus_email_address
+export GIT_AUTHOR_EMAIL
test_expect_success \
'prepare repository with topic branches' \
- 'echo First > A &&
+ 'git config core.logAllRefUpdates true &&
+ echo First > A &&
git update-index --add A &&
- git-commit -m "Add A." &&
+ git commit -m "Add A." &&
git checkout -b my-topic-branch &&
echo Second > B &&
git update-index --add B &&
- git-commit -m "Add B." &&
+ git commit -m "Add B." &&
git checkout -f master &&
echo Third >> A &&
git update-index A &&
- git-commit -m "Modify A." &&
+ git commit -m "Modify A." &&
git checkout -b side my-topic-branch &&
echo Side >> C &&
git add C &&
@@ -39,18 +42,53 @@ test_expect_success \
git tag topic
'
+test_expect_success 'rebase on dirty worktree' '
+ echo dirty >> A &&
+ test_must_fail git rebase master'
+
+test_expect_success 'rebase on dirty cache' '
+ git add A &&
+ test_must_fail git rebase master'
+
test_expect_success 'rebase against master' '
+ git reset --hard HEAD &&
git rebase master'
+test_expect_success 'rebase against master twice' '
+ git rebase master >out &&
+ grep "Current branch my-topic-branch is up to date" out
+'
+
+test_expect_success 'rebase against master twice with --force' '
+ git rebase --force-rebase master >out &&
+ grep "Current branch my-topic-branch is up to date, rebase forced" out
+'
+
+test_expect_success 'rebase against master twice from another branch' '
+ git checkout my-topic-branch^ &&
+ git rebase master my-topic-branch >out &&
+ grep "Current branch my-topic-branch is up to date" out
+'
+
+test_expect_success 'rebase fast-forward to master' '
+ git checkout my-topic-branch^ &&
+ git rebase my-topic-branch >out &&
+ grep "Fast-forwarded HEAD to my-topic-branch" out
+'
+
test_expect_success \
'the rebase operation should not have destroyed author information' \
- '! git log | grep "Author:" | grep "<>"'
+ '! (git log | grep "Author:" | grep "<>")'
+
+test_expect_success 'HEAD was detached during rebase' '
+ test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1})
+'
test_expect_success 'rebase after merge master' '
git reset --hard topic &&
git merge master &&
git rebase master &&
- ! git show | grep "^Merge:"
+ ! (git show | grep "^Merge:")
'
test_expect_success 'rebase of history with merges is linearized' '
@@ -77,10 +115,44 @@ test_expect_success 'rebase a single mode change' '
git checkout -b modechange HEAD^ &&
echo 1 > X &&
git add X &&
- chmod a+x A &&
+ test_chmod +x A &&
test_tick &&
- git commit -m modechange A X &&
+ git commit -m modechange &&
GIT_TRACE=1 git rebase master
'
+test_expect_success 'Show verbose error when HEAD could not be detached' '
+ : > B &&
+ test_must_fail git rebase topic 2> output.err > output.out &&
+ grep "Untracked working tree file .B. would be overwritten" output.err
+'
+
+test_expect_success 'rebase -q is quiet' '
+ rm B &&
+ git checkout -b quiet topic &&
+ git rebase -q master > output.out 2>&1 &&
+ test ! -s output.out
+'
+
+q_to_cr () {
+ tr Q '\015'
+}
+
+test_expect_success 'Rebase a commit that sprinkles CRs in' '
+ (
+ echo "One"
+ echo "TwoQ"
+ echo "Three"
+ echo "FQur"
+ echo "Five"
+ ) | q_to_cr >CR &&
+ git add CR &&
+ test_tick &&
+ git commit -a -m "A file with a line with CR" &&
+ git tag file-with-cr &&
+ git checkout HEAD^0 &&
+ git rebase --onto HEAD^^ HEAD^ &&
+ git diff --exit-code file-with-cr:CR HEAD:CR
+'
+
test_done
diff --git a/t/t3401-rebase-partial.sh b/t/t3401-rebase-partial.sh
index 4934a4e010..aea6685984 100755
--- a/t/t3401-rebase-partial.sh
+++ b/t/t3401-rebase-partial.sh
@@ -15,29 +15,29 @@ test_expect_success \
'prepare repository with topic branch' \
'echo First > A &&
git update-index --add A &&
- git-commit -m "Add A." &&
+ git commit -m "Add A." &&
- git-checkout -b my-topic-branch &&
+ git checkout -b my-topic-branch &&
echo Second > B &&
git update-index --add B &&
- git-commit -m "Add B." &&
+ git commit -m "Add B." &&
echo AnotherSecond > C &&
git update-index --add C &&
- git-commit -m "Add C." &&
+ git commit -m "Add C." &&
- git-checkout -f master &&
+ git checkout -f master &&
echo Third >> A &&
git update-index A &&
- git-commit -m "Modify A."
+ git commit -m "Modify A."
'
test_expect_success \
'pick top patch from topic branch into master' \
'git cherry-pick my-topic-branch^0 &&
- git-checkout -f my-topic-branch &&
+ git checkout -f my-topic-branch &&
git branch master-merge master &&
git branch my-topic-branch-merge my-topic-branch
'
@@ -49,13 +49,13 @@ test_debug \
'
test_expect_success \
- 'rebase topic branch against new master and check git-am did not get halted' \
- 'git-rebase master && test ! -d .dotest'
+ 'rebase topic branch against new master and check git am did not get halted' \
+ 'git rebase master && test ! -d .git/rebase-apply'
test_expect_success \
'rebase --merge topic branch that was partially merged upstream' \
- 'git-checkout -f my-topic-branch-merge &&
- git-rebase --merge master-merge &&
- test ! -d .git/.dotest-merge'
+ 'git checkout -f my-topic-branch-merge &&
+ git rebase --merge master-merge &&
+ test ! -d .git/rebase-merge'
test_done
diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh
index 0a26099658..64446e3db3 100755
--- a/t/t3403-rebase-skip.sh
+++ b/t/t3403-rebase-skip.sh
@@ -7,7 +7,7 @@ test_description='git rebase --merge --skip tests'
. ./test-lib.sh
-# we assume the default git-am -3 --skip strategy is tested independently
+# we assume the default git am -3 --skip strategy is tested independently
# and always works :)
test_expect_success setup '
@@ -32,7 +32,7 @@ test_expect_success setup '
'
test_expect_success 'rebase with git am -3 (default)' '
- ! git rebase master
+ test_must_fail git rebase master
'
test_expect_success 'rebase --skip with am -3' '
@@ -43,7 +43,7 @@ test_expect_success 'rebase moves back to skip-reference' '
test refs/heads/skip-reference = $(git symbolic-ref HEAD) &&
git branch post-rebase &&
git reset --hard pre-rebase &&
- ! git rebase master &&
+ test_must_fail git rebase master &&
echo "hello" > hello &&
git add hello &&
git rebase --continue &&
@@ -53,7 +53,9 @@ test_expect_success 'rebase moves back to skip-reference' '
test_expect_success 'checkout skip-merge' 'git checkout -f skip-merge'
-test_expect_success 'rebase with --merge' '! git rebase --merge master'
+test_expect_success 'rebase with --merge' '
+ test_must_fail git rebase --merge master
+'
test_expect_success 'rebase --skip with --merge' '
git rebase --skip
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 9cf873f7eb..3a37793c0d 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -10,6 +10,10 @@ that the result still makes sense.
'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
# set up two branches like this:
#
# A - B - C - D - E
@@ -61,42 +65,9 @@ test_expect_success 'setup' '
git tag I
'
-echo "#!$SHELL_PATH" >fake-editor.sh
-cat >> fake-editor.sh <<\EOF
-case "$1" in
-*/COMMIT_EDITMSG)
- test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
- test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
- exit
- ;;
-esac
-test -z "$EXPECT_COUNT" ||
- test "$EXPECT_COUNT" = $(sed -e '/^#/d' -e '/^$/d' < "$1" | wc -l) ||
- exit
-test -z "$FAKE_LINES" && exit
-grep -v '^#' < "$1" > "$1".tmp
-rm -f "$1"
-cat "$1".tmp
-action=pick
-for line in $FAKE_LINES; do
- case $line in
- squash|edit)
- action="$line";;
- *)
- echo sed -n "${line}s/^pick/$action/p"
- sed -n "${line}p" < "$1".tmp
- sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
- action=pick;;
- esac
-done
-EOF
-
-chmod a+x fake-editor.sh
-VISUAL="$(pwd)/fake-editor.sh"
-export VISUAL
-
test_expect_success 'no changes are a nop' '
git rebase -i F &&
+ test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" &&
test $(git rev-parse I) = $(git rev-parse HEAD)
'
@@ -105,14 +76,26 @@ test_expect_success 'test the [branch] option' '
git rm file6 &&
git commit -m "stop here" &&
git rebase -i F branch2 &&
+ test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" &&
+ test $(git rev-parse I) = $(git rev-parse branch2) &&
test $(git rev-parse I) = $(git rev-parse HEAD)
'
+test_expect_success 'test --onto <branch>' '
+ git checkout -b test-onto branch2 &&
+ git rebase -i --onto branch1 F &&
+ test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-onto" &&
+ test $(git rev-parse HEAD^) = $(git rev-parse branch1) &&
+ test $(git rev-parse I) = $(git rev-parse branch2)
+'
+
test_expect_success 'rebase on top of a non-conflicting commit' '
git checkout branch1 &&
git tag original-branch1 &&
git rebase -i branch2 &&
test file6 = $(git diff --name-only original-branch1) &&
+ test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" &&
+ test $(git rev-parse I) = $(git rev-parse branch2) &&
test $(git rev-parse I) = $(git rev-parse HEAD~2)
'
@@ -136,26 +119,30 @@ index e69de29..00750ed 100644
EOF
cat > expect2 << EOF
-<<<<<<< HEAD:file1
+<<<<<<< HEAD
2
=======
3
->>>>>>> b7ca976... G:file1
+>>>>>>> b7ca976... G
EOF
test_expect_success 'stop on conflicting pick' '
git tag new-branch1 &&
- ! git rebase -i master &&
- test_cmp expect .git/.dotest-merge/patch &&
+ test_must_fail git rebase -i master &&
+ test "$(git rev-parse HEAD~3)" = "$(git rev-parse master)" &&
+ test_cmp expect .git/rebase-merge/patch &&
test_cmp expect2 file1 &&
- test 4 = $(grep -v "^#" < .git/.dotest-merge/done | wc -l) &&
- test 0 = $(grep -c "^[^#]" < .git/.dotest-merge/git-rebase-todo)
+ test "$(git diff --name-status |
+ sed -n -e "/^U/s/^U[^a-z]*//p")" = file1 &&
+ test 4 = $(grep -v "^#" < .git/rebase-merge/done | wc -l) &&
+ test 0 = $(grep -c "^[^#]" < .git/rebase-merge/git-rebase-todo)
'
test_expect_success 'abort' '
git rebase --abort &&
test $(git rev-parse new-branch1) = $(git rev-parse HEAD) &&
- ! test -d .git/.dotest-merge
+ test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" &&
+ ! test -d .git/rebase-merge
'
test_expect_success 'retain authorship' '
@@ -186,6 +173,9 @@ test_expect_success 'retain authorship when squashing' '
test_expect_success '-p handles "no changes" gracefully' '
HEAD=$(git rev-parse HEAD) &&
git rebase -i -p HEAD^ &&
+ git update-index --refresh &&
+ git diff-files --quiet &&
+ git diff-index --quiet --cached HEAD -- &&
test $HEAD = $(git rev-parse HEAD)
'
@@ -195,7 +185,7 @@ test_expect_success 'preserve merges with -p' '
git add unrelated-file &&
test_tick &&
git commit -m "unrelated" &&
- git checkout -b to-be-rebased master &&
+ git checkout -b another-branch master &&
echo B > file1 &&
test_tick &&
git commit -m J file1 &&
@@ -204,17 +194,48 @@ test_expect_success 'preserve merges with -p' '
echo C > file1 &&
test_tick &&
git commit -m K file1 &&
+ echo D > file1 &&
+ test_tick &&
+ git commit -m L1 file1 &&
+ git checkout HEAD^ &&
+ echo 1 > unrelated-file &&
+ test_tick &&
+ git commit -m L2 unrelated-file &&
+ test_tick &&
+ git merge another-branch &&
+ echo E > file1 &&
+ test_tick &&
+ git commit -m M file1 &&
+ git checkout -b to-be-rebased &&
test_tick &&
git rebase -i -p --onto branch1 master &&
- test $(git rev-parse HEAD^^2) = $(git rev-parse to-be-preserved) &&
- test $(git rev-parse HEAD~3) = $(git rev-parse branch1) &&
- test $(git show HEAD:file1) = C &&
- test $(git show HEAD~2:file1) = B
+ git update-index --refresh &&
+ git diff-files --quiet &&
+ git diff-index --quiet --cached HEAD -- &&
+ test $(git rev-parse HEAD~6) = $(git rev-parse branch1) &&
+ test $(git rev-parse HEAD~4^2) = $(git rev-parse to-be-preserved) &&
+ test $(git rev-parse HEAD^^2^) = $(git rev-parse HEAD^^^) &&
+ test $(git show HEAD~5:file1) = B &&
+ test $(git show HEAD~3:file1) = C &&
+ test $(git show HEAD:file1) = E &&
+ test $(git show HEAD:unrelated-file) = 1
+'
+
+test_expect_success 'edit ancestor with -p' '
+ FAKE_LINES="1 edit 2 3 4" git rebase -i -p HEAD~3 &&
+ echo 2 > unrelated-file &&
+ test_tick &&
+ git commit -m L2-modified --amend unrelated-file &&
+ git rebase --continue &&
+ git update-index --refresh &&
+ git diff-files --quiet &&
+ git diff-index --quiet --cached HEAD -- &&
+ test $(git show HEAD:unrelated-file) = 2
'
test_expect_success '--continue tries to commit' '
test_tick &&
- ! git rebase -i --onto new-branch1 HEAD^ &&
+ test_must_fail git rebase -i --onto new-branch1 HEAD^ &&
echo resolved > file1 &&
git add file1 &&
FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue &&
@@ -225,7 +246,7 @@ test_expect_success '--continue tries to commit' '
test_expect_success 'verbose flag is heeded, even after --continue' '
git reset --hard HEAD@{1} &&
test_tick &&
- ! git rebase -v -i --onto new-branch1 HEAD^ &&
+ test_must_fail git rebase -v -i --onto new-branch1 HEAD^ &&
echo resolved > file1 &&
git add file1 &&
git rebase --continue > output &&
@@ -260,10 +281,14 @@ test_expect_success 'interrupted squash works as expected' '
git commit -m $n
done &&
one=$(git rev-parse HEAD~3) &&
- ! FAKE_LINES="1 squash 3 2" git rebase -i HEAD~3 &&
+ (
+ FAKE_LINES="1 squash 3 2" &&
+ export FAKE_LINES &&
+ test_must_fail git rebase -i HEAD~3
+ ) &&
(echo one; echo two; echo four) > conflict &&
git add conflict &&
- ! git rebase --continue &&
+ test_must_fail git rebase --continue &&
echo resolved > conflict &&
git add conflict &&
git rebase --continue &&
@@ -278,13 +303,17 @@ test_expect_success 'interrupted squash works as expected (case 2)' '
git commit -m $n
done &&
one=$(git rev-parse HEAD~3) &&
- ! FAKE_LINES="3 squash 1 2" git rebase -i HEAD~3 &&
+ (
+ FAKE_LINES="3 squash 1 2" &&
+ export FAKE_LINES &&
+ test_must_fail git rebase -i HEAD~3
+ ) &&
(echo one; echo four) > conflict &&
git add conflict &&
- ! git rebase --continue &&
+ test_must_fail git rebase --continue &&
(echo one; echo two; echo four) > conflict &&
git add conflict &&
- ! git rebase --continue &&
+ test_must_fail git rebase --continue &&
echo resolved > conflict &&
git add conflict &&
git rebase --continue &&
@@ -315,6 +344,38 @@ test_expect_success '--continue tries to commit, even for "edit"' '
test $parent = $(git rev-parse HEAD^)
'
+test_expect_success 'aborted --continue does not squash commits after "edit"' '
+ old=$(git rev-parse HEAD) &&
+ test_tick &&
+ 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 $old = $(git rev-parse HEAD) &&
+ git rebase --abort
+'
+
+test_expect_success 'auto-amend only edited commits after "edit"' '
+ test_tick &&
+ FAKE_LINES="edit 1" git rebase -i HEAD^ &&
+ echo "edited again" > file7 &&
+ git add file7 &&
+ FAKE_COMMIT_MESSAGE="edited file7 again" git commit &&
+ echo "and again" > file7 &&
+ git add file7 &&
+ test_tick &&
+ (
+ FAKE_COMMIT_MESSAGE="and again" &&
+ export FAKE_COMMIT_MESSAGE &&
+ test_must_fail git rebase --continue
+ ) &&
+ git rebase --abort
+'
+
test_expect_success 'rebase a detached HEAD' '
grandparent=$(git rev-parse HEAD~2) &&
git checkout $(git rev-parse HEAD) &&
@@ -332,7 +393,7 @@ test_expect_success 'rebase a commit violating pre-commit' '
chmod a+x $PRE_COMMIT &&
echo "monde! " >> file1 &&
test_tick &&
- ! git commit -m doesnt-verify file1 &&
+ test_must_fail git commit -m doesnt-verify file1 &&
git commit -m doesnt-verify --no-verify file1 &&
test_tick &&
FAKE_LINES=2 git rebase -i HEAD~2
@@ -361,4 +422,66 @@ test_expect_success 'rebase with a file named HEAD in worktree' '
'
+test_expect_success 'do "noop" when there is nothing to cherry-pick' '
+
+ git checkout -b branch4 HEAD &&
+ GIT_EDITOR=: git commit --amend \
+ --author="Somebody else <somebody@else.com>"
+ test $(git rev-parse branch3) != $(git rev-parse branch4) &&
+ git rebase -i branch3 &&
+ test $(git rev-parse branch3) = $(git rev-parse branch4)
+
+'
+
+test_expect_success 'submodule rebase setup' '
+ git checkout A &&
+ mkdir sub &&
+ (
+ cd sub && git init && >elif &&
+ git add elif && git commit -m "submodule initial"
+ ) &&
+ echo 1 >file1 &&
+ git add file1 sub
+ test_tick &&
+ git commit -m "One" &&
+ echo 2 >file1 &&
+ test_tick &&
+ git commit -a -m "Two" &&
+ (
+ cd sub && echo 3 >elif &&
+ git commit -a -m "submodule second"
+ ) &&
+ test_tick &&
+ git commit -a -m "Three changes submodule"
+'
+
+test_expect_success 'submodule rebase -i' '
+ FAKE_LINES="1 squash 2 3" git rebase -i A
+'
+
+test_expect_success 'avoid unnecessary reset' '
+ git checkout master &&
+ test-chmtime =123456789 file3 &&
+ git update-index --refresh &&
+ HEAD=$(git rev-parse HEAD) &&
+ git rebase -i HEAD~4 &&
+ test $HEAD = $(git rev-parse HEAD) &&
+ MTIME=$(test-chmtime -v +0 file3 | sed 's/[^0-9].*$//') &&
+ test 123456789 = $MTIME
+'
+
+test_expect_success 'reword' '
+ git checkout -b reword-branch master &&
+ FAKE_LINES="1 2 3 reword 4" FAKE_COMMIT_MESSAGE="E changed" git rebase -i A &&
+ git show HEAD | grep "E changed" &&
+ test $(git rev-parse master) != $(git rev-parse HEAD) &&
+ test $(git rev-parse master^) = $(git rev-parse HEAD^) &&
+ FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" git rebase -i A &&
+ git show HEAD^ | grep "D changed" &&
+ FAKE_LINES="reword 1 2 3 4" FAKE_COMMIT_MESSAGE="B changed" git rebase -i A &&
+ git show HEAD~3 | grep "B changed" &&
+ FAKE_LINES="1 reword 2 3 4" FAKE_COMMIT_MESSAGE="C changed" git rebase -i A &&
+ git show HEAD~2 | grep "C changed"
+'
+
test_done
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index 5391080943..85fc7c4af8 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -22,7 +22,8 @@ test_expect_success setup '
git checkout topic &&
quick_one A &&
quick_one B &&
- quick_one Z
+ quick_one Z &&
+ git tag start
'
@@ -41,4 +42,24 @@ test_expect_success 'rebase -m' '
'
+test_expect_success 'rebase --stat' '
+ git reset --hard start
+ git rebase --stat master >diffstat.txt &&
+ grep "^ fileX | *1 +$" diffstat.txt
+'
+
+test_expect_success 'rebase w/config rebase.stat' '
+ git reset --hard start
+ git config rebase.stat true &&
+ git rebase master >diffstat.txt &&
+ grep "^ fileX | *1 +$" diffstat.txt
+'
+
+test_expect_success 'rebase -n overrides config rebase.stat config' '
+ git reset --hard start
+ git config rebase.stat true &&
+ git rebase -n master >diffstat.txt &&
+ ! grep "^ fileX | *1 +$" diffstat.txt
+'
+
test_done
diff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh
index 37944c39a3..2999e78937 100755
--- a/t/t3407-rebase-abort.sh
+++ b/t/t3407-rebase-abort.sh
@@ -4,7 +4,13 @@ test_description='git rebase --abort tests'
. ./test-lib.sh
+### Test that we handle space characters properly
+work_dir="$(pwd)/test dir"
+
test_expect_success setup '
+ mkdir -p "$work_dir" &&
+ cd "$work_dir" &&
+ git init &&
echo a > a &&
git add a &&
git commit -m a &&
@@ -28,32 +34,35 @@ testrebase() {
dotest=$2
test_expect_success "rebase$type --abort" '
+ cd "$work_dir" &&
# Clean up the state from the previous one
- git reset --hard pre-rebase
- test_must_fail git rebase'"$type"' master &&
- test -d '$dotest' &&
+ git reset --hard pre-rebase &&
+ test_must_fail git rebase$type master &&
+ test -d "$dotest" &&
git rebase --abort &&
test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
- test ! -d '$dotest'
+ test ! -d "$dotest"
'
test_expect_success "rebase$type --abort after --skip" '
+ cd "$work_dir" &&
# Clean up the state from the previous one
- git reset --hard pre-rebase
- test_must_fail git rebase'"$type"' master &&
- test -d '$dotest' &&
+ git reset --hard pre-rebase &&
+ test_must_fail git rebase$type master &&
+ test -d "$dotest" &&
test_must_fail git rebase --skip &&
test $(git rev-parse HEAD) = $(git rev-parse master) &&
- git-rebase --abort &&
+ git rebase --abort &&
test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
- test ! -d '$dotest'
+ test ! -d "$dotest"
'
test_expect_success "rebase$type --abort after --continue" '
+ cd "$work_dir" &&
# Clean up the state from the previous one
- git reset --hard pre-rebase
- test_must_fail git rebase'"$type"' master &&
- test -d '$dotest' &&
+ git reset --hard pre-rebase &&
+ test_must_fail git rebase$type master &&
+ test -d "$dotest" &&
echo c > a &&
echo d >> a &&
git add a &&
@@ -61,11 +70,11 @@ testrebase() {
test $(git rev-parse HEAD) != $(git rev-parse master) &&
git rebase --abort &&
test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
- test ! -d '$dotest'
+ test ! -d "$dotest"
'
}
-testrebase "" .dotest
-testrebase " --merge" .git/.dotest-merge
+testrebase "" .git/rebase-apply
+testrebase " --merge" .git/rebase-merge
test_done
diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh
new file mode 100755
index 0000000000..8f785e7957
--- /dev/null
+++ b/t/t3409-rebase-preserve-merges.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+#
+# Copyright(C) 2008 Stephen Habermann & Andreas Ericsson
+#
+test_description='git rebase -p should preserve merges
+
+Run "git rebase -p" and check that merges are properly carried along
+'
+. ./test-lib.sh
+
+GIT_AUTHOR_EMAIL=bogus_email_address
+export GIT_AUTHOR_EMAIL
+
+# Clone 1 (trivial merge):
+#
+# A1--A2 <-- origin/master
+# \ \
+# B1--M <-- topic
+# \
+# B2 <-- origin/topic
+#
+# Clone 2 (conflicting merge):
+#
+# A1--A2--B3 <-- origin/master
+# \ \
+# B1------M <-- topic
+# \
+# B2 <-- origin/topic
+#
+# In both cases, 'topic' is rebased onto 'origin/topic'.
+
+test_expect_success 'setup for merge-preserving rebase' \
+ 'echo First > A &&
+ git add A &&
+ git commit -m "Add A1" &&
+ git checkout -b topic &&
+ echo Second > B &&
+ git add B &&
+ git commit -m "Add B1" &&
+ git checkout -f master &&
+ echo Third >> A &&
+ git commit -a -m "Modify A2" &&
+
+ git clone ./. clone1 &&
+ cd clone1 &&
+ git checkout -b topic origin/topic &&
+ git merge origin/master &&
+ cd .. &&
+
+ echo Fifth > B &&
+ git add B &&
+ git commit -m "Add different B" &&
+
+ git clone ./. clone2 &&
+ cd clone2 &&
+ git checkout -b topic origin/topic &&
+ test_must_fail git merge origin/master &&
+ echo Resolved > B &&
+ git add B &&
+ git commit -m "Merge origin/master into topic" &&
+ cd .. &&
+
+ git checkout topic &&
+ echo Fourth >> B &&
+ git commit -a -m "Modify B2"
+'
+
+test_expect_success 'rebase -p fakes interactive rebase' '
+ (
+ cd clone1 &&
+ git fetch &&
+ git rebase -p origin/topic &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Merge remote branch " | wc -l)
+ )
+'
+
+test_expect_success '--continue works after a conflict' '
+ (
+ cd clone2 &&
+ git fetch &&
+ test_must_fail git rebase -p origin/topic &&
+ test 2 = $(git ls-files B | wc -l) &&
+ echo Resolved again > B &&
+ test_must_fail git rebase --continue &&
+ grep "^@@@ " .git/rebase-merge/patch &&
+ git add B &&
+ git rebase --continue &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Add different" | wc -l) &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Merge origin" | wc -l)
+ )
+'
+
+test_done
diff --git a/t/t3410-rebase-preserve-dropped-merges.sh b/t/t3410-rebase-preserve-dropped-merges.sh
new file mode 100755
index 0000000000..c49143a1a4
--- /dev/null
+++ b/t/t3410-rebase-preserve-dropped-merges.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Stephen Haberman
+#
+
+test_description='git rebase preserve merges
+
+This test runs git rebase with preserve merges and ensures commits
+dropped by the --cherry-pick flag have their childrens parents
+rewritten.
+'
+. ./test-lib.sh
+
+# set up two branches like this:
+#
+# A - B - C - D - E
+# \
+# F - G - H
+# \
+# I
+#
+# where B, D and G touch the same file.
+
+test_expect_success 'setup' '
+ test_commit A file1 &&
+ test_commit B file1 1 &&
+ test_commit C file2 &&
+ test_commit D file1 2 &&
+ test_commit E file3 &&
+ git checkout A &&
+ test_commit F file4 &&
+ test_commit G file1 3 &&
+ test_commit H file5 &&
+ git checkout F &&
+ test_commit I file6
+'
+
+# A - B - C - D - E
+# \ \ \
+# F - G - H -- L \ --> L
+# \ | \
+# I -- G2 -- J -- K I -- K
+# G2 = same changes as G
+test_expect_success 'skip same-resolution merges with -p' '
+ git checkout H &&
+ ! git merge E &&
+ test_commit L file1 23 &&
+ git checkout I &&
+ test_commit G2 file1 3 &&
+ ! git merge E &&
+ test_commit J file1 23 &&
+ test_commit K file7 file7 &&
+ git rebase -i -p L &&
+ test $(git rev-parse HEAD^^) = $(git rev-parse L) &&
+ test "23" = "$(cat file1)" &&
+ test "I" = "$(cat file6)" &&
+ test "file7" = "$(cat file7)"
+'
+
+# A - B - C - D - E
+# \ \ \
+# F - G - H -- L2 \ --> L2
+# \ | \
+# I -- G3 --- J2 -- K2 I -- G3 -- K2
+# G2 = different changes as G
+test_expect_success 'keep different-resolution merges with -p' '
+ git checkout H &&
+ ! git merge E &&
+ test_commit L2 file1 23 &&
+ git checkout I &&
+ test_commit G3 file1 4 &&
+ ! git merge E &&
+ test_commit J2 file1 24 &&
+ test_commit K2 file7 file7 &&
+ test_must_fail git rebase -i -p L2 &&
+ echo 234 > file1 &&
+ git add file1 &&
+ git rebase --continue &&
+ test $(git rev-parse HEAD^^^) = $(git rev-parse L2) &&
+ test "234" = "$(cat file1)" &&
+ test "I" = "$(cat file6)" &&
+ test "file7" = "$(cat file7)"
+'
+
+test_done
diff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh
new file mode 100755
index 0000000000..14a23cd872
--- /dev/null
+++ b/t/t3411-rebase-preserve-around-merges.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Stephen Haberman
+#
+
+test_description='git rebase preserve merges
+
+This test runs git rebase with -p and tries to squash a commit from after
+a merge to before the merge.
+'
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+set_fake_editor
+
+# set up two branches like this:
+#
+# A1 - B1 - D1 - E1 - F1
+# \ /
+# -- C1 --
+
+test_expect_success 'setup' '
+ test_commit A1 &&
+ test_commit B1 &&
+ test_commit C1 &&
+ git reset --hard B1 &&
+ test_commit D1 &&
+ test_merge E1 C1 &&
+ test_commit F1
+'
+
+# Should result in:
+#
+# A1 - B1 - D2 - E2
+# \ /
+# -- C1 --
+#
+test_expect_success 'squash F1 into D1' '
+ FAKE_LINES="1 squash 3 2" git rebase -i -p B1 &&
+ test "$(git rev-parse HEAD^2)" = "$(git rev-parse C1)" &&
+ test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" &&
+ git tag E2
+'
+
+# Start with:
+#
+# A1 - B1 - D2 - E2
+# \
+# G1 ---- L1 ---- M1
+# \ /
+# H1 -- J1 -- K1
+# \ /
+# -- I1 --
+#
+# And rebase G1..M1 onto E2
+
+test_expect_success 'rebase two levels of merge' '
+ test_commit G1 &&
+ test_commit H1 &&
+ test_commit I1 &&
+ git checkout -b branch3 H1 &&
+ test_commit J1 &&
+ test_merge K1 I1 &&
+ git checkout -b branch2 G1 &&
+ test_commit L1 &&
+ test_merge M1 K1 &&
+ GIT_EDITOR=: git rebase -i -p E2 &&
+ test "$(git rev-parse HEAD~3)" = "$(git rev-parse E2)" &&
+ test "$(git rev-parse HEAD~2)" = "$(git rev-parse HEAD^2^2~2)" &&
+ test "$(git rev-parse HEAD^2^1^1)" = "$(git rev-parse HEAD^2^2^1)"
+'
+
+test_done
diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh
new file mode 100755
index 0000000000..5869061c5b
--- /dev/null
+++ b/t/t3412-rebase-root.sh
@@ -0,0 +1,280 @@
+#!/bin/sh
+
+test_description='git rebase --root
+
+Tests if git rebase --root --onto <newparent> can rebase the root commit.
+'
+. ./test-lib.sh
+
+log_with_names () {
+ git rev-list --topo-order --parents --pretty="tformat:%s" HEAD |
+ git name-rev --stdin --name-only --refs=refs/heads/$1
+}
+
+
+test_expect_success 'prepare repository' '
+ test_commit 1 A &&
+ test_commit 2 A &&
+ git symbolic-ref HEAD refs/heads/other &&
+ rm .git/index &&
+ test_commit 3 B &&
+ test_commit 1b A 1 &&
+ test_commit 4 B
+'
+
+test_expect_success 'rebase --root expects --onto' '
+ test_must_fail git rebase --root
+'
+
+test_expect_success 'setup pre-rebase hook' '
+ mkdir -p .git/hooks &&
+ cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+echo "\$1,\$2" >.git/PRE-REBASE-INPUT
+EOF
+ chmod +x .git/hooks/pre-rebase
+'
+cat > expect <<EOF
+4
+3
+2
+1
+EOF
+
+test_expect_success 'rebase --root --onto <newbase>' '
+ git checkout -b work &&
+ git rebase --root --onto master &&
+ git log --pretty=tformat:"%s" > rebased &&
+ test_cmp expect rebased
+'
+
+test_expect_success 'pre-rebase got correct input (1)' '
+ test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,
+'
+
+test_expect_success 'rebase --root --onto <newbase> <branch>' '
+ git branch work2 other &&
+ git rebase --root --onto master work2 &&
+ git log --pretty=tformat:"%s" > rebased2 &&
+ test_cmp expect rebased2
+'
+
+test_expect_success 'pre-rebase got correct input (2)' '
+ test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work2
+'
+
+test_expect_success 'rebase -i --root --onto <newbase>' '
+ git checkout -b work3 other &&
+ git rebase -i --root --onto master &&
+ git log --pretty=tformat:"%s" > rebased3 &&
+ test_cmp expect rebased3
+'
+
+test_expect_success 'pre-rebase got correct input (3)' '
+ test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,
+'
+
+test_expect_success 'rebase -i --root --onto <newbase> <branch>' '
+ git branch work4 other &&
+ git rebase -i --root --onto master work4 &&
+ git log --pretty=tformat:"%s" > rebased4 &&
+ test_cmp expect rebased4
+'
+
+test_expect_success 'pre-rebase got correct input (4)' '
+ test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work4
+'
+
+test_expect_success 'rebase -i -p with linear history' '
+ git checkout -b work5 other &&
+ git rebase -i -p --root --onto master &&
+ git log --pretty=tformat:"%s" > rebased5 &&
+ test_cmp expect rebased5
+'
+
+test_expect_success 'pre-rebase got correct input (5)' '
+ test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,
+'
+
+test_expect_success 'set up merge history' '
+ git checkout other^ &&
+ git checkout -b side &&
+ test_commit 5 C &&
+ git checkout other &&
+ git merge side
+'
+
+cat > expect-side <<'EOF'
+commit work6 work6~1 work6^2
+Merge branch 'side' into other
+commit work6^2 work6~2
+5
+commit work6~1 work6~2
+4
+commit work6~2 work6~3
+3
+commit work6~3 work6~4
+2
+commit work6~4
+1
+EOF
+
+test_expect_success 'rebase -i -p with merge' '
+ git checkout -b work6 other &&
+ git rebase -i -p --root --onto master &&
+ log_with_names work6 > rebased6 &&
+ test_cmp expect-side rebased6
+'
+
+test_expect_success 'set up second root and merge' '
+ git symbolic-ref HEAD refs/heads/third &&
+ rm .git/index &&
+ rm A B C &&
+ test_commit 6 D &&
+ git checkout other &&
+ git merge third
+'
+
+cat > expect-third <<'EOF'
+commit work7 work7~1 work7^2
+Merge branch 'third' into other
+commit work7^2 work7~4
+6
+commit work7~1 work7~2 work7~1^2
+Merge branch 'side' into other
+commit work7~1^2 work7~3
+5
+commit work7~2 work7~3
+4
+commit work7~3 work7~4
+3
+commit work7~4 work7~5
+2
+commit work7~5
+1
+EOF
+
+test_expect_success 'rebase -i -p with two roots' '
+ git checkout -b work7 other &&
+ git rebase -i -p --root --onto master &&
+ log_with_names work7 > rebased7 &&
+ test_cmp expect-third rebased7
+'
+
+test_expect_success 'setup pre-rebase hook that fails' '
+ mkdir -p .git/hooks &&
+ cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+false
+EOF
+ chmod +x .git/hooks/pre-rebase
+'
+
+test_expect_success 'pre-rebase hook stops rebase' '
+ git checkout -b stops1 other &&
+ test_must_fail git rebase --root --onto master &&
+ test "z$(git symbolic-ref HEAD)" = zrefs/heads/stops1
+ test 0 = $(git rev-list other...stops1 | wc -l)
+'
+
+test_expect_success 'pre-rebase hook stops rebase -i' '
+ git checkout -b stops2 other &&
+ test_must_fail git rebase --root --onto master &&
+ test "z$(git symbolic-ref HEAD)" = zrefs/heads/stops2
+ test 0 = $(git rev-list other...stops2 | wc -l)
+'
+
+test_expect_success 'remove pre-rebase hook' '
+ rm -f .git/hooks/pre-rebase
+'
+
+test_expect_success 'set up a conflict' '
+ git checkout master &&
+ echo conflict > B &&
+ git add B &&
+ git commit -m conflict
+'
+
+test_expect_success 'rebase --root with conflict (first part)' '
+ git checkout -b conflict1 other &&
+ test_must_fail git rebase --root --onto master &&
+ git ls-files -u | grep "B$"
+'
+
+test_expect_success 'fix the conflict' '
+ echo 3 > B &&
+ git add B
+'
+
+cat > expect-conflict <<EOF
+6
+5
+4
+3
+conflict
+2
+1
+EOF
+
+test_expect_success 'rebase --root with conflict (second part)' '
+ git rebase --continue &&
+ git log --pretty=tformat:"%s" > conflict1 &&
+ test_cmp expect-conflict conflict1
+'
+
+test_expect_success 'rebase -i --root with conflict (first part)' '
+ git checkout -b conflict2 other &&
+ test_must_fail git rebase -i --root --onto master &&
+ git ls-files -u | grep "B$"
+'
+
+test_expect_success 'fix the conflict' '
+ echo 3 > B &&
+ git add B
+'
+
+test_expect_success 'rebase -i --root with conflict (second part)' '
+ git rebase --continue &&
+ git log --pretty=tformat:"%s" > conflict2 &&
+ test_cmp expect-conflict conflict2
+'
+
+cat >expect-conflict-p <<\EOF
+commit conflict3 conflict3~1 conflict3^2
+Merge branch 'third' into other
+commit conflict3^2 conflict3~4
+6
+commit conflict3~1 conflict3~2 conflict3~1^2
+Merge branch 'side' into other
+commit conflict3~1^2 conflict3~3
+5
+commit conflict3~2 conflict3~3
+4
+commit conflict3~3 conflict3~4
+3
+commit conflict3~4 conflict3~5
+conflict
+commit conflict3~5 conflict3~6
+2
+commit conflict3~6
+1
+EOF
+
+test_expect_success 'rebase -i -p --root with conflict (first part)' '
+ git checkout -b conflict3 other &&
+ test_must_fail git rebase -i -p --root --onto master &&
+ git ls-files -u | grep "B$"
+'
+
+test_expect_success 'fix the conflict' '
+ echo 3 > B &&
+ git add B
+'
+
+test_expect_success 'rebase -i -p --root with conflict (second part)' '
+ git rebase --continue &&
+ log_with_names conflict3 >out &&
+ test_cmp expect-conflict-p out
+'
+
+test_done
diff --git a/t/t3413-rebase-hook.sh b/t/t3413-rebase-hook.sh
new file mode 100755
index 0000000000..098b75507b
--- /dev/null
+++ b/t/t3413-rebase-hook.sh
@@ -0,0 +1,146 @@
+#!/bin/sh
+
+test_description='git rebase with its hook(s)'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo hello >file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ echo goodbye >file &&
+ git add file &&
+ test_tick &&
+ git commit -m second &&
+ git checkout -b side HEAD^ &&
+ echo world >git &&
+ git add git &&
+ test_tick &&
+ git commit -m side &&
+ git checkout master &&
+ git log --pretty=oneline --abbrev-commit --graph --all &&
+ git branch test side
+'
+
+test_expect_success 'rebase' '
+ git checkout test &&
+ git reset --hard side &&
+ git rebase master &&
+ test "z$(cat git)" = zworld
+'
+
+test_expect_success 'rebase -i' '
+ git checkout test &&
+ git reset --hard side &&
+ EDITOR=true git rebase -i master &&
+ test "z$(cat git)" = zworld
+'
+
+test_expect_success 'setup pre-rebase hook' '
+ mkdir -p .git/hooks &&
+ cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+echo "\$1,\$2" >.git/PRE-REBASE-INPUT
+EOF
+ chmod +x .git/hooks/pre-rebase
+'
+
+test_expect_success 'pre-rebase hook gets correct input (1)' '
+ git checkout test &&
+ git reset --hard side &&
+ git rebase master &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,
+
+'
+
+test_expect_success 'pre-rebase hook gets correct input (2)' '
+ git checkout test &&
+ git reset --hard side &&
+ git rebase master test &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'pre-rebase hook gets correct input (3)' '
+ git checkout test &&
+ git reset --hard side &&
+ git checkout master &&
+ git rebase master test &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'pre-rebase hook gets correct input (4)' '
+ git checkout test &&
+ git reset --hard side &&
+ EDITOR=true git rebase -i master &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,
+
+'
+
+test_expect_success 'pre-rebase hook gets correct input (5)' '
+ git checkout test &&
+ git reset --hard side &&
+ EDITOR=true git rebase -i master test &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'pre-rebase hook gets correct input (6)' '
+ git checkout test &&
+ git reset --hard side &&
+ git checkout master &&
+ EDITOR=true git rebase -i master test &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'setup pre-rebase hook that fails' '
+ mkdir -p .git/hooks &&
+ cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+false
+EOF
+ chmod +x .git/hooks/pre-rebase
+'
+
+test_expect_success 'pre-rebase hook stops rebase (1)' '
+ git checkout test &&
+ git reset --hard side &&
+ test_must_fail git rebase master &&
+ test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+ test 0 = $(git rev-list HEAD...side | wc -l)
+'
+
+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 "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+ test 0 = $(git rev-list HEAD...side | wc -l)
+'
+
+test_expect_success 'rebase --no-verify overrides pre-rebase (1)' '
+ git checkout test &&
+ git reset --hard side &&
+ git rebase --no-verify master &&
+ test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+ test "z$(cat git)" = zworld
+'
+
+test_expect_success 'rebase --no-verify overrides pre-rebase (2)' '
+ git checkout test &&
+ git reset --hard side &&
+ EDITOR=true git rebase --no-verify -i master &&
+ test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+ test "z$(cat git)" = zworld
+'
+
+test_done
diff --git a/t/t3414-rebase-preserve-onto.sh b/t/t3414-rebase-preserve-onto.sh
new file mode 100755
index 0000000000..ee0a6cccfd
--- /dev/null
+++ b/t/t3414-rebase-preserve-onto.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Greg Price
+#
+
+test_description='git rebase -p should respect --onto
+
+In a rebase with --onto, we should rewrite all the commits that
+aren'"'"'t on top of $ONTO, even if they are on top of $UPSTREAM.
+'
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+# Set up branches like this:
+# A1---B1---E1---F1---G1
+# \ \ /
+# \ \--C1---D1--/
+# H1
+
+test_expect_success 'setup' '
+ test_commit A1 &&
+ test_commit B1 &&
+ test_commit C1 &&
+ test_commit D1 &&
+ git reset --hard B1 &&
+ test_commit E1 &&
+ test_commit F1 &&
+ test_merge G1 D1 &&
+ git reset --hard A1 &&
+ test_commit H1
+'
+
+# Now rebase merge G1 from both branches' base B1, both should move:
+# A1---B1---E1---F1---G1
+# \ \ /
+# \ \--C1---D1--/
+# \
+# H1---E2---F2---G2
+# \ /
+# \--C2---D2--/
+
+test_expect_success 'rebase from B1 onto H1' '
+ git checkout G1 &&
+ git rebase -p --onto H1 B1 &&
+ test "$(git rev-parse HEAD^1^1^1)" = "$(git rev-parse H1)" &&
+ test "$(git rev-parse HEAD^2^1^1)" = "$(git rev-parse H1)"
+'
+
+# On the other hand if rebase from E1 which is within one branch,
+# then the other branch stays:
+# A1---B1---E1---F1---G1
+# \ \ /
+# \ \--C1---D1--/
+# \ \
+# H1-----F3-----G3
+
+test_expect_success 'rebase from E1 onto H1' '
+ git checkout G1 &&
+ git rebase -p --onto H1 E1 &&
+ test "$(git rev-parse HEAD^1^1)" = "$(git rev-parse H1)" &&
+ test "$(git rev-parse HEAD^2)" = "$(git rev-parse D1)"
+'
+
+# And the same if we rebase from a commit in the second-parent branch.
+# A1---B1---E1---F1----G1
+# \ \ \ /
+# \ \--C1---D1-\-/
+# \ \
+# H1------D3------G4
+
+test_expect_success 'rebase from C1 onto H1' '
+ git checkout G1 &&
+ git rev-list --first-parent --pretty=oneline C1..G1 &&
+ git rebase -p --onto H1 C1 &&
+ test "$(git rev-parse HEAD^2^1)" = "$(git rev-parse H1)" &&
+ test "$(git rev-parse HEAD^1)" = "$(git rev-parse F1)"
+'
+
+test_done
diff --git a/t/t3500-cherry.sh b/t/t3500-cherry.sh
index d0a440feba..dadbbc2a9f 100755
--- a/t/t3500-cherry.sh
+++ b/t/t3500-cherry.sh
@@ -10,31 +10,32 @@ checks that git cherry only returns the second patch in the local branch
'
. ./test-lib.sh
-export GIT_AUTHOR_EMAIL=bogus_email_address
+GIT_AUTHOR_EMAIL=bogus_email_address
+export GIT_AUTHOR_EMAIL
test_expect_success \
'prepare repository with topic branch, and check cherry finds the 2 patches from there' \
'echo First > A &&
git update-index --add A &&
- git-commit -m "Add A." &&
+ git commit -m "Add A." &&
- git-checkout -b my-topic-branch &&
+ git checkout -b my-topic-branch &&
echo Second > B &&
git update-index --add B &&
- git-commit -m "Add B." &&
+ git commit -m "Add B." &&
sleep 2 &&
echo AnotherSecond > C &&
git update-index --add C &&
- git-commit -m "Add C." &&
+ git commit -m "Add C." &&
- git-checkout -f master &&
+ git checkout -f master &&
rm -f B C &&
echo Third >> A &&
git update-index A &&
- git-commit -m "Modify A." &&
+ git commit -m "Modify A." &&
expr "$(echo $(git cherry master my-topic-branch) )" : "+ [^ ]* + .*"
'
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 6da212825a..bb4cf00d78 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -45,6 +45,7 @@ test_expect_success 'cherry-pick after renaming branch' '
git checkout rename2 &&
git cherry-pick added &&
+ test $(git rev-parse HEAD^) = $(git rev-parse rename2) &&
test -f opos &&
grep "Add extra line at the end" opos
@@ -54,6 +55,7 @@ test_expect_success 'revert after renaming branch' '
git checkout rename1 &&
git revert added &&
+ test $(git rev-parse HEAD^) = $(git rev-parse rename1) &&
test -f spoo &&
! grep "Add extra line at the end" spoo
diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh
index 7c92e261fc..0ab52da902 100755
--- a/t/t3502-cherry-pick-merge.sh
+++ b/t/t3502-cherry-pick-merge.sh
@@ -35,7 +35,7 @@ test_expect_success 'cherry-pick a non-merge with -m should fail' '
git reset --hard &&
git checkout a^0 &&
- ! git cherry-pick -m 1 b &&
+ test_must_fail git cherry-pick -m 1 b &&
git diff --exit-code a --
'
@@ -44,7 +44,7 @@ test_expect_success 'cherry pick a merge without -m should fail' '
git reset --hard &&
git checkout a^0 &&
- ! git cherry-pick c &&
+ test_must_fail git cherry-pick c &&
git diff --exit-code a --
'
@@ -71,7 +71,7 @@ test_expect_success 'cherry pick a merge relative to nonexistent parent should f
git reset --hard &&
git checkout b^0 &&
- ! git cherry-pick -m 3 c
+ test_must_fail git cherry-pick -m 3 c
'
@@ -79,7 +79,7 @@ test_expect_success 'revert a non-merge with -m should fail' '
git reset --hard &&
git checkout c^0 &&
- ! git revert -m 1 b &&
+ test_must_fail git revert -m 1 b &&
git diff --exit-code c
'
@@ -88,7 +88,7 @@ test_expect_success 'revert a merge without -m should fail' '
git reset --hard &&
git checkout c^0 &&
- ! git revert c &&
+ test_must_fail git revert c &&
git diff --exit-code c
'
@@ -115,7 +115,7 @@ test_expect_success 'revert a merge relative to nonexistent parent should fail'
git reset --hard &&
git checkout c^0 &&
- ! git revert -m 3 c &&
+ test_must_fail git revert -m 3 c &&
git diff --exit-code c
'
diff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh
new file mode 100755
index 0000000000..b0faa29918
--- /dev/null
+++ b/t/t3503-cherry-pick-root.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+test_description='test cherry-picking a root commit'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+ echo first > file1 &&
+ git add file1 &&
+ test_tick &&
+ git commit -m "first" &&
+
+ git symbolic-ref HEAD refs/heads/second &&
+ rm .git/index file1 &&
+ echo second > file2 &&
+ git add file2 &&
+ test_tick &&
+ git commit -m "second"
+
+'
+
+test_expect_success 'cherry-pick a root commit' '
+
+ git cherry-pick master &&
+ test first = $(cat file1)
+
+'
+
+test_done
diff --git a/t/t3504-cherry-pick-rerere.sh b/t/t3504-cherry-pick-rerere.sh
new file mode 100755
index 0000000000..f7b3518a32
--- /dev/null
+++ b/t/t3504-cherry-pick-rerere.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+test_description='cherry-pick should rerere for conflicts'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo foo >foo &&
+ git add foo && test_tick && git commit -q -m 1 &&
+ echo foo-master >foo &&
+ git add foo && test_tick && git commit -q -m 2 &&
+
+ git checkout -b dev HEAD^ &&
+ echo foo-dev >foo &&
+ git add foo && test_tick && git commit -q -m 3 &&
+ git config rerere.enabled true
+'
+
+test_expect_success 'conflicting merge' '
+ test_must_fail git merge master
+'
+
+test_expect_success 'fixup' '
+ echo foo-dev >foo &&
+ git add foo && test_tick && git commit -q -m 4 &&
+ git reset --hard HEAD^
+ echo foo-dev >expect
+'
+
+test_expect_success 'cherry-pick conflict' '
+ test_must_fail git cherry-pick master &&
+ test_cmp expect foo
+'
+
+test_expect_success 'reconfigure' '
+ git config rerere.enabled false
+ git reset --hard
+'
+
+test_expect_success 'cherry-pick conflict without rerere' '
+ test_must_fail git cherry-pick master &&
+ test_must_fail test_cmp expect foo
+'
+
+test_done
diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh
new file mode 100755
index 0000000000..e51e505a9f
--- /dev/null
+++ b/t/t3505-cherry-pick-empty.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+test_description='test cherry-picking an empty commit'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+ echo first > file1 &&
+ git add file1 &&
+ test_tick &&
+ git commit -m "first" &&
+
+ git checkout -b empty-branch &&
+ test_tick &&
+ git commit --allow-empty -m "empty"
+
+'
+
+test_expect_success 'cherry-pick an empty commit' '
+ git checkout master && {
+ git cherry-pick empty-branch
+ test "$?" = 1
+ }
+'
+
+test_expect_success 'index lockfile was removed' '
+
+ test ! -f .git/index.lock
+
+'
+
+test_done
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index f542f0af41..76b1bb4545 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -12,30 +12,37 @@ test_expect_success \
'Initialize test directory' \
"touch -- foo bar baz 'space embedded' -q &&
git add -- foo bar baz 'space embedded' -q &&
- git-commit -m 'add normal files' &&
- test_tabs=y &&
- if touch -- 'tab embedded' 'newline
-embedded'
- then
+ git commit -m 'add normal files'"
+
+if touch -- 'tab embedded' 'newline
+embedded' 2>/dev/null
+then
+ test_set_prereq FUNNYNAMES
+else
+ say 'Your filesystem does not allow tabs in filenames.'
+fi
+
+test_expect_success FUNNYNAMES 'add files with funny names' "
git add -- 'tab embedded' 'newline
embedded' &&
- git-commit -m 'add files with tabs and newlines'
- else
- say 'Your filesystem does not allow tabs in filenames.'
- test_tabs=n
- fi"
+ git commit -m 'add files with tabs and newlines'
+"
+# Determine rm behavior
# Later we will try removing an unremovable path to make sure
# git rm barfs, but if the test is run as root that cannot be
# arranged.
-test_expect_success \
- 'Determine rm behavior' \
- ': >test-file
- chmod a-w .
- rm -f test-file
- test -f test-file && test_failed_remove=y
- chmod 775 .
- rm -f test-file'
+: >test-file
+chmod a-w .
+rm -f test-file 2>/dev/null
+if test -f test-file
+then
+ test_set_prereq RO_DIR
+else
+ say 'skipping removal failure test (perhaps running as root?)'
+fi
+chmod 775 .
+rm -f test-file
test_expect_success \
'Pre-check that foo exists and is in index before git rm foo' \
@@ -67,7 +74,7 @@ test_expect_success \
echo "other content" > foo
git add foo
echo "yet another content" > foo
- ! git rm --cached foo
+ test_must_fail git rm --cached foo
'
test_expect_success \
@@ -82,7 +89,7 @@ test_expect_success \
test_expect_success \
'Post-check that foo exists but is not in index after git rm foo' \
- '[ -f foo ] && ! git ls-files --error-unmatch foo'
+ '[ -f foo ] && test_must_fail git ls-files --error-unmatch foo'
test_expect_success \
'Pre-check that bar exists and is in index before "git rm bar"' \
@@ -94,26 +101,22 @@ test_expect_success \
test_expect_success \
'Post-check that bar does not exist and is not in index after "git rm -f bar"' \
- '! [ -f bar ] && ! git ls-files --error-unmatch bar'
+ '! [ -f bar ] && test_must_fail git ls-files --error-unmatch bar'
test_expect_success \
'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' \
'git rm -- -q'
-test "$test_tabs" = y && test_expect_success \
+test_expect_success FUNNYNAMES \
"Test that \"git rm -f\" succeeds with embedded space, tab, or newline characters." \
"git rm -f 'space embedded' 'tab embedded' 'newline
embedded'"
-if test "$test_failed_remove" = y; then
-chmod a-w .
-test_expect_success \
- 'Test that "git rm -f" fails if its rm fails' \
- '! git rm -f baz'
-chmod 775 .
-else
- test_expect_success 'skipping removal failure (perhaps running as root?)' :
-fi
+test_expect_success RO_DIR 'Test that "git rm -f" fails if its rm fails' '
+ chmod a-w . &&
+ test_must_fail git rm -f baz &&
+ chmod 775 .
+'
test_expect_success \
'When the rm in "git rm -f" fails, it should not remove the file from the index' \
@@ -151,7 +154,7 @@ test_expect_success 'Re-add foo and baz' '
test_expect_success 'Modify foo -- rm should refuse' '
echo >>foo &&
- ! git rm foo baz &&
+ test_must_fail git rm foo baz &&
test -f foo &&
test -f baz &&
git ls-files --error-unmatch foo baz
@@ -161,8 +164,8 @@ test_expect_success 'Modified foo -- rm -f should work' '
git rm -f foo baz &&
test ! -f foo &&
test ! -f baz &&
- ! git ls-files --error-unmatch foo &&
- ! git ls-files --error-unmatch bar
+ test_must_fail git ls-files --error-unmatch foo &&
+ test_must_fail git ls-files --error-unmatch bar
'
test_expect_success 'Re-add foo and baz for HEAD tests' '
@@ -173,7 +176,7 @@ test_expect_success 'Re-add foo and baz for HEAD tests' '
'
test_expect_success 'foo is different in index from HEAD -- rm should refuse' '
- ! git rm foo baz &&
+ test_must_fail git rm foo baz &&
test -f foo &&
test -f baz &&
git ls-files --error-unmatch foo baz
@@ -183,8 +186,21 @@ test_expect_success 'but with -f it should work.' '
git rm -f foo baz &&
test ! -f foo &&
test ! -f baz &&
- ! git ls-files --error-unmatch foo
- ! git ls-files --error-unmatch baz
+ test_must_fail git ls-files --error-unmatch foo
+ test_must_fail git ls-files --error-unmatch baz
+'
+
+test_expect_success 'refuse to remove cached empty file with modifications' '
+ >empty &&
+ git add empty &&
+ echo content >empty &&
+ test_must_fail git rm --cached empty
+'
+
+test_expect_success 'remove intent-to-add file without --force' '
+ echo content >intent-to-add &&
+ git add -N intent-to-add
+ git rm --cached intent-to-add
'
test_expect_success 'Recursive test setup' '
@@ -195,14 +211,14 @@ test_expect_success 'Recursive test setup' '
'
test_expect_success 'Recursive without -r fails' '
- ! git rm frotz &&
+ test_must_fail git rm frotz &&
test -d frotz &&
test -f frotz/nitfol
'
test_expect_success 'Recursive with -r but dirty' '
echo qfwfq >>frotz/nitfol
- ! git rm -r frotz &&
+ test_must_fail git rm -r frotz &&
test -d frotz &&
test -f frotz/nitfol
'
@@ -214,7 +230,45 @@ test_expect_success 'Recursive with -r -f' '
'
test_expect_success 'Remove nonexistent file returns nonzero exit status' '
- ! git rm nonexistent
+ test_must_fail git rm nonexistent
+'
+
+test_expect_success 'Call "rm" from outside the work tree' '
+ mkdir repo &&
+ (cd repo &&
+ git init &&
+ echo something > somefile &&
+ git add somefile &&
+ git commit -m "add a file" &&
+ (cd .. &&
+ git --git-dir=repo/.git --work-tree=repo rm somefile) &&
+ test_must_fail git ls-files --error-unmatch somefile)
+'
+
+test_expect_success 'refresh index before checking if it is up-to-date' '
+
+ git reset --hard &&
+ test-chmtime -86400 frotz/nitfol &&
+ git rm frotz/nitfol &&
+ test ! -f frotz/nitfol
+
+'
+
+test_expect_success 'choking "git rm" should not let it die with cruft' '
+ git reset -q --hard &&
+ H=0000000000000000000000000000000000000000 &&
+ i=0 &&
+ while test $i -lt 12000
+ do
+ echo "100644 $H 0 some-file-$i"
+ i=$(( $i + 1 ))
+ done | git update-index --index-info &&
+ git rm -n "some-file-*" | :;
+ test -f .git/index.lock
+ status=$?
+ rm -f .git/index.lock
+ git reset -q --hard
+ test "$status" != 0
'
test_done
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 287e058e37..85eb0fbf96 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -30,7 +30,7 @@ test_expect_success \
*) echo fail; git ls-files --stage xfoo1; (exit 1);;
esac'
-test_expect_success 'git add: filemode=0 should not get confused by symlink' '
+test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' '
rm -f xfoo1 &&
ln -s foo xfoo1 &&
git add xfoo1 &&
@@ -51,7 +51,7 @@ test_expect_success \
*) echo fail; git ls-files --stage xfoo2; (exit 1);;
esac'
-test_expect_success 'git add: filemode=0 should not get confused by symlink' '
+test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' '
rm -f xfoo2 &&
ln -s foo xfoo2 &&
git update-index --add xfoo2 &&
@@ -61,7 +61,7 @@ test_expect_success 'git add: filemode=0 should not get confused by symlink' '
esac
'
-test_expect_success \
+test_expect_success SYMLINKS \
'git update-index --add: Test that executable bit is not used...' \
'git config core.filemode 0 &&
ln -s xfoo2 xfoo3 &&
@@ -81,17 +81,17 @@ test_expect_success '.gitignore test setup' '
test_expect_success '.gitignore is honored' '
git add . &&
- ! git ls-files | grep "\\.ig"
+ ! (git ls-files | grep "\\.ig")
'
test_expect_success 'error out when attempting to add ignored ones without -f' '
- ! git add a.?? &&
- ! git ls-files | grep "\\.ig"
+ test_must_fail git add a.?? &&
+ ! (git ls-files | grep "\\.ig")
'
test_expect_success 'error out when attempting to add ignored ones without -f' '
- ! git add d.?? &&
- ! git ls-files | grep "\\.ig"
+ test_must_fail git add d.?? &&
+ ! (git ls-files | grep "\\.ig")
'
test_expect_success 'add ignored ones with -f' '
@@ -179,4 +179,80 @@ test_expect_success 'git add --refresh' '
test -z "`git diff-index HEAD -- foo`"
'
+test_expect_success POSIXPERM 'git add should fail atomically upon an unreadable file' '
+ git reset --hard &&
+ date >foo1 &&
+ date >foo2 &&
+ chmod 0 foo2 &&
+ test_must_fail git add --verbose . &&
+ ! ( git ls-files foo1 | grep foo1 )
+'
+
+rm -f foo2
+
+test_expect_success POSIXPERM 'git add --ignore-errors' '
+ git reset --hard &&
+ date >foo1 &&
+ date >foo2 &&
+ chmod 0 foo2 &&
+ test_must_fail git add --verbose --ignore-errors . &&
+ git ls-files foo1 | grep foo1
+'
+
+rm -f foo2
+
+test_expect_success POSIXPERM 'git add (add.ignore-errors)' '
+ git config add.ignore-errors 1 &&
+ git reset --hard &&
+ date >foo1 &&
+ date >foo2 &&
+ chmod 0 foo2 &&
+ test_must_fail git add --verbose . &&
+ git ls-files foo1 | grep foo1
+'
+rm -f foo2
+
+test_expect_success POSIXPERM 'git add (add.ignore-errors = false)' '
+ git config add.ignore-errors 0 &&
+ git reset --hard &&
+ date >foo1 &&
+ date >foo2 &&
+ chmod 0 foo2 &&
+ test_must_fail git add --verbose . &&
+ ! ( git ls-files foo1 | grep foo1 )
+'
+rm -f foo2
+
+test_expect_success POSIXPERM '--no-ignore-errors overrides config' '
+ git config add.ignore-errors 1 &&
+ git reset --hard &&
+ date >foo1 &&
+ date >foo2 &&
+ chmod 0 foo2 &&
+ test_must_fail git add --verbose --no-ignore-errors . &&
+ ! ( git ls-files foo1 | grep foo1 ) &&
+ git config add.ignore-errors 0
+'
+rm -f foo2
+
+test_expect_success BSLASHPSPEC "git add 'fo\\[ou\\]bar' ignores foobar" '
+ git reset --hard &&
+ touch fo\[ou\]bar foobar &&
+ git add '\''fo\[ou\]bar'\'' &&
+ git ls-files fo\[ou\]bar | fgrep fo\[ou\]bar &&
+ ! ( git ls-files foobar | grep foobar )
+'
+
+test_expect_success 'git add to resolve conflicts on otherwise ignored path' '
+ git reset --hard &&
+ H=$(git rev-parse :1/2/a) &&
+ (
+ echo "100644 $H 1 track-this"
+ echo "100644 $H 3 track-this"
+ ) | git update-index --index-info &&
+ echo track-this >>.gitignore &&
+ echo resolved >track-this &&
+ git add track-this
+'
+
test_done
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index f15be93e77..b6eba6a839 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -3,6 +3,11 @@
test_description='add -i basic tests'
. ./test-lib.sh
+if ! test_have_prereq PERL; then
+ say 'skipping git add -i tests, perl not available'
+ test_done
+fi
+
test_expect_success 'setup (initial)' '
echo content >file &&
git add file &&
@@ -66,7 +71,95 @@ test_expect_success 'revert works (commit)' '
grep "unchanged *+3/-0 file" output
'
-test_expect_success 'patch does not affect mode' '
+cat >expected <<EOF
+EOF
+cat >fake_editor.sh <<EOF
+EOF
+chmod a+x fake_editor.sh
+test_set_editor "$(pwd)/fake_editor.sh"
+test_expect_success 'dummy edit works' '
+ (echo e; echo a) | git add -p &&
+ git diff > diff &&
+ test_cmp expected diff
+'
+
+cat >patch <<EOF
+@@ -1,1 +1,4 @@
+ this
++patch
+-doesn't
+ apply
+EOF
+echo "#!$SHELL_PATH" >fake_editor.sh
+cat >>fake_editor.sh <<\EOF
+mv -f "$1" oldpatch &&
+mv -f patch "$1"
+EOF
+chmod a+x fake_editor.sh
+test_set_editor "$(pwd)/fake_editor.sh"
+test_expect_success 'bad edit rejected' '
+ git reset &&
+ (echo e; echo n; echo d) | git add -p >output &&
+ grep "hunk does not apply" output
+'
+
+cat >patch <<EOF
+this patch
+is garbage
+EOF
+test_expect_success 'garbage edit rejected' '
+ git reset &&
+ (echo e; echo n; echo d) | git add -p >output &&
+ grep "hunk does not apply" output
+'
+
+cat >patch <<EOF
+@@ -1,0 +1,0 @@
+ baseline
++content
++newcontent
++lines
+EOF
+cat >expected <<EOF
+diff --git a/file b/file
+index b5dd6c9..f910ae9 100644
+--- a/file
++++ b/file
+@@ -1,4 +1,4 @@
+ baseline
+ content
+-newcontent
++more
+ lines
+EOF
+test_expect_success 'real edit works' '
+ (echo e; echo n; echo d) | git add -p &&
+ git diff >output &&
+ test_cmp expected output
+'
+
+test_expect_success 'skip files similarly as commit -a' '
+ git reset &&
+ echo file >.gitignore &&
+ echo changed >file &&
+ echo y | git add -p file &&
+ git diff >output &&
+ git reset &&
+ git commit -am commit &&
+ git diff >expected &&
+ test_cmp expected output &&
+ git reset --hard HEAD^
+'
+rm -f .gitignore
+
+if test "$(git config --bool core.filemode)" = false
+then
+ say 'skipping filemode tests (filesystem does not properly support modes)'
+else
+ test_set_prereq FILEMODE
+fi
+
+test_expect_success FILEMODE 'patch does not affect mode' '
git reset --hard &&
echo content >>file &&
chmod +x file &&
@@ -75,7 +168,7 @@ test_expect_success 'patch does not affect mode' '
git diff file | grep "new mode"
'
-test_expect_success 'stage mode but not hunk' '
+test_expect_success FILEMODE 'stage mode but not hunk' '
git reset --hard &&
echo content >>file &&
chmod +x file &&
@@ -85,4 +178,91 @@ test_expect_success 'stage mode but not hunk' '
'
+test_expect_success FILEMODE 'stage mode and hunk' '
+ git reset --hard &&
+ echo content >>file &&
+ chmod +x file &&
+ printf "y\\ny\\n" | git add -p &&
+ git diff --cached file | grep "new mode" &&
+ git diff --cached file | grep "+content" &&
+ test -z "$(git diff file)"
+'
+
+# end of tests disabled when filemode is not usable
+
+test_expect_success 'setup again' '
+ git reset --hard &&
+ test_chmod +x file &&
+ echo content >>file
+'
+
+# Write the patch file with a new line at the top and bottom
+cat >patch <<EOF
+index 180b47c..b6f2c08 100644
+--- a/file
++++ b/file
+@@ -1,2 +1,4 @@
++firstline
+ baseline
+ content
++lastline
+EOF
+# Expected output, similar to the patch but w/ diff at the top
+cat >expected <<EOF
+diff --git a/file b/file
+index b6f2c08..61b9053 100755
+--- a/file
++++ b/file
+@@ -1,2 +1,4 @@
++firstline
+ baseline
+ content
++lastline
+EOF
+# Test splitting the first patch, then adding both
+test_expect_success 'add first line works' '
+ git commit -am "clear local changes" &&
+ git apply patch &&
+ (echo s; echo y; echo y) | git add -p file &&
+ git diff --cached > diff &&
+ test_cmp expected diff
+'
+
+cat >expected <<EOF
+diff --git a/non-empty b/non-empty
+deleted file mode 100644
+index d95f3ad..0000000
+--- a/non-empty
++++ /dev/null
+@@ -1 +0,0 @@
+-content
+EOF
+test_expect_success 'deleting a non-empty file' '
+ git reset --hard &&
+ echo content >non-empty &&
+ git add non-empty &&
+ git commit -m non-empty &&
+ rm non-empty &&
+ echo y | git add -p non-empty &&
+ git diff --cached >diff &&
+ test_cmp expected diff
+'
+
+cat >expected <<EOF
+diff --git a/empty b/empty
+deleted file mode 100644
+index e69de29..0000000
+EOF
+
+test_expect_success 'deleting an empty file' '
+ git reset --hard &&
+ > empty &&
+ git add empty &&
+ git commit -m empty &&
+ rm empty &&
+ echo y | git add -p empty &&
+ git diff --cached >diff &&
+ test_cmp expected diff
+'
+
test_done
diff --git a/t/t3702-add-edit.sh b/t/t3702-add-edit.sh
new file mode 100755
index 0000000000..4ee47cc9a8
--- /dev/null
+++ b/t/t3702-add-edit.sh
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='add -e basic tests'
+. ./test-lib.sh
+
+
+cat > file << EOF
+LO, praise of the prowess of people-kings
+of spear-armed Danes, in days long sped,
+we have heard, and what honor the athelings won!
+Oft Scyld the Scefing from squadroned foes,
+from many a tribe, the mead-bench tore,
+awing the earls. Since erst he lay
+friendless, a foundling, fate repaid him:
+for he waxed under welkin, in wealth he throve,
+till before him the folk, both far and near,
+who house by the whale-path, heard his mandate,
+gave him gifts: a good king he!
+EOF
+
+cat > second-part << EOF
+To him an heir was afterward born,
+a son in his halls, whom heaven sent
+to favor the folk, feeling their woe
+that erst they had lacked an earl for leader
+so long a while; the Lord endowed him,
+the Wielder of Wonder, with world's renown.
+EOF
+
+test_expect_success 'setup' '
+
+ git add file &&
+ test_tick &&
+ git commit -m initial file
+
+'
+
+cat > expected-patch << EOF
+diff --git a/file b/file
+index b9834b5..9020acb 100644
+--- a/file
++++ b/file
+@@ -1,11 +1,6 @@
+-LO, praise of the prowess of people-kings
+-of spear-armed Danes, in days long sped,
+-we have heard, and what honor the athelings won!
+-Oft Scyld the Scefing from squadroned foes,
+-from many a tribe, the mead-bench tore,
+-awing the earls. Since erst he lay
+-friendless, a foundling, fate repaid him:
+-for he waxed under welkin, in wealth he throve,
+-till before him the folk, both far and near,
+-who house by the whale-path, heard his mandate,
+-gave him gifts: a good king he!
++To him an heir was afterward born,
++a son in his halls, whom heaven sent
++to favor the folk, feeling their woe
++that erst they had lacked an earl for leader
++so long a while; the Lord endowed him,
++the Wielder of Wonder, with world's renown.
+EOF
+
+cat > patch << EOF
+diff --git a/file b/file
+index b9834b5..ef6e94c 100644
+--- a/file
++++ b/file
+@@ -3,1 +3,333 @@ of spear-armed Danes, in days long sped,
+ we have heard, and what honor the athelings won!
++
+ Oft Scyld the Scefing from squadroned foes,
+@@ -2,7 +1,5 @@ awing the earls. Since erst he lay
+ friendless, a foundling, fate repaid him:
++
+ for he waxed under welkin, in wealth he throve,
+EOF
+
+cat > expected << EOF
+diff --git a/file b/file
+index b9834b5..ef6e94c 100644
+--- a/file
++++ b/file
+@@ -1,10 +1,12 @@
+ LO, praise of the prowess of people-kings
+ of spear-armed Danes, in days long sped,
+ we have heard, and what honor the athelings won!
++
+ Oft Scyld the Scefing from squadroned foes,
+ from many a tribe, the mead-bench tore,
+ awing the earls. Since erst he lay
+ friendless, a foundling, fate repaid him:
++
+ for he waxed under welkin, in wealth he throve,
+ till before him the folk, both far and near,
+ who house by the whale-path, heard his mandate,
+EOF
+
+echo "#!$SHELL_PATH" >fake-editor.sh
+cat >> fake-editor.sh <<\EOF
+mv -f "$1" orig-patch &&
+mv -f patch "$1"
+EOF
+
+test_set_editor "$(pwd)/fake-editor.sh"
+chmod a+x fake-editor.sh
+
+test_expect_success 'add -e' '
+
+ cp second-part file &&
+ git add -e &&
+ test_cmp second-part file &&
+ test_cmp orig-patch expected-patch &&
+ git diff --cached > out &&
+ test_cmp out expected
+
+'
+
+test_done
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index df1fd6f86f..6fb027ba57 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -2,7 +2,7 @@
#
#
-test_description='git-mktag: tag object verify test'
+test_description='git mktag: tag object verify test'
. ./test-lib.sh
@@ -14,7 +14,7 @@ test_description='git-mktag: tag object verify test'
check_verify_failure () {
expect="$2"
test_expect_success "$1" '
- ( test_must_fail git-mktag <tag.sig 2>message ) &&
+ ( test_must_fail git mktag <tag.sig 2>message ) &&
grep "$expect" message
'
}
@@ -24,7 +24,7 @@ check_verify_failure () {
# for the tag.
echo Hello >A
git update-index --add A
-git-commit -m "Initial commit"
+git commit -m "Initial commit"
head=$(git rev-parse --verify HEAD)
############################################################
@@ -222,7 +222,7 @@ EOF
test_expect_success \
'allow empty tag email' \
- 'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
+ 'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
############################################################
# 16. disallow spaces in tag email
@@ -241,11 +241,11 @@ check_verify_failure 'disallow spaces in tag email' \
############################################################
# 17. disallow missing tag timestamp
-cat >tag.sig <<EOF
+tr '_' ' ' >tag.sig <<EOF
object $head
type commit
tag mytag
-tagger T A Gger <tagger@example.com>
+tagger T A Gger <tagger@example.com>__
EOF
@@ -350,14 +350,14 @@ EOF
test_expect_success \
'create valid tag' \
- 'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
+ 'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
############################################################
# 25. check mytag
test_expect_success \
'check mytag' \
- 'git-tag -l | grep mytag'
+ 'git tag -l | grep mytag'
test_done
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index 94b1c24b0a..256c4c9701 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -9,16 +9,24 @@ test_description='commit and log output encodings'
compare_with () {
git show -s $1 | sed -e '1,/^$/d' -e 's/^ //' >current &&
- git diff current "$2"
+ case "$3" in
+ '')
+ test_cmp "$2" current ;;
+ ?*)
+ iconv -f "$3" -t UTF-8 >current.utf8 <current &&
+ iconv -f "$3" -t UTF-8 >expect.utf8 <"$2" &&
+ test_cmp expect.utf8 current.utf8
+ ;;
+ esac
}
test_expect_success setup '
: >F &&
git add F &&
T=$(git write-tree) &&
- C=$(git commit-tree $T <../t3900/1-UTF-8.txt) &&
+ C=$(git commit-tree $T <"$TEST_DIRECTORY"/t3900/1-UTF-8.txt) &&
git update-ref HEAD $C &&
- git-tag C0
+ git tag C0
'
test_expect_success 'no encoding header for base case' '
@@ -26,17 +34,17 @@ test_expect_success 'no encoding header for base case' '
test z = "z$E"
'
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
do
test_expect_success "$H setup" '
git config i18n.commitencoding $H &&
- git-checkout -b $H C0 &&
+ git checkout -b $H C0 &&
echo $H >F &&
- git-commit -a -F ../t3900/$H.txt
+ git commit -a -F "$TEST_DIRECTORY"/t3900/$H.txt
'
done
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
do
test_expect_success "check encoding header for $H" '
E=$(git cat-file commit '$H' | sed -ne "s/^encoding //p") &&
@@ -53,17 +61,17 @@ test_expect_success 'config to remove customization' '
else
test z = "z$Z"
fi &&
- git config i18n.commitencoding utf-8
+ git config i18n.commitencoding UTF-8
'
-test_expect_success 'ISO-8859-1 should be shown in UTF-8 now' '
- compare_with ISO-8859-1 ../t3900/1-UTF-8.txt
+test_expect_success 'ISO8859-1 should be shown in UTF-8 now' '
+ compare_with ISO8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
'
-for H in EUCJP ISO-2022-JP
+for H in eucJP ISO-2022-JP
do
test_expect_success "$H should be shown in UTF-8 now" '
- compare_with '$H' ../t3900/2-UTF-8.txt
+ compare_with '$H' "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
'
done
@@ -78,44 +86,50 @@ test_expect_success 'config to add customization' '
fi
'
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
do
test_expect_success "$H should be shown in itself now" '
git config i18n.commitencoding '$H' &&
- compare_with '$H' ../t3900/'$H'.txt
+ compare_with '$H' "$TEST_DIRECTORY"/t3900/'$H'.txt
'
done
test_expect_success 'config to tweak customization' '
- git config i18n.logoutputencoding utf-8
+ git config i18n.logoutputencoding UTF-8
'
-test_expect_success 'ISO-8859-1 should be shown in UTF-8 now' '
- compare_with ISO-8859-1 ../t3900/1-UTF-8.txt
+test_expect_success 'ISO8859-1 should be shown in UTF-8 now' '
+ compare_with ISO8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
'
-for H in EUCJP ISO-2022-JP
+for H in eucJP ISO-2022-JP
do
test_expect_success "$H should be shown in UTF-8 now" '
- compare_with '$H' ../t3900/2-UTF-8.txt
+ compare_with '$H' "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
'
done
-for J in EUCJP ISO-2022-JP
+for J in eucJP ISO-2022-JP
do
+ if test "$J" = ISO-2022-JP
+ then
+ ICONV=$J
+ else
+ ICONV=
+ fi
git config i18n.logoutputencoding $J
- for H in EUCJP ISO-2022-JP
+ for H in eucJP ISO-2022-JP
do
test_expect_success "$H should be shown in $J now" '
- compare_with '$H' ../t3900/'$J'.txt
+ compare_with '$H' "$TEST_DIRECTORY"/t3900/'$J'.txt $ICONV
'
done
done
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
do
test_expect_success "No conversion with $H" '
- compare_with "--encoding=none '$H'" ../t3900/'$H'.txt
+ compare_with "--encoding=none '$H'" "$TEST_DIRECTORY"/t3900/'$H'.txt
'
done
diff --git a/t/t3900/ISO-8859-1.txt b/t/t3900/ISO8859-1.txt
index 7cbef0ee6f..7cbef0ee6f 100644
--- a/t/t3900/ISO-8859-1.txt
+++ b/t/t3900/ISO8859-1.txt
diff --git a/t/t3900/EUCJP.txt b/t/t3900/eucJP.txt
index 546f2aac01..546f2aac01 100644
--- a/t/t3900/EUCJP.txt
+++ b/t/t3900/eucJP.txt
diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh
index 235f372832..31a5770b34 100755
--- a/t/t3901-i18n-patch.sh
+++ b/t/t3901-i18n-patch.sh
@@ -17,9 +17,9 @@ check_encoding () {
git cat-file commit HEAD~$j |
case "$header" in
8859)
- grep "^encoding ISO-8859-1" ;;
+ grep "^encoding ISO8859-1" ;;
*)
- ! grep "^encoding ISO-8859-1" ;;
+ grep "^encoding ISO8859-1"; test "$?" != 0 ;;
esac || {
bad=1
break
@@ -35,7 +35,7 @@ test_expect_success setup '
# use UTF-8 in author and committer name to match the
# i18n.commitencoding settings
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
test_tick &&
echo "$GIT_AUTHOR_NAME" >mine &&
@@ -55,9 +55,9 @@ test_expect_success setup '
git commit -s -m "Second on side" &&
# the second one on the side branch is ISO-8859-1
- git config i18n.commitencoding ISO-8859-1 &&
+ git config i18n.commitencoding ISO8859-1 &&
# use author and committer name in ISO-8859-1 to match it.
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
test_tick &&
echo Yet another >theirs &&
git add theirs &&
@@ -68,14 +68,14 @@ test_expect_success setup '
'
test_expect_success 'format-patch output (ISO-8859-1)' '
- git config i18n.logoutputencoding ISO-8859-1 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
git format-patch --stdout master..HEAD^ >out-l1 &&
git format-patch --stdout HEAD^ >out-l2 &&
- grep "^Content-Type: text/plain; charset=ISO-8859-1" out-l1 &&
- grep "^From: =?ISO-8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l1 &&
- grep "^Content-Type: text/plain; charset=ISO-8859-1" out-l2 &&
- grep "^From: =?ISO-8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l2
+ grep "^Content-Type: text/plain; charset=ISO8859-1" out-l1 &&
+ grep "^From: =?ISO8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l1 &&
+ grep "^Content-Type: text/plain; charset=ISO8859-1" out-l2 &&
+ grep "^From: =?ISO8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l2
'
test_expect_success 'format-patch output (UTF-8)' '
@@ -101,32 +101,32 @@ test_expect_success 'rebase (U/U)' '
# The result will be committed by GIT_COMMITTER_NAME --
# we want UTF-8 encoded name.
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git checkout -b test &&
- git-rebase master &&
+ git rebase master &&
check_encoding 2
'
test_expect_success 'rebase (U/L)' '
git config i18n.commitencoding UTF-8 &&
- git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-utf8.txt &&
+ git config i18n.logoutputencoding ISO8859-1 &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard side &&
- git-rebase master &&
+ git rebase master &&
check_encoding 2
'
test_expect_success 'rebase (L/L)' '
# In this test we want ISO-8859-1 encoded commits as the result
- git config i18n.commitencoding ISO-8859-1 &&
- git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-8859-1.txt &&
+ git config i18n.commitencoding ISO8859-1 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
- git-rebase master &&
+ git rebase master &&
check_encoding 2 8859
'
@@ -134,12 +134,12 @@ test_expect_success 'rebase (L/L)' '
test_expect_success 'rebase (L/U)' '
# This is pathological -- use UTF-8 as intermediate form
# to get ISO-8859-1 results.
- git config i18n.commitencoding ISO-8859-1 &&
+ git config i18n.commitencoding ISO8859-1 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
- git-rebase master &&
+ git rebase master &&
check_encoding 2 8859
'
@@ -149,7 +149,7 @@ test_expect_success 'cherry-pick(U/U)' '
git config i18n.commitencoding UTF-8 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard master &&
git cherry-pick side^ &&
@@ -162,9 +162,9 @@ test_expect_success 'cherry-pick(U/U)' '
test_expect_success 'cherry-pick(L/L)' '
# Both the commitencoding and logoutputencoding is set to ISO-8859-1
- git config i18n.commitencoding ISO-8859-1 &&
- git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-8859-1.txt &&
+ git config i18n.commitencoding ISO8859-1 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard master &&
git cherry-pick side^ &&
@@ -178,8 +178,8 @@ test_expect_success 'cherry-pick(U/L)' '
# Commitencoding is set to UTF-8 but logoutputencoding is ISO-8859-1
git config i18n.commitencoding UTF-8 &&
- git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-utf8.txt &&
+ git config i18n.logoutputencoding ISO8859-1 &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard master &&
git cherry-pick side^ &&
@@ -193,9 +193,9 @@ test_expect_success 'cherry-pick(L/U)' '
# Again, the commitencoding is set to ISO-8859-1 but
# logoutputencoding is set to UTF-8.
- git config i18n.commitencoding ISO-8859-1 &&
+ git config i18n.commitencoding ISO8859-1 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard master &&
git cherry-pick side^ &&
@@ -208,33 +208,33 @@ test_expect_success 'cherry-pick(L/U)' '
test_expect_success 'rebase --merge (U/U)' '
git config i18n.commitencoding UTF-8 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard side &&
- git-rebase --merge master &&
+ git rebase --merge master &&
check_encoding 2
'
test_expect_success 'rebase --merge (U/L)' '
git config i18n.commitencoding UTF-8 &&
- git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-utf8.txt &&
+ git config i18n.logoutputencoding ISO8859-1 &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard side &&
- git-rebase --merge master &&
+ git rebase --merge master &&
check_encoding 2
'
test_expect_success 'rebase --merge (L/L)' '
# In this test we want ISO-8859-1 encoded commits as the result
- git config i18n.commitencoding ISO-8859-1 &&
- git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-8859-1.txt &&
+ git config i18n.commitencoding ISO8859-1 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
- git-rebase --merge master &&
+ git rebase --merge master &&
check_encoding 2 8859
'
@@ -242,12 +242,12 @@ test_expect_success 'rebase --merge (L/L)' '
test_expect_success 'rebase --merge (L/U)' '
# This is pathological -- use UTF-8 as intermediate form
# to get ISO-8859-1 results.
- git config i18n.commitencoding ISO-8859-1 &&
+ git config i18n.commitencoding ISO8859-1 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
- git-rebase --merge master &&
+ git rebase --merge master &&
check_encoding 2 8859
'
diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh
index fe4fb5116a..5868052425 100755
--- a/t/t3902-quoted.sh
+++ b/t/t3902-quoted.sh
@@ -7,12 +7,6 @@ test_description='quoted output'
. ./test-lib.sh
-P1='pathname with HT'
-: >"$P1" 2>&1 && test -f "$P1" && rm -f "$P1" || {
- echo >&2 'Filesystem does not support HT in names'
- test_done
-}
-
FN='濱野'
GN='ç´”'
HT=' '
@@ -20,7 +14,7 @@ LF='
'
DQ='"'
-echo foo > "Name and an${HT}HT"
+echo foo 2>/dev/null > "Name and an${HT}HT"
test -f "Name and an${HT}HT" || {
# since FAT/NTFS does not allow tabs in filenames, skip this test
say 'Your filesystem does not allow tabs in filenames, test skipped.'
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 2d3ee3b78c..5514f74b30 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2007 Johannes E Schindelin
#
-test_description='Test git-stash'
+test_description='Test git stash'
. ./test-lib.sh
@@ -41,7 +41,7 @@ test_expect_success 'apply needs clean working directory' '
echo 4 > other-file &&
git add other-file &&
echo 5 > other-file &&
- test_must_fail git stash apply
+ test_must_fail git stash apply
'
test_expect_success 'apply stashed changes' '
@@ -117,4 +117,106 @@ test_expect_success 'stash pop' '
test 0 = $(git stash list | wc -l)
'
+cat > expect << EOF
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000..1fe912c
+--- /dev/null
++++ b/file2
+@@ -0,0 +1 @@
++bar2
+EOF
+
+cat > expect1 << EOF
+diff --git a/file b/file
+index 257cc56..5716ca5 100644
+--- a/file
++++ b/file
+@@ -1 +1 @@
+-foo
++bar
+EOF
+
+cat > expect2 << EOF
+diff --git a/file b/file
+index 7601807..5716ca5 100644
+--- a/file
++++ b/file
+@@ -1 +1 @@
+-baz
++bar
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000..1fe912c
+--- /dev/null
++++ b/file2
+@@ -0,0 +1 @@
++bar2
+EOF
+
+test_expect_success 'stash branch' '
+ echo foo > file &&
+ git commit file -m first
+ echo bar > file &&
+ echo bar2 > file2 &&
+ git add file2 &&
+ git stash &&
+ echo baz > file &&
+ git commit file -m second &&
+ git stash branch stashbranch &&
+ test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
+ test $(git rev-parse HEAD) = $(git rev-parse master^) &&
+ git diff --cached > output &&
+ test_cmp output expect &&
+ git diff > output &&
+ test_cmp output expect1 &&
+ git add file &&
+ git commit -m alternate\ second &&
+ git diff master..stashbranch > output &&
+ test_cmp output expect2 &&
+ test 0 = $(git stash list | wc -l)
+'
+
+test_expect_success 'apply -q is quiet' '
+ echo foo > file &&
+ git stash &&
+ git stash apply -q > output.out 2>&1 &&
+ test ! -s output.out
+'
+
+test_expect_success 'save -q is quiet' '
+ git stash save --quiet > output.out 2>&1 &&
+ test ! -s output.out
+'
+
+test_expect_success 'pop -q is quiet' '
+ git stash pop -q > output.out 2>&1 &&
+ test ! -s output.out
+'
+
+test_expect_success 'drop -q is quiet' '
+ git stash &&
+ git stash drop -q > output.out 2>&1 &&
+ test ! -s output.out
+'
+
+test_expect_success 'stash -k' '
+ echo bar3 > file &&
+ echo bar4 > file2 &&
+ git add file2 &&
+ git stash -k &&
+ test bar,bar4 = $(cat file),$(cat file2)
+'
+
+test_expect_success 'stash --invalid-option' '
+ echo bar5 > file &&
+ echo bar6 > file2 &&
+ git add file2 &&
+ test_must_fail git stash --invalid-option &&
+ test_must_fail git stash save --invalid-option &&
+ test bar5,bar6 = $(cat file),$(cat file2) &&
+ git stash -- -message-starting-with-dash &&
+ test bar,bar2 = $(cat file),$(cat file2)
+'
+
test_done
diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh
new file mode 100755
index 0000000000..f37e3bc6ec
--- /dev/null
+++ b/t/t3904-stash-patch.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+test_description='git checkout --patch'
+. ./lib-patch-mode.sh
+
+test_expect_success 'setup' '
+ mkdir dir &&
+ echo parent > dir/foo &&
+ echo dummy > bar &&
+ git add bar dir/foo &&
+ git commit -m initial &&
+ test_tick &&
+ test_commit second dir/foo head &&
+ echo index > dir/foo &&
+ git add dir/foo &&
+ set_and_save_state bar bar_work bar_index &&
+ save_head
+'
+
+# note: bar sorts before dir, so the first 'n' is always to skip 'bar'
+
+test_expect_success 'saying "n" does nothing' '
+ set_state dir/foo work index
+ (echo n; echo n) | test_must_fail git stash save -p &&
+ verify_state dir/foo work index &&
+ verify_saved_state bar
+'
+
+test_expect_success 'git stash -p' '
+ (echo n; echo y) | git stash save -p &&
+ verify_state dir/foo head index &&
+ verify_saved_state bar &&
+ git reset --hard &&
+ git stash apply &&
+ verify_state dir/foo work head &&
+ verify_state bar dummy dummy
+'
+
+test_expect_success 'git stash -p --no-keep-index' '
+ set_state dir/foo work index &&
+ set_state bar bar_work bar_index &&
+ (echo n; echo y) | git stash save -p --no-keep-index &&
+ verify_state dir/foo head head &&
+ verify_state bar bar_work dummy &&
+ git reset --hard &&
+ git stash apply --index &&
+ verify_state dir/foo work index &&
+ verify_state bar dummy bar_index
+'
+
+test_expect_success 'none of this moved HEAD' '
+ verify_saved_head
+'
+
+test_done
diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh
index c44b27aeb2..6ddd46915d 100755
--- a/t/t4000-diff-format.sh
+++ b/t/t4000-diff-format.sh
@@ -7,7 +7,7 @@ test_description='Test built-in diff output engine.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
echo >path0 'Line 1
Line 2
diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh
index a32692417d..71bac83dd5 100755
--- a/t/t4001-diff-rename.sh
+++ b/t/t4001-diff-rename.sh
@@ -7,7 +7,7 @@ test_description='Test rename detection in diff engine.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
echo >path0 'Line 1
Line 2
diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh
index a4cfde6b29..18695ce821 100755
--- a/t/t4002-diff-basic.sh
+++ b/t/t4002-diff-basic.sh
@@ -7,7 +7,7 @@ test_description='Test diff raw-output.
'
. ./test-lib.sh
-. ../lib-read-tree-m-3way.sh
+. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
cat >.test-plain-OA <<\EOF
:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A AA
@@ -169,6 +169,20 @@ test_expect_success \
cmp -s .test-a .test-recursive-AB'
test_expect_success \
+ 'diff-tree --stdin of known trees.' \
+ 'echo $tree_A $tree_B | git diff-tree --stdin > .test-a &&
+ echo $tree_A $tree_B > .test-plain-ABx &&
+ cat .test-plain-AB >> .test-plain-ABx &&
+ cmp -s .test-a .test-plain-ABx'
+
+test_expect_success \
+ 'diff-tree --stdin of known trees.' \
+ 'echo $tree_A $tree_B | git diff-tree -r --stdin > .test-a &&
+ echo $tree_A $tree_B > .test-recursive-ABx &&
+ cat .test-recursive-AB >> .test-recursive-ABx &&
+ cmp -s .test-a .test-recursive-ABx'
+
+test_expect_success \
'diff-cache O with A in cache' \
'git read-tree $tree_A &&
git diff-index --cached $tree_O >.test-a &&
@@ -244,4 +258,12 @@ test_expect_success \
git diff-tree -r -R $tree_A $tree_B >.test-b &&
cmp -s .test-a .test-b'
+test_expect_success \
+ 'diff can read from stdin' \
+ 'test_must_fail git diff --no-index -- MN - < NN |
+ grep -v "^index" | sed "s#/-#/NN#" >.test-a &&
+ test_must_fail git diff --no-index -- MN NN |
+ grep -v "^index" >.test-b &&
+ test_cmp .test-a .test-b'
+
test_done
diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh
index 8b1f875286..c6130c4019 100755
--- a/t/t4003-diff-rename-1.sh
+++ b/t/t4003-diff-rename-1.sh
@@ -7,11 +7,11 @@ test_description='More rename detection
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
'prepare reference tree' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
echo frotz >rezrov &&
git update-index --add COPYING rezrov &&
tree=$(git write-tree) &&
@@ -99,7 +99,7 @@ test_expect_success \
test_expect_success \
'prepare work tree once again' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
git update-index --add --remove COPYING COPYING.1'
# tree has COPYING and rezrov. work tree has COPYING and COPYING.1,
diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh
index 3d25be7a67..a4da1196a9 100755
--- a/t/t4004-diff-rename-symlink.sh
+++ b/t/t4004-diff-rename-symlink.sh
@@ -10,7 +10,13 @@ copy of symbolic links, but should not produce rename/copy followed
by an edit for them.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
+
+if ! test_have_prereq SYMLINKS
+then
+ say 'Symbolic links not supported, skipping tests.'
+ test_done
+fi
test_expect_success \
'prepare reference tree' \
diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh
index 6630017312..1ba359d478 100755
--- a/t/t4005-diff-rename-2.sh
+++ b/t/t4005-diff-rename-2.sh
@@ -7,11 +7,11 @@ test_description='Same rename detection as t4003 but testing diff-raw.
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
'prepare reference tree' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
echo frotz >rezrov &&
git update-index --add COPYING rezrov &&
tree=$(git write-tree) &&
@@ -71,7 +71,7 @@ test_expect_success \
test_expect_success \
'prepare work tree once again' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
git update-index --add --remove COPYING COPYING.1'
git diff-index -C --find-copies-harder $tree >current
diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh
index ab5406dd9f..8c1b81e248 100755
--- a/t/t4006-diff-mode.sh
+++ b/t/t4006-diff-mode.sh
@@ -15,21 +15,10 @@ test_expect_success \
tree=`git write-tree` &&
echo $tree'
-if [ "$(git config --get core.filemode)" = false ]
-then
- say 'filemode disabled on the filesystem, using update-index --chmod=+x'
- test_expect_success \
- 'git update-index --chmod=+x' \
- 'git update-index rezrov &&
- git update-index --chmod=+x rezrov &&
- git diff-index $tree >current'
-else
- test_expect_success \
- 'chmod' \
- 'chmod +x rezrov &&
- git update-index rezrov &&
- git diff-index $tree >current'
-fi
+test_expect_success \
+ 'chmod' \
+ 'test_chmod +x rezrov &&
+ git diff-index $tree >current'
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
@@ -38,6 +27,6 @@ echo ":100644 100755 X X M rezrov" >expected
test_expect_success \
'verify' \
- 'git diff expected check'
+ 'test_cmp expected check'
test_done
diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh
index 104a4e1492..11502b7509 100755
--- a/t/t4007-rename-3.sh
+++ b/t/t4007-rename-3.sh
@@ -7,34 +7,38 @@ test_description='Rename interaction with pathspec.
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
-
-test_expect_success \
- 'prepare reference tree' \
- 'mkdir path0 path1 &&
- cp ../../COPYING path0/COPYING &&
- git update-index --add path0/COPYING &&
- tree=$(git write-tree) &&
- echo $tree'
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
+
+test_expect_success 'prepare reference tree' '
+ mkdir path0 path1 &&
+ cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
+ git update-index --add path0/COPYING &&
+ tree=$(git write-tree) &&
+ echo $tree
+'
-test_expect_success \
- 'prepare work tree' \
- 'cp path0/COPYING path1/COPYING &&
- git update-index --add --remove path0/COPYING path1/COPYING'
+test_expect_success 'prepare work tree' '
+ cp path0/COPYING path1/COPYING &&
+ git update-index --add --remove path0/COPYING path1/COPYING
+'
# In the tree, there is only path0/COPYING. In the cache, path0 and
# path1 both have COPYING and the latter is a copy of path0/COPYING.
# Comparing the full tree with cache should tell us so.
-git diff-index -C --find-copies-harder $tree >current
-
cat >expected <<\EOF
:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 6ff87c4664981e4397625791c8ea3bbb5f2279a3 C100 path0/COPYING path1/COPYING
EOF
-test_expect_success \
- 'validate the result (#1)' \
- 'compare_diff_raw current expected'
+test_expect_success 'copy detection' '
+ git diff-index -C --find-copies-harder $tree >current &&
+ compare_diff_raw current expected
+'
+
+test_expect_success 'copy detection, cached' '
+ git diff-index -C --find-copies-harder --cached $tree >current &&
+ compare_diff_raw current expected
+'
# In the tree, there is only path0/COPYING. In the cache, path0 and
# path1 both have COPYING and the latter is a copy of path0/COPYING.
@@ -42,49 +46,45 @@ test_expect_success \
# path1/COPYING suddenly appearing from nowhere, not detected as
# a copy from path0/COPYING.
-git diff-index -C $tree path1 >current
-
cat >expected <<\EOF
:000000 100644 0000000000000000000000000000000000000000 6ff87c4664981e4397625791c8ea3bbb5f2279a3 A path1/COPYING
EOF
-test_expect_success \
- 'validate the result (#2)' \
- 'compare_diff_raw current expected'
-
-test_expect_success \
- 'tweak work tree' \
- 'rm -f path0/COPYING &&
- git update-index --remove path0/COPYING'
+test_expect_success 'copy, limited to a subtree' '
+ git diff-index -C --find-copies-harder $tree path1 >current &&
+ compare_diff_raw current expected
+'
+test_expect_success 'tweak work tree' '
+ rm -f path0/COPYING &&
+ git update-index --remove path0/COPYING
+'
# In the tree, there is only path0/COPYING. In the cache, path0 does
# not have COPYING anymore and path1 has COPYING which is a copy of
# path0/COPYING. Showing the full tree with cache should tell us about
# the rename.
-git diff-index -C $tree >current
-
cat >expected <<\EOF
:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 6ff87c4664981e4397625791c8ea3bbb5f2279a3 R100 path0/COPYING path1/COPYING
EOF
-test_expect_success \
- 'validate the result (#3)' \
- 'compare_diff_raw current expected'
+test_expect_success 'rename detection' '
+ git diff-index -C --find-copies-harder $tree >current &&
+ compare_diff_raw current expected
+'
# In the tree, there is only path0/COPYING. In the cache, path0 does
# not have COPYING anymore and path1 has COPYING which is a copy of
# path0/COPYING. When we say we care only about path1, we should just
# see path1/COPYING appearing from nowhere.
-git diff-index -C $tree path1 >current
-
cat >expected <<\EOF
:000000 100644 0000000000000000000000000000000000000000 6ff87c4664981e4397625791c8ea3bbb5f2279a3 A path1/COPYING
EOF
-test_expect_success \
- 'validate the result (#4)' \
- 'compare_diff_raw current expected'
+test_expect_success 'rename, limited to a subtree' '
+ git diff-index -C --find-copies-harder $tree path1 >current &&
+ compare_diff_raw current expected
+'
test_done
diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh
index 26c2e4aa65..e19ca65885 100755
--- a/t/t4008-diff-break-rewrite.sh
+++ b/t/t4008-diff-break-rewrite.sh
@@ -22,12 +22,12 @@ four changes in total.
Further, with -B and -M together, these should turn into two renames.
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
setup \
- 'cat ../../README >file0 &&
- cat ../../COPYING >file1 &&
+ 'cat "$TEST_DIRECTORY"/../README >file0 &&
+ cat "$TEST_DIRECTORY"/../COPYING >file1 &&
git update-index --add file0 file1 &&
tree=$(git write-tree) &&
echo "$tree"'
@@ -99,7 +99,7 @@ test_expect_success \
'validate result of -B -M (#4)' \
'compare_diff_raw expected current'
-test_expect_success \
+test_expect_success SYMLINKS \
'make file0 into something completely different' \
'rm -f file0 &&
ln -s frotz file0 &&
@@ -114,7 +114,7 @@ cat >expected <<\EOF
:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100 file1
EOF
-test_expect_success \
+test_expect_success SYMLINKS \
'validate result of -B (#5)' \
'compare_diff_raw expected current'
@@ -129,7 +129,7 @@ cat >expected <<\EOF
:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 R file0 file1
EOF
-test_expect_success \
+test_expect_success SYMLINKS \
'validate result of -B -M (#6)' \
'compare_diff_raw expected current'
@@ -144,7 +144,7 @@ cat >expected <<\EOF
:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M file1
EOF
-test_expect_success \
+test_expect_success SYMLINKS \
'validate result of -M (#7)' \
'compare_diff_raw expected current'
diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh
index d2b45e7b8f..de3f17478e 100755
--- a/t/t4009-diff-rename-4.sh
+++ b/t/t4009-diff-rename-4.sh
@@ -7,11 +7,11 @@ test_description='Same rename detection as t4003 but testing diff-raw -z.
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
'prepare reference tree' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
echo frotz >rezrov &&
git update-index --add COPYING rezrov &&
tree=$(git write-tree) &&
@@ -78,7 +78,7 @@ test_expect_success \
test_expect_success \
'prepare work tree once again' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
git update-index --add --remove COPYING COPYING.1'
git diff-index -z -C --find-copies-harder $tree >current
diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh
index ad3d9e4845..94df7ae53a 100755
--- a/t/t4010-diff-pathspec.sh
+++ b/t/t4010-diff-pathspec.sh
@@ -10,7 +10,7 @@ Prepare:
path1/file1
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
setup \
@@ -62,4 +62,12 @@ test_expect_success \
'git diff-index --cached $tree -- file0/ >current &&
compare_diff_raw current expected'
+test_expect_success 'diff-tree pathspec' '
+ tree2=$(git write-tree) &&
+ echo "$tree2" &&
+ git diff-tree -r --name-only $tree $tree2 -- pa path1/a >current &&
+ >expected &&
+ test_cmp expected current
+'
+
test_done
diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh
index c6d13693ba..d7e327cc5b 100755
--- a/t/t4011-diff-symlink.sh
+++ b/t/t4011-diff-symlink.sh
@@ -7,7 +7,13 @@ test_description='Test diff of symlinks.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
+
+if ! test_have_prereq SYMLINKS
+then
+ say 'Symbolic links not supported, skipping tests.'
+ test_done
+fi
cat > expected << EOF
diff --git a/frotz b/frotz
@@ -82,4 +88,11 @@ test_expect_success \
git diff-index -M -p $tree > current &&
compare_diff_patch current expected'
+test_expect_success \
+ 'diff symlinks with non-existing targets' \
+ 'ln -s narf pinky &&
+ ln -s take\ over brain &&
+ test_must_fail git diff --no-index pinky brain > output 2> output.err &&
+ grep narf output &&
+ ! grep error output.err'
test_done
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index eced1f30fb..f64aa48d24 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -12,7 +12,7 @@ test_expect_success 'prepare repository' \
'echo AIT >a && echo BIT >b && echo CIT >c && echo DIT >d &&
git update-index --add a b c d &&
echo git >a &&
- cat ../test4012.png >b &&
+ cat "$TEST_DIRECTORY"/test4012.png >b &&
echo git >c &&
cat b b >d'
@@ -25,11 +25,11 @@ cat > expected <<\EOF
EOF
test_expect_success 'diff without --binary' \
'git diff | git apply --stat --summary >current &&
- cmp current expected'
+ test_cmp expected current'
test_expect_success 'diff with --binary' \
'git diff --binary | git apply --stat --summary >current &&
- cmp current expected'
+ test_cmp expected current'
# apply needs to be able to skip the binary material correctly
# in order to report the line number of a corrupt patch.
@@ -61,7 +61,7 @@ test_expect_success 'apply detecting corrupt patch correctly' \
detected=`sed -ne "${detected}p" broken` &&
test "$detected" = xCIT'
-test_expect_success 'initial commit' 'git-commit -a -m initial'
+test_expect_success 'initial commit' 'git commit -a -m initial'
# Try removal (b), modification (d), and creation (e).
test_expect_success 'diff-index with --binary' \
@@ -72,9 +72,30 @@ test_expect_success 'diff-index with --binary' \
git apply --stat --summary current'
test_expect_success 'apply binary patch' \
- 'git-reset --hard &&
+ 'git reset --hard &&
git apply --binary --index <current &&
tree1=`git write-tree` &&
test "$tree1" = "$tree0"'
+q_to_nul() {
+ perl -pe 'y/Q/\000/'
+}
+
+nul_to_q() {
+ perl -pe 'y/\000/Q/'
+}
+
+test_expect_success 'diff --no-index with binary creation' '
+ echo Q | q_to_nul >binary &&
+ (: hide error code from diff, which just indicates differences
+ git diff --binary --no-index /dev/null binary >current ||
+ true
+ ) &&
+ rm binary &&
+ git apply --binary <current &&
+ echo Q >expected &&
+ nul_to_q <binary >actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 6b4d1c52bb..8e3694ed5b 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -74,6 +74,10 @@ test_expect_success setup '
for i in 1 2; do echo $i; done >>dir/sub &&
git update-index file0 dir/sub &&
+ mkdir dir3 &&
+ cp dir/sub dir3/sub &&
+ test-chmtime +1 dir3/sub &&
+
git config log.showroot false &&
git commit --amend &&
git show-branch
@@ -97,9 +101,8 @@ do
'' | '#'*) continue ;;
esac
test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'`
- cnt=`expr $test_count + 1`
- pfx=`printf "%04d" $cnt`
- expect="../t4013/diff.$test"
+ pfx=`printf "%04d" $test_count`
+ expect="$TEST_DIRECTORY/t4013/diff.$test"
actual="$pfx-diff.$test"
test_expect_success "git $cmd" '
@@ -112,7 +115,7 @@ do
} >"$actual" &&
if test -f "$expect"
then
- git diff "$expect" "$actual" &&
+ test_cmp "$expect" "$actual" &&
rm -f "$actual"
else
# this is to help developing new tests.
@@ -203,6 +206,11 @@ log --root -c --patch-with-stat --summary master
log --root --cc --patch-with-stat --summary master
log -SF master
log -SF -p master
+log --decorate --all
+log --decorate=full --all
+
+rev-list --parents HEAD
+rev-list --children HEAD
whatchanged master
whatchanged -p master
@@ -236,11 +244,15 @@ show --patch-with-stat --summary side
format-patch --stdout initial..side
format-patch --stdout initial..master^
format-patch --stdout initial..master
+format-patch --stdout --no-numbered initial..master
+format-patch --stdout --numbered initial..master
format-patch --attach --stdout initial..side
+format-patch --attach --stdout --suffix=.diff initial..side
format-patch --attach --stdout initial..master^
format-patch --attach --stdout initial..master
format-patch --inline --stdout initial..side
format-patch --inline --stdout initial..master^
+format-patch --inline --stdout --numbered-files initial..master
format-patch --inline --stdout initial..master
format-patch --inline --stdout --subject-prefix=TESTCASE initial..master
config format.subjectprefix DIFFERENT_PREFIX
@@ -257,6 +269,11 @@ diff --patch-with-raw initial..side
diff --patch-with-stat -r initial..side
diff --patch-with-raw -r initial..side
diff --name-status dir2 dir
+diff --no-index --name-status dir2 dir
+diff --no-index --name-status -- dir2 dir
+diff --no-index dir dir3
+diff master master^ side
+diff --dirstat master~1 master~2
EOF
test_done
diff --git a/t/t4013/diff.diff_--dirstat_master~1_master~2 b/t/t4013/diff.diff_--dirstat_master~1_master~2
new file mode 100644
index 0000000000..b672e1ca63
--- /dev/null
+++ b/t/t4013/diff.diff_--dirstat_master~1_master~2
@@ -0,0 +1,3 @@
+$ git diff --dirstat master~1 master~2
+ 40.0% dir/
+$
diff --git a/t/t4013/diff.diff_--name-status_dir2_dir b/t/t4013/diff.diff_--name-status_dir2_dir
index ef7fdb7335..d0d96aaa91 100644
--- a/t/t4013/diff.diff_--name-status_dir2_dir
+++ b/t/t4013/diff.diff_--name-status_dir2_dir
@@ -1,3 +1,2 @@
$ git diff --name-status dir2 dir
-A dir/sub
$
diff --git a/t/t4013/diff.diff_--no-index_--name-status_--_dir2_dir b/t/t4013/diff.diff_--no-index_--name-status_--_dir2_dir
new file mode 100644
index 0000000000..6756f8de67
--- /dev/null
+++ b/t/t4013/diff.diff_--no-index_--name-status_--_dir2_dir
@@ -0,0 +1,3 @@
+$ git diff --no-index --name-status -- dir2 dir
+A dir/sub
+$
diff --git a/t/t4013/diff.diff_--no-index_--name-status_dir2_dir b/t/t4013/diff.diff_--no-index_--name-status_dir2_dir
new file mode 100644
index 0000000000..6a47584777
--- /dev/null
+++ b/t/t4013/diff.diff_--no-index_--name-status_dir2_dir
@@ -0,0 +1,3 @@
+$ git diff --no-index --name-status dir2 dir
+A dir/sub
+$
diff --git a/t/t4013/diff.diff_--no-index_dir_dir3 b/t/t4013/diff.diff_--no-index_dir_dir3
new file mode 100644
index 0000000000..2142c2b9ad
--- /dev/null
+++ b/t/t4013/diff.diff_--no-index_dir_dir3
@@ -0,0 +1,2 @@
+$ git diff --no-index dir dir3
+$
diff --git a/t/t4013/diff.diff_master_master^_side b/t/t4013/diff.diff_master_master^_side
new file mode 100644
index 0000000000..50ec9cadd6
--- /dev/null
+++ b/t/t4013/diff.diff_master_master^_side
@@ -0,0 +1,29 @@
+$ git diff master master^ side
+diff --cc dir/sub
+index cead32e,7289e35..992913c
+--- a/dir/sub
++++ b/dir/sub
+@@@ -1,6 -1,4 +1,8 @@@
+ A
+ B
+ +C
+ +D
+ +E
+ +F
++ 1
++ 2
+diff --cc file0
+index b414108,f4615da..10a8a9f
+--- a/file0
++++ b/file0
+@@@ -1,6 -1,6 +1,9 @@@
+ 1
+ 2
+ 3
+ +4
+ +5
+ +6
++ A
++ B
++ C
+$
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side
new file mode 100644
index 0000000000..52116d3ead
--- /dev/null
+++ b/t/t4013/diff.format-patch_--attach_--stdout_--suffix=.diff_initial..side
@@ -0,0 +1,61 @@
+$ git format-patch --attach --stdout --suffix=.diff initial..side
+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:03:00 +0000
+Subject: [PATCH] Side
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file3 | 4 ++++
+ 3 files changed, 9 insertions(+), 0 deletions(-)
+ create mode 100644 file3
+
+
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="0001-Side.diff"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: attachment; filename="0001-Side.diff"
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..7289e35 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++1
++2
+diff --git a/file0 b/file0
+index 01e79c3..f4615da 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++A
++B
++C
+diff --git a/file3 b/file3
+new file mode 100644
+index 0000000..7289e35
+--- /dev/null
++++ b/file3
+@@ -0,0 +1,4 @@
++A
++B
++1
++2
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+$
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
index cf6891f748..ce49bd676e 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
@@ -2,7 +2,7 @@ $ git format-patch --attach --stdout initial..master
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
-Subject: [PATCH] Second
+Subject: [PATCH 1/3] Second
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -19,10 +19,12 @@ This is the second commit.
file2 | 3 ---
3 files changed, 5 insertions(+), 3 deletions(-)
delete mode 100644 file2
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Type: text/x-patch; name="0001-Second.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: attachment; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Disposition: attachment; filename="0001-Second.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
@@ -61,7 +63,7 @@ index 01e79c3..0000000
From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
-Subject: [PATCH] Third
+Subject: [PATCH 2/3] Third
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -75,10 +77,12 @@ Content-Transfer-Encoding: 8bit
file1 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 file1
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Type: text/x-patch; name="0002-Third.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: attachment; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Disposition: attachment; filename="0002-Third.patch"
diff --git a/dir/sub b/dir/sub
index 8422d40..cead32e 100644
@@ -107,7 +111,7 @@ index 0000000..b1e6722
From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:03:00 +0000
-Subject: [PATCH] Side
+Subject: [PATCH 3/3] Side
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -122,10 +126,12 @@ Content-Transfer-Encoding: 8bit
file3 | 4 ++++
3 files changed, 9 insertions(+), 0 deletions(-)
create mode 100644 file3
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Type: text/x-patch; name="0003-Side.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: attachment; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Disposition: attachment; filename="0003-Side.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..7289e35 100644
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
index fe0258720c..5f1b23863b 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
@@ -2,7 +2,7 @@ $ git format-patch --attach --stdout initial..master^
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
-Subject: [PATCH] Second
+Subject: [PATCH 1/2] Second
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -19,10 +19,12 @@ This is the second commit.
file2 | 3 ---
3 files changed, 5 insertions(+), 3 deletions(-)
delete mode 100644 file2
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Type: text/x-patch; name="0001-Second.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: attachment; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Disposition: attachment; filename="0001-Second.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
@@ -61,7 +63,7 @@ index 01e79c3..0000000
From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
-Subject: [PATCH] Third
+Subject: [PATCH 2/2] Third
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -75,10 +77,12 @@ Content-Transfer-Encoding: 8bit
file1 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 file1
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Type: text/x-patch; name="0002-Third.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: attachment; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Disposition: attachment; filename="0002-Third.patch"
diff --git a/dir/sub b/dir/sub
index 8422d40..cead32e 100644
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
index 9ff828ee9d..4a2364abc2 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
@@ -17,10 +17,12 @@ Content-Transfer-Encoding: 8bit
file3 | 4 ++++
3 files changed, 9 insertions(+), 0 deletions(-)
create mode 100644 file3
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Type: text/x-patch; name="0001-Side.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: attachment; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Disposition: attachment; filename="0001-Side.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..7289e35 100644
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master
new file mode 100644
index 0000000000..43b81eba54
--- /dev/null
+++ b/t/t4013/diff.format-patch_--inline_--stdout_--numbered-files_initial..master
@@ -0,0 +1,170 @@
+$ git format-patch --inline --stdout --numbered-files initial..master
+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:01:00 +0000
+Subject: [PATCH 1/3] Second
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+
+This is the second commit.
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file2 | 3 ---
+ 3 files changed, 5 insertions(+), 3 deletions(-)
+ delete mode 100644 file2
+
+
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="1"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename="1"
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..8422d40 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++C
++D
+diff --git a/file0 b/file0
+index 01e79c3..b414108 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++4
++5
++6
+diff --git a/file2 b/file2
+deleted file mode 100644
+index 01e79c3..0000000
+--- a/file2
++++ /dev/null
+@@ -1,3 +0,0 @@
+-1
+-2
+-3
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+
+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:02:00 +0000
+Subject: [PATCH 2/3] Third
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+---
+ dir/sub | 2 ++
+ file1 | 3 +++
+ 2 files changed, 5 insertions(+), 0 deletions(-)
+ create mode 100644 file1
+
+
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="2"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename="2"
+
+diff --git a/dir/sub b/dir/sub
+index 8422d40..cead32e 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -2,3 +2,5 @@ A
+ B
+ C
+ D
++E
++F
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+
+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:03:00 +0000
+Subject: [PATCH 3/3] Side
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file3 | 4 ++++
+ 3 files changed, 9 insertions(+), 0 deletions(-)
+ create mode 100644 file3
+
+
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="3"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename="3"
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..7289e35 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++1
++2
+diff --git a/file0 b/file0
+index 01e79c3..f4615da 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++A
++B
++C
+diff --git a/file3 b/file3
+new file mode 100644
+index 0000000..7289e35
+--- /dev/null
++++ b/file3
+@@ -0,0 +1,4 @@
++A
++B
++1
++2
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+$
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
index a8093be7ca..ca3f60bf0e 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
@@ -2,7 +2,7 @@ $ git format-patch --inline --stdout --subject-prefix=TESTCASE initial..master
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
-Subject: [TESTCASE] Second
+Subject: [TESTCASE 1/3] Second
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -19,10 +19,12 @@ This is the second commit.
file2 | 3 ---
3 files changed, 5 insertions(+), 3 deletions(-)
delete mode 100644 file2
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Type: text/x-patch; name="0001-Second.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Disposition: inline; filename="0001-Second.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
@@ -61,7 +63,7 @@ index 01e79c3..0000000
From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
-Subject: [TESTCASE] Third
+Subject: [TESTCASE 2/3] Third
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -75,10 +77,12 @@ Content-Transfer-Encoding: 8bit
file1 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 file1
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Type: text/x-patch; name="0002-Third.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Disposition: inline; filename="0002-Third.patch"
diff --git a/dir/sub b/dir/sub
index 8422d40..cead32e 100644
@@ -107,7 +111,7 @@ index 0000000..b1e6722
From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:03:00 +0000
-Subject: [TESTCASE] Side
+Subject: [TESTCASE 3/3] Side
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -122,10 +126,12 @@ Content-Transfer-Encoding: 8bit
file3 | 4 ++++
3 files changed, 9 insertions(+), 0 deletions(-)
create mode 100644 file3
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Type: text/x-patch; name="0003-Side.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Disposition: inline; filename="0003-Side.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..7289e35 100644
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master
index aa110c0e7f..08f23014bc 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master
@@ -2,7 +2,7 @@ $ git format-patch --inline --stdout initial..master
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
-Subject: [PATCH] Second
+Subject: [PATCH 1/3] Second
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -19,10 +19,12 @@ This is the second commit.
file2 | 3 ---
3 files changed, 5 insertions(+), 3 deletions(-)
delete mode 100644 file2
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Type: text/x-patch; name="0001-Second.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Disposition: inline; filename="0001-Second.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
@@ -61,7 +63,7 @@ index 01e79c3..0000000
From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
-Subject: [PATCH] Third
+Subject: [PATCH 2/3] Third
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -75,10 +77,12 @@ Content-Transfer-Encoding: 8bit
file1 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 file1
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Type: text/x-patch; name="0002-Third.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Disposition: inline; filename="0002-Third.patch"
diff --git a/dir/sub b/dir/sub
index 8422d40..cead32e 100644
@@ -107,7 +111,7 @@ index 0000000..b1e6722
From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:03:00 +0000
-Subject: [PATCH] Side
+Subject: [PATCH 3/3] Side
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -122,10 +126,12 @@ Content-Transfer-Encoding: 8bit
file3 | 4 ++++
3 files changed, 9 insertions(+), 0 deletions(-)
create mode 100644 file3
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Type: text/x-patch; name="0003-Side.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Disposition: inline; filename="0003-Side.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..7289e35 100644
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
index 95e9ea4c59..07f1230d31 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
@@ -2,7 +2,7 @@ $ git format-patch --inline --stdout initial..master^
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
-Subject: [PATCH] Second
+Subject: [PATCH 1/2] Second
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -19,10 +19,12 @@ This is the second commit.
file2 | 3 ---
3 files changed, 5 insertions(+), 3 deletions(-)
delete mode 100644 file2
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Type: text/x-patch; name="0001-Second.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Disposition: inline; filename="0001-Second.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
@@ -61,7 +63,7 @@ index 01e79c3..0000000
From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
-Subject: [PATCH] Third
+Subject: [PATCH 2/2] Third
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
@@ -75,10 +77,12 @@ Content-Transfer-Encoding: 8bit
file1 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 file1
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Type: text/x-patch; name="0002-Third.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Disposition: inline; filename="0002-Third.patch"
diff --git a/dir/sub b/dir/sub
index 8422d40..cead32e 100644
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
index b8e81e1552..29e00ab8af 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
@@ -19,10 +19,12 @@ This is the second commit.
file2 | 3 ---
3 files changed, 5 insertions(+), 3 deletions(-)
delete mode 100644 file2
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Type: text/x-patch; name="0001-Second.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Disposition: inline; filename="0001-Second.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side
index 86ae923d71..67633d424a 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side
@@ -17,10 +17,12 @@ Content-Transfer-Encoding: 8bit
file3 | 4 ++++
3 files changed, 9 insertions(+), 0 deletions(-)
create mode 100644 file3
+
+
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Type: text/x-patch; name="0001-Side.patch"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Disposition: inline; filename="0001-Side.patch"
diff --git a/dir/sub b/dir/sub
index 35d242b..7289e35 100644
diff --git a/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master
new file mode 100644
index 0000000000..f7752ebbea
--- /dev/null
+++ b/t/t4013/diff.format-patch_--stdout_--no-numbered_initial..master
@@ -0,0 +1,127 @@
+$ git format-patch --stdout --no-numbered initial..master
+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:01:00 +0000
+Subject: [PATCH] Second
+
+This is the second commit.
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file2 | 3 ---
+ 3 files changed, 5 insertions(+), 3 deletions(-)
+ delete mode 100644 file2
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..8422d40 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++C
++D
+diff --git a/file0 b/file0
+index 01e79c3..b414108 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++4
++5
++6
+diff --git a/file2 b/file2
+deleted file mode 100644
+index 01e79c3..0000000
+--- a/file2
++++ /dev/null
+@@ -1,3 +0,0 @@
+-1
+-2
+-3
+--
+g-i-t--v-e-r-s-i-o-n
+
+
+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:02:00 +0000
+Subject: [PATCH] Third
+
+---
+ dir/sub | 2 ++
+ file1 | 3 +++
+ 2 files changed, 5 insertions(+), 0 deletions(-)
+ create mode 100644 file1
+
+diff --git a/dir/sub b/dir/sub
+index 8422d40..cead32e 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -2,3 +2,5 @@ A
+ B
+ C
+ D
++E
++F
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
+--
+g-i-t--v-e-r-s-i-o-n
+
+
+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:03:00 +0000
+Subject: [PATCH] Side
+
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file3 | 4 ++++
+ 3 files changed, 9 insertions(+), 0 deletions(-)
+ create mode 100644 file3
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..7289e35 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++1
++2
+diff --git a/file0 b/file0
+index 01e79c3..f4615da 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++A
++B
++C
+diff --git a/file3 b/file3
+new file mode 100644
+index 0000000..7289e35
+--- /dev/null
++++ b/file3
+@@ -0,0 +1,4 @@
++A
++B
++1
++2
+--
+g-i-t--v-e-r-s-i-o-n
+
+$
diff --git a/t/t4013/diff.format-patch_--stdout_--numbered_initial..master b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master
new file mode 100644
index 0000000000..8e67dbf76f
--- /dev/null
+++ b/t/t4013/diff.format-patch_--stdout_--numbered_initial..master
@@ -0,0 +1,127 @@
+$ git format-patch --stdout --numbered initial..master
+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:01:00 +0000
+Subject: [PATCH 1/3] Second
+
+This is the second commit.
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file2 | 3 ---
+ 3 files changed, 5 insertions(+), 3 deletions(-)
+ delete mode 100644 file2
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..8422d40 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++C
++D
+diff --git a/file0 b/file0
+index 01e79c3..b414108 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++4
++5
++6
+diff --git a/file2 b/file2
+deleted file mode 100644
+index 01e79c3..0000000
+--- a/file2
++++ /dev/null
+@@ -1,3 +0,0 @@
+-1
+-2
+-3
+--
+g-i-t--v-e-r-s-i-o-n
+
+
+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:02:00 +0000
+Subject: [PATCH 2/3] Third
+
+---
+ dir/sub | 2 ++
+ file1 | 3 +++
+ 2 files changed, 5 insertions(+), 0 deletions(-)
+ create mode 100644 file1
+
+diff --git a/dir/sub b/dir/sub
+index 8422d40..cead32e 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -2,3 +2,5 @@ A
+ B
+ C
+ D
++E
++F
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
+--
+g-i-t--v-e-r-s-i-o-n
+
+
+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:03:00 +0000
+Subject: [PATCH 3/3] Side
+
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file3 | 4 ++++
+ 3 files changed, 9 insertions(+), 0 deletions(-)
+ create mode 100644 file3
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..7289e35 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++1
++2
+diff --git a/file0 b/file0
+index 01e79c3..f4615da 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++A
++B
++C
+diff --git a/file3 b/file3
+new file mode 100644
+index 0000000..7289e35
+--- /dev/null
++++ b/file3
+@@ -0,0 +1,4 @@
++A
++B
++1
++2
+--
+g-i-t--v-e-r-s-i-o-n
+
+$
diff --git a/t/t4013/diff.format-patch_--stdout_initial..master b/t/t4013/diff.format-patch_--stdout_initial..master
index 8b88ca4927..7b89978e32 100644
--- a/t/t4013/diff.format-patch_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--stdout_initial..master
@@ -2,7 +2,7 @@ $ git format-patch --stdout initial..master
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
-Subject: [PATCH] Second
+Subject: [PATCH 1/3] Second
This is the second commit.
---
@@ -48,7 +48,7 @@ g-i-t--v-e-r-s-i-o-n
From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
-Subject: [PATCH] Third
+Subject: [PATCH 2/3] Third
---
dir/sub | 2 ++
@@ -82,7 +82,7 @@ g-i-t--v-e-r-s-i-o-n
From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:03:00 +0000
-Subject: [PATCH] Side
+Subject: [PATCH 3/3] Side
---
dir/sub | 2 ++
diff --git a/t/t4013/diff.format-patch_--stdout_initial..master^ b/t/t4013/diff.format-patch_--stdout_initial..master^
index 47a4b88637..b7f9725dc4 100644
--- a/t/t4013/diff.format-patch_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--stdout_initial..master^
@@ -2,7 +2,7 @@ $ git format-patch --stdout initial..master^
From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
-Subject: [PATCH] Second
+Subject: [PATCH 1/2] Second
This is the second commit.
---
@@ -48,7 +48,7 @@ g-i-t--v-e-r-s-i-o-n
From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
-Subject: [PATCH] Third
+Subject: [PATCH 2/2] Third
---
dir/sub | 2 ++
diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all
new file mode 100644
index 0000000000..d155e0bab2
--- /dev/null
+++ b/t/t4013/diff.log_--decorate=full_--all
@@ -0,0 +1,34 @@
+$ git log --decorate=full --all
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, refs/heads/master)
+Merge: 9a6d494 c7a2ab9
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:04:00 2006 +0000
+
+ Merge branch 'side'
+
+commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:03:00 2006 +0000
+
+ Side
+
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:02:00 2006 +0000
+
+ Third
+
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:01:00 2006 +0000
+
+ Second
+
+ This is the second commit.
+
+commit 444ac553ac7612cc88969031b02b3767fb8a353a (refs/heads/initial)
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:00:00 2006 +0000
+
+ Initial
+$
diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all
new file mode 100644
index 0000000000..fd7c3e6439
--- /dev/null
+++ b/t/t4013/diff.log_--decorate_--all
@@ -0,0 +1,34 @@
+$ git log --decorate --all
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD, master)
+Merge: 9a6d494 c7a2ab9
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:04:00 2006 +0000
+
+ Merge branch 'side'
+
+commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:03:00 2006 +0000
+
+ Side
+
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:02:00 2006 +0000
+
+ Third
+
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:01:00 2006 +0000
+
+ Second
+
+ This is the second commit.
+
+commit 444ac553ac7612cc88969031b02b3767fb8a353a (initial)
+Author: A U Thor <author@example.com>
+Date: Mon Jun 26 00:00:00 2006 +0000
+
+ Initial
+$
diff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
index 3ceb8e73c5..bd7f5c0f70 100644
--- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
@@ -1,6 +1,6 @@
$ git log --patch-with-stat --summary master -- dir/
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_master
index 43d77761f9..14595a614c 100644
--- a/t/t4013/diff.log_--patch-with-stat_master
+++ b/t/t4013/diff.log_--patch-with-stat_master
@@ -1,6 +1,6 @@
$ git log --patch-with-stat master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
index 5187a26816..5a4e72765d 100644
--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
@@ -1,6 +1,6 @@
$ git log --patch-with-stat master -- dir/
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
index c9640976a8..df0aaa9f2c 100644
--- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git log --root --cc --patch-with-stat --summary master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
index ad050af55f..c11b5f2c7f 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git log --root --patch-with-stat --summary master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_master
index 628c6c03bc..5f0c98f9ce 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_master
@@ -1,6 +1,6 @@
$ git log --root --patch-with-stat master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
index 5d4e0f13b5..e62c368dc6 100644
--- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git log --root -c --patch-with-stat --summary master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--root_-p_master b/t/t4013/diff.log_--root_-p_master
index 217a2eb203..b42c334439 100644
--- a/t/t4013/diff.log_--root_-p_master
+++ b/t/t4013/diff.log_--root_-p_master
@@ -1,6 +1,6 @@
$ git log --root -p master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_--root_master b/t/t4013/diff.log_--root_master
index e17ccfc234..e8f46159da 100644
--- a/t/t4013/diff.log_--root_master
+++ b/t/t4013/diff.log_--root_master
@@ -1,6 +1,6 @@
$ git log --root master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_-p_master b/t/t4013/diff.log_-p_master
index f8fefef2c3..bf1326dc36 100644
--- a/t/t4013/diff.log_-p_master
+++ b/t/t4013/diff.log_-p_master
@@ -1,6 +1,6 @@
$ git log -p master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.log_master b/t/t4013/diff.log_master
index e9d9e7b40a..a8f6ce5abd 100644
--- a/t/t4013/diff.log_master
+++ b/t/t4013/diff.log_master
@@ -1,6 +1,6 @@
$ git log master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.rev-list_--children_HEAD b/t/t4013/diff.rev-list_--children_HEAD
new file mode 100644
index 0000000000..e7f17d5aa0
--- /dev/null
+++ b/t/t4013/diff.rev-list_--children_HEAD
@@ -0,0 +1,7 @@
+$ git rev-list --children HEAD
+59d314ad6f356dd08601a4cd5e530381da3e3c64
+c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a 59d314ad6f356dd08601a4cd5e530381da3e3c64
+9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 59d314ad6f356dd08601a4cd5e530381da3e3c64
+1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+444ac553ac7612cc88969031b02b3767fb8a353a 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
+$
diff --git a/t/t4013/diff.rev-list_--parents_HEAD b/t/t4013/diff.rev-list_--parents_HEAD
new file mode 100644
index 0000000000..65d2a80208
--- /dev/null
+++ b/t/t4013/diff.rev-list_--parents_HEAD
@@ -0,0 +1,7 @@
+$ git rev-list --parents HEAD
+59d314ad6f356dd08601a4cd5e530381da3e3c64 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
+c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a 444ac553ac7612cc88969031b02b3767fb8a353a
+9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
+1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 444ac553ac7612cc88969031b02b3767fb8a353a
+444ac553ac7612cc88969031b02b3767fb8a353a
+$
diff --git a/t/t4013/diff.show_master b/t/t4013/diff.show_master
index 9e6e1f2710..fb08ce0e46 100644
--- a/t/t4013/diff.show_master
+++ b/t/t4013/diff.show_master
@@ -1,6 +1,6 @@
$ git show master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
index 5facf2543d..e96ff1fb8c 100644
--- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git whatchanged --root --cc --patch-with-stat --summary master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
index 10f6767e49..c0aff68ef6 100644
--- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git whatchanged --root -c --patch-with-stat --summary master
commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
-Merge: 9a6d494... c7a2ab9...
+Merge: 9a6d494 c7a2ab9
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index b2b7a8db85..3bc1cccf88 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2006 Junio C Hamano
#
-test_description='Format-patch skipping already incorporated patches'
+test_description='various format-patch tests'
. ./test-lib.sh
@@ -16,9 +16,7 @@ test_expect_success setup '
git checkout -b side &&
for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
- chmod +x elif &&
- git update-index file elif &&
- git update-index --chmod=+x elif &&
+ test_chmod +x elif &&
git commit -m "Side changes #1" &&
for i in D E F; do echo "$i"; done >>file &&
@@ -98,7 +96,7 @@ test_expect_success 'extra headers' '
sed -e "/^$/q" patch2 > hdrs2 &&
grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs2 &&
grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs2
-
+
'
test_expect_success 'extra headers without newlines' '
@@ -109,7 +107,7 @@ test_expect_success 'extra headers without newlines' '
sed -e "/^$/q" patch3 > hdrs3 &&
grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs3 &&
grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs3
-
+
'
test_expect_success 'extra headers with multiple To:s' '
@@ -130,6 +128,21 @@ test_expect_success 'additional command line cc' '
grep "^ *S. E. Cipient <scipient@example.com>$" patch5
'
+test_expect_success 'command line headers' '
+
+ git config --unset-all format.headers &&
+ git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch6 &&
+ grep "^Cc: R. E. Cipient <rcipient@example.com>$" patch6
+'
+
+test_expect_success 'configuration headers and command line headers' '
+
+ git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
+ git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch7 &&
+ grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch7 &&
+ grep "^ *S. E. Cipient <scipient@example.com>$" patch7
+'
+
test_expect_success 'multiple files' '
rm -rf patches/ &&
@@ -138,56 +151,243 @@ test_expect_success 'multiple files' '
ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch
'
-test_expect_success 'thread' '
+check_threading () {
+ expect="$1" &&
+ shift &&
+ (git format-patch --stdout "$@"; echo $? > status.out) |
+ # Prints everything between the Message-ID and In-Reply-To,
+ # and replaces all Message-ID-lookalikes by a sequence number
+ perl -ne '
+ if (/^(message-id|references|in-reply-to)/i) {
+ $printing = 1;
+ } elsif (/^\S/) {
+ $printing = 0;
+ }
+ if ($printing) {
+ $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
+ for $k (keys %h) {s/$k/$h{$k}/};
+ print;
+ }
+ print "---\n" if /^From /i;
+ ' > actual &&
+ test 0 = "$(cat status.out)" &&
+ test_cmp "$expect" actual
+}
+
+cat >> expect.no-threading <<EOF
+---
+---
+---
+EOF
- rm -rf patches/ &&
+test_expect_success 'no threading' '
git checkout side &&
- git format-patch --thread -o patches/ master &&
- FIRST_MID=$(grep "Message-Id:" patches/0001-* | sed "s/^[^<]*\(<[^>]*>\).*$/\1/") &&
- for i in patches/0002-* patches/0003-*
- do
- grep "References: $FIRST_MID" $i &&
- grep "In-Reply-To: $FIRST_MID" $i || break
- done
+ check_threading expect.no-threading master
'
-test_expect_success 'thread in-reply-to' '
+cat > expect.thread <<EOF
+---
+Message-Id: <0>
+---
+Message-Id: <1>
+In-Reply-To: <0>
+References: <0>
+---
+Message-Id: <2>
+In-Reply-To: <0>
+References: <0>
+EOF
- rm -rf patches/ &&
- git checkout side &&
- git format-patch --in-reply-to="<test.message>" --thread -o patches/ master &&
- FIRST_MID="<test.message>" &&
- for i in patches/*
- do
- grep "References: $FIRST_MID" $i &&
- grep "In-Reply-To: $FIRST_MID" $i || break
- done
+test_expect_success 'thread' '
+ check_threading expect.thread --thread master
'
-test_expect_success 'thread cover-letter' '
+cat > expect.in-reply-to <<EOF
+---
+Message-Id: <0>
+In-Reply-To: <1>
+References: <1>
+---
+Message-Id: <2>
+In-Reply-To: <1>
+References: <1>
+---
+Message-Id: <3>
+In-Reply-To: <1>
+References: <1>
+EOF
- rm -rf patches/ &&
- git checkout side &&
- git format-patch --cover-letter --thread -o patches/ master &&
- FIRST_MID=$(grep "Message-Id:" patches/0000-* | sed "s/^[^<]*\(<[^>]*>\).*$/\1/") &&
- for i in patches/0001-* patches/0002-* patches/0003-*
- do
- grep "References: $FIRST_MID" $i &&
- grep "In-Reply-To: $FIRST_MID" $i || break
- done
+test_expect_success 'thread in-reply-to' '
+ check_threading expect.in-reply-to --in-reply-to="<test.message>" \
+ --thread master
+'
+
+cat > expect.cover-letter <<EOF
+---
+Message-Id: <0>
+---
+Message-Id: <1>
+In-Reply-To: <0>
+References: <0>
+---
+Message-Id: <2>
+In-Reply-To: <0>
+References: <0>
+---
+Message-Id: <3>
+In-Reply-To: <0>
+References: <0>
+EOF
+
+test_expect_success 'thread cover-letter' '
+ check_threading expect.cover-letter --cover-letter --thread master
'
+cat > expect.cl-irt <<EOF
+---
+Message-Id: <0>
+In-Reply-To: <1>
+References: <1>
+---
+Message-Id: <2>
+In-Reply-To: <0>
+References: <1>
+ <0>
+---
+Message-Id: <3>
+In-Reply-To: <0>
+References: <1>
+ <0>
+---
+Message-Id: <4>
+In-Reply-To: <0>
+References: <1>
+ <0>
+EOF
+
test_expect_success 'thread cover-letter in-reply-to' '
+ check_threading expect.cl-irt --cover-letter \
+ --in-reply-to="<test.message>" --thread master
+'
- rm -rf patches/ &&
- git checkout side &&
- git format-patch --cover-letter --in-reply-to="<test.message>" --thread -o patches/ master &&
- FIRST_MID="<test.message>" &&
- for i in patches/*
- do
- grep "References: $FIRST_MID" $i &&
- grep "In-Reply-To: $FIRST_MID" $i || break
- done
+test_expect_success 'thread explicit shallow' '
+ check_threading expect.cl-irt --cover-letter \
+ --in-reply-to="<test.message>" --thread=shallow master
+'
+
+cat > expect.deep <<EOF
+---
+Message-Id: <0>
+---
+Message-Id: <1>
+In-Reply-To: <0>
+References: <0>
+---
+Message-Id: <2>
+In-Reply-To: <1>
+References: <0>
+ <1>
+EOF
+
+test_expect_success 'thread deep' '
+ check_threading expect.deep --thread=deep master
+'
+
+cat > expect.deep-irt <<EOF
+---
+Message-Id: <0>
+In-Reply-To: <1>
+References: <1>
+---
+Message-Id: <2>
+In-Reply-To: <0>
+References: <1>
+ <0>
+---
+Message-Id: <3>
+In-Reply-To: <2>
+References: <1>
+ <0>
+ <2>
+EOF
+
+test_expect_success 'thread deep in-reply-to' '
+ check_threading expect.deep-irt --thread=deep \
+ --in-reply-to="<test.message>" master
+'
+
+cat > expect.deep-cl <<EOF
+---
+Message-Id: <0>
+---
+Message-Id: <1>
+In-Reply-To: <0>
+References: <0>
+---
+Message-Id: <2>
+In-Reply-To: <1>
+References: <0>
+ <1>
+---
+Message-Id: <3>
+In-Reply-To: <2>
+References: <0>
+ <1>
+ <2>
+EOF
+
+test_expect_success 'thread deep cover-letter' '
+ check_threading expect.deep-cl --cover-letter --thread=deep master
+'
+
+cat > expect.deep-cl-irt <<EOF
+---
+Message-Id: <0>
+In-Reply-To: <1>
+References: <1>
+---
+Message-Id: <2>
+In-Reply-To: <0>
+References: <1>
+ <0>
+---
+Message-Id: <3>
+In-Reply-To: <2>
+References: <1>
+ <0>
+ <2>
+---
+Message-Id: <4>
+In-Reply-To: <3>
+References: <1>
+ <0>
+ <2>
+ <3>
+EOF
+
+test_expect_success 'thread deep cover-letter in-reply-to' '
+ check_threading expect.deep-cl-irt --cover-letter \
+ --in-reply-to="<test.message>" --thread=deep master
+'
+
+test_expect_success 'thread via config' '
+ git config format.thread true &&
+ check_threading expect.thread master
+'
+
+test_expect_success 'thread deep via config' '
+ git config format.thread deep &&
+ check_threading expect.deep master
+'
+
+test_expect_success 'thread config + override' '
+ git config format.thread deep &&
+ check_threading expect.thread --thread master
+'
+
+test_expect_success 'thread config + --no-thread' '
+ git config format.thread deep &&
+ check_threading expect.no-threading --no-thread master
'
test_expect_success 'excessive subject' '
@@ -226,8 +426,135 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
git format-patch --cover-letter -2 &&
sed -e "1,/A U Thor/d" -e "/^$/q" < 0000-cover-letter.patch > output &&
- git diff expect output
+ test_cmp expect output
+
+'
+
+cat > expect << EOF
+---
+ file | 16 ++++++++++++++++
+ 1 files changed, 16 insertions(+), 0 deletions(-)
+
+diff --git a/file b/file
+index 40f36c6..2dc5c23 100644
+--- a/file
++++ b/file
+@@ -13,4 +13,20 @@ C
+ 10
+ D
+ E
+ F
++5
+EOF
+
+test_expect_success 'format-patch respects -U' '
+
+ git format-patch -U4 -2 &&
+ sed -e "1,/^$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
+ test_cmp expect output
+
+'
+
+cat > expect << EOF
+
+diff --git a/file b/file
+index 40f36c6..2dc5c23 100644
+--- a/file
++++ b/file
+@@ -14,3 +14,19 @@ C
+ D
+ E
+ F
++5
+EOF
+
+test_expect_success 'format-patch -p suppresses stat' '
+
+ git format-patch -p -2 &&
+ sed -e "1,/^$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
+ test_cmp expect output
+
+'
+
+test_expect_success 'format-patch from a subdirectory (1)' '
+ filename=$(
+ rm -rf sub &&
+ mkdir -p sub/dir &&
+ cd sub/dir &&
+ git format-patch -1
+ ) &&
+ case "$filename" in
+ 0*)
+ ;; # ok
+ *)
+ echo "Oops? $filename"
+ false
+ ;;
+ esac &&
+ test -f "$filename"
+'
+
+test_expect_success 'format-patch from a subdirectory (2)' '
+ filename=$(
+ rm -rf sub &&
+ mkdir -p sub/dir &&
+ cd sub/dir &&
+ git format-patch -1 -o ..
+ ) &&
+ case "$filename" in
+ ../0*)
+ ;; # ok
+ *)
+ echo "Oops? $filename"
+ false
+ ;;
+ esac &&
+ basename=$(expr "$filename" : ".*/\(.*\)") &&
+ test -f "sub/$basename"
+'
+
+test_expect_success 'format-patch from a subdirectory (3)' '
+ rm -f 0* &&
+ filename=$(
+ rm -rf sub &&
+ mkdir -p sub/dir &&
+ cd sub/dir &&
+ git format-patch -1 -o "$TRASH_DIRECTORY"
+ ) &&
+ basename=$(expr "$filename" : ".*/\(.*\)") &&
+ test -f "$basename"
+'
+
+test_expect_success 'format-patch --in-reply-to' '
+ git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
+ grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
+ grep "^References: <baz@foo.bar>" patch8
+'
+
+test_expect_success 'format-patch --signoff' '
+ git format-patch -1 --signoff --stdout |
+ grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+'
+echo "fatal: --name-only does not make sense" > expect.name-only
+echo "fatal: --name-status does not make sense" > expect.name-status
+echo "fatal: --check does not make sense" > expect.check
+
+test_expect_success 'options no longer allowed for format-patch' '
+ test_must_fail git format-patch --name-only 2> output &&
+ test_cmp expect.name-only output &&
+ test_must_fail git format-patch --name-status 2> output &&
+ test_cmp expect.name-status output &&
+ test_must_fail git format-patch --check 2> output &&
+ test_cmp expect.check output'
+
+test_expect_success 'format-patch --numstat should produce a patch' '
+ git format-patch --numstat --stdout master..side > output &&
+ test 6 = $(grep "^diff --git a/" output | wc -l)'
+
+test_expect_success 'format-patch -- <path>' '
+ git format-patch master..side -- file 2>error &&
+ ! grep "Use .--" error
'
test_done
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index 83c54b747f..8dd147d78f 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -7,7 +7,7 @@ test_description='Test special whitespace in diff engine.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
# Ray Lehtiniemi's example
@@ -43,13 +43,13 @@ index adf3937..6edc172 100644
EOF
git diff > out
-test_expect_success "Ray's example without options" 'git diff expect out'
+test_expect_success "Ray's example without options" 'test_cmp expect out'
git diff -w > out
-test_expect_success "Ray's example with -w" 'git diff expect out'
+test_expect_success "Ray's example with -w" 'test_cmp expect out'
git diff -b > out
-test_expect_success "Ray's example with -b" 'git diff expect out'
+test_expect_success "Ray's example with -b" 'test_cmp expect out'
tr 'Q' '\015' << EOF > x
whitespace at beginning
@@ -62,16 +62,16 @@ EOF
git update-index x
-cat << EOF > x
+tr '_' ' ' << EOF > x
whitespace at beginning
whitespace change
white space in the middle
-whitespace at end
+whitespace at end__
unchanged line
CR at end
EOF
-tr 'Q' '\015' << EOF > expect
+tr 'Q_' '\015 ' << EOF > expect
diff --git a/x b/x
index d99af23..8b32fb5 100644
--- a/x
@@ -84,20 +84,26 @@ index d99af23..8b32fb5 100644
+ whitespace at beginning
+whitespace change
+white space in the middle
-+whitespace at end
++whitespace at end__
unchanged line
-CR at endQ
+CR at end
EOF
git diff > out
-test_expect_success 'another test, without options' 'git diff expect out'
+test_expect_success 'another test, without options' 'test_cmp expect out'
cat << EOF > expect
diff --git a/x b/x
index d99af23..8b32fb5 100644
EOF
git diff -w > out
-test_expect_success 'another test, with -w' 'git diff expect out'
+test_expect_success 'another test, with -w' 'test_cmp expect out'
+git diff -w -b > out
+test_expect_success 'another test, with -w -b' 'test_cmp expect out'
+git diff -w --ignore-space-at-eol > out
+test_expect_success 'another test, with -w --ignore-space-at-eol' 'test_cmp expect out'
+git diff -w -b --ignore-space-at-eol > out
+test_expect_success 'another test, with -w -b --ignore-space-at-eol' 'test_cmp expect out'
tr 'Q' '\015' << EOF > expect
diff --git a/x b/x
@@ -115,7 +121,28 @@ index d99af23..8b32fb5 100644
CR at endQ
EOF
git diff -b > out
-test_expect_success 'another test, with -b' 'git diff expect out'
+test_expect_success 'another test, with -b' 'test_cmp expect out'
+git diff -b --ignore-space-at-eol > out
+test_expect_success 'another test, with -b --ignore-space-at-eol' 'test_cmp expect out'
+
+tr 'Q' '\015' << EOF > expect
+diff --git a/x b/x
+index d99af23..8b32fb5 100644
+--- a/x
++++ b/x
+@@ -1,6 +1,6 @@
+-whitespace at beginning
+-whitespace change
+-whitespace in the middle
++ whitespace at beginning
++whitespace change
++white space in the middle
+ whitespace at end
+ unchanged line
+ CR at endQ
+EOF
+git diff --ignore-space-at-eol > out
+test_expect_success 'another test, with --ignore-space-at-eol' 'test_cmp expect out'
test_expect_success 'check mixed spaces and tabs in indent' '
@@ -144,7 +171,7 @@ test_expect_success 'check with no whitespace errors' '
test_expect_success 'check with trailing whitespace' '
echo "foo(); " > x &&
- ! git diff --check
+ test_must_fail git diff --check
'
@@ -152,7 +179,7 @@ test_expect_success 'check with space before tab in indent' '
# indent has space followed by hard tab
echo " foo();" > x &&
- ! git diff --check
+ test_must_fail git diff --check
'
@@ -181,7 +208,7 @@ test_expect_success 'check staged with trailing whitespace' '
echo "foo(); " > x &&
git add x &&
- ! git diff --cached --check
+ test_must_fail git diff --cached --check
'
@@ -190,7 +217,7 @@ test_expect_success 'check staged with space before tab in indent' '
# indent has space followed by hard tab
echo " foo();" > x &&
git add x &&
- ! git diff --cached --check
+ test_must_fail git diff --cached --check
'
@@ -206,7 +233,7 @@ test_expect_success 'check with trailing whitespace (diff-index)' '
echo "foo(); " > x &&
git add x &&
- ! git diff-index --check HEAD
+ test_must_fail git diff-index --check HEAD
'
@@ -215,7 +242,7 @@ test_expect_success 'check with space before tab in indent (diff-index)' '
# indent has space followed by hard tab
echo " foo();" > x &&
git add x &&
- ! git diff-index --check HEAD
+ test_must_fail git diff-index --check HEAD
'
@@ -231,7 +258,7 @@ test_expect_success 'check staged with trailing whitespace (diff-index)' '
echo "foo(); " > x &&
git add x &&
- ! git diff-index --cached --check HEAD
+ test_must_fail git diff-index --cached --check HEAD
'
@@ -240,7 +267,7 @@ test_expect_success 'check staged with space before tab in indent (diff-index)'
# indent has space followed by hard tab
echo " foo();" > x &&
git add x &&
- ! git diff-index --cached --check HEAD
+ test_must_fail git diff-index --cached --check HEAD
'
@@ -256,7 +283,7 @@ test_expect_success 'check with trailing whitespace (diff-tree)' '
echo "foo(); " > x &&
git commit -m "another commit" x &&
- ! git diff-tree --check HEAD^ HEAD
+ test_must_fail git diff-tree --check HEAD^ HEAD
'
@@ -265,7 +292,7 @@ test_expect_success 'check with space before tab in indent (diff-tree)' '
# indent has space followed by hard tab
echo " foo();" > x &&
git commit -m "yet another" x &&
- ! git diff-tree --check HEAD^ HEAD
+ test_must_fail git diff-tree --check HEAD^ HEAD
'
@@ -281,7 +308,7 @@ test_expect_success 'check trailing whitespace (trailing-space: on)' '
git config core.whitespace "trailing-space" &&
echo "foo (); " > x &&
- ! git diff --check
+ test_must_fail git diff --check
'
@@ -299,7 +326,7 @@ test_expect_success 'check space before tab in indent (space-before-tab: on)' '
# indent contains space followed by HT
git config core.whitespace "space-before-tab" &&
echo " foo (); " > x &&
- ! git diff --check
+ test_must_fail git diff --check
'
@@ -315,7 +342,7 @@ test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
git config core.whitespace "indent-with-non-tab" &&
echo " foo ();" > x &&
- ! git diff --check
+ test_must_fail git diff --check
'
@@ -323,7 +350,7 @@ test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab:
git config core.whitespace "indent-with-non-tab" &&
echo " foo ();" > x &&
- ! git diff --check
+ test_must_fail git diff --check
'
@@ -335,4 +362,44 @@ test_expect_success 'line numbers in --check output are correct' '
'
+test_expect_success 'checkdiff detects new trailing blank lines (1)' '
+ echo "foo();" >x &&
+ echo "" >>x &&
+ git diff --check | grep "new blank line"
+'
+
+test_expect_success 'checkdiff detects new trailing blank lines (2)' '
+ { echo a; echo b; echo; echo; } >x &&
+ git add x &&
+ { echo a; echo; echo; echo; echo; } >x &&
+ git diff --check | grep "new blank line"
+'
+
+test_expect_success 'checkdiff allows new blank lines' '
+ git checkout x &&
+ mv x y &&
+ (
+ echo "/* This is new */" &&
+ echo "" &&
+ cat y
+ ) >x &&
+ git diff --check
+'
+
+test_expect_success 'combined diff with autocrlf conversion' '
+
+ git reset --hard &&
+ echo >x hello &&
+ git commit -m "one side" x &&
+ git checkout HEAD^ &&
+ echo >x goodbye &&
+ git commit -m "the other side" x &&
+ git config core.autocrlf true &&
+ test_must_fail git merge master &&
+
+ git diff | sed -e "1,/^@@@/d" >actual &&
+ ! grep "^-" actual
+
+'
+
test_done
diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh
index 5dbdc0c9fa..55eb5f83f1 100755
--- a/t/t4016-diff-quote.sh
+++ b/t/t4016-diff-quote.sh
@@ -13,8 +13,8 @@ P1='pathname with HT'
P2='pathname with SP'
P3='pathname
with LF'
-: >"$P1" 2>&1 && test -f "$P1" && rm -f "$P1" || {
- echo >&2 'Filesystem does not support tabs in names'
+: 2>/dev/null >"$P1" && test -f "$P1" && rm -f "$P1" || {
+ say 'Your filesystem does not allow tabs in filenames, test skipped.'
test_done
}
@@ -49,22 +49,22 @@ cat >expect <<\EOF
EOF
test_expect_success 'git diff --summary -M HEAD' '
git diff --summary -M HEAD >actual &&
- git diff expect actual
+ test_cmp expect actual
'
cat >expect <<\EOF
- pathname.1 => "Rpathname\twith HT.0" | 0
- pathname.3 => "Rpathname\nwith LF.0" | 0
- "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0
- pathname.2 => Rpathname with SP.0 | 0
- "pathname\twith HT.2" => Rpathname with SP.1 | 0
- pathname.0 => Rpathname.0 | 0
- "pathname\twith HT.0" => Rpathname.1 | 0
+ pathname.1 => "Rpathname\twith HT.0" | 0
+ pathname.3 => "Rpathname\nwith LF.0" | 0
+ "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0
+ pathname.2 => Rpathname with SP.0 | 0
+ "pathname\twith HT.2" => Rpathname with SP.1 | 0
+ pathname.0 => Rpathname.0 | 0
+ "pathname\twith HT.0" => Rpathname.1 | 0
7 files changed, 0 insertions(+), 0 deletions(-)
EOF
test_expect_success 'git diff --stat -M HEAD' '
git diff --stat -M HEAD >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_done
diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh
index dc0b7126cc..60dd2014d5 100755
--- a/t/t4017-diff-retval.sh
+++ b/t/t4017-diff-retval.sh
@@ -105,4 +105,26 @@ test_expect_success '--check with --no-pager returns 2 for dirty difference' '
'
+
+test_expect_success 'check should test not just the last line' '
+ echo "" >>a &&
+ git --no-pager diff --check
+ test $? = 2
+
+'
+
+test_expect_success 'check detects leftover conflict markers' '
+ git reset --hard &&
+ git checkout HEAD^ &&
+ echo binary >>b &&
+ git commit -m "side" b &&
+ test_must_fail git merge master &&
+ git add b && (
+ git --no-pager diff --cached --check >test.out
+ test $? = 2
+ ) &&
+ test 3 = $(grep "conflict marker" test.out | wc -l) &&
+ git reset --hard
+'
+
test_done
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index f9db81d3ab..5b10e976a3 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -32,14 +32,25 @@ EOF
sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java
+builtin_patterns="bibtex cpp html java objc pascal php python ruby tex"
+for p in $builtin_patterns
+do
+ test_expect_success "builtin $p pattern compiles" '
+ echo "*.java diff=$p" > .gitattributes &&
+ ! ( git diff --no-index Beer.java Beer-correct.java 2>&1 |
+ grep "fatal" > /dev/null )
+ '
+done
+
test_expect_success 'default behaviour' '
- git diff Beer.java Beer-correct.java |
+ rm -f .gitattributes &&
+ git diff --no-index Beer.java Beer-correct.java |
grep "^@@.*@@ public class Beer"
'
test_expect_success 'preset java pattern' '
echo "*.java diff=java" >.gitattributes &&
- git diff Beer.java Beer-correct.java |
+ git diff --no-index Beer.java Beer-correct.java |
grep "^@@.*@@ public static void main("
'
@@ -48,13 +59,26 @@ git config diff.java.funcname '!static
[^ ].*s.*'
test_expect_success 'custom pattern' '
- git diff Beer.java Beer-correct.java |
+ git diff --no-index Beer.java Beer-correct.java |
grep "^@@.*@@ int special;$"
'
test_expect_success 'last regexp must not be negated' '
git config diff.java.funcname "!static" &&
- ! git diff Beer.java Beer-correct.java
+ git diff --no-index Beer.java Beer-correct.java 2>&1 |
+ grep "fatal: Last expression must not be negated:"
+'
+
+test_expect_success 'pattern which matches to end of line' '
+ git config diff.java.funcname "Beer$" &&
+ git diff --no-index Beer.java Beer-correct.java |
+ grep "^@@.*@@ Beer"
+'
+
+test_expect_success 'alternation in pattern' '
+ git config diff.java.xfuncname "^[ ]*((public|static).*)$" &&
+ git diff --no-index Beer.java Beer-correct.java |
+ grep "^@@.*@@ public static void main("
'
test_done
diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh
index 0d9cbb6261..f6d1f1ebab 100755
--- a/t/t4019-diff-wserror.sh
+++ b/t/t4019-diff-wserror.sh
@@ -13,17 +13,34 @@ test_expect_success setup '
echo " HT and SP indent" >>F &&
echo "With trailing SP " >>F &&
echo "Carriage ReturnQ" | tr Q "\015" >>F &&
- echo "No problem" >>F
+ echo "No problem" >>F &&
+ echo >>F
'
blue_grep='7;34m' ;# ESC [ 7 ; 3 4 m
+printf "\033[%s" "$blue_grep" >check-grep
+if (grep "$blue_grep" <check-grep | grep "$blue_grep") >/dev/null 2>&1
+then
+ grep_a=grep
+elif (grep -a "$blue_grep" <check-grep | grep -a "$blue_grep") >/dev/null 2>&1
+then
+ grep_a='grep -a'
+else
+ grep_a=grep ;# expected to fail...
+fi
+rm -f check-grep
+
+prepare_output () {
+ git diff --color >output
+ $grep_a "$blue_grep" output >error
+ $grep_a -v "$blue_grep" output >normal
+}
+
test_expect_success default '
- git diff --color >output
- grep "$blue_grep" output >error
- grep -v "$blue_grep" output >normal
+ prepare_output
grep Eight normal >/dev/null &&
grep HT error >/dev/null &&
@@ -36,9 +53,7 @@ test_expect_success default '
test_expect_success 'without -trail' '
git config core.whitespace -trail
- git diff --color >output
- grep "$blue_grep" output >error
- grep -v "$blue_grep" output >normal
+ prepare_output
grep Eight normal >/dev/null &&
grep HT error >/dev/null &&
@@ -52,9 +67,7 @@ test_expect_success 'without -trail (attribute)' '
git config --unset core.whitespace
echo "F whitespace=-trail" >.gitattributes
- git diff --color >output
- grep "$blue_grep" output >error
- grep -v "$blue_grep" output >normal
+ prepare_output
grep Eight normal >/dev/null &&
grep HT error >/dev/null &&
@@ -68,9 +81,7 @@ test_expect_success 'without -space' '
rm -f .gitattributes
git config core.whitespace -space
- git diff --color >output
- grep "$blue_grep" output >error
- grep -v "$blue_grep" output >normal
+ prepare_output
grep Eight normal >/dev/null &&
grep HT normal >/dev/null &&
@@ -84,9 +95,7 @@ test_expect_success 'without -space (attribute)' '
git config --unset core.whitespace
echo "F whitespace=-space" >.gitattributes
- git diff --color >output
- grep "$blue_grep" output >error
- grep -v "$blue_grep" output >normal
+ prepare_output
grep Eight normal >/dev/null &&
grep HT normal >/dev/null &&
@@ -100,9 +109,7 @@ test_expect_success 'with indent-non-tab only' '
rm -f .gitattributes
git config core.whitespace indent,-trailing,-space
- git diff --color >output
- grep "$blue_grep" output >error
- grep -v "$blue_grep" output >normal
+ prepare_output
grep Eight error >/dev/null &&
grep HT normal >/dev/null &&
@@ -116,9 +123,7 @@ test_expect_success 'with indent-non-tab only (attribute)' '
git config --unset core.whitespace
echo "F whitespace=indent,-trailing,-space" >.gitattributes
- git diff --color >output
- grep "$blue_grep" output >error
- grep -v "$blue_grep" output >normal
+ prepare_output
grep Eight error >/dev/null &&
grep HT normal >/dev/null &&
@@ -132,9 +137,7 @@ test_expect_success 'with cr-at-eol' '
rm -f .gitattributes
git config core.whitespace cr-at-eol
- git diff --color >output
- grep "$blue_grep" output >error
- grep -v "$blue_grep" output >normal
+ prepare_output
grep Eight normal >/dev/null &&
grep HT error >/dev/null &&
@@ -148,9 +151,7 @@ test_expect_success 'with cr-at-eol (attribute)' '
git config --unset core.whitespace
echo "F whitespace=trailing,cr-at-eol" >.gitattributes
- git diff --color >output
- grep "$blue_grep" output >error
- grep -v "$blue_grep" output >normal
+ prepare_output
grep Eight normal >/dev/null &&
grep HT error >/dev/null &&
@@ -160,4 +161,42 @@ test_expect_success 'with cr-at-eol (attribute)' '
'
+test_expect_success 'trailing empty lines (1)' '
+
+ rm -f .gitattributes &&
+ test_must_fail git diff --check >output &&
+ grep "new blank line at" output &&
+ grep "trailing whitespace" output
+
+'
+
+test_expect_success 'trailing empty lines (2)' '
+
+ echo "F -whitespace" >.gitattributes &&
+ git diff --check >output &&
+ ! test -s output
+
+'
+
+test_expect_success 'do not color trailing cr in context' '
+ git config --unset core.whitespace
+ rm -f .gitattributes &&
+ echo AAAQ | tr Q "\015" >G &&
+ git add G &&
+ echo BBBQ | tr Q "\015" >>G
+ git diff --color G | tr "\015" Q >output &&
+ grep "BBB.*${blue_grep}Q" output &&
+ grep "AAA.*\[mQ" output
+
+'
+
+test_expect_success 'color new trailing blank lines' '
+ { echo a; echo b; echo; echo; } >x &&
+ git add x &&
+ { echo a; echo; echo; echo; echo c; echo; echo; echo; echo; } >x &&
+ git diff --color x >output &&
+ cnt=$($grep_a "${blue_grep}" output | wc -l) &&
+ test $cnt = 2
+'
+
test_done
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index 637b4e19d5..a7602cf923 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -43,6 +43,13 @@ test_expect_success 'GIT_EXTERNAL_DIFF environment should apply only to diff' '
'
+test_expect_success 'GIT_EXTERNAL_DIFF environment and --no-ext-diff' '
+
+ GIT_EXTERNAL_DIFF=echo git diff --no-ext-diff |
+ grep "^diff --git a/file b/file"
+
+'
+
test_expect_success 'diff attribute' '
git config diff.parrot.command echo &&
@@ -68,6 +75,13 @@ test_expect_success 'diff attribute should apply only to diff' '
'
+test_expect_success 'diff attribute and --no-ext-diff' '
+
+ git diff --no-ext-diff |
+ grep "^diff --git a/file b/file"
+
+'
+
test_expect_success 'diff attribute' '
git config --unset diff.parrot.command &&
@@ -94,6 +108,13 @@ test_expect_success 'diff attribute should apply only to diff' '
'
+test_expect_success 'diff attribute and --no-ext-diff' '
+
+ git diff --no-ext-diff |
+ grep "^diff --git a/file b/file"
+
+'
+
test_expect_success 'no diff with -diff' '
echo >.gitattributes "file -diff" &&
git diff | grep Binary
@@ -104,7 +125,48 @@ echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file
test_expect_success 'force diff with "diff"' '
echo >.gitattributes "file diff" &&
git diff >actual &&
- test_cmp ../t4020/diff.NUL actual
+ test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual
+'
+
+test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
+ echo anotherfile > file2 &&
+ git add file2 &&
+ git commit -m "added 2nd file" &&
+ echo modified >file2 &&
+ GIT_EXTERNAL_DIFF=echo git diff
+'
+
+test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' '
+ touch file.ext &&
+ git add file.ext &&
+ echo with extension > file.ext &&
+ GIT_EXTERNAL_DIFF=echo git diff file.ext | grep ......_file\.ext &&
+ git update-index --force-remove file.ext &&
+ rm file.ext
+'
+
+echo "#!$SHELL_PATH" >fake-diff.sh
+cat >> fake-diff.sh <<\EOF
+cat $2 >> crlfed.txt
+EOF
+chmod a+x fake-diff.sh
+
+keep_only_cr () {
+ tr -dc '\015'
+}
+
+test_expect_success 'external diff with autocrlf = true' '
+ git 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' '
+ git add file &&
+ git update-index --assume-unchanged file &&
+ echo second >file &&
+ git diff --cached >actual &&
+ test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual
'
test_done
diff --git a/t/t4021-format-patch-numbered.sh b/t/t4021-format-patch-numbered.sh
index 43d64bbd82..709b3231ca 100755
--- a/t/t4021-format-patch-numbered.sh
+++ b/t/t4021-format-patch-numbered.sh
@@ -45,17 +45,22 @@ test_numbered() {
grep "^Subject: \[PATCH 2/2\]" $1
}
-test_expect_success 'Default: no numbered' '
+test_expect_success 'single patch defaults to no numbers' '
+ git format-patch --stdout HEAD~1 >patch0.single &&
+ test_single_no_numbered patch0.single
+'
+
+test_expect_success 'multiple patch defaults to numbered' '
- git format-patch --stdout HEAD~2 >patch0 &&
- test_no_numbered patch0
+ git format-patch --stdout HEAD~2 >patch0.multiple &&
+ test_numbered patch0.multiple
'
test_expect_success 'Use --numbered' '
- git format-patch --numbered --stdout HEAD~2 >patch1 &&
- test_numbered patch1
+ git format-patch --numbered --stdout HEAD~1 >patch1 &&
+ test_single_numbered patch1
'
@@ -81,6 +86,13 @@ test_expect_success 'format.numbered && --no-numbered' '
'
+test_expect_success 'format.numbered && --keep-subject' '
+
+ git format-patch --keep-subject --stdout HEAD^ >patch4a &&
+ grep "^Subject: Third" patch4a
+
+'
+
test_expect_success 'format.numbered = auto' '
git config format.numbered auto
@@ -103,4 +115,10 @@ test_expect_success 'format.numbered = auto && --no-numbered' '
'
+test_expect_success '--start-number && --numbered' '
+
+ git format-patch --start-number 3 --numbered --stdout HEAD~1 > patch8 &&
+ grep "^Subject: \[PATCH 3/3\]" patch8
+'
+
test_done
diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh
index bf996fc414..2a537a21e8 100755
--- a/t/t4022-diff-rewrite.sh
+++ b/t/t4022-diff-rewrite.sh
@@ -6,12 +6,12 @@ test_description='rewrite diff'
test_expect_success setup '
- cat ../../COPYING >test &&
+ cat "$TEST_DIRECTORY"/../COPYING >test &&
git add test &&
tr \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" \
- <../../COPYING >test
+ <"$TEST_DIRECTORY"/../COPYING >test
'
diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh
index 4dbfc6e8b7..9bdf6596d8 100755
--- a/t/t4023-diff-rename-typechange.sh
+++ b/t/t4023-diff-rename-typechange.sh
@@ -4,24 +4,30 @@ test_description='typechange rename detection'
. ./test-lib.sh
+if ! test_have_prereq SYMLINKS
+then
+ say 'Symbolic links not supported, skipping tests.'
+ test_done
+fi
+
test_expect_success setup '
rm -f foo bar &&
- cat ../../COPYING >foo &&
+ cat "$TEST_DIRECTORY"/../COPYING >foo &&
ln -s linklink bar &&
git add foo bar &&
git commit -a -m Initial &&
git tag one &&
rm -f foo bar &&
- cat ../../COPYING >bar &&
+ cat "$TEST_DIRECTORY"/../COPYING >bar &&
ln -s linklink foo &&
git add foo bar &&
git commit -a -m Second &&
git tag two &&
rm -f foo bar &&
- cat ../../COPYING >foo &&
+ cat "$TEST_DIRECTORY"/../COPYING >foo &&
git add foo &&
git commit -a -m Third &&
git tag three &&
@@ -35,15 +41,15 @@ test_expect_success setup '
# This is purely for sanity check
rm -f foo bar &&
- cat ../../COPYING >foo &&
- cat ../../Makefile >bar &&
+ cat "$TEST_DIRECTORY"/../COPYING >foo &&
+ cat "$TEST_DIRECTORY"/../Makefile >bar &&
git add foo bar &&
git commit -a -m Fifth &&
git tag five &&
rm -f foo bar &&
- cat ../../Makefile >foo &&
- cat ../../COPYING >bar &&
+ cat "$TEST_DIRECTORY"/../Makefile >foo &&
+ cat "$TEST_DIRECTORY"/../COPYING >bar &&
git add foo bar &&
git commit -a -m Sixth &&
git tag six
diff --git a/t/t4026-color.sh b/t/t4026-color.sh
index b61e5169f4..5ade44c043 100755
--- a/t/t4026-color.sh
+++ b/t/t4026-color.sh
@@ -66,4 +66,21 @@ test_expect_success 'extra character after attribute' '
invalid_color "dimX"
'
+test_expect_success 'unknown color slots are ignored (diff)' '
+ git config --unset diff.color.new
+ git config color.diff.nosuchslotwilleverbedefined white &&
+ git diff --color
+'
+
+test_expect_success 'unknown color slots are ignored (branch)' '
+ git config color.branch.nosuchslotwilleverbedefined white &&
+ git branch -a
+'
+
+test_expect_success 'unknown color slots are ignored (status)' '
+ git config color.status.nosuchslotwilleverbedefined white || exit
+ git status
+ case $? in 0|1) : ok ;; *) false ;; esac
+'
+
test_done
diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh
index 1fd3fb74d7..5cf8924b21 100755
--- a/t/t4027-diff-submodule.sh
+++ b/t/t4027-diff-submodule.sh
@@ -3,7 +3,7 @@
test_description='difference in submodules'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
_z40=0000000000000000000000000000000000000000
test_expect_success setup '
@@ -50,4 +50,50 @@ test_expect_success 'git diff-files --raw' '
test_cmp expect actual.files
'
+test_expect_success 'git diff (empty submodule dir)' '
+ : >empty &&
+ rm -rf sub/* sub/.git &&
+ git diff > actual.empty &&
+ test_cmp empty actual.empty
+'
+
+test_expect_success 'conflicted submodule setup' '
+
+ # 39 efs
+ c=fffffffffffffffffffffffffffffffffffffff
+ (
+ echo "000000 $_z40 0 sub"
+ echo "160000 1$c 1 sub"
+ echo "160000 2$c 2 sub"
+ echo "160000 3$c 3 sub"
+ ) | git update-index --index-info &&
+ echo >expect.nosub '\''diff --cc sub
+index 2ffffff,3ffffff..0000000
+--- a/sub
++++ b/sub
+@@@ -1,1 -1,1 +1,1 @@@
+- Subproject commit 2fffffffffffffffffffffffffffffffffffffff
+ -Subproject commit 3fffffffffffffffffffffffffffffffffffffff
+++Subproject commit 0000000000000000000000000000000000000000'\'' &&
+
+ hh=$(git rev-parse HEAD) &&
+ sed -e "s/$_z40/$hh/" expect.nosub >expect.withsub
+
+'
+
+test_expect_success 'combined (empty submodule)' '
+ rm -fr sub && mkdir sub &&
+ git diff >actual &&
+ test_cmp expect.nosub actual
+'
+
+test_expect_success 'combined (with submodule)' '
+ rm -fr sub &&
+ git clone --no-checkout . sub &&
+ git diff >actual &&
+ test_cmp expect.withsub actual
+'
+
+
+
test_done
diff --git a/t/t4029-diff-trailing-space.sh b/t/t4029-diff-trailing-space.sh
new file mode 100755
index 0000000000..3ccc237a8d
--- /dev/null
+++ b/t/t4029-diff-trailing-space.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Copyright (c) Jim Meyering
+#
+test_description='diff honors config option, diff.suppressBlankEmpty'
+
+. ./test-lib.sh
+
+cat <<\EOF > exp ||
+diff --git a/f b/f
+index 5f6a263..8cb8bae 100644
+--- a/f
++++ b/f
+@@ -1,2 +1,2 @@
+
+-x
++y
+EOF
+exit 1
+
+test_expect_success \
+ "$test_description" \
+ 'printf "\nx\n" > f &&
+ git add f &&
+ git commit -q -m. f &&
+ printf "\ny\n" > f &&
+ git config --bool diff.suppressBlankEmpty true &&
+ git diff f > actual &&
+ test_cmp exp actual &&
+ perl -i.bak -p -e "s/^\$/ /" exp &&
+ git config --bool diff.suppressBlankEmpty false &&
+ git diff f > actual &&
+ test_cmp exp actual &&
+ git config --bool --unset diff.suppressBlankEmpty &&
+ git diff f > actual &&
+ test_cmp exp actual
+ '
+
+test_done
diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh
new file mode 100755
index 0000000000..a3f0897a52
--- /dev/null
+++ b/t/t4030-diff-textconv.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+test_description='diff.*.textconv tests'
+. ./test-lib.sh
+
+find_diff() {
+ sed '1,/^index /d' | sed '/^-- $/,$d'
+}
+
+cat >expect.binary <<'EOF'
+Binary files a/file and b/file differ
+EOF
+
+cat >expect.text <<'EOF'
+--- a/file
++++ b/file
+@@ -1 +1,2 @@
+ 0
++1
+EOF
+
+cat >hexdump <<'EOF'
+#!/bin/sh
+perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1"
+EOF
+chmod +x hexdump
+
+test_expect_success 'setup binary file with history' '
+ printf "\\0\\n" >file &&
+ git add file &&
+ git commit -m one &&
+ printf "\\01\\n" >>file &&
+ git add file &&
+ git commit -m two
+'
+
+test_expect_success 'file is considered binary by porcelain' '
+ git diff HEAD^ HEAD >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.binary actual
+'
+
+test_expect_success 'file is considered binary by plumbing' '
+ git diff-tree -p HEAD^ HEAD >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.binary actual
+'
+
+test_expect_success 'setup textconv filters' '
+ echo file diff=foo >.gitattributes &&
+ git config diff.foo.textconv "$PWD"/hexdump &&
+ git config diff.fail.textconv false
+'
+
+test_expect_success 'diff produces text' '
+ git diff HEAD^ HEAD >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.text actual
+'
+
+test_expect_success 'diff-tree produces binary' '
+ git diff-tree -p HEAD^ HEAD >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.binary actual
+'
+
+test_expect_success 'log produces text' '
+ git log -1 -p >log &&
+ find_diff <log >actual &&
+ test_cmp expect.text actual
+'
+
+test_expect_success 'format-patch produces binary' '
+ git format-patch --no-binary --stdout HEAD^ >patch &&
+ find_diff <patch >actual &&
+ test_cmp expect.binary actual
+'
+
+test_expect_success 'status -v produces text' '
+ git reset --soft HEAD^ &&
+ git status -v >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.text actual &&
+ git reset --soft HEAD@{1}
+'
+
+cat >expect.stat <<'EOF'
+ file | Bin 2 -> 4 bytes
+ 1 files changed, 0 insertions(+), 0 deletions(-)
+EOF
+test_expect_success 'diffstat does not run textconv' '
+ echo file diff=fail >.gitattributes &&
+ git diff --stat HEAD^ HEAD >actual &&
+ test_cmp expect.stat actual
+'
+# restore working setup
+echo file diff=foo >.gitattributes
+
+cat >expect.typechange <<'EOF'
+--- a/file
++++ /dev/null
+@@ -1,2 +0,0 @@
+-0
+-1
+diff --git a/file b/file
+new file mode 120000
+index 0000000..67be421
+--- /dev/null
++++ b/file
+@@ -0,0 +1 @@
++frotz
+\ No newline at end of file
+EOF
+# make a symlink the hard way that works on symlink-challenged file systems
+test_expect_success 'textconv does not act on symlinks' '
+ printf frotz > file &&
+ git add file &&
+ git ls-files -s | sed -e s/100644/120000/ |
+ git update-index --index-info &&
+ git commit -m typechange &&
+ git show >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.typechange actual
+'
+
+test_done
diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh
new file mode 100755
index 0000000000..a894c60622
--- /dev/null
+++ b/t/t4031-diff-rewrite-binary.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+test_description='rewrite diff on binary file'
+
+. ./test-lib.sh
+
+# We must be large enough to meet the MINIMUM_BREAK_SIZE
+# requirement.
+make_file() {
+ # common first line to help identify rewrite versus regular diff
+ printf "=\n" >file
+ for i in 1 2 3 4 5 6 7 8 9 10
+ do
+ for j in 1 2 3 4 5 6 7 8 9
+ do
+ for k in 1 2 3 4 5
+ do
+ printf "$1\n"
+ done
+ done
+ done >>file
+}
+
+test_expect_success 'create binary file with changes' '
+ make_file "\\0" &&
+ git add file &&
+ make_file "\\01"
+'
+
+test_expect_success 'vanilla diff is binary' '
+ git diff >diff &&
+ grep "Binary files a/file and b/file differ" diff
+'
+
+test_expect_success 'rewrite diff is binary' '
+ git diff -B >diff &&
+ grep "dissimilarity index" diff &&
+ grep "Binary files a/file and b/file differ" diff
+'
+
+test_expect_success 'rewrite diff can show binary patch' '
+ git diff -B --binary >diff &&
+ grep "dissimilarity index" diff &&
+ grep "GIT binary patch" diff
+'
+
+{
+ echo "#!$SHELL_PATH"
+ cat <<'EOF'
+perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1"
+EOF
+} >dump
+chmod +x dump
+
+test_expect_success 'setup textconv' '
+ echo file diff=foo >.gitattributes &&
+ git config diff.foo.textconv "$PWD"/dump
+'
+
+test_expect_success 'rewrite diff respects textconv' '
+ git diff -B >diff &&
+ grep "dissimilarity index" diff &&
+ grep "^-61" diff &&
+ grep "^-0" diff
+'
+
+test_done
diff --git a/t/t4032-diff-inter-hunk-context.sh b/t/t4032-diff-inter-hunk-context.sh
new file mode 100755
index 0000000000..e4e3e28fc7
--- /dev/null
+++ b/t/t4032-diff-inter-hunk-context.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+test_description='diff hunk fusing'
+
+. ./test-lib.sh
+
+f() {
+ echo $1
+ i=1
+ while test $i -le $2
+ do
+ echo $i
+ i=$(expr $i + 1)
+ done
+ echo $3
+}
+
+t() {
+ case $# in
+ 4) hunks=$4; cmd="diff -U$3";;
+ 5) hunks=$5; cmd="diff -U$3 --inter-hunk-context=$4";;
+ esac
+ label="$cmd, $1 common $2"
+ file=f$1
+ expected=expected.$file.$3.$hunks
+
+ if ! test -f $file
+ then
+ f A $1 B >$file
+ git add $file
+ git commit -q -m. $file
+ f X $1 Y >$file
+ fi
+
+ test_expect_success "$label: count hunks ($hunks)" "
+ test $(git $cmd $file | grep '^@@ ' | wc -l) = $hunks
+ "
+
+ test -f $expected &&
+ test_expect_success "$label: check output" "
+ git $cmd $file | grep -v '^index ' >actual &&
+ test_cmp $expected actual
+ "
+}
+
+cat <<EOF >expected.f1.0.1 || exit 1
+diff --git a/f1 b/f1
+--- a/f1
++++ b/f1
+@@ -1,3 +1,3 @@
+-A
++X
+ 1
+-B
++Y
+EOF
+
+cat <<EOF >expected.f1.0.2 || exit 1
+diff --git a/f1 b/f1
+--- a/f1
++++ b/f1
+@@ -1 +1 @@
+-A
++X
+@@ -3 +3 @@ A
+-B
++Y
+EOF
+
+# common lines ctx intrctx hunks
+t 1 line 0 2
+t 1 line 0 0 2
+t 1 line 0 1 1
+t 1 line 0 2 1
+t 1 line 1 1
+
+t 2 lines 0 2
+t 2 lines 0 0 2
+t 2 lines 0 1 2
+t 2 lines 0 2 1
+t 2 lines 1 1
+
+t 3 lines 1 2
+t 3 lines 1 0 2
+t 3 lines 1 1 1
+t 3 lines 1 2 1
+
+t 9 lines 3 2
+t 9 lines 3 2 2
+t 9 lines 3 3 1
+
+test_done
diff --git a/t/t4033-diff-patience.sh b/t/t4033-diff-patience.sh
new file mode 100755
index 0000000000..1eb14989df
--- /dev/null
+++ b/t/t4033-diff-patience.sh
@@ -0,0 +1,168 @@
+#!/bin/sh
+
+test_description='patience diff algorithm'
+
+. ./test-lib.sh
+
+cat >file1 <<\EOF
+#include <stdio.h>
+
+// Frobs foo heartily
+int frobnitz(int foo)
+{
+ int i;
+ for(i = 0; i < 10; i++)
+ {
+ printf("Your answer is: ");
+ printf("%d\n", foo);
+ }
+}
+
+int fact(int n)
+{
+ if(n > 1)
+ {
+ return fact(n-1) * n;
+ }
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ frobnitz(fact(10));
+}
+EOF
+
+cat >file2 <<\EOF
+#include <stdio.h>
+
+int fib(int n)
+{
+ if(n > 2)
+ {
+ return fib(n-1) + fib(n-2);
+ }
+ return 1;
+}
+
+// Frobs foo heartily
+int frobnitz(int foo)
+{
+ int i;
+ for(i = 0; i < 10; i++)
+ {
+ printf("%d\n", foo);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ frobnitz(fib(10));
+}
+EOF
+
+cat >expect <<\EOF
+diff --git a/file1 b/file2
+index 6faa5a3..e3af329 100644
+--- a/file1
++++ b/file2
+@@ -1,26 +1,25 @@
+ #include <stdio.h>
+
++int fib(int n)
++{
++ if(n > 2)
++ {
++ return fib(n-1) + fib(n-2);
++ }
++ return 1;
++}
++
+ // Frobs foo heartily
+ int frobnitz(int foo)
+ {
+ int i;
+ for(i = 0; i < 10; i++)
+ {
+- printf("Your answer is: ");
+ printf("%d\n", foo);
+ }
+ }
+
+-int fact(int n)
+-{
+- if(n > 1)
+- {
+- return fact(n-1) * n;
+- }
+- return 1;
+-}
+-
+ int main(int argc, char **argv)
+ {
+- frobnitz(fact(10));
++ frobnitz(fib(10));
+ }
+EOF
+
+test_expect_success 'patience diff' '
+
+ test_must_fail git diff --no-index --patience file1 file2 > output &&
+ test_cmp expect output
+
+'
+
+test_expect_success 'patience diff output is valid' '
+
+ mv file2 expect &&
+ git apply < output &&
+ test_cmp expect file2
+
+'
+
+cat >uniq1 <<\EOF
+1
+2
+3
+4
+5
+6
+EOF
+
+cat >uniq2 <<\EOF
+a
+b
+c
+d
+e
+f
+EOF
+
+cat >expect <<\EOF
+diff --git a/uniq1 b/uniq2
+index b414108..0fdf397 100644
+--- a/uniq1
++++ b/uniq2
+@@ -1,6 +1,6 @@
+-1
+-2
+-3
+-4
+-5
+-6
++a
++b
++c
++d
++e
++f
+EOF
+
+test_expect_success 'completely different files' '
+
+ test_must_fail git diff --no-index --patience uniq1 uniq2 > output &&
+ test_cmp expect output
+
+'
+
+test_done
diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh
new file mode 100755
index 0000000000..1c21276c55
--- /dev/null
+++ b/t/t4034-diff-words.sh
@@ -0,0 +1,222 @@
+#!/bin/sh
+
+test_description='word diff colors'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+ git config diff.color.old red
+ git config diff.color.new green
+ git config diff.color.func magenta
+
+'
+
+decrypt_color () {
+ sed \
+ -e 's/.\[1m/<WHITE>/g' \
+ -e 's/.\[31m/<RED>/g' \
+ -e 's/.\[32m/<GREEN>/g' \
+ -e 's/.\[35m/<MAGENTA>/g' \
+ -e 's/.\[36m/<BROWN>/g' \
+ -e 's/.\[m/<RESET>/g'
+}
+
+word_diff () {
+ test_must_fail git diff --no-index "$@" pre post > output &&
+ decrypt_color < output > output.decrypted &&
+ test_cmp expect output.decrypted
+}
+
+cat > pre <<\EOF
+h(4)
+
+a = b + c
+EOF
+
+cat > post <<\EOF
+h(4),hh[44]
+
+a = b + c
+
+aa = a
+
+aeff = aeff * ( aaa )
+EOF
+
+cat > expect <<\EOF
+<WHITE>diff --git a/pre b/post<RESET>
+<WHITE>index 330b04f..5ed8eff 100644<RESET>
+<WHITE>--- a/pre<RESET>
+<WHITE>+++ b/post<RESET>
+<BROWN>@@ -1,3 +1,7 @@<RESET>
+<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET>
+
+a = b + c<RESET>
+
+<GREEN>aa = a<RESET>
+
+<GREEN>aeff = aeff * ( aaa )<RESET>
+EOF
+
+test_expect_success 'word diff with runs of whitespace' '
+
+ word_diff --color-words
+
+'
+
+cat > expect <<\EOF
+<WHITE>diff --git a/pre b/post<RESET>
+<WHITE>index 330b04f..5ed8eff 100644<RESET>
+<WHITE>--- a/pre<RESET>
+<WHITE>+++ b/post<RESET>
+<BROWN>@@ -1 +1 @@<RESET>
+<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET>
+<BROWN>@@ -3,0 +4,4 @@<RESET> <RESET><MAGENTA>a = b + c<RESET>
+
+<GREEN>aa = a<RESET>
+
+<GREEN>aeff = aeff * ( aaa )<RESET>
+EOF
+
+test_expect_success 'word diff without context' '
+
+ word_diff --color-words --unified=0
+
+'
+
+cat > expect <<\EOF
+<WHITE>diff --git a/pre b/post<RESET>
+<WHITE>index 330b04f..5ed8eff 100644<RESET>
+<WHITE>--- a/pre<RESET>
+<WHITE>+++ b/post<RESET>
+<BROWN>@@ -1,3 +1,7 @@<RESET>
+h(4),<GREEN>hh<RESET>[44]
+
+a = b + c<RESET>
+
+<GREEN>aa = a<RESET>
+
+<GREEN>aeff = aeff * ( aaa<RESET> )
+EOF
+cp expect expect.letter-runs-are-words
+
+test_expect_success 'word diff with a regular expression' '
+
+ word_diff --color-words="[a-z]+"
+
+'
+
+test_expect_success 'set a diff driver' '
+ git config diff.testdriver.wordRegex "[^[:space:]]" &&
+ cat <<EOF > .gitattributes
+pre diff=testdriver
+post diff=testdriver
+EOF
+'
+
+test_expect_success 'option overrides .gitattributes' '
+
+ word_diff --color-words="[a-z]+"
+
+'
+
+cat > expect <<\EOF
+<WHITE>diff --git a/pre b/post<RESET>
+<WHITE>index 330b04f..5ed8eff 100644<RESET>
+<WHITE>--- a/pre<RESET>
+<WHITE>+++ b/post<RESET>
+<BROWN>@@ -1,3 +1,7 @@<RESET>
+h(4)<GREEN>,hh[44]<RESET>
+
+a = b + c<RESET>
+
+<GREEN>aa = a<RESET>
+
+<GREEN>aeff = aeff * ( aaa )<RESET>
+EOF
+cp expect expect.non-whitespace-is-word
+
+test_expect_success 'use regex supplied by driver' '
+
+ word_diff --color-words
+
+'
+
+test_expect_success 'set diff.wordRegex option' '
+ git config diff.wordRegex "[[:alnum:]]+"
+'
+
+cp expect.letter-runs-are-words expect
+
+test_expect_success 'command-line overrides config' '
+ word_diff --color-words="[a-z]+"
+'
+
+cp expect.non-whitespace-is-word expect
+
+test_expect_success '.gitattributes override config' '
+ word_diff --color-words
+'
+
+test_expect_success 'remove diff driver regex' '
+ git config --unset diff.testdriver.wordRegex
+'
+
+cat > expect <<\EOF
+<WHITE>diff --git a/pre b/post<RESET>
+<WHITE>index 330b04f..5ed8eff 100644<RESET>
+<WHITE>--- a/pre<RESET>
+<WHITE>+++ b/post<RESET>
+<BROWN>@@ -1,3 +1,7 @@<RESET>
+h(4),<GREEN>hh[44<RESET>]
+
+a = b + c<RESET>
+
+<GREEN>aa = a<RESET>
+
+<GREEN>aeff = aeff * ( aaa<RESET> )
+EOF
+
+test_expect_success 'use configured regex' '
+ word_diff --color-words
+'
+
+echo 'aaa (aaa)' > pre
+echo 'aaa (aaa) aaa' > post
+
+cat > expect <<\EOF
+<WHITE>diff --git a/pre b/post<RESET>
+<WHITE>index c29453b..be22f37 100644<RESET>
+<WHITE>--- a/pre<RESET>
+<WHITE>+++ b/post<RESET>
+<BROWN>@@ -1 +1 @@<RESET>
+aaa (aaa) <GREEN>aaa<RESET>
+EOF
+
+test_expect_success 'test parsing words for newline' '
+
+ word_diff --color-words="a+"
+
+
+'
+
+echo '(:' > pre
+echo '(' > post
+
+cat > expect <<\EOF
+<WHITE>diff --git a/pre b/post<RESET>
+<WHITE>index 289cb9d..2d06f37 100644<RESET>
+<WHITE>--- a/pre<RESET>
+<WHITE>+++ b/post<RESET>
+<BROWN>@@ -1 +1 @@<RESET>
+(<RED>:<RESET>
+EOF
+
+test_expect_success 'test when words are only removed at the end' '
+
+ word_diff --color-words=.
+
+'
+
+test_done
diff --git a/t/t4017-quiet.sh b/t/t4035-diff-quiet.sh
index e747e84227..e747e84227 100755
--- a/t/t4017-quiet.sh
+++ b/t/t4035-diff-quiet.sh
diff --git a/t/t4021-format-patch-signer-mime.sh b/t/t4036-format-patch-signer-mime.sh
index ba43f18549..ba43f18549 100755
--- a/t/t4021-format-patch-signer-mime.sh
+++ b/t/t4036-format-patch-signer-mime.sh
diff --git a/t/t4037-diff-r-t-dirs.sh b/t/t4037-diff-r-t-dirs.sh
new file mode 100755
index 0000000000..f5ce3b29a2
--- /dev/null
+++ b/t/t4037-diff-r-t-dirs.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+test_description='diff -r -t shows directory additions and deletions'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ mkdir dc dr dt &&
+ >dc/1 &&
+ >dr/2 &&
+ >dt/3 &&
+ >fc &&
+ >fr &&
+ >ft &&
+ git add . &&
+ test_tick &&
+ git commit -m initial &&
+
+ rm -fr dt dr ft fr &&
+ mkdir da ft &&
+ for p in dc/1 da/4 dt ft/5 fc
+ do
+ echo hello >$p || exit
+ done &&
+ git add -u &&
+ git add . &&
+ test_tick &&
+ git commit -m second
+'
+
+cat >expect <<\EOF
+A da
+A da/4
+M dc
+M dc/1
+D dr
+D dr/2
+A dt
+D dt
+D dt/3
+M fc
+D fr
+D ft
+A ft
+A ft/5
+EOF
+
+test_expect_success verify '
+ git diff-tree -r -t --name-status HEAD^ HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
new file mode 100755
index 0000000000..2cf7e01ac2
--- /dev/null
+++ b/t/t4038-diff-combined.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+test_description='combined diff'
+
+. ./test-lib.sh
+
+setup_helper () {
+ one=$1 branch=$2 side=$3 &&
+
+ git branch $side $branch &&
+ for l in $one two three fyra
+ do
+ echo $l
+ done >file &&
+ git add file &&
+ test_tick &&
+ git commit -m $branch &&
+ git checkout $side &&
+ for l in $one two three quatro
+ do
+ echo $l
+ done >file &&
+ git add file &&
+ test_tick &&
+ git commit -m $side &&
+ test_must_fail git merge $branch &&
+ for l in $one three four
+ do
+ echo $l
+ done >file &&
+ git add file &&
+ test_tick &&
+ git commit -m "merge $branch into $side"
+}
+
+verify_helper () {
+ it=$1 &&
+
+ # Ignore lines that were removed only from the other parent
+ sed -e '
+ 1,/^@@@/d
+ /^ -/d
+ s/^\(.\)./\1/
+ ' "$it" >"$it.actual.1" &&
+ sed -e '
+ 1,/^@@@/d
+ /^- /d
+ s/^.\(.\)/\1/
+ ' "$it" >"$it.actual.2" &&
+
+ git diff "$it^" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.1" &&
+ test_cmp "$it.expect.1" "$it.actual.1" &&
+
+ git diff "$it^2" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.2" &&
+ test_cmp "$it.expect.2" "$it.actual.2"
+}
+
+test_expect_success setup '
+ >file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+
+ git branch withone &&
+ git branch sansone &&
+
+ git checkout withone &&
+ setup_helper one withone sidewithone &&
+
+ git checkout sansone &&
+ setup_helper "" sansone sidesansone
+'
+
+test_expect_success 'check combined output (1)' '
+ git show sidewithone -- >sidewithone &&
+ verify_helper sidewithone
+'
+
+test_expect_failure 'check combined output (2)' '
+ git show sidesansone -- >sidesansone &&
+ verify_helper sidesansone
+'
+
+test_done
diff --git a/t/t4039-diff-assume-unchanged.sh b/t/t4039-diff-assume-unchanged.sh
new file mode 100755
index 0000000000..9d9498bd95
--- /dev/null
+++ b/t/t4039-diff-assume-unchanged.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+test_description='diff with assume-unchanged entries'
+
+. ./test-lib.sh
+
+# external diff has been tested in t4020-diff-external.sh
+
+test_expect_success 'setup' '
+ echo zero > zero &&
+ git add zero &&
+ git commit -m zero &&
+ echo one > one &&
+ echo two > two &&
+ git add one two &&
+ git commit -m onetwo &&
+ git update-index --assume-unchanged one &&
+ echo borked >> one &&
+ test "$(git ls-files -v one)" = "h one"
+'
+
+test_expect_success 'diff-index does not examine assume-unchanged entries' '
+ git diff-index HEAD^ -- one | grep -q 5626abf0f72e58d7a153368ba57db4c673c0e171
+'
+
+test_expect_success 'diff-files does not examine assume-unchanged entries' '
+ rm one &&
+ test -z "$(git diff-files -- one)"
+'
+
+test_done
diff --git a/t/t4041-diff-submodule.sh b/t/t4041-diff-submodule.sh
new file mode 100755
index 0000000000..5bb4fed3f5
--- /dev/null
+++ b/t/t4041-diff-submodule.sh
@@ -0,0 +1,260 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin
+#
+
+test_description='Support for verbose submodule differences in git diff
+
+This test tries to verify the sanity of the --submodule option of git diff.
+'
+
+. ./test-lib.sh
+
+add_file () {
+ sm=$1
+ shift
+ owd=$(pwd)
+ cd "$sm"
+ for name; do
+ echo "$name" > "$name" &&
+ git add "$name" &&
+ test_tick &&
+ git commit -m "Add $name"
+ done >/dev/null
+ git rev-parse --verify HEAD | cut -c1-7
+ cd "$owd"
+}
+commit_file () {
+ test_tick &&
+ git commit "$@" -m "Commit $*" >/dev/null
+}
+
+test_create_repo sm1 &&
+add_file . foo >/dev/null
+
+head1=$(add_file sm1 foo1 foo2)
+
+test_expect_success 'added submodule' "
+ git add sm1 &&
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 0000000...$head1 (new submodule)
+EOF
+"
+
+commit_file sm1 &&
+head2=$(add_file sm1 foo3)
+
+test_expect_success 'modified submodule(forward)' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head1..$head2:
+ > Add foo3
+EOF
+"
+
+test_expect_success 'modified submodule(forward)' "
+ git diff --submodule=log >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head1..$head2:
+ > Add foo3
+EOF
+"
+
+test_expect_success 'modified submodule(forward) --submodule' "
+ git diff --submodule >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head1..$head2:
+ > Add foo3
+EOF
+"
+
+fullhead1=$(cd sm1; git rev-list --max-count=1 $head1)
+fullhead2=$(cd sm1; git rev-list --max-count=1 $head2)
+test_expect_success 'modified submodule(forward) --submodule=short' "
+ git diff --submodule=short >actual &&
+ diff actual - <<-EOF
+diff --git a/sm1 b/sm1
+index $head1..$head2 160000
+--- a/sm1
++++ b/sm1
+@@ -1 +1 @@
+-Subproject commit $fullhead1
++Subproject commit $fullhead2
+EOF
+"
+
+commit_file sm1 &&
+cd sm1 &&
+git reset --hard HEAD~2 >/dev/null &&
+head3=$(git rev-parse --verify HEAD | cut -c1-7) &&
+cd ..
+
+test_expect_success 'modified submodule(backward)' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head2..$head3 (rewind):
+ < Add foo3
+ < Add foo2
+EOF
+"
+
+head4=$(add_file sm1 foo4 foo5) &&
+head4_full=$(GIT_DIR=sm1/.git git rev-parse --verify HEAD)
+test_expect_success 'modified submodule(backward and forward)' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head2...$head4:
+ > Add foo5
+ > Add foo4
+ < Add foo3
+ < Add foo2
+EOF
+"
+
+commit_file sm1 &&
+mv sm1 sm1-bak &&
+echo sm1 >sm1 &&
+head5=$(git hash-object sm1 | cut -c1-7) &&
+git add sm1 &&
+rm -f sm1 &&
+mv sm1-bak sm1
+
+test_expect_success 'typechanged submodule(submodule->blob), --cached' "
+ git diff --submodule=log --cached >actual &&
+ diff actual - <<-EOF
+Submodule sm1 41fbea9...0000000 (submodule deleted)
+diff --git a/sm1 b/sm1
+new file mode 100644
+index 0000000..9da5fb8
+--- /dev/null
++++ b/sm1
+@@ -0,0 +1 @@
++sm1
+EOF
+"
+
+test_expect_success 'typechanged submodule(submodule->blob)' "
+ git diff --submodule=log >actual &&
+ diff actual - <<-EOF
+diff --git a/sm1 b/sm1
+deleted file mode 100644
+index 9da5fb8..0000000
+--- a/sm1
++++ /dev/null
+@@ -1 +0,0 @@
+-sm1
+Submodule sm1 0000000...$head4 (new submodule)
+EOF
+"
+
+rm -rf sm1 &&
+git checkout-index sm1
+test_expect_success 'typechanged submodule(submodule->blob)' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head4...0000000 (submodule deleted)
+diff --git a/sm1 b/sm1
+new file mode 100644
+index 0000000..$head5
+--- /dev/null
++++ b/sm1
+@@ -0,0 +1 @@
++sm1
+EOF
+"
+
+rm -f sm1 &&
+test_create_repo sm1 &&
+head6=$(add_file sm1 foo6 foo7)
+fullhead6=$(cd sm1; git rev-list --max-count=1 $head6)
+test_expect_success 'nonexistent commit' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head4...$head6 (commits not present)
+EOF
+"
+
+commit_file
+test_expect_success 'typechanged submodule(blob->submodule)' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+diff --git a/sm1 b/sm1
+deleted file mode 100644
+index $head5..0000000
+--- a/sm1
++++ /dev/null
+@@ -1 +0,0 @@
+-sm1
+Submodule sm1 0000000...$head6 (new submodule)
+EOF
+"
+
+commit_file sm1 &&
+rm -rf sm1
+test_expect_success 'deleted submodule' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6...0000000 (submodule deleted)
+EOF
+"
+
+test_create_repo sm2 &&
+head7=$(add_file sm2 foo8 foo9) &&
+git add sm2
+
+test_expect_success 'multiple submodules' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6...0000000 (submodule deleted)
+Submodule sm2 0000000...$head7 (new submodule)
+EOF
+"
+
+test_expect_success 'path filter' "
+ git diff-index -p --submodule=log HEAD sm2 >actual &&
+ diff actual - <<-EOF
+Submodule sm2 0000000...$head7 (new submodule)
+EOF
+"
+
+commit_file sm2
+test_expect_success 'given commit' "
+ git diff-index -p --submodule=log HEAD^ >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6...0000000 (submodule deleted)
+Submodule sm2 0000000...$head7 (new submodule)
+EOF
+"
+
+test_expect_success 'given commit --submodule' "
+ git diff-index -p --submodule HEAD^ >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6...0000000 (submodule deleted)
+Submodule sm2 0000000...$head7 (new submodule)
+EOF
+"
+
+fullhead7=$(cd sm2; git rev-list --max-count=1 $head7)
+
+test_expect_success 'given commit --submodule=short' "
+ git diff-index -p --submodule=short HEAD^ >actual &&
+ diff actual - <<-EOF
+diff --git a/sm1 b/sm1
+deleted file mode 160000
+index $head6..0000000
+--- a/sm1
++++ /dev/null
+@@ -1 +0,0 @@
+-Subproject commit $fullhead6
+diff --git a/sm2 b/sm2
+new file mode 160000
+index 0000000..$head7
+--- /dev/null
++++ b/sm2
+@@ -0,0 +1 @@
++Subproject commit $fullhead7
+EOF
+"
+
+test_done
diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
index 435f65b370..9b433de836 100755
--- a/t/t4100-apply-stat.sh
+++ b/t/t4100-apply-stat.sh
@@ -3,44 +3,38 @@
# Copyright (c) 2005 Junio C Hamano
#
-test_description='git apply --stat --summary test.
+test_description='git apply --stat --summary test, with --recount
'
. ./test-lib.sh
-test_expect_success \
- 'rename' \
- 'git apply --stat --summary <../t4100/t-apply-1.patch >current &&
- git diff ../t4100/t-apply-1.expect current'
-
-test_expect_success \
- 'copy' \
- 'git apply --stat --summary <../t4100/t-apply-2.patch >current &&
- git diff ../t4100/t-apply-2.expect current'
-
-test_expect_success \
- 'rewrite' \
- 'git apply --stat --summary <../t4100/t-apply-3.patch >current &&
- git diff ../t4100/t-apply-3.expect current'
-
-test_expect_success \
- 'mode' \
- 'git apply --stat --summary <../t4100/t-apply-4.patch >current &&
- git diff ../t4100/t-apply-4.expect current'
-
-test_expect_success \
- 'non git' \
- 'git apply --stat --summary <../t4100/t-apply-5.patch >current &&
- git diff ../t4100/t-apply-5.expect current'
-
-test_expect_success \
- 'non git' \
- 'git apply --stat --summary <../t4100/t-apply-6.patch >current &&
- git diff ../t4100/t-apply-6.expect current'
-
-test_expect_success \
- 'non git' \
- 'git apply --stat --summary <../t4100/t-apply-7.patch >current &&
- git diff ../t4100/t-apply-7.expect current'
+UNC='s/^\(@@ -[1-9][0-9]*\),[0-9]* \(+[1-9][0-9]*\),[0-9]* @@/\1,999 \2,999 @@/'
+
+num=0
+while read title
+do
+ num=$(( $num + 1 ))
+ test_expect_success "$title" '
+ git apply --stat --summary \
+ <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" >current &&
+ test_cmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current
+ '
+
+ test_expect_success "$title with recount" '
+ sed -e "$UNC" <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" |
+ git apply --recount --stat --summary >current &&
+ test_cmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current
+ '
+done <<\EOF
+rename
+copy
+rewrite
+mode
+non git (1)
+non git (2)
+non git (3)
+incomplete (1)
+incomplete (2)
+EOF
test_done
diff --git a/t/t4100/t-apply-8.expect b/t/t4100/t-apply-8.expect
new file mode 100644
index 0000000000..eef7f2e65c
--- /dev/null
+++ b/t/t4100/t-apply-8.expect
@@ -0,0 +1,2 @@
+ t/t4100-apply-stat.sh | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/t/t4100/t-apply-8.patch b/t/t4100/t-apply-8.patch
new file mode 100644
index 0000000000..5ca13e6594
--- /dev/null
+++ b/t/t4100/t-apply-8.patch
@@ -0,0 +1,11 @@
+diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
+index be837bb..0798c64 100755
+--- a/t/t4100-apply-stat.sh
++++ b/t/t4100-apply-stat.sh
+@@ -35,4 +35,4 @@ non git (2)
+ non git (3)
+ EOF
+
+-test_done
++test_done
+\ No newline at end of file
diff --git a/t/t4100/t-apply-9.expect b/t/t4100/t-apply-9.expect
new file mode 100644
index 0000000000..eef7f2e65c
--- /dev/null
+++ b/t/t4100/t-apply-9.expect
@@ -0,0 +1,2 @@
+ t/t4100-apply-stat.sh | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/t/t4100/t-apply-9.patch b/t/t4100/t-apply-9.patch
new file mode 100644
index 0000000000..875d57d567
--- /dev/null
+++ b/t/t4100/t-apply-9.patch
@@ -0,0 +1,11 @@
+diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
+index 0798c64..be837bb 100755
+--- a/t/t4100-apply-stat.sh
++++ b/t/t4100-apply-stat.sh
+@@ -35,4 +35,4 @@ non git (2)
+ non git (3)
+ EOF
+
+-test_done
+\ No newline at end of file
++test_done
diff --git a/t/t4101-apply-nonl.sh b/t/t4101-apply-nonl.sh
index da8abcf364..e3443d004d 100755
--- a/t/t4101-apply-nonl.sh
+++ b/t/t4101-apply-nonl.sh
@@ -21,9 +21,10 @@ do
do
test $i -eq $j && continue
cat frotz.$i >frotz
- test_expect_success \
- "apply diff between $i and $j" \
- "git apply <../t4101/diff.$i-$j && diff frotz.$j frotz"
+ test_expect_success "apply diff between $i and $j" '
+ git apply <"$TEST_DIRECTORY"/t4101/diff.$i-$j &&
+ test_cmp frotz.$j frotz
+ '
done
done
diff --git a/t/t4102-apply-rename.sh b/t/t4102-apply-rename.sh
index d42abff1ad..1597965241 100755
--- a/t/t4102-apply-rename.sh
+++ b/t/t4102-apply-rename.sh
@@ -31,14 +31,16 @@ test_expect_success setup \
test_expect_success apply \
'git apply --index --stat --summary --apply test-patch'
-if [ "$(git config --get core.filemode)" = false ]
+if test "$(git config --bool core.filemode)" = false
then
say 'filemode disabled on the filesystem'
else
- test_expect_success validate \
- 'test -f bar && ls -l bar | grep "^-..x......"'
+ test_set_prereq FILEMODE
fi
+test_expect_success FILEMODE validate \
+ 'test -f bar && ls -l bar | grep "^-..x......"'
+
test_expect_success 'apply reverse' \
'git apply -R --index --stat --summary --apply test-patch &&
test "$(cat foo)" = "This is foo"'
diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh
index 1b58233da6..ad4cc1a757 100755
--- a/t/t4103-apply-binary.sh
+++ b/t/t4103-apply-binary.sh
@@ -21,16 +21,16 @@ cat file1 >file2
cat file1 >file4
git update-index --add --remove file1 file2 file4
-git-commit -m 'Initial Version' 2>/dev/null
+git commit -m 'Initial Version' 2>/dev/null
-git-checkout -b binary
+git checkout -b binary
perl -pe 'y/x/\000/' <file1 >file3
cat file3 >file4
git add file2
perl -pe 'y/\000/v/' <file3 >file1
rm -f file2
git update-index --add --remove file1 file2 file3 file4
-git-commit -m 'Second Version'
+git commit -m 'Second Version'
git diff-tree -p master binary >B.diff
git diff-tree -p -C master binary >C.diff
@@ -39,64 +39,64 @@ git diff-tree -p --binary master binary >BF.diff
git diff-tree -p --binary -C master binary >CF.diff
test_expect_success 'stat binary diff -- should not fail.' \
- 'git-checkout master
+ 'git checkout master
git apply --stat --summary B.diff'
test_expect_success 'stat binary diff (copy) -- should not fail.' \
- 'git-checkout master
+ 'git checkout master
git apply --stat --summary C.diff'
test_expect_success 'check binary diff -- should fail.' \
- 'git-checkout master &&
- ! git apply --check B.diff'
+ 'git checkout master &&
+ test_must_fail git apply --check B.diff'
test_expect_success 'check binary diff (copy) -- should fail.' \
- 'git-checkout master &&
- ! git apply --check C.diff'
+ 'git checkout master &&
+ test_must_fail git apply --check C.diff'
test_expect_success \
'check incomplete binary diff with replacement -- should fail.' '
- git-checkout master &&
- ! git apply --check --allow-binary-replacement B.diff
+ git checkout master &&
+ test_must_fail git apply --check --allow-binary-replacement B.diff
'
test_expect_success \
'check incomplete binary diff with replacement (copy) -- should fail.' '
- git-checkout master &&
- ! git apply --check --allow-binary-replacement C.diff
+ git checkout master &&
+ test_must_fail git apply --check --allow-binary-replacement C.diff
'
test_expect_success 'check binary diff with replacement.' \
- 'git-checkout master
+ 'git checkout master
git apply --check --allow-binary-replacement BF.diff'
test_expect_success 'check binary diff with replacement (copy).' \
- 'git-checkout master
+ 'git checkout master
git apply --check --allow-binary-replacement CF.diff'
# Now we start applying them.
do_reset () {
rm -f file? &&
- git-reset --hard &&
- git-checkout -f master
+ git reset --hard &&
+ git checkout -f master
}
test_expect_success 'apply binary diff -- should fail.' \
'do_reset &&
- ! git apply B.diff'
+ test_must_fail git apply B.diff'
test_expect_success 'apply binary diff -- should fail.' \
'do_reset &&
- ! git apply --index B.diff'
+ test_must_fail git apply --index B.diff'
test_expect_success 'apply binary diff (copy) -- should fail.' \
'do_reset &&
- ! git apply C.diff'
+ test_must_fail git apply C.diff'
test_expect_success 'apply binary diff (copy) -- should fail.' \
'do_reset &&
- ! git apply --index C.diff'
+ test_must_fail git apply --index C.diff'
test_expect_success 'apply binary diff without replacement.' \
'do_reset &&
diff --git a/t/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh
index 43943ab8ca..0e3ce3611d 100755
--- a/t/t4104-apply-boundary.sh
+++ b/t/t4104-apply-boundary.sh
@@ -27,6 +27,15 @@ test_expect_success setup '
git diff victim >add-a-patch.with &&
git diff --unified=0 >add-a-patch.without &&
+ : insert at line two
+ for i in b a '"$L"' y
+ do
+ echo $i
+ done >victim &&
+ cat victim >insert-a-expect &&
+ git diff victim >insert-a-patch.with &&
+ git diff --unified=0 >insert-a-patch.without &&
+
: modify at the head
for i in a '"$L"' y
do
@@ -55,7 +64,7 @@ test_expect_success setup '
git diff --unified=0 >add-z-patch.without &&
: modify at the tail
- for i in a '"$L"' y
+ for i in b '"$L"' z
do
echo $i
done >victim &&
@@ -81,7 +90,7 @@ do
with) u= ;;
without) u='--unidiff-zero ' ;;
esac
- for kind in add-a add-z mod-a mod-z del-a del-z
+ for kind in add-a add-z insert-a mod-a mod-z del-a del-z
do
test_expect_success "apply $kind-patch $with context" '
cat original >victim &&
@@ -90,12 +99,12 @@ do
cat '"$kind-patch.$with"'
(exit 1)
} &&
- git diff '"$kind"'-expect victim
+ test_cmp '"$kind"'-expect victim
'
done
done
-for kind in add-a add-z mod-a mod-z del-a del-z
+for kind in add-a add-z insert-a mod-a mod-z del-a del-z
do
rm -f $kind-ng.without
sed -e "s/^diff --git /diff /" \
@@ -108,7 +117,7 @@ do
cat '"$kind-ng.without"'
(exit 1)
} &&
- git diff '"$kind"'-expect victim
+ test_cmp '"$kind"'-expect victim
'
done
diff --git a/t/t4106-apply-stdin.sh b/t/t4106-apply-stdin.sh
new file mode 100755
index 0000000000..72467a1e8e
--- /dev/null
+++ b/t/t4106-apply-stdin.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+test_description='git apply --numstat - <patch'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo hello >text &&
+ git add text &&
+ echo goodbye >text &&
+ git diff >patch
+'
+
+test_expect_success 'git apply --numstat - < patch' '
+ echo "1 1 text" >expect &&
+ git apply --numstat - <patch >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git apply --numstat - < patch patch' '
+ for i in 1 2; do echo "1 1 text"; done >expect &&
+ git apply --numstat - < patch patch >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t4107-apply-ignore-whitespace.sh b/t/t4107-apply-ignore-whitespace.sh
new file mode 100755
index 0000000000..b04fc8fc12
--- /dev/null
+++ b/t/t4107-apply-ignore-whitespace.sh
@@ -0,0 +1,185 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Giuseppe Bilotta
+#
+
+test_description='git-apply --ignore-whitespace.
+
+'
+. ./test-lib.sh
+
+# This primes main.c file that indents without using HT at all.
+# Various patches with HT and other spaces are attempted in the test.
+
+cat > patch1.patch <<\EOF
+diff --git a/main.c b/main.c
+new file mode 100644
+--- /dev/null
++++ b/main.c
+@@ -0,0 +1,22 @@
++#include <stdio.h>
++
++void print_int(int num);
++int func(int num);
++
++int main() {
++ int i;
++
++ for (i = 0; i < 10; i++) {
++ print_int(func(i)); /* stuff */
++ }
++
++ return 0;
++}
++
++int func(int num) {
++ return num * num;
++}
++
++void print_int(int num) {
++ printf("%d", num);
++}
+EOF
+
+# Since whitespace is very significant and we want to prevent whitespace
+# mangling when creating this test from a patch, we protect 'fixable'
+# whitespace by replacing spaces with Z and replacing them at patch
+# creation time, hence the sed trick.
+
+# This patch will fail unless whitespace differences are being ignored
+
+sed -e 's/Z/ /g' > patch2.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -10,6 +10,8 @@
+Z print_int(func(i)); /* stuff */
+Z }
+Z
++ printf("\n");
++
+Z return 0;
+Z}
+Z
+EOF
+
+# This patch will fail even if whitespace differences are being ignored,
+# because of the missing string at EOL. TODO: this testcase should be
+# improved by creating a line that has the same hash with and without
+# the final string.
+
+sed -e 's/Z/ /g' > patch3.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -10,3 +10,4 @@
+Z for (i = 0; i < 10; i++) {
+Z print_int(func(i));Z
++ /* stuff */
+Z }
+EOF
+
+# This patch will fail even if whitespace differences are being ignored,
+# because of the missing EOL at EOF.
+
+sed -e 's/Z/ /g' > patch4.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -21,1 +21,1 @@
+- };Z
+\ No newline at end of file
++ };
+EOF
+
+# This patch will fail unless whitespace differences are being ignored.
+
+sed -e 's/Z/ /g' > patch5.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -2,2 +2,3 @@
+Z void print_int(int num);
++ /* a comment */
+Z int func(int num);
+EOF
+
+# And this is how the final output should be. Patches introduce
+# HTs but the original SP indents are mostly kept.
+
+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() {
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ print_int(func(i)); /* stuff */
+ }
+
+Tprintf("\n");
+
+ return 0;
+}
+
+int func(int num) {
+ return num * num;
+}
+
+void print_int(int num) {
+ printf("%d", num);
+}
+EOF
+
+test_expect_success 'file creation' '
+ git apply patch1.patch
+'
+
+test_expect_success 'patch2 fails (retab)' '
+ test_must_fail git apply patch2.patch
+'
+
+test_expect_success 'patch2 applies with --ignore-whitespace' '
+ git apply --ignore-whitespace patch2.patch
+'
+
+test_expect_success 'patch2 reverse applies with --ignore-space-change' '
+ git apply -R --ignore-space-change patch2.patch
+'
+
+git config apply.ignorewhitespace change
+
+test_expect_success 'patch2 applies (apply.ignorewhitespace = change)' '
+ git apply patch2.patch
+'
+
+test_expect_success 'patch3 fails (missing string at EOL)' '
+ test_must_fail git apply patch3.patch
+'
+
+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 're-create file (with --ignore-whitespace)' '
+ rm -f main.c &&
+ git apply patch1.patch
+'
+
+test_expect_success 'patch5 fails (--no-ignore-whitespace)' '
+ test_must_fail git apply --no-ignore-whitespace patch5.patch
+'
+
+test_done
diff --git a/t/t4109-apply-multifrag.sh b/t/t4109-apply-multifrag.sh
index bd40a218cd..ac58083fe2 100755
--- a/t/t4109-apply-multifrag.sh
+++ b/t/t4109-apply-multifrag.sh
@@ -4,173 +4,32 @@
# Copyright (c) 2005 Robert Fitzsimons
#
-test_description='git apply test patches with multiple fragments.
+test_description='git apply test patches with multiple fragments.'
-'
. ./test-lib.sh
-# setup
-
-cat > patch1.patch <<\EOF
-diff --git a/main.c b/main.c
-new file mode 100644
---- /dev/null
-+++ b/main.c
-@@ -0,0 +1,23 @@
-+#include <stdio.h>
-+
-+int func(int num);
-+void print_int(int num);
-+
-+int main() {
-+ int i;
-+
-+ for (i = 0; i < 10; i++) {
-+ print_int(func(i));
-+ }
-+
-+ return 0;
-+}
-+
-+int func(int num) {
-+ return num * num;
-+}
-+
-+void print_int(int num) {
-+ printf("%d", num);
-+}
-+
-EOF
-cat > patch2.patch <<\EOF
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -1,7 +1,9 @@
-+#include <stdlib.h>
- #include <stdio.h>
-
- int func(int num);
- void print_int(int num);
-+void print_ln();
-
- int main() {
- int i;
-@@ -10,6 +12,8 @@
- print_int(func(i));
- }
-
-+ print_ln();
-+
- return 0;
- }
-
-@@ -21,3 +25,7 @@
- printf("%d", num);
- }
-
-+void print_ln() {
-+ printf("\n");
-+}
-+
-EOF
-cat > patch3.patch <<\EOF
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -1,9 +1,7 @@
--#include <stdlib.h>
- #include <stdio.h>
-
- int func(int num);
- void print_int(int num);
--void print_ln();
-
- int main() {
- int i;
-@@ -12,8 +10,6 @@
- print_int(func(i));
- }
-
-- print_ln();
--
- return 0;
- }
-
-@@ -25,7 +21,3 @@
- printf("%d", num);
- }
-
--void print_ln() {
-- printf("\n");
--}
--
-EOF
-cat > patch4.patch <<\EOF
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -1,13 +1,14 @@
- #include <stdio.h>
-
- int func(int num);
--void print_int(int num);
-+int func2(int num);
-
- int main() {
- int i;
-
- for (i = 0; i < 10; i++) {
-- print_int(func(i));
-+ printf("%d", func(i));
-+ printf("%d", func3(i));
- }
-
- return 0;
-@@ -17,7 +18,7 @@
- return num * num;
- }
-
--void print_int(int num) {
-- printf("%d", num);
-+int func2(int num) {
-+ return num * num * num;
- }
-
-EOF
-
-test_expect_success "S = git apply (1)" \
- 'git apply patch1.patch patch2.patch'
-mv main.c main.c.git
-
-test_expect_success "S = patch (1)" \
- 'cat patch1.patch patch2.patch | patch -p1'
-
-test_expect_success "S = cmp (1)" \
- 'cmp main.c.git main.c'
+cp "$TEST_DIRECTORY/t4109/patch1.patch" .
+cp "$TEST_DIRECTORY/t4109/patch2.patch" .
+cp "$TEST_DIRECTORY/t4109/patch3.patch" .
+cp "$TEST_DIRECTORY/t4109/patch4.patch" .
-rm -f main.c main.c.git
-
-test_expect_success "S = git apply (2)" \
- 'git apply patch1.patch patch2.patch patch3.patch'
-mv main.c main.c.git
-
-test_expect_success "S = patch (2)" \
- 'cat patch1.patch patch2.patch patch3.patch | patch -p1'
-
-test_expect_success "S = cmp (2)" \
- 'cmp main.c.git main.c'
+test_expect_success 'git apply (1)' '
+ git apply patch1.patch patch2.patch &&
+ test_cmp "$TEST_DIRECTORY/t4109/expect-1" main.c
+'
+rm -f main.c
-rm -f main.c main.c.git
+test_expect_success 'git apply (2)' '
+ git apply patch1.patch patch2.patch patch3.patch &&
+ test_cmp "$TEST_DIRECTORY/t4109/expect-2" main.c
+'
+rm -f main.c
-test_expect_success "S = git apply (3)" \
- 'git apply patch1.patch patch4.patch'
+test_expect_success 'git apply (3)' '
+ git apply patch1.patch patch4.patch &&
+ test_cmp "$TEST_DIRECTORY/t4109/expect-3" main.c
+'
mv main.c main.c.git
-test_expect_success "S = patch (3)" \
- 'cat patch1.patch patch4.patch | patch -p1'
-
-test_expect_success "S = cmp (3)" \
- 'cmp main.c.git main.c'
-
test_done
diff --git a/t/t4109/expect-1 b/t/t4109/expect-1
new file mode 100644
index 0000000000..1db5ff1050
--- /dev/null
+++ b/t/t4109/expect-1
@@ -0,0 +1,31 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+int func(int num);
+void print_int(int num);
+void print_ln();
+
+int main() {
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ print_int(func(i));
+ }
+
+ print_ln();
+
+ return 0;
+}
+
+int func(int num) {
+ return num * num;
+}
+
+void print_int(int num) {
+ printf("%d", num);
+}
+
+void print_ln() {
+ printf("\n");
+}
+
diff --git a/t/t4109/expect-2 b/t/t4109/expect-2
new file mode 100644
index 0000000000..bc52924112
--- /dev/null
+++ b/t/t4109/expect-2
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+int func(int num);
+void print_int(int num);
+
+int main() {
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ print_int(func(i));
+ }
+
+ return 0;
+}
+
+int func(int num) {
+ return num * num;
+}
+
+void print_int(int num) {
+ printf("%d", num);
+}
+
diff --git a/t/t4109/expect-3 b/t/t4109/expect-3
new file mode 100644
index 0000000000..cd2a475feb
--- /dev/null
+++ b/t/t4109/expect-3
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+int func(int num);
+int func2(int num);
+
+int main() {
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ printf("%d", func(i));
+ printf("%d", func3(i));
+ }
+
+ return 0;
+}
+
+int func(int num) {
+ return num * num;
+}
+
+int func2(int num) {
+ return num * num * num;
+}
+
diff --git a/t/t4109/patch1.patch b/t/t4109/patch1.patch
new file mode 100644
index 0000000000..1d411fc3cc
--- /dev/null
+++ b/t/t4109/patch1.patch
@@ -0,0 +1,28 @@
+diff --git a/main.c b/main.c
+new file mode 100644
+--- /dev/null
++++ b/main.c
+@@ -0,0 +1,23 @@
++#include <stdio.h>
++
++int func(int num);
++void print_int(int num);
++
++int main() {
++ int i;
++
++ for (i = 0; i < 10; i++) {
++ print_int(func(i));
++ }
++
++ return 0;
++}
++
++int func(int num) {
++ return num * num;
++}
++
++void print_int(int num) {
++ printf("%d", num);
++}
++
diff --git a/t/t4109/patch2.patch b/t/t4109/patch2.patch
new file mode 100644
index 0000000000..8c6b06d536
--- /dev/null
+++ b/t/t4109/patch2.patch
@@ -0,0 +1,30 @@
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,7 +1,9 @@
++#include <stdlib.h>
+ #include <stdio.h>
+
+ int func(int num);
+ void print_int(int num);
++void print_ln();
+
+ int main() {
+ int i;
+@@ -10,6 +12,8 @@
+ print_int(func(i));
+ }
+
++ print_ln();
++
+ return 0;
+ }
+
+@@ -21,3 +25,7 @@
+ printf("%d", num);
+ }
+
++void print_ln() {
++ printf("\n");
++}
++
diff --git a/t/t4109/patch3.patch b/t/t4109/patch3.patch
new file mode 100644
index 0000000000..d696c55a75
--- /dev/null
+++ b/t/t4109/patch3.patch
@@ -0,0 +1,31 @@
+cat > patch3.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,9 +1,7 @@
+-#include <stdlib.h>
+ #include <stdio.h>
+
+ int func(int num);
+ void print_int(int num);
+-void print_ln();
+
+ int main() {
+ int i;
+@@ -12,8 +10,6 @@
+ print_int(func(i));
+ }
+
+- print_ln();
+-
+ return 0;
+ }
+
+@@ -25,7 +21,3 @@
+ printf("%d", num);
+ }
+
+-void print_ln() {
+- printf("\n");
+-}
+-
diff --git a/t/t4109/patch4.patch b/t/t4109/patch4.patch
new file mode 100644
index 0000000000..4b085909b1
--- /dev/null
+++ b/t/t4109/patch4.patch
@@ -0,0 +1,30 @@
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,13 +1,14 @@
+ #include <stdio.h>
+
+ int func(int num);
+-void print_int(int num);
++int func2(int num);
+
+ int main() {
+ int i;
+
+ for (i = 0; i < 10; i++) {
+- print_int(func(i));
++ printf("%d", func(i));
++ printf("%d", func3(i));
+ }
+
+ return 0;
+@@ -17,7 +18,7 @@
+ return num * num;
+ }
+
+-void print_int(int num) {
+- printf("%d", num);
++int func2(int num) {
++ return num * num * num;
+ }
+
diff --git a/t/t4110-apply-scan.sh b/t/t4110-apply-scan.sh
index db60652a37..09f58112e0 100755
--- a/t/t4110-apply-scan.sh
+++ b/t/t4110-apply-scan.sh
@@ -9,92 +9,14 @@ test_description='git apply test for patches which require scanning forwards and
'
. ./test-lib.sh
-# setup
-
-cat > patch1.patch <<\EOF
-diff --git a/new.txt b/new.txt
-new file mode 100644
---- /dev/null
-+++ b/new.txt
-@@ -0,0 +1,12 @@
-+a1
-+a11
-+a111
-+a1111
-+b1
-+b11
-+b111
-+b1111
-+c1
-+c11
-+c111
-+c1111
-EOF
-cat > patch2.patch <<\EOF
-diff --git a/new.txt b/new.txt
---- a/new.txt
-+++ b/new.txt
-@@ -1,7 +1,3 @@
--a1
--a11
--a111
--a1111
- b1
- b11
- b111
-EOF
-cat > patch3.patch <<\EOF
-diff --git a/new.txt b/new.txt
---- a/new.txt
-+++ b/new.txt
-@@ -6,6 +6,10 @@
- b11
- b111
- b1111
-+b2
-+b22
-+b222
-+b2222
- c1
- c11
- c111
-EOF
-cat > patch4.patch <<\EOF
-diff --git a/new.txt b/new.txt
---- a/new.txt
-+++ b/new.txt
-@@ -1,3 +1,7 @@
-+a1
-+a11
-+a111
-+a1111
- b1
- b11
- b111
-EOF
-cat > patch5.patch <<\EOF
-diff --git a/new.txt b/new.txt
---- a/new.txt
-+++ b/new.txt
-@@ -10,3 +10,7 @@
- c11
- c111
- c1111
-+c2
-+c22
-+c222
-+c2222
-EOF
-
-test_expect_success "S = git apply scan" \
- 'git apply patch1.patch patch2.patch patch3.patch patch4.patch patch5.patch'
-mv new.txt apply.txt
-
-test_expect_success "S = patch scan" \
- 'cat patch1.patch patch2.patch patch3.patch patch4.patch patch5.patch | patch'
-mv new.txt patch.txt
-
-test_expect_success "S = cmp" \
- 'cmp apply.txt patch.txt'
+test_expect_success 'git apply scan' '
+ git apply \
+ "$TEST_DIRECTORY/t4110/patch1.patch" \
+ "$TEST_DIRECTORY/t4110/patch2.patch" \
+ "$TEST_DIRECTORY/t4110/patch3.patch" \
+ "$TEST_DIRECTORY/t4110/patch4.patch" \
+ "$TEST_DIRECTORY/t4110/patch5.patch" &&
+ test_cmp new.txt "$TEST_DIRECTORY/t4110/expect"
+'
test_done
diff --git a/t/t4110/expect b/t/t4110/expect
new file mode 100644
index 0000000000..87cc493ec8
--- /dev/null
+++ b/t/t4110/expect
@@ -0,0 +1,20 @@
+a1
+a11
+a111
+a1111
+b1
+b11
+b111
+b1111
+b2
+b22
+b222
+b2222
+c1
+c11
+c111
+c1111
+c2
+c22
+c222
+c2222
diff --git a/t/t4110/patch1.patch b/t/t4110/patch1.patch
new file mode 100644
index 0000000000..56139080dc
--- /dev/null
+++ b/t/t4110/patch1.patch
@@ -0,0 +1,17 @@
+diff --git a/new.txt b/new.txt
+new file mode 100644
+--- /dev/null
++++ b/new.txt
+@@ -0,0 +1,12 @@
++a1
++a11
++a111
++a1111
++b1
++b11
++b111
++b1111
++c1
++c11
++c111
++c1111
diff --git a/t/t4110/patch2.patch b/t/t4110/patch2.patch
new file mode 100644
index 0000000000..04974247ec
--- /dev/null
+++ b/t/t4110/patch2.patch
@@ -0,0 +1,11 @@
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -1,7 +1,3 @@
+-a1
+-a11
+-a111
+-a1111
+ b1
+ b11
+ b111
diff --git a/t/t4110/patch3.patch b/t/t4110/patch3.patch
new file mode 100644
index 0000000000..26bd4427f8
--- /dev/null
+++ b/t/t4110/patch3.patch
@@ -0,0 +1,14 @@
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -6,6 +6,10 @@
+ b11
+ b111
+ b1111
++b2
++b22
++b222
++b2222
+ c1
+ c11
+ c111
diff --git a/t/t4110/patch4.patch b/t/t4110/patch4.patch
new file mode 100644
index 0000000000..9ffb9c2d7e
--- /dev/null
+++ b/t/t4110/patch4.patch
@@ -0,0 +1,11 @@
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -1,3 +1,7 @@
++a1
++a11
++a111
++a1111
+ b1
+ b11
+ b111
diff --git a/t/t4110/patch5.patch b/t/t4110/patch5.patch
new file mode 100644
index 0000000000..c5ac6914f9
--- /dev/null
+++ b/t/t4110/patch5.patch
@@ -0,0 +1,11 @@
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -10,3 +10,7 @@
+ c11
+ c111
+ c1111
++c2
++c22
++c222
++c2222
diff --git a/t/t4112-apply-renames.sh b/t/t4112-apply-renames.sh
index 70a1859503..f9ad183758 100755
--- a/t/t4112-apply-renames.sh
+++ b/t/t4112-apply-renames.sh
@@ -36,6 +36,9 @@ typedef struct __jmp_buf jmp_buf[1];
#endif /* _SETJMP_H */
EOF
+cat >klibc/README <<\EOF
+This is a simple readme file.
+EOF
cat >patch <<\EOF
diff --git a/klibc/arch/x86_64/include/klibc/archsetjmp.h b/include/arch/cris/klibc/archsetjmp.h
@@ -113,6 +116,23 @@ rename to include/arch/m32r/klibc/archsetjmp.h
-#endif /* _SETJMP_H */
+#endif /* _KLIBC_ARCHSETJMP_H */
+diff --git a/klibc/README b/klibc/README
+--- a/klibc/README
++++ b/klibc/README
+@@ -1,1 +1,4 @@
+ This is a simple readme file.
++And we add a few
++lines at the
++end of it.
+diff --git a/klibc/README b/klibc/arch/README
+copy from klibc/README
+copy to klibc/arch/README
+--- a/klibc/README
++++ b/klibc/arch/README
+@@ -1,1 +1,3 @@
+ This is a simple readme file.
++And we copy it to one level down, and
++add a few lines at the end of it.
EOF
find klibc -type f -print | xargs git update-index --add --
diff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh
index d741039882..66fa51591e 100755
--- a/t/t4113-apply-ending.sh
+++ b/t/t4113-apply-ending.sh
@@ -30,7 +30,7 @@ test_expect_success setup \
# test
test_expect_success 'apply at the end' \
- '! git apply --index test-patch'
+ 'test_must_fail git apply --index test-patch'
cat >test-patch <<\EOF
diff a/file b/file
@@ -48,6 +48,6 @@ c'
git update-index file
test_expect_success 'apply at the beginning' \
- '! git apply --index test-patch'
+ 'test_must_fail git apply --index test-patch'
test_done
diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh
index 55334927ab..99ec13dd53 100755
--- a/t/t4114-apply-typechange.sh
+++ b/t/t4114-apply-typechange.sh
@@ -9,6 +9,12 @@ test_description='git apply should not get confused with type changes.
. ./test-lib.sh
+if ! test_have_prereq SYMLINKS
+then
+ say 'Symbolic links not supported, skipping tests.'
+ test_done
+fi
+
test_expect_success 'setup repository and commits' '
echo "hello world" > foo &&
echo "hi planet" > bar &&
@@ -25,6 +31,10 @@ test_expect_success 'setup repository and commits' '
git update-index foo &&
git commit -m "foo back to file" &&
git branch foo-back-to-file &&
+ printf "\0" > foo &&
+ git update-index foo &&
+ git commit -m "foo becomes binary" &&
+ git branch foo-becomes-binary &&
rm -f foo &&
git update-index --remove foo &&
mkdir foo &&
@@ -85,6 +95,20 @@ test_expect_success 'symlink becomes file' '
'
test_debug 'cat patch'
+test_expect_success 'binary file becomes symlink' '
+ git checkout -f foo-becomes-binary &&
+ git diff-tree -p --binary HEAD foo-symlinked-to-bar > patch &&
+ git apply --index < patch
+ '
+test_debug 'cat patch'
+
+test_expect_success 'symlink becomes binary file' '
+ git checkout -f foo-symlinked-to-bar &&
+ git diff-tree -p --binary HEAD foo-becomes-binary > patch &&
+ git apply --index < patch
+ '
+test_debug 'cat patch'
+
test_expect_success 'symlink becomes directory' '
git checkout -f foo-symlinked-to-bar &&
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index a07ff42c2f..b852e58980 100755
--- a/t/t4115-apply-symlink.sh
+++ b/t/t4115-apply-symlink.sh
@@ -9,6 +9,12 @@ test_description='git apply symlinks and partial files
. ./test-lib.sh
+if ! test_have_prereq SYMLINKS
+then
+ say 'Symbolic links not supported, skipping tests.'
+ test_done
+fi
+
test_expect_success setup '
ln -s path1/path2/path3/path4/path5 link1 &&
@@ -33,7 +39,7 @@ test_expect_success 'apply symlink patch' '
git checkout side &&
git apply patch &&
git diff-files -p >patched &&
- git diff patch patched
+ test_cmp patch patched
'
@@ -42,7 +48,7 @@ test_expect_success 'apply --index symlink patch' '
git checkout -f side &&
git apply --index patch &&
git diff-index --cached -p HEAD >patched &&
- git diff patch patched
+ test_cmp patch patched
'
diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh
index c3f4579007..2298ece801 100755
--- a/t/t4116-apply-reverse.sh
+++ b/t/t4116-apply-reverse.sh
@@ -42,18 +42,18 @@ test_expect_success 'apply in reverse' '
git reset --hard second &&
git apply --reverse --binary --index patch &&
git diff >diff &&
- git diff /dev/null diff
+ test_cmp /dev/null diff
'
test_expect_success 'setup separate repository lacking postimage' '
- git tar-tree initial initial | tar xf - &&
+ git tar-tree initial initial | $TAR xf - &&
(
cd initial && git init && git add .
) &&
- git tar-tree second second | tar xf - &&
+ git tar-tree second second | $TAR xf - &&
(
cd second && git init && git add .
)
diff --git a/t/t4117-apply-reject.sh b/t/t4117-apply-reject.sh
index 659e17c92e..e9ccd161ee 100755
--- a/t/t4117-apply-reject.sh
+++ b/t/t4117-apply-reject.sh
@@ -54,7 +54,7 @@ test_expect_success 'apply without --reject should fail' '
exit 1
fi
- git diff file1 saved.file1
+ test_cmp file1 saved.file1
'
test_expect_success 'apply without --reject should fail' '
@@ -65,7 +65,7 @@ test_expect_success 'apply without --reject should fail' '
exit 1
fi
- git diff file1 saved.file1
+ test_cmp file1 saved.file1
'
test_expect_success 'apply with --reject should fail but update the file' '
@@ -79,7 +79,7 @@ test_expect_success 'apply with --reject should fail but update the file' '
exit 1
fi
- git diff file1 expected &&
+ test_cmp file1 expected &&
cat file1.rej &&
@@ -105,7 +105,7 @@ test_expect_success 'apply with --reject should fail but update the file' '
echo "file1 still exists?"
exit 1
}
- git diff file2 expected &&
+ test_cmp file2 expected &&
cat file2.rej &&
@@ -132,7 +132,7 @@ test_expect_success 'the same test with --verbose' '
echo "file1 still exists?"
exit 1
}
- git diff file2 expected &&
+ test_cmp file2 expected &&
cat file2.rej &&
@@ -151,7 +151,7 @@ test_expect_success 'apply cleanly with --verbose' '
git apply --verbose patch.1 &&
- git diff file1 clean
+ test_cmp file1 clean
'
test_done
diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh
index 1d531caf79..65f2e4c3ef 100755
--- a/t/t4118-apply-empty-context.sh
+++ b/t/t4118-apply-empty-context.sh
@@ -20,10 +20,10 @@ test_expect_success setup '
cat file1 &&
echo Q | tr -d "\\012"
} >file2 &&
- cat file2 >file2.orig
+ cat file2 >file2.orig &&
git add file1 file2 &&
sed -e "/^B/d" <file1.orig >file1 &&
- sed -e "/^[BQ]/d" <file2.orig >file2 &&
+ cat file1 > file2 &&
echo Q | tr -d "\\012" >>file2 &&
cat file1 >file1.mods &&
cat file2 >file2.mods &&
@@ -38,7 +38,7 @@ test_expect_success 'apply --numstat' '
echo "0 1 file1" &&
echo "0 1 file2"
} >expect &&
- git diff expect actual
+ test_cmp expect actual
'
@@ -48,8 +48,8 @@ test_expect_success 'apply --apply' '
cat file2.orig >file2 &&
git update-index file1 file2 &&
git apply --index diff.output &&
- git diff file1.mods file1 &&
- git diff file2.mods file2
+ test_cmp file1.mods file1 &&
+ test_cmp file2.mods file2
'
test_done
diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh
index b540f7295a..3c73a783a7 100755
--- a/t/t4119-apply-config.sh
+++ b/t/t4119-apply-config.sh
@@ -19,12 +19,12 @@ test_expect_success setup '
'
# Also handcraft GNU diff output; note this has trailing whitespace.
-cat >gpatch.file <<\EOF &&
+tr '_' ' ' >gpatch.file <<\EOF &&
--- file1 2007-02-21 01:04:24.000000000 -0800
+++ file1+ 2007-02-21 01:07:44.000000000 -0800
@@ -1 +1 @@
-A
-+B
++B_
EOF
sed -e 's|file1|sub/&|' gpatch.file >gpatch-sub.file &&
diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh
index 841773f75f..0d3c1d5dd5 100755
--- a/t/t4122-apply-symlink-inside.sh
+++ b/t/t4122-apply-symlink-inside.sh
@@ -3,6 +3,12 @@
test_description='apply to deeper directory without getting fooled with symlink'
. ./test-lib.sh
+if ! test_have_prereq SYMLINKS
+then
+ say 'Symbolic links not supported, skipping tests.'
+ test_done
+fi
+
lecho () {
for l_
do
diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh
index 85f3da2b98..ca26397590 100755
--- a/t/t4124-apply-ws-rule.sh
+++ b/t/t4124-apply-ws-rule.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='core.whitespace rules and git-apply'
+test_description='core.whitespace rules and git apply'
. ./test-lib.sh
@@ -148,4 +148,117 @@ do
done
done
+create_patch () {
+ sed -e "s/_/ /" <<-\EOF
+ diff --git a/target b/target
+ index e69de29..8bd6648 100644
+ --- a/target
+ +++ b/target
+ @@ -0,0 +1,3 @@
+ +An empty line follows
+ +
+ +A line with trailing whitespace and no newline_
+ \ No newline at end of file
+ EOF
+}
+
+test_expect_success 'trailing whitespace & no newline at the end of file' '
+ >target &&
+ create_patch >patch-file &&
+ git apply --whitespace=fix patch-file &&
+ grep "newline$" target &&
+ grep "^$" target
+'
+
+test_expect_success 'blank at EOF with --whitespace=fix (1)' '
+ : these can fail depending on what we did before
+ git config --unset core.whitespace
+ rm -f .gitattributes
+
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ { echo a; echo b; echo c; } >expect &&
+ { cat expect; echo; } >one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=fix patch &&
+ test_cmp expect one
+'
+
+test_expect_success 'blank at EOF with --whitespace=fix (2)' '
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ { echo a; echo c; } >expect &&
+ { cat expect; echo; echo; } >one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=fix patch &&
+ test_cmp expect one
+'
+
+test_expect_success 'blank at EOF with --whitespace=fix (3)' '
+ { echo a; echo b; echo; } >one &&
+ git add one &&
+ { echo a; echo c; echo; } >expect &&
+ { cat expect; echo; echo; } >one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=fix patch &&
+ test_cmp expect one
+'
+
+test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
+ { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
+ git add one &&
+ { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
+ cp expect one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=fix patch &&
+ test_cmp expect one
+'
+
+test_expect_success 'blank at EOF with --whitespace=warn' '
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ echo >>one &&
+ cat one >expect &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=warn patch 2>error &&
+ test_cmp expect one &&
+ grep "new blank line at EOF" error
+'
+
+test_expect_success 'blank at EOF with --whitespace=error' '
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ cat one >expect &&
+ echo >>one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ test_must_fail git apply --whitespace=error patch 2>error &&
+ test_cmp expect one &&
+ grep "new blank line at EOF" error
+'
+
+test_expect_success 'blank but not empty at EOF' '
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+ echo " " >>one &&
+ cat one >expect &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ git apply --whitespace=warn patch 2>error &&
+ test_cmp expect one &&
+ grep "new blank line at EOF" error
+'
+
test_done
diff --git a/t/t4126-apply-empty.sh b/t/t4126-apply-empty.sh
new file mode 100755
index 0000000000..ceb6a79fe0
--- /dev/null
+++ b/t/t4126-apply-empty.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+test_description='apply empty'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ >empty &&
+ git add empty &&
+ test_tick &&
+ git commit -m initial &&
+ for i in a b c d e
+ do
+ echo $i
+ done >empty &&
+ cat empty >expect &&
+ git diff |
+ sed -e "/^diff --git/d" \
+ -e "/^index /d" \
+ -e "s|a/empty|empty.orig|" \
+ -e "s|b/empty|empty|" >patch0 &&
+ sed -e "s|empty|missing|" patch0 >patch1 &&
+ >empty &&
+ git update-index --refresh
+'
+
+test_expect_success 'apply empty' '
+ git reset --hard &&
+ rm -f missing &&
+ git apply patch0 &&
+ test_cmp expect empty
+'
+
+test_expect_success 'apply --index empty' '
+ git reset --hard &&
+ rm -f missing &&
+ git apply --index patch0 &&
+ test_cmp expect empty &&
+ git diff --exit-code
+'
+
+test_expect_success 'apply create' '
+ git reset --hard &&
+ rm -f missing &&
+ git apply patch1 &&
+ test_cmp expect missing
+'
+
+test_expect_success 'apply --index create' '
+ git reset --hard &&
+ rm -f missing &&
+ git apply --index patch1 &&
+ test_cmp expect missing &&
+ git diff --exit-code
+'
+
+test_done
diff --git a/t/t4127-apply-same-fn.sh b/t/t4127-apply-same-fn.sh
new file mode 100755
index 0000000000..3a8202ea93
--- /dev/null
+++ b/t/t4127-apply-same-fn.sh
@@ -0,0 +1,90 @@
+#!/bin/sh
+
+test_description='apply same filename'
+
+. ./test-lib.sh
+
+modify () {
+ sed -e "$1" < "$2" > "$2".x &&
+ mv "$2".x "$2"
+}
+
+test_expect_success setup '
+ for i in a b c d e f g h i j k l m
+ do
+ echo $i
+ done >same_fn &&
+ cp same_fn other_fn &&
+ git add same_fn other_fn &&
+ git commit -m initial
+'
+test_expect_success 'apply same filename with independent changes' '
+ modify "s/^d/z/" same_fn &&
+ git diff > patch0 &&
+ git add same_fn &&
+ modify "s/^i/y/" same_fn &&
+ git diff >> patch0 &&
+ cp same_fn same_fn2 &&
+ git reset --hard &&
+ git apply patch0 &&
+ diff same_fn same_fn2
+'
+
+test_expect_success 'apply same filename with overlapping changes' '
+ git reset --hard
+ modify "s/^d/z/" same_fn &&
+ git diff > patch0 &&
+ git add same_fn &&
+ modify "s/^e/y/" same_fn &&
+ git diff >> patch0 &&
+ cp same_fn same_fn2 &&
+ git reset --hard &&
+ git apply patch0 &&
+ diff same_fn same_fn2
+'
+
+test_expect_success 'apply same new filename after rename' '
+ git reset --hard
+ git mv same_fn new_fn
+ modify "s/^d/z/" new_fn &&
+ git add new_fn &&
+ git diff -M --cached > patch1 &&
+ modify "s/^e/y/" new_fn &&
+ git diff >> patch1 &&
+ cp new_fn new_fn2 &&
+ git reset --hard &&
+ git apply --index patch1 &&
+ diff new_fn new_fn2
+'
+
+test_expect_success 'apply same old filename after rename -- should fail.' '
+ git reset --hard
+ git mv same_fn new_fn
+ modify "s/^d/z/" new_fn &&
+ git add new_fn &&
+ git diff -M --cached > patch1 &&
+ git mv new_fn same_fn
+ modify "s/^e/y/" same_fn &&
+ git diff >> patch1 &&
+ git reset --hard &&
+ test_must_fail git apply patch1
+'
+
+test_expect_success 'apply A->B (rename), C->A (rename), A->A -- should pass.' '
+ git reset --hard
+ git mv same_fn new_fn
+ modify "s/^d/z/" new_fn &&
+ git add new_fn &&
+ git diff -M --cached > patch1 &&
+ git commit -m "a rename" &&
+ git mv other_fn same_fn
+ modify "s/^e/y/" same_fn &&
+ git add same_fn &&
+ git diff -M --cached >> patch1 &&
+ modify "s/^g/x/" same_fn &&
+ git diff >> patch1 &&
+ git reset --hard HEAD^ &&
+ git apply patch1
+'
+
+test_done
diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh
new file mode 100755
index 0000000000..6cc741a634
--- /dev/null
+++ b/t/t4128-apply-root.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+
+test_description='apply same filename'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+ mkdir -p some/sub/dir &&
+ echo Hello > some/sub/dir/file &&
+ git add some/sub/dir/file &&
+ git commit -m initial &&
+ git tag initial
+
+'
+
+cat > patch << EOF
+diff a/bla/blub/dir/file b/bla/blub/dir/file
+--- a/bla/blub/dir/file
++++ b/bla/blub/dir/file
+@@ -1,1 +1,1 @@
+-Hello
++Bello
+EOF
+
+test_expect_success 'apply --directory -p (1)' '
+
+ git apply --directory=some/sub -p3 --index patch &&
+ test Bello = $(git show :some/sub/dir/file) &&
+ test Bello = $(cat some/sub/dir/file)
+
+'
+
+test_expect_success 'apply --directory -p (2) ' '
+
+ git reset --hard initial &&
+ git apply --directory=some/sub/ -p3 --index patch &&
+ test Bello = $(git show :some/sub/dir/file) &&
+ test Bello = $(cat some/sub/dir/file)
+
+'
+
+cat > patch << EOF
+diff --git a/newfile b/newfile
+new file mode 100644
+index 0000000..d95f3ad
+--- /dev/null
++++ b/newfile
+@@ -0,0 +1 @@
++content
+EOF
+
+test_expect_success 'apply --directory (new file)' '
+ git reset --hard initial &&
+ git apply --directory=some/sub/dir/ --index patch &&
+ test content = $(git show :some/sub/dir/newfile) &&
+ test content = $(cat some/sub/dir/newfile)
+'
+
+cat > patch << EOF
+diff --git a/c/newfile2 b/c/newfile2
+new file mode 100644
+index 0000000..d95f3ad
+--- /dev/null
++++ b/c/newfile2
+@@ -0,0 +1 @@
++content
+EOF
+
+test_expect_success 'apply --directory -p (new file)' '
+ git reset --hard initial &&
+ git apply -p2 --directory=some/sub/dir/ --index patch &&
+ test content = $(git show :some/sub/dir/newfile2) &&
+ test content = $(cat some/sub/dir/newfile2)
+'
+
+cat > patch << EOF
+diff --git a/delfile b/delfile
+deleted file mode 100644
+index d95f3ad..0000000
+--- a/delfile
++++ /dev/null
+@@ -1 +0,0 @@
+-content
+EOF
+
+test_expect_success 'apply --directory (delete file)' '
+ git reset --hard initial &&
+ echo content >some/sub/dir/delfile &&
+ git add some/sub/dir/delfile &&
+ git apply --directory=some/sub/dir/ --index patch &&
+ ! (git ls-files | grep delfile)
+'
+
+cat > patch << 'EOF'
+diff --git "a/qu\157tefile" "b/qu\157tefile"
+new file mode 100644
+index 0000000..d95f3ad
+--- /dev/null
++++ "b/qu\157tefile"
+@@ -0,0 +1 @@
++content
+EOF
+
+test_expect_success 'apply --directory (quoted filename)' '
+ git reset --hard initial &&
+ git apply --directory=some/sub/dir/ --index patch &&
+ test content = $(git show :some/sub/dir/quotefile) &&
+ test content = $(cat some/sub/dir/quotefile)
+'
+
+test_done
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
new file mode 100755
index 0000000000..fc7af04931
--- /dev/null
+++ b/t/t4129-apply-samemode.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+test_description='applying patch with mode bits'
+
+. ./test-lib.sh
+
+if test "$(git config --bool core.filemode)" = false
+then
+ say 'filemode disabled on the filesystem'
+else
+ test_set_prereq FILEMODE
+fi
+
+test_expect_success setup '
+ echo original >file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ git tag initial &&
+ echo modified >file &&
+ git diff --stat -p >patch-0.txt &&
+ chmod +x file &&
+ git diff --stat -p >patch-1.txt
+'
+
+test_expect_success FILEMODE 'same mode (no index)' '
+ git reset --hard &&
+ chmod +x file &&
+ git apply patch-0.txt &&
+ test -x file
+'
+
+test_expect_success FILEMODE 'same mode (with index)' '
+ git reset --hard &&
+ chmod +x file &&
+ git add file &&
+ git apply --index patch-0.txt &&
+ test -x file &&
+ git diff --exit-code
+'
+
+test_expect_success FILEMODE 'same mode (index only)' '
+ git reset --hard &&
+ chmod +x file &&
+ git add file &&
+ git apply --cached patch-0.txt &&
+ git ls-files -s file | grep "^100755"
+'
+
+test_expect_success FILEMODE 'mode update (no index)' '
+ git reset --hard &&
+ git apply patch-1.txt &&
+ test -x file
+'
+
+test_expect_success FILEMODE 'mode update (with index)' '
+ git reset --hard &&
+ git apply --index patch-1.txt &&
+ test -x file &&
+ git diff --exit-code
+'
+
+test_expect_success FILEMODE 'mode update (index only)' '
+ git reset --hard &&
+ git apply --cached patch-1.txt &&
+ git ls-files -s file | grep "^100755"
+'
+
+test_done
diff --git a/t/t4130-apply-criss-cross-rename.sh b/t/t4130-apply-criss-cross-rename.sh
new file mode 100755
index 0000000000..7cfa2d6287
--- /dev/null
+++ b/t/t4130-apply-criss-cross-rename.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+test_description='git apply handling criss-cross rename patch.'
+. ./test-lib.sh
+
+create_file() {
+ cnt=0
+ while test $cnt -le 100
+ do
+ cnt=$(($cnt + 1))
+ echo "$2" >> "$1"
+ done
+}
+
+test_expect_success 'setup' '
+ create_file file1 "File1 contents" &&
+ create_file file2 "File2 contents" &&
+ create_file file3 "File3 contents" &&
+ git add file1 file2 file3 &&
+ git commit -m 1
+'
+
+test_expect_success 'criss-cross rename' '
+ mv file1 tmp &&
+ mv file2 file1 &&
+ mv tmp file2 &&
+ cp file1 file1-swapped &&
+ cp file2 file2-swapped
+'
+
+test_expect_success 'diff -M -B' '
+ git diff -M -B > diff &&
+ git reset --hard
+
+'
+
+test_expect_success 'apply' '
+ git apply diff &&
+ test_cmp file1 file1-swapped &&
+ test_cmp file2 file2-swapped
+'
+
+test_expect_success 'criss-cross rename' '
+ git reset --hard &&
+ mv file1 tmp &&
+ mv file2 file1 &&
+ mv file3 file2
+ mv tmp file3 &&
+ cp file1 file1-swapped &&
+ cp file2 file2-swapped &&
+ cp file3 file3-swapped
+'
+
+test_expect_success 'diff -M -B' '
+ git diff -M -B > diff &&
+ git reset --hard
+'
+
+test_expect_success 'apply' '
+ git apply diff &&
+ test_cmp file1 file1-swapped &&
+ test_cmp file2 file2-swapped &&
+ test_cmp file3 file3-swapped
+'
+
+test_done
diff --git a/t/t4131-apply-fake-ancestor.sh b/t/t4131-apply-fake-ancestor.sh
new file mode 100755
index 0000000000..94373ca9a0
--- /dev/null
+++ b/t/t4131-apply-fake-ancestor.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Stephen Boyd
+#
+
+test_description='git apply --build-fake-ancestor handling.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit 1 &&
+ test_commit 2 &&
+ mkdir sub &&
+ test_commit 3 sub/3 &&
+ test_commit 4
+'
+
+test_expect_success 'apply --build-fake-ancestor' '
+ git checkout 2 &&
+ echo "A" > 1.t &&
+ git diff > 1.patch &&
+ git reset --hard &&
+ git checkout 1 &&
+ git apply --build-fake-ancestor 1.ancestor 1.patch
+'
+
+test_expect_success 'apply --build-fake-ancestor in a subdirectory' '
+ git checkout 3 &&
+ echo "C" > sub/3.t &&
+ git diff > 3.patch &&
+ git reset --hard &&
+ git checkout 4 &&
+ (
+ cd sub &&
+ git apply --build-fake-ancestor 3.ancestor ../3.patch &&
+ test -f 3.ancestor
+ ) &&
+ git apply --build-fake-ancestor 3.ancestor 3.patch &&
+ test_cmp sub/3.ancestor 3.ancestor
+'
+
+test_done
diff --git a/t/t4132-apply-removal.sh b/t/t4132-apply-removal.sh
new file mode 100755
index 0000000000..bb1ffe3b6c
--- /dev/null
+++ b/t/t4132-apply-removal.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Junio C Hamano
+
+test_description='git-apply notices removal patches generated by GNU diff'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ cat <<-EOF >c &&
+ diff -ruN a/file b/file
+ --- a/file TS0
+ +++ b/file TS1
+ @@ -0,0 +1 @@
+ +something
+ EOF
+
+ cat <<-EOF >d &&
+ diff -ruN a/file b/file
+ --- a/file TS0
+ +++ b/file TS1
+ @@ -1 +0,0 @@
+ -something
+ EOF
+
+ timeWest="1982-09-16 07:00:00.000000000 -0800" &&
+ timeGMT="1982-09-16 15:00:00.000000000 +0000" &&
+ timeEast="1982-09-17 00:00:00.000000000 +0900" &&
+
+ epocWest="1969-12-31 16:00:00.000000000 -0800" &&
+ epocGMT="1970-01-01 00:00:00.000000000 +0000" &&
+ epocEast="1970-01-01 09:00:00.000000000 +0900" &&
+
+ sed -e "s/TS0/$epocWest/" -e "s/TS1/$timeWest/" <c >createWest.patch &&
+ sed -e "s/TS0/$epocEast/" -e "s/TS1/$timeEast/" <c >createEast.patch &&
+ sed -e "s/TS0/$epocGMT/" -e "s/TS1/$timeGMT/" <c >createGMT.patch &&
+
+ sed -e "s/TS0/$timeWest/" -e "s/TS1/$timeWest/" <c >addWest.patch &&
+ sed -e "s/TS0/$timeEast/" -e "s/TS1/$timeEast/" <c >addEast.patch &&
+ sed -e "s/TS0/$timeGMT/" -e "s/TS1/$timeGMT/" <c >addGMT.patch &&
+
+ sed -e "s/TS0/$timeWest/" -e "s/TS1/$timeWest/" <d >emptyWest.patch &&
+ sed -e "s/TS0/$timeEast/" -e "s/TS1/$timeEast/" <d >emptyEast.patch &&
+ sed -e "s/TS0/$timeGMT/" -e "s/TS1/$timeGMT/" <d >emptyGMT.patch &&
+
+ sed -e "s/TS0/$timeWest/" -e "s/TS1/$epocWest/" <d >removeWest.patch &&
+ sed -e "s/TS0/$timeEast/" -e "s/TS1/$epocEast/" <d >removeEast.patch &&
+ sed -e "s/TS0/$timeGMT/" -e "s/TS1/$epocGMT/" <d >removeGMT.patch &&
+
+ echo something >something &&
+ >empty
+'
+
+for patch in *.patch
+do
+ test_expect_success "test $patch" '
+ rm -f file .git/index &&
+ case "$patch" in
+ create*)
+ # must be able to create
+ git apply --index $patch &&
+ test_cmp file something &&
+ # must notice the file is already there
+ >file &&
+ git add file &&
+ test_must_fail git apply $patch
+ ;;
+ add*)
+ # must be able to create or patch
+ git apply $patch &&
+ test_cmp file something &&
+ >file &&
+ git apply $patch &&
+ test_cmp file something
+ ;;
+ empty*)
+ # must leave an empty file
+ cat something >file &&
+ git add file &&
+ git apply --index $patch &&
+ test -f file &&
+ test_cmp empty file
+ ;;
+ remove*)
+ # must remove the file
+ cat something >file &&
+ git add file &&
+ git apply --index $patch &&
+ ! test -f file
+ ;;
+ esac
+ '
+done
+
+test_done
diff --git a/t/t4150-am-subdir.sh b/t/t4150-am-subdir.sh
deleted file mode 100755
index 52069b469b..0000000000
--- a/t/t4150-am-subdir.sh
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/bin/sh
-
-test_description='git am running from a subdirectory'
-
-. ./test-lib.sh
-
-test_expect_success setup '
- echo hello >world &&
- git add world &&
- test_tick &&
- git commit -m initial &&
- git tag initial &&
- echo goodbye >world &&
- git add world &&
- test_tick &&
- git commit -m second &&
- git format-patch --stdout HEAD^ >patchfile &&
- : >expect
-'
-
-test_expect_success 'am regularly from stdin' '
- git checkout initial &&
- git am <patchfile &&
- git diff master >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'am regularly from file' '
- git checkout initial &&
- git am patchfile &&
- git diff master >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'am regularly from stdin in subdirectory' '
- rm -fr subdir &&
- git checkout initial &&
- (
- mkdir -p subdir &&
- cd subdir &&
- git am <../patchfile
- ) &&
- git diff master>actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'am regularly from file in subdirectory' '
- rm -fr subdir &&
- git checkout initial &&
- (
- mkdir -p subdir &&
- cd subdir &&
- git am ../patchfile
- ) &&
- git diff master >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'am regularly from file in subdirectory with full path' '
- rm -fr subdir &&
- git checkout initial &&
- P=$(pwd) &&
- (
- mkdir -p subdir &&
- cd subdir &&
- git am "$P/patchfile"
- ) &&
- git diff master >actual &&
- test_cmp expect actual
-'
-
-test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
new file mode 100755
index 0000000000..8296605234
--- /dev/null
+++ b/t/t4150-am.sh
@@ -0,0 +1,349 @@
+#!/bin/sh
+
+test_description='git am running'
+
+. ./test-lib.sh
+
+cat >msg <<EOF
+second
+
+Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy
+eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
+voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
+kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem
+ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
+tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
+vero eos et accusam et justo duo dolores et ea rebum.
+
+ Duis autem vel eum iriure dolor in hendrerit in vulputate velit
+ esse molestie consequat, vel illum dolore eu feugiat nulla facilisis
+ at vero eros et accumsan et iusto odio dignissim qui blandit
+ praesent luptatum zzril delenit augue duis dolore te feugait nulla
+ facilisi.
+
+
+Lorem ipsum dolor sit amet,
+consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+laoreet dolore magna aliquam erat volutpat.
+
+ git
+ ---
+ +++
+
+Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
+lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure
+dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
+dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
+dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
+feugait nulla facilisi.
+EOF
+
+cat >failmail <<EOF
+From foo@example.com Fri May 23 10:43:49 2008
+From: foo@example.com
+To: bar@example.com
+Subject: Re: [RFC/PATCH] git-foo.sh
+Date: Fri, 23 May 2008 05:23:42 +0200
+
+Sometimes we have to find out that there's nothing left.
+
+EOF
+
+cat >pine <<EOF
+From MAILER-DAEMON Fri May 23 10:43:49 2008
+Date: 23 May 2008 05:23:42 +0200
+From: Mail System Internal Data <MAILER-DAEMON@example.com>
+Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
+Message-ID: <foo-0001@example.com>
+
+This text is part of the internal format of your mail folder, and is not
+a real message. It is created automatically by the mail system software.
+If deleted, important folder data will be lost, and it will be re-created
+with the data reset to initial values.
+
+EOF
+
+echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected
+
+test_expect_success setup '
+ echo hello >file &&
+ git add file &&
+ test_tick &&
+ git commit -m first &&
+ git tag first &&
+ echo world >>file &&
+ git add file &&
+ test_tick &&
+ git commit -s -F msg &&
+ git tag second &&
+ git format-patch --stdout first >patch1 &&
+ {
+ echo "X-Fake-Field: Line One" &&
+ echo "X-Fake-Field: Line Two" &&
+ echo "X-Fake-Field: Line Three" &&
+ git format-patch --stdout first | sed -e "1d"
+ } > patch1.eml &&
+ sed -n -e "3,\$p" msg >file &&
+ git add file &&
+ test_tick &&
+ git commit -m third &&
+ git format-patch --stdout first >patch2 &&
+ git checkout -b lorem &&
+ sed -n -e "11,\$p" msg >file &&
+ head -n 9 msg >>file &&
+ test_tick &&
+ git commit -a -m "moved stuff" &&
+ echo goodbye >another &&
+ git add another &&
+ test_tick &&
+ git commit -m "added another file" &&
+ git format-patch --stdout master >lorem-move.patch
+'
+
+# reset time
+unset test_tick
+test_tick
+
+test_expect_success 'am applies patch correctly' '
+ git checkout first &&
+ test_tick &&
+ git am <patch1 &&
+ ! test -d .git/rebase-apply &&
+ test -z "$(git diff second)" &&
+ test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
+ test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
+'
+
+test_expect_success 'am applies patch e-mail not in a mbox' '
+ git checkout first &&
+ git am patch1.eml &&
+ ! test -d .git/rebase-apply &&
+ test -z "$(git diff second)" &&
+ test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
+ test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
+'
+
+GIT_AUTHOR_NAME="Another Thor"
+GIT_AUTHOR_EMAIL="a.thor@example.com"
+GIT_COMMITTER_NAME="Co M Miter"
+GIT_COMMITTER_EMAIL="c.miter@example.com"
+export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
+
+compare () {
+ test "$(git cat-file commit "$2" | grep "^$1 ")" = \
+ "$(git cat-file commit "$3" | grep "^$1 ")"
+}
+
+test_expect_success 'am changes committer and keeps author' '
+ test_tick &&
+ git checkout first &&
+ git am patch2 &&
+ ! test -d .git/rebase-apply &&
+ test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
+ test -z "$(git diff master..HEAD)" &&
+ test -z "$(git diff master^..HEAD^)" &&
+ compare author master HEAD &&
+ compare author master^ HEAD^ &&
+ test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
+ "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
+'
+
+test_expect_success 'am --signoff adds Signed-off-by: line' '
+ git checkout -b master2 first &&
+ git am --signoff <patch2 &&
+ echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
+ git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
+ test_cmp actual expected &&
+ echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
+ git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
+ test_cmp actual expected
+'
+
+test_expect_success 'am stays in branch' '
+ test "refs/heads/master2" = "$(git symbolic-ref HEAD)"
+'
+
+test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
+ git format-patch --stdout HEAD^ >patch3 &&
+ sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2," patch3 >patch4
+ git checkout HEAD^ &&
+ git am --signoff patch4 &&
+ test "$(git cat-file commit HEAD | grep -c "^Signed-off-by:")" -eq 1
+'
+
+test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
+ test "$(git rev-parse HEAD)" = "$(git rev-parse master2)"
+'
+
+test_expect_success 'am --keep really keeps the subject' '
+ git checkout HEAD^ &&
+ git am --keep patch4 &&
+ ! test -d .git/rebase-apply &&
+ git cat-file commit HEAD |
+ fgrep "Re: Re: Re: [PATCH 1/5 v2] third"
+'
+
+test_expect_success 'am -3 falls back to 3-way merge' '
+ git checkout -b lorem2 master2 &&
+ sed -n -e "3,\$p" msg >file &&
+ head -n 9 msg >>file &&
+ git add file &&
+ test_tick &&
+ git commit -m "copied stuff" &&
+ git am -3 lorem-move.patch &&
+ ! test -d .git/rebase-apply &&
+ test -z "$(git diff lorem)"
+'
+
+test_expect_success 'am -3 -q is quiet' '
+ git reset master2 --hard &&
+ sed -n -e "3,\$p" msg >file &&
+ head -n 9 msg >>file &&
+ git add file &&
+ test_tick &&
+ git commit -m "copied stuff" &&
+ git am -3 -q lorem-move.patch > output.out 2>&1 &&
+ ! test -s output.out
+'
+
+test_expect_success 'am pauses on conflict' '
+ git checkout lorem2^^ &&
+ test_must_fail git am lorem-move.patch &&
+ test -d .git/rebase-apply
+'
+
+test_expect_success 'am --skip works' '
+ git am --skip &&
+ ! test -d .git/rebase-apply &&
+ test -z "$(git diff lorem2^^ -- file)" &&
+ test goodbye = "$(cat another)"
+'
+
+test_expect_success 'am --resolved works' '
+ git checkout lorem2^^ &&
+ test_must_fail git am lorem-move.patch &&
+ test -d .git/rebase-apply &&
+ echo resolved >>file &&
+ git add file &&
+ git am --resolved &&
+ ! test -d .git/rebase-apply &&
+ test goodbye = "$(cat another)"
+'
+
+test_expect_success 'am takes patches from a Pine mailbox' '
+ git checkout first &&
+ cat pine patch1 | git am &&
+ ! test -d .git/rebase-apply &&
+ test -z "$(git diff master^..HEAD)"
+'
+
+test_expect_success 'am fails on mail without patch' '
+ test_must_fail git am <failmail &&
+ rm -r .git/rebase-apply/
+'
+
+test_expect_success 'am fails on empty patch' '
+ echo "---" >>failmail &&
+ test_must_fail git am <failmail &&
+ git am --skip &&
+ ! test -d .git/rebase-apply
+'
+
+test_expect_success 'am works from stdin in subdirectory' '
+ rm -fr subdir &&
+ git checkout first &&
+ (
+ mkdir -p subdir &&
+ cd subdir &&
+ git am <../patch1
+ ) &&
+ test -z "$(git diff second)"
+'
+
+test_expect_success 'am works from file (relative path given) in subdirectory' '
+ rm -fr subdir &&
+ git checkout first &&
+ (
+ mkdir -p subdir &&
+ cd subdir &&
+ git am ../patch1
+ ) &&
+ test -z "$(git diff second)"
+'
+
+test_expect_success 'am works from file (absolute path given) in subdirectory' '
+ rm -fr subdir &&
+ git checkout first &&
+ P=$(pwd) &&
+ (
+ mkdir -p subdir &&
+ cd subdir &&
+ git am "$P/patch1"
+ ) &&
+ test -z "$(git diff second)"
+'
+
+test_expect_success 'am --committer-date-is-author-date' '
+ git checkout first &&
+ test_tick &&
+ git am --committer-date-is-author-date patch1 &&
+ git cat-file commit HEAD | sed -e "/^$/q" >head1 &&
+ at=$(sed -ne "/^author /s/.*> //p" head1) &&
+ ct=$(sed -ne "/^committer /s/.*> //p" head1) &&
+ test "$at" = "$ct"
+'
+
+test_expect_success 'am without --committer-date-is-author-date' '
+ git checkout first &&
+ test_tick &&
+ git am patch1 &&
+ git cat-file commit HEAD | sed -e "/^$/q" >head1 &&
+ at=$(sed -ne "/^author /s/.*> //p" head1) &&
+ ct=$(sed -ne "/^committer /s/.*> //p" head1) &&
+ test "$at" != "$ct"
+'
+
+# This checks for +0000 because TZ is set to UTC and that should
+# show up when the current time is used. The date in message is set
+# by test_tick that uses -0700 timezone; if this feature does not
+# work, we will see that instead of +0000.
+test_expect_success 'am --ignore-date' '
+ git checkout first &&
+ test_tick &&
+ git am --ignore-date patch1 &&
+ git cat-file commit HEAD | sed -e "/^$/q" >head1 &&
+ at=$(sed -ne "/^author /s/.*> //p" head1) &&
+ echo "$at" | grep "+0000"
+'
+
+test_expect_success 'am into an unborn branch' '
+ rm -fr subdir &&
+ mkdir -p subdir &&
+ git format-patch --numbered-files -o subdir -1 first &&
+ (
+ cd subdir &&
+ git init &&
+ git am 1
+ ) &&
+ result=$(
+ cd subdir && git rev-parse HEAD^{tree}
+ ) &&
+ test "z$result" = "z$(git rev-parse first^{tree})"
+'
+
+test_expect_success 'am newline in subject' '
+ git checkout first &&
+ test_tick &&
+ sed -e "s/second/second \\\n foo/" patch1 > patchnl &&
+ git am < patchnl > output.out 2>&1 &&
+ grep "^Applying: second \\\n foo$" output.out
+'
+
+test_expect_success 'am -q is quiet' '
+ git checkout first &&
+ test_tick &&
+ git am -q < patch1 > output.out 2>&1 &&
+ ! test -s output.out
+'
+
+test_done
diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh
new file mode 100755
index 0000000000..2b912d7728
--- /dev/null
+++ b/t/t4151-am-abort.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+test_description='am --abort'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ for i in a b c d e f g
+ do
+ echo $i
+ done >file-1 &&
+ cp file-1 file-2 &&
+ test_tick &&
+ git add file-1 file-2 &&
+ git commit -m initial &&
+ git tag initial &&
+ for i in 2 3 4 5 6
+ do
+ echo $i >>file-1 &&
+ echo $i >otherfile-$i &&
+ git add otherfile-$i &&
+ test_tick &&
+ git commit -a -m $i || break
+ done &&
+ git format-patch --no-numbered initial &&
+ git checkout -b side initial &&
+ echo local change >file-2-expect
+'
+
+for with3 in '' ' -3'
+do
+ test_expect_success "am$with3 stops at a patch that does not apply" '
+
+ git reset --hard initial &&
+ cp file-2-expect file-2 &&
+
+ test_must_fail git am$with3 000[1245]-*.patch &&
+ git log --pretty=tformat:%s >actual &&
+ for i in 3 2 initial
+ do
+ echo $i
+ done >expect &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "am$with3 --skip continue after failed am$with3" '
+ test_must_fail git am$with3 --skip >output &&
+ test "$(grep "^Applying" output)" = "Applying: 6" &&
+ test_cmp file-2-expect file-2 &&
+ test ! -f .git/rr-cache/MERGE_RR
+ '
+
+ test_expect_success "am --abort goes back after failed am$with3" '
+ git am --abort &&
+ git rev-parse HEAD >actual &&
+ git rev-parse initial >expect &&
+ test_cmp expect actual &&
+ test_cmp file-2-expect file-2 &&
+ git diff-index --exit-code --cached HEAD &&
+ test ! -f .git/rr-cache/MERGE_RR
+ '
+
+done
+
+test_done
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index 3cbfee704e..a6bc028a57 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -9,6 +9,8 @@ test_description='git rerere
. ./test-lib.sh
cat > a1 << EOF
+Some title
+==========
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
@@ -24,6 +26,8 @@ git commit -q -a -m initial
git checkout -b first
cat >> a1 << EOF
+Some title
+==========
To die, to sleep;
To sleep: perchance to dream: ay, there's the rub;
For in that sleep of death what dreams may come
@@ -35,13 +39,13 @@ git commit -q -a -m first
git checkout -b second master
git show first:a1 |
-sed -e 's/To die, t/To die! T/' > a1
+sed -e 's/To die, t/To die! T/' -e 's/Some title/Some Title/' > a1
echo "* END *" >>a1
git commit -q -a -m second
test_expect_success 'nothing recorded without rerere' '
(rm -rf .git/rr-cache; git config rerere.enabled false) &&
- ! git merge first &&
+ test_must_fail git merge first &&
! test -d .git/rr-cache
'
@@ -50,19 +54,19 @@ test_expect_success 'conflicting merge' '
git reset --hard &&
mkdir .git/rr-cache &&
git config --unset rerere.enabled &&
- ! git merge first
+ test_must_fail git merge first
'
-sha1=$(sed -e 's/ .*//' .git/rr-cache/MERGE_RR)
+sha1=$(perl -pe 's/ .*//' .git/MERGE_RR)
rr=.git/rr-cache/$sha1
-test_expect_success 'recorded preimage' "grep ======= $rr/preimage"
+test_expect_success 'recorded preimage' "grep ^=======$ $rr/preimage"
test_expect_success 'rerere.enabled works, too' '
rm -rf .git/rr-cache &&
git config rerere.enabled true &&
git reset --hard &&
- ! git merge first &&
- grep ======= $rr/preimage
+ test_must_fail git merge first &&
+ grep ^=======$ $rr/preimage
'
test_expect_success 'no postimage or thisimage yet' \
@@ -71,7 +75,7 @@ test_expect_success 'no postimage or thisimage yet' \
test_expect_success 'preimage has right number of lines' '
cnt=$(sed -ne "/^<<<<<<</,/^>>>>>>>/p" $rr/preimage | wc -l) &&
- test $cnt = 9
+ test $cnt = 13
'
@@ -80,13 +84,23 @@ git show first:a1 > a1
cat > expect << EOF
--- a/a1
+++ b/a1
-@@ -6,17 +6,9 @@
+@@ -1,4 +1,4 @@
+-Some Title
++Some title
+ ==========
+ Whether 'tis nobler in the mind to suffer
+ The slings and arrows of outrageous fortune,
+@@ -8,21 +8,11 @@
The heart-ache and the thousand natural shocks
That flesh is heir to, 'tis a consummation
Devoutly to be wish'd.
-<<<<<<<
+-Some Title
+-==========
-To die! To sleep;
-=======
+ Some title
+ ==========
To die, to sleep;
->>>>>>>
To sleep: perchance to dream: ay, there's the rub;
@@ -101,7 +115,7 @@ cat > expect << EOF
EOF
git rerere diff > out
-test_expect_success 'rerere diff' 'git diff expect out'
+test_expect_success 'rerere diff' 'test_cmp expect out'
cat > expect << EOF
a1
@@ -109,7 +123,7 @@ EOF
git rerere status > out
-test_expect_success 'rerere status' 'git diff expect out'
+test_expect_success 'rerere status' 'test_cmp expect out'
test_expect_success 'commit succeeds' \
"git commit -q -a -m 'prefer first over second'"
@@ -120,16 +134,16 @@ test_expect_success 'another conflicting merge' '
git checkout -b third master &&
git show second^:a1 | sed "s/To die: t/To die! T/" > a1 &&
git commit -q -a -m third &&
- ! git pull . first
+ test_must_fail git pull . first
'
git show first:a1 | sed 's/To die: t/To die! T/' > expect
-test_expect_success 'rerere kicked in' "! grep ======= a1"
+test_expect_success 'rerere kicked in' "! grep ^=======$ a1"
-test_expect_success 'rerere prefers first change' 'git diff a1 expect'
+test_expect_success 'rerere prefers first change' 'test_cmp a1 expect'
rm $rr/postimage
-echo "$sha1 a1" | perl -pe 'y/\012/\000/' > .git/rr-cache/MERGE_RR
+echo "$sha1 a1" | perl -pe 'y/\012/\000/' > .git/MERGE_RR
test_expect_success 'rerere clear' 'git rerere clear'
@@ -175,9 +189,7 @@ test_expect_success 'file2 added differently in two branches' '
echo Bello > file2 &&
git add file2 &&
git commit -m version2 &&
- ! git merge fourth &&
- sha1=$(sed -e "s/ .*//" .git/rr-cache/MERGE_RR) &&
- rr=.git/rr-cache/$sha1 &&
+ test_must_fail git merge fourth &&
echo Cello > file2 &&
git add file2 &&
git commit -m resolution
@@ -193,9 +205,19 @@ test_expect_success 'resolution was recorded properly' '
echo Bello > file3 &&
git add file3 &&
git commit -m version2 &&
- ! git merge fifth &&
- git diff-files -q &&
- test Cello = "$(cat file3)"
+ git tag version2 &&
+ test_must_fail git merge fifth &&
+ test Cello = "$(cat file3)" &&
+ test 0 != $(git ls-files -u | wc -l)
+'
+
+test_expect_success 'rerere.autoupdate' '
+ git config rerere.autoupdate true
+ git reset --hard &&
+ git checkout version2 &&
+ test_must_fail git merge fifth &&
+ test 0 = $(git ls-files -u | wc -l)
+
'
test_done
diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh
index 405b971191..a01e55bf6b 100755
--- a/t/t4201-shortlog.sh
+++ b/t/t4201-shortlog.sh
@@ -52,4 +52,32 @@ GIT_DIR=non-existing git shortlog -w < log > out
test_expect_success 'shortlog from non-git directory' 'test_cmp expect out'
+iconvfromutf8toiso88591() {
+ printf "%s" "$*" | iconv -f UTF-8 -t ISO8859-1
+}
+
+DSCHO="Jöhännës \"Dschö\" Schindëlin"
+DSCHOE="$DSCHO <Johannes.Schindelin@gmx.de>"
+MSG1="set a1 to 2 and some non-ASCII chars: Äßø"
+MSG2="set a1 to 3 and some non-ASCII chars: áæï"
+cat > expect << EOF
+$DSCHO (2):
+ $MSG1
+ $MSG2
+
+EOF
+
+test_expect_success 'shortlog encoding' '
+ git reset --hard "$commit" &&
+ git config --unset i18n.commitencoding &&
+ echo 2 > a1 &&
+ git commit --quiet -m "$MSG1" --author="$DSCHOE" a1 &&
+ git config i18n.commitencoding "ISO8859-1" &&
+ echo 3 > a1 &&
+ git commit --quiet -m "$(iconvfromutf8toiso88591 "$MSG2")" \
+ --author="$(iconvfromutf8toiso88591 "$DSCHOE")" a1 &&
+ git config --unset i18n.commitencoding &&
+ git shortlog HEAD~2.. > out &&
+test_cmp expect out'
+
test_done
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index b53645417b..779a5adf55 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -16,27 +16,92 @@ test_expect_success setup '
test_tick &&
git commit -m second &&
- mkdir a &&
- echo ni >a/two &&
- git add a/two &&
+ git mv one ichi &&
test_tick &&
git commit -m third &&
- echo san >a/three &&
- git add a/three &&
+ cp ichi ein &&
+ git add ein &&
test_tick &&
git commit -m fourth &&
- git rm a/three &&
+ mkdir a &&
+ echo ni >a/two &&
+ git add a/two &&
test_tick &&
- git commit -m fifth
+ git commit -m fifth &&
+
+ git rm a/two &&
+ test_tick &&
+ git commit -m sixth
+
+'
+
+printf "sixth\nfifth\nfourth\nthird\nsecond\ninitial" > expect
+test_expect_success 'pretty' '
+ git log --pretty="format:%s" > actual &&
+ test_cmp expect actual
+'
+
+printf "sixth\nfifth\nfourth\nthird\nsecond\ninitial\n" > expect
+test_expect_success 'pretty (tformat)' '
+
+ git log --pretty="tformat:%s" > actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'pretty (shortcut)' '
+
+ git log --pretty="%s" > actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'format' '
+
+ git log --format="%s" > actual &&
+ test_cmp expect actual
+'
+
+cat > expect << EOF
+ This is
+ the sixth
+ commit.
+ This is
+ the fifth
+ commit.
+EOF
+
+test_expect_success 'format %w(12,1,2)' '
+
+ git log -2 --format="%w(12,1,2)This is the %s commit." > actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'format %w(,1,2)' '
+
+ git log -2 --format="%w(,1,2)This is%nthe %s%ncommit." > actual &&
+ test_cmp expect actual
+'
+
+cat > expect << EOF
+804a787 sixth
+394ef78 fifth
+5d31159 fourth
+2fbe8c0 third
+f7dab8e second
+3a2fdcb initial
+EOF
+test_expect_success 'oneline' '
+
+ git log --oneline > actual &&
+ test_cmp expect actual
'
test_expect_success 'diff-filter=A' '
actual=$(git log --pretty="format:%s" --diff-filter=A HEAD) &&
- expect=$(echo fourth ; echo third ; echo initial) &&
+ expect=$(echo fifth ; echo fourth ; echo third ; echo initial) &&
test "$actual" = "$expect" || {
echo Oops
echo "Actual: $actual"
@@ -60,7 +125,43 @@ test_expect_success 'diff-filter=M' '
test_expect_success 'diff-filter=D' '
actual=$(git log --pretty="format:%s" --diff-filter=D HEAD) &&
- expect=$(echo fifth) &&
+ expect=$(echo sixth ; echo third) &&
+ test "$actual" = "$expect" || {
+ echo Oops
+ echo "Actual: $actual"
+ false
+ }
+
+'
+
+test_expect_success 'diff-filter=R' '
+
+ actual=$(git log -M --pretty="format:%s" --diff-filter=R HEAD) &&
+ expect=$(echo third) &&
+ test "$actual" = "$expect" || {
+ echo Oops
+ echo "Actual: $actual"
+ false
+ }
+
+'
+
+test_expect_success 'diff-filter=C' '
+
+ actual=$(git log -C -C --pretty="format:%s" --diff-filter=C HEAD) &&
+ expect=$(echo fourth) &&
+ test "$actual" = "$expect" || {
+ echo Oops
+ echo "Actual: $actual"
+ false
+ }
+
+'
+
+test_expect_success 'git log --follow' '
+
+ actual=$(git log --follow --pretty="format:%s" ichi) &&
+ expect=$(echo third ; echo second ; echo initial) &&
test "$actual" = "$expect" || {
echo Oops
echo "Actual: $actual"
@@ -69,6 +170,222 @@ test_expect_success 'diff-filter=D' '
'
+cat > expect << EOF
+804a787 sixth
+394ef78 fifth
+5d31159 fourth
+EOF
+test_expect_success 'git log --no-walk <commits> sorts by commit time' '
+ git log --no-walk --oneline 5d31159 804a787 394ef78 > actual &&
+ test_cmp expect actual
+'
+
+cat > expect << EOF
+5d31159 fourth
+804a787 sixth
+394ef78 fifth
+EOF
+test_expect_success 'git show <commits> leaves list of commits as given' '
+ git show --oneline -s 5d31159 804a787 394ef78 > actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'setup case sensitivity tests' '
+ echo case >one &&
+ test_tick &&
+ git add one
+ git commit -a -m Second
+'
+
+test_expect_success 'log --grep' '
+ echo second >expect &&
+ git log -1 --pretty="tformat:%s" --grep=sec >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log -i --grep' '
+ echo Second >expect &&
+ git log -1 --pretty="tformat:%s" -i --grep=sec >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log --grep -i' '
+ echo Second >expect &&
+ git log -1 --pretty="tformat:%s" --grep=sec -i >actual &&
+ test_cmp expect actual
+'
+
+cat > expect <<EOF
+* Second
+* sixth
+* fifth
+* fourth
+* third
+* second
+* initial
+EOF
+
+test_expect_success 'simple log --graph' '
+ git log --graph --pretty=tformat:%s >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'set up merge history' '
+ git checkout -b side HEAD~4 &&
+ test_commit side-1 1 1 &&
+ test_commit side-2 2 2 &&
+ git checkout master &&
+ git merge side
+'
+
+cat > expect <<\EOF
+* Merge branch 'side'
+|\
+| * side-2
+| * side-1
+* | Second
+* | sixth
+* | fifth
+* | fourth
+|/
+* third
+* second
+* initial
+EOF
+
+test_expect_success 'log --graph with merge' '
+ git log --graph --date-order --pretty=tformat:%s |
+ sed "s/ *$//" >actual &&
+ test_cmp expect actual
+'
+
+cat > expect <<\EOF
+* commit master
+|\ Merge: A B
+| | Author: A U Thor <author@example.com>
+| |
+| | Merge branch 'side'
+| |
+| * commit side
+| | Author: A U Thor <author@example.com>
+| |
+| | side-2
+| |
+| * commit tags/side-1
+| | Author: A U Thor <author@example.com>
+| |
+| | side-1
+| |
+* | commit master~1
+| | Author: A U Thor <author@example.com>
+| |
+| | Second
+| |
+* | commit master~2
+| | Author: A U Thor <author@example.com>
+| |
+| | sixth
+| |
+* | commit master~3
+| | Author: A U Thor <author@example.com>
+| |
+| | fifth
+| |
+* | commit master~4
+|/ Author: A U Thor <author@example.com>
+|
+| fourth
+|
+* commit tags/side-1~1
+| Author: A U Thor <author@example.com>
+|
+| third
+|
+* commit tags/side-1~2
+| Author: A U Thor <author@example.com>
+|
+| second
+|
+* commit tags/side-1~3
+ Author: A U Thor <author@example.com>
+
+ initial
+EOF
+
+test_expect_success 'log --graph with full output' '
+ git log --graph --date-order --pretty=short |
+ git name-rev --name-only --stdin |
+ sed "s/Merge:.*/Merge: A B/;s/ *$//" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'set up more tangled history' '
+ git checkout -b tangle HEAD~6 &&
+ test_commit tangle-a tangle-a a &&
+ git merge master~3 &&
+ git merge side~1 &&
+ git checkout master &&
+ git merge tangle &&
+ git checkout -b reach &&
+ test_commit reach &&
+ git checkout master &&
+ git checkout -b octopus-a &&
+ test_commit octopus-a &&
+ git checkout master &&
+ git checkout -b octopus-b &&
+ test_commit octopus-b &&
+ git checkout master &&
+ test_commit seventh &&
+ git merge octopus-a octopus-b
+ git merge reach
+'
+
+cat > expect <<\EOF
+* Merge commit 'reach'
+|\
+| \
+| \
+*-. \ Merge commit 'octopus-a'; commit 'octopus-b'
+|\ \ \
+* | | | seventh
+| | * | octopus-b
+| |/ /
+|/| |
+| * | octopus-a
+|/ /
+| * reach
+|/
+* Merge branch 'tangle'
+|\
+| * Merge branch 'side' (early part) into tangle
+| |\
+| * \ Merge branch 'master' (early part) into tangle
+| |\ \
+| * | | tangle-a
+* | | | Merge branch 'side'
+|\ \ \ \
+| * | | | side-2
+| | |_|/
+| |/| |
+| * | | side-1
+* | | | Second
+* | | | sixth
+| |_|/
+|/| |
+* | | fifth
+* | | fourth
+|/ /
+* | third
+|/
+* second
+* initial
+EOF
+
+test_expect_success 'log --graph with merge' '
+ git log --graph --date-order --pretty=tformat:%s |
+ sed "s/ *$//" >actual &&
+ test_cmp expect actual
+'
+test_done
-test_done \ No newline at end of file
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
new file mode 100755
index 0000000000..9a7d1b4466
--- /dev/null
+++ b/t/t4203-mailmap.sh
@@ -0,0 +1,215 @@
+#!/bin/sh
+
+test_description='.mailmap configurations'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo one >one &&
+ git add one &&
+ test_tick &&
+ git commit -m initial &&
+ echo two >>one &&
+ git add one &&
+ git commit --author "nick1 <bugs@company.xx>" -m second
+'
+
+cat >expect <<\EOF
+A U Thor (1):
+ initial
+
+nick1 (1):
+ second
+
+EOF
+
+test_expect_success 'No mailmap' '
+ git shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<\EOF
+Repo Guy (1):
+ initial
+
+nick1 (1):
+ second
+
+EOF
+
+test_expect_success 'default .mailmap' '
+ echo "Repo Guy <author@example.com>" > .mailmap &&
+ git shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+# Using a mailmap file in a subdirectory of the repo here, but
+# could just as well have been a file outside of the repository
+cat >expect <<\EOF
+Internal Guy (1):
+ second
+
+Repo Guy (1):
+ initial
+
+EOF
+test_expect_success 'mailmap.file set' '
+ mkdir internal_mailmap &&
+ echo "Internal Guy <bugs@company.xx>" > internal_mailmap/.mailmap &&
+ git config mailmap.file internal_mailmap/.mailmap &&
+ git shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<\EOF
+External Guy (1):
+ initial
+
+Internal Guy (1):
+ second
+
+EOF
+test_expect_success 'mailmap.file override' '
+ echo "External Guy <author@example.com>" >> internal_mailmap/.mailmap &&
+ git config mailmap.file internal_mailmap/.mailmap &&
+ git shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<\EOF
+Repo Guy (1):
+ initial
+
+nick1 (1):
+ second
+
+EOF
+
+test_expect_success 'mailmap.file non-existant' '
+ rm internal_mailmap/.mailmap &&
+ rmdir internal_mailmap &&
+ git shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<\EOF
+A U Thor (1):
+ initial
+
+nick1 (1):
+ second
+
+EOF
+test_expect_success 'No mailmap files, but configured' '
+ rm .mailmap &&
+ git shortlog HEAD >actual &&
+ test_cmp expect actual
+'
+
+# Extended mailmap configurations should give us the following output for shortlog
+cat >expect <<\EOF
+A U Thor <author@example.com> (1):
+ initial
+
+CTO <cto@company.xx> (1):
+ seventh
+
+Other Author <other@author.xx> (2):
+ third
+ fourth
+
+Santa Claus <santa.claus@northpole.xx> (2):
+ fifth
+ sixth
+
+Some Dude <some@dude.xx> (1):
+ second
+
+EOF
+
+test_expect_success 'Shortlog output (complex mapping)' '
+ echo three >>one &&
+ git add one &&
+ test_tick &&
+ git commit --author "nick2 <bugs@company.xx>" -m third &&
+
+ echo four >>one &&
+ git add one &&
+ test_tick &&
+ git commit --author "nick2 <nick2@company.xx>" -m fourth &&
+
+ echo five >>one &&
+ git add one &&
+ test_tick &&
+ git commit --author "santa <me@company.xx>" -m fifth &&
+
+ echo six >>one &&
+ git add one &&
+ test_tick &&
+ git commit --author "claus <me@company.xx>" -m sixth &&
+
+ echo seven >>one &&
+ git add one &&
+ test_tick &&
+ git commit --author "CTO <cto@coompany.xx>" -m seventh &&
+
+ mkdir internal_mailmap &&
+ echo "Committed <committer@example.com>" > internal_mailmap/.mailmap &&
+ echo "<cto@company.xx> <cto@coompany.xx>" >> internal_mailmap/.mailmap &&
+ echo "Some Dude <some@dude.xx> nick1 <bugs@company.xx>" >> internal_mailmap/.mailmap &&
+ echo "Other Author <other@author.xx> nick2 <bugs@company.xx>" >> internal_mailmap/.mailmap &&
+ echo "Other Author <other@author.xx> <nick2@company.xx>" >> internal_mailmap/.mailmap &&
+ echo "Santa Claus <santa.claus@northpole.xx> <me@company.xx>" >> internal_mailmap/.mailmap &&
+ echo "Santa Claus <santa.claus@northpole.xx> <me@company.xx>" >> internal_mailmap/.mailmap &&
+
+ git shortlog -e HEAD >actual &&
+ test_cmp expect actual
+
+'
+
+# git log with --pretty format which uses the name and email mailmap placemarkers
+cat >expect <<\EOF
+Author CTO <cto@coompany.xx> maps to CTO <cto@company.xx>
+Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+
+Author claus <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx>
+Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+
+Author santa <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx>
+Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+
+Author nick2 <nick2@company.xx> maps to Other Author <other@author.xx>
+Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+
+Author nick2 <bugs@company.xx> maps to Other Author <other@author.xx>
+Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+
+Author nick1 <bugs@company.xx> maps to Some Dude <some@dude.xx>
+Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+
+Author A U Thor <author@example.com> maps to A U Thor <author@example.com>
+Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+EOF
+
+test_expect_success 'Log output (complex mapping)' '
+ git log --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
+ test_cmp expect actual
+'
+
+# git blame
+cat >expect <<\EOF
+^3a2fdcb (A U Thor 2005-04-07 15:13:13 -0700 1) one
+7de6f99b (Some Dude 2005-04-07 15:13:13 -0700 2) two
+5815879d (Other Author 2005-04-07 15:14:13 -0700 3) three
+ff859d96 (Other Author 2005-04-07 15:15:13 -0700 4) four
+5ab6d4fa (Santa Claus 2005-04-07 15:16:13 -0700 5) five
+38a42d8b (Santa Claus 2005-04-07 15:17:13 -0700 6) six
+8ddc0386 (CTO 2005-04-07 15:18:13 -0700 7) seven
+EOF
+
+test_expect_success 'Blame output (complex mapping)' '
+ git blame one >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
new file mode 100755
index 0000000000..04f7bae850
--- /dev/null
+++ b/t/t4204-patch-id.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+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
+'
+
+test_expect_success 'patch-id output is well-formed' '
+ git log -p -1 | git patch-id > output &&
+ grep "^[a-f0-9]\{40\} $(git rev-parse HEAD)$" output
+'
+
+get_patch_id () {
+ git log -p -1 "$1" | git patch-id |
+ sed "s# .*##" > patch-id_"$1"
+}
+
+test_expect_success 'patch-id detects equality' '
+ get_patch_id master &&
+ get_patch_id same &&
+ test_cmp patch-id_master patch-id_same
+'
+
+test_expect_success 'patch-id detects inequality' '
+ get_patch_id master &&
+ get_patch_id notsame &&
+ ! test_cmp patch-id_master patch-id_notsame
+'
+
+test_done
diff --git a/t/t4252-am-options.sh b/t/t4252-am-options.sh
new file mode 100755
index 0000000000..f603c1b133
--- /dev/null
+++ b/t/t4252-am-options.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+test_description='git am with options and not losing them'
+. ./test-lib.sh
+
+tm="$TEST_DIRECTORY/t4252"
+
+test_expect_success setup '
+ cp "$tm/file-1-0" file-1 &&
+ cp "$tm/file-2-0" file-2 &&
+ git add file-1 file-2 &&
+ test_tick &&
+ git commit -m initial &&
+ git tag initial
+'
+
+test_expect_success 'interrupted am --whitespace=fix' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am --whitespace=fix "$tm"/am-test-1-? &&
+ git am --skip &&
+ grep 3 file-1 &&
+ grep "^Six$" file-2
+'
+
+test_expect_success 'interrupted am -C1' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am -C1 "$tm"/am-test-2-? &&
+ git am --skip &&
+ grep 3 file-1 &&
+ grep "^Three$" file-2
+'
+
+test_expect_success 'interrupted am -p2' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am -p2 "$tm"/am-test-3-? &&
+ git am --skip &&
+ grep 3 file-1 &&
+ grep "^Three$" file-2
+'
+
+test_expect_success 'interrupted am -C1 -p2' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am -p2 -C1 "$tm"/am-test-4-? &&
+ git am --skip &&
+ grep 3 file-1 &&
+ grep "^Three$" file-2
+'
+
+test_expect_success 'interrupted am --directory="frotz nitfol"' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am --directory="frotz nitfol" "$tm"/am-test-5-? &&
+ git am --skip &&
+ grep One "frotz nitfol/file-5"
+'
+
+test_expect_success 'apply to a funny path' '
+ with_sq="with'\''sq"
+ rm -fr .git/rebase-apply &&
+ git reset --hard initial &&
+ git am --directory="$with_sq" "$tm"/am-test-5-2 &&
+ test -f "$with_sq/file-5"
+'
+
+test_expect_success 'am --reject' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am --reject "$tm"/am-test-6-1 &&
+ grep "@@ -1,3 +1,3 @@" file-2.rej &&
+ test_must_fail git diff-files --exit-code --quiet file-2 &&
+ grep "[-]-reject" .git/rebase-apply/apply-opt
+'
+
+test_done
diff --git a/t/t4252/am-test-1-1 b/t/t4252/am-test-1-1
new file mode 100644
index 0000000000..b0c09dc965
--- /dev/null
+++ b/t/t4252/am-test-1-1
@@ -0,0 +1,19 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Three
+
+Application of this should be rejected because the first line in the
+context does not match.
+
+diff --git i/file-1 w/file-1
+index 06e567b..10f8342 100644
+--- i/file-1
++++ w/file-1
+@@ -1,6 +1,6 @@
+ One
+ 2
+-3
++Three
+ 4
+ 5
+ 6
diff --git a/t/t4252/am-test-1-2 b/t/t4252/am-test-1-2
new file mode 100644
index 0000000000..1b874ae115
--- /dev/null
+++ b/t/t4252/am-test-1-2
@@ -0,0 +1,21 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with --whitespace=fix should lose
+the trailing whitespace after "Six".
+
+diff --git i/file-2 w/file-2
+index 06e567b..b6f3a16 100644
+--- i/file-2
++++ w/file-2
+@@ -1,7 +1,7 @@
+ 1
+ 2
+-3
++Three
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/am-test-2-1 b/t/t4252/am-test-2-1
new file mode 100644
index 0000000000..feda94a0cc
--- /dev/null
+++ b/t/t4252/am-test-2-1
@@ -0,0 +1,19 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Three
+
+Application of this should be rejected even with -C1 because the
+preimage line in the context does not match.
+
+diff --git i/file-1 w/file-1
+index 06e567b..10f8342 100644
+--- i/file-1
++++ w/file-1
+@@ -1,6 +1,6 @@
+ 1
+ 2
+-Tres
++Three
+ 4
+ 5
+ 6
diff --git a/t/t4252/am-test-2-2 b/t/t4252/am-test-2-2
new file mode 100644
index 0000000000..2ac6600976
--- /dev/null
+++ b/t/t4252/am-test-2-2
@@ -0,0 +1,21 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with -C1 should be successful even though
+the first line in the context does not match.
+
+diff --git i/file-2 w/file-2
+index 06e567b..b6f3a16 100644
+--- i/file-2
++++ w/file-2
+@@ -1,7 +1,7 @@
+ One
+ 2
+-3
++Three
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/am-test-3-1 b/t/t4252/am-test-3-1
new file mode 100644
index 0000000000..608e5abba4
--- /dev/null
+++ b/t/t4252/am-test-3-1
@@ -0,0 +1,19 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Three
+
+Application of this should be rejected even with -p2 because the
+preimage line in the context does not match.
+
+diff --git i/junk/file-1 w/junk/file-1
+index 06e567b..10f8342 100644
+--- i/junk/file-1
++++ w/junk/file-1
+@@ -1,6 +1,6 @@
+ 1
+ 2
+-Tres
++Three
+ 4
+ 5
+ 6
diff --git a/t/t4252/am-test-3-2 b/t/t4252/am-test-3-2
new file mode 100644
index 0000000000..0081b96f2a
--- /dev/null
+++ b/t/t4252/am-test-3-2
@@ -0,0 +1,21 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with -p2 should be successful even though
+the patch is against a wrong level.
+
+diff --git i/junk/file-2 w/junk/file-2
+index 06e567b..b6f3a16 100644
+--- i/junk/file-2
++++ w/junk/file-2
+@@ -1,7 +1,7 @@
+ 1
+ 2
+-3
++Three
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/am-test-4-1 b/t/t4252/am-test-4-1
new file mode 100644
index 0000000000..e48cd6cbde
--- /dev/null
+++ b/t/t4252/am-test-4-1
@@ -0,0 +1,19 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Three
+
+Application of this should be rejected even with -C1 -p2 because
+the preimage line in the context does not match.
+
+diff --git i/junk/file-1 w/junk/file-1
+index 06e567b..10f8342 100644
+--- i/junk/file-1
++++ w/junk/file-1
+@@ -1,6 +1,6 @@
+ 1
+ 2
+-Tres
++Three
+ 4
+ 5
+ 6
diff --git a/t/t4252/am-test-4-2 b/t/t4252/am-test-4-2
new file mode 100644
index 0000000000..0e69bfa55b
--- /dev/null
+++ b/t/t4252/am-test-4-2
@@ -0,0 +1,22 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with -C1 -p2 should be successful even though
+the patch is against a wrong level and the first context line does
+not match.
+
+diff --git i/junk/file-2 w/junk/file-2
+index 06e567b..b6f3a16 100644
+--- i/junk/file-2
++++ w/junk/file-2
+@@ -1,7 +1,7 @@
+ One
+ 2
+-3
++Three
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/am-test-5-1 b/t/t4252/am-test-5-1
new file mode 100644
index 0000000000..da7bf29cbe
--- /dev/null
+++ b/t/t4252/am-test-5-1
@@ -0,0 +1,20 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with --directory='frotz nitfol' should fail
+
+diff --git i/junk/file-2 w/junk/file-2
+index 06e567b..b6f3a16 100644
+--- i/junk/file-2
++++ w/junk/file-2
+@@ -1,7 +1,7 @@
+ One
+ 2
+-3
++Three
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/am-test-5-2 b/t/t4252/am-test-5-2
new file mode 100644
index 0000000000..373025bcf6
--- /dev/null
+++ b/t/t4252/am-test-5-2
@@ -0,0 +1,15 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with --directory='frotz nitfol' should succeed
+
+diff --git i/file-5 w/file-5
+new file mode 100644
+index 000000..1d6ed9f
+--- /dev/null
++++ w/file-5
+@@ -0,0 +1,3 @@
++One
++two
++three
diff --git a/t/t4252/am-test-6-1 b/t/t4252/am-test-6-1
new file mode 100644
index 0000000000..a8859e9b8f
--- /dev/null
+++ b/t/t4252/am-test-6-1
@@ -0,0 +1,21 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Huh
+
+Should fail and leave rejects
+
+diff --git i/file-2 w/file-2
+index 06e567b..b6f3a16 100644
+--- i/file-2
++++ w/file-2
+@@ -1,3 +1,3 @@
+-0
++One
+ 2
+ 3
+@@ -4,4 +4,4 @@
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/file-1-0 b/t/t4252/file-1-0
new file mode 100644
index 0000000000..06e567b11d
--- /dev/null
+++ b/t/t4252/file-1-0
@@ -0,0 +1,7 @@
+1
+2
+3
+4
+5
+6
+7
diff --git a/t/t4252/file-2-0 b/t/t4252/file-2-0
new file mode 100644
index 0000000000..06e567b11d
--- /dev/null
+++ b/t/t4252/file-2-0
@@ -0,0 +1,7 @@
+1
+2
+3
+4
+5
+6
+7
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index fa62b6aa21..27bfba55bd 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -25,7 +25,6 @@ commit id embedding:
'
. ./test-lib.sh
-TAR=${TAR:-tar}
UNZIP=${UNZIP:-unzip}
SUBSTFORMAT=%H%n
@@ -38,13 +37,22 @@ test_expect_success \
cp /bin/sh a/bin &&
printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
printf "A not substituted O" >a/substfile2 &&
- ln -s a a/l1 &&
+ if test_have_prereq SYMLINKS; then
+ ln -s a a/l1
+ else
+ printf %s a > a/l1
+ fi &&
(p=long_path_to_a_file && cd a &&
for depth in 1 2 3 4 5; do mkdir $p && cd $p; done &&
echo text >file_with_long_path) &&
(cd a && find .) | sort >a.lst'
test_expect_success \
+ 'add ignored file' \
+ '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 &&
@@ -54,6 +62,15 @@ test_expect_success \
git commit-tree $treeid </dev/null)'
test_expect_success \
+ 'create bare clone' \
+ 'git clone --bare . bare.git &&
+ cp .git/info/attributes bare.git/info/attributes'
+
+test_expect_success \
+ 'remove ignored file' \
+ 'rm a/ignored'
+
+test_expect_success \
'git archive' \
'git archive HEAD >b.tar'
@@ -63,29 +80,45 @@ test_expect_success \
test_expect_success \
'git archive vs. git tar-tree' \
- 'diff b.tar b2.tar'
+ 'test_cmp b.tar b2.tar'
+
+test_expect_success \
+ 'git archive in a bare repo' \
+ '(cd bare.git && git archive HEAD) >b3.tar'
+
+test_expect_success \
+ 'git archive vs. the same in a bare repo' \
+ 'test_cmp b.tar b3.tar'
+
+test_expect_success 'git archive with --output' \
+ 'git archive --output=b4.tar HEAD &&
+ test_cmp b.tar b4.tar'
+
+test_expect_success 'git archive --remote' \
+ 'git archive --remote=. HEAD >b5.tar &&
+ test_cmp b.tar b5.tar'
test_expect_success \
'validate file modification time' \
- 'TZ=GMT $TAR tvf b.tar a/a |
- awk \{print\ \$4,\ \(length\(\$5\)\<7\)\ ?\ \$5\":00\"\ :\ \$5\} \
- >b.mtime &&
- echo "2005-05-27 22:00:00" >expected.mtime &&
- diff expected.mtime b.mtime'
+ 'mkdir extract &&
+ "$TAR" xf b.tar -C extract a/a &&
+ test-chmtime -v +0 extract/a/a |cut -f 1 >b.mtime &&
+ echo "1117231200" >expected.mtime &&
+ test_cmp expected.mtime b.mtime'
test_expect_success \
'git get-tar-commit-id' \
'git get-tar-commit-id <b.tar >b.commitid &&
- diff .git/$(git symbolic-ref HEAD) b.commitid'
+ test_cmp .git/$(git symbolic-ref HEAD) b.commitid'
test_expect_success \
'extract tar archive' \
- '(cd b && $TAR xf -) <b.tar'
+ '(cd b && "$TAR" xf -) <b.tar'
test_expect_success \
'validate filenames' \
'(cd b/a && find .) | sort >b.lst &&
- diff a.lst b.lst'
+ test_cmp a.lst b.lst'
test_expect_success \
'validate file contents' \
@@ -97,12 +130,12 @@ test_expect_success \
test_expect_success \
'extract tar archive with prefix' \
- '(cd c && $TAR xf -) <c.tar'
+ '(cd c && "$TAR" xf -) <c.tar'
test_expect_success \
'validate filenames with prefix' \
'(cd c/prefix/a && find .) | sort >c.lst &&
- diff a.lst c.lst'
+ test_cmp a.lst c.lst'
test_expect_success \
'validate file contents with prefix' \
@@ -110,56 +143,79 @@ test_expect_success \
test_expect_success \
'create archives with substfiles' \
- 'echo "substfile?" export-subst >a/.gitattributes &&
+ 'cp .git/info/attributes .git/info/attributes.before &&
+ echo "substfile?" export-subst >>.git/info/attributes &&
git archive HEAD >f.tar &&
git archive --prefix=prefix/ HEAD >g.tar &&
- rm a/.gitattributes'
+ mv .git/info/attributes.before .git/info/attributes'
test_expect_success \
'extract substfiles' \
- '(mkdir f && cd f && $TAR xf -) <f.tar'
+ '(mkdir f && cd f && "$TAR" xf -) <f.tar'
test_expect_success \
'validate substfile contents' \
'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
>f/a/substfile1.expected &&
- diff f/a/substfile1.expected f/a/substfile1 &&
- diff a/substfile2 f/a/substfile2
+ test_cmp f/a/substfile1.expected f/a/substfile1 &&
+ test_cmp a/substfile2 f/a/substfile2
'
test_expect_success \
'extract substfiles from archive with prefix' \
- '(mkdir g && cd g && $TAR xf -) <g.tar'
+ '(mkdir g && cd g && "$TAR" xf -) <g.tar'
test_expect_success \
'validate substfile contents from archive with prefix' \
'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
>g/prefix/a/substfile1.expected &&
- diff g/prefix/a/substfile1.expected g/prefix/a/substfile1 &&
- diff a/substfile2 g/prefix/a/substfile2
+ test_cmp g/prefix/a/substfile1.expected g/prefix/a/substfile1 &&
+ test_cmp a/substfile2 g/prefix/a/substfile2
'
test_expect_success \
'git archive --format=zip' \
'git archive --format=zip HEAD >d.zip'
+test_expect_success \
+ 'git archive --format=zip in a bare repo' \
+ '(cd bare.git && git archive --format=zip HEAD) >d1.zip'
+
+test_expect_success \
+ 'git archive --format=zip vs. the same in a bare repo' \
+ 'test_cmp 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_expect_success 'git archive with --output, inferring format' '
+ git archive --output=d3.zip HEAD &&
+ test_cmp d.zip d3.zip
+'
+
+test_expect_success 'git archive with --output, override inferred format' '
+ git archive --format=tar --output=d4.zip HEAD &&
+ test_cmp b.tar d4.zip
+'
+
$UNZIP -v >/dev/null 2>&1
if [ $? -eq 127 ]; then
- echo "Skipping ZIP tests, because unzip was not found"
- test_done
- exit
+ say "Skipping ZIP tests, because unzip was not found"
+else
+ test_set_prereq UNZIP
fi
-test_expect_success \
+test_expect_success UNZIP \
'extract ZIP archive' \
'(mkdir d && cd d && $UNZIP ../d.zip)'
-test_expect_success \
+test_expect_success UNZIP \
'validate filenames' \
'(cd d/a && find .) | sort >d.lst &&
- diff a.lst d.lst'
+ test_cmp a.lst d.lst'
-test_expect_success \
+test_expect_success UNZIP \
'validate file contents' \
'diff -r a d/a'
@@ -167,16 +223,16 @@ test_expect_success \
'git archive --format=zip with prefix' \
'git archive --format=zip --prefix=prefix/ HEAD >e.zip'
-test_expect_success \
+test_expect_success UNZIP \
'extract ZIP archive with prefix' \
'(mkdir e && cd e && $UNZIP ../e.zip)'
-test_expect_success \
+test_expect_success UNZIP \
'validate filenames with prefix' \
'(cd e/prefix/a && find .) | sort >e.lst &&
- diff a.lst e.lst'
+ test_cmp a.lst e.lst'
-test_expect_success \
+test_expect_success UNZIP \
'validate file contents with prefix' \
'diff -r a e/prefix/a'
@@ -184,4 +240,16 @@ test_expect_success \
'git archive --list outside of a git repo' \
'GIT_DIR=some/non-existing/directory git archive --list'
+test_expect_success 'git-archive --prefix=olde-' '
+ git archive --prefix=olde- >h.tar HEAD &&
+ (
+ mkdir h &&
+ cd h &&
+ "$TAR" xf - <../h.tar
+ ) &&
+ test -d h/olde-a &&
+ test -d h/olde-a/bin &&
+ test -f h/olde-a/bin/sh
+'
+
test_done
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
new file mode 100755
index 0000000000..426b319bd3
--- /dev/null
+++ b/t/t5001-archive-attr.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+
+test_description='git archive attribute tests'
+
+. ./test-lib.sh
+
+SUBSTFORMAT=%H%n
+
+test_expect_exists() {
+ test_expect_success " $1 exists" "test -e $1"
+}
+
+test_expect_missing() {
+ test_expect_success " $1 does not exist" "test ! -e $1"
+}
+
+test_expect_success 'setup' '
+ echo ignored >ignored &&
+ echo ignored export-ignore >>.git/info/attributes &&
+ git add ignored &&
+
+ echo ignored by tree >ignored-by-tree &&
+ echo ignored-by-tree export-ignore >.gitattributes &&
+ git add ignored-by-tree .gitattributes &&
+
+ echo ignored by worktree >ignored-by-worktree &&
+ echo ignored-by-worktree export-ignore >.gitattributes &&
+ git add ignored-by-worktree &&
+
+ printf "A\$Format:%s\$O" "$SUBSTFORMAT" >nosubstfile &&
+ printf "A\$Format:%s\$O" "$SUBSTFORMAT" >substfile1 &&
+ printf "A not substituted O" >substfile2 &&
+ echo "substfile?" export-subst >>.git/info/attributes &&
+ git add nosubstfile substfile1 substfile2 &&
+
+ git commit -m. &&
+
+ git clone --bare . bare &&
+ cp .git/info/attributes bare/info/attributes
+'
+
+test_expect_success 'git archive' '
+ git archive HEAD >archive.tar &&
+ (mkdir archive && cd archive && "$TAR" xf -) <archive.tar
+'
+
+test_expect_missing archive/ignored
+test_expect_missing archive/ignored-by-tree
+test_expect_exists archive/ignored-by-worktree
+
+test_expect_success 'git archive with worktree attributes' '
+ git archive --worktree-attributes HEAD >worktree.tar &&
+ (mkdir worktree && cd worktree && "$TAR" xf -) <worktree.tar
+'
+
+test_expect_missing worktree/ignored
+test_expect_exists worktree/ignored-by-tree
+test_expect_missing worktree/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_expect_success 'git archive with worktree attributes, bare' '
+ (cd bare && git archive --worktree-attributes HEAD) >bare-worktree.tar &&
+ (mkdir bare-worktree && cd bare-worktree && "$TAR" xf -) <bare-worktree.tar
+'
+
+test_expect_missing bare-worktree/ignored
+test_expect_exists bare-worktree/ignored-by-tree
+test_expect_exists bare-worktree/ignored-by-worktree
+
+test_expect_success 'export-subst' '
+ git log "--pretty=format:A${SUBSTFORMAT}O" HEAD >substfile1.expected &&
+ test_cmp nosubstfile archive/nosubstfile &&
+ test_cmp substfile1.expected archive/substfile1 &&
+ 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/t5100-mailinfo.sh b/t/t5100-mailinfo.sh
index d6c55c1157..ebc36c1758 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -8,21 +8,85 @@ test_description='git mailinfo and git mailsplit test'
. ./test-lib.sh
test_expect_success 'split sample box' \
- 'git mailsplit -o. ../t5100/sample.mbox >last &&
+ 'git mailsplit -o. "$TEST_DIRECTORY"/t5100/sample.mbox >last &&
last=`cat last` &&
echo total is $last &&
- test `cat last` = 9'
+ test `cat last` = 16'
+
+check_mailinfo () {
+ mail=$1 opt=$2
+ mo="$mail$opt"
+ git mailinfo -u $opt msg$mo patch$mo <$mail >info$mo &&
+ test_cmp "$TEST_DIRECTORY"/t5100/msg$mo msg$mo &&
+ test_cmp "$TEST_DIRECTORY"/t5100/patch$mo patch$mo &&
+ test_cmp "$TEST_DIRECTORY"/t5100/info$mo info$mo
+}
+
for mail in `echo 00*`
do
- test_expect_success "mailinfo $mail" \
- "git mailinfo -u msg$mail patch$mail <$mail >info$mail &&
+ test_expect_success "mailinfo $mail" '
+ check_mailinfo $mail "" &&
+ if test -f "$TEST_DIRECTORY"/t5100/msg$mail--scissors
+ then
+ check_mailinfo $mail --scissors
+ fi &&
+ if test -f "$TEST_DIRECTORY"/t5100/msg$mail--no-inbody-headers
+ then
+ check_mailinfo $mail --no-inbody-headers
+ fi
+ '
+done
+
+
+test_expect_success 'split box with rfc2047 samples' \
+ 'mkdir rfc2047 &&
+ git mailsplit -orfc2047 "$TEST_DIRECTORY"/t5100/rfc2047-samples.mbox \
+ >rfc2047/last &&
+ last=`cat rfc2047/last` &&
+ echo total is $last &&
+ test `cat rfc2047/last` = 11'
+
+for mail in `echo rfc2047/00*`
+do
+ test_expect_success "mailinfo $mail" '
+ git mailinfo -u $mail-msg $mail-patch <$mail >$mail-info &&
echo msg &&
- diff ../t5100/msg$mail msg$mail &&
+ test_cmp "$TEST_DIRECTORY"/t5100/empty $mail-msg &&
echo patch &&
- diff ../t5100/patch$mail patch$mail &&
+ test_cmp "$TEST_DIRECTORY"/t5100/empty $mail-patch &&
echo info &&
- diff ../t5100/info$mail info$mail"
+ test_cmp "$TEST_DIRECTORY"/t5100/rfc2047-info-$(basename $mail) $mail-info
+ '
done
+test_expect_success 'respect NULs' '
+
+ git mailsplit -d3 -o. "$TEST_DIRECTORY"/t5100/nul-plain &&
+ test_cmp "$TEST_DIRECTORY"/t5100/nul-plain 001 &&
+ (cat 001 | git mailinfo msg patch) &&
+ test 4 = $(wc -l < patch)
+
+'
+
+test_expect_success 'Preserve NULs out of MIME encoded message' '
+
+ git mailsplit -d5 -o. "$TEST_DIRECTORY"/t5100/nul-b64.in &&
+ test_cmp "$TEST_DIRECTORY"/t5100/nul-b64.in 00001 &&
+ git mailinfo msg patch <00001 &&
+ test_cmp "$TEST_DIRECTORY"/t5100/nul-b64.expect patch
+
+'
+
+test_expect_success 'mailinfo on from header without name works' '
+
+ mkdir info-from &&
+ git mailsplit -oinfo-from "$TEST_DIRECTORY"/t5100/info-from.in &&
+ test_cmp "$TEST_DIRECTORY"/t5100/info-from.in info-from/0001 &&
+ git mailinfo info-from/msg info-from/patch \
+ <info-from/0001 >info-from/out &&
+ test_cmp "$TEST_DIRECTORY"/t5100/info-from.expect info-from/out
+
+'
+
test_done
diff --git a/t/t5100/.gitattributes b/t/t5100/.gitattributes
new file mode 100644
index 0000000000..c93f5142fa
--- /dev/null
+++ b/t/t5100/.gitattributes
@@ -0,0 +1,4 @@
+msg* encoding=UTF-8
+info* encoding=UTF-8
+rfc2047-info-* encoding=UTF-8
+sample.mbox encoding=UTF-8
diff --git a/t/t5100/empty b/t/t5100/empty
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/t/t5100/empty
diff --git a/t/t5100/info-from.expect b/t/t5100/info-from.expect
new file mode 100644
index 0000000000..c31d2eb550
--- /dev/null
+++ b/t/t5100/info-from.expect
@@ -0,0 +1,5 @@
+Author: bare@example.com
+Email: bare@example.com
+Subject: testing bare address in from header
+Date: Sun, 25 May 2008 00:38:18 -0700
+
diff --git a/t/t5100/info-from.in b/t/t5100/info-from.in
new file mode 100644
index 0000000000..4f082093fc
--- /dev/null
+++ b/t/t5100/info-from.in
@@ -0,0 +1,8 @@
+From 667d8940e719cddee1cfe237cbbe215e20270b09 Mon Sep 17 00:00:00 2001
+From: bare@example.com
+Date: Sun, 25 May 2008 00:38:18 -0700
+Subject: [PATCH] testing bare address in from header
+
+commit message
+---
+patch
diff --git a/t/t5100/info0001 b/t/t5100/info0001
index 8c052777e0..f951538acc 100644
--- a/t/t5100/info0001
+++ b/t/t5100/info0001
@@ -1,4 +1,4 @@
-Author: A U Thor
+Author: A (zzz) U Thor (Comment)
Email: a.u.thor@example.com
Subject: a commit.
Date: Fri, 9 Jun 2006 00:44:16 -0700
diff --git a/t/t5100/info0010 b/t/t5100/info0010
new file mode 100644
index 0000000000..1791241e46
--- /dev/null
+++ b/t/t5100/info0010
@@ -0,0 +1,5 @@
+Author: Lukas Sandström
+Email: lukass@etek.chalmers.se
+Subject: git-mailinfo: Fix getting the subject from the body
+Date: Thu, 10 Jul 2008 23:41:33 +0200
+
diff --git a/t/t5100/info0011 b/t/t5100/info0011
new file mode 100644
index 0000000000..da5a605a12
--- /dev/null
+++ b/t/t5100/info0011
@@ -0,0 +1,5 @@
+Author: A U Thor
+Email: a.u.thor@example.com
+Subject: Xyzzy
+Date: Fri, 8 Aug 2008 13:08:37 +0200 (CEST)
+
diff --git a/t/t5100/info0012 b/t/t5100/info0012
new file mode 100644
index 0000000000..ac1216ff75
--- /dev/null
+++ b/t/t5100/info0012
@@ -0,0 +1,5 @@
+Author: Dmitriy Blinov
+Email: bda@mnsspb.ru
+Subject: Изменён ÑпиÑок пакетов необходимых Ð´Ð»Ñ Ñборки
+Date: Wed, 12 Nov 2008 17:54:41 +0300
+
diff --git a/t/t5100/info0013 b/t/t5100/info0013
new file mode 100644
index 0000000000..bbe049e20e
--- /dev/null
+++ b/t/t5100/info0013
@@ -0,0 +1,5 @@
+Author: A U Thor
+Email: a.u.thor@example.com
+Subject: a patch
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+
diff --git a/t/t5100/info0014 b/t/t5100/info0014
new file mode 100644
index 0000000000..08566b34b9
--- /dev/null
+++ b/t/t5100/info0014
@@ -0,0 +1,5 @@
+Author: Junio Hamano
+Email: junkio@cox.net
+Subject: BLAH ONE
+Date: Thu, 20 Aug 2009 17:18:22 -0700
+
diff --git a/t/t5100/info0014--scissors b/t/t5100/info0014--scissors
new file mode 100644
index 0000000000..ab9c8d0905
--- /dev/null
+++ b/t/t5100/info0014--scissors
@@ -0,0 +1,5 @@
+Author: Junio C Hamano
+Email: gitster@pobox.com
+Subject: Teach mailinfo to ignore everything before -- >8 -- mark
+Date: Thu, 20 Aug 2009 17:18:22 -0700
+
diff --git a/t/t5100/info0015 b/t/t5100/info0015
new file mode 100644
index 0000000000..0114f106c5
--- /dev/null
+++ b/t/t5100/info0015
@@ -0,0 +1,5 @@
+Author:
+Email:
+Subject: check bogus body header (from)
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+
diff --git a/t/t5100/info0015--no-inbody-headers b/t/t5100/info0015--no-inbody-headers
new file mode 100644
index 0000000000..c4d8d7720e
--- /dev/null
+++ b/t/t5100/info0015--no-inbody-headers
@@ -0,0 +1,5 @@
+Author: A U Thor
+Email: a.u.thor@example.com
+Subject: check bogus body header (from)
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+
diff --git a/t/t5100/info0016 b/t/t5100/info0016
new file mode 100644
index 0000000000..38ccd0dcf2
--- /dev/null
+++ b/t/t5100/info0016
@@ -0,0 +1,5 @@
+Author: A U Thor
+Email: a.u.thor@example.com
+Subject: check bogus body header (date)
+Date: bogus
+
diff --git a/t/t5100/info0016--no-inbody-headers b/t/t5100/info0016--no-inbody-headers
new file mode 100644
index 0000000000..f4857d45df
--- /dev/null
+++ b/t/t5100/info0016--no-inbody-headers
@@ -0,0 +1,5 @@
+Author: A U Thor
+Email: a.u.thor@example.com
+Subject: check bogus body header (date)
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+
diff --git a/t/t5100/msg0010 b/t/t5100/msg0010
new file mode 100644
index 0000000000..a96c230092
--- /dev/null
+++ b/t/t5100/msg0010
@@ -0,0 +1,5 @@
+"Subject: " isn't in the static array "header", and thus
+memcmp("Subject: ", header[i], 7) will never match.
+
+Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/t/t5100/msg0011 b/t/t5100/msg0011
new file mode 100644
index 0000000000..4667f21007
--- /dev/null
+++ b/t/t5100/msg0011
@@ -0,0 +1,2 @@
+Here comes a commit log message, and
+its second line is here.
diff --git a/t/t5100/msg0012 b/t/t5100/msg0012
new file mode 100644
index 0000000000..1dc2bf7f7f
--- /dev/null
+++ b/t/t5100/msg0012
@@ -0,0 +1,7 @@
+textlive-* иÑправлены на texlive-*
+docutils заменён на python-docutils
+
+ДейÑтвительно, оказалоÑÑŒ, что rest2web вытÑгивает за Ñобой
+python-docutils. Ð’ то Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ðº Ñам rest2web не нужен.
+
+Signed-off-by: Dmitriy Blinov <bda@mnsspb.ru>
diff --git a/t/t5100/msg0013 b/t/t5100/msg0013
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/t/t5100/msg0013
diff --git a/t/t5100/msg0014 b/t/t5100/msg0014
new file mode 100644
index 0000000000..62e5cd2ecd
--- /dev/null
+++ b/t/t5100/msg0014
@@ -0,0 +1,18 @@
+In real life, we will see a discussion that inspired this patch
+discussing related and unrelated things around >8 scissors mark
+in this part of the message.
+
+Subject: [PATCH] BLAH TWO
+
+And then we will see the scissors.
+
+ This line is not a scissors mark -- >8 -- but talks about it.
+ - - >8 - - please remove everything above this line - - >8 - -
+
+Subject: [PATCH] Teach mailinfo to ignore everything before -- >8 -- mark
+From: Junio C Hamano <gitster@pobox.com>
+
+This teaches mailinfo the scissors -- >8 -- mark; the command ignores
+everything before it in the message body.
+
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/t/t5100/msg0014--scissors b/t/t5100/msg0014--scissors
new file mode 100644
index 0000000000..259c6a46d2
--- /dev/null
+++ b/t/t5100/msg0014--scissors
@@ -0,0 +1,4 @@
+This teaches mailinfo the scissors -- >8 -- mark; the command ignores
+everything before it in the message body.
+
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/t/t5100/msg0015 b/t/t5100/msg0015
new file mode 100644
index 0000000000..9577238685
--- /dev/null
+++ b/t/t5100/msg0015
@@ -0,0 +1,2 @@
+- a list
+ - of stuff
diff --git a/t/t5100/msg0015--no-inbody-headers b/t/t5100/msg0015--no-inbody-headers
new file mode 100644
index 0000000000..be5115b1c1
--- /dev/null
+++ b/t/t5100/msg0015--no-inbody-headers
@@ -0,0 +1,3 @@
+From: bogosity
+ - a list
+ - of stuff
diff --git a/t/t5100/msg0016 b/t/t5100/msg0016
new file mode 100644
index 0000000000..0d9adada96
--- /dev/null
+++ b/t/t5100/msg0016
@@ -0,0 +1,2 @@
+and some content
+
diff --git a/t/t5100/msg0016--no-inbody-headers b/t/t5100/msg0016--no-inbody-headers
new file mode 100644
index 0000000000..1063f51178
--- /dev/null
+++ b/t/t5100/msg0016--no-inbody-headers
@@ -0,0 +1,4 @@
+Date: bogus
+
+and some content
+
diff --git a/t/t5100/nul-b64.expect b/t/t5100/nul-b64.expect
new file mode 100644
index 0000000000..d7d680f631
--- /dev/null
+++ b/t/t5100/nul-b64.expect
Binary files differ
diff --git a/t/t5100/nul-b64.in b/t/t5100/nul-b64.in
new file mode 100644
index 0000000000..16540d961f
--- /dev/null
+++ b/t/t5100/nul-b64.in
@@ -0,0 +1,37 @@
+From 667d8940e719cddee1cfe237cbbe215e20270b09 Mon Sep 17 00:00:00 2001
+From: Junio C Hamano <gitster@pobox.com>
+Date: Sun, 25 May 2008 00:38:18 -0700
+Subject: [PATCH] second
+Content-Transfer-Encoding: base64
+
+LS0tCiBmaWxlIHwgIEJpbiAxMzU3IC0+IDEzNTcgYnl0ZXMKIDEgZmlsZXMgY2hhbmdlZCwg
+MCBpbnNlcnRpb25zKCspLCAwIGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL2ZpbGUgYi9m
+aWxlCmluZGV4IDc3MzYxZDguLjllMDJiZTYgMTAwNjQ0Ci0tLSBhL2ZpbGUKKysrIGIvZmls
+ZQpAQCAtMSwxMiArMSwxMiBAQAogTG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNl
+Y3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIFN1c3BlbmRpc3NlCiBzaXQgYW1ldCB0dXJwaXMg
+ZWdldCBlc3QgY3Vyc3VzIGxhb3JlZXQuIEFsaXF1YW0gbWF1cmlzLiBQcmFlc2VudAotdm9s
+dXRwYXQuIFByb2luIGluIHB1cnVzLiBOdWxsYSB1cm5hIHNhcGllbiwgZGFwaWJ1cyBzaXQg
+YW1ldCwKK3ZvbHV0cGF0LiBQcm9pbiBpbiBwdXJ1cy4gTnVsbGEgdXJuYSBzYXBpZW4sIGRh
+cGkAdXMgc2l0IGFtZXQsCiBoZW5kcmVyaXQgbmVjLCB0ZW1wdXMgZXUsIG1pLiBVdCBwb3J0
+YSwgbGVvIGlkIHRpbmNpZHVudCB1bGxhbWNvcnBlciwKLXZlbGl0IGZlbGlzIHRyaXN0aXF1
+ZSBhbnRlLCBhdCBsb2JvcnRpcyBkaWFtIHBlZGUgdXQgZHVpLiBQcm9pbiBhYwordmVsaXQg
+ZmVsaXMgdHJpc3RpcXVlIGFudGUsIGF0IGxvAG9ydGlzIGRpYW0gcGVkZSB1dCBkdWkuIFBy
+b2luIGFjCiBsZWN0dXMuIERvbmVjIGF0IG1hc3NhIGFjIGlwc3VtIGhlbmRyZXJpdCBzb2xs
+aWNpdHVkaW4uIE5hbSBkaWN0dW0KIG5pc2kgc2VkIG1pLiBEdWlzIHNlZCBhbnRlLiBVdCB2
+aXRhZSBlc3QgdXQgZHVpIHVsdHJpY2llcyBkaWduaXNzaW0uCiAKLUluIHZlbCBvZGlvIGVn
+ZXQgbmlzbCBjb252YWxsaXMgdm9sdXRwYXQuIE1vcmJpIHZpdGFlIG5pYmguIE51bGxhbQor
+SW4gdmVsIG9kaW8gZWdldCBuaXNsIGNvbnZhbGxpcyB2b2x1dHBhdC4gTW9yAGkgdml0YWUg
+bmkAaC4gTnVsbGFtCiBhY2N1bXNhbiwgZG9sb3IgcXVpcyBhbGlxdWFtIHNjZWxlcmlzcXVl
+LCBlbGl0IGVuaW0gY29uZGltZW50dW0KIG1hdXJpcywgbm9uIHRyaXN0aXF1ZSBtYXVyaXMg
+dHVycGlzIGV0IG1hdXJpcy4gVXQgbm9uIG5pc2wuIE5hbSBkaWFtCiBtaSwgc2VtcGVyIHBv
+c3VlcmUsIGVsZWlmZW5kIHV0LCBhdWN0b3IgdmVsLCBlcmF0LiBTZWQgcG9zdWVyZQpAQCAt
+MTYsNyArMTYsNyBAQCBzZWQgZXN0LiBFdGlhbSBkaWFtIGZlbGlzLCBmZXJtZW50dW0gZWdl
+dCwgYWRpcGlzY2luZyBhdCwgcG9zdWVyZSBpbiwKIGR1aS4gRXRpYW0gbHVjdHVzLgogCiBO
+dWxsYSBpZCBhdWd1ZS4gTmFtIGlhY3VsaXMgYWNjdW1zYW4gbmlzaS4gU3VzcGVuZGlzc2Ug
+cG90ZW50aS4gTnVuYwotdmFyaXVzIGF1Z3VlIG5lYyBvcmNpLiBVdCBjb25kaW1lbnR1bSBk
+b2xvciBzYWdpdHRpcyBuaWJoLiBTdXNwZW5kaXNzZQordmFyaXVzIGF1Z3VlIG5lYyBvcmNp
+LiBVdCBjb25kaW1lbnR1bSBkb2xvciBzYWdpdHRpcyBuaQBoLiBTdXNwZW5kaXNzZQogdGVt
+cG9yIGxlY3R1cyBzZWQgbWFnbmEuIFN1c3BlbmRpc3NlIHBvdGVudGkuIE51bGxhbSB0ZW1w
+b3IgaXBzdW0uIFNlZAogbW9sZXN0aWUgdGVsbHVzLiBQaGFzZWxsdXMgbGlndWxhLiBJbiB2
+ZWhpY3VsYSB1bHRyaWNlcwogbmlzaS4gU3VzcGVuZGlzc2UgZmVsaXMgYXVndWUsIHBlbGxl
+bnRlc3F1ZSBhdCwgZGljdHVtIHZpdmVycmEsCi0tIAoxLjUuNS4xLjU0MC5nNTc3ODAKCg==
diff --git a/t/t5100/nul-plain b/t/t5100/nul-plain
new file mode 100644
index 0000000000..3d40691787
--- /dev/null
+++ b/t/t5100/nul-plain
Binary files differ
diff --git a/t/t5100/patch0010 b/t/t5100/patch0010
new file mode 100644
index 0000000000..f055481d56
--- /dev/null
+++ b/t/t5100/patch0010
@@ -0,0 +1,20 @@
+---
+ builtin-mailinfo.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 962aa34..2d1520f 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -334,7 +334,7 @@ static int check_header(char *line, unsigned linesize, char **hdr_data, int over
+ return 1;
+ if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
+ for (i = 0; header[i]; i++) {
+- if (!memcmp("Subject: ", header[i], 9)) {
++ if (!memcmp("Subject", header[i], 7)) {
+ if (! handle_header(line, hdr_data[i], 0)) {
+ return 1;
+ }
+--
+1.5.6.2.455.g1efb2
+
diff --git a/t/t5100/patch0011 b/t/t5100/patch0011
new file mode 100644
index 0000000000..8841d3c139
--- /dev/null
+++ b/t/t5100/patch0011
@@ -0,0 +1,22 @@
+---
+ builtin-mailinfo.c | 4 ++--
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 3e5fe51..aabfe5c 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -758,8 +758,8 @@ static void handle_body(void)
+ /* process any boundary lines */
+ if (*content_top && is_multipart_boundary(&line)) {
+ /* flush any leftover */
+- if (line.len)
+- handle_filter(&line);
++ if (prev.len)
++ handle_filter(&prev);
+
+ if (!handle_boundary())
+ goto handle_body_out;
+--
+1.6.0.rc2
+
+
diff --git a/t/t5100/patch0012 b/t/t5100/patch0012
new file mode 100644
index 0000000000..36a0b68161
--- /dev/null
+++ b/t/t5100/patch0012
@@ -0,0 +1,30 @@
+---
+ howto/build_navy.txt | 6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/howto/build_navy.txt b/howto/build_navy.txt
+index 3fd3afb..0ee807e 100644
+--- a/howto/build_navy.txt
++++ b/howto/build_navy.txt
+@@ -119,8 +119,8 @@
+ - libxv-dev
+ - libusplash-dev
+ - latex-make
+- - textlive-lang-cyrillic
+- - textlive-latex-extra
++ - texlive-lang-cyrillic
++ - texlive-latex-extra
+ - dia
+ - python-pyrex
+ - libtool
+@@ -128,7 +128,7 @@
+ - sox
+ - cython
+ - imagemagick
+- - docutils
++ - python-docutils
+
+ #. на машине dinar: добавить Ñвой открытый ssh-ключ в authorized_keys2 Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ddev
+ #. на Ñвоей машине: отредактировать /etc/sudoers (команда ``visudo``) примерно Ñледующим образом::
+--
+1.5.6.5
diff --git a/t/t5100/patch0013 b/t/t5100/patch0013
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/t/t5100/patch0013
diff --git a/t/t5100/patch0014 b/t/t5100/patch0014
new file mode 100644
index 0000000000..124efd234f
--- /dev/null
+++ b/t/t5100/patch0014
@@ -0,0 +1,64 @@
+---
+ builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 36 insertions(+), 1 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index b0b5d8f..461c47e 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -712,6 +712,34 @@ static inline int patchbreak(const struct strbuf *line)
+ return 0;
+ }
+
++static int scissors(const struct strbuf *line)
++{
++ size_t i, len = line->len;
++ int scissors_dashes_seen = 0;
++ const char *buf = line->buf;
++
++ for (i = 0; i < len; i++) {
++ if (isspace(buf[i]))
++ continue;
++ if (buf[i] == '-') {
++ scissors_dashes_seen |= 02;
++ continue;
++ }
++ if (i + 1 < len && !memcmp(buf + i, ">8", 2)) {
++ scissors_dashes_seen |= 01;
++ i++;
++ continue;
++ }
++ if (i + 7 < len && !memcmp(buf + i, "cut here", 8)) {
++ i += 7;
++ continue;
++ }
++ /* everything else --- not scissors */
++ break;
++ }
++ return scissors_dashes_seen == 03;
++}
++
+ static int handle_commit_msg(struct strbuf *line)
+ {
+ static int still_looking = 1;
+@@ -723,10 +751,17 @@ static int handle_commit_msg(struct strbuf *line)
+ strbuf_ltrim(line);
+ if (!line->len)
+ return 0;
+- if ((still_looking = check_header(line, s_hdr_data, 0)) != 0)
++ still_looking = check_header(line, s_hdr_data, 0);
++ if (still_looking)
+ return 0;
+ }
+
++ if (scissors(line)) {
++ fseek(cmitmsg, 0L, SEEK_SET);
++ still_looking = 1;
++ return 0;
++ }
++
+ /* normalize the log message to UTF-8. */
+ if (metainfo_charset)
+ convert_to_utf8(line, charset.buf);
+--
+1.6.4.1
diff --git a/t/t5100/patch0014--scissors b/t/t5100/patch0014--scissors
new file mode 100644
index 0000000000..124efd234f
--- /dev/null
+++ b/t/t5100/patch0014--scissors
@@ -0,0 +1,64 @@
+---
+ builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 36 insertions(+), 1 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index b0b5d8f..461c47e 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -712,6 +712,34 @@ static inline int patchbreak(const struct strbuf *line)
+ return 0;
+ }
+
++static int scissors(const struct strbuf *line)
++{
++ size_t i, len = line->len;
++ int scissors_dashes_seen = 0;
++ const char *buf = line->buf;
++
++ for (i = 0; i < len; i++) {
++ if (isspace(buf[i]))
++ continue;
++ if (buf[i] == '-') {
++ scissors_dashes_seen |= 02;
++ continue;
++ }
++ if (i + 1 < len && !memcmp(buf + i, ">8", 2)) {
++ scissors_dashes_seen |= 01;
++ i++;
++ continue;
++ }
++ if (i + 7 < len && !memcmp(buf + i, "cut here", 8)) {
++ i += 7;
++ continue;
++ }
++ /* everything else --- not scissors */
++ break;
++ }
++ return scissors_dashes_seen == 03;
++}
++
+ static int handle_commit_msg(struct strbuf *line)
+ {
+ static int still_looking = 1;
+@@ -723,10 +751,17 @@ static int handle_commit_msg(struct strbuf *line)
+ strbuf_ltrim(line);
+ if (!line->len)
+ return 0;
+- if ((still_looking = check_header(line, s_hdr_data, 0)) != 0)
++ still_looking = check_header(line, s_hdr_data, 0);
++ if (still_looking)
+ return 0;
+ }
+
++ if (scissors(line)) {
++ fseek(cmitmsg, 0L, SEEK_SET);
++ still_looking = 1;
++ return 0;
++ }
++
+ /* normalize the log message to UTF-8. */
+ if (metainfo_charset)
+ convert_to_utf8(line, charset.buf);
+--
+1.6.4.1
diff --git a/t/t5100/patch0015 b/t/t5100/patch0015
new file mode 100644
index 0000000000..ad64848873
--- /dev/null
+++ b/t/t5100/patch0015
@@ -0,0 +1,8 @@
+---
+diff --git a/foo b/foo
+index e69de29..d95f3ad 100644
+--- a/foo
++++ b/foo
+@@ -0,0 +1 @@
++content
+
diff --git a/t/t5100/patch0015--no-inbody-headers b/t/t5100/patch0015--no-inbody-headers
new file mode 100644
index 0000000000..ad64848873
--- /dev/null
+++ b/t/t5100/patch0015--no-inbody-headers
@@ -0,0 +1,8 @@
+---
+diff --git a/foo b/foo
+index e69de29..d95f3ad 100644
+--- a/foo
++++ b/foo
+@@ -0,0 +1 @@
++content
+
diff --git a/t/t5100/patch0016 b/t/t5100/patch0016
new file mode 100644
index 0000000000..ad64848873
--- /dev/null
+++ b/t/t5100/patch0016
@@ -0,0 +1,8 @@
+---
+diff --git a/foo b/foo
+index e69de29..d95f3ad 100644
+--- a/foo
++++ b/foo
+@@ -0,0 +1 @@
++content
+
diff --git a/t/t5100/patch0016--no-inbody-headers b/t/t5100/patch0016--no-inbody-headers
new file mode 100644
index 0000000000..ad64848873
--- /dev/null
+++ b/t/t5100/patch0016--no-inbody-headers
@@ -0,0 +1,8 @@
+---
+diff --git a/foo b/foo
+index e69de29..d95f3ad 100644
+--- a/foo
++++ b/foo
+@@ -0,0 +1 @@
++content
+
diff --git a/t/t5100/rfc2047-info-0001 b/t/t5100/rfc2047-info-0001
new file mode 100644
index 0000000000..0a383b07e3
--- /dev/null
+++ b/t/t5100/rfc2047-info-0001
@@ -0,0 +1,4 @@
+Author: Keith Moore
+Email: moore@cs.utk.edu
+Subject: If you can read this you understand the example.
+
diff --git a/t/t5100/rfc2047-info-0002 b/t/t5100/rfc2047-info-0002
new file mode 100644
index 0000000000..881be75d6f
--- /dev/null
+++ b/t/t5100/rfc2047-info-0002
@@ -0,0 +1,4 @@
+Author: Olle Järnefors
+Email: ojarnef@admin.kth.se
+Subject: Time for ISO 10646?
+
diff --git a/t/t5100/rfc2047-info-0003 b/t/t5100/rfc2047-info-0003
new file mode 100644
index 0000000000..d0f789177c
--- /dev/null
+++ b/t/t5100/rfc2047-info-0003
@@ -0,0 +1,4 @@
+Author: Patrik Fältström
+Email: paf@nada.kth.se
+Subject: RFC-HDR care and feeding
+
diff --git a/t/t5100/rfc2047-info-0004 b/t/t5100/rfc2047-info-0004
new file mode 100644
index 0000000000..f67a90a974
--- /dev/null
+++ b/t/t5100/rfc2047-info-0004
@@ -0,0 +1,4 @@
+Author: Nathaniel Borenstein (×ולש ןב ילטפנ)
+Email: nsb@thumper.bellcore.com
+Subject: Test of new header generator
+
diff --git a/t/t5100/rfc2047-info-0005 b/t/t5100/rfc2047-info-0005
new file mode 100644
index 0000000000..c27be3bf24
--- /dev/null
+++ b/t/t5100/rfc2047-info-0005
@@ -0,0 +1,2 @@
+Subject: (a)
+
diff --git a/t/t5100/rfc2047-info-0006 b/t/t5100/rfc2047-info-0006
new file mode 100644
index 0000000000..9dad474456
--- /dev/null
+++ b/t/t5100/rfc2047-info-0006
@@ -0,0 +1,2 @@
+Subject: (a b)
+
diff --git a/t/t5100/rfc2047-info-0007 b/t/t5100/rfc2047-info-0007
new file mode 100644
index 0000000000..294f195a57
--- /dev/null
+++ b/t/t5100/rfc2047-info-0007
@@ -0,0 +1,2 @@
+Subject: (ab)
+
diff --git a/t/t5100/rfc2047-info-0008 b/t/t5100/rfc2047-info-0008
new file mode 100644
index 0000000000..294f195a57
--- /dev/null
+++ b/t/t5100/rfc2047-info-0008
@@ -0,0 +1,2 @@
+Subject: (ab)
+
diff --git a/t/t5100/rfc2047-info-0009 b/t/t5100/rfc2047-info-0009
new file mode 100644
index 0000000000..294f195a57
--- /dev/null
+++ b/t/t5100/rfc2047-info-0009
@@ -0,0 +1,2 @@
+Subject: (ab)
+
diff --git a/t/t5100/rfc2047-info-0010 b/t/t5100/rfc2047-info-0010
new file mode 100644
index 0000000000..9dad474456
--- /dev/null
+++ b/t/t5100/rfc2047-info-0010
@@ -0,0 +1,2 @@
+Subject: (a b)
+
diff --git a/t/t5100/rfc2047-info-0011 b/t/t5100/rfc2047-info-0011
new file mode 100644
index 0000000000..9dad474456
--- /dev/null
+++ b/t/t5100/rfc2047-info-0011
@@ -0,0 +1,2 @@
+Subject: (a b)
+
diff --git a/t/t5100/rfc2047-samples.mbox b/t/t5100/rfc2047-samples.mbox
new file mode 100644
index 0000000000..1fc224810d
--- /dev/null
+++ b/t/t5100/rfc2047-samples.mbox
@@ -0,0 +1,48 @@
+From nobody Mon Sep 17 00:00:00 2001
+From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>
+To: =?ISO8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>
+CC: =?ISO8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>
+Subject: =?ISO8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
+ =?ISO8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=
+
+From nobody Mon Sep 17 00:00:00 2001
+From: =?ISO8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>
+To: ietf-822@dimacs.rutgers.edu, ojarnef@admin.kth.se
+Subject: Time for ISO 10646?
+
+From nobody Mon Sep 17 00:00:00 2001
+To: Dave Crocker <dcrocker@mordor.stanford.edu>
+Cc: ietf-822@dimacs.rutgers.edu, paf@comsol.se
+From: =?ISO8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.se>
+Subject: Re: RFC-HDR care and feeding
+
+From nobody Mon Sep 17 00:00:00 2001
+From: Nathaniel Borenstein <nsb@thumper.bellcore.com>
+ (=?ISO8859-8?b?7eXs+SDv4SDp7Oj08A==?=)
+To: Greg Vaudreuil <gvaudre@NRI.Reston.VA.US>, Ned Freed
+ <ned@innosoft.com>, Keith Moore <moore@cs.utk.edu>
+Subject: Test of new header generator
+MIME-Version: 1.0
+Content-type: text/plain; charset=ISO8859-1
+
+From nobody Mon Sep 17 00:00:00 2001
+Subject: (=?ISO8859-1?Q?a?=)
+
+From nobody Mon Sep 17 00:00:00 2001
+Subject: (=?ISO8859-1?Q?a?= b)
+
+From nobody Mon Sep 17 00:00:00 2001
+Subject: (=?ISO8859-1?Q?a?= =?ISO8859-1?Q?b?=)
+
+From nobody Mon Sep 17 00:00:00 2001
+Subject: (=?ISO8859-1?Q?a?= =?ISO8859-1?Q?b?=)
+
+From nobody Mon Sep 17 00:00:00 2001
+Subject: (=?ISO8859-1?Q?a?=
+ =?ISO8859-1?Q?b?=)
+
+From nobody Mon Sep 17 00:00:00 2001
+Subject: (=?ISO8859-1?Q?a_b?=)
+
+From nobody Mon Sep 17 00:00:00 2001
+Subject: (=?ISO8859-1?Q?a?= =?ISO8859-2?Q?_b?=)
diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox
index 0476b96c33..de1031241d 100644
--- a/t/t5100/sample.mbox
+++ b/t/t5100/sample.mbox
@@ -2,7 +2,10 @@
From nobody Mon Sep 17 00:00:00 2001
-From: A U Thor <a.u.thor@example.com>
+From: A (zzz)
+ U
+ Thor
+ <a.u.thor@example.com> (Comment)
Date: Fri, 9 Jun 2006 00:44:16 -0700
Subject: [PATCH] a commit.
@@ -96,7 +99,7 @@ index 9123cdc..918dcf8 100644
From nobody Sat Aug 27 23:07:49 2005
Path: news.gmane.org!not-for-mail
Message-ID: <20050721.091036.01119516.yoshfuji@linux-ipv6.org>
-From: YOSHIFUJI Hideaki / =?iso-2022-jp?B?GyRCNUhGIzFRTEAbKEI=?=
+From: YOSHIFUJI Hideaki / =?ISO-2022-JP?B?GyRCNUhGIzFRTEAbKEI=?=
<yoshfuji@linux-ipv6.org>
Newsgroups: gmane.comp.version-control.git
Subject: [PATCH 1/2] GIT: Try all addresses for given remote name
@@ -215,7 +218,7 @@ GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
From nobody Sat Aug 27 23:07:49 2005
Path: news.gmane.org!not-for-mail
Message-ID: <u5tacjjdpxq.fsf@lysator.liu.se>
-From: =?iso-8859-1?Q?David_K=E5gedal?= <davidk@lysator.liu.se>
+From: =?ISO8859-1?Q?David_K=E5gedal?= <davidk@lysator.liu.se>
Newsgroups: gmane.comp.version-control.git
Subject: [PATCH] Fixed two bugs in git-cvsimport-script.
Date: Mon, 15 Aug 2005 20:18:25 +0200
@@ -223,7 +226,7 @@ Lines: 83
Approved: news@gmane.org
NNTP-Posting-Host: main.gmane.org
Mime-Version: 1.0
-Content-Type: text/plain; charset=iso-8859-1
+Content-Type: text/plain; charset=ISO8859-1
Content-Transfer-Encoding: QUOTED-PRINTABLE
X-Trace: sea.gmane.org 1124130247 31839 80.91.229.2 (15 Aug 2005 18:24:07 GMT)
X-Complaints-To: usenet@sea.gmane.org
@@ -430,3 +433,253 @@ index b426a14..97756ec 100644
=20
=20
2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the
+From b9704a518e21158433baa2cc2d591fea687967f6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Lukas=20Sandstr=C3=B6m?= <lukass@etek.chalmers.se>
+Date: Thu, 10 Jul 2008 23:41:33 +0200
+Subject: Re: discussion that lead to this patch
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+[PATCH] git-mailinfo: Fix getting the subject from the body
+
+"Subject: " isn't in the static array "header", and thus
+memcmp("Subject: ", header[i], 7) will never match.
+
+Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
+---
+ builtin-mailinfo.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 962aa34..2d1520f 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -334,7 +334,7 @@ static int check_header(char *line, unsigned linesize, char **hdr_data, int over
+ return 1;
+ if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
+ for (i = 0; header[i]; i++) {
+- if (!memcmp("Subject: ", header[i], 9)) {
++ if (!memcmp("Subject", header[i], 7)) {
+ if (! handle_header(line, hdr_data[i], 0)) {
+ return 1;
+ }
+--
+1.5.6.2.455.g1efb2
+
+From nobody Fri Aug 8 22:24:03 2008
+Date: Fri, 8 Aug 2008 13:08:37 +0200 (CEST)
+From: A U Thor <a.u.thor@example.com>
+Subject: [PATCH 3/3 v2] Xyzzy
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="=-=-="
+
+--=-=-=
+Content-Type: text/plain; charset=ISO8859-15
+Content-Transfer-Encoding: quoted-printable
+
+Here comes a commit log message, and
+its second line is here.
+---
+ builtin-mailinfo.c | 4 ++--
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 3e5fe51..aabfe5c 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -758,8 +758,8 @@ static void handle_body(void)
+ /* process any boundary lines */
+ if (*content_top && is_multipart_boundary(&line)) {
+ /* flush any leftover */
+- if (line.len)
+- handle_filter(&line);
++ if (prev.len)
++ handle_filter(&prev);
+=20
+ if (!handle_boundary())
+ goto handle_body_out;
+--=20
+1.6.0.rc2
+
+--=-=-=--
+
+From bda@mnsspb.ru Wed Nov 12 17:54:41 2008
+From: Dmitriy Blinov <bda@mnsspb.ru>
+To: navy-patches@dinar.mns.mnsspb.ru
+Date: Wed, 12 Nov 2008 17:54:41 +0300
+Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
+X-Mailer: git-send-email 1.5.6.5
+MIME-Version: 1.0
+Content-Type: text/plain;
+ charset=utf-8
+Content-Transfer-Encoding: 8bit
+Subject: [Navy-patches] [PATCH]
+ =?utf-8?b?0JjQt9C80LXQvdGR0L0g0YHQv9C40YHQvtC6INC/0LA=?=
+ =?utf-8?b?0LrQtdGC0L7QsiDQvdC10L7QsdGF0L7QtNC40LzRi9GFINC00LvRjyA=?=
+ =?utf-8?b?0YHQsdC+0YDQutC4?=
+
+textlive-* иÑправлены на texlive-*
+docutils заменён на python-docutils
+
+ДейÑтвительно, оказалоÑÑŒ, что rest2web вытÑгивает за Ñобой
+python-docutils. Ð’ то Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ðº Ñам rest2web не нужен.
+
+Signed-off-by: Dmitriy Blinov <bda@mnsspb.ru>
+---
+ howto/build_navy.txt | 6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/howto/build_navy.txt b/howto/build_navy.txt
+index 3fd3afb..0ee807e 100644
+--- a/howto/build_navy.txt
++++ b/howto/build_navy.txt
+@@ -119,8 +119,8 @@
+ - libxv-dev
+ - libusplash-dev
+ - latex-make
+- - textlive-lang-cyrillic
+- - textlive-latex-extra
++ - texlive-lang-cyrillic
++ - texlive-latex-extra
+ - dia
+ - python-pyrex
+ - libtool
+@@ -128,7 +128,7 @@
+ - sox
+ - cython
+ - imagemagick
+- - docutils
++ - python-docutils
+
+ #. на машине dinar: добавить Ñвой открытый ssh-ключ в authorized_keys2 Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ddev
+ #. на Ñвоей машине: отредактировать /etc/sudoers (команда ``visudo``) примерно Ñледующим образом::
+--
+1.5.6.5
+From nobody Mon Sep 17 00:00:00 2001
+From: <a.u.thor@example.com> (A U Thor)
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+Subject: [PATCH] a patch
+
+From nobody Mon Sep 17 00:00:00 2001
+From: Junio Hamano <junkio@cox.net>
+Date: Thu, 20 Aug 2009 17:18:22 -0700
+Subject: Why doesn't git-am does not like >8 scissors mark?
+
+Subject: [PATCH] BLAH ONE
+
+In real life, we will see a discussion that inspired this patch
+discussing related and unrelated things around >8 scissors mark
+in this part of the message.
+
+Subject: [PATCH] BLAH TWO
+
+And then we will see the scissors.
+
+ This line is not a scissors mark -- >8 -- but talks about it.
+ - - >8 - - please remove everything above this line - - >8 - -
+
+Subject: [PATCH] Teach mailinfo to ignore everything before -- >8 -- mark
+From: Junio C Hamano <gitster@pobox.com>
+
+This teaches mailinfo the scissors -- >8 -- mark; the command ignores
+everything before it in the message body.
+
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
+---
+ builtin-mailinfo.c | 37 ++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 36 insertions(+), 1 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index b0b5d8f..461c47e 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -712,6 +712,34 @@ static inline int patchbreak(const struct strbuf *line)
+ return 0;
+ }
+
++static int scissors(const struct strbuf *line)
++{
++ size_t i, len = line->len;
++ int scissors_dashes_seen = 0;
++ const char *buf = line->buf;
++
++ for (i = 0; i < len; i++) {
++ if (isspace(buf[i]))
++ continue;
++ if (buf[i] == '-') {
++ scissors_dashes_seen |= 02;
++ continue;
++ }
++ if (i + 1 < len && !memcmp(buf + i, ">8", 2)) {
++ scissors_dashes_seen |= 01;
++ i++;
++ continue;
++ }
++ if (i + 7 < len && !memcmp(buf + i, "cut here", 8)) {
++ i += 7;
++ continue;
++ }
++ /* everything else --- not scissors */
++ break;
++ }
++ return scissors_dashes_seen == 03;
++}
++
+ static int handle_commit_msg(struct strbuf *line)
+ {
+ static int still_looking = 1;
+@@ -723,10 +751,17 @@ static int handle_commit_msg(struct strbuf *line)
+ strbuf_ltrim(line);
+ if (!line->len)
+ return 0;
+- if ((still_looking = check_header(line, s_hdr_data, 0)) != 0)
++ still_looking = check_header(line, s_hdr_data, 0);
++ if (still_looking)
+ return 0;
+ }
+
++ if (scissors(line)) {
++ fseek(cmitmsg, 0L, SEEK_SET);
++ still_looking = 1;
++ return 0;
++ }
++
+ /* normalize the log message to UTF-8. */
+ if (metainfo_charset)
+ convert_to_utf8(line, charset.buf);
+--
+1.6.4.1
+From nobody Mon Sep 17 00:00:00 2001
+From: A U Thor <a.u.thor@example.com>
+Subject: check bogus body header (from)
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+
+From: bogosity
+ - a list
+ - of stuff
+---
+diff --git a/foo b/foo
+index e69de29..d95f3ad 100644
+--- a/foo
++++ b/foo
+@@ -0,0 +1 @@
++content
+
+From nobody Mon Sep 17 00:00:00 2001
+From: A U Thor <a.u.thor@example.com>
+Subject: check bogus body header (date)
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+
+Date: bogus
+
+and some content
+
+---
+diff --git a/foo b/foo
+index e69de29..d95f3ad 100644
+--- a/foo
++++ b/foo
+@@ -0,0 +1 @@
++content
+
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index 983a39398f..e2aa254eae 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2005 Junio C Hamano
#
-test_description='git-pack-object
+test_description='git pack-object
'
. ./test-lib.sh
@@ -13,11 +13,10 @@ TRASH=`pwd`
test_expect_success \
'setup' \
'rm -f .git/index*
- for i in a b c
- do
- dd if=/dev/zero bs=4k count=1 | perl -pe "y/\\000/$i/" >$i &&
- git update-index --add $i || return 1
- done &&
+ perl -e "print \"a\" x 4096;" > a &&
+ perl -e "print \"b\" x 4096;" > b &&
+ perl -e "print \"c\" x 4096;" > c &&
+ git update-index --add a b c &&
cat c >d && echo foo >>d && git update-index --add d &&
tree=`git write-tree` &&
commit=`git commit-tree $tree </dev/null` && {
@@ -180,6 +179,23 @@ test_expect_success \
unset GIT_OBJECT_DIRECTORY
+test_expect_success 'survive missing objects/pack directory' '
+ (
+ rm -fr missing-pack &&
+ mkdir missing-pack &&
+ cd missing-pack &&
+ git init &&
+ GOP=.git/objects/pack
+ rm -fr $GOP &&
+ git index-pack --stdin --keep=test <../test-3-${packname_3}.pack &&
+ test -f $GOP/pack-${packname_3}.pack &&
+ test_cmp $GOP/pack-${packname_3}.pack ../test-3-${packname_3}.pack &&
+ test -f $GOP/pack-${packname_3}.idx &&
+ test_cmp $GOP/pack-${packname_3}.idx ../test-3-${packname_3}.idx &&
+ test -f $GOP/pack-${packname_3}.keep
+ )
+'
+
test_expect_success \
'verify pack' \
'git verify-pack test-1-${packname_1}.idx \
@@ -187,6 +203,12 @@ test_expect_success \
test-3-${packname_3}.idx'
test_expect_success \
+ 'verify pack -v' \
+ 'git verify-pack -v test-1-${packname_1}.idx \
+ test-2-${packname_2}.idx \
+ test-3-${packname_3}.idx'
+
+test_expect_success \
'verify-pack catches mismatched .idx and .pack files' \
'cat test-1-${packname_1}.idx >test-3.idx &&
cat test-2-${packname_2}.pack >test-3.pack &&
@@ -198,7 +220,7 @@ test_expect_success \
test_expect_success \
'verify-pack catches a corrupted pack signature' \
'cat test-1-${packname_1}.pack >test-3.pack &&
- dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=2 &&
+ echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=2 &&
if git verify-pack test-3.idx
then false
else :;
@@ -207,7 +229,7 @@ test_expect_success \
test_expect_success \
'verify-pack catches a corrupted pack version' \
'cat test-1-${packname_1}.pack >test-3.pack &&
- dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=7 &&
+ echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=7 &&
if git verify-pack test-3.idx
then false
else :;
@@ -216,7 +238,7 @@ test_expect_success \
test_expect_success \
'verify-pack catches a corrupted type/size of the 1st packed object data' \
'cat test-1-${packname_1}.pack >test-3.pack &&
- dd if=/dev/zero of=test-3.pack count=1 bs=1 conv=notrunc seek=12 &&
+ echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=12 &&
if git verify-pack test-3.idx
then false
else :;
@@ -227,7 +249,7 @@ test_expect_success \
'l=`wc -c <test-3.idx` &&
l=`expr $l - 20` &&
cat test-1-${packname_1}.pack >test-3.pack &&
- dd if=/dev/zero of=test-3.idx count=20 bs=1 conv=notrunc seek=$l &&
+ printf "%20s" "" | dd of=test-3.idx count=20 bs=1 conv=notrunc seek=$l &&
if git verify-pack test-3.pack
then false
else :;
@@ -236,24 +258,24 @@ test_expect_success \
test_expect_success \
'build pack index for an existing pack' \
'cat test-1-${packname_1}.pack >test-3.pack &&
- git-index-pack -o tmp.idx test-3.pack &&
+ git index-pack -o tmp.idx test-3.pack &&
cmp tmp.idx test-1-${packname_1}.idx &&
- git-index-pack test-3.pack &&
+ git index-pack test-3.pack &&
cmp test-3.idx test-1-${packname_1}.idx &&
cat test-2-${packname_2}.pack >test-3.pack &&
- git-index-pack -o tmp.idx test-2-${packname_2}.pack &&
+ git index-pack -o tmp.idx test-2-${packname_2}.pack &&
cmp tmp.idx test-2-${packname_2}.idx &&
- git-index-pack test-3.pack &&
+ git index-pack test-3.pack &&
cmp test-3.idx test-2-${packname_2}.idx &&
cat test-3-${packname_3}.pack >test-3.pack &&
- git-index-pack -o tmp.idx test-3-${packname_3}.pack &&
+ git index-pack -o tmp.idx test-3-${packname_3}.pack &&
cmp tmp.idx test-3-${packname_3}.idx &&
- git-index-pack test-3.pack &&
+ git index-pack test-3.pack &&
cmp test-3.idx test-3-${packname_3}.idx &&
:'
@@ -266,7 +288,8 @@ test_expect_success \
test_expect_success \
'make sure index-pack detects the SHA1 collision' \
- '! git-index-pack -o bad.idx test-3.pack'
+ 'test_must_fail git index-pack -o bad.idx test-3.pack 2>msg &&
+ grep "SHA1 COLLISION FOUND" msg'
test_expect_success \
'honor pack.packSizeLimit' \
@@ -369,4 +392,10 @@ test_expect_success 'index-pack with --strict' '
)
'
+test_expect_success 'tolerate absurdly small packsizelimit' '
+ git config pack.packSizeLimit 2 &&
+ packname_9=$(git pack-objects test-9 <obj-list) &&
+ test $(wc -l <obj-list) = $(ls test-9-*.pack | wc -l)
+'
+
test_done
diff --git a/t/t5301-sliding-window.sh b/t/t5301-sliding-window.sh
index 073ac0c6f9..0a24e61ff9 100755
--- a/t/t5301-sliding-window.sh
+++ b/t/t5301-sliding-window.sh
@@ -19,7 +19,7 @@ test_expect_success \
tree=`git write-tree` &&
commit1=`git commit-tree $tree </dev/null` &&
git update-ref HEAD $commit1 &&
- git-repack -a -d &&
+ git repack -a -d &&
test "`git count-objects`" = "0 objects, 0 kilobytes" &&
pack1=`ls .git/objects/pack/*.pack` &&
test -f "$pack1"'
@@ -45,7 +45,7 @@ test_expect_success \
git config core.packedGitLimit 512 &&
commit2=`git commit-tree $tree -p $commit1 </dev/null` &&
git update-ref HEAD $commit2 &&
- git-repack -a -d &&
+ git repack -a -d &&
test "`git count-objects`" = "0 objects, 0 kilobytes" &&
pack2=`ls .git/objects/pack/*.pack` &&
test -f "$pack2"
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index b88b5bbd02..4360e77d31 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -10,14 +10,20 @@ test_expect_success \
'setup' \
'rm -rf .git
git init &&
+ git config pack.threads 1 &&
i=1 &&
- while test $i -le 100
+ while test $i -le 100
do
- i=`printf '%03i' $i`
- echo $i >file_$i &&
- test-genrandom "$i" 8192 >>file_$i &&
- git update-index --add file_$i &&
- i=`expr $i + 1` || return 1
+ iii=`printf '%03i' $i`
+ test-genrandom "bar" 200 > wide_delta_$iii &&
+ test-genrandom "baz $iii" 50 >> wide_delta_$iii &&
+ test-genrandom "foo"$i 100 > deep_delta_$iii &&
+ test-genrandom "foo"`expr $i + 1` 100 >> deep_delta_$iii &&
+ test-genrandom "foo"`expr $i + 2` 100 >> deep_delta_$iii &&
+ echo $iii >file_$iii &&
+ test-genrandom "$iii" 8192 >>file_$iii &&
+ git update-index --add file_$iii deep_delta_$iii wide_delta_$iii &&
+ i=`expr $i + 1` || return 1
done &&
{ echo 101 && test-genrandom 100 8192; } >file_101 &&
git update-index --add file_101 &&
@@ -48,11 +54,11 @@ test_expect_success \
test_expect_success \
'index-pack with index version 1' \
- 'git-index-pack --index-version=1 -o 1.idx "test-1-${pack1}.pack"'
+ 'git index-pack --index-version=1 -o 1.idx "test-1-${pack1}.pack"'
test_expect_success \
'index-pack with index version 2' \
- 'git-index-pack --index-version=2 -o 2.idx "test-1-${pack1}.pack"'
+ 'git index-pack --index-version=2 -o 2.idx "test-1-${pack1}.pack"'
test_expect_success \
'index-pack results should match pack-objects ones' \
@@ -63,38 +69,58 @@ test_expect_success \
'index v2: force some 64-bit offsets with pack-objects' \
'pack3=$(git pack-objects --index-version=2,0x40000 test-3 <obj-list)'
-have_64bits=
if msg=$(git verify-pack -v "test-3-${pack3}.pack" 2>&1) ||
- ! echo "$msg" | grep "pack too large .* off_t"
+ ! (echo "$msg" | grep "pack too large .* off_t")
then
- have_64bits=t
+ test_set_prereq OFF64_T
else
say "skipping tests concerning 64-bit offsets"
fi
-test "$have_64bits" &&
-test_expect_success \
+test_expect_success OFF64_T \
'index v2: verify a pack with some 64-bit offsets' \
'git verify-pack -v "test-3-${pack3}.pack"'
-test "$have_64bits" &&
-test_expect_success \
+test_expect_success OFF64_T \
'64-bit offsets: should be different from previous index v2 results' \
'! cmp "test-2-${pack2}.idx" "test-3-${pack3}.idx"'
-test "$have_64bits" &&
-test_expect_success \
+test_expect_success OFF64_T \
'index v2: force some 64-bit offsets with index-pack' \
- 'git-index-pack --index-version=2,0x40000 -o 3.idx "test-1-${pack1}.pack"'
+ 'git index-pack --index-version=2,0x40000 -o 3.idx "test-1-${pack1}.pack"'
-test "$have_64bits" &&
-test_expect_success \
+test_expect_success OFF64_T \
'64-bit offsets: index-pack result should match pack-objects one' \
'cmp "test-3-${pack3}.idx" "3.idx"'
+# returns the object number for given object in given pack index
+index_obj_nr()
+{
+ idx_file=$1
+ object_sha1=$2
+ nr=0
+ git show-index < $idx_file |
+ while read offs sha1 extra
+ do
+ nr=$(($nr + 1))
+ test "$sha1" = "$object_sha1" || continue
+ echo "$(($nr - 1))"
+ break
+ done
+}
+
+# returns the pack offset for given object as found in given pack index
+index_obj_offset()
+{
+ idx_file=$1
+ object_sha1=$2
+ git show-index < $idx_file | grep $object_sha1 |
+ ( read offs extra && echo "$offs" )
+}
+
test_expect_success \
'[index v1] 1) stream pack to repository' \
- 'git-index-pack --index-version=1 --stdin < "test-1-${pack1}.pack" &&
+ 'git index-pack --index-version=1 --stdin < "test-1-${pack1}.pack" &&
git prune-packed &&
git count-objects | ( read nr rest && test "$nr" -eq 1 ) &&
cmp "test-1-${pack1}.pack" ".git/objects/pack/pack-${pack1}.pack" &&
@@ -102,23 +128,26 @@ test_expect_success \
test_expect_success \
'[index v1] 2) create a stealth corruption in a delta base reference' \
- '# this test assumes a delta smaller than 16 bytes at the end of the pack
- git show-index <1.idx | sort -n | sed -ne \$p | (
- read delta_offs delta_sha1 &&
- git cat-file blob "$delta_sha1" > blob_1 &&
- chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
- dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($delta_offs + 1)) \
- if=".git/objects/pack/pack-${pack1}.idx" skip=$((256 * 4 + 4)) \
- bs=1 count=20 conv=notrunc &&
- git cat-file blob "$delta_sha1" > blob_2 )'
+ '# This test assumes file_101 is a delta smaller than 16 bytes.
+ # It should be against file_100 but we substitute its base for file_099
+ sha1_101=`git hash-object file_101` &&
+ sha1_099=`git hash-object file_099` &&
+ offs_101=`index_obj_offset 1.idx $sha1_101` &&
+ nr_099=`index_obj_nr 1.idx $sha1_099` &&
+ chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
+ dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \
+ if=".git/objects/pack/pack-${pack1}.idx" \
+ skip=$((4 + 256 * 4 + $nr_099 * 24)) \
+ bs=1 count=20 conv=notrunc &&
+ git cat-file blob $sha1_101 > file_101_foo1'
test_expect_success \
'[index v1] 3) corrupted delta happily returned wrong data' \
- '! cmp blob_1 blob_2'
+ 'test -f file_101_foo1 && ! cmp file_101 file_101_foo1'
test_expect_success \
'[index v1] 4) confirm that the pack is actually corrupted' \
- '! git fsck --full $commit'
+ 'test_must_fail git fsck --full $commit'
test_expect_success \
'[index v1] 5) pack-objects happily reuses corrupted data' \
@@ -127,12 +156,12 @@ test_expect_success \
test_expect_success \
'[index v1] 6) newly created pack is BAD !' \
- '! git verify-pack -v "test-4-${pack1}.pack"'
+ 'test_must_fail git verify-pack -v "test-4-${pack1}.pack"'
test_expect_success \
'[index v2] 1) stream pack to repository' \
'rm -f .git/objects/pack/* &&
- git-index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" &&
+ git index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" &&
git prune-packed &&
git count-objects | ( read nr rest && test "$nr" -eq 1 ) &&
cmp "test-1-${pack1}.pack" ".git/objects/pack/pack-${pack1}.pack" &&
@@ -140,26 +169,57 @@ test_expect_success \
test_expect_success \
'[index v2] 2) create a stealth corruption in a delta base reference' \
- '# this test assumes a delta smaller than 16 bytes at the end of the pack
- git show-index <1.idx | sort -n | sed -ne \$p | (
- read delta_offs delta_sha1 delta_crc &&
- git cat-file blob "$delta_sha1" > blob_3 &&
- chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
- dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($delta_offs + 1)) \
- if=".git/objects/pack/pack-${pack1}.idx" skip=$((8 + 256 * 4)) \
- bs=1 count=20 conv=notrunc &&
- git cat-file blob "$delta_sha1" > blob_4 )'
+ '# This test assumes file_101 is a delta smaller than 16 bytes.
+ # It should be against file_100 but we substitute its base for file_099
+ sha1_101=`git hash-object file_101` &&
+ sha1_099=`git hash-object file_099` &&
+ offs_101=`index_obj_offset 1.idx $sha1_101` &&
+ nr_099=`index_obj_nr 1.idx $sha1_099` &&
+ chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
+ dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \
+ if=".git/objects/pack/pack-${pack1}.idx" \
+ skip=$((8 + 256 * 4 + $nr_099 * 20)) \
+ bs=1 count=20 conv=notrunc &&
+ git cat-file blob $sha1_101 > file_101_foo2'
test_expect_success \
'[index v2] 3) corrupted delta happily returned wrong data' \
- '! cmp blob_3 blob_4'
+ 'test -f file_101_foo2 && ! cmp file_101 file_101_foo2'
test_expect_success \
'[index v2] 4) confirm that the pack is actually corrupted' \
- '! git fsck --full $commit'
+ 'test_must_fail git fsck --full $commit'
test_expect_success \
'[index v2] 5) pack-objects refuses to reuse corrupted data' \
- '! git pack-objects test-5 <obj-list'
+ 'test_must_fail git pack-objects test-5 <obj-list &&
+ test_must_fail git pack-objects --no-reuse-object test-6 <obj-list'
+
+test_expect_success \
+ '[index v2] 6) verify-pack detects CRC mismatch' \
+ 'rm -f .git/objects/pack/* &&
+ git index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" &&
+ git verify-pack ".git/objects/pack/pack-${pack1}.pack" &&
+ obj=`git hash-object file_001` &&
+ nr=`index_obj_nr ".git/objects/pack/pack-${pack1}.idx" $obj` &&
+ chmod +w ".git/objects/pack/pack-${pack1}.idx" &&
+ printf xxxx | dd of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \
+ bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + $nr * 4)) &&
+ ( while read obj
+ do git cat-file -p $obj >/dev/null || exit 1
+ done <obj-list ) &&
+ err=$(test_must_fail git verify-pack \
+ ".git/objects/pack/pack-${pack1}.pack" 2>&1) &&
+ echo "$err" | grep "CRC mismatch"'
+
+test_expect_success 'running index-pack in the object store' '
+ rm -f .git/objects/pack/* &&
+ cp test-1-${pack1}.pack .git/objects/pack/pack-${pack1}.pack &&
+ (
+ cd .git/objects/pack
+ git index-pack pack-${pack1}.pack
+ ) &&
+ test -f .git/objects/pack/pack-${pack1}.idx
+'
test_done
diff --git a/t/t5303-hash-object.sh b/t/t5303-hash-object.sh
deleted file mode 100755
index 543c0784bd..0000000000
--- a/t/t5303-hash-object.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/sh
-
-test_description=git-hash-object
-
-. ./test-lib.sh
-
-test_expect_success \
- 'git hash-object -w --stdin saves the object' \
- 'obname=$(echo foo | git hash-object -w --stdin) &&
- obpath=$(echo $obname | sed -e "s/\(..\)/\1\//") &&
- test -r .git/objects/"$obpath" &&
- rm -f .git/objects/"$obpath"'
-
-test_expect_success \
- 'git hash-object --stdin -w saves the object' \
- 'obname=$(echo foo | git hash-object --stdin -w) &&
- obpath=$(echo $obname | sed -e "s/\(..\)/\1\//") &&
- test -r .git/objects/"$obpath" &&
- rm -f .git/objects/"$obpath"'
-
-test_expect_success \
- 'git hash-object --stdin file1 <file0 first operates on file0, then file1' \
- 'echo foo > file1 &&
- obname0=$(echo bar | git hash-object --stdin) &&
- obname1=$(git hash-object file1) &&
- obname0new=$(echo bar | git hash-object --stdin file1 | sed -n -e 1p) &&
- obname1new=$(echo bar | git hash-object --stdin file1 | sed -n -e 2p) &&
- test "$obname0" = "$obname0new" &&
- test "$obname1" = "$obname1new"'
-
-test_expect_success \
- 'git hash-object refuses multiple --stdin arguments' \
- '! git hash-object --stdin --stdin < file1'
-
-test_done
diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh
new file mode 100755
index 0000000000..5f6cd4f333
--- /dev/null
+++ b/t/t5303-pack-corruption-resilience.sh
@@ -0,0 +1,287 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Nicolas Pitre
+#
+
+test_description='resilience to pack corruptions with redundant objects'
+. ./test-lib.sh
+
+# Note: the test objects are created with knowledge of their pack encoding
+# to ensure good code path coverage, and to facilitate direct alteration
+# later on. The assumed characteristics are:
+#
+# 1) blob_2 is a delta with blob_1 for base and blob_3 is a delta with blob2
+# for base, such that blob_3 delta depth is 2;
+#
+# 2) the bulk of object data is uncompressible so the text part remains
+# visible;
+#
+# 3) object header is always 2 bytes.
+
+create_test_files() {
+ test-genrandom "foo" 2000 > file_1 &&
+ test-genrandom "foo" 1800 > file_2 &&
+ test-genrandom "foo" 1800 > file_3 &&
+ echo " base " >> file_1 &&
+ echo " delta1 " >> file_2 &&
+ echo " delta delta2 " >> file_3 &&
+ test-genrandom "bar" 150 >> file_2 &&
+ test-genrandom "baz" 100 >> file_3
+}
+
+create_new_pack() {
+ rm -rf .git &&
+ git init &&
+ blob_1=`git hash-object -t blob -w file_1` &&
+ blob_2=`git hash-object -t blob -w file_2` &&
+ blob_3=`git hash-object -t blob -w file_3` &&
+ pack=`printf "$blob_1\n$blob_2\n$blob_3\n" |
+ git pack-objects $@ .git/objects/pack/pack` &&
+ pack=".git/objects/pack/pack-${pack}" &&
+ git verify-pack -v ${pack}.pack
+}
+
+do_repack() {
+ pack=`printf "$blob_1\n$blob_2\n$blob_3\n" |
+ git pack-objects $@ .git/objects/pack/pack` &&
+ pack=".git/objects/pack/pack-${pack}"
+}
+
+do_corrupt_object() {
+ ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` &&
+ ofs=$(($ofs + $2)) &&
+ chmod +w ${pack}.pack &&
+ dd of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs &&
+ test_must_fail git verify-pack ${pack}.pack
+}
+
+printf '\0' > zero
+
+test_expect_success \
+ 'initial setup validation' \
+ 'create_test_files &&
+ create_new_pack &&
+ git prune-packed &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'create corruption in header of first object' \
+ 'do_corrupt_object $blob_1 0 < zero &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... but having a loose copy allows for full recovery' \
+ 'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_1 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and loose copy of first delta allows for partial recovery' \
+ 'git prune-packed &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'create corruption in data of first object' \
+ 'create_new_pack &&
+ git prune-packed &&
+ chmod +w ${pack}.pack &&
+ perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... but having a loose copy allows for full recovery' \
+ 'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_1 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and loose copy of second object allows for partial recovery' \
+ 'git prune-packed &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'create corruption in header of first delta' \
+ 'create_new_pack &&
+ git prune-packed &&
+ do_corrupt_object $blob_2 0 < zero &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... but having a loose copy allows for full recovery' \
+ 'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'create corruption in data of first delta' \
+ 'create_new_pack &&
+ git prune-packed &&
+ chmod +w ${pack}.pack &&
+ perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... but having a loose copy allows for full recovery' \
+ 'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \
+ 'create_new_pack &&
+ git prune-packed &&
+ do_corrupt_object $blob_2 2 < zero &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... but having a loose copy allows for full recovery' \
+ 'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)' \
+ 'create_new_pack --delta-base-offset &&
+ git prune-packed &&
+ do_corrupt_object $blob_2 2 < zero &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... but having a loose copy allows for full recovery' \
+ 'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack --delta-base-offset &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)' \
+ 'create_new_pack --delta-base-offset &&
+ git prune-packed &&
+ printf "\001" | do_corrupt_object $blob_2 2 &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... but having a loose copy allows for full recovery' \
+ 'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack --delta-base-offset &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and a redundant pack allows for full recovery too' \
+ 'do_corrupt_object $blob_2 2 < zero &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null &&
+ mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_1 &&
+ git hash-object -t blob -w file_2 &&
+ printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack &&
+ git prune-packed &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'corrupting header to have too small output buffer fails unpack' \
+ 'create_new_pack &&
+ git prune-packed &&
+ printf "\262\001" | do_corrupt_object $blob_1 0 &&
+ test_must_fail git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_done
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 9fd9d07000..3c6687abec 100644..100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -6,6 +6,17 @@
test_description='prune'
. ./test-lib.sh
+day=$((60*60*24))
+week=$(($day*7))
+
+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
+}
+
test_expect_success setup '
: > file &&
@@ -21,7 +32,7 @@ test_expect_success 'prune stale packs' '
orig_pack=$(echo .git/objects/pack/*.pack) &&
: > .git/objects/tmp_1.pack &&
: > .git/objects/tmp_2.pack &&
- test-chmtime -86501 .git/objects/tmp_1.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 &&
@@ -31,15 +42,11 @@ test_expect_success 'prune stale packs' '
test_expect_success 'prune --expire' '
- before=$(git count-objects | sed "s/ .*//") &&
- BLOB=$(echo aleph | 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 &&
+ add_blob &&
git prune --expire=1.hour.ago &&
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test -f $BLOB_FILE &&
- test-chmtime -86500 $BLOB_FILE &&
+ test-chmtime =-86500 $BLOB_FILE &&
git prune --expire 1.day &&
test $before = $(git count-objects | sed "s/ .*//") &&
! test -f $BLOB_FILE
@@ -48,16 +55,12 @@ test_expect_success 'prune --expire' '
test_expect_success 'gc: implicit prune --expire' '
- 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 &&
- test-chmtime -$((86400*14-30)) $BLOB_FILE &&
+ add_blob &&
+ test-chmtime =-$((2*$week-30)) $BLOB_FILE &&
git gc &&
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test -f $BLOB_FILE &&
- test-chmtime -$((86400*14+1)) $BLOB_FILE &&
+ test-chmtime =-$((2*$week+1)) $BLOB_FILE &&
git gc &&
test $before = $(git count-objects | sed "s/ .*//") &&
! test -f $BLOB_FILE
@@ -112,4 +115,51 @@ test_expect_success 'prune: do not prune heads listed as an argument' '
'
+test_expect_success 'gc --no-prune' '
+
+ add_blob &&
+ 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
+
+'
+
+test_expect_success 'gc respects gc.pruneExpire' '
+
+ git config gc.pruneExpire 5002.days.ago &&
+ git gc &&
+ test -f $BLOB_FILE &&
+ git config gc.pruneExpire 5000.days.ago &&
+ git gc &&
+ test ! -f $BLOB_FILE
+
+'
+
+test_expect_success 'gc --prune=<date>' '
+
+ add_blob &&
+ test-chmtime =-$((5001*$day)) $BLOB_FILE &&
+ git gc --prune=5002.days.ago &&
+ test -f $BLOB_FILE &&
+ git gc --prune=5000.days.ago &&
+ test ! -f $BLOB_FILE
+
+'
+
+test_expect_success 'gc: prune old objects after local clone' '
+ add_blob &&
+ test-chmtime =-$((2*$week+1)) $BLOB_FILE &&
+ git clone --no-hardlinks . aclone &&
+ (
+ cd aclone &&
+ test 1 = $(git count-objects | sed "s/ .*//") &&
+ test -f $BLOB_FILE &&
+ git gc --prune &&
+ test 0 = $(git count-objects | sed "s/ .*//") &&
+ ! test -f $BLOB_FILE
+ )
+'
+
test_done
diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index 0db27547ac..b061864a87 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-pack-object --include-tag'
+test_description='git pack-object --include-tag'
. ./test-lib.sh
TRASH=`pwd`
@@ -50,7 +50,7 @@ test_expect_success 'check unpacked result (have commit, no tag)' '
test_must_fail git cat-file -e $tag &&
git rev-list --objects $commit
) >list.actual &&
- git diff list.expect list.actual
+ test_cmp list.expect list.actual
'
rm -rf clone.git
@@ -78,7 +78,7 @@ test_expect_success 'check unpacked result (have commit, have tag)' '
export GIT_DIR &&
git rev-list --objects $tag
) >list.actual &&
- git diff list.expect list.actual
+ test_cmp list.expect list.actual
'
test_done
diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh
new file mode 100755
index 0000000000..f4931c0c2a
--- /dev/null
+++ b/t/t5306-pack-nobase.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Google Inc.
+#
+
+test_description='git-pack-object with missing base
+
+'
+. ./test-lib.sh
+
+# Create A-B chain
+#
+test_expect_success \
+ 'setup base' \
+ 'for a in a b c d e f g h i; do echo $a >>text; done &&
+ echo side >side &&
+ git update-index --add text side &&
+ A=$(echo A | git commit-tree $(git write-tree)) &&
+
+ echo m >>text &&
+ git update-index text &&
+ B=$(echo B | git commit-tree $(git write-tree) -p $A) &&
+ git update-ref HEAD $B
+ '
+
+# Create repository with C whose parent is B.
+# Repository contains C, C^{tree}, C:text, B, B^{tree}.
+# Repository is missing B:text (best delta base for C:text).
+# Repository is missing A (parent of B).
+# Repository is missing A:side.
+#
+test_expect_success \
+ 'setup patch_clone' \
+ 'base_objects=$(pwd)/.git/objects &&
+ (mkdir patch_clone &&
+ cd patch_clone &&
+ git init &&
+ echo "$base_objects" >.git/objects/info/alternates &&
+ echo q >>text &&
+ git read-tree $B &&
+ git update-index text &&
+ git update-ref HEAD $(echo C | git commit-tree $(git write-tree) -p $B) &&
+ rm .git/objects/info/alternates &&
+
+ git --git-dir=../.git cat-file commit $B |
+ git hash-object -t commit -w --stdin &&
+
+ git --git-dir=../.git cat-file tree "$B^{tree}" |
+ git hash-object -t tree -w --stdin
+ ) &&
+ C=$(git --git-dir=patch_clone/.git rev-parse HEAD)
+ '
+
+# Clone patch_clone indirectly by cloning base and fetching.
+#
+test_expect_success \
+ 'indirectly clone patch_clone' \
+ '(mkdir user_clone &&
+ cd user_clone &&
+ git init &&
+ git pull ../.git &&
+ test $(git rev-parse HEAD) = $B &&
+
+ git pull ../patch_clone/.git &&
+ test $(git rev-parse HEAD) = $C
+ )
+ '
+
+# Cloning the patch_clone directly should fail.
+#
+test_expect_success \
+ 'clone of patch_clone is incomplete' \
+ '(mkdir user_direct &&
+ cd user_direct &&
+ git init &&
+ test_must_fail git fetch ../patch_clone/.git
+ )
+ '
+
+test_done
diff --git a/t/t5307-pack-missing-commit.sh b/t/t5307-pack-missing-commit.sh
new file mode 100755
index 0000000000..ae52a1882d
--- /dev/null
+++ b/t/t5307-pack-missing-commit.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+test_description='pack should notice missing commit objects'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ for i in 1 2 3 4 5
+ do
+ echo "$i" >"file$i" &&
+ git add "file$i" &&
+ test_tick &&
+ git commit -m "$i" &&
+ git tag "tag$i"
+ done &&
+ obj=$(git rev-parse --verify tag3) &&
+ fanout=$(expr "$obj" : "\(..\)") &&
+ remainder=$(expr "$obj" : "..\(.*\)") &&
+ rm -f ".git/objects/$fanout/$remainder"
+'
+
+test_expect_success 'check corruption' '
+ test_must_fail git fsck
+'
+
+test_expect_success 'rev-list notices corruption (1)' '
+ test_must_fail git rev-list HEAD
+'
+
+test_expect_success 'rev-list notices corruption (2)' '
+ test_must_fail git rev-list --objects HEAD
+'
+
+test_expect_success 'pack-objects notices corruption' '
+ echo HEAD |
+ test_must_fail git pack-objects --revs pack
+'
+
+test_done
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index 2b6b6e3f71..f2d5581b12 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -31,10 +31,8 @@ test_expect_success setup '
parent=$commit || return 1
done &&
git update-ref HEAD "$commit" &&
- git-clone ./. victim &&
- cd victim &&
- git log &&
- cd .. &&
+ git clone ./. victim &&
+ ( cd victim && git log ) &&
git update-ref HEAD "$zero" &&
parent=$zero &&
i=0 &&
@@ -59,77 +57,84 @@ test_expect_success 'pack the source repository' '
'
test_expect_success 'pack the destination repository' '
+ (
cd victim &&
git repack -a -d &&
- git prune &&
- cd ..
+ git prune
+ )
'
-test_expect_success \
- 'pushing rewound head should not barf but require --force' '
- # should not fail but refuse to update.
- if git-send-pack ./victim/.git/ master
- then
- # now it should fail with Pasky patch
- echo >&2 Gaah, it should have failed.
- false
- else
- echo >&2 Thanks, it correctly failed.
- true
- fi &&
- if cmp victim/.git/refs/heads/master .git/refs/heads/master
- then
- # should have been left as it was!
- false
- else
- true
- fi &&
+test_expect_success 'refuse pushing rewound head without --force' '
+ pushed_head=$(git rev-parse --verify master) &&
+ victim_orig=$(cd victim && git rev-parse --verify master) &&
+ test_must_fail git send-pack ./victim master &&
+ victim_head=$(cd victim && git rev-parse --verify master) &&
+ test "$victim_head" = "$victim_orig" &&
# this should update
- git-send-pack --force ./victim/.git/ master &&
- cmp victim/.git/refs/heads/master .git/refs/heads/master
+ git send-pack --force ./victim master &&
+ victim_head=$(cd victim && git rev-parse --verify master) &&
+ test "$victim_head" = "$pushed_head"
'
test_expect_success \
'push can be used to delete a ref' '
- cd victim &&
- git branch extra master &&
- cd .. &&
- test -f victim/.git/refs/heads/extra &&
- git-send-pack ./victim/.git/ :extra master &&
- ! test -f victim/.git/refs/heads/extra
+ ( cd victim && git branch extra master ) &&
+ git send-pack ./victim :extra master &&
+ ( cd victim &&
+ test_must_fail git rev-parse --verify extra )
'
-unset GIT_CONFIG GIT_CONFIG_LOCAL
-HOME=`pwd`/no-such-directory
-export HOME ;# this way we force the victim/.git/config to be used.
+test_expect_success 'refuse deleting push with denyDeletes' '
+ (
+ cd victim &&
+ ( git branch -D extra || : ) &&
+ git config receive.denyDeletes true &&
+ git branch extra master
+ ) &&
+ test_must_fail git send-pack ./victim :extra master
+'
-test_expect_success \
- 'pushing with --force should be denied with denyNonFastforwards' '
- cd victim &&
- git config receive.denyNonFastforwards true &&
- cd .. &&
- git update-ref refs/heads/master master^ || return 1
- git-send-pack --force ./victim/.git/ master && return 1
- ! git diff .git/refs/heads/master victim/.git/refs/heads/master
+test_expect_success 'denyNonFastforwards trumps --force' '
+ (
+ cd victim &&
+ ( git branch -D extra || : ) &&
+ git config receive.denyNonFastforwards true
+ ) &&
+ victim_orig=$(cd victim && git rev-parse --verify master) &&
+ test_must_fail git send-pack --force ./victim master^:master &&
+ victim_head=$(cd victim && git rev-parse --verify master) &&
+ test "$victim_orig" = "$victim_head"
'
-test_expect_success \
- 'pushing does not include non-head refs' '
- mkdir parent && cd parent &&
- git-init && touch file && git-add file && git-commit -m add &&
- cd .. &&
- git-clone parent child && cd child && git-push --all &&
- cd ../parent &&
- git-branch -a >branches && ! grep origin/master branches
+test_expect_success 'push --all excludes remote tracking hierarchy' '
+ mkdir parent &&
+ (
+ cd parent &&
+ git init && : >file && git add file && git commit -m add
+ ) &&
+ git clone parent child &&
+ (
+ cd child && git push --all
+ ) &&
+ (
+ cd parent &&
+ test -z "$(git for-each-ref refs/remotes/origin)"
+ )
'
rewound_push_setup() {
rm -rf parent child &&
- mkdir parent && cd parent &&
- git-init && echo one >file && git-add file && git-commit -m one &&
- echo two >file && git-commit -a -m two &&
- cd .. &&
- git-clone parent child && cd child && git-reset --hard HEAD^
+ mkdir parent &&
+ (
+ cd parent &&
+ git init &&
+ echo one >file && git add file && git commit -m one &&
+ echo two >file && git commit -a -m two
+ ) &&
+ git clone parent child &&
+ (
+ cd child && git reset --hard HEAD^
+ )
}
rewound_push_succeeded() {
@@ -145,30 +150,57 @@ rewound_push_failed() {
fi
}
-test_expect_success \
- 'pushing explicit refspecs respects forcing' '
+test_expect_success 'pushing explicit refspecs respects forcing' '
rewound_push_setup &&
- if git-send-pack ../parent/.git refs/heads/master:refs/heads/master
- then
- false
- else
- true
- fi && rewound_push_failed &&
- git-send-pack ../parent/.git +refs/heads/master:refs/heads/master &&
- rewound_push_succeeded
+ parent_orig=$(cd parent && git rev-parse --verify master) &&
+ (
+ cd child &&
+ test_must_fail git send-pack ../parent \
+ refs/heads/master:refs/heads/master
+ ) &&
+ parent_head=$(cd parent && git rev-parse --verify master) &&
+ test "$parent_orig" = "$parent_head" &&
+ (
+ cd child &&
+ git send-pack ../parent \
+ +refs/heads/master:refs/heads/master
+ ) &&
+ parent_head=$(cd parent && git rev-parse --verify master) &&
+ child_head=$(cd parent && git rev-parse --verify master) &&
+ test "$parent_head" = "$child_head"
'
-test_expect_success \
- 'pushing wildcard refspecs respects forcing' '
+test_expect_success 'pushing wildcard refspecs respects forcing' '
rewound_push_setup &&
- if git-send-pack ../parent/.git refs/heads/*:refs/heads/*
- then
- false
- else
- true
- fi && rewound_push_failed &&
- git-send-pack ../parent/.git +refs/heads/*:refs/heads/* &&
- rewound_push_succeeded
+ parent_orig=$(cd parent && git rev-parse --verify master) &&
+ (
+ cd child &&
+ test_must_fail git send-pack ../parent \
+ "refs/heads/*:refs/heads/*"
+ ) &&
+ parent_head=$(cd parent && git rev-parse --verify master) &&
+ test "$parent_orig" = "$parent_head" &&
+ (
+ cd child &&
+ git send-pack ../parent \
+ "+refs/heads/*:refs/heads/*"
+ ) &&
+ parent_head=$(cd parent && git rev-parse --verify master) &&
+ child_head=$(cd parent && git rev-parse --verify master) &&
+ test "$parent_head" = "$child_head"
+'
+
+test_expect_success 'warn pushing to delete current branch' '
+ rewound_push_setup &&
+ (
+ cd child &&
+ git send-pack ../parent :refs/heads/master 2>errs
+ ) &&
+ grep "warning: to refuse deleting" child/errs &&
+ (
+ cd parent &&
+ test_must_fail git rev-parse --verify master
+ )
'
test_done
diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh
index 9a12024241..64f66c94f3 100755
--- a/t/t5401-update-hooks.sh
+++ b/t/t5401-update-hooks.sh
@@ -17,7 +17,7 @@ test_expect_success setup '
commit1=$(echo modify | git commit-tree $tree1 -p $commit0) &&
git update-ref refs/heads/master $commit0 &&
git update-ref refs/heads/tofail $commit1 &&
- git-clone ./. victim &&
+ git clone ./. victim &&
GIT_DIR=victim/.git git update-ref refs/heads/tofail $commit1 &&
git update-ref refs/heads/master $commit1 &&
git update-ref refs/heads/tofail $commit0
@@ -61,7 +61,8 @@ EOF
chmod u+x victim/.git/hooks/post-update
test_expect_success push '
- ! git-send-pack --force ./victim/.git master tofail >send.out 2>send.err
+ test_must_fail git send-pack --force ./victim/.git \
+ master tofail >send.out 2>send.err
'
test_expect_success 'updated as expected' '
@@ -83,23 +84,23 @@ test_expect_success 'hooks ran' '
test_expect_success 'pre-receive hook input' '
(echo $commit0 $commit1 refs/heads/master;
echo $commit1 $commit0 refs/heads/tofail
- ) | git diff - victim/.git/pre-receive.stdin
+ ) | test_cmp - victim/.git/pre-receive.stdin
'
test_expect_success 'update hook arguments' '
(echo refs/heads/master $commit0 $commit1;
echo refs/heads/tofail $commit1 $commit0
- ) | git diff - victim/.git/update.args
+ ) | test_cmp - victim/.git/update.args
'
test_expect_success 'post-receive hook input' '
echo $commit0 $commit1 refs/heads/master |
- git diff - victim/.git/post-receive.stdin
+ test_cmp - victim/.git/post-receive.stdin
'
test_expect_success 'post-update hook arguments' '
echo refs/heads/master |
- git diff - victim/.git/post-update.args
+ test_cmp - victim/.git/post-update.args
'
test_expect_success 'all hook stdin is /dev/null' '
@@ -130,7 +131,7 @@ STDERR post-update
EOF
test_expect_success 'send-pack stderr contains hook messages' '
grep ^STD send.err >actual &&
- git diff - actual <expect
+ test_cmp - actual <expect
'
test_done
diff --git a/t/t5402-post-merge-hook.sh b/t/t5402-post-merge-hook.sh
index 1394047a8d..6eb2ffd6ec 100755
--- a/t/t5402-post-merge-hook.sh
+++ b/t/t5402-post-merge-hook.sh
@@ -16,9 +16,9 @@ test_expect_success setup '
tree1=$(git write-tree) &&
commit1=$(echo modify | git commit-tree $tree1 -p $commit0) &&
git update-ref refs/heads/master $commit0 &&
- git-clone ./. clone1 &&
+ git clone ./. clone1 &&
GIT_DIR=clone1/.git git update-index --add a &&
- git-clone ./. clone2 &&
+ git clone ./. clone2 &&
GIT_DIR=clone2/.git git update-index --add a
'
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 823239a251..d05a9138b4 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,19 +7,19 @@ test_description='Test the post-checkout hook.'
. ./test-lib.sh
test_expect_success setup '
- echo Data for commit0. >a &&
- echo Data for commit0. >b &&
- git update-index --add a &&
- git update-index --add b &&
- tree0=$(git write-tree) &&
- commit0=$(echo setup | git commit-tree $tree0) &&
- git update-ref refs/heads/master $commit0 &&
- git-clone ./. clone1 &&
- git-clone ./. clone2 &&
- GIT_DIR=clone2/.git git branch -a new2 &&
- echo Data for commit1. >clone2/b &&
- GIT_DIR=clone2/.git git add clone2/b &&
- GIT_DIR=clone2/.git git commit -m new2
+ echo Data for commit0. >a &&
+ echo Data for commit0. >b &&
+ git update-index --add a &&
+ git update-index --add b &&
+ tree0=$(git write-tree) &&
+ commit0=$(echo setup | git commit-tree $tree0) &&
+ git update-ref refs/heads/master $commit0 &&
+ git clone ./. clone1 &&
+ git clone ./. clone2 &&
+ GIT_DIR=clone2/.git git branch new2 &&
+ echo Data for commit1. >clone2/b &&
+ GIT_DIR=clone2/.git git add clone2/b &&
+ GIT_DIR=clone2/.git git commit -m new2
'
for clone in 1 2; do
@@ -71,4 +71,18 @@ test_expect_success 'post-checkout receives the right args when not switching br
test $old = $new -a $flag = 0
'
+if test "$(git config --bool core.filemode)" = true; then
+mkdir -p templates/hooks
+cat >templates/hooks/post-checkout <<'EOF'
+#!/bin/sh
+echo $@ > $GIT_DIR/post-checkout.args
+EOF
+chmod +x templates/hooks/post-checkout
+
+test_expect_success 'post-checkout hook is triggered by clone' '
+ git clone --template=templates . clone3 &&
+ test -f clone3/.git/post-checkout.args
+'
+fi
+
test_done
diff --git a/t/t5404-tracking-branches.sh b/t/t5404-tracking-branches.sh
index 1493a92c06..c24003565d 100755
--- a/t/t5404-tracking-branches.sh
+++ b/t/t5404-tracking-branches.sh
@@ -10,6 +10,7 @@ test_expect_success 'setup' '
git commit -m 1 &&
git branch b1 &&
git branch b2 &&
+ git branch b3 &&
git clone . aa &&
git checkout b1 &&
echo b1 >>file &&
@@ -34,7 +35,9 @@ test_expect_success 'prepare pushable branches' '
git commit -a -m aa-master
'
-test_expect_success 'mixed-success push returns error' '! git push'
+test_expect_success 'mixed-success push returns error' '
+ test_must_fail git push
+'
test_expect_success 'check tracking branches updated correctly after push' '
test "$(git rev-parse origin/master)" = "$(git rev-parse master)"
@@ -50,4 +53,10 @@ test_expect_success 'deleted branches have their tracking branches removed' '
test "$(git rev-parse origin/b1)" = "origin/b1"
'
+test_expect_success 'already deleted tracking branches ignored' '
+ git branch -d -r origin/b3 &&
+ git push origin :b3 >output 2>&1 &&
+ ! grep error output
+'
+
test_done
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 86abc62271..cb9aacc7bc 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -12,7 +12,7 @@ test_expect_success setup '
mkdir another && (
cd another &&
git init &&
- git fetch .. master:master
+ git fetch --update-head-ok .. master:master
) &&
>file2 && git add file2 && test_tick &&
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index 46b2cb4e46..59e80a5ea2 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -17,7 +17,7 @@ test_expect_success 'setup' '
git commit -a -m 2
'
-test_expect_success 'push reports error' '! git push 2>stderr'
+test_expect_success 'push reports error' 'test_must_fail git push 2>stderr'
test_expect_success 'individual ref reports error' 'grep rejected stderr'
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 788b4a5aae..18376d6608 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -3,9 +3,8 @@
# Copyright (c) 2005 Johannes Schindelin
#
-test_description='Testing multi_ack pack fetching
+test_description='Testing multi_ack pack fetching'
-'
. ./test-lib.sh
# Test fetch-pack/upload-pack pair.
@@ -13,77 +12,60 @@ test_description='Testing multi_ack pack fetching
# Some convenience functions
add () {
- name=$1
- text="$@"
- branch=`echo $name | sed -e 's/^\(.\).*$/\1/'`
- parents=""
+ name=$1 &&
+ text="$@" &&
+ branch=`echo $name | sed -e 's/^\(.\).*$/\1/'` &&
+ parents="" &&
- shift
+ shift &&
while test $1; do
- parents="$parents -p $1"
+ parents="$parents -p $1" &&
shift
- done
+ done &&
- echo "$text" > test.txt
- git update-index --add test.txt
- tree=$(git write-tree)
+ echo "$text" > test.txt &&
+ git update-index --add test.txt &&
+ tree=$(git write-tree) &&
# make sure timestamps are in correct order
- sec=$(($sec+1))
- commit=$(echo "$text" | GIT_AUTHOR_DATE=$sec \
- git commit-tree $tree $parents 2>>log2.txt)
- export $name=$commit
- echo $commit > .git/refs/heads/$branch
+ test_tick &&
+ commit=$(echo "$text" | git commit-tree $tree $parents) &&
+ eval "$name=$commit; export $name" &&
+ echo $commit > .git/refs/heads/$branch &&
eval ${branch}TIP=$commit
}
-count_objects () {
- ls .git/objects/??/* 2>>log2.txt | wc -l | tr -d " "
-}
-
-test_expect_object_count () {
- message=$1
- count=$2
-
- output="$(count_objects)"
- test_expect_success \
- "new object count $message" \
- "test $count = $output"
-}
-
pull_to_client () {
- number=$1
- heads=$2
- count=$3
- no_strict_count_check=$4
-
- cd client
- test_expect_success "$number pull" \
- "git-fetch-pack -k -v .. $heads"
- case "$heads" in *A*) echo $ATIP > .git/refs/heads/A;; esac
- case "$heads" in *B*) echo $BTIP > .git/refs/heads/B;; esac
- git symbolic-ref HEAD refs/heads/`echo $heads | sed -e 's/^\(.\).*$/\1/'`
-
- test_expect_success "fsck" 'git fsck --full > fsck.txt 2>&1'
-
- test_expect_success 'check downloaded results' \
- 'mv .git/objects/pack/pack-* . &&
- p=`ls -1 pack-*.pack` &&
- git unpack-objects <$p &&
- git fsck --full'
-
- test_expect_success "new object count after $number pull" \
- 'idx=`echo pack-*.idx` &&
- pack_count=`git show-index <$idx | wc -l` &&
- test $pack_count = $count'
- test -z "$pack_count" && pack_count=0
- if [ -z "$no_strict_count_check" ]; then
- test_expect_success "minimal count" "test $count = $pack_count"
- else
- test $count != $pack_count && \
- echo "WARNING: $pack_count objects transmitted, only $count of which were needed"
- fi
- rm -f pack-*
- cd ..
+ number=$1 &&
+ heads=$2 &&
+ count=$3 &&
+ test_expect_success "$number pull" '
+ (
+ cd client &&
+ git fetch-pack -k -v .. $heads &&
+
+ case "$heads" in
+ *A*)
+ echo $ATIP > .git/refs/heads/A;;
+ esac &&
+ case "$heads" in *B*)
+ echo $BTIP > .git/refs/heads/B;;
+ esac &&
+ git symbolic-ref HEAD refs/heads/`echo $heads \
+ | sed -e "s/^\(.\).*$/\1/"` &&
+
+ git fsck --full &&
+
+ mv .git/objects/pack/pack-* . &&
+ p=`ls -1 pack-*.pack` &&
+ git unpack-objects <$p &&
+ git fsck --full &&
+
+ idx=`echo pack-*.idx` &&
+ pack_count=`git show-index <$idx | wc -l` &&
+ test $pack_count = $count &&
+ rm -f pack-*
+ )
+ '
}
# Here begins the actual testing
@@ -94,89 +76,176 @@ pull_to_client () {
# client pulls A20, B1. Then tracks only B. Then pulls A.
-(
+test_expect_success 'setup' '
mkdir client &&
- cd client &&
- git init 2>> log2.txt &&
- git config transfer.unpacklimit 0
-)
-
-add A1
-
-prev=1; cur=2; while [ $cur -le 10 ]; do
- add A$cur $(eval echo \$A$prev)
- prev=$cur
- cur=$(($cur+1))
-done
+ (
+ cd client &&
+ git init &&
+ git config transfer.unpacklimit 0
+ ) &&
+ add A1 &&
+ prev=1 &&
+ cur=2 &&
+ while [ $cur -le 10 ]; do
+ add A$cur $(eval echo \$A$prev) &&
+ prev=$cur &&
+ cur=$(($cur+1))
+ done &&
+ add B1 $A1
+ echo $ATIP > .git/refs/heads/A &&
+ echo $BTIP > .git/refs/heads/B &&
+ git symbolic-ref HEAD refs/heads/B
+'
-add B1 $A1
+pull_to_client 1st "B A" $((11*3))
-echo $ATIP > .git/refs/heads/A
-echo $BTIP > .git/refs/heads/B
-git symbolic-ref HEAD refs/heads/B
+test_expect_success 'post 1st pull setup' '
+ add A11 $A10 &&
+ prev=1 &&
+ cur=2 &&
+ while [ $cur -le 65 ]; do
+ add B$cur $(eval echo \$B$prev) &&
+ prev=$cur &&
+ cur=$(($cur+1))
+ done
+'
-pull_to_client 1st "B A" $((11*3))
+pull_to_client 2nd "B" $((64*3))
-add A11 $A10
+pull_to_client 3rd "A" $((1*3))
-prev=1; cur=2; while [ $cur -le 65 ]; do
- add B$cur $(eval echo \$B$prev)
- prev=$cur
- cur=$(($cur+1))
-done
+test_expect_success 'clone shallow' '
+ git clone --depth 2 "file://$(pwd)/." shallow
+'
-pull_to_client 2nd "B" $((64*3))
+test_expect_success 'clone shallow object count' '
+ (
+ cd shallow &&
+ git count-objects -v
+ ) > count.shallow &&
+ grep "^in-pack: 18" count.shallow
+'
-pull_to_client 3rd "A" $((1*3)) # old fails
+test_expect_success 'clone shallow object count (part 2)' '
+ sed -e "/^in-pack:/d" -e "/^packs:/d" -e "/^size-pack:/d" \
+ -e "/: 0$/d" count.shallow > count_output &&
+ ! test -s count_output
+'
-test_expect_success "clone shallow" "git-clone --depth 2 file://`pwd`/. shallow"
+test_expect_success 'fsck in shallow repo' '
+ (
+ cd shallow &&
+ git fsck --full
+ )
+'
-(cd shallow; git count-objects -v) > count.shallow
+test_expect_success 'simple fetch in shallow repo' '
+ (
+ cd shallow &&
+ git fetch
+ )
+'
-test_expect_success "clone shallow object count" \
- "test \"in-pack: 18\" = \"$(grep in-pack count.shallow)\""
+test_expect_success 'no changes expected' '
+ (
+ cd shallow &&
+ git count-objects -v
+ ) > count.shallow.2 &&
+ cmp count.shallow count.shallow.2
+'
-count_output () {
- sed -e '/^in-pack:/d' -e '/^packs:/d' -e '/: 0$/d' "$1"
-}
+test_expect_success 'fetch same depth in shallow repo' '
+ (
+ cd shallow &&
+ git fetch --depth=2
+ )
+'
-test_expect_success "clone shallow object count (part 2)" '
- test -z "$(count_output count.shallow)"
+test_expect_success 'no changes expected' '
+ (
+ cd shallow &&
+ git count-objects -v
+ ) > count.shallow.3 &&
+ cmp count.shallow count.shallow.3
'
-test_expect_success "fsck in shallow repo" \
- "(cd shallow; git fsck --full)"
+test_expect_success 'add two more' '
+ add B66 $B65 &&
+ add B67 $B66
+'
-#test_done; exit
+test_expect_success 'pull in shallow repo' '
+ (
+ cd shallow &&
+ git pull .. B
+ )
+'
-add B66 $B65
-add B67 $B66
+test_expect_success 'clone shallow object count' '
+ (
+ cd shallow &&
+ git count-objects -v
+ ) > count.shallow &&
+ grep "^count: 6" count.shallow
+'
-test_expect_success "pull in shallow repo" \
- "(cd shallow; git pull .. B)"
+test_expect_success 'add two more (part 2)' '
+ add B68 $B67 &&
+ add B69 $B68
+'
-(cd shallow; git count-objects -v) > count.shallow
-test_expect_success "clone shallow object count" \
- "test \"count: 6\" = \"$(grep count count.shallow)\""
+test_expect_success 'deepening pull in shallow repo' '
+ (
+ cd shallow &&
+ git pull --depth 4 .. B
+ )
+'
-add B68 $B67
-add B69 $B68
+test_expect_success 'clone shallow object count' '
+ (
+ cd shallow &&
+ git count-objects -v
+ ) > count.shallow &&
+ grep "^count: 12" count.shallow
+'
-test_expect_success "deepening pull in shallow repo" \
- "(cd shallow; git pull --depth 4 .. B)"
+test_expect_success 'deepening fetch in shallow repo' '
+ (
+ cd shallow &&
+ git fetch --depth 4 .. A:A
+ )
+'
-(cd shallow; git count-objects -v) > count.shallow
-test_expect_success "clone shallow object count" \
- "test \"count: 12\" = \"$(grep count count.shallow)\""
+test_expect_success 'clone shallow object count' '
+ (
+ cd shallow &&
+ git count-objects -v
+ ) > count.shallow &&
+ grep "^count: 18" count.shallow
+'
-test_expect_success "deepening fetch in shallow repo" \
- "(cd shallow; git fetch --depth 4 .. A:A)"
+test_expect_success 'pull in shallow repo with missing merge base' '
+ (
+ cd shallow &&
+ test_must_fail git pull --depth 4 .. A
+ )
+'
-(cd shallow; git count-objects -v) > count.shallow
-test_expect_success "clone shallow object count" \
- "test \"count: 18\" = \"$(grep count count.shallow)\""
+test_expect_success 'additional simple shallow deepenings' '
+ (
+ cd shallow &&
+ git fetch --depth=8 &&
+ git fetch --depth=10 &&
+ git fetch --depth=11
+ )
+'
-test_expect_success "pull in shallow repo with missing merge base" \
- "(cd shallow && ! git pull --depth 4 .. A)"
+test_expect_success 'clone shallow object count' '
+ (
+ cd shallow &&
+ git count-objects -v
+ ) > count.shallow &&
+ grep "^count: 52" count.shallow
+'
test_done
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index 16eadd6b68..1037a723fe 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -119,4 +119,24 @@ test_expect_success 'quickfetch should not copy from alternate' '
'
+test_expect_success 'quickfetch should handle ~1000 refs (on Windows)' '
+
+ git gc &&
+ head=$(git rev-parse HEAD) &&
+ branchprefix="$head refs/heads/branch" &&
+ for i in 0 1 2 3 4 5 6 7 8 9; do
+ for j in 0 1 2 3 4 5 6 7 8 9; do
+ for k in 0 1 2 3 4 5 6 7 8 9; do
+ echo "$branchprefix$i$j$k" >> .git/packed-refs
+ done
+ done
+ done &&
+ (
+ cd cloned &&
+ git fetch &&
+ git fetch
+ )
+
+'
+
test_done
diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh
index 86e5b9bc26..d5db75d826 100755
--- a/t/t5503-tagfollow.sh
+++ b/t/t5503-tagfollow.sh
@@ -4,6 +4,12 @@ test_description='test automatic tag following'
. ./test-lib.sh
+case $(uname -s) in
+*MINGW*)
+ say "GIT_DEBUG_SEND_PACK not supported - skipping tests"
+ test_done
+esac
+
# End state of the repository:
#
# T - tag1 S - tag2
@@ -50,7 +56,7 @@ test_expect_success 'fetch A (new commit : 1 connection)' '
) &&
test -s $U &&
cut -d" " -f1,2 $U >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success "create tag T on A, create C on branch cat" '
@@ -82,7 +88,7 @@ test_expect_success 'fetch C, T (new branch, tag : 1 connection)' '
) &&
test -s $U &&
cut -d" " -f1,2 $U >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success "create commits O, B, tag S on B" '
@@ -118,7 +124,7 @@ test_expect_success 'fetch B, S (commit and tag : 1 connection)' '
) &&
test -s $U &&
cut -d" " -f1,2 $U >actual &&
- git diff expect actual
+ test_cmp expect actual
'
cat - <<EOF >expect
@@ -144,7 +150,7 @@ test_expect_success 'new clone fetch master and tags' '
) &&
test -s $U &&
cut -d" " -f1,2 $U >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_done
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 48ff2d424d..936fe0a1a6 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -28,7 +28,7 @@ tokens_match () {
}
check_remote_track () {
- actual=$(git remote show "$1" | sed -n -e '$p') &&
+ actual=$(git remote show "$1" | sed -ne 's|^ \(.*\) tracked$|\1|p')
shift &&
tokens_match "$*" "$actual"
}
@@ -107,35 +107,114 @@ test_expect_success 'remove remote' '
)
'
+test_expect_success 'remove remote protects non-remote branches' '
+(
+ cd test &&
+ (cat >expect1 <<EOF
+Note: A non-remote branch was not removed; to delete it, use:
+ git branch -d master
+EOF
+ cat >expect2 <<EOF
+Note: Non-remote branches were not removed; to delete them, use:
+ git branch -d foobranch
+ git branch -d master
+EOF
+) &&
+ git tag footag
+ git config --add remote.oops.fetch "+refs/*:refs/*" &&
+ git remote rm oops 2>actual1 &&
+ git branch foobranch &&
+ git config --add remote.oops.fetch "+refs/*:refs/*" &&
+ git remote rm oops 2>actual2 &&
+ git branch -d foobranch &&
+ git tag -d footag &&
+ test_cmp expect1 actual1 &&
+ test_cmp expect2 actual2
+)
+'
+
cat > test/expect << EOF
* remote origin
- URL: $(pwd)/one/.git
- Remote branch merged with 'git pull' while on branch master
- master
- New remote branch (next fetch will store in remotes/origin)
+ Fetch URL: $(pwd)/one
+ Push URL: $(pwd)/one
+ HEAD branch: master
+ Remote branches:
+ master new (next fetch will store in remotes/origin)
+ side tracked
+ Local branches configured for 'git pull':
+ ahead merges with remote master
+ master merges with remote master
+ octopus merges with remote topic-a
+ and with remote topic-b
+ and with remote topic-c
+ rebase rebases onto remote master
+ Local refs configured for 'git push':
+ master pushes to master (local out of date)
+ master pushes to upstream (create)
+* remote two
+ Fetch URL: ../two
+ Push URL: ../three
+ HEAD branch (remote HEAD is ambiguous, may be one of the following):
+ another
master
- Tracked remote branches
- side master
- Local branches pushed with 'git push'
- master:upstream +refs/tags/lastbackup
+ Local refs configured for 'git push':
+ ahead forces to master (fast-forwardable)
+ master pushes to another (up to date)
EOF
test_expect_success 'show' '
(cd test &&
- git config --add remote.origin.fetch \
- refs/heads/master:refs/heads/upstream &&
+ git config --add remote.origin.fetch refs/heads/master:refs/heads/upstream &&
git fetch &&
+ git checkout -b ahead origin/master &&
+ echo 1 >> file &&
+ test_tick &&
+ git commit -m update file &&
+ git checkout master &&
+ git branch --track octopus origin/master &&
+ git branch --track rebase origin/master &&
git branch -d -r origin/master &&
+ git config --add remote.two.url ../two &&
+ git config --add remote.two.pushurl ../three &&
+ git config branch.rebase.rebase true &&
+ git config branch.octopus.merge "topic-a topic-b topic-c" &&
(cd ../one &&
echo 1 > file &&
test_tick &&
git commit -m update file) &&
- git config remote.origin.push \
- refs/heads/master:refs/heads/upstream &&
- git config --add remote.origin.push \
- +refs/tags/lastbackup &&
- git remote show origin > output &&
- git diff expect output)
+ git config --add remote.origin.push : &&
+ git config --add remote.origin.push refs/heads/master:refs/heads/upstream &&
+ git config --add remote.origin.push +refs/tags/lastbackup &&
+ git config --add remote.two.push +refs/heads/ahead:refs/heads/master &&
+ git config --add remote.two.push refs/heads/master:refs/heads/another &&
+ git remote show origin two > output &&
+ git branch -d rebase octopus &&
+ test_cmp expect output)
+'
+
+cat > test/expect << EOF
+* remote origin
+ Fetch URL: $(pwd)/one
+ Push URL: $(pwd)/one
+ HEAD branch: (not queried)
+ Remote branches: (status not queried)
+ master
+ side
+ Local branches configured for 'git pull':
+ ahead merges with remote master
+ master merges with remote master
+ Local refs configured for 'git push' (status not queried):
+ (matching) pushes to (matching)
+ refs/heads/master pushes to refs/heads/upstream
+ refs/tags/lastbackup forces to refs/tags/lastbackup
+EOF
+
+test_expect_success 'show -n' '
+ (mv one one.unreachable &&
+ cd test &&
+ git remote show -n origin > output &&
+ mv ../one.unreachable ../one &&
+ test_cmp expect output)
'
test_expect_success 'prune' '
@@ -145,25 +224,101 @@ test_expect_success 'prune' '
git fetch origin &&
git remote prune origin &&
git rev-parse refs/remotes/origin/side2 &&
- ! git rev-parse refs/remotes/origin/side)
+ test_must_fail git rev-parse refs/remotes/origin/side)
+'
+
+test_expect_success 'set-head --delete' '
+ (cd test &&
+ git symbolic-ref refs/remotes/origin/HEAD &&
+ git remote set-head --delete origin &&
+ test_must_fail git symbolic-ref refs/remotes/origin/HEAD)
+'
+
+test_expect_success 'set-head --auto' '
+ (cd test &&
+ git remote set-head --auto origin &&
+ echo refs/remotes/origin/master >expect &&
+ git symbolic-ref refs/remotes/origin/HEAD >output &&
+ test_cmp expect output
+ )
+'
+
+cat >test/expect <<EOF
+error: Multiple remote HEAD branches. Please choose one explicitly with:
+ git remote set-head two another
+ git remote set-head two master
+EOF
+
+test_expect_success 'set-head --auto fails w/multiple HEADs' '
+ (cd test &&
+ test_must_fail git remote set-head --auto two >output 2>&1 &&
+ test_cmp expect output)
+'
+
+cat >test/expect <<EOF
+refs/remotes/origin/side2
+EOF
+
+test_expect_success 'set-head explicit' '
+ (cd test &&
+ git remote set-head origin side2 &&
+ git symbolic-ref refs/remotes/origin/HEAD >output &&
+ git remote set-head origin master &&
+ test_cmp expect output)
+'
+
+cat > test/expect << EOF
+Pruning origin
+URL: $(pwd)/one
+ * [would prune] origin/side2
+EOF
+
+test_expect_success 'prune --dry-run' '
+ (cd one &&
+ git branch -m side2 side) &&
+ (cd test &&
+ git remote prune --dry-run origin > output &&
+ git rev-parse refs/remotes/origin/side2 &&
+ test_must_fail git rev-parse refs/remotes/origin/side &&
+ (cd ../one &&
+ git branch -m side side2) &&
+ test_cmp expect output)
'
test_expect_success 'add --mirror && prune' '
(mkdir mirror &&
cd mirror &&
- git init &&
+ git init --bare &&
git remote add --mirror -f origin ../one) &&
(cd one &&
git branch -m side2 side) &&
(cd mirror &&
git rev-parse --verify refs/heads/side2 &&
- ! git rev-parse --verify refs/heads/side &&
+ test_must_fail git rev-parse --verify refs/heads/side &&
git fetch origin &&
git remote prune origin &&
- ! git rev-parse --verify refs/heads/side2 &&
+ test_must_fail git rev-parse --verify refs/heads/side2 &&
git rev-parse --verify refs/heads/side)
'
+test_expect_success 'add alt && prune' '
+ (mkdir alttst &&
+ cd alttst &&
+ git init &&
+ git remote add -f origin ../one &&
+ git config remote.alt.url ../one &&
+ git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*") &&
+ (cd one &&
+ git branch -m side side2) &&
+ (cd alttst &&
+ git rev-parse --verify refs/remotes/origin/side &&
+ test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
+ git fetch alt &&
+ git remote prune alt &&
+ test_must_fail git rev-parse --verify refs/remotes/origin/side &&
+ git rev-parse --verify refs/remotes/origin/side2)
+'
+
cat > one/expect << EOF
apis/master
apis/side
@@ -179,7 +334,7 @@ test_expect_success 'update' '
git remote add apis ../mirror &&
git remote update &&
git branch -r > output &&
- git diff expect output)
+ test_cmp expect output)
'
@@ -206,8 +361,19 @@ test_expect_success 'update with arguments' '
git config remotes.titanus manduca &&
git remote update phobaeticus titanus &&
git branch -r > output &&
- git diff expect output)
+ test_cmp expect output)
+
+'
+test_expect_success 'update --prune' '
+
+ (cd one &&
+ git branch -m side2 side3) &&
+ (cd test &&
+ git remote update --prune &&
+ (cd ../one && git branch -m side3 side2)
+ git rev-parse refs/remotes/origin/side3 &&
+ test_must_fail git rev-parse refs/remotes/origin/side2)
'
cat > one/expect << EOF
@@ -229,7 +395,7 @@ test_expect_success 'update default' '
git config remote.drosophila.skipDefaultUpdate true &&
git remote update default &&
git branch -r > output &&
- git diff expect output)
+ test_cmp expect output)
'
@@ -249,7 +415,21 @@ test_expect_success 'update default (overridden, with funny whitespace)' '
git config remotes.default "$(printf "\t drosophila \n")" &&
git remote update default &&
git branch -r > output &&
- git diff expect output)
+ test_cmp expect output)
+
+'
+
+test_expect_success 'update (with remotes.default defined)' '
+
+ (cd one &&
+ for b in $(git branch -r)
+ do
+ git branch -r -d $b || break
+ done &&
+ git config remotes.default "drosophila" &&
+ git remote update &&
+ git branch -r > output &&
+ test_cmp expect output)
'
@@ -258,15 +438,100 @@ test_expect_success '"remote show" does not show symbolic refs' '
git clone one three &&
(cd three &&
git remote show origin > output &&
- ! grep HEAD < output &&
+ ! grep "^ *HEAD$" < output &&
! grep -i stale < output)
'
test_expect_success 'reject adding remote with an invalid name' '
- ! git remote add some:url desired-name
+ test_must_fail git remote add some:url desired-name
'
+# The first three test if the tracking branches are properly renamed,
+# the last two ones check if the config is updated.
+
+test_expect_success 'rename a remote' '
+
+ git clone one four &&
+ (cd four &&
+ git remote rename origin upstream &&
+ rmdir .git/refs/remotes/origin &&
+ test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
+ test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
+ test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
+ test "$(git config branch.master.remote)" = "upstream")
+
+'
+
+cat > remotes_origin << EOF
+URL: $(pwd)/one
+Push: refs/heads/master:refs/heads/upstream
+Pull: refs/heads/master:refs/heads/origin
+EOF
+
+test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
+ git clone one five &&
+ origin_url=$(pwd)/one &&
+ (cd five &&
+ git remote rm origin &&
+ mkdir -p .git/remotes &&
+ cat ../remotes_origin > .git/remotes/origin &&
+ git remote rename origin origin &&
+ ! test -f .git/remotes/origin &&
+ test "$(git config remote.origin.url)" = "$origin_url" &&
+ test "$(git config remote.origin.push)" = "refs/heads/master:refs/heads/upstream" &&
+ test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+'
+
+test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
+ git clone one six &&
+ origin_url=$(pwd)/one &&
+ (cd six &&
+ git remote rm origin &&
+ echo "$origin_url" > .git/branches/origin &&
+ git remote rename origin origin &&
+ ! test -f .git/branches/origin &&
+ test "$(git config remote.origin.url)" = "$origin_url" &&
+ test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+'
+
+test_expect_success 'remote prune to cause a dangling symref' '
+ git clone one seven &&
+ (
+ cd one &&
+ git checkout side2 &&
+ git branch -D master
+ ) &&
+ (
+ cd seven &&
+ git remote prune origin
+ ) 2>err &&
+ grep "has become dangling" err &&
+
+ : And the dangling symref will not cause other annoying errors
+ (
+ cd seven &&
+ git branch -a
+ ) 2>err &&
+ ! grep "points nowhere" err
+ (
+ cd seven &&
+ test_must_fail git branch nomore origin
+ ) 2>err &&
+ grep "dangling symref" err
+'
+
+test_expect_success 'show empty remote' '
+
+ test_create_repo empty &&
+ git clone empty empty-clone &&
+ (
+ cd empty-clone &&
+ git remote show origin
+ )
+'
+
test_done
+
diff --git a/t/t5506-remote-groups.sh b/t/t5506-remote-groups.sh
new file mode 100755
index 0000000000..b7b7ddaa40
--- /dev/null
+++ b/t/t5506-remote-groups.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+test_description='git remote group handling'
+. ./test-lib.sh
+
+mark() {
+ echo "$1" >mark
+}
+
+update_repo() {
+ (cd $1 &&
+ echo content >>file &&
+ git add file &&
+ git commit -F ../mark)
+}
+
+update_repos() {
+ update_repo one $1 &&
+ update_repo two $1
+}
+
+repo_fetched() {
+ if test "`git log -1 --pretty=format:%s $1 --`" = "`cat mark`"; then
+ echo >&2 "repo was fetched: $1"
+ return 0
+ fi
+ echo >&2 "repo was not fetched: $1"
+ return 1
+}
+
+test_expect_success 'setup' '
+ mkdir one && (cd one && git init) &&
+ mkdir two && (cd two && git init) &&
+ git remote add -m master one one &&
+ git remote add -m master two two
+'
+
+test_expect_success 'no group updates all' '
+ mark update-all &&
+ update_repos &&
+ git remote update &&
+ repo_fetched one &&
+ repo_fetched two
+'
+
+test_expect_success 'nonexistant group produces error' '
+ mark nonexistant &&
+ update_repos &&
+ test_must_fail git remote update nonexistant &&
+ ! repo_fetched one &&
+ ! repo_fetched two
+'
+
+test_expect_success 'updating group updates all members (remote update)' '
+ mark group-all &&
+ update_repos &&
+ git config --add remotes.all one &&
+ git config --add remotes.all two &&
+ git remote update all &&
+ repo_fetched one &&
+ repo_fetched two
+'
+
+test_expect_success 'updating group updates all members (fetch)' '
+ mark fetch-group-all &&
+ update_repos &&
+ git fetch all &&
+ repo_fetched one &&
+ repo_fetched two
+'
+
+test_expect_success 'updating group does not update non-members (remote update)' '
+ mark group-some &&
+ update_repos &&
+ git config --add remotes.some one &&
+ git remote update some &&
+ repo_fetched one &&
+ ! repo_fetched two
+'
+
+test_expect_success 'updating group does not update non-members (fetch)' '
+ mark fetch-group-some &&
+ update_repos &&
+ git config --add remotes.some one &&
+ git remote update some &&
+ repo_fetched one &&
+ ! repo_fetched two
+'
+
+test_expect_success 'updating remote name updates that remote' '
+ mark remote-name &&
+ update_repos &&
+ git remote update one &&
+ repo_fetched one &&
+ ! repo_fetched two
+'
+
+test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 6946557c67..169af1edde 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -9,6 +9,11 @@ test_description='Per branch config variables affects "git fetch".
D=`pwd`
+test_bundle_object_count () {
+ git verify-pack -v "$1" >verify.out &&
+ test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l)
+}
+
test_expect_success setup '
echo >file original &&
git add file &&
@@ -37,7 +42,8 @@ test_expect_success "clone and setup child repos" '
echo "Pull: refs/heads/one:refs/heads/one"
} >.git/remotes/two &&
cd .. &&
- git clone . bundle
+ git clone . bundle &&
+ git clone . seven
'
test_expect_success "fetch test" '
@@ -103,20 +109,20 @@ test_expect_success 'fetch must not resolve short tag name' '
cd five &&
git init &&
- ! git fetch .. anno:five
+ test_must_fail git fetch .. anno:five
'
test_expect_success 'fetch must not resolve short remote name' '
cd "$D" &&
- git-update-ref refs/remotes/six/HEAD HEAD
+ git update-ref refs/remotes/six/HEAD HEAD
mkdir six &&
cd six &&
git init &&
- ! git fetch .. six:six
+ test_must_fail git fetch .. six:six
'
@@ -142,9 +148,10 @@ test_expect_success 'create bundle 2' '
test_expect_success 'unbundle 1' '
cd "$D/bundle" &&
git checkout -b some-branch &&
- ! git fetch "$D/bundle1" master:master
+ test_must_fail git fetch "$D/bundle1" master:master
'
+
test_expect_success 'bundle 1 has only 3 files ' '
cd "$D" &&
(
@@ -155,8 +162,7 @@ test_expect_success 'bundle 1 has only 3 files ' '
cat
) <bundle1 >bundle.pack &&
git index-pack bundle.pack &&
- verify=$(git verify-pack -v bundle.pack) &&
- test 4 = $(echo "$verify" | wc -l)
+ test_bundle_object_count bundle.pack 3
'
test_expect_success 'unbundle 2' '
@@ -179,7 +185,7 @@ test_expect_success 'bundle does not prerequisite objects' '
cat
) <bundle3 >bundle.pack &&
git index-pack bundle.pack &&
- test 4 = $(git verify-pack -v bundle.pack | wc -l)
+ test_bundle_object_count bundle.pack 3
'
test_expect_success 'bundle should be able to create a full history' '
@@ -190,38 +196,39 @@ test_expect_success 'bundle should be able to create a full history' '
'
-test "$TEST_RSYNC" && {
+! rsync --help > /dev/null 2> /dev/null &&
+say 'Skipping rsync tests because rsync was not found' || {
test_expect_success 'fetch via rsync' '
git pack-refs &&
mkdir rsynced &&
- cd rsynced &&
- git init &&
- git fetch rsync://127.0.0.1$(pwd)/../.git master:refs/heads/master &&
- git gc --prune &&
- test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
- git fsck --full
+ (cd rsynced &&
+ git init --bare &&
+ git fetch "rsync:$(pwd)/../.git" master:refs/heads/master &&
+ git gc --prune &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full)
'
test_expect_success 'push via rsync' '
- mkdir ../rsynced2 &&
- (cd ../rsynced2 &&
+ mkdir rsynced2 &&
+ (cd rsynced2 &&
git init) &&
- git push rsync://127.0.0.1$(pwd)/../rsynced2/.git master &&
- cd ../rsynced2 &&
- git gc --prune &&
- test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
- git fsck --full
+ (cd rsynced &&
+ git push "rsync:$(pwd)/../rsynced2/.git" master) &&
+ (cd rsynced2 &&
+ git gc --prune &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full)
'
test_expect_success 'push via rsync' '
- cd .. &&
mkdir rsynced3 &&
(cd rsynced3 &&
git init) &&
- git push --all rsync://127.0.0.1$(pwd)/rsynced3/.git &&
- cd rsynced3 &&
- test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
- git fsck --full
+ git push --all "rsync:$(pwd)/rsynced3/.git" &&
+ (cd rsynced3 &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full)
'
}
@@ -235,7 +242,7 @@ test_expect_success 'fetch with a non-applying branch.<name>.merge' '
# the strange name is: a\!'b
test_expect_success 'quoting of a strangely named repo' '
- ! git fetch "a\\!'\''b" > result 2>&1 &&
+ test_must_fail git fetch "a\\!'\''b" > result 2>&1 &&
cat result &&
grep "fatal: '\''a\\\\!'\''b'\''" result
'
@@ -263,7 +270,7 @@ test_expect_success 'explicit fetch should not update tracking' '
git fetch origin master &&
n=$(git rev-parse --verify refs/remotes/origin/master) &&
test "$o" = "$n" &&
- ! git rev-parse --verify refs/remotes/origin/side
+ test_must_fail git rev-parse --verify refs/remotes/origin/side
)
'
@@ -277,7 +284,7 @@ test_expect_success 'explicit pull should not update tracking' '
git pull origin master &&
n=$(git rev-parse --verify refs/remotes/origin/master) &&
test "$o" = "$n" &&
- ! git rev-parse --verify refs/remotes/origin/side
+ test_must_fail git rev-parse --verify refs/remotes/origin/side
)
'
@@ -295,4 +302,54 @@ test_expect_success 'configured fetch updates tracking' '
)
'
+test_expect_success 'pushing nonexistent branch by mistake should not segv' '
+
+ cd "$D" &&
+ test_must_fail git push seven no:no
+
+'
+
+test_expect_success 'auto tag following fetches minimum' '
+
+ cd "$D" &&
+ git clone .git follow &&
+ git checkout HEAD^0 &&
+ (
+ for i in 1 2 3 4 5 6 7
+ do
+ echo $i >>file &&
+ git commit -m $i -a &&
+ git tag -a -m $i excess-$i || exit 1
+ done
+ ) &&
+ git checkout master &&
+ (
+ cd follow &&
+ git fetch
+ )
+'
+
+test_expect_success 'refuse to fetch into the current branch' '
+
+ test_must_fail git fetch . side:master
+
+'
+
+test_expect_success 'fetch into the current branch with --update-head-ok' '
+
+ git fetch --update-head-ok . side:master
+
+'
+
+test_expect_success "should be able to fetch with duplicate refspecs" '
+ mkdir dups &&
+ cd dups &&
+ git init &&
+ git config branch.master.remote three &&
+ git config remote.three.url ../three/.git &&
+ git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
+ git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
+ git fetch three
+'
+
test_done
diff --git a/t/t5511-refspec.sh b/t/t5511-refspec.sh
index 670a8f1c99..c28932216b 100755
--- a/t/t5511-refspec.sh
+++ b/t/t5511-refspec.sh
@@ -23,10 +23,13 @@ test_refspec () {
}
test_refspec push '' invalid
-test_refspec push ':' invalid
+test_refspec push ':'
+test_refspec push '::' invalid
+test_refspec push '+:'
test_refspec fetch ''
test_refspec fetch ':'
+test_refspec fetch '::' invalid
test_refspec push 'refs/heads/*:refs/remotes/frotz/*'
test_refspec push 'refs/heads/*:refs/remotes/frotz' invalid
@@ -69,4 +72,16 @@ test_refspec fetch ':refs/remotes/frotz/HEAD-to-me'
test_refspec push ':refs/remotes/frotz/delete me' invalid
test_refspec fetch ':refs/remotes/frotz/HEAD to me' invalid
+test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*-blah' invalid
+test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*-blah' invalid
+
+test_refspec fetch 'refs/heads*/for-linus:refs/remotes/mine/*' invalid
+test_refspec push 'refs/heads*/for-linus:refs/remotes/mine/*' invalid
+
+test_refspec fetch 'refs/heads/*/*/for-linus:refs/remotes/mine/*' invalid
+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/*'
+
test_done
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index c0dc94909b..1dd8eed5bb 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -17,7 +17,7 @@ test_expect_success setup '
git show-ref -d | sed -e "s/ / /"
) >expected.all &&
- git remote add self $(pwd)/.git
+ git remote add self "$(pwd)/.git"
'
diff --git a/t/t5513-fetch-track.sh b/t/t5513-fetch-track.sh
new file mode 100755
index 0000000000..9e7486274b
--- /dev/null
+++ b/t/t5513-fetch-track.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+test_description='fetch follows remote tracking branches correctly'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ >file &&
+ git add . &&
+ test_tick &&
+ git commit -m Initial &&
+ git branch b-0 &&
+ git branch b1 &&
+ git branch b/one &&
+ test_create_repo other &&
+ (
+ cd other &&
+ git config remote.origin.url .. &&
+ git config remote.origin.fetch "+refs/heads/b/*:refs/remotes/b/*"
+ )
+'
+
+test_expect_success fetch '
+ (
+ cd other && git fetch origin &&
+ test "$(git for-each-ref --format="%(refname)")" = refs/remotes/b/one
+ )
+'
+
+test_done
diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh
new file mode 100755
index 0000000000..b73733219d
--- /dev/null
+++ b/t/t5514-fetch-multiple.sh
@@ -0,0 +1,154 @@
+#!/bin/sh
+
+test_description='fetch --all works correctly'
+
+. ./test-lib.sh
+
+setup_repository () {
+ mkdir "$1" && (
+ cd "$1" &&
+ git init &&
+ >file &&
+ git add file &&
+ test_tick &&
+ git commit -m "Initial" &&
+ git checkout -b side &&
+ >elif &&
+ git add elif &&
+ test_tick &&
+ git commit -m "Second" &&
+ git checkout master
+ )
+}
+
+test_expect_success setup '
+ setup_repository one &&
+ setup_repository two &&
+ (
+ cd two && git branch another
+ ) &&
+ git clone --mirror two three
+ git clone one test
+'
+
+cat > test/expect << EOF
+ one/master
+ one/side
+ origin/HEAD -> origin/master
+ origin/master
+ origin/side
+ three/another
+ three/master
+ three/side
+ two/another
+ two/master
+ two/side
+EOF
+
+test_expect_success 'git fetch --all' '
+ (cd test &&
+ git remote add one ../one &&
+ git remote add two ../two &&
+ git remote add three ../three &&
+ git fetch --all &&
+ git branch -r > output &&
+ test_cmp expect output)
+'
+
+test_expect_success 'git fetch --all should continue if a remote has errors' '
+ (git clone one test2 &&
+ cd test2 &&
+ git remote add bad ../non-existing &&
+ git remote add one ../one &&
+ git remote add two ../two &&
+ git remote add three ../three &&
+ test_must_fail git fetch --all &&
+ git branch -r > output &&
+ test_cmp ../test/expect output)
+'
+
+test_expect_success 'git fetch --all does not allow non-option arguments' '
+ (cd test &&
+ test_must_fail git fetch --all origin &&
+ test_must_fail git fetch --all origin master)
+'
+
+cat > expect << EOF
+ origin/HEAD -> origin/master
+ origin/master
+ origin/side
+ three/another
+ three/master
+ three/side
+EOF
+
+test_expect_success 'git fetch --multiple (but only one remote)' '
+ (git clone one test3 &&
+ cd test3 &&
+ git remote add three ../three &&
+ git fetch --multiple three &&
+ git branch -r > output &&
+ test_cmp ../expect output)
+'
+
+cat > expect << EOF
+ one/master
+ one/side
+ two/another
+ two/master
+ two/side
+EOF
+
+test_expect_success 'git fetch --multiple (two remotes)' '
+ (git clone one test4 &&
+ cd test4 &&
+ git remote rm origin &&
+ git remote add one ../one &&
+ git remote add two ../two &&
+ git fetch --multiple one two &&
+ git branch -r > output &&
+ test_cmp ../expect output)
+'
+
+test_expect_success 'git fetch --multiple (bad remote names)' '
+ (cd test4 &&
+ test_must_fail git fetch --multiple four)
+'
+
+
+test_expect_success 'git fetch --all (skipFetchAll)' '
+ (cd test4 &&
+ for b in $(git branch -r)
+ do
+ git branch -r -d $b || break
+ done &&
+ git remote add three ../three &&
+ git config remote.three.skipFetchAll true &&
+ git fetch --all &&
+ git branch -r > output &&
+ test_cmp ../expect output)
+'
+
+cat > expect << EOF
+ one/master
+ one/side
+ three/another
+ three/master
+ three/side
+ two/another
+ two/master
+ two/side
+EOF
+
+test_expect_success 'git fetch --multiple (ignoring skipFetchAll)' '
+ (cd test4 &&
+ for b in $(git branch -r)
+ do
+ git branch -r -d $b || break
+ done &&
+ git fetch --multiple one two three &&
+ git branch -r > output &&
+ test_cmp ../expect output)
+'
+
+test_done
diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh
index 65c37744aa..dbb927dec8 100755
--- a/t/t5515-fetch-merge-logic.sh
+++ b/t/t5515-fetch-merge-logic.sh
@@ -129,11 +129,10 @@ do
'' | '#'*) continue ;;
esac
test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'`
- cnt=`expr $test_count + 1`
- pfx=`printf "%04d" $cnt`
- expect_f="../../t5515/fetch.$test"
+ pfx=`printf "%04d" $test_count`
+ expect_f="$TEST_DIRECTORY/t5515/fetch.$test"
actual_f="$pfx-fetch.$test"
- expect_r="../../t5515/refs.$test"
+ expect_r="$TEST_DIRECTORY/t5515/refs.$test"
actual_r="$pfx-refs.$test"
test_expect_success "$cmd" '
@@ -142,16 +141,19 @@ do
set x $cmd; shift
git symbolic-ref HEAD refs/heads/$1 ; shift
rm -f .git/FETCH_HEAD
- rm -f .git/refs/heads/*
- rm -f .git/refs/remotes/rem/*
- rm -f .git/refs/tags/*
+ git for-each-ref \
+ refs/heads refs/remotes/rem refs/tags |
+ while read val type refname
+ do
+ git update-ref -d "$refname" "$val"
+ done
git fetch "$@" >/dev/null
cat .git/FETCH_HEAD
} >"$actual_f" &&
git show-ref >"$actual_r" &&
if test -f "$expect_f"
then
- git diff -u "$expect_f" "$actual_f" &&
+ test_cmp "$expect_f" "$actual_f" &&
rm -f "$actual_f"
else
# this is to help developing new tests.
@@ -160,7 +162,7 @@ do
fi &&
if test -f "$expect_r"
then
- git diff -u "$expect_r" "$actual_r" &&
+ test_cmp "$expect_r" "$actual_r" &&
rm -f "$actual_r"
else
# this is to help developing new tests.
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 0a757d5b9f..6889a53cf9 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -39,6 +39,11 @@ mk_test () {
)
}
+mk_child() {
+ rm -rf "$1" &&
+ git clone testrepo "$1"
+}
+
check_push_result () {
(
cd testrepo &&
@@ -105,7 +110,7 @@ test_expect_success 'fetch with insteadOf' '
(
TRASH=$(pwd)/ &&
cd testrepo &&
- git config url.$TRASH.insteadOf trash/
+ git config "url.$TRASH.insteadOf" trash/ &&
git config remote.up.url trash/. &&
git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&
git fetch up &&
@@ -117,6 +122,23 @@ test_expect_success 'fetch with insteadOf' '
)
'
+test_expect_success 'fetch with pushInsteadOf (should not rewrite)' '
+ mk_empty &&
+ (
+ TRASH=$(pwd)/ &&
+ cd testrepo &&
+ git config "url.trash/.pushInsteadOf" "$TRASH" &&
+ git config remote.up.url "$TRASH." &&
+ git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&
+ git fetch up &&
+
+ r=$(git show-ref -s --verify refs/remotes/origin/master) &&
+ test "z$r" = "z$the_commit" &&
+
+ test 1 = $(git for-each-ref refs/remotes/origin | wc -l)
+ )
+'
+
test_expect_success 'push without wildcard' '
mk_empty &&
@@ -145,8 +167,8 @@ test_expect_success 'push with wildcard' '
test_expect_success 'push with insteadOf' '
mk_empty &&
- TRASH=$(pwd)/ &&
- git config url.$TRASH.insteadOf trash/ &&
+ TRASH="$(pwd)/" &&
+ git config "url.$TRASH.insteadOf" trash/ &&
git push trash/testrepo refs/heads/master:refs/remotes/origin/master &&
(
cd testrepo &&
@@ -157,6 +179,36 @@ test_expect_success 'push with insteadOf' '
)
'
+test_expect_success 'push with pushInsteadOf' '
+ mk_empty &&
+ TRASH="$(pwd)/" &&
+ git config "url.$TRASH.pushInsteadOf" trash/ &&
+ git push trash/testrepo refs/heads/master:refs/remotes/origin/master &&
+ (
+ cd testrepo &&
+ r=$(git show-ref -s --verify refs/remotes/origin/master) &&
+ test "z$r" = "z$the_commit" &&
+
+ test 1 = $(git for-each-ref refs/remotes/origin | wc -l)
+ )
+'
+
+test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf should not rewrite)' '
+ mk_empty &&
+ TRASH="$(pwd)/" &&
+ git config "url.trash2/.pushInsteadOf" trash/ &&
+ git config remote.r.url trash/wrong &&
+ git config remote.r.pushurl "$TRASH/testrepo" &&
+ git push r refs/heads/master:refs/remotes/origin/master &&
+ (
+ cd testrepo &&
+ r=$(git show-ref -s --verify refs/remotes/origin/master) &&
+ test "z$r" = "z$the_commit" &&
+
+ test 1 = $(git for-each-ref refs/remotes/origin | wc -l)
+ )
+'
+
test_expect_success 'push with matching heads' '
mk_test heads/master &&
@@ -165,6 +217,47 @@ test_expect_success 'push with matching heads' '
'
+test_expect_success 'push with matching heads on the command line' '
+
+ mk_test heads/master &&
+ git push testrepo : &&
+ check_push_result $the_commit heads/master
+
+'
+
+test_expect_success 'failed (non-fast-forward) push with matching heads' '
+
+ mk_test heads/master &&
+ git push testrepo : &&
+ git commit --amend -massaged &&
+ test_must_fail git push testrepo &&
+ check_push_result $the_commit heads/master &&
+ git reset --hard $the_commit
+
+'
+
+test_expect_success 'push --force with matching heads' '
+
+ mk_test heads/master &&
+ git push testrepo : &&
+ git commit --amend -massaged &&
+ git push --force testrepo &&
+ ! check_push_result $the_commit heads/master &&
+ git reset --hard $the_commit
+
+'
+
+test_expect_success 'push with matching heads and forced update' '
+
+ mk_test heads/master &&
+ git push testrepo : &&
+ git commit --amend -massaged &&
+ git push testrepo +: &&
+ ! check_push_result $the_commit heads/master &&
+ git reset --hard $the_commit
+
+'
+
test_expect_success 'push with no ambiguity (1)' '
mk_test heads/master &&
@@ -333,7 +426,7 @@ test_expect_success 'push with +HEAD' '
# Without force rewinding should fail
git reset --hard HEAD^ &&
- ! git push testrepo HEAD &&
+ test_must_fail git push testrepo HEAD &&
check_push_result $the_commit heads/local &&
# With force rewinding should succeed
@@ -373,6 +466,19 @@ test_expect_success 'push with config remote.*.push = HEAD' '
git config --remove-section remote.there
git config --remove-section branch.master
+test_expect_success 'push with config remote.*.pushurl' '
+
+ mk_test heads/master &&
+ git checkout master &&
+ git config remote.there.url test2repo &&
+ git config remote.there.pushurl testrepo &&
+ git push there &&
+ check_push_result $the_commit heads/master
+'
+
+# clean up the cruft left with the previous one
+git config --remove-section remote.there
+
test_expect_success 'push with dry-run' '
mk_test heads/master &&
@@ -384,30 +490,48 @@ test_expect_success 'push with dry-run' '
test_expect_success 'push updates local refs' '
- rm -rf parent child &&
- mkdir parent &&
- (cd parent && git init &&
- echo one >foo && git add foo && git commit -m one) &&
- git clone parent child &&
+ mk_test heads/master &&
+ mk_child child &&
(cd child &&
- echo two >foo && git commit -a -m two &&
+ git pull .. master &&
+ git push &&
+ test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
+
+'
+
+test_expect_success 'push updates up-to-date local refs' '
+
+ mk_test heads/master &&
+ mk_child child1 &&
+ mk_child child2 &&
+ (cd child1 && git pull .. master && git push) &&
+ (cd child2 &&
+ git pull ../child1 master &&
git push &&
test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
'
+test_expect_success 'push preserves up-to-date packed refs' '
+
+ mk_test heads/master &&
+ mk_child child &&
+ (cd child &&
+ git push &&
+ ! test -f .git/refs/remotes/origin/master)
+
+'
+
test_expect_success 'push does not update local refs on failure' '
- rm -rf parent child &&
- mkdir parent &&
- (cd parent && git init &&
- echo one >foo && git add foo && git commit -m one &&
- echo exit 1 >.git/hooks/pre-receive &&
- chmod +x .git/hooks/pre-receive) &&
- git clone parent child &&
+ mk_test heads/master &&
+ mk_child child &&
+ mkdir testrepo/.git/hooks &&
+ echo exit 1 >testrepo/.git/hooks/pre-receive &&
+ chmod +x testrepo/.git/hooks/pre-receive &&
(cd child &&
- echo two >foo && git commit -a -m two &&
- ! git push &&
+ git pull .. master
+ test_must_fail git push &&
test $(git rev-parse master) != \
$(git rev-parse remotes/origin/master))
@@ -415,11 +539,98 @@ test_expect_success 'push does not update local refs on failure' '
test_expect_success 'allow deleting an invalid remote ref' '
- pwd &&
+ mk_test heads/master &&
rm -f testrepo/.git/objects/??/* &&
git push testrepo :refs/heads/master &&
- (cd testrepo && ! git rev-parse --verify refs/heads/master)
+ (cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)
+
+'
+
+test_expect_success 'warn on push to HEAD of non-bare repository' '
+ mk_test heads/master
+ (cd testrepo &&
+ git checkout master &&
+ git config receive.denyCurrentBranch warn) &&
+ git push testrepo master 2>stderr &&
+ grep "warning: updating the current branch" stderr
+'
+test_expect_success 'deny push to HEAD of non-bare repository' '
+ mk_test heads/master
+ (cd testrepo &&
+ git checkout master &&
+ git config receive.denyCurrentBranch true) &&
+ test_must_fail git push testrepo master
+'
+
+test_expect_success 'allow push to HEAD of bare repository (bare)' '
+ mk_test heads/master
+ (cd testrepo &&
+ git checkout master &&
+ git config receive.denyCurrentBranch true &&
+ git config core.bare true) &&
+ git push testrepo master 2>stderr &&
+ ! grep "warning: updating the current branch" stderr
+'
+
+test_expect_success 'allow push to HEAD of non-bare repository (config)' '
+ mk_test heads/master
+ (cd testrepo &&
+ git checkout master &&
+ git config receive.denyCurrentBranch false
+ ) &&
+ git push testrepo master 2>stderr &&
+ ! grep "warning: updating the current branch" stderr
+'
+
+test_expect_success 'fetch with branches' '
+ mk_empty &&
+ git branch second $the_first_commit &&
+ git checkout second &&
+ echo ".." > testrepo/.git/branches/branch1 &&
+ (cd testrepo &&
+ git fetch branch1 &&
+ r=$(git show-ref -s --verify refs/heads/branch1) &&
+ test "z$r" = "z$the_commit" &&
+ test 1 = $(git for-each-ref refs/heads | wc -l)
+ ) &&
+ git checkout master
+'
+
+test_expect_success 'fetch with branches containing #' '
+ mk_empty &&
+ echo "..#second" > testrepo/.git/branches/branch2 &&
+ (cd testrepo &&
+ git fetch branch2 &&
+ r=$(git show-ref -s --verify refs/heads/branch2) &&
+ test "z$r" = "z$the_first_commit" &&
+ test 1 = $(git for-each-ref refs/heads | wc -l)
+ ) &&
+ git checkout master
+'
+
+test_expect_success 'push with branches' '
+ mk_empty &&
+ git checkout second &&
+ echo "testrepo" > .git/branches/branch1 &&
+ git push branch1 &&
+ (cd testrepo &&
+ r=$(git show-ref -s --verify refs/heads/master) &&
+ test "z$r" = "z$the_first_commit" &&
+ test 1 = $(git for-each-ref refs/heads | wc -l)
+ )
+'
+
+test_expect_success 'push with branches containing #' '
+ mk_empty &&
+ echo "testrepo#branch3" > .git/branches/branch2 &&
+ git push branch2 &&
+ (cd testrepo &&
+ r=$(git show-ref -s --verify refs/heads/branch3) &&
+ test "z$r" = "z$the_first_commit" &&
+ test 1 = $(git for-each-ref refs/heads | wc -l)
+ ) &&
+ git checkout master
'
test_done
diff --git a/t/t5518-fetch-exit-status.sh b/t/t5518-fetch-exit-status.sh
new file mode 100755
index 0000000000..c2060bb870
--- /dev/null
+++ b/t/t5518-fetch-exit-status.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Dmitry V. Levin
+#
+
+test_description='fetch exit status test'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+ >file &&
+ git add file &&
+ git commit -m initial &&
+
+ git checkout -b side &&
+ echo side >file &&
+ git commit -a -m side &&
+
+ git checkout master &&
+ echo next >file &&
+ git commit -a -m next
+'
+
+test_expect_success 'non-fast-forward fetch' '
+
+ test_must_fail git fetch . master:side
+
+'
+
+test_expect_success 'forced update' '
+
+ git fetch . +master:side
+
+'
+
+test_done
diff --git a/t/t5519-push-alternates.sh b/t/t5519-push-alternates.sh
new file mode 100755
index 0000000000..96be5236a2
--- /dev/null
+++ b/t/t5519-push-alternates.sh
@@ -0,0 +1,143 @@
+#!/bin/sh
+
+test_description='push to a repository that borrows from elsewhere'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ mkdir alice-pub &&
+ (
+ cd alice-pub &&
+ GIT_DIR=. git init
+ ) &&
+ mkdir alice-work &&
+ (
+ cd alice-work &&
+ git init &&
+ >file &&
+ git add . &&
+ git commit -m initial &&
+ git push ../alice-pub master
+ ) &&
+
+ # Project Bob is a fork of project Alice
+ mkdir bob-pub &&
+ (
+ cd bob-pub &&
+ GIT_DIR=. git init &&
+ mkdir -p objects/info &&
+ echo ../../alice-pub/objects >objects/info/alternates
+ ) &&
+ git clone alice-pub bob-work &&
+ (
+ cd bob-work &&
+ git push ../bob-pub master
+ )
+'
+
+test_expect_success 'alice works and pushes' '
+ (
+ cd alice-work &&
+ echo more >file &&
+ git commit -a -m second &&
+ git push ../alice-pub
+ )
+'
+
+test_expect_success 'bob fetches from alice, works and pushes' '
+ (
+ # Bob acquires what Alice did in his work tree first.
+ # Even though these objects are not directly in
+ # the public repository of Bob, this push does not
+ # need to send the commit Bob received from Alice
+ # to his public repository, as all the object Alice
+ # has at her public repository are available to it
+ # via its alternates.
+ cd bob-work &&
+ git pull ../alice-pub master &&
+ echo more bob >file &&
+ git commit -a -m third &&
+ git push ../bob-pub
+ ) &&
+
+ # Check that the second commit by Alice is not sent
+ # to ../bob-pub
+ (
+ cd bob-pub &&
+ second=$(git rev-parse HEAD^) &&
+ rm -f objects/info/alternates &&
+ test_must_fail git cat-file -t $second &&
+ echo ../../alice-pub/objects >objects/info/alternates
+ )
+'
+
+test_expect_success 'clean-up in case the previous failed' '
+ (
+ cd bob-pub &&
+ echo ../../alice-pub/objects >objects/info/alternates
+ )
+'
+
+test_expect_success 'alice works and pushes again' '
+ (
+ # Alice does not care what Bob does. She does not
+ # even have to be aware of his existence. She just
+ # keeps working and pushing
+ cd alice-work &&
+ echo more alice >file &&
+ git commit -a -m fourth &&
+ git push ../alice-pub
+ )
+'
+
+test_expect_success 'bob works and pushes' '
+ (
+ # This time Bob does not pull from Alice, and
+ # the master branch at her public repository points
+ # at a commit Bob does not know about. This should
+ # not prevent the push by Bob from succeeding.
+ cd bob-work &&
+ echo yet more bob >file &&
+ git commit -a -m fifth &&
+ git push ../bob-pub
+ )
+'
+
+test_expect_success 'alice works and pushes yet again' '
+ (
+ # Alice does not care what Bob does. She does not
+ # even have to be aware of his existence. She just
+ # keeps working and pushing
+ cd alice-work &&
+ echo more and more alice >file &&
+ git commit -a -m sixth.1 &&
+ echo more and more alice >>file &&
+ git commit -a -m sixth.2 &&
+ echo more and more alice >>file &&
+ git commit -a -m sixth.3 &&
+ git push ../alice-pub
+ )
+'
+
+test_expect_success 'bob works and pushes again' '
+ (
+ cd alice-pub &&
+ git cat-file commit master >../bob-work/commit
+ )
+ (
+ # This time Bob does not pull from Alice, and
+ # the master branch at her public repository points
+ # at a commit Bob does not fully know about, but
+ # he happens to have the commit object (but not the
+ # necessary tree) in his repository from Alice.
+ # This should not prevent the push by Bob from
+ # succeeding.
+ cd bob-work &&
+ git hash-object -t commit -w commit &&
+ echo even more bob >file &&
+ git commit -a -m seventh &&
+ git push ../bob-pub
+ )
+'
+
+test_done
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 9484129ca5..dd2ee842e0 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -29,6 +29,18 @@ test_expect_success 'checking the results' '
diff file cloned/file
'
+test_expect_success 'pulling into void using master:master' '
+ mkdir cloned-uho &&
+ (
+ cd cloned-uho &&
+ git init &&
+ git pull .. master:master
+ ) &&
+ test -f file &&
+ test -f cloned-uho/file &&
+ test_cmp file cloned-uho/file
+'
+
test_expect_success 'test . as a remote' '
git branch copy master &&
@@ -80,16 +92,72 @@ test_expect_success '--rebase with rebased upstream' '
git remote add -f me . &&
git checkout copy &&
+ git tag copy-orig &&
git reset --hard HEAD^ &&
echo conflicting modification > file &&
git commit -m conflict file &&
git checkout to-rebase &&
echo file > file2 &&
git commit -m to-rebase file2 &&
+ git tag to-rebase-orig &&
git pull --rebase me copy &&
test "conflicting modification" = "$(cat file)" &&
test file = $(cat file2)
'
+test_expect_success '--rebase with rebased default upstream' '
+
+ git update-ref refs/remotes/me/copy copy-orig &&
+ git checkout --track -b to-rebase2 me/copy &&
+ git reset --hard to-rebase-orig &&
+ git pull --rebase &&
+ test "conflicting modification" = "$(cat file)" &&
+ test file = $(cat file2)
+
+'
+
+test_expect_success 'rebased upstream + fetch + pull --rebase' '
+
+ git update-ref refs/remotes/me/copy copy-orig &&
+ git reset --hard to-rebase-orig &&
+ git checkout --track -b to-rebase3 me/copy &&
+ git reset --hard to-rebase-orig &&
+ git fetch &&
+ git pull --rebase &&
+ test "conflicting modification" = "$(cat file)" &&
+ test file = "$(cat file2)"
+
+'
+
+test_expect_success 'pull --rebase dies early with dirty working directory' '
+
+ git checkout to-rebase &&
+ git update-ref refs/remotes/me/copy copy^ &&
+ COPY=$(git rev-parse --verify me/copy) &&
+ git rebase --onto $COPY copy &&
+ git config branch.to-rebase.remote me &&
+ git config branch.to-rebase.merge refs/heads/copy &&
+ git config branch.to-rebase.rebase true &&
+ echo dirty >> file &&
+ git add file &&
+ test_must_fail git pull &&
+ test $COPY = $(git rev-parse --verify me/copy) &&
+ git checkout HEAD -- file &&
+ git pull &&
+ test $COPY != $(git rev-parse --verify me/copy)
+
+'
+
+test_expect_success 'pull --rebase works on branch yet to be born' '
+ git rev-parse master >expect &&
+ mkdir empty_repo &&
+ (cd empty_repo &&
+ git init &&
+ git pull --rebase .. master &&
+ git rev-parse HEAD >../actual
+ ) &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh
new file mode 100755
index 0000000000..83e2e8ab80
--- /dev/null
+++ b/t/t5521-pull-options.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='pull options'
+
+. ./test-lib.sh
+
+D=`pwd`
+
+test_expect_success 'setup' '
+ mkdir parent &&
+ (cd parent && git init &&
+ echo one >file && git add file &&
+ git commit -m one)
+'
+
+cd "$D"
+
+test_expect_success 'git pull -q' '
+ mkdir clonedq &&
+ cd clonedq &&
+ git pull -q "$D/parent" >out 2>err &&
+ test ! -s out
+'
+
+cd "$D"
+
+test_expect_success 'git pull' '
+ mkdir cloned &&
+ cd cloned &&
+ git pull "$D/parent" >out 2>err &&
+ test -s out
+'
+cd "$D"
+
+test_expect_success 'git pull -v' '
+ mkdir clonedv &&
+ cd clonedv &&
+ git pull -v "$D/parent" >out 2>err &&
+ test -s out
+'
+
+cd "$D"
+
+test_expect_success 'git pull -v -q' '
+ mkdir clonedvq &&
+ cd clonedvq &&
+ git pull -v -q "$D/parent" >out 2>err &&
+ test ! -s out
+'
+
+cd "$D"
+
+test_expect_success 'git pull -q -v' '
+ mkdir clonedqv &&
+ cd clonedqv &&
+ git pull -q -v "$D/parent" >out 2>err &&
+ test -s out
+'
+
+test_done
diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh
new file mode 100755
index 0000000000..86bbd7d024
--- /dev/null
+++ b/t/t5522-pull-symlink.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+test_description='pulling from symlinked subdir'
+
+. ./test-lib.sh
+
+if ! test_have_prereq SYMLINKS
+then
+ say 'Symbolic links not supported, skipping tests.'
+ test_done
+fi
+
+# The scenario we are building:
+#
+# trash\ directory/
+# clone-repo/
+# subdir/
+# bar
+# subdir-link -> clone-repo/subdir/
+#
+# The working directory is subdir-link.
+
+mkdir subdir
+echo file >subdir/file
+git add subdir/file
+git commit -q -m file
+git clone -q . clone-repo
+ln -s clone-repo/subdir/ subdir-link
+
+
+# Demonstrate that things work if we just avoid the symlink
+#
+test_expect_success 'pulling from real subdir' '
+ (
+ echo real >subdir/file &&
+ git commit -m real subdir/file &&
+ cd clone-repo/subdir/ &&
+ git pull &&
+ test real = $(cat file)
+ )
+'
+
+# From subdir-link, pulling should work as it does from
+# clone-repo/subdir/.
+#
+# Instead, the error pull gave was:
+#
+# fatal: 'origin': unable to chdir or not a git archive
+# fatal: The remote end hung up unexpectedly
+#
+# because git would find the .git/config for the "trash directory"
+# repo, not for the clone-repo repo. The "trash directory" repo
+# had no entry for origin. Git found the wrong .git because
+# git rev-parse --show-cdup printed a path relative to
+# clone-repo/subdir/, not subdir-link/. Git rev-parse --show-cdup
+# used the correct .git, but when the git pull shell script did
+# "cd `git rev-parse --show-cdup`", it ended up in the wrong
+# directory. A POSIX shell's "cd" works a little differently
+# than chdir() in C; "cd -P" is much closer to chdir().
+#
+test_expect_success 'pulling from symlinked subdir' '
+ (
+ echo link >subdir/file &&
+ git commit -m link subdir/file &&
+ cd subdir-link/ &&
+ git pull &&
+ test link = $(cat file)
+ )
+'
+
+# Prove that the remote end really is a repo, and other commands
+# work fine in this context. It's just that "git pull" breaks.
+#
+test_expect_success 'pushing from symlinked subdir' '
+ (
+ cd subdir-link/ &&
+ echo push >file &&
+ git commit -m push ./file &&
+ git push
+ ) &&
+ test push = $(git show HEAD:subdir/file)
+'
+
+test_done
diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh
index 8b05091069..a696b8791b 100755
--- a/t/t5530-upload-pack-error.sh
+++ b/t/t5530-upload-pack-error.sh
@@ -27,14 +27,15 @@ test_expect_success 'setup and corrupt repository' '
'
test_expect_success 'fsck fails' '
- ! git fsck
+ test_must_fail git fsck
'
-test_expect_success 'upload-pack fails due to error in pack-objects' '
+test_expect_success 'upload-pack fails due to error in pack-objects packing' '
! echo "0032want $(git rev-parse HEAD)
00000009done
-0000" | git-upload-pack . > /dev/null 2> output.err &&
+0000" | git upload-pack . > /dev/null 2> output.err &&
+ grep "unable to read" output.err &&
grep "pack-objects died" output.err
'
@@ -46,14 +47,26 @@ test_expect_success 'corrupt repo differently' '
'
test_expect_success 'fsck fails' '
- ! git fsck
+ test_must_fail git fsck
'
test_expect_success 'upload-pack fails due to error in rev-list' '
! echo "0032want $(git rev-parse HEAD)
+0034shallow $(git rev-parse HEAD^)00000009done
+0000" | git upload-pack . > /dev/null 2> output.err &&
+ # pack-objects survived
+ grep "Total.*, reused" output.err &&
+ # but there was an error, which must have been in rev-list
+ grep "bad tree object" output.err
+'
+
+test_expect_success 'upload-pack fails due to error in pack-objects enumeration' '
+
+ ! echo "0032want $(git rev-parse HEAD)
00000009done
-0000" | git-upload-pack . > /dev/null 2> output.err &&
- grep "waitpid (async) failed" output.err
+0000" | git upload-pack . > /dev/null 2> output.err &&
+ grep "bad tree object" output.err &&
+ grep "pack-objects died" output.err
'
test_expect_success 'create empty repository' '
@@ -66,7 +79,7 @@ test_expect_success 'create empty repository' '
test_expect_success 'fetch fails' '
- ! git fetch .. master
+ test_must_fail git fetch .. master
'
diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh
new file mode 100755
index 0000000000..65d8d474bc
--- /dev/null
+++ b/t/t5531-deep-submodule-push.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+test_description='unpack-objects'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ mkdir pub.git &&
+ GIT_DIR=pub.git git init --bare
+ GIT_DIR=pub.git git config receive.fsckobjects true &&
+ mkdir work &&
+ (
+ cd work &&
+ git init &&
+ mkdir -p gar/bage &&
+ (
+ cd gar/bage &&
+ git init &&
+ >junk &&
+ git add junk &&
+ git commit -m "Initial junk"
+ ) &&
+ git add gar/bage &&
+ git commit -m "Initial superproject"
+ )
+'
+
+test_expect_success push '
+ (
+ cd work &&
+ git push ../pub.git master
+ )
+'
+
+test_done
diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh
index 7372439164..bb18f8bfc4 100755
--- a/t/t5540-http-push.sh
+++ b/t/t5540-http-push.sh
@@ -3,24 +3,24 @@
# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
#
-test_description='test http-push
+test_description='test WebDAV http-push
This test runs various sanity checks on http-push.'
. ./test-lib.sh
-ROOT_PATH="$PWD"
-LIB_HTTPD_DAV=t
-
-. ../lib-httpd.sh
-
-if ! start_httpd >&3 2>&4
+if git http-push > /dev/null 2>&1 || [ $? -eq 128 ]
then
- say "skipping test, web server setup failed"
+ say "skipping test, USE_CURL_MULTI is not defined"
test_done
- exit
fi
+LIB_HTTPD_DAV=t
+LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5540'}
+. "$TEST_DIRECTORY"/lib-httpd.sh
+ROOT_PATH="$PWD"
+start_httpd
+
test_expect_success 'setup remote repository' '
cd "$ROOT_PATH" &&
mkdir test_repo &&
@@ -34,25 +34,79 @@ test_expect_success 'setup remote repository' '
git clone --bare test_repo test_repo.git &&
cd test_repo.git &&
git --bare update-server-info &&
- chmod +x hooks/post-update &&
+ mv hooks/post-update.sample hooks/post-update &&
+ ORIG_HEAD=$(git rev-parse --verify HEAD) &&
cd - &&
- mv test_repo.git $HTTPD_DOCUMENT_ROOT_PATH
+ mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
'
-
+
test_expect_success 'clone remote repository' '
cd "$ROOT_PATH" &&
- git clone $HTTPD_URL/test_repo.git test_repo_clone
+ git clone $HTTPD_URL/dumb/test_repo.git test_repo_clone
'
-test_expect_success 'push to remote repository' '
+test_expect_success 'push to remote repository with packed refs' '
cd "$ROOT_PATH"/test_repo_clone &&
: >path2 &&
git add path2 &&
test_tick &&
git commit -m path2 &&
+ HEAD=$(git rev-parse --verify HEAD) &&
+ git push &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+ test $HEAD = $(git rev-parse --verify HEAD))
+'
+
+test_expect_success 'push already up-to-date' '
git push
'
+test_expect_success 'push to remote repository with unpacked refs' '
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+ rm packed-refs &&
+ git update-ref refs/heads/master $ORIG_HEAD &&
+ git --bare update-server-info) &&
+ git push &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+ test $HEAD = $(git rev-parse --verify HEAD))
+'
+
+test_expect_success 'http-push fetches unpacked objects' '
+ cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
+ "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_unpacked.git &&
+
+ git clone $HTTPD_URL/dumb/test_repo_unpacked.git \
+ "$ROOT_PATH"/fetch_unpacked &&
+
+ # By reset, we force git to retrieve the object
+ (cd "$ROOT_PATH"/fetch_unpacked &&
+ git reset --hard HEAD^ &&
+ git remote rm origin &&
+ git reflog expire --expire=0 --all &&
+ git prune &&
+ git push -f -v $HTTPD_URL/dumb/test_repo_unpacked.git master)
+'
+
+test_expect_success 'http-push fetches packed objects' '
+ cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
+ "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git &&
+
+ git clone $HTTPD_URL/dumb/test_repo_packed.git \
+ "$ROOT_PATH"/test_repo_clone_packed &&
+
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_packed.git &&
+ git --bare repack &&
+ git --bare prune-packed) &&
+
+ # By reset, we force git to retrieve the packed object
+ (cd "$ROOT_PATH"/test_repo_clone_packed &&
+ git reset --hard HEAD^ &&
+ git remote rm origin &&
+ git reflog expire --expire=0 --all &&
+ git prune &&
+ git push -f -v $HTTPD_URL/dumb/test_repo_packed.git master)
+'
+
test_expect_success 'create and delete remote branch' '
cd "$ROOT_PATH"/test_repo_clone &&
git checkout -b dev &&
@@ -61,11 +115,26 @@ test_expect_success 'create and delete remote branch' '
test_tick &&
git commit -m dev &&
git push origin dev &&
- git fetch &&
git push origin :dev &&
- git branch -d -r origin/dev &&
- git fetch &&
- ! git show-ref --verify refs/remotes/origin/dev
+ test_must_fail git show-ref --verify refs/remotes/origin/dev
+'
+
+test_expect_success 'MKCOL sends directory names with trailing slashes' '
+
+ ! grep "\"MKCOL.*[^/] HTTP/[^ ]*\"" < "$HTTPD_ROOT_PATH"/access.log
+
+'
+
+x1="[0-9a-f]"
+x2="$x1$x1"
+x5="$x1$x1$x1$x1$x1"
+x38="$x5$x5$x5$x5$x5$x5$x5$x1$x1$x1"
+x40="$x38$x2"
+
+test_expect_success 'PUT and MOVE sends object to URLs with SHA-1 hash suffix' '
+ sed -e "s/PUT /OP /" -e "s/MOVE /OP /" "$HTTPD_ROOT_PATH"/access.log |
+ grep -e "\"OP .*/objects/$x2/${x38}_$x40 HTTP/[.0-9]*\" 20[0-9] "
+
'
stop_httpd
diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh
new file mode 100755
index 0000000000..2a58d0cc9c
--- /dev/null
+++ b/t/t5541-http-push.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
+#
+
+test_description='test smart pushing over http via http-backend'
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+ say 'skipping test, git built without http support'
+ test_done
+fi
+
+ROOT_PATH="$PWD"
+LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5541'}
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+test_expect_success 'setup remote repository' '
+ cd "$ROOT_PATH" &&
+ mkdir test_repo &&
+ cd test_repo &&
+ git init &&
+ : >path1 &&
+ git add path1 &&
+ test_tick &&
+ git commit -m initial &&
+ cd - &&
+ git clone --bare test_repo test_repo.git &&
+ cd test_repo.git &&
+ git config http.receivepack true &&
+ ORIG_HEAD=$(git rev-parse --verify HEAD) &&
+ cd - &&
+ mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
+'
+
+test_expect_success 'clone remote repository' '
+ cd "$ROOT_PATH" &&
+ git clone $HTTPD_URL/smart/test_repo.git test_repo_clone
+'
+
+test_expect_success 'push to remote repository' '
+ cd "$ROOT_PATH"/test_repo_clone &&
+ : >path2 &&
+ git add path2 &&
+ test_tick &&
+ git commit -m path2 &&
+ HEAD=$(git rev-parse --verify HEAD) &&
+ git push &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+ test $HEAD = $(git rev-parse --verify HEAD))
+'
+
+test_expect_success 'push already up-to-date' '
+ git push
+'
+
+test_expect_success 'create and delete remote branch' '
+ cd "$ROOT_PATH"/test_repo_clone &&
+ git checkout -b dev &&
+ : >path3 &&
+ git add path3 &&
+ test_tick &&
+ git commit -m dev &&
+ git push origin dev &&
+ git push origin :dev &&
+ test_must_fail git show-ref --verify refs/remotes/origin/dev
+'
+
+cat >exp <<EOF
+GET /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200
+GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
+GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
+GET /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
+EOF
+test_expect_success 'used receive-pack service' '
+ sed -e "
+ s/^.* \"//
+ s/\"//
+ s/ [1-9][0-9]*\$//
+ s/^GET /GET /
+ " >act <"$HTTPD_ROOT_PATH"/access.log &&
+ test_cmp exp act
+'
+
+stop_httpd
+test_done
diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh
new file mode 100755
index 0000000000..8cfce969bc
--- /dev/null
+++ b/t/t5550-http-fetch.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+test_description='test dumb fetching over http via static file'
+. ./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
+LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5550'}
+start_httpd
+
+test_expect_success 'setup repository' '
+ echo content >file &&
+ git add file &&
+ git commit -m one
+'
+
+test_expect_success 'create http-accessible bare repository' '
+ mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git --bare init &&
+ echo "exec git update-server-info" >hooks/post-update &&
+ chmod +x hooks/post-update
+ ) &&
+ git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git push public master:master
+'
+
+test_expect_success 'clone http repository' '
+ git clone $HTTPD_URL/dumb/repo.git clone &&
+ test_cmp file clone/file
+'
+
+test_expect_success 'fetch changes via http' '
+ echo content >>file &&
+ git commit -a -m two &&
+ git push public
+ (cd clone && git pull) &&
+ test_cmp file clone/file
+'
+
+test_expect_success 'http remote detects correct HEAD' '
+ git push public master:other &&
+ (cd clone &&
+ git remote set-head origin -d &&
+ git remote set-head origin -a &&
+ git symbolic-ref refs/remotes/origin/HEAD > output &&
+ echo refs/remotes/origin/master > expect &&
+ test_cmp expect output
+ )
+'
+
+test_expect_success 'fetch packed objects' '
+ cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
+ cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git &&
+ git --bare repack &&
+ git --bare prune-packed &&
+ git clone $HTTPD_URL/dumb/repo_pack.git
+'
+
+test_expect_success 'did not use upload-pack service' '
+ grep '/git-upload-pack' <"$HTTPD_ROOT_PATH"/access.log >act
+ : >exp
+ test_cmp exp act
+'
+
+stop_httpd
+test_done
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh
new file mode 100755
index 0000000000..7faa31a299
--- /dev/null
+++ b/t/t5551-http-fetch.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+
+test_description='test smart fetching over http via http-backend'
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+ say 'skipping test, git built without http support'
+ test_done
+fi
+
+LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5551'}
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+test_expect_success 'setup repository' '
+ echo content >file &&
+ git add file &&
+ git commit -m one
+'
+
+test_expect_success 'create http-accessible bare repository' '
+ mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git --bare init
+ ) &&
+ git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git push public master:master
+'
+
+cat >exp <<EOF
+> GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
+> Accept: */*
+> Pragma: no-cache
+< HTTP/1.1 200 OK
+< Pragma: no-cache
+< Cache-Control: no-cache, max-age=0, must-revalidate
+< Content-Type: application/x-git-upload-pack-advertisement
+> POST /smart/repo.git/git-upload-pack HTTP/1.1
+> Accept-Encoding: deflate, gzip
+> Content-Type: application/x-git-upload-pack-request
+> Accept: application/x-git-upload-pack-result
+> Content-Length: xxx
+< HTTP/1.1 200 OK
+< Pragma: no-cache
+< Cache-Control: no-cache, max-age=0, must-revalidate
+< Content-Type: application/x-git-upload-pack-result
+EOF
+test_expect_success 'clone http repository' '
+ GIT_CURL_VERBOSE=1 git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
+ test_cmp file clone/file &&
+ tr '\''\015'\'' Q <err |
+ sed -e "
+ s/Q\$//
+ /^[*] /d
+ /^$/d
+ /^< $/d
+
+ /^[^><]/{
+ s/^/> /
+ }
+
+ /^> User-Agent: /d
+ /^> Host: /d
+ /^> POST /,$ {
+ /^> Accept: [*]\\/[*]/d
+ }
+ s/^> Content-Length: .*/> Content-Length: xxx/
+ /^> 00..want /d
+ /^> 00.*done/d
+
+ /^< Server: /d
+ /^< Expires: /d
+ /^< Date: /d
+ /^< Content-Length: /d
+ /^< Transfer-Encoding: /d
+ " >act &&
+ test_cmp exp act
+'
+
+test_expect_success 'fetch changes via http' '
+ echo content >>file &&
+ git commit -a -m two &&
+ git push public
+ (cd clone && git pull) &&
+ test_cmp file clone/file
+'
+
+cat >exp <<EOF
+GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/repo.git/git-upload-pack HTTP/1.1 200
+GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/repo.git/git-upload-pack HTTP/1.1 200
+EOF
+test_expect_success 'used upload-pack service' '
+ sed -e "
+ s/^.* \"//
+ s/\"//
+ s/ [1-9][0-9]*\$//
+ s/^GET /GET /
+ " >act <"$HTTPD_ROOT_PATH"/access.log &&
+ test_cmp exp act
+'
+
+stop_httpd
+test_done
diff --git a/t/t5560-http-backend.sh b/t/t5560-http-backend.sh
new file mode 100755
index 0000000000..ed034bc980
--- /dev/null
+++ b/t/t5560-http-backend.sh
@@ -0,0 +1,260 @@
+#!/bin/sh
+
+test_description='test git-http-backend'
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+ say 'skipping test, git built without http support'
+ test_done
+fi
+
+LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5560'}
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+find_file() {
+ cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ find $1 -type f |
+ sed -e 1q
+}
+
+config() {
+ git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" config $1 $2
+}
+
+GET() {
+ curl --include "$HTTPD_URL/smart/repo.git/$1" >out 2>/dev/null &&
+ tr '\015' Q <out |
+ sed '
+ s/Q$//
+ 1q
+ ' >act &&
+ echo "HTTP/1.1 $2" >exp &&
+ test_cmp exp act
+}
+
+POST() {
+ curl --include --data "$2" \
+ --header "Content-Type: application/x-$1-request" \
+ "$HTTPD_URL/smart/repo.git/$1" >out 2>/dev/null &&
+ tr '\015' Q <out |
+ sed '
+ s/Q$//
+ 1q
+ ' >act &&
+ echo "HTTP/1.1 $3" >exp &&
+ test_cmp exp act
+}
+
+log_div() {
+ echo >>"$HTTPD_ROOT_PATH"/access.log
+ echo "### $1" >>"$HTTPD_ROOT_PATH"/access.log
+ echo "###" >>"$HTTPD_ROOT_PATH"/access.log
+}
+
+test_expect_success 'setup repository' '
+ echo content >file &&
+ git add file &&
+ git commit -m one &&
+
+ mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git --bare init &&
+ : >objects/info/alternates &&
+ : >objects/info/http-alternates
+ ) &&
+ git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git push public master:master &&
+
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git repack -a -d
+ ) &&
+
+ echo other >file &&
+ git add file &&
+ git commit -m two &&
+ git push public master:master &&
+
+ LOOSE_URL=$(find_file objects/??) &&
+ PACK_URL=$(find_file objects/pack/*.pack) &&
+ IDX_URL=$(find_file objects/pack/*.idx)
+'
+
+get_static_files() {
+ GET HEAD "$1" &&
+ GET info/refs "$1" &&
+ GET objects/info/packs "$1" &&
+ GET objects/info/alternates "$1" &&
+ GET objects/info/http-alternates "$1" &&
+ GET $LOOSE_URL "$1" &&
+ GET $PACK_URL "$1" &&
+ GET $IDX_URL "$1"
+}
+
+test_expect_success 'direct refs/heads/master not found' '
+ log_div "refs/heads/master"
+ GET refs/heads/master "404 Not Found"
+'
+test_expect_success 'static file is ok' '
+ log_div "getanyfile default"
+ get_static_files "200 OK"
+'
+test_expect_success 'static file if http.getanyfile true is ok' '
+ log_div "getanyfile true"
+ config http.getanyfile true &&
+ get_static_files "200 OK"
+'
+test_expect_success 'static file if http.getanyfile false fails' '
+ log_div "getanyfile false"
+ config http.getanyfile false &&
+ get_static_files "403 Forbidden"
+'
+
+test_expect_success 'http.uploadpack default enabled' '
+ log_div "uploadpack default"
+ GET info/refs?service=git-upload-pack "200 OK" &&
+ POST git-upload-pack 0000 "200 OK"
+'
+test_expect_success 'http.uploadpack true' '
+ log_div "uploadpack true"
+ config http.uploadpack true &&
+ GET info/refs?service=git-upload-pack "200 OK" &&
+ POST git-upload-pack 0000 "200 OK"
+'
+test_expect_success 'http.uploadpack false' '
+ log_div "uploadpack false"
+ config http.uploadpack false &&
+ GET info/refs?service=git-upload-pack "403 Forbidden" &&
+ POST git-upload-pack 0000 "403 Forbidden"
+'
+
+test_expect_success 'http.receivepack default disabled' '
+ log_div "receivepack default"
+ GET info/refs?service=git-receive-pack "403 Forbidden" &&
+ POST git-receive-pack 0000 "403 Forbidden"
+'
+test_expect_success 'http.receivepack true' '
+ log_div "receivepack true"
+ config http.receivepack true &&
+ GET info/refs?service=git-receive-pack "200 OK" &&
+ POST git-receive-pack 0000 "200 OK"
+'
+test_expect_success 'http.receivepack false' '
+ log_div "receivepack false"
+ config http.receivepack false &&
+ GET info/refs?service=git-receive-pack "403 Forbidden" &&
+ POST git-receive-pack 0000 "403 Forbidden"
+'
+
+run_backend() {
+ REQUEST_METHOD=GET \
+ GIT_PROJECT_ROOT="$HTTPD_DOCUMENT_ROOT_PATH" \
+ PATH_INFO="$2" \
+ git http-backend >act.out 2>act.err
+}
+
+path_info() {
+ if test $1 = 0; then
+ run_backend "$2"
+ else
+ test_must_fail run_backend "$2" &&
+ echo "fatal: '$2': aliased" >exp.err &&
+ test_cmp exp.err act.err
+ fi
+}
+
+test_expect_success 'http-backend blocks bad PATH_INFO' '
+ config http.getanyfile true &&
+
+ run_backend 0 /repo.git/HEAD &&
+
+ run_backend 1 /repo.git/../HEAD &&
+ run_backend 1 /../etc/passwd &&
+ run_backend 1 ../etc/passwd &&
+ run_backend 1 /etc//passwd &&
+ run_backend 1 /etc/./passwd &&
+ run_backend 1 /etc/.../passwd &&
+ run_backend 1 //domain/data.txt
+'
+
+cat >exp <<EOF
+
+### refs/heads/master
+###
+GET /smart/repo.git/refs/heads/master HTTP/1.1 404 -
+
+### getanyfile default
+###
+GET /smart/repo.git/HEAD HTTP/1.1 200
+GET /smart/repo.git/info/refs HTTP/1.1 200
+GET /smart/repo.git/objects/info/packs HTTP/1.1 200
+GET /smart/repo.git/objects/info/alternates HTTP/1.1 200 -
+GET /smart/repo.git/objects/info/http-alternates HTTP/1.1 200 -
+GET /smart/repo.git/$LOOSE_URL HTTP/1.1 200
+GET /smart/repo.git/$PACK_URL HTTP/1.1 200
+GET /smart/repo.git/$IDX_URL HTTP/1.1 200
+
+### getanyfile true
+###
+GET /smart/repo.git/HEAD HTTP/1.1 200
+GET /smart/repo.git/info/refs HTTP/1.1 200
+GET /smart/repo.git/objects/info/packs HTTP/1.1 200
+GET /smart/repo.git/objects/info/alternates HTTP/1.1 200 -
+GET /smart/repo.git/objects/info/http-alternates HTTP/1.1 200 -
+GET /smart/repo.git/$LOOSE_URL HTTP/1.1 200
+GET /smart/repo.git/$PACK_URL HTTP/1.1 200
+GET /smart/repo.git/$IDX_URL HTTP/1.1 200
+
+### getanyfile false
+###
+GET /smart/repo.git/HEAD HTTP/1.1 403 -
+GET /smart/repo.git/info/refs HTTP/1.1 403 -
+GET /smart/repo.git/objects/info/packs HTTP/1.1 403 -
+GET /smart/repo.git/objects/info/alternates HTTP/1.1 403 -
+GET /smart/repo.git/objects/info/http-alternates HTTP/1.1 403 -
+GET /smart/repo.git/$LOOSE_URL HTTP/1.1 403 -
+GET /smart/repo.git/$PACK_URL HTTP/1.1 403 -
+GET /smart/repo.git/$IDX_URL HTTP/1.1 403 -
+
+### uploadpack default
+###
+GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/repo.git/git-upload-pack HTTP/1.1 200 -
+
+### uploadpack true
+###
+GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+POST /smart/repo.git/git-upload-pack HTTP/1.1 200 -
+
+### uploadpack false
+###
+GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 403 -
+POST /smart/repo.git/git-upload-pack HTTP/1.1 403 -
+
+### receivepack default
+###
+GET /smart/repo.git/info/refs?service=git-receive-pack HTTP/1.1 403 -
+POST /smart/repo.git/git-receive-pack HTTP/1.1 403 -
+
+### receivepack true
+###
+GET /smart/repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
+POST /smart/repo.git/git-receive-pack HTTP/1.1 200 -
+
+### receivepack false
+###
+GET /smart/repo.git/info/refs?service=git-receive-pack HTTP/1.1 403 -
+POST /smart/repo.git/git-receive-pack HTTP/1.1 403 -
+EOF
+test_expect_success 'server request log matches test results' '
+ sed -e "
+ s/^.* \"//
+ s/\"//
+ s/ [1-9][0-9]*\$//
+ s/^GET /GET /
+ " >act <"$HTTPD_ROOT_PATH"/access.log &&
+ test_cmp exp act
+'
+
+stop_httpd
+test_done
diff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh
index acf34cec8f..ee06d28649 100755
--- a/t/t5600-clone-fail-cleanup.sh
+++ b/t/t5600-clone-fail-cleanup.sh
@@ -3,9 +3,9 @@
# Copyright (C) 2006 Carl D. Worth <cworth@cworth.org>
#
-test_description='test git-clone to cleanup after failure
+test_description='test git clone to cleanup after failure
-This test covers the fact that if git-clone fails, it should remove
+This test covers the fact that if git clone fails, it should remove
the directory it created, to avoid the user having to manually
remove the directory before attempting a clone again.'
@@ -13,7 +13,7 @@ remove the directory before attempting a clone again.'
test_expect_success \
'clone of non-existent source should fail' \
- '! git-clone foo bar'
+ 'test_must_fail git clone foo bar'
test_expect_success \
'failed clone should not leave a directory' \
@@ -25,15 +25,15 @@ test_create_repo foo
# clone doesn't like it if there is no HEAD. Is that a bug?
(cd foo && touch file && git add file && git commit -m 'add file' >/dev/null 2>&1)
-# source repository given to git-clone should be relative to the
+# source repository given to git clone should be relative to the
# current path not to the target dir
test_expect_success \
'clone of non-existent (relative to $PWD) source should fail' \
- '! git-clone ../foo baz'
+ 'test_must_fail git clone ../foo baz'
test_expect_success \
'clone should work now that source exists' \
- 'git-clone foo bar'
+ 'git clone foo bar'
test_expect_success \
'successful clone must leave the directory' \
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index dc9d63dbf9..214756731b 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -17,10 +17,163 @@ test_expect_success setup '
'
-test_expect_success 'clone with excess parameters' '
+test_expect_success 'clone with excess parameters (1)' '
+ rm -fr dst &&
+ test_must_fail git clone -n src dst junk
+
+'
+
+test_expect_success 'clone with excess parameters (2)' '
+
+ rm -fr dst &&
test_must_fail git clone -n "file://$(pwd)/src" dst junk
'
+test_expect_success 'output from clone' '
+ rm -fr dst &&
+ git clone -n "file://$(pwd)/src" dst >output &&
+ test $(grep Initialized output | wc -l) = 1
+'
+
+test_expect_success 'clone does not keep pack' '
+
+ rm -fr dst &&
+ git clone -n "file://$(pwd)/src" dst &&
+ ! test -f dst/file &&
+ ! (echo dst/.git/objects/pack/pack-* | grep "\.keep")
+
+'
+
+test_expect_success 'clone checks out files' '
+
+ rm -fr dst &&
+ git clone src dst &&
+ test -f dst/file
+
+'
+
+test_expect_success 'clone respects GIT_WORK_TREE' '
+
+ GIT_WORK_TREE=worktree git clone src bare &&
+ test -f bare/config &&
+ test -f worktree/file
+
+'
+
+test_expect_success 'clone creates intermediate directories' '
+
+ git clone src long/path/to/dst &&
+ test -f long/path/to/dst/file
+
+'
+
+test_expect_success 'clone creates intermediate directories for bare repo' '
+
+ git clone --bare src long/path/to/bare/dst &&
+ test -f long/path/to/bare/dst/config
+
+'
+
+test_expect_success 'clone --mirror' '
+
+ git clone --mirror src mirror &&
+ test -f mirror/HEAD &&
+ test ! -f mirror/file &&
+ FETCH="$(cd mirror && git config remote.origin.fetch)" &&
+ test "+refs/*:refs/*" = "$FETCH" &&
+ MIRROR="$(cd mirror && git config --bool remote.origin.mirror)" &&
+ test "$MIRROR" = true
+
+'
+
+test_expect_success 'clone --bare names the local repository <name>.git' '
+
+ git clone --bare src &&
+ test -d src.git
+
+'
+
+test_expect_success 'clone --mirror does not repeat tags' '
+
+ (cd src &&
+ git tag some-tag HEAD) &&
+ git clone --mirror src mirror2 &&
+ (cd mirror2 &&
+ git show-ref 2> clone.err > clone.out) &&
+ test_must_fail grep Duplicate mirror2/clone.err &&
+ grep some-tag mirror2/clone.out
+
+'
+
+test_expect_success 'clone to destination with trailing /' '
+
+ git clone src target-1/ &&
+ T=$( cd target-1 && git rev-parse HEAD ) &&
+ S=$( cd src && git rev-parse HEAD ) &&
+ test "$T" = "$S"
+
+'
+
+test_expect_success 'clone to destination with extra trailing /' '
+
+ git clone src target-2/// &&
+ T=$( cd target-2 && git rev-parse HEAD ) &&
+ S=$( cd src && git rev-parse HEAD ) &&
+ test "$T" = "$S"
+
+'
+
+test_expect_success 'clone to an existing empty directory' '
+ mkdir target-3 &&
+ git clone src target-3 &&
+ T=$( cd target-3 && git rev-parse HEAD ) &&
+ S=$( cd src && git rev-parse HEAD ) &&
+ test "$T" = "$S"
+'
+
+test_expect_success 'clone to an existing non-empty directory' '
+ mkdir target-4 &&
+ >target-4/Fakefile &&
+ test_must_fail git clone src target-4
+'
+
+test_expect_success 'clone to an existing path' '
+ >target-5 &&
+ test_must_fail git clone src target-5
+'
+
+test_expect_success 'clone a void' '
+ mkdir src-0 &&
+ (
+ cd src-0 && git init
+ ) &&
+ git clone "file://$(pwd)/src-0" target-6 2>err-6 &&
+ ! grep "fatal:" err-6 &&
+ (
+ cd src-0 && test_commit A
+ ) &&
+ git clone "file://$(pwd)/src-0" target-7 2>err-7 &&
+ ! grep "fatal:" err-7 &&
+ # There is no reason to insist they are bit-for-bit
+ # identical, but this test should suffice for now.
+ test_cmp target-6/.git/config target-7/.git/config
+'
+
+test_expect_success 'clone respects global branch.autosetuprebase' '
+ (
+ HOME=$(pwd) &&
+ export HOME &&
+ test_config="$HOME/.gitconfig" &&
+ unset GIT_CONFIG_NOGLOBAL &&
+ git config -f "$test_config" branch.autosetuprebase remote &&
+ rm -fr dst &&
+ git clone src dst &&
+ cd dst &&
+ actual="z$(git config branch.master.rebase)" &&
+ test ztrue = $actual
+ )
+'
+
test_done
diff --git a/t/t5602-clone-remote-exec.sh b/t/t5602-clone-remote-exec.sh
new file mode 100755
index 0000000000..deffdaee49
--- /dev/null
+++ b/t/t5602-clone-remote-exec.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+test_description=clone
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo "#!/bin/sh" > not_ssh
+ echo "echo \"\$*\" > not_ssh_output" >> not_ssh
+ echo "exit 1" >> not_ssh
+ chmod +x not_ssh
+'
+
+test_expect_success 'clone calls git upload-pack unqualified with no -u option' '
+ 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 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
+'
+
+test_done
diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh
index b6a54867b4..1c10916069 100755
--- a/t/t5700-clone-reference.sh
+++ b/t/t5700-clone-reference.sh
@@ -8,6 +8,8 @@ test_description='test clone --reference'
base_dir=`pwd`
+U=$base_dir/UPLOAD_LOG
+
test_expect_success 'preparing first repository' \
'test_create_repo A && cd A &&
echo first > file1 &&
@@ -50,8 +52,13 @@ diff expected current'
cd "$base_dir"
+rm -f "$U"
+
test_expect_success 'cloning with reference (no -l -s)' \
-'git clone --reference B file://`pwd`/A D'
+'GIT_DEBUG_SEND_PACK=3 git clone --reference B "file://$(pwd)/A" D 3>"$U"'
+
+test_expect_success 'fetched no objects' \
+'! grep "^want" "$U"'
cd "$base_dir"
@@ -113,4 +120,30 @@ diff expected current'
cd "$base_dir"
+test_expect_success 'preparing alternate repository #1' \
+'test_create_repo F && cd F &&
+echo first > file1 &&
+git add file1 &&
+git commit -m initial'
+
+cd "$base_dir"
+
+test_expect_success 'cloning alternate repo #2 and adding changes to repo #1' \
+'git clone F G && cd F &&
+echo second > file2 &&
+git add file2 &&
+git commit -m addition'
+
+cd "$base_dir"
+
+test_expect_success 'cloning alternate repo #1, using #2 as reference' \
+'git clone --reference G F H'
+
+cd "$base_dir"
+
+test_expect_success 'cloning with reference being subset of source (-l -s)' \
+'git clone -l -s --reference A B E'
+
+cd "$base_dir"
+
test_done
diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh
index 8dfaaa456e..19b5c0d552 100755
--- a/t/t5701-clone-local.sh
+++ b/t/t5701-clone-local.sh
@@ -11,8 +11,8 @@ test_expect_success 'preparing origin repository' '
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
- git bundle create b1.bundle --all HEAD &&
- git bundle create b2.bundle --all &&
+ git bundle create b1.bundle --all &&
+ git bundle create b2.bundle master &&
mkdir dir &&
cp b1.bundle dir/b3
cp b1.bundle b4
@@ -116,4 +116,30 @@ test_expect_success 'bundle clone with nonexistent HEAD' '
test ! -e .git/refs/heads/master
'
+test_expect_success 'clone empty repository' '
+ cd "$D" &&
+ mkdir empty &&
+ (cd empty && git init) &&
+ git clone empty empty-clone &&
+ test_tick &&
+ (cd empty-clone
+ echo "content" >> foo &&
+ git add foo &&
+ git commit -m "Initial commit" &&
+ git push origin master &&
+ expected=$(git rev-parse master) &&
+ actual=$(git --git-dir=../empty/.git rev-parse master) &&
+ test $actual = $expected)
+'
+
+test_expect_success 'clone empty repository, and then push should not segfault.' '
+ cd "$D" &&
+ rm -fr empty/ empty-clone/ &&
+ mkdir empty &&
+ (cd empty && git init) &&
+ git clone empty empty-clone &&
+ (cd empty-clone &&
+ test_must_fail git push)
+'
+
test_done
diff --git a/t/t5702-clone-options.sh b/t/t5702-clone-options.sh
index 328e4d9a33..27825f5f31 100755
--- a/t/t5702-clone-options.sh
+++ b/t/t5702-clone-options.sh
@@ -19,4 +19,17 @@ test_expect_success 'clone -o' '
'
+test_expect_success 'redirected clone' '
+
+ git clone "file://$(pwd)/parent" clone-redirected >out 2>err &&
+ test ! -s err
+
+'
+test_expect_success 'redirected clone -v' '
+
+ git clone -v "file://$(pwd)/parent" clone-redirected-v >out 2>err &&
+ test -s err
+
+'
+
test_done
diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh
new file mode 100755
index 0000000000..a8f4419e61
--- /dev/null
+++ b/t/t5704-bundle.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+test_description='some bundle related tests'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+ : > file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ test_tick &&
+ git tag -m tag tag &&
+ : > file2 &&
+ git add file2 &&
+ : > file3 &&
+ test_tick &&
+ git commit -m second &&
+ git add file3 &&
+ test_tick &&
+ git commit -m third
+
+'
+
+test_expect_success 'tags can be excluded by rev-list options' '
+
+ git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 &&
+ git ls-remote bundle > output &&
+ ! grep tag output
+
+'
+
+test_done
diff --git a/t/t5705-clone-2gb.sh b/t/t5705-clone-2gb.sh
new file mode 100755
index 0000000000..9f52154cac
--- /dev/null
+++ b/t/t5705-clone-2gb.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+test_description='Test cloning a repository larger than 2 gigabyte'
+. ./test-lib.sh
+
+test -z "$GIT_TEST_CLONE_2GB" &&
+say "Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t" &&
+test_done &&
+exit
+
+test_expect_success 'setup' '
+
+ git config pack.compression 0 &&
+ git config pack.depth 0 &&
+ blobsize=$((20*1024*1024)) &&
+ blobcount=$((2*1024*1024*1024/$blobsize+1)) &&
+ i=1 &&
+ (while test $i -le $blobcount
+ do
+ printf "Generating blob $i/$blobcount\r" >&2 &&
+ printf "blob\nmark :$i\ndata $blobsize\n" &&
+ #test-genrandom $i $blobsize &&
+ printf "%-${blobsize}s" $i &&
+ echo "M 100644 :$i $i" >> commit
+ i=$(($i+1)) ||
+ echo $? > exit-status
+ done &&
+ echo "commit refs/heads/master" &&
+ echo "author A U Thor <author@email.com> 123456789 +0000" &&
+ echo "committer C O Mitter <committer@email.com> 123456789 +0000" &&
+ echo "data 5" &&
+ echo ">2gb" &&
+ cat commit) |
+ git fast-import &&
+ test ! -f exit-status
+
+'
+
+test_expect_success 'clone' '
+
+ git clone --bare --no-hardlinks . clone
+
+'
+
+test_done
diff --git a/t/t5706-clone-branch.sh b/t/t5706-clone-branch.sh
new file mode 100755
index 0000000000..f3f9a76056
--- /dev/null
+++ b/t/t5706-clone-branch.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+test_description='clone --branch option'
+. ./test-lib.sh
+
+check_HEAD() {
+ echo refs/heads/"$1" >expect &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expect actual
+}
+
+check_file() {
+ echo "$1" >expect &&
+ test_cmp expect file
+}
+
+test_expect_success 'setup' '
+ mkdir parent &&
+ (cd parent && git init &&
+ echo one >file && git add file && git commit -m one &&
+ git checkout -b two &&
+ echo two >file && git add file && git commit -m two &&
+ git checkout master)
+'
+
+test_expect_success 'vanilla clone chooses HEAD' '
+ git clone parent clone &&
+ (cd clone &&
+ check_HEAD master &&
+ check_file one
+ )
+'
+
+test_expect_success 'clone -b chooses specified branch' '
+ git clone -b two parent clone-two &&
+ (cd clone-two &&
+ check_HEAD two &&
+ check_file two
+ )
+'
+
+test_expect_success 'clone -b sets up tracking' '
+ (cd clone-two &&
+ echo origin >expect &&
+ git config branch.two.remote >actual &&
+ echo refs/heads/two >>expect &&
+ git config branch.two.merge >>actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'clone -b does not munge remotes/origin/HEAD' '
+ (cd clone-two &&
+ echo refs/remotes/origin/master >expect &&
+ git symbolic-ref refs/remotes/origin/HEAD >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'clone -b with bogus branch chooses HEAD' '
+ git clone -b bogus parent clone-bogus &&
+ (cd clone-bogus &&
+ check_HEAD master &&
+ check_file one
+ )
+'
+
+test_done
diff --git a/t/t5710-info-alternate.sh b/t/t5710-info-alternate.sh
index 910ccb4fff..ef7127c1b3 100755
--- a/t/t5710-info-alternate.sh
+++ b/t/t5710-info-alternate.sh
@@ -81,9 +81,9 @@ test_valid_repo'
cd "$base_dir"
test_expect_success 'breaking of loops' \
-"echo '$base_dir/B/.git/objects' >> '$base_dir'/A/.git/objects/info/alternates&&
+'echo "$base_dir"/B/.git/objects >> "$base_dir"/A/.git/objects/info/alternates&&
cd C &&
-test_valid_repo"
+test_valid_repo'
cd "$base_dir"
diff --git a/t/t6000lib.sh b/t/t6000lib.sh
index c0baaa5360..f55627b641 100755
--- a/t/t6000lib.sh
+++ b/t/t6000lib.sh
@@ -49,13 +49,15 @@ as_author()
shift 1
_save=$GIT_AUTHOR_EMAIL
- export GIT_AUTHOR_EMAIL="$_author"
+ GIT_AUTHOR_EMAIL="$_author"
+ export GIT_AUTHOR_EMAIL
"$@"
if test -z "$_save"
then
unset GIT_AUTHOR_EMAIL
else
- export GIT_AUTHOR_EMAIL="$_save"
+ GIT_AUTHOR_EMAIL="$_save"
+ export GIT_AUTHOR_EMAIL
fi
}
@@ -69,7 +71,8 @@ on_committer_date()
{
_date=$1
shift 1
- export GIT_COMMITTER_DATE="$_date"
+ GIT_COMMITTER_DATE="$_date"
+ export GIT_COMMITTER_DATE
"$@"
unset GIT_COMMITTER_DATE
}
diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh
index 8f5de097ec..b4e8fbaa5e 100755
--- a/t/t6002-rev-list-bisect.sh
+++ b/t/t6002-rev-list-bisect.sh
@@ -5,7 +5,7 @@
test_description='Tests git rev-list --bisect functionality'
. ./test-lib.sh
-. ../t6000lib.sh # t6xxx specific functions
+. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions
# usage: test_bisection max-diff bisect-option head ^prune...
#
diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh
index 5daa0be8cc..2c73f2da7b 100755
--- a/t/t6003-rev-list-topo-order.sh
+++ b/t/t6003-rev-list-topo-order.sh
@@ -6,7 +6,7 @@
test_description='Tests git rev-list --topo-order functionality'
. ./test-lib.sh
-. ../t6000lib.sh # t6xxx specific functions
+. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions
list_duplicates()
{
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 0dc915ea67..571931588e 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -6,16 +6,16 @@ test_description='git rev-list --pretty=format test'
test_tick
test_expect_success 'setup' '
-touch foo && git add foo && git-commit -m "added foo" &&
- echo changed >foo && git-commit -a -m "changed foo"
+touch foo && git add foo && git commit -m "added foo" &&
+ echo changed >foo && git commit -a -m "changed foo"
'
# usage: test_format name format_string <expected_output
test_format() {
cat >expect.$1
test_expect_success "format $1" "
-git rev-list --pretty=format:$2 master >output.$1 &&
-git diff expect.$1 output.$1
+git rev-list --pretty=format:'$2' master >output.$1 &&
+test_cmp expect.$1 output.$1
"
}
@@ -101,6 +101,13 @@ commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
foobarbazxyzzy
EOF
+test_format advanced-colors '%C(red yellow bold)foo%C(reset)' <<'EOF'
+commit 131a310eb913d107dd3c09a65d1651175898735d
+foo
+commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+foo
+EOF
+
cat >commit-msg <<'EOF'
Test printing of complex bodies
@@ -110,7 +117,7 @@ include an iso8859 character: ¡bueno!
EOF
test_expect_success 'setup complex body' '
git config i18n.commitencoding iso8859-1 &&
- echo change2 >foo && git-commit -a -F commit-msg
+ echo change2 >foo && git commit -a -F commit-msg
'
test_format complex-encoding %e <<'EOF'
@@ -139,6 +146,12 @@ commit 131a310eb913d107dd3c09a65d1651175898735d
commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
EOF
+test_expect_success '%ad respects --date=' '
+ echo 2005-04-07 >expect.ad-short &&
+ git log -1 --date=short --pretty=tformat:%ad >output.ad-short master &&
+ test_cmp expect.ad-short output.ad-short
+'
+
test_expect_success 'empty email' '
test_tick &&
C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) &&
@@ -149,4 +162,44 @@ test_expect_success 'empty email' '
}
'
+test_expect_success 'del LF before empty (1)' '
+ git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD^^ >actual &&
+ test $(wc -l <actual) = 2
+'
+
+test_expect_success 'del LF before empty (2)' '
+ git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD >actual &&
+ test $(wc -l <actual) = 6 &&
+ grep "^$" actual
+'
+
+test_expect_success 'add LF before non-empty (1)' '
+ git show -s --pretty=format:"%s%+b%nThanks%n" HEAD^^ >actual &&
+ test $(wc -l <actual) = 2
+'
+
+test_expect_success 'add LF before non-empty (2)' '
+ git show -s --pretty=format:"%s%+b%nThanks%n" HEAD >actual &&
+ test $(wc -l <actual) = 6 &&
+ grep "^$" actual
+'
+
+test_expect_success '"%h %gD: %gs" is same as git-reflog' '
+ git reflog >expect &&
+ git log -g --format="%h %gD: %gs" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '"%h %gD: %gs" is same as git-reflog (with date)' '
+ git reflog --date=raw >expect &&
+ git log -g --format="%h %gD: %gs" --date=raw >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '%gd shortens ref name' '
+ echo "master@{0}" >expect.gd-short &&
+ git log -g -1 --format=%gd refs/heads/master >actual.gd-short &&
+ test_cmp expect.gd-short actual.gd-short
+'
+
test_done
diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh
index 88e96fb91b..c4af9ca0a7 100755
--- a/t/t6008-rev-list-submodule.sh
+++ b/t/t6008-rev-list-submodule.sh
@@ -23,7 +23,7 @@ test_expect_success 'setup' '
: > super-file &&
git add super-file &&
- git submodule add . sub &&
+ git submodule add "$(pwd)" sub &&
git symbolic-ref HEAD refs/heads/super &&
test_tick &&
git commit -m super-initial &&
diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh
index 96f3d35530..0144d9e858 100755
--- a/t/t6010-merge-base.sh
+++ b/t/t6010-merge-base.sh
@@ -13,10 +13,11 @@ T=$(git write-tree)
M=1130000000
Z=+0000
-export GIT_COMMITTER_EMAIL=git@comm.iter.xz
-export GIT_COMMITTER_NAME='C O Mmiter'
-export GIT_AUTHOR_NAME='A U Thor'
-export GIT_AUTHOR_EMAIL=git@au.thor.xz
+GIT_COMMITTER_EMAIL=git@comm.iter.xz
+GIT_COMMITTER_NAME='C O Mmiter'
+GIT_AUTHOR_NAME='A U Thor'
+GIT_AUTHOR_EMAIL=git@au.thor.xz
+export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
doit() {
OFFSET=$1; shift
@@ -107,4 +108,70 @@ test_expect_success 'compute merge-base (all)' \
'MB=$(git merge-base --all PL PR) &&
expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/C2"'
+# Another set to demonstrate base between one commit and a merge
+# in the documentation.
+#
+# * C (MMC) * B (MMB) * A (MMA)
+# * o * o * o
+# * o * o * o
+# * o * o * o
+# * o | _______/
+# | |/
+# | * 1 (MM1)
+# | _______/
+# |/
+# * root (MMR)
+
+
+test_expect_success 'merge-base for octopus-step (setup)' '
+ test_tick && git commit --allow-empty -m root && git tag MMR &&
+ test_tick && git commit --allow-empty -m 1 && git tag MM1 &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m A && git tag MMA &&
+ git checkout MM1 &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m B && git tag MMB &&
+ git checkout MMR &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m C && git tag MMC
+'
+
+test_expect_success 'merge-base A B C' '
+ MB=$(git merge-base --all MMA MMB MMC) &&
+ MM1=$(git rev-parse --verify MM1) &&
+ test "$MM1" = "$MB"
+'
+
+test_expect_success 'merge-base A B C using show-branch' '
+ MB=$(git show-branch --merge-base MMA MMB MMC) &&
+ MMR=$(git rev-parse --verify MMR) &&
+ test "$MMR" = "$MB"
+'
+
+test_expect_success 'criss-cross merge-base for octopus-step (setup)' '
+ git reset --hard MMR &&
+ test_tick && git commit --allow-empty -m 1 && git tag CC1 &&
+ git reset --hard E &&
+ test_tick && git commit --allow-empty -m 2 && git tag CC2 &&
+ test_tick && git merge -s ours CC1 &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m B && git tag CCB &&
+ git reset --hard CC1 &&
+ test_tick && git merge -s ours CC2 &&
+ test_tick && git commit --allow-empty -m A && git tag CCA
+'
+
+test_expect_success 'merge-base B A^^ A^^2' '
+ MB0=$(git merge-base --all CCB CCA^^ CCA^^2 | sort) &&
+ MB1=$(git rev-parse CC1 CC2 | sort) &&
+ test "$MB0" = "$MB1"
+'
+
test_done
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
new file mode 100755
index 0000000000..e51eb41f4b
--- /dev/null
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='git rev-list should notice bad commits'
+
+. ./test-lib.sh
+
+# Note:
+# - compression level is set to zero to make "corruptions" easier to perform
+# - reflog is disabled to avoid extra references which would twart the test
+
+test_expect_success 'setup' \
+ '
+ git init &&
+ git config core.compression 0 &&
+ git config core.logallrefupdates false &&
+ echo "foo" > foo &&
+ git add foo &&
+ git commit -m "first commit" &&
+ echo "bar" > bar &&
+ git add bar &&
+ git commit -m "second commit" &&
+ echo "baz" > baz &&
+ git add baz &&
+ git commit -m "third commit" &&
+ echo "foo again" >> foo &&
+ git add foo &&
+ git commit -m "fourth commit" &&
+ git repack -a -f -d
+ '
+
+test_expect_success 'verify number of revisions' \
+ '
+ revs=$(git rev-list --all | wc -l) &&
+ test $revs -eq 4 &&
+ first_commit=$(git rev-parse HEAD~3)
+ '
+
+test_expect_success 'corrupt second commit object' \
+ '
+ perl -i.bak -pe "s/second commit/socond commit/" .git/objects/pack/*.pack &&
+ test_must_fail git fsck --full
+ '
+
+test_expect_success 'rev-list should fail' \
+ '
+ test_must_fail git rev-list --all > /dev/null
+ '
+
+test_expect_success 'git repack _MUST_ fail' \
+ '
+ test_must_fail git repack -a -f -d
+ '
+
+test_expect_success 'first commit is still available' \
+ '
+ git log $first_commit
+ '
+
+test_done
+
diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh
new file mode 100755
index 0000000000..510bb9679f
--- /dev/null
+++ b/t/t6012-rev-list-simplify.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+test_description='merge simplification'
+
+. ./test-lib.sh
+
+note () {
+ git tag "$1"
+}
+
+_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
+_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+
+unnote () {
+ git name-rev --tags --stdin | sed -e "s|$_x40 (tags/\([^)]*\)) |\1 |g"
+}
+
+test_expect_success setup '
+ echo "Hi there" >file &&
+ git add file &&
+ test_tick && git commit -m "Initial file" &&
+ note A &&
+
+ git branch other-branch &&
+
+ echo "Hello" >file &&
+ git add file &&
+ test_tick && git commit -m "Modified file" &&
+ note B &&
+
+ git checkout other-branch &&
+
+ echo "Hello" >file &&
+ git add file &&
+ test_tick && git commit -m "Modified the file identically" &&
+ note C &&
+
+ echo "This is a stupid example" >another-file &&
+ git add another-file &&
+ test_tick && git commit -m "Add another file" &&
+ note D &&
+
+ test_tick && git merge -m "merge" master &&
+ note E &&
+
+ echo "Yet another" >elif &&
+ git add elif &&
+ test_tick && git commit -m "Irrelevant change" &&
+ note F &&
+
+ git checkout master &&
+ echo "Yet another" >elif &&
+ git add elif &&
+ test_tick && git commit -m "Another irrelevant change" &&
+ note G &&
+
+ test_tick && git merge -m "merge" other-branch &&
+ note H &&
+
+ echo "Final change" >file &&
+ test_tick && git commit -a -m "Final change" &&
+ note I
+'
+
+FMT='tformat:%P %H | %s'
+
+check_result () {
+ for c in $1
+ do
+ echo "$c"
+ done >expect &&
+ shift &&
+ param="$*" &&
+ test_expect_success "log $param" '
+ git log --pretty="$FMT" --parents $param |
+ unnote >actual &&
+ sed -e "s/^.* \([^ ]*\) .*/\1/" >check <actual &&
+ test_cmp expect check || {
+ cat actual
+ false
+ }
+ '
+}
+
+check_result 'I H G F E D C B A' --full-history
+check_result 'I H E C B A' --full-history -- file
+check_result 'I H E C B A' --full-history --topo-order -- file
+check_result 'I H E C B A' --full-history --date-order -- file
+check_result 'I E C B A' --simplify-merges -- file
+check_result 'I B A' -- file
+check_result 'I B A' --topo-order -- file
+
+test_done
diff --git a/t/t6013-rev-list-reverse-parents.sh b/t/t6013-rev-list-reverse-parents.sh
new file mode 100755
index 0000000000..59fc2f06e0
--- /dev/null
+++ b/t/t6013-rev-list-reverse-parents.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+test_description='--reverse combines with --parents'
+
+. ./test-lib.sh
+
+
+commit () {
+ test_tick &&
+ echo $1 > foo &&
+ git add foo &&
+ git commit -m "$1"
+}
+
+test_expect_success 'set up --reverse example' '
+ commit one &&
+ git tag root &&
+ commit two &&
+ git checkout -b side HEAD^ &&
+ commit three &&
+ git checkout master &&
+ git merge -s ours side &&
+ commit five
+ '
+
+test_expect_success '--reverse --parents --full-history combines correctly' '
+ git rev-list --parents --full-history master -- foo |
+ perl -e "print reverse <>" > expected &&
+ git rev-list --reverse --parents --full-history master -- foo \
+ > actual &&
+ test_cmp actual expected
+ '
+
+test_expect_success '--boundary does too' '
+ git rev-list --boundary --parents --full-history master ^root -- foo |
+ perl -e "print reverse <>" > expected &&
+ git rev-list --boundary --reverse --parents --full-history \
+ master ^root -- foo > actual &&
+ test_cmp actual expected
+ '
+
+test_done
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
new file mode 100755
index 0000000000..991ab4a65b
--- /dev/null
+++ b/t/t6014-rev-list-all.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+test_description='--all includes detached HEADs'
+
+. ./test-lib.sh
+
+
+commit () {
+ test_tick &&
+ echo $1 > foo &&
+ git add foo &&
+ git commit -m "$1"
+}
+
+test_expect_success 'setup' '
+
+ commit one &&
+ commit two &&
+ git checkout HEAD^ &&
+ commit detached
+
+'
+
+test_expect_success 'rev-list --all lists detached HEAD' '
+
+ test 3 = $(git rev-list --all | wc -l)
+
+'
+
+test_expect_success 'repack does not lose detached HEAD' '
+
+ git gc &&
+ git prune --expire=now &&
+ git show HEAD
+
+'
+
+test_done
diff --git a/t/t6015-rev-list-show-all-parents.sh b/t/t6015-rev-list-show-all-parents.sh
new file mode 100755
index 0000000000..8b146fb432
--- /dev/null
+++ b/t/t6015-rev-list-show-all-parents.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+test_description='--show-all --parents does not rewrite TREESAME commits'
+
+. ./test-lib.sh
+
+test_expect_success 'set up --show-all --parents test' '
+ test_commit one foo.txt &&
+ commit1=`git rev-list -1 HEAD` &&
+ test_commit two bar.txt &&
+ commit2=`git rev-list -1 HEAD` &&
+ test_commit three foo.txt &&
+ commit3=`git rev-list -1 HEAD`
+ '
+
+test_expect_success '--parents rewrites TREESAME parents correctly' '
+ echo $commit3 $commit1 > expected &&
+ echo $commit1 >> expected &&
+ git rev-list --parents HEAD -- foo.txt > actual &&
+ test_cmp expected actual
+ '
+
+test_expect_success '--parents --show-all does not rewrites TREESAME parents' '
+ echo $commit3 $commit2 > expected &&
+ echo $commit2 $commit1 >> expected &&
+ echo $commit1 >> expected &&
+ git rev-list --parents --show-all HEAD -- foo.txt > actual &&
+ test_cmp expected actual
+ '
+
+test_done
diff --git a/t/t6016-rev-list-graph-simplify-history.sh b/t/t6016-rev-list-graph-simplify-history.sh
new file mode 100755
index 0000000000..27fd52b7be
--- /dev/null
+++ b/t/t6016-rev-list-graph-simplify-history.sh
@@ -0,0 +1,276 @@
+#!/bin/sh
+
+# There's more than one "correct" way to represent the history graphically.
+# These tests depend on the current behavior of the graphing code. If the
+# graphing code is ever changed to draw the output differently, these tests
+# cases will need to be updated to know about the new layout.
+
+test_description='--graph and simplified history'
+
+. ./test-lib.sh
+
+test_expect_success 'set up rev-list --graph test' '
+ # 3 commits on branch A
+ test_commit A1 foo.txt &&
+ test_commit A2 bar.txt &&
+ test_commit A3 bar.txt &&
+ git branch -m master A &&
+
+ # 2 commits on branch B, started from A1
+ git checkout -b B A1 &&
+ test_commit B1 foo.txt &&
+ test_commit B2 abc.txt &&
+
+ # 2 commits on branch C, started from A2
+ git checkout -b C A2 &&
+ test_commit C1 xyz.txt &&
+ test_commit C2 xyz.txt &&
+
+ # Octopus merge B and C into branch A
+ git checkout A &&
+ git merge B C &&
+ git tag A4
+
+ test_commit A5 bar.txt &&
+
+ # More commits on C, then merge C into A
+ git checkout C &&
+ test_commit C3 foo.txt &&
+ test_commit C4 bar.txt &&
+ git checkout A &&
+ git merge -s ours C &&
+ git tag A6
+
+ test_commit A7 bar.txt &&
+
+ # Store commit names in variables for later use
+ A1=$(git rev-parse --verify A1) &&
+ A2=$(git rev-parse --verify A2) &&
+ A3=$(git rev-parse --verify A3) &&
+ A4=$(git rev-parse --verify A4) &&
+ A5=$(git rev-parse --verify A5) &&
+ A6=$(git rev-parse --verify A6) &&
+ A7=$(git rev-parse --verify A7) &&
+ B1=$(git rev-parse --verify B1) &&
+ B2=$(git rev-parse --verify B2) &&
+ C1=$(git rev-parse --verify C1) &&
+ C2=$(git rev-parse --verify C2) &&
+ C3=$(git rev-parse --verify C3) &&
+ C4=$(git rev-parse --verify C4)
+ '
+
+test_expect_success '--graph --all' '
+ rm -f expected &&
+ echo "* $A7" >> expected &&
+ echo "* $A6" >> expected &&
+ echo "|\\ " >> expected &&
+ echo "| * $C4" >> expected &&
+ echo "| * $C3" >> expected &&
+ echo "* | $A5" >> expected &&
+ echo "| | " >> expected &&
+ echo "| \\ " >> expected &&
+ echo "*-. \\ $A4" >> expected &&
+ echo "|\\ \\ \\ " >> expected &&
+ echo "| | |/ " >> expected &&
+ echo "| | * $C2" >> expected &&
+ echo "| | * $C1" >> expected &&
+ echo "| * | $B2" >> expected &&
+ echo "| * | $B1" >> expected &&
+ echo "* | | $A3" >> expected &&
+ echo "| |/ " >> expected &&
+ echo "|/| " >> expected &&
+ echo "* | $A2" >> expected &&
+ echo "|/ " >> expected &&
+ echo "* $A1" >> expected &&
+ git rev-list --graph --all > actual &&
+ test_cmp expected actual
+ '
+
+# Make sure the graph_is_interesting() code still realizes
+# that undecorated merges are interesting, even with --simplify-by-decoration
+test_expect_success '--graph --simplify-by-decoration' '
+ rm -f expected &&
+ git tag -d A4
+ echo "* $A7" >> expected &&
+ echo "* $A6" >> expected &&
+ echo "|\\ " >> expected &&
+ echo "| * $C4" >> expected &&
+ echo "| * $C3" >> expected &&
+ echo "* | $A5" >> expected &&
+ echo "| | " >> expected &&
+ echo "| \\ " >> expected &&
+ echo "*-. \\ $A4" >> expected &&
+ echo "|\\ \\ \\ " >> expected &&
+ echo "| | |/ " >> expected &&
+ echo "| | * $C2" >> expected &&
+ echo "| | * $C1" >> expected &&
+ echo "| * | $B2" >> expected &&
+ echo "| * | $B1" >> expected &&
+ echo "* | | $A3" >> expected &&
+ echo "| |/ " >> expected &&
+ echo "|/| " >> expected &&
+ echo "* | $A2" >> expected &&
+ echo "|/ " >> expected &&
+ echo "* $A1" >> expected &&
+ git rev-list --graph --all --simplify-by-decoration > actual &&
+ test_cmp expected actual
+ '
+
+# Get rid of all decorations on branch B, and graph with it simplified away
+test_expect_success '--graph --simplify-by-decoration prune branch B' '
+ rm -f expected &&
+ git tag -d B2
+ git tag -d B1
+ git branch -d B
+ echo "* $A7" >> expected &&
+ echo "* $A6" >> expected &&
+ echo "|\\ " >> expected &&
+ echo "| * $C4" >> expected &&
+ echo "| * $C3" >> expected &&
+ echo "* | $A5" >> expected &&
+ echo "* | $A4" >> expected &&
+ echo "|\\ \\ " >> expected &&
+ echo "| |/ " >> expected &&
+ echo "| * $C2" >> expected &&
+ echo "| * $C1" >> expected &&
+ echo "* | $A3" >> expected &&
+ echo "|/ " >> expected &&
+ echo "* $A2" >> expected &&
+ echo "* $A1" >> expected &&
+ git rev-list --graph --simplify-by-decoration --all > actual &&
+ test_cmp expected actual
+ '
+
+test_expect_success '--graph --full-history -- bar.txt' '
+ rm -f expected &&
+ git tag -d B2
+ git tag -d B1
+ git branch -d B
+ echo "* $A7" >> expected &&
+ echo "* $A6" >> expected &&
+ echo "|\\ " >> expected &&
+ echo "| * $C4" >> expected &&
+ echo "* | $A5" >> expected &&
+ echo "* | $A4" >> expected &&
+ echo "|\\ \\ " >> expected &&
+ echo "| |/ " >> expected &&
+ echo "* | $A3" >> expected &&
+ echo "|/ " >> expected &&
+ echo "* $A2" >> expected &&
+ git rev-list --graph --full-history --all -- bar.txt > actual &&
+ test_cmp expected actual
+ '
+
+test_expect_success '--graph --full-history --simplify-merges -- bar.txt' '
+ rm -f expected &&
+ git tag -d B2
+ git tag -d B1
+ git branch -d B
+ echo "* $A7" >> expected &&
+ echo "* $A6" >> expected &&
+ echo "|\\ " >> expected &&
+ echo "| * $C4" >> expected &&
+ echo "* | $A5" >> expected &&
+ echo "* | $A3" >> expected &&
+ echo "|/ " >> expected &&
+ echo "* $A2" >> expected &&
+ git rev-list --graph --full-history --simplify-merges --all \
+ -- bar.txt > actual &&
+ test_cmp expected actual
+ '
+
+test_expect_success '--graph -- bar.txt' '
+ rm -f expected &&
+ git tag -d B2
+ git tag -d B1
+ git branch -d B
+ echo "* $A7" >> expected &&
+ echo "* $A5" >> expected &&
+ echo "* $A3" >> expected &&
+ echo "| * $C4" >> expected &&
+ echo "|/ " >> expected &&
+ echo "* $A2" >> expected &&
+ git rev-list --graph --all -- bar.txt > actual &&
+ test_cmp expected actual
+ '
+
+test_expect_success '--graph --sparse -- bar.txt' '
+ rm -f expected &&
+ git tag -d B2
+ git tag -d B1
+ git branch -d B
+ echo "* $A7" >> expected &&
+ echo "* $A6" >> expected &&
+ echo "* $A5" >> expected &&
+ echo "* $A4" >> expected &&
+ echo "* $A3" >> expected &&
+ echo "| * $C4" >> expected &&
+ echo "| * $C3" >> expected &&
+ echo "| * $C2" >> expected &&
+ echo "| * $C1" >> expected &&
+ echo "|/ " >> expected &&
+ echo "* $A2" >> expected &&
+ echo "* $A1" >> expected &&
+ git rev-list --graph --sparse --all -- bar.txt > actual &&
+ test_cmp expected actual
+ '
+
+test_expect_success '--graph ^C4' '
+ rm -f expected &&
+ echo "* $A7" >> expected &&
+ echo "* $A6" >> expected &&
+ echo "* $A5" >> expected &&
+ echo "* $A4" >> expected &&
+ echo "|\\ " >> expected &&
+ echo "| * $B2" >> expected &&
+ echo "| * $B1" >> expected &&
+ echo "* $A3" >> expected &&
+ git rev-list --graph --all ^C4 > actual &&
+ test_cmp expected actual
+ '
+
+test_expect_success '--graph ^C3' '
+ rm -f expected &&
+ echo "* $A7" >> expected &&
+ echo "* $A6" >> expected &&
+ echo "|\\ " >> expected &&
+ echo "| * $C4" >> expected &&
+ echo "* $A5" >> expected &&
+ echo "* $A4" >> expected &&
+ echo "|\\ " >> expected &&
+ echo "| * $B2" >> expected &&
+ echo "| * $B1" >> expected &&
+ echo "* $A3" >> expected &&
+ git rev-list --graph --all ^C3 > actual &&
+ test_cmp expected actual
+ '
+
+# I don't think the ordering of the boundary commits is really
+# that important, but this test depends on it. If the ordering ever changes
+# in the code, we'll need to update this test.
+test_expect_success '--graph --boundary ^C3' '
+ rm -f expected &&
+ echo "* $A7" >> expected &&
+ echo "* $A6" >> expected &&
+ echo "|\\ " >> expected &&
+ echo "| * $C4" >> expected &&
+ echo "* | $A5" >> expected &&
+ echo "| | " >> expected &&
+ echo "| \\ " >> expected &&
+ echo "*-. \\ $A4" >> expected &&
+ echo "|\\ \\ \\ " >> expected &&
+ echo "| * | | $B2" >> expected &&
+ echo "| * | | $B1" >> expected &&
+ echo "* | | | $A3" >> expected &&
+ echo "o | | | $A2" >> expected &&
+ echo "|/ / / " >> expected &&
+ echo "o | | $A1" >> expected &&
+ echo " / / " >> expected &&
+ echo "| o $C3" >> expected &&
+ echo "|/ " >> expected &&
+ echo "o $C2" >> expected &&
+ git rev-list --graph --boundary --all ^C3 > actual &&
+ test_cmp expected actual
+ '
+
+test_done
diff --git a/t/t6017-rev-list-stdin.sh b/t/t6017-rev-list-stdin.sh
new file mode 100755
index 0000000000..f1c32dba42
--- /dev/null
+++ b/t/t6017-rev-list-stdin.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# Copyright (c) 2009, Junio C Hamano
+#
+
+test_description='log family learns --stdin'
+
+. ./test-lib.sh
+
+check () {
+ for cmd in rev-list "log --stat"
+ do
+ for i in "$@"
+ do
+ printf "%s\n" $i
+ done >input &&
+ test_expect_success "check $cmd $*" '
+ git $cmd $(cat input) >expect &&
+ git $cmd --stdin <input >actual &&
+ sed -e "s/^/input /" input &&
+ sed -e "s/^/output /" expect &&
+ test_cmp expect actual
+ '
+ done
+}
+
+them='1 2 3 4 5 6 7'
+
+test_expect_success setup '
+ (
+ for i in 0 $them
+ do
+ for j in $them
+ do
+ echo $i.$j >file-$j &&
+ git add file-$j || exit
+ done &&
+ test_tick &&
+ git commit -m $i || exit
+ done &&
+ for i in $them
+ do
+ git checkout -b side-$i master~$i &&
+ echo updated $i >file-$i &&
+ git add file-$i &&
+ test_tick &&
+ git commit -m side-$i || exit
+ done
+ )
+'
+
+check master
+check side-1 ^side-4
+check side-1 ^side-7 --
+check side-1 ^side-7 -- file-1
+check side-1 ^side-7 -- file-2
+check side-3 ^side-4 -- file-3
+check side-3 ^side-2
+check side-3 ^side-2 -- file-1
+
+test_done
diff --git a/t/t6020-merge-df.sh b/t/t6020-merge-df.sh
index a19d49de28..e71c687f2b 100755
--- a/t/t6020-merge-df.sh
+++ b/t/t6020-merge-df.sh
@@ -22,4 +22,27 @@ git commit -m "File: dir"'
test_expect_code 1 'Merge with d/f conflicts' 'git merge "merge msg" B master'
+test_expect_failure 'F/D conflict' '
+ git reset --hard &&
+ git checkout master &&
+ rm .git/index &&
+
+ mkdir before &&
+ echo FILE >before/one &&
+ echo FILE >after &&
+ git add . &&
+ git commit -m first &&
+
+ rm -f after &&
+ git mv before after &&
+ git commit -m move &&
+
+ git checkout -b para HEAD^ &&
+ echo COMPLETELY ANOTHER FILE >another &&
+ git add . &&
+ git commit -m para &&
+
+ git merge master
+'
+
test_done
diff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh
index 0ab14a6e81..331b9b07d4 100755
--- a/t/t6021-merge-criss-cross.sh
+++ b/t/t6021-merge-criss-cross.sh
@@ -89,4 +89,8 @@ EOF
test_expect_success 'Criss-cross merge result' 'cmp file file-expect'
+test_expect_success 'Criss-cross merge fails (-s resolve)' \
+'git reset --hard A^ &&
+test_must_fail git merge -s resolve -m "final merge" B'
+
test_done
diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh
index 79dc58b2ce..7dcf391914 100755
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
@@ -54,6 +54,12 @@ deduxit me super semitas jusitiae,
EOF
printf "propter nomen suum." >> new4.txt
+test_expect_success 'merge with no changes' '
+ cp orig.txt test.txt &&
+ git merge-file test.txt orig.txt orig.txt &&
+ test_cmp test.txt orig.txt
+'
+
cp new1.txt test.txt
test_expect_success "merge without conflict" \
"git merge-file test.txt orig.txt new2.txt"
@@ -63,11 +69,11 @@ test_expect_success "merge without conflict (missing LF at EOF)" \
"git merge-file test2.txt orig.txt new2.txt"
test_expect_success "merge result added missing LF" \
- "git diff test.txt test2.txt"
+ "test_cmp test.txt test2.txt"
cp test.txt backup.txt
test_expect_success "merge with conflicts" \
- "! git merge-file test.txt orig.txt new3.txt"
+ "test_must_fail git merge-file test.txt orig.txt new3.txt"
cat > expect.txt << EOF
<<<<<<< test.txt
@@ -86,11 +92,11 @@ non timebo mala, quoniam tu mecum es:
virga tua et baculus tuus ipsa me consolata sunt.
EOF
-test_expect_success "expected conflict markers" "git diff test.txt expect.txt"
+test_expect_success "expected conflict markers" "test_cmp test.txt expect.txt"
cp backup.txt test.txt
test_expect_success "merge with conflicts, using -L" \
- "! git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
+ "test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
cat > expect.txt << EOF
<<<<<<< 1
@@ -110,11 +116,11 @@ virga tua et baculus tuus ipsa me consolata sunt.
EOF
test_expect_success "expected conflict markers, with -L" \
- "git diff test.txt expect.txt"
+ "test_cmp test.txt expect.txt"
sed "s/ tu / TU /" < new1.txt > new5.txt
test_expect_success "conflict in removed tail" \
- "! git merge-file -p orig.txt new1.txt new5.txt > out"
+ "test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out"
cat > expect << EOF
Dominus regit me,
@@ -132,10 +138,11 @@ virga tua et baculus tuus ipsa me consolata sunt.
>>>>>>> new5.txt
EOF
-test_expect_success "expected conflict markers" "git diff expect out"
+test_expect_success "expected conflict markers" "test_cmp expect out"
test_expect_success 'binary files cannot be merged' '
- ! git merge-file -p orig.txt ../test4012.png new1.txt 2> merge.err &&
+ test_must_fail git merge-file -p \
+ orig.txt "$TEST_DIRECTORY"/test4012.png new1.txt 2> merge.err &&
grep "Cannot merge binary files" merge.err
'
@@ -144,19 +151,64 @@ sed -e "s/deerit.$/deerit,/" -e "s/me;$/me,/" < new5.txt > new7.txt
test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '
- ! git merge-file -p new6.txt new5.txt new7.txt > output &&
+ test_must_fail git merge-file -p new6.txt new5.txt new7.txt > output &&
test 1 = $(grep ======= < output | wc -l)
'
-sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit;/" < new6.txt > new8.txt
-sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit --/" < new7.txt > new9.txt
+sed -e 's/deerit./&%%%%/' -e "s/locavit,/locavit;/"< new6.txt | tr '%' '\012' > new8.txt
+sed -e 's/deerit./&%%%%/' -e "s/locavit,/locavit --/" < new7.txt | tr '%' '\012' > new9.txt
test_expect_success 'ZEALOUS_ALNUM' '
- ! git merge-file -p new8.txt new5.txt new9.txt > merge.out &&
+ test_must_fail git merge-file -p \
+ new8.txt new5.txt new9.txt > merge.out &&
test 1 = $(grep ======= < merge.out | wc -l)
'
+cat >expect <<\EOF
+Dominus regit me,
+<<<<<<< new8.txt
+et nihil mihi deerit;
+
+
+
+
+In loco pascuae ibi me collocavit;
+super aquam refectionis educavit me.
+|||||||
+et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+=======
+et nihil mihi deerit,
+
+
+
+
+In loco pascuae ibi me collocavit --
+super aquam refectionis educavit me,
+>>>>>>> new9.txt
+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 '"diff3 -m" style output (1)' '
+ test_must_fail git merge-file -p --diff3 \
+ new8.txt new5.txt new9.txt >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '"diff3 -m" style output (2)' '
+ git config merge.conflictstyle diff3 &&
+ test_must_fail git merge-file -p \
+ new8.txt new5.txt new9.txt >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh
index 23d24d3feb..b3fbf659c0 100755
--- a/t/t6024-recursive-merge.sh
+++ b/t/t6024-recursive-merge.sh
@@ -60,26 +60,28 @@ git update-index a1 &&
GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F
'
-test_expect_success "combined merge conflicts" "! git merge -m final G"
+test_expect_success "combined merge conflicts" "
+ test_must_fail git merge -m final G
+"
cat > expect << EOF
-<<<<<<< HEAD:a1
+<<<<<<< HEAD
F
=======
G
->>>>>>> G:a1
+>>>>>>> G
EOF
-test_expect_success "result contains a conflict" "git diff expect a1"
+test_expect_success "result contains a conflict" "test_cmp expect a1"
git ls-files --stage > out
cat > expect << EOF
-100644 da056ce14a2241509897fa68bb2b3b6e6194ef9e 1 a1
+100644 439cc46de773d8a83c77799b7cc9191c128bfcff 1 a1
100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2 a1
100644 fd7923529855d0b274795ae3349c5e0438333979 3 a1
EOF
-test_expect_success "virtual trees were processed" "git diff expect out"
+test_expect_success "virtual trees were processed" "test_cmp expect out"
test_expect_success 'refuse to merge binary files' '
git reset --hard &&
@@ -90,9 +92,31 @@ test_expect_success 'refuse to merge binary files' '
printf "\0\0" > binary-file &&
git add binary-file &&
git commit -m binary2 &&
- ! git merge F > merge.out 2> merge.err &&
- grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \
- merge.err
+ test_must_fail git merge F > merge.out 2> merge.err &&
+ grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge.err
+'
+
+test_expect_success 'mark rename/delete as unmerged' '
+
+ git reset --hard &&
+ git checkout -b delete &&
+ git rm a1 &&
+ test_tick &&
+ git commit -m delete &&
+ git checkout -b rename HEAD^ &&
+ git mv a1 a2
+ test_tick &&
+ git commit -m rename &&
+ test_must_fail git merge delete &&
+ test 1 = $(git ls-files --unmerged | wc -l) &&
+ git rev-parse --verify :2:a2 &&
+ test_must_fail git rev-parse --verify :3:a2 &&
+ git checkout -f delete &&
+ test_must_fail git merge rename &&
+ test 1 = $(git ls-files --unmerged | wc -l) &&
+ test_must_fail git rev-parse --verify :2:a2 &&
+ git rev-parse --verify :3:a2
+
'
test_done
diff --git a/t/t6025-merge-symlinks.sh b/t/t6025-merge-symlinks.sh
index 6004deb432..433c4de08f 100755
--- a/t/t6025-merge-symlinks.sh
+++ b/t/t6025-merge-symlinks.sh
@@ -5,7 +5,7 @@
test_description='merging symlinks on filesystem w/o symlink support.
-This tests that git-merge-recursive writes merge results as plain files
+This tests that git merge-recursive writes merge results as plain files
if core.symlinks is false.'
. ./test-lib.sh
@@ -15,25 +15,25 @@ test_expect_success \
git config core.symlinks false &&
> file &&
git add file &&
-git-commit -m initial &&
+git commit -m initial &&
git branch b-symlink &&
git branch b-file &&
-l=$(echo -n file | git-hash-object -t blob -w --stdin) &&
+l=$(printf file | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info &&
-git-commit -m master &&
-git-checkout b-symlink &&
-l=$(echo -n file-different | git-hash-object -t blob -w --stdin) &&
+git commit -m master &&
+git checkout b-symlink &&
+l=$(printf file-different | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info &&
-git-commit -m b-symlink &&
-git-checkout b-file &&
+git commit -m b-symlink &&
+git checkout b-file &&
echo plain-file > symlink &&
git add symlink &&
-git-commit -m b-file'
+git commit -m b-file'
test_expect_success \
'merge master into b-symlink, which has a different symbolic link' '
-git-checkout b-symlink &&
-! git-merge master'
+git checkout b-symlink &&
+test_must_fail git merge master'
test_expect_success \
'the merge result must be a file' '
@@ -41,8 +41,8 @@ test -f symlink'
test_expect_success \
'merge master into b-file, which has a file instead of a symbolic link' '
-git-reset --hard && git-checkout b-file &&
-! git-merge master'
+git reset --hard && git checkout b-file &&
+test_must_fail git merge master'
test_expect_success \
'the merge result must be a file' '
@@ -50,9 +50,9 @@ test -f symlink'
test_expect_success \
'merge b-file, which has a file instead of a symbolic link, into master' '
-git-reset --hard &&
-git-checkout master &&
-! git-merge b-file'
+git reset --hard &&
+git checkout master &&
+test_must_fail git merge b-file'
test_expect_success \
'the merge result must be a file' '
diff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh
index 56fc341768..1ba0a25223 100755
--- a/t/t6026-merge-attr.sh
+++ b/t/t6026-merge-attr.sh
@@ -106,9 +106,9 @@ test_expect_success 'custom merge backend' '
cmp binary union &&
sed -e 1,3d text >check-1 &&
- o=$(git-unpack-file master^:text) &&
- a=$(git-unpack-file side^:text) &&
- b=$(git-unpack-file master:text) &&
+ o=$(git unpack-file master^:text) &&
+ a=$(git unpack-file side^:text) &&
+ b=$(git unpack-file master:text) &&
sh -c "./custom-merge $o $a $b 0" &&
sed -e 1,3d $a >check-2 &&
cmp check-1 check-2 &&
@@ -133,13 +133,35 @@ test_expect_success 'custom merge backend' '
cmp binary union &&
sed -e 1,3d text >check-1 &&
- o=$(git-unpack-file master^:text) &&
- a=$(git-unpack-file anchor:text) &&
- b=$(git-unpack-file master:text) &&
+ o=$(git unpack-file master^:text) &&
+ a=$(git unpack-file anchor:text) &&
+ b=$(git unpack-file master:text) &&
sh -c "./custom-merge $o $a $b 0" &&
sed -e 1,3d $a >check-2 &&
cmp check-1 check-2 &&
rm -f $o $a $b
'
+test_expect_success 'up-to-date merge without common ancestor' '
+ test_create_repo repo1 &&
+ test_create_repo repo2 &&
+ test_tick &&
+ (
+ cd repo1 &&
+ >a &&
+ git add a &&
+ git commit -m initial
+ ) &&
+ test_tick &&
+ (
+ cd repo2 &&
+ git commit --allow-empty -m initial
+ ) &&
+ test_tick &&
+ (
+ cd repo1 &&
+ git pull ../repo2 master
+ )
+'
+
test_done
diff --git a/t/t6027-merge-binary.sh b/t/t6027-merge-binary.sh
index 92ca1f0f8c..b519626ca0 100755
--- a/t/t6027-merge-binary.sh
+++ b/t/t6027-merge-binary.sh
@@ -6,7 +6,7 @@ test_description='ask merge-recursive to merge binary files'
test_expect_success setup '
- cat ../test4012.png >m &&
+ cat "$TEST_DIRECTORY"/test4012.png >m &&
git add m &&
git ls-files -s | sed -e "s/ 0 / 1 /" >E1 &&
test_tick &&
diff --git a/t/t6028-merge-up-to-date.sh b/t/t6028-merge-up-to-date.sh
index f8f3e3ff2c..a91644e3b2 100755
--- a/t/t6028-merge-up-to-date.sh
+++ b/t/t6028-merge-up-to-date.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='merge fast forward and up to date'
+test_description='merge fast-forward and up to date'
. ./test-lib.sh
diff --git a/t/t6029-merge-subtree.sh b/t/t6029-merge-subtree.sh
index 43f5459c35..5bbfa44e8d 100755
--- a/t/t6029-merge-subtree.sh
+++ b/t/t6029-merge-subtree.sh
@@ -57,7 +57,7 @@ test_expect_success 'initial merge' '
echo "100644 $o1 0 git-gui/git-gui.sh"
echo "100644 $o2 0 git.c"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
test_expect_success 'merge update' '
@@ -73,7 +73,7 @@ test_expect_success 'merge update' '
echo "100644 $o3 0 git-gui/git-gui.sh"
echo "100644 $o2 0 git.c"
) >expected &&
- git diff -u expected actual
+ test_cmp expected actual
'
test_done
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 5e3e5445c7..def397c53a 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -2,7 +2,7 @@
#
# Copyright (c) 2007 Christian Couder
#
-test_description='Tests git-bisect functionality'
+test_description='Tests git bisect functionality'
exec </dev/null
@@ -23,7 +23,7 @@ add_line_into_file()
fi
test_tick
- git-commit --quiet -m "$MSG" $_file
+ git commit --quiet -m "$MSG" $_file
}
HASH1=
@@ -76,7 +76,7 @@ test_expect_success 'bisect fails if given any junk instead of revs' '
test_must_fail git bisect start foo $HASH1 -- &&
test_must_fail git bisect start $HASH4 $HASH1 bar -- &&
test -z "$(git for-each-ref "refs/bisect/*")" &&
- test_must_fail ls .git/BISECT_* &&
+ test -z "$(ls .git/BISECT_* 2>/dev/null)" &&
git bisect start &&
test_must_fail git bisect good foo $HASH1 &&
test_must_fail git bisect good $HASH1 bar &&
@@ -126,6 +126,47 @@ test_expect_success 'bisect reset removes packed refs' '
test -z "$(git for-each-ref "refs/heads/bisect")"
'
+test_expect_success 'bisect start: back in good branch' '
+ git branch > branch.output &&
+ grep "* other" branch.output > /dev/null &&
+ git bisect start $HASH4 $HASH1 -- &&
+ git bisect good &&
+ git bisect start $HASH4 $HASH1 -- &&
+ git bisect bad &&
+ git bisect reset &&
+ git branch > branch.output &&
+ grep "* other" branch.output > /dev/null
+'
+
+test_expect_success 'bisect start: no ".git/BISECT_START" if junk rev' '
+ git bisect start $HASH4 $HASH1 -- &&
+ git bisect good &&
+ test_must_fail git bisect start $HASH4 foo -- &&
+ git branch > branch.output &&
+ grep "* other" branch.output > /dev/null &&
+ test_must_fail test -e .git/BISECT_START
+'
+
+test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' '
+ git bisect start $HASH4 $HASH1 -- &&
+ git bisect good &&
+ test_must_fail git bisect start $HASH1 $HASH4 -- &&
+ git branch > branch.output &&
+ grep "* other" branch.output > /dev/null &&
+ test_must_fail test -e .git/BISECT_START
+'
+
+test_expect_success 'bisect start: no ".git/BISECT_START" if checkout error' '
+ echo "temp stuff" > hello &&
+ test_must_fail git bisect start $HASH4 $HASH1 -- &&
+ git branch &&
+ git branch > branch.output &&
+ grep "* other" branch.output > /dev/null &&
+ test_must_fail test -e .git/BISECT_START &&
+ test -z "$(git for-each-ref "refs/bisect/*")" &&
+ git checkout HEAD hello
+'
+
# $HASH1 is good, $HASH4 is bad, we skip $HASH3
# but $HASH2 is bad,
# so we should find $HASH2 as the first bad commit
@@ -134,7 +175,7 @@ test_expect_success 'bisect skip: successfull result' '
git bisect start $HASH4 $HASH1 &&
git bisect skip &&
git bisect bad > my_bisect_log.txt &&
- grep "$HASH2 is first bad commit" my_bisect_log.txt &&
+ grep "$HASH2 is the first bad commit" my_bisect_log.txt &&
git bisect reset
'
@@ -183,6 +224,31 @@ test_expect_success 'bisect skip: cannot tell between 2 commits' '
fi
'
+# $HASH1 is good, $HASH4 is both skipped and bad, we skip $HASH3
+# and $HASH2 is good,
+# so we should not be able to tell the first bad commit
+# among $HASH3 and $HASH4
+test_expect_success 'bisect skip: with commit both bad and skipped' '
+ git bisect start &&
+ git bisect skip &&
+ git bisect bad &&
+ git bisect good $HASH1 &&
+ git bisect skip &&
+ if git bisect good > my_bisect_log.txt
+ then
+ echo Oops, should have failed.
+ false
+ else
+ test $? -eq 2 &&
+ grep "first bad commit could be any of" my_bisect_log.txt &&
+ ! grep $HASH1 my_bisect_log.txt &&
+ ! grep $HASH2 my_bisect_log.txt &&
+ grep $HASH3 my_bisect_log.txt &&
+ grep $HASH4 my_bisect_log.txt &&
+ git bisect reset
+ fi
+'
+
# We want to automatically find the commit that
# introduced "Another" into hello.
test_expect_success \
@@ -195,7 +261,7 @@ test_expect_success \
git bisect good $HASH1 &&
git bisect bad $HASH4 &&
git bisect run ./test_script.sh > my_bisect_log.txt &&
- grep "$HASH3 is first bad commit" my_bisect_log.txt &&
+ grep "$HASH3 is the first bad commit" my_bisect_log.txt &&
git bisect reset'
# We want to automatically find the commit that
@@ -208,7 +274,7 @@ test_expect_success \
chmod +x test_script.sh &&
git bisect start $HASH4 $HASH1 &&
git bisect run ./test_script.sh > my_bisect_log.txt &&
- grep "$HASH4 is first bad commit" my_bisect_log.txt &&
+ grep "$HASH4 is the first bad commit" my_bisect_log.txt &&
git bisect reset'
# $HASH1 is good, $HASH5 is bad, we skip $HASH3
@@ -221,14 +287,14 @@ test_expect_success 'bisect skip: add line and then a new test' '
git bisect start $HASH5 $HASH1 &&
git bisect skip &&
git bisect good > my_bisect_log.txt &&
- grep "$HASH5 is first bad commit" my_bisect_log.txt &&
+ grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
git bisect log > log_to_replay.txt &&
git bisect reset
'
test_expect_success 'bisect skip and bisect replay' '
git bisect replay log_to_replay.txt > my_bisect_log.txt &&
- grep "$HASH5 is first bad commit" my_bisect_log.txt &&
+ grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
git bisect reset
'
@@ -269,11 +335,28 @@ test_expect_success 'bisect run & skip: find first bad' '
chmod +x test_script.sh &&
git bisect start $HASH7 $HASH1 &&
git bisect run ./test_script.sh > my_bisect_log.txt &&
- grep "$HASH6 is first bad commit" my_bisect_log.txt
+ grep "$HASH6 is the first bad commit" my_bisect_log.txt
'
-test_expect_success 'bisect starting with a detached HEAD' '
+test_expect_success 'bisect skip only one range' '
+ git bisect reset &&
+ git bisect start $HASH7 $HASH1 &&
+ git bisect skip $HASH1..$HASH5 &&
+ test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
+ test_must_fail git bisect bad > my_bisect_log.txt &&
+ grep "first bad commit could be any of" my_bisect_log.txt
+'
+test_expect_success 'bisect skip many ranges' '
+ git bisect start $HASH7 $HASH1 &&
+ test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
+ git bisect skip $HASH2 $HASH2.. ..$HASH5 &&
+ test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
+ test_must_fail git bisect bad > my_bisect_log.txt &&
+ grep "first bad commit could be any of" my_bisect_log.txt
+'
+
+test_expect_success 'bisect starting with a detached HEAD' '
git bisect reset &&
git checkout master^ &&
HEAD=$(git rev-parse --verify HEAD) &&
@@ -281,7 +364,207 @@ test_expect_success 'bisect starting with a detached HEAD' '
test $HEAD = $(cat .git/BISECT_START) &&
git bisect reset &&
test $HEAD = $(git rev-parse --verify HEAD)
+'
+
+test_expect_success 'bisect errors out if bad and good are mistaken' '
+ git bisect reset &&
+ test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error &&
+ grep "mistake good and bad" rev_list_error &&
+ git bisect reset
+'
+
+test_expect_success 'bisect does not create a "bisect" branch' '
+ git bisect reset &&
+ git bisect start $HASH7 $HASH1 &&
+ git branch bisect &&
+ rev_hash4=$(git rev-parse --verify HEAD) &&
+ test "$rev_hash4" = "$HASH4" &&
+ git branch -D bisect &&
+ git bisect good &&
+ git branch bisect &&
+ rev_hash6=$(git rev-parse --verify HEAD) &&
+ test "$rev_hash6" = "$HASH6" &&
+ git bisect good > my_bisect_log.txt &&
+ grep "$HASH7 is the first bad commit" my_bisect_log.txt &&
+ git bisect reset &&
+ rev_hash6=$(git rev-parse --verify bisect) &&
+ test "$rev_hash6" = "$HASH6" &&
+ git branch -D bisect
+'
+
+# This creates a "side" branch to test "siblings" cases.
+#
+# H1-H2-H3-H4-H5-H6-H7 <--other
+# \
+# S5-S6-S7 <--side
+#
+test_expect_success 'side branch creation' '
+ git bisect reset &&
+ git checkout -b side $HASH4 &&
+ add_line_into_file "5(side): first line on a side branch" hello2 &&
+ SIDE_HASH5=$(git rev-parse --verify HEAD) &&
+ add_line_into_file "6(side): second line on a side branch" hello2 &&
+ SIDE_HASH6=$(git rev-parse --verify HEAD) &&
+ add_line_into_file "7(side): third line on a side branch" hello2 &&
+ SIDE_HASH7=$(git rev-parse --verify HEAD)
+'
+
+test_expect_success 'good merge base when good and bad are siblings' '
+ git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
+ grep "merge base must be tested" my_bisect_log.txt &&
+ grep $HASH4 my_bisect_log.txt &&
+ git bisect good > my_bisect_log.txt &&
+ test_must_fail grep "merge base must be tested" my_bisect_log.txt &&
+ grep $HASH6 my_bisect_log.txt &&
+ git bisect reset
+'
+test_expect_success 'skipped merge base when good and bad are siblings' '
+ git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt &&
+ grep "merge base must be tested" my_bisect_log.txt &&
+ grep $HASH4 my_bisect_log.txt &&
+ git bisect skip > my_bisect_log.txt 2>&1 &&
+ grep "Warning" my_bisect_log.txt &&
+ grep $SIDE_HASH6 my_bisect_log.txt &&
+ git bisect reset
+'
+
+test_expect_success 'bad merge base when good and bad are siblings' '
+ git bisect start "$HASH7" HEAD > my_bisect_log.txt &&
+ grep "merge base must be tested" my_bisect_log.txt &&
+ grep $HASH4 my_bisect_log.txt &&
+ test_must_fail git bisect bad > my_bisect_log.txt 2>&1 &&
+ grep "merge base $HASH4 is bad" my_bisect_log.txt &&
+ grep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt &&
+ git bisect reset
+'
+
+# This creates a few more commits (A and B) to test "siblings" cases
+# when a good and a bad rev have many merge bases.
+#
+# We should have the following:
+#
+# H1-H2-H3-H4-H5-H6-H7
+# \ \ \
+# S5-A \
+# \ \
+# S6-S7----B
+#
+# And there A and B have 2 merge bases (S5 and H5) that should be
+# reported by "git merge-base --all A B".
+#
+test_expect_success 'many merge bases creation' '
+ git checkout "$SIDE_HASH5" &&
+ git merge -m "merge HASH5 and SIDE_HASH5" "$HASH5" &&
+ A_HASH=$(git rev-parse --verify HEAD) &&
+ git checkout side &&
+ git merge -m "merge HASH7 and SIDE_HASH7" "$HASH7" &&
+ B_HASH=$(git rev-parse --verify HEAD) &&
+ git merge-base --all "$A_HASH" "$B_HASH" > merge_bases.txt &&
+ test $(wc -l < merge_bases.txt) = "2" &&
+ grep "$HASH5" merge_bases.txt &&
+ grep "$SIDE_HASH5" merge_bases.txt
+'
+
+test_expect_success 'good merge bases when good and bad are siblings' '
+ git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt &&
+ grep "merge base must be tested" my_bisect_log.txt &&
+ git bisect good > my_bisect_log2.txt &&
+ grep "merge base must be tested" my_bisect_log2.txt &&
+ {
+ {
+ grep "$SIDE_HASH5" my_bisect_log.txt &&
+ grep "$HASH5" my_bisect_log2.txt
+ } || {
+ grep "$SIDE_HASH5" my_bisect_log2.txt &&
+ grep "$HASH5" my_bisect_log.txt
+ }
+ } &&
+ git bisect reset
+'
+
+test_expect_success 'optimized merge base checks' '
+ git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
+ grep "merge base must be tested" my_bisect_log.txt &&
+ grep "$HASH4" my_bisect_log.txt &&
+ git bisect good > my_bisect_log2.txt &&
+ test -f ".git/BISECT_ANCESTORS_OK" &&
+ test "$HASH6" = $(git rev-parse --verify HEAD) &&
+ git bisect bad > my_bisect_log3.txt &&
+ git bisect good "$A_HASH" > my_bisect_log4.txt &&
+ grep "merge base must be tested" my_bisect_log4.txt &&
+ test_must_fail test -f ".git/BISECT_ANCESTORS_OK"
+'
+
+# This creates another side branch called "parallel" with some files
+# in some directories, to test bisecting with paths.
+#
+# We should have the following:
+#
+# P1-P2-P3-P4-P5-P6-P7
+# / / /
+# H1-H2-H3-H4-H5-H6-H7
+# \ \ \
+# S5-A \
+# \ \
+# S6-S7----B
+#
+test_expect_success '"parallel" side branch creation' '
+ git bisect reset &&
+ git checkout -b parallel $HASH1 &&
+ mkdir dir1 dir2 &&
+ add_line_into_file "1(para): line 1 on parallel branch" dir1/file1 &&
+ PARA_HASH1=$(git rev-parse --verify HEAD) &&
+ add_line_into_file "2(para): line 2 on parallel branch" dir2/file2 &&
+ PARA_HASH2=$(git rev-parse --verify HEAD) &&
+ add_line_into_file "3(para): line 3 on parallel branch" dir2/file3 &&
+ PARA_HASH3=$(git rev-parse --verify HEAD)
+ git merge -m "merge HASH4 and PARA_HASH3" "$HASH4" &&
+ PARA_HASH4=$(git rev-parse --verify HEAD)
+ add_line_into_file "5(para): add line on parallel branch" dir1/file1 &&
+ PARA_HASH5=$(git rev-parse --verify HEAD)
+ add_line_into_file "6(para): add line on parallel branch" dir2/file2 &&
+ PARA_HASH6=$(git rev-parse --verify HEAD)
+ git merge -m "merge HASH7 and PARA_HASH6" "$HASH7" &&
+ PARA_HASH7=$(git rev-parse --verify HEAD)
+'
+
+test_expect_success 'restricting bisection on one dir' '
+ git bisect reset &&
+ git bisect start HEAD $HASH1 -- dir1 &&
+ para1=$(git rev-parse --verify HEAD) &&
+ test "$para1" = "$PARA_HASH1" &&
+ git bisect bad > my_bisect_log.txt &&
+ grep "$PARA_HASH1 is the first bad commit" my_bisect_log.txt
+'
+
+test_expect_success 'restricting bisection on one dir and a file' '
+ git bisect reset &&
+ git bisect start HEAD $HASH1 -- dir1 hello &&
+ para4=$(git rev-parse --verify HEAD) &&
+ test "$para4" = "$PARA_HASH4" &&
+ git bisect bad &&
+ hash3=$(git rev-parse --verify HEAD) &&
+ test "$hash3" = "$HASH3" &&
+ git bisect good &&
+ hash4=$(git rev-parse --verify HEAD) &&
+ test "$hash4" = "$HASH4" &&
+ git bisect good &&
+ para1=$(git rev-parse --verify HEAD) &&
+ test "$para1" = "$PARA_HASH1" &&
+ git bisect good > my_bisect_log.txt &&
+ grep "$PARA_HASH4 is the first bad commit" my_bisect_log.txt
+'
+test_expect_success 'skipping away from skipped commit' '
+ git bisect start $PARA_HASH7 $HASH1 &&
+ para4=$(git rev-parse --verify HEAD) &&
+ test "$para4" = "$PARA_HASH4" &&
+ git bisect skip &&
+ hash7=$(git rev-parse --verify HEAD) &&
+ test "$hash7" = "$HASH7" &&
+ git bisect skip &&
+ para3=$(git rev-parse --verify HEAD) &&
+ test "$para3" = "$PARA_HASH3"
'
#
diff --git a/t/t6031-merge-recursive.sh b/t/t6031-merge-recursive.sh
index c8310aee4f..8a3304fb0b 100755
--- a/t/t6031-merge-recursive.sh
+++ b/t/t6031-merge-recursive.sh
@@ -3,6 +3,11 @@
test_description='merge-recursive: handle file mode'
. ./test-lib.sh
+if ! test "$(git config --bool core.filemode)" = false
+then
+ test_set_prereq FILEMODE
+fi
+
test_expect_success 'mode change in one branch: keep changed version' '
: >file1 &&
git add file1 &&
@@ -12,11 +17,14 @@ test_expect_success 'mode change in one branch: keep changed version' '
git add dummy &&
git commit -m a &&
git checkout -b b1 master &&
- chmod +x file1 &&
- git add file1 &&
+ test_chmod +x file1 &&
git commit -m b1 &&
git checkout a1 &&
git merge-recursive master -- a1 b1 &&
+ git ls-files -s file1 | grep ^100755
+'
+
+test_expect_success FILEMODE 'verify executable bit on file' '
test -x file1
'
@@ -25,8 +33,7 @@ test_expect_success 'mode change in both branches: expect conflict' '
git checkout -b a2 master &&
: >file2 &&
H=$(git hash-object file2) &&
- chmod +x file2 &&
- git add file2 &&
+ test_chmod +x file2 &&
git commit -m a2 &&
git checkout -b b2 master &&
: >file2 &&
@@ -43,6 +50,10 @@ test_expect_success 'mode change in both branches: expect conflict' '
echo "100644 $H 3 file2"
) >expect &&
test_cmp actual expect &&
+ git ls-files -s file2 | grep ^100755
+'
+
+test_expect_success FILEMODE 'verify executable bit on file' '
test -x file2
'
diff --git a/t/t6032-merge-large-rename.sh b/t/t6032-merge-large-rename.sh
new file mode 100755
index 0000000000..eac5ebac24
--- /dev/null
+++ b/t/t6032-merge-large-rename.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+test_description='merging with large rename matrix'
+. ./test-lib.sh
+
+count() {
+ i=1
+ while test $i -le $1; do
+ echo $i
+ i=$(($i + 1))
+ done
+}
+
+test_expect_success 'setup (initial)' '
+ touch file &&
+ git add . &&
+ git commit -m initial &&
+ git tag initial
+'
+
+make_text() {
+ echo $1: $2
+ for i in `count 20`; do
+ echo $1: $i
+ done
+ echo $1: $3
+}
+
+test_rename() {
+ test_expect_success "rename ($1, $2)" '
+ n='$1'
+ expect='$2'
+ git checkout -f master &&
+ git branch -D test$n || true &&
+ git reset --hard initial &&
+ for i in $(count $n); do
+ make_text $i initial initial >$i
+ done &&
+ git add . &&
+ git commit -m add=$n &&
+ for i in $(count $n); do
+ make_text $i changed initial >$i
+ done &&
+ git commit -a -m change=$n &&
+ git checkout -b test$n HEAD^ &&
+ for i in $(count $n); do
+ git rm $i
+ make_text $i initial changed >$i.moved
+ done &&
+ git add . &&
+ git commit -m change+rename=$n &&
+ case "$expect" in
+ ok) git merge master ;;
+ *) test_must_fail git merge master ;;
+ esac
+ '
+}
+
+test_rename 5 ok
+
+test_expect_success 'set diff.renamelimit to 4' '
+ git config diff.renamelimit 4
+'
+test_rename 4 ok
+test_rename 5 fail
+
+test_expect_success 'set merge.renamelimit to 5' '
+ git config merge.renamelimit 5
+'
+test_rename 5 ok
+test_rename 6 fail
+
+test_done
diff --git a/t/t6033-merge-crlf.sh b/t/t6033-merge-crlf.sh
new file mode 100755
index 0000000000..75d9602de4
--- /dev/null
+++ b/t/t6033-merge-crlf.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+append_cr () {
+ sed -e 's/$/Q/' | tr Q '\015'
+}
+
+remove_cr () {
+ tr '\015' Q | sed -e 's/Q$//'
+}
+
+test_description='merge conflict in crlf repo
+
+ b---M
+ / /
+ initial---a
+
+'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ git config core.autocrlf true &&
+ echo foo | append_cr >file &&
+ git add file &&
+ git commit -m "Initial" &&
+ git tag initial &&
+ git branch side &&
+ echo line from a | append_cr >file &&
+ git commit -m "add line from a" file &&
+ git tag a &&
+ git checkout side &&
+ echo line from b | append_cr >file &&
+ git commit -m "add line from b" file &&
+ git tag b &&
+ git checkout master
+'
+
+test_expect_success 'Check "ours" is CRLF' '
+ git reset --hard initial &&
+ git merge side -s ours &&
+ cat file | remove_cr | append_cr >file.temp &&
+ test_cmp file file.temp
+'
+
+test_expect_success 'Check that conflict file is CRLF' '
+ git reset --hard a &&
+ test_must_fail git merge side &&
+ cat file | remove_cr | append_cr >file.temp &&
+ test_cmp file file.temp
+'
+
+test_done
diff --git a/t/t6023-merge-rename-nocruft.sh b/t/t6034-merge-rename-nocruft.sh
index 65be95fbaa..65be95fbaa 100755
--- a/t/t6023-merge-rename-nocruft.sh
+++ b/t/t6034-merge-rename-nocruft.sh
diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh
new file mode 100755
index 0000000000..5b96fb0b37
--- /dev/null
+++ b/t/t6035-merge-dir-to-symlink.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+test_description='merging when a directory was replaced with a symlink'
+. ./test-lib.sh
+
+if ! test_have_prereq SYMLINKS
+then
+ say 'Symbolic links not supported, skipping tests.'
+ test_done
+fi
+
+test_expect_success 'create a commit where dir a/b changed to symlink' '
+ mkdir -p a/b/c a/b-2/c &&
+ > a/b/c/d &&
+ > a/b-2/c/d &&
+ > a/x &&
+ git add -A &&
+ git commit -m base &&
+ git tag start &&
+ rm -rf a/b &&
+ ln -s b-2 a/b &&
+ git add -A &&
+ git commit -m "dir to symlink"
+'
+
+test_expect_success 'keep a/b-2/c/d across checkout' '
+ git checkout HEAD^0 &&
+ git reset --hard master &&
+ git rm --cached a/b &&
+ git commit -m "untracked symlink remains" &&
+ git checkout start^0 &&
+ test -f a/b-2/c/d
+'
+
+test_expect_success 'checkout should not have deleted a/b-2/c/d' '
+ git checkout HEAD^0 &&
+ git reset --hard master &&
+ git checkout start^0 &&
+ test -f a/b-2/c/d
+'
+
+test_expect_success 'setup for merge test' '
+ git reset --hard &&
+ test -f a/b-2/c/d &&
+ echo x > a/x &&
+ git add a/x &&
+ git commit -m x &&
+ git tag baseline
+'
+
+test_expect_success 'do not lose a/b-2/c/d in merge (resolve)' '
+ git reset --hard &&
+ git checkout baseline^0 &&
+ git merge -s resolve master &&
+ test -h a/b &&
+ test -f a/b-2/c/d
+'
+
+test_expect_failure 'do not lose a/b-2/c/d in merge (recursive)' '
+ git reset --hard &&
+ git checkout baseline^0 &&
+ git merge -s recursive master &&
+ test -h a/b &&
+ test -f a/b-2/c/d
+'
+
+test_expect_success 'setup a merge where dir a/b-2 changed to symlink' '
+ git reset --hard &&
+ git checkout start^0 &&
+ rm -rf a/b-2 &&
+ ln -s b a/b-2 &&
+ git add -A &&
+ git commit -m "dir a/b-2 to symlink" &&
+ git tag test2
+'
+
+test_expect_failure 'merge should not have conflicts (resolve)' '
+ git reset --hard &&
+ git checkout baseline^0 &&
+ git merge -s resolve test2 &&
+ test -h a/b-2 &&
+ test -f a/b/c/d
+'
+
+test_expect_failure 'merge should not have conflicts (recursive)' '
+ git reset --hard &&
+ git checkout baseline^0 &&
+ git merge -s recursive test2 &&
+ test -h a/b-2 &&
+ test -f a/b/c/d
+'
+
+test_done
diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh
new file mode 100755
index 0000000000..b874141658
--- /dev/null
+++ b/t/t6036-recursive-corner-cases.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+test_description='recursive merge corner cases'
+
+. ./test-lib.sh
+
+#
+# L1 L2
+# o---o
+# / \ / \
+# o X ?
+# \ / \ /
+# o---o
+# R1 R2
+#
+
+test_expect_success setup '
+ ten="0 1 2 3 4 5 6 7 8 9"
+ for i in $ten
+ do
+ echo line $i in a sample file
+ done >one &&
+ for i in $ten
+ do
+ echo line $i in another sample file
+ done >two &&
+ git add one two &&
+ test_tick && git commit -m initial &&
+
+ git branch L1 &&
+ git checkout -b R1 &&
+ git mv one three &&
+ test_tick && git commit -m R1 &&
+
+ git checkout L1 &&
+ git mv two three &&
+ test_tick && git commit -m L1 &&
+
+ git checkout L1^0 &&
+ test_tick && git merge -s ours R1 &&
+ git tag L2 &&
+
+ git checkout R1^0 &&
+ test_tick && git merge -s ours L1 &&
+ git tag R2
+'
+
+test_expect_success merge '
+ git reset --hard &&
+ git checkout L2^0 &&
+
+ test_must_fail git merge -s recursive R2^0
+'
+
+test_done
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
new file mode 100755
index 0000000000..00e1de9627
--- /dev/null
+++ b/t/t6040-tracking-info.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+test_description='remote tracking stats'
+
+. ./test-lib.sh
+
+advance () {
+ echo "$1" >"$1" &&
+ git add "$1" &&
+ test_tick &&
+ git commit -m "$1"
+}
+
+test_expect_success setup '
+ for i in a b c;
+ do
+ advance $i || break
+ done &&
+ git clone . test &&
+ (
+ cd test &&
+ git checkout -b b1 origin &&
+ git reset --hard HEAD^ &&
+ advance d &&
+ git checkout -b b2 origin &&
+ git reset --hard b1 &&
+ git checkout -b b3 origin &&
+ git reset --hard HEAD^ &&
+ git checkout -b b4 origin &&
+ advance e &&
+ advance f
+ ) &&
+ git checkout -b follower --track master &&
+ advance g
+'
+
+script='s/^..\(b.\)[ 0-9a-f]*\[\([^]]*\)\].*/\1 \2/p'
+cat >expect <<\EOF
+b1 ahead 1, behind 1
+b2 ahead 1, behind 1
+b3 behind 1
+b4 ahead 2
+EOF
+
+test_expect_success 'branch -v' '
+ (
+ cd test &&
+ git branch -v
+ ) |
+ sed -n -e "$script" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'checkout' '
+ (
+ cd test && git checkout b1
+ ) >actual &&
+ grep "have 1 and 1 different" actual
+'
+
+test_expect_success 'checkout with local tracked branch' '
+ git checkout master &&
+ git checkout follower >actual
+ grep "is ahead of" actual
+'
+
+test_expect_success 'status' '
+ (
+ cd test &&
+ git checkout b1 >/dev/null &&
+ # reports nothing to commit
+ test_must_fail git status
+ ) >actual &&
+ grep "have 1 and 1 different" actual
+'
+
+test_expect_success 'status when tracking lightweight tags' '
+ git checkout master &&
+ git tag light &&
+ git branch --track lighttrack light >actual &&
+ grep "set up to track" actual &&
+ git checkout lighttrack
+'
+
+test_expect_success 'status when tracking annotated tags' '
+ git checkout master &&
+ git tag -m heavy heavy &&
+ git branch --track heavytrack heavy >actual &&
+ grep "set up to track" actual &&
+ git checkout heavytrack
+'
+test_done
diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh
new file mode 100755
index 0000000000..203ffdb17a
--- /dev/null
+++ b/t/t6050-replace.sh
@@ -0,0 +1,224 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Christian Couder
+#
+test_description='Tests replace refs functionality'
+
+exec </dev/null
+
+. ./test-lib.sh
+
+add_and_commit_file()
+{
+ _file="$1"
+ _msg="$2"
+
+ git add $_file || return $?
+ test_tick || return $?
+ git commit --quiet -m "$_file: $_msg"
+}
+
+HASH1=
+HASH2=
+HASH3=
+HASH4=
+HASH5=
+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 &&
+ 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 &&
+ 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 &&
+ add_and_commit_file hello "2 more lines" &&
+ HASH3=$(git rev-parse --verify HEAD) &&
+ 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 &&
+ 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 &&
+ 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 &&
+ add_and_commit_file hello "again 3 more lines" &&
+ HASH7=$(git rev-parse --verify HEAD)
+'
+
+test_expect_success 'replace the author' '
+ git cat-file commit $HASH2 | grep "author A U Thor" &&
+ R=$(git cat-file commit $HASH2 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) &&
+ git cat-file commit $R | grep "author O Thor" &&
+ git update-ref refs/replace/$HASH2 $R &&
+ git show HEAD~5 | grep "O Thor" &&
+ git show $HASH2 | grep "O Thor"
+'
+
+test_expect_success 'test --no-replace-objects option' '
+ git cat-file commit $HASH2 | grep "author O Thor" &&
+ git --no-replace-objects cat-file commit $HASH2 | grep "author A U Thor" &&
+ git show $HASH2 | grep "O Thor" &&
+ git --no-replace-objects show $HASH2 | grep "A U Thor"
+'
+
+test_expect_success 'test GIT_NO_REPLACE_OBJECTS env variable' '
+ GIT_NO_REPLACE_OBJECTS=1 git cat-file commit $HASH2 | grep "author A U Thor" &&
+ GIT_NO_REPLACE_OBJECTS=1 git show $HASH2 | grep "A U Thor"
+'
+
+cat >tag.sig <<EOF
+object $HASH2
+type commit
+tag mytag
+tagger T A Gger <> 0 +0000
+
+EOF
+
+test_expect_success 'tag replaced commit' '
+ git mktag <tag.sig >.git/refs/tags/mytag 2>message
+'
+
+test_expect_success '"git fsck" works' '
+ 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)"
+'
+
+test_expect_success 'repack, clone and fetch work' '
+ git repack -a -d &&
+ git clone --no-hardlinks . clone_dir &&
+ cd clone_dir &&
+ git show HEAD~5 | grep "A U Thor" &&
+ git show $HASH2 | grep "A U Thor" &&
+ git cat-file commit $R &&
+ git repack -a -d &&
+ test_must_fail git cat-file commit $R &&
+ git fetch ../ "refs/replace/*:refs/replace/*" &&
+ git show HEAD~5 | grep "O Thor" &&
+ git show $HASH2 | grep "O Thor" &&
+ git cat-file commit $R &&
+ cd ..
+'
+
+test_expect_success '"git replace" listing and deleting' '
+ test "$HASH2" = "$(git replace -l)" &&
+ test "$HASH2" = "$(git replace)" &&
+ aa=${HASH2%??????????????????????????????????????} &&
+ test "$HASH2" = "$(git replace -l "$aa*")" &&
+ test_must_fail git replace -d $R &&
+ test_must_fail git replace -d &&
+ test_must_fail git replace -l -d $HASH2 &&
+ git replace -d $HASH2 &&
+ git show $HASH2 | grep "A U Thor" &&
+ test -z "$(git replace -l)"
+'
+
+test_expect_success '"git replace" replacing' '
+ git replace $HASH2 $R &&
+ git show $HASH2 | grep "O Thor" &&
+ test_must_fail git replace $HASH2 $R &&
+ git replace -f $HASH2 $R &&
+ test_must_fail git replace -f &&
+ test "$HASH2" = "$(git replace)"
+'
+
+# This creates a side branch where the bug in H2
+# does not appear because P2 is created by applying
+# H2 and squashing H5 into it.
+# P3, P4 and P6 are created by cherry-picking H3, H4
+# and H6 respectively.
+#
+# At this point, we should have the following:
+#
+# P2--P3--P4--P6
+# /
+# H1-H2-H3-H4-H5-H6-H7
+#
+# Then we replace H6 with P6.
+#
+test_expect_success 'create parallel branch without the bug' '
+ git replace -d $HASH2 &&
+ git show $HASH2 | grep "A U Thor" &&
+ git checkout $HASH1 &&
+ git cherry-pick $HASH2 &&
+ git show $HASH5 | git apply &&
+ git commit --amend -m "hello: 4 more lines WITHOUT the bug" hello &&
+ PARA2=$(git rev-parse --verify HEAD) &&
+ git cherry-pick $HASH3 &&
+ PARA3=$(git rev-parse --verify HEAD) &&
+ git cherry-pick $HASH4 &&
+ PARA4=$(git rev-parse --verify HEAD) &&
+ git cherry-pick $HASH6 &&
+ PARA6=$(git rev-parse --verify HEAD) &&
+ git replace $HASH6 $PARA6 &&
+ git checkout master &&
+ cur=$(git rev-parse --verify HEAD) &&
+ test "$cur" = "$HASH7" &&
+ git log --pretty=oneline | grep $PARA2 &&
+ git remote add cloned ./clone_dir
+'
+
+test_expect_success 'push to cloned repo' '
+ git push cloned $HASH6^:refs/heads/parallel &&
+ cd clone_dir &&
+ git checkout parallel &&
+ git log --pretty=oneline | grep $PARA2 &&
+ cd ..
+'
+
+test_expect_success 'push branch with replacement' '
+ git cat-file commit $PARA3 | grep "author A U Thor" &&
+ S=$(git cat-file commit $PARA3 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) &&
+ git cat-file commit $S | grep "author O Thor" &&
+ git replace $PARA3 $S &&
+ git show $HASH6~2 | grep "O Thor" &&
+ git show $PARA3 | grep "O Thor" &&
+ git push cloned $HASH6^:refs/heads/parallel2 &&
+ cd clone_dir &&
+ git checkout parallel2 &&
+ git log --pretty=oneline | grep $PARA3 &&
+ git show $PARA3 | grep "A U Thor" &&
+ cd ..
+'
+
+test_expect_success 'fetch branch with replacement' '
+ git branch tofetch $HASH6 &&
+ cd clone_dir &&
+ git fetch origin refs/heads/tofetch:refs/heads/parallel3
+ git log --pretty=oneline parallel3 | grep $PARA3
+ git show $PARA3 | grep "A U Thor"
+ cd ..
+'
+
+test_expect_success 'bisect and replacements' '
+ git bisect start $HASH7 $HASH1 &&
+ test "$S" = "$(git rev-parse --verify HEAD)" &&
+ git bisect reset &&
+ GIT_NO_REPLACE_OBJECTS=1 git bisect start $HASH7 $HASH1 &&
+ test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
+ git bisect reset &&
+ git --no-replace-objects bisect start $HASH7 $HASH1 &&
+ test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
+ git bisect reset
+'
+
+#
+#
+test_done
diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh
index 2328b69947..f105fab98e 100755
--- a/t/t6101-rev-parse-parents.sh
+++ b/t/t6101-rev-parse-parents.sh
@@ -6,7 +6,7 @@
test_description='Test git rev-parse with different parent options'
. ./test-lib.sh
-. ../t6000lib.sh # t6xxx specific functions
+. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions
date >path0
git update-index --add path0
@@ -26,8 +26,10 @@ test_expect_success 'final^1^1^1 = final^^^' "test $(git rev-parse final^1^1^1)
test_expect_success 'final^1^2' "test $(git rev-parse start2) = $(git rev-parse final^1^2)"
test_expect_success 'final^1^2 != final^1^1' "test $(git rev-parse final^1^2) != $(git rev-parse final^1^1)"
test_expect_success 'final^1^3 not valid' "if git rev-parse --verify final^1^3; then false; else :; fi"
-test_expect_success '--verify start2^1' '! git rev-parse --verify start2^1'
+test_expect_success '--verify start2^1' 'test_must_fail git rev-parse --verify start2^1'
test_expect_success '--verify start2^0' 'git rev-parse --verify start2^0'
+test_expect_success 'final^1^@ = final^1^1 final^1^2' "test \"$(git rev-parse final^1^@)\" = \"$(git rev-parse final^1^1 final^1^2)\""
+test_expect_success 'final^1^! = final^1 ^final^1^1 ^final^1^2' "test \"$(git rev-parse final^1^\!)\" = \"$(git rev-parse final^1 ^final^1^1 ^final^1^2)\""
test_expect_success 'repack for next test' 'git repack -a -d'
test_expect_success 'short SHA-1 works' '
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 56bbd8519d..065deadc29 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -31,57 +31,59 @@ check_describe () {
test_expect_success setup '
test_tick &&
- echo one >file && git add file && git-commit -m initial &&
+ echo one >file && git add file && git commit -m initial &&
one=$(git rev-parse HEAD) &&
+ git describe --always HEAD &&
+
test_tick &&
- echo two >file && git add file && git-commit -m second &&
+ echo two >file && git add file && git commit -m second &&
two=$(git rev-parse HEAD) &&
test_tick &&
- echo three >file && git add file && git-commit -m third &&
+ echo three >file && git add file && git commit -m third &&
test_tick &&
- echo A >file && git add file && git-commit -m A &&
+ echo A >file && git add file && git commit -m A &&
test_tick &&
- git-tag -a -m A A &&
+ git tag -a -m A A &&
test_tick &&
- echo c >file && git add file && git-commit -m c &&
+ echo c >file && git add file && git commit -m c &&
test_tick &&
- git-tag c &&
+ git tag c &&
git reset --hard $two &&
test_tick &&
- echo B >side && git add side && git-commit -m B &&
+ echo B >side && git add side && git commit -m B &&
test_tick &&
- git-tag -a -m B B &&
+ git tag -a -m B B &&
test_tick &&
- git-merge -m Merged c &&
+ git merge -m Merged c &&
merged=$(git rev-parse HEAD) &&
git reset --hard $two &&
test_tick &&
- echo D >another && git add another && git-commit -m D &&
+ echo D >another && git add another && git commit -m D &&
test_tick &&
- git-tag -a -m D D &&
+ git tag -a -m D D &&
test_tick &&
echo DD >another && git commit -a -m another &&
test_tick &&
- git-tag e &&
+ git tag e &&
test_tick &&
echo DDD >another && git commit -a -m "yet another" &&
test_tick &&
- git-merge -m Merged $merged &&
+ git merge -m Merged $merged &&
test_tick &&
echo X >file && echo X >side && git add file side &&
- git-commit -m x
+ git commit -m x
'
@@ -90,16 +92,28 @@ check_describe A-* HEAD^
check_describe D-* HEAD^^
check_describe A-* HEAD^^2
check_describe B HEAD^^2^
+check_describe D-* HEAD^^^
-check_describe A-* --tags HEAD
-check_describe A-* --tags HEAD^
-check_describe D-* --tags HEAD^^
-check_describe A-* --tags HEAD^^2
+check_describe c-* --tags HEAD
+check_describe c-* --tags HEAD^
+check_describe e-* --tags HEAD^^
+check_describe c-* --tags HEAD^^2
check_describe B --tags HEAD^^2^
+check_describe e --tags HEAD^^^
+
+check_describe heads/master --all HEAD
+check_describe tags/c-* --all HEAD^
+check_describe tags/e --all HEAD^^^
check_describe B-0-* --long HEAD^^2^
check_describe A-3-* --long HEAD^^2
+: >err.expect
+check_describe A --all A^0
+test_expect_success 'no warning was displayed for A' '
+ test_cmp err.expect err.actual
+'
+
test_expect_success 'rename tag A to Q locally' '
mv .git/refs/tags/A .git/refs/tags/Q
'
@@ -108,7 +122,7 @@ warning: tag 'A' is really 'Q' here
EOF
check_describe A-* HEAD
test_expect_success 'warning was displayed for Q' '
- git diff err.expect err.actual
+ test_cmp err.expect err.actual
'
test_expect_success 'rename tag Q back to A' '
mv .git/refs/tags/Q .git/refs/tags/A
@@ -117,4 +131,42 @@ test_expect_success 'rename tag Q back to A' '
test_expect_success 'pack tag refs' 'git pack-refs'
check_describe A-* HEAD
+check_describe "A-*[0-9a-f]" --dirty
+
+test_expect_success 'set-up dirty work tree' '
+ echo >>file
+'
+
+check_describe "A-*[0-9a-f]-dirty" --dirty
+
+check_describe "A-*[0-9a-f].mod" --dirty=.mod
+
+test_expect_success 'describe --dirty HEAD' '
+ test_must_fail git describe --dirty HEAD
+'
+
+test_expect_success 'set-up matching pattern tests' '
+ git tag -a -m test-annotated test-annotated &&
+ echo >>file &&
+ test_tick &&
+ git commit -a -m "one more" &&
+ git tag test1-lightweight &&
+ echo >>file &&
+ test_tick &&
+ git commit -a -m "yet another" &&
+ git tag test2-lightweight &&
+ echo >>file &&
+ test_tick &&
+ git commit -a -m "even more"
+
+'
+
+check_describe "test-annotated-*" --match="test-*"
+
+check_describe "test1-lightweight-*" --tags --match="test1-*"
+
+check_describe "test2-lightweight-*" --tags --match="test2-*"
+
+check_describe "test2-lightweight-*" --long --tags --match="test2-*" HEAD^
+
test_done
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index 526d7d1c44..42f6fff373 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -79,20 +79,20 @@ test_expect_success 'merge-msg test #1' '
git fetch . left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- git diff actual expected
+ test_cmp expected actual
'
-cat >expected <<\EOF
-Merge branch 'left' of ../trash
+cat >expected <<EOF
+Merge branch 'left' of $(pwd)
EOF
test_expect_success 'merge-msg test #2' '
git checkout master &&
- git fetch ../trash left &&
+ git fetch "$(pwd)" left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- git diff actual expected
+ test_cmp expected actual
'
cat >expected <<\EOF
@@ -106,8 +106,24 @@ Merge branch 'left'
Common #1
EOF
-test_expect_success 'merge-msg test #3' '
+test_expect_success 'merge-msg test #3-1' '
+
+ git config --unset-all merge.log
+ git config --unset-all merge.summary
+ git config merge.log true &&
+
+ git checkout master &&
+ setdate &&
+ git fetch . left &&
+
+ git fmt-merge-msg <.git/FETCH_HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'merge-msg test #3-2' '
+ git config --unset-all merge.log
+ git config --unset-all merge.summary
git config merge.summary true &&
git checkout master &&
@@ -115,7 +131,7 @@ test_expect_success 'merge-msg test #3' '
git fetch . left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- git diff actual expected
+ test_cmp expected actual
'
cat >expected <<\EOF
@@ -136,8 +152,24 @@ Merge branches 'left' and 'right'
Common #1
EOF
-test_expect_success 'merge-msg test #4' '
+test_expect_success 'merge-msg test #4-1' '
+
+ git config --unset-all merge.log
+ git config --unset-all merge.summary
+ git config merge.log true &&
+ git checkout master &&
+ setdate &&
+ git fetch . left right &&
+
+ git fmt-merge-msg <.git/FETCH_HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'merge-msg test #4-2' '
+
+ git config --unset-all merge.log
+ git config --unset-all merge.summary
git config merge.summary true &&
git checkout master &&
@@ -145,11 +177,27 @@ test_expect_success 'merge-msg test #4' '
git fetch . left right &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- git diff actual expected
+ test_cmp expected actual
'
-test_expect_success 'merge-msg test #5' '
+test_expect_success 'merge-msg test #5-1' '
+
+ git config --unset-all merge.log
+ git config --unset-all merge.summary
+ git config merge.log yes &&
+ git checkout master &&
+ setdate &&
+ git fetch . left right &&
+
+ git fmt-merge-msg <.git/FETCH_HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'merge-msg test #5-2' '
+
+ git config --unset-all merge.log
+ git config --unset-all merge.summary
git config merge.summary yes &&
git checkout master &&
@@ -157,7 +205,39 @@ test_expect_success 'merge-msg test #5' '
git fetch . left right &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- git diff actual expected
+ test_cmp expected actual
+'
+
+test_expect_success 'merge-msg -F' '
+
+ git config --unset-all merge.log
+ git config --unset-all merge.summary
+ git config merge.summary yes &&
+
+ git checkout master &&
+ setdate &&
+ git fetch . left right &&
+
+ git fmt-merge-msg -F .git/FETCH_HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'merge-msg -F in subdirectory' '
+
+ git config --unset-all merge.log
+ git config --unset-all merge.summary
+ git config merge.summary yes &&
+
+ git checkout master &&
+ setdate &&
+ git fetch . left right &&
+ mkdir sub &&
+ cp .git/FETCH_HEAD sub/FETCH_HEAD &&
+ (
+ cd sub &&
+ git fmt-merge-msg -F FETCH_HEAD >../actual
+ ) &&
+ test_cmp expected actual
'
test_done
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index f46ec93c83..8052c86ad3 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -26,45 +26,107 @@ test_expect_success 'Create sample commit with known timestamp' '
git tag -a -m "Tagging at $datestamp" testtag
'
-test_expect_success 'Check atom names are valid' '
- bad=
- for token in \
- refname objecttype objectsize objectname tree parent \
- numparent object type author authorname authoremail \
- authordate committer committername committeremail \
- committerdate tag tagger taggername taggeremail \
- taggerdate creator creatordate subject body contents
- do
- git for-each-ref --format="$token=%($token)" refs/heads || {
- bad=$token
- break
- }
- done
- test -z "$bad"
+test_expect_success 'Create upstream config' '
+ git update-ref refs/remotes/origin/master master &&
+ git remote add origin nowhere &&
+ git config branch.master.remote origin &&
+ git config branch.master.merge refs/heads/master
+'
+
+test_atom() {
+ case "$1" in
+ head) ref=refs/heads/master ;;
+ tag) ref=refs/tags/testtag ;;
+ esac
+ printf '%s\n' "$3" >expected
+ test_expect_${4:-success} "basic atom: $1 $2" "
+ git for-each-ref --format='%($2)' $ref >actual &&
+ test_cmp expected actual
+ "
+}
+
+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 parent ''
+test_atom head numparent 0
+test_atom head object ''
+test_atom head type ''
+test_atom head author 'A U Thor <author@example.com> 1151939924 +0200'
+test_atom head authorname 'A U Thor'
+test_atom head authoremail '<author@example.com>'
+test_atom head authordate 'Mon Jul 3 17:18:44 2006 +0200'
+test_atom head committer 'C O Mitter <committer@example.com> 1151939923 +0200'
+test_atom head committername 'C O Mitter'
+test_atom head committeremail '<committer@example.com>'
+test_atom head committerdate 'Mon Jul 3 17:18:43 2006 +0200'
+test_atom head tag ''
+test_atom head tagger ''
+test_atom head taggername ''
+test_atom head taggeremail ''
+test_atom head taggerdate ''
+test_atom head creator 'C O Mitter <committer@example.com> 1151939923 +0200'
+test_atom head creatordate 'Mon Jul 3 17:18:43 2006 +0200'
+test_atom head subject 'Initial'
+test_atom head body ''
+test_atom head contents 'Initial
+'
+
+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 tree ''
+test_atom tag parent ''
+test_atom tag numparent ''
+test_atom tag object '67a36f10722846e891fbada1ba48ed035de75581'
+test_atom tag type 'commit'
+test_atom tag author ''
+test_atom tag authorname ''
+test_atom tag authoremail ''
+test_atom tag authordate ''
+test_atom tag committer ''
+test_atom tag committername ''
+test_atom tag committeremail ''
+test_atom tag committerdate ''
+test_atom tag tag 'testtag'
+test_atom tag tagger 'C O Mitter <committer@example.com> 1151939925 +0200'
+test_atom tag taggername 'C O Mitter'
+test_atom tag taggeremail '<committer@example.com>'
+test_atom tag taggerdate 'Mon Jul 3 17:18:45 2006 +0200'
+test_atom tag creator 'C O Mitter <committer@example.com> 1151939925 +0200'
+test_atom tag creatordate 'Mon Jul 3 17:18:45 2006 +0200'
+test_atom tag subject 'Tagging at 1151939927'
+test_atom tag body ''
+test_atom tag contents 'Tagging at 1151939927
'
test_expect_success 'Check invalid atoms names are errors' '
- ! git-for-each-ref --format="%(INVALID)" refs/heads
+ test_must_fail git for-each-ref --format="%(INVALID)" refs/heads
'
test_expect_success 'Check format specifiers are ignored in naming date atoms' '
- git-for-each-ref --format="%(authordate)" refs/heads &&
- git-for-each-ref --format="%(authordate:default) %(authordate)" refs/heads &&
- git-for-each-ref --format="%(authordate) %(authordate:default)" refs/heads &&
- git-for-each-ref --format="%(authordate:default) %(authordate:default)" refs/heads
+ git for-each-ref --format="%(authordate)" refs/heads &&
+ git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads &&
+ git for-each-ref --format="%(authordate) %(authordate:default)" refs/heads &&
+ git for-each-ref --format="%(authordate:default) %(authordate:default)" refs/heads
'
test_expect_success 'Check valid format specifiers for date fields' '
- git-for-each-ref --format="%(authordate:default)" refs/heads &&
- git-for-each-ref --format="%(authordate:relative)" refs/heads &&
- git-for-each-ref --format="%(authordate:short)" refs/heads &&
- git-for-each-ref --format="%(authordate:local)" refs/heads &&
- git-for-each-ref --format="%(authordate:iso8601)" refs/heads &&
- git-for-each-ref --format="%(authordate:rfc2822)" refs/heads
+ git for-each-ref --format="%(authordate:default)" refs/heads &&
+ git for-each-ref --format="%(authordate:relative)" refs/heads &&
+ git for-each-ref --format="%(authordate:short)" refs/heads &&
+ git for-each-ref --format="%(authordate:local)" refs/heads &&
+ git for-each-ref --format="%(authordate:iso8601)" refs/heads &&
+ git for-each-ref --format="%(authordate:rfc2822)" refs/heads
'
test_expect_success 'Check invalid format specifiers are errors' '
- ! git-for-each-ref --format="%(authordate:INVALID)" refs/heads
+ test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads
'
cat >expected <<\EOF
@@ -75,14 +137,14 @@ EOF
test_expect_success 'Check unformatted date fields output' '
(git for-each-ref --shell --format="%(refname) %(committerdate) %(authordate)" refs/heads &&
git for-each-ref --shell --format="%(refname) %(taggerdate)" refs/tags) >actual &&
- git diff expected actual
+ test_cmp expected actual
'
test_expect_success 'Check format "default" formatted date fields output' '
f=default &&
(git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- git diff expected actual
+ test_cmp expected actual
'
# Don't know how to do relative check because I can't know when this script
@@ -109,7 +171,7 @@ test_expect_success 'Check format "short" date fields output' '
f=short &&
(git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- git diff expected actual
+ test_cmp expected actual
'
cat >expected <<\EOF
@@ -121,7 +183,7 @@ test_expect_success 'Check format "local" date fields output' '
f=local &&
(git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- git diff expected actual
+ test_cmp expected actual
'
cat >expected <<\EOF
@@ -133,7 +195,7 @@ test_expect_success 'Check format "iso8601" date fields output' '
f=iso8601 &&
(git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- git diff expected actual
+ test_cmp expected actual
'
cat >expected <<\EOF
@@ -145,58 +207,62 @@ test_expect_success 'Check format "rfc2822" date fields output' '
f=rfc2822 &&
(git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- git diff expected actual
+ test_cmp expected actual
'
cat >expected <<\EOF
refs/heads/master
+refs/remotes/origin/master
refs/tags/testtag
EOF
test_expect_success 'Verify ascending sort' '
- git-for-each-ref --format="%(refname)" --sort=refname >actual &&
- git diff expected actual
+ git for-each-ref --format="%(refname)" --sort=refname >actual &&
+ test_cmp expected actual
'
cat >expected <<\EOF
refs/tags/testtag
+refs/remotes/origin/master
refs/heads/master
EOF
test_expect_success 'Verify descending sort' '
- git-for-each-ref --format="%(refname)" --sort=-refname >actual &&
- git diff expected actual
+ git for-each-ref --format="%(refname)" --sort=-refname >actual &&
+ test_cmp expected actual
'
cat >expected <<\EOF
'refs/heads/master'
+'refs/remotes/origin/master'
'refs/tags/testtag'
EOF
test_expect_success 'Quoting style: shell' '
git for-each-ref --shell --format="%(refname)" >actual &&
- git diff expected actual
+ test_cmp expected actual
'
test_expect_success 'Quoting style: perl' '
git for-each-ref --perl --format="%(refname)" >actual &&
- git diff expected actual
+ test_cmp expected actual
'
test_expect_success 'Quoting style: python' '
git for-each-ref --python --format="%(refname)" >actual &&
- git diff expected actual
+ test_cmp expected actual
'
cat >expected <<\EOF
"refs/heads/master"
+"refs/remotes/origin/master"
"refs/tags/testtag"
EOF
test_expect_success 'Quoting style: tcl' '
git for-each-ref --tcl --format="%(refname)" >actual &&
- git diff expected actual
+ test_cmp expected actual
'
for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
@@ -209,4 +275,79 @@ for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
"
done
+cat >expected <<\EOF
+master
+testtag
+EOF
+
+test_expect_success 'Check short refname format' '
+ (git for-each-ref --format="%(refname:short)" refs/heads &&
+ git for-each-ref --format="%(refname:short)" refs/tags) >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+origin/master
+EOF
+
+test_expect_success 'Check short upstream format' '
+ git for-each-ref --format="%(upstream:short)" refs/heads >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'Check for invalid refname format' '
+ test_must_fail git for-each-ref --format="%(refname:INVALID)"
+'
+
+cat >expected <<\EOF
+heads/master
+tags/master
+EOF
+
+test_expect_success 'Check ambiguous head and tag refs (strict)' '
+ git config --bool core.warnambiguousrefs true &&
+ git checkout -b newtag &&
+ echo "Using $datestamp" > one &&
+ git add one &&
+ git commit -m "Branch" &&
+ setdate_and_increment &&
+ git tag -m "Tagging at $datestamp" master &&
+ git for-each-ref --format "%(refname:short)" refs/heads/master refs/tags/master >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+heads/master
+master
+EOF
+
+test_expect_success 'Check ambiguous head and tag refs (loose)' '
+ git config --bool core.warnambiguousrefs false &&
+ git for-each-ref --format "%(refname:short)" refs/heads/master refs/tags/master >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+heads/ambiguous
+ambiguous
+EOF
+
+test_expect_success 'Check ambiguous head and tag refs II (loose)' '
+ git checkout master &&
+ git tag ambiguous testtag^0 &&
+ git branch ambiguous testtag^0 &&
+ git for-each-ref --format "%(refname:short)" refs/heads/ambiguous refs/tags/ambiguous >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'an unusual tag with an incomplete line' '
+
+ git tag -m "bogo" bogo &&
+ bogo=$(git cat-file tag bogo) &&
+ bogo=$(printf "%s" "$bogo" | git mktag) &&
+ git tag -f bogo "$bogo" &&
+ git for-each-ref --format "%(body)" refs/tags/bogo
+
+'
+
test_done
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index fa382c58da..10b8f8c44b 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -6,9 +6,9 @@ test_description='git mv in subdirs'
test_expect_success \
'prepare reference tree' \
'mkdir path0 path1 &&
- cp ../../COPYING path0/COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
git add path0/COPYING &&
- git-commit -m add -a'
+ git commit -m add -a'
test_expect_success \
'moving the file out of subdirectory' \
@@ -17,7 +17,7 @@ test_expect_success \
# in path0 currently
test_expect_success \
'commiting the change' \
- 'cd .. && git-commit -m move-out -a'
+ 'cd .. && git commit -m move-out -a'
test_expect_success \
'checking the commit' \
@@ -31,7 +31,7 @@ test_expect_success \
# in path0 currently
test_expect_success \
'commiting the change' \
- 'cd .. && git-commit -m move-in -a'
+ 'cd .. && git commit -m move-in -a'
test_expect_success \
'checking the commit' \
@@ -39,10 +39,43 @@ test_expect_success \
grep "^R100..*path1/COPYING..*path0/COPYING"'
test_expect_success \
+ 'checking -k on non-existing file' \
+ 'git mv -k idontexist path0'
+
+test_expect_success \
+ 'checking -k on untracked file' \
+ 'touch untracked1 &&
+ git mv -k untracked1 path0 &&
+ test -f untracked1 &&
+ test ! -f path0/untracked1'
+
+test_expect_success \
+ 'checking -k on multiple untracked files' \
+ 'touch untracked2 &&
+ git mv -k untracked1 untracked2 path0 &&
+ test -f untracked1 &&
+ test -f untracked2 &&
+ test ! -f path0/untracked1 &&
+ test ! -f path0/untracked2'
+
+test_expect_success \
+ 'checking -f on untracked file with existing target' \
+ 'touch path0/untracked1 &&
+ git mv -f untracked1 path0
+ test ! -f .git/index.lock &&
+ test -f untracked1 &&
+ test -f path0/untracked1'
+
+# clean up the mess in case bad things happen
+rm -f idontexist untracked1 untracked2 \
+ path0/idontexist path0/untracked1 path0/untracked2 \
+ .git/index.lock
+
+test_expect_success \
'adding another file' \
- 'cp ../../README path0/README &&
+ 'cp "$TEST_DIRECTORY"/../README path0/README &&
git add path0/README &&
- git-commit -m add2 -a'
+ git commit -m add2 -a'
test_expect_success \
'moving whole subdirectory' \
@@ -50,7 +83,7 @@ test_expect_success \
test_expect_success \
'commiting the change' \
- 'git-commit -m dir-move -a'
+ 'git commit -m dir-move -a'
test_expect_success \
'checking the commit' \
@@ -69,7 +102,7 @@ test_expect_success \
test_expect_success \
'commiting the change' \
- 'git-commit -m dir-move -a'
+ 'git commit -m dir-move -a'
test_expect_success \
'checking the commit' \
@@ -80,7 +113,7 @@ test_expect_success \
test_expect_success \
'do not move directory over existing directory' \
- 'mkdir path0 && mkdir path0/path2 && ! git mv path2 path0'
+ 'mkdir path0 && mkdir path0/path2 && test_must_fail git mv path2 path0'
test_expect_success \
'move into "."' \
@@ -149,11 +182,65 @@ test_expect_success 'absolute pathname outside should fail' '(
>sub/file &&
git add sub/file &&
- ! git mv sub "$out/out" &&
+ test_must_fail git mv sub "$out/out" &&
test -d sub &&
! test -d ../in &&
git ls-files --error-unmatch sub/file
)'
+test_expect_success 'git mv should not change sha1 of moved cache entry' '
+
+ rm -fr .git &&
+ git init &&
+ echo 1 >dirty &&
+ git add dirty &&
+ entry="$(git ls-files --stage dirty | cut -f 1)"
+ git mv dirty dirty2 &&
+ [ "$entry" = "$(git ls-files --stage dirty2 | cut -f 1)" ] &&
+ echo 2 >dirty2 &&
+ git mv dirty2 dirty &&
+ [ "$entry" = "$(git ls-files --stage dirty | cut -f 1)" ]
+
+'
+
+rm -f dirty dirty2
+
+test_expect_success SYMLINKS 'git mv should overwrite symlink to a file' '
+
+ rm -fr .git &&
+ git init &&
+ echo 1 >moved &&
+ ln -s moved symlink &&
+ git add moved symlink &&
+ test_must_fail git mv moved symlink &&
+ git mv -f moved symlink &&
+ ! test -e moved &&
+ test -f symlink &&
+ test "$(cat symlink)" = 1 &&
+ git update-index --refresh &&
+ git diff-files --quiet
+
+'
+
+rm -f moved symlink
+
+test_expect_success SYMLINKS 'git mv should overwrite file with a symlink' '
+
+ rm -fr .git &&
+ git init &&
+ echo 1 >moved &&
+ ln -s moved symlink &&
+ git add moved symlink &&
+ test_must_fail git mv symlink moved &&
+ git mv -f symlink moved &&
+ ! test -e symlink &&
+ test -h moved &&
+ git update-index --refresh &&
+ git diff-files --quiet
+
+'
+
+rm -f moved symlink
+
test_done
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index c8b4f65f38..abd14bf819 100755
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
@@ -8,6 +8,16 @@ test_description='git grep various.
. ./test-lib.sh
+cat >hello.c <<EOF
+#include <stdio.h>
+int main(int argc, const char **argv)
+{
+ printf("Hello world.\n");
+ return 0;
+ /* char ?? */
+}
+EOF
+
test_expect_success setup '
{
echo foo mmap bar
@@ -16,15 +26,25 @@ test_expect_success setup '
echo foo mmap bar_mmap
echo foo_mmap bar mmap baz
} >file &&
+ echo vvv >v &&
+ echo ww w >w &&
echo x x xx x >x &&
echo y yy >y &&
echo zzz > z &&
mkdir t &&
echo test >t/t &&
- git add file x y z t/t &&
+ echo vvv >t/v &&
+ mkdir t/a &&
+ echo vvv >t/a/v &&
+ git add . &&
+ test_tick &&
git commit -m initial
'
+test_expect_success 'grep should not segfault with a bad input' '
+ test_must_fail git grep "("
+'
+
for H in HEAD ''
do
case "$H" in
@@ -43,6 +63,12 @@ do
diff expected actual
'
+ test_expect_success "grep -w $L (w)" '
+ : >expected &&
+ ! git grep -n -w -e "^w" >actual &&
+ test_cmp expected actual
+ '
+
test_expect_success "grep -w $L (x)" '
{
echo ${HC}x:1:x x xx x
@@ -108,9 +134,296 @@ do
'
test_expect_success "grep -c $L (no /dev/null)" '
- ! git grep -c test $H | grep -q /dev/null
+ ! git grep -c test $H | grep /dev/null
'
+ test_expect_success "grep --max-depth -1 $L" '
+ {
+ echo ${HC}t/a/v:1:vvv
+ echo ${HC}t/v:1:vvv
+ echo ${HC}v:1:vvv
+ } >expected &&
+ git grep --max-depth -1 -n -e vvv $H >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "grep --max-depth 0 $L" '
+ {
+ echo ${HC}v:1:vvv
+ } >expected &&
+ git grep --max-depth 0 -n -e vvv $H >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "grep --max-depth 0 -- '*' $L" '
+ {
+ echo ${HC}t/a/v:1:vvv
+ echo ${HC}t/v:1:vvv
+ echo ${HC}v:1:vvv
+ } >expected &&
+ git grep --max-depth 0 -n -e vvv $H -- "*" >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "grep --max-depth 1 $L" '
+ {
+ echo ${HC}t/v:1:vvv
+ echo ${HC}v:1:vvv
+ } >expected &&
+ git grep --max-depth 1 -n -e vvv $H >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "grep --max-depth 0 -- t $L" '
+ {
+ echo ${HC}t/v:1:vvv
+ } >expected &&
+ git grep --max-depth 0 -n -e vvv $H -- t >actual &&
+ test_cmp expected actual
+ '
+
done
+cat >expected <<EOF
+file:foo mmap bar_mmap
+EOF
+
+test_expect_success 'grep -e A --and -e B' '
+ git grep -e "foo mmap" --and -e bar_mmap >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+file:foo_mmap bar mmap
+file:foo_mmap bar mmap baz
+EOF
+
+
+test_expect_success 'grep ( -e A --or -e B ) --and -e B' '
+ git grep \( -e foo_ --or -e baz \) \
+ --and -e " mmap" >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+EOF
+
+test_expect_success 'grep -e A --and --not -e B' '
+ git grep -e "foo mmap" --and --not -e bar_mmap >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'grep should ignore GREP_OPTIONS' '
+ GREP_OPTIONS=-v git grep " mmap bar\$" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'grep -f, non-existent file' '
+ test_must_fail git grep -f patterns
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+file:foo_mmap bar
+file:foo_mmap bar mmap
+file:foo mmap bar_mmap
+file:foo_mmap bar mmap baz
+EOF
+
+cat >pattern <<EOF
+mmap
+EOF
+
+test_expect_success 'grep -f, one pattern' '
+ git grep -f pattern >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+file:foo_mmap bar
+file:foo_mmap bar mmap
+file:foo mmap bar_mmap
+file:foo_mmap bar mmap baz
+t/a/v:vvv
+t/v:vvv
+v:vvv
+EOF
+
+cat >patterns <<EOF
+mmap
+vvv
+EOF
+
+test_expect_success 'grep -f, multiple patterns' '
+ git grep -f patterns >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+file:foo mmap bar
+file:foo_mmap bar
+file:foo_mmap bar mmap
+file:foo mmap bar_mmap
+file:foo_mmap bar mmap baz
+t/a/v:vvv
+t/v:vvv
+v:vvv
+EOF
+
+cat >patterns <<EOF
+
+mmap
+
+vvv
+
+EOF
+
+test_expect_success 'grep -f, ignore empty lines' '
+ git grep -f patterns >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+y:y yy
+--
+z:zzz
+EOF
+
+# Create 1024 file names that sort between "y" and "z" to make sure
+# the two files are handled by different calls to an external grep.
+# This depends on MAXARGS in builtin-grep.c being 1024 or less.
+c32="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v"
+test_expect_success 'grep -C1, hunk mark between files' '
+ for a in $c32; do for b in $c32; do : >y-$a$b; done; done &&
+ git add y-?? &&
+ git grep -C1 "^[yz]" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'grep -C1 --no-ext-grep, hunk mark between files' '
+ git grep -C1 --no-ext-grep "^[yz]" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'log grep setup' '
+ echo a >>file &&
+ test_tick &&
+ GIT_AUTHOR_NAME="With * Asterisk" \
+ GIT_AUTHOR_EMAIL="xyzzy@frotz.com" \
+ git commit -a -m "second" &&
+
+ echo a >>file &&
+ test_tick &&
+ git commit -a -m "third"
+
+'
+
+test_expect_success 'log grep (1)' '
+ git log --author=author --pretty=tformat:%s >actual &&
+ ( echo third ; echo initial ) >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log grep (2)' '
+ git log --author=" * " -F --pretty=tformat:%s >actual &&
+ ( echo second ) >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log grep (3)' '
+ git log --author="^A U" --pretty=tformat:%s >actual &&
+ ( echo third ; echo initial ) >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log grep (4)' '
+ git log --author="frotz\.com>$" --pretty=tformat:%s >actual &&
+ ( echo second ) >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log grep (5)' '
+ git log --author=Thor -F --grep=Thu --pretty=tformat:%s >actual &&
+ ( echo third ; echo initial ) >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log grep (6)' '
+ git log --author=-0700 --pretty=tformat:%s >actual &&
+ >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'grep with CE_VALID file' '
+ git update-index --assume-unchanged t/t &&
+ rm t/t &&
+ test "$(git grep --no-ext-grep test)" = "t/t:test" &&
+ git update-index --no-assume-unchanged t/t &&
+ git checkout t/t
+'
+
+cat >expected <<EOF
+hello.c=#include <stdio.h>
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -p with userdiff' '
+ git config diff.custom.funcname "^#" &&
+ echo "hello.c diff=custom" >.gitattributes &&
+ git grep -p return >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c=int main(int argc, const char **argv)
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -p' '
+ rm -f .gitattributes &&
+ git grep -p return >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- printf("Hello world.\n");
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -p -B5' '
+ git grep -p -B5 return >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'grep from a subdirectory to search wider area (1)' '
+ mkdir -p s &&
+ (
+ cd s && git grep "x x x" ..
+ )
+'
+
+test_expect_success 'grep from a subdirectory to search wider area (2)' '
+ mkdir -p s &&
+ (
+ cd s || exit 1
+ ( git grep xxyyzz .. >out ; echo $? >status )
+ ! test -s out &&
+ test 1 = $(cat status)
+ )
+'
+
+cat >expected <<EOF
+hello.c:int main(int argc, const char **argv)
+EOF
+
+test_expect_success 'grep -Fi' '
+ git grep -Fi "CHAR *" >actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index 16df3d4adb..9503875e97 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-filter-branch'
+test_description='git filter-branch'
. ./test-lib.sh
make_commit () {
@@ -32,14 +32,40 @@ test_expect_success 'setup' '
H=$(git rev-parse H)
test_expect_success 'rewrite identically' '
- git-filter-branch branch
+ git filter-branch branch
'
test_expect_success 'result is really identical' '
test $H = $(git rev-parse HEAD)
'
+test_expect_success 'rewrite bare repository identically' '
+ (git config core.bare true && cd .git &&
+ git filter-branch branch > filter-output 2>&1 &&
+ ! fgrep fatal filter-output)
+'
+git config core.bare false
+test_expect_success 'result is really identical' '
+ test $H = $(git rev-parse HEAD)
+'
+
+TRASHDIR=$(pwd)
+test_expect_success 'correct GIT_DIR while using -d' '
+ mkdir drepo &&
+ ( cd drepo &&
+ git init &&
+ test_commit drepo &&
+ git filter-branch -d "$TRASHDIR/dfoo" \
+ --index-filter "cp \"$TRASHDIR\"/dfoo/backup-refs \"$TRASHDIR\"" \
+ ) &&
+ grep drepo "$TRASHDIR/backup-refs"
+'
+
+test_expect_success 'Fail if commit filter fails' '
+ test_must_fail git filter-branch -f --commit-filter "exit 1" HEAD
+'
+
test_expect_success 'rewrite, renaming a specific file' '
- git-filter-branch -f --tree-filter "mv d doh || :" HEAD
+ git filter-branch -f --tree-filter "mv d doh || :" HEAD
'
test_expect_success 'test that the file was renamed' '
@@ -50,7 +76,7 @@ test_expect_success 'test that the file was renamed' '
'
test_expect_success 'rewrite, renaming a specific directory' '
- git-filter-branch -f --tree-filter "mv dir diroh || :" HEAD
+ git filter-branch -f --tree-filter "mv dir diroh || :" HEAD
'
test_expect_success 'test that the directory was renamed' '
@@ -65,7 +91,7 @@ test_expect_success 'test that the directory was renamed' '
git tag oldD HEAD~4
test_expect_success 'rewrite one branch, keeping a side branch' '
git branch modD oldD &&
- git-filter-branch -f --tree-filter "mv b boh || :" D..modD
+ git filter-branch -f --tree-filter "mv b boh || :" D..modD
'
test_expect_success 'common ancestor is still common (unchanged)' '
@@ -88,16 +114,20 @@ test_expect_success 'filter subdirectory only' '
test_tick &&
git commit -m "again not subdir" &&
git branch sub &&
- git-filter-branch -f --subdirectory-filter subdir refs/heads/sub
+ git branch sub-earlier HEAD~2 &&
+ git filter-branch -f --subdirectory-filter subdir \
+ refs/heads/sub refs/heads/sub-earlier
'
test_expect_success 'subdirectory filter result looks okay' '
test 2 = $(git rev-list sub | wc -l) &&
git show sub:new &&
- test_must_fail git show sub:subdir
+ test_must_fail git show sub:subdir &&
+ git show sub-earlier:new &&
+ test_must_fail git show sub-earlier:subdir
'
-test_expect_success 'setup and filter history that requires --full-history' '
+test_expect_success 'more setup' '
git checkout master &&
mkdir subdir &&
echo A > subdir/new &&
@@ -107,30 +137,21 @@ test_expect_success 'setup and filter history that requires --full-history' '
git rm a &&
test_tick &&
git commit -m "again subdir on master" &&
- git merge branch &&
- git branch sub-master &&
- git-filter-branch -f --subdirectory-filter subdir sub-master
-'
-
-test_expect_success 'subdirectory filter result looks okay' '
- test 3 = $(git rev-list -1 --parents sub-master | wc -w) &&
- git show sub-master^:new &&
- git show sub-master^2:new &&
- test_must_fail git show sub:subdir
+ git merge branch
'
test_expect_success 'use index-filter to move into a subdirectory' '
git branch directorymoved &&
- git-filter-branch -f --index-filter \
+ git filter-branch -f --index-filter \
"git ls-files -s | sed \"s-\\t-&newsubdir/-\" |
GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \
git update-index --index-info &&
- mv \$GIT_INDEX_FILE.new \$GIT_INDEX_FILE" directorymoved &&
+ mv \"\$GIT_INDEX_FILE.new\" \"\$GIT_INDEX_FILE\"" directorymoved &&
test -z "$(git diff HEAD directorymoved:newsubdir)"'
test_expect_success 'stops when msg filter fails' '
old=$(git rev-parse HEAD) &&
- test_must_fail git-filter-branch -f --msg-filter false HEAD &&
+ test_must_fail git filter-branch -f --msg-filter false HEAD &&
test $old = $(git rev-parse HEAD) &&
rm -rf .git-rewrite
'
@@ -141,7 +162,7 @@ test_expect_success 'author information is preserved' '
test_tick &&
GIT_AUTHOR_NAME="B V Uips" git commit -m bvuips &&
git branch preserved-author &&
- git-filter-branch -f --msg-filter "cat; \
+ git filter-branch -f --msg-filter "cat; \
test \$GIT_COMMIT != $(git rev-parse master) || \
echo Hallo" \
preserved-author &&
@@ -153,7 +174,7 @@ test_expect_success "remove a certain author's commits" '
test_tick &&
git commit -m i i &&
git branch removed-author &&
- git-filter-branch -f --commit-filter "\
+ git filter-branch -f --commit-filter "\
if [ \"\$GIT_AUTHOR_NAME\" = \"B V Uips\" ];\
then\
skip_commit \"\$@\";
@@ -224,7 +245,7 @@ test_expect_success 'Tag name filtering retains tag message' '
git cat-file tag T > expect &&
git filter-branch -f --tag-name-filter cat &&
git cat-file tag T > actual &&
- git diff expect actual
+ test_cmp expect actual
'
faux_gpg_tag='object XXXXXX
@@ -248,7 +269,41 @@ test_expect_success 'Tag name filtering strips gpg signature' '
echo "$faux_gpg_tag" | sed -e s/XXXXXX/$sha1/ | head -n 6 > expect &&
git filter-branch -f --tag-name-filter cat &&
git cat-file tag S > actual &&
- git diff expect actual
+ test_cmp expect actual
+'
+
+test_expect_success 'Tag name filtering allows slashes in tag names' '
+ git tag -m tag-with-slash X/1 &&
+ git cat-file tag X/1 | sed -e s,X/1,X/2, > expect &&
+ git filter-branch -f --tag-name-filter "echo X/2" &&
+ git cat-file tag X/2 > actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Prune empty commits' '
+ git rev-list HEAD > expect &&
+ make_commit to_remove &&
+ git filter-branch -f --index-filter "git update-index --remove to_remove" --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 &&
+ test_commit add-foo foo 1 &&
+ git branch moved-foo &&
+ test_commit add-bar bar a &&
+ git branch invariant &&
+ orig_invariant=$(git rev-parse invariant) &&
+ git branch moved-bar &&
+ test_commit change-foo foo 2 &&
+ git filter-branch -f --remap-to-ancestor \
+ moved-foo moved-bar A..master \
+ -- -- foo &&
+ test $(git rev-parse moved-foo) = $(git rev-parse moved-bar) &&
+ test $(git rev-parse moved-foo) = $(git rev-parse master^) &&
+ test $orig_invariant = $(git rev-parse invariant)
'
test_done
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 1a7141ecd7..73dbc4360b 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2007 Carlos Rica
#
-test_description='git-tag
+test_description='git tag
Tests for operations with tags.'
@@ -22,25 +22,25 @@ test_expect_success 'listing all tags in an empty tree should succeed' '
'
test_expect_success 'listing all tags in an empty tree should output nothing' '
- test `git-tag -l | wc -l` -eq 0 &&
- test `git-tag | wc -l` -eq 0
+ test `git tag -l | wc -l` -eq 0 &&
+ test `git tag | wc -l` -eq 0
'
test_expect_success 'looking for a tag in an empty tree should fail' \
'! (tag_exists mytag)'
test_expect_success 'creating a tag in an empty tree should fail' '
- ! git-tag mynotag &&
+ test_must_fail git tag mynotag &&
! tag_exists mynotag
'
test_expect_success 'creating a tag for HEAD in an empty tree should fail' '
- ! git-tag mytaghead HEAD &&
+ test_must_fail git tag mytaghead HEAD &&
! tag_exists mytaghead
'
test_expect_success 'creating a tag for an unknown revision should fail' '
- ! git-tag mytagnorev aaaaaaaaaaa &&
+ test_must_fail git tag mytagnorev aaaaaaaaaaa &&
! tag_exists mytagnorev
'
@@ -54,48 +54,48 @@ test_expect_success 'creating a tag using default HEAD should succeed' '
'
test_expect_success 'listing all tags if one exists should succeed' '
- git-tag -l &&
- git-tag
+ git tag -l &&
+ git tag
'
test_expect_success 'listing all tags if one exists should output that tag' '
- test `git-tag -l` = mytag &&
- test `git-tag` = mytag
+ test `git tag -l` = mytag &&
+ test `git tag` = mytag
'
# pattern matching:
test_expect_success 'listing a tag using a matching pattern should succeed' \
- 'git-tag -l mytag'
+ 'git tag -l mytag'
test_expect_success \
'listing a tag using a matching pattern should output that tag' \
- 'test `git-tag -l mytag` = mytag'
+ 'test `git tag -l mytag` = mytag'
# todo: git tag -l now returns always zero, when fixed, change this test
test_expect_success \
'listing tags using a non-matching pattern should suceed' \
- 'git-tag -l xxx'
+ 'git tag -l xxx'
test_expect_success \
'listing tags using a non-matching pattern should output nothing' \
- 'test `git-tag -l xxx | wc -l` -eq 0'
+ 'test `git tag -l xxx | wc -l` -eq 0'
# special cases for creating tags:
test_expect_success \
'trying to create a tag with the name of one existing should fail' \
- '! git tag mytag'
+ 'test_must_fail git tag mytag'
test_expect_success \
'trying to create a tag with a non-valid name should fail' '
- test `git-tag -l | wc -l` -eq 1 &&
- ! git tag "" &&
- ! git tag .othertag &&
- ! git tag "other tag" &&
- ! git tag "othertag^" &&
- ! git tag "other~tag" &&
- test `git-tag -l | wc -l` -eq 1
+ test `git tag -l | wc -l` -eq 1 &&
+ test_must_fail git tag "" &&
+ test_must_fail git tag .othertag &&
+ test_must_fail git tag "other tag" &&
+ test_must_fail git tag "othertag^" &&
+ test_must_fail git tag "other~tag" &&
+ test `git tag -l | wc -l` -eq 1
'
test_expect_success 'creating a tag using HEAD directly should succeed' '
@@ -107,7 +107,7 @@ test_expect_success 'creating a tag using HEAD directly should succeed' '
test_expect_success 'trying to delete an unknown tag should fail' '
! tag_exists unknown-tag &&
- ! git-tag -d unknown-tag
+ test_must_fail git tag -d unknown-tag
'
cat >expect <<EOF
@@ -116,16 +116,16 @@ mytag
EOF
test_expect_success \
'trying to delete tags without params should succeed and do nothing' '
- git tag -l > actual && git diff expect actual &&
- git-tag -d &&
- git tag -l > actual && git diff expect actual
+ git tag -l > actual && test_cmp expect actual &&
+ git tag -d &&
+ git tag -l > actual && test_cmp expect actual
'
test_expect_success \
'deleting two existing tags in one command should succeed' '
tag_exists mytag &&
tag_exists myhead &&
- git-tag -d mytag myhead &&
+ git tag -d mytag myhead &&
! tag_exists mytag &&
! tag_exists myhead
'
@@ -133,7 +133,7 @@ test_expect_success \
test_expect_success \
'creating a tag with the name of another deleted one should succeed' '
! tag_exists mytag &&
- git-tag mytag &&
+ git tag mytag &&
tag_exists mytag
'
@@ -141,13 +141,13 @@ test_expect_success \
'trying to delete two tags, existing and not, should fail in the 2nd' '
tag_exists mytag &&
! tag_exists myhead &&
- ! git-tag -d mytag anothertag &&
+ test_must_fail git tag -d mytag anothertag &&
! tag_exists mytag &&
! tag_exists myhead
'
test_expect_success 'trying to delete an already deleted tag should fail' \
- '! git-tag -d mytag'
+ 'test_must_fail git tag -d mytag'
# listing various tags with pattern matching:
@@ -173,9 +173,9 @@ test_expect_success 'listing all tags should print them ordered' '
git tag v1.0 &&
git tag t210 &&
git tag -l > actual &&
- git diff expect actual &&
+ test_cmp expect actual &&
git tag > actual &&
- git diff expect actual
+ test_cmp expect actual
'
cat >expect <<EOF
@@ -185,8 +185,9 @@ cba
EOF
test_expect_success \
'listing tags with substring as pattern must print those matching' '
- git-tag -l "*a*" > actual &&
- git diff expect actual
+ rm *a* &&
+ git tag -l "*a*" > current &&
+ test_cmp expect current
'
cat >expect <<EOF
@@ -195,8 +196,8 @@ v1.0.1
EOF
test_expect_success \
'listing tags with a suffix as pattern must print those matching' '
- git-tag -l "*.1" > actual &&
- git diff expect actual
+ git tag -l "*.1" > actual &&
+ test_cmp expect actual
'
cat >expect <<EOF
@@ -205,8 +206,8 @@ t211
EOF
test_expect_success \
'listing tags with a prefix as pattern must print those matching' '
- git-tag -l "t21*" > actual &&
- git diff expect actual
+ git tag -l "t21*" > actual &&
+ test_cmp expect actual
'
cat >expect <<EOF
@@ -214,8 +215,8 @@ a1
EOF
test_expect_success \
'listing tags using a name as pattern must print that one matching' '
- git-tag -l a1 > actual &&
- git diff expect actual
+ git tag -l a1 > actual &&
+ test_cmp expect actual
'
cat >expect <<EOF
@@ -223,8 +224,8 @@ v1.0
EOF
test_expect_success \
'listing tags using a name as pattern must print that one matching' '
- git-tag -l v1.0 > actual &&
- git diff expect actual
+ git tag -l v1.0 > actual &&
+ test_cmp expect actual
'
cat >expect <<EOF
@@ -233,15 +234,15 @@ v1.1.3
EOF
test_expect_success \
'listing tags with ? in the pattern should print those matching' '
- git-tag -l "v1.?.?" > actual &&
- git diff expect actual
+ git tag -l "v1.?.?" > actual &&
+ test_cmp expect actual
'
>expect
test_expect_success \
'listing tags using v.* should print nothing because none have v.' '
- git-tag -l "v.*" > actual &&
- git diff expect actual
+ git tag -l "v.*" > actual &&
+ test_cmp expect actual
'
cat >expect <<EOF
@@ -252,29 +253,29 @@ v1.1.3
EOF
test_expect_success \
'listing tags using v* should print only those having v' '
- git-tag -l "v*" > actual &&
- git diff expect actual
+ git tag -l "v*" > actual &&
+ test_cmp expect actual
'
# creating and verifying lightweight tags:
test_expect_success \
'a non-annotated tag created without parameters should point to HEAD' '
- git-tag non-annotated-tag &&
+ git tag non-annotated-tag &&
test $(git cat-file -t non-annotated-tag) = commit &&
test $(git rev-parse non-annotated-tag) = $(git rev-parse HEAD)
'
test_expect_success 'trying to verify an unknown tag should fail' \
- '! git-tag -v unknown-tag'
+ 'test_must_fail git tag -v unknown-tag'
test_expect_success \
'trying to verify a non-annotated and non-signed tag should fail' \
- '! git-tag -v non-annotated-tag'
+ 'test_must_fail git tag -v non-annotated-tag'
test_expect_success \
'trying to verify many non-annotated or unknown tags, should fail' \
- '! git-tag -v unknown-tag1 non-annotated-tag unknown-tag2'
+ 'test_must_fail git tag -v unknown-tag1 non-annotated-tag unknown-tag2'
# creating annotated tags:
@@ -300,9 +301,9 @@ get_tag_header annotated-tag $commit commit $time >expect
echo "A message" >>expect
test_expect_success \
'creating an annotated tag with -m message should succeed' '
- git-tag -m "A message" annotated-tag &&
+ git tag -m "A message" annotated-tag &&
get_tag_msg annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
cat >msgfile <<EOF
@@ -313,9 +314,9 @@ get_tag_header file-annotated-tag $commit commit $time >expect
cat msgfile >>expect
test_expect_success \
'creating an annotated tag with -F messagefile should succeed' '
- git-tag -F msgfile file-annotated-tag &&
+ git tag -F msgfile file-annotated-tag &&
get_tag_msg file-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
cat >inputmsg <<EOF
@@ -325,16 +326,16 @@ EOF
get_tag_header stdin-annotated-tag $commit commit $time >expect
cat inputmsg >>expect
test_expect_success 'creating an annotated tag with -F - should succeed' '
- git-tag -F - stdin-annotated-tag <inputmsg &&
+ git tag -F - stdin-annotated-tag <inputmsg &&
get_tag_msg stdin-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
test_expect_success \
'trying to create a tag with a non-existing -F file should fail' '
! test -f nonexistingfile &&
! tag_exists notag &&
- ! git-tag -F nonexistingfile notag &&
+ test_must_fail git tag -F nonexistingfile notag &&
! tag_exists notag
'
@@ -343,11 +344,12 @@ test_expect_success \
echo "message file 1" >msgfile1 &&
echo "message file 2" >msgfile2 &&
! tag_exists msgtag &&
- ! git-tag -m "message 1" -F msgfile1 msgtag &&
+ test_must_fail git tag -m "message 1" -F msgfile1 msgtag &&
! tag_exists msgtag &&
- ! git-tag -F msgfile1 -m "message 1" msgtag &&
+ test_must_fail git tag -F msgfile1 -m "message 1" msgtag &&
! tag_exists msgtag &&
- ! git-tag -m "message 1" -F msgfile1 -m "message 2" msgtag &&
+ test_must_fail git tag -m "message 1" -F msgfile1 \
+ -m "message 2" msgtag &&
! tag_exists msgtag
'
@@ -356,18 +358,18 @@ test_expect_success \
get_tag_header empty-annotated-tag $commit commit $time >expect
test_expect_success \
'creating a tag with an empty -m message should succeed' '
- git-tag -m "" empty-annotated-tag &&
+ git tag -m "" empty-annotated-tag &&
get_tag_msg empty-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
>emptyfile
get_tag_header emptyfile-annotated-tag $commit commit $time >expect
test_expect_success \
'creating a tag with an empty -F messagefile should succeed' '
- git-tag -F emptyfile emptyfile-annotated-tag &&
+ git tag -F emptyfile emptyfile-annotated-tag &&
get_tag_msg emptyfile-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
printf '\n\n \n\t\nLeading blank lines\n' >blanksfile
@@ -386,17 +388,17 @@ Trailing blank lines
EOF
test_expect_success \
'extra blanks in the message for an annotated tag should be removed' '
- git-tag -F blanksfile blanks-annotated-tag &&
+ git tag -F blanksfile blanks-annotated-tag &&
get_tag_msg blanks-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
get_tag_header blank-annotated-tag $commit commit $time >expect
test_expect_success \
'creating a tag with blank -m message with spaces should succeed' '
- git-tag -m " " blank-annotated-tag &&
+ git tag -m " " blank-annotated-tag &&
get_tag_msg blank-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
echo ' ' >blankfile
@@ -405,18 +407,18 @@ echo ' ' >>blankfile
get_tag_header blankfile-annotated-tag $commit commit $time >expect
test_expect_success \
'creating a tag with blank -F messagefile with spaces should succeed' '
- git-tag -F blankfile blankfile-annotated-tag &&
+ git tag -F blankfile blankfile-annotated-tag &&
get_tag_msg blankfile-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
printf ' ' >blanknonlfile
get_tag_header blanknonlfile-annotated-tag $commit commit $time >expect
test_expect_success \
'creating a tag with -F file of spaces and no newline should succeed' '
- git-tag -F blanknonlfile blanknonlfile-annotated-tag &&
+ git tag -F blanknonlfile blanknonlfile-annotated-tag &&
get_tag_msg blanknonlfile-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
# messages with commented lines:
@@ -449,17 +451,17 @@ Last line.
EOF
test_expect_success \
'creating a tag using a -F messagefile with #comments should succeed' '
- git-tag -F commentsfile comments-annotated-tag &&
+ git tag -F commentsfile comments-annotated-tag &&
get_tag_msg comments-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
get_tag_header comment-annotated-tag $commit commit $time >expect
test_expect_success \
'creating a tag with a #comment in the -m message should succeed' '
- git-tag -m "#comment" comment-annotated-tag &&
+ git tag -m "#comment" comment-annotated-tag &&
get_tag_msg comment-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
echo '#comment' >commentfile
@@ -468,70 +470,70 @@ echo '####' >>commentfile
get_tag_header commentfile-annotated-tag $commit commit $time >expect
test_expect_success \
'creating a tag with #comments in the -F messagefile should succeed' '
- git-tag -F commentfile commentfile-annotated-tag &&
+ git tag -F commentfile commentfile-annotated-tag &&
get_tag_msg commentfile-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
printf '#comment' >commentnonlfile
get_tag_header commentnonlfile-annotated-tag $commit commit $time >expect
test_expect_success \
'creating a tag with a file of #comment and no newline should succeed' '
- git-tag -F commentnonlfile commentnonlfile-annotated-tag &&
+ git tag -F commentnonlfile commentnonlfile-annotated-tag &&
get_tag_msg commentnonlfile-annotated-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
# listing messages for annotated non-signed tags:
test_expect_success \
'listing the one-line message of a non-signed tag should succeed' '
- git-tag -m "A msg" tag-one-line &&
+ git tag -m "A msg" tag-one-line &&
echo "tag-one-line" >expect &&
- git-tag -l | grep "^tag-one-line" >actual &&
- git diff expect actual &&
- git-tag -n0 -l | grep "^tag-one-line" >actual &&
- git diff expect actual &&
- git-tag -n0 -l tag-one-line >actual &&
- git diff expect actual &&
+ git tag -l | grep "^tag-one-line" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l | grep "^tag-one-line" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l tag-one-line >actual &&
+ test_cmp expect actual &&
echo "tag-one-line A msg" >expect &&
- git-tag -n1 -l | grep "^tag-one-line" >actual &&
- git diff expect actual &&
- git-tag -n -l | grep "^tag-one-line" >actual &&
- git diff expect actual &&
- git-tag -n1 -l tag-one-line >actual &&
- git diff expect actual &&
- git-tag -n2 -l tag-one-line >actual &&
- git diff expect actual &&
- git-tag -n999 -l tag-one-line >actual &&
- git diff expect actual
+ git tag -n1 -l | grep "^tag-one-line" >actual &&
+ test_cmp expect actual &&
+ git tag -n -l | grep "^tag-one-line" >actual &&
+ test_cmp expect actual &&
+ git tag -n1 -l tag-one-line >actual &&
+ test_cmp expect actual &&
+ git tag -n2 -l tag-one-line >actual &&
+ test_cmp expect actual &&
+ git tag -n999 -l tag-one-line >actual &&
+ test_cmp expect actual
'
test_expect_success \
'listing the zero-lines message of a non-signed tag should succeed' '
- git-tag -m "" tag-zero-lines &&
+ git tag -m "" tag-zero-lines &&
echo "tag-zero-lines" >expect &&
- git-tag -l | grep "^tag-zero-lines" >actual &&
- git diff expect actual &&
- git-tag -n0 -l | grep "^tag-zero-lines" >actual &&
- git diff expect actual &&
- git-tag -n0 -l tag-zero-lines >actual &&
- git diff expect actual &&
+ git tag -l | grep "^tag-zero-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l | grep "^tag-zero-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l tag-zero-lines >actual &&
+ test_cmp expect actual &&
echo "tag-zero-lines " >expect &&
- git-tag -n1 -l | grep "^tag-zero-lines" >actual &&
- git diff expect actual &&
- git-tag -n -l | grep "^tag-zero-lines" >actual &&
- git diff expect actual &&
- git-tag -n1 -l tag-zero-lines >actual &&
- git diff expect actual &&
- git-tag -n2 -l tag-zero-lines >actual &&
- git diff expect actual &&
- git-tag -n999 -l tag-zero-lines >actual &&
- git diff expect actual
+ git tag -n1 -l | grep "^tag-zero-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n -l | grep "^tag-zero-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n1 -l tag-zero-lines >actual &&
+ test_cmp expect actual &&
+ git tag -n2 -l tag-zero-lines >actual &&
+ test_cmp expect actual &&
+ git tag -n999 -l tag-zero-lines >actual &&
+ test_cmp expect actual
'
echo 'tag line one' >annotagmsg
@@ -539,124 +541,125 @@ echo 'tag line two' >>annotagmsg
echo 'tag line three' >>annotagmsg
test_expect_success \
'listing many message lines of a non-signed tag should succeed' '
- git-tag -F annotagmsg tag-lines &&
+ git tag -F annotagmsg tag-lines &&
echo "tag-lines" >expect &&
- git-tag -l | grep "^tag-lines" >actual &&
- git diff expect actual &&
- git-tag -n0 -l | grep "^tag-lines" >actual &&
- git diff expect actual &&
- git-tag -n0 -l tag-lines >actual &&
- git diff expect actual &&
+ git tag -l | grep "^tag-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l | grep "^tag-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l tag-lines >actual &&
+ test_cmp expect actual &&
echo "tag-lines tag line one" >expect &&
- git-tag -n1 -l | grep "^tag-lines" >actual &&
- git diff expect actual &&
- git-tag -n -l | grep "^tag-lines" >actual &&
- git diff expect actual &&
- git-tag -n1 -l tag-lines >actual &&
- git diff expect actual &&
+ git tag -n1 -l | grep "^tag-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n -l | grep "^tag-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n1 -l tag-lines >actual &&
+ test_cmp expect actual &&
echo " tag line two" >>expect &&
- git-tag -n2 -l | grep "^ *tag.line" >actual &&
- git diff expect actual &&
- git-tag -n2 -l tag-lines >actual &&
- git diff expect actual &&
+ git tag -n2 -l | grep "^ *tag.line" >actual &&
+ test_cmp expect actual &&
+ git tag -n2 -l tag-lines >actual &&
+ test_cmp expect actual &&
echo " tag line three" >>expect &&
- git-tag -n3 -l | grep "^ *tag.line" >actual &&
- git diff expect actual &&
- git-tag -n3 -l tag-lines >actual &&
- git diff expect actual &&
- git-tag -n4 -l | grep "^ *tag.line" >actual &&
- git diff expect actual &&
- git-tag -n4 -l tag-lines >actual &&
- git diff expect actual &&
- git-tag -n99 -l | grep "^ *tag.line" >actual &&
- git diff expect actual &&
- git-tag -n99 -l tag-lines >actual &&
- git diff expect actual
+ git tag -n3 -l | grep "^ *tag.line" >actual &&
+ test_cmp expect actual &&
+ git tag -n3 -l tag-lines >actual &&
+ test_cmp expect actual &&
+ git tag -n4 -l | grep "^ *tag.line" >actual &&
+ test_cmp expect actual &&
+ git tag -n4 -l tag-lines >actual &&
+ test_cmp expect actual &&
+ git tag -n99 -l | grep "^ *tag.line" >actual &&
+ test_cmp expect actual &&
+ git tag -n99 -l tag-lines >actual &&
+ test_cmp expect actual
'
# subsequent tests require gpg; check if it is available
-gpg --version >/dev/null
+gpg --version >/dev/null 2>/dev/null
if [ $? -eq 127 ]; then
- echo "gpg not found - skipping tag signing and verification tests"
- test_done
- exit
+ say "gpg not found - skipping tag signing and verification tests"
+else
+ # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
+ # the gpg version 1.0.6 didn't parse trust packets correctly, so for
+ # that version, creation of signed tags using the generated key fails.
+ case "$(gpg --version)" in
+ 'gpg (GnuPG) 1.0.6'*)
+ say "Skipping signed tag tests, because a bug in 1.0.6 version"
+ ;;
+ *)
+ test_set_prereq GPG
+ ;;
+ esac
fi
# trying to verify annotated non-signed tags:
-test_expect_success \
+test_expect_success GPG \
'trying to verify an annotated non-signed tag should fail' '
tag_exists annotated-tag &&
- ! git-tag -v annotated-tag
+ test_must_fail git tag -v annotated-tag
'
-test_expect_success \
+test_expect_success GPG \
'trying to verify a file-annotated non-signed tag should fail' '
tag_exists file-annotated-tag &&
- ! git-tag -v file-annotated-tag
+ test_must_fail git tag -v file-annotated-tag
'
-test_expect_success \
+test_expect_success GPG \
'trying to verify two annotated non-signed tags should fail' '
tag_exists annotated-tag file-annotated-tag &&
- ! git-tag -v annotated-tag file-annotated-tag
+ test_must_fail git tag -v annotated-tag file-annotated-tag
'
# creating and verifying signed tags:
-# As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
-# the gpg version 1.0.6 didn't parse trust packets correctly, so for
-# that version, creation of signed tags using the generated key fails.
-case "$(gpg --version)" in
-'gpg (GnuPG) 1.0.6'*)
- echo "Skipping signed tag tests, because a bug in 1.0.6 version"
- test_done
- exit
- ;;
-esac
-
# key generation info: gpg --homedir t/t7004 --gen-key
# Type DSA and Elgamal, size 2048 bits, no expiration date.
# Name and email: C O Mitter <committer@example.com>
# No password given, to enable non-interactive operation.
-cp -R ../t7004 ./gpghome
+cp -R "$TEST_DIRECTORY"/t7004 ./gpghome
chmod 0700 gpghome
-export GNUPGHOME="$(pwd)/gpghome"
+GNUPGHOME="$(pwd)/gpghome"
+export GNUPGHOME
get_tag_header signed-tag $commit commit $time >expect
echo 'A signed tag message' >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success 'creating a signed tag with -m message should succeed' '
- git-tag -s -m "A signed tag message" signed-tag &&
+test_expect_success GPG 'creating a signed tag with -m message should succeed' '
+ git tag -s -m "A signed tag message" signed-tag &&
get_tag_msg signed-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
get_tag_header u-signed-tag $commit commit $time >expect
echo 'Another message' >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success 'sign with a given key id' '
+test_expect_success GPG 'sign with a given key id' '
git tag -u committer@example.com -m "Another message" u-signed-tag &&
get_tag_msg u-signed-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
-test_expect_success 'sign with an unknown id (1)' '
+test_expect_success GPG 'sign with an unknown id (1)' '
- ! git tag -u author@example.com -m "Another message" o-signed-tag
+ test_must_fail git tag -u author@example.com \
+ -m "Another message" o-signed-tag
'
-test_expect_success 'sign with an unknown id (2)' '
+test_expect_success GPG 'sign with an unknown id (2)' '
- ! git tag -u DEADBEEF -m "Another message" o-signed-tag
+ test_must_fail git tag -u DEADBEEF -m "Another message" o-signed-tag
'
@@ -671,10 +674,10 @@ chmod +x fakeeditor
get_tag_header implied-sign $commit commit $time >expect
./fakeeditor >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success '-u implies signed tag' '
- GIT_EDITOR=./fakeeditor git-tag -u CDDE430D implied-sign &&
+test_expect_success GPG '-u implies signed tag' '
+ GIT_EDITOR=./fakeeditor git tag -u CDDE430D implied-sign &&
get_tag_msg implied-sign >actual &&
- git diff expect actual
+ test_cmp expect actual
'
cat >sigmsgfile <<EOF
@@ -684,11 +687,11 @@ EOF
get_tag_header file-signed-tag $commit commit $time >expect
cat sigmsgfile >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with -F messagefile should succeed' '
- git-tag -s -F sigmsgfile file-signed-tag &&
+ git tag -s -F sigmsgfile file-signed-tag &&
get_tag_msg file-signed-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
cat >siginputmsg <<EOF
@@ -698,72 +701,73 @@ EOF
get_tag_header stdin-signed-tag $commit commit $time >expect
cat siginputmsg >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success 'creating a signed tag with -F - should succeed' '
- git-tag -s -F - stdin-signed-tag <siginputmsg &&
+test_expect_success GPG 'creating a signed tag with -F - should succeed' '
+ git tag -s -F - stdin-signed-tag <siginputmsg &&
get_tag_msg stdin-signed-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
get_tag_header implied-annotate $commit commit $time >expect
./fakeeditor >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success '-s implies annotated tag' '
- GIT_EDITOR=./fakeeditor git-tag -s implied-annotate &&
+test_expect_success GPG '-s implies annotated tag' '
+ GIT_EDITOR=./fakeeditor git tag -s implied-annotate &&
get_tag_msg implied-annotate >actual &&
- git diff expect actual
+ test_cmp expect actual
'
-test_expect_success \
+test_expect_success GPG \
'trying to create a signed tag with non-existing -F file should fail' '
! test -f nonexistingfile &&
! tag_exists nosigtag &&
- ! git-tag -s -F nonexistingfile nosigtag &&
+ test_must_fail git tag -s -F nonexistingfile nosigtag &&
! tag_exists nosigtag
'
-test_expect_success 'verifying a signed tag should succeed' \
- 'git-tag -v signed-tag'
+test_expect_success GPG 'verifying a signed tag should succeed' \
+ 'git tag -v signed-tag'
-test_expect_success 'verifying two signed tags in one command should succeed' \
- 'git-tag -v signed-tag file-signed-tag'
+test_expect_success GPG 'verifying two signed tags in one command should succeed' \
+ 'git tag -v signed-tag file-signed-tag'
-test_expect_success \
+test_expect_success GPG \
'verifying many signed and non-signed tags should fail' '
- ! git-tag -v signed-tag annotated-tag &&
- ! git-tag -v file-annotated-tag file-signed-tag &&
- ! git-tag -v annotated-tag file-signed-tag file-annotated-tag &&
- ! git-tag -v signed-tag annotated-tag file-signed-tag
+ test_must_fail git tag -v signed-tag annotated-tag &&
+ test_must_fail git tag -v file-annotated-tag file-signed-tag &&
+ test_must_fail git tag -v annotated-tag \
+ file-signed-tag file-annotated-tag &&
+ test_must_fail git tag -v signed-tag annotated-tag file-signed-tag
'
-test_expect_success 'verifying a forged tag should fail' '
+test_expect_success GPG 'verifying a forged tag should fail' '
forged=$(git cat-file tag signed-tag |
sed -e "s/signed-tag/forged-tag/" |
git mktag) &&
git tag forged-tag $forged &&
- ! git-tag -v forged-tag
+ test_must_fail git tag -v forged-tag
'
# blank and empty messages for signed tags:
get_tag_header empty-signed-tag $commit commit $time >expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with an empty -m message should succeed' '
- git-tag -s -m "" empty-signed-tag &&
+ git tag -s -m "" empty-signed-tag &&
get_tag_msg empty-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v empty-signed-tag
+ test_cmp expect actual &&
+ git tag -v empty-signed-tag
'
>sigemptyfile
get_tag_header emptyfile-signed-tag $commit commit $time >expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with an empty -F messagefile should succeed' '
- git-tag -s -F sigemptyfile emptyfile-signed-tag &&
+ git tag -s -F sigemptyfile emptyfile-signed-tag &&
get_tag_msg emptyfile-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v emptyfile-signed-tag
+ test_cmp expect actual &&
+ git tag -v emptyfile-signed-tag
'
printf '\n\n \n\t\nLeading blank lines\n' > sigblanksfile
@@ -781,22 +785,22 @@ Trailing spaces
Trailing blank lines
EOF
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'extra blanks in the message for a signed tag should be removed' '
- git-tag -s -F sigblanksfile blanks-signed-tag &&
+ git tag -s -F sigblanksfile blanks-signed-tag &&
get_tag_msg blanks-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v blanks-signed-tag
+ test_cmp expect actual &&
+ git tag -v blanks-signed-tag
'
get_tag_header blank-signed-tag $commit commit $time >expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with a blank -m message should succeed' '
- git-tag -s -m " " blank-signed-tag &&
+ git tag -s -m " " blank-signed-tag &&
get_tag_msg blank-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v blank-signed-tag
+ test_cmp expect actual &&
+ git tag -v blank-signed-tag
'
echo ' ' >sigblankfile
@@ -804,23 +808,23 @@ echo '' >>sigblankfile
echo ' ' >>sigblankfile
get_tag_header blankfile-signed-tag $commit commit $time >expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with blank -F file with spaces should succeed' '
- git-tag -s -F sigblankfile blankfile-signed-tag &&
+ git tag -s -F sigblankfile blankfile-signed-tag &&
get_tag_msg blankfile-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v blankfile-signed-tag
+ test_cmp expect actual &&
+ git tag -v blankfile-signed-tag
'
printf ' ' >sigblanknonlfile
get_tag_header blanknonlfile-signed-tag $commit commit $time >expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with spaces and no newline should succeed' '
- git-tag -s -F sigblanknonlfile blanknonlfile-signed-tag &&
+ git tag -s -F sigblanknonlfile blanknonlfile-signed-tag &&
get_tag_msg blanknonlfile-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v signed-tag
+ test_cmp expect actual &&
+ git tag -v signed-tag
'
# messages with commented lines for signed tags:
@@ -852,22 +856,22 @@ Another line.
Last line.
EOF
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with a -F file with #comments should succeed' '
- git-tag -s -F sigcommentsfile comments-signed-tag &&
+ git tag -s -F sigcommentsfile comments-signed-tag &&
get_tag_msg comments-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v comments-signed-tag
+ test_cmp expect actual &&
+ git tag -v comments-signed-tag
'
get_tag_header comment-signed-tag $commit commit $time >expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with #commented -m message should succeed' '
- git-tag -s -m "#comment" comment-signed-tag &&
+ git tag -s -m "#comment" comment-signed-tag &&
get_tag_msg comment-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v comment-signed-tag
+ test_cmp expect actual &&
+ git tag -v comment-signed-tag
'
echo '#comment' >sigcommentfile
@@ -875,173 +879,173 @@ echo '' >>sigcommentfile
echo '####' >>sigcommentfile
get_tag_header commentfile-signed-tag $commit commit $time >expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with #commented -F messagefile should succeed' '
- git-tag -s -F sigcommentfile commentfile-signed-tag &&
+ git tag -s -F sigcommentfile commentfile-signed-tag &&
get_tag_msg commentfile-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v commentfile-signed-tag
+ test_cmp expect actual &&
+ git tag -v commentfile-signed-tag
'
printf '#comment' >sigcommentnonlfile
get_tag_header commentnonlfile-signed-tag $commit commit $time >expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag with a #comment and no newline should succeed' '
- git-tag -s -F sigcommentnonlfile commentnonlfile-signed-tag &&
+ git tag -s -F sigcommentnonlfile commentnonlfile-signed-tag &&
get_tag_msg commentnonlfile-signed-tag >actual &&
- git diff expect actual &&
- git-tag -v commentnonlfile-signed-tag
+ test_cmp expect actual &&
+ git tag -v commentnonlfile-signed-tag
'
# listing messages for signed tags:
-test_expect_success \
+test_expect_success GPG \
'listing the one-line message of a signed tag should succeed' '
- git-tag -s -m "A message line signed" stag-one-line &&
+ git tag -s -m "A message line signed" stag-one-line &&
echo "stag-one-line" >expect &&
- git-tag -l | grep "^stag-one-line" >actual &&
- git diff expect actual &&
- git-tag -n0 -l | grep "^stag-one-line" >actual &&
- git diff expect actual &&
- git-tag -n0 -l stag-one-line >actual &&
- git diff expect actual &&
+ git tag -l | grep "^stag-one-line" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l | grep "^stag-one-line" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l stag-one-line >actual &&
+ test_cmp expect actual &&
echo "stag-one-line A message line signed" >expect &&
- git-tag -n1 -l | grep "^stag-one-line" >actual &&
- git diff expect actual &&
- git-tag -n -l | grep "^stag-one-line" >actual &&
- git diff expect actual &&
- git-tag -n1 -l stag-one-line >actual &&
- git diff expect actual &&
- git-tag -n2 -l stag-one-line >actual &&
- git diff expect actual &&
- git-tag -n999 -l stag-one-line >actual &&
- git diff expect actual
-'
-
-test_expect_success \
+ git tag -n1 -l | grep "^stag-one-line" >actual &&
+ test_cmp expect actual &&
+ git tag -n -l | grep "^stag-one-line" >actual &&
+ test_cmp expect actual &&
+ git tag -n1 -l stag-one-line >actual &&
+ test_cmp expect actual &&
+ git tag -n2 -l stag-one-line >actual &&
+ test_cmp expect actual &&
+ git tag -n999 -l stag-one-line >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success GPG \
'listing the zero-lines message of a signed tag should succeed' '
- git-tag -s -m "" stag-zero-lines &&
+ git tag -s -m "" stag-zero-lines &&
echo "stag-zero-lines" >expect &&
- git-tag -l | grep "^stag-zero-lines" >actual &&
- git diff expect actual &&
- git-tag -n0 -l | grep "^stag-zero-lines" >actual &&
- git diff expect actual &&
- git-tag -n0 -l stag-zero-lines >actual &&
- git diff expect actual &&
+ git tag -l | grep "^stag-zero-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l | grep "^stag-zero-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l stag-zero-lines >actual &&
+ test_cmp expect actual &&
echo "stag-zero-lines " >expect &&
- git-tag -n1 -l | grep "^stag-zero-lines" >actual &&
- git diff expect actual &&
- git-tag -n -l | grep "^stag-zero-lines" >actual &&
- git diff expect actual &&
- git-tag -n1 -l stag-zero-lines >actual &&
- git diff expect actual &&
- git-tag -n2 -l stag-zero-lines >actual &&
- git diff expect actual &&
- git-tag -n999 -l stag-zero-lines >actual &&
- git diff expect actual
+ git tag -n1 -l | grep "^stag-zero-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n -l | grep "^stag-zero-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n1 -l stag-zero-lines >actual &&
+ test_cmp expect actual &&
+ git tag -n2 -l stag-zero-lines >actual &&
+ test_cmp expect actual &&
+ git tag -n999 -l stag-zero-lines >actual &&
+ test_cmp expect actual
'
echo 'stag line one' >sigtagmsg
echo 'stag line two' >>sigtagmsg
echo 'stag line three' >>sigtagmsg
-test_expect_success \
+test_expect_success GPG \
'listing many message lines of a signed tag should succeed' '
- git-tag -s -F sigtagmsg stag-lines &&
+ git tag -s -F sigtagmsg stag-lines &&
echo "stag-lines" >expect &&
- git-tag -l | grep "^stag-lines" >actual &&
- git diff expect actual &&
- git-tag -n0 -l | grep "^stag-lines" >actual &&
- git diff expect actual &&
- git-tag -n0 -l stag-lines >actual &&
- git diff expect actual &&
+ git tag -l | grep "^stag-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l | grep "^stag-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n0 -l stag-lines >actual &&
+ test_cmp expect actual &&
echo "stag-lines stag line one" >expect &&
- git-tag -n1 -l | grep "^stag-lines" >actual &&
- git diff expect actual &&
- git-tag -n -l | grep "^stag-lines" >actual &&
- git diff expect actual &&
- git-tag -n1 -l stag-lines >actual &&
- git diff expect actual &&
+ git tag -n1 -l | grep "^stag-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n -l | grep "^stag-lines" >actual &&
+ test_cmp expect actual &&
+ git tag -n1 -l stag-lines >actual &&
+ test_cmp expect actual &&
echo " stag line two" >>expect &&
- git-tag -n2 -l | grep "^ *stag.line" >actual &&
- git diff expect actual &&
- git-tag -n2 -l stag-lines >actual &&
- git diff expect actual &&
+ git tag -n2 -l | grep "^ *stag.line" >actual &&
+ test_cmp expect actual &&
+ git tag -n2 -l stag-lines >actual &&
+ test_cmp expect actual &&
echo " stag line three" >>expect &&
- git-tag -n3 -l | grep "^ *stag.line" >actual &&
- git diff expect actual &&
- git-tag -n3 -l stag-lines >actual &&
- git diff expect actual &&
- git-tag -n4 -l | grep "^ *stag.line" >actual &&
- git diff expect actual &&
- git-tag -n4 -l stag-lines >actual &&
- git diff expect actual &&
- git-tag -n99 -l | grep "^ *stag.line" >actual &&
- git diff expect actual &&
- git-tag -n99 -l stag-lines >actual &&
- git diff expect actual
+ git tag -n3 -l | grep "^ *stag.line" >actual &&
+ test_cmp expect actual &&
+ git tag -n3 -l stag-lines >actual &&
+ test_cmp expect actual &&
+ git tag -n4 -l | grep "^ *stag.line" >actual &&
+ test_cmp expect actual &&
+ git tag -n4 -l stag-lines >actual &&
+ test_cmp expect actual &&
+ git tag -n99 -l | grep "^ *stag.line" >actual &&
+ test_cmp expect actual &&
+ git tag -n99 -l stag-lines >actual &&
+ test_cmp expect actual
'
# tags pointing to objects different from commits:
tree=$(git rev-parse HEAD^{tree})
blob=$(git rev-parse HEAD:foo)
-tag=$(git rev-parse signed-tag)
+tag=$(git rev-parse signed-tag 2>/dev/null)
get_tag_header tree-signed-tag $tree tree $time >expect
echo "A message for a tree" >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag pointing to a tree should succeed' '
- git-tag -s -m "A message for a tree" tree-signed-tag HEAD^{tree} &&
+ git tag -s -m "A message for a tree" tree-signed-tag HEAD^{tree} &&
get_tag_msg tree-signed-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
get_tag_header blob-signed-tag $blob blob $time >expect
echo "A message for a blob" >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag pointing to a blob should succeed' '
- git-tag -s -m "A message for a blob" blob-signed-tag HEAD:foo &&
+ git tag -s -m "A message for a blob" blob-signed-tag HEAD:foo &&
get_tag_msg blob-signed-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
get_tag_header tag-signed-tag $tag tag $time >expect
echo "A message for another tag" >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
'creating a signed tag pointing to another tag should succeed' '
- git-tag -s -m "A message for another tag" tag-signed-tag signed-tag &&
+ git tag -s -m "A message for another tag" tag-signed-tag signed-tag &&
get_tag_msg tag-signed-tag >actual &&
- git diff expect actual
+ test_cmp expect actual
'
# try to sign with bad user.signingkey
git config user.signingkey BobTheMouse
-test_expect_success \
- 'git-tag -s fails if gpg is misconfigured' \
- '! git tag -s -m tail tag-gpg-failure'
+test_expect_success GPG \
+ 'git tag -s fails if gpg is misconfigured' \
+ 'test_must_fail git tag -s -m tail tag-gpg-failure'
git config --unset user.signingkey
# try to verify without gpg:
rm -rf gpghome
-test_expect_success \
+test_expect_success GPG \
'verify signed tag fails when public key is not present' \
- '! git-tag -v signed-tag'
+ 'test_must_fail git tag -v signed-tag'
test_expect_success \
- 'git-tag -a fails if tag annotation is empty' '
+ 'git tag -a fails if tag annotation is empty' '
! (GIT_EDITOR=cat git tag -a initial-comment)
'
@@ -1063,7 +1067,153 @@ test_expect_success \
git tag -a -m "An annotation to be reused" reuse &&
GIT_EDITOR=true git tag -f -a reuse &&
get_tag_msg reuse >actual &&
- git diff expect actual
+ test_cmp expect actual
+'
+
+test_expect_success 'filename for the message is relative to cwd' '
+ mkdir subdir &&
+ echo "Tag message in top directory" >msgfile-5 &&
+ echo "Tag message in sub directory" >subdir/msgfile-5 &&
+ (
+ cd subdir &&
+ git tag -a -F msgfile-5 tag-from-subdir
+ ) &&
+ git cat-file tag tag-from-subdir | grep "in sub directory"
+'
+
+test_expect_success 'filename for the message is relative to cwd' '
+ echo "Tag message in sub directory" >subdir/msgfile-6 &&
+ (
+ cd subdir &&
+ git tag -a -F msgfile-6 tag-from-subdir-2
+ ) &&
+ git cat-file tag tag-from-subdir-2 | grep "in sub directory"
+'
+
+# create a few more commits to test --contains
+
+hash1=$(git rev-parse HEAD)
+
+test_expect_success 'creating second commit and tag' '
+ echo foo-2.0 >foo &&
+ git add foo &&
+ git commit -m second
+ git tag v2.0
+'
+
+hash2=$(git rev-parse HEAD)
+
+test_expect_success 'creating third commit without tag' '
+ echo foo-dev >foo &&
+ git add foo &&
+ git commit -m third
+'
+
+hash3=$(git rev-parse HEAD)
+
+# simple linear checks of --continue
+
+cat > expected <<EOF
+v0.2.1
+v1.0
+v1.0.1
+v1.1.3
+v2.0
+EOF
+
+test_expect_success 'checking that first commit is in all tags (hash)' "
+ git tag -l --contains $hash1 v* >actual
+ test_cmp expected actual
+"
+
+# other ways of specifying the commit
+test_expect_success 'checking that first commit is in all tags (tag)' "
+ git tag -l --contains v1.0 v* >actual
+ test_cmp expected actual
+"
+
+test_expect_success 'checking that first commit is in all tags (relative)' "
+ git tag -l --contains HEAD~2 v* >actual
+ test_cmp expected actual
+"
+
+cat > expected <<EOF
+v2.0
+EOF
+
+test_expect_success 'checking that second commit only has one tag' "
+ git tag -l --contains $hash2 v* >actual
+ test_cmp expected actual
+"
+
+
+cat > expected <<EOF
+EOF
+
+test_expect_success 'checking that third commit has no tags' "
+ git tag -l --contains $hash3 v* >actual
+ test_cmp expected actual
+"
+
+# how about a simple merge?
+
+test_expect_success 'creating simple branch' '
+ git branch stable v2.0 &&
+ git checkout stable &&
+ echo foo-3.0 > foo &&
+ git commit foo -m fourth
+ git tag v3.0
+'
+
+hash4=$(git rev-parse HEAD)
+
+cat > expected <<EOF
+v3.0
+EOF
+
+test_expect_success 'checking that branch head only has one tag' "
+ git tag -l --contains $hash4 v* >actual
+ test_cmp expected actual
+"
+
+test_expect_success 'merging original branch into this branch' '
+ git merge --strategy=ours master &&
+ git tag v4.0
+'
+
+cat > expected <<EOF
+v4.0
+EOF
+
+test_expect_success 'checking that original branch head has one tag now' "
+ git tag -l --contains $hash3 v* >actual
+ test_cmp expected actual
+"
+
+cat > expected <<EOF
+v0.2.1
+v1.0
+v1.0.1
+v1.1.3
+v2.0
+v3.0
+v4.0
+EOF
+
+test_expect_success 'checking that initial commit is in all tags' "
+ git tag -l --contains $hash1 v* >actual
+ test_cmp expected actual
+"
+
+# mixing modes and options:
+
+test_expect_success 'mixing incompatibles modes and options is forbidden' '
+ test_must_fail git tag -a
+ test_must_fail git tag -l -v
+ test_must_fail git tag -n 100
+ test_must_fail git tag -l -m msg
+ test_must_fail git tag -l -F some file
+ test_must_fail git tag -v -s
'
test_done
diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh
index 2d919d69ef..5257f4d261 100755
--- a/t/t7005-editor.sh
+++ b/t/t7005-editor.sh
@@ -4,26 +4,40 @@ test_description='GIT_EDITOR, core.editor, and stuff'
. ./test-lib.sh
-for i in GIT_EDITOR core_editor EDITOR VISUAL vi
+unset EDITOR VISUAL GIT_EDITOR
+
+test_expect_success 'determine default editor' '
+
+ vi=$(TERM=vt100 git var GIT_EDITOR) &&
+ test -n "$vi"
+
+'
+
+if ! expr "$vi" : '^[a-z]*$' >/dev/null
+then
+ vi=
+fi
+
+for i in GIT_EDITOR core_editor EDITOR VISUAL $vi
do
cat >e-$i.sh <<-EOF
+ #!$SHELL_PATH
echo "Edited by $i" >"\$1"
EOF
chmod +x e-$i.sh
done
-unset vi
-mv e-vi.sh vi
-unset EDITOR VISUAL GIT_EDITOR
+
+if ! test -z "$vi"
+then
+ mv e-$vi.sh $vi
+fi
test_expect_success setup '
- msg="Hand edited" &&
+ msg="Hand-edited" &&
+ test_commit "$msg" &&
echo "$msg" >expect &&
- git add vi &&
- test_tick &&
- git commit -m "$msg" &&
- git show -s --pretty=oneline |
- sed -e "s/^[0-9a-f]* //" >actual &&
+ git show -s --format=%s > actual &&
diff actual expect
'
@@ -41,9 +55,19 @@ test_expect_success 'dumb should error out when falling back on vi' '
fi
'
+test_expect_success 'dumb should prefer EDITOR to VISUAL' '
+
+ EDITOR=./e-EDITOR.sh &&
+ VISUAL=./e-VISUAL.sh &&
+ export EDITOR VISUAL &&
+ git commit --amend &&
+ test "$(git show -s --format=%s)" = "Edited by EDITOR"
+
+'
+
TERM=vt100
export TERM
-for i in vi EDITOR VISUAL core_editor GIT_EDITOR
+for i in $vi EDITOR VISUAL core_editor GIT_EDITOR
do
echo "Edited by $i" >expect
unset EDITOR VISUAL GIT_EDITOR
@@ -67,7 +91,7 @@ done
unset EDITOR VISUAL GIT_EDITOR
git config --unset-all core.editor
-for i in vi EDITOR VISUAL core_editor GIT_EDITOR
+for i in $vi EDITOR VISUAL core_editor GIT_EDITOR
do
echo "Edited by $i" >expect
case "$i" in
@@ -87,30 +111,26 @@ do
'
done
+if ! echo 'echo space > "$1"' > "e space.sh"
+then
+ say "Skipping; FS does not support spaces in filenames"
+ test_done
+fi
+
test_expect_success 'editor with a space' '
- if echo "echo space > \"\$1\"" > "e space.sh"
- then
- chmod a+x "e space.sh" &&
- GIT_EDITOR="./e\ space.sh" git commit --amend &&
- test space = "$(git show -s --pretty=format:%s)"
- else
- say "Skipping; FS does not support spaces in filenames"
- fi
+ chmod a+x "e space.sh" &&
+ GIT_EDITOR="./e\ space.sh" git commit --amend &&
+ test space = "$(git show -s --pretty=format:%s)"
'
unset GIT_EDITOR
test_expect_success 'core.editor with a space' '
- if test -f "e space.sh"
- then
- git config core.editor \"./e\ space.sh\" &&
- git commit --amend &&
- test space = "$(git show -s --pretty=format:%s)"
- else
- say "Skipping; FS does not support spaces in filenames"
- fi
+ git config core.editor \"./e\ space.sh\" &&
+ git commit --amend &&
+ test space = "$(git show -s --pretty=format:%s)"
'
diff --git a/t/t7007-show.sh b/t/t7007-show.sh
new file mode 100755
index 0000000000..cce222f052
--- /dev/null
+++ b/t/t7007-show.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='git show'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo hello world >foo &&
+ H=$(git hash-object -w foo) &&
+ git tag -a foo-tag -m "Tags $H" $H &&
+ HH=$(expr "$H" : "\(..\)") &&
+ H38=$(expr "$H" : "..\(.*\)") &&
+ rm -f .git/objects/$HH/$H38
+'
+
+test_expect_success 'showing a tag that point at a missing object' '
+ test_must_fail git --no-pager show foo-tag
+'
+
+test_done
diff --git a/t/t7010-setup.sh b/t/t7010-setup.sh
index 02cf7c5c9d..d8a7c79852 100755
--- a/t/t7010-setup.sh
+++ b/t/t7010-setup.sh
@@ -122,7 +122,7 @@ test_expect_success 'commit using absolute path names' '
test_expect_success 'log using absolute path names' '
echo bb >>a/b/c/d &&
- git commit -m "bb" $(pwd)/a/b/c/d &&
+ git commit -m "bb" "$(pwd)/a/b/c/d" &&
git log a/b/c/d >f1.txt &&
git log "$(pwd)/a/b/c/d" >f2.txt &&
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
new file mode 100755
index 0000000000..1044aa6549
--- /dev/null
+++ b/t/t7060-wtstatus.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+test_description='basic work tree status reporting'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ test_commit A &&
+ test_commit B oneside added &&
+ git checkout A^0 &&
+ test_commit C oneside created
+'
+
+test_expect_success 'A/A conflict' '
+ git checkout B^0 &&
+ test_must_fail git merge C
+'
+
+test_expect_success 'Report path with conflict' '
+ git diff --cached --name-status >actual &&
+ echo "U oneside" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'Report new path with conflict' '
+ git diff --cached --name-status HEAD^ >actual &&
+ echo "U oneside" >expect &&
+ test_cmp expect actual
+'
+
+cat >expect <<EOF
+# On branch side
+# Unmerged paths:
+# (use "git reset HEAD <file>..." to unstage)
+# (use "git add <file>..." to mark resolution)
+#
+# deleted by us: foo
+#
+no changes added to commit (use "git add" and/or "git commit -a")
+EOF
+
+test_expect_success 'M/D conflict does not segfault' '
+ mkdir mdconflict &&
+ (
+ cd mdconflict &&
+ git init &&
+ test_commit initial foo "" &&
+ test_commit modify foo foo &&
+ git checkout -b side HEAD^ &&
+ git rm foo &&
+ git commit -m delete &&
+ test_must_fail git merge master &&
+ test_must_fail git status > ../actual
+ ) &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t7101-reset.sh b/t/t7101-reset.sh
index 0d9874bfd7..96e163f084 100755
--- a/t/t7101-reset.sh
+++ b/t/t7101-reset.sh
@@ -3,33 +3,33 @@
# Copyright (c) 2006 Shawn Pearce
#
-test_description='git-reset should cull empty subdirs'
+test_description='git reset should cull empty subdirs'
. ./test-lib.sh
test_expect_success \
'creating initial files' \
'mkdir path0 &&
- cp ../../COPYING path0/COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
git add path0/COPYING &&
- git-commit -m add -a'
+ git commit -m add -a'
test_expect_success \
'creating second files' \
'mkdir path1 &&
mkdir path1/path2 &&
- cp ../../COPYING path1/path2/COPYING &&
- cp ../../COPYING path1/COPYING &&
- cp ../../COPYING COPYING &&
- cp ../../COPYING path0/COPYING-TOO &&
+ cp "$TEST_DIRECTORY"/../COPYING path1/path2/COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING path1/COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING path0/COPYING-TOO &&
git add path1/path2/COPYING &&
git add path1/COPYING &&
git add COPYING &&
git add path0/COPYING-TOO &&
- git-commit -m change -a'
+ git commit -m change -a'
test_expect_success \
'resetting tree HEAD^' \
- 'git-reset --hard HEAD^'
+ 'git reset --hard HEAD^'
test_expect_success \
'checking initial files exist after rewind' \
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index e5c9f30c73..b8cf2603a1 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -3,9 +3,9 @@
# Copyright (c) 2007 Carlos Rica
#
-test_description='git-reset
+test_description='git reset
-Documented tests for git-reset'
+Documented tests for git reset'
. ./test-lib.sh
@@ -34,13 +34,13 @@ test_expect_success 'creating initial files and commits' '
check_changes () {
test "$(git rev-parse HEAD)" = "$1" &&
- git diff | git diff .diff_expect - &&
- git diff --cached | git diff .cached_expect - &&
+ git diff | test_cmp .diff_expect - &&
+ git diff --cached | test_cmp .cached_expect - &&
for FILE in *
do
echo $FILE':'
cat $FILE || return
- done | git diff .cat_expect -
+ done | test_cmp .cat_expect -
}
>.diff_expect
@@ -52,10 +52,10 @@ secondfile:
EOF
test_expect_success 'giving a non existing revision should fail' '
- ! git reset aaaaaa &&
- ! git reset --mixed aaaaaa &&
- ! git reset --soft aaaaaa &&
- ! git reset --hard aaaaaa &&
+ test_must_fail git reset aaaaaa &&
+ test_must_fail git reset --mixed aaaaaa &&
+ test_must_fail git reset --soft aaaaaa &&
+ test_must_fail git reset --hard aaaaaa &&
check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
'
@@ -63,29 +63,29 @@ test_expect_success 'reset --soft with unmerged index should fail' '
touch .git/MERGE_HEAD &&
echo "100644 44c5b5884550c17758737edcced463447b91d42b 1 un" |
git update-index --index-info &&
- ! git reset --soft HEAD &&
+ test_must_fail git reset --soft HEAD &&
rm .git/MERGE_HEAD &&
git rm --cached -- un
'
test_expect_success \
'giving paths with options different than --mixed should fail' '
- ! git reset --soft -- first &&
- ! git reset --hard -- first &&
- ! git reset --soft HEAD^ -- first &&
- ! git reset --hard HEAD^ -- first &&
+ test_must_fail git reset --soft -- first &&
+ test_must_fail git reset --hard -- first &&
+ test_must_fail git reset --soft HEAD^ -- first &&
+ test_must_fail git reset --hard HEAD^ -- first &&
check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
'
test_expect_success 'giving unrecognized options should fail' '
- ! git reset --other &&
- ! git reset -o &&
- ! git reset --mixed --other &&
- ! git reset --mixed -o &&
- ! git reset --soft --other &&
- ! git reset --soft -o &&
- ! git reset --hard --other &&
- ! git reset --hard -o &&
+ test_must_fail git reset --other &&
+ test_must_fail git reset -o &&
+ test_must_fail git reset --mixed --other &&
+ test_must_fail git reset --mixed -o &&
+ test_must_fail git reset --soft --other &&
+ test_must_fail git reset --soft -o &&
+ test_must_fail git reset --hard --other &&
+ test_must_fail git reset --hard -o &&
check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
'
@@ -102,8 +102,8 @@ test_expect_success \
echo "3rd line in branch2" >>secondfile &&
git commit -a -m "change in branch2" &&
- ! git merge branch1 &&
- ! git reset --soft &&
+ test_must_fail git merge branch1 &&
+ test_must_fail git reset --soft &&
printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
git commit -a -m "the change in branch2" &&
@@ -126,7 +126,7 @@ test_expect_success \
echo "3rd line in branch4" >>secondfile &&
git checkout -m branch3 &&
- ! git reset --soft &&
+ test_must_fail git reset --soft &&
printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
git commit -a -m "the line in branch3" &&
@@ -139,19 +139,19 @@ test_expect_success \
test_expect_success \
'resetting to HEAD with no changes should succeed and do nothing' '
git reset --hard &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
git reset --hard HEAD &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
git reset --soft &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
git reset --soft HEAD &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
git reset --mixed &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
git reset --mixed HEAD &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
git reset &&
- check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
+ check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc &&
git reset HEAD &&
check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
'
@@ -326,7 +326,7 @@ test_expect_success '--hard reset to HEAD should clear a failed merge' '
echo "3rd line in branch2" >>secondfile &&
git commit -a -m "change in branch2" &&
- ! git pull . branch1 &&
+ test_must_fail git pull . branch1 &&
git reset --hard &&
check_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb
'
@@ -388,11 +388,11 @@ test_expect_success 'test --mixed <paths>' '
echo 4 > file4 &&
echo 5 > file1 &&
git add file1 file3 file4 &&
- ! git reset HEAD -- file1 file2 file3 &&
+ test_must_fail git reset HEAD -- file1 file2 file3 &&
git diff > output &&
- git diff output expect &&
+ test_cmp output expect &&
git diff --cached > output &&
- git diff output cached_expect
+ test_cmp output cached_expect
'
test_expect_success 'test resetting the index at give paths' '
@@ -402,11 +402,11 @@ test_expect_success 'test resetting the index at give paths' '
>sub/file2 &&
git update-index --add sub/file1 sub/file2 &&
T=$(git write-tree) &&
- ! git reset HEAD sub/file2 &&
+ test_must_fail git reset HEAD sub/file2 &&
U=$(git write-tree) &&
echo "$T" &&
echo "$U" &&
- ! git diff-index --cached --exit-code "$T" &&
+ test_must_fail git diff-index --cached --exit-code "$T" &&
test "$T" != "$U"
'
@@ -419,13 +419,61 @@ test_expect_success 'resetting an unmodified path is a no-op' '
'
cat > expect << EOF
-file2: needs update
+Unstaged changes after reset:
+M file2
EOF
test_expect_success '--mixed refreshes the index' '
echo 123 >> file2 &&
git reset --mixed HEAD > output &&
- git diff --exit-code expect output
+ test_cmp expect output
+'
+
+test_expect_success 'disambiguation (1)' '
+
+ git reset --hard &&
+ >secondfile &&
+ git add secondfile &&
+ test_must_fail git reset secondfile &&
+ test -z "$(git diff --cached --name-only)" &&
+ test -f secondfile &&
+ test ! -s secondfile
+
+'
+
+test_expect_success 'disambiguation (2)' '
+
+ git reset --hard &&
+ >secondfile &&
+ git add secondfile &&
+ rm -f secondfile &&
+ test_must_fail git reset secondfile &&
+ test -n "$(git diff --cached --name-only -- secondfile)" &&
+ test ! -f secondfile
+
+'
+
+test_expect_success 'disambiguation (3)' '
+
+ git reset --hard &&
+ >secondfile &&
+ git add secondfile &&
+ rm -f secondfile &&
+ test_must_fail git reset HEAD secondfile &&
+ test -z "$(git diff --cached --name-only)" &&
+ test ! -f secondfile
+
+'
+
+test_expect_success 'disambiguation (4)' '
+
+ git reset --hard &&
+ >secondfile &&
+ git add secondfile &&
+ rm -f secondfile &&
+ test_must_fail git reset -- secondfile &&
+ test -z "$(git diff --cached --name-only)" &&
+ test ! -f secondfile
'
test_done
diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh
index b25a77f910..afb55b3a46 100755
--- a/t/t7103-reset-bare.sh
+++ b/t/t7103-reset-bare.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-reset in a bare repository'
+test_description='git reset in a bare repository'
. ./test-lib.sh
test_expect_success 'setup non-bare' '
@@ -11,16 +11,48 @@ test_expect_success 'setup non-bare' '
git commit -a -m two
'
+test_expect_success 'hard reset requires a worktree' '
+ (cd .git &&
+ test_must_fail git reset --hard)
+'
+
+test_expect_success 'merge reset requires a worktree' '
+ (cd .git &&
+ test_must_fail git reset --merge)
+'
+
+test_expect_success 'mixed reset is ok' '
+ (cd .git && git reset)
+'
+
+test_expect_success 'soft reset is ok' '
+ (cd .git && git reset --soft)
+'
+
+test_expect_success 'hard reset works with GIT_WORK_TREE' '
+ mkdir worktree &&
+ GIT_WORK_TREE=$PWD/worktree GIT_DIR=$PWD/.git git reset --hard &&
+ test_cmp file worktree/file
+'
+
test_expect_success 'setup bare' '
git clone --bare . bare.git &&
cd bare.git
'
-test_expect_success 'hard reset is not allowed' '
- ! git reset --hard HEAD^
+test_expect_success 'hard reset is not allowed in bare' '
+ test_must_fail git reset --hard HEAD^
+'
+
+test_expect_success 'merge reset is not allowed in bare' '
+ test_must_fail git reset --merge HEAD^
+'
+
+test_expect_success 'mixed reset is not allowed in bare' '
+ test_must_fail git reset --mixed HEAD^
'
-test_expect_success 'soft reset is allowed' '
+test_expect_success 'soft reset is allowed in bare' '
git reset --soft HEAD^ &&
test "`git show --pretty=format:%s | head -n 1`" = "one"
'
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
new file mode 100755
index 0000000000..c1f4fc3c65
--- /dev/null
+++ b/t/t7105-reset-patch.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+test_description='git reset --patch'
+. ./lib-patch-mode.sh
+
+test_expect_success 'setup' '
+ mkdir dir &&
+ echo parent > dir/foo &&
+ echo dummy > bar &&
+ git add dir &&
+ git commit -m initial &&
+ test_tick &&
+ test_commit second dir/foo head &&
+ set_and_save_state bar bar_work bar_index &&
+ save_head
+'
+
+# note: bar sorts before foo, so the first 'n' is always to skip 'bar'
+
+test_expect_success 'saying "n" does nothing' '
+ set_and_save_state dir/foo work work
+ (echo n; echo n) | git reset -p &&
+ verify_saved_state dir/foo &&
+ verify_saved_state bar
+'
+
+test_expect_success 'git reset -p' '
+ (echo n; echo y) | git reset -p &&
+ verify_state dir/foo work head &&
+ verify_saved_state bar
+'
+
+test_expect_success 'git reset -p HEAD^' '
+ (echo n; echo y) | git reset -p HEAD^ &&
+ verify_state dir/foo work parent &&
+ verify_saved_state bar
+'
+
+# The idea in the rest is that bar sorts first, so we always say 'y'
+# first and if the path limiter fails it'll apply to bar instead of
+# dir/foo. There's always an extra 'n' to reject edits to dir/foo in
+# the failure case (and thus get out of the loop).
+
+test_expect_success 'git reset -p dir' '
+ set_state dir/foo work work
+ (echo y; echo n) | git reset -p dir &&
+ verify_state dir/foo work head &&
+ verify_saved_state bar
+'
+
+test_expect_success 'git reset -p -- foo (inside dir)' '
+ set_state dir/foo work work
+ (echo y; echo n) | (cd dir && git reset -p -- foo) &&
+ verify_state dir/foo work head &&
+ verify_saved_state bar
+'
+
+test_expect_success 'git reset -p HEAD^ -- dir' '
+ (echo y; echo n) | git reset -p HEAD^ -- dir &&
+ verify_state dir/foo work parent &&
+ verify_saved_state bar
+'
+
+test_expect_success 'none of this moved HEAD' '
+ verify_saved_head
+'
+
+
+test_done
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 3111baa9e3..ebfd34df36 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2006 Junio C Hamano
#
-test_description='git-checkout tests.
+test_description='git checkout tests.
Creates master, forks renamer and side branches from it.
Test switching across them.
@@ -171,7 +171,7 @@ test_expect_success 'checkout to detach HEAD' '
git checkout -f renamer && git clean -f &&
git checkout renamer^ 2>messages &&
(cat >messages.expect <<EOF
-Note: moving to "renamer^" which isn'"'"'t a local branch
+Note: moving to '\''renamer^'\'' which isn'\''t a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
git checkout -b <new_branch_name>
@@ -330,11 +330,216 @@ test_expect_success \
test "$(git config branch.track2.merge)"
git config branch.autosetupmerge false'
+test_expect_success 'checkout w/--track from non-branch HEAD fails' '
+ git checkout master^0 &&
+ test_must_fail git symbolic-ref HEAD &&
+ test_must_fail git checkout --track -b track &&
+ test_must_fail git rev-parse --verify track &&
+ test_must_fail git symbolic-ref HEAD &&
+ test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
+'
+
+test_expect_success 'detach a symbolic link HEAD' '
+ git checkout master &&
+ git config --bool core.prefersymlinkrefs yes &&
+ git checkout side &&
+ git checkout master &&
+ it=$(git symbolic-ref HEAD) &&
+ test "z$it" = zrefs/heads/master &&
+ here=$(git rev-parse --verify refs/heads/master) &&
+ git checkout side^ &&
+ test "z$(git rev-parse --verify refs/heads/master)" = "z$here"
+'
+
test_expect_success \
- 'checkout w/--track from non-branch HEAD fails' '
- git checkout -b delete-me master &&
- rm .git/refs/heads/delete-me &&
- test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
- !(git checkout --track -b track)'
+ 'checkout with --track fakes a sensible -b <name>' '
+ git update-ref refs/remotes/origin/koala/bear renamer &&
+ git update-ref refs/new/koala/bear renamer &&
+
+ git checkout --track origin/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
+
+ git checkout master && git branch -D koala/bear &&
+
+ git checkout --track refs/remotes/origin/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
+
+ git checkout master && git branch -D koala/bear &&
+
+ git checkout --track remotes/origin/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
+
+ git checkout master && git branch -D koala/bear &&
+
+ git checkout --track refs/new/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
+'
+
+test_expect_success \
+ 'checkout with --track, but without -b, fails with too short tracked name' '
+ test_must_fail git checkout --track renamer'
+
+setup_conflicting_index () {
+ rm -f .git/index &&
+ O=$(echo original | git hash-object -w --stdin) &&
+ A=$(echo ourside | git hash-object -w --stdin) &&
+ B=$(echo theirside | git hash-object -w --stdin) &&
+ (
+ echo "100644 $A 0 fild" &&
+ echo "100644 $O 1 file" &&
+ echo "100644 $A 2 file" &&
+ echo "100644 $B 3 file" &&
+ echo "100644 $A 0 filf"
+ ) | git update-index --index-info
+}
+
+test_expect_success 'checkout an unmerged path should fail' '
+ setup_conflicting_index &&
+ echo "none of the above" >sample &&
+ cat sample >fild &&
+ cat sample >file &&
+ cat sample >filf &&
+ test_must_fail git checkout fild file filf &&
+ test_cmp sample fild &&
+ test_cmp sample filf &&
+ test_cmp sample file
+'
+
+test_expect_success 'checkout with an unmerged path can be ignored' '
+ setup_conflicting_index &&
+ echo "none of the above" >sample &&
+ echo ourside >expect &&
+ cat sample >fild &&
+ cat sample >file &&
+ cat sample >filf &&
+ git checkout -f fild file filf &&
+ test_cmp expect fild &&
+ test_cmp expect filf &&
+ test_cmp sample file
+'
+
+test_expect_success 'checkout unmerged stage' '
+ setup_conflicting_index &&
+ echo "none of the above" >sample &&
+ echo ourside >expect &&
+ cat sample >fild &&
+ cat sample >file &&
+ cat sample >filf &&
+ git checkout --ours . &&
+ test_cmp expect fild &&
+ test_cmp expect filf &&
+ test_cmp expect file &&
+ git checkout --theirs file &&
+ test ztheirside = "z$(cat file)"
+'
+
+test_expect_success 'checkout with --merge' '
+ setup_conflicting_index &&
+ echo "none of the above" >sample &&
+ echo ourside >expect &&
+ cat sample >fild &&
+ cat sample >file &&
+ cat sample >filf &&
+ git checkout -m -- fild file filf &&
+ (
+ echo "<<<<<<< ours"
+ echo ourside
+ echo "======="
+ echo theirside
+ echo ">>>>>>> theirs"
+ ) >merged &&
+ test_cmp expect fild &&
+ test_cmp expect filf &&
+ test_cmp merged file
+'
+
+test_expect_success 'checkout with --merge, in diff3 -m style' '
+ git config merge.conflictstyle diff3 &&
+ setup_conflicting_index &&
+ echo "none of the above" >sample &&
+ echo ourside >expect &&
+ cat sample >fild &&
+ cat sample >file &&
+ cat sample >filf &&
+ git checkout -m -- fild file filf &&
+ (
+ echo "<<<<<<< ours"
+ echo ourside
+ echo "|||||||"
+ echo original
+ echo "======="
+ echo theirside
+ echo ">>>>>>> theirs"
+ ) >merged &&
+ test_cmp expect fild &&
+ test_cmp expect filf &&
+ test_cmp merged file
+'
+
+test_expect_success 'checkout --conflict=merge, overriding config' '
+ git config merge.conflictstyle diff3 &&
+ setup_conflicting_index &&
+ echo "none of the above" >sample &&
+ echo ourside >expect &&
+ cat sample >fild &&
+ cat sample >file &&
+ cat sample >filf &&
+ git checkout --conflict=merge -- fild file filf &&
+ (
+ echo "<<<<<<< ours"
+ echo ourside
+ echo "======="
+ echo theirside
+ echo ">>>>>>> theirs"
+ ) >merged &&
+ test_cmp expect fild &&
+ test_cmp expect filf &&
+ test_cmp merged file
+'
+
+test_expect_success 'checkout --conflict=diff3' '
+ git config --unset merge.conflictstyle
+ setup_conflicting_index &&
+ echo "none of the above" >sample &&
+ echo ourside >expect &&
+ cat sample >fild &&
+ cat sample >file &&
+ cat sample >filf &&
+ git checkout --conflict=diff3 -- fild file filf &&
+ (
+ echo "<<<<<<< ours"
+ echo ourside
+ echo "|||||||"
+ echo original
+ echo "======="
+ echo theirside
+ echo ">>>>>>> theirs"
+ ) >merged &&
+ test_cmp expect fild &&
+ test_cmp expect filf &&
+ test_cmp merged file
+'
+
+test_expect_success 'failing checkout -b should not break working tree' '
+ git reset --hard master &&
+ git symbolic-ref HEAD refs/heads/master &&
+ test_must_fail git checkout -b renamer side^ &&
+ test $(git symbolic-ref HEAD) = refs/heads/master &&
+ git diff --exit-code &&
+ git diff --cached --exit-code
+
+'
+
+test_expect_success 'switch out of non-branch' '
+ git reset --hard master &&
+ git checkout master^0 &&
+ echo modified >one &&
+ test_must_fail git checkout renamer 2>error.log &&
+ ! grep "^Previous HEAD" error.log
+'
test_done
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index a50492f7c0..118c6ebb18 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2007 Michael Spang
#
-test_description='git-clean basic tests'
+test_description='git clean basic tests'
. ./test-lib.sh
@@ -16,17 +16,17 @@ test_expect_success 'setup' '
echo build >.gitignore &&
echo \*.o >>.gitignore &&
git add . &&
- git-commit -m setup &&
+ git commit -m setup &&
touch src/part2.c README &&
git add .
'
-test_expect_success 'git-clean' '
+test_expect_success 'git clean' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean &&
+ git clean &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -39,11 +39,11 @@ test_expect_success 'git-clean' '
'
-test_expect_success 'git-clean src/' '
+test_expect_success 'git clean src/' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean src/ &&
+ git clean src/ &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -56,11 +56,11 @@ test_expect_success 'git-clean src/' '
'
-test_expect_success 'git-clean src/ src/' '
+test_expect_success 'git clean src/ src/' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean src/ src/ &&
+ git clean src/ src/ &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -73,11 +73,11 @@ test_expect_success 'git-clean src/ src/' '
'
-test_expect_success 'git-clean with prefix' '
+test_expect_success 'git clean with prefix' '
mkdir -p build docs src/test &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so src/test/1.c &&
- (cd src/ && git-clean) &&
+ (cd src/ && git clean) &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -91,7 +91,7 @@ test_expect_success 'git-clean with prefix' '
'
-test_expect_success 'git-clean with relative prefix' '
+test_expect_success 'git clean with relative prefix' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
@@ -106,13 +106,13 @@ test_expect_success 'git-clean with relative prefix' '
}
'
-test_expect_success 'git-clean with absolute path' '
+test_expect_success 'git clean with absolute path' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
would_clean=$(
cd docs &&
- git clean -n $(pwd)/../src |
+ git clean -n "$(pwd)/../src" |
sed -n -e "s|^Would remove ||p"
) &&
test "$would_clean" = ../src/part3.c || {
@@ -121,7 +121,7 @@ test_expect_success 'git-clean with absolute path' '
}
'
-test_expect_success 'git-clean with out of work tree relative path' '
+test_expect_success 'git clean with out of work tree relative path' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
@@ -131,7 +131,7 @@ test_expect_success 'git-clean with out of work tree relative path' '
)
'
-test_expect_success 'git-clean with out of work tree absolute path' '
+test_expect_success 'git clean with out of work tree absolute path' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
@@ -142,11 +142,11 @@ test_expect_success 'git-clean with out of work tree absolute path' '
)
'
-test_expect_success 'git-clean -d with prefix and path' '
+test_expect_success 'git clean -d with prefix and path' '
mkdir -p build docs src/feature &&
touch a.out src/part3.c src/feature/file.c docs/manual.txt obj.o build/lib.so &&
- (cd src/ && git-clean -d feature/) &&
+ (cd src/ && git clean -d feature/) &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -160,12 +160,12 @@ test_expect_success 'git-clean -d with prefix and path' '
'
-test_expect_success 'git-clean symbolic link' '
+test_expect_success 'git clean symbolic link' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
ln -s docs/manual.txt src/part4.c
- git-clean &&
+ git clean &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -179,10 +179,10 @@ test_expect_success 'git-clean symbolic link' '
'
-test_expect_success 'git-clean with wildcard' '
+test_expect_success 'git clean with wildcard' '
touch a.clean b.clean other.c &&
- git-clean "*.clean" &&
+ git clean "*.clean" &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -193,11 +193,11 @@ test_expect_success 'git-clean with wildcard' '
'
-test_expect_success 'git-clean -n' '
+test_expect_success 'git clean -n' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean -n &&
+ git clean -n &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -210,11 +210,11 @@ test_expect_success 'git-clean -n' '
'
-test_expect_success 'git-clean -d' '
+test_expect_success 'git clean -d' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean -d &&
+ git clean -d &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -227,11 +227,11 @@ test_expect_success 'git-clean -d' '
'
-test_expect_success 'git-clean -d src/ examples/' '
+test_expect_success 'git clean -d src/ examples/' '
mkdir -p build docs examples &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so examples/1.c &&
- git-clean -d src/ examples/ &&
+ git clean -d src/ examples/ &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -245,11 +245,11 @@ test_expect_success 'git-clean -d src/ examples/' '
'
-test_expect_success 'git-clean -x' '
+test_expect_success 'git clean -x' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean -x &&
+ git clean -x &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -262,11 +262,11 @@ test_expect_success 'git-clean -x' '
'
-test_expect_success 'git-clean -d -x' '
+test_expect_success 'git clean -d -x' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean -d -x &&
+ git clean -d -x &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -279,11 +279,11 @@ test_expect_success 'git-clean -d -x' '
'
-test_expect_success 'git-clean -X' '
+test_expect_success 'git clean -X' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean -X &&
+ git clean -X &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -296,11 +296,11 @@ test_expect_success 'git-clean -X' '
'
-test_expect_success 'git-clean -d -X' '
+test_expect_success 'git clean -d -X' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean -d -X &&
+ git clean -d -X &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -316,14 +316,14 @@ test_expect_success 'git-clean -d -X' '
test_expect_success 'clean.requireForce defaults to true' '
git config --unset clean.requireForce &&
- ! git-clean
+ test_must_fail git clean
'
test_expect_success 'clean.requireForce' '
git config clean.requireForce true &&
- ! git-clean
+ test_must_fail git clean
'
@@ -331,7 +331,7 @@ test_expect_success 'clean.requireForce and -n' '
mkdir -p build docs &&
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
- git-clean -n &&
+ git clean -n &&
test -f Makefile &&
test -f README &&
test -f src/part1.c &&
@@ -346,7 +346,7 @@ test_expect_success 'clean.requireForce and -n' '
test_expect_success 'clean.requireForce and -f' '
- git-clean -f &&
+ git clean -f &&
test -f README &&
test -f src/part1.c &&
test -f src/part2.c &&
@@ -373,11 +373,50 @@ test_expect_success 'removal failure' '
mkdir foo &&
touch foo/bar &&
- exec <foo/bar &&
- chmod 0 foo &&
- test_must_fail git clean -f -d
+ (exec <foo/bar &&
+ chmod 0 foo &&
+ test_must_fail git clean -f -d)
'
chmod 755 foo
+test_expect_success 'nested git work tree' '
+ rm -fr foo bar &&
+ mkdir foo bar &&
+ (
+ cd foo &&
+ git init &&
+ >hello.world
+ git add . &&
+ git commit -a -m nested
+ ) &&
+ (
+ cd bar &&
+ >goodbye.people
+ ) &&
+ git clean -f -d &&
+ test -f foo/.git/index &&
+ test -f foo/hello.world &&
+ ! test -d bar
+'
+
+test_expect_success 'force removal of nested git work tree' '
+ rm -fr foo bar &&
+ mkdir foo bar &&
+ (
+ cd foo &&
+ git init &&
+ >hello.world
+ git add . &&
+ git commit -a -m nested
+ ) &&
+ (
+ cd bar &&
+ >goodbye.people
+ ) &&
+ git clean -f -f -d &&
+ ! test -d foo &&
+ ! test -d bar
+'
+
test_done
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 2ef85a869d..a0cc99ab9f 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -6,7 +6,7 @@
test_description='Basic porcelain support for submodules
This test tries to verify basic sanity of the init, update and status
-subcommands of git-submodule.
+subcommands of git submodule.
'
. ./test-lib.sh
@@ -22,16 +22,16 @@ subcommands of git-submodule.
#
test_expect_success 'Prepare submodule testing' '
: > t &&
- git-add t &&
- git-commit -m "initial commit" &&
+ git add t &&
+ git commit -m "initial commit" &&
git branch initial HEAD &&
mkdir init &&
cd init &&
git init &&
echo a >a &&
git add a &&
- git-commit -m "submodule commit 1" &&
- git-tag -a -m "rev-1" rev-1 &&
+ git commit -m "submodule commit 1" &&
+ git tag -a -m "rev-1" rev-1 &&
rev1=$(git rev-parse HEAD) &&
if test -z "$rev1"
then
@@ -42,13 +42,72 @@ test_expect_success 'Prepare submodule testing' '
echo a >a &&
echo z >z &&
git add a init z &&
- git-commit -m "super commit 1" &&
+ git commit -m "super commit 1" &&
mv init .subrepo &&
GIT_CONFIG=.gitmodules git config submodule.example.url git://example.com/init.git
'
+test_expect_success 'Prepare submodule add testing' '
+ submodurl=$(pwd)
+ (
+ mkdir addtest &&
+ cd addtest &&
+ git init
+ )
+'
+
+test_expect_success 'submodule add' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" submod &&
+ git submodule init
+ )
+'
+
+test_expect_success 'submodule add --branch' '
+ (
+ cd addtest &&
+ git submodule add -b initial "$submodurl" submod-branch &&
+ git submodule init &&
+ cd submod-branch &&
+ git branch | grep initial
+ )
+'
+
+test_expect_success 'submodule add with ./ in path' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" ././dotsubmod/./frotz/./ &&
+ git submodule init
+ )
+'
+
+test_expect_success 'submodule add with // in path' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" slashslashsubmod///frotz// &&
+ git submodule init
+ )
+'
+
+test_expect_success 'submodule add with /.. in path' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. &&
+ git submodule init
+ )
+'
+
+test_expect_success 'submodule add with ./, /.. and // in path' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. &&
+ git submodule init
+ )
+'
+
test_expect_success 'status should fail for unmapped paths' '
- if git-submodule status
+ if git submodule status
then
echo "[OOPS] submodule status succeeded"
false
@@ -60,22 +119,22 @@ test_expect_success 'status should fail for unmapped paths' '
'
test_expect_success 'status should only print one line' '
- lines=$(git-submodule status | wc -l) &&
+ lines=$(git submodule status | wc -l) &&
test $lines = 1
'
test_expect_success 'status should initially be "missing"' '
- git-submodule status | grep "^-$rev1"
+ git submodule status | grep "^-$rev1"
'
test_expect_success 'init should register submodule url in .git/config' '
- git-submodule init &&
+ git submodule init &&
url=$(git config submodule.example.url) &&
if test "$url" != "git://example.com/init.git"
then
echo "[OOPS] init succeeded but submodule url is wrong"
false
- elif ! git config submodule.example.url ./.subrepo
+ elif test_must_fail git config submodule.example.url ./.subrepo
then
echo "[OOPS] init succeeded but update of url failed"
false
@@ -84,7 +143,7 @@ test_expect_success 'init should register submodule url in .git/config' '
test_expect_success 'update should fail when path is used by a file' '
echo "hello" >init &&
- if git-submodule update
+ if git submodule update
then
echo "[OOPS] update should have failed"
false
@@ -100,7 +159,7 @@ test_expect_success 'update should fail when path is used by a file' '
test_expect_success 'update should fail when path is used by a nonempty directory' '
mkdir init &&
echo "hello" >init/a &&
- if git-submodule update
+ if git submodule update
then
echo "[OOPS] update should have failed"
false
@@ -116,7 +175,7 @@ test_expect_success 'update should fail when path is used by a nonempty director
test_expect_success 'update should work when path is an empty dir' '
rm -rf init &&
mkdir init &&
- git-submodule update &&
+ git submodule update &&
head=$(cd init && git rev-parse HEAD) &&
if test -z "$head"
then
@@ -130,14 +189,14 @@ test_expect_success 'update should work when path is an empty dir' '
'
test_expect_success 'status should be "up-to-date" after update' '
- git-submodule status | grep "^ $rev1"
+ git submodule status | grep "^ $rev1"
'
test_expect_success 'status should be "modified" after submodule commit' '
cd init &&
echo b >b &&
git add b &&
- git-commit -m "submodule commit 2" &&
+ git commit -m "submodule commit 2" &&
rev2=$(git rev-parse HEAD) &&
cd .. &&
if test -z "$rev2"
@@ -145,19 +204,19 @@ test_expect_success 'status should be "modified" after submodule commit' '
echo "[OOPS] submodule git rev-parse returned nothing"
false
fi &&
- git-submodule status | grep "^+$rev2"
+ git submodule status | grep "^+$rev2"
'
test_expect_success 'the --cached sha1 should be rev1' '
- git-submodule --cached status | grep "^+$rev1"
+ git submodule --cached status | grep "^+$rev1"
'
test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
- git-diff | grep "^+Subproject commit $rev2"
+ git diff | grep "^+Subproject commit $rev2"
'
test_expect_success 'update should checkout rev1' '
- git-submodule update init &&
+ git submodule update init &&
head=$(cd init && git rev-parse HEAD) &&
if test -z "$head"
then
@@ -171,12 +230,12 @@ test_expect_success 'update should checkout rev1' '
'
test_expect_success 'status should be "up-to-date" after update' '
- git-submodule status | grep "^ $rev1"
+ git submodule status | grep "^ $rev1"
'
test_expect_success 'checkout superproject with subproject already present' '
- git-checkout initial &&
- git-checkout master
+ git checkout initial &&
+ git checkout master
'
test_expect_success 'apply submodule diff' '
@@ -188,12 +247,79 @@ test_expect_success 'apply submodule diff' '
git commit -m "change subproject"
) &&
git update-index --add init &&
- git-commit -m "change init" &&
- git-format-patch -1 --stdout >P.diff &&
+ git commit -m "change init" &&
+ git format-patch -1 --stdout >P.diff &&
git checkout second &&
git apply --index P.diff &&
D=$(git diff --cached master) &&
test -z "$D"
'
+test_expect_success 'update --init' '
+
+ mv init init2 &&
+ git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
+ git config --remove-section submodule.example
+ git submodule update init > update.out &&
+ grep "not initialized" update.out &&
+ test ! -d init/.git &&
+ git submodule update --init init &&
+ test -d init/.git
+
+'
+
+test_expect_success 'do not add files from a submodule' '
+
+ git reset --hard &&
+ test_must_fail git add init/a
+
+'
+
+test_expect_success 'gracefully add submodule with a trailing slash' '
+
+ git reset --hard &&
+ git commit -m "commit subproject" init &&
+ (cd init &&
+ echo b > a) &&
+ git add init/ &&
+ git diff --exit-code --cached init &&
+ commit=$(cd init &&
+ git commit -m update a >/dev/null &&
+ git rev-parse HEAD) &&
+ git add init/ &&
+ test_must_fail git diff --exit-code --cached init &&
+ test $commit = $(git ls-files --stage |
+ sed -n "s/^160000 \([^ ]*\).*/\1/p")
+
+'
+
+test_expect_success 'ls-files gracefully handles trailing slash' '
+
+ test "init" = "$(git ls-files init/)"
+
+'
+
+test_expect_success 'submodule <invalid-path> warns' '
+
+ git submodule no-such-submodule 2> output.err &&
+ grep "^error: .*no-such-submodule" output.err
+
+'
+
+test_expect_success 'add submodules without specifying an explicit path' '
+ mkdir repo &&
+ cd repo &&
+ git init &&
+ echo r >r &&
+ git add r &&
+ git commit -m "repo commit 1" &&
+ cd .. &&
+ git clone --bare repo/ bare.git &&
+ cd addtest &&
+ git submodule add "$submodurl/repo" &&
+ git config -f .gitmodules submodule.repo.path repo &&
+ git submodule add "$submodurl/bare.git" &&
+ git config -f .gitmodules submodule.bare.path bare
+'
+
test_done
diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index bf12dbdeef..6cc16c39fe 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -5,7 +5,7 @@
test_description='Summary support for submodules
-This test tries to verify the sanity of summary subcommand of git-submodule.
+This test tries to verify the sanity of summary subcommand of git submodule.
'
. ./test-lib.sh
@@ -56,6 +56,15 @@ test_expect_success 'modified submodule(forward)' "
EOF
"
+test_expect_success 'modified submodule(forward), --files' "
+ git submodule summary --files >actual &&
+ diff actual - <<-EOF
+* sm1 $head1...$head2 (1):
+ > Add foo3
+
+EOF
+"
+
commit_file sm1 &&
cd sm1 &&
git reset --hard HEAD~2 >/dev/null &&
@@ -114,6 +123,15 @@ test_expect_success 'typechanged submodule(submodule->blob), --cached' "
EOF
"
+test_expect_success 'typechanged submodule(submodule->blob), --files' "
+ git submodule summary --files >actual &&
+ diff actual - <<-EOF
+* sm1 $head5(blob)->$head4(submodule) (3):
+ > Add foo5
+
+EOF
+"
+
rm -rf sm1 &&
git checkout-index sm1
test_expect_success 'typechanged submodule(submodule->blob)' "
@@ -205,4 +223,8 @@ test_expect_success '--for-status' "
EOF
"
+test_expect_success 'fail when using --files together with --cached' "
+ test_must_fail git submodule summary --files --cached
+"
+
test_done
diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh
new file mode 100755
index 0000000000..f919c8d34d
--- /dev/null
+++ b/t/t7402-submodule-rebase.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Johannes Schindelin
+#
+
+test_description='Test rebasing and stashing with dirty submodules'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+ echo file > file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ git clone . submodule &&
+ git add submodule &&
+ test_tick &&
+ git commit -m submodule &&
+ echo second line >> file &&
+ (cd submodule && git pull) &&
+ test_tick &&
+ git commit -m file-and-submodule -a
+
+'
+
+test_expect_success 'rebase with a dirty submodule' '
+
+ (cd submodule &&
+ echo 3rd line >> file &&
+ test_tick &&
+ git commit -m fork -a) &&
+ echo unrelated >> file2 &&
+ git add file2 &&
+ test_tick &&
+ git commit -m unrelated file2 &&
+ echo other line >> file &&
+ test_tick &&
+ git commit -m update file &&
+ CURRENT=$(cd submodule && git rev-parse HEAD) &&
+ EXPECTED=$(git rev-parse HEAD~2:submodule) &&
+ GIT_TRACE=1 git rebase --onto HEAD~2 HEAD^ &&
+ STORED=$(git rev-parse HEAD:submodule) &&
+ test $EXPECTED = $STORED &&
+ test $CURRENT = $(cd submodule && git rev-parse HEAD)
+
+'
+
+cat > fake-editor.sh << \EOF
+#!/bin/sh
+echo $EDITOR_TEXT
+EOF
+chmod a+x fake-editor.sh
+
+test_expect_success 'interactive rebase with a dirty submodule' '
+
+ test submodule = $(git diff --name-only) &&
+ HEAD=$(git rev-parse HEAD) &&
+ GIT_EDITOR="\"$(pwd)/fake-editor.sh\"" EDITOR_TEXT="pick $HEAD" \
+ git rebase -i HEAD^ &&
+ test submodule = $(git diff --name-only)
+
+'
+
+test_expect_success 'rebase with dirty file and submodule fails' '
+
+ echo yet another line >> file &&
+ test_tick &&
+ git commit -m next file &&
+ echo rewrite > file &&
+ test_tick &&
+ git commit -m rewrite file &&
+ echo dirty > file &&
+ test_must_fail git rebase --onto HEAD~2 HEAD^
+
+'
+
+test_expect_success 'stash with a dirty submodule' '
+
+ echo new > file &&
+ CURRENT=$(cd submodule && git rev-parse HEAD) &&
+ git stash &&
+ test new != $(cat file) &&
+ test submodule = $(git diff --name-only) &&
+ test $CURRENT = $(cd submodule && git rev-parse HEAD) &&
+ git stash apply &&
+ test new = $(cat file) &&
+ test $CURRENT = $(cd submodule && git rev-parse HEAD)
+
+'
+
+test_done
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
new file mode 100755
index 0000000000..7538756487
--- /dev/null
+++ b/t/t7403-submodule-sync.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 David Aguilar
+#
+
+test_description='git submodule sync
+
+These tests exercise the "git submodule sync" subcommand.
+'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo file > file &&
+ git add file &&
+ test_tick &&
+ git commit -m upstream
+ git clone . super &&
+ git clone super submodule &&
+ (cd super &&
+ git submodule add ../submodule submodule &&
+ test_tick &&
+ git commit -m "submodule"
+ ) &&
+ git clone super super-clone &&
+ (cd super-clone && git submodule update --init)
+'
+
+test_expect_success 'change submodule' '
+ (cd submodule &&
+ echo second line >> file &&
+ test_tick &&
+ git commit -a -m "change submodule"
+ )
+'
+
+test_expect_success 'change submodule url' '
+ (cd super &&
+ cd submodule &&
+ git checkout master &&
+ git pull
+ ) &&
+ mv submodule moved-submodule &&
+ (cd super &&
+ git config -f .gitmodules submodule.submodule.url ../moved-submodule
+ test_tick &&
+ git commit -a -m moved-submodule
+ )
+'
+
+test_expect_success '"git submodule sync" should update submodule URLs' '
+ (cd super-clone &&
+ git pull &&
+ git submodule sync
+ ) &&
+ test -d "$(git config -f super-clone/submodule/.git/config \
+ remote.origin.url)" &&
+ (cd super-clone/submodule &&
+ git checkout master &&
+ git pull
+ )
+'
+
+test_done
diff --git a/t/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh
new file mode 100755
index 0000000000..9a21f783d3
--- /dev/null
+++ b/t/t7405-submodule-merge.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+test_description='merging with submodules'
+
+. ./test-lib.sh
+
+#
+# history
+#
+# a --- c
+# / \ /
+# root X
+# \ / \
+# b --- d
+#
+
+test_expect_success setup '
+
+ mkdir sub &&
+ (cd sub &&
+ git init &&
+ echo original > file &&
+ git add file &&
+ test_tick &&
+ git commit -m sub-root) &&
+ git add sub &&
+ test_tick &&
+ git commit -m root &&
+
+ git checkout -b a master &&
+ (cd sub &&
+ echo A > file &&
+ git add file &&
+ test_tick &&
+ git commit -m sub-a) &&
+ git add sub &&
+ test_tick &&
+ git commit -m a &&
+
+ git checkout -b b master &&
+ (cd sub &&
+ echo B > file &&
+ git add file &&
+ test_tick &&
+ git commit -m sub-b) &&
+ git add sub &&
+ test_tick &&
+ git commit -m b
+
+ git checkout -b c a &&
+ git merge -s ours b &&
+
+ git checkout -b d b &&
+ git merge -s ours a
+'
+
+test_expect_success 'merging with modify/modify conflict' '
+
+ git checkout -b test1 a &&
+ test_must_fail git merge b &&
+ test -f .git/MERGE_MSG &&
+ git diff &&
+ test -n "$(git ls-files -u)"
+'
+
+test_expect_success 'merging with a modify/modify conflict between merge bases' '
+
+ git reset --hard HEAD &&
+ git checkout -b test2 c &&
+ git merge d
+
+'
+
+test_done
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
new file mode 100755
index 0000000000..8e2449d244
--- /dev/null
+++ b/t/t7406-submodule-update.sh
@@ -0,0 +1,198 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Red Hat, Inc.
+#
+
+test_description='Test updating submodules
+
+This test verifies that "git submodule update" detaches the HEAD of the
+submodule and "git submodule update --rebase/--merge" does not detach the HEAD.
+'
+
+. ./test-lib.sh
+
+
+compare_head()
+{
+ sha_master=`git rev-list --max-count=1 master`
+ sha_head=`git rev-list --max-count=1 HEAD`
+
+ test "$sha_master" = "$sha_head"
+}
+
+
+test_expect_success 'setup a submodule tree' '
+ echo file > file &&
+ git add file &&
+ test_tick &&
+ git commit -m upstream
+ git clone . super &&
+ git clone super submodule &&
+ (cd super &&
+ git submodule add ../submodule submodule &&
+ test_tick &&
+ git commit -m "submodule" &&
+ git submodule init submodule
+ ) &&
+ (cd submodule &&
+ echo "line2" > file &&
+ git add file &&
+ git commit -m "Commit 2"
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ git pull --rebase origin
+ ) &&
+ git add submodule &&
+ git commit -m "submodule update"
+ )
+'
+
+test_expect_success 'submodule update detaching the HEAD ' '
+ (cd super/submodule &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update submodule &&
+ cd submodule &&
+ ! compare_head
+ )
+'
+
+test_expect_success 'submodule update --rebase staying on master' '
+ (cd super/submodule &&
+ git checkout master
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update --rebase submodule &&
+ cd submodule &&
+ compare_head
+ )
+'
+
+test_expect_success 'submodule update --merge staying on master' '
+ (cd super/submodule &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update --merge submodule &&
+ cd submodule &&
+ compare_head
+ )
+'
+
+test_expect_success 'submodule update - rebase in .git/config' '
+ (cd super &&
+ git config submodule.submodule.update rebase
+ ) &&
+ (cd super/submodule &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update submodule &&
+ cd submodule &&
+ compare_head
+ )
+'
+
+test_expect_success 'submodule update - checkout in .git/config but --rebase given' '
+ (cd super &&
+ git config submodule.submodule.update checkout
+ ) &&
+ (cd super/submodule &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update --rebase submodule &&
+ cd submodule &&
+ compare_head
+ )
+'
+
+test_expect_success 'submodule update - merge in .git/config' '
+ (cd super &&
+ git config submodule.submodule.update merge
+ ) &&
+ (cd super/submodule &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update submodule &&
+ cd submodule &&
+ compare_head
+ )
+'
+
+test_expect_success 'submodule update - checkout in .git/config but --merge given' '
+ (cd super &&
+ git config submodule.submodule.update checkout
+ ) &&
+ (cd super/submodule &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update --merge submodule &&
+ cd submodule &&
+ compare_head
+ )
+'
+
+test_expect_success 'submodule update - checkout in .git/config' '
+ (cd super &&
+ git config submodule.submodule.update checkout
+ ) &&
+ (cd super/submodule &&
+ git reset --hard HEAD^
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update submodule &&
+ cd submodule &&
+ ! compare_head
+ )
+'
+
+test_expect_success 'submodule init picks up rebase' '
+ (cd super &&
+ git config submodule.rebasing.url git://non-existing/git &&
+ git config submodule.rebasing.path does-not-matter &&
+ git config submodule.rebasing.update rebase &&
+ git submodule init rebasing &&
+ test "rebase" = $(git config submodule.rebasing.update)
+ )
+'
+
+test_expect_success 'submodule init picks up merge' '
+ (cd super &&
+ git config submodule.merging.url git://non-existing/git &&
+ git config submodule.merging.path does-not-matter &&
+ git config submodule.merging.update merge &&
+ git submodule init merging &&
+ test "merge" = $(git config submodule.merging.update)
+ )
+'
+
+test_done
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
new file mode 100755
index 0000000000..2a527750ce
--- /dev/null
+++ b/t/t7407-submodule-foreach.sh
@@ -0,0 +1,237 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Johan Herland
+#
+
+test_description='Test "git submodule foreach"
+
+This test verifies that "git submodule foreach" correctly visits all submodules
+that are currently checked out.
+'
+
+. ./test-lib.sh
+
+
+test_expect_success 'setup a submodule tree' '
+ echo file > file &&
+ git add file &&
+ test_tick &&
+ git commit -m upstream
+ git clone . super &&
+ git clone super submodule &&
+ (
+ cd super &&
+ git submodule add ../submodule sub1 &&
+ git submodule add ../submodule sub2 &&
+ git submodule add ../submodule sub3 &&
+ git config -f .gitmodules --rename-section \
+ submodule.sub1 submodule.foo1 &&
+ git config -f .gitmodules --rename-section \
+ submodule.sub2 submodule.foo2 &&
+ git config -f .gitmodules --rename-section \
+ submodule.sub3 submodule.foo3 &&
+ git add .gitmodules
+ test_tick &&
+ git commit -m "submodules" &&
+ git submodule init sub1 &&
+ git submodule init sub2 &&
+ git submodule init sub3
+ ) &&
+ (
+ cd submodule &&
+ echo different > file &&
+ git add file &&
+ test_tick &&
+ git commit -m "different"
+ ) &&
+ (
+ cd super &&
+ (
+ cd sub3 &&
+ git pull
+ ) &&
+ git add sub3 &&
+ test_tick &&
+ git commit -m "update sub3"
+ )
+'
+
+sub1sha1=$(cd super/sub1 && git rev-parse HEAD)
+sub3sha1=$(cd super/sub3 && git rev-parse HEAD)
+
+cat > expect <<EOF
+Entering 'sub1'
+foo1-sub1-$sub1sha1
+Entering 'sub3'
+foo3-sub3-$sub3sha1
+EOF
+
+test_expect_success 'test basic "submodule foreach" usage' '
+ git clone super clone &&
+ (
+ cd clone &&
+ git submodule update --init -- sub1 sub3 &&
+ git submodule foreach "echo \$name-\$path-\$sha1" > ../actual
+ ) &&
+ test_cmp expect actual
+'
+
+test_expect_success 'setup nested submodules' '
+ git clone submodule nested1 &&
+ git clone submodule nested2 &&
+ git clone submodule nested3 &&
+ (
+ cd nested3 &&
+ git submodule add ../submodule submodule &&
+ test_tick &&
+ git commit -m "submodule" &&
+ git submodule init submodule
+ ) &&
+ (
+ cd nested2 &&
+ git submodule add ../nested3 nested3 &&
+ test_tick &&
+ git commit -m "nested3" &&
+ git submodule init nested3
+ ) &&
+ (
+ cd nested1 &&
+ git submodule add ../nested2 nested2 &&
+ test_tick &&
+ git commit -m "nested2" &&
+ git submodule init nested2
+ ) &&
+ (
+ cd super &&
+ git submodule add ../nested1 nested1 &&
+ test_tick &&
+ git commit -m "nested1" &&
+ git submodule init nested1
+ )
+'
+
+test_expect_success 'use "submodule foreach" to checkout 2nd level submodule' '
+ git clone super clone2 &&
+ (
+ cd clone2 &&
+ test ! -d sub1/.git &&
+ test ! -d sub2/.git &&
+ test ! -d sub3/.git &&
+ test ! -d nested1/.git &&
+ git submodule update --init &&
+ test -d sub1/.git &&
+ test -d sub2/.git &&
+ test -d sub3/.git &&
+ test -d nested1/.git &&
+ test ! -d nested1/nested2/.git &&
+ git submodule foreach "git submodule update --init" &&
+ test -d nested1/nested2/.git &&
+ test ! -d nested1/nested2/nested3/.git
+ )
+'
+
+test_expect_success 'use "foreach --recursive" to checkout all submodules' '
+ (
+ cd clone2 &&
+ git submodule foreach --recursive "git submodule update --init" &&
+ test -d nested1/nested2/nested3/.git &&
+ test -d nested1/nested2/nested3/submodule/.git
+ )
+'
+
+cat > expect <<EOF
+Entering 'nested1'
+Entering 'nested1/nested2'
+Entering 'nested1/nested2/nested3'
+Entering 'nested1/nested2/nested3/submodule'
+Entering 'sub1'
+Entering 'sub2'
+Entering 'sub3'
+EOF
+
+test_expect_success 'test messages from "foreach --recursive"' '
+ (
+ cd clone2 &&
+ git submodule foreach --recursive "true" > ../actual
+ ) &&
+ test_cmp expect actual
+'
+
+cat > expect <<EOF
+nested1-nested1
+nested2-nested2
+nested3-nested3
+submodule-submodule
+foo1-sub1
+foo2-sub2
+foo3-sub3
+EOF
+
+test_expect_success 'test "foreach --quiet --recursive"' '
+ (
+ cd clone2 &&
+ git submodule foreach -q --recursive "echo \$name-\$path" > ../actual
+ ) &&
+ test_cmp expect actual
+'
+
+test_expect_success 'use "update --recursive" to checkout all submodules' '
+ git clone super clone3 &&
+ (
+ cd clone3 &&
+ test ! -d sub1/.git &&
+ test ! -d sub2/.git &&
+ test ! -d sub3/.git &&
+ test ! -d nested1/.git &&
+ git submodule update --init --recursive &&
+ test -d sub1/.git &&
+ test -d sub2/.git &&
+ test -d sub3/.git &&
+ test -d nested1/.git &&
+ test -d nested1/nested2/.git &&
+ test -d nested1/nested2/nested3/.git &&
+ test -d nested1/nested2/nested3/submodule/.git
+ )
+'
+
+nested1sha1=$(cd clone3/nested1 && git rev-parse HEAD)
+nested2sha1=$(cd clone3/nested1/nested2 && git rev-parse HEAD)
+nested3sha1=$(cd clone3/nested1/nested2/nested3 && git rev-parse HEAD)
+submodulesha1=$(cd clone3/nested1/nested2/nested3/submodule && git rev-parse HEAD)
+sub1sha1=$(cd clone3/sub1 && git rev-parse HEAD)
+sub2sha1=$(cd clone3/sub2 && git rev-parse HEAD)
+sub3sha1=$(cd clone3/sub3 && git rev-parse HEAD)
+sub1sha1_short=$(cd clone3/sub1 && git rev-parse --short HEAD)
+sub2sha1_short=$(cd clone3/sub2 && git rev-parse --short HEAD)
+
+cat > expect <<EOF
+ $nested1sha1 nested1 (heads/master)
+ $nested2sha1 nested1/nested2 (heads/master)
+ $nested3sha1 nested1/nested2/nested3 (heads/master)
+ $submodulesha1 nested1/nested2/nested3/submodule (heads/master)
+ $sub1sha1 sub1 ($sub1sha1_short)
+ $sub2sha1 sub2 ($sub2sha1_short)
+ $sub3sha1 sub3 (heads/master)
+EOF
+
+test_expect_success 'test "status --recursive"' '
+ (
+ cd clone3 &&
+ git submodule status --recursive > ../actual
+ ) &&
+ test_cmp expect actual
+'
+
+test_expect_success 'use "git clone --recursive" to checkout all submodules' '
+ git clone --recursive super clone4 &&
+ test -d clone4/.git &&
+ test -d clone4/sub1/.git &&
+ test -d clone4/sub2/.git &&
+ test -d clone4/sub3/.git &&
+ test -d clone4/nested1/.git &&
+ test -d clone4/nested1/nested2/.git &&
+ test -d clone4/nested1/nested2/nested3/.git &&
+ test -d clone4/nested1/nested2/nested3/submodule/.git
+'
+
+test_done
diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh
new file mode 100755
index 0000000000..cc16d3f05d
--- /dev/null
+++ b/t/t7408-submodule-reference.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+#
+# Copyright (c) 2009, Red Hat Inc, Author: Michael S. Tsirkin (mst@redhat.com)
+#
+
+test_description='test clone --reference'
+. ./test-lib.sh
+
+base_dir=`pwd`
+
+U=$base_dir/UPLOAD_LOG
+
+test_expect_success 'preparing first repository' \
+'test_create_repo A && cd A &&
+echo first > file1 &&
+git add file1 &&
+git commit -m A-initial'
+
+cd "$base_dir"
+
+test_expect_success 'preparing second repository' \
+'git clone A B && cd B &&
+echo second > file2 &&
+git add file2 &&
+git commit -m B-addition &&
+git repack -a -d &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_success 'preparing supermodule' \
+'test_create_repo super && cd super &&
+echo file > file &&
+git add file &&
+git commit -m B-super-initial'
+
+cd "$base_dir"
+
+test_expect_success 'submodule add --reference' \
+'cd super && git submodule add --reference ../B "file://$base_dir/A" sub &&
+git commit -m B-super-added'
+
+cd "$base_dir"
+
+test_expect_success 'after add: existence of info/alternates' \
+'test `wc -l <super/sub/.git/objects/info/alternates` = 1'
+
+cd "$base_dir"
+
+test_expect_success 'that reference gets used with add' \
+'cd super/sub &&
+echo "0 objects, 0 kilobytes" > expected &&
+git count-objects > current &&
+diff expected current'
+
+cd "$base_dir"
+
+test_expect_success 'cloning supermodule' \
+'git clone super super-clone'
+
+cd "$base_dir"
+
+test_expect_success 'update with reference' \
+'cd super-clone && git submodule update --init --reference ../B'
+
+cd "$base_dir"
+
+test_expect_success 'after update: existence of info/alternates' \
+'test `wc -l <super-clone/sub/.git/objects/info/alternates` = 1'
+
+cd "$base_dir"
+
+test_expect_success 'that reference gets used with update' \
+'cd super-clone/sub &&
+echo "0 objects, 0 kilobytes" > expected &&
+git count-objects > current &&
+diff expected current'
+
+cd "$base_dir"
+
+test_done
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index baed6ce96b..8eec0fa9bc 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2007 Steven Grimm
#
-test_description='git-commit
+test_description='git commit
Tests for selected commit options.'
@@ -23,12 +23,12 @@ test_expect_success 'a basic commit in an empty tree should succeed' '
test_expect_success 'nonexistent template file should return error' '
echo changes >> foo &&
git add foo &&
- ! git commit --template "$PWD"/notexist
+ test_must_fail git commit --template "$PWD"/notexist
'
test_expect_success 'nonexistent template file in config should return error' '
git config commit.template "$PWD"/notexist &&
- ! git commit &&
+ test_must_fail git commit &&
git config --unset commit.template
'
@@ -37,24 +37,33 @@ TEMPLATE="$PWD"/template
test_expect_success 'unedited template should not commit' '
echo "template line" > "$TEMPLATE" &&
- ! git commit --template "$TEMPLATE"
+ test_must_fail git commit --template "$TEMPLATE"
'
test_expect_success 'unedited template with comments should not commit' '
echo "# comment in template" >> "$TEMPLATE" &&
- ! git commit --template "$TEMPLATE"
+ test_must_fail git commit --template "$TEMPLATE"
'
test_expect_success 'a Signed-off-by line by itself should not commit' '
- ! GIT_EDITOR=../t7500/add-signed-off git commit --template "$TEMPLATE"
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-signed-off &&
+ test_must_fail git commit --template "$TEMPLATE"
+ )
'
test_expect_success 'adding comments to a template should not commit' '
- ! GIT_EDITOR=../t7500/add-comments git commit --template "$TEMPLATE"
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-comments &&
+ test_must_fail git commit --template "$TEMPLATE"
+ )
'
test_expect_success 'adding real content to a template should commit' '
- GIT_EDITOR=../t7500/add-content git commit --template "$TEMPLATE" &&
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit --template "$TEMPLATE"
+ ) &&
commit_msg_is "template linecommit message"
'
@@ -62,7 +71,10 @@ test_expect_success '-t option should be short for --template' '
echo "short template" > "$TEMPLATE" &&
echo "new content" >> foo &&
git add foo &&
- GIT_EDITOR=../t7500/add-content git commit -t "$TEMPLATE" &&
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit -t "$TEMPLATE"
+ ) &&
commit_msg_is "short templatecommit message"
'
@@ -71,7 +83,10 @@ test_expect_success 'config-specified template should commit' '
git config commit.template "$TEMPLATE" &&
echo "more content" >> foo &&
git add foo &&
- GIT_EDITOR=../t7500/add-content git commit &&
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit
+ ) &&
git config --unset commit.template &&
commit_msg_is "new templatecommit message"
'
@@ -79,7 +94,7 @@ test_expect_success 'config-specified template should commit' '
test_expect_success 'explicit commit message should override template' '
echo "still more content" >> foo &&
git add foo &&
- GIT_EDITOR=../t7500/add-content git commit --template "$TEMPLATE" \
+ GIT_EDITOR="$TEST_DIRECTORY"/t7500/add-content git commit --template "$TEMPLATE" \
-m "command line msg" &&
commit_msg_is "command line msg"
'
@@ -88,8 +103,10 @@ test_expect_success 'commit message from file should override template' '
echo "content galore" >> foo &&
git add foo &&
echo "standard input msg" |
- GIT_EDITOR=../t7500/add-content git commit \
- --template "$TEMPLATE" --file - &&
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit --template "$TEMPLATE" --file -
+ ) &&
commit_msg_is "standard input msg"
'
@@ -132,10 +149,48 @@ EOF
test_expect_success '--signoff' '
echo "yet another content *narf*" >> foo &&
- echo "zort" |
- GIT_EDITOR=../t7500/add-content git commit -s -F - foo &&
+ echo "zort" | git commit -s -F - foo &&
git cat-file commit HEAD | sed "1,/^$/d" > output &&
- diff expect output
+ test_cmp expect output
+'
+
+test_expect_success 'commit message from file (1)' '
+ mkdir subdir &&
+ echo "Log in top directory" >log &&
+ echo "Log in sub directory" >subdir/log &&
+ (
+ cd subdir &&
+ git commit --allow-empty -F log
+ ) &&
+ commit_msg_is "Log in sub directory"
+'
+
+test_expect_success 'commit message from file (2)' '
+ rm -f log &&
+ echo "Log in sub directory" >subdir/log &&
+ (
+ cd subdir &&
+ git commit --allow-empty -F log
+ ) &&
+ commit_msg_is "Log in sub directory"
+'
+
+test_expect_success 'commit message from stdin' '
+ (
+ cd subdir &&
+ echo "Log with foo word" | git commit --allow-empty -F -
+ ) &&
+ commit_msg_is "Log with foo word"
+'
+
+test_expect_success 'commit -F overrides -t' '
+ (
+ cd subdir &&
+ echo "-F log" > f.log &&
+ echo "-t template" > t.template &&
+ git commit --allow-empty -F f.log -t t.template
+ ) &&
+ commit_msg_is "-F log"
'
test_done
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index c0288f345f..a603f6d21a 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -6,7 +6,7 @@
# FIXME: Test the various index usages, -i and -o, test reflog,
# signoff
-test_description='git-commit'
+test_description='git commit'
. ./test-lib.sh
test_tick
@@ -14,52 +14,52 @@ test_tick
test_expect_success \
"initial status" \
"echo 'bongo bongo' >file &&
- git-add file && \
- git-status | grep 'Initial commit'"
+ git add file && \
+ git status | grep 'Initial commit'"
test_expect_success \
"fail initial amend" \
- "! git-commit --amend"
+ "test_must_fail git commit --amend"
test_expect_success \
"initial commit" \
- "git-commit -m initial"
+ "git commit -m initial"
test_expect_success \
"invalid options 1" \
- "! git-commit -m foo -m bar -F file"
+ "test_must_fail git commit -m foo -m bar -F file"
test_expect_success \
"invalid options 2" \
- "! git-commit -C HEAD -m illegal"
+ "test_must_fail git commit -C HEAD -m illegal"
test_expect_success \
"using paths with -a" \
"echo King of the bongo >file &&
- ! git-commit -m foo -a file"
+ test_must_fail git commit -m foo -a file"
-test_expect_success \
+test_expect_success PERL \
"using paths with --interactive" \
"echo bong-o-bong >file &&
- ! echo 7 | git-commit -m foo --interactive file"
+ ! (echo 7 | git commit -m foo --interactive file)"
test_expect_success \
"using invalid commit with -C" \
- "! git-commit -C bogus"
+ "test_must_fail git commit -C bogus"
test_expect_success \
"testing nothing to commit" \
- "! git-commit -m initial"
+ "test_must_fail git commit -m initial"
test_expect_success \
"next commit" \
"echo 'bongo bongo bongo' >file \
- git-commit -m next -a"
+ git commit -m next -a"
test_expect_success \
"commit message from non-existing file" \
"echo 'more bongo: bongo bongo bongo bongo' >file && \
- ! git-commit -F gah -a"
+ test_must_fail git commit -F gah -a"
# Empty except stray tabs and spaces on a few lines.
sed -e 's/@$//' >msg <<EOF
@@ -70,63 +70,83 @@ Signed-off-by: hula
EOF
test_expect_success \
"empty commit message" \
- "! git-commit -F msg -a"
+ "test_must_fail git commit -F msg -a"
test_expect_success \
"commit message from file" \
"echo 'this is the commit message, coming from a file' >msg && \
- git-commit -F msg -a"
+ git commit -F msg -a"
cat >editor <<\EOF
#!/bin/sh
-sed -e "s/a file/an amend commit/g" < $1 > $1-
-mv $1- $1
+sed -e "s/a file/an amend commit/g" < "$1" > "$1-"
+mv "$1-" "$1"
EOF
chmod 755 editor
test_expect_success \
"amend commit" \
- "VISUAL=./editor git-commit --amend"
+ "EDITOR=./editor git commit --amend"
test_expect_success \
"passing -m and -F" \
"echo 'enough with the bongos' >file && \
- ! git-commit -F msg -m amending ."
+ test_must_fail git commit -F msg -m amending ."
test_expect_success \
"using message from other commit" \
- "git-commit -C HEAD^ ."
+ "git commit -C HEAD^ ."
cat >editor <<\EOF
#!/bin/sh
-sed -e "s/amend/older/g" < $1 > $1-
-mv $1- $1
+sed -e "s/amend/older/g" < "$1" > "$1-"
+mv "$1-" "$1"
EOF
chmod 755 editor
test_expect_success \
"editing message from other commit" \
"echo 'hula hula' >file && \
- VISUAL=./editor git-commit -c HEAD^ -a"
+ EDITOR=./editor git commit -c HEAD^ -a"
test_expect_success \
"message from stdin" \
"echo 'silly new contents' >file && \
- echo commit message from stdin | git-commit -F - -a"
+ echo commit message from stdin | git commit -F - -a"
test_expect_success \
"overriding author from command line" \
"echo 'gak' >file && \
- git-commit -m 'author' --author 'Rubber Duck <rduck@convoy.org>' -a"
+ git commit -m 'author' --author 'Rubber Duck <rduck@convoy.org>' -a"
-test_expect_success \
+test_expect_success PERL \
"interactive add" \
- "echo 7 | git-commit --interactive | grep 'What now'"
+ "echo 7 | git commit --interactive | grep 'What now'"
test_expect_success \
"showing committed revisions" \
- "git-rev-list HEAD >current"
+ "git rev-list HEAD >current"
+
+cat >editor <<\EOF
+#!/bin/sh
+sed -e "s/good/bad/g" < "$1" > "$1-"
+mv "$1-" "$1"
+EOF
+chmod 755 editor
+
+cat >msg <<EOF
+A good commit message.
+EOF
+test_expect_success \
+ 'editor not invoked if -F is given' '
+ echo "moo" >file &&
+ EDITOR=./editor git commit -a -F msg &&
+ git show -s --pretty=format:"%s" | grep -q good &&
+ echo "quack" >file &&
+ echo "Another good message." | EDITOR=./editor git commit -a -F - &&
+ git show -s --pretty=format:"%s" | grep -q good
+ '
# We could just check the head sha1, but checking each commit makes it
# easier to isolate bugs.
@@ -140,8 +160,8 @@ d381ac431806e53f3dd7ac2f1ae0534f36d738b9
EOF
test_expect_success \
- 'validate git-rev-list output.' \
- 'diff current expected'
+ 'validate git rev-list output.' \
+ 'test_cmp expected current'
test_expect_success 'partial commit that involves removal (1)' '
@@ -151,7 +171,7 @@ test_expect_success 'partial commit that involves removal (1)' '
git commit -m "Partial: add elif" elif &&
git diff-tree --name-status HEAD^ HEAD >current &&
echo "A elif" >expected &&
- diff expected current
+ test_cmp expected current
'
@@ -160,7 +180,7 @@ test_expect_success 'partial commit that involves removal (2)' '
git commit -m "Partial: remove file" file &&
git diff-tree --name-status HEAD^ HEAD >current &&
echo "D file" >expected &&
- diff expected current
+ test_cmp expected current
'
@@ -171,7 +191,7 @@ test_expect_success 'partial commit that involves removal (3)' '
git commit -m "Partial: modify elif" elif &&
git diff-tree --name-status HEAD^ HEAD >current &&
echo "M elif" >expected &&
- diff expected current
+ test_cmp expected current
'
@@ -187,7 +207,7 @@ test_expect_success 'amend commit to fix author' '
expected &&
git commit --amend --author="$author" &&
git cat-file -p HEAD > current &&
- diff expected current
+ test_cmp expected current
'
@@ -227,6 +247,47 @@ $existing" &&
'
+test_expect_success 'signoff gap' '
+
+ echo 3 >positive &&
+ git add positive &&
+ alt="Alt-RFC-822-Header: Value" &&
+ git commit -s -m "welcome
+
+$alt" &&
+ git cat-file commit HEAD | sed -e "1,/^\$/d" > actual &&
+ (
+ echo welcome
+ echo
+ echo $alt
+ git var GIT_COMMITTER_IDENT |
+ sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
+ ) >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'signoff gap 2' '
+
+ echo 4 >positive &&
+ git add positive &&
+ alt="fixed: 34" &&
+ git commit -s -m "welcome
+
+We have now
+$alt" &&
+ git cat-file commit HEAD | sed -e "1,/^\$/d" > actual &&
+ (
+ echo welcome
+ echo
+ echo We have now
+ echo $alt
+ echo
+ git var GIT_COMMITTER_IDENT |
+ sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
+ ) >expected &&
+ test_cmp expected actual
+'
+
test_expect_success 'multiple -m' '
>negative &&
@@ -256,7 +317,7 @@ test_expect_success 'amend commit to fix author' '
expected &&
git commit --amend --author="$author" &&
git cat-file -p HEAD > current &&
- diff expected current
+ test_cmp expected current
'
diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index 284c941247..fe94552296 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -89,6 +89,14 @@ test_expect_success 'verbose' '
'
+test_expect_success 'verbose respects diff config' '
+
+ git config color.diff always &&
+ git status -v >actual &&
+ grep "\[1mdiff --git" actual &&
+ git config --unset color.diff
+'
+
test_expect_success 'cleanup commit messages (verbatim,-t)' '
echo >>negative &&
@@ -141,8 +149,8 @@ test_expect_success 'cleanup commit messages (strip,-F)' '
echo "sample
-# Please enter the commit message for your changes.
-# (Comment lines starting with '#' will not be included)" >expect
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit." >expect
test_expect_success 'cleanup commit messages (strip,-F,-e)' '
@@ -154,6 +162,38 @@ test_expect_success 'cleanup commit messages (strip,-F,-e)' '
'
+echo "#
+# Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
+#" >> expect
+
+test_expect_success 'author different from committer' '
+
+ echo >>negative &&
+ git commit -e -m "sample"
+ head -n 7 .git/COMMIT_EDITMSG >actual &&
+ test_cmp expect actual
+'
+
+mv expect expect.tmp
+sed '$d' < expect.tmp > expect
+rm -f expect.tmp
+echo "# Committer:
+#" >> expect
+
+test_expect_success 'committer is automatic' '
+
+ echo >>negative &&
+ (
+ unset GIT_COMMITTER_EMAIL
+ unset GIT_COMMITTER_NAME
+ # must fail because there is no change
+ test_must_fail git commit -e -m "sample"
+ ) &&
+ head -n 8 .git/COMMIT_EDITMSG | \
+ sed "s/^# Committer: .*/# Committer:/" >actual &&
+ test_cmp expect actual
+'
+
pwd=`pwd`
cat >> .git/FAKE_EDITOR << EOF
#! /bin/sh
@@ -164,23 +204,67 @@ chmod +x .git/FAKE_EDITOR
test_expect_success 'do not fire editor in the presence of conflicts' '
- git clean
- echo f>g
- git add g
- git commit -myes
- git branch second
- echo master>g
- echo g>h
- git add g h
- git commit -mmaster
- git checkout second
- echo second>g
- git add g
- git commit -msecond
- git cherry-pick -n master
- echo "editor not started" > .git/result
- GIT_EDITOR=`pwd`/.git/FAKE_EDITOR git commit && exit 1 # should fail
- test "`cat .git/result`" = "editor not started"
+ git clean -f &&
+ echo f >g &&
+ git add g &&
+ git commit -m "add g" &&
+ git branch second &&
+ echo master >g &&
+ echo g >h &&
+ git add g h &&
+ git commit -m "modify g and add h" &&
+ git checkout second &&
+ echo second >g &&
+ git add g &&
+ git commit -m second &&
+ # Must fail due to conflict
+ test_must_fail git cherry-pick -n master &&
+ echo "editor not started" >.git/result &&
+ (
+ GIT_EDITOR="$(pwd)/.git/FAKE_EDITOR" &&
+ export GIT_EDITOR &&
+ test_must_fail git commit
+ ) &&
+ test "$(cat .git/result)" = "editor not started"
+'
+
+pwd=`pwd`
+cat >.git/FAKE_EDITOR <<EOF
+#! $SHELL_PATH
+# kill -TERM command added below.
+EOF
+
+test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' '
+ echo >>negative &&
+ ! "$SHELL_PATH" -c '\''
+ echo kill -TERM $$ >> .git/FAKE_EDITOR
+ GIT_EDITOR=.git/FAKE_EDITOR
+ export GIT_EDITOR
+ exec git commit -a'\'' &&
+ test ! -f .git/index.lock
+'
+
+rm -f .git/MERGE_MSG .git/COMMIT_EDITMSG
+git reset -q --hard
+
+test_expect_success 'Hand committing of a redundant merge removes dups' '
+
+ git rev-parse second master >expect &&
+ test_must_fail git merge second master &&
+ git checkout master g &&
+ EDITOR=: git commit -a &&
+ git cat-file commit HEAD | sed -n -e "s/^parent //p" -e "/^$/q" >actual &&
+ test_cmp expect actual
+
+'
+
+test_expect_success 'A single-liner subject with a token plus colon is not a footer' '
+
+ git reset --hard &&
+ git commit -s -m "hello: kitty" --allow-empty &&
+ git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
+ test $(wc -l <actual) = 3
+
'
test_done
diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh
index 2dd5a5e302..8528f64c8d 100755
--- a/t/t7503-pre-commit-hook.sh
+++ b/t/t7503-pre-commit-hook.sh
@@ -56,7 +56,7 @@ test_expect_success 'with failing hook' '
echo "another" >> file &&
git add file &&
- ! git commit -m "another"
+ test_must_fail git commit -m "another"
'
@@ -69,7 +69,7 @@ test_expect_success '--no-verify with failing hook' '
'
chmod -x "$HOOK"
-test_expect_success 'with non-executable hook' '
+test_expect_success POSIXPERM 'with non-executable hook' '
echo "content" >> file &&
git add file &&
@@ -77,7 +77,7 @@ test_expect_success 'with non-executable hook' '
'
-test_expect_success '--no-verify with non-executable hook' '
+test_expect_success POSIXPERM '--no-verify with non-executable hook' '
echo "more content" >> file &&
git add file &&
diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh
index eff36aaee3..1f53ea8090 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -19,6 +19,9 @@ cp FAKE_MSG "$1"
exit 0
EOF
chmod +x fake-editor
+
+## Not using test_set_editor here so we can easily ensure the editor variable
+## is only set for the editor tests
FAKE_EDITOR="$(pwd)/fake-editor"
export FAKE_EDITOR
@@ -27,7 +30,7 @@ test_expect_success 'with no hook (editor)' '
echo "more foo" >> file &&
git add file &&
echo "more foo" > FAKE_MSG &&
- GIT_EDITOR="$FAKE_EDITOR" git commit
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit
'
@@ -44,7 +47,7 @@ test_expect_success '--no-verify with no hook (editor)' '
echo "more bar" > file &&
git add file &&
echo "more bar" > FAKE_MSG &&
- GIT_EDITOR="$FAKE_EDITOR" git commit --no-verify
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
'
@@ -71,7 +74,7 @@ test_expect_success 'with succeeding hook (editor)' '
echo "more more" >> file &&
git add file &&
echo "more more" > FAKE_MSG &&
- GIT_EDITOR="$FAKE_EDITOR" git commit
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit
'
@@ -88,7 +91,7 @@ test_expect_success '--no-verify with succeeding hook (editor)' '
echo "even more more" >> file &&
git add file &&
echo "even more more" > FAKE_MSG &&
- GIT_EDITOR="$FAKE_EDITOR" git commit --no-verify
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
'
@@ -102,7 +105,7 @@ test_expect_success 'with failing hook' '
echo "another" >> file &&
git add file &&
- ! git commit -m "another"
+ test_must_fail git commit -m "another"
'
@@ -111,7 +114,7 @@ test_expect_success 'with failing hook (editor)' '
echo "more another" >> file &&
git add file &&
echo "more another" > FAKE_MSG &&
- ! (GIT_EDITOR="$FAKE_EDITOR" git commit)
+ ! (GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit)
'
@@ -128,12 +131,12 @@ test_expect_success '--no-verify with failing hook (editor)' '
echo "more stuff" >> file &&
git add file &&
echo "more stuff" > FAKE_MSG &&
- GIT_EDITOR="$FAKE_EDITOR" git commit --no-verify
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
'
chmod -x "$HOOK"
-test_expect_success 'with non-executable hook' '
+test_expect_success POSIXPERM 'with non-executable hook' '
echo "content" >> file &&
git add file &&
@@ -141,16 +144,16 @@ test_expect_success 'with non-executable hook' '
'
-test_expect_success 'with non-executable hook (editor)' '
+test_expect_success POSIXPERM 'with non-executable hook (editor)' '
echo "content again" >> file &&
git add file &&
echo "content again" > FAKE_MSG &&
- GIT_EDITOR="$FAKE_EDITOR" git commit -m "content again"
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -m "content again"
'
-test_expect_success '--no-verify with non-executable hook' '
+test_expect_success POSIXPERM '--no-verify with non-executable hook' '
echo "more content" >> file &&
git add file &&
@@ -158,12 +161,12 @@ test_expect_success '--no-verify with non-executable hook' '
'
-test_expect_success '--no-verify with non-executable hook (editor)' '
+test_expect_success POSIXPERM '--no-verify with non-executable hook (editor)' '
echo "even more content" >> file &&
git add file &&
echo "even more content" > FAKE_MSG &&
- GIT_EDITOR="$FAKE_EDITOR" git commit --no-verify
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
'
@@ -193,7 +196,7 @@ test_expect_success 'hook edits commit message (editor)' '
echo "additional content" >> file &&
git add file &&
echo "additional content" > FAKE_MSG &&
- GIT_EDITOR="$FAKE_EDITOR" git commit &&
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit &&
commit_msg_is "new message"
'
@@ -212,7 +215,7 @@ test_expect_success "hook doesn't edit commit message (editor)" '
echo "more plus" >> file &&
git add file &&
echo "more plus" > FAKE_MSG &&
- GIT_EDITOR="$FAKE_EDITOR" git commit --no-verify &&
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify &&
commit_msg_is "more plus"
'
diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh
index 802aa624d0..ff189624d4 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -18,6 +18,9 @@ cat > fake-editor <<'EOF'
exit 0
EOF
chmod +x fake-editor
+
+## Not using test_set_editor here so we can easily ensure the editor variable
+## is only set for the editor tests
FAKE_EDITOR="$(pwd)/fake-editor"
export FAKE_EDITOR
@@ -29,7 +32,7 @@ echo "#!$SHELL_PATH" > "$HOOK"
cat >> "$HOOK" <<'EOF'
if test "$2" = commit; then
- source=$(git-rev-parse "$3")
+ source=$(git rev-parse "$3")
else
source=${2-default}
fi
@@ -58,7 +61,7 @@ test_expect_success 'with hook (-m editor)' '
echo "more" >> file &&
git add file &&
- GIT_EDITOR="$FAKE_EDITOR" git commit -e -m "more more" &&
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -e -m "more more" &&
test "`git log -1 --pretty=format:%s`" = message
'
@@ -85,7 +88,7 @@ test_expect_success 'with hook (-F editor)' '
echo "more" >> file &&
git add file &&
- (echo more more | GIT_EDITOR="$FAKE_EDITOR" git commit -e -F -) &&
+ (echo more more | GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -e -F -) &&
test "`git log -1 --pretty=format:%s`" = message
'
@@ -104,7 +107,7 @@ test_expect_success 'with hook (editor)' '
echo "more more" >> file &&
git add file &&
- GIT_EDITOR="$FAKE_EDITOR" git commit &&
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit &&
test "`git log -1 --pretty=format:%s`" = default
'
@@ -114,7 +117,7 @@ test_expect_success 'with hook (--amend)' '
head=`git rev-parse HEAD` &&
echo "more" >> file &&
git add file &&
- GIT_EDITOR="$FAKE_EDITOR" git commit --amend &&
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --amend &&
test "`git log -1 --pretty=format:%s`" = "$head"
'
@@ -124,7 +127,7 @@ test_expect_success 'with hook (-c)' '
head=`git rev-parse HEAD` &&
echo "more" >> file &&
git add file &&
- GIT_EDITOR="$FAKE_EDITOR" git commit -c $head &&
+ GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head &&
test "`git log -1 --pretty=format:%s`" = "$head"
'
@@ -139,7 +142,7 @@ test_expect_success 'with failing hook' '
head=`git rev-parse HEAD` &&
echo "more" >> file &&
git add file &&
- ! GIT_EDITOR="$FAKE_EDITOR" git commit -c $head
+ ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
'
@@ -148,7 +151,7 @@ test_expect_success 'with failing hook (--no-verify)' '
head=`git rev-parse HEAD` &&
echo "more" >> file &&
git add file &&
- ! GIT_EDITOR="$FAKE_EDITOR" git commit --no-verify -c $head
+ ! GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
'
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
new file mode 100755
index 0000000000..d9a08aac56
--- /dev/null
+++ b/t/t7506-status-submodule.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+test_description='git status for submodule'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_create_repo sub
+ cd sub &&
+ : >bar &&
+ git add bar &&
+ git commit -m " Add bar" &&
+ cd .. &&
+ git add sub &&
+ git commit -m "Add submodule sub"
+'
+
+test_expect_success 'status clean' '
+ git status |
+ grep "nothing to commit"
+'
+test_expect_success 'status -a clean' '
+ git status -a |
+ grep "nothing to commit"
+'
+test_expect_success 'rm submodule contents' '
+ rm -rf sub/* sub/.git
+'
+test_expect_success 'status clean (empty submodule dir)' '
+ git status |
+ grep "nothing to commit"
+'
+test_expect_success 'status -a clean (empty submodule dir)' '
+ git status -a |
+ grep "nothing to commit"
+'
+
+test_done
diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh
new file mode 100755
index 0000000000..da5bd3b5a5
--- /dev/null
+++ b/t/t7507-commit-verbose.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+test_description='verbose commit template'
+. ./test-lib.sh
+
+cat >check-for-diff <<EOF
+#!$SHELL_PATH
+exec grep '^diff --git' "\$1"
+EOF
+chmod +x check-for-diff
+test_set_editor "$PWD/check-for-diff"
+
+cat >message <<'EOF'
+subject
+
+body
+EOF
+
+test_expect_success 'setup' '
+ echo content >file &&
+ git add file &&
+ git commit -F message
+'
+
+test_expect_success 'initial commit shows verbose diff' '
+ git commit --amend -v
+'
+
+test_expect_success 'second commit' '
+ echo content modified >file &&
+ git add file &&
+ git commit -F message
+'
+
+check_message() {
+ git log -1 --pretty=format:%s%n%n%b >actual &&
+ test_cmp "$1" actual
+}
+
+test_expect_success 'verbose diff is stripped out' '
+ git commit --amend -v &&
+ check_message message
+'
+
+test_expect_success 'verbose diff is stripped out (mnemonicprefix)' '
+ git config diff.mnemonicprefix true &&
+ git commit --amend -v &&
+ check_message message
+'
+
+cat >diff <<'EOF'
+This is an example commit message that contains a diff.
+
+diff --git c/file i/file
+new file mode 100644
+index 0000000..f95c11d
+--- /dev/null
++++ i/file
+@@ -0,0 +1 @@
++this is some content
+EOF
+
+test_expect_success 'diff in message is retained without -v' '
+ git commit --amend -F diff &&
+ check_message diff
+'
+
+test_expect_failure 'diff in message is retained with -v' '
+ git commit --amend -F diff -v &&
+ check_message diff
+'
+
+test_done
diff --git a/t/t7502-status.sh b/t/t7508-status.sh
index e4bfcaece0..93f875f500 100755
--- a/t/t7502-status.sh
+++ b/t/t7508-status.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2007 Johannes E. Schindelin
#
-test_description='git-status'
+test_description='git status'
. ./test-lib.sh
@@ -46,6 +46,7 @@ cat > expect << \EOF
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: dir1/modified
#
@@ -63,8 +64,109 @@ EOF
test_expect_success 'status (2)' '
git status > output &&
- git diff expect output
+ test_cmp expect output
+
+'
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+# (use "git reset HEAD <file>..." to unstage)
+#
+# new file: dir2/added
+#
+# Changed but not updated:
+# (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
+test_expect_success 'status -uno' '
+ mkdir dir3 &&
+ : > dir3/untracked1 &&
+ : > dir3/untracked2 &&
+ git status -uno >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'status (status.showUntrackedFiles no)' '
+ git config status.showuntrackedfiles no
+ git status >output &&
+ test_cmp expect output
+'
+
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+# (use "git reset HEAD <file>..." to unstage)
+#
+# new file: dir2/added
+#
+# Changed but not updated:
+# (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)
+#
+# dir1/untracked
+# dir2/modified
+# dir2/untracked
+# dir3/
+# expect
+# output
+# untracked
+EOF
+test_expect_success 'status -unormal' '
+ git status -unormal >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'status (status.showUntrackedFiles normal)' '
+ git config status.showuntrackedfiles normal
+ git status >output &&
+ test_cmp expect output
+'
+
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+# (use "git reset HEAD <file>..." to unstage)
+#
+# new file: dir2/added
+#
+# Changed but not updated:
+# (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)
+#
+# dir1/untracked
+# dir2/modified
+# dir2/untracked
+# dir3/untracked1
+# dir3/untracked2
+# expect
+# output
+# untracked
+EOF
+test_expect_success 'status -uall' '
+ git status -uall >output &&
+ test_cmp expect output
+'
+test_expect_success 'status (status.showUntrackedFiles all)' '
+ git config status.showuntrackedfiles all
+ git status >output &&
+ rm -rf dir3 &&
+ git config --unset status.showuntrackedfiles &&
+ test_cmp expect output
'
cat > expect << \EOF
@@ -76,6 +178,7 @@ cat > expect << \EOF
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: modified
#
@@ -93,7 +196,7 @@ EOF
test_expect_success 'status with relative paths' '
(cd dir1 && git status) > output &&
- git diff expect output
+ test_cmp expect output
'
@@ -106,6 +209,7 @@ cat > expect << \EOF
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: dir1/modified
#
@@ -124,7 +228,7 @@ test_expect_success 'status without relative paths' '
git config status.relativePaths false
(cd dir1 && git status) > output &&
- git diff expect output
+ test_cmp expect output
'
@@ -169,6 +273,7 @@ cat >expect <<EOF
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: dir1/modified
#
@@ -187,6 +292,12 @@ test_expect_success 'status submodule summary is disabled by default' '
test_cmp expect output
'
+# we expect the same as the previous test
+test_expect_success 'status --untracked-files=all does not show submodule' '
+ git status --untracked-files=all >output &&
+ test_cmp expect output
+'
+
head=$(cd sm && git rev-parse --short=7 --verify HEAD)
cat >expect <<EOF
@@ -199,6 +310,7 @@ cat >expect <<EOF
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: dir1/modified
#
@@ -228,6 +340,7 @@ cat >expect <<EOF
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: dir1/modified
#
@@ -259,6 +372,7 @@ cat >expect <<EOF
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: dir1/modified
#
diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh
new file mode 100755
index 0000000000..d52c060b06
--- /dev/null
+++ b/t/t7509-commit.sh
@@ -0,0 +1,114 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Erick Mattos
+#
+
+test_description='git commit --reset-author'
+
+. ./test-lib.sh
+
+author_header () {
+ git cat-file commit "$1" |
+ sed -n -e '/^$/q' -e '/^author /p'
+}
+
+message_body () {
+ git cat-file commit "$1" |
+ sed -e '1,/^$/d'
+}
+
+test_expect_success '-C option copies authorship and message' '
+ echo "Initial" >foo &&
+ git add foo &&
+ test_tick &&
+ git commit -m "Initial Commit" --author Frigate\ \<flying@over.world\> &&
+ git tag Initial &&
+ echo "Test 1" >>foo &&
+ test_tick &&
+ git commit -a -C Initial &&
+ author_header Initial >expect &&
+ author_header HEAD >actual &&
+ test_cmp expect actual &&
+
+ message_body Initial >expect &&
+ message_body HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '-C option copies only the message with --reset-author' '
+ echo "Test 2" >>foo &&
+ test_tick &&
+ git commit -a -C Initial --reset-author &&
+ echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect &&
+ author_header HEAD >actual
+ test_cmp expect actual &&
+
+ message_body Initial >expect &&
+ message_body HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '-c option copies authorship and message' '
+ echo "Test 3" >>foo &&
+ test_tick &&
+ EDITOR=: VISUAL=: git commit -a -c Initial &&
+ author_header Initial >expect &&
+ author_header HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '-c option copies only the message with --reset-author' '
+ echo "Test 4" >>foo &&
+ test_tick &&
+ EDITOR=: VISUAL=: git commit -a -c Initial --reset-author &&
+ echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect &&
+ author_header HEAD >actual &&
+ test_cmp expect actual &&
+
+ message_body Initial >expect &&
+ message_body HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--amend option copies authorship' '
+ git checkout Initial &&
+ echo "Test 5" >>foo &&
+ test_tick &&
+ git commit -a --amend -m "amend test" &&
+ author_header Initial >expect &&
+ author_header HEAD >actual &&
+
+ echo "amend test" >expect &&
+ message_body HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--reset-author makes the commit ours even with --amend option' '
+ git checkout Initial &&
+ echo "Test 6" >>foo &&
+ test_tick &&
+ git commit -a --reset-author -m "Changed again" --amend &&
+ echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect &&
+ author_header HEAD >actual &&
+ test_cmp expect actual &&
+
+ echo "Changed again" >expect &&
+ message_body HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--reset-author and --author are mutually exclusive' '
+ git checkout Initial &&
+ echo "Test 7" >>foo &&
+ test_tick &&
+ test_must_fail git commit -a --reset-author --author="Xyzzy <frotz@nitfol.xz>"
+'
+
+test_expect_success '--reset-author should be rejected without -c/-C/--amend' '
+ git checkout Initial &&
+ echo "Test 7" >>foo &&
+ test_tick &&
+ test_must_fail git commit -a --reset-author -m done
+'
+
+test_done
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 56869aceed..57f6d2bae7 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2007 Lars Hjemli
#
-test_description='git-merge
+test_description='git merge
Testing basic merge operations/option parsing.'
@@ -104,7 +104,11 @@ create_merge_msgs() {
git log --no-merges ^HEAD c2 >>squash.1-5 &&
echo "Squashed commit of the following:" >squash.1-5-9 &&
echo >>squash.1-5-9 &&
- git log --no-merges ^HEAD c2 c3 >>squash.1-5-9
+ git log --no-merges ^HEAD c2 c3 >>squash.1-5-9 &&
+ echo > msg.nolog &&
+ echo "* commit 'c3':" >msg.log &&
+ echo " commit 3" >>msg.log &&
+ echo >>msg.log
}
verify_diff() {
@@ -122,7 +126,7 @@ verify_merge() {
echo "[OOPS] unmerged files"
false
fi &&
- if ! git diff --exit-code
+ if test_must_fail git diff --exit-code
then
echo "[OOPS] working tree != index"
false
@@ -218,36 +222,16 @@ test_expect_success 'setup' '
test_debug 'gitk --all'
test_expect_success 'test option parsing' '
- if git merge -$ c1
- then
- echo "[OOPS] -$ accepted"
- false
- fi &&
- if git merge --no-such c1
- then
- echo "[OOPS] --no-such accepted"
- false
- fi &&
- if git merge -s foobar c1
- then
- echo "[OOPS] -s foobar accepted"
- false
- fi &&
- if git merge -s=foobar c1
- then
- echo "[OOPS] -s=foobar accepted"
- false
- fi &&
- if git merge -m
- then
- echo "[OOPS] missing commit msg accepted"
- false
- fi &&
- if git merge
- then
- echo "[OOPS] missing commit references accepted"
- false
- fi
+ test_must_fail git merge -$ c1 &&
+ test_must_fail git merge --no-such c1 &&
+ test_must_fail git merge -s foobar c1 &&
+ test_must_fail git merge -s=foobar c1 &&
+ test_must_fail git merge -m &&
+ test_must_fail git merge
+'
+
+test_expect_success 'reject non-strategy with a git-merge-foo name' '
+ test_must_fail git merge -s index c1
'
test_expect_success 'merge c0 with c1' '
@@ -259,6 +243,16 @@ test_expect_success 'merge c0 with c1' '
test_debug 'gitk --all'
+test_expect_success 'merge c0 with c1 with --ff-only' '
+ git reset --hard c0 &&
+ git merge --ff-only c1 &&
+ git merge --ff-only HEAD c0 c1 &&
+ verify_merge file result.1 &&
+ verify_head "$c1"
+'
+
+test_debug 'gitk --all'
+
test_expect_success 'merge c1 with c2' '
git reset --hard c1 &&
test_tick &&
@@ -279,6 +273,14 @@ test_expect_success 'merge c1 with c2 and c3' '
test_debug 'gitk --all'
+test_expect_success 'failing merges with --ff-only' '
+ git reset --hard c1 &&
+ test_tick &&
+ test_must_fail git merge --ff-only c2 &&
+ test_must_fail git merge --ff-only c3 &&
+ test_must_fail git merge --ff-only c2 c3
+'
+
test_expect_success 'merge c0 with c1 (no-commit)' '
git reset --hard c0 &&
git merge --no-commit c1 &&
@@ -319,6 +321,17 @@ test_expect_success 'merge c0 with c1 (squash)' '
test_debug 'gitk --all'
+test_expect_success 'merge c0 with c1 (squash, ff-only)' '
+ git reset --hard c0 &&
+ git merge --squash --ff-only c1 &&
+ verify_merge file result.1 &&
+ verify_head $c0 &&
+ verify_no_mergehead &&
+ verify_diff squash.1 .git/SQUASH_MSG "[OOPS] bad squash message"
+'
+
+test_debug 'gitk --all'
+
test_expect_success 'merge c1 with c2 (squash)' '
git reset --hard c1 &&
git merge --squash c2 &&
@@ -330,6 +343,13 @@ test_expect_success 'merge c1 with c2 (squash)' '
test_debug 'gitk --all'
+test_expect_success 'unsuccesful merge of c1 with c2 (squash, ff-only)' '
+ git reset --hard c1 &&
+ test_must_fail git merge --squash --ff-only c2
+'
+
+test_debug 'gitk --all'
+
test_expect_success 'merge c1 with c2 and c3 (squash)' '
git reset --hard c1 &&
git merge --squash c2 c3 &&
@@ -364,7 +384,7 @@ test_expect_success 'merge c1 with c2 (squash in config)' '
test_debug 'gitk --all'
-test_expect_success 'override config option -n' '
+test_expect_success 'override config option -n with --summary' '
git reset --hard c1 &&
git config branch.master.mergeoptions "-n" &&
test_tick &&
@@ -373,15 +393,30 @@ test_expect_success 'override config option -n' '
verify_parents $c1 $c2 &&
if ! grep "^ file | *2 +-$" diffstat.txt
then
- echo "[OOPS] diffstat was not generated"
+ echo "[OOPS] diffstat was not generated with --summary"
+ false
+ fi
+'
+
+test_expect_success 'override config option -n with --stat' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "-n" &&
+ test_tick &&
+ git merge --stat c2 >diffstat.txt &&
+ verify_merge file result.1-5 msg.1-5 &&
+ verify_parents $c1 $c2 &&
+ if ! grep "^ file | *2 +-$" diffstat.txt
+ then
+ echo "[OOPS] diffstat was not generated with --stat"
+ false
fi
'
test_debug 'gitk --all'
-test_expect_success 'override config option --summary' '
+test_expect_success 'override config option --stat' '
git reset --hard c1 &&
- git config branch.master.mergeoptions "--summary" &&
+ git config branch.master.mergeoptions "--stat" &&
test_tick &&
git merge -n c2 >diffstat.txt &&
verify_merge file result.1-5 msg.1-5 &&
@@ -433,6 +468,11 @@ test_expect_success 'combining --squash and --no-ff is refused' '
test_must_fail git merge --no-ff --squash c1
'
+test_expect_success 'combining --ff-only and --no-ff is refused' '
+ test_must_fail git merge --ff-only --no-ff c1 &&
+ test_must_fail git merge --no-ff --ff-only c1
+'
+
test_expect_success 'merge c0 with c1 (ff overrides no-ff)' '
git reset --hard c0 &&
git config branch.master.mergeoptions "--no-ff" &&
@@ -441,6 +481,124 @@ test_expect_success 'merge c0 with c1 (ff overrides no-ff)' '
verify_head $c1
'
+test_expect_success 'merge log message' '
+ git reset --hard c0 &&
+ git merge --no-log c2 &&
+ git show -s --pretty=format:%b HEAD >msg.act &&
+ verify_diff msg.nolog msg.act "[OOPS] bad merge log message" &&
+
+ git merge --log c3 &&
+ git show -s --pretty=format:%b HEAD >msg.act &&
+ verify_diff msg.log msg.act "[OOPS] bad merge log message" &&
+
+ git reset --hard HEAD^ &&
+ git config merge.log yes &&
+ git merge c3 &&
+ git show -s --pretty=format:%b HEAD >msg.act &&
+ verify_diff msg.log msg.act "[OOPS] bad merge log message"
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c0, c2, c0, and c1' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c0 c2 c0 c1 &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1 $c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c0, c2, c0, and c1' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c0 c2 c0 c1 &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1 $c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c1 and c2' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c1 c2 &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1 $c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge fast-forward in a dirty tree' '
+ git reset --hard c0 &&
+ mv file file1 &&
+ cat file1 >file &&
+ rm -f file1 &&
+ git merge c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'in-index merge' '
+ git reset --hard c0 &&
+ git merge --no-ff -s resolve c1 > out &&
+ grep "Wonderful." out &&
+ verify_parents $c0 $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'refresh the index before merging' '
+ git reset --hard c1 &&
+ sleep 1 &&
+ touch file &&
+ git merge c3
+'
+
+cat >expected <<EOF
+Merge branch 'c5' (early part)
+EOF
+
+test_expect_success 'merge early part of c2' '
+ git reset --hard c3 &&
+ echo c4 > c4.c &&
+ git add c4.c &&
+ git commit -m c4 &&
+ git tag c4 &&
+ echo c5 > c5.c &&
+ git add c5.c &&
+ git commit -m c5 &&
+ git tag c5 &&
+ git reset --hard c3 &&
+ echo c6 > c6.c &&
+ git add c6.c &&
+ git commit -m c6 &&
+ git tag c6 &&
+ git merge c5~1 &&
+ git show -s --pretty=format:%s HEAD > actual &&
+ test_cmp actual expected
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge --no-ff --no-commit && commit' '
+ git reset --hard c0 &&
+ git merge --no-ff --no-commit c1 &&
+ EDITOR=: git commit &&
+ verify_parents $c0 $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'amending no-ff merge commit' '
+ EDITOR=: git commit --amend &&
+ verify_parents $c0 $c1
+'
+
test_debug 'gitk --all'
test_done
diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh
new file mode 100755
index 0000000000..7ba94ea99b
--- /dev/null
+++ b/t/t7601-merge-pull-config.sh
@@ -0,0 +1,156 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing pull.* configuration parsing.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo c0 >c0.c &&
+ git add c0.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ echo c1 >c1.c &&
+ git add c1.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ echo c2 >c2.c &&
+ git add c2.c &&
+ git commit -m c2 &&
+ git tag c2 &&
+ git reset --hard c0 &&
+ echo c3 >c3.c &&
+ git add c3.c &&
+ git commit -m c3 &&
+ git tag c3
+'
+
+test_expect_success 'merge c1 with c2' '
+ git reset --hard c1 &&
+ test -f c0.c &&
+ test -f c1.c &&
+ test ! -f c2.c &&
+ test ! -f c3.c &&
+ git merge c2 &&
+ test -f c1.c &&
+ test -f c2.c
+'
+
+test_expect_success 'merge c1 with c2 (ours in pull.twohead)' '
+ git reset --hard c1 &&
+ git config pull.twohead ours &&
+ git merge c2 &&
+ test -f c1.c &&
+ ! test -f c2.c
+'
+
+test_expect_success 'merge c1 with c2 and c3 (recursive in pull.octopus)' '
+ git reset --hard c1 &&
+ git config pull.octopus "recursive" &&
+ test_must_fail git merge c2 c3 &&
+ test "$(git rev-parse c1)" = "$(git rev-parse HEAD)"
+'
+
+test_expect_success 'merge c1 with c2 and c3 (recursive and octopus in pull.octopus)' '
+ git reset --hard c1 &&
+ git config pull.octopus "recursive octopus" &&
+ git merge c2 c3 &&
+ test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+ test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
+ test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
+ test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" &&
+ git diff --exit-code &&
+ test -f c0.c &&
+ test -f c1.c &&
+ test -f c2.c &&
+ test -f c3.c
+'
+
+conflict_count()
+{
+ {
+ git diff-files --name-only
+ git ls-files --unmerged
+ } | wc -l
+}
+
+# c4 - c5
+# \ c6
+#
+# There are two conflicts here:
+#
+# 1) Because foo.c is renamed to bar.c, recursive will handle this,
+# resolve won't.
+#
+# 2) One in conflict.c and that will always fail.
+
+test_expect_success 'setup conflicted merge' '
+ git reset --hard c0 &&
+ echo A >conflict.c &&
+ git add conflict.c &&
+ echo contents >foo.c &&
+ git add foo.c &&
+ git commit -m c4 &&
+ git tag c4 &&
+ echo B >conflict.c &&
+ git add conflict.c &&
+ git mv foo.c bar.c &&
+ git commit -m c5 &&
+ git tag c5 &&
+ git reset --hard c4 &&
+ echo C >conflict.c &&
+ git add conflict.c &&
+ echo secondline >> foo.c &&
+ git add foo.c &&
+ git commit -m c6 &&
+ git tag c6
+'
+
+# First do the merge with resolve and recursive then verify that
+# recusive is choosen.
+
+test_expect_success 'merge picks up the best result' '
+ git config --unset-all pull.twohead &&
+ git reset --hard c5 &&
+ git merge -s resolve c6
+ resolve_count=$(conflict_count) &&
+ git reset --hard c5 &&
+ git merge -s recursive c6
+ recursive_count=$(conflict_count) &&
+ git reset --hard c5 &&
+ git merge -s recursive -s resolve c6
+ auto_count=$(conflict_count) &&
+ test $auto_count = $recursive_count &&
+ test $auto_count != $resolve_count
+'
+
+test_expect_success 'merge picks up the best result (from config)' '
+ git config pull.twohead "recursive resolve" &&
+ git reset --hard c5 &&
+ git merge -s resolve c6
+ resolve_count=$(conflict_count) &&
+ git reset --hard c5 &&
+ git merge -s recursive c6
+ recursive_count=$(conflict_count) &&
+ git reset --hard c5 &&
+ git merge c6
+ auto_count=$(conflict_count) &&
+ test $auto_count = $recursive_count &&
+ test $auto_count != $resolve_count
+'
+
+test_expect_success 'merge errors out on invalid strategy' '
+ git config pull.twohead "foobar" &&
+ git reset --hard c5 &&
+ test_must_fail git merge c6
+'
+
+test_expect_success 'merge errors out on invalid strategy' '
+ git config --unset-all pull.twohead &&
+ git reset --hard c5 &&
+ test_must_fail git merge -s "resolve recursive" c6
+'
+
+test_done
diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh
new file mode 100755
index 0000000000..2746169514
--- /dev/null
+++ b/t/t7602-merge-octopus-many.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing octopus merge with more than 25 refs.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo c0 > c0.c &&
+ git add c0.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ i=1 &&
+ while test $i -le 30
+ do
+ git reset --hard c0 &&
+ echo c$i > c$i.c &&
+ git add c$i.c &&
+ git commit -m c$i &&
+ git tag c$i &&
+ i=`expr $i + 1` || return 1
+ done
+'
+
+test_expect_success 'merge c1 with c2, c3, c4, ... c29' '
+ git reset --hard c1 &&
+ i=2 &&
+ refs="" &&
+ while test $i -le 30
+ do
+ refs="$refs c$i"
+ i=`expr $i + 1`
+ done
+ git merge $refs &&
+ test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+ i=1 &&
+ while test $i -le 30
+ do
+ test "$(git rev-parse c$i)" = "$(git rev-parse HEAD^$i)" &&
+ i=`expr $i + 1` || return 1
+ done &&
+ git diff --exit-code &&
+ i=1 &&
+ while test $i -le 30
+ do
+ test -f c$i.c &&
+ i=`expr $i + 1` || return 1
+ done
+'
+
+cat >expected <<\EOF
+Trying simple merge with c2
+Trying simple merge with c3
+Trying simple merge with c4
+Merge made by octopus.
+ c2.c | 1 +
+ c3.c | 1 +
+ c4.c | 1 +
+ 3 files changed, 3 insertions(+), 0 deletions(-)
+ create mode 100644 c2.c
+ create mode 100644 c3.c
+ create mode 100644 c4.c
+EOF
+
+test_expect_success 'merge output uses pretty names' '
+ git reset --hard c1 &&
+ git merge c2 c3 c4 >actual &&
+ test_cmp actual expected
+'
+
+cat >expected <<\EOF
+Already up-to-date with c4
+Trying simple merge with c5
+Merge made by octopus.
+ c5.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+ create mode 100644 c5.c
+EOF
+
+test_expect_success 'merge up-to-date output uses pretty names' '
+ git merge c4 c5 >actual &&
+ test_cmp actual expected
+'
+
+cat >expected <<\EOF
+Fast-forwarding to: c1
+Trying simple merge with c2
+Merge made by octopus.
+ c1.c | 1 +
+ c2.c | 1 +
+ 2 files changed, 2 insertions(+), 0 deletions(-)
+ create mode 100644 c1.c
+ create mode 100644 c2.c
+EOF
+
+test_expect_success 'merge fast-forward output uses pretty names' '
+ git reset --hard c0 &&
+ git merge c1 c2 >actual &&
+ test_cmp actual expected
+'
+
+test_done
diff --git a/t/t7603-merge-reduce-heads.sh b/t/t7603-merge-reduce-heads.sh
new file mode 100755
index 0000000000..7e17eb490d
--- /dev/null
+++ b/t/t7603-merge-reduce-heads.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing octopus merge when reducing parents to independent branches.'
+
+. ./test-lib.sh
+
+# 0 - 1
+# \ 2
+# \ 3
+# \ 4 - 5
+#
+# So 1, 2, 3 and 5 should be kept, 4 should be avoided.
+
+test_expect_success 'setup' '
+ echo c0 > c0.c &&
+ git add c0.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ echo c1 > c1.c &&
+ git add c1.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ echo c2 > c2.c &&
+ git add c2.c &&
+ git commit -m c2 &&
+ git tag c2 &&
+ git reset --hard c0 &&
+ echo c3 > c3.c &&
+ git add c3.c &&
+ git commit -m c3 &&
+ git tag c3 &&
+ git reset --hard c0 &&
+ echo c4 > c4.c &&
+ git add c4.c &&
+ git commit -m c4 &&
+ git tag c4 &&
+ echo c5 > c5.c &&
+ git add c5.c &&
+ git commit -m c5 &&
+ git tag c5
+'
+
+test_expect_success 'merge c1 with c2, c3, c4, c5' '
+ git reset --hard c1 &&
+ git merge c2 c3 c4 c5 &&
+ test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+ test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
+ test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
+ test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" &&
+ test "$(git rev-parse c5)" = "$(git rev-parse HEAD^4)" &&
+ git diff --exit-code &&
+ test -f c0.c &&
+ test -f c1.c &&
+ test -f c2.c &&
+ test -f c3.c &&
+ test -f c4.c &&
+ test -f c5.c
+'
+
+test_expect_success 'setup' '
+ for i in A B C D E
+ do
+ echo $i > $i.c &&
+ git add $i.c &&
+ git commit -m $i &&
+ git tag $i
+ done &&
+ git reset --hard A &&
+ for i in F G H I
+ do
+ echo $i > $i.c &&
+ git add $i.c &&
+ git commit -m $i &&
+ git tag $i
+ done
+'
+
+test_expect_success 'merge E and I' '
+ git reset --hard A &&
+ git merge E I
+'
+
+test_expect_success 'verify merge result' '
+ test $(git rev-parse HEAD^1) = $(git rev-parse E) &&
+ test $(git rev-parse HEAD^2) = $(git rev-parse I)
+'
+
+test_expect_success 'add conflicts' '
+ git reset --hard E &&
+ echo foo > file.c &&
+ git add file.c &&
+ git commit -m E2 &&
+ git tag E2 &&
+ git reset --hard I &&
+ echo bar >file.c &&
+ git add file.c &&
+ git commit -m I2 &&
+ git tag I2
+'
+
+test_expect_success 'merge E2 and I2, causing a conflict and resolve it' '
+ git reset --hard A &&
+ test_must_fail git merge E2 I2 &&
+ echo baz > file.c &&
+ git add file.c &&
+ git commit -m "resolve conflict"
+'
+
+test_expect_success 'verify merge result' '
+ test $(git rev-parse HEAD^1) = $(git rev-parse E2) &&
+ test $(git rev-parse HEAD^2) = $(git rev-parse I2)
+'
+test_done
diff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh
new file mode 100755
index 0000000000..269cfdf267
--- /dev/null
+++ b/t/t7604-merge-custom-message.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing merge when using a custom message for the merge commit.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo c0 > c0.c &&
+ git add c0.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ echo c1 > c1.c &&
+ git add c1.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ echo c2 > c2.c &&
+ git add c2.c &&
+ git commit -m c2 &&
+ git tag c2
+'
+
+
+test_expect_success 'merge c2 with a custom message' '
+ git reset --hard c1 &&
+ echo >expected "custom message" &&
+ git merge -m "custom message" c2 &&
+ git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
+ test_cmp expected actual
+'
+
+test_done
diff --git a/t/t7605-merge-resolve.sh b/t/t7605-merge-resolve.sh
new file mode 100755
index 0000000000..0cb9d11f21
--- /dev/null
+++ b/t/t7605-merge-resolve.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing the resolve strategy.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo c0 > c0.c &&
+ git add c0.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ echo c1 > c1.c &&
+ git add c1.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ echo c2 > c2.c &&
+ git add c2.c &&
+ git commit -m c2 &&
+ git tag c2 &&
+ git reset --hard c0 &&
+ echo c3 > c2.c &&
+ git add c2.c &&
+ git commit -m c3 &&
+ git tag c3
+'
+
+test_expect_success 'merge c1 to c2' '
+ git reset --hard c1 &&
+ git merge -s resolve c2 &&
+ test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+ test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
+ test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
+ git diff --exit-code &&
+ test -f c0.c &&
+ test -f c1.c &&
+ test -f c2.c &&
+ test 3 = $(git ls-tree -r HEAD | wc -l) &&
+ test 3 = $(git ls-files | wc -l)
+'
+
+test_expect_success 'merge c2 to c3 (fails)' '
+ git reset --hard c2 &&
+ test_must_fail git merge -s resolve c3
+'
+test_done
diff --git a/t/t7606-merge-custom.sh b/t/t7606-merge-custom.sh
new file mode 100755
index 0000000000..52a451dd57
--- /dev/null
+++ b/t/t7606-merge-custom.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing a custom strategy.'
+
+. ./test-lib.sh
+
+cat >git-merge-theirs <<EOF
+#!$SHELL_PATH
+eval git read-tree --reset -u \\\$\$#
+EOF
+chmod +x git-merge-theirs
+PATH=.:$PATH
+export PATH
+
+test_expect_success 'setup' '
+ echo c0 >c0.c &&
+ git add c0.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ echo c1 >c1.c &&
+ git add c1.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ echo c1c1 >c1.c &&
+ echo c2 >c2.c &&
+ git add c1.c c2.c &&
+ git commit -m c2 &&
+ git tag c2
+'
+
+test_expect_success 'merge c2 with a custom strategy' '
+ git reset --hard c1 &&
+ git merge -s theirs c2 &&
+ test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+ test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
+ test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
+ test "$(git rev-parse c2^{tree})" = "$(git rev-parse HEAD^{tree})" &&
+ git diff --exit-code &&
+ git diff --exit-code c2 HEAD &&
+ git diff --exit-code c2 &&
+ test -f c0.c &&
+ grep c1c1 c1.c &&
+ test -f c2.c
+'
+
+test_done
diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh
new file mode 100755
index 0000000000..49f4e1599a
--- /dev/null
+++ b/t/t7607-merge-overwrite.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+test_description='git-merge
+
+Do not overwrite changes.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo c0 > c0.c &&
+ git add c0.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ echo c1 > c1.c &&
+ git add c1.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ echo c2 > c2.c &&
+ git add c2.c &&
+ git commit -m c2 &&
+ git tag c2 &&
+ git reset --hard c1 &&
+ echo "c1 a" > c1.c &&
+ git add c1.c &&
+ git commit -m "c1 a" &&
+ git tag c1a &&
+ echo "VERY IMPORTANT CHANGES" > important
+'
+
+test_expect_success 'will not overwrite untracked file' '
+ git reset --hard c1 &&
+ cat important > c2.c &&
+ ! git merge c2 &&
+ test_cmp important c2.c
+'
+
+test_expect_success 'will not overwrite new file' '
+ git reset --hard c1 &&
+ cat important > c2.c &&
+ git add c2.c &&
+ ! git merge c2 &&
+ test_cmp important c2.c
+'
+
+test_expect_success 'will not overwrite staged changes' '
+ git reset --hard c1 &&
+ cat important > c2.c &&
+ git add c2.c &&
+ rm c2.c &&
+ ! git merge c2 &&
+ git checkout c2.c &&
+ test_cmp important c2.c
+'
+
+test_expect_success 'will not overwrite removed file' '
+ git reset --hard c1 &&
+ git rm c1.c &&
+ git commit -m "rm c1.c" &&
+ cat important > c1.c &&
+ ! git merge c1a &&
+ test_cmp important c1.c
+'
+
+test_expect_success 'will not overwrite re-added file' '
+ git reset --hard c1 &&
+ git rm c1.c &&
+ git commit -m "rm c1.c" &&
+ cat important > c1.c &&
+ git add c1.c &&
+ ! git merge c1a &&
+ test_cmp important c1.c
+'
+
+test_expect_success 'will not overwrite removed file with staged changes' '
+ git reset --hard c1 &&
+ git rm c1.c &&
+ git commit -m "rm c1.c" &&
+ cat important > c1.c &&
+ git add c1.c &&
+ rm c1.c &&
+ ! git merge c1a &&
+ git checkout c1.c &&
+ test_cmp important c1.c
+'
+
+test_done
diff --git a/t/t7608-merge-messages.sh b/t/t7608-merge-messages.sh
new file mode 100755
index 0000000000..28d56797b1
--- /dev/null
+++ b/t/t7608-merge-messages.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='test auto-generated merge messages'
+. ./test-lib.sh
+
+check_oneline() {
+ echo "$1" | sed "s/Q/'/g" >expect &&
+ git log -1 --pretty=tformat:%s >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'merge local branch' '
+ test_commit master-1 &&
+ git checkout -b local-branch &&
+ test_commit branch-1 &&
+ git checkout master &&
+ test_commit master-2 &&
+ git merge local-branch &&
+ check_oneline "Merge branch Qlocal-branchQ"
+'
+
+test_expect_success 'merge octopus branches' '
+ git checkout -b octopus-a master &&
+ test_commit octopus-1 &&
+ git checkout -b octopus-b master &&
+ test_commit octopus-2 &&
+ git checkout master &&
+ git merge octopus-a octopus-b &&
+ check_oneline "Merge branches Qoctopus-aQ and Qoctopus-bQ"
+'
+
+test_expect_success 'merge tag' '
+ git checkout -b tag-branch master &&
+ test_commit tag-1 &&
+ git checkout master &&
+ test_commit master-3 &&
+ git merge tag-1 &&
+ check_oneline "Merge commit Qtag-1Q"
+'
+
+test_expect_success 'ambiguous tag' '
+ git checkout -b ambiguous master &&
+ test_commit ambiguous &&
+ git checkout master &&
+ test_commit master-4 &&
+ git merge ambiguous &&
+ check_oneline "Merge commit QambiguousQ"
+'
+
+test_expect_success 'remote branch' '
+ git checkout -b remote master &&
+ test_commit remote-1 &&
+ git update-ref refs/remotes/origin/master remote &&
+ git checkout master &&
+ test_commit master-5 &&
+ git merge origin/master &&
+ check_oneline "Merge remote branch Qorigin/masterQ"
+'
+
+test_done
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 6b0483f3e9..e768c3eb2d 100644..100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -3,44 +3,87 @@
# Copyright (c) 2008 Charles Bailey
#
-test_description='git-mergetool
+test_description='git mergetool
Testing basic merge tool invocation'
. ./test-lib.sh
+# All the mergetool test work by checking out a temporary branch based
+# off 'branch1' and then merging in master and checking the results of
+# running mergetool
+
test_expect_success 'setup' '
echo master >file1 &&
- git add file1 &&
+ mkdir subdir &&
+ echo master sub >subdir/file3 &&
+ git add file1 subdir/file3 &&
git commit -m "added file1" &&
+
git checkout -b branch1 master &&
echo branch1 change >file1 &&
echo branch1 newfile >file2 &&
- git add file1 file2 &&
+ echo branch1 sub >subdir/file3 &&
+ git add file1 file2 subdir/file3 &&
git commit -m "branch1 changes" &&
- git checkout -b branch2 master &&
- echo branch2 change >file1 &&
- echo branch2 newfile >file2 &&
- git add file1 file2 &&
- git commit -m "branch2 changes" &&
+
git checkout master &&
echo master updated >file1 &&
echo master new >file2 &&
- git add file1 file2 &&
- git commit -m "master updates"
-'
+ echo master new sub >subdir/file3 &&
+ git add file1 file2 subdir/file3 &&
+ git commit -m "master updates" &&
-test_expect_success 'custom mergetool' '
git config merge.tool mytool &&
git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" &&
- git config mergetool.mytool.trustExitCode true &&
- git checkout branch1 &&
- ! git merge master >/dev/null 2>&1 &&
- ( yes "" | git mergetool file1>/dev/null 2>&1 ) &&
- ( yes "" | git mergetool file2>/dev/null 2>&1 ) &&
+ git config mergetool.mytool.trustExitCode true
+'
+
+test_expect_success 'custom mergetool' '
+ git checkout -b test1 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 subdir/file3 >/dev/null 2>&1 ) &&
test "$(cat file1)" = "master updated" &&
test "$(cat file2)" = "master new" &&
- git commit -m "branch1 resolved with mergetool"
+ test "$(cat subdir/file3)" = "master new sub" &&
+ 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 subdir/file3 >/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 commit -m "branch1 resolved with mergetool - autocrlf" &&
+ git config core.autocrlf false &&
+ git reset --hard
'
+test_expect_success 'mergetool in subdir' '
+ git checkout -b test3 branch1
+ 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" )
+'
+
+# We can't merge files from parent directories when running mergetool
+# from a subdir. Is this a bug?
+#
+#test_expect_failure 'mergetool in subdir' '
+# cd subdir && (
+# ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) &&
+# ( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) &&
+# test "$(cat ../file1)" = "master updated" &&
+# test "$(cat ../file2)" = "master new" &&
+# git commit -m "branch1 resolved with mergetool - subdir" )
+#'
+
test_done
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
new file mode 100755
index 0000000000..f4aa054750
--- /dev/null
+++ b/t/t7700-repack.sh
@@ -0,0 +1,165 @@
+#!/bin/sh
+
+test_description='git repack works correctly'
+
+. ./test-lib.sh
+
+test_expect_success 'objects in packs marked .keep are not repacked' '
+ echo content1 > file1 &&
+ echo content2 > file2 &&
+ git add . &&
+ git commit -m initial_commit &&
+ # Create two packs
+ # The first pack will contain all of the objects except one
+ git rev-list --objects --all | grep -v file2 |
+ git pack-objects pack > /dev/null &&
+ # 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 &&
+ objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |
+ sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") &&
+ mv pack-* .git/objects/pack/ &&
+ git repack -A -d -l &&
+ git prune-packed &&
+ 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 -z "$found_duplicate_object"
+'
+
+test_expect_success 'loose objects in alternate ODB are not repacked' '
+ mkdir alt_objects &&
+ echo `pwd`/alt_objects > .git/objects/info/alternates &&
+ echo content3 > file3 &&
+ objsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&
+ git add file3 &&
+ git commit -m commit_file3 &&
+ git repack -a -d -l &&
+ git prune-packed &&
+ for p in .git/objects/pack/*.idx; do
+ if git verify-pack -v $p | egrep "^$objsha1"; then
+ found_duplicate_object=1
+ echo "DUPLICATE OBJECT FOUND"
+ break
+ fi
+ done &&
+ test -z "$found_duplicate_object"
+'
+
+test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
+ mkdir alt_objects/pack
+ mv .git/objects/pack/* alt_objects/pack &&
+ git repack -a &&
+ myidx=$(ls -1 .git/objects/pack/*.idx) &&
+ test -f "$myidx" &&
+ for p in alt_objects/pack/*.idx; do
+ git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
+ done | while read sha1 rest; do
+ if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
+ echo "Missing object in local pack: $sha1"
+ return 1
+ fi
+ done
+'
+
+test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '
+ rm -f .git/objects/pack/* &&
+ echo new_content >> file1 &&
+ git add file1 &&
+ git commit -m more_content &&
+ git repack &&
+ git repack -a -d &&
+ myidx=$(ls -1 .git/objects/pack/*.idx) &&
+ test -f "$myidx" &&
+ for p in alt_objects/pack/*.idx; do
+ git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
+ done | while read sha1 rest; do
+ if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
+ echo "Missing object in local pack: $sha1"
+ return 1
+ fi
+ done
+'
+
+test_expect_success 'packed obs in alternate ODB kept pack are repacked' '
+ # swap the .keep so the commit object is in the pack with .keep
+ for p in alt_objects/pack/*.pack
+ do
+ base_name=$(basename $p .pack)
+ if test -f alt_objects/pack/$base_name.keep
+ then
+ rm alt_objects/pack/$base_name.keep
+ else
+ touch alt_objects/pack/$base_name.keep
+ fi
+ done
+ git repack -a -d &&
+ myidx=$(ls -1 .git/objects/pack/*.idx) &&
+ test -f "$myidx" &&
+ for p in alt_objects/pack/*.idx; do
+ git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
+ done | while read sha1 rest; do
+ if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
+ echo "Missing object in local pack: $sha1"
+ return 1
+ fi
+ done
+'
+
+test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '
+ rm -f alt_objects/pack/*.keep &&
+ mv .git/objects/pack/* alt_objects/pack/ &&
+ csha1=$(git rev-parse HEAD^{commit}) &&
+ git reset --hard HEAD^ &&
+ sleep 1 &&
+ git reflog expire --expire=now --expire-unreachable=now --all &&
+ # The pack-objects call on the next line is equivalent to
+ # git repack -A -d without the call to prune-packed
+ git pack-objects --honor-pack-keep --non-empty --all --reflog \
+ --unpack-unreachable </dev/null pack &&
+ rm -f .git/objects/pack/* &&
+ mv pack-* .git/objects/pack/ &&
+ test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
+ egrep "^$csha1 " | sort | uniq | wc -l) &&
+ echo > .git/objects/info/alternates &&
+ test_must_fail git show $csha1
+'
+
+test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '
+ echo `pwd`/alt_objects > .git/objects/info/alternates &&
+ echo "$csha1" | git pack-objects --non-empty --all --reflog pack &&
+ rm -f .git/objects/pack/* &&
+ mv pack-* .git/objects/pack/ &&
+ # The pack-objects call on the next line is equivalent to
+ # git repack -A -d without the call to prune-packed
+ git pack-objects --honor-pack-keep --non-empty --all --reflog \
+ --unpack-unreachable </dev/null pack &&
+ rm -f .git/objects/pack/* &&
+ mv pack-* .git/objects/pack/ &&
+ test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
+ egrep "^$csha1 " | sort | uniq | wc -l) &&
+ echo > .git/objects/info/alternates &&
+ test_must_fail git show $csha1
+'
+
+test_expect_success 'objects made unreachable by grafts only are kept' '
+ test_tick &&
+ git commit --allow-empty -m "commit 4" &&
+ H0=$(git rev-parse HEAD) &&
+ H1=$(git rev-parse HEAD^) &&
+ H2=$(git rev-parse HEAD^^) &&
+ echo "$H0 $H2" > .git/info/grafts &&
+ git reflog expire --expire=now --expire-unreachable=now --all &&
+ git repack -a -d &&
+ git cat-file -t $H1
+ '
+
+test_done
+
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
new file mode 100755
index 0000000000..5babdf26e6
--- /dev/null
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+test_description='git repack works correctly'
+
+. ./test-lib.sh
+
+fsha1=
+csha1=
+tsha1=
+
+test_expect_success '-A with -d option leaves unreachable objects unpacked' '
+ echo content > file1 &&
+ git add . &&
+ git commit -m initial_commit &&
+ # create a transient branch with unique content
+ git checkout -b transient_branch &&
+ echo more content >> file1 &&
+ # record the objects created in the database for file, commit, tree
+ fsha1=$(git hash-object file1) &&
+ git commit -a -m more_content &&
+ csha1=$(git rev-parse HEAD^{commit}) &&
+ tsha1=$(git rev-parse HEAD^{tree}) &&
+ git checkout master &&
+ echo even more content >> file1 &&
+ git commit -a -m even_more_content &&
+ # delete the transient branch
+ git branch -D transient_branch &&
+ # pack the repo
+ git repack -A -d -l &&
+ # verify objects are packed in repository
+ test 3 = $(git verify-pack -v -- .git/objects/pack/*.idx |
+ egrep "^($fsha1|$csha1|$tsha1) " |
+ sort | uniq | wc -l) &&
+ git show $fsha1 &&
+ git show $csha1 &&
+ git show $tsha1 &&
+ # now expire the reflog
+ sleep 1 &&
+ git reflog expire --expire-unreachable=now --all &&
+ # and repack
+ git repack -A -d -l &&
+ # verify objects are retained unpacked
+ test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
+ egrep "^($fsha1|$csha1|$tsha1) " |
+ sort | uniq | wc -l) &&
+ git show $fsha1 &&
+ git show $csha1 &&
+ git show $tsha1
+'
+
+compare_mtimes ()
+{
+ read tref rest &&
+ while read t rest; do
+ test "$tref" = "$t" || break
+ done
+}
+
+test_expect_success '-A without -d option leaves unreachable objects packed' '
+ fsha1path=$(echo "$fsha1" | sed -e "s|\(..\)|\1/|") &&
+ fsha1path=".git/objects/$fsha1path" &&
+ csha1path=$(echo "$csha1" | sed -e "s|\(..\)|\1/|") &&
+ csha1path=".git/objects/$csha1path" &&
+ tsha1path=$(echo "$tsha1" | sed -e "s|\(..\)|\1/|") &&
+ tsha1path=".git/objects/$tsha1path" &&
+ git branch transient_branch $csha1 &&
+ git repack -a -d -l &&
+ test ! -f "$fsha1path" &&
+ test ! -f "$csha1path" &&
+ test ! -f "$tsha1path" &&
+ test 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) &&
+ packfile=$(ls .git/objects/pack/pack-*.pack) &&
+ git branch -D transient_branch &&
+ sleep 1 &&
+ git repack -A -l &&
+ test ! -f "$fsha1path" &&
+ test ! -f "$csha1path" &&
+ test ! -f "$tsha1path" &&
+ git show $fsha1 &&
+ git show $csha1 &&
+ git show $tsha1
+'
+
+test_expect_success 'unpacked objects receive timestamp of pack file' '
+ tmppack=".git/objects/pack/tmp_pack" &&
+ ln "$packfile" "$tmppack" &&
+ git repack -A -l -d &&
+ test-chmtime -v +0 "$tmppack" "$fsha1path" "$csha1path" "$tsha1path" \
+ > mtimes &&
+ compare_mtimes < mtimes
+'
+
+test_done
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
new file mode 100755
index 0000000000..fff6a6d0ea
--- /dev/null
+++ b/t/t7800-difftool.sh
@@ -0,0 +1,216 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 David Aguilar
+#
+
+test_description='git-difftool
+
+Testing basic diff tool invocation
+'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PERL; then
+ say 'skipping difftool tests, perl not available'
+ test_done
+fi
+
+remove_config_vars()
+{
+ # Unset all config variables used by git-difftool
+ git config --unset diff.tool
+ git config --unset difftool.test-tool.cmd
+ git config --unset difftool.prompt
+ git config --unset merge.tool
+ git config --unset mergetool.test-tool.cmd
+ return 0
+}
+
+restore_test_defaults()
+{
+ # Restores the test defaults used by several tests
+ remove_config_vars
+ unset GIT_DIFF_TOOL
+ unset GIT_MERGE_TOOL
+ unset GIT_DIFFTOOL_PROMPT
+ unset GIT_DIFFTOOL_NO_PROMPT
+ git config diff.tool test-tool &&
+ git config difftool.test-tool.cmd 'cat $LOCAL'
+}
+
+prompt_given()
+{
+ prompt="$1"
+ test "$prompt" = "Hit return to launch 'test-tool': branch"
+}
+
+# Create a file on master and change it on branch
+test_expect_success 'setup' '
+ echo master >file &&
+ git add file &&
+ git commit -m "added file" &&
+
+ git checkout -b branch master &&
+ echo branch >file &&
+ git commit -a -m "branch changed file" &&
+ git checkout master
+'
+
+# Configure a custom difftool.<tool>.cmd and use it
+test_expect_success 'custom commands' '
+ restore_test_defaults &&
+ git config difftool.test-tool.cmd "cat \$REMOTE" &&
+
+ diff=$(git difftool --no-prompt branch) &&
+ test "$diff" = "master" &&
+
+ restore_test_defaults &&
+ diff=$(git difftool --no-prompt branch) &&
+ test "$diff" = "branch"
+'
+
+# Ensures that git-difftool ignores bogus --tool values
+test_expect_success 'difftool ignores bad --tool values' '
+ diff=$(git difftool --no-prompt --tool=bogus-tool branch)
+ test "$?" = 1 &&
+ test "$diff" = ""
+'
+
+# Specify the diff tool using $GIT_DIFF_TOOL
+test_expect_success 'GIT_DIFF_TOOL variable' '
+ git config --unset diff.tool
+ GIT_DIFF_TOOL=test-tool &&
+ export GIT_DIFF_TOOL &&
+
+ diff=$(git difftool --no-prompt branch) &&
+ test "$diff" = "branch" &&
+
+ restore_test_defaults
+'
+
+# Test the $GIT_*_TOOL variables and ensure
+# that $GIT_DIFF_TOOL always wins unless --tool is specified
+test_expect_success 'GIT_DIFF_TOOL overrides' '
+ git config diff.tool bogus-tool &&
+ git config merge.tool bogus-tool &&
+
+ GIT_MERGE_TOOL=test-tool &&
+ export GIT_MERGE_TOOL &&
+ diff=$(git difftool --no-prompt branch) &&
+ test "$diff" = "branch" &&
+ unset GIT_MERGE_TOOL &&
+
+ GIT_MERGE_TOOL=bogus-tool &&
+ GIT_DIFF_TOOL=test-tool &&
+ export GIT_MERGE_TOOL &&
+ export GIT_DIFF_TOOL &&
+
+ diff=$(git difftool --no-prompt branch) &&
+ test "$diff" = "branch" &&
+
+ GIT_DIFF_TOOL=bogus-tool &&
+ export GIT_DIFF_TOOL &&
+
+ diff=$(git difftool --no-prompt --tool=test-tool branch) &&
+ test "$diff" = "branch" &&
+
+ restore_test_defaults
+'
+
+# Test that we don't have to pass --no-prompt to difftool
+# when $GIT_DIFFTOOL_NO_PROMPT is true
+test_expect_success 'GIT_DIFFTOOL_NO_PROMPT variable' '
+ GIT_DIFFTOOL_NO_PROMPT=true &&
+ export GIT_DIFFTOOL_NO_PROMPT &&
+
+ diff=$(git difftool branch) &&
+ test "$diff" = "branch" &&
+
+ restore_test_defaults
+'
+
+# git-difftool supports the difftool.prompt variable.
+# Test that GIT_DIFFTOOL_PROMPT can override difftool.prompt = false
+test_expect_success 'GIT_DIFFTOOL_PROMPT variable' '
+ git config difftool.prompt false &&
+ GIT_DIFFTOOL_PROMPT=true &&
+ export GIT_DIFFTOOL_PROMPT &&
+
+ prompt=$(echo | git difftool branch | tail -1) &&
+ prompt_given "$prompt" &&
+
+ restore_test_defaults
+'
+
+# Test that we don't have to pass --no-prompt when difftool.prompt is false
+test_expect_success 'difftool.prompt config variable is false' '
+ git config difftool.prompt false &&
+
+ diff=$(git difftool branch) &&
+ test "$diff" = "branch" &&
+
+ restore_test_defaults
+'
+
+# Test that the -y flag can override difftool.prompt = true
+test_expect_success 'difftool.prompt can overridden with -y' '
+ git config difftool.prompt true &&
+
+ diff=$(git difftool -y branch) &&
+ test "$diff" = "branch" &&
+
+ restore_test_defaults
+'
+
+# Test that the --prompt flag can override difftool.prompt = false
+test_expect_success 'difftool.prompt can overridden with --prompt' '
+ git config difftool.prompt false &&
+
+ prompt=$(echo | git difftool --prompt branch | tail -1) &&
+ prompt_given "$prompt" &&
+
+ restore_test_defaults
+'
+
+# Test that the last flag passed on the command-line wins
+test_expect_success 'difftool last flag wins' '
+ diff=$(git difftool --prompt --no-prompt branch) &&
+ test "$diff" = "branch" &&
+
+ restore_test_defaults &&
+
+ prompt=$(echo | git difftool --no-prompt --prompt branch | tail -1) &&
+ prompt_given "$prompt" &&
+
+ restore_test_defaults
+'
+
+# git-difftool falls back to git-mergetool config variables
+# so test that behavior here
+test_expect_success 'difftool + mergetool config variables' '
+ remove_config_vars
+ git config merge.tool test-tool &&
+ git config mergetool.test-tool.cmd "cat \$LOCAL" &&
+
+ diff=$(git difftool --no-prompt branch) &&
+ test "$diff" = "branch" &&
+
+ # set merge.tool to something bogus, diff.tool to test-tool
+ git config merge.tool bogus-tool &&
+ git config diff.tool test-tool &&
+
+ diff=$(git difftool --no-prompt branch) &&
+ test "$diff" = "branch" &&
+
+ restore_test_defaults
+'
+
+test_expect_success 'difftool.<tool>.path' '
+ git config difftool.tkdiff.path echo &&
+ diff=$(git difftool --tool=tkdiff --no-prompt branch) &&
+ git config --unset difftool.tkdiff.path &&
+ lines=$(echo "$diff" | grep file | wc -l) &&
+ test "$lines" -eq 1
+'
+
+test_done
diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh
index eabec2e06e..45cb60ea4b 100755
--- a/t/t8001-annotate.sh
+++ b/t/t8001-annotate.sh
@@ -4,7 +4,7 @@ test_description='git annotate'
. ./test-lib.sh
PROG='git annotate'
-. ../annotate-tests.sh
+. "$TEST_DIRECTORY"/annotate-tests.sh
test_expect_success \
'Annotating an old revision works' \
diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh
index 92ece30fa9..597cf0486f 100755
--- a/t/t8002-blame.sh
+++ b/t/t8002-blame.sh
@@ -4,6 +4,6 @@ test_description='git blame'
. ./test-lib.sh
PROG='git blame -c'
-. ../annotate-tests.sh
+. "$TEST_DIRECTORY"/annotate-tests.sh
test_done
diff --git a/t/t8003-blame.sh b/t/t8003-blame.sh
index 966bb0a61a..ad834f200a 100755
--- a/t/t8003-blame.sh
+++ b/t/t8003-blame.sh
@@ -129,4 +129,32 @@ test_expect_success 'blame wholesale copy and more' '
'
+test_expect_success 'blame path that used to be a directory' '
+ mkdir path &&
+ echo A A A A A >path/file &&
+ echo B B B B B >path/elif &&
+ git add path &&
+ test_tick &&
+ git commit -m "path was a directory" &&
+ rm -fr path &&
+ echo A A A A A >path &&
+ git add path &&
+ test_tick &&
+ git commit -m "path is a regular file" &&
+ git blame HEAD^.. -- path
+'
+
+test_expect_success 'blame to a commit with no author name' '
+ TREE=`git rev-parse HEAD:`
+ cat >badcommit <<EOF
+tree $TREE
+author <noname> 1234567890 +0000
+committer David Reiss <dreiss@facebook.com> 1234567890 +0000
+
+some message
+EOF
+ COMMIT=`git hash-object -t commit -w badcommit`
+ git --no-pager blame $COMMIT -- uno >/dev/null
+'
+
test_done
diff --git a/t/t8005-blame-i18n.sh b/t/t8005-blame-i18n.sh
new file mode 100755
index 0000000000..cb390559f9
--- /dev/null
+++ b/t/t8005-blame-i18n.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+test_description='git blame encoding conversion'
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/t8005/utf8.txt
+. "$TEST_DIRECTORY"/t8005/euc-japan.txt
+. "$TEST_DIRECTORY"/t8005/sjis.txt
+
+test_expect_success 'setup the repository' '
+ # Create the file
+ echo "UTF-8 LINE" > file &&
+ git add file &&
+ git commit --author "$UTF8_NAME <utf8@localhost>" -m "$UTF8_MSG" &&
+
+ echo "EUC-JAPAN LINE" >> file &&
+ git add file &&
+ git config i18n.commitencoding eucJP &&
+ git commit --author "$EUC_JAPAN_NAME <euc-japan@localhost>" -m "$EUC_JAPAN_MSG" &&
+
+ echo "SJIS LINE" >> file &&
+ git add file &&
+ git config i18n.commitencoding SJIS &&
+ git commit --author "$SJIS_NAME <sjis@localhost>" -m "$SJIS_MSG"
+'
+
+cat >expected <<EOF
+author $SJIS_NAME
+summary $SJIS_MSG
+author $SJIS_NAME
+summary $SJIS_MSG
+author $SJIS_NAME
+summary $SJIS_MSG
+EOF
+
+test_expect_success \
+ 'blame respects i18n.commitencoding' '
+ git blame --incremental file | \
+ egrep "^(author|summary) " > actual &&
+ test_cmp actual expected
+'
+
+cat >expected <<EOF
+author $EUC_JAPAN_NAME
+summary $EUC_JAPAN_MSG
+author $EUC_JAPAN_NAME
+summary $EUC_JAPAN_MSG
+author $EUC_JAPAN_NAME
+summary $EUC_JAPAN_MSG
+EOF
+
+test_expect_success \
+ 'blame respects i18n.logoutputencoding' '
+ git config i18n.logoutputencoding eucJP &&
+ git blame --incremental file | \
+ egrep "^(author|summary) " > actual &&
+ test_cmp actual expected
+'
+
+cat >expected <<EOF
+author $UTF8_NAME
+summary $UTF8_MSG
+author $UTF8_NAME
+summary $UTF8_MSG
+author $UTF8_NAME
+summary $UTF8_MSG
+EOF
+
+test_expect_success \
+ 'blame respects --encoding=UTF-8' '
+ git blame --incremental --encoding=UTF-8 file | \
+ egrep "^(author|summary) " > actual &&
+ test_cmp actual expected
+'
+
+cat >expected <<EOF
+author $SJIS_NAME
+summary $SJIS_MSG
+author $EUC_JAPAN_NAME
+summary $EUC_JAPAN_MSG
+author $UTF8_NAME
+summary $UTF8_MSG
+EOF
+
+test_expect_success \
+ 'blame respects --encoding=none' '
+ git blame --incremental --encoding=none file | \
+ egrep "^(author|summary) " > actual &&
+ test_cmp actual expected
+'
+
+test_done
diff --git a/t/t8005/euc-japan.txt b/t/t8005/euc-japan.txt
new file mode 100644
index 0000000000..288f040c99
--- /dev/null
+++ b/t/t8005/euc-japan.txt
@@ -0,0 +1,2 @@
+EUC_JAPAN_NAME="»³ÅÄ ÂÀϺ"
+EUC_JAPAN_MSG="¥Ö¥ì¡¼¥à¤Î¥Æ¥¹¥È¤Ç¤¹¡£"
diff --git a/t/t8005/sjis.txt b/t/t8005/sjis.txt
new file mode 100644
index 0000000000..bbdefeaced
--- /dev/null
+++ b/t/t8005/sjis.txt
@@ -0,0 +1,2 @@
+SJIS_NAME="ŽR“c ‘¾˜Y"
+SJIS_MSG="ƒuƒŒ[ƒ€‚̃eƒXƒg‚Å‚·B"
diff --git a/t/t8005/utf8.txt b/t/t8005/utf8.txt
new file mode 100644
index 0000000000..4d00dbea76
--- /dev/null
+++ b/t/t8005/utf8.txt
@@ -0,0 +1,2 @@
+UTF8_NAME="山田 太郎"
+UTF8_MSG="ブレームã®ãƒ†ã‚¹ãƒˆã§ã™ã€‚"
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index c0973b4e6e..752adaac85 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -1,8 +1,13 @@
#!/bin/sh
-test_description='git-send-email'
+test_description='git send-email'
. ./test-lib.sh
+if ! test_have_prereq PERL; then
+ say 'skipping git send-email tests, perl not available'
+ test_done
+fi
+
PROG='git send-email'
test_expect_success \
'prepare reference tree' \
@@ -13,7 +18,7 @@ test_expect_success \
test_expect_success \
'Setup helper tool' \
- '(echo "#!/bin/sh"
+ '(echo "#!$SHELL_PATH"
echo shift
echo output=1
echo "while test -f commandline\$output; do output=\$((\$output+1)); done"
@@ -32,31 +37,118 @@ clean_fake_sendmail() {
}
test_expect_success 'Extract patches' '
- patches=`git format-patch -n HEAD^1`
+ patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1`
+'
+
+# Test no confirm early to ensure remaining tests will not hang
+test_no_confirm () {
+ rm -f no_confirm_okay
+ echo n | \
+ GIT_SEND_EMAIL_NOTTY=1 \
+ git send-email \
+ --from="Example <from@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $@ \
+ $patches > stdout &&
+ test_must_fail grep "Send this email" stdout &&
+ > no_confirm_okay
+}
+
+# Exit immediately to prevent hang if a no-confirm test fails
+check_no_confirm () {
+ test -f no_confirm_okay || {
+ say 'No confirm test failed; skipping remaining tests to prevent hanging'
+ test_done
+ }
+}
+
+test_expect_success 'No confirm with --suppress-cc' '
+ test_no_confirm --suppress-cc=sob
+'
+check_no_confirm
+
+test_expect_success 'No confirm with --confirm=never' '
+ test_no_confirm --confirm=never
+'
+check_no_confirm
+
+# leave sendemail.confirm set to never after this so that none of the
+# remaining tests prompt unintentionally.
+test_expect_success 'No confirm with sendemail.confirm=never' '
+ git config sendemail.confirm never &&
+ test_no_confirm --compose --subject=foo
'
+check_no_confirm
test_expect_success 'Send patches' '
- git send-email --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
+ git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
'
cat >expected <<\EOF
!nobody@example.com!
!author@example.com!
+!one@example.com!
+!two@example.com!
EOF
test_expect_success \
'Verify commandline' \
- 'diff commandline1 expected'
+ 'test_cmp expected commandline1'
+
+test_expect_success 'Send patches with --envelope-sender' '
+ clean_fake_sendmail &&
+ git send-email --envelope-sender="Patch Contributer <patch@example.com>" --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
+'
+
+cat >expected <<\EOF
+!patch@example.com!
+!-i!
+!nobody@example.com!
+!author@example.com!
+!one@example.com!
+!two@example.com!
+EOF
+test_expect_success \
+ 'Verify commandline' \
+ 'test_cmp expected commandline1'
+
+test_expect_success 'Send patches with --envelope-sender=auto' '
+ clean_fake_sendmail &&
+ git send-email --envelope-sender=auto --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
+'
+
+cat >expected <<\EOF
+!nobody@example.com!
+!-i!
+!nobody@example.com!
+!author@example.com!
+!one@example.com!
+!two@example.com!
+EOF
+test_expect_success \
+ 'Verify commandline' \
+ 'test_cmp expected commandline1'
cat >expected-show-all-headers <<\EOF
0001-Second.patch
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
+(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
+(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<bcc@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<cc@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<bcc@example.com>
From: Example <from@example.com>
To: to@example.com
-Cc: cc@example.com, A <author@example.com>
+Cc: cc@example.com,
+ A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -70,6 +162,7 @@ EOF
test_expect_success 'Show all headers' '
git send-email \
--dry-run \
+ --suppress-cc=sob \
--from="Example <from@example.com>" \
--to=to@example.com \
--cc=cc@example.com \
@@ -84,6 +177,38 @@ test_expect_success 'Show all headers' '
test_cmp expected-show-all-headers actual-show-all-headers
'
+test_expect_success 'Prompting works' '
+ clean_fake_sendmail &&
+ (echo "Example <from@example.com>"
+ echo "to@example.com"
+ echo ""
+ ) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches \
+ 2>errors &&
+ grep "^From: Example <from@example.com>$" msgtxt1 &&
+ grep "^To: to@example.com$" msgtxt1
+'
+
+test_expect_success 'cccmd works' '
+ clean_fake_sendmail &&
+ cp $patches cccmd.patch &&
+ echo cccmd--cccmd@example.com >>cccmd.patch &&
+ {
+ echo "#!$SHELL_PATH"
+ echo sed -n -e s/^cccmd--//p \"\$1\"
+ } > cccmd-sed &&
+ chmod +x cccmd-sed &&
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --cc-cmd=./cccmd-sed \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ cccmd.patch \
+ &&
+ grep "^ cccmd@example.com" msgtxt1
+'
+
z8=zzzzzzzz
z64=$z8$z8$z8$z8$z8$z8$z8$z8
z512=$z64$z64$z64$z64$z64$z64$z64$z64
@@ -91,7 +216,7 @@ test_expect_success 'reject long lines' '
clean_fake_sendmail &&
cp $patches longline.patch &&
echo $z512$z512 >>longline.patch &&
- ! git send-email \
+ test_must_fail git send-email \
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
@@ -104,12 +229,34 @@ test_expect_success 'no patch was sent' '
! test -e commandline1
'
+test_expect_success 'Author From: in message body' '
+ clean_fake_sendmail &&
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches &&
+ sed "1,/^$/d" < msgtxt1 > msgbody1
+ grep "From: A <author@example.com>" msgbody1
+'
+
+test_expect_success 'Author From: not in message body' '
+ clean_fake_sendmail &&
+ git send-email \
+ --from="A <author@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches &&
+ sed "1,/^$/d" < msgtxt1 > msgbody1
+ ! grep "From: A <author@example.com>" msgbody1
+'
+
test_expect_success 'allow long lines with --no-validate' '
git send-email \
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
- --no-validate \
+ --novalidate \
$patches longline.patch \
2>errors
'
@@ -138,32 +285,571 @@ test_expect_success 'Valid In-Reply-To when prompting' '
'
test_expect_success 'setup fake editor' '
- (echo "#!/bin/sh" &&
- echo "echo fake edit >>\$1"
+ (echo "#!$SHELL_PATH" &&
+ echo "echo fake edit >>\"\$1\""
) >fake-editor &&
chmod +x fake-editor
'
+test_set_editor "$(pwd)/fake-editor"
+
test_expect_success '--compose works' '
clean_fake_sendmail &&
+ git send-email \
+ --compose --subject foo \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches \
+ 2>errors
+'
+
+test_expect_success 'first message is compose text' '
+ grep "^fake edit" msgtxt1
+'
+
+test_expect_success 'second message is patch' '
+ grep "Subject:.*Second" msgtxt2
+'
+
+cat >expected-suppress-sob <<\EOF
+0001-Second.patch
+(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
+(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
+(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+Dry-OK. Log says:
+Server: relay.example.com
+MAIL FROM:<from@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<cc@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+From: Example <from@example.com>
+To: to@example.com
+Cc: cc@example.com,
+ A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
+Subject: [PATCH 1/1] Second.
+Date: DATE-STRING
+Message-Id: MESSAGE-ID-STRING
+X-Mailer: X-MAILER-STRING
+
+Result: OK
+EOF
+
+test_suppression () {
+ git send-email \
+ --dry-run \
+ --suppress-cc=$1 ${2+"--suppress-cc=$2"} \
+ --from="Example <from@example.com>" \
+ --to=to@example.com \
+ --smtp-server relay.example.com \
+ $patches |
+ sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \
+ -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
+ -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \
+ >actual-suppress-$1${2+"-$2"} &&
+ test_cmp expected-suppress-$1${2+"-$2"} actual-suppress-$1${2+"-$2"}
+}
+
+test_expect_success 'sendemail.cc set' '
+ git config sendemail.cc cc@example.com &&
+ test_suppression sob
+'
+
+cat >expected-suppress-sob <<\EOF
+0001-Second.patch
+(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
+(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
+(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+Dry-OK. Log says:
+Server: relay.example.com
+MAIL FROM:<from@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+From: Example <from@example.com>
+To: to@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
+Subject: [PATCH 1/1] Second.
+Date: DATE-STRING
+Message-Id: MESSAGE-ID-STRING
+X-Mailer: X-MAILER-STRING
+
+Result: OK
+EOF
+
+test_expect_success 'sendemail.cc unset' '
+ git config --unset sendemail.cc &&
+ test_suppression sob
+'
+
+cat >expected-suppress-cccmd <<\EOF
+0001-Second.patch
+(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
+(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
+(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
+Dry-OK. Log says:
+Server: relay.example.com
+MAIL FROM:<from@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<committer@example.com>
+From: Example <from@example.com>
+To: to@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com,
+ C O Mitter <committer@example.com>
+Subject: [PATCH 1/1] Second.
+Date: DATE-STRING
+Message-Id: MESSAGE-ID-STRING
+X-Mailer: X-MAILER-STRING
+
+Result: OK
+EOF
+
+test_expect_success 'sendemail.cccmd' '
+ echo echo cc-cmd@example.com > cccmd &&
+ chmod +x cccmd &&
+ git config sendemail.cccmd ./cccmd &&
+ test_suppression cccmd
+'
+
+cat >expected-suppress-all <<\EOF
+0001-Second.patch
+Dry-OK. Log says:
+Server: relay.example.com
+MAIL FROM:<from@example.com>
+RCPT TO:<to@example.com>
+From: Example <from@example.com>
+To: to@example.com
+Subject: [PATCH 1/1] Second.
+Date: DATE-STRING
+Message-Id: MESSAGE-ID-STRING
+X-Mailer: X-MAILER-STRING
+
+Result: OK
+EOF
+
+test_expect_success '--suppress-cc=all' '
+ test_suppression all
+'
+
+cat >expected-suppress-body <<\EOF
+0001-Second.patch
+(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
+(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
+(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+(cc-cmd) Adding cc: cc-cmd@example.com from: './cccmd'
+Dry-OK. Log says:
+Server: relay.example.com
+MAIL FROM:<from@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<cc-cmd@example.com>
+From: Example <from@example.com>
+To: to@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com,
+ cc-cmd@example.com
+Subject: [PATCH 1/1] Second.
+Date: DATE-STRING
+Message-Id: MESSAGE-ID-STRING
+X-Mailer: X-MAILER-STRING
+
+Result: OK
+EOF
+
+test_expect_success '--suppress-cc=body' '
+ test_suppression body
+'
+
+cat >expected-suppress-body-cccmd <<\EOF
+0001-Second.patch
+(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
+(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
+(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+Dry-OK. Log says:
+Server: relay.example.com
+MAIL FROM:<from@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+From: Example <from@example.com>
+To: to@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
+Subject: [PATCH 1/1] Second.
+Date: DATE-STRING
+Message-Id: MESSAGE-ID-STRING
+X-Mailer: X-MAILER-STRING
+
+Result: OK
+EOF
+
+test_expect_success '--suppress-cc=body --suppress-cc=cccmd' '
+ test_suppression body cccmd
+'
+
+cat >expected-suppress-sob <<\EOF
+0001-Second.patch
+(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
+(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
+(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+Dry-OK. Log says:
+Server: relay.example.com
+MAIL FROM:<from@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+From: Example <from@example.com>
+To: to@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com
+Subject: [PATCH 1/1] Second.
+Date: DATE-STRING
+Message-Id: MESSAGE-ID-STRING
+X-Mailer: X-MAILER-STRING
+
+Result: OK
+EOF
+
+test_expect_success '--suppress-cc=sob' '
+ git config --unset sendemail.cccmd
+ test_suppression sob
+'
+
+cat >expected-suppress-bodycc <<\EOF
+0001-Second.patch
+(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
+(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
+(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
+Dry-OK. Log says:
+Server: relay.example.com
+MAIL FROM:<from@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<committer@example.com>
+From: Example <from@example.com>
+To: to@example.com
+Cc: A <author@example.com>,
+ One <one@example.com>,
+ two@example.com,
+ C O Mitter <committer@example.com>
+Subject: [PATCH 1/1] Second.
+Date: DATE-STRING
+Message-Id: MESSAGE-ID-STRING
+X-Mailer: X-MAILER-STRING
+
+Result: OK
+EOF
+
+test_expect_success '--suppress-cc=bodycc' '
+ test_suppression bodycc
+'
+
+cat >expected-suppress-cc <<\EOF
+0001-Second.patch
+(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
+(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
+Dry-OK. Log says:
+Server: relay.example.com
+MAIL FROM:<from@example.com>
+RCPT TO:<to@example.com>
+RCPT TO:<author@example.com>
+RCPT TO:<committer@example.com>
+From: Example <from@example.com>
+To: to@example.com
+Cc: A <author@example.com>,
+ C O Mitter <committer@example.com>
+Subject: [PATCH 1/1] Second.
+Date: DATE-STRING
+Message-Id: MESSAGE-ID-STRING
+X-Mailer: X-MAILER-STRING
+
+Result: OK
+EOF
+
+test_expect_success '--suppress-cc=cc' '
+ test_suppression cc
+'
+
+test_confirm () {
echo y | \
- GIT_EDITOR=$(pwd)/fake-editor \
GIT_SEND_EMAIL_NOTTY=1 \
git send-email \
- --compose --subject foo \
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
- $patches \
- 2>errors
+ $@ $patches > stdout &&
+ grep "Send this email" stdout
+}
+
+test_expect_success '--confirm=always' '
+ test_confirm --confirm=always --suppress-cc=all
'
-test_expect_success 'first message is compose text' '
- grep "^fake edit" msgtxt1
+test_expect_success '--confirm=auto' '
+ test_confirm --confirm=auto
'
-test_expect_success 'second message is patch' '
- grep "Subject:.*Second" msgtxt2
+test_expect_success '--confirm=cc' '
+ test_confirm --confirm=cc
+'
+
+test_expect_success '--confirm=compose' '
+ test_confirm --confirm=compose --compose
+'
+
+test_expect_success 'confirm by default (due to cc)' '
+ CONFIRM=$(git config --get sendemail.confirm) &&
+ git config --unset sendemail.confirm &&
+ test_confirm
+ ret="$?"
+ git config sendemail.confirm ${CONFIRM:-never}
+ test $ret = "0"
+'
+
+test_expect_success 'confirm by default (due to --compose)' '
+ CONFIRM=$(git config --get sendemail.confirm) &&
+ git config --unset sendemail.confirm &&
+ test_confirm --suppress-cc=all --compose
+ ret="$?"
+ git config sendemail.confirm ${CONFIRM:-never}
+ test $ret = "0"
+'
+
+test_expect_success 'confirm detects EOF (inform assumes y)' '
+ CONFIRM=$(git config --get sendemail.confirm) &&
+ git config --unset sendemail.confirm &&
+ rm -fr outdir &&
+ git format-patch -2 -o outdir &&
+ GIT_SEND_EMAIL_NOTTY=1 \
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ outdir/*.patch < /dev/null
+ ret="$?"
+ git config sendemail.confirm ${CONFIRM:-never}
+ test $ret = "0"
+'
+
+test_expect_success 'confirm detects EOF (auto causes failure)' '
+ CONFIRM=$(git config --get sendemail.confirm) &&
+ git config sendemail.confirm auto &&
+ GIT_SEND_EMAIL_NOTTY=1 &&
+ export GIT_SEND_EMAIL_NOTTY &&
+ test_must_fail git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches < /dev/null
+ ret="$?"
+ git config sendemail.confirm ${CONFIRM:-never}
+ test $ret = "0"
+'
+
+test_expect_success 'confirm doesnt loop forever' '
+ CONFIRM=$(git config --get sendemail.confirm) &&
+ git config sendemail.confirm auto &&
+ GIT_SEND_EMAIL_NOTTY=1 &&
+ export GIT_SEND_EMAIL_NOTTY &&
+ yes "bogus" | test_must_fail git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches
+ ret="$?"
+ git config sendemail.confirm ${CONFIRM:-never}
+ test $ret = "0"
+'
+
+test_expect_success 'utf8 Cc is rfc2047 encoded' '
+ clean_fake_sendmail &&
+ rm -fr outdir &&
+ git format-patch -1 -o outdir --cc="àéìöú <utf8@example.com>" &&
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ outdir/*.patch &&
+ grep "^ " msgtxt1 |
+ grep "=?UTF-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>"
+'
+
+test_expect_success '--compose adds MIME for utf8 body' '
+ clean_fake_sendmail &&
+ (echo "#!$SHELL_PATH" &&
+ echo "echo utf8 body: àéìöú >>\"\$1\""
+ ) >fake-editor-utf8 &&
+ chmod +x fake-editor-utf8 &&
+ GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
+ git send-email \
+ --compose --subject foo \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches &&
+ grep "^utf8 body" msgtxt1 &&
+ grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
+'
+
+test_expect_success '--compose respects user mime type' '
+ clean_fake_sendmail &&
+ (echo "#!$SHELL_PATH" &&
+ echo "(echo MIME-Version: 1.0"
+ echo " echo Content-Type: text/plain\\; charset=iso-8859-1"
+ echo " echo Content-Transfer-Encoding: 8bit"
+ echo " echo Subject: foo"
+ echo " echo "
+ echo " echo utf8 body: àéìöú) >\"\$1\""
+ ) >fake-editor-utf8-mime &&
+ chmod +x fake-editor-utf8-mime &&
+ GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
+ git send-email \
+ --compose --subject foo \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches &&
+ grep "^utf8 body" msgtxt1 &&
+ grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 &&
+ ! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
+'
+
+test_expect_success '--compose adds MIME for utf8 subject' '
+ clean_fake_sendmail &&
+ GIT_EDITOR="\"$(pwd)/fake-editor\"" \
+ git send-email \
+ --compose --subject utf8-sübjëct \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $patches &&
+ grep "^fake edit" msgtxt1 &&
+ grep "^Subject: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
+'
+
+test_expect_success 'detects ambiguous reference/file conflict' '
+ echo master > master &&
+ git add master &&
+ git commit -m"add master" &&
+ test_must_fail git send-email --dry-run master 2>errors &&
+ grep disambiguate errors
+'
+
+test_expect_success 'feed two files' '
+ rm -fr outdir &&
+ git format-patch -2 -o outdir &&
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ outdir/000?-*.patch 2>errors >out &&
+ grep "^Subject: " out >subjects &&
+ test "z$(sed -n -e 1p subjects)" = "zSubject: [PATCH 1/2] Second." &&
+ test "z$(sed -n -e 2p subjects)" = "zSubject: [PATCH 2/2] add master"
+'
+
+test_expect_success 'in-reply-to but no threading' '
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --in-reply-to="<in-reply-id@example.com>" \
+ --nothread \
+ $patches |
+ grep "In-Reply-To: <in-reply-id@example.com>"
+'
+
+test_expect_success 'no in-reply-to and no threading' '
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --nothread \
+ $patches $patches >stdout &&
+ ! grep "In-Reply-To: " stdout
+'
+
+test_expect_success 'threading but no chain-reply-to' '
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --thread \
+ --nochain-reply-to \
+ $patches $patches >stdout &&
+ grep "In-Reply-To: " stdout
+'
+
+test_expect_success 'warning with an implicit --chain-reply-to' '
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ outdir/000?-*.patch 2>errors >out &&
+ grep "no-chain-reply-to" errors
+'
+
+test_expect_success 'no warning with an explicit --chain-reply-to' '
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --chain-reply-to \
+ outdir/000?-*.patch 2>errors >out &&
+ ! grep "no-chain-reply-to" errors
+'
+
+test_expect_success 'no warning with an explicit --no-chain-reply-to' '
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --nochain-reply-to \
+ outdir/000?-*.patch 2>errors >out &&
+ ! grep "no-chain-reply-to" errors
+'
+
+test_expect_success 'no warning with sendemail.chainreplyto = false' '
+ git config sendemail.chainreplyto false &&
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ outdir/000?-*.patch 2>errors >out &&
+ ! grep "no-chain-reply-to" errors
+'
+
+test_expect_success 'no warning with sendemail.chainreplyto = true' '
+ git config sendemail.chainreplyto true &&
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ outdir/000?-*.patch 2>errors >out &&
+ ! grep "no-chain-reply-to" errors
'
test_done
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index 4e24ab3a7d..570e0359e4 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -3,56 +3,56 @@
# Copyright (c) 2006 Eric Wong
#
-test_description='git-svn basic tests'
-GIT_SVN_LC_ALL=$LC_ALL
+test_description='git svn basic tests'
+GIT_SVN_LC_ALL=${LC_ALL:-$LANG}
-case "$LC_ALL" in
+. ./lib-git-svn.sh
+
+say 'define NO_SVN_TESTS to skip git svn tests'
+
+case "$GIT_SVN_LC_ALL" in
*.UTF-8)
- have_utf8=t
+ test_set_prereq UTF8
;;
*)
- have_utf8=
+ say "UTF-8 locale not set, some tests skipped ($GIT_SVN_LC_ALL)"
;;
esac
-. ./lib-git-svn.sh
-
-echo 'define NO_SVN_TESTS to skip git-svn tests'
-
test_expect_success \
- 'initialize git-svn' "
+ 'initialize git svn' '
mkdir import &&
cd import &&
echo foo > foo &&
ln -s foo foo.link
mkdir -p dir/a/b/c/d/e &&
- echo 'deep dir' > dir/a/b/c/d/e/file &&
+ echo "deep dir" > dir/a/b/c/d/e/file &&
mkdir bar &&
- echo 'zzz' > bar/zzz &&
- echo '#!/bin/sh' > exec.sh &&
+ echo "zzz" > bar/zzz &&
+ echo "#!/bin/sh" > exec.sh &&
chmod +x exec.sh &&
- svn import -m 'import for git-svn' . $svnrepo >/dev/null &&
+ svn_cmd import -m "import for git svn" . "$svnrepo" >/dev/null &&
cd .. &&
rm -rf import &&
- git-svn init $svnrepo"
+ git svn init "$svnrepo"'
test_expect_success \
'import an SVN revision into git' \
- 'git-svn fetch'
+ 'git svn fetch'
-test_expect_success "checkout from svn" "svn co $svnrepo '$SVN_TREE'"
+test_expect_success "checkout from svn" 'svn co "$svnrepo" "$SVN_TREE"'
name='try a deep --rmdir with a commit'
-test_expect_success "$name" "
- git checkout -f -b mybranch remotes/git-svn &&
+test_expect_success "$name" '
+ git checkout -f -b mybranch ${remotes_git_svn} &&
mv dir/a/b/c/d/e/file dir/file &&
cp dir/file file &&
git update-index --add --remove dir/a/b/c/d/e/file dir/file file &&
- git commit -m '$name' &&
- git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch &&
- svn up '$SVN_TREE' &&
- test -d '$SVN_TREE'/dir && test ! -d '$SVN_TREE'/dir/a"
+ git commit -m "$name" &&
+ git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch &&
+ svn_cmd up "$SVN_TREE" &&
+ test -d "$SVN_TREE"/dir && test ! -d "$SVN_TREE"/dir/a'
name='detect node change from file to directory #1'
@@ -63,141 +63,136 @@ test_expect_success "$name" "
git update-index --remove dir/file &&
git update-index --add dir/file/file &&
git commit -m '$name' &&
- ! git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch" || true
+ test_must_fail git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch" || true
name='detect node change from directory to file #1'
-test_expect_success "$name" "
- rm -rf dir '$GIT_DIR'/index &&
- git checkout -f -b mybranch2 remotes/git-svn &&
+test_expect_success "$name" '
+ rm -rf dir "$GIT_DIR"/index &&
+ git checkout -f -b mybranch2 ${remotes_git_svn} &&
mv bar/zzz zzz &&
rm -rf bar &&
mv zzz bar &&
git update-index --remove -- bar/zzz &&
git update-index --add -- bar &&
- git commit -m '$name' &&
- ! git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch2" || true
+ git commit -m "$name" &&
+ test_must_fail git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch2' || true
name='detect node change from file to directory #2'
-test_expect_success "$name" "
- rm -f '$GIT_DIR'/index &&
- git checkout -f -b mybranch3 remotes/git-svn &&
+test_expect_success "$name" '
+ rm -f "$GIT_DIR"/index &&
+ git checkout -f -b mybranch3 ${remotes_git_svn} &&
rm bar/zzz &&
git update-index --remove bar/zzz &&
mkdir bar/zzz &&
echo yyy > bar/zzz/yyy &&
git update-index --add bar/zzz/yyy &&
- git commit -m '$name' &&
- ! git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch3" || true
+ git commit -m "$name" &&
+ test_must_fail git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch3' || true
name='detect node change from directory to file #2'
-test_expect_success "$name" "
- rm -f '$GIT_DIR'/index &&
- git checkout -f -b mybranch4 remotes/git-svn &&
+test_expect_success "$name" '
+ rm -f "$GIT_DIR"/index &&
+ git checkout -f -b mybranch4 ${remotes_git_svn} &&
rm -rf dir &&
git update-index --remove -- dir/file &&
touch dir &&
echo asdf > dir &&
git update-index --add -- dir &&
- git commit -m '$name' &&
- ! git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch4" || true
+ git commit -m "$name" &&
+ test_must_fail git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch4' || true
name='remove executable bit from a file'
-test_expect_success "$name" "
- rm -f '$GIT_DIR'/index &&
- git checkout -f -b mybranch5 remotes/git-svn &&
+test_expect_success "$name" '
+ rm -f "$GIT_DIR"/index &&
+ git checkout -f -b mybranch5 ${remotes_git_svn} &&
chmod -x exec.sh &&
git update-index exec.sh &&
- git commit -m '$name' &&
- git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch5 &&
- svn up '$SVN_TREE' &&
- test ! -x '$SVN_TREE'/exec.sh"
+ git commit -m "$name" &&
+ git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch5 &&
+ svn_cmd up "$SVN_TREE" &&
+ test ! -x "$SVN_TREE"/exec.sh'
name='add executable bit back file'
-test_expect_success "$name" "
+test_expect_success "$name" '
chmod +x exec.sh &&
git update-index exec.sh &&
- git commit -m '$name' &&
- git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch5 &&
- svn up '$SVN_TREE' &&
- test -x '$SVN_TREE'/exec.sh"
+ git commit -m "$name" &&
+ git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch5 &&
+ svn_cmd up "$SVN_TREE" &&
+ test -x "$SVN_TREE"/exec.sh'
name='executable file becomes a symlink to bar/zzz (file)'
-test_expect_success "$name" "
+test_expect_success "$name" '
rm exec.sh &&
ln -s bar/zzz exec.sh &&
git update-index exec.sh &&
- git commit -m '$name' &&
- git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch5 &&
- svn up '$SVN_TREE' &&
- test -L '$SVN_TREE'/exec.sh"
+ git commit -m "$name" &&
+ git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch5 &&
+ svn_cmd up "$SVN_TREE" &&
+ test -L "$SVN_TREE"/exec.sh'
name='new symlink is added to a file that was also just made executable'
-test_expect_success "$name" "
+test_expect_success "$name" '
chmod +x bar/zzz &&
ln -s bar/zzz exec-2.sh &&
git update-index --add bar/zzz exec-2.sh &&
- git commit -m '$name' &&
- git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch5 &&
- svn up '$SVN_TREE' &&
- test -x '$SVN_TREE'/bar/zzz &&
- test -L '$SVN_TREE'/exec-2.sh"
+ git commit -m "$name" &&
+ git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch5 &&
+ svn_cmd up "$SVN_TREE" &&
+ test -x "$SVN_TREE"/bar/zzz &&
+ test -L "$SVN_TREE"/exec-2.sh'
name='modify a symlink to become a file'
-test_expect_success "$name" "
+test_expect_success "$name" '
echo git help > help || true &&
rm exec-2.sh &&
cp help exec-2.sh &&
git update-index exec-2.sh &&
- git commit -m '$name' &&
- git-svn set-tree --find-copies-harder --rmdir \
- remotes/git-svn..mybranch5 &&
- svn up '$SVN_TREE' &&
- test -f '$SVN_TREE'/exec-2.sh &&
- test ! -L '$SVN_TREE'/exec-2.sh &&
- git diff help $SVN_TREE/exec-2.sh"
-
-if test "$have_utf8" = t
-then
- name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL"
- LC_ALL="$GIT_SVN_LC_ALL"
- export LC_ALL
- test_expect_success "$name" "
- echo '# hello' >> exec-2.sh &&
- git update-index exec-2.sh &&
- git commit -m 'éïâˆ' &&
- git-svn set-tree HEAD"
- unset LC_ALL
-else
- echo "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)"
-fi
+ git commit -m "$name" &&
+ git svn set-tree --find-copies-harder --rmdir \
+ ${remotes_git_svn}..mybranch5 &&
+ svn_cmd up "$SVN_TREE" &&
+ test -f "$SVN_TREE"/exec-2.sh &&
+ test ! -L "$SVN_TREE"/exec-2.sh &&
+ test_cmp help "$SVN_TREE"/exec-2.sh'
+
+name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL"
+LC_ALL="$GIT_SVN_LC_ALL"
+export LC_ALL
+test_expect_success UTF8 "$name" "
+ echo '# hello' >> exec-2.sh &&
+ git update-index exec-2.sh &&
+ git commit -m 'éïâˆ' &&
+ git svn set-tree HEAD"
+unset LC_ALL
name='test fetch functionality (svn => git) with alternate GIT_SVN_ID'
GIT_SVN_ID=alt
export GIT_SVN_ID
test_expect_success "$name" \
- "git-svn init $svnrepo && git-svn fetch &&
- git rev-list --pretty=raw remotes/git-svn | grep ^tree | uniq > a &&
+ 'git svn init "$svnrepo" && git svn fetch &&
+ git rev-list --pretty=raw ${remotes_git_svn} | grep ^tree | uniq > a &&
git rev-list --pretty=raw remotes/alt | grep ^tree | uniq > b &&
- git diff a b"
+ test_cmp a b'
name='check imported tree checksums expected tree checksums'
rm -f expected
-if test "$have_utf8" = t
+if test_have_prereq UTF8
then
echo tree bf522353586b1b883488f2bc73dab0d9f774b9a9 > expected
fi
@@ -211,49 +206,68 @@ tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e
tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4
EOF
-test_expect_success "$name" "git diff a expected"
+test_expect_success "$name" "test_cmp a expected"
test_expect_success 'exit if remote refs are ambigious' "
git config --add svn-remote.svn.fetch \
- bar:refs/remotes/git-svn &&
- ! git-svn migrate
+ bar:refs/${remotes_git_svn} &&
+ test_must_fail git svn migrate
"
-test_expect_success 'exit if init-ing a would clobber a URL' "
- svnadmin create ${PWD}/svnrepo2 &&
- svn mkdir -m 'mkdir bar' ${svnrepo}2/bar &&
+test_expect_success 'exit if init-ing a would clobber a URL' '
+ svnadmin create "${PWD}/svnrepo2" &&
+ svn mkdir -m "mkdir bar" "${svnrepo}2/bar" &&
git config --unset svn-remote.svn.fetch \
- '^bar:refs/remotes/git-svn$' &&
- ! git-svn init ${svnrepo}2/bar
- "
+ "^bar:refs/${remotes_git_svn}$" &&
+ test_must_fail git svn init "${svnrepo}2/bar"
+ '
test_expect_success \
- 'init allows us to connect to another directory in the same repo' "
- git-svn init --minimize-url -i bar $svnrepo/bar &&
+ 'init allows us to connect to another directory in the same repo' '
+ git svn init --minimize-url -i bar "$svnrepo/bar" &&
git config --get svn-remote.svn.fetch \
- '^bar:refs/remotes/bar$' &&
+ "^bar:refs/remotes/bar$" &&
git config --get svn-remote.svn.fetch \
- '^:refs/remotes/git-svn$'
- "
+ "^:refs/${remotes_git_svn}$"
+ '
+
+test_expect_success 'dcommit $rev does not clobber current branch' '
+ git svn fetch -i bar &&
+ git checkout -b my-bar refs/remotes/bar &&
+ echo 1 > foo &&
+ git add foo &&
+ git commit -m "change 1" &&
+ echo 2 > foo &&
+ git add foo &&
+ git commit -m "change 2" &&
+ old_head=$(git rev-parse HEAD) &&
+ git svn dcommit -i bar HEAD^ &&
+ test $old_head = $(git rev-parse HEAD) &&
+ test refs/heads/my-bar = $(git symbolic-ref HEAD) &&
+ git log refs/remotes/bar | grep "change 1" &&
+ ! git log refs/remotes/bar | grep "change 2" &&
+ git checkout master &&
+ git branch -D my-bar
+ '
test_expect_success 'able to dcommit to a subdirectory' "
- git-svn fetch -i bar &&
+ git svn fetch -i bar &&
git checkout -b my-bar refs/remotes/bar &&
echo abc > d &&
git update-index --add d &&
git commit -m '/bar/d should be in the log' &&
- git-svn dcommit -i bar &&
+ git svn dcommit -i bar &&
test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" &&
mkdir newdir &&
echo new > newdir/dir &&
git update-index --add newdir/dir &&
git commit -m 'add a new directory' &&
- git-svn dcommit -i bar &&
+ git svn dcommit -i bar &&
test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" &&
echo foo >> newdir/dir &&
git update-index newdir/dir &&
git commit -m 'modify a file in new directory' &&
- git-svn dcommit -i bar &&
+ git svn dcommit -i bar &&
test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\"
"
@@ -261,8 +275,17 @@ test_expect_success 'able to set-tree to a subdirectory' "
echo cba > d &&
git update-index d &&
git commit -m 'update /bar/d' &&
- git-svn set-tree -i bar HEAD &&
+ git svn set-tree -i bar HEAD &&
test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\"
"
+test_expect_success 'git-svn works in a bare repository' '
+ mkdir bare-repo &&
+ ( cd bare-repo &&
+ git init --bare &&
+ GIT_DIR=. git svn init "$svnrepo" &&
+ git svn fetch ) &&
+ rm -rf bare-repo
+ '
+
test_done
diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh
index d7a704754e..929499e996 100755
--- a/t/t9101-git-svn-props.sh
+++ b/t/t9101-git-svn-props.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2006 Eric Wong
#
-test_description='git-svn property tests'
+test_description='git svn property tests'
. ./lib-git-svn.sh
mkdir import
@@ -26,56 +26,56 @@ cd import
EOF
printf "Hello\r\nWorld\r\n" > crlf
- a_crlf=`git-hash-object -w crlf`
+ a_crlf=`git hash-object -w crlf`
printf "Hello\rWorld\r" > cr
- a_cr=`git-hash-object -w cr`
+ a_cr=`git hash-object -w cr`
printf "Hello\nWorld\n" > lf
- a_lf=`git-hash-object -w lf`
+ a_lf=`git hash-object -w lf`
printf "Hello\r\nWorld" > ne_crlf
- a_ne_crlf=`git-hash-object -w ne_crlf`
+ a_ne_crlf=`git hash-object -w ne_crlf`
printf "Hello\nWorld" > ne_lf
- a_ne_lf=`git-hash-object -w ne_lf`
+ a_ne_lf=`git hash-object -w ne_lf`
printf "Hello\rWorld" > ne_cr
- a_ne_cr=`git-hash-object -w ne_cr`
+ a_ne_cr=`git hash-object -w ne_cr`
touch empty
- a_empty=`git-hash-object -w empty`
+ a_empty=`git hash-object -w empty`
printf "\n" > empty_lf
- a_empty_lf=`git-hash-object -w empty_lf`
+ a_empty_lf=`git hash-object -w empty_lf`
printf "\r" > empty_cr
- a_empty_cr=`git-hash-object -w empty_cr`
+ a_empty_cr=`git hash-object -w empty_cr`
printf "\r\n" > empty_crlf
- a_empty_crlf=`git-hash-object -w empty_crlf`
+ a_empty_crlf=`git hash-object -w empty_crlf`
- svn import --no-auto-props -m 'import for git-svn' . "$svnrepo" >/dev/null
+ svn_cmd import --no-auto-props -m 'import for git svn' . "$svnrepo" >/dev/null
cd ..
rm -rf import
-test_expect_success 'checkout working copy from svn' "svn co $svnrepo test_wc"
+test_expect_success 'checkout working copy from svn' 'svn co "$svnrepo" test_wc'
test_expect_success 'setup some commits to svn' \
'cd test_wc &&
echo Greetings >> kw.c &&
poke kw.c &&
- svn commit -m "Not yet an Id" &&
+ svn_cmd commit -m "Not yet an Id" &&
echo Hello world >> kw.c &&
poke kw.c &&
- svn commit -m "Modified file, but still not yet an Id" &&
- svn propset svn:keywords Id kw.c &&
+ svn_cmd commit -m "Modified file, but still not yet an Id" &&
+ svn_cmd propset svn:keywords Id kw.c &&
poke kw.c &&
- svn commit -m "Propset Id" &&
+ svn_cmd commit -m "Propset Id" &&
cd ..'
-test_expect_success 'initialize git-svn' "git-svn init $svnrepo"
-test_expect_success 'fetch revisions from svn' 'git-svn fetch'
+test_expect_success 'initialize git svn' 'git svn init "$svnrepo"'
+test_expect_success 'fetch revisions from svn' 'git svn fetch'
name='test svn:keywords ignoring'
test_expect_success "$name" \
- 'git checkout -b mybranch remotes/git-svn &&
+ 'git checkout -b mybranch ${remotes_git_svn} &&
echo Hi again >> kw.c &&
git commit -a -m "test keywords ignoring" &&
- git-svn set-tree remotes/git-svn..mybranch &&
- git pull . remotes/git-svn'
+ git svn set-tree ${remotes_git_svn}..mybranch &&
+ git pull . ${remotes_git_svn}'
expect='/* $Id$ */'
got="`sed -ne 2p kw.c`"
@@ -83,16 +83,16 @@ test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'"
test_expect_success "propset CR on crlf files" \
'cd test_wc &&
- svn propset svn:eol-style CR empty &&
- svn propset svn:eol-style CR crlf &&
- svn propset svn:eol-style CR ne_crlf &&
- svn commit -m "propset CR on crlf files" &&
+ svn_cmd propset svn:eol-style CR empty &&
+ svn_cmd propset svn:eol-style CR crlf &&
+ svn_cmd propset svn:eol-style CR ne_crlf &&
+ svn_cmd commit -m "propset CR on crlf files" &&
cd ..'
test_expect_success 'fetch and pull latest from svn and checkout a new wc' \
- "git-svn fetch &&
- git pull . remotes/git-svn &&
- svn co $svnrepo new_wc"
+ 'git svn fetch &&
+ git pull . ${remotes_git_svn} &&
+ svn_cmd co "$svnrepo" new_wc'
for i in crlf ne_crlf lf ne_lf cr ne_cr empty_cr empty_lf empty empty_crlf
do
@@ -103,20 +103,20 @@ done
cd test_wc
printf '$Id$\rHello\rWorld\r' > cr
printf '$Id$\rHello\rWorld' > ne_cr
- a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git-hash-object --stdin`
- a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git-hash-object --stdin`
+ a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git hash-object --stdin`
+ a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git hash-object --stdin`
test_expect_success 'Set CRLF on cr files' \
- 'svn propset svn:eol-style CRLF cr &&
- svn propset svn:eol-style CRLF ne_cr &&
- svn propset svn:keywords Id cr &&
- svn propset svn:keywords Id ne_cr &&
- svn commit -m "propset CRLF on cr files"'
+ 'svn_cmd propset svn:eol-style CRLF cr &&
+ svn_cmd propset svn:eol-style CRLF ne_cr &&
+ svn_cmd propset svn:keywords Id cr &&
+ svn_cmd propset svn:keywords Id ne_cr &&
+ svn_cmd commit -m "propset CRLF on cr files"'
cd ..
test_expect_success 'fetch and pull latest from svn' \
- 'git-svn fetch && git pull . remotes/git-svn'
+ 'git svn fetch && git pull . ${remotes_git_svn}'
-b_cr="`git-hash-object cr`"
-b_ne_cr="`git-hash-object ne_cr`"
+b_cr="`git hash-object cr`"
+b_ne_cr="`git hash-object ne_cr`"
test_expect_success 'CRLF + $Id$' "test '$a_cr' = '$b_cr'"
test_expect_success 'CRLF + $Id$ (no newline)' "test '$a_ne_cr' = '$b_ne_cr'"
@@ -140,12 +140,14 @@ test_expect_success 'test show-ignore' "
cd test_wc &&
mkdir -p deeply/nested/directory &&
touch deeply/nested/directory/.keep &&
- svn add deeply &&
- svn up &&
- svn propset -R svn:ignore 'no-such-file*' .
- svn commit -m 'propset svn:ignore'
+ svn_cmd add deeply &&
+ svn_cmd up &&
+ svn_cmd propset -R svn:ignore '
+no-such-file*
+' .
+ svn_cmd commit -m 'propset svn:ignore'
cd .. &&
- git-svn show-ignore > show-ignore.got &&
+ git svn show-ignore > show-ignore.got &&
cmp show-ignore.expect show-ignore.got
"
@@ -161,8 +163,8 @@ cat >create-ignore-index.expect <<\EOF
EOF
test_expect_success 'test create-ignore' "
- git-svn fetch && git pull . remotes/git-svn &&
- git-svn create-ignore &&
+ git svn fetch && git pull . ${remotes_git_svn} &&
+ git svn create-ignore &&
cmp ./.gitignore create-ignore.expect &&
cmp ./deeply/.gitignore create-ignore.expect &&
cmp ./deeply/nested/.gitignore create-ignore.expect &&
@@ -171,6 +173,7 @@ test_expect_success 'test create-ignore' "
"
cat >prop.expect <<\EOF
+
no-such-file*
EOF
@@ -182,15 +185,15 @@ EOF
# pattern, it can pass even though the propget did not execute on the
# right directory.
test_expect_success 'test propget' "
- git-svn propget svn:ignore . | cmp - prop.expect &&
+ git svn propget svn:ignore . | cmp - prop.expect &&
cd deeply &&
- git-svn propget svn:ignore . | cmp - ../prop.expect &&
- git-svn propget svn:entry:committed-rev nested/directory/.keep \
+ git svn propget svn:ignore . | cmp - ../prop.expect &&
+ git svn propget svn:entry:committed-rev nested/directory/.keep \
| cmp - ../prop2.expect &&
- git-svn propget svn:ignore .. | cmp - ../prop.expect &&
- git-svn propget svn:ignore nested/ | cmp - ../prop.expect &&
- git-svn propget svn:ignore ./nested | cmp - ../prop.expect &&
- git-svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect
+ git svn propget svn:ignore .. | cmp - ../prop.expect &&
+ git svn propget svn:ignore nested/ | cmp - ../prop.expect &&
+ git svn propget svn:ignore ./nested | cmp - ../prop.expect &&
+ git svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect
"
cat >prop.expect <<\EOF
@@ -210,8 +213,8 @@ Properties on 'nested/directory/.keep':
EOF
test_expect_success 'test proplist' "
- git-svn proplist . | cmp - prop.expect &&
- git-svn proplist nested/directory/.keep | cmp - prop2.expect
+ git svn proplist . | cmp - prop.expect &&
+ git svn proplist nested/directory/.keep | cmp - prop2.expect
"
test_done
diff --git a/t/t9102-git-svn-deep-rmdir.sh b/t/t9102-git-svn-deep-rmdir.sh
index 4e0808380f..028fb19e09 100755
--- a/t/t9102-git-svn-deep-rmdir.sh
+++ b/t/t9102-git-svn-deep-rmdir.sh
@@ -1,30 +1,30 @@
#!/bin/sh
-test_description='git-svn rmdir'
+test_description='git svn rmdir'
. ./lib-git-svn.sh
-test_expect_success 'initialize repo' "
+test_expect_success 'initialize repo' '
mkdir import &&
cd import &&
mkdir -p deeply/nested/directory/number/1 &&
mkdir -p deeply/nested/directory/number/2 &&
echo foo > deeply/nested/directory/number/1/file &&
echo foo > deeply/nested/directory/number/2/another &&
- svn import -m 'import for git-svn' . $svnrepo &&
+ svn_cmd import -m "import for git svn" . "$svnrepo" &&
cd ..
- "
+ '
-test_expect_success 'mirror via git-svn' "
- git-svn init $svnrepo &&
- git-svn fetch &&
- git checkout -f -b test-rmdir remotes/git-svn
- "
+test_expect_success 'mirror via git svn' '
+ git svn init "$svnrepo" &&
+ git svn fetch &&
+ git checkout -f -b test-rmdir ${remotes_git_svn}
+ '
-test_expect_success 'Try a commit on rmdir' "
+test_expect_success 'Try a commit on rmdir' '
git rm -f deeply/nested/directory/number/2/another &&
- git commit -a -m 'remove another' &&
- git-svn set-tree --rmdir HEAD &&
- svn ls -R $svnrepo | grep ^deeply/nested/directory/number/1
- "
+ git commit -a -m "remove another" &&
+ git svn set-tree --rmdir HEAD &&
+ svn_cmd ls -R "$svnrepo" | grep ^deeply/nested/directory/number/1
+ '
test_done
diff --git a/t/t9103-git-svn-tracked-directory-removed.sh b/t/t9103-git-svn-tracked-directory-removed.sh
index 0f0b0fd2c6..3413164cb1 100755
--- a/t/t9103-git-svn-tracked-directory-removed.sh
+++ b/t/t9103-git-svn-tracked-directory-removed.sh
@@ -3,37 +3,37 @@
# Copyright (c) 2007 Eric Wong
#
-test_description='git-svn tracking removed top-level path'
+test_description='git svn tracking removed top-level path'
. ./lib-git-svn.sh
test_expect_success 'make history for tracking' '
mkdir import &&
mkdir import/trunk &&
echo hello >> import/trunk/README &&
- svn import -m initial import $svnrepo &&
+ svn_cmd import -m initial import "$svnrepo" &&
rm -rf import &&
- svn co $svnrepo/trunk trunk &&
+ svn_cmd co "$svnrepo"/trunk trunk &&
echo bye bye >> trunk/README &&
- svn rm -m "gone" $svnrepo/trunk &&
+ svn_cmd rm -m "gone" "$svnrepo"/trunk &&
rm -rf trunk &&
mkdir trunk &&
echo "new" > trunk/FOLLOWME &&
- svn import -m "new trunk" trunk $svnrepo/trunk
+ svn_cmd import -m "new trunk" trunk "$svnrepo"/trunk
'
test_expect_success 'clone repo with git' '
- git svn clone -s $svnrepo x &&
+ git svn clone -s "$svnrepo" x &&
test -f x/FOLLOWME &&
test ! -f x/README
'
-test_expect_success 'make sure r2 still has old file' '
+test_expect_success 'make sure r2 still has old file' "
cd x &&
- test -n "$(git svn find-rev r1)" &&
- git reset --hard $(git svn find-rev r1) &&
+ test -n \"\$(git svn find-rev r1)\" &&
+ git reset --hard \$(git svn find-rev r1) &&
test -f README &&
test ! -f FOLLOWME &&
- test x$(git svn find-rev r2) = x
-'
+ test x\$(git svn find-rev r2) = x
+"
test_done
diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh
index 7ba76309ac..bbfd7f4793 100755
--- a/t/t9104-git-svn-follow-parent.sh
+++ b/t/t9104-git-svn-follow-parent.sh
@@ -3,168 +3,210 @@
# Copyright (c) 2006 Eric Wong
#
-test_description='git-svn fetching'
+test_description='git svn fetching'
. ./lib-git-svn.sh
-test_expect_success 'initialize repo' "
+test_expect_success 'initialize repo' '
mkdir import &&
cd import &&
mkdir -p trunk &&
echo hello > trunk/readme &&
- svn import -m 'initial' . $svnrepo &&
+ svn_cmd import -m "initial" . "$svnrepo" &&
cd .. &&
- svn co $svnrepo wc &&
+ svn_cmd co "$svnrepo" wc &&
cd wc &&
echo world >> trunk/readme &&
poke trunk/readme &&
- svn commit -m 'another commit' &&
- svn up &&
- svn mv trunk thunk &&
+ svn_cmd commit -m "another commit" &&
+ svn_cmd up &&
+ svn_cmd mv trunk thunk &&
echo goodbye >> thunk/readme &&
poke thunk/readme &&
- svn commit -m 'bye now' &&
+ svn_cmd commit -m "bye now" &&
cd ..
- "
+ '
-test_expect_success 'init and fetch a moved directory' "
- git-svn init --minimize-url -i thunk $svnrepo/thunk &&
- git-svn fetch -i thunk &&
- test \"\`git rev-parse --verify refs/remotes/thunk@2\`\" \
- = \"\`git rev-parse --verify refs/remotes/thunk~1\`\" &&
- test \"\`git cat-file blob refs/remotes/thunk:readme |\
- sed -n -e '3p'\`\" = goodbye &&
- test -z \"\`git config --get svn-remote.svn.fetch \
- '^trunk:refs/remotes/thunk@2$'\`\"
- "
+test_expect_success 'init and fetch a moved directory' '
+ git svn init --minimize-url -i thunk "$svnrepo"/thunk &&
+ git svn fetch -i thunk &&
+ test "`git rev-parse --verify refs/remotes/thunk@2`" \
+ = "`git rev-parse --verify refs/remotes/thunk~1`" &&
+ test "`git cat-file blob refs/remotes/thunk:readme |\
+ sed -n -e "3p"`" = goodbye &&
+ test -z "`git config --get svn-remote.svn.fetch \
+ "^trunk:refs/remotes/thunk@2$"`"
+ '
-test_expect_success 'init and fetch from one svn-remote' "
- git config svn-remote.svn.url $svnrepo &&
+test_expect_success 'init and fetch from one svn-remote' '
+ git config svn-remote.svn.url "$svnrepo" &&
git config --add svn-remote.svn.fetch \
trunk:refs/remotes/svn/trunk &&
git config --add svn-remote.svn.fetch \
thunk:refs/remotes/svn/thunk &&
- git-svn fetch -i svn/thunk &&
- test \"\`git rev-parse --verify refs/remotes/svn/trunk\`\" \
- = \"\`git rev-parse --verify refs/remotes/svn/thunk~1\`\" &&
- test \"\`git cat-file blob refs/remotes/svn/thunk:readme |\
- sed -n -e '3p'\`\" = goodbye
- "
-
-test_expect_success 'follow deleted parent' "
- (svn cp -m 'resurrecting trunk as junk' \
- $svnrepo/trunk@2 $svnrepo/junk ||
- svn cp -m 'resurrecting trunk as junk' \
- -r2 $svnrepo/trunk $svnrepo/junk) &&
+ git svn fetch -i svn/thunk &&
+ test "`git rev-parse --verify refs/remotes/svn/trunk`" \
+ = "`git rev-parse --verify refs/remotes/svn/thunk~1`" &&
+ test "`git cat-file blob refs/remotes/svn/thunk:readme |\
+ sed -n -e "3p"`" = goodbye
+ '
+
+test_expect_success 'follow deleted parent' '
+ (svn_cmd cp -m "resurrecting trunk as junk" \
+ "$svnrepo"/trunk@2 "$svnrepo"/junk ||
+ svn cp -m "resurrecting trunk as junk" \
+ -r2 "$svnrepo"/trunk "$svnrepo"/junk) &&
git config --add svn-remote.svn.fetch \
junk:refs/remotes/svn/junk &&
- git-svn fetch -i svn/thunk &&
- git-svn fetch -i svn/junk &&
- test -z \"\`git diff svn/junk svn/trunk\`\" &&
- test \"\`git merge-base svn/junk svn/trunk\`\" \
- = \"\`git rev-parse svn/trunk\`\"
- "
-
-test_expect_success 'follow larger parent' "
+ git svn fetch -i svn/thunk &&
+ git svn fetch -i svn/junk &&
+ test -z "`git diff svn/junk svn/trunk`" &&
+ test "`git merge-base svn/junk svn/trunk`" \
+ = "`git rev-parse svn/trunk`"
+ '
+
+test_expect_success 'follow larger parent' '
mkdir -p import/trunk/thunk/bump/thud &&
echo hi > import/trunk/thunk/bump/thud/file &&
- svn import -m 'import a larger parent' import $svnrepo/larger-parent &&
- svn cp -m 'hi' $svnrepo/larger-parent $svnrepo/another-larger &&
- git-svn init --minimize-url -i larger \
- $svnrepo/another-larger/trunk/thunk/bump/thud &&
- git-svn fetch -i larger &&
+ svn import -m "import a larger parent" import "$svnrepo"/larger-parent &&
+ svn cp -m "hi" "$svnrepo"/larger-parent "$svnrepo"/another-larger &&
+ git svn init --minimize-url -i larger \
+ "$svnrepo"/another-larger/trunk/thunk/bump/thud &&
+ git svn fetch -i larger &&
git rev-parse --verify refs/remotes/larger &&
git rev-parse --verify \
refs/remotes/larger-parent/trunk/thunk/bump/thud &&
- test \"\`git merge-base \
+ test "`git merge-base \
refs/remotes/larger-parent/trunk/thunk/bump/thud \
- refs/remotes/larger\`\" = \
- \"\`git rev-parse refs/remotes/larger\`\"
+ refs/remotes/larger`" = \
+ "`git rev-parse refs/remotes/larger`"
true
- "
+ '
-test_expect_success 'follow higher-level parent' "
- svn mkdir -m 'follow higher-level parent' $svnrepo/blob &&
- svn co $svnrepo/blob blob &&
+test_expect_success 'follow higher-level parent' '
+ svn mkdir -m "follow higher-level parent" "$svnrepo"/blob &&
+ svn co "$svnrepo"/blob blob &&
cd blob &&
echo hi > hi &&
svn add hi &&
- svn commit -m 'hihi' &&
+ svn commit -m "hihi" &&
cd ..
- svn mkdir -m 'new glob at top level' $svnrepo/glob &&
- svn mv -m 'move blob down a level' $svnrepo/blob $svnrepo/glob/blob &&
- git-svn init --minimize-url -i blob $svnrepo/glob/blob &&
- git-svn fetch -i blob
- "
-
-test_expect_success 'follow deleted directory' "
- svn mv -m 'bye!' $svnrepo/glob/blob/hi $svnrepo/glob/blob/bye &&
- svn rm -m 'remove glob' $svnrepo/glob &&
- git-svn init --minimize-url -i glob $svnrepo/glob &&
- git-svn fetch -i glob &&
- test \"\`git cat-file blob refs/remotes/glob:blob/bye\`\" = hi &&
- test \"\`git ls-tree refs/remotes/glob | wc -l \`\" -eq 1
- "
+ svn mkdir -m "new glob at top level" "$svnrepo"/glob &&
+ svn mv -m "move blob down a level" "$svnrepo"/blob "$svnrepo"/glob/blob &&
+ git svn init --minimize-url -i blob "$svnrepo"/glob/blob &&
+ git svn fetch -i blob
+ '
+
+test_expect_success 'follow deleted directory' '
+ svn_cmd mv -m "bye!" "$svnrepo"/glob/blob/hi "$svnrepo"/glob/blob/bye &&
+ svn_cmd rm -m "remove glob" "$svnrepo"/glob &&
+ git svn init --minimize-url -i glob "$svnrepo"/glob &&
+ git svn fetch -i glob &&
+ test "`git cat-file blob refs/remotes/glob:blob/bye`" = hi &&
+ test "`git ls-tree refs/remotes/glob | wc -l `" -eq 1
+ '
# ref: r9270 of the Subversion repository: (http://svn.collab.net/repos/svn)
# in trunk/subversion/bindings/swig/perl
-test_expect_success 'follow-parent avoids deleting relevant info' "
+test_expect_success 'follow-parent avoids deleting relevant info' '
mkdir -p import/trunk/subversion/bindings/swig/perl/t &&
for i in a b c ; do \
- echo \$i > import/trunk/subversion/bindings/swig/perl/\$i.pm &&
- echo _\$i > import/trunk/subversion/bindings/swig/perl/t/\$i.t; \
+ echo $i > import/trunk/subversion/bindings/swig/perl/$i.pm &&
+ echo _$i > import/trunk/subversion/bindings/swig/perl/t/$i.t; \
done &&
- echo 'bad delete test' > \
+ echo "bad delete test" > \
import/trunk/subversion/bindings/swig/perl/t/larger-parent &&
- echo 'bad delete test 2' > \
+ echo "bad delete test 2" > \
import/trunk/subversion/bindings/swig/perl/another-larger &&
cd import &&
- svn import -m 'r9270 test' . $svnrepo/r9270 &&
+ svn import -m "r9270 test" . "$svnrepo"/r9270 &&
cd .. &&
- svn co $svnrepo/r9270/trunk/subversion/bindings/swig/perl r9270 &&
+ svn_cmd co "$svnrepo"/r9270/trunk/subversion/bindings/swig/perl r9270 &&
cd r9270 &&
svn mkdir native &&
svn mv t native/t &&
- for i in a b c; do svn mv \$i.pm native/\$i.pm; done &&
+ for i in a b c; do svn mv $i.pm native/$i.pm; done &&
echo z >> native/t/c.t &&
poke native/t/c.t &&
- svn commit -m 'reorg test' &&
+ svn commit -m "reorg test" &&
cd .. &&
- git-svn init --minimize-url -i r9270-t \
- $svnrepo/r9270/trunk/subversion/bindings/swig/perl/native/t &&
- git-svn fetch -i r9270-t &&
- test \`git rev-list r9270-t | wc -l\` -eq 2 &&
- test \"\`git ls-tree --name-only r9270-t~1\`\" = \
- \"\`git ls-tree --name-only r9270-t\`\"
- "
+ git svn init --minimize-url -i r9270-t \
+ "$svnrepo"/r9270/trunk/subversion/bindings/swig/perl/native/t &&
+ git svn fetch -i r9270-t &&
+ test `git rev-list r9270-t | wc -l` -eq 2 &&
+ test "`git ls-tree --name-only r9270-t~1`" = \
+ "`git ls-tree --name-only r9270-t`"
+ '
-test_expect_success "track initial change if it was only made to parent" "
- svn cp -m 'wheee!' $svnrepo/r9270/trunk $svnrepo/r9270/drunk &&
- git-svn init --minimize-url -i r9270-d \
- $svnrepo/r9270/drunk/subversion/bindings/swig/perl/native/t &&
- git-svn fetch -i r9270-d &&
- test \`git rev-list r9270-d | wc -l\` -eq 3 &&
- test \"\`git ls-tree --name-only r9270-t\`\" = \
- \"\`git ls-tree --name-only r9270-d\`\" &&
- test \"\`git rev-parse r9270-t\`\" = \
- \"\`git rev-parse r9270-d~1\`\"
- "
+test_expect_success "track initial change if it was only made to parent" '
+ svn_cmd cp -m "wheee!" "$svnrepo"/r9270/trunk "$svnrepo"/r9270/drunk &&
+ git svn init --minimize-url -i r9270-d \
+ "$svnrepo"/r9270/drunk/subversion/bindings/swig/perl/native/t &&
+ git svn fetch -i r9270-d &&
+ test `git rev-list r9270-d | wc -l` -eq 3 &&
+ test "`git ls-tree --name-only r9270-t`" = \
+ "`git ls-tree --name-only r9270-d`" &&
+ test "`git rev-parse r9270-t`" = \
+ "`git rev-parse r9270-d~1`"
+ '
-test_expect_success "track multi-parent paths" "
- svn cp -m 'resurrect /glob' $svnrepo/r9270 $svnrepo/glob &&
- git-svn multi-fetch &&
- test \`git cat-file commit refs/remotes/glob | \
- grep '^parent ' | wc -l\` -eq 2
- "
+test_expect_success "follow-parent is atomic" '
+ (
+ cd wc &&
+ svn_cmd up &&
+ svn_cmd mkdir stunk &&
+ echo "trunk stunk" > stunk/readme &&
+ svn_cmd add stunk/readme &&
+ svn_cmd ci -m "trunk stunk" &&
+ echo "stunk like junk" >> stunk/readme &&
+ svn_cmd ci -m "really stunk" &&
+ echo "stink stank stunk" >> stunk/readme &&
+ svn_cmd ci -m "even the grinch agrees"
+ ) &&
+ svn_cmd copy -m "stunk flunked" "$svnrepo"/stunk "$svnrepo"/flunk &&
+ { svn cp -m "early stunk flunked too" \
+ "$svnrepo"/stunk@17 "$svnrepo"/flunked ||
+ svn_cmd cp -m "early stunk flunked too" \
+ -r17 "$svnrepo"/stunk "$svnrepo"/flunked; } &&
+ git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
+ git svn fetch -i stunk &&
+ git update-ref refs/remotes/flunk@18 refs/remotes/stunk~2 &&
+ git update-ref -d refs/remotes/stunk &&
+ git config --unset svn-remote.svn.fetch stunk &&
+ mkdir -p "$GIT_DIR"/svn/refs/remotes/flunk@18 &&
+ rev_map=$(cd "$GIT_DIR"/svn/refs/remotes/stunk && ls .rev_map*) &&
+ dd if="$GIT_DIR"/svn/refs/remotes/stunk/$rev_map \
+ of="$GIT_DIR"/svn/refs/remotes/flunk@18/$rev_map bs=24 count=1 &&
+ rm -rf "$GIT_DIR"/svn/refs/remotes/stunk &&
+ git svn init --minimize-url -i flunk "$svnrepo"/flunk &&
+ git svn fetch -i flunk &&
+ git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
+ git svn fetch -i stunk &&
+ git svn init --minimize-url -i flunked "$svnrepo"/flunked &&
+ git svn fetch -i flunked
+ test "`git rev-parse --verify refs/remotes/flunk@18`" \
+ = "`git rev-parse --verify refs/remotes/stunk`" &&
+ test "`git rev-parse --verify refs/remotes/flunk~1`" \
+ = "`git rev-parse --verify refs/remotes/stunk`" &&
+ test "`git rev-parse --verify refs/remotes/flunked~1`" \
+ = "`git rev-parse --verify refs/remotes/stunk~1`"
+ '
+
+test_expect_success "track multi-parent paths" '
+ svn_cmd cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob &&
+ git svn multi-fetch &&
+ test `git cat-file commit refs/remotes/glob | \
+ grep "^parent " | wc -l` -eq 2
+ '
test_expect_success "multi-fetch continues to work" "
- git-svn multi-fetch
+ git svn multi-fetch
"
-test_expect_success "multi-fetch works off a 'clean' repository" "
- rm -r $GIT_DIR/svn $GIT_DIR/refs/remotes $GIT_DIR/logs &&
- mkdir $GIT_DIR/svn &&
- git-svn multi-fetch
- "
+test_expect_success "multi-fetch works off a 'clean' repository" '
+ rm -r "$GIT_DIR/svn" "$GIT_DIR/refs/remotes" "$GIT_DIR/logs" &&
+ mkdir "$GIT_DIR/svn" &&
+ git svn multi-fetch
+ '
test_debug 'gitk --all &'
diff --git a/t/t9105-git-svn-commit-diff.sh b/t/t9105-git-svn-commit-diff.sh
index 318e172ef5..dd48e9cba8 100755
--- a/t/t9105-git-svn-commit-diff.sh
+++ b/t/t9105-git-svn-commit-diff.sh
@@ -1,21 +1,21 @@
#!/bin/sh
#
# Copyright (c) 2006 Eric Wong
-test_description='git-svn commit-diff'
+test_description='git svn commit-diff'
. ./lib-git-svn.sh
-test_expect_success 'initialize repo' "
+test_expect_success 'initialize repo' '
mkdir import &&
cd import &&
echo hello > readme &&
- svn import -m 'initial' . $svnrepo &&
+ svn_cmd import -m "initial" . "$svnrepo" &&
cd .. &&
echo hello > readme &&
git update-index --add readme &&
- git commit -a -m 'initial' &&
+ git commit -a -m "initial" &&
echo world >> readme &&
- git commit -a -m 'another'
- "
+ git commit -a -m "another"
+ '
head=`git rev-parse --verify HEAD^0`
prev=`git rev-parse --verify HEAD^1`
@@ -24,20 +24,20 @@ prev=`git rev-parse --verify HEAD^1`
# commit, so only a basic test of functionality is needed since we've
# already tested commit extensively elsewhere
-test_expect_success 'test the commit-diff command' "
- test -n '$prev' && test -n '$head' &&
- git-svn commit-diff -r1 '$prev' '$head' '$svnrepo' &&
- svn co $svnrepo wc &&
+test_expect_success 'test the commit-diff command' '
+ test -n "$prev" && test -n "$head" &&
+ git svn commit-diff -r1 "$prev" "$head" "$svnrepo" &&
+ svn_cmd co "$svnrepo" wc &&
cmp readme wc/readme
- "
+ '
-test_expect_success 'commit-diff to a sub-directory (with git-svn config)' "
- svn import -m 'sub-directory' import $svnrepo/subdir &&
- git-svn init --minimize-url $svnrepo/subdir &&
- git-svn fetch &&
- git-svn commit-diff -r3 '$prev' '$head' &&
- svn cat $svnrepo/subdir/readme > readme.2 &&
+test_expect_success 'commit-diff to a sub-directory (with git svn config)' '
+ svn_cmd import -m "sub-directory" import "$svnrepo"/subdir &&
+ git svn init --minimize-url "$svnrepo"/subdir &&
+ git svn fetch &&
+ git svn commit-diff -r3 "$prev" "$head" &&
+ svn_cmd cat "$svnrepo"/subdir/readme > readme.2 &&
cmp readme readme.2
- "
+ '
test_done
diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh
index f74ab1269e..12f21b700e 100755
--- a/t/t9106-git-svn-commit-diff-clobber.sh
+++ b/t/t9106-git-svn-commit-diff-clobber.sh
@@ -1,93 +1,95 @@
#!/bin/sh
#
# Copyright (c) 2006 Eric Wong
-test_description='git-svn commit-diff clobber'
+test_description='git svn commit-diff clobber'
. ./lib-git-svn.sh
-test_expect_success 'initialize repo' "
+test_expect_success 'initialize repo' '
mkdir import &&
cd import &&
echo initial > file &&
- svn import -m 'initial' . $svnrepo &&
+ svn_cmd import -m "initial" . "$svnrepo" &&
cd .. &&
echo initial > file &&
git update-index --add file &&
- git commit -a -m 'initial'
- "
-test_expect_success 'commit change from svn side' "
- svn co $svnrepo t.svn &&
+ git commit -a -m "initial"
+ '
+test_expect_success 'commit change from svn side' '
+ svn_cmd co "$svnrepo" t.svn &&
cd t.svn &&
echo second line from svn >> file &&
poke file &&
- svn commit -m 'second line from svn' &&
+ svn_cmd commit -m "second line from svn" &&
cd .. &&
rm -rf t.svn
- "
+ '
-test_expect_success 'commit conflicting change from git' "
+test_expect_success 'commit conflicting change from git' '
echo second line from git >> file &&
- git commit -a -m 'second line from git' &&
- ! git-svn commit-diff -r1 HEAD~1 HEAD $svnrepo
-"
+ git commit -a -m "second line from git" &&
+ test_must_fail git svn commit-diff -r1 HEAD~1 HEAD "$svnrepo"
+'
-test_expect_success 'commit complementing change from git' "
+test_expect_success 'commit complementing change from git' '
git reset --hard HEAD~1 &&
echo second line from svn >> file &&
- git commit -a -m 'second line from svn' &&
+ git commit -a -m "second line from svn" &&
echo third line from git >> file &&
- git commit -a -m 'third line from git' &&
- git-svn commit-diff -r2 HEAD~1 HEAD $svnrepo
- "
+ git commit -a -m "third line from git" &&
+ git svn commit-diff -r2 HEAD~1 HEAD "$svnrepo"
+ '
-test_expect_success 'dcommit fails to commit because of conflict' "
- git-svn init $svnrepo &&
- git-svn fetch &&
- git reset --hard refs/remotes/git-svn &&
- svn co $svnrepo t.svn &&
+test_expect_success 'dcommit fails to commit because of conflict' '
+ git svn init "$svnrepo" &&
+ git svn fetch &&
+ git reset --hard refs/${remotes_git_svn} &&
+ svn_cmd co "$svnrepo" t.svn &&
cd t.svn &&
echo fourth line from svn >> file &&
poke file &&
- svn commit -m 'fourth line from svn' &&
+ svn_cmd commit -m "fourth line from svn" &&
cd .. &&
rm -rf t.svn &&
- echo 'fourth line from git' >> file &&
- git commit -a -m 'fourth line from git' &&
- ! git-svn dcommit
- "
+ echo "fourth line from git" >> file &&
+ git commit -a -m "fourth line from git" &&
+ test_must_fail git svn dcommit
+ '
test_expect_success 'dcommit does the svn equivalent of an index merge' "
- git reset --hard refs/remotes/git-svn &&
+ git reset --hard refs/${remotes_git_svn} &&
echo 'index merge' > file2 &&
git update-index --add file2 &&
git commit -a -m 'index merge' &&
echo 'more changes' >> file2 &&
git update-index file2 &&
git commit -a -m 'more changes' &&
- git-svn dcommit
+ git svn dcommit
"
-test_expect_success 'commit another change from svn side' "
- svn co $svnrepo t.svn &&
+test_expect_success 'commit another change from svn side' '
+ svn_cmd co "$svnrepo" t.svn &&
cd t.svn &&
echo third line from svn >> file &&
poke file &&
- svn commit -m 'third line from svn' &&
+ svn_cmd commit -m "third line from svn" &&
cd .. &&
rm -rf t.svn
- "
+ '
-test_expect_success 'multiple dcommit from git-svn will not clobber svn' "
- git reset --hard refs/remotes/git-svn &&
+test_expect_success 'multiple dcommit from git svn will not clobber svn' "
+ git reset --hard refs/${remotes_git_svn} &&
echo new file >> new-file &&
git update-index --add new-file &&
git commit -a -m 'new file' &&
echo clobber > file &&
git commit -a -m 'clobber' &&
- ! git svn dcommit
+ test_must_fail git svn dcommit
"
-test_expect_success 'check that rebase really failed' 'test -d .dotest'
+test_expect_success 'check that rebase really failed' '
+ test -d .git/rebase-apply
+'
test_expect_success 'resolve, continue the rebase and dcommit' "
echo clobber and I really mean it > file &&
diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh
index 0a41d52c7a..901b8e09fb 100755
--- a/t/t9107-git-svn-migrate.sh
+++ b/t/t9107-git-svn-migrate.sh
@@ -1,67 +1,73 @@
#!/bin/sh
# Copyright (c) 2006 Eric Wong
-test_description='git-svn metadata migrations from previous versions'
+test_description='git svn metadata migrations from previous versions'
. ./lib-git-svn.sh
-test_expect_success 'setup old-looking metadata' "
- cp $GIT_DIR/config $GIT_DIR/config-old-git-svn &&
+test_expect_success 'setup old-looking metadata' '
+ cp "$GIT_DIR"/config "$GIT_DIR"/config-old-git-svn &&
mkdir import &&
cd import &&
for i in trunk branches/a branches/b \
tags/0.1 tags/0.2 tags/0.3; do
- mkdir -p \$i && \
- echo hello >> \$i/README || exit 1
+ mkdir -p $i && \
+ echo hello >> $i/README || exit 1
done && \
- svn import -m test . $svnrepo
+ svn_cmd import -m test . "$svnrepo"
cd .. &&
- git-svn init $svnrepo &&
- git-svn fetch &&
- mv $GIT_DIR/svn/* $GIT_DIR/ &&
- mv $GIT_DIR/svn/.metadata $GIT_DIR/ &&
- rmdir $GIT_DIR/svn &&
- git update-ref refs/heads/git-svn-HEAD refs/remotes/git-svn &&
- git update-ref refs/heads/svn-HEAD refs/remotes/git-svn &&
- git update-ref -d refs/remotes/git-svn refs/remotes/git-svn
- "
+ git svn init "$svnrepo" &&
+ git svn fetch &&
+ rm -rf "$GIT_DIR"/svn &&
+ git update-ref refs/heads/git-svn-HEAD refs/${remotes_git_svn} &&
+ git update-ref refs/heads/svn-HEAD refs/${remotes_git_svn} &&
+ git update-ref -d refs/${remotes_git_svn} refs/${remotes_git_svn}
+ '
head=`git rev-parse --verify refs/heads/git-svn-HEAD^0`
test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'"
-test_expect_success 'initialize old-style (v0) git-svn layout' "
- mkdir -p $GIT_DIR/git-svn/info $GIT_DIR/svn/info &&
- echo $svnrepo > $GIT_DIR/git-svn/info/url &&
- echo $svnrepo > $GIT_DIR/svn/info/url &&
- git-svn migrate &&
- ! test -d $GIT_DIR/git-svn &&
- git rev-parse --verify refs/remotes/git-svn^0 &&
+test_expect_success 'initialize old-style (v0) git svn layout' '
+ mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info &&
+ echo "$svnrepo" > "$GIT_DIR"/git-svn/info/url &&
+ echo "$svnrepo" > "$GIT_DIR"/svn/info/url &&
+ git svn migrate &&
+ ! test -d "$GIT_DIR"/git svn &&
+ git rev-parse --verify refs/${remotes_git_svn}^0 &&
git rev-parse --verify refs/remotes/svn^0 &&
- test \`git config --get svn-remote.svn.url\` = '$svnrepo' &&
- test \`git config --get svn-remote.svn.fetch\` = \
- ':refs/remotes/git-svn'
- "
+ test "$(git config --get svn-remote.svn.url)" = "$svnrepo" &&
+ test `git config --get svn-remote.svn.fetch` = \
+ ":refs/${remotes_git_svn}"
+ '
-test_expect_success 'initialize a multi-repository repo' "
- git-svn init $svnrepo -T trunk -t tags -b branches &&
+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 &&
- test -n \"\`git config --get svn-remote.svn.branches \
- '^branches/\*:refs/remotes/\*$'\`\" &&
- test -n \"\`git config --get svn-remote.svn.tags \
- '^tags/\*:refs/remotes/tags/\*$'\`\" &&
+ grep "^trunk:refs/remotes/trunk$" fetch.out &&
+ test -n "`git config --get svn-remote.svn.branches \
+ "^branches/\*:refs/remotes/\*$"`" &&
+ test -n "`git config --get svn-remote.svn.tags \
+ "^tags/\*:refs/remotes/tags/\*$"`" &&
git config --unset svn-remote.svn.branches \
- '^branches/\*:refs/remotes/\*$' &&
+ "^branches/\*:refs/remotes/\*$" &&
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/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" &&
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/$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 "^:refs/${remotes_git_svn}" fetch.out
+ '
# refs should all be different, but the trees should all be the same:
test_expect_success 'multi-fetch works on partial urls + paths' "
- git-svn multi-fetch &&
+ 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;
done &&
@@ -73,43 +79,43 @@ test_expect_success 'multi-fetch works on partial urls + paths' "
refs/remotes/\$j\`\" ||exit 1; done; done
"
-test_expect_success 'migrate --minimize on old inited layout' "
+test_expect_success 'migrate --minimize on old inited layout' '
git config --unset-all svn-remote.svn.fetch &&
git config --unset-all svn-remote.svn.url &&
- rm -rf $GIT_DIR/svn &&
- for i in \`cat fetch.out\`; do
- path=\`expr \$i : '\\([^:]*\\):.*$'\`
- ref=\`expr \$i : '[^:]*:refs/remotes/\\(.*\\)$'\`
- if test -z \"\$ref\"; then continue; fi
- if test -n \"\$path\"; then path=\"/\$path\"; fi
- ( mkdir -p $GIT_DIR/svn/\$ref/info/ &&
- echo $svnrepo\$path > $GIT_DIR/svn/\$ref/info/url ) || exit 1;
+ rm -rf "$GIT_DIR"/svn &&
+ for i in `cat fetch.out`; do
+ path=`expr $i : "\([^:]*\):.*$"`
+ ref=`expr $i : "[^:]*:\(refs/remotes/.*\)$"`
+ if test -z "$ref"; then continue; fi
+ if test -n "$path"; then path="/$path"; fi
+ ( mkdir -p "$GIT_DIR"/svn/$ref/info/ &&
+ echo "$svnrepo"$path > "$GIT_DIR"/svn/$ref/info/url ) || exit 1;
done &&
- git-svn migrate --minimize &&
- test -z \"\`git config -l |grep -v '^svn-remote\.git-svn\.'\`\" &&
+ 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 '^:refs/remotes/git-svn' 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 "^: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/trunk/.rev_db.* 2>/dev/null)\" &&
- expect=\"\$(ls $GIT_DIR/svn/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/trunk/.rev_db.* 2>/dev/null)\" &&
- test ! -e $GIT_DIR/svn/trunk/.rev_db &&
- test -f \$expect
- "
+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 -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 -f "$expect"
+ '
test_done
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index db4344cc84..d732d31302 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Copyright (c) 2007 Eric Wong
-test_description='git-svn globbing refspecs'
+test_description='git svn globbing refspecs'
. ./lib-git-svn.sh
cat > expect.end <<EOF
@@ -10,77 +10,102 @@ start a new branch
initial
EOF
-test_expect_success 'test refspec globbing' "
+test_expect_success 'test refspec globbing' '
mkdir -p trunk/src/a trunk/src/b trunk/doc &&
- echo 'hello world' > trunk/src/a/readme &&
- echo 'goodbye world' > trunk/src/b/readme &&
- svn import -m 'initial' trunk $svnrepo/trunk &&
- svn co $svnrepo tmp &&
- cd tmp &&
+ echo "hello world" > trunk/src/a/readme &&
+ echo "goodbye world" > trunk/src/b/readme &&
+ svn_cmd import -m "initial" trunk "$svnrepo"/trunk &&
+ svn_cmd co "$svnrepo" tmp &&
+ (
+ cd tmp &&
mkdir branches tags &&
- svn add branches tags &&
- svn cp trunk branches/start &&
- svn commit -m 'start a new branch' &&
- svn up &&
- echo 'hi' >> branches/start/src/b/readme &&
+ svn_cmd add branches tags &&
+ svn_cmd cp trunk branches/start &&
+ svn_cmd commit -m "start a new branch" &&
+ svn_cmd up &&
+ echo "hi" >> branches/start/src/b/readme &&
poke branches/start/src/b/readme &&
- echo 'hey' >> branches/start/src/a/readme &&
+ echo "hey" >> branches/start/src/a/readme &&
poke branches/start/src/a/readme &&
- svn commit -m 'hi' &&
- svn up &&
- svn cp branches/start tags/end &&
- echo 'bye' >> tags/end/src/b/readme &&
+ svn_cmd commit -m "hi" &&
+ svn_cmd up &&
+ svn_cmd cp branches/start tags/end &&
+ echo "bye" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
- echo 'aye' >> tags/end/src/a/readme &&
+ echo "aye" >> tags/end/src/a/readme &&
poke tags/end/src/a/readme &&
- svn commit -m 'the end' &&
- echo 'byebye' >> tags/end/src/b/readme &&
+ svn_cmd commit -m "the end" &&
+ echo "byebye" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
- svn commit -m 'nothing to see here'
- cd .. &&
- git config --add svn-remote.svn.url $svnrepo &&
+ svn_cmd commit -m "nothing to see here"
+ ) &&
+ git config --add svn-remote.svn.url "$svnrepo" &&
git config --add svn-remote.svn.fetch \
- 'trunk/src/a:refs/remotes/trunk' &&
+ "trunk/src/a:refs/remotes/trunk" &&
git config --add svn-remote.svn.branches \
- 'branches/*/src/a:refs/remotes/branches/*' &&
+ "branches/*/src/a:refs/remotes/branches/*" &&
git config --add svn-remote.svn.tags\
- 'tags/*/src/a:refs/remotes/tags/*' &&
- git-svn multi-fetch &&
+ "tags/*/src/a:refs/remotes/tags/*" &&
+ git svn multi-fetch &&
git log --pretty=oneline refs/remotes/tags/end | \
- sed -e 's/^.\{41\}//' > output.end &&
- cmp expect.end output.end &&
- test \"\`git rev-parse refs/remotes/tags/end~1\`\" = \
- \"\`git rev-parse refs/remotes/branches/start\`\" &&
- test \"\`git rev-parse refs/remotes/branches/start~2\`\" = \
- \"\`git rev-parse refs/remotes/trunk\`\"
- "
+ sed -e "s/^.\{41\}//" > output.end &&
+ test_cmp expect.end output.end &&
+ test "`git rev-parse refs/remotes/tags/end~1`" = \
+ "`git rev-parse refs/remotes/branches/start`" &&
+ test "`git rev-parse refs/remotes/branches/start~2`" = \
+ "`git rev-parse refs/remotes/trunk`" &&
+ test_must_fail git rev-parse refs/remotes/tags/end@3
+ '
echo try to try > expect.two
echo nothing to see here >> expect.two
cat expect.end >> expect.two
-test_expect_success 'test left-hand-side only globbing' "
- git config --add svn-remote.two.url $svnrepo &&
+test_expect_success 'test left-hand-side only globbing' '
+ git config --add svn-remote.two.url "$svnrepo" &&
git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk &&
git config --add svn-remote.two.branches \
- 'branches/*:refs/remotes/two/branches/*' &&
+ "branches/*:refs/remotes/two/branches/*" &&
git config --add svn-remote.two.tags \
- 'tags/*:refs/remotes/two/tags/*' &&
- cd tmp &&
- echo 'try try' >> tags/end/src/b/readme &&
+ "tags/*:refs/remotes/two/tags/*" &&
+ (
+ cd tmp &&
+ echo "try try" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
- svn commit -m 'try to try'
- cd .. &&
- git-svn fetch two &&
- test \`git rev-list refs/remotes/two/tags/end | wc -l\` -eq 6 &&
- test \`git rev-list refs/remotes/two/branches/start | wc -l\` -eq 3 &&
- test \`git rev-parse refs/remotes/two/branches/start~2\` = \
- \`git rev-parse refs/remotes/two/trunk\` &&
- test \`git rev-parse refs/remotes/two/tags/end~3\` = \
- \`git rev-parse refs/remotes/two/branches/start\` &&
+ svn_cmd commit -m "try to try"
+ ) &&
+ git svn fetch two &&
+ test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
+ test `git rev-list refs/remotes/two/branches/start | wc -l` -eq 3 &&
+ test `git rev-parse refs/remotes/two/branches/start~2` = \
+ `git rev-parse refs/remotes/two/trunk` &&
+ test `git rev-parse refs/remotes/two/tags/end~3` = \
+ `git rev-parse refs/remotes/two/branches/start` &&
git log --pretty=oneline refs/remotes/two/tags/end | \
- sed -e 's/^.\{41\}//' > output.two &&
- cmp expect.two output.two
- "
+ sed -e "s/^.\{41\}//" > output.two &&
+ test_cmp expect.two output.two
+ '
+
+echo "Only one set of wildcard directories" \
+ "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multi-globs' '
+ git config --add svn-remote.three.url "$svnrepo" &&
+ git config --add svn-remote.three.fetch \
+ trunk:refs/remotes/three/trunk &&
+ git config --add svn-remote.three.branches \
+ "branches/*/t/*:refs/remotes/three/branches/*" &&
+ git config --add svn-remote.three.tags \
+ "tags/*/*:refs/remotes/three/tags/*" &&
+ (
+ cd tmp &&
+ echo "try try" >> tags/end/src/b/readme &&
+ poke tags/end/src/b/readme &&
+ svn_cmd commit -m "try to try"
+ ) &&
+ test_must_fail git svn fetch three 2> stderr.three &&
+ test_cmp expect.three stderr.three
+ '
test_done
diff --git a/t/t9109-git-svn-multi-glob.sh b/t/t9109-git-svn-multi-glob.sh
new file mode 100755
index 0000000000..c318f9f946
--- /dev/null
+++ b/t/t9109-git-svn-multi-glob.sh
@@ -0,0 +1,160 @@
+#!/bin/sh
+# Copyright (c) 2007 Eric Wong
+test_description='git svn globbing refspecs'
+. ./lib-git-svn.sh
+
+cat > expect.end <<EOF
+the end
+hi
+start a new branch
+initial
+EOF
+
+test_expect_success 'test refspec globbing' '
+ mkdir -p trunk/src/a trunk/src/b trunk/doc &&
+ echo "hello world" > trunk/src/a/readme &&
+ echo "goodbye world" > trunk/src/b/readme &&
+ svn_cmd import -m "initial" trunk "$svnrepo"/trunk &&
+ svn_cmd co "$svnrepo" tmp &&
+ (
+ cd tmp &&
+ mkdir branches branches/v1 tags &&
+ svn_cmd add branches tags &&
+ svn_cmd cp trunk branches/v1/start &&
+ svn_cmd commit -m "start a new branch" &&
+ svn_cmd up &&
+ echo "hi" >> branches/v1/start/src/b/readme &&
+ poke branches/v1/start/src/b/readme &&
+ echo "hey" >> branches/v1/start/src/a/readme &&
+ poke branches/v1/start/src/a/readme &&
+ svn_cmd commit -m "hi" &&
+ svn_cmd up &&
+ svn_cmd cp branches/v1/start tags/end &&
+ echo "bye" >> tags/end/src/b/readme &&
+ poke tags/end/src/b/readme &&
+ echo "aye" >> tags/end/src/a/readme &&
+ poke tags/end/src/a/readme &&
+ svn_cmd commit -m "the end" &&
+ echo "byebye" >> tags/end/src/b/readme &&
+ poke tags/end/src/b/readme &&
+ svn_cmd commit -m "nothing to see here"
+ ) &&
+ git config --add svn-remote.svn.url "$svnrepo" &&
+ git config --add svn-remote.svn.fetch \
+ "trunk/src/a:refs/remotes/trunk" &&
+ git config --add svn-remote.svn.branches \
+ "branches/*/*/src/a:refs/remotes/branches/*/*" &&
+ git config --add svn-remote.svn.tags\
+ "tags/*/src/a:refs/remotes/tags/*" &&
+ git svn multi-fetch &&
+ git log --pretty=oneline refs/remotes/tags/end | \
+ sed -e "s/^.\{41\}//" > output.end &&
+ test_cmp expect.end output.end &&
+ test "`git rev-parse refs/remotes/tags/end~1`" = \
+ "`git rev-parse refs/remotes/branches/v1/start`" &&
+ test "`git rev-parse refs/remotes/branches/v1/start~2`" = \
+ "`git rev-parse refs/remotes/trunk`" &&
+ test_must_fail git rev-parse refs/remotes/tags/end@3
+ '
+
+echo try to try > expect.two
+echo nothing to see here >> expect.two
+cat expect.end >> expect.two
+
+test_expect_success 'test left-hand-side only globbing' '
+ git config --add svn-remote.two.url "$svnrepo" &&
+ git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk &&
+ git config --add svn-remote.two.branches \
+ "branches/*/*:refs/remotes/two/branches/*/*" &&
+ git config --add svn-remote.two.tags \
+ "tags/*:refs/remotes/two/tags/*" &&
+ (
+ cd tmp &&
+ echo "try try" >> tags/end/src/b/readme &&
+ poke tags/end/src/b/readme &&
+ svn_cmd commit -m "try to try"
+ ) &&
+ git svn fetch two &&
+ test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
+ test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 &&
+ test `git rev-parse refs/remotes/two/branches/v1/start~2` = \
+ `git rev-parse refs/remotes/two/trunk` &&
+ test `git rev-parse refs/remotes/two/tags/end~3` = \
+ `git rev-parse refs/remotes/two/branches/v1/start` &&
+ git log --pretty=oneline refs/remotes/two/tags/end | \
+ sed -e "s/^.\{41\}//" > output.two &&
+ test_cmp expect.two output.two
+ '
+cat > expect.four <<EOF
+adios
+adding more
+Changed 2 in v2/start
+Another versioned branch
+initial
+EOF
+
+test_expect_success 'test another branch' '
+ (
+ cd tmp &&
+ mkdir branches/v2 &&
+ svn_cmd add branches/v2 &&
+ svn_cmd cp trunk branches/v2/start &&
+ svn_cmd commit -m "Another versioned branch" &&
+ svn_cmd up &&
+ echo "hello" >> branches/v2/start/src/b/readme &&
+ poke branches/v2/start/src/b/readme &&
+ echo "howdy" >> branches/v2/start/src/a/readme &&
+ poke branches/v2/start/src/a/readme &&
+ svn_cmd commit -m "Changed 2 in v2/start" &&
+ svn_cmd up &&
+ svn_cmd cp branches/v2/start tags/next &&
+ echo "bye" >> tags/next/src/b/readme &&
+ poke tags/next/src/b/readme &&
+ echo "aye" >> tags/next/src/a/readme &&
+ poke tags/next/src/a/readme &&
+ svn_cmd commit -m "adding more" &&
+ echo "byebye" >> tags/next/src/b/readme &&
+ poke tags/next/src/b/readme &&
+ svn_cmd commit -m "adios"
+ ) &&
+ git config --add svn-remote.four.url "$svnrepo" &&
+ git config --add svn-remote.four.fetch trunk:refs/remotes/four/trunk &&
+ git config --add svn-remote.four.branches \
+ "branches/*/*:refs/remotes/four/branches/*/*" &&
+ git config --add svn-remote.four.tags \
+ "tags/*:refs/remotes/four/tags/*" &&
+ git svn fetch four &&
+ test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 &&
+ test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 &&
+ test `git rev-parse refs/remotes/four/branches/v2/start~2` = \
+ `git rev-parse refs/remotes/four/trunk` &&
+ test `git rev-parse refs/remotes/four/tags/next~2` = \
+ `git rev-parse refs/remotes/four/branches/v2/start` &&
+ git log --pretty=oneline refs/remotes/four/tags/next | \
+ sed -e "s/^.\{41\}//" > output.four &&
+ test_cmp expect.four output.four
+ '
+
+echo "Only one set of wildcard directories" \
+ "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multiple globs' '
+ git config --add svn-remote.three.url "$svnrepo" &&
+ git config --add svn-remote.three.fetch \
+ trunk:refs/remotes/three/trunk &&
+ git config --add svn-remote.three.branches \
+ "branches/*/t/*:refs/remotes/three/branches/*/*" &&
+ git config --add svn-remote.three.tags \
+ "tags/*:refs/remotes/three/tags/*" &&
+ (
+ cd tmp &&
+ echo "try try" >> tags/end/src/b/readme &&
+ poke tags/end/src/b/readme &&
+ svn_cmd commit -m "try to try"
+ ) &&
+ test_must_fail git svn fetch three 2> stderr.three &&
+ test_cmp expect.three stderr.three
+ '
+
+test_done
diff --git a/t/t9110-git-svn-use-svm-props.sh b/t/t9110-git-svn-use-svm-props.sh
index 6235af4db8..a06e4c5b8e 100755
--- a/t/t9110-git-svn-use-svm-props.sh
+++ b/t/t9110-git-svn-use-svm-props.sh
@@ -3,50 +3,59 @@
# Copyright (c) 2007 Eric Wong
#
-test_description='git-svn useSvmProps test'
+test_description='git svn useSvmProps test'
. ./lib-git-svn.sh
-test_expect_success 'load svm repo' "
- svnadmin load -q $rawsvnrepo < ../t9110/svm.dump &&
- git-svn init --minimize-url -R arr -i bar $svnrepo/mirror/arr &&
- git-svn init --minimize-url -R argh -i dir $svnrepo/mirror/argh &&
- git-svn init --minimize-url -R argh -i e \
- $svnrepo/mirror/argh/a/b/c/d/e &&
+test_expect_success 'load svm repo' '
+ svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9110/svm.dump &&
+ git svn init --minimize-url -R arr -i bar "$svnrepo"/mirror/arr &&
+ git svn init --minimize-url -R argh -i dir "$svnrepo"/mirror/argh &&
+ git svn init --minimize-url -R argh -i e \
+ "$svnrepo"/mirror/argh/a/b/c/d/e &&
git config svn.useSvmProps true &&
- git-svn fetch --all
- "
+ git svn fetch --all
+ '
uuid=161ce429-a9dd-4828-af4a-52023f968c89
bar_url=http://mayonaise/svnrepo/bar
test_expect_success 'verify metadata for /bar' "
git cat-file commit refs/remotes/bar | \
- grep '^git-svn-id: $bar_url@12 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@12 $uuid$' &&
git cat-file commit refs/remotes/bar~1 | \
- grep '^git-svn-id: $bar_url@11 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@11 $uuid$' &&
git cat-file commit refs/remotes/bar~2 | \
- grep '^git-svn-id: $bar_url@10 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@10 $uuid$' &&
git cat-file commit refs/remotes/bar~3 | \
- grep '^git-svn-id: $bar_url@9 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@9 $uuid$' &&
git cat-file commit refs/remotes/bar~4 | \
- grep '^git-svn-id: $bar_url@6 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@6 $uuid$' &&
git cat-file commit refs/remotes/bar~5 | \
- grep '^git-svn-id: $bar_url@1 $uuid$'
+ grep '^${git_svn_id}: $bar_url@1 $uuid$'
"
e_url=http://mayonaise/svnrepo/dir/a/b/c/d/e
test_expect_success 'verify metadata for /dir/a/b/c/d/e' "
git cat-file commit refs/remotes/e | \
- grep '^git-svn-id: $e_url@1 $uuid$'
+ grep '^${git_svn_id}: $e_url@1 $uuid$'
"
dir_url=http://mayonaise/svnrepo/dir
test_expect_success 'verify metadata for /dir' "
git cat-file commit refs/remotes/dir | \
- grep '^git-svn-id: $dir_url@2 $uuid$' &&
+ grep '^${git_svn_id}: $dir_url@2 $uuid$' &&
git cat-file commit refs/remotes/dir~1 | \
- grep '^git-svn-id: $dir_url@1 $uuid$'
+ grep '^${git_svn_id}: $dir_url@1 $uuid$'
+ "
+
+test_expect_success 'find commit based on SVN revision number' "
+ git svn find-rev r12 |
+ grep `git rev-parse HEAD`
+ "
+
+test_expect_success 'empty rebase' "
+ git svn rebase
"
test_done
diff --git a/t/t9111-git-svn-use-svnsync-props.sh b/t/t9111-git-svn-use-svnsync-props.sh
index ec7dedd48b..bd081c2ec3 100755
--- a/t/t9111-git-svn-use-svnsync-props.sh
+++ b/t/t9111-git-svn-use-svnsync-props.sh
@@ -3,49 +3,49 @@
# Copyright (c) 2007 Eric Wong
#
-test_description='git-svn useSvnsyncProps test'
+test_description='git svn useSvnsyncProps test'
. ./lib-git-svn.sh
-test_expect_success 'load svnsync repo' "
- svnadmin load -q $rawsvnrepo < ../t9111/svnsync.dump &&
- git-svn init --minimize-url -R arr -i bar $svnrepo/bar &&
- git-svn init --minimize-url -R argh -i dir $svnrepo/dir &&
- git-svn init --minimize-url -R argh -i e $svnrepo/dir/a/b/c/d/e &&
+test_expect_success 'load svnsync repo' '
+ svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9111/svnsync.dump &&
+ git svn init --minimize-url -R arr -i bar "$svnrepo"/bar &&
+ git svn init --minimize-url -R argh -i dir "$svnrepo"/dir &&
+ git svn init --minimize-url -R argh -i e "$svnrepo"/dir/a/b/c/d/e &&
git config svn.useSvnsyncProps true &&
- git-svn fetch --all
- "
+ git svn fetch --all
+ '
uuid=161ce429-a9dd-4828-af4a-52023f968c89
bar_url=http://mayonaise/svnrepo/bar
test_expect_success 'verify metadata for /bar' "
git cat-file commit refs/remotes/bar | \
- grep '^git-svn-id: $bar_url@12 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@12 $uuid$' &&
git cat-file commit refs/remotes/bar~1 | \
- grep '^git-svn-id: $bar_url@11 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@11 $uuid$' &&
git cat-file commit refs/remotes/bar~2 | \
- grep '^git-svn-id: $bar_url@10 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@10 $uuid$' &&
git cat-file commit refs/remotes/bar~3 | \
- grep '^git-svn-id: $bar_url@9 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@9 $uuid$' &&
git cat-file commit refs/remotes/bar~4 | \
- grep '^git-svn-id: $bar_url@6 $uuid$' &&
+ grep '^${git_svn_id}: $bar_url@6 $uuid$' &&
git cat-file commit refs/remotes/bar~5 | \
- grep '^git-svn-id: $bar_url@1 $uuid$'
+ grep '^${git_svn_id}: $bar_url@1 $uuid$'
"
e_url=http://mayonaise/svnrepo/dir/a/b/c/d/e
test_expect_success 'verify metadata for /dir/a/b/c/d/e' "
git cat-file commit refs/remotes/e | \
- grep '^git-svn-id: $e_url@1 $uuid$'
+ grep '^${git_svn_id}: $e_url@1 $uuid$'
"
dir_url=http://mayonaise/svnrepo/dir
test_expect_success 'verify metadata for /dir' "
git cat-file commit refs/remotes/dir | \
- grep '^git-svn-id: $dir_url@2 $uuid$' &&
+ grep '^${git_svn_id}: $dir_url@2 $uuid$' &&
git cat-file commit refs/remotes/dir~1 | \
- grep '^git-svn-id: $dir_url@1 $uuid$'
+ grep '^${git_svn_id}: $dir_url@1 $uuid$'
"
test_done
diff --git a/t/t9112-git-svn-md5less-file.sh b/t/t9112-git-svn-md5less-file.sh
index 646a5f0cdb..a61d6716d2 100755
--- a/t/t9112-git-svn-md5less-file.sh
+++ b/t/t9112-git-svn-md5less-file.sh
@@ -40,8 +40,8 @@ PROPS-END
EOF
-test_expect_success 'load svn dumpfile' "svnadmin load $rawsvnrepo < dumpfile.svn"
+test_expect_success 'load svn dumpfile' 'svnadmin load "$rawsvnrepo" < dumpfile.svn'
-test_expect_success 'initialize git-svn' "git-svn init $svnrepo"
-test_expect_success 'fetch revisions from svn' 'git-svn fetch'
+test_expect_success 'initialize git svn' 'git svn init "$svnrepo"'
+test_expect_success 'fetch revisions from svn' 'git svn fetch'
test_done
diff --git a/t/t9113-git-svn-dcommit-new-file.sh b/t/t9113-git-svn-dcommit-new-file.sh
index 9ef0db9044..e8479cec7a 100755
--- a/t/t9113-git-svn-dcommit-new-file.sh
+++ b/t/t9113-git-svn-dcommit-new-file.sh
@@ -7,26 +7,21 @@
# I don't like the idea of taking a port and possibly leaving a
# daemon running on a users system if the test fails.
# Not all git users will need to interact with SVN.
-test -z "$SVNSERVE_PORT" && exit 0
-test_description='git-svn dcommit new files over svn:// test'
+test_description='git svn dcommit new files over svn:// test'
. ./lib-git-svn.sh
-start_svnserve () {
- svnserve --listen-port $SVNSERVE_PORT \
- --root $rawsvnrepo \
- --listen-once \
- --listen-host 127.0.0.1 &
-}
+require_svnserve
-test_expect_success 'start tracking an empty repo' "
- svn mkdir -m 'empty dir' $svnrepo/empty-dir &&
- echo anon-access = write >> $rawsvnrepo/conf/svnserve.conf &&
+test_expect_success 'start tracking an empty repo' '
+ svn_cmd mkdir -m "empty dir" "$svnrepo"/empty-dir &&
+ echo "[general]" > "$rawsvnrepo"/conf/svnserve.conf &&
+ echo anon-access = write >> "$rawsvnrepo"/conf/svnserve.conf &&
start_svnserve &&
git svn init svn://127.0.0.1:$SVNSERVE_PORT &&
git svn fetch
- "
+ '
test_expect_success 'create files in new directory with dcommit' "
mkdir git-new-dir &&
diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh
index 225060b88b..84f7c9b4bb 100755
--- a/t/t9114-git-svn-dcommit-merge.sh
+++ b/t/t9114-git-svn-dcommit-merge.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2007 Eric Wong
# Based on a script by Joakim Tjernlund <joakim.tjernlund@transmode.se>
-test_description='git-svn dcommit handles merges'
+test_description='git svn dcommit handles merges'
. ./lib-git-svn.sh
@@ -34,35 +34,35 @@ cat << EOF
EOF
}
-test_expect_success 'setup svn repository' "
- svn co $svnrepo mysvnwork &&
+test_expect_success 'setup svn repository' '
+ svn_cmd co "$svnrepo" mysvnwork &&
mkdir -p mysvnwork/trunk &&
cd mysvnwork &&
big_text_block >> trunk/README &&
- svn add trunk &&
- svn ci -m 'first commit' trunk &&
+ svn_cmd add trunk &&
+ svn_cmd ci -m "first commit" trunk &&
cd ..
- "
+ '
-test_expect_success 'setup git mirror and merge' "
- git svn init $svnrepo -t tags -T trunk -b branches &&
+test_expect_success 'setup git mirror and merge' '
+ git svn init "$svnrepo" -t tags -T trunk -b branches &&
git svn fetch &&
git checkout --track -b svn remotes/trunk &&
git checkout -b merge &&
echo new file > new_file &&
git add new_file &&
- git commit -a -m 'New file' &&
+ git commit -a -m "New file" &&
echo hello >> README &&
- git commit -a -m 'hello' &&
+ git commit -a -m "hello" &&
echo add some stuff >> new_file &&
- git commit -a -m 'add some stuff' &&
+ git commit -a -m "add some stuff" &&
git checkout svn &&
mv -f README tmp &&
echo friend > README &&
cat tmp >> README &&
- git commit -a -m 'friend' &&
+ git commit -a -m "friend" &&
git pull . merge
- "
+ '
test_debug 'gitk --all & sleep 1'
diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh
index 182299cbb5..767799e7a7 100755
--- a/t/t9115-git-svn-dcommit-funky-renames.sh
+++ b/t/t9115-git-svn-dcommit-funky-renames.sh
@@ -3,23 +3,23 @@
# Copyright (c) 2007 Eric Wong
-test_description='git-svn dcommit can commit renames of files with ugly names'
+test_description='git svn dcommit can commit renames of files with ugly names'
. ./lib-git-svn.sh
-test_expect_success 'load repository with strange names' "
- svnadmin load -q $rawsvnrepo < ../t9115/funky-names.dump &&
- start_httpd
- "
+test_expect_success 'load repository with strange names' '
+ svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9115/funky-names.dump &&
+ start_httpd gtk+
+ '
-test_expect_success 'init and fetch repository' "
- git svn init $svnrepo &&
+test_expect_success 'init and fetch repository' '
+ git svn init "$svnrepo" &&
git svn fetch &&
git reset --hard git-svn
- "
+ '
test_expect_success 'create file in existing ugly and empty dir' '
- mkdir "#{bad_directory_name}" &&
+ mkdir -p "#{bad_directory_name}" &&
echo hi > "#{bad_directory_name}/ foo" &&
git update-index --add "#{bad_directory_name}/ foo" &&
git commit -m "new file in ugly parent" &&
@@ -37,7 +37,7 @@ test_expect_success 'rename pretty file' '
git update-index --add pretty &&
git commit -m "pretty :x" &&
git svn dcommit &&
- mkdir regular_dir_name &&
+ mkdir -p regular_dir_name &&
git mv pretty regular_dir_name/pretty &&
git commit -m "moved pretty file" &&
git svn dcommit
@@ -49,6 +49,39 @@ test_expect_success 'rename pretty file into ugly one' '
git svn dcommit
'
+test_expect_success 'add a file with plus signs' '
+ echo .. > +_+ &&
+ git update-index --add +_+ &&
+ git commit -m plus &&
+ mkdir gtk+ &&
+ git mv +_+ gtk+/_+_ &&
+ git commit -m plus_dir &&
+ git svn dcommit
+ '
+
+test_expect_success 'clone the repository to test rebase' '
+ git svn clone "$svnrepo" test-rebase &&
+ cd test-rebase &&
+ echo test-rebase > test-rebase &&
+ git add test-rebase &&
+ git commit -m test-rebase &&
+ cd ..
+ '
+
+test_expect_success 'make a commit to test rebase' '
+ echo test-rebase-main > test-rebase-main &&
+ git add test-rebase-main &&
+ git commit -m test-rebase-main &&
+ git svn dcommit
+ '
+
+test_expect_success 'git svn rebase works inside a fresh-cloned repository' '
+ cd test-rebase &&
+ git svn rebase &&
+ test -e test-rebase-main &&
+ test -e test-rebase
+ '
+
stop_httpd
test_done
diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh
index e1e8bdf0e3..0374a7476b 100755
--- a/t/t9116-git-svn-log.sh
+++ b/t/t9116-git-svn-log.sh
@@ -3,21 +3,21 @@
# Copyright (c) 2007 Eric Wong
#
-test_description='git-svn log tests'
+test_description='git svn log tests'
. ./lib-git-svn.sh
-test_expect_success 'setup repository and import' "
+test_expect_success 'setup repository and import' '
mkdir import &&
cd import &&
for i in trunk branches/a branches/b \
tags/0.1 tags/0.2 tags/0.3; do
- mkdir -p \$i && \
- echo hello >> \$i/README || exit 1
+ mkdir -p $i && \
+ echo hello >> $i/README || exit 1
done && \
- svn import -m test . $svnrepo
+ svn_cmd import -m test . "$svnrepo"
cd .. &&
- git-svn init $svnrepo -T trunk -b branches -t tags &&
- git-svn fetch &&
+ git svn init "$svnrepo" -T trunk -b branches -t tags &&
+ git svn fetch &&
git reset --hard trunk &&
echo bye >> README &&
git commit -a -m bye &&
@@ -37,7 +37,7 @@ test_expect_success 'setup repository and import' "
echo try >> README &&
git commit -a -m try &&
git svn dcommit
- "
+ '
test_expect_success 'run log' "
git reset --hard a &&
diff --git a/t/t9117-git-svn-init-clone.sh b/t/t9117-git-svn-init-clone.sh
index d482b407f2..b7ef9e2589 100755
--- a/t/t9117-git-svn-init-clone.sh
+++ b/t/t9117-git-svn-init-clone.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2007 Eric Wong
#
-test_description='git-svn init/clone tests'
+test_description='git svn init/clone tests'
. ./lib-git-svn.sh
@@ -13,43 +13,43 @@ rm -r .git
mkdir tmp
cd tmp
-test_expect_success 'setup svnrepo' "
+test_expect_success 'setup svnrepo' '
mkdir project project/trunk project/branches project/tags &&
echo foo > project/trunk/foo &&
- svn import -m '$test_description' project $svnrepo/project &&
+ svn_cmd import -m "$test_description" project "$svnrepo"/project &&
rm -rf project
- "
+ '
-test_expect_success 'basic clone' "
+test_expect_success 'basic clone' '
test ! -d trunk &&
- git svn clone $svnrepo/project/trunk &&
+ git svn clone "$svnrepo"/project/trunk &&
test -d trunk/.git/svn &&
test -e trunk/foo &&
rm -rf trunk
- "
+ '
-test_expect_success 'clone to target directory' "
+test_expect_success 'clone to target directory' '
test ! -d target &&
- git svn clone $svnrepo/project/trunk target &&
+ git svn clone "$svnrepo"/project/trunk target &&
test -d target/.git/svn &&
test -e target/foo &&
rm -rf target
- "
+ '
-test_expect_success 'clone with --stdlayout' "
+test_expect_success 'clone with --stdlayout' '
test ! -d project &&
- git svn clone -s $svnrepo/project &&
+ git svn clone -s "$svnrepo"/project &&
test -d project/.git/svn &&
test -e project/foo &&
rm -rf project
- "
+ '
-test_expect_success 'clone to target directory with --stdlayout' "
+test_expect_success 'clone to target directory with --stdlayout' '
test ! -d target &&
- git svn clone -s $svnrepo/project target &&
+ git svn clone -s "$svnrepo"/project target &&
test -d target/.git/svn &&
test -e target/foo &&
rm -rf target
- "
+ '
test_done
diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
index 640bb066f3..ac52bff0ef 100755
--- a/t/t9118-git-svn-funky-branch-names.sh
+++ b/t/t9118-git-svn-funky-branch-names.sh
@@ -3,28 +3,35 @@
# Copyright (c) 2007 Eric Wong
#
-test_description='git-svn funky branch names'
+test_description='git svn funky branch names'
. ./lib-git-svn.sh
-test_expect_success 'setup svnrepo' "
+# Abo-Uebernahme (Bug #994)
+scary_uri='Abo-Uebernahme%20%28Bug%20%23994%29'
+scary_ref='Abo-Uebernahme%20(Bug%20#994)'
+
+test_expect_success 'setup svnrepo' '
mkdir project project/trunk project/branches project/tags &&
echo foo > project/trunk/foo &&
- svn import -m '$test_description' project \"$svnrepo/pr ject\" &&
+ svn_cmd import -m "$test_description" project "$svnrepo/pr ject" &&
rm -rf project &&
- svn cp -m 'fun' \"$svnrepo/pr ject/trunk\" \
- \"$svnrepo/pr ject/branches/fun plugin\" &&
- svn cp -m 'more fun!' \"$svnrepo/pr ject/branches/fun plugin\" \
- \"$svnrepo/pr ject/branches/more fun plugin!\" &&
+ svn_cmd cp -m "fun" "$svnrepo/pr ject/trunk" \
+ "$svnrepo/pr ject/branches/fun plugin" &&
+ svn_cmd cp -m "more fun!" "$svnrepo/pr ject/branches/fun plugin" \
+ "$svnrepo/pr ject/branches/more fun plugin!" &&
+ svn_cmd cp -m "scary" "$svnrepo/pr ject/branches/fun plugin" \
+ "$svnrepo/pr ject/branches/$scary_uri" &&
start_httpd
- "
+ '
-test_expect_success 'test clone with funky branch names' "
- git svn clone -s \"$svnrepo/pr ject\" project &&
+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/fun%20plugin" &&
+ git rev-parse "refs/remotes/more%20fun%20plugin!" &&
+ git rev-parse "refs/remotes/$scary_ref" &&
cd ..
- "
+ '
test_expect_success 'test dcommit to funky branch' "
cd project &&
@@ -35,6 +42,15 @@ test_expect_success 'test dcommit to funky branch' "
cd ..
"
+test_expect_success 'test dcommit to scary branch' '
+ cd project &&
+ git reset --hard "refs/remotes/$scary_ref" &&
+ echo urls are scary >> foo &&
+ git commit -m "eep" -- foo &&
+ git svn dcommit &&
+ cd ..
+ '
+
stop_httpd
test_done
diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh
index cc61911593..95741cbbac 100755
--- a/t/t9119-git-svn-info.sh
+++ b/t/t9119-git-svn-info.sh
@@ -2,23 +2,41 @@
#
# Copyright (c) 2007 David D. Kilzer
-test_description='git-svn info'
+test_description='git svn info'
. ./lib-git-svn.sh
-say 'skipping svn-info test (has a race undiagnosed yet)'
-test_done
+
+# Tested with: svn, version 1.4.4 (r25188)
+v=`svn_cmd --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p'`
+case $v in
+1.[45].*)
+ ;;
+*)
+ say "skipping svn-info test (SVN version: $v not supported)"
+ test_done
+ ;;
+esac
ptouch() {
perl -w -e '
use strict;
+ use POSIX qw(mktime);
die "ptouch requires exactly 2 arguments" if @ARGV != 2;
- die "$ARGV[0] does not exist" if ! -e $ARGV[0];
- my @s = stat $ARGV[0];
- utime $s[8], $s[9], $ARGV[1];
- ' "$1" "$2"
+ my $text_last_updated = shift @ARGV;
+ my $git_file = shift @ARGV;
+ die "\"$git_file\" does not exist" if ! -e $git_file;
+ if ($text_last_updated
+ =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) {
+ my $mtime = mktime($6, $5, $4, $3, $2 - 1, $1 - 1900);
+ my $atime = $mtime;
+ utime $atime, $mtime, $git_file;
+ }
+ ' "`svn_cmd info $2 | grep '^Text Last Updated:'`" "$1"
}
-test_expect_success 'setup repository and import' "
+quoted_svnrepo="$(echo $svnrepo | sed 's/ /%20/')"
+
+test_expect_success 'setup repository and import' '
mkdir info &&
cd info &&
echo FIRST > A &&
@@ -27,82 +45,94 @@ test_expect_success 'setup repository and import' "
mkdir directory &&
touch directory/.placeholder &&
ln -s directory symlink-directory &&
- svn import -m 'initial' . $svnrepo &&
+ svn_cmd import -m "initial" . "$svnrepo" &&
+ cd .. &&
+ svn_cmd co "$svnrepo" svnwc &&
+ cd svnwc &&
+ echo foo > foo &&
+ svn_cmd add foo &&
+ svn_cmd commit -m "change outside directory" &&
+ svn_cmd update &&
cd .. &&
mkdir gitwc &&
cd gitwc &&
- git-svn init $svnrepo &&
- git-svn fetch &&
+ git svn init "$svnrepo" &&
+ git svn fetch &&
cd .. &&
- svn co $svnrepo svnwc &&
- ptouch svnwc/file gitwc/file &&
- ptouch svnwc/directory gitwc/directory &&
- ptouch svnwc/symlink-file gitwc/symlink-file &&
- ptouch svnwc/symlink-directory gitwc/symlink-directory
- "
+ ptouch gitwc/file svnwc/file &&
+ ptouch gitwc/directory svnwc/directory &&
+ ptouch gitwc/symlink-file svnwc/symlink-file &&
+ ptouch gitwc/symlink-directory svnwc/symlink-directory
+ '
test_expect_success 'info' "
(cd svnwc; svn info) > expected.info &&
- (cd gitwc; git-svn info) > actual.info &&
- git-diff expected.info actual.info
+ (cd gitwc; git svn info) > actual.info &&
+ test_cmp expected.info actual.info
"
test_expect_success 'info --url' '
- test $(cd gitwc; git-svn info --url) = $svnrepo
+ test "$(cd gitwc; git svn info --url)" = "$quoted_svnrepo"
'
test_expect_success 'info .' "
(cd svnwc; svn info .) > expected.info-dot &&
- (cd gitwc; git-svn info .) > actual.info-dot &&
- git-diff expected.info-dot actual.info-dot
+ (cd gitwc; git svn info .) > actual.info-dot &&
+ test_cmp expected.info-dot actual.info-dot
"
test_expect_success 'info --url .' '
- test $(cd gitwc; git-svn info --url .) = $svnrepo
+ test "$(cd gitwc; git svn info --url .)" = "$quoted_svnrepo"
'
test_expect_success 'info file' "
(cd svnwc; svn info file) > expected.info-file &&
- (cd gitwc; git-svn info file) > actual.info-file &&
- git-diff expected.info-file actual.info-file
+ (cd gitwc; git svn info file) > actual.info-file &&
+ test_cmp expected.info-file actual.info-file
"
test_expect_success 'info --url file' '
- test $(cd gitwc; git-svn info --url file) = "$svnrepo/file"
+ test "$(cd gitwc; git svn info --url file)" = "$quoted_svnrepo/file"
'
test_expect_success 'info directory' "
(cd svnwc; svn info directory) > expected.info-directory &&
- (cd gitwc; git-svn info directory) > actual.info-directory &&
- git-diff expected.info-directory actual.info-directory
+ (cd gitwc; git svn info directory) > actual.info-directory &&
+ test_cmp expected.info-directory actual.info-directory
+ "
+
+test_expect_success 'info inside directory' "
+ (cd svnwc/directory; svn info) > expected.info-inside-directory &&
+ (cd gitwc/directory; git svn info) > actual.info-inside-directory &&
+ test_cmp expected.info-inside-directory actual.info-inside-directory
"
test_expect_success 'info --url directory' '
- test $(cd gitwc; git-svn info --url directory) = "$svnrepo/directory"
+ test "$(cd gitwc; git svn info --url directory)" = "$quoted_svnrepo/directory"
'
test_expect_success 'info symlink-file' "
(cd svnwc; svn info symlink-file) > expected.info-symlink-file &&
- (cd gitwc; git-svn info symlink-file) > actual.info-symlink-file &&
- git-diff expected.info-symlink-file actual.info-symlink-file
+ (cd gitwc; git svn info symlink-file) > actual.info-symlink-file &&
+ test_cmp expected.info-symlink-file actual.info-symlink-file
"
test_expect_success 'info --url symlink-file' '
- test $(cd gitwc; git-svn info --url symlink-file) \
- = "$svnrepo/symlink-file"
+ test "$(cd gitwc; git svn info --url symlink-file)" \
+ = "$quoted_svnrepo/symlink-file"
'
test_expect_success 'info symlink-directory' "
(cd svnwc; svn info symlink-directory) \
> expected.info-symlink-directory &&
- (cd gitwc; git-svn info symlink-directory) \
+ (cd gitwc; git svn info symlink-directory) \
> actual.info-symlink-directory &&
- git-diff expected.info-symlink-directory actual.info-symlink-directory
+ test_cmp expected.info-symlink-directory actual.info-symlink-directory
"
test_expect_success 'info --url symlink-directory' '
- test $(cd gitwc; git-svn info --url symlink-directory) \
- = "$svnrepo/symlink-directory"
+ test "$(cd gitwc; git svn info --url symlink-directory)" \
+ = "$quoted_svnrepo/symlink-directory"
'
test_expect_success 'info added-file' "
@@ -113,16 +143,16 @@ test_expect_success 'info added-file' "
cp gitwc/added-file svnwc/added-file &&
ptouch gitwc/added-file svnwc/added-file &&
cd svnwc &&
- svn add added-file > /dev/null &&
+ svn_cmd add added-file > /dev/null &&
cd .. &&
(cd svnwc; svn info added-file) > expected.info-added-file &&
- (cd gitwc; git-svn info added-file) > actual.info-added-file &&
- git-diff expected.info-added-file actual.info-added-file
+ (cd gitwc; git svn info added-file) > actual.info-added-file &&
+ test_cmp expected.info-added-file actual.info-added-file
"
test_expect_success 'info --url added-file' '
- test $(cd gitwc; git-svn info --url added-file) \
- = "$svnrepo/added-file"
+ test "$(cd gitwc; git svn info --url added-file)" \
+ = "$quoted_svnrepo/added-file"
'
test_expect_success 'info added-directory' "
@@ -130,21 +160,21 @@ test_expect_success 'info added-directory' "
ptouch gitwc/added-directory svnwc/added-directory &&
touch gitwc/added-directory/.placeholder &&
cd svnwc &&
- svn add added-directory > /dev/null &&
+ svn_cmd add added-directory > /dev/null &&
cd .. &&
cd gitwc &&
git add added-directory &&
cd .. &&
(cd svnwc; svn info added-directory) \
> expected.info-added-directory &&
- (cd gitwc; git-svn info added-directory) \
+ (cd gitwc; git svn info added-directory) \
> actual.info-added-directory &&
- git-diff expected.info-added-directory actual.info-added-directory
+ test_cmp expected.info-added-directory actual.info-added-directory
"
test_expect_success 'info --url added-directory' '
- test $(cd gitwc; git-svn info --url added-directory) \
- = "$svnrepo/added-directory"
+ test "$(cd gitwc; git svn info --url added-directory)" \
+ = "$quoted_svnrepo/added-directory"
'
test_expect_success 'info added-symlink-file' "
@@ -154,20 +184,20 @@ test_expect_success 'info added-symlink-file' "
cd .. &&
cd svnwc &&
ln -s added-file added-symlink-file &&
- svn add added-symlink-file > /dev/null &&
+ svn_cmd add added-symlink-file > /dev/null &&
cd .. &&
ptouch gitwc/added-symlink-file svnwc/added-symlink-file &&
(cd svnwc; svn info added-symlink-file) \
> expected.info-added-symlink-file &&
- (cd gitwc; git-svn info added-symlink-file) \
+ (cd gitwc; git svn info added-symlink-file) \
> actual.info-added-symlink-file &&
- git-diff expected.info-added-symlink-file \
+ test_cmp expected.info-added-symlink-file \
actual.info-added-symlink-file
"
test_expect_success 'info --url added-symlink-file' '
- test $(cd gitwc; git-svn info --url added-symlink-file) \
- = "$svnrepo/added-symlink-file"
+ test "$(cd gitwc; git svn info --url added-symlink-file)" \
+ = "$quoted_svnrepo/added-symlink-file"
'
test_expect_success 'info added-symlink-directory' "
@@ -177,20 +207,20 @@ test_expect_success 'info added-symlink-directory' "
cd .. &&
cd svnwc &&
ln -s added-directory added-symlink-directory &&
- svn add added-symlink-directory > /dev/null &&
+ svn_cmd add added-symlink-directory > /dev/null &&
cd .. &&
ptouch gitwc/added-symlink-directory svnwc/added-symlink-directory &&
(cd svnwc; svn info added-symlink-directory) \
> expected.info-added-symlink-directory &&
- (cd gitwc; git-svn info added-symlink-directory) \
+ (cd gitwc; git svn info added-symlink-directory) \
> actual.info-added-symlink-directory &&
- git-diff expected.info-added-symlink-directory \
+ test_cmp expected.info-added-symlink-directory \
actual.info-added-symlink-directory
"
test_expect_success 'info --url added-symlink-directory' '
- test $(cd gitwc; git-svn info --url added-symlink-directory) \
- = "$svnrepo/added-symlink-directory"
+ test "$(cd gitwc; git svn info --url added-symlink-directory)" \
+ = "$quoted_svnrepo/added-symlink-directory"
'
# The next few tests replace the "Text Last Updated" value with a
@@ -203,20 +233,20 @@ test_expect_success 'info deleted-file' "
git rm -f file > /dev/null &&
cd .. &&
cd svnwc &&
- svn rm --force file > /dev/null &&
+ svn_cmd rm --force file > /dev/null &&
cd .. &&
(cd svnwc; svn info file) |
sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
> expected.info-deleted-file &&
- (cd gitwc; git-svn info file) |
+ (cd gitwc; git svn info file) |
sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
> actual.info-deleted-file &&
- git-diff expected.info-deleted-file actual.info-deleted-file
+ test_cmp expected.info-deleted-file actual.info-deleted-file
"
test_expect_success 'info --url file (deleted)' '
- test $(cd gitwc; git-svn info --url file) \
- = "$svnrepo/file"
+ test "$(cd gitwc; git svn info --url file)" \
+ = "$quoted_svnrepo/file"
'
test_expect_success 'info deleted-directory' "
@@ -224,20 +254,20 @@ test_expect_success 'info deleted-directory' "
git rm -r -f directory > /dev/null &&
cd .. &&
cd svnwc &&
- svn rm --force directory > /dev/null &&
+ svn_cmd rm --force directory > /dev/null &&
cd .. &&
(cd svnwc; svn info directory) |
sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
> expected.info-deleted-directory &&
- (cd gitwc; git-svn info directory) |
+ (cd gitwc; git svn info directory) |
sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
> actual.info-deleted-directory &&
- git-diff expected.info-deleted-directory actual.info-deleted-directory
+ test_cmp expected.info-deleted-directory actual.info-deleted-directory
"
test_expect_success 'info --url directory (deleted)' '
- test $(cd gitwc; git-svn info --url directory) \
- = "$svnrepo/directory"
+ test "$(cd gitwc; git svn info --url directory)" \
+ = "$quoted_svnrepo/directory"
'
test_expect_success 'info deleted-symlink-file' "
@@ -245,21 +275,21 @@ test_expect_success 'info deleted-symlink-file' "
git rm -f symlink-file > /dev/null &&
cd .. &&
cd svnwc &&
- svn rm --force symlink-file > /dev/null &&
+ svn_cmd rm --force symlink-file > /dev/null &&
cd .. &&
(cd svnwc; svn info symlink-file) |
sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
> expected.info-deleted-symlink-file &&
- (cd gitwc; git-svn info symlink-file) |
+ (cd gitwc; git svn info symlink-file) |
sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
> actual.info-deleted-symlink-file &&
- git-diff expected.info-deleted-symlink-file \
+ test_cmp expected.info-deleted-symlink-file \
actual.info-deleted-symlink-file
"
test_expect_success 'info --url symlink-file (deleted)' '
- test $(cd gitwc; git-svn info --url symlink-file) \
- = "$svnrepo/symlink-file"
+ test "$(cd gitwc; git svn info --url symlink-file)" \
+ = "$quoted_svnrepo/symlink-file"
'
test_expect_success 'info deleted-symlink-directory' "
@@ -267,21 +297,21 @@ test_expect_success 'info deleted-symlink-directory' "
git rm -f symlink-directory > /dev/null &&
cd .. &&
cd svnwc &&
- svn rm --force symlink-directory > /dev/null &&
+ svn_cmd rm --force symlink-directory > /dev/null &&
cd .. &&
(cd svnwc; svn info symlink-directory) |
sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
> expected.info-deleted-symlink-directory &&
- (cd gitwc; git-svn info symlink-directory) |
+ (cd gitwc; git svn info symlink-directory) |
sed -e 's/^\(Text Last Updated:\).*/\1 TEXT-LAST-UPDATED-STRING/' \
> actual.info-deleted-symlink-directory &&
- git-diff expected.info-deleted-symlink-directory \
+ test_cmp expected.info-deleted-symlink-directory \
actual.info-deleted-symlink-directory
"
test_expect_success 'info --url symlink-directory (deleted)' '
- test $(cd gitwc; git-svn info --url symlink-directory) \
- = "$svnrepo/symlink-directory"
+ test "$(cd gitwc; git svn info --url symlink-directory)" \
+ = "$quoted_svnrepo/symlink-directory"
'
# NOTE: git does not have the concept of replaced objects,
@@ -289,82 +319,59 @@ test_expect_success 'info --url symlink-directory (deleted)' '
test_expect_success 'info unknown-file' "
echo two > gitwc/unknown-file &&
- cp gitwc/unknown-file svnwc/unknown-file &&
- ptouch gitwc/unknown-file svnwc/unknown-file &&
- (cd svnwc; svn info unknown-file) 2> expected.info-unknown-file &&
- (cd gitwc; git-svn info unknown-file) 2> actual.info-unknown-file &&
- git-diff expected.info-unknown-file actual.info-unknown-file
+ (cd gitwc; test_must_fail git svn info unknown-file) \
+ 2> actual.info-unknown-file &&
+ grep unknown-file actual.info-unknown-file
"
test_expect_success 'info --url unknown-file' '
- test -z $(cd gitwc; git-svn info --url unknown-file \
- 2> ../actual.info--url-unknown-file) &&
- git-diff expected.info-unknown-file actual.info--url-unknown-file
+ echo two > gitwc/unknown-file &&
+ (cd gitwc; test_must_fail git svn info --url unknown-file) \
+ 2> actual.info-url-unknown-file &&
+ grep unknown-file actual.info-url-unknown-file
'
test_expect_success 'info unknown-directory' "
mkdir gitwc/unknown-directory svnwc/unknown-directory &&
- ptouch gitwc/unknown-directory svnwc/unknown-directory &&
- touch gitwc/unknown-directory/.placeholder &&
- (cd svnwc; svn info unknown-directory) \
- 2> expected.info-unknown-directory &&
- (cd gitwc; git-svn info unknown-directory) \
- 2> actual.info-unknown-directory &&
- git-diff expected.info-unknown-directory actual.info-unknown-directory
+ (cd gitwc; test_must_fail git svn info unknown-directory) \
+ 2> actual.info-unknown-directory &&
+ grep unknown-directory actual.info-unknown-directory
"
test_expect_success 'info --url unknown-directory' '
- test -z $(cd gitwc; git-svn info --url unknown-directory \
- 2> ../actual.info--url-unknown-directory) &&
- git-diff expected.info-unknown-directory \
- actual.info--url-unknown-directory
+ (cd gitwc; test_must_fail git svn info --url unknown-directory) \
+ 2> actual.info-url-unknown-directory &&
+ grep unknown-directory actual.info-url-unknown-directory
'
test_expect_success 'info unknown-symlink-file' "
cd gitwc &&
ln -s unknown-file unknown-symlink-file &&
cd .. &&
- cd svnwc &&
- ln -s unknown-file unknown-symlink-file &&
- cd .. &&
- ptouch gitwc/unknown-symlink-file svnwc/unknown-symlink-file &&
- (cd svnwc; svn info unknown-symlink-file) \
- 2> expected.info-unknown-symlink-file &&
- (cd gitwc; git-svn info unknown-symlink-file) \
- 2> actual.info-unknown-symlink-file &&
- git-diff expected.info-unknown-symlink-file \
- actual.info-unknown-symlink-file
+ (cd gitwc; test_must_fail git svn info unknown-symlink-file) \
+ 2> actual.info-unknown-symlink-file &&
+ grep unknown-symlink-file actual.info-unknown-symlink-file
"
test_expect_success 'info --url unknown-symlink-file' '
- test -z $(cd gitwc; git-svn info --url unknown-symlink-file \
- 2> ../actual.info--url-unknown-symlink-file) &&
- git-diff expected.info-unknown-symlink-file \
- actual.info--url-unknown-symlink-file
+ (cd gitwc; test_must_fail git svn info --url unknown-symlink-file) \
+ 2> actual.info-url-unknown-symlink-file &&
+ grep unknown-symlink-file actual.info-url-unknown-symlink-file
'
test_expect_success 'info unknown-symlink-directory' "
cd gitwc &&
ln -s unknown-directory unknown-symlink-directory &&
cd .. &&
- cd svnwc &&
- ln -s unknown-directory unknown-symlink-directory &&
- cd .. &&
- ptouch gitwc/unknown-symlink-directory \
- svnwc/unknown-symlink-directory &&
- (cd svnwc; svn info unknown-symlink-directory) \
- 2> expected.info-unknown-symlink-directory &&
- (cd gitwc; git-svn info unknown-symlink-directory) \
- 2> actual.info-unknown-symlink-directory &&
- git-diff expected.info-unknown-symlink-directory \
- actual.info-unknown-symlink-directory
+ (cd gitwc; test_must_fail git svn info unknown-symlink-directory) \
+ 2> actual.info-unknown-symlink-directory &&
+ grep unknown-symlink-directory actual.info-unknown-symlink-directory
"
test_expect_success 'info --url unknown-symlink-directory' '
- test -z $(cd gitwc; git-svn info --url unknown-symlink-directory \
- 2> ../actual.info--url-unknown-symlink-directory) &&
- git-diff expected.info-unknown-symlink-directory \
- actual.info--url-unknown-symlink-directory
+ (cd gitwc; test_must_fail git svn info --url unknown-symlink-directory) \
+ 2> actual.info-url-unknown-symlink-directory &&
+ grep unknown-symlink-directory actual.info-url-unknown-symlink-directory
'
test_done
diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh
index 9a4eabe523..9d9ebd533c 100755
--- a/t/t9120-git-svn-clone-with-percent-escapes.sh
+++ b/t/t9120-git-svn-clone-with-percent-escapes.sh
@@ -3,28 +3,75 @@
# Copyright (c) 2008 Kevin Ballard
#
-test_description='git-svn clone with percent escapes'
+test_description='git svn clone with percent escapes'
. ./lib-git-svn.sh
-test_expect_success 'setup svnrepo' "
+test_expect_success 'setup svnrepo' '
mkdir project project/trunk project/branches project/tags &&
echo foo > project/trunk/foo &&
- svn import -m '$test_description' project '$svnrepo/pr ject' &&
+ svn_cmd import -m "$test_description" project "$svnrepo/pr ject" &&
+ svn_cmd cp -m "branch" "$svnrepo/pr ject/trunk" \
+ "$svnrepo/pr ject/branches/b" &&
+ svn_cmd cp -m "tag" "$svnrepo/pr ject/trunk" \
+ "$svnrepo/pr ject/tags/v1" &&
rm -rf project &&
start_httpd
-"
-
-if test "$SVN_HTTPD_PORT" = ""
-then
- test_expect_failure 'test clone with percent escapes - needs SVN_HTTPD_PORT set' 'false'
-else
- test_expect_success 'test clone with percent escapes' '
- git svn clone "$svnrepo/pr%20ject" clone &&
- cd clone &&
- git rev-parse refs/remotes/git-svn &&
- cd ..
- '
-fi
+'
+
+test_expect_success 'test clone with percent escapes' '
+ git svn clone "$svnrepo/pr%20ject" clone &&
+ cd clone &&
+ git rev-parse refs/${remotes_git_svn} &&
+ cd ..
+'
+
+# SVN works either way, so should we...
+
+test_expect_success 'svn checkout with percent escapes' '
+ svn_cmd checkout "$svnrepo/pr%20ject" svn.percent &&
+ svn_cmd checkout "$svnrepo/pr%20ject/trunk" svn.percent.trunk
+'
+
+test_expect_success 'svn checkout with space' '
+ svn_cmd checkout "$svnrepo/pr ject" svn.space &&
+ svn_cmd checkout "$svnrepo/pr ject/trunk" svn.space.trunk
+'
+
+test_expect_success 'test clone trunk with percent escapes and minimize-url' '
+ git svn clone --minimize-url "$svnrepo/pr%20ject/trunk" minimize &&
+ (
+ cd minimize &&
+ git rev-parse refs/${remotes_git_svn}
+ )
+'
+
+test_expect_success 'test clone trunk with percent escapes' '
+ git svn clone "$svnrepo/pr%20ject/trunk" trunk &&
+ (
+ cd trunk &&
+ git rev-parse refs/${remotes_git_svn}
+ )
+'
+
+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
+ )
+'
+
+test_expect_success 'test clone -s with unescaped space' '
+ git svn clone -s "$svnrepo/pr ject" 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
+ )
+'
stop_httpd
diff --git a/t/t9121-git-svn-fetch-renamed-dir.sh b/t/t9121-git-svn-fetch-renamed-dir.sh
index 5143ed6066..000cad37c6 100755
--- a/t/t9121-git-svn-fetch-renamed-dir.sh
+++ b/t/t9121-git-svn-fetch-renamed-dir.sh
@@ -3,18 +3,18 @@
# Copyright (c) 2008 Santhosh Kumar Mani
-test_description='git-svn can fetch renamed directories'
+test_description='git svn can fetch renamed directories'
. ./lib-git-svn.sh
-test_expect_success 'load repository with renamed directory' "
- svnadmin load -q $rawsvnrepo < ../t9121/renamed-dir.dump
- "
+test_expect_success 'load repository with renamed directory' '
+ svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9121/renamed-dir.dump
+ '
-test_expect_success 'init and fetch repository' "
- git svn init $svnrepo/newname &&
+test_expect_success 'init and fetch repository' '
+ git svn init "$svnrepo/newname" &&
git svn fetch
- "
+ '
test_done
diff --git a/t/t9122-git-svn-author.sh b/t/t9122-git-svn-author.sh
new file mode 100755
index 0000000000..30013b7bb9
--- /dev/null
+++ b/t/t9122-git-svn-author.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+test_description='git svn authorship'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup svn repository' '
+ svn_cmd checkout "$svnrepo" work.svn &&
+ (
+ cd work.svn &&
+ echo >file
+ svn_cmd add file
+ svn_cmd commit -m "first commit" file
+ )
+'
+
+test_expect_success 'interact with it via git svn' '
+ mkdir work.git &&
+ (
+ cd work.git &&
+ git svn init "$svnrepo"
+ git svn fetch &&
+
+ echo modification >file &&
+ test_tick &&
+ git commit -a -m second &&
+
+ test_tick &&
+ git svn dcommit &&
+
+ echo "further modification" >file &&
+ test_tick &&
+ git commit -a -m third &&
+
+ test_tick &&
+ git svn --add-author-from dcommit &&
+
+ echo "yet further modification" >file &&
+ test_tick &&
+ git commit -a -m fourth &&
+
+ test_tick &&
+ git svn --add-author-from --use-log-author dcommit &&
+
+ git log &&
+
+ git show -s HEAD^^ >../actual.2 &&
+ git show -s HEAD^ >../actual.3 &&
+ git show -s HEAD >../actual.4
+
+ ) &&
+
+ # Make sure that --add-author-from without --use-log-author
+ # did not affect the authorship information
+ myself=$(grep "^Author: " actual.2) &&
+ unaffected=$(grep "^Author: " actual.3) &&
+ test "z$myself" = "z$unaffected" &&
+
+ # Make sure lack of --add-author-from did not add cruft
+ ! grep "^ From: A U Thor " actual.2 &&
+
+ # Make sure --add-author-from added cruft
+ grep "^ From: A U Thor " actual.3 &&
+ grep "^ From: A U Thor " actual.4 &&
+
+ # Make sure --add-author-from with --use-log-author affected
+ # the authorship information
+ grep "^Author: A U Thor " actual.4 &&
+
+ # Make sure there are no commit messages with excess blank lines
+ test $(grep "^ " actual.2 | wc -l) = 3 &&
+ test $(grep "^ " actual.3 | wc -l) = 5 &&
+ test $(grep "^ " actual.4 | wc -l) = 5 &&
+
+ # Make sure there are no svn commit messages with excess blank lines
+ (
+ cd work.svn &&
+ svn_cmd up &&
+
+ test $(svn_cmd log -r2:2 | wc -l) = 5 &&
+ test $(svn_cmd log -r4:4 | wc -l) = 7
+ )
+'
+
+test_done
diff --git a/t/t9123-git-svn-rebuild-with-rewriteroot.sh b/t/t9123-git-svn-rebuild-with-rewriteroot.sh
new file mode 100755
index 0000000000..045521615c
--- /dev/null
+++ b/t/t9123-git-svn-rebuild-with-rewriteroot.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Jan Krüger
+#
+
+test_description='git svn respects rewriteRoot during rebuild'
+
+. ./lib-git-svn.sh
+
+mkdir import
+cd import
+ touch foo
+ svn_cmd import -m 'import for git svn' . "$svnrepo" >/dev/null
+cd ..
+rm -rf import
+
+test_expect_success 'init, fetch and checkout repository' '
+ git svn init --rewrite-root=http://invalid.invalid/ "$svnrepo" &&
+ git svn fetch
+ git checkout -b mybranch ${remotes_git_svn}
+ '
+
+test_expect_success 'remove rev_map' '
+ rm "$GIT_SVN_DIR"/.rev_map.*
+ '
+
+test_expect_success 'rebuild rev_map' '
+ git svn rebase >/dev/null
+ '
+
+test_done
+
diff --git a/t/t9124-git-svn-dcommit-auto-props.sh b/t/t9124-git-svn-dcommit-auto-props.sh
new file mode 100755
index 0000000000..d6b076f6b7
--- /dev/null
+++ b/t/t9124-git-svn-dcommit-auto-props.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Brad King
+
+test_description='git svn dcommit honors auto-props'
+
+. ./lib-git-svn.sh
+
+generate_auto_props() {
+cat << EOF
+[miscellany]
+enable-auto-props=$1
+[auto-props]
+*.sh = svn:mime-type=application/x-shellscript; svn:eol-style=LF
+*.txt = svn:mime-type=text/plain; svn:eol-style = native
+EOF
+}
+
+test_expect_success 'initialize git svn' '
+ mkdir import &&
+ (
+ cd import &&
+ echo foo >foo &&
+ svn_cmd import -m "import for git svn" . "$svnrepo"
+ ) &&
+ rm -rf import &&
+ git svn init "$svnrepo"
+ git svn fetch
+'
+
+test_expect_success 'enable auto-props config' '
+ mkdir user &&
+ generate_auto_props yes >user/config
+'
+
+test_expect_success 'add files matching auto-props' '
+ echo "#!$SHELL_PATH" >exec1.sh &&
+ chmod +x exec1.sh &&
+ echo "hello" >hello.txt &&
+ echo bar >bar &&
+ git add exec1.sh hello.txt bar &&
+ git commit -m "files for enabled auto-props" &&
+ git svn dcommit --config-dir=user
+'
+
+test_expect_success 'disable auto-props config' '
+ generate_auto_props no >user/config
+'
+
+test_expect_success 'add files matching disabled auto-props' '
+ echo "#$SHELL_PATH" >exec2.sh &&
+ chmod +x exec2.sh &&
+ echo "world" >world.txt &&
+ echo zot >zot &&
+ git add exec2.sh world.txt zot &&
+ git commit -m "files for disabled auto-props" &&
+ git svn dcommit --config-dir=user
+'
+
+test_expect_success 'check resulting svn repository' '
+(
+ mkdir work &&
+ cd work &&
+ svn_cmd co "$svnrepo" &&
+ cd svnrepo &&
+
+ # Check properties from first commit.
+ test "x$(svn_cmd propget svn:executable exec1.sh)" = "x*" &&
+ test "x$(svn_cmd propget svn:mime-type exec1.sh)" = \
+ "xapplication/x-shellscript" &&
+ test "x$(svn_cmd propget svn:mime-type hello.txt)" = "xtext/plain" &&
+ test "x$(svn_cmd propget svn:eol-style hello.txt)" = "xnative" &&
+ test "x$(svn_cmd propget svn:mime-type bar)" = "x" &&
+
+ # Check properties from second commit.
+ test "x$(svn_cmd propget svn:executable exec2.sh)" = "x*" &&
+ test "x$(svn_cmd propget svn:mime-type exec2.sh)" = "x" &&
+ test "x$(svn_cmd propget svn:mime-type world.txt)" = "x" &&
+ test "x$(svn_cmd propget svn:eol-style world.txt)" = "x" &&
+ test "x$(svn_cmd propget svn:mime-type zot)" = "x"
+)
+'
+
+test_expect_success 'check renamed file' '
+ test -d user &&
+ generate_auto_props yes > user/config &&
+ git mv foo foo.sh &&
+ git commit -m "foo => foo.sh" &&
+ git svn dcommit --config-dir=user &&
+ (
+ cd work/svnrepo &&
+ svn_cmd up &&
+ test ! -e foo &&
+ test -e foo.sh &&
+ test "x$(svn_cmd propget svn:mime-type foo.sh)" = \
+ "xapplication/x-shellscript" &&
+ test "x$(svn_cmd propget svn:eol-style foo.sh)" = "xLF"
+ )
+'
+
+test_done
diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh
new file mode 100755
index 0000000000..c19418614f
--- /dev/null
+++ b/t/t9125-git-svn-multi-glob-branch-names.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Copyright (c) 2008 Marcus Griep
+
+test_description='git svn multi-glob branch names'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup svnrepo' '
+ mkdir project project/trunk project/branches \
+ project/branches/v14.1 project/tags &&
+ echo foo > project/trunk/foo &&
+ svn_cmd import -m "$test_description" project "$svnrepo/project" &&
+ rm -rf project &&
+ svn_cmd cp -m "fun" "$svnrepo/project/trunk" \
+ "$svnrepo/project/branches/v14.1/beta" &&
+ svn_cmd cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
+ "$svnrepo/project/branches/v14.1/gold"
+ '
+
+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" &&
+ cd ..
+ '
+
+test_expect_success 'test dcommit to multi-globbed branch' "
+ cd project &&
+ git reset --hard 'refs/remotes/v14.1/gold' &&
+ echo hello >> foo &&
+ git commit -m 'hello' -- foo &&
+ git svn dcommit &&
+ cd ..
+ "
+
+test_done
diff --git a/t/t9126-git-svn-follow-deleted-readded-directory.sh b/t/t9126-git-svn-follow-deleted-readded-directory.sh
new file mode 100755
index 0000000000..edec640e97
--- /dev/null
+++ b/t/t9126-git-svn-follow-deleted-readded-directory.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Alec Berryman
+
+test_description='git svn fetch repository with deleted and readded directory'
+
+. ./lib-git-svn.sh
+
+# Don't run this by default; it opens up a port.
+require_svnserve
+
+test_expect_success 'load repository' '
+ svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9126/follow-deleted-readded.dump
+ '
+
+test_expect_success 'fetch repository' '
+ start_svnserve &&
+ git svn init svn://127.0.0.1:$SVNSERVE_PORT &&
+ git svn fetch
+ '
+
+test_done
diff --git a/t/t9126/follow-deleted-readded.dump b/t/t9126/follow-deleted-readded.dump
new file mode 100644
index 0000000000..19da5d1ddc
--- /dev/null
+++ b/t/t9126/follow-deleted-readded.dump
@@ -0,0 +1,201 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 1807dc6f-c693-4cda-9710-00e1be8c1f21
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2008-09-14T19:53:13.006748Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 12
+Create trunk
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:13.239689Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 119
+Content-length: 119
+
+K 7
+svn:log
+V 20
+Create trunk/project
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:13.548860Z
+PROPS-END
+
+Node-path: trunk/project
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 3
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 12
+add new file
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:15.433630Z
+PROPS-END
+
+Node-path: trunk/project/foo
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 4
+Text-content-md5: d3b07384d113edec49eaa6238ad5ff00
+Content-length: 14
+
+PROPS-END
+foo
+
+
+Revision-number: 4
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 17
+change foo to bar
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:17.339884Z
+PROPS-END
+
+Node-path: trunk/project/foo
+Node-kind: file
+Node-action: change
+Text-content-length: 4
+Text-content-md5: c157a79031e1c40f85931829bc5fc552
+Content-length: 4
+
+bar
+
+
+Revision-number: 5
+Prop-content-length: 114
+Content-length: 114
+
+K 7
+svn:log
+V 15
+don't like that
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:19.335001Z
+PROPS-END
+
+Node-path: trunk/project
+Node-action: delete
+
+
+Revision-number: 6
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 11
+reset trunk
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:19.845897Z
+PROPS-END
+
+Node-path: trunk/project
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 4
+Node-copyfrom-path: trunk/project
+
+
+Revision-number: 7
+Prop-content-length: 113
+Content-length: 113
+
+K 7
+svn:log
+V 14
+change to quux
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:21.367947Z
+PROPS-END
+
+Node-path: trunk/project/foo
+Node-kind: file
+Node-action: change
+Text-content-length: 5
+Text-content-md5: d3b07a382ec010c01889250fce66fb13
+Content-length: 5
+
+quux
+
+
diff --git a/t/t9127-git-svn-partial-rebuild.sh b/t/t9127-git-svn-partial-rebuild.sh
new file mode 100755
index 0000000000..4aab8ecc14
--- /dev/null
+++ b/t/t9127-git-svn-partial-rebuild.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Deskin Miller
+#
+
+test_description='git svn partial-rebuild tests'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize svnrepo' '
+ mkdir import &&
+ (
+ cd import &&
+ mkdir trunk branches tags &&
+ cd trunk &&
+ echo foo > foo &&
+ cd .. &&
+ svn_cmd import -m "import for git-svn" . "$svnrepo" >/dev/null &&
+ svn_cmd copy "$svnrepo"/trunk "$svnrepo"/branches/a \
+ -m "created branch a" &&
+ cd .. &&
+ rm -rf import &&
+ svn_cmd co "$svnrepo"/trunk trunk &&
+ cd trunk &&
+ echo bar >> foo &&
+ svn_cmd ci -m "updated trunk" &&
+ cd .. &&
+ svn_cmd co "$svnrepo"/branches/a a &&
+ cd a &&
+ echo baz >> a &&
+ svn_cmd add a &&
+ svn_cmd ci -m "updated a" &&
+ cd .. &&
+ git svn init --stdlayout "$svnrepo"
+ )
+'
+
+test_expect_success 'import an early SVN revision into git' '
+ git svn fetch -r1:2
+'
+
+test_expect_success 'make full git mirror of SVN' '
+ mkdir mirror &&
+ (
+ cd mirror &&
+ git init &&
+ git svn init --stdlayout "$svnrepo" &&
+ git svn fetch &&
+ cd ..
+ )
+'
+
+test_expect_success 'fetch from git mirror and partial-rebuild' '
+ git config --add remote.origin.url "file://$PWD/mirror/.git" &&
+ git config --add remote.origin.fetch refs/remotes/*:refs/remotes/* &&
+ git fetch origin &&
+ git svn fetch
+'
+
+test_done
diff --git a/t/t9128-git-svn-cmd-branch.sh b/t/t9128-git-svn-cmd-branch.sh
new file mode 100755
index 0000000000..807e494a3a
--- /dev/null
+++ b/t/t9128-git-svn-cmd-branch.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Deskin Miller
+#
+
+test_description='git svn partial-rebuild tests'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize svnrepo' '
+ mkdir import &&
+ (
+ cd import &&
+ mkdir trunk branches tags &&
+ cd trunk &&
+ echo foo > foo &&
+ cd .. &&
+ svn_cmd import -m "import for git-svn" . "$svnrepo" >/dev/null &&
+ cd .. &&
+ rm -rf import &&
+ svn_cmd co "$svnrepo"/trunk trunk &&
+ cd trunk &&
+ echo bar >> foo &&
+ svn_cmd ci -m "updated trunk" &&
+ cd .. &&
+ rm -rf trunk
+ )
+'
+
+test_expect_success 'import into git' '
+ git svn init --stdlayout "$svnrepo" &&
+ git svn fetch &&
+ git checkout remotes/trunk
+'
+
+test_expect_success 'git svn branch tests' '
+ git svn branch a &&
+ base=$(git rev-parse HEAD:) &&
+ test $base = $(git rev-parse remotes/a:) &&
+ git svn branch -m "created branch b blah" b &&
+ test $base = $(git rev-parse remotes/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 svn branch a &&
+ git svn branch -t tag1 &&
+ test $base = $(git rev-parse remotes/tags/tag1:) &&
+ git svn branch --tag tag2 &&
+ test $base = $(git rev-parse remotes/tags/tag2:) &&
+ git svn tag tag3 &&
+ test $base = $(git rev-parse remotes/tags/tag3:) &&
+ git svn tag -m "created tag4 foo" tag4 &&
+ test $base = $(git rev-parse remotes/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 svn tag tag1
+'
+
+test_expect_success 'branch uses correct svn-remote' '
+ (svn_cmd co "$svnrepo" svn &&
+ cd svn &&
+ mkdir mirror &&
+ svn_cmd add mirror &&
+ svn_cmd copy trunk mirror/ &&
+ svn_cmd copy tags mirror/ &&
+ svn_cmd copy branches mirror/ &&
+ svn_cmd ci -m "made mirror" ) &&
+ rm -rf svn &&
+ git svn init -s -R mirror --prefix=mirror/ "$svnrepo"/mirror &&
+ git svn fetch -R mirror &&
+ git checkout mirror/trunk &&
+ base=$(git rev-parse HEAD:) &&
+ git svn branch -m "branch in mirror" d &&
+ test $base = $(git rev-parse remotes/mirror/d:) &&
+ test_must_fail git rev-parse remotes/d
+'
+
+test_done
diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh
new file mode 100755
index 0000000000..b9224bdb20
--- /dev/null
+++ b/t/t9129-git-svn-i18n-commitencoding.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Eric Wong
+
+test_description='git svn honors i18n.commitEncoding in config'
+
+. ./lib-git-svn.sh
+
+compare_git_head_with () {
+ nr=`wc -l < "$1"`
+ a=7
+ b=$(($a + $nr - 1))
+ git cat-file commit HEAD | sed -ne "$a,${b}p" >current &&
+ test_cmp current "$1"
+}
+
+compare_svn_head_with () {
+ # extract just the log message and strip out committer info.
+ # don't use --limit here since svn 1.1.x doesn't have it,
+ LC_ALL=en_US.UTF-8 svn log `git svn info --url` | perl -w -e '
+ use bytes;
+ $/ = ("-"x72) . "\n";
+ my @x = <STDIN>;
+ @x = split(/\n/, $x[1]);
+ splice(@x, 0, 2);
+ $x[-1] = "";
+ print join("\n", @x);
+ ' > current &&
+ test_cmp current "$1"
+}
+
+for H in ISO8859-1 eucJP ISO-2022-JP
+do
+ test_expect_success "$H setup" '
+ mkdir $H &&
+ svn_cmd import -m "$H test" $H "$svnrepo"/$H &&
+ git svn clone "$svnrepo"/$H $H
+ '
+done
+
+for H in ISO8859-1 eucJP ISO-2022-JP
+do
+ test_expect_success "$H commit on git side" '
+ (
+ cd $H &&
+ git config i18n.commitencoding $H &&
+ git checkout -b t refs/remotes/git-svn &&
+ echo $H >F &&
+ git add F &&
+ git commit -a -F "$TEST_DIRECTORY"/t3900/$H.txt &&
+ E=$(git cat-file commit HEAD | sed -ne "s/^encoding //p") &&
+ test "z$E" = "z$H"
+ compare_git_head_with "$TEST_DIRECTORY"/t3900/$H.txt
+ )
+ '
+done
+
+for H in ISO8859-1 eucJP ISO-2022-JP
+do
+ test_expect_success "$H dcommit to svn" '
+ (
+ cd $H &&
+ git svn dcommit &&
+ git cat-file commit HEAD | grep git-svn-id: &&
+ E=$(git cat-file commit HEAD | sed -ne "s/^encoding //p") &&
+ test "z$E" = "z$H" &&
+ compare_git_head_with "$TEST_DIRECTORY"/t3900/$H.txt
+ )
+ '
+done
+
+if locale -a |grep -q en_US.utf8; then
+ test_set_prereq UTF8
+else
+ say "UTF-8 locale not available, test skipped"
+fi
+
+test_expect_success UTF8 'ISO-8859-1 should match UTF-8 in svn' '
+ (
+ cd ISO8859-1 &&
+ compare_svn_head_with "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
+ )
+'
+
+for H in eucJP ISO-2022-JP
+do
+ test_expect_success UTF8 "$H should match UTF-8 in svn" '
+ (
+ cd $H &&
+ compare_svn_head_with "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
+ )
+ '
+done
+
+test_done
diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh
new file mode 100755
index 0000000000..134411e0a5
--- /dev/null
+++ b/t/t9130-git-svn-authors-file.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Eric Wong
+#
+
+test_description='git svn authors file tests'
+
+. ./lib-git-svn.sh
+
+cat > svn-authors <<EOF
+aa = AAAAAAA AAAAAAA <aa@example.com>
+bb = BBBBBBB BBBBBBB <bb@example.com>
+EOF
+
+test_expect_success 'setup svnrepo' '
+ for i in aa bb cc dd
+ do
+ svn_cmd mkdir -m $i --username $i "$svnrepo"/$i
+ done
+ '
+
+test_expect_success 'start import with incomplete authors file' '
+ ! git svn clone --authors-file=svn-authors "$svnrepo" x
+ '
+
+test_expect_success 'imported 2 revisions successfully' '
+ (
+ cd x
+ test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 2 &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn | \
+ grep "^author BBBBBBB BBBBBBB <bb@example\.com> " &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
+ grep "^author AAAAAAA AAAAAAA <aa@example\.com> "
+ )
+ '
+
+cat >> svn-authors <<EOF
+cc = CCCCCCC CCCCCCC <cc@example.com>
+dd = DDDDDDD DDDDDDD <dd@example.com>
+EOF
+
+test_expect_success 'continues to import once authors have been added' '
+ (
+ cd x
+ git svn fetch --authors-file=../svn-authors &&
+ test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 4 &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn | \
+ grep "^author DDDDDDD DDDDDDD <dd@example\.com> " &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
+ grep "^author CCCCCCC CCCCCCC <cc@example\.com> "
+ )
+ '
+
+test_expect_success 'authors-file against globs' '
+ svn_cmd mkdir -m globs --username aa \
+ "$svnrepo"/aa/trunk "$svnrepo"/aa/branches "$svnrepo"/aa/tags &&
+ git svn clone --authors-file=svn-authors -s "$svnrepo"/aa aa-work &&
+ for i in bb ee cc
+ do
+ branch="aa/branches/$i"
+ svn_cmd mkdir -m "$branch" --username $i "$svnrepo/$branch"
+ done
+ '
+
+test_expect_success 'fetch fails on ee' '
+ ( cd aa-work && ! git svn fetch --authors-file=../svn-authors )
+ '
+
+tmp_config_get () {
+ GIT_CONFIG=.git/svn/.metadata git config --get "$1"
+}
+
+test_expect_success 'failure happened without negative side effects' '
+ (
+ cd aa-work &&
+ test 6 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" &&
+ test 6 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`"
+ )
+ '
+
+cat >> svn-authors <<EOF
+ee = EEEEEEE EEEEEEE <ee@example.com>
+EOF
+
+test_expect_success 'fetch continues after authors-file is fixed' '
+ (
+ cd aa-work &&
+ git svn fetch --authors-file=../svn-authors &&
+ test 8 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" &&
+ test 8 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`"
+ )
+ '
+
+test_expect_success 'fresh clone with svn.authors-file in config' '
+ (
+ rm -r "$GIT_DIR" &&
+ test x = x"$(git config svn.authorsfile)" &&
+ HOME="`pwd`" &&
+ export HOME &&
+ test_config="$HOME"/.gitconfig &&
+ unset GIT_CONFIG_NOGLOBAL &&
+ unset GIT_DIR &&
+ unset GIT_CONFIG &&
+ git config --global \
+ svn.authorsfile "$HOME"/svn-authors &&
+ test x"$HOME"/svn-authors = x"$(git config svn.authorsfile)" &&
+ git svn clone "$svnrepo" gitconfig.clone &&
+ cd gitconfig.clone &&
+ nr_ex=$(git log | grep "^Author:.*example.com" | wc -l) &&
+ nr_rev=$(git rev-list HEAD | wc -l) &&
+ test $nr_rev -eq $nr_ex
+ )
+'
+
+test_debug 'GIT_DIR=gitconfig.clone/.git git log'
+
+test_done
diff --git a/t/t9131-git-svn-empty-symlink.sh b/t/t9131-git-svn-empty-symlink.sh
new file mode 100755
index 0000000000..9a24a65b64
--- /dev/null
+++ b/t/t9131-git-svn-empty-symlink.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+
+test_description='test that git handles an svn repository with empty symlinks'
+
+. ./lib-git-svn.sh
+test_expect_success 'load svn dumpfile' '
+ svnadmin load "$rawsvnrepo" <<EOF
+SVN-fs-dump-format-version: 2
+
+UUID: 60780f9a-7df5-43b4-83ab-60e2c0673ef7
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2008-11-26T07:17:27.590577Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 4
+test
+K 10
+svn:author
+V 12
+normalperson
+K 8
+svn:date
+V 27
+2008-11-26T07:18:03.511836Z
+PROPS-END
+
+Node-path: bar
+Node-kind: file
+Node-action: add
+Prop-content-length: 33
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Content-length: 33
+
+K 11
+svn:special
+V 1
+*
+PROPS-END
+
+Revision-number: 2
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 13
+bar => doink
+
+K 10
+svn:author
+V 12
+normalperson
+K 8
+svn:date
+V 27
+2008-11-27T03:55:31.601672Z
+PROPS-END
+
+Node-path: bar
+Node-kind: file
+Node-action: change
+Text-content-length: 10
+Text-content-md5: 92ca4fe7a9721f877f765c252dcd66c9
+Content-length: 10
+
+link doink
+
+EOF
+'
+
+test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" x'
+test_expect_success 'enable broken symlink workaround' \
+ '(cd x && git config svn.brokenSymlinkWorkaround true)'
+test_expect_success '"bar" is an empty file' 'test -f x/bar && ! test -s x/bar'
+test_expect_success 'get "bar" => symlink fix from svn' \
+ '(cd x && git svn rebase)'
+test_expect_success SYMLINKS '"bar" becomes a symlink' 'test -L x/bar'
+
+
+test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" y'
+test_expect_success 'disable broken symlink workaround' \
+ '(cd y && git config svn.brokenSymlinkWorkaround false)'
+test_expect_success '"bar" is an empty file' 'test -f y/bar && ! test -s y/bar'
+test_expect_success 'get "bar" => symlink fix from svn' \
+ '(cd y && git svn rebase)'
+test_expect_success '"bar" does not become a symlink' '! test -L y/bar'
+
+# svn.brokenSymlinkWorkaround is unset
+test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" z'
+test_expect_success '"bar" is an empty file' 'test -f z/bar && ! test -s z/bar'
+test_expect_success 'get "bar" => symlink fix from svn' \
+ '(cd z && git svn rebase)'
+test_expect_success '"bar" does not become a symlink' '! test -L z/bar'
+
+
+test_done
diff --git a/t/t9132-git-svn-broken-symlink.sh b/t/t9132-git-svn-broken-symlink.sh
new file mode 100755
index 0000000000..6c4c90b036
--- /dev/null
+++ b/t/t9132-git-svn-broken-symlink.sh
@@ -0,0 +1,102 @@
+#!/bin/sh
+
+test_description='test that git handles an svn repository with empty symlinks'
+
+. ./lib-git-svn.sh
+test_expect_success 'load svn dumpfile' '
+ svnadmin load "$rawsvnrepo" <<EOF
+SVN-fs-dump-format-version: 2
+
+UUID: 60780f9a-7df5-43b4-83ab-60e2c0673ef7
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2008-11-26T07:17:27.590577Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 4
+test
+K 10
+svn:author
+V 12
+normalperson
+K 8
+svn:date
+V 27
+2008-11-26T07:18:03.511836Z
+PROPS-END
+
+Node-path: bar
+Node-kind: file
+Node-action: add
+Prop-content-length: 33
+Text-content-length: 4
+Text-content-md5: 912ec803b2ce49e4a541068d495ab570
+Content-length: 37
+
+K 11
+svn:special
+V 1
+*
+PROPS-END
+asdf
+
+Revision-number: 2
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 13
+bar => doink
+
+K 10
+svn:author
+V 12
+normalperson
+K 8
+svn:date
+V 27
+2008-11-27T03:55:31.601672Z
+PROPS-END
+
+Node-path: bar
+Node-kind: file
+Node-action: change
+Text-content-length: 10
+Text-content-md5: 92ca4fe7a9721f877f765c252dcd66c9
+Content-length: 10
+
+link doink
+
+EOF
+'
+
+test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" x'
+
+test_expect_success SYMLINKS '"bar" is a symlink that points to "asdf"' '
+ test -L x/bar &&
+ (cd x && test xasdf = x"`git cat-file blob HEAD:bar`")
+'
+
+test_expect_success 'get "bar" => symlink fix from svn' '
+ (cd x && git svn rebase)
+'
+
+test_expect_success SYMLINKS '"bar" remains a proper symlink' '
+ test -L x/bar &&
+ (cd x && test xdoink = x"`git cat-file blob HEAD:bar`")
+'
+
+test_done
diff --git a/t/t9133-git-svn-nested-git-repo.sh b/t/t9133-git-svn-nested-git-repo.sh
new file mode 100755
index 0000000000..f3c30e63b7
--- /dev/null
+++ b/t/t9133-git-svn-nested-git-repo.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong
+#
+
+test_description='git svn property tests'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup repo with a git repo inside it' '
+ svn_cmd co "$svnrepo" s &&
+ (
+ cd s &&
+ git init &&
+ test -f .git/HEAD &&
+ > .git/a &&
+ echo a > a &&
+ svn_cmd add .git a &&
+ svn_cmd commit -m "create a nested git repo" &&
+ svn_cmd up &&
+ echo hi >> .git/a &&
+ svn_cmd commit -m "modify .git/a" &&
+ svn_cmd up
+ )
+'
+
+test_expect_success 'clone an SVN repo containing a git repo' '
+ git svn clone "$svnrepo" g &&
+ echo a > expect &&
+ test_cmp expect g/a
+'
+
+test_expect_success 'SVN-side change outside of .git' '
+ (
+ cd s &&
+ echo b >> a &&
+ svn_cmd commit -m "SVN-side change outside of .git" &&
+ svn_cmd up &&
+ svn_cmd log -v | fgrep "SVN-side change outside of .git"
+ )
+'
+
+test_expect_success 'update git svn-cloned repo' '
+ (
+ cd g &&
+ git svn rebase &&
+ echo a > expect &&
+ echo b >> expect &&
+ test_cmp a expect &&
+ rm expect
+ )
+'
+
+test_expect_success 'SVN-side change inside of .git' '
+ (
+ cd s &&
+ git add a &&
+ git commit -m "add a inside an SVN repo" &&
+ git log &&
+ svn_cmd add --force .git &&
+ svn_cmd commit -m "SVN-side change inside of .git" &&
+ svn_cmd up &&
+ svn_cmd log -v | fgrep "SVN-side change inside of .git"
+ )
+'
+
+test_expect_success 'update git svn-cloned repo' '
+ (
+ cd g &&
+ git svn rebase &&
+ echo a > expect &&
+ echo b >> expect &&
+ test_cmp a expect &&
+ rm expect
+ )
+'
+
+test_expect_success 'SVN-side change in and out of .git' '
+ (
+ cd s &&
+ echo c >> a &&
+ git add a &&
+ git commit -m "add a inside an SVN repo" &&
+ svn_cmd commit -m "SVN-side change in and out of .git" &&
+ svn_cmd up &&
+ svn_cmd log -v | fgrep "SVN-side change in and out of .git"
+ )
+'
+
+test_expect_success 'update git svn-cloned repo again' '
+ (
+ cd g &&
+ git svn rebase &&
+ echo a > expect &&
+ echo b >> expect &&
+ echo c >> expect &&
+ test_cmp a expect &&
+ rm expect
+ )
+'
+
+test_done
diff --git a/t/t9134-git-svn-ignore-paths.sh b/t/t9134-git-svn-ignore-paths.sh
new file mode 100755
index 0000000000..09ff10cd9b
--- /dev/null
+++ b/t/t9134-git-svn-ignore-paths.sh
@@ -0,0 +1,147 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Vitaly Shukela
+# Copyright (c) 2009 Eric Wong
+#
+
+test_description='git svn property tests'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup test repository' '
+ svn_cmd co "$svnrepo" s &&
+ (
+ cd s &&
+ mkdir qqq www &&
+ echo test_qqq > qqq/test_qqq.txt &&
+ echo test_www > www/test_www.txt &&
+ svn_cmd add qqq &&
+ svn_cmd add www &&
+ svn_cmd commit -m "create some files" &&
+ svn_cmd up &&
+ echo hi >> www/test_www.txt &&
+ svn_cmd commit -m "modify www/test_www.txt" &&
+ svn_cmd up
+ )
+'
+
+test_expect_success 'clone an SVN repository with ignored www directory' '
+ git svn clone --ignore-paths="^www" "$svnrepo" g &&
+ echo test_qqq > expect &&
+ for i in g/*/*.txt; do cat $i >> expect2; done &&
+ test_cmp expect expect2
+'
+
+test_expect_success 'init+fetch an SVN repository with ignored www directory' '
+ git svn init "$svnrepo" c &&
+ ( cd c && git svn fetch --ignore-paths="^www" ) &&
+ rm expect2 &&
+ echo test_qqq > expect &&
+ for i in c/*/*.txt; do cat $i >> expect2; done &&
+ test_cmp expect expect2
+'
+
+test_expect_success 'verify ignore-paths config saved by clone' '
+ (
+ cd g &&
+ git config --get svn-remote.svn.ignore-paths | fgrep "www"
+ )
+'
+
+test_expect_success 'SVN-side change outside of www' '
+ (
+ cd s &&
+ echo b >> qqq/test_qqq.txt &&
+ svn_cmd commit -m "SVN-side change outside of www" &&
+ svn_cmd up &&
+ svn_cmd log -v | fgrep "SVN-side change outside of www"
+ )
+'
+
+test_expect_success 'update git svn-cloned repo (config ignore)' '
+ (
+ cd g &&
+ git svn rebase &&
+ printf "test_qqq\nb\n" > expect &&
+ for i in */*.txt; do cat $i >> expect2; done &&
+ test_cmp expect2 expect &&
+ rm expect expect2
+ )
+'
+
+test_expect_success 'update git svn-cloned repo (option ignore)' '
+ (
+ cd c &&
+ git svn rebase --ignore-paths="^www" &&
+ printf "test_qqq\nb\n" > expect &&
+ for i in */*.txt; do cat $i >> expect2; done &&
+ test_cmp expect2 expect &&
+ rm expect expect2
+ )
+'
+
+test_expect_success 'SVN-side change inside of ignored www' '
+ (
+ cd s &&
+ echo zaq >> www/test_www.txt
+ svn_cmd commit -m "SVN-side change inside of www/test_www.txt" &&
+ svn_cmd up &&
+ svn_cmd log -v | fgrep "SVN-side change inside of www/test_www.txt"
+ )
+'
+
+test_expect_success 'update git svn-cloned repo (config ignore)' '
+ (
+ cd g &&
+ git svn rebase &&
+ printf "test_qqq\nb\n" > expect &&
+ for i in */*.txt; do cat $i >> expect2; done &&
+ test_cmp expect2 expect &&
+ rm expect expect2
+ )
+'
+
+test_expect_success 'update git svn-cloned repo (option ignore)' '
+ (
+ cd c &&
+ git svn rebase --ignore-paths="^www" &&
+ printf "test_qqq\nb\n" > expect &&
+ for i in */*.txt; do cat $i >> expect2; done &&
+ test_cmp expect2 expect &&
+ rm expect expect2
+ )
+'
+
+test_expect_success 'SVN-side change in and out of ignored www' '
+ (
+ cd s &&
+ echo cvf >> www/test_www.txt
+ echo ygg >> qqq/test_qqq.txt
+ svn_cmd commit -m "SVN-side change in and out of ignored www" &&
+ svn_cmd up &&
+ svn_cmd log -v | fgrep "SVN-side change in and out of ignored www"
+ )
+'
+
+test_expect_success 'update git svn-cloned repo again (config ignore)' '
+ (
+ cd g &&
+ git svn rebase &&
+ printf "test_qqq\nb\nygg\n" > expect &&
+ for i in */*.txt; do cat $i >> expect2; done &&
+ test_cmp expect2 expect &&
+ rm expect expect2
+ )
+'
+
+test_expect_success 'update git svn-cloned repo again (option ignore)' '
+ (
+ cd c &&
+ git svn rebase --ignore-paths="^www" &&
+ printf "test_qqq\nb\nygg\n" > expect &&
+ for i in */*.txt; do cat $i >> expect2; done &&
+ test_cmp expect2 expect &&
+ rm expect expect2
+ )
+'
+
+test_done
diff --git a/t/t9135-git-svn-moved-branch-empty-file.sh b/t/t9135-git-svn-moved-branch-empty-file.sh
new file mode 100755
index 0000000000..5280e5f1e4
--- /dev/null
+++ b/t/t9135-git-svn-moved-branch-empty-file.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+test_description='test moved svn branch with missing empty files'
+
+. ./lib-git-svn.sh
+test_expect_success 'load svn dumpfile' '
+ svnadmin load "$rawsvnrepo" < "${TEST_DIRECTORY}/t9135/svn.dump"
+ '
+
+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 &&
+ test -f b1 &&
+ ! test -s b1
+ )
+ '
+
+test_done
diff --git a/t/t9135/svn.dump b/t/t9135/svn.dump
new file mode 100644
index 0000000000..b51c0ccceb
--- /dev/null
+++ b/t/t9135/svn.dump
@@ -0,0 +1,192 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 1f80e919-e9e3-4d80-a3ae-d9f21095e27b
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2009-02-10T19:23:16.424027Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 123
+Content-length: 123
+
+K 7
+svn:log
+V 20
+init standard layout
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-10T19:23:17.195072Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 18
+branch-b off trunk
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-10T19:23:19.160095Z
+PROPS-END
+
+Node-path: branches/branch-b
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+Prop-content-length: 34
+Content-length: 34
+
+K 13
+svn:mergeinfo
+V 0
+
+PROPS-END
+
+
+Revision-number: 3
+Prop-content-length: 120
+Content-length: 120
+
+K 7
+svn:log
+V 17
+add empty file b1
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-10T19:23:20.194568Z
+PROPS-END
+
+Node-path: branches/branch-b/b1
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 4
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 8
+branch-c
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-10T19:23:21.169100Z
+PROPS-END
+
+Node-path: branches/branch-c
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 3
+Node-copyfrom-path: trunk
+
+
+Revision-number: 5
+Prop-content-length: 126
+Content-length: 126
+
+K 7
+svn:log
+V 23
+oops, wrong branchpoint
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-10T19:23:21.253557Z
+PROPS-END
+
+Node-path: branches/branch-c
+Node-action: delete
+
+
+Revision-number: 6
+Prop-content-length: 127
+Content-length: 127
+
+K 7
+svn:log
+V 24
+branch-c off of branch-b
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-10T19:23:21.314659Z
+PROPS-END
+
+Node-path: branches/branch-c
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 5
+Node-copyfrom-path: branches/branch-b
+Prop-content-length: 34
+Content-length: 34
+
+K 13
+svn:mergeinfo
+V 0
+
+PROPS-END
+
+
diff --git a/t/t9136-git-svn-recreated-branch-empty-file.sh b/t/t9136-git-svn-recreated-branch-empty-file.sh
new file mode 100755
index 0000000000..733d16e0b2
--- /dev/null
+++ b/t/t9136-git-svn-recreated-branch-empty-file.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+test_description='test recreated svn branch with empty files'
+
+. ./lib-git-svn.sh
+test_expect_success 'load svn dumpfile' '
+ svnadmin load "$rawsvnrepo" < "${TEST_DIRECTORY}/t9136/svn.dump"
+ '
+
+test_expect_success 'clone using git svn' 'git svn clone -s "$svnrepo" x'
+
+test_done
diff --git a/t/t9136/svn.dump b/t/t9136/svn.dump
new file mode 100644
index 0000000000..6b1ce0b2e8
--- /dev/null
+++ b/t/t9136/svn.dump
@@ -0,0 +1,192 @@
+SVN-fs-dump-format-version: 2
+
+UUID: eecae021-8f16-48da-969d-79beb8ae6ea5
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2009-02-22T00:50:56.292890Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 106
+Content-length: 106
+
+K 7
+svn:log
+V 4
+init
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-22T00:50:57.192384Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tags
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk/file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 105
+Content-length: 105
+
+K 7
+svn:log
+V 3
+1.0
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-22T00:50:58.124724Z
+PROPS-END
+
+Node-path: tags/1.0
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 3
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 9
+1.0.1-bad
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-22T00:50:58.151727Z
+PROPS-END
+
+Node-path: tags/1.0.1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: tags/1.0
+
+
+Revision-number: 4
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 9
+Wrong tag
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-22T00:50:58.167427Z
+PROPS-END
+
+Node-path: tags/1.0.1
+Node-action: delete
+
+
+Revision-number: 5
+Prop-content-length: 113
+Content-length: 113
+
+K 7
+svn:log
+V 10
+1.0-branch
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-22T00:50:58.184498Z
+PROPS-END
+
+Node-path: branches/1.0
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 4
+Node-copyfrom-path: tags/1.0
+
+
+Revision-number: 6
+Prop-content-length: 113
+Content-length: 113
+
+K 7
+svn:log
+V 10
+1.0.1-good
+K 10
+svn:author
+V 8
+john.doe
+K 8
+svn:date
+V 27
+2009-02-22T00:50:58.200695Z
+PROPS-END
+
+Node-path: tags/1.0.1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 5
+Node-copyfrom-path: branches/1.0
+
+
diff --git a/t/t9106-git-svn-dcommit-clobber-series.sh b/t/t9137-git-svn-dcommit-clobber-series.sh
index ca8a00ed0a..636ca0abb9 100755
--- a/t/t9106-git-svn-dcommit-clobber-series.sh
+++ b/t/t9137-git-svn-dcommit-clobber-series.sh
@@ -1,33 +1,33 @@
#!/bin/sh
#
# Copyright (c) 2007 Eric Wong
-test_description='git-svn dcommit clobber series'
+test_description='git svn dcommit clobber series'
. ./lib-git-svn.sh
-test_expect_success 'initialize repo' "
+test_expect_success 'initialize repo' '
mkdir import &&
cd import &&
- awk 'BEGIN { for (i = 1; i < 64; i++) { print i } }' > file
- svn import -m 'initial' . $svnrepo &&
+ awk "BEGIN { for (i = 1; i < 64; i++) { print i } }" > file
+ svn_cmd import -m "initial" . "$svnrepo" &&
cd .. &&
- git svn init $svnrepo &&
+ git svn init "$svnrepo" &&
git svn fetch &&
test -e file
- "
+ '
-test_expect_success '(supposedly) non-conflicting change from SVN' "
- test x\"\`sed -n -e 58p < file\`\" = x58 &&
- test x\"\`sed -n -e 61p < file\`\" = x61 &&
- svn co $svnrepo tmp &&
+test_expect_success '(supposedly) non-conflicting change from SVN' '
+ test x"`sed -n -e 58p < file`" = x58 &&
+ test x"`sed -n -e 61p < file`" = x61 &&
+ svn_cmd co "$svnrepo" tmp &&
cd tmp &&
- perl -i -p -e 's/^58\$/5588/' file &&
- perl -i -p -e 's/^61\$/6611/' file &&
+ perl -i.bak -p -e "s/^58$/5588/" file &&
+ perl -i.bak -p -e "s/^61$/6611/" file &&
poke file &&
- test x\"\`sed -n -e 58p < file\`\" = x5588 &&
- test x\"\`sed -n -e 61p < file\`\" = x6611 &&
- svn commit -m '58 => 5588, 61 => 6611' &&
+ test x"`sed -n -e 58p < file`" = x5588 &&
+ test x"`sed -n -e 61p < file`" = x6611 &&
+ svn_cmd commit -m "58 => 5588, 61 => 6611" &&
cd ..
- "
+ '
test_expect_success 'some unrelated changes to git' "
echo hi > life &&
@@ -40,13 +40,13 @@ test_expect_success 'some unrelated changes to git' "
test_expect_success 'change file but in unrelated area' "
test x\"\`sed -n -e 4p < file\`\" = x4 &&
test x\"\`sed -n -e 7p < file\`\" = x7 &&
- perl -i -p -e 's/^4\$/4444/' file &&
- perl -i -p -e 's/^7\$/7777/' file &&
+ perl -i.bak -p -e 's/^4\$/4444/' file &&
+ perl -i.bak -p -e 's/^7\$/7777/' file &&
test x\"\`sed -n -e 4p < file\`\" = x4444 &&
test x\"\`sed -n -e 7p < file\`\" = x7777 &&
git commit -m '4 => 4444, 7 => 7777' file &&
git svn dcommit &&
- svn up tmp &&
+ svn_cmd up tmp &&
cd tmp &&
test x\"\`sed -n -e 4p < file\`\" = x4444 &&
test x\"\`sed -n -e 7p < file\`\" = x7777 &&
@@ -57,7 +57,7 @@ test_expect_success 'change file but in unrelated area' "
test_expect_success 'attempt to dcommit with a dirty index' '
echo foo >>file &&
git add file &&
- ! git svn dcommit
+ test_must_fail git svn dcommit
'
test_done
diff --git a/t/t9138-git-svn-authors-prog.sh b/t/t9138-git-svn-authors-prog.sh
new file mode 100755
index 0000000000..83cc5fc9d1
--- /dev/null
+++ b/t/t9138-git-svn-authors-prog.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong, Mark Lodato
+#
+
+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";
+}
+EOF
+chmod +x svn-authors-prog
+
+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' '
+ (
+ cd x
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
+ grep "^author ee-foo <ee-foo@example\.com> " &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~2 | \
+ grep "^author dd <dd@sub\.example\.com> " &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~3 | \
+ grep "^author cc <cc@sub\.example\.com> " &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~4 | \
+ grep "^author bb <bb@example\.com> " &&
+ 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' '
+ (
+ cd x
+ 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
+
+test_expect_success 'authors-prog handled special characters in username' '
+ svn mkdir -m bad --username "xyz; touch evil" "$svnrepo"/bad &&
+ (
+ cd x &&
+ git svn --authors-prog=../svn-authors-prog fetch &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn |
+ grep "^author xyz; touch evil <xyz; touch evil@example\.com> " &&
+ ! test -f evil
+ )
+'
+
+test_done
diff --git a/t/t9139-git-svn-non-utf8-commitencoding.sh b/t/t9139-git-svn-non-utf8-commitencoding.sh
new file mode 100755
index 0000000000..f337959ccc
--- /dev/null
+++ b/t/t9139-git-svn-non-utf8-commitencoding.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong
+
+test_description='git svn refuses to dcommit non-UTF8 messages'
+
+. ./lib-git-svn.sh
+
+# ISO-2022-JP can pass for valid UTF-8, so skipping that in this test
+
+for H in ISO8859-1 eucJP
+do
+ test_expect_success "$H setup" '
+ mkdir $H &&
+ svn_cmd import -m "$H test" $H "$svnrepo"/$H &&
+ git svn clone "$svnrepo"/$H $H
+ '
+done
+
+for H in ISO8859-1 eucJP
+do
+ test_expect_success "$H commit on git side" '
+ (
+ cd $H &&
+ git config i18n.commitencoding $H &&
+ git checkout -b t refs/remotes/git-svn &&
+ echo $H >F &&
+ git add F &&
+ git commit -a -F "$TEST_DIRECTORY"/t3900/$H.txt &&
+ E=$(git cat-file commit HEAD | sed -ne "s/^encoding //p") &&
+ test "z$E" = "z$H"
+ )
+ '
+done
+
+for H in ISO8859-1 eucJP
+do
+ test_expect_success "$H dcommit to svn" '
+ (
+ cd $H &&
+ git config --unset i18n.commitencoding &&
+ ! git svn dcommit
+ )
+ '
+done
+
+test_done
diff --git a/t/t9140-git-svn-reset.sh b/t/t9140-git-svn-reset.sh
new file mode 100755
index 0000000000..0735526d4b
--- /dev/null
+++ b/t/t9140-git-svn-reset.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Ben Jackson
+#
+
+test_description='git svn reset'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup test repository' '
+ svn_cmd co "$svnrepo" s &&
+ (
+ cd s &&
+ mkdir vis &&
+ echo always visible > vis/vis.txt &&
+ svn_cmd add vis &&
+ svn_cmd commit -m "create visible files" &&
+ mkdir hid &&
+ echo initially hidden > hid/hid.txt &&
+ svn_cmd add hid &&
+ svn_cmd commit -m "create initially hidden files" &&
+ svn_cmd up &&
+ echo mod >> vis/vis.txt &&
+ svn_cmd commit -m "modify vis" &&
+ svn_cmd up
+ )
+'
+
+test_expect_success 'clone SVN repository with hidden directory' '
+ git svn init "$svnrepo" g &&
+ ( cd g && git svn fetch --ignore-paths="^hid" )
+'
+
+test_expect_success 'modify hidden file in SVN repo' '
+ ( cd s &&
+ echo mod hidden >> hid/hid.txt &&
+ svn_cmd commit -m "modify hid" &&
+ svn_cmd up
+ )
+'
+
+test_expect_success 'fetch fails on modified hidden file' '
+ ( cd g &&
+ git svn find-rev refs/remotes/git-svn > ../expect &&
+ ! git svn fetch 2> ../errors &&
+ git svn find-rev refs/remotes/git-svn > ../expect2 ) &&
+ fgrep "not found in commit" errors &&
+ test_cmp expect expect2
+'
+
+test_expect_success 'reset unwinds back to r1' '
+ ( cd g &&
+ git svn reset -r1 &&
+ git svn find-rev refs/remotes/git-svn > ../expect2 ) &&
+ echo 1 >expect &&
+ test_cmp expect expect2
+'
+
+test_expect_success 'refetch succeeds not ignoring any files' '
+ ( cd g &&
+ git svn fetch &&
+ git svn rebase &&
+ fgrep "mod hidden" hid/hid.txt
+ )
+'
+
+test_done
diff --git a/t/t9141-git-svn-multiple-branches.sh b/t/t9141-git-svn-multiple-branches.sh
new file mode 100755
index 0000000000..3cd06718eb
--- /dev/null
+++ b/t/t9141-git-svn-multiple-branches.sh
@@ -0,0 +1,122 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Marc Branchaud
+#
+
+test_description='git svn multiple branch and tag paths in the svn repo'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup svnrepo' '
+ mkdir project \
+ project/trunk \
+ project/b_one \
+ project/b_two \
+ project/tags_A \
+ project/tags_B &&
+ echo 1 > project/trunk/a.file &&
+ svn_cmd import -m "$test_description" project "$svnrepo/project" &&
+ rm -rf project &&
+ svn_cmd cp -m "Branch 1" "$svnrepo/project/trunk" \
+ "$svnrepo/project/b_one/first" &&
+ svn_cmd cp -m "Tag 1" "$svnrepo/project/trunk" \
+ "$svnrepo/project/tags_A/1.0" &&
+ svn_cmd co "$svnrepo/project" svn_project &&
+ ( cd svn_project &&
+ echo 2 > trunk/a.file &&
+ svn_cmd ci -m "Change 1" trunk/a.file &&
+ svn_cmd cp -m "Branch 2" "$svnrepo/project/trunk" \
+ "$svnrepo/project/b_one/second" &&
+ svn_cmd cp -m "Tag 2" "$svnrepo/project/trunk" \
+ "$svnrepo/project/tags_A/2.0" &&
+ echo 3 > trunk/a.file &&
+ svn_cmd ci -m "Change 2" trunk/a.file &&
+ svn_cmd cp -m "Branch 3" "$svnrepo/project/trunk" \
+ "$svnrepo/project/b_two/1" &&
+ svn_cmd cp -m "Tag 3" "$svnrepo/project/trunk" \
+ "$svnrepo/project/tags_A/3.0" &&
+ echo 4 > trunk/a.file &&
+ svn_cmd ci -m "Change 3" trunk/a.file &&
+ svn_cmd cp -m "Branch 4" "$svnrepo/project/trunk" \
+ "$svnrepo/project/b_two/2" &&
+ svn_cmd cp -m "Tag 4" "$svnrepo/project/trunk" \
+ "$svnrepo/project/tags_A/4.0" &&
+ svn_cmd up &&
+ echo 5 > b_one/first/a.file &&
+ svn_cmd ci -m "Change 4" b_one/first/a.file &&
+ svn_cmd cp -m "Tag 5" "$svnrepo/project/b_one/first" \
+ "$svnrepo/project/tags_B/v5" &&
+ echo 6 > b_one/second/a.file &&
+ svn_cmd ci -m "Change 5" b_one/second/a.file &&
+ svn_cmd cp -m "Tag 6" "$svnrepo/project/b_one/second" \
+ "$svnrepo/project/tags_B/v6" &&
+ echo 7 > b_two/1/a.file &&
+ svn_cmd ci -m "Change 6" b_two/1/a.file &&
+ svn_cmd cp -m "Tag 7" "$svnrepo/project/b_two/1" \
+ "$svnrepo/project/tags_B/v7" &&
+ echo 8 > b_two/2/a.file &&
+ svn_cmd ci -m "Change 7" b_two/2/a.file &&
+ svn_cmd cp -m "Tag 8" "$svnrepo/project/b_two/2" \
+ "$svnrepo/project/tags_B/v8"
+ )
+'
+
+test_expect_success 'clone multiple branch and tag paths' '
+ git svn clone -T trunk \
+ -b b_one/* --branches b_two/* \
+ -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
+ )
+'
+
+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
+ ) &&
+ ( cd svn_project &&
+ svn_cmd up &&
+ test_must_fail test -d b_one/Nope &&
+ test_must_fail test -d b_two/Nope &&
+ test_must_fail test -d tags_A/Tagless &&
+ test_must_fail test -d tags_B/Tagless
+ )
+'
+
+test_expect_success 'create new branches and tags' '
+ ( cd git_project &&
+ git svn branch -m "New branch 1" -d b_one New1 ) &&
+ ( cd svn_project &&
+ svn_cmd up && test -e b_one/New1/a.file ) &&
+
+ ( cd git_project &&
+ git svn branch -m "New branch 2" -d b_two New2 ) &&
+ ( cd svn_project &&
+ svn_cmd up && test -e b_two/New2/a.file ) &&
+
+ ( cd git_project &&
+ git svn branch -t -m "New tag 1" -d tags_A Tag1 ) &&
+ ( cd svn_project &&
+ svn_cmd up && test -e tags_A/Tag1/a.file ) &&
+
+ ( cd git_project &&
+ git svn tag -m "New tag 2" -d tags_B Tag2 ) &&
+ ( cd svn_project &&
+ svn_cmd up && test -e tags_B/Tag2/a.file )
+'
+
+test_done
diff --git a/t/t9142-git-svn-shallow-clone.sh b/t/t9142-git-svn-shallow-clone.sh
new file mode 100755
index 0000000000..1236accd99
--- /dev/null
+++ b/t/t9142-git-svn-shallow-clone.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong
+#
+
+test_description='git svn shallow clone'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup test repository' '
+ svn_cmd mkdir -m "create standard layout" \
+ "$svnrepo"/trunk "$svnrepo"/branches "$svnrepo"/tags &&
+ svn_cmd cp -m "branch off trunk" \
+ "$svnrepo"/trunk "$svnrepo"/branches/a &&
+ svn_cmd co "$svnrepo"/branches/a &&
+ (
+ cd a &&
+ > foo &&
+ svn_cmd add foo &&
+ svn_cmd commit -m "add foo"
+ )
+'
+
+start_httpd
+
+test_expect_success 'clone trunk with "-r HEAD"' '
+ git svn clone -r HEAD "$svnrepo/trunk" g &&
+ ( cd g && git rev-parse --symbolic --verify HEAD )
+'
+
+stop_httpd
+
+test_done
diff --git a/t/t9143-git-svn-gc.sh b/t/t9143-git-svn-gc.sh
new file mode 100755
index 0000000000..99f69c6a0b
--- /dev/null
+++ b/t/t9143-git-svn-gc.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Robert Allan Zeh
+
+test_description='git svn gc basic tests'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'setup directories and test repo' '
+ mkdir import &&
+ mkdir tmp &&
+ echo "Sample text for Subversion repository." > import/test.txt &&
+ svn_cmd import -m "import for git svn" import "$svnrepo" > /dev/null
+ '
+
+test_expect_success 'checkout working copy from svn' \
+ 'svn_cmd co "$svnrepo" test_wc'
+
+test_expect_success 'set some properties to create an unhandled.log file' '
+ (
+ cd test_wc &&
+ svn_cmd propset foo bar test.txt &&
+ svn_cmd commit -m "property set"
+ )'
+
+test_expect_success 'Setup repo' 'git svn init "$svnrepo"'
+
+test_expect_success 'Fetch repo' 'git svn fetch'
+
+test_expect_success 'make backup copy of unhandled.log' '
+ cp .git/svn/refs/remotes/git-svn/unhandled.log tmp
+ '
+
+test_expect_success 'create leftover index' '> .git/svn/refs/remotes/git-svn/index'
+
+test_expect_success 'git svn gc runs' 'git svn gc'
+
+test_expect_success 'git svn index removed' '! test -f .git/svn/refs/remotes/git-svn/index'
+
+if perl -MCompress::Zlib -e 0 2>/dev/null
+then
+ test_expect_success 'git svn gc produces a valid gzip file' '
+ gunzip .git/svn/refs/remotes/git-svn/unhandled.log.gz
+ '
+else
+ say "Perl Compress::Zlib unavailable, skipping gunzip test"
+fi
+
+test_expect_success 'git svn gc does not change unhandled.log files' '
+ test_cmp .git/svn/refs/remotes/git-svn/unhandled.log tmp/unhandled.log
+ '
+
+test_done
diff --git a/t/t9144-git-svn-old-rev_map.sh b/t/t9144-git-svn-old-rev_map.sh
new file mode 100755
index 0000000000..7600a35cd4
--- /dev/null
+++ b/t/t9144-git-svn-old-rev_map.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong
+
+test_description='git svn old rev_map preservd'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup test repository with old layout' '
+ mkdir i &&
+ (cd i && > a) &&
+ svn_cmd import -m- i "$svnrepo" &&
+ git svn init "$svnrepo" &&
+ git svn fetch &&
+ test -d .git/svn/refs/remotes/git-svn/ &&
+ ! test -e .git/svn/git-svn/ &&
+ mv .git/svn/refs/remotes/git-svn .git/svn/ &&
+ rm -r .git/svn/refs
+'
+
+test_expect_success 'old layout continues to work' '
+ svn_cmd import -m- i "$svnrepo/b" &&
+ git svn rebase &&
+ echo a >> b/a &&
+ git add b/a &&
+ git commit -m- -a &&
+ git svn dcommit &&
+ ! test -d .git/svn/refs/ &&
+ test -e .git/svn/git-svn/
+'
+
+test_done
diff --git a/t/t9145-git-svn-master-branch.sh b/t/t9145-git-svn-master-branch.sh
new file mode 100755
index 0000000000..16852d26ae
--- /dev/null
+++ b/t/t9145-git-svn-master-branch.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong
+#
+test_description='git svn initial master branch is "trunk" if possible'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup test repository' '
+ mkdir i &&
+ > i/a &&
+ svn_cmd import -m trunk i "$svnrepo/trunk" &&
+ svn_cmd import -m b/a i "$svnrepo/branches/a" &&
+ svn_cmd import -m b/b i "$svnrepo/branches/b"
+'
+
+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` = \
+ x`git rev-parse --verify refs/heads/master^0`
+ )
+'
+
+test_done
diff --git a/t/t9146-git-svn-empty-dirs.sh b/t/t9146-git-svn-empty-dirs.sh
new file mode 100755
index 0000000000..565365cbd3
--- /dev/null
+++ b/t/t9146-git-svn-empty-dirs.sh
@@ -0,0 +1,142 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong
+
+test_description='git svn creates empty directories'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize repo' '
+ for i in a b c d d/e d/e/f "weird file name"
+ do
+ svn_cmd mkdir -m "mkdir $i" "$svnrepo"/"$i"
+ done
+'
+
+test_expect_success 'clone' 'git svn clone "$svnrepo" cloned'
+
+test_expect_success 'empty directories exist' '
+ (
+ cd cloned &&
+ for i in a b c d d/e d/e/f "weird file name"
+ do
+ if ! test -d "$i"
+ then
+ echo >&2 "$i does not exist"
+ exit 1
+ fi
+ done
+ )
+'
+
+test_expect_success 'more emptiness' '
+ svn_cmd mkdir -m "bang bang" "$svnrepo"/"! !"
+'
+
+test_expect_success 'git svn rebase creates empty directory' '
+ ( cd cloned && git svn rebase )
+ test -d cloned/"! !"
+'
+
+test_expect_success 'git svn mkdirs recreates empty directories' '
+ (
+ cd cloned &&
+ rm -r * &&
+ git svn mkdirs &&
+ for i in a b c d d/e d/e/f "weird file name" "! !"
+ do
+ if ! test -d "$i"
+ then
+ echo >&2 "$i does not exist"
+ exit 1
+ fi
+ done
+ )
+'
+
+test_expect_success 'git svn mkdirs -r works' '
+ (
+ cd cloned &&
+ rm -r * &&
+ git svn mkdirs -r7 &&
+ for i in a b c d d/e d/e/f "weird file name"
+ do
+ if ! test -d "$i"
+ then
+ echo >&2 "$i does not exist"
+ exit 1
+ fi
+ done
+
+ if test -d "! !"
+ then
+ echo >&2 "$i should not exist"
+ exit 1
+ fi
+
+ git svn mkdirs -r8 &&
+ if ! test -d "! !"
+ then
+ echo >&2 "$i not exist"
+ exit 1
+ fi
+ )
+'
+
+test_expect_success 'initialize trunk' '
+ for i in trunk trunk/a trunk/"weird file name"
+ do
+ svn_cmd mkdir -m "mkdir $i" "$svnrepo"/"$i"
+ done
+'
+
+test_expect_success 'clone trunk' 'git svn clone -s "$svnrepo" trunk'
+
+test_expect_success 'empty directories in trunk exist' '
+ (
+ cd trunk &&
+ for i in a "weird file name"
+ do
+ if ! test -d "$i"
+ then
+ echo >&2 "$i does not exist"
+ exit 1
+ fi
+ done
+ )
+'
+
+test_expect_success 'remove a top-level directory from svn' '
+ svn_cmd rm -m "remove d" "$svnrepo"/d
+'
+
+test_expect_success 'removed top-level directory does not exist' '
+ git svn clone "$svnrepo" removed &&
+ test ! -e removed/d
+
+'
+unhandled=.git/svn/refs/remotes/git-svn/unhandled.log
+test_expect_success 'git svn gc-ed files work' '
+ (
+ cd removed &&
+ git svn gc &&
+ : Compress::Zlib may not be available &&
+ if test -f "$unhandled".gz
+ then
+ svn_cmd mkdir -m gz "$svnrepo"/gz &&
+ git reset --hard $(git rev-list HEAD | tail -1) &&
+ git svn rebase &&
+ test -f "$unhandled".gz &&
+ test -f "$unhandled" &&
+ for i in a b c "weird file name" gz "! !"
+ do
+ if ! test -d "$i"
+ then
+ echo >&2 "$i does not exist"
+ exit 1
+ fi
+ done
+ fi
+ )
+'
+
+test_done
diff --git a/t/t9150-svk-mergetickets.sh b/t/t9150-svk-mergetickets.sh
new file mode 100755
index 0000000000..53581425c4
--- /dev/null
+++ b/t/t9150-svk-mergetickets.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Sam Vilain
+#
+
+test_description='git-svn svk merge tickets'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'load svk depot' "
+ svnadmin load -q '$rawsvnrepo' \
+ < '$TEST_DIRECTORY/t9150/svk-merge.dump' &&
+ git svn init --minimize-url -R svkmerge \
+ -T trunk -b branches '$svnrepo' &&
+ git svn fetch --all
+ "
+
+uuid=b48289b2-9c08-4d72-af37-0358a40b9c15
+
+test_expect_success 'svk merges were represented coming in' "
+ [ `git cat-file commit HEAD | grep parent | wc -l` -eq 2 ]
+ "
+
+test_done
diff --git a/t/t9150/make-svk-dump b/t/t9150/make-svk-dump
new file mode 100644
index 0000000000..2242f14ebe
--- /dev/null
+++ b/t/t9150/make-svk-dump
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# this script sets up a Subversion repository for Makefile in the
+# first ever git merge, as if it were done with svk.
+#
+
+set -e
+
+svk depotmap foo ~/.svk/foo
+svk co /foo/ foo
+cd foo
+mkdir trunk
+mkdir branches
+svk add trunk branches
+svk commit -m "Setup trunk and branches"
+cd trunk
+
+git cat-file blob 6683463e:Makefile > Makefile
+svk add Makefile
+
+svk commit -m "ancestor"
+cd ..
+svk cp trunk branches/left
+
+svk commit -m "make left branch"
+cd branches/left/
+
+git cat-file blob 5873b67e:Makefile > Makefile
+svk commit -m "left update 1"
+
+cd ../../trunk
+git cat-file blob 75118b13:Makefile > Makefile
+svk commit -m "trunk update"
+
+cd ../branches/left
+git cat-file blob b5039db6:Makefile > Makefile
+svk commit -m "left update 2"
+
+cd ../../trunk
+svk sm /foo/branches/left
+# in theory we could delete the "left" branch here, but it's not
+# required so don't do it, in case people start getting ideas ;)
+svk commit -m "merge branch 'left' into 'trunk'"
+
+git cat-file blob b51ad431:Makefile > Makefile
+
+svk diff Makefile && echo "Hey! No differences, magic"
+
+cd ../..
+
+svnadmin dump ~/.svk/foo > svk-merge.dump
+
+svk co -d foo
+rm -rf foo
+svk depotmap -d /foo/
+rm -rf ~/.svk/foo
+
diff --git a/t/t9150/svk-merge.dump b/t/t9150/svk-merge.dump
new file mode 100644
index 0000000000..42f70dbec7
--- /dev/null
+++ b/t/t9150/svk-merge.dump
@@ -0,0 +1,616 @@
+SVN-fs-dump-format-version: 2
+
+UUID: b48289b2-9c08-4d72-af37-0358a40b9c15
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2009-10-19T23:44:03.722969Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 123
+Content-length: 123
+
+K 7
+svn:log
+V 24
+Setup trunk and branches
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:04.927533Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 106
+Content-length: 106
+
+K 7
+svn:log
+V 8
+ancestor
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:05.835585Z
+PROPS-END
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2401
+Text-content-md5: bfd8ff778d1492dc6758567373176a89
+Content-length: 2411
+
+PROPS-END
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 3
+Prop-content-length: 115
+Content-length: 115
+
+K 7
+svn:log
+V 16
+make left branch
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:06.719737Z
+PROPS-END
+
+Node-path: branches/left
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk
+
+
+Revision-number: 4
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 13
+left update 1
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:07.167666Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2465
+Text-content-md5: 16e38d9753b061731650561ce01b1195
+Content-length: 2465
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 5
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 12
+trunk update
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:07.619633Z
+PROPS-END
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2521
+Text-content-md5: 0668418a621333f4aa8b6632cd63e2a0
+Content-length: 2521
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 6
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 13
+left update 2
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:08.067554Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2593
+Text-content-md5: 5ccff689fb290e00b85fe18ee50c54ba
+Content-length: 2593
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 7
+Prop-content-length: 131
+Content-length: 131
+
+K 7
+svn:log
+V 32
+merge branch 'left' into 'trunk'
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-10-19T23:44:08.971801Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 83
+Content-length: 83
+
+K 9
+svk:merge
+V 53
+b48289b2-9c08-4d72-af37-0358a40b9c15:/branches/left:6
+PROPS-END
+
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2713
+Text-content-md5: 0afbe34f244cd662b1f97d708c687f90
+Content-length: 2713
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
diff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh
new file mode 100755
index 0000000000..359eeaa738
--- /dev/null
+++ b/t/t9151-svn-mergeinfo.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# Copyright (c) 2007, 2009 Sam Vilain
+#
+
+test_description='git-svn svn mergeinfo properties'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'load svn dump' "
+ svnadmin load -q '$rawsvnrepo' \
+ < '$TEST_DIRECTORY/t9151/svn-mergeinfo.dump' &&
+ git svn init --minimize-url -R svnmerge \
+ -T trunk -b branches '$svnrepo' &&
+ git svn fetch --all
+ "
+
+test_expect_success 'all svn merges became git merge commits' '
+ unmarked=$(git rev-list --parents --all --grep=Merge |
+ grep -v " .* " | cut -f1 -d" ")
+ [ -z "$unmarked" ]
+ '
+
+test_expect_success 'cherry picks did not become git merge commits' '
+ bad_cherries=$(git rev-list --parents --all --grep=Cherry |
+ grep " .* " | cut -f1 -d" ")
+ [ -z "$bad_cherries" ]
+ '
+
+test_expect_success 'svn non-merge merge commits did not become git merge commits' '
+ bad_non_merges=$(git rev-list --parents --all --grep=non-merge |
+ grep " .* " | cut -f1 -d" ")
+ [ -z "$bad_non_merges" ]
+ '
+
+test_expect_success 'everything got merged in the end' '
+ unmerged=$(git rev-list --all --not master)
+ [ -z "$unmerged" ]
+ '
+
+test_done
diff --git a/t/t9151/.gitignore b/t/t9151/.gitignore
new file mode 100644
index 0000000000..587c37dba3
--- /dev/null
+++ b/t/t9151/.gitignore
@@ -0,0 +1,2 @@
+foo
+foo.svn
diff --git a/t/t9151/make-svnmerge-dump b/t/t9151/make-svnmerge-dump
new file mode 100644
index 0000000000..d917717cf3
--- /dev/null
+++ b/t/t9151/make-svnmerge-dump
@@ -0,0 +1,161 @@
+#!/bin/sh
+#
+# this script sets up a Subversion repository for Makefile in the
+# first ever git merge, as if it were done with svnmerge (SVN 1.5+)
+#
+
+rm -rf foo.svn foo
+set -e
+
+mkdir foo.svn
+svnadmin create foo.svn
+svn co file://`pwd`/foo.svn foo
+
+commit() {
+ i=$(( $1 + 1 ))
+ shift;
+ svn commit -m "(r$i) $*" >/dev/null || exit 1
+ echo $i
+}
+
+say() {
+ echo " * $*"
+}
+
+i=0
+cd foo
+mkdir trunk
+mkdir branches
+svn add trunk branches
+i=$(commit $i "Setup trunk and branches")
+
+git cat-file blob 6683463e:Makefile > trunk/Makefile
+svn add trunk/Makefile
+
+say "Committing ANCESTOR"
+i=$(commit $i "ancestor")
+svn cp trunk branches/left
+
+say "Committing BRANCH POINT"
+i=$(commit $i "make left branch")
+svn cp trunk branches/right
+
+say "Committing other BRANCH POINT"
+i=$(commit $i "make right branch")
+
+say "Committing LEFT UPDATE"
+git cat-file blob 5873b67e:Makefile > branches/left/Makefile
+i=$(commit $i "left update 1")
+
+git cat-file blob 75118b13:Makefile > branches/right/Makefile
+say "Committing RIGHT UPDATE"
+pre_right_update_1=$i
+i=$(commit $i "right update 1")
+
+say "Making more commits on LEFT"
+git cat-file blob ff5ebe39:Makefile > branches/left/Makefile
+i=$(commit $i "left update 2")
+git cat-file blob b5039db6:Makefile > branches/left/Makefile
+i=$(commit $i "left update 3")
+
+say "Making a LEFT SUB-BRANCH"
+svn cp branches/left branches/left-sub
+sub_left_make=$i
+i=$(commit $i "make left sub-branch")
+
+say "Making a commit on LEFT SUB-BRANCH"
+echo "crunch" > branches/left-sub/README
+svn add branches/left-sub/README
+i=$(commit $i "left sub-branch update 1")
+
+say "Merging LEFT to TRUNK"
+svn update
+cd trunk
+svn merge ../branches/left --accept postpone
+git cat-file blob b5039db6:Makefile > Makefile
+svn resolved Makefile
+i=$(commit $i "Merge left to trunk 1")
+cd ..
+
+say "Making more commits on LEFT and RIGHT"
+echo "touche" > branches/left/zlonk
+svn add branches/left/zlonk
+i=$(commit $i "left update 4")
+echo "thwacke" > branches/right/bang
+svn add branches/right/bang
+i=$(commit $i "right update 2")
+
+say "Squash merge of RIGHT tip 2 commits onto TRUNK"
+svn update
+cd trunk
+svn merge -r$pre_right_update_1:$i ../branches/right
+i=$(commit $i "Cherry-pick right 2 commits to trunk")
+cd ..
+
+say "Merging RIGHT to TRUNK"
+svn update
+cd trunk
+svn merge ../branches/right --accept postpone
+git cat-file blob b51ad431:Makefile > Makefile
+svn resolved Makefile
+i=$(commit $i "Merge right to trunk 1")
+cd ..
+
+say "Making more commits on RIGHT and TRUNK"
+echo "whamm" > branches/right/urkkk
+svn add branches/right/urkkk
+i=$(commit $i "right update 3")
+echo "pow" > trunk/vronk
+svn add trunk/vronk
+i=$(commit $i "trunk update 1")
+
+say "Merging RIGHT to LEFT SUB-BRANCH"
+svn update
+cd branches/left-sub
+svn merge ../right --accept postpone
+git cat-file blob b51ad431:Makefile > Makefile
+svn resolved Makefile
+i=$(commit $i "Merge right to left sub-branch")
+cd ../..
+
+say "Making more commits on LEFT SUB-BRANCH and LEFT"
+echo "zowie" > branches/left-sub/wham_eth
+svn add branches/left-sub/wham_eth
+pre_sub_left_update_2=$i
+i=$(commit $i "left sub-branch update 2")
+sub_left_update_2=$i
+echo "eee_yow" > branches/left/glurpp
+svn add branches/left/glurpp
+i=$(commit $i "left update 5")
+
+say "Cherry pick LEFT SUB-BRANCH commit to LEFT"
+svn update
+cd branches/left
+svn merge -r$pre_sub_left_update_2:$sub_left_update_2 ../left-sub
+i=$(commit $i "Cherry-pick left sub-branch commit to left")
+cd ../..
+
+say "Merging LEFT SUB-BRANCH back to LEFT"
+svn update
+cd branches/left
+# it's only a merge because the previous merge cherry-picked the top commit
+svn merge -r$sub_left_make:$sub_left_update_2 ../left-sub --accept postpone
+i=$(commit $i "Merge left sub-branch to left")
+cd ../..
+
+say "Merging EVERYTHING to TRUNK"
+svn update
+cd trunk
+svn merge ../branches/left --accept postpone
+svn resolved bang
+i=$(commit $i "Merge left to trunk 2")
+# this merge, svn happily updates the mergeinfo, but there is actually
+# nothing to merge. git-svn will not make a meaningless merge commit.
+svn merge ../branches/right --accept postpone
+i=$(commit $i "non-merge right to trunk 2")
+cd ..
+
+cd ..
+svnadmin dump foo.svn > svn-mergeinfo.dump
+
+rm -rf foo foo.svn
diff --git a/t/t9151/svn-mergeinfo.dump b/t/t9151/svn-mergeinfo.dump
new file mode 100644
index 0000000000..9543e31c96
--- /dev/null
+++ b/t/t9151/svn-mergeinfo.dump
@@ -0,0 +1,1625 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 64142547-0943-4db2-836a-d1e1eb2f9924
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2009-12-19T16:17:51.232640Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 128
+Content-length: 128
+
+K 7
+svn:log
+V 29
+(r1) Setup trunk and branches
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:51.831965Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 13
+(r2) ancestor
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:52.300075Z
+PROPS-END
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2401
+Text-content-md5: bfd8ff778d1492dc6758567373176a89
+Text-content-sha1: 103205ce331f7d64086dba497574734f78439590
+Content-length: 2411
+
+PROPS-END
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 3
+Prop-content-length: 120
+Content-length: 120
+
+K 7
+svn:log
+V 21
+(r3) make left branch
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:52.768800Z
+PROPS-END
+
+Node-path: branches/left
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk/Makefile
+Text-copy-source-md5: bfd8ff778d1492dc6758567373176a89
+Text-copy-source-sha1: 103205ce331f7d64086dba497574734f78439590
+
+
+Revision-number: 4
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 22
+(r4) make right branch
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:53.177879Z
+PROPS-END
+
+Node-path: branches/right
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Node-path: branches/right/Makefile
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk/Makefile
+Text-copy-source-md5: bfd8ff778d1492dc6758567373176a89
+Text-copy-source-sha1: 103205ce331f7d64086dba497574734f78439590
+
+
+Revision-number: 5
+Prop-content-length: 117
+Content-length: 117
+
+K 7
+svn:log
+V 18
+(r5) left update 1
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:53.604691Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2465
+Text-content-md5: 16e38d9753b061731650561ce01b1195
+Text-content-sha1: 36da4b84ea9b64218ab48171dfc5c48ae025f38b
+Content-length: 2465
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 6
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 19
+(r6) right update 1
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:54.063555Z
+PROPS-END
+
+Node-path: branches/right/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2521
+Text-content-md5: 0668418a621333f4aa8b6632cd63e2a0
+Text-content-sha1: 4f29afd038e52f45acb5ef8c41acfc70062a741a
+Content-length: 2521
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 7
+Prop-content-length: 117
+Content-length: 117
+
+K 7
+svn:log
+V 18
+(r7) left update 2
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:54.523904Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2529
+Text-content-md5: f6b197cc3f2e89a83e545d4bb003de73
+Text-content-sha1: 2f656677cfec0bceec85e53036ffb63e25126f8e
+Content-length: 2529
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 8
+Prop-content-length: 117
+Content-length: 117
+
+K 7
+svn:log
+V 18
+(r8) left update 3
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:54.975970Z
+PROPS-END
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2593
+Text-content-md5: 5ccff689fb290e00b85fe18ee50c54ba
+Text-content-sha1: a13de8e23f1483efca3e57b2b64b0ae6f740ce10
+Content-length: 2593
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 9
+Prop-content-length: 124
+Content-length: 124
+
+K 7
+svn:log
+V 25
+(r9) make left sub-branch
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:55.459904Z
+PROPS-END
+
+Node-path: branches/left-sub
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 3
+Node-copyfrom-path: branches/left
+
+
+Node-path: branches/left-sub/Makefile
+Node-kind: file
+Node-action: delete
+
+Node-path: branches/left-sub/Makefile
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 8
+Node-copyfrom-path: branches/left/Makefile
+Text-copy-source-md5: 5ccff689fb290e00b85fe18ee50c54ba
+Text-copy-source-sha1: a13de8e23f1483efca3e57b2b64b0ae6f740ce10
+
+
+
+
+Revision-number: 10
+Prop-content-length: 129
+Content-length: 129
+
+K 7
+svn:log
+V 30
+(r10) left sub-branch update 1
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:55.862113Z
+PROPS-END
+
+Node-path: branches/left-sub/README
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 7
+Text-content-md5: fdbcfb6be9afe1121862143f226b51cf
+Text-content-sha1: 1d1f5ea4ceb584337ffe59b8980d92e3b78dfef4
+Content-length: 17
+
+PROPS-END
+crunch
+
+
+Revision-number: 11
+Prop-content-length: 126
+Content-length: 126
+
+K 7
+svn:log
+V 27
+(r11) Merge left to trunk 1
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:56.413416Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 54
+Content-length: 54
+
+K 13
+svn:mergeinfo
+V 19
+/branches/left:2-10
+PROPS-END
+
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2593
+Text-content-md5: 5ccff689fb290e00b85fe18ee50c54ba
+Text-content-sha1: a13de8e23f1483efca3e57b2b64b0ae6f740ce10
+Content-length: 2593
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Revision-number: 12
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 19
+(r12) left update 4
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:56.831014Z
+PROPS-END
+
+Node-path: branches/left/zlonk
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 7
+Text-content-md5: 8b9d8c7c2aaa6167e7d3407a773bbbba
+Text-content-sha1: 9716527ebd70a75c27625cacbeb2d897c6e86178
+Content-length: 17
+
+PROPS-END
+touche
+
+
+Revision-number: 13
+Prop-content-length: 119
+Content-length: 119
+
+K 7
+svn:log
+V 20
+(r13) right update 2
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:57.341143Z
+PROPS-END
+
+Node-path: branches/right/bang
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 8
+Text-content-md5: 34c28f1d2dc6a9adeccc4265bf7516cb
+Text-content-sha1: 0bc5bb345c0e71d28f784f12e0bd2d384c283062
+Content-length: 18
+
+PROPS-END
+thwacke
+
+
+Revision-number: 14
+Prop-content-length: 141
+Content-length: 141
+
+K 7
+svn:log
+V 42
+(r14) Cherry-pick right 2 commits to trunk
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:57.841851Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 75
+Content-length: 75
+
+K 13
+svn:mergeinfo
+V 40
+/branches/left:2-10
+/branches/right:6-13
+PROPS-END
+
+
+Node-path: trunk/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2713
+Text-content-md5: 0afbe34f244cd662b1f97d708c687f90
+Text-content-sha1: 46d9377d783e67a9b581da110352e799517c8a14
+Content-length: 2713
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Node-path: trunk/bang
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 13
+Node-copyfrom-path: branches/right/bang
+Text-copy-source-md5: 34c28f1d2dc6a9adeccc4265bf7516cb
+Text-copy-source-sha1: 0bc5bb345c0e71d28f784f12e0bd2d384c283062
+
+
+Revision-number: 15
+Prop-content-length: 127
+Content-length: 127
+
+K 7
+svn:log
+V 28
+(r15) Merge right to trunk 1
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:58.368520Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 75
+Content-length: 75
+
+K 13
+svn:mergeinfo
+V 40
+/branches/left:2-10
+/branches/right:2-14
+PROPS-END
+
+
+Revision-number: 16
+Prop-content-length: 119
+Content-length: 119
+
+K 7
+svn:log
+V 20
+(r16) right update 3
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:58.779056Z
+PROPS-END
+
+Node-path: branches/right/urkkk
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 6
+Text-content-md5: 5889c8392e16251b0c80927607a03036
+Text-content-sha1: 3934264d277a0cf886b6b1c7f2b9e56da2525302
+Content-length: 16
+
+PROPS-END
+whamm
+
+
+Revision-number: 17
+Prop-content-length: 119
+Content-length: 119
+
+K 7
+svn:log
+V 20
+(r17) trunk update 1
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:59.221851Z
+PROPS-END
+
+Node-path: trunk/vronk
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 4
+Text-content-md5: b2f80fa02a7f1364b9c29d3da44bf9f9
+Text-content-sha1: e994d980c0f2d7a3f76138bf96d57f36f9633828
+Content-length: 14
+
+PROPS-END
+pow
+
+
+Revision-number: 18
+Prop-content-length: 135
+Content-length: 135
+
+K 7
+svn:log
+V 36
+(r18) Merge right to left sub-branch
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:17:59.781666Z
+PROPS-END
+
+Node-path: branches/left-sub
+Node-kind: dir
+Node-action: change
+Prop-content-length: 55
+Content-length: 55
+
+K 13
+svn:mergeinfo
+V 20
+/branches/right:2-17
+PROPS-END
+
+
+Node-path: branches/left-sub/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2713
+Text-content-md5: 0afbe34f244cd662b1f97d708c687f90
+Text-content-sha1: 46d9377d783e67a9b581da110352e799517c8a14
+Content-length: 2713
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Node-path: branches/left-sub/bang
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 17
+Node-copyfrom-path: branches/right/bang
+Text-copy-source-md5: 34c28f1d2dc6a9adeccc4265bf7516cb
+Text-copy-source-sha1: 0bc5bb345c0e71d28f784f12e0bd2d384c283062
+
+
+Node-path: branches/left-sub/urkkk
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 17
+Node-copyfrom-path: branches/right/urkkk
+Text-copy-source-md5: 5889c8392e16251b0c80927607a03036
+Text-copy-source-sha1: 3934264d277a0cf886b6b1c7f2b9e56da2525302
+
+
+Revision-number: 19
+Prop-content-length: 129
+Content-length: 129
+
+K 7
+svn:log
+V 30
+(r19) left sub-branch update 2
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:18:00.200531Z
+PROPS-END
+
+Node-path: branches/left-sub/wham_eth
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 6
+Text-content-md5: 757bcd5818572ef3f9580052617c1c8b
+Text-content-sha1: b165019b005c199237ba822c4404e771e93b654a
+Content-length: 16
+
+PROPS-END
+zowie
+
+
+Revision-number: 20
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 19
+(r20) left update 5
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:18:00.659636Z
+PROPS-END
+
+Node-path: branches/left/glurpp
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 8
+Text-content-md5: 14a169f628e0bb59df9c2160649d0a30
+Text-content-sha1: ef7d929e52177767ecfcd28941f6b7f04b4131e3
+Content-length: 18
+
+PROPS-END
+eee_yow
+
+
+Revision-number: 21
+Prop-content-length: 147
+Content-length: 147
+
+K 7
+svn:log
+V 48
+(r21) Cherry-pick left sub-branch commit to left
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:18:01.194402Z
+PROPS-END
+
+Node-path: branches/left
+Node-kind: dir
+Node-action: change
+Prop-content-length: 56
+Content-length: 56
+
+K 13
+svn:mergeinfo
+V 21
+/branches/left-sub:19
+PROPS-END
+
+
+Node-path: branches/left/wham_eth
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 19
+Node-copyfrom-path: branches/left-sub/wham_eth
+Text-copy-source-md5: 757bcd5818572ef3f9580052617c1c8b
+Text-copy-source-sha1: b165019b005c199237ba822c4404e771e93b654a
+
+
+Revision-number: 22
+Prop-content-length: 134
+Content-length: 134
+
+K 7
+svn:log
+V 35
+(r22) Merge left sub-branch to left
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:18:01.679218Z
+PROPS-END
+
+Node-path: branches/left
+Node-kind: dir
+Node-action: change
+Prop-content-length: 79
+Content-length: 79
+
+K 13
+svn:mergeinfo
+V 44
+/branches/left-sub:4-19
+/branches/right:2-17
+PROPS-END
+
+
+Node-path: branches/left/Makefile
+Node-kind: file
+Node-action: change
+Text-content-length: 2713
+Text-content-md5: 0afbe34f244cd662b1f97d708c687f90
+Text-content-sha1: 46d9377d783e67a9b581da110352e799517c8a14
+Content-length: 2713
+
+# -DCOLLISION_CHECK if you believe that SHA1's
+# 1461501637330902918203684832716283019655932542976 hashes do not give you
+# enough guarantees about no collisions between objects ever hapenning.
+#
+# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
+# Note that you need some new glibc (at least >2.2.4) for this, and it will
+# BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly
+# break unless your underlying filesystem supports those sub-second times
+# (my ext3 doesn't).
+CFLAGS=-g -O3 -Wall
+
+CC=gcc
+
+
+PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
+ cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
+ check-files ls-tree merge-base merge-cache
+
+all: $(PROG)
+
+install: $(PROG)
+ install $(PROG) $(HOME)/bin/
+
+LIBS= -lssl -lz
+
+init-db: init-db.o
+
+update-cache: update-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o update-cache update-cache.o read-cache.o $(LIBS)
+
+show-diff: show-diff.o read-cache.o
+ $(CC) $(CFLAGS) -o show-diff show-diff.o read-cache.o $(LIBS)
+
+write-tree: write-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o write-tree write-tree.o read-cache.o $(LIBS)
+
+read-tree: read-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o read-tree read-tree.o read-cache.o $(LIBS)
+
+commit-tree: commit-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o commit-tree commit-tree.o read-cache.o $(LIBS)
+
+cat-file: cat-file.o read-cache.o
+ $(CC) $(CFLAGS) -o cat-file cat-file.o read-cache.o $(LIBS)
+
+fsck-cache: fsck-cache.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o fsck-cache fsck-cache.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+checkout-cache: checkout-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o checkout-cache checkout-cache.o read-cache.o $(LIBS)
+
+diff-tree: diff-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o diff-tree diff-tree.o read-cache.o $(LIBS)
+
+rev-tree: rev-tree.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o rev-tree rev-tree.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+show-files: show-files.o read-cache.o
+ $(CC) $(CFLAGS) -o show-files show-files.o read-cache.o $(LIBS)
+
+check-files: check-files.o read-cache.o
+ $(CC) $(CFLAGS) -o check-files check-files.o read-cache.o $(LIBS)
+
+ls-tree: ls-tree.o read-cache.o
+ $(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
+
+merge-base: merge-base.o read-cache.o object.o commit.o tree.o blob.o
+ $(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o object.o commit.o tree.o blob.o $(LIBS)
+
+merge-cache: merge-cache.o read-cache.o
+ $(CC) $(CFLAGS) -o merge-cache merge-cache.o read-cache.o $(LIBS)
+
+read-cache.o: cache.h
+show-diff.o: cache.h
+
+clean:
+ rm -f *.o $(PROG)
+
+backup: clean
+ cd .. ; tar czvf dircache.tar.gz dir-cache
+
+
+Node-path: branches/left/README
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 18
+Node-copyfrom-path: branches/left-sub/README
+Text-copy-source-md5: fdbcfb6be9afe1121862143f226b51cf
+Text-copy-source-sha1: 1d1f5ea4ceb584337ffe59b8980d92e3b78dfef4
+
+
+Node-path: branches/left/bang
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 18
+Node-copyfrom-path: branches/left-sub/bang
+Text-copy-source-md5: 34c28f1d2dc6a9adeccc4265bf7516cb
+Text-copy-source-sha1: 0bc5bb345c0e71d28f784f12e0bd2d384c283062
+
+
+Node-path: branches/left/urkkk
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 18
+Node-copyfrom-path: branches/left-sub/urkkk
+Text-copy-source-md5: 5889c8392e16251b0c80927607a03036
+Text-copy-source-sha1: 3934264d277a0cf886b6b1c7f2b9e56da2525302
+
+
+Revision-number: 23
+Prop-content-length: 126
+Content-length: 126
+
+K 7
+svn:log
+V 27
+(r23) Merge left to trunk 2
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:18:02.212349Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 99
+Content-length: 99
+
+K 13
+svn:mergeinfo
+V 64
+/branches/left:2-22
+/branches/left-sub:4-19
+/branches/right:2-17
+PROPS-END
+
+
+Node-path: trunk/README
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 22
+Node-copyfrom-path: branches/left/README
+Text-copy-source-md5: fdbcfb6be9afe1121862143f226b51cf
+Text-copy-source-sha1: 1d1f5ea4ceb584337ffe59b8980d92e3b78dfef4
+
+
+Node-path: trunk/glurpp
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 22
+Node-copyfrom-path: branches/left/glurpp
+Text-copy-source-md5: 14a169f628e0bb59df9c2160649d0a30
+Text-copy-source-sha1: ef7d929e52177767ecfcd28941f6b7f04b4131e3
+
+
+Node-path: trunk/urkkk
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 22
+Node-copyfrom-path: branches/left/urkkk
+Text-copy-source-md5: 5889c8392e16251b0c80927607a03036
+Text-copy-source-sha1: 3934264d277a0cf886b6b1c7f2b9e56da2525302
+
+
+Node-path: trunk/wham_eth
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 22
+Node-copyfrom-path: branches/left/wham_eth
+Text-copy-source-md5: 757bcd5818572ef3f9580052617c1c8b
+Text-copy-source-sha1: b165019b005c199237ba822c4404e771e93b654a
+
+
+Node-path: trunk/zlonk
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 22
+Node-copyfrom-path: branches/left/zlonk
+Text-copy-source-md5: 8b9d8c7c2aaa6167e7d3407a773bbbba
+Text-copy-source-sha1: 9716527ebd70a75c27625cacbeb2d897c6e86178
+
+
+Revision-number: 24
+Prop-content-length: 131
+Content-length: 131
+
+K 7
+svn:log
+V 32
+(r24) non-merge right to trunk 2
+K 10
+svn:author
+V 4
+samv
+K 8
+svn:date
+V 27
+2009-12-19T16:18:02.672148Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 99
+Content-length: 99
+
+K 13
+svn:mergeinfo
+V 64
+/branches/left:2-22
+/branches/left-sub:4-19
+/branches/right:2-22
+PROPS-END
+
+
diff --git a/t/t9152-svn-empty-dirs-after-gc.sh b/t/t9152-svn-empty-dirs-after-gc.sh
new file mode 100755
index 0000000000..301e779709
--- /dev/null
+++ b/t/t9152-svn-empty-dirs-after-gc.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Robert Zeh
+
+test_description='git svn creates empty directories, calls git gc, makes sure they are still empty'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize repo' '
+ for i in a b c d d/e d/e/f "weird file name"
+ do
+ svn_cmd mkdir -m "mkdir $i" "$svnrepo"/"$i"
+ done
+'
+
+test_expect_success 'clone' 'git svn clone "$svnrepo" cloned'
+
+test_expect_success 'git svn gc runs' '
+ (
+ cd cloned &&
+ git svn gc
+ )
+'
+
+test_expect_success 'git svn mkdirs recreates empty directories after git svn gc' '
+ (
+ cd cloned &&
+ rm -r * &&
+ git svn mkdirs &&
+ for i in a b c d d/e d/e/f "weird file name"
+ do
+ if ! test -d "$i"
+ then
+ echo >&2 "$i does not exist"
+ exit 1
+ fi
+ done
+ )
+'
+
+test_done
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index 42b144b1b3..fc3795dc98 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -6,12 +6,16 @@ test_description='Test export of commits to CVS'
. ./test-lib.sh
+if ! test_have_prereq PERL; then
+ say 'skipping git cvsexportcommit tests, perl not available'
+ test_done
+fi
+
cvs >/dev/null 2>&1
if test $? -ne 1
then
- test_expect_success 'skipping git-cvsexportcommit tests, cvs not found' :
+ say 'skipping git cvsexportcommit tests, cvs not found'
test_done
- exit
fi
CVSROOT=$(pwd)/cvsroot
@@ -45,8 +49,8 @@ test_expect_success \
'mkdir A B C D E F &&
echo hello1 >A/newfile1.txt &&
echo hello2 >B/newfile2.txt &&
- cp ../test9200a.png C/newfile3.png &&
- cp ../test9200a.png D/newfile4.png &&
+ cp "$TEST_DIRECTORY"/test9200a.png C/newfile3.png &&
+ cp "$TEST_DIRECTORY"/test9200a.png D/newfile4.png &&
git add A/newfile1.txt &&
git add B/newfile2.txt &&
git add C/newfile3.png &&
@@ -71,8 +75,8 @@ test_expect_success \
rm -f B/newfile2.txt &&
rm -f C/newfile3.png &&
echo Hello5 >E/newfile5.txt &&
- cp ../test9200b.png D/newfile4.png &&
- cp ../test9200a.png F/newfile6.png &&
+ cp "$TEST_DIRECTORY"/test9200b.png D/newfile4.png &&
+ cp "$TEST_DIRECTORY"/test9200a.png F/newfile6.png &&
git add E/newfile5.txt &&
git add F/newfile6.png &&
git commit -a -m "Test: Remove, add and update" &&
@@ -91,7 +95,7 @@ test_expect_success \
diff F/newfile6.png ../F/newfile6.png
)'
-# Should fail (but only on the git-cvsexportcommit stage)
+# Should fail (but only on the git cvsexportcommit stage)
test_expect_success \
'Fail to change binary more than one generation old' \
'cat F/newfile6.png >>D/newfile4.png &&
@@ -100,7 +104,7 @@ test_expect_success \
git commit -a -m "generation 2" &&
id=$(git rev-list --max-count=1 HEAD) &&
(cd "$CVSWORK" &&
- ! git cvsexportcommit -c $id
+ test_must_fail git cvsexportcommit -c $id
)'
#test_expect_success \
@@ -112,7 +116,7 @@ test_expect_success \
# git commit -a -m "generation 3" &&
# id=$(git rev-list --max-count=1 HEAD) &&
# (cd "$CVSWORK" &&
-# ! git cvsexportcommit -c $id
+# test_must_fail git cvsexportcommit -c $id
# )'
# We reuse the state from two tests back here
@@ -160,24 +164,24 @@ test_expect_success \
'mkdir "G g" &&
echo ok then >"G g/with spaces.txt" &&
git add "G g/with spaces.txt" && \
- cp ../test9200a.png "G g/with spaces.png" && \
+ cp "$TEST_DIRECTORY"/test9200a.png "G g/with spaces.png" && \
git add "G g/with spaces.png" &&
git commit -a -m "With spaces" &&
id=$(git rev-list --max-count=1 HEAD) &&
(cd "$CVSWORK" &&
- git-cvsexportcommit -c $id &&
+ git cvsexportcommit -c $id &&
check_entries "G g" "with spaces.png/1.1/-kb|with spaces.txt/1.1/"
)'
test_expect_success \
'Update file with spaces in file name' \
'echo Ok then >>"G g/with spaces.txt" &&
- cat ../test9200a.png >>"G g/with spaces.png" && \
+ cat "$TEST_DIRECTORY"/test9200a.png >>"G g/with spaces.png" && \
git add "G g/with spaces.png" &&
git commit -a -m "Update with spaces" &&
id=$(git rev-list --max-count=1 HEAD) &&
(cd "$CVSWORK" &&
- git-cvsexportcommit -c $id
+ git cvsexportcommit -c $id
check_entries "G g" "with spaces.png/1.2/-kb|with spaces.txt/1.2/"
)'
@@ -197,12 +201,12 @@ test_expect_success \
'mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö &&
echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
- cp ../test9200a.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
+ cp "$TEST_DIRECTORY"/test9200a.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
git commit -a -m "Går det så går det" && \
id=$(git rev-list --max-count=1 HEAD) &&
(cd "$CVSWORK" &&
- git-cvsexportcommit -v -c $id &&
+ git cvsexportcommit -v -c $id &&
check_entries \
"Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö" \
"gårdetsågårdet.png/1.1/-kb|gårdetsågårdet.txt/1.1/"
@@ -222,14 +226,15 @@ test_expect_success \
git commit -a -m "Update two" &&
id=$(git rev-list --max-count=1 HEAD) &&
(cd "$CVSWORK" &&
- ! git-cvsexportcommit -c $id
+ test_must_fail git cvsexportcommit -c $id
)'
-case "$(git config --bool core.filemode)" in
-false)
- ;;
-*)
-test_expect_success \
+if ! test "$(git config --bool core.filemode)" = false
+then
+ test_set_prereq FILEMODE
+fi
+
+test_expect_success FILEMODE \
'Retain execute bit' \
'mkdir G &&
echo executeon >G/on &&
@@ -239,12 +244,10 @@ test_expect_success \
git add G/off &&
git commit -a -m "Execute test" &&
(cd "$CVSWORK" &&
- git-cvsexportcommit -c HEAD
+ git cvsexportcommit -c HEAD
test -x G/on &&
! test -x G/off
)'
- ;;
-esac
test_expect_success '-w option should work with relative GIT_DIR' '
mkdir W &&
@@ -285,6 +288,27 @@ test_expect_success 'check files before directories' '
'
+test_expect_success 're-commit a removed filename which remains in CVS attic' '
+
+ (cd "$CVSWORK" &&
+ echo >attic_gremlin &&
+ cvs -Q add attic_gremlin &&
+ cvs -Q ci -m "added attic_gremlin" &&
+ rm attic_gremlin &&
+ cvs -Q rm attic_gremlin &&
+ cvs -Q ci -m "removed attic_gremlin") &&
+
+ echo > attic_gremlin &&
+ git add attic_gremlin &&
+ git commit -m "Added attic_gremlin" &&
+ git cvsexportcommit -w "$CVSWORK" -c HEAD &&
+ (cd "$CVSWORK"; cvs -Q update -d) &&
+ test -f "$CVSWORK/attic_gremlin"
+'
+
+# the state of the CVS sandbox may be indeterminate for ' space'
+# after this test on some platforms / with some versions of CVS
+# consider adding new tests above this point
test_expect_success 'commit a file with leading spaces in the name' '
echo space > " space" &&
@@ -292,9 +316,26 @@ test_expect_success 'commit a file with leading spaces in the name' '
git commit -m "Add a file with a leading space" &&
id=$(git rev-parse HEAD) &&
git cvsexportcommit -w "$CVSWORK" -c $id &&
- check_entries "$CVSWORK" " space/1.1/|DS/1.1/|release-notes/1.2/" &&
+ check_entries "$CVSWORK" " space/1.1/|DS/1.1/|attic_gremlin/1.3/|release-notes/1.2/" &&
test_cmp "$CVSWORK/ space" " space"
'
+test_expect_success 'use the same checkout for Git and CVS' '
+
+ (mkdir shared &&
+ cd shared &&
+ unset GIT_DIR &&
+ cvs co . &&
+ git init &&
+ git add " space" &&
+ git commit -m "fake initial commit" &&
+ echo Hello >> " space" &&
+ git commit -m "Another change" " space" &&
+ git cvsexportcommit -W -p -u -c HEAD &&
+ grep Hello " space" &&
+ git diff-files)
+
+'
+
test_done
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index c4f4465dc6..b49815d108 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -3,9 +3,9 @@
# Copyright (c) 2007 Shawn Pearce
#
-test_description='test git-fast-import utility'
+test_description='test git fast-import utility'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
file2_data='file2
second line of EOF'
@@ -56,10 +56,16 @@ M 644 :2 file2
M 644 :3 file3
M 755 :4 file4
+tag series-A
+from :5
+data <<EOF
+An annotated tag without a tagger
+EOF
+
INPUT_END
test_expect_success \
'A: create pack from stdin' \
- 'git-fast-import --export-marks=marks.out <input &&
+ 'git fast-import --export-marks=marks.out <input &&
git whatchanged master'
test_expect_success \
'A: verify pack' \
@@ -74,7 +80,7 @@ EOF
test_expect_success \
'A: verify commit' \
'git cat-file commit master | sed 1d >actual &&
- git diff expect actual'
+ test_cmp expect actual'
cat >expect <<EOF
100644 blob file2
@@ -84,22 +90,34 @@ EOF
test_expect_success \
'A: verify tree' \
'git cat-file -p master^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
- git diff expect actual'
+ test_cmp expect actual'
echo "$file2_data" >expect
test_expect_success \
'A: verify file2' \
- 'git cat-file blob master:file2 >actual && git diff expect actual'
+ 'git cat-file blob master:file2 >actual && test_cmp expect actual'
echo "$file3_data" >expect
test_expect_success \
'A: verify file3' \
- 'git cat-file blob master:file3 >actual && git diff expect actual'
+ 'git cat-file blob master:file3 >actual && test_cmp expect actual'
printf "$file4_data" >expect
test_expect_success \
'A: verify file4' \
- 'git cat-file blob master:file4 >actual && git diff expect actual'
+ 'git cat-file blob master:file4 >actual && test_cmp expect actual'
+
+cat >expect <<EOF
+object $(git rev-parse refs/heads/master)
+type commit
+tag series-A
+
+An annotated tag without a tagger
+EOF
+test_expect_success 'A: verify tag/series-A' '
+ git cat-file tag tags/series-A >actual &&
+ test_cmp expect actual
+'
cat >expect <<EOF
:2 `git rev-parse --verify master:file2`
@@ -109,15 +127,15 @@ cat >expect <<EOF
EOF
test_expect_success \
'A: verify marks output' \
- 'git diff expect marks.out'
+ 'test_cmp expect marks.out'
test_expect_success \
'A: verify marks import' \
- 'git-fast-import \
+ 'git fast-import \
--import-marks=marks.out \
--export-marks=marks.new \
</dev/null &&
- git diff -u expect marks.new'
+ test_cmp expect marks.new'
test_tick
cat >input <<INPUT_END
@@ -133,7 +151,7 @@ M 755 :2 copy-of-file2
INPUT_END
test_expect_success \
'A: verify marks import does not crash' \
- 'git-fast-import --import-marks=marks.out <input &&
+ 'git fast-import --import-marks=marks.out <input &&
git whatchanged verify--import-marks'
test_expect_success \
'A: verify pack' \
@@ -166,7 +184,7 @@ M 755 0000000000000000000000000000000000000001 zero1
INPUT_END
test_expect_success 'B: fail on invalid blob sha1' '
- ! git-fast-import <input
+ test_must_fail git fast-import <input
'
rm -f .git/objects/pack_* .git/objects/index_*
@@ -181,7 +199,7 @@ from refs/heads/master
INPUT_END
test_expect_success 'B: fail on invalid branch name ".badbranchname"' '
- ! git-fast-import <input
+ test_must_fail git fast-import <input
'
rm -f .git/objects/pack_* .git/objects/index_*
@@ -196,7 +214,7 @@ from refs/heads/master
INPUT_END
test_expect_success 'B: fail on invalid branch name "bad[branch]name"' '
- ! git-fast-import <input
+ test_must_fail git fast-import <input
'
rm -f .git/objects/pack_* .git/objects/index_*
@@ -212,7 +230,7 @@ from refs/heads/master
INPUT_END
test_expect_success \
'B: accept branch name "TEMP_TAG"' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
test -f .git/TEMP_TAG &&
test `git rev-parse master` = `git rev-parse TEMP_TAG^`'
rm -f .git/TEMP_TAG
@@ -221,7 +239,7 @@ rm -f .git/TEMP_TAG
### series C
###
-newf=`echo hi newf | git-hash-object -w --stdin`
+newf=`echo hi newf | git hash-object -w --stdin`
oldf=`git rev-parse --verify master:file2`
test_tick
cat >input <<INPUT_END
@@ -239,7 +257,7 @@ D file3
INPUT_END
test_expect_success \
'C: incremental import create pack from stdin' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
git whatchanged branch'
test_expect_success \
'C: verify pack' \
@@ -259,7 +277,7 @@ EOF
test_expect_success \
'C: verify commit' \
'git cat-file commit branch | sed 1d >actual &&
- git diff expect actual'
+ test_cmp expect actual'
cat >expect <<EOF
:000000 100755 0000000000000000000000000000000000000000 f1fb5da718392694d0076d677d6d0e364c79b0bc A file2/newf
@@ -297,7 +315,7 @@ EOF
INPUT_END
test_expect_success \
'D: inline data in commit' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
git whatchanged branch'
test_expect_success \
'D: verify pack' \
@@ -316,13 +334,13 @@ echo "$file5_data" >expect
test_expect_success \
'D: verify file5' \
'git cat-file blob branch:newdir/interesting >actual &&
- git diff expect actual'
+ test_cmp expect actual'
echo "$file6_data" >expect
test_expect_success \
'D: verify file6' \
'git cat-file blob branch:newdir/exec.sh >actual &&
- git diff expect actual'
+ test_cmp expect actual'
###
### series E
@@ -340,11 +358,11 @@ from refs/heads/branch^0
INPUT_END
test_expect_success 'E: rfc2822 date, --date-format=raw' '
- ! git-fast-import --date-format=raw <input
+ test_must_fail git fast-import --date-format=raw <input
'
test_expect_success \
'E: rfc2822 date, --date-format=rfc2822' \
- 'git-fast-import --date-format=rfc2822 <input'
+ 'git fast-import --date-format=rfc2822 <input'
test_expect_success \
'E: verify pack' \
'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
@@ -358,7 +376,7 @@ EOF
test_expect_success \
'E: verify commit' \
'git cat-file commit branch | sed 1,2d >actual &&
- git diff expect actual'
+ test_cmp expect actual'
###
### series F
@@ -381,7 +399,7 @@ from refs/heads/branch
INPUT_END
test_expect_success \
'F: non-fast-forward update skips' \
- 'if git-fast-import <input
+ 'if git fast-import <input
then
echo BAD gfi did not fail
return 1
@@ -411,7 +429,7 @@ EOF
test_expect_success \
'F: verify other commit' \
'git cat-file commit other >actual &&
- git diff expect actual'
+ test_cmp expect actual'
###
### series G
@@ -431,7 +449,7 @@ from refs/heads/branch~1
INPUT_END
test_expect_success \
'G: non-fast-forward update forced' \
- 'git-fast-import --force <input'
+ 'git fast-import --force <input'
test_expect_success \
'G: verify pack' \
'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
@@ -467,7 +485,7 @@ EOF
INPUT_END
test_expect_success \
'H: deletall, add 1' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
git whatchanged H'
test_expect_success \
'H: verify pack' \
@@ -489,7 +507,7 @@ echo "$file5_data" >expect
test_expect_success \
'H: verify file' \
'git cat-file blob H:h/e/l/lo >actual &&
- git diff expect actual'
+ test_cmp expect actual'
###
### series I
@@ -507,7 +525,7 @@ from refs/heads/branch
INPUT_END
test_expect_success \
'I: export-pack-edges' \
- 'git-fast-import --export-pack-edges=edges.list <input'
+ 'git fast-import --export-pack-edges=edges.list <input'
cat >expect <<EOF
.git/objects/pack/pack-.pack: `git rev-parse --verify export-boundary`
@@ -515,7 +533,7 @@ EOF
test_expect_success \
'I: verify edge list' \
'sed -e s/pack-.*pack/pack-.pack/ edges.list >actual &&
- git diff expect actual'
+ test_cmp expect actual'
###
### series J
@@ -541,7 +559,7 @@ COMMIT
INPUT_END
test_expect_success \
'J: reset existing branch creates empty commit' \
- 'git-fast-import <input'
+ 'git fast-import <input'
test_expect_success \
'J: branch has 1 commit, empty tree' \
'test 1 = `git rev-list J | wc -l` &&
@@ -571,7 +589,7 @@ from refs/heads/branch^1
INPUT_END
test_expect_success \
'K: reinit branch with from' \
- 'git-fast-import <input'
+ 'git fast-import <input'
test_expect_success \
'K: verify K^1 = branch^1' \
'test `git rev-parse --verify branch^1` \
@@ -623,9 +641,9 @@ EXPECT_END
test_expect_success \
'L: verify internal tree sorting' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
git diff-tree --abbrev --raw L^ L >output &&
- git diff expect output'
+ test_cmp expect output'
###
### series M
@@ -649,7 +667,7 @@ cat >expect <<EOF
EOF
test_expect_success \
'M: rename file in same subdirectory' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
git diff-tree -M -r M1^ M1 >actual &&
compare_diff_raw expect actual'
@@ -670,7 +688,7 @@ cat >expect <<EOF
EOF
test_expect_success \
'M: rename file to new subdirectory' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
git diff-tree -M -r M2^ M2 >actual &&
compare_diff_raw expect actual'
@@ -691,7 +709,7 @@ cat >expect <<EOF
EOF
test_expect_success \
'M: rename subdirectory to new subdirectory' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
git diff-tree -M -r M3^ M3 >actual &&
compare_diff_raw expect actual'
@@ -717,7 +735,7 @@ cat >expect <<EOF
EOF
test_expect_success \
'N: copy file in same subdirectory' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
git diff-tree -C --find-copies-harder -r N1^ N1 >actual &&
compare_diff_raw expect actual'
@@ -751,7 +769,7 @@ cat >expect <<EOF
EOF
test_expect_success \
'N: copy then modify subdirectory' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
git diff-tree -C --find-copies-harder -r N2^^ N2 >actual &&
compare_diff_raw expect actual'
@@ -775,8 +793,8 @@ INPUT_END
test_expect_success \
'N: copy dirty subdirectory' \
- 'git-fast-import <input &&
- test `git-rev-parse N2^{tree}` = `git-rev-parse N3^{tree}`'
+ 'git fast-import <input &&
+ test `git rev-parse N2^{tree}` = `git rev-parse N3^{tree}`'
###
### series O
@@ -815,8 +833,8 @@ INPUT_END
test_expect_success \
'O: comments are all skipped' \
- 'git-fast-import <input &&
- test `git-rev-parse N3` = `git-rev-parse O1`'
+ 'git fast-import <input &&
+ test `git rev-parse N3` = `git rev-parse O1`'
cat >input <<INPUT_END
commit refs/heads/O2
@@ -836,8 +854,8 @@ INPUT_END
test_expect_success \
'O: blank lines not necessary after data commands' \
- 'git-fast-import <input &&
- test `git-rev-parse N3` = `git-rev-parse O2`'
+ 'git fast-import <input &&
+ test `git rev-parse N3` = `git rev-parse O2`'
test_expect_success \
'O: repack before next test' \
@@ -881,11 +899,11 @@ commits
INPUT_END
test_expect_success \
'O: blank lines not necessary after other commands' \
- 'git-fast-import <input &&
+ 'git fast-import <input &&
test 8 = `find .git/objects/pack -type f | wc -l` &&
test `git rev-parse refs/tags/O3-2nd` = `git rev-parse O3^` &&
git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual &&
- git diff expect actual'
+ test_cmp expect actual'
cat >input <<INPUT_END
commit refs/heads/O4
@@ -914,8 +932,326 @@ progress I'm done!
INPUT_END
test_expect_success \
'O: progress outputs as requested by input' \
- 'git-fast-import <input >actual &&
+ 'git fast-import <input >actual &&
grep "progress " <input >expect &&
- git diff expect actual'
+ test_cmp expect actual'
+
+###
+### series P (gitlinks)
+###
+
+cat >input <<INPUT_END
+blob
+mark :1
+data 10
+test file
+
+reset refs/heads/sub
+commit refs/heads/sub
+mark :2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 12
+sub_initial
+M 100644 :1 file
+
+blob
+mark :3
+data <<DATAEND
+[submodule "sub"]
+ path = sub
+ url = "`pwd`/sub"
+DATAEND
+
+commit refs/heads/subuse1
+mark :4
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 8
+initial
+from refs/heads/master
+M 100644 :3 .gitmodules
+M 160000 :2 sub
+
+blob
+mark :5
+data 20
+test file
+more data
+
+commit refs/heads/sub
+mark :6
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 11
+sub_second
+from :2
+M 100644 :5 file
+
+commit refs/heads/subuse1
+mark :7
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 7
+second
+from :4
+M 160000 :6 sub
+
+INPUT_END
+
+test_expect_success \
+ 'P: supermodule & submodule mix' \
+ 'git fast-import <input &&
+ git checkout subuse1 &&
+ rm -rf sub && mkdir sub && cd sub &&
+ git init &&
+ git fetch --update-head-ok .. refs/heads/sub:refs/heads/master &&
+ git checkout master &&
+ cd .. &&
+ git submodule init &&
+ git submodule update'
+
+SUBLAST=$(git rev-parse --verify sub)
+SUBPREV=$(git rev-parse --verify sub^)
+
+cat >input <<INPUT_END
+blob
+mark :1
+data <<DATAEND
+[submodule "sub"]
+ path = sub
+ url = "`pwd`/sub"
+DATAEND
+
+commit refs/heads/subuse2
+mark :2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 8
+initial
+from refs/heads/master
+M 100644 :1 .gitmodules
+M 160000 $SUBPREV sub
+
+commit refs/heads/subuse2
+mark :3
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 7
+second
+from :2
+M 160000 $SUBLAST sub
+
+INPUT_END
+
+test_expect_success \
+ 'P: verbatim SHA gitlinks' \
+ 'git branch -D sub &&
+ git gc && git prune &&
+ git fast-import <input &&
+ test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1)'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/heads/subuse3
+mark :1
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+corrupt
+COMMIT
+
+from refs/heads/subuse2
+M 160000 inline sub
+data <<DATA
+$SUBPREV
+DATA
+
+INPUT_END
+
+test_expect_success 'P: fail on inline gitlink' '
+ test_must_fail git fast-import <input'
+
+test_tick
+cat >input <<INPUT_END
+blob
+mark :1
+data <<DATA
+$SUBPREV
+DATA
+
+commit refs/heads/subuse3
+mark :2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+corrupt
+COMMIT
+
+from refs/heads/subuse2
+M 160000 :1 sub
+
+INPUT_END
+
+test_expect_success 'P: fail on blob mark in gitlink' '
+ test_must_fail git fast-import <input'
+
+###
+### series Q (notes)
+###
+
+note1_data="Note for the first commit"
+note2_data="Note for the second commit"
+note3_data="Note for the third commit"
+
+test_tick
+cat >input <<INPUT_END
+blob
+mark :2
+data <<EOF
+$file2_data
+EOF
+
+commit refs/heads/notes-test
+mark :3
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+first (:3)
+COMMIT
+
+M 644 :2 file2
+
+blob
+mark :4
+data $file4_len
+$file4_data
+commit refs/heads/notes-test
+mark :5
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+second (:5)
+COMMIT
+
+M 644 :4 file4
+
+commit refs/heads/notes-test
+mark :6
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+third (:6)
+COMMIT
+
+M 644 inline file5
+data <<EOF
+$file5_data
+EOF
+
+M 755 inline file6
+data <<EOF
+$file6_data
+EOF
+
+blob
+mark :7
+data <<EOF
+$note1_data
+EOF
+
+blob
+mark :8
+data <<EOF
+$note2_data
+EOF
+
+commit refs/notes/foobar
+mark :9
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes (:9)
+COMMIT
+
+N :7 :3
+N :8 :5
+N inline :6
+data <<EOF
+$note3_data
+EOF
+
+INPUT_END
+test_expect_success \
+ 'Q: commit notes' \
+ 'git fast-import <input &&
+ git whatchanged notes-test'
+test_expect_success \
+ 'Q: verify pack' \
+ 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+commit1=$(git rev-parse notes-test~2)
+commit2=$(git rev-parse notes-test^)
+commit3=$(git rev-parse notes-test)
+
+cat >expect <<EOF
+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+first (:3)
+EOF
+test_expect_success \
+ 'Q: verify first commit' \
+ 'git cat-file commit notes-test~2 | sed 1d >actual &&
+ test_cmp expect actual'
+
+cat >expect <<EOF
+parent $commit1
+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+second (:5)
+EOF
+test_expect_success \
+ 'Q: verify second commit' \
+ 'git cat-file commit notes-test^ | sed 1d >actual &&
+ test_cmp expect actual'
+
+cat >expect <<EOF
+parent $commit2
+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+third (:6)
+EOF
+test_expect_success \
+ 'Q: verify third commit' \
+ 'git cat-file commit notes-test | sed 1d >actual &&
+ test_cmp expect actual'
+
+cat >expect <<EOF
+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+notes (:9)
+EOF
+test_expect_success \
+ 'Q: verify notes commit' \
+ 'git cat-file commit refs/notes/foobar | sed 1d >actual &&
+ test_cmp expect actual'
+
+cat >expect.unsorted <<EOF
+100644 blob $commit1
+100644 blob $commit2
+100644 blob $commit3
+EOF
+cat expect.unsorted | sort >expect
+test_expect_success \
+ 'Q: verify notes tree' \
+ 'git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual'
+
+echo "$note1_data" >expect
+test_expect_success \
+ 'Q: verify note for first commit' \
+ 'git cat-file blob refs/notes/foobar:$commit1 >actual && test_cmp expect actual'
+
+echo "$note2_data" >expect
+test_expect_success \
+ 'Q: verify note for second commit' \
+ 'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual'
+
+echo "$note3_data" >expect
+test_expect_success \
+ 'Q: verify note for third commit' \
+ 'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'
test_done
diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh
index f09bfb1117..356964e53a 100755
--- a/t/t9301-fast-export.sh
+++ b/t/t9301-fast-export.sh
@@ -3,11 +3,14 @@
# Copyright (c) 2007 Johannes E. Schindelin
#
-test_description='git-fast-export'
+test_description='git fast-export'
. ./test-lib.sh
test_expect_success 'setup' '
+ echo break it > file0 &&
+ git add file0 &&
+ test_tick &&
echo Wohlauf > file &&
git add file &&
test_tick &&
@@ -57,17 +60,17 @@ test_expect_success 'fast-export master~2..master' '
(cd new &&
git fast-import &&
test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
- git diff master..partial &&
- git diff master^..partial^ &&
- ! git rev-parse partial~2)
+ git diff --exit-code master partial &&
+ git diff --exit-code master^ partial^ &&
+ test_must_fail git rev-parse partial~2)
'
test_expect_success 'iso-8859-1' '
- git config i18n.commitencoding ISO-8859-1 &&
+ git config i18n.commitencoding ISO8859-1 &&
# use author and committer name in ISO-8859-1 to match it.
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
test_tick &&
echo rosten >file &&
git commit -s -m den file &&
@@ -78,6 +81,29 @@ test_expect_success 'iso-8859-1' '
git cat-file commit i18n | grep "Ãéí óú")
'
+test_expect_success 'import/export-marks' '
+
+ git checkout -b marks master &&
+ git fast-export --export-marks=tmp-marks HEAD &&
+ test -s tmp-marks &&
+ test $(wc -l < tmp-marks) -eq 3 &&
+ test $(
+ git fast-export --import-marks=tmp-marks\
+ --export-marks=tmp-marks HEAD |
+ grep ^commit |
+ wc -l) \
+ -eq 0 &&
+ echo change > file &&
+ git commit -m "last commit" file &&
+ test $(
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks HEAD |
+ grep ^commit\ |
+ wc -l) \
+ -eq 1 &&
+ test $(wc -l < tmp-marks) -eq 4
+
+'
cat > signed-tag-import << EOF
tag sign-your-name
@@ -102,7 +128,7 @@ test_expect_success 'set up faked signed tag' '
test_expect_success 'signed-tags=abort' '
- ! git fast-export --signed-tags=abort sign-your-name
+ test_must_fail git fast-export --signed-tags=abort sign-your-name
'
@@ -120,4 +146,229 @@ test_expect_success 'signed-tags=strip' '
'
+test_expect_success 'setup submodule' '
+
+ git checkout -f master &&
+ mkdir sub &&
+ cd sub &&
+ git init &&
+ echo test file > file &&
+ git add file &&
+ git commit -m sub_initial &&
+ cd .. &&
+ git submodule add "`pwd`/sub" sub &&
+ git commit -m initial &&
+ test_tick &&
+ cd sub &&
+ echo more data >> file &&
+ git add file &&
+ git commit -m sub_second &&
+ cd .. &&
+ git add sub &&
+ git commit -m second
+
+'
+
+test_expect_success 'submodule fast-export | fast-import' '
+
+ SUBENT1=$(git ls-tree master^ sub) &&
+ SUBENT2=$(git ls-tree master sub) &&
+ rm -rf new &&
+ mkdir new &&
+ git --git-dir=new/.git init &&
+ git fast-export --signed-tags=strip --all |
+ (cd new &&
+ git fast-import &&
+ test "$SUBENT1" = "$(git ls-tree refs/heads/master^ sub)" &&
+ test "$SUBENT2" = "$(git ls-tree refs/heads/master sub)" &&
+ git checkout master &&
+ git submodule init &&
+ git submodule update &&
+ cmp sub/file ../sub/file)
+
+'
+
+GIT_AUTHOR_NAME='A U Thor'; export GIT_AUTHOR_NAME
+GIT_COMMITTER_NAME='C O Mitter'; export GIT_COMMITTER_NAME
+
+test_expect_success 'setup copies' '
+
+ git config --unset i18n.commitencoding &&
+ git checkout -b copy rein &&
+ git mv file file3 &&
+ git commit -m move1 &&
+ test_tick &&
+ cp file2 file4 &&
+ git add file4 &&
+ git mv file2 file5 &&
+ git commit -m copy1 &&
+ test_tick &&
+ cp file3 file6 &&
+ git add file6 &&
+ git commit -m copy2 &&
+ test_tick &&
+ echo more text >> file6 &&
+ echo even more text >> file6 &&
+ git add file6 &&
+ git commit -m modify &&
+ test_tick &&
+ cp file6 file7 &&
+ echo test >> file7 &&
+ git add file7 &&
+ git commit -m copy_modify
+
+'
+
+test_expect_success 'fast-export -C -C | fast-import' '
+
+ ENTRY=$(git rev-parse --verify copy) &&
+ rm -rf new &&
+ mkdir new &&
+ git --git-dir=new/.git init &&
+ git fast-export -C -C --signed-tags=strip --all > output &&
+ grep "^C \"file6\" \"file7\"\$" output &&
+ cat output |
+ (cd new &&
+ git fast-import &&
+ test $ENTRY = $(git rev-parse --verify refs/heads/copy))
+
+'
+
+test_expect_success 'fast-export | fast-import when master is tagged' '
+
+ git tag -m msg last &&
+ git fast-export -C -C --signed-tags=strip --all > output &&
+ test $(grep -c "^tag " output) = 3
+
+'
+
+cat > tag-content << EOF
+object $(git rev-parse HEAD)
+type commit
+tag rosten
+EOF
+
+test_expect_success 'cope with tagger-less tags' '
+
+ TAG=$(git hash-object -t tag -w tag-content) &&
+ git update-ref refs/tags/sonnenschein $TAG &&
+ git fast-export -C -C --signed-tags=strip --all > output &&
+ test $(grep -c "^tag " output) = 4 &&
+ ! grep "Unspecified Tagger" output &&
+ git fast-export -C -C --signed-tags=strip --all \
+ --fake-missing-tagger > output &&
+ test $(grep -c "^tag " output) = 4 &&
+ grep "Unspecified Tagger" output
+
+'
+
+test_expect_success 'setup for limiting exports by PATH' '
+ mkdir limit-by-paths &&
+ cd limit-by-paths &&
+ git init &&
+ echo hi > there &&
+ git add there &&
+ git commit -m "First file" &&
+ echo foo > bar &&
+ git add bar &&
+ git commit -m "Second file" &&
+ git tag -a -m msg mytag &&
+ echo morefoo >> bar &&
+ git add bar &&
+ git commit -m "Change to second file" &&
+ cd ..
+'
+
+cat > limit-by-paths/expected << EOF
+blob
+mark :1
+data 3
+hi
+
+reset refs/tags/mytag
+commit refs/tags/mytag
+mark :2
+author A U Thor <author@example.com> 1112912713 -0700
+committer C O Mitter <committer@example.com> 1112912713 -0700
+data 11
+First file
+M 100644 :1 there
+
+EOF
+
+test_expect_success 'dropping tag of filtered out object' '
+ cd limit-by-paths &&
+ git fast-export --tag-of-filtered-object=drop mytag -- there > output &&
+ test_cmp output expected &&
+ cd ..
+'
+
+cat >> limit-by-paths/expected << EOF
+tag mytag
+from :2
+tagger C O Mitter <committer@example.com> 1112912713 -0700
+data 4
+msg
+
+EOF
+
+test_expect_success 'rewriting tag of filtered out object' '
+ cd limit-by-paths &&
+ git fast-export --tag-of-filtered-object=rewrite mytag -- there > output &&
+ test_cmp output expected &&
+ cd ..
+'
+
+cat > limit-by-paths/expected << EOF
+blob
+mark :1
+data 4
+foo
+
+blob
+mark :2
+data 3
+hi
+
+reset refs/heads/master
+commit refs/heads/master
+mark :3
+author A U Thor <author@example.com> 1112912713 -0700
+committer C O Mitter <committer@example.com> 1112912713 -0700
+data 12
+Second file
+M 100644 :1 bar
+M 100644 :2 there
+
+EOF
+
+test_expect_failure 'no exact-ref revisions included' '
+ cd limit-by-paths &&
+ git fast-export master~2..master~1 > output &&
+ test_cmp output expected &&
+ cd ..
+'
+
+
+test_expect_success 'set-up a few more tags for tag export tests' '
+ git checkout -f master &&
+ HEAD_TREE=`git show -s --pretty=raw HEAD | grep tree | sed "s/tree //"` &&
+ git tag tree_tag -m "tagging a tree" $HEAD_TREE &&
+ git tag -a tree_tag-obj -m "tagging a tree" $HEAD_TREE &&
+ git tag tag-obj_tag -m "tagging a tag" tree_tag-obj &&
+ git tag -a tag-obj_tag-obj -m "tagging a tag" tree_tag-obj
+'
+
+test_expect_success 'tree_tag' '
+ mkdir result &&
+ (cd result && git init) &&
+ git fast-export tree_tag > fe-stream &&
+ (cd result && git fast-import < ../fe-stream)
+'
+
+# NEEDSWORK: not just check return status, but validate the output
+test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj'
+test_expect_success 'tag-obj_tag' 'git fast-export tag-obj_tag'
+test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'
+
test_done
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index 166b43f783..c2ec3cb4bd 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -10,17 +10,19 @@ cvs CLI client via git-cvsserver server'
. ./test-lib.sh
+if ! test_have_prereq PERL; then
+ say 'skipping git cvsserver tests, perl not available'
+ test_done
+fi
cvs >/dev/null 2>&1
if test $? -ne 1
then
- test_expect_success 'skipping git-cvsserver tests, cvs not found' :
+ say 'skipping git-cvsserver tests, cvs not found'
test_done
- exit
fi
-perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
- test_expect_success 'skipping git-cvsserver tests, Perl SQLite interface unavailable' :
+"$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
+ say 'skipping git-cvsserver tests, Perl SQLite interface unavailable'
test_done
- exit
}
unset GIT_DIR GIT_CONFIG
@@ -44,7 +46,7 @@ test_expect_success 'setup' '
git add secondrootfile &&
git commit -m "second root") &&
git pull secondroot master &&
- git clone -q --local --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 &&
+ git clone -q --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 &&
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log"
'
@@ -153,21 +155,21 @@ test_expect_success 'req_Root failure (conflicting roots)' \
tail log | grep "^error 1 Conflicting roots specified$"'
test_expect_success 'req_Root (strict paths)' \
- 'cat request-anonymous | git-cvsserver --strict-paths pserver $SERVERDIR >log 2>&1 &&
+ 'cat request-anonymous | git-cvsserver --strict-paths pserver "$SERVERDIR" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
test_expect_success 'req_Root failure (strict-paths)' '
! cat request-anonymous |
- git-cvsserver --strict-paths pserver $WORKDIR >log 2>&1
+ git-cvsserver --strict-paths pserver "$WORKDIR" >log 2>&1
'
test_expect_success 'req_Root (w/o strict-paths)' \
- 'cat request-anonymous | git-cvsserver pserver $WORKDIR/ >log 2>&1 &&
+ 'cat request-anonymous | git-cvsserver pserver "$WORKDIR/" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
test_expect_success 'req_Root failure (w/o strict-paths)' '
! cat request-anonymous |
- git-cvsserver pserver $WORKDIR/gitcvs >log 2>&1
+ git-cvsserver pserver "$WORKDIR/gitcvs" >log 2>&1
'
cat >request-base <<EOF
@@ -180,25 +182,25 @@ Root /gitcvs.git
EOF
test_expect_success 'req_Root (base-path)' \
- 'cat request-base | git-cvsserver --strict-paths --base-path $WORKDIR/ pserver $SERVERDIR >log 2>&1 &&
+ 'cat request-base | git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
test_expect_success 'req_Root failure (base-path)' '
! cat request-anonymous |
- git-cvsserver --strict-paths --base-path $WORKDIR pserver $SERVERDIR >log 2>&1
+ git-cvsserver --strict-paths --base-path "$WORKDIR" pserver "$SERVERDIR" >log 2>&1
'
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false || exit 1
test_expect_success 'req_Root (export-all)' \
- 'cat request-anonymous | git-cvsserver --export-all pserver $WORKDIR >log 2>&1 &&
+ 'cat request-anonymous | git-cvsserver --export-all pserver "$WORKDIR" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
test_expect_success 'req_Root failure (export-all w/o whitelist)' \
'! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)'
test_expect_success 'req_Root (everything together)' \
- 'cat request-base | git-cvsserver --export-all --strict-paths --base-path $WORKDIR/ pserver $SERVERDIR >log 2>&1 &&
+ 'cat request-base | git-cvsserver --export-all --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU$"'
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true || exit 1
@@ -267,7 +269,7 @@ test_expect_success 'gitcvs.ext.dbname' \
rm -fr "$SERVERDIR"
cd "$WORKDIR" &&
-git clone -q --local --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 &&
+git clone -q --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 &&
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" ||
exit 1
@@ -424,7 +426,7 @@ cd "$WORKDIR"
test_expect_success 'cvs update (-p)' '
touch really-empty &&
echo Line 1 > no-lf &&
- echo -n Line 2 >> no-lf &&
+ printf "Line 2" >> no-lf &&
git add really-empty no-lf &&
git commit -q -m "Update -p test" &&
git push gitcvs.git >/dev/null &&
@@ -438,6 +440,13 @@ test_expect_success 'cvs update (-p)' '
test -z "$(cat failures)"
'
+cd "$WORKDIR"
+test_expect_success 'cvs update (module list supports packed refs)' '
+ GIT_DIR="$SERVERDIR" git pack-refs --all &&
+ GIT_CONFIG="$git_config" cvs -n up -d 2> out &&
+ grep "cvs update: New directory \`master'\''" < out
+'
+
#------------
# CVS STATUS
#------------
@@ -470,4 +479,28 @@ test_expect_success 'cvs status (no subdirs in header)' '
! grep / <../out
'
+#------------
+# CVS CHECKOUT
+#------------
+
+cd "$WORKDIR"
+test_expect_success 'cvs co -c (shows module database)' '
+ GIT_CONFIG="$git_config" cvs co -c > out &&
+ grep "^master[ ]\+master$" < out &&
+ ! grep -v "^master[ ]\+master$" < out
+'
+
+#------------
+# CVS ANNOTATE
+#------------
+
+cd "$WORKDIR"
+test_expect_success 'cvs annotate' '
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs annotate merge >../out &&
+ sed -e "s/ .*//" ../out >../actual &&
+ for i in 3 1 1 1 1 1 1 1 2 4; do echo 1.$i; done >../expect &&
+ test_cmp ../expect ../actual
+'
+
test_done
diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh
new file mode 100755
index 0000000000..40637d6782
--- /dev/null
+++ b/t/t9401-git-cvsserver-crlf.sh
@@ -0,0 +1,340 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Matthew Ogilvie
+# Parts adapted from other tests.
+#
+
+test_description='git-cvsserver -kb modes
+
+tests -kb mode for binary files when accessing a git
+repository using cvs CLI client via git-cvsserver server'
+
+. ./test-lib.sh
+
+q_to_nul () {
+ perl -pe 'y/Q/\000/'
+}
+
+q_to_cr () {
+ tr Q '\015'
+}
+
+marked_as () {
+ foundEntry="$(grep "^/$2/" "$1/CVS/Entries")"
+ if [ x"$foundEntry" = x"" ] ; then
+ echo "NOT FOUND: $1 $2 1 $3" >> "${WORKDIR}/marked.log"
+ return 1
+ fi
+ test x"$(grep "^/$2/" "$1/CVS/Entries" | cut -d/ -f5)" = x"$3"
+ stat=$?
+ echo "$1 $2 $stat '$3'" >> "${WORKDIR}/marked.log"
+ return $stat
+}
+
+not_present() {
+ foundEntry="$(grep "^/$2/" "$1/CVS/Entries")"
+ if [ -r "$1/$2" ] ; then
+ echo "Error: File still exists: $1 $2" >> "${WORKDIR}/marked.log"
+ return 1;
+ fi
+ if [ x"$foundEntry" != x"" ] ; then
+ echo "Error: should not have found: $1 $2" >> "${WORKDIR}/marked.log"
+ return 1;
+ else
+ echo "Correctly not found: $1 $2" >> "${WORKDIR}/marked.log"
+ return 0;
+ fi
+}
+
+cvs >/dev/null 2>&1
+if test $? -ne 1
+then
+ say 'skipping git-cvsserver tests, cvs not found'
+ test_done
+fi
+if ! test_have_prereq PERL
+then
+ say 'skipping git-cvsserver tests, perl not available'
+ test_done
+fi
+"$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
+ say 'skipping git-cvsserver tests, Perl SQLite interface unavailable'
+ test_done
+}
+
+unset GIT_DIR GIT_CONFIG
+WORKDIR=$(pwd)
+SERVERDIR=$(pwd)/gitcvs.git
+git_config="$SERVERDIR/config"
+CVSROOT=":fork:$SERVERDIR"
+CVSWORK="$(pwd)/cvswork"
+CVS_SERVER=git-cvsserver
+export CVSROOT CVS_SERVER
+
+rm -rf "$CVSWORK" "$SERVERDIR"
+test_expect_success 'setup' '
+ echo "Simple text file" >textfile.c &&
+ echo "File with embedded NUL: Q <- there" | q_to_nul > binfile.bin &&
+ mkdir subdir &&
+ echo "Another text file" > subdir/file.h &&
+ echo "Another binary: Q (this time CR)" | q_to_cr > subdir/withCr.bin &&
+ echo "Mixed up NUL, but marked text: Q <- there" | q_to_nul > mixedUp.c
+ echo "Unspecified" > subdir/unspecified.other &&
+ echo "/*.bin -crlf" > .gitattributes &&
+ echo "/*.c crlf" >> .gitattributes &&
+ echo "subdir/*.bin -crlf" >> .gitattributes &&
+ echo "subdir/*.c crlf" >> .gitattributes &&
+ echo "subdir/file.h crlf" >> .gitattributes &&
+ git add .gitattributes textfile.c binfile.bin mixedUp.c subdir/* &&
+ git commit -q -m "First Commit" &&
+ git clone -q --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 &&
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
+ GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log"
+'
+
+test_expect_success 'cvs co (default crlf)' '
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 &&
+ test x"$(grep '/-k' cvswork/CVS/Entries cvswork/subdir/CVS/Entries)" = x""
+'
+
+rm -rf cvswork
+test_expect_success 'cvs co (allbinary)' '
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.allbinary true &&
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 &&
+ marked_as cvswork textfile.c -kb &&
+ marked_as cvswork binfile.bin -kb &&
+ marked_as cvswork .gitattributes -kb &&
+ marked_as cvswork mixedUp.c -kb &&
+ marked_as cvswork/subdir withCr.bin -kb &&
+ marked_as cvswork/subdir file.h -kb &&
+ marked_as cvswork/subdir unspecified.other -kb
+'
+
+rm -rf cvswork cvs.log
+test_expect_success 'cvs co (use attributes/allbinary)' '
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.usecrlfattr true &&
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 &&
+ marked_as cvswork textfile.c "" &&
+ marked_as cvswork binfile.bin -kb &&
+ marked_as cvswork .gitattributes -kb &&
+ marked_as cvswork mixedUp.c "" &&
+ marked_as cvswork/subdir withCr.bin -kb &&
+ marked_as cvswork/subdir file.h "" &&
+ marked_as cvswork/subdir unspecified.other -kb
+'
+
+rm -rf cvswork
+test_expect_success 'cvs co (use attributes)' '
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.allbinary false &&
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 &&
+ marked_as cvswork textfile.c "" &&
+ marked_as cvswork binfile.bin -kb &&
+ marked_as cvswork .gitattributes "" &&
+ marked_as cvswork mixedUp.c "" &&
+ marked_as cvswork/subdir withCr.bin -kb &&
+ marked_as cvswork/subdir file.h "" &&
+ marked_as cvswork/subdir unspecified.other ""
+'
+
+test_expect_success 'adding files' '
+ cd cvswork/subdir &&
+ echo "more text" > src.c &&
+ GIT_CONFIG="$git_config" cvs -Q add src.c >cvs.log 2>&1 &&
+ marked_as . src.c "" &&
+ echo "psuedo-binary" > temp.bin &&
+ cd .. &&
+ GIT_CONFIG="$git_config" cvs -Q add subdir/temp.bin >cvs.log 2>&1 &&
+ marked_as subdir temp.bin "-kb" &&
+ cd subdir &&
+ GIT_CONFIG="$git_config" cvs -Q ci -m "adding files" >cvs.log 2>&1 &&
+ marked_as . temp.bin "-kb" &&
+ marked_as . src.c ""
+'
+
+cd "$WORKDIR"
+test_expect_success 'updating' '
+ git pull gitcvs.git &&
+ echo 'hi' > subdir/newfile.bin &&
+ echo 'junk' > subdir/file.h &&
+ echo 'hi' > subdir/newfile.c &&
+ echo 'hello' >> binfile.bin &&
+ git add subdir/newfile.bin subdir/file.h subdir/newfile.c binfile.bin &&
+ git commit -q -m "Add and change some files" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ cd .. &&
+ marked_as cvswork textfile.c "" &&
+ marked_as cvswork binfile.bin -kb &&
+ marked_as cvswork .gitattributes "" &&
+ marked_as cvswork mixedUp.c "" &&
+ marked_as cvswork/subdir withCr.bin -kb &&
+ marked_as cvswork/subdir file.h "" &&
+ marked_as cvswork/subdir unspecified.other "" &&
+ marked_as cvswork/subdir newfile.bin -kb &&
+ marked_as cvswork/subdir newfile.c "" &&
+ echo "File with embedded NUL: Q <- there" | q_to_nul > tmpExpect1 &&
+ echo "hello" >> tmpExpect1 &&
+ cmp cvswork/binfile.bin tmpExpect1
+'
+
+rm -rf cvswork
+test_expect_success 'cvs co (use attributes/guess)' '
+ GIT_DIR="$SERVERDIR" git config gitcvs.allbinary guess &&
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 &&
+ marked_as cvswork textfile.c "" &&
+ marked_as cvswork binfile.bin -kb &&
+ marked_as cvswork .gitattributes "" &&
+ marked_as cvswork mixedUp.c "" &&
+ marked_as cvswork/subdir withCr.bin -kb &&
+ marked_as cvswork/subdir file.h "" &&
+ marked_as cvswork/subdir unspecified.other "" &&
+ marked_as cvswork/subdir newfile.bin -kb &&
+ marked_as cvswork/subdir newfile.c ""
+'
+
+test_expect_success 'setup multi-line files' '
+ ( echo "line 1" &&
+ echo "line 2" &&
+ echo "line 3" &&
+ echo "line 4 with NUL: Q <-" ) | q_to_nul > multiline.c &&
+ git add multiline.c &&
+ ( echo "line 1" &&
+ echo "line 2" &&
+ echo "line 3" &&
+ echo "line 4" ) | q_to_nul > multilineTxt.c &&
+ git add multilineTxt.c &&
+ git commit -q -m "multiline files" &&
+ git push gitcvs.git >/dev/null
+'
+
+rm -rf cvswork
+test_expect_success 'cvs co (guess)' '
+ GIT_DIR="$SERVERDIR" git config --bool gitcvs.usecrlfattr false &&
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork master >cvs.log 2>&1 &&
+ marked_as cvswork textfile.c "" &&
+ marked_as cvswork binfile.bin -kb &&
+ marked_as cvswork .gitattributes "" &&
+ marked_as cvswork mixedUp.c -kb &&
+ marked_as cvswork multiline.c -kb &&
+ marked_as cvswork multilineTxt.c "" &&
+ marked_as cvswork/subdir withCr.bin -kb &&
+ marked_as cvswork/subdir file.h "" &&
+ marked_as cvswork/subdir unspecified.other "" &&
+ marked_as cvswork/subdir newfile.bin "" &&
+ marked_as cvswork/subdir newfile.c ""
+'
+
+test_expect_success 'cvs co another copy (guess)' '
+ GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 &&
+ marked_as cvswork2 textfile.c "" &&
+ marked_as cvswork2 binfile.bin -kb &&
+ marked_as cvswork2 .gitattributes "" &&
+ marked_as cvswork2 mixedUp.c -kb &&
+ marked_as cvswork2 multiline.c -kb &&
+ marked_as cvswork2 multilineTxt.c "" &&
+ marked_as cvswork2/subdir withCr.bin -kb &&
+ marked_as cvswork2/subdir file.h "" &&
+ marked_as cvswork2/subdir unspecified.other "" &&
+ marked_as cvswork2/subdir newfile.bin "" &&
+ marked_as cvswork2/subdir newfile.c ""
+'
+
+test_expect_success 'add text (guess)' '
+ cd cvswork &&
+ echo "simpleText" > simpleText.c &&
+ GIT_CONFIG="$git_config" cvs -Q add simpleText.c &&
+ cd .. &&
+ marked_as cvswork simpleText.c ""
+'
+
+test_expect_success 'add bin (guess)' '
+ cd cvswork &&
+ echo "simpleBin: NUL: Q <- there" | q_to_nul > simpleBin.bin &&
+ GIT_CONFIG="$git_config" cvs -Q add simpleBin.bin &&
+ cd .. &&
+ marked_as cvswork simpleBin.bin -kb
+'
+
+test_expect_success 'remove files (guess)' '
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q rm -f subdir/file.h &&
+ cd subdir &&
+ GIT_CONFIG="$git_config" cvs -Q rm -f withCr.bin &&
+ cd ../.. &&
+ marked_as cvswork/subdir withCr.bin -kb &&
+ marked_as cvswork/subdir file.h ""
+'
+
+test_expect_success 'cvs ci (guess)' '
+ cd cvswork &&
+ GIT_CONFIG="$git_config" cvs -Q ci -m "add/rm files" >cvs.log 2>&1 &&
+ cd .. &&
+ marked_as cvswork textfile.c "" &&
+ marked_as cvswork binfile.bin -kb &&
+ marked_as cvswork .gitattributes "" &&
+ marked_as cvswork mixedUp.c -kb &&
+ marked_as cvswork multiline.c -kb &&
+ marked_as cvswork multilineTxt.c "" &&
+ not_present cvswork/subdir withCr.bin &&
+ not_present cvswork/subdir file.h &&
+ marked_as cvswork/subdir unspecified.other "" &&
+ marked_as cvswork/subdir newfile.bin "" &&
+ marked_as cvswork/subdir newfile.c "" &&
+ marked_as cvswork simpleBin.bin -kb &&
+ marked_as cvswork simpleText.c ""
+'
+
+test_expect_success 'update subdir of other copy (guess)' '
+ cd cvswork2/subdir &&
+ GIT_CONFIG="$git_config" cvs -Q update &&
+ cd ../.. &&
+ marked_as cvswork2 textfile.c "" &&
+ marked_as cvswork2 binfile.bin -kb &&
+ marked_as cvswork2 .gitattributes "" &&
+ marked_as cvswork2 mixedUp.c -kb &&
+ marked_as cvswork2 multiline.c -kb &&
+ marked_as cvswork2 multilineTxt.c "" &&
+ not_present cvswork2/subdir withCr.bin &&
+ not_present cvswork2/subdir file.h &&
+ marked_as cvswork2/subdir unspecified.other "" &&
+ marked_as cvswork2/subdir newfile.bin "" &&
+ marked_as cvswork2/subdir newfile.c "" &&
+ not_present cvswork2 simpleBin.bin &&
+ not_present cvswork2 simpleText.c
+'
+
+echo "starting update/merge" >> "${WORKDIR}/marked.log"
+test_expect_success 'update/merge full other copy (guess)' '
+ git pull gitcvs.git master &&
+ sed "s/3/replaced_3/" < multilineTxt.c > ml.temp &&
+ mv ml.temp multilineTxt.c &&
+ git add multilineTxt.c &&
+ git commit -q -m "modify multiline file" >> "${WORKDIR}/marked.log" &&
+ git push gitcvs.git >/dev/null &&
+ cd cvswork2 &&
+ sed "s/1/replaced_1/" < multilineTxt.c > ml.temp &&
+ mv ml.temp multilineTxt.c &&
+ GIT_CONFIG="$git_config" cvs update > cvs.log 2>&1 &&
+ cd .. &&
+ marked_as cvswork2 textfile.c "" &&
+ marked_as cvswork2 binfile.bin -kb &&
+ marked_as cvswork2 .gitattributes "" &&
+ marked_as cvswork2 mixedUp.c -kb &&
+ marked_as cvswork2 multiline.c -kb &&
+ marked_as cvswork2 multilineTxt.c "" &&
+ not_present cvswork2/subdir withCr.bin &&
+ not_present cvswork2/subdir file.h &&
+ marked_as cvswork2/subdir unspecified.other "" &&
+ marked_as cvswork2/subdir newfile.bin "" &&
+ marked_as cvswork2/subdir newfile.c "" &&
+ marked_as cvswork2 simpleBin.bin -kb &&
+ marked_as cvswork2 simpleText.c "" &&
+ echo "line replaced_1" > tmpExpect2 &&
+ echo "line 2" >> tmpExpect2 &&
+ echo "line replaced_3" >> tmpExpect2 &&
+ echo "line 4" | q_to_nul >> tmpExpect2 &&
+ cmp cvswork2/multilineTxt.c tmpExpect2
+'
+
+test_done
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 061a2596d3..2fc7fdb124 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -9,72 +9,8 @@ This test runs gitweb (git web interface) as CGI script from
commandline, and checks that it would not write any errors
or warnings to log.'
-gitweb_init () {
- cat >gitweb_config.perl <<EOF
-#!/usr/bin/perl
-
-# gitweb configuration for tests
-
-our \$version = "current";
-our \$GIT = "git";
-our \$projectroot = "$(pwd)";
-our \$project_maxdepth = 8;
-our \$home_link_str = "projects";
-our \$site_name = "[localhost]";
-our \$site_header = "";
-our \$site_footer = "";
-our \$home_text = "indextext.html";
-our @stylesheets = ("file:///$(pwd)/../../gitweb/gitweb.css");
-our \$logo = "file:///$(pwd)/../../gitweb/git-logo.png";
-our \$favicon = "file:///$(pwd)/../../gitweb/git-favicon.png";
-our \$projects_list = "";
-our \$export_ok = "";
-our \$strict_export = "";
-EOF
-
- cat >.git/description <<EOF
-$0 test repository
-EOF
-}
-
-gitweb_run () {
- export GATEWAY_INTERFACE="CGI/1.1"
- export HTTP_ACCEPT="*/*"
- export REQUEST_METHOD="GET"
- export QUERY_STRING=""$1""
- export PATH_INFO=""$2""
-
- export GITWEB_CONFIG=$(pwd)/gitweb_config.perl
-
- # some of git commands write to STDERR on error, but this is not
- # written to web server logs, so we are not interested in that:
- # we are interested only in properly formatted errors/warnings
- rm -f gitweb.log &&
- perl -- $(pwd)/../../gitweb/gitweb.perl \
- >/dev/null 2>gitweb.log &&
- if grep -q -s "^[[]" gitweb.log >/dev/null; then false; else true; fi
-
- # gitweb.log is left for debugging
-}
-
-safe_chmod () {
- chmod "$1" "$2" &&
- if [ "$(git config --get core.filemode)" = false ]
- then
- git update-index --chmod="$1" "$2"
- fi
-}
-
-. ./test-lib.sh
-
-perl -MEncode -e 'decode_utf8("", Encode::FB_CROAK)' >/dev/null 2>&1 || {
- test_expect_success 'skipping gitweb tests, perl version is too old' :
- test_done
- exit
-}
-
-gitweb_init
+. ./gitweb-lib.sh
# ----------------------------------------------------------------------
# no commits (empty, just initialized repository)
@@ -237,7 +173,7 @@ test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): mode change' \
- 'safe_chmod +x new_file &&
+ 'test_chmod +x new_file &&
git commit -a -m "Mode changed." &&
gitweb_run "p=.git;a=commitdiff"'
test_debug 'cat gitweb.log'
@@ -249,7 +185,7 @@ test_expect_success \
gitweb_run "p=.git;a=commitdiff"'
test_debug 'cat gitweb.log'
-test_expect_success \
+test_expect_success SYMLINKS \
'commitdiff(0): file to symlink' \
'rm renamed_file &&
ln -s file renamed_file &&
@@ -276,7 +212,7 @@ test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): mode change and modified' \
'echo "New line" >> file2 &&
- safe_chmod +x file2 &&
+ test_chmod +x file2 &&
git commit -a -m "Mode change and modification." &&
gitweb_run "p=.git;a=commitdiff"'
test_debug 'cat gitweb.log'
@@ -303,7 +239,7 @@ test_expect_success \
'commitdiff(0): renamed, mode change and modified' \
'git mv file3 file2 &&
echo "Propter nomen suum." >> file2 &&
- safe_chmod +x file2 &&
+ test_chmod +x file2 &&
git commit -a -m "File rename, mode change and modification." &&
gitweb_run "p=.git;a=commitdiff"'
test_debug 'cat gitweb.log'
@@ -311,7 +247,7 @@ test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# commitdiff testing (taken from t4114-apply-typechange.sh)
-test_expect_success 'setup typechange commits' '
+test_expect_success SYMLINKS 'setup typechange commits' '
echo "hello world" > foo &&
echo "hi planet" > bar &&
git update-index --add foo bar &&
@@ -420,10 +356,15 @@ test_expect_success \
git add 03-new &&
git mv 04-rename-from 04-rename-to &&
echo "Changed" >> 04-rename-to &&
- safe_chmod +x 05-mode-change &&
- rm -f 06-file-or-symlink && ln -s 01-change 06-file-or-symlink &&
+ test_chmod +x 05-mode-change &&
+ rm -f 06-file-or-symlink &&
+ if test_have_prereq SYMLINKS; then
+ ln -s 01-change 06-file-or-symlink
+ else
+ printf %s 01-change > 06-file-or-symlink
+ fi &&
echo "Changed and have mode changed" > 07-change-mode-change &&
- safe_chmod +x 07-change-mode-change &&
+ test_chmod +x 07-change-mode-change &&
git commit -a -m "Large commit" &&
git checkout master'
@@ -500,6 +441,55 @@ test_expect_success \
test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
+# path_info links
+test_expect_success \
+ 'path_info: project' \
+ 'gitweb_run "" "/.git"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch' \
+ 'gitweb_run "" "/.git/b"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch:file' \
+ 'gitweb_run "" "/.git/master:file"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch:dir/' \
+ 'gitweb_run "" "/.git/master:foo/"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch:file (non-existent)' \
+ 'gitweb_run "" "/.git/master:non-existent"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch:dir/ (non-existent)' \
+ 'gitweb_run "" "/.git/master:non-existent/"'
+test_debug 'cat gitweb.log'
+
+
+test_expect_success \
+ 'path_info: project/branch:/file' \
+ 'gitweb_run "" "/.git/master:/file"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/:/file (implicit HEAD)' \
+ 'gitweb_run "" "/.git/:/file"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/:/ (implicit HEAD, top tree)' \
+ 'gitweb_run "" "/.git/:/"'
+test_debug 'cat gitweb.log'
+
+
+# ----------------------------------------------------------------------
# feed generation
test_expect_success \
@@ -522,20 +512,20 @@ test_debug 'cat gitweb.log'
test_expect_success \
'encode(commit): utf8' \
- '. ../t3901-utf8.txt &&
+ '. "$TEST_DIRECTORY"/t3901-utf8.txt &&
echo "UTF-8" >> file &&
git add file &&
- git commit -F ../t3900/1-UTF-8.txt &&
+ git commit -F "$TEST_DIRECTORY"/t3900/1-UTF-8.txt &&
gitweb_run "p=.git;a=commit"'
test_debug 'cat gitweb.log'
test_expect_success \
'encode(commit): iso-8859-1' \
- '. ../t3901-8859-1.txt &&
+ '. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
echo "ISO-8859-1" >> file &&
git add file &&
git config i18n.commitencoding ISO-8859-1 &&
- git commit -F ../t3900/ISO-8859-1.txt &&
+ git commit -F "$TEST_DIRECTORY"/t3900/ISO8859-1.txt &&
git config --unset i18n.commitencoding &&
gitweb_run "p=.git;a=commit"'
test_debug 'cat gitweb.log'
@@ -605,20 +595,48 @@ cat >>gitweb_config.perl <<EOF
\$feature{'blame'}{'override'} = 1;
\$feature{'snapshot'}{'override'} = 1;
+\$feature{'avatar'}{'override'} = 1;
EOF
test_expect_success \
+ 'config override: tree view, features not overridden in repo config' \
+ 'gitweb_run "p=.git;a=tree"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
'config override: tree view, features disabled in repo config' \
'git config gitweb.blame no &&
git config gitweb.snapshot none &&
+ git config gitweb.avatar gravatar &&
gitweb_run "p=.git;a=tree"'
test_debug 'cat gitweb.log'
test_expect_success \
- 'config override: tree view, features enabled in repo config' \
+ 'config override: tree view, features enabled in repo config (1)' \
'git config gitweb.blame yes &&
git config gitweb.snapshot "zip,tgz, tbz2" &&
gitweb_run "p=.git;a=tree"'
test_debug 'cat gitweb.log'
+cat >.git/config <<\EOF
+# testing noval and alternate separator
+[gitweb]
+ blame
+ snapshot = zip tgz
+EOF
+test_expect_success \
+ 'config override: tree view, features enabled in repo config (2)' \
+ 'gitweb_run "p=.git;a=tree"'
+test_debug 'cat gitweb.log'
+
+# ----------------------------------------------------------------------
+# non-ASCII in README.html
+
+test_expect_success \
+ 'README.html with non-ASCII characters (utf-8)' \
+ 'echo "<b>UTF-8 example:</b><br />" > .git/README.html &&
+ cat "$TEST_DIRECTORY"/t3900/1-UTF-8.txt >> .git/README.html &&
+ gitweb_run "p=.git;a=summary"'
+test_debug 'cat gitweb.log'
+
test_done
diff --git a/t/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh
new file mode 100755
index 0000000000..0688a57e1d
--- /dev/null
+++ b/t/t9501-gitweb-standalone-http-status.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Mark Rada
+#
+
+test_description='gitweb as standalone script (http status tests).
+
+This test runs gitweb (git web interface) as a CGI script from the
+commandline, and checks that it returns the expected HTTP status
+code and message.'
+
+
+. ./gitweb-lib.sh
+
+# ----------------------------------------------------------------------
+# snapshot settings
+
+test_commit \
+ 'SnapshotTests' \
+ 'i can has snapshot?'
+
+cat >>gitweb_config.perl <<\EOF
+$feature{'snapshot'}{'override'} = 0;
+EOF
+
+test_expect_success \
+ 'snapshots: tgz only default format enabled' \
+ 'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tgz" &&
+ grep "Status: 200 OK" gitweb.output &&
+ gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tbz2" &&
+ grep "403 - Unsupported snapshot format" gitweb.output &&
+ gitweb_run "p=.git;a=snapshot;h=HEAD;sf=txz" &&
+ grep "403 - Snapshot format not allowed" gitweb.output &&
+ gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" &&
+ grep "403 - Unsupported snapshot format" gitweb.output'
+test_debug 'cat gitweb.output'
+
+
+cat >>gitweb_config.perl <<\EOF
+$feature{'snapshot'}{'default'} = ['tgz','tbz2','txz','zip'];
+EOF
+
+test_expect_success \
+ 'snapshots: all enabled in default, use default disabled value' \
+ 'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tgz" &&
+ grep "Status: 200 OK" gitweb.output &&
+ gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tbz2" &&
+ grep "Status: 200 OK" gitweb.output &&
+ gitweb_run "p=.git;a=snapshot;h=HEAD;sf=txz" &&
+ grep "403 - Snapshot format not allowed" gitweb.output &&
+ gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" &&
+ grep "Status: 200 OK" gitweb.output'
+test_debug 'cat gitweb.output'
+
+
+cat >>gitweb_config.perl <<\EOF
+$known_snapshot_formats{'zip'}{'disabled'} = 1;
+EOF
+
+test_expect_success \
+ 'snapshots: zip explicitly disabled' \
+ 'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" &&
+ grep "403 - Snapshot format not allowed" gitweb.output'
+test_debug 'cat gitweb.output'
+
+
+cat >>gitweb_config.perl <<\EOF
+$known_snapshot_formats{'tgz'}{'disabled'} = 0;
+EOF
+
+test_expect_success \
+ 'snapshots: tgz explicitly enabled' \
+ 'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tgz" &&
+ grep "Status: 200 OK" gitweb.output'
+test_debug 'cat gitweb.output'
+
+
+# ----------------------------------------------------------------------
+# snapshot hash ids
+
+test_expect_success 'snapshots: good tree-ish id' '
+ gitweb_run "p=.git;a=snapshot;h=master;sf=tgz" &&
+ grep "Status: 200 OK" gitweb.output
+'
+test_debug 'cat gitweb.output'
+
+test_expect_success 'snapshots: bad tree-ish id' '
+ gitweb_run "p=.git;a=snapshot;h=frizzumFrazzum;sf=tgz" &&
+ grep "404 - Object does not exist" gitweb.output
+'
+test_debug 'cat gitweb.output'
+
+test_expect_success 'snapshots: bad tree-ish id (tagged object)' '
+ echo object > tag-object &&
+ git add tag-object &&
+ git commit -m "Object to be tagged" &&
+ git tag tagged-object `git hash-object tag-object` &&
+ gitweb_run "p=.git;a=snapshot;h=tagged-object;sf=tgz" &&
+ grep "400 - Object is not a tree-ish" gitweb.output
+'
+test_debug 'cat gitweb.output'
+
+test_expect_success 'snapshots: good object id' '
+ ID=`git rev-parse --verify HEAD` &&
+ gitweb_run "p=.git;a=snapshot;h=$ID;sf=tgz" &&
+ grep "Status: 200 OK" gitweb.output
+'
+test_debug 'cat gitweb.output'
+
+test_expect_success 'snapshots: bad object id' '
+ gitweb_run "p=.git;a=snapshot;h=abcdef01234;sf=tgz" &&
+ grep "404 - Object does not exist" gitweb.output
+'
+test_debug 'cat gitweb.output'
+
+
+test_done
diff --git a/t/t9502-gitweb-standalone-parse-output.sh b/t/t9502-gitweb-standalone-parse-output.sh
new file mode 100755
index 0000000000..dd83890001
--- /dev/null
+++ b/t/t9502-gitweb-standalone-parse-output.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Mark Rada
+#
+
+test_description='gitweb as standalone script (parsing script output).
+
+This test runs gitweb (git web interface) as a CGI script from the
+commandline, and checks that it produces the correct output, either
+in the HTTP header or the actual script output.'
+
+
+. ./gitweb-lib.sh
+
+# ----------------------------------------------------------------------
+# snapshot file name and prefix
+
+cat >>gitweb_config.perl <<\EOF
+
+$known_snapshot_formats{'tar'} = {
+ 'display' => 'tar',
+ 'type' => 'application/x-tar',
+ 'suffix' => '.tar',
+ 'format' => 'tar',
+};
+
+$feature{'snapshot'}{'default'} = ['tar'];
+EOF
+
+# Call check_snapshot with the arguments "<basename> [<prefix>]"
+#
+# This will check that gitweb HTTP header contains proposed filename
+# as <basename> with '.tar' suffix added, and that generated tarfile
+# (gitweb message body) has <prefix> as prefix for al files in tarfile
+#
+# <prefix> default to <basename>
+check_snapshot () {
+ basename=$1
+ prefix=${2:-"$1"}
+ echo "basename=$basename"
+ grep "filename=.*$basename.tar" gitweb.headers >/dev/null 2>&1 &&
+ "$TAR" tf gitweb.body >file_list &&
+ ! grep -v "^$prefix/" file_list
+}
+
+test_expect_success setup '
+ test_commit first foo &&
+ git branch xx/test &&
+ FULL_ID=$(git rev-parse --verify HEAD) &&
+ SHORT_ID=$(git rev-parse --verify --short=7 HEAD)
+'
+test_debug '
+ echo "FULL_ID = $FULL_ID"
+ echo "SHORT_ID = $SHORT_ID"
+'
+
+test_expect_success 'snapshot: full sha1' '
+ gitweb_run "p=.git;a=snapshot;h=$FULL_ID;sf=tar" &&
+ check_snapshot ".git-$SHORT_ID"
+'
+test_debug 'cat gitweb.headers && cat file_list'
+
+test_expect_success 'snapshot: shortened sha1' '
+ gitweb_run "p=.git;a=snapshot;h=$SHORT_ID;sf=tar" &&
+ check_snapshot ".git-$SHORT_ID"
+'
+test_debug 'cat gitweb.headers && cat file_list'
+
+test_expect_success 'snapshot: almost full sha1' '
+ ID=$(git rev-parse --short=30 HEAD) &&
+ gitweb_run "p=.git;a=snapshot;h=$ID;sf=tar" &&
+ check_snapshot ".git-$SHORT_ID"
+'
+test_debug 'cat gitweb.headers && cat file_list'
+
+test_expect_success 'snapshot: HEAD' '
+ gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tar" &&
+ check_snapshot ".git-HEAD-$SHORT_ID"
+'
+test_debug 'cat gitweb.headers && cat file_list'
+
+test_expect_success 'snapshot: short branch name (master)' '
+ gitweb_run "p=.git;a=snapshot;h=master;sf=tar" &&
+ ID=$(git rev-parse --verify --short=7 master) &&
+ check_snapshot ".git-master-$ID"
+'
+test_debug 'cat gitweb.headers && cat file_list'
+
+test_expect_success 'snapshot: short tag name (first)' '
+ gitweb_run "p=.git;a=snapshot;h=first;sf=tar" &&
+ ID=$(git rev-parse --verify --short=7 first) &&
+ check_snapshot ".git-first-$ID"
+'
+test_debug 'cat gitweb.headers && cat file_list'
+
+test_expect_success 'snapshot: full branch name (refs/heads/master)' '
+ gitweb_run "p=.git;a=snapshot;h=refs/heads/master;sf=tar" &&
+ ID=$(git rev-parse --verify --short=7 master) &&
+ check_snapshot ".git-master-$ID"
+'
+test_debug 'cat gitweb.headers && cat file_list'
+
+test_expect_success 'snapshot: full tag name (refs/tags/first)' '
+ gitweb_run "p=.git;a=snapshot;h=refs/tags/first;sf=tar" &&
+ check_snapshot ".git-first"
+'
+test_debug 'cat gitweb.headers && cat file_list'
+
+test_expect_success 'snapshot: hierarchical branch name (xx/test)' '
+ gitweb_run "p=.git;a=snapshot;h=xx/test;sf=tar" &&
+ ! grep "filename=.*/" gitweb.headers
+'
+test_debug 'cat gitweb.headers'
+
+test_done
diff --git a/t/t9600-cvsimport.sh b/t/t9600-cvsimport.sh
index 00a74ee738..363345faef 100755
--- a/t/t9600-cvsimport.sh
+++ b/t/t9600-cvsimport.sh
@@ -1,43 +1,22 @@
#!/bin/sh
-test_description='git-cvsimport basic tests'
-. ./test-lib.sh
+test_description='git cvsimport basic tests'
+. ./lib-cvs.sh
-CVSROOT=$(pwd)/cvsroot
-export CVSROOT
-# for clean cvsps cache
-HOME=$(pwd)
-export HOME
-
-if ! type cvs >/dev/null 2>&1
-then
- say 'skipping cvsimport tests, cvs not found'
+if ! test_have_prereq PERL; then
+ say 'skipping git cvsimport tests, perl not available'
test_done
- exit
fi
-cvsps_version=`cvsps -h 2>&1 | sed -ne 's/cvsps version //p'`
-case "$cvsps_version" in
-2.1)
- ;;
-'')
- say 'skipping cvsimport tests, cvsps not found'
- test_done
- exit
- ;;
-*)
- say 'skipping cvsimport tests, cvsps too old'
- test_done
- exit
- ;;
-esac
+CVSROOT=$(pwd)/cvsroot
+export CVSROOT
-test_expect_success 'setup cvsroot' 'cvs init'
+test_expect_success 'setup cvsroot' '$CVS init'
test_expect_success 'setup a cvs module' '
- mkdir $CVSROOT/module &&
- cvs co -d module-cvs module &&
+ mkdir "$CVSROOT/module" &&
+ $CVS co -d module-cvs module &&
cd module-cvs &&
cat <<EOF >o_fortuna &&
O Fortuna
@@ -56,20 +35,20 @@ egestatem,
potestatem
dissolvit ut glaciem.
EOF
- cvs add o_fortuna &&
+ $CVS add o_fortuna &&
cat <<EOF >message &&
add "O Fortuna" lyrics
These public domain lyrics make an excellent sample text.
EOF
- cvs commit -F message &&
+ $CVS commit -F message &&
cd ..
'
test_expect_success 'import a trivial module' '
git cvsimport -a -z 0 -C module-git module &&
- git diff module-cvs/o_fortuna module-git/o_fortuna
+ test_cmp module-cvs/o_fortuna module-git/o_fortuna
'
@@ -100,7 +79,7 @@ translate to English
My Latin is terrible.
EOF
- cvs commit -F message &&
+ $CVS commit -F message &&
cd ..
'
@@ -110,7 +89,7 @@ test_expect_success 'update git module' '
git cvsimport -a -z 0 module &&
git merge origin &&
cd .. &&
- git diff module-cvs/o_fortuna module-git/o_fortuna
+ test_cmp module-cvs/o_fortuna module-git/o_fortuna
'
@@ -118,8 +97,8 @@ test_expect_success 'update cvs module' '
cd module-cvs &&
echo 1 >tick &&
- cvs add tick &&
- cvs commit -m 1
+ $CVS add tick &&
+ $CVS commit -m 1
cd ..
'
@@ -131,20 +110,22 @@ test_expect_success 'cvsimport.module config works' '
git cvsimport -a -z0 &&
git merge origin &&
cd .. &&
- git diff module-cvs/tick module-git/tick
+ test_cmp module-cvs/tick module-git/tick
'
test_expect_success 'import from a CVS working tree' '
- cvs co -d import-from-wt module &&
+ $CVS co -d import-from-wt module &&
cd import-from-wt &&
git cvsimport -a -z0 &&
echo 1 >expect &&
git log -1 --pretty=format:%s%n >actual &&
- git diff actual expect &&
+ test_cmp actual expect &&
cd ..
'
+test_expect_success 'test entire HEAD' 'test_cmp_branch_tree master'
+
test_done
diff --git a/t/t9601-cvsimport-vendor-branch.sh b/t/t9601-cvsimport-vendor-branch.sh
new file mode 100755
index 0000000000..3afaf56526
--- /dev/null
+++ b/t/t9601-cvsimport-vendor-branch.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+# Description of the files in the repository:
+#
+# imported-once.txt:
+#
+# Imported once. 1.1 and 1.1.1.1 should be identical.
+#
+# imported-twice.txt:
+#
+# Imported twice. HEAD should reflect the contents of the
+# second import (i.e., have the same contents as 1.1.1.2).
+#
+# imported-modified.txt:
+#
+# Imported, then modified on HEAD. HEAD should reflect the
+# modification.
+#
+# imported-modified-imported.txt:
+#
+# Imported, then modified on HEAD, then imported again.
+#
+# added-imported.txt,v:
+#
+# Added with 'cvs add' to create 1.1, then imported with
+# completely different contents to create 1.1.1.1, therefore the
+# vendor branch was never the default branch.
+#
+# imported-anonymously.txt:
+#
+# Like imported-twice.txt, but with a vendor branch whose branch
+# tag has been removed.
+
+test_description='git cvsimport handling of vendor branches'
+. ./lib-cvs.sh
+
+CVSROOT="$TEST_DIRECTORY"/t9601/cvsroot
+export CVSROOT
+
+test_expect_success 'import a module with a vendor branch' '
+
+ git cvsimport -C module-git module
+
+'
+
+test_expect_success 'check HEAD out of cvs repository' 'test_cvs_co master'
+
+test_expect_success 'check master out of git repository' 'test_git_co master'
+
+test_expect_success 'check a file that was imported once' '
+
+ test_cmp_branch_file master imported-once.txt
+
+'
+
+test_expect_failure 'check a file that was imported twice' '
+
+ test_cmp_branch_file master imported-twice.txt
+
+'
+
+test_expect_success 'check a file that was imported then modified on HEAD' '
+
+ test_cmp_branch_file master imported-modified.txt
+
+'
+
+test_expect_success 'check a file that was imported, modified, then imported again' '
+
+ test_cmp_branch_file master imported-modified-imported.txt
+
+'
+
+test_expect_success 'check a file that was added to HEAD then imported' '
+
+ test_cmp_branch_file master added-imported.txt
+
+'
+
+test_expect_success 'a vendor branch whose tag has been removed' '
+
+ test_cmp_branch_file master imported-anonymously.txt
+
+'
+
+test_done
diff --git a/t/t9601/cvsroot/.gitattributes b/t/t9601/cvsroot/.gitattributes
new file mode 100644
index 0000000000..562b12e16e
--- /dev/null
+++ b/t/t9601/cvsroot/.gitattributes
@@ -0,0 +1 @@
+* -whitespace
diff --git a/t/t9601/cvsroot/CVSROOT/.gitignore b/t/t9601/cvsroot/CVSROOT/.gitignore
new file mode 100644
index 0000000000..3bb9b34173
--- /dev/null
+++ b/t/t9601/cvsroot/CVSROOT/.gitignore
@@ -0,0 +1,2 @@
+history
+val-tags
diff --git a/t/t9601/cvsroot/module/added-imported.txt,v b/t/t9601/cvsroot/module/added-imported.txt,v
new file mode 100644
index 0000000000..5f83072ea4
--- /dev/null
+++ b/t/t9601/cvsroot/module/added-imported.txt,v
@@ -0,0 +1,44 @@
+head 1.1;
+access;
+symbols
+ vtag-4:1.1.1.1
+ vbranchA:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.1
+date 2004.02.09.15.43.15; author kfogel; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2004.02.09.15.43.16; author kfogel; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.1
+log
+@Add a file to the working copy.
+@
+text
+@Adding this file, before importing it with different contents.
+@
+
+
+1.1.1.1
+log
+@Import (vbranchA, vtag-4).
+@
+text
+@d1 1
+a1 1
+This is vtag-4 (on vbranchA) of added-then-imported.txt.
+@
+
diff --git a/t/t9601/cvsroot/module/imported-anonymously.txt,v b/t/t9601/cvsroot/module/imported-anonymously.txt,v
new file mode 100644
index 0000000000..55e1b0ca5d
--- /dev/null
+++ b/t/t9601/cvsroot/module/imported-anonymously.txt,v
@@ -0,0 +1,42 @@
+head 1.1;
+branch 1.1.1;
+access;
+symbols
+ vtag-1:1.1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@This is vtag-1 (on vbranchA) of imported-anonymously.txt.
+@
+
+
+1.1.1.1
+log
+@Import (vbranchA, vtag-1).
+@
+text
+@@
+
+
diff --git a/t/t9601/cvsroot/module/imported-modified-imported.txt,v b/t/t9601/cvsroot/module/imported-modified-imported.txt,v
new file mode 100644
index 0000000000..e5830aeb37
--- /dev/null
+++ b/t/t9601/cvsroot/module/imported-modified-imported.txt,v
@@ -0,0 +1,76 @@
+head 1.2;
+access;
+symbols
+ vtag-2:1.1.1.2
+ vtag-1:1.1.1.1
+ vbranchA:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.2
+date 2004.02.09.15.43.14; author kfogel; state Exp;
+branches;
+next 1.1;
+
+1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches;
+next 1.1.1.2;
+
+1.1.1.2
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.2
+log
+@First regular commit, to imported-modified-imported.txt, on HEAD.
+@
+text
+@This is a modification of imported-modified-imported.txt on HEAD.
+It should supersede the version from the vendor branch.
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d1 2
+a2 1
+This is vtag-1 (on vbranchA) of imported-modified-imported.txt.
+@
+
+
+1.1.1.1
+log
+@Import (vbranchA, vtag-1).
+@
+text
+@@
+
+
+1.1.1.2
+log
+@Import (vbranchA, vtag-2).
+@
+text
+@d1 1
+a1 1
+This is vtag-2 (on vbranchA) of imported-modified-imported.txt.
+@
+
+
diff --git a/t/t9601/cvsroot/module/imported-modified.txt,v b/t/t9601/cvsroot/module/imported-modified.txt,v
new file mode 100644
index 0000000000..bbcfe447b9
--- /dev/null
+++ b/t/t9601/cvsroot/module/imported-modified.txt,v
@@ -0,0 +1,59 @@
+head 1.2;
+access;
+symbols
+ vtag-1:1.1.1.1
+ vbranchA:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.2
+date 2004.02.09.15.43.14; author kfogel; state Exp;
+branches;
+next 1.1;
+
+1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.2
+log
+@Commit on HEAD.
+@
+text
+@This is a modification of imported-modified.txt on HEAD.
+It should supersede the version from the vendor branch.
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d1 2
+a2 1
+This is vtag-1 (on vbranchA) of imported-modified.txt.
+@
+
+
+1.1.1.1
+log
+@Import (vbranchA, vtag-1).
+@
+text
+@@
+
+
diff --git a/t/t9601/cvsroot/module/imported-once.txt,v b/t/t9601/cvsroot/module/imported-once.txt,v
new file mode 100644
index 0000000000..c5dd82b12d
--- /dev/null
+++ b/t/t9601/cvsroot/module/imported-once.txt,v
@@ -0,0 +1,43 @@
+head 1.1;
+branch 1.1.1;
+access;
+symbols
+ vtag-1:1.1.1.1
+ vbranchA:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@This is vtag-1 (on vbranchA) of imported-once.txt.
+@
+
+
+1.1.1.1
+log
+@Import (vbranchA, vtag-1).
+@
+text
+@@
+
+
diff --git a/t/t9601/cvsroot/module/imported-twice.txt,v b/t/t9601/cvsroot/module/imported-twice.txt,v
new file mode 100644
index 0000000000..d1f3f1b344
--- /dev/null
+++ b/t/t9601/cvsroot/module/imported-twice.txt,v
@@ -0,0 +1,60 @@
+head 1.1;
+branch 1.1.1;
+access;
+symbols
+ vtag-2:1.1.1.2
+ vtag-1:1.1.1.1
+ vbranchA:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches;
+next 1.1.1.2;
+
+1.1.1.2
+date 2004.02.09.15.43.13; author kfogel; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@This is vtag-1 (on vbranchA) of imported-twice.txt.
+@
+
+
+1.1.1.1
+log
+@Import (vbranchA, vtag-1).
+@
+text
+@@
+
+
+1.1.1.2
+log
+@Import (vbranchA, vtag-2).
+@
+text
+@d1 1
+a1 1
+This is vtag-2 (on vbranchA) of imported-twice.txt.
+@
+
+
diff --git a/t/t9602-cvsimport-branches-tags.sh b/t/t9602-cvsimport-branches-tags.sh
new file mode 100755
index 0000000000..67878b2d0c
--- /dev/null
+++ b/t/t9602-cvsimport-branches-tags.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+# A description of the repository used for this test can be found in
+# t9602/README.
+
+test_description='git cvsimport handling of branches and tags'
+. ./lib-cvs.sh
+
+CVSROOT="$TEST_DIRECTORY"/t9602/cvsroot
+export CVSROOT
+
+test_expect_success 'import module' '
+
+ git cvsimport -C module-git module
+
+'
+
+test_expect_success 'test branch master' '
+
+ test_cmp_branch_tree master
+
+'
+
+test_expect_success 'test branch vendorbranch' '
+
+ test_cmp_branch_tree vendorbranch
+
+'
+
+test_expect_failure 'test branch B_FROM_INITIALS' '
+
+ test_cmp_branch_tree B_FROM_INITIALS
+
+'
+
+test_expect_failure 'test branch B_FROM_INITIALS_BUT_ONE' '
+
+ test_cmp_branch_tree B_FROM_INITIALS_BUT_ONE
+
+'
+
+test_expect_failure 'test branch B_MIXED' '
+
+ test_cmp_branch_tree B_MIXED
+
+'
+
+test_expect_success 'test branch B_SPLIT' '
+
+ test_cmp_branch_tree B_SPLIT
+
+'
+
+test_expect_failure 'test tag vendortag' '
+
+ test_cmp_branch_tree vendortag
+
+'
+
+test_expect_success 'test tag T_ALL_INITIAL_FILES' '
+
+ test_cmp_branch_tree T_ALL_INITIAL_FILES
+
+'
+
+test_expect_failure 'test tag T_ALL_INITIAL_FILES_BUT_ONE' '
+
+ test_cmp_branch_tree T_ALL_INITIAL_FILES_BUT_ONE
+
+'
+
+test_expect_failure 'test tag T_MIXED' '
+
+ test_cmp_branch_tree T_MIXED
+
+'
+
+
+test_done
diff --git a/t/t9602/README b/t/t9602/README
new file mode 100644
index 0000000000..c231e0f26f
--- /dev/null
+++ b/t/t9602/README
@@ -0,0 +1,62 @@
+This repository is for testing the ability to group revisions
+correctly along tags and branches. Here is its history:
+
+ 1. The initial import (revision 1.1 of everybody) created a
+ directory structure with a file named `default' in each dir:
+
+ ./
+ default
+ sub1/default
+ subsubA/default
+ subsubB/default
+ sub2/default
+ subsubA/default
+ sub3/default
+
+ 2. Then tagged everyone with T_ALL_INITIAL_FILES.
+
+ 3. Then tagged everyone except sub1/subsubB/default with
+ T_ALL_INITIAL_FILES_BUT_ONE.
+
+ 4. Then created branch B_FROM_INITIALS on everyone.
+
+ 5. Then created branch B_FROM_INITIALS_BUT_ONE on everyone except
+ /sub1/subsubB/default.
+
+ 6. Then committed modifications to two files: sub3/default, and
+ sub1/subsubA/default.
+
+ 7. Then committed a modification to all 7 files.
+
+ 8. Then backdated sub3/default to revision 1.2, and
+ sub2/subsubA/default to revision 1.1, and tagged with T_MIXED.
+
+ 9. Same as 8, but tagged with -b to create branch B_MIXED.
+
+ 10. Switched the working copy to B_MIXED, and added
+ sub2/branch_B_MIXED_only. (That's why the RCS file is in
+ sub2/Attic/ -- it never existed on trunk.)
+
+ 11. In one commit, modified default, sub1/default, and
+ sub2/subsubA/default, on branch B_MIXED.
+
+ 12. Did "cvs up -A" on sub2/default, then in one commit, made a
+ change to sub2/default and sub2/branch_B_MIXED_only. So this
+ commit should be spread between the branch and the trunk.
+
+ 13. Do "cvs up -A" to get everyone back to trunk, then make a new
+ branch B_SPLIT on everyone except sub1/subsubB/default,v.
+
+ 14. Switch to branch B_SPLIT (see sub1/subsubB/default disappear)
+ and commit a change that affects everyone except sub3/default.
+
+ 15. An hour or so later, "cvs up -A" to get sub1/subsubB/default
+ back, then commit a change on that file, on trunk. (It's
+ important that this change happened after the previous commits
+ on B_SPLIT.)
+
+ 16. Branch sub1/subsubB/default to B_SPLIT, then "cvs up -r B_SPLIT"
+ to switch the whole working copy to the branch.
+
+ 17. Commit a change on B_SPLIT, to sub1/subsubB/default and
+ sub3/default.
diff --git a/t/t9602/cvsroot/.gitattributes b/t/t9602/cvsroot/.gitattributes
new file mode 100644
index 0000000000..562b12e16e
--- /dev/null
+++ b/t/t9602/cvsroot/.gitattributes
@@ -0,0 +1 @@
+* -whitespace
diff --git a/t/t9602/cvsroot/CVSROOT/.gitignore b/t/t9602/cvsroot/CVSROOT/.gitignore
new file mode 100644
index 0000000000..3bb9b34173
--- /dev/null
+++ b/t/t9602/cvsroot/CVSROOT/.gitignore
@@ -0,0 +1,2 @@
+history
+val-tags
diff --git a/t/t9602/cvsroot/module/default,v b/t/t9602/cvsroot/module/default,v
new file mode 100644
index 0000000000..3b68382a3b
--- /dev/null
+++ b/t/t9602/cvsroot/module/default,v
@@ -0,0 +1,102 @@
+head 1.2;
+access;
+symbols
+ B_SPLIT:1.2.0.4
+ B_MIXED:1.2.0.2
+ T_MIXED:1.2
+ B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4
+ B_FROM_INITIALS:1.1.1.1.0.2
+ T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1
+ T_ALL_INITIAL_FILES:1.1.1.1
+ vendortag:1.1.1.1
+ vendorbranch:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.2
+date 2003.05.23.00.17.53; author jrandom; state Exp;
+branches
+ 1.2.2.1
+ 1.2.4.1;
+next 1.1;
+
+1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches;
+next ;
+
+1.2.2.1
+date 2003.05.23.00.31.36; author jrandom; state Exp;
+branches;
+next ;
+
+1.2.4.1
+date 2003.06.03.03.20.31; author jrandom; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.2
+log
+@Second commit to proj, affecting all 7 files.
+@
+text
+@This is the file `default' in the top level of the project.
+
+Every directory in the `proj' project has a file named `default'.
+
+This line was added in the second commit (affecting all 7 files).
+@
+
+
+1.2.4.1
+log
+@First change on branch B_SPLIT.
+
+This change excludes sub3/default, because it was not part of this
+commit, and sub1/subsubB/default, which is not even on the branch yet.
+@
+text
+@a5 2
+
+First change on branch B_SPLIT.
+@
+
+
+1.2.2.1
+log
+@Modify three files, on branch B_MIXED.
+@
+text
+@a5 2
+
+This line was added on branch B_MIXED only (affecting 3 files).
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d4 2
+@
+
+
+1.1.1.1
+log
+@Initial import.
+@
+text
+@@
diff --git a/t/t9602/cvsroot/module/sub1/default,v b/t/t9602/cvsroot/module/sub1/default,v
new file mode 100644
index 0000000000..b7fdccdfdf
--- /dev/null
+++ b/t/t9602/cvsroot/module/sub1/default,v
@@ -0,0 +1,102 @@
+head 1.2;
+access;
+symbols
+ B_SPLIT:1.2.0.4
+ B_MIXED:1.2.0.2
+ T_MIXED:1.2
+ B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4
+ B_FROM_INITIALS:1.1.1.1.0.2
+ T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1
+ T_ALL_INITIAL_FILES:1.1.1.1
+ vendortag:1.1.1.1
+ vendorbranch:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.2
+date 2003.05.23.00.17.53; author jrandom; state Exp;
+branches
+ 1.2.2.1
+ 1.2.4.1;
+next 1.1;
+
+1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches;
+next ;
+
+1.2.2.1
+date 2003.05.23.00.31.36; author jrandom; state Exp;
+branches;
+next ;
+
+1.2.4.1
+date 2003.06.03.03.20.31; author jrandom; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.2
+log
+@Second commit to proj, affecting all 7 files.
+@
+text
+@This is sub1/default.
+
+Every directory in the `proj' project has a file named `default'.
+
+This line was added in the second commit (affecting all 7 files).
+@
+
+
+1.2.4.1
+log
+@First change on branch B_SPLIT.
+
+This change excludes sub3/default, because it was not part of this
+commit, and sub1/subsubB/default, which is not even on the branch yet.
+@
+text
+@a5 2
+
+First change on branch B_SPLIT.
+@
+
+
+1.2.2.1
+log
+@Modify three files, on branch B_MIXED.
+@
+text
+@a5 2
+
+This line was added on branch B_MIXED only (affecting 3 files).
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d4 2
+@
+
+
+1.1.1.1
+log
+@Initial import.
+@
+text
+@@
diff --git a/t/t9602/cvsroot/module/sub1/subsubA/default,v b/t/t9602/cvsroot/module/sub1/subsubA/default,v
new file mode 100644
index 0000000000..472b7b2bd9
--- /dev/null
+++ b/t/t9602/cvsroot/module/sub1/subsubA/default,v
@@ -0,0 +1,101 @@
+head 1.3;
+access;
+symbols
+ B_SPLIT:1.3.0.4
+ B_MIXED:1.3.0.2
+ T_MIXED:1.3
+ B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4
+ B_FROM_INITIALS:1.1.1.1.0.2
+ T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1
+ T_ALL_INITIAL_FILES:1.1.1.1
+ vendortag:1.1.1.1
+ vendorbranch:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.3
+date 2003.05.23.00.17.53; author jrandom; state Exp;
+branches
+ 1.3.4.1;
+next 1.2;
+
+1.2
+date 2003.05.23.00.15.26; author jrandom; state Exp;
+branches;
+next 1.1;
+
+1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches;
+next ;
+
+1.3.4.1
+date 2003.06.03.03.20.31; author jrandom; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.3
+log
+@Second commit to proj, affecting all 7 files.
+@
+text
+@This is sub1/subsubA/default.
+
+Every directory in the `proj' project has a file named `default'.
+
+This line was added by the first commit (affecting two files).
+
+This line was added in the second commit (affecting all 7 files).
+@
+
+
+1.3.4.1
+log
+@First change on branch B_SPLIT.
+
+This change excludes sub3/default, because it was not part of this
+commit, and sub1/subsubB/default, which is not even on the branch yet.
+@
+text
+@a7 2
+
+First change on branch B_SPLIT.
+@
+
+
+1.2
+log
+@First commit to proj, affecting two files.
+@
+text
+@d6 2
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d4 2
+@
+
+
+1.1.1.1
+log
+@Initial import.
+@
+text
+@@
diff --git a/t/t9602/cvsroot/module/sub1/subsubB/default,v b/t/t9602/cvsroot/module/sub1/subsubB/default,v
new file mode 100644
index 0000000000..fe6efa4554
--- /dev/null
+++ b/t/t9602/cvsroot/module/sub1/subsubB/default,v
@@ -0,0 +1,107 @@
+head 1.3;
+access;
+symbols
+ B_SPLIT:1.3.0.2
+ B_MIXED:1.2.0.2
+ T_MIXED:1.2
+ B_FROM_INITIALS:1.1.1.1.0.2
+ T_ALL_INITIAL_FILES:1.1.1.1
+ vendortag:1.1.1.1
+ vendorbranch:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.3
+date 2003.06.03.04.29.14; author jrandom; state Exp;
+branches
+ 1.3.2.1;
+next 1.2;
+
+1.2
+date 2003.05.23.00.17.53; author jrandom; state Exp;
+branches;
+next 1.1;
+
+1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches;
+next ;
+
+1.3.2.1
+date 2003.06.03.04.33.13; author jrandom; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.3
+log
+@A trunk change to sub1/subsubB/default. This was committed about an
+hour after an earlier change that affected most files on branch
+B_SPLIT. This file is not on that branch yet, but after this commit,
+we'll branch to B_SPLIT, albeit rooted in a revision that didn't exist
+at the time the rest of B_SPLIT was created.
+@
+text
+@This is sub1/subsubB/default.
+
+Every directory in the `proj' project has a file named `default'.
+
+This line was added in the second commit (affecting all 7 files).
+
+This bit was committed on trunk about an hour after an earlier change
+to everyone else on branch B_SPLIT. Afterwards, we'll finally branch
+this file to B_SPLIT, but rooted in a revision that didn't exist at
+the time the rest of B_SPLIT was created.
+@
+
+
+1.3.2.1
+log
+@This change affects sub3/default and sub1/subsubB/default, on branch
+B_SPLIT. Note that the latter file did not even exist on this branch
+until after some other files had had revisions committed on B_SPLIT.
+@
+text
+@a10 4
+
+This change affects sub3/default and sub1/subsubB/default, on branch
+B_SPLIT. Note that the latter file did not even exist on this branch
+until after some other files had had revisions committed on B_SPLIT.
+@
+
+
+1.2
+log
+@Second commit to proj, affecting all 7 files.
+@
+text
+@d6 5
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d4 2
+@
+
+
+1.1.1.1
+log
+@Initial import.
+@
+text
+@@
diff --git a/t/t9602/cvsroot/module/sub2/Attic/branch_B_MIXED_only,v b/t/t9602/cvsroot/module/sub2/Attic/branch_B_MIXED_only,v
new file mode 100644
index 0000000000..34c9789f2f
--- /dev/null
+++ b/t/t9602/cvsroot/module/sub2/Attic/branch_B_MIXED_only,v
@@ -0,0 +1,59 @@
+head 1.1;
+access;
+symbols
+ B_MIXED:1.1.0.2;
+locks; strict;
+comment @# @;
+
+
+1.1
+date 2003.05.23.00.25.26; author jrandom; state dead;
+branches
+ 1.1.2.1;
+next ;
+
+1.1.2.1
+date 2003.05.23.00.25.26; author jrandom; state Exp;
+branches;
+next 1.1.2.2;
+
+1.1.2.2
+date 2003.05.23.00.48.51; author jrandom; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.1
+log
+@file branch_B_MIXED_only was initially added on branch B_MIXED.
+@
+text
+@@
+
+
+1.1.2.1
+log
+@Add a file on branch B_MIXED.
+@
+text
+@a0 1
+This file was added on branch B_MIXED. It never existed on trunk.
+@
+
+
+1.1.2.2
+log
+@A single commit affecting one file on branch B_MIXED and one on trunk.
+@
+text
+@a1 3
+
+The same commit added these two lines here on branch B_MIXED, and two
+similar lines to ./default on trunk.
+@
+
+
diff --git a/t/t9602/cvsroot/module/sub2/default,v b/t/t9602/cvsroot/module/sub2/default,v
new file mode 100644
index 0000000000..018f7f8ece
--- /dev/null
+++ b/t/t9602/cvsroot/module/sub2/default,v
@@ -0,0 +1,102 @@
+head 1.3;
+access;
+symbols
+ B_SPLIT:1.3.0.2
+ B_MIXED:1.2.0.2
+ T_MIXED:1.2
+ B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4
+ B_FROM_INITIALS:1.1.1.1.0.2
+ T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1
+ T_ALL_INITIAL_FILES:1.1.1.1
+ vendortag:1.1.1.1
+ vendorbranch:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.3
+date 2003.05.23.00.48.51; author jrandom; state Exp;
+branches
+ 1.3.2.1;
+next 1.2;
+
+1.2
+date 2003.05.23.00.17.53; author jrandom; state Exp;
+branches;
+next 1.1;
+
+1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches;
+next ;
+
+1.3.2.1
+date 2003.06.03.03.20.31; author jrandom; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.3
+log
+@A single commit affecting one file on branch B_MIXED and one on trunk.
+@
+text
+@This is sub2/default.
+
+Every directory in the `proj' project has a file named `default'.
+
+This line was added in the second commit (affecting all 7 files).
+
+The same commit added these two lines here on trunk, and two similar
+lines to ./branch_B_MIXED_only on branch B_MIXED.
+@
+
+
+1.3.2.1
+log
+@First change on branch B_SPLIT.
+
+This change excludes sub3/default, because it was not part of this
+commit, and sub1/subsubB/default, which is not even on the branch yet.
+@
+text
+@a8 2
+
+First change on branch B_SPLIT.
+@
+
+
+1.2
+log
+@Second commit to proj, affecting all 7 files.
+@
+text
+@d6 3
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d4 2
+@
+
+
+1.1.1.1
+log
+@Initial import.
+@
+text
+@@
diff --git a/t/t9602/cvsroot/module/sub2/subsubA/default,v b/t/t9602/cvsroot/module/sub2/subsubA/default,v
new file mode 100644
index 0000000000..d13242cb09
--- /dev/null
+++ b/t/t9602/cvsroot/module/sub2/subsubA/default,v
@@ -0,0 +1,102 @@
+head 1.2;
+access;
+symbols
+ B_SPLIT:1.2.0.2
+ B_MIXED:1.1.0.2
+ T_MIXED:1.1
+ B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4
+ B_FROM_INITIALS:1.1.1.1.0.2
+ T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1
+ T_ALL_INITIAL_FILES:1.1.1.1
+ vendortag:1.1.1.1
+ vendorbranch:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.2
+date 2003.05.23.00.17.53; author jrandom; state Exp;
+branches
+ 1.2.2.1;
+next 1.1;
+
+1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches
+ 1.1.1.1
+ 1.1.2.1;
+next ;
+
+1.1.1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches;
+next ;
+
+1.1.2.1
+date 2003.05.23.00.31.36; author jrandom; state Exp;
+branches;
+next ;
+
+1.2.2.1
+date 2003.06.03.03.20.31; author jrandom; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.2
+log
+@Second commit to proj, affecting all 7 files.
+@
+text
+@This is sub2/subsub2/default.
+
+Every directory in the `proj' project has a file named `default'.
+
+This line was added in the second commit (affecting all 7 files).
+@
+
+
+1.2.2.1
+log
+@First change on branch B_SPLIT.
+
+This change excludes sub3/default, because it was not part of this
+commit, and sub1/subsubB/default, which is not even on the branch yet.
+@
+text
+@a5 2
+
+First change on branch B_SPLIT.
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d4 2
+@
+
+
+1.1.2.1
+log
+@Modify three files, on branch B_MIXED.
+@
+text
+@a3 2
+
+This line was added on branch B_MIXED only (affecting 3 files).
+@
+
+
+1.1.1.1
+log
+@Initial import.
+@
+text
+@@
diff --git a/t/t9602/cvsroot/module/sub3/default,v b/t/t9602/cvsroot/module/sub3/default,v
new file mode 100644
index 0000000000..88e4567434
--- /dev/null
+++ b/t/t9602/cvsroot/module/sub3/default,v
@@ -0,0 +1,102 @@
+head 1.3;
+access;
+symbols
+ B_SPLIT:1.3.0.2
+ B_MIXED:1.2.0.2
+ T_MIXED:1.2
+ B_FROM_INITIALS_BUT_ONE:1.1.1.1.0.4
+ B_FROM_INITIALS:1.1.1.1.0.2
+ T_ALL_INITIAL_FILES_BUT_ONE:1.1.1.1
+ T_ALL_INITIAL_FILES:1.1.1.1
+ vendortag:1.1.1.1
+ vendorbranch:1.1.1;
+locks; strict;
+comment @# @;
+
+
+1.3
+date 2003.05.23.00.17.53; author jrandom; state Exp;
+branches
+ 1.3.2.1;
+next 1.2;
+
+1.2
+date 2003.05.23.00.15.26; author jrandom; state Exp;
+branches;
+next 1.1;
+
+1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches
+ 1.1.1.1;
+next ;
+
+1.1.1.1
+date 2003.05.22.23.20.19; author jrandom; state Exp;
+branches;
+next ;
+
+1.3.2.1
+date 2003.06.03.04.33.13; author jrandom; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.3
+log
+@Second commit to proj, affecting all 7 files.
+@
+text
+@This is sub3/default.
+
+Every directory in the `proj' project has a file named `default'.
+
+This line was added by the first commit (affecting two files).
+
+This line was added in the second commit (affecting all 7 files).
+@
+
+
+1.3.2.1
+log
+@This change affects sub3/default and sub1/subsubB/default, on branch
+B_SPLIT. Note that the latter file did not even exist on this branch
+until after some other files had had revisions committed on B_SPLIT.
+@
+text
+@a7 4
+
+This change affects sub3/default and sub1/subsubB/default, on branch
+B_SPLIT. Note that the latter file did not even exist on this branch
+until after some other files had had revisions committed on B_SPLIT.
+@
+
+
+1.2
+log
+@First commit to proj, affecting two files.
+@
+text
+@d6 2
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d4 2
+@
+
+
+1.1.1.1
+log
+@Initial import.
+@
+text
+@@
diff --git a/t/t9603-cvsimport-patchsets.sh b/t/t9603-cvsimport-patchsets.sh
new file mode 100755
index 0000000000..958bdce4dd
--- /dev/null
+++ b/t/t9603-cvsimport-patchsets.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+# Structure of the test cvs repository
+#
+# Message File:Content Commit Time
+# Rev 1 a: 1.1 2009-02-21 19:11:43 +0100
+# Rev 2 a: 1.2 b: 1.1 2009-02-21 19:11:14 +0100
+# Rev 3 b: 1.2 2009-02-21 19:11:43 +0100
+#
+# As you can see the commit of Rev 3 has the same time as
+# Rev 1 this leads to a broken import because of a cvsps
+# bug.
+
+test_description='git cvsimport testing for correct patchset estimation'
+. ./lib-cvs.sh
+
+CVSROOT="$TEST_DIRECTORY"/t9603/cvsroot
+export CVSROOT
+
+test_expect_failure 'import with criss cross times on revisions' '
+
+ git cvsimport -p"-x" -C module-git module &&
+ cd module-git &&
+ git log --pretty=format:%s > ../actual-master &&
+ git log A~2..A --pretty="format:%s %ad" -- > ../actual-A &&
+ echo "" >> ../actual-master &&
+ echo "" >> ../actual-A &&
+ cd .. &&
+ echo "Rev 4
+Rev 3
+Rev 2
+Rev 1" > expect-master &&
+ test_cmp actual-master expect-master &&
+
+ echo "Rev 5 Branch A Wed Mar 11 19:09:10 2009 +0000
+Rev 4 Branch A Wed Mar 11 19:03:52 2009 +0000" > expect-A &&
+ test_cmp actual-A expect-A
+'
+
+test_done
diff --git a/t/t9603/cvsroot/.gitattributes b/t/t9603/cvsroot/.gitattributes
new file mode 100644
index 0000000000..562b12e16e
--- /dev/null
+++ b/t/t9603/cvsroot/.gitattributes
@@ -0,0 +1 @@
+* -whitespace
diff --git a/t/t9603/cvsroot/CVSROOT/.gitignore b/t/t9603/cvsroot/CVSROOT/.gitignore
new file mode 100644
index 0000000000..3bb9b34173
--- /dev/null
+++ b/t/t9603/cvsroot/CVSROOT/.gitignore
@@ -0,0 +1,2 @@
+history
+val-tags
diff --git a/t/t9603/cvsroot/module/a,v b/t/t9603/cvsroot/module/a,v
new file mode 100644
index 0000000000..ba8fd5af23
--- /dev/null
+++ b/t/t9603/cvsroot/module/a,v
@@ -0,0 +1,74 @@
+head 1.2;
+access;
+symbols
+ A:1.2.0.2;
+locks; strict;
+comment @# @;
+
+
+1.2
+date 2009.02.21.18.11.14; author tester; state Exp;
+branches
+ 1.2.2.1;
+next 1.1;
+
+1.1
+date 2009.02.21.18.11.43; author tester; state Exp;
+branches;
+next ;
+
+1.2.2.1
+date 2009.03.11.19.03.52; author tester; state Exp;
+branches;
+next 1.2.2.2;
+
+1.2.2.2
+date 2009.03.11.19.09.10; author tester; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.2
+log
+@Rev 2
+@
+text
+@1.2
+@
+
+
+1.2.2.1
+log
+@Rev 4 Branch A
+@
+text
+@d1 1
+a1 1
+1.2.2.1
+@
+
+
+1.2.2.2
+log
+@Rev 5 Branch A
+@
+text
+@d1 1
+a1 1
+1.2.2.2
+@
+
+
+1.1
+log
+@Rev 1
+@
+text
+@d1 1
+a1 1
+1.1
+@
diff --git a/t/t9603/cvsroot/module/b,v b/t/t9603/cvsroot/module/b,v
new file mode 100644
index 0000000000..d26885518a
--- /dev/null
+++ b/t/t9603/cvsroot/module/b,v
@@ -0,0 +1,90 @@
+head 1.3;
+access;
+symbols
+ A:1.2.0.2;
+locks; strict;
+comment @# @;
+
+
+1.3
+date 2009.03.11.19.05.08; author tester; state Exp;
+branches;
+next 1.2;
+
+1.2
+date 2009.02.21.18.11.43; author tester; state Exp;
+branches
+ 1.2.2.1;
+next 1.1;
+
+1.1
+date 2009.02.21.18.11.14; author tester; state Exp;
+branches;
+next ;
+
+1.2.2.1
+date 2009.03.11.19.03.52; author tester; state Exp;
+branches;
+next 1.2.2.2;
+
+1.2.2.2
+date 2009.03.11.19.09.10; author tester; state Exp;
+branches;
+next ;
+
+
+desc
+@@
+
+
+1.3
+log
+@Rev 4
+@
+text
+@1.3
+@
+
+
+1.2
+log
+@Rev 3
+@
+text
+@d1 1
+a1 1
+1.2
+@
+
+
+1.2.2.1
+log
+@Rev 4 Branch A
+@
+text
+@d1 1
+a1 1
+1.2.2.1
+@
+
+
+1.2.2.2
+log
+@Rev 5 Branch A
+@
+text
+@d1 1
+a1 1
+1.2
+@
+
+
+1.1
+log
+@Rev 2
+@
+text
+@d1 1
+a1 1
+1.1
+@
diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh
new file mode 100755
index 0000000000..8686086dde
--- /dev/null
+++ b/t/t9700-perl-git.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Lea Wiemann
+#
+
+test_description='perl interface (Git.pm)'
+. ./test-lib.sh
+
+if ! test_have_prereq PERL; then
+ say 'skipping perl interface tests, perl not available'
+ test_done
+fi
+
+"$PERL_PATH" -MTest::More -e 0 2>/dev/null || {
+ say "Perl Test::More unavailable, skipping test"
+ test_done
+}
+
+# set up test repository
+
+test_expect_success \
+ 'set up test repository' \
+ 'echo "test file 1" > file1 &&
+ echo "test file 2" > file2 &&
+ mkdir directory1 &&
+ echo "in directory1" >> directory1/file &&
+ mkdir directory2 &&
+ echo "in directory2" >> directory2/file &&
+ git add . &&
+ git commit -m "first commit" &&
+
+ echo "new file in subdir 2" > directory2/file2 &&
+ git add . &&
+ git commit -m "commit in directory2" &&
+
+ echo "changed file 1" > file1 &&
+ git commit -a -m "second commit" &&
+
+ git config --add color.test.slot1 green &&
+ git config --add test.string value &&
+ git config --add test.dupstring value1 &&
+ git config --add test.dupstring value2 &&
+ git config --add test.booltrue true &&
+ git config --add test.boolfalse no &&
+ git config --add test.boolother other &&
+ git config --add test.int 2k
+ '
+
+test_external_without_stderr \
+ 'Perl API' \
+ "$PERL_PATH" "$TEST_DIRECTORY"/t9700/test.pl
+
+test_done
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
new file mode 100755
index 0000000000..666722d9bf
--- /dev/null
+++ b/t/t9700/test.pl
@@ -0,0 +1,107 @@
+#!/usr/bin/perl
+use lib (split(/:/, $ENV{GITPERLLIB}));
+
+use 5.006002;
+use warnings;
+use strict;
+
+use Test::More qw(no_plan);
+
+use Cwd;
+use File::Basename;
+
+BEGIN { use_ok('Git') }
+
+# set up
+our $abs_repo_dir = cwd();
+ok(our $r = Git->repository(Directory => "."), "open repository");
+
+# config
+is($r->config("test.string"), "value", "config scalar: string");
+is_deeply([$r->config("test.dupstring")], ["value1", "value2"],
+ "config array: string");
+is($r->config("test.nonexistent"), undef, "config scalar: nonexistent");
+is_deeply([$r->config("test.nonexistent")], [], "config array: nonexistent");
+is($r->config_int("test.int"), 2048, "config_int: integer");
+is($r->config_int("test.nonexistent"), undef, "config_int: nonexistent");
+ok($r->config_bool("test.booltrue"), "config_bool: true");
+ok(!$r->config_bool("test.boolfalse"), "config_bool: false");
+our $ansi_green = "\x1b[32m";
+is($r->get_color("color.test.slot1", "red"), $ansi_green, "get_color");
+# Cannot test $r->get_colorbool("color.foo")) because we do not
+# control whether our STDOUT is a terminal.
+
+# Failure cases for config:
+# Save and restore STDERR; we will probably extract this into a
+# "dies_ok" method and possibly move the STDERR handling to Git.pm.
+open our $tmpstderr, ">&STDERR" or die "cannot save STDERR"; close STDERR;
+eval { $r->config("test.dupstring") };
+ok($@, "config: duplicate entry in scalar context fails");
+eval { $r->config_bool("test.boolother") };
+ok($@, "config_bool: non-boolean values fail");
+open STDERR, ">&", $tmpstderr or die "cannot restore STDERR";
+
+# ident
+like($r->ident("aUthor"), qr/^A U Thor <author\@example.com> [0-9]+ \+0000$/,
+ "ident scalar: author (type)");
+like($r->ident("cOmmitter"), qr/^C O Mitter <committer\@example.com> [0-9]+ \+0000$/,
+ "ident scalar: committer (type)");
+is($r->ident("invalid"), "invalid", "ident scalar: invalid ident string (no parsing)");
+my ($name, $email, $time_tz) = $r->ident('author');
+is_deeply([$name, $email], ["A U Thor", "author\@example.com"],
+ "ident array: author");
+like($time_tz, qr/[0-9]+ \+0000/, "ident array: author");
+is_deeply([$r->ident("Name <email> 123 +0000")], ["Name", "email", "123 +0000"],
+ "ident array: ident string");
+is_deeply([$r->ident("invalid")], [], "ident array: invalid ident string");
+
+# ident_person
+is($r->ident_person("aUthor"), "A U Thor <author\@example.com>",
+ "ident_person: author (type)");
+is($r->ident_person("Name <email> 123 +0000"), "Name <email>",
+ "ident_person: ident string");
+is($r->ident_person("Name", "email", "123 +0000"), "Name <email>",
+ "ident_person: array");
+
+# objects and hashes
+ok(our $file1hash = $r->command_oneline('rev-parse', "HEAD:file1"), "(get file hash)");
+my $tmpfile = "file.tmp";
+open TEMPFILE, "+>$tmpfile" or die "Can't open $tmpfile: $!";
+is($r->cat_blob($file1hash, \*TEMPFILE), 15, "cat_blob: size");
+our $blobcontents;
+{ local $/; seek TEMPFILE, 0, 0; $blobcontents = <TEMPFILE>; }
+is($blobcontents, "changed file 1\n", "cat_blob: data");
+close TEMPFILE or die "Failed writing to $tmpfile: $!";
+is(Git::hash_object("blob", $tmpfile), $file1hash, "hash_object: roundtrip");
+open TEMPFILE, ">$tmpfile" or die "Can't open $tmpfile: $!";
+print TEMPFILE my $test_text = "test blob, to be inserted\n";
+close TEMPFILE or die "Failed writing to $tmpfile: $!";
+like(our $newhash = $r->hash_and_insert_object($tmpfile), qr/[0-9a-fA-F]{40}/,
+ "hash_and_insert_object: returns hash");
+open TEMPFILE, "+>$tmpfile" or die "Can't open $tmpfile: $!";
+is($r->cat_blob($newhash, \*TEMPFILE), length $test_text, "cat_blob: roundtrip size");
+{ local $/; seek TEMPFILE, 0, 0; $blobcontents = <TEMPFILE>; }
+is($blobcontents, $test_text, "cat_blob: roundtrip data");
+close TEMPFILE;
+unlink $tmpfile;
+
+# paths
+is($r->repo_path, $abs_repo_dir . "/.git", "repo_path");
+is($r->wc_path, $abs_repo_dir . "/", "wc_path");
+is($r->wc_subdir, "", "wc_subdir initial");
+$r->wc_chdir("directory1");
+is($r->wc_subdir, "directory1", "wc_subdir after wc_chdir");
+is($r->config("test.string"), "value", "config after wc_chdir");
+
+# Object generation in sub directory
+chdir("directory2");
+my $r2 = Git->repository();
+is($r2->repo_path, $abs_repo_dir . "/.git", "repo_path (2)");
+is($r2->wc_path, $abs_repo_dir . "/", "wc_path (2)");
+is($r2->wc_subdir, "directory2/", "wc_subdir initial (2)");
+
+# commands in sub directory
+my $last_commit = $r2->command_oneline(qw(rev-parse --verify HEAD));
+like($last_commit, qr/^[0-9a-fA-F]{40}$/, 'rev-parse returned hash');
+my $dir_commit = $r2->command_oneline('log', '-n1', '--pretty=format:%H', '.');
+isnt($last_commit, $dir_commit, 'log . does not show last commit');
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 7c2a8ba77d..ec3336aba5 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -3,6 +3,22 @@
# Copyright (c) 2005 Junio C Hamano
#
+# if --tee was passed, write the output not only to the terminal, but
+# additionally to the file test-results/$BASENAME.out, too.
+case "$GIT_TEST_TEE_STARTED, $* " in
+done,*)
+ # do not redirect again
+ ;;
+*' --tee '*|*' --va'*)
+ mkdir -p test-results
+ BASE=test-results/$(basename "$0" .sh)
+ (GIT_TEST_TEE_STARTED=done ${SHELL-sh} "$0" "$@" 2>&1;
+ echo $? > $BASE.exit) | tee $BASE.out
+ test "$(cat $BASE.exit)" = 0
+ exit
+ ;;
+esac
+
# Keep the original TERM for say_color
ORIGINAL_TERM=$TERM
@@ -14,7 +30,7 @@ TZ=UTC
TERM=dumb
export LANG LC_ALL PAGER TERM TZ
EDITOR=:
-VISUAL=:
+unset VISUAL
unset GIT_EDITOR
unset AUTHOR_DATE
unset AUTHOR_EMAIL
@@ -35,13 +51,14 @@ unset GIT_WORK_TREE
unset GIT_EXTERNAL_DIFF
unset GIT_INDEX_FILE
unset GIT_OBJECT_DIRECTORY
+unset GIT_CEILING_DIRECTORIES
unset SHA1_FILE_DIRECTORIES
unset SHA1_FILE_DIRECTORY
GIT_MERGE_VERBOSITY=5
export GIT_MERGE_VERBOSITY
export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
-export EDITOR VISUAL
+export EDITOR
GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u}
# Protect ourselves from common misconfiguration to export
@@ -80,6 +97,8 @@ do
debug=t; shift ;;
-i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
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 ;;
-h|--h|--he|--hel|--help)
help=t; shift ;;
-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
@@ -91,8 +110,15 @@ do
--no-python)
# noop now...
shift ;;
+ --va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind)
+ valgrind=t; verbose=t; shift ;;
+ --tee)
+ shift ;; # was handled already
+ --root=*)
+ root=$(expr "z$1" : 'z[^=]*=\(.*\)')
+ shift ;;
*)
- break ;;
+ echo "error: unknown test option '$1'" >&2; exit 1 ;;
esac
done
@@ -109,8 +135,9 @@ if test -n "$color"; then
*) test -n "$quiet" && return;;
esac
shift
- echo "* $*"
+ printf "* %s" "$*"
tput sgr0
+ echo
)
}
else
@@ -123,7 +150,7 @@ fi
error () {
say_color error "error: $*"
- trap - exit
+ GIT_EXIT_OK=t
exit 1
}
@@ -152,13 +179,37 @@ test_failure=0
test_count=0
test_fixed=0
test_broken=0
+test_success=0
die () {
- echo >&5 "FATAL: Unexpected exit with code $?"
- exit 1
+ code=$?
+ if test -n "$GIT_EXIT_OK"
+ then
+ exit $code
+ else
+ echo >&5 "FATAL: Unexpected exit with code $code"
+ exit 1
+ fi
}
-trap 'die' exit
+GIT_EXIT_OK=
+trap 'die' EXIT
+
+# The semantics of the editor variables are that of invoking
+# sh -c "$EDITOR \"$@\"" files ...
+#
+# If our trash directory contains shell metacharacters, they will be
+# interpreted if we just set $EDITOR directly, so do a little dance with
+# environment variables to work around this.
+#
+# In particular, quoting isn't enough, as the path may contain the same quote
+# that we're using.
+test_set_editor () {
+ FAKE_EDITOR="$1"
+ export FAKE_EDITOR
+ EDITOR='"$FAKE_EDITOR"'
+ export EDITOR
+}
test_tick () {
if test -z "${test_tick+set}"
@@ -172,31 +223,87 @@ test_tick () {
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
}
+# Call test_commit with the arguments "<message> [<file> [<contents>]]"
+#
+# This will commit a file with the given contents and the given commit
+# message. It will also add a tag with <message> as name.
+#
+# Both <file> and <contents> default to <message>.
+
+test_commit () {
+ file=${2:-"$1.t"}
+ echo "${3-$1}" > "$file" &&
+ git add "$file" &&
+ test_tick &&
+ git commit -m "$1" &&
+ git tag "$1"
+}
+
+# Call test_merge with the arguments "<message> <commit>", where <commit>
+# can be a tag pointing to the commit-to-merge.
+
+test_merge () {
+ test_tick &&
+ git merge -m "$1" "$2" &&
+ git tag "$1"
+}
+
+# This function helps systems where core.filemode=false is set.
+# Use it instead of plain 'chmod +x' to set or unset the executable bit
+# of a file in the working directory and add it to the index.
+
+test_chmod () {
+ chmod "$@" &&
+ git update-index --add "--chmod=$@"
+}
+
+# Use test_set_prereq to tell that a particular prerequisite is available.
+# The prerequisite can later be checked for in two ways:
+#
+# - Explicitly using test_have_prereq.
+#
+# - Implicitly by specifying the prerequisite tag in the calls to
+# test_expect_{success,failure,code}.
+#
+# The single parameter is the prerequisite tag (a simple word, in all
+# capital letters by convention).
+
+test_set_prereq () {
+ satisfied="$satisfied$1 "
+}
+satisfied=" "
+
+test_have_prereq () {
+ case $satisfied in
+ *" $1 "*)
+ : yes, have it ;;
+ *)
+ ! : nope ;;
+ esac
+}
+
# You are not expected to call test_ok_ and test_failure_ directly, use
# the text_expect_* functions instead.
test_ok_ () {
- test_count=$(expr "$test_count" + 1)
+ test_success=$(($test_success + 1))
say_color "" " ok $test_count: $@"
}
test_failure_ () {
- test_count=$(expr "$test_count" + 1)
- test_failure=$(expr "$test_failure" + 1);
+ test_failure=$(($test_failure + 1))
say_color error "FAIL $test_count: $1"
shift
echo "$@" | sed -e 's/^/ /'
- test "$immediate" = "" || { trap - exit; exit 1; }
+ test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
}
test_known_broken_ok_ () {
- test_count=$(expr "$test_count" + 1)
test_fixed=$(($test_fixed+1))
say_color "" " FIXED $test_count: $@"
}
test_known_broken_failure_ () {
- test_count=$(expr "$test_count" + 1)
test_broken=$(($test_broken+1))
say_color skip " still broken $test_count: $@"
}
@@ -212,20 +319,23 @@ test_run_ () {
}
test_skip () {
- this_test=$(expr "./$0" : '.*/\(t[0-9]*\)-[^/]*$')
- this_test="$this_test.$(expr "$test_count" + 1)"
+ test_count=$(($test_count+1))
to_skip=
for skp in $GIT_SKIP_TESTS
do
- case "$this_test" in
+ case $this_test.$test_count in
$skp)
to_skip=t
esac
done
+ if test -z "$to_skip" && test -n "$prereq" &&
+ ! test_have_prereq "$prereq"
+ then
+ to_skip=t
+ fi
case "$to_skip" in
t)
say_color skip >&3 "skipping test: $@"
- test_count=$(expr "$test_count" + 1)
say_color skip "skip $test_count: $1"
: true
;;
@@ -236,8 +346,9 @@ test_skip () {
}
test_expect_failure () {
+ test "$#" = 3 && { prereq=$1; shift; } || prereq=
test "$#" = 2 ||
- error "bug in the test script: not 2 parameters to test-expect-failure"
+ error "bug in the test script: not 2 or 3 parameters to test-expect-failure"
if ! test_skip "$@"
then
say >&3 "checking known breakage: $2"
@@ -246,15 +357,16 @@ test_expect_failure () {
then
test_known_broken_ok_ "$1"
else
- test_known_broken_failure_ "$1"
+ test_known_broken_failure_ "$1"
fi
fi
echo >&3 ""
}
test_expect_success () {
+ test "$#" = 3 && { prereq=$1; shift; } || prereq=
test "$#" = 2 ||
- error "bug in the test script: not 2 parameters to test-expect-success"
+ error "bug in the test script: not 2 or 3 parameters to test-expect-success"
if ! test_skip "$@"
then
say >&3 "expecting success: $2"
@@ -270,8 +382,9 @@ test_expect_success () {
}
test_expect_code () {
+ test "$#" = 4 && { prereq=$1; shift; } || prereq=
test "$#" = 3 ||
- error "bug in the test script: not 3 parameters to test-expect-code"
+ error "bug in the test script: not 3 or 4 parameters to test-expect-code"
if ! test_skip "$@"
then
say >&3 "expecting exit code $1: $3"
@@ -286,6 +399,65 @@ test_expect_code () {
echo >&3 ""
}
+# test_external runs external test scripts that provide continuous
+# test output about their progress, and succeeds/fails on
+# zero/non-zero exit code. It outputs the test output on stdout even
+# in non-verbose mode, and announces the external script with "* run
+# <n>: ..." before running it. When providing relative paths, keep in
+# mind that all scripts run in "trash directory".
+# Usage: test_external description command arguments...
+# Example: test_external 'Perl API' perl ../path/to/test.pl
+test_external () {
+ test "$#" = 4 && { prereq=$1; shift; } || prereq=
+ test "$#" = 3 ||
+ error >&5 "bug in the test script: not 3 or 4 parameters to test_external"
+ descr="$1"
+ shift
+ if ! test_skip "$descr" "$@"
+ then
+ # Announce the script to reduce confusion about the
+ # test output that follows.
+ say_color "" " run $test_count: $descr ($*)"
+ # Run command; redirect its stderr to &4 as in
+ # test_run_, but keep its stdout on our stdout even in
+ # non-verbose mode.
+ "$@" 2>&4
+ if [ "$?" = 0 ]
+ then
+ test_ok_ "$descr"
+ else
+ test_failure_ "$descr" "$@"
+ fi
+ fi
+}
+
+# Like test_external, but in addition tests that the command generated
+# no output on stderr.
+test_external_without_stderr () {
+ # The temporary file has no (and must have no) security
+ # implications.
+ tmp="$TMPDIR"; if [ -z "$tmp" ]; then tmp=/tmp; fi
+ stderr="$tmp/git-external-stderr.$$.tmp"
+ test_external "$@" 4> "$stderr"
+ [ -f "$stderr" ] || error "Internal error: $stderr disappeared."
+ descr="no stderr: $1"
+ shift
+ say >&3 "expecting no stderr from previous command"
+ if [ ! -s "$stderr" ]; then
+ rm "$stderr"
+ test_ok_ "$descr"
+ else
+ if [ "$verbose" = t ]; then
+ output=`echo; echo Stderr is:; cat "$stderr"`
+ else
+ output=
+ fi
+ # rm first in case test_failure exits.
+ rm "$stderr"
+ test_failure_ "$descr" "$@" "$output"
+ fi
+}
+
# This is not among top-level (test_expect_success | test_expect_failure)
# but is a prefix that can be used in the test script, like:
#
@@ -300,7 +472,7 @@ test_expect_code () {
test_must_fail () {
"$@"
- test $? -gt 0 -a $? -le 129
+ test $? -gt 0 -a $? -le 129 -o $? -gt 192
}
# test_cmp is a helper function to compare actual and expected output.
@@ -327,16 +499,26 @@ test_create_repo () {
error "bug in the test script: not 1 parameter to test-create-repo"
owd=`pwd`
repo="$1"
- mkdir "$repo"
+ mkdir -p "$repo"
cd "$repo" || error "Cannot setup test environment"
- "$GIT_EXEC_PATH/git" init --template=$GIT_EXEC_PATH/templates/blt/ >/dev/null 2>&1 ||
+ "$GIT_EXEC_PATH/git-init" "--template=$TEST_DIRECTORY/../templates/blt/" >&3 2>&4 ||
error "cannot run git init -- have you built things yet?"
mv .git/hooks .git/hooks-disabled
cd "$owd"
}
test_done () {
- trap - exit
+ GIT_EXIT_OK=t
+ test_results_dir="$TEST_DIRECTORY/test-results"
+ mkdir -p "$test_results_dir"
+ test_results_path="$test_results_dir/${0%.sh}-$$"
+
+ echo "total $test_count" >> $test_results_path
+ echo "success $test_success" >> $test_results_path
+ echo "fixed $test_fixed" >> $test_results_path
+ echo "broken $test_broken" >> $test_results_path
+ echo "failed $test_failure" >> $test_results_path
+ echo "" >> $test_results_path
if test "$test_fixed" != 0
then
@@ -351,15 +533,12 @@ test_done () {
fi
case "$test_failure" in
0)
- # We could:
- # cd .. && rm -fr trash
- # but that means we forbid any tests that use their own
- # subdirectory from calling test_done without coming back
- # to where they started from.
- # The Makefile provided will clean this test area so
- # we will leave things as they are.
-
say_color pass "passed all $msg"
+
+ test -d "$remove_trash" &&
+ cd "$(dirname "$remove_trash")" &&
+ rm -rf "$(basename "$remove_trash")"
+
exit 0 ;;
*)
@@ -370,12 +549,85 @@ test_done () {
}
# Test the binaries we have just built. The tests are kept in
-# t/ subdirectory and are run in trash subdirectory.
-PATH=$(pwd)/..:$PATH
-GIT_EXEC_PATH=$(pwd)/..
+# t/ subdirectory and are run in 'trash directory' subdirectory.
+TEST_DIRECTORY=$(pwd)
+if test -z "$valgrind"
+then
+ if test -z "$GIT_TEST_INSTALLED"
+ then
+ PATH=$TEST_DIRECTORY/..:$PATH
+ GIT_EXEC_PATH=$TEST_DIRECTORY/..
+ else
+ GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path) ||
+ error "Cannot run git from $GIT_TEST_INSTALLED."
+ PATH=$GIT_TEST_INSTALLED:$TEST_DIRECTORY/..:$PATH
+ GIT_EXEC_PATH=${GIT_TEST_EXEC_PATH:-$GIT_EXEC_PATH}
+ fi
+else
+ make_symlink () {
+ test -h "$2" &&
+ test "$1" = "$(readlink "$2")" || {
+ # be super paranoid
+ if mkdir "$2".lock
+ then
+ rm -f "$2" &&
+ ln -s "$1" "$2" &&
+ rm -r "$2".lock
+ else
+ while test -d "$2".lock
+ do
+ say "Waiting for lock on $2."
+ sleep 1
+ done
+ fi
+ }
+ }
+
+ make_valgrind_symlink () {
+ # handle only executables
+ test -x "$1" || return
+
+ base=$(basename "$1")
+ symlink_target=$TEST_DIRECTORY/../$base
+ # do not override scripts
+ if test -x "$symlink_target" &&
+ test ! -d "$symlink_target" &&
+ test "#!" != "$(head -c 2 < "$symlink_target")"
+ then
+ symlink_target=../valgrind.sh
+ fi
+ case "$base" in
+ *.sh|*.perl)
+ symlink_target=../unprocessed-script
+ esac
+ # create the link, or replace it if it is out of date
+ make_symlink "$symlink_target" "$GIT_VALGRIND/bin/$base" || exit
+ }
+
+ # override all git executables in TEST_DIRECTORY/..
+ GIT_VALGRIND=$TEST_DIRECTORY/valgrind
+ mkdir -p "$GIT_VALGRIND"/bin
+ for file in $TEST_DIRECTORY/../git* $TEST_DIRECTORY/../test-*
+ do
+ make_valgrind_symlink $file
+ done
+ OLDIFS=$IFS
+ IFS=:
+ for path in $PATH
+ do
+ ls "$path"/git-* 2> /dev/null |
+ while read file
+ do
+ make_valgrind_symlink "$file"
+ done
+ done
+ IFS=$OLDIFS
+ PATH=$GIT_VALGRIND/bin:$PATH
+ GIT_EXEC_PATH=$GIT_VALGRIND/bin
+ export GIT_VALGRIND
+fi
GIT_TEMPLATE_DIR=$(pwd)/../templates/blt
unset GIT_CONFIG
-unset GIT_CONFIG_LOCAL
GIT_CONFIG_NOSYSTEM=1
GIT_CONFIG_NOGLOBAL=1
export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL
@@ -395,17 +647,26 @@ fi
. ../GIT-BUILD-OPTIONS
# Test repository
-test=trash
+test="trash directory.$(basename "$0" .sh)"
+test -n "$root" && test="$root/$test"
+case "$test" in
+/*) TRASH_DIRECTORY="$test" ;;
+ *) TRASH_DIRECTORY="$TEST_DIRECTORY/$test" ;;
+esac
+test ! -z "$debug" || remove_trash=$TRASH_DIRECTORY
rm -fr "$test" || {
- trap - exit
+ GIT_EXIT_OK=t
echo >&5 "FATAL: Cannot prepare test area"
exit 1
}
-test_create_repo $test
-cd "$test"
+test_create_repo "$test"
+# Use -P to resolve symlinks in our working directory so that the cwd
+# in subprocesses like git equals our $PWD (for pathname comparisons).
+cd -P "$test" || exit 1
-this_test=$(expr "./$0" : '.*/\(t[0-9]*\)-[^/]*$')
+this_test=${0##*/}
+this_test=${this_test%%-*}
for skp in $GIT_SKIP_TESTS
do
to_skip=
@@ -423,3 +684,52 @@ do
test_done
esac
done
+
+# Provide an implementation of the 'yes' utility
+yes () {
+ if test $# = 0
+ then
+ y=y
+ else
+ y="$*"
+ fi
+
+ while echo "$y"
+ do
+ :
+ done
+}
+
+# Fix some commands on Windows
+case $(uname -s) in
+*MINGW*)
+ # Windows has its own (incompatible) sort and find
+ sort () {
+ /usr/bin/sort "$@"
+ }
+ find () {
+ /usr/bin/find "$@"
+ }
+ sum () {
+ md5sum "$@"
+ }
+ # git sees Windows-style pwd
+ pwd () {
+ builtin pwd -W
+ }
+ # no POSIX permissions
+ # backslashes in pathspec are converted to '/'
+ # exec does not inherit the PID
+ ;;
+*)
+ test_set_prereq POSIXPERM
+ test_set_prereq BSLASHPSPEC
+ test_set_prereq EXECKEEPSPID
+ ;;
+esac
+
+test -z "$NO_PERL" && test_set_prereq PERL
+
+# test whether the filesystem supports symbolic links
+ln -s x y 2>/dev/null && test -h y 2>/dev/null && test_set_prereq SYMLINKS
+rm -f y
diff --git a/t/valgrind/.gitignore b/t/valgrind/.gitignore
new file mode 100644
index 0000000000..d4ae6676d1
--- /dev/null
+++ b/t/valgrind/.gitignore
@@ -0,0 +1,2 @@
+/bin/
+/templates
diff --git a/t/valgrind/analyze.sh b/t/valgrind/analyze.sh
new file mode 100755
index 0000000000..d8105d9fab
--- /dev/null
+++ b/t/valgrind/analyze.sh
@@ -0,0 +1,123 @@
+#!/bin/sh
+
+out_prefix=$(dirname "$0")/../test-results/valgrind.out
+output=
+count=0
+total_count=0
+missing_message=
+new_line='
+'
+
+# start outputting the current valgrind error in $out_prefix.++$count,
+# and the test case which failed in the corresponding .message file
+start_output () {
+ test -z "$output" || return
+
+ # progress
+ total_count=$(($total_count+1))
+ test -t 2 && printf "\rFound %d errors" $total_count >&2
+
+ count=$(($count+1))
+ output=$out_prefix.$count
+ : > $output
+
+ echo "*** $1 ***" > $output.message
+}
+
+finish_output () {
+ test ! -z "$output" || return
+ output=
+
+ # if a test case has more than one valgrind error, we need to
+ # copy the last .message file to the previous errors
+ test -z "$missing_message" || {
+ while test $missing_message -lt $count
+ do
+ cp $out_prefix.$count.message \
+ $out_prefix.$missing_message.message
+ missing_message=$(($missing_message+1))
+ done
+ missing_message=
+ }
+}
+
+# group the valgrind errors by backtrace
+output_all () {
+ last_line=
+ j=0
+ i=1
+ while test $i -le $count
+ do
+ # output <number> <backtrace-in-one-line>
+ echo "$i $(tr '\n' ' ' < $out_prefix.$i)"
+ i=$(($i+1))
+ done |
+ sort -t ' ' -k 2 | # order by <backtrace-in-one-line>
+ while read number line
+ do
+ # find duplicates, do not output backtrace twice
+ if test "$line" != "$last_line"
+ then
+ last_line=$line
+ j=$(($j+1))
+ printf "\nValgrind error $j:\n\n"
+ cat $out_prefix.$number
+ printf "\nfound in:\n"
+ fi
+ # print the test case where this came from
+ printf "\n"
+ cat $out_prefix.$number.message
+ done
+}
+
+handle_one () {
+ OLDIFS=$IFS
+ IFS="$new_line"
+ while read line
+ do
+ case "$line" in
+ # backtrace, possibly a new one
+ ==[0-9]*)
+
+ # Does the current valgrind error have a message yet?
+ case "$output" in
+ *.message)
+ test -z "$missing_message" &&
+ missing_message=$count
+ output=
+ esac
+
+ start_output $(basename $1)
+ echo "$line" |
+ sed 's/==[0-9]*==/==valgrind==/' >> $output
+ ;;
+ # end of backtrace
+ '}')
+ test -z "$output" || {
+ echo "$line" >> $output
+ test $output = ${output%.message} &&
+ output=$output.message
+ }
+ ;;
+ # end of test case
+ '')
+ finish_output
+ ;;
+ # normal line; if $output is set, print the line
+ *)
+ test -z "$output" || echo "$line" >> $output
+ ;;
+ esac
+ done < $1
+ IFS=$OLDIFS
+
+ # just to be safe
+ finish_output
+}
+
+for test_script in "$(dirname "$0")"/../test-results/*.out
+do
+ handle_one $test_script
+done
+
+output_all
diff --git a/t/valgrind/default.supp b/t/valgrind/default.supp
new file mode 100644
index 0000000000..9e013fa3b2
--- /dev/null
+++ b/t/valgrind/default.supp
@@ -0,0 +1,45 @@
+{
+ ignore-zlib-errors-cond
+ Memcheck:Cond
+ obj:*libz.so*
+}
+
+{
+ ignore-zlib-errors-value8
+ Memcheck:Value8
+ obj:*libz.so*
+}
+
+{
+ ignore-zlib-errors-value4
+ Memcheck:Value4
+ obj:*libz.so*
+}
+
+{
+ ignore-ldso-cond
+ Memcheck:Cond
+ obj:*ld-*.so
+}
+
+{
+ ignore-ldso-addr8
+ Memcheck:Addr8
+ obj:*ld-*.so
+}
+
+{
+ ignore-ldso-addr4
+ Memcheck:Addr4
+ obj:*ld-*.so
+}
+
+{
+ writing-data-from-zlib-triggers-even-more-errors
+ Memcheck:Param
+ write(buf)
+ obj:/lib/ld-*.so
+ fun:write_in_full
+ fun:write_buffer
+ fun:write_loose_object
+}
diff --git a/t/valgrind/valgrind.sh b/t/valgrind/valgrind.sh
new file mode 100755
index 0000000000..582b4dca94
--- /dev/null
+++ b/t/valgrind/valgrind.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+base=$(basename "$0")
+
+TRACK_ORIGINS=
+
+VALGRIND_VERSION=$(valgrind --version)
+VALGRIND_MAJOR=$(expr "$VALGRIND_VERSION" : '[^0-9]*\([0-9]*\)')
+VALGRIND_MINOR=$(expr "$VALGRIND_VERSION" : '[^0-9]*[0-9]*\.\([0-9]*\)')
+test 3 -gt "$VALGRIND_MAJOR" ||
+test 3 -eq "$VALGRIND_MAJOR" -a 4 -gt "$VALGRIND_MINOR" ||
+TRACK_ORIGINS=--track-origins=yes
+
+exec valgrind -q --error-exitcode=126 \
+ --leak-check=no \
+ --suppressions="$GIT_VALGRIND/default.supp" \
+ --gen-suppressions=all \
+ $TRACK_ORIGINS \
+ --log-fd=4 \
+ --input-fd=4 \
+ $GIT_VALGRIND_OPTIONS \
+ "$GIT_VALGRIND"/../../"$base" "$@"