git_reflow 0.9.0 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/multi-ruby-tests.yml +24 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +109 -10
- data/Gemfile.lock +140 -66
- data/README.md +9 -5
- data/Rakefile +8 -1
- data/Workflow +3 -0
- data/exe/git-reflow +5 -0
- data/git_reflow.gemspec +28 -26
- data/lib/git_reflow/config.rb +30 -4
- data/lib/git_reflow/git_server/git_hub.rb +53 -40
- data/lib/git_reflow/git_server/git_hub/pull_request.rb +22 -6
- data/lib/git_reflow/git_server/pull_request.rb +15 -1
- data/lib/git_reflow/rspec/command_line_helpers.rb +17 -8
- data/lib/git_reflow/sandbox.rb +15 -6
- data/lib/git_reflow/version.rb +1 -1
- data/lib/git_reflow/workflow.rb +31 -4
- data/spec/fixtures/authentication_failure.json +3 -0
- data/spec/fixtures/users/user.json +32 -0
- data/spec/lib/git_reflow/git_server/git_hub/pull_request_spec.rb +1 -1
- data/spec/lib/git_reflow/git_server/git_hub_spec.rb +77 -3
- data/spec/lib/git_reflow/git_server/pull_request_spec.rb +33 -5
- data/spec/lib/git_reflow/workflow_spec.rb +69 -3
- data/spec/lib/git_reflow_spec.rb +0 -1
- data/spec/spec_helper.rb +1 -1
- metadata +58 -40
- data/circle.yml +0 -26
data/README.md
CHANGED
@@ -4,8 +4,8 @@
|
|
4
4
|
</h1>
|
5
5
|
|
6
6
|
<p>
|
7
|
-
<a href="https://
|
8
|
-
<img alt="
|
7
|
+
<a href="https://actions-badge.atrox.dev/reenhanced/gitreflow/goto?ref=master" title="git workflow">
|
8
|
+
<img alt="Git workflow powered by git-reflow" src="https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Freenhanced%2Fgitreflow%2Fbadge%3Fref%3Dmaster&style=flat">
|
9
9
|
</a>
|
10
10
|
<a href="https://github.com/reenhanced/gitreflow" title="git workflow">
|
11
11
|
<img alt="Git workflow powered by git-reflow" src="https://img.shields.io/badge/git--reflow-v0.9.0-blue.svg?style=flat">
|
@@ -443,11 +443,15 @@ If the review is done, it's time to merge. Here's what happens:
|
|
443
443
|
|
444
444
|
In order to streamline delivery you can set the following git config to:
|
445
445
|
|
446
|
-
1. always clean up the feature branch after the PR is merged
|
446
|
+
1. always clean up the remote feature branch after the PR is merged
|
447
447
|
```
|
448
|
-
git config --global --add "reflow.always-cleanup" "true"
|
448
|
+
git config --global --add "reflow.always-cleanup-remote" "true"
|
449
449
|
```
|
450
|
-
2. always
|
450
|
+
2. always clean up the local feature branch after the PR is merged
|
451
|
+
```
|
452
|
+
git config --global --add "reflow.always-cleanup-local" "true"
|
453
|
+
```
|
454
|
+
3. always deliver without further prompt
|
451
455
|
```
|
452
456
|
git config --global --add "reflow.always-deliver" "true"
|
453
457
|
```
|
data/Rakefile
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
2
|
require "bundler/gem_tasks"
|
3
3
|
require "rspec/core/rake_task"
|
4
|
+
require "github_changelog_generator/task"
|
4
5
|
|
5
6
|
RSpec::Core::RakeTask.new(:spec)
|
6
7
|
|
7
|
-
|
8
|
+
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
9
|
+
config.user = 'reenhanced'
|
10
|
+
config.project = 'gitreflow'
|
11
|
+
config.since_tag = 'v0.9.2'
|
12
|
+
config.future_release = 'master'
|
13
|
+
end
|
8
14
|
|
15
|
+
task :default => :spec
|
data/Workflow
ADDED
data/exe/git-reflow
CHANGED
@@ -9,6 +9,11 @@ if reflow_command.nil? || GitReflow.workflow.commands[reflow_command.to_sym].nil
|
|
9
9
|
elsif ARGV.include? "--help"
|
10
10
|
GitReflow.documentation_for_command(reflow_command)
|
11
11
|
else
|
12
|
+
trap 'INT' do
|
13
|
+
GitReflow.say "Aborted.", :error
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
12
17
|
command_options = GitReflow.parse_command_options!(reflow_command)
|
13
18
|
GitReflow.logger.debug "Running command `#{reflow_command}` with options: #{command_options.inspect}"
|
14
19
|
GitReflow.public_send(reflow_command.to_sym, command_options)
|
data/git_reflow.gemspec
CHANGED
@@ -1,38 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Ensure we require the local version and not one we might have installed already
|
2
|
-
require File.join([File.dirname(__FILE__),'lib','git_reflow/version.rb'])
|
4
|
+
require File.join([File.dirname(__FILE__), 'lib', 'git_reflow/version.rb'])
|
3
5
|
Gem::Specification.new do |s|
|
4
|
-
s.name
|
5
|
-
s.version
|
6
|
-
s.license
|
7
|
-
s.authors
|
8
|
-
s.email
|
9
|
-
s.homepage
|
10
|
-
s.summary
|
11
|
-
s.description
|
12
|
-
s.platform
|
13
|
-
s.files
|
14
|
-
s.test_files
|
15
|
-
s.executables
|
16
|
-
s.
|
17
|
-
s.
|
18
|
-
s.
|
19
|
-
s.rdoc_options << '--title' << 'git_reflow' << '-ri'
|
6
|
+
s.name = 'git_reflow'
|
7
|
+
s.version = GitReflow::VERSION
|
8
|
+
s.license = 'MIT'
|
9
|
+
s.authors = ['Valentino Stoll', 'Robert Stern', 'Nicholas Hance']
|
10
|
+
s.email = ['dev@reenhanced.com']
|
11
|
+
s.homepage = 'http://github.com/reenhanced/gitreflow'
|
12
|
+
s.summary = 'A better git process'
|
13
|
+
s.description = 'Git Reflow manages your git workflow.'
|
14
|
+
s.platform = Gem::Platform::RUBY
|
15
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
s.bindir = 'exe'
|
19
|
+
s.require_paths = ['lib']
|
20
|
+
s.rdoc_options << '--title' << 'git_reflow' << '-ri'
|
20
21
|
|
21
|
-
s.add_development_dependency('appraisal', '2.
|
22
|
-
s.add_development_dependency('bundler', "~> 1.16")
|
22
|
+
s.add_development_dependency('appraisal', '2.4.0')
|
23
23
|
s.add_development_dependency('chronic')
|
24
|
-
s.add_development_dependency('
|
25
|
-
s.add_development_dependency('
|
24
|
+
s.add_development_dependency('github_changelog_generator')
|
25
|
+
s.add_development_dependency('ruby_jard')
|
26
|
+
s.add_development_dependency('rake', '~> 13.0.3')
|
26
27
|
s.add_development_dependency('rdoc')
|
27
|
-
s.add_development_dependency('rspec',
|
28
|
+
s.add_development_dependency('rspec', '~> 3.10')
|
28
29
|
s.add_development_dependency('webmock')
|
29
|
-
s.add_development_dependency('wwtd', '1.
|
30
|
+
s.add_development_dependency('wwtd', '1.4')
|
30
31
|
|
31
|
-
s.add_dependency('
|
32
|
+
s.add_dependency('bundler', '>= 1.10.0')
|
33
|
+
s.add_dependency('codenamev_bitbucket_api', '0.4.1')
|
34
|
+
s.add_dependency('colorize', '>= 0.8.1')
|
35
|
+
s.add_dependency('github_api', '0.19')
|
32
36
|
s.add_dependency('highline')
|
33
37
|
s.add_dependency('httpclient')
|
34
|
-
s.add_dependency('github_api', '0.18.2')
|
35
|
-
s.add_dependency('reenhanced_bitbucket_api', '0.3.2')
|
36
38
|
|
37
39
|
s.post_install_message = "You need to setup your GitHub OAuth token\nPlease run 'git-reflow setup'"
|
38
40
|
end
|
data/lib/git_reflow/config.rb
CHANGED
@@ -7,7 +7,14 @@ module GitReflow
|
|
7
7
|
|
8
8
|
module_function
|
9
9
|
|
10
|
-
|
10
|
+
# Gets the reqested git configuration variable.
|
11
|
+
#
|
12
|
+
# @param [String] key The key to get the value(s) for
|
13
|
+
# @option options [Boolean] :reload (false) whether to reload the value or use a cached value if available
|
14
|
+
# @option options [Boolean] :all (false) whether to return all keys for a multi-valued key
|
15
|
+
# @option options [Boolean] :local (false) whether to get the value specific to the current project
|
16
|
+
# @return the value of the git configuration
|
17
|
+
def get(key, reload: false, all: false, local: false, **_other_options)
|
11
18
|
return cached_git_config_value(key) unless reload || cached_git_config_value(key).empty?
|
12
19
|
|
13
20
|
local = local ? '--local ' : ''
|
@@ -19,7 +26,13 @@ module GitReflow
|
|
19
26
|
cache_git_config_key(key, new_value)
|
20
27
|
end
|
21
28
|
|
22
|
-
|
29
|
+
# Sets the reqested git configuration variable.
|
30
|
+
#
|
31
|
+
# @param [String] key The key to set the value for
|
32
|
+
# @param [String] value The value to set it to
|
33
|
+
# @option options [Boolean] :local (false) whether to set the value specific to the current project
|
34
|
+
# @return the value of the git configuration
|
35
|
+
def set(key, value, local: false, **_other_options)
|
23
36
|
value = value.to_s.strip
|
24
37
|
if local
|
25
38
|
GitReflow::Sandbox.run "git config --replace-all #{key} \"#{value}\"", loud: false, blocking: false
|
@@ -28,7 +41,13 @@ module GitReflow
|
|
28
41
|
end
|
29
42
|
end
|
30
43
|
|
31
|
-
|
44
|
+
# Remove values of the reqested git configuration variable.
|
45
|
+
#
|
46
|
+
# @param [String] key The key to remove
|
47
|
+
# @option options [Boolean] :value (nil) The value of the key to remove
|
48
|
+
# @option options [Boolean] :local (false) whether to remove the value specific to the current project
|
49
|
+
# @return the result of running the git command
|
50
|
+
def unset(key, value: nil, local: false, **_other_options)
|
32
51
|
value = value.nil? ? '' : "\"#{value}\""
|
33
52
|
if local
|
34
53
|
GitReflow::Sandbox.run "git config --unset-all #{key} #{value}", loud: false, blocking: false
|
@@ -37,7 +56,14 @@ module GitReflow
|
|
37
56
|
end
|
38
57
|
end
|
39
58
|
|
40
|
-
|
59
|
+
# Adds a new git configuration variable.
|
60
|
+
#
|
61
|
+
# @param [String] key The new key to set the value for
|
62
|
+
# @param [String] value The value to set it to
|
63
|
+
# @option options [Boolean] :local (false) whether to set the value specific to the current project
|
64
|
+
# @option options [Boolean] :global (false) whether to set the value globaly. if neither local or global is set gitreflow will default to using a configuration file
|
65
|
+
# @return the result of running the git command
|
66
|
+
def add(key, value, local: false, global: false, **_other_options)
|
41
67
|
if global
|
42
68
|
GitReflow::Sandbox.run "git config --global --add #{key} \"#{value}\"", loud: false, blocking: false
|
43
69
|
elsif local
|
@@ -84,56 +84,69 @@ module GitReflow
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def authenticate(options = {silent: false})
|
87
|
+
if !options[:user].to_s.empty?
|
88
|
+
self.class.user = options[:user]
|
89
|
+
elsif self.class.user.empty?
|
90
|
+
self.class.user = ask("Please enter your GitHub username: ")
|
91
|
+
end
|
92
|
+
|
87
93
|
if connection and self.class.oauth_token.length > 0
|
88
|
-
unless options[:silent]
|
89
|
-
GitReflow.say "Your GitHub account was already setup with: "
|
90
|
-
GitReflow.say "\tUser Name: #{self.class.user}"
|
91
|
-
GitReflow.say "\tEndpoint: #{self.class.api_endpoint}"
|
92
|
-
end
|
93
|
-
else
|
94
94
|
begin
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
config.endpoint = GitServer::GitHub.api_endpoint
|
101
|
-
config.site = GitServer::GitHub.site_url
|
102
|
-
config.adapter = :net_http
|
95
|
+
connection.users.get
|
96
|
+
unless options[:silent]
|
97
|
+
GitReflow.say "Your GitHub account was already setup with: "
|
98
|
+
GitReflow.say "\tUser Name: #{self.class.user}"
|
99
|
+
GitReflow.say "\tEndpoint: #{self.class.api_endpoint}"
|
103
100
|
end
|
101
|
+
return connection
|
102
|
+
rescue ::Github::Error::Unauthorized => e
|
103
|
+
GitReflow.logger.debug "[GitHub Error] Current oauth-token is invalid or expired..."
|
104
|
+
end
|
105
|
+
end
|
104
106
|
|
105
|
-
|
107
|
+
begin
|
108
|
+
gh_password = options[:password] || ask("Please enter your GitHub password (we do NOT store this): ") { |q| q.echo = false }
|
106
109
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
else
|
114
|
-
authorization = @connection.oauth.create scopes: ['repo'], note: "git-reflow (#{run('hostname', loud: false).strip})"
|
115
|
-
end
|
110
|
+
@connection = ::Github.new do |config|
|
111
|
+
config.basic_auth = "#{self.class.user}:#{gh_password}"
|
112
|
+
config.endpoint = GitServer::GitHub.api_endpoint
|
113
|
+
config.site = GitServer::GitHub.site_url
|
114
|
+
config.adapter = :net_http
|
115
|
+
end
|
116
116
|
|
117
|
-
|
117
|
+
@connection.connection_options = {headers: {"X-GitHub-OTP" => options[:two_factor_auth_code]}} if options[:two_factor_auth_code]
|
118
118
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
119
|
+
previous_authorizations = @connection.oauth.all.select {|auth| auth.note == "git-reflow (#{run('hostname', loud: false).strip})" }
|
120
|
+
if previous_authorizations.any?
|
121
|
+
authorization = previous_authorizations.last
|
122
|
+
GitReflow.say "You have previously setup git-reflow on this machine, but we can no longer find the stored token.", :error
|
123
|
+
GitReflow.say "Please visit https://github.com/settings/tokens and delete the token for: git-reflow (#{run('hostname', loud: false).strip})", :notice
|
124
|
+
raise "Setup could not be completed."
|
125
|
+
else
|
126
|
+
authorization = @connection.oauth.create scopes: ['repo'], note: "git-reflow (#{run('hostname', loud: false).strip})"
|
127
|
+
end
|
128
|
+
|
129
|
+
self.class.oauth_token = authorization.token
|
130
|
+
|
131
|
+
rescue ::Github::Error::Unauthorized => e
|
132
|
+
if e.inspect.to_s.include?('two-factor')
|
133
|
+
begin
|
134
|
+
# dummy request to trigger a 2FA SMS since a HTTP GET won't do it
|
135
|
+
@connection.oauth.create scopes: ['repo'], note: "thank Github for not making this straightforward"
|
136
|
+
rescue ::Github::Error::Unauthorized
|
137
|
+
ensure
|
138
|
+
two_factor_code = ask("Please enter your two-factor authentication code: ")
|
139
|
+
self.authenticate options.merge({user: self.class.user, password: gh_password, two_factor_auth_code: two_factor_code})
|
131
140
|
end
|
132
|
-
rescue StandardError => e
|
133
|
-
raise "We were unable to authenticate with Github."
|
134
141
|
else
|
135
|
-
GitReflow.say "
|
142
|
+
GitReflow.say "Github Authentication Error: #{e.inspect}", :error
|
143
|
+
raise "Setup could not be completed."
|
136
144
|
end
|
145
|
+
rescue StandardError => e
|
146
|
+
raise "We were unable to authenticate with Github."
|
147
|
+
else
|
148
|
+
GitReflow.say "Your GitHub account was successfully setup!", :success
|
149
|
+
|
137
150
|
end
|
138
151
|
|
139
152
|
@connection
|
@@ -24,8 +24,18 @@ module GitReflow
|
|
24
24
|
base: options[:base]))
|
25
25
|
end
|
26
26
|
|
27
|
-
def self.find_open(
|
28
|
-
|
27
|
+
def self.find_open(options = {})
|
28
|
+
options[:to] ||= 'master'
|
29
|
+
options[:from] ||= GitReflow.git_server.class.current_branch
|
30
|
+
|
31
|
+
matching_pull = GitReflow.git_server.connection.pull_requests.all(
|
32
|
+
GitReflow.remote_user,
|
33
|
+
GitReflow.remote_repo_name,
|
34
|
+
base: options[:to],
|
35
|
+
head: "#{GitReflow.remote_user}:#{options[:from]}",
|
36
|
+
state: 'open'
|
37
|
+
).first
|
38
|
+
|
29
39
|
if matching_pull
|
30
40
|
self.new matching_pull
|
31
41
|
end
|
@@ -147,13 +157,19 @@ module GitReflow
|
|
147
157
|
GitReflow.run_command_with_label "git pull origin #{self.base_branch_name}"
|
148
158
|
GitReflow.say "Pull request ##{self.number} successfully merged.", :success
|
149
159
|
|
150
|
-
if
|
151
|
-
GitReflow.run_command_with_label "git push origin :#{self.feature_branch_name}"
|
160
|
+
if cleanup_remote_feature_branch?
|
161
|
+
GitReflow.run_command_with_label "git push origin :#{self.feature_branch_name}", blocking: false
|
162
|
+
else
|
163
|
+
GitReflow.say "Skipped. Remote feature branch #{self.feature_branch_name} left in tact."
|
164
|
+
end
|
165
|
+
|
166
|
+
if cleanup_local_feature_branch?
|
152
167
|
GitReflow.run_command_with_label "git branch -D #{self.feature_branch_name}"
|
153
|
-
GitReflow.say "Nice job buddy."
|
154
168
|
else
|
155
|
-
|
169
|
+
GitReflow.say "Skipped. Local feature branch #{self.feature_branch_name} left in tact."
|
156
170
|
end
|
171
|
+
|
172
|
+
GitReflow.say "Nice job buddy."
|
157
173
|
else
|
158
174
|
GitReflow.say merge_response.to_s, :deliver_halted
|
159
175
|
GitReflow.say "There were problems commiting your feature... please check the errors above and try again.", :error
|
@@ -178,7 +178,21 @@ module GitReflow
|
|
178
178
|
end
|
179
179
|
|
180
180
|
def cleanup_feature_branch?
|
181
|
-
|
181
|
+
cleanup_local_feature_branch? || cleanup_remote_feature_branch?
|
182
|
+
end
|
183
|
+
|
184
|
+
def cleanup_local_feature_branch?
|
185
|
+
# backwards compat
|
186
|
+
always_cleanup_local = GitReflow::Config.get('reflow.always-cleanup').to_s
|
187
|
+
always_cleanup_local = GitReflow::Config.get('reflow.always-cleanup-local') if always_cleanup_local.empty?
|
188
|
+
always_cleanup_local == "true" || (ask "Would you like to cleanup your local feature branch? ") =~ /^y/i
|
189
|
+
end
|
190
|
+
|
191
|
+
def cleanup_remote_feature_branch?
|
192
|
+
# backwards compat
|
193
|
+
always_cleanup_remote = GitReflow::Config.get('reflow.always-cleanup').to_s
|
194
|
+
always_cleanup_remote = GitReflow::Config.get('reflow.always-cleanup-remote') if always_cleanup_remote.empty?
|
195
|
+
always_cleanup_remote == "true" || (ask "Would you like to cleanup your remote feature branch? ") =~ /^y/i
|
182
196
|
end
|
183
197
|
|
184
198
|
def deliver?
|
@@ -7,6 +7,7 @@ module GitReflow
|
|
7
7
|
def stub_command_line
|
8
8
|
$commands_ran = []
|
9
9
|
$stubbed_commands = {}
|
10
|
+
$stubbed_runners = Set.new
|
10
11
|
$output = []
|
11
12
|
$says = []
|
12
13
|
|
@@ -33,6 +34,7 @@ module GitReflow
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def stub_run_for(module_to_stub)
|
37
|
+
$stubbed_runners << module_to_stub
|
36
38
|
allow(module_to_stub).to receive(:run) do |command, options|
|
37
39
|
options = { loud: true, blocking: true }.merge(options || {})
|
38
40
|
$commands_ran << Hashie::Mash.new(command: command, options: options)
|
@@ -52,24 +54,31 @@ module GitReflow
|
|
52
54
|
$says = []
|
53
55
|
end
|
54
56
|
|
55
|
-
def stub_command(command,
|
57
|
+
def stub_command(command:, return_value: "", options: {})
|
56
58
|
$stubbed_commands[command] = return_value
|
57
|
-
|
59
|
+
$stubbed_runners.each do |runner|
|
60
|
+
allow(runner).to receive(:run).with(command, options) do |command, options|
|
61
|
+
options = { loud: true, blocking: true }.merge(options || {})
|
62
|
+
$commands_ran << Hashie::Mash.new(command: command, options: options)
|
63
|
+
$stubbed_commands[command] = return_value
|
64
|
+
raise GitReflow::Sandbox::CommandError.new(return_value, "\"#{command}\" failed to run.") if options[:raise]
|
65
|
+
end
|
66
|
+
end
|
58
67
|
end
|
59
68
|
|
60
69
|
def stub_command_line_inputs_for(module_to_stub, inputs)
|
61
70
|
allow(module_to_stub).to receive(:ask) do |terminal, question|
|
62
|
-
|
63
|
-
|
64
|
-
|
71
|
+
return_value = inputs[question]
|
72
|
+
question = ""
|
73
|
+
return_value
|
65
74
|
end
|
66
75
|
end
|
67
76
|
|
68
77
|
def stub_command_line_inputs(inputs)
|
69
78
|
allow_any_instance_of(HighLine).to receive(:ask) do |terminal, question|
|
70
|
-
|
71
|
-
|
72
|
-
|
79
|
+
return_value = inputs[question]
|
80
|
+
question = ""
|
81
|
+
return_value
|
73
82
|
end
|
74
83
|
end
|
75
84
|
|
data/lib/git_reflow/sandbox.rb
CHANGED
@@ -12,8 +12,16 @@ module GitReflow
|
|
12
12
|
plain: :white
|
13
13
|
}
|
14
14
|
|
15
|
+
class CommandError < StandardError;
|
16
|
+
attr_reader :output
|
17
|
+
def initialize(output, *args)
|
18
|
+
@output = output
|
19
|
+
super(*args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
15
23
|
def run(command, options = {})
|
16
|
-
options = { loud: true, blocking: true }.merge(options)
|
24
|
+
options = { loud: true, blocking: true, raise: false }.merge(options)
|
17
25
|
|
18
26
|
GitReflow.logger.debug "Running... #{command}"
|
19
27
|
|
@@ -22,12 +30,13 @@ module GitReflow
|
|
22
30
|
else
|
23
31
|
output = %x{#{command}}
|
24
32
|
|
25
|
-
if
|
26
|
-
|
27
|
-
|
28
|
-
puts output if options[:loud] == true
|
29
|
-
output
|
33
|
+
if !$?.success?
|
34
|
+
raise CommandError.new(output, "\"#{command}\" failed to run.") if options[:raise] == true
|
35
|
+
abort "\"#{command}\" failed to run." if options[:blocking] == true
|
30
36
|
end
|
37
|
+
|
38
|
+
puts output if options[:loud] == true
|
39
|
+
output
|
31
40
|
end
|
32
41
|
end
|
33
42
|
|