summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2014-10-26 20:18:04 -0700
committerEdward Thomson <ethomson@edwardthomson.com>2014-10-26 20:18:04 -0700
commitb07db1eb7696c1ef71f122c2103780c7bb55ed47 (patch)
treefcb7668ff57891355fb50c8837f6fbb1d31cb245
parent9e44289c8dfece4171c7f272389b14d040c72228 (diff)
parent679172812c47de5af01fd1c9987dee855dfa9b08 (diff)
downloadlibgit2-b07db1eb7696c1ef71f122c2103780c7bb55ed47.tar.gz
Merge pull request #2482 from libgit2/ed/rebase
Rebase (merge)
-rw-r--r--CHANGELOG.md14
-rw-r--r--include/git2.h2
-rw-r--r--include/git2/annotated_commit.h99
-rw-r--r--include/git2/errors.h2
-rw-r--r--include/git2/merge.h68
-rw-r--r--include/git2/notes.h17
-rw-r--r--include/git2/rebase.h261
-rw-r--r--include/git2/reset.h2
-rw-r--r--include/git2/types.h6
-rw-r--r--src/annotated_commit.c121
-rw-r--r--src/annotated_commit.h22
-rw-r--r--src/commit.c36
-rw-r--r--src/merge.c209
-rw-r--r--src/merge.h14
-rw-r--r--src/notes.c35
-rw-r--r--src/notes.h3
-rw-r--r--src/rebase.c1125
-rw-r--r--src/refs.c35
-rw-r--r--src/refs.h9
-rw-r--r--src/repository.c22
-rw-r--r--src/repository.h2
-rw-r--r--src/reset.c2
-rw-r--r--src/signature.c11
-rw-r--r--src/signature.h1
-rw-r--r--tests/merge/merge_helpers.c9
-rw-r--r--tests/merge/workdir/analysis.c9
-rw-r--r--tests/merge/workdir/dirty.c8
-rw-r--r--tests/merge/workdir/setup.c472
-rw-r--r--tests/merge/workdir/simple.c40
-rw-r--r--tests/merge/workdir/submodules.c16
-rw-r--r--tests/merge/workdir/trivial.c8
-rw-r--r--tests/rebase/abort.c158
-rw-r--r--tests/rebase/iterator.c108
-rw-r--r--tests/rebase/merge.c487
-rw-r--r--tests/rebase/setup.c342
-rw-r--r--tests/resources/rebase/.gitted/HEAD1
-rw-r--r--tests/resources/rebase/.gitted/config4
-rw-r--r--tests/resources/rebase/.gitted/indexbin0 -> 488 bytes
-rw-r--r--tests/resources/rebase/.gitted/info/exclude6
-rw-r--r--tests/resources/rebase/.gitted/logs/HEAD1
-rw-r--r--tests/resources/rebase/.gitted/objects/00/66204dd469ee930e551fbcf123f98e211c99cebin0 -> 806 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/00/f1b9a0948a7d5d14405eba6030efcdfbb8ff4a3
-rw-r--r--tests/resources/rebase/.gitted/objects/01/3cc32d341bab0e6f039f50f153c18986f16c58bin0 -> 175 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/01/a17f7d154ab5bf9f8bfede3d82dd00ddf7e7dcbin0 -> 370 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/02/2d3b6bbd0bfbdf147319476fb8bf405691cb0dbin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177acbin0 -> 241 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/0e/f2e2b2a2b8d6e1f8dff5e621e0eca21b693d0c3
-rw-r--r--tests/resources/rebase/.gitted/objects/0f/5f6d3353be1a9966fa5767b7d604b051798224bin0 -> 183 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/11/fac10ca1b9318ce361a0be0c3d889d777e299cbin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/12/c084412b952396962eb420716df01022b847cc2
-rw-r--r--tests/resources/rebase/.gitted/objects/12/f28ed978639d331269d9dc2b74e87db58e10573
-rw-r--r--tests/resources/rebase/.gitted/objects/19/14d57ddf6c5c997664521cc94f190df46dc1c2bin0 -> 277 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/1b/1d19799fcc89fa3cb821581fcf7f2e8fd2cc4dbin0 -> 178 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/1f/2214c1b13b134d5508f41f6a3b77cc6a8f5182bin0 -> 209 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/20/db906c85e78c6dde82eb2ec6d3231c4b96fce8bin0 -> 796 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/22/adb22bef75a0371e85ff6d82e5e60e4b425501bin0 -> 380 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/2a/a3ce842094e08ebac152b3d6d5b0fff39f9c6e1
-rw-r--r--tests/resources/rebase/.gitted/objects/2b/4ebffd3111546d278bb5df62e5630930b605fbbin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/30/69cc907e6294623e5917ef6de663928c1febfb1
-rw-r--r--tests/resources/rebase/.gitted/objects/32/52a0692ace4c4c709f22011227d9dc4845f289bin0 -> 209 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/33/f915f9e4dbd9f4b24430e48731a59b45b155001
-rw-r--r--tests/resources/rebase/.gitted/objects/34/86a9d4cdf0b7b4a702c199eed541dc3af13a031
-rw-r--r--tests/resources/rebase/.gitted/objects/3c/33b080bf75724c8899d8e703614cb59bfbd047bin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/3d/a85aca38a95b44d77ef55a8deb445e49ba19b4bin0 -> 55 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/3e/8989b5a16d5258c935d998ef0e6bb139cc47572
-rw-r--r--tests/resources/rebase/.gitted/objects/3f/05a038dd89f51ba2b3d7b14ba1f8c00f0e31acbin0 -> 209 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/3f/d8d53cf02de539b9a25a5941030451f76a152fbin0 -> 89 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/40/0d89e8ee6cd91b67b1f45de1ca190e1c580c6f1
-rw-r--r--tests/resources/rebase/.gitted/objects/41/4dfc71ead79c07acd4ea47fecf91f289afc4b9bin0 -> 376 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/41/c5a0a761bb4a7670924c1af0800b30fe9a21bebin0 -> 384 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911bin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/44/c801fe026abbc141b52a4dec5df15fa98249c6bin0 -> 367 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/4b/21eb6eeeec7f8fc89a1d334faff9bd5f5f8c342
-rw-r--r--tests/resources/rebase/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850abin0 -> 615 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/4b/ed71df7017283cac61bbf726197ad6a5a18b842
-rw-r--r--tests/resources/rebase/.gitted/objects/4c/acc6f6e740a5bc64faa33e04b8ef0733d8a127bin0 -> 169 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/4f/b698bde45d7d2833e3f2aacfbfe8a7e7f60a65bin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/50/8be4ff49d38465ad3de58f66d38f70e59f881fbin0 -> 241 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/53/f75e45a463033854e52fa8d39dc858e45537d0bin0 -> 209 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/58/8e5d2f04d49707fe4aab865e1deacaf7ef67871
-rw-r--r--tests/resources/rebase/.gitted/objects/5b/1e8bccf7787e942aecf61912f94a2c274f85a5bin0 -> 368 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/60/29cb003b59f710f9a8ebd9da9ece2d73070b69bin0 -> 655 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/61/139b9b40a3e489f4abbc6af14e10ae14006e47bin0 -> 224 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/61/30e5fcbdce2aa8b3cfd84706c58a892e7d8dd0bin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/63/c18bf188b8a1ab0bad85161dc3fb43c48ed0dbbin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/67/ed7afb256807556f9b74fa4f7c9284aaec1120bin0 -> 391 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/68/af1fc7407fd9addf1701a87eb1c95c7494c598bin0 -> 443 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/68/f6182f4c85d39e1309d97c7e456156dc9c0096bin0 -> 755 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/6c/8e16469b6ca09a07e00f0e07a5143c31dcfb641
-rw-r--r--tests/resources/rebase/.gitted/objects/6d/77ce8fa2cd93c6489236e33e45e35203ca748c1
-rw-r--r--tests/resources/rebase/.gitted/objects/6d/fb87d20f3dbca02da4a39890114fd9ba6a51e7bin0 -> 364 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/73/f346c88d965227a03c0af8d555870b8c5021d4bin0 -> 89 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/74/0a804e8963759c98e5b8cb912e15ae74a7a4a6bin0 -> 207 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/78/c320b06544e23d786a9ec84ee93861f2933094bin0 -> 55 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/79/e28694aae0d3064b06f96a5207b943a2357f07bin0 -> 287 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/7a/05900f340af0252aaa4e34941f040c5d2fe7f7bin0 -> 176 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/7a/677f6201c8f9d46bdfe1f4b08cb504e360a34ebin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f1
-rw-r--r--tests/resources/rebase/.gitted/objects/7f/37fe2d7320360f8a9118b1ed8fba6f384816791
-rw-r--r--tests/resources/rebase/.gitted/objects/80/32d630f37266bace093e353f7b97d7f8b20950bin0 -> 209 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/80/dce0e74f0534811db734a68c23b49f98584d7a2
-rw-r--r--tests/resources/rebase/.gitted/objects/83/53b9f9deff7c707f280e0f656c80772cca7cd92
-rw-r--r--tests/resources/rebase/.gitted/objects/85/258e426a341cc1aa035ac7f6d18f84fed2ab38bin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/85/f34ce9ca9e0f33d4146afec9cbe5a26757500abin0 -> 185 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/86/a5415741ed3754ccb0cac1fc19fd82587840a4bin0 -> 634 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/8d/1f13f93c4995760ac07d129246ac1ff64c0be92
-rw-r--r--tests/resources/rebase/.gitted/objects/8d/95ea62e621f1d38d230d9e7d206e41096d76afbin0 -> 773 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/8f/4de6c781b9ff9cedfd7f9f9f224e744f97b2591
-rw-r--r--tests/resources/rebase/.gitted/objects/92/54a37fde7e97f9a28dee2967fdb2c5d1ed94e91
-rw-r--r--tests/resources/rebase/.gitted/objects/95/39b2cc291d6a6b1b266df8474d31fdd344dd79bin0 -> 173 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/9a/8535dfcaf7554c728d874f047c5461fb2c71d1bin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/9c/d483e7da23819d7f71d24e98438123378867531
-rw-r--r--tests/resources/rebase/.gitted/objects/a0/1a6ee390f65d834375e072952deaee0c5e92f7bin0 -> 90 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/a0/fa65f96c1e3bdc7287e334229279dcc1248fa43
-rw-r--r--tests/resources/rebase/.gitted/objects/a1/25b9b655932711abceaf8962948e6b601d67b6bin0 -> 89 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/a7/00acc970eccccc73be53cd269462176544e6d1bin0 -> 373 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/a7/b066537e6be7109abfe4ff97b675d4e077da20bin0 -> 621 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/aa/4c42aecdfc7cd989bbc3209934ea7cda3f4d881
-rw-r--r--tests/resources/rebase/.gitted/objects/ab/25a53ef5622d443ecb0492b7516725f0deac8fbin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/ad/c97cfb874cdfb9d5ab17b54f3771dea6e02ccfbin0 -> 240 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/ae/87cae12879a3c37d7cc994afc6395bcb0eaf99bin0 -> 209 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/b1/46bd7608eac53d9bf9e1a6963543588b555c641
-rw-r--r--tests/resources/rebase/.gitted/objects/b1/b94ec02f8ed87d0efa4c65fb38d5d6da7e8b32bin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/b6/72b141d48c369fee6c4deeb32a904387594365bin0 -> 174 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/b7/c536a5883c8adaeb34d5e198c5a3dbbdc608b5bin0 -> 209 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/b9/f72b9158fa8c49fb4e4c10b26817ed867be8033
-rw-r--r--tests/resources/rebase/.gitted/objects/bc/cc8eabb5cfe2ec09959c7f4155aa73429fd604bin0 -> 207 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/c4/e6cca3ec6ae0148ed231f97257df8c311e015f1
-rw-r--r--tests/resources/rebase/.gitted/objects/c5/17380440ed78865ffe3fa130b9738615c76618bin0 -> 649 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/cb/20a10406172afd6ca3138ce36ecaf8b1269e8ebin0 -> 213 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/d4/82e77aecb8e07da43e4cad6e0dcb59219e12afbin0 -> 175 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/d6/16d97082eb7bb2dc6f180a7cca940993b7a56f1
-rw-r--r--tests/resources/rebase/.gitted/objects/d6/b9ec0dfb972a6815ace42545cde5f2631cd776bin0 -> 790 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/da/82b3a60c50cf5ac524ec3000d743447329465dbin0 -> 369 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/da/9c51a23d02d931a486f45ad18cda05cf5d2b942
-rw-r--r--tests/resources/rebase/.gitted/objects/dc/12ac1e10f2be70e8ecd52132a08da98a309c3a1
-rw-r--r--tests/resources/rebase/.gitted/objects/df/d3d25264693fcd7348ad286f3c34f3f6b30918bin0 -> 177 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/e4/f809f826c1a9fc929874bc0e4644dd2f2a1af43
-rw-r--r--tests/resources/rebase/.gitted/objects/e5/2ff405da5b7e1e9b0929939fa8405d81fe8a453
-rw-r--r--tests/resources/rebase/.gitted/objects/e7/bb00c4eab291e08361fda376733a12b4150aa9bin0 -> 241 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/e8/8cc0a6919a74599ce8e1dcb81eb2bbae33a645bin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/e9/5f47e016dcc70b0b888df8e40e97b8aabafd4cbin0 -> 279 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/e9/f22c10ffb378446c0bbcab7ee3d9d5a00406722
-rw-r--r--tests/resources/rebase/.gitted/objects/ec/725f5639730640f91cd0be5f2d6d7ac5d69c79bin0 -> 377 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/ed/f7b3ffde1624c60d2d6b1a2bb792d86de172e03
-rw-r--r--tests/resources/rebase/.gitted/objects/ee/23c5eeedadf8595c0ff60a366d970a165e373dbin0 -> 372 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/ee/f0edde5daa94da5f297d4ddb5dfbc1980f0902bin0 -> 55 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/ef/ad0b11c47cb2f0220cbd6f5b0f93bb99064b001
-rw-r--r--tests/resources/rebase/.gitted/objects/f5/56d5fef35003561dc0b64b37057d7541239105bin0 -> 90 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/f6/3fa37e285bd11b0a7b48fa584a4091814a3adabin0 -> 55 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/f7/5c193a1df47186727179f24867bc4d27a8991fbin0 -> 802 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/f8/7d14a4a236582a0278a916340a7937142568642
-rw-r--r--tests/resources/rebase/.gitted/objects/fc/e0584b379f535e50e036db587db71884ea6b36bin0 -> 281 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/ff/b36e513f5fdf8a6ba850a20142676a2ac4807dbin0 -> 355 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/ff/dfa89389040a87008c4ab1834120d3046daaeabin0 -> 208 bytes
-rw-r--r--tests/resources/rebase/.gitted/refs/heads/asparagus1
-rw-r--r--tests/resources/rebase/.gitted/refs/heads/barley1
-rw-r--r--tests/resources/rebase/.gitted/refs/heads/beef1
-rw-r--r--tests/resources/rebase/.gitted/refs/heads/dried_pea1
-rw-r--r--tests/resources/rebase/.gitted/refs/heads/gravy1
-rw-r--r--tests/resources/rebase/.gitted/refs/heads/green_pea1
-rw-r--r--tests/resources/rebase/.gitted/refs/heads/master1
-rw-r--r--tests/resources/rebase/.gitted/refs/heads/veal1
-rw-r--r--tests/resources/rebase/asparagus.txt10
-rw-r--r--tests/resources/rebase/beef.txt22
-rw-r--r--tests/resources/rebase/bouilli.txt18
-rw-r--r--tests/resources/rebase/gravy.txt8
-rw-r--r--tests/resources/rebase/oyster.txt13
-rw-r--r--tests/resources/rebase/veal.txt18
169 files changed, 3381 insertions, 566 deletions
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.
diff --git a/include/git2.h b/include/git2.h
index baa7fcaf8..41adbbad2 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"
@@ -39,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/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/errors.h b/include/git2/errors.h
index 1e3ed3acb..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 */
@@ -90,6 +91,7 @@ typedef enum {
GITERR_CALLBACK,
GITERR_CHERRYPICK,
GITERR_DESCRIBE,
+ GITERR_REBASE,
} git_error_t;
/**
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);
/**
@@ -382,69 +383,6 @@ GIT_EXTERN(int) git_merge_base_octopus(
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
* `git_merge_file_result` that reflects the merge result. The
@@ -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/notes.h b/include/git2/notes.h
index 98eb2aef3..1a7794a5c 100644
--- a/include/git2/notes.h
+++ b/include/git2/notes.h
@@ -97,6 +97,23 @@ GIT_EXTERN(int) git_note_read(
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
*
* @param note the note
diff --git a/include/git2/rebase.h b/include/git2/rebase.h
new file mode 100644
index 000000000..095975edb
--- /dev/null
+++ b/include/git2/rebase.h
@@ -0,0 +1,261 @@
+/*
+ * 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"
+#include "annotated_commit.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;
+
+ /**
+ * 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;
+
+/** 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. */
+ git_rebase_operation_t type;
+
+ /**
+ * 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;
+} git_rebase_operation;
+
+/**
+ * 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);
+
+/**
+ * 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`.
+ *
+ * @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
+ * reachable commits
+ * @param onto The branch to rebase onto, or NULL to rebase onto the given
+ * upstream
+ * @param signature The signature of the rebaser (optional)
+ * @param opts Options to specify how rebase is performed
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_rebase_init(
+ git_rebase **out,
+ git_repository *repo,
+ const git_annotated_commit *branch,
+ const git_annotated_commit *upstream,
+ const git_annotated_commit *onto,
+ 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);
+
+/**
+ * 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
+ * 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 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 *rebase,
+ 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 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
+ * @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 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,
+ * -1 on failure.
+ */
+GIT_EXTERN(int) git_rebase_commit(
+ git_oid *id,
+ git_rebase *rebase,
+ 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.
+ *
+ * @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_rebase *rebase,
+ const git_signature *signature);
+
+/**
+ * Finishes a rebase that is currently in progress once all patches have
+ * been applied.
+ *
+ * @param rebase The rebase that is in-progress
+ * @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
+ */
+GIT_EXTERN(int) git_rebase_finish(
+ git_rebase *rebase,
+ const git_signature *signature,
+ const git_rebase_options *opts);
+
+/**
+ * Frees the `git_rebase` object.
+ *
+ * @param rebase The rebase object
+ */
+GIT_EXTERN(void) git_rebase_free(git_rebase *rebase);
+
+/** @} */
+GIT_END_DECL
+#endif
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/include/git2/types.h b/include/git2/types.h
index 16933976e..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;
@@ -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/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/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/merge.c b/src/merge.c
index 8252f6767..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"
@@ -1835,32 +1837,9 @@ 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[],
+ const git_annotated_commit *heads[],
size_t heads_len)
{
git_filebuf file = GIT_FILEBUF_INIT;
@@ -1875,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;
}
@@ -1917,7 +1896,7 @@ cleanup:
}
struct merge_msg_entry {
- const git_merge_head *merge_head;
+ const git_annotated_commit *merge_head;
bool written;
};
@@ -2105,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;
@@ -2151,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;
@@ -2199,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;
}
@@ -2221,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 = write_orig_head(repo, our_head)) == 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);
@@ -2241,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;
@@ -2259,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);
@@ -2288,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;
@@ -2325,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";
}
@@ -2539,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;
@@ -2556,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) {
@@ -2572,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);
@@ -2618,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);
@@ -2646,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. */
@@ -2658,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;
@@ -2735,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/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(&note->id, note_oid);
+
+ if (git_signature_dup(&note->author, git_commit_author(commit)) < 0 ||
+ git_signature_dup(&note->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(&note, &oid, blob)) < 0)
+ if ((error = note_new(&note, &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, &notes_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;
};
diff --git a/src/rebase.c b/src/rebase.c
new file mode 100644
index 000000000..6453ecc67
--- /dev/null
+++ b/src/rebase.c
@@ -0,0 +1,1125 @@
+/*
+ * 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 "config.h"
+#include "annotated_commit.h"
+
+#include <git2/types.h>
+#include <git2/annotated_commit.h>
+#include <git2/rebase.h>
+#include <git2/commit.h>
+#include <git2/reset.h>
+#include <git2/revwalk.h>
+#include <git2/notes.h>
+
+#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.%" PRIuZ
+#define CURRENT_FILE "current"
+#define REWRITTEN_FILE "rewritten"
+
+#define ORIG_DETACHED_HEAD "detached HEAD"
+
+#define NOTES_DEFAULT_REF NULL
+
+#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_INTERACTIVE = 3,
+} git_rebase_type_t;
+
+struct git_rebase {
+ git_repository *repo;
+
+ git_rebase_type_t type;
+ char *state_path;
+
+ int head_detached : 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;
+ size_t current;
+};
+
+#define GIT_REBASE_STATE_INIT {0}
+
+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;
+}
+
+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;
+
+ 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;
+
+ git_buf_rtrim(out);
+
+done:
+ 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;
+ const 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(&current_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((git_oid *)&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;
+}
+
+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;
+
+ assert(repo);
+
+ 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 (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, rebase->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)
+ rebase->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(&rebase->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(&rebase->onto_id, onto_id.ptr)) < 0)
+ goto done;
+
+ if (!rebase->head_detached)
+ rebase->orig_head_name = git_buf_detach(&orig_head_name);
+
+ 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_open_merge(rebase);
+ break;
+ case GIT_REBASE_TYPE_APPLY:
+ giterr_set(GITERR_REBASE, "Patch application rebase is not supported");
+ error = -1;
+ break;
+ default:
+ abort();
+ }
+
+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);
+ git_buf_free(&onto_id);
+ return error;
+}
+
+static int rebase_cleanup(git_rebase *rebase)
+{
+ 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_rebase *rebase, const char *filename, int flags, 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, rebase->state_path, filename)) == 0)
+ error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE);
+
+ git_buf_free(&path);
+ git_buf_free(&contents);
+
+ return error;
+}
+
+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->id_str;
+}
+
+static int rebase_setupfiles_merge(git_rebase *rebase)
+{
+ git_buf commit_filename = GIT_BUF_INIT;
+ char id_str[GIT_OID_HEXSZ];
+ git_rebase_operation *operation;
+ size_t i;
+ 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->onto_name)) < 0)
+ goto done;
+
+ 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, i+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;
+ }
+
+done:
+ git_buf_free(&commit_filename);
+ return error;
+}
+
+static int rebase_setupfiles(git_rebase *rebase)
+{
+ char onto[GIT_OID_HEXSZ], orig_head[GIT_OID_HEXSZ];
+
+ 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 (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;
+
+ return rebase_setupfiles_merge(rebase);
+}
+
+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 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));
+ 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)
+{
+ 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;
+}
+
+static int rebase_init_operations(
+ git_rebase *rebase,
+ git_repository *repo,
+ const git_annotated_commit *branch,
+ const git_annotated_commit *upstream,
+ const git_annotated_commit *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, 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);
+
+ 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((git_oid *)&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_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;
+
+ rebase->onto_name = git__strdup(rebase_onto_name(onto));
+ GITERR_CHECK_ALLOC(rebase->onto_name);
+
+ return 0;
+}
+
+static int rebase_init(
+ git_rebase *rebase,
+ git_repository *repo,
+ 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;
+ 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, 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;
+
+ 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_annotated_commit *branch,
+ const git_annotated_commit *upstream,
+ const git_annotated_commit *onto,
+ 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;
+ git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
+ int error;
+
+ 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)
+ return error;
+
+ rebase = git__calloc(1, sizeof(git_rebase));
+ GITERR_CHECK_ALLOC(rebase);
+
+ 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,
+ git_annotated_commit_id(onto), 1, signature, reflog.ptr)) < 0 ||
+ (error = git_checkout_head(repo, &checkout_opts)) < 0)
+ goto done;
+
+ *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 void normalize_checkout_opts(
+ git_rebase *rebase,
+ git_commit *current_commit,
+ git_checkout_options *checkout_opts,
+ const git_checkout_options *given_checkout_opts)
+{
+ 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 (rebase->type == GIT_REBASE_TYPE_MERGE) {
+ if (!checkout_opts->our_label)
+ checkout_opts->our_label = rebase->onto_name;
+
+ if (!checkout_opts->their_label)
+ checkout_opts->their_label = git_commit_summary(current_commit);
+ } else {
+ abort();
+ }
+}
+
+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 *rebase,
+ git_checkout_options *given_checkout_opts)
+{
+ git_buf path = GIT_BUF_INIT;
+ git_checkout_options checkout_opts = {0};
+ 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;
+
+ *out = NULL;
+
+ if ((error = rebase_movenext(rebase)) < 0)
+ goto done;
+
+ operation = git_array_get(rebase->operations, rebase->current);
+
+ if ((error = git_commit_lookup(&current_commit, rebase->repo, &operation->id)) < 0 ||
+ (error = git_commit_tree(&current_tree, current_commit)) < 0 ||
+ (error = git_repository_head_tree(&head_tree, rebase->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;
+ }
+
+ 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;
+
+ 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;
+
+ *out = operation;
+
+done:
+ git_index_free(index);
+ git_tree_free(current_tree);
+ git_tree_free(head_tree);
+ git_tree_free(parent_tree);
+ git_commit_free(parent_commit);
+ git_commit_free(current_commit);
+ git_buf_free(&path);
+
+ return error;
+}
+
+int git_rebase_next(
+ git_rebase_operation **out,
+ git_rebase *rebase,
+ git_checkout_options *checkout_opts)
+{
+ int error;
+
+ assert(out && rebase);
+
+ switch (rebase->type) {
+ case GIT_REBASE_TYPE_MERGE:
+ error = rebase_next_merge(out, rebase, checkout_opts);
+ break;
+ default:
+ abort();
+ }
+
+ return error;
+}
+
+static int rebase_commit_merge(
+ git_oid *commit_id,
+ git_rebase *rebase,
+ 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 *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;
+ git_buf reflog_msg = GIT_BUF_INIT;
+ char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ];
+ int error;
+
+ operation = git_array_get(rebase->operations, rebase->current);
+ assert(operation);
+
+ if ((error = git_repository_index(&index, rebase->repo)) < 0)
+ goto done;
+
+ if (git_index_has_conflicts(index)) {
+ giterr_set(GITERR_REBASE, "Conflicts have not been resolved");
+ error = GIT_EMERGECONFLICT;
+ goto done;
+ }
+
+ if ((error = git_commit_lookup(&current_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)
+ 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, rebase->repo, &tree_id)) < 0)
+ goto done;
+
+ if (!author)
+ author = git_commit_author(current_commit);
+
+ if (!message) {
+ 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,
+ committer, message_encoding, message, tree, 1,
+ (const git_commit **)&head_commit)) < 0 ||
+ (error = git_commit_lookup(&commit, rebase->repo, commit_id)) < 0 ||
+ (error = git_reference__update_for_commit(
+ rebase->repo, NULL, "HEAD", commit_id, committer, "rebase")) < 0)
+ goto done;
+
+ 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,
+ "%.*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);
+ git_commit_free(head_commit);
+ git_commit_free(current_commit);
+ git_reference_free(head);
+ git_index_free(index);
+
+ return error;
+}
+
+int git_rebase_commit(
+ git_oid *id,
+ git_rebase *rebase,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message_encoding,
+ const char *message)
+{
+ int error;
+
+ assert(rebase && committer);
+
+ switch (rebase->type) {
+ case GIT_REBASE_TYPE_MERGE:
+ error = rebase_commit_merge(
+ id, rebase, author, committer, message_encoding, message);
+ break;
+ default:
+ abort();
+ }
+
+ return error;
+}
+
+int git_rebase_abort(git_rebase *rebase, const git_signature *signature)
+{
+ git_reference *orig_head_ref = NULL;
+ git_commit *orig_head_commit = NULL;
+ int error;
+
+ assert(rebase && signature);
+
+ 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, 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, 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(rebase);
+
+done:
+ git_commit_free(orig_head_commit);
+ git_reference_free(orig_head_ref);
+
+ return error;
+}
+
+static int rebase_copy_note(
+ git_rebase *rebase,
+ git_oid *from,
+ git_oid *to,
+ const git_signature *committer,
+ const git_rebase_options *opts)
+{
+ git_note *note = NULL;
+ git_oid note_id;
+ git_signature *who = NULL;
+ int error;
+
+ if ((error = git_note_read(&note, rebase->repo, opts->rewrite_notes_ref, from)) < 0) {
+ if (error == GIT_ENOTFOUND) {
+ giterr_clear();
+ error = 0;
+ }
+
+ 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(&note_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;
+}
+
+static int rebase_copy_notes(
+ git_rebase *rebase,
+ 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, rebase->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(rebase, &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_rebase *rebase,
+ const git_signature *signature,
+ const git_rebase_options *given_opts)
+{
+ git_rebase_options opts;
+ 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(rebase);
+
+ if ((error = rebase_normalize_opts(rebase->repo, &opts, given_opts)) < 0)
+ goto done;
+
+ git_oid_fmt(onto, &rebase->onto_id);
+
+ if ((error = git_buf_printf(&branch_msg, "rebase finished: %s onto %.*s",
+ rebase->orig_head_name, GIT_OID_HEXSZ, onto)) < 0 ||
+ (error = git_buf_printf(&head_msg, "rebase finished: returning to %s",
+ 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,
+ 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,
+ rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
+ signature, head_msg.ptr)) < 0 ||
+ (error = rebase_copy_notes(rebase, signature, &opts)) < 0)
+ goto done;
+
+ error = rebase_cleanup(rebase);
+
+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_opts_free(&opts);
+
+ 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)
+ return;
+
+ 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/src/refs.c b/src/refs.c
index 08e407e48..43c7333f2 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -22,6 +22,7 @@
#include <git2/refdb.h>
#include <git2/sys/refs.h>
#include <git2/signature.h>
+#include <git2/commit.h>
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/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/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;
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/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
new file mode 100644
index 000000000..71326433f
--- /dev/null
+++ b/tests/rebase/abort.c
@@ -0,0 +1,158 @@
+#include "clar_libgit2.h"
+#include "git2/rebase.h"
+#include "merge.h"
+#include "posix.h"
+#include "annotated_commit.h"
+
+#include <fcntl.h>
+
+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_annotated_commit *branch, git_annotated_commit *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(rebase, 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_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_annotated_commit_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_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);
+ 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_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_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));
+
+ 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);
+
+ git_signature_free(signature);
+
+ 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);
+}
+
+void test_rebase_abort__detached_head(void)
+{
+ git_rebase *rebase;
+ git_oid branch_id;
+ git_reference *onto_ref;
+ git_signature *signature;
+ 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_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));
+
+ 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);
+
+ git_signature_free(signature);
+
+ git_annotated_commit_free(branch_head);
+ git_annotated_commit_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_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_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));
+
+ 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",
+ "rebase-merge/.git/rebase-merge/head");
+
+ test_abort(branch_head, onto_head);
+
+ git_signature_free(signature);
+
+ 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);
+}
diff --git a/tests/rebase/iterator.c b/tests/rebase/iterator.c
new file mode 100644
index 000000000..ddf4413d3
--- /dev/null
+++ b/tests/rebase/iterator.c
@@ -0,0 +1,108 @@
+#include "clar_libgit2.h"
+#include "git2/rebase.h"
+#include "posix.h"
+
+#include <fcntl.h>
+
+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_annotated_commit *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_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);
+ 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_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
new file mode 100644
index 000000000..e7eb16713
--- /dev/null
+++ b/tests/rebase/merge.c
@@ -0,0 +1,487 @@
+#include "clar_libgit2.h"
+#include "git2/rebase.h"
+#include "posix.h"
+#include "signature.h"
+
+#include <fcntl.h>
+
+static git_repository *repo;
+static git_signature *signature;
+
+// Fixture setup and teardown
+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();
+}
+
+void test_rebase_merge__next(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ 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;
+ const git_status_entry *status_entry;
+ git_oid pick_id, 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_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));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase, &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");
+
+ 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_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);
+}
+
+void test_rebase_merge__next_with_conflicts(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ 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;
+ const git_status_entry *status_entry;
+ git_oid pick_id;
+
+ 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_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));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase, &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");
+
+ 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_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);
+}
+
+void test_rebase_merge__next_stops_with_iterover(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ 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;
+ 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_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));
+
+ 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, rebase, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+
+ 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, rebase, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+
+ 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, rebase, &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_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);
+}
+
+void test_rebase_merge__commit(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ 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;
+ git_signature *author;
+ git_commit *commit;
+ git_reflog *reflog;
+ const git_reflog_entry *reflog_entry;
+
+ 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_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));
+
+ 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));
+
+ 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)));
+
+ /* 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_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);
+}
+
+void test_rebase_merge__commit_updates_rewritten(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ 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;
+
+ 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_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));
+
+ 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, rebase, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+
+ cl_assert_equal_file(
+ "da9c51a23d02d931a486f45ad18cda05cf5d2b94 776e4c48922799f903f03f5f6e51da8b01e4cce0\n"
+ "8d1f13f93c4995760ac07d129246ac1ff64c0be9 ba1f9b4fd5cf8151f7818be2111cc0869f1eb95a\n",
+ 164, "rebase/.git/rebase-merge/rewritten");
+
+ 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);
+}
+
+void test_rebase_merge__commit_drops_already_applied(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ 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;
+ 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_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));
+
+ 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, rebase, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+
+ cl_assert_equal_file(
+ "8d1f13f93c4995760ac07d129246ac1ff64c0be9 2ac4fb7b74c1287f6c792acad759e1ec01e18dae\n",
+ 82, "rebase/.git/rebase-merge/rewritten");
+
+ 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);
+}
+
+void test_rebase_merge__finish(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref, *head_ref;
+ 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;
+ 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_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));
+
+ 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, rebase, &checkout_opts));
+ cl_assert_equal_i(GIT_ITEROVER, error);
+
+ cl_git_pass(git_rebase_finish(rebase, signature, NULL));
+
+ 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_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_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);
+ 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_annotated_commit *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;
+ 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_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));
+
+ /* Add a note to a commit */
+ cl_git_pass(git_note_create(&note_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, opts));
+
+ 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(rebase, signature, opts));
+
+ cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));
+
+ if (should_exist) {
+ cl_git_pass(git_note_read(&note, 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(&note, repo, "refs/notes/test", &commit_id));
+ cl_assert_equal_i(GIT_ENOTFOUND, error);
+ }
+
+ git_note_free(note);
+ git_commit_free(branch_commit);
+ 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);
+}
+
+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);
+}
+
diff --git a/tests/rebase/setup.c b/tests/rebase/setup.c
new file mode 100644
index 000000000..c81ca1245
--- /dev/null
+++ b/tests/rebase/setup.c
@@ -0,0 +1,342 @@
+#include "clar_libgit2.h"
+#include "git2/rebase.h"
+#include "posix.h"
+
+#include <fcntl.h>
+
+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_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ 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_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);
+
+ cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo));
+
+ cl_git_fail(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
+
+ git_annotated_commit_free(branch_head);
+ git_annotated_commit_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_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ git_annotated_commit *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_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));
+
+ 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_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);
+}
+
+/* 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_annotated_commit *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_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));
+
+ 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_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);
+}
+
+/* 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_annotated_commit *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_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));
+
+ 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_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);
+ 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_annotated_commit *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_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));
+
+ 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_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);
+}
+
+/* git checkout barley && git rebase --merge master */
+void test_rebase_setup__orphan_branch(void)
+{
+ git_rebase *rebase;
+ git_reference *branch_ref, *upstream_ref;
+ git_annotated_commit *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_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));
+
+ 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_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);
+}
+
+static int rebase_is_blocked(void)
+{
+ git_rebase *rebase = NULL;
+ int error;
+
+ git_reference *branch_ref, *upstream_ref;
+ 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_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_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);
+
+ 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 000000000..cb089cd89
--- /dev/null
+++ b/tests/resources/rebase/.gitted/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/resources/rebase/.gitted/config b/tests/resources/rebase/.gitted/config
new file mode 100644
index 000000000..17e58b1c2
--- /dev/null
+++ b/tests/resources/rebase/.gitted/config
@@ -0,0 +1,4 @@
+[core]
+ repositoryformatversion = 0
+ bare = false
+ logallrefupdates = true
diff --git a/tests/resources/rebase/.gitted/index b/tests/resources/rebase/.gitted/index
new file mode 100644
index 000000000..0f53a2167
--- /dev/null
+++ b/tests/resources/rebase/.gitted/index
Binary files differ
diff --git a/tests/resources/rebase/.gitted/info/exclude b/tests/resources/rebase/.gitted/info/exclude
new file mode 100644
index 000000000..a5196d1be
--- /dev/null
+++ b/tests/resources/rebase/.gitted/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests/resources/rebase/.gitted/logs/HEAD b/tests/resources/rebase/.gitted/logs/HEAD
new file mode 100644
index 000000000..62d3b164e
--- /dev/null
+++ b/tests/resources/rebase/.gitted/logs/HEAD
@@ -0,0 +1 @@
+efad0b11c47cb2f0220cbd6f5b0f93bb99064b00 efad0b11c47cb2f0220cbd6f5b0f93bb99064b00 Edward Thomson <ethomson@edwardthomson.com> 1405623541 -0400 checkout: moving from master to master
diff --git a/tests/resources/rebase/.gitted/objects/00/66204dd469ee930e551fbcf123f98e211c99ce b/tests/resources/rebase/.gitted/objects/00/66204dd469ee930e551fbcf123f98e211c99ce
new file mode 100644
index 000000000..e6f72ce24
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/00/66204dd469ee930e551fbcf123f98e211c99ce
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/00/f1b9a0948a7d5d14405eba6030efcdfbb8ff4a b/tests/resources/rebase/.gitted/objects/00/f1b9a0948a7d5d14405eba6030efcdfbb8ff4a
new file mode 100644
index 000000000..a23f526b5
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/00/f1b9a0948a7d5d14405eba6030efcdfbb8ff4a
@@ -0,0 +1,3 @@
+xAnC! D@*𑪪YG/~(UZͼf}X
+oB%
+BU#DGa9"RH~.-H]o}H-HZSYLyIU/jg\[r8_n/fL:}EVAr+ T \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/01/3cc32d341bab0e6f039f50f153c18986f16c58 b/tests/resources/rebase/.gitted/objects/01/3cc32d341bab0e6f039f50f153c18986f16c58
new file mode 100644
index 000000000..2e32bd339
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/01/3cc32d341bab0e6f039f50f153c18986f16c58
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/01/a17f7d154ab5bf9f8bfede3d82dd00ddf7e7dc b/tests/resources/rebase/.gitted/objects/01/a17f7d154ab5bf9f8bfede3d82dd00ddf7e7dc
new file mode 100644
index 000000000..c21329f33
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/01/a17f7d154ab5bf9f8bfede3d82dd00ddf7e7dc
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/02/2d3b6bbd0bfbdf147319476fb8bf405691cb0d b/tests/resources/rebase/.gitted/objects/02/2d3b6bbd0bfbdf147319476fb8bf405691cb0d
new file mode 100644
index 000000000..b1f7468ac
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/02/2d3b6bbd0bfbdf147319476fb8bf405691cb0d
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177ac b/tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177ac
new file mode 100644
index 000000000..c38c5b255
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177ac
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/0e/f2e2b2a2b8d6e1f8dff5e621e0eca21b693d0c b/tests/resources/rebase/.gitted/objects/0e/f2e2b2a2b8d6e1f8dff5e621e0eca21b693d0c
new file mode 100644
index 000000000..d8ef47c62
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/0e/f2e2b2a2b8d6e1f8dff5e621e0eca21b693d0c
@@ -0,0 +1,3 @@
+xPN1Wl
+g"J:~`^"1A=/FnrwBY9g/U
+JёM$]$,jH>K"Y+F̓y3YL8kfͮ3Z]I~K\>x]zm<~'1~ك:"GB4_yη|1_"fi \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/0f/5f6d3353be1a9966fa5767b7d604b051798224 b/tests/resources/rebase/.gitted/objects/0f/5f6d3353be1a9966fa5767b7d604b051798224
new file mode 100644
index 000000000..739aca383
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/0f/5f6d3353be1a9966fa5767b7d604b051798224
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/11/fac10ca1b9318ce361a0be0c3d889d777e299c b/tests/resources/rebase/.gitted/objects/11/fac10ca1b9318ce361a0be0c3d889d777e299c
new file mode 100644
index 000000000..5af5474b5
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/11/fac10ca1b9318ce361a0be0c3d889d777e299c
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/12/c084412b952396962eb420716df01022b847cc b/tests/resources/rebase/.gitted/objects/12/c084412b952396962eb420716df01022b847cc
new file mode 100644
index 000000000..5244e469d
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/12/c084412b952396962eb420716df01022b847cc
@@ -0,0 +1,2 @@
+xKjC1)IB6^z YAQ0d Mm28 )!mJġ"MLye6.ggC8iUXIWC.g
+8+ j҇<'澿AMZ4jVdFziem) ǗKU \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/12/f28ed978639d331269d9dc2b74e87db58e1057 b/tests/resources/rebase/.gitted/objects/12/f28ed978639d331269d9dc2b74e87db58e1057
new file mode 100644
index 000000000..b0dbc3e07
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/12/f28ed978639d331269d9dc2b74e87db58e1057
@@ -0,0 +1,3 @@
+xO9n0tWbp)KF&e:`\*$|?3,sݩmXX
+c#ۤVBD.F1ڀR F
+sBe'%>ڽnxpe+\ORO9vtmfy.pVonB#Vj \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/19/14d57ddf6c5c997664521cc94f190df46dc1c2 b/tests/resources/rebase/.gitted/objects/19/14d57ddf6c5c997664521cc94f190df46dc1c2
new file mode 100644
index 000000000..921f2cd88
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/19/14d57ddf6c5c997664521cc94f190df46dc1c2
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/1b/1d19799fcc89fa3cb821581fcf7f2e8fd2cc4d b/tests/resources/rebase/.gitted/objects/1b/1d19799fcc89fa3cb821581fcf7f2e8fd2cc4d
new file mode 100644
index 000000000..3d206b0cc
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/1b/1d19799fcc89fa3cb821581fcf7f2e8fd2cc4d
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/1f/2214c1b13b134d5508f41f6a3b77cc6a8f5182 b/tests/resources/rebase/.gitted/objects/1f/2214c1b13b134d5508f41f6a3b77cc6a8f5182
new file mode 100644
index 000000000..84b875c50
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/1f/2214c1b13b134d5508f41f6a3b77cc6a8f5182
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/20/db906c85e78c6dde82eb2ec6d3231c4b96fce8 b/tests/resources/rebase/.gitted/objects/20/db906c85e78c6dde82eb2ec6d3231c4b96fce8
new file mode 100644
index 000000000..2a908da61
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/20/db906c85e78c6dde82eb2ec6d3231c4b96fce8
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/22/adb22bef75a0371e85ff6d82e5e60e4b425501 b/tests/resources/rebase/.gitted/objects/22/adb22bef75a0371e85ff6d82e5e60e4b425501
new file mode 100644
index 000000000..7f17ef059
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/22/adb22bef75a0371e85ff6d82e5e60e4b425501
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/2a/a3ce842094e08ebac152b3d6d5b0fff39f9c6e b/tests/resources/rebase/.gitted/objects/2a/a3ce842094e08ebac152b3d6d5b0fff39f9c6e
new file mode 100644
index 000000000..38eca43dc
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/2a/a3ce842094e08ebac152b3d6d5b0fff39f9c6e
@@ -0,0 +1 @@
+xMn! F@# 8RTeew!ńV}htHO/m[vg$H$bW >*jU̝{ R4d19sD\CbQ0M+mh78S=>0%:-‹ ֚NQ1M׺fTp0\:~'fUN \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/2b/4ebffd3111546d278bb5df62e5630930b605fb b/tests/resources/rebase/.gitted/objects/2b/4ebffd3111546d278bb5df62e5630930b605fb
new file mode 100644
index 000000000..5bdfc1e29
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/2b/4ebffd3111546d278bb5df62e5630930b605fb
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/30/69cc907e6294623e5917ef6de663928c1febfb b/tests/resources/rebase/.gitted/objects/30/69cc907e6294623e5917ef6de663928c1febfb
new file mode 100644
index 000000000..edd86f721
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/30/69cc907e6294623e5917ef6de663928c1febfb
@@ -0,0 +1 @@
+x;n1 DSR] 07.E[eldA7I_eOT!&Ɛ[U5RLPoz+Ab)iF8qۃ?+u餯>_@)n޸[Dz+' TG \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/32/52a0692ace4c4c709f22011227d9dc4845f289 b/tests/resources/rebase/.gitted/objects/32/52a0692ace4c4c709f22011227d9dc4845f289
new file mode 100644
index 000000000..2b2434f87
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/32/52a0692ace4c4c709f22011227d9dc4845f289
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/33/f915f9e4dbd9f4b24430e48731a59b45b15500 b/tests/resources/rebase/.gitted/objects/33/f915f9e4dbd9f4b24430e48731a59b45b15500
new file mode 100644
index 000000000..c33f179bf
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/33/f915f9e4dbd9f4b24430e48731a59b45b15500
@@ -0,0 +1 @@
+xi1E*iVi@Hi@[®Lڏb܁.Z޾0YN"e18K}H!dG^H;I' ' WvD5{Px׾g{koG3W|/{{cFWmV3Q}G.zRsu1PHZ \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/34/86a9d4cdf0b7b4a702c199eed541dc3af13a03 b/tests/resources/rebase/.gitted/objects/34/86a9d4cdf0b7b4a702c199eed541dc3af13a03
new file mode 100644
index 000000000..fdbe16d10
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/34/86a9d4cdf0b7b4a702c199eed541dc3af13a03
@@ -0,0 +1 @@
+xMn0 ;),L-Э@ eҢ*Qu"##{'^>U!:g"\sL}fں?M_R0jMAb`5u+ '!` u&lÞA=Mk!Y,^#(.7*#QD1ɘ!Ic4~KRU%@/l4dH_:Ag$Jr#/n ex9)[t,^g11n;$w/ \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/3c/33b080bf75724c8899d8e703614cb59bfbd047 b/tests/resources/rebase/.gitted/objects/3c/33b080bf75724c8899d8e703614cb59bfbd047
new file mode 100644
index 000000000..8716898f8
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/3c/33b080bf75724c8899d8e703614cb59bfbd047
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/3d/a85aca38a95b44d77ef55a8deb445e49ba19b4 b/tests/resources/rebase/.gitted/objects/3d/a85aca38a95b44d77ef55a8deb445e49ba19b4
new file mode 100644
index 000000000..fa6d9468d
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/3d/a85aca38a95b44d77ef55a8deb445e49ba19b4
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/3e/8989b5a16d5258c935d998ef0e6bb139cc4757 b/tests/resources/rebase/.gitted/objects/3e/8989b5a16d5258c935d998ef0e6bb139cc4757
new file mode 100644
index 000000000..1bbf138ef
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/3e/8989b5a16d5258c935d998ef0e6bb139cc4757
@@ -0,0 +1,2 @@
+xKj1 )t1J&z%C'.\?n u[Pӊ"%C0+ozr
+-&*V,e\b, fP spwstCdz涿 w\b̩I-5ShpU2w_T
diff --git a/tests/resources/rebase/.gitted/objects/3f/05a038dd89f51ba2b3d7b14ba1f8c00f0e31ac b/tests/resources/rebase/.gitted/objects/3f/05a038dd89f51ba2b3d7b14ba1f8c00f0e31ac
new file mode 100644
index 000000000..26bd353f7
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/3f/05a038dd89f51ba2b3d7b14ba1f8c00f0e31ac
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/3f/d8d53cf02de539b9a25a5941030451f76a152f b/tests/resources/rebase/.gitted/objects/3f/d8d53cf02de539b9a25a5941030451f76a152f
new file mode 100644
index 000000000..91c4d957e
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/3f/d8d53cf02de539b9a25a5941030451f76a152f
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/40/0d89e8ee6cd91b67b1f45de1ca190e1c580c6f b/tests/resources/rebase/.gitted/objects/40/0d89e8ee6cd91b67b1f45de1ca190e1c580c6f
new file mode 100644
index 000000000..f67475370
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/40/0d89e8ee6cd91b67b1f45de1ca190e1c580c6f
@@ -0,0 +1 @@
+xO;0 e)|PbadqC6  GzTio3XŲ !tܳ%bqsQA{O$>I1aPTbM|{Y,\eZ :cT#Ow!lm4s)2bZ O=W>{VT \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/41/4dfc71ead79c07acd4ea47fecf91f289afc4b9 b/tests/resources/rebase/.gitted/objects/41/4dfc71ead79c07acd4ea47fecf91f289afc4b9
new file mode 100644
index 000000000..546815ea8
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/41/4dfc71ead79c07acd4ea47fecf91f289afc4b9
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/41/c5a0a761bb4a7670924c1af0800b30fe9a21be b/tests/resources/rebase/.gitted/objects/41/c5a0a761bb4a7670924c1af0800b30fe9a21be
new file mode 100644
index 000000000..ecb399264
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/41/c5a0a761bb4a7670924c1af0800b30fe9a21be
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911 b/tests/resources/rebase/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911
new file mode 100644
index 000000000..99b5e6d2c
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/42/cdad903aef3e7b614675e6584a8be417941911
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/44/c801fe026abbc141b52a4dec5df15fa98249c6 b/tests/resources/rebase/.gitted/objects/44/c801fe026abbc141b52a4dec5df15fa98249c6
new file mode 100644
index 000000000..eaf24ae46
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/44/c801fe026abbc141b52a4dec5df15fa98249c6
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/4b/21eb6eeeec7f8fc89a1d334faff9bd5f5f8c34 b/tests/resources/rebase/.gitted/objects/4b/21eb6eeeec7f8fc89a1d334faff9bd5f5f8c34
new file mode 100644
index 000000000..0c9f4b944
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/4b/21eb6eeeec7f8fc89a1d334faff9bd5f5f8c34
@@ -0,0 +1,2 @@
+x]J1})JOҙL`At:3,^(+68Ts 7L%`I-Ƽi@.$TRF
+l8Q8iJ:g<"[?-wLԋIz{Яbphf:asƼ|TuB빖*<!z?72Z \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850a b/tests/resources/rebase/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850a
new file mode 100644
index 000000000..016398531
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/4b/7c5650008b2e747fe1809eeb5a1dde0e80850a
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/4b/ed71df7017283cac61bbf726197ad6a5a18b84 b/tests/resources/rebase/.gitted/objects/4b/ed71df7017283cac61bbf726197ad6a5a18b84
new file mode 100644
index 000000000..f206618f1
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/4b/ed71df7017283cac61bbf726197ad6a5a18b84
@@ -0,0 +1,2 @@
+x;nB1ES{ 3PD.Gƀ=bt#n ?FAdIOh$ۜI[
+Ϋ?r9^RjA>-s!X\Utܨ9N<Wp[ & i:eQV0e* ~;]MU9 \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/4c/acc6f6e740a5bc64faa33e04b8ef0733d8a127 b/tests/resources/rebase/.gitted/objects/4c/acc6f6e740a5bc64faa33e04b8ef0733d8a127
new file mode 100644
index 000000000..36a6b31fa
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/4c/acc6f6e740a5bc64faa33e04b8ef0733d8a127
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/4f/b698bde45d7d2833e3f2aacfbfe8a7e7f60a65 b/tests/resources/rebase/.gitted/objects/4f/b698bde45d7d2833e3f2aacfbfe8a7e7f60a65
new file mode 100644
index 000000000..8bb69d099
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/4f/b698bde45d7d2833e3f2aacfbfe8a7e7f60a65
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/50/8be4ff49d38465ad3de58f66d38f70e59f881f b/tests/resources/rebase/.gitted/objects/50/8be4ff49d38465ad3de58f66d38f70e59f881f
new file mode 100644
index 000000000..7ce4452b2
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/50/8be4ff49d38465ad3de58f66d38f70e59f881f
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/53/f75e45a463033854e52fa8d39dc858e45537d0 b/tests/resources/rebase/.gitted/objects/53/f75e45a463033854e52fa8d39dc858e45537d0
new file mode 100644
index 000000000..f25ef1f73
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/53/f75e45a463033854e52fa8d39dc858e45537d0
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/58/8e5d2f04d49707fe4aab865e1deacaf7ef6787 b/tests/resources/rebase/.gitted/objects/58/8e5d2f04d49707fe4aab865e1deacaf7ef6787
new file mode 100644
index 000000000..766adc10c
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/58/8e5d2f04d49707fe4aab865e1deacaf7ef6787
@@ -0,0 +1 @@
+xK!D]so1n\4Y`F7pW*<j2w ٓ3\B*ű\2%B(Cv6^;(JϨEmEbaDu U9,ҳOmKymjˣpA?Ԗ(+jRAl?oĵΔ<,7_T \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/5b/1e8bccf7787e942aecf61912f94a2c274f85a5 b/tests/resources/rebase/.gitted/objects/5b/1e8bccf7787e942aecf61912f94a2c274f85a5
new file mode 100644
index 000000000..d4776d883
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/5b/1e8bccf7787e942aecf61912f94a2c274f85a5
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/60/29cb003b59f710f9a8ebd9da9ece2d73070b69 b/tests/resources/rebase/.gitted/objects/60/29cb003b59f710f9a8ebd9da9ece2d73070b69
new file mode 100644
index 000000000..a48e023be
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/60/29cb003b59f710f9a8ebd9da9ece2d73070b69
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/61/139b9b40a3e489f4abbc6af14e10ae14006e47 b/tests/resources/rebase/.gitted/objects/61/139b9b40a3e489f4abbc6af14e10ae14006e47
new file mode 100644
index 000000000..b096a964c
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/61/139b9b40a3e489f4abbc6af14e10ae14006e47
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/61/30e5fcbdce2aa8b3cfd84706c58a892e7d8dd0 b/tests/resources/rebase/.gitted/objects/61/30e5fcbdce2aa8b3cfd84706c58a892e7d8dd0
new file mode 100644
index 000000000..116da7ca9
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/61/30e5fcbdce2aa8b3cfd84706c58a892e7d8dd0
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/63/c18bf188b8a1ab0bad85161dc3fb43c48ed0db b/tests/resources/rebase/.gitted/objects/63/c18bf188b8a1ab0bad85161dc3fb43c48ed0db
new file mode 100644
index 000000000..297c43225
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/63/c18bf188b8a1ab0bad85161dc3fb43c48ed0db
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/67/ed7afb256807556f9b74fa4f7c9284aaec1120 b/tests/resources/rebase/.gitted/objects/67/ed7afb256807556f9b74fa4f7c9284aaec1120
new file mode 100644
index 000000000..82da20626
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/67/ed7afb256807556f9b74fa4f7c9284aaec1120
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/68/af1fc7407fd9addf1701a87eb1c95c7494c598 b/tests/resources/rebase/.gitted/objects/68/af1fc7407fd9addf1701a87eb1c95c7494c598
new file mode 100644
index 000000000..6aaf79fcb
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/68/af1fc7407fd9addf1701a87eb1c95c7494c598
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/68/f6182f4c85d39e1309d97c7e456156dc9c0096 b/tests/resources/rebase/.gitted/objects/68/f6182f4c85d39e1309d97c7e456156dc9c0096
new file mode 100644
index 000000000..ed1de3ada
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/68/f6182f4c85d39e1309d97c7e456156dc9c0096
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/6c/8e16469b6ca09a07e00f0e07a5143c31dcfb64 b/tests/resources/rebase/.gitted/objects/6c/8e16469b6ca09a07e00f0e07a5143c31dcfb64
new file mode 100644
index 000000000..2b8d569ea
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/6c/8e16469b6ca09a07e00f0e07a5143c31dcfb64
@@ -0,0 +1 @@
+xERKn0횧x+Z +5U-D(jdI}ڮD3ɸ _}޾ S (7rLU+E2z9Q :jE4ïӫ</xmqB:_bfug{cN+$&EE$ tV; ]wh?1G!eHήaru%m 0G։ݒ |6Uw"+j;oLANuji{la+QQ#<׶3⅍ ~ſ6vUΘ7|J3([vVx"eL2\ $b^4dne#i箜`9qe6g}??Qȃ \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/6d/77ce8fa2cd93c6489236e33e45e35203ca748c b/tests/resources/rebase/.gitted/objects/6d/77ce8fa2cd93c6489236e33e45e35203ca748c
new file mode 100644
index 000000000..5c3f68625
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/6d/77ce8fa2cd93c6489236e33e45e35203ca748c
@@ -0,0 +1 @@
+x+)JMU0`040031QHJ,I+(ahz >ԜrS57j \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/6d/fb87d20f3dbca02da4a39890114fd9ba6a51e7 b/tests/resources/rebase/.gitted/objects/6d/fb87d20f3dbca02da4a39890114fd9ba6a51e7
new file mode 100644
index 000000000..039c669aa
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/6d/fb87d20f3dbca02da4a39890114fd9ba6a51e7
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/73/f346c88d965227a03c0af8d555870b8c5021d4 b/tests/resources/rebase/.gitted/objects/73/f346c88d965227a03c0af8d555870b8c5021d4
new file mode 100644
index 000000000..215df59d8
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/73/f346c88d965227a03c0af8d555870b8c5021d4
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/74/0a804e8963759c98e5b8cb912e15ae74a7a4a6 b/tests/resources/rebase/.gitted/objects/74/0a804e8963759c98e5b8cb912e15ae74a7a4a6
new file mode 100644
index 000000000..b81718279
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/74/0a804e8963759c98e5b8cb912e15ae74a7a4a6
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/78/c320b06544e23d786a9ec84ee93861f2933094 b/tests/resources/rebase/.gitted/objects/78/c320b06544e23d786a9ec84ee93861f2933094
new file mode 100644
index 000000000..afa39fb97
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/78/c320b06544e23d786a9ec84ee93861f2933094
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/79/e28694aae0d3064b06f96a5207b943a2357f07 b/tests/resources/rebase/.gitted/objects/79/e28694aae0d3064b06f96a5207b943a2357f07
new file mode 100644
index 000000000..17ff306f1
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/79/e28694aae0d3064b06f96a5207b943a2357f07
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/7a/05900f340af0252aaa4e34941f040c5d2fe7f7 b/tests/resources/rebase/.gitted/objects/7a/05900f340af0252aaa4e34941f040c5d2fe7f7
new file mode 100644
index 000000000..43201f89b
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/7a/05900f340af0252aaa4e34941f040c5d2fe7f7
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/7a/677f6201c8f9d46bdfe1f4b08cb504e360a34e b/tests/resources/rebase/.gitted/objects/7a/677f6201c8f9d46bdfe1f4b08cb504e360a34e
new file mode 100644
index 000000000..dc2fd5a36
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/7a/677f6201c8f9d46bdfe1f4b08cb504e360a34e
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f b/tests/resources/rebase/.gitted/objects/7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f
new file mode 100644
index 000000000..fe8b15777
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/7c/7bf85e978f1d18c0566f702d2cb7766b9c8d4f
@@ -0,0 +1 @@
+xN0Dd' \V\~/1rw5m|0 tntƺ%kcnu a:K,^W55<i:q^33qe\ ӝ KR &ڡȶJ,Nי#|VhNwDžԙԺ {Y}RYa) \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/7f/37fe2d7320360f8a9118b1ed8fba6f38481679 b/tests/resources/rebase/.gitted/objects/7f/37fe2d7320360f8a9118b1ed8fba6f38481679
new file mode 100644
index 000000000..400df288f
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/7f/37fe2d7320360f8a9118b1ed8fba6f38481679
@@ -0,0 +1 @@
+xn1;{%hRKG8Q^? ifFuJ\pכ*$ W2#V1FCAcFqř=7uOȘY>A\~km!? |]78/ww\30 0Mnq?ggbs/Bj |5_X$W \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/80/32d630f37266bace093e353f7b97d7f8b20950 b/tests/resources/rebase/.gitted/objects/80/32d630f37266bace093e353f7b97d7f8b20950
new file mode 100644
index 000000000..07050dfd4
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/80/32d630f37266bace093e353f7b97d7f8b20950
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/80/dce0e74f0534811db734a68c23b49f98584d7a b/tests/resources/rebase/.gitted/objects/80/dce0e74f0534811db734a68c23b49f98584d7a
new file mode 100644
index 000000000..1b98b0a6f
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/80/dce0e74f0534811db734a68c23b49f98584d7a
@@ -0,0 +1,2 @@
+xERN0 朧TH* mj5KB0qv׵aUjgV#B0A>@2Qbpd^x:a
+6Ok% <!2 xrsrp֌3Pk;: ~T#E3";]DzGށ 9\ɺU׭><î}?*= g_YGv '{d ~W&FH~䦨٨m|JxM++8Od&8#J,%2<?KyidaS5@%Ƃ=AejTRIEى“P>IRuD8!tl/0x'FxᮜA2Keyq9ܪ \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/83/53b9f9deff7c707f280e0f656c80772cca7cd9 b/tests/resources/rebase/.gitted/objects/83/53b9f9deff7c707f280e0f656c80772cca7cd9
new file mode 100644
index 000000000..a4a7e3aa3
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/83/53b9f9deff7c707f280e0f656c80772cca7cd9
@@ -0,0 +1,2 @@
+xMAj0E)L6]Bh@q,*kTi\7Ji ۇ}y<|:]cΗwԯဗhlt+ C"d%P* CF; X<rl6tatB# PeJŕehߡaW
+o1DQ^#pB~ЭZ1ɶ_('*g6kד* v,0;)FJy^v.=E9\MJ_mAͣΰc%]Do= .# \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/85/258e426a341cc1aa035ac7f6d18f84fed2ab38 b/tests/resources/rebase/.gitted/objects/85/258e426a341cc1aa035ac7f6d18f84fed2ab38
new file mode 100644
index 000000000..af1106d6a
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/85/258e426a341cc1aa035ac7f6d18f84fed2ab38
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/85/f34ce9ca9e0f33d4146afec9cbe5a26757500a b/tests/resources/rebase/.gitted/objects/85/f34ce9ca9e0f33d4146afec9cbe5a26757500a
new file mode 100644
index 000000000..03e75165a
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/85/f34ce9ca9e0f33d4146afec9cbe5a26757500a
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/86/a5415741ed3754ccb0cac1fc19fd82587840a4 b/tests/resources/rebase/.gitted/objects/86/a5415741ed3754ccb0cac1fc19fd82587840a4
new file mode 100644
index 000000000..fe00a22e3
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/86/a5415741ed3754ccb0cac1fc19fd82587840a4
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/8d/1f13f93c4995760ac07d129246ac1ff64c0be9 b/tests/resources/rebase/.gitted/objects/8d/1f13f93c4995760ac07d129246ac1ff64c0be9
new file mode 100644
index 000000000..a66cfccb2
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/8d/1f13f93c4995760ac07d129246ac1ff64c0be9
@@ -0,0 +1,2 @@
+xAn0 {+M[>@⃣Q-vgh[ץo0P"NX*H4Y1̩R.&_;MQh0$+Cc$`ҚA6lK[
+o:߾Gi1tMiE/Ao0S \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/8d/95ea62e621f1d38d230d9e7d206e41096d76af b/tests/resources/rebase/.gitted/objects/8d/95ea62e621f1d38d230d9e7d206e41096d76af
new file mode 100644
index 000000000..464de7c1c
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/8d/95ea62e621f1d38d230d9e7d206e41096d76af
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/8f/4de6c781b9ff9cedfd7f9f9f224e744f97b259 b/tests/resources/rebase/.gitted/objects/8f/4de6c781b9ff9cedfd7f9f9f224e744f97b259
new file mode 100644
index 000000000..faa938958
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/8f/4de6c781b9ff9cedfd7f9f9f224e744f97b259
@@ -0,0 +1 @@
+x+)JMU0d040031QHJ,I+(a|6eՃll?w:/2gJ)LM/HM+tS5W^;?S#;a9$j \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/92/54a37fde7e97f9a28dee2967fdb2c5d1ed94e9 b/tests/resources/rebase/.gitted/objects/92/54a37fde7e97f9a28dee2967fdb2c5d1ed94e9
new file mode 100644
index 000000000..10d6c134f
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/92/54a37fde7e97f9a28dee2967fdb2c5d1ed94e9
@@ -0,0 +1 @@
+xERn0 Y_0z+Z'5ue(VRdp8Av{A G!zQúZ#M oj[w&PѫN)VuP,FU1fpyѳhok}WZ` h ?Un59gsK aW50\5Lˤ,jGH.{ 0*KBCh ۾m3.HƖ4_2㹉 ZO|kp4u#*FpI`D`bTWk.SsM] KG޴I{VG 8#J ;˽'P(b& .dopѻvќK՘#+ {v?wǃ \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/95/39b2cc291d6a6b1b266df8474d31fdd344dd79 b/tests/resources/rebase/.gitted/objects/95/39b2cc291d6a6b1b266df8474d31fdd344dd79
new file mode 100644
index 000000000..964943473
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/95/39b2cc291d6a6b1b266df8474d31fdd344dd79
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/9a/8535dfcaf7554c728d874f047c5461fb2c71d1 b/tests/resources/rebase/.gitted/objects/9a/8535dfcaf7554c728d874f047c5461fb2c71d1
new file mode 100644
index 000000000..d997426b2
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/9a/8535dfcaf7554c728d874f047c5461fb2c71d1
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/9c/d483e7da23819d7f71d24e9843812337886753 b/tests/resources/rebase/.gitted/objects/9c/d483e7da23819d7f71d24e9843812337886753
new file mode 100644
index 000000000..d16845506
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/9c/d483e7da23819d7f71d24e9843812337886753
@@ -0,0 +1 @@
+xMAj0E)L6]ڀہv)XTѨҨo_JiZ-ۇ}U>Q.RK;p˱,kVKs|B@v]$_}U Sun0zQ#PمȼP%gR۾,whX21FN!.JV002WT2rnI]X6kRVdd')Q[٩H<ew7)6 i(cvdmt7C>&"r?v \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/a0/1a6ee390f65d834375e072952deaee0c5e92f7 b/tests/resources/rebase/.gitted/objects/a0/1a6ee390f65d834375e072952deaee0c5e92f7
new file mode 100644
index 000000000..eb98c9da5
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/a0/1a6ee390f65d834375e072952deaee0c5e92f7
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/a0/fa65f96c1e3bdc7287e334229279dcc1248fa4 b/tests/resources/rebase/.gitted/objects/a0/fa65f96c1e3bdc7287e334229279dcc1248fa4
new file mode 100644
index 000000000..fd43545ce
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/a0/fa65f96c1e3bdc7287e334229279dcc1248fa4
@@ -0,0 +1,3 @@
+xERn ޙDMS6iqL S|~tuRPZh~%ı9>|m۴ )VUAX*P3\j }[=yqgX$a\HL<+M#Hf+T2-3Wft]̣
+aB=d9:])$Ml Te>bykpmEWF
+L*XFFS$8SEzG\{3 C d,96ܣ왚;|╔dd9Y։ȏ'Aw@0hђAAEs0.D2Yõɯ9̃ \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/a1/25b9b655932711abceaf8962948e6b601d67b6 b/tests/resources/rebase/.gitted/objects/a1/25b9b655932711abceaf8962948e6b601d67b6
new file mode 100644
index 000000000..50bcee109
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/a1/25b9b655932711abceaf8962948e6b601d67b6
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/a7/00acc970eccccc73be53cd269462176544e6d1 b/tests/resources/rebase/.gitted/objects/a7/00acc970eccccc73be53cd269462176544e6d1
new file mode 100644
index 000000000..e5c62dba7
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/a7/00acc970eccccc73be53cd269462176544e6d1
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/a7/b066537e6be7109abfe4ff97b675d4e077da20 b/tests/resources/rebase/.gitted/objects/a7/b066537e6be7109abfe4ff97b675d4e077da20
new file mode 100644
index 000000000..54f9b6617
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/a7/b066537e6be7109abfe4ff97b675d4e077da20
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/aa/4c42aecdfc7cd989bbc3209934ea7cda3f4d88 b/tests/resources/rebase/.gitted/objects/aa/4c42aecdfc7cd989bbc3209934ea7cda3f4d88
new file mode 100644
index 000000000..628c2d3a1
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/aa/4c42aecdfc7cd989bbc3209934ea7cda3f4d88
@@ -0,0 +1 @@
+x B1D=m@=؁ l~#bFo3o`^ZK~՛dfL61G9)̘1568ezeO:wMzɡZ͠Csb. fԮ2o! Fw \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/ab/25a53ef5622d443ecb0492b7516725f0deac8f b/tests/resources/rebase/.gitted/objects/ab/25a53ef5622d443ecb0492b7516725f0deac8f
new file mode 100644
index 000000000..83ef51e26
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ab/25a53ef5622d443ecb0492b7516725f0deac8f
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/ad/c97cfb874cdfb9d5ab17b54f3771dea6e02ccf b/tests/resources/rebase/.gitted/objects/ad/c97cfb874cdfb9d5ab17b54f3771dea6e02ccf
new file mode 100644
index 000000000..cc7ccd086
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ad/c97cfb874cdfb9d5ab17b54f3771dea6e02ccf
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/ae/87cae12879a3c37d7cc994afc6395bcb0eaf99 b/tests/resources/rebase/.gitted/objects/ae/87cae12879a3c37d7cc994afc6395bcb0eaf99
new file mode 100644
index 000000000..5c8469eb9
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ae/87cae12879a3c37d7cc994afc6395bcb0eaf99
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/b1/46bd7608eac53d9bf9e1a6963543588b555c64 b/tests/resources/rebase/.gitted/objects/b1/46bd7608eac53d9bf9e1a6963543588b555c64
new file mode 100644
index 000000000..3e4b975a9
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/b1/46bd7608eac53d9bf9e1a6963543588b555c64
@@ -0,0 +1 @@
+xj1 D{W,eB.=!_7syÔmk@婢Ƃ3NCyds.% !w]YƯi9bU)bY-eN}i;|ק~:;OҶ`2#|t挻ZAo0cJT/ \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/b1/b94ec02f8ed87d0efa4c65fb38d5d6da7e8b32 b/tests/resources/rebase/.gitted/objects/b1/b94ec02f8ed87d0efa4c65fb38d5d6da7e8b32
new file mode 100644
index 000000000..d15c02246
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/b1/b94ec02f8ed87d0efa4c65fb38d5d6da7e8b32
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/b6/72b141d48c369fee6c4deeb32a904387594365 b/tests/resources/rebase/.gitted/objects/b6/72b141d48c369fee6c4deeb32a904387594365
new file mode 100644
index 000000000..d8cdb71ae
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/b6/72b141d48c369fee6c4deeb32a904387594365
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/b7/c536a5883c8adaeb34d5e198c5a3dbbdc608b5 b/tests/resources/rebase/.gitted/objects/b7/c536a5883c8adaeb34d5e198c5a3dbbdc608b5
new file mode 100644
index 000000000..b59498472
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/b7/c536a5883c8adaeb34d5e198c5a3dbbdc608b5
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/b9/f72b9158fa8c49fb4e4c10b26817ed867be803 b/tests/resources/rebase/.gitted/objects/b9/f72b9158fa8c49fb4e4c10b26817ed867be803
new file mode 100644
index 000000000..970166755
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/b9/f72b9158fa8c49fb4e4c10b26817ed867be803
@@ -0,0 +1,3 @@
+xO;N1 S
+d;Nf"! %=aFb&'{_[/}:7)y֤}`Bb.2]BӣCt3Gʲ$|QuIj4<Y5."[6yq& 2E攦pkm?BpCFg1~]u!ܢ NCU!pN17<v
+m_./d \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/bc/cc8eabb5cfe2ec09959c7f4155aa73429fd604 b/tests/resources/rebase/.gitted/objects/bc/cc8eabb5cfe2ec09959c7f4155aa73429fd604
new file mode 100644
index 000000000..de778eb11
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/bc/cc8eabb5cfe2ec09959c7f4155aa73429fd604
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/c4/e6cca3ec6ae0148ed231f97257df8c311e015f b/tests/resources/rebase/.gitted/objects/c4/e6cca3ec6ae0148ed231f97257df8c311e015f
new file mode 100644
index 000000000..2bbf28f57
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/c4/e6cca3ec6ae0148ed231f97257df8c311e015f
@@ -0,0 +1 @@
+x%P1n0 WCNEN7:*pԒ/WmI$=^^._?~|C6yTȄA(#1e鴓.(Hto@̸K-as1r6)&)8ŷTa<0ׇJ٢[K5IJcq͓쌫r_ۇ"u^@7~X)2 G,fR`B43vQH֩uab SwcJq)fƔOv; \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/c5/17380440ed78865ffe3fa130b9738615c76618 b/tests/resources/rebase/.gitted/objects/c5/17380440ed78865ffe3fa130b9738615c76618
new file mode 100644
index 000000000..b9a52a310
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/c5/17380440ed78865ffe3fa130b9738615c76618
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/cb/20a10406172afd6ca3138ce36ecaf8b1269e8e b/tests/resources/rebase/.gitted/objects/cb/20a10406172afd6ca3138ce36ecaf8b1269e8e
new file mode 100644
index 000000000..acd6bdc56
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/cb/20a10406172afd6ca3138ce36ecaf8b1269e8e
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/d4/82e77aecb8e07da43e4cad6e0dcb59219e12af b/tests/resources/rebase/.gitted/objects/d4/82e77aecb8e07da43e4cad6e0dcb59219e12af
new file mode 100644
index 000000000..af3bd174a
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/d4/82e77aecb8e07da43e4cad6e0dcb59219e12af
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/d6/16d97082eb7bb2dc6f180a7cca940993b7a56f b/tests/resources/rebase/.gitted/objects/d6/16d97082eb7bb2dc6f180a7cca940993b7a56f
new file mode 100644
index 000000000..fa2e8d9ef
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/d6/16d97082eb7bb2dc6f180a7cca940993b7a56f
@@ -0,0 +1 @@
+xNK u))0-Mqҝ`.Z ۋ{yɭjJ@D7D6qbyVW." VC'CGڛ$)%31^/!>D8]| lctׄDFVsFsN킁\RoV< \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/d6/b9ec0dfb972a6815ace42545cde5f2631cd776 b/tests/resources/rebase/.gitted/objects/d6/b9ec0dfb972a6815ace42545cde5f2631cd776
new file mode 100644
index 000000000..123970457
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/d6/b9ec0dfb972a6815ace42545cde5f2631cd776
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/da/82b3a60c50cf5ac524ec3000d743447329465d b/tests/resources/rebase/.gitted/objects/da/82b3a60c50cf5ac524ec3000d743447329465d
new file mode 100644
index 000000000..352a13ad3
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/da/82b3a60c50cf5ac524ec3000d743447329465d
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/da/9c51a23d02d931a486f45ad18cda05cf5d2b94 b/tests/resources/rebase/.gitted/objects/da/9c51a23d02d931a486f45ad18cda05cf5d2b94
new file mode 100644
index 000000000..85b78eed5
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/da/9c51a23d02d931a486f45ad18cda05cf5d2b94
@@ -0,0 +1,2 @@
+x;!9\@3@b1X1+WڲM_!5[K
+clʑ*ICuO+:P,q Py/"P'QٯmS}ږGIG+m9h8!bԹY<4YS \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/dc/12ac1e10f2be70e8ecd52132a08da98a309c3a b/tests/resources/rebase/.gitted/objects/dc/12ac1e10f2be70e8ecd52132a08da98a309c3a
new file mode 100644
index 000000000..9907248f8
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/dc/12ac1e10f2be70e8ecd52132a08da98a309c3a
@@ -0,0 +1 @@
+xMJ1]ϤAd@\UICwLDQ/mUAI1eqU<hKfOg$#2/] /%.(-. uxɟ3mu?鬿== x$D c@4sCycW 5]זkGJFQ- Zy \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/df/d3d25264693fcd7348ad286f3c34f3f6b30918 b/tests/resources/rebase/.gitted/objects/df/d3d25264693fcd7348ad286f3c34f3f6b30918
new file mode 100644
index 000000000..3de3fda62
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/df/d3d25264693fcd7348ad286f3c34f3f6b30918
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/e4/f809f826c1a9fc929874bc0e4644dd2f2a1af4 b/tests/resources/rebase/.gitted/objects/e4/f809f826c1a9fc929874bc0e4644dd2f2a1af4
new file mode 100644
index 000000000..e47501905
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/e4/f809f826c1a9fc929874bc0e4644dd2f2a1af4
@@ -0,0 +1,3 @@
+xM1]ym'0@%y 1"8 fW_tS&Be
+,O15Ⱦ` xpP?hrpb I9CYc p
+~|[+uOYVj!7TR CRDKXV \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/e5/2ff405da5b7e1e9b0929939fa8405d81fe8a45 b/tests/resources/rebase/.gitted/objects/e5/2ff405da5b7e1e9b0929939fa8405d81fe8a45
new file mode 100644
index 000000000..30c1987ed
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/e5/2ff405da5b7e1e9b0929939fa8405d81fe8a45
@@ -0,0 +1,3 @@
+x;j1]sV&eaV3U(
+~du4Z"KF/)&c!,Adv˄ٯ8lqAºm'C:u[ۿ#k+؉΅=Oyo\u*Xh
+ܫ]xV \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/e7/bb00c4eab291e08361fda376733a12b4150aa9 b/tests/resources/rebase/.gitted/objects/e7/bb00c4eab291e08361fda376733a12b4150aa9
new file mode 100644
index 000000000..da96e9d9c
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/e7/bb00c4eab291e08361fda376733a12b4150aa9
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/e8/8cc0a6919a74599ce8e1dcb81eb2bbae33a645 b/tests/resources/rebase/.gitted/objects/e8/8cc0a6919a74599ce8e1dcb81eb2bbae33a645
new file mode 100644
index 000000000..e8ce1728b
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/e8/8cc0a6919a74599ce8e1dcb81eb2bbae33a645
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/e9/5f47e016dcc70b0b888df8e40e97b8aabafd4c b/tests/resources/rebase/.gitted/objects/e9/5f47e016dcc70b0b888df8e40e97b8aabafd4c
new file mode 100644
index 000000000..cc3312a47
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/e9/5f47e016dcc70b0b888df8e40e97b8aabafd4c
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/e9/f22c10ffb378446c0bbcab7ee3d9d5a0040672 b/tests/resources/rebase/.gitted/objects/e9/f22c10ffb378446c0bbcab7ee3d9d5a0040672
new file mode 100644
index 000000000..3446b2f8a
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/e9/f22c10ffb378446c0bbcab7ee3d9d5a0040672
@@ -0,0 +1,2 @@
+xMj0{S\z
+9`ڂiB~=:iavvZ-ۧחcSᴿ6.g?q~?5>^ADbEP0 CFW%V&:1wFaC]F:Ti_28/RRpq2yвp+w Q@ԫ.`P 0_BR-&{YZ怩pP>{YiSɈH1RZɳ3ypRJ[gpM1ny_ ZNkb? \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/ec/725f5639730640f91cd0be5f2d6d7ac5d69c79 b/tests/resources/rebase/.gitted/objects/ec/725f5639730640f91cd0be5f2d6d7ac5d69c79
new file mode 100644
index 000000000..0fb3334db
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ec/725f5639730640f91cd0be5f2d6d7ac5d69c79
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/ed/f7b3ffde1624c60d2d6b1a2bb792d86de172e0 b/tests/resources/rebase/.gitted/objects/ed/f7b3ffde1624c60d2d6b1a2bb792d86de172e0
new file mode 100644
index 000000000..e2e98d6d8
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ed/f7b3ffde1624c60d2d6b1a2bb792d86de172e0
@@ -0,0 +1,3 @@
+xOKN!u)h
+ct f?8fb8{}o:`I0U…ZbH-PKўhE k=t@LrBق>!EnDph~K?C~!pSCoz3
+!D <轛;1]d~juZU \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/ee/23c5eeedadf8595c0ff60a366d970a165e373d b/tests/resources/rebase/.gitted/objects/ee/23c5eeedadf8595c0ff60a366d970a165e373d
new file mode 100644
index 000000000..b32600f78
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ee/23c5eeedadf8595c0ff60a366d970a165e373d
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/ee/f0edde5daa94da5f297d4ddb5dfbc1980f0902 b/tests/resources/rebase/.gitted/objects/ee/f0edde5daa94da5f297d4ddb5dfbc1980f0902
new file mode 100644
index 000000000..e9b3f58c6
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ee/f0edde5daa94da5f297d4ddb5dfbc1980f0902
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/ef/ad0b11c47cb2f0220cbd6f5b0f93bb99064b00 b/tests/resources/rebase/.gitted/objects/ef/ad0b11c47cb2f0220cbd6f5b0f93bb99064b00
new file mode 100644
index 000000000..285e14056
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ef/ad0b11c47cb2f0220cbd6f5b0f93bb99064b00
@@ -0,0 +1 @@
+x=n0 3@ d.D&l^jt{?J[ץ%:]r)I`_Lϖٴ|a3F1H"xfoXb%&'~k;|o+\nm=gzg^K[3D> ^خq.@1qV \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/f5/56d5fef35003561dc0b64b37057d7541239105 b/tests/resources/rebase/.gitted/objects/f5/56d5fef35003561dc0b64b37057d7541239105
new file mode 100644
index 000000000..f4143e1f5
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/f5/56d5fef35003561dc0b64b37057d7541239105
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/f6/3fa37e285bd11b0a7b48fa584a4091814a3ada b/tests/resources/rebase/.gitted/objects/f6/3fa37e285bd11b0a7b48fa584a4091814a3ada
new file mode 100644
index 000000000..e650383a2
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/f6/3fa37e285bd11b0a7b48fa584a4091814a3ada
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/f7/5c193a1df47186727179f24867bc4d27a8991f b/tests/resources/rebase/.gitted/objects/f7/5c193a1df47186727179f24867bc4d27a8991f
new file mode 100644
index 000000000..618cb6814
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/f7/5c193a1df47186727179f24867bc4d27a8991f
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/f8/7d14a4a236582a0278a916340a793714256864 b/tests/resources/rebase/.gitted/objects/f8/7d14a4a236582a0278a916340a793714256864
new file mode 100644
index 000000000..1d29712c5
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/f8/7d14a4a236582a0278a916340a793714256864
@@ -0,0 +1,2 @@
+xKAD])Uqҝ6Жz}an0<n<uT6}Q4$1&+)E.Xh>N1K~h[#Ub4cPLƼijGE|i[WIy!anl޸S&>
+O{T \ No newline at end of file
diff --git a/tests/resources/rebase/.gitted/objects/fc/e0584b379f535e50e036db587db71884ea6b36 b/tests/resources/rebase/.gitted/objects/fc/e0584b379f535e50e036db587db71884ea6b36
new file mode 100644
index 000000000..ce8b2fb54
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/fc/e0584b379f535e50e036db587db71884ea6b36
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/ff/b36e513f5fdf8a6ba850a20142676a2ac4807d b/tests/resources/rebase/.gitted/objects/ff/b36e513f5fdf8a6ba850a20142676a2ac4807d
new file mode 100644
index 000000000..f655d12ea
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ff/b36e513f5fdf8a6ba850a20142676a2ac4807d
Binary files differ
diff --git a/tests/resources/rebase/.gitted/objects/ff/dfa89389040a87008c4ab1834120d3046daaea b/tests/resources/rebase/.gitted/objects/ff/dfa89389040a87008c4ab1834120d3046daaea
new file mode 100644
index 000000000..54c938e2e
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/ff/dfa89389040a87008c4ab1834120d3046daaea
Binary files differ
diff --git a/tests/resources/rebase/.gitted/refs/heads/asparagus b/tests/resources/rebase/.gitted/refs/heads/asparagus
new file mode 100644
index 000000000..a3c9d67c4
--- /dev/null
+++ b/tests/resources/rebase/.gitted/refs/heads/asparagus
@@ -0,0 +1 @@
+4b21eb6eeeec7f8fc89a1d334faff9bd5f5f8c34
diff --git a/tests/resources/rebase/.gitted/refs/heads/barley b/tests/resources/rebase/.gitted/refs/heads/barley
new file mode 100644
index 000000000..feab9443f
--- /dev/null
+++ b/tests/resources/rebase/.gitted/refs/heads/barley
@@ -0,0 +1 @@
+12c084412b952396962eb420716df01022b847cc
diff --git a/tests/resources/rebase/.gitted/refs/heads/beef b/tests/resources/rebase/.gitted/refs/heads/beef
new file mode 100644
index 000000000..1c69e6ac5
--- /dev/null
+++ b/tests/resources/rebase/.gitted/refs/heads/beef
@@ -0,0 +1 @@
+b146bd7608eac53d9bf9e1a6963543588b555c64
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 000000000..9ede6023c
--- /dev/null
+++ b/tests/resources/rebase/.gitted/refs/heads/dried_pea
@@ -0,0 +1 @@
+7f37fe2d7320360f8a9118b1ed8fba6f38481679
diff --git a/tests/resources/rebase/.gitted/refs/heads/gravy b/tests/resources/rebase/.gitted/refs/heads/gravy
new file mode 100644
index 000000000..3753b7330
--- /dev/null
+++ b/tests/resources/rebase/.gitted/refs/heads/gravy
@@ -0,0 +1 @@
+d616d97082eb7bb2dc6f180a7cca940993b7a56f
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 000000000..3bffe27d1
--- /dev/null
+++ b/tests/resources/rebase/.gitted/refs/heads/green_pea
@@ -0,0 +1 @@
+d482e77aecb8e07da43e4cad6e0dcb59219e12af
diff --git a/tests/resources/rebase/.gitted/refs/heads/master b/tests/resources/rebase/.gitted/refs/heads/master
new file mode 100644
index 000000000..abbe9cc15
--- /dev/null
+++ b/tests/resources/rebase/.gitted/refs/heads/master
@@ -0,0 +1 @@
+efad0b11c47cb2f0220cbd6f5b0f93bb99064b00
diff --git a/tests/resources/rebase/.gitted/refs/heads/veal b/tests/resources/rebase/.gitted/refs/heads/veal
new file mode 100644
index 000000000..484f48976
--- /dev/null
+++ b/tests/resources/rebase/.gitted/refs/heads/veal
@@ -0,0 +1 @@
+f87d14a4a236582a0278a916340a793714256864
diff --git a/tests/resources/rebase/asparagus.txt b/tests/resources/rebase/asparagus.txt
new file mode 100644
index 000000000..67ed7afb2
--- /dev/null
+++ b/tests/resources/rebase/asparagus.txt
@@ -0,0 +1,10 @@
+ASPARAGUS SOUP.
+
+TAKE FOUR LARGE BUNCHES of asparagus, scrape it nicely, cut off one inch
+OF THE TOPS, and lay them in water, chop the stalks and put them on the
+FIRE WITH A PIECE OF BACON, a large onion cut up, and pepper and salt;
+ADD TWO QUARTS OF WATER, boil them till the stalks are quite soft, then
+PULP THEM THROUGH A SIEVE, and strain the water to it, which must be put
+back in the pot; put into it a chicken cut up, with the tops of
+asparagus which had been laid by, boil it until these last articles are
+sufficiently done, thicken with flour, butter and milk, and serve it up.
diff --git a/tests/resources/rebase/beef.txt b/tests/resources/rebase/beef.txt
new file mode 100644
index 000000000..68f6182f4
--- /dev/null
+++ b/tests/resources/rebase/beef.txt
@@ -0,0 +1,22 @@
+BEEF SOUP.
+
+Take the hind shin of beef, cut off all the flesh off the leg-bone,
+which must be taken away entirely, or the soup will be greasy. Wash the
+meat clean and lay it in a pot, sprinkle over it one small
+table-spoonful of pounded black pepper, and two of salt; three onions
+the size of a hen's egg, cut small, six small carrots scraped and cut
+up, two small turnips pared and cut into dice; pour on three quarts of
+water, cover the pot close, and keep it gently and steadily boiling five
+hours, which will leave about three pints of clear soup; do not let the
+pot boil over, but take off the scum carefully, as it rises. When it has
+boiled four hours, put in a small bundle of thyme and parsley, and a
+pint of celery cut small, or a tea-spoonful of celery seed pounded.
+These latter ingredients would lose their delicate flavour if boiled too
+much. Just before you take it up, brown it in the following manner: put
+a small table-spoonful of nice brown sugar into an iron skillet, set it
+on the fire and stir it till it melts and looks very dark, pour into it
+a ladle full of the soup, a little at a time; stirring it all the while.
+Strain this browning and mix it well with the soup; take out the bundle
+of thyme and parsley, put the nicest pieces of meat in your tureen, and
+pour on the soup and vegetables; put in some toasted bread cut in dice,
+and serve it up.
diff --git a/tests/resources/rebase/bouilli.txt b/tests/resources/rebase/bouilli.txt
new file mode 100644
index 000000000..4b7c56500
--- /dev/null
+++ b/tests/resources/rebase/bouilli.txt
@@ -0,0 +1,18 @@
+SOUP WITH BOUILLI.
+
+Take the nicest part of the thick brisket of beef, about eight pounds,
+put it into a pot with every thing directed for the other soup; make it
+exactly in the same way, only put it on an hour sooner, that you may
+have time to prepare the bouilli; after it has boiled five hours, take
+out the beef, cover up the soup and set it near the fire that it may
+keep hot. Take the skin off the beef, have the yelk of an egg well
+beaten, dip a feather in it and wash the top of your beef, sprinkle over
+it the crumb of stale bread finely grated, put it in a Dutch oven
+previously heated, put the top on with coals enough to brown, but not
+burn the beef; let it stand nearly an hour, and prepare your gravy
+thus:--Take a sufficient quantity of soup and the vegetables boiled in
+it; add to it a table-spoonful of red wine, and two of mushroom catsup,
+thicken with a little bit of butter and a little brown flour; make it
+very hot, pour it in your dish, and put the beef on it. Garnish it with
+green pickle, cut in thin slices, serve up the soup in a tureen with
+bits of toasted bread.
diff --git a/tests/resources/rebase/gravy.txt b/tests/resources/rebase/gravy.txt
new file mode 100644
index 000000000..c4e6cca3e
--- /dev/null
+++ b/tests/resources/rebase/gravy.txt
@@ -0,0 +1,8 @@
+GRAVY SOUP.
+
+Get eight pounds of coarse lean beef--wash it clean and lay it in your
+pot, put in the same ingredients as for the shin soup, with the same
+quantity of water, and follow the process directed for that. Strain the
+soup through a sieve, and serve it up clear, with nothing more than
+toasted bread in it; two table-spoonsful of mushroom catsup will add a
+fine flavour to the soup.
diff --git a/tests/resources/rebase/oyster.txt b/tests/resources/rebase/oyster.txt
new file mode 100644
index 000000000..68af1fc74
--- /dev/null
+++ b/tests/resources/rebase/oyster.txt
@@ -0,0 +1,13 @@
+OYSTER SOUP.
+
+Wash and drain two quarts of oysters, put them on with three quarts of
+water, three onions chopped up, two or three slices of lean ham, pepper
+and salt; boil it till reduced one-half, strain it through a sieve,
+return the liquid into the pot, put in one quart of fresh oysters, boil
+it till they are sufficiently done, and thicken the soup with four
+spoonsful of flour, two gills of rich cream, and the yelks of six new
+laid eggs beaten well; boil it a few minutes after the thickening is put
+in. Take care that it does not curdle, and that the flour is not in
+lumps; serve it up with the last oysters that were put in. If the
+flavour of thyme be agreeable, you may put in a little, but take care
+that it does not boil in it long enough to discolour the soup.
diff --git a/tests/resources/rebase/veal.txt b/tests/resources/rebase/veal.txt
new file mode 100644
index 000000000..a7b066537
--- /dev/null
+++ b/tests/resources/rebase/veal.txt
@@ -0,0 +1,18 @@
+VEAL SOUP.
+
+Put into a pot three quarts of water, three onions cut small, one
+spoonful of black pepper pounded, and two of salt, with two or three
+slices of lean ham; let it boil steadily two hours; skim it
+occasionally, then put into it a shin of veal, let it boil two hours
+longer; take out the slices of ham, and skim off the grease if any
+should rise, take a gill of good cream, mix with it two table-spoonsful
+of flour very nicely, and the yelks of two eggs beaten well, strain this
+mixture, and add some chopped parsley; pour some soup on by degrees,
+stir it well, and pour it into the pot, continuing to stir until it has
+boiled two or three minutes to take off the raw taste of the eggs. If
+the cream be not perfectly sweet, and the eggs quite new, the thickening
+will curdle in the soup. For a change you may put a dozen ripe tomatos
+in, first taking off their skins, by letting them stand a few minutes in
+hot water, when they may be easily peeled. When made in this way you
+must thicken it with the flour only. Any part of the veal may be used,
+but the shin or knuckle is the nicest.