aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-20 11:36:57 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-20 11:36:57 +0800
commit3115e70aac230bf86a65c4f50eaa561f36550b40 (patch)
tree4f15623fccb3c8a72bb3fefcdc0cf2fc9f372dd3
parent4bdaa699231aed2c0360d459072c7ba0ae25ee88 (diff)
refactor: extract `docs.rs` feature reading into reusable function
-rw-r--r--.run/src/bin/deploy-api-docs.rs35
-rw-r--r--.run/src/lib.rs76
2 files changed, 80 insertions, 31 deletions
diff --git a/.run/src/bin/deploy-api-docs.rs b/.run/src/bin/deploy-api-docs.rs
index ea52886..7aa093c 100644
--- a/.run/src/bin/deploy-api-docs.rs
+++ b/.run/src/bin/deploy-api-docs.rs
@@ -2,43 +2,16 @@ use std::path::Path;
use tools::{println_cargo_style, run_cmd};
-const DOCS_RS_MANIFEST: &str = "mingling/Cargo.toml";
const OUTPUT_DIR: &str = "docs/api-docs";
fn main() {
let repo_root = find_git_repo().expect("Failed to find git repository root");
- let manifest_path = repo_root.join(DOCS_RS_MANIFEST);
- if !manifest_path.exists() {
- eprintln!("Error: Manifest not found at {}", manifest_path.display());
+ // Read features from [package.metadata.docs.rs]
+ let features = tools::read_features().unwrap_or_else(|e| {
+ eprintln!("Error: {}", e);
std::process::exit(1);
- }
-
- // Read and parse [package.metadata.docs.rs]
- let manifest_content =
- std::fs::read_to_string(&manifest_path).expect("Failed to read Cargo.toml");
- let cargo_toml: toml::Value = manifest_content
- .parse()
- .expect("Failed to parse Cargo.toml");
-
- let doc_features = cargo_toml
- .get("package")
- .and_then(|p| p.get("metadata"))
- .and_then(|m| m.get("docs"))
- .and_then(|d| d.get("rs"))
- .and_then(|rs| rs.get("features"))
- .and_then(|f| f.as_array())
- .unwrap_or_else(|| {
- eprintln!("Error: [package.metadata.docs.rs] or its 'features' key not found in mingling/Cargo.toml");
- std::process::exit(1);
- });
-
- let features: Vec<&str> = doc_features.iter().filter_map(|v| v.as_str()).collect();
-
- if features.is_empty() {
- eprintln!("Error: No features defined in [package.metadata.docs.rs]");
- std::process::exit(1);
- }
+ });
let features_arg = features.join(",");
diff --git a/.run/src/lib.rs b/.run/src/lib.rs
index d52c7fd..cff606a 100644
--- a/.run/src/lib.rs
+++ b/.run/src/lib.rs
@@ -334,6 +334,82 @@ pub fn run_cmd_with_progress(phase: &str, label: &str, cmd: String) -> Result<()
}
}
+/// Read `[package.metadata.docs.rs].features` from `mingling/Cargo.toml`.
+///
+/// Finds the git repository root, reads `mingling/Cargo.toml`, parses it as TOML,
+/// and extracts the feature list under `[package.metadata.docs.rs].features`.
+///
+/// # Errors
+///
+/// Returns `std::io::Error` if:
+/// - The git repository root cannot be found.
+/// - The manifest file cannot be read.
+/// - The TOML cannot be parsed.
+/// - The `[package.metadata.docs.rs].features` key is missing or empty.
+pub fn read_features() -> Result<Vec<String>, std::io::Error> {
+ // Find git repo root
+ let mut current_dir = std::env::current_dir()?;
+ let repo_root = loop {
+ let git_dir = current_dir.join(".git");
+ if git_dir.exists() && git_dir.is_dir() {
+ break Some(current_dir);
+ }
+ if !current_dir.pop() {
+ break None;
+ }
+ };
+ let repo_root = repo_root.ok_or_else(|| {
+ std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ "Failed to find git repository root",
+ )
+ })?;
+
+ let manifest_path = repo_root.join("mingling/Cargo.toml");
+ if !manifest_path.exists() {
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ format!("Manifest not found at {}", manifest_path.display()),
+ ));
+ }
+
+ let manifest_content = std::fs::read_to_string(&manifest_path)?;
+ let cargo_toml: toml::Value = manifest_content.parse().map_err(|e| {
+ std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ format!("Failed to parse Cargo.toml: {}", e),
+ )
+ })?;
+
+ let doc_features = cargo_toml
+ .get("package")
+ .and_then(|p| p.get("metadata"))
+ .and_then(|m| m.get("docs"))
+ .and_then(|d| d.get("rs"))
+ .and_then(|rs| rs.get("features"))
+ .and_then(|f| f.as_array())
+ .ok_or_else(|| {
+ std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ "[package.metadata.docs.rs] or its 'features' key not found in mingling/Cargo.toml",
+ )
+ })?;
+
+ let features: Vec<String> = doc_features
+ .iter()
+ .filter_map(|v| v.as_str().map(String::from))
+ .collect();
+
+ if features.is_empty() {
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "No features defined in [package.metadata.docs.rs]",
+ ));
+ }
+
+ Ok(features)
+}
+
#[must_use]
pub fn cargo_tomls() -> Vec<std::path::PathBuf> {
let mut cargo_tomls = Vec::new();