shopify-cli 2.29.0 → 2.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile.lock +1 -1
  4. data/lib/project_types/theme/commands/package.rb +20 -5
  5. data/lib/project_types/theme/messages/messages.rb +4 -2
  6. data/lib/shopify_cli/packager.rb +5 -14
  7. data/lib/shopify_cli/theme/backoff_helper.rb +47 -0
  8. data/lib/shopify_cli/theme/ignore_helper.rb +7 -1
  9. data/lib/shopify_cli/theme/syncer/downloader.rb +63 -0
  10. data/lib/shopify_cli/theme/syncer/uploader/bulk.rb +133 -0
  11. data/lib/shopify_cli/theme/syncer/uploader/bulk_item.rb +64 -0
  12. data/lib/shopify_cli/theme/syncer/uploader/bulk_job.rb +139 -0
  13. data/lib/shopify_cli/theme/syncer/uploader/bulk_request.rb +30 -0
  14. data/lib/shopify_cli/theme/syncer/uploader/forms/apply_to_all.rb +41 -0
  15. data/lib/shopify_cli/theme/syncer/uploader/forms/apply_to_all_form.rb +37 -0
  16. data/lib/shopify_cli/theme/syncer/uploader/forms/base_strategy_form.rb +64 -0
  17. data/lib/shopify_cli/theme/syncer/uploader/forms/select_delete_strategy.rb +29 -0
  18. data/lib/shopify_cli/theme/syncer/uploader/forms/select_update_strategy.rb +30 -0
  19. data/lib/shopify_cli/theme/syncer/uploader/json_delete_handler.rb +49 -0
  20. data/lib/shopify_cli/theme/syncer/uploader/json_update_handler.rb +71 -0
  21. data/lib/shopify_cli/theme/syncer/uploader.rb +227 -0
  22. data/lib/shopify_cli/theme/syncer.rb +91 -144
  23. data/lib/shopify_cli/version.rb +1 -1
  24. metadata +16 -16
  25. data/lib/shopify_cli/theme/syncer/forms/apply_to_all.rb +0 -39
  26. data/lib/shopify_cli/theme/syncer/forms/apply_to_all_form.rb +0 -35
  27. data/lib/shopify_cli/theme/syncer/forms/base_strategy_form.rb +0 -62
  28. data/lib/shopify_cli/theme/syncer/forms/select_delete_strategy.rb +0 -27
  29. data/lib/shopify_cli/theme/syncer/forms/select_update_strategy.rb +0 -28
  30. data/lib/shopify_cli/theme/syncer/json_delete_handler.rb +0 -51
  31. data/lib/shopify_cli/theme/syncer/json_update_handler.rb +0 -96
  32. data/lib/shopify_cli/theme/theme_admin_api_throttler/bulk.rb +0 -102
  33. data/lib/shopify_cli/theme/theme_admin_api_throttler/bulk_job.rb +0 -75
  34. data/lib/shopify_cli/theme/theme_admin_api_throttler/errors.rb +0 -7
  35. data/lib/shopify_cli/theme/theme_admin_api_throttler/put_request.rb +0 -52
  36. data/lib/shopify_cli/theme/theme_admin_api_throttler/request_parser.rb +0 -39
  37. data/lib/shopify_cli/theme/theme_admin_api_throttler/response_parser.rb +0 -21
  38. data/lib/shopify_cli/theme/theme_admin_api_throttler.rb +0 -62
@@ -5,17 +5,18 @@ require "json"
5
5
  require "base64"
6
6
  require "forwardable"
7
7
 
8
+ require_relative "backoff_helper"
9
+ require_relative "ignore_helper"
10
+ require_relative "theme_admin_api"
11
+
8
12
  require_relative "syncer/checksums"
13
+ require_relative "syncer/downloader"
9
14
  require_relative "syncer/error_reporter"
10
- require_relative "syncer/json_delete_handler"
11
- require_relative "syncer/json_update_handler"
12
15
  require_relative "syncer/merger"
13
16
  require_relative "syncer/operation"
14
17
  require_relative "syncer/standard_reporter"
15
18
  require_relative "syncer/unsupported_script_warning"
16
- require_relative "theme_admin_api"
17
- require_relative "ignore_helper"
18
- require_relative "theme_admin_api_throttler"
19
+ require_relative "syncer/uploader"
19
20
 
