zsh-workers
 help / color / mirror / code / Atom feed
* [PATCH] _hosts: use separate cache for known-hosts
@ 2022-07-11  0:08 ronan
  0 siblings, 0 replies; only message in thread
From: ronan @ 2022-07-11  0:08 UTC (permalink / raw)
  To: zsh-workers; +Cc: Ronan Pigott

From: Ronan Pigott <ronan@rjp.ie>

The goal of this patch is to enable using different known-hosts
sources with different commands. The current _hosts cache doesn't
allow this because it relies on a single global cache that is used as
long as the shell is alive. Consider the following:

$ setopt completealias
$ alias myssh='ssh -o UserKnownHostsFile=$HOME/myhosts'
$ zstyle ':completion:*:complete:myssh:*' known-hosts-files ~/myhosts

In the status quo, myssh picks up the usual hosts from
~/.ssh/known_hosts that are stored in _cache_hosts, but with this
change it will now correctly use the specified hosts file(s) for
completion.

The new cache for known-hosts uses an associative array with
known-host files as keys and hosts as the values. We could also
consider just not caching these values altogether, since the
known-hosts files are relatively quick to parse.
---
 Completion/Unix/Type/_hosts | 59 ++++++++++++++++++++++++++-----------
 1 file changed, 41 insertions(+), 18 deletions(-)

diff --git a/Completion/Unix/Type/_hosts b/Completion/Unix/Type/_hosts
index 4057fee10..e08337876 100644
--- a/Completion/Unix/Type/_hosts
+++ b/Completion/Unix/Type/_hosts
@@ -5,7 +5,7 @@
 local expl _hosts tmp useip
 
 if ! zstyle -a ":completion:${curcontext}:hosts" hosts _hosts; then
-  if (( $+_cache_hosts == 0 )); then
+  if (( $+_cache_hosts == 0 )) || ! zstyle -t ":completion:${curcontext}:hosts" use-cache; then
     # uniquify
     typeset -gUa _cache_hosts
     local ipstrip='[:blank:]#[^[:blank:]]#'
@@ -23,23 +23,40 @@ if ! zstyle -a ":completion:${curcontext}:hosts" hosts _hosts; then
     else
       _cache_hosts=(${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##${~ipstrip}}})
       if (( ${+commands[ypcat]} )) &&
-    	tmp=$(_call_program hosts ypcat hosts.byname 2>/dev/null); then
+      tmp=$(_call_program hosts ypcat hosts.byname 2>/dev/null); then
         _cache_hosts+=( ${=${(f)tmp}##${~ipstrip}} ) # If you use YP
       fi
     fi
+  fi
 
-    local khostfile
-    typeset -Ua khostfiles
+  local khostfile
+  typeset -Ua khostfiles
 
-    # This style specifies a list of files to look up for host names and IP
-    # addresses, if asked to. The files can contain comma separated host names
-    # and IP's, and any text on a line after the first whitespace,| or # is
-    # discarded. ssh's known_hosts files are thus supported. This style defaults
-    # to the list /etc/ssh/ssh_known_hosts, ~/.ssh/known_hosts
-    zstyle -a ":completion:${curcontext}:hosts" known-hosts-files khostfiles ||
-    khostfiles=(/etc/ssh/ssh_known_hosts ~/.ssh/known_hosts)
+  # This style specifies a list of files to look up for host names and IP
+  # addresses, if asked to. The files can contain comma separated host names
+  # and IP's, and any text on a line after the first whitespace,| or # is
+  # discarded. ssh's known_hosts files are thus supported. This style defaults
+  # to the list /etc/ssh/ssh_known_hosts, ~/.ssh/known_hosts
+  zstyle -a ":completion:${curcontext}:hosts" known-hosts-files khostfiles ||
+  khostfiles=(/etc/ssh/ssh_known_hosts ~/.ssh/known_hosts)
 
+  _hosts_default_cache_policy() {
     for khostfile in $khostfiles; do
+      [[ $1 -ot $khostfile ]] && return 0
+    done
+    return 1
+  }
+
+  zstyle -s ":completion:$curcontext:hosts" cache-policy user_policy
+  if [[ -z "$user_policy" ]]; then
+    zstyle ":completion:$curcontext:" cache-policy _hosts_default_cache_policy
+  fi
+
+  typeset -A khostcache
+  _cache_invalid khostcache || _retrieve_cache khostcache
+
+  for khostfile in $khostfiles; do
+    if ! (( $+khostcache[$khostfile] )); then
       if [[ -r $khostfile ]]; then
         khosts=(${(s/,/j/,/u)${(f)"$(<$khostfile)"}%%[ |#]*})
 
@@ -62,16 +79,22 @@ if ! zstyle -a ":completion:${curcontext}:hosts" hosts _hosts; then
             fi
           done
         } "$khosts[@]"
-
-        if [[ -z $useip ]]; then
-          khosts=(${${khosts:#(#s)[0-9]##.[0-9]##.[0-9]##.[0-9]##(#e)}:#(#s)[0-9a-f:]##(#e)})
+        if [[ -n "$khosts" ]]; then
+          khostcache[$khostfile]=${(j. .)khosts}
         fi
-        _cache_hosts+=($khosts)
       fi
-    done
-  fi
+    fi
+  done
+  _store_cache khostcache khostcache
 
-  _hosts=( "$_cache_hosts[@]" )
+  local -a khosts=()
+  for khostfile in $khostfiles; do
+    khosts+=($=khostcache[$khostfile])
+  done
+  if [[ -z $useip ]]; then
+    khosts=(${${khosts:#(#s)[0-9]##.[0-9]##.[0-9]##.[0-9]##(#e)}:#(#s)[0-9a-f:]##(#e)})
+  fi
+  _hosts=( "$_cache_hosts[@]" "$khosts[@]" )
 fi
 
 _wanted hosts expl host \
-- 
2.37.0



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-07-11  0:14 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-11  0:08 [PATCH] _hosts: use separate cache for known-hosts ronan

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).