motion-sparkle-sandbox 2.0.0 → 2.1.1
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/.gitignore +4 -0
- data/.rspec +2 -0
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +183 -0
- data/.ruby-version +1 -0
- data/.travis.yml +37 -0
- data/Gemfile +13 -3
- data/README.md +72 -72
- data/Rakefile +2 -7
- data/bin/bundle +114 -0
- data/bin/byebug +29 -0
- data/bin/coderay +29 -0
- data/bin/fuzzy_match +29 -0
- data/bin/htmldiff +29 -0
- data/bin/httpclient +29 -0
- data/bin/ldiff +29 -0
- data/bin/pod +29 -0
- data/bin/pry +29 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/bin/ruby-parse +29 -0
- data/bin/ruby-rewrite +29 -0
- data/bin/sandbox-pod +29 -0
- data/bin/xcodeproj +29 -0
- data/lib/motion/project/appcast.rb +294 -111
- data/lib/motion/project/indent_string.rb +18 -0
- data/lib/motion/project/install.rb +22 -66
- data/lib/motion/project/package.rb +52 -36
- data/lib/motion/project/project.rb +42 -51
- data/lib/motion/project/rake_tasks.rb +38 -28
- data/lib/motion/project/setup.rb +67 -73
- data/lib/motion/project/sparkle.rb +317 -148
- data/lib/motion/project/templates.rb +24 -22
- data/lib/motion-sparkle-sandbox/version.rb +5 -0
- data/lib/motion-sparkle-sandbox.rb +19 -3
- data/motion-sparkle-sandbox.gemspec +26 -16
- data/sample-app/.gitignore +10 -0
- data/sample-app/Gemfile +8 -0
- data/sample-app/README.md +87 -0
- data/sample-app/Rakefile +47 -0
- data/sample-app/app/app_delegate.rb +15 -0
- data/sample-app/app/menu.rb +155 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/1024x1024.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_128x128.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_128x128@2x.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_16x16.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_16x16@2x.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_256x256.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_256x256@2x.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_32x32.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_32x32@2x.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_512x512.png +0 -0
- data/sample-app/resources/Assets.xcassets/AppIcon.appiconset/Icon_512x512@2x.png +0 -0
- data/sample-app/resources/Assets.xcassets/Contents.json +6 -0
- data/sample-app/resources/Credits.rtf +29 -0
- data/sample-app/spec/main_spec.rb +11 -0
- data/spec/appcast_spec.rb +60 -0
- data/spec/setup_spec.rb +42 -0
- data/spec/sparkle_spec.rb +94 -73
- data/spec/spec_helper.rb +100 -27
- data/spec/spec_utils.rb +68 -0
- data/vendor/.git_keep +0 -0
- metadata +80 -14
- data/vendor/README.md +0 -34
- data/vendor/Sparkle.zip +0 -0
- data/vendor/codesign_embedded_executable +0 -46
- data/vendor/generate_appcast +0 -0
@@ -1,127 +1,310 @@
|
|
1
|
-
|
2
|
-
class Sparkle
|
3
|
-
|
4
|
-
def create_release_notes
|
5
|
-
if File.exist?(release_notes_template_path)
|
6
|
-
File.open("#{release_notes_path}", "w") do |f|
|
7
|
-
template = File.read(release_notes_template_path)
|
8
|
-
f << ERB.new(template).result(binding)
|
9
|
-
end
|
10
|
-
App.info 'Create', "./#{release_notes_path}"
|
11
|
-
else
|
12
|
-
App.fail "Release notes template not found as expected at ./#{release_notes_template_path}"
|
13
|
-
end
|
14
|
-
end
|
1
|
+
# frozen_string_literal: true
|
15
2
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
3
|
+
# rubocop:disable Metrics/ClassLength
|
4
|
+
module Motion
|
5
|
+
module Project
|
6
|
+
class Sparkle
|
7
|
+
class Appcast
|
8
|
+
PARAMS = %i[
|
9
|
+
package_base_url
|
10
|
+
package_filename
|
11
|
+
notes_base_url
|
12
|
+
notes_filename
|
13
|
+
use_exported_private_key
|
14
|
+
base_url
|
15
|
+
releases_folder
|
16
|
+
feed_base_url
|
17
|
+
feed_filename
|
18
|
+
].freeze
|
32
19
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
guid = item.add_element('guid')
|
53
|
-
guid.text = "#{@config.name}-#{@config.short_version}"
|
54
|
-
guid.attributes['isPermaLink'] = false
|
55
|
-
item.add_element('sparkle:releaseNotesLink').text = "#{appcast.notes_url}"
|
56
|
-
enclosure = item.add_element('enclosure')
|
57
|
-
enclosure.attributes['url'] = "#{appcast.package_url}"
|
58
|
-
enclosure.attributes['length'] = "#{@package_size}"
|
59
|
-
enclosure.attributes['type'] = "application/octet-stream"
|
60
|
-
enclosure.attributes['sparkle:version'] = @config.version
|
61
|
-
enclosure.attributes['sparkle:shortVersionString'] = @config.short_version
|
62
|
-
enclosure.attributes['sparkle:dsaSignature'] = @package_signature
|
63
|
-
rss
|
64
|
-
end
|
20
|
+
CLI_OPTIONS = {
|
21
|
+
account: '--account',
|
22
|
+
private_eddsa_key: '-s',
|
23
|
+
download_url_prefix: '--download-url-prefix',
|
24
|
+
release_notes_url_prefix: '--release-notes-url-prefix',
|
25
|
+
full_release_notes_url: '--full-release-notes-url',
|
26
|
+
link: '--link',
|
27
|
+
versions: '--versions',
|
28
|
+
maximum_deltas: '--maximum-deltas',
|
29
|
+
delta_compression: '--delta-compression',
|
30
|
+
delta_compression_level: '--delta-compression-level',
|
31
|
+
channel: '--channel',
|
32
|
+
major_version: '--major-version',
|
33
|
+
ignore_skipped_upgrades_below_version: '--ignore-skipped-upgrades-below-version',
|
34
|
+
phased_rollout_interval: '--phased-rollout-interval',
|
35
|
+
critical_update_version: '--critical-update-version',
|
36
|
+
informational_update_versions: '--informational-update-versions',
|
37
|
+
output_path: '-o'
|
38
|
+
}.freeze
|
65
39
|
|
66
|
-
|
67
|
-
|
68
|
-
|
40
|
+
attr_accessor :base_url,
|
41
|
+
:feed_base_url,
|
42
|
+
:feed_filename,
|
43
|
+
:notes_filename,
|
44
|
+
:package_filename,
|
45
|
+
:releases_folder,
|
46
|
+
:use_exported_private_key,
|
47
|
+
:cli_options
|
48
|
+
attr_writer :notes_base_url,
|
49
|
+
:package_base_url
|
69
50
|
|
70
|
-
|
71
|
-
|
72
|
-
|
51
|
+
def initialize(sparkle_object)
|
52
|
+
@sparkle = sparkle_object
|
53
|
+
@cli_options = {
|
54
|
+
account: 'ed25519' # Sparkle's default account
|
55
|
+
}
|
73
56
|
|
74
|
-
|
75
|
-
|
76
|
-
|
57
|
+
@feed_base_url = nil
|
58
|
+
@feed_filename = 'releases.xml'
|
59
|
+
@notes_base_url = nil
|
60
|
+
@notes_filename = nil
|
61
|
+
@package_base_url = nil
|
62
|
+
@package_filename = nil
|
63
|
+
@base_url = nil
|
64
|
+
@releases_folder = nil
|
65
|
+
@use_exported_private_key = false
|
66
|
+
end
|
77
67
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
68
|
+
def process_option(key, value)
|
69
|
+
if CLI_OPTIONS.keys.include?(key)
|
70
|
+
cli_options[key] = value
|
71
|
+
elsif PARAMS.include?(key)
|
72
|
+
send("#{key}=", value)
|
73
|
+
else
|
74
|
+
return false
|
75
|
+
end
|
85
76
|
|
86
|
-
|
87
|
-
|
88
|
-
end
|
77
|
+
true
|
78
|
+
end
|
89
79
|
|
80
|
+
def feed_url
|
81
|
+
"#{feed_base_url || base_url}#{feed_filename}"
|
82
|
+
end
|
90
83
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
:feed_filename,
|
95
|
-
:notes_base_url,
|
96
|
-
:notes_filename,
|
97
|
-
:package_base_url,
|
98
|
-
:package_filename,
|
99
|
-
:archive_folder
|
100
|
-
|
101
|
-
def initialize
|
102
|
-
@feed_base_url = nil
|
103
|
-
@feed_filename = 'releases.xml'
|
104
|
-
@notes_base_url = nil
|
105
|
-
@notes_filename = 'release_notes.html'
|
106
|
-
@package_base_url = nil
|
107
|
-
@package_filename = nil
|
108
|
-
@base_url = nil
|
109
|
-
@archive_folder = nil
|
110
|
-
end
|
84
|
+
def notes_base_url
|
85
|
+
@notes_base_url || base_url
|
86
|
+
end
|
111
87
|
|
112
|
-
|
113
|
-
|
114
|
-
|
88
|
+
def package_base_url
|
89
|
+
@package_base_url || base_url
|
90
|
+
end
|
115
91
|
|
116
|
-
|
117
|
-
|
118
|
-
end
|
92
|
+
def prepare_args
|
93
|
+
args = []
|
119
94
|
|
120
|
-
|
121
|
-
|
122
|
-
|
95
|
+
account(args)
|
96
|
+
private_eddsa_key(args)
|
97
|
+
download_url_prefix(args)
|
98
|
+
release_notes_url_prefix(args)
|
99
|
+
full_release_notes_url(args)
|
100
|
+
link(args)
|
101
|
+
versions(args)
|
102
|
+
maximum_deltas(args)
|
103
|
+
delta_compression(args)
|
104
|
+
delta_compression_level(args)
|
105
|
+
channel(args)
|
106
|
+
major_version(args)
|
107
|
+
ignore_skipped_upgrades_below_version(args)
|
108
|
+
phased_rollout_interval(args)
|
109
|
+
critical_update_version(args)
|
110
|
+
informational_update_versions(args)
|
111
|
+
output_path(args)
|
123
112
|
|
124
|
-
|
113
|
+
args
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
# --account <account> The account name in your keychain associated with
|
119
|
+
# your private EdDSA (ed25519) key to use for signing
|
120
|
+
# new updates. (default: ed25519)
|
121
|
+
def account(args)
|
122
|
+
return unless cli_options[:account].present?
|
123
|
+
|
124
|
+
args << "--account=#{cli_options[:account]}"
|
125
|
+
end
|
126
|
+
|
127
|
+
# -s <private-EdDSA-key> The private EdDSA string (128 characters). If not
|
128
|
+
# specified, the private EdDSA key will be read from
|
129
|
+
# the Keychain instead.
|
130
|
+
def private_eddsa_key(args)
|
131
|
+
if cli_options[:private_eddsa_key].present?
|
132
|
+
args << "-s=#{cli_options[:private_eddsa_key]}"
|
133
|
+
elsif use_exported_private_key && File.exist?(private_key_path)
|
134
|
+
private_key = File.read(private_key_path)
|
135
|
+
args << "-s=#{private_key}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# --download-url-prefix <url> A URL that will be used as prefix for the URL from
|
140
|
+
# where updates will be downloaded.
|
141
|
+
def download_url_prefix(args)
|
142
|
+
if cli_options[:download_url_prefix].present?
|
143
|
+
args << "--download-url-prefix=#{cli_options[:download_url_prefix]}"
|
144
|
+
elsif package_base_url.present?
|
145
|
+
args << "--download-url-prefix=#{package_base_url}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# --release-notes-url-prefix <url> A URL that will be used as prefix for constructing
|
150
|
+
# URLs for release notes.
|
151
|
+
def release_notes_url_prefix(args)
|
152
|
+
if cli_options[:release_notes_url_prefix].present?
|
153
|
+
args << "--release-notes-url-prefix=#{cli_options[:release_notes_url_prefix]}"
|
154
|
+
elsif notes_base_url.present?
|
155
|
+
args << "--release-notes-url-prefix=#{notes_base_url}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# --full-release-notes-url <url>
|
160
|
+
# A URL that will be used for the full release notes.
|
161
|
+
def full_release_notes_url(args)
|
162
|
+
return unless cli_options[:full_release_notes_url].present?
|
163
|
+
|
164
|
+
args << "--full-release-notes-url=#{cli_options[:full_release_notes_url]}"
|
165
|
+
end
|
166
|
+
|
167
|
+
# --link <link> A URL to the application's website which Sparkle may
|
168
|
+
# use for directing users to if they cannot download a
|
169
|
+
# new update from within the application. This will be
|
170
|
+
# used for new generated update items. By default, no
|
171
|
+
# product link is used.
|
172
|
+
def link(args)
|
173
|
+
return unless cli_options[:link].present?
|
125
174
|
|
175
|
+
args << "--link=#{cli_options[:link]}"
|
176
|
+
end
|
177
|
+
|
178
|
+
# --versions <versions> An optional comma delimited list of application
|
179
|
+
# versions (specified by CFBundleVersion) to generate
|
180
|
+
# new update items for. By default, new update items
|
181
|
+
# are inferred from the available archives and are only
|
182
|
+
# generated if they are in the latest 5 updates in the
|
183
|
+
# appcast.
|
184
|
+
def versions(args)
|
185
|
+
return unless cli_options[:versions].present?
|
186
|
+
|
187
|
+
args << "--versions=#{cli_options[:versions]}"
|
188
|
+
end
|
189
|
+
|
190
|
+
# --maximum-deltas <maximum-deltas>
|
191
|
+
# The maximum number of delta items to create for the
|
192
|
+
# latest update for each minimum required operating
|
193
|
+
# system. (default: 5)
|
194
|
+
def maximum_deltas(args)
|
195
|
+
return unless cli_options[:maximum_deltas].present?
|
196
|
+
|
197
|
+
args << "--maximum-deltas=#{cli_options[:maximum_deltas]}"
|
198
|
+
end
|
199
|
+
|
200
|
+
# --delta-compression <delta-compression>
|
201
|
+
# The compression method to use for generating delta
|
202
|
+
# updates. Supported methods for version 3 delta files
|
203
|
+
# are 'lzma', 'bzip2', 'zlib', 'lzfse', 'lz4', 'none',
|
204
|
+
# and 'default'. Note that version 2 delta files only
|
205
|
+
# support 'bzip2', 'none', and 'default' so other
|
206
|
+
# methods will be ignored if version 2 files are being
|
207
|
+
# generated. The 'default' compression for version 3
|
208
|
+
# delta files is currently lzma. (default: default)
|
209
|
+
def delta_compression(args)
|
210
|
+
return unless cli_options[:delta_compression].present?
|
211
|
+
|
212
|
+
args << "--delta-compression=#{cli_options[:delta_compression]}"
|
213
|
+
end
|
214
|
+
|
215
|
+
# --delta-compression-level <delta-compression-level>
|
216
|
+
# The compression level to use for generating delta
|
217
|
+
# updates. This only applies if the compression method
|
218
|
+
# used is bzip2 which accepts values from 1 - 9. A
|
219
|
+
# special value of 0 will use the default compression
|
220
|
+
# level. (default: 0)
|
221
|
+
def delta_compression_level(args)
|
222
|
+
return unless cli_options[:delta_compression_level].present?
|
223
|
+
|
224
|
+
args << "--delta-compression-level=#{cli_options[:delta_compression_level]}"
|
225
|
+
end
|
226
|
+
|
227
|
+
# --channel <channel-name>
|
228
|
+
# The Sparkle channel name that will be used for
|
229
|
+
# generating new updates. By default, no channel is
|
230
|
+
# used. Old applications need to be using Sparkle 2 to
|
231
|
+
# use this feature.
|
232
|
+
def channel(args)
|
233
|
+
return unless cli_options[:channel].present?
|
234
|
+
|
235
|
+
args << "--channel=#{cli_options[:channel]}"
|
236
|
+
end
|
237
|
+
|
238
|
+
# --major-version <major-version>
|
239
|
+
# The last major or minimum autoupdate sparkle:version
|
240
|
+
# that will be used for generating new updates. By
|
241
|
+
# default, no last major version is used.
|
242
|
+
def major_version(args)
|
243
|
+
return unless cli_options[:major_version].present?
|
244
|
+
|
245
|
+
args << "--major-version=#{cli_options[:major_version]}"
|
246
|
+
end
|
247
|
+
|
248
|
+
# --ignore-skipped-upgrades-below-version <below-version>
|
249
|
+
# Ignore skipped major upgrades below this specified
|
250
|
+
# version. Only applicable for major upgrades.
|
251
|
+
def ignore_skipped_upgrades_below_version(args)
|
252
|
+
return unless cli_options[:ignore_skipped_upgrades_below_version].present?
|
253
|
+
|
254
|
+
args << "--ignore-skipped-upgrades-below-version=#{cli_options[:ignore_skipped_upgrades_below_version]}"
|
255
|
+
end
|
256
|
+
|
257
|
+
# --phased-rollout-interval <phased-rollout-interval>
|
258
|
+
# The phased rollout interval in seconds that will be
|
259
|
+
# used for generating new updates. By default, no
|
260
|
+
# phased rollout interval is used.
|
261
|
+
def phased_rollout_interval(args)
|
262
|
+
return unless cli_options[:phased_rollout_interval].present?
|
263
|
+
|
264
|
+
args << "--phased-rollout-interval=#{cli_options[:phased_rollout_interval]}"
|
265
|
+
end
|
266
|
+
|
267
|
+
# --critical-update-version <critical-update-version>
|
268
|
+
# The last critical update sparkle:version that will be
|
269
|
+
# used for generating new updates. An empty string
|
270
|
+
# argument will treat this update as critical coming
|
271
|
+
# from any application version. By default, no last
|
272
|
+
# critical update version is used. Old applications
|
273
|
+
# need to be using Sparkle 2 to use this feature.
|
274
|
+
def critical_update_version(args)
|
275
|
+
return unless cli_options[:critical_update_version].present?
|
276
|
+
|
277
|
+
args << "--critical-update-version=#{cli_options[:critical_update_version]}"
|
278
|
+
end
|
279
|
+
|
280
|
+
# --informational-update-versions <informational-update-versions>
|
281
|
+
# A comma delimited list of application
|
282
|
+
# sparkle:version's that will see newly generated
|
283
|
+
# updates as being informational only. An empty string
|
284
|
+
# argument will treat this update as informational
|
285
|
+
# coming from any application version. Prefix a version
|
286
|
+
# string with '<' to indicate (eg "<2.5") to indicate
|
287
|
+
# older versions than the one specified should treat
|
288
|
+
# the update as informational only. By default, updates
|
289
|
+
# are not informational only. --link must also be
|
290
|
+
# provided. Old applications need to be using Sparkle 2
|
291
|
+
# to use this feature, and 2.1 or later to use the '<'
|
292
|
+
# upper bound feature.
|
293
|
+
def informational_update_versions(args)
|
294
|
+
return unless cli_options[:informational_update_versions].present?
|
295
|
+
|
296
|
+
args << "--informational-update-versions=#{cli_options[:informational_update_versions]}"
|
297
|
+
end
|
298
|
+
|
299
|
+
# -o <output-path> Path to filename for the generated appcast (allowed
|
300
|
+
# when only one will be created).
|
301
|
+
def output_path(args)
|
302
|
+
return unless cli_options[:output_path].present?
|
303
|
+
|
304
|
+
args << "-o=#{cli_options[:output_path]}"
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
126
308
|
end
|
127
309
|
end
|
310
|
+
# rubocop:enable Metrics/ClassLength
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# https://makandracards.com/makandra/6087-ruby-indent-a-string
|
4
|
+
String.class_eval do
|
5
|
+
def indent(count, char = ' ', skip_first_line: false)
|
6
|
+
gsub(/([^\n]*)(\n|$)/) do |_match|
|
7
|
+
last_iteration = (Regexp.last_match(1) == '' && Regexp.last_match(2) == '')
|
8
|
+
line = String.new
|
9
|
+
line << (char * count) unless last_iteration || skip_first_line
|
10
|
+
line << Regexp.last_match(1)
|
11
|
+
line << Regexp.last_match(2)
|
12
|
+
|
13
|
+
skip_first_line = false
|
14
|
+
|
15
|
+
line
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,75 +1,31 @@
|
|
1
|
-
|
2
|
-
class Sparkle
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
Pathname.new(sparkle_vendor_path + SPARKLE_ZIP_FILE)
|
11
|
-
end
|
12
|
-
|
13
|
-
def sparkle_vendor_path
|
14
|
-
file_path = Pathname.new File.dirname(__FILE__)
|
15
|
-
(file_path.parent.parent.parent + 'vendor/').to_s
|
16
|
-
end
|
17
|
-
|
18
|
-
def sparkle_path
|
19
|
-
Pathname.new(vendor_path + 'Sparkle')
|
20
|
-
end
|
21
|
-
|
22
|
-
def sparkle_framework_path
|
23
|
-
Pathname.new(vendor_path + 'Sparkle/Sparkle.framework')
|
24
|
-
end
|
25
|
-
|
26
|
-
def sparkle_xpc_path
|
27
|
-
Pathname.new(vendor_path + 'Sparkle/XPCServices')
|
28
|
-
end
|
29
|
-
|
30
|
-
def sparkle_zipball
|
31
|
-
Pathname.new(vendor_path + SPARKLE_ZIP_FILE)
|
32
|
-
end
|
33
|
-
|
34
|
-
def copy_zipball
|
35
|
-
`cp #{sparkle_distrib} #{sparkle_zipball}`
|
36
|
-
end
|
37
|
-
|
38
|
-
def unzip
|
39
|
-
`unzip #{sparkle_zipball.to_s} -d #{vendor_path.to_s}`
|
40
|
-
`rm #{sparkle_zipball}`
|
41
|
-
end
|
42
|
-
|
43
|
-
def installed?
|
44
|
-
File.directory?(sparkle_framework_path)
|
45
|
-
end
|
3
|
+
module Motion
|
4
|
+
module Project
|
5
|
+
class Sparkle
|
6
|
+
def vendored_sparkle_path
|
7
|
+
vendor_path.join('Pods/Sparkle')
|
8
|
+
end
|
46
9
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
unzip
|
51
|
-
end
|
10
|
+
def vendored_sparkle_framework_path
|
11
|
+
vendored_sparkle_path.join('Sparkle.framework')
|
12
|
+
end
|
52
13
|
|
53
|
-
|
54
|
-
|
55
|
-
|
14
|
+
def vendored_sparkle_xpc_path
|
15
|
+
vendored_sparkle_path.join('XPCServices')
|
16
|
+
end
|
56
17
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
18
|
+
def installed?
|
19
|
+
File.directory?(vendored_sparkle_framework_path)
|
20
|
+
end
|
61
21
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
please explain your setup and problem as an issue on GitHub at:
|
69
|
-
https://github.com/digitalmoksha/motion-sparkle-sandbox/issues
|
70
|
-
"
|
22
|
+
def verify_installation
|
23
|
+
if installed?
|
24
|
+
App.info 'Sparkle', "Framework installed in #{vendored_sparkle_framework_path}"
|
25
|
+
else
|
26
|
+
App.fail "Sparkle Cocoapod not correctly installed to #{vendored_sparkle_path}. Run `rake pod:install`."
|
27
|
+
end
|
71
28
|
end
|
72
29
|
end
|
73
|
-
|
74
30
|
end
|
75
31
|
end
|
@@ -1,44 +1,60 @@
|
|
1
|
-
|
2
|
-
class Sparkle
|
3
|
-
|
4
|
-
def package
|
5
|
-
return unless setup_ok?
|
6
|
-
create_release_folder
|
7
|
-
@config.build_mode = :release
|
8
|
-
return unless create_zip_file
|
9
|
-
App.info "Release", version_string
|
10
|
-
App.info "Version", @config.short_version
|
11
|
-
App.info "Build", @config.version || 'unspecified in Rakefile'
|
12
|
-
App.info "Size", @package_size.to_s
|
13
|
-
sign_package
|
14
|
-
create_appcast
|
15
|
-
create_release_notes
|
16
|
-
`open #{sparkle_release_path}`
|
17
|
-
end
|
1
|
+
# frozen_string_literal: true
|
18
2
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
3
|
+
module Motion
|
4
|
+
module Project
|
5
|
+
class Sparkle
|
6
|
+
def package
|
7
|
+
return unless setup_ok?
|
8
|
+
|
9
|
+
create_release_folder
|
10
|
+
@config.build_mode = :release
|
11
|
+
return unless create_zip_file
|
12
|
+
|
13
|
+
App.info 'Release', version_string
|
14
|
+
App.info 'Version', @config.short_version
|
15
|
+
App.info 'Build', @config.version || 'unspecified in Rakefile'
|
16
|
+
App.info 'Size', @package_size.to_s
|
17
|
+
|
18
|
+
sign_package
|
19
|
+
create_release_notes
|
20
|
+
|
21
|
+
`open #{sparkle_release_path}`
|
25
22
|
end
|
26
|
-
|
27
|
-
|
23
|
+
|
24
|
+
def create_zip_file
|
25
|
+
App.fail 'You need to build your app with the Release target to use Sparkle' unless File.exist?(app_bundle_path)
|
26
|
+
|
27
|
+
App.info 'Create', "./#{sparkle_release_path}/#{zip_file}"
|
28
|
+
|
29
|
+
if File.exist?("#{sparkle_release_path}/#{zip_file}")
|
30
|
+
App.fail "Release already exists at ./#{sparkle_release_path}/#{zip_file} (remove it manually with `rake sparkle:clean`)"
|
31
|
+
end
|
32
|
+
|
33
|
+
FileUtils.cd(app_release_path) do
|
34
|
+
`zip -r --symlinks "#{zip_file}" "#{app_file}"`
|
35
|
+
end
|
36
|
+
|
37
|
+
FileUtils.mv "#{app_release_path}/#{zip_file}", "./#{sparkle_release_path}/"
|
38
|
+
|
39
|
+
@package_file = zip_file
|
40
|
+
@package_size = File.size "./#{sparkle_release_path}/#{zip_file}"
|
28
41
|
end
|
29
|
-
FileUtils.mv "#{app_release_path}/#{zip_file}", "./#{sparkle_release_path}/"
|
30
|
-
App.info "Create", "./#{sparkle_release_path}/#{zip_file}"
|
31
|
-
@package_file = zip_file
|
32
|
-
@package_size = File.size "./#{sparkle_release_path}/#{zip_file}"
|
33
|
-
end
|
34
42
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
43
|
+
def sign_package
|
44
|
+
package = "./#{sparkle_release_path}/#{zip_file}"
|
45
|
+
sign_update_app = "#{vendored_sparkle_path}/bin/sign_update"
|
46
|
+
args = []
|
47
|
+
|
48
|
+
if appcast.use_exported_private_key && File.exist?(private_key_path)
|
49
|
+
# -s <private-key> The private EdDSA (ed25519) key
|
50
|
+
private_key = File.read(private_key_path)
|
51
|
+
args << "-s=#{private_key}"
|
52
|
+
end
|
41
53
|
|
54
|
+
results, _status = Open3.capture2e(sign_update_app, *args, package)
|
42
55
|
|
56
|
+
App.info 'Signature', results
|
57
|
+
end
|
58
|
+
end
|
43
59
|
end
|
44
60
|
end
|