铁铺 (TiePM) 设计笔记
对标实现:铁铺 v0.2.1(
tiepm/核心.xt981 行 +tiepm/铁铺.xt79 行) 本文同步日期:2026-10-05(逐函数对照核心.xt/铁铺.xt/xuantie_compiler/编译.xt/tiepm-site/main.go核对) 注意:site/guide/下的同名文件由site/scripts/sync-docs.mjs从本目录生成,勿直接编辑 site 副本。
设计目标
铁铺是玄铁语言的包管理器,核心目标:
- 安装:查远程索引 → 下载包 → SHA256 校验 → 解压落位
- 搜索:按关键词在索引里过滤包名
- 发布:本地打包、算哈希,并向索引登记
- 轻量:不依赖第三方包管理器运行时(Node.js/Python 等),客户端用玄铁自举实现
架构总览
┌─────────────────┐ HTTP ┌──────────────────┐
│ 铁铺 CLI │ ◄──────────► │ TiePM 官网 │
│ (铁铺.xt) │ JSON API │ (tiepm-site/) │
│ │ │ Go + 静态 HTML │
├─────────────────┤ ├──────────────────┤
│ • 安装/搜索/发布 │ │ GET /api/index │
│ • SHA256 校验 │ │ POST /api/publish │
│ • TOML 清单解析 │ │ GET /api/search │
│ • 本地缓存管理 │ │ GET /download/:名/:版本 │
└─────────────────┘ └────────┬─────────┘
│ 读写
┌──────▼──────────┐
│ data/index.json │
└─────────────────┘关键设计决策(与实现一致):
- 索引与源码分离:官网只托管包索引 JSON;包文件由各项目的 GitHub/GitCode Releases 承载,官网不存包。
- 无状态服务:Go 服务器以本地
data/index.json持久化,无数据库;静态页面用embed.FS编进二进制,单文件部署。 - 裸包名导入:编译器识别裸包名(
引 "UI" 予 UI),自动解析到~/.tiepm/已安装/<包名>/,无需写路径。 - 客户端只用两个端点:
GET /api/index与POST /api/publish。官网另有/api/search与/download/:名/:版本(302 到{仓库}/archive/v{版本}.zip)、以及注册/登录/控制台——CLI 当前不调用这些,搜索是在本地对索引做包名过滤。
包索引格式
索引是单个 JSON 对象(data/index.json):
{
"数组工具": {
"1.0.0": {
"版本": "1.0.0",
"哈希": "sha256 十六进制",
"仓库": "https://github.com/用户名/仓库",
"作者": "张三",
"描述": "提供数组工具函数"
}
}
}CLI 命令
| 命令 | 作用 |
|---|---|
铁铺 安装 <包名> [版本约束](az) | 解依赖并安装;失败以非零码退出 |
铁铺 列出(lc) | 列 ~/.tiepm/已安装 条目 + 编译器内置库表 |
铁铺 搜索 <关键词>(ss) | 拉索引后按包名过滤(不搜描述) |
铁铺 发布(fb) | 打包 + 登记索引(见"发布流程") |
铁铺 清理(ql) | 删除 ~/.tiepm/缓存 内容 |
| 无参数 | 打印用法 |
| 未知命令 | 打印"未知命令"+用法(不设非零退出码) |
暂无 更新 / 卸载 命令。所有命令执行前都会先跑一次初始化(建目录)。
安装流程(实际路径)
- 拉索引:地址硬编码
https://tiepm.xt.markjy.com/api/index,可用环境变量TIEPM_INDEX覆盖(空值/含异常字符时回退默认)。 - 解版本约束:在索引里"查找最高满足版本"(逐键比较,非排序取首)。约束语法:
*/空、>=x.y.z、^x.y.z(0.x 按 semver 锁次版本)、精确匹配;不支持~、<、>与区间。版本号按纯数字三段比较。 - 拼下载地址:
{仓库}/releases/download/v{版本}/{仓库末段}_v{版本}.zip;仓库不含 github.com / gitcode.com 时直接当 URL 用。下载用curl -L -o,落在当前工作目录的_tiepm_dl.zip。 - 哈希校验:三平台分派——Windows
certutil -hashfile、macOSshasum -a 256、Linuxsha256sum(POSIX 两支互备重试)。索引条目没有哈希字段则跳过校验;校验失败 → 安装失败退出。 - 解压落位:
tar -xf解到 CWD 的_tiepm_unzip,再xcopy/cp -R搬到~/.tiepm/已安装/<包名>(不重命名)。zip 内不强制固定层级。 - 依赖递归:读被装包的
tiepm.toml,递归安装[依赖];深度上限 10 层(超限报"可能存在循环依赖");另有显式循环检测、已装/已解析缓存去重、以及多约束冲突检测(同一包出现不一致约束则整单失败)。装完删掉 CWD 里的下载包。
本地目录结构
~/.tiepm/
├── 已安装/<包名>/ # 解压落位处(编译器裸包名解析的目标)
├── 缓存/ # 发布产物 zip、_publish.json(用后删)
└── 认证 # 文件(非目录):发布用 Bearer 令牌安装期的 _tiepm_dl.zip / _tiepm_unzip 在当前工作目录,成功路径会清理;清理 命令只清 ~/.tiepm/缓存,不递归、不清 CWD 残留。
编译期裸包名解析
编译器对 引 "<包名>"(无路径前缀)的解析顺序:
~/.tiepm/已安装/<包名>/<包名>.xt;- 兼容 GitHub archive 多包一层
<名>-<版本>/的目录(再探一层); - 编译器自带副本:发行布局
<编译器同级>/lib/<包名>/<包名>.xt,开发布局上一级lib/。
- 安装副本优先于自带副本;两者版本不一致时打印明确告警("若报'未找到成员'请先核对此处")。
- 安装根目录可用
TIEPM_HOME覆盖。 - 另有
[原生]对象登记路径(本地 C 库/对象文件经此参与链接)。
使用者必读:玄铁的选项是字典,旧库对未知键不报错、静默忽略。给库加了新功能后,只有把新版装进铁铺(或走发布流程)才会在运行期生效——仓库里有新代码、本机装的还是旧版,会表现为"改了没反应"。
tiepm.toml 清单
[包]
名称 = "数组工具"
版本 = "1.0.0" # 2~3 段点分,如 1.0 / 1.0.0
仓库 = "https://github.com/用户名/仓库"
作者 = "开发者名" # 可选
描述 = "一句话" # 可选
[依赖] # 可选:包名 = 版本约束
渲染 = "^1.2.3"- 必填:
[包]节及其名称/版本/仓库。 - 可选后备写法:顶层
[作者].姓名、[描述].简介。 - 依赖约束支持"精确 /
>=/*"(注释口径与实现一致,^亦支持)。 - 包名合法性校验(防路径穿越)只在安装链路使用;
发布时不校验包名。
发布流程
铁铺 发布 实际做四件事:
- 校验清单;打印包名/作者/描述/依赖。
- 打包:
tar -czf(排除.git、.tiepm),产物移到~/.tiepm/缓存/<仓库末段>_v<版本>.zip,并算 SHA256。 - 打印需要手动完成的两步:
git tag v<版本> && git push --tags;- 建 GitHub Release,把上一步缓存目录里的 zip 传上去。
- 自动登记索引:把
{名称, 版本, 哈希, 仓库[, 作者, 描述]}写成缓存/_publish.json,用curl -X POST发到/api/publish(Authorization: Bearer <~/.tiepm/认证>)。
⚠️ 两个已知行为要记牢:
- 无密钥时:提示后跳过注册,但整体仍返回成功——别把"发布完成"当成"索引已登记"。
- 资产名是硬约定:安装端按
<仓库末段>_v<版本>.zip拼下载 URL,Release 里传的文件名与仓库目录名对不上就装不上。
安全设计
- 完整性:安装强制比对 SHA256(索引无哈希则跳过);下载仅判
curl退出码,无大小/文件名检查。 - 路径安全:
校验包名拦截路径穿越(限于安装链路)。 - 服务端:
sync.RWMutex保护索引读写(读并发、写独占);发布 API 校验必填字段,缺则 400;搜索大小写不敏感;哈希日志预览超 16 字符截断。 - 认证:发布走 Bearer 令牌(官网有注册/登录/控制台)。
已知局限与后续
| 局限 | 说明 |
|---|---|
无 更新 / 卸载 | CLI 未实现 |
| 版本约束有限 | 不支持 ~、<、>、区间 |
| 无纯玄铁 SHA256 | 依赖外部命令(三平台分派) |
| 无 lockfile | 按约束取最高满足版本(未找到锁文件机制) |
| 搜索只匹配包名 | 不含描述/关键词 |
| 缓存清理不彻底 | 只清 ~/.tiepm/缓存,CWD 残留需手动 |
| 发布不校验包名 | 校验只在安装链路 |
| 登记失败仍可能"成功" | 无密钥时跳过注册但返回成功 |
项目文件结构
tiepm/
├── 铁铺.xt # CLI 入口(命令分发)
├── 核心.xt # 核心实现(索引/版本/下载/哈希/解压/依赖/发布)
├── 核心_test.xt # 自检(内含旧索引地址,不参与主流程)
├── 示例tiepm.toml # 清单示例(四节齐全)
└── tiepm.exe # 构建产物(发行时同时产出到 build/env/tiepm.exe)
tiepm-site/ # 官网(Go + embed 静态 + data/index.json)构建:xtc 铁 tiepm/铁铺.xt -sc tiepm/tiepm.exe(CI 与发行打包同款)。
平台支持
v0.2.1 起 Windows / macOS / Linux 均可用:平台靠 uname -s 探测(失败回退 Windows),路径分隔符、目录操作、move/xcopy、certutil/shasum/sha256sum、缓存清理各自分派;若探测失败会按 Windows 分支执行("探测失败 ≠ 不可用")。