workspacer_cli/add_internal_dep.rs
1// ---------------- [ File: workspacer-cli/src/add_internal_dep.rs ]
2crate::ix!();
3
4/// 1) Define a new struct for the "internal-dep" subcommand arguments.
5/// It needs `target_crate`, `dep_crate`, an optional `workspace_path`
6/// and a `skip_git_check` flag, just like the other subcommands.
7#[derive(Getters,Setters,Debug,StructOpt)]
8#[getset(get="pub")]
9pub struct AddInternalDepCommand {
10 /// The crate that *will* depend on another
11 #[structopt(long = "target-crate")]
12 target_crate: String,
13
14 /// The crate being depended upon
15 #[structopt(long = "dep-crate")]
16 dep_crate: String,
17
18 /// If provided, we use this path as the workspace root instead of the current directory
19 #[structopt(long = "workspace")]
20 workspace_path: Option<PathBuf>,
21
22 /// If true, we skip the Git clean check (i.e., do not require a clean repo)
23 #[structopt(long = "skip-git-check")]
24 skip_git_check: bool,
25}
26
27impl AddInternalDepCommand {
28 /// This method drives the logic for adding a dependency from one crate to another.
29 pub async fn run(&self) -> Result<(), WorkspaceError> {
30 // We'll use a new helper function (shown below) that is nearly identical
31 // to `run_with_workspace_and_crate_name`, but handles *two* crate names.
32 //
33 // Alternatively, you could define a more general `run_with_workspace` that
34 // doesn't require a crate name at all, then do the logic inside the closure.
35 // But here's the approach with a "two crate names" helper for consistency.
36 //
37 // Step 1) Clone them so we have owned Strings
38 let target_name_owned = self.target_crate().clone();
39 let dep_name_owned = self.dep_crate().clone();
40
41 // Step 2) Call the new helper
42 run_with_workspace_and_two_crate_names(
43 self.workspace_path().clone(),
44 *self.skip_git_check(),
45 target_name_owned,
46 dep_name_owned,
47 |ws, target_name, dep_name| {
48 Box::pin(async move {
49 info!(
50 "Now performing 'add internal dependency' => target='{}', dep='{}'",
51 target_name, dep_name
52 );
53
54 // 2a) Find the target crate by name
55 let maybe_target_crate = ws.find_crate_by_name(target_name).await;
56 let target_crate_arc = match maybe_target_crate {
57 Some(arc) => arc,
58 None => {
59 error!("No crate named '{}' found in workspace", target_name);
60 return Err(CrateError::CrateNotFoundInWorkspace {
61 crate_name: target_name.to_owned(),
62 }.into());
63 }
64 };
65
66 // 2b) Find the dep crate by name
67 let maybe_dep_crate = ws.find_crate_by_name(dep_name).await;
68 let dep_crate_arc = match maybe_dep_crate {
69 Some(arc) => arc,
70 None => {
71 error!("No crate named '{}' found in workspace", dep_name);
72 return Err(CrateError::CrateNotFoundInWorkspace {
73 crate_name: dep_name.to_owned(),
74 }.into());
75 }
76 };
77
78 // 3) Lock each crate handle to get an `H` (so we can pass references to .await calls)
79 let target_handle = target_crate_arc.lock().await.clone();
80 let dep_handle = dep_crate_arc.lock().await.clone();
81
82 // 4) Perform the actual add_internal_dependency call
83 ws.add_internal_dependency(&target_handle, &dep_handle).await?;
84
85 info!(
86 "Successfully added an internal dep to crate='{}' on '{}'",
87 target_name, dep_name
88 );
89 Ok(())
90 })
91 },
92 )
93 .await
94 }
95}