refactor(official-sync): CLI 工程卫生清理

- doctor daemon_status 检查(3-3):ok 与 message 原分别取自解析结果和文件存在性,
  文件存在但解析失败时会“ok=false 却提示可解析”。改为从同一次解析结果派生两者。
- localize_error_message(3-1a):空壳直通占位函数,删除并在 4 处调用点直接用消息。
- daemon 路径 helper 形参(3-1b):output_root 实际语义是 state_dir,统一改名消除误导。
- stop_daemon 非 RPC 路径(3-1c):删除无意义的 let-else(_pid 读后丢弃、两分支
  逐字重复 stop_daemon_inner+print_report),stop_daemon_inner 内已做 PID 校验。
- parse_http_status(3-1d):改为锚定 curl stderr 中 "error" 之后再取三位状态码,
  避免误取端口/字节数等无关三位数字;新增锚定测试。
- 非 Unix process_exists(3-1e):补注释说明保守返回 true 的理由(无法探测存活,
  避免误回收可能仍在运行的 daemon)。

对应 issue #18 维护清单 3-1、3-3。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 09:35:31 -07:00
co-authored by Claude Fable 5
parent 28e9ce5a6f
commit 0656ad05c7
2 changed files with 49 additions and 39 deletions
+21 -4
View File
@@ -500,7 +500,12 @@ fn classify_failure(
}
fn parse_http_status(stderr: &str) -> Option<u16> {
let bytes = stderr.as_bytes();
// curl 的 HTTP 状态错误形如 "curl: (22) The requested URL returned error: 404"。
// 锚定到最后一个 "error" 之后再取三位状态码,避免误取 stderr 中其它三位数字
// (如字节数、IP 片段)而错判 HTTP 状态。
let anchor = stderr.rfind("error")?;
let tail = &stderr[anchor..];
let bytes = tail.as_bytes();
let mut index = 0usize;
while index < bytes.len() {
if !bytes[index].is_ascii_digit() {
@@ -512,9 +517,10 @@ fn parse_http_status(stderr: &str) -> Option<u16> {
index += 1;
}
if index - start == 3 {
let status = stderr[start..index].parse::<u16>().ok()?;
if (100..=599).contains(&status) {
return Some(status);
if let Ok(status) = tail[start..index].parse::<u16>() {
if (100..=599).contains(&status) {
return Some(status);
}
}
}
}
@@ -541,6 +547,17 @@ mod tests {
assert!(!failure.retryable());
}
#[test]
fn parse_http_status_anchors_on_curl_error_context() {
// 状态码前出现无关三位数字(如端口 443)时,仍从 "error" 之后取真正的状态码。
assert_eq!(
parse_http_status("curl: (22) URL https://host:443/a returned error: 503"),
Some(503)
);
// stderr 中不含 "error" 上下文时不猜测状态码。
assert_eq!(parse_http_status("connected to host 200 ok"), None);
}
#[test]
fn treats_5xx_as_retryable() {
let status = std::process::ExitStatus::from_raw(22 << 8);