builtin/config: introduce "edit" subcommand

Introduce a new "edit" subcommand to git-config(1). Please refer to preceding commits regarding the motivation behind this change. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed May 6, 2024 at 10:56 UTC 3cbace5ee0e1d9a959846241ca73d545b8f70878
3 files changed +68 -36
Documentation/git-config.txt
+10 -7
@@ -15,8 +15,8 @@ SYNOPSIS
15 'git config unset' [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>
16 'git config rename-section' [<file-option>] <old-name> <new-name>
17 'git config remove-section' [<file-option>] <name>
18 +'git config edit' [<file-option>]
19 'git config' [<file-option>] --get-colorbool <name> [<stdout-is-tty>]
19 -'git config' [<file-option>] -e | --edit
20
21 DESCRIPTION
22 -----------
@@ -98,6 +98,11 @@ rename-section::
98 remove-section::
99 Remove the given section from the configuration file.
100
101 +edit::
102 + Opens an editor to modify the specified config file; either
103 + `--system`, `--global`, `--local` (default), `--worktree`, or
104 + `--file <config-file>`.
105 +
106 [[OPTIONS]]
107 OPTIONS
108 -------
@@ -274,12 +279,6 @@ Valid `<type>`'s include:
279 When the color setting for `name` is undefined, the command uses
280 `color.ui` as fallback.
281
277 --e::
278 ---edit::
279 - Opens an editor to modify the specified config file; either
280 - `--system`, `--global`, `--local` (default), `--worktree`, or
281 - `--file <config-file>`.
282 -
282 --[no-]includes::
283 Respect `include.*` directives in config files when looking up
284 values. Defaults to `off` when a specific file is given (e.g.,
@@ -336,6 +335,10 @@ recommended to migrate to the new syntax.
335 --remove-section <name>::
336 Replaced by `git config remove-section <name>`.
337
338 +-e::
339 +--edit::
340 + Replaced by `git config edit`.
341 +
342 CONFIGURATION
343 -------------
344 `pager.config` is only respected when listing configuration, i.e., when
builtin/config.c
+55 -26
@@ -22,6 +22,7 @@ static const char *const builtin_config_usage[] = {
22 N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
23 N_("git config rename-section [<file-option>] <old-name> <new-name>"),
24 N_("git config remove-section [<file-option>] <name>"),
25 + N_("git config edit [<file-option>]"),
26 NULL
27 };
28
@@ -55,6 +56,11 @@ static const char *const builtin_config_remove_section_usage[] = {
56 NULL
57 };
58
59 +static const char *const builtin_config_edit_usage[] = {
60 + N_("git config edit [<file-option>]"),
61 + NULL
62 +};
63 +
64 static char *key;
65 static regex_t *key_regexp;
66 static const char *value_pattern;
@@ -1011,6 +1017,53 @@ static int cmd_config_remove_section(int argc, const char **argv, const char *pr
1017 return 0;
1018 }
1019
1020 +static int show_editor(void)
1021 +{
1022 + char *config_file;
1023 +
1024 + if (!given_config_source.file && !startup_info->have_repository)
1025 + die(_("not in a git directory"));
1026 + if (given_config_source.use_stdin)
1027 + die(_("editing stdin is not supported"));
1028 + if (given_config_source.blob)
1029 + die(_("editing blobs is not supported"));
1030 + git_config(git_default_config, NULL);
1031 + config_file = given_config_source.file ?
1032 + xstrdup(given_config_source.file) :
1033 + git_pathdup("config");
1034 + if (use_global_config) {
1035 + int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
1036 + if (fd >= 0) {
1037 + char *content = default_user_config();
1038 + write_str_in_full(fd, content);
1039 + free(content);
1040 + close(fd);
1041 + }
1042 + else if (errno != EEXIST)
1043 + die_errno(_("cannot create configuration file %s"), config_file);
1044 + }
1045 + launch_editor(config_file, NULL, NULL);
1046 + free(config_file);
1047 +
1048 + return 0;
1049 +}
1050 +
1051 +static int cmd_config_edit(int argc, const char **argv, const char *prefix)
1052 +{
1053 + struct option opts[] = {
1054 + CONFIG_LOCATION_OPTIONS,
1055 + OPT_END(),
1056 + };
1057 +
1058 + argc = parse_options(argc, argv, prefix, opts, builtin_config_edit_usage, 0);
1059 + check_write();
1060 + check_argc(argc, 0, 0);
1061 +
1062 + handle_config_location(prefix);
1063 +
1064 + return show_editor();
1065 +}
1066 +
1067 static struct option builtin_subcommand_options[] = {
1068 OPT_SUBCOMMAND("list", &subcommand, cmd_config_list),
1069 OPT_SUBCOMMAND("get", &subcommand, cmd_config_get),
@@ -1018,6 +1071,7 @@ static struct option builtin_subcommand_options[] = {
1071 OPT_SUBCOMMAND("unset", &subcommand, cmd_config_unset),
1072 OPT_SUBCOMMAND("rename-section", &subcommand, cmd_config_rename_section),
1073 OPT_SUBCOMMAND("remove-section", &subcommand, cmd_config_remove_section),
1074 + OPT_SUBCOMMAND("edit", &subcommand, cmd_config_edit),
1075 OPT_END(),
1076 };
1077
@@ -1144,32 +1198,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
1198 }
1199 }
1200 else if (actions == ACTION_EDIT) {
1147 - char *config_file;
1148 -
1149 - check_argc(argc, 0, 0);
1150 - if (!given_config_source.file && !startup_info->have_repository)
1151 - die(_("not in a git directory"));
1152 - if (given_config_source.use_stdin)
1153 - die(_("editing stdin is not supported"));
1154 - if (given_config_source.blob)
1155 - die(_("editing blobs is not supported"));
1156 - git_config(git_default_config, NULL);
1157 - config_file = given_config_source.file ?
1158 - xstrdup(given_config_source.file) :
1159 - git_pathdup("config");
1160 - if (use_global_config) {
1161 - int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
1162 - if (fd >= 0) {
1163 - char *content = default_user_config();
1164 - write_str_in_full(fd, content);
1165 - free(content);
1166 - close(fd);
1167 - }
1168 - else if (errno != EEXIST)
1169 - die_errno(_("cannot create configuration file %s"), config_file);
1170 - }
1171 - launch_editor(config_file, NULL, NULL);
1172 - free(config_file);
1201 + ret = show_editor();
1202 }
1203 else if (actions == ACTION_SET) {
1204 check_write();
t/t1300-config.sh
+3 -3
@@ -666,7 +666,7 @@ test_expect_success 'setting a value in stdin is an error' '
666 '
667
668 test_expect_success 'editing stdin is an error' '
669 - test_must_fail git config --file - --edit
669 + test_must_fail git config ${mode_prefix}edit --file -
670 '
671
672 test_expect_success 'refer config from subdirectory' '
@@ -1768,7 +1768,7 @@ test_expect_success 'command line overrides environment config' '
1768 test_expect_success 'git config --edit works' '
1769 git config -f tmp test.value no &&
1770 echo test.value=yes >expect &&
1771 - GIT_EDITOR="echo [test]value=yes >" git config -f tmp --edit &&
1771 + GIT_EDITOR="echo [test]value=yes >" git config ${mode_prefix}edit -f tmp &&
1772 git config ${mode_prefix}list -f tmp >actual &&
1773 test_cmp expect actual
1774 '
@@ -1777,7 +1777,7 @@ test_expect_success 'git config --edit respects core.editor' '
1777 git config -f tmp test.value no &&
1778 echo test.value=yes >expect &&
1779 test_config core.editor "echo [test]value=yes >" &&
1780 - git config -f tmp --edit &&
1780 + git config ${mode_prefix}edit -f tmp &&
1781 git config ${mode_prefix}list -f tmp >actual &&
1782 test_cmp expect actual
1783 '