142 lines
5.5 KiB
C
142 lines
5.5 KiB
C
#ifndef DIFF_HUNKS_H
|
|
#define DIFF_HUNKS_H
|
|
|
|
#include "hash.h"
|
|
#include "xdiff-interface.h" /* xdl_emit_hunk_consume_func_t */
|
|
|
|
struct object_id;
|
|
struct repository;
|
|
struct object_database;
|
|
|
|
/*
|
|
* A persistent store of precomputed diff hunk coordinates, at
|
|
* .git/objects/info/diff-hunks. Entries are keyed by the two blobs diffed
|
|
* and the xdl_opts they were diffed under, so a cached result is valid
|
|
* in any context that key recurs in, independent of path. The xdl_opts
|
|
* key component mirrors the (always non-negative) diff_options field it
|
|
* projects from, and is serialized and compared as a 4-byte big-endian
|
|
* integer.
|
|
*
|
|
* The hunks a pair produces are not unique. They vary with the xdiff
|
|
* algorithm and ignore flags (xdl_opts, part of the key), and with
|
|
* whether the diff was trimmed: a zero-context diff runs
|
|
* trim_common_tail, which can pick a different but equally valid set of
|
|
* hunks than an untrimmed diff. The store holds one entry per key, so a
|
|
* pair is recorded only when its trimmed and untrimmed diffs are
|
|
* identical (the recording caller checks); such an entry serves a
|
|
* consumer at any context. The rare pair where the two diffs differ is
|
|
* never recorded and is always computed.
|
|
*
|
|
* The store is a cache: ordinary commands read it and fall back to
|
|
* computing the diff when it is absent, stale, or corrupt. It is filled
|
|
* as a side effect of diff and log runs, but only when writing is
|
|
* enabled (such a write-enabled run is a warming run); writing is off
|
|
* by default, so an ordinary command reads the store without recording
|
|
* into it.
|
|
*/
|
|
|
|
/*
|
|
* A hunk's coordinates. The type is long to match the xdiff emit
|
|
* callback; the values are a diff's line numbers and counts, always
|
|
* within the int32 range the on-disk format stores (see
|
|
* diff_hunks_writer_add()).
|
|
*/
|
|
struct precomputed_hunk {
|
|
long old_start;
|
|
long old_count;
|
|
long new_start;
|
|
long new_count;
|
|
};
|
|
|
|
/*
|
|
* The repository's store, loaded once on first use and cached on the
|
|
* object database. Returns NULL when reading is disabled
|
|
* (core.diffHunks=false), the store is absent, or it fails to parse
|
|
* (wrong signature, version, or object hash, or a corrupt structure).
|
|
* The lookup functions below accept a NULL store and treat it as
|
|
* empty (every lookup misses), so callers need not check for NULL.
|
|
* The object database owns the store; callers must not free it.
|
|
*/
|
|
struct diff_hunks_store *repo_diff_hunks_store(struct repository *r);
|
|
|
|
/* Free the repository's cached store, at object-database teardown. */
|
|
void close_diff_hunks_store(struct object_database *o);
|
|
|
|
/*
|
|
* Consultation counters for the repository's store: pairs the store
|
|
* served (hits) and pairs it was consulted for but could not serve
|
|
* (misses). Both zero when reading is disabled or no store exists.
|
|
*/
|
|
void diff_hunks_read_stats(struct repository *r,
|
|
unsigned long *hits, unsigned long *misses);
|
|
|
|
/*
|
|
* Replay the recorded hunks of an (old blob, new blob) pair diffed
|
|
* under xdl_opts through hunk_func. The sequence is validated before
|
|
* any callback runs: on a hit (return 1) every hunk is emitted, on a
|
|
* miss (return 0: absent pair, xdl_opts mismatch, or an entry that
|
|
* fails validation) nothing is emitted, so a caller may accumulate
|
|
* directly into its result.
|
|
*/
|
|
int diff_hunks_replay(struct diff_hunks_store *s,
|
|
const struct object_id *old_oid,
|
|
const struct object_id *new_oid,
|
|
int xdl_opts,
|
|
xdl_emit_hunk_consume_func_t hunk_func, void *cb_data);
|
|
|
|
/*
|
|
* A warming run's writer: it accumulates the hunks it computes in memory
|
|
* and flushes them to the store in one pass at finish.
|
|
*/
|
|
struct diff_hunks_writer;
|
|
|
|
/*
|
|
* Return a writer for a warming run, or NULL when writing is disabled
|
|
* (the default). diff_hunks_writer_add() tolerates a NULL writer, so a
|
|
* caller may attach the result unconditionally. Pair with
|
|
* diff_hunks_writer_finish().
|
|
*/
|
|
struct diff_hunks_writer *diff_hunks_writer_maybe_new(struct repository *r);
|
|
|
|
/*
|
|
* Record a blob pair's hunks as computed under xdl_opts; a later lookup
|
|
* with a matching key is served these hunks. The caller must have
|
|
* checked that the pair's trimmed and untrimmed diffs are identical
|
|
* (see the top of this file), so the entry answers at any context;
|
|
* diff_hunks_writer_record_stable() below performs that check.
|
|
* NULL-safe. Returns 1 when the entry was recorded, 0 when the writer
|
|
* refused it (no hunks, a null object id, or values the on-disk
|
|
* 32-bit fields cannot hold).
|
|
*/
|
|
int diff_hunks_writer_add(struct diff_hunks_writer *w,
|
|
const struct object_id *old_oid,
|
|
const struct object_id *new_oid,
|
|
int xdl_opts,
|
|
const struct precomputed_hunk *hunks,
|
|
size_t nr_hunks);
|
|
|
|
/*
|
|
* Record the pair only if it is trim-stable: the recording caller
|
|
* hands over both the trimmed (xdi_diff) and untrimmed (xdl_diff)
|
|
* zero-context hunk sequences it computed, and the entry is added
|
|
* only when the two are identical. NULL-safe.
|
|
*/
|
|
void diff_hunks_writer_record_stable(struct diff_hunks_writer *w,
|
|
const struct object_id *old_oid,
|
|
const struct object_id *new_oid,
|
|
int xdl_opts,
|
|
const struct precomputed_hunk *trimmed,
|
|
size_t nr_trimmed,
|
|
const struct precomputed_hunk *full,
|
|
size_t nr_full);
|
|
|
|
/* Flush the accumulated entries to the store and free the writer. NULL-safe. */
|
|
void diff_hunks_writer_finish(struct diff_hunks_writer *w);
|
|
|
|
/* Remove the store file. Returns 0 (incl. absent) or -1. */
|
|
int diff_hunks_clear(struct repository *r);
|
|
/* Validate the store. Returns 0 if valid/absent, -1 if corrupt. */
|
|
int diff_hunks_verify(struct repository *r);
|
|
|
|
#endif /* DIFF_HUNKS_H */
|