4
4
#include "cache.h"
5
5
#include "tar.h"
6
6
#include "archive.h"
7
+ #include "run-command.h"
7
8
8
9
#define RECORDSIZE (512)
9
10
#define BLOCKSIZE (RECORDSIZE * 20)
@@ -13,6 +14,9 @@ static unsigned long offset;
13
14
14
15
static int tar_umask = 002 ;
15
16
17
+ static int write_tar_filter_archive (const struct archiver * ar ,
18
+ struct archiver_args * args );
19
+
16
20
/* writes out the whole block, but only if it is full */
17
21
static void write_if_needed (void )
18
22
{
@@ -220,6 +224,60 @@ static int write_global_extended_header(struct archiver_args *args)
220
224
return err ;
221
225
}
222
226
227
+ static struct archiver * * tar_filters ;
228
+ static int nr_tar_filters ;
229
+ static int alloc_tar_filters ;
230
+
231
+ static struct archiver * find_tar_filter (const char * name , int len )
232
+ {
233
+ int i ;
234
+ for (i = 0 ; i < nr_tar_filters ; i ++ ) {
235
+ struct archiver * ar = tar_filters [i ];
236
+ if (!strncmp (ar -> name , name , len ) && !ar -> name [len ])
237
+ return ar ;
238
+ }
239
+ return NULL ;
240
+ }
241
+
242
+ static int tar_filter_config (const char * var , const char * value , void * data )
243
+ {
244
+ struct archiver * ar ;
245
+ const char * dot ;
246
+ const char * name ;
247
+ const char * type ;
248
+ int namelen ;
249
+
250
+ if (prefixcmp (var , "tar." ))
251
+ return 0 ;
252
+ dot = strrchr (var , '.' );
253
+ if (dot == var + 9 )
254
+ return 0 ;
255
+
256
+ name = var + 4 ;
257
+ namelen = dot - name ;
258
+ type = dot + 1 ;
259
+
260
+ ar = find_tar_filter (name , namelen );
261
+ if (!ar ) {
262
+ ar = xcalloc (1 , sizeof (* ar ));
263
+ ar -> name = xmemdupz (name , namelen );
264
+ ar -> write_archive = write_tar_filter_archive ;
265
+ ar -> flags = ARCHIVER_WANT_COMPRESSION_LEVELS ;
266
+ ALLOC_GROW (tar_filters , nr_tar_filters + 1 , alloc_tar_filters );
267
+ tar_filters [nr_tar_filters ++ ] = ar ;
268
+ }
269
+
270
+ if (!strcmp (type , "command" )) {
271
+ if (!value )
272
+ return config_error_nonbool (var );
273
+ free (ar -> data );
274
+ ar -> data = xstrdup (value );
275
+ return 0 ;
276
+ }
277
+
278
+ return 0 ;
279
+ }
280
+
223
281
static int git_tar_config (const char * var , const char * value , void * cb )
224
282
{
225
283
if (!strcmp (var , "tar.umask" )) {
@@ -231,7 +289,8 @@ static int git_tar_config(const char *var, const char *value, void *cb)
231
289
}
232
290
return 0 ;
233
291
}
234
- return 0 ;
292
+
293
+ return tar_filter_config (var , value , cb );
235
294
}
236
295
237
296
static int write_tar_archive (const struct archiver * ar ,
@@ -248,6 +307,45 @@ static int write_tar_archive(const struct archiver *ar,
248
307
return err ;
249
308
}
250
309
310
+ static int write_tar_filter_archive (const struct archiver * ar ,
311
+ struct archiver_args * args )
312
+ {
313
+ struct strbuf cmd = STRBUF_INIT ;
314
+ struct child_process filter ;
315
+ const char * argv [2 ];
316
+ int r ;
317
+
318
+ if (!ar -> data )
319
+ die ("BUG: tar-filter archiver called with no filter defined" );
320
+
321
+ strbuf_addstr (& cmd , ar -> data );
322
+ if (args -> compression_level >= 0 )
323
+ strbuf_addf (& cmd , " -%d" , args -> compression_level );
324
+
325
+ memset (& filter , 0 , sizeof (filter ));
326
+ argv [0 ] = cmd .buf ;
327
+ argv [1 ] = NULL ;
328
+ filter .argv = argv ;
329
+ filter .use_shell = 1 ;
330
+ filter .in = -1 ;
331
+
332
+ if (start_command (& filter ) < 0 )
333
+ die_errno ("unable to start '%s' filter" , argv [0 ]);
334
+ close (1 );
335
+ if (dup2 (filter .in , 1 ) < 0 )
336
+ die_errno ("unable to redirect descriptor" );
337
+ close (filter .in );
338
+
339
+ r = write_tar_archive (ar , args );
340
+
341
+ close (1 );
342
+ if (finish_command (& filter ) != 0 )
343
+ die ("'%s' filter reported error" , argv [0 ]);
344
+
345
+ strbuf_release (& cmd );
346
+ return r ;
347
+ }
348
+
251
349
static struct archiver tar_archiver = {
252
350
"tar" ,
253
351
write_tar_archive ,
@@ -256,6 +354,13 @@ static struct archiver tar_archiver = {
256
354
257
355
void init_tar_archiver (void )
258
356
{
357
+ int i ;
259
358
register_archiver (& tar_archiver );
359
+
260
360
git_config (git_tar_config , NULL );
361
+ for (i = 0 ; i < nr_tar_filters ; i ++ ) {
362
+ /* omit any filters that never had a command configured */
363
+ if (tar_filters [i ]-> data )
364
+ register_archiver (tar_filters [i ]);
365
+ }
261
366
}
0 commit comments