leo_lang/cli/commands/
add.rs1use super::*;
18use leo_package::{Dependency, Location, Manifest};
19use std::path::PathBuf;
20
21#[derive(Parser, Debug)]
23#[clap(name = "leo", author = "The Leo Team <leo@provable.com>", version)]
24pub struct LeoAdd {
25 #[clap(name = "NAME", help = "The dependency name. Ex: `credits.aleo` or `credits`.")]
26 pub(crate) name: String,
27
28 #[clap(flatten)]
29 pub(crate) source: DependencySource,
30
31 #[clap(
32 short = 'c',
33 long,
34 hide = true,
35 help = "[UNUSED] Clear all previous dependencies.",
36 default_value = "false"
37 )]
38 pub(crate) clear: bool,
39
40 #[clap(long, help = "This is a development dependency.", default_value = "false")]
41 pub(crate) dev: bool,
42}
43
44#[derive(Parser, Debug)]
45#[group(required = true, multiple = false)]
46pub struct DependencySource {
47 #[clap(short = 'l', long, help = "Whether the dependency is local to the machine.", group = "source")]
48 pub(crate) local: Option<PathBuf>,
49
50 #[clap(short = 'n', long, help = "Whether the dependency is on a live network.", group = "source")]
51 pub(crate) network: bool,
52
53 #[clap(
54 short = 'e',
55 long,
56 help = "The expected edition of the program. DO NOT USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.",
57 group = "source"
58 )]
59 pub(crate) edition: Option<u16>,
60}
61
62impl Command for LeoAdd {
63 type Input = ();
64 type Output = ();
65
66 fn log_span(&self) -> Span {
67 tracing::span!(tracing::Level::INFO, "Leo")
68 }
69
70 fn prelude(&self, _: Context) -> Result<Self::Input> {
71 Ok(())
72 }
73
74 fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
75 let path = context.dir()?;
76
77 let manifest_path = path.join(leo_package::MANIFEST_FILENAME);
78 let mut manifest = Manifest::read_from_file(&manifest_path)?;
79
80 let name = if self.name.ends_with(".aleo") { self.name.clone() } else { format!("{}.aleo", self.name) };
83
84 if !leo_package::is_valid_aleo_name(&name) {
85 return Err(CliError::invalid_program_name(name).into());
86 }
87
88 let new_dependency = Dependency {
89 name: name.clone(),
90 location: if self.source.local.is_some() { Location::Local } else { Location::Network },
91 path: self.source.local.clone(),
92 edition: self.source.edition,
93 };
94
95 let deps = if self.dev { &mut manifest.dev_dependencies } else { &mut manifest.dependencies };
96
97 if let Some(matched_dep) = deps.get_or_insert_default().iter_mut().find(|dep| dep.name == new_dependency.name) {
98 if let Some(path) = &matched_dep.path {
99 tracing::warn!(
100 "⚠️ Program `{name}` already exists as a local dependency at `{}`. Overwriting.",
101 path.display()
102 );
103 } else {
104 tracing::warn!("⚠️ Program `{name}` already exists as a network dependency. Overwriting.");
105 }
106 *matched_dep = new_dependency;
107 } else {
108 deps.as_mut().unwrap().push(new_dependency);
109 if let Some(path) = self.source.local.as_ref() {
110 tracing::info!("✅ Added local dependency to program `{name}` at path `{}`.", path.display());
111 } else {
112 tracing::info!("✅ Added network dependency `{name}` from network `{}`.", self.source.network);
113 }
114 }
115
116 manifest.write_to_file(manifest_path)?;
117
118 Ok(())
119 }
120}