#include "config.h"
#include "lockfile.h"
#include "dir.h"
+#include "object-store.h"
#include "object.h"
#include "commit.h"
#include "sequencer.h"
* the lines are processed, they are removed from the front of this
* file and written to the tail of 'done'.
*/
-static GIT_PATH_FUNC(rebase_path_todo, "rebase-merge/git-rebase-todo")
+GIT_PATH_FUNC(rebase_path_todo, "rebase-merge/git-rebase-todo")
/*
* The rebase command lines that have already been processed. A line
* is moved here when it is first handled, before any associated user
* (typically rebase --interactive) wants to take care
* of the commit itself so remove CHERRY_PICK_HEAD
*/
- unlink(git_path_cherry_pick_head());
+ unlink(git_path_cherry_pick_head(the_repository));
return;
}
}
}
-static int write_message(const void *buf, size_t len, const char *filename,
- int append_eol)
+int write_message(const void *buf, size_t len, const char *filename,
+ int append_eol)
{
struct lock_file msg_file = LOCK_INIT;
#define VERIFY_MSG (1<<4)
#define CREATE_ROOT_COMMIT (1<<5)
+static int run_command_silent_on_success(struct child_process *cmd)
+{
+ struct strbuf buf = STRBUF_INIT;
+ int rc;
+
+ cmd->stdout_to_stderr = 1;
+ rc = pipe_command(cmd,
+ NULL, 0,
+ NULL, 0,
+ &buf, 0);
+
+ if (rc)
+ fputs(buf.buf, stderr);
+ strbuf_release(&buf);
+ return rc;
+}
+
/*
* If we are cherry-pick, and if the merge did not result in
* hand-editing, we will hit this commit and inherit the original
cmd.git_cmd = 1;
- if (is_rebase_i(opts)) {
- if (!(flags & EDIT_MSG)) {
- cmd.stdout_to_stderr = 1;
- cmd.err = -1;
- }
-
- if (read_env_script(&cmd.env_array)) {
- const char *gpg_opt = gpg_sign_opt_quoted(opts);
+ if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
+ const char *gpg_opt = gpg_sign_opt_quoted(opts);
- return error(_(staged_changes_advice),
- gpg_opt, gpg_opt);
- }
+ return error(_(staged_changes_advice),
+ gpg_opt, gpg_opt);
}
argv_array_push(&cmd.args, "commit");
if (opts->allow_empty_message)
argv_array_push(&cmd.args, "--allow-empty-message");
- if (cmd.err == -1) {
- /* hide stderr on success */
- struct strbuf buf = STRBUF_INIT;
- int rc = pipe_command(&cmd,
- NULL, 0,
- /* stdout is already redirected */
- NULL, 0,
- &buf, 0);
- if (rc)
- fputs(buf.buf, stderr);
- strbuf_release(&buf);
- return rc;
- }
-
- return run_command(&cmd);
+ if (is_rebase_i(opts) && !(flags & EDIT_MSG))
+ return run_command_silent_on_success(&cmd);
+ else
+ return run_command(&cmd);
}
static int rest_is_empty(const struct strbuf *sb, int start)
&oid);
strbuf_release(&sb);
if (!res) {
- unlink(git_path_cherry_pick_head());
- unlink(git_path_merge_msg());
+ unlink(git_path_cherry_pick_head(the_repository));
+ unlink(git_path_merge_msg(the_repository));
if (!is_rebase_i(opts))
print_commit_summary(NULL, &oid,
SUMMARY_SHOW_AUTHOR_DATE);
struct replay_opts *opts, int final_fixup)
{
unsigned int flags = opts->edit ? EDIT_MSG : 0;
- const char *msg_file = opts->edit ? NULL : git_path_merge_msg();
+ const char *msg_file = opts->edit ? NULL : git_path_merge_msg(the_repository);
struct object_id head;
struct commit *base, *next, *parent;
const char *base_label, *next_label;
flags |= CLEANUP_MSG;
msg_file = rebase_path_fixup_msg();
} else {
- const char *dest = git_path_squash_msg();
+ const char *dest = git_path_squash_msg(the_repository);
unlink(dest);
if (copy_file(dest, rebase_path_squash_msg(), 0666))
return error(_("could not rename '%s' to '%s'"),
rebase_path_squash_msg(), dest);
- unlink(git_path_merge_msg());
+ unlink(git_path_merge_msg(the_repository));
msg_file = dest;
flags |= EDIT_MSG;
}
goto leave;
res |= write_message(msgbuf.buf, msgbuf.len,
- git_path_merge_msg(), 0);
+ git_path_merge_msg(the_repository), 0);
} else {
struct commit_list *common = NULL;
struct commit_list *remotes = NULL;
res = write_message(msgbuf.buf, msgbuf.len,
- git_path_merge_msg(), 0);
+ git_path_merge_msg(the_repository), 0);
commit_list_insert(base, &common);
commit_list_insert(next, &remotes);
static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
{
int i;
+ char *strategy_opts_string;
strbuf_reset(buf);
if (!read_oneliner(buf, rebase_path_strategy(), 0))
if (!read_oneliner(buf, rebase_path_strategy_opts(), 0))
return;
- opts->xopts_nr = split_cmdline(buf->buf, (const char ***)&opts->xopts);
+ strategy_opts_string = buf->buf;
+ if (*strategy_opts_string == ' ')
+ strategy_opts_string++;
+ opts->xopts_nr = split_cmdline(strategy_opts_string,
+ (const char ***)&opts->xopts);
for (i = 0; i < opts->xopts_nr; i++) {
const char *arg = opts->xopts[i];
{
struct object_id head_oid;
- if (!file_exists(git_path_cherry_pick_head()) &&
- !file_exists(git_path_revert_head()))
+ if (!file_exists(git_path_cherry_pick_head(the_repository)) &&
+ !file_exists(git_path_revert_head(the_repository)))
return error(_("no cherry-pick or revert in progress"));
if (read_ref_full("HEAD", 0, &head_oid, NULL))
return error(_("cannot resolve HEAD"));
if (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666))
return error(_("could not copy '%s' to '%s'"),
rebase_path_squash_msg(), rebase_path_message());
- unlink(git_path_merge_msg());
- if (copy_file(git_path_merge_msg(), rebase_path_message(), 0666))
+ unlink(git_path_merge_msg(the_repository));
+ if (copy_file(git_path_merge_msg(the_repository), rebase_path_message(), 0666))
return error(_("could not copy '%s' to '%s'"),
- rebase_path_message(), git_path_merge_msg());
+ rebase_path_message(),
+ git_path_merge_msg(the_repository));
return error_with_patch(commit, subject, subject_len, opts, 1, 0);
}
write_author_script(message);
find_commit_subject(message, &body);
len = strlen(body);
- ret = write_message(body, len, git_path_merge_msg(), 0);
+ ret = write_message(body, len, git_path_merge_msg(the_repository), 0);
unuse_commit_buffer(commit, message);
if (ret) {
error_errno(_("could not write '%s'"),
- git_path_merge_msg());
+ git_path_merge_msg(the_repository));
goto leave_merge;
}
} else {
len = buf.len;
}
- ret = write_message(p, len, git_path_merge_msg(), 0);
+ ret = write_message(p, len, git_path_merge_msg(the_repository), 0);
strbuf_release(&buf);
if (ret) {
error_errno(_("could not write '%s'"),
- git_path_merge_msg());
+ git_path_merge_msg(the_repository));
goto leave_merge;
}
}
}
write_message(oid_to_hex(&merge_commit->object.oid), GIT_SHA1_HEXSZ,
- git_path_merge_head(), 0);
- write_message("no-ff", 5, git_path_merge_mode(), 0);
+ git_path_merge_head(the_repository), 0);
+ write_message("no-ff", 5, git_path_merge_mode(the_repository), 0);
bases = get_merge_bases(head_commit, merge_commit);
if (bases && !oidcmp(&merge_commit->object.oid,
* value (a negative one would indicate that the `merge`
* command needs to be rescheduled).
*/
- ret = !!run_git_commit(git_path_merge_msg(), opts,
+ ret = !!run_git_commit(git_path_merge_msg(the_repository), opts,
run_commit_flags);
leave_merge:
return buf.buf;
}
+static int run_git_checkout(struct replay_opts *opts, const char *commit,
+ const char *action)
+{
+ struct child_process cmd = CHILD_PROCESS_INIT;
+
+ cmd.git_cmd = 1;
+
+ argv_array_push(&cmd.args, "checkout");
+ argv_array_push(&cmd.args, commit);
+ argv_array_pushf(&cmd.env_array, GIT_REFLOG_ACTION "=%s", action);
+
+ if (opts->verbose)
+ return run_command(&cmd);
+ else
+ return run_command_silent_on_success(&cmd);
+}
+
+int prepare_branch_to_be_rebased(struct replay_opts *opts, const char *commit)
+{
+ const char *action;
+
+ if (commit && *commit) {
+ action = reflog_message(opts, "start", "checkout %s", commit);
+ if (run_git_checkout(opts, commit, action))
+ return error(_("could not checkout %s"), commit);
+ }
+
+ return 0;
+}
+
static const char rescheduled_advice[] =
N_("Could not execute the todo command\n"
"\n"
intend_to_amend();
return error_failed_squash(item->commit, opts,
item->arg_len, item->arg);
- } else if (res && is_rebase_i(opts) && item->commit)
+ } else if (res && is_rebase_i(opts) && item->commit) {
+ int to_amend = 0;
+ struct object_id oid;
+
+ /*
+ * If we are rewording and have either
+ * fast-forwarded already, or are about to
+ * create a new root commit, we want to amend,
+ * otherwise we do not.
+ */
+ if (item->command == TODO_REWORD &&
+ !get_oid("HEAD", &oid) &&
+ (!oidcmp(&item->commit->object.oid, &oid) ||
+ (opts->have_squash_onto &&
+ !oidcmp(&opts->squash_onto, &oid))))
+ to_amend = 1;
+
return res | error_with_patch(item->commit,
- item->arg, item->arg_len, opts, res,
- item->command == TODO_REWORD);
+ item->arg, item->arg_len, opts,
+ res, to_amend);
+ }
} else if (item->command == TODO_EXEC) {
char *end_of_arg = (char *)(item->arg + item->arg_len);
int saved = *end_of_arg;
{
const char *argv[] = { "commit", NULL };
- if (!file_exists(git_path_cherry_pick_head()) &&
- !file_exists(git_path_revert_head()))
+ if (!file_exists(git_path_cherry_pick_head(the_repository)) &&
+ !file_exists(git_path_revert_head(the_repository)))
return error(_("no cherry-pick or revert in progress"));
return run_command_v_opt(argv, RUN_GIT_CMD);
}
}
if (is_clean) {
- const char *cherry_pick_head = git_path_cherry_pick_head();
+ const char *cherry_pick_head = git_path_cherry_pick_head(the_repository);
if (file_exists(cherry_pick_head) && unlink(cherry_pick_head))
return error(_("could not remove CHERRY_PICK_HEAD"));
if (!is_rebase_i(opts)) {
/* Verify that the conflict has been resolved */
- if (file_exists(git_path_cherry_pick_head()) ||
- file_exists(git_path_revert_head())) {
+ if (file_exists(git_path_cherry_pick_head(the_repository)) ||
+ file_exists(git_path_revert_head(the_repository))) {
res = continue_single_pick();
if (res)
goto release_todo_list;
return i;
}
-enum check_level {
- CHECK_IGNORE = 0, CHECK_WARN, CHECK_ERROR
-};
-
-static enum check_level get_missing_commit_check_level(void)
+enum missing_commit_check_level get_missing_commit_check_level(void)
{
const char *value;
if (git_config_get_value("rebase.missingcommitscheck", &value) ||
!strcasecmp("ignore", value))
- return CHECK_IGNORE;
+ return MISSING_COMMIT_CHECK_IGNORE;
if (!strcasecmp("warn", value))
- return CHECK_WARN;
+ return MISSING_COMMIT_CHECK_WARN;
if (!strcasecmp("error", value))
- return CHECK_ERROR;
+ return MISSING_COMMIT_CHECK_ERROR;
warning(_("unrecognized setting %s for option "
"rebase.missingCommitsCheck. Ignoring."), value);
- return CHECK_IGNORE;
+ return MISSING_COMMIT_CHECK_IGNORE;
}
define_commit_slab(commit_seen, unsigned char);
*/
int check_todo_list(void)
{
- enum check_level check_level = get_missing_commit_check_level();
+ enum missing_commit_check_level check_level = get_missing_commit_check_level();
struct strbuf todo_file = STRBUF_INIT;
struct todo_list todo_list = TODO_LIST_INIT;
struct strbuf missing = STRBUF_INIT;
advise_to_edit_todo = res =
parse_insn_buffer(todo_list.buf.buf, &todo_list);
- if (res || check_level == CHECK_IGNORE)
+ if (res || check_level == MISSING_COMMIT_CHECK_IGNORE)
goto leave_check;
/* Mark the commits in git-rebase-todo as seen */
if (!missing.len)
goto leave_check;
- if (check_level == CHECK_ERROR)
+ if (check_level == MISSING_COMMIT_CHECK_ERROR)
advise_to_edit_todo = res = 1;
fprintf(stderr,