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 );
12+
13+ static void pickaxe (struct diff_queue_struct * q , struct diff_options * o ,
14+ regex_t * regexp , kwset_t kws , pickaxe_fn fn )
15+ {
16+ int i ;
17+ struct diff_queue_struct outq ;
18+
19+ DIFF_QUEUE_CLEAR (& outq );
20+
21+ if (o -> pickaxe_opts & DIFF_PICKAXE_ALL ) {
22+ /* Showing the whole changeset if needle exists */
23+ for (i = 0 ; i < q -> nr ; i ++ ) {
24+ struct diff_filepair * p = q -> queue [i ];
25+ if (fn (p , o , regexp , kws ))
26+ return ; /* do not munge the queue */
27+ }
28+
29+ /*
30+ * Otherwise we will clear the whole queue by copying
31+ * the empty outq at the end of this function, but
32+ * first clear the current entries in the queue.
33+ */
34+ for (i = 0 ; i < q -> nr ; i ++ )
35+ diff_free_filepair (q -> queue [i ]);
36+ } else {
37+ /* Showing only the filepairs that has the needle */
38+ for (i = 0 ; i < q -> nr ; i ++ ) {
39+ struct diff_filepair * p = q -> queue [i ];
40+ if (fn (p , o , regexp , kws ))
41+ diff_q (& outq , p );
42+ else
43+ diff_free_filepair (p );
44+ }
45+ }
46+
47+ free (q -> queue );
48+ * q = outq ;
49+ }
50+
1151struct diffgrep_cb {
1252 regex_t * regexp ;
1353 int hit ;
@@ -45,7 +85,8 @@ static void fill_one(struct diff_filespec *one,
4585 }
4686}
4787
48- static int diff_grep (struct diff_filepair * p , regex_t * regexp , struct diff_options * o )
88+ static int diff_grep (struct diff_filepair * p , struct diff_options * o ,
89+ regex_t * regexp , kwset_t kws )
4990{
5091 regmatch_t regmatch ;
5192 struct userdiff_driver * textconv_one = NULL ;
@@ -95,12 +136,8 @@ static int diff_grep(struct diff_filepair *p, regex_t *regexp, struct diff_optio
95136
96137static void diffcore_pickaxe_grep (struct diff_options * o )
97138{
98- struct diff_queue_struct * q = & diff_queued_diff ;
99- int i , has_changes , err ;
139+ int err ;
100140 regex_t regex ;
101- struct diff_queue_struct outq ;
102- outq .queue = NULL ;
103- outq .nr = outq .alloc = 0 ;
104141
105142 err = regcomp (& regex , o -> pickaxe , REG_EXTENDED | REG_NEWLINE );
106143 if (err ) {
@@ -110,51 +147,21 @@ static void diffcore_pickaxe_grep(struct diff_options *o)
110147 die ("invalid log-grep regex: %s" , errbuf );
111148 }
112149
113- if (o -> pickaxe_opts & DIFF_PICKAXE_ALL ) {
114- /* Showing the whole changeset if needle exists */
115- for (i = has_changes = 0 ; !has_changes && i < q -> nr ; i ++ ) {
116- struct diff_filepair * p = q -> queue [i ];
117- if (diff_grep (p , & regex , o ))
118- has_changes ++ ;
119- }
120- if (has_changes )
121- return ; /* do not munge the queue */
122-
123- /*
124- * Otherwise we will clear the whole queue by copying
125- * the empty outq at the end of this function, but
126- * first clear the current entries in the queue.
127- */
128- for (i = 0 ; i < q -> nr ; i ++ )
129- diff_free_filepair (q -> queue [i ]);
130- } else {
131- /* Showing only the filepairs that has the needle */
132- for (i = 0 ; i < q -> nr ; i ++ ) {
133- struct diff_filepair * p = q -> queue [i ];
134- if (diff_grep (p , & regex , o ))
135- diff_q (& outq , p );
136- else
137- diff_free_filepair (p );
138- }
139- }
150+ pickaxe (& diff_queued_diff , o , & regex , NULL , diff_grep );
140151
141152 regfree (& regex );
142-
143- free (q -> queue );
144- * q = outq ;
145153 return ;
146154}
147155
148- static unsigned int contains (struct diff_filespec * one ,
149- const char * needle , unsigned long len ,
156+ static unsigned int contains (struct diff_filespec * one , struct diff_options * o ,
150157 regex_t * regexp , kwset_t kws )
151158{
152159 unsigned int cnt ;
153160 unsigned long sz ;
154161 const char * data ;
155- if (diff_populate_filespec ( one , 0 ) )
162+ if (! o -> pickaxe [ 0 ] )
156163 return 0 ;
157- if (! len )
164+ if (diff_populate_filespec ( one , 0 ) )
158165 return 0 ;
159166
160167 sz = one -> size ;
@@ -176,32 +183,47 @@ static unsigned int contains(struct diff_filespec *one,
176183
177184 } else { /* Classic exact string match */
178185 while (sz ) {
179- size_t offset = kwsexec (kws , data , sz , NULL );
186+ struct kwsmatch kwsm ;
187+ size_t offset = kwsexec (kws , data , sz , & kwsm );
180188 const char * found ;
181189 if (offset == -1 )
182190 break ;
183191 else
184192 found = data + offset ;
185- sz -= found - data + len ;
186- data = found + len ;
193+ sz -= found - data + kwsm . size [ 0 ] ;
194+ data = found + kwsm . size [ 0 ] ;
187195 cnt ++ ;
188196 }
189197 }
190198 diff_free_filespec_data (one );
191199 return cnt ;
192200}
193201
202+ static int has_changes (struct diff_filepair * p , struct diff_options * o ,
203+ regex_t * regexp , kwset_t kws )
204+ {
205+ if (!DIFF_FILE_VALID (p -> one )) {
206+ if (!DIFF_FILE_VALID (p -> two ))
207+ return 0 ; /* ignore unmerged */
208+ /* created */
209+ return contains (p -> two , o , regexp , kws ) != 0 ;
210+ }
211+ if (!DIFF_FILE_VALID (p -> two ))
212+ return contains (p -> one , o , regexp , kws ) != 0 ;
213+ if (!diff_unmodified_pair (p )) {
214+ return contains (p -> one , o , regexp , kws ) !=
215+ contains (p -> two , o , regexp , kws );
216+ }
217+ return 0 ;
218+ }
219+
194220static void diffcore_pickaxe_count (struct diff_options * o )
195221{
196222 const char * needle = o -> pickaxe ;
197223 int opts = o -> pickaxe_opts ;
198- struct diff_queue_struct * q = & diff_queued_diff ;
199224 unsigned long len = strlen (needle );
200- int i , has_changes ;
201225 regex_t regex , * regexp = NULL ;
202226 kwset_t kws = NULL ;
203- struct diff_queue_struct outq ;
204- DIFF_QUEUE_CLEAR (& outq );
205227
206228 if (opts & DIFF_PICKAXE_REGEX ) {
207229 int err ;
@@ -220,72 +242,12 @@ static void diffcore_pickaxe_count(struct diff_options *o)
220242 kwsprep (kws );
221243 }
222244
223- if (opts & DIFF_PICKAXE_ALL ) {
224- /* Showing the whole changeset if needle exists */
225- for (i = has_changes = 0 ; !has_changes && i < q -> nr ; i ++ ) {
226- struct diff_filepair * p = q -> queue [i ];
227- if (!DIFF_FILE_VALID (p -> one )) {
228- if (!DIFF_FILE_VALID (p -> two ))
229- continue ; /* ignore unmerged */
230- /* created */
231- if (contains (p -> two , needle , len , regexp , kws ))
232- has_changes ++ ;
233- }
234- else if (!DIFF_FILE_VALID (p -> two )) {
235- if (contains (p -> one , needle , len , regexp , kws ))
236- has_changes ++ ;
237- }
238- else if (!diff_unmodified_pair (p ) &&
239- contains (p -> one , needle , len , regexp , kws ) !=
240- contains (p -> two , needle , len , regexp , kws ))
241- has_changes ++ ;
242- }
243- if (has_changes )
244- return ; /* not munge the queue */
245-
246- /* otherwise we will clear the whole queue
247- * by copying the empty outq at the end of this
248- * function, but first clear the current entries
249- * in the queue.
250- */
251- for (i = 0 ; i < q -> nr ; i ++ )
252- diff_free_filepair (q -> queue [i ]);
253- }
254- else
255- /* Showing only the filepairs that has the needle */
256- for (i = 0 ; i < q -> nr ; i ++ ) {
257- struct diff_filepair * p = q -> queue [i ];
258- has_changes = 0 ;
259- if (!DIFF_FILE_VALID (p -> one )) {
260- if (!DIFF_FILE_VALID (p -> two ))
261- ; /* ignore unmerged */
262- /* created */
263- else if (contains (p -> two , needle , len , regexp ,
264- kws ))
265- has_changes = 1 ;
266- }
267- else if (!DIFF_FILE_VALID (p -> two )) {
268- if (contains (p -> one , needle , len , regexp , kws ))
269- has_changes = 1 ;
270- }
271- else if (!diff_unmodified_pair (p ) &&
272- contains (p -> one , needle , len , regexp , kws ) !=
273- contains (p -> two , needle , len , regexp , kws ))
274- has_changes = 1 ;
275-
276- if (has_changes )
277- diff_q (& outq , p );
278- else
279- diff_free_filepair (p );
280- }
245+ pickaxe (& diff_queued_diff , o , regexp , kws , has_changes );
281246
282247 if (opts & DIFF_PICKAXE_REGEX )
283248 regfree (& regex );
284249 else
285250 kwsfree (kws );
286-
287- free (q -> queue );
288- * q = outq ;
289251 return ;
290252}
291253
0 commit comments