Commit 3811dd84f552b3c0a1f59028167e0e78e90ead38

Authored by Corey Jewett
1 parent 3e76602f83

localize and don't leak cross-platform md5

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

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