summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2014-07-18 14:50:06 -0400
committerEdward Thomson <ethomson@microsoft.com>2014-10-26 22:59:21 -0400
commit93a7004cc234da31d912bb0f266c39b99ab8c8db (patch)
tree06fc49a4dda32a64a77e221f6ebe7109d1754d1b
parenta35a9890b00b538cd0f3ef94a526c0dd2ec461bf (diff)
downloadlibgit2-93a7004cc234da31d912bb0f266c39b99ab8c8db.tar.gz
git_rebase_commit: drop already-picked commits
Already cherry-picked commits should not be re-included. If all changes included in a commit exist in the upstream, then we should error with GIT_EAPPLIED.
-rw-r--r--include/git2/errors.h1
-rw-r--r--include/git2/rebase.h4
-rw-r--r--src/rebase.c19
-rw-r--r--tests/rebase/merge.c38
-rw-r--r--tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177acbin0 -> 241 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/50/8be4ff49d38465ad3de58f66d38f70e59f881fbin0 -> 241 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/61/139b9b40a3e489f4abbc6af14e10ae14006e47bin0 -> 224 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/ad/c97cfb874cdfb9d5ab17b54f3771dea6e02ccfbin0 -> 240 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/dc/12ac1e10f2be70e8ecd52132a08da98a309c3a1
-rw-r--r--tests/resources/rebase/.gitted/objects/e7/bb00c4eab291e08361fda376733a12b4150aa9bin0 -> 241 bytes
-rw-r--r--tests/resources/rebase/.gitted/objects/ed/f7b3ffde1624c60d2d6b1a2bb792d86de172e03
-rw-r--r--tests/resources/rebase/.gitted/refs/heads/green_pea1
14 files changed, 62 insertions, 5 deletions
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 5dfa72ab8..b33118e02 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -43,6 +43,7 @@ typedef enum {
GIT_EMODIFIED = -15, /**< Reference value does not match expected */
GIT_EAUTH = -16, /**< Authentication error */
GIT_ECERTIFICATE = -17, /**< Server certificate is invalid */
+ GIT_EAPPLIED = -18, /**< Patch/merge has already been applied */
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
diff --git a/include/git2/rebase.h b/include/git2/rebase.h
index 0fe2b263d..32b4ff614 100644
--- a/include/git2/rebase.h
+++ b/include/git2/rebase.h
@@ -99,7 +99,9 @@ GIT_EXTERN(int) git_rebase_next(
* @param message The message for this commit, or NULL to keep the message
* from the original commit
* @return Zero on success, GIT_EUNMERGED if there are unmerged changes in
- * the index, -1 on failure.
+ * the index, GIT_EAPPLIED if the current commit has already
+ * been applied to the upstream and there is nothing to commit,
+ * -1 on failure.
*/
GIT_EXTERN(int) git_rebase_commit(
git_oid *id,
diff --git a/src/rebase.c b/src/rebase.c
index 9245dcada..a28a928fc 100644
--- a/src/rebase.c
+++ b/src/rebase.c
@@ -674,7 +674,8 @@ static int rebase_commit_merge(
git_index *index = NULL;
git_reference *head = NULL;
git_commit *head_commit = NULL;
- git_tree *tree = NULL;
+ git_tree *head_tree = NULL, *tree = NULL;
+ git_diff *diff = NULL;
git_oid tree_id;
char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ];
int error;
@@ -694,11 +695,19 @@ static int rebase_commit_merge(
goto done;
}
- /* TODO: if there are no changes, error with a useful code */
-
if ((error = git_repository_head(&head, repo)) < 0 ||
(error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 ||
- (error = git_index_write_tree(&tree_id, index)) < 0 ||
+ (error = git_commit_tree(&head_tree, head_commit)) < 0 ||
+ (error = git_diff_tree_to_index(&diff, repo, head_tree, index, NULL)) < 0)
+ goto done;
+
+ if (git_diff_num_deltas(diff) == 0) {
+ giterr_set(GITERR_REBASE, "This patch has already been applied");
+ error = GIT_EAPPLIED;
+ goto done;
+ }
+
+ if ((error = git_index_write_tree(&tree_id, index)) < 0 ||
(error = git_tree_lookup(&tree, repo, &tree_id)) < 0)
goto done;
@@ -722,7 +731,9 @@ static int rebase_commit_merge(
"%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr);
done:
+ git_diff_free(diff);
git_tree_free(tree);
+ git_tree_free(head_tree);
git_commit_free(head_commit);
git_reference_free(head);
git_index_free(index);
diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c
index e578bef9b..04d06d2e8 100644
--- a/tests/rebase/merge.c
+++ b/tests/rebase/merge.c
@@ -207,3 +207,41 @@ void test_rebase_merge__commit_updates_rewritten(void)
git_reference_free(upstream_ref);
}
+void test_rebase_merge__commit_drops_already_applied(void)
+{
+ git_reference *branch_ref, *upstream_ref;
+ git_merge_head *branch_head, *upstream_head;
+ git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
+ git_oid commit_id;
+ int error;
+
+ checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+
+ cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef"));
+ cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/green_pea"));
+
+ cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref));
+ cl_git_pass(git_merge_head_from_ref(&upstream_head, repo, upstream_ref));
+
+ cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL));
+
+ cl_git_pass(git_rebase_next(repo, &checkout_opts));
+ cl_git_fail(error = git_rebase_commit(&commit_id, repo, NULL, signature,
+ NULL, NULL));
+
+ cl_assert_equal_i(GIT_EAPPLIED, error);
+
+ cl_git_pass(git_rebase_next(repo, &checkout_opts));
+ cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature,
+ NULL, NULL));
+
+ cl_assert_equal_file(
+ "8d1f13f93c4995760ac07d129246ac1ff64c0be9 2ac4fb7b74c1287f6c792acad759e1ec01e18dae\n",
+ 82, "rebase/.git/rebase-merge/rewritten");
+
+ git_merge_head_free(branch_head);
+ git_merge_head_free(upstream_head);
+ git_reference_free(branch_ref);
+ git_reference_free(upstream_ref);
+}
+
diff --git a/tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177ac b/tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177ac
new file mode 100644
index 000000000..c38c5b255
--- /dev/null
+++ b/tests/resources/rebase/.gitted/objects/05/3808a709cf91385985369159b296cf61a177ac
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/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/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/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/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/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/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/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