fbb784931e89531094ccdae37c0e96569e069ae0
[infrastructure.git] / scripts / git-mirror.sh
1 #!/bin/bash
2
3 MIRROR_GIT="git://git.planet-lab.org"
4 MASTER_GIT="/git"
5 LOCAL_MIRROR_DIR="/git-mirror"
6 QUIET=0
7
8 function msg () {
9     if [ $QUIET -eq 0 ]
10     then
11         echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx $@"
12     fi
13 }
14
15 function error () {
16     echo "[ERROR] xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx $@"
17 }
18
19 function run () {
20     if [ $QUIET -eq 1 ]
21     then
22         COMMAND="$1 &> /dev/null"
23     else
24         COMMAND="$1"
25         msg $COMMAND
26     fi
27     REPO=$2
28
29     pushd ${REPO} > /dev/null
30     eval $COMMAND
31     popd > /dev/null
32 }
33
34 function merge_all_branches () {
35     NAME=$1
36     REMOTE=$2
37     REPO_DIR=$3
38
39     pushd $REPO_DIR > /dev/null
40     BRANCHES=$(git branch -r | grep $REMOTE | grep -v HEAD | sed "s/.*\///g" | grep -v master)
41     popd > /dev/null
42
43     run "git checkout master" ${REPO_DIR}
44     run "git merge --ff $REMOTE/master" ${REPO_DIR}
45     for BRANCH in $BRANCHES ; do
46         run "git branch $BRANCH $REMOTE/$BRANCH" ${REPO_DIR}
47         run "git checkout $BRANCH" ${REPO_DIR}
48         run "git merge --ff $REMOTE/$BRANCH" ${REPO_DIR}
49     done
50 }
51
52 function push_all_branches () {
53     NAME=$1
54     REMOTE=$2
55     REPO_DIR=$3
56
57     pushd $REPO_DIR > /dev/null
58     BRANCHES=$(git branch -r | grep $REMOTE | grep -v HEAD | sed "s/.*\///g" | grep -v master)
59     popd > /dev/null
60
61     run "git push $REMOTE master:master" ${REPO_DIR}
62     for BRANCH in $BRANCHES ; do
63         run "git push $REMOTE $BRANCH:$BRANCH" ${REPO_DIR}
64     done
65 }
66
67 function mirror () {
68     for arg in "$@" ; do
69         NAME=$(basename ${arg} | sed s/.git$//g)
70         GIT_NAME=${NAME}.git
71         REPO_DIR=${LOCAL_MIRROR_DIR}/${NAME}
72         MIRROR_REPO=${MIRROR_GIT}/${GIT_NAME}
73         MASTER_REPO=${MASTER_GIT}/${GIT_NAME}
74
75         # if there is no remote repository it may be that we only have
76         # the repository locally and don't need to mirror
77         git ls-remote $MIRROR_REPO &> /dev/null
78         if [ $? -eq 0 ]
79         then
80             if [ -d ${REPO_DIR} ]
81             then
82                 msg "pulling from ${NAME}"
83                 run "git fetch origin --tags" ${REPO_DIR}
84                 run "git fetch origin" ${REPO_DIR}
85                 merge_all_branches $NAME origin $REPO_DIR
86                 if [ $? -ne 0 ]
87                 then
88                     error "Can not fetch from ${MASTER_REPO}"
89                 fi
90             else
91                 msg "mirroring ${NAME} for the first time"
92                 run "git clone ${MIRROR_REPO}" ${LOCAL_MIRROR_DIR}
93                 run "git remote add local_master ${MASTER_REPO}" ${REPO_DIR}
94             fi
95
96             msg "pushing ${NAME} to local master"
97             run "git fetch local_master --tags" ${REPO_DIR}
98             run "git fetch local_master" ${REPO_DIR}
99             merge_all_branches $NAME local_master $REPO_DIR
100             if [ $? -ne 0 ]
101             then
102                 error "Can not fetch from ${MIRROR_REPO}"
103             else
104                 run "git push --tags local_master" ${REPO_DIR}
105                 push_all_branches $NAME local_master $REPO_DIR
106             fi
107         fi
108     done
109 }
110
111
112 while getopts ":hq" opt
113 do
114   case $opt in
115       q)
116           QUIET=1
117           break
118           ;;
119       h)
120           echo "USAGE: $0 [-q] REPONAME*"
121           exit 1
122           ;;
123       \?)
124           echo "Invalid option: -$OPTARG" >&2
125           ;;
126   esac
127 done
128
129 shift $((OPTIND-1))
130 mirror $@
131