3
3
using System . IO ;
4
4
using System . Linq ;
5
5
using System . Net ;
6
- using Ionic . Zip ;
6
+ using System . Threading . Tasks ;
7
+ using ICSharpCode . SharpZipLib . Zip ;
7
8
using Newtonsoft . Json ;
8
9
using Newtonsoft . Json . Linq ;
9
10
using Paratext . Data ;
@@ -376,7 +377,7 @@ public static IEnumerable<SFInstallableDblResource> GetInstallableDblResources(
376
377
/// <remarks>
377
378
/// After the resource is extracted, it can be a source or target.
378
379
/// </remarks>
379
- public void ExtractToDirectory ( string path )
380
+ async public Task ExtractToDirectoryAsync ( string path )
380
381
{
381
382
// Check parameters
382
383
if ( string . IsNullOrWhiteSpace ( path ) )
@@ -398,11 +399,34 @@ public void ExtractToDirectory(string path)
398
399
this . DBLEntryUid ,
399
400
ProjectFileManager . resourceFileExtension
400
401
) ;
401
- if ( RobustFile . Exists ( resourceFile ) )
402
+ if ( _fileSystemService . FileExists ( resourceFile ) )
402
403
{
403
- using var zipFile = ZipFile . Read ( resourceFile ) ;
404
- zipFile . Password = this . _passwordProvider ? . GetPassword ( ) ;
405
- zipFile . ExtractAll ( path , ExtractExistingFileAction . DoNotOverwrite ) ;
404
+ await using Stream stream = _fileSystemService . OpenFile ( resourceFile , FileMode . Open ) ;
405
+ using ZipFile zipFile = new ZipFile ( stream ) ;
406
+ zipFile . Password = _passwordProvider ? . GetPassword ( ) ;
407
+ await ExtractAllAsync ( zipFile , path ) ;
408
+ }
409
+ }
410
+
411
+ private async Task ExtractAllAsync ( ZipFile zip , string path )
412
+ {
413
+ foreach ( ZipEntry entry in zip )
414
+ {
415
+ if ( ! entry . IsFile )
416
+ continue ; // Skip directories
417
+
418
+ string entryPath = Path . Combine ( path , entry . Name ) ;
419
+
420
+ if ( _fileSystemService . FileExists ( entryPath ) )
421
+ continue ; // Don't overwrite
422
+
423
+ // Ensure directories in the ZIP entry are created
424
+ _fileSystemService . CreateDirectory ( Path . GetDirectoryName ( entryPath ) ) ;
425
+
426
+ // Extract the file
427
+ await using Stream zipStream = zip . GetInputStream ( entry ) ;
428
+ await using Stream output = _fileSystemService . CreateFile ( entryPath ) ;
429
+ await zipStream . CopyToAsync ( output ) ;
406
430
}
407
431
}
408
432
@@ -475,7 +499,7 @@ public override bool Install()
475
499
/// <returns>
476
500
/// A dictionary where the resource id is the key, and the revision is the value.
477
501
/// </returns>
478
- internal static IReadOnlyDictionary < string , int > GetInstalledResourceRevisions ( )
502
+ internal static async Task < IReadOnlyDictionary < string , int > > GetInstalledResourceRevisionsAsync ( )
479
503
{
480
504
// Initialize variables
481
505
Dictionary < string , int > resourceRevisions = [ ] ;
@@ -510,9 +534,8 @@ internal static IReadOnlyDictionary<string, int> GetInstalledResourceRevisions()
510
534
// See if this a zip file, and if it contains the correct ID
511
535
try
512
536
{
513
- // This only uses DotNetZip because ParatextData uses DotNetZip
514
- // You could use System.IO.Compression if you wanted to
515
- using var zipFile = ZipFile . Read ( resourceFile ) ;
537
+ await using var stream = new FileStream ( resourceFile , FileMode . Open ) ;
538
+ using var zipFile = new ZipFile ( stream ) ;
516
539
// Zip files use forward slashes, even on Windows
517
540
const string idSearchPath = DblFolderName + "/id/" ;
518
541
const string revisionSearchPath = DblFolderName + "/revision/" ;
@@ -524,19 +547,19 @@ internal static IReadOnlyDictionary<string, int> GetInstalledResourceRevisions()
524
547
if (
525
548
string . IsNullOrWhiteSpace ( fileId )
526
549
&& ! entry . IsDirectory
527
- && entry . FileName . StartsWith ( idSearchPath , StringComparison . OrdinalIgnoreCase )
550
+ && entry . Name . StartsWith ( idSearchPath , StringComparison . OrdinalIgnoreCase )
528
551
)
529
552
{
530
- fileId = entry . FileName . Split ( '/' , StringSplitOptions . RemoveEmptyEntries ) . Last ( ) ;
553
+ fileId = entry . Name . Split ( '/' , StringSplitOptions . RemoveEmptyEntries ) . Last ( ) ;
531
554
}
532
555
else if (
533
556
revision == 0
534
557
&& ! entry . IsDirectory
535
- && entry . FileName . StartsWith ( revisionSearchPath , StringComparison . OrdinalIgnoreCase )
558
+ && entry . Name . StartsWith ( revisionSearchPath , StringComparison . OrdinalIgnoreCase )
536
559
)
537
560
{
538
561
string revisionFilename = entry
539
- . FileName . Split ( '/' , StringSplitOptions . RemoveEmptyEntries )
562
+ . Name . Split ( '/' , StringSplitOptions . RemoveEmptyEntries )
540
563
. Last ( ) ;
541
564
if ( ! int . TryParse ( revisionFilename , out revision ) )
542
565
{
0 commit comments