Implement all 14 environment checks for the `pdftract doctor` subcommand. Each check returns a CheckResult with status (OK/WARN/FAIL/NotApplicable) and a human-readable detail message. Checks implemented: - pdftract binary (version, git SHA, compiled features) - tesseract install (version check: >=5 OK, ==4 WARN, <=3 FAIL) - tesseract languages (eng + requested langs present) - leptonica install (>=1.79 OK, older WARN, not found FAIL) - libtiff (pkg-config check with ldconfig fallback) - libopenjp2 (pkg-config check with ldconfig fallback) - pdfium native lib (version >=6555 OK, older WARN, not found FAIL) - network reachability (HEAD example.com with 5s timeout) - cache directory (writable, free space >=1 GiB, layout version) - profile search path (YAML parse, PROFILE_SECRETS_FORBIDDEN detection) - ulimit -n (>=1024 OK, 512-1024 WARN, <512 FAIL) - available RAM (>=256 MiB OK, 128-256 WARN, <128 FAIL) - system locale (UTF-8 OK, non-UTF-8 WARN, unset FAIL) - temp dir writable (writable + free space >=100 MiB) Core module with Check trait, CheckResult, CheckStatus, DoctorCtx, DoctorFeatures, and panic-safe run_check_safe wrapper. Build script injects GIT_SHA and COMPILED_FEATURES at compile time. All checks feature-gated appropriately (ocr, full-render, remote, profiles). Co-Authored-By: Claude Code <noreply@anthropic.com>
58 lines
2.2 KiB
Rust
58 lines
2.2 KiB
Rust
use std::env;
|
|
use std::process::Command;
|
|
|
|
fn main() {
|
|
// Capture git SHA for version reporting
|
|
let git_sha = Command::new("git")
|
|
.args(["rev-parse", "HEAD"])
|
|
.output()
|
|
.ok()
|
|
.and_then(|o| String::from_utf8(o.stdout).ok())
|
|
.map(|s| s.trim().to_string())
|
|
.unwrap_or_else(|| "unknown".to_string());
|
|
|
|
println!("cargo:rustc-env=GIT_SHA={}", git_sha);
|
|
|
|
// Emit compile-time feature list
|
|
// These are the cargo features that affect doctor output
|
|
let features = [
|
|
("OCR", cfg!(feature = "ocr")),
|
|
("FULL_RENDER", cfg!(feature = "full-render")),
|
|
("REMOTE", cfg!(feature = "remote")),
|
|
("PROFILES", cfg!(feature = "profiles")),
|
|
("SERVE", cfg!(feature = "serve")),
|
|
("MCP", cfg!(feature = "mcp")),
|
|
("INSPECT", cfg!(feature = "inspect")),
|
|
("GREP", cfg!(feature = "grep")),
|
|
("CACHE", cfg!(feature = "cache")),
|
|
("RECEIPTS", cfg!(feature = "receipts")),
|
|
("MARKDOWN", cfg!(feature = "markdown")),
|
|
];
|
|
|
|
let enabled: Vec<&str> = features.iter()
|
|
.filter(|(_, enabled)| *enabled)
|
|
.map(|(name, _)| *name)
|
|
.collect();
|
|
|
|
let feature_list = if enabled.is_empty() {
|
|
"default".to_string()
|
|
} else {
|
|
enabled.join(",")
|
|
};
|
|
|
|
println!("cargo:rustc-env=COMPILED_FEATURES={}", feature_list);
|
|
|
|
// Rebuild if git HEAD changes (for accurate GIT_SHA in dev builds)
|
|
println!("cargo:rerun-if-changed=.git/HEAD");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_OCR");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_FULL_RENDER");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_REMOTE");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_PROFILES");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_SERVE");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_MCP");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_INSPECT");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_GREP");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_CACHE");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_RECEIPTS");
|
|
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_MARKDOWN");
|
|
}
|