childprocess 0.2.2 → 0.2.3

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.
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
data/README.md CHANGED
@@ -7,6 +7,8 @@ external programs running in the background on any Ruby / OS combination.
7
7
  The code originated in the selenium-webdriver gem, but should prove useful as
8
8
  a standalone library.
9
9
 
10
+ [![Build Status](https://secure.travis-ci.org/jarib/childprocess.png)](http://travis-ci.org/jarib/childprocess)
11
+
10
12
  Usage
11
13
  -----
12
14
  ```ruby
@@ -36,7 +38,6 @@ How the process is launched and killed depends on the platform:
36
38
  * Unix : fork + exec
37
39
  * Windows : CreateProcess and friends
38
40
  * JRuby : java.lang.{Process,ProcessBuilder}
39
- * IronRuby : System.Diagnostics.Process
40
41
 
41
42
  Note on Patches/Pull Requests
42
43
  -----------------------------
data/lib/childprocess.rb CHANGED
@@ -7,16 +7,12 @@ module ChildProcess
7
7
  autoload :Unix, 'childprocess/unix'
8
8
  autoload :Windows, 'childprocess/windows'
9
9
  autoload :JRuby, 'childprocess/jruby'
10
- autoload :IronRuby, 'childprocess/ironruby'
11
10
 
12
11
  class << self
13
-
14
12
  def new(*args)
15
13
  case platform
16
14
  when :jruby
17
15
  JRuby::Process.new(args)
18
- when :ironruby
19
- IronRuby::Process.new(args)
20
16
  when :windows
21
17
  Windows::Process.new(args)
22
18
  when :macosx, :linux, :unix, :cygwin
@@ -14,6 +14,11 @@ module ChildProcess
14
14
  #
15
15
  attr_accessor :duplex
16
16
 
17
+ #
18
+ # Modify the child's environment variables
19
+ #
20
+ attr_reader :environment
21
+
17
22
  #
18
23
  # Create a new process with the given args.
19
24
  #
@@ -22,12 +27,13 @@ module ChildProcess
22
27
  #
23
28
 
24
29
  def initialize(args)
25
- @args = args
26
- @started = false
27
- @exit_code = nil
28
- @io = nil
29
- @detach = false
30
- @duplex = false
30
+ @args = args
31
+ @started = false
32
+ @exit_code = nil
33
+ @io = nil
34
+ @detach = false
35
+ @duplex = false
36
+ @environment = {}
31
37
  end
32
38
 
33
39
  #
@@ -2,4 +2,5 @@ module ChildProcess
2
2
  class Error < StandardError; end
3
3
  class TimeoutError < StandardError; end
4
4
  class SubclassResponsibility < StandardError; end
5
+ class InvalidEnvironmentVariableName < StandardError; end
5
6
  end
@@ -52,12 +52,11 @@ module ChildProcess
52
52
 
53
53
  def launch_process(&blk)
54
54
  pb = java.lang.ProcessBuilder.new(@args)
55
- pb.directory(java.io.File.new(Dir.pwd))
56
- env = pb.environment
57
- ENV.each { |k,v| env.put(k, v) }
58
55
 
59
- @process = pb.start
56
+ pb.directory java.io.File.new(Dir.pwd)
57
+ set_env pb.environment
60
58
 
59
+ @process = pb.start
61
60
  setup_io
62
61
  end
63
62
 
@@ -87,6 +86,11 @@ module ChildProcess
87
86
  Thread.new { Redirector.new(input, output).run }
88
87
  end
89
88
 
89
+ def set_env(env)
90
+ ENV.each { |k,v| env.put(k, v) } # not sure why this is needed
91
+ @environment.each { |k,v| env.put(k.to_s, v.to_s) }
92
+ end
93
+
90
94
  end # Process
91
95
  end # JRuby
92
96
  end # ChildProcess
@@ -81,6 +81,8 @@ module ChildProcess
81
81
  end
82
82
 
83
83
  @pid = fork {
84
+ set_env
85
+
84
86
  STDOUT.reopen(stdout || "/dev/null")
85
87
  STDERR.reopen(stderr || "/dev/null")
86
88
 
@@ -100,6 +102,10 @@ module ChildProcess
100
102
  ::Process.detach(@pid) if detach?
101
103
  end
102
104
 
105
+ def set_env
106
+ @environment.each { |k, v| ENV[k.to_s] = v.to_s }
107
+ end
108
+
103
109
  end # Process
104
110
  end # Unix
105
111
  end # ChildProcess
@@ -1,3 +1,3 @@
1
1
  module ChildProcess
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
@@ -25,6 +25,8 @@ module ChildProcess::Windows
25
25
 
26
26
  DUPLICATE_SAME_ACCESS = 0x00000002
27
27
 
28
+ CREATE_UNICODE_ENVIRONMENT = 0x00000400
29
+
28
30
  module Lib
29
31
  enum :wait_status, [ :wait_object_0, 0,
30
32
  :wait_timeout, 0x102,
@@ -4,6 +4,7 @@ module ChildProcess
4
4
 
5
5
  def self.create_proc(cmd, opts = {})
6
6
  cmd_ptr = FFI::MemoryPointer.from_string cmd
7
+ env_ptr = environment_pointer_for(opts[:environment])
7
8
 
8
9
  flags = 0
9
10
  inherit = !!opts[:inherit]
@@ -25,7 +26,7 @@ module ChildProcess
25
26
  if opts[:duplex]
26
27
  read_pipe_ptr = FFI::MemoryPointer.new(:pointer)
27
28
  write_pipe_ptr = FFI::MemoryPointer.new(:pointer)
28
- sa = SecurityAttributes.new(:inherit => true)
29
+ sa = SecurityAttributes.new(:inherit => true)
29
30
 
30
31
  ok = create_pipe(read_pipe_ptr, write_pipe_ptr, sa, 0)
31
32
  ok or raise Error, last_error_message
@@ -36,7 +37,19 @@ module ChildProcess
36
37
  si[:hStdInput] = read_pipe
37
38
  end
38
39
 
39
- ok = create_process(nil, cmd_ptr, nil, nil, inherit, flags, nil, nil, si, pi)
40
+ ok = create_process(
41
+ nil, # application name
42
+ cmd_ptr, # command line
43
+ nil, # process attributes
44
+ nil, # thread attributes
45
+ inherit, # inherit handles
46
+ flags, # creation flags
47
+ env_ptr, # environment
48
+ nil, # current directory
49
+ si, # startup info
50
+ pi # process info
51
+ )
52
+
40
53
  ok or raise Error, last_error_message
41
54
 
42
55
  close_handle pi[:hProcess]
@@ -60,13 +73,14 @@ module ChildProcess
60
73
  nil, errnum, 0, buf, buf.size, nil
61
74
  )
62
75
 
63
- buf.read_string(size).strip
76
+ str = buf.read_string(size).strip
77
+ "#{str} (#{errnum})"
64
78
  end
65
79
 
66
80
  def self.handle_for(fd_or_io)
67
81
  case fd_or_io
68
82
  when IO
69
- handle = get_osfhandle(fd.fileno)
83
+ handle = get_osfhandle(fd_or_io.fileno)
70
84
  when Fixnum
71
85
  handle = get_osfhandle(fd_or_io)
72
86
  else
@@ -113,6 +127,27 @@ module ChildProcess
113
127
  close_handle proc
114
128
  end
115
129
 
130
+ def self.environment_pointer_for(env)
131
+ return unless env.kind_of?(Hash) && env.any?
132
+
133
+ strings = ENV.map { |k,v| "#{k}=#{v}\0" }
134
+ env.each do |key, value|
135
+ if key.include?("=")
136
+ raise InvalidEnvironmentVariableName, key
137
+ end
138
+
139
+ strings << "#{key}=#{value}\0"
140
+ end
141
+
142
+ strings << "\0" # terminate the env block
143
+ env_str = strings.join
144
+
145
+ ptr = FFI::MemoryPointer.new(:long, env_str.bytesize)
146
+ ptr.write_bytes env_str, 0, env_str.bytesize
147
+
148
+ ptr
149
+ end
150
+
116
151
  #
117
152
  # BOOL WINAPI CreateProcess(
118
153
  # __in_opt LPCTSTR lpApplicationName,
@@ -42,9 +42,10 @@ module ChildProcess
42
42
 
43
43
  def launch_process
44
44
  opts = {
45
- :inherit => false,
46
- :detach => detach?,
47
- :duplex => duplex?
45
+ :inherit => false,
46
+ :detach => detach?,
47
+ :duplex => duplex?,
48
+ :environment => (@environment unless @environment.empty?)
48
49
  }
49
50
 
50
51
  if @io
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require File.expand_path('../spec_helper', __FILE__)
2
4
 
3
5
  describe ChildProcess do
@@ -49,6 +51,39 @@ describe ChildProcess do
49
51
  end
50
52
  end
51
53
 
54
+ it "can override env vars only for the current process" do
55
+ Tempfile.open("env-spec") do |file|
56
+ process = write_env(file.path)
57
+ process.environment['CHILD_ONLY'] = '1'
58
+ process.start
59
+
60
+ ENV['CHILD_ONLY'].should be_nil
61
+
62
+ process.poll_for_exit(EXIT_TIMEOUT)
63
+ file.rewind
64
+
65
+ child_env = eval(file.read)
66
+ child_env['CHILD_ONLY'].should == '1'
67
+ end
68
+ end
69
+
70
+ it "inherits the parent's env vars also when some are overridden" do
71
+ Tempfile.open("env-spec") do |file|
72
+ with_env('INHERITED' => 'yes', 'CHILD_ONLY' => 'no') do
73
+ process = write_env(file.path)
74
+ process.environment['CHILD_ONLY'] = 'yes'
75
+
76
+ process.start
77
+ process.poll_for_exit(EXIT_TIMEOUT)
78
+ file.rewind
79
+ child_env = eval(file.read)
80
+
81
+ child_env['INHERITED'].should == 'yes'
82
+ child_env['CHILD_ONLY'].should == 'yes'
83
+ end
84
+ end
85
+ end
86
+
52
87
  it "passes arguments to the child" do
53
88
  args = ["foo", "bar"]
54
89
 
@@ -137,32 +172,15 @@ describe ChildProcess do
137
172
  end
138
173
 
139
174
  it "preserves Dir.pwd in the child" do
140
- require 'pathname'
141
- begin
142
- path = nil
143
- Tempfile.open("dir-spec") {|tf| path = tf.path }
144
- path = Pathname.new(path).realpath.to_s
145
- File.unlink(path)
146
- Dir.mkdir(path)
147
- Dir.chdir(path) do
148
- process = ruby("puts Dir.pwd")
149
- begin
150
- out = Tempfile.new("dir-spec-out")
151
-
152
- process.io.stdout = out
153
- process.io.stderr = out
154
-
155
- process.start
156
- process.poll_for_exit(EXIT_TIMEOUT)
157
-
158
- out.rewind
159
- out.read.should == "#{path}\n"
160
- ensure
161
- out.close
162
- end
163
- end
164
- ensure
165
- Dir.rmdir(path) if File.exist?(path)
175
+ Tempfile.open("dir-spec-out") do |file|
176
+ process = ruby("print Dir.pwd")
177
+ process.io.stdout = process.io.stderr = file
178
+
179
+ process.start
180
+ process.poll_for_exit(EXIT_TIMEOUT)
181
+
182
+ file.rewind
183
+ file.read.should == Dir.pwd
166
184
  end
167
185
  end
168
186
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: childprocess
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 2
10
- version: 0.2.2
9
+ - 3
10
+ version: 0.2.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jari Bakken
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-26 00:00:00 Z
18
+ date: 2011-11-27 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec
@@ -92,6 +92,7 @@ files:
92
92
  - .document
93
93
  - .gitignore
94
94
  - .rspec
95
+ - .travis.yml
95
96
  - Gemfile
96
97
  - LICENSE
97
98
  - README.md
@@ -101,8 +102,6 @@ files:
101
102
  - lib/childprocess/abstract_io.rb
102
103
  - lib/childprocess/abstract_process.rb
103
104
  - lib/childprocess/errors.rb
104
- - lib/childprocess/ironruby.rb
105
- - lib/childprocess/ironruby/process.rb
106
105
  - lib/childprocess/jruby.rb
107
106
  - lib/childprocess/jruby/io.rb
108
107
  - lib/childprocess/jruby/process.rb
@@ -155,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
154
  requirements: []
156
155
 
157
156
  rubyforge_project: childprocess
158
- rubygems_version: 1.8.9
157
+ rubygems_version: 1.8.10
159
158
  signing_key:
160
159
  specification_version: 3
161
160
  summary: This gem aims at being a simple and reliable solution for controlling external programs running in the background on any Ruby / OS combination.
@@ -167,3 +166,4 @@ test_files:
167
166
  - spec/spec_helper.rb
168
167
  - spec/unix_spec.rb
169
168
  - spec/windows_spec.rb
169
+ has_rdoc:
@@ -1,6 +0,0 @@
1
- module ChildProcess
2
- module IronRuby
3
- end
4
- end
5
-
6
- require "childprocess/ironruby/process"
@@ -1,7 +0,0 @@
1
- module ChildProcess
2
- module IronRuby
3
- class Process < AbstractProcess
4
-
5
- end # Process
6
- end # IronRuby
7
- end # ChildProcess