跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

资料库

获取和管理文档版本,更新、回滚和恢复,以及 .crib 资料包格式。

1 - 管理资料库

启用、停用、卸载和导入版本,应用更改,恢复以前的资料组合,以及专家模式和“非正式发布”标记的含义。

资料库是 Crib 里已安装的全部文档。打开方式:菜单“资料库 → 管理资料库…”、工具栏的资料库按钮,或主页的“资料库”。菜单“资料库 → 获取更多版本…”和主页的“获取版本”直接打开“全部版本”。

已安装与全部版本

顶部的分段控件切换两种列表:

列表内容
已安装这台 Mac 上的资料包,包括已停用的
全部版本已安装的,加上版本目录里还没安装的;未安装的行显示下载大小和安装后大小

列表按版本状态分组(默认、常规、历史版本……),含义见版本与别名。每行还标出来源(内置或自行安装)、占用空间,以及是否在当前搜索范围内。

筛选框接受版本号或别名,例如 18、pg17、[email protected]。输入能解析成一个确切版本的别名时,列表只显示那一项。

专家模式

专家模式默认关闭,这时列表只显示“默认”和“常规”两组。打开后,列表还显示历史版本、开发版、无法下载和状态未知的版本,不加版本前缀的搜索也会包含它们。

资料库和正文上方的“版本”弹窗里各有一个“专家模式”开关,两处改的是同一个设置。

启用与停用

已安装的每一行左侧有一个勾选框。勾选或取消后,行内显示“应用后启用”或“应用后停用”,底栏显示“有未应用的更改”。点“应用更改”生效,点“放弃更改”撤回。

  • 同一个资料包只能启用一个修订。勾选某个修订时,同一资料包的其他修订会自动取消勾选。
  • 已停用的行右侧有“启用”按钮,点它立即生效,不需要再点“应用更改”。
  • 停用的版本仍在磁盘上,但不参与搜索,也不能从列表打开阅读。

应用更改时发生什么

  1. Crib 用勾选的资料包在后台建立一个新的搜索世代(generation)。进度面板依次显示“下载 → 校验 → 建立索引 → 启用”;不需要下载时从“校验”开始。
  2. 建立期间,旧的搜索世代照常提供搜索和阅读。点“继续阅读”可以关掉资料库窗口,任务在后台继续。
  3. 新世代建好后原子切换。之后的搜索使用新组合;已经打开的页面继续显示打开时的版本。

切换前点“取消”,旧组合保持不变。失败时资料库显示原因和“重试”。

卸载

只有自行安装的资料包有“卸载”按钮。App 内置的资料包不能卸载,只能停用。

卸载分两步:

  1. Crib 先切换到一个不含该资料包的组合,这一行标为“待移除”,显示“不再用于阅读和恢复后即可清理”。
  2. 文件在执行“维护 → 清理不再需要的资料”时删除,前提是没有打开的页面、当前组合或保留的旧组合还在使用它。

卸载不删除笔记、书签和更正。指向已卸载内容的个人资料会保留,内容重新安装后可以再次定位。

导入资料包

点资料库右上角的“导入资料包…”,选择一个 .crib 文件(旧扩展名 .pgdocpack 也可以),或一个已解开的资料包文件夹。导入不需要联网。

Crib 先检查磁盘空间,再解包并逐项校验:签名必须由 App 自带的可信根签发,每个文件的哈希必须与清单一致,数据库结构必须符合格式。通过后,新资料包立即启用,并替换同一资料包当前启用的修订。

以下情况会被拒绝:

  • 与已安装的资料包同名同修订、内容却不同。
  • 修订号低于当前启用的修订。要回到旧修订,用下面的“恢复资料组合…”。
  • 签名密钥不在可信根里,或是开发密钥签名而当前构建不接受开发内容。
说明

现在没有公开发布的资料包。开发构建只能导入用开发密钥签名的测试资料包。格式见资料包格式。

恢复资料组合

每次切换组合时,Crib 保留切换前启用的那一组,以便回退;更早的组合会被释放。

  1. 点底栏的“恢复资料组合…”,从菜单中选一个保留的组合。
  2. 预览窗口列出“现在启用 N 项,恢复后启用 M 项”,以及要启用、停用或替换的资料包、修订和语言。
  3. 点“恢复”。Crib 先完整校验目标组合,再切换。
  • 资料库里有未应用的更改时不能恢复,先应用或放弃它们。
  • 预览打开后如果组合被别的操作改变,点“刷新预览”后再确认。
  • 已打开的页面、笔记和书签不受影响。

维护菜单

