shell-executer 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ DESCRIPTION = <<-EOS
12
12
  EOS
13
13
  AUTHOR = 'Holger Kohnen'
14
14
  AUTHOR_EMAIL = 'h.kohnen@gmail.com'
15
- GEM_VERSION = '1.0.0'
15
+ GEM_VERSION = '1.0.1'
16
16
  HOMEPAGE = "http://#{TITLE}.rubyforge.org/"
17
17
  PROJECT_NAME = TITLE
18
18
 
@@ -15,7 +15,7 @@ module Shell
15
15
  end
16
16
 
17
17
  class Executer
18
- # Holds last executed commands standard output if executed without block.
18
+ # Holds last executed commands standard output.
19
19
  attr_reader :stdout
20
20
 
21
21
  # Holds last executed commands error output.
@@ -27,9 +27,14 @@ module Shell
27
27
  # In lines-mode every line of the output is passed to the block.
28
28
  # In chars-mode every char of the output is passed to the block.
29
29
  # (default is: <tt>:lines</tt>)
30
+ # * <tt>:no_buffer</tt> - Specifies the output mode.
31
+ # Can be <tt>false</tt> or <tt>true</tt>.
32
+ # If true no output is collected, stdout and stderr properties are empty.
33
+ # (default is: <tt>false</tt>)
30
34
  def initialize(options={})
31
35
  @options = {
32
- :mode => :lines # :chars|:lines <- output mode
36
+ :mode => :lines, # :chars|:lines <- output mode
37
+ :no_buffer => false
33
38
  }.merge(options)
34
39
 
35
40
  @reader = (@options[:mode] == :chars) ? proc {|s| s.getc } : proc {|s| s.gets }
@@ -49,10 +54,6 @@ module Shell
49
54
  # In the first form(<tt>execute(command)</tt>) the +command+ ist executed
50
55
  # and the +stdout+, +stderr+ and +success+ attributes are populated.
51
56
  #
52
- # In the second and third form the +stdout+ attribute is *not* populated. The +stdout+
53
- # is passed to the specified block instead. The block is invoked for
54
- # every char or line of output depending on the specified <tt>options</tt>.
55
- #
56
57
  # In the second form only the stdout is passed to the block.
57
58
  #
58
59
  # In the third form either stdout or stderr is filled. The opposite is allways nil.
@@ -69,45 +70,58 @@ module Shell
69
70
  @stderr = ''
70
71
  @success = nil
71
72
 
72
- begin
73
- threads = []
74
- pid, stdin, stdout, stderr = Open4::popen4(command)
75
- [[:stdout, stdout], [:stderr, stderr]].each do |type, stream|
76
- threads << Thread.new(type, stream) do |type, stream|
77
- Thread.current.abort_on_exception = true
78
- while data = @reader.call(stream)
79
- data = ((@options[:mode] == :chars) ? data.chr : data)
80
- @mutex.synchronize do
81
- if type == :stdout
82
- if block_given?
83
- if block.arity == 2
84
- yield data, nil
85
- else
86
- yield data
87
- end
88
- else
89
- @stdout += data
90
- end
73
+ pid, stdin, stdout, stderr = Open4::popen4(command)
74
+
75
+ status = nil
76
+ Thread.start do
77
+ status = Process.waitpid2(pid).last
78
+ end
79
+
80
+ streams = [stdout, stderr]
81
+ until streams.empty?
82
+ selected, = select(streams, nil, nil, 0.1)
83
+ next if selected.nil? or selected.empty?
84
+ selected.each do |stream|
85
+ if stream.eof?
86
+ streams.delete(stream) if status
87
+ next
88
+ end
89
+
90
+ while data = @reader.call(stream)
91
+ data = ((@options[:mode] == :chars) ? data.chr : data)
92
+ if block_given?
93
+ if block.arity == 2
94
+ args = [nil, nil]
95
+ if stream == stdout
96
+ args[0] = data
91
97
  else
92
- yield nil, data if block_given? && block.arity == 2
93
- @stderr += data
98
+ args[1] = data
94
99
  end
