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 |