From 05f5a9cdefe21e05e80a6780a72d9a2e16a4662d Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Tue, 14 Jan 2025 14:56:37 -0500 Subject: [PATCH 01/13] Command: criticalup doc --- Cargo.lock | 56 ++++++++++++++++++- crates/criticalup-cli/Cargo.toml | 1 + crates/criticalup-cli/src/commands/doc.rs | 49 ++++++++++++++++ crates/criticalup-cli/src/commands/mod.rs | 1 + crates/criticalup-cli/src/errors.rs | 13 +++++ crates/criticalup-cli/src/lib.rs | 11 ++++ .../tests/snapshots/cli__root__no_args.snap | 2 +- 7 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 crates/criticalup-cli/src/commands/doc.rs diff --git a/Cargo.lock b/Cargo.lock index fc65eb10..e95a5efe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -510,6 +510,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bstr" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +dependencies = [ + "memchr", + "regex-automata 0.4.9", + "serde", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -694,6 +705,7 @@ dependencies = [ "futures", "insta", "mock-download-server", + "opener", "regex", "serde", "serde_json", @@ -796,6 +808,17 @@ dependencies = [ "syn", ] +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] + [[package]] name = "der" version = "0.7.9" @@ -1437,6 +1460,16 @@ version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "libredox" version = "0.1.3" @@ -1539,6 +1572,15 @@ dependencies = [ "tiny_http", ] +[[package]] +name = "normpath" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1588,6 +1630,18 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "opener" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0812e5e4df08da354c851a3376fead46db31c2214f849d3de356d774d057681" +dependencies = [ + "bstr", + "dbus", + "normpath", + "windows-sys 0.59.0", +] + [[package]] name = "openssl-probe" version = "0.1.5" diff --git a/crates/criticalup-cli/Cargo.toml b/crates/criticalup-cli/Cargo.toml index cf9a4871..6666e813 100644 --- a/crates/criticalup-cli/Cargo.toml +++ b/crates/criticalup-cli/Cargo.toml @@ -32,6 +32,7 @@ tracing.workspace = true tracing-subscriber.workspace = true time = { version = "0.3.36", features = ["std", "serde", "serde-well-known", "macros"] } walkdir.workspace = true +opener = "0.7.2" [dev-dependencies] insta = { version = "1.41.1", features = ["filters"] } diff --git a/crates/criticalup-cli/src/commands/doc.rs b/crates/criticalup-cli/src/commands/doc.rs new file mode 100644 index 00000000..5ab31562 --- /dev/null +++ b/crates/criticalup-cli/src/commands/doc.rs @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: The Ferrocene Developers +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use crate::errors::Error; +use crate::Context; +use criticalup_core::project_manifest::ProjectManifest; +use std::path::PathBuf; + +pub(crate) async fn run( + ctx: &Context, + project: Option, + path_only: bool, +) -> Result<(), Error> { + // Parse and serialize the project manifest. + let manifest = ProjectManifest::get(project).await?; + let installation_dir = &ctx.config.paths.installation_dir; + + for product in manifest.products() { + let doc_package_exists_in_manifest = + product.packages().contains(&"ferrocene-docs".to_string()); + let abs_ferrocene_html_doc_path = installation_dir + .join(product.installation_id()) + .join("share/doc/") + .join(product.name()) + .join("html/index.html"); + + if !doc_package_exists_in_manifest || !abs_ferrocene_html_doc_path.exists() { + return Err(Error::MissingDocPackage()); + } + + if path_only { + tracing::info!( + "Documentation for product '{}' is located at\n {}", + product.name(), + abs_ferrocene_html_doc_path.display() + ); + } else { + // Open in the default browser. + opener::open_browser(abs_ferrocene_html_doc_path.clone()).map_err(|err| { + Error::DocPathOpenError { + path: abs_ferrocene_html_doc_path, + kind: err, + } + })? + } + } + + Ok(()) +} diff --git a/crates/criticalup-cli/src/commands/mod.rs b/crates/criticalup-cli/src/commands/mod.rs index 4f0333db..f212e594 100644 --- a/crates/criticalup-cli/src/commands/mod.rs +++ b/crates/criticalup-cli/src/commands/mod.rs @@ -6,6 +6,7 @@ pub(crate) mod auth; pub(crate) mod auth_remove; pub(crate) mod auth_set; pub(crate) mod clean; +pub(crate) mod doc; pub(crate) mod install; pub(crate) mod remove; pub(crate) mod run; diff --git a/crates/criticalup-cli/src/errors.rs b/crates/criticalup-cli/src/errors.rs index cd47e90b..aeb12117 100644 --- a/crates/criticalup-cli/src/errors.rs +++ b/crates/criticalup-cli/src/errors.rs @@ -135,6 +135,19 @@ pub(crate) enum Error { tracing_subscriber::util::TryInitError, ), + #[error("Failed to open document in browser at {}", path.display())] + DocPathOpenError { + path: PathBuf, + #[source] + kind: opener::OpenError, + }, + + #[error( + "Package 'ferrocene-docs' is not installed for this project. Please add the package \ + 'ferrocene-docs' to the project manifest and run 'criticalup install' again." + )] + MissingDocPackage(), + #[error("Failed to run install command.")] RevocationSignatureExpired(#[source] criticaltrust::Error), #[error("Failed to install package '{}'.", .0)] diff --git a/crates/criticalup-cli/src/lib.rs b/crates/criticalup-cli/src/lib.rs index 3f48c855..3751a4c7 100644 --- a/crates/criticalup-cli/src/lib.rs +++ b/crates/criticalup-cli/src/lib.rs @@ -79,6 +79,7 @@ async fn main_inner(whitelabel: WhitelabelConfig, args: &[OsString]) -> Result<( project, out, } => commands::archive::run(&ctx, project.as_ref(), offline, out.as_ref()).await?, + Commands::Doc { project, path } => commands::doc::run(&ctx, project, path).await?, } Ok(()) @@ -212,6 +213,16 @@ enum Commands { #[arg()] out: Option, }, + + /// Open the documentation for the current toolchain + Doc { + /// Path to the manifest `criticalup.toml` + #[arg(long)] + project: Option, + /// Only print the path to the documentation location + #[arg(long)] + path: bool, + }, } #[derive(Debug, Subcommand, Clone)] diff --git a/crates/criticalup-cli/tests/snapshots/cli__root__no_args.snap b/crates/criticalup-cli/tests/snapshots/cli__root__no_args.snap index 2f116014..61091499 100644 --- a/crates/criticalup-cli/tests/snapshots/cli__root__no_args.snap +++ b/crates/criticalup-cli/tests/snapshots/cli__root__no_args.snap @@ -1,7 +1,6 @@ --- source: crates/criticalup-cli/tests/cli/root.rs expression: repr -snapshot_kind: text --- exit: exit status: 1 @@ -23,6 +22,7 @@ Commands: verify Verify a given toolchain which Display which binary will be run for a given command archive Create a tar archive of the toolchain based on the manifest `criticalup.toml` + doc Open the documentation for the current toolchain Options: -v, --verbose... Enable debug logs, -vv for trace From 1c01c49ecb5e4e44801f6e8f7d3dc1ef628852af Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Tue, 21 Jan 2025 16:07:25 -0500 Subject: [PATCH 02/13] Chore: Sort Cargo.toml deps. --- crates/criticalup-cli/Cargo.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/criticalup-cli/Cargo.toml b/crates/criticalup-cli/Cargo.toml index 6666e813..9acd5d97 100644 --- a/crates/criticalup-cli/Cargo.toml +++ b/crates/criticalup-cli/Cargo.toml @@ -22,24 +22,24 @@ clap = { version = "4.5.21", features = ["std", "derive", "help", "usage"] } criticaltrust = { path = "../criticaltrust" } criticalup-core = { path = "../criticalup-core" } futures.workspace = true +opener = "0.7.2" serde_json = "1.0.132" tar = "0.4.43" -thiserror = "2.0.3" -xz2 = "0.1.7" tempfile.workspace = true +thiserror = "2.0.3" +time = { version = "0.3.36", features = ["std", "serde", "serde-well-known", "macros"] } tokio.workspace = true tracing.workspace = true tracing-subscriber.workspace = true -time = { version = "0.3.36", features = ["std", "serde", "serde-well-known", "macros"] } walkdir.workspace = true -opener = "0.7.2" +xz2 = "0.1.7" [dev-dependencies] insta = { version = "1.41.1", features = ["filters"] } mock-download-server = { path = "../mock-download-server" } +regex = "1.11.1" serde = { version = "1.0.215", features = ["derive"] } tempfile.workspace = true -regex = "1.11.1" [target.x86_64-pc-windows-msvc.dependencies] windows-sys = { version = "0.59.0", features = ["Win32_Foundation", "Win32_System_Console"] } From 6f2232b4db20f40ae4b4dd771e62f44283684360 Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Tue, 21 Jan 2025 19:11:41 -0500 Subject: [PATCH 03/13] Chore: English --- crates/criticalup-cli/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/criticalup-cli/src/errors.rs b/crates/criticalup-cli/src/errors.rs index aeb12117..35d32dc9 100644 --- a/crates/criticalup-cli/src/errors.rs +++ b/crates/criticalup-cli/src/errors.rs @@ -135,7 +135,7 @@ pub(crate) enum Error { tracing_subscriber::util::TryInitError, ), - #[error("Failed to open document in browser at {}", path.display())] + #[error("Failed to open document in the browser at {}", path.display())] DocPathOpenError { path: PathBuf, #[source] From 8dbf4966d9e7e2c2ebe108ca6a27cef6deb47036 Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Tue, 21 Jan 2025 19:32:06 -0500 Subject: [PATCH 04/13] Doc command: Tests --- crates/criticalup-cli/Cargo.toml | 2 +- crates/criticalup-cli/src/commands/doc.rs | 5 + crates/criticalup-cli/tests/cli/doc.rs | 121 ++++++++++++++++++ crates/criticalup-cli/tests/cli/main.rs | 1 + .../resources/criticalup-doc-no-package.toml | 11 ++ .../tests/resources/criticalup-doc.toml | 12 ++ .../snapshots/cli__doc__error_no_file.snap | 12 ++ .../snapshots/cli__doc__error_no_package.snap | 12 ++ .../snapshots/cli__doc__help_message.snap | 22 ++++ .../snapshots/cli__doc__open_browser.snap | 13 ++ .../snapshots/cli__doc__show_path_only.snap | 13 ++ 11 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 crates/criticalup-cli/tests/cli/doc.rs create mode 100644 crates/criticalup-cli/tests/resources/criticalup-doc-no-package.toml create mode 100644 crates/criticalup-cli/tests/resources/criticalup-doc.toml create mode 100644 crates/criticalup-cli/tests/snapshots/cli__doc__error_no_file.snap create mode 100644 crates/criticalup-cli/tests/snapshots/cli__doc__error_no_package.snap create mode 100644 crates/criticalup-cli/tests/snapshots/cli__doc__help_message.snap create mode 100644 crates/criticalup-cli/tests/snapshots/cli__doc__open_browser.snap create mode 100644 crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap diff --git a/crates/criticalup-cli/Cargo.toml b/crates/criticalup-cli/Cargo.toml index 9acd5d97..f1c8e0a1 100644 --- a/crates/criticalup-cli/Cargo.toml +++ b/crates/criticalup-cli/Cargo.toml @@ -22,7 +22,7 @@ clap = { version = "4.5.21", features = ["std", "derive", "help", "usage"] } criticaltrust = { path = "../criticaltrust" } criticalup-core = { path = "../criticalup-core" } futures.workspace = true -opener = "0.7.2" +opener = { version = "0.7.2"} serde_json = "1.0.132" tar = "0.4.43" tempfile.workspace = true diff --git a/crates/criticalup-cli/src/commands/doc.rs b/crates/criticalup-cli/src/commands/doc.rs index 5ab31562..0fbf1663 100644 --- a/crates/criticalup-cli/src/commands/doc.rs +++ b/crates/criticalup-cli/src/commands/doc.rs @@ -36,6 +36,11 @@ pub(crate) async fn run( ); } else { // Open in the default browser. + tracing::info!( + "Opening docs in your browser for product '{}'.\n {}", + product.name(), + abs_ferrocene_html_doc_path.display() + ); opener::open_browser(abs_ferrocene_html_doc_path.clone()).map_err(|err| { Error::DocPathOpenError { path: abs_ferrocene_html_doc_path, diff --git a/crates/criticalup-cli/tests/cli/doc.rs b/crates/criticalup-cli/tests/cli/doc.rs new file mode 100644 index 00000000..9a0d18af --- /dev/null +++ b/crates/criticalup-cli/tests/cli/doc.rs @@ -0,0 +1,121 @@ +// SPDX-FileCopyrightText: The Ferrocene Developers +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use crate::assert_output; +use crate::utils::{construct_toolchains_product_path, TestEnvironment}; +use criticalup_core::project_manifest::ProjectManifest; +use std::fs::File; + +#[tokio::test] +async fn help_message() { + let test_env = TestEnvironment::prepare().await; + assert_output!(test_env.cmd().args(["doc", "--help"])); +} + +#[tokio::test] +async fn show_path_only() { + let test_env = TestEnvironment::prepare().await; + let mut current_dir = + std::env::current_dir().expect("could not read current directory in the test."); + current_dir.push("tests/resources/criticalup-doc.toml"); + + let manifest_path = current_dir.to_str().expect("conversion to str failed"); + + // generate the manifest object so we can get the installation id hash + let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); + let id_hash = p.products()[0].installation_id().0; + + // Manually create the toolchain directory which allows us to skip installation. + // TODO: when tests for `install` command are up, use that instead of manual creation. + let product_toolchain_dir = construct_toolchains_product_path(&test_env, id_hash.as_str()); + let product_toolchain_doc_dir = product_toolchain_dir.join("share/doc/ferrocene/html"); + std::fs::create_dir_all(&product_toolchain_doc_dir) + .expect("could not create product directory"); + + // Create a file "index.html" in the doc dir to mimic docs. + let _ = File::create(product_toolchain_doc_dir.join("index.html")).unwrap(); + + assert_output!(test_env + .cmd() + .args(["doc", "--path", "--project", manifest_path])); +} + +#[tokio::test] +async fn open_browser() { + let test_env = TestEnvironment::prepare().await; + let mut current_dir = + std::env::current_dir().expect("could not read current directory in the test."); + current_dir.push("tests/resources/criticalup-doc.toml"); + + let manifest_path = current_dir.to_str().expect("conversion to str failed"); + + // generate the manifest object so we can get the installation id hash + let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); + let id_hash = p.products()[0].installation_id().0; + + // Manually create the toolchain directory which allows us to skip installation. + // TODO: when tests for `install` command are up, use that instead of manual creation. + let product_toolchain_dir = construct_toolchains_product_path(&test_env, id_hash.as_str()); + let product_toolchain_doc_dir = product_toolchain_dir.join("share/doc/ferrocene/html"); + std::fs::create_dir_all(&product_toolchain_doc_dir) + .expect("could not create product directory"); + + // Create a file "index.html" in the doc dir to mimic docs. + let _ = File::create(product_toolchain_doc_dir.join("index.html")).unwrap(); + assert_output!(test_env.cmd().args(["doc", "--project", manifest_path])); +} + +#[tokio::test] +async fn error_no_file() { + let test_env = TestEnvironment::prepare().await; + let mut current_dir = + std::env::current_dir().expect("could not read current directory in the test."); + current_dir.push("tests/resources/criticalup-doc.toml"); + + let manifest_path = current_dir.to_str().expect("conversion to str failed"); + + // generate the manifest object so we can get the installation id hash + let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); + let id_hash = p.products()[0].installation_id().0; + + // Manually create the toolchain directory which allows us to skip installation. + // TODO: when tests for `install` command are up, use that instead of manual creation. + let product_toolchain_dir = construct_toolchains_product_path(&test_env, id_hash.as_str()); + let product_toolchain_doc_dir = product_toolchain_dir.join("share/doc/ferrocene/html"); + std::fs::create_dir_all(&product_toolchain_doc_dir) + .expect("could not create product directory"); + + assert_output!(test_env + .cmd() + .args(["doc", "--path", "--project", manifest_path])); +} + +#[tokio::test] +async fn error_no_package() { + let test_env = TestEnvironment::prepare().await; + let mut current_dir = + std::env::current_dir().expect("could not read current directory in the test."); + current_dir.push("tests/resources/criticalup-doc-no-package.toml"); + + let manifest_path = current_dir.to_str().expect("conversion to str failed"); + + // generate the manifest object so we can get the installation id hash + let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); + let id_hash = p.products()[0].installation_id().0; + + // Manually create the toolchain directory which allows us to skip installation. + // TODO: when tests for `install` command are up, use that instead of manual creation. + let product_toolchain_dir = construct_toolchains_product_path(&test_env, id_hash.as_str()); + let product_toolchain_doc_dir = product_toolchain_dir.join("share/doc/ferrocene/html"); + std::fs::create_dir_all(&product_toolchain_doc_dir) + .expect("could not create product directory"); + + // Create a file "index.html" in the doc dir to mimic docs. + let _ = File::create(product_toolchain_doc_dir.join("index.html")).unwrap(); + + // Even if the file is available on the disk, it should show error because the manifest + // does not have the 'ferrocene-docs' package. + assert_output!(test_env + .cmd() + .args(["doc", "--path", "--project", manifest_path])); +} diff --git a/crates/criticalup-cli/tests/cli/main.rs b/crates/criticalup-cli/tests/cli/main.rs index 2a1c344a..e91a3983 100644 --- a/crates/criticalup-cli/tests/cli/main.rs +++ b/crates/criticalup-cli/tests/cli/main.rs @@ -8,6 +8,7 @@ mod auth_remove; mod auth_set; mod binary_proxies; mod clean; +mod doc; mod install; mod remove; mod root; diff --git a/crates/criticalup-cli/tests/resources/criticalup-doc-no-package.toml b/crates/criticalup-cli/tests/resources/criticalup-doc-no-package.toml new file mode 100644 index 00000000..4c53a234 --- /dev/null +++ b/crates/criticalup-cli/tests/resources/criticalup-doc-no-package.toml @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: The Ferrocene Developers +# SPDX-License-Identifier: MIT OR Apache-2.0 + +# Manifest for test +manifest-version = 1 + +[products.ferrocene] +release = "stable-2024.11.0" +packages = [ + "rustc-x86_64-unknown-linux-gnu", +] diff --git a/crates/criticalup-cli/tests/resources/criticalup-doc.toml b/crates/criticalup-cli/tests/resources/criticalup-doc.toml new file mode 100644 index 00000000..f0503f6e --- /dev/null +++ b/crates/criticalup-cli/tests/resources/criticalup-doc.toml @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: The Ferrocene Developers +# SPDX-License-Identifier: MIT OR Apache-2.0 + +# Manifest for test +manifest-version = 1 + +[products.ferrocene] +release = "stable-2024.11.0" +packages = [ + "rustc-x86_64-unknown-linux-gnu", + "ferrocene-docs", +] diff --git a/crates/criticalup-cli/tests/snapshots/cli__doc__error_no_file.snap b/crates/criticalup-cli/tests/snapshots/cli__doc__error_no_file.snap new file mode 100644 index 00000000..bce47e25 --- /dev/null +++ b/crates/criticalup-cli/tests/snapshots/cli__doc__error_no_file.snap @@ -0,0 +1,12 @@ +--- +source: crates/criticalup-cli/tests/cli/doc.rs +expression: repr +--- +exit: exit status: 1 + +empty stdout + +stderr +------ +error: Package 'ferrocene-docs' is not installed for this project. Please add the package 'ferrocene-docs' to the project manifest and run 'criticalup install' again. +------ diff --git a/crates/criticalup-cli/tests/snapshots/cli__doc__error_no_package.snap b/crates/criticalup-cli/tests/snapshots/cli__doc__error_no_package.snap new file mode 100644 index 00000000..bce47e25 --- /dev/null +++ b/crates/criticalup-cli/tests/snapshots/cli__doc__error_no_package.snap @@ -0,0 +1,12 @@ +--- +source: crates/criticalup-cli/tests/cli/doc.rs +expression: repr +--- +exit: exit status: 1 + +empty stdout + +stderr +------ +error: Package 'ferrocene-docs' is not installed for this project. Please add the package 'ferrocene-docs' to the project manifest and run 'criticalup install' again. +------ diff --git a/crates/criticalup-cli/tests/snapshots/cli__doc__help_message.snap b/crates/criticalup-cli/tests/snapshots/cli__doc__help_message.snap new file mode 100644 index 00000000..dbfc7b66 --- /dev/null +++ b/crates/criticalup-cli/tests/snapshots/cli__doc__help_message.snap @@ -0,0 +1,22 @@ +--- +source: crates/criticalup-cli/tests/cli/doc.rs +expression: repr +--- +exit: exit status: 0 + +empty stdout + +stderr +------ +Open the documentation for the current toolchain + +Usage: + criticalup-test doc [OPTIONS] + +Options: + --project Path to the manifest `criticalup.toml` + --path Only print the path to the documentation location + -v, --verbose... Enable debug logs, -vv for trace + --log-level [...] Tracing directives + -h, --help Print help +------ diff --git a/crates/criticalup-cli/tests/snapshots/cli__doc__open_browser.snap b/crates/criticalup-cli/tests/snapshots/cli__doc__open_browser.snap new file mode 100644 index 00000000..61f0b6dc --- /dev/null +++ b/crates/criticalup-cli/tests/snapshots/cli__doc__open_browser.snap @@ -0,0 +1,13 @@ +--- +source: crates/criticalup-cli/tests/cli/doc.rs +expression: repr +--- +exit: exit status: 0 + +empty stdout + +stderr +------ + INFO Opening docs in your browser for product 'ferrocene'. + /path/to/toolchain/installation/96e6f26dbe3633b09bca5969805ee049655ef23f0a95fe9d0139fc9c1cc488fd/share/doc/ferrocene/html/index.html +------ diff --git a/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap b/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap new file mode 100644 index 00000000..ed668b57 --- /dev/null +++ b/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap @@ -0,0 +1,13 @@ +--- +source: crates/criticalup-cli/tests/cli/doc.rs +expression: repr +--- +exit: exit status: 0 + +empty stdout + +stderr +------ + INFO Documentation for product 'ferrocene' is located at + /path/to/toolchain/installation/96e6f26dbe3633b09bca5969805ee049655ef23f0a95fe9d0139fc9c1cc488fd/share/doc/ferrocene/html/index.html +------ From 28f81176dd63b81f330ee0dbe44c7cb25bf3176b Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Wed, 22 Jan 2025 21:18:53 -0500 Subject: [PATCH 05/13] Better naming; Clippy appease --- crates/criticalup-cli/src/commands/doc.rs | 2 +- crates/criticalup-cli/src/errors.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/criticalup-cli/src/commands/doc.rs b/crates/criticalup-cli/src/commands/doc.rs index 0fbf1663..ad0e0cca 100644 --- a/crates/criticalup-cli/src/commands/doc.rs +++ b/crates/criticalup-cli/src/commands/doc.rs @@ -42,7 +42,7 @@ pub(crate) async fn run( abs_ferrocene_html_doc_path.display() ); opener::open_browser(abs_ferrocene_html_doc_path.clone()).map_err(|err| { - Error::DocPathOpenError { + Error::FailedToOpenDoc { path: abs_ferrocene_html_doc_path, kind: err, } diff --git a/crates/criticalup-cli/src/errors.rs b/crates/criticalup-cli/src/errors.rs index 35d32dc9..aabdb809 100644 --- a/crates/criticalup-cli/src/errors.rs +++ b/crates/criticalup-cli/src/errors.rs @@ -136,7 +136,7 @@ pub(crate) enum Error { ), #[error("Failed to open document in the browser at {}", path.display())] - DocPathOpenError { + FailedToOpenDoc { path: PathBuf, #[source] kind: opener::OpenError, From e030c4285cf4cf36f63c54dad68a1bf877b00f53 Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Thu, 23 Jan 2025 12:01:28 -0500 Subject: [PATCH 06/13] Print only the path, not the message. --- crates/criticalup-cli/src/commands/doc.rs | 6 +----- .../tests/snapshots/cli__doc__show_path_only.snap | 9 ++++----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/crates/criticalup-cli/src/commands/doc.rs b/crates/criticalup-cli/src/commands/doc.rs index ad0e0cca..11c90b8f 100644 --- a/crates/criticalup-cli/src/commands/doc.rs +++ b/crates/criticalup-cli/src/commands/doc.rs @@ -29,11 +29,7 @@ pub(crate) async fn run( } if path_only { - tracing::info!( - "Documentation for product '{}' is located at\n {}", - product.name(), - abs_ferrocene_html_doc_path.display() - ); + println!("{}", abs_ferrocene_html_doc_path.display()); } else { // Open in the default browser. tracing::info!( diff --git a/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap b/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap index ed668b57..52983596 100644 --- a/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap +++ b/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap @@ -4,10 +4,9 @@ expression: repr --- exit: exit status: 0 -empty stdout - -stderr +stdout ------ - INFO Documentation for product 'ferrocene' is located at - /path/to/toolchain/installation/96e6f26dbe3633b09bca5969805ee049655ef23f0a95fe9d0139fc9c1cc488fd/share/doc/ferrocene/html/index.html +/path/to/toolchain/installation/96e6f26dbe3633b09bca5969805ee049655ef23f0a95fe9d0139fc9c1cc488fd/share/doc/ferrocene/html/index.html ------ + +empty stderr From 4e48399ccc331f261b0509255241605a8aa73f88 Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Thu, 23 Jan 2025 12:44:29 -0500 Subject: [PATCH 07/13] Tests: Windows fix for path --- crates/criticalup-cli/tests/cli/utils.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/criticalup-cli/tests/cli/utils.rs b/crates/criticalup-cli/tests/cli/utils.rs index 77f690ef..5f481425 100644 --- a/crates/criticalup-cli/tests/cli/utils.rs +++ b/crates/criticalup-cli/tests/cli/utils.rs @@ -165,6 +165,12 @@ macro_rules! assert_output { let mut settings = insta::Settings::clone_current(); settings.set_snapshot_path("../snapshots"); + #[cfg(target_os = "windows")] + settings.add_filter( + r"[a-zA-Z]:\\.*\\toolchains\\(?[_a-zA-Z0-9]+)\\.*html.*", + "/path/to/toolchain/installation/$ins_id/share/doc/ferrocene/html/index.html", + ); + // using tempfile in tests changes the output tmp dir on every run // so, this is to normalize the data first #[cfg(target_os = "linux")] From 474ec748c48d78538fa4695d969643e0e8bd71eb Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Thu, 23 Jan 2025 13:04:46 -0500 Subject: [PATCH 08/13] Chore: English --- crates/criticalup-cli/tests/cli/doc.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/criticalup-cli/tests/cli/doc.rs b/crates/criticalup-cli/tests/cli/doc.rs index 9a0d18af..9bab301c 100644 --- a/crates/criticalup-cli/tests/cli/doc.rs +++ b/crates/criticalup-cli/tests/cli/doc.rs @@ -21,7 +21,7 @@ async fn show_path_only() { let manifest_path = current_dir.to_str().expect("conversion to str failed"); - // generate the manifest object so we can get the installation id hash + // Generate the manifest object so we can get the installation id hash. let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); let id_hash = p.products()[0].installation_id().0; @@ -49,7 +49,7 @@ async fn open_browser() { let manifest_path = current_dir.to_str().expect("conversion to str failed"); - // generate the manifest object so we can get the installation id hash + // Generate the manifest object so we can get the installation id hash. let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); let id_hash = p.products()[0].installation_id().0; @@ -74,7 +74,7 @@ async fn error_no_file() { let manifest_path = current_dir.to_str().expect("conversion to str failed"); - // generate the manifest object so we can get the installation id hash + // Generate the manifest object so we can get the installation id hash. let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); let id_hash = p.products()[0].installation_id().0; @@ -99,7 +99,7 @@ async fn error_no_package() { let manifest_path = current_dir.to_str().expect("conversion to str failed"); - // generate the manifest object so we can get the installation id hash + // Generate the manifest object so we can get the installation id hash. let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); let id_hash = p.products()[0].installation_id().0; From e4c329f12474b5e4b51c5fb2c4725d1664a5208f Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Fri, 24 Jan 2025 15:41:17 -0500 Subject: [PATCH 09/13] Review: delete test that opens browser. Tests should not open users' browsers. Reviewed-by: Ana Hobden --- crates/criticalup-cli/tests/cli/doc.rs | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/crates/criticalup-cli/tests/cli/doc.rs b/crates/criticalup-cli/tests/cli/doc.rs index 9bab301c..32813ec2 100644 --- a/crates/criticalup-cli/tests/cli/doc.rs +++ b/crates/criticalup-cli/tests/cli/doc.rs @@ -40,31 +40,6 @@ async fn show_path_only() { .args(["doc", "--path", "--project", manifest_path])); } -#[tokio::test] -async fn open_browser() { - let test_env = TestEnvironment::prepare().await; - let mut current_dir = - std::env::current_dir().expect("could not read current directory in the test."); - current_dir.push("tests/resources/criticalup-doc.toml"); - - let manifest_path = current_dir.to_str().expect("conversion to str failed"); - - // Generate the manifest object so we can get the installation id hash. - let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); - let id_hash = p.products()[0].installation_id().0; - - // Manually create the toolchain directory which allows us to skip installation. - // TODO: when tests for `install` command are up, use that instead of manual creation. - let product_toolchain_dir = construct_toolchains_product_path(&test_env, id_hash.as_str()); - let product_toolchain_doc_dir = product_toolchain_dir.join("share/doc/ferrocene/html"); - std::fs::create_dir_all(&product_toolchain_doc_dir) - .expect("could not create product directory"); - - // Create a file "index.html" in the doc dir to mimic docs. - let _ = File::create(product_toolchain_doc_dir.join("index.html")).unwrap(); - assert_output!(test_env.cmd().args(["doc", "--project", manifest_path])); -} - #[tokio::test] async fn error_no_file() { let test_env = TestEnvironment::prepare().await; From 439f036b97063604b527a09db1108531d4493376 Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Fri, 24 Jan 2025 17:55:12 -0500 Subject: [PATCH 10/13] Review: improve display of path, as url. Reviewed-by: Ana Hobden --- Cargo.lock | 292 ++++++++++++++++-- crates/criticalup-cli/Cargo.toml | 1 + crates/criticalup-cli/src/commands/doc.rs | 33 +- crates/criticalup-cli/src/errors.rs | 4 +- crates/criticalup-cli/tests/cli/doc.rs | 29 ++ .../cli__doc__error_opening_browser.snap | 15 + .../snapshots/cli__doc__show_path_only.snap | 2 +- 7 files changed, 338 insertions(+), 38 deletions(-) create mode 100644 crates/criticalup-cli/tests/snapshots/cli__doc__error_opening_browser.snap diff --git a/Cargo.lock b/Cargo.lock index e95a5efe..514e6b8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -716,6 +716,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "url", "walkdir", "winapi", "windows-sys 0.59.0", @@ -873,6 +874,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ecdsa" version = "0.16.9" @@ -1355,6 +1367,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1363,12 +1493,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1492,6 +1633,12 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.12" @@ -2506,6 +2653,12 @@ dependencies = [ "der", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.11.1" @@ -2538,6 +2691,17 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tar" version = "0.4.43" @@ -2655,6 +2819,16 @@ dependencies = [ "rustls 0.20.9", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2855,27 +3029,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - [[package]] name = "untrusted" version = "0.7.1" @@ -2890,9 +3049,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -2905,6 +3064,18 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.1" @@ -3297,6 +3468,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "xattr" version = "1.3.1" @@ -3323,8 +3506,75 @@ dependencies = [ "lzma-sys", ] +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/crates/criticalup-cli/Cargo.toml b/crates/criticalup-cli/Cargo.toml index f1c8e0a1..273b049d 100644 --- a/crates/criticalup-cli/Cargo.toml +++ b/crates/criticalup-cli/Cargo.toml @@ -31,6 +31,7 @@ time = { version = "0.3.36", features = ["std", "serde", "serde-well-known", "ma tokio.workspace = true tracing.workspace = true tracing-subscriber.workspace = true +url = "2.5.4" walkdir.workspace = true xz2 = "0.1.7" diff --git a/crates/criticalup-cli/src/commands/doc.rs b/crates/criticalup-cli/src/commands/doc.rs index 11c90b8f..3e87c923 100644 --- a/crates/criticalup-cli/src/commands/doc.rs +++ b/crates/criticalup-cli/src/commands/doc.rs @@ -5,6 +5,7 @@ use crate::errors::Error; use crate::Context; use criticalup_core::project_manifest::ProjectManifest; use std::path::PathBuf; +use url::Url; pub(crate) async fn run( ctx: &Context, @@ -28,21 +29,25 @@ pub(crate) async fn run( return Err(Error::MissingDocPackage()); } - if path_only { - println!("{}", abs_ferrocene_html_doc_path.display()); - } else { - // Open in the default browser. - tracing::info!( - "Opening docs in your browser for product '{}'.\n {}", - product.name(), - abs_ferrocene_html_doc_path.display() - ); - opener::open_browser(abs_ferrocene_html_doc_path.clone()).map_err(|err| { - Error::FailedToOpenDoc { - path: abs_ferrocene_html_doc_path, - kind: err, + // Path to the doc root can be clickable so we try to print that. + match Url::from_file_path(abs_ferrocene_html_doc_path.clone()) { + Ok(url) => { + let url = url.to_string(); + if path_only { + println!("{}", url); + } else { + // Open in the default browser. + tracing::info!( + "Opening docs in your browser for product '{}'.", + product.name() + ); + opener::open_browser(abs_ferrocene_html_doc_path.clone()) + .map_err(|err| Error::FailedToOpenDoc { url, kind: err })? } - })? + } + Err(_) => { + println!("{}", abs_ferrocene_html_doc_path.display()); + } } } diff --git a/crates/criticalup-cli/src/errors.rs b/crates/criticalup-cli/src/errors.rs index aabdb809..f5cdd765 100644 --- a/crates/criticalup-cli/src/errors.rs +++ b/crates/criticalup-cli/src/errors.rs @@ -135,9 +135,9 @@ pub(crate) enum Error { tracing_subscriber::util::TryInitError, ), - #[error("Failed to open document in the browser at {}", path.display())] + #[error("Failed to open document in the browser at {}", url)] FailedToOpenDoc { - path: PathBuf, + url: String, #[source] kind: opener::OpenError, }, diff --git a/crates/criticalup-cli/tests/cli/doc.rs b/crates/criticalup-cli/tests/cli/doc.rs index 32813ec2..664fd0ec 100644 --- a/crates/criticalup-cli/tests/cli/doc.rs +++ b/crates/criticalup-cli/tests/cli/doc.rs @@ -4,6 +4,7 @@ use crate::assert_output; use crate::utils::{construct_toolchains_product_path, TestEnvironment}; use criticalup_core::project_manifest::ProjectManifest; +use std::env; use std::fs::File; #[tokio::test] @@ -94,3 +95,31 @@ async fn error_no_package() { .cmd() .args(["doc", "--path", "--project", manifest_path])); } + +#[tokio::test] +async fn error_opening_browser() { + let test_env = TestEnvironment::prepare().await; + let mut current_dir = + std::env::current_dir().expect("could not read current directory in the test."); + current_dir.push("tests/resources/criticalup-doc.toml"); + + let manifest_path = current_dir.to_str().expect("conversion to str failed"); + + // Generate the manifest object so we can get the installation id hash. + let p = ProjectManifest::load(current_dir.as_path()).expect("could not load project manifest"); + let id_hash = p.products()[0].installation_id().0; + + // Manually create the toolchain directory which allows us to skip installation. + // TODO: when tests for `install` command are up, use that instead of manual creation. + let product_toolchain_dir = construct_toolchains_product_path(&test_env, id_hash.as_str()); + let product_toolchain_doc_dir = product_toolchain_dir.join("share/doc/ferrocene/html"); + std::fs::create_dir_all(&product_toolchain_doc_dir) + .expect("could not create product directory"); + + // Create a file "index.html" in the doc dir to mimic docs. + let _ = File::create(product_toolchain_doc_dir.join("index.html")).unwrap(); + + // Override BROWSER to something that will fail so we can see the errors. + env::set_var("BROWSER", "THEREISNOSUCHBROWSER"); + assert_output!(test_env.cmd().args(["doc", "--project", manifest_path])); +} diff --git a/crates/criticalup-cli/tests/snapshots/cli__doc__error_opening_browser.snap b/crates/criticalup-cli/tests/snapshots/cli__doc__error_opening_browser.snap new file mode 100644 index 00000000..5671cab4 --- /dev/null +++ b/crates/criticalup-cli/tests/snapshots/cli__doc__error_opening_browser.snap @@ -0,0 +1,15 @@ +--- +source: crates/criticalup-cli/tests/cli/doc.rs +expression: repr +--- +exit: exit status: 1 + +empty stdout + +stderr +------ + INFO Opening docs in your browser for product 'ferrocene'. +error: Failed to open document in the browser at file:/path/to/toolchain/installation/96e6f26dbe3633b09bca5969805ee049655ef23f0a95fe9d0139fc9c1cc488fd/share/doc/ferrocene/html/index.html + caused by: error spawning command(s) 'THEREISNOSUCHBROWSER' + caused by: No such file or directory (os error 2) +------ diff --git a/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap b/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap index 52983596..4727684d 100644 --- a/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap +++ b/crates/criticalup-cli/tests/snapshots/cli__doc__show_path_only.snap @@ -6,7 +6,7 @@ exit: exit status: 0 stdout ------ -/path/to/toolchain/installation/96e6f26dbe3633b09bca5969805ee049655ef23f0a95fe9d0139fc9c1cc488fd/share/doc/ferrocene/html/index.html +file:/path/to/toolchain/installation/96e6f26dbe3633b09bca5969805ee049655ef23f0a95fe9d0139fc9c1cc488fd/share/doc/ferrocene/html/index.html ------ empty stderr From 47279d008cd5a3fc589f384142ec67215ef7845d Mon Sep 17 00:00:00 2001 From: Amanjeev Sethi Date: Sun, 26 Jan 2025 20:49:42 -0500 Subject: [PATCH 11/13] windows test fixes --- crates/criticalup-cli/tests/cli/utils.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/criticalup-cli/tests/cli/utils.rs b/crates/criticalup-cli/tests/cli/utils.rs index 5f481425..a3b73e24 100644 --- a/crates/criticalup-cli/tests/cli/utils.rs +++ b/crates/criticalup-cli/tests/cli/utils.rs @@ -171,6 +171,12 @@ macro_rules! assert_output { "/path/to/toolchain/installation/$ins_id/share/doc/ferrocene/html/index.html", ); + #[cfg(target_os = "windows")] + settings.add_filter( + r"file:.*[a-zA-Z]:.*toolchains/(?[_a-zA-Z0-9]+)/share/doc/ferrocene.*", + "file:/path/to/toolchain/installation/$ins_id/share/doc/ferrocene/html/index.html", + ); + // using tempfile in tests changes the output tmp dir on every run // so, this is to normalize the data first #[cfg(target_os = "linux")] @@ -195,6 +201,12 @@ macro_rules! assert_output { "error: No such file or directory (os error 2)", ); + #[cfg(windows)] + settings.add_filter( + r"caused by: program not found", + "caused by: No such file or directory (os error 2)", + ); + #[cfg(windows)] settings.add_filter( r"caused by: The system cannot find the path specified\. \(os error 3\)", From 400dcf6eca177f958a5d838b063d009ed256e7a8 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Mon, 27 Jan 2025 09:09:48 -0800 Subject: [PATCH 12/13] Remove dead snapshot --- .../tests/snapshots/cli__doc__open_browser.snap | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 crates/criticalup-cli/tests/snapshots/cli__doc__open_browser.snap diff --git a/crates/criticalup-cli/tests/snapshots/cli__doc__open_browser.snap b/crates/criticalup-cli/tests/snapshots/cli__doc__open_browser.snap deleted file mode 100644 index 61f0b6dc..00000000 --- a/crates/criticalup-cli/tests/snapshots/cli__doc__open_browser.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: crates/criticalup-cli/tests/cli/doc.rs -expression: repr ---- -exit: exit status: 0 - -empty stdout - -stderr ------- - INFO Opening docs in your browser for product 'ferrocene'. - /path/to/toolchain/installation/96e6f26dbe3633b09bca5969805ee049655ef23f0a95fe9d0139fc9c1cc488fd/share/doc/ferrocene/html/index.html ------- From f34f237a0db91c02ba72a677092c3db3e8a19358 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Mon, 27 Jan 2025 09:30:24 -0800 Subject: [PATCH 13/13] Add to CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05816a7f..4807190c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. ### Added +- Added a `criticalup doc` command which opens the documentation of the relevant Ferrocene version. - Release instructions to README. ### Fixed @@ -28,7 +29,7 @@ All notable changes to this project will be documented in this file. - Standardized error messages as close to English rules as possible. - Changed several CriticalTrust APIs to be async. -- Added a `criticalup verify` command that can be used to verify that a locally installed toolchain +- Added a `criticalup verify` command that can be used to verify that a locally installed toolchain. is not corrupted or tampered with. - Added `criticalup archive` which creates an archive of the toolchain for cold storage or backup.