lmrc_cargo_workspace/
lib.rs

1//! # Cargo Workspace Manager
2//!
3//! A comprehensive library for managing Cargo workspaces programmatically.
4//!
5//! This library provides a high-level API for:
6//! - Discovering and analyzing Cargo workspaces
7//! - Detecting workspace members (binaries and libraries)
8//! - Analyzing dependency relationships between crates
9//! - Building and testing workspace members programmatically (including selective and parallel builds)
10//! - Managing versions across workspace members using semver
11//! - Parsing and updating Cargo.toml files while preserving formatting
12//! - Cargo metadata integration for resolved dependency information
13//! - Workspace validation and linting (formatting, clippy, dependencies)
14//!
15//! ## Quick Start
16//!
17//! ```no_run
18//! use lmrc_cargo_workspace::{
19//!     workspace::Workspace,
20//!     build::{WorkspaceBuilder, BuildConfig},
21//!     version::{VersionManager, BumpType, VersionUpdateStrategy},
22//!     dependency::DependencyGraph,
23//! };
24//! use std::path::Path;
25//!
26//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
27//! // Discover workspace
28//! let workspace = Workspace::discover(Path::new("."))?;
29//! println!("Found workspace at: {}", workspace.root.display());
30//! println!("Members: {}", workspace.members.len());
31//!
32//! // Analyze dependencies
33//! let graph = DependencyGraph::from_workspace(&workspace)?;
34//! let build_order = graph.topological_sort()?;
35//! println!("Build order: {:?}", build_order);
36//!
37//! // Build workspace
38//! let builder = WorkspaceBuilder::new(&workspace);
39//! let result = builder.build_all(&BuildConfig::default())?;
40//! if result.success {
41//!     println!("Build succeeded!");
42//! }
43//!
44//! // Bump versions
45//! let version_mgr = VersionManager::new(&workspace);
46//! let changes = version_mgr.preview_changes(
47//!     VersionUpdateStrategy::BumpAll(BumpType::Patch)
48//! )?;
49//! for change in &changes {
50//!     println!("{}", change.description());
51//! }
52//! # Ok(())
53//! # }
54//! ```
55//!
56//! ## Features
57//!
58//! ### Workspace Discovery
59//!
60//! Automatically find and parse Cargo workspaces:
61//!
62//! ```no_run
63//! use lmrc_cargo_workspace::workspace::Workspace;
64//! use std::path::Path;
65//!
66//! // Discover workspace from current directory
67//! let workspace = Workspace::discover(Path::new("."))?;
68//!
69//! // Or load from specific path
70//! let workspace = Workspace::from_path(Path::new("/path/to/workspace"))?;
71//!
72//! // Access workspace members
73//! for member in &workspace.members {
74//!     println!("Member: {} at {}", member.name, member.path.display());
75//! }
76//! # Ok::<(), lmrc_cargo_workspace::error::Error>(())
77//! ```
78//!
79//! ### Dependency Analysis
80//!
81//! Analyze dependency relationships and build orders:
82//!
83//! ```no_run
84//! use lmrc_cargo_workspace::{workspace::Workspace, dependency::DependencyGraph};
85//! use std::path::Path;
86//!
87//! let workspace = Workspace::discover(Path::new("."))?;
88//! let graph = DependencyGraph::from_workspace(&workspace)?;
89//!
90//! // Get dependencies of a crate
91//! let deps = graph.workspace_dependencies("my-crate");
92//! for dep in deps {
93//!     println!("Depends on: {}", dep.name);
94//! }
95//!
96//! // Get reverse dependencies
97//! let dependents = graph.dependents("my-lib");
98//! println!("Crates depending on my-lib: {:?}", dependents);
99//!
100//! // Get build order
101//! let order = graph.topological_sort()?;
102//! println!("Build in this order: {:?}", order);
103//! # Ok::<(), lmrc_cargo_workspace::error::Error>(())
104//! ```
105//!
106//! ### Version Management
107//!
108//! Manage versions across workspace members:
109//!
110//! ```no_run
111//! use lmrc_cargo_workspace::{
112//!     workspace::Workspace,
113//!     version::{VersionManager, BumpType, VersionUpdateStrategy},
114//! };
115//! use std::path::Path;
116//! use semver::Version;
117//!
118//! let workspace = Workspace::discover(Path::new("."))?;
119//! let version_mgr = VersionManager::new(&workspace);
120//!
121//! // Bump all crates by patch version
122//! let changes = version_mgr.update_versions(
123//!     VersionUpdateStrategy::BumpAll(BumpType::Patch)
124//! )?;
125//!
126//! // Apply changes
127//! version_mgr.apply_changes(&changes)?;
128//! # Ok::<(), lmrc_cargo_workspace::error::Error>(())
129//! ```
130//!
131//! ### Build and Test
132//!
133//! Build and test workspace members programmatically:
134//!
135//! ```no_run
136//! use lmrc_cargo_workspace::{
137//!     workspace::Workspace,
138//!     build::{WorkspaceBuilder, BuildConfig, TestConfig, BuildProfile},
139//! };
140//! use std::path::Path;
141//!
142//! let workspace = Workspace::discover(Path::new("."))?;
143//! let builder = WorkspaceBuilder::new(&workspace);
144//!
145//! // Build in release mode
146//! let mut config = BuildConfig::default();
147//! config.profile = BuildProfile::Release;
148//! let result = builder.build_all(&config)?;
149//!
150//! // Run tests
151//! let test_result = builder.test_all(&TestConfig::default())?;
152//! # Ok::<(), lmrc_cargo_workspace::error::Error>(())
153//! ```
154//!
155//! ### Manifest Manipulation
156//!
157//! Parse and update Cargo.toml files while preserving formatting:
158//!
159//! ```no_run
160//! use lmrc_cargo_workspace::manifest::Manifest;
161//! use std::path::Path;
162//! use semver::Version;
163//!
164//! let mut manifest = Manifest::from_path(Path::new("Cargo.toml"))?;
165//!
166//! // Update version
167//! manifest.set_package_version(&Version::new(2, 0, 0))?;
168//!
169//! // Update dependency
170//! manifest.update_dependency("serde", "2.0", "dependencies")?;
171//!
172//! // Save (preserves formatting and comments)
173//! manifest.save()?;
174//! # Ok::<(), lmrc_cargo_workspace::error::Error>(())
175//! ```
176//!
177//! ## Error Handling
178//!
179//! All operations return a [`Result<T, Error>`](error::Error) with comprehensive error types:
180//!
181//! ```no_run
182//! use lmrc_cargo_workspace::{workspace::Workspace, error::Error};
183//! use std::path::Path;
184//!
185//! match Workspace::discover(Path::new(".")) {
186//!     Ok(workspace) => println!("Found workspace!"),
187//!     Err(Error::WorkspaceNotFound(path)) => {
188//!         eprintln!("No workspace found at: {}", path.display());
189//!     }
190//!     Err(e) => eprintln!("Error: {}", e),
191//! }
192//! ```
193
194pub mod build;
195pub mod dependency;
196pub mod error;
197pub mod manifest;
198pub mod metadata;
199pub mod selective;
200pub mod validation;
201pub mod version;
202pub mod workspace;
203
204// Re-export commonly used types
205pub use error::{Error, Result};
206
207#[cfg(test)]
208mod tests {
209    #[test]
210    fn test_version() {
211        // Ensure crate version is valid
212        let version = env!("CARGO_PKG_VERSION");
213        assert!(!version.is_empty());
214    }
215}