关于Go Modules (2) 版本选择MVS


人工翻译、参考、总结 主要来源是:https://go.dev/ref/mod#minimal-version-selection


Minimal version selection (MVS)

版本选择问题是定义构建列表上这四个操作的含义并给出算法实现:

  • 建立当前的构建列表
  • 将所有的module都升级到最新版本
  • 将一个模块升级到特定的较新版本
  • 将一个模块降级到特定的旧版本

目标是操作的步数越少越好,并且能够满足所有依赖。

MVS算法假定所有module都声明了独立的依赖:最小版本的依赖列表;并且也假定module遵守 导入兼容性规则 :新版本的包应该像旧版本一样工作,因此依赖项要求只给出最低版本。

因此,上面的四个操作的定义是:

  • 为给定目标构建构建列表:从目标本身开始列表,然后附加每个依赖自己的构建列表。如果一个模块多次出现在列表中,只保留最新版本。
  • 将所有模块升级到最新版本:构建构建列表,读取所有依赖按照它们所需的最新版本。
  • 将一个模块升级到特定的较新版本: 构建未升级的构建列表,然后附加新模块的构建列表。如果一个模块多次出现在列表中,只保留最新版本。
  • 将一个模块降级到特定的旧版本:倒回每个顶级需求的所需版本,直到该依赖的构建列表不再适用于降级模块的较新版本。

示例

在这里插入图片描述
上图是一个模块需求图,下文都是以此为例。


Low-Fidelity Builds 低保真构建

go get : 如果有本地版本,使用该版本。否则下载使用最新版本。
go get -u : 下载并使用最新版本的一切。


high-Fidelity Builds 高包真构建

目标本身下文统一称为M

算法1:建立构建列表

递归过程 recursive process:
开始一个空列表,添加M,然后为M的每个依赖附加构建列表。然后根据仅仅保留最新版本的规则去简化列表。
在这里插入图片描述图遍历 graph traversal:
和上面是等效的
在这里插入图片描述
通过图的简单递归来计算,不要访问已经访问过的节点。该方法完全忽略不必要的模块版本,而不是像上面一样先保留再简化。

算法2:升级所有模块

这个就是go get -u 所做的事情。
升级模块需求图,升级后的所有模块版本都被替换为最新的版本,忽视原本的模块依赖箭头。
为了升级列表,更改了所有模块的依赖,但是模块A开发过程中的升级必须以某种方式仅记录在A的需求列表(go.mod里),这样就能让算法1生成我们想要的构建列表。
完成以上需要在A的依赖列表里添加一些东西,为此引入算法R。

算法R:计算最小需求列表

首先要在原本的列表中加上原本不包含的模块,但是还是希望能够保持添加尽可能少的模块。比如用C1.3替换掉C1.2。但是F1.1和G1.1可以不要,因为都可以通过C1.3暗示得来。
对于无环图,结果是唯一的、最小的加法集。对于有环图,反向后序遍历必须打破循环,添加的集合对于不包含循环的模块是唯一且最小的。
所以最终升级需要添加的是C1.3、D1.4和E1.3

算法3:升级一个模块

在这里插入图片描述
升级一个模块也是保持尽量改动最小的原则。
比如想为A升级C1.2到C1.3,在需求图里给A到C1.3加上新的箭头,注意不要删除旧箭头。如果直接将A到C1.3的箭头替换掉A到C1.2的,那么D将会直接降级为D1.3,这是我们不希望看到的,也不在我们的预期中。加完线之后,执行R算法去决定如何升级需求列表。这个案例里,我们最终将C1.2替换为C1.3但也会加一个新的依赖在D1.4,去避免D的降级。这次升级并不是简单地满足最新的C的依赖。

算法4:降级一个模块

也许在升级之后发现最新的依赖列表是错的,所以需要降级依赖到之前的版本。目标是尽可能地少降级其他模块。
比如我们发现D1.4有问题,这个问题在D1.3就有了,所以想降级到D1.2。
为了降级到D1.2,必须要找到依赖不早于D1.2版本的B和C。
为了不必要的降级到E1.1,必须在E1.2上加依赖。然后在使用R算法找到要最小新要求写入go.mod。

高保真构建

如果A的用户和A的作者的构建完全匹配,即可重现的构建,就算是高包真。
但是实际的高保真并不是这么简单。
比如上面的案例,A的构建结合了B1.2和D1.4,虽然B的作者使用的是D1.3,但是C1.2需要D1.4,即使如此,A的构建依然是B1.2的高包真构建,它的偏差是因为它必须这样做。如果产生不必要的偏离就是低包真。


英文版总结

Need four operations on build lists:

  • Construct the current build list
  • Upgrade all modules to their latest versions
  • Upgrade one module to specific newer version
  • Downgrade one module to specific older version

Doing so many require upgrading, downgrading, adding an removing modules, ideally as few as possible, to satisfy dependencies.

Minimal version selection assumes that each module declares its own dependency requirements : a list of minimum versions of other modules.
Modules are assumed to follow the import compatibility rule.

Then the definition of the four operations are:

  • To constract the build list for a given target : start the list with the target itself, and then append each requirement’s own build list.
  • Constract the build list , but read each requirement as if it required the latest module version.
  • Constract the non-upgrade build list and then append the new module’s build list.
  • Rewind the required version of each top-level requirement until that requirement’s build list no longer refers to newer versions of the downgrade module.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值