wopen3 0.1 → 0.2

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 +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