2121
2222static int read_directory_contents (const char * path , struct string_list * list ,
2323 const struct pathspec * pathspec ,
24- int skip )
24+ struct strbuf * match )
2525{
26- struct strbuf match = STRBUF_INIT ;
27- int len ;
26+ int len = match -> len ;
2827 DIR * dir ;
2928 struct dirent * e ;
3029
3130 if (!(dir = opendir (path )))
3231 return error ("Could not open directory %s" , path );
3332
34- if (pathspec ) {
35- strbuf_addstr (& match , path );
36- strbuf_complete (& match , '/' );
37- strbuf_remove (& match , 0 , skip );
38-
39- len = match .len ;
40- }
41-
4233 while ((e = readdir_skip_dot_and_dotdot (dir ))) {
4334 if (pathspec ) {
4435 int is_dir = 0 ;
4536
46- strbuf_setlen (& match , len );
47- strbuf_addstr (& match , e -> d_name );
37+ strbuf_setlen (match , len );
38+ strbuf_addstr (match , e -> d_name );
4839 if (NOT_CONSTANT (DTYPE (e )) != DT_UNKNOWN ) {
4940 is_dir = (DTYPE (e ) == DT_DIR );
5041 } else {
@@ -57,15 +48,15 @@ static int read_directory_contents(const char *path, struct string_list *list,
5748 }
5849
5950 if (!match_leading_pathspec (NULL , pathspec ,
60- match . buf , match . len ,
51+ match -> buf , match -> len ,
6152 0 , NULL , is_dir ))
6253 continue ;
6354 }
6455
6556 string_list_insert (list , e -> d_name );
6657 }
6758
68- strbuf_release ( & match );
59+ strbuf_setlen ( match , len );
6960 closedir (dir );
7061 return 0 ;
7162}
@@ -169,7 +160,8 @@ static struct diff_filespec *noindex_filespec(const struct git_hash_algo *algop,
169160
170161static int queue_diff (struct diff_options * o , const struct git_hash_algo * algop ,
171162 const char * name1 , const char * name2 , int recursing ,
172- const struct pathspec * ps , int skip1 , int skip2 )
163+ const struct pathspec * ps ,
164+ struct strbuf * ps_match1 , struct strbuf * ps_match2 )
173165{
174166 int mode1 = 0 , mode2 = 0 ;
175167 enum special special1 = SPECIAL_NONE , special2 = SPECIAL_NONE ;
@@ -208,10 +200,12 @@ static int queue_diff(struct diff_options *o, const struct git_hash_algo *algop,
208200 struct string_list p2 = STRING_LIST_INIT_DUP ;
209201 int i1 , i2 , ret = 0 ;
210202 size_t len1 = 0 , len2 = 0 ;
203+ size_t match1_len = ps_match1 -> len ;
204+ size_t match2_len = ps_match2 -> len ;
211205
212- if (name1 && read_directory_contents (name1 , & p1 , ps , skip1 ))
206+ if (name1 && read_directory_contents (name1 , & p1 , ps , ps_match1 ))
213207 return -1 ;
214- if (name2 && read_directory_contents (name2 , & p2 , ps , skip2 )) {
208+ if (name2 && read_directory_contents (name2 , & p2 , ps , ps_match2 )) {
215209 string_list_clear (& p1 , 0 );
216210 return -1 ;
217211 }
@@ -235,6 +229,11 @@ static int queue_diff(struct diff_options *o, const struct git_hash_algo *algop,
235229 strbuf_setlen (& buffer1 , len1 );
236230 strbuf_setlen (& buffer2 , len2 );
237231
232+ if (ps ) {
233+ strbuf_setlen (ps_match1 , match1_len );
234+ strbuf_setlen (ps_match2 , match2_len );
235+ }
236+
238237 if (i1 == p1 .nr )
239238 comp = 1 ;
240239 else if (i2 == p2 .nr )
@@ -245,18 +244,28 @@ static int queue_diff(struct diff_options *o, const struct git_hash_algo *algop,
245244 if (comp > 0 )
246245 n1 = NULL ;
247246 else {
248- strbuf_addstr (& buffer1 , p1 .items [i1 ++ ].string );
247+ strbuf_addstr (& buffer1 , p1 .items [i1 ].string );
248+ if (ps ) {
249+ strbuf_addstr (ps_match1 , p1 .items [i1 ].string );
250+ strbuf_complete (ps_match1 , '/' );
251+ }
249252 n1 = buffer1 .buf ;
253+ i1 ++ ;
250254 }
251255
252256 if (comp < 0 )
253257 n2 = NULL ;
254258 else {
255- strbuf_addstr (& buffer2 , p2 .items [i2 ++ ].string );
259+ strbuf_addstr (& buffer2 , p2 .items [i2 ].string );
260+ if (ps ) {
261+ strbuf_addstr (ps_match2 , p2 .items [i2 ].string );
262+ strbuf_complete (ps_match2 , '/' );
263+ }
256264 n2 = buffer2 .buf ;
265+ i2 ++ ;
257266 }
258267
259- ret = queue_diff (o , algop , n1 , n2 , 1 , ps , skip1 , skip2 );
268+ ret = queue_diff (o , algop , n1 , n2 , 1 , ps , ps_match1 , ps_match2 );
260269 }
261270 string_list_clear (& p1 , 0 );
262271 string_list_clear (& p2 , 0 );
@@ -346,7 +355,8 @@ int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop,
346355 int implicit_no_index , int argc , const char * * argv )
347356{
348357 struct pathspec pathspec , * ps = NULL ;
349- int i , no_index , skip1 = 0 , skip2 = 0 ;
358+ struct strbuf ps_match1 = STRBUF_INIT , ps_match2 = STRBUF_INIT ;
359+ int i , no_index ;
350360 int ret = 1 ;
351361 const char * paths [2 ];
352362 char * to_free [ARRAY_SIZE (paths )] = { 0 };
@@ -387,11 +397,6 @@ int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop,
387397 NULL , & argv [2 ]);
388398 if (pathspec .nr )
389399 ps = & pathspec ;
390-
391- skip1 = strlen (paths [0 ]);
392- skip1 += paths [0 ][skip1 ] == '/' ? 0 : 1 ;
393- skip2 = strlen (paths [1 ]);
394- skip2 += paths [1 ][skip2 ] == '/' ? 0 : 1 ;
395400 } else if (argc > 2 ) {
396401 warning (_ ("Limiting comparison with pathspecs is only "
397402 "supported if both paths are directories." ));
@@ -415,7 +420,7 @@ int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop,
415420 revs -> diffopt .flags .exit_with_status = 1 ;
416421
417422 if (queue_diff (& revs -> diffopt , algop , paths [0 ], paths [1 ], 0 , ps ,
418- skip1 , skip2 ))
423+ & ps_match1 , & ps_match2 ))
419424 goto out ;
420425 diff_set_mnemonic_prefix (& revs -> diffopt , "1/" , "2/" );
421426 diffcore_std (& revs -> diffopt );
@@ -431,6 +436,8 @@ int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop,
431436 for (i = 0 ; i < ARRAY_SIZE (to_free ); i ++ )
432437 free (to_free [i ]);
433438 strbuf_release (& replacement );
439+ strbuf_release (& ps_match1 );
440+ strbuf_release (& ps_match2 );
434441 if (ps )
435442 clear_pathspec (ps );
436443 return ret ;
0 commit comments