Class: ShopifyCLI::Theme::Syncer
- Inherits:
-
Object
- Object
- ShopifyCLI::Theme::Syncer
show all
- Extended by:
- Forwardable
- Includes:
- BackoffHelper, IgnoreHelper
- Defined in:
- lib/shopify_cli/theme/syncer.rb,
lib/shopify_cli/theme/syncer/merger.rb,
lib/shopify_cli/theme/syncer/uploader.rb,
lib/shopify_cli/theme/syncer/checksums.rb,
lib/shopify_cli/theme/syncer/operation.rb,
lib/shopify_cli/theme/syncer/downloader.rb,
lib/shopify_cli/theme/syncer/uploader/bulk.rb,
lib/shopify_cli/theme/syncer/error_reporter.rb,
lib/shopify_cli/theme/syncer/standard_reporter.rb,
lib/shopify_cli/theme/syncer/uploader/bulk_job.rb,
lib/shopify_cli/theme/syncer/uploader/bulk_item.rb,
lib/shopify_cli/theme/syncer/uploader/bulk_request.rb,
lib/shopify_cli/theme/syncer/unsupported_script_warning.rb,
lib/shopify_cli/theme/syncer/uploader/forms/apply_to_all.rb,
lib/shopify_cli/theme/syncer/uploader/json_delete_handler.rb,
lib/shopify_cli/theme/syncer/uploader/json_update_handler.rb,
lib/shopify_cli/theme/syncer/uploader/forms/apply_to_all_form.rb,
lib/shopify_cli/theme/syncer/uploader/forms/base_strategy_form.rb,
lib/shopify_cli/theme/syncer/uploader/forms/select_delete_strategy.rb,
lib/shopify_cli/theme/syncer/uploader/forms/select_update_strategy.rb
Defined Under Namespace
Classes: Checksums, Downloader, ErrorReporter, Merger, Operation, StandardReporter, UnsupportedScriptWarning, Uploader
Constant Summary
collapse
- QUEUEABLE_METHODS =
[
:get, :update, :delete, :union_merge, ]
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#broken_file?(file) ⇒ Boolean
-
#bulk_updates_activated? ⇒ Boolean
-
#download_theme!(delete: true, &block) ⇒ Object
-
#empty? ⇒ Boolean
-
#enqueue_deletes(files) ⇒ Object
-
#enqueue_get(files) ⇒ Object
-
#enqueue_union_merges(files) ⇒ Object
-
#enqueue_updates(files) ⇒ Object
-
#enqueueable?(operation) ⇒ Boolean
-
#fetch_checksums! ⇒ Object
-
#handle_operation_error(operation, error) ⇒ Object
-
#initialize(ctx, theme:, include_filter: nil, ignore_filter: nil, overwrite_json: true, stable: false) ⇒ Syncer
constructor
A new instance of Syncer.
-
#lock_io! ⇒ Object
-
#overwrite_json? ⇒ Boolean
-
#parse_api_errors(file, exception) ⇒ Object
-
#pending_updates ⇒ Object
-
#remote_file?(file) ⇒ Boolean
-
#report_file_error(file, error_message = "") ⇒ Object
-
#shutdown ⇒ Object
-
#size ⇒ Object
-
#start_threads(count = 2) ⇒ Object
-
#unlock_io! ⇒ Object
-
#update_checksums(api_response) ⇒ Object
-
#upload_theme!(delay_low_priority_files: false, delete: true, &block) ⇒ Object
-
#wait! ⇒ Object
#backingoff?, #backoff!, #backoff_if_near_limit!, #backoff_mutex, #initialize_backoff_helper!, #wait_for_backoff!
#ignore_file?, #ignore_operation?, #ignore_path?
Constructor Details
#initialize(ctx, theme:, include_filter: nil, ignore_filter: nil, overwrite_json: true, stable: false) ⇒ Syncer
Returns a new instance of Syncer.
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
# File 'lib/shopify_cli/theme/syncer.rb', line 41
def initialize(ctx, theme:, include_filter: nil, ignore_filter: nil, overwrite_json: true, stable: false)
@ctx = ctx
@theme = theme
@include_filter = include_filter
@ignore_filter = ignore_filter
@overwrite_json = overwrite_json
@error_reporter = ErrorReporter.new(ctx)
@standard_reporter = StandardReporter.new(ctx)
@reporters = [@error_reporter, @standard_reporter]
@queue = Queue.new
@pending = []
@threads = []
@checksums = Checksums.new(theme)
@error_checksums = []
@bulk_updates_activated = !stable && !Environment.theme_access_password?
@api_client = ThemeAdminAPI.new(ctx, theme.shop)
initialize_backoff_helper!
end
|
Instance Attribute Details
#api_client ⇒ Object
Returns the value of attribute api_client.
36
37
38
|
# File 'lib/shopify_cli/theme/syncer.rb', line 36
def api_client
@api_client
end
|
#checksums ⇒ Object
Returns the value of attribute checksums.
36
37
38
|
# File 'lib/shopify_cli/theme/syncer.rb', line 36
def checksums
@checksums
end
|
#ctx ⇒ Object
Returns the value of attribute ctx.
36
37
38
|
# File 'lib/shopify_cli/theme/syncer.rb', line 36
def ctx
@ctx
end
|
#error_checksums ⇒ Object
Returns the value of attribute error_checksums.
36
37
38
|
# File 'lib/shopify_cli/theme/syncer.rb', line 36
def error_checksums
@error_checksums
end
|
#ignore_filter ⇒ Object
Returns the value of attribute ignore_filter.
37
38
39
|
# File 'lib/shopify_cli/theme/syncer.rb', line 37
def ignore_filter
@ignore_filter
end
|
#include_filter ⇒ Object
Returns the value of attribute include_filter.
37
38
39
|
# File 'lib/shopify_cli/theme/syncer.rb', line 37
def include_filter
@include_filter
end
|
#pending ⇒ Object
Returns the value of attribute pending.
36
37
38
|
# File 'lib/shopify_cli/theme/syncer.rb', line 36
def pending
@pending
end
|
#standard_reporter ⇒ Object
Returns the value of attribute standard_reporter.
36
37
38
|
# File 'lib/shopify_cli/theme/syncer.rb', line 36
def standard_reporter
@standard_reporter
end
|
#theme ⇒ Object
Returns the value of attribute theme.
36
37
38
|
# File 'lib/shopify_cli/theme/syncer.rb', line 36
def theme
@theme
end
|
Instance Method Details
#broken_file?(file) ⇒ Boolean
118
119
120
|
# File 'lib/shopify_cli/theme/syncer.rb', line 118
def broken_file?(file)
error_checksums.include?(checksums[file.relative_path])
end
|
#bulk_updates_activated? ⇒ Boolean
176
177
178
|
# File 'lib/shopify_cli/theme/syncer.rb', line 176
def bulk_updates_activated?
@bulk_updates_activated
end
|
#download_theme!(delete: true, &block) ⇒ Object
171
172
173
174
|
# File 'lib/shopify_cli/theme/syncer.rb', line 171
def download_theme!(delete: true, &block)
downloader = Downloader.new(self, delete, &block)
downloader.download!
end
|
#empty? ⇒ Boolean
106
107
108
|
# File 'lib/shopify_cli/theme/syncer.rb', line 106
def empty?
@pending.empty?
end
|
#enqueue_deletes(files) ⇒ Object
94
95
96
|
# File 'lib/shopify_cli/theme/syncer.rb', line 94
def enqueue_deletes(files)
files.each { |file| enqueue(:delete, file) }
end
|
#enqueue_get(files) ⇒ Object
90
91
92
|
# File 'lib/shopify_cli/theme/syncer.rb', line 90
def enqueue_get(files)
files.each { |file| enqueue(:get, file) }
end
|
#enqueue_union_merges(files) ⇒ Object
98
99
100
|
# File 'lib/shopify_cli/theme/syncer.rb', line 98
def enqueue_union_merges(files)
files.each { |file| enqueue(:union_merge, file) }
end
|
#enqueue_updates(files) ⇒ Object
86
87
88
|
# File 'lib/shopify_cli/theme/syncer.rb', line 86
def enqueue_updates(files)
files.each { |file| enqueue(:update, file) }
end
|
#enqueueable?(operation) ⇒ Boolean
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
# File 'lib/shopify_cli/theme/syncer.rb', line 180
def enqueueable?(operation)
file = operation.file
method = operation.method
return false if @pending.include?(operation) || ignore_operation?(operation)
if [:update, :get].include?(method) && file.exist?
if !!@error_checksums.delete(file.checksum)
@standard_reporter.report(operation.as_fix_message)
end
return checksums.file_has_changed?(file)
end
true
end
|
#fetch_checksums! ⇒ Object
136
137
138
139
140
141
|
# File 'lib/shopify_cli/theme/syncer.rb', line 136
def fetch_checksums!
_status, response = api_client.get(
path: "themes/#{@theme.id}/assets.json",
)
update_checksums(response)
end
|
#handle_operation_error(operation, error) ⇒ Object
199
200
201
202
|
# File 'lib/shopify_cli/theme/syncer.rb', line 199
def handle_operation_error(operation, error)
error_suffix = ":\n " + parse_api_errors(operation.file, error).join("\n ")
report_error(operation, error_suffix)
end
|
#lock_io! ⇒ Object
78
79
80
|
# File 'lib/shopify_cli/theme/syncer.rb', line 78
def lock_io!
@reporters.each(&:disable!)
end
|
#overwrite_json? ⇒ Boolean
204
205
206
|
# File 'lib/shopify_cli/theme/syncer.rb', line 204
def overwrite_json?
theme_created_at_runtime? || @overwrite_json
end
|
#parse_api_errors(file, exception) ⇒ Object
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
# File 'lib/shopify_cli/theme/syncer.rb', line 225
def parse_api_errors(file, exception)
parsed_body = {}
if exception.respond_to?(:response)
response = exception.response
parsed_body = if response&.is_a?(Hash)
response&.[](:body)
else
JSON.parse(response&.body)
end
end
errors = parsed_body.dig("errors") errors = errors.dig("asset") if errors&.is_a?(Hash)
message = errors || parsed_body["message"] || exception.message
[message].flatten.map { |m| m.split("\n", 2).first }
rescue JSON::ParserError
[exception.message]
rescue StandardError => e
cause = "(cause: #{e.message})"
backtrace = e.backtrace.join("\n")
["The asset #{file} could not be synced #{cause} #{backtrace}"]
end
|
#pending_updates ⇒ Object
110
111
112
|
# File 'lib/shopify_cli/theme/syncer.rb', line 110
def pending_updates
@pending.select { |op| op.method == :update }.map(&:file)
end
|
#remote_file?(file) ⇒ Boolean
114
115
116
|
# File 'lib/shopify_cli/theme/syncer.rb', line 114
def remote_file?(file)
checksums.has?(file)
end
|
#report_file_error(file, error_message = "") ⇒ Object
218
219
220
221
222
223
|
# File 'lib/shopify_cli/theme/syncer.rb', line 218
def report_file_error(file, error_message = "")
path = file.relative_path
@error_checksums << checksums[path]
@error_reporter.report(error_message)
end
|
#shutdown ⇒ Object
143
144
145
146
147
|
# File 'lib/shopify_cli/theme/syncer.rb', line 143
def shutdown
@queue.close unless @queue.closed?
ensure
@threads.each { |thread| thread.join if thread.alive? }
end
|
#size ⇒ Object
102
103
104
|
# File 'lib/shopify_cli/theme/syncer.rb', line 102
def size
@pending.size
end
|
#start_threads(count = 2) ⇒ Object
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
# File 'lib/shopify_cli/theme/syncer.rb', line 149
def start_threads(count = 2)
count.times do
@threads << Thread.new do
loop do
operation = @queue.pop
break if operation.nil?
perform(operation)
rescue Exception => e error_suffix = ": #{e}"
error_suffix += + "\n\t#{e.backtrace.join("\n\t")}" if @ctx.debug?
report_error(operation, error_suffix)
end
end
end
end
|
#unlock_io! ⇒ Object
82
83
84
|
# File 'lib/shopify_cli/theme/syncer.rb', line 82
def unlock_io!
@reporters.each(&:enable!)
end
|
#update_checksums(api_response) ⇒ Object
208
209
210
211
212
213
214
215
216
|
# File 'lib/shopify_cli/theme/syncer.rb', line 208
def update_checksums(api_response)
api_response.values.flatten.each do |asset|
next unless asset["key"]
checksums[asset["key"]] = asset["checksum"]
end
checksums.reject_duplicated_checksums!
end
|
#upload_theme!(delay_low_priority_files: false, delete: true, &block) ⇒ Object
166
167
168
169
|
# File 'lib/shopify_cli/theme/syncer.rb', line 166
def upload_theme!(delay_low_priority_files: false, delete: true, &block)
uploader = Uploader.new(self, delete, delay_low_priority_files, &block)
uploader.upload!
end
|
#wait! ⇒ Object
122
123
124
125
126
127
128
129
130
131
132
133
134
|
# File 'lib/shopify_cli/theme/syncer.rb', line 122
def wait!
raise ThreadError, "No syncer threads" if @threads.empty?
total = size
last_size = size
until empty? || @queue.closed?
if block_given? && last_size != size
yield size, total
last_size = size
end
Thread.pass
end
end
|