Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[RFC PATCH v3] vcs_info: choose backend by basedir



Previously, vcs_info iterated over enabled VCS backends and output repository
status from the first backend that works (i.e. first backend that can find a
repository).

But I prefer a different behavior: I want to see the status of the repository
closest to the current working directory. For example: if there is a Mercurial
repository inside a Git repository, and I 'cd' into the Mercurial repository,
I want to see the status of Mercurial repo, even if 'git' comes before 'hg' in
the 'enable' list.

This patch changes how vcs_info chooses the backend:

1. Among backends whose basedir isn't an ancestor of the current directory,
old algorithm is used: whichever comes first in 'enable' list.

2. If all enabled backends return basedirs that are ancestors of the current
directory, the one with basedir closest to the current directory is chosen.

As far as I know, unless the user has set basedir manually (GIT_WORK_TREE),
all backend return basedirs that are ancestors of the current directory.
Backends that return non-ancestor basedirs have higher priority to show the
status of that manually-configured repository.

It's possible to revert to the old behavior of vcs_info, by setting:

    zstyle ':vcs_info:*' backend-choice enablement-order

It can also be set per-backend:

    zstyle ':vcs_info:hg:*' backend-choice enablement-order

This effectively moves the backend into group (1), as if its basedir is never
an ancestor of the current directory. Not sure how useful this is though.

Also, this patch adjusts VCS_INFO_detect_git and VCS_INFO_detect_cvs to make
them set vcs_comm[basedir], by moving basedir detection code from corresponding
VCS_INFO_get_data_* functions. VCS_INFO_detect_git and VCS_INFO_detect_cvs were
the only VCS_INFO_detect_* functions not setting it.

I've omitted the documentation from this patch. If the code (and the approcah)
here is ok, I'll work on the documentation later.

Signed-off-by: Aleksandr Mezin <mezin.alexander@xxxxxxxxx>
---
 .../VCS_Info/Backends/VCS_INFO_detect_cvs     | 17 +++++++++--
 .../VCS_Info/Backends/VCS_INFO_detect_git     |  1 +
 .../VCS_Info/Backends/VCS_INFO_get_data_cvs   | 11 +------
 .../VCS_Info/Backends/VCS_INFO_get_data_git   |  2 +-
 Functions/VCS_Info/vcs_info                   | 30 ++++++++++++++++---
 5 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs b/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs
index 7a5ee1eef..a57959ec9 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs
+++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs
@@ -7,5 +7,18 @@ setopt localoptions NO_shwordsplit
 [[ $1 == '--flavours' ]] && return 1
 
 VCS_INFO_check_com ${vcs_comm[cmd]} || return 1
-[[ -d "./CVS" ]] && [[ -r "./CVS/Repository" ]] && return 0
-return 1
+if ! [[ -d "./CVS" ]] || ! [[ -r "./CVS/Repository" ]] ; then
+    return 1
+fi
+
+# Look for the most distant parent that still has a CVS subdirectory.
+local cvsbase="."
+cvsbase=${cvsbase:P}
+while [[ -d "${cvsbase:h}/CVS" ]]; do
+    cvsbase="${cvsbase:h}"
+    if [[ $cvsbase == '/' ]]; then
+        break
+    fi
+done
+
+vcs_comm[basedir]="${cvsbase}"
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_git b/Functions/VCS_Info/Backends/VCS_INFO_detect_git
index e4191f474..b7955de38 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_detect_git
+++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_git
@@ -7,6 +7,7 @@ setopt localoptions NO_shwordsplit
 [[ $1 == '--flavours' ]] && { print -l git-p4 git-svn; return 0 }
 
 if VCS_INFO_check_com ${vcs_comm[cmd]} && vcs_comm[gitdir]="$(${vcs_comm[cmd]} rev-parse --git-dir 2> /dev/null)" ; then
