mirror of
https://github.com/git/git.git
synced 2026-02-28 10:47:33 +00:00
The previous commit introduced an ability to run multiple commands for hook events and next commit will introduce the ability to define hooks from configs, in addition to the "traditional" hooks from the hookdir. Introduce a new command "git hook list" to make inspecting hooks easier both for users and for the tests we will add. Further commits will expand on this, e.g. by adding a -z output mode. Signed-off-by: Emily Shaffer <emilyshaffer@google.com> Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
228 lines
6.6 KiB
C
228 lines
6.6 KiB
C
#ifndef HOOK_H
|
|
#define HOOK_H
|
|
#include "strvec.h"
|
|
#include "run-command.h"
|
|
#include "string-list.h"
|
|
|
|
struct repository;
|
|
|
|
/**
|
|
* Represents a hook command to be run.
|
|
* Hooks can be:
|
|
* 1. "traditional" (found in the hooks directory)
|
|
* 2. "configured" (defined in Git's configuration, not yet implemented).
|
|
* The 'kind' field determines which part of the union 'u' is valid.
|
|
*/
|
|
struct hook {
|
|
enum {
|
|
HOOK_TRADITIONAL,
|
|
} kind;
|
|
union {
|
|
struct {
|
|
const char *path;
|
|
} traditional;
|
|
} u;
|
|
|
|
/**
|
|
* Opaque data pointer used to keep internal state across callback calls.
|
|
*
|
|
* It can be accessed directly via the third hook callback arg:
|
|
* struct ... *state = pp_task_cb;
|
|
*
|
|
* The caller is responsible for managing the memory for this data by
|
|
* providing alloc/free callbacks to `run_hooks_opt`.
|
|
*
|
|
* Only useful when using `run_hooks_opt.feed_pipe`, otherwise ignore it.
|
|
*/
|
|
void *feed_pipe_cb_data;
|
|
};
|
|
|
|
typedef void (*cb_data_free_fn)(void *data);
|
|
typedef void *(*cb_data_alloc_fn)(void *init_ctx);
|
|
|
|
struct run_hooks_opt
|
|
{
|
|
/* Environment vars to be set for each hook */
|
|
struct strvec env;
|
|
|
|
/* Args to be passed to each hook */
|
|
struct strvec args;
|
|
|
|
/* Emit an error if the hook is missing */
|
|
unsigned int error_if_missing:1;
|
|
|
|
/**
|
|
* Number of processes to parallelize across.
|
|
*
|
|
* If > 1, output will be buffered and de-interleaved (ungroup=0).
|
|
* If == 1, output will be real-time (ungroup=1).
|
|
*/
|
|
unsigned int jobs;
|
|
|
|
/**
|
|
* An optional initial working directory for the hook,
|
|
* translates to "struct child_process"'s "dir" member.
|
|
*/
|
|
const char *dir;
|
|
|
|
/**
|
|
* A pointer which if provided will be set to 1 or 0 depending
|
|
* on if a hook was started, regardless of whether or not that
|
|
* was successful. I.e. if the underlying start_command() was
|
|
* successful this will be set to 1.
|
|
*
|
|
* Used for avoiding TOCTOU races in code that would otherwise
|
|
* call hook_exist() after a "maybe hook run" to see if a hook
|
|
* was invoked.
|
|
*/
|
|
int *invoked_hook;
|
|
|
|
/**
|
|
* Send the hook's stdout to stderr.
|
|
*
|
|
* This is the default behavior for all hooks except pre-push,
|
|
* which has separate stdout and stderr streams for backwards
|
|
* compatibility reasons.
|
|
*/
|
|
unsigned int stdout_to_stderr:1;
|
|
|
|
/**
|
|
* Path to file which should be piped to stdin for each hook.
|
|
*/
|
|
const char *path_to_stdin;
|
|
|
|
/**
|
|
* Callback used to incrementally feed a child hook stdin pipe.
|
|
*
|
|
* Useful especially if a hook consumes large quantities of data
|
|
* (e.g. a list of all refs in a client push), so feeding it via
|
|
* in-memory strings or slurping to/from files is inefficient.
|
|
* While the callback allows piecemeal writing, it can also be
|
|
* used for smaller inputs, where it gets called only once.
|
|
*
|
|
* Add hook callback initalization context to `feed_pipe_ctx`.
|
|
* Add hook callback internal state to `feed_pipe_cb_data`.
|
|
*
|
|
*/
|
|
feed_pipe_fn feed_pipe;
|
|
|
|
/**
|
|
* Opaque data pointer used to pass context to `feed_pipe_fn`.
|
|
*
|
|
* It can be accessed via the second callback arg 'pp_cb':
|
|
* ((struct hook_cb_data *) pp_cb)->hook_cb->options->feed_pipe_ctx;
|
|
*
|
|
* The caller is responsible for managing the memory for this data.
|
|
* Only useful when using `run_hooks_opt.feed_pipe`, otherwise ignore it.
|
|
*/
|
|
void *feed_pipe_ctx;
|
|
|
|
/**
|
|
* Some hooks need to create a fresh `feed_pipe_cb_data` internal state,
|
|
* so they can keep track of progress without affecting one another.
|
|
*
|
|
* If provided, this function will be called to alloc & initialize the
|
|
* `feed_pipe_cb_data` for each hook.
|
|
*
|
|
* The `feed_pipe_ctx` pointer can be used to pass initialization data.
|
|
*/
|
|
cb_data_alloc_fn feed_pipe_cb_data_alloc;
|
|
|
|
/**
|
|
* Called to free the memory initialized by `feed_pipe_cb_data_alloc`.
|
|
*
|
|
* Must always be provided when `feed_pipe_cb_data_alloc` is provided.
|
|
*/
|
|
cb_data_free_fn feed_pipe_cb_data_free;
|
|
};
|
|
|
|
#define RUN_HOOKS_OPT_INIT { \
|
|
.env = STRVEC_INIT, \
|
|
.args = STRVEC_INIT, \
|
|
.stdout_to_stderr = 1, \
|
|
.jobs = 1, \
|
|
}
|
|
|
|
struct hook_cb_data {
|
|
/* rc reflects the cumulative failure state */
|
|
int rc;
|
|
const char *hook_name;
|
|
|
|
/**
|
|
* A list of hook commands/paths to run for the 'hook_name' event.
|
|
*
|
|
* The 'string' member of each item holds the path (for traditional hooks)
|
|
* or the unique friendly-name for hooks specified in configs.
|
|
* The 'util' member of each item points to the corresponding struct hook.
|
|
*/
|
|
struct string_list *hook_command_list;
|
|
|
|
/* Iterator/cursor for the above list, pointing to the next hook to run. */
|
|
size_t hook_to_run_index;
|
|
|
|
struct run_hooks_opt *options;
|
|
};
|
|
|
|
/**
|
|
* Provides a list of hook commands to run for the 'hookname' event.
|
|
*
|
|
* This function consolidates hooks from two sources:
|
|
* 1. The config-based hooks (not yet implemented).
|
|
* 2. The "traditional" hook found in the repository hooks directory
|
|
* (e.g., .git/hooks/pre-commit).
|
|
*
|
|
* The list is ordered by execution priority.
|
|
*
|
|
* The caller is responsible for freeing the memory of the returned list
|
|
* using string_list_clear() and free().
|
|
*/
|
|
struct string_list *list_hooks(struct repository *r, const char *hookname,
|
|
struct run_hooks_opt *options);
|
|
|
|
/**
|
|
* Frees the memory allocated for the hook list, including the `struct hook`
|
|
* items and their internal state.
|
|
*/
|
|
void hook_list_clear(struct string_list *hooks, cb_data_free_fn cb_data_free);
|
|
|
|
/**
|
|
* Returns the path to the hook file, or NULL if the hook is missing
|
|
* or disabled. Note that this points to static storage that will be
|
|
* overwritten by further calls to find_hook and run_hook_*.
|
|
*/
|
|
const char *find_hook(struct repository *r, const char *name);
|
|
|
|
/**
|
|
* A boolean version of find_hook()
|
|
*/
|
|
int hook_exists(struct repository *r, const char *hookname);
|
|
|
|
/**
|
|
* Takes a `hook_name`, resolves it to a path with find_hook(), and
|
|
* runs the hook for you with the options specified in "struct
|
|
* run_hooks opt". Will free memory associated with the "struct run_hooks_opt".
|
|
*
|
|
* Returns the status code of the run hook, or a negative value on
|
|
* error().
|
|
*/
|
|
int run_hooks_opt(struct repository *r, const char *hook_name,
|
|
struct run_hooks_opt *options);
|
|
|
|
/**
|
|
* A wrapper for run_hooks_opt() which provides a dummy "struct
|
|
* run_hooks_opt" initialized with "RUN_HOOKS_OPT_INIT".
|
|
*/
|
|
int run_hooks(struct repository *r, const char *hook_name);
|
|
|
|
/**
|
|
* Like run_hooks(), a wrapper for run_hooks_opt().
|
|
*
|
|
* In addition to the wrapping behavior provided by run_hooks(), this
|
|
* wrapper takes a list of strings terminated by a NULL
|
|
* argument. These things will be used as positional arguments to the
|
|
* hook. This function behaves like the old run_hook_le() API.
|
|
*/
|
|
LAST_ARG_MUST_BE_NULL
|
|
int run_hooks_l(struct repository *r, const char *hook_name, ...);
|
|
#endif
|