X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=scripts%2Fgit-mirror.sh;h=ff07de27c095397b46e85328186a36141bb72492;hb=4139609455bd92533c092a7875b7e414e801cab0;hp=2b46fdbdb664d75b4d403ef3a65686b96e89c70a;hpb=685c48b9ae54c99607073ff2763a7f713387b32f;p=infrastructure.git diff --git a/scripts/git-mirror.sh b/scripts/git-mirror.sh index 2b46fdb..ff07de2 100755 --- a/scripts/git-mirror.sh +++ b/scripts/git-mirror.sh @@ -1,75 +1,152 @@ #!/bin/bash +ADMINS="Talip-Baris.Metin@inria.fr Thierry.Parmentelat@inria.fr" MIRROR_GIT="git://git.planet-lab.org" MASTER_GIT="/git" LOCAL_MIRROR_DIR="/git-mirror" -QUIET=1 +QUIET=0 +FAILED=0 +FAILED_CMDS="" +NOTIFIED_FILE="NOTIFIED_ADMINS" +RUNNING_FILE=$LOCAL_MIRROR_DIR/RUNNING_MIRROR function msg () { - if [ $QUIET -eq 0 ] - then - echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx $1" + if [ $QUIET -eq 0 ] ; then + echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "$@" fi } function error () { - echo "[ERROR] xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx $1" - exit 1 + SUBJECT=$1 + MSG=$2 + CHECK_FILE=$3/$NOTIFIED_FILE + + if [ -f $CHECK_FILE ]; then + return + fi + + for admin in $ADMINS; do + echo -e "$MSG" | mail -s "$SUBJECT" $admin + done + touch $CHECK_FILE } function run () { - if [ $QUIET -eq 1 ] - then + if [ $QUIET -eq 1 ]; then COMMAND="$1 &> /dev/null" else COMMAND="$1" + msg $COMMAND fi REPO=$2 pushd ${REPO} > /dev/null eval $COMMAND + if [ $? -ne 0 ]; then + FAILED=1 + FAILED_CMDS="$FAILED_CMDS\n$COMMAND" + fi + popd > /dev/null +} + +function run_ignore_errors () { + OLD_FAILED=$FAILED + OLD_FAILED_CMDS=$FAILED_CMDS + run "$1" "$2" + FAILED=$OLD_FAILED + FAILED_CMDS=$OLD_FAILED_CMDS +} + +function merge_all_branches () { + NAME=$1 + REMOTE=$2 + REPO_DIR=$3 + + pushd $REPO_DIR > /dev/null + BRANCHES=$(git branch -r | grep $REMOTE | grep -v HEAD | sed "s/.*\///g" | grep -v master) popd > /dev/null + + run "git checkout master" ${REPO_DIR} + run "git merge --ff $REMOTE/master" ${REPO_DIR} + for BRANCH in $BRANCHES ; do + run_ignore_errors "git branch $BRANCH $REMOTE/$BRANCH" ${REPO_DIR} + run "git checkout $BRANCH" ${REPO_DIR} + run "git merge --ff $REMOTE/$BRANCH" ${REPO_DIR} + done +} + +function push_all_branches () { + NAME=$1 + REMOTE=$2 + REPO_DIR=$3 + + pushd $REPO_DIR > /dev/null + BRANCHES=$(git branch -r | grep $REMOTE | grep -v HEAD | sed "s/.*\///g" | grep -v master) + popd > /dev/null + + run "git push $REMOTE master:master" ${REPO_DIR} + for BRANCH in $BRANCHES ; do + run "git push $REMOTE $BRANCH:$BRANCH" ${REPO_DIR} + done } function mirror () { for arg in "$@" ; do - NAME=$(echo ${arg} | sed 's/\/$//') + FAILED=0 # reset previous failure if any + + NAME=$(basename ${arg} | sed s/.git$//g) GIT_NAME=${NAME}.git REPO_DIR=${LOCAL_MIRROR_DIR}/${NAME} MIRROR_REPO=${MIRROR_GIT}/${GIT_NAME} MASTER_REPO=${MASTER_GIT}/${GIT_NAME} - if [ -d ${REPO_DIR} ] - then - msg "pulling from ${REPO_NAME}" - run "git fetch origin --tags" ${REPO_DIR} - run "git fetch origin" ${REPO_DIR} - run "git merge origin/master" ${REPO_DIR} - if [ $? -ne 0 ] - then - error "Can not fetch from ${MASTER_REPO}" + + # if there is no remote repository it may be that we only have + # the repository locally and don't need to mirror + git ls-remote $MIRROR_REPO &> /dev/null + if [ $? -eq 0 ]; then + if [ -d ${REPO_DIR} ]; then + msg "pulling from ${NAME}" + run "git fetch origin --tags" ${REPO_DIR} + run "git fetch origin" ${REPO_DIR} + merge_all_branches $NAME origin $REPO_DIR + if [ $? -ne 0 ]; then + error "git-mirror.sh failed" "Can not fetch from ${MASTER_REPO}" $REPO_DIR + fi + else + msg "mirroring ${NAME} for the first time" + run "git clone ${MIRROR_REPO}" ${LOCAL_MIRROR_DIR} + run "git remote add local_master ${MASTER_REPO}" ${REPO_DIR} fi - else - msg "mirroring in ${REPO_NAME} for the first time" - run "git clone ${MIRROR_REPO}" ${LOCAL_MIRROR_DIR} - run "git remote add local_master ${MASTER_REPO}" ${REPO_DIR} - fi - msg "pushing ${REPO_NAME} to local master" - run "git fetch local_master --tags" ${REPO_DIR} - run "git fetch local_master" ${REPO_DIR} - run "git merge local_master/master" ${REPO_DIR} - if [ $? -ne 0 ] - then - error "Can not fetch from ${MIRROR_REPO}" - fi + msg "pushing ${NAME} to local master" + run "git fetch local_master --tags" ${REPO_DIR} + run "git fetch local_master" ${REPO_DIR} + merge_all_branches $NAME local_master $REPO_DIR + if [ $FAILED -ne 0 ]; then + pushd ${REPO_DIR} > /dev/null + STATUS_OUT=$(git status) + popd > /dev/null + error "git-mirror.sh failed on ${MIRROR_REPO}" "STATUS:\n$STATUS_OUT \n\n------------\n FAILED COMMANDS:\n$FAILED_CMDS" $REPO_DIR + else + run "git push --tags local_master" ${REPO_DIR} + push_all_branches $NAME local_master $REPO_DIR - run "git push local_master" ${REPO_DIR} - run "git push --tags local_master" ${REPO_DIR} + # success, remove previous check file if any + CHECK_FILE=$REPO_DIR/$NOTIFIED_FILE + rm -f $CHECK_FILE + fi + fi done } +function failure () { + msg "Received signal - cleaning up $RUNNING_FILE and aborting" + rm -f $RUNNING_FILE + exit 1 +} + while getopts ":hq" opt do case $opt in @@ -78,7 +155,7 @@ do break ;; h) - echo "USAGE: $0 [-q] REPONAME*" + echo "Usage: $0 [-q] REPONAME*" exit 1 ;; \?) @@ -87,6 +164,24 @@ do esac done + +# is the stamp older than an hour ? +# in minutes +GRACE=60 +is_old=$(find $RUNNING_FILE -mmin +$GRACE 2> /dev/null) +if [ -n "$is_old" ] ; then + msg "$RUNNING_FILE is older than $GRACE minutes - removing" + rm -f $RUNNING_FILE +fi + +if [ -f $RUNNING_FILE ] ; then + msg "Found $RUNNING_FILE - another git-mirror seems to be running. Aborting... " + exit 1 +fi + +trap failure ERR INT + shift $((OPTIND-1)) +date > $RUNNING_FILE mirror $@ - +rm -f $RUNNING_FILE