shopify-cli 2.9.0 → 2.11.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/.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.
|