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.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/right_git/shell/default.rb', line 201 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.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/right_git/shell/default.rb', line 138 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.
38 39 40 |
# File 'lib/right_git/shell/default.rb', line 38 def default_logger ::RightGit::Git::Repository.logger end |
#execute(cmd, options = {}) ⇒ Object
Implements execute interface.
43 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 |
# File 'lib/right_git/shell/default.rb', line 43 def execute(cmd, = {}) = { :directory => nil, :outstream => nil, :raise_on_failure => true, :set_env_vars => nil, :clear_env_vars => nil, :logger => default_logger, :timeout => nil, }.merge() outstream = [:outstream] logger = [:logger] # 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 logger.info(data) unless data.empty? end else break end 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.
125 126 127 128 129 |
# File 'lib/right_git/shell/default.rb', line 125 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
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/right_git/shell/default.rb', line 175 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 |