rc git.kak: fix blame-jump for commits with special characters
Commit 53d9b9b67
(Escaping tweak in git.kak, 2024-02-06) broke
blame-jump when the commit subject contains a single quote.
(Also on unbalanced "{" which is a rare edge case but we already have
it in our Git history.)
git.kak assumes that filenames don't contain ' or unbalanced {,
but we can't really make that assumption about people's names or
commit subjects.
Unfortunately the escaping here is very messy. We need to pass
arbitrary text to callbacks; maybe we should have closures that can
capture private temporary registers.
This commit is contained in:
parent
b838d58e1a
commit
e1fd2351e0
|
@ -166,16 +166,16 @@ define-command -params 1.. \
|
||||||
mkfifo ${output}
|
mkfifo ${output}
|
||||||
( git "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null
|
( git "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null
|
||||||
|
|
||||||
printf %s "evaluate-commands -try-client '$kak_opt_docsclient' %{
|
printf %s "evaluate-commands -try-client '$kak_opt_docsclient' '
|
||||||
edit! -fifo ${output} *git*
|
edit! -fifo ${output} *git*
|
||||||
set-option buffer filetype ${filetype}
|
set-option buffer filetype ${filetype}
|
||||||
$(hide_blame)
|
$(hide_blame)
|
||||||
set-option buffer git_blob %{}
|
set-option buffer git_blob %{}
|
||||||
hook -always -once buffer BufCloseFifo .* %{
|
hook -always -once buffer BufCloseFifo .* ''
|
||||||
nop %sh{ rm -r $(dirname ${output}) }
|
nop %sh{ rm -r $(dirname ${output}) }
|
||||||
$(printf %s "${on_close_fifo}" | sed s/\'/\'\'/g)
|
$(printf %s "${on_close_fifo}" | sed "s/'/''''/g")
|
||||||
}
|
''
|
||||||
}"
|
'"
|
||||||
}
|
}
|
||||||
|
|
||||||
hide_blame() {
|
hide_blame() {
|
||||||
|
|
|
@ -13,6 +13,7 @@ Source structure
|
||||||
└── compose
|
└── compose
|
||||||
└── …
|
└── …
|
||||||
├── [enabled] → applicability
|
├── [enabled] → applicability
|
||||||
|
├── [env] → environment setup
|
||||||
├── [rc] → configuration
|
├── [rc] → configuration
|
||||||
├── [in] → start file
|
├── [in] → start file
|
||||||
├── cmd → command
|
├── cmd → command
|
||||||
|
@ -41,6 +42,9 @@ the test is assumed to be not applicable to the current environment
|
||||||
isn't useful on a different OS)
|
isn't useful on a different OS)
|
||||||
and will be silently skipped.
|
and will be silently skipped.
|
||||||
|
|
||||||
|
+env+ is optional.
|
||||||
|
If it exists, it will be sourced before starting Kakoune.
|
||||||
|
|
||||||
+rc+ is optional
|
+rc+ is optional
|
||||||
and should contain a sequence of commands,
|
and should contain a sequence of commands,
|
||||||
_e.g._, +set-option+, +define-command+, +declare-option+.
|
_e.g._, +set-option+, +define-command+, +declare-option+.
|
||||||
|
|
53
test/run
53
test/run
|
@ -28,7 +28,7 @@ main() {
|
||||||
else
|
else
|
||||||
session_path="${TMPDIR:-/tmp}/kakoune/${USER}/$session"
|
session_path="${TMPDIR:-/tmp}/kakoune/${USER}/$session"
|
||||||
fi
|
fi
|
||||||
trap "rm -R $work" EXIT
|
trap "rm -Rf $work" EXIT
|
||||||
|
|
||||||
number_tests=0
|
number_tests=0
|
||||||
number_failures=0
|
number_failures=0
|
||||||
|
@ -47,13 +47,18 @@ main() {
|
||||||
env_vars=$(ls -1 kak_* 2>/dev/null)
|
env_vars=$(ls -1 kak_* 2>/dev/null)
|
||||||
number_tests=$(($number_tests + 1))
|
number_tests=$(($number_tests + 1))
|
||||||
mkdir -p $work/$dir
|
mkdir -p $work/$dir
|
||||||
cp in cmd rc $work/$dir/ 2>/dev/null
|
cp in cmd rc env $work/$dir/ 2>/dev/null
|
||||||
cd $work/$dir;
|
cd $work/$dir;
|
||||||
|
|
||||||
mkfifo ui-in ui-out
|
mkfifo ui-in ui-out
|
||||||
touch in; cp in out
|
touch in; cp in out
|
||||||
rm -f "$session_path"
|
rm -f "$session_path"
|
||||||
$DEBUGGER $root/../src/kak out -n -s "$session" -ui json -e "$kak_commands" >ui-out <ui-in &
|
(
|
||||||
|
if [ -f env ]; then
|
||||||
|
. ./env
|
||||||
|
fi
|
||||||
|
exec $DEBUGGER $root/../src/kak out -n -s "$session" -ui json -e "$kak_commands" >ui-out <ui-in
|
||||||
|
) &
|
||||||
kakpid=$!
|
kakpid=$!
|
||||||
|
|
||||||
failed=0
|
failed=0
|
||||||
|
@ -82,10 +87,7 @@ main() {
|
||||||
else
|
else
|
||||||
for file in out $env_vars; do
|
for file in out $env_vars; do
|
||||||
if [ -f $root/$dir/$file ] && ! cmp -s $root/$dir/$file $file; then
|
if [ -f $root/$dir/$file ] && ! cmp -s $root/$dir/$file $file; then
|
||||||
if [ $failed -eq 0 ]; then
|
fail_ifn
|
||||||
printf "${red}$indent%s${none}\n" "$name"
|
|
||||||
failed=1
|
|
||||||
fi
|
|
||||||
show_diff $root/$dir/$file $file
|
show_diff $root/$dir/$file $file
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
@ -127,6 +129,13 @@ main() {
|
||||||
|
|
||||||
# Utility ├─────────────────────────────────────────────────────────────────────
|
# Utility ├─────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
fail_ifn() {
|
||||||
|
if [ $failed -eq 0 ]; then
|
||||||
|
printf "${red}$indent%s${none}\n" "$name"
|
||||||
|
failed=1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
show_diff() {
|
show_diff() {
|
||||||
diff -u $1 $2 | while IFS='' read -r line; do
|
diff -u $1 $2 | while IFS='' read -r line; do
|
||||||
first_character=$(printf '%s\n' "$line" | cut -b 1)
|
first_character=$(printf '%s\n' "$line" | cut -b 1)
|
||||||
|
@ -168,20 +177,40 @@ ui_out() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-ignore)
|
-ignore)
|
||||||
shift
|
shift
|
||||||
skip_count="$1"
|
skip_count=$1
|
||||||
while [ $skip_count -gt 0 ]; do
|
while [ $skip_count -gt 0 ]; do
|
||||||
read -r event <&4
|
read -r event <&4
|
||||||
skip_count=$(( skip_count - 1 ))
|
skip_count=$(( skip_count - 1 ))
|
||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
|
-within-next)
|
||||||
|
shift
|
||||||
|
candidate_count=$1
|
||||||
|
shift
|
||||||
|
candidates=
|
||||||
|
found=false
|
||||||
|
while [ $candidate_count -gt 0 ]; do
|
||||||
|
read -r event <&4
|
||||||
|
if [ "$1" = "$event" ]; then
|
||||||
|
found=true
|
||||||
|
elif ! $found; then
|
||||||
|
candidates="$candidates${indent} $event
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
candidate_count=$(( candidate_count - 1 ))
|
||||||
|
done
|
||||||
|
if ! $found; then
|
||||||
|
fail_ifn
|
||||||
|
printf "${indent} Failed to find:\n"
|
||||||
|
printf "${indent} %s\n" "$1"
|
||||||
|
printf "${indent} Candidates:\n%s" "$candidates"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
read -r event <&4
|
read -r event <&4
|
||||||
if [ ! "$1" = "$event" ]; then
|
if [ ! "$1" = "$event" ]; then
|
||||||
if [ $failed -eq 0 ]; then
|
fail_ifn
|
||||||
printf "${red}$indent%s${none}\n" "$name"
|
|
||||||
fi
|
|
||||||
printf "${indent} ${red}- %s\n${indent} ${green}+ %s${none}\n" "$1" "$event"
|
printf "${indent} ${red}- %s\n${indent} ${green}+ %s${none}\n" "$1" "$event"
|
||||||
failed=1
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
1
test/tools/git/blame-jump-message/cmd
Normal file
1
test/tools/git/blame-jump-message/cmd
Normal file
|
@ -0,0 +1 @@
|
||||||
|
:run<ret>
|
2
test/tools/git/blame-jump-message/enabled
Executable file
2
test/tools/git/blame-jump-message/enabled
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
command -v git >/dev/null
|
1
test/tools/git/blame-jump-message/env
Symbolic link
1
test/tools/git/blame-jump-message/env
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../env
|
1
test/tools/git/blame-jump-message/in
Normal file
1
test/tools/git/blame-jump-message/in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
10
test/tools/git/blame-jump-message/rc
Normal file
10
test/tools/git/blame-jump-message/rc
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
declare-option str jumpclient
|
||||||
|
source "%val{runtime}/rc/filetype/diff.kak"
|
||||||
|
source "%val{runtime}/rc/tools/git.kak"
|
||||||
|
|
||||||
|
define-command run %[
|
||||||
|
git init
|
||||||
|
git add
|
||||||
|
git commit --message "Don't break on single quotes or unbalanced {"
|
||||||
|
git blame-jump
|
||||||
|
]
|
10
test/tools/git/blame-jump-message/script
Normal file
10
test/tools/git/blame-jump-message/script
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
ui_out -ignore 7
|
||||||
|
ui_out -ignore 4
|
||||||
|
|
||||||
|
ui_out -ignore 3
|
||||||
|
subject=$(cat <<'EOF'
|
||||||
|
2017-07-14 A U Thor "Don't break on single quotes or unbalanced {"
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
json_quoted_subject=\"$(printf '%s' "$subject" | sed 's/"/\\"/g')\"
|
||||||
|
ui_out -within-next 3 '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[{ "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": '"$json_quoted_subject"' }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "*git* 13:2 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "[scratch]" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }'
|
13
test/tools/git/env
Normal file
13
test/tools/git/env
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
for git_var in $(set | awk -F= '/^GIT_/ {print $1}')
|
||||||
|
do
|
||||||
|
unset -v "$git_var"
|
||||||
|
done
|
||||||
|
export GIT_CONFIG_NOSYSTEM=true
|
||||||
|
export GIT_CONFIG_GLOBAL=/dev/null
|
||||||
|
export GIT_AUTHOR_NAME="A U Thor"
|
||||||
|
export GIT_AUTHOR_EMAIL="author@domain.tld"
|
||||||
|
export GIT_COMMITTER_NAME="C O Mitter"
|
||||||
|
export GIT_COMMITTER_EMAIL="committer@domain.tld"
|
||||||
|
export GIT_AUTHOR_DATE="1500000000 -0500"
|
||||||
|
export GIT_COMMITTER_DATE="1500000000 -0500"
|
||||||
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main # Suppress noisy warning.
|
Loading…
Reference in New Issue
Block a user