Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 37 additions & 9 deletions scripts/pyauto_status.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,17 @@ pyauto-status() {
wait

# Header.
local fmt='%-32s %-30s %-36s %6s %5s %5s %s\n'
printf "$fmt" REPO BRANCH UPSTREAM BEHIND AHEAD DIRTY FLAGS
local fmt='%-32s %-30s %-36s %6s %5s %4s %4s %s\n'
printf "$fmt" REPO BRANCH UPSTREAM BEHIND AHEAD MOD UNTR FLAGS
printf "$fmt" "--------------------------------" \
"------------------------------" \
"------------------------------------" \
"------" "-----" "-----" "-----"
"------" "-----" "----" "----" "-----"

# Per-repo row. All lookups are local after the fetch sweep.
local name branch upstream behind ahead dirty flags counts
# Per-repo row. Porcelain is cached so the dirty-files listing below can
# reuse it without a second `git status` per repo.
declare -A repo_porcelain
local name branch upstream behind ahead mod untr flags counts porcelain
for repo in "${repos[@]}"; do
name="$(basename "$repo")"

Expand Down Expand Up @@ -97,13 +99,39 @@ pyauto-status() {
[[ -e "$fetch_status_dir/$name" ]] && flags+="!"
fi

dirty="$(git -C "$repo" status --porcelain 2>/dev/null | wc -l | tr -d ' ')"
[[ -z "$dirty" ]] && dirty="?"
porcelain="$(git -C "$repo" status --porcelain 2>/dev/null || true)"
repo_porcelain["$name"]="$porcelain"

if [[ -z "$porcelain" ]]; then
mod=0
untr=0
else
untr="$(printf '%s\n' "$porcelain" | grep -c '^??' || true)"
mod="$(printf '%s\n' "$porcelain" | grep -cv '^??' || true)"
fi

[[ "$behind" =~ ^[0-9]+$ ]] && (( behind > 0 )) && flags+="↓"
[[ "$ahead" =~ ^[0-9]+$ ]] && (( ahead > 0 )) && flags+="↑"
[[ "$dirty" =~ ^[0-9]+$ ]] && (( dirty > 0 )) && flags+="*"
(( mod + untr > 0 )) && flags+="*"

printf "$fmt" "$name" "$branch" "$upstream" "$behind" "$ahead" "$mod" "$untr" "$flags"
done

printf "$fmt" "$name" "$branch" "$upstream" "$behind" "$ahead" "$dirty" "$flags"
# Per-repo dirty-file listing. Only repos with non-empty porcelain are
# shown — keeps the output empty when everything is clean. The `??` and
# ` M` etc. prefixes from porcelain are preserved so users can tell
# untracked from modified at a glance.
local printed_header=false
for repo in "${repos[@]}"; do
name="$(basename "$repo")"
porcelain="${repo_porcelain[$name]}"
[[ -z "$porcelain" ]] && continue
if [[ "$printed_header" == "false" ]]; then
echo ""
echo "Dirty files:"
printed_header=true
fi
echo " $name:"
printf '%s\n' "$porcelain" | sed 's/^/ /'
done
}