Skip to content

build: 编译期拒绝实验构建 libgit2 并修正最低版本声明(1.4→1.7) - #12

Open
OrbitZore wants to merge 1 commit into
mainfrom
build/libgit2-experimental-guard
Open

OrbitZore wants to merge 1 commit into
mainfrom
build/libgit2-experimental-guard

Conversation

@OrbitZore

Copy link
Copy Markdown
Owner

Summary

修复 #8 的两个构建诚实性缺陷。

问题

  1. 实验构建 libgit2 编译失败无指引:链接以 -DGIT_EXPERIMENTAL_SHA256 构建的 libgit2(如 libgit2-experimental)时,gitmount 恰在两处 git_oid_fromstr 调用点(src/rawobj.cpp:33 的 oid_from_hex、src/gitmount.cpp:480 的 /commit 命名空间解析)以裸的 too few arguments 编译失败——实验构建下该函数为三参签名,且 git_oid 结构体布局更大(20→33 字节)。v0.1 不支持,但使用者无从得知这是"不支持"而非"待适配"。手动定义 GIT_EXPERIMENTAL_SHA256 无法"启用"(会与库的 git_oid ABI 脱钩),正确的编译期探测是包含 <git2.h> 后检查 GIT_OID_SHA256_HEXSIZE(该宏只在实验头文件分支定义)。
  2. CMake 最低版本声明失真:CMakeLists.txt 声明 libgit2>=1.4,但 src/gitrepo.cpp 使用的 git_repository_oid_type 与 rawobj 使用的 git_oid_t 均首见于 libgit2 v1.7.0,1.4–1.6 系统库在编译阶段必然失败。

实现

  • 新建 src/git_compat.hpp(GPL-3.0-or-later,仿现有头文件风格):全程序统一的 git2 头文件入口,包含 <git2.h> 后以 #ifdef GIT_OID_SHA256_HEXSIZE 探测实验头文件分支,触发带指引的 #error(指向 RFC 0000 §1.3)。仓库内 4 处直接 #include <git2.h>(src/rawobj.hpp、src/gitrepo.hpp、src/errmap.cpp、tests/unit/test_errmap.cpp)全部改为包含 git_compat.hpp,守卫由此覆盖每一个接触到 git2 头的翻译单元(链路:gitmount.hpp → gitrepo.hpp → git_compat.hpp 等,直接包含者亦然)。
  • CMakeLists.txt:系统 libgit2 最低版本 1.4 → 1.7,注释注明依据(git_repository_oid_type/git_oid_t 首见于 v1.7.0);vendored 固定 v1.9.7 不受影响。
  • rfc/0000-gitmount.md §1.3(非目标) 按现有条目风格补记一条:SHA-256 对象格式仓库(v0.1;需 libgit2 实验构建,编译期守卫先行拒绝),使规格口径与能力一致。仅此一条,未动其他章节。
  • CHANGELOG.md 新增 [Unreleased] / ### Changed 三条对应记录。

rawobj 中参数化的 64 位分支(oid_type == GIT_OID_SHA1 ? 40 : 64 等)是正确的未来铺垫,保留不动——待真正支持时只需删守卫 + 适配两处 fromstr + 补 CI 矩阵。

负向验证

在 /tmp 用小探针模拟实验头文件(定义 GIT_OID_SHA256_HEXSIZE 后包含 git_compat.hpp),g++ -std=c++17 -I src 编译:

$ g++ -std=c++17 -I src -c guard_neg.cpp
In file included from guard_neg.cpp:2:
src/git_compat.hpp:15:2: error: #error "gitmount v0.1 does not support libgit2 built with GIT_EXPERIMENTAL_SHA256: the git_oid API/ABI differs (3-argument git_oid_fromstr, larger git_oid). See RFC 0000 §1.3."
   15 | #error \
      |  ^~~~~

不定义宏时同一探针编译通过(exit 0)。另:对照本机 libgit2 1.9.7 头文件确认 GIT_OID_SHA256_HEXSIZE 仅在 #ifdef GIT_EXPERIMENTAL_SHA256 分支(oid.h)中定义,非实验构建头文件不定义该宏——探针选择正确。

测试结果

$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DGITMOUNT_WERROR=ON   # libgit2 1.9.7 found (>=1.7)
$ cmake --build build -j$(nproc)                                       # 0 warnings, -Werror on
$ ctest --test-dir build --output-on-failure
1/2 Test #1: unit ............................. Passed  0.16 sec
2/2 Test #2: integration ...................... Passed  1.24 sec
100% tests passed out of 2

clang-format -i(18.1.8,CI 钉住版本)已应用于全部改动的 .hpp/.cpp。

风险

  • 纯构建期改动,不触碰任何运行时路径;非实验 libgit2 下产物与改动前等价(仅 include 归一)。
  • 系统库恰为 1.4–1.6 的环境将从"链接/编译期失败"变为"configure 阶段即报 libgit2>=1.7 未找到",失败更早、信息更明确;此类环境此前本就无法构建。
  • 无新增/变更 -o 选项、挂载可见语义或缓存/锁行为,故未动 docs/filesystem-semantics.md、man 页与 README。

Type of change

  • feat: new behavior (semantics-affecting — see checklist below)
  • fix: bug fix (aligns behavior with RFC 0000 / semantics doc)
  • docs: / test: / refactor: / chore: non-semantic change

