chakcy ecdfacc620 fix+feat: 修复打包/解包主链路,并把存储层重建为内容寻址 + 快照
起始状态:主链路 100% 不可用,而且失败被静默吞掉——打包后库里 0 个文件、
界面仍打印"文件数量: N";解包导出 0 个文件并在磁盘上生成几百层 sub/sub/sub 垃圾目录。

缺陷修复(4 个 P0 + 12 个 P1,逐条见 BUG_REPORT.md):
- 建表列名 compresse_algo 与 INSERT/read_file 用的 compress_algo 不一致
- list_directory 按 path 而非 parent_path 过滤,导致导出无限自递归
- CLI --ignore-timestamps 把 export_filesystem 赋成引用自身的 lambda
- add_file 缺少 commit(直接调用 API 时静默丢数据)
- LIKE 前缀误伤兄弟目录(删 doc 连带删 docs);mv_dir 二次改名
- 失败路径一律返回 exit code 0;--exclude 是子串匹配而非 glob
- FolderPacker.add_file 反向调用 export_file_safe,会用库内内容覆盖源文件

存储层(schema v3,格式变更,提供 vfsmigrate 迁移):
- 内容移入 blobs(hash PRIMARY KEY):相同内容只存一份,跨路径/跨快照共享
- files 的唯一约束改为 UNIQUE(snapshot_id, path):一个库存多个版本
- 完整性:每文件 sha256 + 快照级摘要 + HMAC-SHA256 签名,只读连接即可验证
- 增量打包:按 mtime+size 或 sha256 只写变化项,未变文件不重写不重压
- get_file_info 不再返回 content(元数据查询不该搬 BLOB)

新增能力:
- 可选 FastAPI 静态文件插件(extras,核心仍零第三方依赖)
- 内容寻址发布到对象存储 + 逐对象校验的取回客户端
- 压缩默认改回 zlib:实测比自研哈夫曼体积小 1/3~1/170、快数百倍

其它:
- P2-4:时间戳显式转字符串,清掉 1240 条 DeprecationWarning(盘上格式不变)
- read_file 负数 offset/size 改为报错(原先会走切片语义从末尾取)
- requires-python 从 >=3.7 改为按实际 API 推导的 >=3.9

测试:0 → 343 个用例,纯标准库 unittest,有/无 FastAPI 两种环境都跑通。
证据见 docs/evidence-*.txt。
2026-09-14 00:11:42 +08:00
2025-11-07 20:52:44 +08:00
2025-11-07 20:52:44 +08:00
2026-01-23 17:50:27 +08:00
2026-01-23 17:50:27 +08:00

SQLite Virtual File System (SVFS)

一个基于 SQLite 的虚拟文件系统实现,可以将本地文件夹打包成单个 SQLite 数据库文件,并支持从数据库中解包还原文件。

特性

  • 高效存储: 使用 SQLite 数据库存储文件和目录结构
  • 压缩支持: 可选的文件压缩功能,节省存储空间
  • 完整元数据: 保留文件权限、创建时间、修改时间等元数据
  • 目录结构保持: 完整的目录层级结构保持
  • 简单易用: 提供命令行工具,支持打包和解包操作
  • 跨平台: 支持 Windows、Linux、macOS

安装

从源码安装

# 克隆仓库
git clone <repository-url>
cd svfs

# 使用 uv 安装(推荐)
uv sync

# 或者使用 pip
pip install -e .

使用 uv

项目使用 uv 作为包管理器和构建工具,确保已安装 uv:

# 安装 uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# 在项目目录中安装依赖
uv sync

使用方法

打包文件夹

# 基本用法
vfspack <源文件夹路径> <输出数据库路径>

# 启用压缩
vfspack ./my_folder ./output.db --compress

# 指定文件系统名称
vfspack ./my_folder ./output.db --name "MyFileSystem"

# 排除特定文件模式
vfspack ./my_folder ./output.db --exclude "*.tmp" "*.log"

解包文件系统

# 解包整个文件系统
vfsunpack <数据库路径> <目标文件夹路径>

# 仅列出根目录内容
vfsunpack ./output.db ./output --list-root

# 解包特定文件或目录
vfsunpack ./output.db ./output --path "docs/readme.txt"
vfsunpack ./output.db ./output --path "images/"

# 忽略时间戳错误(仅导出文件内容)
vfsunpack ./output.db ./output --ignore-timestamps

项目结构

svfs/
├── pyproject.toml          # 项目配置和依赖
├── src/svfs/
│   ├── __init__.py
│   ├── core.py             # 核心 SQLiteVFS 类
│   ├── folder_packer.py    # 文件夹打包逻辑
│   ├── folder_unpacker.py  # 文件夹解包逻辑
│   └── cli/
│       ├── __init__.py
│       ├── packer.py       # 打包命令行工具
│       └── unpacker.py     # 解包命令行工具
└── README.md

核心组件

SQLiteVFS 类

主要功能类,提供以下功能:

  • 创建和管理 SQLite 虚拟文件系统数据库
  • 添加/删除文件和目录
  • 读取文件内容
  • 导出文件到本地文件系统
  • 压缩和解压缩文件内容

FolderPacker 类

文件夹打包工具:

  • 遍历本地文件夹结构
  • 将文件和目录信息存储到 SQLite 数据库
  • 支持文件排除模式

FolderUnpacker 类

文件夹解包工具:

  • 从 SQLite 数据库恢复文件系统
  • 验证数据库完整性
  • 支持部分导出和完整导出

数据库结构

filesystem_metadata 表

存储文件系统元数据,包括名称、创建时间、文件总数和总大小。

files 表

存储所有文件和目录信息:

  • path: 文件/目录路径(唯一)
  • name: 文件名
  • parent_path: 父目录路径
  • is_directory: 是否为目录
  • file_size: 文件大小
  • created_time: 创建时间
  • modified_time: 修改时间
  • permissions: 文件权限
  • content: 文件内容(BLOB)
  • compressed: 是否压缩

开发

设置开发环境

# 安装开发依赖
uv sync --dev

# 运行测试
pytest

# 构建包
uv build

代码示例

from svfs.core import SQLiteVFS

# 创建文件系统
vfs = SQLiteVFS("my_files.db", compress=True)
vfs.connect()

# 获取文件系统统计信息
stats = vfs.get_stats()
print(f"文件系统: {stats['name']}")
print(f"文件数量: {stats['total_files']}")

# 列出目录内容
for item in vfs.list_directory("/"):
    print(f"{'DIR' if item['is_directory'] else 'FILE'}: {item['name']}")

vfs.close()

性能说明

  • 压缩功能默认对大于 1KB 的文件启用
  • 使用 zlib 压缩,压缩级别为 6(平衡压缩比和速度)
  • 文件索引优化,支持快速路径查找
  • 批量操作减少数据库事务开销

注意事项

  1. 文件路径统一使用正斜杠(/)存储,与操作系统无关
  2. 时间戳使用 UTC 时间存储
  3. 文件权限使用 Unix 权限位表示
  4. 数据库文件可以在不同平台间迁移
  5. 大文件处理建议启用压缩以减少数据库大小

许可证

MIT License

贡献

欢迎提交 Issue 和 Pull Request 来改进项目。

S
Description
基于 sqlite 的虚拟文件系统
Readme MIT
1.3 MiB
Languages
Python 100%