sequencer (rebase -i): show only failed cherry-picks' output
[gitweb.git] / sequencer.c
index 41f80ea2c42095684978854daa061be087d6d1bb..27dc91cc95601b7a6ddaf498ce4182cc7371778b 100644 (file)
@@ -433,6 +433,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 +446,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;
@@ -544,18 +548,17 @@ static int write_author_script(const char *message)
 }
 
 /*
- * Read the author-script file into an environment block, ready for use in
- * run_command(), that can be free()d afterwards.
+ * Read a list of environment variable assignments (such as the author-script
+ * file) into an environment block. Returns -1 on error, 0 otherwise.
  */
-static char **read_author_script(void)
+static int read_env_script(struct argv_array *env)
 {
        struct strbuf script = STRBUF_INIT;
        int i, count = 0;
-       char *p, *p2, **env;
-       size_t env_size;
+       char *p, *p2;
 
        if (strbuf_read_file(&script, rebase_path_author_script(), 256) <= 0)
-               return NULL;
+               return -1;
 
        for (p = script.buf; *p; p++)
                if (skip_prefix(p, "'\\\\''", (const char **)&p2))
@@ -567,19 +570,12 @@ static char **read_author_script(void)
                        count++;
                }
 
-       env_size = (count + 1) * sizeof(*env);
-       strbuf_grow(&script, env_size);
-       memmove(script.buf + env_size, script.buf, script.len);
-       p = script.buf + env_size;
-       env = (char **)strbuf_detach(&script, NULL);
-
-       for (i = 0; i < count; i++) {
-               env[i] = p;
+       for (i = 0, p = script.buf; i < count; i++) {
+               argv_array_push(env, p);
                p += strlen(p) + 1;
        }
-       env[count] = NULL;
 
-       return env;
+       return 0;
 }
 
 static const char staged_changes_advice[] =
@@ -612,14 +608,18 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
                          int allow_empty, int edit, int amend,
                          int cleanup_commit_message)
 {
-       char **env = NULL;
-       struct argv_array array;
-       int rc;
+       struct child_process cmd = CHILD_PROCESS_INIT;
        const char *value;
 
+       cmd.git_cmd = 1;
+
        if (is_rebase_i(opts)) {
-               env = read_author_script();
-               if (!env) {
+               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);
 
                        return error(_(staged_changes_advice),
@@ -627,39 +627,47 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
                }
        }
 
-       argv_array_init(&array);
-       argv_array_push(&array, "commit");
-       argv_array_push(&array, "-n");
+       argv_array_push(&cmd.args, "commit");
+       argv_array_push(&cmd.args, "-n");
 
        if (amend)
-               argv_array_push(&array, "--amend");
+               argv_array_push(&cmd.args, "--amend");
        if (opts->gpg_sign)
-               argv_array_pushf(&array, "-S%s", opts->gpg_sign);
+               argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
        if (opts->signoff)
-               argv_array_push(&array, "-s");
+               argv_array_push(&cmd.args, "-s");
        if (defmsg)
-               argv_array_pushl(&array, "-F", defmsg, NULL);
+               argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
        if (cleanup_commit_message)
-               argv_array_push(&array, "--cleanup=strip");
+               argv_array_push(&cmd.args, "--cleanup=strip");
        if (edit)
-               argv_array_push(&array, "-e");
+               argv_array_push(&cmd.args, "-e");
        else if (!cleanup_commit_message &&
                 !opts->signoff && !opts->record_origin &&
                 git_config_get_value("commit.cleanup", &value))
-               argv_array_push(&array, "--cleanup=verbatim");
+               argv_array_push(&cmd.args, "--cleanup=verbatim");
 
        if (allow_empty)
-               argv_array_push(&array, "--allow-empty");
+               argv_array_push(&cmd.args, "--allow-empty");
 
        if (opts->allow_empty_message)
-               argv_array_push(&array, "--allow-empty-message");
+               argv_array_push(&cmd.args, "--allow-empty-message");
 
-       rc = run_command_v_opt_cd_env(array.argv, RUN_GIT_CMD, NULL,
-                       (const char *const *)env);
-       argv_array_clear(&array);
-       free(env);
+       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 rc;
+       return run_command(&cmd);
 }
 
 static int is_original_commit_empty(struct commit *commit)