sfl 1.2 → 2.0

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.
Files changed (7) hide show
  1. data/CHANGELOG.md +41 -0
  2. data/README.md +1 -0
  3. data/Rakefile +16 -0
  4. data/lib/sfl.rb +56 -29
  5. data/sfl.gemspec +28 -0
  6. data/spec/sfl_spec.rb +177 -0
  7. metadata +36 -8
@@ -0,0 +1,41 @@
1
+ # 2.0
2
+
3
+ Version 2.0 is done completely by Bernard Lambeau. Thanks!
4
+
5
+ * Enhancements
6
+
7
+ * Implemented :in redirection, i.e. spawn("...", :in => ...)
8
+ * Implemented :close redirection, i.e. spawn("...", :out/err/in => :close)
9
+ * Removed spawn override if ruby version is >= 1.9
10
+ * Project structure enhanced with Rakefile and SFL::VERSION
11
+ * Spec suite runs against Kernel.spawn to ensure comptability with native spawn in 1.9
12
+
13
+ * Bugfixes
14
+
15
+ * Fix the spec suite for ruby version 1.9.2
16
+
17
+ * Known bugs
18
+
19
+ * The spec suite may fail under ruby 1.9.1, due to ruby bugs on some spawn redirect options
20
+
21
+ # 1.2
22
+
23
+ * Enhancements
24
+
25
+ * Added support for quoted command arguments and spaces
26
+ * Defined spawn even if the ruby version is 1.9
27
+
28
+ # 1.1
29
+
30
+ * Enhancements
31
+
32
+ * Added Process.spawn in addition to Kernel.spawn
33
+ * Added support for Ruby 1.8.6
34
+
35
+ # 1.0
36
+
37
+ * Enhancements
38
+
39
+ * Birthday
40
+
41
+
data/README.md CHANGED
@@ -32,6 +32,7 @@ If your ruby is 1.9, `require 'sfl'` doesn't do anything. If your ruby is 1.8, t
32
32
 
33
33
  ## Supports
34
34
 
35
+ * (On MacOS) MRI 1.8.6, 1.8.7, 1.9.1, 1.9.2-rc2
35
36
  * (On UNIX) MRI 1.8.6, 1.8.7, 1.9.1, 1.9.2pre
36
37
  * (On Windows) MRI 1.9.1, 1.9.2pre
37
38
 
@@ -0,0 +1,16 @@
1
+ require "rspec/core/rake_task"
2
+ require "rake/gempackagetask"
3
+
4
+ task :default => :spec
5
+
6
+ desc "Run all examples"
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.rspec_opts = %w[--color]
9
+ t.verbose = false
10
+ end
11
+
12
+ desc "Create the .gem package"
13
+ $gemspec = eval("#{File.read('sfl.gemspec')}")
14
+ Rake::GemPackageTask.new($gemspec) do |pkg|
15
+ pkg.need_tar = true
16
+ end
data/lib/sfl.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  class SFL
2
+ VERSION = "2.0".freeze
3
+
2
4
  attr_reader :command, :environment, :argument, :option
3
5
 
4
6
  # SFL.new('ls', '-a') becomes
@@ -63,39 +65,62 @@ class SFL
63
65
  end
64
66
 
65
67
  class << self
68
+ REDIRECTION_MAPPING = {
69
+ :in => STDIN,
70
+ :out => STDOUT,
71
+ :err => STDERR,
72
+ }
73
+
74
+ def redirection_ast(v, what_for = :out)
75
+ case v
76
+ when Integer
77
+ raise NotImplementedError, "Redirection to integer FD not yet implemented"
78
+ when :close
79
+ nil
80
+ when :in, :out, :err
81
+ REDIRECTION_MAPPING[v]
82
+ when String # filename
83
+ [File, :open, v, (what_for == :in ? 'r' : 'w')]
84
+ when Array # filename with option
85
+ [File, :open, v[0], v[1]]
86
+ when IO
87
+ v
88
+ end
89
+ end
90
+
66
91
  def option_parser(hash)
67
- mapping = {
68
- :out => STDOUT,
69
- :err => STDERR,
70
- }
71
92
  result = []
93
+
94
+ # changing dir has high priority
72
95
  chdir = hash.delete(:chdir)
