Документация Engee

6. Совместимость

Совместимость — это возможность ограничить версии зависимостей, с которыми совместим ваш проект. Если совместимость для зависимости не указана, предполагается, что проект совместим со всеми версиями этой зависимости.

Совместимость для зависимости указывается в файле Project.toml, например так:

[compat]
julia = "1.6"
Example = "0.5"

После того как запись о совместимости помещена в файл проекта, ее можно применять с помощью up.

Формат спецификатора версии подробно описан ниже.

Используйте команду compat для редактирования записей о совместимости в REPL Pkg или отредактируйте файл проекта вручную.

Приведенные ниже правила относятся к файлу Project.toml. Сведения о реестрах см. в разделе Файл Compat.toml реестра.

Обратите внимание, что для регистрации в общем реестре Julia требуется, чтобы каждая зависимость имела запись [compat] с верхней границей.

Формат спецификатора версий

Как и другие диспетчеры пакетов, диспетчер пакетов Julia соблюдает семантическое управление версиями (semver), с исключением для начальных нулей. Например, спецификатор версии, заданный как 1.2.3, считается совместимым с версиями [1.2.3 - 2.0.0), где ) — неинклюзивная верхняя граница. Более конкретно, спецификатор версии задается либо как спецификатор «курсор», например ^1.2.3, либо как спецификатор «тильда», например ~1.2.3. Спецификаторы «курсор» используются по умолчанию, поэтому 1.2.3 == ^1.2.3. Разница между курсором и тильдой описывается в следующем разделе. Объединение нескольких спецификаторов версий формируется путем разделения запятыми отдельных спецификаторов версий, например

[compat]
Example = "1.2, 2"

приведет к [1.2.0, 3.0.0). Обратите внимание, что начальные нули обрабатываются по-разному, например Example = "0.2, 1" приведет только к [0.2.0 - 0.3.0) ∪ [1.0.0 - 2.0.0). Дополнительные сведения о версиях с начальными нулями см. в следующем разделе.

Поведение версий с начальными нулями (0.0.x и 0.x.y)

Хотя согласно спецификации semver все версии с номером основной версии, равным 0 (версии до 1.0.0), несовместимы друг с другом, мы решили применять этот факт только в тех случаях, когда номера и основной, и дополнительной версий равны нулю. Другими словами, 0.0.1 и 0.0.2 считаются несовместимыми. Версия, предшествующая 1.0, с ненулевым номером дополнительной версии (0.a.b с a != 0) считается совместимой с версиями с тем же номером дополнительной версии и меньшими или равными номерами версий исправления (0.a.c с c <= b); то есть версии 0.2.2 и 0.2.3 совместимы с 0.2.1 и 0.2.0. Версии с нулевым номером основной версии и разными номерами дополнительных версий не считаются совместимыми, поэтому в версии 0.3.0 могут быть изменения, отличные от 0.2.0. В связи с этим запись [compat]:

[compat]
Example = "0.0.1"

приводит к привязке версии Example как [0.0.1, 0.0.2) (что эквивалентно только версии 0.0.1), тогда как запись [compat]:

[compat]
Example = "0.2.1"

приводит к привязке версии Example как [0.2.1, 0.3.0).

В частности, пакет может задать version = "0.2.4", если в нем есть добавления функций по сравнению с 0.2.3, при условии, что он остается обратно совместимым с 0.2.0. См. также The version field.

Спецификаторы «курсор»

Спецификатор «курсор» (^) позволяет выполнять обновление, которое будет совместимым согласно semver. Это поведение по умолчанию, если спецификаторы не используются. Обновленная зависимость считается совместимой, если новая версия не изменяет самую левую ненулевую цифру в спецификаторе версии.

Ниже приведен ряд примеров.

[compat]
PkgA = "^1.2.3" # [1.2.3, 2.0.0)
PkgB = "^1.2"   # [1.2.0, 2.0.0)
PkgC = "^1"     # [1.0.0, 2.0.0)
PkgD = "^0.2.3" # [0.2.3, 0.3.0)
PkgE = "^0.0.3" # [0.0.3, 0.0.4)
PkgF = "^0.0"   # [0.0.0, 0.1.0)
PkgG = "^0"     # [0.0.0, 1.0.0)

Спецификаторы «тильда»

Спецификатор «тильда» предоставляет более ограниченные возможности обновления. При указании основной, дополнительной версий и версии исправления или при указании основной и дополнительной версий допускается изменение только версии исправления. При указании только основной версии разрешается обновлять как дополнительную версию, так и версию исправления (~1, таким образом, эквивалентна ^1). Например:

[compat]
PkgA = "~1.2.3" # [1.2.3, 1.3.0)
PkgB = "~1.2"   # [1.2.0, 1.3.0)
PkgC = "~1"     # [1.0.0, 2.0.0)
PkgD = "~0.2.3" # [0.2.3, 0.3.0)
PkgE = "~0.0.3" # [0.0.3, 0.0.4)
PkgF = "~0.0"   # [0.0.0, 0.1.0)
PkgG = "~0"     # [0.0.0, 1.0.0)

