diff --git a/gitpuller.sh b/gitpuller.sh new file mode 100644 index 0000000..9e020b4 --- /dev/null +++ b/gitpuller.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +# ... +# shellcheck disable=2317,2059 +# created: 20240515 +# purpose: automatic git pull of repos +# author: afinet +# +# update: 20240620 +# purpose: progress bar + +local_repository_folder=$HOME"/GIT-LAB/" + +# Array of git repositories +REPOS=($(find $local_repository_folder -name ".git" -type d)) +# Lenght of the array +PULL_ITER=${#REPOS[@]} + +# Progress bar dedicated variables +# We can control how progress bar work +PROGRESS_BAR_CHAR=(█ ▒) + +# Display template +# We can control how informations is displayed +PROGRESS_BAR_INFO_TEMPLATE=' %s [%2d/%2d] ' +PROGRESS_BAR_COMPL_TEMPLATE=' %2d%% ' +PROGRESS_BAR_TEMPLATE='\033[1m%s%s\033[0m%s%s\r' + +# control which information is displayed" +PROGRESS_BAR_DISPLAY_INFO=1 +PROGRESS_BAR_DISPLAY_COMPL=1 + +puller() { + SECONDS=0 + i=1 + + for repo in ${REPOS[@]}; do + echo $repo $i + git -C $repo/.. pull > /dev/null + ((i++)) + done + duration=$SECONDS + ((i--)) + echo "[Finished] - Pulled $i/$PULL_ITER repositories in $((duration / 60)):$((duration % 60))" +} + +draw_progressbar() { + # function parameters + local -r progress=${1?"progress is mandatory"} + local -r total=${2?"total elements is mandatory"} + local -r info=${3:-"In progress"} + + # function local variables + local progress_segment + local todo_segment + local info_segment="" + local compl_segment="" + + if [[ ${PROGRESS_BAR_DISPLAY_INFO:-1} -eq 1 ]]; then + printf -v info_segment "${PROGRESS_BAR_INFO_TEMPLATE}" \ + "$info" "$progress" "$total" + fi + + local -r progress_ratio=$((progress * 100 / total)) + if [[ ${PROGRESS_BAR_DISPLAY_COMPL:-0} -eq 1 ]]; then + printf -v compl_segment "${PROGRESS_BAR_COMPL_TEMPLATE}" \ + "$progress_ratio" + fi + + # progress bar construction + # calculate each element sizes, bar must fit in ou screen + local -r bar_size=$((COLUMNS - ${#info_segment} - ${#compl_segment})) + local -r progress_segment_size=$((bar_size * progress_ratio / 100)) + local -r todo_segment_size=$((bar_size - progress_segment_size)) + printf -v progress_segment "%${progress_segment_size}s" "" + printf -v todo_segment "%${todo_segment_size}s" "" + + printf >&2 "$PROGRESS_BAR_TEMPLATE" \ + "$info_segment" \ + "${progress_segment// /${PROGRESS_BAR_CHAR[0]}}" \ + "${todo_segment// /${PROGRESS_BAR_CHAR[1]}}" \ + "$compl_segment" + +} + +parse_output() { + # trap if shell column count change + trap change_column_size WINCH + # while puller() echoes + while read -r line; do + if [[ "$line" =~ ^/ ]];then + current_repo=$(echo $line | cut -d " " -f 1 | cut -d "/" -f 5-7 | sed 's/\//::/g') + iteration=$(echo $line | cut -d " " -f 2) + printf -v info "Pulling %-35s %s" $current_repo + draw_progressbar \ + "$iteration" \ + "$PULL_ITER" \ + "$info" + elif [[ "$line" =~ Finished ]]; then + printf >&2 "\033[0K\r" + printf "%s\n" "$line" + fi + done +} + +change_column_size() { + printf >&2 "%${COLUMNS}s" "" + printf >&2 "\033[0K\r" + COLUMNS=$(tput cols) +} + +main() { + COLUMNS=$(tput cols) + puller > >(parse_output) +} + +main +exit 0