73
96
  if chdir
74
97
  result[0] = [Dir, :chdir, chdir]
75
98
  end
99
+
100
+ # other options
76
101
  result += hash.map {|k, v|
77
- right =
78
- case v
79
- when Symbol # :out or :err
80
- mapping[v]
81
- when String # filename
82
- [File, :open, v, 'w']
83
- when Array # filename with option
84
- [File, :open, v[0], v[1]]
85
- when IO
86
- v
102
+ case k
103
+ when :in, :out, :err
104
+ if right = redirection_ast(v, k)
105
+ [[REDIRECTION_MAPPING[k], :reopen, right]]
106
+ else
107
+ [[REDIRECTION_MAPPING[k], :close]]
87
108
  end
88
-
89
- if Symbol === k
90
- [[mapping[k], :reopen, right]]
91
- else
109
+ when Array
92
110
  # assuming k is like [:out, :err]
93
- raise if k.size > 2
94
- left1, left2 = *k.map {|i| mapping[i] }
95
- [
96
- [left1, :reopen, right],
97
- [left2, :reopen, left1],
98
- ]
111
+ raise NotImplementedError if k.size > 2
112
+ left1, left2 = *k.map {|i| REDIRECTION_MAPPING[i] }
113
+ if right = redirection_ast(v)
114
+ [
115
+ [left1, :reopen, right],
116
+ [left2, :reopen, left1],
117
+ ]
118
+ else
119
+ [
120
+ [left1, :close],
121
+ [left2, :close],
122
+ ]
123
+ end
99
124
  end
100
125
  }.flatten(1)
101
126
  result
@@ -149,12 +174,14 @@ class SFL
149
174
  end
150
175
  end
151
176
 
152
- def spawn(*x)
153
- SFL.new(*x).run
154
- end
177
+ if RUBY_VERSION <= "1.9"
178
+ def Kernel.spawn(*x)
179
+ SFL.new(*x).run
180
+ end
155
181
 
156
- def Process.spawn(*x)
157
- SFL.new(*x).run
182
+ def Process.spawn(*x)
183
+ SFL.new(*x).run
184
+ end
158
185
  end
159
186
 
