summaryrefslogtreecommitdiff
path: root/Functions
diff options
context:
space:
mode:
Diffstat (limited to 'Functions')
-rw-r--r--Functions/VCS_Info/.distfiles1
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_detect_hg14
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_git35
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_hg295
-rw-r--r--Functions/VCS_Info/VCS_INFO_formats26
-rw-r--r--Functions/VCS_Info/VCS_INFO_hook10
-rw-r--r--Functions/VCS_Info/VCS_INFO_quilt190
-rw-r--r--Functions/VCS_Info/vcs_info30
8 files changed, 475 insertions, 126 deletions
diff --git a/Functions/VCS_Info/.distfiles b/Functions/VCS_Info/.distfiles
index cde11b26c..988e7ada4 100644
--- a/Functions/VCS_Info/.distfiles
+++ b/Functions/VCS_Info/.distfiles
@@ -11,6 +11,7 @@ vcs_info_lastmsg
VCS_INFO_maxexports
VCS_INFO_nvcsformats
vcs_info_printsys
+VCS_INFO_quilt
VCS_INFO_realpath
VCS_INFO_reposub
VCS_INFO_set
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_hg b/Functions/VCS_Info/Backends/VCS_INFO_detect_hg
index 36078b7a7..e2866afd5 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_detect_hg
+++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_hg
@@ -4,9 +4,17 @@
setopt localoptions NO_shwordsplit
-[[ $1 == '--flavours' ]] && return 1
+[[ $1 == '--flavours' ]] && { print -l hg-git hg-hgsubversion hg-hgsvn; return 0 }
VCS_INFO_check_com ${vcs_comm[cmd]} || return 1
vcs_comm[detect_need_file]=store
-VCS_INFO_bydir_detect '.hg'
-return $?
+VCS_INFO_bydir_detect '.hg' || return 1
+
+if [[ -d ${vcs_comm[basedir]}/.hg/svn ]] ; then
+ vcs_comm[overwrite_name]='hg-hgsubversion'
+elif [[ -d ${vcs_comm[basedir]}/.hgsvn ]] ; then
+ vcs_comm[overwrite_name]='hg-hgsvn'
+elif [[ -e ${vcs_comm[basedir]}/.hg/git-mapfile ]] ; then
+ vcs_comm[overwrite_name]='hg-git'
+fi
+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 4018b5d92..778d0610b 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
@@ -3,7 +3,7 @@
## Distributed under the same BSD-ish license as zsh itself.
setopt localoptions extendedglob NO_shwordsplit
-local gitdir gitbase gitbranch gitaction gitunstaged gitstaged gitsha1 gitmisc
+local gitdir gitbase gitbranch gitaction gitunstaged gitstaged gitsha1
local stgitpatch stgitunapplied
local -xA hook_com
@@ -139,33 +139,40 @@ if [[ -d $patchdir ]] ; then
stgit_unapplied=(${(f)"$(< "${patchdir}/unapplied")"})
stgit_unapplied=( ${(oa)stgit_applied} )
- if VCS_INFO_hook 'gen-stgit-patch-string' "${stgit_applied[@]}"; then
+ if VCS_INFO_hook 'gen-applied-string' "${stgit_applied[@]}"; then
if (( ${#stgit_applied} )); then
stgitpatch=${stgit_applied[1]}
else
- stgitpatch="no patch applied"
+ stgitpatch=""
fi
else
- stgitpatch=${hook_com[stgit-patch-string]}
+ stgitpatch=${hook_com[patch-string]}
fi
- if VCS_INFO_hook 'gen-stgit-unapplied-string' "${stgit_unapplied[@]}"; then
+ hook_com=()
+ if VCS_INFO_hook 'gen-unapplied-string' "${stgit_unapplied[@]}"; then
stgitunapplied=${#stgit_unapplied}
else
- stgitunapplied=${hook_com[stgit-unapplied-string]}
+ stgitunapplied=${hook_com[unapplied-string]}
fi
- zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" stgitformat stgitmsg || stgitmsg=" %p (%c)"
- 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}
+ if (( ${#stgit_applied} )); then
+ zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" patch-format stgitmsg || stgitmsg="%p (%n applied)"
+ else
+ zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" nopatch-format stgitmsg || stgitmsg="no patch applied"
+ fi
+ hook_com=( applied "${stgitpatch}" unapplied "${stgitunapplied}"
+ applied-n ${#stgit_applied} unapplied-n ${#stgit_unapplied} )
+ if VCS_INFO_hook 'set-patch-format' "${stgitmsg}"; then
+ zformat -f stgitmsg "${stgitmsg}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
+ "n:${#stgit_applied}" "c:${#stgit_unapplied}"
else
- gitmisc=${hook_com[stgit-replace]}
+ stgitmsg=${hook_com[patch-replace]}
fi
hook_com=()
else
- gitmisc=''
+ stgitmsg=''
fi
-VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}" "${gitstaged}" "${gitunstaged}" "${gitsha1}" "${gitmisc}"
+backend_misc[patches]="${stgitmsg}"
+VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}" "${gitstaged}" "${gitunstaged}" "${gitsha1}" "${stgitmsg}"
return 0
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg
index 1c103a541..2324bc809 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg
@@ -1,128 +1,239 @@
## vim:ft=zsh
## mercurial support by: Frank Terbeck <ft@bewatermyfriend.org>
+## with large contributions by Seth House <seth@eseth.com>
## Distributed under the same BSD-ish license as zsh itself.
-setopt localoptions NO_shwordsplit
-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
+setopt localoptions extendedglob NO_shwordsplit
+
+local hgbase bmfile branchfile rebasefile dirstatefile mqseriesfile \
+ mqstatusfile mqguardsfile patchdir mergedir \
+ r_csetid r_lrev r_branch i_bmhash i_bmname \
+ revformat branchformat hgactionstring hgchanges \
+ hgbmstring hgmqstring applied_string unapplied_string guards_string
+
+local -a hgid_args defrevformat defbranchformat \
+ hgbmarks mqpatches mqseries mqguards mqunapplied hgmisc \
+ i_patchguards i_negguards i_posguards
+
local -xA hook_com
hgbase=${vcs_comm[basedir]}
rrn=${hgbase:t}
+r_csetid='' # changeset id (long hash)
+r_lrev='' # local revision
+patchdir="${hgbase}/.hg/patches"
+mergedir="${hgbase}/.hg/merge/"
+bmfile="${hgbase}/.hg/bookmarks"
+branchfile="${hgbase}/.hg/branch"
+rebasefile="${hgbase}/.hg/rebasestate"
+dirstatefile="${hgbase}/.hg/dirstate"
+mqstatusfile="${patchdir}/status" # currently applied patches
+mqseriesfile="${patchdir}/series" # all patches
+mqguardsfile="${patchdir}/guards"
+
+# Look for any --flavours
+VCS_INFO_adjust
+
+# Calling the 'hg' program is quite a bit too slow for prompts.
+# Disabled by default anyway, so no harm done.
+if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then
+ # Calling hexdump is (much) faster than hg but doesn't get the local rev
+ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" use-simple \
+ && ( VCS_INFO_check_com hexdump ) && [[ -r ${dirstatefile} ]] ; then
+ r_csetid=$(hexdump -n 20 -e '1/1 "%02x"' ${dirstatefile})
+ else
+ hgid_args=( --debug id -i -n -b )
+
+ # Looking for changes is a tad bit slower since the dirstate cache must
+ # first be refreshed before being read
+ zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" \
+ "check-for-changes" || hgid_args+=( -r. )
+
+ local HGRCPATH
+ HGRCPATH="/dev/null" ${vcs_comm[cmd]} ${(z)hgid_args} \
+ | read -r r_csetid r_lrev r_branch
+ fi
+fi
-file="${hgbase}/.hg/branch"
-if [[ -r ${file} ]] ; then
- hgbranch_name=$(< ${file})
+# If the user doesn't opt to invoke hg we can still get the current branch
+if [[ -z ${r_branch} && -r ${branchfile} ]] ; then
+ r_branch=$(< ${branchfile})
else
- hgbranch_name="default"
+ r_branch="default"
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
+# The working dir has uncommitted-changes if the revision ends with a +
+if [[ $r_lrev[-1] == + ]] ; then
+ hgchanges=1
- if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" \
- "check-for-changes" ; then
+ r_lrev=${r_lrev%+}
+ r_csetid=${r_csetid%+}
+fi
- HGRCPATH="/dev/null" ${vcs_comm[cmd]} id --debug -i -n -b \
- | read -r hghash hglrev r_branch
+# This directory only exists during a merge
+[[ -d $mergedir ]] && hgactionstring="merging"
- # Are there uncommitted-changes?
- if [[ $hglrev[-1] == + ]] ; then
- hgchanges=1
- fi
+# This file only exists during a rebase
+[[ -e $rebasefile ]] && hgactionstring="rebasing"
+
+
+### Build the current revision display
+[[ -n ${r_csetid} ]] && defrevformat+=( "%h" )
+[[ -n ${r_lrev} ]] && defrevformat+=( "%r" )
+
+zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" \
+ "hgrevformat" revformat || revformat=${(j/:/)defrevformat}
+
+hook_com=( localrev "${r_lrev}" "hash" "${r_csetid}" )
- # Remove uncommitted-changes marker, if any
- hglrev=${hglrev/+/}
- hghash=${hghash/+/}
+if VCS_INFO_hook 'set-hgrev-format' "${revformat}"; then
+ zformat -f r_lrev "${revformat}" \
+ "r:${hook_com[localrev]}" "h:${hook_com[hash]}"
+else
+ r_lrev=${hook_com[rev-replace]}
+fi
+
+hook_com=()
+
+### Build the branch display
+[[ -n ${r_branch} ]] && defbranchformat+=( "%b" )
+[[ -n ${r_lrev} ]] && defbranchformat+=( "%r" )
+
+zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" \
+ branchformat branchformat || branchformat=${(j/:/)defbranchformat}
+
+hook_com=( branch "${r_branch}" revision "${r_lrev}" )
+
+if VCS_INFO_hook 'set-branch-format' "${branchformat}"; then
+ zformat -f branchformat "${branchformat}" \
+ "b:${hook_com[branch]}" "r:${hook_com[revision]}"
+else
+ branchformat=${hook_com[branch-replace]}
+fi
+
+hook_com=()
+
+### Look for current Bookmarks (this requires knowing the changeset id)
+if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-bookmarks \
+ && [[ -r "${bmfile}" ]] && [[ -n "$r_csetid" ]] ; then
+ while read -r i_bmhash i_bmname ; do
+ # Compare hash in bookmarks file with changeset id
+ [[ $r_csetid == $i_bmhash ]] && hgbmarks+=( $i_bmname )
+ done < ${bmfile}
+
+ if VCS_INFO_hook 'gen-hg-bookmark-string' "${hgbmarks[@]}"; then
+ hgbmstring=${(j:, :)hgbmarks}
else
- HGRCPATH="/dev/null" ${vcs_comm[cmd]} \
- parents --template="{node} {rev} {branches}\n" \
- | read -r hghash hglrev r_branch
+ hgbmstring=${hook_com[hg-bookmark-string]}
fi
- if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" "get-bookmarks" \
- && getbookmarks=1 || getbookmarks=0
+ hook_com=()
+fi
- 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}
+### Look for any applied Mercurial Queue patches
+if zstyle -T ":vcs_info:${vcs}:${usercontext}:${rrn}" get-mq \
+ && [[ -d $patchdir ]] ; then
+ if [[ -e $mqstatusfile ]]; then
+ mqpatches=( ${${(f)"$(< "${patchdir}/status")"}/(#s)[a-f0-9]##:/} )
+ mqpatches=( ${(Oa)mqpatches} )
fi
- if [[ -n ${hglrev} ]] ; then
- zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" hgrevformat revformat || revformat="%r:%h"
- 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]}
+ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-unapplied \
+ && [[ -r ${mqseriesfile} ]]; then
+ # Okay, here's a little something that assembles a list of unapplied
+ # patches that takes into account if mq-guards are active or not.
+
+ # Collect active guards
+ if [[ -r ${mqguardsfile} ]]; then
+ mqguards=( ${(f)"$(< "${mqguardsfile}")"} )
+ mqguards=( ${(oa)mqguards} )
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]}
+
+ while read -r i_patch i_patchguards ; do
+ # Skip commented lines
+ [[ ${i_patch} == [[:space:]]#"#"* ]] && continue
+
+ # Keep list of all patches
+ mqseries+=( $i_patch )
+
+ # Separate negative and positive guards to more easily find the
+ # intersection of active guards with patch guards
+ i_patchguards=( ${(s: :)i_patchguards} )
+ i_negguards=( ${${(M)i_patchguards:#*"#-"*}/(#s)\#-/} )
+ i_posguards=( ${${(M)i_patchguards:#*"#+"*}/(#s)\#+/} )
+
+ # Patch with any negative guards is never pushed if guard is active
+ if [[ ${#i_negguards} -gt 0
+ && ${#${(@M)mqguards:#${(~j,|,)i_negguards}}} -gt 0 ]] ; then
+ continue
fi
- hook_com=()
- fi
- zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat hgbranch || hgbranch="%b:%r"
- 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=()
+
+ # Patch with positive guards is only pushed if guard is active
+ if [[ ${#i_posguards} -gt 0 ]] ; then
+ if [[ ${#${(@M)mqguards:#${(~j,|,)i_posguards}}} -gt 0 ]] ; then
+ mqunapplied+=( $i_patch )
+ fi
+ continue
+ fi
+
+ # If we made it this far the patch isn't guarded and should be pushed
+ mqunapplied+=( $i_patch )
+ done < ${mqseriesfile}
fi
-else
- hgbranch="${hgbranch_name}"
-fi
-local patchdir=${hgbase}/.hg/patches/
+ if VCS_INFO_hook 'gen-applied-string' "${mqpatches[@]}"; then
+ (( ${#mqpatches} )) && applied_string=${mqpatches[1]}
+ else
+ applied_string=${hook_com[applied-string]}
+ fi
-if [[ -d $patchdir ]] ; then
- local -a mqpatches
- if [[ -e "${patchdir}/status" ]]; then
- mqpatches=( ${${(f)"$(< "${patchdir}/status")"}/(#s)[a-f0-9]##:/} )
- mqpatches=( ${(Oa)mqpatches} )
+ hook_com=()
+
+ if VCS_INFO_hook 'gen-unapplied-string' "${mqunapplied[@]}"; then
+ unapplied_string=${#mqunapplied}
else
- mqpatches=( )
+ unapplied_string=${hook_com[unapplied-string]}
fi
- if VCS_INFO_hook 'gen-mq-patch-string' "${mqpatches[@]}"; then
- if (( ${#mqpatches} )); then
- hgmqstring=${mqpatches[1]}
- else
- hgmqstring="no patch applied"
- fi
+ hook_com=()
+
+ if VCS_INFO_hook 'gen-mqguards-string' "${mqguards[@]}"; then
+ guards_string=${(j:,:)mqguards}
else
- hgbmstring=${hook_com[hg-mqpatch-string]}
+ guards_string=${hook_com[guards-string]}
fi
+
+ if (( ${#mqpatches} )); then
+ zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" patch-format \
+ hgmqstring || hgmqstring="%p (%n applied)"
+ else
+ zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" nopatch-format \
+ hgmqstring || hgmqstring="no patch applied"
+ fi
+
+ hook_com=( applied "${applied_string}" unapplied "${unapplied_string}"
+ applied-n ${#mqpatches} unapplied-n ${#mqunapplied}
+ guards "${guards_string}" guards-n ${#mqguards} )
+
+ if VCS_INFO_hook 'set-patch-format' ${qstring}; then
+ zformat -f hgmqstring "${hgmqstring}" \
+ "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
+ "n:${#mqpatches}" "c:${#mqunapplied}" \
+ "g:${hook_com[guards]}" "G:${#mqguards}"
+ else
+ hgmqstring=${hook_com[patch-replace]}
+ fi
+
hook_com=()
-else
- hgmqstring=''
fi
-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[@]}"
+
+### Build the misc string
+hgmisc+=( ${hgmqstring} )
+hgmisc+=( ${hgbmstring} )
+
+backend_misc[patches]="${hgmqstring}"
+backend_misc[bookmarks]="${hgbmstring}"
+
+VCS_INFO_formats "${hgactionstring}" "${branchformat}" "${hgbase}" '' "${hgchanges}" "${r_lrev}" "${(j:;:)hgmisc}"
return 0
diff --git a/Functions/VCS_Info/VCS_INFO_formats b/Functions/VCS_Info/VCS_INFO_formats
index db7a8dd48..469efa7d4 100644
--- a/Functions/VCS_Info/VCS_INFO_formats
+++ b/Functions/VCS_Info/VCS_INFO_formats
@@ -22,21 +22,18 @@ hook_com=(
unstaged_orig "$5"
revision "$6"
revision_orig "$6"
+ misc "$7"
+ misc_orig "$7"
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]}"
+VCS_INFO_hook 'post-backend'
+
## description:
# action: a string that signals a certain non-default condition in the
# repository (like 'rebase-i' in git). If this in non-empty,
@@ -46,8 +43,7 @@ hook_com[subdir_orig]="${hook_com[subdir]}"
# staged: non-empty if the repository contains staged changes.
# unstaged: non-empty if the repository contains unstaged changes.
# 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.
+# misc: a string that may contain anything the backend author likes.
#
# If an argument has no valid value for a given backend, an empty value
# should be provided. eg:
@@ -71,6 +67,15 @@ if [[ -n ${hook_com[unstaged]} ]] ; then
[[ -z ${tmp} ]] && hook_com[unstaged]='U' || hook_com[unstaged]=${tmp}
fi
+if [[ ${quiltmode} != 'standalone' ]] && VCS_INFO_hook "pre-addon-quilt"; then
+ local -x REPLY
+ VCS_INFO_quilt addon
+ hook_com[quilt]="${REPLY}"
+ unset REPLY
+elif [[ ${quiltmode} == 'standalone' ]]; then
+ hook_com[quilt]=${hook_com[misc]}
+fi
+
(( ${#msgs} > maxexports )) && msgs[$(( maxexports + 1 )),-1]=()
for i in {1..${#msgs}} ; do
if VCS_INFO_hook "set-message" $(( $i - 1 )) "${msgs[$i]}"; then
@@ -83,6 +88,7 @@ for i in {1..${#msgs}} ; do
r:${hook_com[base-name]} \
s:${hook_com[vcs]} \
u:${hook_com[unstaged]} \
+ Q:${hook_com[quilt]} \
R:${hook_com[base]} \
S:${hook_com[subdir]}
msgs[$i]=${msg}
@@ -90,4 +96,6 @@ for i in {1..${#msgs}} ; do
msgs[$i]=${hook_com[message]}
fi
done
+hook_com=()
+backend_misc=()
return 0
diff --git a/Functions/VCS_Info/VCS_INFO_hook b/Functions/VCS_Info/VCS_INFO_hook
index 71845d808..7274d726f 100644
--- a/Functions/VCS_Info/VCS_INFO_hook
+++ b/Functions/VCS_Info/VCS_INFO_hook
@@ -20,8 +20,11 @@ if (( debug )); then
fi
zstyle -a "${context}" hooks hooks || return 0
-# protect some internal variables in hooks
-typeset -r vcs rrn usercontext maxexports msgs vcs_comm
+# Protect some internal variables in hooks. The `-g' parameter to
+# typeset does *not* make the parameters global here (they are already
+# "*-local-export). It prevents typeset from creating *new* *local*
+# parameters in this function's scope.
+typeset -g -r vcs rrn usercontext maxexports msgs vcs_comm
for hook in ${hooks} ; do
func="+vi-${hook}"
if (( ${+functions[$func]} == 0 )); then
@@ -29,6 +32,7 @@ for hook in ${hooks} ; do
continue
fi
(( debug )) && printf ' + Running function: "%s"\n' "${func}"
+ true
${func} "$@"
case $? in
(0)
@@ -38,5 +42,5 @@ for hook in ${hooks} ; do
;;
esac
done
-typeset +r vcs rrn usercontext maxexports msgs vcs_comm
+typeset -g +r vcs rrn usercontext maxexports msgs vcs_comm
return $ret
diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt
new file mode 100644
index 000000000..fc127c23b
--- /dev/null
+++ b/Functions/VCS_Info/VCS_INFO_quilt
@@ -0,0 +1,190 @@
+## vim:ft=zsh:foldmethod=marker
+
+function VCS_INFO_quilt-match() {
+ emulate -L zsh
+ setopt extendedglob
+ local d mode="$1" param="$2"
+ local -a list
+
+ case ${mode} in
+ (assoc) list=( ${(kOP)param} );;
+ (array) : "${foo[@]}" ${(t)foo}; list=( ${(OP)param} );;
+ (*) return 1;;
+ esac
+ for d in "${list[@]}"; do
+ if [[ ${PWD} == ${d%/##}(|/*) ]]; then
+ print "$d"
+ return 0
+ fi
+ done
+ return 1
+}
+
+function VCS_INFO_quilt-standalone-detect() {
+ emulate -L zsh
+ setopt extendedglob
+ local param
+ local -i ret
+
+ zstyle -s "${context}" quilt-standalone param || return 1
+ [[ "${param}" == 'never' ]] && return 1
+ [[ "${param}" == 'always' ]] && return 0
+
+ if (( ${+functions[$param]} )); then
+ ${param}
+ return $?
+ fi
+
+ case ${(Pt)param} in
+ *association*)
+ local m
+ local -A A
+ m="$(VCS_INFO_quilt-match assoc ${param})"
+ A=(${(kvP)param})
+ (( $? == 0 )) && [[ ${A[$m]} == "true" ]] && return 0
+ return 1
+ ;;
+ *array*)
+ typeset -gU ${param}
+ VCS_INFO_quilt-match array ${param} > /dev/null
+ return $?
+ ;;
+ *scalar*)
+ [[ "${(P)param}" == 'always' ]] && return 0
+ [[ "${(P)param}" == 'never' ]] && return 1
+ ;;
+ esac
+ # If nothing hit yet, it just wasn't meant to be.
+ return 1
+}
+
+function VCS_INFO_quilt-dirfind() {
+ # This is a wrapper around VCS_INFO_bydir_detect(). It makes sure
+ # that $vcs_comm[] is unchanged. Currently, changing anything in it
+ # should not be an issue, but this makes sure the code can safely
+ # be called elsewhere, too - if needed.
+ emulate -L zsh
+ setopt extendedglob
+ local dir="$1" file="$2"; shift $#
+ local ret oldfile olddir
+
+ olddir=${vcs_comm[basedir]}
+ vcs_comm[basedir]=''
+ if [[ -n "${file}" ]]; then
+ oldfile=${vcs_comm[detect_need_file]}
+ vcs_comm[detect_need_file]=${file}
+ fi
+ VCS_INFO_bydir_detect ${dir}
+ ret=$?
+ [[ -n "${file}" ]] && vcs_comm[detect_need_file]=${oldfile}
+ printf '%s' ${vcs_comm[basedir]}
+ vcs_comm[basedir]="${olddir}"
+ return ${ret}
+}
+
+function VCS_INFO_quilt() {
+ emulate -L zsh
+ setopt extendedglob
+ local mode="$1"
+ local patches pc tmp qstring root
+ local -i ret
+ local -x context
+ local -a applied unapplied applied_string unapplied_string quiltcommand
+ local -Ax hook_com
+
+ context=":vcs_info:${vcs}.quilt-${mode}:${usercontext}:${rrn}"
+ zstyle -t "${context}" use-quilt || return 1
+
+ case ${mode} in
+ (standalone)
+ VCS_INFO_quilt-standalone-detect || return 1
+ ;;
+ (addon)
+ ;;
+ (*)
+ printf 'Invalid mode: `%s'\''\n' "$1"
+ return 2
+ ;;
+ esac
+
+ zstyle -s "${context}" quilt-patch-dir patches || patches="${QUILT_PATCHES}"
+ if [[ "${patches}" != /* ]]; then
+ tmp=${patches:-patches}
+ patches="$(VCS_INFO_quilt-dirfind "${tmp}")"
+ ret=$?
+ (( ret )) && return ${ret}
+ patches=${patches}/${tmp}
+ else
+ [[ -d ${patches} ]] || return 1
+ fi
+
+ pc="$(VCS_INFO_quilt-dirfind .pc .version)"
+ ret=$?
+ if (( ret == 0 )); then
+ [[ ${quiltmode} == 'standalone' ]] && root=${pc}
+ pc=${pc}/.pc
+ if [[ -e ${pc}/applied-patches ]]; then
+ applied=( ${(f)"$(<$pc/applied-patches)"} )
+ # throw away empty entries
+ applied=( ${applied:#} )
+ applied=( ${(Oa)applied} )
+ else
+ applied=()
+ fi
+ fi
+ if zstyle -t "${context}" get-unapplied; then
+ # This zstyle call needs to be moved further up if `quilt' needs
+ # to be run in more places than this one.
+ zstyle -s "${context}" quiltcommand quiltcommand || quiltcommand='quilt'
+ unapplied=( ${(f)"$(QUILT_PATCHES=$patches $quiltcommand --quiltrc /dev/null unapplied 2> /dev/null)"} )
+ unapplied=( ${unapplied:#} )
+ else
+ unapplied=()
+ fi
+
+ if VCS_INFO_hook 'gen-applied-string' "${applied[@]}"; then
+ if (( ${#applied} )); then
+ applied_string=${applied[1]}
+ else
+ applied_string=""
+ fi
+ else
+ applied_string=${hook_com[applied-string]}
+ fi
+ hook_com=()
+ if VCS_INFO_hook 'gen-unapplied-string' "${unapplied[@]}"; then
+ unapplied_string="${#unapplied}"
+ else
+ unapplied_string=${hook_com[unapplied-string]}
+ fi
+
+ if (( ${#applied} )); then
+ zstyle -s "${context}" patch-format qstring || qstring="%p (%n applied)"
+ else
+ zstyle -s "${context}" nopatch-format qstring || qstring="no patch applied"
+ fi
+ hook_com=( applied "${applied_string}" unapplied "${unapplied_string}"
+ applied-n ${#applied} unapplied-n ${#unapplied} )
+ if VCS_INFO_hook 'set-patch-format' ${qstring}; then
+ zformat -f qstring "${qstring}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
+ "n:${#applied}" "c:${#unapplied}"
+ else
+ qstring=${hook_com[patch-replace]}
+ fi
+ hook_com=()
+
+ case ${mode} in
+ (standalone)
+ VCS_INFO_formats '' '' "${root}" '' '' '' "${qstring}"
+ VCS_INFO_set
+ ;;
+ (addon)
+ # When VCS_INFO_quilt() is called with "addon" a "local -x REPLY" variable
+ # should be in place. That variable can be unset after it's being used.
+ REPLY="${qstring}"
+ ;;
+ esac
+
+ VCS_INFO_hook 'post-quilt' ${mode} ${patches} ${pc:-\\-nopc-}
+}
+VCS_INFO_quilt "$@"
diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info
index 7ae11230e..6ce1cd702 100644
--- a/Functions/VCS_Info/vcs_info
+++ b/Functions/VCS_Info/vcs_info
@@ -21,6 +21,7 @@ static_functions=(
VCS_INFO_hook
VCS_INFO_maxexports
VCS_INFO_nvcsformats
+ VCS_INFO_quilt
VCS_INFO_realpath
VCS_INFO_reposub
VCS_INFO_set
@@ -45,12 +46,12 @@ vcs_info () {
[[ -r . ]] || return 0
local pat
- local -i found
+ local -i found retval
local -a enabled disabled dps
- local -x usercontext vcs rrn LC_MESSAGES
+ local -x usercontext vcs rrn quiltmode LC_MESSAGES
local -ix maxexports
local -ax msgs
- local -Ax vcs_comm
+ local -Ax vcs_comm hook_com backend_misc user_data
LC_MESSAGES=C
if [[ -n ${LC_ALL} ]]; then
@@ -58,9 +59,18 @@ vcs_info () {
LANG=${LC_ALL}
local -x LC_ALL
fi
- vcs='-init-'; rrn='-all-'
+ 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
+ VCS_INFO_set --nvcs
+ return 0
+ fi
+
zstyle -a ":vcs_info:${vcs}:${usercontext}:${rrn}" "enable" enabled
(( ${#enabled} == 0 )) && enabled=( all )
@@ -99,10 +109,20 @@ vcs_info () {
done
(( found == 0 )) && {
- VCS_INFO_set --nvcs
+ 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