Skip to content

Instantly share code, notes, and snippets.

@ProBackup-nl
Forked from s-leroux/pgist.sh
Last active September 6, 2018 16:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ProBackup-nl/3971a45b21749cfff6c0069d3dad1dde to your computer and use it in GitHub Desktop.
Save ProBackup-nl/3971a45b21749cfff6c0069d3dad1dde to your computer and use it in GitHub Desktop.
Gister to POST or PATCH a single file as public gist. PATCH does gist ID lookup: no need to remember gist ID's
#!/bin/sh
# --------------------------------------------------------
# Shell gister to POST or PATCH a single file as public gist.
# PATCH does gist ID lookup: no need to remember gist ID's
# --------------------------------------------------------
# usage: $ pgist file_to_post_or_patch.extension
#
# installation: $ curl -O https://gist.githubusercontent.com/ProBackup-nl/3971a45b21749cfff6c0069d3dad1dde/raw/pgist.sh && chmod 755 pgist.sh && mv pgist.sh /opt/usr/sbin/pgist
#
# tested with Busybox (ash shell) + Entware (opkg)
# Limitation #1: 300 files per gist <- Github API
# Limitation #2: 30 (maybe 100) gists per user <- Github API && pagination is not implemented in this script
# Limitation #3: requires your gist filenames to be user unique (= not any of your gists can have an identical filename; otherwise filename to gist matching fails)
# ToDo: test large files; expect 4 MiB to fail.
# Dependencies
which jq > /dev/null || { echo 'Error: dependency jq not found. Install it with: ''$ opkg install jq''. Exiting'; exit 1 ; }
[ -z "$GITHUB_TOKEN" ] && { echo 'Error: GITHUB_TOKEN is empty. For example ''export GITHUB_TOKEN=replace_this_with_your_token'' in your ''~/.profile''. Create a personal access token <https://developer.github.com/v3/guides/getting-started/#oauth> Exiting'; exit 2; }
[ -z "$1" ] && { echo 'Error: no file supplied as argument. Exiting'; exit 3 ; }
which sed > /dev/null || { echo 'Error: dependency ''sed'' not found. Install it. Exiting'; exit 4 ; }
which awk > /dev/null || { echo 'Error: dependency ''awk'' not found. Install it. Exiting'; exit 5 ; }
which basename > /dev/null || { echo 'Error: dependency ''basename'' not found. Install it. Exiting'; exit 6 ; }
which curl > /dev/null || { echo 'Error: dependency ''curl'' not found. Install it with ''$ opkg install curl ca-certificates''. Exiting'; exit 7 ; }
# ToDo: ca-certificates /opt/etc/ssl/certs/
# Supply filename on the command-line as first argument
[ -f $1 ] && readonly FNAME=$1 || { echo "Error: file '$1' not found. Exiting" ; exit 8 ; }
readonly BNAME=`basename $FNAME`
# Lookup: authenticated user's gists | select matching filename | return parent gist id
# api.github.com/gists?filename=$FNAME doesn't filter results
# curl -I will show headers
readonly GIST_ID=`curl --silent -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/gists?per_page=100 |jq --raw-output '.[]|select(.files["'$BNAME'"])|.id'`
# Count results
id_count=0 ; for i in $GIST_ID ; do let id_count++ ; done
if [ $id_count -gt 1 ]; then
echo "Error: Duplicate filename found. The file names of your gists do need to be unique. Exiting"
exit 10
else
# POST or PATCH
# Sanitize file content
# Replace \ with \\
# Remove \r (from Windows end-of-lines),
# Replace tabs by \t
# Replace " with \"
# Replace EOL by \n (note: awk is not bullet-proof on busybox; awk '{ printf($0 "\\n") }' fails; slow od alternative <https://stackoverflow.com/questions/1251999/how-can-i-replace-a-newline-n-using-sed#answer-23166624>)
[ -n "$FNAME" ] && readonly CONTENT=$(sed -e 's/\\/\\\\/g' -e 's/\r//' -e's/\t/\\t/g' -e 's/"/\\"/g' "${FNAME}" | awk '{ printf("%s\\n", $0) } END { print "" }') || { echo 'Error: at this point the filename can''t be empty. Exiting' ; exit 11 ; }
#echo $CONTENT
if [ $id_count = 1 ] ; then
echo PATCH
# Use curl to send an explicit PATCH request to an existing gist
readonly TDATA="{ \"files\": { \"${BNAME}\": { \"content\": \"${CONTENT}\" } } }"
curl --silent --request PATCH -d "$TDATA" -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/gists/$GIST_ID
elif [ $id_count = 0 ] ; then
echo POST
read -p 'Give a description: ' DESCRIPTION
# Use curl to send an implicit POST request to create a new gist
curl -d "{ \"description\": \"${DESCRIPTION}\", \"public\": true, \"files\": { \"${BNAME}\": { \"content\": \"${CONTENT}\" } } }" -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/gists
else
echo "Logic error. Exiting"
exit 20
fi
fi
echo 'Done'
@ProBackup-nl
Copy link
Author

ProBackup-nl commented Sep 4, 2018

As a result of being unable to update an existing gist file with the answers of "upload-a-file-to-a-gist-with-bash" without installing significant dependencies (like ruby) on a mips router, this script found its existence.
Notes: Tested with scripts that use Heredoc notation. Not expected to handle with 4MiB large files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment