From d2f75170a6c1548b85335c7e84a000ed67a0158b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 7 Sep 2013 21:25:17 +0000 Subject: implement environment variable expansion This will allow users to more-easily edit configs and feel like a real shell. We no longer mistakenly expand nil env variables to "" anymore, either. --- lib/dtas/process.rb | 28 ++++++++++++++++++++--- lib/dtas/source/sox.rb | 2 +- test/test_env.rb | 55 +++++++++++++++++++++++++++++++++++++++++++++ test/test_rg_integration.rb | 3 +-- 4 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 test/test_env.rb diff --git a/lib/dtas/process.rb b/lib/dtas/process.rb index b90b318..a3c1c04 100644 --- a/lib/dtas/process.rb +++ b/lib/dtas/process.rb @@ -19,12 +19,33 @@ module DTAS::Process # :nodoc: end while true end + # expand common shell constructs based on environment variables + # this is order-dependent, but Ruby 1.9+ hashes are already order-dependent + def env_expand(env, opts) + env = env.dup + if false == opts.delete(:expand) + env.each do |key, val| + Numeric === val and env[key] = val.to_s + 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 + end + end + end + end + # for long-running processes (sox/play/ecasound filters) def dtas_spawn(env, cmd, opts) opts = { close_others: true, pgroup: true }.merge!(opts) - - # stringify env, integer values are easier to type unquoted as strings - env.each { |k,v| env[k] = v.to_s } + env = env_expand(env, opts) pid = begin Process.spawn(env, cmd, opts) @@ -53,6 +74,7 @@ module DTAS::Process # :nodoc: re.binmode opts[:err] = we end + env = env_expand(env, opts) pid = begin Process.spawn(env, *cmd, opts) rescue Errno::EINTR # Ruby bug? diff --git a/lib/dtas/source/sox.rb b/lib/dtas/source/sox.rb index e26f54b..484a0ec 100644 --- a/lib/dtas/source/sox.rb +++ b/lib/dtas/source/sox.rb @@ -41,7 +41,7 @@ class DTAS::Source::Sox # :nodoc: def try(infile, offset = nil) err = "" cmd = %W(soxi -s #{infile}) - s = qx(@env, cmd, err_str: err, no_raise: true) + s = qx(@env.dup, cmd, err_str: err, no_raise: true) return if err =~ /soxi FAIL formats:/ self.class.try_to_fail_harder(infile, s, cmd) or return source_file_dup(infile, offset) diff --git a/test/test_env.rb b/test/test_env.rb new file mode 100644 index 0000000..92fc53c --- /dev/null +++ b/test/test_env.rb @@ -0,0 +1,55 @@ +# Copyright (C) 2013, Eric Wong and all contributors +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) +require_relative 'helper' +require 'dtas/process' +class TestEnv < Testcase + include DTAS::Process + def setup + @orig = ENV.to_hash + end + + def teardown + ENV.clear + ENV.update(@orig) + end + + def test_expand + ENV["HELLO"] = 'HIHI' + expect = { "BLAH" => "HIHI/WORLD" } + opts = {} + + env = { "BLAH" => "$HELLO/WORLD" } + assert_equal(expect, env_expand(env, opts)) + + env = { "BLAH" => "${HELLO}/WORLD" } + assert_equal(expect, env_expand(env, opts)) + + env = { "BLAH" => "$(echo $HELLO)/WORLD" } + assert_equal(expect, env_expand(env, opts)) + + env = { "BLAH" => "`echo $HELLO/WORLD`" } + assert_equal(expect, env_expand(env, opts)) + + env = { "BLAH" => "HIHI/WORLD" } + assert_equal(expect, env_expand(env, opts)) + + # disable expansion + env = expect = { "BLAH" => "`echo $HELLO/WORLD`" } + assert_equal(expect, env_expand(env, expand: false)) + + # numeric expansion always happens + env = { "BLAH" => 1 } + assert_equal({"BLAH"=>"1"}, env_expand(env, expand: false)) + env = { "BLAH" => 1 } + assert_equal({"BLAH"=>"1"}, env_expand(env, {})) + + expect = { "BLAH" => nil } + env = expect.dup + assert_equal expect, env_expand(env, expand:false) + assert_equal expect, env_expand(env, expand:true) + + # recursive expansion + res = env_expand({"PATH"=>"$PATH"}, expand: true) + assert_equal ENV["PATH"], res["PATH"] + end +end diff --git a/test/test_rg_integration.rb b/test/test_rg_integration.rb index d6a90b0..2779f86 100644 --- a/test/test_rg_integration.rb +++ b/test/test_rg_integration.rb @@ -40,7 +40,7 @@ class TestRgIntegration < Testcase end while cur["current_offset"] == 0 && sleep(0.01) end - assert_empty cur["current"]["env"]["RGFX"] + assert_nil cur["current"]["env"]["RGFX"] assert_equal DTAS::Format.new.rate * len, cur["current_expect"] @@ -119,7 +119,6 @@ class TestRgIntegration < Testcase "REPLAYGAIN_ALBUM_GAIN" => "-3.0", "REPLAYGAIN_TRACK_PEAK" => "0.666", "REPLAYGAIN_ALBUM_PEAK" => "0.999", - "REPLAYGAIN_REFERENCE_LOUDNESS" => nil } assert_equal expect, rg end -- cgit v1.2.3-24-ge0c7