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

Submitting vcs_info function



Hi list,

I've been working on this for quite some time now. vcs_info is a
function that is able to get information about directories under
version control. That information can be used in prompts, for example.

I am submitting this for inclusion in the next zsh release - if the
developers deem it to be worthy. I think Functions/Misc/vcs_info would
be a proper place.

I short example of how a vcs_info enabled prompt can look like can be
found here:
 <http://bewatermyfriend.org/posts/2008/09-17.13-43-05-computer.html>

I am attaching the vcs_info file to this mail. And I will post a
follow-up message, that will contain a documentation patch against
Doc/Zsh/contrib.yo.

If people want to give this a try, here is what the doc patch
contains:

[snip]
ZSHCONTRIB(1)                                                    ZSHCONTRIB(1)

NAME
       zshcontrib - user contributions to zsh
[...]

UTILITIES
[...]

   Gathering information from version control systems
       In a lot of cases, it is nice  to  automatically  retrieve  information
       from version control systems (VCSs), such as subversion, CVS or git, to
       be able to provide it to the user; possibly in the  user's  prompt.  So
       that  you can instantly tell on which branch you are currently on,  for
       example.

       In order to do that, you may use the vcs_info function.

       Supported VCSs:

              bazaar http://bazaar-vcs.org/
              codeville
                     http://codeville.org/
              cvs    http://www.nongnu.org/cvs/
              darcs  http://darcs.net/
              git    http://git.or.cz/
              gnu arch
                     http://www.gnu.org/software/gnu-arch/
              mercurial
                     http://selenic.com/mercurial/
              monotone
                     http://monotone.ca/
              subversion
                     http://subversion.tigris.org/
              svk    http://svk.bestpractical.com/


       Loading vcs_info:

              autoload -Uz vcs_info && vcs_info

       If you plan to use the information from vcs_info in your prompt  (which
       is its primary use), you need to enable the PROMPT_SUBST option.

       It  can be used in any existing prompt, because it does not require any
       $psvar entries to be left available.

       Quickstart

       To get this feature working quickly (including colors), you can do  the
       following (assuming, you loaded vcs_info properly - see above):

              RED=$'%{\e[31m%}'
              GR=$'%{\e[32m%}'
              MA=$'%{\e[35m%}'
              YE=$'%{\e[33m%}'
              NC=$'%{\e[0m%}'
              zstyle ':vcs_info:*' actionformats \
                  "${MA}(${NC}%s${MA})${YE}-${MA}[${GR}%b${YE}|${RED}%a${MA}]${NC} "
              zstyle ':vcs_info:*' formats       \
                  "${MA}(${NC}%s${MA})${Y}-${MA}[${GR}%b${MA}]${NC}%} "
              zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat "%b${RED}:${YE}%r"
              precmd () { vcs_info }
              PS1="${MA}[${GR}%n${MA}] ${YE}%3~ "'${VCS_INFO_message_0_}'"${NC}%# "

       Obviously,  the last two lines are there for demonstration: You need to
       call vcs_info from your precmd function. Once that is done you  need  a
       single quoted '${VCS_INFO_message_0_}' in your prompt.

       Now call the vcs_info_printsys utility from the command line:

              % vcs_info_printsys
              # list of supported version control backends:
              # disabled systems are prefixed by a hash sign (#)
              git
              hg
              bzr
              darcs
              svk
              mtn
              svn
              cvs
              cdv
              tla
              # flavours (cannot be used in the disable style; they
              # are disabled with their master [git-svn -> git]):
              git-p4
              git-svn

       You may not want all of these. Because there is no point in running the
       code to detect systems you do not use. Ever. So, there is a way to dis-
       able some backends altogether:

              zstyle ':vcs_info:*' disable bzr cdv darcs mtn svk tla

       If you rerun vcs_info_printsys now, you will see the backends listed in
       the disable style marked as diabled by a  hash  sign.  That  means  the
       detection of these systems is skipped completely. No wasted time there.

       Configuration

       The vcs_info feature can be configured via zstyle.

       First, the context in which we are working:
              :vcs_info:<vcs-string>:<user-context>:<repo-root-name>

       ...where <vcs-string> is one of: git, git-svn, git-p4, hg, darcs,  bzr,
       cdv, mtn, svn, cvs, svk or tla.

       ...and  <user-context>  is  a freely configurable string, assignable by
       the user as the first argument to vcs_info (see its description below).

       ...and <repo-root-name> is the name of a repository in which you want a
       style to match. So, if you want a  setting  specific  to  /usr/src/zsh,
       with  that being a cvs checkout, you can set <repo-root-name> to zsh to
       make it so.

       There is are three special values for <vcs-string>: The first is  named
       -init-,  that  is  in  effect as long as there was no decision what vcs
       backend to use. The second is -preinit-; it is used before vcs_info  is
       run,  when initializing the data exporting variables. The third special
       value is 'formats' and is used by the vcs_info_lastmsg for  looking  up
       its styles.

       The  initial value of <repo-root-name> is -all- and it is replaced with
       the actual name, as soon as it is known. Only use this part of the con-
       text for defining the formats, actionformats or branchformat styles. As
       it is guaranteed that <repo-root-name> is set up  correctly  for  these
       only. For all other styles, just use '*' instead.

       There are two pre-defined values for <user-context>:

              default
                     the one used if none is specified
              command
                     used by vcs_info_lastmsg to lookup its styles

       You  may not use print_systems_ as a user-context string, because it is
       used internally.

       You can of course use ':vcs_info:*' to match all VCSs in all  user-con-
       texts at once.

       Another   special   context   is   formats,   which   is  used  by  the
       vcs_info_lastmsg utility function (see below).

       This is a description of all styles, that are looked up:

              formats
                     A list of formats, used when actionformats  is  not  used
                     (which is most of the time).
              actionformats
                     A  list  of  formats, used if a there is a special action
                     going on in your current repository; (like an interactive
                     rebase or a merge conflict).
              branchformat
                     Some backends replace %b in the formats and actionformats
                     styles above, not only by a branch name  but  also  by  a
                     revision  number.  This  style  let's you modify how that
                     string should look like.
              nvcsformats
                     These "formats" are exported, when  we  didn't  detect  a
                     version control system for the current directory. This is
                     useful, if you want vcs_info to completely take over  the
                     generation  of  your prompt.  You would do something like
                     PS1='${VCS_INFO_message_0_}' to accomplish that.
              max-exports
                     Defines the maximum number if  VCS_INFO_message_*_  vari-
                     ables vcs_info will export.
              enable Checked  in the -init- context. If set to false, vcs_info
                     will do nothing.
              disable
                     Provide a list of systems, you don't want the vcs_info to
                     check  for  repositories  (checked in the -init- context,
                     too).
              use-simple
                     If there are two different ways of gathering information,
                     you  can  select the simpler one by setting this style to
                     true; the default is to  use  the  not-that-simple  code,
                     which is potentially a lot slower but might be more accu-
                     rate in all possible cases. This style is  only  used  by
                     the bzr backend.
              use-prompt-escapes
                     Determines  if  we  assume that the assembled string from
                     vcs_info    includes    prompt    escapes.    (Used    by
                     vcs_info_lastmsg.)


       The default values for these styles in all contexts are:

              formats
                     " (%s)-[%b|%a]-"
              actionformats
                     " (%s)-[%b]-"
              branchformat
                     "%b:%r" (for bzr, svn and svk)
              nvcsformats
                     ""
              max-exports
                     2
              enable true
              disable
                     (empty list)
              use-simple
                     false
              use-prompt-escapes
                     true


       In normal formats and actionformats, the following replacements are
              done:

              %s     The vcs in use (git, hg, svn etc.)
              %b     Information about the current branch.
              %a     An  identifier,  that  describes  the  action. Only makes
                     sense in actionformats.
              %R     base directory of the repository.
              %r     repository name. If %R is /foo/bar/repoXY, %r is  repoXY.
              %S     subdirectory    within   a   repository.   If   $PWD   is
                     /foo/bar/reposXY/beer/tasty, %S is beer/tasty.


       In branchformat these replacements are done:

              %b     the branch name
              %r     the current revision number


       Not all vcs backends have to support all replacements. For  nvcsformats
       no replacements are performed at all. It is just a string.

       Oddities

       If you want to use the %b (bold off) prompt expansion in formats, which
       expands %b itself, use %%b. That will cause the vcs_info  expansion  to
       replace %%b with %b. So zsh's prompt expansion mechanism can handle it.
       Similarly, to hand down %b from branchformat, use %%%%b. Sorry for this
       inconvenience, but it cannot be easily avoided. Luckily we do not clash
       with a lot of prompt expansions and this only  needs  to  be  done  for
       those.

       Function descriptions (public API)

              vcs_info
                     The  main  function, that runs all backends and assembles
                     all data into ${VCS_INFO_message_*_}. This is  the  func-
                     tion  you want to call from precmd if you want to include
                     up-to-date  information  in  your  prompt  (see  Variable
                     description below).
              vcs_info_printsys
                     Prints  a  list of all supported version control systems.
                     Useful to find out possible contexts (and which  of  them
                     are enabled) or values for the disable style.
              vcs_info_lastmsg
                     Outputs the last ${VCS_INFO_message_*_} value. Takes into
                     account the value  of  the  use-prompt-escapes  style  in
                     ':vcs_info:formats:command:-all-'.  It  also  only prints
                     max-exports values.

              All functions named VCS_INFO_* are for internal use only.


       Variable description

              ${VCS_INFO_message_N_} (Note the trailing underscore)

                     Where N is  an  integer,  eg:  VCS_INFO_message_0_  These
                     variables  are  the storage for the informational message
                     the last vcs_info call has assembled. These are  strongly
                     connected  to  the formats, actionformats and nvcsformats
                     styles described above. Those styles are lists. The first
                     member  of  that  list gets expanded into ${VCS_INFO_mes-
                     sage_0_}, the second into ${VCS_INFO_message_1_} and  the
                     Nth  into  ${VCS_INFO_message_N-1_}. These parameters are
                     exported into the environment. (See the max-exports style
                     above.)


       Examples

       Don't use vcs_info at all (even though it's in your prompt):
              zstyle ':vcs_info:*' enable false

       Disable the backends for bzr and svk:
              zstyle ':vcs_info:*' disable bzr svk

       Provide a special formats for git:
              zstyle ':vcs_info:git:*' formats       ' GIT, BABY! [%b]'
              zstyle ':vcs_info:git:*' actionformats ' GIT ACTION! [%b|%a]'

       Use the quicker bzr backend
              zstyle ':vcs_info:bzr:*' use-simple true

       If  you do use use-simle, please report if it does the-right-thing[tm].

       Display the revision number in yellow for bzr and svn:
              zstyle ':vcs_info:(svn|bzr):*' branchformat '%b%{'${fg[yellow]}'%}:%r'

       If you want colors, make sure you enclose the color codes  in  %{...%},
       if you want to use the string provided by vcs_info in prompts.

       Here is how to print the vcs infomation as a command (not in a prompt):
              alias vcsi='vcs_info command; vcs_info_lastmsg'

       This way,  you  can  even  define  different  formats  for  output  via
       vcs_info_lastmsg in the ':vcs_info:formats:command:*' namespace.
