diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-06-07 15:18:24 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-06-07 15:18:24 +0800 |
| commit | 8aa276beb88086b866be8a446289106be237348a (patch) | |
| tree | e9081d7b417fee79e59d55bde75ef5de71646121 /mling/src/proj_mgr | |
| parent | 81b348ade98ec12516d0e43e2dc930e1cb3a27a5 (diff) | |
Add hformat_cargo, hprintln_cargo macros and help rendering
Diffstat (limited to 'mling/src/proj_mgr')
| -rw-r--r-- | mling/src/proj_mgr/metadata.rs | 142 | ||||
| -rw-r--r-- | mling/src/proj_mgr/mod.rs | 22 |
2 files changed, 160 insertions, 4 deletions
diff --git a/mling/src/proj_mgr/metadata.rs b/mling/src/proj_mgr/metadata.rs new file mode 100644 index 0000000..c44ed46 --- /dev/null +++ b/mling/src/proj_mgr/metadata.rs @@ -0,0 +1,142 @@ +use serde::Deserialize; +use serde::Serialize; + +use std::path::PathBuf; +use std::process::Command; + +/// Read cargo metadata by running `cargo metadata` with the given manifest path. +pub fn read_metadata(cargo_toml: PathBuf) -> Result<CargoLockFile, std::io::Error> { + let output = Command::new("cargo") + .arg("metadata") + .arg("--format-version") + .arg("1") + .arg("--manifest-path") + .arg(cargo_toml) + .output()?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + format!("cargo metadata failed: {}", stderr), + )); + } + + let lock_file: CargoLockFile = serde_json::from_slice(&output.stdout) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + + Ok(lock_file) +} + +/// A cargo metadata lock file that serde can serialize and deserialize. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CargoLockFile { + pub packages: Vec<Package>, + #[serde(rename = "workspace_members")] + pub workspace_members: Vec<String>, + #[serde(rename = "workspace_default_members")] + pub workspace_default_members: Vec<String>, + pub resolve: Resolve, + #[serde(rename = "target_directory")] + pub target_directory: String, + #[serde(rename = "build_directory")] + pub build_directory: String, + pub version: u64, + #[serde(rename = "workspace_root")] + pub workspace_root: String, + pub metadata: Option<serde_json::Value>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Package { + pub name: String, + pub version: String, + pub id: String, + pub license: Option<String>, + #[serde(rename = "license_file")] + pub license_file: Option<String>, + pub description: Option<String>, + pub source: Option<String>, + pub dependencies: Vec<Dependency>, + pub targets: Vec<Target>, + pub features: std::collections::BTreeMap<String, Vec<String>>, + #[serde(rename = "manifest_path")] + pub manifest_path: String, + pub metadata: Option<serde_json::Value>, + pub publish: Option<serde_json::Value>, + pub authors: Vec<String>, + pub categories: Vec<String>, + pub keywords: Vec<String>, + pub readme: Option<String>, + pub repository: Option<String>, + pub homepage: Option<String>, + pub documentation: Option<String>, + pub edition: String, + pub links: Option<String>, + #[serde(rename = "default_run")] + pub default_run: Option<String>, + #[serde(rename = "rust_version")] + pub rust_version: Option<String>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Dependency { + pub name: String, + pub source: Option<String>, + pub req: String, + pub kind: Option<String>, + pub rename: Option<String>, + pub optional: bool, + #[serde(rename = "uses_default_features")] + pub uses_default_features: bool, + pub features: Vec<String>, + pub target: Option<String>, + pub registry: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub path: Option<String>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Target { + pub kind: Vec<String>, + #[serde(rename = "crate_types")] + pub crate_types: Vec<String>, + pub name: String, + #[serde(rename = "src_path")] + pub src_path: String, + pub edition: String, + pub doc: bool, + pub doctest: bool, + pub test: bool, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "required-features")] + pub required_features: Option<Vec<String>>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Resolve { + pub nodes: Vec<ResolveNode>, + pub root: Option<String>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ResolveNode { + pub id: String, + pub dependencies: Vec<String>, + pub deps: Vec<DepInfo>, + pub features: Vec<String>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DepInfo { + pub name: String, + pub pkg: String, + #[serde(rename = "dep_kinds")] + pub dep_kinds: Vec<DepKind>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DepKind { + pub kind: Option<String>, + pub target: Option<String>, +} diff --git a/mling/src/proj_mgr/mod.rs b/mling/src/proj_mgr/mod.rs index 381784c..07a9910 100644 --- a/mling/src/proj_mgr/mod.rs +++ b/mling/src/proj_mgr/mod.rs @@ -1,6 +1,20 @@ -use mingling::macros::dispatcher; +use crate::ThisProgram; +use mingling::{ + Program, + macros::{dispatcher, program_setup}, +}; -dispatcher!("install"); +pub mod metadata; -dispatcher!("ls.namespace", CMDListNamespace => EntryListNamespace); -dispatcher!("rm.namespace", CMDRemoveNamespace => EntryRemoveNamespace); +dispatcher!("show.binaries"); +dispatcher!("show.workspace"); +dispatcher!("show.target-dir", + CMDShowTargetDirectories => EntryShowTargetDirectories +); + +#[program_setup] +pub fn project_manager_setup(p: &mut Program<ThisProgram>) { + p.with_dispatcher(CMDShowBinaries); + p.with_dispatcher(CMDShowWorkspace); + p.with_dispatcher(CMDShowTargetDirectories); +} |
