Update whatsdirty
Some checks failed
Build-Test-Publish / build (linux/amd64) (push) Failing after 8s
Build-Test-Publish / build (linux/arm64) (push) Failing after 7s

This commit is contained in:
2025-09-30 13:23:54 +13:00
parent 4904d0fc6b
commit 74731173c4

View File

@@ -6,6 +6,8 @@
# Configuration
CONFIG_FILE="$HOME/.config/whatsdirty.conf"
RED='\033[0;31m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# === Configuration Management Functions ===
@@ -57,6 +59,46 @@ handle_directory_argument() {
# === Git Repository Functions ===
fetch_remote_status() {
# Fetch remote updates without merging
# Using -q for quiet mode, timeout for hung connections
timeout 5 git fetch --all --quiet 2>/dev/null || true
}
check_upstream_status() {
local current_branch
current_branch=$(git branch --show-current 2>/dev/null)
if [ -z "$current_branch" ]; then
echo "DETACHED|0|0"
return
fi
# Check if branch has upstream configured
local upstream
upstream=$(git rev-parse --abbrev-ref "@{upstream}" 2>/dev/null)
if [ -z "$upstream" ]; then
echo "NO_UPSTREAM|0|0"
return
fi
# Count commits ahead and behind
local ahead behind
ahead=$(git rev-list --count "@{upstream}..HEAD" 2>/dev/null || echo "0")
behind=$(git rev-list --count "HEAD..@{upstream}" 2>/dev/null || echo "0")
if [ "$behind" -gt 0 ] && [ "$ahead" -gt 0 ]; then
echo "DIVERGED|$ahead|$behind"
elif [ "$behind" -gt 0 ]; then
echo "BEHIND|$ahead|$behind"
elif [ "$ahead" -gt 0 ]; then
echo "AHEAD|$ahead|$behind"
else
echo "UP_TO_DATE|0|0"
fi
}
get_last_commit_hours() {
local last_commit_timestamp
last_commit_timestamp=$(git log -1 --format="%ct" 2>/dev/null)
@@ -131,7 +173,7 @@ analyze_repository() {
local repo_path="$1"
local base_dir="$2"
local repo_name
# Calculate relative path from base directory
if [ -n "$base_dir" ]; then
repo_name=$(realpath --relative-to="$base_dir" "$repo_path" 2>/dev/null)
@@ -142,16 +184,25 @@ analyze_repository() {
else
repo_name=$(basename "$repo_path")
fi
cd "$repo_path" || return 1
# Fetch remote updates first
fetch_remote_status
# Check upstream status
local upstream_info
upstream_info=$(check_upstream_status)
local upstream_status upstream_ahead upstream_behind
IFS='|' read -r upstream_status upstream_ahead upstream_behind <<< "$upstream_info"
# Get commit info
local hours_ago
hours_ago=$(get_last_commit_hours)
local hours_num
local hours_label
local hours_formatted
if [ -n "$hours_ago" ]; then
hours_num="$hours_ago"
hours_label="hours"
@@ -161,35 +212,152 @@ analyze_repository() {
hours_label="commits"
hours_formatted=$(printf "%8s %-7s" "No" "$hours_label")
fi
# Count changes
local total_changes
total_changes=$(count_git_changes)
# Determine status and collect data
if [ "$total_changes" -eq 0 ]; then
echo "C|${hours_num}|${total_changes}|${repo_name}|${hours_formatted}"
echo "C|${hours_num}|${total_changes}|${repo_name}|${hours_formatted}|${upstream_status}|${upstream_ahead}|${upstream_behind}"
else
local changed_files
changed_files=$(get_changed_files_list)
echo "D|${hours_num}|${total_changes}|${repo_name}|${hours_formatted}|||${changed_files}"
echo "D|${hours_num}|${total_changes}|${repo_name}|${hours_formatted}|${upstream_status}|${upstream_ahead}|${upstream_behind}|||${changed_files}"
fi
}
# === Output Formatting Functions ===
format_upstream_status() {
local upstream_status="$1"
local ahead="$2"
local behind="$3"
case "$upstream_status" in
"BEHIND")
echo "${YELLOW}↓${behind}${NC}"
;;
"AHEAD")
echo "${BLUE}↑${ahead}${NC}"
;;
"DIVERGED")
echo "${RED}↑${ahead}↓${behind}${NC}"
;;
"UP_TO_DATE")
echo "✓"
;;
"NO_UPSTREAM")
echo "--"
;;
"DETACHED")
echo "DET"
;;
*)
echo "?"
;;
esac
}
print_summary() {
local temp_file="$1"
local total_dirty total_clean total_behind total_ahead total_diverged
total_dirty=$(grep -c "^D|" "$temp_file" 2>/dev/null || echo 0)
total_clean=$(grep -c "^C|" "$temp_file" 2>/dev/null || echo 0)
# Count upstream statuses
total_behind=0
total_ahead=0
total_diverged=0
while IFS='|' read -r type _ _ _ _ upstream_status _ _; do
case "$upstream_status" in
"BEHIND") ((total_behind++)) ;;
"AHEAD") ((total_ahead++)) ;;
"DIVERGED") ((total_diverged++)) ;;
esac
done < "$temp_file"
# Print summary
echo "=== SUMMARY ==="
echo "Total repositories: $((total_dirty + total_clean))"
if [ "$total_dirty" -gt 0 ]; then
printf "${RED}Dirty: $total_dirty${NC}"
else
printf "Dirty: 0"
fi
echo " | Clean: $total_clean"
if [ "$total_behind" -gt 0 ] || [ "$total_diverged" -gt 0 ]; then
printf "${YELLOW}Needs pull: $((total_behind + total_diverged))${NC}"
if [ "$total_behind" -gt 0 ]; then
printf " (${YELLOW}Behind: $total_behind${NC}"
if [ "$total_diverged" -gt 0 ]; then
printf ", ${RED}Diverged: $total_diverged${NC}"
fi
printf ")"
elif [ "$total_diverged" -gt 0 ]; then
printf " (${RED}Diverged: $total_diverged${NC})"
fi
echo ""
fi
if [ "$total_ahead" -gt 0 ]; then
printf "${BLUE}Ahead: $total_ahead${NC} (can push)\n"
fi
echo ""
}
print_header() {
printf "%-40s %15s %-10s %-10s\n" "Repository" "Last Commit" "Changes" "Status"
printf "%-40s %15s %-10s %-10s\n" "----------" "(hours)" "-------" "------"
printf "%-40s %15s %-10s %-10s %-12s\n" "Repository" "Last Commit" "Changes" "Status" "Upstream"
printf "%-40s %15s %-10s %-10s %-12s\n" "----------" "(hours)" "-------" "------" "--------"
}
print_repos_needing_pull() {
local temp_file="$1"
local needs_pull=false
# Check if any repos need pulling
while IFS='|' read -r type _ _ repo _ upstream_status upstream_ahead upstream_behind rest; do
if [ "$upstream_status" = "BEHIND" ] || [ "$upstream_status" = "DIVERGED" ]; then
needs_pull=true
break
fi
done < "$temp_file"
if [ "$needs_pull" = true ]; then
printf "\n${YELLOW}=== REPOSITORIES NEEDING PULL ===${NC}\n\n"
# Sort by number of commits behind
while IFS='|' read -r type _ changes repo hours_fmt upstream_status upstream_ahead upstream_behind rest; do
if [ "$upstream_status" = "BEHIND" ] || [ "$upstream_status" = "DIVERGED" ]; then
local upstream_fmt
upstream_fmt=$(format_upstream_status "$upstream_status" "$upstream_ahead" "$upstream_behind")
local status_color=""
local status_text="Clean"
if [ "$type" = "D" ]; then
status_color="${RED}"
status_text="Dirty"
fi
printf "%-40s %15s %-10s ${status_color}%-10s${NC} %-12b\n" "$repo" "$hours_fmt" "$changes" "$status_text" "$upstream_fmt"
fi
done < "$temp_file" | sort -t'|' -k8,8nr
fi
}
print_dirty_repositories() {
local temp_file="$1"
if grep -q "^D|" "$temp_file" 2>/dev/null; then
printf "\n=== DIRTY REPOSITORIES ===\n\n"
grep "^D|" "$temp_file" | sort -t'|' -k3,3nr | while IFS='|' read -r _ _ changes repo hours_fmt _ file_list; do
printf "%-40s %15s ${RED}%-10s${NC} ${RED}%-10s${NC}\n" "$repo" "$hours_fmt" "$changes" "Dirty"
grep "^D|" "$temp_file" | sort -t'|' -k3,3nr | while IFS='|' read -r _ _ changes repo hours_fmt upstream_status upstream_ahead upstream_behind _ file_list; do
local upstream_fmt
upstream_fmt=$(format_upstream_status "$upstream_status" "$upstream_ahead" "$upstream_behind")
printf "%-40s %15s ${RED}%-10s${NC} ${RED}%-10s${NC} %-12b\n" "$repo" "$hours_fmt" "$changes" "Dirty" "$upstream_fmt"
if [ -n "$file_list" ]; then
echo -e "$file_list"
fi
@@ -199,11 +367,13 @@ print_dirty_repositories() {
print_clean_repositories() {
local temp_file="$1"
if grep -q "^C|" "$temp_file" 2>/dev/null; then
printf "\n=== CLEAN REPOSITORIES ===\n\n"
grep "^C|" "$temp_file" | sort -t'|' -k2,2n | while IFS='|' read -r _ _ changes repo hours_fmt; do
printf "%-40s %15s %-10s %-10s\n" "$repo" "$hours_fmt" "$changes" "Clean"
grep "^C|" "$temp_file" | sort -t'|' -k2,2n | while IFS='|' read -r _ _ changes repo hours_fmt upstream_status upstream_ahead upstream_behind; do
local upstream_fmt
upstream_fmt=$(format_upstream_status "$upstream_status" "$upstream_ahead" "$upstream_behind")
printf "%-40s %15s %-10s %-10s %-12b\n" "$repo" "$hours_fmt" "$changes" "Clean" "$upstream_fmt"
done
fi
}
@@ -253,7 +423,9 @@ main() {
scan_repositories "$DIR" "$TEMP_FILE"
# Display results
print_summary "$TEMP_FILE"
print_header
print_repos_needing_pull "$TEMP_FILE"
print_dirty_repositories "$TEMP_FILE"
print_clean_repositories "$TEMP_FILE"
}