版本控制概念

最低版本控制

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