diff options
Diffstat (limited to 'sequencer.c')
-rw-r--r-- | sequencer.c | 134 |
1 files changed, 88 insertions, 46 deletions
diff --git a/sequencer.c b/sequencer.c index fa94ed652d..894d12ad72 100644 --- a/sequencer.c +++ b/sequencer.c @@ -347,7 +347,7 @@ static int read_oneliner(struct strbuf *buf, static struct tree *empty_tree(void) { - return lookup_tree(&empty_tree_oid); + return lookup_tree(the_hash_algo->empty_tree); } static int error_dirty_index(struct replay_opts *opts) @@ -449,6 +449,7 @@ static int do_recursive_merge(struct commit *base, struct commit *next, o.branch2 = next ? next_label : "(empty tree)"; if (is_rebase_i(opts)) o.buffer_output = 2; + o.show_rename_progress = 1; head_tree = parse_tree_indirect(head); next_tree = next ? next->tree : empty_tree(); @@ -463,6 +464,7 @@ static int do_recursive_merge(struct commit *base, struct commit *next, if (is_rebase_i(opts) && clean <= 0) fputs(o.obuf.buf, stdout); strbuf_release(&o.obuf); + diff_warn_rename_limit("merge.renamelimit", o.needed_rename_limit, 0); if (clean < 0) return clean; @@ -706,7 +708,7 @@ static int is_original_commit_empty(struct commit *commit) oid_to_hex(&parent->object.oid)); ptree_oid = &parent->tree->object.oid; } else { - ptree_oid = &empty_tree_oid; /* commit is root */ + ptree_oid = the_hash_algo->empty_tree; /* commit is root */ } return !oidcmp(ptree_oid, &commit->tree->object.oid); @@ -795,6 +797,13 @@ static const char *command_to_string(const enum todo_command command) die("Unknown command: %d", command); } +static char command_to_char(const enum todo_command command) +{ + if (command < TODO_COMMENT && todo_command_info[command].c) + return todo_command_info[command].c; + return comment_line_char; +} + static int is_noop(const enum todo_command command) { return TODO_NOOP <= command; @@ -959,7 +968,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit, } else { unborn = get_oid("HEAD", &head); if (unborn) - oidcpy(&head, &empty_tree_oid); + oidcpy(&head, the_hash_algo->empty_tree); if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", NULL, 0)) return error_dirty_index(opts); @@ -1268,6 +1277,7 @@ static int parse_insn_line(struct todo_item *item, const char *bol, char *eol) bol += padding; if (item->command == TODO_EXEC) { + item->commit = NULL; item->arg = bol; item->arg_len = (int)(eol - bol); return 0; @@ -2443,14 +2453,16 @@ void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag) strbuf_release(&sob); } -int sequencer_make_script(int keep_empty, FILE *out, - int argc, const char **argv) +int sequencer_make_script(FILE *out, int argc, const char **argv, + unsigned flags) { char *format = NULL; struct pretty_print_context pp = {0}; struct strbuf buf = STRBUF_INIT; struct rev_info revs; struct commit *commit; + int keep_empty = flags & TODO_LIST_KEEP_EMPTY; + const char *insn = flags & TODO_LIST_ABBREVIATE_CMDS ? "p" : "pick"; init_revisions(&revs, NULL); revs.verbose_header = 1; @@ -2483,7 +2495,8 @@ int sequencer_make_script(int keep_empty, FILE *out, strbuf_reset(&buf); if (!keep_empty && is_original_commit_empty(commit)) strbuf_addf(&buf, "%c ", comment_line_char); - strbuf_addf(&buf, "pick %s ", oid_to_hex(&commit->object.oid)); + strbuf_addf(&buf, "%s %s ", insn, + oid_to_hex(&commit->object.oid)); pretty_print_commit(&pp, commit, &buf); strbuf_addch(&buf, '\n'); fputs(buf.buf, out); @@ -2492,61 +2505,90 @@ int sequencer_make_script(int keep_empty, FILE *out, return 0; } - -int transform_todo_ids(int shorten_ids) +/* + * Add commands after pick and (series of) squash/fixup commands + * in the todo list. + */ +int sequencer_add_exec_commands(const char *commands) { const char *todo_file = rebase_path_todo(); struct todo_list todo_list = TODO_LIST_INIT; - int fd, res, i; - FILE *out; + struct todo_item *item; + struct strbuf *buf = &todo_list.buf; + size_t offset = 0, commands_len = strlen(commands); + int i, first; - 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); + if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0) return error(_("could not read '%s'."), todo_file); - } - close(fd); - res = parse_insn_buffer(todo_list.buf.buf, &todo_list); - if (res) { + if (parse_insn_buffer(todo_list.buf.buf, &todo_list)) { todo_list_release(&todo_list); return error(_("unusable todo list: '%s'"), todo_file); } - out = fopen(todo_file, "w"); - if (!out) { + first = 1; + /* insert <commands> before every pick except the first one */ + for (item = todo_list.items, i = 0; i < todo_list.nr; i++, item++) { + if (item->command == TODO_PICK && !first) { + strbuf_insert(buf, item->offset_in_buf + offset, + commands, commands_len); + offset += commands_len; + } + first = 0; + } + + /* append final <commands> */ + strbuf_add(buf, commands, commands_len); + + i = write_message(buf->buf, buf->len, todo_file, 0); + todo_list_release(&todo_list); + return i; +} + +int transform_todos(unsigned flags) +{ + const char *todo_file = rebase_path_todo(); + struct todo_list todo_list = TODO_LIST_INIT; + struct strbuf buf = STRBUF_INIT; + struct todo_item *item; + int i; + + if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0) + return error(_("could not read '%s'."), todo_file); + + if (parse_insn_buffer(todo_list.buf.buf, &todo_list)) { todo_list_release(&todo_list); - return error(_("unable to open '%s' for writing"), todo_file); + return error(_("unusable todo list: '%s'"), todo_file); } - for (i = 0; i < todo_list.nr; i++) { - struct todo_item *item = todo_list.items + i; - int bol = item->offset_in_buf; - const char *p = todo_list.buf.buf + bol; - int eol = i + 1 < todo_list.nr ? - todo_list.items[i + 1].offset_in_buf : - todo_list.buf.len; - - if (item->command >= TODO_EXEC && item->command != TODO_DROP) - fwrite(p, eol - bol, 1, out); - else { - const char *id = shorten_ids ? - short_commit_name(item->commit) : - oid_to_hex(&item->commit->object.oid); - int len; - - p += strspn(p, " \t"); /* left-trim command */ - len = strcspn(p, " \t"); /* length of command */ - - fprintf(out, "%.*s %s %.*s\n", - len, p, id, item->arg_len, item->arg); + + for (item = todo_list.items, i = 0; i < todo_list.nr; i++, item++) { + /* if the item is not a command write it and continue */ + if (item->command >= TODO_COMMENT) { + strbuf_addf(&buf, "%.*s\n", item->arg_len, item->arg); + continue; } + + /* add command to the buffer */ + if (flags & TODO_LIST_ABBREVIATE_CMDS) + strbuf_addch(&buf, command_to_char(item->command)); + else + strbuf_addstr(&buf, command_to_string(item->command)); + + /* add commit id */ + if (item->commit) { + const char *oid = flags & TODO_LIST_SHORTEN_IDS ? + short_commit_name(item->commit) : + oid_to_hex(&item->commit->object.oid); + + strbuf_addf(&buf, " %s", oid); + } + /* add all the rest */ + strbuf_addf(&buf, " %.*s\n", item->arg_len, item->arg); } - fclose(out); + + i = write_message(buf.buf, buf.len, todo_file, 0); todo_list_release(&todo_list); - return 0; + return i; } enum check_level { |