@@ -9,15 +9,26 @@ use std::{
9
9
fs:: File ,
10
10
path:: { Path , PathBuf } ,
11
11
process:: Command ,
12
+ sync:: Arc ,
12
13
} ;
13
14
14
15
use serde:: Serialize ;
16
+ use tauri:: utils:: config:: { Updater , V1Compatible } ;
15
17
16
18
const UPDATER_PRIVATE_KEY : & str = "dW50cnVzdGVkIGNvbW1lbnQ6IHJzaWduIGVuY3J5cHRlZCBzZWNyZXQga2V5ClJXUlRZMEl5TlFOMFpXYzJFOUdjeHJEVXY4WE1TMUxGNDJVUjNrMmk1WlR3UVJVUWwva0FBQkFBQUFBQUFBQUFBQUlBQUFBQUpVK3ZkM3R3eWhyN3hiUXhQb2hvWFVzUW9FbEs3NlNWYjVkK1F2VGFRU1FEaGxuRUtlell5U0gxYS9DbVRrS0YyZVJGblhjeXJibmpZeGJjS0ZKSUYwYndYc2FCNXpHalM3MHcrODMwN3kwUG9SOWpFNVhCSUd6L0E4TGRUT096TEtLR1JwT1JEVFU9Cg==" ;
19
+ const UPDATED_EXIT_CODE : i32 = 0 ;
20
+ const UP_TO_DATE_EXIT_CODE : i32 = 2 ;
17
21
18
22
#[ derive( Serialize ) ]
19
23
struct Config {
20
24
version : & ' static str ,
25
+ bundle : BundleConfig ,
26
+ }
27
+
28
+ #[ derive( Serialize ) ]
29
+ #[ serde( rename_all = "camelCase" ) ]
30
+ struct BundleConfig {
31
+ create_updater_artifacts : Updater ,
21
32
}
22
33
23
34
#[ derive( Serialize ) ]
@@ -157,44 +168,83 @@ fn update_app() {
157
168
let manifest_dir = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
158
169
let root_dir = manifest_dir. join ( "../../../.." ) ;
159
170
160
- let mut config = Config { version : "1.0.0" } ;
161
-
162
- // bundle app update
163
- build_app ( & manifest_dir, & config, true , Default :: default ( ) ) ;
164
-
165
- let updater_zip_ext = if cfg ! ( target_os = "macos" ) {
166
- Some ( "tar.gz" )
167
- } else {
168
- None
169
- } ;
170
-
171
- for ( bundle_target, out_bundle_path) in bundle_paths ( & root_dir, "1.0.0" ) {
172
- let bundle_updater_ext = out_bundle_path. extension ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
173
- let updater_extension = if let Some ( updater_zip_ext) = updater_zip_ext {
174
- format ! ( "{bundle_updater_ext}.{updater_zip_ext}" )
171
+ for mut config in [
172
+ Config {
173
+ version : "1.0.0" ,
174
+ bundle : BundleConfig {
175
+ create_updater_artifacts : Updater :: Bool ( true ) ,
176
+ } ,
177
+ } ,
178
+ Config {
179
+ version : "1.0.0" ,
180
+ bundle : BundleConfig {
181
+ create_updater_artifacts : Updater :: String ( V1Compatible :: V1Compatible ) ,
182
+ } ,
183
+ } ,
184
+ ] {
185
+ let v1_compatible = matches ! (
186
+ config. bundle. create_updater_artifacts,
187
+ Updater :: String ( V1Compatible :: V1Compatible )
188
+ ) ;
189
+
190
+ // bundle app update
191
+ build_app ( & manifest_dir, & config, true , Default :: default ( ) ) ;
192
+
193
+ let updater_zip_ext = if v1_compatible {
194
+ if cfg ! ( windows) {
195
+ Some ( "zip" )
196
+ } else {
197
+ Some ( "tar.gz" )
198
+ }
199
+ } else if cfg ! ( target_os = "macos" ) {
200
+ Some ( "tar.gz" )
175
201
} else {
176
- format ! ( "{bundle_updater_ext}" )
202
+ None
177
203
} ;
178
- let signature_extension = format ! ( "{updater_extension}.sig" ) ;
179
- let signature_path = out_bundle_path. with_extension ( signature_extension) ;
180
- let signature = std:: fs:: read_to_string ( & signature_path) . unwrap_or_else ( |_| {
181
- panic ! ( "failed to read signature file {}" , signature_path. display( ) )
182
- } ) ;
183
- let out_updater_path = out_bundle_path. with_extension ( updater_extension) ;
184
- let updater_path = root_dir. join ( format ! (
185
- "target/debug/{}" ,
186
- out_updater_path. file_name( ) . unwrap( ) . to_str( ) . unwrap( )
187
- ) ) ;
188
- std:: fs:: rename ( & out_updater_path, & updater_path) . expect ( "failed to rename bundle" ) ;
189
-
190
- let target = target. clone ( ) ;
191
- std:: thread:: spawn ( move || {
204
+
205
+ for ( bundle_target, out_bundle_path) in bundle_paths ( & root_dir, "1.0.0" ) {
206
+ let bundle_updater_ext = if v1_compatible {
207
+ out_bundle_path
208
+ . extension ( )
209
+ . unwrap ( )
210
+ . to_str ( )
211
+ . unwrap ( )
212
+ . replace ( "exe" , "nsis" )
213
+ } else {
214
+ out_bundle_path
215
+ . extension ( )
216
+ . unwrap ( )
217
+ . to_str ( )
218
+ . unwrap ( )
219
+ . to_string ( )
220
+ } ;
221
+ let updater_extension = if let Some ( updater_zip_ext) = updater_zip_ext {
222
+ format ! ( "{bundle_updater_ext}.{updater_zip_ext}" )
223
+ } else {
224
+ format ! ( "{bundle_updater_ext}" )
225
+ } ;
226
+ let signature_extension = format ! ( "{updater_extension}.sig" ) ;
227
+ let signature_path = out_bundle_path. with_extension ( signature_extension) ;
228
+ let signature = std:: fs:: read_to_string ( & signature_path) . unwrap_or_else ( |_| {
229
+ panic ! ( "failed to read signature file {}" , signature_path. display( ) )
230
+ } ) ;
231
+ let out_updater_path = out_bundle_path. with_extension ( updater_extension) ;
232
+ let updater_path = root_dir. join ( format ! (
233
+ "target/debug/{}" ,
234
+ out_updater_path. file_name( ) . unwrap( ) . to_str( ) . unwrap( )
235
+ ) ) ;
236
+ std:: fs:: rename ( & out_updater_path, & updater_path) . expect ( "failed to rename bundle" ) ;
237
+
238
+ let target = target. clone ( ) ;
239
+
192
240
// start the updater server
193
- let server =
194
- tiny_http:: Server :: http ( "localhost:3007" ) . expect ( "failed to start updater server" ) ;
241
+ let server = Arc :: new (
242
+ tiny_http:: Server :: http ( "localhost:3007" ) . expect ( "failed to start updater server" ) ,
243
+ ) ;
195
244
196
- loop {
197
- if let Ok ( request) = server. recv ( ) {
245
+ let server_ = server. clone ( ) ;
246
+ std:: thread:: spawn ( move || {
247
+ for request in server_. incoming_requests ( ) {
198
248
match request. url ( ) {
199
249
"/" => {
200
250
let mut platforms = HashMap :: new ( ) ;
@@ -234,45 +284,63 @@ fn update_app() {
234
284
)
235
285
} ) ,
236
286
) ) ;
237
- // close server
238
- return ;
239
287
}
240
288
_ => ( ) ,
241
289
}
242
290
}
291
+ } ) ;
292
+
293
+ config. version = "0.1.0" ;
294
+
295
+ // bundle initial app version
296
+ build_app ( & manifest_dir, & config, false , bundle_target) ;
297
+
298
+ let status_checks = if matches ! ( bundle_target, BundleTarget :: Msi ) {
299
+ // for msi we can't really check if the app was updated, because we can't change the install path
300
+ vec ! [ UPDATED_EXIT_CODE ]
301
+ } else {
302
+ vec ! [ UPDATED_EXIT_CODE , UP_TO_DATE_EXIT_CODE ]
303
+ } ;
304
+
305
+ for expected_exit_code in status_checks {
306
+ let mut binary_cmd = if cfg ! ( windows) {
307
+ Command :: new ( root_dir. join ( "target/debug/app-updater.exe" ) )
308
+ } else if cfg ! ( target_os = "macos" ) {
309
+ Command :: new (
310
+ bundle_paths ( & root_dir, "0.1.0" )
311
+ . first ( )
312
+ . unwrap ( )
313
+ . 1
314
+ . join ( "Contents/MacOS/app-updater" ) ,
315
+ )
316
+ } else if std:: env:: var ( "CI" ) . map ( |v| v == "true" ) . unwrap_or_default ( ) {
317
+ let mut c = Command :: new ( "xvfb-run" ) ;
318
+ c. arg ( "--auto-servernum" )
319
+ . arg ( & bundle_paths ( & root_dir, "0.1.0" ) . first ( ) . unwrap ( ) . 1 ) ;
320
+ c
321
+ } else {
322
+ Command :: new ( & bundle_paths ( & root_dir, "0.1.0" ) . first ( ) . unwrap ( ) . 1 )
323
+ } ;
324
+
325
+ binary_cmd. env ( "TARGET" , bundle_target. name ( ) ) ;
326
+
327
+ let status = binary_cmd. status ( ) . expect ( "failed to run app" ) ;
328
+ let code = status. code ( ) . unwrap_or ( -1 ) ;
329
+
330
+ if code != expected_exit_code {
331
+ panic ! (
332
+ "failed to run app, expected exit code {expected_exit_code}, got {code}"
333
+ ) ;
334
+ }
335
+ #[ cfg( windows) ]
336
+ if code == UPDATED_EXIT_CODE {
337
+ // wait for the update to finish
338
+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 5 ) ) ;
339
+ }
243
340
}
244
- } ) ;
245
-
246
- config. version = "0.1.0" ;
247
-
248
- // bundle initial app version
249
- build_app ( & manifest_dir, & config, false , bundle_target) ;
250
-
251
- let mut binary_cmd = if cfg ! ( windows) {
252
- Command :: new ( root_dir. join ( "target/debug/app-updater.exe" ) )
253
- } else if cfg ! ( target_os = "macos" ) {
254
- Command :: new (
255
- bundle_paths ( & root_dir, "0.1.0" )
256
- . first ( )
257
- . unwrap ( )
258
- . 1
259
- . join ( "Contents/MacOS/app-updater" ) ,
260
- )
261
- } else if std:: env:: var ( "CI" ) . map ( |v| v == "true" ) . unwrap_or_default ( ) {
262
- let mut c = Command :: new ( "xvfb-run" ) ;
263
- c. arg ( "--auto-servernum" )
264
- . arg ( & bundle_paths ( & root_dir, "0.1.0" ) . first ( ) . unwrap ( ) . 1 ) ;
265
- c
266
- } else {
267
- Command :: new ( & bundle_paths ( & root_dir, "0.1.0" ) . first ( ) . unwrap ( ) . 1 )
268
- } ;
269
-
270
- binary_cmd. env ( "TARGET" , bundle_target. name ( ) ) ;
271
-
272
- let status = binary_cmd. status ( ) . expect ( "failed to run app" ) ;
273
341
274
- if !status . success ( ) {
275
- panic ! ( "failed to run app" ) ;
342
+ // graceful shutdown
343
+ server . unblock ( ) ;
276
344
}
277
345
}
278
346
}
0 commit comments