訓練
版本控制概念
vcpkg 使用最少的選擇方法來進行版本控制,其靈感來自 Go 所使用的版本設定,但在某些方面進行了修改:
- 一律從全新安裝開始,不需要升級/降級作業。
- 引進基準以允許不受限制的相依性。
不過,最小選取原則保持不變。 假設有一組條件約束,vcpkg 會使用可滿足所有條件約束之套件的「最舊」可能版本。
使用最低版本方法有下列優點:
- 這是可預測且容易理解的。
- 使用者控制何時進行升級,如同在 中,發行新版本時不會自動執行任何升級。
- 避免使用 SAT 規劃求解。
若要提供範例,請考慮下列套件圖表:
(A 1.0) -> (B 1.0)
(A 1.1) -> (B 1.0)
-> (C 3.0)
(A 1.2) -> (B 2.0)
-> (C 3.0)
(C 2.0)
以及下列指令清單:
{
"name": "example",
"version": "1.0.0",
"dependencies": [
{ "name": "A", "version>=": "1.1" },
{ "name": "C", "version>=": "2.0" }
],
"builtin-baseline": "<some git commit with A's baseline at 1.0>"
}
在考慮可轉移的相依性之後,我們有下列一組條件約束:
- A >= 1.1
- B >= 1.0
- C >= 3.0
- C >= 2.0
由於 vcpkg 必須滿足所有條件約束,因此一組已安裝的套件會變成:
A 1.1
,即使A 1.2
存在,也沒有比 vcpkg 更高的1.1
條件約束會選取可能的最低版本。B 1.0
,可轉移。A 1.1
C 3.0
,由 新增B 1.0
的可轉移條件約束升級,以滿足版本條件約束。
假設有一組版本相依性的指令清單,vcpkg 會嘗試計算符合所有條件約束的套件安裝計劃。
版本條件約束有下列類型:
- 宣告的條件約束:使用
version>=
在最上層指令清單中明確宣告的條件約束。 - 基準條件約束:由 隱含新增的條件
builtin-baseline
約束。 - 可轉移的條件約束:相依性間接新增的條件約束。
- 覆寫的條件約束:使用
overrides
宣告覆寫最上層指令清單中的條件約束。
若要計算安裝計劃,vcpkg 會遵循下列步驟:
- 將所有最上層條件約束新增至計劃。
- 以遞歸方式將可轉移的條件約束新增至計劃。
- 每次將新套件新增至計劃時,也會將其基準條件約束新增至計劃。
- 每次新增條件約束時:
- 如果封裝的覆寫存在
- 選取覆寫中的版本。
- 否則:
- 如果沒有選取舊版則為 。
- 選取符合條件約束的最低版本。
- 如果已選取舊版:
- 如果新條件約束的版本設定設定與先前選取的版本不符:
- 新增版本衝突。
- 如果條件約束的版本與先前選取的版本不相提並論。 例如,比較 “version-string: apple” 與 “version-string: orange”:
- 新增版本衝突。
- 如果條件約束版本高於先前選取的版本:
- 選取最高版本。
- 否則:
- 保留先前的選取範圍。
- 如果新條件約束的版本設定設定與先前選取的版本不符:
- 如果沒有選取舊版則為 。
- 檢閱計劃:
- 如果沒有衝突
- 安裝選取的套件
- 否則:
- 向使用者報告衝突
- 如果沒有衝突
雖然套件版本的概念一直存在於 vcpkg 中,但版本限制的概念尚未存在。
隨著版本控制條件約束的引進,套件現在可能相依於與本機可用的埠版本不相符。 這會產生問題,因為 vcpkg 需要知道如何取得所要求版本的埠檔案。
為了解決這個問題,引進了一組新的元數據檔案。 這些檔案位於 versions/
vcpkg 存放庫根層級的目錄中。
目錄 versions/
將會包含登錄中每個可用埠的 JSON 檔案。 每個檔案都會列出套件可用的所有版本,並包含 vcpkg 可取出的 Git 樹狀結構-ish 物件,以取得該版本的 portfiles。
範例: zlib.json
{
"versions": [
{
"git-tree": "2dfc991c739ab9f2605c2ad91a58a7982eb15687",
"version-string": "1.2.11",
"port-version": 9
},
...
{
"git-tree": "a516e5ee220c8250f21821077d0e3dd517f02631",
"version-string": "1.2.10",
"port-version": 0
},
{
"git-tree": "3309ec82cd96d752ff890c441cb20ef49b52bf94",
"version-string": "1.2.8",
"port-version": 0
}
]
}
針對每個埠,其對應的版本檔案應該位於 versions/{first letter of port name}-/{port name}.json
中。 例如,zlib 的版本檔案會位於 versions/z-/zlib.json
。 除了埠版本檔案之外,目前的基準檔案位於 versions/baseline.json
。