Skip to content

Commit 217610d

Browse files
committed
Merge branch 'rs/run-command-env-array'
Add managed "env" array to child_process to clarify the lifetime rules. * rs/run-command-env-array: use env_array member of struct child_process run-command: add env_array, an optional argv_array for env
2 parents f35a02b + a915459 commit 217610d

File tree

8 files changed

+38
-39
lines changed

8 files changed

+38
-39
lines changed

Documentation/technical/api-run-command.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ string pointers (NULL terminated) in .env:
169169
. If the string does not contain '=', it names an environment
170170
variable that will be removed from the child process's environment.
171171

172+
If the .env member is NULL, `start_command` will point it at the
173+
.env_array `argv_array` (so you may use one or the other, but not both).
174+
The memory in .env_array will be cleaned up automatically during
175+
`finish_command` (or during `start_command` when it is unsuccessful).
176+
172177
To specify a new initial working directory for the sub-process,
173178
specify it in the .dir member.
174179

builtin/receive-pack.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,6 @@ static const char *check_nonce(const char *buf, size_t len)
453453
static void prepare_push_cert_sha1(struct child_process *proc)
454454
{
455455
static int already_done;
456-
struct argv_array env = ARGV_ARRAY_INIT;
457456

458457
if (!push_cert.len)
459458
return;
@@ -487,20 +486,26 @@ static void prepare_push_cert_sha1(struct child_process *proc)
487486
nonce_status = check_nonce(push_cert.buf, bogs);
488487
}
489488
if (!is_null_sha1(push_cert_sha1)) {
490-
argv_array_pushf(&env, "GIT_PUSH_CERT=%s", sha1_to_hex(push_cert_sha1));
491-
argv_array_pushf(&env, "GIT_PUSH_CERT_SIGNER=%s",
489+
argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT=%s",
490+
sha1_to_hex(push_cert_sha1));
491+
argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_SIGNER=%s",
492492
sigcheck.signer ? sigcheck.signer : "");
493-
argv_array_pushf(&env, "GIT_PUSH_CERT_KEY=%s",
493+
argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_KEY=%s",
494494
sigcheck.key ? sigcheck.key : "");
495-
argv_array_pushf(&env, "GIT_PUSH_CERT_STATUS=%c", sigcheck.result);
495+
argv_array_pushf(&proc->env_array, "GIT_PUSH_CERT_STATUS=%c",
496+
sigcheck.result);
496497
if (push_cert_nonce) {
497-
argv_array_pushf(&env, "GIT_PUSH_CERT_NONCE=%s", push_cert_nonce);
498-
argv_array_pushf(&env, "GIT_PUSH_CERT_NONCE_STATUS=%s", nonce_status);
498+
argv_array_pushf(&proc->env_array,
499+
"GIT_PUSH_CERT_NONCE=%s",
500+
push_cert_nonce);
501+
argv_array_pushf(&proc->env_array,
502+
"GIT_PUSH_CERT_NONCE_STATUS=%s",
503+
nonce_status);
499504
if (nonce_status == NONCE_SLOP)
500-
argv_array_pushf(&env, "GIT_PUSH_CERT_NONCE_SLOP=%ld",
505+
argv_array_pushf(&proc->env_array,
506+
"GIT_PUSH_CERT_NONCE_SLOP=%ld",
501507
nonce_stamp_slop);
502508
}
503-
proc->env = env.argv;
504509
}
505510
}
506511

http-backend.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,6 @@ static void run_service(const char **argv)
314314
const char *encoding = getenv("HTTP_CONTENT_ENCODING");
315315
const char *user = getenv("REMOTE_USER");
316316
const char *host = getenv("REMOTE_ADDR");
317-
struct argv_array env = ARGV_ARRAY_INIT;
318317
int gzipped_request = 0;
319318
struct child_process cld = CHILD_PROCESS_INIT;
320319

@@ -329,13 +328,12 @@ static void run_service(const char **argv)
329328
host = "(none)";
330329

331330
if (!getenv("GIT_COMMITTER_NAME"))
332-
argv_array_pushf(&env, "GIT_COMMITTER_NAME=%s", user);
331+
argv_array_pushf(&cld.env_array, "GIT_COMMITTER_NAME=%s", user);
333332
if (!getenv("GIT_COMMITTER_EMAIL"))
334-
argv_array_pushf(&env, "GIT_COMMITTER_EMAIL=%s@http.%s",
335-
user, host);
333+
argv_array_pushf(&cld.env_array,
334+
"GIT_COMMITTER_EMAIL=%s@http.%s", user, host);
336335

337336
cld.argv = argv;
338-
cld.env = env.argv;
339337
if (gzipped_request)
340338
cld.in = -1;
341339
cld.git_cmd = 1;
@@ -350,7 +348,6 @@ static void run_service(const char **argv)
350348

351349
if (finish_command(&cld))
352350
exit(1);
353-
argv_array_clear(&env);
354351
}
355352