Для всех версий с нулевым номером основной версией спецификаторы «тильда» и «курсор» эквивалентны.

Спецификатор «равенство»

Можно использовать, чтобы указать точные версии:

[compat]
PkgA = "=1.2.3"           # [1.2.3, 1.2.3)
PkgA = "=0.10.1, =0.10.3" # 0.10.1 или 0.10.3

Спецификатор «неравенство»

Можно использовать, чтобы задать диапазоны версий:

[compat]
PkgB = ">= 1.2.3" # [1.2.3,  ∞)
PkgC = "≥ 1.2.3"  # [1.2.3,  ∞)
PkgD = "< 1.2.3"  # [0.0.0, 1.2.3) = [0.0.0, 1.2.2]

Спецификаторы «дефис»

Синтаксис с дефисом можно использовать, чтобы задать диапазоны версий: Убедитесь, что по обе стороны от дефиса есть пробелы.

[compat]
PkgA = "1.2.3 - 4.5.6" # [1.2.3, 4.5.6]
PkgA = "0.2.3 - 4.5.6" # [0.2.3, 4.5.6]

Любые неуказанные конечные числа в первой конечной точке считаются нулями:

[compat]
PkgA = "1.2 - 4.5.6"   # [1.2.0, 4.5.6)
PkgA = "1 - 4.5.6"     # [1.0.0, 4.5.6)
PkgA = "0.2 - 4.5.6"   # [0.2.0, 4.5.6)
PkgA = "0.2 - 0.5.6"   # [0.2.0, 0.5.6)

Любые неуказанные конечные числа во второй конечной точке считаются подстановочными знаками:

[compat]
PkgA = "1.2.3 - 4.5"   # 1.2.3 - 4.5.* = [1.2.3, 4.6.0)
PkgA = "1.2.3 - 4"     # 1.2.3 - 4.*.* = [1.2.3, 5.0.0)
PkgA = "1.2 - 4.5"     # 1.2.0 - 4.5.* = [1.2.0, 4.6.0)
PkgA = "1.2 - 4"       # 1.2.0 - 4.*.* = [1.2.0, 5.0.0)
PkgA = "1 - 4.5"       # 1.0.0 - 4.5.* = [1.0.0, 4.6.0)
PkgA = "1 - 4"         # 1.0.0 - 4.*.* = [1.0.0, 5.0.0)
PkgA = "0.2.3 - 4.5"   # 0.2.3 - 4.5.* = [0.2.3, 4.6.0)
PkgA = "0.2.3 - 4"     # 0.2.3 - 4.*.* = [0.2.3, 5.0.0)
PkgA = "0.2 - 4.5"     # 0.2.0 - 4.5.* = [0.2.0, 4.6.0)
PkgA = "0.2 - 4"       # 0.2.0 - 4.*.* = [0.2.0, 5.0.0)
PkgA = "0.2 - 0.5"     # 0.2.0 - 0.5.* = [0.2.0, 0.6.0)
PkgA = "0.2 - 0"       # 0.2.0 - 0.*.* = [0.2.0, 1.0.0)

Устранение конфликтов

Конфликты версий были представлены ранее на примере конфликта, возникшего в пакете D, используемом двумя другими пакетами, B и C. Анализ сообщения об ошибке показал, что пакет B использует устаревшую версию пакета D. Чтобы исправить ситуацию, сначала попробуйте pkg> dev B, чтобы изменить пакет B и его требования к совместимости. Если вы откроете его файл Project.toml в редакторе, вы, вероятно, заметите что-то вроде следующего:

[compat]
D = "0.1"

Обычно первым шагом является изменение этого параметра на что-то вроде следующего:

[compat]
D = "0.1, 0.2"

Это указывает на то, что пакет B совместим как с версией 0.1, так и с версией 0.2. При выполнении pkg> up ошибка пакета будет исправлена. Однако есть одна серьезная проблема, которую нужно решить в первую очередь: возможно, в версии v0.2 было внесено несовместимое изменение пакета D, которое приводит к сбою пакета B. Прежде чем продолжить, следует обновить все пакеты, а затем запустить тесты для пакета B, проверив вывод pkg> test B, чтобы убедиться, что версия v0.2 пакета D действительно используется. (Возможно, что дополнительная зависимость пакета D закрепляет его к версии v0.1, и вы не хотите заблуждаться, думая, что протестировали пакет B в более новой версии.) Если использовалась новая версия и тесты по-прежнему проходят, можно считать, что пакет B не нуждается в дальнейших обновлениях, чтобы принять v0.2 для D. Вы можете смело отправить это изменение в качестве запроса на вытягивание для B, чтобы вышел новый выпуск. Если же возникает ошибка, это указывает на то, что пакет B требует более всестороннего обновления для совместимости с последней версией пакета D. Эти обновления должны быть завершены, прежде чем станет возможным одновременное использование пакетов A и B. Однако вы можете продолжать использовать их независимо друг от друга.