diff options
Diffstat (limited to 'Functions/VCS_Info')
18 files changed, 345 insertions, 102 deletions
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs b/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs index 7a5ee1eef..a57959ec9 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs +++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs @@ -7,5 +7,18 @@ setopt localoptions NO_shwordsplit [[ $1 == '--flavours' ]] && return 1 VCS_INFO_check_com ${vcs_comm[cmd]} || return 1 -[[ -d "./CVS" ]] && [[ -r "./CVS/Repository" ]] && return 0 -return 1 +if ! [[ -d "./CVS" ]] || ! [[ -r "./CVS/Repository" ]] ; then + return 1 +fi + +# Look for the most distant parent that still has a CVS subdirectory. +local cvsbase="." +cvsbase=${cvsbase:P} +while [[ -d "${cvsbase:h}/CVS" ]]; do + cvsbase="${cvsbase:h}" + if [[ $cvsbase == '/' ]]; then + break + fi +done + +vcs_comm[basedir]="${cvsbase}" diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_git b/Functions/VCS_Info/Backends/VCS_INFO_detect_git index e4191f474..b7955de38 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_detect_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_git @@ -7,6 +7,7 @@ setopt localoptions NO_shwordsplit [[ $1 == '--flavours' ]] && { print -l git-p4 git-svn; return 0 } if VCS_INFO_check_com ${vcs_comm[cmd]} && vcs_comm[gitdir]="$(${vcs_comm[cmd]} rev-parse --git-dir 2> /dev/null)" ; then + vcs_comm[basedir]="$( ${vcs_comm[cmd]} rev-parse --show-toplevel 2> /dev/null )" 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 diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr b/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr index b30e0e12b..f1f5527e8 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr @@ -100,14 +100,7 @@ else fi rrn=${bzrbase:t} -zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat bzrbr || bzrbr="%b:%r" -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_set-branch-format "${bzrinfo[2]}" "${bzrinfo[1]}" && + bzrbr="${REPLY}" VCS_INFO_formats '' "${bzrbr}" "${bzrbase}" '' "${bzr_changes}" "${bzrinfo[1]}" "${bzr_changes}" return 0 diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs b/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs index 9b828bd11..bc0d5cfe5 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs @@ -5,17 +5,8 @@ setopt localoptions NO_shwordsplit local cvsbranch cvsbase -# Look for the most distant parent that still has a CVS subdirectory. +cvsbase="${vcs_comm[basedir]}" # VCS_INFO_detect_cvs ensured that ./CVS/Repository exists. -cvsbase="." -cvsbase=${cvsbase:P} -while [[ -d "${cvsbase:h}/CVS" ]]; do - cvsbase="${cvsbase:h}" - if [[ $cvsbase == '/' ]]; then - break - fi -done - cvsbranch=$(< ./CVS/Repository) rrn=${cvsbase:t} cvsbranch=${cvsbranch##${rrn}/} diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil b/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil index fd0f8389e..e84b3abc0 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil @@ -20,5 +20,6 @@ if [ -n "$merging" ]; then action="merging" fi +rrn=${fsinfo[local_root]:t} VCS_INFO_formats "$action" "${fsbranch}" "${fsinfo[local_root]}" '' "$changed" "${fshash}" "${fsinfo[repository]}" 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 ceb4f978a..e45eebc8e 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -132,13 +132,17 @@ VCS_INFO_git_handle_patches () { VCS_INFO_set-patch-format 'git_patches_applied' 'git_applied_s' \ 'git_patches_unapplied' 'git_unapplied_s' \ ":vcs_info:${vcs}:${usercontext}:${rrn}" gitmsg \ - '' '' + '' '' '' gitmisc=$REPLY } gitdir=${vcs_comm[gitdir]} VCS_INFO_git_getbranch ${gitdir} -gitbase=$( ${vcs_comm[cmd]} rev-parse --show-toplevel ) +gitbase=${vcs_comm[basedir]} +if [[ -z ${gitbase} ]]; then + # Bare repository + gitbase=${gitdir:P} +fi rrn=${gitbase:t} if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then gitsha1=$(${vcs_comm[cmd]} rev-parse --quiet --verify HEAD) @@ -192,13 +196,19 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then # 'git rebase -i' patchdir="${gitdir}/rebase-merge" local p - [[ -f "${patchdir}/done" ]] && - for p in ${(f)"$(< "${patchdir}/done")"}; do + (( ${+functions[VCS_INFO_git_map_rebase_line_to_hash_and_subject]} )) || + VCS_INFO_git_map_rebase_line_to_hash_and_subject() { + local p=$1 + unset REPLY # pick/edit/fixup/squash/reword: Add "$hash $subject" to $git_patches_applied. # exec: Add "exec ${command}" to $git_patches_applied. # (anything else): As 'exec'. case $p in - ((p|pick|e|edit|r|reword|f|fixup|s|squash)' '*) + ([#]*) + # Comment line. Skip. + return 0 + ;; + (''(p|pick|e|edit|r|reword|f|fixup|s|squash)' '*) # The line is of the form "pick $hash $subject". # Just strip the verb and we're good to go. p=${p#* } @@ -221,11 +231,11 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then p="${p%% *} ?" fi ;; - (x *) + (''(x|exec) *) # The line is of the form 'exec foo bar baz' where 'foo bar # baz' is a shell command. There's no way to map _that_ to # "$hash $subject", but I hope this counts as making an effort. - p=${p/x /exec } + p=${p/#x /exec } ;; (*) # Forward compatibility with not-yet-existing 'git rebase -i' verbs. @@ -233,30 +243,74 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then p+=" ?" fi esac - git_patches_applied+=("$p") - done + REPLY=$p + } + if [[ -f "${patchdir}/done" ]] ; then + for p in ${(f)"$(< "${patchdir}/done")"}; do + VCS_INFO_git_map_rebase_line_to_hash_and_subject "$p" + (( $+REPLY )) && git_patches_applied+=( "$REPLY" ) + done + fi if [[ -f "${patchdir}/git-rebase-todo" ]] ; then - # TODO: Process ${patchdir}/git-rebase-todo lines like ${patchdir}/done lines are - git_patches_unapplied=( ${${(f)${"$(<"${patchdir}/git-rebase-todo")"}}:#[#]*} ) + for p in ${(f)"$(< "${patchdir}/git-rebase-todo")"}; do + VCS_INFO_git_map_rebase_line_to_hash_and_subject "$p" + (( $+REPLY )) && git_patches_unapplied+=( "$REPLY" ) + done fi VCS_INFO_git_handle_patches elif [[ -d "${gitdir}/rebase-apply" ]]; then - # 'git rebase' without -i + # 'git rebase' without -i, or 'git am' patchdir="${gitdir}/rebase-apply" local next="${patchdir}/next" + local this_patch_file if [[ -f $next ]]; then local cur=$(< $next) local p subject - # Fake patch names for all but current patch - for ((p = 1; p < cur; p++)); do - printf -v "git_patches_applied[$p]" "%04d ?" "$p" - done + # Compute patch names for patches "before" the current patch + if [[ -r ${patchdir}/rewritten ]]; then + if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" use-simple; then + git_patches_applied=( ${${(f)"$(<${patchdir}/rewritten)"}// */' ?'} ) + else + git_patches_applied=( + ${(f)"$(${vcs_comm[cmd]} log --no-walk=unsorted --pretty='%h %s' ${${(f)"$(<${patchdir}/rewritten)"}%% *} --)"} + ) + fi + else + # Compatibility with old git. In 2.11 and 2.24, at least, + # (( cur == 1 )), so the loop body would never run. However, both + # of these versions have original-commit and orig-head and would + # take the 'if' branch, rather than this 'else' branch. + for ((p = 1; p < cur; p++)); do + printf -v this_patch_file "%s/%04d" "${patchdir}" "${p}" + if [[ -f $this_patch_file ]]; then + VCS_INFO_patch2subject "${this_patch_file}" + git_patches_applied+=( "$p $REPLY" ) + else + git_patches_applied+=( "$p ?" ) + fi + done + fi + # Set $subject to the info for the current patch if [[ -f "${patchdir}/msg-clean" ]]; then subject="${$(< "${patchdir}/msg-clean")[(f)1]}" - elif local this_patch_file - printf -v this_patch_file "%s/%04d" "${patchdir}" "${cur}" + elif [[ -f "${patchdir}/final-commit" ]]; then + # This value is not rfc2047-encoded. It's also available via + # "${patchdir}/info". + subject="${$(< "${patchdir}/final-commit")[(f)1]}" + elif printf -v this_patch_file "%s/%04d" "${patchdir}" "${cur}" [[ -f $this_patch_file ]] then + # This branch is last for several reasons: + # + # - The "Subject" header will be MIME-encoded (rfc2047). + # + # - If the mail has full rfc822 headers (including "Received" and + # so on), we won't find the "Subject:" header, since + # VCS_INFO_patch2subject only checks the first few lines. + # + # - In --scissors mode, we may find the outer "Subject:" header, + # whereas the inner one (after the scissors line) will be used, + # if present. () { local REPLY VCS_INFO_patch2subject "${this_patch_file}" @@ -266,14 +320,32 @@ elif [[ -d "${gitdir}/rebase-apply" ]]; then subject=${subject:-'?'} if [[ -f "${patchdir}/original-commit" ]]; then git_patches_applied+=("$(< ${patchdir}/original-commit) $subject") + elif [[ -f "${patchdir}/next" ]]; then + git_patches_applied+=("$(< ${patchdir}/next) $subject") else git_patches_applied+=("? $subject") fi - local last="$(< "${patchdir}/last")" - if (( cur+1 <= last )); then - git_patches_unapplied=( {$((cur+1))..$last} ) + # Handle patches scheduled for after the current patch, if instructed to. + if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-unapplied; then + local last="$(< "${patchdir}/last")" + if [[ -r ${patchdir}/original-commit && -r ${patchdir}/orig-head ]] && + ! zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" use-simple + then + git_patches_unapplied+=( ${(f)"$(${vcs_comm[cmd]} log --reverse --pretty="%h %s" "$(<${patchdir}/original-commit)..$(<${patchdir}/orig-head)")"} ) + else + for ((p = cur+1; p <= last; p++)); do + printf -v this_patch_file "%s/%04d" "${patchdir}" "${p}" + if [[ -f $this_patch_file ]]; then + VCS_INFO_patch2subject "${this_patch_file}" + git_patches_unapplied+=( "$p $REPLY" ) + else + git_patches_unapplied+=( "$p ?" ) + fi + done + fi fi fi + unset this_patch_file VCS_INFO_git_handle_patches elif [[ -f "${gitdir}/MERGE_HEAD" ]]; then diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg index cd5ef321d..ea3798b81 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg @@ -5,7 +5,7 @@ setopt localoptions extendedglob NO_shwordsplit -local hgbase bmfile branchfile rebasefile dirstatefile mqseriesfile \ +local hgbase bmfile branchfile topicfile rebasefile dirstatefile mqseriesfile \ curbmfile curbm \ mqstatusfile mqguardsfile patchdir mergedir \ r_csetid r_lrev r_branch i_bmhash i_bmname \ @@ -14,7 +14,7 @@ local hgbase bmfile branchfile rebasefile dirstatefile mqseriesfile \ local -a hgid_args defrevformat defbranchformat \ hgbmarks mqpatches mqguards mqunapplied hgmisc \ - i_patchguards i_negguards i_posguards + i_patch i_patchguards i_negguards i_posguards local -A hook_com @@ -27,6 +27,7 @@ mergedir="${hgbase}/.hg/merge/" bmfile="${hgbase}/.hg/bookmarks" curbmfile="${hgbase}/.hg/bookmarks.current" branchfile="${hgbase}/.hg/branch" +topicfile="${hgbase}/.hg/topic" rebasefile="${hgbase}/.hg/rebasestate" dirstatefile="${hgbase}/.hg/dirstate" mqstatusfile="${patchdir}/status" # currently applied patches @@ -48,27 +49,34 @@ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then # Settling for a short (but unique!) hash because getting the full # 40-char hash in addition to all the other info we want isn't # available in a single hg invocation - hgid_args=( id -i -n -b ) + hgid_args=( id -i -n ) # 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 HGPLAIN HGPLAIN=1 ${vcs_comm[cmd]} ${(z)hgid_args} 2> /dev/null \ - | read -r r_csetid r_lrev r_branch + | read -r r_csetid r_lrev fi fi # If the user doesn't opt to invoke hg we can still get the current branch -if [[ -z ${r_branch} && -r ${branchfile} ]] ; then +if [[ -r ${branchfile} ]] ; then r_branch=$(< ${branchfile}) fi # If we still don't know the branch it's safe to assume default [[ -n ${r_branch} ]] || r_branch="default" +# Show topic if there is any (the UI for this experimental concept is not yet +# final, but for a long time the convention has been to join the branch name +# and the topic name by a colon) +if [[ -f ${topicfile} && -r ${topicfile} && -s ${topicfile} ]] ; then + IFS= read -r REPLY < ${topicfile} + r_branch=${r_branch}:${REPLY} +fi + # The working dir has uncommitted-changes if the revision ends with a + if [[ $r_lrev[-1] == + ]] ; then hgchanges=1 @@ -175,6 +183,9 @@ if zstyle -T ":vcs_info:${vcs}:${usercontext}:${rrn}" get-mq \ # Skip commented lines [[ ${i_patch} == [[:space:]]#"#"* ]] && continue + # Skip applied patches + (( ${+mqpatches[(re)${i_patch}]} )) && continue + # Separate negative and positive guards to more easily find the # intersection of active guards with patch guards i_patchguards=( ${(s: :)i_patchguards} ) @@ -208,12 +219,16 @@ if zstyle -T ":vcs_info:${vcs}:${usercontext}:${rrn}" get-mq \ fi local -A extra_hook_com=( guards "${guards_string}" guards-n ${#mqguards} ) - local -a extra_zformats=( "g:${extra_hook_com[guards]}" "G:${#mqguards}" ) + + (( ${+functions[VCS_INFO_hg_extra_zformats]} )) || + VCS_INFO_hg_extra_zformats() { + reply=( "g:${hook_com[guards]}" "G:${#mqguards}" ) + } VCS_INFO_set-patch-format 'mqpatches' 'applied_string' \ 'mqunapplied' 'unapplied_string' \ ":vcs_info:${vcs}:${usercontext}:${rrn}" hgmqstring \ - extra_hook_com extra_zformats + extra_hook_com VCS_INFO_hg_extra_zformats '' hgmqstring=$REPLY fi diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 b/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 index 329884982..e8a08a663 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 @@ -17,13 +17,8 @@ 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" -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=() +rrn=${p4base:t} +VCS_INFO_set-branch-format "${p4info[Client_name]}" "${change}" && + p4branch="${REPLY}" 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 1d2d22ffb..149e30222 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk @@ -8,13 +8,7 @@ local -A hook_com svkbase=${vcs_comm[basedir]} rrn=${svkbase:t} -zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat svkbranch || svkbranch="%b:%r" -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_set-branch-format "${vcs_comm[branch]}" "${vcs_comm[revision]}" && + svkbranch="${REPLY}" 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 21590addd..b33efc2fb 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn @@ -10,6 +10,7 @@ local -i rc local -A svninfo parentinfo cwdinfo local -A hook_com integer -r SVN_ERR_WC_UPGRADE_REQUIRED=155036 # from /usr/local/include/subversion-1/svn_error_codes.h +integer -r SVN_ERR_WC_UNSUPPORTED_FORMAT=155021 svnbase="."; svninfo=() @@ -22,7 +23,14 @@ rc=$? if (( rc != 0 )) ; then if (( rc == 1 )) && [[ -n ${(M)dat:#"svn: E${SVN_ERR_WC_UPGRADE_REQUIRED}: "*} ]]; then hook_com=() - VCS_INFO_formats '' '?' '?' '' '' '?' 'upgrade required' + # User should run 'svn upgrade' + VCS_INFO_formats '' '?' '?' '' '' '?' 'working copy upgrade required' + return $? + elif (( rc == 1 )) && [[ -n ${(M)dat:#"svn: E${SVN_ERR_WC_UNSUPPORTED_FORMAT}: "*} ]]; then + hook_com=() + # User probably needs to install a newer svn, but we're not sure, so point + # the user to svn's error message. + VCS_INFO_formats '' '?' '?' '' '' '?' 'svn error' return $? else return 1 @@ -60,13 +68,7 @@ else fi rrn=${svnbase:t} -zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat svnbranch || svnbranch="%b:%r" -hook_com=( branch "${svninfo[URL]##*/}" revision "${cwdinfo[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_set-branch-format "${svninfo[URL]##*/}" "${cwdinfo[Revision]}" && + svnbranch="${REPLY}" VCS_INFO_formats '' "${svnbranch}" "${svnbase}" '' '' "${cwdinfo[Revision]}" '' return 0 diff --git a/Functions/VCS_Info/VCS_INFO_bydir_detect b/Functions/VCS_Info/VCS_INFO_bydir_detect index 29b261413..89b4d6503 100644 --- a/Functions/VCS_Info/VCS_INFO_bydir_detect +++ b/Functions/VCS_Info/VCS_INFO_bydir_detect @@ -36,4 +36,6 @@ done [[ ${basedir} == "/" ]] && return 1 vcs_comm[basedir]=${basedir} +# TODO: Would the following be correct? --- +# rrn=${vcs_comm[basedir]:t} return 0 diff --git a/Functions/VCS_Info/VCS_INFO_patch2subject b/Functions/VCS_Info/VCS_INFO_patch2subject index a467edcdb..5aa9efd23 100644 --- a/Functions/VCS_Info/VCS_INFO_patch2subject +++ b/Functions/VCS_Info/VCS_INFO_patch2subject @@ -1,3 +1,5 @@ +## vim:ft=zsh +# # This function takes as an argument a filename of a patch and sets $REPLY to # a single-line "subject", or unsets it if no subject could be extracted. { diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index fef85964a..ce5b41f24 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -92,7 +92,7 @@ function VCS_INFO_quilt-patch2subject() { emulate -L zsh setopt extendedglob local mode="$1" - local patches pc tmp qstring root + local patches pc qstring root local -i ret local context local -a applied unapplied applied_string unapplied_string quiltcommand quilt_env @@ -113,9 +113,12 @@ function VCS_INFO_quilt-patch2subject() { ;; esac - VCS_INFO_quilt-dirfind .pc .version - ret=$? pc=$REPLY - if (( ret == 0 )); then + # Look for the patches directory. + # + # 1. Check if there's a .pc/.version file in a parent dir. If so, use the + # patches dir from the corresponding .pc/.quilt_patches. + if VCS_INFO_quilt-dirfind .pc .version; then + pc=$REPLY [[ ${quiltmode} == 'standalone' ]] && root=${pc} pc=${pc}/.pc if [[ -e ${pc}/applied-patches ]]; then @@ -128,33 +131,35 @@ function VCS_INFO_quilt-patch2subject() { fi patches=$(<$pc/.quilt_patches) patches=`builtin cd -q "${pc:h}" && print -r - ${patches:P}` + # 2. Else, locate a patches dir using the style settings. + else + zstyle -s "${context}" quilt-patch-dir patches || patches="${QUILT_PATCHES}" + : ${patches:="patches"} + if [[ "${patches}" != /* ]]; then + if VCS_INFO_quilt-dirfind "${patches}"; then + patches=$REPLY/$patches + else + return $? + fi + else + [[ -d ${patches} ]] || return 1 + fi + quilt_env+=(QUILT_PATCHES="$patches") fi + # At this point, $patches is set and points to an existing directory. + 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' - quilt_env=(env) - if [ -z "$patches" ]; then - zstyle -s "${context}" quilt-patch-dir patches || patches="${QUILT_PATCHES}" - if [[ "${patches}" != /* ]]; then - tmp=${patches:-patches} - VCS_INFO_quilt-dirfind "${tmp}" - ret=$? patches=$REPLY - (( ret )) && return ${ret} - patches=${patches}/${tmp} - else - [[ -d ${patches} ]] || return 1 - fi - quilt_env+=(QUILT_PATCHES="$patches") - fi - unapplied=( ${(f)"$(${quilt_env[@]} $quiltcommand --quiltrc /dev/null unapplied 2> /dev/null)"} ) + unapplied=( ${(f)"$(if (( $+quilt_env[1] )); then export ${quilt_env[@]}; fi + $quiltcommand --quiltrc /dev/null unapplied 2> /dev/null)"} ) unapplied=( ${unapplied:#} ) else unapplied=() fi - if [[ -n $patches ]]; then - () { + { local i for ((i=1; i<=$#applied; i++)); do if VCS_INFO_quilt-patch2subject "$patches/$applied[$i]" && (( $+REPLY )) @@ -172,13 +177,17 @@ function VCS_INFO_quilt-patch2subject() { unapplied[$i]+=" ?" fi done - } - fi + } + + typeset -A quilt_extra_info=( + quilt-patches-dir ${patches} + ${pc:+"quilt-pc-dir"} $pc + ) VCS_INFO_set-patch-format 'applied' 'applied_string' \ 'unapplied' 'unapplied_string' \ ${context} qstring \ - '' '' + quilt_extra_info '' quilt_extra_info qstring=$REPLY case ${mode} in diff --git a/Functions/VCS_Info/VCS_INFO_set-branch-format b/Functions/VCS_Info/VCS_INFO_set-branch-format new file mode 100644 index 000000000..cbab60e29 --- /dev/null +++ b/Functions/VCS_Info/VCS_INFO_set-branch-format @@ -0,0 +1,24 @@ +## vim:ft=zsh +# +# A function for calling the branch-format hook +# +# Return the value to use in REPLY +# +# Parameters: +readonly branch=$1 +readonly revision=$2 +# + +[[ -n $rrn ]] || return 1 +local -A hook_com +local branchformat + +zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat branchformat || branchformat="%b:%r" +hook_com=( branch "${branch}" revision "${revision}" ) +if VCS_INFO_hook 'set-branch-format' "${branchformat}"; then + zformat -f REPLY "${branchformat}" "b:${hook_com[branch]}" "r:${hook_com[revision]}" +else + REPLY=${hook_com[branch-replace]} +fi +hook_com=() +return 0 diff --git a/Functions/VCS_Info/VCS_INFO_set-patch-format b/Functions/VCS_Info/VCS_INFO_set-patch-format index 917ebf6bf..1c774a7f6 100644 --- a/Functions/VCS_Info/VCS_INFO_set-patch-format +++ b/Functions/VCS_Info/VCS_INFO_set-patch-format @@ -1,3 +1,5 @@ +## vim:ft=zsh +# # This function is the common guts of the gen-applied-string / # gen-unapplied-string / set-patch-format dance of several backends. # @@ -12,7 +14,9 @@ # $6 - name of a parameter to store a patch-format format string in # $7 - name of an assoc parameter with extra $hook_com key-value pairs for the # set-patch-format hook invocation, or '' for none -# $8 - name of an array parameter with extra arguments for the patch-format zformat call, or '' for empty +# $8 - name of a function that sets $reply to extra arguments for the patch-format zformat call, or '' for none +# $9 - name of an assoc parameter with extra $hook_com key-value pairs for the +# gen-applied-string & gen-unapplied-string hook invocations, or '' for none # # The expanded patch-format string is returned in $REPLY. # @@ -20,8 +24,10 @@ # - $hook_com is overwritten and the keys 'applied', 'applied-n', # 'unapplied', 'unapplied-n', 'all-n' are set. { + hook_com=() + local applied_needs_escaping='unknown' - local unapplied_needs_escaping='unknown' + hook_com+=( ${9:+"${(@kvP)9}"} ) if VCS_INFO_hook 'gen-applied-string' "${(@P)1}"; then if (( ${(P)#1} )); then REPLY=${(P)1[1]} @@ -35,6 +41,8 @@ : ${(P)2::=$REPLY} hook_com=() + local unapplied_needs_escaping='unknown' + hook_com+=( ${9:+"${(@kvP)9}"} ) if VCS_INFO_hook 'gen-unapplied-string' "${(@P)3}"; then REPLY=${(P)#3} unapplied_needs_escaping='yes' @@ -68,10 +76,12 @@ hook_com[unapplied]=${hook_com[unapplied]//'%'/%%} fi + reply=() + [[ -n $8 ]] && "$8" zformat -f REPLY "${(P)6}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \ "n:${hook_com[applied-n]}" "c:${hook_com[unapplied-n]}" \ "a:${hook_com[all-n]}" \ - ${8:+"${(@P)8}"} + "${reply[@]}" else unset applied_needs_escaping unapplied_needs_escaping # the hook deals with escaping REPLY=${hook_com[patch-replace]} diff --git a/Functions/VCS_Info/test-repo-git-rebase-apply b/Functions/VCS_Info/test-repo-git-rebase-apply new file mode 100755 index 000000000..ce49690cd --- /dev/null +++ b/Functions/VCS_Info/test-repo-git-rebase-apply @@ -0,0 +1,59 @@ +#!/usr/local/bin/zsh -f +# +# This script creates a test repository for testing the git backend's behaviour during rebase-apply operations. +# +# It works in ./vcs-test/. +# +# Suggested zshrc settings: +# +# autoload vcs_info +# precmd() { vcs_info; typeset -pm vcs\* } +# zstyle ':vcs_info:*' actionformats %m +# zstyle ':vcs_info:*' patch-format '[%n+%c=%a] [%p] [%u]' +# zstyle :vcs_info:\*gen-applied-string\* hooks f1 +# +vi-f1() { typeset -p argv hook_com } +# zstyle :vcs_info:\*gen-unapplied-string\* hooks f2 +# +vi-f2() { typeset -p argv hook_com } +# zstyle :vcs_info:\* get-unapplied true +# +mkdir "vcs-test" +cd "vcs-test" +git init + +append_lines() { for 1; do echo line from r$1 >> iota && git commit -am "r$1: Append a line"; done } + +echo "This is the file 'iota'." > iota +git add iota +git commit -m "r1: Add iota" +git tag rebase_onto_this HEAD + +# Make another change to iota +append_lines 2 +git tag rebase_from_this HEAD + +# Make non-conflicting changes +for 1 in 3 4 5 6; do + touch kappa$1 + git add kappa$1 + git commit -m "r${1}: non-conflicting change" +done + +# Make more changes to iota +append_lines 7 8 9 + +# Specify a rebase that would create the history [1,3,4,5,6,7,8,9]. +# This will conflict because r7 depends on r2 which is not included. +git checkout -b myref +case $0:P in + (*/test-repo-git-rebase-apply) + git rebase --onto=rebase_onto_this rebase_from_this myref + ;; + (*/test-repo-git-rebase-merge) + git -c core.editor=true rebase -i --onto=rebase_onto_this rebase_from_this myref + ;; + (*) + echo >&2 "$0: unrecognized basename" + ;; +esac + + diff --git a/Functions/VCS_Info/test-repo-git-rebase-merge b/Functions/VCS_Info/test-repo-git-rebase-merge new file mode 100755 index 000000000..ce49690cd --- /dev/null +++ b/Functions/VCS_Info/test-repo-git-rebase-merge @@ -0,0 +1,59 @@ +#!/usr/local/bin/zsh -f +# +# This script creates a test repository for testing the git backend's behaviour during rebase-apply operations. +# +# It works in ./vcs-test/. +# +# Suggested zshrc settings: +# +# autoload vcs_info +# precmd() { vcs_info; typeset -pm vcs\* } +# zstyle ':vcs_info:*' actionformats %m +# zstyle ':vcs_info:*' patch-format '[%n+%c=%a] [%p] [%u]' +# zstyle :vcs_info:\*gen-applied-string\* hooks f1 +# +vi-f1() { typeset -p argv hook_com } +# zstyle :vcs_info:\*gen-unapplied-string\* hooks f2 +# +vi-f2() { typeset -p argv hook_com } +# zstyle :vcs_info:\* get-unapplied true +# +mkdir "vcs-test" +cd "vcs-test" +git init + +append_lines() { for 1; do echo line from r$1 >> iota && git commit -am "r$1: Append a line"; done } + +echo "This is the file 'iota'." > iota +git add iota +git commit -m "r1: Add iota" +git tag rebase_onto_this HEAD + +# Make another change to iota +append_lines 2 +git tag rebase_from_this HEAD + +# Make non-conflicting changes +for 1 in 3 4 5 6; do + touch kappa$1 + git add kappa$1 + git commit -m "r${1}: non-conflicting change" +done + +# Make more changes to iota +append_lines 7 8 9 + +# Specify a rebase that would create the history [1,3,4,5,6,7,8,9]. +# This will conflict because r7 depends on r2 which is not included. +git checkout -b myref +case $0:P in + (*/test-repo-git-rebase-apply) + git rebase --onto=rebase_onto_this rebase_from_this myref + ;; + (*/test-repo-git-rebase-merge) + git -c core.editor=true rebase -i --onto=rebase_onto_this rebase_from_this myref + ;; + (*) + echo >&2 "$0: unrecognized basename" + ;; +esac + + diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index 9f48bee75..786b61918 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -22,6 +22,7 @@ static_functions=( 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 |