命令作用
清理不再需要的资料删除待移除的资料包,以及不再被当前组合、保留组合或打开的页面使用的搜索世代
备份个人资料…把笔记、书签、标签、阅读历史和更正备份成一个 SQLite 文件,见备份个人资料

启动时的修复提示

Crib 启动时如果发现当前组合不能用(例如 App 换新后原来内置的资料包不在了,或搜索世代损坏),会自动换到一个可用的组合,并在资料库顶部留一条提示,直到你点“知道了”。提示带“重新启用”按钮时,可以把之前启用的资料包重新启用。

“非正式发布”标记

资料库标题旁的“非正式发布”标记表示:这些资料用开发密钥签名,只用于本地测试。构建声明接受开发内容,或 App 自带的可信根是开发可信根时,就会显示这个标记。

Crib 还没有正式签名密钥,现在所有开发构建都会显示它。

2 - 版本与别名

Crib 收录的 31 条 PostgreSQL 版本线、版本目录里五种状态的含义,以及 pg、pg18、pg96、[email protected] 这类别名怎样解析到一个确切版本。

收录的版本线

Crib 收录 31 条 PostgreSQL 手册版本线,每条一个中英双语资料包;Wiki 是另一个资料包。默认版本是 PostgreSQL 18(18.6),也是 pg 别名的目标;只内置一个版本的构建内置的就是它。

版本线内容版本别名
6.3 – 6.56.3.2、6.4.2、6.5.3pg63 … pg65,或 pg6.3 … pg6.5
7.0 – 7.47.0.3、7.1.3、7.2.8、7.3.21、7.4.30pg70 … pg74,或 pg7.0 … pg7.4
8.0 – 8.48.0.26、8.1.23、8.2.23、8.3.23、8.4.22pg80 … pg84,或 pg8.0 … pg8.4
9.0 – 9.69.0.23、9.1.24、9.2.24、9.3.25、9.4.26、9.5.25、9.6.24pg90 … pg96,或 pg9.0 … pg9.6
10 – 1410.23、11.22、12.22、13.23、14.24pg10 … pg14
15 – 1815.19、16.15、17.11、18.6pg15 … pg18
1919rc1(预览版)pg19
2020devel(开发快照)pg20、pgdevel
Wikir5pgwiki

内容版本来自构建时固定的来源快照,不代表上游当前的最新小版本。

版本状态

版本目录给每个版本声明一种状态。状态由发布者写进签名目录,Crib 不按版本号、发布渠道或是否已安装去推断。

目录中的值界面显示普通列表和不带版本前缀的搜索下载
default默认包含可以
active常规包含可以
historical历史版本只在专家模式下包含可以
devel开发版只在专家模式下包含可以
unavailable无法下载只在专家模式下包含不能;已安装的照常阅读和搜索
(未声明)状态未知只在专家模式下包含可以
  • 目录里只有一个默认版本,就是 pg 指向的那个。开发版不能成为默认版本。
  • “常规”只表示出现在普通列表里,不表示上游仍在维护。
  • “状态未知”出现在不带状态字段的旧格式目录里。旧目录指定的默认版本仍出现在普通列表。
  • 状态只决定版本出现在哪里、能不能新下载,不影响已安装内容的可读性。显式指定版本(版本前缀、版本菜单、书签、已打开的页面)照常可用,只要该版本已安装并启用。
  • 还没有任何版本目录时,不带版本前缀的搜索只覆盖 App 内置的资料包。
说明

本页不列出各版本的状态。状态由发布者在签名目录中决定,正式目录还没有发布。

列表里还会出现另一组状态:已启用、已停用、未安装、目录已过期、不在目录中、失败、待移除。它们描述这台 Mac 上的安装情况和最近一次操作,与上表的发布状态互相独立。

别名怎样解析

别名只存在于版本目录中,不对应额外的文件。解析规则:

  1. 输入转成 ASCII 小写,PG18 与 pg18 相同。含非 ASCII 字符的输入不是别名。
  2. 沿目录中的别名链一直走到一个确切版本,格式是 项目@内容版本,例如 [email protected]。链不能有环,目标必须存在。
  3. 在这个版本里选出包含所需语言的资料包。现在每个版本是一个中英双语包。
输入解析路径
pgpg → pg18 → [email protected]
pg18pg18 → [email protected]
pg96pg96 → [email protected]
pg9.6pg9.6 → pg96 → [email protected]
pg19pg19 → pg@19rc1
pgdevelpgdevel → pg20 → pg@20devel
pgwikipgwiki → pgwiki@r5
[email protected]本身就是确切版本
  • pg 是唯一的总别名,指向发布者选定的默认版本线。pg19、pg20 不会自动变成 pg。
  • pg18 这类版本线别名指向该线当前发布的小版本。版本号含点的旧版本线同时接受带点写法,如 pg9.6、pg7.0。
  • 解析只读本机已缓存并校验过的目录,不需要联网。