20
21
  module ShopifyCLI
21
22
  module Theme
@@ -23,8 +24,7 @@ module ShopifyCLI
23
24
  extend Forwardable
24
25
 
25
26
  include ShopifyCLI::Theme::IgnoreHelper
26
- include JsonDeleteHandler
27
- include JsonUpdateHandler
27
+ include ShopifyCLI::Theme::BackoffHelper
28
28
 
29
29
  QUEUEABLE_METHODS = [
30
30
  :get, # - Updates the local file with the remote file content
@@ -33,7 +33,7 @@ module ShopifyCLI
33
33
  :union_merge, # - Union merges the local file content with the remote file content
34
34
  ]
35
35
 
36
- attr_reader :theme, :checksums, :error_checksums, :api_client
36
+ attr_reader :ctx, :theme, :checksums, :error_checksums, :api_client, :pending
37
37
  attr_accessor :include_filter, :ignore_filter
38
38
 
39
39
  def_delegators :@error_reporter, :has_any_error?
@@ -57,12 +57,6 @@ module ShopifyCLI
57
57
  # Thread making the API requests.
58
58
  @threads = []
59
59
 
60
- # Mutex used to pause all threads when backing-off when hitting API rate limits
61
- @backoff_mutex = Mutex.new
62
-
63
- # Mutex used to coordinate changes in the `pending` list
64
- @pending_mutex = Mutex.new
65
-
66
60
  # Latest theme assets checksums. Updated on each upload.
67
61
  @checksums = Checksums.new(theme)
68
62
 
@@ -71,14 +65,14 @@ module ShopifyCLI
71
65
 
72
66
  # Do not use the throttler when --stable is passed or a Theme Access password is set
73
67
  # (Theme Access API is not compatible yet with bulks)
74
- throttler_enabled = !stable && !Environment.theme_access_password?
68
+ @bulk_updates_activated = !stable && !Environment.theme_access_password?
75
69
 
76
70
  # Initialize `api_client` on main thread
77
- @api_client = ThemeAdminAPIThrottler.new(
78
- @ctx,
79
- ThemeAdminAPI.new(@ctx, @theme.shop),
80
- throttler_enabled
81
- )
71
+ @api_client = ThemeAdminAPI.new(ctx, theme.shop)
72
+
73
+ # Initialize backoff helper on main thread to pause all threads when the
74
+ # requests are reaching API rate limits.
75
+ initialize_backoff_helper!
82
76
  end
83
77
 
84
78
  def lock_io!
@@ -146,7 +140,6 @@ module ShopifyCLI
146
140
  end
147
141
 
148
142
  def shutdown
149
- api_client.shutdown
150
143
  @queue.close unless @queue.closed?
151
144
  ensure
152
145
  @threads.each { |thread| thread.join if thread.alive? }
@@ -169,64 +162,70 @@ module ShopifyCLI
169
162
  end
170
163
 
171
164
  def upload_theme!(delay_low_priority_files: false, delete: true, &block)
172
- fetch_checksums!
173
-
174
- if delete
175
- removed_json_files, removed_files = checksums
176
- .keys
177
- .-(@theme.theme_files.map(&:relative_path))
178
- .map { |file| @theme[file] }
179
- .partition(&:json?)
165
+ uploader = Uploader.new(self, delete, delay_low_priority_files, &block)
166
+ uploader.upload!
167
+ end
180
168
 
181
- enqueue_deletes(removed_files)
182
- enqueue_json_deletes(removed_json_files)
183
- end
169
+ def download_theme!(delete: true, &block)
170
+ downloader = Downloader.new(self, delete, &block)
171
+ downloader.download!
172
+ end
184
173
 
185
- enqueue_updates(@theme.liquid_files)
186
- enqueue_json_updates(@theme.json_files)
174
+ def bulk_updates_activated?
175
+ @bulk_updates_activated
176
+ end
187
177
 
188
- if delay_low_priority_files
189
- # Wait for liquid & JSON files to upload, because those are rendered remotely
190
- wait!(&block)
191
- end
178
+ def enqueueable?(operation)
179
+ file = operation.file
180
+ method = operation.method
192
181
 
193
- # Process lower-priority files in the background
182
+ # Already enqueued or ignored
183
+ return false if @pending.include?(operation) || ignore_operation?(operation)
194
184
 
