Skip to content

Instantly share code, notes, and snippets.

@allykzam
Last active August 29, 2015 14:08
Show Gist options
  • Save allykzam/4ccb1faa70e36948d5ac to your computer and use it in GitHub Desktop.
Save allykzam/4ccb1faa70e36948d5ac to your computer and use it in GitHub Desktop.
Bash script that fetches issue descriptions from GitHub via curl and adds them into the branch listing from git.
#!/usr/bin/env bash
# To use this script, go into your GitHub account settings, go into the
# Applications section, and then under `Personal access tokens` click
# `Generate new token`. Name the token whatever you want, give it access
# to the `repo` and `public_repo` scopes (`user` and `gist` are also
# selected by default, but you don't need them for this).
#
# Take the generated token and store it in your personal .gitconfig
# (located at either ~/.gitconfig or ~/.config/git/config on OSX/*nix)
# and put it under github.access-token:
#
# [github]
# access-token = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
#
# Alternatively, you can run `git config --global github.access-token
# xxxx`, but this will leave the token in your .bash_history file.
#
# On my systems, I also set up a git alias for this script, allowing me
# to call it as `git branches`:
#
# git config --global alias.branches '!~/path/to/this/script.sh'
#
set -euo pipefail
IFS=$'\n\t'
# Default values for arguments
user_token=""
use_cache=true
clear_cache=false
all_branches=false
verbose=false
repo_name=""
repo_owner=""
# Handle command-line arguments
while [[ "${1:-}" = -* ]]; do
arg="$1"; shift
case "$arg" in
--token)
user_token="$1"
shift
;;
--clear-cache)
clear_cache=true
;;
--no-cache)
use_cache=false
;;
-a)
all_branches=true
;;
--all)
all_branches=true
;;
-v)
verbose=true
;;
--verbose)
verbose=true
;;
esac
done
rate_limit_remaining=""
cached_issues=""
fetched_issues=""
unknown_issues=""
colors_needed=true
local_branch=""
remote_branch=""
current_branch=""
no_color=`echo -e "\033[0m"`
function colorBranchData {
if $colors_needed ; then
colors_needed=false
local_branch=`git config --get-color color.branch.local white`
remote_branch=`git config --get-color color.branch.remote red`
current_branch=`git config --get-color color.branch.current green`
fi
if `echo "$1" | grep remotes/ | grep \\\-\> > /dev/null` ; then
head=`echo "$1" | sed 's/ \->.\{1,\}//'`
tail=`echo "$1" | sed 's/.\{1,\}\-> //'`
echo "$remote_branch$head$no_color -> $tail"
elif `echo "$1" | grep remotes/ > /dev/null` ; then
echo "$remote_branch$1$no_color$2"
elif `echo "$1" | grep ^\* > /dev/null` ; then
no_star="${1:1}"
echo "$no_color*$current_branch$no_star$no_color$2"
else
echo "$local_branch$1$no_color$2"
fi
}
# Gets information about an issue number from GitHub's API
function getGitHubDesc {
issue_number=$1
user_token=$2
branch_name=$3
# Use curl to get the issue's information
issue_json="$(curl -s --include https://api.github.com/repos/$repo_owner/$repo_name/issues/$issue_number?access_token=$user_token)"
# grep the contents for the title line
set +e
title_line=`echo "$issue_json" | grep \"title\":\ \"`
grep_code=$?
set -e
# If grep couldn't find the title line, return the original text
if [ $grep_code -ne 0 ]; then
echo "$branch_nane"
else
issue_title=`echo "$title_line" | grep '^\ \{1,\}\"title\":\ \"' | sed 's/^ *\"title\": \"//' | sed 's/\",$//'`
echo "$issue_title" > "$git_dir/issues/$issue_number"
colorBranchData "$branch_name" ": (\"$issue_title\")"
fi
# Capture rate limit remaining count
rate_limit_remaining=`echo "$issue_json" | grep '^X-RateLimit-Remaining'` || true
# Do extra stuff when verbose is enabled
if $verbose ; then
if [ $grep_code -eq 0 ]; then
[[ "$fetched_issues" == "" ]] && fetched_issues="$issue_number" || fetched_issues="$fetched_issues, $issue_number"
else
[[ "$unknown_issues" == "" ]] && unknown_issues="$issue_number" || unknown_issues="$unknown_issues, $issue_number"
fi
fi
}
# Finds an issue's description
function getIssueDesc {
if $use_cache ; then
if [ -s "$git_dir/issues/$1" ]; then
desc=`cat "$git_dir/issues/$1"`
colorBranchData "$3" " :(\"$desc\")"
# Do extra stuff when verbose is enabled
if $verbose ; then
[[ "$cached_issues" == "" ]] && cached_issues="$issue_number" || cached_issues="$cached_issues, $issue_number"
fi
else
getGitHubDesc "$1" "$2" "$3"
fi
else
getGitHubDesc "$1" "$2" "$3"
fi
}
# Get .git directory, or exit on failure
git_dir=`git rev-parse --git-dir` || exit
# Check to see if the description cache exists, create it if it doesn't
[[ -d "$git_dir/issues" ]] || mkdir "$git_dir/issues"
# Clean out old cached descriptions
if $clear_cache ; then
find "$git_dir/issues" -type f -exec rm {} \;
else
find "$git_dir/issues" -type f -mtime +2 -exec rm {} \;
fi
# See if there are any remote URLs for GitHub
set +e
remote_url=`git config --list | grep remote | grep url | grep github | head`
grep_code=$?
set -e
# Error out with message to use if no GitHub remote URLs found
if [ $grep_code -ne 0 ]; then
>&2 echo "Current repository does not appear to have an associated GitHub remote"
>&2 echo "A GitHub remote is required for fetching GitHub Issues information"
exit 1
fi
# Clean and split the remote URL
clean_repo=`echo "$remote_url" | sed 's/.\{1,\}github\.com[\\\/:]//g' | sed 's/\.git//g'`
repo_owner=`echo "$clean_repo" | sed 's/[\\\/].\{0,\}//g'`
repo_name=`echo "$clean_repo" | sed 's/[^\\\/]\{0,\}[\\\/]//g'`
# Get the user's GitHub access token
if [ "$user_token" == "" ]; then
# The "|| true" keeps `git config` from erroring out this script
# when the setting doesn't exist; there's specific handling for
# empty token values below.
user_token=`git config --get github.access-token` || true
fi
# Error out with message to user if no access token was found
if [ "$user_token" == "" ]; then
>&2 echo "No GitHub access token has been specified."
>&2 echo "Please create one with repo access and put it in your"
>&2 echo "personal git config file at github.access-token"
exit 1
fi
# Get the current branches
if $all_branches ; then
branches=`git branch -a`
else
branches=`git branch`
fi
# Loop through all branches
for branch in $branches; do
# This command will fail if the current branch doesn't match the
# expected format
set +e
temp=`echo "$branch" | grep "[0-9]\{1,\}$"`
grep_code=$?
set -e
# Just output the branch name if it doesn't end with numbers
if [ $grep_code -ne 0 ]; then
colorBranchData "$branch" ""
else
# Split out numbers
issue_number=`echo "$branch" | sed 's/[^[:digit:]]*\([[:digit:]]\{1,\}$\)/\\1/'`
getIssueDesc "$issue_number" "$user_token" "$branch"
fi
done
if $verbose ; then
echo ""
[[ "$rate_limit_remaining" == "" ]] && echo "GitHub API Status: API Not Used" || echo "GitHub API Status: $rate_limit_remaining"
echo ""
echo "Issue results from:"
[[ "$cached_issues" == "" ]] && echo " Cache : None" || echo " Cache : $cached_issues"
[[ "$fetched_issues" == "" ]] && echo "API-Requested : None" || echo "API-Requested : $fetched_issues"
[[ "$unknown_issues" == "" ]] && echo " API-Unknown : None" || echo " API-Unknown : $unknown_issues"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment