Commit 65520d3c6c308d33a2aeb757fbbe978494829b97

Authored by Shrikant Sharat
1 parent 292d226b93

Git seems to require cd-ing to the clone for submodule update.

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