toys-core 0.9.4 → 0.10.0
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/.yardopts +2 -1
- data/CHANGELOG.md +30 -0
- data/LICENSE.md +1 -1
- data/README.md +3 -3
- data/lib/toys-core.rb +11 -21
- data/lib/toys/acceptor.rb +0 -21
- data/lib/toys/arg_parser.rb +1 -22
- data/lib/toys/cli.rb +102 -70
- data/lib/toys/compat.rb +49 -41
- data/lib/toys/completion.rb +0 -21
- data/lib/toys/context.rb +0 -23
- data/lib/toys/core.rb +1 -22
- data/lib/toys/dsl/flag.rb +0 -21
- data/lib/toys/dsl/flag_group.rb +0 -21
- data/lib/toys/dsl/positional_arg.rb +0 -21
- data/lib/toys/dsl/tool.rb +135 -51
- data/lib/toys/errors.rb +0 -21
- data/lib/toys/flag.rb +0 -21
- data/lib/toys/flag_group.rb +0 -21
- data/lib/toys/input_file.rb +0 -21
- data/lib/toys/loader.rb +41 -78
- data/lib/toys/middleware.rb +146 -77
- data/lib/toys/mixin.rb +0 -21
- data/lib/toys/module_lookup.rb +3 -26
- data/lib/toys/positional_arg.rb +0 -21
- data/lib/toys/source_info.rb +49 -38
- data/lib/toys/standard_middleware/add_verbosity_flags.rb +0 -23
- data/lib/toys/standard_middleware/apply_config.rb +42 -0
- data/lib/toys/standard_middleware/handle_usage_errors.rb +7 -28
- data/lib/toys/standard_middleware/set_default_descriptions.rb +0 -23
- data/lib/toys/standard_middleware/show_help.rb +0 -23
- data/lib/toys/standard_middleware/show_root_version.rb +0 -23
- data/lib/toys/standard_mixins/bundler.rb +89 -0
- data/lib/toys/standard_mixins/exec.rb +124 -35
- data/lib/toys/standard_mixins/fileutils.rb +0 -21
- data/lib/toys/standard_mixins/gems.rb +2 -24
- data/lib/toys/standard_mixins/highline.rb +0 -21
- data/lib/toys/standard_mixins/terminal.rb +0 -21
- data/lib/toys/template.rb +0 -21
- data/lib/toys/tool.rb +22 -34
- data/lib/toys/utils/completion_engine.rb +0 -21
- data/lib/toys/utils/exec.rb +1 -21
- data/lib/toys/utils/gems.rb +174 -63
- data/lib/toys/utils/help_text.rb +0 -21
- data/lib/toys/utils/terminal.rb +46 -37
- data/lib/toys/wrappable_string.rb +0 -21
- metadata +25 -9
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
10
|
-
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
-
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
-
# IN THE SOFTWARE.
|
22
|
-
;
|
23
|
-
|
24
3
|
module Toys
|
25
4
|
module StandardMixins
|
26
5
|
##
|
data/lib/toys/template.rb
CHANGED
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
10
|
-
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
-
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
-
# IN THE SOFTWARE.
|
22
|
-
;
|
23
|
-
|
24
3
|
module Toys
|
25
4
|
##
|
26
5
|
# A template definition. Template classes should include this module.
|
data/lib/toys/tool.rb
CHANGED
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
10
|
-
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
-
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
-
# IN THE SOFTWARE.
|
22
|
-
;
|
23
|
-
|
24
3
|
require "set"
|
25
4
|
|
26
5
|
module Toys
|
@@ -37,11 +16,12 @@ module Toys
|
|
37
16
|
# Should be created only from the DSL via the Loader.
|
38
17
|
# @private
|
39
18
|
#
|
40
|
-
def initialize(loader, parent, full_name, priority, middleware_stack)
|
19
|
+
def initialize(loader, parent, full_name, priority, middleware_stack, middleware_lookup)
|
41
20
|
@parent = parent
|
42
21
|
@full_name = full_name.dup.freeze
|
43
22
|
@priority = priority
|
44
|
-
@
|
23
|
+
@built_middleware = middleware_stack.build(middleware_lookup)
|
24
|
+
@subtool_middleware_stack = middleware_stack.dup
|
45
25
|
|
46
26
|
@acceptors = {}
|
47
27
|
@mixins = {}
|
@@ -201,11 +181,20 @@ module Toys
|
|
201
181
|
attr_reader :default_data
|
202
182
|
|
203
183
|
##
|
204
|
-
# The middleware
|
184
|
+
# The stack of middleware specs used for subtools.
|
185
|
+
#
|
186
|
+
# This array may be modified in place.
|
187
|
+
#
|
188
|
+
# @return [Array<Toys::Middleware::Spec>]
|
189
|
+
#
|
190
|
+
attr_reader :subtool_middleware_stack
|
191
|
+
|
192
|
+
##
|
193
|
+
# The stack of built middleware specs for this tool.
|
205
194
|
#
|
206
195
|
# @return [Array<Toys::Middleware>]
|
207
196
|
#
|
208
|
-
attr_reader :
|
197
|
+
attr_reader :built_middleware
|
209
198
|
|
210
199
|
##
|
211
200
|
# Info on the source of this tool.
|
@@ -473,18 +462,13 @@ module Toys
|
|
473
462
|
##
|
474
463
|
# Sets the path to the file that defines this tool.
|
475
464
|
# A tool may be defined from at most one path. If a different path is
|
476
|
-
# already set,
|
465
|
+
# already set, it is left unchanged.
|
477
466
|
#
|
478
467
|
# @param source [Toys::SourceInfo] Source info
|
479
468
|
# @return [self]
|
480
469
|
#
|
481
470
|
def lock_source(source)
|
482
|
-
|
483
|
-
raise ToolDefinitionError,
|
484
|
-
"Cannot redefine tool #{display_name.inspect} in #{source.source_name}" \
|
485
|
-
" (already defined in #{source_info.source_name})"
|
486
|
-
end
|
487
|
-
@source_info = source
|
471
|
+
@source_info ||= source
|
488
472
|
self
|
489
473
|
end
|
490
474
|
|
@@ -1073,7 +1057,7 @@ module Toys
|
|
1073
1057
|
unless @definition_finished
|
1074
1058
|
ContextualError.capture("Error installing tool middleware!", tool_name: full_name) do
|
1075
1059
|
config_proc = proc {}
|
1076
|
-
|
1060
|
+
@built_middleware.reverse_each do |middleware|
|
1077
1061
|
config_proc = make_config_proc(middleware, loader, config_proc)
|
1078
1062
|
end
|
1079
1063
|
config_proc.call
|
@@ -1306,7 +1290,11 @@ module Toys
|
|
1306
1290
|
private
|
1307
1291
|
|
1308
1292
|
def make_config_proc(middleware, loader, next_config)
|
1309
|
-
|
1293
|
+
if middleware.respond_to?(:config)
|
1294
|
+
proc { middleware.config(self, loader, &next_config) }
|
1295
|
+
else
|
1296
|
+
next_config
|
1297
|
+
end
|
1310
1298
|
end
|
1311
1299
|
|
1312
1300
|
def make_delegation_run_handler(target)
|
@@ -1,26 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright 2019 Daniel Azuma
|
4
|
-
#
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
10
|
-
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
-
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
-
# IN THE SOFTWARE.
|
22
|
-
;
|
23
|
-
|
24
3
|
require "shellwords"
|
25
4
|
|
26
5
|
module Toys
|
data/lib/toys/utils/exec.rb
CHANGED
@@ -1,26 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
#
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
10
|
-
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
-
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
-
# IN THE SOFTWARE.
|
22
|
-
;
|
23
|
-
|
3
|
+
require "rbconfig"
|
24
4
|
require "logger"
|
25
5
|
require "shellwords"
|
26
6
|
|
data/lib/toys/utils/gems.rb
CHANGED
@@ -1,30 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
10
|
-
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
-
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
-
# IN THE SOFTWARE.
|
22
|
-
;
|
3
|
+
require "monitor"
|
4
|
+
require "rubygems"
|
23
5
|
|
24
6
|
module Toys
|
25
7
|
module Utils
|
26
8
|
##
|
27
|
-
# A helper
|
9
|
+
# A helper class that activates and installs gems and sets up bundler.
|
28
10
|
#
|
29
11
|
# This class is not loaded by default. Before using it directly, you should
|
30
12
|
# `require "toys/utils/gems"`
|
@@ -58,6 +40,30 @@ module Toys
|
|
58
40
|
end
|
59
41
|
end
|
60
42
|
|
43
|
+
##
|
44
|
+
# Failed to run Bundler
|
45
|
+
#
|
46
|
+
class BundlerFailedError < ::StandardError
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Could not find a Gemfile
|
51
|
+
#
|
52
|
+
class GemfileNotFoundError < BundlerFailedError
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# The bundle is not and could not be installed
|
57
|
+
#
|
58
|
+
class BundleNotInstalledError < BundlerFailedError
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Bundler has already been run; cannot do so again
|
63
|
+
#
|
64
|
+
class AlreadyBundledError < BundlerFailedError
|
65
|
+
end
|
66
|
+
|
61
67
|
##
|
62
68
|
# Activate the given gem. If it is not present, attempt to install it (or
|
63
69
|
# inform the user to update the bundle).
|
@@ -73,24 +79,42 @@ module Toys
|
|
73
79
|
##
|
74
80
|
# Create a new gem activator.
|
75
81
|
#
|
76
|
-
# @param
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
82
|
+
# @param on_missing [:confirm,:error,:install] What to do if a needed gem
|
83
|
+
# is not installed. Possible values:
|
84
|
+
# * `:confirm` - prompt the user on whether to install
|
85
|
+
# * `:error` - raise an exception
|
86
|
+
# * `:install` - just install the gem
|
87
|
+
# The default is `:confirm`.
|
88
|
+
# @param on_conflict [:error,:warn,:ignore] What to do if bundler has
|
89
|
+
# already been run with a different Gemfile. Possible values:
|
90
|
+
# * `:error` - raise an exception
|
91
|
+
# * `:ignore` - just silently proceed without bundling again
|
92
|
+
# * `:warn` - print a warning and proceed without bundling again
|
93
|
+
# The default is `:error`.
|
94
|
+
# @param terminal [Toys::Utils::Terminal] Terminal to use (optional)
|
95
|
+
# @param input [IO] Input IO (optional, defaults to STDIN)
|
96
|
+
# @param output [IO] Output IO (optional, defaults to STDOUT)
|
97
|
+
# @param suppress_confirm [Boolean] Deprecated. Use `on_missing` instead.
|
98
|
+
# @param default_confirm [Boolean] Deprecated. Use `on_missing` instead.
|
83
99
|
#
|
84
|
-
def initialize(
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
@
|
92
|
-
@
|
93
|
-
|
100
|
+
def initialize(on_missing: nil,
|
101
|
+
on_conflict: nil,
|
102
|
+
terminal: nil,
|
103
|
+
input: nil,
|
104
|
+
output: nil,
|
105
|
+
suppress_confirm: nil,
|
106
|
+
default_confirm: nil)
|
107
|
+
@default_confirm = default_confirm || default_confirm.nil? ? true : false
|
108
|
+
@on_missing = on_missing ||
|
109
|
+
if suppress_confirm
|
110
|
+
@default_confirm ? :install : :error
|
111
|
+
else
|
112
|
+
:confirm
|
113
|
+
end
|
114
|
+
@on_conflict = on_conflict || :error
|
115
|
+
@terminal = terminal
|
116
|
+
@input = input || ::STDIN
|
117
|
+
@output = output || ::STDOUT
|
94
118
|
end
|
95
119
|
|
96
120
|
##
|
@@ -102,13 +126,56 @@ module Toys
|
|
102
126
|
# @return [void]
|
103
127
|
#
|
104
128
|
def activate(name, *requirements)
|
105
|
-
|
106
|
-
|
107
|
-
|
129
|
+
Gems.synchronize do
|
130
|
+
begin
|
131
|
+
gem(name, *requirements)
|
132
|
+
rescue ::Gem::LoadError => e
|
133
|
+
handle_activation_error(e, name, requirements)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# Set up the bundle.
|
140
|
+
#
|
141
|
+
# @param groups [Array<String>] The groups to include in setup
|
142
|
+
# @param search_dirs [Array<String>] Directories to search for a Gemfile
|
143
|
+
# @return [void]
|
144
|
+
#
|
145
|
+
def bundle(groups: nil,
|
146
|
+
search_dirs: nil)
|
147
|
+
Gems.synchronize do
|
148
|
+
gemfile_path = find_gemfile(Array(search_dirs))
|
149
|
+
activate("bundler", "~> 2.1")
|
150
|
+
if configure_gemfile(gemfile_path)
|
151
|
+
setup_bundle(gemfile_path, groups || [])
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
@global_mutex = ::Monitor.new
|
157
|
+
|
158
|
+
## @private
|
159
|
+
def self.synchronize(&block)
|
160
|
+
@global_mutex.synchronize(&block)
|
108
161
|
end
|
109
162
|
|
110
163
|
private
|
111
164
|
|
165
|
+
def terminal
|
166
|
+
@terminal ||= begin
|
167
|
+
require "toys/utils/terminal"
|
168
|
+
Utils::Terminal.new(input: @input, output: @output)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def exec_util
|
173
|
+
@exec_util ||= begin
|
174
|
+
require "toys/utils/exec"
|
175
|
+
Utils::Exec.new
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
112
179
|
def handle_activation_error(error, name, requirements)
|
113
180
|
is_missing_spec =
|
114
181
|
if defined?(::Gem::MissingSpecError)
|
@@ -116,11 +183,11 @@ module Toys
|
|
116
183
|
else
|
117
184
|
error.message.include?("Could not find")
|
118
185
|
end
|
119
|
-
|
186
|
+
if !is_missing_spec || @on_missing == :error
|
120
187
|
report_error(name, requirements, error)
|
121
188
|
return
|
122
189
|
end
|
123
|
-
|
190
|
+
confirm_and_install_gem(name, requirements)
|
124
191
|
begin
|
125
192
|
gem(name, *requirements)
|
126
193
|
rescue ::Gem::LoadError => e
|
@@ -132,28 +199,16 @@ module Toys
|
|
132
199
|
"#{name.inspect}, #{requirements.map(&:inspect).join(', ')}"
|
133
200
|
end
|
134
201
|
|
135
|
-
def
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
default: @default_confirm)
|
202
|
+
def confirm_and_install_gem(name, requirements)
|
203
|
+
if @on_missing == :confirm
|
204
|
+
requirements_text = gem_requirements_text(name, requirements)
|
205
|
+
response = terminal.confirm("Gem needed: #{requirements_text}. Install? ",
|
206
|
+
default: @default_confirm)
|
207
|
+
unless response
|
208
|
+
raise InstallFailedError, "Canceled installation of needed gem: #{requirements_text}"
|
143
209
|
end
|
144
|
-
unless response
|
145
|
-
raise InstallFailedError, "Canceled installation of needed gem: #{requirements_text}"
|
146
|
-
end
|
147
|
-
perform_install(name, requirements)
|
148
|
-
end
|
149
|
-
|
150
|
-
def perform_install(name, requirements)
|
151
|
-
result = @terminal.spinner(leading_text: "Installing gem #{name}... ",
|
152
|
-
final_text: "Done.\n") do
|
153
|
-
@exec.exec(["gem", "install", name, "--version", requirements.join(",")],
|
154
|
-
out: :capture, err: :capture)
|
155
210
|
end
|
156
|
-
|
211
|
+
result = exec_util.exec(["gem", "install", name, "--version", requirements.join(",")])
|
157
212
|
if result.error?
|
158
213
|
raise InstallFailedError, "Failed to install gem #{name}"
|
159
214
|
end
|
@@ -167,6 +222,62 @@ module Toys
|
|
167
222
|
end
|
168
223
|
raise ActivationFailedError, err.message
|
169
224
|
end
|
225
|
+
|
226
|
+
def find_gemfile(search_dirs)
|
227
|
+
search_dirs.each do |dir|
|
228
|
+
gemfile_path = ::File.join(dir, "Gemfile")
|
229
|
+
return gemfile_path if ::File.readable?(gemfile_path)
|
230
|
+
end
|
231
|
+
raise GemfileNotFoundError, "Gemfile not found"
|
232
|
+
end
|
233
|
+
|
234
|
+
def configure_gemfile(gemfile_path)
|
235
|
+
old_path = ::ENV["BUNDLE_GEMFILE"]
|
236
|
+
if old_path && gemfile_path != old_path
|
237
|
+
case @on_conflict
|
238
|
+
when :warn
|
239
|
+
terminal.puts("Warning: could not set up bundler because it is already set up.", :red)
|
240
|
+
when :error
|
241
|
+
raise AlreadyBundledError, "Could not set up bundler because it is already set up"
|
242
|
+
end
|
243
|
+
return false
|
244
|
+
end
|
245
|
+
::ENV["BUNDLE_GEMFILE"] = gemfile_path
|
246
|
+
true
|
247
|
+
end
|
248
|
+
|
249
|
+
def setup_bundle(gemfile_path, groups)
|
250
|
+
require "bundler"
|
251
|
+
begin
|
252
|
+
::Bundler.setup(*groups)
|
253
|
+
rescue ::Bundler::GemNotFound
|
254
|
+
install_bundle(gemfile_path)
|
255
|
+
::Bundler.reset!
|
256
|
+
::Bundler.setup(*groups)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def permission_to_bundle?
|
261
|
+
case @on_missing
|
262
|
+
when :install
|
263
|
+
true
|
264
|
+
when :error
|
265
|
+
false
|
266
|
+
else
|
267
|
+
terminal.confirm("Your bundle is not complete. Install? ", default: @default_confirm)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def install_bundle(gemfile_path)
|
272
|
+
gemfile_dir = ::File.dirname(gemfile_path)
|
273
|
+
unless permission_to_bundle?
|
274
|
+
raise BundleNotInstalledError,
|
275
|
+
"Your bundle is not installed. Consider running" \
|
276
|
+
" `cd #{gemfile_dir} && bundle install`"
|
277
|
+
end
|
278
|
+
require "bundler/cli"
|
279
|
+
::Bundler::CLI.start(["install"])
|
280
|
+
end
|
170
281
|
end
|
171
282
|
end
|
172
283
|
end
|