@@ -156,6 +156,7 @@ func (fs *Filesystem) DecompressFile(ctx context.Context, dir string, file strin
156
156
}
157
157
158
158
return fs .extractStream (ctx , extractStreamOptions {
159
+ FileName : file ,
159
160
Directory : dir ,
160
161
Format : format ,
161
162
Reader : input ,
@@ -190,11 +191,74 @@ type extractStreamOptions struct {
190
191
}
191
192
192
193
func (fs * Filesystem ) extractStream (ctx context.Context , opts extractStreamOptions ) error {
193
- // Decompress and extract archive
194
+
195
+ // See if it's a compressed archive, such as TAR or a ZIP
194
196
ex , ok := opts .Format .(archiver.Extractor )
195
197
if ! ok {
198
+
199
+ // If not, check if it's a single-file compression, such as
200
+ // .log.gz, .sql.gz, and so on
201
+ de , ok := opts .Format .(archiver.Decompressor )
202
+ if ! ok {
203
+ return nil
204
+ }
205
+
206
+ // Strip the compression suffix
207
+ p := filepath .Join (opts .Directory , strings .TrimSuffix (opts .FileName , opts .Format .Name ()))
208
+
209
+ // Make sure it's not ignored
210
+ if err := fs .IsIgnored (p ); err != nil {
211
+ return nil
212
+ }
213
+
214
+ reader , err := de .OpenReader (opts .Reader )
215
+ if err != nil {
216
+ return err
217
+ }
218
+ defer reader .Close ()
219
+
220
+ // Open the file for creation/writing
221
+ f , err := fs .unixFS .OpenFile (p , ufs .O_WRONLY | ufs .O_CREATE , 0o644 )
222
+ if err != nil {
223
+ return err
224
+ }
225
+ defer f .Close ()
226
+
227
+ // Read in 4 KB chunks
228
+ buf := make ([]byte , 4096 )
229
+ for {
230
+ n , err := reader .Read (buf )
231
+ if n > 0 {
232
+
233
+ // Check quota before writing the chunk
234
+ if quotaErr := fs .HasSpaceFor (int64 (n )); quotaErr != nil {
235
+ return quotaErr
236
+ }
237
+
238
+ // Write the chunk
239
+ if _ , writeErr := f .Write (buf [:n ]); writeErr != nil {
240
+ return writeErr
241
+ }
242
+
243
+ // Add to quota
244
+ fs .addDisk (int64 (n ))
245
+ }
246
+
247
+ if err != nil {
248
+ // EOF are expected
249
+ if err == io .EOF {
250
+ break
251
+ }
252
+
253
+ // Return any other
254
+ return err
255
+ }
256
+ }
257
+
196
258
return nil
197
259
}
260
+
261
+ // Decompress and extract archive
198
262
return ex .Extract (ctx , opts .Reader , nil , func (ctx context.Context , f archiver.File ) error {
199
263
if f .IsDir () {
200
264
return nil
0 commit comments