别名不会换成别的小版本

别名总是解析到一个确切版本。目标不可用时,Crib 说明原因,不会改用同一版本线上已安装的其他小版本:

目标状态搜索时的提示(以 18.7 为例)
未安装PG18(18.7)未安装,请在资料库中下载后再搜索。
已停用PG18(18.7)未启用,请在资料库中启用后再搜索。
无法下载且未安装PG18(18.7)已无法下载,请改用已安装的版本。

假设发布者把 pg18 从 18.6 移到 18.7,而你只装了 18.6:资料库在“全部版本”里显示 18.7 未安装;已安装的 18.6 仍可用 [email protected] 或版本菜单打开。

发布新的小版本时,发布者新增一个文件和一条版本记录,再移动对应的版本线别名;18.6 的文件不会被覆盖或改名。只移动别名不会重建搜索索引,也不会改变已打开的页面。

在哪里用别名

  • 搜索框的版本前缀:PG18: vacuum、pg96: vacuum、[email protected]: max_connections lang:en。pg18:vacuum 与 pg18: vacuum 相同。
  • 资料库的筛选框。
  • 本地 API 和 MCP 的搜索文本。

3 - 下载、更新与恢复

从版本目录下载一个版本时的每一步、断点续传、目录过期和离线时的行为,失败时保留什么,以及怎样回到以前的组合。
正式版本目录尚未上线

Crib 默认从 https://repo.pigsty.io/doc/catalog.json 获取版本目录。这个地址是规划中的正式目录,还没有上传,所以现在“刷新目录”拿不到正式目录。下文描述开发构建的行为,在本机测试目录上验证过,没有在公网 HTTPS 和 CDN 上测试。

什么时候联网

打开 Crib 或资料库都不联网。只有两个操作会联网:点“刷新目录”,以及点某个版本的“下载”。

已安装的内容不会过期,阅读和搜索始终离线完成。导入本地资料包也不需要联网。

版本目录

版本目录(catalog.json)列出可下载的版本、它们的状态、别名,以及每个归档的大小和哈希。开发构建可以内置一份签名的目录快照,所以第一次打开、没有联网时也能看到全部版本。

点“刷新目录”时,Crib 下载新目录并检查:

  • 签名必须由 App 自带的可信根签发。服务器不能自己添加可信密钥。
  • 修订号不能低于本机已有的目录;修订号相同而内容不同,只接受签发时间更晚的一份。否则视为回退或冲突,保留原来的目录。
  • 已过期的目录不接受。

刷新失败不改动本机文件。资料库顶部显示“版本目录更新于 …”;刷新中可以点“取消”。

目录过期以后

目录带有效期,由发布者签名时写入。过期后,资料库显示“版本目录已过期,刷新后才能下载。”

  • 版本列表照常显示,别名照常解析。
  • 不能下载新版本,直到刷新到一份未过期的目录。
  • 已安装的内容不受影响。

本机缓存的目录如果无法再通过校验(例如可信根换了密钥),Crib 跳过它,改用 App 内置的快照,并把旧文件移到用户目录的Distribution-rejected/,保留最近 5 份。目录中个别条目有问题时,只忽略那些条目,并在资料库提示;已安装的同一版本照常可读。

下载一个版本

在“全部版本”里点某一行的“下载”。进度面板显示“下载 → 校验 → 建立索引 → 启用”,下载阶段显示已下载和总字节数。

  1. 确认授权。 该版本必须在一份未过期的目录里,且状态不是“无法下载”。归档路径必须是目录给出的相对路径,只走同源 HTTPS,不跟随跨站重定向。
  2. 流式下载。 写入临时目录,总字节数以目录签名的大小为准。
  3. 校验。 核对长度、归档 SHA-256、ZIP 结构、清单哈希(必须等于目录记录的值)、清单签名、解包后的总大小。
  4. 解包。 解到暂存区,再逐个文件核对哈希并检查数据库结构。传输结束后再确认一次目录仍然授权这个版本。
  5. 建立索引。 在后台建立新的搜索世代,旧世代继续服务。
  6. 启用。 原子切换。新版本替换同一资料包当前启用的修订;旧修订仍已安装,状态变为“已停用”。

下载、校验或索引失败时,按钮变为“重试下载”。

