Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml8
-rw-r--r--CMakeLists.txt15
-rw-r--r--README.md5
-rw-r--r--cmake/Modules/FindIconv.cmake29
-rw-r--r--examples/blame.c5
-rw-r--r--examples/general.c3
-rw-r--r--examples/showindex.c2
-rw-r--r--git.git-authors8
-rw-r--r--include/git2/blame.h2
-rw-r--r--include/git2/blob.h7
-rw-r--r--include/git2/branch.h49
-rw-r--r--include/git2/checkout.h7
-rw-r--r--include/git2/clone.h7
-rw-r--r--include/git2/config.h24
-rw-r--r--include/git2/diff.h6
-rw-r--r--include/git2/graph.h14
-rw-r--r--include/git2/index.h2
-rw-r--r--include/git2/merge.h29
-rw-r--r--include/git2/message.h17
-rw-r--r--include/git2/notes.h6
-rw-r--r--include/git2/patch.h7
-rw-r--r--include/git2/refs.h178
-rw-r--r--include/git2/refspec.h7
-rw-r--r--include/git2/remote.h24
-rw-r--r--include/git2/repository.h38
-rw-r--r--include/git2/revwalk.h18
-rw-r--r--include/git2/signature.h7
-rw-r--r--include/git2/submodule.h24
-rw-r--r--include/git2/sys/commit.h2
-rw-r--r--include/git2/tree.h13
-rw-r--r--include/git2/types.h21
-rwxr-xr-xscript/cibuild.sh6
-rwxr-xr-xscript/coverity.sh57
-rw-r--r--src/attr.c13
-rw-r--r--src/blame.c15
-rw-r--r--src/blob.c43
-rw-r--r--src/branch.c170
-rw-r--r--src/buffer.c17
-rw-r--r--src/buffer.h9
-rw-r--r--src/checkout.c119
-rw-r--r--src/clone.c59
-rw-r--r--src/commit.c51
-rw-r--r--src/compress.c53
-rw-r--r--src/compress.h16
-rw-r--r--src/config.c57
-rw-r--r--src/config.h5
-rw-r--r--src/config_file.c6
-rw-r--r--src/crlf.c2
-rw-r--r--src/diff.c46
-rw-r--r--src/diff.h2
-rw-r--r--src/diff_driver.c203
-rw-r--r--src/diff_driver.h2
-rw-r--r--src/diff_file.c26
-rw-r--r--src/diff_patch.c10
-rw-r--r--src/diff_print.c34
-rw-r--r--src/diff_tform.c30
-rw-r--r--src/graph.c14
-rw-r--r--src/index.c173
-rw-r--r--src/index.h2
-rw-r--r--src/indexer.c27
-rw-r--r--src/iterator.c2
-rw-r--r--src/merge.c155
-rw-r--r--src/merge.h2
-rw-r--r--src/merge_file.c20
-rw-r--r--src/merge_file.h23
-rw-r--r--src/message.c30
-rw-r--r--src/notes.c8
-rw-r--r--src/notes.h2
-rw-r--r--src/odb.c3
-rw-r--r--src/oid.c3
-rw-r--r--src/pack-objects.c149
-rw-r--r--src/pack-objects.h2
-rw-r--r--src/pack.c5
-rw-r--r--src/pack.h1
-rw-r--r--src/pathspec.c6
-rw-r--r--src/posix.h9
-rw-r--r--src/push.c4
-rw-r--r--src/refdb_fs.c17
-rw-r--r--src/reflog.c2
-rw-r--r--src/refs.c146
-rw-r--r--src/refs.h2
-rw-r--r--src/refspec.c54
-rw-r--r--src/refspec.h22
-rw-r--r--src/remote.c104
-rw-r--r--src/repository.c82
-rw-r--r--src/reset.c4
-rw-r--r--src/revparse.c5
-rw-r--r--src/revwalk.c72
-rw-r--r--src/settings.c134
-rw-r--r--src/signature.c29
-rw-r--r--src/stash.c4
-rw-r--r--src/status.c18
-rw-r--r--src/strnlen.h23
-rw-r--r--src/submodule.c39
-rw-r--r--src/submodule.h6
-rw-r--r--src/tag.c4
-rw-r--r--src/transports/local.c50
-rw-r--r--src/tree.c25
-rw-r--r--src/userdiff.h210
-rw-r--r--src/util.c128
-rw-r--r--src/util.h4
-rw-r--r--src/vector.c1
-rw-r--r--src/zstream.c156
-rw-r--r--src/zstream.h39
-rw-r--r--tests/attr/repo.c2
-rw-r--r--tests/blame/blame_helpers.c3
-rw-r--r--tests/checkout/conflict.c2
-rw-r--r--tests/checkout/crlf.c4
-rw-r--r--tests/checkout/index.c4
-rw-r--r--tests/checkout/tree.c55
-rw-r--r--tests/checkout/typechange.c4
-rw-r--r--tests/clar/fs.h18
-rw-r--r--tests/clone/empty.c12
-rw-r--r--tests/clone/nonetwork.c52
-rw-r--r--tests/commit/commit.c4
-rw-r--r--tests/commit/write.c2
-rw-r--r--tests/core/buffer.c31
-rw-r--r--tests/core/zstream.c143
-rw-r--r--tests/diff/blob.c91
-rw-r--r--tests/diff/diffiter.c8
-rw-r--r--tests/diff/drivers.c141
-rw-r--r--tests/diff/iterator.c2
-rw-r--r--tests/diff/patch.c43
-rw-r--r--tests/diff/rename.c14
-rw-r--r--tests/diff/submodules.c12
-rw-r--r--tests/diff/workdir.c16
-rw-r--r--tests/filter/blob.c32
-rw-r--r--tests/filter/custom.c4
-rw-r--r--tests/graph/descendant_of.c47
-rw-r--r--tests/index/collision.c106
-rw-r--r--tests/index/conflicts.c40
-rw-r--r--tests/index/rename.c4
-rw-r--r--tests/index/tests.c8
-rw-r--r--tests/merge/merge_helpers.c6
-rw-r--r--tests/merge/trees/automerge.c6
-rw-r--r--tests/merge/trees/commits.c2
-rw-r--r--tests/merge/trees/trivial.c123
-rw-r--r--tests/merge/workdir/dirty.c322
-rw-r--r--tests/merge/workdir/fastforward.c10
-rw-r--r--tests/merge/workdir/setup.c78
-rw-r--r--tests/merge/workdir/simple.c237
-rw-r--r--tests/merge/workdir/submodules.c101
-rw-r--r--tests/merge/workdir/trivial.c110
-rw-r--r--tests/network/remote/local.c41
-rw-r--r--tests/network/remote/remotes.c46
-rw-r--r--tests/notes/notes.c4
-rw-r--r--tests/notes/notesref.c4
-rw-r--r--tests/object/commit/commitstagedfile.c10
-rw-r--r--tests/object/message.c87
-rw-r--r--tests/object/tree/duplicateentries.c6
-rw-r--r--tests/online/clone.c2
-rw-r--r--tests/online/push.c2
-rw-r--r--tests/refs/branches/create.c55
-rw-r--r--tests/refs/branches/delete.c28
-rw-r--r--tests/refs/branches/ishead.c6
-rw-r--r--tests/refs/branches/iterator.c4
-rw-r--r--tests/refs/branches/move.c81
-rw-r--r--tests/refs/branches/remote.c39
-rw-r--r--tests/refs/branches/upstream.c2
-rw-r--r--tests/refs/branches/upstreamname.c10
-rw-r--r--tests/refs/crashes.c2
-rw-r--r--tests/refs/create.c16
-rw-r--r--tests/refs/createwithlog.c2
-rw-r--r--tests/refs/delete.c2
-rw-r--r--tests/refs/foreachglob.c2
-rw-r--r--tests/refs/overwrite.c26
-rw-r--r--tests/refs/pack.c4
-rw-r--r--tests/refs/read.c15
-rw-r--r--tests/refs/reflog/reflog.c14
-rw-r--r--tests/refs/rename.c55
-rw-r--r--tests/refs/revparse.c11
-rw-r--r--tests/refs/settargetwithlog.c2
-rw-r--r--tests/refs/setter.c10
-rw-r--r--tests/refs/unicode.c2
-rw-r--r--tests/refs/update.c2
-rw-r--r--tests/repo/discover.c63
-rw-r--r--tests/repo/head.c98
-rw-r--r--tests/repo/message.c25
-rw-r--r--tests/repo/repo_helpers.c2
-rw-r--r--tests/reset/default.c2
-rw-r--r--tests/reset/hard.c2
-rw-r--r--tests/resources/crlf/.gitted/objects/2c/9a868cfdf8e270d0ec68164433376c68fb1789bin0 -> 169 bytes
-rw-r--r--tests/resources/crlf/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391bin0 -> 15 bytes
-rw-r--r--tests/resources/crlf/.gitted/objects/ef/0dcd356d77221e9c27f4f3928ad28e80b87cebbin0 -> 168 bytes
-rw-r--r--tests/resources/crlf/.gitted/refs/heads/master2
-rw-r--r--tests/resources/merge-resolve/.gitted/config2
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/HEAD1
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/ORIG_HEAD1
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/config15
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/indexbin0 -> 153 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/info/exclude6
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/18/fae1354bba0a5f1e6a531f9988369142c24a9ebin0 -> 54 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/29/7aa6cd028b3336c7802c7a6f49143da4e1602dbin0 -> 161 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/38/6c80dc813b89d719797668f40c1be0a6efa996bin0 -> 32 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/ab/435a147bae6d5906ecfd0916a570c4ab3eeea8bin0 -> 64 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/ad/16e0a7684ea95bf892980a2ee412293ae979ccbin0 -> 64 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/ae/39c77c70cb6bad18bb471912460c4e1ba0f5862
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/c2/0765f6e24e8bbb63a648d0d11d84da63170190bin0 -> 52 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/d3/d806a4bef96889117fd7ebac0e3cb5ec1529323
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/objects/f1/065ff5593604072837fecaad3e2e268cb0147bbin0 -> 64 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/packed-refs3
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/refs/heads/master1
-rw-r--r--tests/resources/merge-resolve/.gitted/modules/submodule/refs/remotes/origin/HEAD1
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/0f/3fc5dddc8964b9ac1040d0e957f9eb02d9efb3bin0 -> 47 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00bin0 -> 51 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85bin0 -> 30 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111babin0 -> 30 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/27/4bbe983022fb4c02f8a2bf2ebe8da4fe130054bin0 -> 24 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/2b/fdd7e1b6c6ae993f23dfe8e84a8e06a772fa2abin0 -> 231 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1ebin0 -> 51 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/42/18670ab81cc219a9f94befb5c5dad90ec52648bin0 -> 47 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/49/fd9edac79d15c8fbfca2d481cbb900beba22a63
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/58/87a5e516c53bd58efb0f02ec6aa031b6fe9ad7bin0 -> 47 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/60/61fe116ecba0800c26113ea1a7dfac2e16eeafbin0 -> 87 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/62/33c6a0670228627f93c01cef32485a30403670bin0 -> 44 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/67/110d77886b2af6309b9212961e72b8583e5fa91
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55bin0 -> 51 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/72/cdb057b340205164478565e91eb71647e66891bin0 -> 65 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/7a/f14d9c679baaef35555095f4f5d33e9a569ab9bin0 -> 149 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/7c/04ca611203ed320c5f495b9813054dd23be3be2
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/81/1c70fcb6d5bbd022d04cc31836d30b436f9551bin0 -> 169 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19bin0 -> 30 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/8b/7cd60d49ce3a1a770ece43b7d29b5cf462a33abin0 -> 82 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/91/f44111cb1cb1358ac6944ad356ca1738813ea1bin0 -> 149 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/96/bca8d4f05cc4c5e33e4389f80a1309e86fe054bin0 -> 149 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730bin0 -> 158 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/ad/26b598134264fd284292cb233fc0b2f25851dabin0 -> 43 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/ca/ff6b7d44973f53e3e0cf31d0d695188b19aec6bin0 -> 54 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf12
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/d3/3cedf513c059e0515653fa2c2e386631387a05bin0 -> 46 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b4601
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/d8/dec75ff2f8b41d1c5bfef0cd57b7300c834f66bin0 -> 164 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/dd/2ae5ab264e5592aa754235d5ad5eac8f0ecdfdbin0 -> 149 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/e5/060729746ca9888239cba08fdcf4bee907b406bin0 -> 24 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/f2/e1550a0c9e53d5811175864a29536642ae3821bin0 -> 73 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/f6/65b45cde9b568009c6e6b7b568e89cfe717df8bin0 -> 132 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/refs/heads/submodules1
-rw-r--r--tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch1
-rw-r--r--tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch21
-rw-r--r--tests/resources/revert/.gitted/indexbin320 -> 464 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/0a/d19525be6d8cae5e5deb2770fc244b65255057bin0 -> 133 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/13/a6fdfd10bd74b1f258fb58801215985dd2e797bin0 -> 121 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/1b/c915c5cb7185a9438de28a7b1a7dfe8c01ee7fbin0 -> 1169 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/1f/f0c423042b46cb1d617b81efb715defbe8054dbin0 -> 751 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/21/a96a98ed84d45866e1de6e266fd3a61a4ae9dcbin0 -> 19 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/39/9fb3aba3d9d13f7d40a9254ce4402067ef31492
-rw-r--r--tests/resources/revert/.gitted/objects/46/ff0854663aeb2182b9838c8da68e33ac23bc1ebin0 -> 20 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/5c/f1d643f100d8112834e540264546ba2c159976bin0 -> 86 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/6b/ccd0dc58cea5ccff86014f3d64b31bd8c02a37bin0 -> 171 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/71/eb9c2b53dbbf3c45fb28b27c850db4b7fb8011bin0 -> 148 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/87/59ad453cf01cf7daf14e2a668f8218f9a678ebbin0 -> 122 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/9a/95fd974e03c5b93828ceedd28755965b5d5c60bin0 -> 122 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/a8/c86221b400b836010567cc3593db6e96c1a83abin0 -> 24 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/ac/c4d33902092efeb3b714aa0b1007c329e2f2e62
-rw-r--r--tests/resources/revert/.gitted/objects/b6/9d88e177455579896e2be495046e2a51456a9a1
-rw-r--r--tests/resources/revert/.gitted/objects/ca/f99de3a49827117bb66721010eac461b06a80cbin0 -> 33 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/de/03538407ed18914ff05657eeff70425c0f304d2
-rw-r--r--tests/resources/revert/.gitted/objects/e3/4ef1afe54eb526fd92eec66084125f340f1d65bin0 -> 150 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/ea/392a157085bc32daccd59aa1998fe2f5fb9fc0bin0 -> 134 bytes
-rw-r--r--tests/resources/revert/.gitted/objects/ee/c6adcb2f3ceca0cadeccfe01b19382252ece9bbin0 -> 66 bytes
-rw-r--r--tests/resources/revert/.gitted/refs/heads/master2
-rw-r--r--tests/resources/revert/.gitted/refs/heads/two1
-rw-r--r--tests/resources/testrepo/.gitted/objects/1d/d0968be3ff95fcaecb6fa4245662db9fdc4568bin0 -> 73 bytes
-rw-r--r--tests/resources/testrepo/.gitted/objects/af/e4393b2b2a965f06acf2ca9658eaa01e0cd6b6bin0 -> 171 bytes
-rw-r--r--tests/resources/testrepo/.gitted/objects/ce/054d4c5e3c83522aed8bc061987b46b7ede3bebin0 -> 194 bytes
-rw-r--r--tests/resources/userdiff/.gitted/HEAD1
-rw-r--r--tests/resources/userdiff/.gitted/config7
-rw-r--r--tests/resources/userdiff/.gitted/description1
-rw-r--r--tests/resources/userdiff/.gitted/indexbin0 -> 1336 bytes
-rw-r--r--tests/resources/userdiff/.gitted/info/refs1
-rw-r--r--tests/resources/userdiff/.gitted/objects/info/packs2
-rw-r--r--tests/resources/userdiff/.gitted/objects/pack/pack-1652578900ac63564f2a24b9714529821276ceb9.idxbin0 -> 2500 bytes
-rw-r--r--tests/resources/userdiff/.gitted/objects/pack/pack-1652578900ac63564f2a24b9714529821276ceb9.packbin0 -> 7102 bytes
-rw-r--r--tests/resources/userdiff/.gitted/packed-refs2
-rw-r--r--tests/resources/userdiff/.gitted/refs/dummy-marker.txt0
-rw-r--r--tests/resources/userdiff/after/file.html41
-rw-r--r--tests/resources/userdiff/after/file.javascript108
-rw-r--r--tests/resources/userdiff/after/file.php50
-rw-r--r--tests/resources/userdiff/before/file.html41
-rw-r--r--tests/resources/userdiff/before/file.javascript109
-rw-r--r--tests/resources/userdiff/before/file.php49
-rw-r--r--tests/resources/userdiff/expected/driver/diff.html26
-rw-r--r--tests/resources/userdiff/expected/driver/diff.javascript40
-rw-r--r--tests/resources/userdiff/expected/driver/diff.php26
-rw-r--r--tests/resources/userdiff/expected/nodriver/diff.html26
-rw-r--r--tests/resources/userdiff/expected/nodriver/diff.javascript40
-rw-r--r--tests/resources/userdiff/expected/nodriver/diff.php26
-rw-r--r--tests/resources/userdiff/files/file.html41
-rw-r--r--tests/resources/userdiff/files/file.javascript108
-rw-r--r--tests/resources/userdiff/files/file.php50
-rw-r--r--tests/revert/workdir.c206
-rw-r--r--tests/revwalk/basic.c38
-rw-r--r--tests/stash/save.c2
-rw-r--r--tests/status/renames.c27
-rw-r--r--tests/status/submodules.c19
-rw-r--r--tests/status/worktree.c12
-rw-r--r--tests/submodule/lookup.c2
-rw-r--r--tests/submodule/modify.c34
-rw-r--r--tests/threads/refdb.c6
299 files changed, 5401 insertions, 2137 deletions
diff --git a/.travis.yml b/.travis.yml
index 151060fb4..f25ff7681 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,13 +9,21 @@ compiler:
# Settings to try
env:
+ global:
+ - secure: "YnhS+8n6B+uoyaYfaJ3Lei7cSJqHDPiKJCKFIF2c87YDfmCvAJke8QtE7IzjYDs7UFkTCM4ox+ph2bERUrxZbSCyEkHdjIZpKuMJfYWja/jgMqTMxdyOH9y8JLFbZsSXDIXDwqBlC6vVyl1fP90M35wuWcNTs6tctfVWVofEFbs="
+ matrix:
- OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release"
- OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=ON"
matrix:
+ fast_finish: true
include:
- compiler: i586-mingw32msvc-gcc
env: OPTIONS="-DBUILD_CLAR=OFF -DWIN32=ON -DMINGW=ON"
+ - compiler: gcc
+ env: COVERITY=1
+ allow_failures:
+ - env: COVERITY=1
install:
- sudo apt-get -qq update
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 48cbccb4e..6f2a2bb82 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,7 +15,7 @@ PROJECT(libgit2 C)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
# Add find modules to the path
-SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules/")
# Build options
#
@@ -136,7 +136,7 @@ ELSE ()
LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES})
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lhttp_parser")
ELSE()
- MESSAGE("http-parser was not found or is too old; using bundled 3rd-party sources.")
+ MESSAGE(STATUS "http-parser was not found or is too old; using bundled 3rd-party sources.")
INCLUDE_DIRECTORIES(deps/http-parser)
FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h)
ENDIF()
@@ -177,9 +177,9 @@ IF (ZLIB_FOUND)
SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} zlib")
ENDIF()
# Fake the message CMake would have shown
- MESSAGE("-- Found zlib: ${ZLIB_LIBRARY}")
+ MESSAGE(STATUS "Found zlib: ${ZLIB_LIBRARY}")
ELSE()
- MESSAGE( "zlib was not found; using bundled 3rd-party sources." )
+ MESSAGE(STATUS "zlib was not found; using bundled 3rd-party sources." )
INCLUDE_DIRECTORIES(deps/zlib)
ADD_DEFINITIONS(-DNO_VIZ -DSTDC -DNO_GZIP)
FILE(GLOB SRC_ZLIB deps/zlib/*.c deps/zlib/*.h)
@@ -202,11 +202,8 @@ IF (USE_ICONV)
ENDIF()
IF (ICONV_FOUND)
ADD_DEFINITIONS(-DGIT_USE_ICONV)
- IF(ICONV_LIBRARIES MATCHES "libiconv")
- SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -liconv")
- ELSE()
- SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} iconv")
- ENDIF()
+ INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR})
+ SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} ${ICONV_LIBRARIES}")
ENDIF()
# Platform specific compilation flags
diff --git a/README.md b/README.md
index 434cc1937..f814b8732 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@ libgit2 - the Git linkable library
==================================
[![Build Status](https://secure.travis-ci.org/libgit2/libgit2.png?branch=development)](http://travis-ci.org/libgit2/libgit2)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639)
`libgit2` is a portable, pure C implementation of the Git core methods provided as a
re-entrant linkable library with a solid API, allowing you to write native
@@ -164,6 +165,8 @@ Here are the bindings to libgit2 that are currently available:
* libgit2-glib <https://live.gnome.org/Libgit2-glib>
* Haskell
* hgit2 <https://github.com/fpco/gitlib>
+* Java
+ * Jagged <https://github.com/ethomson/jagged>
* Lua
* luagit2 <https://github.com/libgit2/luagit2>
* .NET
@@ -181,6 +184,8 @@ Here are the bindings to libgit2 that are currently available:
* Git-Raw <https://github.com/ghedo/p5-Git-Raw>
* PHP
* php-git <https://github.com/libgit2/php-git>
+* PowerShell
+ * GitPowerShell <https://github.com/ethomson/gitpowershell>
* Python
* pygit2 <https://github.com/libgit2/pygit2>
* Ruby
diff --git a/cmake/Modules/FindIconv.cmake b/cmake/Modules/FindIconv.cmake
index fb6d1e210..c5a419011 100644
--- a/cmake/Modules/FindIconv.cmake
+++ b/cmake/Modules/FindIconv.cmake
@@ -4,39 +4,40 @@
# ICONV_FOUND - system has Iconv
# ICONV_INCLUDE_DIR - the Iconv include directory
# ICONV_LIBRARIES - Link these to use Iconv
-# ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const
#
-IF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
# Already in cache, be silent
SET(ICONV_FIND_QUIETLY TRUE)
-ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+ENDIF()
+FIND_PATH(ICONV_INCLUDE_DIR iconv.h PATHS /opt/local/include NO_DEFAULT_PATH)
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
-FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c PATH)
+FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c NO_DEFAULT_PATH PATHS /opt/local/lib)
+FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c)
-IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+IF(ICONV_INCLUDE_DIR AND iconv_lib)
SET(ICONV_FOUND TRUE)
-ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
-
-set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
-set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES})
-set(CMAKE_REQUIRED_INCLUDES)
-set(CMAKE_REQUIRED_LIBRARIES)
+ENDIF()
IF(ICONV_FOUND)
+ # split iconv into -L and -l linker options, so we can set them for pkg-config
+ GET_FILENAME_COMPONENT(iconv_path ${iconv_lib} PATH)
+ GET_FILENAME_COMPONENT(iconv_name ${iconv_lib} NAME_WE)
+ STRING(REGEX REPLACE "^lib" "" iconv_name ${iconv_name})
+ SET(ICONV_LIBRARIES "-L${iconv_path} -l${iconv_name}")
+
IF(NOT ICONV_FIND_QUIETLY)
MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}")
ENDIF(NOT ICONV_FIND_QUIETLY)
-ELSE(ICONV_FOUND)
+ELSE()
IF(Iconv_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find Iconv")
ENDIF(Iconv_FIND_REQUIRED)
-ENDIF(ICONV_FOUND)
+ENDIF()
MARK_AS_ADVANCED(
ICONV_INCLUDE_DIR
ICONV_LIBRARIES
- ICONV_SECOND_ARGUMENT_IS_CONST
)
diff --git a/examples/blame.c b/examples/blame.c
index 06310d540..1f5db69a1 100644
--- a/examples/blame.c
+++ b/examples/blame.c
@@ -14,6 +14,11 @@
#include "common.h"
+#ifdef _MSC_VER
+#define snprintf sprintf_s
+#define strcasecmp strcmpi
+#endif
+
/**
* This example demonstrates how to invoke the libgit2 blame API to roughly
* simulate the output of `git blame` and a few of its command line arguments.
diff --git a/examples/general.c b/examples/general.c
index 58e141b35..ae8756338 100644
--- a/examples/general.c
+++ b/examples/general.c
@@ -47,11 +47,10 @@
// as an example.
static void check_error(int error_code, const char *action)
{
+ const git_error *error = giterr_last();
if (!error_code)
return;
- const git_error *error = giterr_last();
-
printf("Error %d %s - %s\n", error_code, action,
(error && error->message) ? error->message : "???");
diff --git a/examples/showindex.c b/examples/showindex.c
index 7f7c38379..ad4a16e8e 100644
--- a/examples/showindex.c
+++ b/examples/showindex.c
@@ -49,7 +49,7 @@ int main (int argc, char** argv)
for (i = 0; i < ecount; ++i) {
const git_index_entry *e = git_index_get_byindex(index, i);
- git_oid_fmt(out, &e->oid);
+ git_oid_fmt(out, &e->id);
printf("File Path: %s\n", e->path);
printf(" Stage: %d\n", git_index_entry_stage(e));
diff --git a/git.git-authors b/git.git-authors
index 7d4c95bb3..7c72c4bf6 100644
--- a/git.git-authors
+++ b/git.git-authors
@@ -39,27 +39,34 @@
# but has otherwise not contributed to git.)
#
ok Adam Simpkins <adam@adamsimpkins.net> (http transport)
+ok Adrian Johnson <ajohnson@redneon.com>
+ok Alexey Shumkin <alex.crezoff@gmail.com>
ok Andreas Ericsson <ae@op5.se>
ok Boyd Lynn Gerber <gerberb@zenez.com>
+ok Brandon Casey <drafnel@gmail.com>
ok Brian Downing <bdowning@lavos.net>
ok Brian Gernhardt <benji@silverinsanity.com>
ok Christian Couder <chriscool@tuxfamily.org>
ok Daniel Barkalow <barkalow@iabervon.org>
ok Florian Forster <octo@verplant.org>
+ok Gustaf Hendeby <hendeby@isy.liu.se>
ok Holger Weiss <holger@zedat.fu-berlin.de>
ok Jeff King <peff@peff.net>
ok Johannes Schindelin <Johannes.Schindelin@gmx.de>
ok Johannes Sixt <j6t@kdbg.org>
+ask Jonathan Nieder <jrnieder@gmail.com>
ok Junio C Hamano <gitster@pobox.com>
ok Kristian Høgsberg <krh@redhat.com>
ok Linus Torvalds <torvalds@linux-foundation.org>
ok Lukas Sandström <lukass@etek.chalmers.se>
ok Matthieu Moy <Matthieu.Moy@imag.fr>
+ok Michael Haggerty <mhagger@alum.mit.edu>
ign Mike McCormack <mike@codeweavers.com> (imap-send)
ok Nicolas Pitre <nico@fluxnic.net> <nico@cam.org>
ok Paolo Bonzini <bonzini@gnu.org>
ok Paul Kocher <paul@cryptography.com>
ok Peter Hagervall <hager@cs.umu.se>
+ok Petr Onderka <gsvick@gmail.com>
ok Pierre Habouzit <madcoder@debian.org>
ok Pieter de Bie <pdebie@ai.rug.nl>
ok René Scharfe <rene.scharfe@lsrfire.ath.cx>
@@ -68,4 +75,5 @@ ok Sebastian Schuberth <sschuberth@gmail.com>
ok Shawn O. Pearce <spearce@spearce.org>
ok Steffen Prohaska <prohaska@zib.de>
ok Sven Verdoolaege <skimo@kotnet.org>
+ask Thomas Rast <tr@thomasrast.ch> (ok before 6-Oct-2013)
ok Torsten Bögershausen <tboegi@web.de>
diff --git a/include/git2/blame.h b/include/git2/blame.h
index 73bcc5bc6..b98c6f0d7 100644
--- a/include/git2/blame.h
+++ b/include/git2/blame.h
@@ -183,7 +183,7 @@ GIT_EXTERN(int) git_blame_buffer(
git_blame **out,
git_blame *reference,
const char *buffer,
- uint32_t buffer_len);
+ size_t buffer_len);
/**
* Free memory allocated by git_blame_file or git_blame_buffer.
diff --git a/include/git2/blob.h b/include/git2/blob.h
index 19ad4d949..ac4d84392 100644
--- a/include/git2/blob.h
+++ b/include/git2/blob.h
@@ -84,7 +84,7 @@ GIT_EXTERN(git_repository *) git_blob_owner(const git_blob *blob);
* time.
*
* @param blob pointer to the blob
- * @return the pointer; NULL if the blob has no contents
+ * @return the pointer
*/
GIT_EXTERN(const void *) git_blob_rawcontent(const git_blob *blob);
@@ -196,13 +196,14 @@ GIT_EXTERN(int) git_blob_create_fromchunks(
/**
* Write an in-memory buffer to the ODB as a blob
*
- * @param oid return the oid of the written blob
+ * @param id return the id of the written blob
* @param repo repository where to blob will be written
* @param buffer data to be written into the blob
* @param len length of the data
* @return 0 or an error code
*/
-GIT_EXTERN(int) git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len);
+GIT_EXTERN(int) git_blob_create_frombuffer(
+ git_oid *id, git_repository *repo, const void *buffer, size_t len);
/**
* Determine if the blob content is most certainly binary or not.
diff --git a/include/git2/branch.h b/include/git2/branch.h
index 44d6fd9c3..46aef3206 100644
--- a/include/git2/branch.h
+++ b/include/git2/branch.h
@@ -43,6 +43,12 @@ GIT_BEGIN_DECL
*
* @param force Overwrite existing branch.
*
+ * @param signature The identity that will used to populate the reflog entry
+ *
+ * @param log_message The one line long message to be appended to the reflog.
+ * If NULL, the default is "Branch: created"; if you want something more
+ * useful, provide a message.
+ *
* @return 0, GIT_EINVALIDSPEC or an error code.
* A proper reference is written in the refs/heads namespace
* pointing to the provided target commit.
@@ -52,7 +58,9 @@ GIT_EXTERN(int) git_branch_create(
git_repository *repo,
const char *branch_name,
const git_commit *target,
- int force);
+ int force,
+ const git_signature *signature,
+ const char *log_message);
/**
* Delete an existing branch reference.
@@ -115,13 +123,19 @@ GIT_EXTERN(void) git_branch_iterator_free(git_branch_iterator *iter);
*
* @param force Overwrite existing branch.
*
+ * @param signature The identity that will used to populate the reflog entry
+ *
+ * @param log_message The one line long message to be appended to the reflog
+ *
* @return 0 on success, GIT_EINVALIDSPEC or an error code.
*/
GIT_EXTERN(int) git_branch_move(
git_reference **out,
git_reference *branch,
const char *new_branch_name,
- int force);
+ int force,
+ const git_signature *signature,
+ const char *log_message);
/**
* Lookup a branch by its name in a repository.
@@ -200,25 +214,20 @@ GIT_EXTERN(int) git_branch_set_upstream(git_reference *branch, const char *upstr
* Return the name of the reference supporting the remote tracking branch,
* given the name of a local branch reference.
*
- * @param tracking_branch_name_out The user-allocated buffer which will be
- * filled with the name of the reference. Pass NULL if you just want to
- * get the needed size of the name of the reference as the output value.
- *
- * @param buffer_size Size of the `out` buffer in bytes.
+ * @param out Pointer to the user-allocated git_buf which will be
+ * filled with the name of the reference.
*
* @param repo the repository where the branches live
*
- * @param canonical_branch_name name of the local branch.
+ * @param refname reference name of the local branch.
*
- * @return number of characters in the reference name
- * including the trailing NUL byte; GIT_ENOTFOUND when no remote tracking
- * reference exists, otherwise an error code.
+ * @return 0, GIT_ENOTFOUND when no remote tracking reference exists,
+ * otherwise an error code.
*/
GIT_EXTERN(int) git_branch_upstream_name(
- char *tracking_branch_name_out,
- size_t buffer_size,
+ git_buf *out,
git_repository *repo,
- const char *canonical_branch_name);
+ const char *refname);
/**
* Determine if the current local branch is pointed at by HEAD.
@@ -234,25 +243,19 @@ GIT_EXTERN(int) git_branch_is_head(
/**
* Return the name of remote that the remote tracking branch belongs to.
*
- * @param remote_name_out The user-allocated buffer which will be
- * filled with the name of the remote. Pass NULL if you just want to
- * get the needed size of the name of the remote as the output value.
- *
- * @param buffer_size Size of the `out` buffer in bytes.
+ * @param out Pointer to the user-allocated git_buf which will be filled iwth the name of the remote.
*
* @param repo The repository where the branch lives.
*
* @param canonical_branch_name name of the remote tracking branch.
*
- * @return Number of characters in the reference name
- * including the trailing NUL byte; GIT_ENOTFOUND
+ * @return 0, GIT_ENOTFOUND
* when no remote matching remote was found,
* GIT_EAMBIGUOUS when the branch maps to several remotes,
* otherwise an error code.
*/
GIT_EXTERN(int) git_branch_remote_name(
- char *remote_name_out,
- size_t buffer_size,
+ git_buf *out,
git_repository *repo,
const char *canonical_branch_name);
diff --git a/include/git2/checkout.h b/include/git2/checkout.h
index b94a5e2ff..0faf4ab14 100644
--- a/include/git2/checkout.h
+++ b/include/git2/checkout.h
@@ -152,6 +152,12 @@ typedef enum {
/** Don't overwrite ignored files that exist in the checkout target */
GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = (1u << 19),
+ /** Write normal merge files for conflicts */
+ GIT_CHECKOUT_CONFLICT_STYLE_MERGE = (1u << 20),
+
+ /** Include common ancestor data in diff3 format files for conflicts */
+ GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = (1u << 21),
+
/**
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
*/
@@ -252,6 +258,7 @@ typedef struct git_checkout_opts {
const char *target_directory; /** alternative checkout path to workdir */
+ const char *ancestor_label; /** the name of the common ancestor side of conflicts */
const char *our_label; /** the name of the "our" side of conflicts */
const char *their_label; /** the name of the "their" side of conflicts */
} git_checkout_opts;
diff --git a/include/git2/clone.h b/include/git2/clone.h
index 59a73aa15..3e885d103 100644
--- a/include/git2/clone.h
+++ b/include/git2/clone.h
@@ -45,6 +45,8 @@ GIT_BEGIN_DECL
* default is "origin".
* - `checkout_branch` gives the name of the branch to checkout. NULL
* means use the remote's HEAD.
+ * - `signature` is the identity used when updating the reflog. NULL means to
+ * use the default signature using the config.
*/
typedef struct git_clone_options {
@@ -57,6 +59,7 @@ typedef struct git_clone_options {
int ignore_cert_errors;
const char *remote_name;
const char* checkout_branch;
+ git_signature *signature;
} git_clone_options;
#define GIT_CLONE_OPTIONS_VERSION 1
@@ -96,6 +99,7 @@ GIT_EXTERN(int) git_clone(
* @param co_opts options to use during checkout
* @param branch the branch to checkout after the clone, pass NULL for the
* remote's default branch
+ * @param signature The identity used when updating the reflog.
* @return 0 on success, any non-zero return value from a callback
* function, or a negative value to indicate an error (use
* `giterr_last` for a detailed error message)
@@ -104,7 +108,8 @@ GIT_EXTERN(int) git_clone_into(
git_repository *repo,
git_remote *remote,
const git_checkout_opts *co_opts,
- const char *branch);
+ const char *branch,
+ const git_signature *signature);
/** @} */
GIT_END_DECL
diff --git a/include/git2/config.h b/include/git2/config.h
index f650f1b41..663b4f6ba 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -9,6 +9,7 @@
#include "common.h"
#include "types.h"
+#include "buffer.h"
/**
* @file git2/config.h
@@ -90,11 +91,10 @@ typedef struct {
* This method will not guess the path to the xdg compatible
* config file (.config/git/config).
*
- * @param out Buffer to store the path in
- * @param length size of the buffer in bytes
- * @return 0 if a global configuration file has been found. Its path will be stored in `buffer`.
+ * @param out Pointer to a user-allocated git_buf in which to store the path
+ * @return 0 if a global configuration file has been found. Its path will be stored in `out`.
*/
-GIT_EXTERN(int) git_config_find_global(char *out, size_t length);
+GIT_EXTERN(int) git_config_find_global(git_buf *out);
/**
* Locate the path to the global xdg compatible configuration file
@@ -107,25 +107,23 @@ GIT_EXTERN(int) git_config_find_global(char *out, size_t length);
* may be used on any `git_config` call to load the
* xdg compatible configuration file.
*
- * @param out Buffer to store the path in
- * @param length size of the buffer in bytes
+ * @param out Pointer to a user-allocated git_buf in which to store the path
* @return 0 if a xdg compatible configuration file has been
- * found. Its path will be stored in `buffer`.
+ * found. Its path will be stored in `out`.
*/
-GIT_EXTERN(int) git_config_find_xdg(char *out, size_t length);
+GIT_EXTERN(int) git_config_find_xdg(git_buf *out);
/**
* Locate the path to the system configuration file
*
* If /etc/gitconfig doesn't exist, it will look for
* %PROGRAMFILES%\Git\etc\gitconfig.
-
- * @param out Buffer to store the path in
- * @param length size of the buffer in bytes
+ *
+ * @param out Pointer to a user-allocated git_buf in which to store the path
* @return 0 if a system configuration file has been
- * found. Its path will be stored in `buffer`.
+ * found. Its path will be stored in `out`.
*/
-GIT_EXTERN(int) git_config_find_system(char *out, size_t length);
+GIT_EXTERN(int) git_config_find_system(git_buf *out);
/**
* Open the global, XDG and system configuration files
diff --git a/include/git2/diff.h b/include/git2/diff.h
index 76fb23654..a3cdd8193 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -203,7 +203,7 @@ typedef struct git_diff git_diff;
typedef enum {
GIT_DIFF_FLAG_BINARY = (1u << 0), /** file(s) treated as binary data */
GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /** file(s) treated as text data */
- GIT_DIFF_FLAG_VALID_OID = (1u << 2), /** `oid` value is known correct */
+ GIT_DIFF_FLAG_VALID_ID = (1u << 2), /** `id` value is known correct */
} git_diff_flag_t;
/**
@@ -250,7 +250,7 @@ typedef enum {
* be restricted to one of the `git_filemode_t` values.
*/
typedef struct {
- git_oid oid;
+ git_oid id;
const char *path;
git_off_t size;
uint32_t flags;
@@ -361,7 +361,7 @@ typedef struct {
uint16_t context_lines; /**< defaults to 3 */
uint16_t interhunk_lines; /**< defaults to 0 */
- uint16_t oid_abbrev; /**< default 'core.abbrev' or 7 if unset */
+ uint16_t id_abbrev; /**< default 'core.abbrev' or 7 if unset */
git_off_t max_size; /**< defaults to 512MB */
const char *old_prefix; /**< defaults to "a" */
const char *new_prefix; /**< defaults to "b" */
diff --git a/include/git2/graph.h b/include/git2/graph.h
index a2710219e..c997d8ca9 100644
--- a/include/git2/graph.h
+++ b/include/git2/graph.h
@@ -36,6 +36,20 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(int) git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, const git_oid *local, const git_oid *upstream);
+
+/**
+ * Determine if a commit is the descendant of another commit.
+ *
+ * @param commit a previously loaded commit.
+ * @param ancestor a potential ancestor commit.
+ * @return 1 if the given commit is a descendant of the potential ancestor,
+ * 0 if not, error code otherwise.
+ */
+GIT_EXTERN(int) git_graph_descendant_of(
+ git_repository *repo,
+ const git_oid *commit,
+ const git_oid *ancestor);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/index.h b/include/git2/index.h
index ffefad15d..4363a3b9b 100644
--- a/include/git2/index.h
+++ b/include/git2/index.h
@@ -56,7 +56,7 @@ typedef struct git_index_entry {
unsigned int gid;
git_off_t file_size;
- git_oid oid;
+ git_oid id;
unsigned short flags;
unsigned short flags_extended;
diff --git a/include/git2/merge.h b/include/git2/merge.h
index 8a1dfec2e..3ef27e3c7 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -32,14 +32,21 @@ typedef enum {
} git_merge_tree_flag_t;
/**
- * Automerge options for `git_merge_trees_opts`.
+ * Merge file options for `git_merge_trees_opts`.
*/
typedef enum {
- GIT_MERGE_AUTOMERGE_NORMAL = 0,
- GIT_MERGE_AUTOMERGE_NONE = 1,
- GIT_MERGE_AUTOMERGE_FAVOR_OURS = 2,
- GIT_MERGE_AUTOMERGE_FAVOR_THEIRS = 3,
-} git_merge_automerge_flags;
+ /* Produce a conflict in a file when two similar regions are changed. */
+ GIT_MERGE_FILE_FAVOR_NORMAL = 0,
+
+ /* Produce a file containing the "ours" side of conflicting regions. */
+ GIT_MERGE_FILE_FAVOR_OURS = 1,
+
+ /* Produce a file containing the "theirs" side of conflicting regions. */
+ GIT_MERGE_FILE_FAVOR_THEIRS = 2,
+
+ /* Produce a file blending the sides in a union of conflicting regions */
+ GIT_MERGE_FILE_FAVOR_UNION = 3,
+} git_merge_file_favor_t;
typedef struct {
@@ -58,7 +65,7 @@ typedef struct {
git_diff_similarity_metric *metric;
/** Flags for automerging content. */
- git_merge_automerge_flags automerge_flags;
+ git_merge_file_favor_t file_favor;
} git_merge_tree_opts;
#define GIT_MERGE_TREE_OPTS_VERSION 1
@@ -153,13 +160,13 @@ GIT_EXTERN(int) git_merge_head_from_fetchhead(
*
* @param out pointer to store the git_merge_head result in
* @param repo repository that contains the given commit
- * @param oid the commit object id to use as a merge input
+ * @param id the commit object id to use as a merge input
* @return zero on success, -1 on failure.
*/
-GIT_EXTERN(int) git_merge_head_from_oid(
+GIT_EXTERN(int) git_merge_head_from_id(
git_merge_head **out,
git_repository *repo,
- const git_oid *oid);
+ const git_oid *id);
/**
* Frees a `git_merge_head`
@@ -244,7 +251,7 @@ GIT_EXTERN(int) git_merge_result_is_fastforward(git_merge_result *merge_result);
* @param out the OID of the fast-forward
* @param merge_result the results of the merge
*/
-GIT_EXTERN(int) git_merge_result_fastforward_oid(git_oid *out, git_merge_result *merge_result);
+GIT_EXTERN(int) git_merge_result_fastforward_id(git_oid *out, git_merge_result *merge_result);
GIT_EXTERN(void) git_merge_result_free(git_merge_result *merge_result);
diff --git a/include/git2/message.h b/include/git2/message.h
index 395c88690..bcdb72f6a 100644
--- a/include/git2/message.h
+++ b/include/git2/message.h
@@ -8,6 +8,7 @@
#define INCLUDE_git_message_h__
#include "common.h"
+#include "buffer.h"
/**
* @file git2/message.h
@@ -23,25 +24,17 @@ GIT_BEGIN_DECL
*
* Optionally, can remove lines starting with a "#".
*
- * @param out The user-allocated buffer which will be filled with the
- * cleaned up message. Pass NULL if you just want to get the needed
- * size of the prettified message as the output value.
- *
- * @param out_size Size of the `out` buffer in bytes.
+ * @param out The user-allocated git_buf which will be filled with the
+ * cleaned up message.
*
* @param message The message to be prettified.
*
* @param strip_comments Non-zero to remove lines starting with "#", 0 to
* leave them in.
*
- * @return -1 on error, else number of characters in prettified message
- * including the trailing NUL byte
+ * @return 0 or an error code.
*/
-GIT_EXTERN(int) git_message_prettify(
- char *out,
- size_t out_size,
- const char *message,
- int strip_comments);
+GIT_EXTERN(int) git_message_prettify(git_buf *out, const char *message, int strip_comments);
/** @} */
GIT_END_DECL
diff --git a/include/git2/notes.h b/include/git2/notes.h
index 0cb6ce5f1..98eb2aef3 100644
--- a/include/git2/notes.h
+++ b/include/git2/notes.h
@@ -106,12 +106,12 @@ GIT_EXTERN(const char *) git_note_message(const git_note *note);
/**
- * Get the note object OID
+ * Get the note object's id
*
* @param note the note
- * @return the note object OID
+ * @return the note object's id
*/
-GIT_EXTERN(const git_oid *) git_note_oid(const git_note *note);
+GIT_EXTERN(const git_oid *) git_note_id(const git_note *note);
/**
* Add a note for an object
diff --git a/include/git2/patch.h b/include/git2/patch.h
index e09f625c0..1eca29d4a 100644
--- a/include/git2/patch.h
+++ b/include/git2/patch.h
@@ -234,15 +234,14 @@ GIT_EXTERN(int) git_patch_print(
/**
* Get the content of a patch as a single diff text.
*
- * @param string Allocated string; caller must free.
+ * @param out The git_buf to be filled in
* @param patch A git_patch representing changes to one file
* @return 0 on success, <0 on failure.
*/
-GIT_EXTERN(int) git_patch_to_str(
- char **string,
+GIT_EXTERN(int) git_patch_to_buf(
+ git_buf *out,
git_patch *patch);
-
GIT_END_DECL
/**@}*/
diff --git a/include/git2/refs.h b/include/git2/refs.h
index 1df42fead..f9aaea827 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -27,7 +27,7 @@ GIT_BEGIN_DECL
* The returned reference must be freed by the user.
*
* The name will be checked for validity.
- * See `git_reference_create_symbolic()` for rules about valid names.
+ * See `git_reference_symbolic_create()` for rules about valid names.
*
* @param out pointer to the looked-up reference
* @param repo the repository to look up the reference
@@ -89,37 +89,9 @@ GIT_EXTERN(int) git_reference_dwim(git_reference **out, git_repository *repo, co
* This function will return an error if a reference already exists with the
* given name unless `force` is true, in which case it will be overwritten.
*
- * @param out Pointer to the newly created reference
- * @param repo Repository where that reference will live
- * @param name The name of the reference
- * @param target The target of the reference
- * @param force Overwrite existing references
- * @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code
- */
-GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repository *repo, const char *name, const char *target, int force);
-
-/**
- * Create a new symbolic reference and update the reflog with a given
- * message.
- *
- * A symbolic reference is a reference name that refers to another
- * reference name. If the other name moves, the symbolic name will move,
- * too. As a simple example, the "HEAD" reference might refer to
- * "refs/heads/master" while on the "master" branch of a repository.
- *
- * The symbolic reference will be created in the repository and written to
- * the disk. The generated reference object must be freed by the user.
- *
- * Valid reference names must follow one of two patterns:
- *
- * 1. Top-level names must contain only capital letters and underscores,
- * and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD").
- * 2. Names prefixed with "refs/" can be almost anything. You must avoid
- * the characters '~', '^', ':', '\\', '?', '[', and '*', and the
- * sequences ".." and "@{" which have special meaning to revparse.
- *
- * This function will return an error if a reference already exists with the
- * given name unless `force` is true, in which case it will be overwritten.
+ * The signature and message for the reflog will be ignored if the
+ * reference does not belong in the standard set (HEAD, branches and
+ * remote-tracking branches) and it does not have a reflog.
*
* @param out Pointer to the newly created reference
* @param repo Repository where that reference will live
@@ -127,18 +99,10 @@ GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repositor
* @param target The target of the reference
* @param force Overwrite existing references
* @param signature The identity that will used to populate the reflog entry
- * @param log_message The one line long message that has to be appended
- * to the reflog
- * @return 0 on success, EEXISTS, EINVALIDSPEC or an error code
+ * @param log_message The one line long message to be appended to the reflog
+ * @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code
*/
-GIT_EXTERN(int) git_reference_symbolic_create_with_log(
- git_reference **out,
- git_repository *repo,
- const char *name,
- const char *target,
- int force,
- const git_signature *signature,
- const char *log_message);
+GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repository *repo, const char *name, const char *target, int force, const git_signature *signature, const char *log_message);
/**
* Create a new direct reference.
@@ -163,57 +127,21 @@ GIT_EXTERN(int) git_reference_symbolic_create_with_log(
* This function will return an error if a reference already exists with the
* given name unless `force` is true, in which case it will be overwritten.
*
- * @param out Pointer to the newly created reference
- * @param repo Repository where that reference will live
- * @param name The name of the reference
- * @param id The object id pointed to by the reference.
- * @param force Overwrite existing references
- * @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code
- */
-GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force);
-
-/**
- * Create a new direct reference and update the reflog with a given
- * message.
- *
- * A direct reference (also called an object id reference) refers directly
- * to a specific object id (a.k.a. OID or SHA) in the repository. The id
- * permanently refers to the object (although the reference itself can be
- * moved). For example, in libgit2 the direct ref "refs/tags/v0.17.0"
- * refers to OID 5b9fac39d8a76b9139667c26a63e6b3f204b3977.
- *
- * The direct reference will be created in the repository and written to
- * the disk. The generated reference object must be freed by the user.
- *
- * Valid reference names must follow one of two patterns:
- *
- * 1. Top-level names must contain only capital letters and underscores,
- * and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD").
- * 2. Names prefixed with "refs/" can be almost anything. You must avoid
- * the characters '~', '^', ':', '\\', '?', '[', and '*', and the
- * sequences ".." and "@{" which have special meaning to revparse.
- *
- * This function will return an error if a reference already exists with the
- * given name unless `force` is true, in which case it will be overwritten.
+ * The signature and message for the reflog will be ignored if the
+ * reference does not belong in the standard set (HEAD, branches and
+ * remote-tracking branches) and and it does not have a reflog.
*
* @param out Pointer to the newly created reference
* @param repo Repository where that reference will live
* @param name The name of the reference
* @param id The object id pointed to by the reference.
* @param force Overwrite existing references
+ * @param force Overwrite existing references
* @param signature The identity that will used to populate the reflog entry
- * @param log_message The one line long message that has to be appended
- * to the reflog
- * @return 0 on success, EEXISTS, EINVALIDSPEC or an error code
+ * @param log_message The one line long message to be appended to the reflog
+ * @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code
*/
-GIT_EXTERN(int) git_reference_create_with_log(
- git_reference **out,
- git_repository *repo,
- const char *name,
- const git_oid *id,
- int force,
- const git_signature *signature,
- const char *log_message);
+GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force, const git_signature *signature, const char *log_message);
/**
* Get the OID pointed to by a direct reference.
@@ -264,7 +192,7 @@ GIT_EXTERN(git_ref_t) git_reference_type(const git_reference *ref);
/**
* Get the full name of a reference.
*
- * See `git_reference_create_symbolic()` for rules about valid names.
+ * See `git_reference_symbolic_create()` for rules about valid names.
*
* @param ref The reference
* @return the full name for the ref
@@ -305,37 +233,20 @@ GIT_EXTERN(git_repository *) git_reference_owner(const git_reference *ref);
* The new reference will be written to disk, overwriting the given reference.
*
* The target name will be checked for validity.
- * See `git_reference_create_symbolic()` for rules about valid names.
- *
- * @param out Pointer to the newly created reference
- * @param ref The reference
- * @param target The new target for the reference
- * @return 0 on success, GIT_EINVALIDSPEC or an error code
- */
-GIT_EXTERN(int) git_reference_symbolic_set_target(
- git_reference **out,
- git_reference *ref,
- const char *target);
-
-/**
- * Create a new reference with the same name as the given reference but a
- * different symbolic target and update the reflog with a given message.
- *
- * The reference must be a symbolic reference, otherwise this will fail.
- *
- * The new reference will be written to disk, overwriting the given reference.
+ * See `git_reference_symbolic_create()` for rules about valid names.
*
- * The target name will be checked for validity.
- * See `git_reference_create_symbolic()` for rules about valid names.
+ * The signature and message for the reflog will be ignored if the
+ * reference does not belong in the standard set (HEAD, branches and
+ * remote-tracking branches) and and it does not have a reflog.
*
* @param out Pointer to the newly created reference
* @param ref The reference
* @param target The new target for the reference
* @param signature The identity that will used to populate the reflog entry
- * @param log_message The one line long message that has to be appended
- * @return 0 on success, EINVALIDSPEC or an error code
+ * @param log_message The one line long message to be appended to the reflog
+ * @return 0 on success, GIT_EINVALIDSPEC or an error code
*/
-GIT_EXTERN(int) git_reference_symbolic_set_target_with_log(
+GIT_EXTERN(int) git_reference_symbolic_set_target(
git_reference **out,
git_reference *ref,
const char *target,
@@ -349,33 +260,18 @@ GIT_EXTERN(int) git_reference_symbolic_set_target_with_log(
*
* The new reference will be written to disk, overwriting the given reference.
*
- * @param out Pointer to the newly created reference
- * @param ref The reference
- * @param id The new target OID for the reference
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_reference_set_target(
- git_reference **out,
- git_reference *ref,
- const git_oid *id);
-
-/**
- * Create a new reference with the same name as the given reference but a
- * different OID target and update the reflog with a given message.
- *
- * The reference must be a direct reference, otherwise this will fail.
- *
- * The new reference will be written to disk, overwriting the given reference.
+ * The signature and message for the reflog will be ignored if the
+ * reference does not belong in the standard set (HEAD, branches and
+ * remote-tracking branches) and and it does not have a reflog.
*
* @param out Pointer to the newly created reference
* @param ref The reference
* @param id The new target OID for the reference
* @param signature The identity that will used to populate the reflog entry
- * @param log_message The one line long message that has to be appended
- * to the reflog
+ * @param log_message The one line long message to be appended to the reflog
* @return 0 or an error code
*/
-GIT_EXTERN(int) git_reference_set_target_with_log(
+GIT_EXTERN(int) git_reference_set_target(
git_reference **out,
git_reference *ref,
const git_oid *id,
@@ -388,7 +284,7 @@ GIT_EXTERN(int) git_reference_set_target_with_log(
* This method works for both direct and symbolic references.
*
* The new name will be checked for validity.
- * See `git_reference_create_symbolic()` for rules about valid names.
+ * See `git_reference_symbolic_create()` for rules about valid names.
*
* If the `force` flag is not enabled, and there's already
* a reference with the given name, the renaming will fail.
@@ -401,6 +297,8 @@ GIT_EXTERN(int) git_reference_set_target_with_log(
* @param ref The reference to rename
* @param new_name The new name for the reference
* @param force Overwrite an existing reference
+ * @param signature The identity that will used to populate the reflog entry
+ * @param log_message The one line long message to be appended to the reflog
* @return 0 on success, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code
*
*/
@@ -408,7 +306,9 @@ GIT_EXTERN(int) git_reference_rename(
git_reference **new_ref,
git_reference *ref,
const char *new_name,
- int force);
+ int force,
+ const git_signature *signature,
+ const char *log_message);
/**
* Delete an existing reference.
@@ -610,6 +510,16 @@ GIT_EXTERN(int) git_reference_is_remote(git_reference *ref);
*/
GIT_EXTERN(int) git_reference_is_tag(git_reference *ref);
+/**
+ * Check if a reference is a note
+ *
+ * @param ref A git reference
+ *
+ * @return 1 when the reference lives in the refs/notes
+ * namespace; 0 otherwise.
+ */
+GIT_EXTERN(int) git_reference_is_note(git_reference *ref);
+
typedef enum {
GIT_REF_FORMAT_NORMAL = 0u,
@@ -648,7 +558,7 @@ typedef enum {
* Once normalized, if the reference name is valid, it will be returned in
* the user allocated buffer.
*
- * See `git_reference_create_symbolic()` for rules about valid names.
+ * See `git_reference_symbolic_create()` for rules about valid names.
*
* @param buffer_out User allocated buffer to store normalized name
* @param buffer_size Size of buffer_out
diff --git a/include/git2/refspec.h b/include/git2/refspec.h
index d96b83ce2..9acdc72d5 100644
--- a/include/git2/refspec.h
+++ b/include/git2/refspec.h
@@ -10,6 +10,7 @@
#include "common.h"
#include "types.h"
#include "net.h"
+#include "buffer.h"
/**
* @file git2/refspec.h
@@ -82,23 +83,21 @@ GIT_EXTERN(int) git_refspec_dst_matches(const git_refspec *refspec, const char *
* Transform a reference to its target following the refspec's rules
*
* @param out where to store the target name
- * @param outlen the size of the `out` buffer
* @param spec the refspec
* @param name the name of the reference to transform
* @return 0, GIT_EBUFS or another error
*/
-GIT_EXTERN(int) git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name);
+GIT_EXTERN(int) git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name);
/**
* Transform a target reference to its source reference following the refspec's rules
*
* @param out where to store the source reference name
- * @param outlen the size of the `out` buffer
* @param spec the refspec
* @param name the name of the reference to transform
* @return 0, GIT_EBUFS or another error
*/
-GIT_EXTERN(int) git_refspec_rtransform(char *out, size_t outlen, const git_refspec *spec, const char *name);
+GIT_EXTERN(int) git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name);
GIT_END_DECL
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 7410909dc..eba6ca7f9 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -108,6 +108,18 @@ GIT_EXTERN(int) git_remote_load(git_remote **out, git_repository *repo, const ch
GIT_EXTERN(int) git_remote_save(const git_remote *remote);
/**
+ * Create a copy of an existing remote. All internal strings are also
+ * duplicated. Callbacks are not duplicated.
+ *
+ * Call `git_remote_free` to free the data.
+ *
+ * @param dest pointer where to store the copy
+ * @param source object to copy
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_remote_dup(git_remote **dest, git_remote *source);
+
+/**
* Get the remote's repository
*
* @param remote the remote
@@ -182,7 +194,7 @@ GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec);
* @param array pointer to the array in which to store the strings
* @param remote the remote to query
*/
-GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, git_remote *remote);
+GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, const git_remote *remote);
/**
* Set the remote's list of fetch refspecs
@@ -215,7 +227,7 @@ GIT_EXTERN(int) git_remote_add_push(git_remote *remote, const char *refspec);
* @param array pointer to the array in which to store the strings
* @param remote the remote to query
*/
-GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, git_remote *remote);
+GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, const git_remote *remote);
/**
* Set the remote's list of push refspecs
@@ -242,7 +254,7 @@ GIT_EXTERN(void) git_remote_clear_refspecs(git_remote *remote);
* @param remote the remote
* @return the amount of refspecs configured in this remote
*/
-GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote);
+GIT_EXTERN(size_t) git_remote_refspec_count(const git_remote *remote);
/**
* Get a refspec from the remote
@@ -251,7 +263,7 @@ GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote);
* @param n the refspec to get
* @return the nth refspec
*/
-GIT_EXTERN(const git_refspec *)git_remote_get_refspec(git_remote *remote, size_t n);
+GIT_EXTERN(const git_refspec *)git_remote_get_refspec(const git_remote *remote, size_t n);
/**
* Open a connection to a remote
@@ -307,7 +319,7 @@ GIT_EXTERN(int) git_remote_download(git_remote *remote);
* @param remote the remote
* @return 1 if it's connected, 0 otherwise.
*/
-GIT_EXTERN(int) git_remote_connected(git_remote *remote);
+GIT_EXTERN(int) git_remote_connected(const git_remote *remote);
/**
* Cancel the operation
@@ -498,7 +510,7 @@ typedef enum {
* @param remote the remote to query
* @return the auto-follow setting
*/
-GIT_EXTERN(git_remote_autotag_option_t) git_remote_autotag(git_remote *remote);
+GIT_EXTERN(git_remote_autotag_option_t) git_remote_autotag(const git_remote *remote);
/**
* Set the tag auto-follow setting
diff --git a/include/git2/repository.h b/include/git2/repository.h
index 9f71d2959..648667cd6 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -10,6 +10,7 @@
#include "common.h"
#include "types.h"
#include "oid.h"
+#include "buffer.h"
/**
* @file git2/repository.h
@@ -58,10 +59,8 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb);
* The method will automatically detect if the repository is bare
* (if there is a repository).
*
- * @param path_out The user allocated buffer which will
- * contain the found path.
- *
- * @param path_size repository_path size
+ * @param out A pointer to a user-allocated git_buf which will contain
+ * the found path.
*
* @param start_path The base path where the lookup starts.
*
@@ -77,8 +76,7 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb);
* @return 0 or an error code
*/
GIT_EXTERN(int) git_repository_discover(
- char *path_out,
- size_t path_size,
+ git_buf *out,
const char *start_path,
int across_fs,
const char *ceiling_dirs);
@@ -464,21 +462,11 @@ GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo);
* Use this function to get the contents of this file. Don't forget to
* remove the file after you create the commit.
*
- * If the repository message exists and there are no errors reading it, this
- * returns the bytes needed to store the message in memory (i.e. message
- * file size plus one terminating NUL byte). That value is returned even if
- * `out` is NULL or `len` is shorter than the necessary size.
- *
- * The `out` buffer will *always* be NUL terminated, even if truncation
- * occurs.
- *
- * @param out Buffer to write data into or NULL to just read required size
- * @param len Length of `out` buffer in bytes
+ * @param out git_buf to write data into
* @param repo Repository to read prepared message from
- * @return GIT_ENOTFOUND if no message exists, other value < 0 for other
- * errors, or total bytes in message (may be > `len`) on success
+ * @return 0, GIT_ENOTFOUND if no message exists or an error code
*/
-GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *repo);
+GIT_EXTERN(int) git_repository_message(git_buf *out, git_repository *repo);
/**
* Remove git's prepared message.
@@ -579,11 +567,15 @@ GIT_EXTERN(int) git_repository_hashfile(
*
* @param repo Repository pointer
* @param refname Canonical name of the reference the HEAD should point at
+ * @param signature The identity that will used to populate the reflog entry
+ * @param log_message The one line long message to be appended to the reflog
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_set_head(
git_repository* repo,
- const char* refname);
+ const char* refname,
+ const git_signature *signature,
+ const char *log_message);
/**
* Make the repository HEAD directly point to the Commit.
@@ -599,11 +591,15 @@ GIT_EXTERN(int) git_repository_set_head(
*
* @param repo Repository pointer
* @param commitish Object id of the Commit the HEAD should point to
+ * @param signature The identity that will used to populate the reflog entry
+ * @param log_message The one line long message to be appended to the reflog
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_set_head_detached(
git_repository* repo,
- const git_oid* commitish);
+ const git_oid* commitish,
+ const git_signature *signature,
+ const char *log_message);
/**
* Detach the HEAD.
diff --git a/include/git2/revwalk.h b/include/git2/revwalk.h
index c59b79938..aef0b5fa6 100644
--- a/include/git2/revwalk.h
+++ b/include/git2/revwalk.h
@@ -87,7 +87,7 @@ GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker);
/**
* Mark a commit to start traversal from.
*
- * The given OID must belong to a commit on the walked
+ * The given OID must belong to a committish on the walked
* repository.
*
* The given commit will be used as one of the roots
@@ -108,7 +108,10 @@ GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *id);
* pattern will be pushed to the revision walker.
*
* A leading 'refs/' is implied if not present as well as a trailing
- * '/ *' if the glob lacks '?', '*' or '['.
+ * '/\*' if the glob lacks '?', '\*' or '['.
+ *
+ * Any references matching this glob which do not point to a
+ * committish will be ignored.
*
* @param walk the walker being used for the traversal
* @param glob the glob pattern references should match
@@ -127,7 +130,7 @@ GIT_EXTERN(int) git_revwalk_push_head(git_revwalk *walk);
/**
* Mark a commit (and its ancestors) uninteresting for the output.
*
- * The given OID must belong to a commit on the walked
+ * The given OID must belong to a committish on the walked
* repository.
*
* The resolved commit and all its parents will be hidden from the
@@ -147,7 +150,10 @@ GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *commit_id);
* revision walk.
*
* A leading 'refs/' is implied if not present as well as a trailing
- * '/ *' if the glob lacks '?', '*' or '['.
+ * '/\*' if the glob lacks '?', '\*' or '['.
+ *
+ * Any references matching this glob which do not point to a
+ * committish will be ignored.
*
* @param walk the walker being used for the traversal
* @param glob the glob pattern references should match
@@ -166,7 +172,7 @@ GIT_EXTERN(int) git_revwalk_hide_head(git_revwalk *walk);
/**
* Push the OID pointed to by a reference
*
- * The reference must point to a commit.
+ * The reference must point to a committish.
*
* @param walk the walker being used for the traversal
* @param refname the reference to push
@@ -177,7 +183,7 @@ GIT_EXTERN(int) git_revwalk_push_ref(git_revwalk *walk, const char *refname);
/**
* Hide the OID pointed to by a reference
*
- * The reference must point to a commit.
+ * The reference must point to a committish.
*
* @param walk the walker being used for the traversal
* @param refname the reference to hide
diff --git a/include/git2/signature.h b/include/git2/signature.h
index 2fa46d032..a1dd1ec7a 100644
--- a/include/git2/signature.h
+++ b/include/git2/signature.h
@@ -68,10 +68,11 @@ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo)
*
* Call `git_signature_free()` to free the data.
*
- * @param sig signature to duplicated
- * @return a copy of sig, NULL on out of memory
+ * @param dest pointer where to store the copy
+ * @param entry signature to duplicate
+ * @return 0 or an error code
*/
-GIT_EXTERN(git_signature *) git_signature_dup(const git_signature *sig);
+GIT_EXTERN(int) git_signature_dup(git_signature **dest, const git_signature *sig);
/**
* Free an existing signature.
diff --git a/include/git2/submodule.h b/include/git2/submodule.h
index 4b4ba6eef..d72432610 100644
--- a/include/git2/submodule.h
+++ b/include/git2/submodule.h
@@ -97,7 +97,8 @@ typedef enum {
(((S) & GIT_SUBMODULE_STATUS__INDEX_FLAGS) == 0)
#define GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(S) \
- (((S) & GIT_SUBMODULE_STATUS__WD_FLAGS) == 0)
+ (((S) & (GIT_SUBMODULE_STATUS__WD_FLAGS & \
+ ~GIT_SUBMODULE_STATUS_WD_UNINITIALIZED)) == 0)
#define GIT_SUBMODULE_STATUS_IS_WD_DIRTY(S) \
(((S) & (GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED | \
@@ -105,19 +106,6 @@ typedef enum {
GIT_SUBMODULE_STATUS_WD_UNTRACKED)) != 0)
/**
- * Options for submodule recurse.
- *
- * * GIT_SUBMODULE_RECURSE_NO - do no recurse into submodules
- * * GIT_SUBMODULE_RECURSE_YES - recurse into submodules
- * * GIT_SUBMODULE_RECURSE_ONDEMAND - recurse into submodules only when commit not already in local clone
- */
-typedef enum {
- GIT_SUBMODULE_RECURSE_NO = 0,
- GIT_SUBMODULE_RECURSE_YES = 1,
- GIT_SUBMODULE_RECURSE_ONDEMAND = 2,
-} git_submodule_recurse_t;
-
-/**
* Lookup submodule information by name or path.
*
* Given either the submodule name or path (they are usually the same), this
@@ -284,6 +272,14 @@ GIT_EXTERN(const char *) git_submodule_path(git_submodule *submodule);
GIT_EXTERN(const char *) git_submodule_url(git_submodule *submodule);
/**
+* Get the branch for the submodule.
+*
+* @param submodule Pointer to submodule object
+* @return Pointer to the submodule branch
+*/
+GIT_EXTERN(const char *) git_submodule_branch(git_submodule *submodule);
+
+/**
* Set the URL for the submodule.
*
* This sets the URL in memory for the submodule. This will be used for
diff --git a/include/git2/sys/commit.h b/include/git2/sys/commit.h
index 34a12fb15..c8ed56b66 100644
--- a/include/git2/sys/commit.h
+++ b/include/git2/sys/commit.h
@@ -29,7 +29,7 @@ GIT_BEGIN_DECL
* the `tree`, neither the `parents` list of `git_oid`s are checked for
* validity.
*/
-GIT_EXTERN(int) git_commit_create_from_oids(
+GIT_EXTERN(int) git_commit_create_from_ids(
git_oid *oid,
git_repository *repo,
const char *update_ref,
diff --git a/include/git2/tree.h b/include/git2/tree.h
index 422365674..6669652ae 100644
--- a/include/git2/tree.h
+++ b/include/git2/tree.h
@@ -121,11 +121,11 @@ GIT_EXTERN(const git_tree_entry *) git_tree_entry_byindex(
* Warning: this must examine every entry in the tree, so it is not fast.
*
* @param tree a previously loaded tree.
- * @param oid the sha being looked for
+ * @param id the sha being looked for
* @return the tree entry; NULL if not found
*/
-GIT_EXTERN(const git_tree_entry *) git_tree_entry_byoid(
- const git_tree *tree, const git_oid *oid);
+GIT_EXTERN(const git_tree_entry *) git_tree_entry_byid(
+ const git_tree *tree, const git_oid *id);
/**
* Retrieve a tree entry contained in a tree or in any of its subtrees,
@@ -150,10 +150,11 @@ GIT_EXTERN(int) git_tree_entry_bypath(
* Create a copy of a tree entry. The returned copy is owned by the user,
* and must be freed explicitly with `git_tree_entry_free()`.
*
- * @param entry A tree entry to duplicate
- * @return a copy of the original entry or NULL on error (alloc failure)
+ * @param dest pointer where to store the copy
+ * @param entry tree entry to duplicate
+ * @return 0 or an error code
*/
-GIT_EXTERN(git_tree_entry *) git_tree_entry_dup(const git_tree_entry *entry);
+GIT_EXTERN(int) git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source);
/**
* Free a user-owned tree entry
diff --git a/include/git2/types.h b/include/git2/types.h
index 55505b110..2229f6bf4 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -131,7 +131,7 @@ typedef struct git_treebuilder git_treebuilder;
/** Memory representation of an index file. */
typedef struct git_index git_index;
-/** An interator for conflicts in the index. */
+/** An iterator for conflicts in the index. */
typedef struct git_index_conflict_iterator git_index_conflict_iterator;
/** Memory representation of a set of config files */
@@ -323,6 +323,25 @@ typedef enum {
GIT_SUBMODULE_IGNORE_DEFAULT = 0
} git_submodule_ignore_t;
+/**
+ * Options for submodule recurse.
+ *
+ * Represent the value of `submodule.$name.fetchRecurseSubmodules`
+ *
+ * * GIT_SUBMODULE_RECURSE_RESET - reset to the on-disk value
+ * * GIT_SUBMODULE_RECURSE_NO - do no recurse into submodules
+ * * GIT_SUBMODULE_RECURSE_YES - recurse into submodules
+ * * GIT_SUBMODULE_RECURSE_ONDEMAND - recurse into submodules only when
+ * commit not already in local clone
+ */
+typedef enum {
+ GIT_SUBMODULE_RECURSE_RESET = -1,
+
+ GIT_SUBMODULE_RECURSE_NO = 0,
+ GIT_SUBMODULE_RECURSE_YES = 1,
+ GIT_SUBMODULE_RECURSE_ONDEMAND = 2,
+} git_submodule_recurse_t;
+
/** @} */
GIT_END_DECL
diff --git a/script/cibuild.sh b/script/cibuild.sh
index aa4fa47aa..5c0584a80 100755
--- a/script/cibuild.sh
+++ b/script/cibuild.sh
@@ -1,5 +1,11 @@
#!/bin/sh
+if [ "$COVERITY" -eq 1 ];
+then
+ ./script/coverity.sh;
+ exit $?;
+fi
+
# Create a test repo which we can use for the online::push tests
mkdir $HOME/_temp
git init --bare $HOME/_temp/test.git
diff --git a/script/coverity.sh b/script/coverity.sh
new file mode 100755
index 000000000..e72008883
--- /dev/null
+++ b/script/coverity.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+set -e
+
+# Environment check
+[ -z "$COVERITY_TOKEN" ] && echo "Need to set a coverity token" && exit 1
+
+# Only run this on our branches
+echo "Pull request: $TRAVIS_PULL_REQUEST | Slug: $TRAVIS_REPO_SLUG"
+if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_REPO_SLUG" != "libgit2/libgit2" ];
+then
+ echo "Only analyzing 'development' on the main repo."
+ exit 0
+fi
+
+COV_VERSION=6.6.1
+case `uname -m` in
+ i?86) BITS=32 ;;
+ amd64|x86_64) BITS=64 ;;
+esac
+SCAN_TOOL=https://scan.coverity.com/download/linux-${BITS}
+TOOL_BASE=`pwd`/_coverity-scan
+
+# Install coverity tools
+if [ ! -d $TOOL_BASE ]; then
+ echo "Downloading coverity..."
+ mkdir -p $TOOL_BASE
+ cd $TOOL_BASE
+ wget -O coverity_tool.tgz $SCAN_TOOL \
+ --post-data "project=libgit2&token=$COVERITY_TOKEN"
+ tar xzf coverity_tool.tgz
+ cd ..
+ TOOL_DIR=`find $TOOL_BASE -type d -name 'cov-analysis*'`
+ ln -s $TOOL_DIR $TOOL_BASE/cov-analysis
+fi
+
+COV_BUILD="$TOOL_BASE/cov-analysis/bin/cov-build"
+
+# Configure and build
+rm -rf _build
+mkdir _build
+cd _build
+cmake .. -DTHREADSAFE=ON
+COVERITY_UNSUPPORTED=1 \
+ $COV_BUILD --dir cov-int \
+ cmake --build .
+
+# Upload results
+tar czf libgit2.tgz cov-int
+SHA=`git rev-parse --short HEAD`
+curl \
+ --form project=libgit2 \
+ --form token=$COVERITY_TOKEN \
+ --form email=bs@github.com \
+ --form file=@libgit2.tgz \
+ --form version=$SHA \
+ --form description="Travis build" \
+ http://scan5.coverity.com/cgi-bin/upload.py
diff --git a/src/attr.c b/src/attr.c
index e6e274e42..15ed5c9e0 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -49,6 +49,8 @@ int git_attr_get(
git_attr_name attr;
git_attr_rule *rule;
+ assert(value && repo && name);
+
*value = NULL;
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
@@ -103,6 +105,11 @@ int git_attr_get_many(
attr_get_many_info *info = NULL;
size_t num_found = 0;
+ if (!num_attr)
+ return 0;
+
+ assert(values && repo && names);
+
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
return -1;
@@ -169,6 +176,8 @@ int git_attr_foreach(
git_attr_assignment *assign;
git_strmap *seen = NULL;
+ assert(repo && callback);
+
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
return -1;
@@ -314,10 +323,10 @@ static int load_attr_blob_from_index(
entry = git_index_get_byindex(index, pos);
- if (old_oid && git_oid__cmp(old_oid, &entry->oid) == 0)
+ if (old_oid && git_oid__cmp(old_oid, &entry->id) == 0)
return GIT_ENOTFOUND;
- if ((error = git_blob_lookup(blob, repo, &entry->oid)) < 0)
+ if ((error = git_blob_lookup(blob, repo, &entry->id)) < 0)
return error;
*content = git_blob_rawcontent(*blob);
diff --git a/src/blame.c b/src/blame.c
index a1357415a..71bc460c6 100644
--- a/src/blame.c
+++ b/src/blame.c
@@ -76,8 +76,8 @@ static git_blame_hunk* dup_hunk(git_blame_hunk *hunk)
git_oid_cpy(&newhunk->orig_commit_id, &hunk->orig_commit_id);
git_oid_cpy(&newhunk->final_commit_id, &hunk->final_commit_id);
newhunk->boundary = hunk->boundary;
- newhunk->final_signature = git_signature_dup(hunk->final_signature);
- newhunk->orig_signature = git_signature_dup(hunk->orig_signature);
+ git_signature_dup(&newhunk->final_signature, hunk->final_signature);
+ git_signature_dup(&newhunk->orig_signature, hunk->orig_signature);
return newhunk;
}
@@ -121,7 +121,6 @@ git_blame* git_blame__alloc(
git_vector_insert(&gbr->paths, git__strdup(path)) < 0)
{
git_blame_free(gbr);
- git__free(gbr);
return NULL;
}
@@ -242,7 +241,7 @@ static int index_blob_lines(git_blame *blame)
git_off_t len = blame->final_buf_size;
int num = 0, incomplete = 0, bol = 1;
size_t *i;
-
+
if (len && buf[len-1] != '\n')
incomplete++; /* incomplete line at the end */
while (len--) {
@@ -263,13 +262,15 @@ static int index_blob_lines(git_blame *blame)
blame->num_lines = num + incomplete;
return blame->num_lines;
}
-
+
static git_blame_hunk* hunk_from_entry(git_blame__entry *e)
{
git_blame_hunk *h = new_hunk(
e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path);
git_oid_cpy(&h->final_commit_id, git_commit_id(e->suspect->commit));
- h->final_signature = git_signature_dup(git_commit_author(e->suspect->commit));
+ git_oid_cpy(&h->orig_commit_id, git_commit_id(e->suspect->commit));
+ git_signature_dup(&h->final_signature, git_commit_author(e->suspect->commit));
+ git_signature_dup(&h->orig_signature, git_commit_author(e->suspect->commit));
h->boundary = e->is_boundary ? 1 : 0;
return h;
}
@@ -449,7 +450,7 @@ int git_blame_buffer(
git_blame **out,
git_blame *reference,
const char *buffer,
- uint32_t buffer_len)
+ size_t buffer_len)
{
git_blame *blame;
git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
diff --git a/src/blob.c b/src/blob.c
index ab344ae98..faf8a4a99 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -50,25 +50,28 @@ int git_blob__parse(void *blob, git_odb_object *odb_obj)
return 0;
}
-int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len)
+int git_blob_create_frombuffer(
+ git_oid *id, git_repository *repo, const void *buffer, size_t len)
{
int error;
git_odb *odb;
git_odb_stream *stream;
+ assert(id && repo);
+
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
(error = git_odb_open_wstream(&stream, odb, len, GIT_OBJ_BLOB)) < 0)
return error;
if ((error = git_odb_stream_write(stream, buffer, len)) == 0)
- error = git_odb_stream_finalize_write(oid, stream);
+ error = git_odb_stream_finalize_write(id, stream);
git_odb_stream_free(stream);
return error;
}
static int write_file_stream(
- git_oid *oid, git_odb *odb, const char *path, git_off_t file_size)
+ git_oid *id, git_odb *odb, const char *path, git_off_t file_size)
{
int fd, error;
char buffer[4096];
@@ -97,14 +100,14 @@ static int write_file_stream(
}
if (!error)
- error = git_odb_stream_finalize_write(oid, stream);
+ error = git_odb_stream_finalize_write(id, stream);
git_odb_stream_free(stream);
return error;
}
static int write_file_filtered(
- git_oid *oid,
+ git_oid *id,
git_off_t *size,
git_odb *odb,
const char *full_path,
@@ -119,7 +122,7 @@ static int write_file_filtered(
if (!error) {
*size = tgt.size;
- error = git_odb_write(oid, odb, tgt.ptr, tgt.size, GIT_OBJ_BLOB);
+ error = git_odb_write(id, odb, tgt.ptr, tgt.size, GIT_OBJ_BLOB);
}
git_buf_free(&tgt);
@@ -127,7 +130,7 @@ static int write_file_filtered(
}
static int write_symlink(
- git_oid *oid, git_odb *odb, const char *path, size_t link_size)
+ git_oid *id, git_odb *odb, const char *path, size_t link_size)
{
char *link_data;
ssize_t read_len;
@@ -143,13 +146,13 @@ static int write_symlink(
return -1;
}
- error = git_odb_write(oid, odb, (void *)link_data, link_size, GIT_OBJ_BLOB);
+ error = git_odb_write(id, odb, (void *)link_data, link_size, GIT_OBJ_BLOB);
git__free(link_data);
return error;
}
int git_blob__create_from_paths(
- git_oid *oid,
+ git_oid *id,
struct stat *out_st,
git_repository *repo,
const char *content_path,
@@ -188,7 +191,7 @@ int git_blob__create_from_paths(
mode = hint_mode ? hint_mode : st.st_mode;
if (S_ISLNK(mode)) {
- error = write_symlink(oid, odb, content_path, (size_t)size);
+ error = write_symlink(id, odb, content_path, (size_t)size);
} else {
git_filter_list *fl = NULL;
@@ -202,10 +205,10 @@ int git_blob__create_from_paths(
else if (fl == NULL)
/* No filters need to be applied to the document: we can stream
* directly from disk */
- error = write_file_stream(oid, odb, content_path, size);
+ error = write_file_stream(id, odb, content_path, size);
else {
/* We need to apply one or more filters */
- error = write_file_filtered(oid, &size, odb, content_path, fl);
+ error = write_file_filtered(id, &size, odb, content_path, fl);
git_filter_list_free(fl);
}
@@ -233,13 +236,13 @@ done:
}
int git_blob_create_fromworkdir(
- git_oid *oid, git_repository *repo, const char *path)
+ git_oid *id, git_repository *repo, const char *path)
{
- return git_blob__create_from_paths(oid, NULL, repo, NULL, path, 0, true);
+ return git_blob__create_from_paths(id, NULL, repo, NULL, path, 0, true);
}
int git_blob_create_fromdisk(
- git_oid *oid, git_repository *repo, const char *path)
+ git_oid *id, git_repository *repo, const char *path)
{
int error;
git_buf full_path = GIT_BUF_INIT;
@@ -257,7 +260,7 @@ int git_blob_create_fromdisk(
hintpath += strlen(workdir);
error = git_blob__create_from_paths(
- oid, NULL, repo, git_buf_cstr(&full_path), hintpath, 0, true);
+ id, NULL, repo, git_buf_cstr(&full_path), hintpath, 0, true);
git_buf_free(&full_path);
return error;
@@ -266,7 +269,7 @@ int git_blob_create_fromdisk(
#define BUFFER_SIZE 4096
int git_blob_create_fromchunks(
- git_oid *oid,
+ git_oid *id,
git_repository *repo,
const char *hintpath,
int (*source_cb)(char *content, size_t max_length, void *payload),
@@ -277,7 +280,7 @@ int git_blob_create_fromchunks(
git_filebuf file = GIT_FILEBUF_INIT;
git_buf path = GIT_BUF_INIT;
- assert(oid && repo && source_cb);
+ assert(id && repo && source_cb);
if ((error = git_buf_joinpath(
&path, git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0)
@@ -313,7 +316,7 @@ int git_blob_create_fromchunks(
goto cleanup;
error = git_blob__create_from_paths(
- oid, NULL, repo, file.path_lock, hintpath, 0, hintpath != NULL);
+ id, NULL, repo, file.path_lock, hintpath, 0, hintpath != NULL);
cleanup:
git_buf_free(&path);
@@ -347,6 +350,8 @@ int git_blob_filtered_content(
assert(blob && path && out);
+ git_buf_sanitize(out);
+
if (check_for_binary_data && git_blob_is_binary(blob))
return 0;
diff --git a/src/branch.c b/src/branch.c
index ef71c2cd1..133d6f6d4 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -21,27 +21,22 @@ static int retrieve_branch_reference(
const char *branch_name,
int is_remote)
{
- git_reference *branch;
- int error = -1;
+ git_reference *branch = NULL;
+ int error = 0;
char *prefix;
git_buf ref_name = GIT_BUF_INIT;
- *branch_reference_out = NULL;
-
prefix = is_remote ? GIT_REFS_REMOTES_DIR : GIT_REFS_HEADS_DIR;
- if (git_buf_joinpath(&ref_name, prefix, branch_name) < 0)
- goto cleanup;
-
- if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0) {
- giterr_set(GITERR_REFERENCE,
- "Cannot locate %s branch '%s'.", is_remote ? "remote-tracking" : "local", branch_name);
- goto cleanup;
- }
+ if ((error = git_buf_joinpath(&ref_name, prefix, branch_name)) < 0)
+ /* OOM */;
+ else if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0)
+ giterr_set(
+ GITERR_REFERENCE, "Cannot locate %s branch '%s'",
+ is_remote ? "remote-tracking" : "local", branch_name);
- *branch_reference_out = branch;
+ *branch_reference_out = branch; /* will be NULL on error */
-cleanup:
git_buf_free(&ref_name);
return error;
}
@@ -59,10 +54,13 @@ int git_branch_create(
git_repository *repository,
const char *branch_name,
const git_commit *commit,
- int force)
+ int force,
+ const git_signature *signature,
+ const char *log_message)
{
git_reference *branch = NULL;
- git_buf canonical_branch_name = GIT_BUF_INIT;
+ git_buf canonical_branch_name = GIT_BUF_INIT,
+ log_message_buf = GIT_BUF_INIT;
int error = -1;
assert(branch_name && commit && ref_out);
@@ -71,14 +69,19 @@ int git_branch_create(
if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
goto cleanup;
+ if (git_buf_sets(&log_message_buf, log_message ? log_message : "Branch: created") < 0)
+ goto cleanup;
+
error = git_reference_create(&branch, repository,
- git_buf_cstr(&canonical_branch_name), git_commit_id(commit), force);
+ git_buf_cstr(&canonical_branch_name), git_commit_id(commit), force, signature,
+ git_buf_cstr(&log_message_buf));
if (!error)
*ref_out = branch;
cleanup:
git_buf_free(&canonical_branch_name);
+ git_buf_free(&log_message_buf);
return error;
}
@@ -116,6 +119,9 @@ int git_branch_delete(git_reference *branch)
if (git_reference_delete(branch) < 0)
goto on_error;
+ if (git_reflog_delete(git_reference_owner(branch), git_reference_name(branch)) < 0)
+ goto on_error;
+
error = 0;
on_error:
@@ -181,6 +187,9 @@ void git_branch_iterator_free(git_branch_iterator *_iter)
{
branch_iter *iter = (branch_iter *) _iter;
+ if (iter == NULL)
+ return;
+
git_reference_iterator_free(iter->iter);
git__free(iter);
}
@@ -189,11 +198,14 @@ int git_branch_move(
git_reference **out,
git_reference *branch,
const char *new_branch_name,
- int force)
+ int force,
+ const git_signature *signature,
+ const char *log_message)
{
git_buf new_reference_name = GIT_BUF_INIT,
- old_config_section = GIT_BUF_INIT,
- new_config_section = GIT_BUF_INIT;
+ old_config_section = GIT_BUF_INIT,
+ new_config_section = GIT_BUF_INIT,
+ log_message_buf = GIT_BUF_INIT;
int error;
assert(branch && new_branch_name);
@@ -201,14 +213,23 @@ int git_branch_move(
if (!git_reference_is_branch(branch))
return not_a_local_branch(git_reference_name(branch));
- error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name);
- if (error < 0)
+ if ((error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0)
goto done;
+ if (log_message) {
+ if ((error = git_buf_sets(&log_message_buf, log_message)) < 0)
+ goto done;
+ } else {
+ if ((error = git_buf_printf(&log_message_buf, "Branch: renamed %s to %s",
+ git_reference_name(branch), git_buf_cstr(&new_reference_name))) < 0)
+ goto done;
+ }
+
/* first update ref then config so failure won't trash config */
error = git_reference_rename(
- out, branch, git_buf_cstr(&new_reference_name), force);
+ out, branch, git_buf_cstr(&new_reference_name), force,
+ signature, git_buf_cstr(&log_message_buf));
if (error < 0)
goto done;
@@ -225,6 +246,7 @@ done:
git_buf_free(&new_reference_name);
git_buf_free(&old_config_section);
git_buf_free(&new_config_section);
+ git_buf_free(&log_message_buf);
return error;
}
@@ -283,10 +305,10 @@ static int retrieve_upstream_configuration(
return error;
}
-int git_branch_upstream__name(
- git_buf *tracking_name,
+int git_branch_upstream_name(
+ git_buf *out,
git_repository *repo,
- const char *canonical_branch_name)
+ const char *refname)
{
const char *remote_name, *merge_name;
git_buf buf = GIT_BUF_INIT;
@@ -294,22 +316,24 @@ int git_branch_upstream__name(
git_remote *remote = NULL;
const git_refspec *refspec;
- assert(tracking_name && canonical_branch_name);
+ assert(out && refname);
- if (!git_reference__is_branch(canonical_branch_name))
- return not_a_local_branch(canonical_branch_name);
+ git_buf_sanitize(out);
+
+ if (!git_reference__is_branch(refname))
+ return not_a_local_branch(refname);
if ((error = retrieve_upstream_configuration(
- &remote_name, repo, canonical_branch_name, "branch.%s.remote")) < 0)
+ &remote_name, repo, refname, "branch.%s.remote")) < 0)
goto cleanup;
if ((error = retrieve_upstream_configuration(
- &merge_name, repo, canonical_branch_name, "branch.%s.merge")) < 0)
+ &merge_name, repo, refname, "branch.%s.merge")) < 0)
goto cleanup;
if (!*remote_name || !*merge_name) {
giterr_set(GITERR_REFERENCE,
- "branch '%s' does not have an upstream", canonical_branch_name);
+ "branch '%s' does not have an upstream", refname);
error = GIT_ENOTFOUND;
goto cleanup;
}
@@ -324,13 +348,13 @@ int git_branch_upstream__name(
goto cleanup;
}
- if (git_refspec_transform_r(&buf, refspec, merge_name) < 0)
+ if (git_refspec_transform(&buf, refspec, merge_name) < 0)
goto cleanup;
} else
if (git_buf_sets(&buf, merge_name) < 0)
goto cleanup;
- error = git_buf_set(tracking_name, git_buf_cstr(&buf), git_buf_len(&buf));
+ error = git_buf_set(out, git_buf_cstr(&buf), git_buf_len(&buf));
cleanup:
git_remote_free(remote);
@@ -338,7 +362,7 @@ cleanup:
return error;
}
-static int remote_name(git_buf *buf, git_repository *repo, const char *canonical_branch_name)
+int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refname)
{
git_strarray remote_list = {0};
size_t i;
@@ -347,12 +371,14 @@ static int remote_name(git_buf *buf, git_repository *repo, const char *canonical
int error = 0;
char *remote_name = NULL;
- assert(buf && repo && canonical_branch_name);
+ assert(buf && repo && refname);
+
+ git_buf_sanitize(buf);
/* Verify that this is a remote branch */
- if (!git_reference__is_remote(canonical_branch_name)) {
+ if (!git_reference__is_remote(refname)) {
giterr_set(GITERR_INVALID, "Reference '%s' is not a remote branch.",
- canonical_branch_name);
+ refname);
error = GIT_ERROR;
goto cleanup;
}
@@ -366,7 +392,7 @@ static int remote_name(git_buf *buf, git_repository *repo, const char *canonical
if ((error = git_remote_load(&remote, repo, remote_list.strings[i])) < 0)
continue;
- fetchspec = git_remote__matching_dst_refspec(remote, canonical_branch_name);
+ fetchspec = git_remote__matching_dst_refspec(remote, refname);
if (fetchspec) {
/* If we have not already set out yet, then set
* it to the matching remote name. Otherwise
@@ -378,7 +404,7 @@ static int remote_name(git_buf *buf, git_repository *repo, const char *canonical
git_remote_free(remote);
giterr_set(GITERR_REFERENCE,
- "Reference '%s' is ambiguous", canonical_branch_name);
+ "Reference '%s' is ambiguous", refname);
error = GIT_EAMBIGUOUS;
goto cleanup;
}
@@ -392,68 +418,18 @@ static int remote_name(git_buf *buf, git_repository *repo, const char *canonical
error = git_buf_puts(buf, remote_name);
} else {
giterr_set(GITERR_REFERENCE,
- "Could not determine remote for '%s'", canonical_branch_name);
+ "Could not determine remote for '%s'", refname);
error = GIT_ENOTFOUND;
}
cleanup:
+ if (error < 0)
+ git_buf_free(buf);
+
git_strarray_free(&remote_list);
return error;
}
-int git_branch_remote_name(char *buffer, size_t buffer_len, git_repository *repo, const char *refname)
-{
- int ret;
- git_buf buf = GIT_BUF_INIT;
-
- if ((ret = remote_name(&buf, repo, refname)) < 0)
- return ret;
-
- if (buffer)
- git_buf_copy_cstr(buffer, buffer_len, &buf);
-
- ret = (int)git_buf_len(&buf) + 1;
- git_buf_free(&buf);
-
- return ret;
-}
-
-int git_branch_upstream_name(
- char *tracking_branch_name_out,
- size_t buffer_size,
- git_repository *repo,
- const char *canonical_branch_name)
-{
- git_buf buf = GIT_BUF_INIT;
- int error;
-
- assert(canonical_branch_name);
-
- if (tracking_branch_name_out && buffer_size)
- *tracking_branch_name_out = '\0';
-
- if ((error = git_branch_upstream__name(
- &buf, repo, canonical_branch_name)) < 0)
- goto cleanup;
-
- if (tracking_branch_name_out && buf.size + 1 > buffer_size) { /* +1 for NUL byte */
- giterr_set(
- GITERR_INVALID,
- "Buffer too short to hold the tracked reference name.");
- error = -1;
- goto cleanup;
- }
-
- if (tracking_branch_name_out)
- git_buf_copy_cstr(tracking_branch_name_out, buffer_size, &buf);
-
- error = (int)buf.size + 1;
-
-cleanup:
- git_buf_free(&buf);
- return (int)error;
-}
-
int git_branch_upstream(
git_reference **tracking_out,
git_reference *branch)
@@ -461,7 +437,7 @@ int git_branch_upstream(
int error;
git_buf tracking_name = GIT_BUF_INIT;
- if ((error = git_branch_upstream__name(&tracking_name,
+ if ((error = git_branch_upstream_name(&tracking_name,
git_reference_owner(branch), git_reference_name(branch))) < 0)
return error;
@@ -544,7 +520,7 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
if (local)
git_buf_puts(&value, ".");
else
- remote_name(&value, repo, git_reference_name(upstream));
+ git_branch_remote_name(&value, repo, git_reference_name(upstream));
if (git_buf_printf(&key, "branch.%s.remote", shortname) < 0)
goto on_error;
@@ -563,7 +539,7 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
git_buf_clear(&value);
- if (!fetchspec || git_refspec_transform_l(&value, fetchspec, git_reference_name(upstream)) < 0)
+ if (!fetchspec || git_refspec_rtransform(&value, fetchspec, git_reference_name(upstream)) < 0)
goto on_error;
git_remote_free(remote);
diff --git a/src/buffer.c b/src/buffer.c
index 20682322e..318fee753 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -66,8 +66,10 @@ int git_buf_try_grow(
new_ptr = git__realloc(new_ptr, new_size);
if (!new_ptr) {
- if (mark_oom)
+ if (mark_oom) {
+ if (buf->ptr) git__free(buf->ptr);
buf->ptr = git_buf__oom;
+ }
return -1;
}
@@ -100,6 +102,14 @@ void git_buf_free(git_buf *buf)
git_buf_init(buf, 0);
}
+void git_buf_sanitize(git_buf *buf)
+{
+ if (buf->ptr == NULL) {
+ assert (buf->size == 0 && buf->asize == 0);
+ buf->ptr = git_buf__initbuf;
+ }
+}
+
void git_buf_clear(git_buf *buf)
{
buf->size = 0;
@@ -424,7 +434,7 @@ int git_buf_join(
ssize_t offset_a = -1;
/* not safe to have str_b point internally to the buffer */
- assert(str_b < buf->ptr || str_b > buf->ptr + buf->size);
+ assert(str_b < buf->ptr || str_b >= buf->ptr + buf->size);
/* figure out if we need to insert a separator */
if (separator && strlen_a) {
@@ -439,13 +449,14 @@ int git_buf_join(
if (git_buf_grow(buf, strlen_a + strlen_b + need_sep + 1) < 0)
return -1;
+ assert(buf->ptr);
/* fix up internal pointers */
if (offset_a >= 0)
str_a = buf->ptr + offset_a;
/* do the actual copying */
- if (offset_a != 0)
+ if (offset_a != 0 && str_a)
memmove(buf->ptr, str_a, strlen_a);
if (need_sep)
buf->ptr[strlen_a] = separator;
diff --git a/src/buffer.h b/src/buffer.h
index c88af6fef..564a4f561 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -51,6 +51,15 @@ extern void git_buf_init(git_buf *buf, size_t initial_size);
extern int git_buf_try_grow(
git_buf *buf, size_t target_size, bool mark_oom, bool preserve_external);
+/**
+ * Sanitizes git_buf structures provided from user input. Users of the
+ * library, when providing git_buf's, may wish to provide a NULL ptr for
+ * ease of handling. The buffer routines, however, expect a non-NULL ptr
+ * always. This helper method simply handles NULL input, converting to a
+ * git_buf__initbuf.
+ */
+extern void git_buf_sanitize(git_buf *buf);
+
extern void git_buf_swap(git_buf *buf_a, git_buf *buf_b);
extern char *git_buf_detach(git_buf *buf);
extern void git_buf_attach(git_buf *buf, char *ptr, size_t asize);
diff --git a/src/checkout.c b/src/checkout.c
index e642c975e..72fe5368f 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -70,7 +70,9 @@ typedef struct {
int name_collision:1,
directoryfile:1,
- one_to_two:1;
+ one_to_two:1,
+ binary:1,
+ submodule:1;
} checkout_conflictdata;
static int checkout_notify(
@@ -90,10 +92,10 @@ static int checkout_notify(
if (wditem) {
memset(&wdfile, 0, sizeof(wdfile));
- git_oid_cpy(&wdfile.oid, &wditem->oid);
+ git_oid_cpy(&wdfile.id, &wditem->id);
wdfile.path = wditem->path;
wdfile.size = wditem->file_size;
- wdfile.flags = GIT_DIFF_FLAG_VALID_OID;
+ wdfile.flags = GIT_DIFF_FLAG_VALID_ID;
wdfile.mode = wditem->mode;
workdir = &wdfile;
@@ -157,7 +159,7 @@ static bool checkout_is_workdir_modified(
if (!sm_oid)
return false;
- return (git_oid__cmp(&baseitem->oid, sm_oid) != 0);
+ return (git_oid__cmp(&baseitem->id, sm_oid) != 0);
}
/* Look at the cache to decide if the workdir is modified. If not,
@@ -168,7 +170,7 @@ static bool checkout_is_workdir_modified(
if (wditem->mtime.seconds == ie->mtime.seconds &&
wditem->mtime.nanoseconds == ie->mtime.nanoseconds &&
wditem->file_size == ie->file_size)
- return (git_oid__cmp(&baseitem->oid, &ie->oid) != 0);
+ return (git_oid__cmp(&baseitem->id, &ie->id) != 0);
}
/* depending on where base is coming from, we may or may not know
@@ -182,7 +184,7 @@ static bool checkout_is_workdir_modified(
wditem->file_size, &oid) < 0)
return false;
- return (git_oid__cmp(&baseitem->oid, &oid) != 0);
+ return (git_oid__cmp(&baseitem->id, &oid) != 0);
}
#define CHECKOUT_ACTION_IF(FLAG,YES,NO) \
@@ -244,6 +246,8 @@ static int checkout_action_no_wd(
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
break;
case GIT_DELTA_DELETED: /* case 8 or 25 */
+ *action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE);
+ break;
default: /* impossible */
break;
}
@@ -681,6 +685,51 @@ GIT_INLINE(bool) conflict_pathspec_match(
return false;
}
+GIT_INLINE(int) checkout_conflict_detect_submodule(checkout_conflictdata *conflict)
+{
+ conflict->submodule = ((conflict->ancestor && S_ISGITLINK(conflict->ancestor->mode)) ||
+ (conflict->ours && S_ISGITLINK(conflict->ours->mode)) ||
+ (conflict->theirs && S_ISGITLINK(conflict->theirs->mode)));
+ return 0;
+}
+
+GIT_INLINE(int) checkout_conflict_detect_binary(git_repository *repo, checkout_conflictdata *conflict)
+{
+ git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL;
+ int error = 0;
+
+ if (conflict->submodule)
+ return 0;
+
+ if (conflict->ancestor) {
+ if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor->id)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(ancestor_blob);
+ }
+
+ if (!conflict->binary && conflict->ours) {
+ if ((error = git_blob_lookup(&our_blob, repo, &conflict->ours->id)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(our_blob);
+ }
+
+ if (!conflict->binary && conflict->theirs) {
+ if ((error = git_blob_lookup(&their_blob, repo, &conflict->theirs->id)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(their_blob);
+ }
+
+done:
+ git_blob_free(ancestor_blob);
+ git_blob_free(our_blob);
+ git_blob_free(their_blob);
+
+ return error;
+}
+
static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, git_vector *pathspec)
{
git_index_conflict_iterator *iterator = NULL;
@@ -705,6 +754,13 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g
conflict->ours = ours;
conflict->theirs = theirs;
+ if ((error = checkout_conflict_detect_submodule(conflict)) < 0 ||
+ (error = checkout_conflict_detect_binary(data->repo, conflict)) < 0)
+ {
+ git__free(conflict);
+ goto done;
+ }
+
git_vector_insert(&data->conflicts, conflict);
}
@@ -1166,9 +1222,8 @@ static int checkout_update_index(
memset(&entry, 0, sizeof(entry));
entry.path = (char *)file->path; /* cast to prevent warning */
- git_index_entry__init_from_stat(
- &entry, st, !(git_index_caps(data->index) & GIT_INDEXCAP_NO_FILEMODE));
- git_oid_cpy(&entry.oid, &file->oid);
+ git_index_entry__init_from_stat(&entry, st, true);
+ git_oid_cpy(&entry.id, &file->id);
return git_index_add(data->index, &entry);
}
@@ -1325,7 +1380,7 @@ static int checkout_blob(
}
error = checkout_write_content(
- data, &file->oid, git_buf_cstr(&data->path), NULL, file->mode, &st);
+ data, &file->id, git_buf_cstr(&data->path), NULL, file->mode, &st);
/* update the index unless prevented */
if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0)
@@ -1578,7 +1633,7 @@ static int checkout_write_entry(
return error;
return checkout_write_content(data,
- &side->oid, git_buf_cstr(&data->path), hint_path, side->mode, &st);
+ &side->id, git_buf_cstr(&data->path), hint_path, side->mode, &st);
}
static int checkout_write_entries(
@@ -1626,6 +1681,7 @@ static int checkout_write_merge(
{
git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT,
path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT;
+ git_merge_file_options merge_file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
@@ -1633,6 +1689,9 @@ static int checkout_write_merge(
git_filebuf output = GIT_FILEBUF_INIT;
int error = 0;
+ if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)
+ merge_file_opts.style = GIT_MERGE_FILE_STYLE_DIFF3;
+
if ((conflict->ancestor &&
(error = git_merge_file_input_from_index_entry(
&ancestor, data->repo, conflict->ancestor)) < 0) ||
@@ -1642,7 +1701,7 @@ static int checkout_write_merge(
&theirs, data->repo, conflict->theirs)) < 0)
goto done;
- ancestor.label = NULL;
+ ancestor.label = data->opts.ancestor_label ? data->opts.ancestor_label : "ancestor";
ours.label = data->opts.our_label ? data->opts.our_label : "ours";
theirs.label = data->opts.their_label ? data->opts.their_label : "theirs";
@@ -1662,7 +1721,7 @@ static int checkout_write_merge(
theirs.label = git_buf_cstr(&their_label);
}
- if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, 0)) < 0)
+ if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, &merge_file_opts)) < 0)
goto done;
if (result.path == NULL || result.mode == 0) {
@@ -1705,6 +1764,7 @@ static int checkout_create_conflicts(checkout_data *data)
int error = 0;
git_vector_foreach(&data->conflicts, i, conflict) {
+
/* Both deleted: nothing to do */
if (conflict->ours == NULL && conflict->theirs == NULL)
error = 0;
@@ -1748,7 +1808,15 @@ static int checkout_create_conflicts(checkout_data *data)
else if (S_ISLNK(conflict->theirs->mode))
error = checkout_write_entry(data, conflict, conflict->ours);
- else
+ /* If any side is a gitlink, do nothing. */
+ else if (conflict->submodule)
+ error = 0;
+
+ /* If any side is binary, write the ours side */
+ else if (conflict->binary)
+ error = checkout_write_entry(data, conflict, conflict->ours);
+
+ else if (!error)
error = checkout_write_merge(data, conflict);
if (error)
@@ -1891,6 +1959,29 @@ static int checkout_data_init(
goto cleanup;
}
+ if ((data->opts.checkout_strategy &
+ (GIT_CHECKOUT_CONFLICT_STYLE_MERGE | GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)) == 0) {
+ const char *conflict_style;
+ git_config *cfg = NULL;
+
+ if ((error = git_repository_config__weakptr(&cfg, repo)) < 0 ||
+ (error = git_config_get_string(&conflict_style, cfg, "merge.conflictstyle")) < 0 ||
+ error == GIT_ENOTFOUND)
+ ;
+ else if (error)
+ goto cleanup;
+ else if (strcmp(conflict_style, "merge") == 0)
+ data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_MERGE;
+ else if (strcmp(conflict_style, "diff3") == 0)
+ data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3;
+ else {
+ giterr_set(GITERR_CHECKOUT, "unknown style '%s' given for 'merge.conflictstyle'",
+ conflict_style);
+ error = -1;
+ goto cleanup;
+ }
+ }
+
if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 ||
(error = git_vector_init(&data->conflicts, 0, NULL)) < 0 ||
(error = git_pool_init(&data->pool, 1, 0)) < 0 ||
diff --git a/src/clone.c b/src/clone.c
index 828c47ffb..3443528f7 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -27,7 +27,9 @@ static int create_branch(
git_reference **branch,
git_repository *repo,
const git_oid *target,
- const char *name)
+ const char *name,
+ const git_signature *signature,
+ const char *log_message)
{
git_commit *head_obj = NULL;
git_reference *branch_ref = NULL;
@@ -38,7 +40,7 @@ static int create_branch(
return error;
/* Create the new branch */
- error = git_branch_create(&branch_ref, repo, name, head_obj, 0);
+ error = git_branch_create(&branch_ref, repo, name, head_obj, 0, signature, log_message);
git_commit_free(head_obj);
@@ -87,11 +89,13 @@ static int create_tracking_branch(
git_reference **branch,
git_repository *repo,
const git_oid *target,
- const char *branch_name)
+ const char *branch_name,
+ const git_signature *signature,
+ const char *log_message)
{
int error;
- if ((error = create_branch(branch, repo, target, branch_name)) < 0)
+ if ((error = create_branch(branch, repo, target, branch_name, signature, log_message)) < 0)
return error;
return setup_tracking_config(
@@ -131,7 +135,7 @@ static int reference_matches_remote_head(
if (!error && !git_oid__cmp(&head_info->remote_head_oid, &oid)) {
/* Determine the local reference name from the remote tracking one */
- error = git_refspec_transform_l(
+ error = git_refspec_rtransform(
&head_info->branchname, head_info->refspec, reference_name);
if (!error &&
@@ -152,21 +156,29 @@ static int reference_matches_remote_head(
static int update_head_to_new_branch(
git_repository *repo,
const git_oid *target,
- const char *name)
+ const char *name,
+ const git_signature *signature,
+ const char *reflog_message)
{
git_reference *tracking_branch = NULL;
- int error = create_tracking_branch(&tracking_branch, repo, target, name);
+ int error = create_tracking_branch(&tracking_branch, repo, target, name,
+ signature, reflog_message);
if (!error)
error = git_repository_set_head(
- repo, git_reference_name(tracking_branch));
+ repo, git_reference_name(tracking_branch),
+ signature, reflog_message);
git_reference_free(tracking_branch);
return error;
}
-static int update_head_to_remote(git_repository *repo, git_remote *remote)
+static int update_head_to_remote(
+ git_repository *repo,
+ git_remote *remote,
+ const git_signature *signature,
+ const char *reflog_message)
{
int error = 0;
size_t refs_len;
@@ -199,7 +211,7 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
}
/* Determine the remote tracking reference name from the local master */
- if ((error = git_refspec_transform_r(
+ if ((error = git_refspec_transform(
&remote_master_name,
head_info.refspec,
GIT_REFS_HEADS_MASTER_FILE)) < 0)
@@ -215,7 +227,8 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
error = update_head_to_new_branch(
repo,
&head_info.remote_head_oid,
- git_buf_cstr(&head_info.branchname));
+ git_buf_cstr(&head_info.branchname),
+ signature, reflog_message);
goto cleanup;
}
@@ -229,10 +242,11 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
error = update_head_to_new_branch(
repo,
&head_info.remote_head_oid,
- git_buf_cstr(&head_info.branchname));
+ git_buf_cstr(&head_info.branchname),
+ signature, reflog_message);
} else {
error = git_repository_set_head_detached(
- repo, &head_info.remote_head_oid);
+ repo, &head_info.remote_head_oid, signature, reflog_message);
}
cleanup:
@@ -244,7 +258,9 @@ cleanup:
static int update_head_to_branch(
git_repository *repo,
const char *remote_name,
- const char *branch)
+ const char *branch,
+ const git_signature *signature,
+ const char *reflog_message)
{
int retcode;
git_buf remote_branch_name = GIT_BUF_INIT;
@@ -259,7 +275,8 @@ static int update_head_to_branch(
if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0)
goto cleanup;
- retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch);
+ retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
+ signature, reflog_message);
cleanup:
git_reference_free(remote_ref);
@@ -319,10 +336,11 @@ static bool should_checkout(
return !git_repository_head_unborn(repo);
}
-int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch)
+int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch, const git_signature *signature)
{
int error = 0, old_fetchhead;
git_strarray refspecs;
+ git_buf reflog_message = GIT_BUF_INIT;
assert(repo && remote);
@@ -340,15 +358,17 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_
old_fetchhead = git_remote_update_fetchhead(remote);
git_remote_set_update_fetchhead(remote, 0);
+ git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
if ((error = git_remote_fetch(remote)) != 0)
goto cleanup;
if (branch)
- error = update_head_to_branch(repo, git_remote_name(remote), branch);
+ error = update_head_to_branch(repo, git_remote_name(remote), branch,
+ signature, git_buf_cstr(&reflog_message));
/* Point HEAD to the same ref as the remote's head */
else
- error = update_head_to_remote(repo, remote);
+ error = update_head_to_remote(repo, remote, signature, git_buf_cstr(&reflog_message));
if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts))
error = git_checkout_head(repo, co_opts);
@@ -364,6 +384,7 @@ cleanup:
}
git_strarray_free(&refspecs);
+ git_buf_free(&reflog_message);
return error;
}
@@ -403,7 +424,7 @@ int git_clone(
if (!(error = create_and_configure_origin(&origin, repo, url, &options))) {
error = git_clone_into(
- repo, origin, &options.checkout_opts, options.checkout_branch);
+ repo, origin, &options.checkout_opts, options.checkout_branch, options.signature);
git_remote_free(origin);
}
diff --git a/src/commit.c b/src/commit.c
index 4ddfafb41..730fa6403 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -69,7 +69,7 @@ int git_commit_create_v(
return res;
}
-int git_commit_create_from_oids(
+int git_commit_create_from_ids(
git_oid *oid,
git_repository *repo,
const char *update_ref,
@@ -112,7 +112,7 @@ int git_commit_create_from_oids(
git_buf_free(&commit);
if (update_ref != NULL)
- return git_reference__update_terminal(repo, update_ref, oid);
+ return git_reference__update_terminal(repo, update_ref, oid, NULL, NULL);
return 0;
@@ -148,7 +148,7 @@ int git_commit_create(
parent_oids[i] = git_object_id((const git_object *)parents[i]);
}
- retval = git_commit_create_from_oids(
+ retval = git_commit_create_from_ids(
oid, repo, update_ref, author, committer,
message_encoding, message,
git_object_id((const git_object *)tree), parent_count, parent_oids);
@@ -164,33 +164,15 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
const char *buffer_start = git_odb_object_data(odb_obj), *buffer;
const char *buffer_end = buffer_start + git_odb_object_size(odb_obj);
git_oid parent_id;
- uint32_t parent_count = 0;
size_t header_len;
- /* find end-of-header (counting parents as we go) */
- for (buffer = buffer_start; buffer < buffer_end; ++buffer) {
- if (!strncmp("\n\n", buffer, 2)) {
- ++buffer;
- break;
- }
- if (!strncmp("\nparent ", buffer, strlen("\nparent ")))
- ++parent_count;
- }
-
- header_len = buffer - buffer_start;
- commit->raw_header = git__strndup(buffer_start, header_len);
- GITERR_CHECK_ALLOC(commit->raw_header);
+ buffer = buffer_start;
- /* point "buffer" to header data */
- buffer = commit->raw_header;
- buffer_end = commit->raw_header + header_len;
-
- if (parent_count < 1)
- parent_count = 1;
-
- git_array_init_to_size(commit->parent_ids, parent_count);
+ /* Allocate for one, which will allow not to realloc 90% of the time */
+ git_array_init_to_size(commit->parent_ids, 1);
GITERR_CHECK_ARRAY(commit->parent_ids);
+ /* The tree is always the first field */
if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0)
goto bad_buffer;
@@ -221,6 +203,9 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
/* Parse add'l header entries */
while (buffer < buffer_end) {
const char *eoln = buffer;
+ if (buffer[-1] == '\n' && buffer[0] == '\n')
+ break;
+
while (eoln < buffer_end && *eoln != '\n')
++eoln;
@@ -236,13 +221,12 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
buffer = eoln;
}
- /* point "buffer" to data after header */
- buffer = git_odb_object_data(odb_obj);
- buffer_end = buffer + git_odb_object_size(odb_obj);
+ header_len = buffer - buffer_start;
+ commit->raw_header = git__strndup(buffer_start, header_len);
+ GITERR_CHECK_ALLOC(commit->raw_header);
- buffer += header_len;
- if (*buffer == '\n')
- ++buffer;
+ /* point "buffer" to data after header, +1 for the final LF */
+ buffer = buffer_start + header_len + 1;
/* extract commit message */
if (buffer <= buffer_end) {
@@ -311,7 +295,10 @@ const char *git_commit_summary(git_commit *commit)
git_buf_putc(&summary, *msg);
}
- commit->summary = git_buf_detach(&summary);
+ if (summary.asize == 0)
+ commit->summary = git__strdup("");
+ else
+ commit->summary = git_buf_detach(&summary);
}
return commit->summary;
diff --git a/src/compress.c b/src/compress.c
deleted file mode 100644
index 14b79404c..000000000
--- a/src/compress.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#include "compress.h"
-
-#include <zlib.h>
-
-#define BUFFER_SIZE (1024 * 1024)
-
-int git__compress(git_buf *buf, const void *buff, size_t len)
-{
- z_stream zs;
- char *zb;
- size_t have;
-
- memset(&zs, 0, sizeof(zs));
- if (deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK)
- return -1;
-
- zb = git__malloc(BUFFER_SIZE);
- GITERR_CHECK_ALLOC(zb);
-
- zs.next_in = (void *)buff;
- zs.avail_in = (uInt)len;
-
- do {
- zs.next_out = (unsigned char *)zb;
- zs.avail_out = BUFFER_SIZE;
-
- if (deflate(&zs, Z_FINISH) == Z_STREAM_ERROR) {
- git__free(zb);
- return -1;
- }
-
- have = BUFFER_SIZE - (size_t)zs.avail_out;
-
- if (git_buf_put(buf, zb, have) < 0) {
- git__free(zb);
- return -1;
- }
-
- } while (zs.avail_out == 0);
-
- assert(zs.avail_in == 0);
-
- deflateEnd(&zs);
- git__free(zb);
- return 0;
-}
diff --git a/src/compress.h b/src/compress.h
deleted file mode 100644
index 49e6f4749..000000000
--- a/src/compress.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#ifndef INCLUDE_compress_h__
-#define INCLUDE_compress_h__
-
-#include "common.h"
-
-#include "buffer.h"
-
-int git__compress(git_buf *buf, const void *buff, size_t len);
-
-#endif /* INCLUDE_compress_h__ */
diff --git a/src/config.c b/src/config.c
index 056a6ae13..6aa71468a 100644
--- a/src/config.c
+++ b/src/config.c
@@ -458,6 +458,7 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf
if ((result = regcomp(&iter->regex, regexp, REG_EXTENDED)) < 0) {
giterr_set_regex(&iter->regex, result);
regfree(&iter->regex);
+ git__free(iter);
return -1;
}
@@ -651,6 +652,7 @@ static int get_entry(
key = normalized;
}
+ res = GIT_ENOTFOUND;
git_vector_foreach(&cfg->files, i, internal) {
if (!internal || !internal->file)
continue;
@@ -927,64 +929,27 @@ int git_config_next(git_config_entry **entry, git_config_iterator *iter)
void git_config_iterator_free(git_config_iterator *iter)
{
- iter->free(iter);
-}
-
-static int git_config__find_file_to_path(
- char *out, size_t outlen, int (*find)(git_buf *buf))
-{
- int error = 0;
- git_buf path = GIT_BUF_INIT;
-
- if ((error = find(&path)) < 0)
- goto done;
-
- if (path.size >= outlen) {
- giterr_set(GITERR_NOMEMORY, "Buffer is too short for the path");
- error = GIT_EBUFS;
- goto done;
- }
-
- git_buf_copy_cstr(out, outlen, &path);
+ if (iter == NULL)
+ return;
-done:
- git_buf_free(&path);
- return error;
+ iter->free(iter);
}
-int git_config_find_global_r(git_buf *path)
+int git_config_find_global(git_buf *path)
{
return git_futils_find_global_file(path, GIT_CONFIG_FILENAME_GLOBAL);
}
-int git_config_find_global(char *global_config_path, size_t length)
-{
- return git_config__find_file_to_path(
- global_config_path, length, git_config_find_global_r);
-}
-
-int git_config_find_xdg_r(git_buf *path)
+int git_config_find_xdg(git_buf *path)
{
return git_futils_find_xdg_file(path, GIT_CONFIG_FILENAME_XDG);
}
-int git_config_find_xdg(char *xdg_config_path, size_t length)
-{
- return git_config__find_file_to_path(
- xdg_config_path, length, git_config_find_xdg_r);
-}
-
-int git_config_find_system_r(git_buf *path)
+int git_config_find_system(git_buf *path)
{
return git_futils_find_system_file(path, GIT_CONFIG_FILENAME_SYSTEM);
}
-int git_config_find_system(char *system_config_path, size_t length)
-{
- return git_config__find_file_to_path(
- system_config_path, length, git_config_find_system_r);
-}
-
int git_config__global_location(git_buf *buf)
{
const git_buf *paths;
@@ -1021,16 +986,16 @@ int git_config_open_default(git_config **out)
if ((error = git_config_new(&cfg)) < 0)
return error;
- if (!git_config_find_global_r(&buf) || !git_config__global_location(&buf)) {
+ if (!git_config_find_global(&buf) || !git_config__global_location(&buf)) {
error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_GLOBAL, 0);
}
- if (!error && !git_config_find_xdg_r(&buf))
+ if (!error && !git_config_find_xdg(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_XDG, 0);
- if (!error && !git_config_find_system_r(&buf))
+ if (!error && !git_config_find_system(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_SYSTEM, 0);
diff --git a/src/config.h b/src/config.h
index 3cd888c88..03d910616 100644
--- a/src/config.h
+++ b/src/config.h
@@ -24,11 +24,6 @@ struct git_config {
git_vector files;
};
-extern int git_config_find_global_r(git_buf *global_config_path);
-extern int git_config_find_xdg_r(git_buf *system_config_path);
-extern int git_config_find_system_r(git_buf *system_config_path);
-
-
extern int git_config__global_location(git_buf *buf);
extern int git_config_rename_section(
diff --git a/src/config_file.c b/src/config_file.c
index 0971aa7b0..c7727c029 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -213,7 +213,7 @@ static int config_refresh(git_config_backend *cfg)
int res = 0, updated = 0, any_updated = 0;
diskfile_backend *b = (diskfile_backend *)cfg;
git_strmap *old_values;
- struct reader *reader;
+ struct reader *reader = NULL;
uint32_t i;
for (i = 0; i < git_array_size(b->readers); i++) {
@@ -1072,8 +1072,10 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c
git_buf_printf(&buf, "%s.%s", current_section, var_name);
git__free(var_name);
- if (git_buf_oom(&buf))
+ if (git_buf_oom(&buf)) {
+ git__free(var_value);
return -1;
+ }
var->entry->name = git_buf_detach(&buf);
var->entry->value = var_value;
diff --git a/src/crlf.c b/src/crlf.c
index b25c02cce..e1bd5572b 100644
--- a/src/crlf.c
+++ b/src/crlf.c
@@ -101,7 +101,7 @@ static int has_cr_in_index(const git_filter_source *src)
if (!S_ISREG(entry->mode)) /* don't crlf filter non-blobs */
return true;
- if (git_blob_lookup(&blob, repo, &entry->oid) < 0)
+ if (git_blob_lookup(&blob, repo, &entry->id) < 0)
return false;
blobcontent = git_blob_rawcontent(blob);
diff --git a/src/diff.c b/src/diff.c
index 7f2e58c0c..151990ed6 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -110,18 +110,18 @@ static int diff_delta__from_one(
if (delta->status == GIT_DELTA_DELETED) {
delta->old_file.mode = entry->mode;
delta->old_file.size = entry->file_size;
- git_oid_cpy(&delta->old_file.oid, &entry->oid);
+ git_oid_cpy(&delta->old_file.id, &entry->id);
} else /* ADDED, IGNORED, UNTRACKED */ {
delta->new_file.mode = entry->mode;
delta->new_file.size = entry->file_size;
- git_oid_cpy(&delta->new_file.oid, &entry->oid);
+ git_oid_cpy(&delta->new_file.id, &entry->id);
}
- delta->old_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
if (delta->status == GIT_DELTA_DELETED ||
- !git_oid_iszero(&delta->new_file.oid))
- delta->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ !git_oid_iszero(&delta->new_file.id))
+ delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
return diff_insert_delta(diff, delta, matched_pathspec);
}
@@ -156,24 +156,24 @@ static int diff_delta__from_two(
GITERR_CHECK_ALLOC(delta);
delta->nfiles = 2;
- git_oid_cpy(&delta->old_file.oid, &old_entry->oid);
+ git_oid_cpy(&delta->old_file.id, &old_entry->id);
delta->old_file.size = old_entry->file_size;
delta->old_file.mode = old_mode;
- delta->old_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
- git_oid_cpy(&delta->new_file.oid, &new_entry->oid);
+ git_oid_cpy(&delta->new_file.id, &new_entry->id);
delta->new_file.size = new_entry->file_size;
delta->new_file.mode = new_mode;
if (new_oid) {
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE))
- git_oid_cpy(&delta->old_file.oid, new_oid);
+ git_oid_cpy(&delta->old_file.id, new_oid);
else
- git_oid_cpy(&delta->new_file.oid, new_oid);
+ git_oid_cpy(&delta->new_file.id, new_oid);
}
- if (new_oid || !git_oid_iszero(&new_entry->oid))
- delta->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ if (new_oid || !git_oid_iszero(&new_entry->id))
+ delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
return diff_insert_delta(diff, delta, matched_pathspec);
}
@@ -189,21 +189,21 @@ static git_diff_delta *diff_delta__last_for_item(
switch (delta->status) {
case GIT_DELTA_UNMODIFIED:
case GIT_DELTA_DELETED:
- if (git_oid__cmp(&delta->old_file.oid, &item->oid) == 0)
+ if (git_oid__cmp(&delta->old_file.id, &item->id) == 0)
return delta;
break;
case GIT_DELTA_ADDED:
- if (git_oid__cmp(&delta->new_file.oid, &item->oid) == 0)
+ if (git_oid__cmp(&delta->new_file.id, &item->id) == 0)
return delta;
break;
case GIT_DELTA_UNTRACKED:
if (diff->strcomp(delta->new_file.path, item->path) == 0 &&
- git_oid__cmp(&delta->new_file.oid, &item->oid) == 0)
+ git_oid__cmp(&delta->new_file.id, &item->id) == 0)
return delta;
break;
case GIT_DELTA_MODIFIED:
- if (git_oid__cmp(&delta->old_file.oid, &item->oid) == 0 ||
- git_oid__cmp(&delta->new_file.oid, &item->oid) == 0)
+ if (git_oid__cmp(&delta->old_file.id, &item->id) == 0 ||
+ git_oid__cmp(&delta->new_file.id, &item->id) == 0)
return delta;
break;
default:
@@ -629,7 +629,7 @@ static int maybe_modified_submodule(
/* now that we have a HEAD OID, check if HEAD moved */
if ((sm_status & GIT_SUBMODULE_STATUS_IN_WD) != 0 &&
- !git_oid_equal(&info->oitem->oid, found_oid))
+ !git_oid_equal(&info->oitem->id, found_oid))
*status = GIT_DELTA_MODIFIED;
return 0;
@@ -689,15 +689,15 @@ static int maybe_modified(
}
/* if oids and modes match (and are valid), then file is unmodified */
- else if (git_oid_equal(&oitem->oid, &nitem->oid) &&
+ else if (git_oid_equal(&oitem->id, &nitem->id) &&
omode == nmode &&
- !git_oid_iszero(&oitem->oid))
+ !git_oid_iszero(&oitem->id))
status = GIT_DELTA_UNMODIFIED;
/* if we have an unknown OID and a workdir iterator, then check some
* circumstances that can accelerate things or need special handling
*/
- else if (git_oid_iszero(&nitem->oid) && new_is_workdir) {
+ else if (git_oid_iszero(&nitem->id) && new_is_workdir) {
bool use_ctime = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) != 0);
bool use_nanos = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_NANOSECS) != 0);
@@ -732,7 +732,7 @@ static int maybe_modified(
/* if we got here and decided that the files are modified, but we
* haven't calculated the OID of the new item, then calculate it now
*/
- if (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->oid)) {
+ if (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->id)) {
if (git_oid_iszero(&noid)) {
if ((error = git_diff__oid_for_file(diff->repo,
nitem->path, nitem->mode, nitem->file_size, &noid)) < 0)
@@ -744,7 +744,7 @@ static int maybe_modified(
* matches between the index and the workdir HEAD)
*/
if (omode == nmode && !S_ISGITLINK(omode) &&
- git_oid_equal(&oitem->oid, &noid))
+ git_oid_equal(&oitem->id, &noid))
status = GIT_DELTA_UNMODIFIED;
}
diff --git a/src/diff.h b/src/diff.h
index 2c9298a5f..c588f6301 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -134,7 +134,7 @@ GIT_INLINE(int) git_diff_file__resolve_zero_size(
return error;
error = git_odb__read_header_or_object(
- odb_obj, &len, &type, odb, &file->oid);
+ odb_obj, &len, &type, odb, &file->id);
git_odb_free(odb);
diff --git a/src/diff_driver.c b/src/diff_driver.c
index 167c0cc5a..4c9a0af65 100644
--- a/src/diff_driver.c
+++ b/src/diff_driver.c
@@ -26,10 +26,13 @@ typedef enum {
DIFF_DRIVER_PATTERNLIST = 3,
} git_diff_driver_t;
+typedef struct {
+ regex_t re;
+ int flags;
+} git_diff_driver_pattern;
+
enum {
- DIFF_CONTEXT_FIND_NORMAL = 0,
- DIFF_CONTEXT_FIND_ICASE = (1 << 0),
- DIFF_CONTEXT_FIND_EXT = (1 << 1),
+ REG_NEGATE = (1 << 15) /* get out of the way of existing flags */
};
/* data for finding function context for a given file type */
@@ -37,11 +40,13 @@ struct git_diff_driver {
git_diff_driver_t type;
uint32_t binary_flags;
uint32_t other_flags;
- git_array_t(regex_t) fn_patterns;
+ git_array_t(git_diff_driver_pattern) fn_patterns;
regex_t word_pattern;
char name[GIT_FLEX_ARRAY];
};
+#include "userdiff.h"
+
struct git_diff_driver_registry {
git_strmap *drivers;
};
@@ -81,34 +86,59 @@ void git_diff_driver_registry_free(git_diff_driver_registry *reg)
git__free(reg);
}
-static int diff_driver_add_funcname(
- git_diff_driver *drv, const char *name, int regex_flags)
+static int diff_driver_add_patterns(
+ git_diff_driver *drv, const char *regex_str, int regex_flags)
{
- int error;
- regex_t re, *re_ptr;
-
- if ((error = regcomp(&re, name, regex_flags)) != 0) {
- /* TODO: warning about bad regex instead of failure */
- error = giterr_set_regex(&re, error);
- regfree(&re);
- return error;
+ int error = 0;
+ const char *scan, *end;
+ git_diff_driver_pattern *pat = NULL;
+ git_buf buf = GIT_BUF_INIT;
+
+ for (scan = regex_str; scan; scan = end) {
+ /* get pattern to fill in */
+ if ((pat = git_array_alloc(drv->fn_patterns)) == NULL) {
+ error = -1;
+ break;
+ }
+
+ pat->flags = regex_flags;
+ if (*scan == '!') {
+ pat->flags |= REG_NEGATE;
+ ++scan;
+ }
+
+ if ((end = strchr(scan, '\n')) != NULL) {
+ error = git_buf_set(&buf, scan, end - scan);
+ end++;
+ } else {
+ error = git_buf_sets(&buf, scan);
+ }
+ if (error < 0)
+ break;
+
+ if ((error = regcomp(&pat->re, buf.ptr, regex_flags)) < 0) {
+ /* if regex fails to compile, warn? fail? */
+ error = giterr_set_regex(&pat->re, error);
+ regfree(&pat->re);
+ break;
+ }
}
- re_ptr = git_array_alloc(drv->fn_patterns);
- GITERR_CHECK_ALLOC(re_ptr);
+ if (error && pat != NULL)
+ (void)git_array_pop(drv->fn_patterns); /* release last item */
+ git_buf_free(&buf);
- memcpy(re_ptr, &re, sizeof(re));
- return 0;
+ return error;
}
static int diff_driver_xfuncname(const git_config_entry *entry, void *payload)
{
- return diff_driver_add_funcname(payload, entry->value, REG_EXTENDED);
+ return diff_driver_add_patterns(payload, entry->value, REG_EXTENDED);
}
static int diff_driver_funcname(const git_config_entry *entry, void *payload)
{
- return diff_driver_add_funcname(payload, entry->value, 0);
+ return diff_driver_add_patterns(payload, entry->value, 0);
}
static git_diff_driver_registry *git_repository_driver_registry(
@@ -128,12 +158,65 @@ static git_diff_driver_registry *git_repository_driver_registry(
return repo->diff_drivers;
}
+static int git_diff_driver_builtin(
+ git_diff_driver **out,
+ git_diff_driver_registry *reg,
+ const char *driver_name)
+{
+ int error = 0;
+ git_diff_driver_definition *ddef = NULL;
+ git_diff_driver *drv = NULL;
+ size_t namelen, idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(builtin_defs); ++idx) {
+ if (!strcasecmp(driver_name, builtin_defs[idx].name)) {
+ ddef = &builtin_defs[idx];
+ break;
+ }
+ }
+ if (!ddef)
+ goto done;
+
+ namelen = strlen(ddef->name);
+
+ drv = git__calloc(1, sizeof(git_diff_driver) + namelen + 1);
+ GITERR_CHECK_ALLOC(drv);
+
+ drv->type = DIFF_DRIVER_PATTERNLIST;
+ memcpy(drv->name, ddef->name, namelen);
+
+ if (ddef->fns &&
+ (error = diff_driver_add_patterns(
+ drv, ddef->fns, ddef->flags | REG_EXTENDED)) < 0)
+ goto done;
+
+ if (ddef->words &&
+ (error = regcomp(
+ &drv->word_pattern, ddef->words, ddef->flags | REG_EXTENDED)))
+ {
+ error = giterr_set_regex(&drv->word_pattern, error);
+ goto done;
+ }
+
+ git_strmap_insert(reg->drivers, drv->name, drv, error);
+ if (error > 0)
+ error = 0;
+
+done:
+ if (error && drv)
+ git_diff_driver_free(drv);
+ else
+ *out = drv;
+
+ return error;
+}
+
static int git_diff_driver_load(
git_diff_driver **out, git_repository *repo, const char *driver_name)
{
int error = 0;
git_diff_driver_registry *reg;
- git_diff_driver *drv;
+ git_diff_driver *drv = NULL;
size_t namelen = strlen(driver_name);
khiter_t pos;
git_config *cfg;
@@ -141,21 +224,19 @@ static int git_diff_driver_load(
const git_config_entry *ce;
bool found_driver = false;
- reg = git_repository_driver_registry(repo);
- if (!reg)
+ if ((reg = git_repository_driver_registry(repo)) == NULL)
return -1;
- else {
- pos = git_strmap_lookup_index(reg->drivers, driver_name);
- if (git_strmap_valid_index(reg->drivers, pos)) {
- *out = git_strmap_value_at(reg->drivers, pos);
- return 0;
- }
+
+ pos = git_strmap_lookup_index(reg->drivers, driver_name);
+ if (git_strmap_valid_index(reg->drivers, pos)) {
+ *out = git_strmap_value_at(reg->drivers, pos);
+ return 0;
}
/* if you can't read config for repo, just use default driver */
if (git_repository_config__weakptr(&cfg, repo) < 0) {
giterr_clear();
- return GIT_ENOTFOUND;
+ goto done;
}
drv = git__calloc(1, sizeof(git_diff_driver) + namelen + 1);
@@ -178,7 +259,7 @@ static int git_diff_driver_load(
found_driver = true;
break;
default:
- /* diff.<driver>.binary unspecified, so just continue */
+ /* diff.<driver>.binary unspecified or "auto", so just continue */
break;
}
@@ -234,14 +315,18 @@ static int git_diff_driver_load(
git_strmap_insert(reg->drivers, drv->name, drv, error);
if (error < 0)
goto done;
+ error = 0;
*out = drv;
done:
git_buf_free(&name);
- if (!*out)
- *out = &global_drivers[DIFF_DRIVER_AUTO];
+ if (!*out) {
+ int error2 = git_diff_driver_builtin(out, reg, driver_name);
+ if (!error)
+ error = error2;
+ }
if (drv && drv != *out)
git_diff_driver_free(drv);
@@ -256,14 +341,13 @@ int git_diff_driver_lookup(
const char *value;
assert(out);
+ *out = NULL;
if (!repo || !path || !strlen(path))
- goto use_auto;
-
- if ((error = git_attr_get(&value, repo, 0, path, "diff")) < 0)
- return error;
-
- if (GIT_ATTR_UNSPECIFIED(value))
+ /* just use the auto value */;
+ else if ((error = git_attr_get(&value, repo, 0, path, "diff")) < 0)
+ /* return error below */;
+ else if (GIT_ATTR_UNSPECIFIED(value))
/* just use the auto value */;
else if (GIT_ATTR_FALSE(value))
*out = &global_drivers[DIFF_DRIVER_BINARY];
@@ -272,17 +356,16 @@ int git_diff_driver_lookup(
/* otherwise look for driver information in config and build driver */
else if ((error = git_diff_driver_load(out, repo, value)) < 0) {
- if (error != GIT_ENOTFOUND)
- return error;
- else
+ if (error == GIT_ENOTFOUND) {
+ error = 0;
giterr_clear();
+ }
}
-use_auto:
if (!*out)
*out = &global_drivers[DIFF_DRIVER_AUTO];
- return 0;
+ return error;
}
void git_diff_driver_free(git_diff_driver *driver)
@@ -293,7 +376,7 @@ void git_diff_driver_free(git_diff_driver *driver)
return;
for (i = 0; i < git_array_size(driver->fn_patterns); ++i)
- regfree(git_array_get(driver->fn_patterns, i));
+ regfree(& git_array_get(driver->fn_patterns, i)->re);
git_array_clear(driver->fn_patterns);
regfree(&driver->word_pattern);
@@ -330,23 +413,34 @@ int git_diff_driver_content_is_binary(
}
static int diff_context_line__simple(
- git_diff_driver *driver, const char *line, size_t line_len)
+ git_diff_driver *driver, git_buf *line)
{
+ char firstch = line->ptr[0];
GIT_UNUSED(driver);
- GIT_UNUSED(line_len);
- return (git__isalpha(*line) || *line == '_' || *line == '$');
+ return (git__isalpha(firstch) || firstch == '_' || firstch == '$');
}
static int diff_context_line__pattern_match(
- git_diff_driver *driver, const char *line, size_t line_len)
+ git_diff_driver *driver, git_buf *line)
{
- size_t i;
+ size_t i, maxi = git_array_size(driver->fn_patterns);
+ regmatch_t pmatch[2];
- GIT_UNUSED(line_len);
+ for (i = 0; i < maxi; ++i) {
+ git_diff_driver_pattern *pat = git_array_get(driver->fn_patterns, i);
+
+ if (!regexec(&pat->re, line->ptr, 2, pmatch, 0)) {
+ if (pat->flags & REG_NEGATE)
+ return false;
+
+ /* use pmatch data to trim line data */
+ i = (pmatch[1].rm_so >= 0) ? 1 : 0;
+ git_buf_consume(line, git_buf_cstr(line) + pmatch[i].rm_so);
+ git_buf_truncate(line, pmatch[i].rm_eo - pmatch[i].rm_so);
+ git_buf_rtrim(line);
- for (i = 0; i < git_array_size(driver->fn_patterns); ++i) {
- if (!regexec(git_array_get(driver->fn_patterns, i), line, 0, NULL, 0))
return true;
+ }
}
return false;
@@ -368,8 +462,7 @@ static long diff_context_find(
if (!ctxt->line.size)
return -1;
- if (!ctxt->match_line ||
- !ctxt->match_line(ctxt->driver, ctxt->line.ptr, ctxt->line.size))
+ if (!ctxt->match_line || !ctxt->match_line(ctxt->driver, &ctxt->line))
return -1;
if (out_size > (long)ctxt->line.size)
diff --git a/src/diff_driver.h b/src/diff_driver.h
index 9d3f18660..0706dcfc5 100644
--- a/src/diff_driver.h
+++ b/src/diff_driver.h
@@ -31,7 +31,7 @@ typedef long (*git_diff_find_context_fn)(
const char *, long, char *, long, void *);
typedef int (*git_diff_find_context_line)(
- git_diff_driver *, const char *, size_t);
+ git_diff_driver *, git_buf *);
typedef struct {
git_diff_driver *driver;
diff --git a/src/diff_file.c b/src/diff_file.c
index a4c8641bc..fb5d674f7 100644
--- a/src/diff_file.c
+++ b/src/diff_file.c
@@ -143,10 +143,10 @@ int git_diff_file_content__init_from_blob(
fc->flags |= GIT_DIFF_FLAG__NO_DATA;
} else {
fc->flags |= GIT_DIFF_FLAG__LOADED;
- fc->file->flags |= GIT_DIFF_FLAG_VALID_OID;
+ fc->file->flags |= GIT_DIFF_FLAG_VALID_ID;
fc->file->size = git_blob_rawsize(blob);
fc->file->mode = GIT_FILEMODE_BLOB;
- git_oid_cpy(&fc->file->oid, git_blob_id(blob));
+ git_oid_cpy(&fc->file->id, git_blob_id(blob));
fc->map.len = (size_t)fc->file->size;
fc->map.data = (char *)git_blob_rawcontent(blob);
@@ -171,10 +171,10 @@ int git_diff_file_content__init_from_raw(
fc->flags |= GIT_DIFF_FLAG__NO_DATA;
} else {
fc->flags |= GIT_DIFF_FLAG__LOADED;
- fc->file->flags |= GIT_DIFF_FLAG_VALID_OID;
+ fc->file->flags |= GIT_DIFF_FLAG_VALID_ID;
fc->file->size = buflen;
fc->file->mode = GIT_FILEMODE_BLOB;
- git_odb_hash(&fc->file->oid, buf, buflen, GIT_OBJ_BLOB);
+ git_odb_hash(&fc->file->id, buf, buflen, GIT_OBJ_BLOB);
fc->map.len = buflen;
fc->map.data = (char *)buf;
@@ -205,19 +205,19 @@ static int diff_file_content_commit_to_str(
}
/* update OID if we didn't have it previously */
- if ((fc->file->flags & GIT_DIFF_FLAG_VALID_OID) == 0 &&
+ if ((fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0 &&
((sm_head = git_submodule_wd_id(sm)) != NULL ||
(sm_head = git_submodule_head_id(sm)) != NULL))
{
- git_oid_cpy(&fc->file->oid, sm_head);
- fc->file->flags |= GIT_DIFF_FLAG_VALID_OID;
+ git_oid_cpy(&fc->file->id, sm_head);
+ fc->file->flags |= GIT_DIFF_FLAG_VALID_ID;
}
if (GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status))
status = "-dirty";
}
- git_oid_tostr(oid, sizeof(oid), &fc->file->oid);
+ git_oid_tostr(oid, sizeof(oid), &fc->file->id);
if (git_buf_printf(&content, "Subproject commit %s%s\n", oid, status) < 0)
return -1;
@@ -233,7 +233,7 @@ static int diff_file_content_load_blob(git_diff_file_content *fc)
int error = 0;
git_odb_object *odb_obj = NULL;
- if (git_oid_iszero(&fc->file->oid))
+ if (git_oid_iszero(&fc->file->id))
return 0;
if (fc->file->mode == GIT_FILEMODE_COMMIT)
@@ -255,7 +255,7 @@ static int diff_file_content_load_blob(git_diff_file_content *fc)
git_odb_object_free(odb_obj);
} else {
error = git_blob_lookup(
- (git_blob **)&fc->blob, fc->repo, &fc->file->oid);
+ (git_blob **)&fc->blob, fc->repo, &fc->file->id);
}
if (!error) {
@@ -368,10 +368,10 @@ static int diff_file_content_load_workdir(git_diff_file_content *fc)
error = diff_file_content_load_workdir_file(fc, &path);
/* once data is loaded, update OID if we didn't have it previously */
- if (!error && (fc->file->flags & GIT_DIFF_FLAG_VALID_OID) == 0) {
+ if (!error && (fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0) {
error = git_odb_hash(
- &fc->file->oid, fc->map.data, fc->map.len, GIT_OBJ_BLOB);
- fc->file->flags |= GIT_DIFF_FLAG_VALID_OID;
+ &fc->file->id, fc->map.data, fc->map.len, GIT_OBJ_BLOB);
+ fc->file->flags |= GIT_DIFF_FLAG_VALID_ID;
}
git_buf_free(&path);
diff --git a/src/diff_patch.c b/src/diff_patch.c
index 9c2eb885f..ecae3a8ed 100644
--- a/src/diff_patch.c
+++ b/src/diff_patch.c
@@ -133,9 +133,9 @@ static int diff_patch_load(git_patch *patch, git_diff_output *output)
incomplete_data =
(((patch->ofile.flags & GIT_DIFF_FLAG__NO_DATA) != 0 ||
- (patch->ofile.file->flags & GIT_DIFF_FLAG_VALID_OID) != 0) &&
+ (patch->ofile.file->flags & GIT_DIFF_FLAG_VALID_ID) != 0) &&
((patch->nfile.flags & GIT_DIFF_FLAG__NO_DATA) != 0 ||
- (patch->nfile.file->flags & GIT_DIFF_FLAG_VALID_OID) != 0));
+ (patch->nfile.file->flags & GIT_DIFF_FLAG_VALID_ID) != 0));
/* always try to load workdir content first because filtering may
* need 2x data size and this minimizes peak memory footprint
@@ -169,7 +169,7 @@ static int diff_patch_load(git_patch *patch, git_diff_output *output)
if (incomplete_data &&
patch->ofile.file->mode == patch->nfile.file->mode &&
patch->ofile.file->mode != GIT_FILEMODE_COMMIT &&
- git_oid_equal(&patch->ofile.file->oid, &patch->nfile.file->oid) &&
+ git_oid_equal(&patch->ofile.file->id, &patch->nfile.file->id) &&
patch->delta->status == GIT_DELTA_MODIFIED) /* not RENAMED/COPIED! */
patch->delta->status = GIT_DELTA_UNMODIFIED;
@@ -184,7 +184,7 @@ cleanup:
patch->delta->status != GIT_DELTA_UNMODIFIED &&
(patch->ofile.map.len || patch->nfile.map.len) &&
(patch->ofile.map.len != patch->nfile.map.len ||
- !git_oid_equal(&patch->ofile.file->oid, &patch->nfile.file->oid)))
+ !git_oid_equal(&patch->ofile.file->id, &patch->nfile.file->id)))
patch->flags |= GIT_DIFF_PATCH_DIFFABLE;
patch->flags |= GIT_DIFF_PATCH_LOADED;
@@ -315,7 +315,7 @@ static int diff_single_generate(diff_patch_with_delta *pd, git_xdiff_output *xo)
(has_old ? GIT_DELTA_MODIFIED : GIT_DELTA_ADDED) :
(has_old ? GIT_DELTA_DELETED : GIT_DELTA_UNTRACKED);
- if (git_oid_equal(&patch->nfile.file->oid, &patch->ofile.file->oid))
+ if (git_oid_equal(&patch->nfile.file->id, &patch->ofile.file->id))
pd->delta.status = GIT_DELTA_UNMODIFIED;
patch->delta = &pd->delta;
diff --git a/src/diff_print.c b/src/diff_print.c
index 7a70e2b18..1a09bed54 100644
--- a/src/diff_print.c
+++ b/src/diff_print.c
@@ -37,8 +37,8 @@ static int diff_print_info_init(
if (diff)
pi->flags = diff->opts.flags;
- if (diff && diff->opts.oid_abbrev != 0)
- pi->oid_strlen = diff->opts.oid_abbrev;
+ if (diff && diff->opts.id_abbrev != 0)
+ pi->oid_strlen = diff->opts.id_abbrev;
else if (!diff || !diff->repo)
pi->oid_strlen = GIT_ABBREV_DEFAULT;
else if (git_repository__cvar(
@@ -170,8 +170,8 @@ static int diff_print_one_raw(
git_buf_clear(out);
- git_oid_tostr(start_oid, pi->oid_strlen, &delta->old_file.oid);
- git_oid_tostr(end_oid, pi->oid_strlen, &delta->new_file.oid);
+ git_oid_tostr(start_oid, pi->oid_strlen, &delta->old_file.id);
+ git_oid_tostr(end_oid, pi->oid_strlen, &delta->new_file.id);
git_buf_printf(
out, ":%06o %06o %s... %s... %c",
@@ -203,8 +203,8 @@ static int diff_print_oid_range(
{
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
- git_oid_tostr(start_oid, oid_strlen, &delta->old_file.oid);
- git_oid_tostr(end_oid, oid_strlen, &delta->new_file.oid);
+ git_oid_tostr(start_oid, oid_strlen, &delta->old_file.id);
+ git_oid_tostr(end_oid, oid_strlen, &delta->new_file.id);
/* TODO: Match git diff more closely */
if (delta->old_file.mode == delta->new_file.mode) {
@@ -235,11 +235,11 @@ static int diff_delta_format_with_paths(
const char *oldpath = delta->old_file.path;
const char *newpath = delta->new_file.path;
- if (git_oid_iszero(&delta->old_file.oid)) {
+ if (git_oid_iszero(&delta->old_file.id)) {
oldpfx = "";
oldpath = "/dev/null";
}
- if (git_oid_iszero(&delta->new_file.oid)) {
+ if (git_oid_iszero(&delta->new_file.id)) {
newpfx = "";
newpath = "/dev/null";
}
@@ -452,20 +452,10 @@ static int diff_print_to_buffer_cb(
return git_buf_put(output, line->content, line->content_len);
}
-/* print a git_patch to a string buffer */
-int git_patch_to_str(
- char **string,
+/* print a git_patch to a git_buf */
+int git_patch_to_buf(
+ git_buf *out,
git_patch *patch)
{
- int error;
- git_buf output = GIT_BUF_INIT;
-
- if (!(error = git_patch_print(patch, diff_print_to_buffer_cb, &output)))
- *string = git_buf_detach(&output);
- else {
- git_buf_free(&output);
- *string = NULL;
- }
-
- return error;
+ return git_patch_print(patch, diff_print_to_buffer_cb, out);
}
diff --git a/src/diff_tform.c b/src/diff_tform.c
index 263a64d12..dfb59a3f8 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -91,7 +91,7 @@ static git_diff_delta *diff_delta__merge_like_cgit(
dup->status = a->status;
}
- git_oid_cpy(&dup->old_file.oid, &a->old_file.oid);
+ git_oid_cpy(&dup->old_file.id, &a->old_file.id);
dup->old_file.mode = a->old_file.mode;
dup->old_file.size = a->old_file.size;
dup->old_file.flags = a->old_file.flags;
@@ -124,7 +124,7 @@ static git_diff_delta *diff_delta__merge_like_cgit_reversed(
dup->status = b->status;
}
- git_oid_cpy(&dup->old_file.oid, &b->old_file.oid);
+ git_oid_cpy(&dup->old_file.id, &b->old_file.id);
dup->old_file.mode = b->old_file.mode;
dup->old_file.size = b->old_file.size;
dup->old_file.flags = b->old_file.flags;
@@ -375,7 +375,7 @@ static int insert_delete_side_of_split(
deleted->nfiles = 1;
memset(&deleted->new_file, 0, sizeof(deleted->new_file));
deleted->new_file.path = deleted->old_file.path;
- deleted->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ deleted->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
return git_vector_insert(onto, deleted);
}
@@ -408,7 +408,7 @@ static int apply_splits_and_deletes(
delta->nfiles = 1;
memset(&delta->old_file, 0, sizeof(delta->old_file));
delta->old_file.path = delta->new_file.path;
- delta->old_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
}
/* clean up delta before inserting into new list */
@@ -472,7 +472,7 @@ static int similarity_init(
info->blob = NULL;
git_buf_init(&info->data, 0);
- if (info->file->size > 0)
+ if (info->file->size > 0 || info->src == GIT_ITERATOR_TYPE_WORKDIR)
return 0;
return git_diff_file__resolve_zero_size(
@@ -510,7 +510,7 @@ static int similarity_sig(
(git_object **)&info->blob, info->repo,
info->odb_obj, GIT_OBJ_BLOB);
else
- error = git_blob_lookup(&info->blob, info->repo, &file->oid);
+ error = git_blob_lookup(&info->blob, info->repo, &file->id);
if (error < 0) {
/* if lookup fails, just skip this item in similarity calc */
@@ -572,21 +572,21 @@ static int similarity_measure(
/* if exact match is requested, force calculation of missing OIDs now */
if (exact_match) {
- if (git_oid_iszero(&a_file->oid) &&
+ if (git_oid_iszero(&a_file->id) &&
diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
!git_diff__oid_for_file(diff->repo, a_file->path,
- a_file->mode, a_file->size, &a_file->oid))
- a_file->flags |= GIT_DIFF_FLAG_VALID_OID;
+ a_file->mode, a_file->size, &a_file->id))
+ a_file->flags |= GIT_DIFF_FLAG_VALID_ID;
- if (git_oid_iszero(&b_file->oid) &&
+ if (git_oid_iszero(&b_file->id) &&
diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
!git_diff__oid_for_file(diff->repo, b_file->path,
- b_file->mode, b_file->size, &b_file->oid))
- b_file->flags |= GIT_DIFF_FLAG_VALID_OID;
+ b_file->mode, b_file->size, &b_file->id))
+ b_file->flags |= GIT_DIFF_FLAG_VALID_ID;
}
/* check OID match as a quick test */
- if (git_oid__cmp(&a_file->oid, &b_file->oid) == 0) {
+ if (git_oid__cmp(&a_file->id, &b_file->id) == 0) {
*score = 100;
return 0;
}
@@ -999,7 +999,7 @@ find_best_matches:
memcpy(&src->old_file, &swap, sizeof(src->old_file));
memset(&src->new_file, 0, sizeof(src->new_file));
src->new_file.path = src->old_file.path;
- src->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ src->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
num_updates++;
@@ -1024,7 +1024,7 @@ find_best_matches:
src->nfiles = 1;
memset(&src->old_file, 0, sizeof(src->old_file));
src->old_file.path = src->new_file.path;
- src->old_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ src->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
src->flags &= ~GIT_DIFF_FLAG__TO_SPLIT;
num_rewrites--;
diff --git a/src/graph.c b/src/graph.c
index 277f588ca..f39af5ed5 100644
--- a/src/graph.c
+++ b/src/graph.c
@@ -176,3 +176,17 @@ on_error:
git_revwalk_free(walk);
return -1;
}
+
+int git_graph_descendant_of(git_repository *repo, const git_oid *commit, const git_oid *ancestor)
+{
+ git_oid merge_base;
+ int error;
+
+ if (git_oid_equal(commit, ancestor))
+ return 0;
+
+ if ((error = git_merge_base(&merge_base, repo, commit, ancestor) < 0))
+ return error;
+
+ return git_oid_equal(&merge_base, ancestor);
+}
diff --git a/src/index.c b/src/index.c
index bb81f666e..7bc5d5b24 100644
--- a/src/index.c
+++ b/src/index.c
@@ -90,6 +90,7 @@ struct entry_long {
struct entry_srch_key {
const char *path;
+ int path_len;
int stage;
};
@@ -109,28 +110,49 @@ static int index_srch(const void *key, const void *array_member)
{
const struct entry_srch_key *srch_key = key;
const git_index_entry *entry = array_member;
- int ret;
+ int cmp, len1, len2, len;
- ret = strcmp(srch_key->path, entry->path);
+ len1 = srch_key->path_len;
+ len2 = strlen(entry->path);
+ len = len1 < len2 ? len1 : len2;
- if (ret == 0 && srch_key->stage != GIT_INDEX_STAGE_ANY)
- ret = srch_key->stage - GIT_IDXENTRY_STAGE(entry);
+ cmp = memcmp(srch_key->path, entry->path, len);
+ if (cmp)
+ return cmp;
+ if (len1 < len2)
+ return -1;
+ if (len1 > len2)
+ return 1;
- return ret;
+ if (srch_key->stage != GIT_INDEX_STAGE_ANY)
+ return srch_key->stage - GIT_IDXENTRY_STAGE(entry);
+
+ return 0;
}
static int index_isrch(const void *key, const void *array_member)
{
const struct entry_srch_key *srch_key = key;
const git_index_entry *entry = array_member;
- int ret;
+ int cmp, len1, len2, len;
- ret = strcasecmp(srch_key->path, entry->path);
+ len1 = srch_key->path_len;
+ len2 = strlen(entry->path);
+ len = len1 < len2 ? len1 : len2;
- if (ret == 0 && srch_key->stage != GIT_INDEX_STAGE_ANY)
- ret = srch_key->stage - GIT_IDXENTRY_STAGE(entry);
+ cmp = strncasecmp(srch_key->path, entry->path, len);
- return ret;
+ if (cmp)
+ return cmp;
+ if (len1 < len2)
+ return -1;
+ if (len1 > len2)
+ return 1;
+
+ if (srch_key->stage != GIT_INDEX_STAGE_ANY)
+ return srch_key->stage - GIT_IDXENTRY_STAGE(entry);
+
+ return 0;
}
static int index_cmp_path(const void *a, const void *b)
@@ -579,7 +601,7 @@ const git_index_entry *git_index_get_bypath(
git_vector_sort(&index->entries);
- if (git_index__find(&pos, index, path, stage) < 0) {
+ if (git_index__find(&pos, index, path, strlen(path), stage) < 0) {
giterr_set(GITERR_INDEX, "Index does not contain %s", path);
return NULL;
}
@@ -643,7 +665,7 @@ static int index_entry_init(
git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode);
- entry->oid = oid;
+ entry->id = oid;
entry->path = git__strdup(rel_path);
GITERR_CHECK_ALLOC(entry->path);
@@ -701,6 +723,101 @@ static git_index_entry *index_entry_dup(const git_index_entry *source_entry)
return entry;
}
+static int has_file_name(git_index *index,
+ const git_index_entry *entry, size_t pos, int ok_to_replace)
+{
+ int retval = 0;
+ size_t len = strlen(entry->path);
+ int stage = GIT_IDXENTRY_STAGE(entry);
+ const char *name = entry->path;
+
+ while (pos < index->entries.length) {
+ git_index_entry *p = index->entries.contents[pos++];
+
+ if (len >= strlen(p->path))
+ break;
+ if (memcmp(name, p->path, len))
+ break;
+ if (GIT_IDXENTRY_STAGE(p) != stage)
+ continue;
+ if (p->path[len] != '/')
+ continue;
+ retval = -1;
+ if (!ok_to_replace)
+ break;
+ git_vector_remove(&index->entries, --pos);
+ }
+ return retval;
+}
+
+/*
+ * Do we have another file with a pathname that is a proper
+ * subset of the name we're trying to add?
+ */
+static int has_dir_name(git_index *index,
+ const git_index_entry *entry, int ok_to_replace)
+{
+ int retval = 0;
+ int stage = GIT_IDXENTRY_STAGE(entry);
+ const char *name = entry->path;
+ const char *slash = name + strlen(name);
+
+ for (;;) {
+ size_t len, position;
+
+ for (;;) {
+ if (*--slash == '/')
+ break;
+ if (slash <= entry->path)
+ return retval;
+ }
+ len = slash - name;
+
+ if (git_index__find(&position, index, name, len, stage) == 0) {
+ retval = -1;
+ if (!ok_to_replace)
+ break;
+
+ git_vector_remove(&index->entries, position);
+ continue;
+ }
+
+ /*
+ * Trivial optimization: if we find an entry that
+ * already matches the sub-directory, then we know
+ * we're ok, and we can exit.
+ */
+ while (position < index->entries.length) {
+ git_index_entry *p = index->entries.contents[position];
+
+ if ((strlen(p->path) <= len) ||
+ (p->path[len] != '/') ||
+ memcmp(p->path, name, len))
+ break; /* not our subdirectory */
+
+ if (GIT_IDXENTRY_STAGE(p) == stage)
+ return retval;
+
+ position++;
+ }
+ }
+ return retval;
+}
+
+static int check_file_directory_collision(git_index *index,
+ git_index_entry *entry, size_t pos, int ok_to_replace)
+{
+ int retval = has_file_name(index, entry, pos, ok_to_replace);
+ retval = retval + has_dir_name(index, entry, ok_to_replace);
+
+ if (retval) {
+ giterr_set(GITERR_INDEX, "'%s' appears as both a file an a directory", entry->path);
+ return -1;
+ }
+
+ return 0;
+}
+
static int index_insert(git_index *index, git_index_entry *entry, int replace)
{
size_t path_length, position;
@@ -720,13 +837,16 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace)
/* look if an entry with this path already exists */
if (!git_index__find(
- &position, index, entry->path, GIT_IDXENTRY_STAGE(entry))) {
+ &position, index, entry->path, strlen(entry->path),
+ GIT_IDXENTRY_STAGE(entry))) {
existing = (git_index_entry **)&index->entries.contents[position];
-
/* update filemode to existing values if stat is not trusted */
entry->mode = index_merge_mode(index, *existing, entry->mode);
}
+ if (check_file_directory_collision(index, entry, position, replace) < 0)
+ return -1;
+
/* if replacing is not requested or no existing entry exists, just
* insert entry at the end; the index is no longer sorted
*/
@@ -757,9 +877,9 @@ static int index_conflict_to_reuc(git_index *index, const char *path)
our_mode = conflict_entries[1] == NULL ? 0 : conflict_entries[1]->mode;
their_mode = conflict_entries[2] == NULL ? 0 : conflict_entries[2]->mode;
- ancestor_oid = conflict_entries[0] == NULL ? NULL : &conflict_entries[0]->oid;
- our_oid = conflict_entries[1] == NULL ? NULL : &conflict_entries[1]->oid;
- their_oid = conflict_entries[2] == NULL ? NULL : &conflict_entries[2]->oid;
+ ancestor_oid = conflict_entries[0] == NULL ? NULL : &conflict_entries[0]->id;
+ our_oid = conflict_entries[1] == NULL ? NULL : &conflict_entries[1]->id;
+ their_oid = conflict_entries[2] == NULL ? NULL : &conflict_entries[2]->id;
if ((ret = git_index_reuc_add(index, path, ancestor_mode, ancestor_oid,
our_mode, our_oid, their_mode, their_oid)) >= 0)
@@ -832,7 +952,7 @@ int git_index_remove(git_index *index, const char *path, int stage)
git_vector_sort(&index->entries);
- if (git_index__find(&position, index, path, stage) < 0) {
+ if (git_index__find(&position, index, path, strlen(path), stage) < 0) {
giterr_set(GITERR_INDEX, "Index does not contain %s at stage %d",
path, stage);
return GIT_ENOTFOUND;
@@ -889,13 +1009,14 @@ int git_index_remove_directory(git_index *index, const char *dir, int stage)
}
int git_index__find(
- size_t *at_pos, git_index *index, const char *path, int stage)
+ size_t *at_pos, git_index *index, const char *path, int path_len, int stage)
{
struct entry_srch_key srch_key;
assert(path);
srch_key.path = path;
+ srch_key.path_len = path_len;
srch_key.stage = stage;
return git_vector_bsearch2(
@@ -937,6 +1058,7 @@ size_t git_index__prefix_position(git_index *index, const char *path)
size_t pos;
srch_key.path = path;
+ srch_key.path_len = strlen(path);
srch_key.stage = 0;
git_vector_sort(&index->entries);
@@ -1515,7 +1637,7 @@ static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffe
dest->uid = ntohl(source->uid);
dest->gid = ntohl(source->gid);
dest->file_size = ntohl(source->file_size);
- git_oid_cpy(&dest->oid, &source->oid);
+ git_oid_cpy(&dest->id, &source->oid);
dest->flags = ntohs(source->flags);
if (dest->flags & GIT_IDXENTRY_EXTENDED) {
@@ -1756,7 +1878,7 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
ondisk->gid = htonl(entry->gid);
ondisk->file_size = htonl((uint32_t)entry->file_size);
- git_oid_cpy(&ondisk->oid, &entry->oid);
+ git_oid_cpy(&ondisk->oid, &entry->id);
ondisk->flags = htons(entry->flags);
@@ -1983,7 +2105,7 @@ static int read_tree_cb(
GITERR_CHECK_ALLOC(entry);
entry->mode = tentry->attr;
- entry->oid = tentry->oid;
+ entry->id = tentry->oid;
/* look for corresponding old entry and copy data to new entry */
if (data->old_entries) {
@@ -1991,13 +2113,14 @@ static int read_tree_cb(
struct entry_srch_key skey;
skey.path = path.ptr;
+ skey.path_len = strlen(path.ptr);
skey.stage = 0;
if (!git_vector_bsearch2(
&pos, data->old_entries, data->entries_search, &skey) &&
(old_entry = git_vector_get(data->old_entries, pos)) != NULL &&
entry->mode == old_entry->mode &&
- git_oid_equal(&entry->oid, &old_entry->oid))
+ git_oid_equal(&entry->id, &old_entry->id))
{
memcpy(entry, old_entry, sizeof(*entry));
entry->flags_extended = 0;
@@ -2109,7 +2232,7 @@ int git_index_add_all(
/* skip ignored items that are not already in the index */
if ((flags & GIT_INDEX_ADD_FORCE) == 0 &&
git_iterator_current_is_ignored(wditer) &&
- git_index__find(&existing, index, wd->path, 0) < 0)
+ git_index__find(&existing, index, wd->path, strlen(wd->path), 0) < 0)
continue;
/* issue notification callback if requested */
@@ -2135,7 +2258,7 @@ int git_index_add_all(
error = -1;
break;
}
- entry->oid = blobid;
+ entry->id = blobid;
/* add working directory item to index */
if ((error = index_insert(index, entry, 1)) < 0) {
diff --git a/src/index.h b/src/index.h
index 4c448fabf..3dea4aa14 100644
--- a/src/index.h
+++ b/src/index.h
@@ -56,7 +56,7 @@ extern int git_index_entry__cmp(const void *a, const void *b);
extern int git_index_entry__cmp_icase(const void *a, const void *b);
extern int git_index__find(
- size_t *at_pos, git_index *index, const char *path, int stage);
+ size_t *at_pos, git_index *index, const char *path, int path_len, int stage);
extern void git_index__set_ignore_case(git_index *index, bool ignore_case);
diff --git a/src/indexer.c b/src/indexer.c
index 6132571cc..346870faa 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -5,8 +5,6 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include <zlib.h>
-
#include "git2/indexer.h"
#include "git2/object.h"
@@ -18,7 +16,7 @@
#include "filebuf.h"
#include "oid.h"
#include "oidmap.h"
-#include "compress.h"
+#include "zstream.h"
#define UINT31_MAX (0x7FFFFFFF)
@@ -355,7 +353,7 @@ static int hash_and_save(git_indexer *idx, git_rawobj *obj, git_off_t entry_star
git_oid oid;
size_t entry_size;
struct entry *entry;
- struct git_pack_entry *pentry;
+ struct git_pack_entry *pentry = NULL;
entry = git__calloc(1, sizeof(*entry));
GITERR_CHECK_ALLOC(entry);
@@ -379,6 +377,7 @@ static int hash_and_save(git_indexer *idx, git_rawobj *obj, git_off_t entry_star
return save_entry(idx, entry, pentry, entry_start);
on_error:
+ git__free(pentry);
git__free(entry);
git__free(obj->data);
return -1;
@@ -634,7 +633,7 @@ static int inject_object(git_indexer *idx, git_oid *id)
{
git_odb_object *obj;
struct entry *entry;
- struct git_pack_entry *pentry;
+ struct git_pack_entry *pentry = NULL;
git_oid foo = {{0}};
unsigned char hdr[64];
git_buf buf = GIT_BUF_INIT;
@@ -643,9 +642,6 @@ static int inject_object(git_indexer *idx, git_oid *id)
size_t len, hdr_len;
int error;
- entry = git__calloc(1, sizeof(*entry));
- GITERR_CHECK_ALLOC(entry);
-
entry_start = seek_back_trailer(idx);
if (git_odb_read(&obj, idx->odb, id) < 0)
@@ -654,15 +650,18 @@ static int inject_object(git_indexer *idx, git_oid *id)
data = git_odb_object_data(obj);
len = git_odb_object_size(obj);
+ entry = git__calloc(1, sizeof(*entry));
+ GITERR_CHECK_ALLOC(entry);
+
entry->crc = crc32(0L, Z_NULL, 0);
/* Write out the object header */
hdr_len = git_packfile__object_header(hdr, len, git_odb_object_type(obj));
git_filebuf_write(&idx->pack_file, hdr, hdr_len);
idx->pack->mwf.size += hdr_len;
- entry->crc = crc32(entry->crc, hdr, hdr_len);
+ entry->crc = crc32(entry->crc, hdr, (uInt)hdr_len);
- if ((error = git__compress(&buf, data, len)) < 0)
+ if ((error = git_zstream_deflatebuf(&buf, data, len)) < 0)
goto cleanup;
/* And then the compressed object */
@@ -684,10 +683,14 @@ static int inject_object(git_indexer *idx, git_oid *id)
git_oid_cpy(&entry->oid, id);
idx->off = entry_start + hdr_len + len;
- if ((error = save_entry(idx, entry, pentry, entry_start)) < 0)
- git__free(pentry);
+ error = save_entry(idx, entry, pentry, entry_start);
cleanup:
+ if (error) {
+ git__free(entry);
+ git__free(pentry);
+ }
+
git_odb_object_free(obj);
return error;
}
diff --git a/src/iterator.c b/src/iterator.c
index 0e7d0db85..401b5de93 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -447,7 +447,7 @@ static int tree_iterator__update_entry(tree_iterator *ti)
te = tf->entries[tf->current]->te;
ti->entry.mode = te->attr;
- git_oid_cpy(&ti->entry.oid, &te->oid);
+ git_oid_cpy(&ti->entry.id, &te->oid);
ti->entry.path = tree_iterator__current_filename(ti, te);
GITERR_CHECK_ALLOC(ti->entry.path);
diff --git a/src/merge.c b/src/merge.c
index c0be37dd8..ac973efd0 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -42,6 +42,7 @@
#include "git2/sys/index.h"
#define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
+#define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
typedef enum {
TREE_IDX_ANCESTOR = 0,
@@ -316,7 +317,7 @@ GIT_INLINE(int) index_entry_cmp(const git_index_entry *a, const git_index_entry
return (b->path == NULL) ? 0 : 1;
if ((value = a->mode - b->mode) == 0 &&
- (value = git_oid__cmp(&a->oid, &b->oid)) == 0)
+ (value = git_oid__cmp(&a->id, &b->id)) == 0)
value = strcmp(a->path, b->path);
return value;
@@ -447,7 +448,6 @@ static int merge_conflict_resolve_one_removed(
return error;
}
-
static int merge_conflict_resolve_one_renamed(
int *resolved,
git_merge_diff_list *diff_list,
@@ -478,12 +478,12 @@ static int merge_conflict_resolve_one_renamed(
conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
return 0;
- ours_changed = (git_oid__cmp(&conflict->ancestor_entry.oid, &conflict->our_entry.oid) != 0);
- theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.oid, &conflict->their_entry.oid) != 0);
+ ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0);
+ theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0);
/* if both are modified (and not to a common target) require a merge */
if (ours_changed && theirs_changed &&
- git_oid__cmp(&conflict->our_entry.oid, &conflict->their_entry.oid) != 0)
+ git_oid__cmp(&conflict->our_entry.id, &conflict->their_entry.id) != 0)
return 0;
if ((merged = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry))) == NULL)
@@ -511,8 +511,9 @@ static int merge_conflict_resolve_automerge(
int *resolved,
git_merge_diff_list *diff_list,
const git_merge_diff *conflict,
- unsigned int automerge_flags)
+ unsigned int merge_file_favor)
{
+ git_merge_file_options merge_file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
@@ -526,13 +527,18 @@ static int merge_conflict_resolve_automerge(
*resolved = 0;
- if (automerge_flags == GIT_MERGE_AUTOMERGE_NONE)
- return 0;
+ merge_file_opts.favor = merge_file_favor;
/* Reject D/F conflicts */
if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
return 0;
+ /* Reject submodules. */
+ if (S_ISGITLINK(conflict->ancestor_entry.mode) ||
+ S_ISGITLINK(conflict->our_entry.mode) ||
+ S_ISGITLINK(conflict->their_entry.mode))
+ return 0;
+
/* Reject link/file conflicts. */
if ((S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->our_entry.mode)) ||
(S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->their_entry.mode)))
@@ -548,11 +554,15 @@ static int merge_conflict_resolve_automerge(
strcmp(conflict->ancestor_entry.path, conflict->their_entry.path) != 0)
return 0;
+ /* Reject binary conflicts */
+ if (conflict->binary)
+ return 0;
+
if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 ||
(error = git_merge_file_input_from_index_entry(&ancestor, diff_list->repo, &conflict->ancestor_entry)) < 0 ||
(error = git_merge_file_input_from_index_entry(&ours, diff_list->repo, &conflict->our_entry)) < 0 ||
(error = git_merge_file_input_from_index_entry(&theirs, diff_list->repo, &conflict->their_entry)) < 0 ||
- (error = git_merge_files(&result, &ancestor, &ours, &theirs, automerge_flags)) < 0 ||
+ (error = git_merge_files(&result, &ancestor, &ours, &theirs, &merge_file_opts)) < 0 ||
!result.automergeable ||
(error = git_odb_write(&automerge_oid, odb, result.data, result.len, GIT_OBJ_BLOB)) < 0)
goto done;
@@ -565,7 +575,7 @@ static int merge_conflict_resolve_automerge(
index_entry->file_size = result.len;
index_entry->mode = result.mode;
- git_oid_cpy(&index_entry->oid, &automerge_oid);
+ git_oid_cpy(&index_entry->id, &automerge_oid);
git_vector_insert(&diff_list->staged, index_entry);
git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);
@@ -586,7 +596,7 @@ static int merge_conflict_resolve(
int *out,
git_merge_diff_list *diff_list,
const git_merge_diff *conflict,
- unsigned int automerge_flags)
+ unsigned int merge_file_favor)
{
int resolved = 0;
int error = 0;
@@ -596,16 +606,14 @@ static int merge_conflict_resolve(
if ((error = merge_conflict_resolve_trivial(&resolved, diff_list, conflict)) < 0)
goto done;
- if (automerge_flags != GIT_MERGE_AUTOMERGE_NONE) {
- if (!resolved && (error = merge_conflict_resolve_one_removed(&resolved, diff_list, conflict)) < 0)
- goto done;
+ if (!resolved && (error = merge_conflict_resolve_one_removed(&resolved, diff_list, conflict)) < 0)
+ goto done;
- if (!resolved && (error = merge_conflict_resolve_one_renamed(&resolved, diff_list, conflict)) < 0)
- goto done;
+ if (!resolved && (error = merge_conflict_resolve_one_renamed(&resolved, diff_list, conflict)) < 0)
+ goto done;
- if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, automerge_flags)) < 0)
- goto done;
- }
+ if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, merge_file_favor)) < 0)
+ goto done;
*out = resolved;
@@ -635,7 +643,7 @@ static int index_entry_similarity_exact(
GIT_UNUSED(cache);
GIT_UNUSED(opts);
- if (git_oid__cmp(&a->oid, &b->oid) == 0)
+ if (git_oid__cmp(&a->id, &b->id) == 0)
return 100;
return 0;
@@ -654,10 +662,10 @@ static int index_entry_similarity_calc(
*out = NULL;
- if ((error = git_blob_lookup(&blob, repo, &entry->oid)) < 0)
+ if ((error = git_blob_lookup(&blob, repo, &entry->id)) < 0)
return error;
- git_oid_cpy(&diff_file.oid, &entry->oid);
+ git_oid_cpy(&diff_file.id, &entry->id);
diff_file.path = entry->path;
diff_file.size = entry->file_size;
diff_file.mode = entry->mode;
@@ -1147,6 +1155,44 @@ GIT_INLINE(int) merge_diff_detect_type(
return 0;
}
+GIT_INLINE(int) merge_diff_detect_binary(
+ git_repository *repo,
+ git_merge_diff *conflict)
+{
+ git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL;
+ int error = 0;
+
+ if (GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->ancestor_entry)) {
+ if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor_entry.id)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(ancestor_blob);
+ }
+
+ if (!conflict->binary &&
+ GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->our_entry)) {
+ if ((error = git_blob_lookup(&our_blob, repo, &conflict->our_entry.id)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(our_blob);
+ }
+
+ if (!conflict->binary &&
+ GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->their_entry)) {
+ if ((error = git_blob_lookup(&their_blob, repo, &conflict->their_entry.id)) < 0)
+ goto done;
+
+ conflict->binary = git_blob_is_binary(their_blob);
+ }
+
+done:
+ git_blob_free(ancestor_blob);
+ git_blob_free(our_blob);
+ git_blob_free(their_blob);
+
+ return error;
+}
+
GIT_INLINE(int) index_entry_dup(
git_index_entry *out,
git_pool *pool,
@@ -1176,7 +1222,7 @@ GIT_INLINE(int) merge_delta_type_from_index_entries(
return GIT_DELTA_TYPECHANGE;
else if(S_ISLNK(ancestor->mode) ^ S_ISLNK(other->mode))
return GIT_DELTA_TYPECHANGE;
- else if (git_oid__cmp(&ancestor->oid, &other->oid) ||
+ else if (git_oid__cmp(&ancestor->id, &other->id) ||
ancestor->mode != other->mode)
return GIT_DELTA_MODIFIED;
@@ -1218,6 +1264,7 @@ static int merge_diff_list_insert_conflict(
if ((conflict = merge_diff_from_index_entries(diff_list, tree_items)) == NULL ||
merge_diff_detect_type(conflict) < 0 ||
merge_diff_detect_df_conflict(merge_df_data, conflict) < 0 ||
+ merge_diff_detect_binary(diff_list->repo, conflict) < 0 ||
git_vector_insert(&diff_list->conflicts, conflict) < 0)
return -1;
@@ -1450,7 +1497,7 @@ static int merge_index_insert_reuc(
}
mode[idx] = entry->mode;
- oid[idx] = &entry->oid;
+ oid[idx] = &entry->id;
return git_index_reuc_add(index, entry->path,
mode[0], oid[0], mode[1], oid[1], mode[2], oid[2]);
@@ -1589,7 +1636,7 @@ int git_merge_trees(
git_vector_foreach(&changes, i, conflict) {
int resolved = 0;
- if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.automerge_flags)) < 0)
+ if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor)) < 0)
goto done;
if (!resolved)
@@ -2064,7 +2111,7 @@ static int merge_ancestor_head(
if ((error = git_merge_base_many(&ancestor_oid, repo, their_heads_len + 1, oids)) < 0)
goto on_error;
- error = git_merge_head_from_oid(ancestor_head, repo, &ancestor_oid);
+ error = git_merge_head_from_id(ancestor_head, repo, &ancestor_oid);
on_error:
git__free(oids);
@@ -2119,6 +2166,8 @@ static int merge_normalize_opts(
git_repository *repo,
git_merge_opts *opts,
const git_merge_opts *given,
+ const git_merge_head *ancestor_head,
+ const git_merge_head *our_head,
size_t their_heads_len,
const git_merge_head **their_heads)
{
@@ -2138,8 +2187,20 @@ static int merge_normalize_opts(
if (!opts->checkout_opts.checkout_strategy)
opts->checkout_opts.checkout_strategy = default_checkout_strategy;
- if (!opts->checkout_opts.our_label)
- opts->checkout_opts.our_label = "HEAD";
+ /* TODO: for multiple ancestors in merge-recursive, this is "merged common ancestors" */
+ if (!opts->checkout_opts.ancestor_label) {
+ if (ancestor_head && ancestor_head->commit)
+ opts->checkout_opts.ancestor_label = git_commit_summary(ancestor_head->commit);
+ else
+ opts->checkout_opts.ancestor_label = "ancestor";
+ }
+
+ if (!opts->checkout_opts.our_label) {
+ if (our_head && our_head->ref_name)
+ opts->checkout_opts.our_label = our_head->ref_name;
+ else
+ opts->checkout_opts.our_label = "ours";
+ }
if (!opts->checkout_opts.their_label) {
if (their_heads_len == 1 && their_heads[0]->ref_name)
@@ -2269,7 +2330,7 @@ done:
static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
{
- git_tree *head_tree = NULL;
+ git_index *index_repo = NULL;
git_diff *wd_diff_list = NULL;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
int error = 0;
@@ -2280,9 +2341,6 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
- if ((error = git_repository_head_tree(&head_tree, repo)) < 0)
- goto done;
-
/* Workdir changes may exist iff they do not conflict with changes that
* will be applied by the merge (including conflicts). Ensure that there
* are no changes in the workdir to these paths.
@@ -2290,13 +2348,13 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
opts.pathspec.count = merged_paths->length;
opts.pathspec.strings = (char **)merged_paths->contents;
- if ((error = git_diff_tree_to_workdir(&wd_diff_list, repo, head_tree, &opts)) < 0)
+ if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, index_repo, &opts)) < 0)
goto done;
*conflicts = wd_diff_list->deltas.length;
done:
- git_tree_free(head_tree);
+ git_index_free(index_repo);
git_diff_free(wd_diff_list);
return error;
@@ -2337,12 +2395,21 @@ int git_merge__indexes(git_repository *repo, git_index *index_new)
goto done;
}
- /* Update the new index */
+ /* Remove removed items from the index */
git_vector_foreach(&paths, i, path) {
- if ((e = git_index_get_bypath(index_new, path, 0)) != NULL)
- error = git_index_add(index_repo, e);
- else
- error = git_index_remove(index_repo, path, 0);
+ if (git_index_get_bypath(index_new, path, 0) == NULL) {
+ if ((error = git_index_remove(index_repo, path, 0)) < 0 &&
+ error != GIT_ENOTFOUND)
+ goto done;
+ }
+ }
+
+ /* Add updated items to the index */
+ git_vector_foreach(&paths, i, path) {
+ if ((e = git_index_get_bypath(index_new, path, 0)) != NULL) {
+ if ((error = git_index_add(index_repo, e)) < 0)
+ goto done;
+ }
}
/* Add conflicts */
@@ -2434,9 +2501,6 @@ int git_merge(
their_trees = git__calloc(their_heads_len, sizeof(git_tree *));
GITERR_CHECK_ALLOC(their_trees);
- if ((error = merge_normalize_opts(repo, &opts, given_opts, their_heads_len, their_heads)) < 0)
- goto on_error;
-
if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0)
goto on_error;
@@ -2448,6 +2512,9 @@ int git_merge(
error != GIT_ENOTFOUND)
goto on_error;
+ if ((error = merge_normalize_opts(repo, &opts, given_opts, ancestor_head, our_head, their_heads_len, their_heads)) < 0)
+ goto on_error;
+
if (their_heads_len == 1 &&
ancestor_head != NULL &&
(merge_check_uptodate(result, ancestor_head, their_heads[0]) ||
@@ -2554,7 +2621,7 @@ int git_merge_result_is_fastforward(git_merge_result *merge_result)
return merge_result->is_fastforward;
}
-int git_merge_result_fastforward_oid(git_oid *out, git_merge_result *merge_result)
+int git_merge_result_fastforward_id(git_oid *out, git_merge_result *merge_result)
{
assert(out && merge_result);
@@ -2638,7 +2705,7 @@ int git_merge_head_from_ref(
return error;
}
-int git_merge_head_from_oid(
+int git_merge_head_from_id(
git_merge_head **out,
git_repository *repo,
const git_oid *oid)
diff --git a/src/merge.h b/src/merge.h
index b240f6c44..dda023528 100644
--- a/src/merge.h
+++ b/src/merge.h
@@ -106,6 +106,8 @@ typedef struct {
git_index_entry their_entry;
git_delta_t their_status;
+
+ int binary:1;
} git_merge_diff;
/** Internal structure for merge inputs */
diff --git a/src/merge_file.c b/src/merge_file.c
index 48fc46e57..986fbf9fe 100644
--- a/src/merge_file.c
+++ b/src/merge_file.c
@@ -77,7 +77,7 @@ int git_merge_file_input_from_index_entry(
return 0;
if ((error = git_repository_odb(&odb, repo)) < 0 ||
- (error = git_odb_read(&input->odb_object, odb, &entry->oid)) < 0)
+ (error = git_odb_read(&input->odb_object, odb, &entry->id)) < 0)
goto done;
input->mode = entry->mode;
@@ -108,7 +108,7 @@ int git_merge_file_input_from_diff_file(
return 0;
if ((error = git_repository_odb(&odb, repo)) < 0 ||
- (error = git_odb_read(&input->odb_object, odb, &file->oid)) < 0)
+ (error = git_odb_read(&input->odb_object, odb, &file->id)) < 0)
goto done;
input->mode = file->mode;
@@ -130,7 +130,7 @@ int git_merge_files(
git_merge_file_input *ancestor,
git_merge_file_input *ours,
git_merge_file_input *theirs,
- git_merge_automerge_flags flags)
+ git_merge_file_options *opts)
{
xmparam_t xmparam;
mmbuffer_t mmbuffer;
@@ -152,11 +152,19 @@ int git_merge_files(
out->path = merge_file_best_path(ancestor, ours, theirs);
out->mode = merge_file_best_mode(ancestor, ours, theirs);
- if (flags == GIT_MERGE_AUTOMERGE_FAVOR_OURS)
+ if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_OURS)
xmparam.favor = XDL_MERGE_FAVOR_OURS;
-
- if (flags == GIT_MERGE_AUTOMERGE_FAVOR_THEIRS)
+ else if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_THEIRS)
xmparam.favor = XDL_MERGE_FAVOR_THEIRS;
+ else if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_UNION)
+ xmparam.favor = XDL_MERGE_FAVOR_UNION;
+
+ xmparam.level =
+ (opts && (opts->flags & GIT_MERGE_FILE_SIMPLIFY_ALNUM)) ?
+ XDL_MERGE_ZEALOUS_ALNUM : XDL_MERGE_ZEALOUS;
+
+ if (opts && opts->style == GIT_MERGE_FILE_STYLE_DIFF3)
+ xmparam.style = XDL_MERGE_DIFF3;
if ((xdl_result = xdl_merge(&ancestor->mmfile, &ours->mmfile,
&theirs->mmfile, &xmparam, &mmbuffer)) < 0) {
diff --git a/src/merge_file.h b/src/merge_file.h
index 0af2f0a57..332be490b 100644
--- a/src/merge_file.h
+++ b/src/merge_file.h
@@ -34,6 +34,27 @@ typedef struct {
#define GIT_MERGE_FILE_RESULT_INIT {0}
+typedef enum {
+ /* Condense non-alphanumeric regions for simplified diff file */
+ GIT_MERGE_FILE_SIMPLIFY_ALNUM = (1 << 0),
+} git_merge_file_flags_t;
+
+typedef enum {
+ /* Create standard conflicted merge files */
+ GIT_MERGE_FILE_STYLE_MERGE = 0,
+
+ /* Create diff3-style files */
+ GIT_MERGE_FILE_STYLE_DIFF3 = 1,
+} git_merge_file_style_t;
+
+typedef struct {
+ git_merge_file_favor_t favor;
+ git_merge_file_flags_t flags;
+ git_merge_file_style_t style;
+} git_merge_file_options;
+
+#define GIT_MERGE_FILE_OPTIONS_INIT {0}
+
int git_merge_file_input_from_index_entry(
git_merge_file_input *input,
git_repository *repo,
@@ -49,7 +70,7 @@ int git_merge_files(
git_merge_file_input *ancestor,
git_merge_file_input *ours,
git_merge_file_input *theirs,
- git_merge_automerge_flags flags);
+ git_merge_file_options *opts);
GIT_INLINE(void) git_merge_file_input_free(git_merge_file_input *input)
{
diff --git a/src/message.c b/src/message.c
index 0eff426f2..07b2569ad 100644
--- a/src/message.c
+++ b/src/message.c
@@ -21,7 +21,7 @@ static size_t line_length_without_trailing_spaces(const char *line, size_t len)
/* Greatly inspired from git.git "stripspace" */
/* see https://github.com/git/git/blob/497215d8811ac7b8955693ceaad0899ecd894ed2/builtin/stripspace.c#L4-67 */
-int git_message__prettify(git_buf *message_out, const char *message, int strip_comments)
+int git_message_prettify(git_buf *message_out, const char *message, int strip_comments)
{
const size_t message_len = strlen(message);
@@ -29,6 +29,8 @@ int git_message__prettify(git_buf *message_out, const char *message, int strip_c
size_t i, line_length, rtrimmed_line_length;
char *next_newline;
+ git_buf_sanitize(message_out);
+
for (i = 0; i < strlen(message); i += line_length) {
next_newline = memchr(message + i, '\n', message_len - i);
@@ -58,29 +60,3 @@ int git_message__prettify(git_buf *message_out, const char *message, int strip_c
return git_buf_oom(message_out) ? -1 : 0;
}
-
-int git_message_prettify(char *message_out, size_t buffer_size, const char *message, int strip_comments)
-{
- git_buf buf = GIT_BUF_INIT;
- ssize_t out_size = -1;
-
- if (message_out && buffer_size)
- *message_out = '\0';
-
- if (git_message__prettify(&buf, message, strip_comments) < 0)
- goto done;
-
- if (message_out && buf.size + 1 > buffer_size) { /* +1 for NUL byte */
- giterr_set(GITERR_INVALID, "Buffer too short to hold the cleaned message");
- goto done;
- }
-
- if (message_out)
- git_buf_copy_cstr(message_out, buffer_size, &buf);
-
- out_size = buf.size + 1;
-
-done:
- git_buf_free(&buf);
- return (int)out_size;
-}
diff --git a/src/notes.c b/src/notes.c
index 795904917..ffe5d345a 100644
--- a/src/notes.c
+++ b/src/notes.c
@@ -313,7 +313,7 @@ static int note_new(git_note **out, git_oid *note_oid, git_blob *blob)
note = (git_note *)git__malloc(sizeof(git_note));
GITERR_CHECK_ALLOC(note);
- git_oid_cpy(&note->oid, note_oid);
+ git_oid_cpy(&note->id, note_oid);
note->message = git__strdup((char *)git_blob_rawcontent(blob));
GITERR_CHECK_ALLOC(note->message);
@@ -508,10 +508,10 @@ const char * git_note_message(const git_note *note)
return note->message;
}
-const git_oid * git_note_oid(const git_note *note)
+const git_oid * git_note_id(const git_note *note)
{
assert(note);
- return &note->oid;
+ return &note->id;
}
void git_note_free(git_note *note)
@@ -640,7 +640,7 @@ int git_note_next(
if ((error = git_iterator_current(&item, it)) < 0)
return error;
- git_oid_cpy(note_id, &item->oid);
+ git_oid_cpy(note_id, &item->id);
if (!(error = process_entry_path(item->path, annotated_id)))
git_iterator_advance(NULL, it);
diff --git a/src/notes.h b/src/notes.h
index 39e18b621..e9cfa00fa 100644
--- a/src/notes.h
+++ b/src/notes.h
@@ -21,7 +21,7 @@
"Notes removed by 'git_note_remove' from libgit2"
struct git_note {
- git_oid oid;
+ git_oid id;
char *message;
};
diff --git a/src/odb.c b/src/odb.c
index b208b279e..b413f83b4 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -949,6 +949,9 @@ int git_odb_stream_read(git_odb_stream *stream, char *buffer, size_t len)
void git_odb_stream_free(git_odb_stream *stream)
{
+ if (stream == NULL)
+ return;
+
git__free(stream->hash_ctx);
stream->free(stream);
}
diff --git a/src/oid.c b/src/oid.c
index d56b6af24..567b6cf06 100644
--- a/src/oid.c
+++ b/src/oid.c
@@ -314,6 +314,9 @@ git_oid_shorten *git_oid_shorten_new(size_t min_length)
void git_oid_shorten_free(git_oid_shorten *os)
{
+ if (os == NULL)
+ return;
+
git__free(os->nodes);
git__free(os);
}
diff --git a/src/pack-objects.c b/src/pack-objects.c
index 335944c0c..8b65ac26a 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -7,7 +7,7 @@
#include "pack-objects.h"
-#include "compress.h"
+#include "zstream.h"
#include "delta.h"
#include "iterator.h"
#include "netops.h"
@@ -61,6 +61,9 @@ struct pack_write_context {
/* The minimal interval between progress updates (in seconds). */
#define MIN_PROGRESS_UPDATE_INTERVAL 0.5
+/* Size of the buffer to feed to zlib */
+#define COMPRESS_BUFLEN (1024 * 1024)
+
static unsigned name_hash(const char *name)
{
unsigned c, hash = 0;
@@ -127,6 +130,7 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo)
pb->nr_threads = 1; /* do not spawn any thread by default */
if (git_hash_ctx_init(&pb->ctx) < 0 ||
+ git_zstream_init(&pb->zstream) < 0 ||
git_repository_odb(&pb->odb, repo) < 0 ||
packbuilder_config(pb) < 0)
goto on_error;
@@ -275,78 +279,89 @@ on_error:
return -1;
}
-static int write_object(git_buf *buf, git_packbuilder *pb, git_pobject *po)
+static int write_object(
+ git_packbuilder *pb,
+ git_pobject *po,
+ int (*write_cb)(void *buf, size_t size, void *cb_data),
+ void *cb_data)
{
git_odb_object *obj = NULL;
- git_buf zbuf = GIT_BUF_INIT;
git_otype type;
- unsigned char hdr[10];
- size_t hdr_len;
- unsigned long size;
+ unsigned char hdr[10], *zbuf = NULL;
+ void *delta_data = NULL;
void *data;
+ size_t hdr_len, zbuf_len = COMPRESS_BUFLEN, data_len;
+ int error;
if (po->delta) {
if (po->delta_data)
- data = po->delta_data;
- else if (get_delta(&data, pb->odb, po) < 0)
- goto on_error;
- size = po->delta_size;
+ delta_data = po->delta_data;
+ else if ((error = get_delta(&delta_data, pb->odb, po)) < 0)
+ goto done;
+
+ data = delta_data;
+ data_len = po->delta_size;
type = GIT_OBJ_REF_DELTA;
} else {
- if (git_odb_read(&obj, pb->odb, &po->id))
- goto on_error;
+ if ((error = git_odb_read(&obj, pb->odb, &po->id)) < 0)
+ goto done;
data = (void *)git_odb_object_data(obj);
- size = (unsigned long)git_odb_object_size(obj);
+ data_len = git_odb_object_size(obj);
type = git_odb_object_type(obj);
}
/* Write header */
- hdr_len = git_packfile__object_header(hdr, size, type);
-
- if (git_buf_put(buf, (char *)hdr, hdr_len) < 0)
- goto on_error;
+ hdr_len = git_packfile__object_header(hdr, data_len, type);
- if (git_hash_update(&pb->ctx, hdr, hdr_len) < 0)
- goto on_error;
+ if ((error = write_cb(hdr, hdr_len, cb_data)) < 0 ||
+ (error = git_hash_update(&pb->ctx, hdr, hdr_len)) < 0)
+ goto done;
if (type == GIT_OBJ_REF_DELTA) {
- if (git_buf_put(buf, (char *)po->delta->id.id, GIT_OID_RAWSZ) < 0 ||
- git_hash_update(&pb->ctx, po->delta->id.id, GIT_OID_RAWSZ) < 0)
- goto on_error;
+ if ((error = write_cb(po->delta->id.id, GIT_OID_RAWSZ, cb_data)) < 0 ||
+ (error = git_hash_update(&pb->ctx, po->delta->id.id, GIT_OID_RAWSZ)) < 0)
+ goto done;
}
/* Write data */
- if (po->z_delta_size)
- size = po->z_delta_size;
- else if (git__compress(&zbuf, data, size) < 0)
- goto on_error;
- else {
+ if (po->z_delta_size) {
+ data_len = po->z_delta_size;
+
+ if ((error = write_cb(data, data_len, cb_data)) < 0 ||
+ (error = git_hash_update(&pb->ctx, data, data_len)) < 0)
+ goto done;
+ } else {
+ zbuf = git__malloc(zbuf_len);
+ GITERR_CHECK_ALLOC(zbuf);
+
+ git_zstream_reset(&pb->zstream);
+ git_zstream_set_input(&pb->zstream, data, data_len);
+
+ while (!git_zstream_done(&pb->zstream)) {
+ if ((error = git_zstream_get_output(zbuf, &zbuf_len, &pb->zstream)) < 0 ||
+ (error = write_cb(zbuf, zbuf_len, cb_data)) < 0 ||
+ (error = git_hash_update(&pb->ctx, zbuf, zbuf_len)) < 0)
+ goto done;
+
+ zbuf_len = COMPRESS_BUFLEN; /* reuse buffer */
+ }
+
if (po->delta)
- git__free(data);
- data = zbuf.ptr;
- size = (unsigned long)zbuf.size;
+ git__free(delta_data);
}
- if (git_buf_put(buf, data, size) < 0 ||
- git_hash_update(&pb->ctx, data, size) < 0)
- goto on_error;
-
if (po->delta_data) {
git__free(po->delta_data);
po->delta_data = NULL;
}
- git_odb_object_free(obj);
- git_buf_free(&zbuf);
-
pb->nr_written++;
- return 0;
-on_error:
+done:
+ git__free(zbuf);
git_odb_object_free(obj);
- git_buf_free(&zbuf);
- return -1;
+ return error;
}
enum write_one_status {
@@ -356,9 +371,15 @@ enum write_one_status {
WRITE_ONE_RECURSIVE = 2 /* already scheduled to be written */
};
-static int write_one(git_buf *buf, git_packbuilder *pb, git_pobject *po,
- enum write_one_status *status)
+static int write_one(
+ enum write_one_status *status,
+ git_packbuilder *pb,
+ git_pobject *po,
+ int (*write_cb)(void *buf, size_t size, void *cb_data),
+ void *cb_data)
{
+ int error;
+
if (po->recursing) {
*status = WRITE_ONE_RECURSIVE;
return 0;
@@ -369,21 +390,19 @@ static int write_one(git_buf *buf, git_packbuilder *pb, git_pobject *po,
if (po->delta) {
po->recursing = 1;
- if (write_one(buf, pb, po->delta, status) < 0)
- return -1;
- switch (*status) {
- case WRITE_ONE_RECURSIVE:
- /* we cannot depend on this one */
+
+ if ((error = write_one(status, pb, po->delta, write_cb, cb_data)) < 0)
+ return error;
+
+ /* we cannot depend on this one */
+ if (*status == WRITE_ONE_RECURSIVE)
po->delta = NULL;
- break;
- default:
- break;
- }
}
po->written = 1;
po->recursing = 0;
- return write_object(buf, pb, po);
+
+ return write_object(pb, po, write_cb, cb_data);
}
GIT_INLINE(void) add_to_write_order(git_pobject **wo, unsigned int *endp,
@@ -563,12 +582,11 @@ static git_pobject **compute_write_order(git_packbuilder *pb)
}
static int write_pack(git_packbuilder *pb,
- int (*cb)(void *buf, size_t size, void *data),
- void *data)
+ int (*write_cb)(void *buf, size_t size, void *cb_data),
+ void *cb_data)
{
git_pobject **write_order;
git_pobject *po;
- git_buf buf = GIT_BUF_INIT;
enum write_one_status status;
struct git_pack_header ph;
git_oid entry_oid;
@@ -586,10 +604,8 @@ static int write_pack(git_packbuilder *pb,
ph.hdr_version = htonl(PACK_VERSION);
ph.hdr_entries = htonl(pb->nr_objects);
- if ((error = cb(&ph, sizeof(ph), data)) < 0)
- goto done;
-
- if ((error = git_hash_update(&pb->ctx, &ph, sizeof(ph))) < 0)
+ if ((error = write_cb(&ph, sizeof(ph), cb_data)) < 0 ||
+ (error = git_hash_update(&pb->ctx, &ph, sizeof(ph))) < 0)
goto done;
pb->nr_remaining = pb->nr_objects;
@@ -597,21 +613,18 @@ static int write_pack(git_packbuilder *pb,
pb->nr_written = 0;
for ( ; i < pb->nr_objects; ++i) {
po = write_order[i];
- if ((error = write_one(&buf, pb, po, &status)) < 0)
- goto done;
- if ((error = cb(buf.ptr, buf.size, data)) < 0)
+
+ if ((error = write_one(&status, pb, po, write_cb, cb_data)) < 0)
goto done;
- git_buf_clear(&buf);
}
pb->nr_remaining -= pb->nr_written;
} while (pb->nr_remaining && i < pb->nr_objects);
-
if ((error = git_hash_final(&entry_oid, &pb->ctx)) < 0)
goto done;
- error = cb(entry_oid.id, GIT_OID_RAWSZ, data);
+ error = write_cb(entry_oid.id, GIT_OID_RAWSZ, cb_data);
done:
/* if callback cancelled writing, we must still free delta_data */
@@ -624,7 +637,6 @@ done:
}
git__free(write_order);
- git_buf_free(&buf);
return error;
}
@@ -931,7 +943,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
* between writes at that moment.
*/
if (po->delta_data) {
- if (git__compress(&zbuf, po->delta_data, po->delta_size) < 0)
+ if (git_zstream_deflatebuf(&zbuf, po->delta_data, po->delta_size) < 0)
goto on_error;
git__free(po->delta_data);
@@ -1396,6 +1408,7 @@ void git_packbuilder_free(git_packbuilder *pb)
git__free(pb->object_list);
git_hash_ctx_cleanup(&pb->ctx);
+ git_zstream_free(&pb->zstream);
git__free(pb);
}
diff --git a/src/pack-objects.h b/src/pack-objects.h
index 0c94a5a7a..4647df75a 100644
--- a/src/pack-objects.h
+++ b/src/pack-objects.h
@@ -14,6 +14,7 @@
#include "hash.h"
#include "oidmap.h"
#include "netops.h"
+#include "zstream.h"
#include "git2/oid.h"
#include "git2/pack.h"
@@ -54,6 +55,7 @@ struct git_packbuilder {
git_odb *odb; /* associated object database */
git_hash_ctx ctx;
+ git_zstream zstream;
uint32_t nr_objects,
nr_alloc,
diff --git a/src/pack.c b/src/pack.c
index 23fcf3530..de038a45c 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -997,11 +997,6 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
return -1;
}
- /* see if we can parse the sha1 oid in the packfile name */
- if (path_len < 40 ||
- git_oid_fromstr(&p->sha1, path + path_len - GIT_OID_HEXSZ) < 0)
- memset(&p->sha1, 0x0, GIT_OID_RAWSZ);
-
*pack_out = p;
return 0;
diff --git a/src/pack.h b/src/pack.h
index 28146ab30..58f81e2f0 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -88,7 +88,6 @@ struct git_pack_file {
int index_version;
git_time_t mtime;
unsigned pack_local:1, pack_keep:1, has_cache:1;
- git_oid sha1;
git_oidmap *idx_cache;
git_oid **oids;
diff --git a/src/pathspec.c b/src/pathspec.c
index bad8dacdb..bee320576 100644
--- a/src/pathspec.c
+++ b/src/pathspec.c
@@ -89,8 +89,10 @@ int git_pathspec__vinit(
if (ret == GIT_ENOTFOUND) {
git__free(match);
continue;
- } else if (ret < 0)
+ } else if (ret < 0) {
+ git__free(match);
return ret;
+ }
if (git_vector_insert(vspec, match) < 0)
return -1;
@@ -443,7 +445,7 @@ static int pathspec_match_from_iterator(
/* check if path is ignored and untracked */
if (index != NULL &&
git_iterator_current_is_ignored(iter) &&
- git_index__find(NULL, index, entry->path, GIT_INDEX_STAGE_ANY) < 0)
+ git_index__find(NULL, index, entry->path, strlen(entry->path), GIT_INDEX_STAGE_ANY) < 0)
continue;
/* mark the matched pattern as used */
diff --git a/src/posix.h b/src/posix.h
index f529914fe..6d3a84eba 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -89,14 +89,7 @@ extern struct tm * p_gmtime_r (const time_t *timer, struct tm *result);
# include "unix/posix.h"
#endif
-#if defined(__MINGW32__) || defined(__sun)
-GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) {
- const char *end = memchr(s, 0, maxlen);
- return end ? (size_t)(end - s) : maxlen;
-}
-#else
-# define p_strnlen strnlen
-#endif
+#include "strnlen.h"
#ifdef NO_READDIR_R
# include <dirent.h>
diff --git a/src/push.c b/src/push.c
index dd77864a5..d39a27182 100644
--- a/src/push.c
+++ b/src/push.c
@@ -214,7 +214,7 @@ int git_push_update_tips(git_push *push)
if (!fetch_spec)
continue;
- if ((error = git_refspec_transform_r(&remote_ref_name, fetch_spec, status->ref)) < 0)
+ if ((error = git_refspec_transform(&remote_ref_name, fetch_spec, status->ref)) < 0)
goto on_error;
/* Find matching push ref spec */
@@ -241,7 +241,7 @@ int git_push_update_tips(git_push *push)
giterr_clear();
else
goto on_error;
- } else if ((error = git_reference_create(NULL, push->remote->repo, git_buf_cstr(&remote_ref_name), &push_spec->loid, 1)) < 0)
+ } else if ((error = git_reference_create(NULL, push->remote->repo, git_buf_cstr(&remote_ref_name), &push_spec->loid, 1, NULL, NULL)) < 0)
goto on_error;
}
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 53c42458f..89c77c14c 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -1434,12 +1434,14 @@ success:
static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_signature *who, const char *message)
{
int error;
- git_oid old_id, new_id;
+ git_oid old_id, new_id = {{0}};
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
git_repository *repo = backend->repo;
- /* Creation of symbolic references doesn't get a reflog entry */
- if (ref->type == GIT_REF_SYMBOLIC)
+ /* Creation of a symbolic reference doesn't get a reflog entry, except for
+ * HEAD. git_repository_set_head and friends go through here. */
+ if (ref->type == GIT_REF_SYMBOLIC &&
+ 0 != strcmp(ref->name, GIT_HEAD_FILE))
return 0;
error = git_reference_name_to_id(&old_id, repo, ref->name);
@@ -1450,7 +1452,14 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
if (error < 0)
return error;
- git_oid_cpy(&new_id, git_reference_target(ref));
+ if (git_reference_symbolic_target(ref) != NULL) {
+ error = git_reference_name_to_id(&new_id, repo, git_reference_symbolic_target(ref));
+ if (error != 0 && error != GIT_ENOTFOUND)
+ goto cleanup;
+ giterr_clear();
+ }
+ else if (git_reference_target(ref) != NULL)
+ git_oid_cpy(&new_id, git_reference_target(ref));
if ((error = serialize_reflog_entry(&buf, &old_id, &new_id, who, message)) < 0)
goto cleanup;
diff --git a/src/reflog.c b/src/reflog.c
index 9b2b201bf..8e41621ea 100644
--- a/src/reflog.c
+++ b/src/reflog.c
@@ -82,7 +82,7 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_sign
entry = git__calloc(1, sizeof(git_reflog_entry));
GITERR_CHECK_ALLOC(entry);
- if ((entry->committer = git_signature_dup(committer)) == NULL)
+ if ((git_signature_dup(&entry->committer, committer)) < 0)
goto cleanup;
if (msg != NULL) {
diff --git a/src/refs.c b/src/refs.c
index 83343f41b..ca5f24ea2 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -393,32 +393,20 @@ static int reference__create(
return 0;
}
-int git_reference_create(
- git_reference **ref_out,
- git_repository *repo,
- const char *name,
- const git_oid *oid,
- int force)
+static int log_signature(git_signature **out, git_repository *repo)
{
- git_signature *who;
int error;
+ git_signature *who;
- assert(oid);
-
- /* Should we return an error if there is no default? */
- if (((error = git_signature_default(&who, repo)) < 0) &&
- ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) {
+ if(((error = git_signature_default(&who, repo)) < 0) &&
+ ((error = git_signature_now(&who, "unknown", "unknown")) < 0))
return error;
- }
-
- error = reference__create(ref_out, repo, name, oid, NULL, force, who, NULL);
-
- git_signature_free(who);
- return error;
+ *out = who;
+ return 0;
}
-int git_reference_create_with_log(
+int git_reference_create(
git_reference **ref_out,
git_repository *repo,
const char *name,
@@ -427,10 +415,23 @@ int git_reference_create_with_log(
const git_signature *signature,
const char *log_message)
{
- assert(oid && signature && log_message);
+ int error;
+ git_signature *who = NULL;
+
+ assert(oid);
- return reference__create(
+ if (!signature) {
+ if ((error = log_signature(&who, repo)) < 0)
+ return error;
+ else
+ signature = who;
+ }
+
+ error = reference__create(
ref_out, repo, name, oid, NULL, force, signature, log_message);
+
+ git_signature_free(who);
+ return error;
}
int git_reference_symbolic_create(
@@ -438,10 +439,27 @@ int git_reference_symbolic_create(
git_repository *repo,
const char *name,
const char *target,
- int force)
+ int force,
+ const git_signature *signature,
+ const char *log_message)
{
+ int error;
+ git_signature *who = NULL;
+
assert(target);
- return reference__create(ref_out, repo, name, NULL, target, force, NULL, NULL);
+
+ if (!signature) {
+ if ((error = log_signature(&who, repo)) < 0)
+ return error;
+ else
+ signature = who;
+ }
+
+ error = reference__create(
+ ref_out, repo, name, NULL, target, force, signature, log_message);
+
+ git_signature_free(who);
+ return error;
}
static int ensure_is_an_updatable_direct_reference(git_reference *ref)
@@ -456,21 +474,6 @@ static int ensure_is_an_updatable_direct_reference(git_reference *ref)
int git_reference_set_target(
git_reference **out,
git_reference *ref,
- const git_oid *id)
-{
- int error;
-
- assert(out && ref && id);
-
- if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0)
- return error;
-
- return git_reference_create(out, ref->db->repo, ref->name, id, 1);
-}
-
-int git_reference_set_target_with_log(
- git_reference **out,
- git_reference *ref,
const git_oid *id,
const git_signature *signature,
const char *log_message)
@@ -478,12 +481,11 @@ int git_reference_set_target_with_log(
int error;
assert(out && ref && id);
- assert(signature && log_message);
if ((error = ensure_is_an_updatable_direct_reference(ref)) < 0)
return error;
- return git_reference_create_with_log(
+ return git_reference_create(
out, ref->db->repo, ref->name, id, 1, signature, log_message);
}
@@ -499,7 +501,9 @@ static int ensure_is_an_updatable_symbolic_reference(git_reference *ref)
int git_reference_symbolic_set_target(
git_reference **out,
git_reference *ref,
- const char *target)
+ const char *target,
+ const git_signature *signature,
+ const char *log_message)
{
int error;
@@ -508,7 +512,8 @@ int git_reference_symbolic_set_target(
if ((error = ensure_is_an_updatable_symbolic_reference(ref)) < 0)
return error;
- return git_reference_symbolic_create(out, ref->db->repo, ref->name, target, 1);
+ return git_reference_symbolic_create(
+ out, ref->db->repo, ref->name, target, 1, signature, log_message);
}
static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force,
@@ -540,7 +545,7 @@ static int reference__rename(git_reference **out, git_reference *ref, const char
/* Update HEAD it was pointing to the reference being renamed */
if (should_head_be_updated &&
- (error = git_repository_set_head(ref->db->repo, new_name)) < 0) {
+ (error = git_repository_set_head(ref->db->repo, new_name, signature, message)) < 0) {
giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference");
return error;
}
@@ -553,35 +558,28 @@ int git_reference_rename(
git_reference **out,
git_reference *ref,
const char *new_name,
- int force)
+ int force,
+ const git_signature *signature,
+ const char *log_message)
{
- git_signature *who;
+ git_signature *who = (git_signature*)signature;
int error;
/* Should we return an error if there is no default? */
- if (((error = git_signature_default(&who, ref->db->repo)) < 0) &&
+ if (!who &&
+ ((error = git_signature_default(&who, ref->db->repo)) < 0) &&
((error = git_signature_now(&who, "unknown", "unknown")) < 0)) {
return error;
}
- error = reference__rename(out, ref, new_name, force, who, NULL);
+ error = reference__rename(out, ref, new_name, force, who, log_message);
- git_signature_free(who);
+ if (!signature)
+ git_signature_free(who);
return error;
}
-int git_reference_rename_with_log(
- git_reference **out,
- git_reference *ref,
- const char *new_name,
- int force,
- const git_signature *who,
- const char * message)
-{
- return reference__rename(out, ref, new_name, force, who, message);
-}
-
int git_reference_resolve(git_reference **ref_out, const git_reference *ref)
{
switch (git_reference_type(ref)) {
@@ -709,6 +707,9 @@ int git_reference_next_name(const char **out, git_reference_iterator *iter)
void git_reference_iterator_free(git_reference_iterator *iter)
{
+ if (iter == NULL)
+ return;
+
git_refdb_iterator_free(iter);
}
@@ -1002,7 +1003,9 @@ static int reference__update_terminal(
git_repository *repo,
const char *ref_name,
const git_oid *oid,
- int nesting)
+ int nesting,
+ const git_signature *signature,
+ const char *log_message)
{
git_reference *ref;
int error = 0;
@@ -1017,7 +1020,7 @@ static int reference__update_terminal(
/* If we haven't found the reference at all, create a new reference. */
if (error == GIT_ENOTFOUND) {
giterr_clear();
- return git_reference_create(NULL, repo, ref_name, oid, 0);
+ return git_reference_create(NULL, repo, ref_name, oid, 0, signature, log_message);
}
if (error < 0)
@@ -1026,11 +1029,11 @@ static int reference__update_terminal(
/* If the ref is a symbolic reference, follow its target. */
if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
error = reference__update_terminal(repo, git_reference_symbolic_target(ref), oid,
- nesting+1);
+ nesting+1, signature, log_message);
git_reference_free(ref);
} else {
git_reference_free(ref);
- error = git_reference_create(NULL, repo, ref_name, oid, 1);
+ error = git_reference_create(NULL, repo, ref_name, oid, 1, signature, log_message);
}
return error;
@@ -1044,9 +1047,11 @@ static int reference__update_terminal(
int git_reference__update_terminal(
git_repository *repo,
const char *ref_name,
- const git_oid *oid)
+ const git_oid *oid,
+ const git_signature *signature,
+ const char *log_message)
{
- return reference__update_terminal(repo, ref_name, oid, 0);
+ return reference__update_terminal(repo, ref_name, oid, 0, signature, log_message);
}
int git_reference_has_log(git_repository *repo, const char *refname)
@@ -1108,6 +1113,17 @@ int git_reference_is_tag(git_reference *ref)
return git_reference__is_tag(ref->name);
}
+int git_reference__is_note(const char *ref_name)
+{
+ return git__prefixcmp(ref_name, GIT_REFS_NOTES_DIR) == 0;
+}
+
+int git_reference_is_note(git_reference *ref)
+{
+ assert(ref);
+ return git_reference__is_note(ref->name);
+}
+
static int peel_error(int error, git_reference *ref, const char* msg)
{
giterr_set(
diff --git a/src/refs.h b/src/refs.h
index 4d5b6dacb..d57d67026 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -68,7 +68,7 @@ git_reference *git_reference__set_name(git_reference *ref, const char *name);
int git_reference__normalize_name_lax(char *buffer_out, size_t out_size, const char *name);
int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int flags);
-int git_reference__update_terminal(git_repository *repo, const char *ref_name, const git_oid *oid);
+int git_reference__update_terminal(git_repository *repo, const char *ref_name, const git_oid *oid, const git_signature *signature, const char *log_message);
int git_reference__is_valid_name(const char *refname, unsigned int flags);
int git_reference__is_branch(const char *ref_name);
int git_reference__is_remote(const char *ref_name);
diff --git a/src/refspec.c b/src/refspec.c
index a97340071..fa60aa7aa 100644
--- a/src/refspec.c
+++ b/src/refspec.c
@@ -178,54 +178,6 @@ int git_refspec_dst_matches(const git_refspec *refspec, const char *refname)
return (p_fnmatch(refspec->dst, refname, 0) == 0);
}
-static int refspec_transform_internal(char *out, size_t outlen, const char *from, const char *to, const char *name)
-{
- size_t baselen, namelen;
-
- baselen = strlen(to);
- if (outlen <= baselen) {
- giterr_set(GITERR_INVALID, "Reference name too long");
- return GIT_EBUFS;
- }
-
- /*
- * No '*' at the end means that it's mapped to one specific local
- * branch, so no actual transformation is needed.
- */
- if (to[baselen - 1] != '*') {
- memcpy(out, to, baselen + 1); /* include '\0' */
- return 0;
- }
-
- /* There's a '*' at the end, so remove its length */
- baselen--;
-
- /* skip the prefix, -1 is for the '*' */
- name += strlen(from) - 1;
-
- namelen = strlen(name);
-
- if (outlen <= baselen + namelen) {
- giterr_set(GITERR_INVALID, "Reference name too long");
- return GIT_EBUFS;
- }
-
- memcpy(out, to, baselen);
- memcpy(out + baselen, name, namelen + 1);
-
- return 0;
-}
-
-int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name)
-{
- return refspec_transform_internal(out, outlen, spec->src, spec->dst, name);
-}
-
-int git_refspec_rtransform(char *out, size_t outlen, const git_refspec *spec, const char *name)
-{
- return refspec_transform_internal(out, outlen, spec->dst, spec->src, name);
-}
-
static int refspec_transform(
git_buf *out, const char *from, const char *to, const char *name)
{
@@ -233,6 +185,8 @@ static int refspec_transform(
size_t from_len = from ? strlen(from) : 0;
size_t name_len = name ? strlen(name) : 0;
+ git_buf_sanitize(out);
+
if (git_buf_set(out, to, to_len) < 0)
return -1;
@@ -253,12 +207,12 @@ static int refspec_transform(
return git_buf_put(out, name + from_len, name_len - from_len);
}
-int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *name)
+int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name)
{
return refspec_transform(out, spec->src, spec->dst, name);
}
-int git_refspec_transform_l(git_buf *out, const git_refspec *spec, const char *name)
+int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name)
{
return refspec_transform(out, spec->dst, spec->src, name);
}
diff --git a/src/refspec.h b/src/refspec.h
index 51b7bfee9..375465f61 100644
--- a/src/refspec.h
+++ b/src/refspec.h
@@ -31,28 +31,6 @@ int git_refspec__parse(
void git_refspec__free(git_refspec *refspec);
-/**
- * Transform a reference to its target following the refspec's rules,
- * and writes the results into a git_buf.
- *
- * @param out where to store the target name
- * @param spec the refspec
- * @param name the name of the reference to transform
- * @return 0 or error if buffer allocation fails
- */
-int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *name);
-
-/**
- * Transform a reference from its target following the refspec's rules,
- * and writes the results into a git_buf.
- *
- * @param out where to store the source name
- * @param spec the refspec
- * @param name the name of the reference to transform
- * @return 0 or error if buffer allocation fails
- */
-int git_refspec_transform_l(git_buf *out, const git_refspec *spec, const char *name);
-
int git_refspec__serialize(git_buf *out, const git_refspec *refspec);
/**
diff --git a/src/remote.c b/src/remote.c
index 294a8709d..f33f5ef3c 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -248,6 +248,62 @@ int git_remote_create_inmemory(git_remote **out, git_repository *repo, const cha
return 0;
}
+int git_remote_dup(git_remote **dest, git_remote *source)
+{
+ int error = 0;
+ git_strarray refspecs = { 0 };
+ git_remote *remote = git__calloc(1, sizeof(git_remote));
+ GITERR_CHECK_ALLOC(remote);
+
+ if (source->name != NULL) {
+ remote->name = git__strdup(source->name);
+ GITERR_CHECK_ALLOC(remote->name);
+ }
+
+ if (source->url != NULL) {
+ remote->url = git__strdup(source->url);
+ GITERR_CHECK_ALLOC(remote->url);
+ }
+
+ if (source->pushurl != NULL) {
+ remote->pushurl = git__strdup(source->pushurl);
+ GITERR_CHECK_ALLOC(remote->pushurl);
+ }
+
+ remote->repo = source->repo;
+ remote->download_tags = source->download_tags;
+ remote->check_cert = source->check_cert;
+ remote->update_fetchhead = source->update_fetchhead;
+
+ if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
+ git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
+ git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
+ error = -1;
+ goto cleanup;
+ }
+
+ if ((error = git_remote_get_fetch_refspecs(&refspecs, source)) < 0 ||
+ (error = git_remote_set_fetch_refspecs(remote, &refspecs)) < 0)
+ goto cleanup;
+
+ git_strarray_free(&refspecs);
+
+ if ((error = git_remote_get_push_refspecs(&refspecs, source)) < 0 ||
+ (error = git_remote_set_push_refspecs(remote, &refspecs)) < 0)
+ goto cleanup;
+
+ *dest = remote;
+
+cleanup:
+
+ git_strarray_free(&refspecs);
+
+ if (error < 0)
+ git__free(remote);
+
+ return error;
+}
+
struct refspec_cb_data {
git_remote *remote;
int fetch;
@@ -840,7 +896,7 @@ static int remote_head_for_ref(git_remote_head **out, git_refspec *spec, git_vec
if ((error = git_reference_resolve(&resolved_ref, ref)) < 0 ||
(!git_reference_is_branch(resolved_ref)) ||
(error = git_branch_upstream(&tracking_ref, resolved_ref)) < 0 ||
- (error = git_refspec_transform_l(&remote_name, spec, git_reference_name(tracking_ref))) < 0) {
+ (error = git_refspec_rtransform(&remote_name, spec, git_reference_name(tracking_ref))) < 0) {
/* Not an error if HEAD is unborn or no tracking branch */
if (error == GIT_ENOTFOUND)
error = 0;
@@ -955,7 +1011,7 @@ static int update_tips_for_spec(git_remote *remote, git_refspec *spec, git_vecto
continue;
if (git_refspec_src_matches(spec, head->name) && spec->dst) {
- if (git_refspec_transform_r(&refname, spec, head->name) < 0)
+ if (git_refspec_transform(&refname, spec, head->name) < 0)
goto on_error;
} else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
@@ -989,7 +1045,7 @@ static int update_tips_for_spec(git_remote *remote, git_refspec *spec, git_vecto
continue;
/* In autotag mode, don't overwrite any locally-existing tags */
- error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag);
+ error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag, NULL, NULL);
if (error < 0 && error != GIT_EEXISTS)
goto on_error;
@@ -1051,7 +1107,7 @@ out:
return error;
}
-int git_remote_connected(git_remote *remote)
+int git_remote_connected(const git_remote *remote)
{
assert(remote);
@@ -1195,7 +1251,7 @@ const git_transfer_progress* git_remote_stats(git_remote *remote)
return &remote->stats;
}
-git_remote_autotag_option_t git_remote_autotag(git_remote *remote)
+git_remote_autotag_option_t git_remote_autotag(const git_remote *remote)
{
return remote->download_tags;
}
@@ -1276,20 +1332,28 @@ static int rename_one_remote_reference(
{
int error;
git_buf new_name = GIT_BUF_INIT;
+ git_buf log_message = GIT_BUF_INIT;
- error = git_buf_printf(
- &new_name,
- GIT_REFS_REMOTES_DIR "%s%s",
- new_remote_name,
- reference->name + strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name));
+ if ((error = git_buf_printf(
+ &new_name,
+ GIT_REFS_REMOTES_DIR "%s%s",
+ new_remote_name,
+ reference->name + strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name))) < 0)
+ goto cleanup;
- if (!error) {
- error = git_reference_rename(
- NULL, reference, git_buf_cstr(&new_name), 0);
- git_reference_free(reference);
- }
+ if ((error = git_buf_printf(&log_message,
+ "renamed remote %s to %s",
+ old_remote_name, new_remote_name)) < 0)
+ goto cleanup;
+ error = git_reference_rename(
+ NULL, reference, git_buf_cstr(&new_name), 0,
+ NULL, git_buf_cstr(&log_message));
+ git_reference_free(reference);
+
+cleanup:
git_buf_free(&new_name);
+ git_buf_free(&log_message);
return error;
}
@@ -1588,7 +1652,7 @@ int git_remote_set_push_refspecs(git_remote *remote, git_strarray *array)
return set_refspecs(remote, array, true);
}
-static int copy_refspecs(git_strarray *array, git_remote *remote, unsigned int push)
+static int copy_refspecs(git_strarray *array, const git_remote *remote, unsigned int push)
{
size_t i;
git_vector refspecs;
@@ -1622,22 +1686,22 @@ on_error:
return -1;
}
-int git_remote_get_fetch_refspecs(git_strarray *array, git_remote *remote)
+int git_remote_get_fetch_refspecs(git_strarray *array, const git_remote *remote)
{
return copy_refspecs(array, remote, false);
}
-int git_remote_get_push_refspecs(git_strarray *array, git_remote *remote)
+int git_remote_get_push_refspecs(git_strarray *array, const git_remote *remote)
{
return copy_refspecs(array, remote, true);
}
-size_t git_remote_refspec_count(git_remote *remote)
+size_t git_remote_refspec_count(const git_remote *remote)
{
return remote->refspecs.length;
}
-const git_refspec *git_remote_get_refspec(git_remote *remote, size_t n)
+const git_refspec *git_remote_get_refspec(const git_remote *remote, size_t n)
{
return git_vector_get(&remote->refspecs, n);
}
diff --git a/src/repository.c b/src/repository.c
index 94f6603aa..2c1b60266 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -289,16 +289,20 @@ static int read_gitfile(git_buf *path_out, const char *file_path)
return -1;
git_buf_rtrim(&file);
+ /* apparently on Windows, some people use backslashes in paths */
+ git_path_mkposix(file.ptr);
if (git_buf_len(&file) <= prefix_len ||
memcmp(git_buf_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0)
{
- giterr_set(GITERR_REPOSITORY, "The `.git` file at '%s' is malformed", file_path);
+ giterr_set(GITERR_REPOSITORY,
+ "The `.git` file at '%s' is malformed", file_path);
error = -1;
}
else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) {
const char *gitlink = git_buf_cstr(&file) + prefix_len;
while (*gitlink && git__isspace(*gitlink)) gitlink++;
+
error = git_path_prettify_dir(
path_out, gitlink, git_buf_cstr(path_out));
}
@@ -491,34 +495,18 @@ int git_repository_wrap_odb(git_repository **repo_out, git_odb *odb)
}
int git_repository_discover(
- char *repository_path,
- size_t size,
+ git_buf *out,
const char *start_path,
int across_fs,
const char *ceiling_dirs)
{
- git_buf path = GIT_BUF_INIT;
uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
- int error;
-
- assert(start_path && repository_path && size > 0);
- *repository_path = '\0';
+ assert(start_path);
- if ((error = find_repo(&path, NULL, start_path, flags, ceiling_dirs)) < 0)
- return error != GIT_ENOTFOUND ? -1 : error;
+ git_buf_sanitize(out);
- if (size < (size_t)(path.size + 1)) {
- giterr_set(GITERR_REPOSITORY,
- "The given buffer is too small to store the discovered path");
- git_buf_free(&path);
- return -1;
- }
-
- /* success: we discovered a repository */
- git_buf_copy_cstr(repository_path, size, &path);
- git_buf_free(&path);
- return 0;
+ return find_repo(out, NULL, start_path, flags, ceiling_dirs);
}
static int load_config(
@@ -594,9 +582,9 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
git_buf system_buf = GIT_BUF_INIT;
git_config *config;
- git_config_find_global_r(&global_buf);
- git_config_find_xdg_r(&xdg_buf);
- git_config_find_system_r(&system_buf);
+ git_config_find_global(&global_buf);
+ git_config_find_xdg(&xdg_buf);
+ git_config_find_system(&system_buf);
/* If there is no global file, open a backend for it anyway */
if (git_buf_len(&global_buf) == 0)
@@ -1728,14 +1716,13 @@ cleanup:
return error;
}
-int git_repository_message(char *buffer, size_t len, git_repository *repo)
+int git_repository_message(git_buf *out, git_repository *repo)
{
- git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
+ git_buf path = GIT_BUF_INIT;
struct stat st;
int error;
- if (buffer != NULL)
- *buffer = '\0';
+ git_buf_sanitize(out);
if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
return -1;
@@ -1745,16 +1732,10 @@ int git_repository_message(char *buffer, size_t len, git_repository *repo)
error = GIT_ENOTFOUND;
giterr_set(GITERR_OS, "Could not access message file");
}
- else if (buffer != NULL) {
- error = git_futils_readbuffer(&buf, git_buf_cstr(&path));
- git_buf_copy_cstr(buffer, len, &buf);
- }
- git_buf_free(&path);
- git_buf_free(&buf);
+ error = git_futils_readbuffer(out, git_buf_cstr(&path));
- if (!error)
- error = (int)st.st_size + 1; /* add 1 for NUL byte */
+ git_buf_free(&path);
return error;
}
@@ -1849,7 +1830,9 @@ static bool looks_like_a_branch(const char *refname)
int git_repository_set_head(
git_repository* repo,
- const char* refname)
+ const char* refname,
+ const git_signature *signature,
+ const char *log_message)
{
git_reference *ref,
*new_head = NULL;
@@ -1862,12 +1845,17 @@ int git_repository_set_head(
return error;
if (!error) {
- if (git_reference_is_branch(ref))
- error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, git_reference_name(ref), 1);
- else
- error = git_repository_set_head_detached(repo, git_reference_target(ref));
- } else if (looks_like_a_branch(refname))
- error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname, 1);
+ if (git_reference_is_branch(ref)) {
+ error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,
+ git_reference_name(ref), true, signature, log_message);
+ } else {
+ error = git_repository_set_head_detached(repo, git_reference_target(ref),
+ signature, log_message);
+ }
+ } else if (looks_like_a_branch(refname)) {
+ error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname,
+ true, signature, log_message);
+ }
git_reference_free(ref);
git_reference_free(new_head);
@@ -1876,7 +1864,9 @@ int git_repository_set_head(
int git_repository_set_head_detached(
git_repository* repo,
- const git_oid* commitish)
+ const git_oid* commitish,
+ const git_signature *signature,
+ const char *log_message)
{
int error;
git_object *object,
@@ -1891,7 +1881,7 @@ int git_repository_set_head_detached(
if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
goto cleanup;
- error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), 1);
+ error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, signature, log_message);
cleanup:
git_object_free(object);
@@ -1916,7 +1906,7 @@ int git_repository_detach_head(
if ((error = git_object_lookup(&object, repo, git_reference_target(old_head), GIT_OBJ_COMMIT)) < 0)
goto cleanup;
- error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_reference_target(old_head), 1);
+ error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_reference_target(old_head), 1, NULL, NULL);
cleanup:
git_object_free(object);
diff --git a/src/reset.c b/src/reset.c
index 261a36576..15f7fe13a 100644
--- a/src/reset.c
+++ b/src/reset.c
@@ -72,7 +72,7 @@ int git_reset_default(
goto cleanup;
} else {
entry.mode = delta->new_file.mode;
- git_oid_cpy(&entry.oid, &delta->new_file.oid);
+ git_oid_cpy(&entry.id, &delta->new_file.id);
entry.path = (char *)delta->new_file.path;
if ((error = git_index_add(index, &entry)) < 0)
@@ -131,7 +131,7 @@ int git_reset(
/* move HEAD to the new target */
if ((error = git_reference__update_terminal(repo, GIT_HEAD_FILE,
- git_object_id(commit))) < 0)
+ git_object_id(commit), NULL, NULL)) < 0)
goto cleanup;
if (reset_type == GIT_RESET_HARD) {
diff --git a/src/revparse.c b/src/revparse.c
index c120b466f..60872e187 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -168,6 +168,8 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out,
for (i = 0; i < numentries; i++) {
entry = git_reflog_entry_byindex(reflog, i);
msg = git_reflog_entry_message(entry);
+ if (!msg)
+ continue;
if (regexec(&preg, msg, 2, regexmatches, 0))
continue;
@@ -488,8 +490,7 @@ static int handle_grep_syntax(git_object **out, git_repository *repo, const git_
git_revwalk_sorting(walk, GIT_SORT_TIME);
if (spec_oid == NULL) {
- // TODO: @carlosmn: The glob should be refs/* but this makes git_revwalk_next() fails
- if ((error = git_revwalk_push_glob(walk, GIT_REFS_HEADS_DIR "*")) < 0)
+ if ((error = git_revwalk_push_glob(walk, "refs/*")) < 0)
goto cleanup;
} else if ((error = git_revwalk_push(walk, spec_oid)) < 0)
goto cleanup;
diff --git a/src/revwalk.c b/src/revwalk.c
index c0a053211..628057fcd 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -110,25 +110,34 @@ static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commi
return error;
}
-static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
+static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting, int from_glob)
{
+ git_oid commit_id;
int error;
- git_object *obj;
- git_otype type;
+ git_object *obj, *oobj;
git_commit_list_node *commit;
- if ((error = git_object_lookup(&obj, walk->repo, oid, GIT_OBJ_ANY)) < 0)
+ if ((error = git_object_lookup(&oobj, walk->repo, oid, GIT_OBJ_ANY)) < 0)
return error;
- type = git_object_type(obj);
- git_object_free(obj);
+ error = git_object_peel(&obj, oobj, GIT_OBJ_COMMIT);
+ git_object_free(oobj);
+
+ if (error == GIT_ENOTFOUND) {
+ /* If this comes from e.g. push_glob("tags"), ignore this */
+ if (from_glob)
+ return 0;
- if (type != GIT_OBJ_COMMIT) {
- giterr_set(GITERR_INVALID, "Object is no commit object");
+ giterr_set(GITERR_INVALID, "Object is not a committish");
return -1;
}
+ if (error < 0)
+ return error;
+
+ git_oid_cpy(&commit_id, git_object_id(obj));
+ git_object_free(obj);
- commit = git_revwalk__commit_lookup(walk, oid);
+ commit = git_revwalk__commit_lookup(walk, &commit_id);
if (commit == NULL)
return -1; /* error already reported by failed lookup */
@@ -146,24 +155,24 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
{
assert(walk && oid);
- return push_commit(walk, oid, 0);
+ return push_commit(walk, oid, 0, false);
}
int git_revwalk_hide(git_revwalk *walk, const git_oid *oid)
{
assert(walk && oid);
- return push_commit(walk, oid, 1);
+ return push_commit(walk, oid, 1, false);
}
-static int push_ref(git_revwalk *walk, const char *refname, int hide)
+static int push_ref(git_revwalk *walk, const char *refname, int hide, int from_glob)
{
git_oid oid;
if (git_reference_name_to_id(&oid, walk->repo, refname) < 0)
return -1;
- return push_commit(walk, &oid, hide);
+ return push_commit(walk, &oid, hide, from_glob);
}
struct push_cb_data {
@@ -171,17 +180,12 @@ struct push_cb_data {
int hide;
};
-static int push_glob_cb(const char *refname, void *data_)
-{
- struct push_cb_data *data = (struct push_cb_data *)data_;
- return push_ref(data->walk, refname, data->hide);
-}
-
static int push_glob(git_revwalk *walk, const char *glob, int hide)
{
int error = 0;
git_buf buf = GIT_BUF_INIT;
- struct push_cb_data data;
+ git_reference *ref;
+ git_reference_iterator *iter;
size_t wildcard;
assert(walk && glob);
@@ -199,12 +203,20 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
if (!glob[wildcard])
git_buf_put(&buf, "/*", 2);
- data.walk = walk;
- data.hide = hide;
+ if ((error = git_reference_iterator_glob_new(&iter, walk->repo, buf.ptr)) < 0)
+ goto out;
- error = git_reference_foreach_glob(
- walk->repo, git_buf_cstr(&buf), push_glob_cb, &data);
+ while ((error = git_reference_next(&ref, iter)) == 0) {
+ error = push_ref(walk, git_reference_name(ref), hide, true);
+ git_reference_free(ref);
+ if (error < 0)
+ break;
+ }
+ git_reference_iterator_free(iter);
+ if (error == GIT_ITEROVER)
+ error = 0;
+out:
git_buf_free(&buf);
return error;
}
@@ -224,19 +236,19 @@ int git_revwalk_hide_glob(git_revwalk *walk, const char *glob)
int git_revwalk_push_head(git_revwalk *walk)
{
assert(walk);
- return push_ref(walk, GIT_HEAD_FILE, 0);
+ return push_ref(walk, GIT_HEAD_FILE, 0, false);
}
int git_revwalk_hide_head(git_revwalk *walk)
{
assert(walk);
- return push_ref(walk, GIT_HEAD_FILE, 1);
+ return push_ref(walk, GIT_HEAD_FILE, 1, false);
}
int git_revwalk_push_ref(git_revwalk *walk, const char *refname)
{
assert(walk && refname);
- return push_ref(walk, refname, 0);
+ return push_ref(walk, refname, 0, false);
}
int git_revwalk_push_range(git_revwalk *walk, const char *range)
@@ -253,10 +265,10 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
return GIT_EINVALIDSPEC;
}
- if ((error = push_commit(walk, git_object_id(revspec.from), 1)))
+ if ((error = push_commit(walk, git_object_id(revspec.from), 1, false)))
goto out;
- error = push_commit(walk, git_object_id(revspec.to), 0);
+ error = push_commit(walk, git_object_id(revspec.to), 0, false);
out:
git_object_free(revspec.from);
@@ -267,7 +279,7 @@ out:
int git_revwalk_hide_ref(git_revwalk *walk, const char *refname)
{
assert(walk && refname);
- return push_ref(walk, refname, 1);
+ return push_ref(walk, refname, 1, false);
}
static int revwalk_enqueue_timesort(git_revwalk *walk, git_commit_list_node *commit)
diff --git a/src/settings.c b/src/settings.c
new file mode 100644
index 000000000..748f76560
--- /dev/null
+++ b/src/settings.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include <stdarg.h>
+
+#include <git2.h>
+#include "common.h"
+#include "fileops.h"
+#include "cache.h"
+
+void git_libgit2_version(int *major, int *minor, int *rev)
+{
+ *major = LIBGIT2_VER_MAJOR;
+ *minor = LIBGIT2_VER_MINOR;
+ *rev = LIBGIT2_VER_REVISION;
+}
+
+int git_libgit2_capabilities()
+{
+ return 0
+#ifdef GIT_THREADS
+ | GIT_CAP_THREADS
+#endif
+#if defined(GIT_SSL) || defined(GIT_WINHTTP)
+ | GIT_CAP_HTTPS
+#endif
+#if defined(GIT_SSH)
+ | GIT_CAP_SSH
+#endif
+ ;
+}
+
+/* Declarations for tuneable settings */
+extern size_t git_mwindow__window_size;
+extern size_t git_mwindow__mapped_limit;
+
+static int config_level_to_futils_dir(int config_level)
+{
+ int val = -1;
+
+ switch (config_level) {
+ case GIT_CONFIG_LEVEL_SYSTEM: val = GIT_FUTILS_DIR_SYSTEM; break;
+ case GIT_CONFIG_LEVEL_XDG: val = GIT_FUTILS_DIR_XDG; break;
+ case GIT_CONFIG_LEVEL_GLOBAL: val = GIT_FUTILS_DIR_GLOBAL; break;
+ default:
+ giterr_set(
+ GITERR_INVALID, "Invalid config path selector %d", config_level);
+ }
+
+ return val;
+}
+
+int git_libgit2_opts(int key, ...)
+{
+ int error = 0;
+ va_list ap;
+
+ va_start(ap, key);
+
+ switch (key) {
+ case GIT_OPT_SET_MWINDOW_SIZE:
+ git_mwindow__window_size = va_arg(ap, size_t);
+ break;
+
+ case GIT_OPT_GET_MWINDOW_SIZE:
+ *(va_arg(ap, size_t *)) = git_mwindow__window_size;
+ break;
+
+ case GIT_OPT_SET_MWINDOW_MAPPED_LIMIT:
+ git_mwindow__mapped_limit = va_arg(ap, size_t);
+ break;
+
+ case GIT_OPT_GET_MWINDOW_MAPPED_LIMIT:
+ *(va_arg(ap, size_t *)) = git_mwindow__mapped_limit;
+ break;
+
+ case GIT_OPT_GET_SEARCH_PATH:
+ if ((error = config_level_to_futils_dir(va_arg(ap, int))) >= 0) {
+ char *out = va_arg(ap, char *);
+ size_t outlen = va_arg(ap, size_t);
+
+ error = git_futils_dirs_get_str(out, outlen, error);
+ }
+ break;
+
+ case GIT_OPT_SET_SEARCH_PATH:
+ if ((error = config_level_to_futils_dir(va_arg(ap, int))) >= 0)
+ error = git_futils_dirs_set(error, va_arg(ap, const char *));
+ break;
+
+ case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
+ {
+ git_otype type = (git_otype)va_arg(ap, int);
+ size_t size = va_arg(ap, size_t);
+ error = git_cache_set_max_object_size(type, size);
+ break;
+ }
+
+ case GIT_OPT_SET_CACHE_MAX_SIZE:
+ git_cache__max_storage = va_arg(ap, ssize_t);
+ break;
+
+ case GIT_OPT_ENABLE_CACHING:
+ git_cache__enabled = (va_arg(ap, int) != 0);
+ break;
+
+ case GIT_OPT_GET_CACHED_MEMORY:
+ *(va_arg(ap, ssize_t *)) = git_cache__current_storage.val;
+ *(va_arg(ap, ssize_t *)) = git_cache__max_storage;
+ break;
+
+ case GIT_OPT_GET_TEMPLATE_PATH:
+ {
+ char *out = va_arg(ap, char *);
+ size_t outlen = va_arg(ap, size_t);
+
+ error = git_futils_dirs_get_str(out, outlen, GIT_FUTILS_DIR_TEMPLATE);
+ }
+ break;
+
+ case GIT_OPT_SET_TEMPLATE_PATH:
+ error = git_futils_dirs_set(GIT_FUTILS_DIR_TEMPLATE, va_arg(ap, const char *));
+ break;
+ }
+
+ va_end(ap);
+
+ return error;
+}
+
diff --git a/src/signature.c b/src/signature.c
index ec51a42e9..f658d6035 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -82,23 +82,28 @@ int git_signature_new(git_signature **sig_out, const char *name, const char *ema
return 0;
}
-git_signature *git_signature_dup(const git_signature *sig)
+int git_signature_dup(git_signature **dest, const git_signature *source)
{
- git_signature *new;
+ git_signature *signature;
- if (sig == NULL)
- return NULL;
+ if (source == NULL)
+ return 0;
+
+ signature = git__calloc(1, sizeof(git_signature));
+ GITERR_CHECK_ALLOC(signature);
+
+ signature->name = git__strdup(source->name);
+ GITERR_CHECK_ALLOC(signature->name);
- new = git__calloc(1, sizeof(git_signature));
- if (new == NULL)
- return NULL;
+ signature->email = git__strdup(source->email);
+ GITERR_CHECK_ALLOC(signature->email);
- new->name = git__strdup(sig->name);
- new->email = git__strdup(sig->email);
- new->when.time = sig->when.time;
- new->when.offset = sig->when.offset;
+ signature->when.time = source->when.time;
+ signature->when.offset = source->when.offset;
- return new;
+ *dest = signature;
+
+ return 0;
}
int git_signature_now(git_signature **sig_out, const char *name, const char *email)
diff --git a/src/stash.c b/src/stash.c
index 3019816ff..b1dd87b22 100644
--- a/src/stash.c
+++ b/src/stash.c
@@ -417,7 +417,7 @@ static int update_reflog(
if ((error = git_reference_ensure_log(repo, GIT_REFS_STASH_FILE)) < 0)
return error;
- error = git_reference_create_with_log(&stash, repo, GIT_REFS_STASH_FILE, w_commit_oid, 1, stasher, message);
+ error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, w_commit_oid, 1, stasher, message);
git_reference_free(stash);
@@ -628,7 +628,7 @@ int git_stash_drop(
entry = git_reflog_entry_byindex(reflog, 0);
git_reference_free(stash);
- if ((error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, &entry->oid_cur, 1) < 0))
+ if ((error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, &entry->oid_cur, 1, NULL, NULL) < 0))
goto cleanup;
/* We need to undo the writing that we just did */
diff --git a/src/status.c b/src/status.c
index 7a1472d8d..3c95b347c 100644
--- a/src/status.c
+++ b/src/status.c
@@ -38,7 +38,7 @@ static unsigned int index_delta2status(const git_diff_delta *head2idx)
case GIT_DELTA_RENAMED:
st = GIT_STATUS_INDEX_RENAMED;
- if (!git_oid_equal(&head2idx->old_file.oid, &head2idx->new_file.oid))
+ if (!git_oid_equal(&head2idx->old_file.id, &head2idx->new_file.id))
st |= GIT_STATUS_INDEX_MODIFIED;
break;
case GIT_DELTA_TYPECHANGE:
@@ -74,25 +74,25 @@ static unsigned int workdir_delta2status(
case GIT_DELTA_RENAMED:
st = GIT_STATUS_WT_RENAMED;
- if (!git_oid_equal(&idx2wd->old_file.oid, &idx2wd->new_file.oid)) {
+ if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id)) {
/* if OIDs don't match, we might need to calculate them now to
* discern between RENAMED vs RENAMED+MODIFED
*/
- if (git_oid_iszero(&idx2wd->old_file.oid) &&
+ if (git_oid_iszero(&idx2wd->old_file.id) &&
diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
!git_diff__oid_for_file(
diff->repo, idx2wd->old_file.path, idx2wd->old_file.mode,
- idx2wd->old_file.size, &idx2wd->old_file.oid))
- idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ idx2wd->old_file.size, &idx2wd->old_file.id))
+ idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
- if (git_oid_iszero(&idx2wd->new_file.oid) &&
+ if (git_oid_iszero(&idx2wd->new_file.id) &&
diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
!git_diff__oid_for_file(
diff->repo, idx2wd->new_file.path, idx2wd->new_file.mode,
- idx2wd->new_file.size, &idx2wd->new_file.oid))
- idx2wd->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
+ idx2wd->new_file.size, &idx2wd->new_file.id))
+ idx2wd->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
- if (!git_oid_equal(&idx2wd->old_file.oid, &idx2wd->new_file.oid))
+ if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id))
st |= GIT_STATUS_WT_MODIFIED;
}
break;
diff --git a/src/strnlen.h b/src/strnlen.h
new file mode 100644
index 000000000..007da2e55
--- /dev/null
+++ b/src/strnlen.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_strlen_h__
+#define INCLUDE_strlen_h__
+
+#if defined(__MINGW32__) || defined(__sun) || defined(__APPLE__)
+# define NO_STRNLEN
+#endif
+
+#ifdef NO_STRNLEN
+GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) {
+ const char *end = memchr(s, 0, maxlen);
+ return end ? (size_t)(end - s) : maxlen;
+}
+#else
+# define p_strnlen strnlen
+#endif
+
+#endif
diff --git a/src/submodule.c b/src/submodule.c
index 26dfe2c6b..2388bd144 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -387,7 +387,7 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index)
error = -1;
goto cleanup;
}
- git_oid_cpy(&entry.oid, &sm->wd_oid);
+ git_oid_cpy(&entry.id, &sm->wd_oid);
if ((error = git_commit_lookup(&head, sm_repo, &sm->wd_oid)) < 0)
goto cleanup;
@@ -472,6 +472,10 @@ int git_submodule_save(git_submodule *submodule)
(error = git_config_file_set_string(mods, key.ptr, submodule->url)) < 0)
goto cleanup;
+ if ((error = submodule_config_key_trunc_puts(&key, "branch")) < 0 ||
+ (error = git_config_file_set_string(mods, key.ptr, submodule->branch)) < 0)
+ goto cleanup;
+
if (!(error = submodule_config_key_trunc_puts(&key, "update")) &&
(val = git_submodule_update_to_str(submodule->update)) != NULL)
error = git_config_file_set_string(mods, key.ptr, val);
@@ -494,6 +498,7 @@ int git_submodule_save(git_submodule *submodule)
submodule->ignore_default = submodule->ignore;
submodule->update_default = submodule->update;
+ submodule->fetch_recurse_default = submodule->fetch_recurse;
submodule->flags |= GIT_SUBMODULE_STATUS_IN_CONFIG;
cleanup:
@@ -528,6 +533,12 @@ const char *git_submodule_url(git_submodule *submodule)
return submodule->url;
}
+const char *git_submodule_branch(git_submodule *submodule)
+{
+ assert(submodule);
+ return submodule->branch;
+}
+
int git_submodule_set_url(git_submodule *submodule, const char *url)
{
assert(submodule && url);
@@ -640,6 +651,9 @@ git_submodule_recurse_t git_submodule_set_fetch_recurse_submodules(
assert(submodule);
+ if (fetch_recurse_submodules == GIT_SUBMODULE_RECURSE_RESET)
+ fetch_recurse_submodules = submodule->fetch_recurse_default;
+
old = submodule->fetch_recurse;
submodule->fetch_recurse = fetch_recurse_submodules;
return old;
@@ -770,7 +784,7 @@ static void submodule_update_from_index_entry(
if (already_found)
sm->flags |= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES;
else
- git_oid_cpy(&sm->index_oid, &ie->oid);
+ git_oid_cpy(&sm->index_oid, &ie->id);
sm->flags |= GIT_SUBMODULE_STATUS_IN_INDEX |
GIT_SUBMODULE_STATUS__INDEX_OID_VALID;
@@ -990,8 +1004,9 @@ static git_submodule *submodule_alloc(git_repository *repo, const char *name)
GIT_REFCOUNT_INC(sm);
sm->ignore = sm->ignore_default = GIT_SUBMODULE_IGNORE_NONE;
sm->update = sm->update_default = GIT_SUBMODULE_UPDATE_CHECKOUT;
- sm->fetch_recurse = GIT_SUBMODULE_RECURSE_YES;
+ sm->fetch_recurse = sm->fetch_recurse_default = GIT_SUBMODULE_RECURSE_NO;
sm->repo = repo;
+ sm->branch = NULL;
return sm;
}
@@ -1190,6 +1205,15 @@ static int submodule_load_from_config(
goto done;
}
}
+ else if (strcasecmp(property, "branch") == 0) {
+ git__free(sm->branch);
+ sm->branch = NULL;
+
+ if (value != NULL && (sm->branch = git__strdup(value)) == NULL) {
+ error = -1;
+ goto done;
+ }
+ }
else if (strcasecmp(property, "update") == 0) {
if ((error = git_submodule_parse_update(&sm->update, value)) < 0)
goto done;
@@ -1198,6 +1222,7 @@ static int submodule_load_from_config(
else if (strcasecmp(property, "fetchRecurseSubmodules") == 0) {
if (git_submodule_parse_recurse(&sm->fetch_recurse, value) < 0)
return -1;
+ sm->fetch_recurse_default = sm->fetch_recurse;
}
else if (strcasecmp(property, "ignore") == 0) {
if ((error = git_submodule_parse_ignore(&sm->ignore, value)) < 0)
@@ -1261,7 +1286,7 @@ static int load_submodule_config_from_index(
if (!submodule_get(&sm, repo, entry->path, NULL))
submodule_update_from_index_entry(sm, entry);
} else if (strcmp(entry->path, GIT_MODULES_FILE) == 0)
- git_oid_cpy(gitmodules_oid, &entry->oid);
+ git_oid_cpy(gitmodules_oid, &entry->id);
}
if (error == GIT_ITEROVER)
@@ -1300,16 +1325,16 @@ static int load_submodule_config_from_head(
if (S_ISGITLINK(entry->mode))
submodule_update_from_head_data(
- sm, entry->mode, &entry->oid);
+ sm, entry->mode, &entry->id);
else
sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE;
} else if (S_ISGITLINK(entry->mode)) {
if (!submodule_get(&sm, repo, entry->path, NULL))
submodule_update_from_head_data(
- sm, entry->mode, &entry->oid);
+ sm, entry->mode, &entry->id);
} else if (strcmp(entry->path, GIT_MODULES_FILE) == 0 &&
git_oid_iszero(gitmodules_oid)) {
- git_oid_cpy(gitmodules_oid, &entry->oid);
+ git_oid_cpy(gitmodules_oid, &entry->id);
}
}
diff --git a/src/submodule.h b/src/submodule.h
index 2a610e112..5e532e1ae 100644
--- a/src/submodule.h
+++ b/src/submodule.h
@@ -60,7 +60,9 @@
* - `update_default` is the update value from the config
* - `ignore` is a git_submodule_ignore_t value - see gitmodules(5) ignore.
* - `ignore_default` is the ignore value from the config
- * - `fetch_recurse` is 0 or 1 - see gitmodules(5) fetchRecurseSubmodules.
+ * - `fetch_recurse` is a git_submodule_recurse_t value - see gitmodules(5)
+ * fetchRecurseSubmodules.
+ * - `fetch_recurse_default` is the recurse value from the config
*
* - `repo` is the parent repository that contains this submodule.
* - `flags` after for internal use, tracking where this submodule has been
@@ -81,11 +83,13 @@ struct git_submodule {
char *name;
char *path; /* important: may just point to "name" string */
char *url;
+ char *branch;
git_submodule_update_t update;
git_submodule_update_t update_default;
git_submodule_ignore_t ignore;
git_submodule_ignore_t ignore_default;
git_submodule_recurse_t fetch_recurse;
+ git_submodule_recurse_t fetch_recurse_default;
/* internal information */
git_repository *repo;
diff --git a/src/tag.c b/src/tag.c
index be56b05ce..1a4ee1e1c 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -271,7 +271,7 @@ static int git_tag_create__internal(
} else
git_oid_cpy(oid, git_object_id(target));
- error = git_reference_create(&new_ref, repo, ref_name.ptr, oid, allow_ref_overwrite);
+ error = git_reference_create(&new_ref, repo, ref_name.ptr, oid, allow_ref_overwrite, NULL, NULL);
cleanup:
git_reference_free(new_ref);
@@ -376,7 +376,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
return -1;
}
- error = git_reference_create(&new_ref, repo, ref_name.ptr, oid, allow_ref_overwrite);
+ error = git_reference_create(&new_ref, repo, ref_name.ptr, oid, allow_ref_overwrite, NULL, NULL);
git_reference_free(new_ref);
git_buf_free(&ref_name);
diff --git a/src/transports/local.c b/src/transports/local.c
index 4635d5dd3..26ada48e6 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -156,6 +156,24 @@ on_error:
return -1;
}
+static int path_from_url_or_path(git_buf *local_path_out, const char *url_or_path)
+{
+ int error;
+
+ /* If url_or_path begins with file:// treat it as a URL */
+ if (!git__prefixcmp(url_or_path, "file://")) {
+ if ((error = git_path_fromurl(local_path_out, url_or_path)) < 0) {
+ return error;
+ }
+ } else { /* We assume url_or_path is already a path */
+ if ((error = git_buf_sets(local_path_out, url_or_path)) < 0) {
+ return error;
+ }
+ }
+
+ return 0;
+}
+
/*
* Try to open the url as a git directory. The direction doesn't
* matter in this case because we're calulating the heads ourselves.
@@ -181,17 +199,12 @@ static int local_connect(
t->direction = direction;
t->flags = flags;
- /* The repo layer doesn't want the prefix */
- if (!git__prefixcmp(t->url, "file://")) {
- if (git_path_fromurl(&buf, t->url) < 0) {
- git_buf_free(&buf);
- return -1;
- }
- path = git_buf_cstr(&buf);
-
- } else { /* We assume transport->url is already a path */
- path = t->url;
+ /* 'url' may be a url or path; convert to a path */
+ if ((error = path_from_url_or_path(&buf, url)) < 0) {
+ git_buf_free(&buf);
+ return error;
}
+ path = git_buf_cstr(&buf);
error = git_repository_open(&repo, path);
@@ -315,7 +328,7 @@ static int local_push_update_remote_ref(
if (lref) {
/* Create or update a ref */
if ((error = git_reference_create(NULL, remote_repo, rref, loid,
- !git_oid_iszero(roid))) < 0)
+ !git_oid_iszero(roid), NULL, NULL)) < 0)
return error;
} else {
/* Delete a ref */
@@ -344,11 +357,24 @@ static int local_push(
git_repository *remote_repo = NULL;
push_spec *spec;
char *url = NULL;
+ const char *path;
+ git_buf buf = GIT_BUF_INIT;
int error;
unsigned int i;
size_t j;
- if ((error = git_repository_open(&remote_repo, push->remote->url)) < 0)
+ /* 'push->remote->url' may be a url or path; convert to a path */
+ if ((error = path_from_url_or_path(&buf, push->remote->url)) < 0) {
+ git_buf_free(&buf);
+ return error;
+ }
+ path = git_buf_cstr(&buf);
+
+ error = git_repository_open(&remote_repo, path);
+
+ git_buf_free(&buf);
+
+ if (error < 0)
return error;
/* We don't currently support pushing locally to non-bare repos. Proper
diff --git a/src/tree.c b/src/tree.c
index 4d77ff778..877a3fcee 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -204,22 +204,22 @@ void git_tree_entry_free(git_tree_entry *entry)
git__free(entry);
}
-git_tree_entry *git_tree_entry_dup(const git_tree_entry *entry)
+int git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source)
{
size_t total_size;
git_tree_entry *copy;
- assert(entry);
+ assert(source);
- total_size = sizeof(git_tree_entry) + entry->filename_len + 1;
+ total_size = sizeof(git_tree_entry) + source->filename_len + 1;
copy = git__malloc(total_size);
- if (!copy)
- return NULL;
+ GITERR_CHECK_ALLOC(copy);
- memcpy(copy, entry, total_size);
+ memcpy(copy, source, total_size);
- return copy;
+ *dest = copy;
+ return 0;
}
void git_tree__free(void *_tree)
@@ -305,8 +305,8 @@ const git_tree_entry *git_tree_entry_byindex(
return git_vector_get(&tree->entries, idx);
}
-const git_tree_entry *git_tree_entry_byoid(
- const git_tree *tree, const git_oid *oid)
+const git_tree_entry *git_tree_entry_byid(
+ const git_tree *tree, const git_oid *id)
{
size_t i;
const git_tree_entry *e;
@@ -314,7 +314,7 @@ const git_tree_entry *git_tree_entry_byoid(
assert(tree);
git_vector_foreach(&tree->entries, i, e) {
- if (memcmp(&e->oid.id, &oid->id, sizeof(oid->id)) == 0)
+ if (memcmp(&e->oid.id, &id->id, sizeof(id->id)) == 0)
return e;
}
@@ -551,7 +551,7 @@ static int write_tree(
if (error < 0)
goto on_error;
} else {
- error = append_entry(bld, filename, &entry->oid, entry->mode);
+ error = append_entry(bld, filename, &entry->id, entry->mode);
if (error < 0)
goto on_error;
}
@@ -853,8 +853,7 @@ int git_tree_entry_bypath(
case '\0':
/* If there are no more components in the path, return
* this entry */
- *entry_out = git_tree_entry_dup(entry);
- return 0;
+ return git_tree_entry_dup(entry_out, entry);
}
if (git_tree_lookup(&subtree, root->object.repo, &entry->oid) < 0)
diff --git a/src/userdiff.h b/src/userdiff.h
new file mode 100644
index 000000000..7eb095246
--- /dev/null
+++ b/src/userdiff.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_userdiff_h__
+#define INCLUDE_userdiff_h__
+
+/*
+ * This file isolates the built in diff driver function name patterns.
+ * Most of these patterns are taken from Git (with permission from the
+ * original authors for relicensing to libgit2).
+ */
+
+typedef struct {
+ const char *name;
+ const char *fns;
+ const char *words;
+ int flags;
+} git_diff_driver_definition;
+
+#define WORD_DEFAULT "|[^[:space:]]|[\xc0-\xff][\x80-\xbf]+"
+
+/*
+ * These builtin driver definition macros have same signature as in core
+ * git userdiff.c so that the data can be extracted verbatim
+ */
+#define PATTERNS(NAME, FN_PATS, WORD_PAT) \
+ { NAME, FN_PATS, WORD_PAT WORD_DEFAULT, 0 }
+#define IPATTERN(NAME, FN_PATS, WORD_PAT) \
+ { NAME, FN_PATS, WORD_PAT WORD_DEFAULT, REG_ICASE }
+
+/*
+ * The table of diff driver patterns
+ *
+ * Function name patterns are a list of newline separated patterns that
+ * match a function declaration (i.e. the line you want in the hunk header),
+ * or a negative pattern prefixed with a '!' to reject a pattern (such as
+ * rejecting goto labels in C code).
+ *
+ * Word boundary patterns are just a simple pattern that will be OR'ed with
+ * the default value above (i.e. whitespace or non-ASCII characters).
+ */
+static git_diff_driver_definition builtin_defs[] = {
+
+IPATTERN("ada",
+ "!^(.*[ \t])?(is new|renames|is separate)([ \t].*)?$\n"
+ "!^[ \t]*with[ \t].*$\n"
+ "^[ \t]*((procedure|function)[ \t]+.*)$\n"
+ "^[ \t]*((package|protected|task)[ \t]+.*)$",
+ /* -- */
+ "[a-zA-Z][a-zA-Z0-9_]*"
+ "|[0-9][-+0-9#_.eE]"
+ "|=>|\\.\\.|\\*\\*|:=|/=|>=|<=|<<|>>|<>"),
+
+IPATTERN("fortran",
+ "!^([C*]|[ \t]*!)\n"
+ "!^[ \t]*MODULE[ \t]+PROCEDURE[ \t]\n"
+ "^[ \t]*((END[ \t]+)?(PROGRAM|MODULE|BLOCK[ \t]+DATA"
+ "|([^'\" \t]+[ \t]+)*(SUBROUTINE|FUNCTION))[ \t]+[A-Z].*)$",
+ /* -- */
+ "[a-zA-Z][a-zA-Z0-9_]*"
+ "|\\.([Ee][Qq]|[Nn][Ee]|[Gg][TtEe]|[Ll][TtEe]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|[Aa][Nn][Dd]|[Oo][Rr]|[Nn]?[Ee][Qq][Vv]|[Nn][Oo][Tt])\\."
+ /* numbers and format statements like 2E14.4, or ES12.6, 9X.
+ * Don't worry about format statements without leading digits since
+ * they would have been matched above as a variable anyway. */
+ "|[-+]?[0-9.]+([AaIiDdEeFfLlTtXx][Ss]?[-+]?[0-9.]*)?(_[a-zA-Z0-9][a-zA-Z0-9_]*)?"
+ "|//|\\*\\*|::|[/<>=]="),
+
+PATTERNS("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$",
+ "[^<>= \t]+"),
+
+PATTERNS("java",
+ "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
+ "^[ \t]*(([A-Za-z_][A-Za-z_0-9]*[ \t]+)+[A-Za-z_][A-Za-z_0-9]*[ \t]*\\([^;]*)$",
+ /* -- */
+ "[a-zA-Z_][a-zA-Z0-9_]*"
+ "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
+ "|[-+*/<>%&^|=!]="
+ "|--|\\+\\+|<<=?|>>>?=?|&&|\\|\\|"),
+
+PATTERNS("matlab",
+ "^[[:space:]]*((classdef|function)[[:space:]].*)$|^%%[[:space:]].*$",
+ "[a-zA-Z_][a-zA-Z0-9_]*|[-+0-9.e]+|[=~<>]=|\\.[*/\\^']|\\|\\||&&"),
+
+PATTERNS("objc",
+ /* Negate C statements that can look like functions */
+ "!^[ \t]*(do|for|if|else|return|switch|while)\n"
+ /* Objective-C methods */
+ "^[ \t]*([-+][ \t]*\\([ \t]*[A-Za-z_][A-Za-z_0-9* \t]*\\)[ \t]*[A-Za-z_].*)$\n"
+ /* C functions */
+ "^[ \t]*(([A-Za-z_][A-Za-z_0-9]*[ \t]+)+[A-Za-z_][A-Za-z_0-9]*[ \t]*\\([^;]*)$\n"
+ /* Objective-C class/protocol definitions */
+ "^(@(implementation|interface|protocol)[ \t].*)$",
+ /* -- */
+ "[a-zA-Z_][a-zA-Z0-9_]*"
+ "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
+ "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
+
+PATTERNS("pascal",
+ "^(((class[ \t]+)?(procedure|function)|constructor|destructor|interface|"
+ "implementation|initialization|finalization)[ \t]*.*)$"
+ "\n"
+ "^(.*=[ \t]*(class|record).*)$",
+ /* -- */
+ "[a-zA-Z_][a-zA-Z0-9_]*"
+ "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+"
+ "|<>|<=|>=|:=|\\.\\."),
+
+PATTERNS("perl",
+ "^package .*\n"
+ "^sub [[:alnum:]_':]+[ \t]*"
+ "(\\([^)]*\\)[ \t]*)?" /* prototype */
+ /*
+ * Attributes. A regex can't count nested parentheses,
+ * so just slurp up whatever we see, taking care not
+ * to accept lines like "sub foo; # defined elsewhere".
+ *
+ * An attribute could contain a semicolon, but at that
+ * point it seems reasonable enough to give up.
+ */
+ "(:[^;#]*)?"
+ "(\\{[ \t]*)?" /* brace can come here or on the next line */
+ "(#.*)?$\n" /* comment */
+ "^(BEGIN|END|INIT|CHECK|UNITCHECK|AUTOLOAD|DESTROY)[ \t]*"
+ "(\\{[ \t]*)?" /* brace can come here or on the next line */
+ "(#.*)?$\n"
+ "^=head[0-9] .*", /* POD */
+ /* -- */
+ "[[:alpha:]_'][[:alnum:]_']*"
+ "|0[xb]?[0-9a-fA-F_]*"
+ /* taking care not to interpret 3..5 as (3.)(.5) */
+ "|[0-9a-fA-F_]+(\\.[0-9a-fA-F_]+)?([eE][-+]?[0-9_]+)?"
+ "|=>|-[rwxoRWXOezsfdlpSugkbctTBMAC>]|~~|::"
+ "|&&=|\\|\\|=|//=|\\*\\*="
+ "|&&|\\|\\||//|\\+\\+|--|\\*\\*|\\.\\.\\.?"
+ "|[-+*/%.^&<>=!|]="
+ "|=~|!~"
+ "|<<|<>|<=>|>>"),
+
+PATTERNS("python", "^[ \t]*((class|def)[ \t].*)$",
+ /* -- */
+ "[a-zA-Z_][a-zA-Z0-9_]*"
+ "|[-+0-9.e]+[jJlL]?|0[xX]?[0-9a-fA-F]+[lL]?"
+ "|[-+*/<>%&^|=!]=|//=?|<<=?|>>=?|\\*\\*=?"),
+
+PATTERNS("ruby", "^[ \t]*((class|module|def)[ \t].*)$",
+ /* -- */
+ "(@|@@|\\$)?[a-zA-Z_][a-zA-Z0-9_]*"
+ "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+|\\?(\\\\C-)?(\\\\M-)?."
+ "|//=?|[-+*/<>%&^|=!]=|<<=?|>>=?|===|\\.{1,3}|::|[!=]~"),
+
+PATTERNS("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$",
+ "[={}\"]|[^={}\" \t]+"),
+
+PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
+ "\\\\[a-zA-Z@]+|\\\\.|[a-zA-Z0-9\x80-\xff]+"),
+
+PATTERNS("cpp",
+ /* Jump targets or access declarations */
+ "!^[ \t]*[A-Za-z_][A-Za-z_0-9]*:.*$\n"
+ /* C/++ functions/methods at top level */
+ "^([A-Za-z_][A-Za-z_0-9]*([ \t*]+[A-Za-z_][A-Za-z_0-9]*([ \t]*::[ \t]*[^[:space:]]+)?){1,}[ \t]*\\([^;]*)$\n"
+ /* compound type at top level */
+ "^((struct|class|enum)[^;]*)$",
+ /* -- */
+ "[a-zA-Z_][a-zA-Z0-9_]*"
+ "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
+ "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
+
+PATTERNS("csharp",
+ /* Keywords */
+ "!^[ \t]*(do|while|for|if|else|instanceof|new|return|switch|case|throw|catch|using)\n"
+ /* Methods and constructors */
+ "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[<>@._[:alnum:]]+[ \t]*\\(.*\\))[ \t]*$\n"
+ /* Properties */
+ "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[@._[:alnum:]]+)[ \t]*$\n"
+ /* Type definitions */
+ "^[ \t]*(((static|public|internal|private|protected|new|unsafe|sealed|abstract|partial)[ \t]+)*(class|enum|interface|struct)[ \t]+.*)$\n"
+ /* Namespace */
+ "^[ \t]*(namespace[ \t]+.*)$",
+ /* -- */
+ "[a-zA-Z_][a-zA-Z0-9_]*"
+ "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
+ "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
+
+PATTERNS("php",
+ "^[ \t]*(((public|private|protected|static|final)[ \t]+)*((class|function)[ \t].*))$",
+ /* -- */
+ "[a-zA-Z_][a-zA-Z0-9_]*"
+ "|[-+0-9.e]+[fFlL]?|0[xX]?[0-9a-fA-F]+[lL]?"
+ "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
+
+PATTERNS("javascript",
+ "^[ \t]*(function[ \t][a-zA-Z_][^\\{]*)\n"
+ "^[ \t]*(var[ \t]+[a-zA-Z_][a-zA-Z0-9_]*[ \t]*=[ \t]*function[ \t\\(][^\\{]*)\n"
+ "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*[ \t]*:[ \t]*function[ \t\\(][^\\{]*)",
+ /* -- */
+ "[a-zA-Z_][a-zA-Z0-9_]*"
+ "|[-+0-9.e]+[fFlL]?|0[xX]?[0-9a-fA-F]+[lL]?"
+ "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
+};
+
+#undef IPATTERN
+#undef PATTERNS
+#undef WORD_DEFAULT
+
+#endif
+
diff --git a/src/util.c b/src/util.c
index 47516a8f7..3767b890c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -6,140 +6,21 @@
*/
#include <git2.h>
#include "common.h"
-#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include "posix.h"
-#include "fileops.h"
-#include "cache.h"
#ifdef _MSC_VER
# include <Shlwapi.h>
#endif
-void git_libgit2_version(int *major, int *minor, int *rev)
-{
- *major = LIBGIT2_VER_MAJOR;
- *minor = LIBGIT2_VER_MINOR;
- *rev = LIBGIT2_VER_REVISION;
-}
-
-int git_libgit2_capabilities()
-{
- return 0
-#ifdef GIT_THREADS
- | GIT_CAP_THREADS
-#endif
-#if defined(GIT_SSL) || defined(GIT_WINHTTP)
- | GIT_CAP_HTTPS
-#endif
-#if defined(GIT_SSH)
- | GIT_CAP_SSH
-#endif
- ;
-}
-
-/* Declarations for tuneable settings */
-extern size_t git_mwindow__window_size;
-extern size_t git_mwindow__mapped_limit;
-
-static int config_level_to_futils_dir(int config_level)
-{
- int val = -1;
-
- switch (config_level) {
- case GIT_CONFIG_LEVEL_SYSTEM: val = GIT_FUTILS_DIR_SYSTEM; break;
- case GIT_CONFIG_LEVEL_XDG: val = GIT_FUTILS_DIR_XDG; break;
- case GIT_CONFIG_LEVEL_GLOBAL: val = GIT_FUTILS_DIR_GLOBAL; break;
- default:
- giterr_set(
- GITERR_INVALID, "Invalid config path selector %d", config_level);
- }
-
- return val;
-}
-
-int git_libgit2_opts(int key, ...)
-{
- int error = 0;
- va_list ap;
-
- va_start(ap, key);
-
- switch (key) {
- case GIT_OPT_SET_MWINDOW_SIZE:
- git_mwindow__window_size = va_arg(ap, size_t);
- break;
-
- case GIT_OPT_GET_MWINDOW_SIZE:
- *(va_arg(ap, size_t *)) = git_mwindow__window_size;
- break;
-
- case GIT_OPT_SET_MWINDOW_MAPPED_LIMIT:
- git_mwindow__mapped_limit = va_arg(ap, size_t);
- break;
-
- case GIT_OPT_GET_MWINDOW_MAPPED_LIMIT:
- *(va_arg(ap, size_t *)) = git_mwindow__mapped_limit;
- break;
-
- case GIT_OPT_GET_SEARCH_PATH:
- if ((error = config_level_to_futils_dir(va_arg(ap, int))) >= 0) {
- char *out = va_arg(ap, char *);
- size_t outlen = va_arg(ap, size_t);
-
- error = git_futils_dirs_get_str(out, outlen, error);
- }
- break;
-
- case GIT_OPT_SET_SEARCH_PATH:
- if ((error = config_level_to_futils_dir(va_arg(ap, int))) >= 0)
- error = git_futils_dirs_set(error, va_arg(ap, const char *));
- break;
-
- case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
- {
- git_otype type = (git_otype)va_arg(ap, int);
- size_t size = va_arg(ap, size_t);
- error = git_cache_set_max_object_size(type, size);
- break;
- }
-
- case GIT_OPT_SET_CACHE_MAX_SIZE:
- git_cache__max_storage = va_arg(ap, ssize_t);
- break;
-
- case GIT_OPT_ENABLE_CACHING:
- git_cache__enabled = (va_arg(ap, int) != 0);
- break;
-
- case GIT_OPT_GET_CACHED_MEMORY:
- *(va_arg(ap, ssize_t *)) = git_cache__current_storage.val;
- *(va_arg(ap, ssize_t *)) = git_cache__max_storage;
- break;
-
- case GIT_OPT_GET_TEMPLATE_PATH:
- {
- char *out = va_arg(ap, char *);
- size_t outlen = va_arg(ap, size_t);
-
- error = git_futils_dirs_get_str(out, outlen, GIT_FUTILS_DIR_TEMPLATE);
- }
- break;
-
- case GIT_OPT_SET_TEMPLATE_PATH:
- error = git_futils_dirs_set(GIT_FUTILS_DIR_TEMPLATE, va_arg(ap, const char *));
- break;
- }
-
- va_end(ap);
-
- return error;
-}
-
void git_strarray_free(git_strarray *array)
{
size_t i;
+
+ if (array == NULL)
+ return;
+
for (i = 0; i < array->count; ++i)
git__free(array->strings[i]);
@@ -729,6 +610,7 @@ void git__qsort_r(
#if defined(__MINGW32__) || defined(AMIGA) || \
defined(__OpenBSD__) || defined(__NetBSD__) || \
defined(__gnu_hurd__) || defined(__ANDROID_API__) || \
+ defined(__sun) || \
(__GLIBC__ == 2 && __GLIBC_MINOR__ < 8)
git__insertsort_r(els, nel, elsize, NULL, cmp, payload);
#elif defined(GIT_WIN32)
diff --git a/src/util.h b/src/util.h
index f9de909e9..e378786d9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -8,6 +8,7 @@
#define INCLUDE_util_h__
#include "common.h"
+#include "strnlen.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
@@ -50,8 +51,7 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n)
size_t length = 0;
char *ptr;
- while (length < n && str[length])
- ++length;
+ length = p_strnlen(str, n);
ptr = (char*)git__malloc(length + 1);
diff --git a/src/vector.c b/src/vector.c
index 050e032a0..f0c2f06c2 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -6,7 +6,6 @@
*/
#include "common.h"
-#include "repository.h"
#include "vector.h"
/* In elements, not bytes */
diff --git a/src/zstream.c b/src/zstream.c
new file mode 100644
index 000000000..85fa2e0e6
--- /dev/null
+++ b/src/zstream.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include <zlib.h>
+
+#include "zstream.h"
+#include "buffer.h"
+
+#define ZSTREAM_BUFFER_SIZE (1024 * 1024)
+#define ZSTREAM_BUFFER_MIN_EXTRA 8
+
+static int zstream_seterr(git_zstream *zs)
+{
+ if (zs->zerr == Z_OK || zs->zerr == Z_STREAM_END)
+ return 0;
+
+ if (zs->zerr == Z_MEM_ERROR)
+ giterr_set_oom();
+ else if (zs->z.msg)
+ giterr_set(GITERR_ZLIB, zs->z.msg);
+ else
+ giterr_set(GITERR_ZLIB, "Unknown compression error");
+
+ return -1;
+}
+
+int git_zstream_init(git_zstream *zstream)
+{
+ zstream->zerr = deflateInit(&zstream->z, Z_DEFAULT_COMPRESSION);
+ return zstream_seterr(zstream);
+}
+
+void git_zstream_free(git_zstream *zstream)
+{
+ deflateEnd(&zstream->z);
+}
+
+void git_zstream_reset(git_zstream *zstream)
+{
+ deflateReset(&zstream->z);
+ zstream->in = NULL;
+ zstream->in_len = 0;
+ zstream->zerr = Z_STREAM_END;
+}
+
+int git_zstream_set_input(git_zstream *zstream, const void *in, size_t in_len)
+{
+ zstream->in = in;
+ zstream->in_len = in_len;
+ zstream->zerr = Z_OK;
+ return 0;
+}
+
+bool git_zstream_done(git_zstream *zstream)
+{
+ return (!zstream->in_len && zstream->zerr == Z_STREAM_END);
+}
+
+size_t git_zstream_suggest_output_len(git_zstream *zstream)
+{
+ if (zstream->in_len > ZSTREAM_BUFFER_SIZE)
+ return ZSTREAM_BUFFER_SIZE;
+ else if (zstream->in_len > ZSTREAM_BUFFER_MIN_EXTRA)
+ return zstream->in_len;
+ else
+ return ZSTREAM_BUFFER_MIN_EXTRA;
+}
+
+int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream)
+{
+ int zflush = Z_FINISH;
+ size_t out_remain = *out_len;
+
+ while (out_remain > 0 && zstream->zerr != Z_STREAM_END) {
+ size_t out_queued, in_queued, out_used, in_used;
+
+ /* set up in data */
+ zstream->z.next_in = (Bytef *)zstream->in;
+ zstream->z.avail_in = (uInt)zstream->in_len;
+ if ((size_t)zstream->z.avail_in != zstream->in_len) {
+ zstream->z.avail_in = INT_MAX;
+ zflush = Z_NO_FLUSH;
+ } else {
+ zflush = Z_FINISH;
+ }
+ in_queued = (size_t)zstream->z.avail_in;
+
+ /* set up out data */
+ zstream->z.next_out = out;
+ zstream->z.avail_out = (uInt)out_remain;
+ if ((size_t)zstream->z.avail_out != out_remain)
+ zstream->z.avail_out = INT_MAX;
+ out_queued = (size_t)zstream->z.avail_out;
+
+ /* compress next chunk */
+ zstream->zerr = deflate(&zstream->z, zflush);
+
+ if (zstream->zerr == Z_STREAM_ERROR)
+ return zstream_seterr(zstream);
+
+ out_used = (out_queued - zstream->z.avail_out);
+ out_remain -= out_used;
+ out = ((char *)out) + out_used;
+
+ in_used = (in_queued - zstream->z.avail_in);
+ zstream->in_len -= in_used;
+ zstream->in += in_used;
+ }
+
+ /* either we finished the input or we did not flush the data */
+ assert(zstream->in_len > 0 || zflush == Z_FINISH);
+
+ /* set out_size to number of bytes actually written to output */
+ *out_len = *out_len - out_remain;
+
+ return 0;
+}
+
+int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len)
+{
+ git_zstream zs = GIT_ZSTREAM_INIT;
+ int error = 0;
+
+ if ((error = git_zstream_init(&zs)) < 0)
+ return error;
+
+ if ((error = git_zstream_set_input(&zs, in, in_len)) < 0)
+ goto done;
+
+ while (!git_zstream_done(&zs)) {
+ size_t step = git_zstream_suggest_output_len(&zs), written;
+
+ if ((error = git_buf_grow(out, out->asize + step)) < 0)
+ goto done;
+
+ written = out->asize - out->size;
+
+ if ((error = git_zstream_get_output(
+ out->ptr + out->size, &written, &zs)) < 0)
+ goto done;
+
+ out->size += written;
+ }
+
+ /* NULL terminate for consistency if possible */
+ if (out->size < out->asize)
+ out->ptr[out->size] = '\0';
+
+done:
+ git_zstream_free(&zs);
+ return error;
+}
diff --git a/src/zstream.h b/src/zstream.h
new file mode 100644
index 000000000..9b5bf6ace
--- /dev/null
+++ b/src/zstream.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_zstream_h__
+#define INCLUDE_zstream_h__
+
+#include <zlib.h>
+
+#include "common.h"
+#include "buffer.h"
+
+typedef struct {
+ z_stream z;
+ const char *in;
+ size_t in_len;
+ int zerr;
+} git_zstream;
+
+#define GIT_ZSTREAM_INIT {{0}}
+
+int git_zstream_init(git_zstream *zstream);
+void git_zstream_free(git_zstream *zstream);
+
+int git_zstream_set_input(git_zstream *zstream, const void *in, size_t in_len);
+
+size_t git_zstream_suggest_output_len(git_zstream *zstream);
+
+int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream);
+
+bool git_zstream_done(git_zstream *zstream);
+
+void git_zstream_reset(git_zstream *zstream);
+
+int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len);
+
+#endif /* INCLUDE_zstream_h__ */
diff --git a/tests/attr/repo.c b/tests/attr/repo.c
index f9ba585fb..49cccdc5a 100644
--- a/tests/attr/repo.c
+++ b/tests/attr/repo.c
@@ -293,7 +293,7 @@ static void assert_proper_normalization(git_index *index, const char *filename,
cl_assert(!git_index_find(&index_pos, index, filename));
entry = git_index_get_byindex(index, index_pos);
- cl_assert_equal_i(0, git_oid_streq(&entry->oid, expected_sha));
+ cl_assert_equal_i(0, git_oid_streq(&entry->id, expected_sha));
}
void test_attr_repo__staging_properly_normalizes_line_endings_according_to_gitattributes_directives(void)
diff --git a/tests/blame/blame_helpers.c b/tests/blame/blame_helpers.c
index d64bb5c4c..56240dbde 100644
--- a/tests/blame/blame_helpers.c
+++ b/tests/blame/blame_helpers.c
@@ -48,6 +48,9 @@ void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx,
actual, expected);
}
cl_assert_equal_s(actual, expected);
+ cl_assert_equal_i(git_oid_cmp(&hunk->final_commit_id, &hunk->orig_commit_id), 0);
+
+
if (strcmp(hunk->orig_path, orig_path)) {
hunk_message(idx, hunk, "has mismatched original path (got '%s', expected '%s')\n",
hunk->orig_path, orig_path);
diff --git a/tests/checkout/conflict.c b/tests/checkout/conflict.c
index 66965a89b..a8b93b28d 100644
--- a/tests/checkout/conflict.c
+++ b/tests/checkout/conflict.c
@@ -96,7 +96,7 @@ static void create_index(struct checkout_index_entry *entries, size_t entries_le
entry.mode = entries[i].mode;
entry.flags = entries[i].stage << GIT_IDXENTRY_STAGESHIFT;
- git_oid_fromstr(&entry.oid, entries[i].oid_str);
+ git_oid_fromstr(&entry.id, entries[i].oid_str);
entry.path = entries[i].path;
cl_git_pass(git_index_add(g_index, &entry));
diff --git a/tests/checkout/crlf.c b/tests/checkout/crlf.c
index 9a4cbd313..cba79432f 100644
--- a/tests/checkout/crlf.c
+++ b/tests/checkout/crlf.c
@@ -174,13 +174,13 @@ void test_checkout_crlf__with_ident(void)
/* check that blobs have $Id$ */
cl_git_pass(git_blob_lookup(&blob, g_repo,
- & git_index_get_bypath(index, "lf.ident", 0)->oid));
+ & git_index_get_bypath(index, "lf.ident", 0)->id));
cl_assert_equal_s(
ALL_LF_TEXT_RAW "\n$Id$\n", git_blob_rawcontent(blob));
git_blob_free(blob);
cl_git_pass(git_blob_lookup(&blob, g_repo,
- & git_index_get_bypath(index, "more2.identcrlf", 0)->oid));
+ & git_index_get_bypath(index, "more2.identcrlf", 0)->id));
cl_assert_equal_s(
"\n$Id$\n" MORE_CRLF_TEXT_AS_LF, git_blob_rawcontent(blob));
git_blob_free(blob);
diff --git a/tests/checkout/index.c b/tests/checkout/index.c
index 48d6d79f9..57ce4313b 100644
--- a/tests/checkout/index.c
+++ b/tests/checkout/index.c
@@ -307,8 +307,8 @@ static int test_checkout_notify_cb(
cl_assert_equal_i(GIT_CHECKOUT_NOTIFY_CONFLICT, why);
cl_assert_equal_s(expectations->file, path);
- cl_assert_equal_i(0, git_oid_streq(&baseline->oid, expectations->sha));
- cl_assert_equal_i(0, git_oid_streq(&target->oid, expectations->sha));
+ cl_assert_equal_i(0, git_oid_streq(&baseline->id, expectations->sha));
+ cl_assert_equal_i(0, git_oid_streq(&target->id, expectations->sha));
return 0;
}
diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c
index 06aa6a594..407908ad3 100644
--- a/tests/checkout/tree.c
+++ b/tests/checkout/tree.c
@@ -63,7 +63,7 @@ void test_checkout_tree__can_checkout_and_remove_directory(void)
cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees"));
cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
- cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees", NULL, NULL));
cl_assert_equal_i(true, git_path_isdir("./testrepo/ab/"));
cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt"));
@@ -78,7 +78,7 @@ void test_checkout_tree__can_checkout_and_remove_directory(void)
cl_git_pass(git_revparse_single(&g_object, g_repo, "master"));
cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
- cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master"));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master", NULL, NULL));
/* This directory should no longer exist */
cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/"));
@@ -163,7 +163,7 @@ void test_checkout_tree__can_switch_branches(void)
cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
- cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir", NULL, NULL));
cl_assert(git_path_isfile("testrepo/README"));
cl_assert(git_path_isfile("testrepo/branch_file.txt"));
@@ -183,7 +183,7 @@ void test_checkout_tree__can_switch_branches(void)
cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
- cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees", NULL, NULL));
cl_assert(git_path_isfile("testrepo/README"));
cl_assert(git_path_isfile("testrepo/branch_file.txt"));
@@ -253,7 +253,7 @@ static int checkout_tree_with_blob_ignored_in_workdir(int strategy, bool isdir)
cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
- cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir", NULL, NULL));
cl_assert(git_path_isfile("testrepo/README"));
cl_assert(git_path_isfile("testrepo/branch_file.txt"));
@@ -313,7 +313,7 @@ void test_checkout_tree__can_overwrite_ignored_by_default(void)
{
cl_git_pass(checkout_tree_with_blob_ignored_in_workdir(GIT_CHECKOUT_SAFE, false));
- cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees", NULL, NULL));
cl_assert(git_path_isfile("testrepo/ab/4.txt"));
@@ -334,7 +334,7 @@ void test_checkout_tree__can_overwrite_ignored_folder_by_default(void)
{
cl_git_pass(checkout_tree_with_blob_ignored_in_workdir(GIT_CHECKOUT_SAFE, true));
- cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees", NULL, NULL));
cl_assert(git_path_isfile("testrepo/ab/4.txt"));
@@ -367,7 +367,7 @@ void test_checkout_tree__can_update_only(void)
cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
- cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir", NULL, NULL));
assert_on_branch(g_repo, "dir");
@@ -396,7 +396,7 @@ void test_checkout_tree__can_checkout_with_pattern(void)
cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
cl_git_pass(
- git_repository_set_head_detached(g_repo, git_object_id(g_object)));
+ git_repository_set_head_detached(g_repo, git_object_id(g_object), NULL, NULL));
git_object_free(g_object);
g_object = NULL;
@@ -435,7 +435,7 @@ void test_checkout_tree__can_disable_pattern_match(void)
cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
cl_git_pass(
- git_repository_set_head_detached(g_repo, git_object_id(g_object)));
+ git_repository_set_head_detached(g_repo, git_object_id(g_object), NULL, NULL));
git_object_free(g_object);
g_object = NULL;
@@ -480,11 +480,11 @@ void assert_conflict(
/* Create a branch pointing at the parent */
cl_git_pass(git_revparse_single(&g_object, g_repo, parent_sha));
cl_git_pass(git_branch_create(&branch, g_repo,
- "potential_conflict", (git_commit *)g_object, 0));
+ "potential_conflict", (git_commit *)g_object, 0, NULL, NULL));
/* Make HEAD point to this branch */
cl_git_pass(git_reference_symbolic_create(
- &head, g_repo, "HEAD", git_reference_name(branch), 1));
+ &head, g_repo, "HEAD", git_reference_name(branch), 1, NULL, NULL));
git_reference_free(head);
git_reference_free(branch);
@@ -687,7 +687,7 @@ void test_checkout_tree__can_checkout_with_last_workdir_item_missing(void)
cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id));
cl_git_pass(git_checkout_tree(g_repo, (git_object *)commit, &opts));
- cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master"));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master", NULL, NULL));
cl_git_pass(p_mkdir("./testrepo/this-is-dir", 0777));
cl_git_mkfile("./testrepo/this-is-dir/contained_file", "content\n");
@@ -892,16 +892,16 @@ static void create_conflict(void)
memset(&entry, 0x0, sizeof(git_index_entry));
entry.mode = 0100644;
entry.flags = 1 << GIT_IDXENTRY_STAGESHIFT;
- git_oid_fromstr(&entry.oid, "d427e0b2e138501a3d15cc376077a3631e15bd46");
+ git_oid_fromstr(&entry.id, "d427e0b2e138501a3d15cc376077a3631e15bd46");
entry.path = "conflicts.txt";
cl_git_pass(git_index_add(index, &entry));
entry.flags = 2 << GIT_IDXENTRY_STAGESHIFT;
- git_oid_fromstr(&entry.oid, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf");
+ git_oid_fromstr(&entry.id, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf");
cl_git_pass(git_index_add(index, &entry));
entry.flags = 3 << GIT_IDXENTRY_STAGESHIFT;
- git_oid_fromstr(&entry.oid, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
+ git_oid_fromstr(&entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
cl_git_pass(git_index_add(index, &entry));
git_index_write(index);
@@ -925,3 +925,26 @@ void test_checkout_tree__fails_when_conflicts_exist_in_index(void)
git_object_free(obj);
}
+
+void test_checkout_tree__filemode_preserved_in_index(void)
+{
+ git_oid executable_oid;
+ git_commit *commit;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ git_index *index;
+ const git_index_entry *entry;
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ cl_git_pass(git_oid_fromstr(&executable_oid, "afe4393b2b2a965f06acf2ca9658eaa01e0cd6b6"));
+ cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid));
+
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+
+ cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts));
+ cl_assert(entry = git_index_get_bypath(index, "executable.txt", 0));
+ cl_assert_equal_i(0100755, entry->mode);
+
+ git_commit_free(commit);
+ git_index_free(index);
+}
diff --git a/tests/checkout/typechange.c b/tests/checkout/typechange.c
index 6cf99ac15..d88864cf3 100644
--- a/tests/checkout/typechange.c
+++ b/tests/checkout/typechange.c
@@ -122,7 +122,7 @@ void test_checkout_typechange__checkout_typechanges_safe(void)
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
cl_git_pass(
- git_repository_set_head_detached(g_repo, git_object_id(obj)));
+ git_repository_set_head_detached(g_repo, git_object_id(obj), NULL, NULL));
assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true);
@@ -231,7 +231,7 @@ void test_checkout_typechange__checkout_with_conflicts(void)
cl_assert(!git_path_exists("typechanges/untracked"));
cl_git_pass(
- git_repository_set_head_detached(g_repo, git_object_id(obj)));
+ git_repository_set_head_detached(g_repo, git_object_id(obj), NULL, NULL));
assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true);
diff --git a/tests/clar/fs.h b/tests/clar/fs.h
index b7a1ff9d2..7c7dde6fc 100644
--- a/tests/clar/fs.h
+++ b/tests/clar/fs.h
@@ -12,7 +12,7 @@
#endif /* __MINGW32__ */
-static int
+static int
fs__dotordotdot(WCHAR *_tocheck)
{
return _tocheck[0] == '.' &&
@@ -201,7 +201,7 @@ fs_copy(const char *_source, const char *_dest)
DWORD source_attrs, dest_attrs;
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
-
+
/* The input paths are UTF-8. Convert them to wide characters
* for use with the Windows API. */
cl_assert(MultiByteToWideChar(CP_UTF8,
@@ -251,17 +251,22 @@ cl_fs_cleanup(void)
}
#else
+
+#include <errno.h>
+#include <string.h>
+
static int
shell_out(char * const argv[])
{
- int status;
+ int status, piderr;
pid_t pid;
pid = fork();
if (pid < 0) {
fprintf(stderr,
- "System error: `fork()` call failed.\n");
+ "System error: `fork()` call failed (%d) - %s\n",
+ errno, strerror(errno));
exit(-1);
}
@@ -269,7 +274,10 @@ shell_out(char * const argv[])
execv(argv[0], argv);
}
- waitpid(pid, &status, 0);
+ do {
+ piderr = waitpid(pid, &status, WUNTRACED);
+ } while (piderr < 0 && (errno == EAGAIN || errno == EINTR));
+
return WEXITSTATUS(status);
}
diff --git a/tests/clone/empty.c b/tests/clone/empty.c
index 6d19244cc..78aef7dae 100644
--- a/tests/clone/empty.c
+++ b/tests/clone/empty.c
@@ -38,7 +38,7 @@ void test_clone_empty__can_clone_an_empty_local_repo_barely(void)
char *local_name = "refs/heads/master";
const char *expected_tracked_branch_name = "refs/remotes/origin/master";
const char *expected_remote_name = "origin";
- char buffer[1024];
+ git_buf buf = GIT_BUF_INIT;
git_reference *ref;
cl_set_cleanup(&cleanup_repository, "./empty");
@@ -50,16 +50,14 @@ void test_clone_empty__can_clone_an_empty_local_repo_barely(void)
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned, local_name));
/* ...one can still retrieve the name of the remote tracking reference */
- cl_assert_equal_i((int)strlen(expected_tracked_branch_name) + 1,
- git_branch_upstream_name(buffer, 1024, g_repo_cloned, local_name));
+ cl_git_pass(git_branch_upstream_name(&buf, g_repo_cloned, local_name));
- cl_assert_equal_s(expected_tracked_branch_name, buffer);
+ cl_assert_equal_s(expected_tracked_branch_name, buf.ptr);
/* ...and the name of the remote... */
- cl_assert_equal_i((int)strlen(expected_remote_name) + 1,
- git_branch_remote_name(buffer, 1024, g_repo_cloned, expected_tracked_branch_name));
+ cl_git_pass(git_branch_remote_name(&buf, g_repo_cloned, expected_tracked_branch_name));
- cl_assert_equal_s(expected_remote_name, buffer);
+ cl_assert_equal_s(expected_remote_name, buf.ptr);
/* ...even when the remote HEAD is unborn as well */
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned,
diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c
index 3cd5fb7f6..f00d28b7a 100644
--- a/tests/clone/nonetwork.c
+++ b/tests/clone/nonetwork.c
@@ -24,6 +24,7 @@ void test_clone_nonetwork__initialize(void)
g_options.checkout_opts = dummy_opts;
g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
g_options.remote_callbacks = dummy_callbacks;
+ cl_git_pass(git_signature_now(&g_options.signature, "Me", "foo@example.com"));
}
void test_clone_nonetwork__cleanup(void)
@@ -43,6 +44,7 @@ void test_clone_nonetwork__cleanup(void)
g_remote = NULL;
}
+ git_signature_free(g_options.signature);
cl_fixture_cleanup("./foo");
}
@@ -213,11 +215,13 @@ void test_clone_nonetwork__can_detached_head(void)
git_object *obj;
git_repository *cloned;
git_reference *cloned_head;
+ git_reflog *log;
+ const git_reflog_entry *entry;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
cl_git_pass(git_revparse_single(&obj, g_repo, "master~1"));
- cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(obj)));
+ cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(obj), NULL, NULL));
cl_git_pass(git_clone(&cloned, "./foo", "./foo1", &g_options));
@@ -226,9 +230,55 @@ void test_clone_nonetwork__can_detached_head(void)
cl_git_pass(git_repository_head(&cloned_head, cloned));
cl_assert(!git_oid_cmp(git_object_id(obj), git_reference_target(cloned_head)));
+ cl_git_pass(git_reflog_read(&log, cloned, "HEAD"));
+ entry = git_reflog_entry_byindex(log, 0);
+ cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
+
git_object_free(obj);
git_reference_free(cloned_head);
+ git_reflog_free(log);
git_repository_free(cloned);
cl_fixture_cleanup("./foo1");
}
+
+static void assert_correct_reflog(const char *name)
+{
+ git_reflog *log;
+ const git_reflog_entry *entry;
+ char expected_log_message[128] = {0};
+
+ sprintf(expected_log_message, "clone: from %s", cl_git_fixture_url("testrepo.git"));
+
+ cl_git_pass(git_reflog_read(&log, g_repo, name));
+ cl_assert_equal_i(1, git_reflog_entrycount(log));
+ entry = git_reflog_entry_byindex(log, 0);
+ cl_assert_equal_s(expected_log_message, git_reflog_entry_message(entry));
+ cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
+
+ git_reflog_free(log);
+}
+
+void test_clone_nonetwork__clone_updates_reflog_properly(void)
+{
+ cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
+ assert_correct_reflog("HEAD");
+ assert_correct_reflog("refs/heads/master");
+}
+
+void test_clone_nonetwork__clone_into_updates_reflog_properly(void)
+{
+ git_remote *remote;
+ git_signature *sig;
+ cl_git_pass(git_signature_now(&sig, "Me", "foo@example.com"));
+
+ cl_git_pass(git_repository_init(&g_repo, "./foo", false));
+ cl_git_pass(git_remote_create(&remote, g_repo, "origin", cl_git_fixture_url("testrepo.git")));
+ cl_git_pass(git_clone_into(g_repo, remote, NULL, NULL, sig));
+
+ assert_correct_reflog("HEAD");
+ assert_correct_reflog("refs/heads/master");
+
+ git_remote_free(remote);
+ git_signature_free(sig);
+}
diff --git a/tests/commit/commit.c b/tests/commit/commit.c
index 4af9190b5..38397d2df 100644
--- a/tests/commit/commit.c
+++ b/tests/commit/commit.c
@@ -72,4 +72,8 @@ void test_commit_commit__summary(void)
assert_commit_summary("Trailing spaces are removed", "Trailing spaces are removed ");
assert_commit_summary("Trailing tabs", "Trailing tabs\t\n\nare removed");
assert_commit_summary("Trailing spaces", "Trailing spaces \n\nare removed");
+ assert_commit_summary("", "");
+ assert_commit_summary("", " ");
+ assert_commit_summary("", "\n");
+ assert_commit_summary("", "\n \n");
}
diff --git a/tests/commit/write.c b/tests/commit/write.c
index 73436b74b..8e5b67f2f 100644
--- a/tests/commit/write.c
+++ b/tests/commit/write.c
@@ -116,7 +116,7 @@ void test_commit_write__root(void)
cl_assert(head_old != NULL);
git_reference_free(head);
- cl_git_pass(git_reference_symbolic_create(&head, g_repo, "HEAD", branch_name, 1));
+ cl_git_pass(git_reference_symbolic_create(&head, g_repo, "HEAD", branch_name, 1, NULL, NULL));
cl_git_pass(git_commit_create_v(
&commit_id, /* out id */
diff --git a/tests/core/buffer.c b/tests/core/buffer.c
index 11d173d49..0e7dd3d70 100644
--- a/tests/core/buffer.c
+++ b/tests/core/buffer.c
@@ -406,6 +406,23 @@ check_joinbuf_2(
}
static void
+check_joinbuf_overlapped(
+ const char *oldval,
+ int ofs_a,
+ const char *b,
+ const char *expected)
+{
+ char sep = '/';
+ git_buf buf = GIT_BUF_INIT;
+
+ git_buf_sets(&buf, oldval);
+ git_buf_join(&buf, sep, buf.ptr + ofs_a, b);
+ cl_assert(git_buf_oom(&buf) == 0);
+ cl_assert_equal_s(expected, git_buf_cstr(&buf));
+ git_buf_free(&buf);
+}
+
+static void
check_joinbuf_n_2(
const char *a,
const char *b,
@@ -480,6 +497,20 @@ void test_core_buffer__8(void)
check_joinbuf_2("/abcd/", "defg/", "/abcd/defg/");
check_joinbuf_2("/abcd/", "/defg/", "/abcd/defg/");
+ check_joinbuf_overlapped("abcd", 0, "efg", "abcd/efg");
+ check_joinbuf_overlapped("abcd", 1, "efg", "bcd/efg");
+ check_joinbuf_overlapped("abcd", 2, "efg", "cd/efg");
+ check_joinbuf_overlapped("abcd", 3, "efg", "d/efg");
+ check_joinbuf_overlapped("abcd", 4, "efg", "efg");
+ check_joinbuf_overlapped("abc/", 2, "efg", "c/efg");
+ check_joinbuf_overlapped("abc/", 3, "efg", "/efg");
+ check_joinbuf_overlapped("abc/", 4, "efg", "efg");
+ check_joinbuf_overlapped("abcd", 3, "", "d/");
+ check_joinbuf_overlapped("abcd", 4, "", "");
+ check_joinbuf_overlapped("abc/", 2, "", "c/");
+ check_joinbuf_overlapped("abc/", 3, "", "/");
+ check_joinbuf_overlapped("abc/", 4, "", "");
+
check_joinbuf_n_2("", "", "");
check_joinbuf_n_2("", "a", "a");
check_joinbuf_n_2("", "/a", "/a");
diff --git a/tests/core/zstream.c b/tests/core/zstream.c
new file mode 100644
index 000000000..7ba9424ba
--- /dev/null
+++ b/tests/core/zstream.c
@@ -0,0 +1,143 @@
+#include "clar_libgit2.h"
+#include "buffer.h"
+#include "zstream.h"
+
+static const char *data = "This is a test test test of This is a test";
+
+#define INFLATE_EXTRA 2
+
+static void assert_zlib_equal_(
+ const void *expected, size_t e_len,
+ const void *compressed, size_t c_len,
+ const char *msg, const char *file, int line)
+{
+ z_stream stream;
+ char *expanded = git__calloc(1, e_len + INFLATE_EXTRA);
+ cl_assert(expanded);
+
+ memset(&stream, 0, sizeof(stream));
+ stream.next_out = (Bytef *)expanded;
+ stream.avail_out = (uInt)(e_len + INFLATE_EXTRA);
+ stream.next_in = (Bytef *)compressed;
+ stream.avail_in = (uInt)c_len;
+
+ cl_assert(inflateInit(&stream) == Z_OK);
+ cl_assert(inflate(&stream, Z_FINISH));
+ inflateEnd(&stream);
+
+ clar__assert_equal(
+ file, line, msg, 1,
+ "%d", (int)stream.total_out, (int)e_len);
+ clar__assert_equal(
+ file, line, "Buffer len was not exact match", 1,
+ "%d", (int)stream.avail_out, (int)INFLATE_EXTRA);
+
+ clar__assert(
+ memcmp(expanded, expected, e_len) == 0,
+ file, line, "uncompressed data did not match", NULL, 1);
+
+ git__free(expanded);
+}
+
+#define assert_zlib_equal(E,EL,C,CL) \
+ assert_zlib_equal_(E, EL, C, CL, #EL " != " #CL, __FILE__, (int)__LINE__)
+
+void test_core_zstream__basic(void)
+{
+ git_zstream z = GIT_ZSTREAM_INIT;
+ char out[128];
+ size_t outlen = sizeof(out);
+
+ cl_git_pass(git_zstream_init(&z));
+ cl_git_pass(git_zstream_set_input(&z, data, strlen(data) + 1));
+ cl_git_pass(git_zstream_get_output(out, &outlen, &z));
+ cl_assert(git_zstream_done(&z));
+ cl_assert(outlen > 0);
+ git_zstream_free(&z);
+
+ assert_zlib_equal(data, strlen(data) + 1, out, outlen);
+}
+
+void test_core_zstream__buffer(void)
+{
+ git_buf out = GIT_BUF_INIT;
+ cl_git_pass(git_zstream_deflatebuf(&out, data, strlen(data) + 1));
+ assert_zlib_equal(data, strlen(data) + 1, out.ptr, out.size);
+ git_buf_free(&out);
+}
+
+#define BIG_STRING_PART "Big Data IS Big - Long Data IS Long - We need a buffer larger than 1024 x 1024 to make sure we trigger chunked compression - Big Big Data IS Bigger than Big - Long Long Data IS Longer than Long"
+
+static void compress_input_various_ways(git_buf *input)
+{
+ git_buf out1 = GIT_BUF_INIT, out2 = GIT_BUF_INIT;
+ size_t i, fixed_size = max(input->size / 2, 256);
+ char *fixed = git__malloc(fixed_size);
+ cl_assert(fixed);
+
+ /* compress with deflatebuf */
+
+ cl_git_pass(git_zstream_deflatebuf(&out1, input->ptr, input->size));
+ assert_zlib_equal(input->ptr, input->size, out1.ptr, out1.size);
+
+ /* compress with various fixed size buffer (accumulating the output) */
+
+ for (i = 0; i < 3; ++i) {
+ git_zstream zs = GIT_ZSTREAM_INIT;
+ size_t use_fixed_size;
+
+ switch (i) {
+ case 0: use_fixed_size = 256; break;
+ case 1: use_fixed_size = fixed_size / 2; break;
+ case 2: use_fixed_size = fixed_size; break;
+ }
+ cl_assert(use_fixed_size <= fixed_size);
+
+ cl_git_pass(git_zstream_init(&zs));
+ cl_git_pass(git_zstream_set_input(&zs, input->ptr, input->size));
+
+ while (!git_zstream_done(&zs)) {
+ size_t written = use_fixed_size;
+ cl_git_pass(git_zstream_get_output(fixed, &written, &zs));
+ cl_git_pass(git_buf_put(&out2, fixed, written));
+ }
+
+ git_zstream_free(&zs);
+ assert_zlib_equal(input->ptr, input->size, out2.ptr, out2.size);
+
+ /* did both approaches give the same data? */
+ cl_assert_equal_sz(out1.size, out2.size);
+ cl_assert(!memcmp(out1.ptr, out2.ptr, out1.size));
+
+ git_buf_free(&out2);
+ }
+
+ git_buf_free(&out1);
+ git__free(fixed);
+}
+
+void test_core_zstream__big_data(void)
+{
+ git_buf in = GIT_BUF_INIT;
+ size_t scan, target;
+
+ for (target = 1024; target <= 1024 * 1024 * 4; target *= 8) {
+
+ /* make a big string that's easy to compress */
+ git_buf_clear(&in);
+ while (in.size < target)
+ cl_git_pass(
+ git_buf_put(&in, BIG_STRING_PART, strlen(BIG_STRING_PART)));
+
+ compress_input_various_ways(&in);
+
+ /* make a big string that's hard to compress */
+ srand(0xabad1dea);
+ for (scan = 0; scan < in.size; ++scan)
+ in.ptr[scan] = (char)rand();
+
+ compress_input_various_ways(&in);
+ }
+
+ git_buf_free(&in);
+}
diff --git a/tests/diff/blob.c b/tests/diff/blob.c
index 93f20711c..74df3cf85 100644
--- a/tests/diff/blob.c
+++ b/tests/diff/blob.c
@@ -167,9 +167,9 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void)
delta = git_patch_get_delta(p);
cl_assert(delta != NULL);
cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status);
- cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.id));
cl_assert_equal_sz(git_blob_rawsize(a), delta->old_file.size);
- cl_assert(git_oid_equal(git_blob_id(b), &delta->new_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(b), &delta->new_file.id));
cl_assert_equal_sz(git_blob_rawsize(b), delta->new_file.size);
cl_assert_equal_i(1, (int)git_patch_num_hunks(p));
@@ -190,9 +190,9 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void)
delta = git_patch_get_delta(p);
cl_assert(delta != NULL);
cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status);
- cl_assert(git_oid_equal(git_blob_id(b), &delta->old_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(b), &delta->old_file.id));
cl_assert_equal_sz(git_blob_rawsize(b), delta->old_file.size);
- cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.id));
cl_assert_equal_sz(git_blob_rawsize(c), delta->new_file.size);
cl_assert_equal_i(1, (int)git_patch_num_hunks(p));
@@ -213,9 +213,9 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void)
delta = git_patch_get_delta(p);
cl_assert(delta != NULL);
cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status);
- cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.id));
cl_assert_equal_sz(git_blob_rawsize(a), delta->old_file.size);
- cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.id));
cl_assert_equal_sz(git_blob_rawsize(c), delta->new_file.size);
cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p));
@@ -233,9 +233,9 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void)
delta = git_patch_get_delta(p);
cl_assert(delta != NULL);
cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status);
- cl_assert(git_oid_equal(git_blob_id(c), &delta->old_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(c), &delta->old_file.id));
cl_assert_equal_sz(git_blob_rawsize(c), delta->old_file.size);
- cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.id));
cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size);
cl_assert_equal_i(2, (int)git_patch_num_hunks(p));
@@ -328,9 +328,9 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void)
delta = git_patch_get_delta(p);
cl_assert(delta != NULL);
cl_assert_equal_i(GIT_DELTA_DELETED, delta->status);
- cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.id));
cl_assert_equal_sz(git_blob_rawsize(d), delta->old_file.size);
- cl_assert(git_oid_iszero(&delta->new_file.oid));
+ cl_assert(git_oid_iszero(&delta->new_file.id));
cl_assert_equal_sz(0, delta->new_file.size);
cl_assert_equal_i(1, (int)git_patch_num_hunks(p));
@@ -353,9 +353,9 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void)
delta = git_patch_get_delta(p);
cl_assert(delta != NULL);
cl_assert_equal_i(GIT_DELTA_ADDED, delta->status);
- cl_assert(git_oid_iszero(&delta->old_file.oid));
+ cl_assert(git_oid_iszero(&delta->old_file.id));
cl_assert_equal_sz(0, delta->old_file.size);
- cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.id));
cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size);
cl_assert_equal_i(1, (int)git_patch_num_hunks(p));
@@ -446,9 +446,9 @@ void test_diff_blob__can_compare_identical_blobs_with_patch(void)
cl_assert(delta != NULL);
cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status);
cl_assert_equal_sz(delta->old_file.size, git_blob_rawsize(d));
- cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.id));
cl_assert_equal_sz(delta->new_file.size, git_blob_rawsize(d));
- cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid));
+ cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.id));
cl_assert_equal_i(0, (int)git_patch_num_hunks(p));
git_patch_free(p);
@@ -460,9 +460,9 @@ void test_diff_blob__can_compare_identical_blobs_with_patch(void)
cl_assert(delta != NULL);
cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status);
cl_assert_equal_sz(0, delta->old_file.size);
- cl_assert(git_oid_iszero(&delta->old_file.oid));
+ cl_assert(git_oid_iszero(&delta->old_file.id));
cl_assert_equal_sz(0, delta->new_file.size);
- cl_assert(git_oid_iszero(&delta->new_file.oid));
+ cl_assert(git_oid_iszero(&delta->new_file.id));
cl_assert_equal_i(0, (int)git_patch_num_hunks(p));
git_patch_free(p);
@@ -853,7 +853,7 @@ void test_diff_blob__using_path_and_attributes(void)
size_t bin_len = 33;
const char *changed;
git_patch *p;
- char *pout;
+ git_buf buf = GIT_BUF_INIT;
/* set up custom diff drivers and 'diff' attribute mappings for them */
@@ -861,15 +861,15 @@ void test_diff_blob__using_path_and_attributes(void)
cl_git_pass(git_config_set_bool(cfg, "diff.iam_binary.binary", 1));
cl_git_pass(git_config_set_bool(cfg, "diff.iam_text.binary", 0));
cl_git_pass(git_config_set_string(
- cfg, "diff.iam_alphactx.xfuncname", "^[A-Za-z]"));
+ cfg, "diff.iam_alphactx.xfuncname", "^[A-Za-z].*$"));
cl_git_pass(git_config_set_bool(cfg, "diff.iam_textalpha.binary", 0));
cl_git_pass(git_config_set_string(
- cfg, "diff.iam_textalpha.xfuncname", "^[A-Za-z]"));
+ cfg, "diff.iam_textalpha.xfuncname", "^[A-Za-z].*$"));
cl_git_pass(git_config_set_string(
- cfg, "diff.iam_numctx.funcname", "^[0-9]"));
+ cfg, "diff.iam_numctx.funcname", "^[0-9][0-9]*"));
cl_git_pass(git_config_set_bool(cfg, "diff.iam_textnum.binary", 0));
cl_git_pass(git_config_set_string(
- cfg, "diff.iam_textnum.funcname", "^[0-9]"));
+ cfg, "diff.iam_textnum.funcname", "^[0-9][0-9]*"));
git_config_free(cfg);
cl_git_append2file(
@@ -951,7 +951,7 @@ void test_diff_blob__using_path_and_attributes(void)
cl_git_pass(git_patch_from_blob_and_buffer(
&p, nonbin, "zzz.normal", changed, strlen(changed), NULL, &opts));
- cl_git_pass(git_patch_to_str(&pout, p));
+ cl_git_pass(git_patch_to_buf(&buf, p));
cl_assert_equal_s(
"diff --git a/zzz.normal b/zzz.normal\n"
"index 45141a7..75b0dbb 100644\n"
@@ -960,23 +960,23 @@ void test_diff_blob__using_path_and_attributes(void)
"@@ -1,0 +2,3 @@ Hello from the root\n"
"+More lines\n"
"+And more\n"
- "+Go here\n", pout);
- git__free(pout);
+ "+Go here\n", buf.ptr);
+ git_buf_clear(&buf);
git_patch_free(p);
cl_git_pass(git_patch_from_blob_and_buffer(
&p, nonbin, "zzz.binary", changed, strlen(changed), NULL, &opts));
- cl_git_pass(git_patch_to_str(&pout, p));
+ cl_git_pass(git_patch_to_buf(&buf, p));
cl_assert_equal_s(
"diff --git a/zzz.binary b/zzz.binary\n"
"index 45141a7..75b0dbb 100644\n"
- "Binary files a/zzz.binary and b/zzz.binary differ\n", pout);
- git__free(pout);
+ "Binary files a/zzz.binary and b/zzz.binary differ\n", buf.ptr);
+ git_buf_clear(&buf);
git_patch_free(p);
cl_git_pass(git_patch_from_blob_and_buffer(
&p, nonbin, "zzz.alphary", changed, strlen(changed), NULL, &opts));
- cl_git_pass(git_patch_to_str(&pout, p));
+ cl_git_pass(git_patch_to_buf(&buf, p));
cl_assert_equal_s(
"diff --git a/zzz.alphary b/zzz.alphary\n"
"index 45141a7..75b0dbb 100644\n"
@@ -985,13 +985,13 @@ void test_diff_blob__using_path_and_attributes(void)
"@@ -1,0 +2,3 @@ Hello from the root\n"
"+More lines\n"
"+And more\n"
- "+Go here\n", pout);
- git__free(pout);
+ "+Go here\n", buf.ptr);
+ git_buf_clear(&buf);
git_patch_free(p);
cl_git_pass(git_patch_from_blob_and_buffer(
&p, nonbin, "zzz.numary", changed, strlen(changed), NULL, &opts));
- cl_git_pass(git_patch_to_str(&pout, p));
+ cl_git_pass(git_patch_to_buf(&buf, p));
cl_assert_equal_s(
"diff --git a/zzz.numary b/zzz.numary\n"
"index 45141a7..75b0dbb 100644\n"
@@ -1000,8 +1000,8 @@ void test_diff_blob__using_path_and_attributes(void)
"@@ -1,0 +2,3 @@\n"
"+More lines\n"
"+And more\n"
- "+Go here\n", pout);
- git__free(pout);
+ "+Go here\n", buf.ptr);
+ git_buf_clear(&buf);
git_patch_free(p);
/* "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n"
@@ -1012,17 +1012,17 @@ void test_diff_blob__using_path_and_attributes(void)
cl_git_pass(git_patch_from_blob_and_buffer(
&p, bin, "zzz.normal", changed, 37, NULL, &opts));
- cl_git_pass(git_patch_to_str(&pout, p));
+ cl_git_pass(git_patch_to_buf(&buf, p));
cl_assert_equal_s(
"diff --git a/zzz.normal b/zzz.normal\n"
"index b435cd5..1604519 100644\n"
- "Binary files a/zzz.normal and b/zzz.normal differ\n", pout);
- git__free(pout);
+ "Binary files a/zzz.normal and b/zzz.normal differ\n", buf.ptr);
+ git_buf_clear(&buf);
git_patch_free(p);
cl_git_pass(git_patch_from_blob_and_buffer(
&p, bin, "zzz.textary", changed, 37, NULL, &opts));
- cl_git_pass(git_patch_to_str(&pout, p));
+ cl_git_pass(git_patch_to_buf(&buf, p));
cl_assert_equal_s(
"diff --git a/zzz.textary b/zzz.textary\n"
"index b435cd5..1604519 100644\n"
@@ -1030,13 +1030,13 @@ void test_diff_blob__using_path_and_attributes(void)
"+++ b/zzz.textary\n"
"@@ -3 +3 @@\n"
"-0123456789\n"
- "+replace a line\n", pout);
- git__free(pout);
+ "+replace a line\n", buf.ptr);
+ git_buf_clear(&buf);
git_patch_free(p);
cl_git_pass(git_patch_from_blob_and_buffer(
&p, bin, "zzz.textalphary", changed, 37, NULL, &opts));
- cl_git_pass(git_patch_to_str(&pout, p));
+ cl_git_pass(git_patch_to_buf(&buf, p));
cl_assert_equal_s(
"diff --git a/zzz.textalphary b/zzz.textalphary\n"
"index b435cd5..1604519 100644\n"
@@ -1044,13 +1044,13 @@ void test_diff_blob__using_path_and_attributes(void)
"+++ b/zzz.textalphary\n"
"@@ -3 +3 @@\n"
"-0123456789\n"
- "+replace a line\n", pout);
- git__free(pout);
+ "+replace a line\n", buf.ptr);
+ git_buf_clear(&buf);
git_patch_free(p);
cl_git_pass(git_patch_from_blob_and_buffer(
&p, bin, "zzz.textnumary", changed, 37, NULL, &opts));
- cl_git_pass(git_patch_to_str(&pout, p));
+ cl_git_pass(git_patch_to_buf(&buf, p));
cl_assert_equal_s(
"diff --git a/zzz.textnumary b/zzz.textnumary\n"
"index b435cd5..1604519 100644\n"
@@ -1058,10 +1058,11 @@ void test_diff_blob__using_path_and_attributes(void)
"+++ b/zzz.textnumary\n"
"@@ -3 +3 @@ 0123456789\n"
"-0123456789\n"
- "+replace a line\n", pout);
- git__free(pout);
+ "+replace a line\n", buf.ptr);
+ git_buf_clear(&buf);
git_patch_free(p);
+ git_buf_free(&buf);
git_blob_free(nonbin);
git_blob_free(bin);
}
diff --git a/tests/diff/diffiter.c b/tests/diff/diffiter.c
index f886e1baa..c976e30e2 100644
--- a/tests/diff/diffiter.c
+++ b/tests/diff/diffiter.c
@@ -414,16 +414,16 @@ void test_diff_diffiter__iterate_and_generate_patch_text(void)
for (d = 0; d < num_d; ++d) {
git_patch *patch;
- char *text;
+ git_buf buf = GIT_BUF_INIT;
cl_git_pass(git_patch_from_diff(&patch, diff, d));
cl_assert(patch != NULL);
- cl_git_pass(git_patch_to_str(&text, patch));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
- cl_assert_equal_s(expected_patch_text[d], text);
+ cl_assert_equal_s(expected_patch_text[d], buf.ptr);
- git__free(text);
+ git_buf_free(&buf);
git_patch_free(patch);
}
diff --git a/tests/diff/drivers.c b/tests/diff/drivers.c
index fbd1dff81..8b12368ea 100644
--- a/tests/diff/drivers.c
+++ b/tests/diff/drivers.c
@@ -15,6 +15,23 @@ void test_diff_drivers__cleanup(void)
g_repo = NULL;
}
+static void overwrite_filemode(const char *expected, git_buf *actual)
+{
+ size_t offset;
+ char *found;
+
+ found = strstr(expected, "100644");
+ if (!found)
+ return;
+
+ offset = ((const char *)found) - expected;
+ if (actual->size < offset + 6)
+ return;
+
+ if (memcmp(&actual->ptr[offset], "100644", 6) != 0)
+ memcpy(&actual->ptr[offset], "100644", 6);
+}
+
void test_diff_drivers__patterns(void)
{
git_config *cfg;
@@ -22,7 +39,7 @@ void test_diff_drivers__patterns(void)
git_tree *one;
git_diff *diff;
git_patch *patch;
- char *text;
+ git_buf actual = GIT_BUF_INIT;
const char *expected0 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Comes through the blood of the vanguards who\n dreamed--too soon--it had sounded.\r\n \r\n -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n";
const char *expected1 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\nBinary files a/untimely.txt and b/untimely.txt differ\n";
const char *expected2 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Heaven delivers on earth the Hour that cannot be\n dreamed--too soon--it had sounded.\r\n \r\n -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n";
@@ -45,10 +62,10 @@ void test_diff_drivers__patterns(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected0, text);
+ cl_git_pass(git_patch_to_buf(&actual, patch));
+ cl_assert_equal_s(expected0, actual.ptr);
- git__free(text);
+ git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
@@ -60,10 +77,10 @@ void test_diff_drivers__patterns(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected1, text);
+ cl_git_pass(git_patch_to_buf(&actual, patch));
+ cl_assert_equal_s(expected1, actual.ptr);
- git__free(text);
+ git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
@@ -75,10 +92,10 @@ void test_diff_drivers__patterns(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected0, text);
+ cl_git_pass(git_patch_to_buf(&actual, patch));
+ cl_assert_equal_s(expected0, actual.ptr);
- git__free(text);
+ git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
@@ -92,10 +109,10 @@ void test_diff_drivers__patterns(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected1, text);
+ cl_git_pass(git_patch_to_buf(&actual, patch));
+ cl_assert_equal_s(expected1, actual.ptr);
- git__free(text);
+ git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
@@ -106,17 +123,17 @@ void test_diff_drivers__patterns(void)
cl_git_pass(git_repository_config(&cfg, g_repo));
cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 0));
- cl_git_pass(git_config_set_string(cfg, "diff.kipling0.xfuncname", "^H"));
+ cl_git_pass(git_config_set_string(cfg, "diff.kipling0.xfuncname", "^H.*$"));
git_config_free(cfg);
cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected2, text);
+ cl_git_pass(git_patch_to_buf(&actual, patch));
+ cl_assert_equal_s(expected2, actual.ptr);
- git__free(text);
+ git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
@@ -129,7 +146,7 @@ void test_diff_drivers__long_lines(void)
git_index *idx;
git_diff *diff;
git_patch *patch;
- char *actual;
+ git_buf actual = GIT_BUF_INIT;
const char *expected = "diff --git a/longlines.txt b/longlines.txt\nindex c1ce6ef..0134431 100644\n--- a/longlines.txt\n+++ b/longlines.txt\n@@ -3,3 +3,5 @@ Phasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissi\n Nam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\n Mauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\n Aliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n+newline\n+newline\n";
g_repo = cl_git_sandbox_init("empty_standard_repo");
@@ -145,19 +162,91 @@ void test_diff_drivers__long_lines(void)
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
cl_assert_equal_sz(1, git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&actual, patch));
+ cl_git_pass(git_patch_to_buf(&actual, patch));
/* if chmod not supported, overwrite mode bits since anything is possible */
- if (!cl_is_chmod_supported()) {
- size_t actual_len = strlen(actual);
- if (actual_len > 72 && memcmp(&actual[66], "100644", 6) != 0)
- memcpy(&actual[66], "100644", 6);
- }
+ overwrite_filemode(expected, &actual);
- cl_assert_equal_s(expected, actual);
+ cl_assert_equal_s(expected, actual.ptr);
- free(actual);
+ git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
}
+void test_diff_drivers__builtins(void)
+{
+ git_diff *diff;
+ git_patch *patch;
+ git_buf file = GIT_BUF_INIT, actual = GIT_BUF_INIT, expected = GIT_BUF_INIT;
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_vector files = GIT_VECTOR_INIT;
+ size_t i;
+ char *path, *extension;
+
+ g_repo = cl_git_sandbox_init("userdiff");
+
+ cl_git_pass(git_path_dirload("userdiff/files", 9, 0, 0, &files));
+
+ opts.interhunk_lines = 1;
+ opts.context_lines = 1;
+ opts.pathspec.count = 1;
+
+ git_vector_foreach(&files, i, path) {
+ if (git__prefixcmp(path, "files/file."))
+ continue;
+ extension = path + strlen("files/file.");
+ opts.pathspec.strings = &path;
+
+ /* do diff with no special driver */
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+ cl_assert_equal_sz(1, git_diff_num_deltas(diff));
+ cl_git_pass(git_patch_from_diff(&patch, diff, 0));
+ cl_git_pass(git_patch_to_buf(&actual, patch));
+
+ git_buf_sets(&expected, "userdiff/expected/nodriver/diff.");
+ git_buf_puts(&expected, extension);
+ cl_git_pass(git_futils_readbuffer(&expected, expected.ptr));
+
+ overwrite_filemode(expected.ptr, &actual);
+
+ cl_assert_equal_s(expected.ptr, actual.ptr);
+
+ git_buf_clear(&actual);
+ git_patch_free(patch);
+ git_diff_free(diff);
+
+ /* do diff with driver */
+
+ {
+ FILE *fp = fopen("userdiff/.gitattributes", "w");
+ fprintf(fp, "*.%s diff=%s\n", extension, extension);
+ fclose(fp);
+ }
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+ cl_assert_equal_sz(1, git_diff_num_deltas(diff));
+ cl_git_pass(git_patch_from_diff(&patch, diff, 0));
+ cl_git_pass(git_patch_to_buf(&actual, patch));
+
+ git_buf_sets(&expected, "userdiff/expected/driver/diff.");
+ git_buf_puts(&expected, extension);
+ cl_git_pass(git_futils_readbuffer(&expected, expected.ptr));
+
+ overwrite_filemode(expected.ptr, &actual);
+
+ cl_assert_equal_s(expected.ptr, actual.ptr);
+
+ git_buf_clear(&actual);
+ git_patch_free(patch);
+ git_diff_free(diff);
+
+ git__free(path);
+ }
+
+ git_buf_free(&file);
+ git_buf_free(&actual);
+ git_buf_free(&expected);
+ git_vector_free(&files);
+}
diff --git a/tests/diff/iterator.c b/tests/diff/iterator.c
index bbdae8ad1..92e6f723b 100644
--- a/tests/diff/iterator.c
+++ b/tests/diff/iterator.c
@@ -377,7 +377,7 @@ static void index_iterator_test(
if (expected_oids != NULL) {
git_oid oid;
cl_git_pass(git_oid_fromstr(&oid, expected_oids[count]));
- cl_assert_equal_i(git_oid_cmp(&oid, &entry->oid), 0);
+ cl_assert_equal_i(git_oid_cmp(&oid, &entry->id), 0);
}
count++;
diff --git a/tests/diff/patch.c b/tests/diff/patch.c
index 0cef3bd3a..76d7fcde3 100644
--- a/tests/diff/patch.c
+++ b/tests/diff/patch.c
@@ -141,7 +141,7 @@ void test_diff_patch__to_string(void)
git_tree *one, *another;
git_diff *diff;
git_patch *patch;
- char *text;
+ git_buf buf = GIT_BUF_INIT;
const char *expected = "diff --git a/subdir.txt b/subdir.txt\ndeleted file mode 100644\nindex e8ee89e..0000000\n--- a/subdir.txt\n+++ /dev/null\n@@ -1,2 +0,0 @@\n-Is it a bird?\n-Is it a plane?\n";
g_repo = cl_git_sandbox_init("status");
@@ -155,16 +155,16 @@ void test_diff_patch__to_string(void)
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
- cl_assert_equal_s(expected, text);
+ cl_assert_equal_s(expected, buf.ptr);
cl_assert_equal_sz(31, git_patch_size(patch, 0, 0, 0));
cl_assert_equal_sz(31, git_patch_size(patch, 1, 0, 0));
cl_assert_equal_sz(31 + 16, git_patch_size(patch, 1, 1, 0));
cl_assert_equal_sz(strlen(expected), git_patch_size(patch, 1, 1, 1));
- git__free(text);
+ git_buf_free(&buf);
git_patch_free(patch);
git_diff_free(diff);
git_tree_free(another);
@@ -178,7 +178,7 @@ void test_diff_patch__config_options(void)
git_config *cfg;
git_diff *diff;
git_patch *patch;
- char *text;
+ git_buf buf = GIT_BUF_INIT;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
char *onefile = "staged_changes_modified_file";
const char *expected1 = "diff --git c/staged_changes_modified_file i/staged_changes_modified_file\nindex 70bd944..906ee77 100644\n--- c/staged_changes_modified_file\n+++ i/staged_changes_modified_file\n@@ -1 +1,2 @@\n staged_changes_modified_file\n+staged_changes_modified_file\n";
@@ -199,10 +199,10 @@ void test_diff_patch__config_options(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected1, text);
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+ cl_assert_equal_s(expected1, buf.ptr);
- git__free(text);
+ git_buf_clear(&buf);
git_patch_free(patch);
git_diff_free(diff);
@@ -210,10 +210,10 @@ void test_diff_patch__config_options(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected2, text);
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+ cl_assert_equal_s(expected2, buf.ptr);
- git__free(text);
+ git_buf_clear(&buf);
git_patch_free(patch);
git_diff_free(diff);
@@ -224,10 +224,10 @@ void test_diff_patch__config_options(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected3, text);
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+ cl_assert_equal_s(expected3, buf.ptr);
- git__free(text);
+ git_buf_clear(&buf);
git_patch_free(patch);
git_diff_free(diff);
@@ -238,13 +238,14 @@ void test_diff_patch__config_options(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected4, text);
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+ cl_assert_equal_s(expected4, buf.ptr);
- git__free(text);
+ git_buf_clear(&buf);
git_patch_free(patch);
git_diff_free(diff);
+ git_buf_free(&buf);
git_tree_free(one);
git_config_free(cfg);
}
@@ -465,10 +466,10 @@ static void check_single_patch_stats(
cl_assert_equal_sz(dels, actual_dels);
if (expected != NULL) {
- char *text;
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected, text);
- git__free(text);
+ git_buf buf = GIT_BUF_INIT;
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+ cl_assert_equal_s(expected, buf.ptr);
+ git_buf_free(&buf);
cl_assert_equal_sz(
strlen(expected), git_patch_size(patch, 1, 1, 1));
diff --git a/tests/diff/rename.c b/tests/diff/rename.c
index 93e69f479..ca08d15f3 100644
--- a/tests/diff/rename.c
+++ b/tests/diff/rename.c
@@ -584,7 +584,7 @@ void test_diff_rename__patch(void)
git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
git_patch *patch;
const git_diff_delta *delta;
- char *text;
+ git_buf buf = GIT_BUF_INIT;
const char *expected = "diff --git a/sixserving.txt b/ikeepsix.txt\nindex ad0a8e5..36020db 100644\n--- a/sixserving.txt\n+++ b/ikeepsix.txt\n@@ -1,3 +1,6 @@\n+I Keep Six Honest Serving-Men\n+=============================\n+\n I KEEP six honest serving-men\n (They taught me all I knew);\n Their names are What and Why and When\n@@ -21,4 +24,4 @@ She sends'em abroad on her own affairs,\n One million Hows, two million Wheres,\n And seven million Whys!\n \n- -- Rudyard Kipling\n+ -- Rudyard Kipling\n";
old_tree = resolve_commit_oid_to_tree(g_repo, sha0);
@@ -610,9 +610,9 @@ void test_diff_rename__patch(void)
cl_assert((delta = git_patch_get_delta(patch)) != NULL);
cl_assert_equal_i(GIT_DELTA_COPIED, (int)delta->status);
- cl_git_pass(git_patch_to_str(&text, patch));
- cl_assert_equal_s(expected, text);
- git__free(text);
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+ cl_assert_equal_s(expected, buf.ptr);
+ git_buf_free(&buf);
git_patch_free(patch);
@@ -945,7 +945,7 @@ void test_diff_rename__rejected_match_can_match_others(void)
cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
cl_git_pass(git_reference_symbolic_set_target(
- &selfsimilar, head, "refs/heads/renames_similar"));
+ &selfsimilar, head, "refs/heads/renames_similar", NULL, NULL));
cl_git_pass(git_checkout_head(g_repo, &opts));
cl_git_pass(git_repository_index(&index, g_repo));
@@ -1030,7 +1030,7 @@ void test_diff_rename__rejected_match_can_match_others_two(void)
cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
cl_git_pass(git_reference_symbolic_set_target(
- &selfsimilar, head, "refs/heads/renames_similar_two"));
+ &selfsimilar, head, "refs/heads/renames_similar_two", NULL, NULL));
cl_git_pass(git_checkout_head(g_repo, &opts));
cl_git_pass(git_repository_index(&index, g_repo));
@@ -1088,7 +1088,7 @@ void test_diff_rename__rejected_match_can_match_others_three(void)
cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
cl_git_pass(git_reference_symbolic_set_target(
- &selfsimilar, head, "refs/heads/renames_similar_two"));
+ &selfsimilar, head, "refs/heads/renames_similar_two", NULL, NULL));
cl_git_pass(git_checkout_head(g_repo, &opts));
cl_git_pass(git_repository_index(&index, g_repo));
diff --git a/tests/diff/submodules.c b/tests/diff/submodules.c
index 24545b2c7..da96ba9c5 100644
--- a/tests/diff/submodules.c
+++ b/tests/diff/submodules.c
@@ -13,13 +13,15 @@ void test_diff_submodules__cleanup(void)
{
}
+#define get_buf_ptr(buf) ((buf)->asize ? (buf)->ptr : NULL)
+
static void check_diff_patches_at_line(
git_diff *diff, const char **expected, const char *file, int line)
{
const git_diff_delta *delta;
git_patch *patch = NULL;
size_t d, num_d = git_diff_num_deltas(diff);
- char *patch_text;
+ git_buf buf = GIT_BUF_INIT;
for (d = 0; d < num_d; ++d, git_patch_free(patch)) {
cl_git_pass(git_patch_from_diff(&patch, diff, d));
@@ -33,16 +35,16 @@ static void check_diff_patches_at_line(
if (expected[d] && !strcmp(expected[d], "<SKIP>"))
continue;
if (expected[d] && !strcmp(expected[d], "<END>")) {
- cl_git_pass(git_patch_to_str(&patch_text, patch));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
cl_assert_at_line(!strcmp(expected[d], "<END>"), file, line);
}
- cl_git_pass(git_patch_to_str(&patch_text, patch));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
clar__assert_equal(
file, line, "expected diff did not match actual diff", 1,
- "%s", expected[d], patch_text);
- git__free(patch_text);
+ "%s", expected[d], get_buf_ptr(&buf));
+ git_buf_free(&buf);
}
cl_assert_at_line(expected[d] && !strcmp(expected[d], "<END>"), file, line);
diff --git a/tests/diff/workdir.c b/tests/diff/workdir.c
index 7cc032232..449dc6363 100644
--- a/tests/diff/workdir.c
+++ b/tests/diff/workdir.c
@@ -1375,7 +1375,7 @@ void test_diff_workdir__patience_diff(void)
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff *diff = NULL;
git_patch *patch = NULL;
- char *as_str = NULL;
+ git_buf buf = GIT_BUF_INIT;
const char *expected_normal = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n-how to create\n-a patience diff\n I did not know\n how to create\n+a patience diff\n another problem\n-I did not know\n-how to create\n a minimal diff\n";
const char *expected_patience = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n+I did not know\n how to create\n a patience diff\n-I did not know\n-how to create\n another problem\n-I did not know\n-how to create\n a minimal diff\n";
@@ -1397,10 +1397,10 @@ void test_diff_workdir__patience_diff(void)
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
cl_assert_equal_i(1, git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&as_str, patch));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
- cl_assert_equal_s(expected_normal, as_str);
- git__free(as_str);
+ cl_assert_equal_s(expected_normal, buf.ptr);
+ git_buf_clear(&buf);
git_patch_free(patch);
git_diff_free(diff);
@@ -1409,10 +1409,12 @@ void test_diff_workdir__patience_diff(void)
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
cl_assert_equal_i(1, git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
- cl_git_pass(git_patch_to_str(&as_str, patch));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
- cl_assert_equal_s(expected_patience, as_str);
- git__free(as_str);
+ cl_assert_equal_s(expected_patience, buf.ptr);
+ git_buf_clear(&buf);
+
+ git_buf_free(&buf);
git_patch_free(patch);
git_diff_free(diff);
}
diff --git a/tests/filter/blob.c b/tests/filter/blob.c
index 9600a9779..8dce6470a 100644
--- a/tests/filter/blob.c
+++ b/tests/filter/blob.c
@@ -47,6 +47,38 @@ void test_filter_blob__all_crlf(void)
git_blob_free(blob);
}
+void test_filter_blob__sanitizes(void)
+{
+ git_blob *blob;
+ git_buf buf;
+
+ cl_git_pass(git_revparse_single(
+ (git_object **)&blob, g_repo, "e69de29")); /* zero-byte */
+
+ cl_assert_equal_i(0, git_blob_rawsize(blob));
+ cl_assert_equal_s("", git_blob_rawcontent(blob));
+
+ memset(&buf, 0, sizeof(git_buf));
+ cl_git_pass(git_blob_filtered_content(&buf, blob, "file.bin", 1));
+ cl_assert_equal_sz(0, buf.size);
+ cl_assert_equal_s("", buf.ptr);
+ git_buf_free(&buf);
+
+ memset(&buf, 0, sizeof(git_buf));
+ cl_git_pass(git_blob_filtered_content(&buf, blob, "file.crlf", 1));
+ cl_assert_equal_sz(0, buf.size);
+ cl_assert_equal_s("", buf.ptr);
+ git_buf_free(&buf);
+
+ memset(&buf, 0, sizeof(git_buf));
+ cl_git_pass(git_blob_filtered_content(&buf, blob, "file.lf", 1));
+ cl_assert_equal_sz(0, buf.size);
+ cl_assert_equal_s("", buf.ptr);
+ git_buf_free(&buf);
+
+ git_blob_free(blob);
+}
+
void test_filter_blob__ident(void)
{
git_oid id;
diff --git a/tests/filter/custom.c b/tests/filter/custom.c
index a81885c28..70524010e 100644
--- a/tests/filter/custom.c
+++ b/tests/filter/custom.c
@@ -299,7 +299,7 @@ void test_filter_custom__order_dependency(void)
git_index_free(index);
cl_git_pass(git_blob_lookup(&blob, g_repo,
- & git_index_get_bypath(index, "hero.1.rev-ident", 0)->oid));
+ & git_index_get_bypath(index, "hero.1.rev-ident", 0)->id));
cl_assert_equal_s(
"\n!nuf evaH\n$dI$\ntset a si sihT", git_blob_rawcontent(blob));
cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.1.rev-ident", 0));
@@ -310,7 +310,7 @@ void test_filter_custom__order_dependency(void)
git_blob_free(blob);
cl_git_pass(git_blob_lookup(&blob, g_repo,
- & git_index_get_bypath(index, "hero.2.rev-ident", 0)->oid));
+ & git_index_get_bypath(index, "hero.2.rev-ident", 0)->id));
cl_assert_equal_s(
"\n!yzarC\n$Id$\ntset rehtonA", git_blob_rawcontent(blob));
cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.2.rev-ident", 0));
diff --git a/tests/graph/descendant_of.c b/tests/graph/descendant_of.c
new file mode 100644
index 000000000..ffdd0cfc8
--- /dev/null
+++ b/tests/graph/descendant_of.c
@@ -0,0 +1,47 @@
+#include "clar_libgit2.h"
+
+static git_repository *_repo;
+static git_commit *commit;
+
+void test_graph_descendant_of__initialize(void)
+{
+ git_oid oid;
+
+ cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
+
+ git_oid_fromstr(&oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+ cl_git_pass(git_commit_lookup(&commit, _repo, &oid));
+}
+
+void test_graph_descendant_of__cleanup(void)
+{
+ git_commit_free(commit);
+ commit = NULL;
+
+ git_repository_free(_repo);
+ _repo = NULL;
+}
+
+void test_graph_descendant_of__returns_correct_result(void)
+{
+ git_commit *other;
+
+ cl_assert_equal_i(0, git_graph_descendant_of(_repo, git_commit_id(commit), git_commit_id(commit)));
+
+
+ cl_git_pass(git_commit_nth_gen_ancestor(&other, commit, 1));
+
+ cl_assert_equal_i(1, git_graph_descendant_of(_repo, git_commit_id(commit), git_commit_id(other)));
+ cl_assert_equal_i(0, git_graph_descendant_of(_repo, git_commit_id(other), git_commit_id(commit)));
+
+ git_commit_free(other);
+
+
+ cl_git_pass(git_commit_nth_gen_ancestor(&other, commit, 3));
+
+ cl_assert_equal_i(1, git_graph_descendant_of(_repo, git_commit_id(commit), git_commit_id(other)));
+ cl_assert_equal_i(0, git_graph_descendant_of(_repo, git_commit_id(other), git_commit_id(commit)));
+
+ git_commit_free(other);
+
+}
diff --git a/tests/index/collision.c b/tests/index/collision.c
new file mode 100644
index 000000000..1f002e8d3
--- /dev/null
+++ b/tests/index/collision.c
@@ -0,0 +1,106 @@
+#include "clar_libgit2.h"
+#include "git2/repository.h"
+#include "git2/index.h"
+
+git_repository *repo = NULL;
+
+void test_index_collision__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+ repo = NULL;
+}
+
+void test_index_collision__add(void)
+{
+ git_index *index;
+ git_index_entry entry;
+ git_oid tree_id;
+ git_tree *tree;
+
+ repo = cl_git_sandbox_init("empty_standard_repo");
+ cl_git_pass(git_repository_index(&index, repo));
+
+ memset(&entry, 0, sizeof(entry));
+ entry.ctime.seconds = 12346789;
+ entry.mtime.seconds = 12346789;
+ entry.mode = 0100644;
+ entry.file_size = 0;
+ git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
+
+ entry.path = "a/b";
+ cl_git_pass(git_index_add(index, &entry));
+
+ /* create a tree/blob collision */
+ entry.path = "a/b/c";
+ cl_git_fail(git_index_add(index, &entry));
+
+ cl_git_pass(git_index_write_tree(&tree_id, index));
+ cl_git_pass(git_tree_lookup(&tree, repo, &tree_id));
+
+ git_tree_free(tree);
+ git_index_free(index);
+}
+
+void test_index_collision__add_with_highstage_1(void)
+{
+ git_index *index;
+ git_index_entry entry;
+
+ repo = cl_git_sandbox_init("empty_standard_repo");
+ cl_git_pass(git_repository_index(&index, repo));
+
+ memset(&entry, 0, sizeof(entry));
+ entry.ctime.seconds = 12346789;
+ entry.mtime.seconds = 12346789;
+ entry.mode = 0100644;
+ entry.file_size = 0;
+ git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
+
+ entry.path = "a/b";
+ entry.flags = (2 << GIT_IDXENTRY_STAGESHIFT);
+ cl_git_pass(git_index_add(index, &entry));
+
+ /* create a blob beneath the previous tree entry */
+ entry.path = "a/b/c";
+ entry.flags = 0;
+ cl_git_pass(git_index_add(index, &entry));
+
+ /* create another tree entry above the blob */
+ entry.path = "a/b";
+ entry.flags = (1 << GIT_IDXENTRY_STAGESHIFT);
+ cl_git_pass(git_index_add(index, &entry));
+
+ git_index_free(index);
+}
+
+void test_index_collision__add_with_highstage_2(void)
+{
+ git_index *index;
+ git_index_entry entry;
+
+ repo = cl_git_sandbox_init("empty_standard_repo");
+ cl_git_pass(git_repository_index(&index, repo));
+
+ memset(&entry, 0, sizeof(entry));
+ entry.ctime.seconds = 12346789;
+ entry.mtime.seconds = 12346789;
+ entry.mode = 0100644;
+ entry.file_size = 0;
+ git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
+
+ entry.path = "a/b/c";
+ entry.flags = (1 << GIT_IDXENTRY_STAGESHIFT);
+ cl_git_pass(git_index_add(index, &entry));
+
+ /* create a blob beneath the previous tree entry */
+ entry.path = "a/b/c";
+ entry.flags = (2 << GIT_IDXENTRY_STAGESHIFT);
+ cl_git_pass(git_index_add(index, &entry));
+
+ /* create another tree entry above the blob */
+ entry.path = "a/b";
+ entry.flags = (3 << GIT_IDXENTRY_STAGESHIFT);
+ cl_git_pass(git_index_add(index, &entry));
+
+ git_index_free(index);
+}
diff --git a/tests/index/conflicts.c b/tests/index/conflicts.c
index 6311b3a75..90aaa442d 100644
--- a/tests/index/conflicts.c
+++ b/tests/index/conflicts.c
@@ -47,15 +47,15 @@ void test_index_conflicts__add(void)
ancestor_entry.path = "test-one.txt";
ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID);
+ git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID);
our_entry.path = "test-one.txt";
ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&our_entry.oid, TEST_OUR_OID);
+ git_oid_fromstr(&our_entry.id, TEST_OUR_OID);
their_entry.path = "test-one.txt";
ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&their_entry.oid, TEST_THEIR_OID);
+ git_oid_fromstr(&their_entry.id, TEST_THEIR_OID);
cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry));
@@ -75,15 +75,15 @@ void test_index_conflicts__add_fixes_incorrect_stage(void)
ancestor_entry.path = "test-one.txt";
ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID);
+ git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID);
our_entry.path = "test-one.txt";
ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&our_entry.oid, TEST_OUR_OID);
+ git_oid_fromstr(&our_entry.id, TEST_OUR_OID);
their_entry.path = "test-one.txt";
ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&their_entry.oid, TEST_THEIR_OID);
+ git_oid_fromstr(&their_entry.id, TEST_THEIR_OID);
cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry));
@@ -107,13 +107,13 @@ void test_index_conflicts__get(void)
cl_assert_equal_s("conflicts-one.txt", conflict_entry[0]->path);
git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[0]->id, &oid) == 0);
git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[1]->id, &oid) == 0);
git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[2]->id, &oid) == 0);
cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
&conflict_entry[2], repo_index, "conflicts-two.txt"));
@@ -121,13 +121,13 @@ void test_index_conflicts__get(void)
cl_assert_equal_s("conflicts-two.txt", conflict_entry[0]->path);
git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[0]->id, &oid) == 0);
git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[1]->id, &oid) == 0);
git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[2]->id, &oid) == 0);
}
void test_index_conflicts__iterate(void)
@@ -141,29 +141,29 @@ void test_index_conflicts__iterate(void)
cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator));
git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[0]->id, &oid) == 0);
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);
git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[1]->id, &oid) == 0);
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);
git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[2]->id, &oid) == 0);
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);
cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator));
git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[0]->id, &oid) == 0);
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);
git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[1]->id, &oid) == 0);
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);
git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID);
- cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0);
+ cl_assert(git_oid_cmp(&conflict_entry[2]->id, &oid) == 0);
cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);
cl_assert(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator) == GIT_ITEROVER);
@@ -273,7 +273,7 @@ void test_index_conflicts__partial(void)
ancestor_entry.path = "test-one.txt";
ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID);
+ git_oid_fromstr(&ancestor_entry.id, TEST_ANCESTOR_OID);
cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, NULL, NULL));
cl_assert(git_index_entrycount(repo_index) == 9);
@@ -281,7 +281,7 @@ void test_index_conflicts__partial(void)
cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
&conflict_entry[2], repo_index, "test-one.txt"));
- cl_assert(git_oid_cmp(&ancestor_entry.oid, &conflict_entry[0]->oid) == 0);
+ cl_assert(git_oid_cmp(&ancestor_entry.id, &conflict_entry[0]->id) == 0);
cl_assert(conflict_entry[1] == NULL);
cl_assert(conflict_entry[2] == NULL);
}
diff --git a/tests/index/rename.c b/tests/index/rename.c
index 4deef1332..b6fb61d10 100644
--- a/tests/index/rename.c
+++ b/tests/index/rename.c
@@ -27,7 +27,7 @@ void test_index_rename__single_file(void)
cl_assert(!git_index_find(&position, index, "lame.name.txt"));
entry = git_index_get_byindex(index, position);
- cl_assert(git_oid_cmp(&expected, &entry->oid) == 0);
+ cl_assert(git_oid_cmp(&expected, &entry->id) == 0);
/* This removes the entry from the index, but not from the object database */
cl_git_pass(git_index_remove(index, "lame.name.txt", 0));
@@ -41,7 +41,7 @@ void test_index_rename__single_file(void)
cl_assert(!git_index_find(&position, index, "fancy.name.txt"));
entry = git_index_get_byindex(index, position);
- cl_assert(git_oid_cmp(&expected, &entry->oid) == 0);
+ cl_assert(git_oid_cmp(&expected, &entry->id) == 0);
git_index_free(index);
git_repository_free(repo);
diff --git a/tests/index/tests.c b/tests/index/tests.c
index 5a05bd8a9..bd90bc557 100644
--- a/tests/index/tests.c
+++ b/tests/index/tests.c
@@ -243,11 +243,11 @@ void test_index_tests__add(void)
entry = git_index_get_byindex(index, 0);
/* And the built-in hashing mechanism worked as expected */
- cl_assert(git_oid_cmp(&id1, &entry->oid) == 0);
+ cl_assert(git_oid_cmp(&id1, &entry->id) == 0);
/* Test access by path instead of index */
cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
- cl_assert(git_oid_cmp(&id1, &entry->oid) == 0);
+ cl_assert(git_oid_cmp(&id1, &entry->id) == 0);
git_index_free(index);
git_repository_free(repo);
@@ -283,14 +283,14 @@ void test_index_tests__add_issue_1397(void)
/* Make sure the initial SHA-1 is correct */
cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL);
- cl_assert_(git_oid_cmp(&id1, &entry->oid) == 0, "first oid check");
+ cl_assert_(git_oid_cmp(&id1, &entry->id) == 0, "first oid check");
/* Update the index */
cl_git_pass(git_index_add_bypath(index, "crlf_file.txt"));
/* Check the new SHA-1 */
cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL);
- cl_assert_(git_oid_cmp(&id1, &entry->oid) == 0, "second oid check");
+ cl_assert_(git_oid_cmp(&id1, &entry->id) == 0, "second oid check");
git_index_free(index);
}
diff --git a/tests/merge/merge_helpers.c b/tests/merge/merge_helpers.c
index 5660179a7..8d6ef2dbe 100644
--- a/tests/merge/merge_helpers.c
+++ b/tests/merge/merge_helpers.c
@@ -87,7 +87,7 @@ int merge_branches(git_merge_result **result, git_repository *repo, const char *
head_checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
- cl_git_pass(git_reference_symbolic_create(&head_ref, repo, "HEAD", ours_branch, 1));
+ cl_git_pass(git_reference_symbolic_create(&head_ref, repo, "HEAD", ours_branch, 1, NULL, NULL));
cl_git_pass(git_checkout_head(repo, &head_checkout_opts));
cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch));
@@ -112,7 +112,7 @@ void merge__dump_index_entries(git_vector *index_entries)
index_entry = index_entries->contents[i];
printf("%o ", index_entry->mode);
- printf("%s ", git_oid_allocfmt(&index_entry->oid));
+ printf("%s ", git_oid_allocfmt(&index_entry->id));
printf("%d ", git_index_entry_stage(index_entry));
printf("%s ", index_entry->path);
printf("\n");
@@ -166,7 +166,7 @@ static int index_entry_eq_merge_index_entry(const struct merge_index_entry *expe
test_oid = 0;
if (actual->mode != expected->mode ||
- (test_oid && git_oid_cmp(&actual->oid, &expected_oid) != 0) ||
+ (test_oid && git_oid_cmp(&actual->id, &expected_oid) != 0) ||
git_index_entry_stage(actual) != expected->stage)
return 0;
diff --git a/tests/merge/trees/automerge.c b/tests/merge/trees/automerge.c
index 746ce5068..bd710e6d8 100644
--- a/tests/merge/trees/automerge.c
+++ b/tests/merge/trees/automerge.c
@@ -121,7 +121,7 @@ void test_merge_trees_automerge__automerge(void)
cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL);
cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE));
- cl_git_pass(git_object_lookup((git_object **)&blob, repo, &entry->oid, GIT_OBJ_BLOB));
+ cl_git_pass(git_object_lookup((git_object **)&blob, repo, &entry->id, GIT_OBJ_BLOB));
cl_assert(memcmp(git_blob_rawcontent(blob), AUTOMERGEABLE_MERGED_FILE, (size_t)entry->file_size) == 0);
git_index_free(index);
@@ -149,7 +149,7 @@ void test_merge_trees_automerge__favor_ours(void)
REMOVED_IN_MASTER_REUC_ENTRY,
};
- opts.automerge_flags = GIT_MERGE_AUTOMERGE_FAVOR_OURS;
+ opts.file_favor = GIT_MERGE_FILE_FAVOR_OURS;
cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts));
@@ -180,7 +180,7 @@ void test_merge_trees_automerge__favor_theirs(void)
REMOVED_IN_MASTER_REUC_ENTRY,
};
- opts.automerge_flags = GIT_MERGE_AUTOMERGE_FAVOR_THEIRS;
+ opts.file_favor = GIT_MERGE_FILE_FAVOR_THEIRS;
cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts));
diff --git a/tests/merge/trees/commits.c b/tests/merge/trees/commits.c
index f8f4fbacb..eeb30dae5 100644
--- a/tests/merge/trees/commits.c
+++ b/tests/merge/trees/commits.c
@@ -72,7 +72,7 @@ void test_merge_trees_commits__automerge(void)
cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL);
cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE));
- cl_git_pass(git_object_lookup((git_object **)&blob, repo, &entry->oid, GIT_OBJ_BLOB));
+ cl_git_pass(git_object_lookup((git_object **)&blob, repo, &entry->id, GIT_OBJ_BLOB));
cl_assert(memcmp(git_blob_rawcontent(blob), AUTOMERGEABLE_MERGED_FILE, (size_t)entry->file_size) == 0);
git_index_free(index);
diff --git a/tests/merge/trees/trivial.c b/tests/merge/trees/trivial.c
index bfd5dfed3..377b24742 100644
--- a/tests/merge/trees/trivial.c
+++ b/tests/merge/trees/trivial.c
@@ -25,7 +25,7 @@ void test_merge_trees_trivial__cleanup(void)
}
-static int merge_trivial(git_index **index, const char *ours, const char *theirs, bool automerge)
+static int merge_trivial(git_index **index, const char *ours, const char *theirs)
{
git_commit *our_commit, *their_commit, *ancestor_commit;
git_tree *our_tree, *their_tree, *ancestor_tree;
@@ -33,8 +33,6 @@ static int merge_trivial(git_index **index, const char *ours, const char *theirs
git_buf branch_buf = GIT_BUF_INIT;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT;
- opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE;
-
git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours);
cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr));
cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
@@ -86,7 +84,7 @@ void test_merge_trees_trivial__2alt(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-2alt", "trivial-2alt-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-2alt", "trivial-2alt-branch"));
cl_assert(entry = git_index_get_bypath(result, "new-in-branch.txt", 0));
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -101,7 +99,7 @@ void test_merge_trees_trivial__3alt(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-3alt", "trivial-3alt-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-3alt", "trivial-3alt-branch"));
cl_assert(entry = git_index_get_bypath(result, "new-in-3alt.txt", 0));
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -116,7 +114,7 @@ void test_merge_trees_trivial__4(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-4", "trivial-4-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-4", "trivial-4-branch"));
cl_assert((entry = git_index_get_bypath(result, "new-and-different.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -134,7 +132,7 @@ void test_merge_trees_trivial__5alt_1(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-5alt-1", "trivial-5alt-1-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-5alt-1", "trivial-5alt-1-branch"));
cl_assert(entry = git_index_get_bypath(result, "new-and-same.txt", 0));
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -149,7 +147,7 @@ void test_merge_trees_trivial__5alt_2(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-5alt-2", "trivial-5alt-2-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-5alt-2", "trivial-5alt-2-branch"));
cl_assert(entry = git_index_get_bypath(result, "modified-to-same.txt", 0));
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -163,26 +161,9 @@ void test_merge_trees_trivial__6(void)
{
git_index *result;
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-both.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 1);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-both.txt", 1));
-
- git_index_free(result);
-}
-
-/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */
-void test_merge_trees_trivial__6_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch", 1));
+ cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-both.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 1);
@@ -198,27 +179,9 @@ void test_merge_trees_trivial__8(void)
{
git_index *result;
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-8.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 2);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-8.txt", 1));
- cl_assert(entry = git_index_get_bypath(result, "removed-in-8.txt", 3));
-
- git_index_free(result);
-}
-
-/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */
-void test_merge_trees_trivial__8_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch", 1));
+ cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-8.txt", 0)) == NULL);
@@ -236,25 +199,7 @@ void test_merge_trees_trivial__7(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-7.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 2);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 1));
- cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 3));
-
- git_index_free(result);
-}
-
-/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */
-void test_merge_trees_trivial__7_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-7.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -271,27 +216,9 @@ void test_merge_trees_trivial__10(void)
{
git_index *result;
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 2);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 1));
- cl_assert(entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 2));
-
- git_index_free(result);
-}
-
-/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */
-void test_merge_trees_trivial__10_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch", 1));
+ cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 0)) == NULL);
@@ -309,25 +236,7 @@ void test_merge_trees_trivial__9(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(result) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount(result) == 2);
- cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 1));
- cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 2));
-
- git_index_free(result);
-}
-
-/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */
-void test_merge_trees_trivial__9_automerge(void)
-{
- git_index *result;
- const git_index_entry *entry;
-
- cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch", 1));
+ cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch"));
cl_assert((entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 0);
@@ -346,11 +255,11 @@ void test_merge_trees_trivial__13(void)
const git_index_entry *entry;
git_oid expected_oid;
- cl_git_pass(merge_trivial(&result, "trivial-13", "trivial-13-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-13", "trivial-13-branch"));
cl_assert(entry = git_index_get_bypath(result, "modified-in-13.txt", 0));
cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b"));
- cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0);
+ cl_assert(git_oid_cmp(&entry->id, &expected_oid) == 0);
cl_assert(git_index_reuc_entrycount(result) == 0);
cl_assert(merge_trivial_conflict_entrycount(result) == 0);
@@ -365,11 +274,11 @@ void test_merge_trees_trivial__14(void)
const git_index_entry *entry;
git_oid expected_oid;
- cl_git_pass(merge_trivial(&result, "trivial-14", "trivial-14-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-14", "trivial-14-branch"));
cl_assert(entry = git_index_get_bypath(result, "modified-in-14-branch.txt", 0));
cl_git_pass(git_oid_fromstr(&expected_oid, "26153a3ff3649b6c2bb652d3f06878c6e0a172f9"));
- cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0);
+ cl_assert(git_oid_cmp(&entry->id, &expected_oid) == 0);
cl_assert(git_index_reuc_entrycount(result) == 0);
cl_assert(merge_trivial_conflict_entrycount(result) == 0);
@@ -383,7 +292,7 @@ void test_merge_trees_trivial__11(void)
git_index *result;
const git_index_entry *entry;
- cl_git_pass(merge_trivial(&result, "trivial-11", "trivial-11-branch", 0));
+ cl_git_pass(merge_trivial(&result, "trivial-11", "trivial-11-branch"));
cl_assert((entry = git_index_get_bypath(result, "modified-in-both.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(result) == 0);
diff --git a/tests/merge/workdir/dirty.c b/tests/merge/workdir/dirty.c
new file mode 100644
index 000000000..625d3d01a
--- /dev/null
+++ b/tests/merge/workdir/dirty.c
@@ -0,0 +1,322 @@
+#include "clar_libgit2.h"
+#include "git2/merge.h"
+#include "buffer.h"
+#include "merge.h"
+#include "../merge_helpers.h"
+#include "posix.h"
+
+#define TEST_REPO_PATH "merge-resolve"
+#define MERGE_BRANCH_OID "7cb63eed597130ba4abb87b3e544b85021905520"
+
+#define AUTOMERGEABLE_MERGED_FILE \
+ "this file is changed in master\n" \
+ "this file is automergeable\n" \
+ "this file is automergeable\n" \
+ "this file is automergeable\n" \
+ "this file is automergeable\n" \
+ "this file is automergeable\n" \
+ "this file is automergeable\n" \
+ "this file is automergeable\n" \
+ "this file is changed in branch\n"
+
+#define CHANGED_IN_BRANCH_FILE \
+ "changed in branch\n"
+
+static git_repository *repo;
+static git_index *repo_index;
+
+static char *unaffected[][4] = {
+ { "added-in-master.txt", NULL },
+ { "changed-in-master.txt", NULL },
+ { "unchanged.txt", NULL },
+ { "added-in-master.txt", "changed-in-master.txt", NULL },
+ { "added-in-master.txt", "unchanged.txt", NULL },
+ { "changed-in-master.txt", "unchanged.txt", NULL },
+ { "added-in-master.txt", "changed-in-master.txt", "unchanged.txt", NULL },
+ { "new_file.txt", NULL },
+ { "new_file.txt", "unchanged.txt", NULL },
+ { NULL },
+};
+
+static char *affected[][5] = {
+ { "automergeable.txt", NULL },
+ { "changed-in-branch.txt", NULL },
+ { "conflicting.txt", NULL },
+ { "removed-in-branch.txt", NULL },
+ { "automergeable.txt", "changed-in-branch.txt", NULL },
+ { "automergeable.txt", "conflicting.txt", NULL },
+ { "automergeable.txt", "removed-in-branch.txt", NULL },
+ { "changed-in-branch.txt", "conflicting.txt", NULL },
+ { "changed-in-branch.txt", "removed-in-branch.txt", NULL },
+ { "conflicting.txt", "removed-in-branch.txt", NULL },
+ { "automergeable.txt", "changed-in-branch.txt", "conflicting.txt", NULL },
+ { "automergeable.txt", "changed-in-branch.txt", "removed-in-branch.txt", NULL },
+ { "automergeable.txt", "conflicting.txt", "removed-in-branch.txt", NULL },
+ { "changed-in-branch.txt", "conflicting.txt", "removed-in-branch.txt", NULL },
+ { "automergeable.txt", "changed-in-branch.txt", "conflicting.txt", "removed-in-branch.txt", NULL },
+ { NULL },
+};
+
+static char *result_contents[4][6] = {
+ { "automergeable.txt", AUTOMERGEABLE_MERGED_FILE, NULL, NULL },
+ { "changed-in-branch.txt", CHANGED_IN_BRANCH_FILE, NULL, NULL },
+ { "automergeable.txt", AUTOMERGEABLE_MERGED_FILE, "changed-in-branch.txt", CHANGED_IN_BRANCH_FILE, NULL, NULL },
+ { NULL }
+};
+
+void test_merge_workdir_dirty__initialize(void)
+{
+ repo = cl_git_sandbox_init(TEST_REPO_PATH);
+ git_repository_index(&repo_index, repo);
+}
+
+void test_merge_workdir_dirty__cleanup(void)
+{
+ git_index_free(repo_index);
+ cl_git_sandbox_cleanup();
+}
+
+static void set_core_autocrlf_to(git_repository *repo, bool value)
+{
+ git_config *cfg;
+
+ cl_git_pass(git_repository_config(&cfg, repo));
+ cl_git_pass(git_config_set_bool(cfg, "core.autocrlf", value));
+
+ git_config_free(cfg);
+}
+
+static int merge_branch(git_merge_result **result, int merge_file_favor, int checkout_strategy)
+{
+ git_oid their_oids[1];
+ git_merge_head *their_heads[1];
+ git_merge_opts opts = GIT_MERGE_OPTS_INIT;
+ int error;
+
+ cl_git_pass(git_oid_fromstr(&their_oids[0], MERGE_BRANCH_OID));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
+
+ opts.merge_tree_opts.file_favor = merge_file_favor;
+ opts.checkout_opts.checkout_strategy = checkout_strategy;
+ error = git_merge(result, repo, (const git_merge_head **)their_heads, 1, &opts);
+
+ git_merge_head_free(their_heads[0]);
+
+ return error;
+}
+
+static void write_files(char *files[])
+{
+ char *filename;
+ git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT;
+ size_t i;
+
+ for (i = 0, filename = files[i]; filename; filename = files[++i]) {
+ git_buf_clear(&path);
+ git_buf_clear(&content);
+
+ git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename);
+ git_buf_printf(&content, "This is a dirty file in the working directory!\n\n"
+ "It will not be staged! Its filename is %s.\n", filename);
+
+ cl_git_mkfile(path.ptr, content.ptr);
+ }
+
+ git_buf_free(&path);
+ git_buf_free(&content);
+}
+
+static void hack_index(char *files[])
+{
+ char *filename;
+ struct stat statbuf;
+ git_buf path = GIT_BUF_INIT;
+ git_index_entry *entry;
+ size_t i;
+
+ /* Update the index to suggest that checkout placed these files on
+ * disk, keeping the object id but updating the cache, which will
+ * emulate a Git implementation's different filter.
+ */
+ for (i = 0, filename = files[i]; filename; filename = files[++i]) {
+ git_buf_clear(&path);
+
+ cl_assert(entry = (git_index_entry *)
+ git_index_get_bypath(repo_index, filename, 0));
+
+ cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename));
+ cl_git_pass(p_stat(path.ptr, &statbuf));
+
+ entry->ctime.seconds = (git_time_t)statbuf.st_ctime;
+ entry->ctime.nanoseconds = 0;
+ entry->mtime.seconds = (git_time_t)statbuf.st_mtime;
+ entry->mtime.nanoseconds = 0;
+ entry->dev = statbuf.st_dev;
+ entry->ino = statbuf.st_ino;
+ entry->uid = statbuf.st_uid;
+ entry->gid = statbuf.st_gid;
+ entry->file_size = statbuf.st_size;
+ }
+
+ git_buf_free(&path);
+}
+
+static void stage_random_files(char *files[])
+{
+ char *filename;
+ size_t i;
+
+ write_files(files);
+
+ for (i = 0, filename = files[i]; filename; filename = files[++i])
+ cl_git_pass(git_index_add_bypath(repo_index, filename));
+}
+
+static void stage_content(char *content[])
+{
+ git_reference *head;
+ git_object *head_object;
+ git_merge_result *result = NULL;
+ git_buf path = GIT_BUF_INIT;
+ char *filename, *text;
+ size_t i;
+
+ cl_git_pass(git_repository_head(&head, repo));
+ cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
+ cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD));
+
+ for (i = 0, filename = content[i], text = content[++i];
+ filename && text;
+ filename = content[++i], text = content[++i]) {
+
+ git_buf_clear(&path);
+
+ cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename));
+
+ cl_git_mkfile(path.ptr, text);
+ cl_git_pass(git_index_add_bypath(repo_index, filename));
+ }
+
+ git_merge_result_free(result);
+ git_object_free(head_object);
+ git_reference_free(head);
+ git_buf_free(&path);
+}
+
+static int merge_dirty_files(char *dirty_files[])
+{
+ git_reference *head;
+ git_object *head_object;
+ git_merge_result *result = NULL;
+ int error;
+
+ cl_git_pass(git_repository_head(&head, repo));
+ cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
+ cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD));
+
+ write_files(dirty_files);
+
+ error = merge_branch(&result, 0, 0);
+
+ git_merge_result_free(result);
+ git_object_free(head_object);
+ git_reference_free(head);
+
+ return error;
+}
+
+static int merge_differently_filtered_files(char *files[])
+{
+ git_reference *head;
+ git_object *head_object;
+ git_merge_result *result = NULL;
+ int error;
+
+ cl_git_pass(git_repository_head(&head, repo));
+ cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
+ cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD));
+
+ write_files(files);
+ hack_index(files);
+
+ cl_git_pass(git_index_write(repo_index));
+
+ error = merge_branch(&result, 0, 0);
+
+ git_merge_result_free(result);
+ git_object_free(head_object);
+ git_reference_free(head);
+
+ return error;
+}
+
+static int merge_staged_files(char *staged_files[])
+{
+ git_merge_result *result = NULL;
+ int error;
+
+ stage_random_files(staged_files);
+
+ error = merge_branch(&result, 0, 0);
+
+ git_merge_result_free(result);
+
+ return error;
+}
+
+void test_merge_workdir_dirty__unaffected_dirty_files_allowed(void)
+{
+ char **files;
+ size_t i;
+
+ for (i = 0, files = unaffected[i]; files[0]; files = unaffected[++i])
+ cl_git_pass(merge_dirty_files(files));
+}
+
+void test_merge_workdir_dirty__affected_dirty_files_disallowed(void)
+{
+ char **files;
+ size_t i;
+
+ for (i = 0, files = affected[i]; files[0]; files = affected[++i])
+ cl_git_fail(merge_dirty_files(files));
+}
+
+void test_merge_workdir_dirty__staged_files_in_index_disallowed(void)
+{
+ char **files;
+ size_t i;
+
+ for (i = 0, files = unaffected[i]; files[0]; files = unaffected[++i])
+ cl_git_fail(merge_staged_files(files));
+
+ for (i = 0, files = affected[i]; files[0]; files = affected[++i])
+ cl_git_fail(merge_staged_files(files));
+}
+
+void test_merge_workdir_dirty__identical_staged_files_allowed(void)
+{
+ git_merge_result *result;
+ char **content;
+ size_t i;
+
+ set_core_autocrlf_to(repo, false);
+
+ for (i = 0, content = result_contents[i]; content[0]; content = result_contents[++i]) {
+ stage_content(content);
+
+ git_index_write(repo_index);
+ cl_git_pass(merge_branch(&result, 0, 0));
+
+ git_merge_result_free(result);
+ }
+}
+
+void test_merge_workdir_dirty__honors_cache(void)
+{
+ char **files;
+ size_t i;
+
+ for (i = 0, files = affected[i]; files[0]; files = affected[++i])
+ cl_git_pass(merge_differently_filtered_files(files));
+}
diff --git a/tests/merge/workdir/fastforward.c b/tests/merge/workdir/fastforward.c
index 861f38354..d6b31481f 100644
--- a/tests/merge/workdir/fastforward.c
+++ b/tests/merge/workdir/fastforward.c
@@ -13,10 +13,10 @@ static git_index *repo_index;
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
#define THEIRS_FASTFORWARD_BRANCH "ff_branch"
-#define THEIRS_FASTFORWARD_OID "fd89f8cffb663ac89095a0f9764902e93ceaca6a"
+#define THEIRS_FASTFORWARD_ID "fd89f8cffb663ac89095a0f9764902e93ceaca6a"
#define THEIRS_NOFASTFORWARD_BRANCH "branch"
-#define THEIRS_NOFASTFORWARD_OID "7cb63eed597130ba4abb87b3e544b85021905520"
+#define THEIRS_NOFASTFORWARD_ID "7cb63eed597130ba4abb87b3e544b85021905520"
// Fixture setup and teardown
@@ -57,11 +57,11 @@ void test_merge_workdir_fastforward__fastforward(void)
git_merge_result *result;
git_oid expected, ff_oid;
- cl_git_pass(git_oid_fromstr(&expected, THEIRS_FASTFORWARD_OID));
+ cl_git_pass(git_oid_fromstr(&expected, THEIRS_FASTFORWARD_ID));
cl_assert(result = merge_fastforward_branch(0));
cl_assert(git_merge_result_is_fastforward(result));
- cl_git_pass(git_merge_result_fastforward_oid(&ff_oid, result));
+ cl_git_pass(git_merge_result_fastforward_id(&ff_oid, result));
cl_assert(git_oid_cmp(&ff_oid, &expected) == 0);
git_merge_result_free(result);
@@ -136,7 +136,7 @@ void test_merge_workdir_fastforward__uptodate_merging_prev_commit(void)
git_merge_result *result;
cl_git_pass(git_oid_fromstr(&their_oid, "c607fc30883e335def28cd686b51f6cfa02b06ec"));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oid));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, NULL));
diff --git a/tests/merge/workdir/setup.c b/tests/merge/workdir/setup.c
index 870d55ef2..05f994ecd 100644
--- a/tests/merge/workdir/setup.c
+++ b/tests/merge/workdir/setup.c
@@ -79,7 +79,7 @@ void test_merge_workdir_setup__one_branch(void)
git_merge_head *our_head, *their_heads[1];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -105,7 +105,7 @@ void test_merge_workdir_setup__no_fastforward(void)
git_merge_head *our_head, *their_heads[1];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -131,10 +131,10 @@ void test_merge_workdir_setup__one_oid(void)
git_merge_head *our_head, *their_heads[1];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid));
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0));
@@ -156,7 +156,7 @@ void test_merge_workdir_setup__two_branches(void)
git_merge_head *our_head, *their_heads[2];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -189,7 +189,7 @@ void test_merge_workdir_setup__three_branches(void)
git_merge_head *our_head, *their_heads[3];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -227,16 +227,16 @@ void test_merge_workdir_setup__three_oids(void)
git_merge_head *our_head, *their_heads[3];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid));
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[1], repo, &octo2_oid));
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[2], repo, &octo3_oid));
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0));
@@ -260,13 +260,13 @@ void test_merge_workdir_setup__branches_and_oids_1(void)
git_merge_head *our_head, *their_heads[2];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[1], repo, &octo2_oid));
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0));
@@ -293,19 +293,19 @@ void test_merge_workdir_setup__branches_and_oids_2(void)
git_merge_head *our_head, *their_heads[4];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[1], repo, &octo2_oid));
cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref));
cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[3], repo, &octo4_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[3], repo, &octo4_oid));
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0));
@@ -335,16 +335,16 @@ void test_merge_workdir_setup__branches_and_oids_3(void)
git_merge_head *our_head, *their_heads[4];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid));
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[2], repo, &octo3_oid));
cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref));
@@ -378,16 +378,16 @@ void test_merge_workdir_setup__branches_and_oids_4(void)
git_merge_head *our_head, *their_heads[5];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid));
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[2], repo, &octo3_oid));
cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref));
@@ -424,7 +424,7 @@ void test_merge_workdir_setup__three_same_branches(void)
git_merge_head *our_head, *their_heads[3];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_1_ref));
@@ -462,16 +462,16 @@ void test_merge_workdir_setup__three_same_oids(void)
git_merge_head *our_head, *their_heads[3];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_1_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_1_oid));
cl_git_pass(git_oid_fromstr(&octo1_2_oid, OCTO1_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo1_2_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[1], repo, &octo1_2_oid));
cl_git_pass(git_oid_fromstr(&octo1_3_oid, OCTO1_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo1_3_oid));
+ cl_git_pass(git_merge_head_from_id(&their_heads[2], repo, &octo1_3_oid));
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0));
@@ -539,7 +539,7 @@ void test_merge_workdir_setup__remote_tracking_one_branch(void)
cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID));
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -569,7 +569,7 @@ void test_merge_workdir_setup__remote_tracking_two_branches(void)
cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID));
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -606,7 +606,7 @@ void test_merge_workdir_setup__remote_tracking_three_branches(void)
cl_git_pass(create_remote_tracking_branch(OCTO3_BRANCH, OCTO3_OID));
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -645,7 +645,7 @@ void test_merge_workdir_setup__normal_branch_and_remote_tracking_branch(void)
cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID));
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -679,7 +679,7 @@ void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void)
cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID));
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -716,7 +716,7 @@ void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branche
cl_git_pass(create_remote_tracking_branch(OCTO4_BRANCH, OCTO4_OID));
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
@@ -757,7 +757,7 @@ void test_merge_workdir_setup__pull_one(void)
git_merge_head *our_head, *their_heads[1];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID));
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_1_oid));
@@ -782,7 +782,7 @@ void test_merge_workdir_setup__pull_two(void)
git_merge_head *our_head, *their_heads[2];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid));
@@ -812,7 +812,7 @@ void test_merge_workdir_setup__pull_three(void)
git_merge_head *our_head, *their_heads[3];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid));
@@ -845,7 +845,7 @@ void test_merge_workdir_setup__three_remotes(void)
git_merge_head *our_head, *their_heads[3];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid));
@@ -879,7 +879,7 @@ void test_merge_workdir_setup__two_remotes(void)
git_merge_head *our_head, *their_heads[4];
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid));
@@ -1002,7 +1002,7 @@ void test_merge_workdir_setup__retained_after_success(void)
opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD;
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
@@ -1033,7 +1033,7 @@ void test_merge_workdir_setup__removed_after_failure(void)
opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD;
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
- cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
+ cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
diff --git a/tests/merge/workdir/simple.c b/tests/merge/workdir/simple.c
index 4a3b86ee4..4ff761cf8 100644
--- a/tests/merge/workdir/simple.c
+++ b/tests/merge/workdir/simple.c
@@ -93,13 +93,26 @@ static git_index *repo_index;
"this file is automergeable\r\n" \
"this file is changed in branch\r\n"
+#define CONFLICTING_MERGE_FILE \
+ "<<<<<<< HEAD\n" \
+ "this file is changed in master and branch\n" \
+ "=======\n" \
+ "this file is changed in branch and master\n" \
+ ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n"
+
#define CONFLICTING_DIFF3_FILE \
"<<<<<<< HEAD\n" \
"this file is changed in master and branch\n" \
+ "||||||| initial\n" \
+ "this file is a conflict\n" \
"=======\n" \
"this file is changed in branch and master\n" \
">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n"
+#define CONFLICTING_UNION_FILE \
+ "this file is changed in master and branch\n" \
+ "this file is changed in branch and master\n"
+
// Fixture setup and teardown
void test_merge_workdir_simple__initialize(void)
{
@@ -113,7 +126,7 @@ void test_merge_workdir_simple__cleanup(void)
cl_git_sandbox_cleanup();
}
-static git_merge_result *merge_simple_branch(int automerge_flags, int checkout_strategy)
+static git_merge_result *merge_simple_branch(int merge_file_favor, int checkout_strategy)
{
git_oid their_oids[1];
git_merge_head *their_heads[1];
@@ -121,9 +134,9 @@ static git_merge_result *merge_simple_branch(int automerge_flags, int checkout_s
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_SIMPLE_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0]));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
- opts.merge_tree_opts.automerge_flags = automerge_flags;
+ opts.merge_tree_opts.file_favor = merge_file_favor;
opts.checkout_opts.checkout_strategy = checkout_strategy;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts));
@@ -244,6 +257,44 @@ void test_merge_workdir_simple__automerge_crlf(void)
#endif /* GIT_WIN32 */
}
+void test_merge_workdir_simple__mergefile(void)
+{
+ git_merge_result *result;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ ADDED_IN_MASTER_INDEX_ENTRY,
+ AUTOMERGEABLE_INDEX_ENTRY,
+ CHANGED_IN_BRANCH_INDEX_ENTRY,
+ CHANGED_IN_MASTER_INDEX_ENTRY,
+
+ { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" },
+ { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" },
+ { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" },
+
+ UNCHANGED_INDEX_ENTRY,
+ };
+
+ struct merge_reuc_entry merge_reuc_entries[] = {
+ AUTOMERGEABLE_REUC_ENTRY,
+ REMOVED_IN_BRANCH_REUC_ENTRY,
+ REMOVED_IN_MASTER_REUC_ENTRY
+ };
+
+ cl_assert(result = merge_simple_branch(0, 0));
+ cl_assert(!git_merge_result_is_fastforward(result));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+ TEST_REPO_PATH "/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_MERGE_FILE) == 0);
+ git_buf_free(&conflicting_buf);
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
+ cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
+
+ git_merge_result_free(result);
+}
+
void test_merge_workdir_simple__diff3(void)
{
git_merge_result *result;
@@ -268,6 +319,87 @@ void test_merge_workdir_simple__diff3(void)
REMOVED_IN_MASTER_REUC_ENTRY
};
+ cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_DIFF3));
+ cl_assert(!git_merge_result_is_fastforward(result));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+ TEST_REPO_PATH "/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_DIFF3_FILE) == 0);
+ git_buf_free(&conflicting_buf);
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
+ cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
+
+ git_merge_result_free(result);
+}
+
+void test_merge_workdir_simple__union(void)
+{
+ git_merge_result *result;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ ADDED_IN_MASTER_INDEX_ENTRY,
+ AUTOMERGEABLE_INDEX_ENTRY,
+ CHANGED_IN_BRANCH_INDEX_ENTRY,
+ CHANGED_IN_MASTER_INDEX_ENTRY,
+
+ { 0100644, "72cdb057b340205164478565e91eb71647e66891", 0, "conflicting.txt" },
+
+ UNCHANGED_INDEX_ENTRY,
+ };
+
+ struct merge_reuc_entry merge_reuc_entries[] = {
+ AUTOMERGEABLE_REUC_ENTRY,
+ CONFLICTING_REUC_ENTRY,
+ REMOVED_IN_BRANCH_REUC_ENTRY,
+ REMOVED_IN_MASTER_REUC_ENTRY
+ };
+
+ set_core_autocrlf_to(repo, false);
+
+ cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_UNION, 0));
+ cl_assert(!git_merge_result_is_fastforward(result));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+ TEST_REPO_PATH "/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_UNION_FILE) == 0);
+ git_buf_free(&conflicting_buf);
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
+ cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4));
+
+ git_merge_result_free(result);
+}
+
+void test_merge_workdir_simple__diff3_from_config(void)
+{
+ git_merge_result *result;
+ git_config *config;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ ADDED_IN_MASTER_INDEX_ENTRY,
+ AUTOMERGEABLE_INDEX_ENTRY,
+ CHANGED_IN_BRANCH_INDEX_ENTRY,
+ CHANGED_IN_MASTER_INDEX_ENTRY,
+
+ { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" },
+ { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" },
+ { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" },
+
+ UNCHANGED_INDEX_ENTRY,
+ };
+
+ struct merge_reuc_entry merge_reuc_entries[] = {
+ AUTOMERGEABLE_REUC_ENTRY,
+ REMOVED_IN_BRANCH_REUC_ENTRY,
+ REMOVED_IN_MASTER_REUC_ENTRY
+ };
+
+ cl_git_pass(git_repository_config(&config, repo));
+ cl_git_pass(git_config_set_string(config, "merge.conflictstyle", "diff3"));
+
cl_assert(result = merge_simple_branch(0, 0));
cl_assert(!git_merge_result_is_fastforward(result));
@@ -280,6 +412,50 @@ void test_merge_workdir_simple__diff3(void)
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
git_merge_result_free(result);
+ git_config_free(config);
+}
+
+void test_merge_workdir_simple__merge_overrides_config(void)
+{
+ git_merge_result *result;
+ git_config *config;
+ git_buf conflicting_buf = GIT_BUF_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ ADDED_IN_MASTER_INDEX_ENTRY,
+ AUTOMERGEABLE_INDEX_ENTRY,
+ CHANGED_IN_BRANCH_INDEX_ENTRY,
+ CHANGED_IN_MASTER_INDEX_ENTRY,
+
+ { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" },
+ { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" },
+ { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" },
+
+ UNCHANGED_INDEX_ENTRY,
+ };
+
+ struct merge_reuc_entry merge_reuc_entries[] = {
+ AUTOMERGEABLE_REUC_ENTRY,
+ REMOVED_IN_BRANCH_REUC_ENTRY,
+ REMOVED_IN_MASTER_REUC_ENTRY
+ };
+
+ cl_git_pass(git_repository_config(&config, repo));
+ cl_git_pass(git_config_set_string(config, "merge.conflictstyle", "diff3"));
+
+ cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_MERGE));
+ cl_assert(!git_merge_result_is_fastforward(result));
+
+ cl_git_pass(git_futils_readbuffer(&conflicting_buf,
+ TEST_REPO_PATH "/conflicting.txt"));
+ cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_MERGE_FILE) == 0);
+ git_buf_free(&conflicting_buf);
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
+ cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
+
+ git_merge_result_free(result);
+ git_config_free(config);
}
void test_merge_workdir_simple__checkout_ours(void)
@@ -336,7 +512,7 @@ void test_merge_workdir_simple__favor_ours(void)
REMOVED_IN_MASTER_REUC_ENTRY,
};
- cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_OURS, 0));
+ cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_OURS, 0));
cl_assert(!git_merge_result_is_fastforward(result));
cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
@@ -365,7 +541,7 @@ void test_merge_workdir_simple__favor_theirs(void)
REMOVED_IN_MASTER_REUC_ENTRY,
};
- cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_THEIRS, 0));
+ cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_THEIRS, 0));
cl_assert(!git_merge_result_is_fastforward(result));
cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
@@ -406,15 +582,15 @@ void test_merge_workdir_simple__directory_file(void)
{ 0100644, "f5504f36e6f4eb797a56fc5bac6c6c7f32969bf2", 3, "file-5/new" },
};
- cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_DIR OURS_DIRECTORY_FILE, 1));
+ cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_DIR OURS_DIRECTORY_FILE, 1, NULL, NULL));
cl_git_pass(git_reference_name_to_id(&head_commit_id, repo, GIT_HEAD_FILE));
cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_id));
cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD));
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_DIRECTORY_FILE));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0]));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
- opts.merge_tree_opts.automerge_flags = 0;
+ opts.merge_tree_opts.file_favor = 0;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts));
cl_assert(merge_test_index(repo_index, merge_index_entries, 20));
@@ -445,9 +621,9 @@ void test_merge_workdir_simple__unrelated(void)
};
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_PARENT));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0]));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
- opts.merge_tree_opts.automerge_flags = 0;
+ opts.merge_tree_opts.file_favor = 0;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts));
cl_assert(merge_test_index(repo_index, merge_index_entries, 9));
@@ -478,9 +654,9 @@ void test_merge_workdir_simple__unrelated_with_conflicts(void)
};
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_OID));
- cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0]));
+ cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
- opts.merge_tree_opts.automerge_flags = 0;
+ opts.merge_tree_opts.file_favor = 0;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts));
cl_assert(merge_test_index(repo_index, merge_index_entries, 11));
@@ -489,3 +665,40 @@ void test_merge_workdir_simple__unrelated_with_conflicts(void)
git_merge_result_free(result);
}
+void test_merge_workdir_simple__binary(void)
+{
+ git_oid our_oid, their_oid, our_file_oid;
+ git_commit *our_commit;
+ git_merge_head *their_head;
+ git_merge_result *result;
+ const git_index_entry *binary_entry;
+ git_merge_opts opts = GIT_MERGE_OPTS_INIT;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "1c51d885170f57a0c4e8c69ff6363d91a5b51f85", 1, "binary" },
+ { 0100644, "23ed141a6ae1e798b2f721afedbe947c119111ba", 2, "binary" },
+ { 0100644, "836b8b82b26cab22eaaed8820877c76d6c8bca19", 3, "binary" },
+ };
+
+ cl_git_pass(git_oid_fromstr(&our_oid, "cc338e4710c9b257106b8d16d82f86458d5beaf1"));
+ cl_git_pass(git_oid_fromstr(&their_oid, "ad01aebfdf2ac13145efafe3f9fcf798882f1730"));
+
+ cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
+ cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD));
+
+ cl_git_pass(git_merge_head_from_id(&their_head, repo, &their_oid));
+
+ cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
+
+ cl_git_pass(git_index_add_bypath(repo_index, "binary"));
+ cl_assert((binary_entry = git_index_get_bypath(repo_index, "binary", 0)) != NULL);
+
+ cl_git_pass(git_oid_fromstr(&our_file_oid, "23ed141a6ae1e798b2f721afedbe947c119111ba"));
+ cl_assert(git_oid_cmp(&binary_entry->id, &our_file_oid) == 0);
+
+ git_merge_head_free(their_head);
+ git_merge_result_free(result);
+ git_commit_free(our_commit);
+}
diff --git a/tests/merge/workdir/submodules.c b/tests/merge/workdir/submodules.c
new file mode 100644
index 000000000..f01faac43
--- /dev/null
+++ b/tests/merge/workdir/submodules.c
@@ -0,0 +1,101 @@
+#include "clar_libgit2.h"
+#include "git2/repository.h"
+#include "git2/merge.h"
+#include "buffer.h"
+#include "merge.h"
+#include "../merge_helpers.h"
+
+static git_repository *repo;
+
+#define TEST_REPO_PATH "merge-resolve"
+
+#define SUBMODULE_MAIN_BRANCH "submodules"
+#define SUBMODULE_OTHER_BRANCH "submodules-branch"
+#define SUBMODULE_OTHER2_BRANCH "submodules-branch2"
+
+#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
+
+// Fixture setup and teardown
+void test_merge_workdir_submodules__initialize(void)
+{
+ repo = cl_git_sandbox_init(TEST_REPO_PATH);
+}
+
+void test_merge_workdir_submodules__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+void test_merge_workdir_submodules__automerge(void)
+{
+ git_reference *our_ref, *their_ref;
+ git_commit *our_commit;
+ git_merge_head *their_head;
+ git_merge_result *result;
+ git_merge_opts opts = GIT_MERGE_OPTS_INIT;
+ git_index *index;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "caff6b7d44973f53e3e0cf31d0d695188b19aec6", 0, ".gitmodules" },
+ { 0100644, "950a663a6a7b2609eed1ed1ba9f41eb1a3192a9f", 0, "file1.txt" },
+ { 0100644, "343e660b9cb4bee5f407c2e33fcb9df24d9407a4", 0, "file2.txt" },
+ { 0160000, "d3d806a4bef96889117fd7ebac0e3cb5ec152932", 1, "submodule" },
+ { 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 2, "submodule" },
+ { 0160000, "ae39c77c70cb6bad18bb471912460c4e1ba0f586", 3, "submodule" },
+ };
+
+ cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH));
+ cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref)));
+ cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD));
+
+ cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER_BRANCH));
+ cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
+
+ cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts));
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_assert(merge_test_index(index, merge_index_entries, 6));
+
+ git_index_free(index);
+ git_merge_result_free(result);
+ git_merge_head_free(their_head);
+ git_commit_free(our_commit);
+ git_reference_free(their_ref);
+ git_reference_free(our_ref);
+}
+
+void test_merge_workdir_submodules__take_changed(void)
+{
+ git_reference *our_ref, *their_ref;
+ git_commit *our_commit;
+ git_merge_head *their_head;
+ git_merge_result *result;
+ git_merge_opts opts = GIT_MERGE_OPTS_INIT;
+ git_index *index;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "caff6b7d44973f53e3e0cf31d0d695188b19aec6", 0, ".gitmodules" },
+ { 0100644, "b438ff23300b2e0f80b84a6f30140dfa91e71423", 0, "file1.txt" },
+ { 0100644, "f27fbafdfa6693f8f7a5128506fe3e338dbfcad2", 0, "file2.txt" },
+ { 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 0, "submodule" },
+ };
+
+ cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH));
+ cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref)));
+ cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD));
+
+ cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER2_BRANCH));
+ cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
+
+ cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts));
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_assert(merge_test_index(index, merge_index_entries, 4));
+
+ git_index_free(index);
+ git_merge_result_free(result);
+ git_merge_head_free(their_head);
+ git_commit_free(our_commit);
+ git_reference_free(their_ref);
+ git_reference_free(our_ref);
+}
diff --git a/tests/merge/workdir/trivial.c b/tests/merge/workdir/trivial.c
index 9f9566243..a6bbbf095 100644
--- a/tests/merge/workdir/trivial.c
+++ b/tests/merge/workdir/trivial.c
@@ -28,7 +28,7 @@ void test_merge_workdir_trivial__cleanup(void)
}
-static int merge_trivial(const char *ours, const char *theirs, bool automerge)
+static int merge_trivial(const char *ours, const char *theirs)
{
git_buf branch_buf = GIT_BUF_INIT;
git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT;
@@ -39,10 +39,8 @@ static int merge_trivial(const char *ours, const char *theirs, bool automerge)
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
- opts.merge_tree_opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE;
-
git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours);
- cl_git_pass(git_reference_symbolic_create(&our_ref, repo, "HEAD", branch_buf.ptr, 1));
+ cl_git_pass(git_reference_symbolic_create(&our_ref, repo, "HEAD", branch_buf.ptr, 1, NULL, NULL));
cl_git_pass(git_checkout_head(repo, &checkout_opts));
@@ -83,7 +81,7 @@ void test_merge_workdir_trivial__2alt(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-2alt", "trivial-2alt-branch", 0));
+ cl_git_pass(merge_trivial("trivial-2alt", "trivial-2alt-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "new-in-branch.txt", 0));
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -95,7 +93,7 @@ void test_merge_workdir_trivial__3alt(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-3alt", "trivial-3alt-branch", 0));
+ cl_git_pass(merge_trivial("trivial-3alt", "trivial-3alt-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "new-in-3alt.txt", 0));
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -107,7 +105,7 @@ void test_merge_workdir_trivial__4(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-4", "trivial-4-branch", 0));
+ cl_git_pass(merge_trivial("trivial-4", "trivial-4-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "new-and-different.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -122,7 +120,7 @@ void test_merge_workdir_trivial__5alt_1(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-5alt-1", "trivial-5alt-1-branch", 0));
+ cl_git_pass(merge_trivial("trivial-5alt-1", "trivial-5alt-1-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "new-and-same.txt", 0));
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -134,7 +132,7 @@ void test_merge_workdir_trivial__5alt_2(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-5alt-2", "trivial-5alt-2-branch", 0));
+ cl_git_pass(merge_trivial("trivial-5alt-2", "trivial-5alt-2-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "modified-to-same.txt", 0));
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -145,23 +143,9 @@ void test_merge_workdir_trivial__5alt_2(void)
void test_merge_workdir_trivial__6(void)
{
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 1);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 1));
-}
-
-/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */
-void test_merge_workdir_trivial__6_automerge(void)
-{
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 1));
+ cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 1);
@@ -174,24 +158,9 @@ void test_merge_workdir_trivial__6_automerge(void)
void test_merge_workdir_trivial__8(void)
{
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 2);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 1));
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 3));
-}
-
-/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */
-void test_merge_workdir_trivial__8_automerge(void)
-{
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 1));
+ cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL);
@@ -206,22 +175,7 @@ void test_merge_workdir_trivial__7(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 2);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 1));
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 3));
-}
-
-/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */
-void test_merge_workdir_trivial__7_automerge(void)
-{
- const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0));
+ cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -235,24 +189,9 @@ void test_merge_workdir_trivial__7_automerge(void)
void test_merge_workdir_trivial__10(void)
{
const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 2);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 1));
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 2));
-}
-
-/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */
-void test_merge_workdir_trivial__10_automerge(void)
-{
- const git_index_entry *entry;
const git_index_reuc_entry *reuc;
- cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 1));
+ cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL);
@@ -267,22 +206,7 @@ void test_merge_workdir_trivial__9(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 0));
-
- cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL);
- cl_assert(git_index_reuc_entrycount(repo_index) == 0);
-
- cl_assert(merge_trivial_conflict_entrycount() == 2);
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 1));
- cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 2));
-}
-
-/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */
-void test_merge_workdir_trivial__9_automerge(void)
-{
- const git_index_entry *entry;
-
- cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 1));
+ cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
@@ -298,11 +222,11 @@ void test_merge_workdir_trivial__13(void)
const git_index_entry *entry;
git_oid expected_oid;
- cl_git_pass(merge_trivial("trivial-13", "trivial-13-branch", 0));
+ cl_git_pass(merge_trivial("trivial-13", "trivial-13-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-13.txt", 0));
cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b"));
- cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0);
+ cl_assert(git_oid_cmp(&entry->id, &expected_oid) == 0);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
cl_assert(merge_trivial_conflict_entrycount() == 0);
@@ -314,11 +238,11 @@ void test_merge_workdir_trivial__14(void)
const git_index_entry *entry;
git_oid expected_oid;
- cl_git_pass(merge_trivial("trivial-14", "trivial-14-branch", 0));
+ cl_git_pass(merge_trivial("trivial-14", "trivial-14-branch"));
cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-14-branch.txt", 0));
cl_git_pass(git_oid_fromstr(&expected_oid, "26153a3ff3649b6c2bb652d3f06878c6e0a172f9"));
- cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0);
+ cl_assert(git_oid_cmp(&entry->id, &expected_oid) == 0);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
cl_assert(merge_trivial_conflict_entrycount() == 0);
@@ -329,7 +253,7 @@ void test_merge_workdir_trivial__11(void)
{
const git_index_entry *entry;
- cl_git_pass(merge_trivial("trivial-11", "trivial-11-branch", 0));
+ cl_git_pass(merge_trivial("trivial-11", "trivial-11-branch"));
cl_assert((entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 0)) == NULL);
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c
index 309142925..9b9f716b9 100644
--- a/tests/network/remote/local.c
+++ b/tests/network/remote/local.c
@@ -197,6 +197,47 @@ void test_network_remote_local__push_to_bare_remote(void)
cl_fixture_cleanup("localbare.git");
}
+void test_network_remote_local__push_to_bare_remote_with_file_url(void)
+{
+ /* Should be able to push to a bare remote */
+ git_remote *localremote;
+ git_push *push;
+ const char *url;
+
+ /* Get some commits */
+ connect_to_local_repository(cl_fixture("testrepo.git"));
+ cl_git_pass(git_remote_add_fetch(remote, "master:master"));
+ cl_git_pass(git_remote_download(remote));
+ cl_git_pass(git_remote_update_tips(remote));
+ git_remote_disconnect(remote);
+
+ /* Set up an empty bare repo to push into */
+ {
+ git_repository *localbarerepo;
+ cl_git_pass(git_repository_init(&localbarerepo, "./localbare.git", 1));
+ git_repository_free(localbarerepo);
+ }
+
+ /* Create a file URL */
+ url = cl_git_path_url("./localbare.git");
+
+ /* Connect to the bare repo */
+ cl_git_pass(git_remote_create_inmemory(&localremote, repo, NULL, url));
+ cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH));
+
+ /* Try to push */
+ cl_git_pass(git_push_new(&push, localremote));
+ cl_git_pass(git_push_add_refspec(push, "refs/heads/master:"));
+ cl_git_pass(git_push_finish(push));
+ cl_assert(git_push_unpack_ok(push));
+
+ /* Clean up */
+ git_push_free(push);
+ git_remote_free(localremote);
+ cl_fixture_cleanup("localbare.git");
+}
+
+
void test_network_remote_local__push_to_non_bare_remote(void)
{
/* Shouldn't be able to push to a non-bare remote */
diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c
index 954ded82c..fe40d1085 100644
--- a/tests/network/remote/remotes.c
+++ b/tests/network/remote/remotes.c
@@ -129,6 +129,29 @@ void test_network_remote_remotes__add_fetchspec(void)
cl_assert_equal_b(_refspec->push, false);
}
+void test_network_remote_remotes__dup(void)
+{
+ git_strarray array;
+ git_remote *dup;
+
+ cl_git_pass(git_remote_dup(&dup, _remote));
+
+ cl_assert_equal_s(git_remote_name(dup), git_remote_name(_remote));
+ cl_assert_equal_s(git_remote_url(dup), git_remote_url(_remote));
+ cl_assert_equal_s(git_remote_pushurl(dup), git_remote_pushurl(_remote));
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote));
+ cl_assert_equal_i(1, (int)array.count);
+ cl_assert_equal_s("+refs/heads/*:refs/remotes/test/*", array.strings[0]);
+ git_strarray_free(&array);
+
+ cl_git_pass(git_remote_get_push_refspecs(&array, _remote));
+ cl_assert_equal_i(0, (int)array.count);
+ git_strarray_free(&array);
+
+ git_remote_free(dup);
+}
+
void test_network_remote_remotes__add_pushspec(void)
{
size_t size;
@@ -207,27 +230,20 @@ void test_network_remote_remotes__fnmatch(void)
void test_network_remote_remotes__transform(void)
{
- char ref[1024] = {0};
+ git_buf ref = GIT_BUF_INIT;
- cl_git_pass(git_refspec_transform(ref, sizeof(ref), _refspec, "refs/heads/master"));
- cl_assert_equal_s(ref, "refs/remotes/test/master");
+ cl_git_pass(git_refspec_transform(&ref, _refspec, "refs/heads/master"));
+ cl_assert_equal_s(ref.ptr, "refs/remotes/test/master");
+ git_buf_free(&ref);
}
void test_network_remote_remotes__transform_destination_to_source(void)
{
- char ref[1024] = {0};
-
- cl_git_pass(git_refspec_rtransform(ref, sizeof(ref), _refspec, "refs/remotes/test/master"));
- cl_assert_equal_s(ref, "refs/heads/master");
-}
-
-void test_network_remote_remotes__transform_r(void)
-{
- git_buf buf = GIT_BUF_INIT;
+ git_buf ref = GIT_BUF_INIT;
- cl_git_pass(git_refspec_transform_r(&buf, _refspec, "refs/heads/master"));
- cl_assert_equal_s(git_buf_cstr(&buf), "refs/remotes/test/master");
- git_buf_free(&buf);
+ cl_git_pass(git_refspec_rtransform(&ref, _refspec, "refs/remotes/test/master"));
+ cl_assert_equal_s(ref.ptr, "refs/heads/master");
+ git_buf_free(&ref);
}
void test_network_remote_remotes__missing_refspecs(void)
diff --git a/tests/notes/notes.c b/tests/notes/notes.c
index c2579a2c4..e48d9df0e 100644
--- a/tests/notes/notes.c
+++ b/tests/notes/notes.c
@@ -21,7 +21,7 @@ static void assert_note_equal(git_note *note, char *message, git_oid *note_oid)
git_blob *blob;
cl_assert_equal_s(git_note_message(note), message);
- cl_assert(!git_oid_cmp(git_note_oid(note), note_oid));
+ cl_assert(!git_oid_cmp(git_note_id(note), note_oid));
cl_git_pass(git_blob_lookup(&blob, _repo, note_oid));
cl_assert_equal_s(git_note_message(note), (const char *)git_blob_rawcontent(blob));
@@ -290,7 +290,7 @@ void test_notes_notes__can_read_a_note_in_an_existing_fanout(void)
cl_git_pass(git_note_read(&note, _repo, "refs/notes/fanout", &target_oid));
cl_git_pass(git_oid_fromstr(&note_oid, "08b041783f40edfe12bb406c9c9a8a040177c125"));
- cl_assert(!git_oid_cmp(git_note_oid(note), &note_oid));
+ cl_assert(!git_oid_cmp(git_note_id(note), &note_oid));
git_note_free(note);
}
diff --git a/tests/notes/notesref.c b/tests/notes/notesref.c
index c89b71ba5..a33141979 100644
--- a/tests/notes/notesref.c
+++ b/tests/notes/notesref.c
@@ -46,13 +46,13 @@ void test_notes_notesref__config_corenotesref(void)
cl_git_pass(git_note_read(&_note, _repo, NULL, &oid));
cl_assert_equal_s("test123test\n", git_note_message(_note));
- cl_assert(!git_oid_cmp(git_note_oid(_note), &note_oid));
+ cl_assert(!git_oid_cmp(git_note_id(_note), &note_oid));
git_note_free(_note);
cl_git_pass(git_note_read(&_note, _repo, "refs/notes/mydefaultnotesref", &oid));
cl_assert_equal_s("test123test\n", git_note_message(_note));
- cl_assert(!git_oid_cmp(git_note_oid(_note), &note_oid));
+ cl_assert(!git_oid_cmp(git_note_id(_note), &note_oid));
cl_git_pass(git_note_default_ref(&default_ref, _repo));
cl_assert_equal_s("refs/notes/mydefaultnotesref", default_ref);
diff --git a/tests/object/commit/commitstagedfile.c b/tests/object/commit/commitstagedfile.c
index 9867ab418..fbeeccbbd 100644
--- a/tests/object/commit/commitstagedfile.c
+++ b/tests/object/commit/commitstagedfile.c
@@ -25,7 +25,7 @@ void test_object_commit_commitstagedfile__generate_predictable_object_ids(void)
git_oid expected_blob_oid, tree_oid, expected_tree_oid, commit_oid, expected_commit_oid;
git_signature *signature;
git_tree *tree;
- char buffer[128];
+ git_buf buffer;
/*
* The test below replicates the following git scenario
@@ -77,7 +77,7 @@ void test_object_commit_commitstagedfile__generate_predictable_object_ids(void)
entry = git_index_get_byindex(index, 0);
- cl_assert(git_oid_cmp(&expected_blob_oid, &entry->oid) == 0);
+ cl_assert(git_oid_cmp(&expected_blob_oid, &entry->id) == 0);
/*
* Information about index entry should match test file
@@ -111,7 +111,8 @@ void test_object_commit_commitstagedfile__generate_predictable_object_ids(void)
cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60));
cl_git_pass(git_tree_lookup(&tree, repo, &tree_oid));
- cl_assert_equal_i(16, git_message_prettify(buffer, 128, "Initial commit", 0));
+ memset(&buffer, 0, sizeof(git_buf));
+ cl_git_pass(git_message_prettify(&buffer, "Initial commit", 0));
cl_git_pass(git_commit_create_v(
&commit_oid,
@@ -120,12 +121,13 @@ void test_object_commit_commitstagedfile__generate_predictable_object_ids(void)
signature,
signature,
NULL,
- buffer,
+ buffer.ptr,
tree,
0));
cl_assert(git_oid_cmp(&expected_commit_oid, &commit_oid) == 0);
+ git_buf_free(&buffer);
git_signature_free(signature);
git_tree_free(tree);
git_index_free(index);
diff --git a/tests/object/message.c b/tests/object/message.c
index 7ef6374b3..ab5565341 100644
--- a/tests/object/message.c
+++ b/tests/object/message.c
@@ -6,7 +6,7 @@ static void assert_message_prettifying(char *expected_output, char *input, int s
{
git_buf prettified_message = GIT_BUF_INIT;
- git_message__prettify(&prettified_message, input, strip_comments);
+ git_message_prettify(&prettified_message, input, strip_comments);
cl_assert_equal_s(expected_output, git_buf_cstr(&prettified_message));
git_buf_free(&prettified_message);
@@ -172,65 +172,28 @@ void test_object_message__keep_comments(void)
void test_object_message__message_prettify(void)
{
- char buffer[100];
-
- cl_assert(git_message_prettify(buffer, sizeof(buffer), "", 0) == 1);
- cl_assert_equal_s(buffer, "");
- cl_assert(git_message_prettify(buffer, sizeof(buffer), "", 1) == 1);
- cl_assert_equal_s(buffer, "");
-
- cl_assert_equal_i(7, git_message_prettify(buffer, sizeof(buffer), "Short", 0));
- cl_assert_equal_s("Short\n", buffer);
- cl_assert_equal_i(7, git_message_prettify(buffer, sizeof(buffer), "Short", 1));
- cl_assert_equal_s("Short\n", buffer);
-
- cl_assert(git_message_prettify(buffer, sizeof(buffer), "This is longer\nAnd multiline\n# with some comments still in\n", 0) > 0);
- cl_assert_equal_s(buffer, "This is longer\nAnd multiline\n# with some comments still in\n");
-
- cl_assert(git_message_prettify(buffer, sizeof(buffer), "This is longer\nAnd multiline\n# with some comments still in\n", 1) > 0);
- cl_assert_equal_s(buffer, "This is longer\nAnd multiline\n");
-
- /* try out overflow */
- cl_assert(git_message_prettify(buffer, sizeof(buffer),
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"
- "1234567890" "1234567890" "1234567890" "1234567890" "12345678",
- 0) > 0);
- cl_assert_equal_s(buffer,
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"
- "1234567890" "1234567890" "1234567890" "1234567890" "12345678\n");
-
- cl_assert(git_message_prettify(buffer, sizeof(buffer),
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"
- "1234567890" "1234567890" "1234567890" "1234567890" "12345678\n",
- 0) > 0);
- cl_assert_equal_s(buffer,
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"
- "1234567890" "1234567890" "1234567890" "1234567890" "12345678\n");
-
- cl_git_fail(git_message_prettify(buffer, sizeof(buffer),
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"
- "1234567890" "1234567890" "1234567890" "1234567890" "123456789",
- 0));
- cl_git_fail(git_message_prettify(buffer, sizeof(buffer),
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"
- "1234567890" "1234567890" "1234567890" "1234567890" "123456789\n",
- 0));
- cl_git_fail(git_message_prettify(buffer, sizeof(buffer),
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890",
- 0));
- cl_git_fail(git_message_prettify(buffer, sizeof(buffer),
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890""x",
- 0));
-
- cl_assert(git_message_prettify(buffer, sizeof(buffer),
- "1234567890" "1234567890" "1234567890" "1234567890" "1234567890\n"
- "# 1234567890" "1234567890" "1234567890" "1234567890" "1234567890\n"
- "1234567890",
- 1) > 0);
-
- cl_assert(git_message_prettify(NULL, 0, "", 0) == 1);
- cl_assert(git_message_prettify(NULL, 0, "Short test", 0) == 12);
- cl_assert(git_message_prettify(NULL, 0, "Test\n# with\nComments", 1) == 15);
+ git_buf buffer;
+
+ memset(&buffer, 0, sizeof(buffer));
+ cl_git_pass(git_message_prettify(&buffer, "", 0));
+ cl_assert_equal_s(buffer.ptr, "");
+ git_buf_free(&buffer);
+ cl_git_pass(git_message_prettify(&buffer, "", 1));
+ cl_assert_equal_s(buffer.ptr, "");
+ git_buf_free(&buffer);
+
+ cl_git_pass(git_message_prettify(&buffer, "Short", 0));
+ cl_assert_equal_s("Short\n", buffer.ptr);
+ git_buf_free(&buffer);
+ cl_git_pass(git_message_prettify(&buffer, "Short", 1));
+ cl_assert_equal_s("Short\n", buffer.ptr);
+ git_buf_free(&buffer);
+
+ cl_git_pass(git_message_prettify(&buffer, "This is longer\nAnd multiline\n# with some comments still in\n", 0));
+ cl_assert_equal_s(buffer.ptr, "This is longer\nAnd multiline\n# with some comments still in\n");
+ git_buf_free(&buffer);
+
+ cl_git_pass(git_message_prettify(&buffer, "This is longer\nAnd multiline\n# with some comments still in\n", 1));
+ cl_assert_equal_s(buffer.ptr, "This is longer\nAnd multiline\n");
+ git_buf_free(&buffer);
}
diff --git a/tests/object/tree/duplicateentries.c b/tests/object/tree/duplicateentries.c
index 9262f9a1a..1b752acbb 100644
--- a/tests/object/tree/duplicateentries.c
+++ b/tests/object/tree/duplicateentries.c
@@ -127,17 +127,17 @@ static void add_fake_conflicts(git_index *index)
ancestor_entry.path = "duplicate";
ancestor_entry.mode = GIT_FILEMODE_BLOB;
ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&ancestor_entry.oid, "a8233120f6ad708f843d861ce2b7228ec4e3dec6");
+ git_oid_fromstr(&ancestor_entry.id, "a8233120f6ad708f843d861ce2b7228ec4e3dec6");
our_entry.path = "duplicate";
our_entry.mode = GIT_FILEMODE_BLOB;
ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&our_entry.oid, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057");
+ git_oid_fromstr(&our_entry.id, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057");
their_entry.path = "duplicate";
their_entry.mode = GIT_FILEMODE_BLOB;
ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT);
- git_oid_fromstr(&their_entry.oid, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd");
+ git_oid_fromstr(&their_entry.id, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd");
cl_git_pass(git_index_conflict_add(index, &ancestor_entry, &our_entry, &their_entry));
}
diff --git a/tests/online/clone.c b/tests/online/clone.c
index be4421ae5..1222d174d 100644
--- a/tests/online/clone.c
+++ b/tests/online/clone.c
@@ -147,7 +147,7 @@ void test_online_clone__clone_into(void)
callbacks.payload = &fetch_progress_cb_was_called;
git_remote_set_callbacks(remote, &callbacks);
- cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL));
+ cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL, NULL));
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));
diff --git a/tests/online/push.c b/tests/online/push.c
index 33f174654..8efe21e0e 100644
--- a/tests/online/push.c
+++ b/tests/online/push.c
@@ -219,7 +219,7 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r
if (!fetch_spec)
continue;
- cl_git_pass(git_refspec_transform_r(&ref_name, fetch_spec, expected_refs[i].name));
+ cl_git_pass(git_refspec_transform(&ref_name, fetch_spec, expected_refs[i].name));
/* Find matching remote branch */
git_vector_foreach(&actual_refs, j, actual_ref) {
diff --git a/tests/refs/branches/create.c b/tests/refs/branches/create.c
index e4ad6683e..abe5f5940 100644
--- a/tests/refs/branches/create.c
+++ b/tests/refs/branches/create.c
@@ -46,7 +46,7 @@ void test_refs_branches_create__can_create_a_local_branch(void)
{
retrieve_known_commit(&target, repo);
- cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, 0));
+ cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, 0, NULL, NULL));
cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target)));
}
@@ -54,24 +54,69 @@ void test_refs_branches_create__can_not_create_a_branch_if_its_name_collide_with
{
retrieve_known_commit(&target, repo);
- cl_assert_equal_i(GIT_EEXISTS, git_branch_create(&branch, repo, "br2", target, 0));
+ cl_assert_equal_i(GIT_EEXISTS, git_branch_create(&branch, repo, "br2", target, 0, NULL, NULL));
}
void test_refs_branches_create__can_force_create_over_an_existing_branch(void)
{
retrieve_known_commit(&target, repo);
- cl_git_pass(git_branch_create(&branch, repo, "br2", target, 1));
+ cl_git_pass(git_branch_create(&branch, repo, "br2", target, 1, NULL, NULL));
cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target)));
cl_assert_equal_s("refs/heads/br2", git_reference_name(branch));
}
-
void test_refs_branches_create__creating_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void)
{
retrieve_known_commit(&target, repo);
cl_assert_equal_i(GIT_EINVALIDSPEC,
- git_branch_create(&branch, repo, "inv@{id", target, 0));
+ git_branch_create(&branch, repo, "inv@{id", target, 0, NULL, NULL));
+}
+
+void test_refs_branches_create__creation_creates_new_reflog(void)
+{
+ git_reflog *log;
+ const git_reflog_entry *entry;
+ git_signature *sig;
+
+ cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
+
+ retrieve_known_commit(&target, repo);
+ cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, false, sig, "create!"));
+ cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));
+
+ cl_assert_equal_i(1, git_reflog_entrycount(log));
+ entry = git_reflog_entry_byindex(log, 0);
+ cl_assert_equal_s("create!", git_reflog_entry_message(entry));
+ cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
+
+ git_reflog_free(log);
+ git_signature_free(sig);
}
+void test_refs_branches_create__default_reflog_message(void)
+{
+ git_reflog *log;
+ const git_reflog_entry *entry;
+ git_signature *sig;
+ git_config *cfg;
+
+ cl_git_pass(git_repository_config(&cfg, repo));
+ cl_git_pass(git_config_set_string(cfg, "user.name", "Foo Bar"));
+ cl_git_pass(git_config_set_string(cfg, "user.email", "foo@example.com"));
+ git_config_free(cfg);
+
+ cl_git_pass(git_signature_default(&sig, repo));
+
+ retrieve_known_commit(&target, repo);
+ cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, false, NULL, NULL));
+ cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));
+
+ entry = git_reflog_entry_byindex(log, 0);
+ cl_assert_equal_s("Branch: created", git_reflog_entry_message(entry));
+ cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email);
+
+ git_reflog_free(log);
+ git_signature_free(sig);
+}
diff --git a/tests/refs/branches/delete.c b/tests/refs/branches/delete.c
index de90cb734..7d1d400c8 100644
--- a/tests/refs/branches/delete.c
+++ b/tests/refs/branches/delete.c
@@ -14,7 +14,7 @@ void test_refs_branches_delete__initialize(void)
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
- cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0));
+ cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0, NULL, NULL));
}
void test_refs_branches_delete__cleanup(void)
@@ -115,3 +115,29 @@ void test_refs_branches_delete__deleting_a_branch_removes_related_configuration_
assert_config_entry_existence(repo, "branch.track-local.remote", false);
assert_config_entry_existence(repo, "branch.track-local.merge", false);
}
+
+void test_refs_branches_delete__removes_reflog(void)
+{
+ git_reference *branch;
+ git_reflog *log;
+ git_oid oidzero = {{0}};
+ git_signature *sig;
+
+ /* Ensure the reflog has at least one entry */
+ cl_git_pass(git_signature_now(&sig, "Me", "user@example.com"));
+ cl_git_pass(git_reflog_read(&log, repo, "refs/heads/track-local"));
+ cl_git_pass(git_reflog_append(log, &oidzero, sig, "message"));
+ cl_assert(git_reflog_entrycount(log) > 0);
+ git_signature_free(sig);
+ git_reflog_free(log);
+
+ cl_git_pass(git_branch_lookup(&branch, repo, "track-local", GIT_BRANCH_LOCAL));
+ cl_git_pass(git_branch_delete(branch));
+ git_reference_free(branch);
+
+ /* Reading a nonexistant reflog creates it, but it should be empty */
+ cl_git_pass(git_reflog_read(&log, repo, "refs/heads/track-local"));
+ cl_assert_equal_i(0, git_reflog_entrycount(log));
+ git_reflog_free(log);
+}
+
diff --git a/tests/refs/branches/ishead.c b/tests/refs/branches/ishead.c
index b1ad09c3e..12a8c4449 100644
--- a/tests/refs/branches/ishead.c
+++ b/tests/refs/branches/ishead.c
@@ -98,9 +98,9 @@ void test_refs_branches_ishead__only_direct_references_are_considered(void)
git_repository_free(repo);
repo = cl_git_sandbox_init("testrepo.git");
- cl_git_pass(git_reference_symbolic_create(&linked, repo, "refs/heads/linked", "refs/heads/master", 0));
- cl_git_pass(git_reference_symbolic_create(&super, repo, "refs/heads/super", "refs/heads/linked", 0));
- cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, "refs/heads/super", 1));
+ cl_git_pass(git_reference_symbolic_create(&linked, repo, "refs/heads/linked", "refs/heads/master", 0, NULL, NULL));
+ cl_git_pass(git_reference_symbolic_create(&super, repo, "refs/heads/super", "refs/heads/linked", 0, NULL, NULL));
+ cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, "refs/heads/super", 1, NULL, NULL));
cl_assert_equal_i(false, git_branch_is_head(linked));
cl_assert_equal_i(false, git_branch_is_head(super));
diff --git a/tests/refs/branches/iterator.c b/tests/refs/branches/iterator.c
index 904c6a146..29ca59aca 100644
--- a/tests/refs/branches/iterator.c
+++ b/tests/refs/branches/iterator.c
@@ -12,7 +12,7 @@ void test_refs_branches_iterator__initialize(void)
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
- cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0));
+ cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0, NULL, NULL));
}
void test_refs_branches_iterator__cleanup(void)
@@ -113,7 +113,7 @@ void test_refs_branches_iterator__retrieve_remote_symbolic_HEAD_when_present(voi
};
git_reference_free(fake_remote);
- cl_git_pass(git_reference_symbolic_create(&fake_remote, repo, "refs/remotes/nulltoken/HEAD", "refs/remotes/nulltoken/master", 0));
+ cl_git_pass(git_reference_symbolic_create(&fake_remote, repo, "refs/remotes/nulltoken/HEAD", "refs/remotes/nulltoken/master", 0, NULL, NULL));
assert_retrieval(GIT_BRANCH_REMOTE, 3);
diff --git a/tests/refs/branches/move.c b/tests/refs/branches/move.c
index 9d233de1a..6c6dbbe21 100644
--- a/tests/refs/branches/move.c
+++ b/tests/refs/branches/move.c
@@ -22,7 +22,7 @@ void test_refs_branches_move__can_move_a_local_branch(void)
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
- cl_git_pass(git_branch_move(&new_ref, original_ref, NEW_BRANCH_NAME, 0));
+ cl_git_pass(git_branch_move(&new_ref, original_ref, NEW_BRANCH_NAME, 0, NULL, NULL));
cl_assert_equal_s(GIT_REFS_HEADS_DIR NEW_BRANCH_NAME, git_reference_name(new_ref));
git_reference_free(original_ref);
@@ -36,11 +36,11 @@ void test_refs_branches_move__can_move_a_local_branch_to_a_different_namespace(v
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
/* Downward */
- cl_git_pass(git_branch_move(&new_ref, original_ref, "somewhere/" NEW_BRANCH_NAME, 0));
+ cl_git_pass(git_branch_move(&new_ref, original_ref, "somewhere/" NEW_BRANCH_NAME, 0, NULL, NULL));
git_reference_free(original_ref);
/* Upward */
- cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0));
+ cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0, NULL, NULL));
git_reference_free(new_ref);
git_reference_free(newer_ref);
@@ -53,11 +53,11 @@ void test_refs_branches_move__can_move_a_local_branch_to_a_partially_colliding_n
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
/* Downward */
- cl_git_pass(git_branch_move(&new_ref, original_ref, "br2/" NEW_BRANCH_NAME, 0));
+ cl_git_pass(git_branch_move(&new_ref, original_ref, "br2/" NEW_BRANCH_NAME, 0, NULL, NULL));
git_reference_free(original_ref);
/* Upward */
- cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0));
+ cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0, NULL, NULL));
git_reference_free(new_ref);
git_reference_free(newer_ref);
@@ -81,7 +81,7 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
cl_assert_equal_i(GIT_EEXISTS,
- git_branch_move(&new_ref, original_ref, "master", 0));
+ git_branch_move(&new_ref, original_ref, "master", 0, NULL, NULL));
cl_assert(giterr_last()->message != NULL);
cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote"));
@@ -91,7 +91,7 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
cl_assert_equal_i(GIT_EEXISTS,
- git_branch_move(&new_ref, original_ref, "cannot-fetch", 0));
+ git_branch_move(&new_ref, original_ref, "cannot-fetch", 0, NULL, NULL));
cl_assert(giterr_last()->message != NULL);
cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote"));
@@ -103,7 +103,7 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/track-local"));
cl_assert_equal_i(GIT_EEXISTS,
- git_branch_move(&new_ref, original_ref, "master", 0));
+ git_branch_move(&new_ref, original_ref, "master", 0, NULL, NULL));
cl_assert(giterr_last()->message != NULL);
cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote"));
@@ -122,7 +122,7 @@ void test_refs_branches_move__moving_a_branch_with_an_invalid_name_returns_EINVA
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
- cl_assert_equal_i(GIT_EINVALIDSPEC, git_branch_move(&new_ref, original_ref, "Inv@{id", 0));
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_branch_move(&new_ref, original_ref, "Inv@{id", 0, NULL, NULL));
git_reference_free(original_ref);
}
@@ -132,7 +132,7 @@ void test_refs_branches_move__can_not_move_a_non_branch(void)
git_reference *tag, *new_ref;
cl_git_pass(git_reference_lookup(&tag, repo, "refs/tags/e90810b"));
- cl_git_fail(git_branch_move(&new_ref, tag, NEW_BRANCH_NAME, 0));
+ cl_git_fail(git_branch_move(&new_ref, tag, NEW_BRANCH_NAME, 0, NULL, NULL));
git_reference_free(tag);
}
@@ -143,7 +143,7 @@ void test_refs_branches_move__can_force_move_over_an_existing_branch(void)
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
- cl_git_pass(git_branch_move(&new_ref, original_ref, "master", 1));
+ cl_git_pass(git_branch_move(&new_ref, original_ref, "master", 1, NULL, NULL));
git_reference_free(original_ref);
git_reference_free(new_ref);
@@ -161,7 +161,7 @@ void test_refs_branches_move__moving_a_branch_moves_related_configuration_data(v
assert_config_entry_existence(repo, "branch.moved.remote", false);
assert_config_entry_existence(repo, "branch.moved.merge", false);
- cl_git_pass(git_branch_move(&new_branch, branch, "moved", 0));
+ cl_git_pass(git_branch_move(&new_branch, branch, "moved", 0, NULL, NULL));
git_reference_free(branch);
assert_config_entry_existence(repo, "branch.track-local.remote", false);
@@ -178,7 +178,7 @@ void test_refs_branches_move__moving_the_branch_pointed_at_by_HEAD_updates_HEAD(
git_reference *new_branch;
cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master"));
- cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0));
+ cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0, NULL, NULL));
git_reference_free(branch);
git_reference_free(new_branch);
@@ -186,3 +186,58 @@ void test_refs_branches_move__moving_the_branch_pointed_at_by_HEAD_updates_HEAD(
cl_assert_equal_s("refs/heads/master2", git_reference_name(branch));
git_reference_free(branch);
}
+
+void test_refs_branches_move__updates_the_reflog(void)
+{
+ git_reference *branch;
+ git_reference *new_branch;
+ git_reflog *log;
+ const git_reflog_entry *entry;
+ git_signature *sig;
+
+ cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
+
+ cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master"));
+ cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0, sig, "message"));
+
+ cl_git_pass(git_reflog_read(&log, repo, git_reference_name(new_branch)));
+ entry = git_reflog_entry_byindex(log, 0);
+ cl_assert_equal_s("message", git_reflog_entry_message(entry));
+ cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
+
+ git_reference_free(branch);
+ git_reference_free(new_branch);
+ git_reflog_free(log);
+ git_signature_free(sig);
+}
+
+void test_refs_branches_move__default_reflog_message(void)
+{
+ git_reference *branch;
+ git_reference *new_branch;
+ git_reflog *log;
+ const git_reflog_entry *entry;
+ git_signature *sig;
+ git_config *cfg;
+
+ cl_git_pass(git_repository_config(&cfg, repo));
+ cl_git_pass(git_config_set_string(cfg, "user.name", "Foo Bar"));
+ cl_git_pass(git_config_set_string(cfg, "user.email", "foo@example.com"));
+ git_config_free(cfg);
+
+ cl_git_pass(git_signature_default(&sig, repo));
+
+ cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master"));
+ cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0, NULL, NULL));
+
+ cl_git_pass(git_reflog_read(&log, repo, git_reference_name(new_branch)));
+ entry = git_reflog_entry_byindex(log, 0);
+ cl_assert_equal_s("Branch: renamed refs/heads/master to refs/heads/master2",
+ git_reflog_entry_message(entry));
+ cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email);
+
+ git_reference_free(branch);
+ git_reference_free(new_branch);
+ git_reflog_free(log);
+ git_signature_free(sig);
+}
diff --git a/tests/refs/branches/remote.c b/tests/refs/branches/remote.c
index c110adb33..bac088454 100644
--- a/tests/refs/branches/remote.c
+++ b/tests/refs/branches/remote.c
@@ -21,53 +21,40 @@ void test_refs_branches_remote__cleanup(void)
void test_refs_branches_remote__can_get_remote_for_branch(void)
{
- char remotename[1024] = {0};
+ git_buf remotename = {0};
- cl_assert_equal_i(expected_remote_name_length,
- git_branch_remote_name(NULL, 0, g_repo, remote_tracking_branch_name));
+ cl_git_pass(git_branch_remote_name(&remotename, g_repo, remote_tracking_branch_name));
- cl_assert_equal_i(expected_remote_name_length,
- git_branch_remote_name(remotename, expected_remote_name_length, g_repo,
- remote_tracking_branch_name));
-
- cl_assert_equal_s("test", remotename);
-}
-
-void test_refs_branches_remote__insufficient_buffer_returns_error(void)
-{
- char remotename[1024] = {0};
-
- cl_assert_equal_i(expected_remote_name_length,
- git_branch_remote_name(NULL, 0, g_repo, remote_tracking_branch_name));
-
- cl_git_fail_with(git_branch_remote_name(remotename,
- expected_remote_name_length - 1, g_repo, remote_tracking_branch_name),
- expected_remote_name_length);
+ cl_assert_equal_s("test", remotename.ptr);
+ git_buf_free(&remotename);
}
void test_refs_branches_remote__no_matching_remote_returns_error(void)
{
const char *unknown = "refs/remotes/nonexistent/master";
+ git_buf buf;
giterr_clear();
- cl_git_fail_with(git_branch_remote_name(
- NULL, 0, g_repo, unknown), GIT_ENOTFOUND);
+ memset(&buf, 0, sizeof(git_buf));
+ cl_git_fail_with(git_branch_remote_name(&buf, g_repo, unknown), GIT_ENOTFOUND);
cl_assert(giterr_last() != NULL);
}
void test_refs_branches_remote__local_remote_returns_error(void)
{
const char *local = "refs/heads/master";
+ git_buf buf;
giterr_clear();
- cl_git_fail_with(git_branch_remote_name(
- NULL, 0, g_repo, local), GIT_ERROR);
+ memset(&buf, 0, sizeof(git_buf));
+ cl_git_fail_with(git_branch_remote_name(&buf, g_repo, local), GIT_ERROR);
cl_assert(giterr_last() != NULL);
}
void test_refs_branches_remote__ambiguous_remote_returns_error(void)
{
git_remote *remote;
+ git_buf buf;
/* Create the remote */
cl_git_pass(git_remote_create(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2"));
@@ -80,7 +67,7 @@ void test_refs_branches_remote__ambiguous_remote_returns_error(void)
git_remote_free(remote);
giterr_clear();
- cl_git_fail_with(git_branch_remote_name(NULL, 0, g_repo,
- remote_tracking_branch_name), GIT_EAMBIGUOUS);
+ memset(&buf, 0, sizeof(git_buf));
+ cl_git_fail_with(git_branch_remote_name(&buf, g_repo, remote_tracking_branch_name), GIT_EAMBIGUOUS);
cl_assert(giterr_last() != NULL);
}
diff --git a/tests/refs/branches/upstream.c b/tests/refs/branches/upstream.c
index 69e55a0c5..ce3569813 100644
--- a/tests/refs/branches/upstream.c
+++ b/tests/refs/branches/upstream.c
@@ -66,7 +66,7 @@ static void assert_merge_and_or_remote_key_missing(git_repository *repository, c
git_reference *branch;
cl_assert_equal_i(GIT_OBJ_COMMIT, git_object_type((git_object*)target));
- cl_git_pass(git_branch_create(&branch, repository, entry_name, (git_commit*)target, 0));
+ cl_git_pass(git_branch_create(&branch, repository, entry_name, (git_commit*)target, 0, NULL, NULL));
cl_assert_equal_i(GIT_ENOTFOUND, git_branch_upstream(&upstream, branch));
diff --git a/tests/refs/branches/upstreamname.c b/tests/refs/branches/upstreamname.c
index f05607d44..d30002e08 100644
--- a/tests/refs/branches/upstreamname.c
+++ b/tests/refs/branches/upstreamname.c
@@ -21,7 +21,7 @@ void test_refs_branches_upstreamname__cleanup(void)
void test_refs_branches_upstreamname__can_retrieve_the_remote_tracking_reference_name_of_a_local_branch(void)
{
- cl_git_pass(git_branch_upstream__name(
+ cl_git_pass(git_branch_upstream_name(
&upstream_name, repo, "refs/heads/master"));
cl_assert_equal_s("refs/remotes/test/master", git_buf_cstr(&upstream_name));
@@ -29,14 +29,8 @@ void test_refs_branches_upstreamname__can_retrieve_the_remote_tracking_reference
void test_refs_branches_upstreamname__can_retrieve_the_local_upstream_reference_name_of_a_local_branch(void)
{
- cl_git_pass(git_branch_upstream__name(
+ cl_git_pass(git_branch_upstream_name(
&upstream_name, repo, "refs/heads/track-local"));
cl_assert_equal_s("refs/heads/master", git_buf_cstr(&upstream_name));
}
-
-void test_refs_branches_upstreamname__can_return_the_size_of_thelocal_upstream_reference_name_of_a_local_branch(void)
-{
- cl_assert_equal_i((int)strlen("refs/heads/master") + 1,
- git_branch_upstream_name(NULL, 0, repo, "refs/heads/track-local"));
-}
diff --git a/tests/refs/crashes.c b/tests/refs/crashes.c
index 5a1885a7a..03082d71e 100644
--- a/tests/refs/crashes.c
+++ b/tests/refs/crashes.c
@@ -7,7 +7,7 @@ void test_refs_crashes__double_free(void)
const char *REFNAME = "refs/heads/xxx";
cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
- cl_git_pass(git_reference_symbolic_create(&ref, repo, REFNAME, "refs/heads/master", 0));
+ cl_git_pass(git_reference_symbolic_create(&ref, repo, REFNAME, "refs/heads/master", 0, NULL, NULL));
cl_git_pass(git_reference_lookup(&ref2, repo, REFNAME));
cl_git_pass(git_reference_delete(ref));
git_reference_free(ref);
diff --git a/tests/refs/create.c b/tests/refs/create.c
index 85ff05aa9..50b8e84f8 100644
--- a/tests/refs/create.c
+++ b/tests/refs/create.c
@@ -32,7 +32,7 @@ void test_refs_create__symbolic(void)
git_oid_fromstr(&id, current_master_tip);
/* Create and write the new symbolic reference */
- cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0));
+ cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0, NULL, NULL));
/* Ensure the reference can be looked-up... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker));
@@ -73,7 +73,7 @@ void test_refs_create__deep_symbolic(void)
git_oid_fromstr(&id, current_master_tip);
- cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0));
+ cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0, NULL, NULL));
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker));
cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0);
@@ -95,7 +95,7 @@ void test_refs_create__oid(void)
git_oid_fromstr(&id, current_master_tip);
/* Create and write the new object id reference */
- cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0));
+ cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL, NULL));
/* Ensure the reference can be looked-up... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head));
@@ -130,7 +130,7 @@ void test_refs_create__oid_unknown(void)
git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644");
/* Create and write the new object id reference */
- cl_git_fail(git_reference_create(&new_reference, g_repo, new_head, &id, 0));
+ cl_git_fail(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL, NULL));
/* Ensure the reference can't be looked-up... */
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, new_head));
@@ -144,10 +144,10 @@ void test_refs_create__propagate_eexists(void)
/* Make sure it works for oid and for symbolic both */
git_oid_fromstr(&oid, current_master_tip);
- error = git_reference_create(&ref, g_repo, current_head_target, &oid, false);
+ error = git_reference_create(&ref, g_repo, current_head_target, &oid, false, NULL, NULL);
cl_assert(error == GIT_EEXISTS);
- error = git_reference_symbolic_create(&ref, g_repo, "HEAD", current_head_target, false);
+ error = git_reference_symbolic_create(&ref, g_repo, "HEAD", current_head_target, false, NULL, NULL);
cl_assert(error == GIT_EEXISTS);
}
@@ -161,8 +161,8 @@ void test_refs_create__creating_a_reference_with_an_invalid_name_returns_EINVALI
git_oid_fromstr(&id, current_master_tip);
cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_create(
- &new_reference, g_repo, name, &id, 0));
+ &new_reference, g_repo, name, &id, 0, NULL, NULL));
cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_create(
- &new_reference, g_repo, name, current_head_target, 0));
+ &new_reference, g_repo, name, current_head_target, 0, NULL, NULL));
}
diff --git a/tests/refs/createwithlog.c b/tests/refs/createwithlog.c
index 0fe81df91..026ff6d6a 100644
--- a/tests/refs/createwithlog.c
+++ b/tests/refs/createwithlog.c
@@ -35,7 +35,7 @@ void test_refs_createwithlog__creating_a_direct_reference_adds_a_reflog_entry(vo
cl_git_pass(git_signature_now(&signature, "foo", "foo@bar"));
cl_git_pass(
- git_reference_create_with_log(&reference, g_repo, name, &id, 0, signature, message));
+ git_reference_create(&reference, g_repo, name, &id, 0, signature, message));
cl_git_pass(git_reflog_read(&reflog, g_repo, name));
cl_assert_equal_sz(1, git_reflog_entrycount(reflog));
diff --git a/tests/refs/delete.c b/tests/refs/delete.c
index 973768aeb..5e4afb138 100644
--- a/tests/refs/delete.c
+++ b/tests/refs/delete.c
@@ -66,7 +66,7 @@ void test_refs_delete__packed_only(void)
git_oid_fromstr(&id, current_master_tip);
/* Create and write the new object id reference */
- cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &id, 0));
+ cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &id, 0, NULL, NULL));
git_reference_free(ref);
/* Lookup the reference */
diff --git a/tests/refs/foreachglob.c b/tests/refs/foreachglob.c
index c0f6ce763..b992b07b8 100644
--- a/tests/refs/foreachglob.c
+++ b/tests/refs/foreachglob.c
@@ -12,7 +12,7 @@ void test_refs_foreachglob__initialize(void)
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
- cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0));
+ cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0, NULL, NULL));
}
void test_refs_foreachglob__cleanup(void)
diff --git a/tests/refs/overwrite.c b/tests/refs/overwrite.c
index ebe72069c..78ce4ace7 100644
--- a/tests/refs/overwrite.c
+++ b/tests/refs/overwrite.c
@@ -27,8 +27,8 @@ void test_refs_overwrite__symbolic(void)
git_reference *ref, *branch_ref;
/* The target needds to exist and we need to check the name has changed */
- cl_git_pass(git_reference_symbolic_create(&branch_ref, g_repo, ref_branch_name, ref_master_name, 0));
- cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_branch_name, 0));
+ cl_git_pass(git_reference_symbolic_create(&branch_ref, g_repo, ref_branch_name, ref_master_name, 0, NULL, NULL));
+ cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_branch_name, 0, NULL, NULL));
git_reference_free(ref);
/* Ensure it points to the right place*/
@@ -38,8 +38,8 @@ void test_refs_overwrite__symbolic(void)
git_reference_free(ref);
/* Ensure we can't create it unless we force it to */
- cl_git_fail(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0));
- cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 1));
+ cl_git_fail(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0, NULL, NULL));
+ cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 1, NULL, NULL));
git_reference_free(ref);
/* Ensure it points to the right place */
@@ -63,7 +63,7 @@ void test_refs_overwrite__object_id(void)
git_reference_free(ref);
/* Create it */
- cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 0));
+ cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 0, NULL, NULL));
git_reference_free(ref);
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_test_name));
@@ -72,8 +72,8 @@ void test_refs_overwrite__object_id(void)
git_reference_free(ref);
/* Ensure we can't overwrite unless we force it */
- cl_git_fail(git_reference_create(&ref, g_repo, ref_name, &id, 0));
- cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 1));
+ cl_git_fail(git_reference_create(&ref, g_repo, ref_name, &id, 0, NULL, NULL));
+ cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 1, NULL, NULL));
git_reference_free(ref);
/* Ensure it has been overwritten */
@@ -94,10 +94,10 @@ void test_refs_overwrite__object_id_with_symbolic(void)
git_oid_cpy(&id, git_reference_target(ref));
git_reference_free(ref);
- cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 0));
+ cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 0, NULL, NULL));
git_reference_free(ref);
- cl_git_fail(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0));
- cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 1));
+ cl_git_fail(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0, NULL, NULL));
+ cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 1, NULL, NULL));
git_reference_free(ref);
/* Ensure it points to the right place */
@@ -120,11 +120,11 @@ void test_refs_overwrite__symbolic_with_object_id(void)
git_reference_free(ref);
/* Create the symbolic ref */
- cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0));
+ cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0, NULL, NULL));
git_reference_free(ref);
/* It shouldn't overwrite unless we tell it to */
- cl_git_fail(git_reference_create(&ref, g_repo, ref_name, &id, 0));
- cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 1));
+ cl_git_fail(git_reference_create(&ref, g_repo, ref_name, &id, 0, NULL, NULL));
+ cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 1, NULL, NULL));
git_reference_free(ref);
/* Ensure it points to the right place */
diff --git a/tests/refs/pack.c b/tests/refs/pack.c
index 849a052aa..7f5c611a7 100644
--- a/tests/refs/pack.c
+++ b/tests/refs/pack.c
@@ -93,11 +93,11 @@ void test_refs_pack__symbolic(void)
for (i = 0; i < 100; ++i) {
snprintf(name, sizeof(name), "refs/heads/symbolic-%03d", i);
cl_git_pass(git_reference_symbolic_create(
- &ref, g_repo, name, "refs/heads/master", 0));
+ &ref, g_repo, name, "refs/heads/master", 0, NULL, NULL));
git_reference_free(ref);
snprintf(name, sizeof(name), "refs/heads/direct-%03d", i);
- cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0));
+ cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0, NULL, NULL));
git_reference_free(ref);
}
diff --git a/tests/refs/read.c b/tests/refs/read.c
index 35cf17e9e..52c307eb0 100644
--- a/tests/refs/read.c
+++ b/tests/refs/read.c
@@ -271,6 +271,21 @@ void test_refs_read__can_determine_if_a_reference_is_a_tag(void)
assert_is_tag("refs/remotes/test/master", false);
}
+static void assert_is_note(const char *name, bool expected_noteness)
+{
+ git_reference *reference;
+ cl_git_pass(git_reference_lookup(&reference, g_repo, name));
+ cl_assert_equal_i(expected_noteness, git_reference_is_note(reference));
+ git_reference_free(reference);
+}
+
+void test_refs_read__can_determine_if_a_reference_is_a_note(void)
+{
+ assert_is_note("refs/notes/fanout", true);
+ assert_is_note("refs/heads/packed", false);
+ assert_is_note("refs/remotes/test/master", false);
+}
+
void test_refs_read__invalid_name_returns_EINVALIDSPEC(void)
{
git_reference *reference;
diff --git a/tests/refs/reflog/reflog.c b/tests/refs/reflog/reflog.c
index a1c5adaf4..3f7d7d777 100644
--- a/tests/refs/reflog/reflog.c
+++ b/tests/refs/reflog/reflog.c
@@ -82,7 +82,7 @@ void test_refs_reflog_reflog__append_then_read(void)
/* Create a new branch pointing at the HEAD */
git_oid_fromstr(&oid, current_master_tip);
- cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &oid, 0));
+ cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &oid, 0, NULL, NULL));
git_reference_free(ref);
cl_git_pass(git_signature_now(&committer, "foo", "foo@bar"));
@@ -114,7 +114,7 @@ void test_refs_reflog_reflog__renaming_the_reference_moves_the_reflog(void)
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&moved_log_path)));
cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master"));
- cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0));
+ cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0, NULL, NULL));
git_reference_free(master);
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&master_log_path)));
@@ -165,7 +165,7 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void)
cl_git_pass(git_reflog_write(reflog));
- cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0));
+ cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0, NULL, NULL));
git_reference_free(master);
cl_git_fail(git_reflog_write(reflog));
@@ -189,11 +189,11 @@ void test_refs_reflog_reflog__write_only_std_locations(void)
git_oid_fromstr(&id, current_master_tip);
- cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/foo", &id, 1));
+ cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/foo", &id, 1, NULL, NULL));
git_reference_free(ref);
- cl_git_pass(git_reference_create(&ref, g_repo, "refs/tags/foo", &id, 1));
+ cl_git_pass(git_reference_create(&ref, g_repo, "refs/tags/foo", &id, 1, NULL, NULL));
git_reference_free(ref);
- cl_git_pass(git_reference_create(&ref, g_repo, "refs/notes/foo", &id, 1));
+ cl_git_pass(git_reference_create(&ref, g_repo, "refs/notes/foo", &id, 1, NULL, NULL));
git_reference_free(ref);
assert_has_reflog(true, "refs/heads/foo");
@@ -210,7 +210,7 @@ void test_refs_reflog_reflog__write_when_explicitly_active(void)
git_oid_fromstr(&id, current_master_tip);
git_reference_ensure_log(g_repo, "refs/tags/foo");
- cl_git_pass(git_reference_create(&ref, g_repo, "refs/tags/foo", &id, 1));
+ cl_git_pass(git_reference_create(&ref, g_repo, "refs/tags/foo", &id, 1, NULL, NULL));
git_reference_free(ref);
assert_has_reflog(true, "refs/tags/foo");
}
diff --git a/tests/refs/rename.c b/tests/refs/rename.c
index 543bc4d62..88f0afd9c 100644
--- a/tests/refs/rename.c
+++ b/tests/refs/rename.c
@@ -49,7 +49,7 @@ void test_refs_rename__loose(void)
cl_assert(reference_is_packed(looked_up_ref) == 0);
/* Now that the reference is renamed... */
- cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, new_name, 0));
+ cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, new_name, 0, NULL, NULL));
cl_assert_equal_s(new_ref->name, new_name);
git_reference_free(looked_up_ref);
@@ -91,7 +91,7 @@ void test_refs_rename__packed(void)
cl_assert(reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
- cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, brand_new_name, 0));
+ cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, brand_new_name, 0, NULL, NULL));
cl_assert_equal_s(new_ref->name, brand_new_name);
git_reference_free(looked_up_ref);
@@ -140,7 +140,7 @@ void test_refs_rename__packed_doesnt_pack_others(void)
cl_assert(reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
- cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, brand_new_name, 0));
+ cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, brand_new_name, 0, NULL, NULL));
git_reference_free(looked_up_ref);
/* Lookup the other reference */
@@ -166,7 +166,7 @@ void test_refs_rename__name_collision(void)
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
/* Can not be renamed to the name of another existing reference. */
- cl_git_fail(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 0));
+ cl_git_fail(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 0, NULL, NULL));
git_reference_free(looked_up_ref);
/* Failure to rename it hasn't corrupted its state */
@@ -187,12 +187,12 @@ void test_refs_rename__invalid_name(void)
/* Can not be renamed with an invalid name. */
cl_assert_equal_i(
GIT_EINVALIDSPEC,
- git_reference_rename(&renamed_ref, looked_up_ref, "Hello! I'm a very invalid name.", 0));
+ git_reference_rename(&renamed_ref, looked_up_ref, "Hello! I'm a very invalid name.", 0, NULL, NULL));
/* Can not be renamed outside of the refs hierarchy
* unless it's ALL_CAPS_AND_UNDERSCORES.
*/
- cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_rename(&renamed_ref, looked_up_ref, "i-will-sudo-you", 0));
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_rename(&renamed_ref, looked_up_ref, "i-will-sudo-you", 0, NULL, NULL));
/* Failure to rename it hasn't corrupted its state */
git_reference_free(looked_up_ref);
@@ -213,7 +213,7 @@ void test_refs_rename__force_loose_packed(void)
git_oid_cpy(&oid, git_reference_target(looked_up_ref));
/* Can be force-renamed to the name of another existing reference. */
- cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 1));
+ cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 1, NULL, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
@@ -238,7 +238,7 @@ void test_refs_rename__force_loose(void)
git_oid_cpy(&oid, git_reference_target(looked_up_ref));
/* Can be force-renamed to the name of another existing reference. */
- cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, "refs/heads/test", 1));
+ cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, "refs/heads/test", 1, NULL, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
@@ -268,15 +268,15 @@ void test_refs_rename__overwrite(void)
git_oid_cpy(&id, git_reference_target(ref));
/* Create loose references */
- cl_git_pass(git_reference_create(&ref_one, g_repo, ref_one_name, &id, 0));
- cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0));
+ cl_git_pass(git_reference_create(&ref_one, g_repo, ref_one_name, &id, 0, NULL, NULL));
+ cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0, NULL, NULL));
/* Pack everything */
cl_git_pass(git_repository_refdb(&refdb, g_repo));
cl_git_pass(git_refdb_compress(refdb));
/* Attempt to create illegal reference */
- cl_git_fail(git_reference_create(&ref_one_new, g_repo, ref_one_name_new, &id, 0));
+ cl_git_fail(git_reference_create(&ref_one_new, g_repo, ref_one_name_new, &id, 0, NULL, NULL));
/* Illegal reference couldn't be created so this is supposed to fail */
cl_git_fail(git_reference_lookup(&ref_one_new, g_repo, ref_one_name_new));
@@ -301,13 +301,13 @@ void test_refs_rename__prefix(void)
git_oid_cpy(&id, git_reference_target(ref));
/* Create loose references */
- cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0));
+ cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0, NULL, NULL));
/* An existing reference... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name));
/* Can be rename to a new name starting with the old name. */
- cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name_new, 0));
+ cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name_new, 0, NULL, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
@@ -334,14 +334,14 @@ void test_refs_rename__move_up(void)
git_oid_cpy(&id, git_reference_target(ref));
/* Create loose references */
- cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name_new, &id, 0));
+ cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name_new, &id, 0, NULL, NULL));
git_reference_free(ref_two);
/* An existing reference... */
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new));
/* Can be renamed upward the reference tree. */
- cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name, 0));
+ cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name, 0, NULL, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
@@ -361,7 +361,30 @@ void test_refs_rename__propagate_eexists(void)
cl_git_pass(git_reference_lookup(&ref, g_repo, packed_head_name));
- cl_assert_equal_i(GIT_EEXISTS, git_reference_rename(&new_ref, ref, packed_test_head_name, 0));
+ cl_assert_equal_i(GIT_EEXISTS, git_reference_rename(&new_ref, ref, packed_test_head_name, 0, NULL, NULL));
git_reference_free(ref);
}
+
+void test_refs_rename__writes_to_reflog(void)
+{
+ git_reference *ref, *new_ref;
+ git_reflog *log;
+ const git_reflog_entry *entry;
+ git_signature *sig;
+
+ cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
+
+ cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
+ cl_git_pass(git_reference_rename(&new_ref, ref, ref_one_name_new, false,
+ sig, "message"));
+ cl_git_pass(git_reflog_read(&log, g_repo, git_reference_name(new_ref)));
+ entry = git_reflog_entry_byindex(log, 0);
+ cl_assert_equal_s("message", git_reflog_entry_message(entry));
+ cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
+
+ git_reflog_free(log);
+ git_reference_free(ref);
+ git_reference_free(new_ref);
+ git_signature_free(sig);
+}
diff --git a/tests/refs/revparse.c b/tests/refs/revparse.c
index 37d3981bb..a540f389d 100644
--- a/tests/refs/revparse.c
+++ b/tests/refs/revparse.c
@@ -325,7 +325,7 @@ static void create_fake_stash_reference_and_reflog(git_repository *repo)
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&log_path)));
cl_git_pass(git_reference_lookup(&master, repo, "refs/heads/master"));
- cl_git_pass(git_reference_rename(&new_master, master, "refs/fakestash", 0));
+ cl_git_pass(git_reference_rename(&new_master, master, "refs/fakestash", 0, NULL, NULL));
git_reference_free(master);
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&log_path)));
@@ -596,7 +596,8 @@ void test_refs_revparse__issue_994(void)
repo,
"refs/remotes/origin/bim_with_3d@11296",
git_reference_target(head),
- 0));
+ 0,
+ NULL, NULL));
cl_git_pass(git_revparse_single(&target, repo, "origin/bim_with_3d@11296"));
git_object_free(target);
@@ -633,7 +634,7 @@ void test_refs_revparse__try_to_retrieve_branch_before_described_tag(void)
test_object_inrepo("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo);
cl_git_pass(git_revparse_single(&target, repo, "HEAD~3"));
- cl_git_pass(git_branch_create(&branch, repo, "blah-7-gc47800c", (git_commit *)target, 0));
+ cl_git_pass(git_branch_create(&branch, repo, "blah-7-gc47800c", (git_commit *)target, 0, NULL, NULL));
git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target));
@@ -671,7 +672,7 @@ void test_refs_revparse__try_to_retrieve_sha_before_branch(void)
test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo);
cl_git_pass(git_revparse_single(&target, repo, "HEAD~3"));
- cl_git_pass(git_branch_create(&branch, repo, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", (git_commit *)target, 0));
+ cl_git_pass(git_branch_create(&branch, repo, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", (git_commit *)target, 0, NULL, NULL));
git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target));
@@ -707,7 +708,7 @@ void test_refs_revparse__try_to_retrieve_branch_before_abbrev_sha(void)
test_object_inrepo("c47800", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo);
cl_git_pass(git_revparse_single(&target, repo, "HEAD~3"));
- cl_git_pass(git_branch_create(&branch, repo, "c47800", (git_commit *)target, 0));
+ cl_git_pass(git_branch_create(&branch, repo, "c47800", (git_commit *)target, 0, NULL, NULL));
git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target));
diff --git a/tests/refs/settargetwithlog.c b/tests/refs/settargetwithlog.c
index cfa1c99d5..524ce771c 100644
--- a/tests/refs/settargetwithlog.c
+++ b/tests/refs/settargetwithlog.c
@@ -38,7 +38,7 @@ void test_refs_settargetwithlog__updating_a_direct_reference_adds_a_reflog_entry
cl_git_pass(git_signature_now(&signature, "foo", "foo@bar"));
- cl_git_pass(git_reference_set_target_with_log(
+ cl_git_pass(git_reference_set_target(
&reference_out, reference, &target_id, signature, message));
cl_git_pass(git_reflog_read(&reflog, g_repo, br2_name));
diff --git a/tests/refs/setter.c b/tests/refs/setter.c
index 6d875f9b6..9a945db00 100644
--- a/tests/refs/setter.c
+++ b/tests/refs/setter.c
@@ -34,7 +34,7 @@ void test_refs_setter__update_direct(void)
cl_git_pass(git_reference_lookup(&test_ref, g_repo, ref_test_name));
cl_assert(git_reference_type(test_ref) == GIT_REF_OID);
- cl_git_pass(git_reference_set_target(&new_ref, test_ref, &id));
+ cl_git_pass(git_reference_set_target(&new_ref, test_ref, &id, NULL, NULL));
git_reference_free(test_ref);
git_reference_free(new_ref);
@@ -53,7 +53,7 @@ void test_refs_setter__update_symbolic(void)
cl_assert(git_reference_type(head) == GIT_REF_SYMBOLIC);
cl_assert(strcmp(git_reference_symbolic_target(head), ref_master_name) == 0);
- cl_git_pass(git_reference_symbolic_set_target(&new_head, head, ref_test_name));
+ cl_git_pass(git_reference_symbolic_set_target(&new_head, head, ref_test_name, NULL, NULL));
git_reference_free(new_head);
git_reference_free(head);
@@ -73,7 +73,7 @@ void test_refs_setter__cant_update_direct_with_symbolic(void)
cl_assert(git_reference_type(ref) == GIT_REF_OID);
git_oid_cpy(&id, git_reference_target(ref));
- cl_git_fail(git_reference_symbolic_set_target(&new, ref, ref_name));
+ cl_git_fail(git_reference_symbolic_set_target(&new, ref, ref_name, NULL, NULL));
git_reference_free(ref);
}
@@ -90,10 +90,10 @@ void test_refs_setter__cant_update_symbolic_with_direct(void)
git_reference_free(ref);
/* Create the symbolic ref */
- cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0));
+ cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0, NULL, NULL));
/* Can't set an OID on a direct ref */
- cl_git_fail(git_reference_set_target(&new, ref, &id));
+ cl_git_fail(git_reference_set_target(&new, ref, &id, NULL, NULL));
git_reference_free(ref);
}
diff --git a/tests/refs/unicode.c b/tests/refs/unicode.c
index b56012869..471b0b8d3 100644
--- a/tests/refs/unicode.c
+++ b/tests/refs/unicode.c
@@ -24,7 +24,7 @@ void test_refs_unicode__create_and_lookup(void)
/* Create the reference */
cl_git_pass(git_reference_lookup(&ref0, repo, master));
cl_git_pass(git_reference_create(
- &ref1, repo, REFNAME, git_reference_target(ref0), 0));
+ &ref1, repo, REFNAME, git_reference_target(ref0), 0, NULL, NULL));
cl_assert_equal_s(REFNAME, git_reference_name(ref1));
git_reference_free(ref0);
diff --git a/tests/refs/update.c b/tests/refs/update.c
index 205b526a2..873fc4ebe 100644
--- a/tests/refs/update.c
+++ b/tests/refs/update.c
@@ -22,5 +22,5 @@ void test_refs_update__updating_the_target_of_a_symref_with_an_invalid_name_retu
cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
git_reference_free(head);
- cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_create(&head, g_repo, GIT_HEAD_FILE, "refs/heads/inv@{id", 1));
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_create(&head, g_repo, GIT_HEAD_FILE, "refs/heads/inv@{id", 1, NULL, NULL));
}
diff --git a/tests/repo/discover.c b/tests/repo/discover.c
index f93ff2462..7904b6496 100644
--- a/tests/repo/discover.c
+++ b/tests/repo/discover.c
@@ -25,12 +25,13 @@
static void ensure_repository_discover(const char *start_path,
const char *ceiling_dirs,
- const char *expected_path)
+ git_buf *expected_path)
{
- char found_path[GIT_PATH_MAX];
- cl_git_pass(git_repository_discover(found_path, sizeof(found_path), start_path, 0, ceiling_dirs));
+ git_buf found_path = GIT_BUF_INIT;
+ cl_git_pass(git_repository_discover(&found_path, start_path, 0, ceiling_dirs));
//across_fs is always 0 as we can't automate the filesystem change tests
- cl_assert_equal_s(found_path, expected_path);
+ cl_assert_equal_s(found_path.ptr, expected_path->ptr);
+ git_buf_free(&found_path);
}
static void write_file(const char *path, const char *content)
@@ -69,42 +70,40 @@ static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path)
void test_repo_discover__0(void)
{
- // test discover
+ // test discover
git_repository *repo;
- git_buf ceiling_dirs_buf = GIT_BUF_INIT;
+ git_buf ceiling_dirs_buf = GIT_BUF_INIT, repository_path = GIT_BUF_INIT,
+ sub_repository_path = GIT_BUF_INIT, found_path = GIT_BUF_INIT;
const char *ceiling_dirs;
- char repository_path[GIT_PATH_MAX];
- char sub_repository_path[GIT_PATH_MAX];
- char found_path[GIT_PATH_MAX];
const mode_t mode = 0777;
git_futils_mkdir_r(DISCOVER_FOLDER, NULL, mode);
append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER);
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
- cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&repository_path, DISCOVER_FOLDER, 0, ceiling_dirs));
cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
- cl_git_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
+ cl_git_pass(git_repository_discover(&repository_path, DISCOVER_FOLDER, 0, ceiling_dirs));
git_repository_free(repo);
cl_git_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0));
cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
- cl_git_pass(git_repository_discover(sub_repository_path, sizeof(sub_repository_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
+ cl_git_pass(git_repository_discover(&sub_repository_path, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
- ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, sub_repository_path);
- ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
- ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, sub_repository_path);
+ ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
+ ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path);
+ ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, &sub_repository_path);
cl_git_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, NULL, mode));
write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../");
- ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path);
- ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path);
- ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
- ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path);
+ ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, &sub_repository_path);
+ ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
+ ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path);
+ ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, &repository_path);
cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, NULL, mode));
write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:");
@@ -114,29 +113,31 @@ void test_repo_discover__0(void)
write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n");
cl_git_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, NULL, mode));
write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist");
- cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs));
- cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs));
- cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
- cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
+ cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs));
+ cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs));
+ cl_git_fail(git_repository_discover(&found_path, ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER);
ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
//this must pass as ceiling_directories cannot predent the current
//working directory to be checked
- cl_git_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
- cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
- cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
- cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
+ cl_git_pass(git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(&found_path, SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
//.gitfile redirection should not be affected by ceiling directories
- ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path);
- ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path);
- ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
- ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path);
+ ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, &sub_repository_path);
+ ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, &sub_repository_path);
+ ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, &sub_repository_path);
+ ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, &repository_path);
cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES));
git_repository_free(repo);
git_buf_free(&ceiling_dirs_buf);
+ git_buf_free(&repository_path);
+ git_buf_free(&sub_repository_path);
}
diff --git a/tests/repo/head.c b/tests/repo/head.c
index 5a55984bd..8ea9a0f42 100644
--- a/tests/repo/head.c
+++ b/tests/repo/head.c
@@ -26,7 +26,7 @@ void test_repo_head__head_detached(void)
cl_assert_equal_i(true, git_repository_head_detached(repo));
/* take the reop back to it's original state */
- cl_git_pass(git_reference_symbolic_create(&ref, repo, "HEAD", "refs/heads/master", 1));
+ cl_git_pass(git_reference_symbolic_create(&ref, repo, "HEAD", "refs/heads/master", 1, NULL, NULL));
git_reference_free(ref);
cl_assert_equal_i(false, git_repository_head_detached(repo));
@@ -44,7 +44,7 @@ void test_repo_head__unborn_head(void)
/* take the repo back to it's original state */
- cl_git_pass(git_reference_symbolic_create(&ref, repo, "HEAD", "refs/heads/master", 1));
+ cl_git_pass(git_reference_symbolic_create(&ref, repo, "HEAD", "refs/heads/master", 1, NULL, NULL));
cl_assert(git_repository_head_unborn(repo) == 0);
git_reference_free(ref);
@@ -54,7 +54,7 @@ void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_
{
git_reference *head;
- cl_git_pass(git_repository_set_head(repo, "refs/heads/doesnt/exist/yet"));
+ cl_git_pass(git_repository_set_head(repo, "refs/heads/doesnt/exist/yet", NULL, NULL));
cl_assert_equal_i(false, git_repository_head_detached(repo));
@@ -63,19 +63,19 @@ void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_
void test_repo_head__set_head_Returns_ENOTFOUND_when_the_reference_doesnt_exist(void)
{
- cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head(repo, "refs/tags/doesnt/exist/yet"));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head(repo, "refs/tags/doesnt/exist/yet", NULL, NULL));
}
void test_repo_head__set_head_Fails_when_the_reference_points_to_a_non_commitish(void)
{
- cl_git_fail(git_repository_set_head(repo, "refs/tags/point_to_blob"));
+ cl_git_fail(git_repository_set_head(repo, "refs/tags/point_to_blob", NULL, NULL));
}
void test_repo_head__set_head_Attaches_HEAD_when_the_reference_points_to_a_branch(void)
{
git_reference *head;
- cl_git_pass(git_repository_set_head(repo, "refs/heads/br2"));
+ cl_git_pass(git_repository_set_head(repo, "refs/heads/br2", NULL, NULL));
cl_assert_equal_i(false, git_repository_head_detached(repo));
@@ -102,7 +102,7 @@ static void assert_head_is_correctly_detached(void)
void test_repo_head__set_head_Detaches_HEAD_when_the_reference_doesnt_point_to_a_branch(void)
{
- cl_git_pass(git_repository_set_head(repo, "refs/tags/test"));
+ cl_git_pass(git_repository_set_head(repo, "refs/tags/test", NULL, NULL));
cl_assert_equal_i(true, git_repository_head_detached(repo));
@@ -115,7 +115,7 @@ void test_repo_head__set_head_detached_Return_ENOTFOUND_when_the_object_doesnt_e
cl_git_pass(git_oid_fromstr(&oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head_detached(repo, &oid));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head_detached(repo, &oid, NULL, NULL));
}
void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish(void)
@@ -124,7 +124,7 @@ void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish(vo
cl_git_pass(git_revparse_single(&blob, repo, "point_to_blob"));
- cl_git_fail(git_repository_set_head_detached(repo, git_object_id(blob)));
+ cl_git_fail(git_repository_set_head_detached(repo, git_object_id(blob), NULL, NULL));
git_object_free(blob);
}
@@ -136,7 +136,7 @@ void test_repo_head__set_head_detached_Detaches_HEAD_and_make_it_point_to_the_pe
cl_git_pass(git_revparse_single(&tag, repo, "tags/test"));
cl_assert_equal_i(GIT_OBJ_TAG, git_object_type(tag));
- cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag)));
+ cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag), NULL, NULL));
assert_head_is_correctly_detached();
@@ -156,7 +156,7 @@ void test_repo_head__detach_head_Fails_if_HEAD_and_point_to_a_non_commitish(void
{
git_reference *head;
- cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, "refs/tags/point_to_blob", 1));
+ cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, "refs/tags/point_to_blob", 1, NULL, NULL));
cl_git_fail(git_repository_detach_head(repo));
@@ -194,3 +194,79 @@ void test_repo_head__can_tell_if_an_unborn_head_is_detached(void)
cl_assert_equal_i(false, git_repository_head_detached(repo));
}
+
+static void test_reflog(git_repository *repo, size_t idx,
+ const char *old_spec, const char *new_spec,
+ const char *email, const char *message)
+{
+ git_reflog *log;
+ git_reflog_entry *entry;
+
+ cl_git_pass(git_reflog_read(&log, repo, "HEAD"));
+ entry = git_reflog_entry_byindex(log, idx);
+
+ if (old_spec) {
+ git_object *obj;
+ cl_git_pass(git_revparse_single(&obj, repo, old_spec));
+ cl_assert_equal_i(0, git_oid_cmp(git_object_id(obj), git_reflog_entry_id_old(entry)));
+ git_object_free(obj);
+ }
+ if (new_spec) {
+ git_object *obj;
+ cl_git_pass(git_revparse_single(&obj, repo, new_spec));
+ cl_assert_equal_i(0, git_oid_cmp(git_object_id(obj), git_reflog_entry_id_new(entry)));
+ git_object_free(obj);
+ }
+
+ if (email) {
+ cl_assert_equal_s(email, git_reflog_entry_committer(entry)->email);
+ }
+ if (message) {
+ cl_assert_equal_s(message, git_reflog_entry_message(entry));
+ }
+
+ git_reflog_free(log);
+}
+
+void test_repo_head__setting_head_updates_reflog(void)
+{
+ git_object *tag;
+ git_signature *sig;
+
+ cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
+
+ cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", sig, "message1"));
+ cl_git_pass(git_repository_set_head(repo, "refs/heads/unborn", sig, "message2"));
+ cl_git_pass(git_revparse_single(&tag, repo, "tags/test"));
+ cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag), sig, "message3"));
+ cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", sig, "message4"));
+
+ test_reflog(repo, 3, NULL, "refs/heads/haacked", "foo@example.com", "message1");
+ test_reflog(repo, 2, "refs/heads/haacked", NULL, "foo@example.com", "message2");
+ test_reflog(repo, 1, NULL, "tags/test^{commit}", "foo@example.com", "message3");
+ test_reflog(repo, 0, "tags/test^{commit}", "refs/heads/haacked", "foo@example.com", "message4");
+
+ git_object_free(tag);
+ git_signature_free(sig);
+}
+
+void test_repo_head__setting_creates_head_ref(void)
+{
+ git_reference *head;
+ git_reflog *log;
+ const git_reflog_entry *entry;
+
+ cl_git_pass(git_reference_lookup(&head, repo, "HEAD"));
+ cl_git_pass(git_reference_delete(head));
+ cl_git_pass(git_reflog_delete(repo, "HEAD"));
+
+ cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", NULL, "create HEAD"));
+
+ cl_git_pass(git_reflog_read(&log, repo, "HEAD"));
+ cl_assert_equal_i(1, git_reflog_entrycount(log));
+ entry = git_reflog_entry_byindex(log, 0);
+ cl_assert_equal_s("create HEAD", git_reflog_entry_message(entry));
+
+ git_reflog_free(log);
+ git_reference_free(head);
+}
diff --git a/tests/repo/message.c b/tests/repo/message.c
index 629d40c12..57e8e5f4d 100644
--- a/tests/repo/message.c
+++ b/tests/repo/message.c
@@ -5,48 +5,37 @@
static git_repository *_repo;
static git_buf _path;
-static char *_actual;
+static git_buf _actual;
void test_repo_message__initialize(void)
{
_repo = cl_git_sandbox_init("testrepo.git");
+ git_buf_init(&_actual, 0);
}
void test_repo_message__cleanup(void)
{
cl_git_sandbox_cleanup();
git_buf_free(&_path);
- git__free(_actual);
- _actual = NULL;
+ git_buf_free(&_actual);
}
void test_repo_message__none(void)
{
- cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(&_actual, _repo));
}
void test_repo_message__message(void)
{
const char expected[] = "Test\n\nThis is a test of the emergency broadcast system\n";
- ssize_t len;
cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), "MERGE_MSG"));
cl_git_mkfile(git_buf_cstr(&_path), expected);
- len = git_repository_message(NULL, 0, _repo);
- cl_assert(len > 0);
-
- _actual = git__malloc(len + 1);
- cl_assert(_actual != NULL);
-
- /* Test non truncation */
- cl_assert(git_repository_message(_actual, len, _repo) > 0);
+ cl_git_pass(git_repository_message(&_actual, _repo));
cl_assert_equal_s(expected, _actual);
-
- /* Test truncation and that trailing NUL is inserted */
- cl_assert(git_repository_message(_actual, 6, _repo) > 0);
- cl_assert_equal_s("Test\n", _actual);
+ git_buf_free(&_actual);
cl_git_pass(p_unlink(git_buf_cstr(&_path)));
- cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(&_actual, _repo));
}
diff --git a/tests/repo/repo_helpers.c b/tests/repo/repo_helpers.c
index 3d477ff42..7c5db4a81 100644
--- a/tests/repo/repo_helpers.c
+++ b/tests/repo/repo_helpers.c
@@ -7,7 +7,7 @@ void make_head_unborn(git_repository* repo, const char *target)
{
git_reference *head;
- cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, target, 1));
+ cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, target, 1, NULL, NULL));
git_reference_free(head);
}
diff --git a/tests/reset/default.c b/tests/reset/default.c
index e29e63550..57a3f7c51 100644
--- a/tests/reset/default.c
+++ b/tests/reset/default.c
@@ -57,7 +57,7 @@ static void assert_content_in_index(
if (!expected_shas)
continue;
- cl_git_pass(git_oid_streq(&entry->oid, expected_shas->strings[i]));
+ cl_git_pass(git_oid_streq(&entry->id, expected_shas->strings[i]));
} else
cl_assert_equal_i(should_exist, error != GIT_ENOTFOUND);
}
diff --git a/tests/reset/hard.c b/tests/reset/hard.c
index 1c0c84135..0f80d32df 100644
--- a/tests/reset/hard.c
+++ b/tests/reset/hard.c
@@ -111,7 +111,7 @@ static void index_entry_init(git_index *index, int side, git_oid *oid)
entry.path = "conflicting_file";
entry.flags = (side << GIT_IDXENTRY_STAGESHIFT);
entry.mode = 0100644;
- git_oid_cpy(&entry.oid, oid);
+ git_oid_cpy(&entry.id, oid);
cl_git_pass(git_index_add(index, &entry));
}
diff --git a/tests/resources/crlf/.gitted/objects/2c/9a868cfdf8e270d0ec68164433376c68fb1789 b/tests/resources/crlf/.gitted/objects/2c/9a868cfdf8e270d0ec68164433376c68fb1789
new file mode 100644
index 000000000..218e9d192
--- /dev/null
+++ b/tests/resources/crlf/.gitted/objects/2c/9a868cfdf8e270d0ec68164433376c68fb1789
Binary files differ
diff --git a/tests/resources/crlf/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests/resources/crlf/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
new file mode 100644
index 000000000..711223894
--- /dev/null
+++ b/tests/resources/crlf/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
Binary files differ
diff --git a/tests/resources/crlf/.gitted/objects/ef/0dcd356d77221e9c27f4f3928ad28e80b87ceb b/tests/resources/crlf/.gitted/objects/ef/0dcd356d77221e9c27f4f3928ad28e80b87ceb
new file mode 100644
index 000000000..33aceda12
--- /dev/null
+++ b/tests/resources/crlf/.gitted/objects/ef/0dcd356d77221e9c27f4f3928ad28e80b87ceb
Binary files differ
diff --git a/tests/resources/crlf/.gitted/refs/heads/master b/tests/resources/crlf/.gitted/refs/heads/master
index a2dbe0c2d..cfdaaf37b 100644
--- a/tests/resources/crlf/.gitted/refs/heads/master
+++ b/tests/resources/crlf/.gitted/refs/heads/master
@@ -1 +1 @@
-12faf3c1ea55f572473cec9052fca468c3584ccb
+2c9a868cfdf8e270d0ec68164433376c68fb1789
diff --git a/tests/resources/merge-resolve/.gitted/config b/tests/resources/merge-resolve/.gitted/config
index af107929f..26c48426d 100644
--- a/tests/resources/merge-resolve/.gitted/config
+++ b/tests/resources/merge-resolve/.gitted/config
@@ -4,3 +4,5 @@
bare = false
logallrefupdates = true
ignorecase = true
+[submodule "submodule"]
+ url = ../submodule
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/HEAD b/tests/resources/merge-resolve/.gitted/modules/submodule/HEAD
new file mode 100644
index 000000000..cb089cd89
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/ORIG_HEAD b/tests/resources/merge-resolve/.gitted/modules/submodule/ORIG_HEAD
new file mode 100644
index 000000000..d1bfcf0f4
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/ORIG_HEAD
@@ -0,0 +1 @@
+ae39c77c70cb6bad18bb471912460c4e1ba0f586
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/config b/tests/resources/merge-resolve/.gitted/modules/submodule/config
new file mode 100644
index 000000000..575cc8599
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/config
@@ -0,0 +1,15 @@
+[core]
+ repositoryformatversion = 0
+ filemode = false
+ bare = false
+ logallrefupdates = true
+ worktree = ../../../submodule
+ symlinks = false
+ ignorecase = true
+ hideDotFiles = dotGitOnly
+[remote "origin"]
+ url = c:/Temp/TestRepos/submodule
+ fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "master"]
+ remote = origin
+ merge = refs/heads/master
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/index b/tests/resources/merge-resolve/.gitted/modules/submodule/index
new file mode 100644
index 000000000..e948afb27
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/index
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/info/exclude b/tests/resources/merge-resolve/.gitted/modules/submodule/info/exclude
new file mode 100644
index 000000000..a5196d1be
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/18/fae1354bba0a5f1e6a531f9988369142c24a9e b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/18/fae1354bba0a5f1e6a531f9988369142c24a9e
new file mode 100644
index 000000000..fcf1c6381
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/18/fae1354bba0a5f1e6a531f9988369142c24a9e
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/29/7aa6cd028b3336c7802c7a6f49143da4e1602d b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/29/7aa6cd028b3336c7802c7a6f49143da4e1602d
new file mode 100644
index 000000000..aa9fc5006
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/29/7aa6cd028b3336c7802c7a6f49143da4e1602d
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/38/6c80dc813b89d719797668f40c1be0a6efa996 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/38/6c80dc813b89d719797668f40c1be0a6efa996
new file mode 100644
index 000000000..bc9a32ebc
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/38/6c80dc813b89d719797668f40c1be0a6efa996
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ab/435a147bae6d5906ecfd0916a570c4ab3eeea8 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ab/435a147bae6d5906ecfd0916a570c4ab3eeea8
new file mode 100644
index 000000000..65a8d759f
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ab/435a147bae6d5906ecfd0916a570c4ab3eeea8
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ad/16e0a7684ea95bf892980a2ee412293ae979cc b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ad/16e0a7684ea95bf892980a2ee412293ae979cc
new file mode 100644
index 000000000..49e1aafeb
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ad/16e0a7684ea95bf892980a2ee412293ae979cc
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ae/39c77c70cb6bad18bb471912460c4e1ba0f586 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ae/39c77c70cb6bad18bb471912460c4e1ba0f586
new file mode 100644
index 000000000..6ceffdd4e
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/ae/39c77c70cb6bad18bb471912460c4e1ba0f586
@@ -0,0 +1,2 @@
+x¥ŽË !@=S hfù%Æx±†!ëÅ Æö]kðöò/{k©-âa] xW«s =,lÄP…‰
+Šë#g0KÈêIC¶© –ž–,5ù“1¡– ™9;aãlB«è=×>ô­|h}_{{õMŸe·?º¶þêuž¸·‹6˜Àšˆô"€Úí>:å„ʃ6^Õ¤±Kd \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/c2/0765f6e24e8bbb63a648d0d11d84da63170190 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/c2/0765f6e24e8bbb63a648d0d11d84da63170190
new file mode 100644
index 000000000..14781032f
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/c2/0765f6e24e8bbb63a648d0d11d84da63170190
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/d3/d806a4bef96889117fd7ebac0e3cb5ec152932 b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/d3/d806a4bef96889117fd7ebac0e3cb5ec152932
new file mode 100644
index 000000000..8df72a45c
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/d3/d806a4bef96889117fd7ebac0e3cb5ec152932
@@ -0,0 +1,3 @@
+x¥A
+Â0E]çse¦mÚDÜx½À$™Ò‚é@šâõgpóø¼ÅQs^+·§ZD€ÃÐ[¦a
+,c²G‰sBO#Û ãÀ¡v†ºhGúpIðZ4ïºÁUšý­{^cÑ]çz‰šo@½ÇŽ\çÎèM³-\å ó<BÖt¼æµÌ·ÈA› \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/objects/f1/065ff5593604072837fecaad3e2e268cb0147b b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/f1/065ff5593604072837fecaad3e2e268cb0147b
new file mode 100644
index 000000000..e0d73e1c2
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/objects/f1/065ff5593604072837fecaad3e2e268cb0147b
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/packed-refs b/tests/resources/merge-resolve/.gitted/modules/submodule/packed-refs
new file mode 100644
index 000000000..992c4eec6
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/packed-refs
@@ -0,0 +1,3 @@
+# pack-refs with: peeled
+297aa6cd028b3336c7802c7a6f49143da4e1602d refs/remotes/origin/master
+ae39c77c70cb6bad18bb471912460c4e1ba0f586 refs/remotes/origin/submodule-branch
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/refs/heads/master b/tests/resources/merge-resolve/.gitted/modules/submodule/refs/heads/master
new file mode 100644
index 000000000..fe282569b
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/refs/heads/master
@@ -0,0 +1 @@
+297aa6cd028b3336c7802c7a6f49143da4e1602d
diff --git a/tests/resources/merge-resolve/.gitted/modules/submodule/refs/remotes/origin/HEAD b/tests/resources/merge-resolve/.gitted/modules/submodule/refs/remotes/origin/HEAD
new file mode 100644
index 000000000..6efe28fff
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/modules/submodule/refs/remotes/origin/HEAD
@@ -0,0 +1 @@
+ref: refs/remotes/origin/master
diff --git a/tests/resources/merge-resolve/.gitted/objects/0f/3fc5dddc8964b9ac1040d0e957f9eb02d9efb3 b/tests/resources/merge-resolve/.gitted/objects/0f/3fc5dddc8964b9ac1040d0e957f9eb02d9efb3
new file mode 100644
index 000000000..d0ca42dad
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/0f/3fc5dddc8964b9ac1040d0e957f9eb02d9efb3
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00 b/tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00
new file mode 100644
index 000000000..90e729f6d
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85 b/tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85
new file mode 100644
index 000000000..9a21e26c0
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111ba b/tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111ba
new file mode 100644
index 000000000..06dee3b23
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111ba
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/27/4bbe983022fb4c02f8a2bf2ebe8da4fe130054 b/tests/resources/merge-resolve/.gitted/objects/27/4bbe983022fb4c02f8a2bf2ebe8da4fe130054
new file mode 100644
index 000000000..c7afad2a8
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/27/4bbe983022fb4c02f8a2bf2ebe8da4fe130054
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/2b/fdd7e1b6c6ae993f23dfe8e84a8e06a772fa2a b/tests/resources/merge-resolve/.gitted/objects/2b/fdd7e1b6c6ae993f23dfe8e84a8e06a772fa2a
new file mode 100644
index 000000000..c86edfb68
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/2b/fdd7e1b6c6ae993f23dfe8e84a8e06a772fa2a
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1e b/tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1e
new file mode 100644
index 000000000..fd61b6ce5
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1e
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/42/18670ab81cc219a9f94befb5c5dad90ec52648 b/tests/resources/merge-resolve/.gitted/objects/42/18670ab81cc219a9f94befb5c5dad90ec52648
new file mode 100644
index 000000000..33ead6112
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/42/18670ab81cc219a9f94befb5c5dad90ec52648
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/49/fd9edac79d15c8fbfca2d481cbb900beba22a6 b/tests/resources/merge-resolve/.gitted/objects/49/fd9edac79d15c8fbfca2d481cbb900beba22a6
new file mode 100644
index 000000000..d808d9fd9
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/49/fd9edac79d15c8fbfca2d481cbb900beba22a6
@@ -0,0 +1,3 @@
+xUÁ
+Â0D=ç+æ¼èÅ
+‚…þÆf»5dIŽ~¼ÑEhße3Ìó©xœ¯—ÓÍÀ2?ž®‡Ø°Å$Éô%+¢"SëRAºÂWRîm Kýn¸ä\t XZ/µŸhôº¥ÈÝMƱߙìþg2©»ñj># \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/58/87a5e516c53bd58efb0f02ec6aa031b6fe9ad7 b/tests/resources/merge-resolve/.gitted/objects/58/87a5e516c53bd58efb0f02ec6aa031b6fe9ad7
new file mode 100644
index 000000000..550d288d4
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/58/87a5e516c53bd58efb0f02ec6aa031b6fe9ad7
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/60/61fe116ecba0800c26113ea1a7dfac2e16eeaf b/tests/resources/merge-resolve/.gitted/objects/60/61fe116ecba0800c26113ea1a7dfac2e16eeaf
new file mode 100644
index 000000000..3f266f6df
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/60/61fe116ecba0800c26113ea1a7dfac2e16eeaf
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/62/33c6a0670228627f93c01cef32485a30403670 b/tests/resources/merge-resolve/.gitted/objects/62/33c6a0670228627f93c01cef32485a30403670
new file mode 100644
index 000000000..81428dd62
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/62/33c6a0670228627f93c01cef32485a30403670
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/67/110d77886b2af6309b9212961e72b8583e5fa9 b/tests/resources/merge-resolve/.gitted/objects/67/110d77886b2af6309b9212961e72b8583e5fa9
new file mode 100644
index 000000000..877bad703
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/67/110d77886b2af6309b9212961e72b8583e5fa9
@@ -0,0 +1 @@
+x¥=N1 „©÷î^rœ !J:.`'ûŠlP^×gâT3ú43Ò”Ñûuåp·¦*´Z£ %°ælÙÚ4irœÇH‰·žz,ê³¥ä[‰M]a“J©ÂÒbó5¤lÐ8OùX$XÕ³EaÇ")ŠUïœ$d2zO¸ñçÚÇ„—úųÂÛ>úmð¨'ýqÏýZ渶ÊèO`lF“³Oî1!n'=-ýÇÄöªó]A&e‡Ë¯^¶o––^Ý \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55 b/tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55
new file mode 100644
index 000000000..c6100cb01
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/72/cdb057b340205164478565e91eb71647e66891 b/tests/resources/merge-resolve/.gitted/objects/72/cdb057b340205164478565e91eb71647e66891
new file mode 100644
index 000000000..84aa8336b
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/72/cdb057b340205164478565e91eb71647e66891
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/7a/f14d9c679baaef35555095f4f5d33e9a569ab9 b/tests/resources/merge-resolve/.gitted/objects/7a/f14d9c679baaef35555095f4f5d33e9a569ab9
new file mode 100644
index 000000000..b4c4ef734
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/7a/f14d9c679baaef35555095f4f5d33e9a569ab9
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/7c/04ca611203ed320c5f495b9813054dd23be3be b/tests/resources/merge-resolve/.gitted/objects/7c/04ca611203ed320c5f495b9813054dd23be3be
new file mode 100644
index 000000000..e3ba6056d
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/7c/04ca611203ed320c5f495b9813054dd23be3be
@@ -0,0 +1,2 @@
+x¥ŽQ Dýæ{ -,tcüñ^`%õƒb(ÆëKÏà|ͼd&k)¯³±§ÞDÀsžl¢è<fɇ4a¶“1BŒŽ8zs“­CvƒÅ˜„ºEëQüd¡˜ÅO>åEñ§¯µÁ#}¹%x®µìuƒ« z¸{yÅV÷šû%ÖrƒÉžÇ†·pÖ¨µtíòÇ„
+·¸ÎêUrL \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/81/1c70fcb6d5bbd022d04cc31836d30b436f9551 b/tests/resources/merge-resolve/.gitted/objects/81/1c70fcb6d5bbd022d04cc31836d30b436f9551
new file mode 100644
index 000000000..6d8702404
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/81/1c70fcb6d5bbd022d04cc31836d30b436f9551
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19 b/tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19
new file mode 100644
index 000000000..99f828649
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/8b/7cd60d49ce3a1a770ece43b7d29b5cf462a33a b/tests/resources/merge-resolve/.gitted/objects/8b/7cd60d49ce3a1a770ece43b7d29b5cf462a33a
new file mode 100644
index 000000000..790750c0f
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/8b/7cd60d49ce3a1a770ece43b7d29b5cf462a33a
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/91/f44111cb1cb1358ac6944ad356ca1738813ea1 b/tests/resources/merge-resolve/.gitted/objects/91/f44111cb1cb1358ac6944ad356ca1738813ea1
new file mode 100644
index 000000000..51a456f42
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/91/f44111cb1cb1358ac6944ad356ca1738813ea1
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/96/bca8d4f05cc4c5e33e4389f80a1309e86fe054 b/tests/resources/merge-resolve/.gitted/objects/96/bca8d4f05cc4c5e33e4389f80a1309e86fe054
new file mode 100644
index 000000000..8938d3e56
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/96/bca8d4f05cc4c5e33e4389f80a1309e86fe054
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730 b/tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730
new file mode 100644
index 000000000..ae3ef8ce3
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/ad/26b598134264fd284292cb233fc0b2f25851da b/tests/resources/merge-resolve/.gitted/objects/ad/26b598134264fd284292cb233fc0b2f25851da
new file mode 100644
index 000000000..5819a2e25
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/ad/26b598134264fd284292cb233fc0b2f25851da
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/ca/ff6b7d44973f53e3e0cf31d0d695188b19aec6 b/tests/resources/merge-resolve/.gitted/objects/ca/ff6b7d44973f53e3e0cf31d0d695188b19aec6
new file mode 100644
index 000000000..6d0f60077
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/ca/ff6b7d44973f53e3e0cf31d0d695188b19aec6
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf1 b/tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf1
new file mode 100644
index 000000000..85b3b8112
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf1
@@ -0,0 +1,2 @@
+x¥ŽK!]sŠ¾€†æ3`bŒoà »ÉÌ1 Æë‹gpW©E½G­Öm€±x]“ˆ˜Èù6d
+ûƒçeaŽÎ‰ç¢µz¥.ϬŽDv Ù[êhŽ¥äD³[´Jﱶwþ¤ÎðX[ÝÛ.2ínu£ÞöVƉZ½Ú³F´!x8ê8÷¦G‡ü‘PÂÛP_’?KN \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/d3/3cedf513c059e0515653fa2c2e386631387a05 b/tests/resources/merge-resolve/.gitted/objects/d3/3cedf513c059e0515653fa2c2e386631387a05
new file mode 100644
index 000000000..d6d4c2b45
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/d3/3cedf513c059e0515653fa2c2e386631387a05
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b460 b/tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b460
new file mode 100644
index 000000000..b02cda4fa
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b460
@@ -0,0 +1 @@
+x¥K @]sŠ¹€†)ÐÄ7ÞÀ ð™¦]ÐI(Æx{ñ î^Þâ½,µnлSoÌ`¬/¹Xä)Ù™B@GžÃ”¸œaòD¼ «øê«4x”wlž«ÔCv¸ò°?º×-79dé—,õh‚F4Žœµ×Z ;ÆÿH¨´í±}Ô·š=  \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/d8/dec75ff2f8b41d1c5bfef0cd57b7300c834f66 b/tests/resources/merge-resolve/.gitted/objects/d8/dec75ff2f8b41d1c5bfef0cd57b7300c834f66
new file mode 100644
index 000000000..74f807e68
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/d8/dec75ff2f8b41d1c5bfef0cd57b7300c834f66
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/dd/2ae5ab264e5592aa754235d5ad5eac8f0ecdfd b/tests/resources/merge-resolve/.gitted/objects/dd/2ae5ab264e5592aa754235d5ad5eac8f0ecdfd
new file mode 100644
index 000000000..55626a57b
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/dd/2ae5ab264e5592aa754235d5ad5eac8f0ecdfd
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/e5/060729746ca9888239cba08fdcf4bee907b406 b/tests/resources/merge-resolve/.gitted/objects/e5/060729746ca9888239cba08fdcf4bee907b406
new file mode 100644
index 000000000..33299c2b0
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/e5/060729746ca9888239cba08fdcf4bee907b406
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/f2/e1550a0c9e53d5811175864a29536642ae3821 b/tests/resources/merge-resolve/.gitted/objects/f2/e1550a0c9e53d5811175864a29536642ae3821
new file mode 100644
index 000000000..1fdcbe22a
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/f2/e1550a0c9e53d5811175864a29536642ae3821
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/f6/65b45cde9b568009c6e6b7b568e89cfe717df8 b/tests/resources/merge-resolve/.gitted/objects/f6/65b45cde9b568009c6e6b7b568e89cfe717df8
new file mode 100644
index 000000000..7af50d7df
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/f6/65b45cde9b568009c6e6b7b568e89cfe717df8
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/submodules b/tests/resources/merge-resolve/.gitted/refs/heads/submodules
new file mode 100644
index 000000000..e5511eca9
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/refs/heads/submodules
@@ -0,0 +1 @@
+d8dec75ff2f8b41d1c5bfef0cd57b7300c834f66
diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch b/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch
new file mode 100644
index 000000000..7d47e07b8
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch
@@ -0,0 +1 @@
+811c70fcb6d5bbd022d04cc31836d30b436f9551
diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch2 b/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch2
new file mode 100644
index 000000000..ced60d813
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/refs/heads/submodules-branch2
@@ -0,0 +1 @@
+7c04ca611203ed320c5f495b9813054dd23be3be
diff --git a/tests/resources/revert/.gitted/index b/tests/resources/revert/.gitted/index
index 87419ff57..3513c04a6 100644
--- a/tests/resources/revert/.gitted/index
+++ b/tests/resources/revert/.gitted/index
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/0a/d19525be6d8cae5e5deb2770fc244b65255057 b/tests/resources/revert/.gitted/objects/0a/d19525be6d8cae5e5deb2770fc244b65255057
new file mode 100644
index 000000000..4aa0459d8
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/0a/d19525be6d8cae5e5deb2770fc244b65255057
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/13/a6fdfd10bd74b1f258fb58801215985dd2e797 b/tests/resources/revert/.gitted/objects/13/a6fdfd10bd74b1f258fb58801215985dd2e797
new file mode 100644
index 000000000..3c54aab0c
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/13/a6fdfd10bd74b1f258fb58801215985dd2e797
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/1b/c915c5cb7185a9438de28a7b1a7dfe8c01ee7f b/tests/resources/revert/.gitted/objects/1b/c915c5cb7185a9438de28a7b1a7dfe8c01ee7f
new file mode 100644
index 000000000..0a6955b5d
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/1b/c915c5cb7185a9438de28a7b1a7dfe8c01ee7f
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/1f/f0c423042b46cb1d617b81efb715defbe8054d b/tests/resources/revert/.gitted/objects/1f/f0c423042b46cb1d617b81efb715defbe8054d
new file mode 100644
index 000000000..2ed1a2292
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/1f/f0c423042b46cb1d617b81efb715defbe8054d
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/21/a96a98ed84d45866e1de6e266fd3a61a4ae9dc b/tests/resources/revert/.gitted/objects/21/a96a98ed84d45866e1de6e266fd3a61a4ae9dc
new file mode 100644
index 000000000..95842dbf8
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/21/a96a98ed84d45866e1de6e266fd3a61a4ae9dc
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/39/9fb3aba3d9d13f7d40a9254ce4402067ef3149 b/tests/resources/revert/.gitted/objects/39/9fb3aba3d9d13f7d40a9254ce4402067ef3149
new file mode 100644
index 000000000..6cb6839d6
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/39/9fb3aba3d9d13f7d40a9254ce4402067ef3149
@@ -0,0 +1,2 @@
+x¥ŽK!]s
+. á;@bŒoàzºA\0mŒ×Ïàª<äÖžC§£ç,3Ød@û ¢_ÑDò @§K6Å—5Tâ=oS$çT1«Õ.% @zªQ["-—D xÊ]Þèä½rÛy“ç<éo]Û;ï\Æ ¹]¤¶1YüåQE¥Ä¤óèÈ$l<ê,`…í‘ÅaGNÅ \ No newline at end of file
diff --git a/tests/resources/revert/.gitted/objects/46/ff0854663aeb2182b9838c8da68e33ac23bc1e b/tests/resources/revert/.gitted/objects/46/ff0854663aeb2182b9838c8da68e33ac23bc1e
new file mode 100644
index 000000000..7064dab52
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/46/ff0854663aeb2182b9838c8da68e33ac23bc1e
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/5c/f1d643f100d8112834e540264546ba2c159976 b/tests/resources/revert/.gitted/objects/5c/f1d643f100d8112834e540264546ba2c159976
new file mode 100644
index 000000000..dbbf711b5
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/5c/f1d643f100d8112834e540264546ba2c159976
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/6b/ccd0dc58cea5ccff86014f3d64b31bd8c02a37 b/tests/resources/revert/.gitted/objects/6b/ccd0dc58cea5ccff86014f3d64b31bd8c02a37
new file mode 100644
index 000000000..2664da480
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/6b/ccd0dc58cea5ccff86014f3d64b31bd8c02a37
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/71/eb9c2b53dbbf3c45fb28b27c850db4b7fb8011 b/tests/resources/revert/.gitted/objects/71/eb9c2b53dbbf3c45fb28b27c850db4b7fb8011
new file mode 100644
index 000000000..995a1e626
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/71/eb9c2b53dbbf3c45fb28b27c850db4b7fb8011
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/87/59ad453cf01cf7daf14e2a668f8218f9a678eb b/tests/resources/revert/.gitted/objects/87/59ad453cf01cf7daf14e2a668f8218f9a678eb
new file mode 100644
index 000000000..ab19acf83
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/87/59ad453cf01cf7daf14e2a668f8218f9a678eb
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/9a/95fd974e03c5b93828ceedd28755965b5d5c60 b/tests/resources/revert/.gitted/objects/9a/95fd974e03c5b93828ceedd28755965b5d5c60
new file mode 100644
index 000000000..bb93a34bb
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/9a/95fd974e03c5b93828ceedd28755965b5d5c60
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/a8/c86221b400b836010567cc3593db6e96c1a83a b/tests/resources/revert/.gitted/objects/a8/c86221b400b836010567cc3593db6e96c1a83a
new file mode 100644
index 000000000..29654616e
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/a8/c86221b400b836010567cc3593db6e96c1a83a
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/ac/c4d33902092efeb3b714aa0b1007c329e2f2e6 b/tests/resources/revert/.gitted/objects/ac/c4d33902092efeb3b714aa0b1007c329e2f2e6
new file mode 100644
index 000000000..91bb68b41
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/ac/c4d33902092efeb3b714aa0b1007c329e2f2e6
@@ -0,0 +1,2 @@
+xÍ[
+1 @QßJW‘ étÒ6 F,LâþWàßý8peé½ø1llU.LÊiT B‡<dQ­uȉˆ#MTI"ºò¶ç²Âv·?OçË7ঽ´ù>dN0z¸"!:ùMLÿ䮽š¹õ$Î \ No newline at end of file
diff --git a/tests/resources/revert/.gitted/objects/b6/9d88e177455579896e2be495046e2a51456a9a b/tests/resources/revert/.gitted/objects/b6/9d88e177455579896e2be495046e2a51456a9a
new file mode 100644
index 000000000..a5f69f2c8
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/b6/9d88e177455579896e2be495046e2a51456a9a
@@ -0,0 +1 @@
+x¥]j!…ûì*.yoÐÑ™{…RòÒ „l@½NF¨ZÔ´Ûï$Ù@¡o‡Ãù 5ç4@+z-FP¤œó2{ÞH¶n"³zƒZ‹R.<£´J|¹Ë€‰‘ëäµ2Èš:V’fRÚ ñ´Xžaánc« >øÇ5†ËVs¯ÞâNïê”Shµ×uCÍï 4Yk‹¯’¤;݇ŽøqŽß± 8„ZÖÏF*W›+×ØB\¶Ô¡=,žu¾w¿‡ödÞ \ No newline at end of file
diff --git a/tests/resources/revert/.gitted/objects/ca/f99de3a49827117bb66721010eac461b06a80c b/tests/resources/revert/.gitted/objects/ca/f99de3a49827117bb66721010eac461b06a80c
new file mode 100644
index 000000000..7f6f4e0c6
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/ca/f99de3a49827117bb66721010eac461b06a80c
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/de/03538407ed18914ff05657eeff70425c0f304d b/tests/resources/revert/.gitted/objects/de/03538407ed18914ff05657eeff70425c0f304d
new file mode 100644
index 000000000..e651676fd
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/de/03538407ed18914ff05657eeff70425c0f304d
@@ -0,0 +1,2 @@
+x¥Ž]J1„}Î)š}wéIw~D|ñ²H:vÀl–LÔë;ê|)Šú ª¤·¶M æPLeYuY}‰’Ô©+šmXÅ2g0‡.˜{z›,U…5’_¼'¬•ò!Ê‚5i!agÒǼö¯å+—ko{¿Á“é{i›Œ¾÷:ÏÒÛ3,×u H1"š#=ŽNýG…yÓONûÖîï
+Z¶y2ærÝv¿h‡¿(Ka¤b­dµìV[‚u•ÙFrRÙWõ(1ÉÙ|_c& \ No newline at end of file
diff --git a/tests/resources/revert/.gitted/objects/e3/4ef1afe54eb526fd92eec66084125f340f1d65 b/tests/resources/revert/.gitted/objects/e3/4ef1afe54eb526fd92eec66084125f340f1d65
new file mode 100644
index 000000000..fc19ebd3d
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/e3/4ef1afe54eb526fd92eec66084125f340f1d65
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/ea/392a157085bc32daccd59aa1998fe2f5fb9fc0 b/tests/resources/revert/.gitted/objects/ea/392a157085bc32daccd59aa1998fe2f5fb9fc0
new file mode 100644
index 000000000..1451a6ac4
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/ea/392a157085bc32daccd59aa1998fe2f5fb9fc0
Binary files differ
diff --git a/tests/resources/revert/.gitted/objects/ee/c6adcb2f3ceca0cadeccfe01b19382252ece9b b/tests/resources/revert/.gitted/objects/ee/c6adcb2f3ceca0cadeccfe01b19382252ece9b
new file mode 100644
index 000000000..f59f3d48d
--- /dev/null
+++ b/tests/resources/revert/.gitted/objects/ee/c6adcb2f3ceca0cadeccfe01b19382252ece9b
Binary files differ
diff --git a/tests/resources/revert/.gitted/refs/heads/master b/tests/resources/revert/.gitted/refs/heads/master
index d3850daa6..180f407e3 100644
--- a/tests/resources/revert/.gitted/refs/heads/master
+++ b/tests/resources/revert/.gitted/refs/heads/master
@@ -1 +1 @@
-2d440f2b3147d3dc7ad1085813478d6d869d5a4d
+2d440f2b3147d3dc7ad1085813478d6d869d5a4d
diff --git a/tests/resources/revert/.gitted/refs/heads/two b/tests/resources/revert/.gitted/refs/heads/two
new file mode 100644
index 000000000..f31ec00e5
--- /dev/null
+++ b/tests/resources/revert/.gitted/refs/heads/two
@@ -0,0 +1 @@
+e34ef1afe54eb526fd92eec66084125f340f1d65
diff --git a/tests/resources/testrepo/.gitted/objects/1d/d0968be3ff95fcaecb6fa4245662db9fdc4568 b/tests/resources/testrepo/.gitted/objects/1d/d0968be3ff95fcaecb6fa4245662db9fdc4568
new file mode 100644
index 000000000..97c6b2cfa
--- /dev/null
+++ b/tests/resources/testrepo/.gitted/objects/1d/d0968be3ff95fcaecb6fa4245662db9fdc4568
Binary files differ
diff --git a/tests/resources/testrepo/.gitted/objects/af/e4393b2b2a965f06acf2ca9658eaa01e0cd6b6 b/tests/resources/testrepo/.gitted/objects/af/e4393b2b2a965f06acf2ca9658eaa01e0cd6b6
new file mode 100644
index 000000000..6948f1b1c
--- /dev/null
+++ b/tests/resources/testrepo/.gitted/objects/af/e4393b2b2a965f06acf2ca9658eaa01e0cd6b6
Binary files differ
diff --git a/tests/resources/testrepo/.gitted/objects/ce/054d4c5e3c83522aed8bc061987b46b7ede3be b/tests/resources/testrepo/.gitted/objects/ce/054d4c5e3c83522aed8bc061987b46b7ede3be
new file mode 100644
index 000000000..4910e4c0a
--- /dev/null
+++ b/tests/resources/testrepo/.gitted/objects/ce/054d4c5e3c83522aed8bc061987b46b7ede3be
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/HEAD b/tests/resources/userdiff/.gitted/HEAD
new file mode 100644
index 000000000..cb089cd89
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/resources/userdiff/.gitted/config b/tests/resources/userdiff/.gitted/config
new file mode 100644
index 000000000..6c9406b7d
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/config
@@ -0,0 +1,7 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+ ignorecase = true
+ precomposeunicode = true
diff --git a/tests/resources/userdiff/.gitted/description b/tests/resources/userdiff/.gitted/description
new file mode 100644
index 000000000..498b267a8
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/tests/resources/userdiff/.gitted/index b/tests/resources/userdiff/.gitted/index
new file mode 100644
index 000000000..b69d5cfb1
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/index
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/info/refs b/tests/resources/userdiff/.gitted/info/refs
new file mode 100644
index 000000000..b0743141d
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/info/refs
@@ -0,0 +1 @@
+60e3f7b244a5305e2c9fa4ef0e897f3b14f3b8dd refs/heads/master
diff --git a/tests/resources/userdiff/.gitted/objects/info/packs b/tests/resources/userdiff/.gitted/objects/info/packs
new file mode 100644
index 000000000..0c5fc2a30
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/info/packs
@@ -0,0 +1,2 @@
+P pack-1652578900ac63564f2a24b9714529821276ceb9.pack
+
diff --git a/tests/resources/userdiff/.gitted/objects/pack/pack-1652578900ac63564f2a24b9714529821276ceb9.idx b/tests/resources/userdiff/.gitted/objects/pack/pack-1652578900ac63564f2a24b9714529821276ceb9.idx
new file mode 100644
index 000000000..6f4381cc7
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/pack/pack-1652578900ac63564f2a24b9714529821276ceb9.idx
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/objects/pack/pack-1652578900ac63564f2a24b9714529821276ceb9.pack b/tests/resources/userdiff/.gitted/objects/pack/pack-1652578900ac63564f2a24b9714529821276ceb9.pack
new file mode 100644
index 000000000..39bd1d8f0
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/objects/pack/pack-1652578900ac63564f2a24b9714529821276ceb9.pack
Binary files differ
diff --git a/tests/resources/userdiff/.gitted/packed-refs b/tests/resources/userdiff/.gitted/packed-refs
new file mode 100644
index 000000000..802f67ce0
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/packed-refs
@@ -0,0 +1,2 @@
+# pack-refs with: peeled fully-peeled
+60e3f7b244a5305e2c9fa4ef0e897f3b14f3b8dd refs/heads/master
diff --git a/tests/resources/userdiff/.gitted/refs/dummy-marker.txt b/tests/resources/userdiff/.gitted/refs/dummy-marker.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/resources/userdiff/.gitted/refs/dummy-marker.txt
diff --git a/tests/resources/userdiff/after/file.html b/tests/resources/userdiff/after/file.html
new file mode 100644
index 000000000..2320e2f1e
--- /dev/null
+++ b/tests/resources/userdiff/after/file.html
@@ -0,0 +1,41 @@
+<html>
+<body>
+ <h1 id="first section">
+ <ol>
+ <li>item 1.1</li>
+ <li>item 1.2 changed</li>
+ <li>item 1.3 changed</li>
+ <li>item 1.4</li>
+ <li>item 1.5</li>
+ <li>item 1.6</li>
+ <li>item 1.7</li>
+ <li>item 1.8</li>
+ <li>item 1.9</li>
+ <li>item 1.10 added</li>
+ </ol>
+ </h1>
+ <h1 id="second section">
+ <ol>
+ <li>item 2.1</li>
+ <li>item 2.2</li>
+ <li>item 2.3</li>
+ <li>item 2.4</li>
+ <li>item 2.5</li>
+ <li>item 2.6</li>
+ <li>item 2.7 changed</li>
+ <li>item 2.7.1 added</li>
+ <li>item 2.8</li>
+ </ol>
+ </h1>
+ <h1 id="third section">
+ <ol>
+ <li>item 3.1</li>
+ <li>item 3.2</li>
+ <li>item 3.3</li>
+ <li>item 3.4</li>
+ <li>item 3.5</li>
+ <li>item 3.6</li>
+ </ol>
+ </h1>
+</body>
+</html>
diff --git a/tests/resources/userdiff/after/file.javascript b/tests/resources/userdiff/after/file.javascript
new file mode 100644
index 000000000..7cd3c5a8a
--- /dev/null
+++ b/tests/resources/userdiff/after/file.javascript
@@ -0,0 +1,108 @@
+/*
+ Some code extracted from https://github.com/julianlloyd/scrollReveal.js
+ which happens to be a trending Javascript repo with an MIT license at
+ the time I was working on Javascript userdiff support in libgit2
+
+ I extracted just some of the code, so I suspect this is no longer valid
+ Javascript code, but it contains enough example patterns to work.
+*/
+;(function (window) {
+
+ 'use strict';
+
+ var docElem = window.document.documentElement;
+
+ function getViewportH () {
+ var client = docElem['clientHeight'],
+ inner = window['innerHeight'],
+ sample = window['otherProperty'];
+
+ return (client < inner) ? inner : client;
+ }
+
+ function getOffset (el) {
+ var offsetTop = 0,
+ offsetLeft = 0;
+
+ do {
+ if (!isNaN(el.offsetTop)) {
+ offsetTop += el.offsetTop + 1;
+ }
+ if (!isNaN(el.offsetLeft)) {
+ offsetLeft += el.offsetLeft;
+ }
+ } while (el = el.offsetParent)
+
+ return {
+ top: offsetTop,
+ left: offsetLeft
+ }
+ }
+
+ function isElementInViewport (el, h) {
+ var scrolled = window.pageYOffset,
+ viewed = scrolled + getViewportH(),
+ elTop = getOffset(el).top,
+ elBottom = elTop + el.offsetHeight,
+ h = h || 0;
+
+ return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
+ }
+
+ scrollReveal.prototype = {
+
+ _init: function () {
+
+ var self = this;
+
+ this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]'));
+ this.scrolled = false;
+
+ this.elems.forEach(function (el, i) {
+ self.animate(el);
+ });
+
+ var scrollHandler = function () {
+ if (!self.scrolled) {
+ self.scrolled = true;
+ setTimeout(function () {
+ self._scrollPage();
+ }, 61);
+ }
+ };
+
+ var resizeHandler = function () {
+ function delayed() {
+ self._scrollPage();
+ self.resizeTimeout = null;
+ }
+ if (self.resizeTimeout) {
+ clearTimeout(self.resizeTimeout);
+ }
+ self.resizeTimeout = setTimeout(delayed, 200);
+ };
+
+ window.addEventListener('scroll', scrollHandler, false);
+ window.addEventListener('resize', resizeHandler, false);
+ },
+
+ /*=============================================================================*/
+
+ _scrollPage: function () {
+ var self = this;
+
+ this.elems.forEach(function (el, i) {
+ if (isElementInViewport(el, self.options.viewportFactor)) {
+ self.animate(el);
+ }
+ });
+ this.scrolled = false;
+ this.tested = true;
+ },
+ }; // end scrollReveal.prototype
+
+ document.addEventListener("DOMContentLoaded", function (evt) {
+ window.scrollReveal = new scrollReveal();
+ });
+
+})(window);
diff --git a/tests/resources/userdiff/after/file.php b/tests/resources/userdiff/after/file.php
new file mode 100644
index 000000000..967d6466c
--- /dev/null
+++ b/tests/resources/userdiff/after/file.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Faker;
+
+/**
+ * Proxy for other generators, to return only unique values. Works with
+ * Faker\Generator\Base->unique()
+ */
+class UniqueGenerator
+{
+ protected $generator;
+ protected $maxRetries;
+ protected $moreStuff;
+ protected $uniques = array();
+
+ public function __construct(Generator $generator, $maxRetries)
+ {
+ $this->generator = $generator;
+ $this->maxRetries = $maxRetries + 1;
+ }
+
+ /**
+ * Catch and proxy all generator calls but return only unique values
+ */
+ public function __get($attribute)
+ {
+ return $this->__call($attribute, array());
+ }
+
+ /**
+ * Catch and proxy all generator calls with arguments but return only unique values
+ */
+ public function __call($name, $arguments)
+ {
+ $i = 0;
+ if (!isset($this->uniques[$name])) {
+ $this->uniques[$name] = array();
+ }
+ do {
+ $res = call_user_func_array(array($this->generator, $name), $arguments);
+ $i++;
+ if ($i >= $this->maxRetries) {
+ throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
+ }
+ } while (in_array($res, $this->uniques[$name]));
+ $this->uniques[$name][]= $res;
+
+ return $res;
+ }
+}
diff --git a/tests/resources/userdiff/before/file.html b/tests/resources/userdiff/before/file.html
new file mode 100644
index 000000000..872d19663
--- /dev/null
+++ b/tests/resources/userdiff/before/file.html
@@ -0,0 +1,41 @@
+<html>
+<body>
+ <h1 id="first section">
+ <ol>
+ <li>item 1.1</li>
+ <li>item 1.2</li>
+ <li>item 1.3</li>
+ <li>item 1.4</li>
+ <li>item 1.5</li>
+ <li>item 1.6</li>
+ <li>item 1.7</li>
+ <li>item 1.8</li>
+ <li>item 1.9</li>
+ </ol>
+ </h1>
+ <h1 id="second section">
+ <ol>
+ <li>item 2.1</li>
+ <li>item 2.2</li>
+ <li>item 2.3</li>
+ <li>item 2.4</li>
+ <li>item 2.5</li>
+ <li>item 2.6</li>
+ <li>item 2.7</li>
+ <li>item 2.8</li>
+ </ol>
+ </h1>
+ <h1 id="third section">
+ <ol>
+ <li>item 3.1</li>
+ <li>item 3.2</li>
+ <li>item 3.3</li>
+ <li>item 3.4</li>
+ <li>item 3.5</li>
+ <li>item 3.6</li>
+ <li>item 3.7</li>
+ <li>item 3.8</li>
+ </ol>
+ </h1>
+</body>
+</html>
diff --git a/tests/resources/userdiff/before/file.javascript b/tests/resources/userdiff/before/file.javascript
new file mode 100644
index 000000000..b9f1286e5
--- /dev/null
+++ b/tests/resources/userdiff/before/file.javascript
@@ -0,0 +1,109 @@
+/*
+ Some code extracted from https://github.com/julianlloyd/scrollReveal.js
+ which happens to be a trending Javascript repo with an MIT license at
+ the time I was working on Javascript userdiff support in libgit2
+
+ I extracted just some of the code, so I suspect this is no longer valid
+ Javascript code, but it contains enough example patterns to work.
+*/
+;(function (window) {
+
+ 'use strict';
+
+ var docElem = window.document.documentElement;
+
+ function getViewportH () {
+ var client = docElem['clientHeight'],
+ inner = window['innerHeight'];
+
+ return (client < inner) ? inner : client;
+ }
+
+ function getOffset (el) {
+ var offsetTop = 0,
+ offsetLeft = 0;
+
+ do {
+ if (!isNaN(el.offsetTop)) {
+ offsetTop += el.offsetTop;
+ }
+ if (!isNaN(el.offsetLeft)) {
+ offsetLeft += el.offsetLeft;
+ }
+ } while (el = el.offsetParent)
+
+ return {
+ top: offsetTop,
+ left: offsetLeft
+ }
+ }
+
+ function isElementInViewport (el, h) {
+ var scrolled = window.pageYOffset,
+ viewed = scrolled + getViewportH(),
+ elH = el.offsetHeight,
+ elTop = getOffset(el).top,
+ elBottom = elTop + elH,
+ h = h || 0;
+
+ return (elTop + elH * h) <= viewed && (elBottom) >= scrolled;
+ }
+
+ scrollReveal.prototype = {
+
+ _init: function () {
+
+ var self = this;
+
+ this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]'));
+ this.scrolled = false;
+
+ // Initialize all scrollreveals, triggering all
+ // reveals on visible elements.
+ this.elems.forEach(function (el, i) {
+ self.animate(el);
+ });
+
+ var scrollHandler = function () {
+ if (!self.scrolled) {
+ self.scrolled = true;
+ setTimeout(function () {
+ self._scrollPage();
+ }, 60);
+ }
+ };
+
+ var resizeHandler = function () {
+ function delayed() {
+ self._scrollPage();
+ self.resizeTimeout = null;
+ }
+ if (self.resizeTimeout) {
+ clearTimeout(self.resizeTimeout);
+ }
+ self.resizeTimeout = setTimeout(delayed, 200);
+ };
+
+ window.addEventListener('scroll', scrollHandler, false);
+ window.addEventListener('resize', resizeHandler, false);
+ },
+
+ /*=============================================================================*/
+
+ _scrollPage: function () {
+ var self = this;
+
+ this.elems.forEach(function (el, i) {
+ if (isElementInViewport(el, self.options.viewportFactor)) {
+ self.animate(el);
+ }
+ });
+ this.scrolled = false;
+ },
+ }; // end scrollReveal.prototype
+
+ document.addEventListener("DOMContentLoaded", function (evt) {
+ window.scrollReveal = new scrollReveal();
+ });
+
+})(window);
diff --git a/tests/resources/userdiff/before/file.php b/tests/resources/userdiff/before/file.php
new file mode 100644
index 000000000..63250ad01
--- /dev/null
+++ b/tests/resources/userdiff/before/file.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Faker;
+
+/**
+ * Proxy for other generators, to return only unique values. Works with
+ * Faker\Generator\Base->unique()
+ */
+class UniqueGenerator
+{
+ protected $generator;
+ protected $maxRetries;
+ protected $uniques = array();
+
+ public function __construct(Generator $generator, $maxRetries)
+ {
+ $this->generator = $generator;
+ $this->maxRetries = $maxRetries;
+ }
+
+ /**
+ * Catch and proxy all generator calls but return only unique values
+ */
+ public function __get($attribute)
+ {
+ return $this->__call($attribute, array());
+ }
+
+ /**
+ * Catch and proxy all generator calls with arguments but return only unique values
+ */
+ public function __call($name, $arguments)
+ {
+ if (!isset($this->uniques[$name])) {
+ $this->uniques[$name] = array();
+ }
+ $i = 0;
+ do {
+ $res = call_user_func_array(array($this->generator, $name), $arguments);
+ $i++;
+ if ($i > $this->maxRetries) {
+ throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
+ }
+ } while (in_array($res, $this->uniques[$name]));
+ $this->uniques[$name][]= $res;
+
+ return $res;
+ }
+}
diff --git a/tests/resources/userdiff/expected/driver/diff.html b/tests/resources/userdiff/expected/driver/diff.html
new file mode 100644
index 000000000..5a428e7dc
--- /dev/null
+++ b/tests/resources/userdiff/expected/driver/diff.html
@@ -0,0 +1,26 @@
+diff --git a/files/file.html b/files/file.html
+index 872d196..2320e2f 100644
+--- a/files/file.html
++++ b/files/file.html
+@@ -5,4 +5,4 @@ <h1 id="first section">
+ <li>item 1.1</li>
+- <li>item 1.2</li>
+- <li>item 1.3</li>
++ <li>item 1.2 changed</li>
++ <li>item 1.3 changed</li>
+ <li>item 1.4</li>
+@@ -13,2 +13,3 @@ <h1 id="first section">
+ <li>item 1.9</li>
++ <li>item 1.10 added</li>
+ </ol>
+@@ -23,3 +24,4 @@ <h1 id="second section">
+ <li>item 2.6</li>
+- <li>item 2.7</li>
++ <li>item 2.7 changed</li>
++ <li>item 2.7.1 added</li>
+ <li>item 2.8</li>
+@@ -35,4 +37,2 @@ <h1 id="third section">
+ <li>item 3.6</li>
+- <li>item 3.7</li>
+- <li>item 3.8</li>
+ </ol>
diff --git a/tests/resources/userdiff/expected/driver/diff.javascript b/tests/resources/userdiff/expected/driver/diff.javascript
new file mode 100644
index 000000000..4e65d0746
--- /dev/null
+++ b/tests/resources/userdiff/expected/driver/diff.javascript
@@ -0,0 +1,40 @@
+diff --git a/files/file.javascript b/files/file.javascript
+index b9f1286..7cd3c5a 100644
+--- a/files/file.javascript
++++ b/files/file.javascript
+@@ -16,3 +16,4 @@ function getViewportH ()
+ var client = docElem['clientHeight'],
+- inner = window['innerHeight'];
++ inner = window['innerHeight'],
++ sample = window['otherProperty'];
+
+@@ -27,3 +28,3 @@ function getOffset (el)
+ if (!isNaN(el.offsetTop)) {
+- offsetTop += el.offsetTop;
++ offsetTop += el.offsetTop + 1;
+ }
+@@ -43,8 +44,7 @@ function isElementInViewport (el, h)
+ viewed = scrolled + getViewportH(),
+- elH = el.offsetHeight,
+ elTop = getOffset(el).top,
+- elBottom = elTop + elH,
++ elBottom = elTop + el.offsetHeight,
+ h = h || 0;
+
+- return (elTop + elH * h) <= viewed && (elBottom) >= scrolled;
++ return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
+ }
+@@ -60,4 +60,2 @@ _init: function ()
+
+- // Initialize all scrollreveals, triggering all
+- // reveals on visible elements.
+ this.elems.forEach(function (el, i) {
+@@ -71,3 +69,3 @@ var scrollHandler = function ()
+ self._scrollPage();
+- }, 60);
++ }, 61);
+ }
+@@ -101,2 +99,3 @@ _scrollPage: function ()
+ this.scrolled = false;
++ this.tested = true;
+ },
diff --git a/tests/resources/userdiff/expected/driver/diff.php b/tests/resources/userdiff/expected/driver/diff.php
new file mode 100644
index 000000000..9711b5b3e
--- /dev/null
+++ b/tests/resources/userdiff/expected/driver/diff.php
@@ -0,0 +1,26 @@
+diff --git a/files/file.php b/files/file.php
+index 63250ad..967d646 100644
+--- a/files/file.php
++++ b/files/file.php
+@@ -12,2 +12,3 @@ class UniqueGenerator
+ protected $maxRetries;
++ protected $moreStuff;
+ protected $uniques = array();
+@@ -17,3 +18,3 @@ public function __construct(Generator $generator, $maxRetries)
+ $this->generator = $generator;
+- $this->maxRetries = $maxRetries;
++ $this->maxRetries = $maxRetries + 1;
+ }
+@@ -33,10 +34,10 @@ public function __call($name, $arguments)
+ {
++ $i = 0;
+ if (!isset($this->uniques[$name])) {
+ $this->uniques[$name] = array();
+ }
+- $i = 0;
+ do {
+ $res = call_user_func_array(array($this->generator, $name), $arguments);
+ $i++;
+- if ($i > $this->maxRetries) {
++ if ($i >= $this->maxRetries) {
+ throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
diff --git a/tests/resources/userdiff/expected/nodriver/diff.html b/tests/resources/userdiff/expected/nodriver/diff.html
new file mode 100644
index 000000000..2ea4b8a16
--- /dev/null
+++ b/tests/resources/userdiff/expected/nodriver/diff.html
@@ -0,0 +1,26 @@
+diff --git a/files/file.html b/files/file.html
+index 872d196..2320e2f 100644
+--- a/files/file.html
++++ b/files/file.html
+@@ -5,4 +5,4 @@
+ <li>item 1.1</li>
+- <li>item 1.2</li>
+- <li>item 1.3</li>
++ <li>item 1.2 changed</li>
++ <li>item 1.3 changed</li>
+ <li>item 1.4</li>
+@@ -13,2 +13,3 @@
+ <li>item 1.9</li>
++ <li>item 1.10 added</li>
+ </ol>
+@@ -23,3 +24,4 @@
+ <li>item 2.6</li>
+- <li>item 2.7</li>
++ <li>item 2.7 changed</li>
++ <li>item 2.7.1 added</li>
+ <li>item 2.8</li>
+@@ -35,4 +37,2 @@
+ <li>item 3.6</li>
+- <li>item 3.7</li>
+- <li>item 3.8</li>
+ </ol>
diff --git a/tests/resources/userdiff/expected/nodriver/diff.javascript b/tests/resources/userdiff/expected/nodriver/diff.javascript
new file mode 100644
index 000000000..69afe4fd8
--- /dev/null
+++ b/tests/resources/userdiff/expected/nodriver/diff.javascript
@@ -0,0 +1,40 @@
+diff --git a/files/file.javascript b/files/file.javascript
+index b9f1286..7cd3c5a 100644
+--- a/files/file.javascript
++++ b/files/file.javascript
+@@ -16,3 +16,4 @@
+ var client = docElem['clientHeight'],
+- inner = window['innerHeight'];
++ inner = window['innerHeight'],
++ sample = window['otherProperty'];
+
+@@ -27,3 +28,3 @@
+ if (!isNaN(el.offsetTop)) {
+- offsetTop += el.offsetTop;
++ offsetTop += el.offsetTop + 1;
+ }
+@@ -43,8 +44,7 @@
+ viewed = scrolled + getViewportH(),
+- elH = el.offsetHeight,
+ elTop = getOffset(el).top,
+- elBottom = elTop + elH,
++ elBottom = elTop + el.offsetHeight,
+ h = h || 0;
+
+- return (elTop + elH * h) <= viewed && (elBottom) >= scrolled;
++ return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
+ }
+@@ -60,4 +60,2 @@
+
+- // Initialize all scrollreveals, triggering all
+- // reveals on visible elements.
+ this.elems.forEach(function (el, i) {
+@@ -71,3 +69,3 @@
+ self._scrollPage();
+- }, 60);
++ }, 61);
+ }
+@@ -101,2 +99,3 @@
+ this.scrolled = false;
++ this.tested = true;
+ },
diff --git a/tests/resources/userdiff/expected/nodriver/diff.php b/tests/resources/userdiff/expected/nodriver/diff.php
new file mode 100644
index 000000000..e77c094aa
--- /dev/null
+++ b/tests/resources/userdiff/expected/nodriver/diff.php
@@ -0,0 +1,26 @@
+diff --git a/files/file.php b/files/file.php
+index 63250ad..967d646 100644
+--- a/files/file.php
++++ b/files/file.php
+@@ -12,2 +12,3 @@ class UniqueGenerator
+ protected $maxRetries;
++ protected $moreStuff;
+ protected $uniques = array();
+@@ -17,3 +18,3 @@ class UniqueGenerator
+ $this->generator = $generator;
+- $this->maxRetries = $maxRetries;
++ $this->maxRetries = $maxRetries + 1;
+ }
+@@ -33,10 +34,10 @@ class UniqueGenerator
+ {
++ $i = 0;
+ if (!isset($this->uniques[$name])) {
+ $this->uniques[$name] = array();
+ }
+- $i = 0;
+ do {
+ $res = call_user_func_array(array($this->generator, $name), $arguments);
+ $i++;
+- if ($i > $this->maxRetries) {
++ if ($i >= $this->maxRetries) {
+ throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
diff --git a/tests/resources/userdiff/files/file.html b/tests/resources/userdiff/files/file.html
new file mode 100644
index 000000000..2320e2f1e
--- /dev/null
+++ b/tests/resources/userdiff/files/file.html
@@ -0,0 +1,41 @@
+<html>
+<body>
+ <h1 id="first section">
+ <ol>
+ <li>item 1.1</li>
+ <li>item 1.2 changed</li>
+ <li>item 1.3 changed</li>
+ <li>item 1.4</li>
+ <li>item 1.5</li>
+ <li>item 1.6</li>
+ <li>item 1.7</li>
+ <li>item 1.8</li>
+ <li>item 1.9</li>
+ <li>item 1.10 added</li>
+ </ol>
+ </h1>
+ <h1 id="second section">
+ <ol>
+ <li>item 2.1</li>
+ <li>item 2.2</li>
+ <li>item 2.3</li>
+ <li>item 2.4</li>
+ <li>item 2.5</li>
+ <li>item 2.6</li>
+ <li>item 2.7 changed</li>
+ <li>item 2.7.1 added</li>
+ <li>item 2.8</li>
+ </ol>
+ </h1>
+ <h1 id="third section">
+ <ol>
+ <li>item 3.1</li>
+ <li>item 3.2</li>
+ <li>item 3.3</li>
+ <li>item 3.4</li>
+ <li>item 3.5</li>
+ <li>item 3.6</li>
+ </ol>
+ </h1>
+</body>
+</html>
diff --git a/tests/resources/userdiff/files/file.javascript b/tests/resources/userdiff/files/file.javascript
new file mode 100644
index 000000000..7cd3c5a8a
--- /dev/null
+++ b/tests/resources/userdiff/files/file.javascript
@@ -0,0 +1,108 @@
+/*
+ Some code extracted from https://github.com/julianlloyd/scrollReveal.js
+ which happens to be a trending Javascript repo with an MIT license at
+ the time I was working on Javascript userdiff support in libgit2
+
+ I extracted just some of the code, so I suspect this is no longer valid
+ Javascript code, but it contains enough example patterns to work.
+*/
+;(function (window) {
+
+ 'use strict';
+
+ var docElem = window.document.documentElement;
+
+ function getViewportH () {
+ var client = docElem['clientHeight'],
+ inner = window['innerHeight'],
+ sample = window['otherProperty'];
+
+ return (client < inner) ? inner : client;
+ }
+
+ function getOffset (el) {
+ var offsetTop = 0,
+ offsetLeft = 0;
+
+ do {
+ if (!isNaN(el.offsetTop)) {
+ offsetTop += el.offsetTop + 1;
+ }
+ if (!isNaN(el.offsetLeft)) {
+ offsetLeft += el.offsetLeft;
+ }
+ } while (el = el.offsetParent)
+
+ return {
+ top: offsetTop,
+ left: offsetLeft
+ }
+ }
+
+ function isElementInViewport (el, h) {
+ var scrolled = window.pageYOffset,
+ viewed = scrolled + getViewportH(),
+ elTop = getOffset(el).top,
+ elBottom = elTop + el.offsetHeight,
+ h = h || 0;
+
+ return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
+ }
+
+ scrollReveal.prototype = {
+
+ _init: function () {
+
+ var self = this;
+
+ this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]'));
+ this.scrolled = false;
+
+ this.elems.forEach(function (el, i) {
+ self.animate(el);
+ });
+
+ var scrollHandler = function () {
+ if (!self.scrolled) {
+ self.scrolled = true;
+ setTimeout(function () {
+ self._scrollPage();
+ }, 61);
+ }
+ };
+
+ var resizeHandler = function () {
+ function delayed() {
+ self._scrollPage();
+ self.resizeTimeout = null;
+ }
+ if (self.resizeTimeout) {
+ clearTimeout(self.resizeTimeout);
+ }
+ self.resizeTimeout = setTimeout(delayed, 200);
+ };
+
+ window.addEventListener('scroll', scrollHandler, false);
+ window.addEventListener('resize', resizeHandler, false);
+ },
+
+ /*=============================================================================*/
+
+ _scrollPage: function () {
+ var self = this;
+
+ this.elems.forEach(function (el, i) {
+ if (isElementInViewport(el, self.options.viewportFactor)) {
+ self.animate(el);
+ }
+ });
+ this.scrolled = false;
+ this.tested = true;
+ },
+ }; // end scrollReveal.prototype
+
+ document.addEventListener("DOMContentLoaded", function (evt) {
+ window.scrollReveal = new scrollReveal();
+ });
+
+})(window);
diff --git a/tests/resources/userdiff/files/file.php b/tests/resources/userdiff/files/file.php
new file mode 100644
index 000000000..967d6466c
--- /dev/null
+++ b/tests/resources/userdiff/files/file.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Faker;
+
+/**
+ * Proxy for other generators, to return only unique values. Works with
+ * Faker\Generator\Base->unique()
+ */
+class UniqueGenerator
+{
+ protected $generator;
+ protected $maxRetries;
+ protected $moreStuff;
+ protected $uniques = array();
+
+ public function __construct(Generator $generator, $maxRetries)
+ {
+ $this->generator = $generator;
+ $this->maxRetries = $maxRetries + 1;
+ }
+
+ /**
+ * Catch and proxy all generator calls but return only unique values
+ */
+ public function __get($attribute)
+ {
+ return $this->__call($attribute, array());
+ }
+
+ /**
+ * Catch and proxy all generator calls with arguments but return only unique values
+ */
+ public function __call($name, $arguments)
+ {
+ $i = 0;
+ if (!isset($this->uniques[$name])) {
+ $this->uniques[$name] = array();
+ }
+ do {
+ $res = call_user_func_array(array($this->generator, $name), $arguments);
+ $i++;
+ if ($i >= $this->maxRetries) {
+ throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
+ }
+ } while (in_array($res, $this->uniques[$name]));
+ $this->uniques[$name][]= $res;
+
+ return $res;
+ }
+}
diff --git a/tests/revert/workdir.c b/tests/revert/workdir.c
index 9dc72a9a8..5be397c93 100644
--- a/tests/revert/workdir.c
+++ b/tests/revert/workdir.c
@@ -137,6 +137,203 @@ void test_revert_workdir__orphan(void)
git_commit_free(head);
}
+/*
+ * revert the same commit twice (when the first reverts cleanly):
+ *
+ * git revert 2d440f2
+ * git revert 2d440f2
+ */
+void test_revert_workdir__again(void)
+{
+ git_reference *head_ref;
+ git_commit *orig_head;
+ git_tree *reverted_tree;
+ git_oid reverted_tree_oid, reverted_commit_oid;
+ git_signature *signature;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "7731926a337c4eaba1e2187d90ebfa0a93659382", 0, "file1.txt" },
+ { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
+ { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
+ { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
+ };
+
+ cl_git_pass(git_repository_head(&head_ref, repo));
+ cl_git_pass(git_reference_peel((git_object **)&orig_head, head_ref, GIT_OBJ_COMMIT));
+ cl_git_pass(git_reset(repo, (git_object *)orig_head, GIT_RESET_HARD));
+
+ cl_git_pass(git_revert(repo, orig_head, NULL));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ cl_git_pass(git_index_write_tree(&reverted_tree_oid, repo_index));
+ cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid));
+
+ cl_git_pass(git_signature_new(&signature, "Reverter", "reverter@example.org", time(NULL), 0));
+ cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&orig_head));
+
+ cl_git_pass(git_revert(repo, orig_head, NULL));
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ git_signature_free(signature);
+ git_tree_free(reverted_tree);
+ git_commit_free(orig_head);
+ git_reference_free(head_ref);
+}
+
+/* git reset --hard 72333f47d4e83616630ff3b0ffe4c0faebcc3c45
+ * git revert --no-commit d1d403d22cbe24592d725f442835cf46fe60c8ac */
+void test_revert_workdir__again_after_automerge(void)
+{
+ git_commit *head, *commit;
+ git_tree *reverted_tree;
+ git_oid head_oid, revert_oid, reverted_tree_oid, reverted_commit_oid;
+ git_signature *signature;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 0, "file1.txt" },
+ { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
+ { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
+ { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
+ };
+
+ struct merge_index_entry second_revert_entries[] = {
+ { 0100644, "3a3ef367eaf3fe79effbfb0a56b269c04c2b59fe", 1, "file1.txt" },
+ { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 2, "file1.txt" },
+ { 0100644, "747726e021bc5f44b86de60e3032fd6f9f1b8383", 3, "file1.txt" },
+ { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
+ { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
+ { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
+ };
+
+ git_oid_fromstr(&head_oid, "72333f47d4e83616630ff3b0ffe4c0faebcc3c45");
+ cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
+ cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD));
+
+ git_oid_fromstr(&revert_oid, "d1d403d22cbe24592d725f442835cf46fe60c8ac");
+ cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
+ cl_git_pass(git_revert(repo, commit, NULL));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ cl_git_pass(git_index_write_tree(&reverted_tree_oid, repo_index));
+ cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid));
+
+ cl_git_pass(git_signature_new(&signature, "Reverter", "reverter@example.org", time(NULL), 0));
+ cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&head));
+
+ cl_git_pass(git_revert(repo, commit, NULL));
+ cl_assert(merge_test_index(repo_index, second_revert_entries, 6));
+
+ git_signature_free(signature);
+ git_tree_free(reverted_tree);
+ git_commit_free(commit);
+ git_commit_free(head);
+}
+
+/*
+ * revert the same commit twice (when the first reverts cleanly):
+ *
+ * git revert 2d440f2
+ * git revert 2d440f2
+ */
+void test_revert_workdir__again_after_edit(void)
+{
+ git_reference *head_ref;
+ git_commit *orig_head, *commit;
+ git_tree *reverted_tree;
+ git_oid orig_head_oid, revert_oid, reverted_tree_oid, reverted_commit_oid;
+ git_signature *signature;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "3721552e06c4bdc7d478e0674e6304888545d5fd", 0, "file1.txt" },
+ { 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
+ { 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
+ { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
+ };
+
+ cl_git_pass(git_repository_head(&head_ref, repo));
+
+ cl_git_pass(git_oid_fromstr(&orig_head_oid, "399fb3aba3d9d13f7d40a9254ce4402067ef3149"));
+ cl_git_pass(git_commit_lookup(&orig_head, repo, &orig_head_oid));
+ cl_git_pass(git_reset(repo, (git_object *)orig_head, GIT_RESET_HARD));
+
+ cl_git_pass(git_oid_fromstr(&revert_oid, "2d440f2b3147d3dc7ad1085813478d6d869d5a4d"));
+ cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
+
+ cl_git_pass(git_revert(repo, commit, NULL));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ cl_git_pass(git_index_write_tree(&reverted_tree_oid, repo_index));
+ cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid));
+
+ cl_git_pass(git_signature_new(&signature, "Reverter", "reverter@example.org", time(NULL), 0));
+ cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&orig_head));
+
+ cl_git_pass(git_revert(repo, commit, NULL));
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
+
+ git_signature_free(signature);
+ git_tree_free(reverted_tree);
+ git_commit_free(commit);
+ git_commit_free(orig_head);
+ git_reference_free(head_ref);
+}
+
+/*
+ * revert the same commit twice (when the first reverts cleanly):
+ *
+ * git reset --hard e34ef1a
+ * git revert 71eb9c2
+ */
+void test_revert_workdir__again_after_edit_two(void)
+{
+ git_buf diff_buf = GIT_BUF_INIT;
+ git_config *config;
+ git_oid head_commit_oid, revert_commit_oid;
+ git_commit *head_commit, *revert_commit;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "1ff0c423042b46cb1d617b81efb715defbe8054d", 0, ".gitattributes" },
+ { 0100644, "1bc915c5cb7185a9438de28a7b1a7dfe8c01ee7f", 0, ".gitignore" },
+ { 0100644, "a8c86221b400b836010567cc3593db6e96c1a83a", 1, "file.txt" },
+ { 0100644, "46ff0854663aeb2182b9838c8da68e33ac23bc1e", 2, "file.txt" },
+ { 0100644, "21a96a98ed84d45866e1de6e266fd3a61a4ae9dc", 3, "file.txt" },
+ };
+
+ cl_git_pass(git_repository_config(&config, repo));
+ cl_git_pass(git_config_set_bool(config, "core.autocrlf", 0));
+
+ cl_git_pass(git_oid_fromstr(&head_commit_oid, "e34ef1afe54eb526fd92eec66084125f340f1d65"));
+ cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_oid));
+ cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD));
+
+ cl_git_pass(git_oid_fromstr(&revert_commit_oid, "71eb9c2b53dbbf3c45fb28b27c850db4b7fb8011"));
+ cl_git_pass(git_commit_lookup(&revert_commit, repo, &revert_commit_oid));
+
+ cl_git_pass(git_revert(repo, revert_commit, NULL));
+
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 5));
+
+ cl_git_pass(git_futils_readbuffer(&diff_buf, "revert/file.txt"));
+ cl_assert(strcmp(diff_buf.ptr, "a\n" \
+ "<<<<<<< HEAD\n" \
+ "=======\n" \
+ "a\n" \
+ ">>>>>>> parent of 71eb9c2... revert me\n" \
+ "a\n" \
+ "a\n" \
+ "a\n" \
+ "a\n" \
+ "ab\n") == 0);
+
+ git_commit_free(revert_commit);
+ git_commit_free(head_commit);
+ git_config_free(config);
+ git_buf_free(&diff_buf);
+}
+
/* git reset --hard 72333f47d4e83616630ff3b0ffe4c0faebcc3c45
* git revert --no-commit d1d403d22cbe24592d725f442835cf46fe60c8ac */
void test_revert_workdir__conflict_use_ours(void)
@@ -146,22 +343,19 @@ void test_revert_workdir__conflict_use_ours(void)
git_revert_opts opts = GIT_REVERT_OPTS_INIT;
struct merge_index_entry merge_index_entries[] = {
- { 0100644, "3a3ef367eaf3fe79effbfb0a56b269c04c2b59fe", 1, "file1.txt" },
- { 0100644, "7731926a337c4eaba1e2187d90ebfa0a93659382", 2, "file1.txt" },
- { 0100644, "747726e021bc5f44b86de60e3032fd6f9f1b8383", 3, "file1.txt" },
+ { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 0, "file1.txt" },
{ 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
{ 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
{ 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
};
struct merge_index_entry merge_filesystem_entries[] = {
- { 0100644, "7731926a337c4eaba1e2187d90ebfa0a93659382", 0, "file1.txt" },
+ { 0100644, "caf99de3a49827117bb66721010eac461b06a80c", 0, "file1.txt" },
{ 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
{ 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
{ 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
};
- opts.merge_tree_opts.automerge_flags = GIT_MERGE_AUTOMERGE_NONE;
opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS;
git_oid_fromstr(&head_oid, "72333f47d4e83616630ff3b0ffe4c0faebcc3c45");
@@ -172,7 +366,7 @@ void test_revert_workdir__conflict_use_ours(void)
cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
cl_git_pass(git_revert(repo, commit, &opts));
- cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
+ cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
cl_assert(merge_test_workdir(repo, merge_filesystem_entries, 4));
git_commit_free(commit);
diff --git a/tests/revwalk/basic.c b/tests/revwalk/basic.c
index 6d55aed54..9fe8a350b 100644
--- a/tests/revwalk/basic.c
+++ b/tests/revwalk/basic.c
@@ -252,3 +252,41 @@ void test_revwalk_basic__push_range(void)
cl_git_pass(git_revwalk_push_range(_walk, "9fd738e~2..9fd738e"));
cl_git_pass(test_walk_only(_walk, commit_sorting_segment, 1));
}
+
+void test_revwalk_basic__push_mixed(void)
+{
+ git_oid oid;
+ int i = 0;
+
+ revwalk_basic_setup_walk(NULL);
+
+ git_revwalk_reset(_walk);
+ git_revwalk_sorting(_walk, 0);
+ cl_git_pass(git_revwalk_push_glob(_walk, "tags"));
+
+ while (git_revwalk_next(&oid, _walk) == 0) {
+ i++;
+ }
+
+ /* git rev-list --count --glob=tags #=> 9 */
+ cl_assert_equal_i(9, i);
+}
+
+void test_revwalk_basic__push_all(void)
+{
+ git_oid oid;
+ int i = 0;
+
+ revwalk_basic_setup_walk(NULL);
+
+ git_revwalk_reset(_walk);
+ git_revwalk_sorting(_walk, 0);
+ cl_git_pass(git_revwalk_push_glob(_walk, "*"));
+
+ while (git_revwalk_next(&oid, _walk) == 0) {
+ i++;
+ }
+
+ /* git rev-list --count --all #=> 15 */
+ cl_assert_equal_i(15, i);
+}
diff --git a/tests/stash/save.c b/tests/stash/save.c
index 3d92b26bd..293a89a97 100644
--- a/tests/stash/save.c
+++ b/tests/stash/save.c
@@ -174,7 +174,7 @@ void test_stash_save__cannot_stash_against_an_unborn_branch(void)
{
git_reference *head;
- cl_git_pass(git_reference_symbolic_create(&head, repo, "HEAD", "refs/heads/unborn", 1));
+ cl_git_pass(git_reference_symbolic_create(&head, repo, "HEAD", "refs/heads/unborn", 1, NULL, NULL));
cl_assert_equal_i(GIT_EUNBORNBRANCH,
git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT));
diff --git a/tests/status/renames.c b/tests/status/renames.c
index 16fd02676..df5e23087 100644
--- a/tests/status/renames.c
+++ b/tests/status/renames.c
@@ -555,3 +555,30 @@ void test_status_renames__both_casechange_two(void)
git_index_free(index);
}
+
+void test_status_renames__zero_byte_file_does_not_fail(void)
+{
+ git_status_list *statuslist;
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+
+ struct status_entry expected[] = {
+ { GIT_STATUS_WT_DELETED, "ikeepsix.txt", "ikeepsix.txt" },
+ { GIT_STATUS_WT_NEW, "zerobyte.txt", "zerobyte.txt" },
+ };
+
+ opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES |
+ GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |
+ GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR |
+ GIT_STATUS_OPT_INCLUDE_IGNORED |
+ GIT_STATUS_OPT_INCLUDE_UNTRACKED |
+ GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS |
+ GIT_STATUS_SHOW_INDEX_AND_WORKDIR |
+ GIT_STATUS_OPT_RECURSE_IGNORED_DIRS;
+
+ p_unlink("renames/ikeepsix.txt");
+ cl_git_mkfile("renames/zerobyte.txt", "");
+
+ cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts));
+ test_status(statuslist, expected, 2);
+ git_status_list_free(statuslist);
+}
diff --git a/tests/status/submodules.c b/tests/status/submodules.c
index ef2888f7d..80ff162fd 100644
--- a/tests/status/submodules.c
+++ b/tests/status/submodules.c
@@ -140,7 +140,7 @@ void test_status_submodules__moved_head(void)
/* move submodule HEAD to c47800c7266a2be04c571c04d5a6614691ea99bd */
cl_git_pass(
git_oid_fromstr(&oid, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
- cl_git_pass(git_repository_set_head_detached(smrepo, &oid));
+ cl_git_pass(git_repository_set_head_detached(smrepo, &oid, NULL, NULL));
/* first do a normal status, which should now include the submodule */
@@ -221,3 +221,20 @@ void test_status_submodules__dirty_workdir_only(void)
git_status_foreach_ext(g_repo, &opts, cb_status__match, &counts));
cl_assert_equal_i(6, counts.entry_count);
}
+
+void test_status_submodules__uninitialized(void)
+{
+ git_repository *cloned_repo;
+ git_status_list *statuslist;
+
+ g_repo = cl_git_sandbox_init("submod2");
+
+ cl_git_pass(git_clone(&cloned_repo, "submod2", "submod2-clone", NULL));
+
+ cl_git_pass(git_status_list_new(&statuslist, cloned_repo, NULL));
+ cl_assert_equal_i(0, git_status_list_entrycount(statuslist));
+
+ git_status_list_free(statuslist);
+ git_repository_free(cloned_repo);
+ cl_git_sandbox_cleanup();
+}
diff --git a/tests/status/worktree.c b/tests/status/worktree.c
index fd57fcc1e..def3d60f0 100644
--- a/tests/status/worktree.c
+++ b/tests/status/worktree.c
@@ -455,15 +455,15 @@ void test_status_worktree__conflict_with_diff3(void)
memset(&their_entry, 0x0, sizeof(git_index_entry));
ancestor_entry.path = "modified_file";
- git_oid_fromstr(&ancestor_entry.oid,
+ git_oid_fromstr(&ancestor_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
our_entry.path = "modified_file";
- git_oid_fromstr(&our_entry.oid,
+ git_oid_fromstr(&our_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
their_entry.path = "modified_file";
- git_oid_fromstr(&their_entry.oid,
+ git_oid_fromstr(&their_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
cl_git_pass(git_status_file(&status, repo, "modified_file"));
@@ -605,15 +605,15 @@ void test_status_worktree__conflicted_item(void)
memset(&their_entry, 0x0, sizeof(git_index_entry));
ancestor_entry.path = "modified_file";
- git_oid_fromstr(&ancestor_entry.oid,
+ git_oid_fromstr(&ancestor_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
our_entry.path = "modified_file";
- git_oid_fromstr(&our_entry.oid,
+ git_oid_fromstr(&our_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
their_entry.path = "modified_file";
- git_oid_fromstr(&their_entry.oid,
+ git_oid_fromstr(&their_entry.id,
"452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
cl_git_pass(git_status_file(&status, repo, "modified_file"));
diff --git a/tests/submodule/lookup.c b/tests/submodule/lookup.c
index 5f320e702..ac3fa0415 100644
--- a/tests/submodule/lookup.c
+++ b/tests/submodule/lookup.c
@@ -108,7 +108,7 @@ void test_submodule_lookup__lookup_even_with_unborn_head(void)
/* put us on an unborn branch */
cl_git_pass(git_reference_symbolic_create(
- &head, g_repo, "HEAD", "refs/heads/garbage", 1));
+ &head, g_repo, "HEAD", "refs/heads/garbage", 1, NULL, NULL));
git_reference_free(head);
/* lookup existing */
diff --git a/tests/submodule/modify.c b/tests/submodule/modify.c
index 8ec9fceb0..e3e4d8aed 100644
--- a/tests/submodule/modify.c
+++ b/tests/submodule/modify.c
@@ -178,25 +178,28 @@ void test_submodule_modify__edit_and_save(void)
cl_git_pass(git_submodule_set_url(sm1, SM_LIBGIT2_URL));
old_ignore = git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_UNTRACKED);
old_update = git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_REBASE);
- old_fetchrecurse = git_submodule_set_fetch_recurse_submodules(sm1, GIT_SUBMODULE_RECURSE_YES);
+ old_fetchrecurse = git_submodule_set_fetch_recurse_submodules(
+ sm1, GIT_SUBMODULE_RECURSE_YES);
cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1));
cl_assert_equal_i(
- (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1));
+ GIT_SUBMODULE_IGNORE_UNTRACKED, git_submodule_ignore(sm1));
cl_assert_equal_i(
- (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1));
- cl_assert_equal_i(GIT_SUBMODULE_RECURSE_YES, git_submodule_fetch_recurse_submodules(sm1));
+ GIT_SUBMODULE_UPDATE_REBASE, git_submodule_update(sm1));
+ cl_assert_equal_i(
+ GIT_SUBMODULE_RECURSE_YES, git_submodule_fetch_recurse_submodules(sm1));
/* revert without saving (and confirm setters return old value) */
cl_git_pass(git_submodule_set_url(sm1, old_url));
cl_assert_equal_i(
- (int)GIT_SUBMODULE_IGNORE_UNTRACKED,
- (int)git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET));
+ GIT_SUBMODULE_IGNORE_UNTRACKED,
+ git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET));
cl_assert_equal_i(
- (int)GIT_SUBMODULE_UPDATE_REBASE,
- (int)git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET));
+ GIT_SUBMODULE_UPDATE_REBASE,
+ git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET));
cl_assert_equal_i(
- GIT_SUBMODULE_RECURSE_YES, git_submodule_set_fetch_recurse_submodules(sm1, old_fetchrecurse));
+ GIT_SUBMODULE_RECURSE_YES, git_submodule_set_fetch_recurse_submodules(
+ sm1, GIT_SUBMODULE_RECURSE_RESET));
/* check that revert was successful */
cl_assert_equal_s(old_url, git_submodule_url(sm1));
@@ -243,19 +246,22 @@ void test_submodule_modify__edit_and_save(void)
cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm2));
cl_assert_equal_i(
- (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm2));
+ GIT_SUBMODULE_IGNORE_UNTRACKED, git_submodule_ignore(sm2));
cl_assert_equal_i(
- (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm2));
- cl_assert_equal_i(GIT_SUBMODULE_RECURSE_YES, git_submodule_fetch_recurse_submodules(sm2));
+ GIT_SUBMODULE_UPDATE_REBASE, git_submodule_update(sm2));
+ cl_assert_equal_i(
+ GIT_SUBMODULE_RECURSE_NO, git_submodule_fetch_recurse_submodules(sm2));
/* set fetchRecurseSubmodules on-demand */
cl_git_pass(git_submodule_reload(sm1));
git_submodule_set_fetch_recurse_submodules(sm1, GIT_SUBMODULE_RECURSE_ONDEMAND);
- cl_assert_equal_i(GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1));
+ cl_assert_equal_i(
+ GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1));
/* call save */
cl_git_pass(git_submodule_save(sm1));
cl_git_pass(git_submodule_reload(sm1));
- cl_assert_equal_i(GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1));
+ cl_assert_equal_i(
+ GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1));
git_repository_free(r2);
git__free(old_url);
diff --git a/tests/threads/refdb.c b/tests/threads/refdb.c
index 3c651e341..fbf6ac09b 100644
--- a/tests/threads/refdb.c
+++ b/tests/threads/refdb.c
@@ -58,7 +58,7 @@ void test_threads_refdb__iterator(void)
for (r = 0; r < 200; ++r) {
snprintf(name, sizeof(name), "refs/heads/direct-%03d", r);
- cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0));
+ cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0, NULL, NULL));
git_reference_free(ref);
}
@@ -102,7 +102,7 @@ static void *create_refs(void *arg)
for (i = 0; i < 10; ++i) {
snprintf(name, sizeof(name), "refs/heads/thread-%03d-%02d", *id, i);
- cl_git_pass(git_reference_create(&ref[i], g_repo, name, &head, 0));
+ cl_git_pass(git_reference_create(&ref[i], g_repo, name, &head, 0, NULL, NULL));
if (i == 5) {
git_refdb *refdb;
@@ -165,7 +165,7 @@ void test_threads_refdb__edit_while_iterate(void)
for (r = 0; r < 50; ++r) {
snprintf(name, sizeof(name), "refs/heads/starter-%03d", r);
- cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0));
+ cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0, NULL, NULL));
git_reference_free(ref);
}