1
0
mirror of https://github.com/git/git synced 2024-07-05 00:58:49 +00:00
git/builtin/config.c

1315 lines
40 KiB
C
Raw Normal View History

#include "builtin.h"
#include "abspath.h"
#include "config.h"
#include "color.h"
#include "editor.h"
#include "environment.h"
#include "repository.h"
#include "gettext.h"
#include "ident.h"
#include "parse-options.h"
#include "urlmatch.h"
#include "path.h"
#include "quote.h"
#include "setup.h"
#include "strbuf.h"
worktree: add per-worktree config files A new repo extension is added, worktreeConfig. When it is present: - Repository config reading by default includes $GIT_DIR/config _and_ $GIT_DIR/config.worktree. "config" file remains shared in multiple worktree setup. - The special treatment for core.bare and core.worktree, to stay effective only in main worktree, is gone. These config settings are supposed to be in config.worktree. This extension is most useful in multiple worktree setup because you now have an option to store per-worktree config (which is either .git/config.worktree for main worktree, or .git/worktrees/xx/config.worktree for linked ones). This extension can be used in single worktree mode, even though it's pretty much useless (but this can happen after you remove all linked worktrees and move back to single worktree). "git config" reads from both "config" and "config.worktree" by default (i.e. without either --user, --file...) when this extension is present. Default writes still go to "config", not "config.worktree". A new option --worktree is added for that (*). Since a new repo extension is introduced, existing git binaries should refuse to access to the repo (both from main and linked worktrees). So they will not misread the config file (i.e. skip the config.worktree part). They may still accidentally write to the config file anyway if they use with "git config --file <path>". This design places a bet on the assumption that the majority of config variables are shared so it is the default mode. A safer move would be default writes go to per-worktree file, so that accidental changes are isolated. (*) "git config --worktree" points back to "config" file when this extension is not present and there is only one worktree so that it works in any both single and multiple worktree setups. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-21 14:02:28 +00:00
#include "worktree.h"
static const char *const builtin_config_usage[] = {
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
N_("git config list [<file-option>] [<display-option>] [--includes]"),
N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name>"),
N_("git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
N_("git config rename-section [<file-option>] <old-name> <new-name>"),
N_("git config remove-section [<file-option>] <name>"),
N_("git config edit [<file-option>]"),
N_("git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]"),
NULL
};
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
static const char *const builtin_config_list_usage[] = {
N_("git config list [<file-option>] [<display-option>] [--includes]"),
NULL
};
static const char *const builtin_config_get_usage[] = {
N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name>"),
NULL
};
static const char *const builtin_config_set_usage[] = {
N_("git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
NULL
};
static const char *const builtin_config_unset_usage[] = {
N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
NULL
};
static const char *const builtin_config_rename_section_usage[] = {
N_("git config rename-section [<file-option>] <old-name> <new-name>"),
NULL
};
static const char *const builtin_config_remove_section_usage[] = {
N_("git config remove-section [<file-option>] <name>"),
NULL
};
static const char *const builtin_config_edit_usage[] = {
N_("git config edit [<file-option>]"),
NULL
};
static char *key;
static regex_t *key_regexp;
static const char *value_pattern;
static regex_t *regexp;
static int show_keys;
static int omit_values;
static int use_key_regexp;
static int do_all;
static int do_not_match;
static char delim = '=';
static char key_delim = ' ';
static char term = '\n';
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
static parse_opt_subcommand_fn *subcommand;
static int use_global_config, use_system_config, use_local_config;
worktree: add per-worktree config files A new repo extension is added, worktreeConfig. When it is present: - Repository config reading by default includes $GIT_DIR/config _and_ $GIT_DIR/config.worktree. "config" file remains shared in multiple worktree setup. - The special treatment for core.bare and core.worktree, to stay effective only in main worktree, is gone. These config settings are supposed to be in config.worktree. This extension is most useful in multiple worktree setup because you now have an option to store per-worktree config (which is either .git/config.worktree for main worktree, or .git/worktrees/xx/config.worktree for linked ones). This extension can be used in single worktree mode, even though it's pretty much useless (but this can happen after you remove all linked worktrees and move back to single worktree). "git config" reads from both "config" and "config.worktree" by default (i.e. without either --user, --file...) when this extension is present. Default writes still go to "config", not "config.worktree". A new option --worktree is added for that (*). Since a new repo extension is introduced, existing git binaries should refuse to access to the repo (both from main and linked worktrees). So they will not misread the config file (i.e. skip the config.worktree part). They may still accidentally write to the config file anyway if they use with "git config --file <path>". This design places a bet on the assumption that the majority of config variables are shared so it is the default mode. A safer move would be default writes go to per-worktree file, so that accidental changes are isolated. (*) "git config --worktree" points back to "config" file when this extension is not present and there is only one worktree so that it works in any both single and multiple worktree setups. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-21 14:02:28 +00:00
static int use_worktree_config;
static struct git_config_source given_config_source;
static int actions, type;
builtin/config: introduce `--default` For some use cases, callers of the `git-config(1)` builtin would like to fallback to default values when the variable asked for does not exist. In addition, users would like to use existing type specifiers to ensure that values are parsed correctly when they do exist in the configuration. For example, to fetch a value without a type specifier and fallback to `$fallback`, the following is required: $ git config core.foo || echo "$fallback" This is fine for most values, but can be tricky for difficult-to-express `$fallback`'s, like ANSI color codes. This motivates `--get-color`, which is a one-off exception to the normal type specifier rules wherein a user specifies both the configuration variable and an optional fallback. Both are formatted according to their type specifier, which eases the burden on the user to ensure that values are correctly formatted. This commit (and those following it in this series) aim to eventually replace `--get-color` with a consistent alternative. By introducing `--default`, we allow the `--get-color` action to be promoted to a `--type=color` type specifier, retaining the "fallback" behavior via the `--default` flag introduced in this commit. For example, we aim to replace: $ git config --get-color variable [default] [...] with: $ git config --default default --type=color variable [...] Values filled by `--default` behave exactly as if they were present in the affected configuration file; they will be parsed by type specifiers without the knowledge that they are not themselves present in the configuration. Specifically, this means that the following will work: $ git config --int --default 1M does.not.exist 1048576 In subsequent commits, we will offer `--type=color`, which (in conjunction with `--default`) will be sufficient to replace `--get-color`. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-10 00:18:26 +00:00
static char *default_value;
static int end_nul;
static int respect_includes_opt = -1;
static struct config_options config_options;
static int show_origin;
static int show_scope;
static int fixed_value;
static const char *comment_arg;
#define ACTION_GET (1<<0)
#define ACTION_GET_ALL (1<<1)
#define ACTION_GET_REGEXP (1<<2)
#define ACTION_REPLACE_ALL (1<<3)
#define ACTION_ADD (1<<4)
#define ACTION_UNSET (1<<5)
#define ACTION_UNSET_ALL (1<<6)
#define ACTION_RENAME_SECTION (1<<7)
#define ACTION_REMOVE_SECTION (1<<8)
#define ACTION_LIST (1<<9)
#define ACTION_EDIT (1<<10)
#define ACTION_SET (1<<11)
#define ACTION_SET_ALL (1<<12)
#define ACTION_GET_COLOR (1<<13)
#define ACTION_GET_COLORBOOL (1<<14)
#define ACTION_GET_URLMATCH (1<<15)
/*
* The actions "ACTION_LIST | ACTION_GET_*" which may produce more than
* one line of output and which should therefore be paged.
*/
#define PAGING_ACTIONS (ACTION_LIST | ACTION_GET_ALL | \
ACTION_GET_REGEXP | ACTION_GET_URLMATCH)
#define TYPE_BOOL 1
#define TYPE_INT 2
#define TYPE_BOOL_OR_INT 3
#define TYPE_PATH 4
#define TYPE_EXPIRY_DATE 5
#define TYPE_COLOR 6
#define TYPE_BOOL_OR_STR 7
#define OPT_CALLBACK_VALUE(s, l, v, h, i) \
{ OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
PARSE_OPT_NONEG, option_parse_type, (i) }
static NORETURN void usage_builtin_config(void);
static int option_parse_type(const struct option *opt, const char *arg,
int unset)
{
int new_type, *to_type;
if (unset) {
*((int *) opt->value) = 0;
return 0;
}
/*
* To support '--<type>' style flags, begin with new_type equal to
* opt->defval.
*/
new_type = opt->defval;
if (!new_type) {
if (!strcmp(arg, "bool"))
new_type = TYPE_BOOL;
else if (!strcmp(arg, "int"))
new_type = TYPE_INT;
else if (!strcmp(arg, "bool-or-int"))
new_type = TYPE_BOOL_OR_INT;
else if (!strcmp(arg, "bool-or-str"))
new_type = TYPE_BOOL_OR_STR;
else if (!strcmp(arg, "path"))
new_type = TYPE_PATH;
else if (!strcmp(arg, "expiry-date"))
new_type = TYPE_EXPIRY_DATE;
else if (!strcmp(arg, "color"))
new_type = TYPE_COLOR;
else
die(_("unrecognized --type argument, %s"), arg);
}
to_type = opt->value;
if (*to_type && *to_type != new_type) {
/*
* Complain when there is a new type not equal to the old type.
* This allows for combinations like '--int --type=int' and
* '--type=int --type=int', but disallows ones like '--type=bool
* --int' and '--type=bool
* --type=int'.
*/
error(_("only one type at a time"));
usage_builtin_config();
}
*to_type = new_type;
return 0;
}
static void check_argc(int argc, int min, int max)
{
if (argc >= min && argc <= max)
return;
if (min == max)
error(_("wrong number of arguments, should be %d"), min);
else
error(_("wrong number of arguments, should be from %d to %d"),
min, max);
usage_builtin_config();
}
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
static void show_config_origin(const struct key_value_info *kvi,
struct strbuf *buf)
{
const char term = end_nul ? '\0' : '\t';
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
strbuf_addstr(buf, config_origin_type_name(kvi->origin_type));
strbuf_addch(buf, ':');
if (end_nul)
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
strbuf_addstr(buf, kvi->filename ? kvi->filename : "");
else
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
quote_c_style(kvi->filename ? kvi->filename : "", buf, NULL, 0);
strbuf_addch(buf, term);
}
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
static void show_config_scope(const struct key_value_info *kvi,
struct strbuf *buf)
{
const char term = end_nul ? '\0' : '\t';
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
const char *scope = config_scope_name(kvi->scope);
strbuf_addstr(buf, N_(scope));
strbuf_addch(buf, term);
}
static int show_all_config(const char *key_, const char *value_,
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
const struct config_context *ctx,
void *cb UNUSED)
{
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
const struct key_value_info *kvi = ctx->kvi;
if (show_origin || show_scope) {
struct strbuf buf = STRBUF_INIT;
if (show_scope)
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
show_config_scope(kvi, &buf);
if (show_origin)
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
show_config_origin(kvi, &buf);
/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
fwrite(buf.buf, 1, buf.len, stdout);
strbuf_release(&buf);
}
if (!omit_values && value_)
printf("%s%c%s%c", key_, delim, value_, term);
else
printf("%s%c", key_, term);
return 0;
}
struct strbuf_list {
struct strbuf *items;
int nr;
int alloc;
};
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
static int format_config(struct strbuf *buf, const char *key_,
const char *value_, const struct key_value_info *kvi)
{
if (show_scope)
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
show_config_scope(kvi, buf);
if (show_origin)
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
show_config_origin(kvi, buf);
if (show_keys)
strbuf_addstr(buf, key_);
if (!omit_values) {
if (show_keys)
strbuf_addch(buf, key_delim);
if (type == TYPE_INT)
strbuf_addf(buf, "%"PRId64,
git_config_int64(key_, value_ ? value_ : "", kvi));
else if (type == TYPE_BOOL)
strbuf_addstr(buf, git_config_bool(key_, value_) ?
"true" : "false");
else if (type == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key_, value_, kvi,
&is_bool);
if (is_bool)
strbuf_addstr(buf, v ? "true" : "false");
else
strbuf_addf(buf, "%d", v);
} else if (type == TYPE_BOOL_OR_STR) {
int v = git_parse_maybe_bool(value_);
if (v < 0)
strbuf_addstr(buf, value_);
else
strbuf_addstr(buf, v ? "true" : "false");
} else if (type == TYPE_PATH) {
const char *v;
if (git_config_pathname(&v, key_, value_) < 0)
return -1;
strbuf_addstr(buf, v);
free((char *)v);
} else if (type == TYPE_EXPIRY_DATE) {
timestamp_t t;
if (git_config_expiry_date(&t, key_, value_) < 0)
return -1;
strbuf_addf(buf, "%"PRItime, t);
} else if (type == TYPE_COLOR) {
char v[COLOR_MAXLEN];
if (git_config_color(v, key_, value_) < 0)
return -1;
strbuf_addstr(buf, v);
} else if (value_) {
strbuf_addstr(buf, value_);
} else {
/* Just show the key name; back out delimiter */
if (show_keys)
strbuf_setlen(buf, buf->len - 1);
}
}
git-config: do not complain about duplicate entries If git-config is asked for a single value, it will complain and exit with an error if it finds multiple instances of that value. This is unlike the usual internal config parsing, however, which will generally overwrite previous values, leaving only the final one. For example: [set a multivar] $ git config user.email one@example.com $ git config --add user.email two@example.com [use the internal parser to fetch it] $ git var GIT_AUTHOR_IDENT Your Name <two@example.com> ... [use git-config to fetch it] $ git config user.email one@example.com error: More than one value for the key user.email: two@example.com This overwriting behavior is critical for the regular parser, which starts with the lowest-priority file (e.g., /etc/gitconfig) and proceeds to the highest-priority file ($GIT_DIR/config). Overwriting yields the highest priority value at the end. Git-config solves this problem by implementing its own parsing. It goes from highest to lowest priorty, but does not proceed to the next file if it has seen a value. So in practice, this distinction never mattered much, because it only triggered for values in the same file. And there was not much point in doing that; the real value is in overwriting values from lower-priority files. However, this changed with the implementation of config include files. Now we might see an include overriding a value from the parent file, which is a sensible thing to do, but git-config will flag as a duplication. This patch drops the duplicate detection for git-config and switches to a pure-overwrite model (for the single case; --get-all can still be used if callers want to do something more fancy). As is shown by the modifications to the test suite, this is a user-visible change in behavior. An alternative would be to just change the include case, but this is much cleaner for a few reasons: 1. If you change the include case, then to what? If you just stop parsing includes after getting a value, then you will get a _different_ answer than the regular config parser (you'll get the first value instead of the last value). So you'd want to implement overwrite semantics anyway. 2. Even though it is a change in behavior for git-config, it is bringing us in line with what the internal parsers already do. 3. The file-order reimplementation is the only thing keeping us from sharing more code with the internal config parser, which will help keep differences to a minimum. Going under the assumption that the primary purpose of git-config is to behave identically to how git's internal parsing works, this change can be seen as a bug-fix. Signed-off-by: Jeff King <peff@peff.net>
2012-10-23 20:52:44 +00:00
strbuf_addch(buf, term);
return 0;
}
config: add ctx arg to config_fn_t Add a new "const struct config_context *ctx" arg to config_fn_t to hold additional information about the config iteration operation. config_context has a "struct key_value_info kvi" member that holds metadata about the config source being read (e.g. what kind of config source it is, the filename, etc). In this series, we're only interested in .kvi, so we could have just used "struct key_value_info" as an arg, but config_context makes it possible to add/adjust members in the future without changing the config_fn_t signature. We could also consider other ways of organizing the args (e.g. moving the config name and value into config_context or key_value_info), but in my experiments, the incremental benefit doesn't justify the added complexity (e.g. a config_fn_t will sometimes invoke another config_fn_t but with a different config value). In subsequent commits, the .kvi member will replace the global "struct config_reader" in config.c, making config iteration a global-free operation. It requires much more work for the machinery to provide meaningful values of .kvi, so for now, merely change the signature and call sites, pass NULL as a placeholder value, and don't rely on the arg in any meaningful way. Most of the changes are performed by contrib/coccinelle/config_fn_ctx.pending.cocci, which, for every config_fn_t: - Modifies the signature to accept "const struct config_context *ctx" - Passes "ctx" to any inner config_fn_t, if needed - Adds UNUSED attributes to "ctx", if needed Most config_fn_t instances are easily identified by seeing if they are called by the various config functions. Most of the remaining ones are manually named in the .cocci patch. Manual cleanups are still needed, but the majority of it is trivial; it's either adjusting config_fn_t that the .cocci patch didn't catch, or adding forward declarations of "struct config_context ctx" to make the signatures make sense. The non-trivial changes are in cases where we are invoking a config_fn_t outside of config machinery, and we now need to decide what value of "ctx" to pass. These cases are: - trace2/tr2_cfg.c:tr2_cfg_set_fl() This is indirectly called by git_config_set() so that the trace2 machinery can notice the new config values and update its settings using the tr2 config parsing function, i.e. tr2_cfg_cb(). - builtin/checkout.c:checkout_main() This calls git_xmerge_config() as a shorthand for parsing a CLI arg. This might be worth refactoring away in the future, since git_xmerge_config() can call git_default_config(), which can do much more than just parsing. Handle them by creating a KVI_INIT macro that initializes "struct key_value_info" to a reasonable default, and use that to construct the "ctx" arg. Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:22 +00:00
static int collect_config(const char *key_, const char *value_,
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
const struct config_context *ctx, void *cb)
{
struct strbuf_list *values = cb;
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
const struct key_value_info *kvi = ctx->kvi;
if (!use_key_regexp && strcmp(key_, key))
return 0;
if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0))
return 0;
if (fixed_value && strcmp(value_pattern, (value_?value_:"")))
return 0;
if (regexp != NULL &&
(do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0)))
return 0;
ALLOC_GROW(values->items, values->nr + 1, values->alloc);
strbuf_init(&values->items[values->nr], 0);
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
return format_config(&values->items[values->nr++], key_, value_, kvi);
}
static int get_value(const char *key_, const char *regex_, unsigned flags)
{
int ret = CONFIG_GENERIC_ERROR;
struct strbuf_list values = {NULL};
int i;
if (use_key_regexp) {
char *tl;
/*
* NEEDSWORK: this naive pattern lowercasing obviously does not
* work for more complex patterns like "^[^.]*Foo.*bar".
* Perhaps we should deprecate this altogether someday.
*/
key = xstrdup(key_);
for (tl = key + strlen(key) - 1;
tl >= key && *tl != '.';
tl--)
*tl = tolower(*tl);
for (tl = key; *tl && *tl != '.'; tl++)
*tl = tolower(*tl);
key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
if (regcomp(key_regexp, key, REG_EXTENDED)) {
error(_("invalid key pattern: %s"), key_);
FREE_AND_NULL(key_regexp);
ret = CONFIG_INVALID_PATTERN;
goto free_strings;
}
} else {
if (git_config_parse_key(key_, &key, NULL)) {
ret = CONFIG_INVALID_KEY;
goto free_strings;
}
}
if (regex_ && (flags & CONFIG_FLAGS_FIXED_VALUE))
value_pattern = regex_;
else if (regex_) {
if (regex_[0] == '!') {
do_not_match = 1;
regex_++;
}
regexp = (regex_t*)xmalloc(sizeof(regex_t));
if (regcomp(regexp, regex_, REG_EXTENDED)) {
error(_("invalid pattern: %s"), regex_);
FREE_AND_NULL(regexp);
ret = CONFIG_INVALID_PATTERN;
goto free_strings;
}
}
config_with_options(collect_config, &values,
config: pass 'repo' directly to 'config_with_options()' Add a 'struct repository' argument to 'config_with_options()' and remove the 'repo' field from 'struct git_config_source'. A 'struct repository' instance was originally added to the config source in e3e8bf046e9 (submodule-config: pass repo upon blob config read, 2021-08-16) to improve how submodule blob config content was accessed. At the time, this was the only use for a 'repository' instance, so it was naturally added only where it was needed: to 'struct git_config_source'. However, in upcoming patches, 'config_with_options()' will need the repository instance to access extension information (regardless of whether a 'config_source' exists). To make the 'struct repository' instance more easily accessible, move it into the function's arguments. Update all callers of 'config_with_options()' to pass the appropriate 'repo' value: * in 'builtin/config.c', use 'the_repository' * in 'submodule--config.c', use the 'repo' arg in 'config_from_gitmodules()' * in 'read_[very_]early_config()' & 'read_protected_config()', set 'repo' to NULL (repository instances aren't available there) * in 'populate_remote_urls()', use the repo instance that has been added to the 'struct config_include_data' * in 'repo_read_config()', use the given 'repo' arg Finally, note that this patch eliminates the fallback to 'the_repository' that previously existed for the 'config_source' repo instance if it was NULL. The fallback is no longer necessary, as the 'repo' is set explicitly in all cases where it is needed. Signed-off-by: Victoria Dye <vdye@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-05-26 01:32:59 +00:00
&given_config_source, the_repository,
&config_options);
builtin/config: introduce `--default` For some use cases, callers of the `git-config(1)` builtin would like to fallback to default values when the variable asked for does not exist. In addition, users would like to use existing type specifiers to ensure that values are parsed correctly when they do exist in the configuration. For example, to fetch a value without a type specifier and fallback to `$fallback`, the following is required: $ git config core.foo || echo "$fallback" This is fine for most values, but can be tricky for difficult-to-express `$fallback`'s, like ANSI color codes. This motivates `--get-color`, which is a one-off exception to the normal type specifier rules wherein a user specifies both the configuration variable and an optional fallback. Both are formatted according to their type specifier, which eases the burden on the user to ensure that values are correctly formatted. This commit (and those following it in this series) aim to eventually replace `--get-color` with a consistent alternative. By introducing `--default`, we allow the `--get-color` action to be promoted to a `--type=color` type specifier, retaining the "fallback" behavior via the `--default` flag introduced in this commit. For example, we aim to replace: $ git config --get-color variable [default] [...] with: $ git config --default default --type=color variable [...] Values filled by `--default` behave exactly as if they were present in the affected configuration file; they will be parsed by type specifiers without the knowledge that they are not themselves present in the configuration. Specifically, this means that the following will work: $ git config --int --default 1M does.not.exist 1048576 In subsequent commits, we will offer `--type=color`, which (in conjunction with `--default`) will be sufficient to replace `--get-color`. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-10 00:18:26 +00:00
if (!values.nr && default_value) {
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
struct key_value_info kvi = KVI_INIT;
builtin/config: introduce `--default` For some use cases, callers of the `git-config(1)` builtin would like to fallback to default values when the variable asked for does not exist. In addition, users would like to use existing type specifiers to ensure that values are parsed correctly when they do exist in the configuration. For example, to fetch a value without a type specifier and fallback to `$fallback`, the following is required: $ git config core.foo || echo "$fallback" This is fine for most values, but can be tricky for difficult-to-express `$fallback`'s, like ANSI color codes. This motivates `--get-color`, which is a one-off exception to the normal type specifier rules wherein a user specifies both the configuration variable and an optional fallback. Both are formatted according to their type specifier, which eases the burden on the user to ensure that values are correctly formatted. This commit (and those following it in this series) aim to eventually replace `--get-color` with a consistent alternative. By introducing `--default`, we allow the `--get-color` action to be promoted to a `--type=color` type specifier, retaining the "fallback" behavior via the `--default` flag introduced in this commit. For example, we aim to replace: $ git config --get-color variable [default] [...] with: $ git config --default default --type=color variable [...] Values filled by `--default` behave exactly as if they were present in the affected configuration file; they will be parsed by type specifiers without the knowledge that they are not themselves present in the configuration. Specifically, this means that the following will work: $ git config --int --default 1M does.not.exist 1048576 In subsequent commits, we will offer `--type=color`, which (in conjunction with `--default`) will be sufficient to replace `--get-color`. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-10 00:18:26 +00:00
struct strbuf *item;
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
kvi_from_param(&kvi);
builtin/config: introduce `--default` For some use cases, callers of the `git-config(1)` builtin would like to fallback to default values when the variable asked for does not exist. In addition, users would like to use existing type specifiers to ensure that values are parsed correctly when they do exist in the configuration. For example, to fetch a value without a type specifier and fallback to `$fallback`, the following is required: $ git config core.foo || echo "$fallback" This is fine for most values, but can be tricky for difficult-to-express `$fallback`'s, like ANSI color codes. This motivates `--get-color`, which is a one-off exception to the normal type specifier rules wherein a user specifies both the configuration variable and an optional fallback. Both are formatted according to their type specifier, which eases the burden on the user to ensure that values are correctly formatted. This commit (and those following it in this series) aim to eventually replace `--get-color` with a consistent alternative. By introducing `--default`, we allow the `--get-color` action to be promoted to a `--type=color` type specifier, retaining the "fallback" behavior via the `--default` flag introduced in this commit. For example, we aim to replace: $ git config --get-color variable [default] [...] with: $ git config --default default --type=color variable [...] Values filled by `--default` behave exactly as if they were present in the affected configuration file; they will be parsed by type specifiers without the knowledge that they are not themselves present in the configuration. Specifically, this means that the following will work: $ git config --int --default 1M does.not.exist 1048576 In subsequent commits, we will offer `--type=color`, which (in conjunction with `--default`) will be sufficient to replace `--get-color`. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-10 00:18:26 +00:00
ALLOC_GROW(values.items, values.nr + 1, values.alloc);
item = &values.items[values.nr++];
strbuf_init(item, 0);
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
if (format_config(item, key_, default_value, &kvi) < 0)
builtin/config: introduce `--default` For some use cases, callers of the `git-config(1)` builtin would like to fallback to default values when the variable asked for does not exist. In addition, users would like to use existing type specifiers to ensure that values are parsed correctly when they do exist in the configuration. For example, to fetch a value without a type specifier and fallback to `$fallback`, the following is required: $ git config core.foo || echo "$fallback" This is fine for most values, but can be tricky for difficult-to-express `$fallback`'s, like ANSI color codes. This motivates `--get-color`, which is a one-off exception to the normal type specifier rules wherein a user specifies both the configuration variable and an optional fallback. Both are formatted according to their type specifier, which eases the burden on the user to ensure that values are correctly formatted. This commit (and those following it in this series) aim to eventually replace `--get-color` with a consistent alternative. By introducing `--default`, we allow the `--get-color` action to be promoted to a `--type=color` type specifier, retaining the "fallback" behavior via the `--default` flag introduced in this commit. For example, we aim to replace: $ git config --get-color variable [default] [...] with: $ git config --default default --type=color variable [...] Values filled by `--default` behave exactly as if they were present in the affected configuration file; they will be parsed by type specifiers without the knowledge that they are not themselves present in the configuration. Specifically, this means that the following will work: $ git config --int --default 1M does.not.exist 1048576 In subsequent commits, we will offer `--type=color`, which (in conjunction with `--default`) will be sufficient to replace `--get-color`. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-10 00:18:26 +00:00
die(_("failed to format default config value: %s"),
default_value);
}
git-config: do not complain about duplicate entries If git-config is asked for a single value, it will complain and exit with an error if it finds multiple instances of that value. This is unlike the usual internal config parsing, however, which will generally overwrite previous values, leaving only the final one. For example: [set a multivar] $ git config user.email one@example.com $ git config --add user.email two@example.com [use the internal parser to fetch it] $ git var GIT_AUTHOR_IDENT Your Name <two@example.com> ... [use git-config to fetch it] $ git config user.email one@example.com error: More than one value for the key user.email: two@example.com This overwriting behavior is critical for the regular parser, which starts with the lowest-priority file (e.g., /etc/gitconfig) and proceeds to the highest-priority file ($GIT_DIR/config). Overwriting yields the highest priority value at the end. Git-config solves this problem by implementing its own parsing. It goes from highest to lowest priorty, but does not proceed to the next file if it has seen a value. So in practice, this distinction never mattered much, because it only triggered for values in the same file. And there was not much point in doing that; the real value is in overwriting values from lower-priority files. However, this changed with the implementation of config include files. Now we might see an include overriding a value from the parent file, which is a sensible thing to do, but git-config will flag as a duplication. This patch drops the duplicate detection for git-config and switches to a pure-overwrite model (for the single case; --get-all can still be used if callers want to do something more fancy). As is shown by the modifications to the test suite, this is a user-visible change in behavior. An alternative would be to just change the include case, but this is much cleaner for a few reasons: 1. If you change the include case, then to what? If you just stop parsing includes after getting a value, then you will get a _different_ answer than the regular config parser (you'll get the first value instead of the last value). So you'd want to implement overwrite semantics anyway. 2. Even though it is a change in behavior for git-config, it is bringing us in line with what the internal parsers already do. 3. The file-order reimplementation is the only thing keeping us from sharing more code with the internal config parser, which will help keep differences to a minimum. Going under the assumption that the primary purpose of git-config is to behave identically to how git's internal parsing works, this change can be seen as a bug-fix. Signed-off-by: Jeff King <peff@peff.net>
2012-10-23 20:52:44 +00:00
ret = !values.nr;
config: add include directive It can be useful to split your ~/.gitconfig across multiple files. For example, you might have a "main" file which is used on many machines, but a small set of per-machine tweaks. Or you may want to make some of your config public (e.g., clever aliases) while keeping other data back (e.g., your name or other identifying information). Or you may want to include a number of config options in some subset of your repos without copying and pasting (e.g., you want to reference them from the .git/config of participating repos). This patch introduces an include directive for config files. It looks like: [include] path = /path/to/file This is syntactically backwards-compatible with existing git config parsers (i.e., they will see it as another config entry and ignore it unless you are looking up include.path). The implementation provides a "git_config_include" callback which wraps regular config callbacks. Callers can pass it to git_config_from_file, and it will transparently follow any include directives, passing all of the discovered options to the real callback. Include directives are turned on automatically for "regular" git config parsing. This includes calls to git_config, as well as calls to the "git config" program that do not specify a single file (e.g., using "-f", "--global", etc). They are not turned on in other cases, including: 1. Parsing of other config-like files, like .gitmodules. There isn't a real need, and I'd rather be conservative and avoid unnecessary incompatibility or confusion. 2. Reading single files via "git config". This is for two reasons: a. backwards compatibility with scripts looking at config-like files. b. inspection of a specific file probably means you care about just what's in that file, not a general lookup for "do we have this value anywhere at all". If that is not the case, the caller can always specify "--includes". 3. Writing files via "git config"; we want to treat include.* variables as literal items to be copied (or modified), and not expand them. So "git config --unset-all foo.bar" would operate _only_ on .git/config, not any of its included files (just as it also does not operate on ~/.gitconfig). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 09:54:04 +00:00
for (i = 0; i < values.nr; i++) {
struct strbuf *buf = values.items + i;
git-config: do not complain about duplicate entries If git-config is asked for a single value, it will complain and exit with an error if it finds multiple instances of that value. This is unlike the usual internal config parsing, however, which will generally overwrite previous values, leaving only the final one. For example: [set a multivar] $ git config user.email one@example.com $ git config --add user.email two@example.com [use the internal parser to fetch it] $ git var GIT_AUTHOR_IDENT Your Name <two@example.com> ... [use git-config to fetch it] $ git config user.email one@example.com error: More than one value for the key user.email: two@example.com This overwriting behavior is critical for the regular parser, which starts with the lowest-priority file (e.g., /etc/gitconfig) and proceeds to the highest-priority file ($GIT_DIR/config). Overwriting yields the highest priority value at the end. Git-config solves this problem by implementing its own parsing. It goes from highest to lowest priorty, but does not proceed to the next file if it has seen a value. So in practice, this distinction never mattered much, because it only triggered for values in the same file. And there was not much point in doing that; the real value is in overwriting values from lower-priority files. However, this changed with the implementation of config include files. Now we might see an include overriding a value from the parent file, which is a sensible thing to do, but git-config will flag as a duplication. This patch drops the duplicate detection for git-config and switches to a pure-overwrite model (for the single case; --get-all can still be used if callers want to do something more fancy). As is shown by the modifications to the test suite, this is a user-visible change in behavior. An alternative would be to just change the include case, but this is much cleaner for a few reasons: 1. If you change the include case, then to what? If you just stop parsing includes after getting a value, then you will get a _different_ answer than the regular config parser (you'll get the first value instead of the last value). So you'd want to implement overwrite semantics anyway. 2. Even though it is a change in behavior for git-config, it is bringing us in line with what the internal parsers already do. 3. The file-order reimplementation is the only thing keeping us from sharing more code with the internal config parser, which will help keep differences to a minimum. Going under the assumption that the primary purpose of git-config is to behave identically to how git's internal parsing works, this change can be seen as a bug-fix. Signed-off-by: Jeff King <peff@peff.net>
2012-10-23 20:52:44 +00:00
if (do_all || i == values.nr - 1)
fwrite(buf->buf, 1, buf->len, stdout);
strbuf_release(buf);
}
free(values.items);
free_strings:
free(key);
if (key_regexp) {
regfree(key_regexp);
free(key_regexp);
}
if (regexp) {
regfree(regexp);
free(regexp);
}
return ret;
}
static char *normalize_value(const char *key, const char *value,
struct key_value_info *kvi)
{
if (!value)
return NULL;
if (type == 0 || type == TYPE_PATH || type == TYPE_EXPIRY_DATE)
/*
* We don't do normalization for TYPE_PATH here: If
* the path is like ~/foobar/, we prefer to store
* "~/foobar/" in the config file, and to expand the ~
* when retrieving the value.
* Also don't do normalization for expiry dates.
*/
return xstrdup(value);
if (type == TYPE_INT)
return xstrfmt("%"PRId64, git_config_int64(key, value, kvi));
if (type == TYPE_BOOL)
return xstrdup(git_config_bool(key, value) ? "true" : "false");
if (type == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key, value, kvi, &is_bool);
if (!is_bool)
return xstrfmt("%d", v);
else
return xstrdup(v ? "true" : "false");
}
if (type == TYPE_BOOL_OR_STR) {
int v = git_parse_maybe_bool(value);
if (v < 0)
return xstrdup(value);
else
return xstrdup(v ? "true" : "false");
}
if (type == TYPE_COLOR) {
char v[COLOR_MAXLEN];
if (git_config_color(v, key, value))
die(_("cannot parse color '%s'"), value);
/*
* The contents of `v` now contain an ANSI escape
* sequence, not suitable for including within a
* configuration file. Treat the above as a
* "sanity-check", and return the given value, which we
* know is representable as valid color code.
*/
return xstrdup(value);
}
BUG("cannot normalize type %d", type);
}
static int get_color_found;
static const char *get_color_slot;
static const char *get_colorbool_slot;
static char parsed_color[COLOR_MAXLEN];
static int git_get_color_config(const char *var, const char *value,
config: add ctx arg to config_fn_t Add a new "const struct config_context *ctx" arg to config_fn_t to hold additional information about the config iteration operation. config_context has a "struct key_value_info kvi" member that holds metadata about the config source being read (e.g. what kind of config source it is, the filename, etc). In this series, we're only interested in .kvi, so we could have just used "struct key_value_info" as an arg, but config_context makes it possible to add/adjust members in the future without changing the config_fn_t signature. We could also consider other ways of organizing the args (e.g. moving the config name and value into config_context or key_value_info), but in my experiments, the incremental benefit doesn't justify the added complexity (e.g. a config_fn_t will sometimes invoke another config_fn_t but with a different config value). In subsequent commits, the .kvi member will replace the global "struct config_reader" in config.c, making config iteration a global-free operation. It requires much more work for the machinery to provide meaningful values of .kvi, so for now, merely change the signature and call sites, pass NULL as a placeholder value, and don't rely on the arg in any meaningful way. Most of the changes are performed by contrib/coccinelle/config_fn_ctx.pending.cocci, which, for every config_fn_t: - Modifies the signature to accept "const struct config_context *ctx" - Passes "ctx" to any inner config_fn_t, if needed - Adds UNUSED attributes to "ctx", if needed Most config_fn_t instances are easily identified by seeing if they are called by the various config functions. Most of the remaining ones are manually named in the .cocci patch. Manual cleanups are still needed, but the majority of it is trivial; it's either adjusting config_fn_t that the .cocci patch didn't catch, or adding forward declarations of "struct config_context ctx" to make the signatures make sense. The non-trivial changes are in cases where we are invoking a config_fn_t outside of config machinery, and we now need to decide what value of "ctx" to pass. These cases are: - trace2/tr2_cfg.c:tr2_cfg_set_fl() This is indirectly called by git_config_set() so that the trace2 machinery can notice the new config values and update its settings using the tr2 config parsing function, i.e. tr2_cfg_cb(). - builtin/checkout.c:checkout_main() This calls git_xmerge_config() as a shorthand for parsing a CLI arg. This might be worth refactoring away in the future, since git_xmerge_config() can call git_default_config(), which can do much more than just parsing. Handle them by creating a KVI_INIT macro that initializes "struct key_value_info" to a reasonable default, and use that to construct the "ctx" arg. Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:22 +00:00
const struct config_context *ctx UNUSED,
void *cb UNUSED)
{
if (!strcmp(var, get_color_slot)) {
if (!value)
config_error_nonbool(var);
if (color_parse(value, parsed_color) < 0)
return -1;
get_color_found = 1;
}
return 0;
}
config: fix parsing of "git config --get-color some.key -1" Most of git-config's command line options use OPT_BIT to choose an action, and then parse the non-option arguments in a context-dependent way. However, --get-color and --get-colorbool are unlike the rest of the options, in that they are OPT_STRING, taking the option name as a parameter. This generally works, because we then use the presence of those strings to set an action bit anyway. But it does mean that the option-parser will continue looking for options even after the key (because it is not a non-option; it is an argument to an option). And running: git config --get-color some.key -1 (to use "-1" as the default color spec) will barf, claiming that "-1" is not an option. Instead, we should treat --get-color and --get-colorbool as action bits, just like --add, --get, and all the other actions, and then check that the non-option arguments we got are sane. This fixes the weirdness above, and makes those two options like all the others. This "fixes" a test in t4026, which checked that feeding "-2" as a color should fail (it does fail, but prior to this patch, because parseopt barfed, not because we actually ever tried to parse the color). This also catches other errors, like: git config --get-color some.key black blue which previously silently ignored "blue" (and now will complain that you gave too many arguments). There are some possible regressions, though. We now disallow these, which currently do what you would expect: # specifying other options after the action git config --get-color some.key --file whatever # using long-arg syntax git config --get-color=some.key However, we have never advertised these in the documentation, and in fact they did not work in some older versions of git. The behavior was apparently switched as an accidental side effect of d64ec16 (git config: reorganize to use parseopt, 2009-02-21). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-20 15:15:51 +00:00
static void get_color(const char *var, const char *def_color)
{
config: fix parsing of "git config --get-color some.key -1" Most of git-config's command line options use OPT_BIT to choose an action, and then parse the non-option arguments in a context-dependent way. However, --get-color and --get-colorbool are unlike the rest of the options, in that they are OPT_STRING, taking the option name as a parameter. This generally works, because we then use the presence of those strings to set an action bit anyway. But it does mean that the option-parser will continue looking for options even after the key (because it is not a non-option; it is an argument to an option). And running: git config --get-color some.key -1 (to use "-1" as the default color spec) will barf, claiming that "-1" is not an option. Instead, we should treat --get-color and --get-colorbool as action bits, just like --add, --get, and all the other actions, and then check that the non-option arguments we got are sane. This fixes the weirdness above, and makes those two options like all the others. This "fixes" a test in t4026, which checked that feeding "-2" as a color should fail (it does fail, but prior to this patch, because parseopt barfed, not because we actually ever tried to parse the color). This also catches other errors, like: git config --get-color some.key black blue which previously silently ignored "blue" (and now will complain that you gave too many arguments). There are some possible regressions, though. We now disallow these, which currently do what you would expect: # specifying other options after the action git config --get-color some.key --file whatever # using long-arg syntax git config --get-color=some.key However, we have never advertised these in the documentation, and in fact they did not work in some older versions of git. The behavior was apparently switched as an accidental side effect of d64ec16 (git config: reorganize to use parseopt, 2009-02-21). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-20 15:15:51 +00:00
get_color_slot = var;
get_color_found = 0;
parsed_color[0] = '\0';
config_with_options(git_get_color_config, NULL,
config: pass 'repo' directly to 'config_with_options()' Add a 'struct repository' argument to 'config_with_options()' and remove the 'repo' field from 'struct git_config_source'. A 'struct repository' instance was originally added to the config source in e3e8bf046e9 (submodule-config: pass repo upon blob config read, 2021-08-16) to improve how submodule blob config content was accessed. At the time, this was the only use for a 'repository' instance, so it was naturally added only where it was needed: to 'struct git_config_source'. However, in upcoming patches, 'config_with_options()' will need the repository instance to access extension information (regardless of whether a 'config_source' exists). To make the 'struct repository' instance more easily accessible, move it into the function's arguments. Update all callers of 'config_with_options()' to pass the appropriate 'repo' value: * in 'builtin/config.c', use 'the_repository' * in 'submodule--config.c', use the 'repo' arg in 'config_from_gitmodules()' * in 'read_[very_]early_config()' & 'read_protected_config()', set 'repo' to NULL (repository instances aren't available there) * in 'populate_remote_urls()', use the repo instance that has been added to the 'struct config_include_data' * in 'repo_read_config()', use the given 'repo' arg Finally, note that this patch eliminates the fallback to 'the_repository' that previously existed for the 'config_source' repo instance if it was NULL. The fallback is no longer necessary, as the 'repo' is set explicitly in all cases where it is needed. Signed-off-by: Victoria Dye <vdye@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-05-26 01:32:59 +00:00
&given_config_source, the_repository,
&config_options);
if (!get_color_found && def_color) {
if (color_parse(def_color, parsed_color) < 0)
die(_("unable to parse default color value"));
}
fputs(parsed_color, stdout);
}
static int get_colorbool_found;
static int get_diff_color_found;
static int get_color_ui_found;
static int git_get_colorbool_config(const char *var, const char *value,
config: add ctx arg to config_fn_t Add a new "const struct config_context *ctx" arg to config_fn_t to hold additional information about the config iteration operation. config_context has a "struct key_value_info kvi" member that holds metadata about the config source being read (e.g. what kind of config source it is, the filename, etc). In this series, we're only interested in .kvi, so we could have just used "struct key_value_info" as an arg, but config_context makes it possible to add/adjust members in the future without changing the config_fn_t signature. We could also consider other ways of organizing the args (e.g. moving the config name and value into config_context or key_value_info), but in my experiments, the incremental benefit doesn't justify the added complexity (e.g. a config_fn_t will sometimes invoke another config_fn_t but with a different config value). In subsequent commits, the .kvi member will replace the global "struct config_reader" in config.c, making config iteration a global-free operation. It requires much more work for the machinery to provide meaningful values of .kvi, so for now, merely change the signature and call sites, pass NULL as a placeholder value, and don't rely on the arg in any meaningful way. Most of the changes are performed by contrib/coccinelle/config_fn_ctx.pending.cocci, which, for every config_fn_t: - Modifies the signature to accept "const struct config_context *ctx" - Passes "ctx" to any inner config_fn_t, if needed - Adds UNUSED attributes to "ctx", if needed Most config_fn_t instances are easily identified by seeing if they are called by the various config functions. Most of the remaining ones are manually named in the .cocci patch. Manual cleanups are still needed, but the majority of it is trivial; it's either adjusting config_fn_t that the .cocci patch didn't catch, or adding forward declarations of "struct config_context ctx" to make the signatures make sense. The non-trivial changes are in cases where we are invoking a config_fn_t outside of config machinery, and we now need to decide what value of "ctx" to pass. These cases are: - trace2/tr2_cfg.c:tr2_cfg_set_fl() This is indirectly called by git_config_set() so that the trace2 machinery can notice the new config values and update its settings using the tr2 config parsing function, i.e. tr2_cfg_cb(). - builtin/checkout.c:checkout_main() This calls git_xmerge_config() as a shorthand for parsing a CLI arg. This might be worth refactoring away in the future, since git_xmerge_config() can call git_default_config(), which can do much more than just parsing. Handle them by creating a KVI_INIT macro that initializes "struct key_value_info" to a reasonable default, and use that to construct the "ctx" arg. Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:22 +00:00
const struct config_context *ctx UNUSED,
void *data UNUSED)
{
if (!strcmp(var, get_colorbool_slot))
get_colorbool_found = git_config_colorbool(var, value);
else if (!strcmp(var, "diff.color"))
get_diff_color_found = git_config_colorbool(var, value);
else if (!strcmp(var, "color.ui"))
get_color_ui_found = git_config_colorbool(var, value);
return 0;
}
config: fix parsing of "git config --get-color some.key -1" Most of git-config's command line options use OPT_BIT to choose an action, and then parse the non-option arguments in a context-dependent way. However, --get-color and --get-colorbool are unlike the rest of the options, in that they are OPT_STRING, taking the option name as a parameter. This generally works, because we then use the presence of those strings to set an action bit anyway. But it does mean that the option-parser will continue looking for options even after the key (because it is not a non-option; it is an argument to an option). And running: git config --get-color some.key -1 (to use "-1" as the default color spec) will barf, claiming that "-1" is not an option. Instead, we should treat --get-color and --get-colorbool as action bits, just like --add, --get, and all the other actions, and then check that the non-option arguments we got are sane. This fixes the weirdness above, and makes those two options like all the others. This "fixes" a test in t4026, which checked that feeding "-2" as a color should fail (it does fail, but prior to this patch, because parseopt barfed, not because we actually ever tried to parse the color). This also catches other errors, like: git config --get-color some.key black blue which previously silently ignored "blue" (and now will complain that you gave too many arguments). There are some possible regressions, though. We now disallow these, which currently do what you would expect: # specifying other options after the action git config --get-color some.key --file whatever # using long-arg syntax git config --get-color=some.key However, we have never advertised these in the documentation, and in fact they did not work in some older versions of git. The behavior was apparently switched as an accidental side effect of d64ec16 (git config: reorganize to use parseopt, 2009-02-21). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-20 15:15:51 +00:00
static int get_colorbool(const char *var, int print)
{
config: fix parsing of "git config --get-color some.key -1" Most of git-config's command line options use OPT_BIT to choose an action, and then parse the non-option arguments in a context-dependent way. However, --get-color and --get-colorbool are unlike the rest of the options, in that they are OPT_STRING, taking the option name as a parameter. This generally works, because we then use the presence of those strings to set an action bit anyway. But it does mean that the option-parser will continue looking for options even after the key (because it is not a non-option; it is an argument to an option). And running: git config --get-color some.key -1 (to use "-1" as the default color spec) will barf, claiming that "-1" is not an option. Instead, we should treat --get-color and --get-colorbool as action bits, just like --add, --get, and all the other actions, and then check that the non-option arguments we got are sane. This fixes the weirdness above, and makes those two options like all the others. This "fixes" a test in t4026, which checked that feeding "-2" as a color should fail (it does fail, but prior to this patch, because parseopt barfed, not because we actually ever tried to parse the color). This also catches other errors, like: git config --get-color some.key black blue which previously silently ignored "blue" (and now will complain that you gave too many arguments). There are some possible regressions, though. We now disallow these, which currently do what you would expect: # specifying other options after the action git config --get-color some.key --file whatever # using long-arg syntax git config --get-color=some.key However, we have never advertised these in the documentation, and in fact they did not work in some older versions of git. The behavior was apparently switched as an accidental side effect of d64ec16 (git config: reorganize to use parseopt, 2009-02-21). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-20 15:15:51 +00:00
get_colorbool_slot = var;
get_colorbool_found = -1;
get_diff_color_found = -1;
get_color_ui_found = -1;
config_with_options(git_get_colorbool_config, NULL,
config: pass 'repo' directly to 'config_with_options()' Add a 'struct repository' argument to 'config_with_options()' and remove the 'repo' field from 'struct git_config_source'. A 'struct repository' instance was originally added to the config source in e3e8bf046e9 (submodule-config: pass repo upon blob config read, 2021-08-16) to improve how submodule blob config content was accessed. At the time, this was the only use for a 'repository' instance, so it was naturally added only where it was needed: to 'struct git_config_source'. However, in upcoming patches, 'config_with_options()' will need the repository instance to access extension information (regardless of whether a 'config_source' exists). To make the 'struct repository' instance more easily accessible, move it into the function's arguments. Update all callers of 'config_with_options()' to pass the appropriate 'repo' value: * in 'builtin/config.c', use 'the_repository' * in 'submodule--config.c', use the 'repo' arg in 'config_from_gitmodules()' * in 'read_[very_]early_config()' & 'read_protected_config()', set 'repo' to NULL (repository instances aren't available there) * in 'populate_remote_urls()', use the repo instance that has been added to the 'struct config_include_data' * in 'repo_read_config()', use the given 'repo' arg Finally, note that this patch eliminates the fallback to 'the_repository' that previously existed for the 'config_source' repo instance if it was NULL. The fallback is no longer necessary, as the 'repo' is set explicitly in all cases where it is needed. Signed-off-by: Victoria Dye <vdye@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-05-26 01:32:59 +00:00
&given_config_source, the_repository,
&config_options);
if (get_colorbool_found < 0) {
if (!strcmp(get_colorbool_slot, "color.diff"))
get_colorbool_found = get_diff_color_found;
if (get_colorbool_found < 0)
get_colorbool_found = get_color_ui_found;
}
if (get_colorbool_found < 0)
/* default value if none found in config */
get_colorbool_found = GIT_COLOR_AUTO;
color: delay auto-color decision until point of use When we read a color value either from a config file or from the command line, we use git_config_colorbool to convert it from the tristate always/never/auto into a single yes/no boolean value. This has some timing implications with respect to starting a pager. If we start (or decide not to start) the pager before checking the colorbool, everything is fine. Either isatty(1) will give us the right information, or we will properly check for pager_in_use(). However, if we decide to start a pager after we have checked the colorbool, things are not so simple. If stdout is a tty, then we will have already decided to use color. However, the user may also have configured color.pager not to use color with the pager. In this case, we need to actually turn off color. Unfortunately, the pager code has no idea which color variables were turned on (and there are many of them throughout the code, and they may even have been manipulated after the colorbool selection by something like "--color" on the command line). This bug can be seen any time a pager is started after config and command line options are checked. This has affected "git diff" since 89d07f7 (diff: don't run pager if user asked for a diff style exit code, 2007-08-12). It has also affect the log family since 1fda91b (Fix 'git log' early pager startup error case, 2010-08-24). This patch splits the notion of parsing a colorbool and actually checking the configuration. The "use_color" variables now have an additional possible value, GIT_COLOR_AUTO. Users of the variable should use the new "want_color()" wrapper, which will lazily determine and cache the auto-color decision. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-18 05:04:23 +00:00
get_colorbool_found = want_color(get_colorbool_found);
if (print) {
printf("%s\n", get_colorbool_found ? "true" : "false");
return 0;
} else
return get_colorbool_found ? 0 : 1;
}
static void check_write(void)
{
if (!given_config_source.file && !startup_info->have_repository)
die(_("not in a git directory"));
if (given_config_source.use_stdin)
die(_("writing to stdin is not supported"));
if (given_config_source.blob)
die(_("writing config blobs is not supported"));
}
struct urlmatch_current_candidate_value {
char value_is_null;
struct strbuf value;
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
struct key_value_info kvi;
};
config: add ctx arg to config_fn_t Add a new "const struct config_context *ctx" arg to config_fn_t to hold additional information about the config iteration operation. config_context has a "struct key_value_info kvi" member that holds metadata about the config source being read (e.g. what kind of config source it is, the filename, etc). In this series, we're only interested in .kvi, so we could have just used "struct key_value_info" as an arg, but config_context makes it possible to add/adjust members in the future without changing the config_fn_t signature. We could also consider other ways of organizing the args (e.g. moving the config name and value into config_context or key_value_info), but in my experiments, the incremental benefit doesn't justify the added complexity (e.g. a config_fn_t will sometimes invoke another config_fn_t but with a different config value). In subsequent commits, the .kvi member will replace the global "struct config_reader" in config.c, making config iteration a global-free operation. It requires much more work for the machinery to provide meaningful values of .kvi, so for now, merely change the signature and call sites, pass NULL as a placeholder value, and don't rely on the arg in any meaningful way. Most of the changes are performed by contrib/coccinelle/config_fn_ctx.pending.cocci, which, for every config_fn_t: - Modifies the signature to accept "const struct config_context *ctx" - Passes "ctx" to any inner config_fn_t, if needed - Adds UNUSED attributes to "ctx", if needed Most config_fn_t instances are easily identified by seeing if they are called by the various config functions. Most of the remaining ones are manually named in the .cocci patch. Manual cleanups are still needed, but the majority of it is trivial; it's either adjusting config_fn_t that the .cocci patch didn't catch, or adding forward declarations of "struct config_context ctx" to make the signatures make sense. The non-trivial changes are in cases where we are invoking a config_fn_t outside of config machinery, and we now need to decide what value of "ctx" to pass. These cases are: - trace2/tr2_cfg.c:tr2_cfg_set_fl() This is indirectly called by git_config_set() so that the trace2 machinery can notice the new config values and update its settings using the tr2 config parsing function, i.e. tr2_cfg_cb(). - builtin/checkout.c:checkout_main() This calls git_xmerge_config() as a shorthand for parsing a CLI arg. This might be worth refactoring away in the future, since git_xmerge_config() can call git_default_config(), which can do much more than just parsing. Handle them by creating a KVI_INIT macro that initializes "struct key_value_info" to a reasonable default, and use that to construct the "ctx" arg. Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:22 +00:00
static int urlmatch_collect_fn(const char *var, const char *value,
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
const struct config_context *ctx,
config: add ctx arg to config_fn_t Add a new "const struct config_context *ctx" arg to config_fn_t to hold additional information about the config iteration operation. config_context has a "struct key_value_info kvi" member that holds metadata about the config source being read (e.g. what kind of config source it is, the filename, etc). In this series, we're only interested in .kvi, so we could have just used "struct key_value_info" as an arg, but config_context makes it possible to add/adjust members in the future without changing the config_fn_t signature. We could also consider other ways of organizing the args (e.g. moving the config name and value into config_context or key_value_info), but in my experiments, the incremental benefit doesn't justify the added complexity (e.g. a config_fn_t will sometimes invoke another config_fn_t but with a different config value). In subsequent commits, the .kvi member will replace the global "struct config_reader" in config.c, making config iteration a global-free operation. It requires much more work for the machinery to provide meaningful values of .kvi, so for now, merely change the signature and call sites, pass NULL as a placeholder value, and don't rely on the arg in any meaningful way. Most of the changes are performed by contrib/coccinelle/config_fn_ctx.pending.cocci, which, for every config_fn_t: - Modifies the signature to accept "const struct config_context *ctx" - Passes "ctx" to any inner config_fn_t, if needed - Adds UNUSED attributes to "ctx", if needed Most config_fn_t instances are easily identified by seeing if they are called by the various config functions. Most of the remaining ones are manually named in the .cocci patch. Manual cleanups are still needed, but the majority of it is trivial; it's either adjusting config_fn_t that the .cocci patch didn't catch, or adding forward declarations of "struct config_context ctx" to make the signatures make sense. The non-trivial changes are in cases where we are invoking a config_fn_t outside of config machinery, and we now need to decide what value of "ctx" to pass. These cases are: - trace2/tr2_cfg.c:tr2_cfg_set_fl() This is indirectly called by git_config_set() so that the trace2 machinery can notice the new config values and update its settings using the tr2 config parsing function, i.e. tr2_cfg_cb(). - builtin/checkout.c:checkout_main() This calls git_xmerge_config() as a shorthand for parsing a CLI arg. This might be worth refactoring away in the future, since git_xmerge_config() can call git_default_config(), which can do much more than just parsing. Handle them by creating a KVI_INIT macro that initializes "struct key_value_info" to a reasonable default, and use that to construct the "ctx" arg. Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:22 +00:00
void *cb)
{
struct string_list *values = cb;
struct string_list_item *item = string_list_insert(values, var);
struct urlmatch_current_candidate_value *matched = item->util;
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
const struct key_value_info *kvi = ctx->kvi;
if (!matched) {
matched = xmalloc(sizeof(*matched));
strbuf_init(&matched->value, 0);
item->util = matched;
} else {
strbuf_reset(&matched->value);
}
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
matched->kvi = *kvi;
if (value) {
strbuf_addstr(&matched->value, value);
matched->value_is_null = 0;
} else {
matched->value_is_null = 1;
}
return 0;
}
static int get_urlmatch(const char *var, const char *url)
{
int ret;
char *section_tail;
struct string_list_item *item;
struct urlmatch_config config = URLMATCH_CONFIG_INIT;
struct string_list values = STRING_LIST_INIT_DUP;
config.collect_fn = urlmatch_collect_fn;
config.cascade_fn = NULL;
config.cb = &values;
if (!url_normalize(url, &config.url))
die("%s", config.url.err);
config.section = xstrdup_tolower(var);
section_tail = strchr(config.section, '.');
if (section_tail) {
*section_tail = '\0';
config.key = section_tail + 1;
show_keys = 0;
} else {
config.key = NULL;
show_keys = 1;
}
config_with_options(urlmatch_config_entry, &config,
config: pass 'repo' directly to 'config_with_options()' Add a 'struct repository' argument to 'config_with_options()' and remove the 'repo' field from 'struct git_config_source'. A 'struct repository' instance was originally added to the config source in e3e8bf046e9 (submodule-config: pass repo upon blob config read, 2021-08-16) to improve how submodule blob config content was accessed. At the time, this was the only use for a 'repository' instance, so it was naturally added only where it was needed: to 'struct git_config_source'. However, in upcoming patches, 'config_with_options()' will need the repository instance to access extension information (regardless of whether a 'config_source' exists). To make the 'struct repository' instance more easily accessible, move it into the function's arguments. Update all callers of 'config_with_options()' to pass the appropriate 'repo' value: * in 'builtin/config.c', use 'the_repository' * in 'submodule--config.c', use the 'repo' arg in 'config_from_gitmodules()' * in 'read_[very_]early_config()' & 'read_protected_config()', set 'repo' to NULL (repository instances aren't available there) * in 'populate_remote_urls()', use the repo instance that has been added to the 'struct config_include_data' * in 'repo_read_config()', use the given 'repo' arg Finally, note that this patch eliminates the fallback to 'the_repository' that previously existed for the 'config_source' repo instance if it was NULL. The fallback is no longer necessary, as the 'repo' is set explicitly in all cases where it is needed. Signed-off-by: Victoria Dye <vdye@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-05-26 01:32:59 +00:00
&given_config_source, the_repository,
&config_options);
ret = !values.nr;
for_each_string_list_item(item, &values) {
struct urlmatch_current_candidate_value *matched = item->util;
struct strbuf buf = STRBUF_INIT;
format_config(&buf, item->string,
config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-28 19:26:25 +00:00
matched->value_is_null ? NULL : matched->value.buf,
&matched->kvi);
fwrite(buf.buf, 1, buf.len, stdout);
strbuf_release(&buf);
strbuf_release(&matched->value);
}
urlmatch_config_release(&config);
string_list_clear(&values, 1);
free(config.url.url);
free((void *)config.section);
return ret;
}
static char *default_user_config(void)
{
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf,
_("# This is Git's per-user configuration file.\n"
"[user]\n"
"# Please adapt and uncomment the following lines:\n"
"# name = %s\n"
"# email = %s\n"),
ident_default_name(),
ident_default_email());
return strbuf_detach(&buf, NULL);
}
static void handle_config_location(const char *prefix)
{
if (use_global_config + use_system_config + use_local_config +
worktree: add per-worktree config files A new repo extension is added, worktreeConfig. When it is present: - Repository config reading by default includes $GIT_DIR/config _and_ $GIT_DIR/config.worktree. "config" file remains shared in multiple worktree setup. - The special treatment for core.bare and core.worktree, to stay effective only in main worktree, is gone. These config settings are supposed to be in config.worktree. This extension is most useful in multiple worktree setup because you now have an option to store per-worktree config (which is either .git/config.worktree for main worktree, or .git/worktrees/xx/config.worktree for linked ones). This extension can be used in single worktree mode, even though it's pretty much useless (but this can happen after you remove all linked worktrees and move back to single worktree). "git config" reads from both "config" and "config.worktree" by default (i.e. without either --user, --file...) when this extension is present. Default writes still go to "config", not "config.worktree". A new option --worktree is added for that (*). Since a new repo extension is introduced, existing git binaries should refuse to access to the repo (both from main and linked worktrees). So they will not misread the config file (i.e. skip the config.worktree part). They may still accidentally write to the config file anyway if they use with "git config --file <path>". This design places a bet on the assumption that the majority of config variables are shared so it is the default mode. A safer move would be default writes go to per-worktree file, so that accidental changes are isolated. (*) "git config --worktree" points back to "config" file when this extension is not present and there is only one worktree so that it works in any both single and multiple worktree setups. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-21 14:02:28 +00:00
use_worktree_config +
!!given_config_source.file + !!given_config_source.blob > 1) {
error(_("only one config file at a time"));
usage_builtin_config();
}
if (!startup_info->have_repository) {
if (use_local_config)
die(_("--local can only be used inside a git repository"));
if (given_config_source.blob)
die(_("--blob can only be used inside a git repository"));
if (use_worktree_config)
die(_("--worktree can only be used inside a git repository"));
}
if (given_config_source.file &&
!strcmp(given_config_source.file, "-")) {
given_config_source.file = NULL;
given_config_source.use_stdin = 1;
given_config_source.scope = CONFIG_SCOPE_COMMAND;
}
if (use_global_config) {
given_config_source.file = git_global_config();
if (!given_config_source.file)
/*
* It is unknown if HOME/.gitconfig exists, so
* we do not know if we should write to XDG
* location; error out even if XDG_CONFIG_HOME
* is set and points at a sane location.
*/
die(_("$HOME not set"));
given_config_source.scope = CONFIG_SCOPE_GLOBAL;
} else if (use_system_config) {
given_config_source.file = git_system_config();
given_config_source.scope = CONFIG_SCOPE_SYSTEM;
} else if (use_local_config) {
given_config_source.file = git_pathdup("config");
given_config_source.scope = CONFIG_SCOPE_LOCAL;
} else if (use_worktree_config) {
struct worktree **worktrees = get_worktrees();
if (the_repository->repository_format_worktree_config)
worktree: add per-worktree config files A new repo extension is added, worktreeConfig. When it is present: - Repository config reading by default includes $GIT_DIR/config _and_ $GIT_DIR/config.worktree. "config" file remains shared in multiple worktree setup. - The special treatment for core.bare and core.worktree, to stay effective only in main worktree, is gone. These config settings are supposed to be in config.worktree. This extension is most useful in multiple worktree setup because you now have an option to store per-worktree config (which is either .git/config.worktree for main worktree, or .git/worktrees/xx/config.worktree for linked ones). This extension can be used in single worktree mode, even though it's pretty much useless (but this can happen after you remove all linked worktrees and move back to single worktree). "git config" reads from both "config" and "config.worktree" by default (i.e. without either --user, --file...) when this extension is present. Default writes still go to "config", not "config.worktree". A new option --worktree is added for that (*). Since a new repo extension is introduced, existing git binaries should refuse to access to the repo (both from main and linked worktrees). So they will not misread the config file (i.e. skip the config.worktree part). They may still accidentally write to the config file anyway if they use with "git config --file <path>". This design places a bet on the assumption that the majority of config variables are shared so it is the default mode. A safer move would be default writes go to per-worktree file, so that accidental changes are isolated. (*) "git config --worktree" points back to "config" file when this extension is not present and there is only one worktree so that it works in any both single and multiple worktree setups. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-21 14:02:28 +00:00
given_config_source.file = git_pathdup("config.worktree");
else if (worktrees[0] && worktrees[1])
die(_("--worktree cannot be used with multiple "
"working trees unless the config\n"
"extension worktreeConfig is enabled. "
"Please read \"CONFIGURATION FILE\"\n"
"section in \"git help worktree\" for details"));
else
given_config_source.file = git_pathdup("config");
given_config_source.scope = CONFIG_SCOPE_LOCAL;
worktree: add per-worktree config files A new repo extension is added, worktreeConfig. When it is present: - Repository config reading by default includes $GIT_DIR/config _and_ $GIT_DIR/config.worktree. "config" file remains shared in multiple worktree setup. - The special treatment for core.bare and core.worktree, to stay effective only in main worktree, is gone. These config settings are supposed to be in config.worktree. This extension is most useful in multiple worktree setup because you now have an option to store per-worktree config (which is either .git/config.worktree for main worktree, or .git/worktrees/xx/config.worktree for linked ones). This extension can be used in single worktree mode, even though it's pretty much useless (but this can happen after you remove all linked worktrees and move back to single worktree). "git config" reads from both "config" and "config.worktree" by default (i.e. without either --user, --file...) when this extension is present. Default writes still go to "config", not "config.worktree". A new option --worktree is added for that (*). Since a new repo extension is introduced, existing git binaries should refuse to access to the repo (both from main and linked worktrees). So they will not misread the config file (i.e. skip the config.worktree part). They may still accidentally write to the config file anyway if they use with "git config --file <path>". This design places a bet on the assumption that the majority of config variables are shared so it is the default mode. A safer move would be default writes go to per-worktree file, so that accidental changes are isolated. (*) "git config --worktree" points back to "config" file when this extension is not present and there is only one worktree so that it works in any both single and multiple worktree setups. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-21 14:02:28 +00:00
free_worktrees(worktrees);
} else if (given_config_source.file) {
if (!is_absolute_path(given_config_source.file) && prefix)
given_config_source.file =
prefix_filename(prefix, given_config_source.file);
given_config_source.scope = CONFIG_SCOPE_COMMAND;
} else if (given_config_source.blob) {
given_config_source.scope = CONFIG_SCOPE_COMMAND;
}
if (respect_includes_opt == -1)
config_options.respect_includes = !given_config_source.file;
else
config_options.respect_includes = respect_includes_opt;
if (startup_info->have_repository) {
config_options.commondir = get_git_common_dir();
config_options.git_dir = get_git_dir();
}
}
static void handle_nul(void) {
if (end_nul) {
term = '\0';
delim = '\n';
key_delim = '\n';
}
}
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
#define CONFIG_LOCATION_OPTIONS \
OPT_GROUP(N_("Config file location")), \
OPT_BOOL(0, "global", &use_global_config, N_("use global config file")), \
OPT_BOOL(0, "system", &use_system_config, N_("use system config file")), \
OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")), \
OPT_BOOL(0, "worktree", &use_worktree_config, N_("use per-worktree config file")), \
OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")), \
OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object"))
#define CONFIG_TYPE_OPTIONS \
OPT_GROUP(N_("Type")), \
OPT_CALLBACK('t', "type", &type, N_("type"), N_("value is given this type"), option_parse_type), \
OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL), \
OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT), \
OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT), \
OPT_CALLBACK_VALUE(0, "bool-or-str", &type, N_("value is --bool or string"), TYPE_BOOL_OR_STR), \
OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH), \
OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE)
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
#define CONFIG_DISPLAY_OPTIONS \
OPT_GROUP(N_("Display options")), \
OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")), \
OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")), \
OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")), \
OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)"))
static struct option builtin_config_options[] = {
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
CONFIG_LOCATION_OPTIONS,
OPT_GROUP(N_("Action")),
OPT_CMDMODE(0, "get", &actions, N_("get value: name [<value-pattern>]"), ACTION_GET),
OPT_CMDMODE(0, "get-all", &actions, N_("get all values: key [<value-pattern>]"), ACTION_GET_ALL),
OPT_CMDMODE(0, "get-regexp", &actions, N_("get values for regexp: name-regex [<value-pattern>]"), ACTION_GET_REGEXP),
OPT_CMDMODE(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
OPT_CMDMODE(0, "replace-all", &actions, N_("replace all matching variables: name value [<value-pattern>]"), ACTION_REPLACE_ALL),
OPT_CMDMODE(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
OPT_CMDMODE(0, "unset", &actions, N_("remove a variable: name [<value-pattern>]"), ACTION_UNSET),
OPT_CMDMODE(0, "unset-all", &actions, N_("remove all matches: name [<value-pattern>]"), ACTION_UNSET_ALL),
OPT_CMDMODE(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
OPT_CMDMODE(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
OPT_CMDMODE('l', "list", &actions, N_("list all"), ACTION_LIST),
OPT_CMDMODE('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
OPT_CMDMODE(0, "get-color", &actions, N_("find the color configured: slot [<default>]"), ACTION_GET_COLOR),
OPT_CMDMODE(0, "get-colorbool", &actions, N_("find the color setting: slot [<stdout-is-tty>]"), ACTION_GET_COLORBOOL),
CONFIG_TYPE_OPTIONS,
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
CONFIG_DISPLAY_OPTIONS,
OPT_GROUP(N_("Other")),
OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
OPT_STRING(0, "comment", &comment_arg, N_("value"), N_("human-readable comment string (# will be prepended as needed)")),
OPT_BOOL(0, "fixed-value", &fixed_value, N_("use string equality when comparing values to 'value-pattern'")),
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
OPT_END(),
};
static NORETURN void usage_builtin_config(void)
{
usage_with_options(builtin_config_usage, builtin_config_options);
}
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
static int cmd_config_list(int argc, const char **argv, const char *prefix)
{
struct option opts[] = {
CONFIG_LOCATION_OPTIONS,
CONFIG_DISPLAY_OPTIONS,
OPT_GROUP(N_("Other")),
OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
OPT_END(),
};
argc = parse_options(argc, argv, prefix, opts, builtin_config_list_usage, 0);
check_argc(argc, 0, 0);
handle_config_location(prefix);
handle_nul();
setup_auto_pager("config", 1);
if (config_with_options(show_all_config, NULL,
&given_config_source, the_repository,
&config_options) < 0) {
if (given_config_source.file)
die_errno(_("unable to read config file '%s'"),
given_config_source.file);
else
die(_("error processing config file(s)"));
}
return 0;
}
static int cmd_config_get(int argc, const char **argv, const char *prefix)
{
const char *value_pattern = NULL, *url = NULL;
int flags = 0;
struct option opts[] = {
CONFIG_LOCATION_OPTIONS,
CONFIG_TYPE_OPTIONS,
OPT_GROUP(N_("Filter options")),
OPT_BOOL(0, "all", &do_all, N_("return all values for multi-valued config options")),
OPT_BOOL(0, "regexp", &use_key_regexp, N_("interpret the name as a regular expression")),
OPT_STRING(0, "value", &value_pattern, N_("pattern"), N_("show config with values matching the pattern")),
OPT_BIT(0, "fixed-value", &flags, N_("use string equality when comparing values to value pattern"), CONFIG_FLAGS_FIXED_VALUE),
OPT_STRING(0, "url", &url, N_("URL"), N_("show config matching the given URL")),
CONFIG_DISPLAY_OPTIONS,
OPT_BOOL(0, "show-names", &show_keys, N_("show config keys in addition to their values")),
OPT_GROUP(N_("Other")),
OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
OPT_STRING(0, "default", &default_value, N_("value"), N_("use default value when missing entry")),
OPT_END(),
};
argc = parse_options(argc, argv, prefix, opts, builtin_config_get_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
check_argc(argc, 1, 1);
if ((flags & CONFIG_FLAGS_FIXED_VALUE) && !value_pattern)
die(_("--fixed-value only applies with 'value-pattern'"));
if (default_value && (do_all || url))
die(_("--default= cannot be used with --all or --url="));
if (url && (do_all || use_key_regexp || value_pattern))
die(_("--url= cannot be used with --all, --regexp or --value"));
handle_config_location(prefix);
handle_nul();
setup_auto_pager("config", 1);
if (url)
return get_urlmatch(argv[0], url);
return get_value(argv[0], value_pattern, flags);
}
static int cmd_config_set(int argc, const char **argv, const char *prefix)
{
const char *value_pattern = NULL, *comment_arg = NULL;
char *comment = NULL;
int flags = 0, append = 0;
struct option opts[] = {
CONFIG_LOCATION_OPTIONS,
CONFIG_TYPE_OPTIONS,
OPT_GROUP(N_("Filter")),
OPT_BIT(0, "all", &flags, N_("replace multi-valued config option with new value"), CONFIG_FLAGS_MULTI_REPLACE),
OPT_STRING(0, "value", &value_pattern, N_("pattern"), N_("show config with values matching the pattern")),
OPT_BIT(0, "fixed-value", &flags, N_("use string equality when comparing values to value pattern"), CONFIG_FLAGS_FIXED_VALUE),
OPT_GROUP(N_("Other")),
OPT_STRING(0, "comment", &comment_arg, N_("value"), N_("human-readable comment string (# will be prepended as needed)")),
OPT_BOOL(0, "append", &append, N_("add a new line without altering any existing values")),
OPT_END(),
};
struct key_value_info default_kvi = KVI_INIT;
char *value;
int ret;
argc = parse_options(argc, argv, prefix, opts, builtin_config_set_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
check_write();
check_argc(argc, 2, 2);
if ((flags & CONFIG_FLAGS_FIXED_VALUE) && !value_pattern)
die(_("--fixed-value only applies with --value=<pattern>"));
if (append && value_pattern)
die(_("--append cannot be used with --value=<pattern>"));
if (append)
value_pattern = CONFIG_REGEX_NONE;
comment = git_config_prepare_comment_string(comment_arg);
handle_config_location(prefix);
value = normalize_value(argv[0], argv[1], &default_kvi);
if ((flags & CONFIG_FLAGS_MULTI_REPLACE) || value_pattern) {
ret = git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value, value_pattern,
comment, flags);
} else {
ret = git_config_set_in_file_gently(given_config_source.file,
argv[0], comment, value);
if (ret == CONFIG_NOTHING_SET)
error(_("cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."), argv[0]);
}
free(comment);
free(value);
return ret;
}
static int cmd_config_unset(int argc, const char **argv, const char *prefix)
{
const char *value_pattern = NULL;
int flags = 0;
struct option opts[] = {
CONFIG_LOCATION_OPTIONS,
OPT_GROUP(N_("Filter")),
OPT_BIT(0, "all", &flags, N_("replace multi-valued config option with new value"), CONFIG_FLAGS_MULTI_REPLACE),
OPT_STRING(0, "value", &value_pattern, N_("pattern"), N_("show config with values matching the pattern")),
OPT_BIT(0, "fixed-value", &flags, N_("use string equality when comparing values to value pattern"), CONFIG_FLAGS_FIXED_VALUE),
OPT_END(),
};
argc = parse_options(argc, argv, prefix, opts, builtin_config_unset_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
check_write();
check_argc(argc, 1, 1);
if ((flags & CONFIG_FLAGS_FIXED_VALUE) && !value_pattern)
die(_("--fixed-value only applies with 'value-pattern'"));
handle_config_location(prefix);
if ((flags & CONFIG_FLAGS_MULTI_REPLACE) || value_pattern)
return git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], NULL, value_pattern,
NULL, flags);
else
return git_config_set_in_file_gently(given_config_source.file, argv[0],
NULL, NULL);
}
static int cmd_config_rename_section(int argc, const char **argv, const char *prefix)
{
struct option opts[] = {
CONFIG_LOCATION_OPTIONS,
OPT_END(),
};
int ret;
argc = parse_options(argc, argv, prefix, opts, builtin_config_rename_section_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
check_write();
check_argc(argc, 2, 2);
handle_config_location(prefix);
ret = git_config_rename_section_in_file(given_config_source.file,
argv[0], argv[1]);
if (ret < 0)
return ret;
else if (!ret)
die(_("no such section: %s"), argv[0]);
return 0;
}
static int cmd_config_remove_section(int argc, const char **argv, const char *prefix)
{
struct option opts[] = {
CONFIG_LOCATION_OPTIONS,
OPT_END(),
};
int ret;
argc = parse_options(argc, argv, prefix, opts, builtin_config_remove_section_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
check_write();
check_argc(argc, 1, 1);
handle_config_location(prefix);
ret = git_config_rename_section_in_file(given_config_source.file,
argv[0], NULL);
if (ret < 0)
return ret;
else if (!ret)
die(_("no such section: %s"), argv[0]);
return 0;
}
static int show_editor(void)
{
char *config_file;
if (!given_config_source.file && !startup_info->have_repository)
die(_("not in a git directory"));
if (given_config_source.use_stdin)
die(_("editing stdin is not supported"));
if (given_config_source.blob)
die(_("editing blobs is not supported"));
git_config(git_default_config, NULL);
config_file = given_config_source.file ?
xstrdup(given_config_source.file) :
git_pathdup("config");
if (use_global_config) {
int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
if (fd >= 0) {
char *content = default_user_config();
write_str_in_full(fd, content);
free(content);
close(fd);
}
else if (errno != EEXIST)
die_errno(_("cannot create configuration file %s"), config_file);
}
launch_editor(config_file, NULL, NULL);
free(config_file);
return 0;
}
static int cmd_config_edit(int argc, const char **argv, const char *prefix)
{
struct option opts[] = {
CONFIG_LOCATION_OPTIONS,
OPT_END(),
};
argc = parse_options(argc, argv, prefix, opts, builtin_config_edit_usage, 0);
check_write();
check_argc(argc, 0, 0);
handle_config_location(prefix);
return show_editor();
}
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
static struct option builtin_subcommand_options[] = {
OPT_SUBCOMMAND("list", &subcommand, cmd_config_list),
OPT_SUBCOMMAND("get", &subcommand, cmd_config_get),
OPT_SUBCOMMAND("set", &subcommand, cmd_config_set),
OPT_SUBCOMMAND("unset", &subcommand, cmd_config_unset),
OPT_SUBCOMMAND("rename-section", &subcommand, cmd_config_rename_section),
OPT_SUBCOMMAND("remove-section", &subcommand, cmd_config_remove_section),
OPT_SUBCOMMAND("edit", &subcommand, cmd_config_edit),
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
OPT_END(),
};
int cmd_config(int argc, const char **argv, const char *prefix)
{
char *value = NULL, *comment = NULL;
int flags = 0;
int ret = 0;
struct key_value_info default_kvi = KVI_INIT;
given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
/*
* This is somewhat hacky: we first parse the command line while
* keeping all args intact in order to determine whether a subcommand
* has been specified. If so, we re-parse it a second time, but this
* time we drop KEEP_ARGV0. This is so that we don't munge the command
* line in case no subcommand was given, which would otherwise confuse
* us when parsing the legacy-style modes that don't use subcommands.
*/
argc = parse_options(argc, argv, prefix, builtin_subcommand_options, builtin_config_usage,
PARSE_OPT_SUBCOMMAND_OPTIONAL|PARSE_OPT_KEEP_ARGV0|PARSE_OPT_KEEP_UNKNOWN_OPT);
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
if (subcommand) {
argc = parse_options(argc, argv, prefix, builtin_subcommand_options, builtin_config_usage,
PARSE_OPT_SUBCOMMAND_OPTIONAL|PARSE_OPT_KEEP_UNKNOWN_OPT);
builtin/config: introduce "list" subcommand While git-config(1) has several modes, those modes are not exposed with subcommands but instead by specifying action flags like `--unset` or `--list`. This user interface is not really in line with how our more modern commands work, where it is a lot more customary to say e.g. `git remote list`. Furthermore, to add to the confusion, git-config(1) also allows the user to request modes implicitly by just specifying the correct number of arguments. Thus, `git config foo.bar` will retrieve the value of "foo.bar" while `git config foo.bar baz` will set it to "baz". Overall, this makes for a confusing interface that could really use a makeover. It hurts discoverability of what you can do with git-config(1) and is comparatively easy to get wrong. Converting the command to have subcommands instead would go a long way to help address these issues. One concern in this context is backwards compatibility. Luckily, we can introduce subcommands without breaking backwards compatibility at all. This is because all the implicit modes of git-config(1) require that the first argument is a properly formatted config key. And as config keys _must_ have a dot in their name, any value without a dot would have been discarded by git-config(1) previous to this change. Thus, given that none of the subcommands do have a dot, they are unambiguous. Introduce the first such new subcommand, which is "git config list". To retain backwards compatibility we only conditionally use subcommands and will fall back to the old syntax in case no subcommand was detected. This should help to transition to the new-style syntax until we eventually deprecate and remove the old-style syntax. Note that the way we handle this we're duplicating some functionality across old and new syntax. While this isn't pretty, it helps us to ensure that there really is no change in behaviour for the old syntax. Amend tests such that we run them both with old and new style syntax. As tests are now run twice, state from the first run may be still be around in the second run and thus cause tests to fail. Add cleanup logic as required to fix such tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-05-06 08:56:24 +00:00
return subcommand(argc, argv, prefix);
}
argc = parse_options(argc, argv, prefix, builtin_config_options,
builtin_config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
handle_config_location(prefix);
handle_nul();
if ((actions & (ACTION_GET_COLOR|ACTION_GET_COLORBOOL)) && type) {
error(_("--get-color and variable type are incoherent"));
usage_builtin_config();
}
if (actions == 0)
switch (argc) {
case 1: actions = ACTION_GET; break;
case 2: actions = ACTION_SET; break;
case 3: actions = ACTION_SET_ALL; break;
default:
usage_builtin_config();
}
if (omit_values &&
!(actions == ACTION_LIST || actions == ACTION_GET_REGEXP)) {
error(_("--name-only is only applicable to --list or --get-regexp"));
usage_builtin_config();
}
if (show_origin && !(actions &
(ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST))) {
error(_("--show-origin is only applicable to --get, --get-all, "
"--get-regexp, and --list"));
usage_builtin_config();
}
builtin/config: introduce `--default` For some use cases, callers of the `git-config(1)` builtin would like to fallback to default values when the variable asked for does not exist. In addition, users would like to use existing type specifiers to ensure that values are parsed correctly when they do exist in the configuration. For example, to fetch a value without a type specifier and fallback to `$fallback`, the following is required: $ git config core.foo || echo "$fallback" This is fine for most values, but can be tricky for difficult-to-express `$fallback`'s, like ANSI color codes. This motivates `--get-color`, which is a one-off exception to the normal type specifier rules wherein a user specifies both the configuration variable and an optional fallback. Both are formatted according to their type specifier, which eases the burden on the user to ensure that values are correctly formatted. This commit (and those following it in this series) aim to eventually replace `--get-color` with a consistent alternative. By introducing `--default`, we allow the `--get-color` action to be promoted to a `--type=color` type specifier, retaining the "fallback" behavior via the `--default` flag introduced in this commit. For example, we aim to replace: $ git config --get-color variable [default] [...] with: $ git config --default default --type=color variable [...] Values filled by `--default` behave exactly as if they were present in the affected configuration file; they will be parsed by type specifiers without the knowledge that they are not themselves present in the configuration. Specifically, this means that the following will work: $ git config --int --default 1M does.not.exist 1048576 In subsequent commits, we will offer `--type=color`, which (in conjunction with `--default`) will be sufficient to replace `--get-color`. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-10 00:18:26 +00:00
if (default_value && !(actions & ACTION_GET)) {
error(_("--default is only applicable to --get"));
usage_builtin_config();
builtin/config: introduce `--default` For some use cases, callers of the `git-config(1)` builtin would like to fallback to default values when the variable asked for does not exist. In addition, users would like to use existing type specifiers to ensure that values are parsed correctly when they do exist in the configuration. For example, to fetch a value without a type specifier and fallback to `$fallback`, the following is required: $ git config core.foo || echo "$fallback" This is fine for most values, but can be tricky for difficult-to-express `$fallback`'s, like ANSI color codes. This motivates `--get-color`, which is a one-off exception to the normal type specifier rules wherein a user specifies both the configuration variable and an optional fallback. Both are formatted according to their type specifier, which eases the burden on the user to ensure that values are correctly formatted. This commit (and those following it in this series) aim to eventually replace `--get-color` with a consistent alternative. By introducing `--default`, we allow the `--get-color` action to be promoted to a `--type=color` type specifier, retaining the "fallback" behavior via the `--default` flag introduced in this commit. For example, we aim to replace: $ git config --get-color variable [default] [...] with: $ git config --default default --type=color variable [...] Values filled by `--default` behave exactly as if they were present in the affected configuration file; they will be parsed by type specifiers without the knowledge that they are not themselves present in the configuration. Specifically, this means that the following will work: $ git config --int --default 1M does.not.exist 1048576 In subsequent commits, we will offer `--type=color`, which (in conjunction with `--default`) will be sufficient to replace `--get-color`. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-10 00:18:26 +00:00
}
if (comment_arg &&
!(actions & (ACTION_ADD|ACTION_SET|ACTION_SET_ALL|ACTION_REPLACE_ALL))) {
error(_("--comment is only applicable to add/set/replace operations"));
usage_builtin_config();
}
/* check usage of --fixed-value */
if (fixed_value) {
int allowed_usage = 0;
switch (actions) {
/* git config --get <name> <value-pattern> */
case ACTION_GET:
/* git config --get-all <name> <value-pattern> */
case ACTION_GET_ALL:
/* git config --get-regexp <name-pattern> <value-pattern> */
case ACTION_GET_REGEXP:
/* git config --unset <name> <value-pattern> */
case ACTION_UNSET:
/* git config --unset-all <name> <value-pattern> */
case ACTION_UNSET_ALL:
allowed_usage = argc > 1 && !!argv[1];
break;
/* git config <name> <value> <value-pattern> */
case ACTION_SET_ALL:
/* git config --replace-all <name> <value> <value-pattern> */
case ACTION_REPLACE_ALL:
allowed_usage = argc > 2 && !!argv[2];
break;
/* other options don't allow --fixed-value */
}
if (!allowed_usage) {
error(_("--fixed-value only applies with 'value-pattern'"));
usage_builtin_config();
}
flags |= CONFIG_FLAGS_FIXED_VALUE;
}
comment = git_config_prepare_comment_string(comment_arg);
if (actions & PAGING_ACTIONS)
setup_auto_pager("config", 1);
if (actions == ACTION_LIST) {
check_argc(argc, 0, 0);
if (config_with_options(show_all_config, NULL,
config: pass 'repo' directly to 'config_with_options()' Add a 'struct repository' argument to 'config_with_options()' and remove the 'repo' field from 'struct git_config_source'. A 'struct repository' instance was originally added to the config source in e3e8bf046e9 (submodule-config: pass repo upon blob config read, 2021-08-16) to improve how submodule blob config content was accessed. At the time, this was the only use for a 'repository' instance, so it was naturally added only where it was needed: to 'struct git_config_source'. However, in upcoming patches, 'config_with_options()' will need the repository instance to access extension information (regardless of whether a 'config_source' exists). To make the 'struct repository' instance more easily accessible, move it into the function's arguments. Update all callers of 'config_with_options()' to pass the appropriate 'repo' value: * in 'builtin/config.c', use 'the_repository' * in 'submodule--config.c', use the 'repo' arg in 'config_from_gitmodules()' * in 'read_[very_]early_config()' & 'read_protected_config()', set 'repo' to NULL (repository instances aren't available there) * in 'populate_remote_urls()', use the repo instance that has been added to the 'struct config_include_data' * in 'repo_read_config()', use the given 'repo' arg Finally, note that this patch eliminates the fallback to 'the_repository' that previously existed for the 'config_source' repo instance if it was NULL. The fallback is no longer necessary, as the 'repo' is set explicitly in all cases where it is needed. Signed-off-by: Victoria Dye <vdye@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-05-26 01:32:59 +00:00
&given_config_source, the_repository,
&config_options) < 0) {
if (given_config_source.file)
die_errno(_("unable to read config file '%s'"),
given_config_source.file);
else
die(_("error processing config file(s)"));
}
}
else if (actions == ACTION_EDIT) {
ret = show_editor();
}
else if (actions == ACTION_SET) {
check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1], &default_kvi);
ret = git_config_set_in_file_gently(given_config_source.file, argv[0], comment, value);
if (ret == CONFIG_NOTHING_SET)
error(_("cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."), argv[0]);
}
else if (actions == ACTION_SET_ALL) {
check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1], &default_kvi);
built-ins: use free() not UNLEAK() if trivial, rm dead code For a lot of uses of UNLEAK() it would be quite tricky to release the memory involved, or we're missing the relevant *_(release|clear)() functions. But in these cases we have them already, and can just invoke them on the variable(s) involved, instead of UNLEAK(). For "builtin/worktree.c" the UNLEAK() was also added in [1], but the struct member it's unleaking was removed in [2]. The only non-"int" member of that structure is "const char *keep_locked", which comes to us via "argv" or a string literal[3]. We have good visibility via the compiler and tooling (e.g. SANITIZE=address) on bad free()-ing, but none on UNLEAK() we don't need anymore. So let's prefer releasing the memory when it's easy. For "bugreport", "worktree" and "config" we need to start using a "ret = ..." return pattern. For "builtin/bugreport.c" these UNLEAK() were added in [4], and for "builtin/config.c" in [1]. For "config" the code seen here was the only user of the "value" variable. For "ACTION_{RENAME,REMOVE}_SECTION" we need to be sure to return the right exit code in the cases where we were relying on falling through to the top-level. I think there's still a use-case for UNLEAK(), but hat it's changed since then. Using it so that "we can see the real leaks" is counter-productive in these cases. It's more useful to have UNLEAK() be a marker of the remaining odd cases where it's hard to free() the memory for whatever reason. With this change less than 20 of them remain in-tree. 1. 0e5bba53af7 (add UNLEAK annotation for reducing leak false positives, 2017-09-08) 2. d861d34a6ed (worktree: remove extra members from struct add_opts, 2018-04-24) 3. 0db4961c49b (worktree: teach `add` to accept --reason <string> with --lock, 2021-07-15) 4. 0e5bba53af7 and 00d8c311050 (commit: fix "author_ident" leak, 2022-05-12). Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-08 18:17:51 +00:00
ret = git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value, argv[2],
comment, flags);
}
else if (actions == ACTION_ADD) {
check_write();
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1], &default_kvi);
built-ins: use free() not UNLEAK() if trivial, rm dead code For a lot of uses of UNLEAK() it would be quite tricky to release the memory involved, or we're missing the relevant *_(release|clear)() functions. But in these cases we have them already, and can just invoke them on the variable(s) involved, instead of UNLEAK(). For "builtin/worktree.c" the UNLEAK() was also added in [1], but the struct member it's unleaking was removed in [2]. The only non-"int" member of that structure is "const char *keep_locked", which comes to us via "argv" or a string literal[3]. We have good visibility via the compiler and tooling (e.g. SANITIZE=address) on bad free()-ing, but none on UNLEAK() we don't need anymore. So let's prefer releasing the memory when it's easy. For "bugreport", "worktree" and "config" we need to start using a "ret = ..." return pattern. For "builtin/bugreport.c" these UNLEAK() were added in [4], and for "builtin/config.c" in [1]. For "config" the code seen here was the only user of the "value" variable. For "ACTION_{RENAME,REMOVE}_SECTION" we need to be sure to return the right exit code in the cases where we were relying on falling through to the top-level. I think there's still a use-case for UNLEAK(), but hat it's changed since then. Using it so that "we can see the real leaks" is counter-productive in these cases. It's more useful to have UNLEAK() be a marker of the remaining odd cases where it's hard to free() the memory for whatever reason. With this change less than 20 of them remain in-tree. 1. 0e5bba53af7 (add UNLEAK annotation for reducing leak false positives, 2017-09-08) 2. d861d34a6ed (worktree: remove extra members from struct add_opts, 2018-04-24) 3. 0db4961c49b (worktree: teach `add` to accept --reason <string> with --lock, 2021-07-15) 4. 0e5bba53af7 and 00d8c311050 (commit: fix "author_ident" leak, 2022-05-12). Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-08 18:17:51 +00:00
ret = git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value,
CONFIG_REGEX_NONE,
comment, flags);
}
else if (actions == ACTION_REPLACE_ALL) {
check_write();
check_argc(argc, 2, 3);
value = normalize_value(argv[0], argv[1], &default_kvi);
built-ins: use free() not UNLEAK() if trivial, rm dead code For a lot of uses of UNLEAK() it would be quite tricky to release the memory involved, or we're missing the relevant *_(release|clear)() functions. But in these cases we have them already, and can just invoke them on the variable(s) involved, instead of UNLEAK(). For "builtin/worktree.c" the UNLEAK() was also added in [1], but the struct member it's unleaking was removed in [2]. The only non-"int" member of that structure is "const char *keep_locked", which comes to us via "argv" or a string literal[3]. We have good visibility via the compiler and tooling (e.g. SANITIZE=address) on bad free()-ing, but none on UNLEAK() we don't need anymore. So let's prefer releasing the memory when it's easy. For "bugreport", "worktree" and "config" we need to start using a "ret = ..." return pattern. For "builtin/bugreport.c" these UNLEAK() were added in [4], and for "builtin/config.c" in [1]. For "config" the code seen here was the only user of the "value" variable. For "ACTION_{RENAME,REMOVE}_SECTION" we need to be sure to return the right exit code in the cases where we were relying on falling through to the top-level. I think there's still a use-case for UNLEAK(), but hat it's changed since then. Using it so that "we can see the real leaks" is counter-productive in these cases. It's more useful to have UNLEAK() be a marker of the remaining odd cases where it's hard to free() the memory for whatever reason. With this change less than 20 of them remain in-tree. 1. 0e5bba53af7 (add UNLEAK annotation for reducing leak false positives, 2017-09-08) 2. d861d34a6ed (worktree: remove extra members from struct add_opts, 2018-04-24) 3. 0db4961c49b (worktree: teach `add` to accept --reason <string> with --lock, 2021-07-15) 4. 0e5bba53af7 and 00d8c311050 (commit: fix "author_ident" leak, 2022-05-12). Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-08 18:17:51 +00:00
ret = git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], value, argv[2],
comment, flags | CONFIG_FLAGS_MULTI_REPLACE);
}
else if (actions == ACTION_GET) {
check_argc(argc, 1, 2);
return get_value(argv[0], argv[1], flags);
}
else if (actions == ACTION_GET_ALL) {
do_all = 1;
check_argc(argc, 1, 2);
return get_value(argv[0], argv[1], flags);
}
else if (actions == ACTION_GET_REGEXP) {
show_keys = 1;
use_key_regexp = 1;
do_all = 1;
check_argc(argc, 1, 2);
return get_value(argv[0], argv[1], flags);
}
else if (actions == ACTION_GET_URLMATCH) {
check_argc(argc, 2, 2);
return get_urlmatch(argv[0], argv[1]);
}
else if (actions == ACTION_UNSET) {
check_write();
check_argc(argc, 1, 2);
if (argc == 2)
return git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], NULL, argv[1],
NULL, flags);
else
return git_config_set_in_file_gently(given_config_source.file,
argv[0], NULL, NULL);
}
else if (actions == ACTION_UNSET_ALL) {
check_write();
check_argc(argc, 1, 2);
return git_config_set_multivar_in_file_gently(given_config_source.file,
argv[0], NULL, argv[1],
NULL, flags | CONFIG_FLAGS_MULTI_REPLACE);
}
else if (actions == ACTION_RENAME_SECTION) {
check_write();
check_argc(argc, 2, 2);
ret = git_config_rename_section_in_file(given_config_source.file,
argv[0], argv[1]);
if (ret < 0)
return ret;
built-ins: use free() not UNLEAK() if trivial, rm dead code For a lot of uses of UNLEAK() it would be quite tricky to release the memory involved, or we're missing the relevant *_(release|clear)() functions. But in these cases we have them already, and can just invoke them on the variable(s) involved, instead of UNLEAK(). For "builtin/worktree.c" the UNLEAK() was also added in [1], but the struct member it's unleaking was removed in [2]. The only non-"int" member of that structure is "const char *keep_locked", which comes to us via "argv" or a string literal[3]. We have good visibility via the compiler and tooling (e.g. SANITIZE=address) on bad free()-ing, but none on UNLEAK() we don't need anymore. So let's prefer releasing the memory when it's easy. For "bugreport", "worktree" and "config" we need to start using a "ret = ..." return pattern. For "builtin/bugreport.c" these UNLEAK() were added in [4], and for "builtin/config.c" in [1]. For "config" the code seen here was the only user of the "value" variable. For "ACTION_{RENAME,REMOVE}_SECTION" we need to be sure to return the right exit code in the cases where we were relying on falling through to the top-level. I think there's still a use-case for UNLEAK(), but hat it's changed since then. Using it so that "we can see the real leaks" is counter-productive in these cases. It's more useful to have UNLEAK() be a marker of the remaining odd cases where it's hard to free() the memory for whatever reason. With this change less than 20 of them remain in-tree. 1. 0e5bba53af7 (add UNLEAK annotation for reducing leak false positives, 2017-09-08) 2. d861d34a6ed (worktree: remove extra members from struct add_opts, 2018-04-24) 3. 0db4961c49b (worktree: teach `add` to accept --reason <string> with --lock, 2021-07-15) 4. 0e5bba53af7 and 00d8c311050 (commit: fix "author_ident" leak, 2022-05-12). Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-08 18:17:51 +00:00
else if (!ret)
die(_("no such section: %s"), argv[0]);
built-ins: use free() not UNLEAK() if trivial, rm dead code For a lot of uses of UNLEAK() it would be quite tricky to release the memory involved, or we're missing the relevant *_(release|clear)() functions. But in these cases we have them already, and can just invoke them on the variable(s) involved, instead of UNLEAK(). For "builtin/worktree.c" the UNLEAK() was also added in [1], but the struct member it's unleaking was removed in [2]. The only non-"int" member of that structure is "const char *keep_locked", which comes to us via "argv" or a string literal[3]. We have good visibility via the compiler and tooling (e.g. SANITIZE=address) on bad free()-ing, but none on UNLEAK() we don't need anymore. So let's prefer releasing the memory when it's easy. For "bugreport", "worktree" and "config" we need to start using a "ret = ..." return pattern. For "builtin/bugreport.c" these UNLEAK() were added in [4], and for "builtin/config.c" in [1]. For "config" the code seen here was the only user of the "value" variable. For "ACTION_{RENAME,REMOVE}_SECTION" we need to be sure to return the right exit code in the cases where we were relying on falling through to the top-level. I think there's still a use-case for UNLEAK(), but hat it's changed since then. Using it so that "we can see the real leaks" is counter-productive in these cases. It's more useful to have UNLEAK() be a marker of the remaining odd cases where it's hard to free() the memory for whatever reason. With this change less than 20 of them remain in-tree. 1. 0e5bba53af7 (add UNLEAK annotation for reducing leak false positives, 2017-09-08) 2. d861d34a6ed (worktree: remove extra members from struct add_opts, 2018-04-24) 3. 0db4961c49b (worktree: teach `add` to accept --reason <string> with --lock, 2021-07-15) 4. 0e5bba53af7 and 00d8c311050 (commit: fix "author_ident" leak, 2022-05-12). Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-08 18:17:51 +00:00
else
ret = 0;
}
else if (actions == ACTION_REMOVE_SECTION) {
check_write();
check_argc(argc, 1, 1);
ret = git_config_rename_section_in_file(given_config_source.file,
argv[0], NULL);
if (ret < 0)
return ret;
built-ins: use free() not UNLEAK() if trivial, rm dead code For a lot of uses of UNLEAK() it would be quite tricky to release the memory involved, or we're missing the relevant *_(release|clear)() functions. But in these cases we have them already, and can just invoke them on the variable(s) involved, instead of UNLEAK(). For "builtin/worktree.c" the UNLEAK() was also added in [1], but the struct member it's unleaking was removed in [2]. The only non-"int" member of that structure is "const char *keep_locked", which comes to us via "argv" or a string literal[3]. We have good visibility via the compiler and tooling (e.g. SANITIZE=address) on bad free()-ing, but none on UNLEAK() we don't need anymore. So let's prefer releasing the memory when it's easy. For "bugreport", "worktree" and "config" we need to start using a "ret = ..." return pattern. For "builtin/bugreport.c" these UNLEAK() were added in [4], and for "builtin/config.c" in [1]. For "config" the code seen here was the only user of the "value" variable. For "ACTION_{RENAME,REMOVE}_SECTION" we need to be sure to return the right exit code in the cases where we were relying on falling through to the top-level. I think there's still a use-case for UNLEAK(), but hat it's changed since then. Using it so that "we can see the real leaks" is counter-productive in these cases. It's more useful to have UNLEAK() be a marker of the remaining odd cases where it's hard to free() the memory for whatever reason. With this change less than 20 of them remain in-tree. 1. 0e5bba53af7 (add UNLEAK annotation for reducing leak false positives, 2017-09-08) 2. d861d34a6ed (worktree: remove extra members from struct add_opts, 2018-04-24) 3. 0db4961c49b (worktree: teach `add` to accept --reason <string> with --lock, 2021-07-15) 4. 0e5bba53af7 and 00d8c311050 (commit: fix "author_ident" leak, 2022-05-12). Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-08 18:17:51 +00:00
else if (!ret)
die(_("no such section: %s"), argv[0]);
built-ins: use free() not UNLEAK() if trivial, rm dead code For a lot of uses of UNLEAK() it would be quite tricky to release the memory involved, or we're missing the relevant *_(release|clear)() functions. But in these cases we have them already, and can just invoke them on the variable(s) involved, instead of UNLEAK(). For "builtin/worktree.c" the UNLEAK() was also added in [1], but the struct member it's unleaking was removed in [2]. The only non-"int" member of that structure is "const char *keep_locked", which comes to us via "argv" or a string literal[3]. We have good visibility via the compiler and tooling (e.g. SANITIZE=address) on bad free()-ing, but none on UNLEAK() we don't need anymore. So let's prefer releasing the memory when it's easy. For "bugreport", "worktree" and "config" we need to start using a "ret = ..." return pattern. For "builtin/bugreport.c" these UNLEAK() were added in [4], and for "builtin/config.c" in [1]. For "config" the code seen here was the only user of the "value" variable. For "ACTION_{RENAME,REMOVE}_SECTION" we need to be sure to return the right exit code in the cases where we were relying on falling through to the top-level. I think there's still a use-case for UNLEAK(), but hat it's changed since then. Using it so that "we can see the real leaks" is counter-productive in these cases. It's more useful to have UNLEAK() be a marker of the remaining odd cases where it's hard to free() the memory for whatever reason. With this change less than 20 of them remain in-tree. 1. 0e5bba53af7 (add UNLEAK annotation for reducing leak false positives, 2017-09-08) 2. d861d34a6ed (worktree: remove extra members from struct add_opts, 2018-04-24) 3. 0db4961c49b (worktree: teach `add` to accept --reason <string> with --lock, 2021-07-15) 4. 0e5bba53af7 and 00d8c311050 (commit: fix "author_ident" leak, 2022-05-12). Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-08 18:17:51 +00:00
else
ret = 0;
}
else if (actions == ACTION_GET_COLOR) {
config: fix parsing of "git config --get-color some.key -1" Most of git-config's command line options use OPT_BIT to choose an action, and then parse the non-option arguments in a context-dependent way. However, --get-color and --get-colorbool are unlike the rest of the options, in that they are OPT_STRING, taking the option name as a parameter. This generally works, because we then use the presence of those strings to set an action bit anyway. But it does mean that the option-parser will continue looking for options even after the key (because it is not a non-option; it is an argument to an option). And running: git config --get-color some.key -1 (to use "-1" as the default color spec) will barf, claiming that "-1" is not an option. Instead, we should treat --get-color and --get-colorbool as action bits, just like --add, --get, and all the other actions, and then check that the non-option arguments we got are sane. This fixes the weirdness above, and makes those two options like all the others. This "fixes" a test in t4026, which checked that feeding "-2" as a color should fail (it does fail, but prior to this patch, because parseopt barfed, not because we actually ever tried to parse the color). This also catches other errors, like: git config --get-color some.key black blue which previously silently ignored "blue" (and now will complain that you gave too many arguments). There are some possible regressions, though. We now disallow these, which currently do what you would expect: # specifying other options after the action git config --get-color some.key --file whatever # using long-arg syntax git config --get-color=some.key However, we have never advertised these in the documentation, and in fact they did not work in some older versions of git. The behavior was apparently switched as an accidental side effect of d64ec16 (git config: reorganize to use parseopt, 2009-02-21). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-20 15:15:51 +00:00
check_argc(argc, 1, 2);
get_color(argv[0], argv[1]);
}
else if (actions == ACTION_GET_COLORBOOL) {
config: fix parsing of "git config --get-color some.key -1" Most of git-config's command line options use OPT_BIT to choose an action, and then parse the non-option arguments in a context-dependent way. However, --get-color and --get-colorbool are unlike the rest of the options, in that they are OPT_STRING, taking the option name as a parameter. This generally works, because we then use the presence of those strings to set an action bit anyway. But it does mean that the option-parser will continue looking for options even after the key (because it is not a non-option; it is an argument to an option). And running: git config --get-color some.key -1 (to use "-1" as the default color spec) will barf, claiming that "-1" is not an option. Instead, we should treat --get-color and --get-colorbool as action bits, just like --add, --get, and all the other actions, and then check that the non-option arguments we got are sane. This fixes the weirdness above, and makes those two options like all the others. This "fixes" a test in t4026, which checked that feeding "-2" as a color should fail (it does fail, but prior to this patch, because parseopt barfed, not because we actually ever tried to parse the color). This also catches other errors, like: git config --get-color some.key black blue which previously silently ignored "blue" (and now will complain that you gave too many arguments). There are some possible regressions, though. We now disallow these, which currently do what you would expect: # specifying other options after the action git config --get-color some.key --file whatever # using long-arg syntax git config --get-color=some.key However, we have never advertised these in the documentation, and in fact they did not work in some older versions of git. The behavior was apparently switched as an accidental side effect of d64ec16 (git config: reorganize to use parseopt, 2009-02-21). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-20 15:15:51 +00:00
check_argc(argc, 1, 2);
if (argc == 2)
color_stdout_is_tty = git_config_bool("command line", argv[1]);
return get_colorbool(argv[0], argc == 2);
}
free(comment);
built-ins: use free() not UNLEAK() if trivial, rm dead code For a lot of uses of UNLEAK() it would be quite tricky to release the memory involved, or we're missing the relevant *_(release|clear)() functions. But in these cases we have them already, and can just invoke them on the variable(s) involved, instead of UNLEAK(). For "builtin/worktree.c" the UNLEAK() was also added in [1], but the struct member it's unleaking was removed in [2]. The only non-"int" member of that structure is "const char *keep_locked", which comes to us via "argv" or a string literal[3]. We have good visibility via the compiler and tooling (e.g. SANITIZE=address) on bad free()-ing, but none on UNLEAK() we don't need anymore. So let's prefer releasing the memory when it's easy. For "bugreport", "worktree" and "config" we need to start using a "ret = ..." return pattern. For "builtin/bugreport.c" these UNLEAK() were added in [4], and for "builtin/config.c" in [1]. For "config" the code seen here was the only user of the "value" variable. For "ACTION_{RENAME,REMOVE}_SECTION" we need to be sure to return the right exit code in the cases where we were relying on falling through to the top-level. I think there's still a use-case for UNLEAK(), but hat it's changed since then. Using it so that "we can see the real leaks" is counter-productive in these cases. It's more useful to have UNLEAK() be a marker of the remaining odd cases where it's hard to free() the memory for whatever reason. With this change less than 20 of them remain in-tree. 1. 0e5bba53af7 (add UNLEAK annotation for reducing leak false positives, 2017-09-08) 2. d861d34a6ed (worktree: remove extra members from struct add_opts, 2018-04-24) 3. 0db4961c49b (worktree: teach `add` to accept --reason <string> with --lock, 2021-07-15) 4. 0e5bba53af7 and 00d8c311050 (commit: fix "author_ident" leak, 2022-05-12). Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-08 18:17:51 +00:00
free(value);
return ret;
}