Commit 3c16e1f03b03b5b0362befb289094623ed17b414

Authored by Shrikant Sharat
1 parent 96f9ef5473

Avoid git cd-less magic.

It appears that the whole git magic that's going on to avoid starting a subshell
is causing problems on certain slightly old versions of git. Now switched to
`cd`-ing to the clone to avoid any trouble in this regard.

Showing 1 changed file with 3 additions and 5 deletions Inline Diff

1 #!/bin/zsh 1 #!/bin/zsh
2 2
3 # Each line in this string has the following entries separated by a space 3 # Each line in this string has the following entries separated by a space
4 # character. 4 # character.
5 # <repo-url>, <plugin-location>, <bundle-type>, <has-local-clone> 5 # <repo-url>, <plugin-location>, <bundle-type>, <has-local-clone>
6 # FIXME: Is not kept local by zsh! 6 # FIXME: Is not kept local by zsh!
7 local _ANTIGEN_BUNDLE_RECORD="" 7 local _ANTIGEN_BUNDLE_RECORD=""
8 local _ANTIGEN_INSTALL_DIR="$(dirname $0)" 8 local _ANTIGEN_INSTALL_DIR="$(dirname $0)"
9 9
10 # Syntaxes 10 # Syntaxes
11 # antigen-bundle <url> [<loc>=/] 11 # antigen-bundle <url> [<loc>=/]
12 # Keyword only arguments: 12 # Keyword only arguments:
13 # branch - The branch of the repo to use for this bundle. 13 # branch - The branch of the repo to use for this bundle.
14 antigen-bundle () { 14 antigen-bundle () {
15 15
16 # Bundle spec arguments' default values. 16 # Bundle spec arguments' default values.
17 local url="$ANTIGEN_DEFAULT_REPO_URL" 17 local url="$ANTIGEN_DEFAULT_REPO_URL"
18 local loc=/ 18 local loc=/
19 local branch= 19 local branch=
20 local no_local_clone=false 20 local no_local_clone=false
21 local btype=plugin 21 local btype=plugin
22 22
23 # Parse the given arguments. (Will overwrite the above values). 23 # Parse the given arguments. (Will overwrite the above values).
24 eval "$(-antigen-parse-args \ 24 eval "$(-antigen-parse-args \
25 'url?, loc? ; branch:?, no-local-clone?, btype:?' \ 25 'url?, loc? ; branch:?, no-local-clone?, btype:?' \
26 "$@")" 26 "$@")"
27 27
28 # Check if url is just the plugin name. Super short syntax. 28 # Check if url is just the plugin name. Super short syntax.
29 if [[ "$url" != */* ]]; then 29 if [[ "$url" != */* ]]; then
30 loc="plugins/$url" 30 loc="plugins/$url"
31 url="$ANTIGEN_DEFAULT_REPO_URL" 31 url="$ANTIGEN_DEFAULT_REPO_URL"
32 fi 32 fi
33 33
34 # Resolve the url. 34 # Resolve the url.
35 url="$(-antigen-resolve-bundle-url "$url")" 35 url="$(-antigen-resolve-bundle-url "$url")"
36 36
37 # Add the branch information to the url. 37 # Add the branch information to the url.
38 if [[ ! -z $branch ]]; then 38 if [[ ! -z $branch ]]; then
39 url="$url|$branch" 39 url="$url|$branch"
40 fi 40 fi
41 41
42 # The `make_local_clone` variable better represents whether there should be 42 # The `make_local_clone` variable better represents whether there should be
43 # a local clone made. For cloning to be avoided, firstly, the `$url` should 43 # a local clone made. For cloning to be avoided, firstly, the `$url` should
44 # be an absolute local path and `$branch` should be empty. In addition to 44 # be an absolute local path and `$branch` should be empty. In addition to
45 # these two conditions, either the `--no-local-clone` option should be 45 # these two conditions, either the `--no-local-clone` option should be
46 # given, or `$url` should not a git repo. 46 # given, or `$url` should not a git repo.
47 local make_local_clone=true 47 local make_local_clone=true
48 if [[ $url == /* && -z $branch && 48 if [[ $url == /* && -z $branch &&
49 ( $no_local_clone == true || ! -d $url/.git ) ]]; then 49 ( $no_local_clone == true || ! -d $url/.git ) ]]; then
50 make_local_clone=false 50 make_local_clone=false
51 fi 51 fi
52 52
53 # Add the theme extension to `loc`, if this is a theme. 53 # Add the theme extension to `loc`, if this is a theme.
54 if [[ $btype == theme && $loc != *.zsh-theme ]]; then 54 if [[ $btype == theme && $loc != *.zsh-theme ]]; then
55 loc="$loc.zsh-theme" 55 loc="$loc.zsh-theme"
56 fi 56 fi
57 57
58 # Add it to the record. 58 # Add it to the record.
59 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD\n$url $loc $btype" 59 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD\n$url $loc $btype"
60 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD $make_local_clone" 60 _ANTIGEN_BUNDLE_RECORD="$_ANTIGEN_BUNDLE_RECORD $make_local_clone"
61 61
62 # Ensure a clone exists for this repo, if needed. 62 # Ensure a clone exists for this repo, if needed.
63 if $make_local_clone; then 63 if $make_local_clone; then
64 -antigen-ensure-repo "$url" 64 -antigen-ensure-repo "$url"
65 fi 65 fi
66 66
67 # Load the plugin. 67 # Load the plugin.
68 -antigen-load "$url" "$loc" "$btype" "$make_local_clone" 68 -antigen-load "$url" "$loc" "$btype" "$make_local_clone"
69 69
70 } 70 }
71 71
72 -antigen-resolve-bundle-url () { 72 -antigen-resolve-bundle-url () {
73 # Given an acceptable short/full form of a bundle's repo url, this function 73 # Given an acceptable short/full form of a bundle's repo url, this function
74 # echoes the full form of the repo's clone url. 74 # echoes the full form of the repo's clone url.
75 75
76 local url="$1" 76 local url="$1"
77 77
78 # Expand short github url syntax: `username/reponame`. 78 # Expand short github url syntax: `username/reponame`.
79 if [[ $url != git://* && 79 if [[ $url != git://* &&
80 $url != https://* && 80 $url != https://* &&
81 $url != /* && 81 $url != /* &&
82 $url != git@github.com:*/* 82 $url != git@github.com:*/*
83 ]]; then 83 ]]; then
84 url="https://github.com/${url%.git}.git" 84 url="https://github.com/${url%.git}.git"
85 fi 85 fi
86 86
87 echo "$url" 87 echo "$url"
88 } 88 }
89 89
90 antigen-bundles () { 90 antigen-bundles () {
91 # Bulk add many bundles at one go. Empty lines and lines starting with a `#` 91 # Bulk add many bundles at one go. Empty lines and lines starting with a `#`
92 # are ignored. Everything else is given to `antigen-bundle` as is, no 92 # are ignored. Everything else is given to `antigen-bundle` as is, no
93 # quoting rules applied. 93 # quoting rules applied.
94 94
95 local line 95 local line
96 96
97 grep -v '^\s*$\|^#' | while read line; do 97 grep -v '^\s*$\|^#' | while read line; do
98 # Using `eval` so that we can use the shell-style quoting in each line 98 # Using `eval` so that we can use the shell-style quoting in each line
99 # piped to `antigen-bundles`. 99 # piped to `antigen-bundles`.
100 eval "antigen-bundle $line" 100 eval "antigen-bundle $line"
101 done 101 done
102 } 102 }
103 103
104 antigen-update () { 104 antigen-update () {
105 # Update your bundles, i.e., `git pull` in all the plugin repos. 105 # Update your bundles, i.e., `git pull` in all the plugin repos.
106 106
107 date > $ADOTDIR/revert-info 107 date > $ADOTDIR/revert-info
108 108
109 -antigen-echo-record | 109 -antigen-echo-record |
110 awk '$4 == "true" {print $1}' | 110 awk '$4 == "true" {print $1}' |
111 sort -u | 111 sort -u |
112 while read url; do 112 while read url; do
113 echo "**** Pulling $url" 113 echo "**** Pulling $url"
114 114
115 local clone_dir="$(-antigen-get-clone-dir "$url")" 115 local clone_dir="$(-antigen-get-clone-dir "$url")"
116 if [[ -d "$clone_dir" ]]; then 116 if [[ -d "$clone_dir" ]]; then
117 (echo -n "$clone_dir:" 117 (echo -n "$clone_dir:"
118 cd "$clone_dir" 118 cd "$clone_dir"
119 git rev-parse HEAD) >> $ADOTDIR/revert-info 119 git rev-parse HEAD) >> $ADOTDIR/revert-info
120 fi 120 fi
121 121
122 -antigen-ensure-repo "$url" --update --verbose 122 -antigen-ensure-repo "$url" --update --verbose
123 123
124 echo 124 echo
125 done 125 done
126 } 126 }
127 127
128 antigen-revert () { 128 antigen-revert () {
129 if ! [[ -f $ADOTDIR/revert-info ]]; then 129 if ! [[ -f $ADOTDIR/revert-info ]]; then
130 echo 'No revert information available. Cannot revert.' >&2 130 echo 'No revert information available. Cannot revert.' >&2
131 fi 131 fi
132 132
133 cat $ADOTDIR/revert-info | sed '1!p' | while read line; do 133 cat $ADOTDIR/revert-info | sed '1!p' | while read line; do
134 dir="$(echo "$line" | cut -d: -f1)" 134 dir="$(echo "$line" | cut -d: -f1)"
135 git --git-dir="$dir/.git" --work-tree="$dir" \ 135 git --git-dir="$dir/.git" --work-tree="$dir" \
136 checkout "$(echo "$line" | cut -d: -f2)" 2> /dev/null 136 checkout "$(echo "$line" | cut -d: -f2)" 2> /dev/null
137 done 137 done
138 138
139 echo "Reverted to state before running -update on $( 139 echo "Reverted to state before running -update on $(
140 cat $ADOTDIR/revert-info | sed -n 1p)." 140 cat $ADOTDIR/revert-info | sed -n 1p)."
141 } 141 }
142 142
143 -antigen-get-clone-dir () { 143 -antigen-get-clone-dir () {
144 # Takes a repo url and gives out the path that this url needs to be cloned 144 # Takes a repo url and gives out the path that this url needs to be cloned
145 # to. Doesn't actually clone anything. 145 # to. Doesn't actually clone anything.
146 echo -n $ADOTDIR/repos/ 146 echo -n $ADOTDIR/repos/
147 147
148 if [[ "$1" == "https://github.com/sorin-ionescu/prezto.git" ]]; then 148 if [[ "$1" == "https://github.com/sorin-ionescu/prezto.git" ]]; then
149 # Prezto's directory *has* to be `.zprezto`. 149 # Prezto's directory *has* to be `.zprezto`.
150 echo .zprezto 150 echo .zprezto
151 151
152 else 152 else
153 echo "$1" | sed \ 153 echo "$1" | sed \
154 -e 's./.-SLASH-.g' \ 154 -e 's./.-SLASH-.g' \
155 -e 's.:.-COLON-.g' \ 155 -e 's.:.-COLON-.g' \
156 -e 's.|.-PIPE-.g' 156 -e 's.|.-PIPE-.g'
157 157
158 fi 158 fi
159 } 159 }
160 160
161 -antigen-get-clone-url () { 161 -antigen-get-clone-url () {
162 # Takes a repo's clone dir and gives out the repo's original url that was 162 # Takes a repo's clone dir and gives out the repo's original url that was
163 # used to create the given directory path. 163 # used to create the given directory path.
164 164
165 if [[ "$1" == ".zprezto" ]]; then 165 if [[ "$1" == ".zprezto" ]]; then
166 # Prezto's (in `.zprezto`), is assumed to be from `sorin-ionescu`'s 166 # Prezto's (in `.zprezto`), is assumed to be from `sorin-ionescu`'s
167 # remote. 167 # remote.
168 echo https://github.com/sorin-ionescu/prezto.git 168 echo https://github.com/sorin-ionescu/prezto.git
169 169
170 else 170 else
171 echo "$1" | sed \ 171 echo "$1" | sed \
172 -e "s:^$ADOTDIR/repos/::" \ 172 -e "s:^$ADOTDIR/repos/::" \
173 -e 's.-SLASH-./.g' \ 173 -e 's.-SLASH-./.g' \
174 -e 's.-COLON-.:.g' \ 174 -e 's.-COLON-.:.g' \
175 -e 's.-PIPE-.|.g' 175 -e 's.-PIPE-.|.g'
176 176
177 fi 177 fi
178 } 178 }
179 179
180 -antigen-ensure-repo () { 180 -antigen-ensure-repo () {
181 181
182 # Ensure that a clone exists for the given repo url and branch. If the first 182 # Ensure that a clone exists for the given repo url and branch. If the first
183 # argument is `--update` and if a clone already exists for the given repo 183 # argument is `--update` and if a clone already exists for the given repo
184 # and branch, it is pull-ed, i.e., updated. 184 # and branch, it is pull-ed, i.e., updated.
185 185
186 # Argument defaults. 186 # Argument defaults.
187 # The url. No sane default for this, so just empty. 187 # The url. No sane default for this, so just empty.
188 local url= 188 local url=
189 # Check if we have to update. 189 # Check if we have to update.
190 local update=false 190 local update=false
191 # Verbose output. 191 # Verbose output.
192 local verbose=false 192 local verbose=false
193 193
194 eval "$(-antigen-parse-args 'url ; update?, verbose?' "$@")" 194 eval "$(-antigen-parse-args 'url ; update?, verbose?' "$@")"
195 shift $# 195 shift $#
196 196
197 # Get the clone's directory as per the given repo url and branch. 197 # Get the clone's directory as per the given repo url and branch.
198 local clone_dir="$(-antigen-get-clone-dir $url)" 198 local clone_dir="$(-antigen-get-clone-dir $url)"
199 199
200 # A temporary function wrapping the `git` command with repeated arguments. 200 # A temporary function wrapping the `git` command with repeated arguments.
201 --plugin-git () { 201 --plugin-git () {
202 eval git --no-pager \ 202 (cd "$clone_dir" && git --no-pager "$@")
203 --git-dir=$clone_dir/.git --work-tree=$clone_dir "$@"
204 } 203 }
205 204
206 # Clone if it doesn't already exist. 205 # Clone if it doesn't already exist.
207 if [[ ! -d $clone_dir ]]; then 206 if [[ ! -d $clone_dir ]]; then
208 git clone --recursive "${url%|*}" "$clone_dir" 207 git clone --recursive "${url%|*}" "$clone_dir"
209 elif $update; then 208 elif $update; then
210 # Save current revision. 209 # Save current revision.
211 local old_rev="$(--plugin-git rev-parse HEAD)" 210 local old_rev="$(--plugin-git rev-parse HEAD)"
212 # Pull changes if update requested. 211 # Pull changes if update requested.
213 (cd "$clone_dir" && git --no-pager pull) 212 --plugin-git pull
214 #--plugin-git pull
215 # Update submodules. 213 # Update submodules.
216 (cd "$clone_dir" && git submodule update --recursive) 214 --plugin-git submodule update --recursive
217 # Get the new revision. 215 # Get the new revision.
218 local new_rev="$(--plugin-git rev-parse HEAD)" 216 local new_rev="$(--plugin-git rev-parse HEAD)"
219 fi 217 fi
220 218
221 # If its a specific branch that we want, checkout that branch. 219 # If its a specific branch that we want, checkout that branch.
222 if [[ $url == *\|* ]]; then 220 if [[ $url == *\|* ]]; then
223 local current_branch=${$(--plugin-git symbolic-ref HEAD)##refs/heads/} 221 local current_branch=${$(--plugin-git symbolic-ref HEAD)##refs/heads/}
224 local requested_branch="${url#*|}" 222 local requested_branch="${url#*|}"
225 # Only do the checkout when we are not already on the branch. 223 # Only do the checkout when we are not already on the branch.
226 [[ $requested_branch != $current_branch ]] && 224 [[ $requested_branch != $current_branch ]] &&
227 --plugin-git checkout $requested_branch 225 --plugin-git checkout $requested_branch
228 fi 226 fi
229 227
230 if ! [[ -z $old_rev || $old_rev == $new_rev ]]; then 228 if ! [[ -z $old_rev || $old_rev == $new_rev ]]; then
231 echo Updated from ${old_rev:0:7} to ${new_rev:0:7}. 229 echo Updated from ${old_rev:0:7} to ${new_rev:0:7}.
232 if $verbose; then 230 if $verbose; then
233 --plugin-git log --oneline --reverse --no-merges --stat '@{1}..' 231 --plugin-git log --oneline --reverse --no-merges --stat '@{1}..'
234 fi 232 fi
235 fi 233 fi
236 234
237 # Remove the temporary git wrapper function. 235 # Remove the temporary git wrapper function.
238 unfunction -- --plugin-git 236 unfunction -- --plugin-git
239 237
240 } 238 }
241 239
242 -antigen-load () { 240 -antigen-load () {
243 241
244 local url="$1" 242 local url="$1"
245 local loc="$2" 243 local loc="$2"
246 local btype="$3" 244 local btype="$3"
247 local make_local_clone="$4" 245 local make_local_clone="$4"
248 246
249 # The full location where the plugin is located. 247 # The full location where the plugin is located.
250 local location 248 local location
251 if $make_local_clone; then 249 if $make_local_clone; then
252 location="$(-antigen-get-clone-dir "$url")/$loc" 250 location="$(-antigen-get-clone-dir "$url")/$loc"
253 else 251 else
254 location="$url" 252 location="$url"
255 fi 253 fi
256 254
257 if [[ $btype == theme ]]; then 255 if [[ $btype == theme ]]; then
258 256
259 # Of course, if its a theme, the location would point to the script 257 # Of course, if its a theme, the location would point to the script
260 # file. 258 # file.
261 source "$location" 259 source "$location"
262 260
263 else 261 else
264 262
265 # Source the plugin script. 263 # Source the plugin script.
266 # FIXME: I don't know. Looks very very ugly. Needs a better 264 # FIXME: I don't know. Looks very very ugly. Needs a better
267 # implementation once tests are ready. 265 # implementation once tests are ready.
268 local script_loc="$(ls "$location" | grep -m1 '\.plugin\.zsh$')" 266 local script_loc="$(ls "$location" | grep -m1 '\.plugin\.zsh$')"
269 267
270 if [[ -f $location/$script_loc ]]; then 268 if [[ -f $location/$script_loc ]]; then
271 # If we have a `*.plugin.zsh`, source it. 269 # If we have a `*.plugin.zsh`, source it.
272 source "$location/$script_loc" 270 source "$location/$script_loc"
273 271
274 elif [[ -f $location/init.zsh ]]; then 272 elif [[ -f $location/init.zsh ]]; then
275 # If we have a `init.zsh`, source it. 273 # If we have a `init.zsh`, source it.
276 source "$location/init.zsh" 274 source "$location/init.zsh"
277 275
278 elif ls "$location" | grep -qm1 '\.zsh$'; then 276 elif ls "$location" | grep -qm1 '\.zsh$'; then
279 # If there is no `*.plugin.zsh` file, source *all* the `*.zsh` 277 # If there is no `*.plugin.zsh` file, source *all* the `*.zsh`
280 # files. 278 # files.
281 for script ($location/*.zsh(N)) source "$script" 279 for script ($location/*.zsh(N)) source "$script"
282 280
283 elif ls "$location" | grep -qm1 '\.sh$'; then 281 elif ls "$location" | grep -qm1 '\.sh$'; then
284 # If there are no `*.zsh` files either, we look for and source any 282 # If there are no `*.zsh` files either, we look for and source any
285 # `*.sh` files instead. 283 # `*.sh` files instead.
286 for script ($location/*.sh(N)) source "$script" 284 for script ($location/*.sh(N)) source "$script"
287 285
288 fi 286 fi
289 287
290 # Add to $fpath, for completion(s). 288 # Add to $fpath, for completion(s).
291 fpath=($location $fpath) 289 fpath=($location $fpath)
292 290
293 fi 291 fi
294 292
295 } 293 }
296 294
297 antigen-selfupdate () { 295 antigen-selfupdate () {
298 # Initiate subshell 296 # Initiate subshell
299 ( 297 (
300 cd $_ANTIGEN_INSTALL_DIR 298 cd $_ANTIGEN_INSTALL_DIR
301 # Sanity checks 299 # Sanity checks
302 if [ ! -d .git ]; then 300 if [ ! -d .git ]; then
303 echo "antigen is not under git CVS" 301 echo "antigen is not under git CVS"
304 return 1 302 return 1
305 fi 303 fi
306 git pull 304 git pull
307 ) 305 )
308 } 306 }
309 307
310 antigen-cleanup () { 308 antigen-cleanup () {
311 309
312 # Cleanup unused repositories. 310 # Cleanup unused repositories.
313 311
314 local force=false 312 local force=false
315 if [[ $1 == --force ]]; then 313 if [[ $1 == --force ]]; then
316 force=true 314 force=true
317 fi 315 fi
318 316
319 if [[ ! -d "$ADOTDIR/repos" || -z "$(ls "$ADOTDIR/repos/")" ]]; then 317 if [[ ! -d "$ADOTDIR/repos" || -z "$(ls "$ADOTDIR/repos/")" ]]; then
320 echo "You don't have any bundles." 318 echo "You don't have any bundles."
321 return 0 319 return 0
322 fi 320 fi
323 321
324 # Find directores in ADOTDIR/repos, that are not in the bundles record. 322 # Find directores in ADOTDIR/repos, that are not in the bundles record.
325 local unused_clones="$(comm -13 \ 323 local unused_clones="$(comm -13 \
326 <(-antigen-echo-record | 324 <(-antigen-echo-record |
327 awk '$4 == "true" {print $1}' | 325 awk '$4 == "true" {print $1}' |
328 while read line; do 326 while read line; do
329 -antigen-get-clone-dir "$line" 327 -antigen-get-clone-dir "$line"
330 done | 328 done |
331 sort -u) \ 329 sort -u) \
332 <(ls -d "$ADOTDIR/repos/"* | sort -u))" 330 <(ls -d "$ADOTDIR/repos/"* | sort -u))"
333 331
334 if [[ -z $unused_clones ]]; then 332 if [[ -z $unused_clones ]]; then
335 echo "You don't have any unidentified bundles." 333 echo "You don't have any unidentified bundles."
336 return 0 334 return 0
337 fi 335 fi
338 336
339 echo 'You have clones for the following repos, but are not used.' 337 echo 'You have clones for the following repos, but are not used.'
340 echo "$unused_clones" | 338 echo "$unused_clones" |
341 while read line; do 339 while read line; do
342 -antigen-get-clone-url "$line" 340 -antigen-get-clone-url "$line"
343 done | 341 done |
344 sed -e 's/^/ /' -e 's/|/, branch /' 342 sed -e 's/^/ /' -e 's/|/, branch /'
345 343
346 if $force || (echo -n '\nDelete them all? [y/N] '; read -q); then 344 if $force || (echo -n '\nDelete them all? [y/N] '; read -q); then
347 echo 345 echo
348 echo 346 echo
349 echo "$unused_clones" | while read line; do 347 echo "$unused_clones" | while read line; do
350 echo -n "Deleting clone for $(-antigen-get-clone-url "$line")..." 348 echo -n "Deleting clone for $(-antigen-get-clone-url "$line")..."
351 rm -rf "$line" 349 rm -rf "$line"
352 echo ' done.' 350 echo ' done.'
353 done 351 done
354 else 352 else
355 echo 353 echo
356 echo Nothing deleted. 354 echo Nothing deleted.
357 fi 355 fi
358 } 356 }
359 357
360 antigen-lib () { 358 antigen-lib () {
361 antigen-bundle --loc=lib 359 antigen-bundle --loc=lib
362 } 360 }
363 361
364 antigen-prezto-lib () { 362 antigen-prezto-lib () {
365 antigen-bundle sorin-ionescu/prezto 363 antigen-bundle sorin-ionescu/prezto
366 export ZDOTDIR=$ADOTDIR/repos/ 364 export ZDOTDIR=$ADOTDIR/repos/
367 } 365 }
368 366
369 antigen-theme () { 367 antigen-theme () {
370 368
371 if [[ "$1" != */* && "$1" != --* ]]; then 369 if [[ "$1" != */* && "$1" != --* ]]; then
372 # The first argument is just a name of the plugin, to be picked up from 370 # The first argument is just a name of the plugin, to be picked up from
373 # the default repo. 371 # the default repo.
374 local name="${1:-robbyrussell}" 372 local name="${1:-robbyrussell}"
375 antigen-bundle --loc=themes/$name --btype=theme 373 antigen-bundle --loc=themes/$name --btype=theme
376 374
377 else 375 else
378 antigen-bundle "$@" --btype=theme 376 antigen-bundle "$@" --btype=theme
379 377
380 fi 378 fi
381 379
382 } 380 }
383 381
384 antigen-apply () { 382 antigen-apply () {
385 # Initialize completion. 383 # Initialize completion.
386 # TODO: Only load completions if there are any changes to the bundle 384 # TODO: Only load completions if there are any changes to the bundle
387 # repositories. 385 # repositories.
388 compinit -i 386 compinit -i
389 } 387 }
390 388
391 antigen-list () { 389 antigen-list () {
392 # List all currently installed bundles. 390 # List all currently installed bundles.
393 if [[ -z "$_ANTIGEN_BUNDLE_RECORD" ]]; then 391 if [[ -z "$_ANTIGEN_BUNDLE_RECORD" ]]; then
394 echo "You don't have any bundles." >&2 392 echo "You don't have any bundles." >&2
395 return 1 393 return 1
396 else 394 else
397 -antigen-echo-record | sort -u 395 -antigen-echo-record | sort -u
398 fi 396 fi
399 } 397 }
400 398
401 antigen-snapshot () { 399 antigen-snapshot () {
402 400
403 local snapshot_file="${1:-antigen-shapshot}" 401 local snapshot_file="${1:-antigen-shapshot}"
404 402
405 # The snapshot content lines are pairs of repo-url and git version hash, in 403 # The snapshot content lines are pairs of repo-url and git version hash, in
406 # the form: 404 # the form:
407 # <version-hash> <repo-url> 405 # <version-hash> <repo-url>
408 local snapshot_content="$(-antigen-echo-record | 406 local snapshot_content="$(-antigen-echo-record |
409 grep 'true$' | 407 grep 'true$' |
410 sed 's/ .*$//' | 408 sed 's/ .*$//' |
411 sort -u | 409 sort -u |
412 while read url; do 410 while read url; do
413 local dir="$(-antigen-get-clone-dir "$url")" 411 local dir="$(-antigen-get-clone-dir "$url")"
414 local version_hash="$(cd "$dir" && git rev-parse HEAD)" 412 local version_hash="$(cd "$dir" && git rev-parse HEAD)"
415 echo "$version_hash $url" 413 echo "$version_hash $url"
416 done)" 414 done)"
417 415
418 { 416 {
419 # The first line in the snapshot file is for metadata, in the form: 417 # The first line in the snapshot file is for metadata, in the form:
420 # key='value'; key='value'; key='value'; 418 # key='value'; key='value'; key='value';
421 # Where `key`s are valid shell variable names. 419 # Where `key`s are valid shell variable names.
422 420
423 # Snapshot version. Has no relation to antigen version. If the snapshot 421 # Snapshot version. Has no relation to antigen version. If the snapshot
424 # file format changes, this number can be incremented. 422 # file format changes, this number can be incremented.
425 echo -n "version='1';" 423 echo -n "version='1';"
426 424
427 # Snapshot creation date+time. 425 # Snapshot creation date+time.
428 echo -n " created_on='$(date)';" 426 echo -n " created_on='$(date)';"
429 427
430 # Add a checksum with the md5 checksum of all the snapshot lines. 428 # Add a checksum with the md5 checksum of all the snapshot lines.
431 local checksum="$(echo "$snapshot_content" | md5sum)" 429 local checksum="$(echo "$snapshot_content" | md5sum)"
432 echo -n " checksum='${checksum%% *}';" 430 echo -n " checksum='${checksum%% *}';"
433 431
434 # A newline after the metadata and then the snapshot lines. 432 # A newline after the metadata and then the snapshot lines.
435 echo "\n$snapshot_content" 433 echo "\n$snapshot_content"
436 434
437 } > "$snapshot_file" 435 } > "$snapshot_file"
438 436
439 } 437 }
440 438
441 antigen-restore () { 439 antigen-restore () {
442 440
443 if [[ $# == 0 ]]; then 441 if [[ $# == 0 ]]; then
444 echo 'Please provide a snapshot file to restore from.' >&2 442 echo 'Please provide a snapshot file to restore from.' >&2
445 return 1 443 return 1
446 fi 444 fi
447 445
448 local snapshot_file="$1" 446 local snapshot_file="$1"
449 447
450 # TODO: Before doing anything with the snapshot file, verify its checksum. 448 # TODO: Before doing anything with the snapshot file, verify its checksum.
451 # If it fails, notify this to the user and confirm if restore should 449 # If it fails, notify this to the user and confirm if restore should
452 # proceed. 450 # proceed.
453 451
454 echo -n "Restoring from $snapshot_file..." 452 echo -n "Restoring from $snapshot_file..."
455 453
456 sed -n '1!p' "$snapshot_file" | 454 sed -n '1!p' "$snapshot_file" |
457 while read line; do 455 while read line; do
458 456
459 local version_hash="${line%% *}" 457 local version_hash="${line%% *}"
460 local url="${line##* }" 458 local url="${line##* }"
461 local clone_dir="$(-antigen-get-clone-dir "$url")" 459 local clone_dir="$(-antigen-get-clone-dir "$url")"
462 460
463 if [[ ! -d $clone_dir ]]; then 461 if [[ ! -d $clone_dir ]]; then
464 git clone "$url" "$clone_dir" > /dev/null 462 git clone "$url" "$clone_dir" > /dev/null
465 fi 463 fi
466 464
467 (cd "$clone_dir" && git checkout $version_hash) 2> /dev/null 465 (cd "$clone_dir" && git checkout $version_hash) 2> /dev/null
468 466
469 done 467 done
470 468
471 echo ' done.' 469 echo ' done.'
472 echo 'Please open a new shell to get the restored changes.' 470 echo 'Please open a new shell to get the restored changes.'
473 } 471 }
474 472
475 antigen-help () { 473 antigen-help () {
476 cat <<EOF 474 cat <<EOF
477 Antigen is a plugin management system for zsh. It makes it easy to grab awesome 475 Antigen is a plugin management system for zsh. It makes it easy to grab awesome
478 shell scripts and utilities, put up on github. For further details and complete 476 shell scripts and utilities, put up on github. For further details and complete
479 documentation, visit the project's page at 'http://antigen.sharats.me'. 477 documentation, visit the project's page at 'http://antigen.sharats.me'.
480 EOF 478 EOF
481 } 479 }
482 480
483 # A syntax sugar to avoid the `-` when calling antigen commands. With this 481 # A syntax sugar to avoid the `-` when calling antigen commands. With this
484 # function, you can write `antigen-bundle` as `antigen bundle` and so on. 482 # function, you can write `antigen-bundle` as `antigen bundle` and so on.
485 antigen () { 483 antigen () {
486 local cmd="$1" 484 local cmd="$1"
487 shift 485 shift
488 "antigen-$cmd" "$@" 486 "antigen-$cmd" "$@"
489 } 487 }
490 488
491 -antigen-parse-args () { 489 -antigen-parse-args () {
492 # An argument parsing functionality to parse arguments the *antigen* way :). 490 # An argument parsing functionality to parse arguments the *antigen* way :).
493 # Takes one first argument (called spec), which dictates how to parse and 491 # Takes one first argument (called spec), which dictates how to parse and
494 # the rest of the arguments are parsed. Outputs a piece of valid shell code 492 # the rest of the arguments are parsed. Outputs a piece of valid shell code
495 # that can be passed to `eval` inside a function which creates the arguments 493 # that can be passed to `eval` inside a function which creates the arguments
496 # and their values as local variables. Suggested use is to set the defaults 494 # and their values as local variables. Suggested use is to set the defaults
497 # to all arguments first and then eval the output of this function. 495 # to all arguments first and then eval the output of this function.
498 496
499 # Spec: Only long argument supported. No support for parsing short options. 497 # Spec: Only long argument supported. No support for parsing short options.
500 # The spec must have two sections, separated by a `;`. 498 # The spec must have two sections, separated by a `;`.
501 # '<positional-arguments>;<keyword-only-arguments>' 499 # '<positional-arguments>;<keyword-only-arguments>'
502 # Positional arguments are passed as just values, like `command a b`. 500 # Positional arguments are passed as just values, like `command a b`.
503 # Keyword arguments are passed as a `--name=value` pair, like `command 501 # Keyword arguments are passed as a `--name=value` pair, like `command
504 # --arg1=a --arg2=b`. 502 # --arg1=a --arg2=b`.
505 503
506 # Each argument in the spec is separated by a `,`. Each keyword argument can 504 # Each argument in the spec is separated by a `,`. Each keyword argument can
507 # end in a `:` to specifiy that this argument wants a value, otherwise it 505 # end in a `:` to specifiy that this argument wants a value, otherwise it
508 # doesn't take a value. (The value in the output when the keyword argument 506 # doesn't take a value. (The value in the output when the keyword argument
509 # doesn't have a `:` is `true`). 507 # doesn't have a `:` is `true`).
510 508
511 # Arguments in either section can end with a `?` (should come after `:`, if 509 # Arguments in either section can end with a `?` (should come after `:`, if
512 # both are present), means optional. FIXME: Not yet implemented. 510 # both are present), means optional. FIXME: Not yet implemented.
513 511
514 # See the test file, tests/arg-parser.t for (working) examples. 512 # See the test file, tests/arg-parser.t for (working) examples.
515 513
516 local spec="$1" 514 local spec="$1"
517 shift 515 shift
518 516
519 # Sanitize the spec 517 # Sanitize the spec
520 spec="$(echo "$spec" | tr '\n' ' ' | sed 's/[[:space:]]//g')" 518 spec="$(echo "$spec" | tr '\n' ' ' | sed 's/[[:space:]]//g')"
521 519
522 local code='' 520 local code=''
523 521
524 --add-var () { 522 --add-var () {
525 test -z "$code" || code="$code\n" 523 test -z "$code" || code="$code\n"
526 code="${code}local $1='$2'" 524 code="${code}local $1='$2'"
527 } 525 }
528 526
529 local positional_args="$(echo "$spec" | cut -d\; -f1)" 527 local positional_args="$(echo "$spec" | cut -d\; -f1)"
530 local positional_args_count="$(echo $positional_args | 528 local positional_args_count="$(echo $positional_args |
531 awk -F, '{print NF}')" 529 awk -F, '{print NF}')"
532 530
533 # Set spec values based on the positional arguments. 531 # Set spec values based on the positional arguments.
534 local i=1 532 local i=1
535 while ! [[ -z $1 || $1 == --* ]]; do 533 while ! [[ -z $1 || $1 == --* ]]; do
536 534
537 if (( $i > $positional_args_count )); then 535 if (( $i > $positional_args_count )); then
538 echo "Only $positional_args_count positional arguments allowed." >&2 536 echo "Only $positional_args_count positional arguments allowed." >&2
539 echo "Found at least one more: '$1'" >&2 537 echo "Found at least one more: '$1'" >&2
540 return 538 return
541 fi 539 fi
542 540
543 local name_spec="$(echo "$positional_args" | cut -d, -f$i)" 541 local name_spec="$(echo "$positional_args" | cut -d, -f$i)"
544 local name="${${name_spec%\?}%:}" 542 local name="${${name_spec%\?}%:}"
545 local value="$1" 543 local value="$1"
546 544
547 if echo "$code" | grep -qm1 "^local $name="; then 545 if echo "$code" | grep -qm1 "^local $name="; then
548 echo "Argument '$name' repeated with the value '$value'". >&2 546 echo "Argument '$name' repeated with the value '$value'". >&2
549 return 547 return
550 fi 548 fi
551 549
552 --add-var $name "$value" 550 --add-var $name "$value"
553 551
554 shift 552 shift
555 i=$(($i + 1)) 553 i=$(($i + 1))
556 done 554 done
557 555
558 local keyword_args="$( 556 local keyword_args="$(
559 # Positional arguments can double up as keyword arguments too. 557 # Positional arguments can double up as keyword arguments too.
560 echo "$positional_args" | tr , '\n' | 558 echo "$positional_args" | tr , '\n' |
561 while read line; do 559 while read line; do
562 if [[ $line == *\? ]]; then 560 if [[ $line == *\? ]]; then
563 echo "${line%?}:?" 561 echo "${line%?}:?"
564 else 562 else
565 echo "$line:" 563 echo "$line:"
566 fi 564 fi
567 done 565 done
568 566
569 # Specified keyword arguments. 567 # Specified keyword arguments.
570 echo "$spec" | cut -d\; -f2 | tr , '\n' 568 echo "$spec" | cut -d\; -f2 | tr , '\n'
571 )" 569 )"
572 local keyword_args_count="$(echo $keyword_args | awk -F, '{print NF}')" 570 local keyword_args_count="$(echo $keyword_args | awk -F, '{print NF}')"
573 571
574 # Set spec values from keyword arguments, if any. The remaining arguments 572 # Set spec values from keyword arguments, if any. The remaining arguments
575 # are all assumed to be keyword arguments. 573 # are all assumed to be keyword arguments.
576 while [[ $1 == --* ]]; do 574 while [[ $1 == --* ]]; do
577 # Remove the `--` at the start. 575 # Remove the `--` at the start.
578 local arg="${1#--}" 576 local arg="${1#--}"
579 577
580 # Get the argument name and value. 578 # Get the argument name and value.
581 if [[ $arg != *=* ]]; then 579 if [[ $arg != *=* ]]; then
582 local name="$arg" 580 local name="$arg"
583 local value='' 581 local value=''
584 else 582 else
585 local name="${arg%\=*}" 583 local name="${arg%\=*}"
586 local value="${arg#*=}" 584 local value="${arg#*=}"
587 fi 585 fi
588 586
589 if echo "$code" | grep -qm1 "^local $name="; then 587 if echo "$code" | grep -qm1 "^local $name="; then
590 echo "Argument '$name' repeated with the value '$value'". >&2 588 echo "Argument '$name' repeated with the value '$value'". >&2
591 return 589 return
592 fi 590 fi
593 591
594 # The specification for this argument, used for validations. 592 # The specification for this argument, used for validations.
595 local arg_line="$(echo "$keyword_args" | grep -m1 "^$name:\??\?")" 593 local arg_line="$(echo "$keyword_args" | grep -m1 "^$name:\??\?")"
596 594
597 # Validate argument and value. 595 # Validate argument and value.
598 if [[ -z $arg_line ]]; then 596 if [[ -z $arg_line ]]; then
599 # This argument is not known to us. 597 # This argument is not known to us.
600 echo "Unknown argument '$name'." >&2 598 echo "Unknown argument '$name'." >&2
601 return 599 return
602 600
603 elif (echo "$arg_line" | grep -qm1 ':') && [[ -z $value ]]; then 601 elif (echo "$arg_line" | grep -qm1 ':') && [[ -z $value ]]; then
604 # This argument needs a value, but is not provided. 602 # This argument needs a value, but is not provided.
605 echo "Required argument for '$name' not provided." >&2 603 echo "Required argument for '$name' not provided." >&2
606 return 604 return
607 605
608 elif (echo "$arg_line" | grep -vqm1 ':') && [[ ! -z $value ]]; then 606 elif (echo "$arg_line" | grep -vqm1 ':') && [[ ! -z $value ]]; then
609 # This argument doesn't need a value, but is provided. 607 # This argument doesn't need a value, but is provided.
610 echo "No argument required for '$name', but provided '$value'." >&2 608 echo "No argument required for '$name', but provided '$value'." >&2
611 return 609 return
612 610
613 fi 611 fi
614 612
615 if [[ -z $value ]]; then 613 if [[ -z $value ]]; then
616 value=true 614 value=true
617 fi 615 fi
618 616
619 --add-var "${name//-/_}" "$value" 617 --add-var "${name//-/_}" "$value"
620 shift 618 shift
621 done 619 done
622 620
623 echo "$code" 621 echo "$code"
624 622
625 unfunction -- --add-var 623 unfunction -- --add-var
626 624
627 } 625 }
628 626
629 # Echo the bundle specs as in the record. The first line is not echoed since it 627 # Echo the bundle specs as in the record. The first line is not echoed since it
630 # is a blank line. 628 # is a blank line.
631 -antigen-echo-record () { 629 -antigen-echo-record () {
632 echo "$_ANTIGEN_BUNDLE_RECORD" | sed -n '1!p' 630 echo "$_ANTIGEN_BUNDLE_RECORD" | sed -n '1!p'
633 } 631 }
634 632
635 -antigen-env-setup () { 633 -antigen-env-setup () {
636 # Pre-startup initializations. 634 # Pre-startup initializations.
637 -set-default ANTIGEN_DEFAULT_REPO_URL \ 635 -set-default ANTIGEN_DEFAULT_REPO_URL \
638 https://github.com/robbyrussell/oh-my-zsh.git 636 https://github.com/robbyrussell/oh-my-zsh.git
639 -set-default ADOTDIR $HOME/.antigen 637 -set-default ADOTDIR $HOME/.antigen
640 638
641 # Load the compinit module. Required for `compdef` to be defined, which is 639 # Load the compinit module. Required for `compdef` to be defined, which is
642 # used by many plugins to define completions. 640 # used by many plugins to define completions.
643 autoload -U compinit 641 autoload -U compinit
644 compinit -i 642 compinit -i
645 643
646 # Setup antigen's own completion. 644 # Setup antigen's own completion.
647 compdef _antigen antigen 645 compdef _antigen antigen
648 } 646 }
649 647
650 # Same as `export $1=$2`, but will only happen if the name specified by `$1` is 648 # Same as `export $1=$2`, but will only happen if the name specified by `$1` is
651 # not already set. 649 # not already set.
652 -set-default () { 650 -set-default () {
653 local arg_name="$1" 651 local arg_name="$1"
654 local arg_value="$2" 652 local arg_value="$2"
655 eval "test -z \"\$$arg_name\" && export $arg_name='$arg_value'" 653 eval "test -z \"\$$arg_name\" && export $arg_name='$arg_value'"
656 } 654 }
657 655
658 # Setup antigen's autocompletion 656 # Setup antigen's autocompletion
659 _antigen () { 657 _antigen () {
660 compadd \ 658 compadd \
661 bundle \ 659 bundle \
662 bundles \ 660 bundles \
663 update \ 661 update \
664 revert \ 662 revert \
665 list \ 663 list \
666 cleanup \ 664 cleanup \
667 lib \ 665 lib \
668 selfupdate \ 666 selfupdate \
669 theme \ 667 theme \
670 apply \ 668 apply \
671 help 669 help
672 } 670 }
673 671
674 -antigen-env-setup 672 -antigen-env-setup
675 673