Skip to content

Commit

Permalink
Better branch functions
Browse files Browse the repository at this point in the history
  • Loading branch information
shadoath committed May 10, 2024
1 parent 5248d95 commit 82da0b8
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 0 deletions.
137 changes: 137 additions & 0 deletions include/better-git-branch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#!/usr/bin/env bash

# Inspired by: https://gist.github.com/schacon/e9e743dee2e92db9a464619b99e94eff
# https://www.youtube.com/watch?v=aolI_Rz0ZqY
# This version available from: https://gist.github.com/adamcrews/b39f7db45b920281942c179a4882fb18
# Install by copying this script to some local directory then add an alias to git:
# git config --global alias.bb '!~/dot_files/include/better-git-branch.sh'


# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[0;33m'
PURPLE='\033[0;35m'
NO_COLOR='\033[0m'

# Function to count commits
count_commits() {
local branch="$1"
local base_branch="$2"
local ahead_behind

ahead_behind=$(git rev-list --left-right --count "$base_branch"..."$branch")
echo "$ahead_behind"
}

dashes() {
local length="$1"
printf '%*s' "$length" | tr ' ' '-'
}

format_string="%(objectname:short)@%(refname:short)@%(committerdate:relative)"
readarray -t branches_data < <(git for-each-ref --sort=-authordate --format="$format_string" refs/heads/)

# Main script
main_branch=$(git rev-parse --abbrev-ref HEAD)

