11/*
22 * Copyright (C) 2005 Junio C Hamano
33 */
4+ #include <regex.h>
5+
46#include "cache.h"
57#include "diff.h"
68#include "diffcore.h"
79
810static unsigned int contains (struct diff_filespec * one ,
9- const char * needle , unsigned long len )
11+ const char * needle , unsigned long len ,
12+ regex_t * regexp )
1013{
1114 unsigned int cnt ;
1215 unsigned long offset , sz ;
@@ -18,15 +21,28 @@ static unsigned int contains(struct diff_filespec *one,
1821 data = one -> data ;
1922 cnt = 0 ;
2023
21- /* Yes, I've heard of strstr(), but the thing is *data may
22- * not be NUL terminated. Sue me.
23- */
24- for (offset = 0 ; offset + len <= sz ; offset ++ ) {
25- /* we count non-overlapping occurrences of needle */
26- if (!memcmp (needle , data + offset , len )) {
27- offset += len - 1 ;
24+ if (regexp ) {
25+ regmatch_t regmatch ;
26+ int flags = 0 ;
27+
28+ while (* data && !regexec (regexp , data , 1 , & regmatch , flags )) {
29+ flags |= REG_NOTBOL ;
30+ data += regmatch .rm_so ;
31+ if (* data ) data ++ ;
2832 cnt ++ ;
2933 }
34+
35+ } else { /* Classic exact string match */
36+ /* Yes, I've heard of strstr(), but the thing is *data may
37+ * not be NUL terminated. Sue me.
38+ */
39+ for (offset = 0 ; offset + len <= sz ; offset ++ ) {
40+ /* we count non-overlapping occurrences of needle */
41+ if (!memcmp (needle , data + offset , len )) {
42+ offset += len - 1 ;
43+ cnt ++ ;
44+ }
45+ }
3046 }
3147 return cnt ;
3248}
@@ -36,10 +52,24 @@ void diffcore_pickaxe(const char *needle, int opts)
3652 struct diff_queue_struct * q = & diff_queued_diff ;
3753 unsigned long len = strlen (needle );
3854 int i , has_changes ;
55+ regex_t regex , * regexp = NULL ;
3956 struct diff_queue_struct outq ;
4057 outq .queue = NULL ;
4158 outq .nr = outq .alloc = 0 ;
4259
60+ if (opts & DIFF_PICKAXE_REGEX ) {
61+ int err ;
62+ err = regcomp (& regex , needle , REG_EXTENDED | REG_NEWLINE );
63+ if (err ) {
64+ /* The POSIX.2 people are surely sick */
65+ char errbuf [1024 ];
66+ regerror (err , & regex , errbuf , 1024 );
67+ regfree (& regex );
68+ die ("invalid pickaxe regex: %s" , errbuf );
69+ }
70+ regexp = & regex ;
71+ }
72+
4373 if (opts & DIFF_PICKAXE_ALL ) {
4474 /* Showing the whole changeset if needle exists */
4575 for (i = has_changes = 0 ; !has_changes && i < q -> nr ; i ++ ) {
@@ -48,16 +78,16 @@ void diffcore_pickaxe(const char *needle, int opts)
4878 if (!DIFF_FILE_VALID (p -> two ))
4979 continue ; /* ignore unmerged */
5080 /* created */
51- if (contains (p -> two , needle , len ))
81+ if (contains (p -> two , needle , len , regexp ))
5282 has_changes ++ ;
5383 }
5484 else if (!DIFF_FILE_VALID (p -> two )) {
55- if (contains (p -> one , needle , len ))
85+ if (contains (p -> one , needle , len , regexp ))
5686 has_changes ++ ;
5787 }
5888 else if (!diff_unmodified_pair (p ) &&
59- contains (p -> one , needle , len ) !=
60- contains (p -> two , needle , len ))
89+ contains (p -> one , needle , len , regexp ) !=
90+ contains (p -> two , needle , len , regexp ))
6191 has_changes ++ ;
6292 }
6393 if (has_changes )
@@ -80,16 +110,16 @@ void diffcore_pickaxe(const char *needle, int opts)
80110 if (!DIFF_FILE_VALID (p -> two ))
81111 ; /* ignore unmerged */
82112 /* created */
83- else if (contains (p -> two , needle , len ))
113+ else if (contains (p -> two , needle , len , regexp ))
84114 has_changes = 1 ;
85115 }
86116 else if (!DIFF_FILE_VALID (p -> two )) {
87- if (contains (p -> one , needle , len ))
117+ if (contains (p -> one , needle , len , regexp ))
88118 has_changes = 1 ;
89119 }
90120 else if (!diff_unmodified_pair (p ) &&
91- contains (p -> one , needle , len ) !=
92- contains (p -> two , needle , len ))
121+ contains (p -> one , needle , len , regexp ) !=
122+ contains (p -> two , needle , len , regexp ))
93123 has_changes = 1 ;
94124
95125 if (has_changes )
@@ -98,6 +128,10 @@ void diffcore_pickaxe(const char *needle, int opts)
98128 diff_free_filepair (p );
99129 }
100130
131+ if (opts & DIFF_PICKAXE_REGEX ) {
132+ regfree (& regex );
133+ }
134+
101135 free (q -> queue );
102136 * q = outq ;
103137 return ;
0 commit comments