workspacer_cli/register.rs
1// ---------------- [ File: workspacer-cli/src/register.rs ]
2crate::ix!();
3
4/// Register subcommand for naming files, adding crate references, etc.
5#[derive(Debug, StructOpt)]
6pub enum RegisterSubcommand {
7 /// Ensure all source files in a single crate are “registered”
8 /// (that is, it calls `CrateHandle::ensure_all_source_files_are_registered()`).
9 CrateFiles {
10 /// Path (or name) of the crate directory
11 #[structopt(long = "crate")]
12 crate_name: PathBuf,
13
14 /// If true, skip checking for Git cleanliness
15 #[structopt(long)]
16 skip_git_check: bool,
17 },
18
19 /// Ensure all source files in every crate of a workspace are “registered.”
20 /// (Calls `Workspace::ensure_all_source_files_are_registered()`.)
21 AllFiles {
22 /// Path to the workspace root
23 #[structopt(long = "path")]
24 workspace_path: PathBuf,
25
26 /// If true, skip checking for Git cleanliness
27 #[structopt(long)]
28 skip_git_check: bool,
29 },
30
31 /// Register a new internal crate in a “prefix group” crate
32 /// by adding a `[dependencies]` entry in the prefix crate’s Cargo.toml
33 /// plus a `pub use new_crate_name::*;` line in `src/lib.rs`.
34 Internal {
35 /// Path (or name) of the prefix crate
36 #[structopt(long = "prefix-crate")]
37 prefix_crate: PathBuf,
38
39 /// Path (or name) of the new crate to add
40 #[structopt(long = "new-crate")]
41 new_crate: PathBuf,
42
43 /// Optionally specify the workspace root path
44 /// (defaults to current directory if omitted).
45 #[structopt(long = "workspace-path")]
46 workspace_path: Option<PathBuf>,
47
48 /// If true, skip checking for Git cleanliness
49 #[structopt(long)]
50 skip_git_check: bool,
51 },
52}
53
54impl RegisterSubcommand {
55 pub async fn run(&self) -> Result<(), WorkspaceError> {
56 match self {
57 // ------------------------------------------------------------
58 // 1) Single crate “register” => ensure_all_source_files_are_registered
59 // ------------------------------------------------------------
60 RegisterSubcommand::CrateFiles {
61 crate_name,
62 skip_git_check,
63 } => {
64 // Use our helper that loads the workspace plus a specific crate
65 // e.g. `run_with_workspace_and_crate_name`.
66 // Then call `crate_handle.ensure_all_source_files_are_registered()`.
67
68 let crate_name_owned = crate_name.clone();
69 let skip_git = *skip_git_check;
70 run_with_workspace_and_crate_name(Some(crate_name_owned), skip_git, crate_name.to_string_lossy().to_string(),
71 |ws, crate_name_str| {
72 Box::pin(async move {
73 // Find that crate in the workspace
74 let crate_option = ws.find_crate_by_name(crate_name_str).await;
75 let ch = match crate_option {
76 Some(ch) => ch,
77 None => {
78 return Err(CrateError::CrateNotFoundInWorkspace {
79 crate_name: crate_name_str.to_string()
80 }.into());
81 }
82 };
83
84 let mut guard = ch.lock().await;
85 guard.ensure_all_source_files_are_registered().await?;
86
87 Ok(())
88 })
89 }
90 ).await
91 }
92
93 // ------------------------------------------------------------
94 // 2) AllFiles => entire workspace `ensure_all_source_files_are_registered`
95 // ------------------------------------------------------------
96 RegisterSubcommand::AllFiles {
97 workspace_path,
98 skip_git_check,
99 } => {
100 let ws_path = Some(workspace_path.clone());
101 let skip_git = *skip_git_check;
102
103 run_with_workspace(ws_path, skip_git, move |ws| {
104 Box::pin(async move {
105 ws.ensure_all_source_files_are_registered().await?;
106
107 Ok(())
108 })
109 }).await
110 }
111
112 // ------------------------------------------------------------
113 // 3) Internal => “register_in_prefix_crate” routine
114 // ------------------------------------------------------------
115 RegisterSubcommand::Internal {
116 prefix_crate,
117 new_crate,
118 workspace_path,
119 skip_git_check,
120 } => {
121 // We'll interpret `prefix_crate` and `new_crate` as *names* or *paths*
122 // and do the usual pattern: load the workspace, find the two crates,
123 // then call `ws.register_in_prefix_crate(&prefix_crate_handle, &new_crate_handle)`.
124 let skip_git = *skip_git_check;
125 let ws_path = workspace_path.clone();
126 let prefix_crate_str = prefix_crate.to_string_lossy().to_string();
127 let new_crate_str = new_crate.to_string_lossy().to_string();
128
129 run_with_workspace(ws_path, skip_git, move |ws| {
130 Box::pin(async move {
131 // We do `ws.find_crate_by_name(...)` or by path.
132 // Or you can do the `CrateHandle::new(&prefix_crate_path).await`
133 // if it’s not truly a name but a path.
134 // For consistency, let's treat them as “workspace crate name”:
135 let prefix_opt = ws.find_crate_by_name(&prefix_crate_str).await;
136 let prefix_h = match prefix_opt {
137 Some(ch) => ch,
138 None => {
139 return Err(CrateError::CrateNotFoundInWorkspace {
140 crate_name: prefix_crate_str
141 }.into());
142 }
143 };
144
145 let new_opt = ws.find_crate_by_name(&new_crate_str).await;
146 let new_h = match new_opt {
147 Some(ch) => ch,
148 None => {
149 return Err(CrateError::CrateNotFoundInWorkspace {
150 crate_name: new_crate_str
151 }.into());
152 }
153 };
154
155 // For the call to `ws.register_in_prefix_crate`,
156 // we need ephemeral handles of type H (not Arc<Mutex<H>>).
157 let prefix_clone = {
158 let locked = prefix_h.lock().await;
159 locked.clone()
160 };
161 let new_clone = {
162 let locked = new_h.lock().await;
163 locked.clone()
164 };
165
166 // Now call the library trait:
167 ws.register_in_prefix_crate(&prefix_clone, &new_clone).await
168 })
169 }).await
170 }
171 }
172 }
173}