356353
static int show_text_ref(const char *name, const unsigned char *sha1,

pager.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,10 @@ void setup_pager(void)
7474
pager_process.use_shell = 1;
7575
pager_process.argv = pager_argv;
7676
pager_process.in = -1;
77-
if (!getenv("LESS") || !getenv("LV")) {
78-
static const char *env[3];
79-
int i = 0;
80-
81-
if (!getenv("LESS"))
82-
env[i++] = "LESS=FRX";
83-
if (!getenv("LV"))
84-
env[i++] = "LV=-c";
85-
env[i] = NULL;
86-
pager_process.env = env;
87-
}
77+
if (!getenv("LESS"))
78+
argv_array_push(&pager_process.env_array, "LESS=FRX");
79+
if (!getenv("LV"))
80+
argv_array_push(&pager_process.env_array, "LV=-c");
8881
if (start_command(&pager_process))
8982
return;
9083

run-command.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ void child_process_init(struct child_process *child)
1212
{
1313
memset(child, 0, sizeof(*child));
1414
argv_array_init(&child->args);
15+
argv_array_init(&child->env_array);
1516
}
1617

1718
struct child_to_clean {
@@ -287,6 +288,8 @@ int start_command(struct child_process *cmd)
287288

288289
if (!cmd->argv)
289290
cmd->argv = cmd->args.argv;
291+
if (!cmd->env)
292+
cmd->env = cmd->env_array.argv;
290293

291294
/*
292295
* In case of errors we must keep the promise to close FDs
@@ -338,6 +341,7 @@ int start_command(struct child_process *cmd)
338341
error("cannot create %s pipe for %s: %s",
339342
str, cmd->argv[0], strerror(failed_errno));
340343
argv_array_clear(&cmd->args);
344+
argv_array_clear(&cmd->env_array);
341345
errno = failed_errno;
342346
return -1;
343347
}
@@ -524,6 +528,7 @@ int start_command(struct child_process *cmd)
524528
else if (cmd->err)
525529
close(cmd->err);
526530
argv_array_clear(&cmd->args);
531+
argv_array_clear(&cmd->env_array);
527532
errno = failed_errno;
528533
return -1;
529534
}
@@ -550,6 +555,7 @@ int finish_command(struct child_process *cmd)
550555
{
551556
int ret = wait_or_whine(cmd->pid, cmd->argv[0]);
552557
argv_array_clear(&cmd->args);
558+
argv_array_clear(&cmd->env_array);
553559
return ret;
554560
}
555561

run-command.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
struct child_process {
1111
const char **argv;
1212
struct argv_array args;
13+
struct argv_array env_array;
1314
pid_t pid;
1415
/*
1516
* Using .in, .out, .err:
@@ -44,7 +45,7 @@ struct child_process {
4445
unsigned clean_on_exit:1;
4546
};
4647

47-
#define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT }
48+
#define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
4849
void child_process_init(struct child_process *);
4950

5051
int start_command(struct child_process *);

transport-helper.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,6 @@ static struct child_process *get_helper(struct transport *transport)
108108
int refspec_alloc = 0;
109109
int duped;
110110
int code;
111-
char git_dir_buf[sizeof(GIT_DIR_ENVIRONMENT) + PATH_MAX + 1];
112-
const char *helper_env[] = {
113-
git_dir_buf,
114-
NULL
115-
};
116-
117111

118112
if (data->helper)
119113
return data->helper;
@@ -129,8 +123,8 @@ static struct child_process *get_helper(struct transport *transport)
129123
helper->git_cmd = 0;
130124
helper->silent_exec_failure = 1;
131125

132-
snprintf(git_dir_buf, sizeof(git_dir_buf), "%s=%s", GIT_DIR_ENVIRONMENT, get_git_dir());
133-
helper->env = helper_env;
126+
argv_array_pushf(&helper->env_array, "%s=%s", GIT_DIR_ENVIRONMENT,
127+
get_git_dir());
134128

135129
code = start_command(helper);
136130
if (code < 0 && errno == ENOENT)

wt-status.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -726,14 +726,14 @@ static void wt_status_print_changed(struct wt_status *s)
726726
static void wt_status_print_submodule_summary(struct wt_status *s, int uncommitted)
727727
{
728728
struct child_process sm_summary = CHILD_PROCESS_INIT;
729-
struct argv_array env = ARGV_ARRAY_INIT;
730729
struct argv_array argv = ARGV_ARRAY_INIT;
731730
struct strbuf cmd_stdout = STRBUF_INIT;
732731
struct strbuf summary = STRBUF_INIT;
733732
char *summary_content;
734733
size_t len;
735734

736-
argv_array_pushf(&env, "GIT_INDEX_FILE=%s", s->index_file);
735+
argv_array_pushf(&sm_summary.env_array, "GIT_INDEX_FILE=%s",
736+
s->index_file);
737737

738738
argv_array_push(&argv, "submodule");
739739
argv_array_push(&argv, "summary");
@@ -745,14 +745,12 @@ static void wt_status_print_submodule_summary(struct wt_status *s, int uncommitt
745745
argv_array_push(&argv, s->amend ? "HEAD^" : "HEAD");
746746

747747
sm_summary.argv = argv.argv;
748-
sm_summary.env = env.argv;
749748
sm_summary.git_cmd = 1;
750749
sm_summary.no_stdin = 1;
751750
fflush(s->fp);
752751
sm_summary.out = -1;
753752

754753
run_command(&sm_summary);
755-
argv_array_clear(&env);
756754
argv_array_clear(&argv);
757755

758756
len = strbuf_read(&cmd_stdout, sm_summary.out, 1024);

0 commit comments

Comments
 (0)