On Wed, Dec 14, 2016 at 07:53:23AM -0500, Jeff King wrote:

> On Wed, Dec 14, 2016 at 09:34:20AM +0100, Johannes Sixt wrote:
> 
> > I wanted to see what it would look like if we make it the caller's
> > responsibility to throw away stderr. The patch is below, as fixup
> > of patch 29/34. The change is gross, but the end result is not that
> > bad, though not really a delightful read, either, mostly due to the
> > strange cleanup semantics of the start_command/finish_command combo,
> > so... I dunno.
> 
> I don't have a strong opinion on the patches under discussion, but here
> are a few pointers on the run-command interface:
> [...]

And here is a patch representing my suggestions, on top of yours. Not
tested beyond "make test".

I think read_author_script() could be simplified even more by appending
to the env array in the first loop, but I didn't want to refactor the
quote handling.

---
 sequencer.c | 65 +++++++++++------------------------
 1 file changed, 20 insertions(+), 45 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index f375880bd..27a9eaf15 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -591,18 +591,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 the author-script file into an environment block. Returns -1
+ * on error, 0 otherwise.
  */
-static char **read_author_script(void)
+static int read_author_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))
@@ -614,19 +613,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;
+               argv_array_push(env, p);
                p += strlen(p) + 1;
        }
-       env[count] = NULL;
 
-       return env;
+       return 0;
 }
 
 static const char staged_changes_advice[] =
@@ -659,20 +651,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;
-       int rc;
        const char *value;
-       struct strbuf errout = STRBUF_INIT;
        struct child_process cmd = CHILD_PROCESS_INIT;
 
        cmd.git_cmd = 1;
 
        if (is_rebase_i(opts)) {
-               if (!edit)
+               if (!edit) {
                        cmd.stdout_to_stderr = 1;
+                       cmd.err = -1;
+               }
 
-               env = read_author_script();
-               if (!env) {
+               if (read_author_script(&cmd.env_array)) {
                        const char *gpg_opt = gpg_sign_opt_quoted(opts);
 
                        return error(_(staged_changes_advice),
@@ -706,35 +696,20 @@ 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");
 
-       cmd.env = (const char *const *)env;
-
-       if (cmd.stdout_to_stderr) {
+       if (cmd.err == -1) {
                /* hide stderr on success */
-               cmd.err = -1;
-               rc = -1;
-               if (start_command(&cmd) < 0)
-                       goto cleanup;
-
-               if (strbuf_read(&errout, cmd.err, 0) < 0) {
-                       close(cmd.err);
-                       finish_command(&cmd); /* throw away exit code */
-                       goto cleanup;
-               }
-
-               close(cmd.err);
-               rc = finish_command(&cmd);
+               struct strbuf errout = STRBUF_INIT;
+               int rc = pipe_command(&cmd,
+                                     NULL, 0, /* stdin */
+                                     NULL, 0, /* stdout */
+                                     &errout, 0);
                if (rc)
                        fputs(errout.buf, stderr);
-       } else {
-               rc = run_command(&cmd);
+               strbuf_release(&errout);
+               return rc;
        }
 
-cleanup:
-       child_process_clear(&cmd);
-       strbuf_release(&errout);
-       free(env);
-
-       return rc;
+       return run_command(&cmd);
 }
 
 static int is_original_commit_empty(struct commit *commit)

Reply via email to