summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2017-05-01 14:14:44 +0900
committerJunio C Hamano <gitster@pobox.com>2017-05-01 14:14:44 +0900
commit0998b648d6addfb7eaf17e1aa4e7fb1dbefac548 (patch)
tree80376d1e5a944d055086022cfb99d67bbc7c0835
parent3c0a7b9d6b94ba86db2015445d0963a3fae932dc (diff)
parent54fd3243daec7d59394f25846450d83c0012e57c (diff)
downloadgit-0998b648d6addfb7eaf17e1aa4e7fb1dbefac548.tar.gz
Merge branch 'sh/rebase-i-reread-todo-after-exec'
"git rebase -i" failed to re-read the todo list file when the command specified with the `exec` instruction updated it. * sh/rebase-i-reread-todo-after-exec: rebase -i: reread the todo list if `exec` touched it
-rw-r--r--sequencer.c22
-rwxr-xr-xt/t3429-rebase-edit-todo.sh14
2 files changed, 36 insertions, 0 deletions
diff --git a/sequencer.c b/sequencer.c
index 130cc868e5..10c3b4ff81 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);
diff --git a/t/t3429-rebase-edit-todo.sh b/t/t3429-rebase-edit-todo.sh
new file mode 100755
index 0000000000..b9292dfc2a
--- /dev/null
+++ b/t/t3429-rebase-edit-todo.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+test_description='rebase should reread the todo file if an exec modifies it'
+
+. ./test-lib.sh
+
+test_expect_success 'rebase exec modifies rebase-todo' '
+ test_commit initial &&
+ todo=.git/rebase-merge/git-rebase-todo &&
+ git rebase HEAD -x "echo exec touch F >>$todo" &&
+ test -e F
+'
+
+test_done