断点续传

  • 网络中断时(不包括你点“取消”),已下载的部分保存在用户目录的 Distribution-partials/ 中,保留 7 天。
  • 再次下载同一个归档时,Crib 先重新计算已保存部分的哈希,再用 Range 加 If-Range(强 ETag 或 Last-Modified)请求剩余部分。
  • 服务器返回 206 时必须带完全匹配的 Content-Range;返回 200 就从头重下。最终仍以目录签名的归档哈希为准。
  • 点“取消”,或者校验、大小、路径检查失败时,已下载的部分直接丢弃。
  • 单次下载最长 48 小时;连续 60 秒收不到数据视为中断,已下载部分保留以便续传。目录请求最长 600 秒。

失败、取消与磁盘空间

  • 切换之前的任何失败、取消或磁盘空间不足,都保留原来的组合,不做切换。
  • 资料包写入资料库之前先检查磁盘空间。
  • 切换一旦完成,新组合就是当前组合,即使之后又报告了错误。重试前先看资料库里实际启用的是什么。
  • 失败只记在这一个版本上。之前启用的旧修订照常可读。

更新到新的小版本

发布者发布新的小版本时,新增一个归档并移动版本线别名,例如把 pg18 从 18.6 移到 18.7;18.6 的文件不变。

刷新目录后,“全部版本”里出现 18.7,状态为未安装。刷新本身不会自动下载,也不会重建索引。下载 18.7 后,它替换 18.6 成为启用的修订;18.6 仍已安装,可以重新启用,也可以卸载。

下载或导入同一资料包中比当前启用修订更低的修订会被拒绝。要回到以前的修订,用“恢复资料组合…”。

Crib 没有自动更新。App 本身也没有公开的更新通道。

回到以前的组合

每次切换组合,Crib 保留切换前启用的那一组。在资料库底栏点“恢复资料组合…”可以预览并恢复,步骤见管理资料库。

启动时如果当前搜索世代损坏,或 App 换新后原来内置的资料包不在了,Crib 自动换到保留的组合或 App 内置的初始组合,并在资料库顶部提示。提示里的“重新启用”可以把之前启用的资料包重新启用。

个人资料不受影响

下载、导入、启用、停用、卸载和恢复组合都不写个人资料:笔记、书签、标签、阅读历史、更正、片段和设置。卸载一个版本后,挂在上面的笔记和书签保留;内容重新安装后可以再次定位。

4 - 资料包格式

.crib 文件里有什么、怎样签名和校验、可信根与密钥策略,以及发布目录的布局、不可变规则和 HTTP 缓存要求。
说明

现在没有公开的资料包,也没有正式签名密钥。发布目录规划在 https://repo.pigsty.io/doc/,还没有上传。本页描述开发构建和构建工具 crib-pack 实现的格式。

文件

资料包是一个 ZIP 文件(支持 ZIP64,条目为 stored 或 DEFLATE),条目按名称排序,时间戳固定。2026-11-06 起新发布的资料包以 .crib 结尾;之前签发的目录和归档使用 .pgdocpack,这些已签名的路径继续有效。版本目录里的归档路径只接受这两种结尾,.CRIB、.crib.zip 等都会被拒绝。

App 还没有注册 .crib 文件类型,双击不能导入;请用资料库的“导入资料包…”。

一个手册资料包的内容:

pg/18.6-r4.crib

  • manifest.json清单:身份、版本、语言、文件列表与每个文件的哈希
  • manifest.sig对 manifest.json 原始字节的 Ed25519 签名
  • sources.json来源:上游修订、版次、修复记录和处理说明
  • content.sqlite文档、章节、精确名称键、双语对应、链接和搜索词元
  • documents/
    • en/英文 HTML 与资源
    • zh-Hans/简体中文 HTML 与资源
  • licenses/许可文本,按语言分目录

Wiki 资料包的页面在 documents/<语言>/wiki/<集合>/ 下,另外带有原始来源记录和许可说明 licenses/center-sources.json。

清单

format_version
资料包格式,现在是 1
schema_version
content.sqlite 的结构版本,现在是 1
analyzer_id
分词器标识 pgdash-han2-v1;旧名称属于格式身份,不随产品改名
pack_id
资料包身份,如 postgresql/manual/18、postgresql/wiki
project_id、branch、content_version、channel
项目、版本线、内容版本、发布渠道
pack_revision
修订号,同一 pack_id 跨内容版本单调递增
languages
["en", "zh-Hans"]
min_reader_version
能读取它的最低 Crib 版本
source_manifest_sha256
sources.json 的哈希
files
除清单和签名外每个文件的 path、bytes、sha256
licenses
许可文件路径
trust
签名类别;开发构建中是 development

