aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xgist137
1 files changed, 84 insertions, 53 deletions
diff --git a/gist b/gist
index c65fb00..2c16c50 100755
--- a/gist
+++ b/gist
@@ -58,8 +58,9 @@ configuredClient=""
58NAME=${GISTSCRIPT:-$(basename $0)} #show hint and helper message with current script name 58NAME=${GISTSCRIPT:-$(basename $0)} #show hint and helper message with current script name
59GITHUB_API=https://api.github.com 59GITHUB_API=https://api.github.com
60CONFIG=~/.config/gist.conf; mkdir -p ~/.config 60CONFIG=~/.config/gist.conf; mkdir -p ~/.config
61per_page=100
61 62
62INDEX_FORMAT=('index' 'url' 'tags_string' 'blob_code' 'file_array' 'file_num' 'comment_num' 'author' 'created_at' 'updated_at' 'description') 63INDEX_FORMAT=('index' 'public' 'url' 'tags_string' 'blob_code' 'file_array' 'file_num' 'comment_num' 'author' 'created_at' 'updated_at' 'description')
63TAG_CHAR='-_[:alnum:]' 64TAG_CHAR='-_[:alnum:]'
64if [[ ! -t 0 ]]; then 65if [[ ! -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 '
360raw = json.load(sys.stdin) 361raw = json.load(sys.stdin)
361for gist in raw: 362for 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
814if [[ $init ]]; then _fetch_gists; exit 0; fi 845if [[ $init ]]; then _update_gists; exit 0; fi
815case "$1" in 846case "$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 "$@" ;;