-
Notifications
You must be signed in to change notification settings - Fork 0
/
yadm-prompt.plugin.zsh
273 lines (238 loc) · 9.71 KB
/
yadm-prompt.plugin.zsh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
function __yadm_prompt_yadm() {
YADM_OPTIONAL_LOCKS=0 command yadm "$@"
}
function yadm_prompt_info() {
# If we are on a folder not tracked by yadm, get out.
# Otherwise, check for hide-info at global and local repository level
if ! __yadm_prompt_yadm rev-parse --git-dir &> /dev/null \
|| [[ "$(__yadm_prompt_yadm config --get oh-my-zsh.hide-info 2>/dev/null)" == 1 ]]; then
return 0
fi
local ref
ref=$(__yadm_prompt_yadm symbolic-ref --short HEAD 2> /dev/null) \
|| ref=$(__yadm_prompt_yadm rev-parse --short HEAD 2> /dev/null) \
|| return 0
# Use global ZSH_THEME_GIT_SHOW_UPSTREAM=1 for including upstream remote info
local upstream
if (( ${+ZSH_THEME_GIT_SHOW_UPSTREAM} )); then
upstream=$(__yadm_prompt_yadm rev-parse --abbrev-ref --symbolic-full-name "@{upstream}" 2>/dev/null) \
&& upstream=" -> ${upstream}"
fi
echo "%{$magenta_bold%}yadm: ${ZSH_THEME_GIT_PROMPT_PREFIX}${ref}${upstream}$(parse_yadm_dirty)${ZSH_THEME_GIT_PROMPT_SUFFIX}"
}
# Checks if working tree is dirty
function parse_yadm_dirty() {
local STATUS
local -a FLAGS
FLAGS=('--porcelain')
if [[ "$(__yadm_prompt_yadm config --get oh-my-zsh.hide-dirty)" != "1" ]]; then
if [[ "${DISABLE_UNTRACKED_FILES_DIRTY:-}" == "true" ]]; then
FLAGS+='--untracked-files=no'
fi
case "${YADM_STATUS_IGNORE_SUBMODULES:-}" in
yadm)
# let yadm decide (this respects per-repo config in .yadmmodules)
;;
*)
# if unset: ignore dirty submodules
# other values are passed to --ignore-submodules
FLAGS+="--ignore-submodules=${YADM_STATUS_IGNORE_SUBMODULES:-dirty}"
;;
esac
STATUS=$(__yadm_prompt_yadm status ${FLAGS} 2> /dev/null | tail -n1)
fi
if [[ -n $STATUS ]]; then
echo "$ZSH_THEME_GIT_PROMPT_DIRTY"
else
echo "$ZSH_THEME_GIT_PROMPT_CLEAN"
fi
}
# Gets the difference between the local and remote branches
function yadm_remote_status() {
local remote ahead behind yadm_remote_status yadm_remote_status_detailed
remote=${$(__yadm_prompt_yadm rev-parse --verify ${hook_com[branch]}@{upstream} --symbolic-full-name 2>/dev/null)/refs\/remotes\/}
if [[ -n ${remote} ]]; then
ahead=$(__yadm_prompt_yadm rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l)
behind=$(__yadm_prompt_yadm rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l)
if [[ $ahead -eq 0 ]] && [[ $behind -eq 0 ]]; then
yadm_remote_status="$ZSH_THEME_GIT_PROMPT_EQUAL_REMOTE"
elif [[ $ahead -gt 0 ]] && [[ $behind -eq 0 ]]; then
yadm_remote_status="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE"
yadm_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}"
elif [[ $behind -gt 0 ]] && [[ $ahead -eq 0 ]]; then
yadm_remote_status="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE"
yadm_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}"
elif [[ $ahead -gt 0 ]] && [[ $behind -gt 0 ]]; then
yadm_remote_status="$ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE"
yadm_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}"
fi
if [[ -n $ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_DETAILED ]]; then
yadm_remote_status="$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_PREFIX$remote$yadm_remote_status_detailed$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_SUFFIX"
fi
echo $yadm_remote_status
fi
}
# Outputs the name of the current branch
# Usage example: yadm pull origin $(yadm_current_branch)
# Using '--quiet' with 'symbolic-ref' will not cause a fatal error (128) if
# it's not a symbolic ref, but in a Git repo.
function yadm_current_branch() {
local ref
ref=$(__yadm_prompt_yadm symbolic-ref --quiet HEAD 2> /dev/null)
local ret=$?
if [[ $ret != 0 ]]; then
[[ $ret == 128 ]] && return # no yadm repo.
ref=$(__yadm_prompt_yadm rev-parse --short HEAD 2> /dev/null) || return
fi
echo ${ref#refs/heads/}
}
# Gets the number of commits ahead from remote
function yadm_commits_ahead() {
if __yadm_prompt_yadm rev-parse --yadm-dir &>/dev/null; then
local commits="$(__yadm_prompt_yadm rev-list --count @{upstream}..HEAD 2>/dev/null)"
if [[ -n "$commits" && "$commits" != 0 ]]; then
echo "$ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX$commits$ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX"
fi
fi
}
# Gets the number of commits behind remote
function yadm_commits_behind() {
if __yadm_prompt_yadm rev-parse --yadm-dir &>/dev/null; then
local commits="$(__yadm_prompt_yadm rev-list --count HEAD..@{upstream} 2>/dev/null)"
if [[ -n "$commits" && "$commits" != 0 ]]; then
echo "$ZSH_THEME_GIT_COMMITS_BEHIND_PREFIX$commits$ZSH_THEME_GIT_COMMITS_BEHIND_SUFFIX"
fi
fi
}
# Outputs if current branch is ahead of remote
function yadm_prompt_ahead() {
if [[ -n "$(__yadm_prompt_yadm rev-list origin/$(yadm_current_branch)..HEAD 2> /dev/null)" ]]; then
echo "$ZSH_THEME_GIT_PROMPT_AHEAD"
fi
}
# Outputs if current branch is behind remote
function yadm_prompt_behind() {
if [[ -n "$(__yadm_prompt_yadm rev-list HEAD..origin/$(yadm_current_branch) 2> /dev/null)" ]]; then
echo "$ZSH_THEME_GIT_PROMPT_BEHIND"
fi
}
# Outputs if current branch exists on remote or not
function yadm_prompt_remote() {
if [[ -n "$(__yadm_prompt_yadm show-ref origin/$(yadm_current_branch) 2> /dev/null)" ]]; then
echo "$ZSH_THEME_GIT_PROMPT_REMOTE_EXISTS"
else
echo "$ZSH_THEME_GIT_PROMPT_REMOTE_MISSING"
fi
}
# Formats prompt string for current yadm commit short SHA
function yadm_prompt_short_sha() {
local SHA
SHA=$(__yadm_prompt_yadm rev-parse --short HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER"
}
# Formats prompt string for current yadm commit long SHA
function yadm_prompt_long_sha() {
local SHA
SHA=$(__yadm_prompt_yadm rev-parse HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER"
}
function yadm_prompt_status() {
[[ "$(__yadm_prompt_yadm config --get oh-my-zsh.hide-status 2>/dev/null)" = 1 ]] && return
# Maps a yadm status prefix to an internal constant
# This cannot use the prompt constants, as they may be empty
local -A prefix_constant_map
prefix_constant_map=(
'\?\? ' 'UNTRACKED'
'A ' 'ADDED'
'M ' 'ADDED'
'MM ' 'ADDED'
' M ' 'MODIFIED'
'AM ' 'MODIFIED'
' T ' 'MODIFIED'
'R ' 'RENAMED'
' D ' 'DELETED'
'D ' 'DELETED'
'UU ' 'UNMERGED'
'ahead' 'AHEAD'
'behind' 'BEHIND'
'diverged' 'DIVERGED'
'stashed' 'STASHED'
)
# Maps the internal constant to the prompt theme
local -A constant_prompt_map
constant_prompt_map=(
'UNTRACKED' "$ZSH_THEME_GIT_PROMPT_UNTRACKED"
'ADDED' "$ZSH_THEME_GIT_PROMPT_ADDED"
'MODIFIED' "$ZSH_THEME_GIT_PROMPT_MODIFIED"
'RENAMED' "$ZSH_THEME_GIT_PROMPT_RENAMED"
'DELETED' "$ZSH_THEME_GIT_PROMPT_DELETED"
'UNMERGED' "$ZSH_THEME_GIT_PROMPT_UNMERGED"
'AHEAD' "$ZSH_THEME_GIT_PROMPT_AHEAD"
'BEHIND' "$ZSH_THEME_GIT_PROMPT_BEHIND"
'DIVERGED' "$ZSH_THEME_GIT_PROMPT_DIVERGED"
'STASHED' "$ZSH_THEME_GIT_PROMPT_STASHED"
)
# The order that the prompt displays should be added to the prompt
local status_constants
status_constants=(
UNTRACKED ADDED MODIFIED RENAMED DELETED
STASHED UNMERGED AHEAD BEHIND DIVERGED
)
local status_text="$(__yadm_prompt_yadm status --porcelain -b 2> /dev/null)"
# Don't continue on a catastrophic failure
if [[ $? -eq 128 ]]; then
return 1
fi
# A lookup table of each yadm status encountered
local -A statuses_seen
if __yadm_prompt_yadm rev-parse --verify refs/stash &>/dev/null; then
statuses_seen[STASHED]=1
fi
local status_lines
status_lines=("${(@f)${status_text}}")
# If the tracking line exists, get and parse it
if [[ "$status_lines[1]" =~ "^## [^ ]+ \[(.*)\]" ]]; then
local branch_statuses
branch_statuses=("${(@s/,/)match}")
for branch_status in $branch_statuses; do
if [[ ! $branch_status =~ "(behind|diverged|ahead) ([0-9]+)?" ]]; then
continue
fi
local last_parsed_status=$prefix_constant_map[$match[1]]
statuses_seen[$last_parsed_status]=$match[2]
done
fi
# For each status prefix, do a regex comparison
for status_prefix in ${(k)prefix_constant_map}; do
local status_constant="${prefix_constant_map[$status_prefix]}"
local status_regex=$'(^|\n)'"$status_prefix"
if [[ "$status_text" =~ $status_regex ]]; then
statuses_seen[$status_constant]=1
fi
done
# Display the seen statuses in the order specified
local status_prompt
for status_constant in $status_constants; do
if (( ${+statuses_seen[$status_constant]} )); then
local next_display=$constant_prompt_map[$status_constant]
status_prompt="$next_display$status_prompt"
fi
done
echo $status_prompt
}
# Outputs the name of the current user
# Usage example: $(yadm_current_user_name)
function yadm_current_user_name() {
__yadm_prompt_yadm config user.name 2>/dev/null
}
# Outputs the email of the current user
# Usage example: $(yadm_current_user_email)
function yadm_current_user_email() {
__yadm_prompt_yadm config user.email 2>/dev/null
}
# Output the name of the root directory of the yadm repository
# Usage example: $(yadm_repo_name)
function yadm_repo_name() {
local repo_path
if repo_path="$(__yadm_prompt_yadm rev-parse --show-toplevel 2>/dev/null)" && [[ -n "$repo_path" ]]; then
echo ${repo_path:t}
fi
}