## vim:ft=zsh:foldmethod=marker ## ## vcs_info - provide version control information ## ## Written by Frank Terbeck ## ## This file and all corresponding files in Functions/VCS_Info/ are ## distributed under the same BSD-ish license as zsh itself. ## setopt localoptions noksharrays extendedglob NO_shwordsplit local file func sys local -a static_functions msgs local -i maxexports static_functions=( VCS_INFO_adjust VCS_INFO_bydir_detect VCS_INFO_check_com VCS_INFO_formats VCS_INFO_get_cmd VCS_INFO_hexdump VCS_INFO_hook VCS_INFO_set-patch-format VCS_INFO_set-branch-format VCS_INFO_maxexports VCS_INFO_nvcsformats VCS_INFO_patch2subject VCS_INFO_quilt VCS_INFO_reposub VCS_INFO_set vcs_info_hookadd vcs_info_hookdel vcs_info_lastmsg vcs_info_printsys vcs_info_setsys ) for func in ${static_functions} ; do autoload -Uz ${func} done [[ -n ${(Mk)parameters:#vcs_info_msg_<->_} ]] && unset ${parameters[(I)vcs_info_msg_<->_]} VCS_INFO_maxexports VCS_INFO_set --nvcs '-preinit-' vcs_info_setsys # and now, finally create the real vcs_info function vcs_info () { emulate -L zsh setopt extendedglob NO_warn_create_global [[ -r . ]] || return 0 local pat local -i retval local -a enabled disabled dps local usercontext vcs rrn quiltmode local -x LC_MESSAGES local -i maxexports local -a msgs # 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 LC_MESSAGES=C if [[ -n ${LC_ALL} ]]; then local -x LANG LANG=${LC_ALL} local -x LC_ALL fi vcs='-init-'; rrn='-all-'; quiltmode='addon' usercontext=${1:-default} VCS_INFO_hook "start-up" retval=$? if (( retval == 1 )); then return 0 elif (( retval == 2 )); then # This needs `max-exports' set. We're still setting it again later # for more specific contexts. VCS_INFO_maxexports VCS_INFO_set --nvcs return 0 fi zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" "enable" enabled (( ${#enabled} == 0 )) && enabled=( all ) if [[ -n ${(M)enabled:#(#i)none} ]] ; then [[ -n ${vcs_info_msg_0_} ]] && VCS_INFO_set --nvcs return 0 fi if [[ -n ${(M)enabled:#(#i)all} ]] ; then enabled=( ${VCS_INFO_backends} ) zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" "disable" disabled fi zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" "disable-patterns" dps for pat in ${dps} ; do if [[ ${PWD} == ${~pat} ]] ; then VCS_INFO_maxexports [[ -n ${vcs_info_msg_0_} ]] && VCS_INFO_set --nvcs return 0 fi done VCS_INFO_maxexports 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 printf 'vcs_info: configured unknown backend: '\''%s'\''\n' ${vcs} printf 'vcs_info: use '\''vcs_info_printsys'\'' to find supported systems.\n' continue fi vcs_comm=() VCS_INFO_get_cmd 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 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 } VCS_INFO_hook "pre-get-data" retval=$? if (( retval == 1 )); then return 0 elif (( retval == 2 )); then VCS_INFO_set --nvcs return 0 fi VCS_INFO_get_data_${vcs} || { VCS_INFO_set --nvcs return 1 } VCS_INFO_set return 0 } vcs_info "$@"