Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implement basic Task class that manages STDOUT, STDIN, and STDERR. Mo…

…re features will be coming around the Task class.
  • Loading branch information...
commit 29b8c39fc8394007ed3349c639c06e9991ed79ed 1 parent 0f5afe4
Carl Lerche authored
View
18 Rakefile
@@ -0,0 +1,18 @@
+
+
+desc "Run specs"
+begin
+ require 'spec/rake/spectask'
+rescue LoadError
+ task :spec do
+ abort 'Run `gem install rspec` to be able to run specs'
+ end
+else
+ Spec::Rake::SpecTask.new do |t|
+ t.spec_files = FileList['spec/**/*_spec.rb']
+ t.spec_opts = %w(-fs --color)
+ t.warning = true
+ end
+end
+
+task :default => :spec
View
1  childlabor.gemsec
@@ -16,6 +16,5 @@ Gem::Specification.new do |s|
s.add_development_dependency "rspec"
s.files = Dir.glob("lib/**/*") + %w(LICENSE README.md)
- s.executables = ['bundle']
s.require_path = 'lib'
end
View
95 lib/child_labor.rb
@@ -1,3 +1,96 @@
module ChildLabor
- # Nothing here yet
+ def self.subprocess(cmd)
+ t = Task.new(cmd)
+ t.launch
+ return t unless block_given?
+ yield t
+ t.wait
+ t
+ ensure
+ t.close if block_given?
+ end
+
+ class Task
+ attr_reader :cmd
+
+ def initialize(cmd)
+ @cmd = cmd
+ @pid = nil
+ end
+
+ def launch
+ create_pipes
+
+ @pid = Process.fork
+
+ # child
+ if !@pid
+ @stdout.close
+ STDOUT.reopen @stdout_child
+
+ @stdin.close
+ STDIN.reopen @stdin_child
+
+ @stderr.close
+ STDERR.reopen @stderr_child
+
+ Process.exec cmd
+ end
+
+ @stdout_child.close
+ @stdin_child.close
+ @stderr_child.close
+
+ true
+ end
+
+ def launched?
+ @pid
+ end
+
+ def wait
+ Process.wait2 @pid
+ end
+
+ def read(length = nil, buffer = nil)
+ @stdout.read(length, buffer)
+ end
+
+ def read_stderr(length = nil, buffer = nil)
+ @stderr.read(length, buffer)
+ end
+
+ def write(str)
+ @stdin.write(str)
+ end
+
+ def close_read
+ @stdout.close if @stdout
+ @stdout = nil
+ end
+
+ def close_write
+ @stdin.close if @stdin
+ @stdin = nil
+ end
+
+ def close_stderr
+ @stderr.close if @stderr
+ @stderr = nil
+ end
+
+ def close
+ close_read
+ close_write
+ close_stderr
+ end
+
+ private
+
+ def create_pipes
+ @stdout, @stdout_child = IO.pipe
+ @stdin_child, @stdin = IO.pipe
+ @stderr, @stderr_child = IO.pipe
+ end
+ end
end
View
22 spec/spec_helper.rb
@@ -0,0 +1,22 @@
+require 'child_labor'
+require 'pathname'
+require 'fileutils'
+
+module PathHelpers
+ def root(*args)
+ Pathname.new("../../").expand_path(__FILE__).join(*args)
+ end
+
+ def tmp(*args)
+ root("tmp", *args)
+ end
+end
+
+Spec::Runner.configure do |c|
+ c.include PathHelpers
+
+ c.before :each do
+ FileUtils.rm_rf(tmp)
+ FileUtils.mkdir_p(tmp)
+ end
+end
View
30 spec/task_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe "ChildLabor.subprocess" do
+ it "runs the subprocess" do
+ ChildLabor.subprocess("echo 'hello world' > #{tmp}/hello_world.txt") { }
+ tmp("hello_world.txt").should exist
+ end
+
+ it "sets up STDOUT correctly" do
+ out = nil
+ ChildLabor.subprocess("echo 'hello world'") { |t| out = t.read }
+ out.should == "hello world\n"
+ end
+
+ it "sets up STDIN correctly" do
+ out = nil
+ ChildLabor.subprocess("cat") do |t|
+ t.write "hello world"
+ t.close_write
+ out = t.read
+ end
+ out.should == "hello world"
+ end
+
+ it "sets up STDERR correctly" do
+ out = nil
+ ChildLabor.subprocess("echo 'hello world' 1>&2") { |t| out = t.read_stderr }
+ out.should == "hello world\n"
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.