Skip to content

Commit f944434

Browse files
committed
Implement #24353 - Propegate cmd flags in interpolation
Too late for 1.2 for which this was originally marked, but nevertheless, it's a quick change, so might as well get it in now and have it be available in 1.3. Fixes #24353
1 parent 4dd91fa commit f944434

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

NEWS.md

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ New library functions
2424
Standard library changes
2525
------------------------
2626

27+
* Cmd interpolation (``` `$(x::Cmd) a b c` ``` where) now propagates `x`'s process flags (environment, flags, working directory, etc) if `x` is the first interpolant and errors otherwise ([#24353]).
28+
2729
#### LinearAlgebra
2830

2931

base/process.jl

+25-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ struct Cmd <: AbstractCmd
3030
end
3131
end
3232

33+
has_nondefault_cmd_flags(c::Cmd) =
34+
c.ignorestatus ||
35+
c.flags != 0x00 ||
36+
c.env !== nothing ||
37+
c.dir !== ""
38+
3339
"""
3440
Cmd(cmd::Cmd; ignorestatus, detach, windows_verbatim, windows_hide, env, dir)
3541
@@ -901,7 +907,12 @@ end
901907

902908
arg_gen() = String[]
903909
arg_gen(x::AbstractString) = String[cstr(x)]
904-
arg_gen(cmd::Cmd) = cmd.exec
910+
function arg_gen(cmd::Cmd)
911+
if has_nondefault_cmd_flags(cmd)
912+
throw(ArgumentError("Non-default environment behavior is only permitted for the first interpolant."))
913+
end
914+
cmd.exec
915+
end
905916

906917
function arg_gen(head)
907918
if isiterable(typeof(head))
@@ -927,10 +938,20 @@ end
927938

928939
function cmd_gen(parsed)
929940
args = String[]
930-
for arg in parsed
931-
append!(args, arg_gen(arg...))
941+
if length(parsed) >= 1 && isa(parsed[1], Tuple{Cmd})
942+
cmd = parsed[1][1]
943+
(ignorestatus, flags, env, dir) = (cmd.ignorestatus, cmd.flags, cmd.env, cmd.dir)
944+
append!(args, cmd.exec)
945+
for arg in tail(parsed)
946+
append!(args, arg_gen(arg...))
947+
end
948+
return Cmd(Cmd(args), ignorestatus, flags, env, dir)
949+
else
950+
for arg in parsed
951+
append!(args, arg_gen(arg...))
952+
end
953+
return Cmd(args)
932954
end
933-
return Cmd(args)
934955
end
935956

936957
"""

test/spawn.jl

+9
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,15 @@ end
456456
@test Set([``, echocmd]) != Set([``, ``])
457457
@test Set([echocmd, ``, ``, echocmd]) == Set([echocmd, ``])
458458

459+
# test for interpolation of Cmd
460+
let c = setenv(`x`, "A"=>true)
461+
@test (`$c a`).env == String["A=true"]
462+
@test (`"$c" a`).env == String["A=true"]
463+
@test_throws ArgumentError `a $c`
464+
@test (`$(c.exec) a`).env === nothing
465+
@test_throws ArgumentError `"$c "`
466+
end
467+
459468
# equality tests for AndCmds
460469
@test Base.AndCmds(`$echocmd abc`, `$echocmd def`) == Base.AndCmds(`$echocmd abc`, `$echocmd def`)
461470
@test Base.AndCmds(`$echocmd abc`, `$echocmd def`) != Base.AndCmds(`$echocmd abc`, `$echocmd xyz`)

0 commit comments

Comments
 (0)