From 94777f64e8963b5418ce86c8e8bb51ad7094587e Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 16 Feb 2010 10:09:15 +0000 Subject: Frank Terbeck, Seth House: 27712, 22713, 27714: VCS Info hooks and Mercurial improvements --- Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr | 9 +- Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 65 ++++++------ Functions/VCS_Info/Backends/VCS_INFO_get_data_hg | 117 ++++++++++++++++------ Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 | 15 ++- Functions/VCS_Info/Backends/VCS_INFO_get_data_svk | 9 +- Functions/VCS_Info/Backends/VCS_INFO_get_data_svn | 9 +- Functions/VCS_Info/VCS_INFO_formats | 83 ++++++++++----- Functions/VCS_Info/vcs_info | 1 + 8 files changed, 210 insertions(+), 98 deletions(-) (limited to 'Functions') diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr b/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr index e85de311e..5d4deaac9 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr @@ -5,6 +5,7 @@ setopt localoptions noksharrays extendedglob NO_shwordsplit local bzrbase bzrbr local -a bzrinfo +local -xA hook_com if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" "use-simple" ; then bzrbase=${vcs_comm[basedir]} @@ -21,6 +22,12 @@ 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]}" +hook_com=( branch "${bzrinfo[2]}" revision "${bzrinfo[1]}" ) +if VCS_INFO_hook 'set-branch-format' "${bzrbr}"; then + zformat -f bzrbr "${bzrbr}" "b:${hook_com[branch]}" "r:${hook_com[revision]}" +else + bzrbr=${hook_com[branch-replace]} +fi +hook_com=() VCS_INFO_formats '' "${bzrbr}" "${bzrbase}" '' '' "${bzrinfo[1]}" '' return 0 diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index bf7c47927..4018b5d92 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -4,6 +4,8 @@ setopt localoptions extendedglob NO_shwordsplit local gitdir gitbase gitbranch gitaction gitunstaged gitstaged gitsha1 gitmisc +local stgitpatch stgitunapplied +local -xA hook_com VCS_INFO_git_getaction () { local gitaction='' gitdir=$1 @@ -97,36 +99,6 @@ VCS_INFO_git_getbranch () { return 0 } -VCS_INFO_git_get_stgit_top_patch () { - local patchdir=$1 - - if [[ -d "$patchdir" ]]; then - local -a patches - patches=(${(f)"$(< "${patchdir}/applied")"}) - printf '%s' $patches[-1] - return 0 - fi - - return 1 -} - -VCS_INFO_git_get_stgit_unapplied() { - local patchdir=$1 - - if [[ -d "$patchdir" ]]; then - local -a patches - patches=(${(f)"$(< "${patchdir}/unapplied")"}) - if [[ -z $patches[@] ]]; then - printf 0 - else - printf '%d' $#patches - fi - return 0 - fi - - return 1 -} - gitdir=${vcs_comm[gitdir]} gitbranch="$(VCS_INFO_git_getbranch ${gitdir})" if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision && \ @@ -160,14 +132,37 @@ rrn=${gitbase:t} local patchdir=${gitdir}/patches/${gitbranch} if [[ -d $patchdir ]] ; then - stgitpatch=$(VCS_INFO_git_get_stgit_top_patch "${patchdir}") - stgitunapplied=$(VCS_INFO_git_get_stgit_unapplied "${patchdir}") + local -a stgit_applied stgit_unapplied - stgitpatch=${stgitpatch:-"no patch applied"} + stgit_applied=(${(f)"$(< "${patchdir}/applied")"}) + stgit_applied=( ${(Oa)stgit_applied} ) + stgit_unapplied=(${(f)"$(< "${patchdir}/unapplied")"}) + stgit_unapplied=( ${(oa)stgit_applied} ) + + if VCS_INFO_hook 'gen-stgit-patch-string' "${stgit_applied[@]}"; then + if (( ${#stgit_applied} )); then + stgitpatch=${stgit_applied[1]} + else + stgitpatch="no patch applied" + fi + else + stgitpatch=${hook_com[stgit-patch-string]} + fi + if VCS_INFO_hook 'gen-stgit-unapplied-string' "${stgit_unapplied[@]}"; then + stgitunapplied=${#stgit_unapplied} + else + stgitunapplied=${hook_com[stgit-unapplied-string]} + fi zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" stgitformat stgitmsg || stgitmsg=" %p (%c)" - zformat -f stgitmsg "${stgitmsg}" "p:${stgitpatch}" "c:${stgitunapplied}" - gitmisc=${stgitmsg} + hook_com=( patch "${stgitpatch}" unapplied "${stgitunapplied}" ) + if VCS_INFO_hook 'set-stgit-format' "${stgitformat}"; then + zformat -f stgitmsg "${stgitmsg}" "p:${hook_com[patch]}" "c:${hook_com[unapplied]}" + gitmisc=${stgitmsg} + else + gitmisc=${hook_com[stgit-replace]} + fi + hook_com=() else gitmisc='' fi diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg index 0b66463fa..1c103a541 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg @@ -3,21 +3,11 @@ ## Distributed under the same BSD-ish license as zsh itself. setopt localoptions NO_shwordsplit -local file hgbranch hgbranch_name hgbase hghash hglrev hgmisc r_branch r_info revformat - -VCS_INFO_hg_get_mq_top_patch () { - local patchdir=$1 - - if [[ -e "${patchdir}/status" ]]; then - local -a patches - patches=(${(f)"$(< "${patchdir}/status")"}) - printf "%s" "${patches[-1]/[^:]*:/}" - return 0 - fi - - return 1 -} - +local file hgbranch hgbranch_name hgbase hghash hglrev hgmqstring \ + r_branch hgchanges revformat bookmarks r_bmhash r_bmname hgbmstring +local -i getbookmarks +local -a hgbm mqpatches hgmisc_args +local -xA hook_com hgbase=${vcs_comm[basedir]} rrn=${hgbase:t} @@ -31,27 +21,70 @@ fi hghash='' hglrev='' +hgbm=() +bookmarks="${hgbase}/.hg/bookmarks" if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then # Calling the 'hg' program is quite a bit too slow for prompts. # If there's a way around that, I'd be interested. # Disabled by default anyway, so no harm done. + local HGRCPATH - HGRCPATH="/dev/null" ${vcs_comm[cmd]} branches \ - | while read -r r_branch r_info ; do - if [[ ${r_branch} == ${hgbranch_name} ]] ; then - match=() - : ${r_info/(#b)([^:]##):(*)} - hglrev=${match[1]} - hghash=${match[2]} - break + if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" \ + "check-for-changes" ; then + + HGRCPATH="/dev/null" ${vcs_comm[cmd]} id --debug -i -n -b \ + | read -r hghash hglrev r_branch + + # Are there uncommitted-changes? + if [[ $hglrev[-1] == + ]] ; then + hgchanges=1 fi - done + + # Remove uncommitted-changes marker, if any + hglrev=${hglrev/+/} + hghash=${hghash/+/} + else + HGRCPATH="/dev/null" ${vcs_comm[cmd]} \ + parents --template="{node} {rev} {branches}\n" \ + | read -r hghash hglrev r_branch + fi + + if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" "get-bookmarks" \ + && getbookmarks=1 || getbookmarks=0 + + if (( getbookmarks )) && [[ -r "${bookmarks}" ]] ; then + while read -r r_bmhash r_bmname ; do + if [[ $hghash == $r_bmhash ]] ; then + hgbm=( "$r_bmname" ${hgbm} ) + fi + done < ${bookmarks} + fi if [[ -n ${hglrev} ]] ; then zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" hgrevformat revformat || revformat="%r:%h" - zformat -f hglrev "${revformat}" "r:${hglrev}" "h:${hghash}" + hook_com=( localrev "${hglrev}" "hash" "${hghash}" ) + if VCS_INFO_hook 'set-hgrev-format' "${revformat}"; then + zformat -f hglrev "${revformat}" "r:${hook_com[localrev]}" "h:${hook_com[hash]}" + else + hglrev=${hook_com[rev-replace]} + fi + hook_com=() + if (( getbookmarks )) ; then + if VCS_INFO_hook 'gen-hg-bookmark-string' "${hgbm[@]}"; then + hgbmstring=${(j.;.)hgbm} + else + hgbmstring=${hook_com[hg-bookmark-string]} + fi + hook_com=() + fi zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat hgbranch || hgbranch="%b:%r" - zformat -f hgbranch "${hgbranch}" "b:${hgbranch_name}" "r:${hglrev}" + hook_com=( branch "${hgbranch_name}" revision "${hglrev}" ) + if VCS_INFO_hook 'set-branch-format' "${hgbranch}"; then + zformat -f hgbranch "${hgbranch}" "b:${hook_com[branch]}" "r:${hook_com[revision]}" + else + hgbranch=${hook_com[branch-replace]} + fi + hook_com=() fi else hgbranch="${hgbranch_name}" @@ -60,12 +93,36 @@ fi local patchdir=${hgbase}/.hg/patches/ if [[ -d $patchdir ]] ; then - hgmisc=$(VCS_INFO_hg_get_mq_top_patch "${patchdir}") + local -a mqpatches + if [[ -e "${patchdir}/status" ]]; then + mqpatches=( ${${(f)"$(< "${patchdir}/status")"}/(#s)[a-f0-9]##:/} ) + mqpatches=( ${(Oa)mqpatches} ) + else + mqpatches=( ) + fi - hgmisc=${hgmisc:-"no patch applied"} + if VCS_INFO_hook 'gen-mq-patch-string' "${mqpatches[@]}"; then + if (( ${#mqpatches} )); then + hgmqstring=${mqpatches[1]} + else + hgmqstring="no patch applied" + fi + else + hgbmstring=${hook_com[hg-mqpatch-string]} + fi + hook_com=() else - hgmisc='' + hgmqstring='' fi -VCS_INFO_formats '' "${hgbranch}" "${hgbase}" '' '' "${hglrev}" "${hgmisc}" +if [[ -z "${hgmqstring}" ]] && [[ -z "${hgbmstring}" ]]; then + hgmisc_args=( '' ) # make sure there's at least *one* misc argument +elif [[ -z "${hgmqstring}" ]]; then + hgmisc_args=( "${hgmqstring}" ) +elif [[ -z "${hgbmstring}" ]]; then + hgmisc_args=( "${hgbmstring}" ) +else + hgmisc_args=( "${hgmqstring}" "${hgbmstring}" ) +fi +VCS_INFO_formats '' "${hgbranch}" "${hgbase}" '' "${hgchanges}" "${hglrev}" "${hgmisc_args[@]}" return 0 diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 b/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 index e4bbb06c4..430cfa6f0 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 @@ -6,6 +6,7 @@ setopt localoptions extendedglob local p4base a b local -A p4info +local -xA hook_com ${vcs_comm[cmd]} info | while IFS=: read a b; do p4info[${a// /_}]="${b## #}"; done p4base=${vcs_comm[basedir]} @@ -16,9 +17,13 @@ local p4branch change # here down is synced as the revision. # I suppose the following might be slow on a tortuous client view. change="${${$(${vcs_comm[cmd]} changes -m 1 ...\#have)##Change }%% *}" -zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat p4branch || -p4branch="%b:%r" -zformat -f p4branch "${p4branch}" "b:${p4info[Client_name]}" \ -"r:$change" - +zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat p4branch || p4branch="%b:%r" +hook_com=( branch "${p4info[Client_name]}" revision "${change}" ) +if VCS_INFO_hook 'set-branch-format' "${p4branch}"; then + zformat -f p4branch "${p4branch}" "b:${hook_com[branch]}" "r:${hook_com[revision]}" +else + p4branch=${hook_com[branch-replace]} +fi +hook_com=() VCS_INFO_formats '' "${p4branch}" "${p4base}" '' '' "$change" '' +return 0 diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk index 3df9a7366..6107a14f3 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk @@ -4,10 +4,17 @@ setopt localoptions NO_shwordsplit local svkbranch svkbase +local -xA hook_com 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]}" +hook_com=( branch "${vcs_comm[branch]}" revision "${vcs_comm[revision]}" ) +if VCS_INFO_hook 'set-branch-format' "${svkbranch}"; then + zformat -f svkbranch "${svkbranch}" "b:${hook_com[branch]}" "r:${hook_com[revision]}" +else + svkbranch=${hook_com[branch-replace]} +fi +hook_com=() VCS_INFO_formats '' "${svkbranch}" "${svkbase}" '' '' "${vcs_comm[revision]}" '' return 0 diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn index 75da22bda..b1cb7302b 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn @@ -7,6 +7,7 @@ setopt localoptions noksharrays extendedglob NO_shwordsplit local svnbase svnbranch a b rrn local -A svninfo parentinfo +local -xA hook_com svnbase="."; svninfo=() @@ -23,6 +24,12 @@ svnbase="$(VCS_INFO_realpath ${svnbase})" rrn=${svnbase:t} zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat svnbranch || svnbranch="%b:%r" -zformat -f svnbranch "${svnbranch}" "b:${svninfo[URL]##*/}" "r:${svninfo[Revision]}" +hook_com=( branch "${svninfo[URL]##*/}" revision "${svninfo[Revision]}" ) +if VCS_INFO_hook 'set-branch-format' "${svnbranch}"; then + zformat -f svnbranch "${svnbranch}" "b:${hook_com[branch]}" "r:${hook_com[revision]}" +else + svnbranch=${hook_com[branch-replace]} +fi +hook_com=() VCS_INFO_formats '' "${svnbranch}" "${svnbase}" '' '' "${svninfo[Revision]}" '' return 0 diff --git a/Functions/VCS_Info/VCS_INFO_formats b/Functions/VCS_Info/VCS_INFO_formats index 35b3b963d..db7a8dd48 100644 --- a/Functions/VCS_Info/VCS_INFO_formats +++ b/Functions/VCS_Info/VCS_INFO_formats @@ -3,7 +3,39 @@ ## Distributed under the same BSD-ish license as zsh itself. setopt localoptions noksharrays NO_shwordsplit -local action=$1 branch=$2 base=$3 staged=$4 unstaged=$5 rev=$6 misc=$7 +local msg tmp +local -i i +local -xA hook_com +# The _origs are needed because hooks can change values and there would +# be no way to get the originals back for later hooks (a hook is run for +# each message, that's being created). +hook_com=( + action "$1" + action_orig "$1" + branch "$2" + branch_orig "$2" + base "$3" + base_orig "$3" + staged "$4" + staged_orig "$4" + unstaged "$5" + unstaged_orig "$5" + revision "$6" + revision_orig "$6" + vcs "${vcs}" + vcs_orig "${vcs}" +) +shift 6 +i=0 +for tmp in "$@"; do + hook_com[misc$((i++))]="${tmp}" +done +hook_com[misc]=${(j:,:)argv} +hook_com[misc_orig]=${hook_com[misc]} +hook_com[base-name]="${${hook_com[base]}:t}" +hook_com[base-name_orig]="${hook_com[base_name]}" +hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})" +hook_com[subdir_orig]="${hook_com[subdir]}" ## description: # action: a string that signals a certain non-default condition in the @@ -13,18 +45,15 @@ local action=$1 branch=$2 base=$3 staged=$4 unstaged=$5 rev=$6 misc=$7 # base: the full name of the repository's root directory. # staged: non-empty if the repository contains staged changes. # unstaged: non-empty if the repository contains unstaged changes. -# rev: an identifier of the currently checked out revision. -# misc: a string that may contain anything the author likes. +# revision: an identifier of the currently checked out revision. +# misc0..N: a set of strings that may contain anything the author likes. # the backends should document what they put in it and when. # # If an argument has no valid value for a given backend, an empty value # should be provided. eg: # VCS_INFO_formats '' "${foobranch}" "${foobase}" '' '' '' "${foomisc}" -local msg -local -i i j - -if [[ -n ${action} ]] ; then +if [[ -n ${hook_com[action]} ]] ; then zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" actionformats msgs (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b|%a]-' else @@ -32,29 +61,33 @@ else (( ${#msgs} < 1 )) && msgs[1]=' (%s)-[%b]-' fi -if [[ -n ${staged} ]] ; then - zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" stagedstr staged - [[ -z ${staged} ]] && staged='S' +if [[ -n ${hook_com[staged]} ]] ; then + zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" stagedstr tmp + [[ -z ${tmp} ]] && hook_com[staged]='S' || hook_com[staged]=${tmp} fi -if [[ -n ${unstaged} ]] ; then - zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" unstagedstr unstaged - [[ -z ${unstaged} ]] && unstaged='U' +if [[ -n ${hook_com[unstaged]} ]] ; then + zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" unstagedstr tmp + [[ -z ${tmp} ]] && hook_com[unstaged]='U' || hook_com[unstaged]=${tmp} fi (( ${#msgs} > maxexports )) && msgs[$(( maxexports + 1 )),-1]=() for i in {1..${#msgs}} ; do - zformat -f msg ${msgs[$i]} \ - a:${action} \ - b:${branch} \ - c:${staged} \ - i:${rev} \ - m:${misc} \ - r:${base:t} \ - s:${vcs} \ - u:${unstaged} \ - R:${base} \ - S:"$(VCS_INFO_reposub ${base})" - msgs[$i]=${msg} + if VCS_INFO_hook "set-message" $(( $i - 1 )) "${msgs[$i]}"; then + zformat -f msg ${msgs[$i]} \ + a:${hook_com[action]} \ + b:${hook_com[branch]} \ + c:${hook_com[staged]} \ + i:${hook_com[revision]} \ + m:${hook_com[misc]} \ + r:${hook_com[base-name]} \ + s:${hook_com[vcs]} \ + u:${hook_com[unstaged]} \ + R:${hook_com[base]} \ + S:${hook_com[subdir]} + msgs[$i]=${msg} + else + msgs[$i]=${hook_com[message]} + fi done return 0 diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index 4344d0b6e..906d984ef 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -18,6 +18,7 @@ static_functions=( VCS_INFO_check_com VCS_INFO_formats VCS_INFO_get_cmd + VCS_INFO_hook VCS_INFO_maxexports VCS_INFO_nvcsformats VCS_INFO_realpath -- cgit 1.4.1