Commit 18b439b9 by Edward Thomson

git_rebase_next: provide info about the operation

parent 5ae9d296
......@@ -39,9 +39,67 @@ typedef struct {
const char *rewrite_notes_ref;
} git_rebase_options;
/** Type of rebase operation in-progress after calling `git_rebase_next`. */
typedef enum {
/**
* The given commit is to be cherry-picked. The client should commit
* the changes and continue if there are no conflicts.
*/
GIT_REBASE_OPERATION_PICK = 0,
/**
* The given commit is to be cherry-picked, but the client should prompt
* the user to provide an updated commit message.
*/
GIT_REBASE_OPERATION_REWORD,
/**
* The given commit is to be cherry-picked, but the client should stop
* to allow the user to edit the changes before committing them.
*/
GIT_REBASE_OPERATION_EDIT,
/**
* The given commit is to be squashed into the previous commit. The
* commit message will be merged with the previous message.
*/
GIT_REBASE_OPERATION_SQUASH,
/**
* The given commit is to be squashed into the previous commit. The
* commit message from this commit will be discarded.
*/
GIT_REBASE_OPERATION_FIXUP,
/**
* No commit will be cherry-picked. The client should run the given
* command and (if successful) continue.
*/
GIT_REBASE_OPERATION_EXEC,
} git_rebase_operation_t;
#define GIT_REBASE_OPTIONS_VERSION 1
#define GIT_REBASE_OPTIONS_INIT {GIT_REBASE_OPTIONS_VERSION}
typedef struct {
/** The type of rebase operation. */
unsigned int type;
union {
/**
* The commit ID being cherry-picked. This will be populated for
* all operations except those of type `GIT_REBASE_OPERATION_EXEC`.
*/
git_oid id;
/**
* The executable the user has requested be run. This will only
* be populated for operations of type `GIT_REBASE_OPERATION_EXEC`.
*/
const char *exec;
};
} git_rebase_operation;
/**
* Initializes a `git_rebase_options` with default values. Equivalent to
* creating an instance with GIT_REBASE_OPTIONS_INIT.
......@@ -78,15 +136,19 @@ GIT_EXTERN(int) git_rebase(
const git_rebase_options *opts);
/**
* Applies the next patch, updating the index and working directory with the
* changes. If there are conflicts, you will need to address those before
* committing the changes.
* Performs the next rebase operation and returns the information about it.
* If the operation is one that applies a patch (which is any operation except
* GIT_REBASE_OPERATION_EXEC) then the patch will be applied and the index and
* working directory will be updated with the changes. If there are conflicts,
* you will need to address those before committing the changes.
*
* @param out The rebase operation that is to be performed next
* @param repo The repository with a rebase in progress
* @param checkout_opts Options to specify how the patch should be checked out
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_rebase_next(
git_rebase_operation *operation,
git_repository *repo,
git_checkout_options *checkout_opts);
......@@ -94,7 +156,7 @@ GIT_EXTERN(int) git_rebase_next(
* Commits the current patch. You must have resolved any conflicts that
* were introduced during the patch application from the `git_rebase_next`
* invocation.
*
*
* @param id Pointer in which to store the OID of the newly created commit
* @param repo The repository with the in-progress rebase
* @param author The author of the updated commit, or NULL to keep the
......@@ -105,8 +167,8 @@ GIT_EXTERN(int) git_rebase_next(
* this should also be NULL, and the encoding from the original
* commit will be maintained. If message is specified, this may be
* NULL to indicate that "UTF-8" is to be used.
* @param message The message for this commit, or NULL to keep the message
* from the original commit
* @param message The message for this commit, or NULL to use the message
* from the original commit.
* @return Zero on success, GIT_EUNMERGED if there are unmerged changes in
* the index, GIT_EAPPLIED if the current commit has already
* been applied to the upstream and there is nothing to commit,
......
......@@ -624,6 +624,7 @@ static int normalize_checkout_opts(
}
static int rebase_next_merge(
git_rebase_operation *out,
git_repository *repo,
git_rebase_state *state,
git_checkout_options *given_checkout_opts)
......@@ -678,6 +679,9 @@ static int rebase_next_merge(
(error = git_checkout_index(repo, index, &checkout_opts)) < 0)
goto done;
out->type = GIT_REBASE_OPERATION_PICK;
memcpy(&out->id, &current_id, sizeof(git_oid));
done:
git_index_free(index);
git_tree_free(current_tree);
......@@ -691,20 +695,23 @@ done:
}
int git_rebase_next(
git_rebase_operation *out,
git_repository *repo,
git_checkout_options *checkout_opts)
{
git_rebase_state state = GIT_REBASE_STATE_INIT;
int error;
assert(repo);
assert(out && repo);
memset(out, 0, sizeof(git_rebase_operation));
if ((error = rebase_state(&state, repo)) < 0)
return -1;
switch (state.type) {
case GIT_REBASE_TYPE_MERGE:
error = rebase_next_merge(repo, &state, checkout_opts);
error = rebase_next_merge(out, repo, &state, checkout_opts);
break;
default:
abort();
......
......@@ -26,10 +26,11 @@ void test_rebase_merge__next(void)
{
git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_status_list *status_list;
const git_status_entry *status_entry;
git_oid file1_id;
git_oid pick_id, file1_id;
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
......@@ -41,8 +42,12 @@ void test_rebase_merge__next(void)
cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
git_oid_fromstr(&pick_id, "da9c51a23d02d931a486f45ad18cda05cf5d2b94");
cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation.type);
cl_assert_equal_oid(&pick_id, &rebase_operation.id);
cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n", 41, "rebase/.git/rebase-merge/current");
cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum");
......@@ -66,9 +71,11 @@ void test_rebase_merge__next_with_conflicts(void)
{
git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_status_list *status_list;
const git_status_entry *status_entry;
git_oid pick_id;
const char *expected_merge =
"ASPARAGUS SOUP.\n"
......@@ -100,8 +107,12 @@ void test_rebase_merge__next_with_conflicts(void)
cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
git_oid_fromstr(&pick_id, "33f915f9e4dbd9f4b24430e48731a59b45b15500");
cl_assert_equal_i(GIT_REBASE_OPERATION_PICK, rebase_operation.type);
cl_assert_equal_oid(&pick_id, &rebase_operation.id);
cl_assert_equal_file("33f915f9e4dbd9f4b24430e48731a59b45b15500\n", 41, "rebase/.git/rebase-merge/current");
cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/msgnum");
......@@ -124,6 +135,7 @@ void test_rebase_merge__next_stops_with_iterover(void)
{
git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_oid commit_id;
int error;
......@@ -138,27 +150,27 @@ void test_rebase_merge__next_stops_with_iterover(void)
cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
cl_git_fail(error = git_rebase_next(repo, &checkout_opts));
cl_git_fail(error = git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_assert_equal_i(GIT_ITEROVER, error);
cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end");
......@@ -174,6 +186,7 @@ void test_rebase_merge__commit(void)
{
git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_oid commit_id, tree_id, parent_id;
git_signature *author;
......@@ -191,7 +204,7 @@ void test_rebase_merge__commit(void)
cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
......@@ -233,6 +246,7 @@ void test_rebase_merge__commit_updates_rewritten(void)
{
git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_oid commit_id;
......@@ -246,11 +260,11 @@ void test_rebase_merge__commit_updates_rewritten(void)
cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
......@@ -269,6 +283,7 @@ void test_rebase_merge__commit_drops_already_applied(void)
{
git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_oid commit_id;
int error;
......@@ -283,13 +298,13 @@ void test_rebase_merge__commit_drops_already_applied(void)
cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_fail(error = git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
cl_assert_equal_i(GIT_EAPPLIED, error);
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
......@@ -307,6 +322,7 @@ void test_rebase_merge__finish(void)
{
git_reference *branch_ref, *upstream_ref, *head_ref;
git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_oid commit_id;
git_reflog *reflog;
......@@ -323,11 +339,11 @@ void test_rebase_merge__finish(void)
cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
cl_git_fail(error = git_rebase_next(repo, &checkout_opts));
cl_git_fail(error = git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_assert_equal_i(GIT_ITEROVER, error);
cl_git_pass(git_rebase_finish(repo, signature, NULL));
......@@ -367,6 +383,7 @@ static void test_copy_note(
git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head;
git_commit *branch_commit;
git_rebase_operation rebase_operation;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_oid note_id, commit_id;
git_note *note = NULL;
......@@ -391,7 +408,7 @@ static void test_copy_note(
cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, opts));
cl_git_pass(git_rebase_next(repo, &checkout_opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
NULL, NULL));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment