Skip to content

Commit ef90ab6

Browse files
committed
pickaxe: use textconv for -S counting
We currently just look at raw blob data when using "-S" to pickaxe. This is mostly historical, as pickaxe predates the textconv feature. If the user has bothered to define a textconv filter, it is more likely that their search string will be on the textconv output, as that is what they will see in the diff (and we do not even provide a mechanism for them to search for binary needles that contain NUL characters). This patch teaches "-S" to use textconv, just as we already do for "-G". Signed-off-by: Jeff King <[email protected]>
1 parent 8fa4b09 commit ef90ab6

File tree

2 files changed

+51
-17
lines changed

2 files changed

+51
-17
lines changed

diffcore-pickaxe.c

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,15 @@ static void diffcore_pickaxe_grep(struct diff_options *o)
157157
return;
158158
}
159159

160-
static unsigned int contains(struct diff_filespec *one, struct diff_options *o,
160+
static unsigned int contains(mmfile_t *mf, struct diff_options *o,
161161
regex_t *regexp, kwset_t kws)
162162
{
163163
unsigned int cnt;
164164
unsigned long sz;
165165
const char *data;
166-
if (diff_populate_filespec(one, 0))
167-
return 0;
168166

169-
sz = one->size;
170-
data = one->data;
167+
sz = mf->size;
168+
data = mf->ptr;
171169
cnt = 0;
172170

173171
if (regexp) {
@@ -197,29 +195,53 @@ static unsigned int contains(struct diff_filespec *one, struct diff_options *o,
197195
cnt++;
198196
}
199197
}
200-
diff_free_filespec_data(one);
201198
return cnt;
202199
}
203200

204201
static int has_changes(struct diff_filepair *p, struct diff_options *o,
205202
regex_t *regexp, kwset_t kws)
206203
{
204+
struct userdiff_driver *textconv_one = get_textconv(p->one);
205+
struct userdiff_driver *textconv_two = get_textconv(p->two);
206+
mmfile_t mf1, mf2;
207+
int ret;
208+
207209
if (!o->pickaxe[0])
208210
return 0;
209211

210-
if (!DIFF_FILE_VALID(p->one)) {
211-
if (!DIFF_FILE_VALID(p->two))
212-
return 0; /* ignore unmerged */
212+
/*
213+
* If we have an unmodified pair, we know that the count will be the
214+
* same and don't even have to load the blobs. Unless textconv is in
215+
* play, _and_ we are using two different textconv filters (e.g.,
216+
* because a pair is an exact rename with different textconv attributes
217+
* for each side, which might generate different content).
218+
*/
219+
if (textconv_one == textconv_two && diff_unmodified_pair(p))
220+
return 0;
221+
222+
fill_one(p->one, &mf1, &textconv_one);
223+
fill_one(p->two, &mf2, &textconv_two);
224+
225+
if (!mf1.ptr) {
226+
if (!mf2.ptr)
227+
ret = 0; /* ignore unmerged */
213228
/* created */
214-
return contains(p->two, o, regexp, kws) != 0;
215-
}
216-
if (!DIFF_FILE_VALID(p->two))
217-
return contains(p->one, o, regexp, kws) != 0;
218-
if (!diff_unmodified_pair(p)) {
219-
return contains(p->one, o, regexp, kws) !=
220-
contains(p->two, o, regexp, kws);
229+
ret = contains(&mf2, o, regexp, kws) != 0;
221230
}
222-
return 0;
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);
236+
237+
if (textconv_one)
238+
free(mf1.ptr);
239+
if (textconv_two)
240+
free(mf2.ptr);
241+
diff_free_filespec_data(p->one);
242+
diff_free_filespec_data(p->two);
243+
244+
return ret;
223245
}
224246

225247
static void diffcore_pickaxe_count(struct diff_options *o)

t/t4030-diff-textconv.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ test_expect_success 'grep-diff (-G) operates on textconv data (modification)' '
9696
test_cmp expect actual
9797
'
9898

99+
test_expect_success 'pickaxe (-S) operates on textconv data (add)' '
100+
echo one >expect &&
101+
git log --root --format=%s -S0 >actual &&
102+
test_cmp expect actual
103+
'
104+
105+
test_expect_success 'pickaxe (-S) operates on textconv data (modification)' '
106+
echo two >expect &&
107+
git log --root --format=%s -S1 >actual &&
108+
test_cmp expect actual
109+
'
110+
99111
cat >expect.stat <<'EOF'
100112
file | Bin 2 -> 4 bytes
101113
1 file changed, 0 insertions(+), 0 deletions(-)

0 commit comments

Comments
 (0)