文件
使用 LayerFS 進行本機開發
Native Shell 的儲存庫包含一套本機 LayerFS 工作流程,用來測試可重複使用的建置工作區。它會匯入已提交的原始碼樹,在 Linux Sandbox 內執行 Cargo,儲存產生的檔案,並從該儲存狀態的 fork 再次執行測試。原始碼編輯與 Git 提交仍在你現有的 NSH checkout 中進行。
#快照會儲存什麼
LayerFS 儲存的是檔案系統樹:原始碼檔案、Git 中繼資料、被忽略的檔案,以及在工作區內產生的建置輸出。fork 會從已儲存的樹開始,並記錄自己的變更。如此一來,多個任務可以從同一個已建置的狀態出發,同時保持各自的變更互相獨立。
在 NSH 的本機試驗中,第一個分支會執行 nsh-package 的測試,並儲存 target/ 以及一個被忽略的探測檔案。第二個分支從該 commit 開始,檢查這些檔案,並在離線狀態下重複執行測試。第三個分支則從原始的原始碼狀態開始,用來驗證隔離性。
| 階段 | 執行內容 |
|---|---|
| Init | 匯入 checkout 的 HEAD commit 匯出內容,以及全新的 .git 目錄 |
| Build | fork 一個工作區並執行 cargo +1.98.1 test --locked -p nsh-package |
| Commit | 將產生的 target/ 與探測檔案儲存至 LayerFS 歷史紀錄 |
| Reuse | fork 已儲存的分支、掛載它,並以 --offline 重複執行測試 |
| Verify | 讀取 commit 歷史紀錄,並確認原始的原始碼分支維持乾淨 |
每次呼叫都會建立全新的 Store,並執行完整的上述流程。快照的重複使用發生在該次呼叫的各個分支之間。此試驗要衡量的效益,是取得另一個可用且已通過測試的工作區所需的成本,包括掛載、commit 與卸載的時間。
#準備開發環境
請使用 NSH 儲存庫的 checkout,並具備以下條件:
- 一個本機 Linux Docker engine,其 Store volume 使用 ext4、XFS 或 Btrfs,可在 Linux 上執行,或透過 OrbStack 等 macOS 環境執行。
- Docker Engine 提供 API 1.54 或更新版本;已驗證的本機設定使用 Engine 29.7.2。
/dev/fuse,且 Docker 須允許將該裝置與CAP_SYS_ADMIN暴露給 Sandbox。- Git 與 Python 3.12 或更新版本;在 Linux 上還需要 rustup 與 C/C++ 編譯器。
- 可連線的網路,用於取得固定版本的 LayerFS 原始碼、Cargo 相依套件與執行階段映像檔。
此試驗會建置 LayerFS 1.0.0,固定於原始碼 commit 2aaf2552ce21154928b9f9c83582e41a637f5910。其執行階段映像檔為 Linux 程序提供 Rust 1.98.1、Node 與 clang。上游 SDK 指南說明了 Store 與 Sandbox 的生命週期。
請在 NSH checkout 的根目錄執行以下指令:
./scripts/layerfs prepare
./scripts/layerfs smoke
./scripts/layerfs status
此可執行檔會選用 Python 3.12 或更新版本(包括 macOS 上 Homebrew 安裝的版本),並從目前作用中的 Docker context 找出 socket。可使用 --docker-socket PATH 明確指定本機 socket。
prepare 會檢查 Docker API、安裝 Rust 1.85.1,並建置固定版本的 daemon、Node addon 與執行階段映像檔。在 macOS 上,這些項目會在暫時的 Linux 建置容器中準備。它會重複使用一般的 Cargo registry 與 target/,包括既有的 CARGO_TARGET_DIR 設定。確切的執行階段映像檔 ID 與 daemon 路徑會記錄於 .nsh/layerfs/deployment.json。status 會檢查已儲存的建置輸出與映像檔,並顯示最近一次的驗證結果。
smoke 會從 checkout 中已提交的 HEAD 建立 .nsh/layerfs/nsh-<id>/input,然後將該輸入匯入新的 Store。若要包含原始碼的編輯內容,請在執行前先將它們提交到你的主題分支。產生的輸入會從全新的 Git 儲存庫開始,並在 Sandbox 內取得其建置輸出。
控制程序會在具名的本機 Docker volume 中開啟 Store。Sandbox daemon 會開啟同一個 Store,並掛載該分支的檔案系統檢視;Cargo 在該掛載的工作區中執行。你一般的 checkout 仍是編輯與提交原始碼變更的地方。
#讀取結果
此指令會印出收據目錄與 Store volume 名稱。開啟產生的 result.json,即可查看 "ok": true 以及各階段的耗時。同一個目錄中還有用來識別原始碼 commit 與映像檔的 settings.json,以及記錄 SDK 呼叫的 trace.jsonl。
本機驗證在 build 與 reuse 階段各執行了 22 個套件測試。初始的建置/測試階段包含相依套件的下載;離線階段則使用已儲存的 target/ 與同一個 Sandbox 的 Cargo registry。在評估其價值時,請將完整週期與你工作負載上一般的 Cargo 建置相比較。
重複使用已建置的狀態時,請使用相同的作業系統、架構、工具鏈與相依套件。本指南的工作負載是 Linux 的 nsh-package 測試套件;平台 UI 檢查則使用各自的平台環境(Testing)。
#保留有用的工作並管理 Store
請將原始碼變更保存在 Git 中,並透過 pull request 提交。此試驗使用 LayerFS 的 Disposable Store 設定檔,用於可重新建置的工作區歷史紀錄。記錄量測結果時,請另外保留有用的收據。
產生的輸入會在其初始 commit 期間停用 Git 自動維護,使物件資料庫在 LayerFS 匯入時保持穩定。試驗中的 Git 狀態檢查使用 --no-optional-locks,讓讀取狀態時能保留原始的 index。對於自訂指令碼,請在匯入或提交樹之前,先結束所有背景寫入程序。
成功且已卸載的 Sandbox 會在 LayerFS 的閒置逾時後停止。每次試驗都會保留其 Store volume;請依收據中的識別碼管理該特定的 volume 及其容器。失敗的操作會保留其記錄的狀態以供診斷。維護者參考文件涵蓋了指令碼、收據與資源清理。