Update whatsdirty
This commit is contained in:
204
whatsdirty
204
whatsdirty
@@ -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"
|
||||
}
|
||||
|
Reference in New Issue
Block a user