Skip to content

Commit dee7f6c

Browse files
committed
Add dir argument to setenv
Allows setting the directory in which the child process is supposed to execute. Also changes the printing for `Cmd`s to distinguish those with modified env or dir fields. This was long overdue.
1 parent c19a8e9 commit dee7f6c

File tree

4 files changed

+24
-19
lines changed

4 files changed

+24
-19
lines changed

base/process.jl

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ type Cmd <: AbstractCmd
55
ignorestatus::Bool
66
detach::Bool
77
env::Union(Array{ByteString},Nothing)
8-
Cmd(exec::Vector{ByteString}) = new(exec,false,false,nothing)
8+
dir::UTF8String
9+
Cmd(exec::Vector{ByteString}) = new(exec,false,false,nothing,"")
910
end
1011

1112
type OrCmds <: AbstractCmd
@@ -29,19 +30,21 @@ end
2930
shell_escape(cmd::Cmd) = shell_escape(cmd.exec...)
3031

3132
function show(io::IO, cmd::Cmd)
32-
if isa(cmd.exec,Vector{ByteString})
33-
esc = shell_escape(cmd)
34-
print(io,'`')
35-
for c in esc
36-
if c == '`'
37-
print(io,'\\')
38-
end
39-
print(io,c)
33+
print_env = cmd.env !== nothing
34+
print_dir = !isempty(cmd.dir)
35+
(print_env || print_dir) && print(io,"setenv(")
36+
esc = shell_escape(cmd)
37+
print(io,'`')
38+
for c in esc
39+
if c == '`'
40+
print(io,'\\')
4041
end
41-
print(io,'`')
42-
else
43-
print(io, cmd.exec)
42+
print(io,c)
4443
end
44+
print(io,'`')
45+
print_env && (print(io,","); show(io,cmd.env))
46+
print_dir && (print(io,"; dir="); show(io,cmd.dir))
47+
(print_dir || print_env) && print(io,")")
4548
end
4649

4750
function show(io::IO, cmds::OrCmds)
@@ -132,8 +135,9 @@ ignorestatus(cmd::Cmd) = (cmd.ignorestatus=true; cmd)
132135
ignorestatus(cmd::Union(OrCmds,AndCmds)) = (ignorestatus(cmd.a); ignorestatus(cmd.b); cmd)
133136
detach(cmd::Cmd) = (cmd.detach=true; cmd)
134137

135-
setenv{S<:ByteString}(cmd::Cmd, env::Array{S}) = (cmd.env = ByteString[x for x in env];cmd)
136-
setenv(cmd::Cmd, env::Associative) = (cmd.env = ByteString[string(k)*"="*string(v) for (k,v) in env];cmd)
138+
setenv{S<:ByteString}(cmd::Cmd, env::Array{S}; dir="") = (cmd.env = ByteString[x for x in env]; setenv(cmd,dir=dir); cmd)
139+
setenv(cmd::Cmd, env::Associative; dir="") = (cmd.env = ByteString[string(k)*"="*string(v) for (k,v) in env]; setenv(cmd,dir=dir); cmd)
140+
setenv(cmd::Cmd; dir="") = (cmd.dir = dir; cmd)
137141

138142
(&)(left::AbstractCmd,right::AbstractCmd) = AndCmds(left,right)
139143
(|>)(src::AbstractCmd,dest::AbstractCmd) = OrCmds(src,dest)
@@ -196,10 +200,10 @@ function _jl_spawn(cmd::Ptr{Uint8}, argv::Ptr{Ptr{Uint8}}, loop::Ptr{Void}, pp::
196200
error = ccall(:jl_spawn, Int32,
197201
(Ptr{Uint8}, Ptr{Ptr{Uint8}}, Ptr{Void}, Ptr{Void}, Any, Int32,
198202
Ptr{Void}, Int32, Ptr{Void}, Int32, Ptr{Void},
199-
Int32, Ptr{Ptr{Uint8}}),
203+
Int32, Ptr{Ptr{Uint8}}, Ptr{Uint8}),
200204
cmd, argv, loop, proc, pp, uvtype(in),
201205
uvhandle(in), uvtype(out), uvhandle(out), uvtype(err), uvhandle(err),
202-
pp.cmd.detach, pp.cmd.env === nothing ? C_NULL : pp.cmd.env)
206+
pp.cmd.detach, pp.cmd.env === nothing ? C_NULL : pp.cmd.env, isempty(pp.cmd.dir) ? C_NULL : pp.cmd.dir)
203207
if error != 0
204208
c_free(proc)
205209
throw(UVError("spawn",error))

src/jl_uv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
330330
uv_handle_type stdin_type, uv_pipe_t *stdin_pipe,
331331
uv_handle_type stdout_type, uv_pipe_t *stdout_pipe,
332332
uv_handle_type stderr_type, uv_pipe_t *stderr_pipe,
333-
int detach, char **env)
333+
int detach, char **env, char *cwd)
334334
{
335335
uv_process_options_t opts;
336336
uv_stdio_container_t stdio[3];
@@ -342,7 +342,7 @@ DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
342342
#else
343343
opts.flags = UV_PROCESS_RESET_SIGPIPE;
344344
#endif
345-
opts.cwd = NULL;
345+
opts.cwd = cwd;
346346
opts.args = argv;
347347
if (detach)
348348
opts.flags |= UV_PROCESS_DETACHED;

src/julia.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
836836
uv_handle_type stdin_type,uv_pipe_t *stdin_pipe,
837837
uv_handle_type stdout_type,uv_pipe_t *stdout_pipe,
838838
uv_handle_type stderr_type,uv_pipe_t *stderr_pipe,
839-
int detach, char **env);
839+
int detach, char **env, char *cwd);
840840
DLLEXPORT void jl_run_event_loop(uv_loop_t *loop);
841841
DLLEXPORT int jl_run_once(uv_loop_t *loop);
842842
DLLEXPORT int jl_process_events(uv_loop_t *loop);

test/spawn.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ end
8383

8484
readall(setenv(`sh -c "echo \$TEST"`,["TEST=Hello World"])) == "Hello World\n"
8585
readall(setenv(`sh -c "echo \$TEST"`,["TEST"=>"Hello World"])) == "Hello World\n"
86+
readall(setenv(`sh -c "pwd"`;dir="/")) == readall(setenv(`sh -c "cd / && pwd"`))
8687

8788
# Here we test that if we close a stream with pending writes, we don't lose the writes.
8889
str = ""

0 commit comments

Comments
 (0)