Subject: [PATCH v2] scalar: accept -C and -c options before the subcommand

From: "Johannes Schindelin via GitGitGadget" <[email-masked]>
Date: Fri, 28 Jan 2022 14:31:57 +0000

From: Johannes Schindelin <[email-masked]>

The `git` executable has these two very useful options:

-C <directory>:
	switch to the specified directory before performing any actions

-c <key>=<value>:
	temporarily configure this setting for the duration of the
	specified scalar subcommand

With this commit, we teach the `scalar` executable the same trick.

Note: It might look like a good idea to try to reuse the
`handle_options()` function in `git.c` instead of replicating only the
`-c`/`-C` part. However, that function is not only not in `libgit.a`, it
is also intricately entangled with the rest of the code in `git.c` that
is necessary e.g. to handle `--paginate`. Besides, no other option
handled by that `handle_options()` function is relevant to Scalar,
therefore the cost of refactoring vastly would outweigh the benefit.

Signed-off-by: Johannes Schindelin <[email-masked]>
---
    scalar: accept -C and -c options
    
    This makes the scalar command a bit more handy by offering the same -c
    <key>=<value> and -C <directory> options as the git command.
    
    Changes since v1:
    
     * Added a regression test case.
     * Augmented the commit message with a brief analysis why we're choosing
       not to refactor git.c:handle_options() but instead copy-edit the
       dozen or so lines that we want.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1130%2Fdscho%2Fscalar-c-and-C-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1130/dscho/scalar-c-and-C-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1130

Range-diff vs v1:

 1:  8f2af8c3ec1 ! 1:  d7ee2d03b04 scalar: accept -C and -c options before the subcommand
     @@ Commit message
      
          With this commit, we teach the `scalar` executable the same trick.
      
     +    Note: It might look like a good idea to try to reuse the
     +    `handle_options()` function in `git.c` instead of replicating only the
     +    `-c`/`-C` part. However, that function is not only not in `libgit.a`, it
     +    is also intricately entangled with the rest of the code in `git.c` that
     +    is necessary e.g. to handle `--paginate`. Besides, no other option
     +    handled by that `handle_options()` function is relevant to Scalar,
     +    therefore the cost of refactoring vastly would outweigh the benefit.
     +
          Signed-off-by: Johannes Schindelin <[email-masked]>
      
       ## contrib/scalar/scalar.c ##
     @@ contrib/scalar/scalar.txt: The `scalar` command implements various subcommands,
       COMMANDS
       --------
       
     +
     + ## contrib/scalar/t/t9099-scalar.sh ##
     +@@ contrib/scalar/t/t9099-scalar.sh: test_expect_success 'scalar delete with enlistment' '
     + 	test_path_is_missing cloned
     + '
     + 
     ++test_expect_success 'scalar supports -c/-C' '
     ++	test_when_finished "scalar delete sub" &&
     ++	git init sub &&
     ++	scalar -C sub -c status.aheadBehind=bogus register &&
     ++	test -z "$(git -C sub config --local status.aheadBehind)" &&
     ++	test true = "$(git -C sub config core.preloadIndex)"
     ++'
     ++
     + test_done

 contrib/scalar/scalar.c          | 22 +++++++++++++++++++++-
 contrib/scalar/scalar.txt        | 10 ++++++++++
 contrib/scalar/t/t9099-scalar.sh |  8 ++++++++
 3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c
index 1ce9c2b00e8..7db2a97416e 100644
--- a/contrib/scalar/scalar.c
+++ b/contrib/scalar/scalar.c
@@ -808,6 +808,25 @@ int cmd_main(int argc, const char **argv)
 	struct strbuf scalar_usage = STRBUF_INIT;
 	int i;
 
+	while (argc > 1 && *argv[1] == '-') {
+		if (!strcmp(argv[1], "-C")) {
+			if (argc < 3)
+				die(_("-C requires a <directory>"));
+			if (chdir(argv[2]) < 0)
+				die_errno(_("could not change to '%s'"),
+					  argv[2]);
+			argc -= 2;
+			argv += 2;
+		} else if (!strcmp(argv[1], "-c")) {
+			if (argc < 3)
+				die(_("-c requires a <key>=<value> argument"));
+			git_config_push_parameter(argv[2]);
+			argc -= 2;
+			argv += 2;
+		} else
+			break;
+	}
+
 	if (argc > 1) {
 		argv++;
 		argc--;
@@ -818,7 +837,8 @@ int cmd_main(int argc, const char **argv)
 	}
 
 	strbuf_addstr(&scalar_usage,
-		      N_("scalar <command> [<options>]\n\nCommands:\n"));
+		      N_("scalar [-C <directory>] [-c <key>=<value>] "
+			 "<command> [<options>]\n\nCommands:\n"));
 	for (i = 0; builtins[i].name; i++)
 		strbuf_addf(&scalar_usage, "\t%s\n", builtins[i].name);
 
diff --git a/contrib/scalar/scalar.txt b/contrib/scalar/scalar.txt
index f416d637289..cf4e5b889cc 100644
--- a/contrib/scalar/scalar.txt
+++ b/contrib/scalar/scalar.txt
@@ -36,6 +36,16 @@ The `scalar` command implements various subcommands, and different options
 depending on the subcommand. With the exception of `clone`, `list` and
 `reconfigure --all`, all subcommands expect to be run in an enlistment.
 
+The following options can be specified _before_ the subcommand:
+
+-C <directory>::
+	Before running the subcommand, change the working directory. This
+	option imitates the same option of linkgit:git[1].
+
+-c <key>=<value>::
+	For the duration of running the specified subcommand, configure this
+	setting. This option imitates the same option of linkgit:git[1].
+
 COMMANDS
 --------
 
diff --git a/contrib/scalar/t/t9099-scalar.sh b/contrib/scalar/t/t9099-scalar.sh
index 2e1502ad45e..89781568f43 100755
--- a/contrib/scalar/t/t9099-scalar.sh
+++ b/contrib/scalar/t/t9099-scalar.sh
@@ -85,4 +85,12 @@ test_expect_success 'scalar delete with enlistment' '
 	test_path_is_missing cloned
 '
 
+test_expect_success 'scalar supports -c/-C' '
+	test_when_finished "scalar delete sub" &&
+	git init sub &&
+	scalar -C sub -c status.aheadBehind=bogus register &&
+	test -z "$(git -C sub config --local status.aheadBehind)" &&
+	test true = "$(git -C sub config core.preloadIndex)"
+'
+
 test_done

base-commit: ddc35d833dd6f9e8946b09cecd3311b8aa18d295
-- 
gitgitgadget