diff mbox series

[3/3] mergetool: use shell variable magic instead of `awk`

Message ID d6675b02918364736ec74db937481127ab7d8990.1560152205.git.j6t@kdbg.org (mailing list archive)
State New, archived
Headers show
Series Reduce number of processes spawned by git-mergetool | expand

Commit Message

Johannes Sixt June 10, 2019, 8:59 a.m. UTC
git-mergetool spawns an enormous amount of processes. For this reason,
the test script, t7610, is exceptionally slow, in particular, on
Windows. Most of the processes are invocations of git, but there are
also some that can be replaced with shell builtins. Avoid repeated
calls of `git ls-files` and `awk`.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
 git-mergetool.sh | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

Comments

Junio C Hamano June 10, 2019, 5:21 p.m. UTC | #1
Johannes Sixt <j6t@kdbg.org> writes:

> +	# here, $IFS is just a LF
> +	for line in $f
> +	do
> +		mode=${line%% *}		# 1st word
> +		sha1=${line#"$mode "}
> +		sha1=${sha1%% *}		# 2nd word
> +		case "${line#$mode $sha1 }" in	# remainder
> +		'1	'*)
> +			base_mode=$mode
> +			;;
> +		'2	'*)
> +			local_mode=$mode local_sha1=$sha1
> +			;;
> +		'3	'*)
> +			remote_mode=$mode remote_sha1=$sha1
> +			;;
> +		esac
> +	done

OK.  $mode won't have any glob metacharacter, and there is only one
invocation of "ls-files -u", which is now two fewer processes ;-)

>  
>  	if is_submodule "$local_mode" || is_submodule "$remote_mode"
>  	then
>  		echo "Submodule merge conflict for '$MERGED':"
> -		local_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $2;}')
> -		remote_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $2;}')
>  		describe_file "$local_mode" "local" "$local_sha1"
>  		describe_file "$remote_mode" "remote" "$remote_sha1"
>  		resolve_submodule_merge
Johannes Sixt June 10, 2019, 10:01 p.m. UTC | #2
Am 10.06.19 um 19:21 schrieb Junio C Hamano:
> Johannes Sixt <j6t@kdbg.org> writes:
> 
>> +	# here, $IFS is just a LF
>> +	for line in $f
>> +	do
>> +		mode=${line%% *}		# 1st word
>> +		sha1=${line#"$mode "}
>> +		sha1=${sha1%% *}		# 2nd word
>> +		case "${line#$mode $sha1 }" in	# remainder
>> +		'1	'*)
>> +			base_mode=$mode
>> +			;;
>> +		'2	'*)
>> +			local_mode=$mode local_sha1=$sha1
>> +			;;
>> +		'3	'*)
>> +			remote_mode=$mode remote_sha1=$sha1
>> +			;;
>> +		esac
>> +	done
> 
> OK.  $mode won't have any glob metacharacter, and there is only one
> invocation of "ls-files -u", which is now two fewer processes ;-)

I think it's better than that: there're about 9 fewer from the context
that you didn't quote:

-	base_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==1) print $1;}')
-	local_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}')
-	remote_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}')

and sometimes the 6 from below on top of that. But I won't insist in
having counted correctly ;-)

>>  
>>  	if is_submodule "$local_mode" || is_submodule "$remote_mode"
>>  	then
>>  		echo "Submodule merge conflict for '$MERGED':"
>> -		local_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $2;}')
>> -		remote_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $2;}')
>>  		describe_file "$local_mode" "local" "$local_sha1"
>>  		describe_file "$remote_mode" "remote" "$remote_sha1"
>>  		resolve_submodule_merge
diff mbox series

Patch

diff --git a/git-mergetool.sh b/git-mergetool.sh
index 8a937f680f..e3f6d543fb 100755
--- a/git-mergetool.sh
+++ b/git-mergetool.sh
@@ -279,15 +279,30 @@  merge_file () {
 	REMOTE="$MERGETOOL_TMPDIR/${BASE}_REMOTE_$$$ext"
 	BASE="$MERGETOOL_TMPDIR/${BASE}_BASE_$$$ext"
 
-	base_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==1) print $1;}')
-	local_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}')
-	remote_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}')
+	base_mode= local_mode= remote_mode=
+
+	# here, $IFS is just a LF
+	for line in $f
+	do
+		mode=${line%% *}		# 1st word
+		sha1=${line#"$mode "}
+		sha1=${sha1%% *}		# 2nd word
+		case "${line#$mode $sha1 }" in	# remainder
+		'1	'*)
+			base_mode=$mode
+			;;
+		'2	'*)
+			local_mode=$mode local_sha1=$sha1
+			;;
+		'3	'*)
+			remote_mode=$mode remote_sha1=$sha1
+			;;
+		esac
+	done
 
 	if is_submodule "$local_mode" || is_submodule "$remote_mode"
 	then
 		echo "Submodule merge conflict for '$MERGED':"
-		local_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $2;}')
-		remote_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $2;}')
 		describe_file "$local_mode" "local" "$local_sha1"
 		describe_file "$remote_mode" "remote" "$remote_sha1"
 		resolve_submodule_merge