diff --git a/README.md b/README.md index 5f2345d..6d91f21 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,18 @@ -# git-my v0.1 +# git-my v0.3.0 -> Lists (stale) (branches|tags) in the remote named (origin) (where you were -> the last committer) +> Lists a user's remote branches and shows if it was merged and/or available +> locally [Homepage](https://github.com/davidosomething/git-my) ## About -Unlike `git branch -r` this shows only YOUR branches. +Unlike `git branch -r` and `git remote show origin` this shows only branches +where YOU were the last committer and it will tell you if you have a copy of +that branch locally. + +Here's a screenshot: +![Example output](https://raw.githubusercontent.com/davidosomething/git-my/docs/git-my/screenshot.png) ## Installation @@ -16,19 +21,27 @@ Unlike `git branch -r` this shows only YOUR branches. ## Usage From command line execute: + ``` git my ``` -## TODO -- Add options: +## To do + +- Colorize output +- Options support + ``` --U|--username="gitconfig user.name" --R|--remote=origin --T|--tags --B|--branches --F|--filter=mine,stale + -v|--version + -h|--help + -d|--decorate LOCAL,MERGED + -r|--remote-ref origin/master + -U|--username + --no-color + --no-header + --no-decorate ``` -Copyright (c) 2015 David O'Trakoun + +Copyright (c) 2015 David O'Trakoun diff --git a/git-my b/git-my index d680093..56ea6d1 100755 --- a/git-my +++ b/git-my @@ -1,72 +1,189 @@ #!/usr/bin/env bash -# git-my v0.1 +# git-my v0.3.0 # -# Lists (stale) (branches|tags) in the remote named (origin) (where you were -# the last committer) +# Lists a user's remote branches and shows if it was merged +# and/or available locally # # Copyright (c) 2015 David O'Trakoun # # Usage: # git my # -# Options: -# @todo NOT IMPLEMENTED -# -U|--username="gitconfig user.name" -# -R|--remote=origin -# -T|--tags -# -B|--branches -# -F|--filter=mine,stale -# set -eu +# _check_in_repository +# +# Exits with error if not a git repository +# _check_in_repository() { git rev-parse --git-dir > /dev/null 2>&1 } -_filter_mine() { - local git_user - git_user=$(git config --get user.name) +# _get_local_branches +# +# Proper way to get a porcelain list of local branches for shell script use +# +_get_local_branches() { + local fmt + local cmd_get_local_branches - # use eval to not parse the fmt string - local my_remotes - my_remotes=$(echo "$1" | grep -i "^$git_user") - echo "$my_remotes" | awk -F'\t' '{ print $2 }' + # shellcheck disable=SC2016 + fmt=' + r=%(refname) + refname_without_prefix=${r#refs/heads/} + printf "%s\t%s\n" "$refname_without_prefix" + ' + + cmd_get_local_branches=$( + git for-each-ref --shell --format="$fmt" refs/heads + ) + + eval "$cmd_get_local_branches" } -# @TODO -_filter_stales() { - local raw_stales - raw_stales=$(git remote prune --dry-run origin) - echo "$raw_stales" -} - -_main() { - if ! _check_in_repository ; then - echo "This is not a git repository." - exit 1 - fi +# _get_everyones_remotes +# +# Get porcelain list of all remote branches +# +# @TODO support remote_name (currently origin) +# +_get_everyones_remotes() { + local fmt + local cmd_everyones_remotes # user.namebranch.name # the TAB is used as a delimiter to awk with # shellcheck disable=SC2016 - local fmt=' + fmt=' a=%(authorname) r=%(refname) - b=${r#refs/remotes/origin/} - printf "%s\t%s\n" "$a" "$b" + refname_without_prefix=${r#refs/remotes/origin/} + printf "%s\t%s\n" "$a" "$refname_without_prefix" ' - local cmd_everyones_remotes cmd_everyones_remotes=$( git for-each-ref --shell --format="$fmt" refs/remotes/origin ) - local everyones_remotes - everyones_remotes=$(eval "$cmd_everyones_remotes") - _filter_mine "$everyones_remotes" + eval "$cmd_everyones_remotes" } +# _get_merged_remote_branches +# +# @TODO support param remote_branche (currently origin/master) +# +# @output names of remote branches that are merged into origin/master +_get_merged_remote_branches() { + local remote_name + local remote_refname + local merged_remote_branches + local stripped_branchnames + + remote_name="origin" + remote_refname="master" + + merged_remote_branches=$( \ + git branch --no-color \ + --remotes \ + --merged $remote_name/$remote_refname \ + ) + + # remove "origin/" + # shellcheck disable=SC2001 + stripped_branchnames=$( \ + echo "$merged_remote_branches" | sed "s/^\s*$remote_name\///g" \ + ) + + echo "$stripped_branchnames" +} + +# _filter_mine +# +# @param git_user +# @param branchnames +# @output branchnames owned by current git user +_filter_mine() { + local git_user + local branchnames + git_user=$1 + branchnames=$2 + + # use eval to not parse the fmt string + local my_remotes + my_remotes=$(echo "$branchnames" | grep -i "^$git_user") + + # output only the branchname + echo "$my_remotes" | awk -F'\t' '{ print $2 }' +} + +# _decorate_merged +# +# @TODO support param branch to check against +# +# @param branchnames to check if merged into against +# @output branchnames with [merged] +_decorate_merged() { + local merged_remote_branches + local decorated + + merged_remote_branches=$(_get_merged_remote_branches) + local_branches=$(_get_local_branches) + + # heading + decorated=$( printf '%12s %12s %s' \ + "local copy?" "in master? " "branch name" + ) + decorated+=$'\n' + + # body + for branchname in $1 + do + local local_text="..........." + local merged_text='............' + + echo "$local_branches" | grep -q "$branchname" && \ + local_text="..[local].." + + echo "$merged_remote_branches" | grep -q "$branchname" && \ + merged_text="..[merged].." + + decorated+=$(printf "%12s.%12s %s" \ + "$local_text" "$merged_text" "$branchname" + ) + decorated+=$'\n' + done + + echo "$decorated" +} + +_main() { + local everyones_remotes + local my_remotes + local output + local git_user + local git_remote + local heading + + git_user=$(git config --get user.name) + git_remote=$(git config --get remote.origin.url) + heading="$git_user's remote branches in $git_remote" + + everyones_remotes=$(_get_everyones_remotes) + my_remotes=$(_filter_mine "$git_user" "$everyones_remotes") + output=$(_decorate_merged "$my_remotes") + + printf '+%78s+\n' | tr ' ' - + printf '| %-76s |\n' "$heading" + printf '+%78s+\n' | tr ' ' - + echo "$output" +} + +if ! _check_in_repository ; then + echo "This is not a git repository." + exit 1 +fi + _main