195
- # Assets are served locally, so can be uploaded in the background
196
- enqueue_updates(@theme.static_asset_files)
185
+ if [:update, :get].include?(method) && file.exist?
186
+ # File is fixed (and it has been never updated)
187
+ if !!@error_checksums.delete(file.checksum)
188
+ @standard_reporter.report(operation.as_fix_message)
189
+ end
197
190
 
198
- unless delay_low_priority_files
199
- wait!(&block)
191
+ return checksums.file_has_changed?(file)
200
192
  end
201
193
 
202
- api_client.deactivate_throttler!
203
- enqueue_delayed_files_updates
194
+ true
204
195
  end
205
196
 
206
- def download_theme!(delete: true, &block)
207
- fetch_checksums!
208
-
209
- if delete
210
- # Delete local files not present remotely
211
- missing_files = @theme.theme_files
212
- .reject { |file| checksums.has?(file) }.uniq
213
- .reject { |file| ignore_file?(file) }
214
- missing_files.each do |file|
215
- @ctx.debug("rm #{file.relative_path}")
216
- file.delete
217
- end
197
+ def handle_operation_error(operation, error)
198
+ error_suffix = ":\n " + parse_api_errors(operation, error).join("\n ")
199
+ report_error(operation, error_suffix)
200
+ end
201
+
202
+ def overwrite_json?
203
+ theme_created_at_runtime? || @overwrite_json
204
+ end
205
+
206
+ def update_checksums(api_response)
207
+ api_response.values.flatten.each do |asset|
208
+ next unless asset["key"]
209
+ checksums[asset["key"]] = asset["checksum"]
218
210
  end
219
211
 
220
- enqueue_get(checksums.keys)
212
+ checksums.reject_duplicated_checksums!
213
+ end
214
+
215
+ def report_file_error(file, error_message = "")
216
+ path = file.relative_path
221
217
 
222
- wait!(&block)
218
+ @error_checksums << checksums[path]
219
+ @error_reporter.report(error_message)
223
220
  end
224
221
 
225
222
  private
226
223
 
227
224
  def report_error(operation, error_suffix = "")
228
- @error_checksums << checksums[operation.file_path]
229
- @error_reporter.report("#{operation.as_error_message}#{error_suffix}")
225
+ file = operation.file
226
+ error_message = "#{operation.as_error_message}#{error_suffix}"
227
+
228
+ report_file_error(file, error_message)
230
229
  end
231
230
 
232
231
  def enqueue(method, file)
@@ -235,22 +234,24 @@ module ShopifyCLI
235
234
 
236
235
  operation = Operation.new(@ctx, method, @theme[file])
237
236
 
238
- # Already enqueued
239
- return if @pending.include?(operation)
237
+ return unless enqueueable?(operation)
240
238
 
241
- if ignore_operation?(operation)
242
- @ctx.debug("ignore #{operation.file_path}")
243
- return
244
- end
239
+ @pending << operation
240
+ @queue << operation unless @queue.closed?
241
+ end
245
242
 
246
- if [:update, :get].include?(method) && operation.file.exist?
247
- is_fixed = !!@error_checksums.delete(operation.file.checksum)
248
- @standard_reporter.report(operation.as_fix_message) if is_fixed
249
- return unless checksums.file_has_changed?(operation.file)
243
+ def report_performed_operation(operation)
244
+ file = operation.file
245
+
246
+ if file.warnings.any?
247
+ warning_message =
248
+ operation.as_synced_message(color: :yellow) +
249
+ UnsupportedScriptWarning.new(@ctx, file).to_s
250
+
251
+ return @error_reporter.report(warning_message)
250
252
  end
251
253
 
252
- @pending << operation
253
- @queue << operation unless @queue.closed?
254
+ @standard_reporter.report(operation.as_synced_message)
254
255
  end
255
256
 
256
257
  def perform(operation)
@@ -258,36 +259,15 @@ module ShopifyCLI
258
259
  wait_for_backoff!
259
260
  @ctx.debug(operation.to_s)
260
261
 
261
- send(operation.method, operation.file) do |response|
262
- raise response if response.is_a?(StandardError)
263
-
264
- file = operation.file
262
+ response = send(operation.method, operation.file)
265
263
 
