1## vim:ft=zsh
2## git support by: Frank Terbeck <ft@bewatermyfriend.org>
3## Distributed under the same BSD-ish license as zsh itself.
4
5setopt localoptions extendedglob NO_shwordsplit
6local gitdir gitbase gitbranch gitaction gitunstaged gitstaged gitsha1
7local stgitpatch stgitunapplied
8local -A hook_com
9
10VCS_INFO_git_getaction () {
11    local gitdir=$1
12    local tmp
13
14    for tmp in "${gitdir}/rebase-apply" \
15               "${gitdir}/rebase"       \
16               "${gitdir}/../.dotest" ; do
17        if [[ -d ${tmp} ]] ; then
18            if   [[ -f "${tmp}/rebasing" ]] ; then
19                gitaction="rebase"
20            elif [[ -f "${tmp}/applying" ]] ; then
21                gitaction="am"
22            else
23                gitaction="am/rebase"
24            fi
25            return 0
26        fi
27    done
28
29    for tmp in "${gitdir}/rebase-merge/interactive" \
30               "${gitdir}/.dotest-merge/interactive" ; do
31        if [[ -f "${tmp}" ]] ; then
32            gitaction="rebase-i"
33            return 0
34        fi
35    done
36
37    for tmp in "${gitdir}/rebase-merge" \
38               "${gitdir}/.dotest-merge" ; do
39        if [[ -d "${tmp}" ]] ; then
40            gitaction="rebase-m"
41            return 0
42        fi
43    done
44
45    if [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
46        gitaction="merge"
47        return 0
48    fi
49
50    if [[ -f "${gitdir}/BISECT_LOG" ]] ; then
51        gitaction="bisect"
52        return 0
53    fi
54
55    if [[ -f "${gitdir}/CHERRY_PICK_HEAD" ]] ; then
56        if [[ -d "${gitdir}/sequencer" ]] ; then
57            gitaction=cherry-seq
58        else
59            gitaction=cherry
60        fi
61        return 0
62    fi
63
64    return 1
65}
66
67VCS_INFO_git_getbranch () {
68    local gitdir=$1 tmp actiondir
69    local gitsymref="${vcs_comm[cmd]} symbolic-ref HEAD"
70
71    actiondir=''
72    for tmp in "${gitdir}/rebase-apply" \
73               "${gitdir}/rebase"       \
74               "${gitdir}/../.dotest"; do
75        if [[ -d ${tmp} ]]; then
76            actiondir=${tmp}
77            break
78        fi
79    done
80    if [[ -n ${actiondir} ]]; then
81        gitbranch="$(${(z)gitsymref} 2> /dev/null)"
82        [[ -z ${gitbranch} ]] && [[ -r ${actiondir}/head-name ]] \
83            && gitbranch="$(< ${actiondir}/head-name)"
84
85    elif [[ -f "${gitdir}/MERGE_HEAD" ]] ; then
86        gitbranch="$(${(z)gitsymref} 2> /dev/null)"
87        [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/MERGE_HEAD)"
88
89    elif [[ -d "${gitdir}/rebase-merge" ]] ; then
90        gitbranch="$(< ${gitdir}/rebase-merge/head-name)"
91
92    elif [[ -d "${gitdir}/.dotest-merge" ]] ; then
93        gitbranch="$(< ${gitdir}/.dotest-merge/head-name)"
94
95    else
96        gitbranch="$(${(z)gitsymref} 2> /dev/null)"
97
98        if [[ $? -ne 0 ]] ; then
99            gitbranch="refs/tags/$(${vcs_comm[cmd]} describe --exact-match HEAD 2>/dev/null)"
100
101            if [[ $? -ne 0 ]] ; then
102                gitbranch="${${"$(< $gitdir/HEAD)"}[1,7]}..."
103            fi
104        fi
105    fi
106
107    return 0
108}
109
110gitdir=${vcs_comm[gitdir]}
111VCS_INFO_git_getbranch ${gitdir}
112if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then
113    gitsha1=$(${vcs_comm[cmd]} rev-parse --quiet --verify HEAD)
114else
115    gitsha1=''
116fi
117gitbranch="${gitbranch##refs/[^/]##/}"
118
119if [[ -z ${gitdir} ]] || [[ -z ${gitbranch} ]] ; then
120    return 1
121fi
122
123if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" "check-for-changes" && \
124   [[ "$(${vcs_comm[cmd]} rev-parse --is-inside-git-dir 2> /dev/null)" != 'true' ]] && \
125   ${vcs_comm[cmd]} rev-parse --quiet --verify HEAD &> /dev/null ; then
126    # Default: off - these are potentially expensive on big repositories
127    ${vcs_comm[cmd]} diff --no-ext-diff --ignore-submodules --quiet --exit-code ||
128        gitunstaged=1
129    ${vcs_comm[cmd]} diff-index --cached --quiet --ignore-submodules HEAD 2> /dev/null
130    (( $? && $? != 128 )) && gitstaged=1
131fi
132
133VCS_INFO_adjust
134VCS_INFO_git_getaction ${gitdir}
135gitbase=$( ${vcs_comm[cmd]} rev-parse --show-toplevel )
136rrn=${gitbase:t}
137
138local patchdir=${gitdir}/patches/${gitbranch}
139if [[ -d $patchdir ]] && [[ -f $patchdir/applied ]] \
140   && [[ -f $patchdir/unapplied ]]
141then
142    local -a stgit_applied stgit_unapplied stgit_all
143
144    stgit_applied=(${(f)"$(< "${patchdir}/applied")"})
145    stgit_applied=( ${(Oa)stgit_applied} )
146    stgit_unapplied=(${(f)"$(< "${patchdir}/unapplied")"})
147    stgit_unapplied=( ${(oa)stgit_unapplied} )
148    stgit_all=( ${(Oa)stgit_applied} ${stgit_unapplied} )
149
150    if VCS_INFO_hook 'gen-applied-string' "${stgit_applied[@]}"; then
151        if (( ${#stgit_applied} )); then
152            stgitpatch=${stgit_applied[1]}
153        else
154            stgitpatch=""
155        fi
156    else
157        stgitpatch=${hook_com[patch-string]}
158    fi
159    hook_com=()
160    if VCS_INFO_hook 'gen-unapplied-string' "${stgit_unapplied[@]}"; then
161        stgitunapplied=${#stgit_unapplied}
162    else
163        stgitunapplied=${hook_com[unapplied-string]}
164    fi
165
166    if (( ${#stgit_applied} )); then
167        zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" patch-format stgitmsg || stgitmsg="%p (%n applied)"
168    else
169        zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" nopatch-format stgitmsg || stgitmsg="no patch applied"
170    fi
171    hook_com=( applied "${stgitpatch}"     unapplied "${stgitunapplied}"
172               applied-n ${#stgit_applied} unapplied-n ${#stgit_unapplied} all-n ${#stgit_all} )
173    if VCS_INFO_hook 'set-patch-format' "${stgitmsg}"; then
174        zformat -f stgitmsg "${stgitmsg}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
175                                          "n:${#stgit_applied}" "c:${#stgit_unapplied}" "a:${#stgit_all}"
176    else
177        stgitmsg=${hook_com[patch-replace]}
178    fi
179    hook_com=()
180else
181    stgitmsg=''
182fi
183
184backend_misc[patches]="${stgitmsg}"
185VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}" "${gitstaged}" "${gitunstaged}" "${gitsha1}" "${stgitmsg}"
186return 0
187