git_rebase: iterators for operations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
diff --git a/include/git2/rebase.h b/include/git2/rebase.h
index 9ffdc48..b9b0af7 100644
--- a/include/git2/rebase.h
+++ b/include/git2/rebase.h
@@ -150,6 +150,33 @@ GIT_EXTERN(int) git_rebase_init(
GIT_EXTERN(int) git_rebase_open(git_rebase **out, git_repository *repo);
/**
+ * Gets the count of rebase operations that are to be applied.
+ *
+ * @param rebase The in-progress rebase
+ * @return The number of rebase operations in total
+ */
+GIT_EXTERN(size_t) git_rebase_operation_entrycount(git_rebase *rebase);
+
+/**
+ * Gets the index of the rebase operation that is currently being applied.
+ *
+ * @param rebase The in-progress rebase
+ * @return The index of the rebase operation currently being applied.
+ */
+GIT_EXTERN(size_t) git_rebase_operation_current(git_rebase *rebase);
+
+/**
+ * Gets the rebase operation specified by the given index.
+ *
+ * @param rebase The in-progress rebase
+ * @param idx The index of the rebase operation to retrieve
+ * @return The rebase operation or NULL if `idx` was out of bounds
+ */
+GIT_EXTERN(git_rebase_operation *) git_rebase_operation_byindex(
+ git_rebase *rebase,
+ size_t idx);
+
+/**
* Performs the next rebase operation and returns the information about it.
* If the operation is one that applies a patch (which is any operation except
* GIT_REBASE_OPERATION_EXEC) then the patch will be applied and the index and
diff --git a/src/rebase.c b/src/rebase.c
index 635682f..a4e9bad 100644
--- a/src/rebase.c
+++ b/src/rebase.c
@@ -1087,6 +1087,27 @@ done:
return error;
}
+size_t git_rebase_operation_entrycount(git_rebase *rebase)
+{
+ assert(rebase);
+
+ return git_array_size(rebase->operations);
+}
+
+size_t git_rebase_operation_current(git_rebase *rebase)
+{
+ assert(rebase);
+
+ return rebase->current;
+}
+
+git_rebase_operation *git_rebase_operation_byindex(git_rebase *rebase, size_t idx)
+{
+ assert(rebase);
+
+ return git_array_get(rebase->operations, idx);
+}
+
void git_rebase_free(git_rebase *rebase)
{
if (rebase == NULL)
diff --git a/tests/rebase/iterator.c b/tests/rebase/iterator.c
new file mode 100644
index 0000000..cfc6dce
--- /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_merge_head *branch_head, *upstream_head;
+ git_rebase_operation *rebase_operation;
+ git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
+ git_oid commit_id;
+ int error;
+
+ checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+
+ cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
+ cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
+
+ cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref));
+ cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref));
+
+ cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
+ test_operations(rebase, 0);
+ git_rebase_free(rebase);
+
+ cl_git_pass(git_rebase_open(&rebase, repo));
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+ test_operations(rebase, 0);
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+ test_operations(rebase, 1);
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+ test_operations(rebase, 2);
+
+ git_rebase_free(rebase);
+ cl_git_pass(git_rebase_open(&rebase, repo));
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+ test_operations(rebase, 3);
+
+ cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
+ NULL, NULL));
+ test_operations(rebase, 4);
+
+ cl_git_fail(error = git_rebase_next(&rebase_operation, rebase, &checkout_opts));
+ cl_assert_equal_i(GIT_ITEROVER, error);
+ test_operations(rebase, 4);
+
+ git_merge_head_free(branch_head);
+ git_merge_head_free(upstream_head);
+ git_reference_free(branch_ref);
+ git_reference_free(upstream_ref);
+ git_rebase_free(rebase);
+}