Commit 1aa14921 by Carlos Martín Nieto

Merge pull request #3615 from ethomson/rebase_bare

rebase: persist a single in-memory index
parents 5a296ad0 f28bae0c
......@@ -142,12 +142,6 @@ typedef struct {
* be populated for operations of type `GIT_REBASE_OPERATION_EXEC`.
*/
const char *exec;
/**
* The index that is the result of an operation.
* This is set only for in-memory rebases.
*/
git_index *index;
} git_rebase_operation;
/**
......@@ -248,6 +242,21 @@ GIT_EXTERN(int) git_rebase_next(
git_rebase *rebase);
/**
* Gets the index produced by the last operation, which is the result
* of `git_rebase_next` and which will be committed by the next
* invocation of `git_rebase_commit`. This is useful for resolving
* conflicts in an in-memory rebase before committing them. You must
* call `git_index_free` when you are finished with this.
*
* This is only applicable for in-memory rebases; for rebases within
* a working directory, the changes were applied to the repository's
* index.
*/
GIT_EXTERN(int) git_rebase_inmemory_index(
git_index **index,
git_rebase *rebase);
/**
* Commits the current patch. You must have resolved any conflicts that
* were introduced during the patch application from the `git_rebase_next`
* invocation.
......
......@@ -71,8 +71,8 @@ struct git_rebase {
size_t current;
/* Used by in-memory rebase */
git_index *index;
git_commit *last_commit;
git_index *last_index;
/* Used by regular (not in-memory) merge-style rebase */
git_oid orig_head_id;
......@@ -856,10 +856,13 @@ static int rebase_next_inmemory(
(error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0)
goto done;
git_index_free(rebase->last_index);
rebase->last_index = index;
operation->index = index;
index = NULL;
if (!rebase->index) {
rebase->index = index;
index = NULL;
} else {
if ((error = git_index_read_index(rebase->index, index)) < 0)
goto done;
}
*out = operation;
......@@ -895,6 +898,18 @@ int git_rebase_next(
return error;
}
int git_rebase_inmemory_index(
git_index **out,
git_rebase *rebase)
{
assert(out && rebase && rebase->index);
GIT_REFCOUNT_INC(rebase->index);
*out = rebase->index;
return 0;
}
static int rebase_commit__create(
git_commit **out,
git_rebase *rebase,
......@@ -1018,17 +1033,13 @@ static int rebase_commit_inmemory(
operation = git_array_get(rebase->operations, rebase->current);
assert(operation);
assert(operation->index);
assert(rebase->index);
assert(rebase->last_commit);
if ((error = rebase_commit__create(&commit, rebase, operation->index,
if ((error = rebase_commit__create(&commit, rebase, rebase->index,
rebase->last_commit, author, committer, message_encoding, message)) < 0)
goto done;
git_index_free(rebase->last_index);
operation->index = NULL;
rebase->last_index = NULL;
git_commit_free(rebase->last_commit);
rebase->last_commit = commit;
......@@ -1313,7 +1324,7 @@ void git_rebase_free(git_rebase *rebase)
if (rebase == NULL)
return;
git_index_free(rebase->last_index);
git_index_free(rebase->index);
git_commit_free(rebase->last_commit);
git__free(rebase->onto_name);
git__free(rebase->orig_head_name);
......
......@@ -54,7 +54,7 @@ void test_rebase_inmemory__can_resolve_conflicts(void)
git_status_list *status_list;
git_oid pick_id, commit_id, expected_commit_id;
git_signature *signature;
git_index *repo_index;
git_index *rebase_index, *repo_index;
git_index_entry resolution = {{0}};
git_rebase_options opts = GIT_REBASE_OPTIONS_INIT;
......@@ -86,7 +86,8 @@ void test_rebase_inmemory__can_resolve_conflicts(void)
cl_assert_equal_i(0, git_status_list_entrycount(status_list));
/* but that the index returned from rebase does have conflicts */
cl_assert(git_index_has_conflicts(rebase_operation->index));
cl_git_pass(git_rebase_inmemory_index(&rebase_index, rebase));
cl_assert(git_index_has_conflicts(rebase_index));
cl_git_fail_with(GIT_EUNMERGED, git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL));
......@@ -94,8 +95,8 @@ void test_rebase_inmemory__can_resolve_conflicts(void)
resolution.path = "asparagus.txt";
resolution.mode = GIT_FILEMODE_BLOB;
git_oid_fromstr(&resolution.id, "414dfc71ead79c07acd4ea47fecf91f289afc4b9");
cl_git_pass(git_index_conflict_remove(rebase_operation->index, "asparagus.txt"));
cl_git_pass(git_index_add(rebase_operation->index, &resolution));
cl_git_pass(git_index_conflict_remove(rebase_index, "asparagus.txt"));
cl_git_pass(git_index_add(rebase_index, &resolution));
/* and finally create a commit for the resolved rebase operation */
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL));
......@@ -110,5 +111,6 @@ void test_rebase_inmemory__can_resolve_conflicts(void)
git_reference_free(branch_ref);
git_reference_free(upstream_ref);
git_index_free(repo_index);
git_index_free(rebase_index);
git_rebase_free(rebase);
}
......@@ -13,7 +13,8 @@ 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"));
cl_git_pass(git_signature_new(&signature, "Rebaser",
"rebaser@rebaser.rb", 1405694510, 0));
}
void test_rebase_iterator__cleanup(void)
......@@ -53,7 +54,7 @@ void test_iterator(bool inmemory)
git_reference *branch_ref, *upstream_ref;
git_annotated_commit *branch_head, *upstream_head;
git_rebase_operation *rebase_operation;
git_oid commit_id;
git_oid commit_id, expected_id;
int error;
opts.inmemory = inmemory;
......@@ -77,16 +78,25 @@ void test_iterator(bool inmemory)
NULL, NULL));
test_operations(rebase, 0);
git_oid_fromstr(&expected_id, "776e4c48922799f903f03f5f6e51da8b01e4cce0");
cl_assert_equal_oid(&expected_id, &commit_id);
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL));
test_operations(rebase, 1);
git_oid_fromstr(&expected_id, "ba1f9b4fd5cf8151f7818be2111cc0869f1eb95a");
cl_assert_equal_oid(&expected_id, &commit_id);
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL));
test_operations(rebase, 2);
git_oid_fromstr(&expected_id, "948b12fe18b84f756223a61bece4c307787cd5d4");
cl_assert_equal_oid(&expected_id, &commit_id);
if (!inmemory) {
git_rebase_free(rebase);
cl_git_pass(git_rebase_open(&rebase, repo, NULL));
......@@ -97,11 +107,17 @@ void test_iterator(bool inmemory)
NULL, NULL));
test_operations(rebase, 3);
git_oid_fromstr(&expected_id, "d9d5d59d72c9968687f9462578d79878cd80e781");
cl_assert_equal_oid(&expected_id, &commit_id);
cl_git_pass(git_rebase_next(&rebase_operation, rebase));
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL));
test_operations(rebase, 4);
git_oid_fromstr(&expected_id, "9cf383c0a125d89e742c5dec58ed277dd07588b3");
cl_assert_equal_oid(&expected_id, &commit_id);
cl_git_fail(error = git_rebase_next(&rebase_operation, rebase));
cl_assert_equal_i(GIT_ITEROVER, error);
test_operations(rebase, 4);
......
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