Skip to content

fix: list tar.zst entries with --zstd as its own argument - #11

Merged
caokai674 merged 1 commit into
hitmux:mainfrom
Dai2010:fix/tar-zstd-listing
Oct 2, 2026
Merged

caokai674 merged 1 commit into
hitmux:mainfrom
Dai2010:fix/tar-zstd-listing

Conversation

@Dai2010

@Dai2010 Dai2010 commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

问题

.tar.zst 在 TUI 归档浏览器里永远显示为空列表——不报错,是静默空列表,因此既不能浏览,也不能从里面预览或提取条目。

原因在 src/lib/tui_archive_ops.cpp 的 list_tar():列出 zstd 压缩的 tar 时,"--zstd -tf" 被当作一个 argv 元素传给了 tar:

std::string flags = "-tf";
if (type == file_type::FileType::ARCHIVE_TAR_ZSTD) {
    flags = "--zstd -tf";
}
...
auto result = run_command_capture({"tar", flags, archive_path});

tar 不接受把长选项与短选项合并成单个参数,直接以退出码 64 拒绝:

$ tar '--zstd -tf' a.tar.zst
tar: unrecognized option '--zstd -tf'
Try 'tar --help' or 'tar --usage' for more information.
$ echo $?
64

于是 list_tar() 走 result.exit_code != 0 的分支返回空列表。

解压路径从未受影响——它本来就把 --zstd 作为独立参数传入({"tar", "--zstd", "-xf", ...})。坏的只有「列表」这一步,所以命令行提取正常、只有 TUI 浏览是空的。同一归档的对照:

$ tar --zstd -tf a.tar.zst      # 正确写法
a.txt
$ echo $?
0

$ hitpag a.tar.zst out          # 解压路径
$ echo $?
0                               # 且 out/a.txt 已落地

修复

把 tar 命令按参数逐个构造,让 zstd 的「列表」与 zstd 的「解压」保持同一种形状:

std::vector<std::string> cmd = {"tar"};
if (type == file_type::FileType::ARCHIVE_TAR_ZSTD) {
    /* zstd has no tar short option, so it must be its own argv element:
     * tar rejects the merged "--zstd -tf" with exit code 64. */
    cmd.push_back("--zstd");
    cmd.push_back("-tf");
} else if (type == file_type::FileType::ARCHIVE_TAR_GZ) {
    cmd.push_back("-tzf");
}
...
cmd.push_back(archive_path);

auto result = run_command_capture(cmd);

测试

tests/tui_smoke_test.cpp 新增 test_tar_zstd_listing():用 tar --zstd -cf 造一个 .tar.zst,断言 list_archive(..., ARCHIVE_TAR_ZSTD, "") 非空、且条目路径正确。(路径做了引号处理,取 front() 前先判空。)

该断言在修复前必然失败:

FAIL: list_archive should list tar.zst entries

两设备验证

设备 验证的修订 结果
aarch64 / Android(Termux, clang++, vendored FTXUI) f4d4dc8(最终) 100% tests passed out of 4(10.67 s)
x86_64 / Ubuntu(g++, vendored FTXUI) f42cd1b(最终提交的前一版;此后只增加了「缺 zstd 时跳过」的守卫) 100% tests passed, 0 tests failed out of 4(4.08 s)

反向对照:在 x86_64 与 aarch64 上各把 src/lib/tui_archive_ops.cpp 回退到本次修复之前、只重建 tui_smoke_test,都会重现上面那条 FAIL: list_archive should list tar.zst entries(该提交未改动修复源码,对照仍准确)。

另外单独验过「缺 zstd 工具」这条路径(PATH 里只放 tar):

skip tar.zst listing coverage: tool not available
tui_smoke_test passed

范围

只改这一处列表参数拼装,并补一条断言。未触碰解压路径;.tar.gz / .tar.bz2 / .tar.xz 的列表用的是单个合法短选项(-tzf / -tjf / -tJf),行为不变。

list_tar() passed "--zstd -tf" as a single argv element, and tar rejects
that merged option with exit code 64. list_archive() therefore returned an
empty entry list for every tar.zst archive, so the TUI could not browse
them at all. Extraction was never affected: it already passes --zstd as a
separate argument.

Build the tar command as a vector of arguments so the zstd listing has the
same shape as the zstd extraction path, and add a smoke assertion that
fails on the merged form. The assertion skips when the optional zstd tool
is absent, matching the existing single-file zstd coverage.
@caokai674
caokai674 merged commit a607ef5 into hitmux:main Oct 2, 2026
1 check passed
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.

2 participants