среда, 10 февраля 2021 г.

Модули в Golang: выбор минимальной версии (MVS)

Go использует алгоритм, называемый Выбор минимальной версии (MVS, Minimal version selection), чтобы выбрать набор версий модуля для использования при сборке пакетов.

Концептуально MVS работает с направленным графом модулей, указанным в файлах go.mod. Каждая вершина в графе представляет версию модуля. Каждое ребро представляет минимально необходимую версию зависимости, указанную с помощью директивы require. Директивы replace и exclude в файле go.mod главного модуля изменяют граф.

MVS производит список сборки в качестве вывода, список версий модуля, используемых для сборки.

MVS начинается с основного модуля (особая вершина в графе, у которой нет версии) и проходит по графу, отслеживая самую высокую требуемую версию каждого модуля. В конце обхода самые высокие требуемые версии составляют список сборки: это минимальные версии, которые удовлетворяют всем требованиям.

Список сборки можно просмотреть с помощью команды go list -m all. В отличие от других систем управления зависимостями, список сборки не сохраняется в "заблокированном" файле. MVS детерминирован, и список сборки не изменяется при выпуске новых версий зависимостей, поэтому MVS используется для его вычисления в начале каждой команды, поддерживающей модули.

Рассмотрим пример на диаграмме ниже. Для основного модуля требуется модуль A версии 1.2 или выше и модуль B версии 1.2 или выше. A 1.2 и B 1.2 требуют C 1.3 и C 1.4 соответственно. Для C 1.3 и C 1.4 требуется D 1.2.

MVS посещает и загружает файл go.mod для каждой версии модуля, выделенной синим цветом. В конце обхода графа MVS возвращает список сборки, содержащий версии, выделенные жирным шрифтом: A 1.2, B 1.2, C 1.4 и D 1.2. Обратите внимание, что доступны более поздние версии B и D, но MVS не выбирает их, поскольку они ничем не требуются.

Замена

Содержимое модуля (включая его файл go.mod) можно заменить с помощью директивы replace в файле go.mod главного модуля. Директива replace может применяться к определенной версии модуля или ко всем версиям модуля.

Замены изменяют граф модуля, поскольку заменяемый модуль может иметь другие зависимости, чем замененные версии.

Рассмотрим пример ниже, где C 1.4 был заменен на R. R зависит от D 1.3 вместо D 1.2, поэтому MVS возвращает список сборки, содержащий A 1.2, B 1.2, C 1.4 (замененный на R) и D 1.3.

Исключение

Модуль также может быть исключен в определенных версиях с помощью директивы exclude в файле go.mod основного модуля.

Исключения также меняют граф модуля. Когда версия исключается, она удаляется из графа модуля, а требования к ней перенаправляются на следующую более высокую версию.

Рассмотрим пример ниже. C 1.3 был исключен. MVS будет действовать так, как если бы A 1.2 требовал C 1.4 (следующая более высокая версия) вместо C 1.3.

Обновления

Команду go get можно использовать для обновления набора модулей. Чтобы выполнить обновление, команда go изменяет граф модуля перед запуском MVS, добавляя ребра из посещенных версий в обновленные версии.

Рассмотрим пример ниже. Модуль B может быть обновлен с 1.2 до 1.3, C может быть повышен с 1.3 до 1.4, а D может быть повышен с 1.2 до 1.3.

Обновления (и более ранние версии) могут добавлять или удалять косвенные зависимости. В этом случае E 1.1 и F 1.1 появятся в списке сборки после обновления, поскольку E 1.1 требуется для B 1.3.

Чтобы сохранить обновления, команда go обновляет требования в go.mod. Это изменит требования к B до версии 1.3. Она также добавит требования к C 1.4 и D 1.3 с // indirect комментариями, поскольку в противном случае эти версии не были бы выбраны.

Понижение

Команду go get также можно использовать для понижения версии набора модулей. Чтобы выполнить переход на более раннюю версию, команда go изменяет граф модуля, удаляя версии выше, чем предыдущие. Она также удаляет версии других модулей, которые зависят от удаленных версий, поскольку они могут быть несовместимы с более ранними версиями их зависимостей. Если для основного модуля требуется, чтобы версия модуля была удалена путем понижения, требование изменяется на предыдущую версию, которая не была удалена. Если предыдущая версия недоступна, требование снимается.

Рассмотрим пример ниже. Предположим, что проблема была обнаружена с C 1.4, поэтому мы переходим на C 1.3. C 1.4 удален из графа модуля. B 1.2 также удаляется, так как для него требуется C 1.4 или выше. Требование основного модуля к B изменено на 1.1.

go get также может полностью удалить зависимости, используя суффикс @none после аргумента. Это работает аналогично переходу на более раннюю версию. Все версии указанного модуля удаляются из графа модулей.


Читайте также:


Комментариев нет:

Отправить комментарий