1111#include "tree-walk.h"
1212#include "builtin.h"
1313#include "parse-options.h"
14+ #include "string-list.h"
15+ #include "run-command.h"
1416#include "userdiff.h"
1517#include "grep.h"
1618#include "quote.h"
@@ -556,6 +558,33 @@ static int grep_file(struct grep_opt *opt, const char *filename)
556558 }
557559}
558560
561+ static void append_path (struct grep_opt * opt , const void * data , size_t len )
562+ {
563+ struct string_list * path_list = opt -> output_priv ;
564+
565+ if (len == 1 && * (const char * )data == '\0' )
566+ return ;
567+ string_list_append (path_list , xstrndup (data , len ));
568+ }
569+
570+ static void run_pager (struct grep_opt * opt , const char * prefix )
571+ {
572+ struct string_list * path_list = opt -> output_priv ;
573+ const char * * argv = xmalloc (sizeof (const char * ) * (path_list -> nr + 1 ));
574+ int i , status ;
575+
576+ for (i = 0 ; i < path_list -> nr ; i ++ )
577+ argv [i ] = path_list -> items [i ].string ;
578+ argv [path_list -> nr ] = NULL ;
579+
580+ if (prefix && chdir (prefix ))
581+ die ("Failed to chdir: %s" , prefix );
582+ status = run_command_v_opt (argv , RUN_USING_SHELL );
583+ if (status )
584+ exit (status );
585+ free (argv );
586+ }
587+
559588static int grep_cache (struct grep_opt * opt , const char * * paths , int cached )
560589{
561590 int hit = 0 ;
@@ -590,7 +619,6 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
590619 if (hit && opt -> status_only )
591620 break ;
592621 }
593- free_grep_patterns (opt );
594622 return hit ;
595623}
596624
@@ -675,6 +703,25 @@ static int grep_object(struct grep_opt *opt, const char **paths,
675703 die ("unable to grep from object of type %s" , typename (obj -> type ));
676704}
677705
706+ static int grep_objects (struct grep_opt * opt , const char * * paths ,
707+ const struct object_array * list )
708+ {
709+ unsigned int i ;
710+ int hit = 0 ;
711+ const unsigned int nr = list -> nr ;
712+
713+ for (i = 0 ; i < nr ; i ++ ) {
714+ struct object * real_obj ;
715+ real_obj = deref_tag (list -> objects [i ].item , NULL , 0 );
716+ if (grep_object (opt , paths , real_obj , list -> objects [i ].name )) {
717+ hit = 1 ;
718+ if (opt -> status_only )
719+ break ;
720+ }
721+ }
722+ return hit ;
723+ }
724+
678725static int grep_directory (struct grep_opt * opt , const char * * paths )
679726{
680727 struct dir_struct dir ;
@@ -689,7 +736,6 @@ static int grep_directory(struct grep_opt *opt, const char **paths)
689736 if (hit && opt -> status_only )
690737 break ;
691738 }
692- free_grep_patterns (opt );
693739 return hit ;
694740}
695741
@@ -786,9 +832,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
786832 int cached = 0 ;
787833 int seen_dashdash = 0 ;
788834 int external_grep_allowed__ignored ;
835+ const char * show_in_pager = NULL , * default_pager = "dummy" ;
789836 struct grep_opt opt ;
790837 struct object_array list = { 0 , 0 , NULL };
791838 const char * * paths = NULL ;
839+ struct string_list path_list = { NULL , 0 , 0 , 0 };
792840 int i ;
793841 int dummy ;
794842 int nongit = 0 , use_index = 1 ;
@@ -872,6 +920,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
872920 OPT_BOOLEAN (0 , "all-match" , & opt .all_match ,
873921 "show only matches from files that match all patterns" ),
874922 OPT_GROUP ("" ),
923+ { OPTION_STRING , 'O' , "open-files-in-pager" , & show_in_pager ,
924+ "pager" , "show matching files in the pager" ,
925+ PARSE_OPT_OPTARG , NULL , (intptr_t )default_pager },
875926 OPT_BOOLEAN (0 , "ext-grep" , & external_grep_allowed__ignored ,
876927 "allow calling of grep(1) (ignored by this build)" ),
877928 { OPTION_CALLBACK , 0 , "help-all" , & options , NULL , "show usage" ,
@@ -947,6 +998,17 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
947998 argc -- ;
948999 }
9491000
1001+ if (show_in_pager == default_pager )
1002+ show_in_pager = git_pager (1 );
1003+ if (show_in_pager ) {
1004+ opt .name_only = 1 ;
1005+ opt .null_following_name = 1 ;
1006+ opt .output_priv = & path_list ;
1007+ opt .output = append_path ;
1008+ string_list_append (& path_list , show_in_pager );
1009+ use_threads = 0 ;
1010+ }
1011+
9501012 if (!opt .pattern_list )
9511013 die ("no pattern given." );
9521014 if (!opt .fixed && opt .ignore_case )
@@ -1003,44 +1065,51 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
10031065 paths [1 ] = NULL ;
10041066 }
10051067
1068+ if (show_in_pager && (cached || list .nr ))
1069+ die ("--open-files-in-pager only works on the worktree" );
1070+
1071+ if (show_in_pager && opt .pattern_list && !opt .pattern_list -> next ) {
1072+ const char * pager = path_list .items [0 ].string ;
1073+ int len = strlen (pager );
1074+
1075+ if (len > 4 && is_dir_sep (pager [len - 5 ]))
1076+ pager += len - 4 ;
1077+
1078+ if (!strcmp ("less" , pager ) || !strcmp ("vi" , pager )) {
1079+ struct strbuf buf = STRBUF_INIT ;
1080+ strbuf_addf (& buf , "+/%s%s" ,
1081+ strcmp ("less" , pager ) ? "" : "*" ,
1082+ opt .pattern_list -> pattern );
1083+ string_list_append (& path_list , buf .buf );
1084+ strbuf_detach (& buf , NULL );
1085+ }
1086+ }
1087+
1088+ if (!show_in_pager )
1089+ setup_pager ();
1090+
1091+
10061092 if (!use_index ) {
1007- int hit ;
10081093 if (cached )
10091094 die ("--cached cannot be used with --no-index." );
10101095 if (list .nr )
10111096 die ("--no-index cannot be used with revs." );
10121097 hit = grep_directory (& opt , paths );
1013- if (use_threads )
1014- hit |= wait_all ();
1015- return !hit ;
1016- }
1017-
1018- if (!list .nr ) {
1019- int hit ;
1098+ } else if (!list .nr ) {
10201099 if (!cached )
10211100 setup_work_tree ();
10221101
10231102 hit = grep_cache (& opt , paths , cached );
1024- if (use_threads )
1025- hit |= wait_all ();
1026- return !hit ;
1027- }
1028-
1029- if (cached )
1030- die ("both --cached and trees are given." );
1031-
1032- for (i = 0 ; i < list .nr ; i ++ ) {
1033- struct object * real_obj ;
1034- real_obj = deref_tag (list .objects [i ].item , NULL , 0 );
1035- if (grep_object (& opt , paths , real_obj , list .objects [i ].name )) {
1036- hit = 1 ;
1037- if (opt .status_only )
1038- break ;
1039- }
1103+ } else {
1104+ if (cached )
1105+ die ("both --cached and trees are given." );
1106+ hit = grep_objects (& opt , paths , & list );
10401107 }
10411108
10421109 if (use_threads )
10431110 hit |= wait_all ();
1111+ if (hit && show_in_pager )
1112+ run_pager (& opt , prefix );
10441113 free_grep_patterns (& opt );
10451114 return !hit ;
10461115}
0 commit comments