From 0abd26763c439dc36f399e6f0ad48e78addd2ac7 Mon Sep 17 00:00:00 2001 From: "R. Steve McKown" Date: Wed, 16 Dec 2009 16:27:39 -0700 Subject: [PATCH] git-overview walks a subtree commenting on git repos contained within. --- git-overview | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100755 git-overview diff --git a/git-overview b/git-overview new file mode 100755 index 0000000..7012705 --- /dev/null +++ b/git-overview @@ -0,0 +1,145 @@ +#!/bin/bash +# git-overview +# +# Review a filesystem subtree for git repos and show their overall state. +# Runs on the current directory if no argument is provided + +usage() +{ + [ -n "$1" ] && echo "$1" >&2 + echo "usage: $0 [directory]" >&2 + exit 1 +} + +# __gitdir accepts 0 or 1 arguments (i.e., location) +# returns location of .git repo +__gitdir () +{ + if [ -z "${1-}" ]; then + if [ -n "${__git_dir-}" ]; then + echo "$__git_dir" + elif [ -d .git ]; then + echo .git + else + git rev-parse --git-dir 2>/dev/null + fi + elif [ -d "$1/.git" ]; then + echo "$1/.git" + else + echo "$1" + fi +} + +# __git_ps1 accepts 0 or 1 arguments (i.e., format string) +# returns text to add to bash PS1 prompt (includes branch name) +__git_ps1 () +{ + local g="$(__gitdir)" + if [ -n "$g" ]; then + local r + local b + if [ -f "$g/rebase-merge/interactive" ]; then + r="|REBASE-i" + b="$(cat "$g/rebase-merge/head-name")" + elif [ -d "$g/rebase-merge" ]; then + r="|REBASE-m" + b="$(cat "$g/rebase-merge/head-name")" + else + if [ -d "$g/rebase-apply" ]; then + if [ -f "$g/rebase-apply/rebasing" ]; then + r="|REBASE" + elif [ -f "$g/rebase-apply/applying" ]; then + r="|AM" + else + r="|AM/REBASE" + fi + elif [ -f "$g/MERGE_HEAD" ]; then + r="|MERGING" + elif [ -f "$g/BISECT_LOG" ]; then + r="|BISECTING" + fi + + b="$(git symbolic-ref HEAD 2>/dev/null)" || { + + b="$( + case "${GIT_PS1_DESCRIBE_STYLE-}" in + (contains) + git describe --contains HEAD ;; + (branch) + git describe --contains --all HEAD ;; + (describe) + git describe HEAD ;; + (* | default) + git describe --exact-match HEAD ;; + esac 2>/dev/null)" || + + b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." || + b="unknown" + b="($b)" + } + fi + + local w + local i + local s + local u + local c + + if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then + if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then + c="BARE:" + else + b="GIT_DIR!" + fi + elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then + if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then + if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then + git diff --no-ext-diff --ignore-submodules \ + --quiet --exit-code || w="*" + if git rev-parse --quiet --verify HEAD >/dev/null; then + git diff-index --cached --quiet \ + --ignore-submodules HEAD -- || i="+" + else + i="#" + fi + fi + fi + if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then + git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$" + fi + + if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ]; then + if [ -n "$(git ls-files --others --exclude-standard)" ]; then + u="%" + fi + fi + fi + + if [ -n "${1-}" ]; then + printf "$1" "$c${b##refs/heads/}$w$i$s$u$r" + else + printf " (%s)" "$c${b##refs/heads/}$w$i$s$u$r" + fi + fi +} + +# MAIN + +if [ $# -eq 1 ]; then + cd "$1" || usage "Bad directory" +fi + +( +for path in $(find . -maxdepth 3 -name .git -type d); do + repo="${path/\/.git}" + ( + cd $repo + echo $repo: $(__git_ps1) + for remote in $(git remote show); do + echo " $remote:" + git remote show $remote | grep "pushes to" + done + echo + ) +done +) 2>&1 -- 2.39.2