workspacer_cli/
info.rs

1// ---------------- [ File: workspacer-cli/src/info.rs ]
2crate::ix!();
3
4/// Print general info about the workspace or crate
5#[derive(Debug, StructOpt)]
6pub enum InfoSubcommand {
7    Crate {
8        #[structopt(long = "crate")]
9        crate_name: PathBuf,
10    },
11    Workspace {
12        #[structopt(long = "path")]
13        path: PathBuf,
14    },
15}
16
17impl InfoSubcommand {
18    pub async fn run(&self) -> Result<(), WorkspaceError> {
19        trace!("Entering InfoSubcommand::run with {:?}", self);
20
21        match self {
22            InfoSubcommand::Crate { crate_name } => {
23                info!("Gathering crate info for path='{}'", crate_name.display());
24
25                // 1) Build a CrateHandle from the given path
26                let handle = CrateHandle::new(&crate_name.clone())
27                    .await
28                    .map_err(|crate_err| {
29                        error!("Failed to create CrateHandle for '{}': {:?}", crate_name.display(), crate_err);
30                        WorkspaceError::CrateError(crate_err)
31                    })?;
32
33                // 2) Basic info: name, version, private or not
34                let name = handle.name();
35                debug!("Crate '{}' => retrieved name='{}'", crate_name.display(), name);
36
37                let version = handle.version().map_err(|err| {
38                    error!("Crate '{}' => cannot get version: {:?}", name, err);
39                    WorkspaceError::CrateError(err)
40                })?;
41
42                let is_priv = handle.is_private().await.map_err(|err| {
43                    error!("Crate '{}' => is_private check failed: {:?}", name, err);
44                    WorkspaceError::CrateError(err)
45                })?;
46
47                println!("Crate path='{}'", crate_name.display());
48                println!("  name='{}'", name);
49                println!("  version='{}'", version);
50                println!("  private?={}", is_priv);
51
52                // 3) Check if tests/ directory is present, list test files if so
53                if handle.has_tests_directory() {
54                    let test_files = handle.test_files().await.map_err(|err| {
55                        error!("Crate '{}' => test_files() failed: {:?}", name, err);
56                        WorkspaceError::CrateError(err)
57                    })?;
58                    info!("Crate '{}' => found {} test file(s)", name, test_files.len());
59                    println!("  tests directory is present. Test files: {:?}", test_files);
60                } else {
61                    println!("  no tests/ directory found.");
62                }
63
64                // 4) Check for README
65                match handle.readme_path().await {
66                    Ok(Some(readme)) => {
67                        info!("Crate '{}' => found README at '{}'", name, readme.display());
68                        println!("  README present at '{}'", readme.display());
69                    }
70                    Ok(None) => {
71                        warn!("Crate '{}' => no README.md found", name);
72                        println!("  no README.md present");
73                    }
74                    Err(e) => {
75                        error!("Crate '{}' => error checking readme_path: {:?}", name, e);
76                        return Err(WorkspaceError::CrateError(e));
77                    }
78                }
79
80                // 5) Optionally, gather bin target names if any
81                match handle.gather_bin_target_names().await {
82                    Ok(bin_targets) if !bin_targets.is_empty() => {
83                        debug!("Crate '{}' => found bin targets: {:?}", name, bin_targets);
84                        println!("  bin targets: {:?}", bin_targets);
85                    }
86                    Ok(_) => {
87                        println!("  no [bin] targets found");
88                    }
89                    Err(e) => {
90                        error!("Crate '{}' => gather_bin_target_names failed: {:?}", name, e);
91                        return Err(WorkspaceError::CrateError(e));
92                    }
93                }
94
95                info!("Finished printing info for crate='{}'", name);
96                Ok(())
97            },
98
99            InfoSubcommand::Workspace { path } => {
100                info!("Gathering workspace info at path='{}'", path.display());
101
102                // 1) Build a Workspace from the given path
103                let ws = Workspace::<PathBuf, CrateHandle>::new(path).await.map_err(|err| {
104                    error!("Failed to create Workspace at '{}': {:?}", path.display(), err);
105                    err
106                })?;
107
108                // 2) Print basic workspace details
109                let crate_count = ws.n_crates();
110                println!("Workspace at '{}':", path.display());
111                println!("  number of crates: {}", crate_count);
112
113                // 3) Print each crate’s name, version, etc.
114                //    We’ll do a quick pass: name + (private?).
115                //    If you want more details, you can do an additional lock + gather info.
116                let all_names = ws.get_all_crate_names().await;
117                info!(
118                    "Workspace '{}' => crate names: {:?}",
119                    path.display(),
120                    all_names
121                );
122
123                println!("Crates in this workspace:");
124                for crate_name in all_names {
125                    // We can attempt to find the crate quickly and check if it’s private
126                    if let Some(arc_crate) = ws.find_crate_by_name(&crate_name).await {
127                        let guard = arc_crate.lock().await;
128                        let ver = match guard.version() {
129                            Ok(v) => v.to_string(),
130                            Err(e) => {
131                                warn!("Crate '{}' => cannot retrieve version: {:?}", crate_name, e);
132                                "(unknown)".to_string()
133                            }
134                        };
135                        let priv_status = match guard.is_private().await {
136                            Ok(b) => b,
137                            Err(e) => {
138                                warn!("Crate '{}' => is_private() errored: {:?}", crate_name, e);
139                                false
140                            }
141                        };
142                        println!(
143                            "  - name='{}', version='{}', private?={}",
144                            crate_name, ver, priv_status
145                        );
146                    } else {
147                        println!("  - name='{}' => error finding crate handle", crate_name);
148                    }
149                }
150
151                // That’s enough for a “general info” view.
152                info!("Completed workspace info for path='{}'", path.display());
153                Ok(())
154            }
155        }
156    }
157}