OSDN Git Service

Replaced mongrel with thin
[redminele/redminele.git] / ruby / lib / ruby / gems / 1.8 / gems / eventmachine-0.12.10-x86-mswin32-60 / lib / em / processes.rb
1 #--
2 #
3 # Author:: Francis Cianfrocca (gmail: blackhedd)
4 # Homepage::  http://rubyeventmachine.com
5 # Date:: 13 Dec 07
6
7 # See EventMachine and EventMachine::Connection for documentation and
8 # usage examples.
9 #
10 #----------------------------------------------------------------------------
11 #
12 # Copyright (C) 2006-08 by Francis Cianfrocca. All Rights Reserved.
13 # Gmail: blackhedd
14
15 # This program is free software; you can redistribute it and/or modify
16 # it under the terms of either: 1) the GNU General Public License
17 # as published by the Free Software Foundation; either version 2 of the
18 # License, or (at your option) any later version; or 2) Ruby's License.
19
20 # See the file COPYING for complete licensing information.
21 #
22 #---------------------------------------------------------------------------
23 #
24
25
26
27 module EventMachine
28
29   # EM::DeferrableChildProcess is a sugaring of a common use-case
30   # involving EM::popen.
31   # Call the #open method on EM::DeferrableChildProcess, passing
32   # a command-string. #open immediately returns an EM::Deferrable
33   # object. It also schedules the forking of a child process, which
34   # will execute the command passed to #open.
35   # When the forked child terminates, the Deferrable will be signalled
36   # and execute its callbacks, passing the data that the child process
37   # wrote to stdout.
38   #
39   class DeferrableChildProcess < EventMachine::Connection
40     include EventMachine::Deferrable
41
42     def initialize # :nodoc:
43       super
44       @data = []
45     end
46
47     # Sugars a common use-case involving forked child processes.
48     # #open takes a String argument containing an shell command
49     # string (including arguments if desired). #open immediately
50     # returns an EventMachine::Deferrable object, without blocking.
51     #
52     # It also invokes EventMachine#popen to run the passed-in
53     # command in a forked child process.
54     #
55     # When the forked child terminates, the Deferrable that
56     # #open calls its callbacks, passing the data returned
57     # from the child process.
58     #
59     def self.open cmd
60       EventMachine.popen( cmd, DeferrableChildProcess )
61     end
62
63     def receive_data data # :nodoc:
64       @data << data
65     end
66
67     def unbind # :nodoc:
68       succeed( @data.join )
69     end
70   end
71
72   class SystemCmd < EventMachine::Connection # :nodoc:
73     def initialize cb
74       @cb = cb
75       @output = []
76     end
77     def receive_data data
78       @output << data
79     end
80     def unbind
81       @cb.call @output.join(''), get_status if @cb
82     end
83   end
84
85   # EM::system is a simple wrapper for EM::popen. It is similar to Kernel::system, but requires a
86   # single string argument for the command and performs no shell expansion.
87   #
88   # The block or proc passed to EM::system is called with two arguments: the output generated by the command,
89   # and a Process::Status that contains information about the command's execution.
90   #
91   #  EM.run{
92   #    EM.system('ls'){ |output,status| puts output if status.exitstatus == 0 }
93   #  }
94   #
95   # You can also supply an additional proc to send some data to the process:
96   #
97   #  EM.run{
98   #    EM.system('sh', proc{ |process|
99   #      process.send_data("echo hello\n")
100   #      process.send_data("exit\n")
101   #    }, proc{ |out,status|
102   #      puts(out)
103   #    })
104   #  }
105   #
106   # Like EventMachine.popen, EventMachine.system currently does not work on windows.
107   # It returns the pid of the spawned process.
108   def EventMachine::system cmd, *args, &cb
109     cb ||= args.pop if args.last.is_a? Proc
110     init = args.pop if args.last.is_a? Proc
111
112     # merge remaining arguments into the command
113     cmd = ([cmd] + args.map{|a|a.to_s.dump}).join(' ')
114
115     EM.get_subprocess_pid(EM.popen(cmd, SystemCmd, cb) do |c|
116       init[c] if init
117     end.signature)
118   end
119 end