100
+ yield *args
101
+ else
102
+ if stream == stdout
103
+ yield data
104
+ end
105
+ end
106
+ end
107
+ unless @options[:no_buffer]
108
+ if stream == stdout
109
+ @stdout += data
110
+ else
111
+ @stderr += data
95
112
  end
96
113
  end
97
114
  end
98
115
  end
99
-
100
- ignored, status = Process::waitpid2 pid
101
- @success = (status.exitstatus == 0)
102
-
103
- ensure
104
- threads.each(&:join)
105
- stdin.close if stdin
106
- stdout.close if stdout
107
- stderr.close if stderr
108
116
  end
109
117
 
118
+ @success = (status.exitstatus == 0)
119
+
110
120
  self
121
+ ensure
122
+ stdin.close rescue nil
123
+ stdout.close rescue nil
124
+ stderr.close rescue nil
111
125
  end
112
126
 
113
127
  # :call-seq: execute!(command) -> Shell::Executer
@@ -1,4 +1,5 @@
1
1
  require 'expectations'
2
+
2
3
  require File.expand_path(File.join(File.dirname(__FILE__), '../lib/shell/executer.rb'))
3
4
 
4
5
  Expectations do
@@ -47,4 +48,12 @@ Expectations do
47
48
  Shell.execute!('ls /does_not_exist')
48
49
  end
49
50
 
51
+ expect false do
52
+ Shell.execute('ls /does_not_exist').success?
53
+ end
54
+
55
+ expect '' do
56
+ Shell.execute('echo test', no_buffer: true).stdout
57
+ end
58
+
50
59
  end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shell-executer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 1
9
+ version: 1.0.1
5
10
  platform: ruby
6
11
  authors:
7
12
  - Holger Kohnen
@@ -9,30 +14,36 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-04-30 00:00:00 +02:00
17
+ date: 2010-11-28 00:00:00 +01:00
13
18
  default_executable:
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: open4
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
20
25
  requirements:
21
26
  - - ">="
22
27
  - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
23
30
  version: "0"
24
- version:
31
+ type: :runtime
32
+ version_requirements: *id001
25
33
  - !ruby/object:Gem::Dependency
26
34
  name: expectations
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
30
38
  requirements:
31
39
  - - ">="
32
40
  - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
33
43
  version: "0"
34
- version:
35
- description: Shell::Executer provides an easy and robust way to execute shell commands. The stdout and stderr data can be read completly after the execution or in chunks during the execution.
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ description: " Shell::Executer provides an easy and robust way to execute shell commands.\n The stdout and stderr data can be read completly after the execution or\n in chunks during the execution.\n"
36
47
  email: h.kohnen@gmail.com
37
48
  executables: []
38
49
 
@@ -47,6 +58,8 @@ files:
47
58
  - README
48
59
  has_rdoc: true
49
60
  homepage: http://shell-executer.rubyforge.org/
61
+ licenses: []
62
+
50
63
  post_install_message:
51
64
  rdoc_options:
52
65
  - --title
@@ -58,23 +71,27 @@ rdoc_options:
58
71
  require_paths:
59
72
  - lib
60
73
  required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
61
75
  requirements:
62
76
  - - ">="
63
77
  - !ruby/object:Gem::Version
78
+ segments:
79
+ - 0
64
80
  version: "0"
65
- version:
66
81
  required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
67
83
  requirements:
68
84
  - - ">="
69
85
  - !ruby/object:Gem::Version
86
+ segments:
87
+ - 0
70
88
  version: "0"
71
- version:
72
89
  requirements: []
73
90
 
74
91
  rubyforge_project: shell-executer
75
- rubygems_version: 1.3.1
92
+ rubygems_version: 1.3.7
76
93
  signing_key:
77
- specification_version: 2
94
+ specification_version: 3
78
95
  summary: Shell::Executer provides an easy and robust way to execute shell commands. The stdout and stderr data can be read completly after the execution or in chunks during the execution.
79
96
  test_files: []
80
97