shopify-cli 2.29.0 → 2.30.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.
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