gitbucketのrepositoryをbitbucketでバックアップする

# 背景

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では大文字が使えないので、全て小文字にします。
* 変数は、スクリプトの頭にもってきます。

```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
```

* 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すると、デバッグが捗るかも

```bash: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
```

# おまけ

ゴミリポジトリができたりするのでそれを消す奴


```bash: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
```

https://github.com/aminamid/gitb-sync