2 个版本

0.1.1 2021年12月26日
0.1.0 2021年12月13日

#2020 in 算法


用于 elm-solve-deps-bin

MPL-2.0 许可证

57KB
771

elm生态系统依赖解析

elm-solve-deps 库提供了一套类型、函数和特质,用于处理 elm 生态系统的依赖。它基于 pubgrub 库,并为 elm 生态系统的一些工具的依赖解析器提供支持,例如

依赖解析的主要目标是从一个依赖约束集合开始,例如由软件包的 elm.json 提供

{
  ...,
  "dependencies": {
    "elm/core": "1.0.2 <= v < 2.0.0",
    "elm/http": "2.0.0 <= v < 3.0.0",
    "elm/json": "1.1.2 <= v < 2.0.0"
  },
  "test-dependencies": {
    "elm-explorations/test": "1.2.0 <= v < 2.0.0"
  }
}

然后找到一个满足这些约束的软件包版本集合。通常我们还想有优先级,比如选择兼容的最新版本。在这个案例和这个日期,不考虑测试依赖项,最新的解决方案是

{
  "direct": {
    "elm/core": "1.0.5",
    "elm/http": "2.0.0",
    "elm/json": "1.1.3"
  },
  "indirect": {
    "elm/bytes": "1.0.8",
    "elm/file": "1.0.5",
    "elm/time": "1.0.0"
  }
}

如果我们还考虑测试依赖项,则得到的是

{
  "direct": {
    "elm/core": "1.0.5",
    "elm/http": "2.0.0",
    "elm/json": "1.1.3",
    "elm-explorations/test": "1.2.2"
  },
  "indirect": {
    "elm/bytes": "1.0.8",
    "elm/file": "1.0.5",
    "elm/html": "1.0.0",
    "elm/random": "1.0.0",
    "elm/time": "1.0.0",
    "elm/virtual-dom": "1.0.2"
  }
}

简单的离线依赖解析器

此库已经提供了一种适用于离线用例的依赖解析器。需要使用 solver::Offline 结构体,并使用 ELM_HOME 的路径以及使用的 elm 版本(具体来说,目前这应该是 "0.19.1")。然后它提供了一个 solve_deps 函数,该函数将成功返回一个解决方案,或者在出现错误时失败。

离线解析器将仅在 ELM_HOME 内查找软件包,因此应该与其他 "elm 兼容" 的生态系统(如 Lamdera)一起工作。您可以使用它如下。

// Define an offline solver.
let offline_solver = solver::Offline::new(elm_home(), "0.19.1");

// Load the project elm.json.
let elm_json_str = std::fs::read_to_string("elm.json")
    .expect("Are you in an elm project? there was an issue loading the elm.json");
let project_elm_json = serde_json::from_str(&elm_json_str)
    .expect("Failed to decode the elm.json");

// Solve with tests dependencies.
let use_test = true;

// Do not add any extra additional dependency.
let extras = &[];

// Solve dependencies.
let solution = offline_solver
    .solve_deps(&project_elm_json, use_test, extras)
    .expect("Dependency solving failed");

请注意,可以提供额外的软件包约束,这对于工具来说非常方便,因为当需要添加未直接记录在原始 elm.json 文件中的软件包时。

在线依赖解析器

我们还提供在线求解器以方便使用。初始化时,它首先更新已知软件包的数据库。然后在解决依赖关系时,它与离线求解器的工作方式类似,但所使用的软件包集是本地存在的软件包和软件包服务器上存在的软件包的并集。有关更多信息,请参阅 solver::Online 文档。

自定义依赖关系求解器

最后,如果您想对选择依赖关系的流程有更多的控制,您可以使用可配置函数 solver::solve_deps_with,或者通过编写自己的依赖关系提供者并进行完全自定义,直接使用 pubgrub crate。

当使用 solver::solve_deps_with 时,您必须提供两个函数,即 fetch_elm_jsonlist_available_versions,实现以下伪特质限制

fetch_elm_json: Fn(&Pkg, SemVer) -> Result<PackageConfig, Error>
list_available_versions: Fn(&Pkg) -> Result<Iterator<SemVer>, Error>

您需要自行确定配置 elm.json 的位置以及如何提供现有版本列表。注意,返回的版本迭代器中的顺序将对应于选择版本的优先级。这意味着优先选择最新或最旧的版本只是您部分的一个 .reverse()

其他辅助模块

为了使不同的求解器类型能够很好地结合在一起,此 crate 还提供了一些辅助模块。

  • project_config:处理配置 elm.json 文件序列化和反序列化的模块。
  • pkg_version:定义唯一软件包版本的基类型。它还提供了一些辅助类型和函数,用于在 ELM_HOME 中读取/写入缓存,并从服务器获取软件包,遵循与官方 elm 软件包服务器相同的 API。
  • constraint:帮助进行版本约束的序列化和反序列化的模块。
  • dependency_provider:将通用依赖关系提供者转换为使用项目 elm.json 作为根的辅助实现。

依赖项

~0.9–1.8MB
~38K SLoC