Commit 7636f740 by Carlos Martín Nieto

Merge pull request #2992 from ethomson/rebase_fixes

Rebase fixes
parents 3a63e8c2 aa9bb425
...@@ -28,6 +28,9 @@ v0.22 + 1 ...@@ -28,6 +28,9 @@ v0.22 + 1
allow for specifying the expression from the user to be put into the allow for specifying the expression from the user to be put into the
reflog. reflog.
* `git_rebase_commit` now returns `GIT_EUNMERGED` when you attempt to
commit with unstaged changes.
### API additions ### API additions
* The `git_merge_options` gained a `file_flags` member. * The `git_merge_options` gained a `file_flags` member.
...@@ -101,6 +104,18 @@ v0.22 + 1 ...@@ -101,6 +104,18 @@ v0.22 + 1
* `git_note_default_ref()` now uses a `git_buf` to return the string, * `git_note_default_ref()` now uses a `git_buf` to return the string,
as the string is otherwise not guaranteed to stay allocated. as the string is otherwise not guaranteed to stay allocated.
* `git_rebase_operation_current()` will return `GIT_REBASE_NO_OPERATION`
if it is called immediately after creating a rebase session but before
you have applied the first patch.
* `git_rebase_options` now contains an optional pointer to
`git_checkout_options` that will be used for functions that modify
the working directory, namely `git_checkout_init`, `git_checkout_next`
and `git_checkout_abort`. As a result, `git_rebase_open` now also
takes a `git_rebase_options` and only the `git_rebase_init` and
`git_rebase_open` functions take a `git_rebase_options`, where they
will persist the options to subsequent `git_rebase` calls.
v0.22 v0.22
------ ------
......
...@@ -30,19 +30,32 @@ typedef struct { ...@@ -30,19 +30,32 @@ typedef struct {
unsigned int version; unsigned int version;
/** /**
* Provide a quiet rebase experience; unused by libgit2 but provided for * Used by `git_rebase_init`, this will instruct other clients working
* interoperability with other clients. * on this rebase that you want a quiet rebase experience, which they
* may choose to provide in an application-specific manner. This has no
* effect upon libgit2 directly, but is provided for interoperability
* between Git tools.
*/ */
int quiet; int quiet;
/** /**
* Canonical name of the notes reference used to rewrite notes for * Used by `git_rebase_finish`, this is the name of the notes reference
* rebased commits when finishing the rebase; if NULL, the contents of * used to rewrite notes for rebased commits when finishing the rebase;
* the coniguration option `notes.rewriteRef` is examined, unless the * if NULL, the contents of the coniguration option `notes.rewriteRef`
* configuration option `notes.rewrite.rebase` is set to false. If * is examined, unless the configuration option `notes.rewrite.rebase`
* `notes.rewriteRef` is NULL, notes will not be rewritten. * is set to false. If `notes.rewriteRef` is also NULL, notes will
* not be rewritten.
*/ */
const char *rewrite_notes_ref; const char *rewrite_notes_ref;
/**
* Options to control how files are written during `git_rebase_init`,
* `git_checkout_next` and `git_checkout_abort`. Note that a minimum
* strategy of `GIT_CHECKOUT_SAFE` is defaulted in `init` and `next`,
* and a minimum strategy of `GIT_CHECKOUT_FORCE` is defaulted in
* `abort` to match git semantics.
*/
git_checkout_options checkout_options;
} git_rebase_options; } git_rebase_options;
/** /**
...@@ -87,7 +100,11 @@ typedef enum { ...@@ -87,7 +100,11 @@ typedef enum {
} git_rebase_operation_t; } git_rebase_operation_t;
#define GIT_REBASE_OPTIONS_VERSION 1 #define GIT_REBASE_OPTIONS_VERSION 1
#define GIT_REBASE_OPTIONS_INIT {GIT_REBASE_OPTIONS_VERSION} #define GIT_REBASE_OPTIONS_INIT \
{GIT_REBASE_OPTIONS_VERSION, 0, NULL, GIT_CHECKOUT_OPTIONS_INIT}
/** Indicates that a rebase operation is not (yet) in progress. */
#define GIT_REBASE_NO_OPERATION SIZE_MAX
/** /**
* A rebase operation * A rebase operation
...@@ -139,7 +156,7 @@ GIT_EXTERN(int) git_rebase_init_options( ...@@ -139,7 +156,7 @@ GIT_EXTERN(int) git_rebase_init_options(
* reachable commits * reachable commits
* @param onto The branch to rebase onto, or NULL to rebase onto the given * @param onto The branch to rebase onto, or NULL to rebase onto the given
* upstream * upstream
* @param opts Options to specify how rebase is performed * @param opts Options to specify how rebase is performed, or NULL
* @return Zero on success; -1 on failure. * @return Zero on success; -1 on failure.
*/ */
GIT_EXTERN(int) git_rebase_init( GIT_EXTERN(int) git_rebase_init(
...@@ -156,9 +173,13 @@ GIT_EXTERN(int) git_rebase_init( ...@@ -156,9 +173,13 @@ GIT_EXTERN(int) git_rebase_init(
* *
* @param out Pointer to store the rebase object * @param out Pointer to store the rebase object
* @param repo The repository that has a rebase in-progress * @param repo The repository that has a rebase in-progress
* @param opts Options to specify how rebase is performed
* @return Zero on success; -1 on failure. * @return Zero on success; -1 on failure.
*/ */
GIT_EXTERN(int) git_rebase_open(git_rebase **out, git_repository *repo); GIT_EXTERN(int) git_rebase_open(
git_rebase **out,
git_repository *repo,
const git_rebase_options *opts);
/** /**
* Gets the count of rebase operations that are to be applied. * Gets the count of rebase operations that are to be applied.
...@@ -170,6 +191,9 @@ GIT_EXTERN(size_t) git_rebase_operation_entrycount(git_rebase *rebase); ...@@ -170,6 +191,9 @@ GIT_EXTERN(size_t) git_rebase_operation_entrycount(git_rebase *rebase);
/** /**
* Gets the index of the rebase operation that is currently being applied. * Gets the index of the rebase operation that is currently being applied.
* If the first operation has not yet been applied (because you have
* called `init` but not yet `next`) then this returns
* `GIT_REBASE_NO_OPERATION`.
* *
* @param rebase The in-progress rebase * @param rebase The in-progress rebase
* @return The index of the rebase operation currently being applied. * @return The index of the rebase operation currently being applied.
...@@ -196,13 +220,11 @@ GIT_EXTERN(git_rebase_operation *) git_rebase_operation_byindex( ...@@ -196,13 +220,11 @@ GIT_EXTERN(git_rebase_operation *) git_rebase_operation_byindex(
* *
* @param operation Pointer to store the rebase operation that is to be performed next * @param operation Pointer to store the rebase operation that is to be performed next
* @param rebase The rebase in progress * @param rebase The rebase in progress
* @param checkout_opts Options to specify how the patch should be checked out
* @return Zero on success; -1 on failure. * @return Zero on success; -1 on failure.
*/ */
GIT_EXTERN(int) git_rebase_next( GIT_EXTERN(int) git_rebase_next(
git_rebase_operation **operation, git_rebase_operation **operation,
git_rebase *rebase, git_rebase *rebase);
git_checkout_options *checkout_opts);
/** /**
* Commits the current patch. You must have resolved any conflicts that * Commits the current patch. You must have resolved any conflicts that
...@@ -250,13 +272,11 @@ GIT_EXTERN(int) git_rebase_abort(git_rebase *rebase); ...@@ -250,13 +272,11 @@ GIT_EXTERN(int) git_rebase_abort(git_rebase *rebase);
* *
* @param rebase The rebase that is in-progress * @param rebase The rebase that is in-progress
* @param signature The identity that is finishing the rebase (optional) * @param signature The identity that is finishing the rebase (optional)
* @param opts Options to specify how rebase is finished
* @return Zero on success; -1 on error * @return Zero on success; -1 on error
*/ */
GIT_EXTERN(int) git_rebase_finish( GIT_EXTERN(int) git_rebase_finish(
git_rebase *rebase, git_rebase *rebase,
const git_signature *signature, const git_signature *signature);
const git_rebase_options *opts);
/** /**
* Frees the `git_rebase` object. * Frees the `git_rebase` object.
......
...@@ -62,7 +62,7 @@ GIT_EXTERN(int) git_reset( ...@@ -62,7 +62,7 @@ GIT_EXTERN(int) git_reset(
git_repository *repo, git_repository *repo,
git_object *target, git_object *target,
git_reset_t reset_type, git_reset_t reset_type,
git_checkout_options *checkout_opts); const git_checkout_options *checkout_opts);
/** /**
* Sets the current head to the specified commit oid and optionally * Sets the current head to the specified commit oid and optionally
...@@ -80,7 +80,7 @@ GIT_EXTERN(int) git_reset_from_annotated( ...@@ -80,7 +80,7 @@ GIT_EXTERN(int) git_reset_from_annotated(
git_repository *repo, git_repository *repo,
git_annotated_commit *commit, git_annotated_commit *commit,
git_reset_t reset_type, git_reset_t reset_type,
git_checkout_options *checkout_opts); const git_checkout_options *checkout_opts);
/** /**
* Updates some entries in the index from the target commit tree. * Updates some entries in the index from the target commit tree.
......
...@@ -102,7 +102,7 @@ static int reset( ...@@ -102,7 +102,7 @@ static int reset(
git_object *target, git_object *target,
const char *to, const char *to,
git_reset_t reset_type, git_reset_t reset_type,
git_checkout_options *checkout_opts) const git_checkout_options *checkout_opts)
{ {
git_object *commit = NULL; git_object *commit = NULL;
git_index *index = NULL; git_index *index = NULL;
...@@ -183,7 +183,7 @@ int git_reset( ...@@ -183,7 +183,7 @@ int git_reset(
git_repository *repo, git_repository *repo,
git_object *target, git_object *target,
git_reset_t reset_type, git_reset_t reset_type,
git_checkout_options *checkout_opts) const git_checkout_options *checkout_opts)
{ {
return reset(repo, target, git_oid_tostr_s(git_object_id(target)), reset_type, checkout_opts); return reset(repo, target, git_oid_tostr_s(git_object_id(target)), reset_type, checkout_opts);
} }
...@@ -192,7 +192,7 @@ int git_reset_from_annotated( ...@@ -192,7 +192,7 @@ int git_reset_from_annotated(
git_repository *repo, git_repository *repo,
git_annotated_commit *commit, git_annotated_commit *commit,
git_reset_t reset_type, git_reset_t reset_type,
git_checkout_options *checkout_opts) const git_checkout_options *checkout_opts)
{ {
return reset(repo, (git_object *) commit->commit, commit->ref_name, reset_type, checkout_opts); return reset(repo, (git_object *) commit->commit, commit->ref_name, reset_type, checkout_opts);
} }
...@@ -27,7 +27,7 @@ static void test_abort(git_annotated_commit *branch, git_annotated_commit *onto) ...@@ -27,7 +27,7 @@ static void test_abort(git_annotated_commit *branch, git_annotated_commit *onto)
git_reflog *reflog; git_reflog *reflog;
const git_reflog_entry *reflog_entry; const git_reflog_entry *reflog_entry;
cl_git_pass(git_rebase_open(&rebase, repo)); cl_git_pass(git_rebase_open(&rebase, repo, NULL));
cl_git_pass(git_rebase_abort(rebase)); cl_git_pass(git_rebase_abort(rebase));
cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));
......
...@@ -52,12 +52,9 @@ void test_rebase_iterator__iterates(void) ...@@ -52,12 +52,9 @@ void test_rebase_iterator__iterates(void)
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_annotated_commit *branch_head, *upstream_head; git_annotated_commit *branch_head, *upstream_head;
git_rebase_operation *rebase_operation; git_rebase_operation *rebase_operation;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_oid commit_id; git_oid commit_id;
int error; 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(&branch_ref, repo, "refs/heads/beef"));
cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master"));
...@@ -65,39 +62,39 @@ void test_rebase_iterator__iterates(void) ...@@ -65,39 +62,39 @@ void test_rebase_iterator__iterates(void)
cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_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, NULL)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL));
test_operations(rebase, 0); test_operations(rebase, GIT_REBASE_NO_OPERATION);
git_rebase_free(rebase); git_rebase_free(rebase);
cl_git_pass(git_rebase_open(&rebase, repo)); cl_git_pass(git_rebase_open(&rebase, repo, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase));
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
test_operations(rebase, 0); test_operations(rebase, 0);
cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase));
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
test_operations(rebase, 1); test_operations(rebase, 1);
cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase));
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
test_operations(rebase, 2); test_operations(rebase, 2);
git_rebase_free(rebase); git_rebase_free(rebase);
cl_git_pass(git_rebase_open(&rebase, repo)); cl_git_pass(git_rebase_open(&rebase, repo, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase));
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
test_operations(rebase, 3); test_operations(rebase, 3);
cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase));
cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
test_operations(rebase, 4); test_operations(rebase, 4);
cl_git_fail(error = git_rebase_next(&rebase_operation, rebase, &checkout_opts)); cl_git_fail(error = git_rebase_next(&rebase_operation, rebase));
cl_assert_equal_i(GIT_ITEROVER, error); cl_assert_equal_i(GIT_ITEROVER, error);
test_operations(rebase, 4); 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