@@ -38,11 +38,18 @@ static int write_tar_filter_archive(const struct archiver *ar,
38
38
#define USTAR_MAX_MTIME 077777777777ULL
39
39
#endif
40
40
41
+ static void tar_write_block (const void * buf )
42
+ {
43
+ write_or_die (1 , buf , BLOCKSIZE );
44
+ }
45
+
46
+ static void (* write_block )(const void * ) = tar_write_block ;
47
+
41
48
/* writes out the whole block, but only if it is full */
42
49
static void write_if_needed (void )
43
50
{
44
51
if (offset == BLOCKSIZE ) {
45
- write_or_die ( 1 , block , BLOCKSIZE );
52
+ write_block ( block );
46
53
offset = 0 ;
47
54
}
48
55
}
@@ -66,7 +73,7 @@ static void do_write_blocked(const void *data, unsigned long size)
66
73
write_if_needed ();
67
74
}
68
75
while (size >= BLOCKSIZE ) {
69
- write_or_die ( 1 , buf , BLOCKSIZE );
76
+ write_block ( buf );
70
77
size -= BLOCKSIZE ;
71
78
buf += BLOCKSIZE ;
72
79
}
@@ -101,10 +108,10 @@ static void write_trailer(void)
101
108
{
102
109
int tail = BLOCKSIZE - offset ;
103
110
memset (block + offset , 0 , tail );
104
- write_or_die ( 1 , block , BLOCKSIZE );
111
+ write_block ( block );
105
112
if (tail < 2 * RECORDSIZE ) {
106
113
memset (block , 0 , offset );
107
- write_or_die ( 1 , block , BLOCKSIZE );
114
+ write_block ( block );
108
115
}
109
116
}
110
117
@@ -383,8 +390,8 @@ static int tar_filter_config(const char *var, const char *value, void *data)
383
390
if (!strcmp (type , "command" )) {
384
391
if (!value )
385
392
return config_error_nonbool (var );
386
- free (ar -> data );
387
- ar -> data = xstrdup (value );
393
+ free (ar -> filter_command );
394
+ ar -> filter_command = xstrdup (value );
388
395
return 0 ;
389
396
}
390
397
if (!strcmp (type , "remote" )) {
@@ -425,17 +432,65 @@ static int write_tar_archive(const struct archiver *ar,
425
432
return err ;
426
433
}
427
434
435
+ static git_zstream gzstream ;
436
+ static unsigned char outbuf [16384 ];
437
+
438
+ static void tgz_deflate (int flush )
439
+ {
440
+ while (gzstream .avail_in || flush == Z_FINISH ) {
441
+ int status = git_deflate (& gzstream , flush );
442
+ if (!gzstream .avail_out || status == Z_STREAM_END ) {
443
+ write_or_die (1 , outbuf , gzstream .next_out - outbuf );
444
+ gzstream .next_out = outbuf ;
445
+ gzstream .avail_out = sizeof (outbuf );
446
+ if (status == Z_STREAM_END )
447
+ break ;
448
+ }
449
+ if (status != Z_OK && status != Z_BUF_ERROR )
450
+ die (_ ("deflate error (%d)" ), status );
451
+ }
452
+ }
453
+
454
+ static void tgz_write_block (const void * data )
455
+ {
456
+ gzstream .next_in = (void * )data ;
457
+ gzstream .avail_in = BLOCKSIZE ;
458
+ tgz_deflate (Z_NO_FLUSH );
459
+ }
460
+
461
+ static const char internal_gzip_command [] = "git archive gzip" ;
462
+
428
463
static int write_tar_filter_archive (const struct archiver * ar ,
429
464
struct archiver_args * args )
430
465
{
466
+ #if ZLIB_VERNUM >= 0x1221
467
+ struct gz_header_s gzhead = { .os = 3 }; /* Unix, for reproducibility */
468
+ #endif
431
469
struct strbuf cmd = STRBUF_INIT ;
432
470
struct child_process filter = CHILD_PROCESS_INIT ;
433
471
int r ;
434
472
435
- if (!ar -> data )
473
+ if (!ar -> filter_command )
436
474
BUG ("tar-filter archiver called with no filter defined" );
437
475
438
- strbuf_addstr (& cmd , ar -> data );
476
+ if (!strcmp (ar -> filter_command , internal_gzip_command )) {
477
+ write_block = tgz_write_block ;
478
+ git_deflate_init_gzip (& gzstream , args -> compression_level );
479
+ #if ZLIB_VERNUM >= 0x1221
480
+ if (deflateSetHeader (& gzstream .z , & gzhead ) != Z_OK )
481
+ BUG ("deflateSetHeader() called too late" );
482
+ #endif
483
+ gzstream .next_out = outbuf ;
484
+ gzstream .avail_out = sizeof (outbuf );
485
+
486
+ r = write_tar_archive (ar , args );
487
+
488
+ tgz_deflate (Z_FINISH );
489
+ git_deflate_end (& gzstream );
490
+ return r ;
491
+ }
492
+
493
+ strbuf_addstr (& cmd , ar -> filter_command );
439
494
if (args -> compression_level >= 0 )
440
495
strbuf_addf (& cmd , " -%d" , args -> compression_level );
441
496
@@ -471,14 +526,14 @@ void init_tar_archiver(void)
471
526
int i ;
472
527
register_archiver (& tar_archiver );
473
528
474
- tar_filter_config ("tar.tgz.command" , "gzip -cn" , NULL );
529
+ tar_filter_config ("tar.tgz.command" , internal_gzip_command , NULL );
475
530
tar_filter_config ("tar.tgz.remote" , "true" , NULL );
476
- tar_filter_config ("tar.tar.gz.command" , "gzip -cn" , NULL );
531
+ tar_filter_config ("tar.tar.gz.command" , internal_gzip_command , NULL );
477
532
tar_filter_config ("tar.tar.gz.remote" , "true" , NULL );
478
533
git_config (git_tar_config , NULL );
479
534
for (i = 0 ; i < nr_tar_filters ; i ++ ) {
480
535
/* omit any filters that never had a command configured */
481
- if (tar_filters [i ]-> data )
536
+ if (tar_filters [i ]-> filter_command )
482
537
register_archiver (tar_filters [i ]);
483
538
}
484
539
}
0 commit comments