19
19
#include "dir.h"
20
20
#include "pathspec.h"
21
21
#include "submodule.h"
22
+ #include "submodule-config.h"
22
23
23
24
static char const * const grep_usage [] = {
24
25
N_ ("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]" ),
@@ -28,6 +29,7 @@ static char const * const grep_usage[] = {
28
29
static const char * super_prefix ;
29
30
static int recurse_submodules ;
30
31
static struct argv_array submodule_options = ARGV_ARRAY_INIT ;
32
+ static const char * parent_basename ;
31
33
32
34
static int grep_submodule_launch (struct grep_opt * opt ,
33
35
const struct grep_source * gs );
@@ -534,19 +536,53 @@ static int grep_submodule_launch(struct grep_opt *opt,
534
536
{
535
537
struct child_process cp = CHILD_PROCESS_INIT ;
536
538
int status , i ;
539
+ const char * end_of_base ;
540
+ const char * name ;
537
541
struct work_item * w = opt -> output_priv ;
538
542
543
+ end_of_base = strchr (gs -> name , ':' );
544
+ if (gs -> identifier && end_of_base )
545
+ name = end_of_base + 1 ;
546
+ else
547
+ name = gs -> name ;
548
+
539
549
prepare_submodule_repo_env (& cp .env_array );
540
550
541
551
/* Add super prefix */
542
552
argv_array_pushf (& cp .args , "--super-prefix=%s%s/" ,
543
553
super_prefix ? super_prefix : "" ,
544
- gs -> name );
554
+ name );
545
555
argv_array_push (& cp .args , "grep" );
546
556
557
+ /*
558
+ * Add basename of parent project
559
+ * When performing grep on a tree object the filename is prefixed
560
+ * with the object's name: 'tree-name:filename'. In order to
561
+ * provide uniformity of output we want to pass the name of the
562
+ * parent project's object name to the submodule so the submodule can
563
+ * prefix its output with the parent's name and not its own SHA1.
564
+ */
565
+ if (gs -> identifier && end_of_base )
566
+ argv_array_pushf (& cp .args , "--parent-basename=%.*s" ,
567
+ (int ) (end_of_base - gs -> name ),
568
+ gs -> name );
569
+
547
570
/* Add options */
548
- for (i = 0 ; i < submodule_options .argc ; i ++ )
571
+ for (i = 0 ; i < submodule_options .argc ; i ++ ) {
572
+ /*
573
+ * If there is a tree identifier for the submodule, add the
574
+ * rev after adding the submodule options but before the
575
+ * pathspecs. To do this we listen for the '--' and insert the
576
+ * sha1 before pushing the '--' onto the child process argv
577
+ * array.
578
+ */
579
+ if (gs -> identifier &&
580
+ !strcmp ("--" , submodule_options .argv [i ])) {
581
+ argv_array_push (& cp .args , sha1_to_hex (gs -> identifier ));
582
+ }
583
+
549
584
argv_array_push (& cp .args , submodule_options .argv [i ]);
585
+ }
550
586
551
587
cp .git_cmd = 1 ;
552
588
cp .dir = gs -> path ;
@@ -673,12 +709,22 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
673
709
enum interesting match = entry_not_interesting ;
674
710
struct name_entry entry ;
675
711
int old_baselen = base -> len ;
712
+ struct strbuf name = STRBUF_INIT ;
713
+ int name_base_len = 0 ;
714
+ if (super_prefix ) {
715
+ strbuf_addstr (& name , super_prefix );
716
+ name_base_len = name .len ;
717
+ }
676
718
677
719
while (tree_entry (tree , & entry )) {
678
720
int te_len = tree_entry_len (& entry );
679
721
680
722
if (match != all_entries_interesting ) {
681
- match = tree_entry_interesting (& entry , base , tn_len , pathspec );
723
+ strbuf_addstr (& name , base -> buf + tn_len );
724
+ match = tree_entry_interesting (& entry , & name ,
725
+ 0 , pathspec );
726
+ strbuf_setlen (& name , name_base_len );
727
+
682
728
if (match == all_entries_not_interesting )
683
729
break ;
684
730
if (match == entry_not_interesting )
@@ -690,8 +736,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
690
736
if (S_ISREG (entry .mode )) {
691
737
hit |= grep_sha1 (opt , entry .oid -> hash , base -> buf , tn_len ,
692
738
check_attr ? base -> buf + tn_len : NULL );
693
- }
694
- else if (S_ISDIR (entry .mode )) {
739
+ } else if (S_ISDIR (entry .mode )) {
695
740
enum object_type type ;
696
741
struct tree_desc sub ;
697
742
void * data ;
@@ -707,12 +752,18 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
707
752
hit |= grep_tree (opt , pathspec , & sub , base , tn_len ,
708
753
check_attr );
709
754
free (data );
755
+ } else if (recurse_submodules && S_ISGITLINK (entry .mode )) {
756
+ hit |= grep_submodule (opt , entry .oid -> hash , base -> buf ,
757
+ base -> buf + tn_len );
710
758
}
759
+
711
760
strbuf_setlen (base , old_baselen );
712
761
713
762
if (hit && opt -> status_only )
714
763
break ;
715
764
}
765
+
766
+ strbuf_release (& name );
716
767
return hit ;
717
768
}
718
769
@@ -736,6 +787,10 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
736
787
if (!data )
737
788
die (_ ("unable to read tree (%s)" ), oid_to_hex (& obj -> oid ));
738
789
790
+ /* Use parent's name as base when recursing submodules */
791
+ if (recurse_submodules && parent_basename )
792
+ name = parent_basename ;
793
+
739
794
len = name ? strlen (name ) : 0 ;
740
795
strbuf_init (& base , PATH_MAX + len + 1 );
741
796
if (len ) {
@@ -762,6 +817,12 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
762
817
for (i = 0 ; i < nr ; i ++ ) {
763
818
struct object * real_obj ;
764
819
real_obj = deref_tag (list -> objects [i ].item , NULL , 0 );
820
+
821
+ /* load the gitmodules file for this rev */
822
+ if (recurse_submodules ) {
823
+ submodule_free ();
824
+ gitmodules_config_sha1 (real_obj -> oid .hash );
825
+ }
765
826
if (grep_object (opt , pathspec , real_obj , list -> objects [i ].name , list -> objects [i ].path )) {
766
827
hit = 1 ;
767
828
if (opt -> status_only )
@@ -902,6 +963,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
902
963
N_ ("ignore files specified via '.gitignore'" ), 1 ),
903
964
OPT_BOOL (0 , "recurse-submodules" , & recurse_submodules ,
904
965
N_ ("recursivley search in each submodule" )),
966
+ OPT_STRING (0 , "parent-basename" , & parent_basename ,
967
+ N_ ("basename" ),
968
+ N_ ("prepend parent project's basename to output" )),
905
969
OPT_GROUP ("" ),
906
970
OPT_BOOL ('v' , "invert-match" , & opt .invert ,
907
971
N_ ("show non-matching lines" )),
@@ -1154,7 +1218,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1154
1218
}
1155
1219
}
1156
1220
1157
- if (recurse_submodules && (!use_index || untracked || list . nr ))
1221
+ if (recurse_submodules && (!use_index || untracked ))
1158
1222
die (_ ("option not supported with --recurse-submodules." ));
1159
1223
1160
1224
if (!show_in_pager && !opt .status_only )
0 commit comments