Last active
August 29, 2015 14:08
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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