Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I've tried to write a bash script that gives me a general overview of the status of git repos I have cloned/created. It's not meant to replace git status by any means, but give an overview of several repos.

Keep in mind I'm not the most knowledgeable about bash scripting AND git, so I imagine there is a better way to do this:

#!/bin/bash
# Help from: http://www.leancrew.com/all-this/2010/12/batch-comparison-of-git-repositories/

index=0
gitrepos=()

#TODO: There has got to be a better way to add all these folders to the array
#add repos folder
for d in ~/repos/*; do
    gitrepos[(index+=1)]="$d"
done

#add other important folders
gitrepos[(index+=1)]=~/.vim
gitrepos[(index+=1)]=~/dot_files
gitrepos[(index+=1)]=~/bin

for d in "${gitrepos[@]}"; do
    if [ -e $d ]; then
        cd $d
    else
        echo " Did not find repo: $d"
        continue
    fi

    reponame="`basename $d`"

    ok=true
    git fetch --quiet origin 2>/dev/null
    if [ ! -z "`git diff HEAD origin/HEAD 2> /dev/null`" ]; then
        echo " $reponame --> Out of sync with origin/HEAD"
        ok=false
    fi
    if [ ! -z "`git ls-files --other --exclude-standard 2> /dev/null`" ]; then
        echo " $reponame --> Untracked files present"
        ok=false
    fi
    if [ ! -z "`git diff --cached --shortstat 2> /dev/null`" ]; then
        echo " $reponame --> Changes to be committed"
        ok=false
    fi
    if [ ! -z "`git diff --shortstat 2> /dev/null`" ]; then
        echo " $reponame --> Changes to be staged/committed"
        ok=false
    fi
    if $ok; then
        echo " OK --> $reponame"
    fi
done
share|improve this question
    
Have you tried fgit? It's served me well for years. Disclaimer: I'm the author. –  l0b0 Apr 3 '13 at 11:48

1 Answer 1

up vote 3 down vote accepted

Yes there is a better way of filling an array. You can use globbing inside of array parens. Also I suggest being explicit about what you do in bash and use declare -a to declare arrays and later on declare for other variables

declare -a repos=(~/repos/* ~/.vim ~/dot_files ~/bin)

In case of adding stuff to an array, after it got created:

repos+=("more stuff" here)

Maybe you want to name you iterating variable more verbose, instead of d repodir or something.

Your first if contains a continue so you can emphasize on this one and just go on with no else. Also don't miss the double quotes in case of directory names with spaces in them. Also you should check for -d since you cd into it.

if [ -d "$d" ]; then
  echo "No repo at $d"
  continue
fi
cd "$d"

[ ! -z "`cmd`" ] is more verbose than it needs to be. You can just do [ "`cmd`" ].

Read the "Arrays" chapter in the bash manpage.

I attach my test file for this answer which also shows functions and some refactoring which allows to discard this ok variable.

#!/bin/bash
main() {
    local -a repos=(* /foo/bar)
    echo -e "repos: ${repos[@]}"
    for path in "${repos[@]}"; do
      check_repo "$path"
    done
}

check_repo() {
    local path="$1"
    local name="`basename "$path"`"
    local report=""
    if [ ! -d "$path" ]; then
      echo -e "$name\n not a directory: $path"
      return
    fi
    cd "$path"
    if [ "`echo foo 2> /dev/null`" ]; then
        report+="\n oh oh"
    fi
    cd - > /dev/null
    if [ -z "$report" ]; then
        report+="\n OK"
    fi
    echo -e "$name$report"
}

main
share|improve this answer
    
Thanks for your comments! They have taught me quite a lot about bash. –  lawrensm Feb 19 '13 at 5:08
    
Me too. Never have read "Arrays" before. –  payload Feb 19 '13 at 17:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.