childprocess 0.3.2 → 0.3.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.
@@ -19,6 +19,11 @@ module ChildProcess
19
19
  #
20
20
  attr_reader :environment
21
21
 
22
+ #
23
+ # Set the child's current working directory.
24
+ #
25
+ attr_accessor :cwd
26
+
22
27
  #
23
28
  # Create a new process with the given args.
24
29
  #
@@ -66,7 +66,7 @@ module ChildProcess
66
66
  def launch_process(&blk)
67
67
  pb = java.lang.ProcessBuilder.new(@args)
68
68
 
69
- pb.directory java.io.File.new(Dir.pwd)
69
+ pb.directory java.io.File.new(@cwd || Dir.pwd)
70
70
  set_env pb.environment
71
71
 
72
72
  begin
@@ -18,6 +18,10 @@ module ChildProcess
18
18
  end
19
19
 
20
20
  @pid = fork {
21
+ if @cwd
22
+ Dir.chdir(@cwd)
23
+ end
24
+
21
25
  exec_r.close
22
26
  set_env
23
27
 
@@ -1,10 +1,13 @@
1
1
  require 'ffi'
2
+ require 'thread'
2
3
 
3
4
  module ChildProcess
4
5
  module Unix
5
6
  class PosixSpawnProcess < Process
6
7
  private
7
8
 
9
+ @@cwd_lock = Mutex.new
10
+
8
11
  def launch_process
9
12
  pid_ptr = FFI::MemoryPointer.new(:pid_t)
10
13
  actions = Lib::FileActions.new
@@ -41,21 +44,26 @@ module ChildProcess
41
44
  argv = Argv.new(@args)
42
45
  envp = Envp.new(ENV.to_hash.merge(@environment))
43
46
 
44
- if ChildProcess.jruby?
45
- # on JRuby, the current working directory is for some reason not inherited.
46
- # We'll work around it by making a chdir call through FFI.
47
- # TODO: report this to JRuby
48
- Lib.chdir Dir.pwd
49
- end
47
+ ret = 0
48
+ @@cwd_lock.synchronize do
49
+ Dir.chdir(@cwd || Dir.pwd) do
50
+ if ChildProcess.jruby?
51
+ # on JRuby, the current working directory is for some reason not inherited.
52
+ # We'll work around it by making a chdir call through FFI.
53
+ # TODO: report this to JRuby
54
+ Lib.chdir Dir.pwd
55
+ end
50
56
 
51
- ret = Lib.posix_spawnp(
52
- pid_ptr,
53
- @args.first, # TODO: not sure this matches exec() behaviour
54
- actions,
55
- attrs,
56
- argv,
57
- envp
58
- )
57
+ ret = Lib.posix_spawnp(
58
+ pid_ptr,
59
+ @args.first, # TODO: not sure this matches exec() behaviour
60
+ actions,
61
+ attrs,
62
+ argv,
63
+ envp
64
+ )
65
+ end
66
+ end
59
67
 
60
68
  if duplex?
61
69
  io._stdin = writer
@@ -1,3 +1,3 @@
1
1
  module ChildProcess
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3"
3
3
  end
@@ -53,6 +53,7 @@ module ChildProcess
53
53
  builder.detach = detach?
54
54
  builder.duplex = duplex?
55
55
  builder.environment = @environment unless @environment.empty?
56
+ builder.cwd = @cwd
56
57
 
57
58
  if @io
58
59
  builder.stdout = @io.stdout
@@ -1,7 +1,7 @@
1
1
  module ChildProcess
2
2
  module Windows
3
3
  class ProcessBuilder
4
- attr_accessor :inherit, :detach, :duplex, :environment, :stdout, :stderr
4
+ attr_accessor :inherit, :detach, :duplex, :environment, :stdout, :stderr, :cwd
5
5
  attr_reader :stdin
6
6
 
7
7
  def initialize(args)
@@ -11,6 +11,7 @@ module ChildProcess
11
11
  @detach = false
12
12
  @duplex = false
13
13
  @environment = nil
14
+ @cwd = nil
14
15
 
15
16
  @stdout = nil
16
17
  @stderr = nil
@@ -19,11 +20,13 @@ module ChildProcess
19
20
  @flags = 0
20
21
  @cmd_ptr = nil
21
22
  @env_ptr = nil
23
+ @cwd_ptr = nil
22
24
  end
23
25
 
24
26
  def start
25
27
  create_command_pointer
26
28
  create_environment_pointer
29
+ create_cwd_pointer
27
30
 
28
31
  setup_detach
29
32
  setup_io
@@ -63,6 +66,10 @@ module ChildProcess
63
66
  @env_ptr.put_bytes 0, env_str, 0, env_str.bytesize
64
67
  end
65
68
 
69
+ def create_cwd_pointer
70
+ @cwd_ptr = FFI::MemoryPointer.from_string(@cwd || Dir.pwd)
71
+ end
72
+
66
73
  def create_process
67
74
  ok = Lib.create_process(
68
75
  nil, # application name
@@ -72,7 +79,7 @@ module ChildProcess
72
79
  @inherit, # inherit handles
73
80
  @flags, # creation flags
74
81
  @env_ptr, # environment
75
- cwd, # current directory
82
+ @cwd_ptr, # current directory
76
83
  startup_info, # startup info
77
84
  process_info # process info
78
85
  )
@@ -94,10 +101,6 @@ module ChildProcess
94
101
  @flags |= DETACHED_PROCESS if @detach
95
102
  end
96
103
 
97
- def cwd
98
- @cwd ||= FFI::MemoryPointer.from_string(Dir.pwd)
99
- end
100
-
101
104
  def setup_io
102
105
  if @stdout || @stderr
103
106
  startup_info[:dwFlags] ||= 0
@@ -173,4 +176,4 @@ module ChildProcess
173
176
  end
174
177
  end # ProcessBuilder
175
178
  end # Windows
176
- end # ChildProcess
179
+ end # ChildProcess
@@ -168,4 +168,25 @@ describe ChildProcess do
168
168
  lambda { process.poll_for_exit(0.1) }.should raise_error(ChildProcess::TimeoutError)
169
169
  end
170
170
 
171
+ it "can change working directory" do
172
+ process = ruby "print Dir.pwd"
173
+
174
+ with_tmpdir { |dir|
175
+ process.cwd = dir
176
+
177
+ orig_pwd = Dir.pwd
178
+
179
+ Tempfile.open('cwd') do |file|
180
+ process.io.stdout = file
181
+
182
+ process.start
183
+ process.wait
184
+
185
+ file.rewind
186
+ file.read.should == dir
187
+ end
188
+
189
+ Dir.pwd.should == orig_pwd
190
+ }
191
+ end
171
192
  end
@@ -123,6 +123,17 @@ module ChildProcessSpecHelper
123
123
  port
124
124
  end
125
125
 
126
+ def with_tmpdir(&blk)
127
+ name = "#{Time.now.strftime("%Y%m%d")}-#{$$}-#{rand(0x100000000).to_s(36)}"
128
+ FileUtils.mkdir_p(name)
129
+
130
+ begin
131
+ yield File.expand_path(name)
132
+ ensure
133
+ FileUtils.rm_rf name
134
+ end
135
+ end
136
+
126
137
  def wait_until(timeout = 10, &blk)
127
138
  end_time = Time.now + timeout
128
139
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: childprocess
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-20 00:00:00.000000000 Z
12
+ date: 2012-06-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -147,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
147
  version: '0'
148
148
  requirements: []
149
149
  rubyforge_project: childprocess
150
- rubygems_version: 1.8.21
150
+ rubygems_version: 1.8.24
151
151
  signing_key:
152
152
  specification_version: 3
153
153
  summary: This gem aims at being a simple and reliable solution for controlling external