All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] alias: document caveats and add trace of prepared command
@ 2024-05-22  2:41 Ian Wienand
  2024-05-22  3:29 ` Eric Sunshine
                   ` (2 more replies)
  0 siblings, 3 replies; 43+ messages in thread
From: Ian Wienand @ 2024-05-22  2:41 UTC (permalink / raw)
  To: git; +Cc: Ian Wienand

There are a number of hidden caveats when using command/shell
expansion ("!") in an alias.  The command is exec'd, unless it can be
split, when it is then run as an argument to "sh -c".  Split commands
have "$@" appended.

Firstly this updates the documentation to explain this a little
clearer.

Secondly, this adds a trace point in prepare_cmd where this
substitution is done, so we can see the command being run without
having to resort to strace/code inspection.  e.g. "test = !echo" you
will show:

 $ GIT_TRACE=1 git test hello
 10:58:56.877234 git.c:755               trace: exec: git-test hello
 10:58:56.877382 run-command.c:657       trace: run_command: git-test hello
 10:58:56.878655 run-command.c:657       trace: run_command: echo hello
 10:58:56.878747 run-command.c:437       trace: prepare_cmd: /usr/bin/echo hello
 hello

For a "split" alias, e.g. test = "!echo $*" you will see

 $ GIT_TRACE=1 git test hello
 11:00:45.959420 git.c:755               trace: exec: git-test hello
 11:00:45.959737 run-command.c:657       trace: run_command: git-test hello
 11:00:45.961424 run-command.c:657       trace: run_command: 'echo $*' hello
 11:00:45.961528 run-command.c:437       trace: prepare_cmd: /bin/sh -c 'echo $* "$@"' 'echo $*' hello
 hello hello

which clearly shows you the appended "$@".  This can be very helpful
when an alias is giving you an unexpected synatx error that is very
difficult figure out from only the run_command trace point,
e.g. test = "!for i in 1 2 3; do echo $i; done"

 $ GIT_TRACE=1 test hello
 11:02:39.813030 git.c:755               trace: exec: git-test hello
 11:02:39.813233 run-command.c:657       trace: run_command: git-test hello
 11:02:39.814384 run-command.c:657       trace: run_command: 'for i in 1 2 3; do echo $i; done' hello
 11:02:39.814468 run-command.c:437       trace: prepare_cmd: /bin/sh -c 'for i in 1 2 3; do echo $i; done "$@"' 'for i in 1 2 3; do echo $i; done' hello
 for i in 1 2 3; do echo $i; done: -c: line 1: syntax error near unexpected token `"$@"'
 for i in 1 2 3; do echo $i; done: -c: line 1: `for i in 1 2 3; do echo $i; done "$@"'

Signed-off-by: Ian Wienand <iwienand@redhat.com>
---
 Documentation/config/alias.txt | 26 +++++++++++++++++++++-----
 run-command.c                  |  1 +
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/Documentation/config/alias.txt b/Documentation/config/alias.txt
index 01df96fab3..a3f090d79d 100644
--- a/Documentation/config/alias.txt
+++ b/Documentation/config/alias.txt
@@ -21,8 +21,24 @@ If the alias expansion is prefixed with an exclamation point,
 it will be treated as a shell command.  For example, defining
 `alias.new = !gitk --all --not ORIG_HEAD`, the invocation
 `git new` is equivalent to running the shell command
-`gitk --all --not ORIG_HEAD`.  Note that shell commands will be
-executed from the top-level directory of a repository, which may
-not necessarily be the current directory.
-`GIT_PREFIX` is set as returned by running `git rev-parse --show-prefix`
-from the original current directory. See linkgit:git-rev-parse[1].
+`gitk --all --not ORIG_HEAD`.  Note:
++
+* Shell commands will be executed from the top-level directory of a
+  repository, which may not necessarily be the current directory.
+* `GIT_PREFIX` is set as returned by running `git rev-parse --show-prefix`
+  from the original current directory. See linkgit:git-rev-parse[1].
+* Single commands will be executed directly.  Commands that can be "split"
+  (contain whitespace or shell-reserved characters) will be run as shell
+  commands via an argument to `sh -c`.
+* When arguments are present to a "split" command running in a shell,
+  the shell command will have `"$@"` appended.  The first non-command
+  argument to `sh -c` (i.e. `$0` to the command) is always the alias
+  string, and other user specified arguments will follow.
+** This may initially be confusing if your command references argument
+   variables or is not expecting the presence of `"$@"`.  For example:
+   `alias.echo = "!echo $1"` when run as `git echo arg` will execute
+   `sh -c "echo $1 $@" "echo $1" "1"` resulting in output `1 1`.
+   An alias `alias.for = "!for i in 1 2 3; do echo $i; done"` will fail
+   if any arguments are specified to `git for` as the appended `"$@"` will
+   create invalid shell syntax.  Setting `GIT_TRACE=1` can help debug
+   the command being run.
diff --git a/run-command.c b/run-command.c
index 1b821042b4..36b2b2f194 100644
--- a/run-command.c
+++ b/run-command.c
@@ -435,6 +435,7 @@ static int prepare_cmd(struct strvec *out, const struct child_process *cmd)
 		}
 	}
 
