wopen3 0.1

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 (2) hide show
  1. data/lib/wopen3.rb +89 -0
  2. metadata +46 -0
data/lib/wopen3.rb ADDED
@@ -0,0 +1,89 @@
1
+ # Copyright 2007 Wincent Colaiuta
2
+ # $Id$
3
+
4
+ # Wopen3 is a replacement for Open3.
5
+ #
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.
8
+ #
9
+ # Usage example:
10
+ #
11
+ # result, errors = '', ''
12
+ # Wopen3.popen3('svn', 'log') do |stdin, stdout, stderr|
13
+ # threads = []
14
+ # threads << Thread.new(stdout) do |out|
15
+ # out.each { |line| result << line }
16
+ # end
17
+ # threads << Thread.new(stderr) do |err|
18
+ # err.each { |line| errors << line }
19
+ # end
20
+ # threads.each { |thread| thread.join }
21
+ # end
22
+ # status = $?.exitstatus
23
+ # raise "Non-zero exit status #{status}" if status != 0
24
+ #
25
+ #
26
+ module Wopen3
27
+
28
+ class Opener
29
+
30
+ READ = 0
31
+ WRITE = 1
32
+
33
+ def initialize(*cmd)
34
+
35
+ write_pipe = IO::pipe
36
+ read_pipe = IO::pipe
37
+ error_pipe = IO::pipe
38
+
39
+ pid = fork do
40
+
41
+ # in child
42
+ write_pipe[WRITE].close
43
+ STDIN.reopen(write_pipe[READ]) # file descriptor duplicated here
44
+ write_pipe[READ].close # must close in order for parent to see EOF
45
+
46
+ read_pipe[READ].close
47
+ STDOUT.reopen(read_pipe[WRITE])
48
+ read_pipe[WRITE].close
49
+
50
+ error_pipe[READ].close
51
+ STDERR.reopen(error_pipe[WRITE])
52
+ error_pipe[WRITE].close
53
+
54
+ exec(*cmd) # will raise SystemCallError if command can't be executed (eg Errno::NOENT)
55
+ exit! # should never get here
56
+
57
+ end
58
+
59
+ # in parent
60
+ write_pipe[READ].close
61
+ read_pipe[WRITE].close
62
+ error_pipe[WRITE].close
63
+
64
+ pipes = [write_pipe[WRITE], read_pipe[READ], error_pipe[READ]]
65
+ write_pipe[WRITE].sync = true
66
+
67
+ if defined? yield
68
+ begin
69
+ result = yield(*pipes)
70
+ Process.waitpid(pid) # global $? gets set here
71
+ return result
72
+ ensure
73
+ pipes.each { |pipe| pipe.close unless pipe.closed? }
74
+ end
75
+ end
76
+
77
+ # can't wait immediately (will hang); wait once garbage collection destroys/finalizes this instance
78
+ ObjectSpace.define_finalizer(self, proc { Process.waitpid(pid) })
79
+ pipes
80
+
81
+ end
82
+
83
+ end
84
+
85
+ def self.popen3(*cmd, &block)
86
+ Opener.new(*cmd, &block)
87
+ end
88
+
89
+ end # module Wopen3
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: wopen3
5
+ 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:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Wincent Colaiuta
31
+ files:
32
+ - lib/wopen3.rb
33
+ test_files: []
34
+
35
+ rdoc_options: []
36
+
37
+ extra_rdoc_files: []
38
+
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ requirements: []
44
+
45
+ dependencies: []
46
+