Commit 5b8e33407732f8dcad92d44c71bf4a454646cd78

Authored by Shrikant Sharat
1 parent fb74da6ce7

Only save bundles that have a local clone in snapshot.

Saving the hash of bundles that don't have a local git clone doesn't make sense.

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