+	trace_argv_printf(&out->v[1], "trace: prepare_cmd:");
 	return 0;
 }
 
-- 
2.45.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2024-05-27 17:48 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-22  2:41 [PATCH] alias: document caveats and add trace of prepared command Ian Wienand
2024-05-22  3:29 ` Eric Sunshine
2024-05-22 16:07 ` Junio C Hamano
2024-05-23  0:38   ` Ian Wienand
2024-05-23  4:20 ` [PATCH v2 1/3] Documentation: alias: rework notes into points Ian Wienand
2024-05-23  4:20   ` [PATCH v2 2/3] Documentation: alias: add notes on shell expansion Ian Wienand
2024-05-23  4:20   ` [PATCH v2 3/3] run-command: show prepared command Ian Wienand
2024-05-23  4:27   ` [PATCH v2 1/3] Documentation: alias: rework notes into points Eric Sunshine
2024-05-23  4:39     ` Ian Wienand
2024-05-23  4:37   ` [PATCH v3 " Ian Wienand
2024-05-23  4:37     ` [PATCH v3 2/3] Documentation: alias: add notes on shell expansion Ian Wienand
2024-05-23  4:37     ` [PATCH v3 3/3] run-command: show prepared command Ian Wienand
2024-05-23 15:29       ` Junio C Hamano
2024-05-23 23:40         ` Junio C Hamano
2024-05-24  6:09           ` Junio C Hamano
2024-05-24  7:18             ` Ian Wienand
2024-05-24 15:33               ` Junio C Hamano
2024-05-24  0:43         ` Ian Wienand
2024-05-24 17:50           ` Junio C Hamano
2024-05-25  1:13             ` Ian Wienand
2024-05-23 15:14     ` [PATCH v3 1/3] Documentation: alias: rework notes into points Junio C Hamano
2024-05-24  7:32     ` [PATCH v4 " Ian Wienand
2024-05-24  7:32       ` [PATCH v4 2/3] Documentation: alias: add notes on shell expansion Ian Wienand
2024-05-24  7:32       ` [PATCH v4 3/3] run-command: show prepared command Ian Wienand
2024-05-24 19:16         ` Junio C Hamano
2024-05-24 19:58           ` Junio C Hamano
2024-05-25  1:14           ` Ian Wienand
2024-05-25  1:20       ` [PATCH v5 1/3] Documentation: alias: rework notes into points Ian Wienand
2024-05-25  1:20         ` [PATCH v5 2/3] Documentation: alias: add notes on shell expansion Ian Wienand
2024-05-25  1:20         ` [PATCH v5 3/3] run-command: show prepared command Ian Wienand
2024-05-25  5:44           ` Junio C Hamano
2024-05-25  6:06           ` Junio C Hamano
2024-05-25 23:49             ` Ian Wienand
2024-05-25 23:44         ` [PATCH v6 1/3] Documentation: alias: rework notes into points Ian Wienand
2024-05-25 23:44           ` [PATCH v6 2/3] Documentation: alias: add notes on shell expansion Ian Wienand
2024-05-26 23:26             ` Junio C Hamano
2024-05-27  0:22               ` Ian Wienand
2024-05-25 23:44           ` [PATCH v6 3/3] run-command: show prepared command Ian Wienand
2024-05-26 16:20             ` Junio C Hamano
2024-05-27  0:30           ` [PATCH v7 1/3] Documentation: alias: rework notes into points Ian Wienand
2024-05-27  0:30             ` [PATCH v7 2/3] Documentation: alias: add notes on shell expansion Ian Wienand
2024-05-27 17:48               ` Junio C Hamano
2024-05-27  0:30             ` [PATCH v7 3/3] run-command: show prepared command Ian Wienand

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.