leo_lang/cli/commands/
add.rsuse super::*;
use leo_retriever::{Dependency, Location, Manifest, NetworkName};
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[clap(name = "leo", author = "The Leo Team <leo@provable.com>", version)]
pub struct LeoAdd {
#[clap(name = "NAME", help = "The dependency name. Ex: `credits.aleo` or `credits`.")]
pub(crate) name: String,
#[clap(short = 'l', long, help = "Path to local dependency")]
pub(crate) local: Option<PathBuf>,
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "testnet")]
pub(crate) network: String,
#[clap(short = 'c', long, help = "Clear all previous dependencies.", default_value = "false")]
pub(crate) clear: bool,
}
impl Command for LeoAdd {
type Input = ();
type Output = ();
fn log_span(&self) -> Span {
tracing::span!(tracing::Level::INFO, "Leo")
}
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
let path = context.dir()?;
let program_data: String = std::fs::read_to_string(path.join("program.json"))
.map_err(|err| PackageError::failed_to_read_file(path.to_str().unwrap(), err))?;
let manifest: Manifest = serde_json::from_str(&program_data)
.map_err(|err| PackageError::failed_to_deserialize_manifest_file(path.to_str().unwrap(), err))?;
let name: String = match &self.name {
name if name.ends_with(".aleo") && Package::is_aleo_name_valid(&name[0..self.name.len() - 5]) => {
name.clone()
}
name if Package::is_aleo_name_valid(name) => format!("{name}.aleo"),
name => return Err(PackageError::invalid_file_name_dependency(name).into()),
};
let mut dependencies = match (self.clear, manifest.dependencies()) {
(false, Some(ref dependencies)) => dependencies
.iter()
.filter_map(|dependency| {
if dependency.name() == &name {
let msg = match (dependency.path(), dependency.network()) {
(Some(local_path), _) => {
format!("local dependency at path `{}`", local_path.to_str().unwrap().replace('\"', ""))
}
(_, Some(network)) => {
format!("network dependency from `{}`", network)
}
_ => "git dependency".to_string(),
};
tracing::warn!("⚠️ Program `{name}` already exists as a {msg}. Overwriting.");
None
} else if self.local.is_some() && &self.local == dependency.path() {
tracing::warn!(
"⚠️ Path `{}` already exists as the location for local dependency `{}`. Overwriting.",
self.local.clone().unwrap().to_str().unwrap().replace('\"', ""),
dependency.name()
);
None
} else {
Some(dependency.clone())
}
})
.collect(),
_ => Vec::new(),
};
dependencies.push(match self.local {
Some(local_path) => {
tracing::info!(
"✅ Added local dependency to program `{name}` at path `{}`.",
local_path.to_str().unwrap().replace('\"', "")
);
Dependency::new(name, Location::Local, None, Some(local_path))
}
None => {
tracing::info!("✅ Added network dependency to program `{name}` from network `{}`.", self.network);
Dependency::new(name, Location::Network, Some(NetworkName::try_from(self.network.as_str())?), None)
}
});
let new_manifest = Manifest::new(
manifest.program(),
manifest.version(),
manifest.description(),
manifest.license(),
Some(dependencies),
);
new_manifest.write_to_dir(&path)?;
Ok(())
}
}