| 1 | #ifndef HOOK_H |
| 2 | #define HOOK_H |
| 3 | #include "config.h" |
| 4 | #include "run-command.h" |
| 5 | #include "string-list.h" |
| 6 | #include "strmap.h" |
| 7 | #include "strvec.h" |
| 8 | |
| 9 | struct repository; |
| 10 | |
| 11 | typedef void (*hook_data_free_fn)(void *data); |
| 12 | typedef void *(*hook_data_alloc_fn)(void *init_ctx); |
| 13 | |
| 14 | /** |
| 15 | * Represents a hook command to be run. |
| 16 | * Hooks can be: |
| 17 | * 1. "traditional" (found in the hooks directory) |
| 18 | * 2. "configured" (defined in Git's configuration via hook.<friendly-name>.event). |
| 19 | * The 'kind' field determines which part of the union 'u' is valid. |
| 20 | */ |
| 21 | struct hook { |
| 22 | enum { |
| 23 | HOOK_TRADITIONAL, |
| 24 | HOOK_CONFIGURED, |
| 25 | } kind; |
| 26 | union { |
| 27 | struct { |
| 28 | const char *path; |
| 29 | } traditional; |
| 30 | struct { |
| 31 | const char *friendly_name; |
| 32 | const char *command; |
| 33 | enum config_scope scope; |
| 34 | bool disabled; |
| 35 | bool event_disabled; |
| 36 | } configured; |
| 37 | } u; |
| 38 | |
| 39 | /** |
| 40 | * Whether this hook may run in parallel with other hooks for the same |
| 41 | * event. Only useful for configured (named) hooks. Traditional hooks |
| 42 | * always default to 0 (serial). Set via `hook.<name>.parallel = true`. |
| 43 | */ |
| 44 | bool parallel; |
| 45 | |
| 46 | /** |
| 47 | * Opaque data pointer used to keep internal state across callback calls. |
| 48 | * |
| 49 | * It can be accessed directly via the third hook callback arg: |
| 50 | * struct ... *state = pp_task_cb; |
| 51 | * |
| 52 | * The caller is responsible for managing the memory for this data by |
| 53 | * providing alloc/free callbacks to `run_hooks_opt`. |
| 54 | * |
| 55 | * Only useful when using `run_hooks_opt.feed_pipe`, otherwise ignore it. |
| 56 | */ |
| 57 | void *feed_pipe_cb_data; |
| 58 | |
| 59 | /** |
| 60 | * Callback to free `feed_pipe_cb_data`. |
| 61 | * |
| 62 | * It is called automatically and points to the `feed_pipe_cb_data_free` |
| 63 | * provided via the `run_hook_opt` parameter. |
| 64 | */ |
| 65 | hook_data_free_fn data_free; |
| 66 | }; |
| 67 | |
| 68 | struct run_hooks_opt { |
| 69 | /* Environment vars to be set for each hook */ |
| 70 | struct strvec env; |
| 71 | |
| 72 | /* Args to be passed to each hook */ |
| 73 | struct strvec args; |
| 74 | |
| 75 | /* Emit an error if the hook is missing */ |
| 76 | unsigned int error_if_missing:1; |
| 77 | |
| 78 | /** |
| 79 | * Number of processes to parallelize across. |
| 80 | * |
| 81 | * If > 1, output will be buffered and de-interleaved (ungroup=0). |
| 82 | * If == 1, output will be real-time (ungroup=1). |
| 83 | * If == 0, the 'hook.jobs' config is used or, if the config is unset, |
| 84 | * defaults to 1 (serial execution). |
| 85 | */ |
| 86 | unsigned int jobs; |
| 87 | |
| 88 | /** |
| 89 | * An optional initial working directory for the hook, |
| 90 | * translates to "struct child_process"'s "dir" member. |
| 91 | */ |
| 92 | const char *dir; |
| 93 | |
| 94 | /** |
| 95 | * A pointer which if provided will be set to 1 or 0 depending |
| 96 | * on if a hook was started, regardless of whether or not that |
| 97 | * was successful. I.e. if the underlying start_command() was |
| 98 | * successful this will be set to 1. |
| 99 | * |
| 100 | * Used for avoiding TOCTOU races in code that would otherwise |
| 101 | * call hook_exist() after a "maybe hook run" to see if a hook |
| 102 | * was invoked. |
| 103 | */ |
| 104 | int *invoked_hook; |
| 105 | |
| 106 | /** |
| 107 | * Send the hook's stdout to stderr. |
| 108 | * |
| 109 | * This is the default behavior for all hooks except pre-push, |
| 110 | * which keeps stdout and stderr separate for backwards compatibility. |
| 111 | * When parallel execution is requested (jobs > 1), get_hook_jobs() |
| 112 | * overrides this to 1 for all hooks so run-command can de-interleave |
| 113 | * their outputs correctly. |
| 114 | */ |
| 115 | unsigned int stdout_to_stderr:1; |
| 116 | |
| 117 | /** |
| 118 | * Path to file which should be piped to stdin for each hook. |
| 119 | */ |
| 120 | const char *path_to_stdin; |
| 121 | |
| 122 | /** |
| 123 | * Callback used to incrementally feed a child hook stdin pipe. |
| 124 | * |
| 125 | * Useful especially if a hook consumes large quantities of data |
| 126 | * (e.g. a list of all refs in a client push), so feeding it via |
| 127 | * in-memory strings or slurping to/from files is inefficient. |
| 128 | * While the callback allows piecemeal writing, it can also be |
| 129 | * used for smaller inputs, where it gets called only once. |
| 130 | * |
| 131 | * Add hook callback initialization context to `feed_pipe_ctx`. |
| 132 | * Add hook callback internal state to `feed_pipe_cb_data`. |
| 133 | * |
| 134 | */ |
| 135 | feed_pipe_fn feed_pipe; |
| 136 | |
| 137 | /** |
| 138 | * Opaque data pointer used to pass context to `feed_pipe_fn`. |
| 139 | * |
| 140 | * It can be accessed via the second callback arg 'pp_cb': |
| 141 | * ((struct hook_cb_data *) pp_cb)->hook_cb->options->feed_pipe_ctx; |
| 142 | * |
| 143 | * The caller is responsible for managing the memory for this data. |
| 144 | * Only useful when using `run_hooks_opt.feed_pipe`, otherwise ignore it. |
| 145 | */ |
| 146 | void *feed_pipe_ctx; |
| 147 | |
| 148 | /** |
| 149 | * Some hooks need to create a fresh `feed_pipe_cb_data` internal state, |
| 150 | * so they can keep track of progress without affecting one another. |
| 151 | * |
| 152 | * If provided, this function will be called to alloc & initialize the |
| 153 | * `feed_pipe_cb_data` for each hook. |
| 154 | * |
| 155 | * The `feed_pipe_ctx` pointer can be used to pass initialization data. |
| 156 | */ |
| 157 | hook_data_alloc_fn feed_pipe_cb_data_alloc; |
| 158 | |
| 159 | /** |
| 160 | * Called to free the memory initialized by `feed_pipe_cb_data_alloc`. |
| 161 | * |
| 162 | * Must always be provided when `feed_pipe_cb_data_alloc` is provided. |
| 163 | */ |
| 164 | hook_data_free_fn feed_pipe_cb_data_free; |
| 165 | }; |
| 166 | |
| 167 | /** |
| 168 | * Default initializer for hooks. Parallelism is opt-in: .jobs = 0 defers to |
| 169 | * the 'hook.jobs' config, falling back to serial (1) if unset. |
| 170 | */ |
| 171 | #define RUN_HOOKS_OPT_INIT { \ |
| 172 | .env = STRVEC_INIT, \ |
| 173 | .args = STRVEC_INIT, \ |
| 174 | .stdout_to_stderr = 1, \ |
| 175 | .jobs = 0, \ |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Initializer for hooks that must always run sequentially regardless of |
| 180 | * 'hook.jobs'. Use this when git knows the hook cannot safely be parallelized |
| 181 | * .jobs = 1 is non-overridable. |
| 182 | */ |
| 183 | #define RUN_HOOKS_OPT_INIT_FORCE_SERIAL { \ |
| 184 | .env = STRVEC_INIT, \ |
| 185 | .args = STRVEC_INIT, \ |
| 186 | .stdout_to_stderr = 1, \ |
| 187 | .jobs = 1, \ |
| 188 | } |
| 189 | |
| 190 | struct hook_cb_data { |
| 191 | /* rc reflects the cumulative failure state */ |
| 192 | int rc; |
| 193 | const char *hook_name; |
| 194 | |
| 195 | /** |
| 196 | * A list of hook commands/paths to run for the 'hook_name' event. |
| 197 | * |
| 198 | * The 'string' member of each item holds the path (for traditional hooks) |
| 199 | * or the unique friendly-name for hooks specified in configs. |
| 200 | * The 'util' member of each item points to the corresponding struct hook. |
| 201 | */ |
| 202 | struct string_list *hook_command_list; |
| 203 | |
| 204 | /* Iterator/cursor for the above list, pointing to the next hook to run. */ |
| 205 | size_t hook_to_run_index; |
| 206 | |
| 207 | struct run_hooks_opt *options; |
| 208 | }; |
| 209 | |
| 210 | /** |
| 211 | * Provides a list of hook commands to run for the 'hookname' event. |
| 212 | * |
| 213 | * This function consolidates hooks from two sources: |
| 214 | * 1. The config-based hooks (not yet implemented). |
| 215 | * 2. The "traditional" hook found in the repository hooks directory |
| 216 | * (e.g., .git/hooks/pre-commit). |
| 217 | * |
| 218 | * The list is ordered by execution priority. |
| 219 | * |
| 220 | * The caller is responsible for freeing the memory of the returned list |
| 221 | * using string_list_clear() and free(). |
| 222 | */ |
| 223 | struct string_list *list_hooks(struct repository *r, const char *hookname, |
| 224 | struct run_hooks_opt *options); |
| 225 | |
| 226 | /** |
| 227 | * Frees a struct hook stored as the util pointer of a string_list_item. |
| 228 | * Suitable for use as a string_list_clear_func_t callback. |
| 229 | */ |
| 230 | void hook_free(void *p, const char *str); |
| 231 | |
| 232 | /** |
| 233 | * Frees the hook configuration cache stored in `struct repository`. |
| 234 | * Called by repo_clear(). |
| 235 | */ |
| 236 | void hook_cache_clear(struct strmap *cache); |
| 237 | |
| 238 | /** |
| 239 | * Returns true if `name` is a recognized hook event name |
| 240 | * (e.g. "pre-commit", "post-receive"). |
| 241 | */ |
| 242 | bool is_known_hook(const char *name); |
| 243 | |
| 244 | /** |
| 245 | * Returns the path to the hook file, or NULL if the hook is missing |
| 246 | * or disabled. Note that this points to static storage that will be |
| 247 | * overwritten by further calls to find_hook and run_hook_*. |
| 248 | */ |
| 249 | const char *find_hook(struct repository *r, const char *name); |
| 250 | |
| 251 | /** |
| 252 | * A boolean version of find_hook() |
| 253 | */ |
| 254 | int hook_exists(struct repository *r, const char *hookname); |
| 255 | |
| 256 | /** |
| 257 | * Takes a `hook_name`, resolves it to a path with find_hook(), and |
| 258 | * runs the hook for you with the options specified in "struct |
| 259 | * run_hooks opt". Will free memory associated with the "struct run_hooks_opt". |
| 260 | * |
| 261 | * Returns the status code of the run hook, or a negative value on |
| 262 | * error(). |
| 263 | */ |
| 264 | int run_hooks_opt(struct repository *r, const char *hook_name, |
| 265 | struct run_hooks_opt *options); |
| 266 | |
| 267 | /** |
| 268 | * A wrapper for run_hooks_opt() which provides a dummy "struct |
| 269 | * run_hooks_opt" initialized with "RUN_HOOKS_OPT_INIT". |
| 270 | */ |
| 271 | int run_hooks(struct repository *r, const char *hook_name); |
| 272 | |
| 273 | /** |
| 274 | * Like run_hooks(), a wrapper for run_hooks_opt(). |
| 275 | * |
| 276 | * In addition to the wrapping behavior provided by run_hooks(), this |
| 277 | * wrapper takes a list of strings terminated by a NULL |
| 278 | * argument. These things will be used as positional arguments to the |
| 279 | * hook. This function behaves like the old run_hook_le() API. |
| 280 | */ |
| 281 | LAST_ARG_MUST_BE_NULL |
| 282 | int run_hooks_l(struct repository *r, const char *hook_name, ...); |
| 283 | #endif |