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)