yunibuild: Git submoduleを再帰的にミラーしたい
いろいろ考えてみたけど、これ多分簡単な方法は無いよね。。簡単なスクリプトを書くか。。
ターゲット
手元の(公開)プロジェクトでsubmoduleを使ったインテグレーションをしているのは:
- https://github.com/okuoku/yunibase
- https://github.com/okuoku/wasmlinux-project
- https://github.com/okuoku/em2native-tests
やることとしては:
- これらの
master
ブランチのHEADの.gitmodules
から再帰的に辿っていって、全部のGitリポジトリのリストを作る/更新する - リストに載っているリポジトリを
url.<URL>.insteadOf
で書き換えるようなコマンドを出力する -- (全体の置き換えではなく、)単なるリファレンスとしてだけ使うみたいのがあった気もする - 再帰的にshallowなcloneをするスクリプトを書く -- 最近のGitは標準のコマンドでできた気もする
.gitmodules
だけfetchする
filter=blob:none
でshallow cloneしてから、
git clone --depth=1 --no-checkout --filter=blob:none https://github.com/okuoku/yunibase yunibase
cat-file
するのが一番安いと思うんだけどどうかな。。(自動的に当該オブジェクトが取得される)
git cat-file HEAD:.gitmodules
ファイルのハッシュは ls-tree
にある oid
から求められる。 .gitmodules
が変更されていないなら操作する必要は無い。
% git ls-tree HEAD
100644 blob 6b8710a711f3b689885aa5c26c6c06bde348e82b .dockerignore
100644 blob 0e6b2e55756cea827d8f50be8e122ccd602568b3 .gitmodules
取得した .gitmodules
は git のconfigと同じフォーマットなので、同様に git config
コマンドでパースできる。
...というか blob を直接アクセスできるんだから、bare repositoryで良いな。
% git clone --depth=1 --bare --filter=blob:none https://github.com/okuoku/yunibase yunibase
% GIT_DIR=yunibase git ls-tree HEAD .gitmodules
100644 blob 0e6b2e55756cea827d8f50be8e122ccd602568b3 .gitmodules
% GIT_DIR=yunibase git config --blob HEAD:.gitmodules --get-regexp "submodule.*.url"
100件もあんのか。。
ちょっと多いねぇ。。
ここで生成したリストを使って、ミラーのメンテナンスとかを実装していく必要がある。自動GC禁止とか諸々の設定が必要。
llvm-projectの挙動がおかしい
EDIT: たぶんだけどGitHubはPRのマージ先が更新されると merge
のrefを自動的に更新してるんではないか説。じゃぁ常時大量のPRが出ているようなプロジェクトをmirrorするのは良くないな。。本質的にmirrorが必要なのは自分のプロジェクトだけだし。。
LLVMは超巨大なGitリポジトリをGitHub上に持っている https://github.com/llvm/llvm-project 。これを --mirror
でcloneすると挙動がおかしくなる。
とりあえず最初のcloneに失敗するのは http.postBuffer
の指定で治ったが、fetchするたびに大量のrefが更新される症状が出る。
From https://github.com/llvm/llvm-project
- [deleted] (none) -> refs/pull/106948/merge
e1bde1c5b203..2a9f93bf13c7 main -> main
+ f493c7a6795c...33d50dcfec4c refs/pull/100579/merge -> refs/pull/100579/merge (forced update)
+ ad47ac69d797...2492d99df489 refs/pull/100608/merge -> refs/pull/100608/merge (forced update)
+ c2a1ea6bd4d7...6a5fb9c33ed1 refs/pull/100667/merge -> refs/pull/100667/merge (forced update)
+ c469b0a9da8f...bc5c0eb9f6d8 refs/pull/100785/merge -> refs/pull/100785/merge (forced update)
+ 3315eaec0aa4...b4eb5d5369f2 refs/pull/100977/merge -> refs/pull/100977/merge (forced update)
+ 40760ecdb24b...c1e307603e28 refs/pull/100995/merge -> refs/pull/100995/merge (forced update)
+ 129ccc3cf7b2...ff32630fb23b refs/pull/101053/merge -> refs/pull/101053/merge (forced update)
+ f895b92ba805...39544d3888f4 refs/pull/101172/merge -> refs/pull/101172/merge (forced update)
+ a9305b1263fe...fd5f12253cd7 refs/pull/101261/merge -> refs/pull/101261/merge (forced update)
+ 607124ea1b4d...0593d2b11420 refs/pull/101485/merge -> refs/pull/101485/merge (forced update)
106948は実際このタイミングでマージされたPR https://github.com/llvm/llvm-project/pull/106948 なので良いとして、他のPRを参照しているrefは特にGHEのページを見ても更新されている様子がない。
本質的にmirrorが必要なのは自分がPRを出すリポジトリだけだから、こういう例外的なリポジトリは --mirror
ではなく --bare
でcloneできるようにdenylistの仕組みを作るのが良いかな。。