runsisi's

technical notes

git submodule 使用本地镜像

2019-04-22 runsisigit

通常,主项目会由开发人员自己主动跟踪并更新至社区的最新的代码,但对于主项目中引用的第三方模块(submodule)一般都不会太关注,主项目也不会频繁更新对它的引用,但在构建时(特别是 CI 构建时)可能需要频繁的从 github 等第三方频繁的拉取代码,在 GFW 和内部网络双重控制的网络环境下,实际上大大延长了构建所需的时间,对于这些第三方模块,可以使用本地的 git 镜像仓库进行加速构建。

需要注意的是第三方模块自身又可能引用第三方模块,且引用的第三方模块可能又与主项目引用的同名但属于不同的 git 仓库,因此使用本地镜像的关键是对第三方模块 URL 的替换操作。

参考脚本如下:

#!/bin/bash -x

mirrors() {
    cat > .git_submodule_mirrors <<EOF 
ceph-object-corpus http://src.example.com/ceph/ceph-object-corpus.git
src/civetweb http://src.example.com/ceph/civetweb.git
src/libs3 http://src.example.com/ceph/libs3.git
src/mongoose http://src.example.com/ceph/mongoose.git
src/leveldb http://src.example.com/ceph/leveldb.git
src/erasure-code/jerasure/jerasure http://src.example.com/ceph/jerasure.git
src/erasure-code/jerasure/gf-complete http://src.example.com/ceph/gf-complete.git
src/rocksdb http://src.example.com/ceph/rocksdb.git
ceph-erasure-code-corpus http://src.example.com/ceph/ceph-erasure-code-corpus.git
src/gmock http://src.example.com/ceph/gmock.git
src/dpdk http://src.example.com/ceph/dpdk.git
src/spdk http://src.example.com/ceph/spdk.git
dpdk spdk http://src.example.com/spdk/dpdk.git
src/xxHash http://src.example.com/ceph/xxHash.git
gtest http://src.example.com/ceph/gtest.git
src/isa-l http://src.example.com/ceph/isa-l.git
src/googletest http://src.example.com/ceph/googletest.git
src/lua http://src.example.com/ceph/lua.git
src/boost http://src.example.com/boostorg/boost.git
src/Beast http://src.example.com/ceph/Beast.git
src/zetascale http://src.example.com/ceph/zetascale.git
src/zstd http://src.example.com/facebook/zstd.git
src/crypto/isa-l/isa-l_crypto http://src.example.com/01org/isa-l_crypto.git
src/blkin http://src.example.com/ceph/blkin.git
src/rapidjson http://src.example.com/ceph/rapidjson.git
thirdparty/gtest http://src.example.com/google/googletest.git
src/dmclock http://src.example.com/ceph/dmclock.git
src/seastar http://src.example.com/ceph/seastar.git
dpdk seastar http://src.example.com/ceph/dpdk.git
src/fmt http://src.example.com/ceph/fmt.git
fmt seastar http://src.example.com/ceph/fmt.git
src/c-ares http://src.example.com/ceph/c-ares.git
extern/dpdk http://src.example.com/scylladb/dpdk.git
intel-ipsec-mb http://src.example.com/spdk/intel-ipsec-mb.git
EOF
}

replace() {
    mirrors

    git submodule init

    for submodule in $(git config -l | grep submodule | cut -d'.' -f2); do
        grep -i -e "^${submodule}[[:space:]]" .git_submodule_mirrors | while read -r line; do
            fields=$(echo ${line} | wc -w)
            if [ ${fields} -eq 2 ]; then
                giturl=$(echo ${line} | cut -d" " -f2)
                git config --replace-all submodule.${submodule}.url ${giturl}
            else
                curmodule=$(basename $(pwd))
                parent=$(echo ${line} | cut -d" " -f2)
                if [ ${curmodule} = ${parent} ]; then
                    giturl=$(echo ${line} | cut -d" " -f3)
                    git config --replace-all submodule.${submodule}.url ${giturl}
                fi
            fi
        done
    done

    git submodule update --init

    rm -f .git_submodule_mirrors
}

if python -mplatform | grep -qi centos; then
    export -f mirrors
    export -f replace

    replace
    git submodule foreach bash -x -c 'replace'

    unset -f mirrors
    unset -f replace
elif python -mplatform | grep -qi ubuntu; then
    replace
    git submodule foreach bash -x -c "$(declare -pf mirrors replace); replace"
else
    echo 'not supported platform, exiting'
    exit 1
fi