清单之外出现未声明的文件,或任何文件与清单哈希不符,资料包都会被拒绝。Crib 用 manifest.json 原始字节的 SHA-256 标识一个已安装的资料包,链接里的 manifest 参数就是这个值。

签名与可信根

manifest.sig 是 {"key_id": "…", "signature": "<base64>"},签名对象是 manifest.json 的原始字节。目录 catalog.json 用同样的 Ed25519 签名。

公钥只来自 App 自带的 trust.json。资料包或服务器里的密钥都不会被信任。

{
  "development": false,
  "keys": { "<key_id>": "<base64 公钥>" },
  "key_policies": {
    "<key_id>": { "roles": ["pack", "catalog"], "not_after": "2027-12-31T00:00:00Z" }
  }
}
  • key_policies 可选。roles 取 pack、seed、catalog 的子集;not_after 必须是 YYYY-MM-DDTHH:MM:SSZ。没有列出的密钥可签所有用途、永不过期。
  • 未知字段、空的 roles、不规范的日期、指向不存在密钥的策略都会让整个可信根被拒绝。
  • 密钥过期只阻止获取(刷新目录、下载、导入)和发布端签名,已安装的内容照常可用。
  • 从可信根删除密钥等于吊销。要退役一把密钥,先设 not_after。

开发签名的内容只在两种情况下被接受:构建在 Info.plist 中声明 CribDevelopmentContent=true,或测试环境设置CRIB_ALLOW_DEVELOPMENT_CONTENT=1。这时资料库显示“非正式发布”。

导入与下载时的检查

解包之前,Crib 先完整检查整个 ZIP,拒绝符号链接、特殊文件、加密条目、分卷、路径穿越、大小写或 Unicode 规范化后重名的路径、多余的尾部字节。

上限值
条目数65,000
单个文件8 GiB
解包后总大小16 GiB
压缩文件20 GiB
压缩比1000:1

然后核对签名、每个文件的哈希、数据库结构和引用。同一 pack_id 同一修订号而内容不同的资料包会被拒绝。从目录下载时还要核对归档长度和 SHA-256、清单哈希和解包后大小,它们必须与目录记录一致。

发布目录

https://repo.pigsty.io/doc/(规划中)

  • catalog.json签名目录:别名、版本与状态、每个归档的路径、大小和哈希
  • pg/
    • 18.6-r4.crib
    • 17.11-r4.crib
    • 9.6.24-r4.crib
    • 20devel-r4.crib
  • pgwiki/
    • r5.crib

完整目录有 31 个手册归档和 1 个 Wiki 归档。文件名是内容版本加修订号。别名只写在 catalog.json 里,不复制文件,也不建符号链接。

catalog.json 是一个签名信封,解码后的载荷包含目录身份、修订号、签发和过期时间、默认别名、别名表和版本表:

{"format":"crib-signed-catalog-1","key_id":"…","payload":"<base64>","signature":"<base64>"}
{
  "format_version": 3,
  "catalog_id": "crib-docs",
  "revision": 2026102901,
  "default_alias": "pg",
  "aliases": {"pg": "pg18", "pg18": "[email protected]"},
  "releases": {
    "[email protected]": [{
      "pack_id": "postgresql/manual/18",
      "content_version": "18.6",
      "lifecycle": "default",
      "pack_revision": 4,
      "languages": ["en", "zh-Hans"],
      "archive_path": "pg/18.6-r4.crib",
      "manifest_sha256": "…",
      "archive_sha256": "…"
    }]
  }
}

这是节选,正式载荷还有 generated_at、expires_at、大小、结构版本等字段。版本状态 lifecycle 的含义见版本与别名。

客户端只使用目录给出的归档路径:一级目录加一个文件名,不接受绝对地址、查询串、片段、百分号转义、反斜杠和 ..,下载走与目录同源的 HTTPS。

不可变规则

  • 同一个 URL 的字节永远不变。内容有任何更正,都发新的内容版本或更高的修订号。
  • 修订号按 pack_id 单调递增,换内容版本也不重置:18.6-r4 之后发布 18.7,修订号至少是 r5。
  • 先上传并核对所有新归档,最后再替换 catalog.json。
  • 目录修订号只增不减。crib-pack distribute 的 --previous-catalog 要求新修订号更大;--validity 设定目录有效期,默认 720 小时,范围 24 小时到 400 天。

HTTP 缓存

这些是发布端的要求,还没有在真实服务器上配置和测试。

对象响应头
catalog.jsonCache-Control: no-cache
带版本和修订号的归档Cache-Control: public, max-age=31536000, immutable,Content-Length,强 ETag,支持 Range,不做内容转换

客户端续传时发送 Range 和 If-Range,规则见断点续传。