git: allow alias-shadowing deprecated builtins
git-whatchanged(1) is deprecated and you need to pass
`--i-still-use-this` in order to force it to work as before.
There are two affected users, or usages:
1. people who use the command in scripts; and
2. people who are used to using it interactively.
For (1) the replacement is straightforward.[1] But people in (2) might
like the name or be really used to typing it.[3]
An obvious first thought is to suggest aliasing `whatchanged` to the
git-log(1) equivalent.[1] But this doesn’t work and is awkward since you
cannot shadow builtins via aliases.
Now you are left in an uncomfortable limbo; your alias won’t work until
the command is removed for good.
Let’s lift this limitation by allowing *deprecated* builtins to be
shadowed by aliases.
The only observed demand for aliasing has been for git-whatchanged(1),
not for git-pack-redundant(1). But let’s be consistent and treat all
deprecated commands the same.
[1]:
git log --raw --no-merges
With a minor caveat: you get different outputs if you happen to
have empty commits (no changes)[2]
[2]: https://lore.kernel.org/git/20250825085428.GA367101@coredump.intra.peff.net/
[3]: https://lore.kernel.org/git/BL3P221MB0449288C8B0FA448A227FD48833AA@BL3P221MB0449.NAMP221.PROD.OUTLOOK.COM/
Based-on-patch-by: Jeff King <peff@peff.net>
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
parent
b4f9282d8d
commit
bf68b11699
|
|
@ -3,7 +3,8 @@ alias.*::
|
|||
after defining `alias.last = cat-file commit HEAD`, the invocation
|
||||
`git last` is equivalent to `git cat-file commit HEAD`. To avoid
|
||||
confusion and troubles with script usage, aliases that
|
||||
hide existing Git commands are ignored. Arguments are split by
|
||||
hide existing Git commands are ignored except for deprecated
|
||||
commands. Arguments are split by
|
||||
spaces, the usual shell quoting and escaping are supported.
|
||||
A quote pair or a backslash can be used to quote them.
|
||||
+
|
||||
|
|
|
|||
17
git.c
17
git.c
|
|
@ -824,12 +824,29 @@ static void execv_dashed_external(const char **argv)
|
|||
exit(128);
|
||||
}
|
||||
|
||||
static int is_deprecated_command(const char *cmd)
|
||||
{
|
||||
struct cmd_struct *builtin = get_builtin(cmd);
|
||||
return builtin && (builtin->option & DEPRECATED);
|
||||
}
|
||||
|
||||
static int run_argv(struct strvec *args)
|
||||
{
|
||||
int done_alias = 0;
|
||||
struct string_list expanded_aliases = STRING_LIST_INIT_DUP;
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* Allow deprecated commands to be overridden by aliases. This
|
||||
* creates a seamless path forward for people who want to keep
|
||||
* using the name after it is gone, but want to skip the
|
||||
* deprecation complaint in the meantime.
|
||||
*/
|
||||
if (is_deprecated_command(args->v[0]) &&
|
||||
handle_alias(args, &expanded_aliases)) {
|
||||
done_alias = 1;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* If we tried alias and futzed with our environment,
|
||||
* it no longer is safe to invoke builtins directly in
|
||||
|
|
|
|||
|
|
@ -27,6 +27,20 @@ test_expect_success 'looping aliases - internal execution' '
|
|||
test_grep "^fatal: alias loop detected: expansion of" output
|
||||
'
|
||||
|
||||
test_expect_success 'looping aliases - deprecated builtins' '
|
||||
test_config alias.whatchanged pack-redundant &&
|
||||
test_config alias.pack-redundant whatchanged &&
|
||||
cat >expect <<-EOF &&
|
||||
${SQ}whatchanged${SQ} is aliased to ${SQ}pack-redundant${SQ}
|
||||
${SQ}pack-redundant${SQ} is aliased to ${SQ}whatchanged${SQ}
|
||||
fatal: alias loop detected: expansion of ${SQ}whatchanged${SQ} does not terminate:
|
||||
whatchanged <==
|
||||
pack-redundant ==>
|
||||
EOF
|
||||
test_must_fail git whatchanged -h 2>actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
# This test is disabled until external loops are fixed, because would block
|
||||
# the test suite for a full minute.
|
||||
#
|
||||
|
|
@ -55,4 +69,30 @@ test_expect_success 'tracing a shell alias with arguments shows trace of prepare
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
can_alias_deprecated_builtin () {
|
||||
cmd="$1" &&
|
||||
# some git(1) commands will fail for `-h` (the case for
|
||||
# git-status as of 2025-09-07)
|
||||
test_might_fail git status -h >expect &&
|
||||
test_file_not_empty expect &&
|
||||
test_might_fail git -c alias."$cmd"=status "$cmd" -h >actual &&
|
||||
test_cmp expect actual
|
||||
}
|
||||
|
||||
test_expect_success 'can alias-shadow deprecated builtins' '
|
||||
for cmd in $(git --list-cmds=deprecated)
|
||||
do
|
||||
can_alias_deprecated_builtin "$cmd" || return 1
|
||||
done
|
||||
'
|
||||
|
||||
test_expect_success 'can alias-shadow via two deprecated builtins' '
|
||||
# some git(1) commands will fail... (see above)
|
||||
test_might_fail git status -h >expect &&
|
||||
test_file_not_empty expect &&
|
||||
test_might_fail git -c alias.whatchanged=pack-redundant \
|
||||
-c alias.pack-redundant=status whatchanged -h >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
|
|||
Loading…
Reference in New Issue