sheller 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/sheller.rb +65 -0
- data/test/fixtures/cities.txt +4 -0
- data/test/fixtures/stderr_frog +3 -0
- data/test/fixtures/stdout_stderr_puma +4 -0
- data/test/fixtures/stdout_turtle +3 -0
- data/test/sheller_test.rb +92 -0
- data/test/test_helper.rb +6 -0
- metadata +11 -5
data/lib/sheller.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'POpen4'
|
2
|
+
|
3
|
+
module Sheller
|
4
|
+
VERSION = '0.0.3'
|
5
|
+
|
6
|
+
INESCAPABLE = {}
|
7
|
+
|
8
|
+
{
|
9
|
+
'STDOUT_TO_FILE' => :>,
|
10
|
+
'STDOUT_TO_PIPE' => :|,
|
11
|
+
'STDOUT_APPEND_TO_FILE' => :>>,
|
12
|
+
'STDOUT_TO_STDERR' => :'1>&2',
|
13
|
+
'STDERR_TO_FILE' => :'2>',
|
14
|
+
'STDERR_TO_STDOUT' => :'2>&1',
|
15
|
+
'STDERR_APPEND_TO_FILE' => :'2>>',
|
16
|
+
'STDOUT_AND_STDERR_TO_FILE' => :'&>',
|
17
|
+
'STDIN_FROM_FILE' => :<
|
18
|
+
}.each do |c, s|
|
19
|
+
const_set(c, s)
|
20
|
+
INESCAPABLE[s] = s.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
SHELL_SAFE = /\A[0-9A-Za-z+,.\/:=@_-]+\z/
|
24
|
+
ARG_SCAN = /('+)|[^']+/
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def command(*args)
|
28
|
+
args.map { |a| arg_to_cmd(a) }.join(' ')
|
29
|
+
end
|
30
|
+
|
31
|
+
def execute(*args)
|
32
|
+
stdout, stderr = nil
|
33
|
+
status = POpen4.popen4(command(*args)) do |_stdout, _stderr, _stdin, _pid|
|
34
|
+
stdout = _stdout.read
|
35
|
+
stderr = _stderr.read
|
36
|
+
end
|
37
|
+
ShellerResult.new(stdout, stderr, status)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def arg_to_cmd(arg)
|
42
|
+
if INESCAPABLE[arg]
|
43
|
+
arg.to_s
|
44
|
+
elsif arg.empty? || SHELL_SAFE =~ arg
|
45
|
+
"'%s'" % arg
|
46
|
+
else
|
47
|
+
result = ''
|
48
|
+
arg.scan(ARG_SCAN) do
|
49
|
+
result << ($1 ? "\\'" * $1.length : "'#{$&}'")
|
50
|
+
end
|
51
|
+
result
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class ShellerResult
|
57
|
+
attr_reader 'stdout', 'stderr', 'exit_status'
|
58
|
+
|
59
|
+
def initialize(stdout, stderr, exit_status)
|
60
|
+
@stdout = stdout
|
61
|
+
@stderr = stderr
|
62
|
+
@exit_status = exit_status
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class ShellerTest < Test::Unit::TestCase
|
4
|
+
TEST_DIR = File.expand_path(File.join(File.dirname(__FILE__)))
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@original_dir = Dir.pwd
|
8
|
+
Dir.chdir(TEST_DIR)
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
Dir.chdir(TEST_DIR) do
|
13
|
+
FileUtils.rm('output.txt', :force => true)
|
14
|
+
end
|
15
|
+
Dir.chdir(@original_dir)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_command_no_arguments
|
19
|
+
assert_equal "turtle\n", Sheller.execute('./fixtures/stdout_turtle').stdout
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_command_one_argument
|
23
|
+
assert_equal "frog\n", Sheller.execute('echo', 'frog').stdout
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_command_one_argument_with_quotes
|
27
|
+
assert_equal "\"toad\"\n", Sheller.execute('echo', '"toad"').stdout
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_command_one_argument_with_redirect
|
31
|
+
assert_equal "toad > newt\n", Sheller.execute('echo', 'toad > newt').stdout
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_echo_to_stderr
|
35
|
+
assert_equal "frog\n", Sheller.execute('./fixtures/stderr_frog').stderr
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_successful_exit_status_code
|
39
|
+
assert_equal 0, Sheller.execute('echo').exit_status
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_unsuccessful_exit_status_code
|
43
|
+
assert_not_equal 0, Sheller.execute('false').exit_status
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_stdout_to_file
|
47
|
+
result = Sheller.execute('./fixtures/stdout_stderr_puma', Sheller::STDOUT_TO_FILE, 'output.txt')
|
48
|
+
assert_equal "puma1\n", File.read('output.txt')
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_stdout_to_pipe
|
52
|
+
result = Sheller.execute('./fixtures/stdout_stderr_puma', Sheller::STDOUT_TO_PIPE, 'grep', 'puma')
|
53
|
+
assert_equal "puma1\n", result.stdout
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_stdout_append_to_file
|
57
|
+
File.open('output.txt', 'w') { |f| f.puts "jungle" }
|
58
|
+
Sheller.execute('./fixtures/stdout_stderr_puma', Sheller::STDOUT_APPEND_TO_FILE, 'output.txt')
|
59
|
+
assert_equal "jungle\npuma1\n", File.read('output.txt')
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_stdout_to_stderr
|
63
|
+
result = Sheller.execute('./fixtures/stdout_stderr_puma', Sheller::STDOUT_TO_STDERR)
|
64
|
+
assert_equal "puma2\npuma1\n", result.stderr
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_stderr_to_file
|
68
|
+
Sheller.execute('./fixtures/stdout_stderr_puma', Sheller::STDERR_TO_FILE, 'output.txt')
|
69
|
+
assert_equal "puma2\n", File.read('output.txt')
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_stderr_to_stdout
|
73
|
+
result = Sheller.execute('./fixtures/stdout_stderr_puma', Sheller::STDERR_TO_STDOUT)
|
74
|
+
assert_equal "puma2\npuma1\n", result.stdout
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_stderr_append_to_file
|
78
|
+
File.open('output.txt', 'w') { |f| f.puts "jungle" }
|
79
|
+
Sheller.execute('./fixtures/stdout_stderr_puma', Sheller::STDERR_APPEND_TO_FILE, 'output.txt')
|
80
|
+
assert_equal "jungle\npuma2\n", File.read('output.txt')
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_stdout_and_stderr_to_file
|
84
|
+
Sheller.execute('./fixtures/stdout_stderr_puma', Sheller::STDOUT_AND_STDERR_TO_FILE, 'output.txt')
|
85
|
+
assert_equal "puma2\npuma1\n", File.read('output.txt')
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_stdin_from_file
|
89
|
+
result = Sheller.execute('grep', 'Dublin', Sheller::STDIN_FROM_FILE, './fixtures/cities.txt')
|
90
|
+
assert_equal "Dublin\n", result.stdout
|
91
|
+
end
|
92
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sheller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Duncan Beevers
|
@@ -42,8 +42,14 @@ extensions: []
|
|
42
42
|
|
43
43
|
extra_rdoc_files: []
|
44
44
|
|
45
|
-
files:
|
46
|
-
|
45
|
+
files:
|
46
|
+
- lib/sheller.rb
|
47
|
+
- test/fixtures/cities.txt
|
48
|
+
- test/fixtures/stderr_frog
|
49
|
+
- test/fixtures/stdout_stderr_puma
|
50
|
+
- test/fixtures/stdout_turtle
|
51
|
+
- test/sheller_test.rb
|
52
|
+
- test/test_helper.rb
|
47
53
|
has_rdoc: true
|
48
54
|
homepage: http://github.com/duncanbeevers/sheller
|
49
55
|
licenses: []
|