summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/Makefile9
-rw-r--r--t/README40
-rw-r--r--t/annotate-tests.sh5
-rw-r--r--t/diff-lib.sh2
-rw-r--r--t/gitweb-lib.sh88
-rw-r--r--t/lib-cvs.sh75
-rw-r--r--t/lib-git-svn.sh36
-rw-r--r--t/lib-httpd.sh46
-rw-r--r--t/lib-httpd/apache.conf37
-rw-r--r--t/lib-patch-mode.sh43
-rw-r--r--t/lib-rebase.sh33
-rwxr-xr-xt/t0000-basic.sh66
-rwxr-xr-xt/t0001-init.sh83
-rwxr-xr-xt/t0004-unwritable.sh8
-rwxr-xr-xt/t0006-date.sh76
-rwxr-xr-xt/t0020-crlf.sh84
-rwxr-xr-xt/t0021-conversion.sh3
-rwxr-xr-xt/t0022-crlf-rename.sh2
-rwxr-xr-xt/t0024-crlf-archive.sh8
-rwxr-xr-xt/t0040-parse-options.sh95
-rwxr-xr-xt/t0050-filesystem.sh45
-rwxr-xr-xt/t0055-beyond-symlinks.sh6
-rwxr-xr-xt/t0060-path-utils.sh116
-rwxr-xr-xt/t0061-run-command.sh14
-rwxr-xr-xt/t0101-at-syntax.sh45
-rwxr-xr-xt/t1000-read-tree-m-3way.sh3
-rwxr-xr-xt/t1001-read-tree-m-2way.sh8
-rwxr-xr-xt/t1002-read-tree-m-u-2way.sh2
-rwxr-xr-xt/t1004-read-tree-m-u-wf.sh6
-rwxr-xr-xt/t1009-read-tree-new-index.sh25
-rwxr-xr-xt/t1010-mktree.sh71
-rwxr-xr-xt/t1011-read-tree-sparse-checkout.sh150
-rwxr-xr-xt/t1012-read-tree-df.sh102
-rwxr-xr-xt/t1020-subdirectory.sh2
-rwxr-xr-xt/t1100-commit-tree-options.sh2
-rwxr-xr-xt/t1200-tutorial.sh224
-rwxr-xr-xt/t1300-repo-config.sh77
-rwxr-xr-xt/t1301-shared-repo.sh12
-rwxr-xr-xt/t1304-default-acl.sh67
-rwxr-xr-xt/t1400-update-ref.sh6
-rwxr-xr-xt/t1402-check-ref-format.sh61
-rwxr-xr-xt/t1410-reflog.sh45
-rwxr-xr-xt/t1411-reflog-show.sh76
-rwxr-xr-xt/t1450-fsck.sh67
-rwxr-xr-xt/t1501-worktree.sh21
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh43
-rwxr-xr-xt/t1504-ceiling-dirs.sh2
-rwxr-xr-xt/t1506-rev-parse-diagnosis.sh69
-rwxr-xr-xt/t1507-rev-parse-upstream.sh139
-rwxr-xr-xt/t1508-at-combinations.sh51
-rwxr-xr-xt/t2000-checkout-cache-clash.sh9
-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/t2007-checkout-symlink.sh6
-rwxr-xr-xt/t2012-checkout-last.sh27
-rwxr-xr-xt/t2015-checkout-unborn.sh40
-rwxr-xr-xt/t2016-checkout-patch.sh115
-rwxr-xr-xt/t2030-unresolve-info.sh170
-rwxr-xr-xt/t2100-update-cache-badpath.sh14
-rwxr-xr-xt/t2104-update-index-skip-worktree.sh57
-rwxr-xr-xt/t2105-update-index-gitfile.sh38
-rwxr-xr-xt/t2200-add-update.sh4
-rwxr-xr-xt/t2201-add-update-typechange.sh16
-rwxr-xr-xt/t2204-add-ignored.sh79
-rwxr-xr-xt/t2300-cd-to-toplevel.sh16
-rwxr-xr-xt/t3000-ls-files-others.sh25
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh61
-rwxr-xr-xt/t3003-ls-files-exclude.sh40
-rwxr-xr-xt/t3010-ls-files-killed-modified.sh21
-rwxr-xr-xt/t3030-merge-recursive.sh9
-rwxr-xr-xt/t3031-merge-criscross.sh95
-rwxr-xr-xt/t3100-ls-tree-restrict.sh42
-rwxr-xr-xt/t3101-ls-tree-dirname.sh87
-rwxr-xr-xt/t3200-branch.sh28
-rwxr-xr-xt/t3202-show-branch-octopus.sh8
-rwxr-xr-xt/t3203-branch-output.sh81
-rwxr-xr-xt/t3301-notes.sh210
-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.sh64
-rwxr-xr-xt/t3404-rebase-interactive.sh234
-rwxr-xr-xt/t3406-rebase-message.sh23
-rwxr-xr-xt/t3408-rebase-multi-line.sh4
-rwxr-xr-xt/t3409-rebase-preserve-merges.sh8
-rwxr-xr-xt/t3411-rebase-preserve-around-merges.sh2
-rwxr-xr-xt/t3413-rebase-hook.sh (renamed from t/t3409-rebase-hook.sh)0
-rwxr-xr-xt/t3414-rebase-preserve-onto.sh80
-rwxr-xr-xt/t3415-rebase-autosquash.sh73
-rwxr-xr-xt/t3416-rebase-onto-threedots.sh105
-rwxr-xr-xt/t3417-rebase-whitespace-fix.sh126
-rwxr-xr-xt/t3501-revert-cherry-pick.sh2
-rwxr-xr-xt/t3505-cherry-pick-empty.sh10
-rwxr-xr-xt/t3600-rm.sh65
-rwxr-xr-xt/t3700-add.sh41
-rwxr-xr-xt/t3701-add-interactive.sh114
-rwxr-xr-xt/t3702-add-edit.sh121
-rwxr-xr-xt/t3900-i18n-commit.sh46
-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.sh40
-rwxr-xr-xt/t3902-quoted.sh19
-rwxr-xr-xt/t3903-stash.sh51
-rwxr-xr-xt/t3904-stash-patch.sh55
-rwxr-xr-xt/t4002-diff-basic.sh8
-rwxr-xr-xt/t4004-diff-rename-symlink.sh6
-rwxr-xr-xt/t4006-diff-mode.sh21
-rwxr-xr-xt/t4007-rename-3.sh74
-rwxr-xr-xt/t4008-diff-break-rewrite.sh8
-rwxr-xr-xt/t4011-diff-symlink.sh6
-rwxr-xr-xt/t4012-diff-binary.sh6
-rwxr-xr-xt/t4013-diff-various.sh12
-rw-r--r--t/t4013/diff.diff_--dirstat_master~1_master~23
-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..master12
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..master^8
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..side4
-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..master12
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..master12
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..master^8
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..master^^4
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..side4
-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.rev-list_--children_HEAD7
-rw-r--r--t/t4013/diff.rev-list_--parents_HEAD7
-rwxr-xr-xt/t4014-format-patch.sh370
-rwxr-xr-xt/t4015-diff-whitespace.sh25
-rwxr-xr-xt/t4017-diff-retval.sh15
-rwxr-xr-xt/t4019-diff-wserror.sh65
-rwxr-xr-xt/t4020-diff-external.sh11
-rwxr-xr-xt/t4021-format-patch-numbered.sh13
-rwxr-xr-xt/t4023-diff-rename-typechange.sh6
-rwxr-xr-xt/t4026-color.sh17
-rwxr-xr-xt/t4027-diff-submodule.sh84
-rwxr-xr-xt/t4029-diff-trailing-space.sh2
-rwxr-xr-xt/t4030-diff-textconv.sh2
-rwxr-xr-xt/t4031-diff-rewrite-binary.sh2
-rwxr-xr-xt/t4034-diff-words.sh52
-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/t4040-whitespace-status.sh63
-rwxr-xr-xt/t4041-diff-submodule.sh327
-rwxr-xr-xt/t4102-apply-rename.sh8
-rwxr-xr-xt/t4104-apply-boundary.sh9
-rwxr-xr-xt/t4107-apply-ignore-whitespace.sh185
-rwxr-xr-xt/t4114-apply-typechange.sh6
-rwxr-xr-xt/t4115-apply-symlink.sh6
-rwxr-xr-xt/t4118-apply-empty-context.sh4
-rwxr-xr-xt/t4120-apply-popt.sh5
-rwxr-xr-xt/t4122-apply-symlink-inside.sh6
-rwxr-xr-xt/t4124-apply-ws-rule.sh283
-rwxr-xr-xt/t4125-apply-ws-fuzz.sh4
-rwxr-xr-xt/t4128-apply-root.sh17
-rwxr-xr-xt/t4129-apply-samemode.sh19
-rwxr-xr-xt/t4131-apply-fake-ancestor.sh42
-rwxr-xr-xt/t4132-apply-removal.sh95
-rwxr-xr-xt/t4133-apply-filenames.sh38
-rwxr-xr-xt/t4150-am.sh77
-rwxr-xr-xt/t4200-rerere.sh19
-rwxr-xr-xt/t4201-shortlog.sh28
-rwxr-xr-xt/t4202-log.sh253
-rwxr-xr-xt/t4204-patch-id.sh38
-rwxr-xr-xt/t5000-tar-tree.sh89
-rwxr-xr-xt/t5001-archive-attr.sh91
-rwxr-xr-xt/t5100-mailinfo.sh28
-rw-r--r--t/t5100/.gitattributes4
-rw-r--r--t/t5100/001035
-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/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/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-samples.mbox32
-rw-r--r--t/t5100/sample.mbox130
-rwxr-xr-xt/t5300-pack-object.sh77
-rwxr-xr-xt/t5302-pack-index.sh17
-rwxr-xr-xt/t5303-pack-corruption-resilience.sh21
-rwxr-xr-xt/t5304-prune.sh86
-rwxr-xr-xt/t5400-send-pack.sh12
-rwxr-xr-xt/t5401-update-hooks.sh83
-rwxr-xr-xt/t5403-post-checkout-hook.sh14
-rwxr-xr-xt/t5405-send-pack-rewind.sh1
-rwxr-xr-xt/t5500-fetch-pack.sh315
-rwxr-xr-xt/t5502-quickfetch.sh20
-rwxr-xr-xt/t5503-tagfollow.sh6
-rwxr-xr-xt/t5505-remote.sh373
-rwxr-xr-xt/t5506-remote-groups.sh98
-rwxr-xr-xt/t5510-fetch.sh11
-rwxr-xr-xt/t5511-refspec.sh12
-rwxr-xr-xt/t5514-fetch-multiple.sh154
-rwxr-xr-xt/t5515-fetch-merge-logic.sh3
-rwxr-xr-xt/t5516-fetch-push.sh87
-rwxr-xr-xt/t5517-push-mirror.sh3
-rwxr-xr-xt/t5518-fetch-exit-status.sh2
-rwxr-xr-xt/t5520-pull.sh38
-rwxr-xr-xt/t5521-pull-options.sh85
-rwxr-xr-xt/t5522-pull-symlink.sh (renamed from t/t5521-pull-symlink.sh)26
-rwxr-xr-xt/t5523-push-upstream.sh69
-rwxr-xr-xt/t5524-pull-msg.sh35
-rwxr-xr-xt/t5530-upload-pack-error.sh17
-rwxr-xr-xt/t5531-deep-submodule-push.sh35
-rwxr-xr-xt/t5540-http-push.sh71
-rwxr-xr-xt/t5541-http-push.sh132
-rwxr-xr-xt/t5550-http-fetch.sh71
-rwxr-xr-xt/t5551-http-fetch.sh105
-rwxr-xr-xt/t5560-http-backend-noserver.sh73
-rwxr-xr-xt/t5561-http-backend.sh149
-rwxr-xr-xt/t556x_common122
-rwxr-xr-xt/t5601-clone.sh15
-rwxr-xr-xt/t5602-clone-remote-exec.sh4
-rwxr-xr-xt/t5701-clone-local.sh14
-rwxr-xr-xt/t5702-clone-options.sh3
-rwxr-xr-xt/t5705-clone-2gb.sh45
-rwxr-xr-xt/t5706-clone-branch.sh68
-rw-r--r--[-rwxr-xr-x]t/t6000lib.sh2
-rwxr-xr-xt/t6006-rev-list-format.sh47
-rwxr-xr-xt/t6010-merge-base.sh18
-rwxr-xr-xt/t6012-rev-list-simplify.sh3
-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/t6018-rev-list-glob.sh195
-rwxr-xr-xt/t6020-merge-df.sh23
-rwxr-xr-xt/t6023-merge-file.sh10
-rwxr-xr-xt/t6024-recursive-merge.sh9
-rwxr-xr-xt/t6026-merge-attr.sh12
-rwxr-xr-xt/t6028-merge-up-to-date.sh2
-rwxr-xr-xt/t6029-merge-subtree.sh47
-rwxr-xr-xt/t6030-bisect-porcelain.sh106
-rwxr-xr-xt/t6031-merge-recursive.sh20
-rwxr-xr-xt/t6033-merge-crlf.sh8
-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/t6037-merge-ours-theirs.sh64
-rwxr-xr-xt/t6040-tracking-info.sh47
-rwxr-xr-xt/t6050-replace.sh224
-rwxr-xr-xt/t6120-describe.sh22
-rwxr-xr-xt/t6200-fmt-merge-msg.sh36
-rwxr-xr-xt/t6300-for-each-ref.sh40
-rwxr-xr-xt/t7001-mv.sh16
-rwxr-xr-xt/t7002-grep.sh306
-rwxr-xr-xt/t7003-filter-branch.sh57
-rwxr-xr-xt/t7004-tag.sh104
-rwxr-xr-xt/t7005-editor.sh76
-rwxr-xr-xt/t7006-pager.sh176
-rwxr-xr-xt/t7006/test-terminal.perl58
-rwxr-xr-xt/t7011-skip-worktree-reading.sh163
-rwxr-xr-xt/t7012-skip-worktree-writing.sh146
-rwxr-xr-xt/t7060-wtstatus.sh59
-rwxr-xr-xt/t7102-reset.sh3
-rwxr-xr-xt/t7103-reset-bare.sh38
-rwxr-xr-xt/t7105-reset-patch.sh69
-rwxr-xr-xt/t7110-reset-merge.sh183
-rwxr-xr-xt/t7111-reset-table.sh113
-rwxr-xr-xt/t7201-co.sh97
-rwxr-xr-xt/t7300-clean.sh64
-rwxr-xr-xt/t7400-submodule-basic.sh35
-rwxr-xr-xt/t7401-submodule-summary.sh24
-rwxr-xr-xt/t7405-submodule-merge.sh6
-rwxr-xr-xt/t7406-submodule-update.sh206
-rwxr-xr-xt/t7407-submodule-foreach.sh237
-rwxr-xr-xt/t7408-submodule-reference.sh81
-rwxr-xr-xt/t7500-commit.sh12
-rwxr-xr-xt/t7501-commit.sh72
-rwxr-xr-xt/t7502-commit.sh120
-rwxr-xr-xt/t7503-pre-commit-hook.sh4
-rwxr-xr-xt/t7504-commit-msg-hook.sh8
-rwxr-xr-xt/t7506-status-submodule.sh85
-rwxr-xr-xt/t7508-status.sh (renamed from t/t7502-status.sh)350
-rwxr-xr-xt/t7509-commit.sh114
-rwxr-xr-xt/t7600-merge.sh41
-rwxr-xr-xt/t7602-merge-octopus-many.sh51
-rwxr-xr-xt/t7604-merge-custom-message.sh7
-rwxr-xr-xt/t7608-merge-messages.sh60
-rwxr-xr-xt/t7700-repack.sh14
-rwxr-xr-xt/t7800-difftool.sh267
-rwxr-xr-xt/t8003-blame.sh58
-rwxr-xr-xt/t8005-blame-i18n.sh40
-rw-r--r--t/t8005/cp1251.txt2
-rw-r--r--t/t8005/euc-japan.txt2
-rw-r--r--t/t8005/sjis.txt4
-rw-r--r--t/t8005/utf8.txt4
-rwxr-xr-xt/t9001-send-email.sh466
-rwxr-xr-xt/t9100-git-svn-basic.sh70
-rwxr-xr-xt/t9101-git-svn-props.sh41
-rwxr-xr-xt/t9102-git-svn-deep-rmdir.sh4
-rwxr-xr-xt/t9103-git-svn-tracked-directory-removed.sh8
-rwxr-xr-xt/t9104-git-svn-follow-parent.sh50
-rwxr-xr-xt/t9105-git-svn-commit-diff.sh8
-rwxr-xr-xt/t9106-git-svn-commit-diff-clobber.sh14
-rwxr-xr-xt/t9107-git-svn-migrate.sh30
-rwxr-xr-xt/t9108-git-svn-glob.sh26
-rwxr-xr-xt/t9109-git-svn-multi-glob.sh (renamed from t/t9108-git-svn-multi-glob.sh)44
-rwxr-xr-xt/t9113-git-svn-dcommit-new-file.sh2
-rwxr-xr-xt/t9114-git-svn-dcommit-merge.sh6
-rwxr-xr-xt/t9115-git-svn-dcommit-funky-renames.sh4
-rwxr-xr-xt/t9116-git-svn-log.sh2
-rwxr-xr-xt/t9117-git-svn-init-clone.sh2
-rwxr-xr-xt/t9118-git-svn-funky-branch-names.sh8
-rwxr-xr-xt/t9119-git-svn-info.sh30
-rwxr-xr-xt/t9120-git-svn-clone-with-percent-escapes.sh71
-rwxr-xr-xt/t9122-git-svn-author.sh12
-rwxr-xr-xt/t9123-git-svn-rebuild-with-rewriteroot.sh2
-rwxr-xr-xt/t9124-git-svn-dcommit-auto-props.sh30
-rwxr-xr-xt/t9125-git-svn-multi-glob-branch-names.sh6
-rwxr-xr-xt/t9127-git-svn-partial-rebuild.sh14
-rwxr-xr-xt/t9128-git-svn-cmd-branch.sh18
-rwxr-xr-xt/t9129-git-svn-i18n-commitencoding.sh32
-rwxr-xr-xt/t9130-git-svn-authors-file.sh29
-rwxr-xr-xt/t9131-git-svn-empty-symlink.sh2
-rwxr-xr-xt/t9132-git-svn-broken-symlink.sh4
-rwxr-xr-xt/t9133-git-svn-nested-git-repo.sh32
-rwxr-xr-xt/t9134-git-svn-ignore-paths.sh87
-rwxr-xr-xt/t9135-git-svn-moved-branch-empty-file.sh7
-rwxr-xr-xt/t9137-git-svn-dcommit-clobber-series.sh (renamed from t/t9106-git-svn-dcommit-clobber-series.sh)8
-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-dump222
-rw-r--r--t/t9151/svn-mergeinfo.dump1922
-rwxr-xr-xt/t9152-svn-empty-dirs-after-gc.sh40
-rwxr-xr-xt/t9153-git-svn-rewrite-uuid.sh25
-rw-r--r--t/t9153/svn.dump75
-rwxr-xr-xt/t9154-git-svn-fancy-glob.sh42
-rw-r--r--t/t9154/svn.dump222
-rwxr-xr-xt/t9200-git-cvsexportcommit.sh44
-rwxr-xr-xt/t9300-fast-import.sh494
-rwxr-xr-xt/t9301-fast-import-notes.sh623
-rwxr-xr-xt/t9350-fast-export.sh (renamed from t/t9301-fast-export.sh)105
-rwxr-xr-xt/t9400-git-cvsserver-server.sh58
-rwxr-xr-xt/t9401-git-cvsserver-crlf.sh23
-rwxr-xr-xt/t9500-gitweb-standalone-no-errors.sh110
-rwxr-xr-xt/t9501-gitweb-standalone-http-status.sh137
-rwxr-xr-xt/t9502-gitweb-standalone-parse-output.sh115
-rwxr-xr-xt/t9600-cvsimport.sh50
-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.sh15
-rwxr-xr-xt/t9700/test.pl25
-rw-r--r--t/test-lib.sh321
-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
399 files changed, 23659 insertions, 1895 deletions
diff --git a/t/Makefile b/t/Makefile
index 9149373032..25c559bb49 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)
@@ -25,6 +27,8 @@ pre-clean:
clean:
$(RM) -r 'trash directory'.* test-results
+ $(RM) t????/cvsroot/CVSROOT/?*
+ $(RM) -r valgrind/bin
aggregate-results-and-cleanup: $(T)
$(MAKE) aggregate-results
@@ -38,4 +42,7 @@ 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: pre-clean $(T) aggregate-results clean
+valgrind:
+ GIT_TEST_OPTS=--valgrind $(MAKE)
+
+.PHONY: pre-clean $(T) aggregate-results clean valgrind
diff --git a/t/README b/t/README
index f208cf1db9..dcd3ebb5f2 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
@@ -58,6 +59,43 @@ You can pass --verbose (or -v), --debug (or -d), and --immediate
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.
+
+--with-dashes::
+ By default tests are run without dashed forms of
+ commands (like git-commit) in the PATH (it only uses
+ wrappers from ../bin-wrappers). Use this option to include
+ the build directory (..) in the PATH, which contains all
+ the dashed forms of commands. This option is currently
+ implied by other options like --valgrind and
+ GIT_TEST_INSTALLED.
+
+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
--------------
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 4bddeb591e..75a35fcd06 100644
--- a/t/diff-lib.sh
+++ b/t/diff-lib.sh
@@ -1,7 +1,5 @@
:
-_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"
sanitize_diff_raw='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]* / X X \1# /'
compare_diff_raw () {
# When heuristics are improved, the score numbers would change.
diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh
new file mode 100644
index 0000000000..5a734b1b7b
--- /dev/null
+++ b/t/gitweb-lib.sh
@@ -0,0 +1,88 @@
+#!/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 = '';
+our \$maxload = undef;
+
+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 67c431d4eb..0f7f35ccc9 100644
--- a/t/lib-git-svn.sh
+++ b/t/lib-git-svn.sh
@@ -5,27 +5,32 @@ 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);
@@ -41,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"
@@ -53,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 \
@@ -114,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]";
@@ -144,7 +161,6 @@ require_svnserve () {
then
say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)'
test_done
- exit
fi
}
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index 86cdebc727..28aff887b5 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
HTTPD_PARA=""
+for DEFAULT_HTTPD_PATH in '/usr/sbin/httpd' '/usr/sbin/apache2'
+do
+ if test -x "$DEFAULT_HTTPD_PATH"
+ then
+ break
+ fi
+done
+
+for DEFAULT_HTTPD_MODULE_PATH in '/usr/libexec/apache2' \
+ '/usr/lib/apache2/modules' \
+ '/usr/lib64/httpd/modules' \
+ '/usr/lib/httpd/modules'
+do
+ if test -d "$DEFAULT_HTTPD_MODULE_PATH"
+ then
+ break
+ fi
+done
+
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"}
@@ -36,7 +48,6 @@ if ! test -x "$LIB_HTTPD_PATH"
then
say "skipping test, no web server found at '$LIB_HTTPD_PATH'"
test_done
- exit
fi
HTTPD_VERSION=`$LIB_HTTPD_PATH -v | \
@@ -50,7 +61,11 @@ then
then
say "skipping test, at least Apache version 2 is required"
test_done
- exit
+ fi
+ if ! test -d "$DEFAULT_HTTPD_MODULE_PATH"
+ then
+ say "Apache module directory not found. Skipping tests."
+ test_done
fi
LIB_HTTPD_MODULE_PATH="$DEFAULT_HTTPD_MODULE_PATH"
@@ -94,13 +109,20 @@ 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" -d "$HTTPD_ROOT_PATH" \
-f "$TEST_PATH/apache.conf" $HTTPD_PARA \
- -c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start
+ -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() {
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index af6e5e1d6a..4961505d1d 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -1,15 +1,40 @@
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
-
-<IfDefine Darwin>
+<IfModule !mod_log_config.c>
LoadModule log_config_module modules/mod_log_config.so
- LockFile accept.lock
- PidFile httpd.pid
-</IfDefine>
+</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}
+ SetEnv GIT_HTTP_EXPORT_ALL
+</Location>
+<Location /smart_noexport/>
+ SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
+</Location>
+ScriptAlias /smart/ ${GIT_EXEC_PATH}/git-http-backend/
+ScriptAlias /smart_noexport/ ${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
@@ -28,7 +53,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 100644
index 0000000000..ce36f34d03
--- /dev/null
+++ b/t/lib-patch-mode.sh
@@ -0,0 +1,43 @@
+: included from t2016 and others
+
+. ./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
index 260a231933..6aefe27593 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -2,21 +2,33 @@
# After setting the fake editor with this function, you can
#
-# - override the commit message with $FAKE_COMMIT_MESSAGE,
+# - 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
+# - check the commit count in the commit message header with $EXPECT_HEADER_COUNT
+# - rewrite a rebase -i script as directed by $FAKE_LINES.
+# $FAKE_LINES consists of a sequence of words separated by spaces.
+# The following word combinations are possible:
#
-# "[<lineno1>] [<lineno2>]..."
+# "<lineno>" -- add a "pick" line with the SHA1 taken from the
+# specified line.
#
-# If a line number is prefixed with "squash" or "edit", the respective line's
-# command will be replaced with the specified one.
+# "<cmd> <lineno>" -- add a line with the specified command
+# ("squash", "fixup", "edit", or "reword") and the SHA1 taken
+# from the specified line.
+#
+# "#" -- Add a comment line.
+#
+# ">" -- Add a blank line.
set_fake_editor () {
echo "#!$SHELL_PATH" >fake-editor.sh
cat >> fake-editor.sh <<\EOF
case "$1" in
*/COMMIT_EDITMSG)
+ test -z "$EXPECT_HEADER_COUNT" ||
+ test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" ||
+ exit
test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
exit
@@ -28,19 +40,24 @@ test -z "$EXPECT_COUNT" ||
test -z "$FAKE_LINES" && exit
grep -v '^#' < "$1" > "$1".tmp
rm -f "$1"
+echo 'rebase -i script before editing:'
cat "$1".tmp
action=pick
for line in $FAKE_LINES; do
case $line in
- squash|edit)
+ squash|fixup|edit|reword)
action="$line";;
+ "#")
+ echo '# comment' >> "$1";;
+ ">")
+ echo >> "$1";;
*)
- 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
+echo 'rebase -i script after editing:'
+cat "$1"
EOF
test_set_editor "$(pwd)/fake-editor.sh"
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 70df15cbd8..f4ca4fc85c 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -57,6 +57,21 @@ 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
@@ -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
@@ -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 &&
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index e3d846420d..5386504790 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -208,4 +208,87 @@ test_expect_success 'init rejects insanely long --template' '
)
'
+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/t0004-unwritable.sh b/t/t0004-unwritable.sh
index 63e1217e71..2342ac5788 100755
--- a/t/t0004-unwritable.sh
+++ b/t/t0004-unwritable.sh
@@ -15,7 +15,7 @@ test_expect_success setup '
'
-test_expect_success 'write-tree should notice unwritable repository' '
+test_expect_success POSIXPERM 'write-tree should notice unwritable repository' '
(
chmod a-w .git/objects .git/objects/?? &&
@@ -27,7 +27,7 @@ test_expect_success 'write-tree should notice unwritable repository' '
'
-test_expect_success 'commit should notice unwritable repository' '
+test_expect_success POSIXPERM 'commit should notice unwritable repository' '
(
chmod a-w .git/objects .git/objects/?? &&
@@ -39,7 +39,7 @@ test_expect_success 'commit should notice unwritable repository' '
'
-test_expect_success 'update-index should notice unwritable repository' '
+test_expect_success POSIXPERM 'update-index should notice unwritable repository' '
(
echo 6O >file &&
@@ -52,7 +52,7 @@ test_expect_success 'update-index should notice unwritable repository' '
'
-test_expect_success 'add should notice unwritable repository' '
+test_expect_success POSIXPERM 'add should notice unwritable repository' '
(
echo b >file &&
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 1be7446d8d..c3e7e322a8 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -4,21 +4,8 @@ test_description='CRLF conversion'
. ./test-lib.sh
-q_to_nul () {
- perl -pe 'y/Q/\000/'
-}
-
-q_to_cr () {
- tr Q '\015'
-}
-
-append_cr () {
- sed -e 's/$/Q/' | tr Q '\015'
-}
-
-remove_cr () {
- tr '\015' Q <"$1" | grep Q >/dev/null &&
- tr '\015' Q <"$1" | sed -ne 's/Q$//p'
+has_cr() {
+ tr '\015' Q <"$1" | grep Q >/dev/null
}
test_expect_success setup '
@@ -156,7 +143,7 @@ test_expect_success 'checkout with autocrlf=true' '
for f in one dir/two
do
- remove_cr "$f" >tmp && mv -f tmp $f &&
+ remove_cr <"$f" >tmp && mv -f tmp $f &&
git update-index -- $f || {
echo "Eh? $f"
false
@@ -180,7 +167,7 @@ test_expect_success 'checkout with autocrlf=input' '
for f in one dir/two
do
- if remove_cr "$f" >/dev/null
+ if has_cr "$f"
then
echo "Eh? $f"
false
@@ -245,7 +232,7 @@ test_expect_success 'apply patch (autocrlf=true)' '
git read-tree --reset -u HEAD &&
git apply patch.file &&
- test "$patched" = "`remove_cr one | git hash-object --stdin`" || {
+ test "$patched" = "`remove_cr <one | git hash-object --stdin`" || {
echo "Eh? apply without index"
false
}
@@ -272,7 +259,7 @@ test_expect_success 'apply patch --index (autocrlf=true)' '
git apply --index patch.file &&
test "$patched" = `git rev-parse :one` &&
- test "$patched" = "`remove_cr one | git hash-object --stdin`" || {
+ test "$patched" = "`remove_cr <one | git hash-object --stdin`" || {
echo "Eh? apply with --index"
false
}
@@ -285,7 +272,7 @@ test_expect_success '.gitattributes says two is binary' '
git config core.autocrlf true &&
git read-tree --reset -u HEAD &&
- if remove_cr dir/two >/dev/null
+ if has_cr dir/two
then
echo "Huh?"
false
@@ -293,7 +280,7 @@ test_expect_success '.gitattributes says two is binary' '
: happy
fi &&
- if remove_cr one >/dev/null
+ if has_cr one
then
: happy
else
@@ -301,7 +288,7 @@ test_expect_success '.gitattributes says two is binary' '
false
fi &&
- if remove_cr three >/dev/null
+ if has_cr three
then
echo "Huh?"
false
@@ -316,7 +303,7 @@ test_expect_success '.gitattributes says two is input' '
echo "two crlf=input" >.gitattributes &&
git read-tree --reset -u HEAD &&
- if remove_cr dir/two >/dev/null
+ if has_cr dir/two
then
echo "Huh?"
false
@@ -331,7 +318,7 @@ test_expect_success '.gitattributes says two and three are text' '
echo "t* crlf" >.gitattributes &&
git read-tree --reset -u HEAD &&
- if remove_cr dir/two >/dev/null
+ if has_cr dir/two
then
: happy
else
@@ -339,7 +326,7 @@ test_expect_success '.gitattributes says two and three are text' '
false
fi &&
- if remove_cr three >/dev/null
+ if has_cr three
then
: happy
else
@@ -357,14 +344,14 @@ test_expect_success 'in-tree .gitattributes (1)' '
rm -rf tmp one dir .gitattributes patch.file three &&
git read-tree --reset -u HEAD &&
- if remove_cr one >/dev/null
+ if has_cr one
then
echo "Eh? one should not have CRLF"
false
else
: happy
fi &&
- remove_cr three >/dev/null || {
+ has_cr three || {
echo "Eh? three should still have CRLF"
false
}
@@ -376,14 +363,14 @@ test_expect_success 'in-tree .gitattributes (2)' '
git read-tree --reset HEAD &&
git checkout-index -f -q -u -a &&
- if remove_cr one >/dev/null
+ if has_cr one
then
echo "Eh? one should not have CRLF"
false
else
: happy
fi &&
- remove_cr three >/dev/null || {
+ has_cr three || {
echo "Eh? three should still have CRLF"
false
}
@@ -396,14 +383,14 @@ test_expect_success 'in-tree .gitattributes (3)' '
git checkout-index -u .gitattributes &&
git checkout-index -u one dir/two three &&
- if remove_cr one >/dev/null
+ if has_cr one
then
echo "Eh? one should not have CRLF"
false
else
: happy
fi &&
- remove_cr three >/dev/null || {
+ has_cr three || {
echo "Eh? three should still have CRLF"
false
}
@@ -416,19 +403,50 @@ test_expect_success 'in-tree .gitattributes (4)' '
git checkout-index -u one dir/two three &&
git checkout-index -u .gitattributes &&
- if remove_cr one >/dev/null
+ if has_cr one
then
echo "Eh? one should not have CRLF"
false
else
: happy
fi &&
- remove_cr three >/dev/null || {
+ has_cr three || {
echo "Eh? three should still have CRLF"
false
}
'
+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 &&
+ has_cr .file2
+
+'
+
test_expect_success 'invalid .gitattributes (must not crash)' '
echo "three +crlf" >>.gitattributes &&
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index 8fc39d77ce..6cb8d60ea2 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -4,7 +4,8 @@ test_description='blob conversion via gitattributes'
. ./test-lib.sh
-cat <<\EOF >rot13.sh
+cat <<EOF >rot13.sh
+#!$SHELL_PATH
tr \
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \
'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
diff --git a/t/t0022-crlf-rename.sh b/t/t0022-crlf-rename.sh
index f1e1d48869..7af3fbcc7b 100755
--- a/t/t0022-crlf-rename.sh
+++ b/t/t0022-crlf-rename.sh
@@ -12,7 +12,7 @@ test_expect_success setup '
test_tick &&
git commit -m Initial &&
- sed -e "s/\$/ /" "$TEST_DIRECTORY"/t0022-crlf-rename.sh >elpmas &&
+ append_cr <"$TEST_DIRECTORY"/t0022-crlf-rename.sh >elpmas &&
git add elpmas &&
rm -f sample &&
diff --git a/t/t0024-crlf-archive.sh b/t/t0024-crlf-archive.sh
index e5330395fc..c7d0324374 100755
--- a/t/t0024-crlf-archive.sh
+++ b/t/t0024-crlf-archive.sh
@@ -28,12 +28,12 @@ test_expect_success 'tar archive' '
"$UNZIP" -v >/dev/null 2>&1
if [ $? -eq 127 ]; then
- echo "Skipping ZIP test, because unzip was not found"
- test_done
- exit
+ say "Skipping ZIP test, because unzip was not found"
+else
+ test_set_prereq UNZIP
fi
-test_expect_success 'zip archive' '
+test_expect_success UNZIP 'zip archive' '
git archive --format=zip HEAD >test.zip &&
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index e38241c80a..3d450ed379 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -12,12 +12,14 @@ 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
-s, --string <string>
@@ -29,6 +31,10 @@ String options
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
@@ -53,10 +59,12 @@ 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 -vv -n > output 2> output.err &&
+ 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
'
@@ -70,11 +78,12 @@ 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 \
+ --verbose --verbose --no-dry-run --abbrev=10 --file fi.le\
> output 2> output.err &&
test ! -s output.err &&
test_cmp expect output
@@ -84,6 +93,8 @@ test_expect_success 'missing required value' '
test-parse-options -s;
test $? = 129 &&
test-parse-options --string;
+ test $? = 129 &&
+ test-parse-options --file;
test $? = 129
'
@@ -96,6 +107,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
arg 00: a1
arg 01: b1
arg 02: --boolean
@@ -117,6 +129,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'unambiguously abbreviated option' '
@@ -145,6 +158,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'non ambiguous option (after two options it abbreviates)' '
@@ -172,6 +186,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
arg 00: --quux
EOF
@@ -190,6 +205,7 @@ abbrev: 7
verbose: 0
quiet: yes
dry run: no
+file: (not set)
arg 00: foo
EOF
@@ -210,6 +226,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
@@ -237,6 +254,7 @@ abbrev: 7
verbose: 0
quiet: no
dry run: no
+file: (not set)
EOF
test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
@@ -245,7 +263,76 @@ test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
test_cmp expect output
'
-# --or4
-# --no-or4
+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 7edf49db3c..41df6bcf27 100755
--- a/t/t0050-filesystem.sh
+++ b/t/t0050-filesystem.sh
@@ -8,7 +8,9 @@ auml=`printf '\xc3\xa4'`
aumlcdiar=`printf '\x61\xcc\x88'`
case_insensitive=
-test_expect_success 'see if we expect ' '
+unibad=
+no_symlinks=
+test_expect_success 'see what we expect' '
test_case=test_expect_success
test_unicode=test_expect_success
@@ -19,7 +21,6 @@ test_expect_success 'see if we expect ' '
then
test_case=test_expect_failure
case_insensitive=t
- say "will test on a case insensitive filesystem"
fi &&
rm -fr junk &&
mkdir junk &&
@@ -27,13 +28,26 @@ 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" '
@@ -48,6 +62,21 @@ test_expect_success "detection of case insensitive filesystem during repo init"
'
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 &&
@@ -79,13 +108,17 @@ $test_case 'merge (case change)' '
'
-$test_case 'add (with different case)' '
+
+
+test_expect_failure '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
+ camel=$(git ls-files | grep -i camelcase) &&
+ test $(echo "$camel" | wc -l) = 1 &&
+ test "z$(git cat-file blob :$camel)" = z1
'
diff --git a/t/t0055-beyond-symlinks.sh b/t/t0055-beyond-symlinks.sh
index b29c37a5a4..0c6ff567a1 100755
--- a/t/t0055-beyond-symlinks.sh
+++ b/t/t0055-beyond-symlinks.sh
@@ -4,7 +4,7 @@ test_description='update-index and add refuse to add beyond symlinks'
. ./test-lib.sh
-test_expect_success setup '
+test_expect_success SYMLINKS setup '
>a &&
mkdir b &&
ln -s b c &&
@@ -12,12 +12,12 @@ test_expect_success setup '
git update-index --add a b/d
'
-test_expect_success 'update-index --add beyond symlinks' '
+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 'add beyond symlinks' '
+test_expect_success SYMLINKS 'add beyond symlinks' '
test_must_fail git add c/d &&
! ( git ls-files | grep c/d )
'
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 8336114f98..53cf1f8dc4 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -7,41 +7,91 @@ test_description='Test various path utilities'
. ./test-lib.sh
-norm_abs() {
- test_expect_success "normalize absolute: $1 => $2" \
+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() {
- test_expect_success "longest ancestor: $1 $2 => $3" \
- "test \"\$(test-path-utils longest_ancestor_length '$1' '$2')\" = '$3'"
+ # 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'"
}
-norm_abs "" ""
-norm_abs / /
-norm_abs // /
-norm_abs /// /
-norm_abs /. /
-norm_abs /./ /
-norm_abs /./.. ++failed++
-norm_abs /../. ++failed++
-norm_abs /./../.// ++failed++
-norm_abs /dir/.. /
-norm_abs /dir/sub/../.. /
-norm_abs /dir/sub/../../.. ++failed++
-norm_abs /dir /dir
-norm_abs /dir// /dir/
-norm_abs /./dir /dir
-norm_abs /dir/. /dir/
-norm_abs /dir///./ /dir/
-norm_abs /dir//sub/.. /dir/
-norm_abs /dir/sub/../ /dir/
-norm_abs //dir/sub/../. /dir/
-norm_abs /dir/s1/../s2/ /dir/s2/
-norm_abs /d1/s1///s2/..//../s3/ /d1/s3/
-norm_abs /d1/s1//../s2/../../d2 /d2
-norm_abs /d1/.../d2 /d1/.../d2
-norm_abs /d1/..././../d2 /d1/d2
+# 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
@@ -80,10 +130,10 @@ 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
+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 \
diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh
new file mode 100755
index 0000000000..10b26e4d8e
--- /dev/null
+++ b/t/t0061-run-command.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Ilari Liusvaara
+#
+
+test_description='Test run command'
+
+. ./test-lib.sh
+
+test_expect_success 'start_command reports ENOENT' '
+ test-run-command start-command-ENOENT ./does-not-exist
+'
+
+test_done
diff --git a/t/t0101-at-syntax.sh b/t/t0101-at-syntax.sh
new file mode 100755
index 0000000000..a1998b558f
--- /dev/null
+++ b/t/t0101-at-syntax.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+test_description='various @{whatever} syntax tests'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit one &&
+ test_commit two
+'
+
+check_at() {
+ echo "$2" >expect &&
+ git log -1 --format=%s "$1" >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success '@{0} shows current' '
+ check_at @{0} two
+'
+
+test_expect_success '@{1} shows old' '
+ check_at @{1} one
+'
+
+test_expect_success '@{now} shows current' '
+ check_at @{now} two
+'
+
+test_expect_success '@{2001-09-17} (before the first commit) shows old' '
+ check_at @{2001-09-17} one
+'
+
+test_expect_success 'silly approxidates work' '
+ check_at @{3.hot.dogs.on.2001-09-17} one
+'
+
+test_expect_success 'notice misspelled upstream' '
+ test_must_fail git log -1 --format=%s @{usptream}
+'
+
+test_expect_success 'complain about total nonsense' '
+ test_must_fail git log -1 --format=%s @{utter.bogosity}
+'
+
+test_done
diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh
index 22ba7a5442..4f171722d9 100755
--- a/t/t1000-read-tree-m-3way.sh
+++ b/t/t1000-read-tree-m-3way.sh
@@ -126,9 +126,6 @@ cat >expected <<\EOF
100644 X 0 Z/NN
EOF
-_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"
-
check_result () {
git ls-files --stage | sed -e 's/ '"$_x40"' / X /' >current &&
test_cmp expected current
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 271bc4e17f..6327d205cb 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
@@ -26,8 +26,6 @@ read_tree_twoway () {
git read-tree -m "$1" "$2" && git ls-files --stage
}
-_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 -n >current \
-e '/^--- /d; /^+++ /d; /^@@ /d;' \
@@ -51,7 +49,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
@@ -300,7 +298,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 &&
diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh
index 5e40cec530..0241329a08 100755
--- a/t/t1002-read-tree-m-u-2way.sh
+++ b/t/t1002-read-tree-m-u-2way.sh
@@ -10,8 +10,6 @@ This is identical to t1001, but uses -u to update the work tree as well.
'
. ./test-lib.sh
-_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;}' \
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/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/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh
new file mode 100755
index 0000000000..62246dbf95
--- /dev/null
+++ b/t/t1011-read-tree-sparse-checkout.sh
@@ -0,0 +1,150 @@
+#!/bin/sh
+
+test_description='sparse checkout tests'
+
+. ./test-lib.sh
+
+cat >expected <<EOF
+100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t
+100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/added
+EOF
+test_expect_success 'setup' '
+ test_commit init &&
+ echo modified >> init.t &&
+ mkdir sub &&
+ touch sub/added &&
+ git add init.t sub/added &&
+ git commit -m "modified and added" &&
+ git tag top &&
+ git rm sub/added &&
+ git commit -m removed &&
+ git tag removed &&
+ git checkout top &&
+ git ls-files --stage > result &&
+ test_cmp expected result
+'
+
+cat >expected.swt <<EOF
+H init.t
+H sub/added
+EOF
+test_expect_success 'read-tree without .git/info/sparse-checkout' '
+ git read-tree -m -u HEAD &&
+ git ls-files --stage > result &&
+ test_cmp expected result &&
+ git ls-files -t > result &&
+ test_cmp expected.swt result
+'
+
+test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' '
+ echo > .git/info/sparse-checkout
+ git read-tree -m -u HEAD &&
+ git ls-files -t > result &&
+ test_cmp expected.swt result &&
+ test -f init.t &&
+ test -f sub/added
+'
+
+test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse-checkout and enabled' '
+ git config core.sparsecheckout true &&
+ echo > .git/info/sparse-checkout &&
+ git read-tree --no-sparse-checkout -m -u HEAD &&
+ git ls-files -t > result &&
+ test_cmp expected.swt result &&
+ test -f init.t &&
+ test -f sub/added
+'
+
+test_expect_success 'read-tree with empty .git/info/sparse-checkout' '
+ git config core.sparsecheckout true &&
+ echo > .git/info/sparse-checkout &&
+ test_must_fail git read-tree -m -u HEAD &&
+ git ls-files --stage > result &&
+ test_cmp expected result &&
+ git ls-files -t > result &&
+ test_cmp expected.swt result &&
+ test -f init.t &&
+ test -f sub/added
+'
+
+cat >expected.swt <<EOF
+S init.t
+H sub/added
+EOF
+test_expect_success 'match directories with trailing slash' '
+ echo sub/ > .git/info/sparse-checkout &&
+ git read-tree -m -u HEAD &&
+ git ls-files -t > result &&
+ test_cmp expected.swt result &&
+ test ! -f init.t &&
+ test -f sub/added
+'
+
+cat >expected.swt <<EOF
+H init.t
+H sub/added
+EOF
+test_expect_failure 'match directories without trailing slash' '
+ echo init.t > .git/info/sparse-checkout &&
+ echo sub >> .git/info/sparse-checkout &&
+ git read-tree -m -u HEAD &&
+ git ls-files -t > result &&
+ test_cmp expected.swt result &&
+ test ! -f init.t &&
+ test -f sub/added
+'
+
+cat >expected.swt <<EOF
+H init.t
+S sub/added
+EOF
+test_expect_success 'checkout area changes' '
+ echo init.t > .git/info/sparse-checkout &&
+ git read-tree -m -u HEAD &&
+ git ls-files -t > result &&
+ test_cmp expected.swt result &&
+ test -f init.t &&
+ test ! -f sub/added
+'
+
+test_expect_success 'read-tree updates worktree, absent case' '
+ echo sub/added > .git/info/sparse-checkout &&
+ git checkout -f top &&
+ git read-tree -m -u HEAD^ &&
+ test ! -f init.t
+'
+
+test_expect_success 'read-tree updates worktree, dirty case' '
+ echo sub/added > .git/info/sparse-checkout &&
+ git checkout -f top &&
+ echo dirty > init.t &&
+ git read-tree -m -u HEAD^ &&
+ grep -q dirty init.t &&
+ rm init.t
+'
+
+test_expect_success 'read-tree removes worktree, dirty case' '
+ echo init.t > .git/info/sparse-checkout &&
+ git checkout -f top &&
+ echo dirty > added &&
+ git read-tree -m -u HEAD^ &&
+ grep -q dirty added
+'
+
+test_expect_success 'read-tree adds to worktree, absent case' '
+ echo init.t > .git/info/sparse-checkout &&
+ git checkout -f removed &&
+ git read-tree -u -m HEAD^ &&
+ test ! -f sub/added
+'
+
+test_expect_success 'read-tree adds to worktree, dirty case' '
+ echo init.t > .git/info/sparse-checkout &&
+ git checkout -f removed &&
+ mkdir sub &&
+ echo dirty > sub/added &&
+ git read-tree -u -m HEAD^ &&
+ grep -q dirty sub/added
+'
+
+test_done
diff --git a/t/t1012-read-tree-df.sh b/t/t1012-read-tree-df.sh
new file mode 100755
index 0000000000..9811d467da
--- /dev/null
+++ b/t/t1012-read-tree-df.sh
@@ -0,0 +1,102 @@
+#!/bin/sh
+
+test_description='read-tree D/F conflict corner cases'
+
+. ./test-lib.sh
+
+maketree () {
+ (
+ rm -f .git/index .git/index.lock &&
+ git clean -d -f -f -q -x &&
+ name="$1" &&
+ shift &&
+ for it
+ do
+ path=$(expr "$it" : '\([^:]*\)') &&
+ mkdir -p $(dirname "$path") &&
+ echo "$it" >"$path" &&
+ git update-index --add "$path" || exit
+ done &&
+ git tag "$name" $(git write-tree)
+ )
+}
+
+settree () {
+ rm -f .git/index .git/index.lock &&
+ git clean -d -f -f -q -x &&
+ git read-tree "$1" &&
+ git checkout-index -f -q -u -a &&
+ git update-index --refresh
+}
+
+checkindex () {
+ git ls-files -s |
+ sed "s|^[0-7][0-7]* $_x40 \([0-3]\) |\1 |" >current &&
+ cat >expect &&
+ test_cmp expect current
+}
+
+test_expect_success setup '
+ maketree O-000 a/b-2/c/d a/b/c/d a/x &&
+ maketree A-000 a/b-2/c/d a/b/c/d a/x &&
+ maketree A-001 a/b-2/c/d a/b/c/d a/b/c/e a/x &&
+ maketree B-000 a/b-2/c/d a/b a/x &&
+
+ maketree O-010 t-0 t/1 t/2 t=3 &&
+ maketree A-010 t-0 t t=3 &&
+ maketree B-010 t/1: t=3: &&
+
+ maketree O-020 ds/dma/ioat.c ds/dma/ioat_dca.c &&
+ maketree A-020 ds/dma/ioat/Makefile ds/dma/ioat/registers.h &&
+ :
+'
+
+test_expect_success '3-way (1)' '
+ settree A-000 &&
+ git read-tree -m -u O-000 A-000 B-000 &&
+ checkindex <<-EOF
+ 3 a/b
+ 0 a/b-2/c/d
+ 1 a/b/c/d
+ 2 a/b/c/d
+ 0 a/x
+ EOF
+'
+
+test_expect_success '3-way (2)' '
+ settree A-001 &&
+ git read-tree -m -u O-000 A-001 B-000 &&
+ checkindex <<-EOF
+ 3 a/b
+ 0 a/b-2/c/d
+ 1 a/b/c/d
+ 2 a/b/c/d
+ 2 a/b/c/e
+ 0 a/x
+ EOF
+'
+
+test_expect_success '3-way (3)' '
+ settree A-010 &&
+ git read-tree -m -u O-010 A-010 B-010 &&
+ checkindex <<-EOF
+ 2 t
+ 1 t-0
+ 2 t-0
+ 1 t/1
+ 3 t/1
+ 1 t/2
+ 0 t=3
+ EOF
+'
+
+test_expect_success '2-way (1)' '
+ settree O-020 &&
+ git read-tree -m -u O-020 A-020 &&
+ checkindex <<-EOF
+ 0 ds/dma/ioat/Makefile
+ 0 ds/dma/ioat/registers.h
+ EOF
+'
+
+test_done
diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh
index fc386ba033..210e594f6f 100755
--- a/t/t1020-subdirectory.sh
+++ b/t/t1020-subdirectory.sh
@@ -126,7 +126,7 @@ test_expect_success 'no file/rev ambiguity check inside a bare repo' '
cd foo.git && git show -s HEAD
'
-test_expect_success 'detection should not be fooled by a symlink' '
+test_expect_success SYMLINKS 'detection should not be fooled by a symlink' '
cd "$HERE" &&
rm -fr foo.git &&
git clone -s .git another &&
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 67e637b781..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,39 +83,47 @@ 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' '
test_must_fail git merge -m "Merge work in mybranch" mybranch
'
@@ -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 3c06842d99..f11f98c3ce 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'
@@ -391,6 +398,17 @@ test_expect_success 'alternative GIT_CONFIG' 'cmp output expect'
test_expect_success 'alternative GIT_CONFIG (--file)' \
'git config --file other-config -l > output && cmp output expect'
+test_expect_success 'refer config from subdirectory' '
+ mkdir x &&
+ (
+ cd x &&
+ echo strasse >expect
+ git config --get --file ../other-config ein.bahn >actual &&
+ test_cmp expect actual
+ )
+
+'
+
GIT_CONFIG=other-config git config anwohner.park ausweis
cat > expect << EOF
@@ -453,6 +471,28 @@ EOF
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"]
EOF
@@ -654,6 +694,34 @@ test_expect_success 'set --bool-or-int' '
rm .git/config
+cat >expect <<\EOF
+[path]
+ home = ~/
+ normal = /dev/null
+ trailingtilde = foo~
+EOF
+
+test_expect_success 'set --path' '
+ git config --path path.home "~/" &&
+ git config --path path.normal "/dev/null" &&
+ git config --path path.trailingtilde "foo~" &&
+ test_cmp expect .git/config'
+
+cat >expect <<EOF
+$HOME/
+/dev/null
+foo~
+EOF
+
+test_expect_success 'get --path' '
+ git config --get --path path.home > result &&
+ git config --get --path path.normal >> result &&
+ git config --get --path path.trailingtilde >> result &&
+ test_cmp expect result
+'
+
+rm .git/config
+
git config quote.leading " test"
git config quote.ending "test "
git config quote.semicolon "test;test"
@@ -726,7 +794,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 &&
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 3fddc9ee78..de42d21c92 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -26,7 +26,7 @@ modebits () {
for u in 002 022
do
- test_expect_success "shared=1 does not clear bits preset by umask $u" '
+ test_expect_success POSIXPERM "shared=1 does not clear bits preset by umask $u" '
mkdir sub && (
cd sub &&
umask $u &&
@@ -54,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 &&
@@ -85,7 +85,7 @@ 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 &&
@@ -97,7 +97,7 @@ 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 &&
@@ -111,7 +111,7 @@ do
done
-test_expect_success 'git reflog expire honors core.sharedRepository' '
+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)" &&
@@ -126,7 +126,7 @@ test_expect_success 'git reflog expire honors core.sharedRepository' '
esac
'
-test_expect_success 'forced modes' '
+test_expect_success POSIXPERM 'forced modes' '
mkdir -p templates/hooks &&
echo update-server-info >templates/hooks/post-update &&
chmod +x templates/hooks/post-update &&
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
new file mode 100755
index 0000000000..cc30be4a65
--- /dev/null
+++ b/t/t1304-default-acl.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Matthieu Moy
+#
+
+test_description='Test repository with default ACL'
+
+# Create the test repo with restrictive umask
+# => this must come before . ./test-lib.sh
+umask 077
+
+. ./test-lib.sh
+
+# We need an arbitrary other user give permission to using ACLs. root
+# is a good candidate: exists on all unices, and it has permission
+# anyway, so we don't create a security hole running the testsuite.
+
+if ! setfacl -m u:root:rwx .; then
+ say "Skipping ACL tests: unable to use setfacl"
+ test_done
+fi
+
+modebits () {
+ ls -l "$1" | sed -e 's|^\(..........\).*|\1|'
+}
+
+check_perms_and_acl () {
+ actual=$(modebits "$1") &&
+ case "$actual" in
+ -r--r-----*)
+ : happy
+ ;;
+ *)
+ echo "Got permission '$actual', expected '-r--r-----'"
+ false
+ ;;
+ esac &&
+ getfacl "$1" > actual &&
+ grep -q "user:root:rwx" actual &&
+ grep -q "user:${LOGNAME}:rwx" actual &&
+ grep -q "mask::r--" actual &&
+ grep -q "group::---" actual || false
+}
+
+dirs_to_set="./ .git/ .git/objects/ .git/objects/pack/"
+
+test_expect_success 'Setup test repo' '
+ setfacl -m u:root:rwx $dirs_to_set &&
+ setfacl -d -m u:"$LOGNAME":rwx $dirs_to_set &&
+ setfacl -d -m u:root:rwx $dirs_to_set &&
+
+ touch file.txt &&
+ git add file.txt &&
+ git commit -m "init"
+'
+
+test_expect_success 'Objects creation does not break ACLs with restrictive umask' '
+ # SHA1 for empty blob
+ check_perms_and_acl .git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
+'
+
+test_expect_success 'git gc does not break ACLs with restrictive umask' '
+ git gc &&
+ check_perms_and_acl .git/objects/pack/*.pack
+'
+
+test_done
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index bd589268fc..54ba3df95f 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -137,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 \
@@ -168,7 +168,7 @@ $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
@@ -272,7 +272,7 @@ $h_FIXED $h_MERGED $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117151100 +0000 c
EOF
test_expect_success \
'git commit logged updates' \
- "diff expect .git/logs/$m"
+ "test_cmp expect .git/logs/$m"
unset h_TEST h_OTHER h_FIXED h_MERGED
test_expect_success \
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 5b24f05573..25046c4208 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` &&
@@ -216,4 +214,45 @@ test_expect_success 'delete' '
'
+test_expect_success 'rewind2' '
+
+ test_tick && git reset --hard HEAD~2 &&
+ loglen=$(wc -l <.git/logs/refs/heads/master) &&
+ test $loglen = 4
+
+'
+
+test_expect_success '--expire=never' '
+
+ git reflog expire --verbose \
+ --expire=never \
+ --expire-unreachable=never \
+ --all &&
+ loglen=$(wc -l <.git/logs/refs/heads/master) &&
+ test $loglen = 4
+
+'
+
+test_expect_success 'gc.reflogexpire=never' '
+
+ git config gc.reflogexpire never &&
+ git config gc.reflogexpireunreachable never &&
+ git reflog expire --verbose --all &&
+ loglen=$(wc -l <.git/logs/refs/heads/master) &&
+ test $loglen = 4
+'
+
+test_expect_success 'gc.reflogexpire=false' '
+
+ git config gc.reflogexpire false &&
+ git config gc.reflogexpireunreachable false &&
+ git reflog expire --verbose --all &&
+ loglen=$(wc -l <.git/logs/refs/heads/master) &&
+ test $loglen = 4 &&
+
+ git config --unset gc.reflogexpire &&
+ git config --unset gc.reflogexpireunreachable
+
+'
+
test_done
diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh
new file mode 100755
index 0000000000..ba25ff354d
--- /dev/null
+++ b/t/t1411-reflog-show.sh
@@ -0,0 +1,76 @@
+#!/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
+'
+
+: >expect
+test_expect_success 'empty reflog file' '
+ git branch empty &&
+ : >.git/logs/refs/heads/empty &&
+
+ git log -g empty >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 4597af0eb6..49cae3ed52 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -28,4 +28,71 @@ test_expect_success 'loose objects borrowed from alternate are not missing' '
)
'
+# 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_success 'tag pointing to nonexistent' '
+ tag=$(git hash-object -t tag -w --stdin < invalid-tag) &&
+ echo $tag > .git/refs/tags/invalid &&
+ test_must_fail git fsck --tags >out &&
+ cat out &&
+ grep "broken link" 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_success 'tag pointing to something else than its type' '
+ tag=$(git hash-object -t tag -w --stdin < wrong-tag) &&
+ echo $tag > .git/refs/tags/wrong &&
+ test_must_fail git fsck --tags 2>out &&
+ cat out &&
+ grep "error in tag.*broken links" out &&
+ rm .git/refs/tags/wrong
+'
+
+
+
test_done
diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh
index f6a6f839a1..9df301211c 100755
--- a/t/t1501-worktree.sh
+++ b/t/t1501-worktree.sh
@@ -174,4 +174,25 @@ test_expect_success 'git grep' '
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 997002d4c4..e504058062 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -20,8 +20,7 @@ Extras
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
+
+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/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh
index e377d48902..df5ad8c686 100755
--- a/t/t1504-ceiling-dirs.sh
+++ b/t/t1504-ceiling-dirs.sh
@@ -13,7 +13,7 @@ test_fail() {
"git rev-parse --show-prefix"
}
-TRASH_ROOT="$(pwd)"
+TRASH_ROOT="$PWD"
ROOT_PARENT=$(dirname "$TRASH_ROOT")
diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh
new file mode 100755
index 0000000000..af721f9719
--- /dev/null
+++ b/t/t1506-rev-parse-diagnosis.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+test_description='test git rev-parse diagnosis for invalid argument'
+
+exec </dev/null
+
+. ./test-lib.sh
+
+HASH_file=
+
+test_expect_success 'set up basic repo' '
+ echo one > file.txt &&
+ mkdir subdir &&
+ echo two > subdir/file.txt &&
+ echo three > subdir/file2.txt &&
+ git add . &&
+ git commit -m init &&
+ echo four > index-only.txt &&
+ git add index-only.txt &&
+ echo five > disk-only.txt
+'
+
+test_expect_success 'correct file objects' '
+ HASH_file=$(git rev-parse HEAD:file.txt) &&
+ git rev-parse HEAD:subdir/file.txt &&
+ git rev-parse :index-only.txt &&
+ (cd subdir &&
+ git rev-parse HEAD:subdir/file2.txt &&
+ test $HASH_file = $(git rev-parse HEAD:file.txt) &&
+ test $HASH_file = $(git rev-parse :file.txt) &&
+ test $HASH_file = $(git rev-parse :0:file.txt) )
+'
+
+test_expect_success 'incorrect revision id' '
+ test_must_fail git rev-parse foobar:file.txt 2>error &&
+ grep "Invalid object name '"'"'foobar'"'"'." error &&
+ test_must_fail git rev-parse foobar 2> error &&
+ grep "unknown revision or path not in the working tree." error
+'
+
+test_expect_success 'incorrect file in sha1:path' '
+ test_must_fail git rev-parse HEAD:nothing.txt 2> error &&
+ grep "fatal: Path '"'"'nothing.txt'"'"' does not exist in '"'"'HEAD'"'"'" error &&
+ test_must_fail git rev-parse HEAD:index-only.txt 2> error &&
+ grep "fatal: Path '"'"'index-only.txt'"'"' exists on disk, but not in '"'"'HEAD'"'"'." error &&
+ (cd subdir &&
+ test_must_fail git rev-parse HEAD:file2.txt 2> error &&
+ grep "Did you mean '"'"'HEAD:subdir/file2.txt'"'"'?" error )
+'
+
+test_expect_success 'incorrect file in :path and :N:path' '
+ test_must_fail git rev-parse :nothing.txt 2> error &&
+ grep "fatal: Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error &&
+ test_must_fail git rev-parse :1:nothing.txt 2> error &&
+ grep "Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error &&
+ test_must_fail git rev-parse :1:file.txt 2> error &&
+ grep "Did you mean '"'"':0:file.txt'"'"'?" error &&
+ (cd subdir &&
+ test_must_fail git rev-parse :1:file.txt 2> error &&
+ grep "Did you mean '"'"':0:file.txt'"'"'?" error &&
+ test_must_fail git rev-parse :file2.txt 2> error &&
+ grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error &&
+ test_must_fail git rev-parse :2:file2.txt 2> error &&
+ grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error) &&
+ test_must_fail git rev-parse :disk-only.txt 2> error &&
+ grep "fatal: Path '"'"'disk-only.txt'"'"' exists on disk, but not in the index." error
+'
+
+test_done
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
new file mode 100755
index 0000000000..8c8dfdaf9f
--- /dev/null
+++ b/t/t1507-rev-parse-upstream.sh
@@ -0,0 +1,139 @@
+#!/bin/sh
+
+test_description='test <branch>@{upstream} syntax'
+
+. ./test-lib.sh
+
+
+test_expect_success 'setup' '
+
+ test_commit 1 &&
+ git checkout -b side &&
+ test_commit 2 &&
+ git checkout master &&
+ git clone . clone &&
+ test_commit 3 &&
+ (cd clone &&
+ test_commit 4 &&
+ git branch --track my-side origin/side)
+
+'
+
+full_name () {
+ (cd clone &&
+ git rev-parse --symbolic-full-name "$@")
+}
+
+commit_subject () {
+ (cd clone &&
+ git show -s --pretty=format:%s "$@")
+}
+
+test_expect_success '@{upstream} resolves to correct full name' '
+ test refs/remotes/origin/master = "$(full_name @{upstream})"
+'
+
+test_expect_success '@{u} resolves to correct full name' '
+ test refs/remotes/origin/master = "$(full_name @{u})"
+'
+
+test_expect_success 'my-side@{upstream} resolves to correct full name' '
+ test refs/remotes/origin/side = "$(full_name my-side@{u})"
+'
+
+test_expect_success 'my-side@{u} resolves to correct commit' '
+ git checkout side &&
+ test_commit 5 &&
+ (cd clone && git fetch) &&
+ test 2 = "$(commit_subject my-side)" &&
+ test 5 = "$(commit_subject my-side@{u})"
+'
+
+test_expect_success 'not-tracking@{u} fails' '
+ test_must_fail full_name non-tracking@{u} &&
+ (cd clone && git checkout --no-track -b non-tracking) &&
+ test_must_fail full_name non-tracking@{u}
+'
+
+test_expect_success '<branch>@{u}@{1} resolves correctly' '
+ test_commit 6 &&
+ (cd clone && git fetch) &&
+ test 5 = $(commit_subject my-side@{u}@{1})
+'
+
+test_expect_success '@{u} without specifying branch fails on a detached HEAD' '
+ git checkout HEAD^0 &&
+ test_must_fail git rev-parse @{u}
+'
+
+test_expect_success 'checkout -b new my-side@{u} forks from the same' '
+(
+ cd clone &&
+ git checkout -b new my-side@{u} &&
+ git rev-parse --symbolic-full-name my-side@{u} >expect &&
+ git rev-parse --symbolic-full-name new@{u} >actual &&
+ test_cmp expect actual
+)
+'
+
+test_expect_success 'merge my-side@{u} records the correct name' '
+(
+ sq="'\''" &&
+ cd clone || exit
+ git checkout master || exit
+ git branch -D new ;# can fail but is ok
+ git branch -t new my-side@{u} &&
+ git merge -s ours new@{u} &&
+ git show -s --pretty=format:%s >actual &&
+ echo "Merge remote branch ${sq}origin/side${sq}" >expect &&
+ test_cmp expect actual
+)
+'
+
+test_expect_success 'branch -d other@{u}' '
+ git checkout -t -b other master &&
+ git branch -d @{u} &&
+ git for-each-ref refs/heads/master >actual &&
+ >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'checkout other@{u}' '
+ git branch -f master HEAD &&
+ git checkout -t -b another master &&
+ git checkout @{u} &&
+ git symbolic-ref HEAD >actual &&
+ echo refs/heads/master >expect &&
+ test_cmp expect actual
+'
+
+cat >expect <<EOF
+commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5
+Reflog: master@{0} (C O Mitter <committer@example.com>)
+Reflog message: branch: Created from HEAD
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:15:13 2005 -0700
+
+ 3
+EOF
+test_expect_success 'log -g other@{u}' '
+ git log -1 -g other@{u} >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<EOF
+commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5
+Reflog: master@{Thu Apr 7 15:17:13 2005 -0700} (C O Mitter <committer@example.com>)
+Reflog message: branch: Created from HEAD
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:15:13 2005 -0700
+
+ 3
+EOF
+
+test_expect_success 'log -g other@{u}@{now}' '
+ git log -1 -g other@{u}@{now} >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh
new file mode 100755
index 0000000000..d5d6244178
--- /dev/null
+++ b/t/t1508-at-combinations.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+test_description='test various @{X} syntax combinations together'
+. ./test-lib.sh
+
+check() {
+test_expect_${3:-success} "$1 = $2" "
+ echo '$2' >expect &&
+ git log -1 --format=%s '$1' >actual &&
+ test_cmp expect actual
+"
+}
+nonsense() {
+test_expect_${2:-success} "$1 is nonsensical" "
+ test_must_fail git log -1 '$1'
+"
+}
+fail() {
+ "$@" failure
+}
+
+test_expect_success 'setup' '
+ test_commit master-one &&
+ test_commit master-two &&
+ git checkout -b upstream-branch &&
+ test_commit upstream-one &&
+ test_commit upstream-two &&
+ git checkout -b old-branch &&
+ test_commit old-one &&
+ test_commit old-two &&
+ git checkout -b new-branch &&
+ test_commit new-one &&
+ test_commit new-two &&
+ git config branch.old-branch.remote . &&
+ git config branch.old-branch.merge refs/heads/master &&
+ git config branch.new-branch.remote . &&
+ git config branch.new-branch.merge refs/heads/upstream-branch
+'
+
+check HEAD new-two
+check "@{1}" new-one
+check "@{-1}" old-two
+check "@{-1}@{1}" old-one
+check "@{u}" upstream-two
+check "@{u}@{1}" upstream-one
+check "@{-1}@{u}" master-two
+check "@{-1}@{u}@{1}" master-one
+nonsense "@{u}@{-1}"
+nonsense "@{1}@{u}"
+
+test_done
diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh
index f7e1a735ec..de3edb5d57 100755
--- a/t/t2000-checkout-cache-clash.sh
+++ b/t/t2000-checkout-cache-clash.sh
@@ -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/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/t2012-checkout-last.sh b/t/t2012-checkout-last.sh
index 87b30a268c..b44de9dc62 100755
--- a/t/t2012-checkout-last.sh
+++ b/t/t2012-checkout-last.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='checkout can switch to last branch'
+test_description='checkout can switch to last branch and merge base'
. ./test-lib.sh
@@ -91,4 +91,29 @@ test_expect_success 'switch to twelfth from the last' '
test "z$(git symbolic-ref HEAD)" = "zrefs/heads/branch13"
'
+test_expect_success 'merge base test setup' '
+ git checkout -b another other &&
+ echo "hello again" >>world &&
+ git add world &&
+ git commit -m third
+'
+
+test_expect_success 'another...master' '
+ git checkout another &&
+ git checkout another...master &&
+ test "z$(git rev-parse --verify HEAD)" = "z$(git rev-parse --verify master^)"
+'
+
+test_expect_success '...master' '
+ git checkout another &&
+ git checkout ...master &&
+ test "z$(git rev-parse --verify HEAD)" = "z$(git rev-parse --verify master^)"
+'
+
+test_expect_success 'master...' '
+ git checkout another &&
+ git checkout master... &&
+ test "z$(git rev-parse --verify HEAD)" = "z$(git rev-parse --verify master^)"
+'
+
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..2144184d79
--- /dev/null
+++ b/t/t2016-checkout-patch.sh
@@ -0,0 +1,115 @@
+#!/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
+'
+
+test_expect_success 'git checkout -p handles deletion' '
+ set_state dir/foo work index &&
+ rm dir/foo &&
+ (echo n; echo y) | git checkout -p &&
+ verify_saved_state bar &&
+ verify_state dir/foo index index
+'
+
+# 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/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh
new file mode 100755
index 0000000000..cb7effe0a3
--- /dev/null
+++ b/t/t2030-unresolve-info.sh
@@ -0,0 +1,170 @@
+#!/bin/sh
+
+test_description='undoing resolution'
+
+. ./test-lib.sh
+
+check_resolve_undo () {
+ msg=$1
+ shift
+ while case $# in
+ 0) break ;;
+ 1|2|3) die "Bug in check-resolve-undo test" ;;
+ esac
+ do
+ path=$1
+ shift
+ for stage in 1 2 3
+ do
+ sha1=$1
+ shift
+ case "$sha1" in
+ '') continue ;;
+ esac
+ sha1=$(git rev-parse --verify "$sha1")
+ printf "100644 %s %s\t%s\n" $sha1 $stage $path
+ done
+ done >"$msg.expect" &&
+ git ls-files --resolve-undo >"$msg.actual" &&
+ test_cmp "$msg.expect" "$msg.actual"
+}
+
+prime_resolve_undo () {
+ git reset --hard &&
+ git checkout second^0 &&
+ test_tick &&
+ test_must_fail git merge third^0 &&
+ echo merge does not leave anything &&
+ check_resolve_undo empty &&
+ echo different >fi/le &&
+ git add fi/le &&
+ echo resolving records &&
+ check_resolve_undo recorded fi/le initial:fi/le second:fi/le third:fi/le
+}
+
+test_expect_success setup '
+ mkdir fi &&
+ test_commit initial fi/le first &&
+ git branch side &&
+ git branch another &&
+ test_commit second fi/le second &&
+ git checkout side &&
+ test_commit third fi/le third &&
+ git checkout another &&
+ test_commit fourth fi/le fourth &&
+ git checkout master
+'
+
+test_expect_success 'add records switch clears' '
+ prime_resolve_undo &&
+ test_tick &&
+ git commit -m merged &&
+ echo committing keeps &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+ git checkout second^0 &&
+ echo switching clears &&
+ check_resolve_undo cleared
+'
+
+test_expect_success 'rm records reset clears' '
+ prime_resolve_undo &&
+ test_tick &&
+ git commit -m merged &&
+ echo committing keeps &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+
+ echo merge clears upfront &&
+ test_must_fail git merge fourth^0 &&
+ check_resolve_undo nuked &&
+
+ git rm -f fi/le &&
+ echo resolving records &&
+ check_resolve_undo recorded fi/le initial:fi/le HEAD:fi/le fourth:fi/le &&
+
+ git reset --hard &&
+ echo resetting discards &&
+ check_resolve_undo discarded
+'
+
+test_expect_success 'plumbing clears' '
+ prime_resolve_undo &&
+ test_tick &&
+ git commit -m merged &&
+ echo committing keeps &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+
+ echo plumbing clear &&
+ git update-index --clear-resolve-undo &&
+ check_resolve_undo cleared
+'
+
+test_expect_success 'add records checkout -m undoes' '
+ prime_resolve_undo &&
+ git diff HEAD &&
+ git checkout --conflict=merge fi/le &&
+ echo checkout used the record and removed it &&
+ check_resolve_undo removed &&
+ echo the index and the work tree is unmerged again &&
+ git diff >actual &&
+ grep "^++<<<<<<<" actual
+'
+
+test_expect_success 'unmerge with plumbing' '
+ prime_resolve_undo &&
+ git update-index --unresolve fi/le &&
+ git ls-files -u >actual &&
+ test $(wc -l <actual) = 3
+'
+
+test_expect_success 'rerere and rerere forget' '
+ mkdir .git/rr-cache &&
+ prime_resolve_undo &&
+ echo record the resolution &&
+ git rerere &&
+ rerere_id=$(cd .git/rr-cache && echo */postimage) &&
+ rerere_id=${rerere_id%/postimage} &&
+ test -f .git/rr-cache/$rerere_id/postimage &&
+ git checkout -m fi/le &&
+ echo resurrect the conflict &&
+ grep "^=======" fi/le &&
+ echo reresolve the conflict &&
+ git rerere &&
+ test "z$(cat fi/le)" = zdifferent &&
+ echo register the resolution again &&
+ git add fi/le &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+ test -z "$(git ls-files -u)" &&
+ git rerere forget fi/le &&
+ ! test -f .git/rr-cache/$rerere_id/postimage &&
+ tr "\0" "\n" <.git/MERGE_RR >actual &&
+ echo "$rerere_id fi/le" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rerere and rerere forget (subdirectory)' '
+ rm -fr .git/rr-cache &&
+ mkdir .git/rr-cache &&
+ prime_resolve_undo &&
+ echo record the resolution &&
+ (cd fi && git rerere) &&
+ rerere_id=$(cd .git/rr-cache && echo */postimage) &&
+ rerere_id=${rerere_id%/postimage} &&
+ test -f .git/rr-cache/$rerere_id/postimage &&
+ (cd fi && git checkout -m le) &&
+ echo resurrect the conflict &&
+ grep "^=======" fi/le &&
+ echo reresolve the conflict &&
+ (cd fi && git rerere) &&
+ test "z$(cat fi/le)" = zdifferent &&
+ echo register the resolution again &&
+ (cd fi && git add le) &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+ test -z "$(git ls-files -u)" &&
+ (cd fi && git rerere forget le) &&
+ ! test -f .git/rr-cache/$rerere_id/postimage &&
+ tr "\0" "\n" <.git/MERGE_RR >actual &&
+ echo "$rerere_id fi/le" >expect &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh
index 6ef2dcfd8a..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
diff --git a/t/t2104-update-index-skip-worktree.sh b/t/t2104-update-index-skip-worktree.sh
new file mode 100755
index 0000000000..1d0879be06
--- /dev/null
+++ b/t/t2104-update-index-skip-worktree.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Nguyá»…n Thái Ngá»c Duy
+#
+
+test_description='skip-worktree bit test'
+
+. ./test-lib.sh
+
+cat >expect.full <<EOF
+H 1
+H 2
+H sub/1
+H sub/2
+EOF
+
+cat >expect.skip <<EOF
+S 1
+H 2
+S sub/1
+H sub/2
+EOF
+
+test_expect_success 'setup' '
+ mkdir sub &&
+ touch ./1 ./2 sub/1 sub/2 &&
+ git add 1 2 sub/1 sub/2 &&
+ git ls-files -t | test_cmp expect.full -
+'
+
+test_expect_success 'index is at version 2' '
+ test "$(test-index-version < .git/index)" = 2
+'
+
+test_expect_success 'update-index --skip-worktree' '
+ git update-index --skip-worktree 1 sub/1 &&
+ git ls-files -t | test_cmp expect.skip -
+'
+
+test_expect_success 'index is at version 3 after having some skip-worktree entries' '
+ test "$(test-index-version < .git/index)" = 3
+'
+
+test_expect_success 'ls-files -t' '
+ git ls-files -t | test_cmp expect.skip -
+'
+
+test_expect_success 'update-index --no-skip-worktree' '
+ git update-index --no-skip-worktree 1 sub/1 &&
+ git ls-files -t | test_cmp expect.full -
+'
+
+test_expect_success 'index version is back to 2 when there is no skip-worktree entry' '
+ test "$(test-index-version < .git/index)" = 2
+'
+
+test_done
diff --git a/t/t2105-update-index-gitfile.sh b/t/t2105-update-index-gitfile.sh
new file mode 100755
index 0000000000..641607d89a
--- /dev/null
+++ b/t/t2105-update-index-gitfile.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Brad King
+#
+
+test_description='git update-index for gitlink to .git file.
+'
+
+. ./test-lib.sh
+
+test_expect_success 'submodule with absolute .git file' '
+ mkdir sub1 &&
+ (cd sub1 &&
+ git init &&
+ REAL="$(pwd)/.real" &&
+ mv .git "$REAL"
+ echo "gitdir: $REAL" >.git &&
+ test_commit first)
+'
+
+test_expect_success 'add gitlink to absolute .git file' '
+ git update-index --add -- sub1
+'
+
+test_expect_success 'submodule with relative .git file' '
+ mkdir sub2 &&
+ (cd sub2 &&
+ git init &&
+ mv .git .real &&
+ echo "gitdir: .real" >.git &&
+ test_commit first)
+'
+
+test_expect_success 'add gitlink to relative .git file' '
+ git update-index --add -- sub2
+'
+
+test_done
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index b2ddf5ace3..912075063b 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -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 &&
@@ -150,7 +150,7 @@ test_expect_success 'add -u resolves unmerged paths' '
echo 2 >path3 &&
echo 2 >path5 &&
git add -u &&
- git ls-files -s "path?" >actual &&
+ git ls-files -s path1 path2 path3 path4 path5 path6 >actual &&
{
echo "100644 $three 0 path1"
echo "100644 $one 1 path3"
diff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh
index d24c7d9e5f..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/{
diff --git a/t/t2204-add-ignored.sh b/t/t2204-add-ignored.sh
new file mode 100755
index 0000000000..24afdabab7
--- /dev/null
+++ b/t/t2204-add-ignored.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+test_description='giving ignored paths to git add'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ mkdir sub dir dir/sub &&
+ echo sub >.gitignore &&
+ echo ign >>.gitignore &&
+ for p in . sub dir dir/sub
+ do
+ >"$p/ign" &&
+ >"$p/file" || exit 1
+ done
+'
+
+for i in file dir/file dir 'd*'
+do
+ test_expect_success "no complaints for unignored $i" '
+ rm -f .git/index &&
+ git add "$i" &&
+ git ls-files "$i" >out &&
+ test -s out
+ '
+done
+
+for i in ign dir/ign dir/sub dir/sub/*ign sub/file sub sub/*
+do
+ test_expect_success "complaints for ignored $i" '
+ rm -f .git/index &&
+ test_must_fail git add "$i" 2>err &&
+ git ls-files "$i" >out &&
+ ! test -s out &&
+ grep -e "Use -f if" err &&
+ cat err
+ '
+
+ test_expect_success "complaints for ignored $i with unignored file" '
+ rm -f .git/index &&
+ test_must_fail git add "$i" file 2>err &&
+ git ls-files "$i" >out &&
+ ! test -s out &&
+ grep -e "Use -f if" err &&
+ cat err
+ '
+done
+
+for i in sub sub/*
+do
+ test_expect_success "complaints for ignored $i in dir" '
+ rm -f .git/index &&
+ (
+ cd dir &&
+ test_must_fail git add "$i" 2>err &&
+ git ls-files "$i" >out &&
+ ! test -s out &&
+ grep -e "Use -f if" err &&
+ cat err
+ )
+ '
+done
+
+for i in ign file
+do
+ test_expect_success "complaints for ignored $i in sub" '
+ rm -f .git/index &&
+ (
+ cd sub &&
+ test_must_fail git add "$i" 2>err &&
+ git ls-files "$i" >out &&
+ ! test -s out &&
+ grep -e "Use -f if" err &&
+ cat err
+ )
+ '
+done
+
+test_done
diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh
index 293dc353b1..9965bc5c92 100755
--- a/t/t2300-cd-to-toplevel.sh
+++ b/t/t2300-cd-to-toplevel.sh
@@ -5,10 +5,10 @@ test_description='cd_to_toplevel'
. ./test-lib.sh
test_cd_to_toplevel () {
- test_expect_success "$2" '
+ test_expect_success $3 "$2" '
(
cd '"'$1'"' &&
- . git-sh-setup &&
+ . "$(git --exec-path)"/git-sh-setup &&
cd_to_toplevel &&
[ "$(pwd -P)" = "$TOPLEVEL" ]
)
@@ -24,14 +24,14 @@ test_cd_to_toplevel repo 'at physical root'
test_cd_to_toplevel repo/sub/dir 'at physical subdir'
-ln -s repo symrepo
-test_cd_to_toplevel symrepo 'at symbolic root'
+ln -s repo symrepo 2>/dev/null
+test_cd_to_toplevel symrepo 'at symbolic root' SYMLINKS
-ln -s repo/sub/dir subdir-link
-test_cd_to_toplevel subdir-link 'at symbolic subdir'
+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
-test_cd_to_toplevel internal-link 'at internal symbolic subdir'
+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 c65bca8388..6d2f2b67ee 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -64,6 +64,8 @@ two/*.4
echo '!*.2
!*.8' >one/two/.gitignore
+allignores='.gitignore one/.gitignore one/two/.gitignore'
+
test_expect_success \
'git ls-files --others with various exclude options.' \
'git ls-files --others \
@@ -85,6 +87,26 @@ test_expect_success \
>output &&
test_cmp expect output'
+test_expect_success 'setup skip-worktree gitignore' '
+ git add $allignores &&
+ git update-index --skip-worktree $allignores &&
+ rm $allignores
+'
+
+test_expect_success \
+ 'git ls-files --others with various exclude options.' \
+ 'git ls-files --others \
+ --exclude=\*.6 \
+ --exclude-per-directory=.gitignore \
+ --exclude-from=.git/ignore \
+ >output &&
+ test_cmp expect output'
+
+test_expect_success 'restore gitignore' '
+ git checkout $allignores &&
+ rm .git/index
+'
+
cat > excludes-file <<\EOF
*.[1-8]
e*
@@ -153,4 +175,43 @@ test_expect_success 'negated exclude matches can override previous ones' '
grep "^a.1" output
'
+test_expect_success 'subdirectory ignore (setup)' '
+ mkdir -p top/l1/l2 &&
+ (
+ cd top &&
+ git init &&
+ echo /.gitignore >.gitignore &&
+ echo l1 >>.gitignore &&
+ echo l2 >l1/.gitignore &&
+ >l1/l2/l1
+ )
+'
+
+test_expect_success 'subdirectory ignore (toplevel)' '
+ (
+ cd top &&
+ git ls-files -o --exclude-standard
+ ) >actual &&
+ >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'subdirectory ignore (l1/l2)' '
+ (
+ cd top/l1/l2 &&
+ git ls-files -o --exclude-standard
+ ) >actual &&
+ >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'subdirectory ignore (l1)' '
+ (
+ cd top/l1 &&
+ git ls-files -o --exclude-standard
+ ) >actual &&
+ >expect &&
+ test_cmp expect actual
+'
+
test_done
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/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index 0de613dc53..9929f82021 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -276,8 +276,13 @@ test_expect_success 'fail if the index has unresolved entries' '
test_must_fail git merge "$c5" &&
test_must_fail git merge "$c5" 2> out &&
- grep "You are in the middle of a conflicted merge" out
-
+ grep "not possible because you have unmerged files" out &&
+ git add -u &&
+ 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 "Your local changes to .* would be overwritten by merge." out
'
test_expect_success 'merge-recursive remove conflict' '
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/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh
index 6e6a2542a2..eee0d344d2 100755
--- a/t/t3100-ls-tree-restrict.sh
+++ b/t/t3100-ls-tree-restrict.sh
@@ -22,17 +22,27 @@ 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 &&
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"
test_output () {
sed -e "s/ $_x40 / X /" <current >check
test_cmp expected check
@@ -41,7 +51,7 @@ test_output () {
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 +61,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 +73,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 +87,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 +96,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 +106,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 +115,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 +124,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 +133,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 +145,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 +153,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 51cb4a30f5..06654c6f82 100755
--- a/t/t3101-ls-tree-dirname.sh
+++ b/t/t3101-ls-tree-dirname.sh
@@ -39,8 +39,6 @@ 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"
test_output () {
sed -e "s/ $_x40 / X /" <current >check
test_cmp expected check
@@ -141,4 +139,89 @@ test_expect_success 'ls-tree filter is leading path match' '
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 1b1e9ece57..e0b760513c 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -121,7 +121,7 @@ test_expect_success 'renaming a symref is not allowed' \
! test -f .git/refs/heads/master3
'
-test_expect_success \
+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 &&
@@ -468,4 +468,30 @@ test_expect_success 'detect misconfigured autosetuprebase (no value)' '
git config --unset branch.autosetuprebase
'
+test_expect_success 'attempt to delete a branch without base and unmerged to HEAD' '
+ git checkout my9 &&
+ git config --unset branch.my8.merge &&
+ test_must_fail git branch -d my8
+'
+
+test_expect_success 'attempt to delete a branch merged to its base' '
+ # we are on my9 which is the initial commit; traditionally
+ # we would not have allowed deleting my8 that is not merged
+ # to my9, but it is set to track master that already has my8
+ git config branch.my8.merge refs/heads/master &&
+ git branch -d my8
+'
+
+test_expect_success 'attempt to delete a branch merged to its base' '
+ git checkout master &&
+ echo Third >>A &&
+ git commit -m "Third commit" A &&
+ git branch -t my10 my9 &&
+ git branch -f my10 HEAD^ &&
+ # we are on master which is at the third commit, and my10
+ # is behind us, so traditionally we would have allowed deleting
+ # it; but my10 is set to track my9 that is further behind.
+ test_must_fail git branch -d my10
+'
+
test_done
diff --git a/t/t3202-show-branch-octopus.sh b/t/t3202-show-branch-octopus.sh
index 7fe4a6ecb0..0a5d5e669f 100755
--- a/t/t3202-show-branch-octopus.sh
+++ b/t/t3202-show-branch-octopus.sh
@@ -56,4 +56,12 @@ test_expect_success 'show-branch with more than 8 branches' '
'
+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/t3301-notes.sh b/t/t3301-notes.sh
new file mode 100755
index 0000000000..714626d2d6
--- /dev/null
+++ b/t/t3301-notes.sh
@@ -0,0 +1,210 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='Test commit notes'
+
+. ./test-lib.sh
+
+cat > fake_editor.sh << \EOF
+#!/bin/sh
+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 be7ae5a004..4314ad2d66 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -3,9 +3,10 @@
# 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
@@ -41,9 +42,40 @@ 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 "<>")'
@@ -83,9 +115,9 @@ 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
'
@@ -95,4 +127,28 @@ test_expect_success 'Show verbose error when HEAD could not be detached' '
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
+'
+
+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/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 603b003edf..4e3513709e 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -10,62 +10,51 @@ that the result still makes sense.
'
. ./test-lib.sh
-. ../lib-rebase.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
set_fake_editor
-# set up two branches like this:
+# Set up the repository like this:
#
-# A - B - C - D - E
+# one - two - three - four (conflict-branch)
+# /
+# A - B - C - D - E (master)
+# | \
+# | F - G - H (branch1)
+# | \
+# \ I (branch2)
# \
-# F - G - H
-# \
-# I
+# J - K - L - M (no-conflict-branch)
#
-# where B, D and G touch the same file.
+# where A, B, D and G all touch file1, and one, two, three, four all
+# touch file "conflict".
test_expect_success 'setup' '
- : > file1 &&
- git add file1 &&
- test_tick &&
- git commit -m A &&
- git tag A &&
- echo 1 > file1 &&
- test_tick &&
- git commit -m B file1 &&
- : > file2 &&
- git add file2 &&
- test_tick &&
- git commit -m C &&
- echo 2 > file1 &&
- test_tick &&
- git commit -m D file1 &&
- : > file3 &&
- git add file3 &&
- test_tick &&
- git commit -m E &&
+ test_commit A file1 &&
+ test_commit B file1 &&
+ test_commit C file2 &&
+ test_commit D file1 &&
+ test_commit E file3 &&
git checkout -b branch1 A &&
- : > file4 &&
- git add file4 &&
- test_tick &&
- git commit -m F &&
- git tag F &&
- echo 3 > file1 &&
- test_tick &&
- git commit -m G file1 &&
- : > file5 &&
- git add file5 &&
- test_tick &&
- git commit -m H &&
+ test_commit F file4 &&
+ test_commit G file1 &&
+ test_commit H file5 &&
git checkout -b branch2 F &&
- : > file6 &&
- git add file6 &&
- test_tick &&
- git commit -m I &&
- git tag I
+ test_commit I file6
+ git checkout -b conflict-branch A &&
+ for n in one two three four
+ do
+ test_commit $n conflict
+ done &&
+ git checkout -b no-conflict-branch A &&
+ for n in J K L M
+ do
+ test_commit $n file$n
+ done
'
test_expect_success 'no changes are a nop' '
+ git checkout branch2 &&
git rebase -i F &&
test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" &&
test $(git rev-parse I) = $(git rev-parse HEAD)
@@ -111,19 +100,20 @@ test_expect_success 'exchange two commits' '
cat > expect << EOF
diff --git a/file1 b/file1
-index e69de29..00750ed 100644
+index f70f10e..fd79235 100644
--- a/file1
+++ b/file1
-@@ -0,0 +1 @@
-+3
+@@ -1 +1 @@
+-A
++G
EOF
cat > expect2 << EOF
-<<<<<<< HEAD:file1
-2
+<<<<<<< HEAD
+D
=======
-3
->>>>>>> b7ca976... G:file1
+G
+>>>>>>> 51047de... G
EOF
test_expect_success 'stop on conflicting pick' '
@@ -161,7 +151,8 @@ test_expect_success 'squash' '
test_tick &&
GIT_AUTHOR_NAME="Nitfol" git commit -m "nitfol" file7 &&
echo "******************************" &&
- FAKE_LINES="1 squash 2" git rebase -i --onto master HEAD~2 &&
+ FAKE_LINES="1 squash 2" EXPECT_HEADER_COUNT=2 \
+ git rebase -i --onto master HEAD~2 &&
test B = $(cat file7) &&
test $(git rev-parse HEAD^) = $(git rev-parse master)
'
@@ -256,30 +247,113 @@ test_expect_success 'verbose flag is heeded, even after --continue' '
test_expect_success 'multi-squash only fires up editor once' '
base=$(git rev-parse HEAD~4) &&
FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 squash 2 squash 3 squash 4" \
+ EXPECT_HEADER_COUNT=4 \
git rebase -i $base &&
test $base = $(git rev-parse HEAD^) &&
test 1 = $(git show | grep ONCE | wc -l)
'
+test_expect_success 'multi-fixup does not fire up editor' '
+ git checkout -b multi-fixup E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="NEVER" FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \
+ git rebase -i $base &&
+ test $base = $(git rev-parse HEAD^) &&
+ test 0 = $(git show | grep NEVER | wc -l) &&
+ git checkout to-be-rebased &&
+ git branch -D multi-fixup
+'
+
+test_expect_success 'commit message used after conflict' '
+ git checkout -b conflict-fixup conflict-branch &&
+ base=$(git rev-parse HEAD~4) &&
+ (
+ FAKE_LINES="1 fixup 3 fixup 4" &&
+ export FAKE_LINES &&
+ test_must_fail git rebase -i $base
+ ) &&
+ echo three > conflict &&
+ git add conflict &&
+ FAKE_COMMIT_AMEND="ONCE" EXPECT_HEADER_COUNT=2 \
+ git rebase --continue &&
+ test $base = $(git rev-parse HEAD^) &&
+ test 1 = $(git show | grep ONCE | wc -l) &&
+ git checkout to-be-rebased &&
+ git branch -D conflict-fixup
+'
+
+test_expect_success 'commit message retained after conflict' '
+ git checkout -b conflict-squash conflict-branch &&
+ base=$(git rev-parse HEAD~4) &&
+ (
+ FAKE_LINES="1 fixup 3 squash 4" &&
+ export FAKE_LINES &&
+ test_must_fail git rebase -i $base
+ ) &&
+ echo three > conflict &&
+ git add conflict &&
+ FAKE_COMMIT_AMEND="TWICE" EXPECT_HEADER_COUNT=2 \
+ git rebase --continue &&
+ test $base = $(git rev-parse HEAD^) &&
+ test 2 = $(git show | grep TWICE | wc -l) &&
+ git checkout to-be-rebased &&
+ git branch -D conflict-squash
+'
+
+cat > expect-squash-fixup << EOF
+B
+
+D
+
+ONCE
+EOF
+
+test_expect_success 'squash and fixup generate correct log messages' '
+ git checkout -b squash-fixup E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 squash 3 fixup 4" \
+ EXPECT_HEADER_COUNT=4 \
+ git rebase -i $base &&
+ git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup &&
+ test_cmp expect-squash-fixup actual-squash-fixup &&
+ git checkout to-be-rebased &&
+ git branch -D squash-fixup
+'
+
+test_expect_success 'squash ignores comments' '
+ git checkout -b skip-comments E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="# 1 # squash 2 # squash 3 # squash 4 #" \
+ EXPECT_HEADER_COUNT=4 \
+ git rebase -i $base &&
+ test $base = $(git rev-parse HEAD^) &&
+ test 1 = $(git show | grep ONCE | wc -l) &&
+ git checkout to-be-rebased &&
+ git branch -D skip-comments
+'
+
+test_expect_success 'squash ignores blank lines' '
+ git checkout -b skip-blank-lines E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="> 1 > squash 2 > squash 3 > squash 4 >" \
+ EXPECT_HEADER_COUNT=4 \
+ git rebase -i $base &&
+ test $base = $(git rev-parse HEAD^) &&
+ test 1 = $(git show | grep ONCE | wc -l) &&
+ git checkout to-be-rebased &&
+ git branch -D skip-blank-lines
+'
+
test_expect_success 'squash works as expected' '
- for n in one two three four
- do
- echo $n >> file$n &&
- git add file$n &&
- git commit -m $n
- done &&
+ git checkout -b squash-works no-conflict-branch &&
one=$(git rev-parse HEAD~3) &&
- FAKE_LINES="1 squash 3 2" git rebase -i HEAD~3 &&
+ FAKE_LINES="1 squash 3 2" EXPECT_HEADER_COUNT=2 \
+ git rebase -i HEAD~3 &&
test $one = $(git rev-parse HEAD~2)
'
test_expect_success 'interrupted squash works as expected' '
- for n in one two three four
- do
- echo $n >> conflict &&
- git add conflict &&
- git commit -m $n
- done &&
+ git checkout -b interrupted-squash conflict-branch &&
one=$(git rev-parse HEAD~3) &&
(
FAKE_LINES="1 squash 3 2" &&
@@ -296,12 +370,7 @@ test_expect_success 'interrupted squash works as expected' '
'
test_expect_success 'interrupted squash works as expected (case 2)' '
- for n in one two three four
- do
- echo $n >> conflict &&
- git add conflict &&
- git commit -m $n
- done &&
+ git checkout -b interrupted-squash2 conflict-branch &&
one=$(git rev-parse HEAD~3) &&
(
FAKE_LINES="3 squash 1 2" &&
@@ -459,4 +528,29 @@ 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/t3408-rebase-multi-line.sh b/t/t3408-rebase-multi-line.sh
index e12cd578e8..2062b858bb 100755
--- a/t/t3408-rebase-multi-line.sh
+++ b/t/t3408-rebase-multi-line.sh
@@ -32,8 +32,8 @@ test_expect_success rebase '
git checkout side &&
git rebase master &&
- git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
- git cat-file commit side@{1} | sed -e "1,/^$/d" >expect &&
+ git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
+ git cat-file commit side@{1} | sed -e "1,/^\$/d" >expect &&
test_cmp expect actual
'
diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh
index e6c832780f..8f785e7957 100755
--- a/t/t3409-rebase-preserve-merges.sh
+++ b/t/t3409-rebase-preserve-merges.sh
@@ -32,14 +32,14 @@ export GIT_AUTHOR_EMAIL
test_expect_success 'setup for merge-preserving rebase' \
'echo First > A &&
git add A &&
- git-commit -m "Add A1" &&
+ git commit -m "Add A1" &&
git checkout -b topic &&
echo Second > B &&
git add B &&
- git-commit -m "Add B1" &&
+ git commit -m "Add B1" &&
git checkout -f master &&
echo Third >> A &&
- git-commit -a -m "Modify A2" &&
+ git commit -a -m "Modify A2" &&
git clone ./. clone1 &&
cd clone1 &&
@@ -71,7 +71,7 @@ test_expect_success 'rebase -p fakes interactive rebase' '
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 commit" | wc -l)
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Merge remote branch " | wc -l)
)
'
diff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh
index 6533505218..14a23cd872 100755
--- a/t/t3411-rebase-preserve-around-merges.sh
+++ b/t/t3411-rebase-preserve-around-merges.sh
@@ -10,7 +10,7 @@ a merge to before the merge.
'
. ./test-lib.sh
-. ../lib-rebase.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
set_fake_editor
diff --git a/t/t3409-rebase-hook.sh b/t/t3413-rebase-hook.sh
index 098b75507b..098b75507b 100755
--- a/t/t3409-rebase-hook.sh
+++ b/t/t3413-rebase-hook.sh
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/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
new file mode 100755
index 0000000000..b63f4e2d67
--- /dev/null
+++ b/t/t3415-rebase-autosquash.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+test_description='auto squash'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo 0 >file0 &&
+ git add . &&
+ test_tick &&
+ git commit -m "initial commit" &&
+ echo 0 >file1 &&
+ echo 2 >file2 &&
+ git add . &&
+ test_tick &&
+ git commit -m "first commit" &&
+ echo 3 >file3 &&
+ git add . &&
+ test_tick &&
+ git commit -m "second commit" &&
+ git tag base
+'
+
+test_expect_success 'auto fixup' '
+ git reset --hard base &&
+ echo 1 >file1 &&
+ git add -u &&
+ test_tick &&
+ git commit -m "fixup! first"
+
+ git tag final-fixup &&
+ test_tick &&
+ git rebase --autosquash -i HEAD^^^ &&
+ git log --oneline >actual &&
+ test 3 = $(wc -l <actual) &&
+ git diff --exit-code final-fixup &&
+ test 1 = "$(git cat-file blob HEAD^:file1)" &&
+ test 1 = $(git cat-file commit HEAD^ | grep first | wc -l)
+'
+
+test_expect_success 'auto squash' '
+ git reset --hard base &&
+ echo 1 >file1 &&
+ git add -u &&
+ test_tick &&
+ git commit -m "squash! first"
+
+ git tag final-squash &&
+ test_tick &&
+ git rebase --autosquash -i HEAD^^^ &&
+ git log --oneline >actual &&
+ test 3 = $(wc -l <actual) &&
+ git diff --exit-code final-squash &&
+ test 1 = "$(git cat-file blob HEAD^:file1)" &&
+ test 2 = $(git cat-file commit HEAD^ | grep first | wc -l)
+'
+
+test_expect_success 'misspelled auto squash' '
+ git reset --hard base &&
+ echo 1 >file1 &&
+ git add -u &&
+ test_tick &&
+ git commit -m "squash! forst"
+ git tag final-missquash &&
+ test_tick &&
+ git rebase --autosquash -i HEAD^^^ &&
+ git log --oneline >actual &&
+ test 4 = $(wc -l <actual) &&
+ git diff --exit-code final-missquash &&
+ test 0 = $(git rev-list final-missquash...HEAD | wc -l)
+'
+
+test_done
diff --git a/t/t3416-rebase-onto-threedots.sh b/t/t3416-rebase-onto-threedots.sh
new file mode 100755
index 0000000000..ddf2f64853
--- /dev/null
+++ b/t/t3416-rebase-onto-threedots.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+
+test_description='git rebase --onto A...B'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-rebase.sh"
+
+# Rebase only the tip commit of "topic" on merge base between "master"
+# and "topic". Cannot do this for "side" with "master" because there
+# is no single merge base.
+#
+#
+# F---G topic G'
+# / /
+# A---B---C---D---E master --> A---B---C---D---E
+# \ \ /
+# \ x
+# \ / \
+# H---I---J---K side
+
+test_expect_success setup '
+ test_commit A &&
+ test_commit B &&
+ git branch side &&
+ test_commit C &&
+ git branch topic &&
+ git checkout side &&
+ test_commit H &&
+ git checkout master &&
+ test_tick &&
+ git merge H &&
+ git tag D &&
+ test_commit E &&
+ git checkout topic &&
+ test_commit F &&
+ test_commit G &&
+ git checkout side &&
+ test_tick &&
+ git merge C &&
+ git tag I &&
+ test_commit J &&
+ test_commit K
+'
+
+test_expect_success 'rebase --onto master...topic' '
+ git reset --hard &&
+ git checkout topic &&
+ git reset --hard G &&
+
+ git rebase --onto master...topic F &&
+ git rev-parse HEAD^1 >actual &&
+ git rev-parse C^0 >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rebase --onto master...' '
+ git reset --hard &&
+ git checkout topic &&
+ git reset --hard G &&
+
+ git rebase --onto master... F &&
+ git rev-parse HEAD^1 >actual &&
+ git rev-parse C^0 >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rebase --onto master...side' '
+ git reset --hard &&
+ git checkout side &&
+ git reset --hard K &&
+
+ test_must_fail git rebase --onto master...side J
+'
+
+test_expect_success 'rebase -i --onto master...topic' '
+ git reset --hard &&
+ git checkout topic &&
+ git reset --hard G &&
+ set_fake_editor &&
+ EXPECT_COUNT=1 git rebase -i --onto master...topic F &&
+ git rev-parse HEAD^1 >actual &&
+ git rev-parse C^0 >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rebase -i --onto master...' '
+ git reset --hard &&
+ git checkout topic &&
+ git reset --hard G &&
+ set_fake_editor &&
+ EXPECT_COUNT=1 git rebase -i --onto master... F &&
+ git rev-parse HEAD^1 >actual &&
+ git rev-parse C^0 >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rebase -i --onto master...side' '
+ git reset --hard &&
+ git checkout side &&
+ git reset --hard K &&
+
+ test_must_fail git rebase -i --onto master...side J
+'
+
+test_done
diff --git a/t/t3417-rebase-whitespace-fix.sh b/t/t3417-rebase-whitespace-fix.sh
new file mode 100755
index 0000000000..220a740ee8
--- /dev/null
+++ b/t/t3417-rebase-whitespace-fix.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+test_description='git rebase --whitespace=fix
+
+This test runs git rebase --whitespace=fix and make sure that it works.
+'
+
+. ./test-lib.sh
+
+# prepare initial revision of "file" with a blank line at the end
+cat >file <<EOF
+a
+b
+c
+
+EOF
+
+# expected contents in "file" after rebase
+cat >expect-first <<EOF
+a
+b
+c
+EOF
+
+# prepare second revision of "file"
+cat >second <<EOF
+a
+b
+c
+
+d
+e
+f
+
+
+
+
+EOF
+
+# expected contents in second revision after rebase
+cat >expect-second <<EOF
+a
+b
+c
+
+d
+e
+f
+EOF
+
+test_expect_success 'blank line at end of file; extend at end of file' '
+ git commit --allow-empty -m "Initial empty commit" &&
+ git add file && git commit -m first &&
+ mv second file &&
+ git add file && git commit -m second &&
+ git rebase --whitespace=fix HEAD^^ &&
+ git diff --exit-code HEAD^:file expect-first &&
+ test_cmp file expect-second
+'
+
+# prepare third revision of "file"
+sed -e's/Z//' >third <<EOF
+a
+b
+c
+
+d
+e
+f
+ Z
+ Z
+h
+i
+j
+k
+l
+EOF
+
+sed -e's/ //g' <third >expect-third
+
+test_expect_success 'two blanks line at end of file; extend at end of file' '
+ cp third file && git add file && git commit -m third &&
+ git rebase --whitespace=fix HEAD^^ &&
+ git diff --exit-code HEAD^:file expect-second &&
+ test_cmp file expect-third
+'
+
+test_expect_success 'same, but do not remove trailing spaces' '
+ git config core.whitespace "-blank-at-eol" &&
+ git reset --hard HEAD^ &&
+ cp third file && git add file && git commit -m third &&
+ git rebase --whitespace=fix HEAD^^
+ git diff --exit-code HEAD^:file expect-second &&
+ test_cmp file third
+'
+
+sed -e's/Z//' >beginning <<EOF
+a
+ Z
+ Z
+EOF
+
+cat >expect-beginning <<EOF
+a
+
+
+1
+2
+3
+4
+5
+EOF
+
+test_expect_success 'at beginning of file' '
+ git config core.whitespace "blank-at-eol" &&
+ cp beginning file &&
+ git commit -m beginning file &&
+ for i in 1 2 3 4 5; do
+ echo $i
+ done >> file &&
+ git commit -m more file &&
+ git rebase --whitespace=fix HEAD^^ &&
+ test_cmp file expect-beginning
+'
+
+test_done
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index bb4cf00d78..7f858151d4 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -66,7 +66,7 @@ test_expect_success 'revert forbidden on dirty working tree' '
echo content >extra_file &&
git add extra_file &&
test_must_fail git revert HEAD 2>errors &&
- grep "Dirty index" errors
+ grep "Your local changes would be overwritten by " errors
'
diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh
index 9aaeabd972..e51e505a9f 100755
--- a/t/t3505-cherry-pick-empty.sh
+++ b/t/t3505-cherry-pick-empty.sh
@@ -17,11 +17,11 @@ test_expect_success setup '
'
-test_expect_code 1 'cherry-pick an empty commit' '
-
- git checkout master &&
- git cherry-pick empty-branch
-
+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' '
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 95542e9cfe..0aaf0ad84b 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"
+"
+# 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' \
@@ -100,20 +107,16 @@ 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' \
- 'test_must_fail 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' \
@@ -268,4 +271,12 @@ test_expect_success 'choking "git rm" should not let it die with cruft' '
test "$status" != 0
'
+test_expect_success 'rm removes subdirectories recursively' '
+ mkdir -p dir/subdir/subsubdir &&
+ echo content >dir/subdir/subsubdir/file &&
+ git add dir/subdir/subsubdir/file &&
+ git rm -f dir/subdir/subsubdir/file &&
+ ! test -d dir
+'
+
test_done
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 9f6454d2ff..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 &&
@@ -179,7 +179,7 @@ test_expect_success 'git add --refresh' '
test -z "`git diff-index HEAD -- foo`"
'
-test_expect_success 'git add should fail atomically upon an unreadable file' '
+test_expect_success POSIXPERM 'git add should fail atomically upon an unreadable file' '
git reset --hard &&
date >foo1 &&
date >foo2 &&
@@ -190,7 +190,7 @@ test_expect_success 'git add should fail atomically upon an unreadable file' '
rm -f foo2
-test_expect_success 'git add --ignore-errors' '
+test_expect_success POSIXPERM 'git add --ignore-errors' '
git reset --hard &&
date >foo1 &&
date >foo2 &&
@@ -201,7 +201,7 @@ test_expect_success 'git add --ignore-errors' '
rm -f foo2
-test_expect_success 'git add (add.ignore-errors)' '
+test_expect_success POSIXPERM 'git add (add.ignore-errors)' '
git config add.ignore-errors 1 &&
git reset --hard &&
date >foo1 &&
@@ -212,7 +212,7 @@ test_expect_success 'git add (add.ignore-errors)' '
'
rm -f foo2
-test_expect_success 'git add (add.ignore-errors = false)' '
+test_expect_success POSIXPERM 'git add (add.ignore-errors = false)' '
git config add.ignore-errors 0 &&
git reset --hard &&
date >foo1 &&
@@ -221,8 +221,21 @@ test_expect_success 'git add (add.ignore-errors = false)' '
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 'git add '\''fo\[ou\]bar'\'' ignores foobar' '
+test_expect_success BSLASHPSPEC "git add 'fo\\[ou\\]bar' ignores foobar" '
git reset --hard &&
touch fo\[ou\]bar foobar &&
git add '\''fo\[ou\]bar'\'' &&
@@ -230,4 +243,16 @@ test_expect_success 'git add '\''fo\[ou\]bar'\'' ignores foobar' '
! ( 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 e95663d8e6..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 &&
@@ -133,12 +138,28 @@ test_expect_success 'real edit works' '
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)'
+ say 'skipping filemode tests (filesystem does not properly support modes)'
else
+ test_set_prereq FILEMODE
+fi
-test_expect_success 'patch does not affect mode' '
+test_expect_success FILEMODE 'patch does not affect mode' '
git reset --hard &&
echo content >>file &&
chmod +x file &&
@@ -147,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 &&
@@ -156,7 +177,92 @@ test_expect_success 'stage mode but not hunk' '
git diff file | grep "+content"
'
-fi
+
+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/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index 784c31aec9..256c4c9701 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -9,7 +9,15 @@ test_description='commit and log output encodings'
compare_with () {
git show -s $1 | sed -e '1,/^$/d' -e 's/^ //' >current &&
- test_cmp 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 '
@@ -26,7 +34,7 @@ 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 &&
@@ -36,7 +44,7 @@ do
'
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,14 +61,14 @@ 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 "$TEST_DIRECTORY"/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' "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
@@ -78,7 +86,7 @@ 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' &&
@@ -87,32 +95,38 @@ do
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 "$TEST_DIRECTORY"/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' "$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' "$TEST_DIRECTORY"/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'" "$TEST_DIRECTORY"/t3900/'$H'.txt
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 7655da3f8d..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
@@ -55,7 +55,7 @@ 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.
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
test_tick &&
@@ -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)' '
@@ -110,7 +110,7 @@ test_expect_success 'rebase (U/U)' '
test_expect_success 'rebase (U/L)' '
git config i18n.commitencoding UTF-8 &&
- git config i18n.logoutputencoding ISO-8859-1 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
. "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard side &&
@@ -121,8 +121,8 @@ test_expect_success 'rebase (U/L)' '
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 &&
+ git config i18n.commitencoding ISO8859-1 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
@@ -134,7 +134,7 @@ 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 &&
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
@@ -162,8 +162,8 @@ 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 &&
+ git config i18n.commitencoding ISO8859-1 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard master &&
@@ -178,7 +178,7 @@ 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 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
. "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard master &&
@@ -193,7 +193,7 @@ 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 &&
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
@@ -218,7 +218,7 @@ test_expect_success 'rebase --merge (U/U)' '
test_expect_success 'rebase --merge (U/L)' '
git config i18n.commitencoding UTF-8 &&
- git config i18n.logoutputencoding ISO-8859-1 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
. "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard side &&
@@ -229,8 +229,8 @@ test_expect_success 'rebase --merge (U/L)' '
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 &&
+ git config i18n.commitencoding ISO8859-1 &&
+ git config i18n.logoutputencoding ISO8859-1 &&
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
@@ -242,7 +242,7 @@ 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 &&
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh
index 5868052425..29103f65dc 100755
--- a/t/t3902-quoted.sh
+++ b/t/t3902-quoted.sh
@@ -25,7 +25,7 @@ for_each_name () {
for name in \
Name "Name and a${LF}LF" "Name and an${HT}HT" "Name${DQ}" \
"$FN$HT$GN" "$FN$LF$GN" "$FN $GN" "$FN$GN" "$FN$DQ$GN" \
- "With SP in it"
+ "With SP in it" "$FN/file"
do
eval "$1"
done
@@ -33,6 +33,7 @@ for_each_name () {
test_expect_success setup '
+ mkdir "$FN" &&
for_each_name "echo initial >\"\$name\""
git add . &&
git commit -q -m Initial &&
@@ -54,6 +55,7 @@ With SP in it
"\346\277\261\351\207\216\n\347\264\224"
"\346\277\261\351\207\216 \347\264\224"
"\346\277\261\351\207\216\"\347\264\224"
+"\346\277\261\351\207\216/file"
"\346\277\261\351\207\216\347\264\224"
EOF
@@ -67,6 +69,7 @@ With SP in it
"濱野\n純"
濱野 純
"濱野\"純"
+濱野/file
濱野純
EOF
@@ -97,6 +100,13 @@ test_expect_success 'check fully quoted output from diff-tree' '
'
+test_expect_success 'check fully quoted output from ls-tree' '
+
+ git ls-tree --name-only -r HEAD >current &&
+ test_cmp expect.quoted current
+
+'
+
test_expect_success 'setting core.quotepath' '
git config --bool core.quotepath false
@@ -130,4 +140,11 @@ test_expect_success 'check fully quoted output from diff-tree' '
'
+test_expect_success 'check fully quoted output from ls-tree' '
+
+ git ls-tree --name-only -r HEAD >current &&
+ test_cmp expect.raw current
+
+'
+
test_done
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 7484cbede6..476e5ec038 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -177,4 +177,55 @@ test_expect_success 'stash branch' '
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 'pop -q --index works and is quiet' '
+ echo foo > file &&
+ git add file &&
+ git stash save --quiet &&
+ git stash pop -q --index > output.out 2>&1 &&
+ test foo = "$(git show :file)" &&
+ 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/t4002-diff-basic.sh b/t/t4002-diff-basic.sh
index cc3681f161..18695ce821 100755
--- a/t/t4002-diff-basic.sh
+++ b/t/t4002-diff-basic.sh
@@ -258,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/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh
index b35af9b42d..a4da1196a9 100755
--- a/t/t4004-diff-rename-symlink.sh
+++ b/t/t4004-diff-rename-symlink.sh
@@ -12,6 +12,12 @@ by an edit for them.
. ./test-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' \
'echo xyzzy | tr -d '\\\\'012 >yomin &&
diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh
index 4e92fce1d0..ff8c2f7532 100755
--- a/t/t4006-diff-mode.sh
+++ b/t/t4006-diff-mode.sh
@@ -15,24 +15,11 @@ 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"
sed -e 's/\(:100644 100755\) \('"$_x40"'\) \2 /\1 X X /' <current >check
echo ":100644 100755 X X M rezrov" >expected
diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh
index 42072d724e..11502b7509 100755
--- a/t/t4007-rename-3.sh
+++ b/t/t4007-rename-3.sh
@@ -9,32 +9,36 @@ test_description='Rename interaction with pathspec.
. ./test-lib.sh
. "$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 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
+'
# 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 7e343a9cd1..e19ca65885 100755
--- a/t/t4008-diff-break-rewrite.sh
+++ b/t/t4008-diff-break-rewrite.sh
@@ -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/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh
index 9055c8b318..d7e327cc5b 100755
--- a/t/t4011-diff-symlink.sh
+++ b/t/t4011-diff-symlink.sh
@@ -9,6 +9,12 @@ test_description='Test diff of symlinks.
. ./test-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
new file mode 120000
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index 3cf5b5c4ea..bc46563afc 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -77,17 +77,13 @@ test_expect_success 'apply binary patch' \
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
+ (: hide error code from diff, which just indicates differences
git diff --binary --no-index /dev/null binary >current ||
true
) &&
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 9c709022ef..8e3694ed5b 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -101,8 +101,7 @@ do
'' | '#'*) continue ;;
esac
test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'`
- cnt=`expr $test_count + 1`
- pfx=`printf "%04d" $cnt`
+ pfx=`printf "%04d" $test_count`
expect="$TEST_DIRECTORY/t4013/diff.$test"
actual="$pfx-diff.$test"
@@ -207,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
@@ -243,11 +247,12 @@ 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 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
@@ -268,6 +273,7 @@ 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.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 e5ab74437e..ce49bd676e 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
@@ -22,9 +22,9 @@ This is the second commit.
--------------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
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
--------------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
@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit
--------------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 2c71d20d37..5f1b23863b 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
@@ -22,9 +22,9 @@ This is the second commit.
--------------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
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
--------------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 38f790290a..4a2364abc2 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
@@ -20,9 +20,9 @@ Content-Transfer-Encoding: 8bit
--------------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 58f8a7b7d6..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
@@ -22,9 +22,9 @@ This is the second commit.
--------------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
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
--------------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
@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit
--------------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 9e7bbdffa2..08f23014bc 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master
@@ -22,9 +22,9 @@ This is the second commit.
--------------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
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
--------------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
@@ -129,9 +129,9 @@ Content-Transfer-Encoding: 8bit
--------------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 f881f644cc..07f1230d31 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
@@ -22,9 +22,9 @@ This is the second commit.
--------------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
@@ -80,9 +80,9 @@ Content-Transfer-Encoding: 8bit
--------------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 4f258b8858..29e00ab8af 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
@@ -22,9 +22,9 @@ This is the second commit.
--------------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 e86dce69a3..67633d424a 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side
@@ -20,9 +20,9 @@ Content-Transfer-Encoding: 8bit
--------------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.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.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/t4014-format-patch.sh b/t/t4014-format-patch.sh
index f045898fe3..f2a2aaa2b9 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.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 &&
@@ -95,9 +93,9 @@ test_expect_success 'extra headers' '
git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
" &&
git format-patch --stdout master..side > patch2 &&
- sed -e "/^$/q" patch2 > hdrs2 &&
- grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs2 &&
- grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs2
+ sed -e "/^\$/q" patch2 > hdrs2 &&
+ grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
+ grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
'
@@ -106,9 +104,9 @@ test_expect_success 'extra headers without newlines' '
git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
git format-patch --stdout master..side >patch3 &&
- sed -e "/^$/q" patch3 > hdrs3 &&
- grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs3 &&
- grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs3
+ sed -e "/^\$/q" patch3 > hdrs3 &&
+ grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
+ grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
'
@@ -117,17 +115,32 @@ test_expect_success 'extra headers with multiple To:s' '
git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
git format-patch --stdout master..side > patch4 &&
- sed -e "/^$/q" patch4 > hdrs4 &&
- grep "^To: R. E. Cipient <rcipient@example.com>,$" hdrs4 &&
- grep "^ *S. E. Cipient <scipient@example.com>$" hdrs4
+ sed -e "/^\$/q" patch4 > hdrs4 &&
+ grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
+ grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
'
test_expect_success 'additional command line cc' '
git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
- git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch5 &&
- grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch5 &&
- grep "^ *S. E. Cipient <scipient@example.com>$" patch5
+ git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
+ grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
+ 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' '
@@ -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' '
@@ -206,9 +406,9 @@ test_expect_success 'cover-letter inherits diff options' '
git mv file foo &&
git commit -m foo &&
git format-patch --cover-letter -1 &&
- ! grep "file => foo .* 0 *$" 0000-cover-letter.patch &&
+ ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
git format-patch --cover-letter -1 -M &&
- grep "file => foo .* 0 *$" 0000-cover-letter.patch
+ grep "file => foo .* 0 *\$" 0000-cover-letter.patch
'
@@ -225,7 +425,7 @@ EOF
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 &&
+ sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
test_cmp expect output
'
@@ -250,7 +450,28 @@ 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 &&
+ 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
'
@@ -293,16 +514,47 @@ test_expect_success 'format-patch from a subdirectory (2)' '
'
test_expect_success 'format-patch from a subdirectory (3)' '
- here="$TEST_DIRECTORY/$test" &&
rm -f 0* &&
filename=$(
rm -rf sub &&
mkdir -p sub/dir &&
cd sub/dir &&
- git format-patch -1 -o "$here"
+ 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 6d13da30da..90f3342373 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -93,8 +93,6 @@ git diff > 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' 'test_cmp expect out'
@@ -362,10 +360,17 @@ test_expect_success 'line numbers in --check output are correct' '
'
-test_expect_success 'checkdiff detects trailing blank lines' '
+test_expect_success 'checkdiff detects new trailing blank lines (1)' '
echo "foo();" >x &&
echo "" >>x &&
- git diff --check | grep "ends with blank"
+ 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' '
@@ -379,6 +384,18 @@ test_expect_success 'checkdiff allows new blank lines' '
git diff --check
'
+cat <<EOF >expect
+EOF
+test_expect_success 'whitespace-only changes not reported' '
+ git reset --hard &&
+ echo >x "hello world" &&
+ git add x &&
+ git commit -m "hello 1" &&
+ echo >x "hello world" &&
+ git diff -b >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'combined diff with autocrlf conversion' '
git reset --hard &&
diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh
index 60dd2014d5..0391a5827e 100755
--- a/t/t4017-diff-retval.sh
+++ b/t/t4017-diff-retval.sh
@@ -5,6 +5,9 @@ test_description='Return value of diffs'
. ./test-lib.sh
test_expect_success 'setup' '
+ echo "1 " >a &&
+ git add . &&
+ git commit -m zeroth &&
echo 1 >a &&
git add . &&
git commit -m first &&
@@ -13,6 +16,18 @@ test_expect_success 'setup' '
git commit -a -m second
'
+test_expect_success 'git diff --quiet -w HEAD^^ HEAD^' '
+ git diff --quiet -w HEAD^^ HEAD^
+'
+
+test_expect_success 'git diff --quiet HEAD^^ HEAD^' '
+ test_must_fail git diff --quiet HEAD^^ HEAD^
+'
+
+test_expect_success 'git diff --quiet -w HEAD^ HEAD' '
+ test_must_fail git diff --quiet -w HEAD^ HEAD
+'
+
test_expect_success 'git diff-tree HEAD^ HEAD' '
git diff-tree --exit-code HEAD^ HEAD
test $? = 1
diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh
index 84a1fe3115..f6d1f1ebab 100755
--- a/t/t4019-diff-wserror.sh
+++ b/t/t4019-diff-wserror.sh
@@ -20,11 +20,27 @@ test_expect_success setup '
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 &&
@@ -37,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 &&
@@ -53,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 &&
@@ -69,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 &&
@@ -85,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 &&
@@ -101,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 &&
@@ -117,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 &&
@@ -133,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 &&
@@ -149,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 &&
@@ -165,7 +165,7 @@ test_expect_success 'trailing empty lines (1)' '
rm -f .gitattributes &&
test_must_fail git diff --check >output &&
- grep "ends with blank lines." output &&
+ grep "new blank line at" output &&
grep "trailing whitespace" output
'
@@ -190,4 +190,13 @@ test_expect_success 'do not color trailing cr in context' '
'
+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 0720001281..a7602cf923 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -136,6 +136,15 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
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
@@ -157,7 +166,7 @@ test_expect_success 'diff --cached' '
git update-index --assume-unchanged file &&
echo second >file &&
git diff --cached >actual &&
- test_cmp ../t4020/diff.NUL 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 390af2389f..709b3231ca 100755
--- a/t/t4021-format-patch-numbered.sh
+++ b/t/t4021-format-patch-numbered.sh
@@ -86,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
@@ -108,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/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh
index 297ddb5a25..9bdf6596d8 100755
--- a/t/t4023-diff-rename-typechange.sh
+++ b/t/t4023-diff-rename-typechange.sh
@@ -4,6 +4,12 @@ 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 &&
diff --git a/t/t4026-color.sh b/t/t4026-color.sh
index 49eced20e7..d5ccdd0cf8 100755
--- a/t/t4026-color.sh
+++ b/t/t4026-color.sh
@@ -73,4 +73,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 5cf8924b21..83c1914771 100755
--- a/t/t4027-diff-submodule.sh
+++ b/t/t4027-diff-submodule.sh
@@ -32,7 +32,8 @@ test_expect_success setup '
cd sub &&
git rev-list HEAD
) &&
- echo ":160000 160000 $3 $_z40 M sub" >expect
+ echo ":160000 160000 $3 $_z40 M sub" >expect &&
+ subtip=$3 subprev=$2
'
test_expect_success 'git diff --raw HEAD' '
@@ -50,6 +51,87 @@ test_expect_success 'git diff-files --raw' '
test_cmp expect actual.files
'
+expect_from_to () {
+ printf "%sSubproject commit %s\n+Subproject commit %s\n" \
+ "-" "$1" "$2"
+}
+
+test_expect_success 'git diff HEAD' '
+ git diff HEAD >actual &&
+ sed -e "1,/^@@/d" actual >actual.body &&
+ expect_from_to >expect.body $subtip $subprev &&
+ test_cmp expect.body actual.body
+'
+
+test_expect_success 'git diff HEAD with dirty submodule (work tree)' '
+ echo >>sub/world &&
+ git diff HEAD >actual &&
+ sed -e "1,/^@@/d" actual >actual.body &&
+ expect_from_to >expect.body $subtip $subprev-dirty &&
+ test_cmp expect.body actual.body
+'
+
+test_expect_success 'git diff HEAD with dirty submodule (index)' '
+ (
+ cd sub &&
+ git reset --hard &&
+ echo >>world &&
+ git add world
+ ) &&
+ git diff HEAD >actual &&
+ sed -e "1,/^@@/d" actual >actual.body &&
+ expect_from_to >expect.body $subtip $subprev-dirty &&
+ test_cmp expect.body actual.body
+'
+
+test_expect_success 'git diff HEAD with dirty submodule (untracked)' '
+ (
+ cd sub &&
+ git reset --hard &&
+ git clean -qfdx &&
+ >cruft
+ ) &&
+ git diff HEAD >actual &&
+ sed -e "1,/^@@/d" actual >actual.body &&
+ expect_from_to >expect.body $subtip $subprev-dirty &&
+ test_cmp expect.body actual.body
+'
+
+test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)' '
+ git commit -m "x" sub &&
+ echo >>sub/world &&
+ git diff HEAD >actual &&
+ sed -e "1,/^@@/d" actual >actual.body &&
+ expect_from_to >expect.body $subprev $subprev-dirty &&
+ test_cmp expect.body actual.body
+'
+
+test_expect_success 'git diff HEAD with dirty submodule (index, refs match)' '
+ (
+ cd sub &&
+ git reset --hard &&
+ echo >>world &&
+ git add world
+ ) &&
+ git diff HEAD >actual &&
+ sed -e "1,/^@@/d" actual >actual.body &&
+ expect_from_to >expect.body $subprev $subprev-dirty &&
+ test_cmp expect.body actual.body
+'
+
+test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)' '
+ (
+ cd sub &&
+ git reset --hard &&
+ git clean -qfdx &&
+ >cruft
+ ) &&
+ git diff HEAD >actual &&
+ sed -e "1,/^@@/d" actual >actual.body &&
+ expect_from_to >expect.body $subprev $subprev-dirty &&
+ test_cmp expect.body actual.body
+'
+
test_expect_success 'git diff (empty submodule dir)' '
: >empty &&
rm -rf sub/* sub/.git &&
diff --git a/t/t4029-diff-trailing-space.sh b/t/t4029-diff-trailing-space.sh
index 9ddbbcde57..3ccc237a8d 100755
--- a/t/t4029-diff-trailing-space.sh
+++ b/t/t4029-diff-trailing-space.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Copyright (c) Jim Meyering
#
diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh
index a3f0897a52..88c5619ae7 100755
--- a/t/t4030-diff-textconv.sh
+++ b/t/t4030-diff-textconv.sh
@@ -48,7 +48,7 @@ test_expect_success 'file is considered binary by plumbing' '
test_expect_success 'setup textconv filters' '
echo file diff=foo >.gitattributes &&
- git config diff.foo.textconv "$PWD"/hexdump &&
+ git config diff.foo.textconv "\"$(pwd)\""/hexdump &&
git config diff.fail.textconv false
'
diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh
index a894c60622..7e7b307a24 100755
--- a/t/t4031-diff-rewrite-binary.sh
+++ b/t/t4031-diff-rewrite-binary.sh
@@ -54,7 +54,7 @@ chmod +x dump
test_expect_success 'setup textconv' '
echo file diff=foo >.gitattributes &&
- git config diff.foo.textconv "$PWD"/dump
+ git config diff.foo.textconv "\"$(pwd)\""/dump
'
test_expect_success 'rewrite diff respects textconv' '
diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh
index 4508effcaa..2e2e103b31 100755
--- a/t/t4034-diff-words.sh
+++ b/t/t4034-diff-words.sh
@@ -8,21 +8,13 @@ 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/.\[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_decode_color <output >output.decrypted &&
test_cmp expect output.decrypted
}
@@ -47,9 +39,9 @@ cat > expect <<\EOF
<WHITE>index 330b04f..5ed8eff 100644<RESET>
<WHITE>--- a/pre<RESET>
<WHITE>+++ b/post<RESET>
-<BROWN>@@ -1,3 +1,7 @@<RESET>
+<CYAN>@@ -1,3 +1,7 @@<RESET>
<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET>
-<RESET>
+
a = b + c<RESET>
<GREEN>aa = a<RESET>
@@ -68,9 +60,29 @@ cat > expect <<\EOF
<WHITE>index 330b04f..5ed8eff 100644<RESET>
<WHITE>--- a/pre<RESET>
<WHITE>+++ b/post<RESET>
-<BROWN>@@ -1,3 +1,7 @@<RESET>
+<CYAN>@@ -1 +1 @@<RESET>
+<RED>h(4)<RESET><GREEN>h(4),hh[44]<RESET>
+<CYAN>@@ -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>
+<CYAN>@@ -1,3 +1,7 @@<RESET>
h(4),<GREEN>hh<RESET>[44]
-<RESET>
+
a = b + c<RESET>
<GREEN>aa = a<RESET>
@@ -104,9 +116,9 @@ cat > expect <<\EOF
<WHITE>index 330b04f..5ed8eff 100644<RESET>
<WHITE>--- a/pre<RESET>
<WHITE>+++ b/post<RESET>
-<BROWN>@@ -1,3 +1,7 @@<RESET>
+<CYAN>@@ -1,3 +1,7 @@<RESET>
h(4)<GREEN>,hh[44]<RESET>
-<RESET>
+
a = b + c<RESET>
<GREEN>aa = a<RESET>
@@ -146,9 +158,9 @@ cat > expect <<\EOF
<WHITE>index 330b04f..5ed8eff 100644<RESET>
<WHITE>--- a/pre<RESET>
<WHITE>+++ b/post<RESET>
-<BROWN>@@ -1,3 +1,7 @@<RESET>
+<CYAN>@@ -1,3 +1,7 @@<RESET>
h(4),<GREEN>hh[44<RESET>]
-<RESET>
+
a = b + c<RESET>
<GREEN>aa = a<RESET>
@@ -168,7 +180,7 @@ cat > expect <<\EOF
<WHITE>index c29453b..be22f37 100644<RESET>
<WHITE>--- a/pre<RESET>
<WHITE>+++ b/post<RESET>
-<BROWN>@@ -1 +1 @@<RESET>
+<CYAN>@@ -1 +1 @@<RESET>
aaa (aaa) <GREEN>aaa<RESET>
EOF
@@ -187,7 +199,7 @@ cat > expect <<\EOF
<WHITE>index 289cb9d..2d06f37 100644<RESET>
<WHITE>--- a/pre<RESET>
<WHITE>+++ b/post<RESET>
-<BROWN>@@ -1 +1 @@<RESET>
+<CYAN>@@ -1 +1 @@<RESET>
(<RED>:<RESET>
EOF
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..7584efa36b
--- /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_success '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/t4040-whitespace-status.sh b/t/t4040-whitespace-status.sh
new file mode 100755
index 0000000000..a30b03bcf2
--- /dev/null
+++ b/t/t4040-whitespace-status.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+test_description='diff --exit-code with whitespace'
+. ./test-lib.sh
+
+test_expect_success setup '
+ mkdir a b &&
+ echo >c &&
+ echo >a/d &&
+ echo >b/e &&
+ git add . &&
+ test_tick &&
+ git commit -m initial &&
+ echo " " >a/d &&
+ test_tick &&
+ git commit -a -m second &&
+ echo " " >a/d &&
+ echo " " >b/e &&
+ git add a/d
+'
+
+test_expect_success 'diff-tree --exit-code' '
+ test_must_fail git diff --exit-code HEAD^ HEAD &&
+ test_must_fail git diff-tree --exit-code HEAD^ HEAD
+'
+
+test_expect_success 'diff-tree -b --exit-code' '
+ git diff -b --exit-code HEAD^ HEAD &&
+ git diff-tree -b -p --exit-code HEAD^ HEAD &&
+ git diff-tree -b --exit-code HEAD^ HEAD
+'
+
+test_expect_success 'diff-index --cached --exit-code' '
+ test_must_fail git diff --cached --exit-code HEAD &&
+ test_must_fail git diff-index --cached --exit-code HEAD
+'
+
+test_expect_success 'diff-index -b -p --cached --exit-code' '
+ git diff -b --cached --exit-code HEAD &&
+ git diff-index -b -p --cached --exit-code HEAD
+'
+
+test_expect_success 'diff-index --exit-code' '
+ test_must_fail git diff --exit-code HEAD &&
+ test_must_fail git diff-index --exit-code HEAD
+'
+
+test_expect_success 'diff-index -b -p --exit-code' '
+ git diff -b --exit-code HEAD &&
+ git diff-index -b -p --exit-code HEAD
+'
+
+test_expect_success 'diff-files --exit-code' '
+ test_must_fail git diff --exit-code &&
+ test_must_fail git diff-files --exit-code
+'
+
+test_expect_success 'diff-files -b -p --exit-code' '
+ git diff -b --exit-code &&
+ git diff-files -b -p --exit-code
+'
+
+test_done
diff --git a/t/t4041-diff-submodule.sh b/t/t4041-diff-submodule.sh
new file mode 100755
index 0000000000..464305405a
--- /dev/null
+++ b/t/t4041-diff-submodule.sh
@@ -0,0 +1,327 @@
+#!/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 &&
+test_expect_success 'submodule is up to date' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+EOF
+"
+
+test_expect_success 'submodule contains untracked content' "
+ echo new > sm1/new-file &&
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head6-dirty:
+EOF
+"
+
+test_expect_success 'submodule contains untracked and modifed content' "
+ echo new > sm1/foo6 &&
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head6-dirty:
+EOF
+"
+
+test_expect_success 'submodule contains modifed content' "
+ rm -f sm1/new-file &&
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head6-dirty:
+EOF
+"
+
+(cd sm1; git commit -mchange foo6 >/dev/null) &&
+head8=$(cd sm1; git rev-parse --verify HEAD | cut -c1-7) &&
+test_expect_success 'submodule is modified' "
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head8:
+ > change
+EOF
+"
+
+test_expect_success 'modified submodule contains untracked content' "
+ echo new > sm1/new-file &&
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head8-dirty:
+ > change
+EOF
+"
+
+test_expect_success 'modified submodule contains untracked and modifed content' "
+ echo modification >> sm1/foo6 &&
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head8-dirty:
+ > change
+EOF
+"
+
+test_expect_success 'modified submodule contains modifed content' "
+ rm -f sm1/new-file &&
+ git diff-index -p --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head8-dirty:
+ > change
+EOF
+"
+
+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/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/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh
index 0e3ce3611d..c617c2a33d 100755
--- a/t/t4104-apply-boundary.sh
+++ b/t/t4104-apply-boundary.sh
@@ -134,4 +134,13 @@ test_expect_success 'two lines' '
'
+test_expect_success 'apply patch with 3 context lines matching at end' '
+ { echo a; echo b; echo c; echo d; } >file &&
+ git add file &&
+ echo e >>file &&
+ git diff >patch &&
+ >file &&
+ test_must_fail git apply patch
+'
+
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/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh
index 0f185caa44..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 &&
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index 9ace578f17..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 &&
diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh
index f92e259cc6..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 &&
diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh
index 83d4ba6798..b463b4f05c 100755
--- a/t/t4120-apply-popt.sh
+++ b/t/t4120-apply-popt.sh
@@ -22,4 +22,9 @@ test_expect_success 'apply git diff with -p2' '
git apply -p2 patch.file
'
+test_expect_success 'apply with too large -p' '
+ test_must_fail git apply --stat -p3 patch.file 2>err &&
+ grep "removing 3 leading" err
+'
+
test_done
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 f83322e513..fb9ad247bf 100755
--- a/t/t4124-apply-ws-rule.sh
+++ b/t/t4124-apply-ws-rule.sh
@@ -148,4 +148,287 @@ 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_expect_success 'applying beyond EOF requires one non-blank context line' '
+ { echo; echo; echo; echo; } >one &&
+ git add one &&
+ { echo b; } >>one &&
+ git diff -- one >patch &&
+
+ git checkout one &&
+ { echo a; echo; } >one &&
+ cp one expect &&
+ test_must_fail git apply --whitespace=fix patch &&
+ test_cmp one expect &&
+ test_must_fail git apply --ignore-space-change --whitespace=fix patch &&
+ test_cmp one expect
+'
+
+test_expect_success 'tons of blanks at EOF should not apply' '
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
+ echo; echo; echo; echo;
+ done >one &&
+ git add one &&
+ echo a >>one &&
+ git diff -- one >patch &&
+
+ >one &&
+ test_must_fail git apply --whitespace=fix patch &&
+ test_must_fail git apply --ignore-space-change --whitespace=fix patch
+'
+
+test_expect_success 'missing blank line at end with --whitespace=fix' '
+ echo a >one &&
+ echo >>one &&
+ git add one &&
+ echo b >>one &&
+ cp one expect &&
+ git diff -- one >patch &&
+ echo a >one &&
+ cp one saved-one &&
+ test_must_fail git apply patch &&
+ git apply --whitespace=fix patch &&
+ test_cmp one expect &&
+ mv saved-one one &&
+ git apply --ignore-space-change --whitespace=fix patch &&
+ test_cmp one expect
+'
+
+test_expect_success 'two missing blank lines at end with --whitespace=fix' '
+ { echo a; echo; echo b; echo c; } >one &&
+ cp one no-blank-lines &&
+ { echo; echo; } >>one &&
+ git add one &&
+ echo d >>one &&
+ cp one expect &&
+ echo >>one &&
+ git diff -- one >patch &&
+ cp no-blank-lines one &&
+ test_must_fail git apply patch &&
+ git apply --whitespace=fix patch &&
+ test_cmp one expect &&
+ mv no-blank-lines one &&
+ test_must_fail git apply patch &&
+ git apply --ignore-space-change --whitespace=fix patch &&
+ test_cmp one expect
+'
+
+test_expect_success 'shrink file with tons of missing blanks at end of file' '
+ { echo a; echo b; echo c; } >one &&
+ cp one no-blank-lines &&
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
+ echo; echo; echo; echo;
+ done >>one &&
+ git add one &&
+ echo a >one &&
+ cp one expect &&
+ git diff -- one >patch &&
+ cp no-blank-lines one &&
+ test_must_fail git apply patch &&
+ git apply --whitespace=fix patch &&
+ test_cmp one expect &&
+ mv no-blank-lines one &&
+ git apply --ignore-space-change --whitespace=fix patch &&
+ test_cmp one expect
+'
+
+test_expect_success 'missing blanks at EOF must only match blank lines' '
+ { echo a; echo b; } >one &&
+ git add one &&
+ { echo c; echo d; } >>one &&
+ git diff -- one >patch &&
+
+ echo a >one &&
+ test_must_fail git apply patch
+ test_must_fail git apply --whitespace=fix patch &&
+ test_must_fail git apply --ignore-space-change --whitespace=fix patch
+'
+
+sed -e's/Z//' >one <<EOF
+a
+b
+c
+ Z
+EOF
+
+test_expect_success 'missing blank line should match context line with spaces' '
+ git add one &&
+ echo d >>one &&
+ git diff -- one >patch &&
+ { echo a; echo b; echo c; } >one &&
+ cp one expect &&
+ { echo; echo d; } >>expect &&
+ git add one &&
+
+ git apply --whitespace=fix patch &&
+ test_cmp one expect
+'
+
+sed -e's/Z//' >one <<EOF
+a
+b
+c
+ Z
+EOF
+
+test_expect_success 'same, but with the --ignore-space-option' '
+ git add one &&
+ echo d >>one &&
+ cp one expect &&
+ git diff -- one >patch &&
+ { echo a; echo b; echo c; } >one &&
+ git add one &&
+
+ git checkout-index -f one &&
+ git apply --ignore-space-change --whitespace=fix patch &&
+ test_cmp one expect
+'
+
+test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
+ git config core.whitespace cr-at-eol &&
+ printf "a\r\n" >one &&
+ printf "b\r\n" >>one &&
+ printf "c\r\n" >>one &&
+ cp one save-one &&
+ printf " \r\n" >>one
+ git add one &&
+ printf "d\r\n" >>one &&
+ cp one expect &&
+ git diff -- one >patch &&
+ mv save-one one &&
+
+ git apply --ignore-space-change --whitespace=fix patch &&
+ test_cmp one expect
+'
+
+test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
+ git config --unset core.whitespace &&
+ printf "a\r\n" >one &&
+ printf "b\r\n" >>one &&
+ printf "c\r\n" >>one &&
+ cp one save-one &&
+ printf " \r\n" >>one
+ git add one &&
+ cp one expect &&
+ printf "d\r\n" >>one &&
+ git diff -- one >patch &&
+ mv save-one one &&
+ echo d >>expect &&
+
+ git apply --ignore-space-change --whitespace=fix patch &&
+ test_cmp one expect
+'
+
test_done
diff --git a/t/t4125-apply-ws-fuzz.sh b/t/t4125-apply-ws-fuzz.sh
index 3b471b641b..9671de7999 100755
--- a/t/t4125-apply-ws-fuzz.sh
+++ b/t/t4125-apply-ws-fuzz.sh
@@ -37,11 +37,11 @@ test_expect_success setup '
# patch-2 is the same as patch-1 but is based
# on a version that already has whitespace fixed,
# and does not introduce whitespace breakages.
- sed -e "s/ $//" patch-1 >patch-2 &&
+ sed -e "s/ \$//" patch-1 >patch-2 &&
# If all whitespace breakages are fixed the contents
# should look like file-fixed
- sed -e "s/ $//" file-1 >file-fixed
+ sed -e "s/ \$//" file-1 >file-fixed
'
diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh
index 8f6aea48d8..6cc741a634 100755
--- a/t/t4128-apply-root.sh
+++ b/t/t4128-apply-root.sh
@@ -58,6 +58,23 @@ test_expect_success 'apply --directory (new file)' '
'
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
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
index adfcbb5a3b..fc7af04931 100755
--- a/t/t4129-apply-samemode.sh
+++ b/t/t4129-apply-samemode.sh
@@ -4,6 +4,13 @@ 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 &&
@@ -16,14 +23,14 @@ test_expect_success setup '
git diff --stat -p >patch-1.txt
'
-test_expect_success 'same mode (no index)' '
+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 'same mode (with index)' '
+test_expect_success FILEMODE 'same mode (with index)' '
git reset --hard &&
chmod +x file &&
git add file &&
@@ -32,7 +39,7 @@ test_expect_success 'same mode (with index)' '
git diff --exit-code
'
-test_expect_success 'same mode (index only)' '
+test_expect_success FILEMODE 'same mode (index only)' '
git reset --hard &&
chmod +x file &&
git add file &&
@@ -40,20 +47,20 @@ test_expect_success 'same mode (index only)' '
git ls-files -s file | grep "^100755"
'
-test_expect_success 'mode update (no index)' '
+test_expect_success FILEMODE 'mode update (no index)' '
git reset --hard &&
git apply patch-1.txt &&
test -x file
'
-test_expect_success 'mode update (with index)' '
+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 'mode update (index only)' '
+test_expect_success FILEMODE 'mode update (index only)' '
git reset --hard &&
git apply --cached patch-1.txt &&
git ls-files -s file | grep "^100755"
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/t4133-apply-filenames.sh b/t/t4133-apply-filenames.sh
new file mode 100755
index 0000000000..34218071b6
--- /dev/null
+++ b/t/t4133-apply-filenames.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Andreas Gruenbacher
+#
+
+test_description='git apply filename consistency check'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ cat > bad1.patch <<EOF
+diff --git a/f b/f
+new file mode 100644
+index 0000000..d00491f
+--- /dev/null
++++ b/f-blah
+@@ -0,0 +1 @@
++1
+EOF
+ cat > bad2.patch <<EOF
+diff --git a/f b/f
+deleted file mode 100644
+index d00491f..0000000
+--- b/f-blah
++++ /dev/null
+@@ -1 +0,0 @@
+-1
+EOF
+'
+
+test_expect_success 'apply diff with inconsistent filenames in headers' '
+ test_must_fail git apply bad1.patch 2>err
+ grep "inconsistent new filename" err
+ test_must_fail git apply bad2.patch 2>err
+ grep "inconsistent old filename" err
+'
+
+test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 5e65afa0c1..810b04b817 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -77,6 +77,18 @@ test_expect_success setup '
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 &&
+ {
+ 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"
+ } | append_cr >patch1-crlf.eml &&
sed -n -e "3,\$p" msg >file &&
git add file &&
test_tick &&
@@ -108,6 +120,24 @@ test_expect_success 'am applies patch correctly' '
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^)"
+'
+
+test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
+ git checkout first &&
+ git am patch1-crlf.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"
@@ -180,6 +210,17 @@ test_expect_success 'am -3 falls back to 3-way merge' '
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 &&
@@ -261,7 +302,7 @@ 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 &&
+ 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"
@@ -271,7 +312,7 @@ 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 &&
+ 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"
@@ -285,9 +326,39 @@ 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 &&
+ 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/t4200-rerere.sh b/t/t4200-rerere.sh
index b68ab11f29..bb402c3780 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -57,7 +57,7 @@ test_expect_success 'conflicting merge' '
test_must_fail git merge first
'
-sha1=$(sed -e 's/ .*//' .git/MERGE_RR)
+sha1=$(perl -pe 's/ .*//' .git/MERGE_RR)
rr=.git/rr-cache/$sha1
test_expect_success 'recorded preimage' "grep ^=======$ $rr/preimage"
@@ -190,8 +190,6 @@ test_expect_success 'file2 added differently in two branches' '
git add file2 &&
git commit -m version2 &&
test_must_fail git merge fourth &&
- sha1=$(sed -e "s/ .*//" .git/MERGE_RR) &&
- rr=.git/rr-cache/$sha1 &&
echo Cello > file2 &&
git add file2 &&
git commit -m resolution
@@ -219,7 +217,22 @@ test_expect_success 'rerere.autoupdate' '
git checkout version2 &&
test_must_fail git merge fifth &&
test 0 = $(git ls-files -u | wc -l)
+'
+test_expect_success 'merge --rerere-autoupdate' '
+ git config --unset rerere.autoupdate
+ git reset --hard &&
+ git checkout version2 &&
+ test_must_fail git merge --rerere-autoupdate fifth &&
+ test 0 = $(git ls-files -u | wc -l)
+'
+
+test_expect_success 'merge --no-rerere-autoupdate' '
+ git config rerere.autoupdate true
+ git reset --hard &&
+ git checkout version2 &&
+ test_must_fail git merge --no-rerere-autoupdate fifth &&
+ test 2 = $(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 7b976ee36d..1dc224f6fb 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -37,6 +37,67 @@ test_expect_success setup '
'
+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) &&
@@ -109,6 +170,26 @@ test_expect_success 'git log --follow' '
'
+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 &&
@@ -134,5 +215,177 @@ test_expect_success 'log --grep -i' '
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
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/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index c942c8be85..27bfba55bd 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -37,7 +37,11 @@ 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) &&
@@ -46,7 +50,7 @@ test_expect_success \
test_expect_success \
'add ignored file' \
'echo ignore me >a/ignored &&
- echo ignored export-ignore >.gitattributes'
+ echo ignored export-ignore >.git/info/attributes'
test_expect_success \
'add files to repository' \
@@ -60,7 +64,7 @@ test_expect_success \
test_expect_success \
'create bare clone' \
'git clone --bare . bare.git &&
- cp .gitattributes bare.git/info/attributes'
+ cp .git/info/attributes bare.git/info/attributes'
test_expect_success \
'remove ignored file' \
@@ -76,7 +80,7 @@ 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' \
@@ -86,18 +90,26 @@ 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' \
'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 &&
- diff expected.mtime b.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' \
@@ -106,7 +118,7 @@ test_expect_success \
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' \
@@ -123,7 +135,7 @@ test_expect_success \
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' \
@@ -131,10 +143,11 @@ 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' \
@@ -144,8 +157,8 @@ 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 \
@@ -156,8 +169,8 @@ 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 \
@@ -172,23 +185,37 @@ 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'
@@ -196,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'
@@ -213,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 e70ea94a13..ebc36c1758 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -11,18 +11,30 @@ test_expect_success 'split sample box' \
'git mailsplit -o. "$TEST_DIRECTORY"/t5100/sample.mbox >last &&
last=`cat last` &&
echo total is $last &&
- test `cat last` = 13'
+ 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 &&
- echo msg &&
- test_cmp "$TEST_DIRECTORY"/t5100/msg$mail msg$mail &&
- echo patch &&
- test_cmp "$TEST_DIRECTORY"/t5100/patch$mail patch$mail &&
- echo info &&
- test_cmp "$TEST_DIRECTORY"/t5100/info$mail info$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
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/0010 b/t/t5100/0010
deleted file mode 100644
index f5892c9da7..0000000000
--- a/t/t5100/0010
+++ /dev/null
@@ -1,35 +0,0 @@
-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
-
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/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..4abb3d5c6c
--- /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/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-samples.mbox b/t/t5100/rfc2047-samples.mbox
index 3ca2470da2..1fc224810d 100644
--- a/t/t5100/rfc2047-samples.mbox
+++ b/t/t5100/rfc2047-samples.mbox
@@ -1,48 +1,48 @@
From nobody Mon Sep 17 00:00:00 2001
From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>
-To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>
-CC: =?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>
-Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
- =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=
+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: =?ISO-8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>
+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: =?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.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>
- (=?iso-8859-8?b?7eXs+SDv4SDp7Oj08A==?=)
+ (=?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=ISO-8859-1
+Content-type: text/plain; charset=ISO8859-1
From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?=)
+Subject: (=?ISO8859-1?Q?a?=)
From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?= b)
+Subject: (=?ISO8859-1?Q?a?= b)
From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)
+Subject: (=?ISO8859-1?Q?a?= =?ISO8859-1?Q?b?=)
From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)
+Subject: (=?ISO8859-1?Q?a?= =?ISO8859-1?Q?b?=)
From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?=
- =?ISO-8859-1?Q?b?=)
+Subject: (=?ISO8859-1?Q?a?=
+ =?ISO8859-1?Q?b?=)
From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a_b?=)
+Subject: (=?ISO8859-1?Q?a_b?=)
From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?= =?ISO-8859-2?Q?_b?=)
+Subject: (=?ISO8859-1?Q?a?= =?ISO8859-2?Q?_b?=)
diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox
index c5ad206b40..de1031241d 100644
--- a/t/t5100/sample.mbox
+++ b/t/t5100/sample.mbox
@@ -99,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
@@ -218,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
@@ -226,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
@@ -476,7 +476,7 @@ MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
--=-=-=
-Content-Type: text/plain; charset=iso-8859-15
+Content-Type: text/plain; charset=ISO8859-15
Content-Transfer-Encoding: quoted-printable
Here comes a commit log message, and
@@ -561,3 +561,125 @@ 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 ccfc64c6ee..7649b810b1 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -13,11 +13,12 @@ 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 &&
+ test-genrandom "seed a" 2097152 > a_big &&
+ test-genrandom "seed b" 2097152 > b_big &&
+ git update-index --add a a_big b b_big c &&
cat c >d && echo foo >>d && git update-index --add d &&
tree=`git write-tree` &&
commit=`git commit-tree $tree </dev/null` && {
@@ -221,7 +222,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 :;
@@ -230,7 +231,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 :;
@@ -239,7 +240,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 :;
@@ -250,7 +251,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 :;
@@ -281,26 +282,8 @@ test_expect_success \
:'
-test_expect_success \
- 'fake a SHA1 hash collision' \
- 'test -f .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67 &&
- cp -f .git/objects/9d/235ed07cd19811a6ceb342de82f190e49c9f68 \
- .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67'
-
-test_expect_success \
- 'make sure index-pack detects the SHA1 collision' \
- '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' \
- 'git config pack.packSizeLimit 200 &&
- packname_4=$(git pack-objects test-4 <obj-list) &&
- test 3 = $(ls test-4-*.pack | wc -l)'
-
test_expect_success 'unpacking with --strict' '
- git config --unset pack.packsizelimit &&
for j in a b c d e f g
do
for i in 0 1 2 3 4 5 6 7 8 9
@@ -393,10 +376,42 @@ 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_expect_success 'honor pack.packSizeLimit' '
+ git config pack.packSizeLimit 3m &&
+ packname_10=$(git pack-objects test-10 <obj-list) &&
+ test 2 = $(ls test-10-*.pack | wc -l)
+'
+
+test_expect_success 'verify resulting packs' '
+ git verify-pack test-10-*.pack
+'
+
+test_expect_success 'tolerate packsizelimit smaller than biggest object' '
+ git config pack.packSizeLimit 1 &&
+ packname_11=$(git pack-objects test-11 <obj-list) &&
+ test 5 = $(ls test-11-*.pack | wc -l)
'
+test_expect_success 'verify resulting packs' '
+ git verify-pack test-11-*.pack
+'
+
+#
+# WARNING!
+#
+# The following test is destructive. Please keep the next
+# two tests at the end of this file.
+#
+
+test_expect_success \
+ 'fake a SHA1 hash collision' \
+ 'test -f .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67 &&
+ cp -f .git/objects/9d/235ed07cd19811a6ceb342de82f190e49c9f68 \
+ .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67'
+
+test_expect_success \
+ 'make sure index-pack detects the SHA1 collision' \
+ 'test_must_fail git index-pack -o bad.idx test-3.pack 2>msg &&
+ grep "SHA1 COLLISION FOUND" msg'
+
test_done
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index e6f70d474f..4360e77d31 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -69,32 +69,27 @@ 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")
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"'
-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"'
@@ -208,7 +203,7 @@ test_expect_success \
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" &&
- dd if=/dev/zero of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \
+ 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
diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh
index d4e30fc43c..5f6cd4f333 100755
--- a/t/t5303-pack-corruption-resilience.sh
+++ b/t/t5303-pack-corruption-resilience.sh
@@ -55,6 +55,8 @@ do_corrupt_object() {
test_must_fail git verify-pack ${pack}.pack
}
+printf '\0' > zero
+
test_expect_success \
'initial setup validation' \
'create_test_files &&
@@ -66,7 +68,7 @@ test_expect_success \
test_expect_success \
'create corruption in header of first object' \
- 'do_corrupt_object $blob_1 0 < /dev/zero &&
+ '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'
@@ -125,7 +127,7 @@ test_expect_success \
'create corruption in header of first delta' \
'create_new_pack &&
git prune-packed &&
- do_corrupt_object $blob_2 0 < /dev/zero &&
+ 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'
@@ -180,7 +182,7 @@ 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 < /dev/zero &&
+ 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'
@@ -207,7 +209,7 @@ 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 < /dev/zero &&
+ 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'
@@ -259,7 +261,7 @@ test_expect_success \
test_expect_success \
'... and a redundant pack allows for full recovery too' \
- 'do_corrupt_object $blob_2 2 < /dev/zero &&
+ '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 &&
@@ -273,4 +275,13 @@ test_expect_success \
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 55ed7c7935..e2ed13dba2 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 &&
@@ -31,11 +42,7 @@ 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 &&
@@ -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
@@ -114,12 +117,8 @@ test_expect_success 'prune: do not prune heads listed as an argument' '
test_expect_success 'gc --no-prune' '
- 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*5001)) $BLOB_FILE &&
+ 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/ .*//") &&
@@ -140,9 +139,8 @@ test_expect_success 'gc respects gc.pruneExpire' '
test_expect_success 'gc --prune=<date>' '
- BLOB=$(echo aleph_0 | git hash-object -w --stdin) &&
- BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
- test-chmtime =-$((86400*5001)) $BLOB_FILE &&
+ add_blob &&
+ test-chmtime =-$((5001*$day)) $BLOB_FILE &&
git gc --prune=5002.days.ago &&
test -f $BLOB_FILE &&
git gc --prune=5000.days.ago &&
@@ -150,4 +148,50 @@ test_expect_success 'gc --prune=<date>' '
'
+test_expect_success 'gc --prune=never' '
+
+ add_blob &&
+ git gc --prune=never &&
+ test -f $BLOB_FILE &&
+ git gc --prune=now &&
+ test ! -f $BLOB_FILE
+
+'
+
+test_expect_success 'gc respects gc.pruneExpire=never' '
+
+ git config gc.pruneExpire never &&
+ add_blob &&
+ git gc &&
+ test -f $BLOB_FILE &&
+ git config gc.pruneExpire now &&
+ git gc &&
+ test ! -f $BLOB_FILE
+
+'
+
+test_expect_success 'prune --expire=never' '
+
+ add_blob &&
+ git prune --expire=never &&
+ test -f $BLOB_FILE &&
+ git prune &&
+ 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/t5400-send-pack.sh b/t/t5400-send-pack.sh
index f2d5581b12..c718253673 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -32,7 +32,7 @@ test_expect_success setup '
done &&
git update-ref HEAD "$commit" &&
git clone ./. victim &&
- ( cd victim && git log ) &&
+ ( cd victim && git config receive.denyCurrentBranch warn && git log ) &&
git update-ref HEAD "$zero" &&
parent=$zero &&
i=0 &&
@@ -129,6 +129,7 @@ rewound_push_setup() {
cd parent &&
git init &&
echo one >file && git add file && git commit -m one &&
+ git config receive.denyCurrentBranch warn &&
echo two >file && git commit -a -m two
) &&
git clone parent child &&
@@ -190,16 +191,11 @@ test_expect_success 'pushing wildcard refspecs respects forcing' '
test "$parent_head" = "$child_head"
'
-test_expect_success 'warn pushing to delete current branch' '
+test_expect_success 'deny 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_must_fail git send-pack ../parent :refs/heads/master 2>errs
)
'
diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh
index 64f66c94f3..17bcb0b040 100755
--- a/t/t5401-update-hooks.sh
+++ b/t/t5401-update-hooks.sh
@@ -17,22 +17,22 @@ 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_DIR=victim/.git git update-ref refs/heads/tofail $commit1 &&
+ git clone --bare ./. victim.git &&
+ 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
'
-cat >victim/.git/hooks/pre-receive <<'EOF'
+cat >victim.git/hooks/pre-receive <<'EOF'
#!/bin/sh
printf %s "$@" >>$GIT_DIR/pre-receive.args
cat - >$GIT_DIR/pre-receive.stdin
echo STDOUT pre-receive
echo STDERR pre-receive >&2
EOF
-chmod u+x victim/.git/hooks/pre-receive
+chmod u+x victim.git/hooks/pre-receive
-cat >victim/.git/hooks/update <<'EOF'
+cat >victim.git/hooks/update <<'EOF'
#!/bin/sh
echo "$@" >>$GIT_DIR/update.args
read x; printf %s "$x" >$GIT_DIR/update.stdin
@@ -40,77 +40,77 @@ echo STDOUT update $1
echo STDERR update $1 >&2
test "$1" = refs/heads/master || exit
EOF
-chmod u+x victim/.git/hooks/update
+chmod u+x victim.git/hooks/update
-cat >victim/.git/hooks/post-receive <<'EOF'
+cat >victim.git/hooks/post-receive <<'EOF'
#!/bin/sh
printf %s "$@" >>$GIT_DIR/post-receive.args
cat - >$GIT_DIR/post-receive.stdin
echo STDOUT post-receive
echo STDERR post-receive >&2
EOF
-chmod u+x victim/.git/hooks/post-receive
+chmod u+x victim.git/hooks/post-receive
-cat >victim/.git/hooks/post-update <<'EOF'
+cat >victim.git/hooks/post-update <<'EOF'
#!/bin/sh
echo "$@" >>$GIT_DIR/post-update.args
read x; printf %s "$x" >$GIT_DIR/post-update.stdin
echo STDOUT post-update
echo STDERR post-update >&2
EOF
-chmod u+x victim/.git/hooks/post-update
+chmod u+x victim.git/hooks/post-update
test_expect_success push '
- test_must_fail git send-pack --force ./victim/.git \
+ test_must_fail git send-pack --force ./victim.git \
master tofail >send.out 2>send.err
'
test_expect_success 'updated as expected' '
- test $(GIT_DIR=victim/.git git rev-parse master) = $commit1 &&
- test $(GIT_DIR=victim/.git git rev-parse tofail) = $commit1
+ test $(GIT_DIR=victim.git git rev-parse master) = $commit1 &&
+ test $(GIT_DIR=victim.git git rev-parse tofail) = $commit1
'
test_expect_success 'hooks ran' '
- test -f victim/.git/pre-receive.args &&
- test -f victim/.git/pre-receive.stdin &&
- test -f victim/.git/update.args &&
- test -f victim/.git/update.stdin &&
- test -f victim/.git/post-receive.args &&
- test -f victim/.git/post-receive.stdin &&
- test -f victim/.git/post-update.args &&
- test -f victim/.git/post-update.stdin
+ test -f victim.git/pre-receive.args &&
+ test -f victim.git/pre-receive.stdin &&
+ test -f victim.git/update.args &&
+ test -f victim.git/update.stdin &&
+ test -f victim.git/post-receive.args &&
+ test -f victim.git/post-receive.stdin &&
+ test -f victim.git/post-update.args &&
+ test -f victim.git/post-update.stdin
'
test_expect_success 'pre-receive hook input' '
(echo $commit0 $commit1 refs/heads/master;
echo $commit1 $commit0 refs/heads/tofail
- ) | test_cmp - 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
- ) | test_cmp - victim/.git/update.args
+ ) | test_cmp - victim.git/update.args
'
test_expect_success 'post-receive hook input' '
echo $commit0 $commit1 refs/heads/master |
- test_cmp - victim/.git/post-receive.stdin
+ test_cmp - victim.git/post-receive.stdin
'
test_expect_success 'post-update hook arguments' '
echo refs/heads/master |
- test_cmp - victim/.git/post-update.args
+ test_cmp - victim.git/post-update.args
'
test_expect_success 'all hook stdin is /dev/null' '
- ! test -s victim/.git/update.stdin &&
- ! test -s victim/.git/post-update.stdin
+ ! test -s victim.git/update.stdin &&
+ ! test -s victim.git/post-update.stdin
'
test_expect_success 'all *-receive hook args are empty' '
- ! test -s victim/.git/pre-receive.args &&
- ! test -s victim/.git/post-receive.args
+ ! test -s victim.git/pre-receive.args &&
+ ! test -s victim.git/post-receive.args
'
test_expect_success 'send-pack produced no output' '
@@ -118,20 +118,21 @@ test_expect_success 'send-pack produced no output' '
'
cat <<EOF >expect
-STDOUT pre-receive
-STDERR pre-receive
-STDOUT update refs/heads/master
-STDERR update refs/heads/master
-STDOUT update refs/heads/tofail
-STDERR update refs/heads/tofail
-STDOUT post-receive
-STDERR post-receive
-STDOUT post-update
-STDERR post-update
+remote: STDOUT pre-receive
+remote: STDERR pre-receive
+remote: STDOUT update refs/heads/master
+remote: STDERR update refs/heads/master
+remote: STDOUT update refs/heads/tofail
+remote: STDERR update refs/heads/tofail
+remote: error: hook declined to update refs/heads/tofail
+remote: STDOUT post-receive
+remote: STDERR post-receive
+remote: STDOUT post-update
+remote: STDERR post-update
EOF
test_expect_success 'send-pack stderr contains hook messages' '
- grep ^STD send.err >actual &&
- test_cmp - actual <expect
+ grep ^remote: send.err | sed "s/ *\$//" >actual &&
+ test_cmp expect actual
'
test_done
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index a7bef9371f..d05a9138b4 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -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/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index cb9aacc7bc..4bda18a662 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -8,6 +8,7 @@ test_expect_success setup '
>file1 && git add file1 && test_tick &&
git commit -m Initial &&
+ git config receive.denyCurrentBranch warn &&
mkdir another && (
cd another &&
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index c450f33f33..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)
- eval "$name=$commit; export $name"
- 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 '/^size-pack:/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 && test_must_fail 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 4074e23ffa..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
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index eb637184a0..a82c5ffa1c 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 -e '1,/Tracked/d') &&
+ actual=$(git remote show "$1" | sed -ne 's|^ \(.*\) tracked$|\1|p')
shift &&
tokens_match "$*" "$actual"
}
@@ -135,48 +135,78 @@ EOF
cat > test/expect << EOF
* remote origin
- URL: $(pwd)/one
- Remote branch merged with 'git pull' while on branch master
+ 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
- New remote branch (next fetch will store in remotes/origin)
- 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 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
- URL: $(pwd)/one
- Remote branch merged with 'git pull' while on branch master
- master
- Tracked remote branches
+ Fetch URL: $(pwd)/one
+ Push URL: $(pwd)/one
+ HEAD branch: (not queried)
+ Remote branches: (status not queried)
master
side
- Local branches pushed with 'git push'
- master:upstream
- +refs/tags/lastbackup
+ 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' '
@@ -197,6 +227,46 @@ test_expect_success 'prune' '
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
@@ -295,6 +365,17 @@ test_expect_success 'update with arguments' '
'
+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
apis/master
apis/side
@@ -338,12 +419,26 @@ test_expect_success 'update default (overridden, with funny whitespace)' '
'
+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)
+
+'
+
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)
'
@@ -428,5 +523,229 @@ test_expect_success 'remote prune to cause a dangling symref' '
grep "dangling symref" err
'
-test_done
+test_expect_success 'show empty remote' '
+
+ test_create_repo empty &&
+ git clone empty empty-clone &&
+ (
+ cd empty-clone &&
+ git remote show origin
+ )
+'
+
+test_expect_success 'new remote' '
+(
+ git remote add someremote foo &&
+ echo foo >expect &&
+ git config --get-all remote.someremote.url >actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url bar' '
+(
+ git remote set-url someremote bar &&
+ echo bar >expect &&
+ git config --get-all remote.someremote.url >actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url baz bar' '
+(
+ git remote set-url someremote baz bar &&
+ echo baz >expect &&
+ git config --get-all remote.someremote.url >actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url zot bar' '
+(
+ test_must_fail git remote set-url someremote zot bar &&
+ echo baz >expect &&
+ git config --get-all remote.someremote.url >actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --push zot baz' '
+(
+ test_must_fail git remote set-url --push someremote zot baz &&
+ echo "YYY" >expect &&
+ echo baz >>expect &&
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --push zot' '
+(
+ git remote set-url --push someremote zot &&
+ echo zot >expect &&
+ echo "YYY" >>expect &&
+ echo baz >>expect &&
+ git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --push qux zot' '
+(
+ git remote set-url --push someremote qux zot &&
+ echo qux >expect &&
+ echo "YYY" >>expect &&
+ echo baz >>expect &&
+ git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --push foo qu+x' '
+(
+ git remote set-url --push someremote foo qu+x &&
+ echo foo >expect &&
+ echo "YYY" >>expect &&
+ echo baz >>expect &&
+ git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --push --add aaa' '
+(
+ git remote set-url --push --add someremote aaa &&
+ echo foo >expect &&
+ echo aaa >>expect &&
+ echo "YYY" >>expect &&
+ echo baz >>expect &&
+ git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --push bar aaa' '
+(
+ git remote set-url --push someremote bar aaa &&
+ echo foo >expect &&
+ echo bar >>expect &&
+ echo "YYY" >>expect &&
+ echo baz >>expect &&
+ git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --push --delete bar' '
+(
+ git remote set-url --push --delete someremote bar &&
+ echo foo >expect &&
+ echo "YYY" >>expect &&
+ echo baz >>expect &&
+ git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+test_expect_success 'remote set-url --push --delete foo' '
+(
+ git remote set-url --push --delete someremote foo &&
+ echo "YYY" >expect &&
+ echo baz >>expect &&
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --add bbb' '
+(
+ git remote set-url --add someremote bbb &&
+ echo "YYY" >expect &&
+ echo baz >>expect &&
+ echo bbb >>expect &&
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --delete .*' '
+(
+ test_must_fail git remote set-url --delete someremote .* &&
+ echo "YYY" >expect &&
+ echo baz >>expect &&
+ echo bbb >>expect &&
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --delete bbb' '
+(
+ git remote set-url --delete someremote bbb &&
+ echo "YYY" >expect &&
+ echo baz >>expect &&
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --delete baz' '
+(
+ test_must_fail git remote set-url --delete someremote baz &&
+ echo "YYY" >expect &&
+ echo baz >>expect &&
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --add ccc' '
+(
+ git remote set-url --add someremote ccc &&
+ echo "YYY" >expect &&
+ echo baz >>expect &&
+ echo ccc >>expect &&
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+test_expect_success 'remote set-url --delete baz' '
+(
+ git remote set-url --delete someremote baz &&
+ echo "YYY" >expect &&
+ echo ccc >>expect &&
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
+ echo "YYY" >>actual &&
+ git config --get-all remote.someremote.url >>actual &&
+ cmp expect actual
+)
+'
+
+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 d13c806624..169af1edde 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -341,4 +341,15 @@ test_expect_success 'fetch into the current branch with --update-head-ok' '
'
+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 22ba380034..c28932216b 100755
--- a/t/t5511-refspec.sh
+++ b/t/t5511-refspec.sh
@@ -72,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/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 1f4608d8ba..dbb927dec8 100755
--- a/t/t5515-fetch-merge-logic.sh
+++ b/t/t5515-fetch-merge-logic.sh
@@ -129,8 +129,7 @@ do
'' | '#'*) continue ;;
esac
test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'`
- cnt=`expr $test_count + 1`
- pfx=`printf "%04d" $cnt`
+ pfx=`printf "%04d" $test_count`
expect_f="$TEST_DIRECTORY/t5515/fetch.$test"
actual_f="$pfx-fetch.$test"
expect_r="$TEST_DIRECTORY/t5515/refs.$test"
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 89649e7a9b..0f04b2e894 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -12,6 +12,7 @@ mk_empty () {
(
cd testrepo &&
git init &&
+ git config receive.denyCurrentBranch warn &&
mv .git/hooks .git/hooks-disabled
)
}
@@ -122,6 +123,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 &&
@@ -162,6 +180,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 &&
@@ -419,6 +467,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 &&
@@ -486,6 +547,32 @@ test_expect_success 'allow deleting an invalid remote ref' '
'
+test_expect_success 'allow deleting a ref using --delete' '
+ mk_test heads/master &&
+ (cd testrepo && git config receive.denyDeleteCurrent warn) &&
+ git push testrepo --delete master &&
+ (cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)
+'
+
+test_expect_success 'allow deleting a tag using --delete' '
+ mk_test heads/master &&
+ git tag -a -m dummy_message deltag heads/master &&
+ git push testrepo --tags &&
+ (cd testrepo && git rev-parse --verify -q refs/tags/deltag) &&
+ git push testrepo --delete tag deltag &&
+ (cd testrepo && test_must_fail git rev-parse --verify refs/tags/deltag)
+'
+
+test_expect_success 'push --delete without args aborts' '
+ mk_test heads/master &&
+ test_must_fail git push testrepo --delete
+'
+
+test_expect_success 'push --delete refuses src:dest refspecs' '
+ mk_test heads/master &&
+ test_must_fail git push testrepo --delete master:foo
+'
+
test_expect_success 'warn on push to HEAD of non-bare repository' '
mk_test heads/master
(cd testrepo &&
diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh
index ea49dedbf8..e2ad260508 100755
--- a/t/t5517-push-mirror.sh
+++ b/t/t5517-push-mirror.sh
@@ -19,7 +19,8 @@ mk_repo_pair () {
mkdir mirror &&
(
cd mirror &&
- git init
+ git init &&
+ git config receive.denyCurrentBranch warn
) &&
mkdir master &&
(
diff --git a/t/t5518-fetch-exit-status.sh b/t/t5518-fetch-exit-status.sh
index c6bc65faa0..c2060bb870 100755
--- a/t/t5518-fetch-exit-status.sh
+++ b/t/t5518-fetch-exit-status.sh
@@ -22,7 +22,7 @@ test_expect_success setup '
git commit -a -m next
'
-test_expect_success 'non fast forward fetch' '
+test_expect_success 'non-fast-forward fetch' '
test_must_fail git fetch . master:side
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 725771fac1..dd2ee842e0 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -92,20 +92,47 @@ 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 &&
@@ -122,4 +149,15 @@ test_expect_success 'pull --rebase dies early with dirty working directory' '
'
+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
index 83e2e8ab80..1b06691bb4 100755
--- a/t/t5521-pull-options.sh
+++ b/t/t5521-pull-options.sh
@@ -4,8 +4,6 @@ test_description='pull options'
. ./test-lib.sh
-D=`pwd`
-
test_expect_success 'setup' '
mkdir parent &&
(cd parent && git init &&
@@ -13,48 +11,83 @@ test_expect_success 'setup' '
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 clonedq && git init &&
+ git pull -q "../parent" >out 2>err &&
+ test ! -s 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 cloned && git init &&
+ git pull "../parent" >out 2>err &&
+ test -s 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 clonedv && git init &&
+ git pull -v "../parent" >out 2>err &&
+ test -s 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 clonedvq && git init &&
+ git pull -v -q "../parent" >out 2>err &&
+ test ! -s out &&
+ test ! -s err)
'
-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
+ (cd clonedqv && git init &&
+ git pull -q -v "../parent" >out 2>err &&
+ test ! -s out &&
+ test -s err)
+'
+
+test_expect_success 'git pull --force' '
+ mkdir clonedoldstyle &&
+ (cd clonedoldstyle && git init &&
+ cat >>.git/config <<-\EOF &&
+ [remote "one"]
+ url = ../parent
+ fetch = refs/heads/master:refs/heads/mirror
+ [remote "two"]
+ url = ../parent
+ fetch = refs/heads/master:refs/heads/origin
+ [branch "master"]
+ remote = two
+ merge = refs/heads/master
+ EOF
+ git pull two &&
+ test_commit A &&
+ git branch -f origin &&
+ git pull --all --force
+ )
+'
+
+test_expect_success 'git pull --all' '
+ mkdir clonedmulti &&
+ (cd clonedmulti && git init &&
+ cat >>.git/config <<-\EOF &&
+ [remote "one"]
+ url = ../parent
+ fetch = refs/heads/*:refs/remotes/one/*
+ [remote "two"]
+ url = ../parent
+ fetch = refs/heads/*:refs/remotes/two/*
+ [branch "master"]
+ remote = one
+ merge = refs/heads/master
+ EOF
+ git pull --all
+ )
'
test_done
diff --git a/t/t5521-pull-symlink.sh b/t/t5522-pull-symlink.sh
index 5672b51e2e..7206817ca1 100755
--- a/t/t5521-pull-symlink.sh
+++ b/t/t5522-pull-symlink.sh
@@ -4,6 +4,12 @@ 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/
@@ -14,13 +20,19 @@ test_description='pulling from symlinked 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
-
+test_expect_success setup '
+ 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 &&
+ (
+ cd clone-repo &&
+ git config receive.denyCurrentBranch warn
+ ) &&
+ git config receive.denyCurrentBranch warn
+'
# Demonstrate that things work if we just avoid the symlink
#
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
new file mode 100755
index 0000000000..00da70763b
--- /dev/null
+++ b/t/t5523-push-upstream.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+test_description='push with --set-upstream'
+. ./test-lib.sh
+
+test_expect_success 'setup bare parent' '
+ git init --bare parent &&
+ git remote add upstream parent
+'
+
+test_expect_success 'setup local commit' '
+ echo content >file &&
+ git add file &&
+ git commit -m one
+'
+
+check_config() {
+ (echo $2; echo $3) >expect.$1
+ (git config branch.$1.remote
+ git config branch.$1.merge) >actual.$1
+ test_cmp expect.$1 actual.$1
+}
+
+test_expect_success 'push -u master:master' '
+ git push -u upstream master:master &&
+ check_config master upstream refs/heads/master
+'
+
+test_expect_success 'push -u master:other' '
+ git push -u upstream master:other &&
+ check_config master upstream refs/heads/other
+'
+
+test_expect_success 'push -u --dry-run master:otherX' '
+ git push -u --dry-run upstream master:otherX &&
+ check_config master upstream refs/heads/other
+'
+
+test_expect_success 'push -u master2:master2' '
+ git branch master2 &&
+ git push -u upstream master2:master2 &&
+ check_config master2 upstream refs/heads/master2
+'
+
+test_expect_success 'push -u master2:other2' '
+ git push -u upstream master2:other2 &&
+ check_config master2 upstream refs/heads/other2
+'
+
+test_expect_success 'push -u :master2' '
+ git push -u upstream :master2 &&
+ check_config master2 upstream refs/heads/other2
+'
+
+test_expect_success 'push -u --all' '
+ git branch all1 &&
+ git branch all2 &&
+ git push -u --all &&
+ check_config all1 upstream refs/heads/all1 &&
+ check_config all2 upstream refs/heads/all2
+'
+
+test_expect_success 'push -u HEAD' '
+ git checkout -b headbranch &&
+ git push -u upstream HEAD &&
+ check_config headbranch upstream refs/heads/headbranch
+'
+
+test_done
diff --git a/t/t5524-pull-msg.sh b/t/t5524-pull-msg.sh
new file mode 100755
index 0000000000..8cccecc2fc
--- /dev/null
+++ b/t/t5524-pull-msg.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+test_description='git pull message generation'
+
+. ./test-lib.sh
+
+dollar='$Dollar'
+
+test_expect_success setup '
+ test_commit initial afile original &&
+ git clone . cloned &&
+ (
+ cd cloned &&
+ echo added >bfile &&
+ git add bfile &&
+ test_tick &&
+ git commit -m "add bfile"
+ ) &&
+ test_tick && test_tick &&
+ echo "original $dollar" >afile &&
+ git add afile &&
+ git commit -m "do not clobber $dollar signs"
+'
+
+test_expect_success pull '
+(
+ cd cloned &&
+ git pull --log &&
+ git log -2 &&
+ git cat-file commit HEAD >result &&
+ grep Dollar result
+)
+'
+
+test_done
diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh
index f5102b902a..a696b8791b 100755
--- a/t/t5530-upload-pack-error.sh
+++ b/t/t5530-upload-pack-error.sh
@@ -30,11 +30,12 @@ test_expect_success 'fsck fails' '
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 &&
+ grep "unable to read" output.err &&
grep "pack-objects died" output.err
'
@@ -51,9 +52,21 @@ test_expect_success 'fsck fails' '
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
+ grep "bad tree object" output.err &&
+ grep "pack-objects died" output.err
'
test_expect_success 'create empty repository' '
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 10e5fd0d5a..bb18f8bfc4 100755
--- a/t/t5540-http-push.sh
+++ b/t/t5540-http-push.sh
@@ -3,30 +3,23 @@
# 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
-
if git http-push > /dev/null 2>&1 || [ $? -eq 128 ]
then
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
-
-if ! start_httpd >&3 2>&4
-then
- say "skipping test, web server setup failed"
- test_done
- exit
-fi
+ROOT_PATH="$PWD"
+start_httpd
test_expect_success 'setup remote repository' '
cd "$ROOT_PATH" &&
@@ -42,16 +35,17 @@ test_expect_success 'setup remote repository' '
cd test_repo.git &&
git --bare update-server-info &&
mv hooks/post-update.sample hooks/post-update &&
+ 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/test_repo.git test_repo_clone
+ git clone $HTTPD_URL/dumb/test_repo.git test_repo_clone
'
-test_expect_failure 'push to remote repository with packed refs' '
+test_expect_success 'push to remote repository with packed refs' '
cd "$ROOT_PATH"/test_repo_clone &&
: >path2 &&
git add path2 &&
@@ -63,16 +57,56 @@ test_expect_failure 'push to remote repository with packed refs' '
test $HEAD = $(git rev-parse --verify HEAD))
'
-test_expect_success ' push to remote repository with unpacked refs' '
+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 \
- 0c973ae9bd51902a28466f3850b543fa66a6aaf4) &&
+ 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 &&
@@ -81,10 +115,7 @@ 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 &&
test_must_fail git show-ref --verify refs/remotes/origin/dev
'
diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh
new file mode 100755
index 0000000000..53f54a2789
--- /dev/null
+++ b/t/t5541-http-push.sh
@@ -0,0 +1,132 @@
+#!/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
+'
+
+test_expect_success 'non-fast-forward push fails' '
+ cd "$ROOT_PATH"/test_repo_clone &&
+ git checkout master &&
+ echo "changed" > path2 &&
+ git commit -a -m path2 --amend &&
+
+ HEAD=$(git rev-parse --verify HEAD) &&
+ !(git push -v origin >output 2>&1) &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+ test $HEAD != $(git rev-parse --verify HEAD))
+'
+
+test_expect_success 'non-fast-forward push show ref status' '
+ grep "^ ! \[rejected\][ ]*master -> master (non-fast-forward)$" output
+'
+
+test_expect_success 'non-fast-forward push shows help message' '
+ grep "To prevent you from losing history, non-fast-forward updates were rejected" \
+ output
+'
+
+test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper' '
+ # create a dissimilarly-named remote ref so that git is unable to match the
+ # two refs (viz. local, remote) unless an explicit refspec is provided.
+ git push origin master:retsam
+
+ echo "change changed" > path2 &&
+ git commit -a -m path2 --amend &&
+
+ # push master too; this ensures there is at least one '"'push'"' command to
+ # the remote helper and triggers interaction with the helper.
+ !(git push -v origin +master master:retsam >output 2>&1) &&
+
+ grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *master -> master (forced update)$" output &&
+ grep "^ ! \[rejected\] *master -> retsam (non-fast-forward)$" output &&
+
+ grep "To prevent you from losing history, non-fast-forward updates were rejected" \
+ output
+'
+
+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-noserver.sh b/t/t5560-http-backend-noserver.sh
new file mode 100755
index 0000000000..44885b850c
--- /dev/null
+++ b/t/t5560-http-backend-noserver.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+test_description='test git-http-backend-noserver'
+. ./test-lib.sh
+
+HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
+
+run_backend() {
+ echo "$2" |
+ QUERY_STRING="${1#*\?}" \
+ GIT_PROJECT_ROOT="$HTTPD_DOCUMENT_ROOT_PATH" \
+ PATH_INFO="${1%%\?*}" \
+ git http-backend >act.out 2>act.err
+}
+
+GET() {
+ export REQUEST_METHOD="GET" &&
+ run_backend "/repo.git/$1" &&
+ unset REQUEST_METHOD &&
+ if ! grep "Status" act.out >act
+ then
+ printf "Status: 200 OK\r\n" >act
+ fi
+ printf "Status: $2\r\n" >exp &&
+ test_cmp exp act
+}
+
+POST() {
+ export REQUEST_METHOD="POST" &&
+ export CONTENT_TYPE="application/x-$1-request" &&
+ run_backend "/repo.git/$1" "$2" &&
+ unset REQUEST_METHOD &&
+ unset CONTENT_TYPE &&
+ if ! grep "Status" act.out >act
+ then
+ printf "Status: 200 OK\r\n" >act
+ fi
+ printf "Status: $3\r\n" >exp &&
+ test_cmp exp act
+}
+
+log_div() {
+ return 0
+}
+
+. "$TEST_DIRECTORY"/t556x_common
+
+expect_aliased() {
+ export REQUEST_METHOD="GET" &&
+ if test $1 = 0; then
+ run_backend "$2"
+ else
+ run_backend "$2" &&
+ echo "fatal: '$2': aliased" >exp.err &&
+ test_cmp exp.err act.err
+ fi
+ unset REQUEST_METHOD
+}
+
+test_expect_success 'http-backend blocks bad PATH_INFO' '
+ config http.getanyfile true &&
+
+ expect_aliased 0 /repo.git/HEAD &&
+
+ expect_aliased 1 /repo.git/../HEAD &&
+ expect_aliased 1 /../etc/passwd &&
+ expect_aliased 1 ../etc/passwd &&
+ expect_aliased 1 /etc//passwd &&
+ expect_aliased 1 /etc/./passwd &&
+ expect_aliased 1 //domain/data.txt
+'
+
+test_done
diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh
new file mode 100755
index 0000000000..8c6d0b2f20
--- /dev/null
+++ b/t/t5561-http-backend.sh
@@ -0,0 +1,149 @@
+#!/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-'5561'}
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+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_DIRECTORY"/t556x_common
+
+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
+
+### no git-daemon-export-ok
+###
+GET /smart_noexport/repo.git/HEAD HTTP/1.1 404 -
+GET /smart_noexport/repo.git/info/refs HTTP/1.1 404 -
+GET /smart_noexport/repo.git/objects/info/packs HTTP/1.1 404 -
+GET /smart_noexport/repo.git/objects/info/alternates HTTP/1.1 404 -
+GET /smart_noexport/repo.git/objects/info/http-alternates HTTP/1.1 404 -
+GET /smart_noexport/repo.git/$LOOSE_URL HTTP/1.1 404 -
+GET /smart_noexport/repo.git/$PACK_URL HTTP/1.1 404 -
+GET /smart_noexport/repo.git/$IDX_URL HTTP/1.1 404 -
+
+### git-daemon-export-ok
+###
+GET /smart_noexport/repo.git/HEAD HTTP/1.1 200
+GET /smart_noexport/repo.git/info/refs HTTP/1.1 200
+GET /smart_noexport/repo.git/objects/info/packs HTTP/1.1 200
+GET /smart_noexport/repo.git/objects/info/alternates HTTP/1.1 200 -
+GET /smart_noexport/repo.git/objects/info/http-alternates HTTP/1.1 200 -
+GET /smart_noexport/repo.git/$LOOSE_URL HTTP/1.1 200
+GET /smart_noexport/repo.git/$PACK_URL HTTP/1.1 200
+GET /smart_noexport/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/t556x_common b/t/t556x_common
new file mode 100755
index 0000000000..be024e551c
--- /dev/null
+++ b/t/t556x_common
@@ -0,0 +1,122 @@
+#!/bin/sh
+
+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
+}
+
+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"
+}
+
+SMART=smart
+export GIT_HTTP_EXPORT_ALL=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"
+'
+SMART=smart_noexport
+unset GIT_HTTP_EXPORT_ALL
+test_expect_success 'no export by default' '
+ log_div "no git-daemon-export-ok"
+ get_static_files "404 Not Found"
+'
+test_expect_success 'export if git-daemon-export-ok' '
+ log_div "git-daemon-export-ok"
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ touch git-daemon-export-ok
+ ) &&
+ get_static_files "200 OK"
+'
+SMART=smart
+export GIT_HTTP_EXPORT_ALL=1
+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"
+'
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index c3ffc8f15c..214756731b 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -161,4 +161,19 @@ test_expect_success 'clone a void' '
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
index 82b1d1e2b3..deffdaee49 100755
--- a/t/t5602-clone-remote-exec.sh
+++ b/t/t5602-clone-remote-exec.sh
@@ -18,8 +18,8 @@ test_expect_success 'clone calls git upload-pack unqualified with no -u option'
'
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
+ GIT_SSH=./not_ssh git clone -u ./something/bin/git-upload-pack localhost:/path/to/repo junk
+ echo "localhost ./something/bin/git-upload-pack '\''/path/to/repo'\''" >expected
test_cmp expected not_ssh_output
'
diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh
index 3559d17964..8b4c356cd2 100755
--- a/t/t5701-clone-local.sh
+++ b/t/t5701-clone-local.sh
@@ -119,7 +119,9 @@ test_expect_success 'bundle clone with nonexistent HEAD' '
test_expect_success 'clone empty repository' '
cd "$D" &&
mkdir empty &&
- (cd empty && git init) &&
+ (cd empty &&
+ git init &&
+ git config receive.denyCurrentBranch warn) &&
git clone empty empty-clone &&
test_tick &&
(cd empty-clone
@@ -132,4 +134,14 @@ test_expect_success 'clone empty repository' '
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 27825f5f31..02cb024723 100755
--- a/t/t5702-clone-options.sh
+++ b/t/t5702-clone-options.sh
@@ -27,7 +27,8 @@ test_expect_success 'redirected clone' '
'
test_expect_success 'redirected clone -v' '
- git clone -v "file://$(pwd)/parent" clone-redirected-v >out 2>err &&
+ git clone --progress "file://$(pwd)/parent" clone-redirected-progress \
+ >out 2>err &&
test -s err
'
diff --git a/t/t5705-clone-2gb.sh b/t/t5705-clone-2gb.sh
new file mode 100755
index 0000000000..adfaae8c5b
--- /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 --big-file-threshold=2 &&
+ 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/t6000lib.sh b/t/t6000lib.sh
index f55627b641..985d517a1c 100755..100644
--- a/t/t6000lib.sh
+++ b/t/t6000lib.sh
@@ -1,3 +1,5 @@
+: included from 6002 and others
+
[ -d .git/refs/tags ] || mkdir -p .git/refs/tags
:> sed.script
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 59d1f6283b..b0047d3c6b 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -19,6 +19,13 @@ test_cmp expect.$1 output.$1
"
}
+test_format percent %%h <<'EOF'
+commit 131a310eb913d107dd3c09a65d1651175898735d
+%h
+commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+%h
+EOF
+
test_format hash %H%n%h <<'EOF'
commit 131a310eb913d107dd3c09a65d1651175898735d
131a310eb913d107dd3c09a65d1651175898735d
@@ -162,4 +169,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/t6010-merge-base.sh b/t/t6010-merge-base.sh
index 04e4b7c5c2..0144d9e858 100755
--- a/t/t6010-merge-base.sh
+++ b/t/t6010-merge-base.sh
@@ -110,6 +110,18 @@ test_expect_success 'compute merge-base (all)' \
# 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 &&
@@ -137,6 +149,12 @@ test_expect_success 'merge-base A B C' '
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 &&
diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh
index 510bb9679f..af34a1e817 100755
--- a/t/t6012-rev-list-simplify.sh
+++ b/t/t6012-rev-list-simplify.sh
@@ -8,9 +8,6 @@ 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"
}
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/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh
new file mode 100755
index 0000000000..8d3fa7d014
--- /dev/null
+++ b/t/t6018-rev-list-glob.sh
@@ -0,0 +1,195 @@
+#!/bin/sh
+
+test_description='rev-list/rev-parse --glob'
+
+. ./test-lib.sh
+
+commit () {
+ test_tick &&
+ echo $1 > foo &&
+ git add foo &&
+ git commit -m "$1"
+}
+
+compare () {
+ # Split arguments on whitespace.
+ git $1 $2 >expected &&
+ git $1 $3 >actual &&
+ test_cmp expected actual
+}
+
+test_expect_success 'setup' '
+
+ commit master &&
+ git checkout -b subspace/one master &&
+ commit one &&
+ git checkout -b subspace/two master &&
+ commit two &&
+ git checkout -b subspace-x master &&
+ commit subspace-x &&
+ git checkout -b other/three master &&
+ commit three &&
+ git checkout -b someref master &&
+ commit some &&
+ git checkout master &&
+ commit master2 &&
+ git tag foo/bar master &&
+ git update-ref refs/remotes/foo/baz master
+'
+
+test_expect_success 'rev-parse --glob=refs/heads/subspace/*' '
+
+ compare rev-parse "subspace/one subspace/two" "--glob=refs/heads/subspace/*"
+
+'
+
+test_expect_success 'rev-parse --glob=heads/subspace/*' '
+
+ compare rev-parse "subspace/one subspace/two" "--glob=heads/subspace/*"
+
+'
+
+test_expect_success 'rev-parse --glob=refs/heads/subspace/' '
+
+ compare rev-parse "subspace/one subspace/two" "--glob=refs/heads/subspace/"
+
+'
+
+test_expect_success 'rev-parse --glob=heads/subspace/' '
+
+ compare rev-parse "subspace/one subspace/two" "--glob=heads/subspace/"
+
+'
+
+test_expect_success 'rev-parse --glob=heads/subspace' '
+
+ compare rev-parse "subspace/one subspace/two" "--glob=heads/subspace"
+
+'
+
+test_expect_success 'rev-parse --branches=subspace/*' '
+
+ compare rev-parse "subspace/one subspace/two" "--branches=subspace/*"
+
+'
+
+test_expect_success 'rev-parse --branches=subspace/' '
+
+ compare rev-parse "subspace/one subspace/two" "--branches=subspace/"
+
+'
+
+test_expect_success 'rev-parse --branches=subspace' '
+
+ compare rev-parse "subspace/one subspace/two" "--branches=subspace"
+
+'
+
+test_expect_success 'rev-parse --glob=heads/subspace/* --glob=heads/other/*' '
+
+ compare rev-parse "subspace/one subspace/two other/three" "--glob=heads/subspace/* --glob=heads/other/*"
+
+'
+
+test_expect_success 'rev-parse --glob=heads/someref/* master' '
+
+ compare rev-parse "master" "--glob=heads/someref/* master"
+
+'
+
+test_expect_success 'rev-parse --glob=heads/*' '
+
+ compare rev-parse "master other/three someref subspace-x subspace/one subspace/two" "--glob=heads/*"
+
+'
+
+test_expect_success 'rev-parse --tags=foo' '
+
+ compare rev-parse "foo/bar" "--tags=foo"
+
+'
+
+test_expect_success 'rev-parse --remotes=foo' '
+
+ compare rev-parse "foo/baz" "--remotes=foo"
+
+'
+
+test_expect_success 'rev-list --glob=refs/heads/subspace/*' '
+
+ compare rev-list "subspace/one subspace/two" "--glob=refs/heads/subspace/*"
+
+'
+
+test_expect_success 'rev-list --glob=heads/subspace/*' '
+
+ compare rev-list "subspace/one subspace/two" "--glob=heads/subspace/*"
+
+'
+
+test_expect_success 'rev-list --glob=refs/heads/subspace/' '
+
+ compare rev-list "subspace/one subspace/two" "--glob=refs/heads/subspace/"
+
+'
+
+test_expect_success 'rev-list --glob=heads/subspace/' '
+
+ compare rev-list "subspace/one subspace/two" "--glob=heads/subspace/"
+
+'
+
+test_expect_success 'rev-list --glob=heads/subspace' '
+
+ compare rev-list "subspace/one subspace/two" "--glob=heads/subspace"
+
+'
+
+test_expect_success 'rev-list --branches=subspace/*' '
+
+ compare rev-list "subspace/one subspace/two" "--branches=subspace/*"
+
+'
+
+test_expect_success 'rev-list --branches=subspace/' '
+
+ compare rev-list "subspace/one subspace/two" "--branches=subspace/"
+
+'
+
+test_expect_success 'rev-list --branches=subspace' '
+
+ compare rev-list "subspace/one subspace/two" "--branches=subspace"
+
+'
+test_expect_success 'rev-list --glob=heads/someref/* master' '
+
+ compare rev-list "master" "--glob=heads/someref/* master"
+
+'
+
+test_expect_success 'rev-list --glob=heads/subspace/* --glob=heads/other/*' '
+
+ compare rev-list "subspace/one subspace/two other/three" "--glob=heads/subspace/* --glob=heads/other/*"
+
+'
+
+test_expect_success 'rev-list --glob=heads/*' '
+
+ compare rev-list "master other/three someref subspace-x subspace/one subspace/two" "--glob=heads/*"
+
+'
+
+test_expect_success 'rev-list --tags=foo' '
+
+ compare rev-list "foo/bar" "--tags=foo"
+
+'
+
+test_expect_success 'rev-list --remotes=foo' '
+
+ compare rev-list "foo/baz" "--remotes=foo"
+
+'
+
+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/t6023-merge-file.sh b/t/t6023-merge-file.sh
index f8942bc890..6291307cd0 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"
@@ -140,8 +146,8 @@ test_expect_success 'binary files cannot be merged' '
grep "Cannot merge binary files" merge.err
'
-sed -e "s/deerit.$/deerit;/" -e "s/me;$/me./" < new5.txt > new6.txt
-sed -e "s/deerit.$/deerit,/" -e "s/me;$/me,/" < new5.txt > new7.txt
+sed -e "s/deerit.\$/deerit;/" -e "s/me;\$/me./" < new5.txt > new6.txt
+sed -e "s/deerit.\$/deerit,/" -e "s/me;\$/me,/" < new5.txt > new7.txt
test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '
diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh
index 129fa3000c..b3fbf659c0 100755
--- a/t/t6024-recursive-merge.sh
+++ b/t/t6024-recursive-merge.sh
@@ -65,18 +65,18 @@ test_expect_success "combined merge conflicts" "
"
cat > expect << EOF
-<<<<<<< HEAD:a1
+<<<<<<< HEAD
F
=======
G
->>>>>>> G:a1
+>>>>>>> G
EOF
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
@@ -93,8 +93,7 @@ test_expect_success 'refuse to merge binary files' '
git add binary-file &&
git commit -m binary2 &&
test_must_fail git merge F > merge.out 2> merge.err &&
- grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \
- merge.err
+ grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge.err
'
test_expect_success 'mark rename/delete as unmerged' '
diff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh
index 1ba0a25223..5e439972be 100755
--- a/t/t6026-merge-attr.sh
+++ b/t/t6026-merge-attr.sh
@@ -70,6 +70,18 @@ test_expect_success 'check merge result in working tree' '
'
+test_expect_success 'retry the merge with longer context' '
+ echo text conflict-marker-size=32 >>.gitattributes &&
+ git checkout -m text &&
+ sed -ne "/^\([<=>]\)\1\1\1*/{
+ s/ .*$//
+ p
+ }" >actual text &&
+ grep ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" actual &&
+ grep "================================" actual &&
+ grep "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" actual
+'
+
cat >./custom-merge <<\EOF
#!/bin/sh
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 5bbfa44e8d..3900d9f61f 100755
--- a/t/t6029-merge-subtree.sh
+++ b/t/t6029-merge-subtree.sh
@@ -52,6 +52,7 @@ test_expect_success 'initial merge' '
git merge -s ours --no-commit gui/master &&
git read-tree --prefix=git-gui/ -u gui/master &&
git commit -m "Merge git-gui as our subdirectory" &&
+ git checkout -b work &&
git ls-files -s >actual &&
(
echo "100644 $o1 0 git-gui/git-gui.sh"
@@ -65,9 +66,10 @@ test_expect_success 'merge update' '
echo git-gui2 > git-gui.sh &&
o3=$(git hash-object git-gui.sh) &&
git add git-gui.sh &&
+ git checkout -b master2 &&
git commit -m "update git-gui" &&
cd ../git &&
- git pull -s subtree gui master &&
+ git pull -s subtree gui master2 &&
git ls-files -s >actual &&
(
echo "100644 $o3 0 git-gui/git-gui.sh"
@@ -76,4 +78,47 @@ test_expect_success 'merge update' '
test_cmp expected actual
'
+test_expect_success 'initial ambiguous subtree' '
+ cd ../git &&
+ git reset --hard master &&
+ git checkout -b master2 &&
+ git merge -s ours --no-commit gui/master &&
+ git read-tree --prefix=git-gui2/ -u gui/master &&
+ git commit -m "Merge git-gui2 as our subdirectory" &&
+ git checkout -b work2 &&
+ git ls-files -s >actual &&
+ (
+ echo "100644 $o1 0 git-gui/git-gui.sh"
+ echo "100644 $o1 0 git-gui2/git-gui.sh"
+ echo "100644 $o2 0 git.c"
+ ) >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'merge using explicit' '
+ cd ../git &&
+ git reset --hard master2 &&
+ git pull -Xsubtree=git-gui gui master2 &&
+ git ls-files -s >actual &&
+ (
+ echo "100644 $o3 0 git-gui/git-gui.sh"
+ echo "100644 $o1 0 git-gui2/git-gui.sh"
+ echo "100644 $o2 0 git.c"
+ ) >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'merge2 using explicit' '
+ cd ../git &&
+ git reset --hard master2 &&
+ git pull -Xsubtree=git-gui2 gui master2 &&
+ git ls-files -s >actual &&
+ (
+ echo "100644 $o1 0 git-gui/git-gui.sh"
+ echo "100644 $o3 0 git-gui2/git-gui.sh"
+ echo "100644 $o2 0 git.c"
+ ) >expected &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 052a6c90f5..3b042aacd6 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -175,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
'
@@ -261,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
@@ -274,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
@@ -287,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
'
@@ -335,7 +335,7 @@ 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 skip only one range' '
@@ -385,7 +385,7 @@ test_expect_success 'bisect does not create a "bisect" branch' '
rev_hash6=$(git rev-parse --verify HEAD) &&
test "$rev_hash6" = "$HASH6" &&
git bisect good > my_bisect_log.txt &&
- grep "$HASH7 is first bad commit" 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" &&
@@ -423,7 +423,7 @@ test_expect_success 'skipped merge base when good and bad are siblings' '
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 "warning" my_bisect_log.txt &&
grep $SIDE_HASH6 my_bisect_log.txt &&
git bisect reset
'
@@ -482,28 +482,94 @@ test_expect_success 'good merge bases when good and bad are siblings' '
git bisect reset
'
-check_trace() {
- grep "$1" "$GIT_TRACE" | grep "\^$2" | grep "$3" >/dev/null
-}
-
test_expect_success 'optimized merge base checks' '
- GIT_TRACE="$(pwd)/trace.log" &&
- export GIT_TRACE &&
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 &&
- check_trace "rev-list" "$HASH7" "$SIDE_HASH7" &&
git bisect good > my_bisect_log2.txt &&
test -f ".git/BISECT_ANCESTORS_OK" &&
test "$HASH6" = $(git rev-parse --verify HEAD) &&
- : > "$GIT_TRACE" &&
git bisect bad > my_bisect_log3.txt &&
- test_must_fail check_trace "rev-list" "$HASH6" "$SIDE_HASH7" &&
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" &&
- check_trace "rev-list" "$HASH6" "$A_HASH" &&
- unset GIT_TRACE
+ 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"
+'
+
+test_expect_success 'erroring out when using bad path parameters' '
+ test_must_fail git bisect start $PARA_HASH7 $HASH1 -- foobar 2> error.txt &&
+ grep "bad path parameters" error.txt
'
#
diff --git a/t/t6031-merge-recursive.sh b/t/t6031-merge-recursive.sh
index 8073e0c3ef..8a3304fb0b 100755
--- a/t/t6031-merge-recursive.sh
+++ b/t/t6031-merge-recursive.sh
@@ -3,8 +3,10 @@
test_description='merge-recursive: handle file mode'
. ./test-lib.sh
-# Note that we follow "chmod +x F" with "update-index --chmod=+x F" to
-# help filesystems that do not have the executable bit.
+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 &&
@@ -15,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 update-index --chmod=+x 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
'
@@ -28,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 update-index --add --chmod=+x file2 &&
+ test_chmod +x file2 &&
git commit -m a2 &&
git checkout -b b2 master &&
: >file2 &&
@@ -46,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/t6033-merge-crlf.sh b/t/t6033-merge-crlf.sh
index 75d9602de4..e8d65eefb5 100755
--- a/t/t6033-merge-crlf.sh
+++ b/t/t6033-merge-crlf.sh
@@ -1,13 +1,5 @@
#!/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
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..3202e1de6d
--- /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_success '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/t6037-merge-ours-theirs.sh b/t/t6037-merge-ours-theirs.sh
new file mode 100755
index 0000000000..8ab3d61f44
--- /dev/null
+++ b/t/t6037-merge-ours-theirs.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+test_description='Merge-recursive ours and theirs variants'
+. ./test-lib.sh
+
+test_expect_success setup '
+ for i in 1 2 3 4 5 6 7 8 9
+ do
+ echo "$i"
+ done >file &&
+ git add file &&
+ cp file elif &&
+ git commit -m initial &&
+
+ sed -e "s/1/one/" -e "s/9/nine/" >file <elif &&
+ git commit -a -m ours &&
+
+ git checkout -b side HEAD^ &&
+
+ sed -e "s/9/nueve/" >file <elif &&
+ git commit -a -m theirs &&
+
+ git checkout master^0
+'
+
+test_expect_success 'plain recursive - should conflict' '
+ git reset --hard master &&
+ test_must_fail git merge -s recursive side &&
+ grep nine file &&
+ grep nueve file &&
+ ! grep 9 file &&
+ grep one file &&
+ ! grep 1 file
+'
+
+test_expect_success 'recursive favouring theirs' '
+ git reset --hard master &&
+ git merge -s recursive -Xtheirs side &&
+ ! grep nine file &&
+ grep nueve file &&
+ ! grep 9 file &&
+ grep one file &&
+ ! grep 1 file
+'
+
+test_expect_success 'recursive favouring ours' '
+ git reset --hard master &&
+ git merge -s recursive -X ours side &&
+ grep nine file &&
+ ! grep nueve file &&
+ ! grep 9 file &&
+ grep one file &&
+ ! grep 1 file
+'
+
+test_expect_success 'pull with -X' '
+ git reset --hard master && git pull -s recursive -Xours . side &&
+ git reset --hard master && git pull -s recursive -X ours . side &&
+ git reset --hard master && git pull -s recursive -Xtheirs . side &&
+ git reset --hard master && git pull -s recursive -X theirs . side &&
+ git reset --hard master && ! git pull -s recursive -X bork . side
+'
+
+test_done
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
index ba9060190d..1785e178a4 100755
--- a/t/t6040-tracking-info.sh
+++ b/t/t6040-tracking-info.sh
@@ -29,7 +29,9 @@ test_expect_success setup '
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'
@@ -56,15 +58,56 @@ test_expect_success 'checkout' '
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
+ test_must_fail git commit --dry-run
) >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_expect_success 'setup tracking with branch --set-upstream on existing branch' '
+ git branch from-master master &&
+ test_must_fail git config branch.from-master.merge > actual &&
+ git branch --set-upstream from-master master &&
+ git config branch.from-master.merge > actual &&
+ grep -q "^refs/heads/master$" actual
+'
+test_expect_success '--set-upstream does not change branch' '
+ git branch from-master2 master &&
+ test_must_fail git config branch.from-master2.merge > actual &&
+ git rev-list from-master2 &&
+ git update-ref refs/heads/from-master2 from-master2^ &&
+ git rev-parse from-master2 >expect2 &&
+ git branch --set-upstream from-master2 master &&
+ git config branch.from-master.merge > actual &&
+ git rev-parse from-master2 >actual2 &&
+ grep -q "^refs/heads/master$" actual &&
+ cmp expect2 actual2
+'
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/t6120-describe.sh b/t/t6120-describe.sh
index 8c7e081c53..065deadc29 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -34,6 +34,8 @@ test_expect_success setup '
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 &&
two=$(git rev-parse HEAD) &&
@@ -90,12 +92,18 @@ check_describe A-* HEAD^
check_describe D-* HEAD^^
check_describe A-* HEAD^^2
check_describe B HEAD^^2^
+check_describe D-* HEAD^^^
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
@@ -123,6 +131,20 @@ 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 &&
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index 8f5a06f7dd..42f6fff373 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -83,13 +83,13 @@ test_expect_success 'merge-msg test #1' '
'
cat >expected <<EOF
-Merge branch 'left' of $TEST_DIRECTORY/$test
+Merge branch 'left' of $(pwd)
EOF
test_expect_success 'merge-msg test #2' '
git checkout master &&
- git fetch "$TEST_DIRECTORY/$test" left &&
+ git fetch "$(pwd)" left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
test_cmp expected actual
@@ -208,4 +208,36 @@ test_expect_success 'merge-msg test #5-2' '
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 8bfae44a83..8052c86ad3 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -26,6 +26,13 @@ test_expect_success 'Create sample commit with known timestamp' '
git tag -a -m "Tagging at $datestamp" testtag
'
+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 ;;
@@ -39,6 +46,7 @@ test_atom() {
}
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
@@ -68,6 +76,7 @@ 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
@@ -203,6 +212,7 @@ test_expect_success 'Check format "rfc2822" date fields output' '
cat >expected <<\EOF
refs/heads/master
+refs/remotes/origin/master
refs/tags/testtag
EOF
@@ -214,6 +224,7 @@ test_expect_success 'Verify ascending sort' '
cat >expected <<\EOF
refs/tags/testtag
+refs/remotes/origin/master
refs/heads/master
EOF
@@ -224,6 +235,7 @@ test_expect_success 'Verify descending sort' '
cat >expected <<\EOF
'refs/heads/master'
+'refs/remotes/origin/master'
'refs/tags/testtag'
EOF
@@ -244,6 +256,7 @@ test_expect_success 'Quoting style: python' '
cat >expected <<\EOF
"refs/heads/master"
+"refs/remotes/origin/master"
"refs/tags/testtag"
EOF
@@ -273,16 +286,26 @@ test_expect_success 'Check short refname format' '
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
-master
+tags/master
EOF
-test_expect_success 'Check ambiguous head and tag refs' '
+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 &&
@@ -294,11 +317,22 @@ test_expect_success 'Check ambiguous head and tag refs' '
'
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' '
+test_expect_success 'Check ambiguous head and tag refs II (loose)' '
git checkout master &&
git tag ambiguous testtag^0 &&
git branch ambiguous testtag^0 &&
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 8fb3a56838..65a35d94a0 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -189,6 +189,18 @@ test_expect_success 'absolute pathname outside should fail' '(
)'
+test_expect_success 'git mv to move multiple sources into a directory' '
+ rm -fr .git && git init &&
+ mkdir dir other &&
+ >dir/a.txt &&
+ >dir/b.txt &&
+ git add dir/?.txt &&
+ git mv dir/a.txt dir/b.txt other &&
+ git ls-files >actual &&
+ { echo other/a.txt; echo other/b.txt; } >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'git mv should not change sha1 of moved cache entry' '
rm -fr .git &&
@@ -206,7 +218,7 @@ test_expect_success 'git mv should not change sha1 of moved cache entry' '
rm -f dirty dirty2
-test_expect_success 'git mv should overwrite symlink to a file' '
+test_expect_success SYMLINKS 'git mv should overwrite symlink to a file' '
rm -fr .git &&
git init &&
@@ -225,7 +237,7 @@ test_expect_success 'git mv should overwrite symlink to a file' '
rm -f moved symlink
-test_expect_success 'git mv should overwrite file with a symlink' '
+test_expect_success SYMLINKS 'git mv should overwrite file with a symlink' '
rm -fr .git &&
git init &&
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index b81593780a..af63d6ec6d 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,12 +26,17 @@ 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
'
@@ -48,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
@@ -116,8 +137,184 @@ do
! 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
+
+test_expect_success 'grep -q, silently report matches' '
+ >empty &&
+ git grep -q mmap >actual &&
+ test_cmp empty actual &&
+ test_must_fail git grep -q qfwfq >actual &&
+ test_cmp empty actual
+'
+
+# 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 hunk mark between files' '
+ git grep -C1 "^[yz]" >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'log grep setup' '
echo a >>file &&
test_tick &&
@@ -156,7 +353,7 @@ test_expect_success 'log grep (4)' '
'
test_expect_success 'log grep (5)' '
- git log --author=Thor -F --grep=Thu --pretty=tformat:%s >actual &&
+ git log --author=Thor -F --pretty=tformat:%s >actual &&
( echo third ; echo initial ) >expect &&
test_cmp expect actual
'
@@ -167,12 +364,115 @@ test_expect_success 'log grep (6)' '
test_cmp expect actual
'
+test_expect_success 'log --grep --author implicitly uses all-match' '
+ # grep matches initial and second but not third
+ # author matches only initial and third
+ git log --author="A U Thor" --grep=s --grep=l --format=%s >actual &&
+ echo initial >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 t)" = "t/t:test" &&
+ test "$(git 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_expect_success 'setup double-dash tests' '
+cat >double-dash <<EOF &&
+--
+->
+other
+EOF
+git add double-dash
+'
+
+cat >expected <<EOF
+double-dash:->
+EOF
+test_expect_success 'grep -- pattern' '
+ git grep -- "->" >actual &&
+ test_cmp expected actual
+'
+test_expect_success 'grep -- pattern -- pathspec' '
+ git grep -- "->" -- double-dash >actual &&
+ test_cmp expected actual
+'
+test_expect_success 'grep -e pattern -- path' '
+ git grep -e "->" -- double-dash >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+double-dash:--
+EOF
+test_expect_success 'grep -e -- -- path' '
+ git grep -e -- -- double-dash >actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index 329c851685..0da13a8d6b 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -288,4 +288,61 @@ test_expect_success 'Prune empty commits' '
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_expect_success 'setup submodule' '
+ rm -fr ?* .git &&
+ git init &&
+ test_commit file &&
+ mkdir submod &&
+ submodurl="$PWD/submod" &&
+ ( cd submod &&
+ git init &&
+ test_commit file-in-submod ) &&
+ git submodule add "$submodurl" &&
+ git commit -m "added submodule" &&
+ test_commit add-file &&
+ ( cd submod && test_commit add-in-submodule ) &&
+ git add submod &&
+ git commit -m "changed submodule" &&
+ git branch original HEAD
+'
+
+orig_head=`git show-ref --hash --head HEAD`
+
+test_expect_success 'rewrite submodule with another content' '
+ git filter-branch --tree-filter "test -d submod && {
+ rm -rf submod &&
+ git rm -rf --quiet submod &&
+ mkdir submod &&
+ : > submod/file
+ } || :" HEAD &&
+ test $orig_head != `git show-ref --hash --head HEAD`
+'
+
+test_expect_success 'replace submodule revision' '
+ git reset --hard original &&
+ git filter-branch -f --tree-filter \
+ "if git ls-files --error-unmatch -- submod > /dev/null 2>&1
+ then git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 submod
+ fi" HEAD &&
+ test $orig_head != `git show-ref --hash --head HEAD`
+'
+
test_done
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 69501e2711..73dbc4360b 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -185,8 +185,9 @@ cba
EOF
test_expect_success \
'listing tags with substring as pattern must print those matching' '
- git tag -l "*a*" > actual &&
- test_cmp expect actual
+ rm *a* &&
+ git tag -l "*a*" > current &&
+ test_cmp expect current
'
cat >expect <<EOF
@@ -580,28 +581,38 @@ test_expect_success \
'
# 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 &&
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 &&
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 &&
test_must_fail git tag -v annotated-tag file-annotated-tag
@@ -609,17 +620,6 @@ test_expect_success \
# 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>
@@ -633,7 +633,7 @@ 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' '
+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 &&
test_cmp expect actual
@@ -642,7 +642,7 @@ test_expect_success 'creating a signed tag with -m message should succeed' '
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 &&
@@ -650,14 +650,14 @@ test_expect_success 'sign with a given key id' '
'
-test_expect_success 'sign with an unknown id (1)' '
+test_expect_success GPG 'sign with an unknown id (1)' '
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)' '
test_must_fail git tag -u DEADBEEF -m "Another message" o-signed-tag
@@ -674,7 +674,7 @@ 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' '
+test_expect_success GPG '-u implies signed tag' '
GIT_EDITOR=./fakeeditor git tag -u CDDE430D implied-sign &&
get_tag_msg implied-sign >actual &&
test_cmp expect actual
@@ -687,7 +687,7 @@ 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 &&
get_tag_msg file-signed-tag >actual &&
@@ -701,7 +701,7 @@ 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' '
+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 &&
test_cmp expect actual
@@ -710,13 +710,13 @@ test_expect_success 'creating a signed tag with -F - should succeed' '
get_tag_header implied-annotate $commit commit $time >expect
./fakeeditor >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success '-s implies annotated tag' '
+test_expect_success GPG '-s implies annotated tag' '
GIT_EDITOR=./fakeeditor git tag -s implied-annotate &&
get_tag_msg implied-annotate >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 &&
@@ -724,13 +724,13 @@ test_expect_success \
! tag_exists nosigtag
'
-test_expect_success 'verifying a signed tag should succeed' \
+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' \
+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' '
test_must_fail git tag -v signed-tag annotated-tag &&
test_must_fail git tag -v file-annotated-tag file-signed-tag &&
@@ -739,7 +739,7 @@ test_expect_success \
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) &&
@@ -751,7 +751,7 @@ test_expect_success 'verifying a forged tag should fail' '
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 &&
get_tag_msg empty-signed-tag >actual &&
@@ -762,7 +762,7 @@ test_expect_success \
>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 &&
get_tag_msg emptyfile-signed-tag >actual &&
@@ -785,7 +785,7 @@ 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 &&
get_tag_msg blanks-signed-tag >actual &&
@@ -795,7 +795,7 @@ test_expect_success \
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 &&
get_tag_msg blank-signed-tag >actual &&
@@ -808,7 +808,7 @@ 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 &&
get_tag_msg blankfile-signed-tag >actual &&
@@ -819,7 +819,7 @@ test_expect_success \
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 &&
get_tag_msg blanknonlfile-signed-tag >actual &&
@@ -856,7 +856,7 @@ 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 &&
get_tag_msg comments-signed-tag >actual &&
@@ -866,7 +866,7 @@ test_expect_success \
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 &&
get_tag_msg comment-signed-tag >actual &&
@@ -879,7 +879,7 @@ 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 &&
get_tag_msg commentfile-signed-tag >actual &&
@@ -890,7 +890,7 @@ test_expect_success \
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 &&
get_tag_msg commentnonlfile-signed-tag >actual &&
@@ -900,7 +900,7 @@ test_expect_success \
# 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 &&
@@ -925,7 +925,7 @@ test_expect_success \
test_cmp expect actual
'
-test_expect_success \
+test_expect_success GPG \
'listing the zero-lines message of a signed tag should succeed' '
git tag -s -m "" stag-zero-lines &&
@@ -953,7 +953,7 @@ test_expect_success \
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 &&
@@ -998,12 +998,12 @@ test_expect_success \
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} &&
get_tag_msg tree-signed-tag >actual &&
@@ -1013,7 +1013,7 @@ test_expect_success \
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 &&
get_tag_msg blob-signed-tag >actual &&
@@ -1023,7 +1023,7 @@ test_expect_success \
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 &&
get_tag_msg tag-signed-tag >actual &&
@@ -1032,7 +1032,7 @@ test_expect_success \
# try to sign with bad user.signingkey
git config user.signingkey BobTheMouse
-test_expect_success \
+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
@@ -1040,7 +1040,7 @@ 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' \
'test_must_fail git tag -v signed-tag'
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/t7006-pager.sh b/t/t7006-pager.sh
new file mode 100755
index 0000000000..d9202d5af5
--- /dev/null
+++ b/t/t7006-pager.sh
@@ -0,0 +1,176 @@
+#!/bin/sh
+
+test_description='Test automatic use of a pager.'
+
+. ./test-lib.sh
+
+rm -f stdout_is_tty
+test_expect_success 'set up terminal for tests' '
+ if test -t 1
+ then
+ : > stdout_is_tty
+ elif
+ test_have_prereq PERL &&
+ "$PERL_PATH" "$TEST_DIRECTORY"/t7006/test-terminal.perl \
+ sh -c "test -t 1"
+ then
+ : > test_terminal_works
+ fi
+'
+
+if test -e stdout_is_tty
+then
+ test_terminal() { "$@"; }
+ test_set_prereq TTY
+elif test -e test_terminal_works
+then
+ test_terminal() {
+ "$PERL_PATH" "$TEST_DIRECTORY"/t7006/test-terminal.perl "$@"
+ }
+ test_set_prereq TTY
+else
+ say no usable terminal, so skipping some tests
+fi
+
+unset GIT_PAGER GIT_PAGER_IN_USE
+git config --unset core.pager
+PAGER='cat > paginated.out'
+export PAGER
+
+test_expect_success 'setup' '
+ test_commit initial
+'
+
+rm -f paginated.out
+test_expect_success TTY 'some commands use a pager' '
+ test_terminal git log &&
+ test -e paginated.out
+'
+
+rm -f paginated.out
+test_expect_success TTY 'some commands do not use a pager' '
+ test_terminal git rev-list HEAD &&
+ ! test -e paginated.out
+'
+
+rm -f paginated.out
+test_expect_success 'no pager when stdout is a pipe' '
+ git log | cat &&
+ ! test -e paginated.out
+'
+
+rm -f paginated.out
+test_expect_success 'no pager when stdout is a regular file' '
+ git log > file &&
+ ! test -e paginated.out
+'
+
+rm -f paginated.out
+test_expect_success TTY 'git --paginate rev-list uses a pager' '
+ test_terminal git --paginate rev-list HEAD &&
+ test -e paginated.out
+'
+
+rm -f file paginated.out
+test_expect_success 'no pager even with --paginate when stdout is a pipe' '
+ git --paginate log | cat &&
+ ! test -e paginated.out
+'
+
+rm -f paginated.out
+test_expect_success TTY 'no pager with --no-pager' '
+ test_terminal git --no-pager log &&
+ ! test -e paginated.out
+'
+
+# A colored commit log will begin with an appropriate ANSI escape
+# for the first color; the text "commit" comes later.
+colorful() {
+ read firstline < $1
+ ! expr "$firstline" : "^[a-zA-Z]" >/dev/null
+}
+
+rm -f colorful.log colorless.log
+test_expect_success 'tests can detect color' '
+ git log --no-color > colorless.log &&
+ git log --color > colorful.log &&
+ ! colorful colorless.log &&
+ colorful colorful.log
+'
+
+rm -f colorless.log
+git config color.ui auto
+test_expect_success 'no color when stdout is a regular file' '
+ git log > colorless.log &&
+ ! colorful colorless.log
+'
+
+rm -f paginated.out
+git config color.ui auto
+test_expect_success TTY 'color when writing to a pager' '
+ TERM=vt100 test_terminal git log &&
+ colorful paginated.out
+'
+
+rm -f colorful.log
+git config color.ui auto
+test_expect_success 'color when writing to a file intended for a pager' '
+ TERM=vt100 GIT_PAGER_IN_USE=true git log > colorful.log &&
+ colorful colorful.log
+'
+
+unset PAGER GIT_PAGER
+git config --unset core.pager
+test_expect_success 'determine default pager' '
+ less=$(git var GIT_PAGER) &&
+ test -n "$less"
+'
+
+if expr "$less" : '^[a-z]*$' > /dev/null && test_have_prereq TTY
+then
+ test_set_prereq SIMPLEPAGER
+fi
+
+unset PAGER GIT_PAGER
+git config --unset core.pager
+rm -f default_pager_used
+test_expect_success SIMPLEPAGER 'default pager is used by default' '
+ cat > $less <<-EOF &&
+ #!$SHELL_PATH
+ wc > default_pager_used
+ EOF
+ chmod +x $less &&
+ PATH=.:$PATH test_terminal git log &&
+ test -e default_pager_used
+'
+
+unset GIT_PAGER
+git config --unset core.pager
+rm -f PAGER_used
+test_expect_success TTY 'PAGER overrides default pager' '
+ PAGER="wc > PAGER_used" &&
+ export PAGER &&
+ test_terminal git log &&
+ test -e PAGER_used
+'
+
+unset GIT_PAGER
+rm -f core.pager_used
+test_expect_success TTY 'core.pager overrides PAGER' '
+ PAGER=wc &&
+ export PAGER &&
+ git config core.pager "wc > core.pager_used" &&
+ test_terminal git log &&
+ test -e core.pager_used
+'
+
+rm -f GIT_PAGER_used
+test_expect_success TTY 'GIT_PAGER overrides core.pager' '
+ git config core.pager wc &&
+ GIT_PAGER="wc > GIT_PAGER_used" &&
+ export GIT_PAGER &&
+ test_terminal git log &&
+ test -e GIT_PAGER_used
+'
+
+test_done
diff --git a/t/t7006/test-terminal.perl b/t/t7006/test-terminal.perl
new file mode 100755
index 0000000000..73ff809371
--- /dev/null
+++ b/t/t7006/test-terminal.perl
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use IO::Pty;
+use File::Copy;
+
+# Run @$argv in the background with stdout redirected to $out.
+sub start_child {
+ my ($argv, $out) = @_;
+ my $pid = fork;
+ if (not defined $pid) {
+ die "fork failed: $!"
+ } elsif ($pid == 0) {
+ open STDOUT, ">&", $out;
+ close $out;
+ exec(@$argv) or die "cannot exec '$argv->[0]': $!"
+ }
+ return $pid;
+}
+
+# Wait for $pid to finish.
+sub finish_child {
+ # Simplified from wait_or_whine() in run-command.c.
+ my ($pid) = @_;
+
+ my $waiting = waitpid($pid, 0);
+ if ($waiting < 0) {
+ die "waitpid failed: $!";
+ } elsif ($? & 127) {
+ my $code = $? & 127;
+ warn "died of signal $code";
+ return $code - 128;
+ } else {
+ return $? >> 8;
+ }
+}
+
+sub xsendfile {
+ my ($out, $in) = @_;
+
+ # Note: the real sendfile() cannot read from a terminal.
+
+ # It is unspecified by POSIX whether reads
+ # from a disconnected terminal will return
+ # EIO (as in AIX 4.x, IRIX, and Linux) or
+ # end-of-file. Either is fine.
+ copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
+}
+
+if ($#ARGV < 1) {
+ die "usage: test-terminal program args";
+}
+my $master = new IO::Pty;
+my $slave = $master->slave;
+my $pid = start_child(\@ARGV, $slave);
+close $slave;
+xsendfile(\*STDOUT, $master);
+exit(finish_child($pid));
diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh
new file mode 100755
index 0000000000..bb4066f767
--- /dev/null
+++ b/t/t7011-skip-worktree-reading.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Nguyá»…n Thái Ngá»c Duy
+#
+
+test_description='skip-worktree bit test'
+
+. ./test-lib.sh
+
+cat >expect.full <<EOF
+H 1
+H 2
+H init.t
+H sub/1
+H sub/2
+EOF
+
+cat >expect.skip <<EOF
+S 1
+H 2
+H init.t
+S sub/1
+H sub/2
+EOF
+
+NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+ZERO_SHA0=0000000000000000000000000000000000000000
+setup_absent() {
+ test -f 1 && rm 1
+ git update-index --remove 1 &&
+ git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+ git update-index --skip-worktree 1
+}
+
+test_absent() {
+ echo "100644 $NULL_SHA1 0 1" > expected &&
+ git ls-files --stage 1 > result &&
+ test_cmp expected result &&
+ test ! -f 1
+}
+
+setup_dirty() {
+ git update-index --force-remove 1 &&
+ echo dirty > 1 &&
+ git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+ git update-index --skip-worktree 1
+}
+
+test_dirty() {
+ echo "100644 $NULL_SHA1 0 1" > expected &&
+ git ls-files --stage 1 > result &&
+ test_cmp expected result &&
+ echo dirty > expected
+ test_cmp expected 1
+}
+
+test_expect_success 'setup' '
+ test_commit init &&
+ mkdir sub &&
+ touch ./1 ./2 sub/1 sub/2 &&
+ git add 1 2 sub/1 sub/2 &&
+ git update-index --skip-worktree 1 sub/1 &&
+ git ls-files -t > result &&
+ test_cmp expect.skip result
+'
+
+test_expect_success 'update-index' '
+ setup_absent &&
+ git update-index 1 &&
+ test_absent
+'
+
+test_expect_success 'update-index' '
+ setup_dirty &&
+ git update-index 1 &&
+ test_dirty
+'
+
+test_expect_success 'update-index --remove' '
+ setup_absent &&
+ git update-index --remove 1 &&
+ test -z "$(git ls-files 1)" &&
+ test ! -f 1
+'
+
+test_expect_success 'update-index --remove' '
+ setup_dirty &&
+ git update-index --remove 1 &&
+ test -z "$(git ls-files 1)" &&
+ echo dirty > expected &&
+ test_cmp expected 1
+'
+
+test_expect_success 'ls-files --delete' '
+ setup_absent &&
+ test -z "$(git ls-files -d)"
+'
+
+test_expect_success 'ls-files --delete' '
+ setup_dirty &&
+ test -z "$(git ls-files -d)"
+'
+
+test_expect_success 'ls-files --modified' '
+ setup_absent &&
+ test -z "$(git ls-files -m)"
+'
+
+test_expect_success 'ls-files --modified' '
+ setup_dirty &&
+ test -z "$(git ls-files -m)"
+'
+
+test_expect_success 'grep with skip-worktree file' '
+ git update-index --no-skip-worktree 1 &&
+ echo test > 1 &&
+ git update-index 1 &&
+ git update-index --skip-worktree 1 &&
+ rm 1 &&
+ test "$(git grep --no-ext-grep test)" = "1:test"
+'
+
+echo ":000000 100644 $ZERO_SHA0 $NULL_SHA1 A 1" > expected
+test_expect_success 'diff-index does not examine skip-worktree absent entries' '
+ setup_absent &&
+ git diff-index HEAD -- 1 > result &&
+ test_cmp expected result
+'
+
+test_expect_success 'diff-index does not examine skip-worktree dirty entries' '
+ setup_dirty &&
+ git diff-index HEAD -- 1 > result &&
+ test_cmp expected result
+'
+
+test_expect_success 'diff-files does not examine skip-worktree absent entries' '
+ setup_absent &&
+ test -z "$(git diff-files -- one)"
+'
+
+test_expect_success 'diff-files does not examine skip-worktree dirty entries' '
+ setup_dirty &&
+ test -z "$(git diff-files -- one)"
+'
+
+test_expect_success 'git-rm succeeds on skip-worktree absent entries' '
+ setup_absent &&
+ git rm 1
+'
+
+test_expect_success 'commit on skip-worktree absent entries' '
+ git reset &&
+ setup_absent &&
+ test_must_fail git commit -m null 1
+'
+
+test_expect_success 'commit on skip-worktree dirty entries' '
+ git reset &&
+ setup_dirty &&
+ test_must_fail git commit -m null 1
+'
+
+test_done
diff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh
new file mode 100755
index 0000000000..8d8b1c0e25
--- /dev/null
+++ b/t/t7012-skip-worktree-writing.sh
@@ -0,0 +1,146 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Nguyá»…n Thái Ngá»c Duy
+#
+
+test_description='test worktree writing operations when skip-worktree is used'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit init &&
+ echo modified >> init.t &&
+ touch added &&
+ git add init.t added &&
+ git commit -m "modified and added" &&
+ git tag top
+'
+
+test_expect_success 'read-tree updates worktree, absent case' '
+ git checkout -f top &&
+ git update-index --skip-worktree init.t &&
+ rm init.t &&
+ git read-tree -m -u HEAD^ &&
+ echo init > expected &&
+ test_cmp expected init.t
+'
+
+test_expect_success 'read-tree updates worktree, dirty case' '
+ git checkout -f top &&
+ git update-index --skip-worktree init.t &&
+ echo dirty >> init.t &&
+ test_must_fail git read-tree -m -u HEAD^ &&
+ grep -q dirty init.t &&
+ test "$(git ls-files -t init.t)" = "S init.t" &&
+ git update-index --no-skip-worktree init.t
+'
+
+test_expect_success 'read-tree removes worktree, absent case' '
+ git checkout -f top &&
+ git update-index --skip-worktree added &&
+ rm added &&
+ git read-tree -m -u HEAD^ &&
+ test ! -f added
+'
+
+test_expect_success 'read-tree removes worktree, dirty case' '
+ git checkout -f top &&
+ git update-index --skip-worktree added &&
+ echo dirty >> added &&
+ test_must_fail git read-tree -m -u HEAD^ &&
+ grep -q dirty added &&
+ test "$(git ls-files -t added)" = "S added" &&
+ git update-index --no-skip-worktree added
+'
+
+NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+ZERO_SHA0=0000000000000000000000000000000000000000
+setup_absent() {
+ test -f 1 && rm 1
+ git update-index --remove 1 &&
+ git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+ git update-index --skip-worktree 1
+}
+
+test_absent() {
+ echo "100644 $NULL_SHA1 0 1" > expected &&
+ git ls-files --stage 1 > result &&
+ test_cmp expected result &&
+ test ! -f 1
+}
+
+setup_dirty() {
+ git update-index --force-remove 1 &&
+ echo dirty > 1 &&
+ git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+ git update-index --skip-worktree 1
+}
+
+test_dirty() {
+ echo "100644 $NULL_SHA1 0 1" > expected &&
+ git ls-files --stage 1 > result &&
+ test_cmp expected result &&
+ echo dirty > expected
+ test_cmp expected 1
+}
+
+cat >expected <<EOF
+S 1
+H 2
+H init.t
+S sub/1
+H sub/2
+EOF
+
+test_expect_success 'index setup' '
+ git checkout -f init &&
+ mkdir sub &&
+ touch ./1 ./2 sub/1 sub/2 &&
+ git add 1 2 sub/1 sub/2 &&
+ git update-index --skip-worktree 1 sub/1 &&
+ git ls-files -t > result &&
+ test_cmp expected result
+'
+
+test_expect_success 'git-add ignores worktree content' '
+ setup_absent &&
+ git add 1 &&
+ test_absent
+'
+
+test_expect_success 'git-add ignores worktree content' '
+ setup_dirty &&
+ git add 1 &&
+ test_dirty
+'
+
+test_expect_success 'git-rm fails if worktree is dirty' '
+ setup_dirty &&
+ test_must_fail git rm 1 &&
+ test_dirty
+'
+
+cat >expected <<EOF
+Would remove expected
+Would remove result
+EOF
+test_expect_success 'git-clean, absent case' '
+ setup_absent &&
+ git clean -n > result &&
+ test_cmp expected result
+'
+
+test_expect_success 'git-clean, dirty case' '
+ setup_dirty &&
+ git clean -n > result &&
+ test_cmp expected result
+'
+
+test_expect_failure 'git-apply adds file' false
+test_expect_failure 'git-apply updates file' false
+test_expect_failure 'git-apply removes file' false
+test_expect_failure 'git-mv to skip-worktree' false
+test_expect_failure 'git-mv from skip-worktree' false
+test_expect_failure 'git-checkout' false
+
+test_done
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
new file mode 100755
index 0000000000..fcac472598
--- /dev/null
+++ b/t/t7060-wtstatus.sh
@@ -0,0 +1,59 @@
+#!/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 add/rm <file>..." as appropriate 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 commit --dry-run >../actual &&
+ test_cmp ../expect ../actual &&
+ git status >../actual &&
+ test_cmp ../expect ../actual
+ )
+'
+
+test_done
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 5f3916bf4f..b8cf2603a1 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -419,7 +419,8 @@ test_expect_success 'resetting an unmodified path is a no-op' '
'
cat > expect << EOF
-file2: locally modified
+Unstaged changes after reset:
+M file2
EOF
test_expect_success '--mixed refreshes the index' '
diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh
index 42bf518c68..afb55b3a46 100755
--- a/t/t7103-reset-bare.sh
+++ b/t/t7103-reset-bare.sh
@@ -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' '
- test_must_fail 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/t7110-reset-merge.sh b/t/t7110-reset-merge.sh
new file mode 100755
index 0000000000..8704d00196
--- /dev/null
+++ b/t/t7110-reset-merge.sh
@@ -0,0 +1,183 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Christian Couder
+#
+
+test_description='Tests for "git reset --merge"'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ for i in 1 2 3; do echo line $i; done >file1 &&
+ cat file1 >file2 &&
+ git add file1 file2 &&
+ test_tick &&
+ git commit -m "Initial commit" &&
+ git tag initial &&
+ echo line 4 >>file1 &&
+ cat file1 >file2 &&
+ test_tick &&
+ git commit -m "add line 4 to file1" file1 &&
+ git tag second
+'
+
+# The next test will test the following:
+#
+# working index HEAD target working index HEAD
+# ----------------------------------------------------
+# file1: C C C D --merge D D D
+# file2: C D D D --merge C D D
+test_expect_success 'reset --merge is ok with changes in file it does not touch' '
+ git reset --merge HEAD^ &&
+ ! grep 4 file1 &&
+ grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
+ test -z "$(git diff --cached)"
+'
+
+test_expect_success 'reset --merge is ok when switching back' '
+ git reset --merge second &&
+ grep 4 file1 &&
+ grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)"
+'
+
+# The next test will test the following:
+#
+# working index HEAD target working index HEAD
+# ----------------------------------------------------
+# file1: B B C D --merge D D D
+# file2: C D D D --merge C D D
+test_expect_success 'reset --merge discards changes added to index (1)' '
+ git reset --hard second &&
+ cat file1 >file2 &&
+ echo "line 5" >> file1 &&
+ git add file1 &&
+ git reset --merge HEAD^ &&
+ ! grep 4 file1 &&
+ ! grep 5 file1 &&
+ grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
+ test -z "$(git diff --cached)"
+'
+
+test_expect_success 'reset --merge is ok again when switching back (1)' '
+ git reset --hard initial &&
+ echo "line 5" >> file2 &&
+ git add file2 &&
+ git reset --merge second &&
+ ! grep 4 file2 &&
+ ! grep 5 file1 &&
+ grep 4 file1 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)"
+'
+
+# The next test will test the following:
+#
+# working index HEAD target working index HEAD
+# ----------------------------------------------------
+# file1: C C C D --merge D D D
+# file2: C C D D --merge D D D
+test_expect_success 'reset --merge discards changes added to index (2)' '
+ git reset --hard second &&
+ echo "line 4" >> file2 &&
+ git add file2 &&
+ git reset --merge HEAD^ &&
+ ! grep 4 file2 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" &&
+ test -z "$(git diff)" &&
+ test -z "$(git diff --cached)"
+'
+
+test_expect_success 'reset --merge is ok again when switching back (2)' '
+ git reset --hard initial &&
+ git reset --merge second &&
+ ! grep 4 file2 &&
+ grep 4 file1 &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)"
+'
+
+# The next test will test the following:
+#
+# working index HEAD target working index HEAD
+# ----------------------------------------------------
+# file1: A B B C --merge (disallowed)
+test_expect_success 'reset --merge fails with changes in file it touches' '
+ git reset --hard second &&
+ echo "line 5" >> file1 &&
+ test_tick &&
+ git commit -m "add line 5" file1 &&
+ sed -e "s/line 1/changed line 1/" <file1 >file3 &&
+ mv file3 file1 &&
+ test_must_fail git reset --merge HEAD^ 2>err.log &&
+ grep file1 err.log | grep "not uptodate"
+'
+
+test_expect_success 'setup 3 different branches' '
+ git reset --hard second &&
+ git branch branch1 &&
+ git branch branch2 &&
+ git branch branch3 &&
+ git checkout branch1 &&
+ echo "line 5 in branch1" >> file1 &&
+ test_tick &&
+ git commit -a -m "change in branch1" &&
+ git checkout branch2 &&
+ echo "line 5 in branch2" >> file1 &&
+ test_tick &&
+ git commit -a -m "change in branch2" &&
+ git tag third &&
+ git checkout branch3 &&
+ echo a new file >file3 &&
+ rm -f file1 &&
+ git add file3 &&
+ test_tick &&
+ git commit -a -m "change in branch3"
+'
+
+# The next test will test the following:
+#
+# working index HEAD target working index HEAD
+# ----------------------------------------------------
+# file1: X U B C --merge C C C
+test_expect_success '"reset --merge HEAD^" is ok with pending merge' '
+ git checkout third &&
+ test_must_fail git merge branch1 &&
+ git reset --merge HEAD^ &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+ test -z "$(git diff --cached)" &&
+ test -z "$(git diff)"
+'
+
+# The next test will test the following:
+#
+# working index HEAD target working index HEAD
+# ----------------------------------------------------
+# file1: X U B B --merge B B B
+test_expect_success '"reset --merge HEAD" is ok with pending merge' '
+ git reset --hard third &&
+ test_must_fail git merge branch1 &&
+ git reset --merge HEAD &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse third)" &&
+ test -z "$(git diff --cached)" &&
+ test -z "$(git diff)"
+'
+
+test_expect_success '--merge with added/deleted' '
+ git reset --hard third &&
+ rm -f file2 &&
+ test_must_fail git merge branch3 &&
+ ! test -f file2 &&
+ test -f file3 &&
+ git diff --exit-code file3 &&
+ git diff --exit-code branch3 file3 &&
+ git reset --merge HEAD &&
+ ! test -f file3 &&
+ ! test -f file2 &&
+ git diff --exit-code --cached
+'
+
+test_done
diff --git a/t/t7111-reset-table.sh b/t/t7111-reset-table.sh
new file mode 100755
index 0000000000..de896c948d
--- /dev/null
+++ b/t/t7111-reset-table.sh
@@ -0,0 +1,113 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Christian Couder
+#
+
+test_description='Tests to check that "reset" options follow a known table'
+
+. ./test-lib.sh
+
+
+test_expect_success 'creating initial commits' '
+ test_commit E file1 &&
+ test_commit D file1 &&
+ test_commit C file1
+'
+
+while read W1 I1 H1 T opt W2 I2 H2
+do
+ test_expect_success "check: $W1 $I1 $H1 $T --$opt $W2 $I2 $H2" '
+ git reset --hard C &&
+ if test "$I1" != "$H1"
+ then
+ echo "$I1" >file1 &&
+ git add file1
+ fi &&
+ if test "$W1" != "$I1"
+ then
+ echo "$W1" >file1
+ fi &&
+ if test "$W2" != "XXXXX"
+ then
+ git reset --$opt $T &&
+ test "$(cat file1)" = "$W2" &&
+ git checkout-index -f -- file1 &&
+ test "$(cat file1)" = "$I2" &&
+ git checkout -f HEAD -- file1 &&
+ test "$(cat file1)" = "$H2"
+ else
+ test_must_fail git reset --$opt $T
+ fi
+ '
+done <<\EOF
+A B C D soft A B D
+A B C D mixed A D D
+A B C D hard D D D
+A B C D merge XXXXX
+A B C C soft A B C
+A B C C mixed A C C
+A B C C hard C C C
+A B C C merge XXXXX
+B B C D soft B B D
+B B C D mixed B D D
+B B C D hard D D D
+B B C D merge D D D
+B B C C soft B B C
+B B C C mixed B C C
+B B C C hard C C C
+B B C C merge C C C
+B C C D soft B C D
+B C C D mixed B D D
+B C C D hard D D D
+B C C D merge XXXXX
+B C C C soft B C C
+B C C C mixed B C C
+B C C C hard C C C
+B C C C merge B C C
+EOF
+
+test_expect_success 'setting up branches to test with unmerged entries' '
+ git reset --hard C &&
+ git branch branch1 &&
+ git branch branch2 &&
+ git checkout branch1 &&
+ test_commit B1 file1 &&
+ git checkout branch2 &&
+ test_commit B file1
+'
+
+while read W1 I1 H1 T opt W2 I2 H2
+do
+ test_expect_success "check: $W1 $I1 $H1 $T --$opt $W2 $I2 $H2" '
+ git reset --hard B &&
+ test_must_fail git merge branch1 &&
+ cat file1 >X_file1 &&
+ if test "$W2" != "XXXXX"
+ then
+ git reset --$opt $T &&
+ if test "$W2" = "X"
+ then
+ test_cmp file1 X_file1
+ else
+ test "$(cat file1)" = "$W2"
+ fi &&
+ git checkout-index -f -- file1 &&
+ test "$(cat file1)" = "$I2" &&
+ git checkout -f HEAD -- file1 &&
+ test "$(cat file1)" = "$H2"
+ else
+ test_must_fail git reset --$opt $T
+ fi
+ '
+done <<\EOF
+X U B C soft XXXXX
+X U B C mixed X C C
+X U B C hard C C C
+X U B C merge C C C
+X U B B soft XXXXX
+X U B B mixed X B B
+X U B B hard B B B
+X U B B merge B B B
+EOF
+
+test_done
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index bdb808af1a..d20ed61b48 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -166,19 +166,31 @@ test_expect_success 'checkout -m with merge conflict' '
! test -s current
'
-test_expect_success 'checkout to detach HEAD' '
+test_expect_success 'checkout to detach HEAD (with advice declined)' '
+ git config advice.detachedHead false &&
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
-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>
-HEAD is now at 7329388... Initial A one, A two
-EOF
-) &&
- test_cmp messages.expect messages &&
+ grep "HEAD is now at 7329388" messages &&
+ test 1 -eq $(wc -l <messages) &&
+ H=$(git rev-parse --verify HEAD) &&
+ M=$(git show-ref -s --verify refs/heads/master) &&
+ test "z$H" = "z$M" &&
+ if git symbolic-ref HEAD >/dev/null 2>&1
+ then
+ echo "OOPS, HEAD is still symbolic???"
+ false
+ else
+ : happy
+ fi
+'
+
+test_expect_success 'checkout to detach HEAD' '
+ git config advice.detachedHead true &&
+ git checkout -f renamer && git clean -f &&
+ git checkout renamer^ 2>messages &&
+ grep "HEAD is now at 7329388" messages &&
+ test 1 -lt $(wc -l <messages) &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/master) &&
test "z$H" = "z$M" &&
@@ -534,4 +546,69 @@ test_expect_success 'failing checkout -b should not break working tree' '
'
+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
+'
+
+(
+ echo "#!$SHELL_PATH"
+ cat <<\EOF
+O=$1 A=$2 B=$3
+cat "$A" >.tmp
+exec >"$A"
+echo '<<<<<<< filfre-theirs'
+cat "$B"
+echo '||||||| filfre-common'
+cat "$O"
+echo '======='
+cat ".tmp"
+echo '>>>>>>> filfre-ours'
+rm -f .tmp
+exit 1
+EOF
+) >filfre.sh
+chmod +x filfre.sh
+
+test_expect_success 'custom merge driver with checkout -m' '
+ git reset --hard &&
+
+ git config merge.filfre.driver "./filfre.sh %O %A %B" &&
+ git config merge.filfre.name "Feel-free merge driver" &&
+ git config merge.filfre.recursive binary &&
+ echo "arm merge=filfre" >.gitattributes &&
+
+ git checkout -b left &&
+ echo neutral >arm &&
+ git add arm .gitattributes &&
+ test_tick &&
+ git commit -m neutral &&
+ git branch right &&
+
+ echo left >arm &&
+ test_tick &&
+ git commit -a -m left &&
+ git checkout right &&
+
+ echo right >arm &&
+ test_tick &&
+ git commit -a -m right &&
+
+ test_must_fail git merge left &&
+ (
+ for t in filfre-common left right
+ do
+ grep $t arm || exit 1
+ done
+ exit 0
+ ) &&
+
+ mv arm expect &&
+ git checkout -m arm &&
+ test_cmp expect arm
+'
+
test_done
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 1636fac2a4..7d8ed68bef 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -22,6 +22,25 @@ test_expect_success 'setup' '
'
+test_expect_success 'git clean with skip-worktree .gitignore' '
+ git update-index --skip-worktree .gitignore &&
+ rm .gitignore &&
+ mkdir -p build docs &&
+ touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
+ git clean &&
+ test -f Makefile &&
+ test -f README &&
+ test -f src/part1.c &&
+ test -f src/part2.c &&
+ test ! -f a.out &&
+ test ! -f src/part3.c &&
+ test -f docs/manual.txt &&
+ test -f obj.o &&
+ test -f build/lib.so &&
+ git update-index --no-skip-worktree .gitignore &&
+ git checkout .gitignore
+'
+
test_expect_success 'git clean' '
mkdir -p build docs &&
@@ -373,11 +392,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 af690ec6c1..1a4dc5f893 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -64,6 +64,16 @@ test_expect_success 'submodule add' '
)
'
+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 &&
@@ -289,6 +299,15 @@ test_expect_success 'ls-files gracefully handles trailing slash' '
'
+test_expect_success 'moving to a commit without submodule does not leave empty dir' '
+ rm -rf init &&
+ mkdir init &&
+ git reset --hard &&
+ git checkout initial &&
+ test ! -d init &&
+ git checkout second
+'
+
test_expect_success 'submodule <invalid-path> warns' '
git submodule no-such-submodule 2> output.err &&
@@ -296,4 +315,20 @@ test_expect_success 'submodule <invalid-path> warns' '
'
+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 61498293b9..d3c039f724 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.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)' "
@@ -195,7 +213,7 @@ EOF
test_expect_success '--for-status' "
git submodule summary --for-status HEAD^ >actual &&
test_cmp actual - <<EOF
-# Modified submodules:
+# Submodule changes to be committed:
#
# * sm1 $head6...0000000:
#
@@ -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/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh
index aa6c44ce4f..9a21f783d3 100755
--- a/t/t7405-submodule-merge.sh
+++ b/t/t7405-submodule-merge.sh
@@ -54,13 +54,13 @@ test_expect_success setup '
git merge -s ours a
'
-test_expect_failure 'merging with modify/modify conflict' '
+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
-
+ git diff &&
+ test -n "$(git ls-files -u)"
'
test_expect_success 'merging with a modify/modify conflict between merge bases' '
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
new file mode 100755
index 0000000000..1382a8e58a
--- /dev/null
+++ b/t/t7406-submodule-update.sh
@@ -0,0 +1,206 @@
+#!/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 &&
+ git clone super rebasing &&
+ git clone super merging &&
+ (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"
+ ) &&
+ (cd super &&
+ git submodule add ../rebasing rebasing &&
+ test_tick &&
+ git commit -m "rebasing"
+ ) &&
+ (cd super &&
+ git submodule add ../merging merging &&
+ test_tick &&
+ git commit -m "rebasing"
+ )
+'
+
+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 -f .gitmodules 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 -f .gitmodules 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 5998baf27b..9f5c3edb03 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -150,7 +150,7 @@ EOF
test_expect_success '--signoff' '
echo "yet another content *narf*" >> foo &&
echo "zort" | git commit -s -F - foo &&
- git cat-file commit HEAD | sed "1,/^$/d" > output &&
+ git cat-file commit HEAD | sed "1,/^\$/d" > output &&
test_cmp expect output
'
@@ -183,4 +183,14 @@ test_expect_success 'commit message from stdin' '
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 b4e2b4db84..7940901d47 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -38,7 +38,7 @@ test_expect_success \
"echo King of the bongo >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)"
@@ -86,7 +86,7 @@ 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" \
@@ -107,7 +107,7 @@ 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" \
@@ -117,9 +117,13 @@ test_expect_success \
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 >output 2>&1"
test_expect_success \
+ "commit --author output mentions author" \
+ "grep Rubber.Duck output"
+
+test_expect_success PERL \
"interactive add" \
"echo 7 | git commit --interactive | grep 'What now'"
@@ -141,10 +145,10 @@ EOF
test_expect_success \
'editor not invoked if -F is given' '
echo "moo" >file &&
- VISUAL=./editor git commit -a -F msg &&
+ EDITOR=./editor git commit -a -F msg &&
git show -s --pretty=format:"%s" | grep -q good &&
echo "quack" >file &&
- echo "Another good message." | VISUAL=./editor git commit -a -F - &&
+ 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
@@ -211,6 +215,21 @@ test_expect_success 'amend commit to fix author' '
'
+test_expect_success 'amend commit to fix date' '
+
+ test_tick &&
+ newtick=$GIT_AUTHOR_DATE &&
+ git reset --hard &&
+ git cat-file -p HEAD |
+ sed -e "s/author.*/author $author $newtick/" \
+ -e "s/^\(committer.*> \).*$/\1$GIT_COMMITTER_DATE/" > \
+ expected &&
+ git commit --amend --date="$newtick" &&
+ git cat-file -p HEAD > current &&
+ test_cmp expected current
+
+'
+
test_expect_success 'sign off (1)' '
echo 1 >positive &&
@@ -247,6 +266,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 &&
diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index ad42c78d7c..844fb43c6d 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -234,7 +234,7 @@ cat >.git/FAKE_EDITOR <<EOF
# kill -TERM command added below.
EOF
-test_expect_success 'a SIGTERM should break locks' '
+test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' '
echo >>negative &&
! "$SHELL_PATH" -c '\''
echo kill -TERM $$ >> .git/FAKE_EDITOR
@@ -258,4 +258,122 @@ test_expect_success 'Hand committing of a redundant merge removes dups' '
'
+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
+
+'
+
+cat >.git/FAKE_EDITOR <<EOF
+#!$SHELL_PATH
+mv "\$1" "\$1.orig"
+(
+ echo message
+ cat "\$1.orig"
+) >"\$1"
+EOF
+
+echo '## Custom template' >template
+
+clear_config () {
+ (
+ git config --unset-all "$1"
+ case $? in
+ 0|5) exit 0 ;;
+ *) exit 1 ;;
+ esac
+ )
+}
+
+try_commit () {
+ git reset --hard &&
+ echo >>negative &&
+ GIT_EDITOR=.git/FAKE_EDITOR git commit -a $* $use_template &&
+ case "$use_template" in
+ '')
+ ! grep "^## Custom template" .git/COMMIT_EDITMSG ;;
+ *)
+ grep "^## Custom template" .git/COMMIT_EDITMSG ;;
+ esac
+}
+
+try_commit_status_combo () {
+
+ test_expect_success 'commit' '
+ clear_config commit.status &&
+ try_commit "" &&
+ grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+ test_expect_success 'commit' '
+ clear_config commit.status &&
+ try_commit "" &&
+ grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+ test_expect_success 'commit --status' '
+ clear_config commit.status &&
+ try_commit --status &&
+ grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+ test_expect_success 'commit --no-status' '
+ clear_config commit.status &&
+ try_commit --no-status
+ ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+ test_expect_success 'commit with commit.status = yes' '
+ clear_config commit.status &&
+ git config commit.status yes &&
+ try_commit "" &&
+ grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+ test_expect_success 'commit with commit.status = no' '
+ clear_config commit.status &&
+ git config commit.status no &&
+ try_commit "" &&
+ ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+ test_expect_success 'commit --status with commit.status = yes' '
+ clear_config commit.status &&
+ git config commit.status yes &&
+ try_commit --status &&
+ grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+ test_expect_success 'commit --no-status with commit.status = yes' '
+ clear_config commit.status &&
+ git config commit.status yes &&
+ try_commit --no-status &&
+ ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+ test_expect_success 'commit --status with commit.status = no' '
+ clear_config commit.status &&
+ git config commit.status no &&
+ try_commit --status &&
+ grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+ test_expect_success 'commit --no-status with commit.status = no' '
+ clear_config commit.status &&
+ git config commit.status no &&
+ try_commit --no-status &&
+ ! grep "^# Changes to be committed:" .git/COMMIT_EDITMSG
+ '
+
+}
+
+try_commit_status_combo
+
+use_template="-t template"
+
+try_commit_status_combo
+
test_done
diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh
index b069095995..8528f64c8d 100755
--- a/t/t7503-pre-commit-hook.sh
+++ b/t/t7503-pre-commit-hook.sh
@@ -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 47680e6df4..1f53ea8090 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -136,7 +136,7 @@ test_expect_success '--no-verify with failing hook (editor)' '
'
chmod -x "$HOOK"
-test_expect_success 'with non-executable hook' '
+test_expect_success POSIXPERM 'with non-executable hook' '
echo "content" >> file &&
git add file &&
@@ -144,7 +144,7 @@ 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 &&
@@ -153,7 +153,7 @@ test_expect_success 'with non-executable hook (editor)' '
'
-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 &&
@@ -161,7 +161,7 @@ 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 &&
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
index d9a08aac56..253c334319 100755
--- a/t/t7506-status-submodule.sh
+++ b/t/t7506-status-submodule.sh
@@ -5,34 +5,87 @@ 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 &&
+ test_create_repo sub &&
+ (
+ cd sub &&
+ : >bar &&
+ git add bar &&
+ git commit -m " Add bar" &&
+ : >foo &&
+ git add foo &&
+ git commit -m " Add foo"
+ ) &&
+ echo output > .gitignore &&
+ git add sub .gitignore &&
git commit -m "Add submodule sub"
'
test_expect_success 'status clean' '
- git status |
- grep "nothing to commit"
+ git status >output &&
+ grep "nothing to commit" output
'
-test_expect_success 'status -a clean' '
- git status -a |
- grep "nothing to commit"
+
+test_expect_success 'commit --dry-run -a clean' '
+ test_must_fail git commit --dry-run -a >output &&
+ grep "nothing to commit" output
+'
+
+test_expect_success 'status with modified file in submodule' '
+ (cd sub && git reset --hard) &&
+ echo "changed" >sub/foo &&
+ git status >output &&
+ grep "modified: sub" output
+'
+
+test_expect_success 'status with modified file in submodule (porcelain)' '
+ (cd sub && git reset --hard) &&
+ echo "changed" >sub/foo &&
+ git status --porcelain >output &&
+ diff output - <<-\EOF
+ M sub
+ EOF
+'
+
+test_expect_success 'status with added file in submodule' '
+ (cd sub && git reset --hard && echo >foo && git add foo) &&
+ git status >output &&
+ grep "modified: sub" output
+'
+
+test_expect_success 'status with added file in submodule (porcelain)' '
+ (cd sub && git reset --hard && echo >foo && git add foo) &&
+ git status --porcelain >output &&
+ diff output - <<-\EOF
+ M sub
+ EOF
+'
+
+test_expect_success 'status with untracked file in submodule' '
+ (cd sub && git reset --hard) &&
+ echo "content" >sub/new-file &&
+ git status >output &&
+ grep "modified: sub" output
+'
+
+test_expect_success 'status with untracked file in submodule (porcelain)' '
+ git status --porcelain >output &&
+ diff output - <<-\EOF
+ M sub
+ EOF
'
+
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"
+ git status >output &&
+ grep "nothing to commit" output
'
+
test_expect_success 'status -a clean (empty submodule dir)' '
- git status -a |
- grep "nothing to commit"
+ test_must_fail git commit --dry-run -a >output &&
+ grep "nothing to commit" output
'
test_done
diff --git a/t/t7502-status.sh b/t/t7508-status.sh
index 93f875f500..556d0faa77 100755
--- a/t/t7502-status.sh
+++ b/t/t7508-status.sh
@@ -8,26 +8,26 @@ test_description='git status'
. ./test-lib.sh
test_expect_success 'setup' '
- : > tracked &&
- : > modified &&
+ : >tracked &&
+ : >modified &&
mkdir dir1 &&
- : > dir1/tracked &&
- : > dir1/modified &&
+ : >dir1/tracked &&
+ : >dir1/modified &&
mkdir dir2 &&
- : > dir1/tracked &&
- : > dir1/modified &&
+ : >dir1/tracked &&
+ : >dir1/modified &&
git add . &&
git status >output &&
test_tick &&
git commit -m initial &&
- : > untracked &&
- : > dir1/untracked &&
- : > dir2/untracked &&
- echo 1 > dir1/modified &&
- echo 2 > dir2/modified &&
- echo 3 > dir2/added &&
+ : >untracked &&
+ : >dir1/untracked &&
+ : >dir2/untracked &&
+ echo 1 >dir1/modified &&
+ echo 2 >dir2/modified &&
+ echo 3 >dir2/added &&
git add dir2/added
'
@@ -37,7 +37,7 @@ test_expect_success 'status (1)' '
'
-cat > expect << \EOF
+cat >expect <<\EOF
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
@@ -63,7 +63,25 @@ EOF
test_expect_success 'status (2)' '
- git status > output &&
+ git status >output &&
+ test_cmp expect output
+
+'
+
+cat >expect <<\EOF
+ M dir1/modified
+A dir2/added
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+
+test_expect_success 'status -s (2)' '
+
+ git status -s >output &&
test_cmp expect output
'
@@ -85,8 +103,8 @@ cat >expect <<EOF
EOF
test_expect_success 'status -uno' '
mkdir dir3 &&
- : > dir3/untracked1 &&
- : > dir3/untracked2 &&
+ : >dir3/untracked1 &&
+ : >dir3/untracked2 &&
git status -uno >output &&
test_cmp expect output
'
@@ -97,6 +115,22 @@ test_expect_success 'status (status.showUntrackedFiles no)' '
test_cmp expect output
'
+cat >expect << EOF
+ M dir1/modified
+A dir2/added
+EOF
+test_expect_success 'status -s -uno' '
+ git config --unset status.showuntrackedfiles
+ git status -s -uno >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'status -s (status.showUntrackedFiles no)' '
+ git config status.showuntrackedfiles no
+ git status -s >output &&
+ test_cmp expect output
+'
+
cat >expect <<EOF
# On branch master
# Changes to be committed:
@@ -133,6 +167,29 @@ test_expect_success 'status (status.showUntrackedFiles normal)' '
'
cat >expect <<EOF
+ M dir1/modified
+A dir2/added
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? dir3/
+?? expect
+?? output
+?? untracked
+EOF
+test_expect_success 'status -s -unormal' '
+ git config --unset status.showuntrackedfiles
+ git status -s -unormal >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'status -s (status.showUntrackedFiles normal)' '
+ git config status.showuntrackedfiles normal
+ git status -s >output &&
+ test_cmp expect output
+'
+
+cat >expect <<EOF
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
@@ -169,7 +226,30 @@ test_expect_success 'status (status.showUntrackedFiles all)' '
test_cmp expect output
'
-cat > expect << \EOF
+cat >expect <<EOF
+ M dir1/modified
+A dir2/added
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+test_expect_success 'status -s -uall' '
+ git config --unset status.showuntrackedfiles
+ git status -s -uall >output &&
+ test_cmp expect output
+'
+test_expect_success 'status -s (status.showUntrackedFiles all)' '
+ git config status.showuntrackedfiles all
+ git status -s >output &&
+ rm -rf dir3 &&
+ git config --unset status.showuntrackedfiles &&
+ test_cmp expect output
+'
+
+cat >expect <<\EOF
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
@@ -195,12 +275,156 @@ EOF
test_expect_success 'status with relative paths' '
- (cd dir1 && git status) > output &&
+ (cd dir1 && git status) >output &&
+ test_cmp expect output
+
+'
+
+cat >expect <<\EOF
+ M modified
+A ../dir2/added
+?? untracked
+?? ../dir2/modified
+?? ../dir2/untracked
+?? ../expect
+?? ../output
+?? ../untracked
+EOF
+test_expect_success 'status -s with relative paths' '
+
+ (cd dir1 && git status -s) >output &&
test_cmp expect output
'
-cat > expect << \EOF
+cat >expect <<\EOF
+ M dir1/modified
+A dir2/added
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+
+test_expect_success 'status --porcelain ignores relative paths setting' '
+
+ (cd dir1 && git status --porcelain) >output &&
+ test_cmp expect output
+
+'
+
+test_expect_success 'setup unique colors' '
+
+ git config status.color.untracked blue
+
+'
+
+cat >expect <<\EOF
+# On branch master
+# Changes to be committed:
+# (use "git reset HEAD <file>..." to unstage)
+#
+# <GREEN>new file: dir2/added<RESET>
+#
+# Changed but not updated:
+# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
+#
+# <RED>modified: dir1/modified<RESET>
+#
+# Untracked files:
+# (use "git add <file>..." to include in what will be committed)
+#
+# <BLUE>dir1/untracked<RESET>
+# <BLUE>dir2/modified<RESET>
+# <BLUE>dir2/untracked<RESET>
+# <BLUE>expect<RESET>
+# <BLUE>output<RESET>
+# <BLUE>untracked<RESET>
+EOF
+
+test_expect_success 'status with color.ui' '
+
+ git config color.ui always &&
+ git status | test_decode_color >output &&
+ test_cmp expect output
+
+'
+
+test_expect_success 'status with color.status' '
+
+ git config --unset color.ui &&
+ git config color.status always &&
+ git status | test_decode_color >output &&
+ test_cmp expect output
+
+'
+
+cat >expect <<\EOF
+ <RED>M<RESET> dir1/modified
+<GREEN>A<RESET> dir2/added
+<BLUE>??<RESET> dir1/untracked
+<BLUE>??<RESET> dir2/modified
+<BLUE>??<RESET> dir2/untracked
+<BLUE>??<RESET> expect
+<BLUE>??<RESET> output
+<BLUE>??<RESET> untracked
+EOF
+
+test_expect_success 'status -s with color.ui' '
+
+ git config --unset color.status &&
+ git config color.ui always &&
+ git status -s | test_decode_color >output &&
+ test_cmp expect output
+
+'
+
+test_expect_success 'status -s with color.status' '
+
+ git config --unset color.ui &&
+ git config color.status always &&
+ git status -s | test_decode_color >output &&
+ test_cmp expect output
+
+'
+
+cat >expect <<\EOF
+ M dir1/modified
+A dir2/added
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+
+test_expect_success 'status --porcelain ignores color.ui' '
+
+ git config --unset color.status &&
+ git config color.ui always &&
+ git status --porcelain | test_decode_color >output &&
+ test_cmp expect output
+
+'
+
+test_expect_success 'status --porcelain ignores color.status' '
+
+ git config --unset color.ui &&
+ git config color.status always &&
+ git status --porcelain | test_decode_color >output &&
+ test_cmp expect output
+
+'
+
+# recover unconditionally from color tests
+git config --unset color.status
+git config --unset color.ui
+
+cat >expect <<\EOF
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
@@ -224,10 +448,29 @@ cat > expect << \EOF
# untracked
EOF
+
test_expect_success 'status without relative paths' '
git config status.relativePaths false
- (cd dir1 && git status) > output &&
+ (cd dir1 && git status) >output &&
+ test_cmp expect output
+
+'
+
+cat >expect <<\EOF
+ M dir1/modified
+A dir2/added
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+
+test_expect_success 'status -s without relative paths' '
+
+ (cd dir1 && git status -s) >output &&
test_cmp expect output
'
@@ -248,8 +491,8 @@ cat <<EOF >expect
# output
# untracked
EOF
-test_expect_success 'status of partial commit excluding new file in index' '
- git status dir1/modified >output &&
+test_expect_success 'dry-run of partial commit excluding new file in index' '
+ git commit --dry-run dir1/modified >output &&
test_cmp expect output
'
@@ -298,6 +541,28 @@ test_expect_success 'status --untracked-files=all does not show submodule' '
test_cmp expect output
'
+cat >expect <<EOF
+ M dir1/modified
+A dir2/added
+A sm
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+test_expect_success 'status -s submodule summary is disabled by default' '
+ git status -s >output &&
+ test_cmp expect output
+'
+
+# we expect the same as the previous test
+test_expect_success 'status -s --untracked-files=all does not show submodule' '
+ git status -s --untracked-files=all >output &&
+ test_cmp expect output
+'
+
head=$(cd sm && git rev-parse --short=7 --verify HEAD)
cat >expect <<EOF
@@ -314,7 +579,7 @@ cat >expect <<EOF
#
# modified: dir1/modified
#
-# Modified submodules:
+# Submodule changes to be committed:
#
# * sm 0000000...$head (1):
# > Add foo
@@ -335,6 +600,21 @@ test_expect_success 'status submodule summary' '
test_cmp expect output
'
+cat >expect <<EOF
+ M dir1/modified
+A dir2/added
+A sm
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+test_expect_success 'status -s submodule summary' '
+ git status -s >output &&
+ test_cmp expect output
+'
cat >expect <<EOF
# On branch master
@@ -358,7 +638,23 @@ EOF
test_expect_success 'status submodule summary (clean submodule)' '
git commit -m "commit submodule" &&
git config status.submodulesummary 10 &&
- test_must_fail git status >output &&
+ test_must_fail git commit --dry-run >output &&
+ test_cmp expect output &&
+ git status >output &&
+ test_cmp expect output
+'
+
+cat >expect <<EOF
+ M dir1/modified
+?? dir1/untracked
+?? dir2/modified
+?? dir2/untracked
+?? expect
+?? output
+?? untracked
+EOF
+test_expect_success 'status -s submodule summary (clean submodule)' '
+ git status -s >output &&
test_cmp expect output
'
@@ -376,7 +672,7 @@ cat >expect <<EOF
#
# modified: dir1/modified
#
-# Modified submodules:
+# Submodule changes to be committed:
#
# * sm 0000000...$head (1):
# > Add foo
@@ -391,9 +687,9 @@ cat >expect <<EOF
# output
# untracked
EOF
-test_expect_success 'status submodule summary (--amend)' '
+test_expect_success 'commit --dry-run submodule summary (--amend)' '
git config status.submodulesummary 10 &&
- git status --amend >output &&
+ git commit --dry-run --amend >output &&
test_cmp expect output
'
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 e5b210bc96..57f6d2bae7 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -243,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 &&
@@ -263,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 &&
@@ -303,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 &&
@@ -314,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 &&
@@ -432,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" &&
diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh
index 01e5415e94..2746169514 100755
--- a/t/t7602-merge-octopus-many.sh
+++ b/t/t7602-merge-octopus-many.sh
@@ -49,4 +49,55 @@ test_expect_success 'merge c1 with c2, c3, c4, ... c29' '
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/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh
index de977c5e2f..269cfdf267 100755
--- a/t/t7604-merge-custom-message.sh
+++ b/t/t7604-merge-custom-message.sh
@@ -22,15 +22,12 @@ test_expect_success 'setup' '
git tag c2
'
-cat >expected <<\EOF
-custom message
-Merge commit 'c2'
-EOF
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 &&
+ git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
test_cmp expected actual
'
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/t7700-repack.sh b/t/t7700-repack.sh
index 6b29bff782..f4aa054750 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -69,7 +69,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is
done
'
-test_expect_failure 'packed obs in alt ODB are repacked when local repo has packs' '
+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 &&
@@ -149,5 +149,17 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar
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/t7800-difftool.sh b/t/t7800-difftool.sh
new file mode 100755
index 0000000000..19c72f55bf
--- /dev/null
+++ b/t/t7800-difftool.sh
@@ -0,0 +1,267 @@
+#!/bin/sh
+#
+# Copyright (c) 2009, 2010 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
+
+LF='
+'
+
+remove_config_vars()
+{
+ # Unset all config variables used by git-difftool
+ git config --unset diff.tool
+ git config --unset diff.guitool
+ git config --unset difftool.test-tool.cmd
+ git config --unset difftool.prompt
+ git config --unset merge.tool
+ git config --unset mergetool.test-tool.cmd
+ git config --unset mergetool.prompt
+ return 0
+}
+
+restore_test_defaults()
+{
+ # Restores the test defaults used by several tests
+ remove_config_vars
+ unset GIT_DIFF_TOOL
+ unset GIT_DIFFTOOL_PROMPT
+ unset GIT_DIFFTOOL_NO_PROMPT
+ git config diff.tool test-tool &&
+ git config difftool.test-tool.cmd 'cat $LOCAL'
+ git config difftool.bogus-tool.cmd false
+}
+
+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=bad-tool branch)
+ test "$?" = 1 &&
+ test "$diff" = ""
+'
+
+test_expect_success 'difftool honors --gui' '
+ git config merge.tool bogus-tool &&
+ git config diff.tool bogus-tool &&
+ git config diff.guitool test-tool &&
+
+ diff=$(git difftool --no-prompt --gui branch) &&
+ test "$diff" = "branch" &&
+
+ restore_test_defaults
+'
+
+# 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_DIFF_TOOL=test-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 we don't have to pass --no-prompt when mergetool.prompt is false
+test_expect_success 'difftool merge.prompt = false' '
+ git config --unset difftool.prompt
+ git config mergetool.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 &&
+
+ restore_test_defaults
+'
+
+test_expect_success 'difftool --extcmd=cat' '
+ diff=$(git difftool --no-prompt --extcmd=cat branch) &&
+ test "$diff" = branch"$LF"master
+'
+
+test_expect_success 'difftool --extcmd cat' '
+ diff=$(git difftool --no-prompt --extcmd cat branch) &&
+ test "$diff" = branch"$LF"master
+'
+
+test_expect_success 'difftool -x cat' '
+ diff=$(git difftool --no-prompt -x cat branch) &&
+ test "$diff" = branch"$LF"master
+'
+
+test_expect_success 'difftool --extcmd echo arg1' '
+ diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"echo\ \$1\" branch)
+ test "$diff" = file
+'
+
+test_expect_success 'difftool --extcmd cat arg1' '
+ diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$1\" branch)
+ test "$diff" = master
+'
+
+test_expect_success 'difftool --extcmd cat arg2' '
+ diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$2\" branch)
+ test "$diff" = branch
+'
+
+test_done
diff --git a/t/t8003-blame.sh b/t/t8003-blame.sh
index 966bb0a61a..230143cf31 100755
--- a/t/t8003-blame.sh
+++ b/t/t8003-blame.sh
@@ -11,7 +11,15 @@ test_expect_success setup '
echo B B B B B >two &&
echo C C C C C >tres &&
echo ABC >mouse &&
- git add one two tres mouse &&
+ for i in 1 2 3 4 5 6 7 8 9
+ do
+ echo $i
+ done >nine_lines &&
+ for i in 1 2 3 4 5 6 7 8 9 a
+ do
+ echo $i
+ done >ten_lines &&
+ git add one two tres mouse nine_lines ten_lines &&
test_tick &&
GIT_AUTHOR_NAME=Initial git commit -m Initial &&
@@ -129,4 +137,52 @@ 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_expect_success 'blame -L with invalid start' '
+ test_must_fail git blame -L5 tres 2>errors &&
+ grep "has only 2 lines" errors
+'
+
+test_expect_success 'blame -L with invalid end' '
+ test_must_fail git blame -L1,5 tres 2>errors &&
+ grep "has only 2 lines" errors
+'
+
+test_expect_success 'indent of line numbers, nine lines' '
+ git blame nine_lines >actual &&
+ test $(grep -c " " actual) = 0
+'
+
+test_expect_success 'indent of line numbers, ten lines' '
+ git blame ten_lines >actual &&
+ test $(grep -c " " actual) = 9
+'
+
test_done
diff --git a/t/t8005-blame-i18n.sh b/t/t8005-blame-i18n.sh
index 4470a92bb2..cb390559f9 100755
--- a/t/t8005-blame-i18n.sh
+++ b/t/t8005-blame-i18n.sh
@@ -4,7 +4,7 @@ test_description='git blame encoding conversion'
. ./test-lib.sh
. "$TEST_DIRECTORY"/t8005/utf8.txt
-. "$TEST_DIRECTORY"/t8005/cp1251.txt
+. "$TEST_DIRECTORY"/t8005/euc-japan.txt
. "$TEST_DIRECTORY"/t8005/sjis.txt
test_expect_success 'setup the repository' '
@@ -13,14 +13,14 @@ test_expect_success 'setup the repository' '
git add file &&
git commit --author "$UTF8_NAME <utf8@localhost>" -m "$UTF8_MSG" &&
- echo "CP1251 LINE" >> file &&
+ echo "EUC-JAPAN LINE" >> file &&
git add file &&
- git config i18n.commitencoding cp1251 &&
- git commit --author "$CP1251_NAME <cp1251@localhost>" -m "$CP1251_MSG" &&
+ 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 shift-jis &&
+ git config i18n.commitencoding SJIS &&
git commit --author "$SJIS_NAME <sjis@localhost>" -m "$SJIS_MSG"
'
@@ -36,24 +36,24 @@ EOF
test_expect_success \
'blame respects i18n.commitencoding' '
git blame --incremental file | \
- grep "^\(author\|summary\) " > actual &&
+ egrep "^(author|summary) " > actual &&
test_cmp actual expected
'
cat >expected <<EOF
-author $CP1251_NAME
-summary $CP1251_MSG
-author $CP1251_NAME
-summary $CP1251_MSG
-author $CP1251_NAME
-summary $CP1251_MSG
+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 cp1251 &&
+ git config i18n.logoutputencoding eucJP &&
git blame --incremental file | \
- grep "^\(author\|summary\) " > actual &&
+ egrep "^(author|summary) " > actual &&
test_cmp actual expected
'
@@ -67,17 +67,17 @@ summary $UTF8_MSG
EOF
test_expect_success \
- 'blame respects --encoding=utf-8' '
- git blame --incremental --encoding=utf-8 file | \
- grep "^\(author\|summary\) " > actual &&
+ '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 $CP1251_NAME
-summary $CP1251_MSG
+author $EUC_JAPAN_NAME
+summary $EUC_JAPAN_MSG
author $UTF8_NAME
summary $UTF8_MSG
EOF
@@ -85,7 +85,7 @@ EOF
test_expect_success \
'blame respects --encoding=none' '
git blame --incremental --encoding=none file | \
- grep "^\(author\|summary\) " > actual &&
+ egrep "^(author|summary) " > actual &&
test_cmp actual expected
'
diff --git a/t/t8005/cp1251.txt b/t/t8005/cp1251.txt
deleted file mode 100644
index ce41e98b81..0000000000
--- a/t/t8005/cp1251.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-CP1251_NAME="Èâàí Ïåòðîâè÷ Ñèäîðîâ"
-CP1251_MSG="Òåñòîâîå ñîîáùåíèå"
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
index 2ccfbad207..bbdefeaced 100644
--- a/t/t8005/sjis.txt
+++ b/t/t8005/sjis.txt
@@ -1,2 +1,2 @@
-SJIS_NAME="„I„r„p„~ „P„u„„„‚„€„r„y„‰ „R„y„t„€„‚„€„r"
-SJIS_MSG="„S„u„ƒ„„„€„r„€„u „ƒ„€„€„q„‹„u„~„y„u"
+SJIS_NAME="ŽR“c ‘¾˜Y"
+SJIS_MSG="ƒuƒŒ[ƒ€‚̃eƒXƒg‚Å‚·B"
diff --git a/t/t8005/utf8.txt b/t/t8005/utf8.txt
index f46cfc56d8..4d00dbea76 100644
--- a/t/t8005/utf8.txt
+++ b/t/t8005/utf8.txt
@@ -1,2 +1,2 @@
-UTF8_NAME="Иван Петрович Сидоров"
-UTF8_MSG="ТеÑтовое Ñообщение"
+UTF8_NAME="山田 太郎"
+UTF8_MSG="ブレームã®ãƒ†ã‚¹ãƒˆã§ã™ã€‚"
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index d7634187aa..c09f375288 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -3,6 +3,11 @@
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' \
@@ -35,6 +40,47 @@ test_expect_success 'Extract patches' '
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 --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
'
@@ -47,7 +93,41 @@ cat >expected <<\EOF
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
@@ -57,10 +137,18 @@ cat >expected-show-all-headers <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@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>, One <one@example.com>, two@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
@@ -89,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
@@ -116,7 +236,7 @@ test_expect_success 'Author From: in message body' '
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
$patches &&
- sed "1,/^$/d" < msgtxt1 > msgbody1
+ sed "1,/^\$/d" < msgtxt1 > msgbody1
grep "From: A <author@example.com>" msgbody1
'
@@ -127,7 +247,7 @@ test_expect_success 'Author From: not in message body' '
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
$patches &&
- sed "1,/^$/d" < msgtxt1 > msgbody1
+ sed "1,/^\$/d" < msgtxt1 > msgbody1
! grep "From: A <author@example.com>" msgbody1
'
@@ -175,15 +295,13 @@ test_set_editor "$(pwd)/fake-editor"
test_expect_success '--compose works' '
clean_fake_sendmail &&
- echo y | \
- 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
+ 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' '
@@ -202,10 +320,17 @@ cat >expected-suppress-sob <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@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
+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
@@ -217,7 +342,7 @@ EOF
test_suppression () {
git send-email \
--dry-run \
- --suppress-cc=$1 \
+ --suppress-cc=$1 ${2+"--suppress-cc=$2"} \
--from="Example <from@example.com>" \
--to=to@example.com \
--smtp-server relay.example.com \
@@ -225,8 +350,8 @@ test_suppression () {
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 &&
- test_cmp expected-suppress-$1 actual-suppress-$1
+ >actual-suppress-$1${2+"-$2"} &&
+ test_cmp expected-suppress-$1${2+"-$2"} actual-suppress-$1${2+"-$2"}
}
test_expect_success 'sendemail.cc set' '
@@ -242,10 +367,15 @@ cat >expected-suppress-sob <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@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
+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
@@ -259,6 +389,41 @@ test_expect_success 'sendemail.cc unset' '
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:
@@ -284,13 +449,21 @@ cat >expected-suppress-body <<\EOF
(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>,<author@example.com>,<one@example.com>,<two@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: 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
@@ -303,6 +476,35 @@ 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>'
@@ -311,10 +513,15 @@ cat >expected-suppress-sob <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@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
+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
@@ -324,6 +531,7 @@ Result: OK
EOF
test_expect_success '--suppress-cc=sob' '
+ git config --unset sendemail.cccmd
test_suppression sob
'
@@ -336,10 +544,17 @@ cat >expected-suppress-bodycc <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<committer@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>
+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
@@ -359,10 +574,13 @@ cat >expected-suppress-cc <<\EOF
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
-RCPT TO:<to@example.com>,<author@example.com>,<committer@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>
+Cc: A <author@example.com>,
+ C O Mitter <committer@example.com>
Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
@@ -375,15 +593,117 @@ test_expect_success '--suppress-cc=cc' '
test_suppression cc
'
+test_confirm () {
+ echo y | \
+ GIT_SEND_EMAIL_NOTTY=1 \
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ $@ $patches > stdout &&
+ grep "Send this email" stdout
+}
+
+test_expect_success '--confirm=always' '
+ test_confirm --confirm=always --suppress-cc=all
+'
+
+test_expect_success '--confirm=auto' '
+ test_confirm --confirm=auto
+'
+
+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 &&
- echo y | \
GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
- GIT_SEND_EMAIL_NOTTY=1 \
git send-email \
--compose --subject foo \
--from="Example <nobody@example.com>" \
@@ -391,7 +711,7 @@ test_expect_success '--compose adds MIME for utf8 body' '
--smtp-server="$(pwd)/fake.sendmail" \
$patches &&
grep "^utf8 body" msgtxt1 &&
- grep "^Content-Type: text/plain; charset=utf-8" msgtxt1
+ grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
'
test_expect_success '--compose respects user mime type' '
@@ -405,9 +725,7 @@ test_expect_success '--compose respects user mime type' '
echo " echo utf8 body: àéìöú) >\"\$1\""
) >fake-editor-utf8-mime &&
chmod +x fake-editor-utf8-mime &&
- echo y | \
GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
- GIT_SEND_EMAIL_NOTTY=1 \
git send-email \
--compose --subject foo \
--from="Example <nobody@example.com>" \
@@ -416,14 +734,12 @@ test_expect_success '--compose respects user mime type' '
$patches &&
grep "^utf8 body" msgtxt1 &&
grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 &&
- ! grep "^Content-Type: text/plain; charset=utf-8" msgtxt1
+ ! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
'
test_expect_success '--compose adds MIME for utf8 subject' '
clean_fake_sendmail &&
- echo y | \
GIT_EDITOR="\"$(pwd)/fake-editor\"" \
- GIT_SEND_EMAIL_NOTTY=1 \
git send-email \
--compose --subject utf8-sübjëct \
--from="Example <nobody@example.com>" \
@@ -431,7 +747,7 @@ test_expect_success '--compose adds MIME for utf8 subject' '
--smtp-server="$(pwd)/fake.sendmail" \
$patches &&
grep "^fake edit" msgtxt1 &&
- grep "^Subject: =?utf-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
+ grep "^Subject: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
'
test_expect_success 'detects ambiguous reference/file conflict' '
@@ -445,7 +761,7 @@ test_expect_success 'detects ambiguous reference/file conflict' '
test_expect_success 'feed two files' '
rm -fr outdir &&
git format-patch -2 -o outdir &&
- GIT_SEND_EMAIL_NOTTY=1 git send-email \
+ git send-email \
--dry-run \
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
@@ -461,9 +777,79 @@ test_expect_success 'in-reply-to but no threading' '
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--in-reply-to="<in-reply-id@example.com>" \
- --no-thread \
+ --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 bb921af56a..570e0359e4 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -6,19 +6,19 @@
test_description='git svn basic tests'
GIT_SVN_LC_ALL=${LC_ALL:-$LANG}
+. ./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
-
-say 'define NO_SVN_TESTS to skip git svn tests'
-
test_expect_success \
'initialize git svn' '
mkdir import &&
@@ -31,7 +31,7 @@ test_expect_success \
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"'
@@ -51,7 +51,7 @@ test_expect_success "$name" '
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
${remotes_git_svn}..mybranch &&
- svn up "$SVN_TREE" &&
+ svn_cmd up "$SVN_TREE" &&
test -d "$SVN_TREE"/dir && test ! -d "$SVN_TREE"/dir/a'
@@ -118,7 +118,7 @@ test_expect_success "$name" '
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
${remotes_git_svn}..mybranch5 &&
- svn up "$SVN_TREE" &&
+ svn_cmd up "$SVN_TREE" &&
test ! -x "$SVN_TREE"/exec.sh'
@@ -129,7 +129,7 @@ test_expect_success "$name" '
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
${remotes_git_svn}..mybranch5 &&
- svn up "$SVN_TREE" &&
+ svn_cmd up "$SVN_TREE" &&
test -x "$SVN_TREE"/exec.sh'
@@ -141,7 +141,7 @@ test_expect_success "$name" '
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
${remotes_git_svn}..mybranch5 &&
- svn up "$SVN_TREE" &&
+ 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'
@@ -153,7 +153,7 @@ test_expect_success "$name" '
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
${remotes_git_svn}..mybranch5 &&
- svn up "$SVN_TREE" &&
+ svn_cmd up "$SVN_TREE" &&
test -x "$SVN_TREE"/bar/zzz &&
test -L "$SVN_TREE"/exec-2.sh'
@@ -166,25 +166,20 @@ test_expect_success "$name" '
git commit -m "$name" &&
git svn set-tree --find-copies-harder --rmdir \
${remotes_git_svn}..mybranch5 &&
- svn up "$SVN_TREE" &&
+ 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'
-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
- say "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)"
-fi
+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
@@ -197,7 +192,7 @@ test_expect_success "$name" \
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
@@ -236,6 +231,25 @@ test_expect_success \
"^: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 checkout -b my-bar refs/remotes/bar &&
diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh
index 1e31d6ea72..929499e996 100755
--- a/t/t9101-git-svn-props.sh
+++ b/t/t9101-git-svn-props.sh
@@ -48,7 +48,7 @@ EOF
printf "\r\n" > 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
@@ -57,13 +57,13 @@ 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"'
@@ -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'
+ 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
@@ -106,11 +106,11 @@ cd test_wc
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}'
@@ -140,10 +140,12 @@ 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 &&
cmp show-ignore.expect show-ignore.got
@@ -171,6 +173,7 @@ test_expect_success 'test create-ignore' "
"
cat >prop.expect <<\EOF
+
no-such-file*
EOF
diff --git a/t/t9102-git-svn-deep-rmdir.sh b/t/t9102-git-svn-deep-rmdir.sh
index e223218015..028fb19e09 100755
--- a/t/t9102-git-svn-deep-rmdir.sh
+++ b/t/t9102-git-svn-deep-rmdir.sh
@@ -9,7 +9,7 @@ test_expect_success 'initialize repo' '
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 ..
'
@@ -23,7 +23,7 @@ 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
+ svn_cmd ls -R "$svnrepo" | grep ^deeply/nested/directory/number/1
'
diff --git a/t/t9103-git-svn-tracked-directory-removed.sh b/t/t9103-git-svn-tracked-directory-removed.sh
index 963dd95e4a..3413164cb1 100755
--- a/t/t9103-git-svn-tracked-directory-removed.sh
+++ b/t/t9103-git-svn-tracked-directory-removed.sh
@@ -10,15 +10,15 @@ 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' '
diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh
index ab9fa32220..bbfd7f4793 100755
--- a/t/t9104-git-svn-follow-parent.sh
+++ b/t/t9104-git-svn-follow-parent.sh
@@ -11,18 +11,18 @@ test_expect_success 'initialize repo' '
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 ..
'
@@ -51,7 +51,7 @@ test_expect_success 'init and fetch from one svn-remote' '
'
test_expect_success 'follow deleted parent' '
- (svn cp -m "resurrecting trunk as junk" \
+ (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) &&
@@ -97,8 +97,8 @@ test_expect_success 'follow higher-level parent' '
'
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 &&
+ 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 &&
@@ -120,7 +120,7 @@ test_expect_success 'follow-parent avoids deleting relevant info' '
cd import &&
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 &&
@@ -138,7 +138,7 @@ test_expect_success 'follow-parent avoids deleting relevant info' '
'
test_expect_success "track initial change if it was only made to parent" '
- svn cp -m "wheee!" "$svnrepo"/r9270/trunk "$svnrepo"/r9270/drunk &&
+ 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 &&
@@ -152,31 +152,31 @@ test_expect_success "track initial change if it was only made to parent" '
test_expect_success "follow-parent is atomic" '
(
cd wc &&
- svn up &&
- svn mkdir stunk &&
+ svn_cmd up &&
+ svn_cmd mkdir stunk &&
echo "trunk stunk" > stunk/readme &&
- svn add stunk/readme &&
- svn ci -m "trunk stunk" &&
+ svn_cmd add stunk/readme &&
+ svn_cmd ci -m "trunk stunk" &&
echo "stunk like junk" >> stunk/readme &&
- svn ci -m "really stunk" &&
+ svn_cmd ci -m "really stunk" &&
echo "stink stank stunk" >> stunk/readme &&
- svn ci -m "even the grinch agrees"
+ svn_cmd ci -m "even the grinch agrees"
) &&
- svn copy -m "stunk flunked" "$svnrepo"/stunk "$svnrepo"/flunk &&
+ svn_cmd copy -m "stunk flunked" "$svnrepo"/stunk "$svnrepo"/flunk &&
{ svn cp -m "early stunk flunked too" \
"$svnrepo"/stunk@17 "$svnrepo"/flunked ||
- svn cp -m "early stunk flunked too" \
+ 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/flunk@18 &&
- rev_map=$(cd "$GIT_DIR"/svn/stunk && ls .rev_map*) &&
- dd if="$GIT_DIR"/svn/stunk/$rev_map \
- of="$GIT_DIR"/svn/flunk@18/$rev_map bs=24 count=1 &&
- rm -rf "$GIT_DIR"/svn/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 &&
@@ -192,7 +192,7 @@ test_expect_success "follow-parent is atomic" '
'
test_expect_success "track multi-parent paths" '
- svn cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob &&
+ 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
diff --git a/t/t9105-git-svn-commit-diff.sh b/t/t9105-git-svn-commit-diff.sh
index ba99abb6d9..dd48e9cba8 100755
--- a/t/t9105-git-svn-commit-diff.sh
+++ b/t/t9105-git-svn-commit-diff.sh
@@ -8,7 +8,7 @@ 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 &&
@@ -27,16 +27,16 @@ prev=`git rev-parse --verify HEAD^1`
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 &&
+ 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 &&
+ 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 cat "$svnrepo"/subdir/readme > readme.2 &&
+ svn_cmd cat "$svnrepo"/subdir/readme > readme.2 &&
cmp readme readme.2
'
diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh
index 6eb0fd85c8..12f21b700e 100755
--- a/t/t9106-git-svn-commit-diff-clobber.sh
+++ b/t/t9106-git-svn-commit-diff-clobber.sh
@@ -8,18 +8,18 @@ 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 &&
+ 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
'
@@ -43,11 +43,11 @@ 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 &&
+ 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 &&
@@ -67,11 +67,11 @@ test_expect_success 'dcommit does the svn equivalent of an index merge' "
"
test_expect_success 'commit another change from svn side' '
- svn co "$svnrepo" t.svn &&
+ 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
'
diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh
index acad16a6f0..901b8e09fb 100755
--- a/t/t9107-git-svn-migrate.sh
+++ b/t/t9107-git-svn-migrate.sh
@@ -12,13 +12,11 @@ test_expect_success 'setup old-looking metadata' '
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 &&
+ 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}
@@ -56,7 +54,15 @@ test_expect_success 'initialize a multi-repository repo' '
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:
@@ -79,36 +85,36 @@ test_expect_success 'migrate --minimize on old inited layout' '
rm -rf "$GIT_DIR"/svn &&
for i in `cat fetch.out`; do
path=`expr $i : "\([^:]*\):.*$"`
- ref=`expr $i : "[^:]*:refs/remotes/\(.*\)$"`
+ 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\."`" &&
+ 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 "^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 -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/trunk/.rev_db.* 2>/dev/null)" &&
- test ! -e "$GIT_DIR"/svn/trunk/.rev_db &&
+ 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"
'
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index d8582b1aa5..d732d31302 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -14,30 +14,30 @@ 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 &&
+ 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 &&
+ 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 &&
poke branches/start/src/a/readme &&
- svn commit -m "hi" &&
- svn up &&
- svn cp branches/start tags/end &&
+ 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 &&
poke tags/end/src/a/readme &&
- svn commit -m "the end" &&
+ 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"
+ svn_cmd commit -m "nothing to see here"
) &&
git config --add svn-remote.svn.url "$svnrepo" &&
git config --add svn-remote.svn.fetch \
@@ -72,7 +72,7 @@ test_expect_success 'test left-hand-side only globbing' '
cd tmp &&
echo "try try" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
- svn commit -m "try to try"
+ svn_cmd commit -m "try to try"
) &&
git svn fetch two &&
test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
@@ -102,7 +102,7 @@ test_expect_success 'test disallow multi-globs' '
cd tmp &&
echo "try try" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
- svn commit -m "try to try"
+ svn_cmd commit -m "try to try"
) &&
test_must_fail git svn fetch three 2> stderr.three &&
test_cmp expect.three stderr.three
diff --git a/t/t9108-git-svn-multi-glob.sh b/t/t9109-git-svn-multi-glob.sh
index 8f79c3f251..c318f9f946 100755
--- a/t/t9108-git-svn-multi-glob.sh
+++ b/t/t9109-git-svn-multi-glob.sh
@@ -14,30 +14,30 @@ 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 &&
+ svn_cmd import -m "initial" trunk "$svnrepo"/trunk &&
+ svn_cmd co "$svnrepo" tmp &&
(
cd tmp &&
mkdir branches branches/v1 tags &&
- svn add branches tags &&
- svn cp trunk branches/v1/start &&
- svn commit -m "start a new branch" &&
- svn up &&
+ 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 commit -m "hi" &&
- svn up &&
- svn cp branches/v1/start tags/end &&
+ 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 commit -m "the end" &&
+ 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"
+ svn_cmd commit -m "nothing to see here"
) &&
git config --add svn-remote.svn.url "$svnrepo" &&
git config --add svn-remote.svn.fetch \
@@ -72,7 +72,7 @@ test_expect_success 'test left-hand-side only globbing' '
cd tmp &&
echo "try try" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
- svn commit -m "try to try"
+ svn_cmd commit -m "try to try"
) &&
git svn fetch two &&
test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
@@ -97,25 +97,25 @@ test_expect_success 'test another branch' '
(
cd tmp &&
mkdir branches/v2 &&
- svn add branches/v2 &&
- svn cp trunk branches/v2/start &&
- svn commit -m "Another versioned branch" &&
- svn up &&
+ 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 commit -m "Changed 2 in v2/start" &&
- svn up &&
- svn cp branches/v2/start tags/next &&
+ 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 commit -m "adding more" &&
+ svn_cmd commit -m "adding more" &&
echo "byebye" >> tags/next/src/b/readme &&
poke tags/next/src/b/readme &&
- svn commit -m "adios"
+ 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 &&
@@ -151,7 +151,7 @@ test_expect_success 'test disallow multiple globs' '
cd tmp &&
echo "try try" >> tags/end/src/b/readme &&
poke tags/end/src/b/readme &&
- svn commit -m "try to try"
+ svn_cmd commit -m "try to try"
) &&
test_must_fail git svn fetch three 2> stderr.three &&
test_cmp expect.three stderr.three
diff --git a/t/t9113-git-svn-dcommit-new-file.sh b/t/t9113-git-svn-dcommit-new-file.sh
index e9b6128b3f..e8479cec7a 100755
--- a/t/t9113-git-svn-dcommit-new-file.sh
+++ b/t/t9113-git-svn-dcommit-new-file.sh
@@ -15,7 +15,7 @@ test_description='git svn dcommit new files over svn:// test'
require_svnserve
test_expect_success 'start tracking an empty repo' '
- svn mkdir -m "empty dir" "$svnrepo"/empty-dir &&
+ 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 &&
diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh
index 17b2855c4f..84f7c9b4bb 100755
--- a/t/t9114-git-svn-dcommit-merge.sh
+++ b/t/t9114-git-svn-dcommit-merge.sh
@@ -35,12 +35,12 @@ EOF
}
test_expect_success 'setup svn repository' '
- svn co "$svnrepo" mysvnwork &&
+ 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 ..
'
diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh
index 9be7aefaee..767799e7a7 100755
--- a/t/t9115-git-svn-dcommit-funky-renames.sh
+++ b/t/t9115-git-svn-dcommit-funky-renames.sh
@@ -19,7 +19,7 @@ test_expect_success 'init and fetch repository' '
'
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
diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh
index fd6d1d2046..0374a7476b 100755
--- a/t/t9116-git-svn-log.sh
+++ b/t/t9116-git-svn-log.sh
@@ -14,7 +14,7 @@ test_expect_success 'setup repository and import' '
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 &&
diff --git a/t/t9117-git-svn-init-clone.sh b/t/t9117-git-svn-init-clone.sh
index dde46cd92f..b7ef9e2589 100755
--- a/t/t9117-git-svn-init-clone.sh
+++ b/t/t9117-git-svn-init-clone.sh
@@ -16,7 +16,7 @@ cd tmp
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
'
diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
index 7a7c128687..ac52bff0ef 100755
--- a/t/t9118-git-svn-funky-branch-names.sh
+++ b/t/t9118-git-svn-funky-branch-names.sh
@@ -13,13 +13,13 @@ 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" \
+ svn_cmd cp -m "fun" "$svnrepo/pr ject/trunk" \
"$svnrepo/pr ject/branches/fun plugin" &&
- svn cp -m "more fun!" "$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 cp -m "scary" "$svnrepo/pr ject/branches/fun plugin" \
+ svn_cmd cp -m "scary" "$svnrepo/pr ject/branches/fun plugin" \
"$svnrepo/pr ject/branches/$scary_uri" &&
start_httpd
'
diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh
index 27dd7c273a..95741cbbac 100755
--- a/t/t9119-git-svn-info.sh
+++ b/t/t9119-git-svn-info.sh
@@ -7,7 +7,7 @@ test_description='git svn info'
. ./lib-git-svn.sh
# Tested with: svn, version 1.4.4 (r25188)
-v=`svn --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p'`
+v=`svn_cmd --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p'`
case $v in
1.[45].*)
;;
@@ -31,7 +31,7 @@ ptouch() {
my $atime = $mtime;
utime $atime, $mtime, $git_file;
}
- ' "`svn info $2 | grep '^Text Last Updated:'`" "$1"
+ ' "`svn_cmd info $2 | grep '^Text Last Updated:'`" "$1"
}
quoted_svnrepo="$(echo $svnrepo | sed 's/ /%20/')"
@@ -45,14 +45,14 @@ 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 co "$svnrepo" svnwc &&
+ svn_cmd co "$svnrepo" svnwc &&
cd svnwc &&
echo foo > foo &&
- svn add foo &&
- svn commit -m "change outside directory" &&
- svn update &&
+ svn_cmd add foo &&
+ svn_cmd commit -m "change outside directory" &&
+ svn_cmd update &&
cd .. &&
mkdir gitwc &&
cd gitwc &&
@@ -143,7 +143,7 @@ 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 &&
@@ -160,7 +160,7 @@ 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 &&
@@ -184,7 +184,7 @@ 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) \
@@ -207,7 +207,7 @@ 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) \
@@ -233,7 +233,7 @@ 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/' \
@@ -254,7 +254,7 @@ 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/' \
@@ -275,7 +275,7 @@ 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/' \
@@ -297,7 +297,7 @@ 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/' \
diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh
index ef2c0523cd..9d9ebd533c 100755
--- a/t/t9120-git-svn-clone-with-percent-escapes.sh
+++ b/t/t9120-git-svn-clone-with-percent-escapes.sh
@@ -9,22 +9,69 @@ test_description='git svn clone with percent escapes'
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/t9122-git-svn-author.sh b/t/t9122-git-svn-author.sh
index 1b1cf47281..30013b7bb9 100755
--- a/t/t9122-git-svn-author.sh
+++ b/t/t9122-git-svn-author.sh
@@ -4,12 +4,12 @@ test_description='git svn authorship'
. ./lib-git-svn.sh
test_expect_success 'setup svn repository' '
- svn checkout "$svnrepo" work.svn &&
+ svn_cmd checkout "$svnrepo" work.svn &&
(
cd work.svn &&
echo >file
- svn add file
- svn commit -m "first commit" file
+ svn_cmd add file
+ svn_cmd commit -m "first commit" file
)
'
@@ -74,10 +74,10 @@ test_expect_success 'interact with it via git svn' '
# Make sure there are no svn commit messages with excess blank lines
(
cd work.svn &&
- svn up &&
+ svn_cmd up &&
- test $(svn log -r2:2 | wc -l) = 5 &&
- test $(svn log -r4:4 | wc -l) = 7
+ test $(svn_cmd log -r2:2 | wc -l) = 5 &&
+ test $(svn_cmd log -r4:4 | wc -l) = 7
)
'
diff --git a/t/t9123-git-svn-rebuild-with-rewriteroot.sh b/t/t9123-git-svn-rebuild-with-rewriteroot.sh
index cf0415274c..045521615c 100755
--- a/t/t9123-git-svn-rebuild-with-rewriteroot.sh
+++ b/t/t9123-git-svn-rebuild-with-rewriteroot.sh
@@ -10,7 +10,7 @@ test_description='git svn respects rewriteRoot during rebuild'
mkdir import
cd import
touch foo
- 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
diff --git a/t/t9124-git-svn-dcommit-auto-props.sh b/t/t9124-git-svn-dcommit-auto-props.sh
index 263dbf5fc2..d6b076f6b7 100755
--- a/t/t9124-git-svn-dcommit-auto-props.sh
+++ b/t/t9124-git-svn-dcommit-auto-props.sh
@@ -21,7 +21,7 @@ test_expect_success 'initialize git svn' '
(
cd import &&
echo foo >foo &&
- svn import -m "import for git svn" . "$svnrepo"
+ svn_cmd import -m "import for git svn" . "$svnrepo"
) &&
rm -rf import &&
git svn init "$svnrepo"
@@ -61,23 +61,23 @@ test_expect_success 'check resulting svn repository' '
(
mkdir work &&
cd work &&
- svn co "$svnrepo" &&
+ svn_cmd co "$svnrepo" &&
cd svnrepo &&
# Check properties from first commit.
- test "x$(svn propget svn:executable exec1.sh)" = "x*" &&
- test "x$(svn propget svn:mime-type exec1.sh)" = \
+ 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 propget svn:mime-type hello.txt)" = "xtext/plain" &&
- test "x$(svn propget svn:eol-style hello.txt)" = "xnative" &&
- test "x$(svn propget svn:mime-type bar)" = "x" &&
+ 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 propget svn:executable exec2.sh)" = "x*" &&
- test "x$(svn propget svn:mime-type exec2.sh)" = "x" &&
- test "x$(svn propget svn:mime-type world.txt)" = "x" &&
- test "x$(svn propget svn:eol-style world.txt)" = "x" &&
- test "x$(svn propget svn:mime-type zot)" = "x"
+ 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"
)
'
@@ -89,12 +89,12 @@ test_expect_success 'check renamed file' '
git svn dcommit --config-dir=user &&
(
cd work/svnrepo &&
- svn up &&
+ svn_cmd up &&
test ! -e foo &&
test -e foo.sh &&
- test "x$(svn propget svn:mime-type foo.sh)" = \
+ test "x$(svn_cmd propget svn:mime-type foo.sh)" = \
"xapplication/x-shellscript" &&
- test "x$(svn propget svn:eol-style foo.sh)" = "xLF"
+ test "x$(svn_cmd propget svn:eol-style foo.sh)" = "xLF"
)
'
diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh
index 475c751c1c..c19418614f 100755
--- a/t/t9125-git-svn-multi-glob-branch-names.sh
+++ b/t/t9125-git-svn-multi-glob-branch-names.sh
@@ -8,11 +8,11 @@ test_expect_success 'setup svnrepo' '
mkdir project project/trunk project/branches \
project/branches/v14.1 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 &&
- svn cp -m "fun" "$svnrepo/project/trunk" \
+ svn_cmd cp -m "fun" "$svnrepo/project/trunk" \
"$svnrepo/project/branches/v14.1/beta" &&
- svn cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
+ svn_cmd cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
"$svnrepo/project/branches/v14.1/gold"
'
diff --git a/t/t9127-git-svn-partial-rebuild.sh b/t/t9127-git-svn-partial-rebuild.sh
index 87696a92dc..4aab8ecc14 100755
--- a/t/t9127-git-svn-partial-rebuild.sh
+++ b/t/t9127-git-svn-partial-rebuild.sh
@@ -14,21 +14,21 @@ test_expect_success 'initialize svnrepo' '
cd trunk &&
echo foo > foo &&
cd .. &&
- svn import -m "import for git-svn" . "$svnrepo" >/dev/null &&
- svn copy "$svnrepo"/trunk "$svnrepo"/branches/a \
+ 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 co "$svnrepo"/trunk trunk &&
+ svn_cmd co "$svnrepo"/trunk trunk &&
cd trunk &&
echo bar >> foo &&
- svn ci -m "updated trunk" &&
+ svn_cmd ci -m "updated trunk" &&
cd .. &&
- svn co "$svnrepo"/branches/a a &&
+ svn_cmd co "$svnrepo"/branches/a a &&
cd a &&
echo baz >> a &&
- svn add a &&
- svn ci -m "updated a" &&
+ svn_cmd add a &&
+ svn_cmd ci -m "updated a" &&
cd .. &&
git svn init --stdlayout "$svnrepo"
)
diff --git a/t/t9128-git-svn-cmd-branch.sh b/t/t9128-git-svn-cmd-branch.sh
index 252daa7e1a..807e494a3a 100755
--- a/t/t9128-git-svn-cmd-branch.sh
+++ b/t/t9128-git-svn-cmd-branch.sh
@@ -14,13 +14,13 @@ test_expect_success 'initialize svnrepo' '
cd trunk &&
echo foo > foo &&
cd .. &&
- 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 &&
- svn co "$svnrepo"/trunk trunk &&
+ svn_cmd co "$svnrepo"/trunk trunk &&
cd trunk &&
echo bar >> foo &&
- svn ci -m "updated trunk" &&
+ svn_cmd ci -m "updated trunk" &&
cd .. &&
rm -rf trunk
)
@@ -57,14 +57,14 @@ test_expect_success 'git svn branch tests' '
'
test_expect_success 'branch uses correct svn-remote' '
- (svn co "$svnrepo" svn &&
+ (svn_cmd co "$svnrepo" svn &&
cd svn &&
mkdir mirror &&
- svn add mirror &&
- svn copy trunk mirror/ &&
- svn copy tags mirror/ &&
- svn copy branches mirror/ &&
- svn ci -m "made 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 &&
diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh
index 9c7b1ad18b..b9224bdb20 100755
--- a/t/t9129-git-svn-i18n-commitencoding.sh
+++ b/t/t9129-git-svn-i18n-commitencoding.sh
@@ -29,16 +29,16 @@ compare_svn_head_with () {
test_cmp current "$1"
}
-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" '
mkdir $H &&
- svn import -m "$H test" $H "$svnrepo"/$H &&
+ svn_cmd import -m "$H test" $H "$svnrepo"/$H &&
git svn clone "$svnrepo"/$H $H
'
done
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
do
test_expect_success "$H commit on git side" '
(
@@ -55,7 +55,7 @@ do
'
done
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
do
test_expect_success "$H dcommit to svn" '
(
@@ -70,24 +70,26 @@ do
done
if locale -a |grep -q en_US.utf8; then
- test_expect_success 'ISO-8859-1 should match UTF-8 in svn' '
+ 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 ISO-8859-1 &&
+ 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 '$H should match UTF-8 in svn' '
+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
-else
- say "UTF-8 locale not available, test skipped"
-fi
+ '
+done
test_done
diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh
index b8fb277562..134411e0a5 100755
--- a/t/t9130-git-svn-authors-file.sh
+++ b/t/t9130-git-svn-authors-file.sh
@@ -15,7 +15,7 @@ EOF
test_expect_success 'setup svnrepo' '
for i in aa bb cc dd
do
- svn mkdir -m $i --username $i "$svnrepo"/$i
+ svn_cmd mkdir -m $i --username $i "$svnrepo"/$i
done
'
@@ -52,13 +52,13 @@ test_expect_success 'continues to import once authors have been added' '
'
test_expect_success 'authors-file against globs' '
- svn mkdir -m globs --username aa \
+ 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 mkdir -m "$branch" --username $i "$svnrepo/$branch"
+ svn_cmd mkdir -m "$branch" --username $i "$svnrepo/$branch"
done
'
@@ -91,4 +91,27 @@ test_expect_success 'fetch continues after authors-file is fixed' '
)
'
+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
index 8f35e294aa..9a24a65b64 100755
--- a/t/t9131-git-svn-empty-symlink.sh
+++ b/t/t9131-git-svn-empty-symlink.sh
@@ -88,7 +88,7 @@ test_expect_success 'enable broken symlink workaround' \
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 '"bar" becomes a symlink' 'test -L x/bar'
+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'
diff --git a/t/t9132-git-svn-broken-symlink.sh b/t/t9132-git-svn-broken-symlink.sh
index b8de59e493..6c4c90b036 100755
--- a/t/t9132-git-svn-broken-symlink.sh
+++ b/t/t9132-git-svn-broken-symlink.sh
@@ -85,7 +85,7 @@ EOF
test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" x'
-test_expect_success '"bar" is a symlink that points to "asdf"' '
+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`")
'
@@ -94,7 +94,7 @@ test_expect_success 'get "bar" => symlink fix from svn' '
(cd x && git svn rebase)
'
-test_expect_success '"bar" remains a proper symlink' '
+test_expect_success SYMLINKS '"bar" remains a proper symlink' '
test -L x/bar &&
(cd x && test xdoink = x"`git cat-file blob HEAD:bar`")
'
diff --git a/t/t9133-git-svn-nested-git-repo.sh b/t/t9133-git-svn-nested-git-repo.sh
index 893f57ef73..f3c30e63b7 100755
--- a/t/t9133-git-svn-nested-git-repo.sh
+++ b/t/t9133-git-svn-nested-git-repo.sh
@@ -7,19 +7,19 @@ test_description='git svn property tests'
. ./lib-git-svn.sh
test_expect_success 'setup repo with a git repo inside it' '
- svn co "$svnrepo" s &&
+ svn_cmd co "$svnrepo" s &&
(
cd s &&
git init &&
test -f .git/HEAD &&
> .git/a &&
echo a > a &&
- svn add .git a &&
- svn commit -m "create a nested git repo" &&
- svn up &&
+ svn_cmd add .git a &&
+ svn_cmd commit -m "create a nested git repo" &&
+ svn_cmd up &&
echo hi >> .git/a &&
- svn commit -m "modify .git/a" &&
- svn up
+ svn_cmd commit -m "modify .git/a" &&
+ svn_cmd up
)
'
@@ -33,9 +33,9 @@ test_expect_success 'SVN-side change outside of .git' '
(
cd s &&
echo b >> a &&
- svn commit -m "SVN-side change outside of .git" &&
- svn up &&
- svn log -v | fgrep "SVN-side change outside of .git"
+ svn_cmd commit -m "SVN-side change outside of .git" &&
+ svn_cmd up &&
+ svn_cmd log -v | fgrep "SVN-side change outside of .git"
)
'
@@ -56,10 +56,10 @@ test_expect_success 'SVN-side change inside of .git' '
git add a &&
git commit -m "add a inside an SVN repo" &&
git log &&
- svn add --force .git &&
- svn commit -m "SVN-side change inside of .git" &&
- svn up &&
- svn log -v | fgrep "SVN-side change inside of .git"
+ 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"
)
'
@@ -80,9 +80,9 @@ test_expect_success 'SVN-side change in and out of .git' '
echo c >> a &&
git add a &&
git commit -m "add a inside an SVN repo" &&
- svn commit -m "SVN-side change in and out of .git" &&
- svn up &&
- svn log -v | fgrep "SVN-side change in and out of .git"
+ 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"
)
'
diff --git a/t/t9134-git-svn-ignore-paths.sh b/t/t9134-git-svn-ignore-paths.sh
index c4b5b8bcf7..09ff10cd9b 100755
--- a/t/t9134-git-svn-ignore-paths.sh
+++ b/t/t9134-git-svn-ignore-paths.sh
@@ -8,19 +8,19 @@ test_description='git svn property tests'
. ./lib-git-svn.sh
test_expect_success 'setup test repository' '
- svn co "$svnrepo" s &&
+ 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 add qqq &&
- svn add www &&
- svn commit -m "create some files" &&
- svn up &&
+ 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 commit -m "modify www/test_www.txt" &&
- svn up
+ svn_cmd commit -m "modify www/test_www.txt" &&
+ svn_cmd up
)
'
@@ -31,19 +31,46 @@ test_expect_success 'clone an SVN repository with ignored www directory' '
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 commit -m "SVN-side change outside of www" &&
- svn up &&
- svn log -v | fgrep "SVN-side change outside of www"
+ 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' '
+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 &&
@@ -56,15 +83,26 @@ test_expect_success 'SVN-side change inside of ignored www' '
(
cd s &&
echo zaq >> www/test_www.txt
- svn commit -m "SVN-side change inside of www/test_www.txt" &&
- svn up &&
- svn log -v | fgrep "SVN-side change inside of 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' '
+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 &&
@@ -78,15 +116,26 @@ 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 commit -m "SVN-side change in and out of ignored www" &&
- svn up &&
- svn log -v | fgrep "SVN-side change in and out of ignored www"
+ 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' '
+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 &&
diff --git a/t/t9135-git-svn-moved-branch-empty-file.sh b/t/t9135-git-svn-moved-branch-empty-file.sh
index 03705fa4ce..5280e5f1e4 100755
--- a/t/t9135-git-svn-moved-branch-empty-file.sh
+++ b/t/t9135-git-svn-moved-branch-empty-file.sh
@@ -10,7 +10,12 @@ test_expect_success 'load svn dumpfile' '
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 && test -f b1 && ! test -s b1)
+ (
+ cd x &&
+ git reset --hard branch-c &&
+ test -f b1 &&
+ ! test -s b1
+ )
'
test_done
diff --git a/t/t9106-git-svn-dcommit-clobber-series.sh b/t/t9137-git-svn-dcommit-clobber-series.sh
index fd185011b7..636ca0abb9 100755
--- a/t/t9106-git-svn-dcommit-clobber-series.sh
+++ b/t/t9137-git-svn-dcommit-clobber-series.sh
@@ -8,7 +8,7 @@ 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" &&
+ svn_cmd import -m "initial" . "$svnrepo" &&
cd .. &&
git svn init "$svnrepo" &&
git svn fetch &&
@@ -18,14 +18,14 @@ test_expect_success 'initialize repo' '
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 &&
+ svn_cmd co "$svnrepo" tmp &&
cd tmp &&
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" &&
+ svn_cmd commit -m "58 => 5588, 61 => 6611" &&
cd ..
'
@@ -46,7 +46,7 @@ test_expect_success 'change file but in unrelated area' "
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 &&
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..3569c62096
--- /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_failure '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..3d73f140f8
--- /dev/null
+++ b/t/t9151/make-svnmerge-dump
@@ -0,0 +1,222 @@
+#!/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
+mkdir tags
+svn add trunk branches tags
+i=$(commit $i "Setup trunk, branches, and tags")
+
+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 ..
+
+say "Adding subdirectory to LEFT"
+svn update
+cd branches/left
+mkdir subdir
+echo "Yeehaw" > subdir/cowboy
+svn add subdir
+i=$(commit $i "add subdirectory to left branch")
+cd ../../
+
+say "Merging LEFT to TRUNK"
+svn update
+cd trunk
+svn merge ../branches/left --accept postpone
+i=$(commit $i "merge left to trunk")
+cd ..
+
+say "Make PARTIAL branch"
+svn update
+i=$(commit $i "make partial branch")
+svn cp trunk/subdir branches/partial
+
+say "Make a commit to PARTIAL"
+svn update
+cd branches/partial
+echo "racecar" > palindromes
+svn add palindromes
+i=$(commit $i "partial update")
+cd ../../
+
+say "Merge PARTIAL to TRUNK"
+svn update
+cd trunk/subdir
+svn merge ../../branches/partial --accept postpone
+i=$(commit $i "merge partial to trunk")
+cd ../../
+
+say "Tagging trunk"
+svn update
+i=$(commit $i "tagging v1.0")
+svn cp trunk tags/v1.0
+
+say "Branching BUGFIX from v1.0"
+svn update
+i=$(commit $i "make bugfix branch from tag")
+svn cp tags/v1.0 branches/bugfix
+
+say "Make a commit to BUGFIX"
+svn update
+cd branches/bugfix/
+echo "kayak" >> subdir/palindromes
+i=$(commit $i "commit to bugfix")
+cd ../../
+
+say "Merge BUGFIX to TRUNK"
+svn update
+cd trunk
+svn merge ../branches/bugfix/ --accept postpone
+i=$(commit $i "Merge BUGFIX to TRUNK")
+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..ebf386ebd5
--- /dev/null
+++ b/t/t9151/svn-mergeinfo.dump
@@ -0,0 +1,1922 @@
+SVN-fs-dump-format-version: 2
+
+UUID: d6191530-2693-4a8e-98e7-b194d4c3edd8
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2010-01-19T04:14:02.832406Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 134
+Content-length: 134
+
+K 7
+svn:log
+V 36
+(r1) Setup trunk, branches, and tags
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:03.055172Z
+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
+
+
+Revision-number: 2
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 13
+(r2) ancestor
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:04.064506Z
+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: 119
+Content-length: 119
+
+K 7
+svn:log
+V 21
+(r3) make left branch
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:06.040389Z
+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: 120
+Content-length: 120
+
+K 7
+svn:log
+V 22
+(r4) make right branch
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:08.040905Z
+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: 116
+Content-length: 116
+
+K 7
+svn:log
+V 18
+(r5) left update 1
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:09.049169Z
+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: 117
+Content-length: 117
+
+K 7
+svn:log
+V 19
+(r6) right update 1
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:10.049350Z
+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: 116
+Content-length: 116
+
+K 7
+svn:log
+V 18
+(r7) left update 2
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:11.049209Z
+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: 116
+Content-length: 116
+
+K 7
+svn:log
+V 18
+(r8) left update 3
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:12.049234Z
+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: 123
+Content-length: 123
+
+K 7
+svn:log
+V 25
+(r9) make left sub-branch
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:14.040894Z
+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: 128
+Content-length: 128
+
+K 7
+svn:log
+V 30
+(r10) left sub-branch update 1
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:15.049935Z
+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: 125
+Content-length: 125
+
+K 7
+svn:log
+V 27
+(r11) Merge left to trunk 1
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:18.056594Z
+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: 117
+Content-length: 117
+
+K 7
+svn:log
+V 19
+(r12) left update 4
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:19.049620Z
+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: 118
+Content-length: 118
+
+K 7
+svn:log
+V 20
+(r13) right update 2
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:20.049659Z
+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: 140
+Content-length: 140
+
+K 7
+svn:log
+V 42
+(r14) Cherry-pick right 2 commits to trunk
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:23.041991Z
+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: 126
+Content-length: 126
+
+K 7
+svn:log
+V 28
+(r15) Merge right to trunk 1
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:26.054456Z
+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: 118
+Content-length: 118
+
+K 7
+svn:log
+V 20
+(r16) right update 3
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:27.049955Z
+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: 118
+Content-length: 118
+
+K 7
+svn:log
+V 20
+(r17) trunk update 1
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:28.049615Z
+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: 134
+Content-length: 134
+
+K 7
+svn:log
+V 36
+(r18) Merge right to left sub-branch
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:31.061460Z
+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: 128
+Content-length: 128
+
+K 7
+svn:log
+V 30
+(r19) left sub-branch update 2
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:32.049244Z
+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: 117
+Content-length: 117
+
+K 7
+svn:log
+V 19
+(r20) left update 5
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:33.049332Z
+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: 146
+Content-length: 146
+
+K 7
+svn:log
+V 48
+(r21) Cherry-pick left sub-branch commit to left
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:36.041839Z
+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: 133
+Content-length: 133
+
+K 7
+svn:log
+V 35
+(r22) Merge left sub-branch to left
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:39.045014Z
+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: 125
+Content-length: 125
+
+K 7
+svn:log
+V 27
+(r23) Merge left to trunk 2
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:42.052798Z
+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: 130
+Content-length: 130
+
+K 7
+svn:log
+V 32
+(r24) non-merge right to trunk 2
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:44.038434Z
+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
+
+
+Revision-number: 25
+Prop-content-length: 135
+Content-length: 135
+
+K 7
+svn:log
+V 37
+(r25) add subdirectory to left branch
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:46.052649Z
+PROPS-END
+
+Node-path: branches/left/subdir
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: branches/left/subdir/cowboy
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 7
+Text-content-md5: f1d6530278ad409e68cc675476ad995f
+Text-content-sha1: 732d9e3e5c391ffd767a98b45ddcc848de778cea
+Content-length: 17
+
+PROPS-END
+Yeehaw
+
+
+Revision-number: 26
+Prop-content-length: 123
+Content-length: 123
+
+K 7
+svn:log
+V 25
+(r26) merge left to trunk
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:49.040783Z
+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-25
+/branches/left-sub:4-19
+/branches/right:2-22
+PROPS-END
+
+
+Node-path: trunk/subdir
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 25
+Node-copyfrom-path: branches/left/subdir
+
+
+Revision-number: 27
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 20
+(r28) partial update
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:53.049037Z
+PROPS-END
+
+Node-path: branches/partial
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 26
+Node-copyfrom-path: trunk/subdir
+
+
+Node-path: branches/partial/palindromes
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 8
+Text-content-md5: 5d1c2024fb5efc4eef812856df1b080c
+Text-content-sha1: 5f8509ddd14c91a52864dd1447344e706f9bbc69
+Content-length: 18
+
+PROPS-END
+racecar
+
+
+Revision-number: 28
+Prop-content-length: 126
+Content-length: 126
+
+K 7
+svn:log
+V 28
+(r29) merge partial to trunk
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:14:56.041526Z
+PROPS-END
+
+Node-path: trunk/subdir
+Node-kind: dir
+Node-action: change
+Prop-content-length: 142
+Content-length: 142
+
+K 13
+svn:mergeinfo
+V 106
+/branches/left/subdir:2-25
+/branches/left-sub/subdir:4-19
+/branches/partial:27
+/branches/right/subdir:2-22
+PROPS-END
+
+
+Node-path: trunk/subdir/palindromes
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 27
+Node-copyfrom-path: branches/partial/palindromes
+Text-copy-source-md5: 5d1c2024fb5efc4eef812856df1b080c
+Text-copy-source-sha1: 5f8509ddd14c91a52864dd1447344e706f9bbc69
+
+
+Revision-number: 29
+Prop-content-length: 131
+Content-length: 131
+
+K 7
+svn:log
+V 33
+(r31) make bugfix branch from tag
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:15:00.039761Z
+PROPS-END
+
+Node-path: tags/v1.0
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 28
+Node-copyfrom-path: trunk
+
+
+Revision-number: 30
+Prop-content-length: 120
+Content-length: 120
+
+K 7
+svn:log
+V 22
+(r32) commit to bugfix
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:15:03.043218Z
+PROPS-END
+
+Node-path: branches/bugfix
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 29
+Node-copyfrom-path: tags/v1.0
+
+
+Node-path: branches/bugfix/subdir/palindromes
+Node-kind: file
+Node-action: change
+Text-content-length: 14
+Text-content-md5: 3b12d98578a3f4320ba97e66da54fe5f
+Text-content-sha1: 672931c9e8ac2c408209efab2f015638b6d64042
+Content-length: 14
+
+racecar
+kayak
+
+
+Revision-number: 31
+Prop-content-length: 125
+Content-length: 125
+
+K 7
+svn:log
+V 27
+(r33) Merge BUGFIX to TRUNK
+K 10
+svn:author
+V 3
+adm
+K 8
+svn:date
+V 27
+2010-01-19T04:15:06.043723Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: change
+Prop-content-length: 133
+Content-length: 133
+
+K 13
+svn:mergeinfo
+V 98
+/branches/bugfix:30
+/branches/left:2-25
+/branches/left-sub:4-19
+/branches/right:2-22
+/tags/v1.0:29
+PROPS-END
+
+
+Node-path: trunk/subdir
+Node-kind: dir
+Node-action: change
+Prop-content-length: 190
+Content-length: 190
+
+K 13
+svn:mergeinfo
+V 154
+/branches/bugfix/subdir:30
+/branches/left/subdir:2-25
+/branches/left-sub/subdir:4-19
+/branches/partial:27
+/branches/right/subdir:2-22
+/tags/v1.0/subdir:29
+PROPS-END
+
+
+Node-path: trunk/subdir/palindromes
+Node-kind: file
+Node-action: change
+Text-content-length: 14
+Text-content-md5: 3b12d98578a3f4320ba97e66da54fe5f
+Text-content-sha1: 672931c9e8ac2c408209efab2f015638b6d64042
+Content-length: 14
+
+racecar
+kayak
+
+
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/t9153-git-svn-rewrite-uuid.sh b/t/t9153-git-svn-rewrite-uuid.sh
new file mode 100755
index 0000000000..88a2cfa233
--- /dev/null
+++ b/t/t9153-git-svn-rewrite-uuid.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Jay Soffian
+#
+
+test_description='git svn --rewrite-uuid test'
+
+. ./lib-git-svn.sh
+
+uuid=6cc8ada4-5932-4b4a-8242-3534ed8a3232
+
+test_expect_success 'load svn repo' "
+ svnadmin load -q '$rawsvnrepo' < '$TEST_DIRECTORY/t9153/svn.dump' &&
+ git svn init --minimize-url --rewrite-uuid='$uuid' '$svnrepo' &&
+ git svn fetch
+ "
+
+test_expect_success 'verify uuid' "
+ git cat-file commit refs/remotes/git-svn~0 | \
+ grep '^${git_svn_id}: .*@2 $uuid$' &&
+ git cat-file commit refs/remotes/git-svn~1 | \
+ grep '^${git_svn_id}: .*@1 $uuid$'
+ "
+
+test_done
diff --git a/t/t9153/svn.dump b/t/t9153/svn.dump
new file mode 100644
index 0000000000..0ddfe7025d
--- /dev/null
+++ b/t/t9153/svn.dump
@@ -0,0 +1,75 @@
+SVN-fs-dump-format-version: 2
+
+UUID: b4885626-c94f-4a6c-b179-00c030fc68e8
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2010-01-23T06:41:03.908576Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 109
+Content-length: 109
+
+K 7
+svn:log
+V 11
+initial foo
+K 10
+svn:author
+V 3
+jay
+K 8
+svn:date
+V 27
+2010-01-23T06:41:48.353776Z
+PROPS-END
+
+Node-path: foo
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 4
+Text-content-md5: d3b07384d113edec49eaa6238ad5ff00
+Text-content-sha1: f1d2d2f924e986ac86fdf7b36c94bcdf32beec15
+Content-length: 14
+
+PROPS-END
+foo
+
+
+Revision-number: 2
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 12
+now with bar
+K 10
+svn:author
+V 3
+jay
+K 8
+svn:date
+V 27
+2010-01-23T06:42:14.214640Z
+PROPS-END
+
+Node-path: foo
+Node-kind: file
+Node-action: change
+Text-content-length: 8
+Text-content-md5: f47c75614087a8dd938ba4acff252494
+Text-content-sha1: 4e48e2c9a3d2ca8a708cb0cc545700544efb5021
+Content-length: 8
+
+foo
+bar
+
+
diff --git a/t/t9154-git-svn-fancy-glob.sh b/t/t9154-git-svn-fancy-glob.sh
new file mode 100755
index 0000000000..a6a56a6cb9
--- /dev/null
+++ b/t/t9154-git-svn-fancy-glob.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Jay Soffian
+#
+
+test_description='git svn fancy glob test'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'load svn repo' "
+ svnadmin load -q '$rawsvnrepo' < '$TEST_DIRECTORY/t9154/svn.dump' &&
+ git svn init --minimize-url -T trunk '$svnrepo' &&
+ git svn fetch
+ "
+
+test_expect_success 'add red branch' "
+ git config svn-remote.svn.branches 'branches/{red}:refs/remotes/*' &&
+ git svn fetch &&
+ git rev-parse refs/remotes/red &&
+ test_must_fail git rev-parse refs/remotes/green &&
+ test_must_fail git rev-parse refs/remotes/blue
+ "
+
+test_expect_success 'add green branch' "
+ GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
+ git config svn-remote.svn.branches 'branches/{red,green}:refs/remotes/*' &&
+ git svn fetch &&
+ git rev-parse refs/remotes/red &&
+ git rev-parse refs/remotes/green &&
+ test_must_fail git rev-parse refs/remotes/blue
+ "
+
+test_expect_success 'add all branches' "
+ GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
+ git config svn-remote.svn.branches 'branches/*:refs/remotes/*' &&
+ git svn fetch &&
+ git rev-parse refs/remotes/red &&
+ git rev-parse refs/remotes/green &&
+ git rev-parse refs/remotes/blue
+ "
+
+test_done
diff --git a/t/t9154/svn.dump b/t/t9154/svn.dump
new file mode 100644
index 0000000000..3dfabb67db
--- /dev/null
+++ b/t/t9154/svn.dump
@@ -0,0 +1,222 @@
+SVN-fs-dump-format-version: 2
+
+UUID: a18093a0-5f0b-44e0-8d88-8911ac7078db
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2010-01-23T07:40:25.660053Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 104
+Content-length: 104
+
+K 7
+svn:log
+V 7
+initial
+K 10
+svn:author
+V 3
+jay
+K 8
+svn:date
+V 27
+2010-01-23T07:41:33.636365Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk/foo
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 4
+Text-content-md5: d3b07384d113edec49eaa6238ad5ff00
+Text-content-sha1: f1d2d2f924e986ac86fdf7b36c94bcdf32beec15
+Content-length: 14
+
+PROPS-END
+foo
+
+
+Revision-number: 2
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 12
+add branches
+K 10
+svn:author
+V 3
+jay
+K 8
+svn:date
+V 27
+2010-01-23T07:42:37.290694Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: branches/blue
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Node-path: branches/green
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Node-path: branches/red
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 3
+Prop-content-length: 108
+Content-length: 108
+
+K 7
+svn:log
+V 10
+red change
+K 10
+svn:author
+V 3
+jay
+K 8
+svn:date
+V 27
+2010-01-23T07:43:02.208918Z
+PROPS-END
+
+Node-path: branches/red/foo
+Node-kind: file
+Node-action: change
+Text-content-length: 8
+Text-content-md5: 64c3c8cf7d0233ab7627623a68888bd1
+Text-content-sha1: 95a0492027876adfd3891ec71ee37b79ee44d640
+Content-length: 8
+
+foo
+red
+
+
+Revision-number: 4
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 12
+green change
+K 10
+svn:author
+V 3
+jay
+K 8
+svn:date
+V 27
+2010-01-23T07:43:15.746586Z
+PROPS-END
+
+Node-path: branches/green/foo
+Node-kind: file
+Node-action: change
+Text-content-length: 10
+Text-content-md5: 0209b6450891abc033d5eaaa9d3a8023
+Text-content-sha1: 87fc3bef9faeec48c0cd61dfc9851db377fdccf7
+Content-length: 10
+
+foo
+green
+
+
+Revision-number: 5
+Prop-content-length: 109
+Content-length: 109
+
+K 7
+svn:log
+V 11
+blue change
+K 10
+svn:author
+V 3
+jay
+K 8
+svn:date
+V 27
+2010-01-23T07:43:29.364811Z
+PROPS-END
+
+Node-path: branches/blue/foo
+Node-kind: file
+Node-action: change
+Text-content-length: 9
+Text-content-md5: 9fbe4c13d0bae86386ae5209b2e6b275
+Text-content-sha1: cc4575083459a16f9aaef796c4a2456d64691ba0
+Content-length: 9
+
+foo
+blue
+
+
+Revision-number: 6
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 12
+trunk change
+K 10
+svn:author
+V 3
+jay
+K 8
+svn:date
+V 27
+2010-01-23T07:44:01.313130Z
+PROPS-END
+
+Node-path: trunk/foo
+Node-kind: file
+Node-action: change
+Text-content-length: 10
+Text-content-md5: 1c4db977d7a57c3bae582aab87948516
+Text-content-sha1: 469c08df449e702cf2a1fe746244a9ef3f837fad
+Content-length: 10
+
+foo
+trunk
+
+
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index 245a7c3662..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
@@ -225,11 +229,12 @@ test_expect_success \
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 &&
@@ -243,8 +248,6 @@ test_expect_success \
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,7 +316,7 @@ 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"
'
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 821be7ce8d..131f032988 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1088,4 +1088,498 @@ INPUT_END
test_expect_success 'P: fail on blob mark in gitlink' '
test_must_fail git fast-import <input'
+###
+### series Q (notes)
+###
+
+note1_data="The first note for the first commit"
+note2_data="The first note for the second commit"
+note3_data="The first note for the third commit"
+note1b_data="The second note for the first commit"
+note1c_data="The third note for the first commit"
+note2b_data="The second note for the second 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
+
+commit refs/notes/foobar
+mark :10
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes (:10)
+COMMIT
+
+N inline :3
+data <<EOF
+$note1b_data
+EOF
+
+commit refs/notes/foobar2
+mark :11
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes (:11)
+COMMIT
+
+N inline :3
+data <<EOF
+$note1c_data
+EOF
+
+commit refs/notes/foobar
+mark :12
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes (:12)
+COMMIT
+
+deleteall
+N inline :5
+data <<EOF
+$note2b_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 first notes commit' \
+ 'git cat-file commit refs/notes/foobar~2 | 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 first notes tree' \
+ 'git cat-file -p refs/notes/foobar~2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual'
+
+echo "$note1_data" >expect
+test_expect_success \
+ 'Q: verify first note for first commit' \
+ 'git cat-file blob refs/notes/foobar~2:$commit1 >actual && test_cmp expect actual'
+
+echo "$note2_data" >expect
+test_expect_success \
+ 'Q: verify first note for second commit' \
+ 'git cat-file blob refs/notes/foobar~2:$commit2 >actual && test_cmp expect actual'
+
+echo "$note3_data" >expect
+test_expect_success \
+ 'Q: verify first note for third commit' \
+ 'git cat-file blob refs/notes/foobar~2:$commit3 >actual && test_cmp expect actual'
+
+cat >expect <<EOF
+parent `git rev-parse --verify refs/notes/foobar~2`
+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+notes (:10)
+EOF
+test_expect_success \
+ 'Q: verify second 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 second notes tree' \
+ 'git cat-file -p refs/notes/foobar^^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual'
+
+echo "$note1b_data" >expect
+test_expect_success \
+ 'Q: verify second 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 first 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 first note for third commit' \
+ 'git cat-file blob refs/notes/foobar^:$commit3 >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 (:11)
+EOF
+test_expect_success \
+ 'Q: verify third notes commit' \
+ 'git cat-file commit refs/notes/foobar2 | sed 1d >actual &&
+ test_cmp expect actual'
+
+cat >expect.unsorted <<EOF
+100644 blob $commit1
+EOF
+cat expect.unsorted | sort >expect
+test_expect_success \
+ 'Q: verify third notes tree' \
+ 'git cat-file -p refs/notes/foobar2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual'
+
+echo "$note1c_data" >expect
+test_expect_success \
+ 'Q: verify third note for first commit' \
+ 'git cat-file blob refs/notes/foobar2:$commit1 >actual && test_cmp expect actual'
+
+cat >expect <<EOF
+parent `git rev-parse --verify refs/notes/foobar^`
+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+notes (:12)
+EOF
+test_expect_success \
+ 'Q: verify fourth notes commit' \
+ 'git cat-file commit refs/notes/foobar | sed 1d >actual &&
+ test_cmp expect actual'
+
+cat >expect.unsorted <<EOF
+100644 blob $commit2
+EOF
+cat expect.unsorted | sort >expect
+test_expect_success \
+ 'Q: verify fourth notes tree' \
+ 'git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual'
+
+echo "$note2b_data" >expect
+test_expect_success \
+ 'Q: verify second note for second commit' \
+ 'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual'
+
+###
+### series R (feature and option)
+###
+
+cat >input <<EOF
+feature no-such-feature-exists
+EOF
+
+test_expect_success 'R: abort on unsupported feature' '
+ test_must_fail git fast-import <input
+'
+
+cat >input <<EOF
+feature date-format=now
+EOF
+
+test_expect_success 'R: supported feature is accepted' '
+ git fast-import <input
+'
+
+cat >input << EOF
+blob
+data 3
+hi
+feature date-format=now
+EOF
+
+test_expect_success 'R: abort on receiving feature after data command' '
+ test_must_fail git fast-import <input
+'
+
+cat >input << EOF
+feature import-marks=git.marks
+feature import-marks=git2.marks
+EOF
+
+test_expect_success 'R: only one import-marks feature allowed per stream' '
+ test_must_fail git fast-import <input
+'
+
+cat >input << EOF
+feature export-marks=git.marks
+blob
+mark :1
+data 3
+hi
+
+EOF
+
+test_expect_success \
+ 'R: export-marks feature results in a marks file being created' \
+ 'cat input | git fast-import &&
+ grep :1 git.marks'
+
+test_expect_success \
+ 'R: export-marks options can be overriden by commandline options' \
+ 'cat input | git fast-import --export-marks=other.marks &&
+ grep :1 other.marks'
+
+cat >input << EOF
+feature import-marks=marks.out
+feature export-marks=marks.new
+EOF
+
+test_expect_success \
+ 'R: import to output marks works without any content' \
+ 'cat input | git fast-import &&
+ test_cmp marks.out marks.new'
+
+cat >input <<EOF
+feature import-marks=nonexistant.marks
+feature export-marks=marks.new
+EOF
+
+test_expect_success \
+ 'R: import marks prefers commandline marks file over the stream' \
+ 'cat input | git fast-import --import-marks=marks.out &&
+ test_cmp marks.out marks.new'
+
+
+cat >input <<EOF
+feature import-marks=nonexistant.marks
+feature export-marks=combined.marks
+EOF
+
+test_expect_success 'R: multiple --import-marks= should be honoured' '
+ head -n2 marks.out > one.marks &&
+ tail -n +3 marks.out > two.marks &&
+ git fast-import --import-marks=one.marks --import-marks=two.marks <input &&
+ test_cmp marks.out combined.marks
+'
+
+cat >input <<EOF
+feature relative-marks
+feature import-marks=relative.in
+feature export-marks=relative.out
+EOF
+
+test_expect_success 'R: feature relative-marks should be honoured' '
+ mkdir -p .git/info/fast-import/ &&
+ cp marks.new .git/info/fast-import/relative.in &&
+ git fast-import <input &&
+ test_cmp marks.new .git/info/fast-import/relative.out
+'
+
+cat >input <<EOF
+feature relative-marks
+feature import-marks=relative.in
+feature no-relative-marks
+feature export-marks=non-relative.out
+EOF
+
+test_expect_success 'R: feature no-relative-marks should be honoured' '
+ git fast-import <input &&
+ test_cmp marks.new non-relative.out
+'
+
+cat >input << EOF
+option git quiet
+blob
+data 3
+hi
+
+EOF
+
+touch empty
+
+test_expect_success 'R: quiet option results in no stats being output' '
+ cat input | git fast-import 2> output &&
+ test_cmp empty output
+'
+
+cat >input <<EOF
+option git non-existing-option
+EOF
+
+test_expect_success 'R: die on unknown option' '
+ test_must_fail git fast-import <input
+'
+
+test_expect_success 'R: unknown commandline options are rejected' '\
+ test_must_fail git fast-import --non-existing-option < /dev/null
+'
+
+cat >input <<EOF
+option non-existing-vcs non-existing-option
+EOF
+
+test_expect_success 'R: ignore non-git options' '
+ git fast-import <input
+'
+
+##
+## R: very large blobs
+##
+blobsize=$((2*1024*1024 + 53))
+test-genrandom bar $blobsize >expect
+cat >input <<INPUT_END
+commit refs/heads/big-file
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+R - big file
+COMMIT
+
+M 644 inline big1
+data $blobsize
+INPUT_END
+cat expect >>input
+cat >>input <<INPUT_END
+M 644 inline big2
+data $blobsize
+INPUT_END
+cat expect >>input
+echo >>input
+
+test_expect_success \
+ 'R: blob bigger than threshold' \
+ 'test_create_repo R &&
+ git --git-dir=R/.git fast-import --big-file-threshold=1 <input'
+test_expect_success \
+ 'R: verify created pack' \
+ ': >verify &&
+ for p in R/.git/objects/pack/*.pack;
+ do
+ git verify-pack -v $p >>verify || exit;
+ done'
+test_expect_success \
+ 'R: verify written objects' \
+ 'git --git-dir=R/.git cat-file blob big-file:big1 >actual &&
+ test_cmp expect actual &&
+ a=$(git --git-dir=R/.git rev-parse big-file:big1) &&
+ b=$(git --git-dir=R/.git rev-parse big-file:big2) &&
+ test $a = $b'
+test_expect_success \
+ 'R: blob appears only once' \
+ 'n=$(grep $a verify | wc -l) &&
+ test 1 = $n'
+
test_done
diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh
new file mode 100755
index 0000000000..a5c99d8507
--- /dev/null
+++ b/t/t9301-fast-import-notes.sh
@@ -0,0 +1,623 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Johan Herland
+#
+
+test_description='test git fast-import of notes objects'
+. ./test-lib.sh
+
+
+test_tick
+cat >input <<INPUT_END
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+first commit
+COMMIT
+
+M 644 inline foo
+data <<EOF
+file foo in first commit
+EOF
+
+M 755 inline bar
+data <<EOF
+file bar in first commit
+EOF
+
+M 644 inline baz/xyzzy
+data <<EOF
+file baz/xyzzy in first commit
+EOF
+
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+second commit
+COMMIT
+
+M 644 inline foo
+data <<EOF
+file foo in second commit
+EOF
+
+M 755 inline baz/xyzzy
+data <<EOF
+file baz/xyzzy in second commit
+EOF
+
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+third commit
+COMMIT
+
+M 644 inline foo
+data <<EOF
+file foo in third commit
+EOF
+
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+fourth commit
+COMMIT
+
+M 755 inline bar
+data <<EOF
+file bar in fourth commit
+EOF
+
+INPUT_END
+
+test_expect_success 'set up master branch' '
+
+ git fast-import <input &&
+ git whatchanged master
+'
+
+commit4=$(git rev-parse refs/heads/master)
+commit3=$(git rev-parse "$commit4^")
+commit2=$(git rev-parse "$commit4~2")
+commit1=$(git rev-parse "$commit4~3")
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+first notes commit
+COMMIT
+
+M 644 inline $commit1
+data <<EOF
+first note for first commit
+EOF
+
+M 755 inline $commit2
+data <<EOF
+first note for second commit
+EOF
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ third commit
+ second commit
+ first note for second commit
+ first commit
+ first note for first commit
+EXPECT_END
+
+test_expect_success 'add notes with simple M command' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+second notes commit
+COMMIT
+
+from refs/notes/test^0
+N inline $commit3
+data <<EOF
+first note for third commit
+EOF
+
+N inline $commit4
+data <<EOF
+first note for fourth commit
+EOF
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ first note for fourth commit
+ third commit
+ first note for third commit
+ second commit
+ first note for second commit
+ first commit
+ first note for first commit
+EXPECT_END
+
+test_expect_success 'add notes with simple N command' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+third notes commit
+COMMIT
+
+from refs/notes/test^0
+N inline $commit1
+data <<EOF
+second note for first commit
+EOF
+
+N inline $commit2
+data <<EOF
+second note for second commit
+EOF
+
+N inline $commit3
+data <<EOF
+second note for third commit
+EOF
+
+N inline $commit4
+data <<EOF
+second note for fourth commit
+EOF
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ second note for fourth commit
+ third commit
+ second note for third commit
+ second commit
+ second note for second commit
+ first commit
+ second note for first commit
+EXPECT_END
+
+test_expect_success 'update existing notes with N command' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+fourth notes commit
+COMMIT
+
+from refs/notes/test^0
+M 644 inline $(echo "$commit3" | sed "s|^..|&/|")
+data <<EOF
+prefix of note for third commit
+EOF
+
+M 644 inline $(echo "$commit4" | sed "s|^..|&/|")
+data <<EOF
+prefix of note for fourth commit
+EOF
+
+M 644 inline $(echo "$commit4" | sed "s|^\(..\)\(..\)|\1/\2/|")
+data <<EOF
+pre-prefix of note for fourth commit
+EOF
+
+N inline $commit1
+data <<EOF
+third note for first commit
+EOF
+
+N inline $commit2
+data <<EOF
+third note for second commit
+EOF
+
+N inline $commit3
+data <<EOF
+third note for third commit
+EOF
+
+N inline $commit4
+data <<EOF
+third note for fourth commit
+EOF
+
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ pre-prefix of note for fourth commit
+ prefix of note for fourth commit
+ third note for fourth commit
+ third commit
+ prefix of note for third commit
+ third note for third commit
+ second commit
+ third note for second commit
+ first commit
+ third note for first commit
+EXPECT_END
+
+test_expect_success 'add concatentation notes with M command' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+fifth notes commit
+COMMIT
+
+from refs/notes/test^0
+deleteall
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ third commit
+ second commit
+ first commit
+EXPECT_END
+
+test_expect_success 'verify that deleteall also removes notes' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+sixth notes commit
+COMMIT
+
+from refs/notes/test^0
+M 644 inline $commit1
+data <<EOF
+third note for first commit
+EOF
+
+M 644 inline $commit3
+data <<EOF
+third note for third commit
+EOF
+
+N inline $commit1
+data <<EOF
+fourth note for first commit
+EOF
+
+N inline $commit3
+data <<EOF
+fourth note for third commit
+EOF
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ third commit
+ fourth note for third commit
+ second commit
+ first commit
+ fourth note for first commit
+EXPECT_END
+
+test_expect_success 'verify that later N commands override earlier M commands' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+# Write fast-import commands to create the given number of commits
+fast_import_commits () {
+ my_ref=$1
+ my_num_commits=$2
+ my_append_to_file=$3
+ my_i=0
+ while test $my_i -lt $my_num_commits
+ do
+ my_i=$(($my_i + 1))
+ test_tick
+ cat >>"$my_append_to_file" <<INPUT_END
+commit $my_ref
+mark :$my_i
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+commit #$my_i
+COMMIT
+
+M 644 inline file
+data <<EOF
+file contents in commit #$my_i
+EOF
+
+INPUT_END
+ done
+}
+
+# Write fast-import commands to create the given number of notes annotating
+# the commits created by fast_import_commits()
+fast_import_notes () {
+ my_notes_ref=$1
+ my_num_commits=$2
+ my_append_to_file=$3
+ my_note_append=$4
+ test_tick
+ cat >>"$my_append_to_file" <<INPUT_END
+commit $my_notes_ref
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+committing $my_num_commits notes
+COMMIT
+
+INPUT_END
+
+ my_i=0
+ while test $my_i -lt $my_num_commits
+ do
+ my_i=$(($my_i + 1))
+ cat >>"$my_append_to_file" <<INPUT_END
+N inline :$my_i
+data <<EOF
+note for commit #$my_i$my_note_append
+EOF
+
+INPUT_END
+ done
+}
+
+
+rm input expect
+num_commits=400
+# Create lots of commits
+fast_import_commits "refs/heads/many_commits" $num_commits input
+# Create one note per above commit
+fast_import_notes "refs/notes/many_notes" $num_commits input
+# Add a couple of non-notes as well
+test_tick
+cat >>input <<INPUT_END
+commit refs/notes/many_notes
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+committing some non-notes to the notes tree
+COMMIT
+
+M 755 inline foobar/non-note.txt
+data <<EOF
+This is not a note, but rather a regular file residing in a notes tree
+EOF
+
+M 644 inline deadbeef
+data <<EOF
+Non-note file
+EOF
+
+M 644 inline de/adbeef
+data <<EOF
+Another non-note file
+EOF
+
+INPUT_END
+# Finally create the expected output from all these notes and commits
+i=$num_commits
+while test $i -gt 0
+do
+ cat >>expect <<EXPECT_END
+ commit #$i
+ note for commit #$i
+EXPECT_END
+ i=$(($i - 1))
+done
+
+test_expect_success 'add lots of commits and notes' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
+ grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_expect_success 'verify that lots of notes trigger a fanout scheme' '
+
+ # None of the entries in the top-level notes tree should be a full SHA1
+ git ls-tree --name-only refs/notes/many_notes |
+ while read path
+ do
+ if test $(expr length "$path") -ge 40
+ then
+ return 1
+ fi
+ done
+
+'
+
+cat >>expect_non-note1 << EOF
+This is not a note, but rather a regular file residing in a notes tree
+EOF
+
+cat >>expect_non-note2 << EOF
+Non-note file
+EOF
+
+cat >>expect_non-note3 << EOF
+Another non-note file
+EOF
+
+test_expect_success 'verify that non-notes are untouched by a fanout change' '
+
+ git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
+ test_cmp expect_non-note1 actual &&
+ git cat-file -p refs/notes/many_notes:deadbeef > actual &&
+ test_cmp expect_non-note2 actual &&
+ git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
+ test_cmp expect_non-note3 actual
+
+'
+remaining_notes=10
+test_tick
+cat >>input <<INPUT_END
+commit refs/notes/many_notes
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+removing all notes but $remaining_notes
+COMMIT
+from refs/notes/many_notes^0
+INPUT_END
+
+i=$remaining_notes
+while test $i -lt $num_commits
+do
+ i=$(($i + 1))
+ cat >>input <<INPUT_END
+N 0000000000000000000000000000000000000000 :$i
+INPUT_END
+done
+
+i=$num_commits
+rm expect
+while test $i -gt 0
+do
+ cat >>expect <<EXPECT_END
+ commit #$i
+EXPECT_END
+ if test $i -le $remaining_notes
+ then
+ cat >>expect <<EXPECT_END
+ note for commit #$i
+EXPECT_END
+ fi
+ i=$(($i - 1))
+done
+
+test_expect_success 'remove lots of notes' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
+ grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_expect_success 'verify that removing notes trigger fanout consolidation' '
+
+ # All entries in the top-level notes tree should be a full SHA1
+ git ls-tree --name-only -r refs/notes/many_notes |
+ while read path
+ do
+ # Explicitly ignore the non-note paths
+ test "$path" = "foobar/non-note.txt" && continue
+ test "$path" = "deadbeef" && continue
+ test "$path" = "de/adbeef" && continue
+
+ if test $(expr length "$path") -ne 40
+ then
+ return 1
+ fi
+ done
+
+'
+
+test_expect_success 'verify that non-notes are untouched by a fanout change' '
+
+ git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
+ test_cmp expect_non-note1 actual &&
+ git cat-file -p refs/notes/many_notes:deadbeef > actual &&
+ test_cmp expect_non-note2 actual &&
+ git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
+ test_cmp expect_non-note3 actual
+
+'
+
+
+rm input expect
+num_notes_refs=10
+num_commits=16
+some_commits=8
+# Create commits
+fast_import_commits "refs/heads/more_commits" $num_commits input
+# Create one note per above commit per notes ref
+i=0
+while test $i -lt $num_notes_refs
+do
+ i=$(($i + 1))
+ fast_import_notes "refs/notes/more_notes_$i" $num_commits input
+done
+# Trigger branch reloading in git-fast-import by repeating the note creation
+i=0
+while test $i -lt $num_notes_refs
+do
+ i=$(($i + 1))
+ fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)"
+done
+# Finally create the expected output from the notes in refs/notes/more_notes_1
+i=$num_commits
+while test $i -gt 0
+do
+ note_data="note for commit #$i"
+ if test $i -le $some_commits
+ then
+ note_data="$note_data (2)"
+ fi
+ cat >>expect <<EXPECT_END
+ commit #$i
+ $note_data
+EXPECT_END
+ i=$(($i - 1))
+done
+
+test_expect_success "add notes to $num_commits commits in each of $num_notes_refs refs" '
+
+ git fast-import --active-branches=5 <input &&
+ GIT_NOTES_REF=refs/notes/more_notes_1 git log refs/heads/more_commits |
+ grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_done
diff --git a/t/t9301-fast-export.sh b/t/t9350-fast-export.sh
index 4a87f36258..356964e53a 100755
--- a/t/t9301-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -8,6 +8,9 @@ test_description='git fast-export'
test_expect_success 'setup' '
+ echo break it > file0 &&
+ git add file0 &&
+ test_tick &&
echo Wohlauf > file &&
git add file &&
test_tick &&
@@ -57,15 +60,15 @@ 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 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.
. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
test_tick &&
@@ -259,6 +262,94 @@ test_expect_success 'cope with tagger-less tags' '
'
+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 //"` &&
@@ -268,8 +359,14 @@ test_expect_success 'set-up a few more tags for tag export tests' '
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' 'git fast-export tree_tag'
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'
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index 6a37f71d11..daef2d6c23 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"
'
@@ -94,7 +96,7 @@ EOF
test_expect_success 'pserver authentication' \
'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU$"'
+ sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'pserver authentication failure (non-anonymous user)' \
'if cat request-git | git-cvsserver pserver >log 2>&1
@@ -103,11 +105,11 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \
else
true
fi &&
- sed -ne \$p log | grep "^I HATE YOU$"'
+ sed -ne \$p log | grep "^I HATE YOU\$"'
test_expect_success 'pserver authentication (login)' \
'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU$"'
+ sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'pserver authentication failure (login/non-anonymous user)' \
'if cat login-git | git-cvsserver pserver >log 2>&1
@@ -116,7 +118,7 @@ test_expect_success 'pserver authentication failure (login/non-anonymous user)'
else
true
fi &&
- sed -ne \$p log | grep "^I HATE YOU$"'
+ sed -ne \$p log | grep "^I HATE YOU\$"'
# misuse pserver authentication for testing of req_Root
@@ -154,7 +156,7 @@ test_expect_success 'req_Root failure (conflicting roots)' \
test_expect_success 'req_Root (strict paths)' \
'cat request-anonymous | git-cvsserver --strict-paths pserver "$SERVERDIR" >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU$"'
+ sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'req_Root failure (strict-paths)' '
! cat request-anonymous |
@@ -163,7 +165,7 @@ test_expect_success 'req_Root failure (strict-paths)' '
test_expect_success 'req_Root (w/o strict-paths)' \
'cat request-anonymous | git-cvsserver pserver "$WORKDIR/" >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU$"'
+ sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'req_Root failure (w/o strict-paths)' '
! cat request-anonymous |
@@ -181,7 +183,7 @@ EOF
test_expect_success 'req_Root (base-path)' \
'cat request-base | git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 &&
- sed -ne \$p log | grep "^I LOVE YOU$"'
+ sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'req_Root failure (base-path)' '
! cat request-anonymous |
@@ -192,14 +194,14 @@ 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 &&
- sed -ne \$p log | grep "^I LOVE YOU$"'
+ 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 &&
- sed -ne \$p log | grep "^I LOVE YOU$"'
+ sed -ne \$p log | grep "^I LOVE YOU\$"'
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true || exit 1
@@ -224,7 +226,7 @@ test_expect_success 'gitcvs.ext.enabled = true' \
'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true &&
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false &&
GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 &&
- diff -q cvswork cvswork2'
+ test_cmp cvswork cvswork2'
rm -fr cvswork2
test_expect_success 'gitcvs.ext.enabled = false' \
@@ -245,7 +247,7 @@ test_expect_success 'gitcvs.dbname' \
'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true &&
GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs.%a.%m.sqlite &&
GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 &&
- diff -q cvswork cvswork2 &&
+ test_cmp cvswork cvswork2 &&
test -f "$SERVERDIR/gitcvs.ext.master.sqlite" &&
cmp "$SERVERDIR/gitcvs.master.sqlite" "$SERVERDIR/gitcvs.ext.master.sqlite"'
@@ -255,7 +257,7 @@ test_expect_success 'gitcvs.ext.dbname' \
GIT_DIR="$SERVERDIR" git config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite &&
GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite &&
GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 master >cvs.log 2>&1 &&
- diff -q cvswork cvswork2 &&
+ test_cmp cvswork cvswork2 &&
test -f "$SERVERDIR/gitcvs1.ext.master.sqlite" &&
test ! -f "$SERVERDIR/gitcvs2.ext.master.sqlite" &&
cmp "$SERVERDIR/gitcvs.master.sqlite" "$SERVERDIR/gitcvs1.ext.master.sqlite"'
@@ -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
@@ -280,7 +282,7 @@ test_expect_success 'cvs update (create new file)' \
cd cvswork &&
GIT_CONFIG="$git_config" cvs -Q update &&
test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.1/" &&
- diff -q testfile1 ../testfile1'
+ test_cmp testfile1 ../testfile1'
cd "$WORKDIR"
test_expect_success 'cvs update (update existing file)' \
@@ -291,7 +293,7 @@ test_expect_success 'cvs update (update existing file)' \
cd cvswork &&
GIT_CONFIG="$git_config" cvs -Q update &&
test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.2/" &&
- diff -q testfile1 ../testfile1'
+ test_cmp testfile1 ../testfile1'
cd "$WORKDIR"
#TODO: cvsserver doesn't support update w/o -d
@@ -320,7 +322,7 @@ test_expect_success 'cvs update (subdirectories)' \
(for dir in A A/B A/B/C A/D E; do
filename="file_in_$(echo $dir|sed -e "s#/# #g")" &&
if test "$(echo $(grep -v ^D $dir/CVS/Entries|cut -d/ -f2,3,5))" = "$filename/1.1/" &&
- diff -q "$dir/$filename" "../$dir/$filename"; then
+ test_cmp "$dir/$filename" "../$dir/$filename"; then
:
else
echo >failure
@@ -347,7 +349,7 @@ test_expect_success 'cvs update (re-add deleted file)' \
cd cvswork &&
GIT_CONFIG="$git_config" cvs -Q update &&
test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.4/" &&
- diff -q testfile1 ../testfile1'
+ test_cmp testfile1 ../testfile1'
cd "$WORKDIR"
test_expect_success 'cvs update (merge)' \
@@ -364,7 +366,7 @@ test_expect_success 'cvs update (merge)' \
cd cvswork &&
GIT_CONFIG="$git_config" cvs -Q update &&
test "$(echo $(grep merge CVS/Entries|cut -d/ -f2,3,5))" = "merge/1.1/" &&
- diff -q merge ../merge &&
+ test_cmp merge ../merge &&
( echo Line 0; cat merge ) >merge.tmp &&
mv merge.tmp merge &&
cd "$WORKDIR" &&
@@ -375,7 +377,7 @@ test_expect_success 'cvs update (merge)' \
cd cvswork &&
sleep 1 && touch merge &&
GIT_CONFIG="$git_config" cvs -Q update &&
- diff -q merge ../expected'
+ test_cmp merge ../expected'
cd "$WORKDIR"
@@ -400,13 +402,13 @@ test_expect_success 'cvs update (conflict merge)' \
git push gitcvs.git >/dev/null &&
cd cvswork &&
GIT_CONFIG="$git_config" cvs -Q update &&
- diff -q merge ../expected.C'
+ test_cmp merge ../expected.C'
cd "$WORKDIR"
test_expect_success 'cvs update (-C)' \
'cd cvswork &&
GIT_CONFIG="$git_config" cvs -Q update -C &&
- diff -q merge ../merge'
+ test_cmp merge ../merge'
cd "$WORKDIR"
test_expect_success 'cvs update (merge no-op)' \
@@ -418,7 +420,7 @@ test_expect_success 'cvs update (merge no-op)' \
cd cvswork &&
sleep 1 && touch merge &&
GIT_CONFIG="$git_config" cvs -Q update &&
- diff -q merge ../merge'
+ test_cmp merge ../merge'
cd "$WORKDIR"
test_expect_success 'cvs update (-p)' '
diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh
index e27a1c5f85..ed7b513f3e 100755
--- a/t/t9401-git-cvsserver-crlf.sh
+++ b/t/t9401-git-cvsserver-crlf.sh
@@ -11,14 +11,6 @@ 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
@@ -49,14 +41,17 @@ not_present() {
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
+fi
+if ! test_have_prereq PERL
+then
+ say 'skipping git-cvsserver tests, perl not available'
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
@@ -84,7 +79,7 @@ test_expect_success 'setup' '
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 --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"
'
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 6ed10d0933..63b6b060e6 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -9,77 +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 () {
- 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" \
- >/dev/null 2>gitweb.log &&
- if grep "^[[]" gitweb.log >/dev/null 2>&1; 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)
@@ -242,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'
@@ -254,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 &&
@@ -281,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'
@@ -308,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'
@@ -316,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 &&
@@ -425,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'
@@ -589,7 +525,7 @@ test_expect_success \
echo "ISO-8859-1" >> file &&
git add file &&
git config i18n.commitencoding ISO-8859-1 &&
- git commit -F "$TEST_DIRECTORY"/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'
@@ -655,13 +591,22 @@ test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# gitweb config and repo config
-cat >>gitweb_config.perl <<EOF
+cat >>gitweb_config.perl <<\EOF
-\$feature{'blame'}{'override'} = 1;
-\$feature{'snapshot'}{'override'} = 1;
+# turn on override for each overridable feature
+foreach my $key (keys %feature) {
+ if ($feature{$key}{'sub'}) {
+ $feature{$key}{'override'} = 1;
+ }
+}
EOF
test_expect_success \
+ 'config override: projects list (implicit)' \
+ 'gitweb_run'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
'config override: tree view, features not overridden in repo config' \
'gitweb_run "p=.git;a=tree"'
test_debug 'cat gitweb.log'
@@ -670,6 +615,7 @@ 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'
diff --git a/t/t9501-gitweb-standalone-http-status.sh b/t/t9501-gitweb-standalone-http-status.sh
new file mode 100755
index 0000000000..d196cc5ca9
--- /dev/null
+++ b/t/t9501-gitweb-standalone-http-status.sh
@@ -0,0 +1,137 @@
+#!/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'
+
+
+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'
+
+
+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.headers'
+
+
+# ----------------------------------------------------------------------
+# 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.headers'
+
+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.headers'
+
+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'
+
+
+# ----------------------------------------------------------------------
+# load checking
+
+# always hit the load limit
+cat >>gitweb_config.perl <<\EOF
+our $maxload = -1;
+EOF
+
+test_expect_success 'load checking: load too high (default action)' '
+ gitweb_run "p=.git" &&
+ grep "Status: 503 Service Unavailable" gitweb.headers &&
+ grep "503 - The load average on the server is too high" gitweb.body
+'
+test_debug 'cat gitweb.log' # just in case
+test_debug 'cat gitweb.headers'
+
+# turn off load checking
+cat >>gitweb_config.perl <<\EOF
+our $maxload = undef;
+EOF
+
+
+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 d2379e7f62..363345faef 100755
--- a/t/t9600-cvsimport.sh
+++ b/t/t9600-cvsimport.sh
@@ -1,44 +1,22 @@
#!/bin/sh
test_description='git cvsimport basic tests'
-. ./test-lib.sh
+. ./lib-cvs.sh
-CVSROOT=$(pwd)/cvsroot
-export CVSROOT
-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'
+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 | 2.2*)
- ;;
-'')
- say 'skipping cvsimport tests, cvsps not found'
- test_done
- exit
- ;;
-*)
- say 'skipping cvsimport tests, unsupported cvsps version'
- 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 &&
+ $CVS co -d module-cvs module &&
cd module-cvs &&
cat <<EOF >o_fortuna &&
O Fortuna
@@ -57,13 +35,13 @@ 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 ..
'
@@ -101,7 +79,7 @@ translate to English
My Latin is terrible.
EOF
- cvs commit -F message &&
+ $CVS commit -F message &&
cd ..
'
@@ -119,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 ..
'
@@ -138,7 +116,7 @@ test_expect_success 'cvsimport.module config works' '
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 &&
@@ -148,4 +126,6 @@ test_expect_success 'import from a CVS working tree' '
'
+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
index b81d5dfc34..8686086dde 100755
--- a/t/t9700-perl-git.sh
+++ b/t/t9700-perl-git.sh
@@ -6,8 +6,13 @@
test_description='perl interface (Git.pm)'
. ./test-lib.sh
-perl -MTest::More -e 0 2>/dev/null || {
- say_color skip "Perl Test::More unavailable, skipping test"
+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
}
@@ -24,6 +29,10 @@ test_expect_success \
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" &&
@@ -39,6 +48,6 @@ test_expect_success \
test_external_without_stderr \
'Perl API' \
- perl "$TEST_DIRECTORY"/t9700/test.pl
+ "$PERL_PATH" "$TEST_DIRECTORY"/t9700/test.pl
test_done
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
index 697daf3ffd..666722d9bf 100755
--- a/t/t9700/test.pl
+++ b/t/t9700/test.pl
@@ -13,7 +13,7 @@ use File::Basename;
BEGIN { use_ok('Git') }
# set up
-our $abs_repo_dir = Cwd->cwd;
+our $abs_repo_dir = cwd();
ok(our $r = Git->repository(Directory => "."), "open repository");
# config
@@ -86,15 +86,22 @@ close TEMPFILE;
unlink $tmpfile;
# paths
-is($r->repo_path, "./.git", "repo_path");
+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");
-TODO: {
- local $TODO = "commands do not work after wc_chdir";
- # Failure output is active even in non-verbose mode and thus
- # annoying. Hence we skip these tests as long as they fail.
- todo_skip 'config after wc_chdir', 1;
- is($r->config("color.string"), "value", "config 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 59d82d25e9..a0e396a952 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
@@ -42,13 +58,15 @@ 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
# CDPATH into the environment
unset CDPATH
+unset GREP_OPTIONS
+
case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
1|2|true)
echo "* warning: Some tests will not work if GIT_TRACE" \
@@ -58,6 +76,12 @@ case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
;;
esac
+# Convenience
+#
+# A regexp to match 5 and 40 hexdigits
+_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"
+
# Each test should start with something like this, after copyright notices:
#
# test_description='Description of this test...
@@ -89,13 +113,22 @@ do
verbose=t; shift ;;
-q|--q|--qu|--qui|--quie|--quiet)
quiet=t; shift ;;
+ --with-dashes)
+ with_dashes=t; shift ;;
--no-color)
color=; shift ;;
--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
@@ -127,7 +160,7 @@ fi
error () {
say_color error "error: $*"
- trap - EXIT
+ GIT_EXIT_OK=t
exit 1
}
@@ -159,10 +192,17 @@ 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
}
+GIT_EXIT_OK=
trap 'die' EXIT
# The semantics of the editor variables are that of invoking
@@ -177,8 +217,35 @@ trap 'die' EXIT
test_set_editor () {
FAKE_EDITOR="$1"
export FAKE_EDITOR
- VISUAL='"$FAKE_EDITOR"'
- export VISUAL
+ EDITOR='"$FAKE_EDITOR"'
+ export EDITOR
+}
+
+test_decode_color () {
+ sed -e 's/.\[1m/<WHITE>/g' \
+ -e 's/.\[31m/<RED>/g' \
+ -e 's/.\[32m/<GREEN>/g' \
+ -e 's/.\[33m/<YELLOW>/g' \
+ -e 's/.\[34m/<BLUE>/g' \
+ -e 's/.\[35m/<MAGENTA>/g' \
+ -e 's/.\[36m/<CYAN>/g' \
+ -e 's/.\[m/<RESET>/g'
+}
+
+q_to_nul () {
+ perl -pe 'y/Q/\000/'
+}
+
+q_to_cr () {
+ tr Q '\015'
+}
+
+append_cr () {
+ sed -e 's/$/Q/' | tr Q '\015'
+}
+
+remove_cr () {
+ tr '\015' Q | sed -e 's/Q$//'
}
test_tick () {
@@ -218,32 +285,62 @@ test_merge () {
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=$(expr "$test_success" + 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: $@"
}
@@ -259,20 +356,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
;;
@@ -283,8 +383,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"
@@ -293,15 +394,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"
@@ -317,8 +419,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"
@@ -342,15 +445,16 @@ test_expect_code () {
# Usage: test_external description command arguments...
# Example: test_external 'Perl API' perl ../path/to/test.pl
test_external () {
- test "$#" -eq 3 ||
- error >&5 "bug in the test script: not 3 parameters to 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 $(expr "$test_count" + 1): $descr ($*)"
+ 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.
@@ -434,17 +538,17 @@ test_create_repo () {
repo="$1"
mkdir -p "$repo"
cd "$repo" || error "Cannot setup test environment"
- "$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >&3 2>&4 ||
+ "$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%-*}-$$"
+ test_results_path="$test_results_dir/${0%.sh}-$$"
echo "total $test_count" >> $test_results_path
echo "success $test_success" >> $test_results_path
@@ -484,33 +588,127 @@ test_done () {
# Test the binaries we have just built. The tests are kept in
# t/ subdirectory and are run in 'trash directory' subdirectory.
TEST_DIRECTORY=$(pwd)
-PATH=$TEST_DIRECTORY/..:$PATH
-GIT_EXEC_PATH=$(pwd)/..
+if test -n "$valgrind"
+then
+ 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
+elif test -n "$GIT_TEST_INSTALLED" ; then
+ 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}
+else # normal case, use ../bin-wrappers only unless $with_dashes:
+ git_bin_dir="$TEST_DIRECTORY/../bin-wrappers"
+ if ! test -x "$git_bin_dir/git" ; then
+ if test -z "$with_dashes" ; then
+ say "$git_bin_dir/git is not executable; using GIT_EXEC_PATH"
+ fi
+ with_dashes=t
+ fi
+ PATH="$git_bin_dir:$PATH"
+ GIT_EXEC_PATH=$TEST_DIRECTORY/..
+ if test -n "$with_dashes" ; then
+ PATH="$TEST_DIRECTORY/..:$PATH"
+ fi
+fi
GIT_TEMPLATE_DIR=$(pwd)/../templates/blt
unset GIT_CONFIG
GIT_CONFIG_NOSYSTEM=1
GIT_CONFIG_NOGLOBAL=1
export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL
+. ../GIT-BUILD-OPTIONS
+
GITPERLLIB=$(pwd)/../perl/blib/lib:$(pwd)/../perl/blib/arch/auto/Git
export GITPERLLIB
test -d ../templates/blt || {
error "You haven't built things yet, have you?"
}
+if test -z "$GIT_TEST_INSTALLED" && test -z "$NO_PYTHON"
+then
+ GITPYTHONLIB="$(pwd)/../git_remote_helpers/build/lib"
+ export GITPYTHONLIB
+ test -d ../git_remote_helpers/build || {
+ error "You haven't built git_remote_helpers yet, have you?"
+ }
+fi
+
if ! test -x ../test-chmtime; then
echo >&2 'You need to build test-chmtime:'
echo >&2 'Run "make test-chmtime" in the source (toplevel) directory'
exit 1
fi
-. ../GIT-BUILD-OPTIONS
-
# Test repository
test="trash directory.$(basename "$0" .sh)"
-test ! -z "$debug" || remove_trash="$TEST_DIRECTORY/$test"
+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
}
@@ -520,7 +718,8 @@ test_create_repo "$test"
# 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=
@@ -538,3 +737,53 @@ 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 -z "$NO_PYTHON" && test_set_prereq PYTHON
+
+# 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" "$@"