4 # for sending emails (-a option)
5 ADMINS="Thierry.Parmentelat@inria.fr baris@metin.org"
6 # the other end of the mirror (-r option)
7 REMOTE_GIT="git://git.planet-lab.org"
11 # local path to the reference (bare) repos
13 # local path to the working repos; can be trashed if needed
14 LOCAL_MIRROR_DIR="/git-mirror"
15 # a file in each repo to avoid too many notifications
16 NOTIFIED_FILE="NOTIFIED_ADMINS"
17 # global stamp to avoid multiple instances of this script
18 RUNNING_FILE=$LOCAL_MIRROR_DIR/RUNNING_MIRROR
19 # global list - errors to report
23 [ -n "$QUIET" ] || echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "$@"
27 msg "Received signal - cleaning up $RUNNING_FILE and aborting"
34 local SUBJECT=$1; shift
38 [ -f $REPO/$NOTIFIED_FILE ] && return
40 for admin in $ADMINS; do
41 echo -e "$BODY" | mail -s "$SUBJECT" $admin
43 touch $REPO/$NOTIFIED_FILE
46 # run directory command
47 # -or- to ignore errors
48 # run -i directory "command"
51 case "$1" in -i) IGNORE=true ; shift ;; esac
55 pushd ${REPO} > /dev/null
56 # quiet mode: record stdout and err for the mail
58 if [ -n "$QUIET" ] ; then
59 OUTPUT=$($COMMAND 2>&1) || ok=
60 TORECORD="[$REPO] $OUTPUT"
62 echo "[$REPO] Running $COMMAND"
68 # let's record the failure unless ignore is set
69 if [ -z "$IGNORE" ] ; then
70 FAILED_CMDS=("${FAILED_CMDS[@]}" "$TORECORD")
76 function merge_all_branches () {
77 local REPO_DIR=$1; shift
79 local REMOTE=$1; shift
81 pushd $REPO_DIR > /dev/null
82 BRANCHES=$(git branch -r | grep $REMOTE | grep -v HEAD | sed "s/.*\///g" | grep -v master)
85 run ${REPO_DIR} git checkout master
86 run ${REPO_DIR} git merge --ff $REMOTE/master
87 for BRANCH in $BRANCHES ; do
88 run -i ${REPO_DIR} git branch $BRANCH $REMOTE/$BRANCH
89 run ${REPO_DIR} git checkout $BRANCH
90 run ${REPO_DIR} git merge --ff $REMOTE/$BRANCH
94 function push_all_branches () {
95 local REPO_DIR=$1; shift
97 local PUSH_TO=$1; shift
98 local PUSH_FROM=$1; shift
100 pushd $REPO_DIR > /dev/null
101 BRANCHES=$(git branch -r | grep $PUSH_FROM | grep -v HEAD | sed "s/.*\///g" | grep -v master)
104 run ${REPO_DIR} git push $PUSH_TO master:master
105 for BRANCH in $BRANCHES ; do
106 run ${REPO_DIR} git push $PUSH_TO $BRANCH:$BRANCH
110 function mirror_repo () {
112 FAILED_CMDS=() # reset previous failure if any
114 NAME=$(basename ${repo} ".git")
116 REPO_DIR=${LOCAL_MIRROR_DIR}/${NAME}
117 REMOTE_REPO=${REMOTE_GIT}/${GIT_NAME}
118 MASTER_REPO=${MASTER_GIT}/${GIT_NAME}
121 # if there is no remote repository it may be that we only have
122 # the repository locally and don't need to mirror
123 git ls-remote $REMOTE_REPO &> /dev/null || return
125 if [ -d ${REPO_DIR} ] ; then
126 msg "pulling from ${NAME}"
127 run ${REPO_DIR} git fetch origin --tags
128 run ${REPO_DIR} git fetch origin
129 merge_all_branches $REPO_DIR $NAME origin
130 if [ $? -ne 0 ]; then
131 error $REPO_DIR "git-mirror.sh failed with module ${NAME}" "Can not fetch from ${MASTER_REPO}"
134 msg "mirroring ${NAME} for the first time"
135 run ${LOCAL_MIRROR_DIR} git clone ${REMOTE_REPO}
136 run ${REPO_DIR} git remote add local_master ${MASTER_REPO}
139 msg "pushing ${NAME} to local master"
140 run ${REPO_DIR} git fetch local_master --tags
141 run ${REPO_DIR} git fetch local_master
142 merge_all_branches $REPO_DIR $NAME local_master
143 if [ -n "$FAILED_CMDS" ]; then
144 pushd ${REPO_DIR} > /dev/null
145 STATUS_OUT=$(git status)
148 body="STATUS (in $REPO_DIR):\n$STATUS_OUT \n\n------------\n FAILED COMMANDS:\n"
149 for line in "${FAILED_CMDS[@]}"; do body="$body$line\n"; done
150 error $REPO_DIR "git-mirror.sh failed on with module ${NAME}" $body
152 run ${REPO_DIR} git push --tags local_master
153 push_all_branches $REPO_DIR $NAME local_master origin
155 # success, remove previous check file if any
156 rm -f $REPO_DIR/$NOTIFIED_FILE
161 echo "Usage $COMMAND [-a admin-mails] [-r remote-git-url] [-q] REPONAME*"
165 while getopts "a:r:qh" opt; do
168 r) REMOTE_GIT=$OPTARG ;;
171 \?) echo "Invalid option: -$opt" >&2 ;;
175 # is the stamp older than an hour ?
178 is_old=$(find $RUNNING_FILE -mmin +$GRACE 2> /dev/null)
179 if [ -n "$is_old" ] ; then
180 msg "$RUNNING_FILE is older than $GRACE minutes - removing"
184 if [ -f $RUNNING_FILE ] ; then
185 msg "Found $RUNNING_FILE - another git-mirror seems to be running. Aborting... "
193 for gitrepo in "$@"; do mirror_repo $gitrepo ; done