數據遷移基礎實現
AppPorts 的數據遷移功能負責將應用關聯的數據目錄(如 ~/Library/Application Support、~/Library/Caches 等)遷移至外部存儲,以釋放本地磁盤空間。
核心策略:符號鏈接
數據目錄遷移採用整體符號鏈接策略,流程如下:
- 將原始本地目錄完整複製到外部存儲
- 在外部目錄寫入托管鏈接元數據(
.appports-link-metadata.plist) - 將本地原始目錄改名為同卷隱藏安全備份
- 在原始路徑創建符號鏈接,指向外部存儲中的副本
- 符號鏈接創建成功後,清理本地安全備份
~/Library/Application Support/SomeApp
→ /Volumes/External/AppPortsData/SomeApp (符號鏈接)遷移流程
mermaid
flowchart TD
A[選擇數據目錄] --> B{權限與保護檢查}
B -->|失敗| Z[終止]
B -->|通過| C{目標路徑衝突檢測}
C -->|存在託管元數據| D[自動恢復模式]
C -->|無衝突| E[複製到外部存儲]
D --> E
E --> F[寫入托管鏈接元數據]
F --> G[改名為本地安全備份]
G -->|失敗| H[保留外部副本並停止]
G -->|成功| I[創建符號鏈接]
I -->|失敗| J[恢復本地安全備份並保留外部副本]
I -->|成功| K[清理本地安全備份]
K -->|成功| L[遷移完成]
K -->|失敗| M[遷移完成但保留安全備份]託管鏈接元數據
AppPorts 在外部目錄中寫入 .appports-link-metadata.plist 文件,用於標識該目錄由 AppPorts 管理。元數據包含:
| 字段 | 說明 |
|---|---|
schemaVersion | 元數據版本號(當前爲 1) |
managedBy | 管理者標識(com.shimoko.AppPorts) |
sourcePath | 原始本地路徑 |
destinationPath | 外部存儲目標路徑 |
dataDirType | 數據目錄類型 |
該元數據在掃描階段用於區分 AppPorts 創建的託管鏈接與用戶手動創建的符號鏈接,並在遷移中斷時支持自動恢復。
自動恢復採用嚴格匹配策略。外部目標目錄已存在時,AppPorts 只有在 schemaVersion、managedBy、sourcePath、destinationPath 和 dataDirType 全部與當前任務一致時,才會認為這是可接續的 AppPorts 託管目錄。沒有 metadata、metadata 不完整或路徑/類型不一致的真實目錄都會被視為衝突,AppPorts 不會僅憑目錄大小相近就接管或覆蓋。
接回與規範化都只面向目錄。AppPorts 會拒絕把外部普通文件當作數據目錄重新鏈接或移動,避免誤把文件替換為本地符號鏈接。
支持的數據目錄類型
| 類型 | 路徑示例 |
|---|---|
applicationSupport | ~/Library/Application Support/ |
preferences | ~/Library/Preferences/ |
containers | ~/Library/Containers/ |
groupContainers | ~/Library/Group Containers/ |
caches | ~/Library/Caches/ |
webKit | ~/Library/WebKit/ |
httpStorages | ~/Library/HTTPStorages/ |
applicationScripts | ~/Library/Application Scripts/ |
logs | ~/Library/Logs/ |
savedState | ~/Library/Saved Application State/ |
dotFolder | ~/.npm、~/.vscode 等 |
custom | 用戶自定義路徑 |
還原流程
- 驗證本地路徑爲符號鏈接且指向有效外部目錄
- 移除本地符號鏈接
- 將外部目錄複製回本地
- 刪除外部目錄(盡力而爲)
若複製失敗,自動重建符號鏈接以保證一致性。
錯誤處理與回滾
遷移過程中的每個關鍵步驟均包含回滾機制:
- 複製失敗:不執行後續操作,清理已複製的外部文件
- 移動本地安全備份失敗:停止遷移並保留外部副本,不刪除本地源目錄
- 創建符號鏈接失敗:優先將本地安全備份恢復到原路徑,同時保留外部副本,避免兩端數據同時丟失
- 清理安全備份失敗:遷移仍視為完成,本地會保留
.appports-migration-backup-*備份,用戶確認數據無誤後可手動清理
這種設計確保在任何階段發生故障時,數據不會丟失且系統狀態保持一致。