[snap]

Comments welcome. :)

Regards, Frank
## vim:ft=zsh:foldmethod=marker
##
## vcs_info - provide version control information
##
## Written by Frank Terbeck <ft@xxxxxxxxxxxxxxxxxxx>
## Distributed under the same BSD-ish license as zsh itself.
##

# utilities
VCS_INFO_adjust () { #{{{
    [[ -n ${vcs_comm[overwrite_name]} ]] && vcs=${vcs_comm[overwrite_name]}
    return 0
}
# }}}
VCS_INFO_check_com () { #{{{
    (( ${+commands[$1]} )) && [[ -x ${commands[$1]} ]] && return 0
    return 1
}
# }}}
VCS_INFO_formats () { # {{{
    setopt localoptions noksharrays
    local action=$1 branch=$2 base=$3
    local msg
    local -i i j

    if [[ -n ${action} ]] ; then
        zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" actionformats msgs
        (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b|%a]-'
    else
        zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" formats msgs
        (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b]-'
    fi

    (( ${#msgs} > maxexports )) && msgs[$(( maxexports + 1 )),-1]=()
    for i in {1..${#msgs}} ; do
        zformat -f msg ${msgs[$i]} a:${action} b:${branch} s:${vcs} r:${base:t} R:${base} S:"$(VCS_INFO_reposub ${base})"
        msgs[$i]=${msg}
    done
    return 0
}
# }}}
VCS_INFO_maxexports () { #{{{
    zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" "max-exports" maxexports || maxexports=2
    if [[ ${maxexports} != <-> ]] || (( maxexports < 1 )); then
        printf 'vcs_info(): expecting numeric arg >= 1 for max-exports (got %s).\n' ${maxexports}
        printf 'Defaulting to 2.\n'
        maxexports=2
    fi
}
# }}}
VCS_INFO_nvcsformats () { #{{{
    setopt localoptions noksharrays
    local c v rr

    if [[ $1 == '-preinit-' ]] ; then
        c='default'
        v='-preinit-'
        rr='-all-'
    fi
    zstyle -a ":vcs_info:${v:-$vcs}:${c:-$usercontext}:${rrn:-$rr}" nvcsformats msgs
    (( ${#msgs} > maxexports )) && msgs[${maxexports},-1]=()
}
# }}}
VCS_INFO_realpath () { #{{{
    # a portable 'readlink -f'
    # forcing a subshell, to ensure chpwd() is not removed
    # from the calling shell (if VCS_INFO_realpath() is called
    # manually).
    (
        (( ${+functions[chpwd]} )) && unfunction chpwd
        setopt chaselinks
        cd $1 2>/dev/null && pwd
    )
}
# }}}
VCS_INFO_reposub () { #{{{
    setopt localoptions extendedglob
    local base=${1%%/##}

    [[ ${PWD} == ${base}/* ]] || {
        printf '.'
        return 1
    }
    printf '%s' ${PWD#$base/}
    return 0
}
# }}}
VCS_INFO_set () { #{{{
    setopt localoptions noksharrays
    local -i i j

    if [[ $1 == '--clear' ]] ; then
        for i in {0..9} ; do
            unset VCS_INFO_message_${i}_
        done
    fi
    if [[ $1 == '--nvcs' ]] ; then
        [[ $2 == '-preinit-' ]] && (( maxexports == 0 )) && (( maxexports = 1 ))
        for i in {0..$((maxexports - 1))} ; do
            typeset -gx VCS_INFO_message_${i}_=
        done
        VCS_INFO_nvcsformats $2
    fi

    (( ${#msgs} - 1 < 0 )) && return 0
    for i in {0..$(( ${#msgs} - 1 ))} ; do
        (( j = i + 1 ))
        typeset -gx VCS_INFO_message_${i}_=${msgs[$j]}
    done

    if (( i < maxexports )) ; then
        for j in {$(( i + 1 ))..${maxexports}} ; do
            [[ -n ${(P)${:-VCS_INFO_message_${j}_}} ]] && typeset -gx VCS_INFO_message_${j}_=
        done
    fi
    return 0
}
# }}}
# information gathering
VCS_INFO_bzr_get_data () { # {{{
    setopt localoptions noksharrays extendedglob
    local bzrbase bzrbr
    local -a bzrinfo

    if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" "use-simple" ; then
        bzrbase=${vcs_comm[basedir]}
        bzrinfo[2]=${bzrbase:t}
        if [[ -f ${bzrbase}/.bzr/branch/last-revision ]] ; then
            bzrinfo[1]=$(< ${bzrbase}/.bzr/branch/last-revision)
            bzrinfo[1]=${${bzrinfo[1]}%% *}
        fi
    else
        bzrbase=${${(M)${(f)"$( bzr info )"}:# ##branch\ root:*}/*: ##/}
        bzrinfo=( ${${${(M)${(f)"$( bzr version-info )"}:#(#s)(revno|branch-nick)*}/*: /}/*\//} )
        bzrbase="$(VCS_INFO_realpath ${bzrbase})"
    fi

    rrn=${bzrbase:t}
    zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat bzrbr || bzrbr="%b:%r"
    zformat -f bzrbr "${bzrbr}" "b:${bzrinfo[2]}" "r:${bzrinfo[1]}"
    VCS_INFO_formats '' "${bzrbr}" "${bzrbase}"
    return 0
}
# }}}
VCS_INFO_cdv_get_data () { # {{{
    local cdvbase

    cdvbase=${vcs_comm[basedir]}
    rrn=${cdvbase:t}
    VCS_INFO_formats '' "${cdvbase:t}" "${cdvbase}"
    return 0
}
# }}}
VCS_INFO_cvs_get_data () { # {{{
    local cvsbranch cvsbase

    cvsbase="."
    while [[ -d "${cvsbase}/../CVS" ]]; do
        cvsbase="${cvsbase}/.."
    done
    cvsbase="$(VCS_INFO_realpath ${cvsbase})"
    cvsbranch=$(< ./CVS/Repository)
    rrn=${cvsbase:t}
    cvsbranch=${cvsbranch##${rrn}/}
    [[ -z ${cvsbranch} ]] && cvsbranch=${rrn}
    VCS_INFO_formats '' "${cvsbranch}" "${cvsbase}"
    return 0
}
# }}}
VCS_INFO_darcs_get_data () { # {{{
    local darcsbase

    darcsbase=${vcs_comm[basedir]}
    rrn=${darcsbase:t}
    VCS_INFO_formats '' "${darcsbase:t}" "${darcsbase}"
    return 0
}
# }}}
VCS_INFO_git_get_data () { # {{{
    setopt localoptions extendedglob
    local gitdir gitbase gitbranch gitaction

    gitdir=${vcs_comm[gitdir]}
    gitbranch="$(VCS_INFO_git_getbranch ${gitdir})"

    if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
        return 1
    fi

    VCS_INFO_adjust
    gitaction="$(VCS_INFO_git_getaction ${gitdir})"
    gitbase=${PWD%/${$( git rev-parse --show-prefix )%/##}}
    rrn=${gitbase:t}
    VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}"
    return 0
}
# }}}
VCS_INFO_git_getaction () { #{{{
    local gitaction='' gitdir=$1
    local tmp

    for tmp in "${gitdir}/rebase-apply" \
               "${gitdir}/rebase"       \
               "${gitdir}/../.dotest" ; do
        if [[ -d ${tmp} ]] ; then
            if   [[ -f "${tmp}/rebasing" ]] ; then
                gitaction="rebase"
            elif [[ -f "${tmp}/applying" ]] ; then
                gitaction="am"
            else
                gitaction="am/rebase"
            fi
            printf '%s' ${gitaction}
            return 0
        fi
    done

    for tmp in "${gitdir}/rebase-merge/interactive" \
               "${gitdir}/.dotest-merge/interactive" ; do
        if [[ -f "${tmp}" ]] ; then
            printf '%s' "rebase-i"
            return 0
        fi
    done

    for tmp in "${gitdir}/rebase-merge" \
               "${gitdir}/.dotest-merge" ; do
        if [[ -d "${tmp}" ]] ; then
            printf '%s' "rebase-m"
            return 0
        fi
    done

    if [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
        printf '%s' "merge"
        return 0
    fi

    if [[ -f "${gitdir}/BISECT_LOG" ]] ; then
        printf '%s' "bisect"
        return 0
    fi
    return 1
}
# }}}
VCS_INFO_git_getbranch () { #{{{
    local gitbranch gitdir=$1
    local gitsymref='git symbolic-ref HEAD'

    if    [[ -d "${gitdir}/rebase-apply" ]] \
       || [[ -d "${gitdir}/rebase" ]]       \
       || [[ -d "${gitdir}/../.dotest" ]]   \
       || [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
        gitbranch="$(${(z)gitsymref} 2> /dev/null)"
        [[ -z ${gitbranch} ]] && [[ -r ${gitdir}/rebase-apply/head-name ]] \
            && gitbranch="$(< ${gitdir}/rebase-apply/head-name)"

    elif   [[ -f "${gitdir}/rebase-merge/interactive" ]] \
        || [[ -d "${gitdir}/rebase-merge" ]] ; then
        gitbranch="$(< ${gitdir}/rebase-merge/head-name)"

    elif   [[ -f "${gitdir}/.dotest-merge/interactive" ]] \
        || [[ -d "${gitdir}/.dotest-merge" ]] ; then
        gitbranch="$(< ${gitdir}/.dotest-merge/head-name)"

    else
        gitbranch="$(${(z)gitsymref} 2> /dev/null)"

        if [[ $? -ne 0 ]] ; then
            gitbranch="$(git describe --exact-match HEAD 2>/dev/null)"

            if [[ $? -ne 0 ]] ; then
                gitbranch="${${"$(< $gitdir/HEAD)"}[1,7]}..."
            fi
        fi
    fi

    printf '%s' "${gitbranch##refs/heads/}"
    return 0
}
# }}}
VCS_INFO_hg_get_data () { # {{{
    local hgbranch hgbase

    hgbase=${vcs_comm[basedir]}
    rrn=${hgbase:t}
    hgbranch=$(< ${hgbase}/.hg/branch)
    VCS_INFO_formats '' "${hgbranch}" "${hgbase}"
    return 0
}
# }}}
VCS_INFO_mtn_get_data () { # {{{
    setopt localoptions extendedglob
    local mtnbranch mtnbase

    mtnbase=${vcs_comm[basedir]}
    rrn=${mtnbase:t}
    mtnbranch=${${(M)${(f)"$( mtn status )"}:#(#s)Current branch:*}/*: /}
    VCS_INFO_formats '' "${mtnbranch}" "${mtnbase}"
    return 0
}
# }}}
VCS_INFO_svk_get_data () { # {{{
    local svkbranch svkbase

    svkbase=${vcs_comm[basedir]}
    rrn=${svkbase:t}
    zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat svkbranch || svkbranch="%b:%r"
    zformat -f svkbranch "${svkbranch}" "b:${vcs_comm[branch]}" "r:${vcs_comm[revision]}"
    VCS_INFO_formats '' "${svkbranch}" "${svkbase}"
    return 0
}
# }}}
VCS_INFO_svn_get_data () { # {{{
    setopt localoptions noksharrays extendedglob
    local svnbase svnbranch
    local -a svninfo

    svnbase="."
    while [[ -d "${svnbase}/../.svn" ]]; do
        svnbase="${svnbase}/.."
    done
    svnbase="$(VCS_INFO_realpath ${svnbase})"
    svninfo=( ${${${(M)${(f)"$( svn info )"}:#(#s)(URL|Revision)*}/*: /}/*\//} )

    rrn=${svnbase:t}
    zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat svnbranch || svnbranch="%b:%r"
    zformat -f svnbranch "${svnbranch}" "b:${svninfo[1]}" "r:${svninfo[2]}"
    VCS_INFO_formats '' "${svnbranch}" "${svnbase}"
    return 0
}
# }}}
VCS_INFO_tla_get_data () { # {{{
    setopt localoptions extendedglob
    local tlabase tlabranch

    tlabase="$(VCS_INFO_realpath ${vcs_comm[basedir]})"
    rrn=${tlabase:t}
    # tree-id gives us something like 'foo@xxxxxxxxxxx/demo--1.0--patch-4', so:
    tlabranch=${${"$( tla tree-id )"}/*\//}
    VCS_INFO_formats '' "${tlabranch}" "${tlabase}"
    return 0
}
# }}}
# detection
VCS_INFO_detect_by_dir() { #{{{
    local dirname=$1
    local basedir="." realbasedir

    realbasedir="$(VCS_INFO_realpath ${basedir})"
    while [[ ${realbasedir} != '/' ]]; do
        if [[ -n ${vcs_comm[detect_need_file]} ]] ; then
            [[ -d ${basedir}/${dirname} ]] && \
            [[ -f ${basedir}/${dirname}/${vcs_comm[detect_need_file]} ]] && \
                break
        else
            [[ -d ${basedir}/${dirname} ]] && break
        fi

        basedir=${basedir}/..
        realbasedir="$(VCS_INFO_realpath ${basedir})"
    done

    [[ ${realbasedir} == "/" ]] && return 1
    vcs_comm[basedir]=${realbasedir}
    return 0
}
# }}}
VCS_INFO_bzr_detect() { #{{{
    VCS_INFO_check_com bzr || return 1
    vcs_comm[detect_need_file]=branch/format
    VCS_INFO_detect_by_dir '.bzr'
    return $?
}
# }}}
VCS_INFO_cdv_detect() { #{{{
    VCS_INFO_check_com cdv || return 1
    vcs_comm[detect_need_file]=format
    VCS_INFO_detect_by_dir '.cdv'
    return $?
}
# }}}
VCS_INFO_cvs_detect() { #{{{
    VCS_INFO_check_com svn || return 1
    [[ -d "./CVS" ]] && [[ -r "./CVS/Repository" ]] && return 0
    return 1
}
# }}}
VCS_INFO_darcs_detect() { #{{{
    VCS_INFO_check_com darcs || return 1
    vcs_comm[detect_need_file]=format
    VCS_INFO_detect_by_dir '_darcs'
    return $?
}
# }}}
VCS_INFO_git_detect() { #{{{
    if VCS_INFO_check_com git && git rev-parse --is-inside-work-tree &> /dev/null ; then
        vcs_comm[gitdir]="$(git rev-parse --git-dir 2> /dev/null)" || return 1
        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
    fi
    return 1
}
# }}}
VCS_INFO_hg_detect() { #{{{
    VCS_INFO_check_com hg || return 1
    vcs_comm[detect_need_file]=branch
    VCS_INFO_detect_by_dir '.hg'
    return $?
}
# }}}
VCS_INFO_mtn_detect() { #{{{
    VCS_INFO_check_com mtn || return 1
    vcs_comm[detect_need_file]=revision
    VCS_INFO_detect_by_dir '_MTN'
    return $?
}
# }}}
VCS_INFO_svk_detect() { #{{{
    setopt localoptions noksharrays extendedglob
    local -i fhash
    fhash=0

    VCS_INFO_check_com svk || return 1
    [[ -f ~/.svk/config ]] || return 1

    # This detection function is a bit different from the others.
    # We need to read svk's config file to detect a svk repository
    # in the first place. Therefore, we'll just proceed and read
    # the other information, too. This is more then any of the
    # other detections do but this takes only one file open for
    # svk at most. VCS_INFO_svk_get_data() gets simpler, too. :-)
    while IFS= read -r line ; do
        if [[ -n ${vcs_comm[basedir]} ]] ; then
            line=${line## ##}
            [[ ${line} == depotpath:* ]] && vcs_comm[branch]=${line##*/}
            [[ ${line} == revision:* ]] && vcs_comm[revision]=${line##*[[:space:]]##}
            [[ -n ${vcs_comm[branch]} ]] && [[ -n ${vcs_comm[revision]} ]] && break
            continue
        fi
        (( fhash > 0 )) && [[ ${line} == '  '[^[:space:]]*:* ]] && break
        [[ ${line} == '  hash:'* ]] && fhash=1 && continue
        (( fhash == 0 )) && continue
        [[ ${PWD}/ == ${${line## ##}%:*}/* ]] && vcs_comm[basedir]=${${line## ##}%:*}
    done < ~/.svk/config

    [[ -n ${vcs_comm[basedir]} ]]  && \
    [[ -n ${vcs_comm[branch]} ]]   && \
    [[ -n ${vcs_comm[revision]} ]] && return 0
    return 1
}
# }}}
VCS_INFO_svn_detect() { #{{{
    VCS_INFO_check_com svn || return 1
    [[ -d ".svn" ]] && return 0
    return 1
}
# }}}
VCS_INFO_tla_detect() { #{{{
    VCS_INFO_check_com tla || return 1
    vcs_comm[basedir]="$(tla tree-root 2> /dev/null)" && return 0
    return 1
}
# }}}
# public API
vcs_info_printsys () { # {{{
    vcs_info print_systems_
}
# }}}
vcs_info_lastmsg () { # {{{
    local -i i
    local -ix maxexports

    VCS_INFO_maxexports
    for i in {0..$((maxexports - 1))} ; do
        printf '$VCS_INFO_message_%d_: "' $i
        if zstyle -T ':vcs_info:formats:command:-all-' use-prompt-escapes ; then
            print -nP ${(P)${:-VCS_INFO_message_${i}_}}
        else
            print -n ${(P)${:-VCS_INFO_message_${i}_}}
        fi
        printf '"\n'
    done
}
# }}}
vcs_info () { # {{{
    setopt localoptions noksharrays extendedglob
    local -i found
    local -a VCSs disabled
    local -x usercontext vcs rrn
    local -ix maxexports
    local -ax msgs
    local -Ax vcs_comm

    vcs='-init-'; rrn='-all-'
    VCSs=(git hg bzr darcs svk mtn svn cvs cdv tla)
    case $1 in
        (print_systems_)
            zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" "disable" disabled
            print -l '# list of supported version control backends:' \
                     '# disabled systems are prefixed by a hash sign (#)'
            for vcs in ${VCSs} ; do
                [[ -n ${(M)disabled:#${vcs}} ]] && printf '#'
                printf '%s\n' ${vcs}
            done
            print -l '# flavours (cannot be used in the disable style; they' \
                     '# are disabled with their master [git-svn -> git]):'   \
                     git-{p4,svn}
            return 0
            ;;
        ('')
            [[ -z ${usercontext} ]] && usercontext=default
            ;;
        (*) [[ -z ${usercontext} ]] && usercontext=$1
            ;;
    esac

    zstyle -T ":vcs_info:${vcs}:${usercontext}:${rrn}" "enable" || {
        [[ -n ${VCS_INFO_message_0_} ]] && VCS_INFO_set --clear
        return 0
    }
    zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" "disable" disabled
    VCS_INFO_maxexports

    (( found = 0 ))
    for vcs in ${VCSs} ; do
        [[ -n ${(M)disabled:#${vcs}} ]] && continue
        vcs_comm=()
        VCS_INFO_${vcs}_detect && (( found = 1 )) && break
    done

    (( found == 0 )) && {
        VCS_INFO_set --nvcs
        return 0
    }

    VCS_INFO_${vcs}_get_data || {
        VCS_INFO_set --nvcs
        return 1
    }

    VCS_INFO_set
    return 0
}

VCS_INFO_set --nvcs '-preinit-'
# }}}


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