summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--Doc/Zsh/contrib.yo15
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_detect_p478
3 files changed, 92 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 6f225124f..202a2fd7b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2008-09-23  Peter Stephenson  <pws@csr.com>
 
+	* 25732: Functions/VCS_Info/Backends/VCS_INFO_detect_p4,
+	Doc/Zsh/contrib.yo: make vcs_info detect Perforce from server
+	if style use-server is set.
+
 	* Rocky Bernstein: 25727: Src/hist.c, Test/B06fc.ztst: remove
 	restriction on interactive use of fc and test another problem.
 
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index a3a74134e..44b918aac 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -502,6 +502,21 @@ A list of VCSs, you don't want var(vcs_info) to test for
 repositories (checked in the var(-init-) context, too). Only used if
 tt(enable) contains tt(ALL).
 )
+kindex(use-server)
+item(tt(use-server))(
+This is used by the Perforce backend (tt(p4)) to decide if it should
+contact the Perforce server to find out if a directory is managed
+by Perforce.  This is the only reliable way of doing this, but runs
+the risk of a delay if the server name cannot be found.  If the
+server (more specifically, the var(host)tt(:)var(port) pair describing the
+server) cannot be contacted its name is put into the associative array
+tt(vcs_info_p4_dead_servers) and not contacted again during the session
+until it is removed by hand.  If you do not set this style, the tt(p4)
+backend is only usable if you have set the environment variable
+tt(P4CONFIG) to a file name and have corresponding files in the root
+directories of each Perforce client.  See comments in the function
+tt(VCS_INFO_detect_p4) for more detail.
+)
 kindex(use-simple)
 item(tt(use-simple))(
 If there are two different ways of gathering
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_p4 b/Functions/VCS_Info/Backends/VCS_INFO_detect_p4
index 3cd649a0d..d9475fa01 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_detect_p4
+++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_p4
@@ -2,8 +2,76 @@
 ## perforce support by: Phil Pennock
 ## Distributed under the same BSD-ish license as zsh itself.
 
-[[ -n ${P4CONFIG} ]] || return 1
-VCS_INFO_check_com p4 || return 1
-vcs_comm[detect_need_file]="${P4CONFIG}"
-VCS_INFO_bydir_detect .
-return $?
+# If user-server is true in the :vcs_info:p4:... context, contact the
+# server to decide whether the directory is handled by Perforce.  This can
+# cause a delay if the network times out, in particular if looking up the
+# server name failed.  Hence this is not the default.  If a timeout
+# occurred, the server:port pair is added to the associative array
+# vcs_info_p4_dead_servers and the server is never contacted again.  The
+# array must be edited by hand to remove it.
+#
+# If user-server is false or not set, the function looks to see if there is
+# a file $P4CONFIG somewhere above in the hierarchy.  This is far from
+# foolproof; in fact it relies on you using the particular working practice
+# of having such files in all client root directories and nowhere above.
+
+
+VCS_INFO_p4_get_server() {
+  emulate -L zsh
+  setopt extendedglob
+
+  local -a settings
+  settings=(${(f)"$(p4 set)"})
+  serverport=${${settings[(r)P4PORT=*]##P4PORT=}%% *}
+  case $serverport in
+    (''|:)
+    serverport=perforce:1666
+    ;;
+
+    (:*)
+    serverport=perforce${serverport}
+    ;;
+
+    (*:)
+    serverport=${serverport}1666
+    ;;
+
+    (<->)
+    serverport=perforce:${serverport}
+    ;;
+  esac
+}
+
+
+VCS_INFO_detect_p4() {
+  local serverport p4where
+
+  if zstyle -t ":vcs_info:p4:${usercontext}:${rrn}" use-server; then
+    # Use "p4 where" to decide whether the path is under the
+    # client workspace.
+    if (( ${#vcs_info_p4_dead_servers} )); then
+      # See if the server is in the list of defunct servers
+      VCS_INFO_p4_get_server
+      [[ -n $vcs_info_p4_dead_servers[$serverport] ]] && return 1
+    fi
+    if p4where="$(p4 where 2>&1)"; then
+      return 0
+    fi
+    if [[ $p4where = *"Connect to server failed"* ]]; then
+      # If the connection failed, mark the server as defunct.
+      # Otherwise it worked but we weren't within a client.
+      typeset -gA vcs_info_p4_dead_servers
+      [[ -z $serverport ]] && VCS_INFO_p4_get_server
+      vcs_info_p4_dead_servers[$serverport]=1
+    fi
+    return 1
+  else
+    [[ -n ${P4CONFIG} ]] || return 1
+    VCS_INFO_check_com p4 || return 1
+    vcs_comm[detect_need_file]="${P4CONFIG}"
+    VCS_INFO_bydir_detect .
+    return $?
+  fi
+}
+
+VCS_INFO_detect_p4 "$@"