@@ -123,6 +123,7 @@ struct grep_opt {
123123 struct grep_pat * pattern_list ;
124124 struct grep_pat * * pattern_tail ;
125125 struct grep_expr * pattern_expression ;
126+ int prefix_length ;
126127 regex_t regexp ;
127128 unsigned linenum :1 ;
128129 unsigned invert :1 ;
@@ -136,6 +137,7 @@ struct grep_opt {
136137#define GREP_BINARY_TEXT 2
137138 unsigned binary :2 ;
138139 unsigned extended :1 ;
140+ unsigned relative :1 ;
139141 int regflags ;
140142 unsigned pre_context ;
141143 unsigned post_context ;
@@ -632,19 +634,40 @@ static int grep_buffer(struct grep_opt *opt, const char *name,
632634 return !!last_hit ;
633635}
634636
635- static int grep_sha1 (struct grep_opt * opt , const unsigned char * sha1 , const char * name )
637+ static int grep_sha1 (struct grep_opt * opt , const unsigned char * sha1 , const char * name , int tree_name_len )
636638{
637639 unsigned long size ;
638640 char * data ;
639641 char type [20 ];
642+ char * to_free = NULL ;
640643 int hit ;
644+
641645 data = read_sha1_file (sha1 , type , & size );
642646 if (!data ) {
643647 error ("'%s': unable to read %s" , name , sha1_to_hex (sha1 ));
644648 return 0 ;
645649 }
650+ if (opt -> relative && opt -> prefix_length ) {
651+ static char name_buf [PATH_MAX ];
652+ char * cp ;
653+ int name_len = strlen (name ) - opt -> prefix_length + 1 ;
654+
655+ if (!tree_name_len )
656+ name += opt -> prefix_length ;
657+ else {
658+ if (ARRAY_SIZE (name_buf ) <= name_len )
659+ cp = to_free = xmalloc (name_len );
660+ else
661+ cp = name_buf ;
662+ memcpy (cp , name , tree_name_len );
663+ strcpy (cp + tree_name_len ,
664+ name + tree_name_len + opt -> prefix_length );
665+ name = cp ;
666+ }
667+ }
646668 hit = grep_buffer (opt , name , data , size );
647669 free (data );
670+ free (to_free );
648671 return hit ;
649672}
650673
@@ -674,6 +697,8 @@ static int grep_file(struct grep_opt *opt, const char *filename)
674697 return 0 ;
675698 }
676699 close (i );
700+ if (opt -> relative && opt -> prefix_length )
701+ filename += opt -> prefix_length ;
677702 i = grep_buffer (opt , filename , data , st .st_size );
678703 free (data );
679704 return i ;
@@ -720,7 +745,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
720745 char * argptr = randarg ;
721746 struct grep_pat * p ;
722747
723- if (opt -> extended )
748+ if (opt -> extended || ( opt -> relative && opt -> prefix_length ) )
724749 return -1 ;
725750 len = nr = 0 ;
726751 push_arg ("grep" );
@@ -845,7 +870,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
845870 if (!pathspec_matches (paths , ce -> name ))
846871 continue ;
847872 if (cached )
848- hit |= grep_sha1 (opt , ce -> sha1 , ce -> name );
873+ hit |= grep_sha1 (opt , ce -> sha1 , ce -> name , 0 );
849874 else
850875 hit |= grep_file (opt , ce -> name );
851876 }
@@ -860,11 +885,12 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
860885 int hit = 0 ;
861886 struct name_entry entry ;
862887 char * down ;
863- char * path_buf = xmalloc (PATH_MAX + strlen (tree_name ) + 100 );
888+ int tn_len = strlen (tree_name );
889+ char * path_buf = xmalloc (PATH_MAX + tn_len + 100 );
864890
865- if (tree_name [ 0 ] ) {
866- int offset = sprintf (path_buf , "%s:" , tree_name );
867- down = path_buf + offset ;
891+ if (tn_len ) {
892+ tn_len = sprintf (path_buf , "%s:" , tree_name );
893+ down = path_buf + tn_len ;
868894 strcat (down , base );
869895 }
870896 else {
@@ -886,7 +912,7 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
886912 if (!pathspec_matches (paths , down ))
887913 ;
888914 else if (S_ISREG (entry .mode ))
889- hit |= grep_sha1 (opt , entry .sha1 , path_buf );
915+ hit |= grep_sha1 (opt , entry .sha1 , path_buf , tn_len );
890916 else if (S_ISDIR (entry .mode )) {
891917 char type [20 ];
892918 struct tree_desc sub ;
@@ -907,7 +933,7 @@ static int grep_object(struct grep_opt *opt, const char **paths,
907933 struct object * obj , const char * name )
908934{
909935 if (obj -> type == OBJ_BLOB )
910- return grep_sha1 (opt , obj -> sha1 , name );
936+ return grep_sha1 (opt , obj -> sha1 , name , 0 );
911937 if (obj -> type == OBJ_COMMIT || obj -> type == OBJ_TREE ) {
912938 struct tree_desc tree ;
913939 void * data ;
@@ -945,6 +971,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
945971 int i ;
946972
947973 memset (& opt , 0 , sizeof (opt ));
974+ opt .prefix_length = (prefix && * prefix ) ? strlen (prefix ) : 0 ;
975+ opt .relative = 1 ;
948976 opt .pattern_tail = & opt .pattern_list ;
949977 opt .regflags = REG_NEWLINE ;
950978
@@ -1118,6 +1146,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
11181146 }
11191147 die (emsg_missing_argument , arg );
11201148 }
1149+ if (!strcmp ("--full-name" , arg )) {
1150+ opt .relative = 0 ;
1151+ continue ;
1152+ }
11211153 if (!strcmp ("--" , arg )) {
11221154 /* later processing wants to have this at argv[1] */
11231155 argv -- ;
@@ -1176,8 +1208,15 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
11761208 verify_filename (prefix , argv [j ]);
11771209 }
11781210
1179- if (i < argc )
1211+ if (i < argc ) {
11801212 paths = get_pathspec (prefix , argv + i );
1213+ if (opt .prefix_length && opt .relative ) {
1214+ /* Make sure we do not get outside of paths */
1215+ for (i = 0 ; paths [i ]; i ++ )
1216+ if (strncmp (prefix , paths [i ], opt .prefix_length ))
1217+ die ("git-grep: cannot generate relative filenames containing '..'" );
1218+ }
1219+ }
11811220 else if (prefix ) {
11821221 paths = xcalloc (2 , sizeof (const char * ));
11831222 paths [0 ] = prefix ;
0 commit comments