@ -4700,52 +4700,22 @@ out:
@@ -4700,52 +4700,22 @@ out:
return res;
}
static int rewrite_file(const char *path, const char *buf, size_t len)
{
int rc = 0;
int fd = open(path, O_WRONLY | O_TRUNC);
if (fd < 0)
return error_errno(_("could not open '%s' for writing"), path);
if (write_in_full(fd, buf, len) < 0)
rc = error_errno(_("could not write to '%s'"), path);
if (close(fd) && !rc)
rc = error_errno(_("could not close '%s'"), path);
return rc;
}
/* skip picking commits whose parents are unchanged */
static int skip_unnecessary_picks(struct repository *r, struct object_id *output_oid)
static int skip_unnecessary_picks(struct repository *r,
struct todo_list *todo_list,
struct object_id *base_oid)
{
const char *todo_file = rebase_path_todo();
struct strbuf buf = STRBUF_INIT;
struct todo_list todo_list = TODO_LIST_INIT;
struct object_id *parent_oid;
int fd, i;
if (!read_oneliner(&buf, rebase_path_onto(), 0))
return error(_("could not read 'onto'"));
if (get_oid(buf.buf, output_oid)) {
strbuf_release(&buf);
return error(_("need a HEAD to fixup"));
}
strbuf_release(&buf);
if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
return -1;
if (todo_list_parse_insn_buffer(r, todo_list.buf.buf, &todo_list) < 0) {
todo_list_release(&todo_list);
return -1;
}
int i;
for (i = 0; i < todo_list.nr; i++) {
struct todo_item *item = todo_list.items + i;
for (i = 0; i < todo_list->nr; i++) {
struct todo_item *item = todo_list->items + i;
if (item->command >= TODO_NOOP)
continue;
if (item->command != TODO_PICK)
break;
if (parse_commit(item->commit)) {
todo_list_release(&todo_list);
return error(_("could not parse commit '%s'"),
oid_to_hex(&item->commit->object.oid));
}
@ -4754,42 +4724,26 @@ static int skip_unnecessary_picks(struct repository *r, struct object_id *output
@@ -4754,42 +4724,26 @@ static int skip_unnecessary_picks(struct repository *r, struct object_id *output
if (item->commit->parents->next)
break; /* merge commit */
parent_oid = &item->commit->parents->item->object.oid;
if (!oideq(parent_oid, output_oid))
if (!oideq(parent_oid, base_oid))
break;
oidcpy(output_oid, &item->commit->object.oid);
oidcpy(base_oid, &item->commit->object.oid);
}
if (i > 0) {
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);
if (fd < 0) {
error_errno(_("could not open '%s' for writing"),
done_path);
todo_list_release(&todo_list);
return -1;
}
if (write_in_full(fd, todo_list.buf.buf, offset) < 0) {
if (todo_list_write_to_file(r, todo_list, done_path, NULL, NULL, i, 0)) {
error_errno(_("could not write to '%s'"), done_path);
todo_list_release(&todo_list);
close(fd);
return -1;
}
close(fd);
if (rewrite_file(rebase_path_todo(), todo_list.buf.buf + offset,
todo_list.buf.len - offset) < 0) {
todo_list_release(&todo_list);
return -1;
}
MOVE_ARRAY(todo_list->items, todo_list->items + i, todo_list->nr - i);
todo_list->nr -= i;
todo_list->current = 0;
todo_list.current = i;
if (is_fixup(peek_command(&todo_list, 0)))
record_in_rewritten(output_oid, peek_command(&todo_list, 0));
if (is_fixup(peek_command(todo_list, 0)))
record_in_rewritten(base_oid, peek_command(todo_list, 0));
}
todo_list_release(&todo_list);
return 0;
}
@ -4860,6 +4814,11 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
@@ -4860,6 +4814,11 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
return -1;
}
if (opts->allow_ff && skip_unnecessary_picks(r, &new_todo, &oid)) {
todo_list_release(&new_todo);
return error(_("could not skip unnecessary pick commands"));
}
if (todo_list_write_to_file(r, &new_todo, todo_file, NULL, NULL, -1,
flags & ~(TODO_LIST_SHORTEN_IDS))) {
todo_list_release(&new_todo);
@ -4868,9 +4827,6 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
@@ -4868,9 +4827,6 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
todo_list_release(&new_todo);
if (opts->allow_ff && skip_unnecessary_picks(r, &oid))
return error(_("could not skip unnecessary pick commands"));
if (checkout_onto(opts, onto_name, oid_to_hex(&oid), orig_head))
return -1;