diff mbox series

[v5,13/14] builtin/config: introduce "edit" subcommand

Message ID 1893c23afc982e1d442f50b5e4b8ab0073aaa05d.1714982328.git.ps@pks.im (mailing list archive)
State Accepted
Commit 3cbace5ee0e1d9a959846241ca73d545b8f70878
Headers show
Series builtin/config: introduce subcommands | expand

Commit Message

Patrick Steinhardt May 6, 2024, 8:56 a.m. UTC
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>
---
 Documentation/git-config.txt | 17 ++++----
 builtin/config.c             | 81 ++++++++++++++++++++++++------------
 t/t1300-config.sh            |  6 +--
 3 files changed, 68 insertions(+), 36 deletions(-)
diff mbox series

Patch

diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index ef46520c15..65c645d461 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -15,8 +15,8 @@  SYNOPSIS
 'git config unset' [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>
 'git config rename-section' [<file-option>] <old-name> <new-name>
 'git config remove-section' [<file-option>] <name>
+'git config edit' [<file-option>]
 'git config' [<file-option>] --get-colorbool <name> [<stdout-is-tty>]
-'git config' [<file-option>] -e | --edit
 
 DESCRIPTION
 -----------
@@ -98,6 +98,11 @@  rename-section::
 remove-section::
 	Remove the given section from the configuration file.
 
+edit::
+	Opens an editor to modify the specified config file; either
+	`--system`, `--global`, `--local` (default), `--worktree`, or
+	`--file <config-file>`.
+
 [[OPTIONS]]
 OPTIONS
 -------
@@ -274,12 +279,6 @@  Valid `<type>`'s include:
 	When the color setting for `name` is undefined, the command uses
 	`color.ui` as fallback.
 
--e::
---edit::
-	Opens an editor to modify the specified config file; either
-	`--system`, `--global`, `--local` (default), `--worktree`, or
-	`--file <config-file>`.
-
 --[no-]includes::
 	Respect `include.*` directives in config files when looking up
 	values. Defaults to `off` when a specific file is given (e.g.,
@@ -336,6 +335,10 @@  recommended to migrate to the new syntax.
 --remove-section <name>::
 	Replaced by `git config remove-section <name>`.
 
+-e::
+--edit::
+	Replaced by `git config edit`.
+
 CONFIGURATION
 -------------
 `pager.config` is only respected when listing configuration, i.e., when
diff --git a/builtin/config.c b/builtin/config.c
index cea03fb517..8f7fa8f31a 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -22,6 +22,7 @@  static const char *const builtin_config_usage[] = {
 	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>]"),
 	NULL
 };
 
@@ -55,6 +56,11 @@  static const char *const builtin_config_remove_section_usage[] = {
 	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;
@@ -1011,6 +1017,53 @@  static int cmd_config_remove_section(int argc, const char **argv, const char *pr
 	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();
+}
+
 static struct option builtin_subcommand_options[] = {
 	OPT_SUBCOMMAND("list", &subcommand, cmd_config_list),
 	OPT_SUBCOMMAND("get", &subcommand, cmd_config_get),
@@ -1018,6 +1071,7 @@  static struct option builtin_subcommand_options[] = {
 	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),
 	OPT_END(),
 };
 
@@ -1144,32 +1198,7 @@  int cmd_config(int argc, const char **argv, const char *prefix)
 		}
 	}
 	else if (actions == ACTION_EDIT) {
-		char *config_file;
-
-		check_argc(argc, 0, 0);
-		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);
+		ret = show_editor();
 	}
 	else if (actions == ACTION_SET) {
 		check_write();
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 9d71ec1260..f3c4d28e06 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -666,7 +666,7 @@  test_expect_success 'setting a value in stdin is an error' '
 '
 
 test_expect_success 'editing stdin is an error' '
-	test_must_fail git config --file - --edit
+	test_must_fail git config ${mode_prefix}edit --file -
 '
 
 test_expect_success 'refer config from subdirectory' '
@@ -1768,7 +1768,7 @@  test_expect_success 'command line overrides environment config' '
 test_expect_success 'git config --edit works' '
 	git config -f tmp test.value no &&
 	echo test.value=yes >expect &&
-	GIT_EDITOR="echo [test]value=yes >" git config -f tmp --edit &&
+	GIT_EDITOR="echo [test]value=yes >" git config ${mode_prefix}edit -f tmp &&
 	git config ${mode_prefix}list -f tmp >actual &&
 	test_cmp expect actual
 '
@@ -1777,7 +1777,7 @@  test_expect_success 'git config --edit respects core.editor' '
 	git config -f tmp test.value no &&
 	echo test.value=yes >expect &&
 	test_config core.editor "echo [test]value=yes >" &&
-	git config -f tmp --edit &&
+	git config ${mode_prefix}edit -f tmp &&
 	git config ${mode_prefix}list -f tmp >actual &&
 	test_cmp expect actual
 '