shopify-cli 1.0.5 → 1.1.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/CHANGELOG.md +4 -0
- data/bin/load_shopify.rb +3 -1
- data/bin/shopify +2 -0
- data/ext/shopify-cli/extconf.rb +40 -20
- data/lib/project_types/node/commands/create.rb +4 -4
- data/lib/project_types/node/commands/deploy/heroku.rb +6 -1
- data/lib/project_types/node/commands/generate/billing.rb +6 -5
- data/lib/project_types/node/commands/generate/page.rb +8 -5
- data/lib/project_types/node/commands/generate/webhook.rb +4 -1
- data/lib/project_types/node/messages/messages.rb +1 -0
- data/lib/project_types/rails/commands/create.rb +52 -4
- data/lib/project_types/rails/commands/generate.rb +1 -0
- data/lib/project_types/rails/commands/generate/webhook.rb +3 -2
- data/lib/project_types/rails/commands/serve.rb +6 -2
- data/lib/project_types/rails/gem.rb +61 -6
- data/lib/project_types/rails/messages/messages.rb +27 -11
- data/lib/project_types/script/config/extension_points.yml +3 -3
- data/lib/project_types/script/forms/create.rb +1 -1
- data/lib/rubygems_plugin.rb +18 -10
- data/lib/shopify-cli/admin_api/populate_resource_command.rb +1 -1
- data/lib/shopify-cli/commands/connect.rb +1 -1
- data/lib/shopify-cli/commands/system.rb +9 -8
- data/lib/shopify-cli/context.rb +28 -0
- data/lib/shopify-cli/heroku.rb +18 -2
- data/lib/shopify-cli/js_deps.rb +2 -2
- data/lib/shopify-cli/js_system.rb +2 -2
- data/lib/shopify-cli/process_supervision.rb +52 -15
- data/lib/shopify-cli/project.rb +14 -6
- data/lib/shopify-cli/tunnel.rb +10 -4
- data/lib/shopify-cli/version.rb +1 -1
- data/lib/shopify_cli.rb +6 -2
- data/shopify-cli.gemspec +4 -1
- data/vendor/deps/cli-kit/REVISION +1 -1
- data/vendor/deps/cli-kit/lib/cli/kit.rb +1 -1
- data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +2 -2
- data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +12 -6
- data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +9 -11
- data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +8 -2
- data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +7 -7
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +48 -17
- data/vendor/deps/cli-ui/REVISION +1 -1
- data/vendor/deps/cli-ui/lib/cli/ui.rb +5 -4
- data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +9 -3
- data/vendor/deps/cli-ui/lib/cli/ui/color.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +3 -2
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/box.rb +13 -5
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/bracket.rb +29 -2
- data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +21 -10
- data/vendor/deps/cli-ui/lib/cli/ui/os.rb +63 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +11 -2
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +3 -3
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +6 -8
- data/vendor/deps/cli-ui/lib/cli/ui/widgets.rb +2 -0
- data/vendor/gen/lib/gen.rb +39 -0
- data/vendor/gen/lib/gen/commands.rb +18 -0
- data/vendor/gen/lib/gen/commands/help.rb +20 -0
- data/vendor/gen/lib/gen/commands/new.rb +21 -0
- data/vendor/gen/lib/gen/entry_point.rb +10 -0
- data/vendor/gen/lib/gen/generator.rb +165 -0
- data/vendor/gen/template/.gitignore +2 -0
- data/vendor/gen/template/Gemfile +10 -0
- data/vendor/gen/template/README.md +1 -0
- data/vendor/gen/template/bin/testunit +23 -0
- data/vendor/gen/template/bin/update-deps +97 -0
- data/vendor/gen/template/dev-gems.yml +3 -0
- data/vendor/gen/template/dev-vendor.yml +4 -0
- data/vendor/gen/template/exe/__app__-gems +17 -0
- data/vendor/gen/template/exe/__app__-vendor +18 -0
- data/vendor/gen/template/lib/__app__.rb +33 -0
- data/vendor/gen/template/lib/__app__/commands.rb +18 -0
- data/vendor/gen/template/lib/__app__/commands/example.rb +19 -0
- data/vendor/gen/template/lib/__app__/commands/help.rb +21 -0
- data/vendor/gen/template/lib/__app__/entry_point.rb +10 -0
- data/vendor/gen/template/test/example_test.rb +17 -0
- data/vendor/gen/template/test/test_helper.rb +22 -0
- metadata +25 -4
- data/Vagrantfile +0 -17
- data/lib/project_types/script/forms/script_form.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f47a49090da5b25b266e4186c08b377e91e6fe240620076f24bb0174accc854
|
4
|
+
data.tar.gz: 68be2a02c00aa4e0c67295024d0997c453eb40b9d92f4cec9ae06dc5c0b3d0fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0cd5e1c1e79ec89fcba9834eb1c1ea98d53a98ad46f2fcc45e5fefebfabcd9b1655cb73c1431c503b9c1a26f2d684d6a1c330813423733601670839c7e82efc
|
7
|
+
data.tar.gz: a3f83e966247aee450f3a73615dce3d324f82ab944304be131dec81973d1984c405d060844601047ceb259163faaa79524d859bbe9a874479ea4a26c21530152
|
data/CHANGELOG.md
CHANGED
data/bin/load_shopify.rb
CHANGED
@@ -9,7 +9,9 @@ ENV['USER_PWD'] ||= Dir.pwd
|
|
9
9
|
# Prune non-absolute paths from PATH to prevent non-deterministic behavior
|
10
10
|
# i.e. If user has "." or "./bin" in their PATH
|
11
11
|
# Note that this logic is duplicated in lib/shopify.rb
|
12
|
-
ENV['PATH'] = ENV['PATH'].split(
|
12
|
+
ENV['PATH'] = ENV['PATH'].split(File::PATH_SEPARATOR).select do |p|
|
13
|
+
p.start_with?('/', '~', /[A-Z]:\\/)
|
14
|
+
end.join(File::PATH_SEPARATOR)
|
13
15
|
|
14
16
|
$original_env = ENV.to_hash
|
15
17
|
|
data/bin/shopify
CHANGED
@@ -8,6 +8,8 @@ module Kernel
|
|
8
8
|
def require(name)
|
9
9
|
original_require(name)
|
10
10
|
rescue LoadError => e
|
11
|
+
# Special case for readline.so, which fails harmlessly on Windows
|
12
|
+
raise if (name == "readline.so") && ShopifyCli::Context.new.windows?
|
11
13
|
# Special case for psych (yaml), which rescues this itself
|
12
14
|
raise if name == "#{RUBY_VERSION[/\d+\.\d+/]}/psych.so"
|
13
15
|
STDERR.puts "[Note] You cannot use gems with Shopify App CLI."
|
data/ext/shopify-cli/extconf.rb
CHANGED
@@ -3,25 +3,45 @@ require 'fileutils'
|
|
3
3
|
|
4
4
|
gem = File.expand_path('../../../', __FILE__)
|
5
5
|
exe = File.join(gem, 'bin', 'shopify')
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#{RbConfig.ruby} --disable=gems -I #{gem} #{exe}
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
6
|
+
|
7
|
+
if RUBY_PLATFORM.match(/mingw32/)
|
8
|
+
bat_path = File.dirname(RbConfig.ruby)
|
9
|
+
bat = "#{bat_path}\\shopify.bat"
|
10
|
+
|
11
|
+
script_content = "#{RbConfig.ruby} --disable=gems -I '#{gem}' '#{exe}' %*"
|
12
|
+
|
13
|
+
FileUtils.mkdir_p(bat_path)
|
14
|
+
makefile_content = <<~MAKEFILE
|
15
|
+
.PHONY: clean install
|
16
|
+
|
17
|
+
clean:
|
18
|
+
\t rm -f "#{bat}"
|
19
|
+
|
20
|
+
install: clean
|
21
|
+
\t echo "@ECHO OFF"> "#{bat}"
|
22
|
+
\t echo "#{script_content}">> "#{bat}"
|
23
|
+
MAKEFILE
|
24
|
+
else
|
25
|
+
script = exe + '.sh'
|
26
|
+
symlink = '/usr/local/bin/shopify'
|
27
|
+
|
28
|
+
script_content = <<~SCRIPT
|
29
|
+
#!/usr/bin/env bash
|
30
|
+
#{RbConfig.ruby} --disable=gems -I #{gem} #{exe} $@
|
31
|
+
SCRIPT
|
32
|
+
|
33
|
+
File.write(script, script_content)
|
34
|
+
FileUtils.chmod("+x", script)
|
35
|
+
|
36
|
+
makefile_content = <<~MAKEFILE
|
37
|
+
.PHONY: clean install
|
38
|
+
|
39
|
+
clean:
|
40
|
+
\t@sudo rm -f #{symlink}
|
41
|
+
|
42
|
+
install: clean
|
43
|
+
\t@sudo ln -s #{script} #{symlink}
|
44
|
+
MAKEFILE
|
45
|
+
end
|
26
46
|
|
27
47
|
File.write('Makefile', makefile_content)
|
@@ -54,8 +54,8 @@ module Node
|
|
54
54
|
private
|
55
55
|
|
56
56
|
def check_node
|
57
|
-
|
58
|
-
@ctx.abort(@ctx.message('node.create.error.node_required'))
|
57
|
+
cmd_path = @ctx.which('node')
|
58
|
+
@ctx.abort(@ctx.message('node.create.error.node_required')) if cmd_path.nil?
|
59
59
|
|
60
60
|
version, stat = @ctx.capture2e('node', '-v')
|
61
61
|
@ctx.abort(@ctx.message('node.create.error.node_version_failure')) unless stat.success?
|
@@ -64,8 +64,8 @@ module Node
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def check_npm
|
67
|
-
|
68
|
-
@ctx.abort(@ctx.message('node.create.error.npm_required'))
|
67
|
+
cmd_path = @ctx.which('npm')
|
68
|
+
@ctx.abort(@ctx.message('node.create.error.npm_required')) if cmd_path.nil?
|
69
69
|
|
70
70
|
version, stat = @ctx.capture2e('npm', '-v')
|
71
71
|
@ctx.abort(@ctx.message('node.create.error.npm_version_failure')) unless stat.success?
|
@@ -19,10 +19,15 @@ module Node
|
|
19
19
|
end
|
20
20
|
spin_group.wait
|
21
21
|
|
22
|
-
|
22
|
+
install_message = @ctx.message(
|
23
|
+
@ctx.windows? ? 'node.deploy.heroku.installing_windows' : 'node.deploy.heroku.installing'
|
24
|
+
)
|
25
|
+
spin_group.add(install_message) do |spinner|
|
23
26
|
heroku_service.install
|
24
27
|
spinner.update_title(@ctx.message('node.deploy.heroku.installed'))
|
25
28
|
end
|
29
|
+
spin_group.wait
|
30
|
+
|
26
31
|
spin_group.add(@ctx.message('node.deploy.heroku.git.checking')) do |spinner|
|
27
32
|
ShopifyCli::Git.init(@ctx)
|
28
33
|
spinner.update_title(@ctx.message('node.deploy.heroku.git.initialized'))
|
@@ -5,8 +5,8 @@ module Node
|
|
5
5
|
class Generate
|
6
6
|
class Billing < ShopifyCli::SubCommand
|
7
7
|
BILLING_TYPES = {
|
8
|
-
'recurring-billing' => './node_modules/.bin/generate-node-app recurring-billing',
|
9
|
-
'one-time-billing' => './node_modules/.bin/generate-node-app one-time-billing',
|
8
|
+
'recurring-billing' => ['./node_modules/.bin/generate-node-app', 'recurring-billing'],
|
9
|
+
'one-time-billing' => ['./node_modules/.bin/generate-node-app', 'one-time-billing'],
|
10
10
|
}
|
11
11
|
def call(args, _name)
|
12
12
|
selected_type = BILLING_TYPES[args[1]]
|
@@ -18,11 +18,12 @@ module Node
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
billing_type_name = BILLING_TYPES.key(selected_type)
|
21
|
+
selected_type[0] = File.join(ShopifyCli::Project.current.directory, selected_type[0])
|
22
|
+
selected_type = selected_type.join(' ')
|
23
|
+
|
21
24
|
spin_group = CLI::UI::SpinGroup.new
|
22
25
|
spin_group.add(@ctx.message('node.generate.billing.generating', billing_type_name)) do |spinner|
|
23
|
-
Node::Commands::Generate.run_generate(
|
24
|
-
selected_type, billing_type_name, @ctx
|
25
|
-
)
|
26
|
+
Node::Commands::Generate.run_generate(selected_type, billing_type_name, @ctx)
|
26
27
|
spinner.update_title(@ctx.message('node.generate.billing.generated', billing_type_name))
|
27
28
|
end
|
28
29
|
spin_group.wait
|
@@ -5,10 +5,10 @@ module Node
|
|
5
5
|
class Generate
|
6
6
|
class Page < ShopifyCli::SubCommand
|
7
7
|
PAGE_TYPES = {
|
8
|
-
'empty-state' => './node_modules/.bin/generate-node-app empty-state-page',
|
9
|
-
'two-column' => './node_modules/.bin/generate-node-app two-column-page',
|
10
|
-
'annotated' => './node_modules/.bin/generate-node-app settings-page',
|
11
|
-
'list' => './node_modules/.bin/generate-node-app list-page',
|
8
|
+
'empty-state' => ['./node_modules/.bin/generate-node-app', 'empty-state-page'],
|
9
|
+
'two-column' => ['./node_modules/.bin/generate-node-app', 'two-column-page'],
|
10
|
+
'annotated' => ['./node_modules/.bin/generate-node-app', 'settings-page'],
|
11
|
+
'list' => ['./node_modules/.bin/generate-node-app', 'list-page'],
|
12
12
|
}
|
13
13
|
|
14
14
|
options do |parser, flags|
|
@@ -37,9 +37,12 @@ module Node
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
40
|
+
page_type_name = PAGE_TYPES.key(selected_type)
|
41
|
+
selected_type[0] = File.join(ShopifyCli::Project.current.directory, selected_type[0])
|
42
|
+
selected_type = selected_type.join(' ')
|
40
43
|
|
41
44
|
spin_group = CLI::UI::SpinGroup.new
|
42
|
-
spin_group.add(@ctx.message('node.generate.page.generating',
|
45
|
+
spin_group.add(@ctx.message('node.generate.page.generating', page_type_name)) do |spinner|
|
43
46
|
Node::Commands::Generate.run_generate("#{selected_type} #{name}", name, @ctx)
|
44
47
|
spinner.update_title(@ctx.message('node.generate.page.generated', name, name))
|
45
48
|
end
|
@@ -15,9 +15,12 @@ module Node
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
|
+
|
19
|
+
generate_path = File.join(ShopifyCli::Project.current.directory, "node_modules/.bin/generate-node-app")
|
20
|
+
|
18
21
|
spin_group = CLI::UI::SpinGroup.new
|
19
22
|
spin_group.add(@ctx.message('node.generate.webhook.generating', selected_type)) do |spinner|
|
20
|
-
Node::Commands::Generate.run_generate("
|
23
|
+
Node::Commands::Generate.run_generate("#{generate_path} webhook #{selected_type}",
|
21
24
|
selected_type, @ctx)
|
22
25
|
spinner.update_title(@ctx.message('node.generate.webhook.generated', selected_type))
|
23
26
|
end
|
@@ -54,6 +54,7 @@ module Node
|
|
54
54
|
downloading: "Downloading Heroku CLI…",
|
55
55
|
downloaded: "Downloaded Heroku CLI",
|
56
56
|
installing: "Installing Heroku CLI…",
|
57
|
+
installing_windows: "Running Heroku CLI install wizard…",
|
57
58
|
installed: "Installed Heroku CLI",
|
58
59
|
authenticating: "Authenticating with Heroku…",
|
59
60
|
authenticated: "{{v}} Authenticated with Heroku",
|
@@ -30,6 +30,9 @@ module Rails
|
|
30
30
|
@ctx.abort(@ctx.message('rails.create.error.invalid_ruby_version')) unless
|
31
31
|
Ruby.version(@ctx).satisfies?('~>2.5')
|
32
32
|
|
33
|
+
check_node
|
34
|
+
check_yarn
|
35
|
+
|
33
36
|
build(form.name, form.db)
|
34
37
|
set_custom_ua
|
35
38
|
ShopifyCli::Project.write(
|
@@ -65,12 +68,51 @@ module Rails
|
|
65
68
|
|
66
69
|
private
|
67
70
|
|
71
|
+
def check_node
|
72
|
+
cmd_path = @ctx.which('node')
|
73
|
+
if cmd_path.nil?
|
74
|
+
@ctx.abort(@ctx.message('rails.create.error.node_required')) unless @ctx.windows?
|
75
|
+
@ctx.puts("{{x}} {{red:" + @ctx.message('rails.create.error.node_required') + "}}")
|
76
|
+
@ctx.puts(@ctx.message('rails.create.info.open_new_shell', 'node'))
|
77
|
+
raise ShopifyCli::AbortSilent
|
78
|
+
end
|
79
|
+
|
80
|
+
version, stat = @ctx.capture2e('node', '-v')
|
81
|
+
unless stat.success?
|
82
|
+
@ctx.abort(@ctx.message('rails.create.error.node_version_failure')) unless @ctx.windows?
|
83
|
+
# execution stops above if not Windows
|
84
|
+
@ctx.puts("{{x}} {{red:" + @ctx.message('rails.create.error.node_version_failure') + "}}")
|
85
|
+
@ctx.puts(@ctx.message('rails.create.info.open_new_shell', 'node'))
|
86
|
+
raise ShopifyCli::AbortSilent
|
87
|
+
end
|
88
|
+
|
89
|
+
@ctx.done(@ctx.message('rails.create.node_version', version))
|
90
|
+
end
|
91
|
+
|
92
|
+
def check_yarn
|
93
|
+
cmd_path = @ctx.which('yarn')
|
94
|
+
if cmd_path.nil?
|
95
|
+
@ctx.abort(@ctx.message('rails.create.error.yarn_required')) unless @ctx.windows?
|
96
|
+
@ctx.puts("{{x}} {{red:" + @ctx.message('rails.create.error.yarn_required') + "}}")
|
97
|
+
@ctx.puts(@ctx.message('rails.create.info.open_new_shell', 'yarn'))
|
98
|
+
raise ShopifyCli::AbortSilent
|
99
|
+
end
|
100
|
+
|
101
|
+
version, stat = @ctx.capture2e('yarn', '-v')
|
102
|
+
unless stat.success?
|
103
|
+
@ctx.abort(@ctx.message('rails.create.error.yarn_version_failure')) unless @ctx.windows?
|
104
|
+
@ctx.puts("{{x}} {{red:" + @ctx.message('rails.create.error.yarn_version_failure') + "}}")
|
105
|
+
@ctx.puts(@ctx.message('rails.create.info.open_new_shell', 'yarn'))
|
106
|
+
raise ShopifyCli::AbortSilent
|
107
|
+
end
|
108
|
+
|
109
|
+
@ctx.done(@ctx.message('rails.create.yarn_version', version))
|
110
|
+
end
|
111
|
+
|
68
112
|
def build(name, db)
|
69
|
-
install_gem('rails')
|
70
|
-
|
71
|
-
install_gem('bundler', '~>1.0')
|
113
|
+
@ctx.abort(@ctx.message('rails.create.error.install_failure', 'rails')) unless install_gem('rails')
|
114
|
+
@ctx.abort(@ctx.message('rails.create.error.install_failure', 'bundler ~>2.0')) unless
|
72
115
|
install_gem('bundler', '~>2.0')
|
73
|
-
end
|
74
116
|
|
75
117
|
CLI::UI::Frame.open(@ctx.message('rails.create.generating_app', name)) do
|
76
118
|
new_command = %w(rails new)
|
@@ -106,6 +148,12 @@ module Rails
|
|
106
148
|
syscall(%w(rails db:create))
|
107
149
|
syscall(%w(rails db:migrate RAILS_ENV=development))
|
108
150
|
end
|
151
|
+
|
152
|
+
unless File.exist?(File.join(@ctx.root, 'config/webpacker.yml'))
|
153
|
+
CLI::UI::Frame.open(@ctx.message('rails.create.running_webpacker_install')) do
|
154
|
+
syscall(%w(rails webpacker:install))
|
155
|
+
end
|
156
|
+
end
|
109
157
|
end
|
110
158
|
|
111
159
|
def set_custom_ua
|
@@ -29,9 +29,10 @@ module Rails
|
|
29
29
|
|
30
30
|
def generate_command(selected_type)
|
31
31
|
parts = selected_type.downcase.split("_")
|
32
|
-
|
32
|
+
host = ShopifyCli::Project.current.env.host
|
33
33
|
selected_type = parts[0..-2].join("_") + "/" + parts[-1]
|
34
|
-
|
34
|
+
command = @ctx.windows? ? "ruby bin\\rails" : "bin/rails"
|
35
|
+
"#{command} g shopify_app:add_webhook -t #{selected_type} -a #{host}/webhooks/#{selected_type.downcase}"
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
@@ -26,12 +26,16 @@ module Rails
|
|
26
26
|
@ctx.open_url!("#{project.env.host}/login?shop=#{project.env.shop}")
|
27
27
|
end
|
28
28
|
end
|
29
|
-
Gem.gem_home(@ctx)
|
30
29
|
CLI::UI::Frame.open(@ctx.message('rails.serve.running_server')) do
|
31
30
|
env = ShopifyCli::Project.current.env.to_h
|
32
31
|
env.delete('HOST')
|
33
32
|
env['PORT'] = ShopifyCli::Tunnel::PORT.to_s
|
34
|
-
|
33
|
+
env['GEM_PATH'] = Gem.gem_path(@ctx)
|
34
|
+
if @ctx.windows?
|
35
|
+
@ctx.system("ruby bin\\rails server", env: env)
|
36
|
+
else
|
37
|
+
@ctx.system('bin/rails server', env: env)
|
38
|
+
end
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
@@ -15,30 +15,65 @@ module Rails
|
|
15
15
|
version = args.shift
|
16
16
|
gem = new(ctx: ctx, name: name, version: version)
|
17
17
|
ctx.debug(ctx.message('rails.gem.installed_debug', name, gem.installed?))
|
18
|
-
gem.
|
18
|
+
gem.installed? ? true : gem.install!
|
19
19
|
end
|
20
20
|
|
21
21
|
def binary_path_for(ctx, binary)
|
22
|
-
File.join(gem_home(ctx), 'bin', binary)
|
22
|
+
path_to_binary = File.join(gem_home(ctx), 'bin', binary)
|
23
|
+
File.exist?(path_to_binary) ? path_to_binary : binary
|
23
24
|
end
|
24
25
|
|
25
26
|
def gem_home(ctx)
|
26
27
|
ctx.getenv('GEM_HOME') || apply_gem_home(ctx)
|
27
28
|
end
|
28
29
|
|
30
|
+
def gem_path(ctx)
|
31
|
+
ctx.getenv('GEM_PATH') || apply_gem_path(ctx)
|
32
|
+
end
|
33
|
+
|
29
34
|
private
|
30
35
|
|
31
36
|
def apply_gem_home(ctx)
|
32
|
-
path =
|
37
|
+
path = ''
|
38
|
+
# extract GEM_HOME from `gem environment home` command
|
39
|
+
out, stat = ctx.capture2e('gem', 'environment', 'home')
|
40
|
+
path = out&.empty? ? '' : out.strip if stat.success?
|
41
|
+
# fallback if return from `gem environment home` is empty (somewhat unlikely)
|
42
|
+
path = fallback_gem_home_path(ctx) if path.empty?
|
43
|
+
# fallback if path isn't writable (if using a system installed ruby)
|
44
|
+
path = fallback_gem_home_path(ctx) unless File.writable?(path)
|
33
45
|
ctx.mkdir_p(path) unless Dir.exist?(path)
|
46
|
+
ctx.debug(ctx.message('rails.gem.setting_gem_home', path))
|
34
47
|
ctx.setenv('GEM_HOME', path)
|
35
48
|
end
|
49
|
+
|
50
|
+
def apply_gem_path(ctx)
|
51
|
+
path = ''
|
52
|
+
out, stat = ctx.capture2e('gem', 'environment', 'path')
|
53
|
+
path = out&.empty? ? '' : out.strip if stat.success?
|
54
|
+
# usually GEM_PATH already contains GEM_HOME
|
55
|
+
# if gem_home() falls back to our fallback path, we need to add it
|
56
|
+
path = gem_home(ctx) + File::PATH_SEPARATOR + path unless path.include?(gem_home(ctx))
|
57
|
+
ctx.debug(ctx.message('rails.gem.setting_gem_path', path))
|
58
|
+
ctx.setenv('GEM_PATH', path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def fallback_gem_home_path(ctx)
|
62
|
+
File.join(ctx.getenv('HOME'), '.gem', 'ruby', RUBY_VERSION)
|
63
|
+
end
|
36
64
|
end
|
37
65
|
|
38
66
|
def installed?
|
39
|
-
|
40
|
-
|
67
|
+
found = false
|
68
|
+
paths = self.class.gem_path(ctx).split(File::PATH_SEPARATOR)
|
69
|
+
paths.each do |path|
|
70
|
+
ctx.debug(ctx.message('rails.gem.checking_installation_path', "#{path}/gems/", name))
|
71
|
+
found = !!Dir.glob("#{path}/gems/#{name}-*").detect do |f|
|
72
|
+
gem_satisfies_version?(f)
|
73
|
+
end
|
74
|
+
break if found
|
41
75
|
end
|
76
|
+
found
|
42
77
|
end
|
43
78
|
|
44
79
|
def install!
|
@@ -46,11 +81,31 @@ module Rails
|
|
46
81
|
spin.add(ctx.message('rails.gem.installing', name)) do |spinner|
|
47
82
|
args = %w(gem install)
|
48
83
|
args.push(name)
|
49
|
-
|
84
|
+
unless version.nil?
|
85
|
+
if ctx.windows? && version.include?('~')
|
86
|
+
args.push('-v', "\"#{version}\"")
|
87
|
+
else
|
88
|
+
args.push('-v', version)
|
89
|
+
end
|
90
|
+
end
|
50
91
|
ctx.system(*args)
|
51
92
|
spinner.update_title(ctx.message('rails.gem.installed', name))
|
52
93
|
end
|
53
94
|
spin.wait
|
54
95
|
end
|
96
|
+
|
97
|
+
def gem_satisfies_version?(path)
|
98
|
+
if version
|
99
|
+
# there was a specific version given during new(), so
|
100
|
+
# check version of gem found to determine match
|
101
|
+
require 'semantic/semantic'
|
102
|
+
found_version, _ = path.match(%r{/#{Regexp.quote(name)}-([\d\.]+)})&.captures
|
103
|
+
found_version.nil? ? false : Semantic::Version.new(found_version).satisfies?(version)
|
104
|
+
else
|
105
|
+
# otherwise ignore the actual version number,
|
106
|
+
# just check there's an initial digit
|
107
|
+
%r{/#{Regexp.quote(name)}-\d}.match?(path)
|
108
|
+
end
|
109
|
+
end
|
55
110
|
end
|
56
111
|
end
|