Class: FluidCLI::Theme::Syncer
- Inherits:
-
Object
- Object
- FluidCLI::Theme::Syncer
show all
- Extended by:
- Forwardable
- Defined in:
- lib/fluid_cli/theme/syncer.rb,
lib/fluid_cli/theme/syncer/merger.rb,
lib/fluid_cli/theme/syncer/uploader.rb,
lib/fluid_cli/theme/syncer/checksums.rb,
lib/fluid_cli/theme/syncer/operation.rb,
lib/fluid_cli/theme/syncer/downloader.rb,
lib/fluid_cli/theme/syncer/error_reporter.rb,
lib/fluid_cli/theme/syncer/standard_reporter.rb,
lib/fluid_cli/theme/syncer/unsupported_script_warning.rb,
lib/fluid_cli/theme/syncer/uploader/forms/apply_to_all.rb,
lib/fluid_cli/theme/syncer/uploader/json_delete_handler.rb,
lib/fluid_cli/theme/syncer/uploader/json_update_handler.rb,
lib/fluid_cli/theme/syncer/uploader/forms/apply_to_all_form.rb,
lib/fluid_cli/theme/syncer/uploader/forms/base_strategy_form.rb,
lib/fluid_cli/theme/syncer/uploader/forms/select_delete_strategy.rb,
lib/fluid_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, :get_asset, ]
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(ctx, theme:, overwrite_json: true, force: false) ⇒ Syncer
Returns a new instance of Syncer.
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
# File 'lib/fluid_cli/theme/syncer.rb', line 34
def initialize(ctx, theme:, overwrite_json: true, force: false)
@ctx = ctx
@theme = theme
@overwrite_json = overwrite_json
@force = force
@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 = []
@api_client = FluidCLI::API.new(ctx)
end
|
Instance Attribute Details
#api_client ⇒ Object
Returns the value of attribute api_client.
30
31
32
|
# File 'lib/fluid_cli/theme/syncer.rb', line 30
def api_client
@api_client
end
|
#checksums ⇒ Object
Returns the value of attribute checksums.
30
31
32
|
# File 'lib/fluid_cli/theme/syncer.rb', line 30
def checksums
@checksums
end
|
#ctx ⇒ Object
Returns the value of attribute ctx.
30
31
32
|
# File 'lib/fluid_cli/theme/syncer.rb', line 30
def ctx
@ctx
end
|
#error_checksums ⇒ Object
Returns the value of attribute error_checksums.
30
31
32
|
# File 'lib/fluid_cli/theme/syncer.rb', line 30
def error_checksums
@error_checksums
end
|
#pending ⇒ Object
Returns the value of attribute pending.
30
31
32
|
# File 'lib/fluid_cli/theme/syncer.rb', line 30
def pending
@pending
end
|
#standard_reporter ⇒ Object
Returns the value of attribute standard_reporter.
30
31
32
|
# File 'lib/fluid_cli/theme/syncer.rb', line 30
def standard_reporter
@standard_reporter
end
|
#theme ⇒ Object
Returns the value of attribute theme.
30
31
32
|
# File 'lib/fluid_cli/theme/syncer.rb', line 30
def theme
@theme
end
|
Instance Method Details
#broken_file?(file) ⇒ Boolean
102
103
104
|
# File 'lib/fluid_cli/theme/syncer.rb', line 102
def broken_file?(file)
error_checksums.include?(checksums[file.relative_path])
end
|
#download_theme!(delete: true, &block) ⇒ Object
174
175
176
177
|
# File 'lib/fluid_cli/theme/syncer.rb', line 174
def download_theme!(delete: true, &block)
downloader = Downloader.new(self, delete, &block)
downloader.download!
end
|
#empty? ⇒ Boolean
90
91
92
|
# File 'lib/fluid_cli/theme/syncer.rb', line 90
def empty?
@pending.empty?
end
|
#enqueue_deletes(files) ⇒ Object
78
79
80
|
# File 'lib/fluid_cli/theme/syncer.rb', line 78
def enqueue_deletes(files)
files.each { |file| enqueue(:delete, file) }
end
|
#enqueue_get(files) ⇒ Object
74
75
76
|
# File 'lib/fluid_cli/theme/syncer.rb', line 74
def enqueue_get(files)
files.each { |file| enqueue(:get, file) }
end
|
#enqueue_union_merges(files) ⇒ Object
82
83
84
|
# File 'lib/fluid_cli/theme/syncer.rb', line 82
def enqueue_union_merges(files)
files.each { |file| enqueue(:union_merge, file) }
end
|
#enqueue_updates(files) ⇒ Object
70
71
72
|
# File 'lib/fluid_cli/theme/syncer.rb', line 70
def enqueue_updates(files)
files.each { |file| enqueue(:update, file) }
end
|
#enqueueable?(operation) ⇒ Boolean
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
# File 'lib/fluid_cli/theme/syncer.rb', line 179
def enqueueable?(operation)
file = operation.file
method = operation.method
return false if @pending.include?(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
120
121
122
123
124
125
|
# File 'lib/fluid_cli/theme/syncer.rb', line 120
def fetch_checksums!
_status, response = api_client.get(
path: "application_themes/#{theme.id}/resources"
)
update_checksums(response["application_theme_resources"])
end
|
#get_theme_resources! ⇒ Object
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'lib/fluid_cli/theme/syncer.rb', line 128
def get_theme_resources!
_status, response = api_client.get(
path: "application_themes/#{theme.id}/resources"
)
update_checksums(response["application_theme_resources"])
response["application_theme_resources"].each do |resource|
file = theme[resource["key"]]
next unless file
if resource["resource_type"] == "FileResource" && !file.text?
enqueue(:get_asset, file, { url: resource["url"] })
else
file.write(resource["content"])
end
end
end
|
#handle_operation_error(operation, error) ⇒ Object
197
198
199
200
|
# File 'lib/fluid_cli/theme/syncer.rb', line 197
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
62
63
64
|
# File 'lib/fluid_cli/theme/syncer.rb', line 62
def lock_io!
@reporters.each(&:disable!)
end
|
#overwrite_json? ⇒ Boolean
202
203
204
|
# File 'lib/fluid_cli/theme/syncer.rb', line 202
def overwrite_json?
theme_created_at_runtime? || @overwrite_json
end
|
#parse_api_errors(file, exception) ⇒ Object
223
224
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
|
# File 'lib/fluid_cli/theme/syncer.rb', line 223
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
errors = parsed_body.dig("errors") errors = errors.dig("asset") if errors&.is_a?(Hash)
["#{parsed_body['error_message']}\n#{errors}"]
elsif exception.respond_to?(:message)
[exception.message]
else
["An unknown error occurred while syncing the asset #{file}"]
end
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
94
95
96
|
# File 'lib/fluid_cli/theme/syncer.rb', line 94
def pending_updates
@pending.select { |op| op.method == :update }.map(&:file)
end
|
#remote_file?(file) ⇒ Boolean
98
99
100
|
# File 'lib/fluid_cli/theme/syncer.rb', line 98
def remote_file?(file)
checksums.has?(file)
end
|
#report_file_error(file, error_message = "") ⇒ Object
216
217
218
219
220
221
|
# File 'lib/fluid_cli/theme/syncer.rb', line 216
def report_file_error(file, error_message = "")
path = file.relative_path
@error_checksums << checksums[path]
@error_reporter.report(error_message)
end
|
#shutdown ⇒ Object
146
147
148
149
150
|
# File 'lib/fluid_cli/theme/syncer.rb', line 146
def shutdown
@queue.close unless @queue.closed?
ensure
@threads.each { |thread| thread.join if thread.alive? }
end
|
#size ⇒ Object
86
87
88
|
# File 'lib/fluid_cli/theme/syncer.rb', line 86
def size
@pending.size
end
|
#start_threads(count = 2) ⇒ Object
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
# File 'lib/fluid_cli/theme/syncer.rb', line 152
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
66
67
68
|
# File 'lib/fluid_cli/theme/syncer.rb', line 66
def unlock_io!
@reporters.each(&:enable!)
end
|
#update_checksums(api_response) ⇒ Object
206
207
208
209
210
211
212
213
214
|
# File 'lib/fluid_cli/theme/syncer.rb', line 206
def update_checksums(api_response)
api_response.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
169
170
171
172
|
# File 'lib/fluid_cli/theme/syncer.rb', line 169
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
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/fluid_cli/theme/syncer.rb', line 106
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
|