shopify-cli 2.9.0 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.yaml +117 -0
- data/.github/ISSUE_TEMPLATE/enhancement.yaml +38 -0
- data/.github/ISSUE_TEMPLATE/feature.yaml +47 -0
- data/.github/ISSUE_TEMPLATE.md +18 -0
- data/CHANGELOG.md +38 -5
- data/Gemfile.lock +1 -1
- data/dev.yml +3 -0
- data/lib/project_types/extension/commands/build.rb +3 -0
- data/lib/project_types/extension/commands/check.rb +3 -0
- data/lib/project_types/extension/commands/create.rb +3 -0
- data/lib/project_types/extension/commands/push.rb +3 -0
- data/lib/project_types/extension/commands/serve.rb +3 -0
- data/lib/project_types/extension/models/specification_handlers/default.rb +1 -1
- data/lib/project_types/extension/tasks/convert_server_config.rb +3 -1
- data/lib/project_types/script/cli.rb +5 -0
- data/lib/project_types/script/commands/connect.rb +3 -1
- data/lib/project_types/script/commands/create.rb +2 -0
- data/lib/project_types/script/commands/push.rb +6 -0
- data/lib/project_types/script/config/extension_points.yml +12 -0
- data/lib/project_types/script/graphql/app_script_set.graphql +2 -0
- data/lib/project_types/script/graphql/module_upload_url_generate.graphql +5 -1
- data/lib/project_types/script/layers/application/build_script.rb +6 -3
- data/lib/project_types/script/layers/application/project_dependencies.rb +1 -1
- data/lib/project_types/script/layers/application/push_script.rb +38 -30
- data/lib/project_types/script/layers/domain/errors.rb +10 -3
- data/lib/project_types/script/layers/domain/extension_point.rb +2 -2
- data/lib/project_types/script/layers/domain/push_package.rb +0 -3
- data/lib/project_types/script/layers/domain/script_config.rb +6 -4
- data/lib/project_types/script/layers/domain/script_project.rb +1 -0
- data/lib/project_types/script/layers/infrastructure/errors.rb +47 -24
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +2 -12
- data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +1 -0
- data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +1 -0
- data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +2 -12
- data/lib/project_types/script/layers/infrastructure/languages/wasm_project_creator.rb +15 -0
- data/lib/project_types/script/layers/infrastructure/languages/wasm_task_runner.rb +36 -0
- data/lib/project_types/script/layers/infrastructure/metadata_repository.rb +18 -0
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +7 -8
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +45 -54
- data/lib/project_types/script/layers/infrastructure/script_service.rb +35 -12
- data/lib/project_types/script/layers/infrastructure/script_uploader.rb +22 -9
- data/lib/project_types/script/loaders/project.rb +2 -1
- data/lib/project_types/script/messages/messages.rb +94 -88
- data/lib/project_types/script/ui/error_handler.rb +75 -38
- data/lib/project_types/theme/commands/check.rb +3 -0
- data/lib/project_types/theme/commands/delete.rb +3 -0
- data/lib/project_types/theme/commands/init.rb +3 -0
- data/lib/project_types/theme/commands/language_server.rb +3 -0
- data/lib/project_types/theme/commands/package.rb +3 -0
- data/lib/project_types/theme/commands/publish.rb +3 -0
- data/lib/project_types/theme/commands/pull.rb +12 -1
- data/lib/project_types/theme/commands/push.rb +12 -1
- data/lib/project_types/theme/commands/serve.rb +3 -0
- data/lib/project_types/theme/messages/messages.rb +4 -0
- data/lib/shopify_cli/command/sub_command.rb +2 -0
- data/lib/shopify_cli/command.rb +66 -0
- data/lib/shopify_cli/commands/app/create/node.rb +3 -0
- data/lib/shopify_cli/commands/app/create/rails.rb +3 -0
- data/lib/shopify_cli/commands/app/create.rb +3 -0
- data/lib/shopify_cli/commands/app/deploy.rb +3 -0
- data/lib/shopify_cli/commands/app/serve.rb +3 -0
- data/lib/shopify_cli/commands/login.rb +4 -10
- data/lib/shopify_cli/constants.rb +18 -2
- data/lib/shopify_cli/core/executor.rb +4 -4
- data/lib/shopify_cli/environment.rb +61 -16
- data/lib/shopify_cli/exception_reporter.rb +9 -0
- data/lib/shopify_cli/github/issue_url_generator.rb +19 -8
- data/lib/shopify_cli/identity_auth/env_auth_token.rb +34 -0
- data/lib/shopify_cli/identity_auth.rb +36 -18
- data/lib/shopify_cli/messages/messages.rb +2 -2
- data/lib/shopify_cli/method_object.rb +21 -9
- data/lib/shopify_cli/partners_api.rb +7 -2
- data/lib/shopify_cli/result.rb +61 -59
- data/lib/shopify_cli/services/app/create/rails_service.rb +37 -13
- data/lib/shopify_cli/task.rb +5 -3
- data/lib/shopify_cli/theme/file.rb +2 -2
- data/lib/shopify_cli/theme/filter/path_matcher.rb +38 -0
- data/lib/shopify_cli/theme/ignore_filter.rb +14 -18
- data/lib/shopify_cli/theme/include_filter.rb +65 -0
- data/lib/shopify_cli/theme/syncer.rb +17 -2
- data/lib/shopify_cli/utilities.rb +7 -0
- data/lib/shopify_cli/version.rb +1 -1
- data/lib/shopify_cli.rb +3 -1
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +11 -6
- data/vendor/deps/cli-kit/lib/cli/kit/util.rb +5 -1
- data/vendor/deps/cli-ui/lib/cli/ui/os.rb +6 -4
- data/vendor/deps/ruby2_keywords/LICENSE +22 -0
- data/vendor/deps/ruby2_keywords/README.md +67 -0
- data/vendor/deps/ruby2_keywords/Rakefile +54 -0
- data/vendor/deps/ruby2_keywords/lib/ruby2_keywords.rb +57 -0
- data/vendor/deps/ruby2_keywords/ruby2_keywords.gemspec +18 -0
- data/vendor/deps/ruby2_keywords/test/test_keyword.rb +41 -0
- data/vendor/lib/semantic/version.rb +0 -1
- metadata +18 -3
- data/lib/project_types/rails/commands/create.rb +0 -210
@@ -66,15 +66,27 @@ module ShopifyCLI
|
|
66
66
|
# initializer or to `call`. If the keyword argument matches the name of
|
67
67
|
# property, it is forwarded to the initializer, otherwise to call.
|
68
68
|
#
|
69
|
-
def call(*args,
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
ruby2_keywords def call(*args, &block)
|
70
|
+
# This is an extremely complicated case of delegation. The method wants
|
71
|
+
# to delegate arguments, but to have control over which keyword
|
72
|
+
# arguments are delegated. I'm not sure the forward and backward
|
73
|
+
# compatibility of this unusual form of delegation has really been
|
74
|
+
# explored or there's any good way to support it. So I have done
|
75
|
+
# done something hacky here and I'm looking at the last argument and
|
76
|
+
# modifying the package of arguments to be delegated in-place.
|
77
|
+
if args.last.is_a?(Hash)
|
78
|
+
kwargs = args.last
|
79
|
+
|
80
|
+
initializer_kwargs = kwargs.slice(*properties.keys)
|
81
|
+
instance = new(**initializer_kwargs)
|
82
|
+
|
83
|
+
kwargs.reject! { |key| initializer_kwargs.key?(key) }
|
84
|
+
args.pop if kwargs.empty?
|
85
|
+
instance.call(*args, &block)
|
86
|
+
else
|
87
|
+
# Since the former is so complicated - let's have a fast path that
|
88
|
+
# is much simpler.
|
89
|
+
new.call(*args, &block)
|
78
90
|
end
|
79
91
|
end
|
80
92
|
|
@@ -38,7 +38,11 @@ module ShopifyCLI
|
|
38
38
|
def query(ctx, query_name, **variables)
|
39
39
|
CLI::Kit::Util.begin do
|
40
40
|
api_client(ctx).query(query_name, variables: variables)
|
41
|
-
end.retry_after(
|
41
|
+
end.retry_after(
|
42
|
+
API::APIRequestUnauthorizedError,
|
43
|
+
retries: 1,
|
44
|
+
only: -> { !IdentityAuth::EnvAuthToken.partners_token_present? }
|
45
|
+
) do
|
42
46
|
ShopifyCLI::IdentityAuth.new(ctx: ctx).reauthenticate
|
43
47
|
end
|
44
48
|
rescue API::APIRequestUnauthorizedError => e
|
@@ -60,9 +64,10 @@ module ShopifyCLI
|
|
60
64
|
private
|
61
65
|
|
62
66
|
def api_client(ctx)
|
67
|
+
identity_auth = ShopifyCLI::IdentityAuth.new(ctx: ctx)
|
63
68
|
new(
|
64
69
|
ctx: ctx,
|
65
|
-
token:
|
70
|
+
token: identity_auth.fetch_or_auth_partners_token,
|
66
71
|
url: "https://#{Environment.partners_domain}/api/cli/graphql",
|
67
72
|
)
|
68
73
|
end
|
data/lib/shopify_cli/result.rb
CHANGED
@@ -363,70 +363,72 @@ module ShopifyCLI
|
|
363
363
|
Result::Failure.new(error)
|
364
364
|
end
|
365
365
|
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
366
|
+
class << self
|
367
|
+
##
|
368
|
+
# takes either a value or a block and chooses the appropriate result
|
369
|
+
# container based on the type of the value or the type of the block's return
|
370
|
+
# value. If the type is an exception, it is wrapped in a
|
371
|
+
# `ShopifyCli::Result::Failure` and otherwise in a
|
372
|
+
# `ShopifyCli::Result::Success`. If a block was provided instead of value, a
|
373
|
+
# `Proc` is returned and the result wrapping doesn't occur until the block
|
374
|
+
# is invoked.
|
375
|
+
#
|
376
|
+
# #### Parameters
|
377
|
+
#
|
378
|
+
# * `*args` should be an `Array` with zero or one element
|
379
|
+
# * `&block` should be a `Proc` that takes zero or one argument
|
380
|
+
#
|
381
|
+
# #### Returns
|
382
|
+
#
|
383
|
+
# Returns either a `Result::Success`, `Result::Failure` or a `Proc` that
|
384
|
+
# produces one of the former when invoked.
|
385
|
+
#
|
386
|
+
# #### Examples
|
387
|
+
#
|
388
|
+
# Result.wrap(1) # => ShopifyCli::Result::Success
|
389
|
+
# Result.wrap(RuntimeError.new) # => ShopifyCli::Result::Failure
|
390
|
+
#
|
391
|
+
# Result.wrap { 1 } # => Proc
|
392
|
+
# Result.wrap { 1 }.call # => ShopifyCli::Result::Success
|
393
|
+
# Result.wrap { raise }.call # => ShopifyCli::Result::Failure
|
394
|
+
#
|
395
|
+
# Result.wrap { |s| s.upcase }.call("hello").tap do |result|
|
396
|
+
# result # => Result::Success
|
397
|
+
# result.value # => "HELLO"
|
398
|
+
# end
|
399
|
+
#
|
400
|
+
ruby2_keywords def wrap(*values, &block)
|
401
|
+
raise ArgumentError, "expected either a value or a block" unless (values.length == 1) ^ block
|
401
402
|
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
end
|
413
|
-
else
|
414
|
-
->(*args) do
|
415
|
-
begin
|
416
|
-
wrap(block.call(*args))
|
417
|
-
rescue Exception => error # rubocop:disable Lint/RescueException
|
418
|
-
wrap(error)
|
403
|
+
if values.length == 1
|
404
|
+
values.pop.yield_self do |value|
|
405
|
+
case value
|
406
|
+
when Result::Success, Result::Failure
|
407
|
+
value
|
408
|
+
when NilClass, Exception
|
409
|
+
Result.failure(value)
|
410
|
+
else
|
411
|
+
Result.success(value)
|
412
|
+
end
|
419
413
|
end
|
414
|
+
else
|
415
|
+
->(*args) do
|
416
|
+
begin
|
417
|
+
wrap(block.call(*args))
|
418
|
+
rescue Exception => error # rubocop:disable Lint/RescueException
|
419
|
+
wrap(error)
|
420
|
+
end
|
421
|
+
end.ruby2_keywords
|
420
422
|
end
|
421
423
|
end
|
422
|
-
end
|
423
424
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
425
|
+
##
|
426
|
+
# Wraps the given block and invokes it with the passed arguments.
|
427
|
+
#
|
428
|
+
ruby2_keywords def call(*args, &block)
|
429
|
+
raise ArgumentError, "expected a block" unless block
|
430
|
+
wrap(&block).call(*args)
|
431
|
+
end
|
430
432
|
end
|
431
433
|
end
|
432
434
|
end
|
@@ -41,12 +41,7 @@ module ShopifyCLI
|
|
41
41
|
|
42
42
|
raise ShopifyCLI::AbortSilent if form.nil?
|
43
43
|
|
44
|
-
|
45
|
-
context.abort(context.message("core.app.create.rails.error.invalid_ruby_version")) unless
|
46
|
-
ruby_version.satisfies?("~>2.5") || ruby_version.satisfies?("~>3.0.0")
|
47
|
-
|
48
|
-
check_node
|
49
|
-
check_yarn
|
44
|
+
check_dependencies
|
50
45
|
|
51
46
|
build(form.name, form.db)
|
52
47
|
set_custom_ua
|
@@ -106,6 +101,18 @@ module ShopifyCLI
|
|
106
101
|
end
|
107
102
|
end
|
108
103
|
|
104
|
+
def check_dependencies
|
105
|
+
check_ruby
|
106
|
+
check_node
|
107
|
+
check_yarn
|
108
|
+
end
|
109
|
+
|
110
|
+
def check_ruby
|
111
|
+
ruby_version = Rails::Ruby.version(context)
|
112
|
+
return if ruby_version.satisfies?("~>2.5") || ruby_version.satisfies?("~>3.0.0")
|
113
|
+
context.abort(context.message("core.app.create.rails.error.invalid_ruby_version"))
|
114
|
+
end
|
115
|
+
|
109
116
|
def check_node
|
110
117
|
cmd_path = context.which("node")
|
111
118
|
if cmd_path.nil?
|
@@ -148,11 +155,13 @@ module ShopifyCLI
|
|
148
155
|
end
|
149
156
|
|
150
157
|
def build(name, db)
|
151
|
-
|
152
|
-
"rails"
|
153
|
-
|
154
|
-
|
155
|
-
|
158
|
+
unless install_gem("rails")
|
159
|
+
context.abort(context.message("core.app.create.rails.error.install_failure", "rails"))
|
160
|
+
end
|
161
|
+
|
162
|
+
unless install_gem("bundler", "~>2.0")
|
163
|
+
context.abort(context.message("core.app.create.rails.error.install_failure", "bundler ~>2.0"))
|
164
|
+
end
|
156
165
|
|
157
166
|
full_path = File.join(context.root, name)
|
158
167
|
context.abort(context.message("core.app.create.rails.error.dir_exists", name)) if Dir.exist?(full_path)
|
@@ -173,7 +182,7 @@ module ShopifyCLI
|
|
173
182
|
|
174
183
|
context.puts(context.message("core.app.create.rails.adding_shopify_gem"))
|
175
184
|
File.open(File.join(context.root, "Gemfile"), "a") do |f|
|
176
|
-
f.puts "\ngem 'shopify_app', '>=
|
185
|
+
f.puts "\ngem 'shopify_app', '>=18.1.0'"
|
177
186
|
end
|
178
187
|
CLI::UI::Frame.open(context.message("core.app.create.rails.running_bundle_install")) do
|
179
188
|
syscall(%w(bundle install))
|
@@ -188,7 +197,7 @@ module ShopifyCLI
|
|
188
197
|
syscall(%w(rails db:migrate RAILS_ENV=development))
|
189
198
|
end
|
190
199
|
|
191
|
-
|
200
|
+
if install_webpacker?
|
192
201
|
CLI::UI::Frame.open(context.message("core.app.create.rails.running_webpacker_install")) do
|
193
202
|
syscall(%w(rails webpacker:install))
|
194
203
|
end
|
@@ -208,6 +217,21 @@ module ShopifyCLI
|
|
208
217
|
def install_gem(name, version = nil)
|
209
218
|
Rails::Gem.install(context, name, version)
|
210
219
|
end
|
220
|
+
|
221
|
+
def install_webpacker?
|
222
|
+
rails_version < ::Semantic::Version.new("7.0.0") &&
|
223
|
+
!File.exist?(File.join(context.root, "config/webpacker.yml"))
|
224
|
+
end
|
225
|
+
|
226
|
+
def rails_version
|
227
|
+
output, status = context.capture2e("rails", "--version")
|
228
|
+
unless status.success?
|
229
|
+
context.abort(context.message("core.app.create.rails.error.install_failure", "rails"))
|
230
|
+
end
|
231
|
+
|
232
|
+
version = output.scan(/Rails \d+\.\d+\.\d+/).first.split(" ").last
|
233
|
+
::Semantic::Version.new(version)
|
234
|
+
end
|
211
235
|
end
|
212
236
|
end
|
213
237
|
end
|
data/lib/shopify_cli/task.rb
CHANGED
@@ -18,7 +18,7 @@ module ShopifyCLI
|
|
18
18
|
|
19
19
|
def read
|
20
20
|
if text?
|
21
|
-
path.read
|
21
|
+
path.read(universal_newline: true)
|
22
22
|
else
|
23
23
|
path.read(mode: "rb")
|
24
24
|
end
|
@@ -27,7 +27,7 @@ module ShopifyCLI
|
|
27
27
|
def write(content)
|
28
28
|
path.parent.mkpath unless path.parent.directory?
|
29
29
|
if text?
|
30
|
-
path.write(content)
|
30
|
+
path.write(content, universal_newline: true)
|
31
31
|
else
|
32
32
|
path.write(content, 0, mode: "wb")
|
33
33
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShopifyCLI
|
4
|
+
module Theme
|
5
|
+
module Filter
|
6
|
+
module PathMatcher
|
7
|
+
def regex_match?(regex, path)
|
8
|
+
regex.match?(path)
|
9
|
+
rescue StandardError
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
def glob_match?(glob, path)
|
14
|
+
!!::File.fnmatch?(glob, path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def regex?(pattern)
|
18
|
+
pattern.start_with?("/") && pattern.end_with?("/")
|
19
|
+
end
|
20
|
+
|
21
|
+
def as_regex(pattern)
|
22
|
+
Regexp.new(pattern.gsub(%r{^\/|\/$}, ""))
|
23
|
+
end
|
24
|
+
|
25
|
+
def as_glob(pattern)
|
26
|
+
# if specifying a directory, match everything below it
|
27
|
+
pattern += "*" if pattern.end_with?("/")
|
28
|
+
|
29
|
+
# The pattern will be scoped to root directory, so it should match anything
|
30
|
+
# within that space
|
31
|
+
pattern.prepend("*") unless pattern.start_with?("*")
|
32
|
+
|
33
|
+
pattern
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,8 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "filter/path_matcher"
|
4
|
+
|
3
5
|
module ShopifyCLI
|
4
6
|
module Theme
|
5
7
|
class IgnoreFilter
|
8
|
+
include Filter::PathMatcher
|
9
|
+
|
6
10
|
FILE = ".shopifyignore"
|
7
11
|
|
8
12
|
DEFAULT_REGEXES = [
|
@@ -72,11 +76,11 @@ module ShopifyCLI
|
|
72
76
|
return true if path.empty?
|
73
77
|
|
74
78
|
regexes.each do |regex|
|
75
|
-
return true if regex
|
79
|
+
return true if regex_match?(regex, path)
|
76
80
|
end
|
77
81
|
|
78
82
|
globs.each do |glob|
|
79
|
-
return true if
|
83
|
+
return true if glob_match?(glob, path)
|
80
84
|
end
|
81
85
|
|
82
86
|
false
|
@@ -91,24 +95,16 @@ module ShopifyCLI
|
|
91
95
|
new_regexes = DEFAULT_REGEXES.dup
|
92
96
|
new_globs = DEFAULT_GLOBS.dup
|
93
97
|
|
94
|
-
patterns
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
98
|
+
patterns
|
99
|
+
.map(&:strip)
|
100
|
+
.each do |pattern|
|
101
|
+
if regex?(pattern)
|
102
|
+
new_regexes << as_regex(pattern)
|
103
|
+
else
|
104
|
+
new_globs << as_glob(pattern)
|
105
|
+
end
|
100
106
|
end
|
101
107
|
|
102
|
-
# if specifying a directory, match everything below it
|
103
|
-
pattern += "*" if pattern.end_with?("/")
|
104
|
-
|
105
|
-
# The pattern will be scoped to root directory, so it should match anything
|
106
|
-
# within that space
|
107
|
-
pattern.prepend("*") unless pattern.start_with?("*")
|
108
|
-
|
109
|
-
new_globs << pattern
|
110
|
-
end
|
111
|
-
|
112
108
|
[new_regexes, new_globs]
|
113
109
|
end
|
114
110
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "filter/path_matcher"
|
4
|
+
|
5
|
+
module ShopifyCLI
|
6
|
+
module Theme
|
7
|
+
class IncludeFilter
|
8
|
+
include Filter::PathMatcher
|
9
|
+
|
10
|
+
attr_reader :globs, :regexes
|
11
|
+
|
12
|
+
def initialize(patterns = [])
|
13
|
+
@patterns = patterns.nil? ? [] : patterns.compact.reject(&:empty?)
|
14
|
+
|
15
|
+
regexes, globs = patterns_to_regexes_and_globs(@patterns)
|
16
|
+
|
17
|
+
@regexes = regexes
|
18
|
+
@globs = globs
|
19
|
+
end
|
20
|
+
|
21
|
+
def match?(path)
|
22
|
+
return true unless present?(@patterns)
|
23
|
+
|
24
|
+
path = path.to_s
|
25
|
+
|
26
|
+
return true if path.empty?
|
27
|
+
|
28
|
+
regexes.each do |regex|
|
29
|
+
return true if regex_match?(regex, path)
|
30
|
+
end
|
31
|
+
|
32
|
+
globs.each do |glob|
|
33
|
+
return true if glob_match?(glob, path)
|
34
|
+
end
|
35
|
+
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def present?(patterns)
|
42
|
+
!patterns.nil? && !patterns.empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
# Take in string patterns and convert them to either
|
46
|
+
# regex patterns or glob patterns so that they are handled in an expected manner.
|
47
|
+
def patterns_to_regexes_and_globs(patterns)
|
48
|
+
new_regexes = []
|
49
|
+
new_globs = []
|
50
|
+
|
51
|
+
patterns
|
52
|
+
.map(&:strip)
|
53
|
+
.each do |pattern|
|
54
|
+
if regex?(pattern)
|
55
|
+
new_regexes << as_regex(pattern)
|
56
|
+
else
|
57
|
+
new_globs << as_glob(pattern)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
[new_regexes, new_globs]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -16,13 +16,15 @@ module ShopifyCLI
|
|
16
16
|
API_VERSION = "unstable"
|
17
17
|
|
18
18
|
attr_reader :checksums
|
19
|
+
attr_accessor :include_filter
|
19
20
|
attr_accessor :ignore_filter
|
20
21
|
|
21
22
|
def_delegators :@error_reporter, :has_any_error?
|
22
23
|
|
23
|
-
def initialize(ctx, theme:, ignore_filter: nil)
|
24
|
+
def initialize(ctx, theme:, include_filter: nil, ignore_filter: nil)
|
24
25
|
@ctx = ctx
|
25
26
|
@theme = theme
|
27
|
+
@include_filter = include_filter
|
26
28
|
@ignore_filter = ignore_filter
|
27
29
|
@error_reporter = ErrorReporter.new(ctx)
|
28
30
|
@standard_reporter = StandardReporter.new(ctx)
|
@@ -193,7 +195,7 @@ module ShopifyCLI
|
|
193
195
|
# Already enqueued
|
194
196
|
return if @pending.include?(operation)
|
195
197
|
|
196
|
-
if
|
198
|
+
if ignore?(operation)
|
197
199
|
@ctx.debug("ignore #{operation.file_path}")
|
198
200
|
return
|
199
201
|
end
|
@@ -251,6 +253,19 @@ module ShopifyCLI
|
|
251
253
|
response
|
252
254
|
end
|
253
255
|
|
256
|
+
def ignore?(operation)
|
257
|
+
path = operation.file_path
|
258
|
+
ignored_by_ignore_filter?(path) || ignored_by_include_filter?(path)
|
259
|
+
end
|
260
|
+
|
261
|
+
def ignored_by_ignore_filter?(path)
|
262
|
+
ignore_filter&.ignore?(path)
|
263
|
+
end
|
264
|
+
|
265
|
+
def ignored_by_include_filter?(path)
|
266
|
+
include_filter && !include_filter.match?(path)
|
267
|
+
end
|
268
|
+
|
254
269
|
def get(file)
|
255
270
|
_status, body, response = ShopifyCLI::AdminAPI.rest_request(
|
256
271
|
@ctx,
|
data/lib/shopify_cli/version.rb
CHANGED
data/lib/shopify_cli.rb
CHANGED
@@ -15,12 +15,13 @@ ENV["PATH"] = ENV["PATH"].split(":").select { |p| p.start_with?("/", "~") }.join
|
|
15
15
|
vendor_path = File.expand_path("../../vendor/lib", __FILE__)
|
16
16
|
$LOAD_PATH.unshift(vendor_path) unless $LOAD_PATH.include?(vendor_path)
|
17
17
|
|
18
|
-
deps = %w(cli-ui cli-kit smart_properties webrick)
|
18
|
+
deps = %w(cli-ui cli-kit smart_properties ruby2_keywords webrick)
|
19
19
|
deps.each do |dep|
|
20
20
|
vendor_path = File.expand_path("../../vendor/deps/#{dep}/lib", __FILE__)
|
21
21
|
$LOAD_PATH.unshift(vendor_path) unless $LOAD_PATH.include?(vendor_path)
|
22
22
|
end
|
23
23
|
|
24
|
+
require "ruby2_keywords"
|
24
25
|
require "cli/ui"
|
25
26
|
require "cli/kit"
|
26
27
|
require "smart_properties"
|
@@ -135,6 +136,7 @@ module ShopifyCLI
|
|
135
136
|
autoload :Tasks, "shopify_cli/tasks"
|
136
137
|
autoload :TransformDataStructure, "shopify_cli/transform_data_structure"
|
137
138
|
autoload :Tunnel, "shopify_cli/tunnel"
|
139
|
+
autoload :Utilities, "shopify_cli/utilities"
|
138
140
|
|
139
141
|
require "shopify_cli/messages/messages"
|
140
142
|
Context.load_messages(ShopifyCLI::Messages::MESSAGES)
|
@@ -174,11 +174,16 @@ module CLI
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def os
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
177
|
+
@current_os ||= case RbConfig::CONFIG['host_os']
|
178
|
+
when /darwin/ then :mac
|
179
|
+
when /linux/ then :linux
|
180
|
+
else
|
181
|
+
if RUBY_PLATFORM !~ /cygwin/ && ENV['OS'] == 'Windows_NT'
|
182
|
+
:windows
|
183
|
+
else
|
184
|
+
raise "Could not determine OS from host_os #{RbConfig::CONFIG["host_os"]}"
|
185
|
+
end
|
186
|
+
end
|
182
187
|
end
|
183
188
|
|
184
189
|
private
|
@@ -222,7 +227,7 @@ module CLI
|
|
222
227
|
end
|
223
228
|
|
224
229
|
def which(cmd, env)
|
225
|
-
exts = os == :windows
|
230
|
+
exts = (os == :windows && env['PATHEXT']&.split(';')) || ['']
|
226
231
|
env.fetch('PATH', '').split(File::PATH_SEPARATOR).each do |path|
|
227
232
|
exts.each do |ext|
|
228
233
|
exe = File.join(path, "#{cmd}#{ext}")
|
@@ -168,9 +168,13 @@ module CLI
|
|
168
168
|
@block_that_might_raise = block_that_might_raise
|
169
169
|
end
|
170
170
|
|
171
|
-
def retry_after(exception = StandardError, retries: 1, &before_retry)
|
171
|
+
def retry_after(exception = StandardError, retries: 1, only: nil, &before_retry)
|
172
172
|
@block_that_might_raise.call
|
173
173
|
rescue exception => e
|
174
|
+
should_retry = only ? only.call : true
|
175
|
+
|
176
|
+
raise unless should_retry
|
177
|
+
|
174
178
|
raise if (retries -= 1) < 0
|
175
179
|
if before_retry
|
176
180
|
if before_retry.arity == 0
|
@@ -4,15 +4,17 @@ module CLI
|
|
4
4
|
# Determines which OS is currently running the UI, to make it easier to
|
5
5
|
# adapt its behaviour to the features of the OS.
|
6
6
|
def self.current
|
7
|
-
@current_os ||= case
|
7
|
+
@current_os ||= case RbConfig::CONFIG['host_os']
|
8
8
|
when /darwin/
|
9
9
|
Mac
|
10
10
|
when /linux/
|
11
11
|
Linux
|
12
|
-
when /mingw32/
|
13
|
-
Windows
|
14
12
|
else
|
15
|
-
|
13
|
+
if RUBY_PLATFORM !~ /cygwin/ && ENV['OS'] == 'Windows_NT'
|
14
|
+
Windows
|
15
|
+
else
|
16
|
+
raise "Could not determine OS from host_os #{RbConfig::CONFIG["host_os"]}"
|
17
|
+
end
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright 2019-2020 Nobuyoshi Nakada, Yusuke Endoh
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
7
|
+
list of conditions and the following disclaimer.
|
8
|
+
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
15
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
16
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
17
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
18
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
19
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
20
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
21
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
22
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|