# Find field lengths
ahead_width=5
behind_width=6
url_width=5
max_branch_width=0
max_age_width=0
max_desc_width=0
desc_found=false
for branch_data in "${branches_data[@]}"; do
IFS='@' read -r sha branch age <<<"$branch_data"
if [ "$branch" != "$main_branch" ]; then
description=$(git config branch."$branch".description)
if [ -n "$description" ]; then
desc_found=true
IFS=$'\n' readarray -t d_lines <<<"$description"
for d in "${d_lines[@]}"; do
max_desc_width=$((max_desc_width > ${#d} ? max_desc_width : ${#d}))
done
fi

max_branch_width=$((max_branch_width > ${#branch} ? max_branch_width : ${#branch}))
max_age_width=$((max_age_width > ${#age} ? max_age_width : ${#age}))
fi
done

# Header and separator with conditional Description field
header_format="${GREEN}%-${ahead_width}s ${RED}%-${behind_width}s ${BLUE}%-${max_branch_width}s ${YELLOW}%-${max_age_width}s ${PURPLE}%-${url_width}s"
separator_format="${GREEN}%-${ahead_width}s ${RED}%-${behind_width}s ${BLUE}%-${max_branch_width}s ${YELLOW}%-${max_age_width}s ${PURPLE}%-${url_width}s"
if $desc_found; then
header_format+=" ${NO_COLOR}%-${max_desc_width}s"
separator_format+=" ${NO_COLOR}%-${max_desc_width}s"
printf "$header_format\n" "Ahead" "Behind" "Branch" "Last Commit" "PR #" "Description"
printf "$separator_format\n" "$(dashes $ahead_width)" "$(dashes $behind_width)" "$(dashes $max_branch_width)" "$(dashes $max_age_width)" "$(dashes $url_width)" "$(dashes $max_desc_width)"
else
printf "$header_format\n" "Ahead" "Behind" "Branch" "Last Commit" "PR #"
printf "$separator_format\n" "$(dashes $ahead_width)" "$(dashes $behind_width)" "$(dashes $max_branch_width)" "$(dashes $max_age_width)" "$(dashes $url_width)"
fi

IFS=$'\n'

#url escape chars
url_start=$'\e]8;;'
url_sep=$'\e\\'
url_end=$'\e]8;;\e\\'

for branch_data in "${branches_data[@]}"; do
IFS='@' read -r sha branch age <<<"$branch_data"
link=""
if [ "$branch" != "$main_branch" ]; then
# Get branch description
description=$(git config branch."$branch".description | sed 's/\n/\n/g') # Make sure actual newlines are present

# Count commits ahead and behind
ahead_behind=$(count_commits "$sha" "$main_branch")
ahead=$(echo "$ahead_behind" | cut -f2)
behind=$(echo "$ahead_behind" | cut -f1)

info_format="${GREEN}%-${ahead_width}s ${RED}%-${behind_width}s ${BLUE}%-${max_branch_width}s ${YELLOW}%-${max_age_width}s"
readarray -t pr_info < <(gh pr view --json url,number,state --jq '.url, .number, .state' $branch 2>/dev/null)
if [ -n "${pr_info[0]}" ]; then
case "${pr_info[2]}" in
'MERGED')
info_format+=" ${PURPLE}%-${url_width}s" ;;
'OPEN')
info_format+=" ${GREEN}%-${url_width}s" ;;
*)
# Catch 'CLOSED' and anything else
info_format+=" ${RED}%-${url_width}s" ;;
esac
link+="#${url_start}${pr_info[0]}${url_sep}${pr_info[1]}${url_end}"
else
info_format+=" ${NO_COLOR}%-${url_width}s"
fi

if [ -n "$description" ]; then
# Read description into an array by lines
IFS=$'\n' read -d '' -ra description_lines <<<"$description"

# Print the first line with proper formatting
info_format+=" ${NO_COLOR}%-${max_desc_width}s"
printf "$info_format\n" "$ahead" "$behind" "$branch" "$age" "$link" "${description_lines[0]}"

# Handle additional lines if they exist
if [ "${#description_lines[@]}" -gt 1 ]; then
indent=$((ahead_width + behind_width + max_branch_width + max_age_width + url_width + 5)) # 5 spaces for each color code
description_indent=$((indent - 1)) # One less since we don't want to count the first space

# Loop through the remaining lines and print them with indentation
for i in "${!description_lines[@]}"; do
if [ $i -ne 0 ]; then # Skip first line, as it is already printed
printf "%${description_indent}s %s\n" " " "${description_lines[i]}"
fi
done
fi
else
printf "$info_format\n" "$ahead" "$behind" "$branch" "$age" "$link"
fi
fi
done
57 changes: 57 additions & 0 deletions include/functions.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,60 @@ if [ $HOST=='mbp-42' ]
then
alias ssh=color-ssh
fi

better-branch() {

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
NO_COLOR='\033[0m'
BLUE='\033[0;34m'
YELLOW='\033[0;33m'
NO_COLOR='\033[0m'

width1=5
width2=6
width3=30
width4=20
width5=40

# Function to count commits
count_commits() {
local branch="$1"
local base_branch="$2"
local ahead_behind

ahead_behind=$(git rev-list --left-right --count "$base_branch"..."$branch")
echo "$ahead_behind"
}

# Main script
main_branch=$(git rev-parse HEAD)

printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" "Ahead" "Behind" "Branch" "Last Commit" " "

# Separator line for clarity
printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" "-----" "------" "------------------------------" "-------------------" " "


format_string="%(objectname:short)@%(refname:short)@%(committerdate:relative)"
IFS=$'\n'

for branchdata in $(git for-each-ref --sort=-authordate --format="$format_string" refs/heads/ --no-merged); do
sha=$(echo "$branchdata" | cut -d '@' -f1)
branch=$(echo "$branchdata" | cut -d '@' -f2)
time=$(echo "$branchdata" | cut -d '@' -f3)
if [ "$branch" != "$main_branch" ]; then
# Get branch description
description=$(git config branch."$branch".description)

# Count commits ahead and behind
ahead_behind=$(count_commits "$sha" "$main_branch")
ahead=$(echo "$ahead_behind" | cut -f2)
behind=$(echo "$ahead_behind" | cut -f1)

# Display branch info
printf "${GREEN}%-${width1}s ${RED}%-${width2}s ${BLUE}%-${width3}s ${YELLOW}%-${width4}s ${NO_COLOR}%-${width5}s\n" $ahead $behind $branch "$time" "$description"
fi
done
}

0 comments on commit 82da0b8

Please sign in to comment.