Raw
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 */