部數(shù)據(jù)表示與實(shí)現(xiàn)解析)
開發(fā)工具CLI后端【免費(fèi)下載鏈接】saplingA Scalable, User-Friendly Source Control System.項目地址https://gitcode.com/gh_mirrors/sa/sapling點(diǎn)擊查看免費(fèi)下載導(dǎo)讀本文基于 git_lfs.md 展開系統(tǒng)講解 Sapling 項目Mononoke 是其服務(wù)端存儲引擎如何在內(nèi)部數(shù)據(jù)模型Bonsai Changeset中表示 Git LFS 文件從 Git 指針文件pointer到 BonsaiFileChange上git_lfs標(biāo)記的轉(zhuǎn)換邏輯、Thrift 序列化結(jié)構(gòu)、指針識別與回退策略以及該特性如何做到完全可選、且允許倉庫內(nèi)新舊歷史不一致。讀完本文你將理解 Mononoke 如何做到內(nèi)部存儲完整文件內(nèi)容、對外按 Git 協(xié)議輸出 LFS 指針并掌握相關(guān)配置開關(guān)git_lfs_interpret_pointers與端到端驗(yàn)證路徑。為什么 Mononoke 要理解 Git LFSVanilla Git 本身并不感知文件是否為 LFS 文件所有 LFS 處理都在客戶端完成由 git-lfs 的 filter 接管服務(wù)端只接收和提供指向 LFS 文件的指針。Mononoke 完全可以照搬這一做法繼續(xù)做一個純 Git 兼容的服務(wù)端——但這會帶來一系列不理想的副作用通過各類訪問面如 SCS API查詢 Git LFS 文件時只能拿到指針內(nèi)容拿不到真實(shí)文件所有匯總統(tǒng)計和哈希都基于指針大小而非實(shí)際檢出checkout大小無法用于評估終端用戶的真實(shí)體驗(yàn)Mononoke 內(nèi)部的數(shù)據(jù)完整性校驗(yàn)無法覆蓋 LFS 文件內(nèi)容跨倉庫Cross-Repo同步會同步指針而非文件從 Git 同步到 Sapling 時文件會被替換成幾乎無用的指針內(nèi)容同步到其他 Git 倉庫時也無法保證對方倉庫啟用了 LFS真實(shí)文件內(nèi)容無法得到復(fù)制。因此Mononoke 選擇在自己的內(nèi)部模型中主動識別并解釋 LFS 指針。它是可選的如果上述副作用對你不是問題或者你使用的是 Mononoke 之外的第三方 LFS 服務(wù)器則完全不需要擔(dān)心該特性整體可選。若關(guān)閉LFS 指針會被當(dāng)作普通文件一樣處理。這一開關(guān)在倉庫元配置中體現(xiàn)為GitConfigs::git_lfs_interpret_pointers: bool見 metaconfig/types/src/lib.rsON從 Git 提交轉(zhuǎn)換為 Bonsai 時Git LFS 指針會被解釋真實(shí)文件內(nèi)容會被存儲文件內(nèi)容必須能獲取到OFFGit LFS 指針與倉庫中其他任何文件一視同仁。集成測試 test-git-lfs-derive-and-clone.t 通過環(huán)境變量GIT_LFS_INTERPRET_POINTERS1打開該行為后構(gòu)建倉庫驗(yàn)證了完整鏈路?;径x術(shù)語含義Git LFS 指針Git LFS pointer一小段被檢入倉庫的文本文件指向 LFS 服務(wù)器上的真實(shí)文件內(nèi)容完整文件內(nèi)容Full file contents指針?biāo)傅恼鎸?shí)文件字節(jié)規(guī)范形式的指針長這樣以\n結(jié)尾version https://git-lfs.github.com/spec/v1 oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 size 12345 (ending \n)指針的解釋流程從 Git 數(shù)據(jù)模型到 Bonsai當(dāng) Mononoke 把 Git 數(shù)據(jù)模型翻譯為內(nèi)部模型Bonsai Changeset時會對文件內(nèi)容做模式匹配。如果內(nèi)容看起來像 LFS 指針則確保指針與完整文件內(nèi)容都已上傳到 Mononoke 的 blobstore在 Bonsai 中使用完整文件內(nèi)容作為文件內(nèi)容在 Bonsai 的文件變更file change上設(shè)置一個特殊標(biāo)記指明該文件在 Git 一側(cè)應(yīng)表示為 LFS。指針識別與解析的源碼實(shí)現(xiàn)解析邏輯位于 git/git_types/src/git_lfs.rs通過正則git-media|hawser|git-lfs預(yù)篩內(nèi)容只有命中才嘗試按 LFS 解析LFS_MATCHER_RE拒絕解析超過1024 字節(jié)的文件MAX_METADATA_LENGTH與 git-lfs 上游掃描器使用的限制一致見 git_lfs.rs逐行解析version/oid/size字段并兼容三個 v1 別名http://git-media.io/v/2alpha、https://hawser.github.com/spec/v1pre-release、https://git-lfs.github.com/spec/v1正式版見 V1_ALIASES允許存在額外擴(kuò)展字段Git LFS 支持格式擴(kuò)展Mononoke 選擇忽略若解析出的sha256、size、version缺一則判定不是合法指針parse_lfs_pointer返回None通過is_canonical字段判斷當(dāng)前內(nèi)容是否與由format_lfs_pointer(sha256, size)重新生成的規(guī)范指針逐字節(jié)相等。規(guī)范指針的生成函數(shù)format_lfs_pointer直接對應(yīng)文檔中給出的格式見 git_lfs.rspub fn format_lfs_pointer(sha256: Sha256, size: u64) - String { format!(version https://git-lfs.github.com/spec/v1\noid sha256:{sha256}\nsize {size}\n) }從 Bonsai 反推 Git LFS 指針當(dāng)需要以 Git 數(shù)據(jù)格式對外服務(wù)時Mononoke 會根據(jù) Bonsai 文件變更中的標(biāo)記用文件的 sha256 與 size 重新生成指針并寫入 blobstoregenerate_and_store_git_lfs_pointer返回該指針 blob 的 Git SHA1 供 Git 協(xié)議使用。數(shù)據(jù)表示Bonsai 的FileChange與GitLfs結(jié)構(gòu)對每個提交變更的文件Bonsai Changeset 持有一個FileChange結(jié)構(gòu)其中含可選的git_lfs字段struct FileChange { ... 5: optional GitLfs git_lfs; } struct GitLfs { 1: optional id.ContentId non_canonical_pointer_content_id; }定義見 serialization/bonsai.thrift關(guān)鍵語義如下只要該結(jié)構(gòu)存在該文件變更在以 Git 數(shù)據(jù)格式服務(wù)時就會以 Git LFS 指針呈現(xiàn)推薦在創(chuàng)建源自 Git 之外的新提交時將該結(jié)構(gòu)整體留空若提交來自非規(guī)范rogue客戶端且指針與 Git-LFS / Mononoke 會生成的指針不是逐字節(jié)相等則此時需要把非規(guī)范指針的內(nèi)容 ID 填入non_canonical_pointer_content_id以保證數(shù)據(jù)可往返roundtrip。規(guī)范指針 vs 非規(guī)范指針規(guī)范指針canonical pointer指與上面format_lfs_pointer輸出逐字節(jié)完全一致的指針。反過來說以下情況都屬于非規(guī)范指針需要記錄原始指針內(nèi)容使用了舊版本別名如https://hawser.github.com/spec/v1字段順序不同或包含額外擴(kuò)展字段文件末尾缺少換行符其他與規(guī)范生成結(jié)果不一致的格式變體。這些情況在 git_lfs.rs 的單元測試 中都有覆蓋legacy version、extra fields、無結(jié)尾換行、非指針隨機(jī)字符串、錯誤版本號、錯誤 oid、錯誤 size、缺字段等而規(guī)范場景則驗(yàn)證了is_canonical true且重新生成結(jié)果與原文逐字節(jié)相等。Rust 側(cè)的類型映射Rust 中對應(yīng)的枚舉定義在 mononoke_types/src/file_change.rspub enum GitLfs { /// Full contents of the file should be served over Git protocol #[default] FullContent, /// A Git-LFS pointer should be served over git protocol GitLfsPointer { /// The content id of the pointer if different from the default /// one created by Git LFS or Mononoke. non_canonical_pointer: OptionContentId, }, }GitLfs::FullContent默認(rèn)表示以完整內(nèi)容對外服務(wù)Thrift 序列化時git_lfs字段為NoneGitLfs::GitLfsPointer表示以指針對外服務(wù)構(gòu)造器canonical_pointer()生成non_canonical_pointer None的規(guī)范指針non_canonical_pointer(content_id)用于非規(guī)范指針。BasicFileChange結(jié)構(gòu)體包含content_id、file_type、size與git_lfs四個字段見 file_change.rsTrackedFileChange則在其之上疊加copy_from拷貝信息。向不支持 LFS 的倉庫鏡像時丟棄標(biāo)記當(dāng)把提交鏡像到不支持 Git LFS 的倉庫時TrackedFileChange::without_git_lfs()會丟棄 Git-LFS 信息把標(biāo)記降級為FullContent見 file_change.rs確??鐐}庫同步不會帶上對方無法處理的語義。關(guān)閉指針解釋時的行為如果 Git LFS 指針解釋被禁用Mononoke 就直接存儲指針本身并將git_lfs字段置為None對應(yīng) Rust 側(cè)GitLfs::FullContent。此時文件在 Mononoke 內(nèi)部與普通文件完全一致。倉庫內(nèi)部不要求一致性Mononoke 允許同一個倉庫內(nèi)部分指針被解釋、部分仍以原始指針存儲不做解析。這種混合狀態(tài)在以下場景很有用倉庫歷史中某些部分的歷史文件內(nèi)容已丟失例如它們存儲在外部的 LFS 服務(wù)器上存在取不回的可能性此時只能用指針形式保存對新內(nèi)容則希望啟用指針解釋享受完整內(nèi)容帶來的統(tǒng)計、校驗(yàn)與跨倉同步收益。集成測試端到端驗(yàn)證test-git-lfs-derive-and-clone.t 提供了完整的端到端示例展示了這套表示如何在實(shí)際運(yùn)行中生效開啟GIT_LFS_INTERPRET_POINTERS用testtool_drawdag構(gòu)造包含large_file以lfs類型寫入與.gitattributes的提交派生git_commits/git_delta_manifests_v2/unodes數(shù)據(jù)啟動 LFS 服務(wù)器與 Mononoke Git 服務(wù)進(jìn)行g(shù)it clone驗(yàn)證工作區(qū)檢出的是真實(shí)內(nèi)容contents of LFS file而git show HEAD:large_file看到的是指針文本用mononoke_admin fetch檢查 Bonsailarge_file顯示為ADDED/MODIFIED (LFS)其內(nèi)容 ID 指向真實(shí)內(nèi)容修改并推送新 LFS 變更后同樣以(LFS)標(biāo)記寫入 Bonsai且 blobstore 中可通過內(nèi)容 ID 取回規(guī)范指針文本。該測試清晰演示了內(nèi)部存完整內(nèi)容 對外呈現(xiàn)指針這一設(shè)計的實(shí)際效果。Gitimport 中的 LFS 對象獲取指針解釋要落地Mononoke 必須能拿到真實(shí)文件內(nèi)容。在gitimport工具中這一職責(zé)由 git/import_tools/src/gitlfs.rs 承擔(dān)它提供三種獲取方式模式說明UpstreamLfs通過 HTTP 從上游 LFS 服務(wù)器按GET {server}/{sha256}Dewey 風(fēng)格或GET {server}/{repo}/download_sha256/{sha256}Mononoke Git LFS拉取對象InternalLfs直接從本地 Mononoke filestore 按 SHA256 別名查找對象GitHubLfs通過 GitHub LFS Batch APIPOST {batch_url}換取簽名下載 URL 后再GET拉取使用 GitHub App 安裝令牌認(rèn)證三個模式共享同一套重試與降級策略allow_not_foundtrue時若對象在上游不存在HTTP 404 或批處理返回code404則回退為把指針字節(jié)本身作為文件內(nèi)容存儲并告警allow_not_foundfalse時則視為不可恢復(fù)錯誤直接失敗。gitimport 的命令行參數(shù)--lfs-server、--internal-lfs、--github-lfs-url、--github-lfs-token-file、--allow-dangling-lfs-pointers、--lfs-import-max-attempts、--lfs-concurrency等在 gitimport/src/main.rs 中定義且這些選項僅在倉庫開啟了git_lfs_interpret_pointers時才生效。結(jié)論通過在 Bonsai 文件變更上附加git_lfs標(biāo)記Mononoke 把 Git LFS 語義隔離在 Git 數(shù)據(jù)格式這一層其他 API如 SCS、diff、統(tǒng)計無需了解 Git 的細(xì)節(jié)可以直接以一致的方式訪問完整文件內(nèi)容完整性校驗(yàn)、跨倉庫同步、匯總統(tǒng)計都基于真實(shí)文件內(nèi)容對外服務(wù) Git 協(xié)議時再按需還原成規(guī)范或非規(guī)范的 LFS 指針保證與 Git 客戶端的兼容性該特性完全可選、支持倉庫內(nèi)新舊歷史混用適合歷史內(nèi)容丟失但新內(nèi)容希望享受完整存儲收益的場景。提示Git-LFS 指針的數(shù)據(jù)格式規(guī)范可參考 git-lfs 官方 spec詳見 git_lfs.rs 與 bonsai.thrift 中的注釋說明。贊分享開發(fā)工具CLI后端【免費(fèi)下載鏈接】saplingA Scalable, User-Friendly Source Control System.項目地址https://gitcode.com/gh_mirrors/sa/sapling點(diǎn)擊查看免費(fèi)下載相關(guān)推薦KernelSU 裝完模塊 /system 沒變化meta-overlayfs 元模塊五步裝好systemless 覆蓋立刻生效KernelSU 裝完模塊 /system 沒變化meta overlayfs 元模塊五步裝好systemless 覆蓋立刻生效 你裝了個要覆蓋 /syst操作系統(tǒng)驅(qū)動開發(fā)Git LFS命令重構(gòu)從源碼角度理解git-lfs migrate實(shí)現(xiàn)Git LFS命令重構(gòu)從源碼角度理解git lfs migrate實(shí)現(xiàn) 引言大文件倉庫的性能噩夢與解決方案 你是否曾在包含GB級設(shè)計文件的Git倉庫中經(jīng)歷過開發(fā)工具CLI版本控制如何使用 RevokeMsgPatcherPC 微信/QQ/TIM 防撤回實(shí)戰(zhàn)手冊含安裝步驟與多開工具如何使用 RevokeMsgPatcherPC 微信/QQ/TIM 防撤回實(shí)戰(zhàn)手冊含安裝步驟與多開工具 RevokeMsgPatcher 是一款針對 PC開發(fā)工具CLI后端上一篇AG Grid終極指南如何構(gòu)建高性能企業(yè)級數(shù)據(jù)表格應(yīng)用下一篇Vira ThemeMaterial Theme的官方繼承者深度解析創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考