grep: plug a trivial memory leak
[gitweb.git] / sequencer.c
index 6d5d6c3e9bb0463537f06c0f14d905960d51f686..1f729b053bbc6f544fe0b3e8736113082894b24d 100644 (file)
@@ -46,6 +46,16 @@ static GIT_PATH_FUNC(rebase_path_todo, "rebase-merge/git-rebase-todo")
  * actions.
  */
 static GIT_PATH_FUNC(rebase_path_done, "rebase-merge/done")
+/*
+ * The file to keep track of how many commands were already processed (e.g.
+ * for the prompt).
+ */
+static GIT_PATH_FUNC(rebase_path_msgnum, "rebase-merge/msgnum");
+/*
+ * The file to keep track of how many commands are to be processed in total
+ * (e.g. for the prompt).
+ */
+static GIT_PATH_FUNC(rebase_path_msgtotal, "rebase-merge/end");
 /*
  * The commit message that is planned to be used for any changes that
  * need to be committed following a user interaction.
@@ -433,6 +443,8 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
        o.ancestor = base ? base_label : "(empty tree)";
        o.branch1 = "HEAD";
        o.branch2 = next ? next_label : "(empty tree)";
+       if (is_rebase_i(opts))
+               o.buffer_output = 2;
 
        head_tree = parse_tree_indirect(head);
        next_tree = next ? next->tree : empty_tree();
@@ -444,6 +456,8 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
        clean = merge_trees(&o,
                            head_tree,
                            next_tree, base_tree, &result);
+       if (is_rebase_i(opts) && clean <= 0)
+               fputs(o.obuf.buf, stdout);
        strbuf_release(&o.obuf);
        if (clean < 0)
                return clean;
@@ -610,6 +624,11 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
        cmd.git_cmd = 1;
 
        if (is_rebase_i(opts)) {
+               if (!edit) {
+                       cmd.stdout_to_stderr = 1;
+                       cmd.err = -1;
+               }
+
                if (read_env_script(&cmd.env_array)) {
                        const char *gpg_opt = gpg_sign_opt_quoted(opts);
 
@@ -644,6 +663,19 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
        if (opts->allow_empty_message)
                argv_array_push(&cmd.args, "--allow-empty-message");
 
+       if (cmd.err == -1) {
+               /* hide stderr on success */
+               struct strbuf buf = STRBUF_INIT;
+               int rc = pipe_command(&cmd,
+                                     NULL, 0,
+                                     /* stdout is already redirected */
+                                     NULL, 0,
+                                     &buf, 0);
+               if (rc)
+                       fputs(buf.buf, stderr);
+               strbuf_release(&buf);
+               return rc;
+       }
 
        return run_command(&cmd);
 }
@@ -1159,6 +1191,7 @@ struct todo_list {
        struct strbuf buf;
        struct todo_item *items;
        int nr, alloc, current;
+       int done_nr, total_nr;
 };
 
 #define TODO_LIST_INIT { STRBUF_INIT }
@@ -1275,6 +1308,17 @@ static int parse_insn_buffer(char *buf, struct todo_list *todo_list)
        return res;
 }
 
+static int count_commands(struct todo_list *todo_list)
+{
+       int count = 0, i;
+
+       for (i = 0; i < todo_list->nr; i++)
+               if (todo_list->items[i].command != TODO_COMMENT)
+                       count++;
+
+       return count;
+}
+
 static int read_populate_todo(struct todo_list *todo_list,
                        struct replay_opts *opts)
 {
@@ -1292,8 +1336,12 @@ static int read_populate_todo(struct todo_list *todo_list,
        close(fd);
 
        res = parse_insn_buffer(todo_list->buf.buf, todo_list);
-       if (res)
+       if (res) {
+               if (is_rebase_i(opts))
+                       return error(_("please fix this using "
+                                      "'git rebase --edit-todo'."));
                return error(_("unusable instruction sheet: '%s'"), todo_file);
+       }
 
        if (!todo_list->nr &&
            (!is_rebase_i(opts) || !file_exists(rebase_path_done())))
@@ -1313,6 +1361,26 @@ static int read_populate_todo(struct todo_list *todo_list,
                                return error(_("cannot revert during a cherry-pick."));
        }
 
+       if (is_rebase_i(opts)) {
+               struct todo_list done = TODO_LIST_INIT;
+               FILE *f = fopen(rebase_path_msgtotal(), "w");
+
+               if (strbuf_read_file(&done.buf, rebase_path_done(), 0) > 0 &&
+                               !parse_insn_buffer(done.buf.buf, &done))
+                       todo_list->done_nr = count_commands(&done);
+               else
+                       todo_list->done_nr = 0;
+
+               todo_list->total_nr = todo_list->done_nr
+                       + count_commands(todo_list);
+               todo_list_release(&done);
+
+               if (f) {
+                       fprintf(f, "%d\n", todo_list->total_nr);
+                       fclose(f);
+               }
+       }
+
        return 0;
 }
 
@@ -1894,6 +1962,20 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
                if (save_todo(todo_list, opts))
                        return -1;
                if (is_rebase_i(opts)) {
+                       if (item->command != TODO_COMMENT) {
+                               FILE *f = fopen(rebase_path_msgnum(), "w");
+
+                               todo_list->done_nr++;
+
+                               if (f) {
+                                       fprintf(f, "%d\n", todo_list->done_nr);
+                                       fclose(f);
+                               }
+                               fprintf(stderr, "Rebasing (%d/%d)%s",
+                                       todo_list->done_nr,
+                                       todo_list->total_nr,
+                                       opts->verbose ? "\n" : "\r");
+                       }
                        unlink(rebase_path_message());
                        unlink(rebase_path_author_script());
                        unlink(rebase_path_stopped_sha());
@@ -2045,6 +2127,9 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
                }
                apply_autostash(opts);
 
+               fprintf(stderr, "Successfully rebased and updated %s.\n",
+                       head_ref.buf);
+
                strbuf_release(&buf);
                strbuf_release(&head_ref);
        }