As discussed in the thread for v1 of this patch [1] [2], this changes the
rules for "git foo --help" when foo is an alias.

(0) When invoked as "git help foo", we continue to print the "foo is
aliased to bar" message and nothing else.

(1) If foo is an alias for a shell command, print "foo is aliased to
!bar" as usual.

(2) Otherwise, break the alias string into words, and pretend that "git
word0 --help" was called.

At least for me, getting the man page for git-cherry-pick directly with
"git cp --help" is more useful (and how I expect an alias to behave)
than the short "is aliased to" notice. It is also consistent with
"--help" generally providing more comprehensive help than "-h".

I believe that printing the "is aliased to" message also in case (2) has
value: Depending on pager setup, or if the user has help.format=web, the
message is still present immediately above the prompt when the user
quits the pager/returns to the terminal. That serves as an explanation
for why one was redirected to "man git-cherry-pick" from "git cp
--help", and if cp is actually 'cherry-pick -n', it reminds the user
that using cp has some flag implicitly set before firing off the next
command.

It also provides some useful info in case we end up erroring out, either
in the "bad alias string" check, or in the "No manual entry for gitbar"
case.

[1] https://public-inbox.org/git/20180926102636.30691-1...@rasmusvillemoes.dk/
[2] https://public-inbox.org/git/20180926184914.gc30...@sigill.intra.peff.net/

Signed-off-by: Rasmus Villemoes <r...@rasmusvillemoes.dk>
---
 builtin/help.c | 34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/builtin/help.c b/builtin/help.c
index 8d4f6dd301..e0e3fe62e9 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -415,9 +415,37 @@ static const char *check_git_cmd(const char* cmd)
 
        alias = alias_lookup(cmd);
        if (alias) {
-               printf_ln(_("'%s' is aliased to '%s'"), cmd, alias);
-               free(alias);
-               exit(0);
+               const char **argv;
+               int count;
+
+               /*
+                * handle_builtin() in git.c rewrites "git cmd --help"
+                * to "git help --exclude-guides cmd", so we can use
+                * exclude_guides to distinguish "git cmd --help" from
+                * "git help cmd". In the latter case, or if cmd is an
+                * alias for a shell command, just print the alias
+                * definition.
+                */
+               if (!exclude_guides || alias[0] == '!') {
+                       printf_ln(_("'%s' is aliased to '%s'"), cmd, alias);
+                       free(alias);
+                       exit(0);
+               }
+               /*
+                * Otherwise, we pretend that the command was "git
+                * word0 --help". We use split_cmdline() to get the
+                * first word of the alias, to ensure that we use the
+                * same rules as when the alias is actually
+                * used. split_cmdline() modifies alias in-place.
+                */
+               fprintf_ln(stderr, _("'%s' is aliased to '%s'"), cmd, alias);
+               count = split_cmdline(alias, &argv);
+               if (count < 0)
+                       die(_("bad alias.%s string: %s"), cmd,
+                           split_cmdline_strerror(count));
+               free(argv);
+               UNLEAK(alias);
+               return alias;
        }
 
        if (exclude_guides)
-- 
2.19.0

Reply via email to