@@ -11,6 +11,7 @@ public sealed class ZipFileSystem : IVirtualFileSystem, IAsyncDisposable, IDispo
1111{
1212 private readonly ZipArchive _archive ;
1313 private readonly FileStream _file ;
14+ private readonly Dictionary < string , long > _writtenLengths = new ( StringComparer . Ordinal ) ;
1415
1516 public ZipFileSystem ( string path )
1617 {
@@ -50,6 +51,10 @@ public async ValueTask WriteAllBytesAsync(
5051
5152 await using var stream = entry . Open ( ) ;
5253 await stream . WriteAsync ( data , cancellationToken ) . ConfigureAwait ( false ) ;
54+
55+ // ZipArchiveEntry.Length is unavailable in update mode once an entry has been opened for
56+ // writing, so track the uncompressed size ourselves for ListAsync.
57+ _writtenLengths [ name ] = data . Length ;
5358 }
5459
5560 public async Task < Stream > OpenReadAsync ( string path , CancellationToken cancellationToken = default )
@@ -67,14 +72,16 @@ public Task<Stream> OpenWriteAsync(string path, CancellationToken cancellationTo
6772
6873 public ValueTask < bool > DeleteAsync ( string path , CancellationToken cancellationToken = default )
6974 {
70- var entry = _archive . GetEntry ( VfsPath . Normalize ( path ) ) ;
75+ var name = VfsPath . Normalize ( path ) ;
76+ var entry = _archive . GetEntry ( name ) ;
7177
7278 if ( entry is null )
7379 {
7480 return ValueTask . FromResult ( false ) ;
7581 }
7682
7783 entry . Delete ( ) ;
84+ _writtenLengths . Remove ( name ) ;
7885
7986 return ValueTask . FromResult ( true ) ;
8087 }
@@ -92,12 +99,31 @@ public async IAsyncEnumerable<VfsEntry> ListAsync(
9299 continue ;
93100 }
94101
95- yield return new VfsEntry ( entry . FullName , entry . Length , entry . LastWriteTime ) ;
102+ yield return new VfsEntry ( entry . FullName , EntrySize ( entry ) , entry . LastWriteTime ) ;
96103
97104 await Task . CompletedTask ;
98105 }
99106 }
100107
108+ private long EntrySize ( ZipArchiveEntry entry )
109+ {
110+ if ( _writtenLengths . TryGetValue ( entry . FullName , out var length ) )
111+ {
112+ return length ;
113+ }
114+
115+ try
116+ {
117+ return entry . Length ;
118+ }
119+ catch ( InvalidOperationException )
120+ {
121+ // Unavailable in update mode for an entry opened for writing this session that we did
122+ // not track (should not happen, but never let listing throw).
123+ return 0 ;
124+ }
125+ }
126+
101127 public async ValueTask DisposeAsync ( )
102128 {
103129 _archive . Dispose ( ) ;
0 commit comments