Skip to content

Commit

Permalink
Add dir argument to setenv
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Keno committed Jan 27, 2014
1 parent c19a8e9 commit dee7f6c
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 19 deletions.
36 changes: 20 additions & 16 deletions base/process.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ type Cmd <: AbstractCmd
ignorestatus::Bool
detach::Bool
env::Union(Array{ByteString},Nothing)
Cmd(exec::Vector{ByteString}) = new(exec,false,false,nothing)
dir::UTF8String
Cmd(exec::Vector{ByteString}) = new(exec,false,false,nothing,"")
end

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

function show(io::IO, cmd::Cmd)
if isa(cmd.exec,Vector{ByteString})
esc = shell_escape(cmd)
print(io,'`')
for c in esc
if c == '`'
print(io,'\\')
end
print(io,c)
print_env = cmd.env !== nothing
print_dir = !isempty(cmd.dir)
(print_env || print_dir) && print(io,"setenv(")
esc = shell_escape(cmd)
print(io,'`')
for c in esc
if c == '`'
print(io,'\\')
end
print(io,'`')
else
print(io, cmd.exec)
print(io,c)
end
print(io,'`')
print_env && (print(io,","); show(io,cmd.env))
print_dir && (print(io,"; dir="); show(io,cmd.dir))
(print_dir || print_env) && print(io,")")
end

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

setenv{S<:ByteString}(cmd::Cmd, env::Array{S}) = (cmd.env = ByteString[x for x in env];cmd)
setenv(cmd::Cmd, env::Associative) = (cmd.env = ByteString[string(k)*"="*string(v) for (k,v) in env];cmd)
setenv{S<:ByteString}(cmd::Cmd, env::Array{S}; dir="") = (cmd.env = ByteString[x for x in env]; setenv(cmd,dir=dir); cmd)
setenv(cmd::Cmd, env::Associative; dir="") = (cmd.env = ByteString[string(k)*"="*string(v) for (k,v) in env]; setenv(cmd,dir=dir); cmd)
setenv(cmd::Cmd; dir="") = (cmd.dir = dir; cmd)

(&)(left::AbstractCmd,right::AbstractCmd) = AndCmds(left,right)
(|>)(src::AbstractCmd,dest::AbstractCmd) = OrCmds(src,dest)
Expand Down Expand Up @@ -196,10 +200,10 @@ function _jl_spawn(cmd::Ptr{Uint8}, argv::Ptr{Ptr{Uint8}}, loop::Ptr{Void}, pp::
error = ccall(:jl_spawn, Int32,
(Ptr{Uint8}, Ptr{Ptr{Uint8}}, Ptr{Void}, Ptr{Void}, Any, Int32,
Ptr{Void}, Int32, Ptr{Void}, Int32, Ptr{Void},
Int32, Ptr{Ptr{Uint8}}),
Int32, Ptr{Ptr{Uint8}}, Ptr{Uint8}),
cmd, argv, loop, proc, pp, uvtype(in),
uvhandle(in), uvtype(out), uvhandle(out), uvtype(err), uvhandle(err),
pp.cmd.detach, pp.cmd.env === nothing ? C_NULL : pp.cmd.env)
pp.cmd.detach, pp.cmd.env === nothing ? C_NULL : pp.cmd.env, isempty(pp.cmd.dir) ? C_NULL : pp.cmd.dir)
if error != 0
c_free(proc)
throw(UVError("spawn",error))
Expand Down
4 changes: 2 additions & 2 deletions src/jl_uv.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
uv_handle_type stdin_type, uv_pipe_t *stdin_pipe,
uv_handle_type stdout_type, uv_pipe_t *stdout_pipe,
uv_handle_type stderr_type, uv_pipe_t *stderr_pipe,
int detach, char **env)
int detach, char **env, char *cwd)
{
uv_process_options_t opts;
uv_stdio_container_t stdio[3];
Expand All @@ -342,7 +342,7 @@ DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
#else
opts.flags = UV_PROCESS_RESET_SIGPIPE;
#endif
opts.cwd = NULL;
opts.cwd = cwd;
opts.args = argv;
if (detach)
opts.flags |= UV_PROCESS_DETACHED;
Expand Down
2 changes: 1 addition & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
uv_handle_type stdin_type,uv_pipe_t *stdin_pipe,
uv_handle_type stdout_type,uv_pipe_t *stdout_pipe,
uv_handle_type stderr_type,uv_pipe_t *stderr_pipe,
int detach, char **env);
int detach, char **env, char *cwd);
DLLEXPORT void jl_run_event_loop(uv_loop_t *loop);
DLLEXPORT int jl_run_once(uv_loop_t *loop);
DLLEXPORT int jl_process_events(uv_loop_t *loop);
Expand Down
1 change: 1 addition & 0 deletions test/spawn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ end

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

This comment has been minimized.

Copy link
@tkelman

tkelman Jun 24, 2014

Contributor

Anybody notice that these tests don't @test? And interestingly the left hand side of this third one returns "/c\n" on Windows right now, replacing c with whatever drive letter you happen to be in.

This comment has been minimized.

Copy link
@Keno

Keno Jun 24, 2014

Author Member

That's a good catch. Definitely an oversight.


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

3 comments on commit dee7f6c

@vtjnash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@JeffBezanson
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should add a NEWS entry for this.

@StefanKarpinski
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

goodnewseveryone

Please sign in to comment.