#primary-key #xattr #path #table #btrfs #attributes

bin+lib ghee

在文件系统上数据变更管理的一层薄薄的外壳

5 个版本 (3 个破坏性更新)

0.6.1 2023年10月2日
0.5.1 2023年9月20日
0.5.0 2023年9月19日
0.4.0 2023年8月31日
0.3.0 2023年8月11日

#377文件系统

每月 39 次下载

GPL-3.0 许可证

325KB
8K SLoC

C++ 4.5K SLoC // 0.1% comments Rust 4K SLoC // 0.1% comments Shell 122 SLoC // 0.2% comments

Ghee:在 Btrfs 上数据变更管理的一层薄薄的外壳,使用 Linux 扩展属性(xattrs)

使用 Linux 扩展属性(xattrs)管理数据的最佳方式,纯 Rust 编写,由美味、纤维丰富的开源代码组成。

Ghee 提供了用于操作单个文件上的 xattrs 的工具,以及将文件系统作为文档数据库进行工作的工具,其中文件系统路径作为主键,扩展属性作为字段。

可以使用类似 Git 风格的提交来管理 Ghee 表中的数据,这些提交作为 Btrfs 子卷和只读快照实现。

这样,Ghee 利用 Btrfs 的写时复制(CoW)特性,有效地存储增量,即使在大型二进制块中也是如此。

许可证

此软件仅根据 GPL 版本 3 许可。

约定

Ghee 以一致的方式解析扩展属性名称。任何不以 trustedsecuritysystemuser 命名空间开头的 xattr 将默认为 user 命名空间。例如,xattr trusted.uptime 保持不变,而 uptime 将变为 user.uptime

如果可能,扩展属性值将被解析为 f64 数字;否则,它们将被解释为字符串。

REPL

没有参数运行 ghee 将进入一个读取-评估-打印循环(REPL),允许流畅的命令输入

  $ ghee
  Ghee 0.6.0

  ghee$ set ./test -s test=1

等等。

子命令

Ghee 通过一组子命令操作,每个子命令都有一个主要功能。运行 ghee --help 列出它们,并运行 ghee $SUBCMD --help 获取每个子命令的用法信息。

以下列出了每个子命令的示例

移动

将 xattr 值从一个路径移动到另一个路径。

  • ghee mv path1.txt path2.txt:将 path1.txt 上的所有 xattr 移动到 path2.txt
  • ghee mv -f id path1.txt path2.txt:将 xattr id 从 path1.txt 移动到 path2.txt
  • ghee mv -f id -f url path1.txt path2.txt:将 xattrs idurl 从 path1.txt 移动到 path2.txt

复制

从一个路径复制 xattr 值到另一个路径。

  • ghee cp path1.txt path2.txt:复制 path1.txt 中的所有 xattr 到 path2.txt
  • ghee cp -f id path1.txt path2.txt:将 xattr id 从 path1.txt 复制到 path2.txt
  • ghee cp -f id -f url path1.txt path2.txt:将 xattrs idurl 从 path1.txt 复制到 path2.txt

删除

默认情况下,递归删除 xattr 值。

  • ghee rm path.txt:从 path.txt 删除所有 xattr
  • ghee rm dir:从 dir 及其所有子目录中删除所有 xattr
  • ghee rm --flat dir:仅从 dir 中删除所有 xattr,不包括其子目录
  • ghee rm -f id path.txt:从 path.txt 删除 xattr id
  • ghee rm -f id -f url path1.txt path2.txt path3.txt:从 path1.txt、path2.txt 和 path3.txt 中删除 xattrs idurl
  • ghee rm -f name dir:从 dir 及其所有子目录中删除 xattr name

设置

默认情况下,递归设置 xattr 值。

  • ghee set -s id=123 path1.txt:将 path1.txt 上的 xattr id 设置为值 123
  • ghee set -s name=Jama dir:将 dir 及其所有子目录上的 xattr name 设置为值 "Jama"
  • ghee set -s name=Amira --flat dir:仅将 dir 上的 xattr name 设置为值 "Amira",不包括其子目录
  • ghee set -s id=123 -s url=http://example.com path1.txt path2.txt path3.txt:将 path1.txt、path2.txt 和 path3.txt 上的 xattr id 设置为值 123,将 xattr url 设置为值 "http://example.com"

获取

递归地获取并打印一个或多个路径的 xattr 值。

默认情况下,get 子命令输出一个以制表符分隔的表,列顺序为 pathfieldvalue。值字节作为原始数据写入 stdout,不进行解码。

这排除了 user.ghee 前缀,除非传递了 -a --all

要取消递归默认值,请使用 --flat

  • ghee get dir:以原始(未解码)的TSV格式打印目录 dir 以及所有子文件和子目录的所有xattr。
  • ghee get -f id path1.txt:以原始(未解码)的TSV格式打印路径1.txt上的xattr id 和其值。
  • ghee get -f id -f url path1.txt path2.txt path3.txt:以原始(未解码)的TSV格式打印路径1.txt、path2.txt 和 path3.txt 上的xattr idurl 及其相应的值。

