@@ -17,9 +17,39 @@ struct batch_options {
17
17
int print_contents ;
18
18
int buffer_output ;
19
19
int all_objects ;
20
+ int cmdmode ; /* may be 'w' or 'c' for --filters or --textconv */
20
21
const char * format ;
21
22
};
22
23
24
+ static const char * force_path ;
25
+
26
+ static int filter_object (const char * path , unsigned mode ,
27
+ const unsigned char * sha1 ,
28
+ char * * buf , unsigned long * size )
29
+ {
30
+ enum object_type type ;
31
+
32
+ * buf = read_sha1_file (sha1 , & type , size );
33
+ if (!* buf )
34
+ return error (_ ("cannot read object %s '%s'" ),
35
+ sha1_to_hex (sha1 ), path );
36
+ if (type != OBJ_BLOB ) {
37
+ free (* buf );
38
+ return error (_ ("blob expected for %s '%s'" ),
39
+ sha1_to_hex (sha1 ), path );
40
+ }
41
+ if (S_ISREG (mode )) {
42
+ struct strbuf strbuf = STRBUF_INIT ;
43
+ if (convert_to_working_tree (path , * buf , * size , & strbuf )) {
44
+ free (* buf );
45
+ * size = strbuf .len ;
46
+ * buf = strbuf_detach (& strbuf , NULL );
47
+ }
48
+ }
49
+
50
+ return 0 ;
51
+ }
52
+
23
53
static int cat_one_file (int opt , const char * exp_type , const char * obj_name ,
24
54
int unknown_type )
25
55
{
@@ -31,13 +61,19 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
31
61
struct object_info oi = {NULL };
32
62
struct strbuf sb = STRBUF_INIT ;
33
63
unsigned flags = LOOKUP_REPLACE_OBJECT ;
64
+ const char * path = force_path ;
34
65
35
66
if (unknown_type )
36
67
flags |= LOOKUP_UNKNOWN_OBJECT ;
37
68
38
69
if (get_sha1_with_context (obj_name , 0 , sha1 , & obj_context ))
39
70
die ("Not a valid object name %s" , obj_name );
40
71
72
+ if (!path )
73
+ path = obj_context .path ;
74
+ else if (obj_context .mode == S_IFINVALID )
75
+ obj_context .mode = 0100644 ;
76
+
41
77
buf = NULL ;
42
78
switch (opt ) {
43
79
case 't' :
@@ -61,12 +97,23 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
61
97
case 'e' :
62
98
return !has_sha1_file (sha1 );
63
99
100
+ case 'w' :
101
+ if (!path [0 ])
102
+ die ("git cat-file --filters %s: <object> must be "
103
+ "<sha1:path>" , obj_name );
104
+
105
+ if (filter_object (path , obj_context .mode ,
106
+ sha1 , & buf , & size ))
107
+ return -1 ;
108
+ break ;
109
+
64
110
case 'c' :
65
- if (!obj_context . path [0 ])
111
+ if (!path [0 ])
66
112
die ("git cat-file --textconv %s: <object> must be <sha1:path>" ,
67
113
obj_name );
68
114
69
- if (textconv_object (obj_context .path , obj_context .mode , sha1 , 1 , & buf , & size ))
115
+ if (textconv_object (path , obj_context .mode ,
116
+ sha1 , 1 , & buf , & size ))
70
117
break ;
71
118
72
119
case 'p' :
@@ -239,7 +286,32 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
239
286
if (data -> type == OBJ_BLOB ) {
240
287
if (opt -> buffer_output )
241
288
fflush (stdout );
242
- if (stream_blob_to_fd (1 , sha1 , NULL , 0 ) < 0 )
289
+ if (opt -> cmdmode ) {
290
+ char * contents ;
291
+ unsigned long size ;
292
+
293
+ if (!data -> rest )
294
+ die ("missing path for '%s'" , sha1_to_hex (sha1 ));
295
+
296
+ if (opt -> cmdmode == 'w' ) {
297
+ if (filter_object (data -> rest , 0100644 , sha1 ,
298
+ & contents , & size ))
299
+ die ("could not convert '%s' %s" ,
300
+ sha1_to_hex (sha1 ), data -> rest );
301
+ } else if (opt -> cmdmode == 'c' ) {
302
+ enum object_type type ;
303
+ if (!textconv_object (data -> rest , 0100644 , sha1 ,
304
+ 1 , & contents , & size ))
305
+ contents = read_sha1_file (sha1 , & type ,
306
+ & size );
307
+ if (!contents )
308
+ die ("could not convert '%s' %s" ,
309
+ sha1_to_hex (sha1 ), data -> rest );
310
+ } else
311
+ die ("BUG: invalid cmdmode: %c" , opt -> cmdmode );
312
+ batch_write (opt , contents , size );
313
+ free (contents );
314
+ } else if (stream_blob_to_fd (1 , sha1 , NULL , 0 ) < 0 )
243
315
die ("unable to stream %s to stdout" , sha1_to_hex (sha1 ));
244
316
}
245
317
else {
@@ -376,6 +448,8 @@ static int batch_objects(struct batch_options *opt)
376
448
data .mark_query = 1 ;
377
449
strbuf_expand (& buf , opt -> format , expand_format , & data );
378
450
data .mark_query = 0 ;
451
+ if (opt -> cmdmode )
452
+ data .split_on_whitespace = 1 ;
379
453
380
454
if (opt -> all_objects ) {
381
455
struct object_info empty ;
@@ -440,8 +514,8 @@ static int batch_objects(struct batch_options *opt)
440
514
}
441
515
442
516
static const char * const cat_file_usage [] = {
443
- N_ ("git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|<type>|--textconv) <object>" ),
444
- N_ ("git cat-file (--batch | --batch-check) [--follow-symlinks]" ),
517
+ N_ ("git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|<type>|--textconv|--filters) [--path=<path>] <object>" ),
518
+ N_ ("git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv|--filters] " ),
445
519
NULL
446
520
};
447
521
@@ -473,7 +547,7 @@ static int batch_option_callback(const struct option *opt,
473
547
int cmd_cat_file (int argc , const char * * argv , const char * prefix )
474
548
{
475
549
int opt = 0 ;
476
- const char * exp_type = NULL , * obj_name = NULL ;
550
+ const char * exp_type = NULL , * obj_name = NULL , * force_use_path = NULL ;
477
551
struct batch_options batch = {0 };
478
552
int unknown_type = 0 ;
479
553
@@ -486,6 +560,14 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
486
560
OPT_CMDMODE ('p' , NULL , & opt , N_ ("pretty-print object's content" ), 'p' ),
487
561
OPT_CMDMODE (0 , "textconv" , & opt ,
488
562
N_ ("for blob objects, run textconv on object's content" ), 'c' ),
563
+ OPT_CMDMODE (0 , "filters" , & opt ,
564
+ N_ ("for blob objects, run filters on object's content" ), 'w' ),
565
+ OPT_STRING (0 , "path" , & force_path , N_ ("blob" ),
566
+ N_ ("use a specific path for --textconv/--filters" )),
567
+ OPT_CMDMODE (0 , "smudge" , & opt ,
568
+ N_ ("deprecated, use --filters instead" ), 'W' ),
569
+ OPT_STRING (0 , "use-path" , & force_use_path , N_ ("blob" ),
570
+ N_ ("deprecated, use --path=<path> instead" )),
489
571
OPT_BOOL (0 , "allow-unknown-type" , & unknown_type ,
490
572
N_ ("allow -s and -t to work with broken/corrupt objects" )),
491
573
OPT_BOOL (0 , "buffer" , & batch .buffer_output , N_ ("buffer --batch output" )),
@@ -507,8 +589,20 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
507
589
batch .buffer_output = -1 ;
508
590
argc = parse_options (argc , argv , prefix , options , cat_file_usage , 0 );
509
591
592
+ if (opt == 'W' ) {
593
+ warning ("--smudge is deprecated, please use --filters instead" );
594
+ opt = 'w' ;
595
+ }
596
+ if (force_use_path ) {
597
+ warning ("--use-path=<path> is deprecated, please use "
598
+ "--path=<path> instead" );
599
+ force_path = force_use_path ;
600
+ }
601
+
510
602
if (opt ) {
511
- if (argc == 1 )
603
+ if (batch .enabled && (opt == 'c' || opt == 'w' ))
604
+ batch .cmdmode = opt ;
605
+ else if (argc == 1 )
512
606
obj_name = argv [0 ];
513
607
else
514
608
usage_with_options (cat_file_usage , options );
@@ -520,14 +614,28 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
520
614
} else
521
615
usage_with_options (cat_file_usage , options );
522
616
}
523
- if (batch .enabled && (opt || argc )) {
524
- usage_with_options (cat_file_usage , options );
617
+ if (batch .enabled ) {
618
+ if (batch .cmdmode != opt || argc )
619
+ usage_with_options (cat_file_usage , options );
620
+ if (batch .cmdmode && batch .all_objects )
621
+ die ("--batch-all-objects cannot be combined with "
622
+ "--textconv nor with --filters" );
525
623
}
526
624
527
625
if ((batch .follow_symlinks || batch .all_objects ) && !batch .enabled ) {
528
626
usage_with_options (cat_file_usage , options );
529
627
}
530
628
629
+ if (force_path && opt != 'c' && opt != 'w' ) {
630
+ error ("--path=<path> needs --textconv or --filters" );
631
+ usage_with_options (cat_file_usage , options );
632
+ }
633
+
634
+ if (force_path && batch .enabled ) {
635
+ error ("--path=<path> incompatible with --batch" );
636
+ usage_with_options (cat_file_usage , options );
637
+ }
638
+
531
639
if (batch .buffer_output < 0 )
532
640
batch .buffer_output = batch .all_objects ;
533
641
0 commit comments