summaryrefslogtreecommitdiff
path: root/sequencer.c
diff options
context:
space:
mode:
authorStephen Hicks <sdh@google.com>2017-04-26 19:17:40 (GMT)
committerJunio C Hamano <gitster@pobox.com>2017-04-27 01:56:26 (GMT)
commit54fd3243daec7d59394f25846450d83c0012e57c (patch)
treef5dac03405fbe120d5a1fcad876fe8fd60a00a6e /sequencer.c
parente2cb6ab84c94f147f1259260961513b40c36108a (diff)
downloadgit-54fd3243daec7d59394f25846450d83c0012e57c.zip
git-54fd3243daec7d59394f25846450d83c0012e57c.tar.gz
git-54fd3243daec7d59394f25846450d83c0012e57c.tar.bz2
rebase -i: reread the todo list if `exec` touched it
In the scripted version of the interactive rebase, there was no internal representation of the todo list; it was re-read before every command. That allowed the hack that an `exec` command could append (or even completely rewrite) the todo list. This hack was broken by the partial conversion of the interactive rebase to C, and this patch reinstates it. We also add a small test to verify that this fix does not regress in the future. Signed-off-by: Stephen Hicks <sdh@google.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'sequencer.c')
-rw-r--r--sequencer.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/sequencer.c b/sequencer.c
index 77afeca..3fe9fcd 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1200,6 +1200,7 @@ struct todo_list {
struct todo_item *items;
int nr, alloc, current;
int done_nr, total_nr;
+ struct stat_data stat;
};
#define TODO_LIST_INIT { STRBUF_INIT }
@@ -1330,6 +1331,7 @@ static int count_commands(struct todo_list *todo_list)
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;
@@ -1343,6 +1345,11 @@ static int read_populate_todo(struct todo_list *todo_list,
}
close(fd);
+ res = stat(todo_file, &st);
+ if (res)
+ return error(_("could not stat '%s'"), todo_file);
+ fill_stat_data(&todo_list->stat, &st);
+
res = parse_insn_buffer(todo_list->buf.buf, todo_list);
if (res) {
if (is_rebase_i(opts))
@@ -2028,10 +2035,25 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
} else if (item->command == TODO_EXEC) {
char *end_of_arg = (char *)(item->arg + item->arg_len);
int saved = *end_of_arg;
+ struct stat st;
*end_of_arg = '\0';
res = do_exec(item->arg);
*end_of_arg = saved;
+
+ /* Reread the todo file if it has changed. */
+ if (res)
+ ; /* fall through */
+ else if (stat(get_todo_path(opts), &st))
+ res = error_errno(_("could not stat '%s'"),
+ get_todo_path(opts));
+ else if (match_stat_data(&todo_list->stat, &st)) {
+ todo_list_release(todo_list);
+ if (read_populate_todo(todo_list, opts))
+ res = -1; /* message was printed */
+ /* `current` will be incremented below */
+ todo_list->current = -1;
+ }
} else if (!is_noop(item->command))
return error(_("unknown command %d"), item->command);