right_popen 1.0.11 → 1.0.16

Sign up to get free protection for your applications and to get access to all the features.
data/spec/runner.rb ADDED
@@ -0,0 +1,112 @@
1
+ #-- -*- mode: ruby; encoding: utf-8 -*-
2
+ # Copyright: Copyright (c) 2011 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module RightScale
25
+ class Runner
26
+ class RunnerStatus
27
+ def initialize(command, block)
28
+ @output_text = ""
29
+ @error_text = ""
30
+ @status = nil
31
+ @did_timeout = false
32
+ @callback = block
33
+ @pid = nil
34
+ EM.next_tick do
35
+ @timeout = EM::Timer.new(2) do
36
+ puts "\n** Failed to run #{command.inspect}: Timeout"
37
+ @did_timeout = true
38
+ @callback.call(self)
39
+ end
40
+ end
41
+ end
42
+
43
+ attr_accessor :output_text, :error_text, :status, :did_timeout, :pid
44
+
45
+ def on_read_stdout(data)
46
+ @output_text << data
47
+ end
48
+
49
+ def on_read_stderr(data)
50
+ @error_text << data
51
+ end
52
+
53
+ def on_pid(pid)
54
+ raise "PID already set!" unless @pid.nil?
55
+ @pid = pid
56
+ end
57
+
58
+ def on_exit(status)
59
+ @timeout.cancel if @timeout
60
+ @status = status
61
+ @callback.call(self)
62
+ end
63
+ end
64
+
65
+ def initialize
66
+ @count = 0
67
+ @done = false
68
+ @last_exception = nil
69
+ @last_iteration = 0
70
+ end
71
+
72
+ def do_right_popen(command, env=nil, input=nil, &callback)
73
+ status = RunnerStatus.new(command, callback)
74
+ RightScale.popen3(:command => command,
75
+ :input => input,
76
+ :target => status,
77
+ :environment => env,
78
+ :stdout_handler => :on_read_stdout,
79
+ :stderr_handler => :on_read_stderr,
80
+ :pid_handler => :on_pid,
81
+ :exit_handler => :on_exit)
82
+ status
83
+ end
84
+
85
+ def run_right_popen(command, env=nil, input=nil, count=1)
86
+ begin
87
+ @iterations = 0
88
+ EM.run do
89
+ EM.next_tick do
90
+ do_right_popen(command, env, input) do |status|
91
+ maybe_continue(status)
92
+ end
93
+ end
94
+ end
95
+ @status
96
+ rescue Exception => e
97
+ puts "\n** Failed: #{e.message} FROM\n#{e.backtrace.join("\n")}"
98
+ raise e
99
+ end
100
+ end
101
+
102
+ def maybe_continue(status)
103
+ @iterations += 1
104
+ if @iterations < @count
105
+ do_right_popen(command, env, input) {|status| maybe_continue(status)}
106
+ else
107
+ @status = status
108
+ EM.stop
109
+ end
110
+ end
111
+ end
112
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'rubygems'
2
+ require 'bundler/setup'
2
3
  require 'spec'
3
4
  require 'eventmachine'
5
+ require 'flexmock'
4
6
  require File.join(File.dirname(__FILE__), '..', 'lib', 'right_popen')
5
7
 
6
8
  RUBY_CMD = 'ruby'
@@ -18,3 +20,7 @@ REPEAT_TEST_COUNTER = 256
18
20
  def is_windows?
19
21
  return RUBY_PLATFORM =~ /mswin/
20
22
  end
23
+
24
+ Spec::Runner.configure do |config|
25
+ config.mock_with :flexmock
26
+ end
data/spec/stdout.rb ADDED
@@ -0,0 +1,28 @@
1
+ #-- -*- mode: ruby; encoding: utf-8 -*-
2
+ # Copyright: Copyright (c) 2011 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ $stderr.puts "Closing stdout"
25
+ STDOUT.close
26
+ sleep 3
27
+ $stderr.puts "Exiting"
28
+ exit 0
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: right_popen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.11
4
+ hash: 55
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 16
10
+ version: 1.0.16
5
11
  platform: ruby
6
12
  authors:
7
13
  - Scott Messier
@@ -11,19 +17,69 @@ autorequire:
11
17
  bindir: bin
12
18
  cert_chain: []
13
19
 
14
- date: 2010-09-08 00:00:00 -07:00
15
- default_executable:
20
+ date: 2012-05-15 00:00:00 Z
16
21
  dependencies:
17
22
  - !ruby/object:Gem::Dependency
18
23
  name: eventmachine
19
- type: :runtime
20
- version_requirement:
21
- version_requirements: !ruby/object:Gem::Requirement
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
+ none: false
22
26
  requirements:
23
27
  - - ">="
24
28
  - !ruby/object:Gem::Version
29
+ hash: 59
30
+ segments:
31
+ - 0
32
+ - 12
33
+ - 10
25
34
  version: 0.12.10
26
- version:
35
+ type: :runtime
36
+ requirement: *id001
37
+ prerelease: false
38
+ - !ruby/object:Gem::Dependency
39
+ name: rspec
40
+ version_requirements: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 9
46
+ segments:
47
+ - 1
48
+ - 3
49
+ version: "1.3"
50
+ type: :development
51
+ requirement: *id002
52
+ prerelease: false
53
+ - !ruby/object:Gem::Dependency
54
+ name: rake
55
+ version_requirements: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 49
61
+ segments:
62
+ - 0
63
+ - 8
64
+ - 7
65
+ version: 0.8.7
66
+ type: :development
67
+ requirement: *id003
68
+ prerelease: false
69
+ - !ruby/object:Gem::Dependency
70
+ name: flexmock
71
+ version_requirements: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 3
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ type: :development
81
+ requirement: *id004
82
+ prerelease: false
27
83
  description: |
