Commit b6b636a7 by Edward Thomson

rebase: init/open a git_rebase object

parent 18b439b9
...@@ -114,9 +114,12 @@ GIT_EXTERN(int) git_rebase_init_options( ...@@ -114,9 +114,12 @@ GIT_EXTERN(int) git_rebase_init_options(
unsigned int version); unsigned int version);
/** /**
* Sets up a rebase operation to rebase the changes in ours relative to * Initializes a rebase operation to rebase the changes in `ours`
* upstream onto another branch. * relative to `upstream` onto another branch. To begin the rebase
* process, call `git_rebase_next`. When you have finished with this
* object, call `git_rebase_free`.
* *
* @param out Pointer to store the rebase object
* @param repo The repository to perform the rebase * @param repo The repository to perform the rebase
* @param branch The terminal commit to rebase * @param branch The terminal commit to rebase
* @param upstream The commit to begin rebasing from, or NULL to rebase all * @param upstream The commit to begin rebasing from, or NULL to rebase all
...@@ -127,7 +130,8 @@ GIT_EXTERN(int) git_rebase_init_options( ...@@ -127,7 +130,8 @@ GIT_EXTERN(int) git_rebase_init_options(
* @param opts Options to specify how rebase is performed * @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( GIT_EXTERN(int) git_rebase_init(
git_rebase **out,
git_repository *repo, git_repository *repo,
const git_merge_head *branch, const git_merge_head *branch,
const git_merge_head *upstream, const git_merge_head *upstream,
...@@ -136,6 +140,16 @@ GIT_EXTERN(int) git_rebase( ...@@ -136,6 +140,16 @@ GIT_EXTERN(int) git_rebase(
const git_rebase_options *opts); const git_rebase_options *opts);
/** /**
* Opens an existing rebase that was previously started by either an
* invocation of `git_rebase_init` or by another client.
*
* @param out Pointer to store the rebase object
* @param reop The repository that has a rebase in-progress
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_rebase_open(git_rebase **out, git_repository *repo);
/**
* Performs the next rebase operation and returns the information about it. * 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 * 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 * GIT_REBASE_OPERATION_EXEC) then the patch will be applied and the index and
...@@ -143,13 +157,13 @@ GIT_EXTERN(int) git_rebase( ...@@ -143,13 +157,13 @@ GIT_EXTERN(int) git_rebase(
* you will need to address those before committing the changes. * you will need to address those before committing the changes.
* *
* @param out The rebase operation that is to be performed next * @param out The rebase operation that is to be performed next
* @param repo The repository with a rebase in progress * @param repo The rebase in progress
* @param checkout_opts Options to specify how the patch should be checked out * @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_repository *repo, git_rebase *rebase,
git_checkout_options *checkout_opts); git_checkout_options *checkout_opts);
/** /**
...@@ -158,7 +172,7 @@ GIT_EXTERN(int) git_rebase_next( ...@@ -158,7 +172,7 @@ GIT_EXTERN(int) git_rebase_next(
* invocation. * invocation.
* *
* @param id Pointer in which to store the OID of the newly created commit * @param id Pointer in which to store the OID of the newly created commit
* @param repo The repository with the in-progress rebase * @param repo The rebase that is in-progress
* @param author The author of the updated commit, or NULL to keep the * @param author The author of the updated commit, or NULL to keep the
* author from the original commit * author from the original commit
* @param committer The committer of the rebase * @param committer The committer of the rebase
...@@ -176,7 +190,7 @@ GIT_EXTERN(int) git_rebase_next( ...@@ -176,7 +190,7 @@ GIT_EXTERN(int) git_rebase_next(
*/ */
GIT_EXTERN(int) git_rebase_commit( GIT_EXTERN(int) git_rebase_commit(
git_oid *id, git_oid *id,
git_repository *repo, git_rebase *rebase,
const git_signature *author, const git_signature *author,
const git_signature *committer, const git_signature *committer,
const char *message_encoding, const char *message_encoding,
...@@ -186,29 +200,36 @@ GIT_EXTERN(int) git_rebase_commit( ...@@ -186,29 +200,36 @@ GIT_EXTERN(int) git_rebase_commit(
* Aborts a rebase that is currently in progress, resetting the repository * Aborts a rebase that is currently in progress, resetting the repository
* and working directory to their state before rebase began. * and working directory to their state before rebase began.
* *
* @param repo The repository with the in-progress rebase * @param rebase The rebase that is in-progress
* @param signature The identity that is aborting the rebase * @param signature The identity that is aborting the rebase
* @return Zero on success; GIT_ENOTFOUND if a rebase is not in progress, * @return Zero on success; GIT_ENOTFOUND if a rebase is not in progress,
* -1 on other errors. * -1 on other errors.
*/ */
GIT_EXTERN(int) git_rebase_abort( GIT_EXTERN(int) git_rebase_abort(
git_repository *repo, git_rebase *rebase,
const git_signature *signature); const git_signature *signature);
/** /**
* Finishes a rebase that is currently in progress once all patches have * Finishes a rebase that is currently in progress once all patches have
* been applied. * been applied.
* *
* @param repo The repository with the in-progress rebase * @param rebase The rebase that is in-progress
* @param signature The identity that is finishing the rebase * @param signature The identity that is finishing the rebase
* @param opts Options to specify how rebase is finished * @param opts Options to specify how rebase is finished
* @param Zero on success; -1 on error * @param Zero on success; -1 on error
*/ */
GIT_EXTERN(int) git_rebase_finish( GIT_EXTERN(int) git_rebase_finish(
git_repository *repo, git_rebase *rebase,
const git_signature *signature, const git_signature *signature,
const git_rebase_options *opts); const git_rebase_options *opts);
/**
* Frees the `git_rebase` object.
*
* @param rebase The rebase that is in-progress
*/
GIT_EXTERN(void) git_rebase_free(git_rebase *rebase);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
#endif #endif
...@@ -183,6 +183,8 @@ typedef struct git_merge_result git_merge_result; ...@@ -183,6 +183,8 @@ typedef struct git_merge_result git_merge_result;
/** Representation of a status collection */ /** Representation of a status collection */
typedef struct git_status_list git_status_list; typedef struct git_status_list git_status_list;
/** Representation of a rebase */
typedef struct git_rebase git_rebase;
/** Basic type of any Git reference. */ /** Basic type of any Git reference. */
typedef enum { typedef enum {
......
...@@ -51,7 +51,7 @@ typedef enum { ...@@ -51,7 +51,7 @@ typedef enum {
GIT_REBASE_TYPE_INTERACTIVE = 3, GIT_REBASE_TYPE_INTERACTIVE = 3,
} git_rebase_type_t; } git_rebase_type_t;
struct git_rebase_state_merge { struct git_rebase_merge {
int32_t msgnum; int32_t msgnum;
int32_t end; int32_t end;
char *onto_name; char *onto_name;
...@@ -59,21 +59,26 @@ struct git_rebase_state_merge { ...@@ -59,21 +59,26 @@ struct git_rebase_state_merge {
git_commit *current; git_commit *current;
}; };
typedef struct { struct git_rebase {
git_repository *repo;
git_rebase_type_t type; git_rebase_type_t type;
char *state_path; char *state_path;
int head_detached : 1; int head_detached : 1,
quiet : 1;
char *orig_head_name; char *orig_head_name;
git_oid orig_head_id; git_oid orig_head_id;
git_oid onto_id; git_oid onto_id;
git_array_t(git_rebase_operation) operations;
union { union {
struct git_rebase_state_merge merge; struct git_rebase_merge merge;
}; };
} git_rebase_state; };
#define GIT_REBASE_STATE_INIT {0} #define GIT_REBASE_STATE_INIT {0}
...@@ -113,16 +118,14 @@ done: ...@@ -113,16 +118,14 @@ done:
return 0; return 0;
} }
static int rebase_state_merge(git_rebase_state *state, git_repository *repo) static int rebase_open_merge(git_rebase *rebase)
{ {
git_buf path = GIT_BUF_INIT, msgnum = GIT_BUF_INIT, end = GIT_BUF_INIT, git_buf path = GIT_BUF_INIT, msgnum = GIT_BUF_INIT, end = GIT_BUF_INIT,
onto_name = GIT_BUF_INIT, current = GIT_BUF_INIT; onto_name = GIT_BUF_INIT, current = GIT_BUF_INIT;
git_oid current_id; git_oid current_id;
int state_path_len, error; int state_path_len, error;
GIT_UNUSED(repo); if ((error = git_buf_puts(&path, rebase->state_path)) < 0)
if ((error = git_buf_puts(&path, state->state_path)) < 0)
goto done; goto done;
state_path_len = git_buf_len(&path); state_path_len = git_buf_len(&path);
...@@ -134,7 +137,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) ...@@ -134,7 +137,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo)
git_buf_rtrim(&end); git_buf_rtrim(&end);
if ((error = git__strtol32(&state->merge.end, end.ptr, NULL, 10)) < 0) if ((error = git__strtol32(&rebase->merge.end, end.ptr, NULL, 10)) < 0)
goto done; goto done;
/* Read 'onto_name' */ /* Read 'onto_name' */
...@@ -146,7 +149,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) ...@@ -146,7 +149,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo)
git_buf_rtrim(&onto_name); git_buf_rtrim(&onto_name);
state->merge.onto_name = git_buf_detach(&onto_name); rebase->merge.onto_name = git_buf_detach(&onto_name);
/* Read 'msgnum' if it exists, otherwise let msgnum = 0 */ /* Read 'msgnum' if it exists, otherwise let msgnum = 0 */
git_buf_truncate(&path, state_path_len); git_buf_truncate(&path, state_path_len);
...@@ -160,7 +163,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) ...@@ -160,7 +163,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo)
git_buf_rtrim(&msgnum); git_buf_rtrim(&msgnum);
if ((error = git__strtol32(&state->merge.msgnum, msgnum.ptr, NULL, 10)) < 0) if ((error = git__strtol32(&rebase->merge.msgnum, msgnum.ptr, NULL, 10)) < 0)
goto done; goto done;
} }
...@@ -178,7 +181,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo) ...@@ -178,7 +181,7 @@ static int rebase_state_merge(git_rebase_state *state, git_repository *repo)
git_buf_rtrim(&current); git_buf_rtrim(&current);
if ((error = git_oid_fromstr(&current_id, current.ptr)) < 0 || if ((error = git_oid_fromstr(&current_id, current.ptr)) < 0 ||
(error = git_commit_lookup(&state->merge.current, repo, &current_id)) < 0) (error = git_commit_lookup(&rebase->merge.current, rebase->repo, &current_id)) < 0)
goto done; goto done;
} }
...@@ -192,23 +195,29 @@ done: ...@@ -192,23 +195,29 @@ done:
return error; return error;
} }
static int rebase_state(git_rebase_state *state, git_repository *repo) int git_rebase_open(git_rebase **out, git_repository *repo)
{ {
git_rebase *rebase;
git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT, git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT,
orig_head_id = GIT_BUF_INIT, onto_id = GIT_BUF_INIT; orig_head_id = GIT_BUF_INIT, onto_id = GIT_BUF_INIT;
int state_path_len, error; int state_path_len, error;
memset(state, 0x0, sizeof(git_rebase_state)); assert(repo);
rebase = git__calloc(1, sizeof(git_rebase));
GITERR_CHECK_ALLOC(rebase);
if ((error = rebase_state_type(&state->type, &state->state_path, repo)) < 0) rebase->repo = repo;
if ((error = rebase_state_type(&rebase->type, &rebase->state_path, repo)) < 0)
goto done; goto done;
if (state->type == GIT_REBASE_TYPE_NONE) { if (rebase->type == GIT_REBASE_TYPE_NONE) {
giterr_set(GITERR_REBASE, "There is no rebase in progress"); giterr_set(GITERR_REBASE, "There is no rebase in progress");
return GIT_ENOTFOUND; return GIT_ENOTFOUND;
} }
if ((error = git_buf_puts(&path, state->state_path)) < 0) if ((error = git_buf_puts(&path, rebase->state_path)) < 0)
goto done; goto done;
state_path_len = git_buf_len(&path); state_path_len = git_buf_len(&path);
...@@ -220,7 +229,7 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) ...@@ -220,7 +229,7 @@ static int rebase_state(git_rebase_state *state, git_repository *repo)
git_buf_rtrim(&orig_head_name); git_buf_rtrim(&orig_head_name);
if (strcmp(ORIG_DETACHED_HEAD, orig_head_name.ptr) == 0) if (strcmp(ORIG_DETACHED_HEAD, orig_head_name.ptr) == 0)
state->head_detached = 1; rebase->head_detached = 1;
git_buf_truncate(&path, state_path_len); git_buf_truncate(&path, state_path_len);
...@@ -240,7 +249,7 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) ...@@ -240,7 +249,7 @@ static int rebase_state(git_rebase_state *state, git_repository *repo)
git_buf_rtrim(&orig_head_id); git_buf_rtrim(&orig_head_id);
if ((error = git_oid_fromstr(&state->orig_head_id, orig_head_id.ptr)) < 0) if ((error = git_oid_fromstr(&rebase->orig_head_id, orig_head_id.ptr)) < 0)
goto done; goto done;
git_buf_truncate(&path, state_path_len); git_buf_truncate(&path, state_path_len);
...@@ -251,19 +260,19 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) ...@@ -251,19 +260,19 @@ static int rebase_state(git_rebase_state *state, git_repository *repo)
git_buf_rtrim(&onto_id); git_buf_rtrim(&onto_id);
if ((error = git_oid_fromstr(&state->onto_id, onto_id.ptr)) < 0) if ((error = git_oid_fromstr(&rebase->onto_id, onto_id.ptr)) < 0)
goto done; goto done;
if (!state->head_detached) if (!rebase->head_detached)
state->orig_head_name = git_buf_detach(&orig_head_name); rebase->orig_head_name = git_buf_detach(&orig_head_name);
switch (state->type) { switch (rebase->type) {
case GIT_REBASE_TYPE_INTERACTIVE: case GIT_REBASE_TYPE_INTERACTIVE:
giterr_set(GITERR_REBASE, "Interactive rebase is not supported"); giterr_set(GITERR_REBASE, "Interactive rebase is not supported");
error = -1; error = -1;
break; break;
case GIT_REBASE_TYPE_MERGE: case GIT_REBASE_TYPE_MERGE:
error = rebase_state_merge(state, repo); error = rebase_open_merge(rebase);
break; break;
case GIT_REBASE_TYPE_APPLY: case GIT_REBASE_TYPE_APPLY:
giterr_set(GITERR_REBASE, "Patch application rebase is not supported"); giterr_set(GITERR_REBASE, "Patch application rebase is not supported");
...@@ -274,6 +283,11 @@ static int rebase_state(git_rebase_state *state, git_repository *repo) ...@@ -274,6 +283,11 @@ static int rebase_state(git_rebase_state *state, git_repository *repo)
} }
done: done:
if (error == 0)
*out = rebase;
else
git_rebase_free(rebase);
git_buf_free(&path); git_buf_free(&path);
git_buf_free(&orig_head_name); git_buf_free(&orig_head_name);
git_buf_free(&orig_head_id); git_buf_free(&orig_head_id);
...@@ -281,28 +295,14 @@ done: ...@@ -281,28 +295,14 @@ done:
return error; return error;
} }
static void rebase_state_free(git_rebase_state *state) static int rebase_cleanup(git_rebase *rebase)
{ {
if (state == NULL) return git_path_isdir(rebase->state_path) ?
return; git_futils_rmdir_r(rebase->state_path, NULL, GIT_RMDIR_REMOVE_FILES) :
if (state->type == GIT_REBASE_TYPE_MERGE) {
git__free(state->merge.onto_name);
git_commit_free(state->merge.current);
}
git__free(state->orig_head_name);
git__free(state->state_path);
}
static int rebase_cleanup(git_rebase_state *state)
{
return git_path_isdir(state->state_path) ?
git_futils_rmdir_r(state->state_path, NULL, GIT_RMDIR_REMOVE_FILES) :
0; 0;
} }
static int rebase_setupfile(git_repository *repo, const char *filename, int flags, const char *fmt, ...) static int rebase_setupfile(git_rebase *rebase, const char *filename, int flags, const char *fmt, ...)
{ {
git_buf path = GIT_BUF_INIT, git_buf path = GIT_BUF_INIT,
contents = GIT_BUF_INIT; contents = GIT_BUF_INIT;
...@@ -313,8 +313,7 @@ static int rebase_setupfile(git_repository *repo, const char *filename, int flag ...@@ -313,8 +313,7 @@ static int rebase_setupfile(git_repository *repo, const char *filename, int flag
git_buf_vprintf(&contents, fmt, ap); git_buf_vprintf(&contents, fmt, ap);
va_end(ap); va_end(ap);
if ((error = git_buf_joinpath(&path, repo->path_repository, REBASE_MERGE_DIR)) == 0 && if ((error = git_buf_joinpath(&path, rebase->state_path, filename)) == 0)
(error = git_buf_joinpath(&path, path.ptr, filename)) == 0)
error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE); error = git_futils_writebuffer(&contents, path.ptr, flags, REBASE_FILE_MODE);
git_buf_free(&path); git_buf_free(&path);
...@@ -323,9 +322,6 @@ static int rebase_setupfile(git_repository *repo, const char *filename, int flag ...@@ -323,9 +322,6 @@ static int rebase_setupfile(git_repository *repo, const char *filename, int flag
return error; return error;
} }
/* TODO: git.git actually uses the literal argv here, this is an attempt
* to emulate that.
*/
static const char *rebase_onto_name(const git_merge_head *onto) static const char *rebase_onto_name(const git_merge_head *onto)
{ {
if (onto->ref_name && git__strncmp(onto->ref_name, "refs/heads/", 11) == 0) if (onto->ref_name && git__strncmp(onto->ref_name, "refs/heads/", 11) == 0)
...@@ -336,108 +332,56 @@ static const char *rebase_onto_name(const git_merge_head *onto) ...@@ -336,108 +332,56 @@ static const char *rebase_onto_name(const git_merge_head *onto)
return onto->oid_str; return onto->oid_str;
} }
static int rebase_setup_merge( static int rebase_setupfiles_merge(git_rebase *rebase)
git_repository *repo,
const git_merge_head *branch,
const git_merge_head *upstream,
const git_merge_head *onto,
const git_rebase_options *opts)
{ {
git_revwalk *revwalk = NULL;
git_commit *commit;
git_buf commit_filename = GIT_BUF_INIT; git_buf commit_filename = GIT_BUF_INIT;
git_oid id;
char id_str[GIT_OID_HEXSZ]; char id_str[GIT_OID_HEXSZ];
bool merge; git_rebase_operation *operation;
int commit_cnt = 0, error; size_t i;
int error = 0;
GIT_UNUSED(opts);
if (!upstream)
upstream = onto;
if ((error = git_revwalk_new(&revwalk, repo)) < 0 ||
(error = git_revwalk_push(revwalk, &branch->oid)) < 0 ||
(error = git_revwalk_hide(revwalk, &upstream->oid)) < 0)
goto done;
git_revwalk_sorting(revwalk, GIT_SORT_REVERSE | GIT_SORT_TIME);
while ((error = git_revwalk_next(&id, revwalk)) == 0) { if ((error = rebase_setupfile(rebase, END_FILE, -1, "%d\n", git_array_size(rebase->operations))) < 0 ||
if ((error = git_commit_lookup(&commit, repo, &id)) < 0) (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->merge.onto_name)) < 0)
goto done; goto done;
merge = (git_commit_parentcount(commit) > 1); for (i = 0; i < git_array_size(rebase->operations); i++) {
git_commit_free(commit); operation = git_array_get(rebase->operations, i);
if (merge)
continue;
commit_cnt++;
git_buf_clear(&commit_filename); git_buf_clear(&commit_filename);
git_buf_printf(&commit_filename, CMT_FILE_FMT, commit_cnt); git_buf_printf(&commit_filename, CMT_FILE_FMT, i+1);
git_oid_fmt(id_str, &operation->id);
git_oid_fmt(id_str, &id); if ((error = rebase_setupfile(rebase, commit_filename.ptr, -1,
if ((error = rebase_setupfile(repo, commit_filename.ptr, -1,
"%.*s\n", GIT_OID_HEXSZ, id_str)) < 0) "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0)
goto done; goto done;
} }
if (error != GIT_ITEROVER ||
(error = rebase_setupfile(repo, END_FILE, -1, "%d\n", commit_cnt)) < 0)
goto done;
error = rebase_setupfile(repo, ONTO_NAME_FILE, -1, "%s\n",
rebase_onto_name(onto));
done: done:
git_revwalk_free(revwalk);
git_buf_free(&commit_filename); git_buf_free(&commit_filename);
return error; return error;
} }
static int rebase_setup( static int rebase_setupfiles(git_rebase *rebase)
git_repository *repo,
const git_merge_head *branch,
const git_merge_head *upstream,
const git_merge_head *onto,
const git_rebase_options *opts)
{ {
git_buf state_path = GIT_BUF_INIT; char onto[GIT_OID_HEXSZ], orig_head[GIT_OID_HEXSZ];
const char *orig_head_name;
int error;
if (git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR) < 0) git_oid_fmt(onto, &rebase->onto_id);
return -1; git_oid_fmt(orig_head, &rebase->orig_head_id);
if ((error = p_mkdir(state_path.ptr, REBASE_DIR_MODE)) < 0) { if (p_mkdir(rebase->state_path, REBASE_DIR_MODE) < 0) {
giterr_set(GITERR_OS, "Failed to create rebase directory '%s'", giterr_set(GITERR_OS, "Failed to create rebase directory '%s'", rebase->state_path);
state_path.ptr); return -1;
goto done;
} }
if ((error = git_repository__set_orig_head(repo, &branch->oid)) < 0) if (git_repository__set_orig_head(rebase->repo, &rebase->orig_head_id) < 0 ||
goto done; rebase_setupfile(rebase, HEAD_NAME_FILE, -1, "%s\n", rebase->orig_head_name) < 0 ||
rebase_setupfile(rebase, ONTO_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 ||
orig_head_name = branch->ref_name ? branch->ref_name : ORIG_DETACHED_HEAD; rebase_setupfile(rebase, ORIG_HEAD_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 ||
rebase_setupfile(rebase, QUIET_FILE, -1, rebase->quiet ? "t\n" : "\n") < 0)
if ((error = rebase_setupfile(repo, HEAD_NAME_FILE, -1, "%s\n", orig_head_name)) < 0 || return -1;
(error = rebase_setupfile(repo, ONTO_FILE, -1, "%s\n", onto->oid_str)) < 0 ||
(error = rebase_setupfile(repo, ORIG_HEAD_FILE, -1, "%s\n", branch->oid_str)) < 0 ||
(error = rebase_setupfile(repo, QUIET_FILE, -1, opts->quiet ? "t\n" : "\n")) < 0)
goto done;
error = rebase_setup_merge(repo, branch, upstream, onto, opts);
done:
if (error < 0)
git_repository__cleanup_files(repo, (const char **)&state_path.ptr, 1);
git_buf_free(&state_path);
return error; return rebase_setupfiles_merge(rebase);
} }
int git_rebase_init_options(git_rebase_options *opts, unsigned int version) int git_rebase_init_options(git_rebase_options *opts, unsigned int version)
...@@ -542,7 +486,104 @@ done: ...@@ -542,7 +486,104 @@ done:
return error; return error;
} }
int git_rebase( static int rebase_init_operations(
git_rebase *rebase,
git_repository *repo,
const git_merge_head *branch,
const git_merge_head *upstream,
const git_merge_head *onto)
{
git_revwalk *revwalk = NULL;
git_commit *commit;
git_oid id;
bool merge;
git_rebase_operation *operation;
int error;
if (!upstream)
upstream = onto;
if ((error = git_revwalk_new(&revwalk, rebase->repo)) < 0 ||
(error = git_revwalk_push(revwalk, &branch->oid)) < 0 ||
(error = git_revwalk_hide(revwalk, &upstream->oid)) < 0)
goto done;
git_revwalk_sorting(revwalk, GIT_SORT_REVERSE | GIT_SORT_TIME);
while ((error = git_revwalk_next(&id, revwalk)) == 0) {
if ((error = git_commit_lookup(&commit, repo, &id)) < 0)
goto done;
merge = (git_commit_parentcount(commit) > 1);
git_commit_free(commit);
if (merge)
continue;
operation = git_array_alloc(rebase->operations);
operation->type = GIT_REBASE_OPERATION_PICK;
git_oid_cpy(&operation->id, &id);
}
error = 0;
done:
git_revwalk_free(revwalk);
return error;
}
static int rebase_init_merge(
git_rebase *rebase,
git_repository *repo,
const git_merge_head *branch,
const git_merge_head *upstream,
const git_merge_head *onto)
{
if (rebase_init_operations(rebase, repo, branch, upstream, onto) < 0)
return -1;
rebase->merge.end = git_array_size(rebase->operations);
rebase->merge.onto_name = git__strdup(rebase_onto_name(onto));
GITERR_CHECK_ALLOC(rebase->merge.onto_name);
return 0;
}
static int rebase_init(
git_rebase *rebase,
git_repository *repo,
const git_merge_head *branch,
const git_merge_head *upstream,
const git_merge_head *onto,
const git_rebase_options *opts)
{
git_buf state_path = GIT_BUF_INIT;
int error;
git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR);
rebase->repo = repo;
rebase->type = GIT_REBASE_TYPE_MERGE;
rebase->state_path = git_buf_detach(&state_path);
rebase->orig_head_name = git__strdup(branch->ref_name ? branch->ref_name : ORIG_DETACHED_HEAD);
rebase->quiet = opts->quiet;
git_oid_cpy(&rebase->orig_head_id, &branch->oid);
git_oid_cpy(&rebase->onto_id, &onto->oid);
if (!rebase->orig_head_name || !rebase->state_path)
return -1;
error = rebase_init_merge(rebase, repo, branch, upstream, onto);
git_buf_free(&state_path);
return error;
}
int git_rebase_init(
git_rebase **out,
git_repository *repo, git_repository *repo,
const git_merge_head *branch, const git_merge_head *branch,
const git_merge_head *upstream, const git_merge_head *upstream,
...@@ -550,6 +591,7 @@ int git_rebase( ...@@ -550,6 +591,7 @@ int git_rebase(
const git_signature *signature, const git_signature *signature,
const git_rebase_options *given_opts) const git_rebase_options *given_opts)
{ {
git_rebase *rebase = NULL;
git_rebase_options opts; git_rebase_options opts;
git_reference *head_ref = NULL; git_reference *head_ref = NULL;
git_buf reflog = GIT_BUF_INIT; git_buf reflog = GIT_BUF_INIT;
...@@ -558,46 +600,55 @@ int git_rebase( ...@@ -558,46 +600,55 @@ int git_rebase(
assert(repo && branch && (upstream || onto)); assert(repo && branch && (upstream || onto));
*out = NULL;
GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options"); GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options");
if (!onto)
onto = upstream;
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
if ((error = rebase_normalize_opts(repo, &opts, given_opts)) < 0 || if ((error = rebase_normalize_opts(repo, &opts, given_opts)) < 0 ||
(error = git_repository__ensure_not_bare(repo, "rebase")) < 0 || (error = git_repository__ensure_not_bare(repo, "rebase")) < 0 ||
(error = rebase_ensure_not_in_progress(repo)) < 0 || (error = rebase_ensure_not_in_progress(repo)) < 0 ||
(error = rebase_ensure_not_dirty(repo)) < 0) (error = rebase_ensure_not_dirty(repo)) < 0)
goto done; return error;
if (!onto)
onto = upstream;
if ((error = rebase_setup(repo, branch, upstream, onto, &opts)) < 0) rebase = git__calloc(1, sizeof(git_rebase));
goto done; GITERR_CHECK_ALLOC(rebase);
if ((error = git_buf_printf(&reflog, if ((error = rebase_init(rebase, repo, branch, upstream, onto, &opts)) < 0 ||
(error = rebase_setupfiles(rebase)) < 0 ||
(error = git_buf_printf(&reflog,
"rebase: checkout %s", rebase_onto_name(onto))) < 0 || "rebase: checkout %s", rebase_onto_name(onto))) < 0 ||
(error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE, (error = git_reference_create(&head_ref, repo, GIT_HEAD_FILE,
&onto->oid, 1, signature, reflog.ptr)) < 0) &onto->oid, 1, signature, reflog.ptr)) < 0 ||
(error = git_checkout_head(repo, &checkout_opts)) < 0)
goto done; goto done;
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; *out = rebase;
error = git_checkout_head(repo, &checkout_opts);
done: done:
if (error < 0) {
rebase_cleanup(rebase);
git_rebase_free(rebase);
}
git_reference_free(head_ref); git_reference_free(head_ref);
git_buf_free(&reflog); git_buf_free(&reflog);
rebase_opts_free(&opts); rebase_opts_free(&opts);
return error; return error;
} }
static int normalize_checkout_opts( static int normalize_checkout_opts(
git_repository *repo, git_rebase *rebase,
git_checkout_options *checkout_opts, git_checkout_options *checkout_opts,
const git_checkout_options *given_checkout_opts, const git_checkout_options *given_checkout_opts)
const git_rebase_state *state)
{ {
int error = 0; int error = 0;
GIT_UNUSED(repo);
if (given_checkout_opts != NULL) if (given_checkout_opts != NULL)
memcpy(checkout_opts, given_checkout_opts, sizeof(git_checkout_options)); memcpy(checkout_opts, given_checkout_opts, sizeof(git_checkout_options));
else { else {
...@@ -610,12 +661,12 @@ static int normalize_checkout_opts( ...@@ -610,12 +661,12 @@ static int normalize_checkout_opts(
if (!checkout_opts->ancestor_label) if (!checkout_opts->ancestor_label)
checkout_opts->ancestor_label = "ancestor"; checkout_opts->ancestor_label = "ancestor";
if (state->type == GIT_REBASE_TYPE_MERGE) { if (rebase->type == GIT_REBASE_TYPE_MERGE) {
if (!checkout_opts->our_label) if (!checkout_opts->our_label)
checkout_opts->our_label = state->merge.onto_name; checkout_opts->our_label = rebase->merge.onto_name;
if (!checkout_opts->their_label) if (!checkout_opts->their_label)
checkout_opts->their_label = git_commit_summary(state->merge.current); checkout_opts->their_label = git_commit_summary(rebase->merge.current);
} else { } else {
abort(); abort();
} }
...@@ -625,8 +676,7 @@ static int normalize_checkout_opts( ...@@ -625,8 +676,7 @@ static int normalize_checkout_opts(
static int rebase_next_merge( static int rebase_next_merge(
git_rebase_operation *out, git_rebase_operation *out,
git_repository *repo, git_rebase *rebase,
git_rebase_state *state,
git_checkout_options *given_checkout_opts) git_checkout_options *given_checkout_opts)
{ {
git_buf path = GIT_BUF_INIT, current = GIT_BUF_INIT; git_buf path = GIT_BUF_INIT, current = GIT_BUF_INIT;
...@@ -638,45 +688,45 @@ static int rebase_next_merge( ...@@ -638,45 +688,45 @@ static int rebase_next_merge(
unsigned int parent_count; unsigned int parent_count;
int error; int error;
if (state->merge.msgnum == state->merge.end) if (rebase->merge.msgnum == rebase->merge.end)
return GIT_ITEROVER; return GIT_ITEROVER;
state->merge.msgnum++; rebase->merge.msgnum++;
if ((error = git_buf_joinpath(&path, state->state_path, "cmt.")) < 0 || if ((error = git_buf_joinpath(&path, rebase->state_path, "cmt.")) < 0 ||
(error = git_buf_printf(&path, "%d", state->merge.msgnum)) < 0 || (error = git_buf_printf(&path, "%d", rebase->merge.msgnum)) < 0 ||
(error = git_futils_readbuffer(&current, path.ptr)) < 0) (error = git_futils_readbuffer(&current, path.ptr)) < 0)
goto done; goto done;
git_buf_rtrim(&current); git_buf_rtrim(&current);
if (state->merge.current) if (rebase->merge.current)
git_commit_free(state->merge.current); git_commit_free(rebase->merge.current);
if ((error = git_oid_fromstr(&current_id, current.ptr)) < 0 || if ((error = git_oid_fromstr(&current_id, current.ptr)) < 0 ||
(error = git_commit_lookup(&state->merge.current, repo, &current_id)) < 0 || (error = git_commit_lookup(&rebase->merge.current, rebase->repo, &current_id)) < 0 ||
(error = git_commit_tree(&current_tree, state->merge.current)) < 0 || (error = git_commit_tree(&current_tree, rebase->merge.current)) < 0 ||
(error = git_repository_head_tree(&head_tree, repo)) < 0) (error = git_repository_head_tree(&head_tree, rebase->repo)) < 0)
goto done; goto done;
if ((parent_count = git_commit_parentcount(state->merge.current)) > 1) { if ((parent_count = git_commit_parentcount(rebase->merge.current)) > 1) {
giterr_set(GITERR_REBASE, "Cannot rebase a merge commit"); giterr_set(GITERR_REBASE, "Cannot rebase a merge commit");
error = -1; error = -1;
goto done; goto done;
} else if (parent_count) { } else if (parent_count) {
if ((error = git_commit_parent(&parent_commit, state->merge.current, 0)) < 0 || if ((error = git_commit_parent(&parent_commit, rebase->merge.current, 0)) < 0 ||
(error = git_commit_tree(&parent_tree, parent_commit)) < 0) (error = git_commit_tree(&parent_tree, parent_commit)) < 0)
goto done; goto done;
} }
if ((error = rebase_setupfile(repo, MSGNUM_FILE, -1, "%d\n", state->merge.msgnum)) < 0 || if ((error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%d\n", rebase->merge.msgnum)) < 0 ||
(error = rebase_setupfile(repo, CURRENT_FILE, -1, "%s\n", current.ptr)) < 0) (error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%s\n", current.ptr)) < 0)
goto done; goto done;
if ((error = normalize_checkout_opts(repo, &checkout_opts, given_checkout_opts, state)) < 0 || if ((error = normalize_checkout_opts(rebase, &checkout_opts, given_checkout_opts)) < 0 ||
(error = git_merge_trees(&index, repo, parent_tree, head_tree, current_tree, NULL)) < 0 || (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, NULL)) < 0 ||
(error = git_merge__check_result(repo, index)) < 0 || (error = git_merge__check_result(rebase->repo, index)) < 0 ||
(error = git_checkout_index(repo, index, &checkout_opts)) < 0) (error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0)
goto done; goto done;
out->type = GIT_REBASE_OPERATION_PICK; out->type = GIT_REBASE_OPERATION_PICK;
...@@ -696,35 +746,29 @@ done: ...@@ -696,35 +746,29 @@ done:
int git_rebase_next( int git_rebase_next(
git_rebase_operation *out, git_rebase_operation *out,
git_repository *repo, git_rebase *rebase,
git_checkout_options *checkout_opts) git_checkout_options *checkout_opts)
{ {
git_rebase_state state = GIT_REBASE_STATE_INIT;
int error; int error;
assert(out && repo); assert(out && rebase);
memset(out, 0, sizeof(git_rebase_operation)); memset(out, 0, sizeof(git_rebase_operation));
if ((error = rebase_state(&state, repo)) < 0) switch (rebase->type) {
return -1;
switch (state.type) {
case GIT_REBASE_TYPE_MERGE: case GIT_REBASE_TYPE_MERGE:
error = rebase_next_merge(out, repo, &state, checkout_opts); error = rebase_next_merge(out, rebase, checkout_opts);
break; break;
default: default:
abort(); abort();
} }
rebase_state_free(&state);
return error; return error;
} }
static int rebase_commit_merge( static int rebase_commit_merge(
git_oid *commit_id, git_oid *commit_id,
git_repository *repo, git_rebase *rebase,
git_rebase_state *state,
const git_signature *author, const git_signature *author,
const git_signature *committer, const git_signature *committer,
const char *message_encoding, const char *message_encoding,
...@@ -740,13 +784,13 @@ static int rebase_commit_merge( ...@@ -740,13 +784,13 @@ static int rebase_commit_merge(
char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ]; char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ];
int error; int error;
if (!state->merge.msgnum || !state->merge.current) { if (!rebase->merge.msgnum || !rebase->merge.current) {
giterr_set(GITERR_REBASE, "No rebase-merge state files exist"); giterr_set(GITERR_REBASE, "No rebase-merge state files exist");
error = -1; error = -1;
goto done; goto done;
} }
if ((error = git_repository_index(&index, repo)) < 0) if ((error = git_repository_index(&index, rebase->repo)) < 0)
goto done; goto done;
if (git_index_has_conflicts(index)) { if (git_index_has_conflicts(index)) {
...@@ -755,10 +799,10 @@ static int rebase_commit_merge( ...@@ -755,10 +799,10 @@ static int rebase_commit_merge(
goto done; goto done;
} }
if ((error = git_repository_head(&head, repo)) < 0 || if ((error = git_repository_head(&head, rebase->repo)) < 0 ||
(error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 || (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 ||
(error = git_commit_tree(&head_tree, head_commit)) < 0 || (error = git_commit_tree(&head_tree, head_commit)) < 0 ||
(error = git_diff_tree_to_index(&diff, repo, head_tree, index, NULL)) < 0) (error = git_diff_tree_to_index(&diff, rebase->repo, head_tree, index, NULL)) < 0)
goto done; goto done;
if (git_diff_num_deltas(diff) == 0) { if (git_diff_num_deltas(diff) == 0) {
...@@ -768,29 +812,29 @@ static int rebase_commit_merge( ...@@ -768,29 +812,29 @@ static int rebase_commit_merge(
} }
if ((error = git_index_write_tree(&tree_id, index)) < 0 || if ((error = git_index_write_tree(&tree_id, index)) < 0 ||
(error = git_tree_lookup(&tree, repo, &tree_id)) < 0) (error = git_tree_lookup(&tree, rebase->repo, &tree_id)) < 0)
goto done; goto done;
if (!author) if (!author)
author = git_commit_author(state->merge.current); author = git_commit_author(rebase->merge.current);
if (!message) { if (!message) {
message_encoding = git_commit_message_encoding(state->merge.current); message_encoding = git_commit_message_encoding(rebase->merge.current);
message = git_commit_message(state->merge.current); message = git_commit_message(rebase->merge.current);
} }
if ((error = git_commit_create(commit_id, repo, NULL, author, if ((error = git_commit_create(commit_id, rebase->repo, NULL, author,
committer, message_encoding, message, tree, 1, committer, message_encoding, message, tree, 1,
(const git_commit **)&head_commit)) < 0 || (const git_commit **)&head_commit)) < 0 ||
(error = git_commit_lookup(&commit, repo, commit_id)) < 0 || (error = git_commit_lookup(&commit, rebase->repo, commit_id)) < 0 ||
(error = git_reference__update_for_commit( (error = git_reference__update_for_commit(
repo, NULL, "HEAD", commit_id, committer, "rebase")) < 0) rebase->repo, NULL, "HEAD", commit_id, committer, "rebase")) < 0)
goto done; goto done;
git_oid_fmt(old_idstr, git_commit_id(state->merge.current)); git_oid_fmt(old_idstr, git_commit_id(rebase->merge.current));
git_oid_fmt(new_idstr, commit_id); git_oid_fmt(new_idstr, commit_id);
error = rebase_setupfile(repo, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND, error = rebase_setupfile(rebase, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND,
"%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr); "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr);
done: done:
...@@ -808,74 +852,63 @@ done: ...@@ -808,74 +852,63 @@ done:
int git_rebase_commit( int git_rebase_commit(
git_oid *id, git_oid *id,
git_repository *repo, git_rebase *rebase,
const git_signature *author, const git_signature *author,
const git_signature *committer, const git_signature *committer,
const char *message_encoding, const char *message_encoding,
const char *message) const char *message)
{ {
git_rebase_state state = GIT_REBASE_STATE_INIT;
int error; int error;
assert(repo && committer); assert(rebase && committer);
if ((error = rebase_state(&state, repo)) < 0) switch (rebase->type) {
goto done;
switch (state.type) {
case GIT_REBASE_TYPE_MERGE: case GIT_REBASE_TYPE_MERGE:
error = rebase_commit_merge( error = rebase_commit_merge(
id, repo, &state, author, committer, message_encoding, message); id, rebase, author, committer, message_encoding, message);
break; break;
default: default:
abort(); abort();
} }
done:
rebase_state_free(&state);
return error; return error;
} }
int git_rebase_abort(git_repository *repo, const git_signature *signature) int git_rebase_abort(git_rebase *rebase, const git_signature *signature)
{ {
git_rebase_state state = GIT_REBASE_STATE_INIT;
git_reference *orig_head_ref = NULL; git_reference *orig_head_ref = NULL;
git_commit *orig_head_commit = NULL; git_commit *orig_head_commit = NULL;
int error; int error;
assert(repo && signature); assert(rebase && signature);
if ((error = rebase_state(&state, repo)) < 0)
goto done;
error = state.head_detached ? error = rebase->head_detached ?
git_reference_create(&orig_head_ref, repo, GIT_HEAD_FILE, git_reference_create(&orig_head_ref, rebase->repo, GIT_HEAD_FILE,
&state.orig_head_id, 1, signature, "rebase: aborting") : &rebase->orig_head_id, 1, signature, "rebase: aborting") :
git_reference_symbolic_create( git_reference_symbolic_create(
&orig_head_ref, repo, GIT_HEAD_FILE, state.orig_head_name, 1, &orig_head_ref, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
signature, "rebase: aborting"); signature, "rebase: aborting");
if (error < 0) if (error < 0)
goto done; goto done;
if ((error = git_commit_lookup( if ((error = git_commit_lookup(
&orig_head_commit, repo, &state.orig_head_id)) < 0 || &orig_head_commit, rebase->repo, &rebase->orig_head_id)) < 0 ||
(error = git_reset(repo, (git_object *)orig_head_commit, (error = git_reset(rebase->repo, (git_object *)orig_head_commit,
GIT_RESET_HARD, NULL, signature, NULL)) < 0) GIT_RESET_HARD, NULL, signature, NULL)) < 0)
goto done; goto done;
error = rebase_cleanup(&state); error = rebase_cleanup(rebase);
done: done:
git_commit_free(orig_head_commit); git_commit_free(orig_head_commit);
git_reference_free(orig_head_ref); git_reference_free(orig_head_ref);
rebase_state_free(&state);
return error; return error;
} }
static int rebase_copy_note( static int rebase_copy_note(
git_repository *repo, git_rebase *rebase,
git_oid *from, git_oid *from,
git_oid *to, git_oid *to,
const git_signature *committer, const git_signature *committer,
...@@ -885,7 +918,7 @@ static int rebase_copy_note( ...@@ -885,7 +918,7 @@ static int rebase_copy_note(
git_oid note_id; git_oid note_id;
int error; int error;
if ((error = git_note_read(&note, repo, opts->rewrite_notes_ref, from)) < 0) { if ((error = git_note_read(&note, rebase->repo, opts->rewrite_notes_ref, from)) < 0) {
if (error == GIT_ENOTFOUND) { if (error == GIT_ENOTFOUND) {
giterr_clear(); giterr_clear();
error = 0; error = 0;
...@@ -894,7 +927,7 @@ static int rebase_copy_note( ...@@ -894,7 +927,7 @@ static int rebase_copy_note(
goto done; goto done;
} }
error = git_note_create(&note_id, repo, git_note_author(note), error = git_note_create(&note_id, rebase->repo, git_note_author(note),
committer, opts->rewrite_notes_ref, to, git_note_message(note), 0); committer, opts->rewrite_notes_ref, to, git_note_message(note), 0);
done: done:
...@@ -904,8 +937,7 @@ done: ...@@ -904,8 +937,7 @@ done:
} }
static int rebase_copy_notes( static int rebase_copy_notes(
git_repository *repo, git_rebase *rebase,
git_rebase_state *state,
const git_signature *committer, const git_signature *committer,
const git_rebase_options *opts) const git_rebase_options *opts)
{ {
...@@ -918,7 +950,7 @@ static int rebase_copy_notes( ...@@ -918,7 +950,7 @@ static int rebase_copy_notes(
if (!opts->rewrite_notes_ref) if (!opts->rewrite_notes_ref)
goto done; goto done;
if ((error = git_buf_joinpath(&path, state->state_path, REWRITTEN_FILE)) < 0 || if ((error = git_buf_joinpath(&path, rebase->state_path, REWRITTEN_FILE)) < 0 ||
(error = git_futils_readbuffer(&rewritten, path.ptr)) < 0) (error = git_futils_readbuffer(&rewritten, path.ptr)) < 0)
goto done; goto done;
...@@ -945,7 +977,7 @@ static int rebase_copy_notes( ...@@ -945,7 +977,7 @@ static int rebase_copy_notes(
git_oid_fromstr(&to, tostr) < 0) git_oid_fromstr(&to, tostr) < 0)
goto on_error; goto on_error;
if ((error = rebase_copy_note(repo, &from, &to, committer, opts)) < 0) if ((error = rebase_copy_note(rebase, &from, &to, committer, opts)) < 0)
goto done; goto done;
linenum++; linenum++;
...@@ -965,43 +997,41 @@ done: ...@@ -965,43 +997,41 @@ done:
} }
int git_rebase_finish( int git_rebase_finish(
git_repository *repo, git_rebase *rebase,
const git_signature *signature, const git_signature *signature,
const git_rebase_options *given_opts) const git_rebase_options *given_opts)
{ {
git_rebase_options opts; git_rebase_options opts;
git_rebase_state state = GIT_REBASE_STATE_INIT;
git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL; git_reference *terminal_ref = NULL, *branch_ref = NULL, *head_ref = NULL;
git_commit *terminal_commit = NULL; git_commit *terminal_commit = NULL;
git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT; git_buf branch_msg = GIT_BUF_INIT, head_msg = GIT_BUF_INIT;
char onto[GIT_OID_HEXSZ]; char onto[GIT_OID_HEXSZ];
int error; int error;
assert(repo); assert(rebase);
if ((error = rebase_normalize_opts(repo, &opts, given_opts)) < 0 || if ((error = rebase_normalize_opts(rebase->repo, &opts, given_opts)) < 0)
(error = rebase_state(&state, repo)) < 0)
goto done; goto done;
git_oid_fmt(onto, &state.onto_id); git_oid_fmt(onto, &rebase->onto_id);
if ((error = git_buf_printf(&branch_msg, "rebase finished: %s onto %.*s", if ((error = git_buf_printf(&branch_msg, "rebase finished: %s onto %.*s",
state.orig_head_name, GIT_OID_HEXSZ, onto)) < 0 || rebase->orig_head_name, GIT_OID_HEXSZ, onto)) < 0 ||
(error = git_buf_printf(&head_msg, "rebase finished: returning to %s", (error = git_buf_printf(&head_msg, "rebase finished: returning to %s",
state.orig_head_name)) < 0 || rebase->orig_head_name)) < 0 ||
(error = git_repository_head(&terminal_ref, repo)) < 0 || (error = git_repository_head(&terminal_ref, rebase->repo)) < 0 ||
(error = git_reference_peel((git_object **)&terminal_commit, (error = git_reference_peel((git_object **)&terminal_commit,
terminal_ref, GIT_OBJ_COMMIT)) < 0 || terminal_ref, GIT_OBJ_COMMIT)) < 0 ||
(error = git_reference_create_matching(&branch_ref, (error = git_reference_create_matching(&branch_ref,
repo, state.orig_head_name, git_commit_id(terminal_commit), 1, rebase->repo, rebase->orig_head_name, git_commit_id(terminal_commit), 1,
&state.orig_head_id, signature, branch_msg.ptr)) < 0 || &rebase->orig_head_id, signature, branch_msg.ptr)) < 0 ||
(error = git_reference_symbolic_create(&head_ref, (error = git_reference_symbolic_create(&head_ref,
repo, GIT_HEAD_FILE, state.orig_head_name, 1, rebase->repo, GIT_HEAD_FILE, rebase->orig_head_name, 1,
signature, head_msg.ptr)) < 0 || signature, head_msg.ptr)) < 0 ||
(error = rebase_copy_notes(repo, &state, signature, &opts)) < 0) (error = rebase_copy_notes(rebase, signature, &opts)) < 0)
goto done; goto done;
error = rebase_cleanup(&state); error = rebase_cleanup(rebase);
done: done:
git_buf_free(&head_msg); git_buf_free(&head_msg);
...@@ -1010,9 +1040,21 @@ done: ...@@ -1010,9 +1040,21 @@ done:
git_reference_free(head_ref); git_reference_free(head_ref);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(terminal_ref); git_reference_free(terminal_ref);
rebase_state_free(&state);
rebase_opts_free(&opts); rebase_opts_free(&opts);
return error; return error;
} }
void git_rebase_free(git_rebase *rebase)
{
if (rebase == NULL)
return;
if (rebase->type == GIT_REBASE_TYPE_MERGE) {
git__free(rebase->merge.onto_name);
git_commit_free(rebase->merge.current);
}
git__free(rebase->orig_head_name);
git__free(rebase->state_path);
}
...@@ -20,14 +20,16 @@ void test_rebase_abort__cleanup(void) ...@@ -20,14 +20,16 @@ void test_rebase_abort__cleanup(void)
static void test_abort(git_merge_head *branch, git_merge_head *onto) static void test_abort(git_merge_head *branch, git_merge_head *onto)
{ {
git_rebase *rebase;
git_reference *head_ref, *branch_ref = NULL; git_reference *head_ref, *branch_ref = NULL;
git_signature *signature; git_signature *signature;
git_status_list *statuslist; git_status_list *statuslist;
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_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400));
cl_git_pass(git_rebase_abort(repo, signature)); cl_git_pass(git_rebase_abort(rebase, signature));
cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));
...@@ -58,10 +60,12 @@ static void test_abort(git_merge_head *branch, git_merge_head *onto) ...@@ -58,10 +60,12 @@ static void test_abort(git_merge_head *branch, git_merge_head *onto)
git_reference_free(head_ref); git_reference_free(head_ref);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_signature_free(signature); git_signature_free(signature);
git_rebase_free(rebase);
} }
void test_rebase_abort__merge(void) void test_rebase_abort__merge(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *onto_ref; git_reference *branch_ref, *onto_ref;
git_signature *signature; git_signature *signature;
git_merge_head *branch_head, *onto_head; git_merge_head *branch_head, *onto_head;
...@@ -74,7 +78,7 @@ void test_rebase_abort__merge(void) ...@@ -74,7 +78,7 @@ void test_rebase_abort__merge(void)
cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400));
cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, NULL, onto_head, signature, NULL));
cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo));
test_abort(branch_head, onto_head); test_abort(branch_head, onto_head);
...@@ -86,10 +90,12 @@ void test_rebase_abort__merge(void) ...@@ -86,10 +90,12 @@ void test_rebase_abort__merge(void)
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(onto_ref); git_reference_free(onto_ref);
git_rebase_free(rebase);
} }
void test_rebase_abort__detached_head(void) void test_rebase_abort__detached_head(void)
{ {
git_rebase *rebase;
git_oid branch_id; git_oid branch_id;
git_reference *onto_ref; git_reference *onto_ref;
git_signature *signature; git_signature *signature;
...@@ -103,7 +109,7 @@ void test_rebase_abort__detached_head(void) ...@@ -103,7 +109,7 @@ void test_rebase_abort__detached_head(void)
cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400));
cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, NULL, onto_head, signature, NULL));
cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo));
test_abort(branch_head, onto_head); test_abort(branch_head, onto_head);
...@@ -114,10 +120,12 @@ void test_rebase_abort__detached_head(void) ...@@ -114,10 +120,12 @@ void test_rebase_abort__detached_head(void)
git_merge_head_free(onto_head); git_merge_head_free(onto_head);
git_reference_free(onto_ref); git_reference_free(onto_ref);
git_rebase_free(rebase);
} }
void test_rebase_abort__old_style_head_file(void) void test_rebase_abort__old_style_head_file(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *onto_ref; git_reference *branch_ref, *onto_ref;
git_signature *signature; git_signature *signature;
git_merge_head *branch_head, *onto_head; git_merge_head *branch_head, *onto_head;
...@@ -130,7 +138,7 @@ void test_rebase_abort__old_style_head_file(void) ...@@ -130,7 +138,7 @@ void test_rebase_abort__old_style_head_file(void)
cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400)); cl_git_pass(git_signature_new(&signature, "Rebaser", "rebaser@example.com", 1404157834, -400));
cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, NULL, onto_head, signature, NULL));
cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo));
p_rename("rebase-merge/.git/rebase-merge/orig-head", p_rename("rebase-merge/.git/rebase-merge/orig-head",
...@@ -145,4 +153,5 @@ void test_rebase_abort__old_style_head_file(void) ...@@ -145,4 +153,5 @@ void test_rebase_abort__old_style_head_file(void)
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(onto_ref); git_reference_free(onto_ref);
git_rebase_free(rebase);
} }
...@@ -24,6 +24,7 @@ void test_rebase_merge__cleanup(void) ...@@ -24,6 +24,7 @@ void test_rebase_merge__cleanup(void)
void test_rebase_merge__next(void) void test_rebase_merge__next(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation; git_rebase_operation rebase_operation;
...@@ -40,9 +41,9 @@ void test_rebase_merge__next(void) ...@@ -40,9 +41,9 @@ void test_rebase_merge__next(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
git_oid_fromstr(&pick_id, "da9c51a23d02d931a486f45ad18cda05cf5d2b94"); git_oid_fromstr(&pick_id, "da9c51a23d02d931a486f45ad18cda05cf5d2b94");
...@@ -65,10 +66,12 @@ void test_rebase_merge__next(void) ...@@ -65,10 +66,12 @@ void test_rebase_merge__next(void)
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
void test_rebase_merge__next_with_conflicts(void) void test_rebase_merge__next_with_conflicts(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation; git_rebase_operation rebase_operation;
...@@ -105,9 +108,9 @@ void test_rebase_merge__next_with_conflicts(void) ...@@ -105,9 +108,9 @@ void test_rebase_merge__next_with_conflicts(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
git_oid_fromstr(&pick_id, "33f915f9e4dbd9f4b24430e48731a59b45b15500"); git_oid_fromstr(&pick_id, "33f915f9e4dbd9f4b24430e48731a59b45b15500");
...@@ -129,10 +132,12 @@ void test_rebase_merge__next_with_conflicts(void) ...@@ -129,10 +132,12 @@ void test_rebase_merge__next_with_conflicts(void)
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
void test_rebase_merge__next_stops_with_iterover(void) void test_rebase_merge__next_stops_with_iterover(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation; git_rebase_operation rebase_operation;
...@@ -148,29 +153,29 @@ void test_rebase_merge__next_stops_with_iterover(void) ...@@ -148,29 +153,29 @@ void test_rebase_merge__next_stops_with_iterover(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_git_fail(error = git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_fail(error = git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_assert_equal_i(GIT_ITEROVER, error); cl_assert_equal_i(GIT_ITEROVER, error);
cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end");
...@@ -180,10 +185,12 @@ void test_rebase_merge__next_stops_with_iterover(void) ...@@ -180,10 +185,12 @@ void test_rebase_merge__next_stops_with_iterover(void)
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
void test_rebase_merge__commit(void) void test_rebase_merge__commit(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation; git_rebase_operation rebase_operation;
...@@ -202,10 +209,10 @@ void test_rebase_merge__commit(void) ...@@ -202,10 +209,10 @@ void test_rebase_merge__commit(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_git_pass(git_commit_lookup(&commit, repo, &commit_id)); cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
...@@ -240,10 +247,12 @@ void test_rebase_merge__commit(void) ...@@ -240,10 +247,12 @@ void test_rebase_merge__commit(void)
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
void test_rebase_merge__commit_updates_rewritten(void) void test_rebase_merge__commit_updates_rewritten(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation; git_rebase_operation rebase_operation;
...@@ -258,14 +267,14 @@ void test_rebase_merge__commit_updates_rewritten(void) ...@@ -258,14 +267,14 @@ void test_rebase_merge__commit_updates_rewritten(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_assert_equal_file( cl_assert_equal_file(
...@@ -277,10 +286,12 @@ void test_rebase_merge__commit_updates_rewritten(void) ...@@ -277,10 +286,12 @@ void test_rebase_merge__commit_updates_rewritten(void)
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
void test_rebase_merge__commit_drops_already_applied(void) void test_rebase_merge__commit_drops_already_applied(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation; git_rebase_operation rebase_operation;
...@@ -296,16 +307,16 @@ void test_rebase_merge__commit_drops_already_applied(void) ...@@ -296,16 +307,16 @@ void test_rebase_merge__commit_drops_already_applied(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_fail(error = git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_fail(error = git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_assert_equal_i(GIT_EAPPLIED, error); cl_assert_equal_i(GIT_EAPPLIED, error);
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_assert_equal_file( cl_assert_equal_file(
...@@ -316,10 +327,12 @@ void test_rebase_merge__commit_drops_already_applied(void) ...@@ -316,10 +327,12 @@ void test_rebase_merge__commit_drops_already_applied(void)
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
void test_rebase_merge__finish(void) void test_rebase_merge__finish(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref, *head_ref; git_reference *branch_ref, *upstream_ref, *head_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_rebase_operation rebase_operation; git_rebase_operation rebase_operation;
...@@ -337,16 +350,16 @@ void test_rebase_merge__finish(void) ...@@ -337,16 +350,16 @@ void test_rebase_merge__finish(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_git_fail(error = git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_fail(error = git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_assert_equal_i(GIT_ITEROVER, error); cl_assert_equal_i(GIT_ITEROVER, error);
cl_git_pass(git_rebase_finish(repo, signature, NULL)); cl_git_pass(git_rebase_finish(rebase, signature, NULL));
cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));
...@@ -374,12 +387,14 @@ void test_rebase_merge__finish(void) ...@@ -374,12 +387,14 @@ void test_rebase_merge__finish(void)
git_reference_free(head_ref); git_reference_free(head_ref);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
static void test_copy_note( static void test_copy_note(
const git_rebase_options *opts, const git_rebase_options *opts,
bool should_exist) bool should_exist)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_commit *branch_commit; git_commit *branch_commit;
...@@ -406,13 +421,13 @@ static void test_copy_note( ...@@ -406,13 +421,13 @@ static void test_copy_note(
"refs/notes/test", git_commit_id(branch_commit), "refs/notes/test", git_commit_id(branch_commit),
"This is a commit note.", 0)); "This is a commit note.", 0));
cl_git_pass(git_rebase(repo, branch_head, upstream_head, NULL, signature, opts)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, opts));
cl_git_pass(git_rebase_next(&rebase_operation, repo, &checkout_opts)); cl_git_pass(git_rebase_next(&rebase_operation, rebase, &checkout_opts));
cl_git_pass(git_rebase_commit(&commit_id, repo, NULL, signature, cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature,
NULL, NULL)); NULL, NULL));
cl_git_pass(git_rebase_finish(repo, signature, opts)); cl_git_pass(git_rebase_finish(rebase, signature, opts));
cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo));
...@@ -431,6 +446,7 @@ static void test_copy_note( ...@@ -431,6 +446,7 @@ static void test_copy_note(
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
void test_rebase_merge__copy_notes_off_by_default(void) void test_rebase_merge__copy_notes_off_by_default(void)
......
...@@ -27,6 +27,7 @@ void test_rebase_setup__cleanup(void) ...@@ -27,6 +27,7 @@ void test_rebase_setup__cleanup(void)
* git checkout beef ; git rebase --merge master */ * git checkout beef ; git rebase --merge master */
void test_rebase_setup__blocked_when_in_progress(void) void test_rebase_setup__blocked_when_in_progress(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
...@@ -38,11 +39,11 @@ void test_rebase_setup__blocked_when_in_progress(void) ...@@ -38,11 +39,11 @@ void test_rebase_setup__blocked_when_in_progress(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo));
cl_git_fail(git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL)); cl_git_fail(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
git_merge_head_free(branch_head); git_merge_head_free(branch_head);
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
...@@ -53,6 +54,7 @@ void test_rebase_setup__blocked_when_in_progress(void) ...@@ -53,6 +54,7 @@ void test_rebase_setup__blocked_when_in_progress(void)
/* git checkout beef ; git rebase --merge master */ /* git checkout beef ; git rebase --merge master */
void test_rebase_setup__merge(void) void test_rebase_setup__merge(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_reference *head; git_reference *head;
...@@ -67,7 +69,7 @@ void test_rebase_setup__merge(void) ...@@ -67,7 +69,7 @@ void test_rebase_setup__merge(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo));
...@@ -94,11 +96,13 @@ void test_rebase_setup__merge(void) ...@@ -94,11 +96,13 @@ void test_rebase_setup__merge(void)
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
/* git checkout beef && git rebase --merge --root --onto master */ /* git checkout beef && git rebase --merge --root --onto master */
void test_rebase_setup__merge_root(void) void test_rebase_setup__merge_root(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *onto_ref; git_reference *branch_ref, *onto_ref;
git_merge_head *branch_head, *onto_head; git_merge_head *branch_head, *onto_head;
git_reference *head; git_reference *head;
...@@ -113,7 +117,7 @@ void test_rebase_setup__merge_root(void) ...@@ -113,7 +117,7 @@ void test_rebase_setup__merge_root(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref));
cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref));
cl_git_pass(git_rebase(repo, branch_head, NULL, onto_head, signature, NULL)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, NULL, onto_head, signature, NULL));
git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00");
cl_git_pass(git_repository_head(&head, repo)); cl_git_pass(git_repository_head(&head, repo));
...@@ -140,11 +144,13 @@ void test_rebase_setup__merge_root(void) ...@@ -140,11 +144,13 @@ void test_rebase_setup__merge_root(void)
git_merge_head_free(onto_head); git_merge_head_free(onto_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(onto_ref); git_reference_free(onto_ref);
git_rebase_free(rebase);
} }
/* git checkout gravy && git rebase --merge --onto master veal */ /* git checkout gravy && git rebase --merge --onto master veal */
void test_rebase_setup__merge_onto_and_upstream(void) void test_rebase_setup__merge_onto_and_upstream(void)
{ {
git_rebase *rebase;
git_reference *branch1_ref, *branch2_ref, *onto_ref; git_reference *branch1_ref, *branch2_ref, *onto_ref;
git_merge_head *branch1_head, *branch2_head, *onto_head; git_merge_head *branch1_head, *branch2_head, *onto_head;
git_reference *head; git_reference *head;
...@@ -161,7 +167,7 @@ void test_rebase_setup__merge_onto_and_upstream(void) ...@@ -161,7 +167,7 @@ void test_rebase_setup__merge_onto_and_upstream(void)
cl_git_pass(git_merge_head_from_ref(&branch2_head, repo, branch2_ref)); cl_git_pass(git_merge_head_from_ref(&branch2_head, repo, branch2_ref));
cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref)); cl_git_pass(git_merge_head_from_ref(&onto_head, repo, onto_ref));
cl_git_pass(git_rebase(repo, branch1_head, branch2_head, onto_head, signature, NULL)); cl_git_pass(git_rebase_init(&rebase, repo, branch1_head, branch2_head, onto_head, signature, NULL));
git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00");
cl_git_pass(git_repository_head(&head, repo)); cl_git_pass(git_repository_head(&head, repo));
...@@ -186,12 +192,14 @@ void test_rebase_setup__merge_onto_and_upstream(void) ...@@ -186,12 +192,14 @@ void test_rebase_setup__merge_onto_and_upstream(void)
git_reference_free(branch1_ref); git_reference_free(branch1_ref);
git_reference_free(branch2_ref); git_reference_free(branch2_ref);
git_reference_free(onto_ref); git_reference_free(onto_ref);
git_rebase_free(rebase);
} }
/* Ensure merge commits are dropped in a rebase */ /* Ensure merge commits are dropped in a rebase */
/* git checkout veal && git rebase --merge master */ /* git checkout veal && git rebase --merge master */
void test_rebase_setup__branch_with_merges(void) void test_rebase_setup__branch_with_merges(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_reference *head; git_reference *head;
...@@ -206,7 +214,7 @@ void test_rebase_setup__branch_with_merges(void) ...@@ -206,7 +214,7 @@ void test_rebase_setup__branch_with_merges(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo));
...@@ -233,11 +241,13 @@ void test_rebase_setup__branch_with_merges(void) ...@@ -233,11 +241,13 @@ void test_rebase_setup__branch_with_merges(void)
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
/* git checkout barley && git rebase --merge master */ /* git checkout barley && git rebase --merge master */
void test_rebase_setup__orphan_branch(void) void test_rebase_setup__orphan_branch(void)
{ {
git_rebase *rebase;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
git_merge_head *branch_head, *upstream_head; git_merge_head *branch_head, *upstream_head;
git_reference *head; git_reference *head;
...@@ -252,7 +262,7 @@ void test_rebase_setup__orphan_branch(void) ...@@ -252,7 +262,7 @@ void test_rebase_setup__orphan_branch(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_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_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL));
cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo));
...@@ -279,10 +289,12 @@ void test_rebase_setup__orphan_branch(void) ...@@ -279,10 +289,12 @@ void test_rebase_setup__orphan_branch(void)
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
} }
static int rebase_is_blocked(void) static int rebase_is_blocked(void)
{ {
git_rebase *rebase = NULL;
int error; int error;
git_reference *branch_ref, *upstream_ref; git_reference *branch_ref, *upstream_ref;
...@@ -296,13 +308,14 @@ static int rebase_is_blocked(void) ...@@ -296,13 +308,14 @@ static int rebase_is_blocked(void)
cl_git_pass(git_merge_head_from_ref(&branch_head, repo, branch_ref)); 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_merge_head_from_ref(&upstream_head, repo, upstream_ref));
error = git_rebase(repo, branch_head, upstream_head, NULL, signature, NULL); error = git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, signature, NULL);
git_merge_head_free(branch_head); git_merge_head_free(branch_head);
git_merge_head_free(upstream_head); git_merge_head_free(upstream_head);
git_reference_free(branch_ref); git_reference_free(branch_ref);
git_reference_free(upstream_ref); git_reference_free(upstream_ref);
git_rebase_free(rebase);
return error; return error;
} }
......
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