Class: RightGit::Shell::Default
- Inherits:
-
Object
- Object
- RightGit::Shell::Default
- Includes:
- Interface, RightSupport::Ruby::EasySingleton
- Defined in:
- lib/right_git/shell/default.rb
Overview
Default shell singleton implementation.
Instance Method Summary collapse
-
#clear_env_vars(names) { ... } ⇒ TrueClass
Clears (set-to-nil) the given list of environment variables while executing the given block.
-
#configure_executioner(executioner, options) ⇒ Proc
Encapsulates the given executioner with child-process-modifying behavior based on options.
-
#default_logger ⇒ Object
Delegates to the RightGit class logger.
-
#execute(cmd, options = {}) ⇒ Object
Implements execute interface.
-
#output_for(cmd, options = {}) ⇒ Object
Implements output_for interface.
-
#set_env_vars(variables) { ... } ⇒ TrueClass
Sets the given list of environment variables while executing the given block.
Instance Method Details
#clear_env_vars(names) { ... } ⇒ TrueClass
Clears (set-to-nil) the given list of environment variables while executing the given block.
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/right_git/shell/default.rb', line 236 def clear_env_vars(names, &block) save_vars = {} names.each do |k| k = k.to_s save_vars[k] = ENV[k] ENV[k] = nil end begin yield ensure names.each do |k| k = k.to_s ENV[k] = save_vars[k] end end true end |
#configure_executioner(executioner, options) ⇒ Proc
Encapsulates the given executioner with child-process-modifying behavior based on options. Builds the executioner as a series of callbacks.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/right_git/shell/default.rb', line 173 def configure_executioner(executioner, ) # set specific environment variables, if requested. sev = [:set_env_vars] if (sev && !sev.empty?) executioner = lambda do |e| lambda { set_env_vars(sev) { e.call } } end.call(executioner) end # clear specific environment variables, if requested. cev = [:clear_env_vars] if (cev && !cev.empty?) executioner = lambda do |e| lambda { clear_env_vars(cev) { e.call } } end.call(executioner) end # working directory. if directory = [:directory] executioner = lambda do |e, d| lambda { ::Dir.chdir(d) { e.call } } end.call(executioner, directory) end executioner end |
#default_logger ⇒ Object
Delegates to the RightGit class logger.
39 40 41 |
# File 'lib/right_git/shell/default.rb', line 39 def default_logger ::RightGit::Git::Repository.logger end |
#execute(cmd, options = {}) ⇒ Object
Implements execute interface.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/right_git/shell/default.rb', line 44 def execute(cmd, = {}) = { :directory => nil, :outstream => nil, :raise_on_failure => true, :set_env_vars => nil, :clear_env_vars => nil, :logger => default_logger, :timeout => nil, :keep_alive_interval => nil, :keep_alive_timeout => nil }.merge() outstream = [:outstream] logger = [:logger] if keep_alive_interval = [:keep_alive_interval] keep_alive_wake_time = ::Time.now + keep_alive_interval else keep_alive_wake_time = nil end if keep_alive_timeout = [:keep_alive_timeout] unless keep_alive_interval raise ::ArgumentError, ':keep_alive_interval is required when using :keep_alive_timeout' end keep_alive_stop_time = ::Time.now + keep_alive_timeout else keep_alive_stop_time = nil end # build initial popener. exitstatus = nil popener = lambda do |output| output.sync = true loop do # note stdout remains selectable after process dies. if (::IO.select([output], nil, nil, 0.1) rescue nil) if data = output.gets if outstream outstream << data else data = data.strip unless data.empty? logger.info(data) # reset keep alive timer whenever we have normal output. if keep_alive_wake_time keep_alive_wake_time = ::Time.now + keep_alive_interval end end end else break end elsif keep_alive_wake_time now = ::Time.now if keep_alive_stop_time && now >= keep_alive_stop_time keep_alive_wake_time = nil elsif now >= keep_alive_wake_time # keep-alives go to logger, not the outstream, if any. logger.info('.') keep_alive_wake_time = now + keep_alive_interval end now = nil end end end # timeout optionally wraps popener. the timeout must happen inside of the # IO.popen block or else it has no good effect. if timeout = [:timeout] popener = lambda do |p| lambda do |o| ::Timeout.timeout(timeout) { p.call(o) } end end.call(popener) end # build initial executioner in terms of popener. executioner = lambda do logger.info("+ #{cmd}") error_msg = nil ::IO.popen("#{cmd} 2>&1", 'r') do |output| begin popener.call(output) rescue ::EOFError # done rescue ::Timeout::Error # kill still-running process or else popen's ensure will hang. ::Process.kill('KILL', output.pid) # intentionally not reading last data as that could still block # due to a child of created process inheriting stdout. error_msg = "Execution timed out after #{[:timeout]} seconds." end end # note that a killed process may exit 0 under Windows. exitstatus = $?.exitstatus if 0 == exitstatus && error_msg exitstatus = 1 end if (exitstatus != 0 && [:raise_on_failure]) error_msg ||= "Execution failed with exitstatus #{exitstatus}" raise ShellError, error_msg end end # configure executioner (by options) and then invoke executioner. configure_executioner(executioner, ).call return exitstatus end |
#output_for(cmd, options = {}) ⇒ Object
Implements output_for interface.
160 161 162 163 164 |
# File 'lib/right_git/shell/default.rb', line 160 def output_for(cmd, = {}) output = StringIO.new execute(cmd, .merge(:outstream => output)) output.string end |
#set_env_vars(variables) { ... } ⇒ TrueClass
Sets the given list of environment variables while executing the given block.
Parameters
Yield
Return
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/right_git/shell/default.rb', line 210 def set_env_vars(variables) save_vars = {} variables.each do |k, v| k = k.to_s save_vars[k] = ENV[k] ENV[k] = v.nil? ? v : v.to_s end begin yield ensure variables.each_key do |k| k = k.to_s ENV[k] = save_vars[k] end end true end |