Skip to content

Instantly share code, notes, and snippets.

@rsvp
Created January 12, 2018 19:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rsvp/3957124731c4c218aa67c215f4f66b97 to your computer and use it in GitHub Desktop.
Save rsvp/3957124731c4c218aa67c215f4f66b97 to your computer and use it in GitHub Desktop.
git-logur : get log of GitHub repository without cloning. Shell script in bash for git log using GitHub API.
#!/usr/bin/env bash
# bash 4.3.11(1) Linux 3.13.0 git 1.9.1 Date : 2018-01-12
#
# _______________| git-logur : get log of GitHub repo without cloning.
#
# Usage: $ git-logur [username] [repository] [-m|-c|-v]
# # Format defaults to messages -m, else
# # -c for concise text, or -v for verbose json.
# # Concise includes author and committer, with timestamps.
#
# Example: $ ./git-logur pydata pandas-datareader -c
# # Outputs log as paragraphs in text format.
#
# Dependencies: curl
# GitHub API v3 https://developer.github.com/v3/
# esp. https://developer.github.com/v3/repos/commits
#
# CHANGE LOG Latest version at https://git.io/logur
# 2018-01-12 Append ?per_page=100&page=1 which means last 100 commits.
# Message only format. Case format arg.
# 2018-01-11 First version.
# _____ PREAMBLE_v3: settings, variables, and error handling.
#
LC_ALL=POSIX
# locale means "ASCII, US English, no special rules,
# output per ISO and RFC standards."
# Esp. use ASCII encoding for glob and sorting characters.
shopt -s extglob
# ^set extended glob for pattern matching.
shopt -s failglob
# ^failed pattern matching signals error.
set -e
# ^errors checked: immediate exit if a command has non-zero status.
set -o pipefail
# ^exit status on fail within pipe, not (default) last command.
set -u
# ^unassigned variables shall be errors.
# Example of default VARIABLE ASSIGNMENT: arg1=${1:-'foo'}
user=${1:-'pydata'}
repo=${2:-'pandas-datareader'}
format=${3:-'-m'}
pager=${PAGER:-'less'}
program=${0##*/} # similar to using basename
memf=$( mktemp /dev/shm/88_${program}_tmp.XXXXXXXXXX )
errf=$( mktemp /dev/shm/88_${program}_tmp.XXXXXXXXXX )
cleanup () {
# Delete temporary files, then optionally exit given status.
local status=${1:-'0'}
rm -f $memf $errf
[ $status = '-1' ] || exit $status # thus -1 prevents exit.
} #--------------------------------------------------------------------
warn () {
# Message with basename to stderr. Usage: warn "message"
echo -e "\n !! ${program}: $1 " >&2
} #--------------------------------------------------------------------
die () {
# Exit with status of most recent command or custom status, after
# cleanup and warn. Usage: command || die "message" [status]
local status=${2:-"$?"}
# cat $errf >&2
cleanup -1 && warn "$1" && exit $status
} #--------------------------------------------------------------------
trap "die 'SIG disruption, but cleanup finished.' 114" 1 2 3 15
# Cleanup after INTERRUPT: 1=SIGHUP, 2=SIGINT, 3=SIGQUIT, 15=SIGTERM
trap "die 'unhandled ERR via trap, but cleanup finished.' 116" ERR
# Cleanup after command failure unless it's part of a test clause.
#
# _______________ :: BEGIN Script ::::::::::::::::::::::::::::::::::::::::
# Many API methods take optional parameters. For GET requests, any parameters
# not specified as a segment in the path can be passed as an HTTP query string
# parameter:
#
# curl "https://api.github.com/repos/vmg/redcarpet/issues?state=closed"
#
# In this example, the 'vmg' and 'redcarpet' values are provided for the :owner
# and :repo parameters in the path while :state is passed in the query string.
api="https://api.github.com/repos/${user}/${repo}"
# Parameter: "?per_page" 30 items on a page by default, 100 max.
# We request multiple "?page=1", "?page=2", etc. and concatenate
# them into memf. The last 200 commits seem sufficient.
curl -s "${api}/commits?per_page=100&page=1" > $memf \
&& curl -s "${api}/commits?per_page=100&page=2" >> $memf \
|| die "No connection to GitHub API using curl." 115
case "$format" in
# Message format adds newlines for text display, and provides URL/sha.
-m) grep -E '^ "sha":|"message":' $memf \
| sed -e 's/^ *//' -e 's/,$//' -e 's/"//g' \
-e "s/^message: //" -e "s/\\\n/\n/g" -e "s/\\\r//g" \
-e "s;^sha: ;---\nhttps://github.com/${user}/${repo}/commit/;" \
| $pager ;;
# Concise format includes author and committer, with respective dates.
-c) grep -E '^ "sha":|"login":|"date":|"message":' $memf \
| sed -e 's/^ *//' -e 's/,$//' -e 's/"//g' \
-e "s;^sha: ;---\nhttps://github.com/${user}/${repo}/commit/;" \
| $pager ;;
# CATCH-ALL is VERBOSE -v format.
*) $pager $memf ;;
esac
# __________ Notes on concise format
# Commit identifier "sha" of parents will not be shown.
# Commit "sha" is converted to URL. Too many "html_url" json fields.
# Double "date" and "login": first for author, second for committer.
# Username web-flow is GitHub, i.e. its web interface.
# Add "---" between commits for paragraph effect.
# Sample concise format, still with json crud, before sed edits:
# [Double labels: first, author; second, committer.]
#
# "sha": "ddf71eff5c9752b2b9866756bac48b8307f58d5c",
# "date": "2018-01-11T13:56:14Z"
# "date": "2018-01-11T13:56:14Z"
# "message": "Merge pull request #441 from bashtage/update-travis",
# "login": "bashtage",
# "login": "web-flow",
# "sha": "bb3f4f45f7546023ff7e9f849c3f2638453b7f52",
# "date": "2018-01-11T11:39:59Z"
# "date": "2018-01-11T11:43:49Z"
# "message": "BLD: Add versioneer to simplify versioning",
# "login": "bashtage",
# "login": "bashtage",
cleanup # Instead of: trap arg EXIT
# _______________ EOS :: END of Script ::::::::::::::::::::::::::::::::::::::::
# __________ List commits on a repository [Unused qualifiers]
#
# GET /repos/:owner/:repo/commits
#
# Parameter Type Description
# sha string SHA or branch to start listing commits from.
# Default: repo’s default branch (usually master).
# path string Only commits containing this file path will be returned.
# author string GitHub login or email address of commit author.
# since string Only commits after this date will be returned.
# In ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ.
# until string Only commits before this date will be returned.
# In ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ.
# vim: set fileencoding=utf-8 ff=unix tw=78 ai syn=sh :
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment