kit.program/kit/doc/kit remote 仓库格式设计.md

16 KiB
Raw Permalink Blame History

  • 基于 webdav 协议访问。包括远程仓库存储方案(基于 WebDAV 协议)与本地客户端存储方案
  • 支持存储多种操作系统Linux、Windows、多种架构X86、aarch64
  • 支持记录官网地址,方便定期从官网拉取新版本存储。

Part A远程仓库存储方案基于 WebDAV

1. 概述

本方案定义了一种基于 WebDAV 协议访问的远程仓库存储格式,用于存储开源项目的目标代码(二进制分发文件)。仓库支持:

  • 多种操作系统Linux、Windows、macOS、FreeBSD 等)
  • 多种硬件架构x86_64、aarch64、armv7、i386 等)
  • 平台无关的二进制文件(如 Java JAR、Python 轮包、纯 JS 文件等)
  • 单文件可执行程序与多文件压缩包zip、tar.gz 等)
  • 版本管理(语义化版本)与元数据记录

仓库通过 WebDAV 的目录和文件操作进行访问,支持枚举、下载、上传、删除等操作。

2. 仓库根目录结构

/repo/                          # WebDAV 服务暴露的根路径
  └─ {group}/                   # 分组目录,默认 /modules空值等同 /
      └─ {project-id}/          # 项目目录(唯一标识),实际路径为 group/id
          ├─ metadata.json      # 项目级元数据文件
          └─ {version}/         # 版本目录(如 1.0、1.1、2.0
              ├─ version.json   # 版本级元数据文件(推荐)
              ├─ any/any/       # 平台无关文件目录(保留字)
              │   └─ ...        # 单文件或压缩包
              ├─ {os}/          # 操作系统(如 linux, windows, darwin
              │   └─ {arch}/    # 架构(如 x86_64, aarch64
              │       └─ ...    # 具体二进制文件或压缩包
              └─ ...

2.1 命名规则

  • project-id:来自项目 meta.json 中的唯一 id,小写字母、数字、连字符(-),长度 ≤ 64。
  • group:来自项目 meta.json,默认 /modules;空字符串等同 /;支持 /docker/tmpls/docker/net 等子路径。
  • version:来自项目 meta.jsonversion;若为空,发布时根据远程 metadata.json.version 尾数 +1远程不存在时初始为 1.0
  • osarch 使用标准化名称(见下表),any 为保留字,表示任意平台。
操作系统 标准名称 架构 标准名称
Linux linux x86_64 x86_64
Windows windows aarch64 aarch64
macOS darwin armv7 armv7
FreeBSD freebsd i386 i386
任意平台 any 任意架构 any

2.2 目录说明

  • any/any/:存放与操作系统和架构均无关的文件(如 JAR、纯 Python 脚本、WASM 模块)。客户端在任何平台均可直接使用此目录下的文件。
  • {os}/{arch}/:存放特定平台、特定架构的二进制文件或压缩包。
  • 同一版本下可同时包含 any/any/ 和具体平台目录。

3. 元数据文件规范

3.1 项目级元数据:metadata.json

位于每个项目根目录UTF-8 编码JSON 格式。

字段说明

