Основные понятия управления версиями

Минимальное управление версиями

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 наличии ограничений выше, чем 1.1 vcpkg, выбирает минимальную версию.
  • 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-файлы для каждого из портов, доступных в реестре. Каждый файл будет перечислять все версии, доступные для пакета, и содержит объект Git tree-ish, который vcpkg может проверка, чтобы получить портфайлы этой версии.

Пример: 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.