diff options
| -rwxr-xr-x | gist | 137 |
1 files changed, 84 insertions, 53 deletions
| @@ -58,8 +58,9 @@ configuredClient="" | |||
| 58 | NAME=${GISTSCRIPT:-$(basename $0)} #show hint and helper message with current script name | 58 | NAME=${GISTSCRIPT:-$(basename $0)} #show hint and helper message with current script name |
| 59 | GITHUB_API=https://api.github.com | 59 | GITHUB_API=https://api.github.com |
| 60 | CONFIG=~/.config/gist.conf; mkdir -p ~/.config | 60 | CONFIG=~/.config/gist.conf; mkdir -p ~/.config |
| 61 | per_page=100 | ||
| 61 | 62 | ||
| 62 | INDEX_FORMAT=('index' 'url' 'tags_string' 'blob_code' 'file_array' 'file_num' 'comment_num' 'author' 'created_at' 'updated_at' 'description') | 63 | INDEX_FORMAT=('index' 'public' 'url' 'tags_string' 'blob_code' 'file_array' 'file_num' 'comment_num' 'author' 'created_at' 'updated_at' 'description') |
| 63 | TAG_CHAR='-_[:alnum:]' | 64 | TAG_CHAR='-_[:alnum:]' |
| 64 | if [[ ! -t 0 ]]; then | 65 | if [[ ! -t 0 ]]; then |
| 65 | INPUT=$(cat) | 66 | INPUT=$(cat) |
| @@ -125,7 +126,7 @@ http_method() { | |||
| 125 | case "$configuredClient" in | 126 | case "$configuredClient" in |
| 126 | curl) [[ -n $token ]] && header_opt="--header" header="Authorization: token $token" | 127 | curl) [[ -n $token ]] && header_opt="--header" header="Authorization: token $token" |
| 127 | [[ $METHOD =~ (POST|PATCH) ]] && data_opt='--data' | 128 | [[ $METHOD =~ (POST|PATCH) ]] && data_opt='--data' |
| 128 | curl -X "$METHOD" -A curl -s $header_opt "$header" $data_opt "@$http_data" "$@" ;; | 129 | curl -X "$METHOD" -A curl -s $header_opt "$header" $data_opt ${HEADER:+-D $HEADER} "@$http_data" "$@" ;; |
| 129 | wget) [[ -n $token ]] && header_opt="--header" header="Authorization: token $token" | 130 | wget) [[ -n $token ]] && header_opt="--header" header="Authorization: token $token" |
| 130 | [[ $METHOD =~ (POST|PATCH) ]] && data_opt='--body-file' | 131 | [[ $METHOD =~ (POST|PATCH) ]] && data_opt='--body-file' |
| 131 | wget --method="$METHOD" -qO- $header_opt "$header" $data_opt "$http_data" "$@" ;; | 132 | wget --method="$METHOD" -qO- $header_opt "$header" $data_opt "$http_data" "$@" ;; |
| @@ -356,30 +357,26 @@ _grep_content() { | |||
| 356 | 357 | ||
| 357 | # Parse JSON object of the result of gist fetch | 358 | # Parse JSON object of the result of gist fetch |
| 358 | _parse_gists() { | 359 | _parse_gists() { |
| 359 | _process_json ' | 360 | _process_json ' |
| 360 | raw = json.load(sys.stdin) | 361 | raw = json.load(sys.stdin) |
| 361 | for gist in raw: | 362 | for gist in raw: |
| 362 | print(gist["html_url"], end=" ") | 363 | print(gist["public"], end=" ") |
| 363 | print(gist["public"], end=" ") | 364 | print(gist["html_url"], end=" ") |
| 364 | print(",".join(file["raw_url"] for file in gist["files"].values()), end=" ") | 365 | print(",".join(file["raw_url"] for file in gist["files"].values()), end=" ") |
| 365 | print(",".join(file["filename"].replace(" ", "-") + "@" + str(file["language"]).replace(" ", "-") for file in gist["files"].values()), end=" ") | 366 | print(",".join(file["filename"].replace(" ", "-") + "@" + str(file["language"]).replace(" ", "-") for file in gist["files"].values()), end=" ") |
| 366 | print(len(gist["files"]), end=" ") | 367 | print(len(gist["files"]), end=" ") |
| 367 | print(gist["comments"], end=" ") | 368 | print(gist["comments"], end=" ") |
| 368 | print(gist["owner"]["login"], end=" ") | 369 | print(gist["owner"]["login"], end=" ") |
| 369 | print(gist["created_at"], end=" ") | 370 | print(gist["created_at"], end=" ") |
| 370 | print(gist["updated_at"], end=" ") | 371 | print(gist["updated_at"], end=" ") |
| 371 | print(gist["description"]) | 372 | print(gist["description"]) |
| 372 | ' | 373 | ' |
| 373 | } | 374 | } |
| 374 | 375 | ||
| 375 | # Parse response from 'gist fetch' to the format for index file | 376 | # Parse response from 'gist fetch' to the format for index file |
| 376 | _parse_response() { | 377 | _parse_response() { |
| 377 | _parse_gists \ | 378 | _parse_gists \ |
| 378 | | tac | nl -s' ' \ | 379 | | while read -r "${INDEX_FORMAT[@]:1:2}" file_url_array "${INDEX_FORMAT[@]:5:7}"; do |
| 379 | | while read -r "${INDEX_FORMAT[@]:0:2}" public file_url_array "${INDEX_FORMAT[@]:4:7}"; do | ||
| 380 | local private_prefix=''; [[ $public == 'False' ]] && private_prefix=p | ||
| 381 | [[ -n $1 ]] && local index=${1}; index=${private_prefix}${prefix}${index} | ||
| 382 | |||
| 383 | local blob_code=$(echo "$file_url_array" | tr ',' '\n' | sed -E -e 's#.*raw/(.*)/.*#\1#' | sort | cut -c -7 | paste -s -d '-' -) | 380 | local blob_code=$(echo "$file_url_array" | tr ',' '\n' | sed -E -e 's#.*raw/(.*)/.*#\1#' | sort | cut -c -7 | paste -s -d '-' -) |
| 384 | file_array=${file_array//@None/@Text} | 381 | file_array=${file_array//@None/@Text} |
| 385 | 382 | ||
| @@ -392,41 +389,72 @@ _parse_response() { | |||
| 392 | done | 389 | done |
| 393 | } | 390 | } |
| 394 | 391 | ||
| 392 | # Get a single JSON object of gist from response, and update index file | ||
| 393 | _update_gist() { | ||
| 394 | local record="$(sed -e '1 s/^/[/; $ s/$/]/' | index=$1 _parse_response)" | ||
| 395 | [[ -n $record ]] && sed -i'' -Ee "/^$1 / s^.+^$record^" $INDEX | ||
| 396 | } | ||
| 397 | |||
| 395 | # Get latest list of gists from Github API | 398 | # Get latest list of gists from Github API |
| 396 | # TODO pagnation for more than 100 gists | ||
| 397 | _fetch_gists() { | 399 | _fetch_gists() { |
| 398 | echo "fetching $user's gists from $GITHUB_API..." | 400 | local route=${route:-users/$user/gists} |
| 399 | echo | ||
| 400 | local route="users/$user/gists" | ||
| 401 | local prifix='' | ||
| 402 | if [[ $mark == s ]]; then | 401 | if [[ $mark == s ]]; then |
| 403 | route='gists/starred' | 402 | route='gists/starred' |
| 404 | prefix=s | ||
| 405 | extra="s0 https://gist.github.com/b0d2e7e67aa50298fdf8111ae7466b56 #bash,#gist NONE README.md@Markdown,gist@Shell 2 30 typebrook 2019-12-26T06:49:40Z 2020-05-15T13:00:31Z [bash-gist] A bash script for gist management" | ||
| 406 | fi | 403 | fi |
| 407 | 404 | ||
| 408 | result=$(http_method GET $GITHUB_API/$route?per_page=100 | prefix=$prefix _parse_response) | 405 | # set global variable HEADER in http_method, so prevent using pipe |
| 409 | result=$(printf "${extra:+$extra\n}$result") | 406 | HEADER=$(tmp_file HEADER) |
| 410 | [[ -z $result ]] && echo 'Not a single valid gist' && return 0 | 407 | HEADER=$HEADER http_method GET $GITHUB_API/$route${1} | _parse_response |
| 408 | } | ||
| 411 | 409 | ||
| 412 | sed -i'' -Ee "/^$mark/ d" $INDEX && echo "$result" >> $INDEX | 410 | # consider if HEADER is not exist |
| 413 | hint=$hint _show_list | 411 | _fetch_gists_with_pagnation() { |
| 412 | _fetch_gists "?per_page=$per_page" >> $1 | ||
| 413 | |||
| 414 | while true; do | ||
| 415 | local next_page='' | ||
| 416 | [[ -e $HEADER ]] && next_page=$(sed -Ene '/^[lL]ink: / s/.+page=([[:digit:]]+)>; rel=\"next\".+/\1/p' $HEADER) | ||
| 417 | [[ -z $next_page ]] && break | ||
| 418 | printf "%-4s gists fetched\n" $(( ($next_page -1) * $per_page )) > /dev/tty | ||
| 419 | |||
| 420 | _fetch_gists "?per_page=$per_page&page=$next_page" >> $1 | ||
| 421 | done || return 1 | ||
| 422 | } | ||
| 423 | |||
| 424 | # Update index file by GITHUB API with pagnation | ||
| 425 | _update_gists() { | ||
| 426 | echo "fetching $user's gists from $GITHUB_API..." | ||
| 427 | echo | ||
| 428 | |||
| 429 | local fetched_records=$(tmp_file fetched) | ||
| 430 | _fetch_gists_with_pagnation $fetched_records || { echo Something screwed; exit 1; } | ||
| 431 | |||
| 432 | [[ ! -s $fetched_records ]] && echo 'Not a single valid gist' && return 0 | ||
| 433 | sed -i'' -Ee "/^$mark/ d" $INDEX | ||
| 414 | 434 | ||
| 435 | extra="s0 True https://gist.github.com/b0d2e7e67aa50298fdf8111ae7466b56 #bash,#gist NONE README.md@Markdown,gist@Shell 2 30 typebrook 2019-12-26T06:49:40Z 2020-05-15T13:00:31Z [bash-gist] A bash script for gist management" | ||
| 436 | [[ $mark == s ]] && echo $extra >> $INDEX | ||
| 437 | |||
| 438 | tac <$fetched_records | nl -s' ' \ | ||
| 439 | | while read -r "${INDEX_FORMAT[@]:0:2}" extra; do | ||
| 440 | local prefix='' | ||
| 441 | [[ $public == False ]] && prefix=p; [[ $mark == s ]] && prefix=s | ||
| 442 | echo $prefix$index $public $extra | ||
| 443 | done >> $INDEX | ||
| 444 | |||
| 445 | hint=$hint _show_list | ||
| 415 | [[ $auto_sync != false ]] && (_sync_repos &> /dev/null &) | 446 | [[ $auto_sync != false ]] && (_sync_repos &> /dev/null &) |
| 416 | true | 447 | true |
| 417 | } | 448 | } |
| 418 | 449 | ||
| 419 | # Fetch gists for a given user | 450 | # Fetch gists for a given user |
| 420 | # TODO pagnation for more than 100 gists | ||
| 421 | _query_user() { | 451 | _query_user() { |
| 422 | local route="users/$1/gists" | 452 | local fetched_records=$(tmp_file fetched) |
| 423 | result="$(http_method GET $GITHUB_API/$route?per_page=100 | _parse_response)" | 453 | route=users/$1/gists _fetch_gists_with_pagnation $fetched_records |
| 424 | [[ -z $result ]] && echo "Failed to query $1's gists" && return 1 | 454 | cat $fetched_records \ |
| 425 | 455 | | while read -r ${INDEX_FORMAT[@]#index}; do | |
| 426 | echo "$result" \ | ||
| 427 | | while read -r "${INDEX_FORMAT[@]}"; do | ||
| 428 | echo "$url $author $file_num $comment_num $description" | cut -c -"$(tput cols)" | 456 | echo "$url $author $file_num $comment_num $description" | cut -c -"$(tput cols)" |
| 429 | done | 457 | done || { echo "Failed to query $1's gists"; exit 1; } |
| 430 | } | 458 | } |
| 431 | 459 | ||
| 432 | # Return the unique code for current commit, to compare repo status and the result of 'gist fetch' | 460 | # Return the unique code for current commit, to compare repo status and the result of 'gist fetch' |
| @@ -450,7 +478,7 @@ _pull_if_needed() { | |||
| 450 | # Update local git repos | 478 | # Update local git repos |
| 451 | _sync_repos() { | 479 | _sync_repos() { |
| 452 | comm -1 <(ls -A "$folder" | sort) \ | 480 | comm -1 <(ls -A "$folder" | sort) \ |
| 453 | <(cut -d' ' -f1-2 < "$INDEX" | sed -ne "/^$mark/ s#.*/##p" | sort) \ | 481 | <(while read -r ${INDEX_FORMAT[@]}; do echo $index $url; done < "$INDEX" | sed -ne "/^$mark/ s#.*/##p" | sort) \ |
| 454 | | { | 482 | | { |
| 455 | result=$(cat) | 483 | result=$(cat) |
| 456 | 484 | ||
| @@ -477,7 +505,8 @@ _repo_url() { | |||
| 477 | 505 | ||
| 478 | # Get gist id from index files | 506 | # Get gist id from index files |
| 479 | _gist_id() { | 507 | _gist_id() { |
| 480 | GIST_ID=$(sed -En -e "/^$1 / s#^$1 [^ ]+/([[:alnum:]]+) .+#\1#p" $INDEX | head -1) | 508 | read -r ${INDEX_FORMAT[@]} <<<"$(sed -ne "/$1 / p" $INDEX)" |
| 509 | GIST_ID=${url##*/} | ||
| 481 | if [[ -z $GIST_ID || ! $1 =~ [0-9a-z]+ ]]; then | 510 | if [[ -z $GIST_ID || ! $1 =~ [0-9a-z]+ ]]; then |
| 482 | echo -e "$(hint=false _show_list | sed -Ee 's/^( *[0-9a-z]+)/\\e[5m\1\\e[0m/')" | 511 | echo -e "$(hint=false _show_list | sed -Ee 's/^( *[0-9a-z]+)/\\e[5m\1\\e[0m/')" |
| 483 | echo | 512 | echo |
| @@ -546,7 +575,7 @@ _delete_gist() { | |||
| 546 | # Remove repos which are not in index file anymore | 575 | # Remove repos which are not in index file anymore |
| 547 | _clean_repos() { | 576 | _clean_repos() { |
| 548 | comm -23 <(find $folder -maxdepth 1 -type d | sed -e '1d; s#.*/##' | sort) \ | 577 | comm -23 <(find $folder -maxdepth 1 -type d | sed -e '1d; s#.*/##' | sort) \ |
| 549 | <(cut -d' ' -f2 < "$INDEX" | sed -e 's#.*/##' | sort 2> /dev/null ) \ | 578 | <(while read -r ${INDEX_FORMAT[@]}; do echo $url; done < "$INDEX" | sed -e 's#.*/##' | sort 2> /dev/null ) \ |
| 550 | | while read -r dir; do | 579 | | while read -r dir; do |
| 551 | mv $folder/"$dir" /tmp && echo $folder/"$dir" is moved to /tmp | 580 | mv $folder/"$dir" /tmp && echo $folder/"$dir" is moved to /tmp |
| 552 | done | 581 | done |
| @@ -601,7 +630,8 @@ _push_to_remote() { | |||
| 601 | git add . && git commit -m 'update' | 630 | git add . && git commit -m 'update' |
| 602 | fi | 631 | fi |
| 603 | if [[ -n $(git cherry) ]]; then | 632 | if [[ -n $(git cherry) ]]; then |
| 604 | git push origin master && (hint=false _fetch_gists &> /dev/null &) | 633 | git push origin master && \ |
| 634 | (http_method GET "$GITHUB_API/gists/$GIST_ID" | _update_gist $1 &> /dev/null &) | ||
| 605 | fi | 635 | fi |
| 606 | } | 636 | } |
| 607 | 637 | ||
| @@ -662,17 +692,20 @@ _create_gist() { | |||
| 662 | _set_gist "$@" || return 1 | 692 | _set_gist "$@" || return 1 |
| 663 | [[ -z ${files[*]} ]] && files+=($(_new_file "$filename")) | 693 | [[ -z ${files[*]} ]] && files+=($(_new_file "$filename")) |
| 664 | [[ -z $description ]] && read -e -r -p 'Type description: ' description < /dev/tty | 694 | [[ -z $description ]] && read -e -r -p 'Type description: ' description < /dev/tty |
| 695 | local index=$([[ $public == False ]] && echo p)$(( $(sed -e '/^s/ d' $INDEX | wc -l) +1 )) | ||
| 665 | 696 | ||
| 666 | echo 'Creating a new gist...' | 697 | echo 'Creating a new gist...' |
| 667 | http_data=$(tmp_file PATLOAD.CREATE) | 698 | http_data=$(tmp_file PATLOAD.CREATE) |
| 668 | echo -e "${files[*]}\n$description" \ | 699 | echo -e "${files[*]}\n$description" \ |
| 669 | | _gist_body > "$http_data" \ | 700 | | _gist_body > "$http_data" \ |
| 670 | && http_method POST $GITHUB_API/gists \ | 701 | && http_method POST $GITHUB_API/gists \ |
| 671 | | xargs -I{} -0 echo "[{}]" \ | 702 | | sed -e '1 s/^/\[/; $ s/$/\]/' \ |
| 672 | | _parse_response $(( $(sed -e '/^s/ d' $INDEX | wc -l) +1 )) \ | 703 | | index=$index _parse_response \ |
| 673 | | tee -a $INDEX \ | 704 | | tee -a $INDEX \ |
| 674 | | cut -d' ' -f2 | sed -E -e 's#.*/##' \ | 705 | | while read -r "${INDEX_FORMAT[@]}"; do |
| 675 | | (xargs -I{} git clone "$(_repo_url {})" $folder/{} &> /dev/null &) | 706 | local gist_id=${url/##*/} |
| 707 | (git clone "$(_repo_url $gist_id)" $folder/$gist_id &> /dev/null &) | ||
| 708 | done | ||
| 676 | 709 | ||
| 677 | # shellcheck disable=2181 | 710 | # shellcheck disable=2181 |
| 678 | if [[ $? -eq 0 ]]; then | 711 | if [[ $? -eq 0 ]]; then |
| @@ -699,10 +732,8 @@ _edit_gist() { | |||
| 699 | 732 | ||
| 700 | http_data=$(tmp_file PAYLOAD.EDIT) | 733 | http_data=$(tmp_file PAYLOAD.EDIT) |
| 701 | echo '{' \"description\": \""${DESC//\"/\\\"}"\" '}' > "$http_data" | 734 | echo '{' \"description\": \""${DESC//\"/\\\"}"\" '}' > "$http_data" |
| 702 | new_record=$(http_method PATCH "$GITHUB_API/gists/$GIST_ID" \ | 735 | |
| 703 | | sed -e '1 s/^/[/; $ s/$/]/' \ | 736 | http_method PATCH "$GITHUB_API/gists/$GIST_ID" | _update_gist $index \ |
| 704 | | _parse_response "${index#[[:alpha:]]}" ) | ||
| 705 | [[ -n $new_record ]] && sed -i'' -E -e "/^$index / s^.+^$new_record^" $INDEX \ | ||
| 706 | && hint=false mark="$index " _show_list \ | 737 | && hint=false mark="$index " _show_list \ |
| 707 | || echo 'Fail to modify gist description' | 738 | || echo 'Fail to modify gist description' |
| 708 | } | 739 | } |
| @@ -811,7 +842,7 @@ _access_last_index() { | |||
| 811 | } | 842 | } |
| 812 | 843 | ||
| 813 | _apply_config "$@" || exit 1 | 844 | _apply_config "$@" || exit 1 |
| 814 | if [[ $init ]]; then _fetch_gists; exit 0; fi | 845 | if [[ $init ]]; then _update_gists; exit 0; fi |
| 815 | case "$1" in | 846 | case "$1" in |
| 816 | "") | 847 | "") |
| 817 | _show_list ;; | 848 | _show_list ;; |
| @@ -821,7 +852,7 @@ case "$1" in | |||
| 821 | mark=.; _show_list ;; | 852 | mark=.; _show_list ;; |
| 822 | fetch | f) | 853 | fetch | f) |
| 823 | [[ $2 =~ ^(s|star)$ ]] && mark=s || mark=[^s] | 854 | [[ $2 =~ ^(s|star)$ ]] && mark=s || mark=[^s] |
| 824 | _fetch_gists ;; | 855 | _update_gists ;; |
| 825 | new | n) | 856 | new | n) |
| 826 | shift | 857 | shift |
| 827 | _create_gist "$@" ;; | 858 | _create_gist "$@" ;; |