4505
* Add commands after pick and (series of) squash/fixup commands
4506
* in the todo list.
4507
*/
4508
-int sequencer_add_exec_commands(struct repository *r,
4509
- const char *commands)
4508
+static void todo_list_add_exec_commands(struct todo_list *todo_list,
4509
+ struct string_list *commands)
4510
{
4511
- const char *todo_file = rebase_path_todo();
4512
- struct todo_list todo_list = TODO_LIST_INIT;
4513
- struct strbuf *buf = &todo_list.buf;
4514
- size_t offset = 0, commands_len = strlen(commands);
4515
- int i, insert;
4511
+ struct strbuf *buf = &todo_list->buf;
4512
+ size_t base_offset = buf->len;
4513
+ int i, insert, nr = 0, alloc = 0;
4514
+ struct todo_item *items = NULL, *base_items = NULL;
4515
4517
- if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
4518
- return error(_("could not read '%s'."), todo_file);
4516
+ base_items = xcalloc(commands->nr, sizeof(struct todo_item));
4517
+ for (i = 0; i < commands->nr; i++) {
4518
+ size_t command_len = strlen(commands->items[i].string);
4519
4520
- if (todo_list_parse_insn_buffer(r, todo_list.buf.buf, &todo_list)) {
4521
- todo_list_release(&todo_list);
4522
- return error(_("unusable todo list: '%s'"), todo_file);
4520
+ strbuf_addstr(buf, commands->items[i].string);
4521
+ strbuf_addch(buf, '\n');
4522
+
4523
+ base_items[i].command = TODO_EXEC;
4524
+ base_items[i].offset_in_buf = base_offset;
4525
+ base_items[i].arg_offset = base_offset + strlen("exec ");
4526
+ base_items[i].arg_len = command_len - strlen("exec ");
4527
+
4528
+ base_offset += command_len + 1;
4529
}
4530
4531
/*
4532
* Insert <commands> after every pick. Here, fixup/squash chains
4533
* are considered part of the pick, so we insert the commands *after*
4534
* those chains if there are any.
4535
+ *
4536
+ * As we insert the exec commands immediatly after rearranging
4537
+ * any fixups and before the user edits the list, a fixup chain
4538
+ * can never contain comments (any comments are empty picks that
4539
+ * have been commented out because the user did not specify
4540
+ * --keep-empty). So, it is safe to insert an exec command
4541
+ * without looking at the command following a comment.
4542
*/
4530
- insert = -1;
4531
- for (i = 0; i < todo_list.nr; i++) {
4532
- enum todo_command command = todo_list.items[i].command;
4533
-
4534
- if (insert >= 0) {
4535
- /* skip fixup/squash chains */
4536
- if (command == TODO_COMMENT)
4537
- continue;
4538
- else if (is_fixup(command)) {
4539
- insert = i + 1;
4540
- continue;
4541
- }
4542
- strbuf_insert(buf,
4543
- todo_list.items[insert].offset_in_buf +
4544
- offset, commands, commands_len);
4545
- offset += commands_len;
4546
- insert = -1;
4543
+ insert = 0;
4544
+ for (i = 0; i < todo_list->nr; i++) {
4545
+ enum todo_command command = todo_list->items[i].command;
4546
+ if (insert && !is_fixup(command)) {
4547
+ ALLOC_GROW(items, nr + commands->nr, alloc);
4548
+ COPY_ARRAY(items + nr, base_items, commands->nr);
4549
+ nr += commands->nr;
4550
+
4551
+ insert = 0;
4552
}
4553
4554
+ ALLOC_GROW(items, nr + 1, alloc);
4555
+ items[nr++] = todo_list->items[i];
4556
+
4557
if (command == TODO_PICK || command == TODO_MERGE)
4550
- insert = i + 1;
4558
+ insert = 1;
4559
}
4560
4561
/* insert or append final <commands> */
4554
- if (insert >= 0 && insert < todo_list.nr)
4555
- strbuf_insert(buf, todo_list.items[insert].offset_in_buf +
4556
- offset, commands, commands_len);
4557
- else if (insert >= 0 || !offset)
4558
- strbuf_add(buf, commands, commands_len);
4562
+ if (insert || nr == todo_list->nr) {
4563
+ ALLOC_GROW(items, nr + commands->nr, alloc);
4564
+ COPY_ARRAY(items + nr, base_items, commands->nr);
4565
+ nr += commands->nr;
4566
+ }
4567
+
4568
+ free(base_items);
4569
+ FREE_AND_NULL(todo_list->items);
4570
+ todo_list->items = items;
4571
+ todo_list->nr = nr;
4572
+ todo_list->alloc = alloc;
4573
+}
4574
+
4575
+int sequencer_add_exec_commands(struct repository *r,
4576
+ struct string_list *commands)
4577
+{
4578
+ const char *todo_file = rebase_path_todo();
4579
+ struct todo_list todo_list = TODO_LIST_INIT;
4580
+ int res;
4581
+
4582
+ if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
4583
+ return error_errno(_("could not read '%s'."), todo_file);
4584
4560
- i = write_message(buf->buf, buf->len, todo_file, 0);
4585
+ if (todo_list_parse_insn_buffer(r, todo_list.buf.buf, &todo_list)) {
4586
+ todo_list_release(&todo_list);
4587
+ return error(_("unusable todo list: '%s'"), todo_file);
4588
+ }
4589
+
4590
+ todo_list_add_exec_commands(&todo_list, commands);
4591
+ res = todo_list_write_to_file(r, &todo_list, todo_file, NULL, NULL, -1, 0);
4592
todo_list_release(&todo_list);
4562
- return i;
4593
+
4594
+ if (res)
4595
+ return error_errno(_("could not write '%s'."), todo_file);
4596
+ return 0;
4597
}
4598
4599
static void todo_list_to_strbuf(struct repository *r, struct todo_list *todo_list,
4824
4825
int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
4826
const char *shortrevisions, const char *onto_name,
4793
- const char *onto, const char *orig_head, const char *cmd,
4827
+ const char *onto, const char *orig_head, struct string_list *commands,
4828
unsigned autosquash)
4829
{
4830
const char *shortonto, *todo_file = rebase_path_todo();
4843
if (autosquash && rearrange_squash(r))
4844
return -1;
4845
4812
- if (cmd && *cmd)
4813
- sequencer_add_exec_commands(r, cmd);
4846
+ if (commands->nr)
4847
+ sequencer_add_exec_commands(r, commands);
4848
4849
if (strbuf_read_file(buf, todo_file, 0) < 0)
4850
return error_errno(_("could not read '%s'."), todo_file);