19
#include "dir.h"
20
#include "pathspec.h"
21
#include "submodule.h"
22
+#include "submodule-config.h"
23
24
static char const * const grep_usage[] = {
25
N_("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"),
29
static const char *super_prefix;
30
static int recurse_submodules;
31
static struct argv_array submodule_options = ARGV_ARRAY_INIT;
32
+static const char *parent_basename;
33
34
static int grep_submodule_launch(struct grep_opt *opt,
35
const struct grep_source *gs);
536
{
537
struct child_process cp = CHILD_PROCESS_INIT;
538
int status, i;
539
+ const char *end_of_base;
540
+ const char *name;
541
struct work_item *w = opt->output_priv;
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
+
549
prepare_submodule_repo_env(&cp.env_array);
550
551
/* Add super prefix */
552
argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
553
super_prefix ? super_prefix : "",
544
- gs->name);
554
+ name);
555
argv_array_push(&cp.args, "grep");
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
+
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
+
584
argv_array_push(&cp.args, submodule_options.argv[i]);
585
+ }
586
587
cp.git_cmd = 1;
588
cp.dir = gs->path;
709
enum interesting match = entry_not_interesting;
710
struct name_entry entry;
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
+ }
718
719
while (tree_entry(tree, &entry)) {
720
int te_len = tree_entry_len(&entry);
721
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
+
728
if (match == all_entries_not_interesting)
729
break;
730
if (match == entry_not_interesting)
736
if (S_ISREG(entry.mode)) {
737
hit |= grep_sha1(opt, entry.oid->hash, base->buf, tn_len,
738
check_attr ? base->buf + tn_len : NULL);
693
- }
694
- else if (S_ISDIR(entry.mode)) {
739
+ } else if (S_ISDIR(entry.mode)) {
740
enum object_type type;
741
struct tree_desc sub;
742
void *data;
752
hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
753
check_attr);
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);
758
}
759
+
760
strbuf_setlen(base, old_baselen);
761
762
if (hit && opt->status_only)
763
break;
764
}
765
+
766
+ strbuf_release(&name);
767
return hit;
768
}
769
787
if (!data)
788
die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid));
789
790
+ /* Use parent's name as base when recursing submodules */
791
+ if (recurse_submodules && parent_basename)
792
+ name = parent_basename;
793
+
794
len = name ? strlen(name) : 0;
795
strbuf_init(&base, PATH_MAX + len + 1);
796
if (len) {
817
for (i = 0; i < nr; i++) {
818
struct object *real_obj;
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
+ }
826
if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path)) {
827
hit = 1;
828
if (opt->status_only)
963
N_("ignore files specified via '.gitignore'"), 1),
964
OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
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")),
969
OPT_GROUP(""),
970
OPT_BOOL('v', "invert-match", &opt.invert,
971
N_("show non-matching lines")),
1218
}
1219
}
1220
1157
- if (recurse_submodules && (!use_index || untracked || list.nr))
1221
+ if (recurse_submodules && (!use_index || untracked))
1222
die(_("option not supported with --recurse-submodules."));
1223
1224
if (!show_in_pager && !opt.status_only)