read_cache();
if (checkout_fast_forward(from, to, 1))
- exit(128); /* the callee should have complained already */
+ return -1; /* the callee should have complained already */
strbuf_addf(&sb, _("%s: fast-forward"), action_name(opts));
* to work on.
*/
if (write_cache_as_tree(head, 0, NULL))
- die (_("Your index file is unmerged."));
+ return error(_("Your index file is unmerged."));
} else {
unborn = get_sha1("HEAD", head);
if (unborn)
return res;
}
-static void prepare_revs(struct replay_opts *opts)
+static int prepare_revs(struct replay_opts *opts)
{
/*
* picking (but not reverting) ranges (but not individual revisions)
opts->revs->reverse ^= 1;
if (prepare_revision_walk(opts->revs))
- die(_("revision walk setup failed"));
+ return error(_("revision walk setup failed"));
if (!opts->revs->commits)
- die(_("empty commit set passed"));
+ return error(_("empty commit set passed"));
+ return 0;
}
-static void read_and_refresh_cache(struct replay_opts *opts)
+static int read_and_refresh_cache(struct replay_opts *opts)
{
static struct lock_file index_lock;
int index_fd = hold_locked_index(&index_lock, 0);
- if (read_index_preload(&the_index, NULL) < 0)
- die(_("git %s: failed to read the index"), action_name(opts));
+ if (read_index_preload(&the_index, NULL) < 0) {
+ rollback_lock_file(&index_lock);
+ return error(_("git %s: failed to read the index"),
+ action_name(opts));
+ }
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
if (the_index.cache_changed && index_fd >= 0) {
- if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
- die(_("git %s: failed to refresh the index"), action_name(opts));
+ if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK)) {
+ rollback_lock_file(&index_lock);
+ return error(_("git %s: failed to refresh the index"),
+ action_name(opts));
+ }
}
rollback_lock_file(&index_lock);
+ return 0;
}
static int format_todo(struct strbuf *buf, struct commit_list *todo_list,
return 0;
}
-static void read_populate_todo(struct commit_list **todo_list,
+static int read_populate_todo(struct commit_list **todo_list,
struct replay_opts *opts)
{
struct strbuf buf = STRBUF_INIT;
fd = open(git_path_todo_file(), O_RDONLY);
if (fd < 0)
- die_errno(_("Could not open %s"), git_path_todo_file());
+ return error_errno(_("Could not open %s"),
+ git_path_todo_file());
if (strbuf_read(&buf, fd, 0) < 0) {
close(fd);
strbuf_release(&buf);
- die(_("Could not read %s."), git_path_todo_file());
+ return error(_("Could not read %s."), git_path_todo_file());
}
close(fd);
res = parse_insn_buffer(buf.buf, todo_list, opts);
strbuf_release(&buf);
if (res)
- die(_("Unusable instruction sheet: %s"), git_path_todo_file());
+ return error(_("Unusable instruction sheet: %s"),
+ git_path_todo_file());
+ return 0;
}
static int populate_opts_cb(const char *key, const char *value, void *data)
return 0;
}
-static void read_populate_opts(struct replay_opts **opts_ptr)
+static int read_populate_opts(struct replay_opts **opts)
{
if (!file_exists(git_path_opts_file()))
- return;
- if (git_config_from_file(populate_opts_cb, git_path_opts_file(), *opts_ptr) < 0)
- die(_("Malformed options sheet: %s"), git_path_opts_file());
+ return 0;
+ /*
+ * The function git_parse_source(), called from git_config_from_file(),
+ * may die() in case of a syntactically incorrect file. We do not care
+ * about this case, though, because we wrote that file ourselves, so we
+ * are pretty certain that it is syntactically correct.
+ */
+ if (git_config_from_file(populate_opts_cb, git_path_opts_file(), *opts) < 0)
+ return error(_("Malformed options sheet: %s"),
+ git_path_opts_file());
+ return 0;
}
-static void walk_revs_populate_todo(struct commit_list **todo_list,
+static int walk_revs_populate_todo(struct commit_list **todo_list,
struct replay_opts *opts)
{
struct commit *commit;
struct commit_list **next;
- prepare_revs(opts);
+ if (prepare_revs(opts))
+ return -1;
next = todo_list;
while ((commit = get_revision(opts->revs)))
next = commit_list_append(commit, next);
+ return 0;
}
static int create_seq_dir(void)
return -1;
}
else if (mkdir(git_path_seq_dir(), 0777) < 0)
- die_errno(_("Could not create sequencer directory %s"),
- git_path_seq_dir());
+ return error_errno(_("Could not create sequencer directory %s"),
+ git_path_seq_dir());
return 0;
}
-static void save_head(const char *head)
+static int save_head(const char *head)
{
static struct lock_file head_lock;
struct strbuf buf = STRBUF_INIT;
int fd;
- fd = hold_lock_file_for_update(&head_lock, git_path_head_file(), LOCK_DIE_ON_ERROR);
+ fd = hold_lock_file_for_update(&head_lock, git_path_head_file(), 0);
+ if (fd < 0) {
+ rollback_lock_file(&head_lock);
+ return error_errno(_("Could not lock HEAD"));
+ }
strbuf_addf(&buf, "%s\n", head);
- if (write_in_full(fd, buf.buf, buf.len) < 0)
- die_errno(_("Could not write to %s"), git_path_head_file());
- if (commit_lock_file(&head_lock) < 0)
- die(_("Error wrapping up %s."), git_path_head_file());
+ if (write_in_full(fd, buf.buf, buf.len) < 0) {
+ rollback_lock_file(&head_lock);
+ return error_errno(_("Could not write to %s"),
+ git_path_head_file());
+ }
+ if (commit_lock_file(&head_lock) < 0) {
+ rollback_lock_file(&head_lock);
+ return error(_("Error wrapping up %s."), git_path_head_file());
+ }
+ return 0;
}
static int reset_for_rollback(const unsigned char *sha1)
return -1;
}
-static void save_todo(struct commit_list *todo_list, struct replay_opts *opts)
+static int save_todo(struct commit_list *todo_list, struct replay_opts *opts)
{
static struct lock_file todo_lock;
struct strbuf buf = STRBUF_INIT;
int fd;
- fd = hold_lock_file_for_update(&todo_lock, git_path_todo_file(), LOCK_DIE_ON_ERROR);
- if (format_todo(&buf, todo_list, opts) < 0)
- die(_("Could not format %s."), git_path_todo_file());
+ fd = hold_lock_file_for_update(&todo_lock, git_path_todo_file(), 0);
+ if (fd < 0)
+ return error_errno(_("Could not lock '%s'"),
+ git_path_todo_file());
+ if (format_todo(&buf, todo_list, opts) < 0) {
+ strbuf_release(&buf);
+ return error(_("Could not format %s."), git_path_todo_file());
+ }
if (write_in_full(fd, buf.buf, buf.len) < 0) {
strbuf_release(&buf);
- die_errno(_("Could not write to %s"), git_path_todo_file());
+ return error_errno(_("Could not write to %s"),
+ git_path_todo_file());
}
if (commit_lock_file(&todo_lock) < 0) {
strbuf_release(&buf);
- die(_("Error wrapping up %s."), git_path_todo_file());
+ return error(_("Error wrapping up %s."), git_path_todo_file());
}
strbuf_release(&buf);
+ return 0;
}
-static void save_opts(struct replay_opts *opts)
+static int save_opts(struct replay_opts *opts)
{
const char *opts_file = git_path_opts_file();
+ int res = 0;
if (opts->no_commit)
- git_config_set_in_file(opts_file, "options.no-commit", "true");
+ res |= git_config_set_in_file_gently(opts_file, "options.no-commit", "true");
if (opts->edit)
- git_config_set_in_file(opts_file, "options.edit", "true");
+ res |= git_config_set_in_file_gently(opts_file, "options.edit", "true");
if (opts->signoff)
- git_config_set_in_file(opts_file, "options.signoff", "true");
+ res |= git_config_set_in_file_gently(opts_file, "options.signoff", "true");
if (opts->record_origin)
- git_config_set_in_file(opts_file, "options.record-origin", "true");
+ res |= git_config_set_in_file_gently(opts_file, "options.record-origin", "true");
if (opts->allow_ff)
- git_config_set_in_file(opts_file, "options.allow-ff", "true");
+ res |= git_config_set_in_file_gently(opts_file, "options.allow-ff", "true");
if (opts->mainline) {
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf, "%d", opts->mainline);
- git_config_set_in_file(opts_file, "options.mainline", buf.buf);
+ res |= git_config_set_in_file_gently(opts_file, "options.mainline", buf.buf);
strbuf_release(&buf);
}
if (opts->strategy)
- git_config_set_in_file(opts_file, "options.strategy", opts->strategy);
+ res |= git_config_set_in_file_gently(opts_file, "options.strategy", opts->strategy);
if (opts->gpg_sign)
- git_config_set_in_file(opts_file, "options.gpg-sign", opts->gpg_sign);
+ res |= git_config_set_in_file_gently(opts_file, "options.gpg-sign", opts->gpg_sign);
if (opts->xopts) {
int i;
for (i = 0; i < opts->xopts_nr; i++)
- git_config_set_multivar_in_file(opts_file,
+ res |= git_config_set_multivar_in_file_gently(opts_file,
"options.strategy-option",
opts->xopts[i], "^$", 0);
}
+ return res;
}
static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
if (opts->allow_ff)
assert(!(opts->signoff || opts->no_commit ||
opts->record_origin || opts->edit));
- read_and_refresh_cache(opts);
+ if (read_and_refresh_cache(opts))
+ return -1;
for (cur = todo_list; cur; cur = cur->next) {
- save_todo(cur, opts);
+ if (save_todo(cur, opts))
+ return -1;
res = do_pick_commit(cur->item, opts);
if (res)
return res;
if (!file_exists(git_path_todo_file()))
return continue_single_pick();
- read_populate_opts(&opts);
- read_populate_todo(&todo_list, opts);
+ if (read_populate_opts(&opts) ||
+ read_populate_todo(&todo_list, opts))
+ return -1;
/* Verify that the conflict has been resolved */
if (file_exists(git_path_cherry_pick_head()) ||
if (opts->subcommand == REPLAY_NONE)
assert(opts->revs);
- read_and_refresh_cache(opts);
+ if (read_and_refresh_cache(opts))
+ return -1;
/*
* Decide what to do depending on the arguments; a fresh
* progress
*/
- walk_revs_populate_todo(&todo_list, opts);
- if (create_seq_dir() < 0)
+ if (walk_revs_populate_todo(&todo_list, opts) ||
+ create_seq_dir() < 0)
return -1;
if (get_sha1("HEAD", sha1) && (opts->action == REPLAY_REVERT))
return error(_("Can't revert as initial commit"));
- save_head(sha1_to_hex(sha1));
- save_opts(opts);
+ if (save_head(sha1_to_hex(sha1)))
+ return -1;
+ if (save_opts(opts))
+ return -1;
return pick_commits(todo_list, opts);
}