2
#include "grep.h"
3
#include "userdiff.h"
4
#include "xdiff-interface.h"
5
+#include "diff.h"
6
+#include "diffcore.h"
7
8
static int grep_source_load(struct grep_source *gs);
9
static int grep_source_is_binary(struct grep_source *gs);
1324
fwrite(buf, size, 1, stdout);
1325
}
1326
1327
+static int fill_textconv_grep(struct userdiff_driver *driver,
1328
+ struct grep_source *gs)
1329
+{
1330
+ struct diff_filespec *df;
1331
+ char *buf;
1332
+ size_t size;
1333
+
1334
+ if (!driver || !driver->textconv)
1335
+ return grep_source_load(gs);
1336
+
1337
+ /*
1338
+ * The textconv interface is intimately tied to diff_filespecs, so we
1339
+ * have to pretend to be one. If we could unify the grep_source
1340
+ * and diff_filespec structs, this mess could just go away.
1341
+ */
1342
+ df = alloc_filespec(gs->path);
1343
+ switch (gs->type) {
1344
+ case GREP_SOURCE_SHA1:
1345
+ fill_filespec(df, gs->identifier, 1, 0100644);
1346
+ break;
1347
+ case GREP_SOURCE_FILE:
1348
+ fill_filespec(df, null_sha1, 0, 0100644);
1349
+ break;
1350
+ default:
1351
+ die("BUG: attempt to textconv something without a path?");
1352
+ }
1353
+
1354
+ /*
1355
+ * fill_textconv is not remotely thread-safe; it may load objects
1356
+ * behind the scenes, and it modifies the global diff tempfile
1357
+ * structure.
1358
+ */
1359
+ grep_read_lock();
1360
+ size = fill_textconv(driver, df, &buf);
1361
+ grep_read_unlock();
1362
+ free_filespec(df);
1363
+
1364
+ /*
1365
+ * The normal fill_textconv usage by the diff machinery would just keep
1366
+ * the textconv'd buf separate from the diff_filespec. But much of the
1367
+ * grep code passes around a grep_source and assumes that its "buf"
1368
+ * pointer is the beginning of the thing we are searching. So let's
1369
+ * install our textconv'd version into the grep_source, taking care not
1370
+ * to leak any existing buffer.
1371
+ */
1372
+ grep_source_clear_data(gs);
1373
+ gs->buf = buf;
1374
+ gs->size = size;
1375
+
1376
+ return 0;
1377
+}
1378
+
1379
static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int collect_hits)
1380
{
1381
char *bol;
1386
unsigned count = 0;
1387
int try_lookahead = 0;
1388
int show_function = 0;
1389
+ struct userdiff_driver *textconv = NULL;
1390
enum grep_context ctx = GREP_CONTEXT_HEAD;
1391
xdemitconf_t xecfg;
1392
1408
}
1409
opt->last_shown = 0;
1410
1356
- switch (opt->binary) {
1357
- case GREP_BINARY_DEFAULT:
1358
- if (grep_source_is_binary(gs))
1359
- binary_match_only = 1;
1360
- break;
1361
- case GREP_BINARY_NOMATCH:
1362
- if (grep_source_is_binary(gs))
1363
- return 0; /* Assume unmatch */
1364
- break;
1365
- case GREP_BINARY_TEXT:
1366
- break;
1367
- default:
1368
- die("bug: unknown binary handling mode");
1411
+ if (opt->allow_textconv) {
1412
+ grep_source_load_driver(gs);
1413
+ /*
1414
+ * We might set up the shared textconv cache data here, which
1415
+ * is not thread-safe.
1416
+ */
1417
+ grep_attr_lock();
1418
+ textconv = userdiff_get_textconv(gs->driver);
1419
+ grep_attr_unlock();
1420
+ }
1421
+
1422
+ /*
1423
+ * We know the result of a textconv is text, so we only have to care
1424
+ * about binary handling if we are not using it.
1425
+ */
1426
+ if (!textconv) {
1427
+ switch (opt->binary) {
1428
+ case GREP_BINARY_DEFAULT:
1429
+ if (grep_source_is_binary(gs))
1430
+ binary_match_only = 1;
1431
+ break;
1432
+ case GREP_BINARY_NOMATCH:
1433
+ if (grep_source_is_binary(gs))
1434
+ return 0; /* Assume unmatch */
1435
+ break;
1436
+ case GREP_BINARY_TEXT:
1437
+ break;
1438
+ default:
1439
+ die("bug: unknown binary handling mode");
1440
+ }
1441
}
1442
1443
memset(&xecfg, 0, sizeof(xecfg));
1445
1446
try_lookahead = should_lookahead(opt);
1447
1376
- if (grep_source_load(gs) < 0)
1448
+ if (fill_textconv_grep(textconv, gs) < 0)
1449
return 0;
1450
1451
bol = gs->buf;