+    vcs_comm[basedir]="$( ${vcs_comm[cmd]} rev-parse --show-toplevel 2> /dev/null )"
     if   [[ -d ${vcs_comm[gitdir]}/svn ]]             ; then vcs_comm[overwrite_name]='git-svn'
     elif [[ -d ${vcs_comm[gitdir]}/refs/remotes/p4 ]] ; then vcs_comm[overwrite_name]='git-p4' ; fi
     return 0
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs b/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs
index 9b828bd11..bc0d5cfe5 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs
@@ -5,17 +5,8 @@
 setopt localoptions NO_shwordsplit
 local cvsbranch cvsbase
 
-# Look for the most distant parent that still has a CVS subdirectory.
+cvsbase="${vcs_comm[basedir]}"
 # VCS_INFO_detect_cvs ensured that ./CVS/Repository exists.
-cvsbase="."
-cvsbase=${cvsbase:P}
-while [[ -d "${cvsbase:h}/CVS" ]]; do
-    cvsbase="${cvsbase:h}"
-    if [[ $cvsbase == '/' ]]; then
-        break
-    fi
-done
-
 cvsbranch=$(< ./CVS/Repository)
 rrn=${cvsbase:t}
 cvsbranch=${cvsbranch##${rrn}/}
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
index 79429c8e0..eb04d4b41 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
@@ -138,7 +138,7 @@ VCS_INFO_git_handle_patches () {
 
 gitdir=${vcs_comm[gitdir]}
 VCS_INFO_git_getbranch ${gitdir}
-gitbase=$( ${vcs_comm[cmd]} rev-parse --show-toplevel 2> /dev/null )
+gitbase=${vcs_comm[basedir]}
 if [[ -z ${gitbase} ]]; then
     # Bare repository
     gitbase=${gitdir:P}
diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info
index 786b61918..de8efc6b4 100644
--- a/Functions/VCS_Info/vcs_info
+++ b/Functions/VCS_Info/vcs_info
@@ -54,7 +54,7 @@ vcs_info () {
     [[ -r . ]] || return 0
 
     local pat
-    local -i found retval
+    local -i retval
     local -a enabled disabled dps
     local usercontext vcs rrn quiltmode
     local -x LC_MESSAGES
@@ -114,7 +114,9 @@ vcs_info () {
 
     VCS_INFO_maxexports
 
-    (( found = 0 ))
+    local -A chosen_vcs_comm chosen_backend_misc
+    local chosen_vcs basedir_realpath chosen_basedir_realpath choose_closest
+
     for vcs in ${enabled} ; do
         [[ -n ${(M)disabled:#${vcs}} ]] && continue
         if (( ${+functions[VCS_INFO_detect_${vcs}]} == 0 )) ; then
@@ -124,10 +126,30 @@ vcs_info () {
         fi
         vcs_comm=()
         VCS_INFO_get_cmd
-        VCS_INFO_detect_${vcs} && (( found = 1 )) && break
+        if VCS_INFO_detect_${vcs}; then
+            basedir_realpath="${vcs_comm[basedir]:P}"
+
+            zstyle -m ":vcs_info:${vcs}:${usercontext}:${rrn}" backend-choice enablement-order
+            choose_closest=$?
+
+            [[ "${PWD:P}/" != "${basedir_realpath}"/* ]] && choose_closest=0
+
+            if (( ! choose_closest )) || (( ${#basedir_realpath} > ${#chosen_basedir_realpath} )) ; then
+                chosen_vcs="${vcs}"
+                chosen_vcs_comm=("${(kv)vcs_comm[@]}")
+                chosen_backend_misc=("${(kv)backend_misc[@]}")
+                chosen_basedir_realpath="${basedir_realpath}"
+
+                (( ! choose_closest )) && break
+            fi
+        fi
     done
 
-    (( found == 0 )) && {
+    vcs="${chosen_vcs}"
+    vcs_comm=("${(kv)chosen_vcs_comm[@]}")
+    backend_misc=("${(kv)chosen_backend_misc[@]}")
+
+    [ -z "${vcs}" ] && {
         vcs='-quilt-'; quiltmode='standalone'
         VCS_INFO_quilt standalone || VCS_INFO_set --nvcs
         return 0
-- 
2.29.1





Messages sorted by: Reverse Date, Date, Thread, Author