1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
| | # This function is designed to do a poor person's automount in
# the user space, typically of a sshfs file system as this is
# entirely controlled by the user.
#
# The return status is 0 if the path exists; 1 if it does not exist
# (even if a mount was made in an attempt to provide it); 2 if some
# condition other than a missing directory was found, in particular
# bad zstyle configuration or an sshfs failure.
#
# The style mount-path in context :chpwd: is set to an array of pairs of
# paths and URL-style references looking like
#
# /local/dir method:path-to-dir
#
# If the argument to the function is a path that doesn't exist, the
# system checks to see if the path is under /local/dir. If, so the
# other element of the pair is examined. If "method" is a known method
# for mounting the remote path path-to-dir the path, it is mounted and
# the function returns success.
#
# Currently the only method knonwn is sshfs, in which case path-to-dir
# is a standard ssh path e.g. "rhost:/home/mydir". Mounting is done
# simply: "sshfs -o workaround=rename path-to_dir /local/dir". This
# may become more configurable in future. It is assumed the user
# has an appropriate ssh agent running, else the call may prompt for
# login info at an unexpected place.
#
# Does not currently handle (the unusual case of) recursive mounts,
# i.e. /local/dir and /local/dir/under/that does not handle the second case.
emulate -L zsh
setopt extendedglob cbases
local -a mpath
# If no directories we could mount, fail silently;
# no point even looking at the argument.
zstyle -a ':chpwd:' mount-path mpath || return 1
# Nothing to if path exists.
#
# We'll allow the path to be something other than a directory as we
# are in any case going to check prefixes.
if [[ -d $1 ]]; then
# As this may be the mount point itself, we'll assume it
# should be non-empty, though we don't know for sure.
local -a files
# Glob dots; expand to empty if no matches; don't bother globbing
# more than one file, we just want to know if there are any
files=($1/*(DNY1))
(( ${#files} )) && return 0
elif [[ -e $1 ]]; then
# Not a directory, so assume everything is OK.
return 0
fi
local -a match mbegin mend
local dir
if [[ $1 = /* ]]; then
dir="$1"
else
# Hmm... We can't use (:a) or (:A) as the path doesn't yet exist in
# the file system. We'll just bang it on the end of $PWD..
# It's not clear whether we should remove symbolic links from
# $PWD as we don't know whether the user has or has not rationalised
# the zstyle accordingly.
dir="$PWD/$1"
# Rationalise ..'s --- a bit naive, but hopefully good enough...
while [[ $dir = (#b)(*/)([^/]##)/..(/*|) ]]; do
dir="$match[1]${match[3]##/}"
done
dir=${dir%%/#}
fi
local locdir remote mpoint cmdargs
for locdir remote in $mpath; do
# To be clever here we would look for the shortest matching path
# and work our way down.
if [[ $dir = ${locdir%%:*}(|/*) ]]; then
mpoint=${locdir#*:}
case $remote in
((#b)sshfs:(*))
zstyle -a ':chpwd:sshfs:' command-args cmdargs ||
cmdargs=(sshfs -o workaround=rename)
if ! "${cmdargs[@]}" "${match[1]}" "$mpoint"; then
# Bad mount: it probably complained, but let's be clear.
print -r -- "$0: attempt to mount $remote for $locdir failed." >&2
return 2
fi
# Break for success / failure depending on whether path is now provided.
# To be clever (see above) could loop further.
break
;;
(*)
# Incorrect configuration, so return noisily.
print -r -- "$0: method ${remote%%:*} not handled" >&2
return 2
;;
esac
fi
done
# Final test in case we found something that might be a mount point.
# If we couldn't mount it but this is the directory being referred to,
# assume it's OK.
[[ -e $dir ]]
|