Skip to content

Commit

Permalink
refactor!: logging (#242)
Browse files Browse the repository at this point in the history
* refactor!: logging

feat: add logging to update module

refactor: remove useless utility to read a file

feat: add logging to utils

feat: verbose flag

feat: support RUST_LOG

fix: disable tui

* fix: don't display header in logging mode
  • Loading branch information
beeb authored Feb 13, 2025
1 parent c7e8198 commit 355a3e9
Show file tree
Hide file tree
Showing 31 changed files with 1,885 additions and 928 deletions.
922 changes: 644 additions & 278 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ keywords = ["solidity", "package-manager", "foundry"]
license = "MIT"
readme = "./README.md"
repository = "https://github.com/mario-eth/soldeer"
rust-version = "1.80"
rust-version = "1.83"
version = "0.5.2"

[workspace.lints.clippy]
Expand All @@ -23,21 +23,20 @@ uninlined-format-args = "warn"
use-self = "warn"
redundant-clone = "warn"
unwrap_used = "warn"
rustdoc = "warn"

[workspace.lints.rust]
rust-2018-idioms = "warn"
unreachable-pub = "warn"
unused-must-use = "warn"
redundant-lifetimes = "warn"

[workspace.lints.rustdoc]
all = "warn"

[workspace.dependencies]
bon = "3.0.0"
clap = { version = "4.5.9", features = ["derive"] }
cliclack = "0.3.4"
derive_more = { version = "1.0.0", features = ["from", "display", "from_str"] }
log = { version = "0.4.25", features = ["kv"] }
mockito = "1.5.0"
path-slash = "0.2.1"
rayon = "1.10.0"
Expand Down
6 changes: 4 additions & 2 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ const HAVE_COLOR: Condition = Condition(|| {
async fn main() {
// disable colors if unsupported
yansi::whenever(HAVE_COLOR);
banner();
let args = Args::parse();
if let Err(err) = run(args.command).await {
if !args.verbose.is_present() {
banner();
}
if let Err(err) = run(args.command, args.verbose).await {
eprintln!("{}", err.to_string().red())
}
}
Expand Down
9 changes: 7 additions & 2 deletions crates/commands/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,24 @@ workspace = true
[dependencies]
bon.workspace = true
clap.workspace = true
clap-verbosity-flag = "3.0.2"
cliclack.workspace = true
derive_more.workspace = true
email-address-parser = "2.0.0"
env_logger = { version = "0.11.6", features = ["unstable-kv"] }
path-slash.workspace = true
rayon.workspace = true
soldeer-core = { path = "../core", version = "0.5.2", features = ["cli"] }
soldeer-core = { path = "../core", version = "0.5.2" }
tokio.workspace = true

[dev-dependencies]
mockito.workspace = true
reqwest.workspace = true
temp-env.workspace = true
testdir.workspace = true
tokio.workspace = true

[features]
default = ["rustls"]
rustls = ["soldeer-core/rustls"]
default-tls = ["soldeer-core/default-tls"]
serde = ["soldeer-core/serde"]
46 changes: 22 additions & 24 deletions crates/commands/src/commands/init.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use crate::ConfigLocation;
use clap::Parser;
use cliclack::{
log::{remark, success},
multi_progress,
use crate::{
utils::{remark, success, Progress},
ConfigLocation,
};
use clap::Parser;
use soldeer_core::{
config::{add_to_config, read_soldeer_config, update_config_libs, Paths},
install::{ensure_dependencies_dir, install_dependency, Progress},
install::{ensure_dependencies_dir, install_dependency, InstallProgress},
lock::add_to_lockfile,
registry::get_latest_version,
remappings::{edit_remappings, RemappingsAction},
Expand All @@ -17,7 +16,8 @@ use std::fs;

/// Convert a Foundry project to use Soldeer
#[derive(Debug, Clone, Default, Parser, bon::Builder)]
#[builder(on(String, into))]
#[allow(clippy::duplicated_attributes)]
#[builder(on(String, into), on(ConfigLocation, into))]
#[clap(after_help = "For more information, read the README.md")]
#[non_exhaustive]
pub struct Init {
Expand All @@ -36,34 +36,32 @@ pub struct Init {

pub(crate) async fn init_command(paths: &Paths, cmd: Init) -> Result<()> {
if cmd.clean {
remark("Flag `--clean` was set, removing `lib` dir and submodules")?;
remark!("Flag `--clean` was set, removing `lib` dir and submodules");
remove_forge_lib(&paths.root).await?;
}
let config = read_soldeer_config(&paths.config)?;
success("Done reading config")?;
success!("Done reading config");
ensure_dependencies_dir(&paths.dependencies)?;
let dependency = get_latest_version("forge-std").await?;
let multi = multi_progress(format!("Installing {dependency}"));
let progress = Progress::new(&multi, 1);
progress.start_all();
let lock =
install_dependency(&dependency, None, &paths.dependencies, None, false, progress.clone())
.await
.inspect_err(|e| {
multi.error(e);
})?;
progress.stop_all();
multi.stop();
let (progress, monitor) = InstallProgress::new();
let bars = Progress::new(format!("Installing {dependency}"), 1, monitor);
bars.start_all();
let lock = install_dependency(&dependency, None, &paths.dependencies, None, false, progress)
.await
.inspect_err(|e| {
bars.set_error(e);
})?;
bars.stop_all();
add_to_config(&dependency, &paths.config)?;
let foundry_config = paths.root.join("foundry.toml");
if foundry_config.exists() {
update_config_libs(foundry_config)?;
}
success("Dependency added to config")?;
success!("Dependency added to config");
add_to_lockfile(lock, &paths.lock)?;
success("Dependency added to lockfile")?;
success!("Dependency added to lockfile");
edit_remappings(&RemappingsAction::Add(dependency), &config, paths)?;
success("Dependency added to remappings")?;
success!("Dependency added to remappings");

let gitignore_path = paths.root.join(".gitignore");
if gitignore_path.exists() {
Expand All @@ -73,7 +71,7 @@ pub(crate) async fn init_command(paths: &Paths, cmd: Init) -> Result<()> {
fs::write(&gitignore_path, gitignore)?;
}
}
success("Added `dependencies` to .gitignore")?;
success!("Added `dependencies` to .gitignore");

Ok(())
}
55 changes: 27 additions & 28 deletions crates/commands/src/commands/install.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
use super::validate_dependency;
use crate::ConfigLocation;
use clap::Parser;
use cliclack::{
log::{remark, success, warning},
multi_progress, outro,
use crate::{
utils::{outro, remark, success, warning, Progress},
ConfigLocation,
};
use clap::Parser;
use soldeer_core::{
config::{
add_to_config, read_config_deps, read_soldeer_config, Dependency, GitIdentifier, Paths,
UrlType,
},
errors::{InstallError, LockError},
install::{ensure_dependencies_dir, install_dependencies, install_dependency, Progress},
install::{ensure_dependencies_dir, install_dependencies, install_dependency, InstallProgress},
lock::{add_to_lockfile, generate_lockfile_contents, read_lockfile},
remappings::{edit_remappings, RemappingsAction},
Result,
Expand All @@ -20,7 +19,8 @@ use std::fs;

/// Install a dependency
#[derive(Debug, Clone, Default, Parser, bon::Builder)]
#[builder(on(String, into))]
#[allow(clippy::duplicated_attributes)]
#[builder(on(String, into), on(ConfigLocation, into))]
#[clap(
long_about = "Install a dependency
Expand Down Expand Up @@ -100,42 +100,42 @@ pub(crate) async fn install_command(paths: &Paths, cmd: Install) -> Result<()> {
if cmd.recursive_deps {
config.recursive_deps = true;
}
success("Done reading config")?;
success!("Done reading config");
ensure_dependencies_dir(&paths.dependencies)?;
let dependencies: Vec<Dependency> = read_config_deps(&paths.config)?;
match cmd.dependency {
None => {
let lockfile = read_lockfile(&paths.lock)?;
success("Done reading lockfile")?;
success!("Done reading lockfile");
if cmd.clean {
remark("Flag `--clean` was set, re-installing all dependencies")?;
remark!("Flag `--clean` was set, re-installing all dependencies");
fs::remove_dir_all(&paths.dependencies).map_err(|e| InstallError::IOError {
path: paths.dependencies.clone(),
source: e,
})?;
ensure_dependencies_dir(&paths.dependencies)?;
}
let multi = multi_progress("Installing dependencies");
let progress = Progress::new(&multi, dependencies.len() as u64);
progress.start_all();

let (progress, monitor) = InstallProgress::new();
let bars = Progress::new("Installing dependencies", dependencies.len(), monitor);
bars.start_all();
let new_locks = install_dependencies(
&dependencies,
&lockfile.entries,
&paths.dependencies,
config.recursive_deps,
progress.clone(),
progress,
)
.await?;
progress.stop_all();
multi.stop();
bars.stop_all();
let new_lockfile_content = generate_lockfile_contents(new_locks);
if !lockfile.raw.is_empty() && new_lockfile_content != lockfile.raw {
warning("Warning: the lock file is out of sync with the dependencies. Consider running `soldeer update` to re-generate the lockfile.")?;
warning!("Warning: the lock file is out of sync with the dependencies. Consider running `soldeer update` to re-generate the lockfile.");
} else if lockfile.raw.is_empty() {
fs::write(&paths.lock, new_lockfile_content).map_err(LockError::IOError)?;
}
edit_remappings(&RemappingsAction::Update, &config, paths)?;
success("Updated remappings")?;
success!("Updated remappings");
}
Some(dependency) => {
let identifier = match (cmd.rev, cmd.branch, cmd.tag) {
Expand All @@ -151,23 +151,22 @@ pub(crate) async fn install_command(paths: &Paths, cmd: Install) -> Result<()> {
.iter()
.any(|d| d.name() == dep.name() && d.version_req() == dep.version_req())
{
outro(format!("{dep} is already installed"))?;
outro!(format!("{dep} is already installed"));
return Ok(());
}
let multi = multi_progress(format!("Installing {dep}"));
let progress = Progress::new(&multi, 1);
progress.start_all();
let (progress, monitor) = InstallProgress::new();
let bars = Progress::new(format!("Installing {dep}"), 1, monitor);
bars.start_all();
let lock = install_dependency(
&dep,
None,
&paths.dependencies,
None,
config.recursive_deps,
progress.clone(),
progress,
)
.await?;
progress.stop_all();
multi.stop();
bars.stop_all();
// for git deps, we need to add the commit hash before adding them to the
// config, unless a branch/tag was specified
if let Some(git_dep) = dep.as_git_mut() {
Expand All @@ -178,11 +177,11 @@ pub(crate) async fn install_command(paths: &Paths, cmd: Install) -> Result<()> {
}
}
add_to_config(&dep, &paths.config)?;
success("Dependency added to config")?;
success!("Dependency added to config");
add_to_lockfile(lock, &paths.lock)?;
success("Dependency added to lockfile")?;
success!("Dependency added to lockfile");
edit_remappings(&RemappingsAction::Add(dep), &config, paths)?;
success("Dependency added to remappings")?;
success!("Dependency added to remappings");
}
}
Ok(())
Expand Down
52 changes: 33 additions & 19 deletions crates/commands/src/commands/login.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use crate::utils::{info, remark, step, success};
use clap::Parser;
use cliclack::{
input,
log::{remark, step},
};
use email_address_parser::{EmailAddress, ParsingOptions};
use path_slash::PathBufExt as _;
use soldeer_core::{
auth::{execute_login, Credentials},
errors::AuthError,
Result,
};
use std::path::PathBuf;

/// Log into the central repository to push packages
///
Expand All @@ -29,35 +28,50 @@ pub struct Login {
}

pub(crate) async fn login_command(cmd: Login) -> Result<()> {
remark("If you do not have an account, please visit soldeer.xyz to create one.")?;
remark!("If you do not have an account, please visit soldeer.xyz to create one.");

let email: String = match cmd.email {
Some(email) => {
if EmailAddress::parse(&email, Some(ParsingOptions::default())).is_none() {
return Err(AuthError::InvalidCredentials.into());
}
step(format!("Email: {email}"))?;
step!(format!("Email: {email}"));
email
}
None => input("Email address")
.validate(|input: &String| {
if input.is_empty() {
Err("Email is required")
} else {
match EmailAddress::parse(input, Some(ParsingOptions::default())) {
None => Err("Invalid email address"),
Some(_) => Ok(()),
None => {
if !crate::TUI_ENABLED.load(std::sync::atomic::Ordering::Relaxed) {
return Err(AuthError::TuiDisabled.into());
}
cliclack::input("Email address")
.validate(|input: &String| {
if input.is_empty() {
Err("Email is required")
} else {
match EmailAddress::parse(input, Some(ParsingOptions::default())) {
None => Err("Invalid email address"),
Some(_) => Ok(()),
}
}
}
})
.interact()?,
})
.interact()?
}
};

let password = match cmd.password {
Some(pw) => pw,
None => cliclack::password("Password").mask('▪').interact()?,
None => {
if !crate::TUI_ENABLED.load(std::sync::atomic::Ordering::Relaxed) {
return Err(AuthError::TuiDisabled.into());
}
cliclack::password("Password").mask('▪').interact()?
}
};

execute_login(&Credentials { email, password }).await?;
let token_path = execute_login(&Credentials { email, password }).await?;
success!("Login successful");
info!(format!(
"Login details saved in: {}",
PathBuf::from_slash_lossy(&token_path).to_string_lossy() /* normalize separators */
));
Ok(())
}
Loading

0 comments on commit 355a3e9

Please sign in to comment.