diff options
Diffstat (limited to 'config.h')
-rw-r--r-- | config.h | 242 |
1 files changed, 157 insertions, 85 deletions
@@ -3,7 +3,8 @@ #include "hashmap.h" #include "string-list.h" - +#include "repository.h" +#include "parse.h" /** * The config API gives callers a way to access Git configuration files @@ -49,13 +50,12 @@ const char *config_scope_name(enum config_scope scope); struct git_config_source { unsigned int use_stdin:1; const char *file; - /* The repository if blob is not NULL; leave blank for the_repository */ - struct repository *repo; const char *blob; enum config_scope scope; }; enum config_origin_type { + CONFIG_ORIGIN_UNKNOWN = 0, CONFIG_ORIGIN_BLOB, CONFIG_ORIGIN_FILE, CONFIG_ORIGIN_STDIN, @@ -72,6 +72,7 @@ enum config_event_t { CONFIG_EVENT_ERROR }; +struct config_source; /* * The parser event function (if not NULL) is called with the event type and * the begin/end offsets of the parsed elements. @@ -81,6 +82,7 @@ enum config_event_t { */ typedef int (*config_parser_event_fn_t)(enum config_event_t type, size_t begin_offset, size_t end_offset, + struct config_source *cs, void *event_fn_data); struct config_options { @@ -89,8 +91,21 @@ struct config_options { unsigned int ignore_worktree : 1; unsigned int ignore_cmdline : 1; unsigned int system_gently : 1; + + /* + * For internal use. Include all includeif.hasremoteurl paths without + * checking if the repo has that remote URL, and when doing so, verify + * that files included in this way do not configure any remote URLs + * themselves. + */ + unsigned int unconditional_remote_url : 1; + const char *commondir; const char *git_dir; + /* + * event_fn and event_fn_data are for internal use only. Handles events + * emitted by the config parser. + */ config_parser_event_fn_t event_fn; void *event_fn_data; enum config_error_action { @@ -101,8 +116,31 @@ struct config_options { } error_action; }; +/* Config source metadata for a given config key-value pair */ +struct key_value_info { + const char *filename; + int linenr; + enum config_origin_type origin_type; + enum config_scope scope; + const char *path; +}; +#define KVI_INIT { \ + .filename = NULL, \ + .linenr = -1, \ + .origin_type = CONFIG_ORIGIN_UNKNOWN, \ + .scope = CONFIG_SCOPE_UNKNOWN, \ + .path = NULL, \ +} + +/* Captures additional information that a config callback can use. */ +struct config_context { + /* Config source metadata for key and value. */ + const struct key_value_info *kvi; +}; +#define CONFIG_CONTEXT_INIT { 0 } + /** - * A config callback function takes three parameters: + * A config callback function takes four parameters: * * - the name of the parsed variable. This is in canonical "flat" form: the * section, subsection, and variable segments will be separated by dots, @@ -113,33 +151,44 @@ struct config_options { * value specified, the value will be NULL (typically this means it * should be interpreted as boolean true). * + * - the 'config context', that is, additional information about the config + * iteration operation provided by the config machinery. For example, this + * includes information about the config source being parsed (e.g. the + * filename). + * * - a void pointer passed in by the caller of the config API; this can * contain callback-specific data * * A config callback should return 0 for success, or -1 if the variable * could not be parsed properly. */ -typedef int (*config_fn_t)(const char *, const char *, void *); +typedef int (*config_fn_t)(const char *, const char *, + const struct config_context *, void *); -int git_default_config(const char *, const char *, void *); +int git_default_config(const char *, const char *, + const struct config_context *, void *); /** * Read a specific file in git-config format. * This function takes the same callback and data parameters as `git_config`. + * + * Unlike git_config(), this function does not respect includes. */ int git_config_from_file(config_fn_t fn, const char *, void *); int git_config_from_file_with_options(config_fn_t fn, const char *, - void *, + void *, enum config_scope, const struct config_options *); int git_config_from_mem(config_fn_t fn, const enum config_origin_type, const char *name, const char *buf, size_t len, - void *data, const struct config_options *opts); + void *data, enum config_scope scope, + const struct config_options *opts); int git_config_from_blob_oid(config_fn_t fn, const char *name, struct repository *repo, - const struct object_id *oid, void *data); + const struct object_id *oid, void *data, + enum config_scope scope); void git_config_push_parameter(const char *text); void git_config_push_env(const char *spec); int git_config_from_parameters(config_fn_t fn, void *data); @@ -158,6 +207,8 @@ void read_very_early_config(config_fn_t cb, void *data); * will first feed the user-wide one to the callback, and then the * repo-specific one; by overwriting, the higher-priority repo-specific * value is left at the end). + * + * Unlike git_config_from_file(), this function respects includes. */ void git_config(config_fn_t fn, void *); @@ -182,6 +233,7 @@ void git_config(config_fn_t fn, void *); */ int config_with_options(config_fn_t fn, void *, struct git_config_source *config_source, + struct repository *repo, const struct config_options *opts); /** @@ -191,35 +243,30 @@ int config_with_options(config_fn_t fn, void *, * The following helper functions aid in parsing string values */ -int git_parse_ssize_t(const char *, ssize_t *); -int git_parse_ulong(const char *, unsigned long *); - -/** - * Same as `git_config_bool`, except that it returns -1 on error rather - * than dying. - */ -int git_parse_maybe_bool(const char *); - /** * Parse the string to an integer, including unit factors. Dies on error; * otherwise, returns the parsed result. */ -int git_config_int(const char *, const char *); +int git_config_int(const char *, const char *, const struct key_value_info *); -int64_t git_config_int64(const char *, const char *); +int64_t git_config_int64(const char *, const char *, + const struct key_value_info *); /** * Identical to `git_config_int`, but for unsigned longs. */ -unsigned long git_config_ulong(const char *, const char *); +unsigned long git_config_ulong(const char *, const char *, + const struct key_value_info *); -ssize_t git_config_ssize_t(const char *, const char *); +ssize_t git_config_ssize_t(const char *, const char *, + const struct key_value_info *); /** * Same as `git_config_bool`, except that integers are returned as-is, and * an `is_bool` flag is unset. */ -int git_config_bool_or_int(const char *, const char *, int *); +int git_config_bool_or_int(const char *, const char *, + const struct key_value_info *, int *); /** * Parse a string into a boolean value, respecting keywords like "true" and @@ -243,7 +290,7 @@ int git_config_pathname(const char **, const char *, const char *); int git_config_expiry_date(timestamp_t *, const char *, const char *); int git_config_color(char *, const char *, const char *); -int git_config_set_in_file_gently(const char *, const char *, const char *); +int git_config_set_in_file_gently(const char *, const char *, const char *, const char *); /** * write config values to a specific config file, takes a key/value pair as @@ -254,12 +301,18 @@ void git_config_set_in_file(const char *, const char *, const char *); int git_config_set_gently(const char *, const char *); /** + * Write a config value that should apply to the current worktree. If + * extensions.worktreeConfig is enabled, then the write will happen in the + * current worktree's config. Otherwise, write to the common config file. + */ +int repo_config_set_worktree_gently(struct repository *, const char *, const char *); + +/** * write config values to `.git/config`, takes a key/value pair as parameter. */ void git_config_set(const char *, const char *); int git_config_parse_key(const char *, char **, size_t *); -int git_config_key_is_valid(const char *key); /* * The following macros specify flag bits that alter the behavior @@ -282,7 +335,10 @@ int git_config_key_is_valid(const char *key); int git_config_set_multivar_gently(const char *, const char *, const char *, unsigned); void git_config_set_multivar(const char *, const char *, const char *, unsigned); -int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, unsigned); +int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned); +int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned); + +const char *git_config_prepare_comment_string(const char *); /** * takes four parameters: @@ -321,8 +377,6 @@ int git_config_rename_section(const char *, const char *); int git_config_rename_section_in_file(const char *, const char *, const char *); int git_config_copy_section(const char *, const char *); int git_config_copy_section_in_file(const char *, const char *, const char *); -int git_env_bool(const char *, int); -unsigned long git_env_ulong(const char *, unsigned long); int git_config_system(void); int config_error_nonbool(const char *); #if defined(__GNUC__) @@ -330,47 +384,13 @@ int config_error_nonbool(const char *); #endif char *git_system_config(void); -void git_global_config(char **user, char **xdg); +char *git_global_config(void); +void git_global_config_paths(char **user, char **xdg); int git_config_parse_parameter(const char *, config_fn_t fn, void *data); -enum config_scope current_config_scope(void); -const char *current_config_origin_type(void); -const char *current_config_name(void); -int current_config_line(void); - -/** - * Include Directives - * ------------------ - * - * By default, the config parser does not respect include directives. - * However, a caller can use the special `git_config_include` wrapper - * callback to support them. To do so, you simply wrap your "real" callback - * function and data pointer in a `struct config_include_data`, and pass - * the wrapper to the regular config-reading functions. For example: - * - * ------------------------------------------- - * int read_file_with_include(const char *file, config_fn_t fn, void *data) - * { - * struct config_include_data inc = CONFIG_INCLUDE_INIT; - * inc.fn = fn; - * inc.data = data; - * return git_config_from_file(git_config_include, file, &inc); - * } - * ------------------------------------------- - * - * `git_config` respects includes automatically. The lower-level - * `git_config_from_file` does not. - * - */ -struct config_include_data { - int depth; - config_fn_t fn; - void *data; - const struct config_options *opts; -}; -#define CONFIG_INCLUDE_INIT { 0 } -int git_config_include(const char *name, const char *value, void *data); +const char *config_origin_type_name(enum config_origin_type type); +void kvi_from_param(struct key_value_info *out); /* * Match and parse a config key of the form: @@ -462,10 +482,31 @@ int git_configset_add_file(struct config_set *cs, const char *filename); /** * Finds and returns the value list, sorted in order of increasing priority * for the configuration variable `key` and config set `cs`. When the - * configuration variable `key` is not found, returns NULL. The caller - * should not free or modify the returned pointer, as it is owned by the cache. + * configuration variable `key` is not found, returns 1 without touching + * `value`. + * + * The key will be parsed for validity with git_config_parse_key(), on + * error a negative value will be returned. + * + * The caller should not free or modify the returned pointer, as it is + * owned by the cache. */ -const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key); +RESULT_MUST_BE_USED +int git_configset_get_value_multi(struct config_set *cs, const char *key, + const struct string_list **dest); + +/** + * A validation wrapper for git_configset_get_value_multi() which does + * for it what git_configset_get_string() does for + * git_configset_get_value(). + * + * The configuration syntax allows for "[section] key", which will + * give us a NULL entry in the "struct string_list", as opposed to + * "[section] key =" which is the empty string. Most users of the API + * are not prepared to handle NULL in a "struct string_list". + */ +int git_configset_get_string_multi(struct config_set *cs, const char *key, + const struct string_list **dest); /** * Clears `config_set` structure, removes all saved variable-value pairs. @@ -477,6 +518,13 @@ void git_configset_clear(struct config_set *cs); * value in the 'dest' pointer. */ +/** + * git_configset_get() returns negative values on error, see + * repo_config_get() below. + */ +RESULT_MUST_BE_USED +int git_configset_get(struct config_set *cs, const char *key); + /* * Finds the highest-priority value for the configuration variable `key` * and config set `cs`, stores the pointer to it in `value` and returns 0. @@ -484,10 +532,10 @@ void git_configset_clear(struct config_set *cs); * touching `value`. The caller should not free or modify `value`, as it * is owned by the cache. */ -int git_configset_get_value(struct config_set *cs, const char *key, const char **dest); +int git_configset_get_value(struct config_set *cs, const char *key, + const char **dest, struct key_value_info *kvi); int git_configset_get_string(struct config_set *cs, const char *key, char **dest); -int git_configset_get_string_tmp(struct config_set *cs, const char *key, const char **dest); int git_configset_get_int(struct config_set *cs, const char *key, int *dest); int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest); int git_configset_get_bool(struct config_set *cs, const char *key, int *dest); @@ -498,10 +546,22 @@ int git_configset_get_pathname(struct config_set *cs, const char *key, const cha /* Functions for reading a repository's config */ struct repository; void repo_config(struct repository *repo, config_fn_t fn, void *data); + +/** + * Run only the discover part of the repo_config_get_*() functions + * below, in addition to 1 if not found, returns negative values on + * error (e.g. if the key itself is invalid). + */ +RESULT_MUST_BE_USED +int repo_config_get(struct repository *repo, const char *key); int repo_config_get_value(struct repository *repo, const char *key, const char **value); -const struct string_list *repo_config_get_value_multi(struct repository *repo, - const char *key); +RESULT_MUST_BE_USED +int repo_config_get_value_multi(struct repository *repo, const char *key, + const struct string_list **dest); +RESULT_MUST_BE_USED +int repo_config_get_string_multi(struct repository *repo, const char *key, + const struct string_list **dest); int repo_config_get_string(struct repository *repo, const char *key, char **dest); int repo_config_get_string_tmp(struct repository *repo, @@ -519,6 +579,13 @@ int repo_config_get_maybe_bool(struct repository *repo, int repo_config_get_pathname(struct repository *repo, const char *key, const char **dest); +/* + * Functions for reading protected config. By definition, protected + * config ignores repository config, so these do not take a `struct + * repository` parameter. + */ +void git_protected_config(config_fn_t fn, void *data); + /** * Querying For Specific Variables * ------------------------------- @@ -527,8 +594,15 @@ int repo_config_get_pathname(struct repository *repo, * manner, the config API provides two functions `git_config_get_value` * and `git_config_get_value_multi`. They both read values from an internal * cache generated previously from reading the config files. + * + * For those git_config_get*() functions that aren't documented, + * consult the corresponding repo_config_get*() function's + * documentation. */ +RESULT_MUST_BE_USED +int git_config_get(const char *key); + /** * Finds the highest-priority value for the configuration variable `key`, * stores the pointer to it in `value` and returns 0. When the @@ -541,10 +615,17 @@ int git_config_get_value(const char *key, const char **value); /** * Finds and returns the value list, sorted in order of increasing priority * for the configuration variable `key`. When the configuration variable - * `key` is not found, returns NULL. The caller should not free or modify - * the returned pointer, as it is owned by the cache. + * `key` is not found, returns 1 without touching `value`. + * + * The caller should not free or modify the returned pointer, as it is + * owned by the cache. */ -const struct string_list *git_config_get_value_multi(const char *key); +RESULT_MUST_BE_USED +int git_config_get_value_multi(const char *key, + const struct string_list **dest); +RESULT_MUST_BE_USED +int git_config_get_string_multi(const char *key, + const struct string_list **dest); /** * Resets and invalidates the config cache. @@ -609,10 +690,8 @@ int git_config_get_maybe_bool(const char *key, int *dest); int git_config_get_pathname(const char *key, const char **dest); int git_config_get_index_threads(int *dest); -int git_config_get_untracked_cache(void); int git_config_get_split_index(void); int git_config_get_max_percent_split_change(void); -int git_config_get_fsmonitor(void); /* This dies if the configured or default date is in the future */ int git_config_get_expiry(const char *key, const char **output); @@ -620,13 +699,6 @@ int git_config_get_expiry(const char *key, const char **output); /* parse either "this many days" integer, or "5.days.ago" approxidate */ int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now); -struct key_value_info { - const char *filename; - int linenr; - enum config_origin_type origin_type; - enum config_scope scope; -}; - /** * First prints the error message specified by the caller in `err` and then * dies printing the line number and the file name of the highest priority |