diff options
-rwxr-xr-x | gist | 54 |
1 files changed, 35 insertions, 19 deletions
@@ -95,7 +95,7 @@ httpGet(){ | |||
95 | http_method GET "$@" | 95 | http_method GET "$@" |
96 | } | 96 | } |
97 | 97 | ||
98 | # parse JSON from STDIN with string of commands | 98 | # Parse JSON from STDIN with string of commands |
99 | _process_json() { | 99 | _process_json() { |
100 | PYTHONIOENCODING=utf-8 \ | 100 | PYTHONIOENCODING=utf-8 \ |
101 | python -c "from __future__ import print_function; import sys, json; $1" | 101 | python -c "from __future__ import print_function; import sys, json; $1" |
@@ -150,7 +150,7 @@ update() { | |||
150 | fi | 150 | fi |
151 | } | 151 | } |
152 | 152 | ||
153 | # handle configuration cases | 153 | # Handle configuration cases |
154 | _configure() { | 154 | _configure() { |
155 | [[ $# == 0 ]] && (${EDITOR:-vi} "$CONFIG") && return 0 | 155 | [[ $# == 0 ]] && (${EDITOR:-vi} "$CONFIG") && return 0 |
156 | 156 | ||
@@ -176,7 +176,7 @@ _configure() { | |||
176 | cat "$CONFIG" | 176 | cat "$CONFIG" |
177 | } | 177 | } |
178 | 178 | ||
179 | # prompt for username | 179 | # Prompt for username |
180 | _ask_username() { | 180 | _ask_username() { |
181 | while [[ ! $user =~ ^[[:alnum:]]+$ ]]; do | 181 | while [[ ! $user =~ ^[[:alnum:]]+$ ]]; do |
182 | [[ -n $user ]] && echo "Not a valid username" | 182 | [[ -n $user ]] && echo "Not a valid username" |
@@ -185,7 +185,7 @@ _ask_username() { | |||
185 | _configure user "$user" | 185 | _configure user "$user" |
186 | } | 186 | } |
187 | 187 | ||
188 | # prompt for token | 188 | # Prompt for token |
189 | # TODO check token scope contains gist, ref: https://developer.github.com/v3/apps/oauth_applications/#check-a-token | 189 | # TODO check token scope contains gist, ref: https://developer.github.com/v3/apps/oauth_applications/#check-a-token |
190 | _ask_token() { | 190 | _ask_token() { |
191 | echo -n "Create a new token from web browser? [Y/n] " | 191 | echo -n "Create a new token from web browser? [Y/n] " |
@@ -201,7 +201,7 @@ _ask_token() { | |||
201 | _configure token "$token" | 201 | _configure token "$token" |
202 | } | 202 | } |
203 | 203 | ||
204 | # check configuration is fine with user setting | 204 | # Check configuration is fine with user setting |
205 | _validate_config(){ | 205 | _validate_config(){ |
206 | # shellcheck source=/dev/null | 206 | # shellcheck source=/dev/null |
207 | source "$CONFIG" 2> /dev/null | 207 | source "$CONFIG" 2> /dev/null |
@@ -224,7 +224,7 @@ _validate_config(){ | |||
224 | fi | 224 | fi |
225 | } | 225 | } |
226 | 226 | ||
227 | # load configuration | 227 | # Load configuration |
228 | _apply_config() { | 228 | _apply_config() { |
229 | _validate_config "$@" || return 1 | 229 | _validate_config "$@" || return 1 |
230 | 230 | ||
@@ -233,6 +233,7 @@ _apply_config() { | |||
233 | INDEX=$folder/index; [[ -e $INDEX ]] || touch $INDEX | 233 | INDEX=$folder/index; [[ -e $INDEX ]] || touch $INDEX |
234 | } | 234 | } |
235 | 235 | ||
236 | # Return git status of a given repo | ||
236 | _check_repo_status() { | 237 | _check_repo_status() { |
237 | if [[ ! -d $1 ]]; then | 238 | if [[ ! -d $1 ]]; then |
238 | if [[ $auto_sync == 'true' ]]; then | 239 | if [[ $auto_sync == 'true' ]]; then |
@@ -241,7 +242,7 @@ _check_repo_status() { | |||
241 | echo "\e[32m[Not cloned yet]\e[0m"; | 242 | echo "\e[32m[Not cloned yet]\e[0m"; |
242 | fi | 243 | fi |
243 | else | 244 | else |
244 | cd "$1" || exit | 245 | cd "$1" |
245 | if [[ -n $(git status --short) || $(git branch | sed -n '/\* / s///p') != 'master' ]] &>/dev/null; then | 246 | if [[ -n $(git status --short) || $(git branch | sed -n '/\* / s///p') != 'master' ]] &>/dev/null; then |
246 | echo "\e[36m[working]\e[0m" | 247 | echo "\e[36m[working]\e[0m" |
247 | else | 248 | else |
@@ -252,8 +253,8 @@ _check_repo_status() { | |||
252 | fi | 253 | fi |
253 | } | 254 | } |
254 | 255 | ||
255 | # Show the list of gist, but not updated time | 256 | # Display the list of gist, show username for starred gist |
256 | # show username for starred gist | 257 | # If hint=true, print hint to tty. If mark=<pattern>, filter index with regex |
257 | # TODO color private/starred mark | 258 | # TODO color private/starred mark |
258 | _show_list() { | 259 | _show_list() { |
259 | if [[ ! -e $INDEX ]]; then | 260 | if [[ ! -e $INDEX ]]; then |
@@ -279,6 +280,7 @@ _show_list() { | |||
279 | || return 0 | 280 | || return 0 |
280 | } | 281 | } |
281 | 282 | ||
283 | # Grep description, filename or file content with a given pattern | ||
282 | # TODO support filenames, file contents | 284 | # TODO support filenames, file contents |
283 | # TODO add option to configure case-sensitive | 285 | # TODO add option to configure case-sensitive |
284 | _grep_content() { | 286 | _grep_content() { |
@@ -307,12 +309,14 @@ _import_to_github() { | |||
307 | python -mwebbrowser https://github.com/new/import | 309 | python -mwebbrowser https://github.com/new/import |
308 | } | 310 | } |
309 | 311 | ||
312 | # Simply commit current changes and push to remote | ||
310 | _push_to_remote() { | 313 | _push_to_remote() { |
311 | _gist_id "$1" || return 1 | 314 | _gist_id "$1" || return 1 |
312 | cd "$folder/$GIST_ID" && git add . \ | 315 | cd "$folder/$GIST_ID" && git add . \ |
313 | && git commit --allow-empty-message -m '' && git push origin master | 316 | && git commit --allow-empty-message -m '' && git push origin master |
314 | } | 317 | } |
315 | 318 | ||
319 | # Parse JSON object of the result of gist fetch | ||
316 | _parse_gists() { | 320 | _parse_gists() { |
317 | _process_json ' | 321 | _process_json ' |
318 | raw = json.load(sys.stdin) | 322 | raw = json.load(sys.stdin) |
@@ -329,7 +333,7 @@ for gist in raw: | |||
329 | ' | 333 | ' |
330 | } | 334 | } |
331 | 335 | ||
332 | # parse response from gists require | 336 | # Parse response from 'gist fetch' to the format for index file |
333 | _parse_response() { | 337 | _parse_response() { |
334 | _parse_gists \ | 338 | _parse_gists \ |
335 | | tac | sed -e 's/, /,/g' | nl -s' ' \ | 339 | | tac | sed -e 's/, /,/g' | nl -s' ' \ |
@@ -341,9 +345,9 @@ _parse_response() { | |||
341 | done | 345 | done |
342 | } | 346 | } |
343 | 347 | ||
348 | # Get latest list of gists from Github API | ||
344 | # TODO pagnation for more than 100 gists | 349 | # TODO pagnation for more than 100 gists |
345 | # TODO add files of a gist | 350 | # TODO add files of a gist |
346 | # get latest list of gists from Github API | ||
347 | _fetch_gists() { | 351 | _fetch_gists() { |
348 | echo "fetching $user's gists from $GITHUB_API..." | 352 | echo "fetching $user's gists from $GITHUB_API..." |
349 | echo | 353 | echo |
@@ -365,6 +369,7 @@ _fetch_gists() { | |||
365 | true | 369 | true |
366 | } | 370 | } |
367 | 371 | ||
372 | # Fetch gists for a given user | ||
368 | # TODO pagnation for more than 100 gists | 373 | # TODO pagnation for more than 100 gists |
369 | _query_user() { | 374 | _query_user() { |
370 | local route="users/$1/gists" | 375 | local route="users/$1/gists" |
@@ -377,11 +382,13 @@ _query_user() { | |||
377 | done | 382 | done |
378 | } | 383 | } |
379 | 384 | ||
385 | # Return the unique code for current commit, to compare repo status and the result of 'gist fetch' | ||
386 | # Because there is no way to get commit SHA with 'gist fetch' | ||
380 | _blob_code() { | 387 | _blob_code() { |
381 | cd "$1" && git ls-tree master | cut -d' ' -f3 | cut -c-7 | sort | paste -sd '-' | 388 | cd "$1" && git ls-tree master | cut -d' ' -f3 | cut -c-7 | sort | paste -sd '-' |
382 | } | 389 | } |
383 | 390 | ||
384 | # update local git repos | 391 | # Update local git repos |
385 | _sync_repos() { | 392 | _sync_repos() { |
386 | # clone repos which are not in the local | 393 | # clone repos which are not in the local |
387 | comm -13 <(find $folder -maxdepth 1 -type d | sed -e '1d; s#.*/##' | sort) \ | 394 | comm -13 <(find $folder -maxdepth 1 -type d | sed -e '1d; s#.*/##' | sort) \ |
@@ -401,7 +408,7 @@ _sync_repos() { | |||
401 | echo Everything is fine! | 408 | echo Everything is fine! |
402 | } | 409 | } |
403 | 410 | ||
404 | # get the url where to clone repo, take user and repo name as parameters | 411 | # Get the url where to clone repo, take user and repo name as parameters |
405 | _repo_url() { | 412 | _repo_url() { |
406 | if [[ $protocol == 'ssh' ]]; then | 413 | if [[ $protocol == 'ssh' ]]; then |
407 | echo "git@gist.github.com:$1.git" | 414 | echo "git@gist.github.com:$1.git" |
@@ -410,7 +417,7 @@ _repo_url() { | |||
410 | fi | 417 | fi |
411 | } | 418 | } |
412 | 419 | ||
413 | # get gist id from index files | 420 | # Get gist id from index files |
414 | _gist_id() { | 421 | _gist_id() { |
415 | GIST_ID=$( (grep -hs '' $INDEX || true) | sed -n -e "/^$1 / p" | cut -d' ' -f2 | sed -E -e 's#.*/##') | 422 | GIST_ID=$( (grep -hs '' $INDEX || true) | sed -n -e "/^$1 / p" | cut -d' ' -f2 | sed -E -e 's#.*/##') |
416 | if [[ -z $GIST_ID ]]; then | 423 | if [[ -z $GIST_ID ]]; then |
@@ -422,6 +429,8 @@ _gist_id() { | |||
422 | fi | 429 | fi |
423 | } | 430 | } |
424 | 431 | ||
432 | # Return the path of local repo with a given index | ||
433 | # If action is not empty, eval it! | ||
425 | _goto_gist() { | 434 | _goto_gist() { |
426 | _gist_id "$1" || return 1 | 435 | _gist_id "$1" || return 1 |
427 | 436 | ||
@@ -447,6 +456,8 @@ _goto_gist() { | |||
447 | fi | 456 | fi |
448 | } | 457 | } |
449 | 458 | ||
459 | # Delete gists with given indices | ||
460 | # Specify confirm=false to suppress confirmation | ||
450 | _delete_gist() { | 461 | _delete_gist() { |
451 | if [[ $confirm != false ]]; then | 462 | if [[ $confirm != false ]]; then |
452 | read -r -p "Delete gists above? [y/N] " response | 463 | read -r -p "Delete gists above? [y/N] " response |
@@ -462,7 +473,7 @@ _delete_gist() { | |||
462 | done | 473 | done |
463 | } | 474 | } |
464 | 475 | ||
465 | # remove repos which are not in user gists anymore | 476 | # Remove repos which are not in index file anymore |
466 | _clean_repos() { | 477 | _clean_repos() { |
467 | comm -23 <(find $folder -maxdepth 1 -type d | sed -e '1d; s#.*/##' | sort) \ | 478 | comm -23 <(find $folder -maxdepth 1 -type d | sed -e '1d; s#.*/##' | sort) \ |
468 | <(cut -d' ' -f2 < "$INDEX" | sed -e 's#.*/##' | sort 2> /dev/null ) \ | 479 | <(cut -d' ' -f2 < "$INDEX" | sed -e 's#.*/##' | sort 2> /dev/null ) \ |
@@ -471,7 +482,7 @@ _clean_repos() { | |||
471 | done | 482 | done |
472 | } | 483 | } |
473 | 484 | ||
474 | # equal to jq '.[] | {user: .user.login, created_at: .created_at, updated_at: .updated_at, body: .body}' | 485 | # Parse JSON object of gist user comments |
475 | _parse_comment() { | 486 | _parse_comment() { |
476 | _process_json ' | 487 | _process_json ' |
477 | raw = json.load(sys.stdin); | 488 | raw = json.load(sys.stdin); |
@@ -484,6 +495,7 @@ for comment in raw: | |||
484 | ' | 495 | ' |
485 | } | 496 | } |
486 | 497 | ||
498 | # Show the detail of a gist | ||
487 | # TODO add parameter --comment to fetch comments | 499 | # TODO add parameter --comment to fetch comments |
488 | _show_detail() { | 500 | _show_detail() { |
489 | _gist_id "$1" || return 1 | 501 | _gist_id "$1" || return 1 |
@@ -500,7 +512,7 @@ _show_detail() { | |||
500 | fi | 512 | fi |
501 | } | 513 | } |
502 | 514 | ||
503 | # set filename/description/permission for a new gist | 515 | # Set filename/description/permission for a new gist |
504 | _set_gist() { | 516 | _set_gist() { |
505 | files=() | 517 | files=() |
506 | public=True | 518 | public=True |
@@ -533,6 +545,7 @@ _new_file() { | |||
533 | echo /tmp/"$filename" | 545 | echo /tmp/"$filename" |
534 | } | 546 | } |
535 | 547 | ||
548 | # Parse JSON object of a single gist | ||
536 | _gist_body(){ | 549 | _gist_body(){ |
537 | _process_json " | 550 | _process_json " |
538 | import os.path | 551 | import os.path |
@@ -546,7 +559,7 @@ print(json.dumps({'public': $public, 'files': files_json, 'description': descrip | |||
546 | " | 559 | " |
547 | } | 560 | } |
548 | 561 | ||
549 | # create a new gist with files | 562 | # Create a new gist with files. If success, also update index file and clone the repo |
550 | _create_gist() { | 563 | _create_gist() { |
551 | _set_gist "$@" || return 1 | 564 | _set_gist "$@" || return 1 |
552 | [[ -z ${files[*]} ]] && files+=($(_new_file "$filename")) | 565 | [[ -z ${files[*]} ]] && files+=($(_new_file "$filename")) |
@@ -572,7 +585,7 @@ _create_gist() { | |||
572 | fi | 585 | fi |
573 | } | 586 | } |
574 | 587 | ||
575 | # update description of a gist | 588 | # Update description of a gist |
576 | _edit_gist() { | 589 | _edit_gist() { |
577 | _gist_id "$1" || return 1 | 590 | _gist_id "$1" || return 1 |
578 | 591 | ||
@@ -593,10 +606,13 @@ _edit_gist() { | |||
593 | || echo 'Fail to modify gist description' | 606 | || echo 'Fail to modify gist description' |
594 | } | 607 | } |
595 | 608 | ||
609 | # Print helper message | ||
596 | usage() { | 610 | usage() { |
597 | sed -E -n -e ' /^$/ q; 7,$ s/^# //p' "$0" | 611 | sed -E -n -e ' /^$/ q; 7,$ s/^# //p' "$0" |
598 | } | 612 | } |
599 | 613 | ||
614 | # Check remote urls of all repos match current protocol in configuration file | ||
615 | # If not, update them | ||
600 | _check_protocol() { | 616 | _check_protocol() { |
601 | find $folder -maxdepth 1 -mindepth 1 -type d \ | 617 | find $folder -maxdepth 1 -mindepth 1 -type d \ |
602 | | while read -r repo; do | 618 | | while read -r repo; do |