@@ -258,7 +258,7 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
ret = check_todo_list_from_file();
break;
case REARRANGE_SQUASH:
- ret = rearrange_squash();
+ ret = rearrange_squash_in_todo_file();
break;
case ADD_EXEC:
ret = sequencer_add_exec_commands(cmd);
@@ -4632,7 +4632,7 @@ int complete_action(struct replay_opts *opts, unsigned flags,
write_message("noop\n", 5, todo_file, 0))
return -1;
- if (autosquash && rearrange_squash())
+ if (autosquash && rearrange_squash_in_todo_file())
return -1;
if (cmd && *cmd)
@@ -4738,22 +4738,13 @@ define_commit_slab(commit_todo_item, struct todo_item *);
* message will have to be retrieved from the commit (as the oneline in the
* script cannot be trusted) in order to normalize the autosquash arrangement.
*/
-int rearrange_squash(void)
+static int todo_list_rearrange_squash(struct todo_list *todo_list)
{
- 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, i;
+ int rearranged = 0, *next, *tail, i;
char **subjects;
struct commit_todo_item commit_todo;
- if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
- return -1;
- if (todo_list_parse_insn_buffer(todo_list.buf.buf, &todo_list) < 0) {
- todo_list_release(&todo_list);
- return -1;
- }
-
init_commit_todo_item(&commit_todo);
/*
* The hashmap maps onelines to the respective todo list index.
@@ -4765,13 +4756,13 @@ int rearrange_squash(void)
* be moved to appear after the i'th.
*/
hashmap_init(&subject2item, (hashmap_cmp_fn) subject2item_cmp,
- NULL, todo_list.nr);
- ALLOC_ARRAY(next, todo_list.nr);
- ALLOC_ARRAY(tail, todo_list.nr);
- ALLOC_ARRAY(subjects, todo_list.nr);
- for (i = 0; i < todo_list.nr; i++) {
+ NULL, todo_list->nr);
+ ALLOC_ARRAY(next, todo_list->nr);
+ ALLOC_ARRAY(tail, todo_list->nr);
+ ALLOC_ARRAY(subjects, todo_list->nr);
+ for (i = 0; i < todo_list->nr; i++) {
struct strbuf buf = STRBUF_INIT;
- struct todo_item *item = todo_list.items + i;
+ struct todo_item *item = todo_list->items + i;
const char *commit_buffer, *subject, *p;
size_t subject_len;
int i2 = -1;
@@ -4784,7 +4775,6 @@ int rearrange_squash(void)
}
if (is_fixup(item->command)) {
- todo_list_release(&todo_list);
clear_commit_todo_item(&commit_todo);
return error(_("the script was already rearranged."));
}
@@ -4819,7 +4809,7 @@ int rearrange_squash(void)
*commit_todo_item_at(&commit_todo, commit2))
/* found by commit name */
i2 = *commit_todo_item_at(&commit_todo, commit2)
- - todo_list.items;
+ - todo_list->items;
else {
/* copy can be a prefix of the commit subject */
for (i2 = 0; i2 < i; i2++)
@@ -4832,7 +4822,7 @@ int rearrange_squash(void)
}
if (i2 >= 0) {
rearranged = 1;
- todo_list.items[i].command =
+ todo_list->items[i].command =
starts_with(subject, "fixup!") ?
TODO_FIXUP : TODO_SQUASH;
if (next[i2] < 0)
@@ -4852,8 +4842,8 @@ int rearrange_squash(void)
if (rearranged) {
struct strbuf buf = STRBUF_INIT;
- for (i = 0; i < todo_list.nr; i++) {
- enum todo_command command = todo_list.items[i].command;
+ for (i = 0; i < todo_list->nr; i++) {
+ enum todo_command command = todo_list->items[i].command;
int cur = i;
/*
@@ -4865,12 +4855,12 @@ int rearrange_squash(void)
while (cur >= 0) {
const char *bol =
- get_item_line(&todo_list, cur);
+ get_item_line(todo_list, cur);
const char *eol =
- get_item_line(&todo_list, cur + 1);
+ get_item_line(todo_list, cur + 1);
/* replace 'pick', by 'fixup' or 'squash' */
- command = todo_list.items[cur].command;
+ command = todo_list->items[cur].command;
if (is_fixup(command)) {
strbuf_addstr(&buf,
todo_command_info[command].str);
@@ -4883,18 +4873,43 @@ int rearrange_squash(void)
}
}
- res = rewrite_file(todo_file, buf.buf, buf.len);
+ strbuf_reset(&todo_list->buf);
+ strbuf_add(&todo_list->buf, buf.buf, buf.len);
strbuf_release(&buf);
}
free(next);
free(tail);
- for (i = 0; i < todo_list.nr; i++)
+ for (i = 0; i < todo_list->nr; i++)
free(subjects[i]);
free(subjects);
hashmap_free(&subject2item, 1);
- todo_list_release(&todo_list);
clear_commit_todo_item(&commit_todo);
+
+ if (todo_list_parse_insn_buffer(todo_list->buf.buf, todo_list))
+ BUG("unusable todo list");
+
+ return 0;
+}
+
+int rearrange_squash_in_todo_file(void)
+{
+ const char *todo_file = rebase_path_todo();
+ struct todo_list todo_list = TODO_LIST_INIT;
+ int res = 0;
+
+ if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
+ return -1;
+ if (todo_list_parse_insn_buffer(todo_list.buf.buf, &todo_list) < 0) {
+ todo_list_release(&todo_list);
+ return -1;
+ }
+
+ res = todo_list_rearrange_squash(&todo_list);
+ if (!res)
+ res = rewrite_file(todo_file, todo_list.buf.buf, todo_list.buf.len);
+
+ todo_list_release(&todo_list);
return res;
}
@@ -141,7 +141,7 @@ int complete_action(struct replay_opts *opts, unsigned flags,
const char *shortrevisions, const char *onto_name,
const char *onto, const char *orig_head, const char *cmd,
unsigned autosquash);
-int rearrange_squash(void);
+int rearrange_squash_in_todo_file(void);
extern const char sign_off_header[];
This refactors rearrange_squash() to work on a todo_list to avoid redundant reads and writes. The function is renamed todo_list_rearrange_squash(). As rebase -p still need to check the todo list from the disk, a new function is introduced, rearrange_squash_in_todo_file(). Signed-off-by: Alban Gruin <alban.gruin@gmail.com> --- builtin/rebase--interactive.c | 2 +- sequencer.c | 73 +++++++++++++++++++++-------------- sequencer.h | 2 +- 3 files changed, 46 insertions(+), 31 deletions(-)