(以 build: 提交——构建系统/依赖声明修正,非语义变更;清单项按 fix/build 混合口径勾选如下。)

Checklist

  • Commit messages follow Conventional Commits (CI enforces).
  • Unit tests added/updated for new logic.
    (守卫为编译期 #error,单测无法表达"编译失败即通过";以负向编译探针验证,见上。既有单测保持绿。)
  • Integration assertions added when mount-visible behavior changes
    (update tests/fixtures/make_repo.sh if a new repository shape is
    needed).
    (无挂载可见行为变化;集成套件原样通过。)
  • clang-format -i applied to touched sources (CI enforces).
  • No new compiler warnings (-Wall -Wextra -Wpedantic -Werror).

If observable filesystem semantics changed

  • 不适用(无挂载可见语义变化)。

If cache or lock behavior changed

  • 不适用;decompression-counter 断言随集成套件原样通过。

Closes #8

English summary

Fixes two build-honesty defects from #8. (1) Building against an experimental (GIT_EXPERIMENTAL_SHA256) libgit2 used to fail with a bare "too few arguments" at exactly two git_oid_fromstr call sites; its 3-arg signature and larger (33-byte) git_oid ABI are unsupported in v0.1, so this is now a compile-time #error with guidance, probed via #ifdef GIT_OID_SHA256_HEXSIZE (defined only in the experimental header branch — defining GIT_EXPERIMENTAL_SHA256 by hand would desync the struct layout, hence the result-macro probe). New src/git_compat.hpp is the single include point for git2 headers; all four direct #include <git2.h> sites (rawobj.hpp, gitrepo.hpp, errmap.cpp, test_errmap.cpp) now go through it, so the guard covers every TU touching git2 headers. (2) CMake declared libgit2>=1.4 but git_repository_oid_type/git_oid_t first appeared in v1.7.0 — the system minimum is corrected to 1.7 with a rationale comment; the vendored path pins v1.9.7 and is unaffected. Also adds a one-line SHA-256 non-goal entry to RFC 0000 §1.3 and [Unreleased]/Changed CHANGELOG entries. Negative verification: a probe defining GIT_OID_SHA256_HEXSIZE before including git_compat.hpp fails to compile with exactly the intended #error message; without the macro it compiles. Full build with -DGITMOUNT_WERROR=ON is warning-free; ctest: unit + integration 2/2 passed. No runtime paths touched; the rawobj parameterized 64-bit branches are deliberate future groundwork and stay unchanged.

Closes #8

问题(#8):
- 链接以 GIT_EXPERIMENTAL_SHA256 构建的 libgit2 时,gitmount恰在两处
  git_oid_fromstr 调用点(src/rawobj.cpp 的 oid_from_hex、
  src/gitmount.cpp 的 /commit 命名空间解析)以裸的 "too few arguments"
  编译失败——实验构建下该函数为三参签名且 git_oid 结构体布局更大
  (20→33 字节),v0.1 不支持,但使用者无从得知这是"不支持"而非"待适配"。
- CMakeLists.txt 声明 libgit2>=1.4,但 src/gitrepo.cpp 使用的
  git_repository_oid_type 与 rawobj 使用的 git_oid_t 均首见于
  libgit2 v1.7.0,1.4–1.6 的系统库在编译阶段必然失败,声明失真。

实现:
- 新建 src/git_compat.hpp(GPL-3.0-or-later):全程序统一的 git2 头文件
  入口,包含 <git2.h> 后以 #ifdef GIT_OID_SHA256_HEXSIZE 探测实验头文件
  分支(该宏只在实验构建的 oid.h 中定义;手动定义 GIT_EXPERIMENTAL_SHA256
  会与库的 git_oid ABI 脱钩,故用结果宏探测而非原因宏),触发带指引的
  #error。仓库内 4 处直接 #include <git2.h>(src/rawobj.hpp、
  src/gitrepo.hpp、src/errmap.cpp、tests/unit/test_errmap.cpp)全部改为
  包含 git_compat.hpp,守卫由此覆盖每一个接触到 git2 头的翻译单元。
- CMakeLists.txt:系统 libgit2 最低版本 1.4→1.7,注释注明依据
  (git_repository_oid_type/git_oid_t 首见于 v1.7.0);vendored 固定
  v1.9.7 不受影响。
- rfc/0000-gitmount.md §1.3(非目标)补记一条:SHA-256 对象格式仓库
  (v0.1;需 libgit2 实验构建,编译期守卫先行拒绝),使规格口径与
  能力一致。
- CHANGELOG.md 新增 [Unreleased]/Changed 三条对应记录。

rawobj 中参数化的 64 位分支(oid_type == GIT_OID_SHA1 ? 40 : 64 等)是
正确的未来铺垫,保留不动——待真正支持时删守卫 + 适配两处 fromstr +
补 CI 矩阵即可。

验证:
- 负向:在 /tmp 定义 GIT_OID_SHA256_HEXSIZE=64 模拟实验头文件后包含
  git_compat.hpp,g++ -std=c++17 编译失败并输出指引 #error;不定义时
  编译通过。
- cmake -DGITMOUNT_WERROR=ON 全量构建 + ctest(unit + integration)全绿。

Closes #8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

构建:实验构建 libgit2(GIT_EXPERIMENTAL_SHA256)编译失败无指引;CMake 最低版本声明 1.4 失真(实际需 1.7+)

1 participant