160 lines
6.5 KiB
C
160 lines
6.5 KiB
C
#ifndef DIFF_PROVIDER_H
|
|
#define DIFF_PROVIDER_H
|
|
|
|
#include "xdiff-interface.h"
|
|
|
|
/*
|
|
* The hunk provider interface sits between naming a pair of file
|
|
* versions to diff and computing their changed line ranges.
|
|
* Consumers that operate on hunk coordinates route their diff
|
|
* through here, so that a provider can answer for the pair before
|
|
* its content is loaded.
|
|
*
|
|
* A hunk provider answers a consumer's request from the pair's
|
|
* identity, its blob object ids and the settings that determine the
|
|
* diff, before any content is loaded; a request no provider answers
|
|
* falls through to the consumer's own computation. Two providers implement this
|
|
* interface with different authority. The diff-hunks store
|
|
* (diff-hunks.h) is in-process and not authoritative: it may only
|
|
* reproduce the builtin result, so it never asserts a pair
|
|
* equivalent, and it stands aside wherever a process outranks it. A
|
|
* process configured in diff.<driver>.process (diff-process.c) is
|
|
* authoritative for its paths: its answer may deliberately differ
|
|
* from the builtin diff, including asserting a pair equivalent. The
|
|
* interface resolves that authority through a provider chain owned
|
|
* by the repository, built on first consultation and released by
|
|
* repo_clear(): chain order is the resolution, and the builtin
|
|
* computation itself is the chain's terminal provider. A consumer
|
|
* never names a provider; it reads the outcome below. Every answer a
|
|
* provider serves from identity passes the shared coordinate check
|
|
* (diff-provider-internal.h) before any consumer sees it.
|
|
*/
|
|
|
|
struct diff_options;
|
|
struct object_id;
|
|
struct repository;
|
|
|
|
/*
|
|
* The result of a consultation: two dependent axes flattened into
|
|
* their four valid points. The first axis is the state of the
|
|
* response: the pair was answered, no provider answered, or (from
|
|
* diff_provider_emit_hunks() alone) the attempt failed. The second
|
|
* axis exists only in the unanswered state: whether what the caller
|
|
* computes for this request may be recorded, the one rule the
|
|
* interface imposes on an otherwise free caller. The rule travels
|
|
* in the outcome because the knowledge is a provider's while the
|
|
* recording is the caller's, and it shares the enum with the state,
|
|
* rather than riding a separate flag, so that no meaningless
|
|
* combination is representable and -Wswitch forces every consumer
|
|
* that switches to place the no-record arm.
|
|
*
|
|
* These values describe consultations, not providers: the set does
|
|
* not grow when a provider is added; a new provider maps onto these
|
|
* values inside the interface, so consumer code is written once.
|
|
* Each entry point returns a subrange of the set (stated at its
|
|
* declaration); a switch over this enum should list every value and
|
|
* omit "default:" so -Wswitch keeps it exhaustive, and a caller for
|
|
* whom only one value is actionable may compare against that value
|
|
* alone.
|
|
*/
|
|
enum diff_provider_outcome {
|
|
/*
|
|
* Loading or diffing the pair failed. Returned only by
|
|
* diff_provider_emit_hunks(), whose compute leg is the only
|
|
* part of a consultation that can fail.
|
|
*/
|
|
DIFF_PROVIDER_ERROR = -1,
|
|
|
|
/*
|
|
* The request is answered: every hunk of the pair has been
|
|
* emitted through the callback. An authoritative provider
|
|
* that finds the pair equivalent answers with no hunks at
|
|
* all, so a callback that never fired is an answer, not an
|
|
* accident.
|
|
*/
|
|
DIFF_PROVIDER_ANSWERED = 0,
|
|
|
|
/*
|
|
* No provider answered. What happens next is the caller's
|
|
* business, typically computing the diff itself; a result it
|
|
* computes for this request may be recorded.
|
|
*/
|
|
DIFF_PROVIDER_UNANSWERED,
|
|
|
|
/*
|
|
* No provider answered, and what the caller computes for
|
|
* this request must not be recorded: either an authoritative
|
|
* provider owns the pair and declined this request, or the
|
|
* request is shaped by parameters outside the recording key,
|
|
* the key a recorded result is later served by.
|
|
*/
|
|
DIFF_PROVIDER_UNANSWERED_NO_RECORD,
|
|
};
|
|
|
|
/*
|
|
* A consultation request. The interface consults providers from
|
|
* these fields alone; no content is loaded before an answer.
|
|
*
|
|
* repo owns the provider chain the request walks. old_oid/new_oid
|
|
* name the blobs whose bytes are diffed; pass NULL for a side whose
|
|
* bytes are not a stored blob (a working-tree file, textconv output,
|
|
* a gitlink), so no provider answers from an id it cannot look up.
|
|
* path names the file the pair is diffed as; a provider selected by
|
|
* path applies only where it is set. diffopt carries the diff
|
|
* settings that live outside xpp; xpp carries the parameters the
|
|
* diff runs with. Each provider gates itself on the fields that
|
|
* concern it.
|
|
*/
|
|
struct diff_provider_request {
|
|
struct repository *repo;
|
|
const struct object_id *old_oid;
|
|
const struct object_id *new_oid;
|
|
const char *path;
|
|
struct diff_options *diffopt;
|
|
const xpparam_t *xpp;
|
|
};
|
|
|
|
/*
|
|
* Consult the providers for the request's pair without computing.
|
|
* On DIFF_PROVIDER_ANSWERED the hunks were emitted through hunk_cb
|
|
* (0-based emission coordinates, context 0) and were validated
|
|
* before the first callback ran, so a consumer may accumulate
|
|
* directly into its result. Never returns DIFF_PROVIDER_ERROR.
|
|
* The callback's return value is not consulted: emission of a
|
|
* validated answer has no error leg, so the callback must return 0.
|
|
*/
|
|
enum diff_provider_outcome
|
|
diff_provider_consult(const struct diff_provider_request *req,
|
|
xdl_emit_hunk_consume_func_t hunk_cb, void *cb_data);
|
|
|
|
/*
|
|
* Load the pair's content. Called at most once per request, only
|
|
* when the ranges are computed rather than provided. The buffers
|
|
* borrow storage owned by the callback's owner.
|
|
*/
|
|
typedef int (*diff_provider_fill_fn)(void *data, mmfile_t *old_file,
|
|
mmfile_t *new_file);
|
|
|
|
/*
|
|
* Consult the providers and, when no identity answer serves the
|
|
* request, load the pair's content through fill and compute its
|
|
* exact changed ranges (context 0). Emits to hunk_cb either way and
|
|
* returns DIFF_PROVIDER_ANSWERED, or DIFF_PROVIDER_ERROR when fill
|
|
* or the diff fails. The unanswered outcomes are never returned: a
|
|
* pair no provider answers is computed here instead of in the caller.
|
|
*/
|
|
enum diff_provider_outcome
|
|
diff_provider_emit_hunks(const struct diff_provider_request *req,
|
|
diff_provider_fill_fn fill, void *fill_data,
|
|
xdl_emit_hunk_consume_func_t hunk_cb,
|
|
void *cb_data);
|
|
|
|
/*
|
|
* Release the repository's provider chain: stop any provider-owned
|
|
* processes and free the providers. Called by repo_clear(); the
|
|
* chain builds again on the next consultation.
|
|
*/
|
|
void diff_providers_clear(struct repository *r);
|
|
|
|
#endif /* DIFF_PROVIDER_H */
|