@@ -73,14 +73,17 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
73
73
struct object_info oi = OBJECT_INFO_INIT ;
74
74
struct strbuf sb = STRBUF_INIT ;
75
75
unsigned flags = OBJECT_INFO_LOOKUP_REPLACE ;
76
+ unsigned get_oid_flags = GET_OID_RECORD_PATH | GET_OID_ONLY_TO_DIE ;
76
77
const char * path = force_path ;
78
+ const int opt_cw = (opt == 'c' || opt == 'w' );
79
+ if (!path && opt_cw )
80
+ get_oid_flags |= GET_OID_REQUIRE_PATH ;
77
81
78
82
if (unknown_type )
79
83
flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE ;
80
84
81
- if (get_oid_with_context (the_repository , obj_name ,
82
- GET_OID_RECORD_PATH ,
83
- & oid , & obj_context ))
85
+ if (get_oid_with_context (the_repository , obj_name , get_oid_flags , & oid ,
86
+ & obj_context ))
84
87
die ("Not a valid object name %s" , obj_name );
85
88
86
89
if (!path )
@@ -112,20 +115,13 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
112
115
return !has_object_file (& oid );
113
116
114
117
case 'w' :
115
- if (!path )
116
- die ("git cat-file --filters %s: <object> must be "
117
- "<sha1:path>" , obj_name );
118
118
119
119
if (filter_object (path , obj_context .mode ,
120
120
& oid , & buf , & size ))
121
121
return -1 ;
122
122
break ;
123
123
124
124
case 'c' :
125
- if (!path )
126
- die ("git cat-file --textconv %s: <object> must be <sha1:path>" ,
127
- obj_name );
128
-
129
125
if (textconv_object (the_repository , path , obj_context .mode ,
130
126
& oid , 1 , & buf , & size ))
131
127
break ;
@@ -618,12 +614,6 @@ static int batch_objects(struct batch_options *opt)
618
614
return retval ;
619
615
}
620
616
621
- static const char * const cat_file_usage [] = {
622
- N_ ("git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -p | <type> | --textconv | --filters) [--path=<path>] <object>" ),
623
- N_ ("git cat-file (--batch[=<format>] | --batch-check[=<format>]) [--follow-symlinks] [--textconv | --filters]" ),
624
- NULL
625
- };
626
-
627
617
static int git_cat_file_config (const char * var , const char * value , void * cb )
628
618
{
629
619
if (userdiff_config (var , value ) < 0 )
@@ -654,90 +644,138 @@ static int batch_option_callback(const struct option *opt,
654
644
int cmd_cat_file (int argc , const char * * argv , const char * prefix )
655
645
{
656
646
int opt = 0 ;
647
+ int opt_cw = 0 ;
648
+ int opt_epts = 0 ;
657
649
const char * exp_type = NULL , * obj_name = NULL ;
658
650
struct batch_options batch = {0 };
659
651
int unknown_type = 0 ;
660
652
653
+ const char * const usage [] = {
654
+ N_ ("git cat-file <type> <object>" ),
655
+ N_ ("git cat-file (-e | -p) <object>" ),
656
+ N_ ("git cat-file (-t | -s) [--allow-unknown-type] <object>" ),
657
+ N_ ("git cat-file (--batch | --batch-check) [--batch-all-objects]\n"
658
+ " [--buffer] [--follow-symlinks] [--unordered]\n"
659
+ " [--textconv | --filters]" ),
660
+ N_ ("git cat-file (--textconv | --filters)\n"
661
+ " [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]" ),
662
+ NULL
663
+ };
661
664
const struct option options [] = {
662
- OPT_GROUP (N_ ("<type> can be one of: blob, tree, commit, tag" )),
663
- OPT_CMDMODE ('t' , NULL , & opt , N_ ("show object type" ), 't' ),
664
- OPT_CMDMODE ('s' , NULL , & opt , N_ ("show object size" ), 's' ),
665
+ /* Simple queries */
666
+ OPT_GROUP (N_ ("Check object existence or emit object contents" )),
665
667
OPT_CMDMODE ('e' , NULL , & opt ,
666
- N_ ("exit with zero when there's no error" ), 'e' ),
667
- OPT_CMDMODE ('p' , NULL , & opt , N_ ("pretty-print object's content" ), 'p' ),
668
- OPT_CMDMODE (0 , "textconv" , & opt ,
669
- N_ ("for blob objects, run textconv on object's content" ), 'c' ),
670
- OPT_CMDMODE (0 , "filters" , & opt ,
671
- N_ ("for blob objects, run filters on object's content" ), 'w' ),
672
- OPT_STRING (0 , "path" , & force_path , N_ ("blob" ),
673
- N_ ("use a specific path for --textconv/--filters" )),
668
+ N_ ("check if <object> exists" ), 'e' ),
669
+ OPT_CMDMODE ('p' , NULL , & opt , N_ ("pretty-print <object> content" ), 'p' ),
670
+
671
+ OPT_GROUP (N_ ("Emit [broken] object attributes" )),
672
+ OPT_CMDMODE ('t' , NULL , & opt , N_ ("show object type (one of 'blob', 'tree', 'commit', 'tag', ...)" ), 't' ),
673
+ OPT_CMDMODE ('s' , NULL , & opt , N_ ("show object size" ), 's' ),
674
674
OPT_BOOL (0 , "allow-unknown-type" , & unknown_type ,
675
675
N_ ("allow -s and -t to work with broken/corrupt objects" )),
676
- OPT_BOOL (0 , "buffer" , & batch .buffer_output , N_ ("buffer --batch output" )),
677
- OPT_CALLBACK_F (0 , "batch" , & batch , "format" ,
678
- N_ ("show info and content of objects fed from the standard input" ),
676
+ /* Batch mode */
677
+ OPT_GROUP (N_ ("Batch objects requested on stdin (or --batch-all-objects)" )),
678
+ OPT_CALLBACK_F (0 , "batch" , & batch , N_ ("format" ),
679
+ N_ ("show full <object> or <rev> contents" ),
679
680
PARSE_OPT_OPTARG | PARSE_OPT_NONEG ,
680
681
batch_option_callback ),
681
- OPT_CALLBACK_F (0 , "batch-check" , & batch , "format" ,
682
- N_ ("show info about objects fed from the standard input " ),
682
+ OPT_CALLBACK_F (0 , "batch-check" , & batch , N_ ( "format" ) ,
683
+ N_ ("like --batch, but don't emit <contents> " ),
683
684
PARSE_OPT_OPTARG | PARSE_OPT_NONEG ,
684
685
batch_option_callback ),
686
+ OPT_CMDMODE (0 , "batch-all-objects" , & opt ,
687
+ N_ ("with --batch[-check]: ignores stdin, batches all known objects" ), 'b' ),
688
+ /* Batch-specific options */
689
+ OPT_GROUP (N_ ("Change or optimize batch output" )),
690
+ OPT_BOOL (0 , "buffer" , & batch .buffer_output , N_ ("buffer --batch output" )),
685
691
OPT_BOOL (0 , "follow-symlinks" , & batch .follow_symlinks ,
686
- N_ ("follow in-tree symlinks (used with --batch or --batch-check)" )),
687
- OPT_BOOL (0 , "batch-all-objects" , & batch .all_objects ,
688
- N_ ("show all objects with --batch or --batch-check" )),
692
+ N_ ("follow in-tree symlinks" )),
689
693
OPT_BOOL (0 , "unordered" , & batch .unordered ,
690
- N_ ("do not order --batch-all-objects output" )),
694
+ N_ ("do not order objects before emitting them" )),
695
+ /* Textconv options, stand-ole*/
696
+ OPT_GROUP (N_ ("Emit object (blob or tree) with conversion or filter (stand-alone, or with batch)" )),
697
+ OPT_CMDMODE (0 , "textconv" , & opt ,
698
+ N_ ("run textconv on object's content" ), 'c' ),
699
+ OPT_CMDMODE (0 , "filters" , & opt ,
700
+ N_ ("run filters on object's content" ), 'w' ),
701
+ OPT_STRING (0 , "path" , & force_path , N_ ("blob|tree" ),
702
+ N_ ("use a <path> for (--textconv | --filters); Not with 'batch'" )),
691
703
OPT_END ()
692
704
};
693
705
694
706
git_config (git_cat_file_config , NULL );
695
707
696
708
batch .buffer_output = -1 ;
697
- argc = parse_options (argc , argv , prefix , options , cat_file_usage , 0 );
698
-
699
- if (opt ) {
700
- if (batch .enabled && (opt == 'c' || opt == 'w' ))
701
- batch .cmdmode = opt ;
702
- else if (argc == 1 )
703
- obj_name = argv [0 ];
704
- else
705
- usage_with_options (cat_file_usage , options );
706
- }
707
- if (!opt && !batch .enabled ) {
708
- if (argc == 2 ) {
709
- exp_type = argv [0 ];
710
- obj_name = argv [1 ];
711
- } else
712
- usage_with_options (cat_file_usage , options );
713
- }
714
- if (batch .enabled ) {
715
- if (batch .cmdmode != opt || argc )
716
- usage_with_options (cat_file_usage , options );
717
- if (batch .cmdmode && batch .all_objects )
718
- die ("--batch-all-objects cannot be combined with "
719
- "--textconv nor with --filters" );
720
- }
721
709
722
- if (( batch . follow_symlinks || batch . all_objects ) && ! batch . enabled ) {
723
- usage_with_options ( cat_file_usage , options );
724
- }
710
+ argc = parse_options ( argc , argv , prefix , options , usage , 0 );
711
+ opt_cw = ( opt == 'c' || opt == 'w' );
712
+ opt_epts = ( opt == 'e' || opt == 'p' || opt == 't' || opt == 's' );
725
713
726
- if (force_path && opt != 'c' && opt != 'w' ) {
727
- error ("--path=<path> needs --textconv or --filters" );
728
- usage_with_options (cat_file_usage , options );
729
- }
714
+ /* --batch-all-objects? */
715
+ if (opt == 'b' )
716
+ batch .all_objects = 1 ;
730
717
731
- if (force_path && batch .enabled ) {
732
- error ("options '--path=<path>' and '--batch' cannot be used together" );
733
- usage_with_options (cat_file_usage , options );
734
- }
718
+ /* Option compatibility */
719
+ if (force_path && !opt_cw )
720
+ usage_msg_optf (_ ("'%s=<%s>' needs '%s' or '%s'" ),
721
+ usage , options ,
722
+ "--path" , _ ("path|tree-ish" ), "--filters" ,
723
+ "--textconv" );
735
724
725
+ /* Option compatibility with batch mode */
726
+ if (batch .enabled )
727
+ ;
728
+ else if (batch .follow_symlinks )
729
+ usage_msg_optf (_ ("'%s' requires a batch mode" ), usage , options ,
730
+ "--follow-symlinks" );
731
+ else if (batch .buffer_output >= 0 )
732
+ usage_msg_optf (_ ("'%s' requires a batch mode" ), usage , options ,
733
+ "--buffer" );
734
+ else if (batch .all_objects )
735
+ usage_msg_optf (_ ("'%s' requires a batch mode" ), usage , options ,
736
+ "--batch-all-objects" );
737
+
738
+ /* Batch defaults */
736
739
if (batch .buffer_output < 0 )
737
740
batch .buffer_output = batch .all_objects ;
738
741
739
- if (batch .enabled )
742
+ /* Return early if we're in batch mode? */
743
+ if (batch .enabled ) {
744
+ if (opt_cw )
745
+ batch .cmdmode = opt ;
746
+ else if (opt && opt != 'b' )
747
+ usage_msg_optf (_ ("'-%c' is incompatible with batch mode" ),
748
+ usage , options , opt );
749
+ else if (argc )
750
+ usage_msg_opt (_ ("batch modes take no arguments" ), usage ,
751
+ options );
752
+
740
753
return batch_objects (& batch );
754
+ }
755
+
756
+ if (opt ) {
757
+ if (!argc && opt == 'c' )
758
+ usage_msg_optf (_ ("<rev> required with '%s'" ),
759
+ usage , options , "--textconv" );
760
+ else if (!argc && opt == 'w' )
761
+ usage_msg_optf (_ ("<rev> required with '%s'" ),
762
+ usage , options , "--filters" );
763
+ else if (!argc && opt_epts )
764
+ usage_msg_optf (_ ("<object> required with '-%c'" ),
765
+ usage , options , opt );
766
+ else if (argc == 1 )
767
+ obj_name = argv [0 ];
768
+ else
769
+ usage_msg_opt (_ ("too many arguments" ), usage , options );
770
+ } else if (!argc ) {
771
+ usage_with_options (usage , options );
772
+ } else if (argc != 2 ) {
773
+ usage_msg_optf (_ ("only two arguments allowed in <type> <object> mode, not %d" ),
774
+ usage , options , argc );
775
+ } else if (argc ) {
776
+ exp_type = argv [0 ];
777
+ obj_name = argv [1 ];
778
+ }
741
779
742
780
if (unknown_type && opt != 't' && opt != 's' )
743
781
die ("git cat-file --allow-unknown-type: use with -s or -t" );
0 commit comments