| 1497 | } |
| 1498 | |
| 1499 | static int fill_textconv_grep(struct repository *r, |
| 1500 | struct userdiff_driver *driver, |
| 1501 | struct grep_source *gs) |
| 1502 | { |
| 1503 | struct diff_filespec *df; |
| 1504 | char *buf; |
| 1505 | size_t size; |
| 1506 | |
| 1507 | if (!driver || !driver->textconv) |
| 1508 | return grep_source_load(gs); |
| 1509 | |
| 1510 | /* |
| 1511 | * The textconv interface is intimately tied to diff_filespecs, so we |
| 1512 | * have to pretend to be one. If we could unify the grep_source |
| 1513 | * and diff_filespec structs, this mess could just go away. |
| 1514 | */ |
| 1515 | df = alloc_filespec(gs->path); |
| 1516 | switch (gs->type) { |
| 1517 | case GREP_SOURCE_OID: |
| 1518 | fill_filespec(df, gs->identifier, 1, 0100644); |
| 1519 | break; |
| 1520 | case GREP_SOURCE_FILE: |
| 1521 | fill_filespec(df, null_oid(r->hash_algo), 0, 0100644); |
| 1522 | break; |
| 1523 | default: |
| 1524 | BUG("attempt to textconv something without a path?"); |
| 1525 | } |
| 1526 | |
| 1527 | /* |
| 1528 | * fill_textconv is not remotely thread-safe; it modifies the global |
| 1529 | * diff tempfile structure, writes to the_repo's odb and might |
| 1530 | * internally call thread-unsafe functions such as the |
| 1531 | * prepare_packed_git() lazy-initializator. Because of the last two, we |
| 1532 | * must ensure mutual exclusion between this call and the object reading |
| 1533 | * API, thus we use obj_read_lock() here. |
| 1534 | * |
| 1535 | * TODO: allowing text conversion to run in parallel with object |
| 1536 | * reading operations might increase performance in the multithreaded |
| 1537 | * non-worktreee git-grep with --textconv. |
| 1538 | */ |
| 1539 | obj_read_lock(); |
| 1540 | size = fill_textconv(r, driver, df, &buf); |
| 1541 | obj_read_unlock(); |
| 1542 | free_filespec(df); |
| 1543 | |
| 1544 | /* |
| 1545 | * The normal fill_textconv usage by the diff machinery would just keep |
| 1546 | * the textconv'd buf separate from the diff_filespec. But much of the |
| 1547 | * grep code passes around a grep_source and assumes that its "buf" |
| 1548 | * pointer is the beginning of the thing we are searching. So let's |
| 1549 | * install our textconv'd version into the grep_source, taking care not |
| 1550 | * to leak any existing buffer. |
| 1551 | */ |
| 1552 | grep_source_clear_data(gs); |
| 1553 | gs->buf = buf; |
| 1554 | gs->size = size; |
| 1555 | |
| 1556 | return 0; |
no test coverage detected