get 命令还可以输出JSON - 在这种情况下,值以UTF-8解码,解码失败时填充默认代码点。

  • ghee get -j --flat dir:以UTF-8解码的JSON格式打印目录 dir 本身的所有xattr,但不包括其子目录。
  • ghee get -j -f id path1.txt:以UTF-8解码的JSON格式打印路径1.txt上的xattr id 和其值。
  • ghee get -j -f id -f url path1.txt path2.txt path3.txt:以JSON格式打印路径1.txt、path2.txt 和 path3.txt 上的xattr idurl 及其相应的值。

通过添加 --where(或 -w),可以提供类似SQL WHERE的子句来选择要包含在输出中的文件。例如,ghee get -w age >= 65 ./patients 将选择目录 ./patients 下所有 user.age 属性为65或更大的文件。

get 输出中始终忽略嵌套索引,尽管当指定WHERE样式谓词时,它们将适当用作遍历的快捷方式。

初始化

使用指定的主键将目录初始化为表,可选地从JSON插入记录,每行独立解析 - 请参阅存储库中的 people.json 示例。

示例

  • ghee init -k name ./people:将 ./people 目录标记为主键为 name 的表。
  • ghee init -k state -k id ./people-by-state-and-id:将 ./people-by-state-and-id 目录标记为主键为 [stateid] 的表。
  • ghee init -k sauce ./pizza < ./pizzas.json:将./pizza目录标记为表,以sauce为主键,从./pizzas.json导入记录

创建

init完全相同,但首先创建目录,如果已存在则报错。

插入

将JSON格式的记录插入到表中。

记录从stdin逐行读取。

  • ghee ins ./people < ./people.json:将./people.json中的记录插入到./people的表中,按其主键索引
  • ghee ins ./people ./people.json:与上述相同,但不需要shell进行重定向

删除

从表中删除记录。

它们将从所有表索引中取消链接。

要删除的记录通过提供主键的组成部分或SQL风格的WHERE子句来指定。

  • ghee del ./people Von:因为表的主键是name,从./people及其所有索引中删除name=Von的记录
  • ghee del ./people -w name=Von:如上删除./people/Von,从所有索引中取消链接

索引

对表进行索引。

当Ghee将目录作为数据库表处理时,每个文件作为关系型“记录”,其主键由其位于表目录下的子路径推断。

每个文件的扩展属性作为关系型属性。

Ghee创建的表目录还包含一个特殊的xattr user.ghee.tableinfo,其中存储表的主键和相关索引(包括自身)。

如果没有提供索引位置,它将被放置在索引表的默认路径下。

示例

  • ghee idx -k name ./people ./people-by-name:递归地将./people的内容重新索引到新目录./people-by-name中,主键来自xattr name,并将文件硬链接到./people中相应的文件。

    这意味着./people-by-name目录的文件将使用xattr name中定义的人的名字作为文件名。

    user.ghee.tableinfo xattr为./people记录./people-by-name作为相关索引,反之亦然:./people-by-nameuser.ghee.tableinfo xattr记录./people作为相关索引。

    使用可用的索引,将有机会加速查询,如getdel

  • ghee idx -k region -k name --s ./people-by-name ./people-by-region-and-name:递归地重新索引 ./people-by-name 的内容,将其放入新的目录 ./people-by-region-and-name,其中主键是 xattr region 和 xattr name 的复合(按此顺序),文件通过 ./people-by-name 中的硬链接与 ./people 中的对应文件硬链接。

    两个目录的 user.ghee.tableinfo xattr 将被更新以反映它们的关系。

列表

类似于 ls 命令,列出目录内容,但以 Ghee 的视角进行注释。

每个路径都被标记为表或记录。对于表,给出主键。

  • ghee ls:列出当前目录的内容
  • ghee ls example:列出 ./example 的内容

提交

将表当前状态存储在 Btrfs 快照中,由 UUID 标识。

可选地,可以提供描述自上次快照以来(如果有)所做的更改的消息。

  • ghee commit-m"更新 README.md"

输出提交的 UUID。

日志

显示过去的提交。

  • ghee log:列出当前表的所有过去提交

触摸

类似于 Unix 的 touch 命令,在指定的路径创建一个空文件;如果路径是 Ghee 表的一部分,将根据路径推断 xattr 并写入新文件。

这是向新表添加新记录的便捷方式。

使用 -p / --parents,将创建父目录。

  • ghee touch /pizza/pepperoni:在 /pizza/pepperoni 创建一个空文件,设置 xattr toppingpepperoni,因为 /pizza 表的键是 topping

恢复

将路径恢复到 HEAD 提交的状态。

  • ghee restore README.md

重置

将表中所有文件重置到指定提交的状态。

  • ghee reset add133b4-f58b-a64e-992a-46f983a0e7ed

依赖项

~9–23MB
~316K SLoC