Baulk – 开发一个简单的包管理工具历程

前言

相对于其他操作系统,我更习惯使用 Windows,但一直以来 Windows 缺乏官方的包管理器,而第三方无论是 Scoop 还是 Chocolatey 都无法满足我独特的需求,我的要求很简单,所有的软件包都应该使用绿色解压模式,这包括了 MSI 安装包,另外安装软件时不应该修改系统和用户环境变量。包管理工具应该足够快,还要支持创建启动器等等。

从毕业工作以来,我开发了 clangbuilder ,一个简化在 Windows 上使用 Visual Studio 构建 LLVM/Clang 的工具(含 GUI 工具),为了解决安装构建 LLVM 时所需工具依赖的问题,后来多次开坑编写各种软件,多年的失败经验与认知不断积累,于是在今年这个环球同此凉热的年份,我开始了新坑 ➡ baulk ,baulk 花费了我半年的下班时间,现在基本可用,ReadMe 也写好了,应该可以给大家分享一下了。

安装和使用 Baulk

这个步骤只有四五步,下载 baulk 二进制包,解压 baulk 二进制包,点击 baulkterminal,更新元数据,安装你需要的软件,:ok:,你可以使用 baulk 安装的软件了。

baulk update
# i 是 install 的别名
# baulk i cmake curl 7z ...
baulk install cmake curl 7z
cmake --version

baulk 升级命令可以使用如下命令:

baulk update
baulk upgrade

也可以使用别名:

# u 是特殊的别名,包含 update 和 upgrade 两个步骤
# baulk update and upgrade
baulk u

升级 baulk 自身可以使用帮助程序 baulk-update

baulk-update

卸载软件也很容易:

# r 是 uninstall 的别名
baulk uninstall 7z

在开发 baulk 时,我就决定只支持 Windows 10 1903 或更新的版本,好处显而易见,可以使用 Windows Terminal,利用 ANSI 转义输出颜色,体验非常不错:

baulk 提供了 baulk-exec 在命令行中执行 baulk-exec 可以初始化 baulk 环境,还提供了 ssh-askpass-baulk,ssh-askpass-baulk 用于 TunnelSSH 某些 ssh 无法打开标准输入时请求输入密码,截图如下:

在 baulk 中我引入了 VirtualEnv 机制,这种机制能够使得用户并行安装多个软件版本,在 baulk-exec,baulkterminal 中通过指定参数支持启动任意的 VENV,baulk 还提供了 baulk-dock 能够选择按照特定的 VENV 启动环境:

在 Baulk 元数据存储库 bucket ,收录了 OpenJDK8(Java),OpenJDK9(Java),GraalVM8(Java),Zulu14(Java),Go(golang),DMD(dlang) 等支持 VENV 的包,如果有人想把 Ruby 收录一下,在 Windows 上实现类似 rbenv 功能也不是什么难事。

Baulk 的内幕

入门说完,可以稍稍讲一下 Baulk 的实现细节,baulk 的包管理类似于 Scoop,即将包的元数据存储在 Github 上,官方源为 baulk/bucket ,baulk 还可以通过编写 $BAULK_ROOT/config/baulk.json 添加新的源,或者删除某个源,如果不同的源中存在相同名字的包,baulk 还能根据 bucket 的权重去选择使用哪个源,但目前为止,只有 baulk/bucket 一个源。

{
    "bucket": [
        {
            "description": "Baulk default bucket",
            "name": "Baulk",
            "url": "https://github.com/baulk/bucket",
            "weights": 100
        }
    ]
}

baulk update 命令更新 bucket,这里我们使用了 Github Atom RSS 机制,以官方源为例,通过 HTTP 请求项目的 commits/master.atom 获得当前的最新的 commitID,如果本地不存在或者与其不同,则说明 bucket 有更新,于是 baulk 下载对应的 bucket 的压缩包,解压完成元数据的更新。然后检测本地已安装的包是否存在更新版本,存在就输出提示。

GET https://github.com/baulk/bucket/commits/master.atom

当人们运行 baulk upgrade 时,就会真正的升级已安装的包,更新元数据和升级分开这种机制类似于 apt-get ,为了简化操作,baulk 提供了 baulk u 别名将 update/upgrade 合并在一起简化升级。