1## vim:ft=zsh 2## mercurial support by: Frank Terbeck <ft@bewatermyfriend.org> 3## with large contributions by Seth House <seth@eseth.com> 4## Distributed under the same BSD-ish license as zsh itself. 5 6setopt localoptions extendedglob NO_shwordsplit 7 8local hgbase bmfile branchfile rebasefile dirstatefile mqseriesfile \ 9 mqstatusfile mqguardsfile patchdir mergedir \ 10 r_csetid r_lrev r_branch i_bmhash i_bmname \ 11 revformat branchformat hgactionstring hgchanges \ 12 hgbmstring hgmqstring applied_string unapplied_string guards_string 13 14local -a hgid_args defrevformat defbranchformat \ 15 hgbmarks mqpatches mqseries mqguards mqunapplied hgmisc \ 16 i_patchguards i_negguards i_posguards 17 18local -xA hook_com 19 20hgbase=${vcs_comm[basedir]} 21rrn=${hgbase:t} 22r_csetid='' # changeset id (long hash) 23r_lrev='' # local revision 24patchdir="${hgbase}/.hg/patches" 25mergedir="${hgbase}/.hg/merge/" 26bmfile="${hgbase}/.hg/bookmarks" 27branchfile="${hgbase}/.hg/branch" 28rebasefile="${hgbase}/.hg/rebasestate" 29dirstatefile="${hgbase}/.hg/dirstate" 30mqstatusfile="${patchdir}/status" # currently applied patches 31mqseriesfile="${patchdir}/series" # all patches 32mqguardsfile="${patchdir}/guards" 33 34# Look for any --flavours 35VCS_INFO_adjust 36 37# Calling the 'hg' program is quite a bit too slow for prompts. 38# Disabled by default anyway, so no harm done. 39if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then 40 if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" use-simple \ 41 && ( VCS_INFO_check_com hexdump ) && [[ -r ${dirstatefile} ]] ; then 42 # Calling hexdump is (much) faster than hg but doesn't get the local rev 43 r_csetid=$(hexdump -n 20 -e '1/1 "%02x"' ${dirstatefile}) 44 else 45 # Settling for a short (but unique!) hash because getting the full 46 # 40-char hash in addition to all the other info we want isn't 47 # available in a single hg invocation 48 hgid_args=( id -i -n -b ) 49 50 # Looking for changes is a tad bit slower since the dirstate cache must 51 # first be refreshed before being read 52 zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" \ 53 "check-for-changes" || hgid_args+=( -r. ) 54 55 local HGRCPATH 56 HGRCPATH="/dev/null" ${vcs_comm[cmd]} ${(z)hgid_args} 2> /dev/null \ 57 | read -r r_csetid r_lrev r_branch 58 fi 59fi 60 61# If the user doesn't opt to invoke hg we can still get the current branch 62if [[ -z ${r_branch} && -r ${branchfile} ]] ; then 63 r_branch=$(< ${branchfile}) 64fi 65 66# If we still don't know the branch it's safe to assume default 67[[ -n ${r_branch} ]] || r_branch="default" 68 69# The working dir has uncommitted-changes if the revision ends with a + 70if [[ $r_lrev[-1] == + ]] ; then 71 hgchanges=1 72 73 r_lrev=${r_lrev%+} 74 r_csetid=${r_csetid%+} 75fi 76 77# This directory only exists during a merge 78[[ -d $mergedir ]] && hgactionstring="merging" 79 80# This file only exists during a rebase 81[[ -e $rebasefile ]] && hgactionstring="rebasing" 82 83 84### Build the current revision display 85[[ -n ${r_csetid} ]] && defrevformat+=( "%h" ) 86[[ -n ${r_lrev} ]] && defrevformat+=( "%r" ) 87 88zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" \ 89 "hgrevformat" revformat || revformat=${(j/:/)defrevformat} 90 91hook_com=( localrev "${r_lrev}" "hash" "${r_csetid}" ) 92 93if VCS_INFO_hook 'set-hgrev-format' "${revformat}"; then 94 zformat -f r_lrev "${revformat}" \ 95 "r:${hook_com[localrev]}" "h:${hook_com[hash]}" 96else 97 r_lrev=${hook_com[rev-replace]} 98fi 99 100hook_com=() 101 102### Build the branch display 103[[ -n ${r_branch} ]] && defbranchformat+=( "%b" ) 104[[ -n ${r_lrev} ]] && defbranchformat+=( "%r" ) 105 106zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" \ 107 branchformat branchformat || branchformat=${(j/:/)defbranchformat} 108 109hook_com=( branch "${r_branch}" revision "${r_lrev}" ) 110 111if VCS_INFO_hook 'set-branch-format' "${branchformat}"; then 112 zformat -f branchformat "${branchformat}" \ 113 "b:${hook_com[branch]}" "r:${hook_com[revision]}" 114else 115 branchformat=${hook_com[branch-replace]} 116fi 117 118hook_com=() 119 120### Look for current Bookmarks (this requires knowing the changeset id) 121if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-bookmarks \ 122 && [[ -r "${bmfile}" ]] && [[ -n "$r_csetid" ]] ; then 123 while read -r i_bmhash i_bmname ; do 124 # Compare hash in bookmarks file with changeset id 125 [[ $i_bmhash == $r_csetid* ]] && hgbmarks+=( $i_bmname ) 126 done < ${bmfile} 127 128 if VCS_INFO_hook 'gen-hg-bookmark-string' "${hgbmarks[@]}"; then 129 hgbmstring=${(j:, :)hgbmarks} 130 else 131 hgbmstring=${hook_com[hg-bookmark-string]} 132 fi 133 134 hook_com=() 135fi 136 137### Look for any applied Mercurial Queue patches 138if zstyle -T ":vcs_info:${vcs}:${usercontext}:${rrn}" get-mq \ 139 && [[ -d $patchdir ]] ; then 140 if [[ -e $mqstatusfile ]]; then 141 mqpatches=( ${${(f)"$(< "${patchdir}/status")"}/(#s)[a-f0-9]##:/} ) 142 mqpatches=( ${(Oa)mqpatches} ) 143 fi 144 145 if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-unapplied \ 146 && [[ -r ${mqseriesfile} ]]; then 147 # Okay, here's a little something that assembles a list of unapplied 148 # patches that takes into account if mq-guards are active or not. 149 150 # Collect active guards 151 if [[ -r ${mqguardsfile} ]]; then 152 mqguards=( ${(f)"$(< "${mqguardsfile}")"} ) 153 mqguards=( ${(oa)mqguards} ) 154 fi 155 156 while read -r i_patch i_patchguards ; do 157 # Skip commented lines 158 [[ ${i_patch} == [[:space:]]#"#"* ]] && continue 159 160 # Keep list of all patches 161 mqseries+=( $i_patch ) 162 163 # Separate negative and positive guards to more easily find the 164 # intersection of active guards with patch guards 165 i_patchguards=( ${(s: :)i_patchguards} ) 166 i_negguards=( ${${(M)i_patchguards:#*"#-"*}/(#s)\#-/} ) 167 i_posguards=( ${${(M)i_patchguards:#*"#+"*}/(#s)\#+/} ) 168 169 # Patch with any negative guards is never pushed if guard is active 170 if [[ ${#i_negguards} -gt 0 171 && ${#${(@M)mqguards:#${(~j,|,)i_negguards}}} -gt 0 ]] ; then 172 continue 173 fi 174 175 # Patch with positive guards is only pushed if guard is active 176 if [[ ${#i_posguards} -gt 0 ]] ; then 177 if [[ ${#${(@M)mqguards:#${(~j,|,)i_posguards}}} -gt 0 ]] ; then 178 mqunapplied+=( $i_patch ) 179 fi 180 continue 181 fi 182 183 # If we made it this far the patch isn't guarded and should be pushed 184 mqunapplied+=( $i_patch ) 185 done < ${mqseriesfile} 186 fi 187 188 if VCS_INFO_hook 'gen-applied-string' "${mqpatches[@]}"; then 189 (( ${#mqpatches} )) && applied_string=${mqpatches[1]} 190 else 191 applied_string=${hook_com[applied-string]} 192 fi 193 194 hook_com=() 195 196 if VCS_INFO_hook 'gen-unapplied-string' "${mqunapplied[@]}"; then 197 unapplied_string=${#mqunapplied} 198 else 199 unapplied_string=${hook_com[unapplied-string]} 200 fi 201 202 hook_com=() 203 204 if VCS_INFO_hook 'gen-mqguards-string' "${mqguards[@]}"; then 205 guards_string=${(j:,:)mqguards} 206 else 207 guards_string=${hook_com[guards-string]} 208 fi 209 210 if (( ${#mqpatches} )); then 211 zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" patch-format \ 212 hgmqstring || hgmqstring="%p (%n applied)" 213 else 214 zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" nopatch-format \ 215 hgmqstring || hgmqstring="no patch applied" 216 fi 217 218 hook_com=( applied "${applied_string}" unapplied "${unapplied_string}" 219 applied-n ${#mqpatches} unapplied-n ${#mqunapplied} all-n ${#mqseries} 220 guards "${guards_string}" guards-n ${#mqguards} ) 221 222 if VCS_INFO_hook 'set-patch-format' ${qstring}; then 223 zformat -f hgmqstring "${hgmqstring}" \ 224 "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \ 225 "n:${#mqpatches}" "c:${#mqunapplied}" "a:${#mqseries}" \ 226 "g:${hook_com[guards]}" "G:${#mqguards}" 227 else 228 hgmqstring=${hook_com[patch-replace]} 229 fi 230 231 hook_com=() 232fi 233 234 235### Build the misc string 236hgmisc+=( ${hgmqstring} ) 237hgmisc+=( ${hgbmstring} ) 238 239backend_misc[patches]="${hgmqstring}" 240backend_misc[bookmarks]="${hgbmstring}" 241 242VCS_INFO_formats "${hgactionstring}" "${branchformat}" "${hgbase}" '' "${hgchanges}" "${r_lrev}" "${(j:;:)hgmisc}" 243return 0 244