266
- if file.warnings.any?
267
- warning_message =
268
- operation.as_synced_message(color: :yellow) +
269
- UnsupportedScriptWarning.new(@ctx, file).to_s
270
- @error_reporter.report(warning_message)
271
- else
272
- @standard_reporter.report(operation.as_synced_message)
273
- end
264
+ report_performed_operation(operation)
265
+ backoff_if_near_limit!(response)
274
266
 
275
- # Check if the API told us we're near the rate limit
276
- if !backingoff? && (limit = response["x-shopify-shop-api-call-limit"])
277
- used, total = limit.split("/").map(&:to_i)
278
- backoff_if_near_limit!(used, total)
279
- end
280
- rescue StandardError => error
281
- handle_operation_error(operation, error)
282
- ensure
283
- @pending_mutex.synchronize do
284
- # Avoid abrupt jumps in the progress bar
285
- wait(0.05)
286
- @pending.delete(operation)
287
- end
288
- end
289
267
  rescue StandardError => error
290
268
  handle_operation_error(operation, error)
269
+ ensure
270
+ @pending.delete(operation)
291
271
  end
292
272
 
293
273
  def update(file)
@@ -300,15 +280,16 @@ module ShopifyCLI
300
280
  end
301
281
 
302
282
  path = "themes/#{@theme.id}/assets.json"
303
- req_body = JSON.generate(asset: asset)
304
283
 
305
- api_client.put(path: path, body: req_body) do |_status, resp_body, response|
306
- update_checksums(resp_body)
284
+ _status, body, response = api_client.put(
285
+ path: path,
286
+ body: JSON.generate(asset: asset)
287
+ )
288
+ file.warnings = body.dig("asset", "warnings")
307
289
 
308
- file.warnings = resp_body.dig("asset", "warnings")
290
+ update_checksums(body)
309
291
 
310
- yield(response) if block_given?
311
- end
292
+ response
312
293
  end
313
294
 
314
295
  def get(file)
@@ -326,7 +307,7 @@ module ShopifyCLI
326
307
  file.write(body.dig("asset", "value"))
327
308
  end
328
309
 
329
- yield(response)
310
+ response
330
311
  end
331
312
 
332
313
  def delete(file)
@@ -337,7 +318,7 @@ module ShopifyCLI
337
318
  })
338
319
  )
339
320
 
340
- yield(response)
321
+ response
341
322
  end
342
323
 
343
324
  def union_merge(file)
@@ -346,11 +327,11 @@ module ShopifyCLI
346
327
  query: URI.encode_www_form("asset[key]" => file.relative_path),
347
328
  )
348
329
 
349
- return yield(response) unless file.text?
330
+ return response unless file.text?
350
331
 
351
332
  remote_content = body.dig("asset", "value")
352
333
 
353
- return yield(response) if remote_content.nil?
334
+ return response if remote_content.nil?
354
335
 
355
336
  content = Merger.union_merge(file, remote_content)
356
337
 
@@ -358,16 +339,7 @@ module ShopifyCLI
358
339
 
359
340
  enqueue(:update, file)
360
341
 
361
- yield(response)
362
- end
363
-
364
- def update_checksums(api_response)
365
- api_response.values.flatten.each do |asset|
366
- next unless asset["key"]
367
- checksums[asset["key"]] = asset["checksum"]
368
- end
369
-
370
- checksums.reject_duplicated_checksums!
342
+ response
371
343
  end
372
344
 
373
345
  def parse_api_errors(operation, exception)
@@ -397,35 +369,10 @@ module ShopifyCLI
397
369
  ["The asset #{operation.file} could not be synced #{cause} #{backtrace}"]
398
370
  end
399
371
 
400
- def backoff_if_near_limit!(used, limit)
401
- if used > limit - @threads.size
402
- @ctx.debug("Near API call limit, waiting 2 sec…")
403
- @backoff_mutex.synchronize { wait(2) }
404
- end
405
- end
406
-
407
- def overwrite_json?
408
- theme_created_at_runtime? || @overwrite_json
409
- end
410
-
411
372
  def theme_created_at_runtime?
412
373
  @theme.created_at_runtime?
413
374
  end
414
375
 
415
- def backingoff?
416
- @backoff_mutex.locked?
417
- end
418
-
419
- def wait_for_backoff!
420
- # Sleeping in the mutex in another thread. Wait for unlock
421
- @backoff_mutex.synchronize {} if backingoff?
422
- end
423
-
424
- def handle_operation_error(operation, error)
425
- error_suffix = ":\n " + parse_api_errors(operation, error).join("\n ")
426
- report_error(operation, error_suffix)
427
- end
428
-
429
376
  def wait(duration)
