Discussion:
[PATCH] process: implement array expansion to preserve spaces
Eric Wong
2015-05-18 00:21:15 UTC
Permalink
This can make it easier to specify mcompand parameters in
socks, as those require separate levels of parameter parsing
and require quoting in shell.
---
lib/dtas/process.rb | 39 +++++++++++++++++++++++++++++++--------
test/test_env.rb | 16 ++++++++++++++++
2 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/lib/dtas/process.rb b/lib/dtas/process.rb
index 8c5e8e9..f5f9a9e 100644
--- a/lib/dtas/process.rb
+++ b/lib/dtas/process.rb
@@ -1,6 +1,7 @@
# Copyright (C) 2013-2015 all contributors <dtas-***@nongnu.org>
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
require 'io/wait'
+require 'shellwords'
require_relative '../dtas'
require_relative 'xs'

@@ -23,6 +24,7 @@ module DTAS::Process # :nodoc:

# expand common shell constructs based on environment variables
# this is order-dependent, but Ruby 1.9+ hashes are already order-dependent
+ # This recurses
def env_expand(env, opts)
env = env.dup
if false == opts.delete(:expand)
@@ -31,19 +33,40 @@ module DTAS::Process # :nodoc:
end
else
env.each do |key, val|
- case val
- when Numeric # stringify numeric values to simplify users' lives
- env[key] = val.to_s
- when /[\`\$]/ # perform variable/command expansion
- tmp = env.dup
- tmp.delete(key)
- val = qx(tmp, "echo #{val}", expand: false)
- env[key] = val.chomp
+ case val = env_expand_i(env, key, val)
+ when Array
+ val.flatten!
+ env[key] = Shellwords.join(val)
end
end
end
end

+ def env_expand_i(env, key, val)
+ case val
+ when Numeric # stringify numeric values to simplify users' lives
+ env[key] = val.to_s
+ when /[\`\$]/ # perform variable/command expansion
+ tmp = env.dup
+ tmp.delete(key)
+ tmp.each do |k,v|
+ # best effort, this can get wonky
+ tmp[k] = Shellwords.join(v.flatten) if Array === v
+ end
+ val = qx(tmp, "echo #{val}", expand: false)
+ env[key] = val.chomp
+ when Array
+ env[key] = env_expand_ary(env, key, val)
+ else
+ val
+ end
+ end
+
+ # warning, recursion:
+ def env_expand_ary(env, key, val)
+ val.map { |v| env_expand_i(env.dup, key, v) }
+ end
+
# for long-running processes (sox/play/ecasound filters)
def dtas_spawn(env, cmd, opts)
opts = { close_others: true, pgroup: true }.merge!(opts)
diff --git a/test/test_env.rb b/test/test_env.rb
index bd7961d..6b36f32 100644
--- a/test/test_env.rb
+++ b/test/test_env.rb
@@ -52,4 +52,20 @@ class TestEnv < Testcase
res = env_expand({"PATH"=>"$PATH"}, expand: true)
assert_equal ENV["PATH"], res["PATH"]
end
+
+ def test_ary
+ ENV['HELLO'] = 'HIHI'
+ ENV['PAATH'] = '/usr/local/bin:/usr/bin:/bin'
+ env = { 'BLAH' => [ '$HELLO/WORLD', '$PAATH', '$(echo hello world)' ] }
+ res = env_expand(env, expand: true)
+ exp = [ "HIHI/WORLD", ENV['PAATH'], 'hello world' ]
+ assert_equal exp, Shellwords.split(res['BLAH'])
+ env = {
+ 'BLAH' => [ '$(echo hello world)' ],
+ 'MOAR' => [ '$BLAH', 'OMG HALP SPACES' ]
+ }
+ res = env_expand(env, expand: true)
+ exp = ["hello\\ world", "OMG HALP SPACES"]
+ assert_equal exp, Shellwords.split(res['MOAR'])
+ end
end
--
EW
Loading...