systemu-2.6.0/0000755000004100000410000000000012261224657013267 5ustar www-datawww-datasystemu-2.6.0/Rakefile0000644000004100000410000002272112261224657014740 0ustar www-datawww-dataThis.rubyforge_project = 'codeforpeople' This.author = "Ara T. Howard" This.email = "ara.t.howard@gmail.com" This.homepage = "https://github.com/ahoward/#{ This.lib }" task :license do open('LICENSE', 'w'){|fd| fd.puts "same as ruby's"} end task :default do puts((Rake::Task.tasks.map{|task| task.name.gsub(/::/,':')} - ['default']).sort) end task :test do run_tests! end namespace :test do task(:unit){ run_tests!(:unit) } task(:functional){ run_tests!(:functional) } task(:integration){ run_tests!(:integration) } end def run_tests!(which = nil) which ||= '**' test_dir = File.join(This.dir, "test") test_glob ||= File.join(test_dir, "#{ which }/**_test.rb") test_rbs = Dir.glob(test_glob).sort div = ('=' * 119) line = ('-' * 119) test_rbs.each_with_index do |test_rb, index| testno = index + 1 command = "#{ This.ruby } -I ./lib -I ./test/lib #{ test_rb }" puts say(div, :color => :cyan, :bold => true) say("@#{ testno } => ", :bold => true, :method => :print) say(command, :color => :cyan, :bold => true) say(line, :color => :cyan, :bold => true) system(command) say(line, :color => :cyan, :bold => true) status = $?.exitstatus if status.zero? say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print) say("SUCCESS", :color => :green, :bold => true) else say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print) say("FAILURE", :color => :red, :bold => true) end say(line, :color => :cyan, :bold => true) exit(status) unless status.zero? end end task :gemspec do ignore_extensions = ['git', 'svn', 'tmp', /sw./, 'bak', 'gem'] ignore_directories = ['pkg'] ignore_files = ['test/log', 'a.rb'] shiteless = lambda do |list| list.delete_if do |entry| next unless test(?e, entry) extension = File.basename(entry).split(%r/[.]/).last ignore_extensions.any?{|ext| ext === extension} end list.delete_if do |entry| next unless test(?d, entry) dirname = File.expand_path(entry) ignore_directories.any?{|dir| File.expand_path(dir) == dirname} end list.delete_if do |entry| next unless test(?f, entry) filename = File.expand_path(entry) ignore_files.any?{|file| File.expand_path(file) == filename} end end lib = This.lib object = This.object version = This.version files = shiteless[Dir::glob("**/**")] executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)} #has_rdoc = true #File.exist?('doc') test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb") summary = object.respond_to?(:summary) ? object.summary : "summary: #{ lib } kicks the ass" description = object.respond_to?(:description) ? object.description : "description: #{ lib } kicks the ass" if This.extensions.nil? This.extensions = [] extensions = This.extensions %w( Makefile configure extconf.rb ).each do |ext| extensions << ext if File.exists?(ext) end end extensions = [extensions].flatten.compact template = if test(?e, 'gemspec.erb') Template{ IO.read('gemspec.erb') } else Template { <<-__ ## #{ lib }.gemspec # Gem::Specification::new do |spec| spec.name = #{ lib.inspect } spec.version = #{ version.inspect } spec.platform = Gem::Platform::RUBY spec.summary = #{ lib.inspect } spec.description = #{ description.inspect } spec.license = "same as ruby's" spec.files =\n#{ files.sort.pretty_inspect } spec.executables = #{ executables.inspect } spec.require_path = "lib" spec.test_files = #{ test_files.inspect } ### spec.add_dependency 'lib', '>= version' #### spec.add_dependency 'map' spec.extensions.push(*#{ extensions.inspect }) spec.rubyforge_project = #{ This.rubyforge_project.inspect } spec.author = #{ This.author.inspect } spec.email = #{ This.email.inspect } spec.homepage = #{ This.homepage.inspect } end __ } end Fu.mkdir_p(This.pkgdir) gemspec = "#{ lib }.gemspec" open(gemspec, "w"){|fd| fd.puts(template)} This.gemspec = gemspec end task :gem => [:clean, :gemspec] do Fu.mkdir_p(This.pkgdir) before = Dir['*.gem'] cmd = "gem build #{ This.gemspec }" `#{ cmd }` after = Dir['*.gem'] gem = ((after - before).first || after.first) or abort('no gem!') Fu.mv(gem, This.pkgdir) This.gem = File.join(This.pkgdir, File.basename(gem)) end task :readme do samples = '' prompt = '~ > ' lib = This.lib version = This.version Dir['sample*/*'].sort.each do |sample| samples << "\n" << " <========< #{ sample } >========>" << "\n\n" cmd = "cat #{ sample }" samples << Util.indent(prompt + cmd, 2) << "\n\n" samples << Util.indent(`#{ cmd }`, 4) << "\n" cmd = "ruby #{ sample }" samples << Util.indent(prompt + cmd, 2) << "\n\n" cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -I ./lib #{ sample })'" samples << Util.indent(`#{ cmd } 2>&1`, 4) << "\n" end template = if test(?e, 'readme.erb') Template{ IO.read('readme.erb') } else Template { <<-__ NAME #{ lib } DESCRIPTION INSTALL gem install #{ lib } SAMPLES #{ samples } __ } end open("README", "w"){|fd| fd.puts template} end task :clean do Dir[File.join(This.pkgdir, '**/**')].each{|entry| Fu.rm_rf(entry)} end task :release => [:clean, :gemspec, :gem] do gems = Dir[File.join(This.pkgdir, '*.gem')].flatten raise "which one? : #{ gems.inspect }" if gems.size > 1 raise "no gems?" if gems.size < 1 cmd = "gem push #{ This.gem }" puts cmd puts system(cmd) abort("cmd(#{ cmd }) failed with (#{ $?.inspect })") unless $?.exitstatus.zero? cmd = "rubyforge login && rubyforge add_release #{ This.rubyforge_project } #{ This.lib } #{ This.version } #{ This.gem }" puts cmd puts system(cmd) abort("cmd(#{ cmd }) failed with (#{ $?.inspect })") unless $?.exitstatus.zero? end BEGIN { # support for this rakefile # $VERBOSE = nil require 'ostruct' require 'erb' require 'fileutils' require 'rbconfig' require 'pp' # fu shortcut # Fu = FileUtils # cache a bunch of stuff about this rakefile/environment # This = OpenStruct.new This.file = File.expand_path(__FILE__) This.dir = File.dirname(This.file) This.pkgdir = File.join(This.dir, 'pkg') # grok lib # lib = ENV['LIB'] unless lib lib = File.basename(Dir.pwd).sub(/[-].*$/, '') end This.lib = lib # grok version # version = ENV['VERSION'] unless version require "./lib/#{ This.lib }" This.name = lib.capitalize This.object = eval(This.name) version = This.object.send(:version) end This.version = version # we need to know the name of the lib an it's version # abort('no lib') unless This.lib abort('no version') unless This.version # discover full path to this ruby executable # c = begin; ::RbConfig::CONFIG; rescue NameError; ::Config::CONFIG; end bindir = c["bindir"] || c['BINDIR'] ruby_install_name = c['ruby_install_name'] || c['RUBY_INSTALL_NAME'] || 'ruby' ruby_ext = c['EXEEXT'] || '' ruby = File.join(bindir, (ruby_install_name + ruby_ext)) This.ruby = ruby # some utils # module Util def indent(s, n = 2) s = unindent(s) ws = ' ' * n s.gsub(%r/^/, ws) end def unindent(s) indent = nil s.each_line do |line| next if line =~ %r/^\s*$/ indent = line[%r/^\s*/] and break end indent ? s.gsub(%r/^#{ indent }/, "") : s end extend self end # template support # class Template def initialize(&block) @block = block @template = block.call.to_s end def expand(b=nil) ERB.new(Util.unindent(@template)).result((b||@block).binding) end alias_method 'to_s', 'expand' end def Template(*args, &block) Template.new(*args, &block) end # colored console output support # This.ansi = { :clear => "\e[0m", :reset => "\e[0m", :erase_line => "\e[K", :erase_char => "\e[P", :bold => "\e[1m", :dark => "\e[2m", :underline => "\e[4m", :underscore => "\e[4m", :blink => "\e[5m", :reverse => "\e[7m", :concealed => "\e[8m", :black => "\e[30m", :red => "\e[31m", :green => "\e[32m", :yellow => "\e[33m", :blue => "\e[34m", :magenta => "\e[35m", :cyan => "\e[36m", :white => "\e[37m", :on_black => "\e[40m", :on_red => "\e[41m", :on_green => "\e[42m", :on_yellow => "\e[43m", :on_blue => "\e[44m", :on_magenta => "\e[45m", :on_cyan => "\e[46m", :on_white => "\e[47m" } def say(phrase, *args) options = args.last.is_a?(Hash) ? args.pop : {} options[:color] = args.shift.to_s.to_sym unless args.empty? keys = options.keys keys.each{|key| options[key.to_s.to_sym] = options.delete(key)} color = options[:color] bold = options.has_key?(:bold) parts = [phrase] parts.unshift(This.ansi[color]) if color parts.unshift(This.ansi[:bold]) if bold parts.push(This.ansi[:clear]) if parts.size > 1 method = options[:method] || :puts Kernel.send(method, parts.join) end # always run out of the project dir # Dir.chdir(This.dir) } systemu-2.6.0/README.erb0000644000004100000410000000112612261224657014716 0ustar www-datawww-dataNAME systemu SYNOPSIS univeral capture of stdout and stderr and handling of child process pid for windows, *nix, etc. URIS http://github.com/ahoward/systemu http://rubyforge.org/projects/codeforpeople/ INSTALL gem install systemu HISTORY 2.0.0 - versioning issue. new gem release. 1.3.1 - updates for ruby 1.9.1 1.3.0 - move to github 1.2.0 - fixed handling of background thread management - needed Thread.current.abort_on_exception = true - fixed reporting of child pid, it was reported as the parent's pid before SAMPLES <%= samples %> systemu-2.6.0/README0000644000004100000410000000735312261224657014157 0ustar www-datawww-dataNAME systemu SYNOPSIS universal capture of stdout and stderr and handling of child process pid for windows, *nix, etc. URIS http://github.com/ahoward/systemu http://rubyforge.org/projects/codeforpeople/ INSTALL gem install systemu HISTORY 2.0.0 - versioning issue. new gem release. 1.3.1 - updates for ruby 1.9.1 1.3.0 - move to github 1.2.0 - fixed handling of background thread management - needed Thread.current.abort_on_exception = true - fixed reporting of child pid, it was reported as the parent's pid before SAMPLES <========< samples/a.rb >========> ~ > cat samples/a.rb # # systemu can be used on any platform to return status, stdout, and stderr of # any command. unlike other methods like open3/popen4 there is zero danger of # full pipes or threading issues hanging your process or subprocess. # require 'systemu' date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " ) status, stdout, stderr = systemu date p [ status, stdout, stderr ] ~ > ruby samples/a.rb [#, "2011-12-11 22:07:30 -0700\n", "2011-12-11 22:07:30 -0700\n"] <========< samples/b.rb >========> ~ > cat samples/b.rb # # quite a few keys can be passed to the command to alter it's behaviour. if # either stdout or stderr is supplied those objects should respond_to? '<<' # and only status will be returned # require 'systemu' date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " ) stdout, stderr = '', '' status = systemu date, 'stdout' => stdout, 'stderr' => stderr p [ status, stdout, stderr ] ~ > ruby samples/b.rb [#, "2011-12-11 22:07:30 -0700\n", "2011-12-11 22:07:30 -0700\n"] <========< samples/c.rb >========> ~ > cat samples/c.rb # # of course stdin can be supplied too. synonyms for 'stdin' include '0' and # 0. the other stdio streams have similar shortcuts # require 'systemu' cat = %q( ruby -e" ARGF.each{|line| puts line} " ) status = systemu cat, 0=>'the stdin for cat', 1=>stdout='' puts stdout ~ > ruby samples/c.rb the stdin for cat <========< samples/d.rb >========> ~ > cat samples/d.rb # # the cwd can be supplied # require 'systemu' require 'tmpdir' pwd = %q( ruby -e" STDERR.puts Dir.pwd " ) status = systemu pwd, 2=>(stderr=''), :cwd=>Dir.tmpdir puts stderr ~ > ruby samples/d.rb /private/var/folders/sp/nwtflj890qnb6z4b53dqxvlw0000gp/T <========< samples/e.rb >========> ~ > cat samples/e.rb # # any environment vars specified are merged into the child's environment # require 'systemu' env = %q( ruby -r yaml -e" puts ENV[ 'answer' ] " ) status = systemu env, 1=>stdout='', 'env'=>{ 'answer' => 0b101010 } puts stdout ~ > ruby samples/e.rb 42 <========< samples/f.rb >========> ~ > cat samples/f.rb # # if a block is specified then it is passed the child pid and run in a # background thread. note that this thread will __not__ be blocked during the # execution of the command so it may do useful work such as killing the child # if execution time passes a certain threshold # require 'systemu' looper = %q( ruby -e" loop{ STDERR.puts Time.now.to_i; sleep 1 } " ) status, stdout, stderr = systemu looper do |cid| sleep 3 Process.kill 9, cid end p status p stderr ~ > ruby samples/f.rb # "1323666451\n1323666452\n1323666453\n" systemu-2.6.0/systemu.gemspec0000644000004100000410000000161212261224657016345 0ustar www-datawww-data## systemu.gemspec # Gem::Specification::new do |spec| spec.name = "systemu" spec.version = "2.6.0" spec.platform = Gem::Platform::RUBY spec.summary = "systemu" spec.description = "description: systemu kicks the ass" spec.license = "same as ruby's" spec.files = ["LICENSE", "README", "README.erb", "Rakefile", "lib", "lib/systemu.rb", "samples", "samples/a.rb", "samples/b.rb", "samples/c.rb", "samples/d.rb", "samples/e.rb", "samples/f.rb", "systemu.gemspec", "test", "test/systemu_test.rb", "test/testing.rb"] spec.executables = [] spec.require_path = "lib" spec.test_files = nil ### spec.add_dependency 'lib', '>= version' #### spec.add_dependency 'map' spec.extensions.push(*[]) spec.rubyforge_project = "codeforpeople" spec.author = "Ara T. Howard" spec.email = "ara.t.howard@gmail.com" spec.homepage = "https://github.com/ahoward/systemu" end systemu-2.6.0/lib/0000755000004100000410000000000012261224657014035 5ustar www-datawww-datasystemu-2.6.0/lib/systemu.rb0000644000004100000410000002032112261224657016071 0ustar www-datawww-data# encoding: utf-8 require 'tmpdir' require 'socket' require 'fileutils' require 'rbconfig' require 'thread' class Object def systemu(*a, &b) SystemUniversal.new(*a, &b).systemu end end class SystemUniversal # # constants # SystemUniversal::VERSION = '2.6.0' unless SystemUniversal.send(:const_defined?, :VERSION) def SystemUniversal.version() SystemUniversal::VERSION end def version() SystemUniversal::VERSION end # # class methods # @host = Socket.gethostname @ppid = Process.ppid @pid = Process.pid @turd = ENV['SYSTEMU_TURD'] c = begin; ::RbConfig::CONFIG; rescue NameError; ::Config::CONFIG; end ruby = File.join(c['bindir'], c['ruby_install_name']) << c['EXEEXT'] @ruby = if system('%s -e 42' % ruby) ruby else system('%s -e 42' % 'ruby') ? 'ruby' : warn('no ruby in PATH/CONFIG') end class << SystemUniversal %w( host ppid pid ruby turd ).each{|a| attr_accessor a} def quote(*words) words.map{|word| word.inspect}.join(' ') end end # # instance methods # def initialize argv, opts = {}, &block getopt = getopts opts @argv = argv @block = block @stdin = getopt[ ['stdin', 'in', '0', 0] ] @stdout = getopt[ ['stdout', 'out', '1', 1] ] @stderr = getopt[ ['stderr', 'err', '2', 2] ] @env = getopt[ 'env' ] @cwd = getopt[ 'cwd' ] @host = getopt[ 'host', self.class.host ] @ppid = getopt[ 'ppid', self.class.ppid ] @pid = getopt[ 'pid', self.class.pid ] @ruby = getopt[ 'ruby', self.class.ruby ] end def systemu tmpdir do |tmp| c = child_setup tmp status = nil begin thread = nil quietly{ IO.popen "#{ quote(@ruby) } #{ quote(c['program']) }", 'rb+' do |pipe| line = pipe.gets case line when %r/^pid: \d+$/ cid = Integer line[%r/\d+/] else begin buf = pipe.read buf = "#{ line }#{ buf }" e = Marshal.load buf raise unless Exception === e raise e rescue raise "systemu: Error - process interrupted!\n#{ buf }\n" end end thread = new_thread cid, @block if @block pipe.read rescue nil end } status = $? ensure if thread begin class << status attr 'thread' end status.instance_eval{ @thread = thread } rescue 42 end end end if @stdout or @stderr open(c['stdout'], 'rb'){|f| relay f => @stdout} if @stdout open(c['stderr'], 'rb'){|f| relay f => @stderr} if @stderr status else [status, open(c['stdout'], 'rb'){|f| f.read}, open(c['stderr'], 'rb'){|f| f.read}] end end end def quote *args, &block SystemUniversal.quote(*args, &block) end def new_thread cid, block q = Queue.new Thread.new(cid) do |cid| current = Thread.current current.abort_on_exception = true q.push current block.call cid end q.pop end def child_setup tmp stdin = File.expand_path(File.join(tmp, 'stdin')) stdout = File.expand_path(File.join(tmp, 'stdout')) stderr = File.expand_path(File.join(tmp, 'stderr')) program = File.expand_path(File.join(tmp, 'program')) config = File.expand_path(File.join(tmp, 'config')) if @stdin open(stdin, 'wb'){|f| relay @stdin => f} else FileUtils.touch stdin end FileUtils.touch stdout FileUtils.touch stderr c = {} c['argv'] = @argv c['env'] = @env c['cwd'] = @cwd c['stdin'] = stdin c['stdout'] = stdout c['stderr'] = stderr c['program'] = program open(config, 'wb'){|f| Marshal.dump(c, f)} open(program, 'wb'){|f| f.write child_program(config)} c end def quietly v = $VERBOSE $VERBOSE = nil yield ensure $VERBOSE = v end def child_program config <<-program # encoding: utf-8 PIPE = STDOUT.dup begin config = Marshal.load(IO.read('#{ config }')) argv = config['argv'] env = config['env'] cwd = config['cwd'] stdin = config['stdin'] stdout = config['stdout'] stderr = config['stderr'] Dir.chdir cwd if cwd env.each{|k,v| ENV[k.to_s] = v.to_s} if env STDIN.reopen stdin STDOUT.reopen stdout STDERR.reopen stderr PIPE.puts "pid: \#{ Process.pid }" PIPE.flush ### the process is ready yo! PIPE.close exec *argv rescue Exception => e PIPE.write Marshal.dump(e) rescue nil exit 42 end program end def relay srcdst src, dst, ignored = srcdst.to_a.first if src.respond_to? 'read' while((buf = src.read(8192))); dst << buf; end else if src.respond_to?(:each_line) src.each_line{|buf| dst << buf} else src.each{|buf| dst << buf} end end end def slug_for(*args) options = args.last.is_a?(Hash) ? args.pop : {} join = (options[:join] || options['join'] || '_').to_s string = args.flatten.compact.join(join) words = string.to_s.scan(%r|[/\w]+|) words.map!{|word| word.gsub %r|[^/0-9a-zA-Z_-]|, ''} words.delete_if{|word| word.nil? or word.strip.empty?} words.join(join).downcase.gsub('/', (join * 2)) end def tmpdir d = Dir.tmpdir, max = 42, &b i = -1 and loop{ i += 1 tmp = File.join(d, slug_for("systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }")) begin Dir.mkdir tmp rescue Errno::EEXIST raise if i >= max next end break( if b begin b.call tmp ensure FileUtils.rm_rf tmp unless SystemU.turd end else tmp end ) } end def getopts opts = {} lambda do |*args| keys, default, ignored = args catch(:opt) do [keys].flatten.each do |key| [key, key.to_s, key.to_s.intern].each do |key| throw :opt, opts[key] if opts.has_key?(key) end end default end end end end # some monkeypatching for JRuby if defined? JRUBY_VERSION require 'jruby' java_import org.jruby.RubyProcess class SystemUniversal def systemu split_argv = JRuby::PathHelper.smart_split_command @argv process = java.lang.Runtime.runtime.exec split_argv.to_java(:string) stdout, stderr = [process.input_stream, process.error_stream].map do |stream| StreamReader.new(stream) end exit_code = process.wait_for field = process.get_class.get_declared_field("pid") field.set_accessible(true) pid = field.get(process) [ RubyProcess::RubyStatus.new_process_status(JRuby.runtime, exit_code, pid), stdout.join, stderr.join ] end class StreamReader def initialize(stream) @data = "" @thread = Thread.new do reader = java.io.BufferedReader.new java.io.InputStreamReader.new(stream) while line = reader.read_line @data << line << "\n" end end end def join @thread.join @data end end end end SystemU = SystemUniversal unless defined? SystemU Systemu = SystemUniversal unless defined? Systemu if $0 == __FILE__ # # date # date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " ) status, stdout, stderr = systemu date p [status, stdout, stderr] status = systemu date, 1=>(stdout = '') p [status, stdout] status = systemu date, 2=>(stderr = '') p [status, stderr] # # sleep # sleep = %q( ruby -e" p(sleep(1)) " ) status, stdout, stderr = systemu sleep p [status, stdout, stderr] sleep = %q( ruby -e" p(sleep(42)) " ) status, stdout, stderr = systemu(sleep){|cid| Process.kill 9, cid} p [status, stdout, stderr] # # env # env = %q( ruby -e" p ENV['A'] " ) status, stdout, stderr = systemu env, :env => {'A' => 42} p [status, stdout, stderr] # # cwd # env = %q( ruby -e" p Dir.pwd " ) status, stdout, stderr = systemu env, :cwd => Dir.tmpdir p [status, stdout, stderr] end systemu-2.6.0/samples/0000755000004100000410000000000012261224657014733 5ustar www-datawww-datasystemu-2.6.0/samples/d.rb0000644000004100000410000000027612261224657015510 0ustar www-datawww-data# # the cwd can be supplied # require 'systemu' require 'tmpdir' pwd = %q( ruby -e" STDERR.puts Dir.pwd " ) status = systemu pwd, 2=>(stderr=''), :cwd=>Dir.tmpdir puts stderr systemu-2.6.0/samples/b.rb0000644000004100000410000000062612261224657015505 0ustar www-datawww-data# # quite a few keys can be passed to the command to alter it's behaviour. if # either stdout or stderr is supplied those objects should respond_to? '<<' # and only status will be returned # require 'systemu' date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " ) stdout, stderr = '', '' status = systemu date, 'stdout' => stdout, 'stderr' => stderr p [ status, stdout, stderr ] systemu-2.6.0/samples/e.rb0000644000004100000410000000035612261224657015510 0ustar www-datawww-data# # any environment vars specified are merged into the child's environment # require 'systemu' env = %q( ruby -r yaml -e" puts ENV[ 'answer' ] " ) status = systemu env, 1=>stdout='', 'env'=>{ 'answer' => 0b101010 } puts stdout systemu-2.6.0/samples/a.rb0000644000004100000410000000061212261224657015477 0ustar www-datawww-data# # systemu can be used on any platform to return status, stdout, and stderr of # any command. unlike other methods like open3/popen4 there is zero danger of # full pipes or threading issues hanging your process or subprocess. # require 'systemu' date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " ) status, stdout, stderr = systemu date p [ status, stdout, stderr ] systemu-2.6.0/samples/c.rb0000644000004100000410000000043612261224657015505 0ustar www-datawww-data# # of course stdin can be supplied too. synonyms for 'stdin' include '0' and # 0. the other stdio streams have similar shortcuts # require 'systemu' cat = %q( ruby -e" ARGF.each{|line| puts line} " ) status = systemu cat, 0=>'the stdin for cat', 1=>stdout='' puts stdout systemu-2.6.0/samples/f.rb0000644000004100000410000000076212261224657015512 0ustar www-datawww-data# # if a block is specified then it is passed the child pid and run in a # background thread. note that this thread will __not__ be blocked during the # execution of the command so it may do useful work such as killing the child # if execution time passes a certain threshold # require 'systemu' looper = %q( ruby -e" loop{ STDERR.puts Time.now.to_i; sleep 1 } " ) status, stdout, stderr = systemu looper do |cid| sleep 3 Process.kill 9, cid end p status p stderr systemu-2.6.0/metadata.yml0000644000004100000410000000217512261224657015577 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: systemu version: !ruby/object:Gem::Version version: 2.6.0 platform: ruby authors: - Ara T. Howard autorequire: bindir: bin cert_chain: [] date: 2013-12-07 00:00:00.000000000 Z dependencies: [] description: ! 'description: systemu kicks the ass' email: ara.t.howard@gmail.com executables: [] extensions: [] extra_rdoc_files: [] files: - LICENSE - README - README.erb - Rakefile - lib/systemu.rb - samples/a.rb - samples/b.rb - samples/c.rb - samples/d.rb - samples/e.rb - samples/f.rb - systemu.gemspec - test/systemu_test.rb - test/testing.rb homepage: https://github.com/ahoward/systemu licenses: - same as ruby's metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: codeforpeople rubygems_version: 2.0.3 signing_key: specification_version: 4 summary: systemu test_files: [] systemu-2.6.0/test/0000755000004100000410000000000012261224657014246 5ustar www-datawww-datasystemu-2.6.0/test/testing.rb0000644000004100000410000001045312261224657016253 0ustar www-datawww-datarequire 'test/unit' testdir = File.expand_path(File.dirname(__FILE__)) rootdir = File.dirname(testdir) libdir = File.join(rootdir, 'lib') STDOUT.sync = true $:.unshift(testdir) unless $:.include?(testdir) $:.unshift(libdir) unless $:.include?(libdir) $:.unshift(rootdir) unless $:.include?(rootdir) class Testing class Slug < ::String def Slug.for(*args) string = args.flatten.compact.join('-') words = string.to_s.scan(%r/\w+/) words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''} words.delete_if{|word| word.nil? or word.strip.empty?} new(words.join('-').downcase) end end class Context attr_accessor :name def initialize(name, *args) @name = name end def to_s Slug.for(name) end end end def Testing(*args, &block) Class.new(::Test::Unit::TestCase) do ## class methods # class << self def contexts @contexts ||= [] end def context(*args, &block) return contexts.last if(args.empty? and block.nil?) context = Testing::Context.new(*args) contexts.push(context) begin block.call(context) ensure contexts.pop end end def slug_for(*args) string = [context, args].flatten.compact.join('-') words = string.to_s.scan(%r/\w+/) words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''} words.delete_if{|word| word.nil? or word.strip.empty?} words.join('-').downcase.sub(/_$/, '') end def name() const_get(:Name) end def testno() '%05d' % (@testno ||= 0) ensure @testno += 1 end def testing(*args, &block) method = ["test", testno, slug_for(*args)].delete_if{|part| part.empty?}.join('_') define_method(method, &block) end def test(*args, &block) testing(*args, &block) end def setup(&block) define_method(:setup, &block) if block end def teardown(&block) define_method(:teardown, &block) if block end def prepare(&block) @prepare ||= [] @prepare.push(block) if block @prepare end def cleanup(&block) @cleanup ||= [] @cleanup.push(block) if block @cleanup end end ## configure the subclass! # const_set(:Testno, '0') slug = slug_for(*args).gsub(%r/-/,'_') name = ['TESTING', '%03d' % const_get(:Testno), slug].delete_if{|part| part.empty?}.join('_') name = name.upcase! const_set(:Name, name) const_set(:Missing, Object.new.freeze) ## instance methods # alias_method('__assert__', 'assert') def assert(*args, &block) if args.size == 1 and args.first.is_a?(Hash) options = args.first expected = getopt(:expected, options){ missing } actual = getopt(:actual, options){ missing } if expected == missing and actual == missing actual, expected, *ignored = options.to_a.flatten end expected = expected.call() if expected.respond_to?(:call) actual = actual.call() if actual.respond_to?(:call) assert_equal(expected, actual) end if block label = "assert(#{ args.join(' ') })" result = nil assert_nothing_raised{ result = block.call } __assert__(result, label) result else result = args.shift label = "assert(#{ args.join(' ') })" __assert__(result, label) result end end def missing self.class.const_get(:Missing) end def getopt(opt, hash, options = nil, &block) [opt.to_s, opt.to_s.to_sym].each do |key| return hash[key] if hash.has_key?(key) end default = if block block.call else options.is_a?(Hash) ? options[:default] : nil end return default end def subclass_of exception class << exception def ==(other) super or self > other end end exception end ## # module_eval(&block) self.setup() self.prepare.each{|b| b.call()} at_exit{ self.teardown() self.cleanup.each{|b| b.call()} } self end end if $0 == __FILE__ Testing 'Testing' do testing('foo'){ assert true } test{ assert true } p instance_methods.grep(/test/) end end systemu-2.6.0/test/systemu_test.rb0000644000004100000410000000342212261224657017344 0ustar www-datawww-data Testing SystemU do ## # testing 'that simple usage works' do status, stdout, stderr = assert{ systemu :bin/:ls } assert{ status == 0 } assert{ stdout['lib'] } assert{ stderr.strip.empty? } end testing 'program with stdin' do stdin = '42' status, stdout, stderr = assert{ systemu :bin/:cat, :stdin => stdin } assert{ status == 0 } assert{ stdout == stdin } end testing 'silly hostnames' do host = SystemU.instance_variable_get('@host') silly_hostname = "silly's hostname with spaces" begin SystemU.instance_variable_set('@host', silly_hostname) assert{ SystemU.instance_variable_get('@host') == silly_hostname } stdin = '42' status, stdout, stderr = assert{ systemu :bin/:cat, :stdin => stdin } assert{ status == 0 } ensure assert{ SystemU.instance_variable_set('@host', host) } end end end BEGIN { # silly hax to build commands we can shell out to on any platform. since # tests might run on windoze we assume only that 'ruby' is available and build # other command-line programs from it. # module Kernel private def bin(which, options = {}, &block) case which.to_s when 'ls' %| ruby -e'puts Dir.glob("*").sort' | when 'cat' %| ruby -e'STDOUT.write(ARGF.read)' | when 'find' %| ruby -e'puts Dir.glob("**/**").sort' | end end end # just let's us write: :bin/:ls # class Symbol def / other, options = {}, &block eval "#{ self }(:#{ other }, options, &block)" end end testdir = File.dirname(File.expand_path(__FILE__)) rootdir = File.dirname(testdir) libdir = File.join(rootdir, 'lib') require File.join(libdir, 'systemu') require File.join(testdir, 'testing') Dir.chdir(rootdir) } systemu-2.6.0/LICENSE0000644000004100000410000000007012261224657014271 0ustar www-datawww-datasame as Ruby's http://www.ruby-lang.org/en/LICENSE.txt systemu-2.6.0/checksums.yaml.gz0000444000004100000410000000065112261224657016557 0ustar www-datawww-dataRO0)ܽxCƁa#hniR<=,Ǣ,= {36ӗ= )x>ގ_/5Fo L(RC 3;.Grc=Cӥ[-%h\ բ*@PVw0C|'X&]AlI*C2dk^P*Ya7q< :iKM[ wj 6Sd044*ǒlOưTm 5 gs`(4"=זB肨 ,nl,џxEC,_V:i ԉRUάyuC9QK\-qvOT