430
377
  sleep(duration)
431
378
  end
@@ -1,3 +1,3 @@
1
1
  module ShopifyCLI
2
- VERSION = "2.29.0"
2
+ VERSION = "2.30.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.29.0
4
+ version: 2.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-19 00:00:00.000000000 Z
11
+ date: 2022-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -456,6 +456,7 @@ files:
456
456
  - lib/shopify_cli/tasks/ensure_project_type.rb
457
457
  - lib/shopify_cli/tasks/select_org_and_shop.rb
458
458
  - lib/shopify_cli/tasks/update_dashboard_urls.rb
459
+ - lib/shopify_cli/theme/backoff_helper.rb
459
460
  - lib/shopify_cli/theme/dev_server.rb
460
461
  - lib/shopify_cli/theme/dev_server/cdn_fonts.rb
461
462
  - lib/shopify_cli/theme/dev_server/certificate_manager.rb
@@ -504,28 +505,27 @@ files:
504
505
  - lib/shopify_cli/theme/root.rb
505
506
  - lib/shopify_cli/theme/syncer.rb
506
507
  - lib/shopify_cli/theme/syncer/checksums.rb
508
+ - lib/shopify_cli/theme/syncer/downloader.rb
507
509
  - lib/shopify_cli/theme/syncer/error_reporter.rb
508
- - lib/shopify_cli/theme/syncer/forms/apply_to_all.rb
509
- - lib/shopify_cli/theme/syncer/forms/apply_to_all_form.rb
510
- - lib/shopify_cli/theme/syncer/forms/base_strategy_form.rb
511
- - lib/shopify_cli/theme/syncer/forms/select_delete_strategy.rb
512
- - lib/shopify_cli/theme/syncer/forms/select_update_strategy.rb
513
- - lib/shopify_cli/theme/syncer/json_delete_handler.rb
514
- - lib/shopify_cli/theme/syncer/json_update_handler.rb
515
510
  - lib/shopify_cli/theme/syncer/merger.rb
516
511
  - lib/shopify_cli/theme/syncer/operation.rb
517
512
  - lib/shopify_cli/theme/syncer/standard_reporter.rb
518
513
  - lib/shopify_cli/theme/syncer/unsupported_script_warning.rb
514
+ - lib/shopify_cli/theme/syncer/uploader.rb
515
+ - lib/shopify_cli/theme/syncer/uploader/bulk.rb
516
+ - lib/shopify_cli/theme/syncer/uploader/bulk_item.rb
517
+ - lib/shopify_cli/theme/syncer/uploader/bulk_job.rb
518
+ - lib/shopify_cli/theme/syncer/uploader/bulk_request.rb
519
+ - lib/shopify_cli/theme/syncer/uploader/forms/apply_to_all.rb
520
+ - lib/shopify_cli/theme/syncer/uploader/forms/apply_to_all_form.rb
521
+ - lib/shopify_cli/theme/syncer/uploader/forms/base_strategy_form.rb
522
+ - lib/shopify_cli/theme/syncer/uploader/forms/select_delete_strategy.rb
523
+ - lib/shopify_cli/theme/syncer/uploader/forms/select_update_strategy.rb
524
+ - lib/shopify_cli/theme/syncer/uploader/json_delete_handler.rb
525
+ - lib/shopify_cli/theme/syncer/uploader/json_update_handler.rb
519
526
  - lib/shopify_cli/theme/theme.rb
520
527
  - lib/shopify_cli/theme/theme_access_api.rb
521
528
  - lib/shopify_cli/theme/theme_admin_api.rb
522
- - lib/shopify_cli/theme/theme_admin_api_throttler.rb
523
- - lib/shopify_cli/theme/theme_admin_api_throttler/bulk.rb
524
- - lib/shopify_cli/theme/theme_admin_api_throttler/bulk_job.rb
525
- - lib/shopify_cli/theme/theme_admin_api_throttler/errors.rb
526
- - lib/shopify_cli/theme/theme_admin_api_throttler/put_request.rb
527
- - lib/shopify_cli/theme/theme_admin_api_throttler/request_parser.rb
528
- - lib/shopify_cli/theme/theme_admin_api_throttler/response_parser.rb
529
529
  - lib/shopify_cli/thread_pool.rb
