Merge branch 'sh/rebase-i-reread-todo-after-exec'
authorJunio C Hamano <gitster@pobox.com>
Mon, 1 May 2017 05:14:44 +0000 (14:14 +0900)
committerJunio C Hamano <gitster@pobox.com>
Mon, 1 May 2017 05:14:44 +0000 (14:14 +0900)
"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

1  2 
sequencer.c
diff --combined sequencer.c
index 130cc868e511e646badde9ebc0894602e27ea37b,3fe9fcdab72f62ca2f7e6e6ba84c67d8846adba5..10c3b4ff81547891172319cee0e291c5160050e1
@@@ -1065,12 -1065,12 +1065,12 @@@ static int do_pick_commit(enum todo_com
                        flags |= CLEANUP_MSG;
                        msg_file = rebase_path_fixup_msg();
                } else {
 -                      const char *dest = git_path("SQUASH_MSG");
 +                      const char *dest = git_path_squash_msg();
                        unlink(dest);
                        if (copy_file(dest, rebase_path_squash_msg(), 0666))
                                return error(_("could not rename '%s' to '%s'"),
                                             rebase_path_squash_msg(), dest);
 -                      unlink(git_path("MERGE_MSG"));
 +                      unlink(git_path_merge_msg());
                        msg_file = dest;
                        flags |= EDIT_MSG;
                }
@@@ -1200,6 -1200,7 +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 +1331,7 @@@ static int count_commands(struct todo_l
  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;
  
        }
        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))
@@@ -1820,10 -1827,10 +1827,10 @@@ static int error_failed_squash(struct c
                return error(_("could not rename '%s' to '%s'"),
                        rebase_path_squash_msg(), rebase_path_message());
        unlink(rebase_path_fixup_msg());
 -      unlink(git_path("MERGE_MSG"));
 -      if (copy_file(git_path("MERGE_MSG"), rebase_path_message(), 0666))
 +      unlink(git_path_merge_msg());
 +      if (copy_file(git_path_merge_msg(), rebase_path_message(), 0666))
                return error(_("could not copy '%s' to '%s'"),
 -                           rebase_path_message(), git_path("MERGE_MSG"));
 +                           rebase_path_message(), git_path_merge_msg());
        return error_with_patch(commit, subject, subject_len, opts, 1, 0);
  }
  
@@@ -2028,10 -2035,25 +2035,25 @@@ static int pick_commits(struct todo_lis
                } 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);
  
@@@ -2167,7 -2189,7 +2189,7 @@@ static int commit_staged_changes(struc
        if (has_unstaged_changes(1))
                return error(_("cannot rebase: You have unstaged changes."));
        if (!has_uncommitted_changes(0)) {
 -              const char *cherry_pick_head = git_path("CHERRY_PICK_HEAD");
 +              const char *cherry_pick_head = git_path_cherry_pick_head();
  
                if (file_exists(cherry_pick_head) && unlink(cherry_pick_head))
                        return error(_("could not remove CHERRY_PICK_HEAD"));