1
+ use std:: ffi:: { OsStr , OsString } ;
1
2
use std:: io:: Write ;
3
+ use std:: fs:: { self , File } ;
4
+ use std:: path:: { PathBuf } ;
5
+ use std:: collections:: HashMap ;
2
6
use std:: thread;
3
7
use std:: time:: { Instant , Duration } ;
4
8
use std:: sync:: { mpsc, Arc , Mutex } ;
@@ -312,19 +316,106 @@ fn get_path_score(path: &str) -> i8 {
312
316
}
313
317
}
314
318
319
+ fn pick_files_to_move ( path : & PathBuf ) -> Result < Vec < PathBuf > , Box < dyn std:: error:: Error > > {
320
+ // Traverse through the directories and pick files for flattenning
321
+ // If identical filename, choose one with higher path score
322
+ let path = path. to_path_buf ( ) ;
323
+
324
+ fn traverse ( path : PathBuf ) -> Result < Vec < PathBuf > , std:: io:: Error > {
325
+ let entries = path. as_path ( ) . read_dir ( ) ?;
326
+
327
+ let mut file_list: Vec < PathBuf > = Vec :: new ( ) ;
328
+
329
+ for entry in entries {
330
+ let entry = entry?;
331
+
332
+ if entry. file_type ( ) ?. is_dir ( ) {
333
+ file_list. append ( & mut traverse ( entry. path ( ) ) ?) ;
334
+ continue ;
335
+ }
336
+
337
+ file_list. push ( entry. path ( ) ) ;
338
+ }
339
+
340
+ return Ok ( file_list) ;
341
+ }
342
+
343
+ let file_list = traverse ( path) ?;
344
+
345
+ let mut file_map: HashMap < OsString , PathBuf > = HashMap :: new ( ) ;
346
+
347
+ for path in file_list {
348
+ let name = path. file_name ( ) ;
349
+
350
+ if name. is_none ( ) {
351
+ return Err (
352
+ format ! ( "Failed to get filename for file: {:#?}" , path) . into ( )
353
+ ) ;
354
+ }
355
+
356
+ let name = name. unwrap ( ) ;
357
+
358
+ if file_map. contains_key ( name) {
359
+ let other_path = file_map. get ( name) . unwrap ( ) ;
360
+
361
+ let path_str = path. to_str ( ) ;
362
+ let other_path_str = other_path. to_str ( ) ;
363
+
364
+ if path_str. is_none ( ) {
365
+ return Err (
366
+ format ! ( "Failed to get UTF-8 path string for path: {:#?}" , path) . into ( )
367
+ ) ;
368
+ }
369
+
370
+ if other_path_str. is_none ( ) {
371
+ return Err (
372
+ format ! ( "Failed to get UTF-8 path string for path: {:#?}" , path) . into ( )
373
+ ) ;
374
+ }
375
+
376
+ let cur_score = get_path_score ( path_str. unwrap ( ) ) ;
377
+ let other_score = get_path_score ( other_path_str. unwrap ( ) ) ;
378
+
379
+ if cur_score > other_score {
380
+ file_map. insert ( name. into ( ) , path. to_owned ( ) ) ;
381
+ }
382
+ } else {
383
+ file_map. insert ( name. into ( ) , path. to_owned ( ) ) ;
384
+ }
385
+ }
386
+
387
+ return Ok (
388
+ file_map
389
+ . values ( )
390
+ . cloned ( )
391
+ . collect ( )
392
+ ) ;
393
+ }
394
+
315
395
pub fn unpack_cold_clear ( version : & str ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
316
- let save_path = paths:: get_cold_clear_download_path ( version) ;
317
- let save_path = save_path . as_path ( ) ;
396
+ let zip_path = paths:: get_cold_clear_download_path ( version) ;
397
+ let zip_path = zip_path . as_path ( ) ;
318
398
319
- if !save_path . exists ( ) {
399
+ if !zip_path . exists ( ) {
320
400
download_cold_clear ( version) ?;
321
401
}
322
402
323
- let save_path = save_path. to_str ( ) . unwrap ( ) ;
403
+ let zip_file = std:: fs:: File :: open ( zip_path) ?;
404
+ let mut zip_archive = ZipArchive :: new ( & zip_file) ?;
405
+
406
+ let lib_path = paths:: get_sandboxed_save_path ( ) . join ( "lib" ) ;
407
+ let temp_lib_path = paths:: get_sandboxed_save_path ( ) . join ( "~lib" ) ;
324
408
325
- let zip_file = std :: fs :: File :: open ( save_path ) ?;
409
+ zip_archive . extract ( & temp_lib_path ) ?;
326
410
327
- let mut zip_archive = ZipArchive :: new ( zip_file) ?;
411
+ let files_to_move = pick_files_to_move ( & temp_lib_path) ?;
412
+
413
+ for path in files_to_move {
414
+ let dest = lib_path. join ( path. file_name ( ) . unwrap ( ) ) ;
415
+ fs:: rename ( path, dest) ?;
416
+ }
328
417
329
- todo ! ( ) ; // TODO: Extract, flatten, select (path_score) and move library files
418
+ fs:: remove_dir_all ( temp_lib_path) ?;
419
+
420
+ return Ok ( ( ) ) ;
330
421
}
0 commit comments