| 1 | #ifndef DIFF_HUNKS_H |
| 2 | #define DIFF_HUNKS_H |
| 3 | |
| 4 | #include "hash.h" |
| 5 | #include "xdiff-interface.h" /* xdl_emit_hunk_consume_func_t */ |
| 6 | |
| 7 | struct object_id; |
| 8 | struct repository; |
| 9 | struct object_database; |
| 10 | |
| 11 | /* |
| 12 | * A persistent store of precomputed diff hunk coordinates, at |
| 13 | * .git/objects/info/diff-hunks. Entries are keyed by the two blobs diffed |
| 14 | * and the xdl_opts they were diffed under, so a cached result is valid |
| 15 | * in any context that key recurs in, independent of path. The xdl_opts |
| 16 | * key component mirrors the (always non-negative) diff_options field it |
| 17 | * projects from, and is serialized and compared as a 4-byte big-endian |
| 18 | * integer. |
| 19 | * |
| 20 | * The hunks a pair produces are not unique. They vary with the xdiff |
| 21 | * algorithm and ignore flags (xdl_opts, part of the key), and with |
| 22 | * whether the diff was trimmed: a zero-context diff runs |
| 23 | * trim_common_tail, which can pick a different but equally valid set of |
| 24 | * hunks than an untrimmed diff. The store holds one entry per key, so a |
| 25 | * pair is recorded only when its trimmed and untrimmed diffs are |
| 26 | * identical (the recording caller checks); such an entry serves a |
| 27 | * consumer at any context. The rare pair where the two diffs differ is |
| 28 | * never recorded and is always computed. |
| 29 | * |
| 30 | * The store is a cache: ordinary commands read it and fall back to |
| 31 | * computing the diff when it is absent, stale, or corrupt. It is filled |
| 32 | * as a side effect of diff and log runs, but only when writing is |
| 33 | * enabled (such a write-enabled run is a warming run); writing is off |
| 34 | * by default, so an ordinary command reads the store without recording |
| 35 | * into it. |
| 36 | */ |
| 37 | |
| 38 | /* |
| 39 | * A hunk's coordinates. The type is long to match the xdiff emit |
| 40 | * callback; the values are a diff's line numbers and counts, always |
| 41 | * within the int32 range the on-disk format stores (see |
| 42 | * diff_hunks_writer_add()). |
| 43 | */ |
| 44 | struct precomputed_hunk { |
| 45 | long old_start; |
| 46 | long old_count; |
| 47 | long new_start; |
| 48 | long new_count; |
| 49 | }; |
| 50 | |
| 51 | /* |
| 52 | * The repository's store, loaded once on first use and cached on the |
| 53 | * object database. Returns NULL when reading is disabled |
| 54 | * (core.diffHunks=false), the store is absent, or it fails to parse |
| 55 | * (wrong signature, version, or object hash, or a corrupt structure). |
| 56 | * The lookup functions below accept a NULL store and treat it as |
| 57 | * empty (every lookup misses), so callers need not check for NULL. |
| 58 | * The object database owns the store; callers must not free it. |
| 59 | */ |
| 60 | struct diff_hunks_store *repo_diff_hunks_store(struct repository *r); |
| 61 | |
| 62 | /* Free the repository's cached store, at object-database teardown. */ |
| 63 | void close_diff_hunks_store(struct object_database *o); |
| 64 | |
| 65 | /* |
| 66 | * Consultation counters for the repository's store: pairs the store |
| 67 | * served (hits) and pairs it was consulted for but could not serve |
| 68 | * (misses). Both zero when reading is disabled or no store exists. |
| 69 | */ |
| 70 | void diff_hunks_read_stats(struct repository *r, |
| 71 | unsigned long *hits, unsigned long *misses); |
| 72 | |
| 73 | /* |
| 74 | * Replay the recorded hunks of an (old blob, new blob) pair diffed |
| 75 | * under xdl_opts through hunk_func. The sequence is validated before |
| 76 | * any callback runs: on a hit (return 1) every hunk is emitted, on a |
| 77 | * miss (return 0: absent pair, xdl_opts mismatch, or an entry that |
| 78 | * fails validation) nothing is emitted, so a caller may accumulate |
| 79 | * directly into its result. |
| 80 | */ |
| 81 | int diff_hunks_replay(struct diff_hunks_store *s, |
| 82 | const struct object_id *old_oid, |
| 83 | const struct object_id *new_oid, |
| 84 | int xdl_opts, |
| 85 | xdl_emit_hunk_consume_func_t hunk_func, void *cb_data); |
| 86 | |
| 87 | /* |
| 88 | * A warming run's writer: it accumulates the hunks it computes in memory |
| 89 | * and flushes them to the store in one pass at finish. |
| 90 | */ |
| 91 | struct diff_hunks_writer; |
| 92 | |
| 93 | /* |
| 94 | * Return a writer for a warming run, or NULL when writing is disabled |
| 95 | * (the default). diff_hunks_writer_add() tolerates a NULL writer, so a |
| 96 | * caller may attach the result unconditionally. Pair with |
| 97 | * diff_hunks_writer_finish(). |
| 98 | */ |
| 99 | struct diff_hunks_writer *diff_hunks_writer_maybe_new(struct repository *r); |
| 100 | |
| 101 | /* |
| 102 | * Record a blob pair's hunks as computed under xdl_opts; a later lookup |
| 103 | * with a matching key is served these hunks. The caller must have |
| 104 | * checked that the pair's trimmed and untrimmed diffs are identical |
| 105 | * (see the top of this file), so the entry answers at any context; |
| 106 | * diff_hunks_writer_record_stable() below performs that check. |
| 107 | * NULL-safe. Returns 1 when the entry was recorded, 0 when the writer |
| 108 | * refused it (no hunks, a null object id, or values the on-disk |
| 109 | * 32-bit fields cannot hold). |
| 110 | */ |
| 111 | int diff_hunks_writer_add(struct diff_hunks_writer *w, |
| 112 | const struct object_id *old_oid, |
| 113 | const struct object_id *new_oid, |
| 114 | int xdl_opts, |
| 115 | const struct precomputed_hunk *hunks, |
| 116 | size_t nr_hunks); |
| 117 | |
| 118 | /* |
| 119 | * Record the pair only if it is trim-stable: the recording caller |
| 120 | * hands over both the trimmed (xdi_diff) and untrimmed (xdl_diff) |
| 121 | * zero-context hunk sequences it computed, and the entry is added |
| 122 | * only when the two are identical. NULL-safe. |
| 123 | */ |
| 124 | void diff_hunks_writer_record_stable(struct diff_hunks_writer *w, |
| 125 | const struct object_id *old_oid, |
| 126 | const struct object_id *new_oid, |
| 127 | int xdl_opts, |
| 128 | const struct precomputed_hunk *trimmed, |
| 129 | size_t nr_trimmed, |
| 130 | const struct precomputed_hunk *full, |
| 131 | size_t nr_full); |
| 132 | |
| 133 | /* Flush the accumulated entries to the store and free the writer. NULL-safe. */ |
| 134 | void diff_hunks_writer_finish(struct diff_hunks_writer *w); |
| 135 | |
| 136 | /* Remove the store file. Returns 0 (incl. absent) or -1. */ |
| 137 | int diff_hunks_clear(struct repository *r); |
| 138 | /* Validate the store. Returns 0 if valid/absent, -1 if corrupt. */ |
| 139 | int diff_hunks_verify(struct repository *r); |
| 140 | |
| 141 | #endif /* DIFF_HUNKS_H */ |