diff mbox series

[v3,2/2] completion: bash: check for alias loop

Message ID 20201110020343.548848-3-felipe.contreras@gmail.com (mailing list archive)
State Accepted
Commit c2822a842dc993722a9d6f8226189312b95d8801
Headers show
Series completion: bash: support for recursive aliases | expand

Commit Message

Felipe Contreras Nov. 10, 2020, 2:03 a.m. UTC
We don't want to be stuck in an endless cycle.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/completion/git-completion.bash | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

Comments

SZEDER Gábor Nov. 12, 2020, 10:02 a.m. UTC | #1
On Mon, Nov 09, 2020 at 08:03:43PM -0600, Felipe Contreras wrote:
> We don't want to be stuck in an endless cycle.
> 
> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
> ---
>  contrib/completion/git-completion.bash | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index eb00d9ba22..ce0dc1e0f8 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -1121,11 +1121,16 @@ __git_pretty_aliases ()
>  # __git_aliased_command requires 1 argument
>  __git_aliased_command ()
>  {
> -	local cur=$1 last word cmdline
> +	local cur=$1 list word cmdline
>  
>  	while [[ -n "$cur" ]]; do
> +		if [[ "$list" == *"$cur "* ]]; then

I suspect the right hand side should be *" $cur "* ...

> +			# loop detected
> +			return
> +		fi
> +
>  		cmdline=$(__git config --get "alias.$cur")
> -		last=$cur
> +		list="$cur $list"

... and this should be list=" $cur $list", because otherwise a partial
match is possible and would be mistaken for a loop (though I didn't
actually test whether that's indeed the case).

>  		cur=
>  
>  		for word in $cmdline; do
> @@ -1149,7 +1154,7 @@ __git_aliased_command ()
>  		done
>  	done
>  
> -	cur=$last
> +	cur="${list%% *}"
>  	if [[ "$cur" != "$1" ]]; then
>  		echo "$cur"
>  	fi
> -- 
> 2.29.2
>
Junio C Hamano Nov. 12, 2020, 5:20 p.m. UTC | #2
SZEDER Gábor <szeder.dev@gmail.com> writes:

>>  	while [[ -n "$cur" ]]; do
>> +		if [[ "$list" == *"$cur "* ]]; then
>
> I suspect the right hand side should be *" $cur "* ...
>
>> +			# loop detected
>> +			return
>> +		fi
>> +
>>  		cmdline=$(__git config --get "alias.$cur")
>> -		last=$cur
>> +		list="$cur $list"
>
> ... and this should be list=" $cur $list", because otherwise a partial
> match is possible and would be mistaken for a loop (though I didn't
> actually test whether that's indeed the case).

Traditionist may use

	list=
	while :
	do
		cur=$(obtain cur somehow)
                case " $list " in
                *" $cur "*) : cur appears in list ;;
                esac
                list="$cur${list+ }$list"
	done

to make the invariant "$list is a SP-separated tokens, no extra SP on
either ends" and I think the same idea would work with [[ $a == $b ]],
but "one SP on both ends, two SPs in between" like yours do is OK, too.

Not keeping excess SPs out of the list (unlike the above "no extra
SP on ends") means how "finally, take the first token in the list,
that's the answer" is coded, though.  You'd need to split off the
leading SP from it (below).

>>  		cur=
>>  
>>  		for word in $cmdline; do
>> @@ -1149,7 +1154,7 @@ __git_aliased_command ()
>>  		done
>>  	done
>>  
>> -	cur=$last
>> +	cur="${list%% *}"
>>  	if [[ "$cur" != "$1" ]]; then
>>  		echo "$cur"
>>  	fi
>> -- 
>> 2.29.2
>>
diff mbox series

Patch

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index eb00d9ba22..ce0dc1e0f8 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1121,11 +1121,16 @@  __git_pretty_aliases ()
 # __git_aliased_command requires 1 argument
 __git_aliased_command ()
 {
-	local cur=$1 last word cmdline
+	local cur=$1 list word cmdline
 
 	while [[ -n "$cur" ]]; do
+		if [[ "$list" == *"$cur "* ]]; then
+			# loop detected
+			return
+		fi
+
 		cmdline=$(__git config --get "alias.$cur")
-		last=$cur
+		list="$cur $list"
 		cur=
 
 		for word in $cmdline; do
@@ -1149,7 +1154,7 @@  __git_aliased_command ()
 		done
 	done
 
-	cur=$last
+	cur="${list%% *}"
 	if [[ "$cur" != "$1" ]]; then
 		echo "$cur"
 	fi