Skip to content

Commit 1d72577

Browse files
committed
fix(rsync): overescape remote paths if rsync version is < 3.2.4
1 parent e0fc2f3 commit 1d72577

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

completions/rsync

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
# bash completion for rsync -*- shell-script -*-
22

3+
_comp_cmd_rsync__vercomp()
4+
{
5+
if [[ "$1" == "$2" ]]; then
6+
return 0
7+
fi
8+
local IFS=.
9+
local i ver1=($1) ver2=($2)
10+
# fill empty fields in ver1 with zeros
11+
for ((i = ${#ver1[@]}; i < ${#ver2[@]}; i++)); do
12+
ver1[i]=0
13+
done
14+
for ((i = 0; i < ${#ver1[@]}; i++)); do
15+
if [[ ! ${ver1[i]} ]]; then
16+
# replace empty strings ver1 with zeros
17+
ver1[i]=0
18+
fi
19+
if [[ ! ${ver2[i]} ]]; then
20+
# fill empty fields in ver2 with zeros
21+
ver2[i]=0
22+
fi
23+
if ((10#${ver1[i]} > 10#${ver2[i]})); then
24+
return 1
25+
fi
26+
if ((10#${ver1[i]} < 10#${ver2[i]})); then
27+
return 2
28+
fi
29+
done
30+
return 0
31+
}
32+
333
_rsync()
434
{
535
local cur prev words cword split comp_args
@@ -59,7 +89,15 @@ _rsync()
5989
break
6090
fi
6191
done
62-
[[ $shell == ssh ]] && _comp_xfunc ssh scp_remote_files
92+
if [[ $shell == ssh ]]; then
93+
local rsync_version=$(rsync --version | sed -n 's/rsync version \([0-9\.]*\).*/\1/; 1p')
94+
_comp_cmd_rsync__vercomp "$rsync_version" "3.2.4"
95+
if [[ $? == "2" ]]; then
96+
_comp_xfunc ssh scp_remote_files
97+
else
98+
_comp_xfunc ssh scp_remote_files no-overescape
99+
fi
100+
fi
63101
;;
64102
*)
65103
_known_hosts_real -c -a -- "$cur"

completions/ssh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,11 @@ _comp_cmd_scp__path_esc='[][(){}<>"'"'"',:;^&!$=?`\\|[:space:]]'
434434
# Complete remote files with ssh. If the first arg is -d, complete on dirs
435435
# only. Returns paths escaped with three backslashes.
436436
# shellcheck disable=SC2120
437+
# @param $1 `no-overescape` if we should use 1 backslash for escaping instead of 3
437438
_comp_xfunc_ssh_scp_remote_files()
438439
{
440+
local no_overescape=$1
441+
439442
# remove backslash escape from the first colon
440443
cur=${cur/\\:/:}
441444

@@ -451,20 +454,25 @@ _comp_xfunc_ssh_scp_remote_files()
451454
path=$(ssh -o 'Batchmode yes' "$userhost" pwd 2>/dev/null)
452455
fi
453456

457+
local escape_replacement='\\\\\\&'
458+
if [[ "$no_overescape" == "no-overescape" ]]; then
459+
escape_replacement='\\&'
460+
fi
461+
454462
local files
455463
if [[ ${1-} == -d ]]; then
456464
# escape problematic characters; remove non-dirs
457465
# shellcheck disable=SC2090
458466
files=$(ssh -o 'Batchmode yes' "$userhost" \
459467
command ls -aF1dL "$path*" 2>/dev/null |
460-
command sed -e 's/'"$_comp_cmd_scp__path_esc"'/\\&/g' -e '/[^\/]$/d')
468+
command sed -e 's/'"$_comp_cmd_scp__path_esc"'/'"$escape_replacement"'/g' -e '/[^\/]$/d')
461469
else
462470
# escape problematic characters; remove executables, aliases, pipes
463471
# and sockets; add space at end of file names
464472
# shellcheck disable=SC2090
465473
files=$(ssh -o 'Batchmode yes' "$userhost" \
466474
command ls -aF1dL "$path*" 2>/dev/null |
467-
command sed -e 's/'"$_comp_cmd_scp__path_esc"'/\\&/g' -e 's/[*@|=]$//g' \
475+
command sed -e 's/'"$_comp_cmd_scp__path_esc"'/'"$escape_replacement"'/g' -e 's/[*@|=]$//g' \
468476
-e 's/[^\/]$/& /g')
469477
fi
470478
_comp_split -la COMPREPLY "$files"

0 commit comments

Comments
 (0)