88#include "xdiff-interface.h"
99#include "kwset.h"
1010
11- typedef int (* pickaxe_fn )(struct diff_filepair * p , struct diff_options * o , regex_t * regexp , kwset_t kws );
11+ typedef int (* pickaxe_fn )(mmfile_t * one , mmfile_t * two ,
12+ struct diff_options * o ,
13+ regex_t * regexp , kwset_t kws );
14+
15+ static int pickaxe_match (struct diff_filepair * p , struct diff_options * o ,
16+ regex_t * regexp , kwset_t kws , pickaxe_fn fn );
1217
1318static void pickaxe (struct diff_queue_struct * q , struct diff_options * o ,
1419 regex_t * regexp , kwset_t kws , pickaxe_fn fn )
@@ -22,7 +27,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
2227 /* Showing the whole changeset if needle exists */
2328 for (i = 0 ; i < q -> nr ; i ++ ) {
2429 struct diff_filepair * p = q -> queue [i ];
25- if (fn (p , o , regexp , kws ))
30+ if (pickaxe_match (p , o , regexp , kws , fn ))
2631 return ; /* do not munge the queue */
2732 }
2833
@@ -37,7 +42,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
3742 /* Showing only the filepairs that has the needle */
3843 for (i = 0 ; i < q -> nr ; i ++ ) {
3944 struct diff_filepair * p = q -> queue [i ];
40- if (fn (p , o , regexp , kws ))
45+ if (pickaxe_match (p , o , regexp , kws , fn ))
4146 diff_q (& outq , p );
4247 else
4348 diff_free_filepair (p );
@@ -74,64 +79,33 @@ static void diffgrep_consume(void *priv, char *line, unsigned long len)
7479 line [len ] = hold ;
7580}
7681
77- static void fill_one (struct diff_filespec * one ,
78- mmfile_t * mf , struct userdiff_driver * * textconv )
79- {
80- if (DIFF_FILE_VALID (one )) {
81- * textconv = get_textconv (one );
82- mf -> size = fill_textconv (* textconv , one , & mf -> ptr );
83- } else {
84- memset (mf , 0 , sizeof (* mf ));
85- }
86- }
87-
88- static int diff_grep (struct diff_filepair * p , struct diff_options * o ,
82+ static int diff_grep (mmfile_t * one , mmfile_t * two ,
83+ struct diff_options * o ,
8984 regex_t * regexp , kwset_t kws )
9085{
9186 regmatch_t regmatch ;
92- struct userdiff_driver * textconv_one = NULL ;
93- struct userdiff_driver * textconv_two = NULL ;
94- mmfile_t mf1 , mf2 ;
95- int hit ;
87+ struct diffgrep_cb ecbdata ;
88+ xpparam_t xpp ;
89+ xdemitconf_t xecfg ;
9690
97- if (diff_unmodified_pair (p ))
98- return 0 ;
91+ if (!one )
92+ return !regexec (regexp , two -> ptr , 1 , & regmatch , 0 );
93+ if (!two )
94+ return !regexec (regexp , one -> ptr , 1 , & regmatch , 0 );
9995
100- fill_one (p -> one , & mf1 , & textconv_one );
101- fill_one (p -> two , & mf2 , & textconv_two );
102-
103- if (!mf1 .ptr ) {
104- if (!mf2 .ptr )
105- return 0 ; /* ignore unmerged */
106- /* created "two" -- does it have what we are looking for? */
107- hit = !regexec (regexp , mf2 .ptr , 1 , & regmatch , 0 );
108- } else if (!mf2 .ptr ) {
109- /* removed "one" -- did it have what we are looking for? */
110- hit = !regexec (regexp , mf1 .ptr , 1 , & regmatch , 0 );
111- } else {
112- /*
113- * We have both sides; need to run textual diff and see if
114- * the pattern appears on added/deleted lines.
115- */
116- struct diffgrep_cb ecbdata ;
117- xpparam_t xpp ;
118- xdemitconf_t xecfg ;
119-
120- memset (& xpp , 0 , sizeof (xpp ));
121- memset (& xecfg , 0 , sizeof (xecfg ));
122- ecbdata .regexp = regexp ;
123- ecbdata .hit = 0 ;
124- xecfg .ctxlen = o -> context ;
125- xecfg .interhunkctxlen = o -> interhunkcontext ;
126- xdi_diff_outf (& mf1 , & mf2 , diffgrep_consume , & ecbdata ,
127- & xpp , & xecfg );
128- hit = ecbdata .hit ;
129- }
130- if (textconv_one )
131- free (mf1 .ptr );
132- if (textconv_two )
133- free (mf2 .ptr );
134- return hit ;
96+ /*
97+ * We have both sides; need to run textual diff and see if
98+ * the pattern appears on added/deleted lines.
99+ */
100+ memset (& xpp , 0 , sizeof (xpp ));
101+ memset (& xecfg , 0 , sizeof (xecfg ));
102+ ecbdata .regexp = regexp ;
103+ ecbdata .hit = 0 ;
104+ xecfg .ctxlen = o -> context ;
105+ xecfg .interhunkctxlen = o -> interhunkcontext ;
106+ xdi_diff_outf (one , two , diffgrep_consume , & ecbdata ,
107+ & xpp , & xecfg );
108+ return ecbdata .hit ;
135109}
136110
137111static void diffcore_pickaxe_grep (struct diff_options * o )
@@ -198,17 +172,37 @@ static unsigned int contains(mmfile_t *mf, struct diff_options *o,
198172 return cnt ;
199173}
200174
201- static int has_changes (struct diff_filepair * p , struct diff_options * o ,
175+ static int has_changes (mmfile_t * one , mmfile_t * two ,
176+ struct diff_options * o ,
202177 regex_t * regexp , kwset_t kws )
203178{
204- struct userdiff_driver * textconv_one = get_textconv (p -> one );
205- struct userdiff_driver * textconv_two = get_textconv (p -> two );
179+ if (!one )
180+ return contains (two , o , regexp , kws ) != 0 ;
181+ if (!two )
182+ return contains (one , o , regexp , kws ) != 0 ;
183+ return contains (one , o , regexp , kws ) != contains (two , o , regexp , kws );
184+ }
185+
186+ static int pickaxe_match (struct diff_filepair * p , struct diff_options * o ,
187+ regex_t * regexp , kwset_t kws , pickaxe_fn fn )
188+ {
189+ struct userdiff_driver * textconv_one = NULL ;
190+ struct userdiff_driver * textconv_two = NULL ;
206191 mmfile_t mf1 , mf2 ;
207192 int ret ;
208193
209194 if (!o -> pickaxe [0 ])
210195 return 0 ;
211196
197+ /* ignore unmerged */
198+ if (!DIFF_FILE_VALID (p -> one ) && !DIFF_FILE_VALID (p -> two ))
199+ return 0 ;
200+
201+ if (DIFF_OPT_TST (o , ALLOW_TEXTCONV )) {
202+ textconv_one = get_textconv (p -> one );
203+ textconv_two = get_textconv (p -> two );
204+ }
205+
212206 /*
213207 * If we have an unmodified pair, we know that the count will be the
214208 * same and don't even have to load the blobs. Unless textconv is in
@@ -219,20 +213,12 @@ static int has_changes(struct diff_filepair *p, struct diff_options *o,
219213 if (textconv_one == textconv_two && diff_unmodified_pair (p ))
220214 return 0 ;
221215
222- fill_one ( p -> one , & mf1 , & textconv_one );
223- fill_one ( p -> two , & mf2 , & textconv_two );
216+ mf1 . size = fill_textconv ( textconv_one , p -> one , & mf1 . ptr );
217+ mf2 . size = fill_textconv ( textconv_two , p -> two , & mf2 . ptr );
224218
225- if (!mf1 .ptr ) {
226- if (!mf2 .ptr )
227- ret = 0 ; /* ignore unmerged */
228- /* created */
229- ret = contains (& mf2 , o , regexp , kws ) != 0 ;
230- }
231- else if (!mf2 .ptr ) /* removed */
232- ret = contains (& mf1 , o , regexp , kws ) != 0 ;
233- else
234- ret = contains (& mf1 , o , regexp , kws ) !=
235- contains (& mf2 , o , regexp , kws );
219+ ret = fn (DIFF_FILE_VALID (p -> one ) ? & mf1 : NULL ,
220+ DIFF_FILE_VALID (p -> two ) ? & mf2 : NULL ,
221+ o , regexp , kws );
236222
237223 if (textconv_one )
238224 free (mf1 .ptr );
0 commit comments