depclean/
lib.rs

1// src/lib.rs
2
3// Re-export modules for easier external access.
4pub mod parser;
5pub mod graph;
6pub mod analysis;
7pub mod impact;
8pub mod report;
9pub mod cli;
10// Optional: Include if you're supporting npm as well.
11
12use clap::Parser;
13use std::fs;
14
15use crate::cli::Cli;
16use crate::parser::parse_cargo_lock;
17use crate::graph::DependencyGraph;
18use crate::analysis::{find_duplicates, find_optimal_version};
19use crate::impact::estimate_impact;
20use crate::report::{print_report, VersionSuggestion};
21
22/// Runs the main functionality of the depclean tool.
23///
24/// This function:
25/// - Parses command-line arguments using Clap.
26/// - Reads the specified lockfile (e.g., Cargo.lock).
27/// - Parses the lockfile into a structured format.
28/// - Builds a dependency graph from the parsed data.
29/// - Analyzes the graph for duplicate dependencies.
30/// - Generates version suggestions and estimates potential savings.
31/// - Prints a formatted report to standard output.
32pub fn run() {
33    // Create a Tokio runtime to execute asynchronous code.
34    let rt = tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime");
35
36    rt.block_on(async {
37        // Parse command-line arguments.
38        let args = Cli::parse();
39
40        // Load the lockfile contents.
41        let lockfile_contents = fs::read_to_string(&args.lockfile)
42            .expect("Failed to read lockfile");
43
44        // Parse the Cargo.lock file.
45        let lockfile = parse_cargo_lock(&lockfile_contents)
46            .expect("Failed to parse lockfile");
47
48        // Build the dependency graph from the parsed packages.
49        let graph = DependencyGraph::from_lockfile(lockfile.package);
50
51        // Analyze duplicates in the dependency graph.
52        let duplicates = find_duplicates(&graph);
53
54        // Generate version suggestions for each duplicate dependency.
55        let mut suggestions = Vec::new();
56        for dup in &duplicates {
57            // Use the duplicate's package name as the crate name.
58            let recommended = find_optimal_version(&dup.name, &dup.versions).await
59                .unwrap_or_else(|| "No optimal version found".to_string());
60            suggestions.push(VersionSuggestion {
61                recommended_version: recommended,
62                estimated_saving: 10 * (dup.versions.len() - 1), // simplistic calculation
63            });
64        }
65
66        // Optionally, perform a more detailed impact estimation.
67        let _impact = estimate_impact(&duplicates);
68
69        // Print the final report.
70        print_report(duplicates, suggestions);
71    });
72}