Open6

Reposoup: Submodule入りのコミットを普通のtreeに変換する

okuokuokuoku

とりあえず前回必要なプリミティブは用意したので、実際のリポジトリを普通のtreeに変換してみる。

ビルドノードへのソースコード配布のための前処理が目的なので、 この処理自体はbareリポジトリ上で行う

prev

https://zenn.dev/okuoku/scraps/7264c456220cd7

okuokuokuoku

.gitmodules のパース

これはプリミティブか。。 .gitmodules.git/config と同じ形式のファイルであるため、 git config コマンドでそのままパースできる。

また、 git config コマンドは、オプション --blob により実ファイルではなくリポジトリから直接コンフィグファイルを読み取ることもできる。

# URLを取得する場合
$ git config --blob HEAD:.gitmodules --get-regexp "submodule.*.url"

# Submoduleの配置先のパスを取得する場合
$ git config --blob HEAD:.gitmodules --get-regexp "submodule.*.path"
okuokuokuoku

再帰処理に対応していない版

まぁ↑をそのまま実装すれば良い。

https://github.com/okuoku/rs-gitdb-proto/commit/a56d298856a41cbc85bf20a026bd72ef27f7cb43

ちょっと工夫があるのは fetch で、--jobs--multiple オプションで並列してfetchを行うようにしている。 --multiple オプションではrefspecを与えられなくなるが、今回の用途では問題ない。

https://github.com/okuoku/rs-gitdb-proto/blob/a56d298856a41cbc85bf20a026bd72ef27f7cb43/gitutil.mjs#L390-L396

実際には、手元のリポジトリ(yunibaseやemscripten2native)はどちらもSubmoduleを再帰的に使用している。このため、configの生成をワンショットで行うことはできず、コミットの取得 → .gitmodulesのパース → 個々のpathからコミットを取得 → ... を再帰的に実行しなければならない。

okuokuokuoku

実際の置き換えを行う

https://github.com/okuoku/rs-gitdb-proto/commit/7dcd845dc3b076a594f029d08d6fee8ac4af8ab3

処理は2passで実装している。

  1. 最初のpass (step) は、 ["submoduleになっているパス", "参照しているコミット"] のペアのリストを出力する
  2. 実際の置き換えpass (do_replace) は、最初のpassが出力したペアを先頭から順番に置き換えていく

置き換えたパスのrootに .gitmodules ファイルがあった場合は削除しているが、更に、元のリポジトリのrootの .gitmodules も追加で削除している。 .gitmodules を消す必要があるかは何とも言えないが、Gitの --recurse-submodule オプションが .gitmodules を見ているのか自信が無かったので念のため消しておく事にした。