wopen3 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/wopen3.rb +55 -31
  2. metadata +46 -31
data/lib/wopen3.rb CHANGED
@@ -1,15 +1,13 @@
1
- # Copyright 2007 Wincent Colaiuta
2
- # $Id$
3
-
4
1
  # Wopen3 is a replacement for Open3.
5
2
  #
6
- # Unlike Open3, Wopen3 does not throw away the exit code of the executed (grandchild) process.
7
- # Only a child process is spawned and the exit status is returned in $? as normal.
3
+ # Unlike Open3, Wopen3 does not throw away the exit code of the executed
4
+ # (grandchild) process. Only a child process is spawned and the exit status is
5
+ # returned in $? as normal.
8
6
  #
9
7
  # Usage example:
10
8
  #
11
9
  # result, errors = '', ''
12
- # Wopen3.popen3('svn', 'log') do |stdin, stdout, stderr|
10
+ # Wopen3.popen3('git', 'log') do |stdin, stdout, stderr|
13
11
  # threads = []
14
12
  # threads << Thread.new(stdout) do |out|
15
13
  # out.each { |line| result << line }
@@ -17,53 +15,56 @@
17
15
  # threads << Thread.new(stderr) do |err|
18
16
  # err.each { |line| errors << line }
19
17
  # end
20
- # threads.each { |thread| thread.join }
18
+ # threads.each { |thread| thread.join }
21
19
  # end
22
20
  # status = $?.exitstatus
23
21
  # raise "Non-zero exit status #{status}" if status != 0
24
22
  #
23
+ # As this is such a common usage pattern, a 'system' method is provided as a
24
+ # convenience:
25
+ #
26
+ # result = Wopen3.system('git', 'log')
27
+ # result.status # => 0
28
+ # result.stderr # => ''
29
+ # result.stdout # => 'commit 491411b3...'
25
30
  #
26
31
  module Wopen3
27
-
28
32
  class Opener
29
-
30
33
  READ = 0
31
34
  WRITE = 1
32
-
33
- def initialize(*cmd)
34
-
35
+
36
+ def initialize *cmd
35
37
  write_pipe = IO::pipe
36
38
  read_pipe = IO::pipe
37
39
  error_pipe = IO::pipe
38
-
40
+
39
41
  pid = fork do
40
-
41
42
  # in child
42
43
  write_pipe[WRITE].close
43
44
  STDIN.reopen(write_pipe[READ]) # file descriptor duplicated here
44
- write_pipe[READ].close # must close in order for parent to see EOF
45
-
45
+ write_pipe[READ].close # must close in order for parent to
46
+ # see EOF
46
47
  read_pipe[READ].close
47
48
  STDOUT.reopen(read_pipe[WRITE])
48
49
  read_pipe[WRITE].close
49
-
50
+
50
51
  error_pipe[READ].close
51
52
  STDERR.reopen(error_pipe[WRITE])
52
53
  error_pipe[WRITE].close
53
-
54
- exec(*cmd) # will raise SystemCallError if command can't be executed (eg Errno::NOENT)
54
+
55
+ exec(*cmd) # will raise SystemCallError if command can't be executed
56
+ # (eg Errno::NOENT)
55
57
  exit! # should never get here
56
-
57
58
  end
58
-
59
+
59
60
  # in parent
60
61
  write_pipe[READ].close
61
62
  read_pipe[WRITE].close
62
63
  error_pipe[WRITE].close
63
-
64
+
64
65
  pipes = [write_pipe[WRITE], read_pipe[READ], error_pipe[READ]]
65
66
  write_pipe[WRITE].sync = true
66
-
67
+
67
68
  if defined? yield
68
69
  begin
69
70
  result = yield(*pipes)
@@ -73,17 +74,40 @@ module Wopen3
73
74
  pipes.each { |pipe| pipe.close unless pipe.closed? }
74
75
  end
75
76
  end
76
-
77
- # can't wait immediately (will hang); wait once garbage collection destroys/finalizes this instance
77
+
78
+ # can't wait immediately (will hang); wait once garbage collection
79
+ # destroys/finalizes this instance
78
80
  ObjectSpace.define_finalizer(self, proc { Process.waitpid(pid) })
79
81
  pipes
80
-
81
82
  end
82
-
83
+ end # class Opener
84
+
85
+ class Result
86
+ attr_reader :args, :status, :stderr, :stdout
87
+
88
+ def initialize *args
89
+ @args = args
90
+ @stderr = ''
91
+ @stdout = ''
92
+ Wopen3.popen3 *args do |stdin, stdout, stderr|
93
+ threads = []
94
+ threads << Thread.new(stdout) do |out|
95
+ out.each { |line| @stdout << line }
96
+ end
97
+ threads << Thread.new(stderr) do |err|
98
+ err.each { |line| @stderr << line }
99
+ end
100
+ threads.each { |thread| thread.join }
101
+ end
102
+ @status = $?.exitstatus
103
+ end
104
+ end # class Result
105
+
106
+ def self.popen3 *cmd, &block
107
+ Opener.new *cmd, &block
83
108
  end
84
-
85
- def self.popen3(*cmd, &block)
86
- Opener.new(*cmd, &block)
109
+
110
+ def self.system *args
111
+ Result.new *args
87
112
  end
88
-
89
113
  end # module Wopen3
metadata CHANGED
@@ -1,46 +1,61 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.2
3
- specification_version: 1
4
2
  name: wopen3
5
3
  version: !ruby/object:Gem::Version
6
- version: "0.1"
7
- date: 2007-04-12 00:00:00 +02:00
8
- summary: Wopen3 is a simple replacement for Open3.
9
- require_paths:
10
- - lib
11
- email: win@wincent.com
12
- homepage: http://wincent.com/a/products/walrus/wopen3/
13
- rubyforge_project:
14
- description: Unlike Open3, Wopen3 does not throw away the exit code of the executed (grandchild) process. Only a child process is spawned and the exit status is returned in $? as normal.
15
- autorequire: wopen3
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: false
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ version: "0.2"
25
9
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
10
  authors:
30
11
  - Wincent Colaiuta
31
- files:
32
- - lib/wopen3.rb
33
- test_files: []
34
-
35
- rdoc_options: []
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
36
15
 
37
- extra_rdoc_files: []
16
+ date: 2010-07-28 00:00:00 +02:00
17
+ default_executable:
18
+ dependencies: []
38
19
 
20
+ description: " Unlike Open3, Wopen3 does not throw away the exit code of the executed\n (grandchild) process. Only a child process is spawned and the exit\n status is returned in $? as normal.\n"
21
+ email: win@wincent.com
39
22
  executables: []
40
23
 
41
24
  extensions: []
42
25
 
26
+ extra_rdoc_files: []
27
+
28
+ files:
29
+ - lib/wopen3.rb
30
+ has_rdoc: false
31
+ homepage: https://wincent.com/products/wopen3
32
+ licenses: []
33
+
34
+ post_install_message:
35
+ rdoc_options: []
36
+
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ segments:
51
+ - 0
52
+ version: "0"
43
53
  requirements: []
44
54
 
45
- dependencies: []
55
+ rubyforge_project: walrus
56
+ rubygems_version: 1.3.6
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: Wopen3 is a simple replacement for Open3
60
+ test_files: []
46
61