背景
gitbucketは、warファイル一発で、イントラでgithubライクなインタフェースを提供できて大変便利に使わせてもらってます。
https://github.com/takezoe/gitbucket
ですが、自前運用だとバックアップ運用が大変になります。
そこで、無料でprivateリポジトリ作れるbitbucketに丸投げすることにしました。
基本方針
- bitbucketの1アカウントに、全リポジトリをつっこみます。
- 名前が衝突するので、
user/reponame.git
を、bitbucketuser/user__reponame.git
に変換します。 - wikiの場所が違うので、
user/reponame.wiki.git
を、bitbucketuser/user__reponame.git/wiki
に変換します。 - bitbucketでは大文字が使えないので、全て小文字にします。
- 変数は、スクリプトの頭にもってきます。
GB_LOCAL_REPO=/var/gitbucket/data/repositories
MIRROR_BASE=/var/gitbucket/mirrors
SRC_BASE=${GB_LOCAL_REPO}/
DST_BASE=git@bitbucket.org:
DST_USER=bitbucketuser
- GB_LOCAL_REPO: ローカルのgitbucketrepositoryを指定します。ここから対象の名前を抽出します。
- MIRROR_BASE: テンポラリに作るリポジトリを置くディレクトリ
- SRC_BASE: テンポラリからpullするためのソースURLのベース ("http://host.com/git/"のように、gitで使えればリモートでも使えるはず)
- DST_USER: bitbucketのアカウント名を指定します。
必要条件
bitbucketのssh key設定が必要です。
実装例
bash -x sync_all.shすると、デバッグが捗るかも
sync_all.sh
# !/bin/bash
GB_LOCAL_REPO=/var/gitbucket/data/repositories
MIRROR_BASE=/var/gitbucket/mirrors
SRC_BASE=${GB_LOCAL_REPO}/
DST_BASE=git@bitbucket.org:
DST_USER=bitbucketuser
function repo_put() {
export DESTREPO=$(tr '[A-Z]' '[a-z]' <<< $1 )
curl -X POST \
-H "Content-type: application/json" \
https://api.bitbucket.org/2.0/repositories/${DST_USER}/$DESTREPO \
-d '{"scm":"git", "is_private":true, "fork_policy":"no_forks", "has_wiki":"true" }'
}
function repo_del() {
export DESTREPO=$(tr '[A-Z]' '[a-z]' <<< $1 )
curl -X DELETE \
https://api.bitbucket.org/2.0/repositories/${DST_USER}/$DESTREPO
}
function repo_get() {
export DESTREPO=$(tr '[A-Z]' '[a-z]' <<< $1 )
curl -X GET \
https://api.bitbucket.org/2.0/repositories/${DST_USER}/$DESTREPO
}
function repos_init() {
echo $1 / $2
NOFOUND="`repo_get $1__$2 | grep ' not found'`"
echo NOFOUND=${NOFOUND}
if [ -z "$NOFOUND" ]
then
echo not err
cd ${MIRROR_BASE}/${1}/${2}.git
git fetch --all
git push origin2 --mirror
cd ${MIRROR_BASE}/${1}/${2}.wiki.git
git fetch --all
git push origin2 --mirror
else
echo err
export DESTREPO=$(tr '[A-Z]' '[a-z]' <<< ${1}__${2} )
repo_put $1__$2
cd ${MIRROR_BASE}
mkdir -p $1
cd $1
git clone --mirror ${SRC_BASE}${1}/${2}.git
cd ${2}.git
git remote add origin2 ${DST_BASE}${DST_USER}/${DESTREPO}.git
git push origin2 --mirror
cd ${MIRROR_BASE}/${1}
git clone --mirror ${SRC_BASE}${1}/${2}.wiki.git
cd ${2}.wiki.git
git remote add origin2 ${DST_BASE}${DST_USER}/${DESTREPO}.git/wiki
git push origin2 --mirror
cd ..
fi
}
LISTS=`find ${GB_LOCAL_REPO} -type d -name '*.git' | grep -v 'wiki.git' | sed "s#$GB_LOCAL_REPO/\(.*\)/\(.*\).git#\1_\2#"`
for item in $LISTS
do
repos_init ${item%%_*} ${item#*_}
done
おまけ
ゴミリポジトリができたりするのでそれを消す奴
del_all.sh
# !/bin/bash
GB_LOCAL_REPO=/var/gitbucket/data/repositories
MIRROR_BASE=/var/gitbucket/mirrors
SRC_BASE=${GB_LOCAL_REPO}/
DST_BASE=git@bitbucket.org:
DST_USER=bitbucketuser
function repo_put() {
curl -X POST \
-H "Content-type: application/json" \
https://api.bitbucket.org/2.0/repositories/${DST_USER}/$1 \
-d '{"scm":"git", "is_private":true, "fork_policy":"no_forks", "has_wiki":"true" }'
}
function repo_del() {
curl -X DELETE \
https://api.bitbucket.org/2.0/repositories/${DST_USER}/$1
}
function repo_get() {
curl -X GET \
https://api.bitbucket.org/2.0/repositories/${DST_USER}/$1
}
function repos_delete() {
echo $1 / $2
NOFOUND="`repo_get $1__$2 | grep ' not found'`"
echo NOFOUND=${NOFOUND}
if [ -z "$NOFOUND" ]
then
echo found
repo_del $1__$2
else
echo notfound
fi
}
LISTS=`find ${GB_LOCAL_REPO} -type d -name '*.git' | grep -v 'wiki.git' | sed "s#$GB_LOCAL_REPO/\(.*\)/\(.*\).git#\1_\2#"`
for item in $LISTS
do
repos_delete ${item%%_*} ${item#*_}
done