530
530
  - lib/shopify_cli/thread_pool/job.rb
531
531
  - lib/shopify_cli/transform_data_structure.rb
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "apply_to_all_form"
4
-
5
- module ShopifyCLI
6
- module Theme
7
- class Syncer
8
- module Forms
9
- class ApplyToAll
10
- attr_reader :value
11
-
12
- def initialize(ctx, number_of_files)
13
- @ctx = ctx
14
- @number_of_files = number_of_files
15
- @value = nil
16
- @apply = nil
17
- end
18
-
19
- def apply?(value)
20
- return unless @number_of_files > 1
21
-
22
- if @apply.nil?
23
- @apply = ask.apply?
24
- @value = value if @apply
25
- end
26
-
27
- @apply
28
- end
29
-
30
- private
31
-
32
- def ask
33
- ApplyToAllForm.ask(@ctx, [], number_of_files: @number_of_files)
34
- end
35
- end
36
- end
37
- end
38
- end
39
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ShopifyCLI
4
- module Theme
5
- class Syncer
6
- module Forms
7
- class ApplyToAllForm < ShopifyCLI::Form
8
- attr_accessor :apply
9
- flag_arguments :number_of_files
10
-
11
- def ask
12
- title = message("title", number_of_files - 1)
13
-
14
- self.apply = CLI::UI::Prompt.ask(title, allow_empty: false) do |handler|
15
- handler.option(message("yes")) { true }
16
- handler.option(message("no")) { false }
17
- end
18
-
19
- self
20
- end
21
-
22
- def apply?
23
- apply
24
- end
25
-
26
- private
27
-
28
- def message(key, *params)
29
- ctx.message("theme.serve.syncer.forms.apply_to_all.#{key}", *params)
30
- end
31
- end
32
- end
33
- end
34
- end
35
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ShopifyCLI
4
- module Theme
5
- class Syncer
6
- module Forms
7
- class BaseStrategyForm < ShopifyCLI::Form
8
- attr_accessor :strategy
9
-
10
- def ask
11
- ctx.puts(title_context(file))
12
-
13
- self.strategy = CLI::UI::Prompt.ask(title_question, allow_empty: false) do |handler|
14
- strategies.each do |strategy|
15
- handler.option(as_text(strategy)) { strategy }
16
- end
17
- end
18
-
19
- exit_cli if self.strategy == :exit
20
-
21
- self
22
- end
23
-
24
- protected
25
-
26
- ##
27
- # List of strategies that populate the form options
28
- #
29
- def strategies
30
- raise "`#{self.class.name}#strategies' must be defined"
31
- end
32
-
33
- ##
34
- # Message prefix for the form title and options (strategies).
35
- # See the methods `title` and `as_text`
36
- #
37
- def prefix
38
- raise "`#{self.class.name}#prefix' must be defined"
39
- end
40
-
41
- private
42
-
43
- def exit_cli
44
- exit(0)
45
- end
46
-
47
- def title_context(file)
48
- ctx.message("#{prefix}.title_context", file.relative_path)
49
- end
50
-
51
- def title_question
52
- ctx.message("#{prefix}.title_question")
53
- end
54
-
55
- def as_text(strategy)
56
- ctx.message("#{prefix}.#{strategy}")
57
- end
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "base_strategy_form"
4
-
5
- module ShopifyCLI
6
- module Theme
7
- class Syncer
8
- module Forms
9
- class SelectDeleteStrategy < BaseStrategyForm
10
- flag_arguments :file
11
-
12
- def strategies
13
- %i[
14
- delete
15
- restore
16
- exit
17
- ]
18
- end
19
-
20
- def prefix
21
- "theme.serve.syncer.forms.delete_strategy"
22
- end
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "base_strategy_form"
4
-
5
- module ShopifyCLI
6
- module Theme
7
- class Syncer
8
- module Forms
9
- class SelectUpdateStrategy < BaseStrategyForm
10
- flag_arguments :file, :exists_remotely
11
-
12
- def strategies
13
- %i[
14
- keep_remote
15
- keep_local
16
- union_merge
17
- exit
18
- ]
19
- end
20
-
21
- def prefix
22
- "theme.serve.syncer.forms.#{exists_remotely ? "update_strategy" : "update_remote_deleted_strategy"}"
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end