From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 29976 invoked from network); 4 Jun 2021 06:15:11 -0000 Received: from zero.zsh.org (2a02:898:31:0:48:4558:7a:7368) by inbox.vuxu.org with ESMTPUTF8; 4 Jun 2021 06:15:11 -0000 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=zsh.org; s=rsa-20200801; t=1622787311; b=RAKcQf1N2/rpl6oCbYPerUZ0XAqKEBo+EhsZ++7fRc8oXzXBDzc9w/XwHptbTgfqHQtej1WI5b DQPr+b1gPtsbt7renI+HDuOBbGzPur2hQEMAX71iulbUsXVBDh3y6C9CUlSZHo2YfrWAH12MWW f7xNr/7QqqUZ64I9MMvlCWm8uwo8riF4R9irq6r07Zr/z+ktoz/D5czAWhGEKfKh1KVTkZtE4m FtZkzdNIFtRWPRWcXeueDsv3otpdR7diZuB9tlhAVrYhkdPFBrGgKv2MICVdTqEmOWtBOo5YzD xOT6UaOERRieQ0TtM1ToqzLjfB8g1ul383BDm9RqZ6Xcvw==; ARC-Authentication-Results: i=1; zsh.org; iprev=pass (mail-lf1-f48.google.com) smtp.remote-ip=209.85.167.48; dkim=pass header.d=gmail.com header.s=20161025 header.a=rsa-sha256; dmarc=pass header.from=gmail.com; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=zsh.org; s=rsa-20200801; t=1622787311; bh=QPusoQCxSRbn06/HZC34WFJS4GcvEb8sId2ATVZQ+q8=; h=List-Archive:List-Owner:List-Post:List-Unsubscribe:List-Subscribe:List-Help: List-Id:Sender:Content-Transfer-Encoding:MIME-Version:Message-ID:Date: Subject:Cc:To:From:DKIM-Signature:DKIM-Signature; b=heFEOViNCcmd/epCgkedydqV7cH9HaCjlnTd9AITfF22AJ3yQtYDRyrdhg6uc+ZdNpcyYzr3Bp QgsBU/cetCFf4MuINm93t/GnY197rz7PmbP9Z8AD4f9R8yQlHpuesocy+mn50IhzuyegvtLj6A zIwPEfjM7L+mX0CzrJmXNN+CnwIgHwLBLvq2VoVhFDOV6Wj2KGnM/SSHXPyETZtHiai42vM8Us po7cAu85HsQ/AzsVqTUFkjBqGeywfPAIN1tCql1U7qMKH8DsvNzs6GHpeVNPgX4E9IqJ7sm7Fx 5LPfRtjrFCilLrLHlzROP4BYKOcwjsl3OTqdg6Hhty9p1A==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zsh.org; s=rsa-20200801; h=List-Archive:List-Owner:List-Post:List-Unsubscribe: List-Subscribe:List-Help:List-Id:Sender:Content-Transfer-Encoding: MIME-Version:Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References; bh=EAfnlMV5v1YqCjYvxCOsZpKyiiNgaFhxUhJNauWVL2Q=; b=Q8U+jmX6JhIqgMcA5+n0bzJk+Z JGPNVSUcKLBYDu3vRsRz02d56BQ0BScjEi/nIhR5A3DJYZrOJEEDgu2DtsiNJgdugB3ESChD5/KEJ BGMWVWNKiq4lNDd9rZDAoyAJ2rFZHQSmyQFtynY8F01NxoYX4kW8w52vu0ZDAW3W/yZBjn3I880Bt j67kuedyAtX1Oue+IdntXzts3Fk+GDRoXzL6XwzRTpcLWDiyg+OyZ2d9oTJGRMRmUY8jF7OKY0QIK P2HEYmbq+GjmtLsmgy6mHI004adqdioLsfTqT8QUs6IkKEe9qanHXd3HNXUr/Yh0cuLV7TPqsw7UR fjT2616g==; Received: from authenticated user by zero.zsh.org with local id 1lp36r-0004M8-LT; Fri, 04 Jun 2021 06:15:09 +0000 Authentication-Results: zsh.org; iprev=pass (mail-lf1-f48.google.com) smtp.remote-ip=209.85.167.48; dkim=pass header.d=gmail.com header.s=20161025 header.a=rsa-sha256; dmarc=pass header.from=gmail.com; arc=none Received: from mail-lf1-f48.google.com ([209.85.167.48]:45949) by zero.zsh.org with esmtps (TLS1.3:TLS_AES_128_GCM_SHA256:128) id 1lp36I-00040w-3l; Fri, 04 Jun 2021 06:14:34 +0000 Received: by mail-lf1-f48.google.com with SMTP id a1so2723543lfr.12 for ; Thu, 03 Jun 2021 23:14:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=EAfnlMV5v1YqCjYvxCOsZpKyiiNgaFhxUhJNauWVL2Q=; b=KqaR4zkTKka+4CVCVnQxqlu4qkTu0G8LPkGes0/a7Y78iVbWIh7zpGVkhc7Yd390fs yEH06RxCi5EfEEH10IZzrWwqLXHb0SnKCb2EPTyGx+qNdXCEpGeU/IgRGIrwgMMdMYQD 71q7c1O0kSMx/Fxkb1TjPu1kzIAW1tnVxnQYmapDsLwW0hMGSmfRDAji54AqL+TW0x9e gBp6SwWZo4DIvOLOVpa7AHXnBgFPanotOfRRBqYVHHsqX97o6nlLENTsn+//behs+sAI 4WkUyKFRBmfID5V17huoQKtGC7THAJL8M4u18JsGmmB4+Rr5aDvem8K02tW/hyXgkKqD NOmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=EAfnlMV5v1YqCjYvxCOsZpKyiiNgaFhxUhJNauWVL2Q=; b=cvFjFE35nWg+MQMH7X7GgEoRr7v1rWItcxWqrsXRShTEM7urblVHgvhxCGkCuWXYGr zhoixJUoPR//d56jpJO7R8Db5LuVQG2pmbyDL+/MeGakXrybPcdK+RU/JAueJ/ViXjcS y7t6UVGz6obPqUe0K6jaLav9xWrYtsJEP9XeMSpCdH/t27rOfI0bUXyOaLVqNRvnJE76 6Lx5O93TUeGiiKTHkJqVzt92H/KTR1T1rZzbJrNebaL/VbcKfGUvWb7xSLv5g/4uWfjp PBDuIP43QRODf86VyPKfFsfx3Xi3JDUJZf2NpJ7wuv44wrzHjzkdkzoFMCqNz2ZzEnwP RwLw== X-Gm-Message-State: AOAM5326NTkHzf7DdXpeeejrYrfasR2UB6d63aU8AB5KTusWxEaUu+49 Q60Pmasftk5+5lewBmd0j/YbkW9Iqde/hA== X-Google-Smtp-Source: ABdhPJzksUrxnc5+oeGqiDBZbief8b5hD54J9IjaNn3s6EIfN9daMc913bWiPEfC+LTgm/2TVqW8QA== X-Received: by 2002:a05:6512:2294:: with SMTP id f20mr1766599lfu.128.1622787272285; Thu, 03 Jun 2021 23:14:32 -0700 (PDT) Received: from trx40.home.arpa ([2a02:2698:542b:18fe:2feb:a041:c5e2:c556]) by smtp.gmail.com with ESMTPSA id r15sm514253lfr.245.2021.06.03.23.14.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Jun 2021 23:14:31 -0700 (PDT) From: Aleksandr Mezin To: zsh-workers@zsh.org Cc: Aleksandr Mezin Subject: [PATCH v5] vcs_info: choose backend by basedir Date: Fri, 4 Jun 2021 12:14:21 +0600 Message-Id: <20210604061421.172899-1-mezin.alexander@gmail.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Seq: 49013 Archived-At: X-Loop: zsh-workers@zsh.org Errors-To: zsh-workers-owner@zsh.org Precedence: list Precedence: bulk Sender: zsh-workers-request@zsh.org X-no-archive: yes List-Id: List-Help: List-Subscribe: List-Unsubscribe: List-Post: List-Owner: List-Archive: 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 adds a new algorithm for vcs_info to choose 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 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. The algorithm used by vcs_info can be configured using 'choose-closest-backend' zstyle: zstyle ':vcs_info:*' choose-closest-backend yes By default, old algorithm is used. It can also be configured per-backend: zstyle ':vcs_info:hg:*' choose-closest-backend no 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. Signed-off-by: Aleksandr Mezin --- v4: back to boolean zstyle, keep old behavior by default, documentation v5: described expected vcs_info[basedir] use in a comment, addressed Daniel's questions in comments. Completion/Zsh/Command/_zstyle | 1 + Doc/Zsh/contrib.yo | 41 ++++++++++++++++++++++ Functions/VCS_Info/vcs_info | 62 +++++++++++++++++++++++++++++++--- 3 files changed, 100 insertions(+), 4 deletions(-) diff --git a/Completion/Zsh/Command/_zstyle b/Completion/Zsh/Command/_zstyle index 9d06076e4..b7a73c5a2 100644 --- a/Completion/Zsh/Command/_zstyle +++ b/Completion/Zsh/Command/_zstyle @@ -193,6 +193,7 @@ styles=( quilt-standalone v:bool quilt-patch-dir v:_directories quiltcommand v:_command_names + choose-closest-backend v:bool chpwd z:bool progress z:progress diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index a972f08d6..67823716a 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1238,6 +1238,46 @@ of unapplied patches (for example with Mercurial Queue patches). Used by the tt(quilt), tt(hg), and tt(git) backends. ) +kindex(choose-closest-backend) +item(tt(choose-closest-backend))( +By default, tt(vcs_info) tries backends in the order given by the tt(enable) +style, and operates on the repository detected by the first backend to +successfully detect a repository. + +If this style (tt(choose-closest-backend)) is set to tt(true) for some (or all) +backends, all backends will be divided into two groups: + +1) Backends, for which this style is set to tt(true), that detect a +repository/working copy that is an ancestor of the current directory (including +the current directory itself). + +2) All other backends: backends with tt(choose-closest-backend) unset/set to +tt(false); and backends that detected a repository/working copy that's not an +ancestor of the current directory, even if tt(choose-closest-backend) is set to +tt(true) for them. + +First, tt(vcs_info) will try backends from the 2nd group in the order given by +the tt(enable) style, and operate on the repository detected by the first +backend to successfully detect a repository (the default behavior of +tt(vcs_info), only limited to backends from the 2nd group). + +If no backends from the 2nd group detected a repository (or if there are no +backends in that group), tt(vcs_info) will try backends from the 1st group. +tt(vcs_info) will then operate on the repository closest to the current working +directory. + +Usually, all VCS backends search for repositories only in ancestors of the +current directory, and choose the repository closest to the current directory. +So if tt(choose-closest-backend) is set to tt(true) globally for all backends, +tt(vcs_info) will effectively search for the repository closest to the current +directory. + +However, there is at least one backend that can detect a repository in an +arbitrary location - Git backend. tt(GIT_WORK_TREE) can be set to a path that +doesn't point to an ancestor of the current directory. In this case, even if +tt(choose-closest-backend) is set to tt(true) globally for all backends, +the repository/working copy pointed by tt(GIT_WORK_TREE) will be preferred. +) enditem() The default values for these styles in all contexts are: @@ -1272,6 +1312,7 @@ sitem(tt(quiltcommand))(quilt) sitem(tt(patch-format))(var(backend dependent)) sitem(tt(nopatch-format))(var(backend dependent)) sitem(tt(get-unapplied))(false) +sitem(tt(choose-closest-backend))(false) endsitem() In normal tt(formats) and tt(actionformats) the following replacements are diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index 786b61918..85f7ca0ab 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 @@ -64,6 +64,9 @@ vcs_info () { # vcs_comm is used internally for passing values among VCS_INFO_* functions. # It is not part of the public API. # + # VCS_INFO_detect_* functions should set vcs_comm[basedir] to the path to + # the root of the working copy. + # # hook_com, backend_misc, and user_data are public API; see zshcontrib(1) # and Misc/vcs_info-examples. local -A vcs_comm hook_com backend_misc user_data @@ -114,7 +117,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_first_available + for vcs in ${enabled} ; do [[ -n ${(M)disabled:#${vcs}} ]] && continue if (( ${+functions[VCS_INFO_detect_${vcs}]} == 0 )) ; then @@ -124,10 +129,59 @@ vcs_info () { fi vcs_comm=() VCS_INFO_get_cmd - VCS_INFO_detect_${vcs} && (( found = 1 )) && break + if VCS_INFO_detect_${vcs}; then + # Most backends already set vcs_comm[basedir] to an absolute path + # with symlinks resolved: + # + # * Backends using VCS_INFO_bydir_detect: + # bzr, cdv, darcs, fossil, hg, mtn, p4, svn + # + # * cvs - custom logic, but uses :P too + # + # * git - $(git rev-parse --show-toplevel) resolves symlinks and + # returns an absolute path + # + # * for tla (GNU Arch) I can't find any online documentation or + # packages (seems to be dead) + # + # * svk doesn't use :P modifier and returns the path as is from + # the config file (as far as I understand) + # + # So I'm not sure whether to modify the backends or just resolve + # the path here to be sure. VCS_INFO_get_data_* usually reads + # vcs_comm[basedir] too. In particular, I'm not sure if it's safe to + # resolve symlinks in vcs_comm[basedir] for svk. + # + # Because most backends already do :P substitution, I expect all + # the info needed to resolve the path to be cached in memory by the + # OS (so it shouldn't cause performance issues). + basedir_realpath="${vcs_comm[basedir]:P}" + + zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" choose-closest-backend + choose_first_available=$? + + [[ "${PWD:P}/" == "${basedir_realpath}"/* ]] || [[ "${basedir_realpath}" == "/" ]] || choose_first_available=1 + + # If choose_first_available is 0 at this point, all basedir_realpaths + # (and thus chosen_basedir_realpath) are parents (and thus prefixes) + # of PWD:P. So comparing their lengths is enough to figure out which + # one is closer to PWD. + if (( choose_first_available )) || (( ${#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_first_available )) && 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.31.1