| 字段名 | 类型 | 必选 | 说明 | | project_id | string | 是 | 项目唯一标识,与目录名相同 | | group | string | 否 | 仓库分组路径,默认 /modules,空值等同 / | | official_url | string | 是 | 项目官网地址(用于定期拉取新版本) | | description | string | 否 | 项目简述 | | version | string | 是 | 当前远程最新版本号;不再使用 versions 数组 | | last_fetch_check | string (ISO 8601) | 否 | 上次检查官网更新的时间戳 | | fetch_rules | array of objects | 否 | 自动拉取时的匹配规则(见 3.3 | | extra | object | 否 | 扩展字段 |

示例

{
  "project_id": "myapp",
  "group": "/modules",
  "official_url": "",
  "description": "An example tool",
  "version": "1.2",
  "last_fetch_check": "2026-06-15T12:00:00Z",
  "fetch_rules": [...],
  "extra": { "license": "Apache-2.0" }
}

3.2 版本级元数据:version.json

位于每个版本目录下,包含该版本的详细信息和文件清单。

字段说明

字段名 类型 必选 说明
version string 版本号,与目录名一致
release_date string (ISO 8601) 官方发布日期
official_download_url string 官网的直接下载页或 API 地址
artifacts array of objects 该版本包含的所有文件条目(见 3.2.1
checksums object 文件路径到哈希值的映射(可选,与 artifacts 可共存)
signatures object 文件路径到数字签名的映射
3.2.1 artifacts 数组中每个对象的字段
字段名 类型 必选 说明
path string 相对于版本目录的文件路径,如 linux/x86_64/myappany/any/app.zip
type string 文件类型:executable(单文件可执行)、archive(压缩包)、library(库文件)、data(资源数据)
archive_format string type="archive" 时,取值为 ziptar.gztar.xz
entry_point string type="archive" 时,指定压缩包内的可执行文件相对路径(如 bin/app
unpack boolean 是否建议客户端自动解压,默认 false。若为 true,客户端解压后应运行 entry_point
checksum string 该文件的哈希值(格式 算法:值,如 sha256:abc...

示例

  • 单文件可执行Linux
{
  "version": "1.0.0",
  "artifacts": [
    {
      "path": "linux/x86_64/myapp",
      "type": "executable"
    }
  ],
  "checksums": {
    "linux/x86_64/myapp": "sha256:e3b0c442..."
  }
}
  • 多文件压缩包Windows
{
  "version": "2.0.0",
  "artifacts": [
    {
      "path": "windows/x86_64/myapp.zip",
      "type": "archive",
      "archive_format": "zip",
      "entry_point": "myapp/bin/myapp.exe",
      "unpack": true
    }
  ]
}
  • 平台无关 JAR 文件
{
  "version": "3.0.0",
  "artifacts": [
    {
      "path": "any/any/myapp.jar",
      "type": "executable"
    }
  ]
}

3.3 自动拉取规则(fetch_rules

metadata.json 中可定义 fetch_rules 数组,用于指导自动化工具从官网下载并分类存储。

每个规则对象包含:

字段名 类型 说明
url_pattern string 正则表达式,匹配下载 URL
os string 目标操作系统(linuxwindowsdarwinany 等)
arch string 目标架构(x86_64aarch64any 等)
type string 文件类型(executablearchive
archive_format string 可选,当 type="archive" 时指定
entry_point string 可选,压缩包内的入口点
unpack boolean 可选,是否自动解压

示例

"fetch_rules": [
  {
    "url_pattern": ".*-linux-amd64\\.tar\\.gz$",
    "os": "linux",
    "arch": "x86_64",
    "type": "archive",
    "archive_format": "tar.gz",
    "entry_point": "myapp/bin/myapp",
    "unpack": true
  },
  {
    "url_pattern": ".*\\.jar$",
    "os": "any",
    "arch": "any",
    "type": "executable"
  }
]

4. 客户端访问方式

基于 WebDAV 协议,客户端可通过以下 HTTP 方法操作:

  • PROPFIND列举项目、版本、os/arch 目录。
  • GET:下载二进制文件或元数据文件。
  • PUT / MKCOL:上传新版本或新文件(用于手动或自动填充)。
  • DELETE:删除过期版本。

推荐 WebDAV 服务器配置:启用目录列表、支持 CORS、支持 HTTPS。

5. 自动化拉取新版本流程

外部工具(如 cron 作业)按以下步骤更新仓库:

  1. 遍历仓库根目录下每个项目的 metadata.json
  2. 访问 official_url,获取所有可用版本列表及最新版本。
  3. 对比已存储版本,找出缺失的新版本。
  4. 对于每个新版本,根据 fetch_rules(或内置逻辑)匹配下载 URL下载对应的二进制/压缩包。
  5. os / arch / any 规则存放到 {group}/{project-id}/{version}/{os}/{arch}/ 下。
  6. 计算文件哈希,生成或更新该版本的 version.json
  7. 更新项目级 metadata.jsonversiongrouplast_fetch_check),不再写入 versions

Part B本地客户端存储方案用于版本管理与回退

1. 概述

客户端从远程 WebDAV 仓库下载项目的目标代码后,需要在本地持久化存储,并支持:

  • 多版本共存
  • 当前激活版本的快速切换(符号链接)
  • 版本回退(无需重新下载)
  • 压缩包自动解压与入口点管理
  • 元数据记录(安装历史、校验信息)
  • 可配置的旧版本清理策略

2. 本地根目录结构

客户端约定一个根目录(如 ~/.cache/artifact-repo/~/.local/share/artifact-repo/),其下按项目组织:

~/.local/share/artifact-repo/
  └─ {project-id}/                # 项目目录(与远程 project-id 一致)
      ├─ .meta/                   # 元数据目录(隐藏)
      │   ├─ install.json         # 本地安装记录
      │   └─ history/             # 可选,操作历史 JSON 文件
      ├─ versions/                # 所有已下载的版本
      │   ├─ {semver}/            # 版本目录(如 1.2.0
      │   │   ├─ .version.json    # 从远程复制的 version.json附加本地信息
      │   │   └─ {os}/{arch}/     # 与远程结构一致的实际文件
      │   │        └─ ...
      │   └─ {semver}/...
      └─ current -> versions/{semver}   # 符号链接,指向当前激活的版本

注意:符号链接可放在项目根目录下,也可放在 .meta/current。推荐项目根目录下的 current,便于外部脚本直接引用(如 $REPO_HOME/myapp/current/bin/myapp)。

3. 元数据文件 install.json

位于 .meta/install.json,记录项目的本地安装状态。

字段说明

字段名 类型 说明
project_id string 项目标识
installed_versions array of strings 已下载到本地的所有版本号
current_version string 当前激活的版本号(应与 current 符号链接一致)
last_updated string (ISO 8601) 最后一次变更时间(安装、切换、删除)
history array of objects 操作历史记录,每个元素包含 timestamp, action, version, from(可选)
options object 客户端配置,如 auto_cleanup, max_versions

示例

{
  "project_id": "myapp",
  "installed_versions": ["1.0.0", "1.2.0", "1.2.1"],
  "current_version": "1.2.1",
  "last_updated": "2026-06-15T14:30:00Z",
  "history": [
    {
      "timestamp": "2026-06-10T09:00:00Z",
      "action": "install",
      "version": "1.0.0"
    },
    {
      "timestamp": "2026-06-15T14:30:00Z",
      "action": "switch",
      "version": "1.2.1",
      "from": "1.2.0"
    }
  ],
  "options": {
    "auto_cleanup": true,
    "max_versions": 5
  }
}

4. 版本目录中的 .version.json

从远程仓库的 version.json 复制而来,并增加本地特有字段:

{
  "version": "1.2.1",
  "installed_at": "2026-06-15T14:25:00Z",
  "local_checksums": {
    "linux/x86_64/myapp": "sha256:..."
  },
  ... // 原始远程字段artifacts, release_date 等)
}

5. 核心操作流程

5.1 安装新版本(更新)

  1. 从远程 WebDAV 仓库下载指定版本的所有相关文件到 versions/{new_version}/,保持远程目录结构(包括 any/any/ 和具体平台目录)。
  2. 同时下载 version.json 并保存为 .version.json,添加 installed_at 时间戳。
  3. 更新 .meta/install.json
    • new_version 加入 installed_versions(若未存在)。
    • 设置 current_versionnew_version(若需要立即激活)。
    • 添加历史记录(action: "install""switch")。
  4. 更新项目根目录下的 current 符号链接指向 versions/{new_version}
  5. 如果 artifacts 中有 type="archive"unpack=true 的条目,则解压到版本目录下的特定子目录(如 extracted/),并在 .version.json 中记录解压后的入口点路径。
  6. 根据 options 中的清理策略删除旧版本(保留最近 N 个版本或保留指定天数)。

5.2 回退到已安装的旧版本

  1. 确认目标旧版本存在于 installed_versions 中。
  2. 修改 current 符号链接指向 versions/{old_version}
  3. 更新 .meta/install.json
    • current_version 改为 old_version
    • 添加历史记录(action: "rollback""switch",可记录 from 原版本)。
  4. 无需重新下载任何文件。

5.3 卸载特定版本

  1. 如果卸载的是当前激活版本,先切换到另一个已安装版本(或提示用户)。
  2. 删除 versions/{version} 整个目录。
  3. install.jsoninstalled_versions 数组中移除该版本。
  4. 添加历史记录(action: "uninstall")。

5.4 清理旧版本(自动或手动)

清理策略示例:

  • 保留最近 max_versions 个版本(不计当前版本)。
  • 或删除 keep_recent_days 天之前安装且不是当前版本的版本。
  • 每次安装新版本后自动触发清理。

6. 处理压缩包archive的特别说明

当远程 artifactunpack=true 时:

  • 客户端下载压缩包到 versions/{version}/{path}
  • 立即解压到同目录下的 _extracted/ 子目录(例如 versions/1.2.1/linux/x86_64/_extracted/)。
  • 根据 entry_point.version.json 中记录解压后的可执行文件绝对路径(或相对于版本目录的路径)。
  • 符号链接 current 可以直接指向解压后的入口点文件,而不是整个版本目录。实现方式:
    current/bin/myapp -> ../versions/1.2.1/_extracted/bin/myapp
    

这样切换版本时只需更新符号链接,无需重新解压。

7. 多平台兼容性

客户端在下载时,应根据当前运行的操作系统和架构,仅从远程仓库获取匹配的文件:

  • 优先尝试 {os}/{arch}/
  • 若不存在,回退到 any/any/
  • 下载后保持远程的相对路径结构,但客户端实际运行时只使用与当前平台相关的文件。

在本地存储中,所有版本目录仍保留完整的 {os}/{arch}/any/any/ 结构,便于在不同平台间迁移或共享缓存。