28
84
  RightPopen allows running external processes aynchronously while still
29
85
  capturing their standard and error outputs. It relies on EventMachine for most
@@ -41,9 +97,14 @@ files:
41
97
  - LICENSE
42
98
  - README.rdoc
43
99
  - Rakefile
44
- - lib/linux/right_popen.rb
45
100
  - lib/right_popen.rb
101
+ - lib/right_popen/linux/accumulator.rb
102
+ - lib/right_popen/linux/process.rb
103
+ - lib/right_popen/linux/right_popen.rb
104
+ - lib/right_popen/linux/utilities.rb
105
+ - lib/right_popen/version.rb
46
106
  - right_popen.gemspec
107
+ - spec/background.rb
47
108
  - spec/increment.rb
48
109
  - spec/print_env.rb
49
110
  - spec/produce_mixed_output.rb
@@ -51,9 +112,12 @@ files:
51
112
  - spec/produce_status.rb
52
113
  - spec/produce_stderr_only.rb
53
114
  - spec/produce_stdout_only.rb
115
+ - spec/right_popen/linux/accumulator_spec.rb
116
+ - spec/right_popen/linux/utilities_spec.rb
54
117
  - spec/right_popen_spec.rb
118
+ - spec/runner.rb
55
119
  - spec/spec_helper.rb
56
- has_rdoc: true
120
+ - spec/stdout.rb
57
121
  homepage: https://github.com/rightscale/right_popen
58
122
  licenses: []
59
123
 
@@ -66,21 +130,29 @@ rdoc_options:
66
130
  require_paths:
67
131
  - lib
68
132
  required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
69
134
  requirements:
70
135
  - - ">="
71
136
  - !ruby/object:Gem::Version
137
+ hash: 59
138
+ segments:
139
+ - 1
140
+ - 8
141
+ - 6
72
142
  version: 1.8.6
73
- version:
74
143
  required_rubygems_version: !ruby/object:Gem::Requirement
144
+ none: false
75
145
  requirements:
76
146
  - - ">="
77
147
  - !ruby/object:Gem::Version
148
+ hash: 3
149
+ segments:
150
+ - 0
78
151
  version: "0"
79
- version:
80
152
  requirements: []
81
153
 
82
154
  rubyforge_project: right_popen
83
- rubygems_version: 1.3.5
155
+ rubygems_version: 1.8.24
84
156
  signing_key:
85
157
  specification_version: 3
86
158
  summary: Provides a platform-independent popen implementation
@@ -1,118 +0,0 @@
1
- #--
2
- # Copyright (c) 2009 RightScale Inc
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- # RightScale.popen3 allows running external processes aynchronously
25
- # while still capturing their standard and error outputs.
26
- # It relies on EventMachine for most of its internal mechanisms.
27
-
28
- require 'rubygems'
29
- require 'eventmachine'
30
- require 'tempfile'
31
-
32
- module RightScale
33
- module PipeHandler
34
- def initialize(target, handler)
35
- @target = target
36
- @handler = handler
37
- end
38
-
39
- def receive_data(data)
40
- @target.method(@handler).call(data) if @handler
41
- end
42
- end
43
- module InputHandler
44
- def initialize(string)
45
- @string = string
46
- end
47
-
48
- def post_init
49
- send_data(@string) if @string
50
- close_connection_after_writing
51
- end
52
- end
53
-
54
- # Forks process to run given command asynchronously, hooking all three
55
- # standard streams of the child process.
56
- #
57
- # === Parameters
58
- # options[:pid_handler](Symbol):: Token for pid handler method name.
59
- # options[:temp_dir]:: Path to temporary directory where executable files are
60
- # created, default to /tmp if not specified
61
- #
62
- # See RightScale.popen3
63
- def self.popen3_imp(options)
64
- GC.start # To garbage collect open file descriptors from passed executions
65
- EM.next_tick do
66
- inr, inw = IO::pipe
67
- outr, outw = IO::pipe
68
- errr, errw = IO::pipe
69
-
70
- [inr, inw, outr, outw, errr, errw].each {|fdes| fdes.sync = true}
71
-
72
- pid = fork do
73
- options[:environment].each do |k, v|
74
- ENV[k.to_s] = v
75
- end unless options[:environment].nil?
76
-
77
- inw.close
78
- outr.close
79
- errr.close
80
- $stdin.reopen inr
81
- $stdout.reopen outw
82
- $stderr.reopen errw
83
-
84
- if options[:command].instance_of?(String)
85
- exec "sh", "-c", options[:command]
86
- else
87
- exec *options[:command]
88
- end
89
- end
90
-
91
- inr.close
92
- outw.close
93
- errw.close
94
- stderr = EM.attach(errr, PipeHandler, options[:target],
95
- options[:stderr_handler])
96
- stdout = EM.attach(outr, PipeHandler, options[:target],
97
- options[:stdout_handler])
98
- stdin = EM.attach(inw, InputHandler, options[:input])
99
-
100
- options[:target].method(options[:pid_handler]).call(pid) if
101
- options.key? :pid_handler
102
-
103
- wait_timer = EM::PeriodicTimer.new(1) do
104
- value = Process.waitpid2(pid, Process::WNOHANG)
105
- unless value.nil?
106
- ignored, status = value
107
- wait_timer.cancel
108
- stdin.close_connection
109
- stdout.close_connection
110
- stderr.close_connection
111
- options[:target].method(options[:exit_handler]).call(status) if
112
- options[:exit_handler]
113
- end
114
- end
115
- end
116
- true
117
- end
118
- end