feat(file_ops): 日志导出改为分卷 zip,不再截断文件#246
Open
ocsin1 wants to merge 2 commits into
Open
Conversation
- 按 24.5 MB/卷切分,所有 on_error/vision 图保证完整入包 - 图片按 mtime 新→旧排序,最近崩溃图一定在 part01.zip - async + spawn_blocking 解决导出期间 UI 卡顿 - 产物移到 debug_exports/,自动保留最近 10 次 - vision 始终包含;export_logs 去掉 save_draw 参数
Contributor
There was a problem hiding this comment.
Hey - 我发现了 1 个问题,并留下了一些整体性的反馈:
- 在
estimate_entry_upper_bound中,从archive_name.as_bytes().len()切换到archive_name.len(),对于包含非 ASCII 字符的名称,会低估头部大小;建议改回按字节长度计算,以确保上界估算仍然安全。 prune_old_exports在计算let keep_others = MAX_EXPORTS_TO_KEEP - 1时假设MAX_EXPORTS_TO_KEEP >= 1;添加一个 debug 断言或前置返回的保护,可以让它在常量未来被修改时更健壮。
给 AI Agent 的提示
Please address the comments from this code review:
## Overall Comments
- 在 `estimate_entry_upper_bound` 中,从 `archive_name.as_bytes().len()` 切换到 `archive_name.len()`,对于包含非 ASCII 字符的名称,会低估头部大小;建议改回按字节长度计算,以确保上界估算仍然安全。
- `prune_old_exports` 在计算 `let keep_others = MAX_EXPORTS_TO_KEEP - 1` 时假设 `MAX_EXPORTS_TO_KEEP >= 1`;添加一个 debug 断言或前置返回的保护,可以让它在常量未来被修改时更健壮。
## Individual Comments
### Comment 1
<location path="src-tauri/src/commands/file_ops.rs" line_range="695-700" />
<code_context>
- Ok(zip_path.to_string_lossy().to_string())
+/// 从导出目录名末尾解出 `YYYYMMDD-HHMMSS` 时间戳作为排序键。
+fn parse_export_timestamp(dir_name: &str) -> Option<String> {
+ const TS_LEN: usize = 15;
+ if dir_name.len() < TS_LEN {
+ return None;
+ }
+ let tail = &dir_name[dir_name.len() - TS_LEN..];
+ let bytes = tail.as_bytes();
+ let shape_ok = bytes[..8].iter().all(|b| b.is_ascii_digit())
</code_context>
<issue_to_address>
**issue (bug_risk):** 按字节索引切片 `dir_name` 在遇到非 ASCII 目录名时可能会 panic。
`dir_name.len()` 返回的是字节长度,因此 `&dir_name[dir_name.len() - TS_LEN..]` 可能会把非 ASCII 名称中的 UTF‑8 码点切成两半,从而在运行时触发 panic。由于你只需要 `YYYYMMDD-HHMMSS` 这个后缀,建议基于 `dir_name.as_bytes()` 操作,然后对尾部使用 `from_utf8`,或者从后往前查找 `-` 分隔符并基于字节切片做校验,这样既能避免 panic,又能保留基于时间戳的排序行为。
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的评审。
Original comment in English
Hey - I've found 1 issue, and left some high level feedback:
- In
estimate_entry_upper_bound, switching fromarchive_name.as_bytes().len()toarchive_name.len()can underestimate header size for non-ASCII names; consider reverting to byte length to ensure the upper bound remains safe. prune_old_exportsassumesMAX_EXPORTS_TO_KEEP >= 1when computinglet keep_others = MAX_EXPORTS_TO_KEEP - 1; adding a debug assertion or early-return guard would make this more robust against future changes to the constant.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `estimate_entry_upper_bound`, switching from `archive_name.as_bytes().len()` to `archive_name.len()` can underestimate header size for non-ASCII names; consider reverting to byte length to ensure the upper bound remains safe.
- `prune_old_exports` assumes `MAX_EXPORTS_TO_KEEP >= 1` when computing `let keep_others = MAX_EXPORTS_TO_KEEP - 1`; adding a debug assertion or early-return guard would make this more robust against future changes to the constant.
## Individual Comments
### Comment 1
<location path="src-tauri/src/commands/file_ops.rs" line_range="695-700" />
<code_context>
- Ok(zip_path.to_string_lossy().to_string())
+/// 从导出目录名末尾解出 `YYYYMMDD-HHMMSS` 时间戳作为排序键。
+fn parse_export_timestamp(dir_name: &str) -> Option<String> {
+ const TS_LEN: usize = 15;
+ if dir_name.len() < TS_LEN {
+ return None;
+ }
+ let tail = &dir_name[dir_name.len() - TS_LEN..];
+ let bytes = tail.as_bytes();
+ let shape_ok = bytes[..8].iter().all(|b| b.is_ascii_digit())
</code_context>
<issue_to_address>
**issue (bug_risk):** Slicing `dir_name` by byte index can panic for non-ASCII directory names.
`dir_name.len()` returns a byte length, so `&dir_name[dir_name.len() - TS_LEN..]` can split a UTF‑8 code point for non‑ASCII names and panic at runtime. Since you only need the `YYYYMMDD-HHMMSS` suffix, consider operating on `dir_name.as_bytes()` and then `from_utf8` the tail, or searching backward for the `-` separator and validating via byte slices to avoid panics while preserving timestamp-based sorting.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
正文
Summary by Sourcery
将日志导出为多卷 zip 归档文件,提供更精确的大小控制,并自动保留最近的导出记录。
New Features:
debug_exports目录下,并将第一卷的路径返回给调用方。Enhancements:
Original summary in English
Summary by Sourcery
Export logs into multi-volume zip archives with better size accounting and automatic retention of recent exports.
New Features:
Enhancements: