diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f8d3c434f..9bf896582 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,9 +28,8 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} - uses: Swatinem/rust-cache@v2 with: - shared-key: test + shared-key: unit save-if: ${{ github.ref_name == 'main' }} - cache-all-crates: true - uses: taiki-e/install-action@v2 with: tool: nextest,just,cargo-deny,cargo-msrv,cargo-machete @@ -66,12 +65,11 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - #- run: rustup toolchain install nightly --component llvm-tools-preview --profile minimal - uses: Swatinem/rust-cache@v2 with: - shared-key: test - save-if: false + shared-key: coverage + save-if: ${{ github.ref_name == 'main' }} - run: sudo apt-get update; sudo apt-get install zsh fish direnv shfmt - run: npm i -g markdown-magic - uses: taiki-e/install-action@v2 diff --git a/e2e/test_poetry b/e2e/test_poetry index bd9620041..9a013b093 100755 --- a/e2e/test_poetry +++ b/e2e/test_poetry @@ -4,7 +4,7 @@ set -euo pipefail source "$(dirname "$0")/assert.sh" if [ "${TEST_ALL:-}" != 1 ]; then - exit + exit fi rm -rf "$RTX_DATA_DIR/cache/poetry" diff --git a/e2e/test_python b/e2e/test_python index 6c87599df..b1b1e678c 100755 --- a/e2e/test_python +++ b/e2e/test_python @@ -4,7 +4,7 @@ set -euo pipefail source "$(dirname "$0")/assert.sh" if [ "${TEST_ALL:-}" != 1 ]; then - exit + exit fi export RTX_EXPERIMENTAL=1 diff --git a/src/cli/plugins/uninstall.rs b/src/cli/plugins/uninstall.rs index af5c7a58a..b3c3e1454 100644 --- a/src/cli/plugins/uninstall.rs +++ b/src/cli/plugins/uninstall.rs @@ -52,12 +52,12 @@ impl PluginsUninstall { match config.get_or_create_plugin(plugin_name) { plugin if plugin.is_installed() => { let mut pr = mpr.add(); - plugin.decorate_progress_bar(&mut pr, None); - plugin.uninstall(&pr)?; + plugin.decorate_progress_bar(pr.as_mut(), None); + plugin.uninstall(pr.as_ref())?; if self.purge { - plugin.purge(&pr)?; + plugin.purge(pr.as_ref())?; } - pr.finish_with_message("uninstalled"); + pr.finish_with_message("uninstalled".into()); } _ => mpr.suspend(|| { warn!( diff --git a/src/cli/prune.rs b/src/cli/prune.rs index 218dbc479..a1b63840e 100644 --- a/src/cli/prune.rs +++ b/src/cli/prune.rs @@ -59,11 +59,11 @@ impl Prune { for (p, tv) in to_delete { let mut pr = mpr.add(); if self.dry_run { - pr.set_prefix(format!("{} {} ", pr.prefix(), style("[dryrun]").bold())); + pr.set_prefix(&format!("{} {} ", pr.prefix(), style("[dryrun]").bold())); } if self.dry_run || settings.yes || prompt::confirm(&format!("remove {} ?", &tv))? { - p.decorate_progress_bar(&mut pr, Some(&tv)); - p.uninstall_version(&tv, &pr, self.dry_run)?; + p.decorate_progress_bar(pr.as_mut(), Some(&tv)); + p.uninstall_version(&tv, pr.as_ref(), self.dry_run)?; pr.finish(); } } diff --git a/src/cli/uninstall.rs b/src/cli/uninstall.rs index 5f09581e5..2581c2ae0 100644 --- a/src/cli/uninstall.rs +++ b/src/cli/uninstall.rs @@ -53,15 +53,15 @@ impl Uninstall { } let mut pr = mpr.add(); - plugin.decorate_progress_bar(&mut pr, Some(&tv)); - if let Err(err) = plugin.uninstall_version(&tv, &pr, self.dry_run) { + plugin.decorate_progress_bar(pr.as_mut(), Some(&tv)); + if let Err(err) = plugin.uninstall_version(&tv, pr.as_ref(), self.dry_run) { pr.error(err.to_string()); return Err(eyre!(err).wrap_err(format!("failed to uninstall {tv}"))); } if self.dry_run { - pr.finish_with_message("uninstalled (dry-run)"); + pr.finish_with_message("uninstalled (dry-run)".into()); } else { - pr.finish_with_message("uninstalled"); + pr.finish_with_message("uninstalled".into()); } } diff --git a/src/cli/upgrade.rs b/src/cli/upgrade.rs index f2634421e..c3611b1d7 100644 --- a/src/cli/upgrade.rs +++ b/src/cli/upgrade.rs @@ -12,7 +12,7 @@ use crate::runtime_symlinks; use crate::shims; use crate::toolset::{InstallOptions, ToolVersion, ToolsetBuilder}; use crate::ui::multi_progress_report::MultiProgressReport; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; /// Upgrades outdated tool versions #[derive(Debug, clap::Args)] @@ -95,7 +95,7 @@ impl Upgrade { ts.install_versions(config, new_versions, &mpr, &opts)?; for (tool, tv) in to_remove { let mut pr = mpr.add(); - self.uninstall_old_version(tool.clone(), &tv, &mut pr)?; + self.uninstall_old_version(tool.clone(), &tv, pr.as_mut())?; } let ts = ToolsetBuilder::new().with_args(&self.tool).build(config)?; @@ -108,7 +108,7 @@ impl Upgrade { &self, tool: Arc, tv: &ToolVersion, - pr: &mut ProgressReport, + pr: &mut dyn SingleReport, ) -> Result<()> { tool.decorate_progress_bar(pr, Some(tv)); match tool.uninstall_version(tv, pr, self.dry_run) { diff --git a/src/cmd.rs b/src/cmd.rs index 42e58e38a..3fe46fc18 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -14,7 +14,7 @@ use eyre::Context; use crate::env; use crate::errors::Error::ScriptFailed; use crate::file::display_path; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; /// Create a command with any number of of positional arguments, which may be /// different types (anything that implements @@ -90,7 +90,7 @@ where pub struct CmdLineRunner<'a> { cmd: Command, - pr: Option<&'a ProgressReport>, + pr: Option<&'a dyn SingleReport>, stdin: Option, } @@ -171,7 +171,7 @@ impl<'a> CmdLineRunner<'a> { self } - pub fn with_pr(mut self, pr: &'a ProgressReport) -> Self { + pub fn with_pr(mut self, pr: &'a dyn SingleReport) -> Self { self.pr = Some(pr); self } @@ -270,7 +270,7 @@ impl<'a> CmdLineRunner<'a> { fn on_stdout(&self, line: &str) { if !line.trim().is_empty() { if let Some(pr) = self.pr { - pr.set_message(line) + pr.set_message(line.into()) } } } @@ -278,7 +278,7 @@ impl<'a> CmdLineRunner<'a> { fn on_stderr(&self, line: &str) { if !line.trim().is_empty() { match self.pr { - Some(pr) => pr.println(line), + Some(pr) => pr.println(line.into()), None => eprintln!("{}", line), } } diff --git a/src/install_context.rs b/src/install_context.rs index daa1baefa..b4e39436e 100644 --- a/src/install_context.rs +++ b/src/install_context.rs @@ -1,10 +1,10 @@ use crate::toolset::{ToolVersion, Toolset}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; pub struct InstallContext<'a> { pub ts: &'a Toolset, pub tv: ToolVersion, - pub pr: ProgressReport, + pub pr: Box, pub raw: bool, pub force: bool, } diff --git a/src/plugins/core/bun.rs b/src/plugins/core/bun.rs index 85dc6c125..693ec3c60 100644 --- a/src/plugins/core/bun.rs +++ b/src/plugins/core/bun.rs @@ -11,7 +11,7 @@ use crate::install_context::InstallContext; use crate::plugins::core::CorePlugin; use crate::plugins::{Plugin, HTTP}; use crate::toolset::{ToolVersion, ToolVersionRequest}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::{file, http}; #[derive(Debug)] @@ -48,14 +48,14 @@ impl BunPlugin { } fn test_bun(&self, ctx: &InstallContext) -> Result<()> { - ctx.pr.set_message("bun -v"); + ctx.pr.set_message("bun -v".into()); CmdLineRunner::new(self.bun_bin(&ctx.tv)) - .with_pr(&ctx.pr) + .with_pr(ctx.pr.as_ref()) .arg("-v") .execute() } - fn download(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result { + fn download(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result { let http = http::Client::new()?; let url = format!( "https://github.com/oven-sh/bun/releases/download/bun-v{}/bun-{}-{}.zip", @@ -116,7 +116,7 @@ impl Plugin for BunPlugin { ToolVersionRequest::Version { .. } )); - let tarball_path = self.download(&ctx.tv, &ctx.pr)?; + let tarball_path = self.download(&ctx.tv, ctx.pr.as_ref())?; self.install(ctx, &tarball_path)?; self.verify(ctx)?; diff --git a/src/plugins/core/deno.rs b/src/plugins/core/deno.rs index 5368c1902..b8eddf375 100644 --- a/src/plugins/core/deno.rs +++ b/src/plugins/core/deno.rs @@ -13,7 +13,7 @@ use crate::install_context::InstallContext; use crate::plugins::core::CorePlugin; use crate::plugins::{Plugin, HTTP}; use crate::toolset::{ToolVersion, ToolVersionRequest, Toolset}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::{file, http}; #[derive(Debug)] @@ -51,15 +51,15 @@ impl DenoPlugin { tv.install_path().join("bin/deno") } - fn test_deno(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("deno -V"); + fn test_deno(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("deno -V".into()); CmdLineRunner::new(self.deno_bin(tv)) .with_pr(pr) .arg("-V") .execute() } - fn download(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result { + fn download(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result { let http = http::Client::new()?; let url = format!( "https://github.com/denoland/deno/releases/download/v{}/deno-{}-{}.zip", @@ -78,7 +78,7 @@ impl DenoPlugin { Ok(tarball_path) } - fn install(&self, tv: &ToolVersion, pr: &ProgressReport, tarball_path: &Path) -> Result<()> { + fn install(&self, tv: &ToolVersion, pr: &dyn SingleReport, tarball_path: &Path) -> Result<()> { pr.set_message(format!("installing {}", tarball_path.display())); file::remove_all(tv.install_path())?; file::create_dir_all(tv.install_path().join("bin"))?; @@ -88,7 +88,7 @@ impl DenoPlugin { Ok(()) } - fn verify(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { + fn verify(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { self.test_deno(tv, pr) } } @@ -115,9 +115,9 @@ impl Plugin for DenoPlugin { ToolVersionRequest::Version { .. } )); - let tarball_path = self.download(&ctx.tv, &ctx.pr)?; - self.install(&ctx.tv, &ctx.pr, &tarball_path)?; - self.verify(&ctx.tv, &ctx.pr)?; + let tarball_path = self.download(&ctx.tv, ctx.pr.as_ref())?; + self.install(&ctx.tv, ctx.pr.as_ref(), &tarball_path)?; + self.verify(&ctx.tv, ctx.pr.as_ref())?; Ok(()) } diff --git a/src/plugins/core/go.rs b/src/plugins/core/go.rs index a29a19c7c..569df5d40 100644 --- a/src/plugins/core/go.rs +++ b/src/plugins/core/go.rs @@ -12,7 +12,7 @@ use crate::install_context::InstallContext; use crate::plugins::core::CorePlugin; use crate::plugins::Plugin; use crate::toolset::{ToolVersion, Toolset}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::{cmd, env, file, hash, http}; #[derive(Debug)] @@ -57,7 +57,7 @@ impl GoPlugin { tv.install_path().join("packages") } - fn install_default_packages(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { + fn install_default_packages(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { let body = file::read_to_string(&*env::RTX_GO_DEFAULT_PACKAGES_FILE).unwrap_or_default(); for package in body.lines() { let package = package.split('#').next().unwrap_or_default().trim(); @@ -87,15 +87,15 @@ impl GoPlugin { Ok(()) } - fn test_go(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("go version"); + fn test_go(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("go version".into()); CmdLineRunner::new(self.go_bin(tv)) .with_pr(pr) .arg("version") .execute() } - fn download(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result { + fn download(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result { let http = http::Client::new()?; let filename = format!("go{}.{}-{}.tar.gz", tv.version, platform(), arch()); let tarball_url = format!("{}/{}", &*env::RTX_GO_DOWNLOAD_MIRROR, &filename); @@ -118,7 +118,7 @@ impl GoPlugin { Ok(()) } - fn install(&self, tv: &ToolVersion, pr: &ProgressReport, tarball_path: &Path) -> Result<()> { + fn install(&self, tv: &ToolVersion, pr: &dyn SingleReport, tarball_path: &Path) -> Result<()> { let tarball = tarball_path .file_name() .unwrap_or_default() @@ -128,7 +128,7 @@ impl GoPlugin { Ok(()) } - fn verify(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { + fn verify(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { self.test_go(tv, pr)?; self.install_default_packages(tv, pr) } @@ -150,9 +150,9 @@ impl Plugin for GoPlugin { } fn install_version_impl(&self, ctx: &InstallContext) -> Result<()> { - let tarball_path = self.download(&ctx.tv, &ctx.pr)?; - self.install(&ctx.tv, &ctx.pr, &tarball_path)?; - self.verify(&ctx.tv, &ctx.pr)?; + let tarball_path = self.download(&ctx.tv, ctx.pr.as_ref())?; + self.install(&ctx.tv, ctx.pr.as_ref(), &tarball_path)?; + self.verify(&ctx.tv, ctx.pr.as_ref())?; Ok(()) } diff --git a/src/plugins/core/java.rs b/src/plugins/core/java.rs index 3c983adb6..50ecccf7c 100644 --- a/src/plugins/core/java.rs +++ b/src/plugins/core/java.rs @@ -17,7 +17,7 @@ use crate::install_context::InstallContext; use crate::plugins::core::CorePlugin; use crate::plugins::Plugin; use crate::toolset::{ToolVersion, ToolVersionRequest, Toolset}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::{env, file, hash, http}; #[derive(Debug)] @@ -114,7 +114,7 @@ impl JavaPlugin { tv.install_path().join("bin/java") } - fn test_java(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { + fn test_java(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { CmdLineRunner::new(self.java_bin(tv)) .with_pr(pr) .env("JAVA_HOME", tv.install_path()) @@ -122,7 +122,12 @@ impl JavaPlugin { .execute() } - fn download(&self, tv: &ToolVersion, pr: &ProgressReport, m: &JavaMetadata) -> Result { + fn download( + &self, + tv: &ToolVersion, + pr: &dyn SingleReport, + m: &JavaMetadata, + ) -> Result { let http = http::Client::new()?; let filename = m.url.split('/').last().unwrap(); let tarball_path = tv.download_path().join(filename); @@ -138,7 +143,7 @@ impl JavaPlugin { fn install( &self, tv: &ToolVersion, - pr: &ProgressReport, + pr: &dyn SingleReport, tarball_path: &Path, m: &JavaMetadata, ) -> Result<()> { @@ -206,8 +211,8 @@ impl JavaPlugin { Ok(()) } - fn verify(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("java -version"); + fn verify(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("java -version".into()); self.test_java(tv, pr) } @@ -288,9 +293,9 @@ impl Plugin for JavaPlugin { )); let metadata = self.tv_to_metadata(&ctx.tv)?; - let tarball_path = self.download(&ctx.tv, &ctx.pr, metadata)?; - self.install(&ctx.tv, &ctx.pr, &tarball_path, metadata)?; - self.verify(&ctx.tv, &ctx.pr)?; + let tarball_path = self.download(&ctx.tv, ctx.pr.as_ref(), metadata)?; + self.install(&ctx.tv, ctx.pr.as_ref(), &tarball_path, metadata)?; + self.verify(&ctx.tv, ctx.pr.as_ref())?; Ok(()) } diff --git a/src/plugins/core/node.rs b/src/plugins/core/node.rs index 057a73e1e..6e258ad81 100644 --- a/src/plugins/core/node.rs +++ b/src/plugins/core/node.rs @@ -14,7 +14,7 @@ use crate::install_context::InstallContext; use crate::plugins::core::CorePlugin; use crate::plugins::Plugin; use crate::toolset::ToolVersion; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::{env, file, hash, http}; #[derive(Debug)] @@ -63,7 +63,7 @@ impl NodePlugin { fn install_precompiled(&self, ctx: &InstallContext, opts: &BuildOpts) -> Result<()> { match self.fetch_tarball( - &ctx.pr, + ctx.pr.as_ref(), &opts.binary_tarball_url, &opts.binary_tarball_path, &opts.version, @@ -87,7 +87,7 @@ impl NodePlugin { fn install_compiled(&self, ctx: &InstallContext, opts: &BuildOpts) -> Result<()> { let tarball_name = &opts.source_tarball_name; self.fetch_tarball( - &ctx.pr, + ctx.pr.as_ref(), &opts.source_tarball_url, &opts.source_tarball_path, &opts.version, @@ -103,7 +103,7 @@ impl NodePlugin { fn fetch_tarball( &self, - pr: &ProgressReport, + pr: &dyn SingleReport, url: &Url, local: &Path, version: &str, @@ -127,7 +127,10 @@ impl NodePlugin { for p in &opts.path { cmd.prepend_path_env(p.clone()); } - cmd = cmd.with_pr(&ctx.pr).current_dir(&opts.build_dir).arg("-c"); + cmd = cmd + .with_pr(ctx.pr.as_ref()) + .current_dir(&opts.build_dir) + .arg("-c"); if let Some(cflags) = &*env::RTX_NODE_CFLAGS { cmd = cmd.env("CFLAGS", cflags); } @@ -169,7 +172,7 @@ impl NodePlugin { &self, config: &Config, tv: &ToolVersion, - pr: &ProgressReport, + pr: &dyn SingleReport, ) -> Result<()> { let body = file::read_to_string(&*env::RTX_NODE_DEFAULT_PACKAGES_FILE).unwrap_or_default(); for package in body.lines() { @@ -198,8 +201,8 @@ impl NodePlugin { Ok(()) } - fn enable_default_corepack_shims(&self, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("enabling corepack shims"); + fn enable_default_corepack_shims(&self, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("enabling corepack shims".into()); let corepack = self.corepack_path(tv); CmdLineRunner::new(corepack) .with_pr(pr) @@ -209,8 +212,8 @@ impl NodePlugin { Ok(()) } - fn test_node(&self, config: &Config, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("node -v"); + fn test_node(&self, config: &Config, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("node -v".into()); CmdLineRunner::new(self.node_path(tv)) .with_pr(pr) .arg("-v") @@ -218,8 +221,8 @@ impl NodePlugin { .execute() } - fn test_npm(&self, config: &Config, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("npm -v"); + fn test_npm(&self, config: &Config, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("npm -v".into()); CmdLineRunner::new(self.npm_path(tv)) .env("PATH", CorePlugin::path_env_with_tv_path(tv)?) .with_pr(pr) @@ -297,12 +300,12 @@ impl Plugin for NodePlugin { } else { self.install_precompiled(ctx, &opts)?; } - self.test_node(&config, &ctx.tv, &ctx.pr)?; + self.test_node(&config, &ctx.tv, ctx.pr.as_ref())?; self.install_npm_shim(&ctx.tv)?; - self.test_npm(&config, &ctx.tv, &ctx.pr)?; - self.install_default_packages(&config, &ctx.tv, &ctx.pr)?; + self.test_npm(&config, &ctx.tv, ctx.pr.as_ref())?; + self.install_default_packages(&config, &ctx.tv, ctx.pr.as_ref())?; if *env::RTX_NODE_COREPACK && self.corepack_path(&ctx.tv).exists() { - self.enable_default_corepack_shims(&ctx.tv, &ctx.pr)?; + self.enable_default_corepack_shims(&ctx.tv, ctx.pr.as_ref())?; } Ok(()) diff --git a/src/plugins/core/node_build.rs b/src/plugins/core/node_build.rs index 48303945e..41bd55c22 100644 --- a/src/plugins/core/node_build.rs +++ b/src/plugins/core/node_build.rs @@ -16,7 +16,7 @@ use crate::lock_file::LockFile; use crate::plugins::core::CorePlugin; use crate::plugins::Plugin; use crate::toolset::{ToolVersion, ToolVersionRequest}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::{cmd, env, file}; #[derive(Debug)] @@ -114,7 +114,7 @@ impl NodeBuildPlugin { &self, config: &Config, tv: &ToolVersion, - pr: &ProgressReport, + pr: &dyn SingleReport, ) -> Result<()> { let body = file::read_to_string(&*env::RTX_NODE_DEFAULT_PACKAGES_FILE).unwrap_or_default(); for package in body.lines() { @@ -143,8 +143,8 @@ impl NodeBuildPlugin { Ok(()) } - fn test_node(&self, config: &Config, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("node -v"); + fn test_node(&self, config: &Config, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("node -v".into()); CmdLineRunner::new(self.node_path(tv)) .with_pr(pr) .arg("-v") @@ -152,8 +152,8 @@ impl NodeBuildPlugin { .execute() } - fn test_npm(&self, config: &Config, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("npm -v"); + fn test_npm(&self, config: &Config, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("npm -v".into()); CmdLineRunner::new(self.npm_path(tv)) .env("PATH", CorePlugin::path_env_with_tv_path(tv)?) .with_pr(pr) @@ -256,9 +256,9 @@ impl Plugin for NodeBuildPlugin { fn install_version_impl(&self, ctx: &InstallContext) -> Result<()> { let config = Config::get(); self.install_node_build()?; - ctx.pr.set_message("running node-build"); + ctx.pr.set_message("running node-build".into()); let mut cmd = CmdLineRunner::new(self.node_build_bin()) - .with_pr(&ctx.pr) + .with_pr(ctx.pr.as_ref()) .env("NODE_BUILD_MIRROR_URL", RTX_NODE_MIRROR_URL.to_string()) .envs(&config.env) .arg(ctx.tv.version.as_str()); @@ -286,10 +286,10 @@ impl Plugin for NodeBuildPlugin { cmd = cmd.arg("--verbose"); } cmd.arg(&ctx.tv.install_path()).execute()?; - self.test_node(&config, &ctx.tv, &ctx.pr)?; + self.test_node(&config, &ctx.tv, ctx.pr.as_ref())?; self.install_npm_shim(&ctx.tv)?; - self.test_npm(&config, &ctx.tv, &ctx.pr)?; - self.install_default_packages(&config, &ctx.tv, &ctx.pr)?; + self.test_npm(&config, &ctx.tv, ctx.pr.as_ref())?; + self.install_default_packages(&config, &ctx.tv, ctx.pr.as_ref())?; Ok(()) } } diff --git a/src/plugins/core/python.rs b/src/plugins/core/python.rs index 655a6f6f5..d4b980da8 100644 --- a/src/plugins/core/python.rs +++ b/src/plugins/core/python.rs @@ -12,7 +12,7 @@ use crate::install_context::InstallContext; use crate::plugins::core::CorePlugin; use crate::plugins::Plugin; use crate::toolset::{ToolVersion, ToolVersionRequest, Toolset}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::{cmd, env, file, http}; #[derive(Debug)] @@ -90,12 +90,12 @@ impl PythonPlugin { &self, config: &Config, tv: &ToolVersion, - pr: &ProgressReport, + pr: &dyn SingleReport, ) -> Result<()> { if !env::RTX_PYTHON_DEFAULT_PACKAGES_FILE.exists() { return Ok(()); } - pr.set_message("installing default packages"); + pr.set_message("installing default packages".into()); CmdLineRunner::new(tv.install_path().join("bin/python")) .with_pr(pr) .arg("-m") @@ -112,7 +112,7 @@ impl PythonPlugin { &self, config: &Config, tv: &ToolVersion, - pr: Option<&ProgressReport>, + pr: Option<&dyn SingleReport>, ) -> Result> { if let Some(virtualenv) = tv.opts.get("virtualenv") { let mut virtualenv: PathBuf = file::replace_path(Path::new(virtualenv)); @@ -155,8 +155,8 @@ impl PythonPlugin { Ok(()) } - fn test_python(&self, config: &Config, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("python --version"); + fn test_python(&self, config: &Config, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("python --version".into()); CmdLineRunner::new(self.python_path(tv)) .arg("--version") .envs(&config.env) @@ -187,9 +187,9 @@ impl Plugin for PythonPlugin { if matches!(&ctx.tv.request, ToolVersionRequest::Ref(..)) { return Err(eyre!("Ref versions not supported for python")); } - ctx.pr.set_message("Running python-build"); + ctx.pr.set_message("Running python-build".into()); let mut cmd = CmdLineRunner::new(self.python_build_bin()) - .with_pr(&ctx.pr) + .with_pr(ctx.pr.as_ref()) .arg(ctx.tv.version.as_str()) .arg(&ctx.tv.install_path()) .envs(&config.env); @@ -216,11 +216,11 @@ impl Plugin for PythonPlugin { } } cmd.execute()?; - self.test_python(&config, &ctx.tv, &ctx.pr)?; - if let Err(e) = self.get_virtualenv(&config, &ctx.tv, Some(&ctx.pr)) { + self.test_python(&config, &ctx.tv, ctx.pr.as_ref())?; + if let Err(e) = self.get_virtualenv(&config, &ctx.tv, Some(ctx.pr.as_ref())) { warn!("failed to get virtualenv: {e}"); } - self.install_default_packages(&config, &ctx.tv, &ctx.pr)?; + self.install_default_packages(&config, &ctx.tv, ctx.pr.as_ref())?; Ok(()) } diff --git a/src/plugins/core/ruby.rs b/src/plugins/core/ruby.rs index 916877180..4dad31a10 100644 --- a/src/plugins/core/ruby.rs +++ b/src/plugins/core/ruby.rs @@ -15,7 +15,7 @@ use crate::lock_file::LockFile; use crate::plugins::core::CorePlugin; use crate::plugins::Plugin; use crate::toolset::{ToolVersion, ToolVersionRequest, Toolset}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::{cmd, env, file, http}; #[derive(Debug)] @@ -172,7 +172,7 @@ impl RubyPlugin { &self, config: &Config, tv: &ToolVersion, - pr: &ProgressReport, + pr: &dyn SingleReport, ) -> Result<()> { let body = file::read_to_string(&*env::RTX_RUBY_DEFAULT_PACKAGES_FILE).unwrap_or_default(); for package in body.lines() { @@ -197,8 +197,8 @@ impl RubyPlugin { Ok(()) } - fn test_ruby(&self, config: &Config, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("ruby -v"); + fn test_ruby(&self, config: &Config, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("ruby -v".into()); CmdLineRunner::new(self.ruby_path(tv)) .with_pr(pr) .arg("-v") @@ -206,8 +206,8 @@ impl RubyPlugin { .execute() } - fn test_gem(&self, config: &Config, tv: &ToolVersion, pr: &ProgressReport) -> Result<()> { - pr.set_message("gem -v"); + fn test_gem(&self, config: &Config, tv: &ToolVersion, pr: &dyn SingleReport) -> Result<()> { + pr.set_message("gem -v".into()); CmdLineRunner::new(self.gem_path(tv)) .with_pr(pr) .arg("-v") @@ -246,7 +246,7 @@ impl RubyPlugin { &'a self, config: &'a Config, tv: &ToolVersion, - pr: &'a ProgressReport, + pr: &'a dyn SingleReport, ) -> Result { let cmd = if *env::RTX_RUBY_INSTALL { CmdLineRunner::new(self.ruby_install_bin()).args(self.install_args_ruby_install(tv)?) @@ -354,14 +354,15 @@ impl Plugin for RubyPlugin { ToolVersionRequest::Version { .. } )); - ctx.pr.set_message("running ruby-build"); + ctx.pr.set_message("running ruby-build".into()); let config = Config::get(); - self.install_cmd(&config, &ctx.tv, &ctx.pr)?.execute()?; + self.install_cmd(&config, &ctx.tv, ctx.pr.as_ref())? + .execute()?; - self.test_ruby(&config, &ctx.tv, &ctx.pr)?; + self.test_ruby(&config, &ctx.tv, ctx.pr.as_ref())?; self.install_rubygems_hook(&ctx.tv)?; - self.test_gem(&config, &ctx.tv, &ctx.pr)?; - self.install_default_gems(&config, &ctx.tv, &ctx.pr)?; + self.test_gem(&config, &ctx.tv, ctx.pr.as_ref())?; + self.install_default_gems(&config, &ctx.tv, ctx.pr.as_ref())?; Ok(()) } diff --git a/src/plugins/external_plugin.rs b/src/plugins/external_plugin.rs index bf16c670b..cc6fe6b13 100644 --- a/src/plugins/external_plugin.rs +++ b/src/plugins/external_plugin.rs @@ -29,7 +29,7 @@ use crate::plugins::{Plugin, PluginName, PluginType, Script, ScriptManager, HTTP use crate::timeout::run_with_timeout; use crate::toolset::{ToolVersion, ToolVersionRequest, Toolset}; use crate::ui::multi_progress_report::MultiProgressReport; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::ui::prompt; use crate::{dirs, env, file, http}; @@ -100,7 +100,7 @@ impl ExternalPlugin { .ok_or_else(|| eyre!("No repository found for plugin {}", self.name)) } - fn install(&self, pr: &ProgressReport) -> Result<()> { + fn install(&self, pr: &dyn SingleReport) -> Result<()> { let config = Config::get(); let repository = self.get_repo_url(&config)?; let (repo_url, repo_ref) = Git::split_url_and_ref(&repository); @@ -465,9 +465,9 @@ impl Plugin for ExternalPlugin { let _mpr = MultiProgressReport::new(); let mpr = mpr.unwrap_or(&_mpr); let mut pr = mpr.add(); - self.decorate_progress_bar(&mut pr, None); + self.decorate_progress_bar(pr.as_mut(), None); let _lock = self.get_lock(&self.plugin_path, force)?; - self.install(&pr) + self.install(pr.as_ref()) } fn update(&self, gitref: Option) -> Result<()> { @@ -493,11 +493,11 @@ impl Plugin for ExternalPlugin { Ok(()) } - fn uninstall(&self, pr: &ProgressReport) -> Result<()> { + fn uninstall(&self, pr: &dyn SingleReport) -> Result<()> { if !self.is_installed() { return Ok(()); } - pr.set_message("uninstalling"); + pr.set_message("uninstalling".into()); let rmdir = |dir: &Path| { if !dir.exists() { @@ -635,13 +635,13 @@ impl Plugin for ExternalPlugin { sm.prepend_path(p); } - let run_script = |script| sm.run_by_line(script, &ctx.pr); + let run_script = |script| sm.run_by_line(script, ctx.pr.as_ref()); if sm.script_exists(&Download) { - ctx.pr.set_message("downloading"); + ctx.pr.set_message("downloading".into()); run_script(&Download)?; } - ctx.pr.set_message("installing"); + ctx.pr.set_message("installing".into()); run_script(&Install)?; Ok(()) diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs index 02e11df4c..71549dc39 100644 --- a/src/plugins/mod.rs +++ b/src/plugins/mod.rs @@ -25,7 +25,7 @@ use crate::lock_file::LockFile; use crate::runtime_symlinks::is_runtime_symlink; use crate::toolset::{ToolVersion, ToolVersionRequest, Toolset}; use crate::ui::multi_progress_report::MultiProgressReport; -use crate::ui::progress_report::{ProgressReport, PROG_TEMPLATE}; +use crate::ui::progress_report::{SingleReport, PROG_TEMPLATE}; use crate::{dirs, file, http}; pub mod core; @@ -158,10 +158,10 @@ pub trait Plugin: Debug + Send + Sync { fn update(&self, _git_ref: Option) -> Result<()> { Ok(()) } - fn uninstall(&self, _pr: &ProgressReport) -> Result<()> { + fn uninstall(&self, _pr: &dyn SingleReport) -> Result<()> { Ok(()) } - fn purge(&self, pr: &ProgressReport) -> Result<()> { + fn purge(&self, pr: &dyn SingleReport) -> Result<()> { rmdir(&self.installs_path(), pr)?; rmdir(&self.cache_path(), pr)?; rmdir(&self.downloads_path(), pr)?; @@ -188,12 +188,12 @@ pub trait Plugin: Debug + Send + Sync { let settings = Settings::try_get()?; if self.is_version_installed(&ctx.tv) { if ctx.force { - self.uninstall_version(&ctx.tv, &ctx.pr, false)?; + self.uninstall_version(&ctx.tv, ctx.pr.as_ref(), false)?; } else { return Ok(()); } } - self.decorate_progress_bar(&mut ctx.pr, Some(&ctx.tv)); + self.decorate_progress_bar(ctx.pr.as_mut(), Some(&ctx.tv)); let _lock = self.get_lock(&ctx.tv.install_path(), ctx.force)?; self.create_install_dirs(&ctx.tv)?; @@ -214,13 +214,18 @@ pub trait Plugin: Debug + Send + Sync { if let Err(err) = file::remove_file(self.incomplete_file_path(&ctx.tv)) { debug!("error removing incomplete file: {:?}", err); } - ctx.pr.set_message(""); + ctx.pr.set_message("".into()); ctx.pr.finish(); Ok(()) } fn install_version_impl(&self, ctx: &InstallContext) -> Result<()>; - fn uninstall_version(&self, tv: &ToolVersion, pr: &ProgressReport, dryrun: bool) -> Result<()> { + fn uninstall_version( + &self, + tv: &ToolVersion, + pr: &dyn SingleReport, + dryrun: bool, + ) -> Result<()> { pr.set_message(format!("uninstall {tv}")); if !dryrun { @@ -304,13 +309,13 @@ pub trait Plugin: Debug + Send + Sync { let _ = remove_all_with_warning(tv.download_path()); } } - fn decorate_progress_bar(&self, pr: &mut ProgressReport, tv: Option<&ToolVersion>) { + fn decorate_progress_bar(&self, pr: &mut dyn SingleReport, tv: Option<&ToolVersion>) { pr.set_style(PROG_TEMPLATE.clone()); let tool = match tv { Some(tv) => tv.to_string(), None => self.name().to_string(), }; - pr.set_prefix(format!( + pr.set_prefix(&format!( "{} {} ", style("rtx").dim().for_stderr(), style(tool).cyan().for_stderr(), @@ -361,7 +366,7 @@ fn find_match_in_list(list: &[String], query: &str) -> Option { }; v } -fn rmdir(dir: &Path, pr: &ProgressReport) -> Result<()> { +fn rmdir(dir: &Path, pr: &dyn SingleReport) -> Result<()> { if !dir.exists() { return Ok(()); } diff --git a/src/plugins/script_manager.rs b/src/plugins/script_manager.rs index e156a2fe0..0e6aed2c2 100644 --- a/src/plugins/script_manager.rs +++ b/src/plugins/script_manager.rs @@ -16,7 +16,7 @@ use crate::errors::Error; use crate::errors::Error::ScriptFailed; use crate::fake_asdf::get_path_with_fake_asdf; use crate::file::{basename, display_path}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::SingleReport; use crate::{dirs, env}; #[derive(Debug, Clone)] @@ -174,7 +174,7 @@ impl ScriptManager { .wrap_err_with(|| ScriptFailed(display_path(&self.get_script_path(script)), None)) } - pub fn run_by_line(&self, script: &Script, pr: &ProgressReport) -> Result<()> { + pub fn run_by_line(&self, script: &Script, pr: &dyn SingleReport) -> Result<()> { let cmd = CmdLineRunner::new(self.get_script_path(script)) .with_pr(pr) .env_clear() diff --git a/src/ui/multi_progress_report.rs b/src/ui/multi_progress_report.rs index 702a558b7..0bfdd774b 100644 --- a/src/ui/multi_progress_report.rs +++ b/src/ui/multi_progress_report.rs @@ -1,8 +1,8 @@ use crate::config::Settings; use console::style; -use indicatif::MultiProgress; +use indicatif::{MultiProgress, ProgressBar}; -use crate::ui::progress_report::ProgressReport; +use crate::ui::progress_report::{ProgressReport, QuietReport, SingleReport, VerboseReport}; #[derive(Debug)] pub struct MultiProgressReport { @@ -22,14 +22,11 @@ impl MultiProgressReport { quiet: settings.quiet, } } - pub fn add(&self) -> ProgressReport { + pub fn add(&self) -> Box { match &self.mp { - Some(mp) => { - let mut pr = ProgressReport::new(false, self.quiet); - pr.pb = Some(mp.add(pr.pb.unwrap())); - pr - } - None => ProgressReport::new(true, self.quiet), + _ if self.quiet => Box::new(QuietReport::new()), + Some(mp) => Box::new(ProgressReport::new(mp.add(ProgressBar::new(0)))), + None => Box::new(VerboseReport::new()), } } pub fn suspend R, R>(&self, f: F) -> R { @@ -51,14 +48,6 @@ impl MultiProgressReport { _ => (), } } - // pub fn clear(&self) { - // match &self.mp { - // Some(mp) => { - // let _ = mp.clear(); - // }, - // None => () - // } - // } } #[cfg(test)] @@ -71,8 +60,8 @@ mod tests { let pr = mpr.add(); pr.set_style(indicatif::ProgressStyle::with_template("").unwrap()); pr.enable_steady_tick(); - pr.finish_with_message("test"); - pr.println(""); - pr.set_message("test"); + pr.finish_with_message("test".into()); + pr.println("".into()); + pr.set_message("test".into()); } } diff --git a/src/ui/progress_report.rs b/src/ui/progress_report.rs index db1d05168..8389fe683 100644 --- a/src/ui/progress_report.rs +++ b/src/ui/progress_report.rs @@ -1,15 +1,20 @@ -use std::borrow::Cow; use std::time::Duration; use console::style; use indicatif::{ProgressBar, ProgressStyle}; use once_cell::sync::Lazy; -#[derive(Debug)] -pub struct ProgressReport { - pub pb: Option, - prefix: String, - quiet: bool, +pub trait SingleReport: Send + Sync { + fn enable_steady_tick(&self) {} + fn set_prefix(&mut self, prefix: &str); + fn prefix(&self) -> String; + fn set_style(&self, _style: ProgressStyle) {} + fn set_message(&self, _message: String) {} + fn println(&self, _message: String) {} + fn warn(&self, _message: String) {} + fn error(&self, _message: String) {} + fn finish(&self) {} + fn finish_with_message(&self, _message: String) {} } pub static PROG_TEMPLATE: Lazy = Lazy::new(|| { @@ -17,7 +22,7 @@ pub static PROG_TEMPLATE: Lazy = Lazy::new(|| { .unwrap() }); -pub static SUCCESS_TEMPLATE: Lazy = Lazy::new(|| { +static SUCCESS_TEMPLATE: Lazy = Lazy::new(|| { let tmpl = format!( "{{prefix}}{{wide_msg}} {} {{elapsed:3.dim.italic}}", style("✓").bright().green().for_stderr() @@ -25,7 +30,7 @@ pub static SUCCESS_TEMPLATE: Lazy = Lazy::new(|| { ProgressStyle::with_template(tmpl.as_str()).unwrap() }); -pub static ERROR_TEMPLATE: Lazy = Lazy::new(|| { +static ERROR_TEMPLATE: Lazy = Lazy::new(|| { let tmpl = format!( "{{prefix:.red}}{{wide_msg}} {} {{elapsed:3.dim.italic}}", style("✗").red().for_stderr() @@ -33,111 +38,111 @@ pub static ERROR_TEMPLATE: Lazy = Lazy::new(|| { ProgressStyle::with_template(tmpl.as_str()).unwrap() }); +#[derive(Debug)] +pub struct ProgressReport { + pub pb: ProgressBar, +} + impl ProgressReport { - pub fn new(verbose: bool, quiet: bool) -> ProgressReport { - let pb = match verbose { - true => None, - false => Some(ProgressBar::new(0)), - }; - ProgressReport { - pb, - prefix: String::new(), - quiet, - } + pub fn new(pb: ProgressBar) -> ProgressReport { + ProgressReport { pb } } +} - pub fn enable_steady_tick(&self) { - match &self.pb { - Some(pb) => pb.enable_steady_tick(Duration::from_millis(250)), - None => (), - } +impl SingleReport for ProgressReport { + fn enable_steady_tick(&self) { + self.pb.enable_steady_tick(Duration::from_millis(250)); } - pub fn set_prefix(&mut self, prefix: impl Into>) { - match &self.pb { - Some(pb) => pb.set_prefix(prefix), - None => { - self.prefix = prefix.into().to_string(); - } - } + fn set_prefix(&mut self, prefix: &str) { + self.pb.set_prefix(prefix.to_string()); } - pub fn prefix(&self) -> String { - match &self.pb { - Some(pb) => pb.prefix(), - None => self.prefix.clone(), - } + fn prefix(&self) -> String { + self.pb.prefix() } - pub fn set_style(&self, style: ProgressStyle) { - match &self.pb { - Some(pb) => { - pb.set_style(style); - pb.set_prefix(console::style("rtx").dim().for_stderr().to_string()); - } - None => (), - } + fn set_style(&self, style: ProgressStyle) { + self.pb.set_style(style); + self.pb + .set_prefix(console::style("rtx").dim().for_stderr().to_string()); } - pub fn set_message>(&self, message: S) { - match &self.pb { - Some(pb) => pb.set_message(message.as_ref().replace('\r', "")), - None if !self.quiet => eprintln!("{}", message.as_ref()), - _ => (), - } + fn set_message(&self, message: String) { + self.pb.set_message(message.replace('\r', "")); } - pub fn println>(&self, message: S) { - match &self.pb { - Some(pb) => pb.println(message), - None if !self.quiet => eprintln!("{}", message.as_ref()), - _ => (), - } + fn println(&self, message: String) { + self.pb.println(message); } - pub fn warn>(&self, message: S) { - match &self.pb { - Some(pb) => pb.println(format!("{} {}", style("[WARN]").yellow(), message.as_ref())), - None if !self.quiet => eprintln!("{}", message.as_ref()), - _ => (), - } + fn warn(&self, message: String) { + self.pb + .println(format!("{} {}", style("[WARN]").yellow(), message)); } - pub fn error>(&self, message: S) { - match &self.pb { - Some(pb) => { - self.set_message(format!( - "{} {}", - style("[ERROR]").red().for_stderr(), - message.as_ref() - )); - pb.set_style(ERROR_TEMPLATE.clone()); - pb.finish() - } - None => (), - } + fn error(&self, message: String) { + self.set_message(format!( + "{} {}", + style("[ERROR]").red().for_stderr(), + message + )); + self.pb.set_style(ERROR_TEMPLATE.clone()); + self.pb.finish(); } - pub fn finish(&self) { - match &self.pb { - Some(pb) => { - pb.set_style(SUCCESS_TEMPLATE.clone()); - pb.finish() - } - None => (), + fn finish(&self) { + self.pb.set_style(SUCCESS_TEMPLATE.clone()); + self.pb.finish() + } + fn finish_with_message(&self, message: String) { + self.pb.set_style(SUCCESS_TEMPLATE.clone()); + self.pb.finish_with_message(message); + } +} + +pub struct QuietReport { + prefix: String, +} +impl QuietReport { + pub fn new() -> QuietReport { + QuietReport { + prefix: String::new(), } } - pub fn finish_with_message(&self, message: impl Into>) { - match &self.pb { - Some(pb) => { - pb.set_style(SUCCESS_TEMPLATE.clone()); - pb.finish_with_message(message); - } - None if !self.quiet => eprintln!("{}", message.into()), - _ => (), +} +impl SingleReport for QuietReport { + fn set_prefix(&mut self, prefix: &str) { + self.prefix = prefix.to_string(); + } + + fn prefix(&self) -> String { + self.prefix.clone() + } +} +pub struct VerboseReport { + prefix: String, +} +impl VerboseReport { + pub fn new() -> VerboseReport { + VerboseReport { + prefix: String::new(), } } - // pub fn clear(&self) { - // match &self.pb { - // Some(pb) => pb.finish_and_clear(), - // None => (), - // } - // } +} +impl SingleReport for VerboseReport { + fn set_prefix(&mut self, prefix: &str) { + self.prefix = prefix.to_string(); + } + + fn prefix(&self) -> String { + self.prefix.clone() + } + + fn set_message(&self, message: String) { + eprintln!("{}", message); + } + fn println(&self, message: String) { + eprintln!("{}", message); + } + fn warn(&self, message: String) { + eprintln!("{}", message); + } } #[cfg(test)] @@ -146,19 +151,28 @@ mod tests { #[test] fn test_progress_report() { - let mut pr = ProgressReport::new(false, false); + let mut pr = ProgressReport::new(ProgressBar::new(0)); pr.set_prefix("prefix"); assert_eq!(pr.prefix(), "prefix"); - pr.set_message("message"); - pr.finish_with_message("message"); + pr.set_message("message".into()); + pr.finish_with_message("message".into()); } #[test] fn test_progress_report_verbose() { - let mut pr = ProgressReport::new(true, false); + let mut pr = VerboseReport::new(); + pr.set_prefix("prefix"); + assert_eq!(pr.prefix(), "prefix"); + pr.set_message("message".into()); + pr.finish_with_message("message".into()); + } + + #[test] + fn test_progress_report_quiet() { + let mut pr = QuietReport::new(); pr.set_prefix("prefix"); assert_eq!(pr.prefix(), "prefix"); - pr.set_message("message"); - pr.finish_with_message("message"); + pr.set_message("message".into()); + pr.finish_with_message("message".into()); } }