160
187
  if RUBY_VERSION <= '1.8.6'
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../lib/sfl', __FILE__)
2
+ Gem::Specification.new do |s|
3
+ s.name = %q{sfl}
4
+ s.version = SFL::VERSION.dup
5
+ s.date = Time.now.strftime('%Y-%m-%d')
6
+
7
+ s.summary = %q{Spawn For Ruby 1.8}
8
+ s.description = %q{Spawn For Ruby 1.8}
9
+
10
+ s.author = 'ujihisa'
11
+ s.email = %q{ujihisa at gmail.com}
12
+
13
+ s.files =
14
+ Dir['lib/**/*'] +
15
+ Dir['spec/**/*'] +
16
+ %w{ sfl.gemspec Rakefile README.md CHANGELOG.md }
17
+
18
+ s.require_paths = ["lib"]
19
+ s.executables = []
20
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
21
+
22
+ s.homepage = %q{https://github.com/ujihisa/spawn-for-legacy}
23
+
24
+ s.extra_rdoc_files = %w< README.md >
25
+
26
+ s.add_development_dependency('rake')
27
+ s.add_development_dependency('rspec', ">= 2.4.0")
28
+ end
@@ -0,0 +1,177 @@
1
+ $: << File.dirname(__FILE__) + '/../lib'
2
+ require 'sfl'
3
+ require 'tempfile'
4
+
5
+ describe 'SFL.new' do
6
+ context 'with argument "ls", "."' do
7
+ subject { SFL.new('ls', '.') }
8
+ it { should == SFL.new('ls', '.') }
9
+ it { should == SFL.new(['ls', 'ls'], '.') }
10
+ it { should_not == SFL.new('ls', 'aaaaa') }
11
+ it { should == SFL.new({}, 'ls', '.') }
12
+ it { should == SFL.new({}, 'ls', '.', {}) }
13
+ it { should_not == SFL.new({1=>2}, 'ls', '.', {}) }
14
+ end
15
+
16
+ context 'with argument {"A" => "1"}, ["ls", "dir"]' do
17
+ subject { SFL.new({"A" => "1"}, ['ls', 'dir']) }
18
+ it { should == SFL.new({"A" => "1"}, ['ls', 'dir']) }
19
+ it { should == SFL.new({"A" => "1"}, ['ls', 'dir'], {}) }
20
+ it { should_not == SFL.new({"A" => "1"}, 'ls', 'dir', {}) }
21
+ it { should_not == SFL.new(['ls', 'ls']) }
22
+ end
23
+
24
+ context 'with argument {"A" => "a"}, "ls", ".", {:out => :err}' do
25
+ subject { SFL.new({"A" => "a"}, "ls", ".", {:out => :err}) }
26
+ it { should == SFL.new({"A" => "a"}, ['ls', 'ls'], '.', {:out => :err}) }
27
+ end
28
+
29
+ context 'with argument "ls ."' do
30
+ subject { SFL.new('ls .') }
31
+ it { should == SFL.new('ls .') }
32
+ it { should == SFL.new('ls', '.') }
33
+ it { should == SFL.new(['ls', 'ls'], '.') }
34
+ end
35
+ end
36
+
37
+ describe 'Kernel.spawn' do
38
+ def mocker(code)
39
+ sfl_expanded = File.expand_path('../../lib/sfl', __FILE__)
40
+ rubyfile = File.expand_path('../mocker.rb', __FILE__) # Tempfile.new('-').path
41
+ File.open(rubyfile, 'w') {|io| io.puts <<-"EOF"
42
+ require '#{sfl_expanded}'
43
+ #{code}
44
+ EOF
45
+ }
46
+ resultfile = File.expand_path('../mocker_output.txt', __FILE__) # Tempfile.new('-').path
47
+ system "ruby #{rubyfile} > #{resultfile}"
48
+ File.read(resultfile)
49
+ end
50
+
51
+ context 'with command "ls", "."' do
52
+ it 'outputs the result of "ls ." on stdout' do
53
+ mocker(%q|
54
+ pid = Kernel.spawn('ls', '.')
55
+ Process.wait(pid)
56
+ |).should == `ls .`
57
+ end
58
+ end
59
+
60
+ # The following test is unsound and lead to spec
61
+ # failures under specific rubies...
62
+ #
63
+ # it 'is asynchronous' do
64
+ # mocker(%q|
65
+ # Kernel.spawn('sh', '-c', 'echo 1; sleep 1; echo 2')
66
+ # sleep 0.1
67
+ # |).should == "1\n"
68
+ # end
69
+
70
+ context 'with environment {"A" => "1"}' do
71
+ it 'outputs with given ENV "1"' do
72
+ mocker(%q|
73
+ pid = Kernel.spawn({'A' => 'a'}, 'ruby', '-e', 'p ENV["A"]')
74
+ Process.wait(pid)
75
+ |).should == "a".inspect + "\n"
76
+ end
77
+ end
78
+
79
+ context 'with option {:err => :out}' do
80
+ it 'outputs with given ENV "1"' do
81
+ mocker(
82
+ %q|
83
+ pid = Kernel.spawn('ls', 'nonexistfile', {:err => :out})
84
+ Process.wait(pid)
85
+ |).should =~ /^ls:/
86
+ end
87
+ end
88
+
89
+ context 'with option {:out => "/tmp/aaaaaaa.txt"}' do
90
+ it 'outputs with given ENV "1"' do
91
+ mocker(
92
+ %q|
93
+ pid = Kernel.spawn('echo', '123', {:out => "/tmp/aaaaaaa.txt"})
94
+ Process.wait(pid)
95
+ |).should == ""
96
+ File.read('/tmp/aaaaaaa.txt').should == "123\n"
97
+ end
98
+ end
99
+
100
+ context 'with option {:out => :close, :err => :close}' do
101
+ it 'outputs nothing at all' do
102
+ mocker(
103
+ %q|
104
+ pid = Kernel.spawn('echo', '123', {:out => :close, :err => :close})
105
+ Process.wait(pid)
106
+ |).should == ""
107
+ end
108
+ end
109
+
110
+ context 'with option {[:out, :err] => :close}' do
111
+ it 'outputs nothing at all' do
112
+ mocker(
113
+ %q|
114
+ pid = Kernel.spawn('echo', '123', {[:out, :err] => :close})
115
+ Process.wait(pid)
116
+ |).should == ""
117
+ end
118
+ end
119
+
120
+ context 'with option {:in => "README.md"}' do
121
+ it 'outputs README.md' do
122
+ mocker(
123
+ %q|
124
+ pid = Kernel.spawn('cat', {:in => File.expand_path('../../README.md', __FILE__)})
125
+ Process.wait(pid)
126
+ |).should =~ /Spawn for Legacy/
127
+ end
128
+ end
129
+ end
130
+
131
+ describe 'SFL.option_parser' do
132
+ it 'with symbol arguments' do
133
+ SFL.option_parser({:err => :out}).
134
+ should == [[STDERR, :reopen, STDOUT]]
135
+
136
+ SFL.option_parser({:err => 'filename'}).
137
+ should == [[STDERR, :reopen, [File, :open, 'filename', 'w']]]
138
+
139
+ o = File.open('/dev/null', 'w')
140
+ SFL.option_parser({:out => o}).
141
+ should == [[STDOUT, :reopen, o]]
142
+
143
+ SFL.option_parser({[:out, :err] => 'filename'}).
144
+ should == [
145
+ [STDOUT, :reopen, [File, :open, 'filename', 'w'] ],
146
+ [STDERR, :reopen, STDOUT]
147
+ ]
148
+
149
+ SFL.option_parser({:chdir => 'aaa'}).
150
+ should == [[Dir, :chdir, 'aaa']]
151
+
152
+ SFL.option_parser({:err => :out, :chdir => 'aaa'}).
153
+ should == [
154
+ [Dir, :chdir, 'aaa'],
155
+ [STDERR, :reopen, STDOUT]
156
+ ]
157
+ end
158
+ end
159
+
160
+ describe 'SFL.parse_command_with_arg' do
161
+ context 'ls .' do
162
+ subject { SFL.parse_command_with_arg('ls .') }
163
+ it { should == ['ls', '.'] }
164
+ end
165
+
166
+ context 'ls " "' do
167
+ subject { SFL.parse_command_with_arg('ls " "') }
168
+ it { should == ['ls', ' '] }
169
+ end
170
+ end
171
+
172
+ describe 'spawn()' do
173
+ it 'exists' do
174
+ Kernel.should be_respond_to(:spawn, true)
175
+ Process.should be_respond_to(:spawn, true)
176
+ end
177
+ end
metadata CHANGED
@@ -1,12 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sfl
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
5
4
  prerelease: false
6
5
  segments:
7
- - 1
8
6
  - 2
9
- version: "1.2"
7
+ - 0
8
+ version: "2.0"
10
9
  platform: ruby
11
10
  authors:
12
11
  - ujihisa
@@ -14,10 +13,37 @@ autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
15
 
17
- date: 2010-03-11 00:00:00 -08:00
16
+ date: 2011-01-19 00:00:00 -08:00
18
17
  default_executable:
19
- dependencies: []
20
-
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rake
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: rspec
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 2
42
+ - 4
43
+ - 0
44
+ version: 2.4.0
45
+ type: :development
46
+ version_requirements: *id002
21
47
  description: Spawn For Ruby 1.8
22
48
  email: ujihisa at gmail.com
23
49
  executables: []
@@ -28,7 +54,11 @@ extra_rdoc_files:
28
54
  - README.md
29
55
  files:
30
56
  - lib/sfl.rb
57
+ - spec/sfl_spec.rb
58
+ - sfl.gemspec
59
+ - Rakefile
31
60
  - README.md
61
+ - CHANGELOG.md
32
62
  has_rdoc: true
33
63
  homepage: https://github.com/ujihisa/spawn-for-legacy
34
64
  licenses: []
@@ -43,7 +73,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
43
73
  requirements:
44
74
  - - ">="
45
75
  - !ruby/object:Gem::Version
46
- hash: 3
47
76
  segments:
48
77
  - 0
49
78
  version: "0"
@@ -52,7 +81,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
81
  requirements:
53
82
  - - ">="
54
83
  - !ruby/object:Gem::Version
55
- hash: 3
56
84
  segments:
57
85
  - 0
58
86
  version: "0"