#include "sequencer.h"
#include "tag.h"
#include "run-command.h"
-#include "exec_cmd.h"
+#include "exec-cmd.h"
#include "utf8.h"
#include "cache-tree.h"
#include "diff.h"
static const char *short_commit_name(struct commit *commit)
{
- return find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV);
+ return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV);
}
static int get_message(struct commit *commit, struct commit_message *out)
static int write_message(const void *buf, size_t len, const char *filename,
int append_eol)
{
- static struct lock_file msg_file;
+ struct lock_file msg_file = LOCK_INIT;
int msg_fd = hold_lock_file_for_update(&msg_file, filename, 0);
if (msg_fd < 0)
return error_errno(_("could not lock '%s'"), filename);
if (write_in_full(msg_fd, buf, len) < 0) {
+ error_errno(_("could not write to '%s'"), filename);
rollback_lock_file(&msg_file);
- return error_errno(_("could not write to '%s'"), filename);
+ return -1;
}
if (append_eol && write(msg_fd, "\n", 1) < 0) {
+ error_errno(_("could not write eol to '%s'"), filename);
rollback_lock_file(&msg_file);
- return error_errno(_("could not write eol to '%s'"), filename);
- }
- if (commit_lock_file(&msg_file) < 0) {
- rollback_lock_file(&msg_file);
- return error(_("failed to finalize '%s'."), filename);
+ return -1;
}
+ if (commit_lock_file(&msg_file) < 0)
+ return error(_("failed to finalize '%s'"), filename);
return 0;
}
struct tree *result, *next_tree, *base_tree, *head_tree;
int clean;
char **xopt;
- static struct lock_file index_lock;
+ struct lock_file index_lock = LOCK_INIT;
if (hold_locked_index(&index_lock, LOCK_REPORT_ON_ERROR) < 0)
return -1;
fputs(o.obuf.buf, stdout);
strbuf_release(&o.obuf);
diff_warn_rename_limit("merge.renamelimit", o.needed_rename_limit, 0);
- if (clean < 0)
+ if (clean < 0) {
+ rollback_lock_file(&index_lock);
return clean;
+ }
- if (active_cache_changed &&
- write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &index_lock,
+ COMMIT_LOCK | SKIP_IF_UNCHANGED))
/*
* TRANSLATORS: %s will be "revert", "cherry-pick" or
* "rebase -i".
*/
return error(_("%s: Unable to write new index file"),
_(action_name(opts)));
- rollback_lock_file(&index_lock);
if (!clean)
append_conflicts_hint(msgbuf);
commit_list_insert(current_head, &parents);
}
- if (write_cache_as_tree(tree.hash, 0, NULL)) {
+ if (write_cache_as_tree(&tree, 0, NULL)) {
res = error(_("git write-tree failed to write a tree"));
goto out;
}
goto out;
}
- if (commit_tree_extended(msg->buf, msg->len, tree.hash, parents,
- oid->hash, author, opts->gpg_sign, extra)) {
+ if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
+ oid, author, opts->gpg_sign, extra)) {
res = error(_("failed to write commit object"));
goto out;
}
* that represents the "current" state for merge-recursive
* to work on.
*/
- if (write_cache_as_tree(head.hash, 0, NULL))
+ if (write_cache_as_tree(&head, 0, NULL))
return error(_("your index file is unmerged."));
} else {
unborn = get_oid("HEAD", &head);
static int read_and_refresh_cache(struct replay_opts *opts)
{
- static struct lock_file index_lock;
+ struct lock_file index_lock = LOCK_INIT;
int index_fd = hold_locked_index(&index_lock, 0);
if (read_index_preload(&the_index, NULL) < 0) {
rollback_lock_file(&index_lock);
_(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)) {
+ if (index_fd >= 0) {
+ if (write_locked_index(&the_index, &index_lock,
+ COMMIT_LOCK | SKIP_IF_UNCHANGED)) {
return error(_("git %s: failed to refresh the index"),
_(action_name(opts)));
}
}
- rollback_lock_file(&index_lock);
return 0;
}
return count;
}
+static int get_item_line_offset(struct todo_list *todo_list, int index)
+{
+ return index < todo_list->nr ?
+ todo_list->items[index].offset_in_buf : todo_list->buf.len;
+}
+
+static const char *get_item_line(struct todo_list *todo_list, int index)
+{
+ return todo_list->buf.buf + get_item_line_offset(todo_list, index);
+}
+
+static int get_item_line_length(struct todo_list *todo_list, int index)
+{
+ return get_item_line_offset(todo_list, index + 1)
+ - get_item_line_offset(todo_list, index);
+}
+
+static ssize_t strbuf_read_file_or_whine(struct strbuf *sb, const char *path)
+{
+ int fd;
+ ssize_t len;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return error_errno(_("could not open '%s'"), path);
+ len = strbuf_read(sb, fd, 0);
+ close(fd);
+ if (len < 0)
+ return error(_("could not read '%s'."), path);
+ return len;
+}
+
static int read_populate_todo(struct todo_list *todo_list,
struct replay_opts *opts)
{
struct stat st;
const char *todo_file = get_todo_path(opts);
- int fd, res;
+ int res;
strbuf_reset(&todo_list->buf);
- fd = open(todo_file, O_RDONLY);
- if (fd < 0)
- return error_errno(_("could not open '%s'"), todo_file);
- if (strbuf_read(&todo_list->buf, fd, 0) < 0) {
- close(fd);
- return error(_("could not read '%s'."), todo_file);
- }
- close(fd);
+ if (strbuf_read_file_or_whine(&todo_list->buf, todo_file) < 0)
+ return -1;
res = stat(todo_file, &st);
if (res)
static int save_head(const char *head)
{
- static struct lock_file head_lock;
+ struct lock_file head_lock = LOCK_INIT;
struct strbuf buf = STRBUF_INIT;
int fd;
ssize_t written;
fd = hold_lock_file_for_update(&head_lock, git_path_head_file(), 0);
- if (fd < 0) {
- rollback_lock_file(&head_lock);
+ if (fd < 0)
return error_errno(_("could not lock HEAD"));
- }
strbuf_addf(&buf, "%s\n", head);
written = write_in_full(fd, buf.buf, buf.len);
strbuf_release(&buf);
if (written < 0) {
+ error_errno(_("could not write to '%s'"), git_path_head_file());
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(_("failed to finalize '%s'."), git_path_head_file());
+ return -1;
}
+ if (commit_lock_file(&head_lock) < 0)
+ return error(_("failed to finalize '%s'"), git_path_head_file());
return 0;
}
static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
{
- static struct lock_file todo_lock;
+ struct lock_file todo_lock = LOCK_INIT;
const char *todo_path = get_todo_path(opts);
int next = todo_list->current, offset, fd;
fd = hold_lock_file_for_update(&todo_lock, todo_path, 0);
if (fd < 0)
return error_errno(_("could not lock '%s'"), todo_path);
- offset = next < todo_list->nr ?
- todo_list->items[next].offset_in_buf : todo_list->buf.len;
+ offset = get_item_line_offset(todo_list, next);
if (write_in_full(fd, todo_list->buf.buf + offset,
todo_list->buf.len - offset) < 0)
return error_errno(_("could not write to '%s'"), todo_path);
if (commit_lock_file(&todo_lock) < 0)
- return error(_("failed to finalize '%s'."), todo_path);
+ return error(_("failed to finalize '%s'"), todo_path);
- if (is_rebase_i(opts)) {
- const char *done_path = rebase_path_done();
- int fd = open(done_path, O_CREAT | O_WRONLY | O_APPEND, 0666);
- int prev_offset = !next ? 0 :
- todo_list->items[next - 1].offset_in_buf;
+ if (is_rebase_i(opts) && next > 0) {
+ const char *done = rebase_path_done();
+ int fd = open(done, O_CREAT | O_WRONLY | O_APPEND, 0666);
+ int ret = 0;
- if (fd >= 0 && offset > prev_offset &&
- write_in_full(fd, todo_list->buf.buf + prev_offset,
- offset - prev_offset) < 0) {
- close(fd);
- return error_errno(_("could not write to '%s'"),
- done_path);
- }
- if (fd >= 0)
- close(fd);
+ if (fd < 0)
+ return 0;
+ if (write_in_full(fd, get_item_line(todo_list, next - 1),
+ get_item_line_length(todo_list, next - 1))
+ < 0)
+ ret = error_errno(_("could not write to '%s'"), done);
+ if (close(fd) < 0)
+ ret = error_errno(_("failed to finalize '%s'"), done);
+ return ret;
}
return 0;
}
p = short_commit_name(commit);
if (write_message(p, strlen(p), rebase_path_stopped_sha(), 1) < 0)
return -1;
+ if (update_ref("rebase", "REBASE_HEAD", &commit->object.oid,
+ NULL, REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
+ res |= error(_("could not update %s"), "REBASE_HEAD");
strbuf_addf(&buf, "%s/patch", get_dir(opts));
memset(&log_tree_opt, 0, sizeof(log_tree_opt));
return buf.buf;
}
+static const char rescheduled_advice[] =
+N_("Could not execute the todo command\n"
+"\n"
+" %.*s"
+"\n"
+"It has been rescheduled; To edit the command before continuing, please\n"
+"edit the todo list first:\n"
+"\n"
+" git rebase --edit-todo\n"
+" git rebase --continue\n");
+
static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
{
int res = 0;
unlink(rebase_path_author_script());
unlink(rebase_path_stopped_sha());
unlink(rebase_path_amend());
+ delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
}
if (item->command <= TODO_SQUASH) {
if (is_rebase_i(opts))
opts, is_final_fixup(todo_list));
if (is_rebase_i(opts) && res < 0) {
/* Reschedule */
+ advise(_(rescheduled_advice),
+ get_item_line_length(todo_list,
+ todo_list->current),
+ get_item_line(todo_list,
+ todo_list->current));
todo_list->current--;
if (save_todo(todo_list, opts))
return -1;
if (!get_oid(name, &oid)) {
if (!lookup_commit_reference_gently(&oid, 1)) {
- enum object_type type = sha1_object_info(oid.hash, NULL);
+ enum object_type type = oid_object_info(&oid,
+ NULL);
return error(_("%s: can't cherry-pick a %s"),
- name, typename(type));
+ name, type_name(type));
}
} else
return error(_("%s: bad revision"), name);
struct strbuf todo_file = STRBUF_INIT;
struct todo_list todo_list = TODO_LIST_INIT;
struct strbuf missing = STRBUF_INIT;
- int advise_to_edit_todo = 0, res = 0, fd, i;
+ int advise_to_edit_todo = 0, res = 0, i;
strbuf_addstr(&todo_file, rebase_path_todo());
- fd = open(todo_file.buf, O_RDONLY);
- if (fd < 0) {
- res = error_errno(_("could not open '%s'"), todo_file.buf);
- goto leave_check;
- }
- if (strbuf_read(&todo_list.buf, fd, 0) < 0) {
- close(fd);
- res = error(_("could not read '%s'."), todo_file.buf);
+ if (strbuf_read_file_or_whine(&todo_list.buf, todo_file.buf) < 0) {
+ res = -1;
goto leave_check;
}
- close(fd);
advise_to_edit_todo = res =
parse_insn_buffer(todo_list.buf.buf, &todo_list);
todo_list_release(&todo_list);
strbuf_addstr(&todo_file, ".backup");
- fd = open(todo_file.buf, O_RDONLY);
- if (fd < 0) {
- res = error_errno(_("could not open '%s'"), todo_file.buf);
- goto leave_check;
- }
- if (strbuf_read(&todo_list.buf, fd, 0) < 0) {
- close(fd);
- res = error(_("could not read '%s'."), todo_file.buf);
+ if (strbuf_read_file_or_whine(&todo_list.buf, todo_file.buf) < 0) {
+ res = -1;
goto leave_check;
}
- close(fd);
strbuf_release(&todo_file);
res = !!parse_insn_buffer(todo_list.buf.buf, &todo_list);
}
strbuf_release(&buf);
- fd = open(todo_file, O_RDONLY);
- if (fd < 0) {
- return error_errno(_("could not open '%s'"), todo_file);
- }
- if (strbuf_read(&todo_list.buf, fd, 0) < 0) {
- close(fd);
- return error(_("could not read '%s'."), todo_file);
- }
- close(fd);
+ if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
+ return -1;
if (parse_insn_buffer(todo_list.buf.buf, &todo_list) < 0) {
todo_list_release(&todo_list);
return -1;
oid = &item->commit->object.oid;
}
if (i > 0) {
- int offset = i < todo_list.nr ?
- todo_list.items[i].offset_in_buf : todo_list.buf.len;
+ int offset = get_item_line_offset(&todo_list, i);
const char *done_path = rebase_path_done();
fd = open(done_path, O_CREAT | O_WRONLY | O_APPEND, 0666);
const char *todo_file = rebase_path_todo();
struct todo_list todo_list = TODO_LIST_INIT;
struct hashmap subject2item;
- int res = 0, rearranged = 0, *next, *tail, fd, i;
+ int res = 0, rearranged = 0, *next, *tail, i;
char **subjects;
- fd = open(todo_file, O_RDONLY);
- if (fd < 0)
- return error_errno(_("could not open '%s'"), todo_file);
- if (strbuf_read(&todo_list.buf, fd, 0) < 0) {
- close(fd);
- return error(_("could not read '%s'."), todo_file);
- }
- close(fd);
+ if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
+ return -1;
if (parse_insn_buffer(todo_list.buf.buf, &todo_list) < 0) {
todo_list_release(&todo_list);
return -1;
struct subject2item_entry *entry;
next[i] = tail[i] = -1;
- if (item->command >= TODO_EXEC) {
+ if (!item->commit || item->command == TODO_DROP) {
subjects[i] = NULL;
continue;
}
continue;
while (cur >= 0) {
- int offset = todo_list.items[cur].offset_in_buf;
- int end_offset = cur + 1 < todo_list.nr ?
- todo_list.items[cur + 1].offset_in_buf :
- todo_list.buf.len;
- char *bol = todo_list.buf.buf + offset;
- char *eol = todo_list.buf.buf + end_offset;
+ const char *bol =
+ get_item_line(&todo_list, cur);
+ const char *eol =
+ get_item_line(&todo_list, cur + 1);
/* replace 'pick', by 'fixup' or 'squash' */
command = todo_list.items[cur].command;