From 867a36f3a67d0d1905572b84a3e44093fcac643b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 14 Jul 2014 14:35:01 -0400 Subject: [PATCH 01/21] Introduce git_rebase to set up a rebase session Introduce `git_rebase` to set up a rebase session that can then be continued. Immediately, only merge-type rebase is supported. --- include/git2/errors.h | 1 + include/git2/rebase.h | 73 ++++ src/merge.c | 25 +- src/rebase.c | 332 ++++++++++++++++++ src/repository.c | 22 ++ src/repository.h | 2 + tests/rebase/setup.c | 328 +++++++++++++++++ tests/resources/rebase/.gitted/HEAD | Bin 0 -> 23 bytes tests/resources/rebase/.gitted/config | Bin 0 -> 75 bytes tests/resources/rebase/.gitted/index | Bin 0 -> 488 bytes tests/resources/rebase/.gitted/info/exclude | Bin 0 -> 240 bytes tests/resources/rebase/.gitted/logs/HEAD | Bin 0 -> 182 bytes .../00/66204dd469ee930e551fbcf123f98e211c99ce | Bin 0 -> 806 bytes .../00/f1b9a0948a7d5d14405eba6030efcdfbb8ff4a | Bin 0 -> 173 bytes .../01/3cc32d341bab0e6f039f50f153c18986f16c58 | Bin 0 -> 175 bytes .../01/a17f7d154ab5bf9f8bfede3d82dd00ddf7e7dc | Bin 0 -> 370 bytes .../02/2d3b6bbd0bfbdf147319476fb8bf405691cb0d | Bin 0 -> 208 bytes .../0e/f2e2b2a2b8d6e1f8dff5e621e0eca21b693d0c | Bin 0 -> 207 bytes .../0f/5f6d3353be1a9966fa5767b7d604b051798224 | Bin 0 -> 183 bytes .../11/fac10ca1b9318ce361a0be0c3d889d777e299c | Bin 0 -> 208 bytes .../12/c084412b952396962eb420716df01022b847cc | Bin 0 -> 176 bytes .../12/f28ed978639d331269d9dc2b74e87db58e1057 | Bin 0 -> 178 bytes .../19/14d57ddf6c5c997664521cc94f190df46dc1c2 | Bin 0 -> 277 bytes .../1b/1d19799fcc89fa3cb821581fcf7f2e8fd2cc4d | Bin 0 -> 178 bytes .../1f/2214c1b13b134d5508f41f6a3b77cc6a8f5182 | Bin 0 -> 209 bytes .../20/db906c85e78c6dde82eb2ec6d3231c4b96fce8 | Bin 0 -> 796 bytes .../22/adb22bef75a0371e85ff6d82e5e60e4b425501 | Bin 0 -> 380 bytes .../2a/a3ce842094e08ebac152b3d6d5b0fff39f9c6e | Bin 0 -> 175 bytes .../2b/4ebffd3111546d278bb5df62e5630930b605fb | Bin 0 -> 208 bytes .../30/69cc907e6294623e5917ef6de663928c1febfb | Bin 0 -> 174 bytes .../32/52a0692ace4c4c709f22011227d9dc4845f289 | Bin 0 -> 209 bytes .../33/f915f9e4dbd9f4b24430e48731a59b45b15500 | Bin 0 -> 186 bytes .../34/86a9d4cdf0b7b4a702c199eed541dc3af13a03 | Bin 0 -> 271 bytes .../3c/33b080bf75724c8899d8e703614cb59bfbd047 | Bin 0 -> 208 bytes .../3d/a85aca38a95b44d77ef55a8deb445e49ba19b4 | Bin 0 -> 55 bytes .../3e/8989b5a16d5258c935d998ef0e6bb139cc4757 | Bin 0 -> 174 bytes .../3f/05a038dd89f51ba2b3d7b14ba1f8c00f0e31ac | Bin 0 -> 209 bytes .../3f/d8d53cf02de539b9a25a5941030451f76a152f | Bin 0 -> 89 bytes .../40/0d89e8ee6cd91b67b1f45de1ca190e1c580c6f | Bin 0 -> 174 bytes .../41/4dfc71ead79c07acd4ea47fecf91f289afc4b9 | Bin 0 -> 376 bytes .../41/c5a0a761bb4a7670924c1af0800b30fe9a21be | Bin 0 -> 384 bytes .../42/cdad903aef3e7b614675e6584a8be417941911 | Bin 0 -> 208 bytes .../44/c801fe026abbc141b52a4dec5df15fa98249c6 | Bin 0 -> 367 bytes .../4b/21eb6eeeec7f8fc89a1d334faff9bd5f5f8c34 | Bin 0 -> 185 bytes .../4b/7c5650008b2e747fe1809eeb5a1dde0e80850a | Bin 0 -> 615 bytes .../4b/ed71df7017283cac61bbf726197ad6a5a18b84 | Bin 0 -> 175 bytes .../4c/acc6f6e740a5bc64faa33e04b8ef0733d8a127 | Bin 0 -> 169 bytes .../4f/b698bde45d7d2833e3f2aacfbfe8a7e7f60a65 | Bin 0 -> 208 bytes .../53/f75e45a463033854e52fa8d39dc858e45537d0 | Bin 0 -> 209 bytes .../58/8e5d2f04d49707fe4aab865e1deacaf7ef6787 | Bin 0 -> 171 bytes .../5b/1e8bccf7787e942aecf61912f94a2c274f85a5 | Bin 0 -> 368 bytes .../60/29cb003b59f710f9a8ebd9da9ece2d73070b69 | Bin 0 -> 655 bytes .../61/30e5fcbdce2aa8b3cfd84706c58a892e7d8dd0 | Bin 0 -> 208 bytes .../63/c18bf188b8a1ab0bad85161dc3fb43c48ed0db | Bin 0 -> 208 bytes .../67/ed7afb256807556f9b74fa4f7c9284aaec1120 | Bin 0 -> 391 bytes .../68/af1fc7407fd9addf1701a87eb1c95c7494c598 | Bin 0 -> 443 bytes .../68/f6182f4c85d39e1309d97c7e456156dc9c0096 | Bin 0 -> 755 bytes .../6c/8e16469b6ca09a07e00f0e07a5143c31dcfb64 | Bin 0 -> 380 bytes .../6d/77ce8fa2cd93c6489236e33e45e35203ca748c | Bin 0 -> 54 bytes .../6d/fb87d20f3dbca02da4a39890114fd9ba6a51e7 | Bin 0 -> 364 bytes .../73/f346c88d965227a03c0af8d555870b8c5021d4 | Bin 0 -> 89 bytes .../74/0a804e8963759c98e5b8cb912e15ae74a7a4a6 | Bin 0 -> 207 bytes .../78/c320b06544e23d786a9ec84ee93861f2933094 | Bin 0 -> 55 bytes .../79/e28694aae0d3064b06f96a5207b943a2357f07 | Bin 0 -> 287 bytes .../7a/05900f340af0252aaa4e34941f040c5d2fe7f7 | Bin 0 -> 176 bytes .../7a/677f6201c8f9d46bdfe1f4b08cb504e360a34e | Bin 0 -> 208 bytes .../7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f | Bin 0 -> 198 bytes .../7f/37fe2d7320360f8a9118b1ed8fba6f38481679 | Bin 0 -> 176 bytes .../80/32d630f37266bace093e353f7b97d7f8b20950 | Bin 0 -> 209 bytes .../80/dce0e74f0534811db734a68c23b49f98584d7a | Bin 0 -> 373 bytes .../83/53b9f9deff7c707f280e0f656c80772cca7cd9 | Bin 0 -> 283 bytes .../85/258e426a341cc1aa035ac7f6d18f84fed2ab38 | Bin 0 -> 208 bytes .../85/f34ce9ca9e0f33d4146afec9cbe5a26757500a | Bin 0 -> 185 bytes .../86/a5415741ed3754ccb0cac1fc19fd82587840a4 | Bin 0 -> 634 bytes .../8d/1f13f93c4995760ac07d129246ac1ff64c0be9 | Bin 0 -> 173 bytes .../8d/95ea62e621f1d38d230d9e7d206e41096d76af | Bin 0 -> 773 bytes .../8f/4de6c781b9ff9cedfd7f9f9f224e744f97b259 | Bin 0 -> 89 bytes .../92/54a37fde7e97f9a28dee2967fdb2c5d1ed94e9 | Bin 0 -> 388 bytes .../95/39b2cc291d6a6b1b266df8474d31fdd344dd79 | Bin 0 -> 173 bytes .../9a/8535dfcaf7554c728d874f047c5461fb2c71d1 | Bin 0 -> 208 bytes .../9c/d483e7da23819d7f71d24e9843812337886753 | Bin 0 -> 284 bytes .../a0/1a6ee390f65d834375e072952deaee0c5e92f7 | Bin 0 -> 90 bytes .../a0/fa65f96c1e3bdc7287e334229279dcc1248fa4 | Bin 0 -> 373 bytes .../a1/25b9b655932711abceaf8962948e6b601d67b6 | Bin 0 -> 89 bytes .../a7/00acc970eccccc73be53cd269462176544e6d1 | Bin 0 -> 373 bytes .../a7/b066537e6be7109abfe4ff97b675d4e077da20 | Bin 0 -> 621 bytes .../aa/4c42aecdfc7cd989bbc3209934ea7cda3f4d88 | Bin 0 -> 137 bytes .../ab/25a53ef5622d443ecb0492b7516725f0deac8f | Bin 0 -> 208 bytes .../ae/87cae12879a3c37d7cc994afc6395bcb0eaf99 | Bin 0 -> 209 bytes .../b1/46bd7608eac53d9bf9e1a6963543588b555c64 | Bin 0 -> 174 bytes .../b1/b94ec02f8ed87d0efa4c65fb38d5d6da7e8b32 | Bin 0 -> 208 bytes .../b6/72b141d48c369fee6c4deeb32a904387594365 | Bin 0 -> 174 bytes .../b7/c536a5883c8adaeb34d5e198c5a3dbbdc608b5 | Bin 0 -> 209 bytes .../b9/f72b9158fa8c49fb4e4c10b26817ed867be803 | Bin 0 -> 210 bytes .../bc/cc8eabb5cfe2ec09959c7f4155aa73429fd604 | Bin 0 -> 207 bytes .../c4/e6cca3ec6ae0148ed231f97257df8c311e015f | Bin 0 -> 268 bytes .../c5/17380440ed78865ffe3fa130b9738615c76618 | Bin 0 -> 649 bytes .../d6/16d97082eb7bb2dc6f180a7cca940993b7a56f | Bin 0 -> 170 bytes .../d6/b9ec0dfb972a6815ace42545cde5f2631cd776 | Bin 0 -> 790 bytes .../da/82b3a60c50cf5ac524ec3000d743447329465d | Bin 0 -> 369 bytes .../da/9c51a23d02d931a486f45ad18cda05cf5d2b94 | Bin 0 -> 170 bytes .../df/d3d25264693fcd7348ad286f3c34f3f6b30918 | Bin 0 -> 177 bytes .../e4/f809f826c1a9fc929874bc0e4644dd2f2a1af4 | Bin 0 -> 175 bytes .../e5/2ff405da5b7e1e9b0929939fa8405d81fe8a45 | Bin 0 -> 176 bytes .../e8/8cc0a6919a74599ce8e1dcb81eb2bbae33a645 | Bin 0 -> 208 bytes .../e9/5f47e016dcc70b0b888df8e40e97b8aabafd4c | Bin 0 -> 279 bytes .../e9/f22c10ffb378446c0bbcab7ee3d9d5a0040672 | Bin 0 -> 280 bytes .../ec/725f5639730640f91cd0be5f2d6d7ac5d69c79 | Bin 0 -> 377 bytes .../ee/23c5eeedadf8595c0ff60a366d970a165e373d | Bin 0 -> 372 bytes .../ee/f0edde5daa94da5f297d4ddb5dfbc1980f0902 | Bin 0 -> 55 bytes .../ef/ad0b11c47cb2f0220cbd6f5b0f93bb99064b00 | Bin 0 -> 177 bytes .../f5/56d5fef35003561dc0b64b37057d7541239105 | Bin 0 -> 90 bytes .../f6/3fa37e285bd11b0a7b48fa584a4091814a3ada | Bin 0 -> 55 bytes .../f7/5c193a1df47186727179f24867bc4d27a8991f | Bin 0 -> 802 bytes .../f8/7d14a4a236582a0278a916340a793714256864 | Bin 0 -> 174 bytes .../fc/e0584b379f535e50e036db587db71884ea6b36 | Bin 0 -> 281 bytes .../ff/b36e513f5fdf8a6ba850a20142676a2ac4807d | Bin 0 -> 355 bytes .../ff/dfa89389040a87008c4ab1834120d3046daaea | Bin 0 -> 208 bytes .../rebase/.gitted/refs/heads/asparagus | Bin 0 -> 41 bytes .../rebase/.gitted/refs/heads/barley | Bin 0 -> 41 bytes .../resources/rebase/.gitted/refs/heads/beef | Bin 0 -> 41 bytes .../rebase/.gitted/refs/heads/dried_pea | Bin 0 -> 41 bytes .../resources/rebase/.gitted/refs/heads/gravy | Bin 0 -> 41 bytes .../rebase/.gitted/refs/heads/master | Bin 0 -> 41 bytes .../resources/rebase/.gitted/refs/heads/veal | Bin 0 -> 41 bytes tests/resources/rebase/asparagus.txt | Bin 0 -> 587 bytes tests/resources/rebase/beef.txt | Bin 0 -> 1372 bytes tests/resources/rebase/bouilli.txt | Bin 0 -> 1092 bytes tests/resources/rebase/gravy.txt | Bin 0 -> 390 bytes tests/resources/rebase/oyster.txt | Bin 0 -> 774 bytes tests/resources/rebase/veal.txt | Bin 0 -> 1095 bytes 131 files changed, 759 insertions(+), 24 deletions(-) create mode 100644 include/git2/rebase.h create mode 100644 src/rebase.c create mode 100644 tests/rebase/setup.c create mode 100644 tests/resources/rebase/.gitted/HEAD create mode 100644 tests/resources/rebase/.gitted/config create mode 100644 tests/resources/rebase/.gitted/index create mode 100644 tests/resources/rebase/.gitted/info/exclude create mode 100644 tests/resources/rebase/.gitted/logs/HEAD create mode 100644 tests/resources/rebase/.gitted/objects/00/66204dd469ee930e551fbcf123f98e211c99ce create mode 100644 tests/resources/rebase/.gitted/objects/00/f1b9a0948a7d5d14405eba6030efcdfbb8ff4a create mode 100644 tests/resources/rebase/.gitted/objects/01/3cc32d341bab0e6f039f50f153c18986f16c58 create mode 100644 tests/resources/rebase/.gitted/objects/01/a17f7d154ab5bf9f8bfede3d82dd00ddf7e7dc create mode 100644 tests/resources/rebase/.gitted/objects/02/2d3b6bbd0bfbdf147319476fb8bf405691cb0d create mode 100644 tests/resources/rebase/.gitted/objects/0e/f2e2b2a2b8d6e1f8dff5e621e0eca21b693d0c create mode 100644 tests/resources/rebase/.gitted/objects/0f/5f6d3353be1a9966fa5767b7d604b051798224 create mode 100644 tests/resources/rebase/.gitted/objects/11/fac10ca1b9318ce361a0be0c3d889d777e299c create mode 100644 tests/resources/rebase/.gitted/objects/12/c084412b952396962eb420716df01022b847cc create mode 100644 tests/resources/rebase/.gitted/objects/12/f28ed978639d331269d9dc2b74e87db58e1057 create mode 100644 tests/resources/rebase/.gitted/objects/19/14d57ddf6c5c997664521cc94f190df46dc1c2 create mode 100644 tests/resources/rebase/.gitted/objects/1b/1d19799fcc89fa3cb821581fcf7f2e8fd2cc4d create mode 100644 tests/resources/rebase/.gitted/objects/1f/2214c1b13b134d5508f41f6a3b77cc6a8f5182 create mode 100644 tests/resources/rebase/.gitted/objects/20/db906c85e78c6dde82eb2ec6d3231c4b96fce8 create mode 100644 tests/resources/rebase/.gitted/objects/22/adb22bef75a0371e85ff6d82e5e60e4b425501 create mode 100644 tests/resources/rebase/.gitted/objects/2a/a3ce842094e08ebac152b3d6d5b0fff39f9c6e create mode 100644 tests/resources/rebase/.gitted/objects/2b/4ebffd3111546d278bb5df62e5630930b605fb create mode 100644 tests/resources/rebase/.gitted/objects/30/69cc907e6294623e5917ef6de663928c1febfb create mode 100644 tests/resources/rebase/.gitted/objects/32/52a0692ace4c4c709f22011227d9dc4845f289 create mode 100644 tests/resources/rebase/.gitted/objects/33/f915f9e4dbd9f4b24430e48731a59b45b15500 create mode 100644 tests/resources/rebase/.gitted/objects/34/86a9d4cdf0b7b4a702c199eed541dc3af13a03 create mode 100644 tests/resources/rebase/.gitted/objects/3c/33b080bf75724c8899d8e703614cb59bfbd047 create mode 100644 tests/resources/rebase/.gitted/objects/3d/a85aca38a95b44d77ef55a8deb445e49ba19b4 create mode 100644 tests/resources/rebase/.gitted/objects/3e/8989b5a16d5258c935d998ef0e6bb139cc4757 create mode 100644 tests/resources/rebase/.gitted/objects/3f/05a038dd89f51ba2b3d7b14ba1f8c00f0e31ac create mode 100644 tests/resources/rebase/.gitted/objects/3f/d8d53cf02de539b9a25a5941030451f76a152f create mode 100644 tests/resources/rebase/.gitted/objects/40/0d89e8ee6cd91b67b1f45de1ca190e1c580c6f create mode 100644 tests/resources/rebase/.gitted/objects/41/4dfc71ead79c07acd4ea47fecf91f289afc4b9 create mode 100644 tests/resources/rebase/.gitted/objects/41/c5a0a761bb4a7670924c1af0800b30fe9a21be create mode 100644 tests/resources/rebase/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911 create mode 100644 tests/resources/rebase/.gitted/objects/44/c801fe026abbc141b52a4dec5df15fa98249c6 create mode 100644 tests/resources/rebase/.gitted/objects/4b/21eb6eeeec7f8fc89a1d334faff9bd5f5f8c34 create mode 100644 tests/resources/rebase/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850a create mode 100644 tests/resources/rebase/.gitted/objects/4b/ed71df7017283cac61bbf726197ad6a5a18b84 create mode 100644 tests/resources/rebase/.gitted/objects/4c/acc6f6e740a5bc64faa33e04b8ef0733d8a127 create mode 100644 tests/resources/rebase/.gitted/objects/4f/b698bde45d7d2833e3f2aacfbfe8a7e7f60a65 create mode 100644 tests/resources/rebase/.gitted/objects/53/f75e45a463033854e52fa8d39dc858e45537d0 create mode 100644 tests/resources/rebase/.gitted/objects/58/8e5d2f04d49707fe4aab865e1deacaf7ef6787 create mode 100644 tests/resources/rebase/.gitted/objects/5b/1e8bccf7787e942aecf61912f94a2c274f85a5 create mode 100644 tests/resources/rebase/.gitted/objects/60/29cb003b59f710f9a8ebd9da9ece2d73070b69 create mode 100644 tests/resources/rebase/.gitted/objects/61/30e5fcbdce2aa8b3cfd84706c58a892e7d8dd0 create mode 100644 tests/resources/rebase/.gitted/objects/63/c18bf188b8a1ab0bad85161dc3fb43c48ed0db create mode 100644 tests/resources/rebase/.gitted/objects/67/ed7afb256807556f9b74fa4f7c9284aaec1120 create mode 100644 tests/resources/rebase/.gitted/objects/68/af1fc7407fd9addf1701a87eb1c95c7494c598 create mode 100644 tests/resources/rebase/.gitted/objects/68/f6182f4c85d39e1309d97c7e456156dc9c0096 create mode 100644 tests/resources/rebase/.gitted/objects/6c/8e16469b6ca09a07e00f0e07a5143c31dcfb64 create mode 100644 tests/resources/rebase/.gitted/objects/6d/77ce8fa2cd93c6489236e33e45e35203ca748c create mode 100644 tests/resources/rebase/.gitted/objects/6d/fb87d20f3dbca02da4a39890114fd9ba6a51e7 create mode 100644 tests/resources/rebase/.gitted/objects/73/f346c88d965227a03c0af8d555870b8c5021d4 create mode 100644 tests/resources/rebase/.gitted/objects/74/0a804e8963759c98e5b8cb912e15ae74a7a4a6 create mode 100644 tests/resources/rebase/.gitted/objects/78/c320b06544e23d786a9ec84ee93861f2933094 create mode 100644 tests/resources/rebase/.gitted/objects/79/e28694aae0d3064b06f96a5207b943a2357f07 create mode 100644 tests/resources/rebase/.gitted/objects/7a/05900f340af0252aaa4e34941f040c5d2fe7f7 create mode 100644 tests/resources/rebase/.gitted/objects/7a/677f6201c8f9d46bdfe1f4b08cb504e360a34e create mode 100644 tests/resources/rebase/.gitted/objects/7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f create mode 100644 tests/resources/rebase/.gitted/objects/7f/37fe2d7320360f8a9118b1ed8fba6f38481679 create mode 100644 tests/resources/rebase/.gitted/objects/80/32d630f37266bace093e353f7b97d7f8b20950 create mode 100644 tests/resources/rebase/.gitted/objects/80/dce0e74f0534811db734a68c23b49f98584d7a create mode 100644 tests/resources/rebase/.gitted/objects/83/53b9f9deff7c707f280e0f656c80772cca7cd9 create mode 100644 tests/resources/rebase/.gitted/objects/85/258e426a341cc1aa035ac7f6d18f84fed2ab38 create mode 100644 tests/resources/rebase/.gitted/objects/85/f34ce9ca9e0f33d4146afec9cbe5a26757500a create mode 100644 tests/resources/rebase/.gitted/objects/86/a5415741ed3754ccb0cac1fc19fd82587840a4 create mode 100644 tests/resources/rebase/.gitted/objects/8d/1f13f93c4995760ac07d129246ac1ff64c0be9 create mode 100644 tests/resources/rebase/.gitted/objects/8d/95ea62e621f1d38d230d9e7d206e41096d76af create mode 100644 tests/resources/rebase/.gitted/objects/8f/4de6c781b9ff9cedfd7f9f9f224e744f97b259 create mode 100644 tests/resources/rebase/.gitted/objects/92/54a37fde7e97f9a28dee2967fdb2c5d1ed94e9 create mode 100644 tests/resources/rebase/.gitted/objects/95/39b2cc291d6a6b1b266df8474d31fdd344dd79 create mode 100644 tests/resources/rebase/.gitted/objects/9a/8535dfcaf7554c728d874f047c5461fb2c71d1 create mode 100644 tests/resources/rebase/.gitted/objects/9c/d483e7da23819d7f71d24e9843812337886753 create mode 100644 tests/resources/rebase/.gitted/objects/a0/1a6ee390f65d834375e072952deaee0c5e92f7 create mode 100644 tests/resources/rebase/.gitted/objects/a0/fa65f96c1e3bdc7287e334229279dcc1248fa4 create mode 100644 tests/resources/rebase/.gitted/objects/a1/25b9b655932711abceaf8962948e6b601d67b6 create mode 100644 tests/resources/rebase/.gitted/objects/a7/00acc970eccccc73be53cd269462176544e6d1 create mode 100644 tests/resources/rebase/.gitted/objects/a7/b066537e6be7109abfe4ff97b675d4e077da20 create mode 100644 tests/resources/rebase/.gitted/objects/aa/4c42aecdfc7cd989bbc3209934ea7cda3f4d88 create mode 100644 tests/resources/rebase/.gitted/objects/ab/25a53ef5622d443ecb0492b7516725f0deac8f create mode 100644 tests/resources/rebase/.gitted/objects/ae/87cae12879a3c37d7cc994afc6395bcb0eaf99 create mode 100644 tests/resources/rebase/.gitted/objects/b1/46bd7608eac53d9bf9e1a6963543588b555c64 create mode 100644 tests/resources/rebase/.gitted/objects/b1/b94ec02f8ed87d0efa4c65fb38d5d6da7e8b32 create mode 100644 tests/resources/rebase/.gitted/objects/b6/72b141d48c369fee6c4deeb32a904387594365 create mode 100644 tests/resources/rebase/.gitted/objects/b7/c536a5883c8adaeb34d5e198c5a3dbbdc608b5 create mode 100644 tests/resources/rebase/.gitted/objects/b9/f72b9158fa8c49fb4e4c10b26817ed867be803 create mode 100644 tests/resources/rebase/.gitted/objects/bc/cc8eabb5cfe2ec09959c7f4155aa73429fd604 create mode 100644 tests/resources/rebase/.gitted/objects/c4/e6cca3ec6ae0148ed231f97257df8c311e015f create mode 100644 tests/resources/rebase/.gitted/objects/c5/17380440ed78865ffe3fa130b9738615c76618 create mode 100644 tests/resources/rebase/.gitted/objects/d6/16d97082eb7bb2dc6f180a7cca940993b7a56f create mode 100644 tests/resources/rebase/.gitted/objects/d6/b9ec0dfb972a6815ace42545cde5f2631cd776 create mode 100644 tests/resources/rebase/.gitted/objects/da/82b3a60c50cf5ac524ec3000d743447329465d create mode 100644 tests/resources/rebase/.gitted/objects/da/9c51a23d02d931a486f45ad18cda05cf5d2b94 create mode 100644 tests/resources/rebase/.gitted/objects/df/d3d25264693fcd7348ad286f3c34f3f6b30918 create mode 100644 tests/resources/rebase/.gitted/objects/e4/f809f826c1a9fc929874bc0e4644dd2f2a1af4 create mode 100644 tests/resources/rebase/.gitted/objects/e5/2ff405da5b7e1e9b0929939fa8405d81fe8a45 create mode 100644 tests/resources/rebase/.gitted/objects/e8/8cc0a6919a74599ce8e1dcb81eb2bbae33a645 create mode 100644 tests/resources/rebase/.gitted/objects/e9/5f47e016dcc70b0b888df8e40e97b8aabafd4c create mode 100644 tests/resources/rebase/.gitted/objects/e9/f22c10ffb378446c0bbcab7ee3d9d5a0040672 create mode 100644 tests/resources/rebase/.gitted/objects/ec/725f5639730640f91cd0be5f2d6d7ac5d69c79 create mode 100644 tests/resources/rebase/.gitted/objects/ee/23c5eeedadf8595c0ff60a366d970a165e373d create mode 100644 tests/resources/rebase/.gitted/objects/ee/f0edde5daa94da5f297d4ddb5dfbc1980f0902 create mode 100644 tests/resources/rebase/.gitted/objects/ef/ad0b11c47cb2f0220cbd6f5b0f93bb99064b00 create mode 100644 tests/resources/rebase/.gitted/objects/f5/56d5fef35003561dc0b64b37057d7541239105 create mode 100644 tests/resources/rebase/.gitted/objects/f6/3fa37e285bd11b0a7b48fa584a4091814a3ada create mode 100644 tests/resources/rebase/.gitted/objects/f7/5c193a1df47186727179f24867bc4d27a8991f create mode 100644 tests/resources/rebase/.gitted/objects/f8/7d14a4a236582a0278a916340a793714256864 create mode 100644 tests/resources/rebase/.gitted/objects/fc/e0584b379f535e50e036db587db71884ea6b36 create mode 100644 tests/resources/rebase/.gitted/objects/ff/b36e513f5fdf8a6ba850a20142676a2ac4807d create mode 100644 tests/resources/rebase/.gitted/objects/ff/dfa89389040a87008c4ab1834120d3046daaea create mode 100644 tests/resources/rebase/.gitted/refs/heads/asparagus create mode 100644 tests/resources/rebase/.gitted/refs/heads/barley create mode 100644 tests/resources/rebase/.gitted/refs/heads/beef create mode 100644 tests/resources/rebase/.gitted/refs/heads/dried_pea create mode 100644 tests/resources/rebase/.gitted/refs/heads/gravy create mode 100644 tests/resources/rebase/.gitted/refs/heads/master create mode 100644 tests/resources/rebase/.gitted/refs/heads/veal create mode 100644 tests/resources/rebase/asparagus.txt create mode 100644 tests/resources/rebase/beef.txt create mode 100644 tests/resources/rebase/bouilli.txt create mode 100644 tests/resources/rebase/gravy.txt create mode 100644 tests/resources/rebase/oyster.txt create mode 100644 tests/resources/rebase/veal.txt diff --git a/include/git2/errors.h b/include/git2/errors.h index 1e3ed3acb..5dfa72ab8 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -90,6 +90,7 @@ typedef enum { GITERR_CALLBACK, GITERR_CHERRYPICK, GITERR_DESCRIBE, + GITERR_REBASE, } git_error_t; /** diff --git a/include/git2/rebase.h b/include/git2/rebase.h new file mode 100644 index 000000000..6eb279412 --- /dev/null +++ b/include/git2/rebase.h @@ -0,0 +1,73 @@ +/* + * 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_git_rebase_h__ +#define INCLUDE_git_rebase_h__ + +#include "common.h" +#include "types.h" +#include "oid.h" + +/** + * @file git2/rebase.h + * @brief Git rebase routines + * @defgroup git_rebase Git merge routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +typedef struct { + unsigned int version; + + /** + * Provide a quiet rebase experience; unused by libgit2 but provided for + * interoperability with other clients. + */ + int quiet; +} git_rebase_options; + +#define GIT_REBASE_OPTIONS_VERSION 1 +#define GIT_REBASE_OPTIONS_INIT {GIT_REBASE_OPTIONS_VERSION} + +/** + * Initializes a `git_rebase_options` with default values. Equivalent to + * creating an instance with GIT_REBASE_OPTIONS_INIT. + * + * @param opts the `git_rebase_options` instance to initialize. + * @param version the version of the struct; you should pass + * `GIT_REBASE_OPTIONS_VERSION` here. + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_rebase_init_options( + git_rebase_options *opts, + unsigned int version); + +/** + * Sets up a rebase operation to rebase the changes in ours relative to + * upstream onto another branch. + * + * @param repo The repository to perform the rebase + * @param branch The terminal commit to rebase + * @param upstream The commit to begin rebasing from, or NULL to rebase all + * reachable commits + * @param onto The branch to rebase onto, or NULL to rebase onto the given + * upstream + * @param signature The signature of the rebaser + * @param opts Options to specify how rebase is performed + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_rebase( + git_repository *repo, + const git_merge_head *branch, + const git_merge_head *upstream, + const git_merge_head *onto, + const git_signature *signature, + const git_rebase_options *opts); + +/** @} */ +GIT_END_DECL +#endif diff --git a/src/merge.c b/src/merge.c index 8252f6767..3cafc5d03 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1835,29 +1835,6 @@ done: /* Merge setup / cleanup */ -static int write_orig_head( - git_repository *repo, - const git_merge_head *our_head) -{ - git_filebuf file = GIT_FILEBUF_INIT; - git_buf file_path = GIT_BUF_INIT; - int error = 0; - - assert(repo && our_head); - - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_ORIG_HEAD_FILE)) == 0 && - (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) == 0 && - (error = git_filebuf_printf(&file, "%s\n", our_head->oid_str)) == 0) - error = git_filebuf_commit(&file); - - if (error < 0) - git_filebuf_cleanup(&file); - - git_buf_free(&file_path); - - return error; -} - static int write_merge_head( git_repository *repo, const git_merge_head *heads[], @@ -2229,7 +2206,7 @@ int git_merge__setup( assert (repo && our_head && heads); - if ((error = write_orig_head(repo, our_head)) == 0 && + if ((error = git_repository__set_orig_head(repo, &our_head->oid)) == 0 && (error = write_merge_head(repo, heads, heads_len)) == 0 && (error = write_merge_mode(repo)) == 0) { error = write_merge_msg(repo, heads, heads_len); diff --git a/src/rebase.c b/src/rebase.c new file mode 100644 index 000000000..68d741d25 --- /dev/null +++ b/src/rebase.c @@ -0,0 +1,332 @@ +/* + * 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 "common.h" +#include "buffer.h" +#include "repository.h" +#include "posix.h" +#include "filebuf.h" +#include "merge.h" +#include "array.h" + +#include +#include +#include +#include +#include + +#define REBASE_APPLY_DIR "rebase-apply" +#define REBASE_MERGE_DIR "rebase-merge" + +#define HEAD_NAME_FILE "head-name" +#define ORIG_HEAD_FILE "orig-head" +#define HEAD_FILE "head" +#define ONTO_FILE "onto" +#define ONTO_NAME_FILE "onto_name" +#define QUIET_FILE "quiet" + +#define MSGNUM_FILE "msgnum" +#define END_FILE "end" +#define CMT_FILE_FMT "cmt.%d" + +#define ORIG_DETACHED_HEAD "detached HEAD" + +#define REBASE_DIR_MODE 0777 +#define REBASE_FILE_MODE 0666 + +typedef enum { + GIT_REBASE_TYPE_NONE = 0, + GIT_REBASE_TYPE_APPLY = 1, + GIT_REBASE_TYPE_MERGE = 2, +} git_rebase_type_t; + +static int rebase_state_type( + git_rebase_type_t *type_out, + char **path_out, + git_repository *repo) +{ + git_buf path = GIT_BUF_INIT; + git_rebase_type_t type = GIT_REBASE_TYPE_NONE; + + if (git_buf_joinpath(&path, repo->path_repository, REBASE_APPLY_DIR) < 0) + return -1; + + if (git_path_isdir(git_buf_cstr(&path))) { + type = GIT_REBASE_TYPE_APPLY; + goto done; + } + + git_buf_clear(&path); + if (git_buf_joinpath(&path, repo->path_repository, REBASE_MERGE_DIR) < 0) + return -1; + + if (git_path_isdir(git_buf_cstr(&path))) { + type = GIT_REBASE_TYPE_MERGE; + goto done; + } + +done: + *type_out = type; + + if (type != GIT_REBASE_TYPE_NONE && path_out) + *path_out = git_buf_detach(&path); + + git_buf_free(&path); + + return 0; +} + +static int rebase_setupfile(git_repository *repo, const char *filename, const char *fmt, ...) +{ + git_buf path = GIT_BUF_INIT, + contents = GIT_BUF_INIT; + va_list ap; + int error; + + va_start(ap, fmt); + git_buf_vprintf(&contents, fmt, ap); + va_end(ap); + + if ((error = git_buf_joinpath(&path, repo->path_repository, REBASE_MERGE_DIR)) == 0 && + (error = git_buf_joinpath(&path, path.ptr, filename)) == 0) + error = git_futils_writebuffer(&contents, path.ptr, O_RDWR|O_CREAT, REBASE_FILE_MODE); + + git_buf_free(&path); + git_buf_free(&contents); + + return error; +} + +/* TODO: git.git actually uses the literal argv here, this is an attempt + * to emulate that. + */ +static const char *rebase_onto_name(const git_merge_head *onto) +{ + if (onto->ref_name && git__strncmp(onto->ref_name, "refs/heads/", 11) == 0) + return onto->ref_name + 11; + else if (onto->ref_name) + return onto->ref_name; + else + return onto->oid_str; +} + +static int rebase_setup_merge( + git_repository *repo, + const git_merge_head *branch, + const git_merge_head *upstream, + const git_merge_head *onto, + const git_rebase_options *opts) +{ + git_revwalk *revwalk = NULL; + git_commit *commit; + git_buf commit_filename = GIT_BUF_INIT; + git_oid id; + char id_str[GIT_OID_HEXSZ]; + bool merge; + int commit_cnt = 0, error; + + GIT_UNUSED(opts); + + if (!upstream) + upstream = onto; + + if ((error = git_revwalk_new(&revwalk, repo)) < 0 || + (error = git_revwalk_push(revwalk, &branch->oid)) < 0 || + (error = git_revwalk_hide(revwalk, &upstream->oid)) < 0) + goto done; + + git_revwalk_sorting(revwalk, GIT_SORT_REVERSE | GIT_SORT_TIME); + + while ((error = git_revwalk_next(&id, revwalk)) == 0) { + if ((error = git_commit_lookup(&commit, repo, &id)) < 0) + goto done; + + merge = (git_commit_parentcount(commit) > 1); + git_commit_free(commit); + + if (merge) + continue; + + commit_cnt++; + + git_buf_clear(&commit_filename); + git_buf_printf(&commit_filename, CMT_FILE_FMT, commit_cnt); + + git_oid_fmt(id_str, &id); + if ((error = rebase_setupfile(repo, commit_filename.ptr, + "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0) + goto done; + } + + if (error != GIT_ITEROVER || + (error = rebase_setupfile(repo, END_FILE, "%d\n", commit_cnt)) < 0) + goto done; + + error = rebase_setupfile(repo, ONTO_NAME_FILE, "%s\n", + rebase_onto_name(onto)); + +done: + git_revwalk_free(revwalk); + git_buf_free(&commit_filename); + + return error; +} + +static int rebase_setup( + git_repository *repo, + const git_merge_head *branch, + const git_merge_head *upstream, + const git_merge_head *onto, + const git_rebase_options *opts) +{ + git_buf state_path = GIT_BUF_INIT; + const char *orig_head_name; + int error; + + if (git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR) < 0) + return -1; + + if ((error = p_mkdir(state_path.ptr, REBASE_DIR_MODE)) < 0) { + giterr_set(GITERR_OS, "Failed to create rebase directory '%s'", + state_path.ptr); + goto done; + } + + if ((error = git_repository__set_orig_head(repo, &branch->oid)) < 0) + goto done; + + orig_head_name = branch->ref_name ? branch->ref_name : ORIG_DETACHED_HEAD; + + if ((error = rebase_setupfile(repo, HEAD_NAME_FILE, "%s\n", orig_head_name)) < 0 || + (error = rebase_setupfile(repo, ONTO_FILE, "%s\n", onto->oid_str)) < 0 || + (error = rebase_setupfile(repo, ORIG_HEAD_FILE, "%s\n", branch->oid_str)) < 0 || + (error = rebase_setupfile(repo, QUIET_FILE, opts->quiet ? "t\n" : "\n")) < 0) + goto done; + + error = rebase_setup_merge(repo, branch, upstream, onto, opts); + +done: + if (error < 0) + git_repository__cleanup_files(repo, (const char **)&state_path.ptr, 1); + + git_buf_free(&state_path); + + return error; +} + +int git_rebase_init_options(git_rebase_options *opts, unsigned int version) +{ + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_rebase_options, GIT_REBASE_OPTIONS_INIT); + return 0; +} + +static void rebase_normalize_options( + git_rebase_options *opts, + const git_rebase_options *given_opts) +{ + if (given_opts) + memcpy(&opts, given_opts, sizeof(git_rebase_options)); +} + +static int rebase_ensure_not_in_progress(git_repository *repo) +{ + int error; + git_rebase_type_t type; + + if ((error = rebase_state_type(&type, NULL, repo)) < 0) + return error; + + if (type != GIT_REBASE_TYPE_NONE) { + giterr_set(GITERR_REBASE, "There is an existing rebase in progress"); + return -1; + } + + return 0; +} + +static int rebase_ensure_not_dirty(git_repository *repo) +{ + git_tree *head = NULL; + git_index *index = NULL; + git_diff *diff = NULL; + int error; + + if ((error = git_repository_head_tree(&head, repo)) < 0 || + (error = git_repository_index(&index, repo)) < 0 || + (error = git_diff_tree_to_index(&diff, repo, head, index, NULL)) < 0) + goto done; + + if (git_diff_num_deltas(diff) > 0) { + giterr_set(GITERR_REBASE, "Uncommitted changes exist in index"); + error = -1; + goto done; + } + + git_diff_free(diff); + diff = NULL; + + if ((error = git_diff_index_to_workdir(&diff, repo, index, NULL)) < 0) + goto done; + + if (git_diff_num_deltas(diff) > 0) { + giterr_set(GITERR_REBASE, "Unstaged changes exist in workdir"); + error = -1; + } + +done: + git_diff_free(diff); + git_index_free(index); + git_tree_free(head); + + return error; +} + +int git_rebase( + git_repository *repo, + const git_merge_head *branch, + const git_merge_head *upstream, + const git_merge_head *onto, + const git_signature *signature, + const git_rebase_options *given_opts) +{ + git_rebase_options opts = GIT_REBASE_OPTIONS_INIT; + git_reference *head_ref = NULL; + git_buf reflog = GIT_BUF_INIT; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + int error; + + assert(repo && branch && (upstream || onto)); + + GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options"); + rebase_normalize_options(&opts, given_opts); + + if ((error = git_repository__ensure_not_bare(repo, "rebase")) < 0 || + (error = rebase_ensure_not_in_progress(repo)) < 0 || + (error = rebase_ensure_not_dirty(repo)) < 0) + goto done; + + if (!onto) + onto = upstream; + + if ((error = rebase_setup(repo, branch, upstream, onto, &opts)) < 0) + goto done; + + if ((error = git_buf_printf(&reflog, + "rebase: checkout %s", rebase_onto_name(onto))) < 0 || + (error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE, + &onto->oid, 1, signature, reflog.ptr)) < 0) + goto done; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + error = git_checkout_head(repo, &checkout_opts); + +done: + git_reference_free(head_ref); + git_buf_free(&reflog); + return error; +} diff --git a/src/repository.c b/src/repository.c index f032c899d..2bab52919 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1728,6 +1728,28 @@ cleanup: return error; } +int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head) +{ + git_filebuf file = GIT_FILEBUF_INIT; + git_buf file_path = GIT_BUF_INIT; + char orig_head_str[GIT_OID_HEXSZ]; + int error = 0; + + git_oid_fmt(orig_head_str, orig_head); + + if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_ORIG_HEAD_FILE)) == 0 && + (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) == 0 && + (error = git_filebuf_printf(&file, "%.*s\n", GIT_OID_HEXSZ, orig_head_str)) == 0) + error = git_filebuf_commit(&file); + + if (error < 0) + git_filebuf_cleanup(&file); + + git_buf_free(&file_path); + + return error; +} + int git_repository_message(git_buf *out, git_repository *repo) { git_buf path = GIT_BUF_INIT; diff --git a/src/repository.h b/src/repository.h index aba16a016..45b95a0f0 100644 --- a/src/repository.h +++ b/src/repository.h @@ -170,6 +170,8 @@ GIT_INLINE(int) git_repository__ensure_not_bare( return GIT_EBAREREPO; } +int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head); + int git_repository__cleanup_files(git_repository *repo, const char *files[], size_t files_len); #endif diff --git a/tests/rebase/setup.c b/tests/rebase/setup.c new file mode 100644 index 000000000..4828c4057 --- /dev/null +++ b/tests/rebase/setup.c @@ -0,0 +1,328 @@ +#include "clar_libgit2.h" +#include "git2/rebase.h" +#include "posix.h" + +#include + +static git_repository *repo; +static git_index *_index; +static git_signature *signature; + +// Fixture setup and teardown +void test_rebase_setup__initialize(void) +{ + repo = cl_git_sandbox_init("rebase"); + cl_git_pass(git_repository_index(&_index, repo)); + cl_git_pass(git_signature_now(&signature, "Rebaser", "rebaser@rebaser.rb")); +} + +void test_rebase_setup__cleanup(void) +{ + git_signature_free(signature); + git_index_free(_index); + cl_git_sandbox_cleanup(); +} + +/* git checkout beef ; git rebase --merge master + * git checkout beef ; git rebase --merge master */ +void test_rebase_setup__blocked_when_in_progress(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); + + cl_git_fail(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + +/* git checkout beef ; git rebase --merge master */ +void test_rebase_setup__merge(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_reference *head; + git_commit *head_commit; + git_oid head_id; + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); + + git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); + cl_git_pass(git_repository_head(&head, repo)); + cl_git_pass(git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)); + cl_assert_equal_oid(&head_id, git_commit_id(head_commit)); + + cl_assert_equal_file("b146bd7608eac53d9bf9e1a6963543588b555c64\n", 41, "rebase/.git/ORIG_HEAD"); + + cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n", 41, "rebase/.git/rebase-merge/cmt.1"); + cl_assert_equal_file("8d1f13f93c4995760ac07d129246ac1ff64c0be9\n", 41, "rebase/.git/rebase-merge/cmt.2"); + cl_assert_equal_file("3069cc907e6294623e5917ef6de663928c1febfb\n", 41, "rebase/.git/rebase-merge/cmt.3"); + cl_assert_equal_file("588e5d2f04d49707fe4aab865e1deacaf7ef6787\n", 41, "rebase/.git/rebase-merge/cmt.4"); + cl_assert_equal_file("b146bd7608eac53d9bf9e1a6963543588b555c64\n", 41, "rebase/.git/rebase-merge/cmt.5"); + cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); + cl_assert_equal_file("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n", 41, "rebase/.git/rebase-merge/onto"); + cl_assert_equal_file("master\n", 7, "rebase/.git/rebase-merge/onto_name"); + cl_assert_equal_file("b146bd7608eac53d9bf9e1a6963543588b555c64\n", 41, "rebase/.git/rebase-merge/orig-head"); + + git_commit_free(head_commit); + git_reference_free(head); + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + +/* git checkout beef && git rebase --merge --root --onto master */ +void test_rebase_setup__merge_root(void) +{ + git_reference *branch_ref, *onto_ref; + git_merge_head *branch_head, *onto_head; + git_reference *head; + git_commit *head_commit; + git_oid head_id; + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + + cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); + + git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); + cl_git_pass(git_repository_head(&head, repo)); + cl_git_pass(git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)); + cl_assert_equal_oid(&head_id, git_commit_id(head_commit)); + + cl_assert_equal_file("b146bd7608eac53d9bf9e1a6963543588b555c64\n", 41, "rebase/.git/ORIG_HEAD"); + + cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); + + cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n", 41, "rebase/.git/rebase-merge/cmt.1"); + cl_assert_equal_file("8d1f13f93c4995760ac07d129246ac1ff64c0be9\n", 41, "rebase/.git/rebase-merge/cmt.2"); + cl_assert_equal_file("3069cc907e6294623e5917ef6de663928c1febfb\n", 41, "rebase/.git/rebase-merge/cmt.3"); + cl_assert_equal_file("588e5d2f04d49707fe4aab865e1deacaf7ef6787\n", 41, "rebase/.git/rebase-merge/cmt.4"); + cl_assert_equal_file("b146bd7608eac53d9bf9e1a6963543588b555c64\n", 41, "rebase/.git/rebase-merge/cmt.5"); + cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); + cl_assert_equal_file("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n", 41, "rebase/.git/rebase-merge/onto"); + cl_assert_equal_file("master\n", 7, "rebase/.git/rebase-merge/onto_name"); + cl_assert_equal_file("b146bd7608eac53d9bf9e1a6963543588b555c64\n", 41, "rebase/.git/rebase-merge/orig-head"); + + git_commit_free(head_commit); + git_reference_free(head); + git_merge_head_free(branch_head); + git_merge_head_free(onto_head); + git_reference_free(branch_ref); + git_reference_free(onto_ref); +} + +/* git checkout gravy && git rebase --merge --onto master veal */ +void test_rebase_setup__merge_onto_and_upstream(void) +{ + git_reference *branch1_ref, *branch2_ref, *onto_ref; + git_merge_head *branch1_head, *branch2_head, *onto_head; + git_reference *head; + git_commit *head_commit; + git_oid head_id; + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + cl_git_pass(git_reference_lookup(&branch1_ref, repo, "refs/heads/gravy")); + cl_git_pass(git_reference_lookup(&branch2_ref, repo, "refs/heads/veal")); + cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch1_head, repo, branch1_ref)); + cl_git_pass(git_merge_head_from_ref(&branch2_head, repo, branch2_ref)); + cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + + cl_git_pass(git_rebase(repo, branch1_head, branch2_head, onto_head, signature, NULL)); + + git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); + cl_git_pass(git_repository_head(&head, repo)); + cl_git_pass(git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)); + cl_assert_equal_oid(&head_id, git_commit_id(head_commit)); + + cl_assert_equal_file("d616d97082eb7bb2dc6f180a7cca940993b7a56f\n", 41, "rebase/.git/ORIG_HEAD"); + + cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); + + cl_assert_equal_file("d616d97082eb7bb2dc6f180a7cca940993b7a56f\n", 41, "rebase/.git/rebase-merge/cmt.1"); + cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/end"); + cl_assert_equal_file("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n", 41, "rebase/.git/rebase-merge/onto"); + cl_assert_equal_file("master\n", 7, "rebase/.git/rebase-merge/onto_name"); + cl_assert_equal_file("d616d97082eb7bb2dc6f180a7cca940993b7a56f\n", 41, "rebase/.git/rebase-merge/orig-head"); + + git_commit_free(head_commit); + git_reference_free(head); + git_merge_head_free(branch1_head); + git_merge_head_free(branch2_head); + git_merge_head_free(onto_head); + git_reference_free(branch1_ref); + git_reference_free(branch2_ref); + git_reference_free(onto_ref); +} + +/* Ensure merge commits are dropped in a rebase */ +/* git checkout veal && git rebase --merge master */ +void test_rebase_setup__branch_with_merges(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_reference *head; + git_commit *head_commit; + git_oid head_id; + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/veal")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); + + git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); + cl_git_pass(git_repository_head(&head, repo)); + cl_git_pass(git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)); + cl_assert_equal_oid(&head_id, git_commit_id(head_commit)); + + cl_assert_equal_file("f87d14a4a236582a0278a916340a793714256864\n", 41, "rebase/.git/ORIG_HEAD"); + + cl_assert_equal_file("4bed71df7017283cac61bbf726197ad6a5a18b84\n", 41, "rebase/.git/rebase-merge/cmt.1"); + cl_assert_equal_file("2aa3ce842094e08ebac152b3d6d5b0fff39f9c6e\n", 41, "rebase/.git/rebase-merge/cmt.2"); + cl_assert_equal_file("3e8989b5a16d5258c935d998ef0e6bb139cc4757\n", 41, "rebase/.git/rebase-merge/cmt.3"); + cl_assert_equal_file("4cacc6f6e740a5bc64faa33e04b8ef0733d8a127\n", 41, "rebase/.git/rebase-merge/cmt.4"); + cl_assert_equal_file("f87d14a4a236582a0278a916340a793714256864\n", 41, "rebase/.git/rebase-merge/cmt.5"); + cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); + cl_assert_equal_file("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n", 41, "rebase/.git/rebase-merge/onto"); + cl_assert_equal_file("master\n", 7, "rebase/.git/rebase-merge/onto_name"); + cl_assert_equal_file("f87d14a4a236582a0278a916340a793714256864\n", 41, "rebase/.git/rebase-merge/orig-head"); + + git_commit_free(head_commit); + git_reference_free(head); + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + +/* git checkout barley && git rebase --merge master */ +void test_rebase_setup__orphan_branch(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_reference *head; + git_commit *head_commit; + git_oid head_id; + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/barley")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); + + git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); + cl_git_pass(git_repository_head(&head, repo)); + cl_git_pass(git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)); + cl_assert_equal_oid(&head_id, git_commit_id(head_commit)); + + cl_assert_equal_file("12c084412b952396962eb420716df01022b847cc\n", 41, "rebase/.git/ORIG_HEAD"); + + cl_assert_equal_file("aa4c42aecdfc7cd989bbc3209934ea7cda3f4d88\n", 41, "rebase/.git/rebase-merge/cmt.1"); + cl_assert_equal_file("e4f809f826c1a9fc929874bc0e4644dd2f2a1af4\n", 41, "rebase/.git/rebase-merge/cmt.2"); + cl_assert_equal_file("9539b2cc291d6a6b1b266df8474d31fdd344dd79\n", 41, "rebase/.git/rebase-merge/cmt.3"); + cl_assert_equal_file("013cc32d341bab0e6f039f50f153c18986f16c58\n", 41, "rebase/.git/rebase-merge/cmt.4"); + cl_assert_equal_file("12c084412b952396962eb420716df01022b847cc\n", 41, "rebase/.git/rebase-merge/cmt.5"); + cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); + cl_assert_equal_file("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n", 41, "rebase/.git/rebase-merge/onto"); + cl_assert_equal_file("master\n", 7, "rebase/.git/rebase-merge/onto_name"); + cl_assert_equal_file("12c084412b952396962eb420716df01022b847cc\n", 41, "rebase/.git/rebase-merge/orig-head"); + + git_commit_free(head_commit); + git_reference_free(head); + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + +static int rebase_is_blocked(void) +{ + int error; + + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + error = git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL); + + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + + git_reference_free(branch_ref); + git_reference_free(upstream_ref); + + return error; +} + +void test_rebase_setup__blocked_for_staged_change(void) +{ + cl_git_rewritefile("rebase/newfile.txt", "Stage an add"); + git_index_add_bypath(_index, "newfile.txt"); + cl_git_fail(rebase_is_blocked()); +} + +void test_rebase_setup__blocked_for_unstaged_change(void) +{ + cl_git_rewritefile("rebase/asparagus.txt", "Unstaged change"); + cl_git_fail(rebase_is_blocked()); +} + +void test_rebase_setup__not_blocked_for_untracked_add(void) +{ + cl_git_rewritefile("rebase/newfile.txt", "Untracked file"); + cl_git_pass(rebase_is_blocked()); +} + diff --git a/tests/resources/rebase/.gitted/HEAD b/tests/resources/rebase/.gitted/HEAD new file mode 100644 index 0000000000000000000000000000000000000000..cb089cd89a7d7686d284d8761201649346b5aa1c GIT binary patch literal 23 ecmXR)O|w!cN=+-)&qz&7Db~+TEG|hc;sO9;xClW2 literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/config b/tests/resources/rebase/.gitted/config new file mode 100644 index 0000000000000000000000000000000000000000..17e58b1c21f2a9fef9508ab51ee3839ea157e4e0 GIT binary patch literal 75 zcmWN`!3lsc3$QY10X~;Cxyf9SrSYtB2N$C5uUY;k+ zd9$X@H8JeY9ENEO97(CEX%M4um=lg_4vUL-O;`X!w_Zv8!-jdUqh#;#HMDXua3|%L zX6EE%!d->%ADTZ`pqj_ncI4Ta#c#46i1b}D{8USved*Jh-o*TD_q_dxX8m^g~QSG*wXEFn_aR1Eh>?0 literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/info/exclude b/tests/resources/rebase/.gitted/info/exclude new file mode 100644 index 0000000000000000000000000000000000000000..a5196d1be8fb59edf8062bef36d3a602e0812139 GIT binary patch literal 240 zcmXYqK?=e!6h!x)VxWtv*mf_t5?px$aS_{}Hj?C*WhEe*D&hibb?OE#yj6)yn;GKaTI>Zf6!Vi7+ VBUF9e=Npu!6>3_#H0Zk0_5-$jIZFTl literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/00/66204dd469ee930e551fbcf123f98e211c99ce b/tests/resources/rebase/.gitted/objects/00/66204dd469ee930e551fbcf123f98e211c99ce new file mode 100644 index 0000000000000000000000000000000000000000..e6f72ce24060c03cd8d378695f5350c60e18dda2 GIT binary patch literal 806 zcmV+>1KIp|0c})GkJ~m7?U}z~ZoOy?v^@mKp1g?yyV=-AY0msddq1nzsQs2;i>VCEA_V7e%R2L^YKJ47>0>ETEDITBzDPx*o(TCT1y(8^9vieRYlX0Xe_*_v6(YT9c@>h=X3fn17 zfCm~cul3XMu;1@KonM7Q@U!cvXfdJqtA&_8+E`Y!3@dN`B0JUD1V?lM`uE!pyQ7-AeB9J zrsZb=8Uf&e-$3{ctL%l4F6cLooQH`cg; zdUIv9*`L22E4q!Q9T)K}>noFPJPck02mmBov4C|X@#&d5PYydR%PCfeJ^bBoUupk` z0BhvW`U3F~5y6+*c@j~$pRIVVlfa86ae~QEQyxd1lnkjqQZK|ue58s3h83e1(HeLs zKFi?y1gMY}0w&8c7Y|w;w!2dS%$DQ5WcA??vZe`2Jf+~h1DJmuOAHep(O9X|$O%E# zIZK`#0@)d;nds(civU7vVP+zAY)z}PbU zu~YXN3;nf=CD%#04itPb$2$5kpKVy literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/00/f1b9a0948a7d5d14405eba6030efcdfbb8ff4a b/tests/resources/rebase/.gitted/objects/00/f1b9a0948a7d5d14405eba6030efcdfbb8ff4a new file mode 100644 index 0000000000000000000000000000000000000000..a23f526b576e5e87d8045f61c45627212194b0a5 GIT binary patch literal 173 zcmV;e08;;W0i}*XZbKmqM7!n`zCbE}!0?f(s#)X)*+&K&>^T>NPe*{ElB3hU2g-JeessHNG-8QT2s!& zSxm`!H0C#nq2>855rLvrdJV%Q)W074Ge%Kk3nahrf2$$MFDxeN2cPGu(Ri-ktQ6 dUG~o#_dImp_FmV1DiEvztmg?8a!F4 z5zWVY%@ldU_n$w$-97y}-{J9m!t=xH*?tQyh3seicDSxaKU}p zJtp$Wmd6(64Ze{5P^B^=SA}l0yO8W#i11N;QE5RJDxVNu6^FNG96`5h6Q{sQFmIeQ zEvR|03#}~9rv>7pj+i*ao((-18`mNub}uc1b{rHVT6gv$*S@WAeKSBOfi5(nkk-<` z2r+!ruplJmzRs+J6=8m-1oQ219?_RKLJl;ODY&UN&3?@qjleKX*j$Bog2XUWS4~!Q zY-BF)LqBj0b4vb3GILsMY-5=z_Q8;eXRc|X05AV|0V^p=O;s>5GG{O}FfcPQQAjKTj;SFV484ZsWk8T$lY^VAlR8|EF&&z4D;^ KmI45#Azomv@?(eq literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/0e/f2e2b2a2b8d6e1f8dff5e621e0eca21b693d0c b/tests/resources/rebase/.gitted/objects/0e/f2e2b2a2b8d6e1f8dff5e621e0eca21b693d0c new file mode 100644 index 0000000000000000000000000000000000000000..d8ef47c62741cddea82e3168c39d0e86674b751d GIT binary patch literal 207 zcmV;=05Jb}0i{s8P6IIzr1n>AmkP9JukEvhA{t6Meqg;`=OX3K$T30uJqLm>pqrOQ znvu4y=K*eVccZI97Li#wXD?N)3Z~?f#7dL*%+ZlewFD&d#$C4oBrFnY&`8KWOQ6c^ zoFe5}D@Nza%#)3OdAqx!Gg(ZeIBRB^yv?qJ;xpD-U8+ff8h#&3>+oDYxEFX`+Inpp zJnF7~qbL0_e%XVx^#~K857s&&xJN=XySk4X`p+8kqW!dA(|MBx4yVqy&jXyd(cq?h JF<%fOW@&uoWsLv; literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/0f/5f6d3353be1a9966fa5767b7d604b051798224 b/tests/resources/rebase/.gitted/objects/0f/5f6d3353be1a9966fa5767b7d604b051798224 new file mode 100644 index 0000000000000000000000000000000000000000..739aca383a8c0b405e533f8e72a0f74f55d098b1 GIT binary patch literal 183 zcmV;o07(CM0i};!3IZ_?Bg#+-8CmOGAtR)LrP8(*Kx@CNY_T4yygRigj^ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/11/fac10ca1b9318ce361a0be0c3d889d777e299c b/tests/resources/rebase/.gitted/objects/11/fac10ca1b9318ce361a0be0c3d889d777e299c new file mode 100644 index 0000000000000000000000000000000000000000..5af5474b55bbb69d5b86faa9902d190a9d8a3e54 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKTj;SFV484ZsWk8T$lY^VAlR8|EF&&z4D;^ KmI46pr(VNl@@3Ef literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/12/c084412b952396962eb420716df01022b847cc b/tests/resources/rebase/.gitted/objects/12/c084412b952396962eb420716df01022b847cc new file mode 100644 index 0000000000000000000000000000000000000000..5244e469dc9a3fe9dd13b661ced86e00b4973019 GIT binary patch literal 176 zcmV;h08jsT0i}*hYC|y)1hdvD<^m4-%;-rFLN;D{mkW%f5f7q0-xu;|MUyI$!h=7hdhQSz2?5ZgF#K+TJ#$nG-|C@ eyJV;Q^G2O|X|-jZZ7Cqk4vEK?+|(UQfK?THfl|`| literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/12/f28ed978639d331269d9dc2b74e87db58e1057 b/tests/resources/rebase/.gitted/objects/12/f28ed978639d331269d9dc2b74e87db58e1057 new file mode 100644 index 0000000000000000000000000000000000000000..b0dbc3e0732d033a2916edff81b63ef04021da8a GIT binary patch literal 178 zcmV;j08RgR0i{nlZo@DTbj?@n2V!t3iAw@TkS1k1e_**>+A1Ul5`}y}wBaAPn*%eL zk-98%1LxhTZK{A+SkMY%iUS7G!6VzGR)!ox%tWLvMlrv<>DqvVQVEkr3I%fy*vb1s z)@3J&$omu}da|73OHe9dmv7nPfc2!3w#r2ZZYFLy_q`fS{4De790ASMOzT zLA}KjmI_(SOPw)F;p&%z326;z3R73ljP?SX1x8KcwO&NB_EV}|$4Na*Mzmz=&T~u& b)ODcH$IR#xUHwTg->$#$dYkYMBn^t6-KLOD literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/1b/1d19799fcc89fa3cb821581fcf7f2e8fd2cc4d b/tests/resources/rebase/.gitted/objects/1b/1d19799fcc89fa3cb821581fcf7f2e8fd2cc4d new file mode 100644 index 0000000000000000000000000000000000000000..3d206b0cc1bb53097035f173fb471d5eed75b485 GIT binary patch literal 178 zcmV;j08RgR0i}*TPD3#egsFXsy#Q#v{@W)ZL_n~N>UBZcTB5Sqz%6t2TPt3D zwOA;!O)4ByQATI-_qvP;AM%r@!09sfuW^M}J?LM0*Z<+(Uh3H2z5GG{O}FfcPQQAjK$CU5B2tu*mvakOg5AC#59LoQJSOm2PYJc67?0> zDNT@vF>W5}tKIX{)8prt2OVJ!i|?eP#&LU~S>{<{RdDku=z+v8UxPOa0KE-98TDaz z|E<>7Or!We63H;EP81@Du>Y-`)N+g=CrWMP8BD4fmYJ95ij<@Lf$|c)ofFL*f1bfm zIZ$U?xmKYO0xn9vFC2jxdh@#7*Z+dL46BC218QAJvW{^Onbm{=F1vGKPg%ILcxZxk z)(_O%qnHr{siMH30UxIzzjjk3IgFsx~FUE0(o#c(NkiSUxADL6*c;2 zKEOOgMD?Y1nbZ{N7pFVtr1GLolCWgBsgENkqag62*TFC1W`LDNuckHFo$gtI&l9A= zS{Rs|C@vn@sNy16oWyg<>SaU78WWtjN^=MvV*Yn535YMz*qHq&2|?zZHBTOa>@3_& zbP9_@0O7SxW+QdtY|B|Yz(>_>QId6x9DJg6 zDb=h#I2TU3qlvwj_!q$f!*8MC#>p@GJ+g8ENy~s0l>{*$BeIhY=#*$huq&HQi4#cB zzDqDL1C(T~9=<1Wn6i{CghL|q=}aBRL$$`SfCGnNjxItsx^4q&MmDenayDnY;;e4l z2}w?9I~qDD!`q#K)H&IhU5;EPw`rY1k179zI^p<9Kyb3TTm+Z+t>G#W#popw=J$!v z^r)$75>_xRwEB!&F| literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/22/adb22bef75a0371e85ff6d82e5e60e4b425501 b/tests/resources/rebase/.gitted/objects/22/adb22bef75a0371e85ff6d82e5e60e4b425501 new file mode 100644 index 0000000000000000000000000000000000000000..7f17ef059a66be6cf1e7a5c55ac9373afdeb495c GIT binary patch literal 380 zcmV-?0fYW{0Yy^HZo)7O-Z@X<2dKDBo5ZQ0@}o@@QP9q5>e8s8$r1;|+s_GzotikG zzaP7;u`RrRe!P{eB(f%fq^Y#c8+PR1Mf3WN^~Ua|{Ip z<)uT=1d~>1?ggkwjOoEnT%Ob*>J=O}6&&k*Q-GX0F!ByG;Dw*zCJ8+^4c4U^1d?V9 z8RnQM!|as4VzoU~@UuN`poIOlT2{c!i*i}-n3hTX8Cg^_I$4PBA?DCI^qDY7Lvta! z4(Mj#H%d<-#d&&Ytu_xq(k7o?Zagwv6Wg;r6$vy67frT&;j6dtJg|wN@rn=KKwfgb zlqvHAS)Nh>w?V4`E-?_a2%J&0QjKX83F<7(Q<3i(&zy=IM*I(T(==o(S(ogK*EXKq zgY1}^JB-wP;+5oNyrMX9veX-pAK3v6d^ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/2b/4ebffd3111546d278bb5df62e5630930b605fb b/tests/resources/rebase/.gitted/objects/2b/4ebffd3111546d278bb5df62e5630930b605fb new file mode 100644 index 0000000000000000000000000000000000000000..5bdfc1e293b2e28e54f072801b1f307dadf85351 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKTj;SFV484ZsWk8T$lY^VAlR8|EF&&z4D;^ KmI450zFr6;@?x<7 literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/30/69cc907e6294623e5917ef6de663928c1febfb b/tests/resources/rebase/.gitted/objects/30/69cc907e6294623e5917ef6de663928c1febfb new file mode 100644 index 0000000000000000000000000000000000000000..edd86f7212b38c4187f492a3ee10ffca0f694eca GIT binary patch literal 174 zcmV;f08#&V0i}*RZUZq4L{sY&ynq8zpIr$s0yi$x5GG{O}FfcPQQAjKUz(YdlL=PlT@x0- z(5+We|FB`+>nPcKd=0H!P-W>wiDi{wMMs{US^OsJfk@va!=FXr_j?TG7~`Re@+*r= zQj5T>c3Q4nDBR}o}r literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/33/f915f9e4dbd9f4b24430e48731a59b45b15500 b/tests/resources/rebase/.gitted/objects/33/f915f9e4dbd9f4b24430e48731a59b45b15500 new file mode 100644 index 0000000000000000000000000000000000000000..c33f179bf6740299549780ccd7d5be00a68fd38b GIT binary patch literal 186 zcmV;r07d_J0i}=IX#+73Mf0sHrhyn~RvKx+gg{6KX+Vz|TM(_nu1wmGV%&lM?gK98 z=H6NzfZo20of$A$P9kM7#yCp_eMrd_A!J93UKgE6J4xy%?z|1~*(V8(S0BU_6S8(h z;x!h`$$O%-=1{DtcpKNg!)N)8dx5WOZ%5zY%rpI0?|d&F?v#6b17qhHqDF#OZM9Z2 oov?$SoKYWrlkb{G-7e62sZw(sb>bKp9pW*+#mntbe@MPs-rqD>WB>pF literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/34/86a9d4cdf0b7b4a702c199eed541dc3af13a03 b/tests/resources/rebase/.gitted/objects/34/86a9d4cdf0b7b4a702c199eed541dc3af13a03 new file mode 100644 index 0000000000000000000000000000000000000000..fdbe16d1056485ec6c9a248617e4cff6f1b3a370 GIT binary patch literal 271 zcmV+q0r38K0Zov-Zo@DPggfgg?g5M}oq|j)(5*m&{tO*un~sIjqAF2!{Pv}V2IwLI z$0P3}dzK#e$K&1O!|U_YC*EE@&IjktRUr{NXChnzbAe3geP-IaKl!`*tW96NQtmL( zYE406!C?J0b*_Xf2A{K-u?*QK8sX#E>LIFN3glA_}WX6_J6`sRV5lggD-3} z&C6s+vtK%_L1!dNiE<+^p7rEzAcbZ94+55Wxj89YzR}inz`HD7rNC#hF^;YSG20gK V;~3O#20Mn%!OkS+cfTGlkBXSaf%*Ud literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/3c/33b080bf75724c8899d8e703614cb59bfbd047 b/tests/resources/rebase/.gitted/objects/3c/33b080bf75724c8899d8e703614cb59bfbd047 new file mode 100644 index 0000000000000000000000000000000000000000..8716898f8b4b2d0de04e7aca7784d3fae0266984 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK@U{2UVDqnwkbylkrVL->3ERJYmk8HFd6uVRz;*OoOS(FU`!!$pkC&t_cfZ z=+-N#f7meZb(HKqzJ^vVsIv5;#Ij1Tq9f1FEPj*qK&0=I;m@M*`#pwojPX!K`IW^b zsYMVQ*UKMwsK2@PzBuEGx{W7eN~Rp00aaC&nwSGtvwTBZa9#Fufm!>X{GYz9^vZ+s KTM7UIH(uX+on`0% literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/3d/a85aca38a95b44d77ef55a8deb445e49ba19b4 b/tests/resources/rebase/.gitted/objects/3d/a85aca38a95b44d77ef55a8deb445e49ba19b4 new file mode 100644 index 0000000000000000000000000000000000000000..fa6d9468d9743cd416b26d605c00b64a4cafe929 GIT binary patch literal 55 zcmb)7U|?ckU~CxZ;iYrRbL|!Fl^TgFYOa{2UTr>|b1%n!bJLA-D}AH2 L>Ff-dB?8v~G4&PD literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/3e/8989b5a16d5258c935d998ef0e6bb139cc4757 b/tests/resources/rebase/.gitted/objects/3e/8989b5a16d5258c935d998ef0e6bb139cc4757 new file mode 100644 index 0000000000000000000000000000000000000000..1bbf138ef8959816ee182524d53b063b68f97cfa GIT binary patch literal 174 zcmV;f08#&V0i}*hY6CG0hP(DDbb%E4F}4Ou=_bqUdI60k6GJC1uA5vxZpaO~`ycS} z<+ks2fLqeb=&DeP6sFbFiUFAtBIUrFB_FIq@fe~oE1PfbdKr*%+6pbYCMs4eWn5w` z37xpSr4-|~W|B}0|BiF(aFiQ&fzNZ>f7%7!bgqBtLm$Vpz2>&RgAEhroOd1$(+164 cr|i&wV$7*YEj9C~Q^CS$a8>>?cVEs_3M2Yd+W-In literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/3f/05a038dd89f51ba2b3d7b14ba1f8c00f0e31ac b/tests/resources/rebase/.gitted/objects/3f/05a038dd89f51ba2b3d7b14ba1f8c00f0e31ac new file mode 100644 index 0000000000000000000000000000000000000000..26bd353f74d585938ea58579df3ab22d48d9c821 GIT binary patch literal 209 zcmV;?051P{0V^p=O;s>5GG{O}FfcPQQAjKXI{9?**Bd#j>)f3mv*4bfny~2D_)hCAMN7amjN9Q9<#0Pk{#1Bprr6itkA= zVNg_Jw1ewSeAate;4H7W2wd-FTFVTF+|&;`<*)H$yHutlxKEvT)FEtbu+}uSjjj35 c7;`By>X>33+XRGKAg=9CyggU*20nXMRM`$uSO5S3 literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/41/4dfc71ead79c07acd4ea47fecf91f289afc4b9 b/tests/resources/rebase/.gitted/objects/41/4dfc71ead79c07acd4ea47fecf91f289afc4b9 new file mode 100644 index 0000000000000000000000000000000000000000..546815ea85b67a781ee20058cf01d24a99e81fc1 GIT binary patch literal 376 zcmV-;0f+v00X30LPQ)+_g<0nm?*N4zu;{ANRAK}gU}j*Swl0lG8PV}H>(6`^kmKZrahY+9PJnY2iAAObtXE@E8Rdzz4a zBLgK2sypm(>YmOm1~#^8BW;X@bBHZg9g7C7*vMLFH^J)|FMUhk{2_qqwC~^h7J*U@ zt`uR-S2h!jOI&l$sgb~ppX4BZE1ZVa;e+4}jRHBVAs3r<%xr}~FvYNOVrwNtYetI2 zs*?awTiF|j&!&F3h^a*SI(lX|XIpwlvUM>e#yw{@(R48@7|DpM!drA;A|`fJ^;D$r zO$9ak7K@g+LL}BPiPR8CPZ%qnc$^ARSr-NcHW-Z928G65EbM)~(0NZOtl z!OZ)Z$7KD4FWIcBc`C=Vu)D9bWgl7r_IxYLE}yFWt;|w{mlVakxs-v4L8Bs9lMq-BNAq z8EAaz-WjQ!Vlh$UYG{Q-Fk0y%Ws=G}hJA?i&Ugov2|3)!`mXQ0Bij8B4DH+aB;-7U zt{xv*Myhrm8YXY-T^AW!EBsZ%#2?v^M)C_aMa^D>Y^&r8&qSZkMOHHUx4!cxijw^m z=M|s*^OhQ1SEE+EpN0|NJFrK=7PhjA(i%KHA+UVoYCmHt9@zAMQ*{HZ0OO$_c+=uv z8V~GM&X_b$SZTQ8NUAfAC_8pmc#`JFL}-uW>+Y=^xadU6%VLz#j_eJycWi_n+?8{& e{23T56Gv7Px){6N-45OH7soxKe4RhpQ^o_eWWQ_x literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911 b/tests/resources/rebase/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911 new file mode 100644 index 0000000000000000000000000000000000000000..99b5e6d2c8f1feb318ae3effc47c16d1f66918ce GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKIQ$+tt_V?XZL0=CHjtW{)$$7)k<%=}6EQZzswSM!*~~;j!cnvP~EX zSirL-ckRFyQOpRN^(%a=U*3%t$V4C^DjxlyeAjw&0`_o0p`=Aqhz*qm-JBb2d)UMN z{q<9s>S{(#1Q(VG5F(SMDy2soywWZrgXiFzgc5JfBE?9l5oUDqY;YJrE&Hr5t#6iu>aRL){OVs*>fkc5 zo#0fmKu-{h7_~6hC@M4td9IgwZg}OiS}@bUsg^*+)<87^^EZu!d%{7fwZb9mPDj$5 z>4=I~XSGizeN+XS09&U+#Y85Tab(Nn#a&?tUX94oyY(EMeg-8gq9bd8p4iQcTT0*U N7nFE!egIA!&7-4Fu#*4) literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/4b/21eb6eeeec7f8fc89a1d334faff9bd5f5f8c34 b/tests/resources/rebase/.gitted/objects/4b/21eb6eeeec7f8fc89a1d334faff9bd5f5f8c34 new file mode 100644 index 0000000000000000000000000000000000000000..0c9f4b94442a6f1c02bdf0f802b3dd8af2e6e518 GIT binary patch literal 185 zcmV;q07n0K0i};!N(38;fPHqgU3RKbaJ2{%k7_+Ux4EylcQK({U=$;VVuMhfPW58VfBzBm$%!cnm}muaDu zi%OKFp6xnkJR%#uk6S||;On=mi{uY1kNqT#Rh0w3oVsP+?glJ|u nVTb;6#=Q2ud{h~Aze4M|mMT2z#32|R_?+MPdOyuKG7(zc>!w_V literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850a b/tests/resources/rebase/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850a new file mode 100644 index 0000000000000000000000000000000000000000..016398531ebf1408a8bcff0d4a2974da890c3874 GIT binary patch literal 615 zcmV-t0+{`H0Zo(5j@vK{gnRZ=@BzF*+grQ0qCgv9fi2Ko^eo%7Em#pD%8Onl|EL(9jB2A{ZB9%z(Q zDp~`0c9}Zy!LU4TnP`R_a2j)I$sDeGffp+4!3AhA43rTJ zWFou6(+HCX3{H(@VP2uCCwfgfFK{R0k?|pZ5Tn=5VX^q(kEe+?4x#DTDaRH8q9={` zWw}8EEsSAvd9G9{tKCHm=?0zGU48B3V`RP-+bXJ(v;jb>SGxw2^@RZPNXkU^> z6Gz{R_OmI(24P;kl#I&RsBV>}TARmX?7g^Q>{EiS6pz508ZlJQ-6Vs%~M z*Ma+pM6e6PV2lD}J@`D|vUsy84q^v%_ahx0 zZtJ=XupU1~7Xd+J))bOS6rE3r1;rH3Xe8U5Nw!-G&Z|G_avBgh=89fY#A=E`);@$9 zwJnx&j3MO2SX@H$svRXNPXPn-Y% literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/4c/acc6f6e740a5bc64faa33e04b8ef0733d8a127 b/tests/resources/rebase/.gitted/objects/4c/acc6f6e740a5bc64faa33e04b8ef0733d8a127 new file mode 100644 index 0000000000000000000000000000000000000000..36a6b31fa528d31d4146f769ad035622cfc17e91 GIT binary patch literal 169 zcmV;a09OBa0i{k$3c@fDb)8ep1(f_I9}scl(w!HWBvV?jjnt^uH;OlK_x`+G=Xq+N z(Qn$y4Bko#(sGE-c#Js)#uRdjO0z;@Z^@G-CvLRz(!lg&hzUu#f*M1P221R%L9$Cp znV7Tn=mkC6SXVfe7p(;@W1a7HfjxKigO2<)er%WPd;n!7I<1Wfu$5Ly(bayo@t-r| XT+1{}ncCDZXlNClOjq#+-(ypL0Nhed literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/4f/b698bde45d7d2833e3f2aacfbfe8a7e7f60a65 b/tests/resources/rebase/.gitted/objects/4f/b698bde45d7d2833e3f2aacfbfe8a7e7f60a65 new file mode 100644 index 0000000000000000000000000000000000000000..8bb69d099e4c24aaf740ed6715c778ab5b6ae415 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK3ERJYmk8HFd6uVRz;*OoOS(FU`!!$pkC&t_cfZ z=+-N#f7meZb(HKqzJ^vVsIv5;#Ij1Tq9f1FEPj*qK&0=I;m@M*`#pwojPX!K`IW^b zsYMVQ*UKMwsK2@PzBuEGx{W7eN~Rp00aaC&nwSGtvwTBZa9#Fufm!>X{GYz9^vZ+s KTM7W$Mql=Ok7!;1 literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/53/f75e45a463033854e52fa8d39dc858e45537d0 b/tests/resources/rebase/.gitted/objects/53/f75e45a463033854e52fa8d39dc858e45537d0 new file mode 100644 index 0000000000000000000000000000000000000000..f25ef1f7324af817bcaf81538abfee334484440d GIT binary patch literal 209 zcmV;?051P{0V^p=O;s>5GG{O}FfcPQQAjK29G3?G9hG{T0`K6gTIhkN(-ZfzX z4BdJq^$#27y^fN-$Jfxx1yz<_lvq{?R&?aqnZ<9i9*Fc^GW=N-e!s_1jxippD8I6} zB((@)<9hky4)r(J-WO+FQMd7AOv#j^GoY%CE5Z*ACQ{6DTVkY8AYMy|hw_L5FPT ZKX1gfmATH8`aBdY^ah!^iZ|$ARGmeBQMv#C literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/5b/1e8bccf7787e942aecf61912f94a2c274f85a5 b/tests/resources/rebase/.gitted/objects/5b/1e8bccf7787e942aecf61912f94a2c274f85a5 new file mode 100644 index 0000000000000000000000000000000000000000..d4776d883ee806d9e0f3db1bec254d13b32e84fc GIT binary patch literal 368 zcmV-$0gwK80Yy?vPQx$|W$jbU0V;L~q^<%gAb}`q=>Z&P(pYtE*B(>#_B=ZUR=vp`s&_R^t|3}=)K##tmtv~@$|adQW#0+sFU88 zyr687j!ag_Tf^?MAX5aGk%C9rn@OQTCMF3Hc&RqUP+ZjYsk{}R=>29o*)pze3s!@(HgZaHG0B`~z>B{okIC_ZN zPFA73wV(*RVIcvAxSIW?~y8oNseX~M`8*ZY*S~V!lE<OjE8sRBb3pEUK9Cs=v6GX;!yjYp*@sb4=nMMy!YwwbAlW})~ z?zwBiiDOidd34h7wKe!@Z8h6Rq~N#1Z#3WA#0)K zIw2WxW(JNNwygz0HW=b~&bbg(>Yg1is#%Pwr_fmVCwjqcu;0_85Adz-w7WxWKhdC< zoF`3<{{x+a85xKNoqSZr?Wi>&!b#l=_bnRG3`ucuCt4zLkOsPRJU|&isHx@oAAjRi z2QJ&O&5~f$E_pS0B4iT%kr@i^>AU05AV|0V^p=O;s>5GG{O}FfcPQQAjKTj;SFV484ZsWk8T$lY^VAlR8|EF&&z4D;^ KmI45=n_Vvskz(Ee literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/63/c18bf188b8a1ab0bad85161dc3fb43c48ed0db b/tests/resources/rebase/.gitted/objects/63/c18bf188b8a1ab0bad85161dc3fb43c48ed0db new file mode 100644 index 0000000000000000000000000000000000000000..297c43225f8c359087078b579c081b0bbe8bb1eb GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK*bF-)ZbitUz~A8-NutKB~y;hfT}7>P0RtSS-v4HxGwv-z^wgG{!ialdgVd+ KEd>DQk6#foUS&!E literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/67/ed7afb256807556f9b74fa4f7c9284aaec1120 b/tests/resources/rebase/.gitted/objects/67/ed7afb256807556f9b74fa4f7c9284aaec1120 new file mode 100644 index 0000000000000000000000000000000000000000..82da2062677f502302aa7a53e4da9969082e7573 GIT binary patch literal 391 zcmV;20eJp+0Yy^Fa^oNn%$cv44^ZWn%2wrs9sH!}5JK)gl#aaL{ulTw?5G|304^5(m(0PR9?_yqiuR|e>(&7u_ zudmP_Yxpzpw(l~>k@uplV06ab1<}}Y`k5wZ_)G?AJU3yLK?`e!w^J)#)~`ji=kUB$8BMjIypcL0h$;xRP)6!ZczhVDt&1Uz7p0H#<{OJl97U zgcwL^i5W6ZZB!^p_&s_KCn&Y+wT76b&1wP);T2CVV{KWjLBcUKIyRwQV5gK<6 z)~_RqSxxl-GK~?&j23};H_~@_E=n^{u@yQ>XL$7&gwgEO=&L0>iH;?yFt$ALrztI(nqaC8z&a>7Zp&I8pAN0WCFP$2O-q(?ym5+LeLvPrCSY~yt{$?L+G6)tk4kU%Y>M`aoYkefxZI?kit~>LRrGIFjO%(nP(;)X}h2946ur z+LbAYF6|e45M+MnQfz#Cg!Q=4 zcScoIbgOWsAqe9+zywtAm4JvTr`nO`;^Q?4rJEG{3*AXqz;l)RAP<^TiqjU1LQY#8 zWu!jvaHT9cOX*tOx+lA!9O@(b7D2)2Q&eZP)c?X6q-l}(Qc33dRH8Kk2>NQ?wqlvpHMgV+B-53jsBV)y09GA#Q*rNI9BU?-PR8n4rX8b{NiUDrkJS z#>IVIL}6sEP#W!F$k9Vhr9Eu{287ne%oiFZ_yGf?T1>7bFzwL9(DilYug92+rlY;JP3e_oWtY%)Op0?3(po5hq;V1r2sz+akEz z?=)AlD5y6_xc@uC++(7eNLWJI3%(6++bHOZXBm1=GNfpG~)RDjN_rhufx-;;DxjjlJh(-?aX+$^5+6=ag~We1GPF|r(%+3i*>AL zpz*bPW2EvGiw=aVPAeq5CPhWcB$cxayNh&II}4Q)vcHq{UEg=_Xb(Rzw7hO_eNY&1+VRG8sbtP@;34hfv@kiE)5Z#iRqUIocHdXS4cY@33A}eb8q&sg+L9)N% zyyCNePN~6l)oR7tX&CXN1A7!~VJlITQSZ_tJj>U%&NHUsg^m83stK?HjK_Z9q{Y8B zcI;Kon20xw)O_Mfsxz)ATXt4>BJpKR-~_ZXT&fHtVqO-lG}&Zsn4M)KY3Ht-i{Zz> aU^#JRwV{hP+wPXaXMF|PKZrk3!pMUQtHI6y literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/6d/77ce8fa2cd93c6489236e33e45e35203ca748c b/tests/resources/rebase/.gitted/objects/6d/77ce8fa2cd93c6489236e33e45e35203ca748c new file mode 100644 index 0000000000000000000000000000000000000000..5c3f68625e3f4f0aaadf1c44ee3384580ecb31e0 GIT binary patch literal 54 zcmV-60LlM&0V^p=O;s?qU@$Z=Ff%bxNJ=cqNv+f?sVHG+4&M3m-v63{dJR7Q)SQNL Mol`Y80czY4z%bVr00000 literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/6d/fb87d20f3dbca02da4a39890114fd9ba6a51e7 b/tests/resources/rebase/.gitted/objects/6d/fb87d20f3dbca02da4a39890114fd9ba6a51e7 new file mode 100644 index 0000000000000000000000000000000000000000..039c669aa4745247d956e7870c24de49d9d7de79 GIT binary patch literal 364 zcmV-y0h9iC0X309Zrv~pM7!20<^XPXZ5Cb?NEQJCKnOzDaBox zvZ&#k;S_noulwIW9{xT(KH&2B2d^*hmpkX){FT6o@L7FP@CwN>C^C5&zy;4?_n62h zJ04q@H~2#KLzT*iTot;}?n1I}p;Jei(2dF$gjdDktrr)s z;(S^lKI({xL+skngRyZfGGh1AG-$^`F`{*6FLL&6h3kg_Itg^65rwpt21bbCvxWsB zDfe?`9jplRl@iQvhx3TOd=PS=*-}~ERGZB{W{pN*m}c0#3hxAoVWw_1S<$hPxm<_- z;1qL8{-SnJM;Q$c$&MX`$sbYZw~LRpV_s2!h3S)AgKCxlu!{dBo5GG{O}FfcPQQAjK`wgTT#);VL1Q* literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/78/c320b06544e23d786a9ec84ee93861f2933094 b/tests/resources/rebase/.gitted/objects/78/c320b06544e23d786a9ec84ee93861f2933094 new file mode 100644 index 0000000000000000000000000000000000000000..afa39fb97a7285366c61beb28a08de6cfe213a5a GIT binary patch literal 55 zcmV-70LcG%0V^p=O;s?qU@$Z=Ff%bxNJ=cqNv+f?sVHHXbEWzDE#=0!^@W%GW;i!0 Nn|GuK0|0Sj5tU3%7NGzD literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/79/e28694aae0d3064b06f96a5207b943a2357f07 b/tests/resources/rebase/.gitted/objects/79/e28694aae0d3064b06f96a5207b943a2357f07 new file mode 100644 index 0000000000000000000000000000000000000000..17ff306f1b1c90b6d15182494094742e35161dbb GIT binary patch literal 287 zcmV+)0pR|40Zov>YQr!PM0?g(%mLqa3eefg-8Wx^DiyYeS%? zh1p@|?RM68c;0TGUh=vuzR*)tr_=*@*Pkw6k>mrTco?@KCA z(V4Jjspcau%N;szEDYmHj_n;hdyIaHX+a`~Ag#t>5D7kFFh7LgC)cl(Vo`Oze@9j0 zSjd!)+r;dh0IcxI3eD=ZBuJyaWta_*2owUvl{{(7JM{ob*3bVzV7u;KUf{r9HiheI-ty}@!_lD(XkZ15{5|S6c`U9#JimITSx8*(8$#EyR!>@FuHd!i*h>@%iF-4IZZO#+ zi%Dd9-3CUTLRPfZM_J&)FIpIGk20-ghNCq1qt5aLzwMC9bOPfw25Um}u-EO8YHkZ# e<erd8iEDp67Z literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/7a/677f6201c8f9d46bdfe1f4b08cb504e360a34e b/tests/resources/rebase/.gitted/objects/7a/677f6201c8f9d46bdfe1f4b08cb504e360a34e new file mode 100644 index 0000000000000000000000000000000000000000..dc2fd5a364be82bbc29f6a57f61bbdd1bf3c3a14 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK2344pnwkbylkrVL->3ERJYmk8HFd6uVRz;*OoOS(FU`!!$pkC&t_cfZ z=+-N#f7meZb(HKqzJ^vVsIv5;#Ij1Tq9f1FEPj*qK&0=I;m@M*`#pwojPX!K`IW^b zsYMVQ*UKMwsK2@PzBuEGx{W7eN~Rp00aaC&nwSGtvwTBZa9#Fufm!>X{GYz9^vZ+s KTM7VOOc2kZG6Bm=nK+xp>A}>x~?VH_7?k*tmy`824fU%b(Re8VaFWcI!i2) z;F%8klV0gp{I#=}_yWf2)-|T>H9TpnwL0i=Ug@7R>N9a=Tp-h(3rkY!4JO*5$hIEP z^GXG#ED=uEnc$1_jT0k$$X00QiB6AzcjN`fg@6;(nbf+C3wsC>k<(dy15#OGDOags A)Bpeg literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/7f/37fe2d7320360f8a9118b1ed8fba6f38481679 b/tests/resources/rebase/.gitted/objects/7f/37fe2d7320360f8a9118b1ed8fba6f38481679 new file mode 100644 index 0000000000000000000000000000000000000000..400df288f6021040a8af9f585f820ff2095f6dfd GIT binary patch literal 176 zcmV;h08jsT0i}+;ZUQk7gsJ@$`vRcz;yZgKglJNxOCS06N4PkQj8R@c2IUQ+X=c8W zM#FX6N(WqU*PALN3!)3h;-b7f+GMm=jq(@|w`k z$s1cV)MSFpL0o?JYi;l$Ke-8fUF-I!H#q5_FL%**@s|!WR} ew(CD<+-H?yg>x_CLV#)@t*Ct8HM?I}Bv*$}D^w-` literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/80/32d630f37266bace093e353f7b97d7f8b20950 b/tests/resources/rebase/.gitted/objects/80/32d630f37266bace093e353f7b97d7f8b20950 new file mode 100644 index 0000000000000000000000000000000000000000..07050dfd44136505c12ec4dcd1f39f103d82658c GIT binary patch literal 209 zcmV;?051P{0V^p=O;s>5GG{O}FfcPQQAjK30Yy^HPQx$^=A5VS1614)NSrDd3<3d> z{kFHhhr5USn|9Z=pY7{m2fOW|yH#qhXN1w`2v)}GUaAb6K@a{_X3){L$vKZ1Qv~AVVU;_hggg zC7-QOD$vsm4vs@cI|-&(nCk5V&-=1G)fIA^Y@`l0bnDy&VRWvgLL-pk{K5?4{ zO2NgIW%6jf-=SgW;RII-;%|_dG4Pb~qC^2vx4M8{BXC0Reh87L(5;qQG0C=H%P7$D z_82D-4l1z9XRkJE*OMv@b}TSE84xK(N~?LcUUud#l0DD=Mc_GH?@da&Uu~zjLCvET h&ajCTW9YXf@AVh3UFSq^20exhE+ez{%^wT%jEbb@jJ*H= literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/85/258e426a341cc1aa035ac7f6d18f84fed2ab38 b/tests/resources/rebase/.gitted/objects/85/258e426a341cc1aa035ac7f6d18f84fed2ab38 new file mode 100644 index 0000000000000000000000000000000000000000..af1106d6aa290c265027ee5b7fc80267ad3b9dde GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKTj;SFV484ZsWk8T$lY^VAlR8|EF&&z4D;^ KmI449`dfQT@;^+W;)Ccs9nFBnz#p_k~>W zAqDnm6S^g=QERK{Hm-e#PyVHy;p^Jl(Kk5DO#jup+>3`h<=)<4vFNPz)CBvww1OEXD697RvbI)u?gYn`NnC1 zW1RW<{-*V@rO%(fe);hI+ru-xp5D#}W6p0EdV0B>=z-3s3*|8}(|fTg3&nv}n>jVN z=NMcJLS4xuv-Q5A7}&g?Pp6m1w`VPHz3nDicv(2n5=-d0Z^(w8@*1^3tj`UtE|2?5 z+D9AluH(AVvkf%b`AD8KxlCe4fnAmkzfDDK>h01{zKy)ET z?YAVO3%dL#TVVcwtfH#ZjE~{U=}6g5OcCvvL;p|#(9WYSjl)p?UlUtlasw!CMli|u zl$zmUfcI1ac1hq2zz>3Y!c7gQGH7LFNtM= zr_^rLGsv+tMzTvP<33&|)q1>CfmNm@!qYB>>_TzjO3=M_6}))u9jzF(5nF2xZmvU# zP%>;s!>;>H*JM{bz;l&OHz>~oJq<=bs*GSwA!cMP4cuiULsn+sxa(A03j&VJx?+C?LZF!qj2AMZS^Ydn~LCGO?!`jy_-Z+ UDBYww!6^*WL`puGKPB;mGf7D}^8f$< literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/8d/1f13f93c4995760ac07d129246ac1ff64c0be9 b/tests/resources/rebase/.gitted/objects/8d/1f13f93c4995760ac07d129246ac1ff64c0be9 new file mode 100644 index 0000000000000000000000000000000000000000..a66cfccb2bc318159af2cedcff77d81d65c8d559 GIT binary patch literal 173 zcmV;e08;;W0i}*XZo@DP1bfyi_<2Esu-|*kQw5>;ojA^8pnc))|G3<1g b?f&LX_-VG(MWrvh0zq#uyVvjn;+s=|VEtEp literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/8d/95ea62e621f1d38d230d9e7d206e41096d76af b/tests/resources/rebase/.gitted/objects/8d/95ea62e621f1d38d230d9e7d206e41096d76af new file mode 100644 index 0000000000000000000000000000000000000000..464de7c1c67de95b3798f383ad501ed6ec841d91 GIT binary patch literal 773 zcmV+g1N!`U0c})GZ`3dlD8OJuU}m6_aEv0>*KebF%MUt_w;bHr<>cm4|I>e6bEXVhlaYP z;4qN&p31~Dc$TUDM^B!|i#7&s%+t;7`y2Z5c>h4x7>0>=boF%goj4Si*`FGUxlWL{ zBw8KjwM=7XE2kYjSxm)5GqWw!dA5OU=*im?xk3&nO0hH~DZ6m+O!3HBzruEs8SqT8 zt>+6#F@|CBN+HE1^xRYHZFiu=DRFM<+_FZ!Al8>l?9GgU!Nnj(X^H!VGf30K;iV9d zKa=`&NqwY%ou2g;8{MyitNabM`eS=gu?GDfIxMq_!f-%6 zx1#W}6Bd{ZHT5`IF**cV3`+bAE@4|F;#&;ff? z+zut#Xp|VuymZr!J}m-;c!-(l6qijMaMnPyIj&UzuvD>z=zUz(quGYQ`5i$5W1mCw zPn-j?avmbfXcaCJgr>NR?8pI~Vyy_ga>dj*VF}uI4hA>?Nzv-zb7l{gwPZ0KgwUrG z^)?@xEsk|K=2(cMMyR8k8?YJKfC=PXDfkMNh1zaLk_Bx?Lr2~4{AM6^o_FTHWLud# z*;wc`-9MvFxV|zLtgh6D;2gg#Ts5MgUK3&dp9oElimD>Pg5(&VinqQf*b6uC04=C` zsQE#bpG&t9s#uOZa(zeyt=s}B5$P+@qFH!K@L<)7YgDzojZq518EpcICGE^_xw_;v Dnyhto literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/8f/4de6c781b9ff9cedfd7f9f9f224e744f97b259 b/tests/resources/rebase/.gitted/objects/8f/4de6c781b9ff9cedfd7f9f9f224e744f97b259 new file mode 100644 index 0000000000000000000000000000000000000000..faa9389585ad1c58869cda0c046608f875cf08f3 GIT binary patch literal 89 zcmV-f0H*(V0V^p=O;s?rWH2-^Ff%bxNJ=cqNv+f?sVHHneAG5&)q~4y-fTa!g4lOD vFEXuXhpI{`%1lj(FGx)UD|GbzQ~2uo9QHL=Ub+7}Kk-xN`Xf65VL2pfVTC6A literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/92/54a37fde7e97f9a28dee2967fdb2c5d1ed94e9 b/tests/resources/rebase/.gitted/objects/92/54a37fde7e97f9a28dee2967fdb2c5d1ed94e9 new file mode 100644 index 0000000000000000000000000000000000000000..10d6c134f79dc2c9b1cc52f4de37cb7023bd9083 GIT binary patch literal 388 zcmV-~0ek*<0Yy^FZsRZv>{(yI4={QwTA(L2bsp%V&ia9zWrdD~D3(^D8szVnQi}Fu zi5kvuI3BGV;pyf1L3VrD%FWP0*9`kdA$s{y!@3z-_#@j*4R6EeYFl^UCQ#9Liiw;*A^t5-EJ^P5~XpG?c7;e;$|7@bE*{x0UxdklpzDod|I zzQ03%XyET4+rG;j2iezc1*0?eE=b0f)6X;k;a@VutVV>O literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/95/39b2cc291d6a6b1b266df8474d31fdd344dd79 b/tests/resources/rebase/.gitted/objects/95/39b2cc291d6a6b1b266df8474d31fdd344dd79 new file mode 100644 index 0000000000000000000000000000000000000000..96494347320439eb5c1ad707c012d5b0c63194d5 GIT binary patch literal 173 zcmV;e08;;W0i}*X3c@fDMP26MJJv@MCa8xrCwc+)(H<3#N4>*+(0P@8*@M}9mgyYV;JZx zR>>2kgc-TxOokurQYswMlWT(0rA+rS!&VpiNqhYczqXMw?VuyudqkoLYfILeg)Xv9 b|GY8BlEyp=w{cNGXa&w(ulh1?8wgbbVHi$j literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/9a/8535dfcaf7554c728d874f047c5461fb2c71d1 b/tests/resources/rebase/.gitted/objects/9a/8535dfcaf7554c728d874f047c5461fb2c71d1 new file mode 100644 index 0000000000000000000000000000000000000000..d997426b2d01f1d596d14be0dba16f05f3f17257 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK*bF-)ZbitUz~A8-NutKB~y;hfT}7>P0RtSNzgpaU>*5g;OC0hH*d{5r(4X< Koe2Qbh+MNWE@jsM literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/9c/d483e7da23819d7f71d24e9843812337886753 b/tests/resources/rebase/.gitted/objects/9c/d483e7da23819d7f71d24e9843812337886753 new file mode 100644 index 0000000000000000000000000000000000000000..d1684550681cc4bd913621c40b0d0621dcbb7d34 GIT binary patch literal 284 zcmV+%0ptF70ZouWYQr!PMZ4B1{sBxjU4^XD654><1lxgjDcj>%RMDu?sIG5c*%0VT z@aOa9X ze9}Upz(5n&8Fmp}5+q-!`uKt8eN~;B8nFx7QxEO>b#9z6dec#nBT&ZKh3Uk|yig?t zXZ*@i_1nHIcWBvI7{QgC*cmc0Mou9vO61`4R^u?_2plk&AA;xP`qeU5RM6emGIF%M z18zx#T^3m7qs=yJ*HTs*^{v2UWP~U0DXivETiL0*NVGit7lCDWy*DZ3{n%WNrQhbl)4vH$y&#j3y#-?yEm`gp2BpCXCGh literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/a0/1a6ee390f65d834375e072952deaee0c5e92f7 b/tests/resources/rebase/.gitted/objects/a0/1a6ee390f65d834375e072952deaee0c5e92f7 new file mode 100644 index 0000000000000000000000000000000000000000..eb98c9da52e3cd72be5a7d30edea584bb55ad63a GIT binary patch literal 90 zcmV-g0HyzU0V^p=O;s?rWH2-^Ff%bxNJ=cqNv+f?sVHGEXa?1$}JmNOlk`R=OY w9jlL4%urP+MVYB7@dc@gV1uW{5w(g(b{qLS_(_MzU-=E(B0KfJnYtAPtPyhe` literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/a0/fa65f96c1e3bdc7287e334229279dcc1248fa4 b/tests/resources/rebase/.gitted/objects/a0/fa65f96c1e3bdc7287e334229279dcc1248fa4 new file mode 100644 index 0000000000000000000000000000000000000000..fd43545ce7250baf8e056bca9093ea16438a6ab7 GIT binary patch literal 373 zcmV-*0gC>30Yy^HZo?o9-kGQH14O+|o77V_wX3vgshaiy2yq$|0u)T6zWofXx>LY> z{(kIq#&z)e{`OM0`}$CSomyy{(|#qyvHsq`wmBW(r#^gb;N$fBx!bhh29VLqAkQgQ z5LJ*KK@(W5(A+9ei5N40vs|`n6wMZnyA2$heOrOFJs5cd8gb@lSR`TKrqTIagGka$ zvA{eN6_~U6D+V197EL2a@ER3nE1gu%GA)yaGgqu;bheQEUCg8R7z$yOhSoy%J<#Id zl4PKmIUXK5r_EiEv?-^j8y3DKO>EB%RArDAKAB>9=4){2oNYyoSG?;+3X=2XOoboF z@sui9My*DeQzYmRIHTYQQyxWzdPnPAULGRi{b1*LPs=7qHvNF(F To9U4j!?pYc$*;s8InT_4whp^i literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/a1/25b9b655932711abceaf8962948e6b601d67b6 b/tests/resources/rebase/.gitted/objects/a1/25b9b655932711abceaf8962948e6b601d67b6 new file mode 100644 index 0000000000000000000000000000000000000000..50bcee1092e976df746cf3c81eb020b8d28dad1f GIT binary patch literal 89 zcmV-f0H*(V0V^p=O;s?rWH2-^Ff%bxNJ=cqNv+f?sVHGEXa?1$}JmNOlk`R=OY v9jlL4%urP+MVYB7@dc@gV1@6LkG^}m_D5t4|2HnP-056maptxF&G#b*m=-B~ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/a7/00acc970eccccc73be53cd269462176544e6d1 b/tests/resources/rebase/.gitted/objects/a7/00acc970eccccc73be53cd269462176544e6d1 new file mode 100644 index 0000000000000000000000000000000000000000..e5c62dba737e0fd0aff0bdc27e10fb2c7000f1cf GIT binary patch literal 373 zcmV-*0gC>30Yy?vZsRZvowZKE0|ea_GeB3yG-wOVq(+k*fR^c)up+4v)gZSorMT_N zvi$gd^x(n(_kVu>>h^v2);%5fuzx-Fcg7rWA(%o*;4qyChT`o^8NvjZBPKkRyn$>J zMgkV_Y{^|WV2dbbg4f*^UUq+~Mb z;PAZtuT1r6CQbwwmKhKtlcj29KpVW$t|o)$;G2aKZ({wn@3(Kz?H*y@{X0Au97m8# zfcJt)TAbCx5ZK*(3A=WJFE=XuURVfnm}FDk>`W}KSw8Db3guL7Wu_0h>1Ii&`D*gU zulcp54P0inGn`8n7zkn!qY;)`MTN#75A{;t8(ulB4lMK&sx|Ocs8(RUx3O~1I4ZSH zIAlHPN?I~qQSq9r>SWT7>OdP{>vXA@$mB9jY?-{cD~!Qw5LvaG=H&EeP_iPrvbLc! TyJbyF>7)GxCEl4&Z*R+kPO`QW literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/a7/b066537e6be7109abfe4ff97b675d4e077da20 b/tests/resources/rebase/.gitted/objects/a7/b066537e6be7109abfe4ff97b675d4e077da20 new file mode 100644 index 0000000000000000000000000000000000000000..54f9b66175cf9c6bd4592ad9048f2d45c195beda GIT binary patch literal 621 zcmV-z0+RiB0Zmi8uGBCPrS@0M2ZR+A6lkkkfP{p^l@L%*lF7!3W9NEoLil>lIJ-a@ z$8+Yq+=tZD+c)puz54#)=`(%(^6mNJ+;c7DV@brcr9x%SBJ@%@7o{}O&P8%}KTgr7 zs5D?iR}P`06vgS5Qk-hA>wVy1p-r|;GVp2~W$cLKNM%oUK{=F;c3<2ht)u`f#+VIn}IJ(#5a1;LR5xTw{XwHZoM`8?_-rwp z@P^dxM!&$W#l%@j6TqjDy@99J~55yH+;^16EI%6By~P^H2JJZk{8o{uLe9rQ=)d} zB^n27;L9v4oM~y$B>P|eKDrrN?vHJ^2IKD0RzoLBX4T(B;NXRR*#DKsJ8`cVJdCPa zs}VUxw#?c)gS4|xDTd=hPZ3af-w$u?RXjFT#d~%AqyFvPWLjb!7V`;70n8ey<>LMT HT=<4_?*22G literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/aa/4c42aecdfc7cd989bbc3209934ea7cda3f4d88 b/tests/resources/rebase/.gitted/objects/aa/4c42aecdfc7cd989bbc3209934ea7cda3f4d88 new file mode 100644 index 0000000000000000000000000000000000000000..628c2d3a109f33e301d5900c8bf3e0402592492a GIT binary patch literal 137 zcmV;40CxX)0i}(>2|_UtL_Md9Z9v%{68!-YJ=lQ_Y_c1Ez_<`2V)sU|18*~LU|!N% zO9zX7)td;2WE5ucOcWfG&o=DXF-OlirYX#rF`zZ{=!-Tu^OG9GWzl-q8|-D!PddtX r__a;adVtBH-&*UY8P@0!&7ecx<)VlKT5y=I8iuJST(Aqz%#OkY6v literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/ab/25a53ef5622d443ecb0492b7516725f0deac8f b/tests/resources/rebase/.gitted/objects/ab/25a53ef5622d443ecb0492b7516725f0deac8f new file mode 100644 index 0000000000000000000000000000000000000000..83ef51e2654b9c3460e951ccdaa52260844a7292 GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK~@o7 zJ<40=&xr7?f+|c(O-%!<$@nIr@6&pDo-pUlnmX6Susd@Yroq(YmuBYVWP+7>*MtQy zbnBJWKWv!yI!g8)UqdSwR9SjaVp%0v(UE6o7Qe}QAkufq@Mlr@{T@R(#(1cr{L12z z)FOzD>*bF-)ZbitUz~A8-NutKB~y;hfT}7>P0RtSS-v4HxGwv-z^wgG{!ialdgVd+ KEd>DWwO+qwUS|9N literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/ae/87cae12879a3c37d7cc994afc6395bcb0eaf99 b/tests/resources/rebase/.gitted/objects/ae/87cae12879a3c37d7cc994afc6395bcb0eaf99 new file mode 100644 index 0000000000000000000000000000000000000000..5c8469eb9ec9c18ab737bd885c21450572151696 GIT binary patch literal 209 zcmV;?051P{0V^p=O;s>5GG{O}FfcPQQAjKNcK?DVcI~22@p9YGMvp&GHRt!FAcs1!nDk@_+ia(kl`J?ZufEEJAf-_D-u@ZT#O)rhtjqaVDyv%G9!HY=)D_s cobCGNjJveD+FGQq;{ri%FsqvT1!GE7FCX7iF#rGn literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/b1/b94ec02f8ed87d0efa4c65fb38d5d6da7e8b32 b/tests/resources/rebase/.gitted/objects/b1/b94ec02f8ed87d0efa4c65fb38d5d6da7e8b32 new file mode 100644 index 0000000000000000000000000000000000000000..d15c022462f3cd0c3a4a4ea6f98fa0576f61b6cf GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjK$0B<%-a9t|MYF8S00q# KQUCylv0c)~(q-8I literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/b6/72b141d48c369fee6c4deeb32a904387594365 b/tests/resources/rebase/.gitted/objects/b6/72b141d48c369fee6c4deeb32a904387594365 new file mode 100644 index 0000000000000000000000000000000000000000..d8cdb71ae13ae80a05daff42de02deb48ee858dc GIT binary patch literal 174 zcmV;f08#&V0i}*H4gw(%MXfo-TtEY}3(F+N*jU=xn_(Fu#fm|U*OxWk!0!L|lb1i2 zWyuZD;igp)V1qVLaMsd*lQA4-;pE97jb2=E+C(=6rygA8-ass-G-?~!hDnT2(1b(- zCH5=!CW+_KDt@(Fsc?#Kt`RP`vOLQj_R{H^j`AITZ8w+Y0HzBZqV*GO^{BP#w4ZJA cr$(Ji%qh>@a=(C362zJ%ULV5h1H^|_uxO4}4gdfE literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/b7/c536a5883c8adaeb34d5e198c5a3dbbdc608b5 b/tests/resources/rebase/.gitted/objects/b7/c536a5883c8adaeb34d5e198c5a3dbbdc608b5 new file mode 100644 index 0000000000000000000000000000000000000000..b59498472d3216b7973d5869d564d31fe8e40f15 GIT binary patch literal 209 zcmV;?051P{0V^p=O;s>5GG{O}FfcPQQAjK(d zZoQKFhYj;yN6FsfYiQ+yDoZa)EUN@7I`Zty;x}0jMEWin{wxZ=-(x7p7!OsHUs+s| zS_D>=v0nbTL;cOQ_r)1k)NMQ&Q!?e~45+HI)WjUHn&lhPg6p!M3(VU8fdA3lcKNMdp;IaP4bt@R&bB%kaF`{k4q99H~9pk$G^UU<5?NuSRaHJJZF|;@RJi&JK3b}2X MUoIM^FWTB<+qrsWC;$Ke literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/bc/cc8eabb5cfe2ec09959c7f4155aa73429fd604 b/tests/resources/rebase/.gitted/objects/bc/cc8eabb5cfe2ec09959c7f4155aa73429fd604 new file mode 100644 index 0000000000000000000000000000000000000000..de778eb118669059ccbe155d19634dcd1e470437 GIT binary patch literal 207 zcmV;=05Jb}0V^p=O;s>5GG{O}FfcPQQAjK*bF-)ZbitUz~A8-NutKB~y;hfT}7>P0RtSIVx_!;_$YjE&iYVLW7;fZKB81 JBml?@Te{XVWxoIb literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/c4/e6cca3ec6ae0148ed231f97257df8c311e015f b/tests/resources/rebase/.gitted/objects/c4/e6cca3ec6ae0148ed231f97257df8c311e015f new file mode 100644 index 0000000000000000000000000000000000000000..2bbf28f57352c06c42eb8b2a5eda9a9dde1ece90 GIT binary patch literal 268 zcmV+n0rUQN0VPl|Zp1JQ>+DzX0l7ngPDQ6qH@4`Z1v)B;k{EET)RHf_-&f9U0!fjS z`XoJGUZ0;XU++J^xPE+pof#bXwHmP}3$b>vlXKxQayA7iCMh_$#kW-I)?tsfJTTXXze?Gn-CKv9j7x_W zHAzacAF{2;z^WKy;la3Z&6Dhms}*uz4+zcMhaz=eK+woHepo4&oA)xfpxxpLM};ir zrDm*BxcTK^LfQiQ!ZfxsqrJg)fl;6Mq?<_AsixL-t?FU2Vjxp@-eXFjaRh}aX2z80 S=1+q8cKeOjJBNSmtBjvLQHhWM literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/c5/17380440ed78865ffe3fa130b9738615c76618 b/tests/resources/rebase/.gitted/objects/c5/17380440ed78865ffe3fa130b9738615c76618 new file mode 100644 index 0000000000000000000000000000000000000000..b9a52a310682a51ac5809bc61139840da64cc557 GIT binary patch literal 649 zcmV;40(Sj)0ZmiOj?*v{W$mxHA5bb-us~f^qZv`DG?m%`v2>D~#)@MHKM3LLIoHV` zmT~Umyl!oMO&>pe{`BtK^YKi#>h-!;>iT-8)8$^#k*?L9QXiP&PO&nUjRg-#FES%XVzD zBp9_zSq+{DnM8kLhJt(gF8@c}Zoo}M<04Sim<7m6vUpbR4Aj;ElrGZ95%L{C!sUNhLukmA>kmntA7OB^SM6gDSsG8c&R{3*A Y9dn%06u3_9f`OXhT=?-)Zx(^b literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/d6/b9ec0dfb972a6815ace42545cde5f2631cd776 b/tests/resources/rebase/.gitted/objects/d6/b9ec0dfb972a6815ace42545cde5f2631cd776 new file mode 100644 index 0000000000000000000000000000000000000000..123970457b57013fa481beb1819abe8098ee500f GIT binary patch literal 790 zcmV+x1L^#D0c})GZ{s!)?U}z~ZhKJ-bbBb!oSdx}**2RjU5sZ30RXPN3Rdh$HpwJ~sG-X6bvdZe$f#}hpO42aLPf7|~-9E!{AuMNdq z5hN~&RtLP6Y0PZpx}!G>R3MtKhy95@JstMXWJ6EhUda`5fh?t18j_Sj^C4va|*TzYm%{dk!>9S2=Qq73WEU6*osDGfcq#=w**I zY$gy$L+j+aX$#-8y)fA}V!&Gf34)Xr1Z*?uobIWQ6u{|OZ?RE+1+MWo)asw@S;HFi zIdWKL4TXor>&&gFyzGPpLq?i=P&_Lx z4%VpRDwsXzYwhZ7Lg<<$BylGx#sD$jT@wcJtr|OXnpjX|TaYy9QOMpQO`$a|9tA|! z>da;8*}Dz{!4BAq>ULO?%|?mQ%u6@z=(k0X5DzgkUE{K)1J7EBHpjIF0GArp5WSD9 z&SiuJ={Iq->i1q)#vKEP+Ght10iY}U{4zJ7W$dO;=v2~qLr2j#oelM}FqGYX{+>=a@{WkEOR2HPsp z{_Xignd;Y!oCwY=6Cgw;OVvt`Hh867Oa{-vgDnCjUd1BCNU0HKbn<9$7(mVez6vI3 zaTX7KV0ZN;?Ai)`-Kg+aVIjz2l&*rjiN!U`C*7t{j@4FX`lhRHmV}zGCU5+jUt8+n zJh7eNRI)%%5Q`X%FxM(7GzNLBhq`Zg<+OTXrvFf_fr_n#Y6a$R8VmP?gHr1ahpa0d zNlT_9DqfRSolN>u9cTk=oemWfnOw$^Et3~_fgyMeB8zs@9GyM}B`cyMYlWWJ%}ZKJ P-|ZEYcx!$D&c4j!RW+}j literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/da/9c51a23d02d931a486f45ad18cda05cf5d2b94 b/tests/resources/rebase/.gitted/objects/da/9c51a23d02d931a486f45ad18cda05cf5d2b94 new file mode 100644 index 0000000000000000000000000000000000000000..85b78eed537f38c9c1cc4c283b89a176ce90a60b GIT binary patch literal 170 zcmV;b09F5Z0i}*R4gw(%hOIfpTtG9x!a!n-jisFz;4u@oSTQTc>x;%4*!_>>%U9a6 z%pHuQO<$QIpf%N76ideYoC;&KY@HR#kt#{Z2BSlDPb=R#P@ycraik!+>QK;mFNCI= zl8FW)mQW{A>DjMsg;RZ{wZi4vmPfn6p2zx0NB$nawkvHpfSv}-Xz~%ZI3cRB4%yCs YV$`|SS>}@ZJQOta2ANsZ8}+YKl?gjkcmMzZ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/df/d3d25264693fcd7348ad286f3c34f3f6b30918 b/tests/resources/rebase/.gitted/objects/df/d3d25264693fcd7348ad286f3c34f3f6b30918 new file mode 100644 index 0000000000000000000000000000000000000000..3de3fda62fce2b75e53e8fe502dbc4e8f7f6443c GIT binary patch literal 177 zcmV;i08amS0i};kP6QzkgC?J^_H!j_Ifr2WWUi4tPnRtECcmsFuCwci^ z8~eUZK*EQ4s6yzKO0J?IN)pW8tMAC%dhMDyY3gK|qWR=QZxbAL%qk^i@@O=L*~`)=x1T6E)_@zF_hU*1>qgaL7QwVmmV~|x1w*}3M7zpMy#fDNRv4isSI__e literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/e5/2ff405da5b7e1e9b0929939fa8405d81fe8a45 b/tests/resources/rebase/.gitted/objects/e5/2ff405da5b7e1e9b0929939fa8405d81fe8a45 new file mode 100644 index 0000000000000000000000000000000000000000..30c1987ed01a5e983d503c9e124cbac9420bdfd0 GIT binary patch literal 176 zcmV;h08jsT0i}*RY6CG4hF$9vbAgzVR*w}JlO|=l^kG&rgH`OxCuar2j^&W$4 z6mdb(!n$p%swYF=m$9&^Z0A$()KIZiHgpJ05AV|0V^p=O;s>5GG{O}FfcPQQAjK$uPiP} zErQs%UjDd4{mr%a#Ti%BZ9ExMGUezDsH(Em#2m1i$0B<%-a9t|MYF8S00q# KQUCxrG+hBKIAUG^ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/e9/5f47e016dcc70b0b888df8e40e97b8aabafd4c b/tests/resources/rebase/.gitted/objects/e9/5f47e016dcc70b0b888df8e40e97b8aabafd4c new file mode 100644 index 0000000000000000000000000000000000000000..cc3312a4730f93e6b76d43ea2c52e5188f8c7573 GIT binary patch literal 279 zcmV+y0qFjC0VPmDZo)te?0H`?4**oDr>ZBUBFY7536(fHi9=S}tfO6rh~L+n-mIDN z%-D618gK8fFZ-YE?+usJ^}KOzzpJo2?7u3UPuJt;1=67rN|_OuB5LMty`Cxe@QP-^ zD7FanEP#)A%9PysRIM;h3!ptC)4)dF6StnDW>7{a2@BWTR+ed8VfNbpW2SfC*X^-7 zRJYP$Cgrq3iRvT-nHSlZq~V;=`oxWL;fg2e1{Y0az82t$w+%_Adk;eP{NR79%;{mh z6ecLQSi({vidv~V21#7}qEn$<0_w!nmNUJ6Kxctc9eABbk(j$Fl&-^+EldV9q}iNj d9|EXtL9X+W(FJRcpJJ2b zMW3xusxZ(D4vs@cR|F+iCc7Itn-Z%rcgaTTVMD*}T@Xg^I;vCxX`Ej&gE+Y_sZvsK zam_M$vfl5|vh#3)D+Td)$jlhIq`V+eK-8-)U{DF1Ft}er^w0J2TjLS<1SN-=u-q1?=l z6sgbm$-(o0ho{H8!|Ay{;Jxo~e*1X8H|Em4^mse=`18@7F5npwy~~JXr2!|ry47MJ z8#LV(H!iS=^dV;Y3$5n)h|BL&f73Zvp(~|t2+tXt)n;riFWQ`lz`=14j0?v| z6H07!poYnG#{!roO&hOgD8)M;;q{V8bYS4;}yoU`Fq7}LIEs4vg0vd62r51^D zNud_u-QVISxR80zBj-i~H-1ro`rY9yyiK2k=x9{P*$k!H+{esb2^3QeyP&pKf_OKQ zRI5P)i1oTRPG8Ob;U;D>*P|i7ghZ@eYyMN>-^Mk)1H^clOd|sUvk)q{|p+ XX1(w?mx`C_*IE@W@!tFcToK8Xn6|@g literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/ee/23c5eeedadf8595c0ff60a366d970a165e373d b/tests/resources/rebase/.gitted/objects/ee/23c5eeedadf8595c0ff60a366d970a165e373d new file mode 100644 index 0000000000000000000000000000000000000000..b32600f78503917778b60b3d303fa467b1c3628b GIT binary patch literal 372 zcmV-)0gL{40X309QsgiUMOph4{{VpC0n;=Ga1w>Ma4e5ycZ%C1n`S3j z^4I&)=y}BL-#=G($A{q#ufqXvFYm86#+(k1174m7{ChtfPv8X-y~~JXr2{8Cxy@oE z8#LWlH?6RV^dVaM5|ILT5@}5MDBNtIgP5UbQ(9frH~9m{yLF zW|Y|JKn;_zVTM?rdyMRS(?;GIE0-iaHY-(wHtgg*YIn3Em%cS|`A|S3j?UC0Q7$Re zBE0)w+zb~ow>)z0G;q@=1*qQ!XW?!7AVf!#LM~=3)n*&BcqLFwHSB`g+6dy^L{hB= z4H`Bgr_Zi^xQLld_F5uyScUx&sw5rHIUOMx0#H~oyEB^YaBXw7#%NS{4z3>;8 SikIrwS`{ww#(V?BAj)*hwzG@? literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/ee/f0edde5daa94da5f297d4ddb5dfbc1980f0902 b/tests/resources/rebase/.gitted/objects/ee/f0edde5daa94da5f297d4ddb5dfbc1980f0902 new file mode 100644 index 0000000000000000000000000000000000000000..e9b3f58c65bd5df07a1eceada0f0d59b37cc06bf GIT binary patch literal 55 zcmV-70LcG%0V^p=O;s?qU@$Z=Ff%bxNJ=cqNv+f?sVHGEXa?1$}JmNOlk`R=OY N9jlL4%m93_6GAyO7bO4y literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/ef/ad0b11c47cb2f0220cbd6f5b0f93bb99064b00 b/tests/resources/rebase/.gitted/objects/ef/ad0b11c47cb2f0220cbd6f5b0f93bb99064b00 new file mode 100644 index 0000000000000000000000000000000000000000..285e14056c5d2f43e608928c4de45edf269f2d64 GIT binary patch literal 177 zcmV;i08amS0i};UZo@DPg){3Eyg&92a%XYuD=OIzQ-GsZ+d%?Vz{7P^rR f*slMaai6U&wiM~hK#0&A$T9xN^>Mf#=BZW_rDjx3 literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/f5/56d5fef35003561dc0b64b37057d7541239105 b/tests/resources/rebase/.gitted/objects/f5/56d5fef35003561dc0b64b37057d7541239105 new file mode 100644 index 0000000000000000000000000000000000000000..f4143e1f5506bed257b104d6343cbc40c29ce799 GIT binary patch literal 90 zcmV-g0HyzU0V^p=O;s?rWH2-^Ff%bxNJ=cqNv+f?sVHGEXa?1$}JmNOlk`R=OY w9jlL4%urP+MVYB7@dc@gV1>EA+b{9k?pdI_Wbup%g8nymWd%M50L8*2Tg7E4@c;k- literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/f6/3fa37e285bd11b0a7b48fa584a4091814a3ada b/tests/resources/rebase/.gitted/objects/f6/3fa37e285bd11b0a7b48fa584a4091814a3ada new file mode 100644 index 0000000000000000000000000000000000000000..e650383a22e03d10db15aede5419ea655f61c3d0 GIT binary patch literal 55 zcmV-70LcG%0V^p=O;s?qU@$Z=Ff%bxNJ=cqNv+f?sVHH1`AJ9M|KmJ{{ Nx`2hP2mo-a5+*{L7VH23 literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/f7/5c193a1df47186727179f24867bc4d27a8991f b/tests/resources/rebase/.gitted/objects/f7/5c193a1df47186727179f24867bc4d27a8991f new file mode 100644 index 0000000000000000000000000000000000000000..618cb68148e321b5bfbe692ac3592da5e73ca458 GIT binary patch literal 802 zcmV+-1Ks?10c})GZ{s!)?U}z~ZoMc5+8zotCuggL(`MsfZEw)tM$$+kOpz){+4aBg z8_J7qfnIFLqG#SG8y6b-;isQ}{O+l)Khj};dfOOt-2PtEaaYss`Sn*i;FCg6jYwZn zyJS4{#LiJ3g?cAxEWhZJli{HWUMlmxd;YMaPp89?o-hm(UupZk{e#438^zr!3b9N` zVVUV_F|QFCqHwxx=$$bY6V0c3d!!F9_4bw6cjWj+Hk0+lG>2SKnxpk+CloFc^%b^L zng9Tr1e zv)0#4qxkO=$uO)+ltlnx|6X@e%Q1$WD7BGiY*NgS%$(jT(jDawl$Yr3oM`6w?F>le zK%H&nQGrGPxFh*%;fR@`H}BhH{TZtZSrr@_Q0qdHmBv|QRuKlM>~3Xy%EFz+LldmC zexTl7#O(H`&xeYxqix4kd?$Pn;wHf0Re%|QbSoAJM^c|2sSD(>(}|uE^R|b-`{x(h ze^FqK{+Z7Z4-rv(sa+-&Mf%05=bRK?v`G?7hMM{~ax#hzTJ%bM#7C-V#;{`aDp~{Y z)Mp)hn*bHkLcrui=i-5lA})Z%NxYS;-W@{Ln4rW%nnUma^RHt`u=pO0jX92z5M<6- z^W+i8&O*&Z*RVJQ5LzoU8>tg#Th7`6z9?>slB_gx2xeN^aYMf?DI?f@h(foptm=UC zGDEExu0;T_RI&QtT)3)76MHZ57nQ*9*U)g|;r)BO|bgyUDif~(EtBDlwI4OfXM zsFy^T|4)RbM@3bUV8Lt!-->qP{DGML9!~J(8@KCDIk40 gFq(y{1Q%ARxQ^8FRz@i#iD(l@Ec3?v1DJH(wPB`}cmMzZ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/f8/7d14a4a236582a0278a916340a793714256864 b/tests/resources/rebase/.gitted/objects/f8/7d14a4a236582a0278a916340a793714256864 new file mode 100644 index 0000000000000000000000000000000000000000..1d29712c5d6cf10e1860a1d97aa0ef2a2457bb2d GIT binary patch literal 174 zcmV;f08#&V0i}*hiUL6pL|xY@@&XQ3+4U0!apTgR7s$>JHrUqCmU?~LVQw(Hh!+q% zZu2~Kz*IJUQH34VG$b)5D=9@TSf!R|J{C?f2OE(~kl=o3(OU5WE(LNcg5Q=4j9{edn5rP}c}Od@0GW|y)KbLhRufQB?g f<;6M&YFm)$?8xXGJ>y8w_?@nBG<2*eK(fL(So$ovP zbpzpRbt+Wiq?-l`CRN`pUvSK^o|~=WB!phksfhaE=JlVLJ)Dn`~DdU1Yvrj>l_zo4eA`2mp_&;vFX BuR#C+ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/ff/dfa89389040a87008c4ab1834120d3046daaea b/tests/resources/rebase/.gitted/objects/ff/dfa89389040a87008c4ab1834120d3046daaea new file mode 100644 index 0000000000000000000000000000000000000000..54c938e2e710a21ace8561627587660f3e922ddb GIT binary patch literal 208 zcmV;>05AV|0V^p=O;s>5GG{O}FfcPQQAjKtGT9 literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/refs/heads/asparagus b/tests/resources/rebase/.gitted/refs/heads/asparagus new file mode 100644 index 0000000000000000000000000000000000000000..a3c9d67c4a63fa462c9c2f782b09c3ce571f8270 GIT binary patch literal 41 tcmWN;NdW*L2n4{tZ4gk1!?pb*=#1p1$unPF7|J}TnFRrOwnAaWvK|aX3}FBO literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/refs/heads/barley b/tests/resources/rebase/.gitted/refs/heads/barley new file mode 100644 index 0000000000000000000000000000000000000000..feab9443f2d478ca339d560c089d765cd55c6076 GIT binary patch literal 41 ucmV~$K>+|D2m`>sX|{; literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/refs/heads/dried_pea b/tests/resources/rebase/.gitted/refs/heads/dried_pea new file mode 100644 index 0000000000000000000000000000000000000000..9ede6023c049141a22a02164744f333597555d1b GIT binary patch literal 41 vcmV~$$qfK72m`Qxr{Sm|j02+Ce}vjePd?jp6AvM}R5AJ%oDMoJG_uYI=mQF| literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/refs/heads/gravy b/tests/resources/rebase/.gitted/refs/heads/gravy new file mode 100644 index 0000000000000000000000000000000000000000..3753b73309d143acdc7397d38d00fbfc4c0927f8 GIT binary patch literal 41 vcmV~$NdW*L2n4{tX#jPBI2_VHf-?<9yOPOE&6F+-8--SdA9CNRaWU%y@5Ku? literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/refs/heads/master b/tests/resources/rebase/.gitted/refs/heads/master new file mode 100644 index 0000000000000000000000000000000000000000..abbe9cc15fd859638b4229a17aee5ebadf8bc7ce GIT binary patch literal 41 ucmV~$!4Uu;2m`Rc(-cHJ#<6JkAHn45T+pmzH(hW?^QIP|nq(C+2#gN^Mhk8L literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/refs/heads/veal b/tests/resources/rebase/.gitted/refs/heads/veal new file mode 100644 index 0000000000000000000000000000000000000000..484f489761e8fb440dd445b1cd19ff961ef1144c GIT binary patch literal 41 ucmV~$$qfK72m`Qxr{M?z#)(vQ{}F1x>FW>_$(oQwkJgzm^=3PwIK=tZ3JHP$ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/asparagus.txt b/tests/resources/rebase/asparagus.txt new file mode 100644 index 0000000000000000000000000000000000000000..67ed7afb256807556f9b74fa4f7c9284aaec1120 GIT binary patch literal 587 zcmYLH%W}gY47~Fd`T$RUpeK@&$26^7KbkWkIA%f&1<_3YzJhepi;cxzX@2^LkoM}ZUiickJVOm;6{+q%OKAwRuEN?UV}lHjnejBfl5f25!_7W zSxu~7L%$W!*G*S}oKIlo9dOcDx`vxX9jIw?KGz_kw3k?5o`?#}&H2sNyH>zq*KdJC zvlA-;#JuFI`h#eRG@Lbw8baq0l7EPK?Y$0#FiMLrjK97@f2iSe;BDV!jsx#STfxy8 z`w&E9%jr2y(D0oM(s*vfDuZU$4ErV<_QoZzAHcgIJq}zz;vvqPWRqBRY~ytr%GWb%_X#1mv~p|j&dkp2 zhnJU+^!4+%FBj)t`6^U5q0Psc6rYq98by|YrlaDp5QosNEJ1W@zu1Ey>(iK`4DQ_g zw9$TO#Y3v77>Q55lf>$ag!@3LvQ56;4E?j8}!gvla0Tp~D zAY#g?4y3vGcnw17CdK|jchVj3T;(yyljfA-as;E0(-CKxX$(AFDND{$hE}(p$u1~| z`i#CsP%!!w)fp}IziGJHgi^kSG_P-&|)#-4{#a9+Mv5=BW7oFw!-%v zP$4Y@)F4(D2X= zg^*60(ateSc~6kQ@tbM>v2%o19!2z6+2F!KNQy7;j$V-|v4~(+zPe^7G(q|v#sCK( zsTMta?-IbWg)F7367qDXnag$Pc5KB_harv)!Y10Mfq=jp7y<=fEB-=cp|;=QWJTJM z(A7G;?F_gs$i;oFg&T9PorPVq{yXA?>!+Z>>1$gA5BqgXp zl)d2F@V1SDzL*9U(1EDO<{xn7xx>#=;i4E literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/bouilli.txt b/tests/resources/rebase/bouilli.txt new file mode 100644 index 0000000000000000000000000000000000000000..4b7c5650008b2e747fe1809eeb5a1dde0e80850a GIT binary patch literal 1092 zcmYk5U5?u@420ix3Le0l19abt0__3|v_N;!XW6E0!HVcgR9xS_Lpl2c1OcK@!*7Pv z@1L)~=+D#35BmD^_38Qf>EhgrUzv1aN@3ulwE3(gQ#;Zn3@i0Hl$G0I&pdVHd#Oqs z<^|WFC}9nj|-QLEB74>h?%i!wBm5pC2?H z5NajGUzv7)bR-F<_b!siCt9T1ZAqLv6nmvZDufQV_!~S0Tm{XR8J0K!ahVf?yz%*q@#zm^@){YAh@B235V# zd(vfvJDJXmPw|r&y$+76#Secx&$M%lu4k{DIs}NGG~t)!1`V_@hTWH?QK@Wp7ct~J zblGx9Yh*HbhkElfd{qu1EIC5uWy8Yvvy*o*9A$W-Ljl-{*^E!`a&in=ugH z4yQ{kUmhM>rk+ZjrZ5CfN`I?Q8uV!X-lk-HH=bF2ANhUYAt4d$!Z;eEg^9VN;Gt~T zs;NfP$k>b>*_2nZdFFDS~^jr)hcPt3-R{ e9o9Bu**`CHo3z$;vxxw{7`=)w_G;UjT-<*kZ-7$( literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/gravy.txt b/tests/resources/rebase/gravy.txt new file mode 100644 index 0000000000000000000000000000000000000000..c4e6cca3ec6ae0148ed231f97257df8c311e015f GIT binary patch literal 390 zcmX9)L2kn^47>Xkd_da|?6gyl8&+(Y(Y^3lH<7BTm(g|Y>S3~CB2#zXb19%0K_TVJNQEB$B$#iH-*~-C_yiai$1`1g+}r15kD{bR+?Mf56N8>)Vgt z@cQ!S*V(zhz9sNwf~k5cAREI+_f;Bj1m2rqZ6{c}fFxXi3v47w9~JSt(`{ZGPxo&w z#HB$IYY&%2ZiE-Ps!(a zf+j<+HKfXYRuj+&Z+LPQrB}6*5Hfvqnt+P%c&{vn8MUfdhXHdMD{2m3evRBc$Q5V@ zUlCf5kpf|nyu+mPr;(f_3RgS`8~61{C~~i^t*lAJo(D(PuOo_CO^pC5g#@9ZMPS}d z^p5#DijDq3!Odl_9&nx;Tu^h?6=2Ta33-UP!9t~rrs|_^V&L3$QJI07tW_mdrYW;}#xl-A QH$PDeJZzXqThZBl0*7D{sQ>@~ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/veal.txt b/tests/resources/rebase/veal.txt new file mode 100644 index 0000000000000000000000000000000000000000..a7b066537e6be7109abfe4ff97b675d4e077da20 GIT binary patch literal 1095 zcmYjQOODhq5Z(I}b%4+p=+!JhLPBCB#IUX;mBfl;XIwTRoSs)sH?WN3di8#O`}p#O zzJ2}vdUNiz7V@zqV%k%ovSbl@ubhign&{vnxqBR^=u=c0FrpiW&{2xwbWbTxHQ4n& z@UYS@`z{%HHI6cN#Bro@B)gy-N=Jt;%XN}3Xs5vs(l!R+NDFUw3Ib|{`s4#?5gvUw z+tiY3);sCyH(YRO7+Ap!j83B}k@lx5%roiYqb>g_49@?<8morpLW;BGI~87q62^f; z|5$<0rK2rP)71XYSy+Yq1c|3pAcc{#R{;&fVVZqt#>^>=G~ha5Hvj8#0OX87;XcTR zW~0JK2c}biMDWcgMHpkcnu*|aN?4mwHY)S1)C)q2bciLQB{S5P#jC@jQZvZdERQ2; z+JuHBA)b+T&Kl&rTTc1)2C+5d-VW`aumh<-DFy09ai%RNde3nspaPW09}`Z Date: Fri, 18 Jul 2014 17:40:07 -0400 Subject: [PATCH 02/21] git_reset: const the git_signature arg --- include/git2/reset.h | 2 +- src/reset.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/git2/reset.h b/include/git2/reset.h index 5f2ba572d..53f3e891e 100644 --- a/include/git2/reset.h +++ b/include/git2/reset.h @@ -70,7 +70,7 @@ GIT_EXTERN(int) git_reset( git_object *target, git_reset_t reset_type, git_checkout_options *checkout_opts, - git_signature *signature, + const git_signature *signature, const char *log_message); /** diff --git a/src/reset.c b/src/reset.c index d063abe25..dc3aa4a66 100644 --- a/src/reset.c +++ b/src/reset.c @@ -101,7 +101,7 @@ int git_reset( git_object *target, git_reset_t reset_type, git_checkout_options *checkout_opts, - git_signature *signature, + const git_signature *signature, const char *log_message) { git_object *commit = NULL; From 4fe84d624b42a1ef1b9b392483ddc43064b1180e Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 14 Jul 2014 15:19:19 -0400 Subject: [PATCH 03/21] Introduce git_rebase_abort Abort an in-progress rebase and move the working directory and repository back to the ORIG_HEAD state. --- include/git2/rebase.h | 13 ++++ src/rebase.c | 128 ++++++++++++++++++++++++++++++++++++ tests/rebase/abort.c | 148 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 tests/rebase/abort.c diff --git a/include/git2/rebase.h b/include/git2/rebase.h index 6eb279412..c760fbe74 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -68,6 +68,19 @@ GIT_EXTERN(int) git_rebase( const git_signature *signature, const git_rebase_options *opts); +/** + * Aborts a rebase that is currently in progress, resetting the repository + * and working directory to their state before rebase began. + * + * @param repo The repository with the in-progress rebase + * @param signature The identity that is aborting the rebase + * @return Zero on success; GIT_ENOTFOUND if a rebase is not in progress, + * -1 on other errors. + */ +GIT_EXTERN(int) git_rebase_abort( + git_repository *repo, + const git_signature *signature); + /** @} */ GIT_END_DECL #endif diff --git a/src/rebase.c b/src/rebase.c index 68d741d25..38ced24bb 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -44,6 +44,18 @@ typedef enum { GIT_REBASE_TYPE_MERGE = 2, } git_rebase_type_t; +typedef struct { + git_rebase_type_t type; + char *state_path; + + int head_detached : 1; + + char *orig_head_name; + git_oid orig_head_id; +} git_rebase_state; + +#define GIT_REBASE_STATE_INIT {0} + static int rebase_state_type( git_rebase_type_t *type_out, char **path_out, @@ -80,6 +92,84 @@ done: return 0; } +static int rebase_state(git_rebase_state *state, git_repository *repo) +{ + git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT, + orig_head_id = GIT_BUF_INIT; + int state_path_len, error; + + memset(state, 0x0, sizeof(git_rebase_state)); + + if ((error = rebase_state_type(&state->type, &state->state_path, repo)) < 0) + goto done; + + if (state->type == GIT_REBASE_TYPE_NONE) { + giterr_set(GITERR_REBASE, "There is no rebase in progress"); + return GIT_ENOTFOUND; + } + + if ((error = git_buf_puts(&path, state->state_path)) < 0) + goto done; + + state_path_len = git_buf_len(&path); + + if ((error = git_buf_joinpath(&path, path.ptr, HEAD_NAME_FILE)) < 0 || + (error = git_futils_readbuffer(&orig_head_name, path.ptr)) < 0) + goto done; + + git_buf_rtrim(&orig_head_name); + + if (strcmp(ORIG_DETACHED_HEAD, orig_head_name.ptr) == 0) + state->head_detached = 1; + + git_buf_truncate(&path, state_path_len); + + if ((error = git_buf_joinpath(&path, path.ptr, ORIG_HEAD_FILE)) < 0) + goto done; + + if (!git_path_isfile(path.ptr)) { + /* Previous versions of git.git used 'head' here; support that. */ + git_buf_truncate(&path, state_path_len); + + if ((error = git_buf_joinpath(&path, path.ptr, HEAD_FILE)) < 0) + goto done; + } + + if ((error = git_futils_readbuffer(&orig_head_id, path.ptr)) < 0) + goto done; + + git_buf_rtrim(&orig_head_id); + + if ((error = git_oid_fromstr(&state->orig_head_id, orig_head_id.ptr)) < 0) + goto done; + + if (!state->head_detached) + state->orig_head_name = git_buf_detach(&orig_head_name); + +done: + git_buf_free(&path); + git_buf_free(&orig_head_name); + git_buf_free(&orig_head_id); + git_buf_free(&onto_id); + return error; +} + +static void rebase_state_free(git_rebase_state *state) +{ + if (state == NULL) + return; + + git__free(state->orig_head_name); + git__free(state->state_path); +} + +static int rebase_finish(git_rebase_state *state) +{ + return git_path_isdir(state->state_path) ? + git_futils_rmdir_r(state->state_path, NULL, GIT_RMDIR_REMOVE_FILES) : + 0; +} + static int rebase_setupfile(git_repository *repo, const char *filename, const char *fmt, ...) { git_buf path = GIT_BUF_INIT, @@ -330,3 +420,41 @@ done: git_buf_free(&reflog); return error; } + +int git_rebase_abort(git_repository *repo, const git_signature *signature) +{ + git_rebase_state state = GIT_REBASE_STATE_INIT; + git_reference *orig_head_ref = NULL; + git_commit *orig_head_commit = NULL; + int error; + + assert(repo && signature); + + if ((error = rebase_state(&state, repo)) < 0) + goto done; + + error = state.head_detached ? + git_reference_create(&orig_head_ref, repo, GIT_HEAD_FILE, + &state.orig_head_id, 1, signature, "rebase: aborting") : + git_reference_symbolic_create( + &orig_head_ref, repo, GIT_HEAD_FILE, state.orig_head_name, 1, + signature, "rebase: aborting"); + + if (error < 0) + goto done; + + if ((error = git_commit_lookup( + &orig_head_commit, repo, &state.orig_head_id)) < 0 || + (error = git_reset(repo, (git_object *)orig_head_commit, + GIT_RESET_HARD, NULL, signature, NULL)) < 0) + goto done; + + error = rebase_finish(&state); + +done: + git_commit_free(orig_head_commit); + git_reference_free(orig_head_ref); + rebase_state_free(&state); + + return error; +} diff --git a/tests/rebase/abort.c b/tests/rebase/abort.c new file mode 100644 index 000000000..896eb4805 --- /dev/null +++ b/tests/rebase/abort.c @@ -0,0 +1,148 @@ +#include "clar_libgit2.h" +#include "git2/rebase.h" +#include "merge.h" +#include "posix.h" + +#include + +static git_repository *repo; + +// Fixture setup and teardown +void test_rebase_abort__initialize(void) +{ + repo = cl_git_sandbox_init("rebase"); +} + +void test_rebase_abort__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void test_abort(git_merge_head *branch, git_merge_head *onto) +{ + git_reference *head_ref, *branch_ref = NULL; + git_signature *signature; + git_status_list *statuslist; + git_reflog *reflog; + const git_reflog_entry *reflog_entry; + + cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); + cl_git_pass(git_rebase_abort(repo, signature)); + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + /* Make sure the refs are updated appropriately */ + cl_git_pass(git_reference_lookup(&head_ref, repo, "HEAD")); + + if (branch->ref_name == NULL) + cl_assert_equal_oid(git_merge_head_id(branch), git_reference_target(head_ref)); + else { + cl_assert_equal_s("refs/heads/beef", git_reference_symbolic_target(head_ref)); + cl_git_pass(git_reference_lookup(&branch_ref, repo, git_reference_symbolic_target(head_ref))); + cl_assert_equal_oid(git_merge_head_id(branch), git_reference_target(branch_ref)); + } + + git_status_list_new(&statuslist, repo, NULL); + cl_assert_equal_i(0, git_status_list_entrycount(statuslist)); + git_status_list_free(statuslist); + + /* Make sure the reflogs are updated appropriately */ + cl_git_pass(git_reflog_read(&reflog, repo, "HEAD")); + + cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0)); + cl_assert_equal_oid(git_merge_head_id(onto), git_reflog_entry_id_old(reflog_entry)); + cl_assert_equal_oid(git_merge_head_id(branch), git_reflog_entry_id_new(reflog_entry)); + cl_assert_equal_s("rebase: aborting", git_reflog_entry_message(reflog_entry)); + + git_reflog_free(reflog); + git_reference_free(head_ref); + git_reference_free(branch_ref); + git_signature_free(signature); +} + +void test_rebase_abort__merge(void) +{ + git_reference *branch_ref, *onto_ref; + git_signature *signature; + git_merge_head *branch_head, *onto_head; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + + cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); + + cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); + cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); + + test_abort(branch_head, onto_head); + + git_signature_free(signature); + + git_merge_head_free(branch_head); + git_merge_head_free(onto_head); + + git_reference_free(branch_ref); + git_reference_free(onto_ref); +} + +void test_rebase_abort__detached_head(void) +{ + git_oid branch_id; + git_reference *onto_ref; + git_signature *signature; + git_merge_head *branch_head, *onto_head; + + git_oid_fromstr(&branch_id, "b146bd7608eac53d9bf9e1a6963543588b555c64"); + cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_id(&branch_head, repo, &branch_id)); + cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + + cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); + + cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); + cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); + + test_abort(branch_head, onto_head); + + git_signature_free(signature); + + git_merge_head_free(branch_head); + git_merge_head_free(onto_head); + + git_reference_free(onto_ref); +} + +void test_rebase_abort__old_style_head_file(void) +{ + git_reference *branch_ref, *onto_ref; + git_signature *signature; + git_merge_head *branch_head, *onto_head; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + + cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); + + cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); + cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); + + p_rename("rebase-merge/.git/rebase-merge/orig-head", + "rebase-merge/.git/rebase-merge/head"); + + test_abort(branch_head, onto_head); + + git_signature_free(signature); + + git_merge_head_free(branch_head); + git_merge_head_free(onto_head); + + git_reference_free(branch_ref); + git_reference_free(onto_ref); +} From 950a70915930342d18286c6d6350929662a978e2 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 15 Jul 2014 10:23:10 -0400 Subject: [PATCH 04/21] Introduce git_rebase_next `git_rebase_next` will apply the next patch (or cherry-pick) operation, leaving the results checked out in the index / working directory so that consumers can resolve any conflicts, as appropriate. --- include/git2/rebase.h | 13 ++++ src/rebase.c | 156 ++++++++++++++++++++++++++++++++++++++++++ tests/rebase/merge.c | 59 ++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 tests/rebase/merge.c diff --git a/include/git2/rebase.h b/include/git2/rebase.h index c760fbe74..e4300ebf6 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -68,6 +68,19 @@ GIT_EXTERN(int) git_rebase( const git_signature *signature, const git_rebase_options *opts); +/** + * Applies the next patch, updating the index and working directory with the + * changes. If there are conflicts, you will need to address those before + * committing the changes. + * + * @param repo The repository with a rebase in progress + * @param checkout_opts Options to specify how the patch should be checked out + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_rebase_next( + git_repository *repo, + git_checkout_options *checkout_opts); + /** * Aborts a rebase that is currently in progress, resetting the repository * and working directory to their state before rebase began. diff --git a/src/rebase.c b/src/rebase.c index 38ced24bb..1062b2a2b 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -32,6 +32,7 @@ #define MSGNUM_FILE "msgnum" #define END_FILE "end" #define CMT_FILE_FMT "cmt.%d" +#define CURRENT_FILE "current" #define ORIG_DETACHED_HEAD "detached HEAD" @@ -42,8 +43,14 @@ typedef enum { GIT_REBASE_TYPE_NONE = 0, GIT_REBASE_TYPE_APPLY = 1, GIT_REBASE_TYPE_MERGE = 2, + GIT_REBASE_TYPE_INTERACTIVE = 3, } git_rebase_type_t; +struct git_rebase_state_merge { + int32_t msgnum; + int32_t end; +}; + typedef struct { git_rebase_type_t type; char *state_path; @@ -52,6 +59,10 @@ typedef struct { char *orig_head_name; git_oid orig_head_id; + + union { + struct git_rebase_state_merge merge; + }; } git_rebase_state; #define GIT_REBASE_STATE_INIT {0} @@ -92,6 +103,50 @@ done: return 0; } +static int rebase_state_merge(git_rebase_state *state, git_repository *repo) +{ + git_buf path = GIT_BUF_INIT, msgnum = GIT_BUF_INIT, end = GIT_BUF_INIT; + int state_path_len, error; + + GIT_UNUSED(repo); + + if ((error = git_buf_puts(&path, state->state_path)) < 0) + goto done; + + state_path_len = git_buf_len(&path); + + if ((error = git_buf_joinpath(&path, path.ptr, MSGNUM_FILE)) < 0) + goto done; + + if (git_path_isfile(path.ptr)) { + if ((error = git_futils_readbuffer(&msgnum, path.ptr)) < 0) + goto done; + + git_buf_rtrim(&msgnum); + + if ((error = git__strtol32(&state->merge.msgnum, msgnum.ptr, NULL, 10)) < 0) + goto done; + } + + git_buf_truncate(&path, state_path_len); + + if ((error = git_buf_joinpath(&path, path.ptr, END_FILE)) < 0 || + (error = git_futils_readbuffer(&end, path.ptr)) < 0) + goto done; + + git_buf_rtrim(&end); + + if ((error = git__strtol32(&state->merge.end, end.ptr, NULL, 10)) < 0) + goto done; + +done: + git_buf_free(&path); + git_buf_free(&msgnum); + git_buf_free(&end); + + return error; +} + static int rebase_state(git_rebase_state *state, git_repository *repo) { git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT, @@ -146,6 +201,22 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) if (!state->head_detached) state->orig_head_name = git_buf_detach(&orig_head_name); + switch (state->type) { + case GIT_REBASE_TYPE_INTERACTIVE: + giterr_set(GITERR_REBASE, "Interactive rebase is not supported"); + error = -1; + break; + case GIT_REBASE_TYPE_MERGE: + error = rebase_state_merge(state, repo); + break; + case GIT_REBASE_TYPE_APPLY: + giterr_set(GITERR_REBASE, "Patch application rebase is not supported"); + error = -1; + break; + default: + abort(); + } + done: git_buf_free(&path); git_buf_free(&orig_head_name); @@ -421,6 +492,91 @@ done: return error; } +static int rebase_next_merge( + git_repository *repo, + git_rebase_state *state, + git_checkout_options *checkout_opts) +{ + git_buf path = GIT_BUF_INIT, current = GIT_BUF_INIT; + git_oid current_id; + git_commit *current_commit = NULL, *parent_commit = NULL; + git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL; + git_index *index = NULL; + unsigned int parent_count; + int error; + + if (state->merge.msgnum == state->merge.end) + return GIT_ITEROVER; + + state->merge.msgnum++; + + if ((error = git_buf_joinpath(&path, state->state_path, "cmt.")) < 0 || + (error = git_buf_printf(&path, "%d", state->merge.msgnum)) < 0 || + (error = git_futils_readbuffer(¤t, path.ptr)) < 0) + goto done; + + git_buf_rtrim(¤t); + + if ((error = git_oid_fromstr(¤t_id, current.ptr)) < 0 || + (error = git_commit_lookup(¤t_commit, repo, ¤t_id)) < 0 || + (error = git_commit_tree(¤t_tree, current_commit)) < 0 || + (error = git_repository_head_tree(&head_tree, repo)) < 0) + goto done; + + if ((parent_count = git_commit_parentcount(current_commit)) > 1) { + giterr_set(GITERR_REBASE, "Cannot rebase a merge commit"); + error = -1; + goto done; + } else if (parent_count) { + if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 || + (error = git_commit_tree(&parent_tree, parent_commit)) < 0) + goto done; + } + + if ((error = rebase_setupfile(repo, MSGNUM_FILE, "%d\n", state->merge.msgnum)) < 0 || + (error = rebase_setupfile(repo, CURRENT_FILE, "%s\n", current.ptr)) < 0) + goto done; + + if ((error = git_merge_trees(&index, repo, parent_tree, head_tree, current_tree, NULL)) < 0 || + (error = git_merge__check_result(repo, index)) < 0 || + (error = git_checkout_index(repo, index, checkout_opts)) < 0) + goto done; + +done: + git_index_free(index); + git_tree_free(current_tree); + git_tree_free(head_tree); + git_tree_free(parent_tree); + git_commit_free(current_commit); + git_commit_free(parent_commit); + git_buf_free(&path); + git_buf_free(¤t); + + return error; +} + +int git_rebase_next(git_repository *repo, git_checkout_options *opts) +{ + git_rebase_state state = GIT_REBASE_STATE_INIT; + int error; + + assert(repo); + + if ((error = rebase_state(&state, repo)) < 0) + return -1; + + switch (state.type) { + case GIT_REBASE_TYPE_MERGE: + error = rebase_next_merge(repo, &state, opts); + break; + default: + abort(); + } + + rebase_state_free(&state); + return error; +} + int git_rebase_abort(git_repository *repo, const git_signature *signature) { git_rebase_state state = GIT_REBASE_STATE_INIT; diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c new file mode 100644 index 000000000..e44fdd3f6 --- /dev/null +++ b/tests/rebase/merge.c @@ -0,0 +1,59 @@ +#include "clar_libgit2.h" +#include "git2/rebase.h" +#include "posix.h" + +#include + +static git_repository *repo; +static git_signature *signature; + +// Fixture setup and teardown +void test_rebase_merge__initialize(void) +{ + repo = cl_git_sandbox_init("rebase"); +} + +void test_rebase_merge__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_rebase_merge__next(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_status_list *status_list; + const git_status_entry *status_entry; + git_oid file1_id; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + + cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n", 41, "rebase/.git/rebase-merge/current"); + cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum"); + + cl_git_pass(git_status_list_new(&status_list, repo, NULL)); + cl_assert_equal_i(1, git_status_list_entrycount(status_list)); + cl_assert(status_entry = git_status_byindex(status_list, 0)); + + cl_assert_equal_s("beef.txt", status_entry->head_to_index->new_file.path); + + git_oid_fromstr(&file1_id, "8d95ea62e621f1d38d230d9e7d206e41096d76af"); + cl_assert_equal_oid(&file1_id, &status_entry->head_to_index->new_file.id); + + git_status_list_free(status_list); + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} From 443d5674fe3f2edd4cb51c7657e7ad5063275bff Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 17 Jul 2014 11:59:01 -0400 Subject: [PATCH 05/21] git_rebase_next: write conflicts nicely during rebase --- src/rebase.c | 138 ++++++++++++++++++++++++++++++++++--------- tests/rebase/merge.c | 59 ++++++++++++++++++ 2 files changed, 170 insertions(+), 27 deletions(-) diff --git a/src/rebase.c b/src/rebase.c index 1062b2a2b..676a803cc 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -49,6 +49,9 @@ typedef enum { struct git_rebase_state_merge { int32_t msgnum; int32_t end; + char *onto_name; + + git_commit *current; }; typedef struct { @@ -105,7 +108,9 @@ done: static int rebase_state_merge(git_rebase_state *state, git_repository *repo) { - git_buf path = GIT_BUF_INIT, msgnum = GIT_BUF_INIT, end = GIT_BUF_INIT; + git_buf path = GIT_BUF_INIT, msgnum = GIT_BUF_INIT, end = GIT_BUF_INIT, + onto_name = GIT_BUF_INIT, current = GIT_BUF_INIT; + git_oid current_id; int state_path_len, error; GIT_UNUSED(repo); @@ -115,21 +120,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) state_path_len = git_buf_len(&path); - if ((error = git_buf_joinpath(&path, path.ptr, MSGNUM_FILE)) < 0) - goto done; - - if (git_path_isfile(path.ptr)) { - if ((error = git_futils_readbuffer(&msgnum, path.ptr)) < 0) - goto done; - - git_buf_rtrim(&msgnum); - - if ((error = git__strtol32(&state->merge.msgnum, msgnum.ptr, NULL, 10)) < 0) - goto done; - } - - git_buf_truncate(&path, state_path_len); - + /* Read 'end' */ if ((error = git_buf_joinpath(&path, path.ptr, END_FILE)) < 0 || (error = git_futils_readbuffer(&end, path.ptr)) < 0) goto done; @@ -139,10 +130,57 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) if ((error = git__strtol32(&state->merge.end, end.ptr, NULL, 10)) < 0) goto done; + /* Read 'onto_name' */ + git_buf_truncate(&path, state_path_len); + + if ((error = git_buf_joinpath(&path, path.ptr, ONTO_NAME_FILE)) < 0 || + (error = git_futils_readbuffer(&onto_name, path.ptr)) < 0) + goto done; + + git_buf_rtrim(&onto_name); + + state->merge.onto_name = git_buf_detach(&onto_name); + + /* Read 'msgnum' if it exists, otherwise let msgnum = 0 */ + git_buf_truncate(&path, state_path_len); + + if ((error = git_buf_joinpath(&path, path.ptr, MSGNUM_FILE)) < 0) + goto done; + + if (git_path_exists(path.ptr)) { + if ((error = git_futils_readbuffer(&msgnum, path.ptr)) < 0) + goto done; + + git_buf_rtrim(&msgnum); + + if ((error = git__strtol32(&state->merge.msgnum, msgnum.ptr, NULL, 10)) < 0) + goto done; + } + + + /* Read 'current' if it exists, otherwise let current = null */ + git_buf_truncate(&path, state_path_len); + + if ((error = git_buf_joinpath(&path, path.ptr, CURRENT_FILE)) < 0) + goto done; + + if (git_path_exists(path.ptr)) { + if ((error = git_futils_readbuffer(¤t, path.ptr)) < 0) + goto done; + + git_buf_rtrim(¤t); + + if ((error = git_oid_fromstr(¤t_id, current.ptr)) < 0 || + (error = git_commit_lookup(&state->merge.current, repo, ¤t_id)) < 0) + goto done; + } + done: git_buf_free(&path); git_buf_free(&msgnum); git_buf_free(&end); + git_buf_free(&onto_name); + git_buf_free(¤t); return error; } @@ -230,6 +268,11 @@ static void rebase_state_free(git_rebase_state *state) if (state == NULL) return; + if (state->type == GIT_REBASE_TYPE_MERGE) { + git__free(state->merge.onto_name); + git_commit_free(state->merge.current); + } + git__free(state->orig_head_name); git__free(state->state_path); } @@ -492,14 +535,50 @@ done: return error; } +static int normalize_checkout_opts( + git_repository *repo, + git_checkout_options *checkout_opts, + const git_checkout_options *given_checkout_opts, + const git_rebase_state *state) +{ + int error = 0; + + GIT_UNUSED(repo); + + if (given_checkout_opts != NULL) + memcpy(checkout_opts, given_checkout_opts, sizeof(git_checkout_options)); + else { + git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + default_checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + memcpy(checkout_opts, &default_checkout_opts, sizeof(git_checkout_options)); + } + + if (!checkout_opts->ancestor_label) + checkout_opts->ancestor_label = "ancestor"; + + if (state->type == GIT_REBASE_TYPE_MERGE) { + if (!checkout_opts->our_label) + checkout_opts->our_label = state->merge.onto_name; + + if (!checkout_opts->their_label) + checkout_opts->their_label = git_commit_summary(state->merge.current); + } else { + abort(); + } + + return error; +} + static int rebase_next_merge( git_repository *repo, git_rebase_state *state, - git_checkout_options *checkout_opts) + git_checkout_options *given_checkout_opts) { git_buf path = GIT_BUF_INIT, current = GIT_BUF_INIT; + git_checkout_options checkout_opts = {0}; git_oid current_id; - git_commit *current_commit = NULL, *parent_commit = NULL; + git_commit *parent_commit = NULL; git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL; git_index *index = NULL; unsigned int parent_count; @@ -517,18 +596,21 @@ static int rebase_next_merge( git_buf_rtrim(¤t); + if (state->merge.current) + git_commit_free(state->merge.current); + if ((error = git_oid_fromstr(¤t_id, current.ptr)) < 0 || - (error = git_commit_lookup(¤t_commit, repo, ¤t_id)) < 0 || - (error = git_commit_tree(¤t_tree, current_commit)) < 0 || + (error = git_commit_lookup(&state->merge.current, repo, ¤t_id)) < 0 || + (error = git_commit_tree(¤t_tree, state->merge.current)) < 0 || (error = git_repository_head_tree(&head_tree, repo)) < 0) goto done; - if ((parent_count = git_commit_parentcount(current_commit)) > 1) { + if ((parent_count = git_commit_parentcount(state->merge.current)) > 1) { giterr_set(GITERR_REBASE, "Cannot rebase a merge commit"); error = -1; goto done; } else if (parent_count) { - if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 || + if ((error = git_commit_parent(&parent_commit, state->merge.current, 0)) < 0 || (error = git_commit_tree(&parent_tree, parent_commit)) < 0) goto done; } @@ -537,9 +619,10 @@ static int rebase_next_merge( (error = rebase_setupfile(repo, CURRENT_FILE, "%s\n", current.ptr)) < 0) goto done; - if ((error = git_merge_trees(&index, repo, parent_tree, head_tree, current_tree, NULL)) < 0 || + if ((error = normalize_checkout_opts(repo, &checkout_opts, given_checkout_opts, state)) < 0 || + (error = git_merge_trees(&index, repo, parent_tree, head_tree, current_tree, NULL)) < 0 || (error = git_merge__check_result(repo, index)) < 0 || - (error = git_checkout_index(repo, index, checkout_opts)) < 0) + (error = git_checkout_index(repo, index, &checkout_opts)) < 0) goto done; done: @@ -547,7 +630,6 @@ done: git_tree_free(current_tree); git_tree_free(head_tree); git_tree_free(parent_tree); - git_commit_free(current_commit); git_commit_free(parent_commit); git_buf_free(&path); git_buf_free(¤t); @@ -555,7 +637,9 @@ done: return error; } -int git_rebase_next(git_repository *repo, git_checkout_options *opts) +int git_rebase_next( + git_repository *repo, + git_checkout_options *checkout_opts) { git_rebase_state state = GIT_REBASE_STATE_INIT; int error; @@ -567,7 +651,7 @@ int git_rebase_next(git_repository *repo, git_checkout_options *opts) switch (state.type) { case GIT_REBASE_TYPE_MERGE: - error = rebase_next_merge(repo, &state, opts); + error = rebase_next_merge(repo, &state, checkout_opts); break; default: abort(); diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index e44fdd3f6..506c411ed 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -57,3 +57,62 @@ void test_rebase_merge__next(void) git_reference_free(branch_ref); git_reference_free(upstream_ref); } + +void test_rebase_merge__next_with_conflicts(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_status_list *status_list; + const git_status_entry *status_entry; + + const char *expected_merge = +"ASPARAGUS SOUP.\n" +"\n" +"<<<<<<< master\n" +"TAKE FOUR LARGE BUNCHES of asparagus, scrape it nicely, cut off one inch\n" +"OF THE TOPS, and lay them in water, chop the stalks and put them on the\n" +"FIRE WITH A PIECE OF BACON, a large onion cut up, and pepper and salt;\n" +"ADD TWO QUARTS OF WATER, boil them till the stalks are quite soft, then\n" +"PULP THEM THROUGH A SIEVE, and strain the water to it, which must be put\n" +"=======\n" +"Take four large bunches of asparagus, scrape it nicely, CUT OFF ONE INCH\n" +"of the tops, and lay them in water, chop the stalks and PUT THEM ON THE\n" +"fire with a piece of bacon, a large onion cut up, and pepper and salt;\n" +"add two quarts of water, boil them till the stalks are quite soft, then\n" +"pulp them through a sieve, and strain the water to it, which must be put\n" +">>>>>>> Conflicting modification 1 to asparagus\n" +"back in the pot; put into it a chicken cut up, with the tops of\n" +"asparagus which had been laid by, boil it until these last articles are\n" +"sufficiently done, thicken with flour, butter and milk, and serve it up.\n"; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/asparagus")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + + cl_assert_equal_file("33f915f9e4dbd9f4b24430e48731a59b45b15500\n", 41, "rebase/.git/rebase-merge/current"); + cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum"); + + cl_git_pass(git_status_list_new(&status_list, repo, NULL)); + cl_assert_equal_i(1, git_status_list_entrycount(status_list)); + cl_assert(status_entry = git_status_byindex(status_list, 0)); + + cl_assert_equal_s("asparagus.txt", status_entry->head_to_index->new_file.path); + + cl_assert_equal_file(expected_merge, strlen(expected_merge), "rebase/asparagus.txt"); + + git_status_list_free(status_list); + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + From a35a9890b00b538cd0f3ef94a526c0dd2ec461bf Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 17 Jul 2014 18:25:03 -0400 Subject: [PATCH 06/21] Introduce git_rebase_commit Commit the current patch of a rebase process. --- include/git2/rebase.h | 28 ++++++++++ src/rebase.c | 121 ++++++++++++++++++++++++++++++++++++++---- src/signature.c | 11 ++++ src/signature.h | 1 + tests/rebase/merge.c | 91 +++++++++++++++++++++++++++++++ 5 files changed, 241 insertions(+), 11 deletions(-) diff --git a/include/git2/rebase.h b/include/git2/rebase.h index e4300ebf6..0fe2b263d 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -81,6 +81,34 @@ GIT_EXTERN(int) git_rebase_next( git_repository *repo, git_checkout_options *checkout_opts); +/** + * Commits the current patch. You must have resolved any conflicts that + * were introduced during the patch application from the `git_rebase_next` + * invocation. + * + * @param id Pointer in which to store the OID of the newly created commit + * @param repo The repository with the in-progress rebase + * @param author The author of the updated commit, or NULL to keep the + * author from the original commit + * @param committer The committer of the rebase + * @param message_encoding The encoding for the message in the commit, + * represented with a standard encoding name. If message is NULL, + * this should also be NULL, and the encoding from the original + * commit will be maintained. If message is specified, this may be + * NULL to indicate that "UTF-8" is to be used. + * @param message The message for this commit, or NULL to keep the message + * from the original commit + * @return Zero on success, GIT_EUNMERGED if there are unmerged changes in + * the index, -1 on failure. + */ +GIT_EXTERN(int) git_rebase_commit( + git_oid *id, + git_repository *repo, + const git_signature *author, + const git_signature *committer, + const char *message_encoding, + const char *message); + /** * Aborts a rebase that is currently in progress, resetting the repository * and working directory to their state before rebase began. diff --git a/src/rebase.c b/src/rebase.c index 676a803cc..9245dcada 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -33,6 +33,7 @@ #define END_FILE "end" #define CMT_FILE_FMT "cmt.%d" #define CURRENT_FILE "current" +#define REWRITTEN_FILE "rewritten" #define ORIG_DETACHED_HEAD "detached HEAD" @@ -284,7 +285,7 @@ static int rebase_finish(git_rebase_state *state) 0; } -static int rebase_setupfile(git_repository *repo, const char *filename, const char *fmt, ...) +static int rebase_setupfile(git_repository *repo, const char *filename, int flags, const char *fmt, ...) { git_buf path = GIT_BUF_INIT, contents = GIT_BUF_INIT; @@ -297,7 +298,7 @@ static int rebase_setupfile(git_repository *repo, const char *filename, const ch if ((error = git_buf_joinpath(&path, repo->path_repository, REBASE_MERGE_DIR)) == 0 && (error = git_buf_joinpath(&path, path.ptr, filename)) == 0) - error = git_futils_writebuffer(&contents, path.ptr, O_RDWR|O_CREAT, REBASE_FILE_MODE); + error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE); git_buf_free(&path); git_buf_free(&contents); @@ -361,16 +362,16 @@ static int rebase_setup_merge( git_buf_printf(&commit_filename, CMT_FILE_FMT, commit_cnt); git_oid_fmt(id_str, &id); - if ((error = rebase_setupfile(repo, commit_filename.ptr, + if ((error = rebase_setupfile(repo, commit_filename.ptr, -1, "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0) goto done; } if (error != GIT_ITEROVER || - (error = rebase_setupfile(repo, END_FILE, "%d\n", commit_cnt)) < 0) + (error = rebase_setupfile(repo, END_FILE, -1, "%d\n", commit_cnt)) < 0) goto done; - error = rebase_setupfile(repo, ONTO_NAME_FILE, "%s\n", + error = rebase_setupfile(repo, ONTO_NAME_FILE, -1, "%s\n", rebase_onto_name(onto)); done: @@ -405,10 +406,10 @@ static int rebase_setup( orig_head_name = branch->ref_name ? branch->ref_name : ORIG_DETACHED_HEAD; - if ((error = rebase_setupfile(repo, HEAD_NAME_FILE, "%s\n", orig_head_name)) < 0 || - (error = rebase_setupfile(repo, ONTO_FILE, "%s\n", onto->oid_str)) < 0 || - (error = rebase_setupfile(repo, ORIG_HEAD_FILE, "%s\n", branch->oid_str)) < 0 || - (error = rebase_setupfile(repo, QUIET_FILE, opts->quiet ? "t\n" : "\n")) < 0) + if ((error = rebase_setupfile(repo, HEAD_NAME_FILE, -1, "%s\n", orig_head_name)) < 0 || + (error = rebase_setupfile(repo, ONTO_FILE, -1, "%s\n", onto->oid_str)) < 0 || + (error = rebase_setupfile(repo, ORIG_HEAD_FILE, -1, "%s\n", branch->oid_str)) < 0 || + (error = rebase_setupfile(repo, QUIET_FILE, -1, opts->quiet ? "t\n" : "\n")) < 0) goto done; error = rebase_setup_merge(repo, branch, upstream, onto, opts); @@ -615,8 +616,8 @@ static int rebase_next_merge( goto done; } - if ((error = rebase_setupfile(repo, MSGNUM_FILE, "%d\n", state->merge.msgnum)) < 0 || - (error = rebase_setupfile(repo, CURRENT_FILE, "%s\n", current.ptr)) < 0) + if ((error = rebase_setupfile(repo, MSGNUM_FILE, -1, "%d\n", state->merge.msgnum)) < 0 || + (error = rebase_setupfile(repo, CURRENT_FILE, -1, "%s\n", current.ptr)) < 0) goto done; if ((error = normalize_checkout_opts(repo, &checkout_opts, given_checkout_opts, state)) < 0 || @@ -661,6 +662,104 @@ int git_rebase_next( return error; } +static int rebase_commit_merge( + git_oid *commit_id, + git_repository *repo, + git_rebase_state *state, + const git_signature *author, + const git_signature *committer, + const char *message_encoding, + const char *message) +{ + git_index *index = NULL; + git_reference *head = NULL; + git_commit *head_commit = NULL; + git_tree *tree = NULL; + git_oid tree_id; + char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ]; + int error; + + if (!state->merge.msgnum || !state->merge.current) { + giterr_set(GITERR_REBASE, "No rebase-merge state files exist"); + error = -1; + goto done; + } + + if ((error = git_repository_index(&index, repo)) < 0) + goto done; + + if (git_index_has_conflicts(index)) { + giterr_set(GITERR_REBASE, "Conflicts have not been resolved"); + error = GIT_EMERGECONFLICT; + goto done; + } + + /* TODO: if there are no changes, error with a useful code */ + + if ((error = git_repository_head(&head, repo)) < 0 || + (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 || + (error = git_index_write_tree(&tree_id, index)) < 0 || + (error = git_tree_lookup(&tree, repo, &tree_id)) < 0) + goto done; + + if (!author) + author = git_commit_author(state->merge.current); + + if (!message) { + message_encoding = git_commit_message_encoding(state->merge.current); + message = git_commit_message(state->merge.current); + } + + if ((error = git_commit_create(commit_id, repo, "HEAD", author, + committer, message_encoding, message, tree, 1, + (const git_commit **)&head_commit)) < 0) + goto done; + + git_oid_fmt(old_idstr, git_commit_id(state->merge.current)); + git_oid_fmt(new_idstr, commit_id); + + error = rebase_setupfile(repo, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND, + "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr); + +done: + git_tree_free(tree); + git_commit_free(head_commit); + git_reference_free(head); + git_index_free(index); + + return error; +} + +int git_rebase_commit( + git_oid *id, + git_repository *repo, + const git_signature *author, + const git_signature *committer, + const char *message_encoding, + const char *message) +{ + git_rebase_state state = GIT_REBASE_STATE_INIT; + int error; + + assert(repo && committer); + + if ((error = rebase_state(&state, repo)) < 0) + goto done; + + switch (state.type) { + case GIT_REBASE_TYPE_MERGE: + error = rebase_commit_merge( + id, repo, &state, author, committer, message_encoding, message); + break; + default: + abort(); + } + +done: + rebase_state_free(&state); + return error; +} + int git_rebase_abort(git_repository *repo, const git_signature *signature) { git_rebase_state state = GIT_REBASE_STATE_INIT; diff --git a/src/signature.c b/src/signature.c index 514b153ac..818cd300e 100644 --- a/src/signature.c +++ b/src/signature.c @@ -270,3 +270,14 @@ void git_signature__writebuf(git_buf *buf, const char *header, const git_signatu (unsigned)sig->when.time, sign, hours, mins); } +bool git_signature__equal(const git_signature *one, const git_signature *two) +{ + assert(one && two); + + return + git__strcmp(one->name, two->name) == 0 && + git__strcmp(one->email, two->email) == 0 && + one->when.time == two->when.time && + one->when.offset == two->when.offset; +} + diff --git a/src/signature.h b/src/signature.h index eb71db7db..75265df52 100644 --- a/src/signature.h +++ b/src/signature.h @@ -14,6 +14,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out, const char *buffer_end, const char *header, char ender); void git_signature__writebuf(git_buf *buf, const char *header, const git_signature *sig); +bool git_signature__equal(const git_signature *one, const git_signature *two); int git_signature__pdup(git_signature **dest, const git_signature *source, git_pool *pool); diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index 506c411ed..e578bef9b 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "git2/rebase.h" #include "posix.h" +#include "signature.h" #include @@ -11,10 +12,13 @@ static git_signature *signature; void test_rebase_merge__initialize(void) { repo = cl_git_sandbox_init("rebase"); + cl_git_pass(git_signature_new(&signature, + "Rebaser", "rebaser@rebaser.rb", 1405694510, 0)); } void test_rebase_merge__cleanup(void) { + git_signature_free(signature); cl_git_sandbox_cleanup(); } @@ -116,3 +120,90 @@ void test_rebase_merge__next_with_conflicts(void) git_reference_free(upstream_ref); } +void test_rebase_merge__commit(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_oid commit_id, tree_id, parent_id; + git_signature *author; + git_commit *commit; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_git_pass(git_commit_lookup(&commit, repo, &commit_id)); + + git_oid_fromstr(&parent_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); + cl_assert_equal_i(1, git_commit_parentcount(commit)); + cl_assert_equal_oid(&parent_id, git_commit_parent_id(commit, 0)); + + git_oid_fromstr(&tree_id, "4461379789c777d2a6c1f2ee0e9d6c86731b9992"); + cl_assert_equal_oid(&tree_id, git_commit_tree_id(commit)); + + cl_assert_equal_s(NULL, git_commit_message_encoding(commit)); + cl_assert_equal_s("Modification 1 to beef\n", git_commit_message(commit)); + + cl_git_pass(git_signature_new(&author, + "Edward Thomson", "ethomson@edwardthomson.com", 1405621769, 0-(4*60))); + cl_assert(git_signature__equal(author, git_commit_author(commit))); + + cl_assert(git_signature__equal(signature, git_commit_committer(commit))); + + cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94 776e4c48922799f903f03f5f6e51da8b01e4cce0\n", 82, "rebase/.git/rebase-merge/rewritten"); + + git_signature_free(author); + git_commit_free(commit); + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + +void test_rebase_merge__commit_updates_rewritten(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_oid commit_id; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_assert_equal_file( + "da9c51a23d02d931a486f45ad18cda05cf5d2b94 776e4c48922799f903f03f5f6e51da8b01e4cce0\n" + "8d1f13f93c4995760ac07d129246ac1ff64c0be9 ba1f9b4fd5cf8151f7818be2111cc0869f1eb95a\n", + 164, "rebase/.git/rebase-merge/rewritten"); + + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + From 93a7004cc234da31d912bb0f266c39b99ab8c8db Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 18 Jul 2014 14:50:06 -0400 Subject: [PATCH 07/21] git_rebase_commit: drop already-picked commits Already cherry-picked commits should not be re-included. If all changes included in a commit exist in the upstream, then we should error with GIT_EAPPLIED. --- include/git2/errors.h | 1 + include/git2/rebase.h | 4 +- src/rebase.c | 19 +++++++-- tests/rebase/merge.c | 38 ++++++++++++++++++ .../05/3808a709cf91385985369159b296cf61a177ac | Bin 0 -> 241 bytes .../50/8be4ff49d38465ad3de58f66d38f70e59f881f | Bin 0 -> 241 bytes .../61/139b9b40a3e489f4abbc6af14e10ae14006e47 | Bin 0 -> 224 bytes .../ad/c97cfb874cdfb9d5ab17b54f3771dea6e02ccf | Bin 0 -> 240 bytes .../cb/20a10406172afd6ca3138ce36ecaf8b1269e8e | Bin 0 -> 213 bytes .../d4/82e77aecb8e07da43e4cad6e0dcb59219e12af | Bin 0 -> 175 bytes .../dc/12ac1e10f2be70e8ecd52132a08da98a309c3a | Bin 0 -> 187 bytes .../e7/bb00c4eab291e08361fda376733a12b4150aa9 | Bin 0 -> 241 bytes .../ed/f7b3ffde1624c60d2d6b1a2bb792d86de172e0 | Bin 0 -> 171 bytes .../rebase/.gitted/refs/heads/green_pea | Bin 0 -> 41 bytes 14 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177ac create mode 100644 tests/resources/rebase/.gitted/objects/50/8be4ff49d38465ad3de58f66d38f70e59f881f create mode 100644 tests/resources/rebase/.gitted/objects/61/139b9b40a3e489f4abbc6af14e10ae14006e47 create mode 100644 tests/resources/rebase/.gitted/objects/ad/c97cfb874cdfb9d5ab17b54f3771dea6e02ccf create mode 100644 tests/resources/rebase/.gitted/objects/cb/20a10406172afd6ca3138ce36ecaf8b1269e8e create mode 100644 tests/resources/rebase/.gitted/objects/d4/82e77aecb8e07da43e4cad6e0dcb59219e12af create mode 100644 tests/resources/rebase/.gitted/objects/dc/12ac1e10f2be70e8ecd52132a08da98a309c3a create mode 100644 tests/resources/rebase/.gitted/objects/e7/bb00c4eab291e08361fda376733a12b4150aa9 create mode 100644 tests/resources/rebase/.gitted/objects/ed/f7b3ffde1624c60d2d6b1a2bb792d86de172e0 create mode 100644 tests/resources/rebase/.gitted/refs/heads/green_pea diff --git a/include/git2/errors.h b/include/git2/errors.h index 5dfa72ab8..b33118e02 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -43,6 +43,7 @@ typedef enum { GIT_EMODIFIED = -15, /**< Reference value does not match expected */ GIT_EAUTH = -16, /**< Authentication error */ GIT_ECERTIFICATE = -17, /**< Server certificate is invalid */ + GIT_EAPPLIED = -18, /**< Patch/merge has already been applied */ GIT_PASSTHROUGH = -30, /**< Internal only */ GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */ diff --git a/include/git2/rebase.h b/include/git2/rebase.h index 0fe2b263d..32b4ff614 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -99,7 +99,9 @@ GIT_EXTERN(int) git_rebase_next( * @param message The message for this commit, or NULL to keep the message * from the original commit * @return Zero on success, GIT_EUNMERGED if there are unmerged changes in - * the index, -1 on failure. + * the index, GIT_EAPPLIED if the current commit has already + * been applied to the upstream and there is nothing to commit, + * -1 on failure. */ GIT_EXTERN(int) git_rebase_commit( git_oid *id, diff --git a/src/rebase.c b/src/rebase.c index 9245dcada..a28a928fc 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -674,7 +674,8 @@ static int rebase_commit_merge( git_index *index = NULL; git_reference *head = NULL; git_commit *head_commit = NULL; - git_tree *tree = NULL; + git_tree *head_tree = NULL, *tree = NULL; + git_diff *diff = NULL; git_oid tree_id; char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ]; int error; @@ -694,11 +695,19 @@ static int rebase_commit_merge( goto done; } - /* TODO: if there are no changes, error with a useful code */ - if ((error = git_repository_head(&head, repo)) < 0 || (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 || - (error = git_index_write_tree(&tree_id, index)) < 0 || + (error = git_commit_tree(&head_tree, head_commit)) < 0 || + (error = git_diff_tree_to_index(&diff, repo, head_tree, index, NULL)) < 0) + goto done; + + if (git_diff_num_deltas(diff) == 0) { + giterr_set(GITERR_REBASE, "This patch has already been applied"); + error = GIT_EAPPLIED; + goto done; + } + + if ((error = git_index_write_tree(&tree_id, index)) < 0 || (error = git_tree_lookup(&tree, repo, &tree_id)) < 0) goto done; @@ -722,7 +731,9 @@ static int rebase_commit_merge( "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr); done: + git_diff_free(diff); git_tree_free(tree); + git_tree_free(head_tree); git_commit_free(head_commit); git_reference_free(head); git_index_free(index); diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index e578bef9b..04d06d2e8 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -207,3 +207,41 @@ void test_rebase_merge__commit_updates_rewritten(void) git_reference_free(upstream_ref); } +void test_rebase_merge__commit_drops_already_applied(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_oid commit_id; + int error; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/green_pea")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_fail(error = git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_assert_equal_i(GIT_EAPPLIED, error); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_assert_equal_file( + "8d1f13f93c4995760ac07d129246ac1ff64c0be9 2ac4fb7b74c1287f6c792acad759e1ec01e18dae\n", + 82, "rebase/.git/rebase-merge/rewritten"); + + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + diff --git a/tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177ac b/tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177ac new file mode 100644 index 0000000000000000000000000000000000000000..c38c5b2559b84ceb7258e8da700eedc03890bbe9 GIT binary patch literal 241 zcmV5vtTeZFfcPQQAjK(d zZoQKFhYj;yN6FsfYiQ+yDoZa)EUN@7I`Zty;x}0jMEWin{wxZ=-(x7p7!OyJnwl41 zkeUcqm?%7Zw!`8lonKb($@=Iguug;_&mF2Tzp}U_wFs;#W4-)whx(gq?~608sM~ll rrew;|8BkSasfjsYHOn`o1=nRi7nrsG$^YrwO0PU9zoh^G>x*v?$P9A> literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/50/8be4ff49d38465ad3de58f66d38f70e59f881f b/tests/resources/rebase/.gitted/objects/50/8be4ff49d38465ad3de58f66d38f70e59f881f new file mode 100644 index 0000000000000000000000000000000000000000..7ce4452b20d881ce6da47bae4d2d29bb7ab34217 GIT binary patch literal 241 zcmV5vtTeZFfcPQQAjKe(PQ)+_MOo)7?gvz}m=zMMibgQv(a}64W|_7wiExw9II8;hqyn+C zu8;3=$Dzaiet-9L()t}oUE|zdk2|H_>KBc}1^T0Yyu98}pK)uiXj)vJHJZ~wH~)Br z;CY4fh-`X77$KHaPfYWQL^M>0Szus|AI8iZF*z^jZHSQuq{%Q>DBA+XZBvLfWdErm znN(r1uD6(S5_E(vI4)O3SUgA}M~GvFkRND%D5>ke$ioR1Cl*G1XEO`UTWt}P;$a)R aEG7K)$`X)b2tNHiIC9AIPW=FMfM2`M3u^%Y literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/ad/c97cfb874cdfb9d5ab17b54f3771dea6e02ccf b/tests/resources/rebase/.gitted/objects/ad/c97cfb874cdfb9d5ab17b54f3771dea6e02ccf new file mode 100644 index 0000000000000000000000000000000000000000..cc7ccd086741e69c8497d5d45ab28f9c6aff4754 GIT binary patch literal 240 zcmV5vtTeZFfcPQQAjK*bF-)ZbitUz~A8-NutK qB~y;hfT}7>P0RtSS-v4HxGwv-z^wgG{!ialdgVd+Ed>CSKW@m+7H>=d literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/cb/20a10406172afd6ca3138ce36ecaf8b1269e8e b/tests/resources/rebase/.gitted/objects/cb/20a10406172afd6ca3138ce36ecaf8b1269e8e new file mode 100644 index 0000000000000000000000000000000000000000..acd6bdc56c66e9a9d28822b20e7d525bf8edd683 GIT binary patch literal 213 zcmV;`04o1@0WFR(Zo@DPMLX*h{{TjYOa(e+FgmpjQuF|_L{~y&QI#k-zI`dQ8$mw) z_m{*A&d=wk*V{b5<2qmP`SEo<8S`fEgeahgb&?L)hJ!miLju9qNFIeO8uv1Rvm!C0 zBOVfqDgJDDNWF;LSy#Q$aOB@Ly8cI5PwDGPXh2tm~aeWNp26Qv?q|r<) zIZqW#XEt>e0gqu6my#RU2G@CF%i=@oy5>`l;)fK1PHLf5<_a9Op{PY;GNUveB(gW! z8p6Od1hP0pONyTLURF5qi&loqz2rxkVJ|KHsH1$r&+TH#2ha|EkG-}Iw&)O5OWW8g df7YmT;VDg#>eMD^s0D8A`+Qx5)Ej|dR+c2HQEvbM literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/dc/12ac1e10f2be70e8ecd52132a08da98a309c3a b/tests/resources/rebase/.gitted/objects/dc/12ac1e10f2be70e8ecd52132a08da98a309c3a new file mode 100644 index 0000000000000000000000000000000000000000..9907248f80272eb58e06e82f680ad4640f9f1cd2 GIT binary patch literal 187 zcmV;s07UJ&!nb7WI$ZH^8!^##STMvhD=1fy-~b@yZ7D) zk1w@ts{1m4XX_-`BQh`M%3b#XnhS|9C991tq=?z& zD3+ZFEiRwp1mqMAe~h(tc*&pKGrX;ByR{u2b*?|@tiRx|J*2ihfem;hj6@6EV?Z=> pow7s!d1Ibe?fna`HC^id4u{v4YpIDxok|u)15qsp^9{O>T6wLJR`>t_ literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/objects/e7/bb00c4eab291e08361fda376733a12b4150aa9 b/tests/resources/rebase/.gitted/objects/e7/bb00c4eab291e08361fda376733a12b4150aa9 new file mode 100644 index 0000000000000000000000000000000000000000..da96e9d9c06f9526ab0d57d2fe2b2accd1b5475f GIT binary patch literal 241 zcmV5vtTeZFfcPQQAjKr68u>*Q zZbXQ!aF%GUeveB(;6r}uA#l3%?W^zbqEr1tZ+bKC?1}sK3L*ML9Kr@t ZpE2%TWF70Q?*^aq^?tr;b-!AYRfImAR)qin literal 0 HcmV?d00001 diff --git a/tests/resources/rebase/.gitted/refs/heads/green_pea b/tests/resources/rebase/.gitted/refs/heads/green_pea new file mode 100644 index 0000000000000000000000000000000000000000..3bffe27d1e1b412f5a7e62fb191b68805fd34921 GIT binary patch literal 41 ucmV~$NdW*L2n4{tX#i0m4#(O*f-|EoFiUhf$R>3|JLiI?>x6KCCExl0mka3t literal 0 HcmV?d00001 From 14864fbfebfd3eb949790f302cfd872f1c0cc214 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 18 Jul 2014 15:37:42 -0400 Subject: [PATCH 08/21] git_rebase_next: test that we return GIT_ITEROVER --- tests/rebase/merge.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index 04d06d2e8..31fa6cc5e 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -120,6 +120,56 @@ void test_rebase_merge__next_with_conflicts(void) git_reference_free(upstream_ref); } +void test_rebase_merge__next_stops_with_iterover(void) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_oid commit_id; + int error; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_git_fail(error = git_rebase_next(repo, &checkout_opts)); + cl_assert_equal_i(GIT_ITEROVER, error); + + cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); + cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/msgnum"); + + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + void test_rebase_merge__commit(void) { git_reference *branch_ref, *upstream_ref; From 517644cce4df8ac9ea40669dd22574d6dc76c02f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 18 Jul 2014 17:19:10 -0400 Subject: [PATCH 09/21] Introduce git_rebase_finish to complete a rebase --- include/git2/rebase.h | 12 +++++++++ src/rebase.c | 63 ++++++++++++++++++++++++++++++++++++++++++- tests/rebase/merge.c | 57 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) diff --git a/include/git2/rebase.h b/include/git2/rebase.h index 32b4ff614..e123ae506 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -124,6 +124,18 @@ GIT_EXTERN(int) git_rebase_abort( git_repository *repo, const git_signature *signature); +/** + * Finishes a rebase that is currently in progress once all patches have + * been applied. + * + * @param repo The repository with the in-progress rebase + * @param signature The identity that is finishing the rebase + * @param Zero on success; -1 on error + */ +GIT_EXTERN(int) git_rebase_finish( + git_repository *repo, + const git_signature *signature); + /** @} */ GIT_END_DECL #endif diff --git a/src/rebase.c b/src/rebase.c index a28a928fc..101dfb107 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -64,6 +64,8 @@ typedef struct { char *orig_head_name; git_oid orig_head_id; + git_oid onto_id; + union { struct git_rebase_state_merge merge; }; @@ -189,7 +191,7 @@ done: static int rebase_state(git_rebase_state *state, git_repository *repo) { git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT, - orig_head_id = GIT_BUF_INIT; + orig_head_id = GIT_BUF_INIT, onto_id = GIT_BUF_INIT; int state_path_len, error; memset(state, 0x0, sizeof(git_rebase_state)); @@ -237,6 +239,17 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) if ((error = git_oid_fromstr(&state->orig_head_id, orig_head_id.ptr)) < 0) goto done; + git_buf_truncate(&path, state_path_len); + + if ((error = git_buf_joinpath(&path, path.ptr, ONTO_FILE)) < 0 || + (error = git_futils_readbuffer(&onto_id, path.ptr)) < 0) + goto done; + + git_buf_rtrim(&onto_id); + + if ((error = git_oid_fromstr(&state->onto_id, onto_id.ptr)) < 0) + goto done; + if (!state->head_detached) state->orig_head_name = git_buf_detach(&orig_head_name); @@ -808,3 +821,51 @@ done: return error; } + +int git_rebase_finish(git_repository *repo, const git_signature *signature) +{ + git_rebase_state state = GIT_REBASE_STATE_INIT; + git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL; + git_commit *terminal_commit = NULL; + git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT; + char onto[GIT_OID_HEXSZ]; + int error; + + assert(repo); + + if ((error = rebase_state(&state, repo)) < 0) + goto done; + + git_oid_fmt(onto, &state.onto_id); + + if ((error = git_buf_printf(&branch_msg, "rebase finished: %s onto %.*s", + state.orig_head_name, GIT_OID_HEXSZ, onto)) < 0 || + (error = git_buf_printf(&head_msg, "rebase finished: returning to %s", + state.orig_head_name)) < 0 || + (error = git_repository_head(&terminal_ref, repo)) < 0 || + (error = git_reference_peel((git_object **)&terminal_commit, + terminal_ref, GIT_OBJ_COMMIT)) < 0) + goto done; + + if ((error = git_reference_create_matching(&branch_ref, + repo, state.orig_head_name, git_commit_id(terminal_commit), 1, + &state.orig_head_id, signature, branch_msg.ptr)) < 0 || + (error = git_reference_symbolic_create(&head_ref, + repo, GIT_HEAD_FILE, state.orig_head_name, 1, + signature, head_msg.ptr)) < 0) + goto done; + + error = rebase_finish(&state); + +done: + git_buf_free(&head_msg); + git_buf_free(&branch_msg); + git_commit_free(terminal_commit); + git_reference_free(head_ref); + git_reference_free(branch_ref); + git_reference_free(terminal_ref); + rebase_state_free(&state); + + return error; +} + diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index 31fa6cc5e..fa37e89e6 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -295,3 +295,60 @@ void test_rebase_merge__commit_drops_already_applied(void) git_reference_free(upstream_ref); } +void test_rebase_merge__finish(void) +{ + git_reference *branch_ref, *upstream_ref, *head_ref; + git_merge_head *branch_head, *upstream_head; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_oid commit_id; + git_reflog *reflog; + const git_reflog_entry *reflog_entry; + int error; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_git_fail(error = git_rebase_next(repo, &checkout_opts)); + cl_assert_equal_i(GIT_ITEROVER, error); + + cl_git_pass(git_rebase_finish(repo, signature)); + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + cl_git_pass(git_reference_lookup(&head_ref, repo, "HEAD")); + cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head_ref)); + cl_assert_equal_s("refs/heads/gravy", git_reference_symbolic_target(head_ref)); + + /* Make sure the reflogs are updated appropriately */ + cl_git_pass(git_reflog_read(&reflog, repo, "HEAD")); + cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0)); + cl_assert_equal_oid(&commit_id, git_reflog_entry_id_old(reflog_entry)); + cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry)); + cl_assert_equal_s("rebase finished: returning to refs/heads/gravy", git_reflog_entry_message(reflog_entry)); + git_reflog_free(reflog); + + cl_git_pass(git_reflog_read(&reflog, repo, "refs/heads/gravy")); + cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0)); + cl_assert_equal_oid(git_merge_head_id(branch_head), git_reflog_entry_id_old(reflog_entry)); + cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry)); + cl_assert_equal_s("rebase finished: refs/heads/gravy onto f87d14a4a236582a0278a916340a793714256864", git_reflog_entry_message(reflog_entry)); + + git_reflog_free(reflog); + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(head_ref); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + From a612a25fa673447e874407fd2d9501998885d392 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 18 Jul 2014 18:22:54 -0400 Subject: [PATCH 10/21] git_rebase_commit: write HEAD's reflog appropriately --- src/commit.c | 36 +++++------------------------------- src/rebase.c | 12 +++++++++--- src/refs.c | 35 +++++++++++++++++++++++++++++++++++ src/refs.h | 9 +++++++++ tests/rebase/merge.c | 10 +++++++++- 5 files changed, 67 insertions(+), 35 deletions(-) diff --git a/src/commit.c b/src/commit.c index 227d5c4a5..78c4b9de3 100644 --- a/src/commit.c +++ b/src/commit.c @@ -16,6 +16,7 @@ #include "commit.h" #include "signature.h" #include "message.h" +#include "refs.h" void git_commit__free(void *_commit) { @@ -34,35 +35,6 @@ void git_commit__free(void *_commit) git__free(commit); } -static int update_ref_for_commit(git_repository *repo, git_reference *ref, const char *update_ref, const git_oid *id, const git_signature *committer) -{ - git_reference *ref2 = NULL; - int error; - git_commit *c; - const char *shortmsg; - git_buf reflog_msg = GIT_BUF_INIT; - - if ((error = git_commit_lookup(&c, repo, id)) < 0) { - return error; - } - - shortmsg = git_commit_summary(c); - git_buf_printf(&reflog_msg, "commit%s: %s", - git_commit_parentcount(c) == 0 ? " (initial)" : "", - shortmsg); - git_commit_free(c); - - if (ref) { - error = git_reference_set_target(&ref2, ref, id, committer, git_buf_cstr(&reflog_msg)); - git_reference_free(ref2); - } else { - error = git_reference__update_terminal(repo, update_ref, id, committer, git_buf_cstr(&reflog_msg)); - } - - git_buf_free(&reflog_msg); - return error; -} - int git_commit_create_from_callback( git_oid *id, git_repository *repo, @@ -131,7 +103,8 @@ int git_commit_create_from_callback( git_buf_free(&commit); if (update_ref != NULL) { - error = update_ref_for_commit(repo, ref, update_ref, id, committer); + error = git_reference__update_for_commit( + repo, ref, update_ref, id, committer, "commit"); git_reference_free(ref); return error; } @@ -321,7 +294,8 @@ int git_commit_amend( &tree_id, commit_parent_for_amend, (void *)commit_to_amend); if (!error && update_ref) { - error = update_ref_for_commit(repo, ref, NULL, id, committer); + error = git_reference__update_for_commit( + repo, ref, NULL, id, committer, "commit"); git_reference_free(ref); } diff --git a/src/rebase.c b/src/rebase.c index 101dfb107..60c3dd02b 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -686,10 +686,11 @@ static int rebase_commit_merge( { git_index *index = NULL; git_reference *head = NULL; - git_commit *head_commit = NULL; + git_commit *head_commit = NULL, *commit = NULL; git_tree *head_tree = NULL, *tree = NULL; git_diff *diff = NULL; git_oid tree_id; + git_buf reflog_msg = GIT_BUF_INIT; char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ]; int error; @@ -732,9 +733,12 @@ static int rebase_commit_merge( message = git_commit_message(state->merge.current); } - if ((error = git_commit_create(commit_id, repo, "HEAD", author, + if ((error = git_commit_create(commit_id, repo, NULL, author, committer, message_encoding, message, tree, 1, - (const git_commit **)&head_commit)) < 0) + (const git_commit **)&head_commit)) < 0 || + (error = git_commit_lookup(&commit, repo, commit_id)) < 0 || + (error = git_reference__update_for_commit( + repo, NULL, "HEAD", commit_id, committer, "rebase")) < 0) goto done; git_oid_fmt(old_idstr, git_commit_id(state->merge.current)); @@ -744,6 +748,8 @@ static int rebase_commit_merge( "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr); done: + git_buf_free(&reflog_msg); + git_commit_free(commit); git_diff_free(diff); git_tree_free(tree); git_tree_free(head_tree); diff --git a/src/refs.c b/src/refs.c index 08e407e48..43c7333f2 100644 --- a/src/refs.c +++ b/src/refs.c @@ -22,6 +22,7 @@ #include #include #include +#include GIT__USE_STRMAP; @@ -1090,6 +1091,40 @@ int git_reference__update_terminal( return reference__update_terminal(repo, ref_name, oid, 0, signature, log_message); } +int git_reference__update_for_commit( + git_repository *repo, + git_reference *ref, + const char *ref_name, + const git_oid *id, + const git_signature *committer, + const char *operation) +{ + git_reference *ref_new = NULL; + git_commit *commit = NULL; + git_buf reflog_msg = GIT_BUF_INIT; + int error; + + if ((error = git_commit_lookup(&commit, repo, id)) < 0 || + (error = git_buf_printf(&reflog_msg, "%s%s: %s", + operation ? operation : "commit", + git_commit_parentcount(commit) == 0 ? " (initial)" : "", + git_commit_summary(commit))) < 0) + goto done; + + if (ref) + error = git_reference_set_target( + &ref_new, ref, id, committer, git_buf_cstr(&reflog_msg)); + else + error = git_reference__update_terminal( + repo, ref_name, id, committer, git_buf_cstr(&reflog_msg)); + +done: + git_reference_free(ref_new); + git_buf_free(&reflog_msg); + git_commit_free(commit); + return error; +} + int git_reference_has_log(git_repository *repo, const char *refname) { int error; diff --git a/src/refs.h b/src/refs.h index c6ec429a5..5f48efc41 100644 --- a/src/refs.h +++ b/src/refs.h @@ -100,4 +100,13 @@ int git_reference_lookup_resolved( int git_reference__log_signature(git_signature **out, git_repository *repo); +/** Update a reference after a commit. */ +int git_reference__update_for_commit( + git_repository *repo, + git_reference *ref, + const char *ref_name, + const git_oid *id, + const git_signature *committer, + const char *operation); + #endif diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index fa37e89e6..0d4dca489 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -178,6 +178,8 @@ void test_rebase_merge__commit(void) git_oid commit_id, tree_id, parent_id; git_signature *author; git_commit *commit; + git_reflog *reflog; + const git_reflog_entry *reflog_entry; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; @@ -211,8 +213,14 @@ void test_rebase_merge__commit(void) cl_assert(git_signature__equal(signature, git_commit_committer(commit))); - cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94 776e4c48922799f903f03f5f6e51da8b01e4cce0\n", 82, "rebase/.git/rebase-merge/rewritten"); + /* Make sure the reflogs are updated appropriately */ + cl_git_pass(git_reflog_read(&reflog, repo, "HEAD")); + cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0)); + cl_assert_equal_oid(&parent_id, git_reflog_entry_id_old(reflog_entry)); + cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry)); + cl_assert_equal_s("rebase: Modification 1 to beef", git_reflog_entry_message(reflog_entry)); + git_reflog_free(reflog); git_signature_free(author); git_commit_free(commit); git_merge_head_free(branch_head); From bad4937ea50a8874598171c7ccb3d3443f1daf7b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 21 Jul 2014 10:47:01 -0400 Subject: [PATCH 11/21] Introduce `git_note_author`, `git_note_committer` --- include/git2/notes.h | 17 +++++++++++++++++ src/notes.c | 35 +++++++++++++++++++++++++++++++---- src/notes.h | 3 +++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/include/git2/notes.h b/include/git2/notes.h index 98eb2aef3..1a7794a5c 100644 --- a/include/git2/notes.h +++ b/include/git2/notes.h @@ -96,6 +96,23 @@ GIT_EXTERN(int) git_note_read( const char *notes_ref, const git_oid *oid); +/** + * Get the note author + * + * @param note the note + * @return the author + */ +GIT_EXTERN(const git_signature *) git_note_author(const git_note *note); + +/** + * Get the note committer + * + * @param note the note + * @return the committer + */ +GIT_EXTERN(const git_signature *) git_note_committer(const git_note *note); + + /** * Get the note message * diff --git a/src/notes.c b/src/notes.c index ffe5d345a..046a91614 100644 --- a/src/notes.c +++ b/src/notes.c @@ -306,7 +306,11 @@ cleanup: return error; } -static int note_new(git_note **out, git_oid *note_oid, git_blob *blob) +static int note_new( + git_note **out, + git_oid *note_oid, + git_commit *commit, + git_blob *blob) { git_note *note = NULL; @@ -314,6 +318,11 @@ static int note_new(git_note **out, git_oid *note_oid, git_blob *blob) GITERR_CHECK_ALLOC(note); git_oid_cpy(¬e->id, note_oid); + + if (git_signature_dup(¬e->author, git_commit_author(commit)) < 0 || + git_signature_dup(¬e->committer, git_commit_committer(commit)) < 0) + return -1; + note->message = git__strdup((char *)git_blob_rawcontent(blob)); GITERR_CHECK_ALLOC(note->message); @@ -323,7 +332,11 @@ static int note_new(git_note **out, git_oid *note_oid, git_blob *blob) } static int note_lookup( - git_note **out, git_repository *repo, git_tree *tree, const char *target) + git_note **out, + git_repository *repo, + git_commit *commit, + git_tree *tree, + const char *target) { int error, fanout = 0; git_oid oid; @@ -340,7 +353,7 @@ static int note_lookup( if ((error = git_blob_lookup(&blob, repo, &oid)) < 0) goto cleanup; - if ((error = note_new(¬e, &oid, blob)) < 0) + if ((error = note_new(¬e, &oid, commit, blob)) < 0) goto cleanup; *out = note; @@ -432,7 +445,7 @@ int git_note_read(git_note **out, git_repository *repo, if (!(error = retrieve_note_tree_and_commit( &tree, &commit, repo, ¬es_ref))) - error = note_lookup(out, repo, tree, target); + error = note_lookup(out, repo, commit, tree, target); git__free(target); git_tree_free(tree); @@ -502,6 +515,18 @@ int git_note_default_ref(const char **out, git_repository *repo) return note_get_default_ref(out, repo); } +const git_signature *git_note_committer(const git_note *note) +{ + assert(note); + return note->committer; +} + +const git_signature *git_note_author(const git_note *note) +{ + assert(note); + return note->author; +} + const char * git_note_message(const git_note *note) { assert(note); @@ -519,6 +544,8 @@ void git_note_free(git_note *note) if (note == NULL) return; + git_signature_free(note->committer); + git_signature_free(note->author); git__free(note->message); git__free(note); } diff --git a/src/notes.h b/src/notes.h index e9cfa00fa..cfc0ca239 100644 --- a/src/notes.h +++ b/src/notes.h @@ -23,6 +23,9 @@ struct git_note { git_oid id; + git_signature *author; + git_signature *committer; + char *message; }; From 5ae9d296e3313be59a969cb8eab250c7c8f7307d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 21 Jul 2014 12:25:03 -0400 Subject: [PATCH 12/21] git_rebase_finish: rewrite notes when finishing rebase --- include/git2/rebase.h | 13 +++- src/rebase.c | 166 ++++++++++++++++++++++++++++++++++++++---- tests/rebase/merge.c | 94 +++++++++++++++++++++++- 3 files changed, 255 insertions(+), 18 deletions(-) diff --git a/include/git2/rebase.h b/include/git2/rebase.h index e123ae506..d9cf2318e 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -28,6 +28,15 @@ typedef struct { * interoperability with other clients. */ int quiet; + + /** + * Canonical name of the notes reference used to rewrite notes for + * rebased commits when finishing the rebase; if NULL, the contents of + * the coniguration option `notes.rewriteRef` is examined, unless the + * configuration option `notes.rewrite.rebase` is set to false. If + * `notes.rewriteRef` is NULL, notes will not be rewritten. + */ + const char *rewrite_notes_ref; } git_rebase_options; #define GIT_REBASE_OPTIONS_VERSION 1 @@ -130,11 +139,13 @@ GIT_EXTERN(int) git_rebase_abort( * * @param repo The repository with the in-progress rebase * @param signature The identity that is finishing the rebase + * @param opts Options to specify how rebase is finished * @param Zero on success; -1 on error */ GIT_EXTERN(int) git_rebase_finish( git_repository *repo, - const git_signature *signature); + const git_signature *signature, + const git_rebase_options *opts); /** @} */ GIT_END_DECL diff --git a/src/rebase.c b/src/rebase.c index 60c3dd02b..3384a14f2 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -12,12 +12,14 @@ #include "filebuf.h" #include "merge.h" #include "array.h" +#include "config.h" #include #include #include #include #include +#include #define REBASE_APPLY_DIR "rebase-apply" #define REBASE_MERGE_DIR "rebase-merge" @@ -37,6 +39,8 @@ #define ORIG_DETACHED_HEAD "detached HEAD" +#define NOTES_DEFAULT_REF NULL + #define REBASE_DIR_MODE 0777 #define REBASE_FILE_MODE 0666 @@ -291,7 +295,7 @@ static void rebase_state_free(git_rebase_state *state) git__free(state->state_path); } -static int rebase_finish(git_rebase_state *state) +static int rebase_cleanup(git_rebase_state *state) { return git_path_isdir(state->state_path) ? git_futils_rmdir_r(state->state_path, NULL, GIT_RMDIR_REMOVE_FILES) : @@ -443,12 +447,46 @@ int git_rebase_init_options(git_rebase_options *opts, unsigned int version) return 0; } -static void rebase_normalize_options( +static int rebase_normalize_opts( + git_repository *repo, git_rebase_options *opts, const git_rebase_options *given_opts) { + git_rebase_options default_opts = GIT_REBASE_OPTIONS_INIT; + git_config *config; + if (given_opts) - memcpy(&opts, given_opts, sizeof(git_rebase_options)); + memcpy(opts, given_opts, sizeof(git_rebase_options)); + else + memcpy(opts, &default_opts, sizeof(git_rebase_options)); + + if (git_repository_config(&config, repo) < 0) + return -1; + + if (given_opts && given_opts->rewrite_notes_ref) { + opts->rewrite_notes_ref = git__strdup(given_opts->rewrite_notes_ref); + GITERR_CHECK_ALLOC(opts->rewrite_notes_ref); + } else if (git_config__get_bool_force(config, "notes.rewrite.rebase", 1)) { + const char *rewrite_ref = git_config__get_string_force( + config, "notes.rewriteref", NOTES_DEFAULT_REF); + + if (rewrite_ref) { + opts->rewrite_notes_ref = git__strdup(rewrite_ref); + GITERR_CHECK_ALLOC(opts->rewrite_notes_ref); + } + } + + git_config_free(config); + + return 0; +} + +static void rebase_opts_free(git_rebase_options *opts) +{ + if (!opts) + return; + + git__free((char *)opts->rewrite_notes_ref); } static int rebase_ensure_not_in_progress(git_repository *repo) @@ -512,7 +550,7 @@ int git_rebase( const git_signature *signature, const git_rebase_options *given_opts) { - git_rebase_options opts = GIT_REBASE_OPTIONS_INIT; + git_rebase_options opts; git_reference *head_ref = NULL; git_buf reflog = GIT_BUF_INIT; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; @@ -521,9 +559,9 @@ int git_rebase( assert(repo && branch && (upstream || onto)); GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options"); - rebase_normalize_options(&opts, given_opts); - if ((error = git_repository__ensure_not_bare(repo, "rebase")) < 0 || + if ((error = rebase_normalize_opts(repo, &opts, given_opts)) < 0 || + (error = git_repository__ensure_not_bare(repo, "rebase")) < 0 || (error = rebase_ensure_not_in_progress(repo)) < 0 || (error = rebase_ensure_not_dirty(repo)) < 0) goto done; @@ -546,6 +584,7 @@ int git_rebase( done: git_reference_free(head_ref); git_buf_free(&reflog); + rebase_opts_free(&opts); return error; } @@ -818,7 +857,7 @@ int git_rebase_abort(git_repository *repo, const git_signature *signature) GIT_RESET_HARD, NULL, signature, NULL)) < 0) goto done; - error = rebase_finish(&state); + error = rebase_cleanup(&state); done: git_commit_free(orig_head_commit); @@ -828,8 +867,102 @@ done: return error; } -int git_rebase_finish(git_repository *repo, const git_signature *signature) +static int rebase_copy_note( + git_repository *repo, + git_oid *from, + git_oid *to, + const git_signature *committer, + const git_rebase_options *opts) { + git_note *note = NULL; + git_oid note_id; + int error; + + if ((error = git_note_read(¬e, repo, opts->rewrite_notes_ref, from)) < 0) { + if (error == GIT_ENOTFOUND) { + giterr_clear(); + error = 0; + } + + goto done; + } + + error = git_note_create(¬e_id, repo, git_note_author(note), + committer, opts->rewrite_notes_ref, to, git_note_message(note), 0); + +done: + git_note_free(note); + + return error; +} + +static int rebase_copy_notes( + git_repository *repo, + git_rebase_state *state, + const git_signature *committer, + const git_rebase_options *opts) +{ + git_buf path = GIT_BUF_INIT, rewritten = GIT_BUF_INIT; + char *pair_list, *fromstr, *tostr, *end; + git_oid from, to; + unsigned int linenum = 1; + int error = 0; + + if (!opts->rewrite_notes_ref) + goto done; + + if ((error = git_buf_joinpath(&path, state->state_path, REWRITTEN_FILE)) < 0 || + (error = git_futils_readbuffer(&rewritten, path.ptr)) < 0) + goto done; + + pair_list = rewritten.ptr; + + while (*pair_list) { + fromstr = pair_list; + + if ((end = strchr(fromstr, '\n')) == NULL) + goto on_error; + + pair_list = end+1; + *end = '\0'; + + if ((end = strchr(fromstr, ' ')) == NULL) + goto on_error; + + tostr = end+1; + *end = '\0'; + + if (strlen(fromstr) != GIT_OID_HEXSZ || + strlen(tostr) != GIT_OID_HEXSZ || + git_oid_fromstr(&from, fromstr) < 0 || + git_oid_fromstr(&to, tostr) < 0) + goto on_error; + + if ((error = rebase_copy_note(repo, &from, &to, committer, opts)) < 0) + goto done; + + linenum++; + } + + goto done; + +on_error: + giterr_set(GITERR_REBASE, "Invalid rewritten file at line %d", linenum); + error = -1; + +done: + git_buf_free(&rewritten); + git_buf_free(&path); + + return error; +} + +int git_rebase_finish( + git_repository *repo, + const git_signature *signature, + const git_rebase_options *given_opts) +{ + git_rebase_options opts; git_rebase_state state = GIT_REBASE_STATE_INIT; git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL; git_commit *terminal_commit = NULL; @@ -839,7 +972,8 @@ int git_rebase_finish(git_repository *repo, const git_signature *signature) assert(repo); - if ((error = rebase_state(&state, repo)) < 0) + if ((error = rebase_normalize_opts(repo, &opts, given_opts)) < 0 || + (error = rebase_state(&state, repo)) < 0) goto done; git_oid_fmt(onto, &state.onto_id); @@ -850,18 +984,17 @@ int git_rebase_finish(git_repository *repo, const git_signature *signature) state.orig_head_name)) < 0 || (error = git_repository_head(&terminal_ref, repo)) < 0 || (error = git_reference_peel((git_object **)&terminal_commit, - terminal_ref, GIT_OBJ_COMMIT)) < 0) - goto done; - - if ((error = git_reference_create_matching(&branch_ref, + terminal_ref, GIT_OBJ_COMMIT)) < 0 || + (error = git_reference_create_matching(&branch_ref, repo, state.orig_head_name, git_commit_id(terminal_commit), 1, &state.orig_head_id, signature, branch_msg.ptr)) < 0 || (error = git_reference_symbolic_create(&head_ref, repo, GIT_HEAD_FILE, state.orig_head_name, 1, - signature, head_msg.ptr)) < 0) + signature, head_msg.ptr)) < 0 || + (error = rebase_copy_notes(repo, &state, signature, &opts)) < 0) goto done; - - error = rebase_finish(&state); + + error = rebase_cleanup(&state); done: git_buf_free(&head_msg); @@ -871,6 +1004,7 @@ done: git_reference_free(branch_ref); git_reference_free(terminal_ref); rebase_state_free(&state); + rebase_opts_free(&opts); return error; } diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index 0d4dca489..fddab8397 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -330,7 +330,7 @@ void test_rebase_merge__finish(void) cl_git_fail(error = git_rebase_next(repo, &checkout_opts)); cl_assert_equal_i(GIT_ITEROVER, error); - cl_git_pass(git_rebase_finish(repo, signature)); + cl_git_pass(git_rebase_finish(repo, signature, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); @@ -360,3 +360,95 @@ void test_rebase_merge__finish(void) git_reference_free(upstream_ref); } +static void test_copy_note( + const git_rebase_options *opts, + bool should_exist) +{ + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_commit *branch_commit; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_oid note_id, commit_id; + git_note *note = NULL; + int error; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_reference_peel((git_object **)&branch_commit, + branch_ref, GIT_OBJ_COMMIT)); + + /* Add a note to a commit */ + cl_git_pass(git_note_create(¬e_id, repo, + git_commit_author(branch_commit), git_commit_committer(branch_commit), + "refs/notes/test", git_commit_id(branch_commit), + "This is a commit note.", 0)); + + cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, opts)); + + cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + NULL, NULL)); + + cl_git_pass(git_rebase_finish(repo, signature, opts)); + + cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); + + if (should_exist) { + cl_git_pass(git_note_read(¬e, repo, "refs/notes/test", &commit_id)); + cl_assert_equal_s("This is a commit note.", git_note_message(note)); + } else { + cl_git_fail(error = + git_note_read(¬e, repo, "refs/notes/test", &commit_id)); + cl_assert_equal_i(GIT_ENOTFOUND, error); + } + + git_note_free(note); + git_commit_free(branch_commit); + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); +} + +void test_rebase_merge__copy_notes_off_by_default(void) +{ + test_copy_note(NULL, 0); +} + +void test_rebase_merge__copy_notes_specified_in_options(void) +{ + git_rebase_options opts = GIT_REBASE_OPTIONS_INIT; + opts.rewrite_notes_ref = "refs/notes/test"; + + test_copy_note(&opts, 1); +} + +void test_rebase_merge__copy_notes_specified_in_config(void) +{ + git_config *config; + + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_set_string(config, + "notes.rewriteRef", "refs/notes/test")); + + test_copy_note(NULL, 1); +} + +void test_rebase_merge__copy_notes_disabled_in_config(void) +{ + git_config *config; + + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_set_bool(config, "notes.rewrite.rebase", 0)); + cl_git_pass(git_config_set_string(config, + "notes.rewriteRef", "refs/notes/test")); + + test_copy_note(NULL, 0); +} + From 18b439b9beee050de0dbf2f4649609764a69fb3c Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 23 Aug 2014 18:19:34 -0500 Subject: [PATCH 13/21] git_rebase_next: provide info about the operation --- include/git2/rebase.h | 74 +++++++++++++++++++++++++++++++++++++++---- src/rebase.c | 11 +++++-- tests/rebase/merge.c | 51 +++++++++++++++++++---------- 3 files changed, 111 insertions(+), 25 deletions(-) diff --git a/include/git2/rebase.h b/include/git2/rebase.h index d9cf2318e..3b4f44709 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -39,9 +39,67 @@ typedef struct { const char *rewrite_notes_ref; } git_rebase_options; +/** Type of rebase operation in-progress after calling `git_rebase_next`. */ +typedef enum { + /** + * The given commit is to be cherry-picked. The client should commit + * the changes and continue if there are no conflicts. + */ + GIT_REBASE_OPERATION_PICK = 0, + + /** + * The given commit is to be cherry-picked, but the client should prompt + * the user to provide an updated commit message. + */ + GIT_REBASE_OPERATION_REWORD, + + /** + * The given commit is to be cherry-picked, but the client should stop + * to allow the user to edit the changes before committing them. + */ + GIT_REBASE_OPERATION_EDIT, + + /** + * The given commit is to be squashed into the previous commit. The + * commit message will be merged with the previous message. + */ + GIT_REBASE_OPERATION_SQUASH, + + /** + * The given commit is to be squashed into the previous commit. The + * commit message from this commit will be discarded. + */ + GIT_REBASE_OPERATION_FIXUP, + + /** + * No commit will be cherry-picked. The client should run the given + * command and (if successful) continue. + */ + GIT_REBASE_OPERATION_EXEC, +} git_rebase_operation_t; + #define GIT_REBASE_OPTIONS_VERSION 1 #define GIT_REBASE_OPTIONS_INIT {GIT_REBASE_OPTIONS_VERSION} +typedef struct { + /** The type of rebase operation. */ + unsigned int type; + + union { + /** + * The commit ID being cherry-picked. This will be populated for + * all operations except those of type `GIT_REBASE_OPERATION_EXEC`. + */ + git_oid id; + + /** + * The executable the user has requested be run. This will only + * be populated for operations of type `GIT_REBASE_OPERATION_EXEC`. + */ + const char *exec; + }; +} git_rebase_operation; + /** * Initializes a `git_rebase_options` with default values. Equivalent to * creating an instance with GIT_REBASE_OPTIONS_INIT. @@ -78,15 +136,19 @@ GIT_EXTERN(int) git_rebase( const git_rebase_options *opts); /** - * Applies the next patch, updating the index and working directory with the - * changes. If there are conflicts, you will need to address those before - * committing the changes. + * Performs the next rebase operation and returns the information about it. + * If the operation is one that applies a patch (which is any operation except + * GIT_REBASE_OPERATION_EXEC) then the patch will be applied and the index and + * working directory will be updated with the changes. If there are conflicts, + * you will need to address those before committing the changes. * + * @param out The rebase operation that is to be performed next * @param repo The repository with a rebase in progress * @param checkout_opts Options to specify how the patch should be checked out * @return Zero on success; -1 on failure. */ GIT_EXTERN(int) git_rebase_next( + git_rebase_operation *operation, git_repository *repo, git_checkout_options *checkout_opts); @@ -94,7 +156,7 @@ GIT_EXTERN(int) git_rebase_next( * Commits the current patch. You must have resolved any conflicts that * were introduced during the patch application from the `git_rebase_next` * invocation. - * + * * @param id Pointer in which to store the OID of the newly created commit * @param repo The repository with the in-progress rebase * @param author The author of the updated commit, or NULL to keep the @@ -105,8 +167,8 @@ GIT_EXTERN(int) git_rebase_next( * this should also be NULL, and the encoding from the original * commit will be maintained. If message is specified, this may be * NULL to indicate that "UTF-8" is to be used. - * @param message The message for this commit, or NULL to keep the message - * from the original commit + * @param message The message for this commit, or NULL to use the message + * from the original commit. * @return Zero on success, GIT_EUNMERGED if there are unmerged changes in * the index, GIT_EAPPLIED if the current commit has already * been applied to the upstream and there is nothing to commit, diff --git a/src/rebase.c b/src/rebase.c index 3384a14f2..c6bbfbfb8 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -624,6 +624,7 @@ static int normalize_checkout_opts( } static int rebase_next_merge( + git_rebase_operation *out, git_repository *repo, git_rebase_state *state, git_checkout_options *given_checkout_opts) @@ -678,6 +679,9 @@ static int rebase_next_merge( (error = git_checkout_index(repo, index, &checkout_opts)) < 0) goto done; + out->type = GIT_REBASE_OPERATION_PICK; + memcpy(&out->id, ¤t_id, sizeof(git_oid)); + done: git_index_free(index); git_tree_free(current_tree); @@ -691,20 +695,23 @@ done: } int git_rebase_next( + git_rebase_operation *out, git_repository *repo, git_checkout_options *checkout_opts) { git_rebase_state state = GIT_REBASE_STATE_INIT; int error; - assert(repo); + assert(out && repo); + + memset(out, 0, sizeof(git_rebase_operation)); if ((error = rebase_state(&state, repo)) < 0) return -1; switch (state.type) { case GIT_REBASE_TYPE_MERGE: - error = rebase_next_merge(repo, &state, checkout_opts); + error = rebase_next_merge(out, repo, &state, checkout_opts); break; default: abort(); diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index fddab8397..a3bb711b2 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -26,10 +26,11 @@ void test_rebase_merge__next(void) { git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; + git_rebase_operation rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_status_list *status_list; const git_status_entry *status_entry; - git_oid file1_id; + git_oid pick_id, file1_id; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; @@ -41,8 +42,12 @@ void test_rebase_merge__next(void) cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); + git_oid_fromstr(&pick_id, "da9c51a23d02d931a486f45ad18cda05cf5d2b94"); + + cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation.type); + cl_assert_equal_oid(&pick_id, &rebase_operation.id); cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n", 41, "rebase/.git/rebase-merge/current"); cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum"); @@ -66,9 +71,11 @@ void test_rebase_merge__next_with_conflicts(void) { git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; + git_rebase_operation rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_status_list *status_list; const git_status_entry *status_entry; + git_oid pick_id; const char *expected_merge = "ASPARAGUS SOUP.\n" @@ -100,8 +107,12 @@ void test_rebase_merge__next_with_conflicts(void) cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); + git_oid_fromstr(&pick_id, "33f915f9e4dbd9f4b24430e48731a59b45b15500"); + + cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation.type); + cl_assert_equal_oid(&pick_id, &rebase_operation.id); cl_assert_equal_file("33f915f9e4dbd9f4b24430e48731a59b45b15500\n", 41, "rebase/.git/rebase-merge/current"); cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum"); @@ -124,6 +135,7 @@ void test_rebase_merge__next_stops_with_iterover(void) { git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; + git_rebase_operation rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; int error; @@ -138,27 +150,27 @@ void test_rebase_merge__next_stops_with_iterover(void) cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); - cl_git_fail(error = git_rebase_next(repo, &checkout_opts)); + cl_git_fail(error = git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_assert_equal_i(GIT_ITEROVER, error); cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); @@ -174,6 +186,7 @@ void test_rebase_merge__commit(void) { git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; + git_rebase_operation rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id, tree_id, parent_id; git_signature *author; @@ -191,7 +204,7 @@ void test_rebase_merge__commit(void) cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); @@ -233,6 +246,7 @@ void test_rebase_merge__commit_updates_rewritten(void) { git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; + git_rebase_operation rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; @@ -246,11 +260,11 @@ void test_rebase_merge__commit_updates_rewritten(void) cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); @@ -269,6 +283,7 @@ void test_rebase_merge__commit_drops_already_applied(void) { git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; + git_rebase_operation rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; int error; @@ -283,13 +298,13 @@ void test_rebase_merge__commit_drops_already_applied(void) cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_fail(error = git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); cl_assert_equal_i(GIT_EAPPLIED, error); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); @@ -307,6 +322,7 @@ void test_rebase_merge__finish(void) { git_reference *branch_ref, *upstream_ref, *head_ref; git_merge_head *branch_head, *upstream_head; + git_rebase_operation rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; git_reflog *reflog; @@ -323,11 +339,11 @@ void test_rebase_merge__finish(void) cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); - cl_git_fail(error = git_rebase_next(repo, &checkout_opts)); + cl_git_fail(error = git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_assert_equal_i(GIT_ITEROVER, error); cl_git_pass(git_rebase_finish(repo, signature, NULL)); @@ -367,6 +383,7 @@ static void test_copy_note( git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_commit *branch_commit; + git_rebase_operation rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid note_id, commit_id; git_note *note = NULL; @@ -391,7 +408,7 @@ static void test_copy_note( cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, opts)); - cl_git_pass(git_rebase_next(repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, NULL, NULL)); From b6b636a7fad2d87067df4df47f37b57467ad6bb6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 25 Aug 2014 13:29:50 -0500 Subject: [PATCH 14/21] rebase: init/open a git_rebase object --- include/git2/rebase.h | 43 +++- include/git2/types.h | 2 + src/rebase.c | 510 +++++++++++++++++++++++------------------- tests/rebase/abort.c | 17 +- tests/rebase/merge.c | 92 ++++---- tests/rebase/setup.c | 29 ++- 6 files changed, 398 insertions(+), 295 deletions(-) diff --git a/include/git2/rebase.h b/include/git2/rebase.h index 3b4f44709..3d3c1c78c 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -114,9 +114,12 @@ GIT_EXTERN(int) git_rebase_init_options( unsigned int version); /** - * Sets up a rebase operation to rebase the changes in ours relative to - * upstream onto another branch. + * Initializes a rebase operation to rebase the changes in `ours` + * relative to `upstream` onto another branch. To begin the rebase + * process, call `git_rebase_next`. When you have finished with this + * object, call `git_rebase_free`. * + * @param out Pointer to store the rebase object * @param repo The repository to perform the rebase * @param branch The terminal commit to rebase * @param upstream The commit to begin rebasing from, or NULL to rebase all @@ -127,7 +130,8 @@ GIT_EXTERN(int) git_rebase_init_options( * @param opts Options to specify how rebase is performed * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_rebase( +GIT_EXTERN(int) git_rebase_init( + git_rebase **out, git_repository *repo, const git_merge_head *branch, const git_merge_head *upstream, @@ -135,6 +139,16 @@ GIT_EXTERN(int) git_rebase( const git_signature *signature, const git_rebase_options *opts); +/** + * Opens an existing rebase that was previously started by either an + * invocation of `git_rebase_init` or by another client. + * + * @param out Pointer to store the rebase object + * @param reop The repository that has a rebase in-progress + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_rebase_open(git_rebase **out, git_repository *repo); + /** * Performs the next rebase operation and returns the information about it. * If the operation is one that applies a patch (which is any operation except @@ -143,13 +157,13 @@ GIT_EXTERN(int) git_rebase( * you will need to address those before committing the changes. * * @param out The rebase operation that is to be performed next - * @param repo The repository with a rebase in progress + * @param repo The rebase in progress * @param checkout_opts Options to specify how the patch should be checked out * @return Zero on success; -1 on failure. */ GIT_EXTERN(int) git_rebase_next( git_rebase_operation *operation, - git_repository *repo, + git_rebase *rebase, git_checkout_options *checkout_opts); /** @@ -158,7 +172,7 @@ GIT_EXTERN(int) git_rebase_next( * invocation. * * @param id Pointer in which to store the OID of the newly created commit - * @param repo The repository with the in-progress rebase + * @param repo The rebase that is in-progress * @param author The author of the updated commit, or NULL to keep the * author from the original commit * @param committer The committer of the rebase @@ -176,7 +190,7 @@ GIT_EXTERN(int) git_rebase_next( */ GIT_EXTERN(int) git_rebase_commit( git_oid *id, - git_repository *repo, + git_rebase *rebase, const git_signature *author, const git_signature *committer, const char *message_encoding, @@ -186,29 +200,36 @@ GIT_EXTERN(int) git_rebase_commit( * Aborts a rebase that is currently in progress, resetting the repository * and working directory to their state before rebase began. * - * @param repo The repository with the in-progress rebase + * @param rebase The rebase that is in-progress * @param signature The identity that is aborting the rebase * @return Zero on success; GIT_ENOTFOUND if a rebase is not in progress, * -1 on other errors. */ GIT_EXTERN(int) git_rebase_abort( - git_repository *repo, + git_rebase *rebase, const git_signature *signature); /** * Finishes a rebase that is currently in progress once all patches have * been applied. * - * @param repo The repository with the in-progress rebase + * @param rebase The rebase that is in-progress * @param signature The identity that is finishing the rebase * @param opts Options to specify how rebase is finished * @param Zero on success; -1 on error */ GIT_EXTERN(int) git_rebase_finish( - git_repository *repo, + git_rebase *rebase, const git_signature *signature, const git_rebase_options *opts); +/** + * Frees the `git_rebase` object. + * + * @param rebase The rebase that is in-progress + */ +GIT_EXTERN(void) git_rebase_free(git_rebase *rebase); + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/types.h b/include/git2/types.h index 16933976e..416140716 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -183,6 +183,8 @@ typedef struct git_merge_result git_merge_result; /** Representation of a status collection */ typedef struct git_status_list git_status_list; +/** Representation of a rebase */ +typedef struct git_rebase git_rebase; /** Basic type of any Git reference. */ typedef enum { diff --git a/src/rebase.c b/src/rebase.c index c6bbfbfb8..17e34e191 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -51,7 +51,7 @@ typedef enum { GIT_REBASE_TYPE_INTERACTIVE = 3, } git_rebase_type_t; -struct git_rebase_state_merge { +struct git_rebase_merge { int32_t msgnum; int32_t end; char *onto_name; @@ -59,21 +59,26 @@ struct git_rebase_state_merge { git_commit *current; }; -typedef struct { +struct git_rebase { + git_repository *repo; + git_rebase_type_t type; char *state_path; - int head_detached : 1; + int head_detached : 1, + quiet : 1; char *orig_head_name; git_oid orig_head_id; git_oid onto_id; + git_array_t(git_rebase_operation) operations; + union { - struct git_rebase_state_merge merge; + struct git_rebase_merge merge; }; -} git_rebase_state; +}; #define GIT_REBASE_STATE_INIT {0} @@ -113,16 +118,14 @@ done: return 0; } -static int rebase_state_merge(git_rebase_state *state, git_repository *repo) +static int rebase_open_merge(git_rebase *rebase) { git_buf path = GIT_BUF_INIT, msgnum = GIT_BUF_INIT, end = GIT_BUF_INIT, onto_name = GIT_BUF_INIT, current = GIT_BUF_INIT; git_oid current_id; int state_path_len, error; - GIT_UNUSED(repo); - - if ((error = git_buf_puts(&path, state->state_path)) < 0) + if ((error = git_buf_puts(&path, rebase->state_path)) < 0) goto done; state_path_len = git_buf_len(&path); @@ -134,7 +137,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) git_buf_rtrim(&end); - if ((error = git__strtol32(&state->merge.end, end.ptr, NULL, 10)) < 0) + if ((error = git__strtol32(&rebase->merge.end, end.ptr, NULL, 10)) < 0) goto done; /* Read 'onto_name' */ @@ -146,7 +149,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) git_buf_rtrim(&onto_name); - state->merge.onto_name = git_buf_detach(&onto_name); + rebase->merge.onto_name = git_buf_detach(&onto_name); /* Read 'msgnum' if it exists, otherwise let msgnum = 0 */ git_buf_truncate(&path, state_path_len); @@ -160,7 +163,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) git_buf_rtrim(&msgnum); - if ((error = git__strtol32(&state->merge.msgnum, msgnum.ptr, NULL, 10)) < 0) + if ((error = git__strtol32(&rebase->merge.msgnum, msgnum.ptr, NULL, 10)) < 0) goto done; } @@ -178,7 +181,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) git_buf_rtrim(¤t); if ((error = git_oid_fromstr(¤t_id, current.ptr)) < 0 || - (error = git_commit_lookup(&state->merge.current, repo, ¤t_id)) < 0) + (error = git_commit_lookup(&rebase->merge.current, rebase->repo, ¤t_id)) < 0) goto done; } @@ -192,23 +195,29 @@ done: return error; } -static int rebase_state(git_rebase_state *state, git_repository *repo) +int git_rebase_open(git_rebase **out, git_repository *repo) { + git_rebase *rebase; git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT, orig_head_id = GIT_BUF_INIT, onto_id = GIT_BUF_INIT; int state_path_len, error; - memset(state, 0x0, sizeof(git_rebase_state)); + assert(repo); - if ((error = rebase_state_type(&state->type, &state->state_path, repo)) < 0) + rebase = git__calloc(1, sizeof(git_rebase)); + GITERR_CHECK_ALLOC(rebase); + + rebase->repo = repo; + + if ((error = rebase_state_type(&rebase->type, &rebase->state_path, repo)) < 0) goto done; - if (state->type == GIT_REBASE_TYPE_NONE) { + if (rebase->type == GIT_REBASE_TYPE_NONE) { giterr_set(GITERR_REBASE, "There is no rebase in progress"); return GIT_ENOTFOUND; } - if ((error = git_buf_puts(&path, state->state_path)) < 0) + if ((error = git_buf_puts(&path, rebase->state_path)) < 0) goto done; state_path_len = git_buf_len(&path); @@ -220,7 +229,7 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) git_buf_rtrim(&orig_head_name); if (strcmp(ORIG_DETACHED_HEAD, orig_head_name.ptr) == 0) - state->head_detached = 1; + rebase->head_detached = 1; git_buf_truncate(&path, state_path_len); @@ -240,7 +249,7 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) git_buf_rtrim(&orig_head_id); - if ((error = git_oid_fromstr(&state->orig_head_id, orig_head_id.ptr)) < 0) + if ((error = git_oid_fromstr(&rebase->orig_head_id, orig_head_id.ptr)) < 0) goto done; git_buf_truncate(&path, state_path_len); @@ -251,19 +260,19 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) git_buf_rtrim(&onto_id); - if ((error = git_oid_fromstr(&state->onto_id, onto_id.ptr)) < 0) + if ((error = git_oid_fromstr(&rebase->onto_id, onto_id.ptr)) < 0) goto done; - if (!state->head_detached) - state->orig_head_name = git_buf_detach(&orig_head_name); + if (!rebase->head_detached) + rebase->orig_head_name = git_buf_detach(&orig_head_name); - switch (state->type) { + switch (rebase->type) { case GIT_REBASE_TYPE_INTERACTIVE: giterr_set(GITERR_REBASE, "Interactive rebase is not supported"); error = -1; break; case GIT_REBASE_TYPE_MERGE: - error = rebase_state_merge(state, repo); + error = rebase_open_merge(rebase); break; case GIT_REBASE_TYPE_APPLY: giterr_set(GITERR_REBASE, "Patch application rebase is not supported"); @@ -274,6 +283,11 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) } done: + if (error == 0) + *out = rebase; + else + git_rebase_free(rebase); + git_buf_free(&path); git_buf_free(&orig_head_name); git_buf_free(&orig_head_id); @@ -281,28 +295,14 @@ done: return error; } -static void rebase_state_free(git_rebase_state *state) +static int rebase_cleanup(git_rebase *rebase) { - if (state == NULL) - return; - - if (state->type == GIT_REBASE_TYPE_MERGE) { - git__free(state->merge.onto_name); - git_commit_free(state->merge.current); - } - - git__free(state->orig_head_name); - git__free(state->state_path); -} - -static int rebase_cleanup(git_rebase_state *state) -{ - return git_path_isdir(state->state_path) ? - git_futils_rmdir_r(state->state_path, NULL, GIT_RMDIR_REMOVE_FILES) : + return git_path_isdir(rebase->state_path) ? + git_futils_rmdir_r(rebase->state_path, NULL, GIT_RMDIR_REMOVE_FILES) : 0; } -static int rebase_setupfile(git_repository *repo, const char *filename, int flags, const char *fmt, ...) +static int rebase_setupfile(git_rebase *rebase, const char *filename, int flags, const char *fmt, ...) { git_buf path = GIT_BUF_INIT, contents = GIT_BUF_INIT; @@ -313,8 +313,7 @@ static int rebase_setupfile(git_repository *repo, const char *filename, int flag git_buf_vprintf(&contents, fmt, ap); va_end(ap); - if ((error = git_buf_joinpath(&path, repo->path_repository, REBASE_MERGE_DIR)) == 0 && - (error = git_buf_joinpath(&path, path.ptr, filename)) == 0) + if ((error = git_buf_joinpath(&path, rebase->state_path, filename)) == 0) error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE); git_buf_free(&path); @@ -323,9 +322,6 @@ static int rebase_setupfile(git_repository *repo, const char *filename, int flag return error; } -/* TODO: git.git actually uses the literal argv here, this is an attempt - * to emulate that. - */ static const char *rebase_onto_name(const git_merge_head *onto) { if (onto->ref_name && git__strncmp(onto->ref_name, "refs/heads/", 11) == 0) @@ -336,108 +332,56 @@ static const char *rebase_onto_name(const git_merge_head *onto) return onto->oid_str; } -static int rebase_setup_merge( - git_repository *repo, - const git_merge_head *branch, - const git_merge_head *upstream, - const git_merge_head *onto, - const git_rebase_options *opts) +static int rebase_setupfiles_merge(git_rebase *rebase) { - git_revwalk *revwalk = NULL; - git_commit *commit; git_buf commit_filename = GIT_BUF_INIT; - git_oid id; char id_str[GIT_OID_HEXSZ]; - bool merge; - int commit_cnt = 0, error; + git_rebase_operation *operation; + size_t i; + int error = 0; - GIT_UNUSED(opts); - - if (!upstream) - upstream = onto; - - if ((error = git_revwalk_new(&revwalk, repo)) < 0 || - (error = git_revwalk_push(revwalk, &branch->oid)) < 0 || - (error = git_revwalk_hide(revwalk, &upstream->oid)) < 0) + if ((error = rebase_setupfile(rebase, END_FILE, -1, "%d\n", git_array_size(rebase->operations))) < 0 || + (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->merge.onto_name)) < 0) goto done; - git_revwalk_sorting(revwalk, GIT_SORT_REVERSE | GIT_SORT_TIME); - - while ((error = git_revwalk_next(&id, revwalk)) == 0) { - if ((error = git_commit_lookup(&commit, repo, &id)) < 0) - goto done; - - merge = (git_commit_parentcount(commit) > 1); - git_commit_free(commit); - - if (merge) - continue; - - commit_cnt++; + for (i = 0; i < git_array_size(rebase->operations); i++) { + operation = git_array_get(rebase->operations, i); git_buf_clear(&commit_filename); - git_buf_printf(&commit_filename, CMT_FILE_FMT, commit_cnt); + git_buf_printf(&commit_filename, CMT_FILE_FMT, i+1); - git_oid_fmt(id_str, &id); - if ((error = rebase_setupfile(repo, commit_filename.ptr, -1, + git_oid_fmt(id_str, &operation->id); + + if ((error = rebase_setupfile(rebase, commit_filename.ptr, -1, "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0) goto done; } - if (error != GIT_ITEROVER || - (error = rebase_setupfile(repo, END_FILE, -1, "%d\n", commit_cnt)) < 0) - goto done; - - error = rebase_setupfile(repo, ONTO_NAME_FILE, -1, "%s\n", - rebase_onto_name(onto)); - done: - git_revwalk_free(revwalk); git_buf_free(&commit_filename); - return error; } -static int rebase_setup( - git_repository *repo, - const git_merge_head *branch, - const git_merge_head *upstream, - const git_merge_head *onto, - const git_rebase_options *opts) +static int rebase_setupfiles(git_rebase *rebase) { - git_buf state_path = GIT_BUF_INIT; - const char *orig_head_name; - int error; + char onto[GIT_OID_HEXSZ], orig_head[GIT_OID_HEXSZ]; - if (git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR) < 0) + git_oid_fmt(onto, &rebase->onto_id); + git_oid_fmt(orig_head, &rebase->orig_head_id); + + if (p_mkdir(rebase->state_path, REBASE_DIR_MODE) < 0) { + giterr_set(GITERR_OS, "Failed to create rebase directory '%s'", rebase->state_path); return -1; - - if ((error = p_mkdir(state_path.ptr, REBASE_DIR_MODE)) < 0) { - giterr_set(GITERR_OS, "Failed to create rebase directory '%s'", - state_path.ptr); - goto done; } - if ((error = git_repository__set_orig_head(repo, &branch->oid)) < 0) - goto done; + if (git_repository__set_orig_head(rebase->repo, &rebase->orig_head_id) < 0 || + rebase_setupfile(rebase, HEAD_NAME_FILE, -1, "%s\n", rebase->orig_head_name) < 0 || + rebase_setupfile(rebase, ONTO_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 || + rebase_setupfile(rebase, ORIG_HEAD_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 || + rebase_setupfile(rebase, QUIET_FILE, -1, rebase->quiet ? "t\n" : "\n") < 0) + return -1; - orig_head_name = branch->ref_name ? branch->ref_name : ORIG_DETACHED_HEAD; - - if ((error = rebase_setupfile(repo, HEAD_NAME_FILE, -1, "%s\n", orig_head_name)) < 0 || - (error = rebase_setupfile(repo, ONTO_FILE, -1, "%s\n", onto->oid_str)) < 0 || - (error = rebase_setupfile(repo, ORIG_HEAD_FILE, -1, "%s\n", branch->oid_str)) < 0 || - (error = rebase_setupfile(repo, QUIET_FILE, -1, opts->quiet ? "t\n" : "\n")) < 0) - goto done; - - error = rebase_setup_merge(repo, branch, upstream, onto, opts); - -done: - if (error < 0) - git_repository__cleanup_files(repo, (const char **)&state_path.ptr, 1); - - git_buf_free(&state_path); - - return error; + return rebase_setupfiles_merge(rebase); } int git_rebase_init_options(git_rebase_options *opts, unsigned int version) @@ -542,7 +486,104 @@ done: return error; } -int git_rebase( +static int rebase_init_operations( + git_rebase *rebase, + git_repository *repo, + const git_merge_head *branch, + const git_merge_head *upstream, + const git_merge_head *onto) +{ + git_revwalk *revwalk = NULL; + git_commit *commit; + git_oid id; + bool merge; + git_rebase_operation *operation; + int error; + + if (!upstream) + upstream = onto; + + if ((error = git_revwalk_new(&revwalk, rebase->repo)) < 0 || + (error = git_revwalk_push(revwalk, &branch->oid)) < 0 || + (error = git_revwalk_hide(revwalk, &upstream->oid)) < 0) + goto done; + + git_revwalk_sorting(revwalk, GIT_SORT_REVERSE | GIT_SORT_TIME); + + while ((error = git_revwalk_next(&id, revwalk)) == 0) { + if ((error = git_commit_lookup(&commit, repo, &id)) < 0) + goto done; + + merge = (git_commit_parentcount(commit) > 1); + git_commit_free(commit); + + if (merge) + continue; + + operation = git_array_alloc(rebase->operations); + operation->type = GIT_REBASE_OPERATION_PICK; + git_oid_cpy(&operation->id, &id); + } + + error = 0; + +done: + git_revwalk_free(revwalk); + return error; +} + +static int rebase_init_merge( + git_rebase *rebase, + git_repository *repo, + const git_merge_head *branch, + const git_merge_head *upstream, + const git_merge_head *onto) +{ + if (rebase_init_operations(rebase, repo, branch, upstream, onto) < 0) + return -1; + + rebase->merge.end = git_array_size(rebase->operations); + rebase->merge.onto_name = git__strdup(rebase_onto_name(onto)); + + GITERR_CHECK_ALLOC(rebase->merge.onto_name); + + return 0; +} + +static int rebase_init( + git_rebase *rebase, + git_repository *repo, + const git_merge_head *branch, + const git_merge_head *upstream, + const git_merge_head *onto, + const git_rebase_options *opts) +{ + git_buf state_path = GIT_BUF_INIT; + int error; + + git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR); + + rebase->repo = repo; + rebase->type = GIT_REBASE_TYPE_MERGE; + rebase->state_path = git_buf_detach(&state_path); + rebase->orig_head_name = git__strdup(branch->ref_name ? branch->ref_name : ORIG_DETACHED_HEAD); + rebase->quiet = opts->quiet; + + git_oid_cpy(&rebase->orig_head_id, &branch->oid); + git_oid_cpy(&rebase->onto_id, &onto->oid); + + if (!rebase->orig_head_name || !rebase->state_path) + return -1; + + error = rebase_init_merge(rebase, repo, branch, upstream, onto); + + git_buf_free(&state_path); + + return error; +} + +int git_rebase_init( + git_rebase **out, git_repository *repo, const git_merge_head *branch, const git_merge_head *upstream, @@ -550,6 +591,7 @@ int git_rebase( const git_signature *signature, const git_rebase_options *given_opts) { + git_rebase *rebase = NULL; git_rebase_options opts; git_reference *head_ref = NULL; git_buf reflog = GIT_BUF_INIT; @@ -558,46 +600,55 @@ int git_rebase( assert(repo && branch && (upstream || onto)); + *out = NULL; + GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options"); + if (!onto) + onto = upstream; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + if ((error = rebase_normalize_opts(repo, &opts, given_opts)) < 0 || (error = git_repository__ensure_not_bare(repo, "rebase")) < 0 || (error = rebase_ensure_not_in_progress(repo)) < 0 || (error = rebase_ensure_not_dirty(repo)) < 0) - goto done; + return error; - if (!onto) - onto = upstream; + rebase = git__calloc(1, sizeof(git_rebase)); + GITERR_CHECK_ALLOC(rebase); - if ((error = rebase_setup(repo, branch, upstream, onto, &opts)) < 0) - goto done; - - if ((error = git_buf_printf(&reflog, + if ((error = rebase_init(rebase, repo, branch, upstream, onto, &opts)) < 0 || + (error = rebase_setupfiles(rebase)) < 0 || + (error = git_buf_printf(&reflog, "rebase: checkout %s", rebase_onto_name(onto))) < 0 || (error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE, - &onto->oid, 1, signature, reflog.ptr)) < 0) + &onto->oid, 1, signature, reflog.ptr)) < 0 || + (error = git_checkout_head(repo, &checkout_opts)) < 0) goto done; - checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; - error = git_checkout_head(repo, &checkout_opts); + *out = rebase; done: + if (error < 0) { + rebase_cleanup(rebase); + git_rebase_free(rebase); + } + git_reference_free(head_ref); git_buf_free(&reflog); rebase_opts_free(&opts); + return error; } static int normalize_checkout_opts( - git_repository *repo, + git_rebase *rebase, git_checkout_options *checkout_opts, - const git_checkout_options *given_checkout_opts, - const git_rebase_state *state) + const git_checkout_options *given_checkout_opts) { int error = 0; - GIT_UNUSED(repo); - if (given_checkout_opts != NULL) memcpy(checkout_opts, given_checkout_opts, sizeof(git_checkout_options)); else { @@ -610,12 +661,12 @@ static int normalize_checkout_opts( if (!checkout_opts->ancestor_label) checkout_opts->ancestor_label = "ancestor"; - if (state->type == GIT_REBASE_TYPE_MERGE) { + if (rebase->type == GIT_REBASE_TYPE_MERGE) { if (!checkout_opts->our_label) - checkout_opts->our_label = state->merge.onto_name; + checkout_opts->our_label = rebase->merge.onto_name; if (!checkout_opts->their_label) - checkout_opts->their_label = git_commit_summary(state->merge.current); + checkout_opts->their_label = git_commit_summary(rebase->merge.current); } else { abort(); } @@ -625,8 +676,7 @@ static int normalize_checkout_opts( static int rebase_next_merge( git_rebase_operation *out, - git_repository *repo, - git_rebase_state *state, + git_rebase *rebase, git_checkout_options *given_checkout_opts) { git_buf path = GIT_BUF_INIT, current = GIT_BUF_INIT; @@ -638,45 +688,45 @@ static int rebase_next_merge( unsigned int parent_count; int error; - if (state->merge.msgnum == state->merge.end) + if (rebase->merge.msgnum == rebase->merge.end) return GIT_ITEROVER; - state->merge.msgnum++; + rebase->merge.msgnum++; - if ((error = git_buf_joinpath(&path, state->state_path, "cmt.")) < 0 || - (error = git_buf_printf(&path, "%d", state->merge.msgnum)) < 0 || + if ((error = git_buf_joinpath(&path, rebase->state_path, "cmt.")) < 0 || + (error = git_buf_printf(&path, "%d", rebase->merge.msgnum)) < 0 || (error = git_futils_readbuffer(¤t, path.ptr)) < 0) goto done; git_buf_rtrim(¤t); - if (state->merge.current) - git_commit_free(state->merge.current); + if (rebase->merge.current) + git_commit_free(rebase->merge.current); if ((error = git_oid_fromstr(¤t_id, current.ptr)) < 0 || - (error = git_commit_lookup(&state->merge.current, repo, ¤t_id)) < 0 || - (error = git_commit_tree(¤t_tree, state->merge.current)) < 0 || - (error = git_repository_head_tree(&head_tree, repo)) < 0) + (error = git_commit_lookup(&rebase->merge.current, rebase->repo, ¤t_id)) < 0 || + (error = git_commit_tree(¤t_tree, rebase->merge.current)) < 0 || + (error = git_repository_head_tree(&head_tree, rebase->repo)) < 0) goto done; - if ((parent_count = git_commit_parentcount(state->merge.current)) > 1) { + if ((parent_count = git_commit_parentcount(rebase->merge.current)) > 1) { giterr_set(GITERR_REBASE, "Cannot rebase a merge commit"); error = -1; goto done; } else if (parent_count) { - if ((error = git_commit_parent(&parent_commit, state->merge.current, 0)) < 0 || + if ((error = git_commit_parent(&parent_commit, rebase->merge.current, 0)) < 0 || (error = git_commit_tree(&parent_tree, parent_commit)) < 0) goto done; } - if ((error = rebase_setupfile(repo, MSGNUM_FILE, -1, "%d\n", state->merge.msgnum)) < 0 || - (error = rebase_setupfile(repo, CURRENT_FILE, -1, "%s\n", current.ptr)) < 0) + if ((error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%d\n", rebase->merge.msgnum)) < 0 || + (error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%s\n", current.ptr)) < 0) goto done; - if ((error = normalize_checkout_opts(repo, &checkout_opts, given_checkout_opts, state)) < 0 || - (error = git_merge_trees(&index, repo, parent_tree, head_tree, current_tree, NULL)) < 0 || - (error = git_merge__check_result(repo, index)) < 0 || - (error = git_checkout_index(repo, index, &checkout_opts)) < 0) + if ((error = normalize_checkout_opts(rebase, &checkout_opts, given_checkout_opts)) < 0 || + (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, NULL)) < 0 || + (error = git_merge__check_result(rebase->repo, index)) < 0 || + (error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0) goto done; out->type = GIT_REBASE_OPERATION_PICK; @@ -696,35 +746,29 @@ done: int git_rebase_next( git_rebase_operation *out, - git_repository *repo, + git_rebase *rebase, git_checkout_options *checkout_opts) { - git_rebase_state state = GIT_REBASE_STATE_INIT; int error; - assert(out && repo); + assert(out && rebase); memset(out, 0, sizeof(git_rebase_operation)); - if ((error = rebase_state(&state, repo)) < 0) - return -1; - - switch (state.type) { + switch (rebase->type) { case GIT_REBASE_TYPE_MERGE: - error = rebase_next_merge(out, repo, &state, checkout_opts); + error = rebase_next_merge(out, rebase, checkout_opts); break; default: abort(); } - rebase_state_free(&state); return error; } static int rebase_commit_merge( git_oid *commit_id, - git_repository *repo, - git_rebase_state *state, + git_rebase *rebase, const git_signature *author, const git_signature *committer, const char *message_encoding, @@ -740,13 +784,13 @@ static int rebase_commit_merge( char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ]; int error; - if (!state->merge.msgnum || !state->merge.current) { + if (!rebase->merge.msgnum || !rebase->merge.current) { giterr_set(GITERR_REBASE, "No rebase-merge state files exist"); error = -1; goto done; } - if ((error = git_repository_index(&index, repo)) < 0) + if ((error = git_repository_index(&index, rebase->repo)) < 0) goto done; if (git_index_has_conflicts(index)) { @@ -755,10 +799,10 @@ static int rebase_commit_merge( goto done; } - if ((error = git_repository_head(&head, repo)) < 0 || + if ((error = git_repository_head(&head, rebase->repo)) < 0 || (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 || (error = git_commit_tree(&head_tree, head_commit)) < 0 || - (error = git_diff_tree_to_index(&diff, repo, head_tree, index, NULL)) < 0) + (error = git_diff_tree_to_index(&diff, rebase->repo, head_tree, index, NULL)) < 0) goto done; if (git_diff_num_deltas(diff) == 0) { @@ -768,29 +812,29 @@ static int rebase_commit_merge( } if ((error = git_index_write_tree(&tree_id, index)) < 0 || - (error = git_tree_lookup(&tree, repo, &tree_id)) < 0) + (error = git_tree_lookup(&tree, rebase->repo, &tree_id)) < 0) goto done; if (!author) - author = git_commit_author(state->merge.current); + author = git_commit_author(rebase->merge.current); if (!message) { - message_encoding = git_commit_message_encoding(state->merge.current); - message = git_commit_message(state->merge.current); + message_encoding = git_commit_message_encoding(rebase->merge.current); + message = git_commit_message(rebase->merge.current); } - if ((error = git_commit_create(commit_id, repo, NULL, author, + if ((error = git_commit_create(commit_id, rebase->repo, NULL, author, committer, message_encoding, message, tree, 1, (const git_commit **)&head_commit)) < 0 || - (error = git_commit_lookup(&commit, repo, commit_id)) < 0 || + (error = git_commit_lookup(&commit, rebase->repo, commit_id)) < 0 || (error = git_reference__update_for_commit( - repo, NULL, "HEAD", commit_id, committer, "rebase")) < 0) + rebase->repo, NULL, "HEAD", commit_id, committer, "rebase")) < 0) goto done; - git_oid_fmt(old_idstr, git_commit_id(state->merge.current)); + git_oid_fmt(old_idstr, git_commit_id(rebase->merge.current)); git_oid_fmt(new_idstr, commit_id); - error = rebase_setupfile(repo, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND, + error = rebase_setupfile(rebase, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND, "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr); done: @@ -808,74 +852,63 @@ done: int git_rebase_commit( git_oid *id, - git_repository *repo, + git_rebase *rebase, const git_signature *author, const git_signature *committer, const char *message_encoding, const char *message) { - git_rebase_state state = GIT_REBASE_STATE_INIT; int error; - assert(repo && committer); + assert(rebase && committer); - if ((error = rebase_state(&state, repo)) < 0) - goto done; - - switch (state.type) { + switch (rebase->type) { case GIT_REBASE_TYPE_MERGE: error = rebase_commit_merge( - id, repo, &state, author, committer, message_encoding, message); + id, rebase, author, committer, message_encoding, message); break; default: abort(); } -done: - rebase_state_free(&state); return error; } -int git_rebase_abort(git_repository *repo, const git_signature *signature) +int git_rebase_abort(git_rebase *rebase, const git_signature *signature) { - git_rebase_state state = GIT_REBASE_STATE_INIT; git_reference *orig_head_ref = NULL; git_commit *orig_head_commit = NULL; int error; - assert(repo && signature); + assert(rebase && signature); - if ((error = rebase_state(&state, repo)) < 0) - goto done; - - error = state.head_detached ? - git_reference_create(&orig_head_ref, repo, GIT_HEAD_FILE, - &state.orig_head_id, 1, signature, "rebase: aborting") : + error = rebase->head_detached ? + git_reference_create(&orig_head_ref, rebase->repo, GIT_HEAD_FILE, + &rebase->orig_head_id, 1, signature, "rebase: aborting") : git_reference_symbolic_create( - &orig_head_ref, repo, GIT_HEAD_FILE, state.orig_head_name, 1, + &orig_head_ref, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1, signature, "rebase: aborting"); if (error < 0) goto done; if ((error = git_commit_lookup( - &orig_head_commit, repo, &state.orig_head_id)) < 0 || - (error = git_reset(repo, (git_object *)orig_head_commit, + &orig_head_commit, rebase->repo, &rebase->orig_head_id)) < 0 || + (error = git_reset(rebase->repo, (git_object *)orig_head_commit, GIT_RESET_HARD, NULL, signature, NULL)) < 0) goto done; - error = rebase_cleanup(&state); + error = rebase_cleanup(rebase); done: git_commit_free(orig_head_commit); git_reference_free(orig_head_ref); - rebase_state_free(&state); return error; } static int rebase_copy_note( - git_repository *repo, + git_rebase *rebase, git_oid *from, git_oid *to, const git_signature *committer, @@ -885,7 +918,7 @@ static int rebase_copy_note( git_oid note_id; int error; - if ((error = git_note_read(¬e, repo, opts->rewrite_notes_ref, from)) < 0) { + if ((error = git_note_read(¬e, rebase->repo, opts->rewrite_notes_ref, from)) < 0) { if (error == GIT_ENOTFOUND) { giterr_clear(); error = 0; @@ -894,7 +927,7 @@ static int rebase_copy_note( goto done; } - error = git_note_create(¬e_id, repo, git_note_author(note), + error = git_note_create(¬e_id, rebase->repo, git_note_author(note), committer, opts->rewrite_notes_ref, to, git_note_message(note), 0); done: @@ -904,8 +937,7 @@ done: } static int rebase_copy_notes( - git_repository *repo, - git_rebase_state *state, + git_rebase *rebase, const git_signature *committer, const git_rebase_options *opts) { @@ -918,7 +950,7 @@ static int rebase_copy_notes( if (!opts->rewrite_notes_ref) goto done; - if ((error = git_buf_joinpath(&path, state->state_path, REWRITTEN_FILE)) < 0 || + if ((error = git_buf_joinpath(&path, rebase->state_path, REWRITTEN_FILE)) < 0 || (error = git_futils_readbuffer(&rewritten, path.ptr)) < 0) goto done; @@ -945,7 +977,7 @@ static int rebase_copy_notes( git_oid_fromstr(&to, tostr) < 0) goto on_error; - if ((error = rebase_copy_note(repo, &from, &to, committer, opts)) < 0) + if ((error = rebase_copy_note(rebase, &from, &to, committer, opts)) < 0) goto done; linenum++; @@ -965,43 +997,41 @@ done: } int git_rebase_finish( - git_repository *repo, + git_rebase *rebase, const git_signature *signature, const git_rebase_options *given_opts) { git_rebase_options opts; - git_rebase_state state = GIT_REBASE_STATE_INIT; git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL; git_commit *terminal_commit = NULL; git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT; char onto[GIT_OID_HEXSZ]; int error; - assert(repo); + assert(rebase); - if ((error = rebase_normalize_opts(repo, &opts, given_opts)) < 0 || - (error = rebase_state(&state, repo)) < 0) + if ((error = rebase_normalize_opts(rebase->repo, &opts, given_opts)) < 0) goto done; - git_oid_fmt(onto, &state.onto_id); + git_oid_fmt(onto, &rebase->onto_id); if ((error = git_buf_printf(&branch_msg, "rebase finished: %s onto %.*s", - state.orig_head_name, GIT_OID_HEXSZ, onto)) < 0 || + rebase->orig_head_name, GIT_OID_HEXSZ, onto)) < 0 || (error = git_buf_printf(&head_msg, "rebase finished: returning to %s", - state.orig_head_name)) < 0 || - (error = git_repository_head(&terminal_ref, repo)) < 0 || + rebase->orig_head_name)) < 0 || + (error = git_repository_head(&terminal_ref, rebase->repo)) < 0 || (error = git_reference_peel((git_object **)&terminal_commit, terminal_ref, GIT_OBJ_COMMIT)) < 0 || (error = git_reference_create_matching(&branch_ref, - repo, state.orig_head_name, git_commit_id(terminal_commit), 1, - &state.orig_head_id, signature, branch_msg.ptr)) < 0 || + rebase->repo, rebase->orig_head_name, git_commit_id(terminal_commit), 1, + &rebase->orig_head_id, signature, branch_msg.ptr)) < 0 || (error = git_reference_symbolic_create(&head_ref, - repo, GIT_HEAD_FILE, state.orig_head_name, 1, + rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1, signature, head_msg.ptr)) < 0 || - (error = rebase_copy_notes(repo, &state, signature, &opts)) < 0) + (error = rebase_copy_notes(rebase, signature, &opts)) < 0) goto done; - error = rebase_cleanup(&state); + error = rebase_cleanup(rebase); done: git_buf_free(&head_msg); @@ -1010,9 +1040,21 @@ done: git_reference_free(head_ref); git_reference_free(branch_ref); git_reference_free(terminal_ref); - rebase_state_free(&state); rebase_opts_free(&opts); return error; } +void git_rebase_free(git_rebase *rebase) +{ + if (rebase == NULL) + return; + + if (rebase->type == GIT_REBASE_TYPE_MERGE) { + git__free(rebase->merge.onto_name); + git_commit_free(rebase->merge.current); + } + + git__free(rebase->orig_head_name); + git__free(rebase->state_path); +} diff --git a/tests/rebase/abort.c b/tests/rebase/abort.c index 896eb4805..c6d27f19d 100644 --- a/tests/rebase/abort.c +++ b/tests/rebase/abort.c @@ -20,14 +20,16 @@ void test_rebase_abort__cleanup(void) static void test_abort(git_merge_head *branch, git_merge_head *onto) { + git_rebase *rebase; git_reference *head_ref, *branch_ref = NULL; git_signature *signature; git_status_list *statuslist; git_reflog *reflog; const git_reflog_entry *reflog_entry; + cl_git_pass(git_rebase_open(&rebase, repo)); cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); - cl_git_pass(git_rebase_abort(repo, signature)); + cl_git_pass(git_rebase_abort(rebase, signature)); cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); @@ -58,10 +60,12 @@ static void test_abort(git_merge_head *branch, git_merge_head *onto) git_reference_free(head_ref); git_reference_free(branch_ref); git_signature_free(signature); + git_rebase_free(rebase); } void test_rebase_abort__merge(void) { + git_rebase *rebase; git_reference *branch_ref, *onto_ref; git_signature *signature; git_merge_head *branch_head, *onto_head; @@ -74,7 +78,7 @@ void test_rebase_abort__merge(void) cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); - cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, NULL, onto_head, signature, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); test_abort(branch_head, onto_head); @@ -86,10 +90,12 @@ void test_rebase_abort__merge(void) git_reference_free(branch_ref); git_reference_free(onto_ref); + git_rebase_free(rebase); } void test_rebase_abort__detached_head(void) { + git_rebase *rebase; git_oid branch_id; git_reference *onto_ref; git_signature *signature; @@ -103,7 +109,7 @@ void test_rebase_abort__detached_head(void) cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); - cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, NULL, onto_head, signature, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); test_abort(branch_head, onto_head); @@ -114,10 +120,12 @@ void test_rebase_abort__detached_head(void) git_merge_head_free(onto_head); git_reference_free(onto_ref); + git_rebase_free(rebase); } void test_rebase_abort__old_style_head_file(void) { + git_rebase *rebase; git_reference *branch_ref, *onto_ref; git_signature *signature; git_merge_head *branch_head, *onto_head; @@ -130,7 +138,7 @@ void test_rebase_abort__old_style_head_file(void) cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); - cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, NULL, onto_head, signature, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); p_rename("rebase-merge/.git/rebase-merge/orig-head", @@ -145,4 +153,5 @@ void test_rebase_abort__old_style_head_file(void) git_reference_free(branch_ref); git_reference_free(onto_ref); + git_rebase_free(rebase); } diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index a3bb711b2..9b96ecbce 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -24,6 +24,7 @@ void test_rebase_merge__cleanup(void) void test_rebase_merge__next(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_rebase_operation rebase_operation; @@ -40,9 +41,9 @@ void test_rebase_merge__next(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); git_oid_fromstr(&pick_id, "da9c51a23d02d931a486f45ad18cda05cf5d2b94"); @@ -65,10 +66,12 @@ void test_rebase_merge__next(void) git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } void test_rebase_merge__next_with_conflicts(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_rebase_operation rebase_operation; @@ -105,9 +108,9 @@ void test_rebase_merge__next_with_conflicts(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); git_oid_fromstr(&pick_id, "33f915f9e4dbd9f4b24430e48731a59b45b15500"); @@ -129,10 +132,12 @@ void test_rebase_merge__next_with_conflicts(void) git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } void test_rebase_merge__next_stops_with_iterover(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_rebase_operation rebase_operation; @@ -148,29 +153,29 @@ void test_rebase_merge__next_stops_with_iterover(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); - cl_git_fail(error = git_rebase_next(&rebase_operation, repo, &checkout_opts)); + cl_git_fail(error = git_rebase_next(&rebase_operation, rebase, &checkout_opts)); cl_assert_equal_i(GIT_ITEROVER, error); cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); @@ -180,10 +185,12 @@ void test_rebase_merge__next_stops_with_iterover(void) git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } void test_rebase_merge__commit(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_rebase_operation rebase_operation; @@ -202,10 +209,10 @@ void test_rebase_merge__commit(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); cl_git_pass(git_commit_lookup(&commit, repo, &commit_id)); @@ -240,10 +247,12 @@ void test_rebase_merge__commit(void) git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } void test_rebase_merge__commit_updates_rewritten(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_rebase_operation rebase_operation; @@ -258,14 +267,14 @@ void test_rebase_merge__commit_updates_rewritten(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); cl_assert_equal_file( @@ -277,10 +286,12 @@ void test_rebase_merge__commit_updates_rewritten(void) git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } void test_rebase_merge__commit_drops_already_applied(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_rebase_operation rebase_operation; @@ -296,16 +307,16 @@ void test_rebase_merge__commit_drops_already_applied(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_fail(error = git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_fail(error = git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); cl_assert_equal_i(GIT_EAPPLIED, error); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); cl_assert_equal_file( @@ -316,10 +327,12 @@ void test_rebase_merge__commit_drops_already_applied(void) git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } void test_rebase_merge__finish(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref, *head_ref; git_merge_head *branch_head, *upstream_head; git_rebase_operation rebase_operation; @@ -337,16 +350,16 @@ void test_rebase_merge__finish(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); - cl_git_fail(error = git_rebase_next(&rebase_operation, repo, &checkout_opts)); + cl_git_fail(error = git_rebase_next(&rebase_operation, rebase, &checkout_opts)); cl_assert_equal_i(GIT_ITEROVER, error); - cl_git_pass(git_rebase_finish(repo, signature, NULL)); + cl_git_pass(git_rebase_finish(rebase, signature, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); @@ -374,12 +387,14 @@ void test_rebase_merge__finish(void) git_reference_free(head_ref); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } static void test_copy_note( const git_rebase_options *opts, bool should_exist) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_commit *branch_commit; @@ -406,13 +421,13 @@ static void test_copy_note( "refs/notes/test", git_commit_id(branch_commit), "This is a commit note.", 0)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, opts)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, opts)); - cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); - cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); - cl_git_pass(git_rebase_finish(repo, signature, opts)); + cl_git_pass(git_rebase_finish(rebase, signature, opts)); cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); @@ -431,6 +446,7 @@ static void test_copy_note( git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } void test_rebase_merge__copy_notes_off_by_default(void) diff --git a/tests/rebase/setup.c b/tests/rebase/setup.c index 4828c4057..175641494 100644 --- a/tests/rebase/setup.c +++ b/tests/rebase/setup.c @@ -27,6 +27,7 @@ void test_rebase_setup__cleanup(void) * git checkout beef ; git rebase --merge master */ void test_rebase_setup__blocked_when_in_progress(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; @@ -38,11 +39,11 @@ void test_rebase_setup__blocked_when_in_progress(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); - cl_git_fail(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_fail(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); git_merge_head_free(branch_head); git_merge_head_free(upstream_head); @@ -53,6 +54,7 @@ void test_rebase_setup__blocked_when_in_progress(void) /* git checkout beef ; git rebase --merge master */ void test_rebase_setup__merge(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_reference *head; @@ -67,7 +69,7 @@ void test_rebase_setup__merge(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); @@ -94,11 +96,13 @@ void test_rebase_setup__merge(void) git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } /* git checkout beef && git rebase --merge --root --onto master */ void test_rebase_setup__merge_root(void) { + git_rebase *rebase; git_reference *branch_ref, *onto_ref; git_merge_head *branch_head, *onto_head; git_reference *head; @@ -113,7 +117,7 @@ void test_rebase_setup__merge_root(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); - cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, NULL, onto_head, signature, NULL)); git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); cl_git_pass(git_repository_head(&head, repo)); @@ -140,11 +144,13 @@ void test_rebase_setup__merge_root(void) git_merge_head_free(onto_head); git_reference_free(branch_ref); git_reference_free(onto_ref); + git_rebase_free(rebase); } /* git checkout gravy && git rebase --merge --onto master veal */ void test_rebase_setup__merge_onto_and_upstream(void) { + git_rebase *rebase; git_reference *branch1_ref, *branch2_ref, *onto_ref; git_merge_head *branch1_head, *branch2_head, *onto_head; git_reference *head; @@ -161,7 +167,7 @@ void test_rebase_setup__merge_onto_and_upstream(void) cl_git_pass(git_merge_head_from_ref(&branch2_head, repo, branch2_ref)); cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); - cl_git_pass(git_rebase(repo, branch1_head, branch2_head, onto_head, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch1_head, branch2_head, onto_head, signature, NULL)); git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); cl_git_pass(git_repository_head(&head, repo)); @@ -186,12 +192,14 @@ void test_rebase_setup__merge_onto_and_upstream(void) git_reference_free(branch1_ref); git_reference_free(branch2_ref); git_reference_free(onto_ref); + git_rebase_free(rebase); } /* Ensure merge commits are dropped in a rebase */ /* git checkout veal && git rebase --merge master */ void test_rebase_setup__branch_with_merges(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_reference *head; @@ -206,7 +214,7 @@ void test_rebase_setup__branch_with_merges(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); @@ -233,11 +241,13 @@ void test_rebase_setup__branch_with_merges(void) git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } /* git checkout barley && git rebase --merge master */ void test_rebase_setup__orphan_branch(void) { + git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_reference *head; @@ -252,7 +262,7 @@ void test_rebase_setup__orphan_branch(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); @@ -279,10 +289,12 @@ void test_rebase_setup__orphan_branch(void) git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); } static int rebase_is_blocked(void) { + git_rebase *rebase = NULL; int error; git_reference *branch_ref, *upstream_ref; @@ -296,13 +308,14 @@ static int rebase_is_blocked(void) cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); - error = git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL); + error = git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL); git_merge_head_free(branch_head); git_merge_head_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); + git_rebase_free(rebase); return error; } From f152f8ac0c6c20bf5e245e79629dc70a913496b1 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 26 Aug 2014 16:18:46 -0500 Subject: [PATCH 15/21] rebase: preload all operations --- include/git2/rebase.h | 4 +- src/rebase.c | 304 ++++++++++++++++++++++++------------------ tests/rebase/merge.c | 24 ++-- 3 files changed, 186 insertions(+), 146 deletions(-) diff --git a/include/git2/rebase.h b/include/git2/rebase.h index 3d3c1c78c..9ffdc4805 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -156,13 +156,13 @@ GIT_EXTERN(int) git_rebase_open(git_rebase **out, git_repository *repo); * working directory will be updated with the changes. If there are conflicts, * you will need to address those before committing the changes. * - * @param out The rebase operation that is to be performed next + * @param out Pointer to store the rebase operation that is to be performed next * @param repo The rebase in progress * @param checkout_opts Options to specify how the patch should be checked out * @return Zero on success; -1 on failure. */ GIT_EXTERN(int) git_rebase_next( - git_rebase_operation *operation, + git_rebase_operation **operation, git_rebase *rebase, git_checkout_options *checkout_opts); diff --git a/src/rebase.c b/src/rebase.c index 17e34e191..635682f73 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -51,14 +51,6 @@ typedef enum { GIT_REBASE_TYPE_INTERACTIVE = 3, } git_rebase_type_t; -struct git_rebase_merge { - int32_t msgnum; - int32_t end; - char *onto_name; - - git_commit *current; -}; - struct git_rebase { git_repository *repo; @@ -66,18 +58,17 @@ struct git_rebase { char *state_path; int head_detached : 1, - quiet : 1; + quiet : 1, + started : 1; char *orig_head_name; git_oid orig_head_id; git_oid onto_id; + char *onto_name; git_array_t(git_rebase_operation) operations; - - union { - struct git_rebase_merge merge; - }; + size_t current; }; #define GIT_REBASE_STATE_INIT {0} @@ -118,79 +109,115 @@ done: return 0; } -static int rebase_open_merge(git_rebase *rebase) +GIT_INLINE(int) rebase_readfile(git_buf *out, git_buf *state_path, const char *filename) { - git_buf path = GIT_BUF_INIT, msgnum = GIT_BUF_INIT, end = GIT_BUF_INIT, - onto_name = GIT_BUF_INIT, current = GIT_BUF_INIT; - git_oid current_id; - int state_path_len, error; + size_t state_path_len = state_path->size; + int error; - if ((error = git_buf_puts(&path, rebase->state_path)) < 0) + git_buf_clear(out); + + if ((error = git_buf_joinpath(state_path, state_path->ptr, filename)) < 0 || + (error = git_futils_readbuffer(out, state_path->ptr)) < 0) goto done; - state_path_len = git_buf_len(&path); - - /* Read 'end' */ - if ((error = git_buf_joinpath(&path, path.ptr, END_FILE)) < 0 || - (error = git_futils_readbuffer(&end, path.ptr)) < 0) - goto done; - - git_buf_rtrim(&end); - - if ((error = git__strtol32(&rebase->merge.end, end.ptr, NULL, 10)) < 0) - goto done; - - /* Read 'onto_name' */ - git_buf_truncate(&path, state_path_len); - - if ((error = git_buf_joinpath(&path, path.ptr, ONTO_NAME_FILE)) < 0 || - (error = git_futils_readbuffer(&onto_name, path.ptr)) < 0) - goto done; - - git_buf_rtrim(&onto_name); - - rebase->merge.onto_name = git_buf_detach(&onto_name); - - /* Read 'msgnum' if it exists, otherwise let msgnum = 0 */ - git_buf_truncate(&path, state_path_len); - - if ((error = git_buf_joinpath(&path, path.ptr, MSGNUM_FILE)) < 0) - goto done; - - if (git_path_exists(path.ptr)) { - if ((error = git_futils_readbuffer(&msgnum, path.ptr)) < 0) - goto done; - - git_buf_rtrim(&msgnum); - - if ((error = git__strtol32(&rebase->merge.msgnum, msgnum.ptr, NULL, 10)) < 0) - goto done; - } - - - /* Read 'current' if it exists, otherwise let current = null */ - git_buf_truncate(&path, state_path_len); - - if ((error = git_buf_joinpath(&path, path.ptr, CURRENT_FILE)) < 0) - goto done; - - if (git_path_exists(path.ptr)) { - if ((error = git_futils_readbuffer(¤t, path.ptr)) < 0) - goto done; - - git_buf_rtrim(¤t); - - if ((error = git_oid_fromstr(¤t_id, current.ptr)) < 0 || - (error = git_commit_lookup(&rebase->merge.current, rebase->repo, ¤t_id)) < 0) - goto done; - } + git_buf_rtrim(out); done: - git_buf_free(&path); - git_buf_free(&msgnum); - git_buf_free(&end); - git_buf_free(&onto_name); - git_buf_free(¤t); + git_buf_truncate(state_path, state_path_len); + return error; +} + +GIT_INLINE(int) rebase_readint( + size_t *out, git_buf *asc_out, git_buf *state_path, const char *filename) +{ + int32_t num; + char *eol; + int error = 0; + + if ((error = rebase_readfile(asc_out, state_path, filename)) < 0) + return error; + + if (git__strtol32(&num, asc_out->ptr, &eol, 10) < 0 || num < 0 || *eol) { + giterr_set(GITERR_REBASE, "The file '%s' contains an invalid numeric value", filename); + return -1; + } + + *out = (size_t) num; + + return 0; +} + +GIT_INLINE(int) rebase_readoid( + git_oid *out, git_buf *str_out, git_buf *state_path, const char *filename) +{ + int error; + + if ((error = rebase_readfile(str_out, state_path, filename)) < 0) + return error; + + if (str_out->size != GIT_OID_HEXSZ || git_oid_fromstr(out, str_out->ptr) < 0) { + giterr_set(GITERR_REBASE, "The file '%s' contains an invalid object ID", filename); + return -1; + } + + return 0; +} + +static int rebase_open_merge(git_rebase *rebase) +{ + git_buf state_path = GIT_BUF_INIT, buf = GIT_BUF_INIT, cmt = GIT_BUF_INIT; + git_oid current_id = {0}; + git_rebase_operation *operation; + size_t i, msgnum = 0, end; + int error; + + if ((error = git_buf_puts(&state_path, rebase->state_path)) < 0) + goto done; + + /* Read 'msgnum' if it exists (otherwise, let msgnum = 0) */ + if ((error = rebase_readint(&msgnum, &buf, &state_path, MSGNUM_FILE)) < 0 && + error != GIT_ENOTFOUND) + goto done; + + if (msgnum) { + rebase->started = 1; + rebase->current = msgnum - 1; + } + + /* Read 'end' */ + if ((error = rebase_readint(&end, &buf, &state_path, END_FILE)) < 0) + goto done; + + /* Read 'current' if it exists */ + if ((error = rebase_readoid(¤t_id, &buf, &state_path, CURRENT_FILE)) < 0 && + error != GIT_ENOTFOUND) + goto done; + + /* Read cmt.* */ + git_array_init_to_size(rebase->operations, end); + GITERR_CHECK_ARRAY(rebase->operations); + + for (i = 0; i < end; i++) { + operation = git_array_alloc(rebase->operations); + GITERR_CHECK_ALLOC(operation); + + git_buf_clear(&cmt); + + if ((error = git_buf_printf(&cmt, "cmt.%" PRIuZ, (i+1))) < 0 || + (error = rebase_readoid(&operation->id, &buf, &state_path, cmt.ptr)) < 0) + goto done; + } + + /* Read 'onto_name' */ + if ((error = rebase_readfile(&buf, &state_path, ONTO_NAME_FILE)) < 0) + goto done; + + rebase->onto_name = git_buf_detach(&buf); + +done: + git_buf_free(&cmt); + git_buf_free(&state_path); + git_buf_free(&buf); return error; } @@ -341,7 +368,7 @@ static int rebase_setupfiles_merge(git_rebase *rebase) int error = 0; if ((error = rebase_setupfile(rebase, END_FILE, -1, "%d\n", git_array_size(rebase->operations))) < 0 || - (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->merge.onto_name)) < 0) + (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->onto_name)) < 0) goto done; for (i = 0; i < git_array_size(rebase->operations); i++) { @@ -542,10 +569,8 @@ static int rebase_init_merge( if (rebase_init_operations(rebase, repo, branch, upstream, onto) < 0) return -1; - rebase->merge.end = git_array_size(rebase->operations); - rebase->merge.onto_name = git__strdup(rebase_onto_name(onto)); - - GITERR_CHECK_ALLOC(rebase->merge.onto_name); + rebase->onto_name = git__strdup(rebase_onto_name(onto)); + GITERR_CHECK_ALLOC(rebase->onto_name); return 0; } @@ -647,6 +672,7 @@ static int normalize_checkout_opts( git_checkout_options *checkout_opts, const git_checkout_options *given_checkout_opts) { + git_commit *current_commit = NULL; int error = 0; if (given_checkout_opts != NULL) @@ -663,64 +689,83 @@ static int normalize_checkout_opts( if (rebase->type == GIT_REBASE_TYPE_MERGE) { if (!checkout_opts->our_label) - checkout_opts->our_label = rebase->merge.onto_name; + checkout_opts->our_label = rebase->onto_name; - if (!checkout_opts->their_label) - checkout_opts->their_label = git_commit_summary(rebase->merge.current); + if (!checkout_opts->their_label) { + git_rebase_operation *operation = + git_array_get(rebase->operations, rebase->current); + + if ((error = git_commit_lookup( + ¤t_commit, rebase->repo, &operation->id)) < 0) + goto done; + + checkout_opts->their_label = + git__strdup(git_commit_summary(current_commit)); + GITERR_CHECK_ALLOC(checkout_opts->their_label); + } } else { abort(); } +done: + git_commit_free(current_commit); return error; } +GIT_INLINE(int) rebase_movenext(git_rebase *rebase) +{ + size_t next = rebase->started ? rebase->current + 1 : 0; + + if (next == git_array_size(rebase->operations)) + return GIT_ITEROVER; + + rebase->started = 1; + rebase->current = next; + + return 0; +} + static int rebase_next_merge( - git_rebase_operation *out, + git_rebase_operation **out, git_rebase *rebase, git_checkout_options *given_checkout_opts) { - git_buf path = GIT_BUF_INIT, current = GIT_BUF_INIT; + git_buf path = GIT_BUF_INIT; git_checkout_options checkout_opts = {0}; - git_oid current_id; - git_commit *parent_commit = NULL; + git_commit *current_commit = NULL, *parent_commit = NULL; git_tree *current_tree = NULL, *head_tree = NULL, *parent_tree = NULL; git_index *index = NULL; + git_rebase_operation *operation; + char current_idstr[GIT_OID_HEXSZ]; unsigned int parent_count; int error; - if (rebase->merge.msgnum == rebase->merge.end) - return GIT_ITEROVER; + *out = NULL; - rebase->merge.msgnum++; - - if ((error = git_buf_joinpath(&path, rebase->state_path, "cmt.")) < 0 || - (error = git_buf_printf(&path, "%d", rebase->merge.msgnum)) < 0 || - (error = git_futils_readbuffer(¤t, path.ptr)) < 0) + if ((error = rebase_movenext(rebase)) < 0) goto done; - git_buf_rtrim(¤t); + operation = git_array_get(rebase->operations, rebase->current); - if (rebase->merge.current) - git_commit_free(rebase->merge.current); - - if ((error = git_oid_fromstr(¤t_id, current.ptr)) < 0 || - (error = git_commit_lookup(&rebase->merge.current, rebase->repo, ¤t_id)) < 0 || - (error = git_commit_tree(¤t_tree, rebase->merge.current)) < 0 || + if ((error = git_commit_lookup(¤t_commit, rebase->repo, &operation->id)) < 0 || + (error = git_commit_tree(¤t_tree, current_commit)) < 0 || (error = git_repository_head_tree(&head_tree, rebase->repo)) < 0) goto done; - if ((parent_count = git_commit_parentcount(rebase->merge.current)) > 1) { + if ((parent_count = git_commit_parentcount(current_commit)) > 1) { giterr_set(GITERR_REBASE, "Cannot rebase a merge commit"); error = -1; goto done; } else if (parent_count) { - if ((error = git_commit_parent(&parent_commit, rebase->merge.current, 0)) < 0 || + if ((error = git_commit_parent(&parent_commit, current_commit, 0)) < 0 || (error = git_commit_tree(&parent_tree, parent_commit)) < 0) goto done; } - if ((error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%d\n", rebase->merge.msgnum)) < 0 || - (error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%s\n", current.ptr)) < 0) + git_oid_fmt(current_idstr, &operation->id); + + if ((error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%d\n", rebase->current+1)) < 0 || + (error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0) goto done; if ((error = normalize_checkout_opts(rebase, &checkout_opts, given_checkout_opts)) < 0 || @@ -729,8 +774,7 @@ static int rebase_next_merge( (error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0) goto done; - out->type = GIT_REBASE_OPERATION_PICK; - memcpy(&out->id, ¤t_id, sizeof(git_oid)); + *out = operation; done: git_index_free(index); @@ -738,14 +782,14 @@ done: git_tree_free(head_tree); git_tree_free(parent_tree); git_commit_free(parent_commit); + git_commit_free(current_commit); git_buf_free(&path); - git_buf_free(¤t); return error; } int git_rebase_next( - git_rebase_operation *out, + git_rebase_operation **out, git_rebase *rebase, git_checkout_options *checkout_opts) { @@ -753,8 +797,6 @@ int git_rebase_next( assert(out && rebase); - memset(out, 0, sizeof(git_rebase_operation)); - switch (rebase->type) { case GIT_REBASE_TYPE_MERGE: error = rebase_next_merge(out, rebase, checkout_opts); @@ -776,7 +818,8 @@ static int rebase_commit_merge( { git_index *index = NULL; git_reference *head = NULL; - git_commit *head_commit = NULL, *commit = NULL; + git_commit *current_commit = NULL, *head_commit = NULL, *commit = NULL; + git_rebase_operation *operation; git_tree *head_tree = NULL, *tree = NULL; git_diff *diff = NULL; git_oid tree_id; @@ -784,11 +827,8 @@ static int rebase_commit_merge( char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ]; int error; - if (!rebase->merge.msgnum || !rebase->merge.current) { - giterr_set(GITERR_REBASE, "No rebase-merge state files exist"); - error = -1; - goto done; - } + operation = git_array_get(rebase->operations, rebase->current); + assert(operation); if ((error = git_repository_index(&index, rebase->repo)) < 0) goto done; @@ -799,7 +839,8 @@ static int rebase_commit_merge( goto done; } - if ((error = git_repository_head(&head, rebase->repo)) < 0 || + if ((error = git_commit_lookup(¤t_commit, rebase->repo, &operation->id)) < 0 || + (error = git_repository_head(&head, rebase->repo)) < 0 || (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 || (error = git_commit_tree(&head_tree, head_commit)) < 0 || (error = git_diff_tree_to_index(&diff, rebase->repo, head_tree, index, NULL)) < 0) @@ -816,11 +857,11 @@ static int rebase_commit_merge( goto done; if (!author) - author = git_commit_author(rebase->merge.current); + author = git_commit_author(current_commit); if (!message) { - message_encoding = git_commit_message_encoding(rebase->merge.current); - message = git_commit_message(rebase->merge.current); + message_encoding = git_commit_message_encoding(current_commit); + message = git_commit_message(current_commit); } if ((error = git_commit_create(commit_id, rebase->repo, NULL, author, @@ -831,7 +872,7 @@ static int rebase_commit_merge( rebase->repo, NULL, "HEAD", commit_id, committer, "rebase")) < 0) goto done; - git_oid_fmt(old_idstr, git_commit_id(rebase->merge.current)); + git_oid_fmt(old_idstr, git_commit_id(current_commit)); git_oid_fmt(new_idstr, commit_id); error = rebase_setupfile(rebase, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND, @@ -844,6 +885,7 @@ done: git_tree_free(tree); git_tree_free(head_tree); git_commit_free(head_commit); + git_commit_free(current_commit); git_reference_free(head); git_index_free(index); @@ -1050,11 +1092,9 @@ void git_rebase_free(git_rebase *rebase) if (rebase == NULL) return; - if (rebase->type == GIT_REBASE_TYPE_MERGE) { - git__free(rebase->merge.onto_name); - git_commit_free(rebase->merge.current); - } - + git__free(rebase->onto_name); git__free(rebase->orig_head_name); git__free(rebase->state_path); + git_array_clear(rebase->operations); + git__free(rebase); } diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index 9b96ecbce..80ca88b09 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -27,7 +27,7 @@ void test_rebase_merge__next(void) git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; - git_rebase_operation rebase_operation; + git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_status_list *status_list; const git_status_entry *status_entry; @@ -47,8 +47,8 @@ void test_rebase_merge__next(void) git_oid_fromstr(&pick_id, "da9c51a23d02d931a486f45ad18cda05cf5d2b94"); - cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation.type); - cl_assert_equal_oid(&pick_id, &rebase_operation.id); + cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation->type); + cl_assert_equal_oid(&pick_id, &rebase_operation->id); cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n", 41, "rebase/.git/rebase-merge/current"); cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum"); @@ -74,7 +74,7 @@ void test_rebase_merge__next_with_conflicts(void) git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; - git_rebase_operation rebase_operation; + git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_status_list *status_list; const git_status_entry *status_entry; @@ -114,8 +114,8 @@ void test_rebase_merge__next_with_conflicts(void) git_oid_fromstr(&pick_id, "33f915f9e4dbd9f4b24430e48731a59b45b15500"); - cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation.type); - cl_assert_equal_oid(&pick_id, &rebase_operation.id); + cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation->type); + cl_assert_equal_oid(&pick_id, &rebase_operation->id); cl_assert_equal_file("33f915f9e4dbd9f4b24430e48731a59b45b15500\n", 41, "rebase/.git/rebase-merge/current"); cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum"); @@ -140,7 +140,7 @@ void test_rebase_merge__next_stops_with_iterover(void) git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; - git_rebase_operation rebase_operation; + git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; int error; @@ -193,7 +193,7 @@ void test_rebase_merge__commit(void) git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; - git_rebase_operation rebase_operation; + git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id, tree_id, parent_id; git_signature *author; @@ -255,7 +255,7 @@ void test_rebase_merge__commit_updates_rewritten(void) git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; - git_rebase_operation rebase_operation; + git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; @@ -294,7 +294,7 @@ void test_rebase_merge__commit_drops_already_applied(void) git_rebase *rebase; git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; - git_rebase_operation rebase_operation; + git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; int error; @@ -335,7 +335,7 @@ void test_rebase_merge__finish(void) git_rebase *rebase; git_reference *branch_ref, *upstream_ref, *head_ref; git_merge_head *branch_head, *upstream_head; - git_rebase_operation rebase_operation; + git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; git_reflog *reflog; @@ -398,7 +398,7 @@ static void test_copy_note( git_reference *branch_ref, *upstream_ref; git_merge_head *branch_head, *upstream_head; git_commit *branch_commit; - git_rebase_operation rebase_operation; + git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid note_id, commit_id; git_note *note = NULL; From ed2c06a6a1c8725483759782f60531d582d9ec46 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 11 Sep 2014 16:47:20 -0400 Subject: [PATCH 16/21] git_rebase: iterators for operations --- include/git2/rebase.h | 27 ++++++++++ src/rebase.c | 21 ++++++++ tests/rebase/iterator.c | 108 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 tests/rebase/iterator.c diff --git a/include/git2/rebase.h b/include/git2/rebase.h index 9ffdc4805..b9b0af73b 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -149,6 +149,33 @@ GIT_EXTERN(int) git_rebase_init( */ GIT_EXTERN(int) git_rebase_open(git_rebase **out, git_repository *repo); +/** + * Gets the count of rebase operations that are to be applied. + * + * @param rebase The in-progress rebase + * @return The number of rebase operations in total + */ +GIT_EXTERN(size_t) git_rebase_operation_entrycount(git_rebase *rebase); + +/** + * Gets the index of the rebase operation that is currently being applied. + * + * @param rebase The in-progress rebase + * @return The index of the rebase operation currently being applied. + */ +GIT_EXTERN(size_t) git_rebase_operation_current(git_rebase *rebase); + +/** + * Gets the rebase operation specified by the given index. + * + * @param rebase The in-progress rebase + * @param idx The index of the rebase operation to retrieve + * @return The rebase operation or NULL if `idx` was out of bounds + */ +GIT_EXTERN(git_rebase_operation *) git_rebase_operation_byindex( + git_rebase *rebase, + size_t idx); + /** * Performs the next rebase operation and returns the information about it. * If the operation is one that applies a patch (which is any operation except diff --git a/src/rebase.c b/src/rebase.c index 635682f73..a4e9bade7 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -1087,6 +1087,27 @@ done: return error; } +size_t git_rebase_operation_entrycount(git_rebase *rebase) +{ + assert(rebase); + + return git_array_size(rebase->operations); +} + +size_t git_rebase_operation_current(git_rebase *rebase) +{ + assert(rebase); + + return rebase->current; +} + +git_rebase_operation *git_rebase_operation_byindex(git_rebase *rebase, size_t idx) +{ + assert(rebase); + + return git_array_get(rebase->operations, idx); +} + void git_rebase_free(git_rebase *rebase) { if (rebase == NULL) diff --git a/tests/rebase/iterator.c b/tests/rebase/iterator.c new file mode 100644 index 000000000..cfc6dce7b --- /dev/null +++ b/tests/rebase/iterator.c @@ -0,0 +1,108 @@ +#include "clar_libgit2.h" +#include "git2/rebase.h" +#include "posix.h" + +#include + +static git_repository *repo; +static git_index *_index; +static git_signature *signature; + +// Fixture setup and teardown +void test_rebase_iterator__initialize(void) +{ + repo = cl_git_sandbox_init("rebase"); + cl_git_pass(git_repository_index(&_index, repo)); + cl_git_pass(git_signature_now(&signature, "Rebaser", "rebaser@rebaser.rb")); +} + +void test_rebase_iterator__cleanup(void) +{ + git_signature_free(signature); + git_index_free(_index); + cl_git_sandbox_cleanup(); +} + +static void test_operations(git_rebase *rebase, size_t expected_current) +{ + size_t i, expected_count = 5; + git_oid expected_oid[5]; + git_rebase_operation *operation; + + git_oid_fromstr(&expected_oid[0], "da9c51a23d02d931a486f45ad18cda05cf5d2b94"); + git_oid_fromstr(&expected_oid[1], "8d1f13f93c4995760ac07d129246ac1ff64c0be9"); + git_oid_fromstr(&expected_oid[2], "3069cc907e6294623e5917ef6de663928c1febfb"); + git_oid_fromstr(&expected_oid[3], "588e5d2f04d49707fe4aab865e1deacaf7ef6787"); + git_oid_fromstr(&expected_oid[4], "b146bd7608eac53d9bf9e1a6963543588b555c64"); + + cl_assert_equal_i(expected_count, git_rebase_operation_entrycount(rebase)); + cl_assert_equal_i(expected_current, git_rebase_operation_current(rebase)); + + for (i = 0; i < expected_count; i++) { + operation = git_rebase_operation_byindex(rebase, i); + cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, operation->type); + cl_assert_equal_oid(&expected_oid[i], &operation->id); + } +} + +void test_rebase_iterator__iterates(void) +{ + git_rebase *rebase; + git_reference *branch_ref, *upstream_ref; + git_merge_head *branch_head, *upstream_head; + git_rebase_operation *rebase_operation; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_oid commit_id; + int error; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); + + cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); + test_operations(rebase, 0); + git_rebase_free(rebase); + + cl_git_pass(git_rebase_open(&rebase, repo)); + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, + NULL, NULL)); + test_operations(rebase, 0); + + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, + NULL, NULL)); + test_operations(rebase, 1); + + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, + NULL, NULL)); + test_operations(rebase, 2); + + git_rebase_free(rebase); + cl_git_pass(git_rebase_open(&rebase, repo)); + + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, + NULL, NULL)); + test_operations(rebase, 3); + + cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, + NULL, NULL)); + test_operations(rebase, 4); + + cl_git_fail(error = git_rebase_next(&rebase_operation, rebase, &checkout_opts)); + cl_assert_equal_i(GIT_ITEROVER, error); + test_operations(rebase, 4); + + git_merge_head_free(branch_head); + git_merge_head_free(upstream_head); + git_reference_free(branch_ref); + git_reference_free(upstream_ref); + git_rebase_free(rebase); +} From e69737d76098d67cd3ebf53b9c152cfc2675fc61 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 11 Sep 2014 16:46:46 -0400 Subject: [PATCH 17/21] rebase: oid member of operation should be const --- include/git2/rebase.h | 2 +- src/rebase.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/git2/rebase.h b/include/git2/rebase.h index b9b0af73b..46fadc67b 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -90,7 +90,7 @@ typedef struct { * The commit ID being cherry-picked. This will be populated for * all operations except those of type `GIT_REBASE_OPERATION_EXEC`. */ - git_oid id; + const git_oid id; /** * The executable the user has requested be run. This will only diff --git a/src/rebase.c b/src/rebase.c index a4e9bade7..a27ecabc3 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -204,7 +204,7 @@ static int rebase_open_merge(git_rebase *rebase) git_buf_clear(&cmt); if ((error = git_buf_printf(&cmt, "cmt.%" PRIuZ, (i+1))) < 0 || - (error = rebase_readoid(&operation->id, &buf, &state_path, cmt.ptr)) < 0) + (error = rebase_readoid((git_oid *)&operation->id, &buf, &state_path, cmt.ptr)) < 0) goto done; } @@ -549,7 +549,7 @@ static int rebase_init_operations( operation = git_array_alloc(rebase->operations); operation->type = GIT_REBASE_OPERATION_PICK; - git_oid_cpy(&operation->id, &id); + git_oid_cpy((git_oid *)&operation->id, &id); } error = 0; From 796b03bd4969f170d8e7a7c9edd567f636b58cb3 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 3 Oct 2014 20:47:48 +0000 Subject: [PATCH 18/21] rebase: clean up some warnings and memory leaks --- src/rebase.c | 40 ++++++++++++++-------------------------- tests/rebase/setup.c | 1 + 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/rebase.c b/src/rebase.c index a27ecabc3..91e3d9058 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -33,7 +33,7 @@ #define MSGNUM_FILE "msgnum" #define END_FILE "end" -#define CMT_FILE_FMT "cmt.%d" +#define CMT_FILE_FMT "cmt.%" PRIuZ #define CURRENT_FILE "current" #define REWRITTEN_FILE "rewritten" @@ -109,7 +109,10 @@ done: return 0; } -GIT_INLINE(int) rebase_readfile(git_buf *out, git_buf *state_path, const char *filename) +GIT_INLINE(int) rebase_readfile( + git_buf *out, + git_buf *state_path, + const char *filename) { size_t state_path_len = state_path->size; int error; @@ -131,7 +134,7 @@ GIT_INLINE(int) rebase_readint( size_t *out, git_buf *asc_out, git_buf *state_path, const char *filename) { int32_t num; - char *eol; + const char *eol; int error = 0; if ((error = rebase_readfile(asc_out, state_path, filename)) < 0) @@ -166,7 +169,7 @@ GIT_INLINE(int) rebase_readoid( static int rebase_open_merge(git_rebase *rebase) { git_buf state_path = GIT_BUF_INIT, buf = GIT_BUF_INIT, cmt = GIT_BUF_INIT; - git_oid current_id = {0}; + git_oid current_id = {{0}}; git_rebase_operation *operation; size_t i, msgnum = 0, end; int error; @@ -667,14 +670,12 @@ done: return error; } -static int normalize_checkout_opts( +static void normalize_checkout_opts( git_rebase *rebase, + git_commit *current_commit, git_checkout_options *checkout_opts, const git_checkout_options *given_checkout_opts) { - git_commit *current_commit = NULL; - int error = 0; - if (given_checkout_opts != NULL) memcpy(checkout_opts, given_checkout_opts, sizeof(git_checkout_options)); else { @@ -691,25 +692,11 @@ static int normalize_checkout_opts( if (!checkout_opts->our_label) checkout_opts->our_label = rebase->onto_name; - if (!checkout_opts->their_label) { - git_rebase_operation *operation = - git_array_get(rebase->operations, rebase->current); - - if ((error = git_commit_lookup( - ¤t_commit, rebase->repo, &operation->id)) < 0) - goto done; - - checkout_opts->their_label = - git__strdup(git_commit_summary(current_commit)); - GITERR_CHECK_ALLOC(checkout_opts->their_label); - } + if (!checkout_opts->their_label) + checkout_opts->their_label = git_commit_summary(current_commit); } else { abort(); } - -done: - git_commit_free(current_commit); - return error; } GIT_INLINE(int) rebase_movenext(git_rebase *rebase) @@ -768,8 +755,9 @@ static int rebase_next_merge( (error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0) goto done; - if ((error = normalize_checkout_opts(rebase, &checkout_opts, given_checkout_opts)) < 0 || - (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, NULL)) < 0 || + normalize_checkout_opts(rebase, current_commit, &checkout_opts, given_checkout_opts); + + if ((error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, NULL)) < 0 || (error = git_merge__check_result(rebase->repo, index)) < 0 || (error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0) goto done; diff --git a/tests/rebase/setup.c b/tests/rebase/setup.c index 175641494..e72075a88 100644 --- a/tests/rebase/setup.c +++ b/tests/rebase/setup.c @@ -40,6 +40,7 @@ void test_rebase_setup__blocked_when_in_progress(void) cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); + git_rebase_free(rebase); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); From 18b00406c6427eb8c9d96864448474e1d85017de Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 3 Oct 2014 19:02:29 -0400 Subject: [PATCH 19/21] s/git_merge_head/git_annotated_commit Rename git_merge_head to git_annotated_commit, as it becomes used in more operations than just merge. --- include/git2.h | 1 + include/git2/annotated_commit.h | 99 +++++++ include/git2/merge.h | 68 +---- include/git2/rebase.h | 7 +- include/git2/types.h | 4 +- src/annotated_commit.c | 121 ++++++++ src/annotated_commit.h | 22 ++ src/merge.c | 186 +++--------- src/merge.h | 14 +- src/rebase.c | 40 +-- tests/merge/merge_helpers.c | 9 +- tests/merge/workdir/analysis.c | 9 +- tests/merge/workdir/dirty.c | 8 +- tests/merge/workdir/setup.c | 472 +++++++++++++++---------------- tests/merge/workdir/simple.c | 40 +-- tests/merge/workdir/submodules.c | 16 +- tests/merge/workdir/trivial.c | 8 +- tests/rebase/abort.c | 41 +-- tests/rebase/iterator.c | 10 +- tests/rebase/merge.c | 82 +++--- tests/rebase/setup.c | 74 ++--- 21 files changed, 700 insertions(+), 631 deletions(-) create mode 100644 include/git2/annotated_commit.h create mode 100644 src/annotated_commit.c create mode 100644 src/annotated_commit.h diff --git a/include/git2.h b/include/git2.h index baa7fcaf8..5e032b2bf 100644 --- a/include/git2.h +++ b/include/git2.h @@ -8,6 +8,7 @@ #ifndef INCLUDE_git_git_h__ #define INCLUDE_git_git_h__ +#include "git2/annotated_commit.h" #include "git2/attr.h" #include "git2/blob.h" #include "git2/blame.h" diff --git a/include/git2/annotated_commit.h b/include/git2/annotated_commit.h new file mode 100644 index 000000000..87e3398a0 --- /dev/null +++ b/include/git2/annotated_commit.h @@ -0,0 +1,99 @@ +/* + * 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_git_annotated_commit_h__ +#define INCLUDE_git_annotated_commit_h__ + +#include "common.h" +#include "repository.h" +#include "types.h" + +/** + * @file git2/annotated_commit.h + * @brief Git annotated commit routines + * @defgroup git_annotated_commit Git annotated commit routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Creates a `git_annotated_commit` from the given reference. + * The resulting git_annotated_commit must be freed with + * `git_annotated_commit_free`. + * + * @param out pointer to store the git_annotated_commit result in + * @param repo repository that contains the given reference + * @param ref reference to use to lookup the git_annotated_commit + * @return 0 on success or error code + */ +GIT_EXTERN(int) git_annotated_commit_from_ref( + git_annotated_commit **out, + git_repository *repo, + const git_reference *ref); + +/** + * Creates a `git_annotated_commit` from the given fetch head data. + * The resulting git_annotated_commit must be freed with + * `git_annotated_commit_free`. + * + * @param out pointer to store the git_annotated_commit result in + * @param repo repository that contains the given commit + * @param branch_name name of the (remote) branch + * @param remote_url url of the remote + * @param oid the commit object id of the remote branch + * @return 0 on success or error code + */ +GIT_EXTERN(int) git_annotated_commit_from_fetchhead( + git_annotated_commit **out, + git_repository *repo, + const char *branch_name, + const char *remote_url, + const git_oid *id); + +/** + * Creates a `git_annotated_commit` from the given commit id. + * The resulting git_annotated_commit must be freed with + * `git_annotated_commit_free`. + * + * An annotated commit contains information about how it was + * looked up, which may be useful for functions like merge or + * rebase to provide context to the operation. For example, + * conflict files will include the name of the source or target + * branches being merged. It is therefore preferable to use the + * most specific function (eg `git_annotated_commit_from_ref`) + * instead of this one when that data is known. + * + * @param out pointer to store the git_annotated_commit result in + * @param repo repository that contains the given commit + * @param id the commit object id to lookup + * @return 0 on success or error code + */ +GIT_EXTERN(int) git_annotated_commit_lookup( + git_annotated_commit **out, + git_repository *repo, + const git_oid *id); + +/** + * Gets the commit ID that the given `git_annotated_commit` refers to. + * + * @param head the given annotated commit + * @return commit id + */ +GIT_EXTERN(const git_oid *) git_annotated_commit_id( + const git_annotated_commit *commit); + +/** + * Frees a `git_annotated_commit`. + * + * @param annotated_commit annotated commit to free + */ +GIT_EXTERN(void) git_annotated_commit_free( + git_annotated_commit *commit); + +/** @} */ +GIT_END_DECL +#endif diff --git a/include/git2/merge.h b/include/git2/merge.h index ed1b9a30f..9082fd6fb 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -13,6 +13,7 @@ #include "oidarray.h" #include "checkout.h" #include "index.h" +#include "annotated_commit.h" /** * @file git2/merge.h @@ -303,7 +304,7 @@ GIT_EXTERN(int) git_merge_analysis( git_merge_analysis_t *analysis_out, git_merge_preference_t *preference_out, git_repository *repo, - const git_merge_head **their_heads, + const git_annotated_commit **their_heads, size_t their_heads_len); /** @@ -381,69 +382,6 @@ GIT_EXTERN(int) git_merge_base_octopus( size_t length, const git_oid input_array[]); -/** - * Creates a `git_merge_head` from the given reference. The resulting - * git_merge_head must be freed with `git_merge_head_free`. - * - * @param out pointer to store the git_merge_head result in - * @param repo repository that contains the given reference - * @param ref reference to use as a merge input - * @return 0 on success or error code - */ -GIT_EXTERN(int) git_merge_head_from_ref( - git_merge_head **out, - git_repository *repo, - const git_reference *ref); - -/** - * Creates a `git_merge_head` from the given fetch head data. The resulting - * git_merge_head must be freed with `git_merge_head_free`. - * - * @param out pointer to store the git_merge_head result in - * @param repo repository that contains the given commit - * @param branch_name name of the (remote) branch - * @param remote_url url of the remote - * @param oid the commit object id to use as a merge input - * @return 0 on success or error code - */ -GIT_EXTERN(int) git_merge_head_from_fetchhead( - git_merge_head **out, - git_repository *repo, - const char *branch_name, - const char *remote_url, - const git_oid *oid); - -/** - * Creates a `git_merge_head` from the given commit id. The resulting - * git_merge_head must be freed with `git_merge_head_free`. - * - * @param out pointer to store the git_merge_head result in - * @param repo repository that contains the given commit - * @param id the commit object id to use as a merge input - * @return 0 on success or error code - */ -GIT_EXTERN(int) git_merge_head_from_id( - git_merge_head **out, - git_repository *repo, - const git_oid *id); - -/** - * Gets the commit ID that the given `git_merge_head` refers to. - * - * @param head the given merge head - * @return commit id - */ -GIT_EXTERN(const git_oid *) git_merge_head_id( - const git_merge_head *head); - -/** - * Frees a `git_merge_head`. - * - * @param head merge head to free - */ -GIT_EXTERN(void) git_merge_head_free( - git_merge_head *head); - /** * Merge two files as they exist in the in-memory data structures, using * the given common ancestor as the baseline, producing a @@ -557,7 +495,7 @@ GIT_EXTERN(int) git_merge_commits( */ GIT_EXTERN(int) git_merge( git_repository *repo, - const git_merge_head **their_heads, + const git_annotated_commit **their_heads, size_t their_heads_len, const git_merge_options *merge_opts, const git_checkout_options *checkout_opts); diff --git a/include/git2/rebase.h b/include/git2/rebase.h index 46fadc67b..24d8fcf71 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -10,6 +10,7 @@ #include "common.h" #include "types.h" #include "oid.h" +#include "annotated_commit.h" /** * @file git2/rebase.h @@ -133,9 +134,9 @@ GIT_EXTERN(int) git_rebase_init_options( GIT_EXTERN(int) git_rebase_init( git_rebase **out, git_repository *repo, - const git_merge_head *branch, - const git_merge_head *upstream, - const git_merge_head *onto, + const git_annotated_commit *branch, + const git_annotated_commit *upstream, + const git_annotated_commit *onto, const git_signature *signature, const git_rebase_options *opts); diff --git a/include/git2/types.h b/include/git2/types.h index 416140716..aa7a56f56 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -174,8 +174,8 @@ typedef struct git_reference_iterator git_reference_iterator; /** Transactional interface to references */ typedef struct git_transaction git_transaction; -/** Merge heads, the input to merge */ -typedef struct git_merge_head git_merge_head; +/** Annotated commits, the input to merge and rebase. */ +typedef struct git_annotated_commit git_annotated_commit; /** Merge result */ typedef struct git_merge_result git_merge_result; diff --git a/src/annotated_commit.c b/src/annotated_commit.c new file mode 100644 index 000000000..0a917802a --- /dev/null +++ b/src/annotated_commit.c @@ -0,0 +1,121 @@ +/* + * 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 "common.h" +#include "annotated_commit.h" + +#include "git2/commit.h" +#include "git2/refs.h" +#include "git2/repository.h" +#include "git2/annotated_commit.h" + +static int annotated_commit_init( + git_annotated_commit **out, + git_repository *repo, + const git_oid *id, + const char *ref_name, + const char *remote_url) +{ + git_annotated_commit *annotated_commit; + int error = 0; + + assert(out && id); + + *out = NULL; + + annotated_commit = git__calloc(1, sizeof(git_annotated_commit)); + GITERR_CHECK_ALLOC(annotated_commit); + + if (ref_name) { + annotated_commit->ref_name = git__strdup(ref_name); + GITERR_CHECK_ALLOC(annotated_commit->ref_name); + } + + if (remote_url) { + annotated_commit->remote_url = git__strdup(remote_url); + GITERR_CHECK_ALLOC(annotated_commit->remote_url); + } + + git_oid_fmt(annotated_commit->id_str, id); + annotated_commit->id_str[GIT_OID_HEXSZ] = '\0'; + + if ((error = git_commit_lookup(&annotated_commit->commit, repo, id)) < 0) { + git_annotated_commit_free(annotated_commit); + return error; + } + + *out = annotated_commit; + return error; +} + +int git_annotated_commit_from_ref( + git_annotated_commit **out, + git_repository *repo, + const git_reference *ref) +{ + git_reference *resolved; + int error = 0; + + assert(out && repo && ref); + + *out = NULL; + + if ((error = git_reference_resolve(&resolved, ref)) < 0) + return error; + + error = annotated_commit_init(out, repo, git_reference_target(resolved), + git_reference_name(ref), NULL); + + git_reference_free(resolved); + return error; +} + +int git_annotated_commit_lookup( + git_annotated_commit **out, + git_repository *repo, + const git_oid *id) +{ + assert(out && repo && id); + + return annotated_commit_init(out, repo, id, NULL, NULL); +} + +int git_annotated_commit_from_fetchhead( + git_annotated_commit **out, + git_repository *repo, + const char *branch_name, + const char *remote_url, + const git_oid *id) +{ + assert(repo && id && branch_name && remote_url); + + return annotated_commit_init(out, repo, id, branch_name, remote_url); +} + +const git_oid *git_annotated_commit_id( + const git_annotated_commit *annotated_commit) +{ + assert(annotated_commit); + return git_commit_id(annotated_commit->commit); +} + +void git_annotated_commit_free(git_annotated_commit *annotated_commit) +{ + if (annotated_commit == NULL) + return; + + if (annotated_commit->commit != NULL) + git_commit_free(annotated_commit->commit); + + if (annotated_commit->ref_name != NULL) + git__free(annotated_commit->ref_name); + + if (annotated_commit->remote_url != NULL) + git__free(annotated_commit->remote_url); + + git__free(annotated_commit); +} diff --git a/src/annotated_commit.h b/src/annotated_commit.h new file mode 100644 index 000000000..e873184ae --- /dev/null +++ b/src/annotated_commit.h @@ -0,0 +1,22 @@ +/* + * 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_annotated_commit_h__ +#define INCLUDE_annotated_commit_h__ + +#include "git2/oid.h" + +/** Internal structure for merge inputs */ +struct git_annotated_commit { + git_commit *commit; + + char *ref_name; + char *remote_url; + + char id_str[GIT_OID_HEXSZ+1]; +}; + +#endif diff --git a/src/merge.c b/src/merge.c index 3cafc5d03..1c55e797b 100644 --- a/src/merge.c +++ b/src/merge.c @@ -27,6 +27,7 @@ #include "filebuf.h" #include "config.h" #include "oidarray.h" +#include "annotated_commit.h" #include "git2/types.h" #include "git2/repository.h" @@ -40,6 +41,7 @@ #include "git2/config.h" #include "git2/tree.h" #include "git2/oidarray.h" +#include "git2/annotated_commit.h" #include "git2/sys/index.h" #include "git2/sys/hashsig.h" @@ -1837,7 +1839,7 @@ done: static int write_merge_head( git_repository *repo, - const git_merge_head *heads[], + const git_annotated_commit *heads[], size_t heads_len) { git_filebuf file = GIT_FILEBUF_INIT; @@ -1852,7 +1854,7 @@ static int write_merge_head( goto cleanup; for (i = 0; i < heads_len; i++) { - if ((error = git_filebuf_printf(&file, "%s\n", heads[i]->oid_str)) < 0) + if ((error = git_filebuf_printf(&file, "%s\n", heads[i]->id_str)) < 0) goto cleanup; } @@ -1894,7 +1896,7 @@ cleanup: } struct merge_msg_entry { - const git_merge_head *merge_head; + const git_annotated_commit *merge_head; bool written; }; @@ -2082,7 +2084,7 @@ static int merge_msg_write_remotes( static int write_merge_msg( git_repository *repo, - const git_merge_head *heads[], + const git_annotated_commit *heads[], size_t heads_len) { git_filebuf file = GIT_FILEBUF_INIT; @@ -2128,7 +2130,7 @@ static int write_merge_msg( if ((error = git_filebuf_printf(&file, "%scommit '%s'", (i > 0) ? "; " : "", - entries[i].merge_head->oid_str)) < 0) + entries[i].merge_head->id_str)) < 0) goto cleanup; entries[i].written = 1; @@ -2176,7 +2178,7 @@ static int write_merge_msg( continue; if ((error = git_filebuf_printf(&file, "; commit '%s'", - entries[i].merge_head->oid_str)) < 0) + entries[i].merge_head->id_str)) < 0) goto cleanup; } @@ -2198,15 +2200,15 @@ cleanup: int git_merge__setup( git_repository *repo, - const git_merge_head *our_head, - const git_merge_head *heads[], + const git_annotated_commit *our_head, + const git_annotated_commit *heads[], size_t heads_len) { int error = 0; assert (repo && our_head && heads); - if ((error = git_repository__set_orig_head(repo, &our_head->oid)) == 0 && + if ((error = git_repository__set_orig_head(repo, git_annotated_commit_id(our_head))) == 0 && (error = write_merge_head(repo, heads, heads_len)) == 0 && (error = write_merge_mode(repo)) == 0) { error = write_merge_msg(repo, heads, heads_len); @@ -2218,10 +2220,10 @@ int git_merge__setup( /* Merge branches */ static int merge_ancestor_head( - git_merge_head **ancestor_head, + git_annotated_commit **ancestor_head, git_repository *repo, - const git_merge_head *our_head, - const git_merge_head **their_heads, + const git_annotated_commit *our_head, + const git_annotated_commit **their_heads, size_t their_heads_len) { git_oid *oids, ancestor_oid; @@ -2236,12 +2238,12 @@ static int merge_ancestor_head( git_oid_cpy(&oids[0], git_commit_id(our_head->commit)); for (i = 0; i < their_heads_len; i++) - git_oid_cpy(&oids[i + 1], &their_heads[i]->oid); + git_oid_cpy(&oids[i + 1], git_annotated_commit_id(their_heads[i])); if ((error = git_merge_base_many(&ancestor_oid, repo, their_heads_len + 1, oids)) < 0) goto on_error; - error = git_merge_head_from_id(ancestor_head, repo, &ancestor_oid); + error = git_annotated_commit_lookup(ancestor_head, repo, &ancestor_oid); on_error: git__free(oids); @@ -2265,10 +2267,10 @@ static int merge_normalize_checkout_opts( git_repository *repo, git_checkout_options *checkout_opts, const git_checkout_options *given_checkout_opts, - const git_merge_head *ancestor_head, - const git_merge_head *our_head, + const git_annotated_commit *ancestor_head, + const git_annotated_commit *our_head, size_t their_heads_len, - const git_merge_head **their_heads) + const git_annotated_commit **their_heads) { int error = 0; @@ -2302,7 +2304,7 @@ static int merge_normalize_checkout_opts( if (their_heads_len == 1 && their_heads[0]->ref_name) checkout_opts->their_label = merge_their_label(their_heads[0]->ref_name); else if (their_heads_len == 1) - checkout_opts->their_label = their_heads[0]->oid_str; + checkout_opts->their_label = their_heads[0]->id_str; else checkout_opts->their_label = "theirs"; } @@ -2516,13 +2518,13 @@ static int merge_state_cleanup(git_repository *repo) } static int merge_heads( - git_merge_head **ancestor_head_out, - git_merge_head **our_head_out, + git_annotated_commit **ancestor_head_out, + git_annotated_commit **our_head_out, git_repository *repo, - const git_merge_head **their_heads, + const git_annotated_commit **their_heads, size_t their_heads_len) { - git_merge_head *ancestor_head = NULL, *our_head = NULL; + git_annotated_commit *ancestor_head = NULL, *our_head = NULL; git_reference *our_ref = NULL; int error = 0; @@ -2533,7 +2535,7 @@ static int merge_heads( goto done; if ((error = git_reference_lookup(&our_ref, repo, GIT_HEAD_FILE)) < 0 || - (error = git_merge_head_from_ref(&our_head, repo, our_ref)) < 0) + (error = git_annotated_commit_from_ref(&our_head, repo, our_ref)) < 0) goto done; if ((error = merge_ancestor_head(&ancestor_head, repo, our_head, their_heads, their_heads_len)) < 0) { @@ -2549,8 +2551,8 @@ static int merge_heads( done: if (error < 0) { - git_merge_head_free(ancestor_head); - git_merge_head_free(our_head); + git_annotated_commit_free(ancestor_head); + git_annotated_commit_free(our_head); } git_reference_free(our_ref); @@ -2595,10 +2597,10 @@ int git_merge_analysis( git_merge_analysis_t *analysis_out, git_merge_preference_t *preference_out, git_repository *repo, - const git_merge_head **their_heads, + const git_annotated_commit **their_heads, size_t their_heads_len) { - git_merge_head *ancestor_head = NULL, *our_head = NULL; + git_annotated_commit *ancestor_head = NULL, *our_head = NULL; int error = 0; assert(analysis_out && preference_out && repo && their_heads); @@ -2623,11 +2625,13 @@ int git_merge_analysis( goto done; /* We're up-to-date if we're trying to merge our own common ancestor. */ - if (ancestor_head && git_oid_equal(&ancestor_head->oid, &their_heads[0]->oid)) + if (ancestor_head && git_oid_equal( + git_annotated_commit_id(ancestor_head), git_annotated_commit_id(their_heads[0]))) *analysis_out |= GIT_MERGE_ANALYSIS_UP_TO_DATE; /* We're fastforwardable if we're our own common ancestor. */ - else if (ancestor_head && git_oid_equal(&ancestor_head->oid, &our_head->oid)) + else if (ancestor_head && git_oid_equal( + git_annotated_commit_id(ancestor_head), git_annotated_commit_id(our_head))) *analysis_out |= GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_NORMAL; /* Otherwise, just a normal merge is possible. */ @@ -2635,21 +2639,21 @@ int git_merge_analysis( *analysis_out |= GIT_MERGE_ANALYSIS_NORMAL; done: - git_merge_head_free(ancestor_head); - git_merge_head_free(our_head); + git_annotated_commit_free(ancestor_head); + git_annotated_commit_free(our_head); return error; } int git_merge( git_repository *repo, - const git_merge_head **their_heads, + const git_annotated_commit **their_heads, size_t their_heads_len, const git_merge_options *merge_opts, const git_checkout_options *given_checkout_opts) { git_reference *our_ref = NULL; git_checkout_options checkout_opts; - git_merge_head *ancestor_head = NULL, *our_head = NULL; + git_annotated_commit *ancestor_head = NULL, *our_head = NULL; git_tree *ancestor_tree = NULL, *our_tree = NULL, **their_trees = NULL; git_index *index_new = NULL; size_t i; @@ -2712,126 +2716,14 @@ done: git__free(their_trees); - git_merge_head_free(our_head); - git_merge_head_free(ancestor_head); + git_annotated_commit_free(our_head); + git_annotated_commit_free(ancestor_head); git_reference_free(our_ref); return error; } -/* Merge heads are the input to merge */ - -static int merge_head_init( - git_merge_head **out, - git_repository *repo, - const char *ref_name, - const char *remote_url, - const git_oid *oid) -{ - git_merge_head *head; - int error = 0; - - assert(out && oid); - - *out = NULL; - - head = git__calloc(1, sizeof(git_merge_head)); - GITERR_CHECK_ALLOC(head); - - if (ref_name) { - head->ref_name = git__strdup(ref_name); - GITERR_CHECK_ALLOC(head->ref_name); - } - - if (remote_url) { - head->remote_url = git__strdup(remote_url); - GITERR_CHECK_ALLOC(head->remote_url); - } - - git_oid_cpy(&head->oid, oid); - - git_oid_fmt(head->oid_str, oid); - head->oid_str[GIT_OID_HEXSZ] = '\0'; - - if ((error = git_commit_lookup(&head->commit, repo, &head->oid)) < 0) { - git_merge_head_free(head); - return error; - } - - *out = head; - return error; -} - -int git_merge_head_from_ref( - git_merge_head **out, - git_repository *repo, - const git_reference *ref) -{ - git_reference *resolved; - int error = 0; - - assert(out && repo && ref); - - *out = NULL; - - if ((error = git_reference_resolve(&resolved, ref)) < 0) - return error; - - error = merge_head_init(out, repo, git_reference_name(ref), NULL, - git_reference_target(resolved)); - - git_reference_free(resolved); - return error; -} - -int git_merge_head_from_id( - git_merge_head **out, - git_repository *repo, - const git_oid *oid) -{ - assert(out && repo && oid); - - return merge_head_init(out, repo, NULL, NULL, oid); -} - -int git_merge_head_from_fetchhead( - git_merge_head **out, - git_repository *repo, - const char *branch_name, - const char *remote_url, - const git_oid *oid) -{ - assert(repo && branch_name && remote_url && oid); - - return merge_head_init(out, repo, branch_name, remote_url, oid); -} - -const git_oid *git_merge_head_id( - const git_merge_head *head) -{ - assert(head); - - return &head->oid; -} - -void git_merge_head_free(git_merge_head *head) -{ - if (head == NULL) - return; - - if (head->commit != NULL) - git_object_free((git_object *)head->commit); - - if (head->ref_name != NULL) - git__free(head->ref_name); - - if (head->remote_url != NULL) - git__free(head->remote_url); - - git__free(head); -} - int git_merge_init_options(git_merge_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( diff --git a/src/merge.h b/src/merge.h index cc17389ab..2684c15f8 100644 --- a/src/merge.h +++ b/src/merge.h @@ -110,16 +110,6 @@ typedef struct { int binary:1; } git_merge_diff; -/** Internal structure for merge inputs */ -struct git_merge_head { - char *ref_name; - char *remote_url; - - git_oid oid; - char oid_str[GIT_OID_HEXSZ+1]; - git_commit *commit; -}; - int git_merge__bases_many( git_commit_list **out, git_revwalk *walk, @@ -145,8 +135,8 @@ void git_merge_diff_list__free(git_merge_diff_list *diff_list); int git_merge__setup( git_repository *repo, - const git_merge_head *our_head, - const git_merge_head *heads[], + const git_annotated_commit *our_head, + const git_annotated_commit *heads[], size_t heads_len); int git_merge__check_result(git_repository *repo, git_index *index_new); diff --git a/src/rebase.c b/src/rebase.c index 91e3d9058..6905d17dd 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -13,8 +13,10 @@ #include "merge.h" #include "array.h" #include "config.h" +#include "annotated_commit.h" #include +#include #include #include #include @@ -352,14 +354,14 @@ static int rebase_setupfile(git_rebase *rebase, const char *filename, int flags, return error; } -static const char *rebase_onto_name(const git_merge_head *onto) +static const char *rebase_onto_name(const git_annotated_commit *onto) { if (onto->ref_name && git__strncmp(onto->ref_name, "refs/heads/", 11) == 0) return onto->ref_name + 11; else if (onto->ref_name) return onto->ref_name; else - return onto->oid_str; + return onto->id_str; } static int rebase_setupfiles_merge(git_rebase *rebase) @@ -519,9 +521,9 @@ done: static int rebase_init_operations( git_rebase *rebase, git_repository *repo, - const git_merge_head *branch, - const git_merge_head *upstream, - const git_merge_head *onto) + const git_annotated_commit *branch, + const git_annotated_commit *upstream, + const git_annotated_commit *onto) { git_revwalk *revwalk = NULL; git_commit *commit; @@ -534,8 +536,8 @@ static int rebase_init_operations( upstream = onto; if ((error = git_revwalk_new(&revwalk, rebase->repo)) < 0 || - (error = git_revwalk_push(revwalk, &branch->oid)) < 0 || - (error = git_revwalk_hide(revwalk, &upstream->oid)) < 0) + (error = git_revwalk_push(revwalk, git_annotated_commit_id(branch))) < 0 || + (error = git_revwalk_hide(revwalk, git_annotated_commit_id(upstream))) < 0) goto done; git_revwalk_sorting(revwalk, GIT_SORT_REVERSE | GIT_SORT_TIME); @@ -565,9 +567,9 @@ done: static int rebase_init_merge( git_rebase *rebase, git_repository *repo, - const git_merge_head *branch, - const git_merge_head *upstream, - const git_merge_head *onto) + const git_annotated_commit *branch, + const git_annotated_commit *upstream, + const git_annotated_commit *onto) { if (rebase_init_operations(rebase, repo, branch, upstream, onto) < 0) return -1; @@ -581,9 +583,9 @@ static int rebase_init_merge( static int rebase_init( git_rebase *rebase, git_repository *repo, - const git_merge_head *branch, - const git_merge_head *upstream, - const git_merge_head *onto, + const git_annotated_commit *branch, + const git_annotated_commit *upstream, + const git_annotated_commit *onto, const git_rebase_options *opts) { git_buf state_path = GIT_BUF_INIT; @@ -597,8 +599,8 @@ static int rebase_init( rebase->orig_head_name = git__strdup(branch->ref_name ? branch->ref_name : ORIG_DETACHED_HEAD); rebase->quiet = opts->quiet; - git_oid_cpy(&rebase->orig_head_id, &branch->oid); - git_oid_cpy(&rebase->onto_id, &onto->oid); + git_oid_cpy(&rebase->orig_head_id, git_annotated_commit_id(branch)); + git_oid_cpy(&rebase->onto_id, git_annotated_commit_id(onto)); if (!rebase->orig_head_name || !rebase->state_path) return -1; @@ -613,9 +615,9 @@ static int rebase_init( int git_rebase_init( git_rebase **out, git_repository *repo, - const git_merge_head *branch, - const git_merge_head *upstream, - const git_merge_head *onto, + const git_annotated_commit *branch, + const git_annotated_commit *upstream, + const git_annotated_commit *onto, const git_signature *signature, const git_rebase_options *given_opts) { @@ -651,7 +653,7 @@ int git_rebase_init( (error = git_buf_printf(&reflog, "rebase: checkout %s", rebase_onto_name(onto))) < 0 || (error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE, - &onto->oid, 1, signature, reflog.ptr)) < 0 || + git_annotated_commit_id(onto), 1, signature, reflog.ptr)) < 0 || (error = git_checkout_head(repo, &checkout_opts)) < 0) goto done; diff --git a/tests/merge/merge_helpers.c b/tests/merge/merge_helpers.c index e3e703943..9a6ead984 100644 --- a/tests/merge/merge_helpers.c +++ b/tests/merge/merge_helpers.c @@ -6,6 +6,7 @@ #include "merge.h" #include "git2/merge.h" #include "git2/sys/index.h" +#include "git2/annotated_commit.h" int merge_trees_from_branches( git_index **index, git_repository *repo, @@ -84,7 +85,7 @@ int merge_branches(git_repository *repo, git_merge_options *merge_opts, git_checkout_options *checkout_opts) { git_reference *head_ref, *theirs_ref; - git_merge_head *theirs_head; + git_annotated_commit *theirs_head; git_checkout_options head_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; head_checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; @@ -93,13 +94,13 @@ int merge_branches(git_repository *repo, cl_git_pass(git_checkout_head(repo, &head_checkout_opts)); cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch)); - cl_git_pass(git_merge_head_from_ref(&theirs_head, repo, theirs_ref)); + cl_git_pass(git_annotated_commit_from_ref(&theirs_head, repo, theirs_ref)); - cl_git_pass(git_merge(repo, (const git_merge_head **)&theirs_head, 1, merge_opts, checkout_opts)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)&theirs_head, 1, merge_opts, checkout_opts)); git_reference_free(head_ref); git_reference_free(theirs_ref); - git_merge_head_free(theirs_head); + git_annotated_commit_free(theirs_head); return 0; } diff --git a/tests/merge/workdir/analysis.c b/tests/merge/workdir/analysis.c index 85918abe4..351cfbdd5 100644 --- a/tests/merge/workdir/analysis.c +++ b/tests/merge/workdir/analysis.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "git2/repository.h" #include "git2/merge.h" +#include "git2/annotated_commit.h" #include "git2/sys/index.h" #include "merge.h" #include "../merge_helpers.h" @@ -43,17 +44,17 @@ static void analysis_from_branch( { git_buf refname = GIT_BUF_INIT; git_reference *their_ref; - git_merge_head *their_head; + git_annotated_commit *their_head; git_buf_printf(&refname, "%s%s", GIT_REFS_HEADS_DIR, branchname); cl_git_pass(git_reference_lookup(&their_ref, repo, git_buf_cstr(&refname))); - cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_head, repo, their_ref)); - cl_git_pass(git_merge_analysis(merge_analysis, merge_pref, repo, (const git_merge_head **)&their_head, 1)); + cl_git_pass(git_merge_analysis(merge_analysis, merge_pref, repo, (const git_annotated_commit **)&their_head, 1)); git_buf_free(&refname); - git_merge_head_free(their_head); + git_annotated_commit_free(their_head); git_reference_free(their_ref); } diff --git a/tests/merge/workdir/dirty.c b/tests/merge/workdir/dirty.c index 0549b06b3..4b68b213b 100644 --- a/tests/merge/workdir/dirty.c +++ b/tests/merge/workdir/dirty.c @@ -89,18 +89,18 @@ static void set_core_autocrlf_to(git_repository *repo, bool value) static int merge_branch(void) { git_oid their_oids[1]; - git_merge_head *their_heads[1]; + git_annotated_commit *their_head; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_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])); + cl_git_pass(git_annotated_commit_lookup(&their_head, repo, &their_oids[0])); checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; - error = git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, &checkout_opts); + error = git_merge(repo, (const git_annotated_commit **)&their_head, 1, &merge_opts, &checkout_opts); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(their_head); return error; } diff --git a/tests/merge/workdir/setup.c b/tests/merge/workdir/setup.c index a0028ec6d..099bc1211 100644 --- a/tests/merge/workdir/setup.c +++ b/tests/merge/workdir/setup.c @@ -76,15 +76,15 @@ void test_merge_workdir_setup__one_branch(void) { git_oid our_oid; git_reference *octo1_ref; - git_merge_head *our_head, *their_heads[1]; + git_annotated_commit *our_head, *their_heads[1]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 1)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -93,8 +93,8 @@ void test_merge_workdir_setup__one_branch(void) git_reference_free(octo1_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); } /* git merge --no-ff 16f825815cfd20a07a75c71554e82d8eede0b061 */ @@ -102,23 +102,23 @@ void test_merge_workdir_setup__one_oid(void) { git_oid our_oid; git_oid octo1_oid; - git_merge_head *our_head, *their_heads[1]; + git_annotated_commit *our_head, *their_heads[1]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid)); cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid)); + cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &octo1_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 1)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'\n")); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); } /* git merge octo1 octo2 */ @@ -127,18 +127,18 @@ void test_merge_workdir_setup__two_branches(void) git_oid our_oid; git_reference *octo1_ref; git_reference *octo2_ref; - git_merge_head *our_head, *their_heads[2]; + git_annotated_commit *our_head, *their_heads[2]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); 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_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -148,9 +148,9 @@ void test_merge_workdir_setup__two_branches(void) git_reference_free(octo1_ref); git_reference_free(octo2_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); } /* git merge octo1 octo2 octo3 */ @@ -160,21 +160,21 @@ void test_merge_workdir_setup__three_branches(void) git_reference *octo1_ref; git_reference *octo2_ref; git_reference *octo3_ref; - git_merge_head *our_head, *their_heads[3]; + git_annotated_commit *our_head, *their_heads[3]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); 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_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref)); 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_annotated_commit_from_ref(&their_heads[2], repo, octo3_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 3)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -185,10 +185,10 @@ void test_merge_workdir_setup__three_branches(void) git_reference_free(octo2_ref); git_reference_free(octo3_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); } /* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 158dc7bedb202f5b26502bf3574faa7f4238d56c 50ce7d7d01217679e26c55939eef119e0c93e272 */ @@ -198,31 +198,31 @@ void test_merge_workdir_setup__three_oids(void) git_oid octo1_oid; git_oid octo2_oid; git_oid octo3_oid; - git_merge_head *our_head, *their_heads[3]; + git_annotated_commit *our_head, *their_heads[3]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid)); cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid)); + cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &octo1_oid)); cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_id(&their_heads[1], repo, &octo2_oid)); + cl_git_pass(git_annotated_commit_lookup(&their_heads[1], repo, &octo2_oid)); cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_id(&their_heads[2], repo, &octo3_oid)); + cl_git_pass(git_annotated_commit_lookup(&their_heads[2], repo, &octo3_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 3)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO2_OID "'; commit '" OCTO3_OID "'\n")); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); } /* git merge octo1 158dc7bedb202f5b26502bf3574faa7f4238d56c */ @@ -231,18 +231,18 @@ void test_merge_workdir_setup__branches_and_oids_1(void) git_oid our_oid; git_reference *octo1_ref; git_oid octo2_oid; - git_merge_head *our_head, *their_heads[2]; + git_annotated_commit *our_head, *their_heads[2]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_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_id(&their_heads[1], repo, &octo2_oid)); + cl_git_pass(git_annotated_commit_lookup(&their_heads[1], repo, &octo2_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -251,9 +251,9 @@ void test_merge_workdir_setup__branches_and_oids_1(void) git_reference_free(octo1_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); } /* git merge octo1 158dc7bedb202f5b26502bf3574faa7f4238d56c octo3 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae */ @@ -264,24 +264,24 @@ void test_merge_workdir_setup__branches_and_oids_2(void) git_oid octo2_oid; git_reference *octo3_ref; git_oid octo4_oid; - git_merge_head *our_head, *their_heads[4]; + git_annotated_commit *our_head, *their_heads[4]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_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_id(&their_heads[1], repo, &octo2_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_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_id(&their_heads[3], repo, &octo4_oid)); + cl_git_pass(git_annotated_commit_lookup(&their_heads[3], repo, &octo4_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 4)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -291,11 +291,11 @@ void test_merge_workdir_setup__branches_and_oids_2(void) git_reference_free(octo1_ref); git_reference_free(octo3_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); + git_annotated_commit_free(their_heads[3]); } /* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 octo2 50ce7d7d01217679e26c55939eef119e0c93e272 octo4 */ @@ -306,24 +306,24 @@ void test_merge_workdir_setup__branches_and_oids_3(void) git_reference *octo2_ref; git_oid octo3_oid; git_reference *octo4_ref; - git_merge_head *our_head, *their_heads[4]; + git_annotated_commit *our_head, *their_heads[4]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid)); cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_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_id(&their_heads[2], repo, &octo3_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[3], repo, octo4_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 4)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -333,11 +333,11 @@ void test_merge_workdir_setup__branches_and_oids_3(void) git_reference_free(octo2_ref); git_reference_free(octo4_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); + git_annotated_commit_free(their_heads[3]); } /* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 octo2 50ce7d7d01217679e26c55939eef119e0c93e272 octo4 octo5 */ @@ -349,27 +349,27 @@ void test_merge_workdir_setup__branches_and_oids_4(void) git_oid octo3_oid; git_reference *octo4_ref; git_reference *octo5_ref; - git_merge_head *our_head, *their_heads[5]; + git_annotated_commit *our_head, *their_heads[5]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid)); cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_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_id(&their_heads[2], repo, &octo3_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[3], repo, octo4_ref)); cl_git_pass(git_reference_lookup(&octo5_ref, repo, GIT_REFS_HEADS_DIR OCTO5_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[4], repo, octo5_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[4], repo, octo5_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 5)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 5)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n" OCTO5_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -380,12 +380,12 @@ void test_merge_workdir_setup__branches_and_oids_4(void) git_reference_free(octo4_ref); git_reference_free(octo5_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); - git_merge_head_free(their_heads[4]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); + git_annotated_commit_free(their_heads[3]); + git_annotated_commit_free(their_heads[4]); } /* git merge octo1 octo1 octo1 */ @@ -395,21 +395,21 @@ void test_merge_workdir_setup__three_same_branches(void) git_reference *octo1_1_ref; git_reference *octo1_2_ref; git_reference *octo1_3_ref; - git_merge_head *our_head, *their_heads[3]; + git_annotated_commit *our_head, *their_heads[3]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_1_ref)); cl_git_pass(git_reference_lookup(&octo1_2_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo1_2_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo1_2_ref)); cl_git_pass(git_reference_lookup(&octo1_3_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo1_3_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[2], repo, octo1_3_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 3)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -420,10 +420,10 @@ void test_merge_workdir_setup__three_same_branches(void) git_reference_free(octo1_2_ref); git_reference_free(octo1_3_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); } /* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 16f825815cfd20a07a75c71554e82d8eede0b061 16f825815cfd20a07a75c71554e82d8eede0b061 */ @@ -433,31 +433,31 @@ void test_merge_workdir_setup__three_same_oids(void) git_oid octo1_1_oid; git_oid octo1_2_oid; git_oid octo1_3_oid; - git_merge_head *our_head, *their_heads[3]; + git_annotated_commit *our_head, *their_heads[3]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&our_head, repo, &our_oid)); cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_1_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_id(&their_heads[1], repo, &octo1_2_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_id(&their_heads[2], repo, &octo1_3_oid)); + cl_git_pass(git_annotated_commit_lookup(&their_heads[2], repo, &octo1_3_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 3)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO1_OID "'; commit '" OCTO1_OID "'\n")); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); } static int create_remote_tracking_branch(const char *branch_name, const char *oid_str) @@ -508,17 +508,17 @@ void test_merge_workdir_setup__remote_tracking_one_branch(void) { git_oid our_oid; git_reference *octo1_ref; - git_merge_head *our_head, *their_heads[1]; + git_annotated_commit *our_head, *their_heads[1]; 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_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 1)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -527,8 +527,8 @@ void test_merge_workdir_setup__remote_tracking_one_branch(void) git_reference_free(octo1_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); } /* git merge refs/remotes/origin/octo1 refs/remotes/origin/octo2 */ @@ -537,21 +537,21 @@ void test_merge_workdir_setup__remote_tracking_two_branches(void) git_oid our_oid; git_reference *octo1_ref; git_reference *octo2_ref; - git_merge_head *our_head, *their_heads[2]; + git_annotated_commit *our_head, *their_heads[2]; cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); 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_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -561,9 +561,9 @@ void test_merge_workdir_setup__remote_tracking_two_branches(void) git_reference_free(octo1_ref); git_reference_free(octo2_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); } /* git merge refs/remotes/origin/octo1 refs/remotes/origin/octo2 refs/remotes/origin/octo3 */ @@ -573,25 +573,25 @@ void test_merge_workdir_setup__remote_tracking_three_branches(void) git_reference *octo1_ref; git_reference *octo2_ref; git_reference *octo3_ref; - git_merge_head *our_head, *their_heads[3]; + git_annotated_commit *our_head, *their_heads[3]; cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); 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_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref)); cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO3_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[2], repo, octo3_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 3)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -602,10 +602,10 @@ void test_merge_workdir_setup__remote_tracking_three_branches(void) git_reference_free(octo2_ref); git_reference_free(octo3_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); } /* git merge octo1 refs/remotes/origin/octo2 */ @@ -614,20 +614,20 @@ void test_merge_workdir_setup__normal_branch_and_remote_tracking_branch(void) git_oid our_oid; git_reference *octo1_ref; git_reference *octo2_ref; - git_merge_head *our_head, *their_heads[2]; + git_annotated_commit *our_head, *their_heads[2]; 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_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -637,9 +637,9 @@ void test_merge_workdir_setup__normal_branch_and_remote_tracking_branch(void) git_reference_free(octo1_ref); git_reference_free(octo2_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); } /* git merge refs/remotes/origin/octo1 octo2 */ @@ -648,20 +648,20 @@ void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void) git_oid our_oid; git_reference *octo1_ref; git_reference *octo2_ref; - git_merge_head *our_head, *their_heads[2]; + git_annotated_commit *our_head, *their_heads[2]; 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_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); 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_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -671,9 +671,9 @@ void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void) git_reference_free(octo1_ref); git_reference_free(octo2_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); } /* git merge octo1 refs/remotes/origin/octo2 octo3 refs/remotes/origin/octo4 */ @@ -684,27 +684,27 @@ void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branche git_reference *octo2_ref; git_reference *octo3_ref; git_reference *octo4_ref; - git_merge_head *our_head, *their_heads[4]; + git_annotated_commit *our_head, *their_heads[4]; cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); 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_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[1], repo, octo2_ref)); 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_annotated_commit_from_ref(&their_heads[2], repo, octo3_ref)); cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO4_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[3], repo, octo4_ref)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 4)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -716,11 +716,11 @@ void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branche git_reference_free(octo3_ref); git_reference_free(octo4_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); + git_annotated_commit_free(their_heads[3]); } /* git pull origin branch octo1 */ @@ -728,23 +728,23 @@ void test_merge_workdir_setup__pull_one(void) { git_oid our_oid; git_oid octo1_1_oid; - git_merge_head *our_head, *their_heads[1]; + git_annotated_commit *our_head, *their_heads[1]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_1_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 1)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch 'octo1' of http://remote.url/repo.git\n")); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); } /* git pull origin octo1 octo2 */ @@ -753,27 +753,27 @@ void test_merge_workdir_setup__pull_two(void) git_oid our_oid; git_oid octo1_oid; git_oid octo2_oid; - git_merge_head *our_head, *their_heads[2]; + git_annotated_commit *our_head, *their_heads[2]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid)); cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 2)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "' of http://remote.url/repo.git\n")); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); } /* git pull origin octo1 octo2 octo3 */ @@ -783,31 +783,31 @@ void test_merge_workdir_setup__pull_three(void) git_oid octo1_oid; git_oid octo2_oid; git_oid octo3_oid; - git_merge_head *our_head, *their_heads[3]; + git_annotated_commit *our_head, *their_heads[3]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid)); cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid)); cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.url/repo.git", &octo3_oid)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.url/repo.git", &octo3_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 3)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.url/repo.git\n")); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); } void test_merge_workdir_setup__three_remotes(void) @@ -816,31 +816,31 @@ void test_merge_workdir_setup__three_remotes(void) git_oid octo1_oid; git_oid octo2_oid; git_oid octo3_oid; - git_merge_head *our_head, *their_heads[3]; + git_annotated_commit *our_head, *their_heads[3]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid)); cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid)); cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.third/repo.git", &octo3_oid)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.third/repo.git", &octo3_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 3)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "' of http://remote.first/repo.git, branch '" OCTO2_BRANCH "' of http://remote.second/repo.git, branch '" OCTO3_BRANCH "' of http://remote.third/repo.git\n")); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); } void test_merge_workdir_setup__two_remotes(void) @@ -850,35 +850,35 @@ void test_merge_workdir_setup__two_remotes(void) git_oid octo2_oid; git_oid octo3_oid; git_oid octo4_oid; - git_merge_head *our_head, *their_heads[4]; + git_annotated_commit *our_head, *their_heads[4]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid)); cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid)); cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.first/repo.git", &octo3_oid)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.first/repo.git", &octo3_oid)); cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[3], repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH, "http://remote.second/repo.git", &octo4_oid)); + cl_git_pass(git_annotated_commit_from_fetchhead(&their_heads[3], repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH, "http://remote.second/repo.git", &octo4_oid)); - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4)); + cl_git_pass(git_merge__setup(repo, our_head, (const git_annotated_commit **)their_heads, 4)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.first/repo.git, branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "' of http://remote.second/repo.git\n")); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); + git_annotated_commit_free(their_heads[1]); + git_annotated_commit_free(their_heads[2]); + git_annotated_commit_free(their_heads[3]); } void test_merge_workdir_setup__id_from_head(void) @@ -886,39 +886,39 @@ void test_merge_workdir_setup__id_from_head(void) git_oid expected_id; const git_oid *id; git_reference *ref; - git_merge_head *heads[3]; + git_annotated_commit *heads[3]; cl_git_pass(git_oid_fromstr(&expected_id, OCTO1_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &expected_id)); - id = git_merge_head_id(heads[0]); + cl_git_pass(git_annotated_commit_from_fetchhead(&heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &expected_id)); + id = git_annotated_commit_id(heads[0]); cl_assert_equal_i(1, git_oid_equal(id, &expected_id)); - cl_git_pass(git_merge_head_from_id(&heads[1], repo, &expected_id)); - id = git_merge_head_id(heads[1]); + cl_git_pass(git_annotated_commit_lookup(&heads[1], repo, &expected_id)); + id = git_annotated_commit_id(heads[1]); cl_assert_equal_i(1, git_oid_equal(id, &expected_id)); cl_git_pass(git_reference_lookup(&ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&heads[2], repo, ref)); - id = git_merge_head_id(heads[2]); + cl_git_pass(git_annotated_commit_from_ref(&heads[2], repo, ref)); + id = git_annotated_commit_id(heads[2]); cl_assert_equal_i(1, git_oid_equal(id, &expected_id)); git_reference_free(ref); - git_merge_head_free(heads[0]); - git_merge_head_free(heads[1]); - git_merge_head_free(heads[2]); + git_annotated_commit_free(heads[0]); + git_annotated_commit_free(heads[1]); + git_annotated_commit_free(heads[2]); } -struct merge_head_cb_data { +struct annotated_commit_cb_data { const char **oid_str; unsigned int len; unsigned int i; }; -static int merge_head_foreach_cb(const git_oid *oid, void *payload) +static int annotated_commit_foreach_cb(const git_oid *oid, void *payload) { git_oid expected_oid; - struct merge_head_cb_data *cb_data = payload; + struct annotated_commit_cb_data *cb_data = payload; git_oid_fromstr(&expected_oid, cb_data->oid_str[cb_data->i]); cl_assert(git_oid_cmp(&expected_oid, oid) == 0); @@ -931,7 +931,7 @@ void test_merge_workdir_setup__head_notfound(void) int error; cl_git_fail((error = git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, NULL))); + annotated_commit_foreach_cb, NULL))); cl_assert(error == GIT_ENOTFOUND); } @@ -942,7 +942,7 @@ void test_merge_workdir_setup__head_invalid_oid(void) write_file_contents(GIT_MERGE_HEAD_FILE, "invalid-oid\n"); cl_git_fail((error = git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, NULL))); + annotated_commit_foreach_cb, NULL))); cl_assert(error == -1); } @@ -953,7 +953,7 @@ void test_merge_workdir_setup__head_foreach_nonewline(void) write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID); cl_git_fail((error = git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, NULL))); + annotated_commit_foreach_cb, NULL))); cl_assert(error == -1); } @@ -961,12 +961,12 @@ void test_merge_workdir_setup__head_foreach_one(void) { const char *expected = THEIRS_SIMPLE_OID; - struct merge_head_cb_data cb_data = { &expected, 1 }; + struct annotated_commit_cb_data cb_data = { &expected, 1 }; write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID "\n"); cl_git_pass(git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, &cb_data)); + annotated_commit_foreach_cb, &cb_data)); cl_assert(cb_data.i == cb_data.len); } @@ -976,7 +976,7 @@ void test_merge_workdir_setup__head_foreach_octopus(void) const char *expected[] = { THEIRS_SIMPLE_OID, OCTO1_OID, OCTO2_OID, OCTO3_OID, OCTO4_OID, OCTO5_OID }; - struct merge_head_cb_data cb_data = { expected, 6 }; + struct annotated_commit_cb_data cb_data = { expected, 6 }; write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID "\n" @@ -987,7 +987,7 @@ void test_merge_workdir_setup__head_foreach_octopus(void) OCTO5_OID "\n"); cl_git_pass(git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, &cb_data)); + annotated_commit_foreach_cb, &cb_data)); cl_assert(cb_data.i == cb_data.len); } @@ -996,16 +996,16 @@ void test_merge_workdir_setup__retained_after_success(void) { git_oid our_oid; git_reference *octo1_ref; - git_merge_head *our_head, *their_heads[1]; + git_annotated_commit *our_head, *their_heads[1]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); - cl_git_pass(git_merge(repo, (const git_merge_head **)&their_heads[0], 1, NULL, NULL)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)&their_heads[0], 1, NULL, NULL)); cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); @@ -1014,27 +1014,27 @@ void test_merge_workdir_setup__retained_after_success(void) git_reference_free(octo1_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); } void test_merge_workdir_setup__removed_after_failure(void) { git_oid our_oid; git_reference *octo1_ref; - git_merge_head *our_head, *their_heads[1]; + git_annotated_commit *our_head, *their_heads[1]; cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); + cl_git_pass(git_annotated_commit_lookup(&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_annotated_commit_from_ref(&their_heads[0], repo, octo1_ref)); cl_git_rewritefile("merge-resolve/new-in-octo1.txt", "Conflicting file!\n\nMerge will fail!\n"); cl_git_fail(git_merge( - repo, (const git_merge_head **)&their_heads[0], 1, NULL, NULL)); + repo, (const git_annotated_commit **)&their_heads[0], 1, NULL, NULL)); cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_HEAD_FILE)); cl_assert(!git_path_exists("merge-resolve/" GIT_ORIG_HEAD_FILE)); @@ -1043,6 +1043,6 @@ void test_merge_workdir_setup__removed_after_failure(void) git_reference_free(octo1_ref); - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(our_head); + git_annotated_commit_free(their_heads[0]); } diff --git a/tests/merge/workdir/simple.c b/tests/merge/workdir/simple.c index fcd84dcd1..df531f48f 100644 --- a/tests/merge/workdir/simple.c +++ b/tests/merge/workdir/simple.c @@ -95,20 +95,20 @@ void test_merge_workdir_simple__cleanup(void) static void merge_simple_branch(int merge_file_favor, int addl_checkout_strategy) { git_oid their_oids[1]; - git_merge_head *their_heads[1]; + git_annotated_commit *their_heads[1]; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_SIMPLE_OID)); - cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); + cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &their_oids[0])); merge_opts.file_favor = merge_file_favor; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS | addl_checkout_strategy; - cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, &checkout_opts)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)their_heads, 1, &merge_opts, &checkout_opts)); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(their_heads[0]); } static void set_core_autocrlf_to(git_repository *repo, bool value) @@ -486,7 +486,7 @@ void test_merge_workdir_simple__directory_file(void) { git_reference *head; git_oid their_oids[1], head_commit_id; - git_merge_head *their_heads[1]; + git_annotated_commit *their_heads[1]; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT; git_commit *head_commit; @@ -519,22 +519,22 @@ void test_merge_workdir_simple__directory_file(void) cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD, NULL, NULL, NULL)); cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_DIRECTORY_FILE)); - cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); + cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &their_oids[0])); merge_opts.file_favor = 0; - cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, NULL)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)their_heads, 1, &merge_opts, NULL)); cl_assert(merge_test_index(repo_index, merge_index_entries, 20)); git_reference_free(head); git_commit_free(head_commit); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(their_heads[0]); } void test_merge_workdir_simple__unrelated(void) { git_oid their_oids[1]; - git_merge_head *their_heads[1]; + git_annotated_commit *their_heads[1]; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT; struct merge_index_entry merge_index_entries[] = { @@ -550,20 +550,20 @@ 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_id(&their_heads[0], repo, &their_oids[0])); + cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &their_oids[0])); merge_opts.file_favor = 0; - cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, NULL)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)their_heads, 1, &merge_opts, NULL)); cl_assert(merge_test_index(repo_index, merge_index_entries, 9)); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(their_heads[0]); } void test_merge_workdir_simple__unrelated_with_conflicts(void) { git_oid their_oids[1]; - git_merge_head *their_heads[1]; + git_annotated_commit *their_heads[1]; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT; struct merge_index_entry merge_index_entries[] = { @@ -581,21 +581,21 @@ 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_id(&their_heads[0], repo, &their_oids[0])); + cl_git_pass(git_annotated_commit_lookup(&their_heads[0], repo, &their_oids[0])); merge_opts.file_favor = 0; - cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, NULL)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)their_heads, 1, &merge_opts, NULL)); cl_assert(merge_test_index(repo_index, merge_index_entries, 11)); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(their_heads[0]); } 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_annotated_commit *their_head; const git_index_entry *binary_entry; struct merge_index_entry merge_index_entries[] = { @@ -610,9 +610,9 @@ void test_merge_workdir_simple__binary(void) cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid)); cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL, NULL)); - cl_git_pass(git_merge_head_from_id(&their_head, repo, &their_oid)); + cl_git_pass(git_annotated_commit_lookup(&their_head, repo, &their_oid)); - cl_git_pass(git_merge(repo, (const git_merge_head **)&their_head, 1, NULL, NULL)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)&their_head, 1, NULL, NULL)); cl_assert(merge_test_index(repo_index, merge_index_entries, 3)); @@ -622,6 +622,6 @@ void test_merge_workdir_simple__binary(void) 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_annotated_commit_free(their_head); git_commit_free(our_commit); } diff --git a/tests/merge/workdir/submodules.c b/tests/merge/workdir/submodules.c index eec9f14a9..31ded4662 100644 --- a/tests/merge/workdir/submodules.c +++ b/tests/merge/workdir/submodules.c @@ -30,7 +30,7 @@ void test_merge_workdir_submodules__automerge(void) { git_reference *our_ref, *their_ref; git_commit *our_commit; - git_merge_head *their_head; + git_annotated_commit *their_head; git_index *index; struct merge_index_entry merge_index_entries[] = { @@ -47,15 +47,15 @@ void test_merge_workdir_submodules__automerge(void) cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL, NULL)); 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_annotated_commit_from_ref(&their_head, repo, their_ref)); - cl_git_pass(git_merge(repo, (const git_merge_head **)&their_head, 1, NULL, NULL)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)&their_head, 1, NULL, NULL)); cl_git_pass(git_repository_index(&index, repo)); cl_assert(merge_test_index(index, merge_index_entries, 6)); git_index_free(index); - git_merge_head_free(their_head); + git_annotated_commit_free(their_head); git_commit_free(our_commit); git_reference_free(their_ref); git_reference_free(our_ref); @@ -65,7 +65,7 @@ void test_merge_workdir_submodules__take_changed(void) { git_reference *our_ref, *their_ref; git_commit *our_commit; - git_merge_head *their_head; + git_annotated_commit *their_head; git_index *index; struct merge_index_entry merge_index_entries[] = { @@ -80,15 +80,15 @@ void test_merge_workdir_submodules__take_changed(void) cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD, NULL, NULL, NULL)); 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_annotated_commit_from_ref(&their_head, repo, their_ref)); - cl_git_pass(git_merge(repo, (const git_merge_head **)&their_head, 1, NULL, NULL)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)&their_head, 1, NULL, NULL)); cl_git_pass(git_repository_index(&index, repo)); cl_assert(merge_test_index(index, merge_index_entries, 4)); git_index_free(index); - git_merge_head_free(their_head); + git_annotated_commit_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 cc82d990c..fa261c3a1 100644 --- a/tests/merge/workdir/trivial.c +++ b/tests/merge/workdir/trivial.c @@ -33,7 +33,7 @@ static int merge_trivial(const char *ours, const char *theirs) git_buf branch_buf = GIT_BUF_INIT; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_reference *our_ref, *their_ref; - git_merge_head *their_heads[1]; + git_annotated_commit *their_heads[1]; checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; @@ -45,14 +45,14 @@ static int merge_trivial(const char *ours, const char *theirs) git_buf_clear(&branch_buf); git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs); cl_git_pass(git_reference_lookup(&their_ref, repo, branch_buf.ptr)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); + cl_git_pass(git_annotated_commit_from_ref(&their_heads[0], repo, their_ref)); - cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, NULL, NULL)); + cl_git_pass(git_merge(repo, (const git_annotated_commit **)their_heads, 1, NULL, NULL)); git_buf_free(&branch_buf); git_reference_free(our_ref); git_reference_free(their_ref); - git_merge_head_free(their_heads[0]); + git_annotated_commit_free(their_heads[0]); return 0; } diff --git a/tests/rebase/abort.c b/tests/rebase/abort.c index c6d27f19d..71326433f 100644 --- a/tests/rebase/abort.c +++ b/tests/rebase/abort.c @@ -2,6 +2,7 @@ #include "git2/rebase.h" #include "merge.h" #include "posix.h" +#include "annotated_commit.h" #include @@ -18,7 +19,7 @@ void test_rebase_abort__cleanup(void) cl_git_sandbox_cleanup(); } -static void test_abort(git_merge_head *branch, git_merge_head *onto) +static void test_abort(git_annotated_commit *branch, git_annotated_commit *onto) { git_rebase *rebase; git_reference *head_ref, *branch_ref = NULL; @@ -37,11 +38,11 @@ static void test_abort(git_merge_head *branch, git_merge_head *onto) cl_git_pass(git_reference_lookup(&head_ref, repo, "HEAD")); if (branch->ref_name == NULL) - cl_assert_equal_oid(git_merge_head_id(branch), git_reference_target(head_ref)); + cl_assert_equal_oid(git_annotated_commit_id(branch), git_reference_target(head_ref)); else { cl_assert_equal_s("refs/heads/beef", git_reference_symbolic_target(head_ref)); cl_git_pass(git_reference_lookup(&branch_ref, repo, git_reference_symbolic_target(head_ref))); - cl_assert_equal_oid(git_merge_head_id(branch), git_reference_target(branch_ref)); + cl_assert_equal_oid(git_annotated_commit_id(branch), git_reference_target(branch_ref)); } git_status_list_new(&statuslist, repo, NULL); @@ -52,8 +53,8 @@ static void test_abort(git_merge_head *branch, git_merge_head *onto) cl_git_pass(git_reflog_read(&reflog, repo, "HEAD")); cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0)); - cl_assert_equal_oid(git_merge_head_id(onto), git_reflog_entry_id_old(reflog_entry)); - cl_assert_equal_oid(git_merge_head_id(branch), git_reflog_entry_id_new(reflog_entry)); + cl_assert_equal_oid(git_annotated_commit_id(onto), git_reflog_entry_id_old(reflog_entry)); + cl_assert_equal_oid(git_annotated_commit_id(branch), git_reflog_entry_id_new(reflog_entry)); cl_assert_equal_s("rebase: aborting", git_reflog_entry_message(reflog_entry)); git_reflog_free(reflog); @@ -68,13 +69,13 @@ void test_rebase_abort__merge(void) git_rebase *rebase; git_reference *branch_ref, *onto_ref; git_signature *signature; - git_merge_head *branch_head, *onto_head; + git_annotated_commit *branch_head, *onto_head; cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&onto_head, repo, onto_ref)); cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); @@ -85,8 +86,8 @@ void test_rebase_abort__merge(void) git_signature_free(signature); - git_merge_head_free(branch_head); - git_merge_head_free(onto_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(onto_head); git_reference_free(branch_ref); git_reference_free(onto_ref); @@ -99,13 +100,13 @@ void test_rebase_abort__detached_head(void) git_oid branch_id; git_reference *onto_ref; git_signature *signature; - git_merge_head *branch_head, *onto_head; + git_annotated_commit *branch_head, *onto_head; git_oid_fromstr(&branch_id, "b146bd7608eac53d9bf9e1a6963543588b555c64"); cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_id(&branch_head, repo, &branch_id)); - cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + cl_git_pass(git_annotated_commit_lookup(&branch_head, repo, &branch_id)); + cl_git_pass(git_annotated_commit_from_ref(&onto_head, repo, onto_ref)); cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); @@ -116,8 +117,8 @@ void test_rebase_abort__detached_head(void) git_signature_free(signature); - git_merge_head_free(branch_head); - git_merge_head_free(onto_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(onto_head); git_reference_free(onto_ref); git_rebase_free(rebase); @@ -128,13 +129,13 @@ void test_rebase_abort__old_style_head_file(void) git_rebase *rebase; git_reference *branch_ref, *onto_ref; git_signature *signature; - git_merge_head *branch_head, *onto_head; + git_annotated_commit *branch_head, *onto_head; cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&onto_head, repo, onto_ref)); cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); @@ -148,8 +149,8 @@ void test_rebase_abort__old_style_head_file(void) git_signature_free(signature); - git_merge_head_free(branch_head); - git_merge_head_free(onto_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(onto_head); git_reference_free(branch_ref); git_reference_free(onto_ref); diff --git a/tests/rebase/iterator.c b/tests/rebase/iterator.c index cfc6dce7b..ddf4413d3 100644 --- a/tests/rebase/iterator.c +++ b/tests/rebase/iterator.c @@ -49,7 +49,7 @@ void test_rebase_iterator__iterates(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; @@ -60,8 +60,8 @@ void test_rebase_iterator__iterates(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); test_operations(rebase, 0); @@ -100,8 +100,8 @@ void test_rebase_iterator__iterates(void) cl_assert_equal_i(GIT_ITEROVER, error); test_operations(rebase, 4); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c index 80ca88b09..e7eb16713 100644 --- a/tests/rebase/merge.c +++ b/tests/rebase/merge.c @@ -26,7 +26,7 @@ void test_rebase_merge__next(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_status_list *status_list; @@ -38,8 +38,8 @@ void test_rebase_merge__next(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -62,8 +62,8 @@ void test_rebase_merge__next(void) cl_assert_equal_oid(&file1_id, &status_entry->head_to_index->new_file.id); git_status_list_free(status_list); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); @@ -73,7 +73,7 @@ void test_rebase_merge__next_with_conflicts(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_status_list *status_list; @@ -105,8 +105,8 @@ void test_rebase_merge__next_with_conflicts(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/asparagus")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -128,8 +128,8 @@ void test_rebase_merge__next_with_conflicts(void) cl_assert_equal_file(expected_merge, strlen(expected_merge), "rebase/asparagus.txt"); git_status_list_free(status_list); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); @@ -139,7 +139,7 @@ void test_rebase_merge__next_stops_with_iterover(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; @@ -150,8 +150,8 @@ void test_rebase_merge__next_stops_with_iterover(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -181,8 +181,8 @@ void test_rebase_merge__next_stops_with_iterover(void) cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/msgnum"); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); @@ -192,7 +192,7 @@ void test_rebase_merge__commit(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id, tree_id, parent_id; @@ -206,8 +206,8 @@ void test_rebase_merge__commit(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -243,8 +243,8 @@ void test_rebase_merge__commit(void) git_reflog_free(reflog); git_signature_free(author); git_commit_free(commit); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); @@ -254,7 +254,7 @@ void test_rebase_merge__commit_updates_rewritten(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; @@ -264,8 +264,8 @@ void test_rebase_merge__commit_updates_rewritten(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -282,8 +282,8 @@ void test_rebase_merge__commit_updates_rewritten(void) "8d1f13f93c4995760ac07d129246ac1ff64c0be9 ba1f9b4fd5cf8151f7818be2111cc0869f1eb95a\n", 164, "rebase/.git/rebase-merge/rewritten"); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); @@ -293,7 +293,7 @@ void test_rebase_merge__commit_drops_already_applied(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; @@ -304,8 +304,8 @@ void test_rebase_merge__commit_drops_already_applied(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/green_pea")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -323,8 +323,8 @@ void test_rebase_merge__commit_drops_already_applied(void) "8d1f13f93c4995760ac07d129246ac1ff64c0be9 2ac4fb7b74c1287f6c792acad759e1ec01e18dae\n", 82, "rebase/.git/rebase-merge/rewritten"); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); @@ -334,7 +334,7 @@ void test_rebase_merge__finish(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref, *head_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid commit_id; @@ -347,8 +347,8 @@ void test_rebase_merge__finish(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -377,13 +377,13 @@ void test_rebase_merge__finish(void) cl_git_pass(git_reflog_read(&reflog, repo, "refs/heads/gravy")); cl_assert(reflog_entry = git_reflog_entry_byindex(reflog, 0)); - cl_assert_equal_oid(git_merge_head_id(branch_head), git_reflog_entry_id_old(reflog_entry)); + cl_assert_equal_oid(git_annotated_commit_id(branch_head), git_reflog_entry_id_old(reflog_entry)); cl_assert_equal_oid(&commit_id, git_reflog_entry_id_new(reflog_entry)); cl_assert_equal_s("rebase finished: refs/heads/gravy onto f87d14a4a236582a0278a916340a793714256864", git_reflog_entry_message(reflog_entry)); git_reflog_free(reflog); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(head_ref); git_reference_free(branch_ref); git_reference_free(upstream_ref); @@ -396,7 +396,7 @@ static void test_copy_note( { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_commit *branch_commit; git_rebase_operation *rebase_operation; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; @@ -409,8 +409,8 @@ static void test_copy_note( cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_reference_peel((git_object **)&branch_commit, branch_ref, GIT_OBJ_COMMIT)); @@ -442,8 +442,8 @@ static void test_copy_note( git_note_free(note); git_commit_free(branch_commit); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); diff --git a/tests/rebase/setup.c b/tests/rebase/setup.c index e72075a88..c81ca1245 100644 --- a/tests/rebase/setup.c +++ b/tests/rebase/setup.c @@ -29,15 +29,15 @@ void test_rebase_setup__blocked_when_in_progress(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); git_rebase_free(rebase); @@ -46,8 +46,8 @@ void test_rebase_setup__blocked_when_in_progress(void) cl_git_fail(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); } @@ -57,7 +57,7 @@ void test_rebase_setup__merge(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_reference *head; git_commit *head_commit; git_oid head_id; @@ -67,8 +67,8 @@ void test_rebase_setup__merge(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -93,8 +93,8 @@ void test_rebase_setup__merge(void) git_commit_free(head_commit); git_reference_free(head); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); @@ -105,7 +105,7 @@ void test_rebase_setup__merge_root(void) { git_rebase *rebase; git_reference *branch_ref, *onto_ref; - git_merge_head *branch_head, *onto_head; + git_annotated_commit *branch_head, *onto_head; git_reference *head; git_commit *head_commit; git_oid head_id; @@ -115,8 +115,8 @@ void test_rebase_setup__merge_root(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&onto_head, repo, onto_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, NULL, onto_head, signature, NULL)); @@ -141,8 +141,8 @@ void test_rebase_setup__merge_root(void) git_commit_free(head_commit); git_reference_free(head); - git_merge_head_free(branch_head); - git_merge_head_free(onto_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(onto_head); git_reference_free(branch_ref); git_reference_free(onto_ref); git_rebase_free(rebase); @@ -153,7 +153,7 @@ void test_rebase_setup__merge_onto_and_upstream(void) { git_rebase *rebase; git_reference *branch1_ref, *branch2_ref, *onto_ref; - git_merge_head *branch1_head, *branch2_head, *onto_head; + git_annotated_commit *branch1_head, *branch2_head, *onto_head; git_reference *head; git_commit *head_commit; git_oid head_id; @@ -164,9 +164,9 @@ void test_rebase_setup__merge_onto_and_upstream(void) cl_git_pass(git_reference_lookup(&branch2_ref, repo, "refs/heads/veal")); cl_git_pass(git_reference_lookup(&onto_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch1_head, repo, branch1_ref)); - cl_git_pass(git_merge_head_from_ref(&branch2_head, repo, branch2_ref)); - cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch1_head, repo, branch1_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch2_head, repo, branch2_ref)); + cl_git_pass(git_annotated_commit_from_ref(&onto_head, repo, onto_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch1_head, branch2_head, onto_head, signature, NULL)); @@ -187,9 +187,9 @@ void test_rebase_setup__merge_onto_and_upstream(void) git_commit_free(head_commit); git_reference_free(head); - git_merge_head_free(branch1_head); - git_merge_head_free(branch2_head); - git_merge_head_free(onto_head); + git_annotated_commit_free(branch1_head); + git_annotated_commit_free(branch2_head); + git_annotated_commit_free(onto_head); git_reference_free(branch1_ref); git_reference_free(branch2_ref); git_reference_free(onto_ref); @@ -202,7 +202,7 @@ void test_rebase_setup__branch_with_merges(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_reference *head; git_commit *head_commit; git_oid head_id; @@ -212,8 +212,8 @@ void test_rebase_setup__branch_with_merges(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/veal")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -238,8 +238,8 @@ void test_rebase_setup__branch_with_merges(void) git_commit_free(head_commit); git_reference_free(head); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); @@ -250,7 +250,7 @@ void test_rebase_setup__orphan_branch(void) { git_rebase *rebase; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; git_reference *head; git_commit *head_commit; git_oid head_id; @@ -260,8 +260,8 @@ void test_rebase_setup__orphan_branch(void) cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/barley")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL)); @@ -286,8 +286,8 @@ void test_rebase_setup__orphan_branch(void) git_commit_free(head_commit); git_reference_free(head); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); git_rebase_free(rebase); @@ -299,20 +299,20 @@ static int rebase_is_blocked(void) int error; git_reference *branch_ref, *upstream_ref; - git_merge_head *branch_head, *upstream_head; + git_annotated_commit *branch_head, *upstream_head; cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); - cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); - cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref)); + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); error = git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL); - git_merge_head_free(branch_head); - git_merge_head_free(upstream_head); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); git_reference_free(branch_ref); git_reference_free(upstream_ref); From 979645a7195b8ce9895c18ee00c8913ea38f93eb Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 4 Oct 2014 20:17:26 -0400 Subject: [PATCH 20/21] rebase: updates based on PR comments --- include/git2.h | 1 + include/git2/rebase.h | 32 ++++++++++++++--------------- src/rebase.c | 48 ++++++++++++++++++++++++++++--------------- 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/include/git2.h b/include/git2.h index 5e032b2bf..41adbbad2 100644 --- a/include/git2.h +++ b/include/git2.h @@ -40,6 +40,7 @@ #include "git2/patch.h" #include "git2/pathspec.h" #include "git2/push.h" +#include "git2/rebase.h" #include "git2/refdb.h" #include "git2/reflog.h" #include "git2/refs.h" diff --git a/include/git2/rebase.h b/include/git2/rebase.h index 24d8fcf71..095975edb 100644 --- a/include/git2/rebase.h +++ b/include/git2/rebase.h @@ -84,21 +84,19 @@ typedef enum { typedef struct { /** The type of rebase operation. */ - unsigned int type; + git_rebase_operation_t type; - union { - /** - * The commit ID being cherry-picked. This will be populated for - * all operations except those of type `GIT_REBASE_OPERATION_EXEC`. - */ - const git_oid id; + /** + * The commit ID being cherry-picked. This will be populated for + * all operations except those of type `GIT_REBASE_OPERATION_EXEC`. + */ + const git_oid id; - /** - * The executable the user has requested be run. This will only - * be populated for operations of type `GIT_REBASE_OPERATION_EXEC`. - */ - const char *exec; - }; + /** + * The executable the user has requested be run. This will only + * be populated for operations of type `GIT_REBASE_OPERATION_EXEC`. + */ + const char *exec; } git_rebase_operation; /** @@ -115,7 +113,7 @@ GIT_EXTERN(int) git_rebase_init_options( unsigned int version); /** - * Initializes a rebase operation to rebase the changes in `ours` + * Initializes a rebase operation to rebase the changes in `branch` * relative to `upstream` onto another branch. To begin the rebase * process, call `git_rebase_next`. When you have finished with this * object, call `git_rebase_free`. @@ -127,7 +125,7 @@ GIT_EXTERN(int) git_rebase_init_options( * reachable commits * @param onto The branch to rebase onto, or NULL to rebase onto the given * upstream - * @param signature The signature of the rebaser + * @param signature The signature of the rebaser (optional) * @param opts Options to specify how rebase is performed * @return Zero on success; -1 on failure. */ @@ -242,7 +240,7 @@ GIT_EXTERN(int) git_rebase_abort( * been applied. * * @param rebase The rebase that is in-progress - * @param signature The identity that is finishing the rebase + * @param signature The identity that is finishing the rebase (optional) * @param opts Options to specify how rebase is finished * @param Zero on success; -1 on error */ @@ -254,7 +252,7 @@ GIT_EXTERN(int) git_rebase_finish( /** * Frees the `git_rebase` object. * - * @param rebase The rebase that is in-progress + * @param rebase The rebase object */ GIT_EXTERN(void) git_rebase_free(git_rebase *rebase); diff --git a/src/rebase.c b/src/rebase.c index 6905d17dd..6453ecc67 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -23,28 +23,28 @@ #include #include -#define REBASE_APPLY_DIR "rebase-apply" -#define REBASE_MERGE_DIR "rebase-merge" +#define REBASE_APPLY_DIR "rebase-apply" +#define REBASE_MERGE_DIR "rebase-merge" -#define HEAD_NAME_FILE "head-name" -#define ORIG_HEAD_FILE "orig-head" -#define HEAD_FILE "head" -#define ONTO_FILE "onto" -#define ONTO_NAME_FILE "onto_name" -#define QUIET_FILE "quiet" +#define HEAD_NAME_FILE "head-name" +#define ORIG_HEAD_FILE "orig-head" +#define HEAD_FILE "head" +#define ONTO_FILE "onto" +#define ONTO_NAME_FILE "onto_name" +#define QUIET_FILE "quiet" -#define MSGNUM_FILE "msgnum" -#define END_FILE "end" -#define CMT_FILE_FMT "cmt.%" PRIuZ -#define CURRENT_FILE "current" -#define REWRITTEN_FILE "rewritten" +#define MSGNUM_FILE "msgnum" +#define END_FILE "end" +#define CMT_FILE_FMT "cmt.%" PRIuZ +#define CURRENT_FILE "current" +#define REWRITTEN_FILE "rewritten" -#define ORIG_DETACHED_HEAD "detached HEAD" +#define ORIG_DETACHED_HEAD "detached HEAD" -#define NOTES_DEFAULT_REF NULL +#define NOTES_DEFAULT_REF NULL -#define REBASE_DIR_MODE 0777 -#define REBASE_FILE_MODE 0666 +#define REBASE_DIR_MODE 0777 +#define REBASE_FILE_MODE 0666 typedef enum { GIT_REBASE_TYPE_NONE = 0, @@ -948,6 +948,7 @@ static int rebase_copy_note( { git_note *note = NULL; git_oid note_id; + git_signature *who = NULL; int error; if ((error = git_note_read(¬e, rebase->repo, opts->rewrite_notes_ref, from)) < 0) { @@ -959,11 +960,24 @@ static int rebase_copy_note( goto done; } + if (!committer) { + if((error = git_signature_default(&who, rebase->repo)) < 0) { + if (error != GIT_ENOTFOUND || + (error = git_signature_now(&who, "unknown", "unknown")) < 0) + goto done; + + giterr_clear(); + } + + committer = who; + } + error = git_note_create(¬e_id, rebase->repo, git_note_author(note), committer, opts->rewrite_notes_ref, to, git_note_message(note), 0); done: git_note_free(note); + git_signature_free(who); return error; } From 679172812c47de5af01fd1c9987dee855dfa9b08 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 26 Oct 2014 22:37:01 -0400 Subject: [PATCH 21/21] rebase: add information to the CHANGELOG --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e076dd5ab..93b189c05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -90,3 +90,17 @@ v0.21 + 1 * Introduce git_merge_bases_many() to expose all merge bases between multiple commits. + +* git_merge_head is now git_annotated_commit, to better reflect its usage + for multiple functions (including rebase) + +* Introduce rebase functionality (using the merge algorithm only). + Introduce git_rebase_init() to begin a new rebase session, + git_rebase_open() to open an in-progress rebase session, + git_rebase_commit() to commit the current rebase operation, + git_rebase_next() to apply the next rebase operation, + git_rebase_abort() to abort an in-progress rebase and git_rebase_finish() + to complete a rebase operation. + +* Introduce git_note_author() and git_note_committer() to get the author + and committer information on a git_note, respectively.