diff --git a/Cargo.lock b/Cargo.lock index 641b67c..d80ee27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1873,6 +1873,7 @@ dependencies = [ "toml_edit", "tracing", "tracing-subscriber", + "unindent", "url", "which", "winreg", @@ -2495,6 +2496,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 35fa863..02f321d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ semver = { version = "1.0", features = ["serde"] } tar = "0.4" tempfile = "3.3" thiserror = "1.0" +unindent = "0.2" url = { version = "2.5", features = ["serde"] } which = "6.0" zip = "2.1" diff --git a/lib/manifests/auth.rs b/lib/manifests/auth.rs index 222124a..dc02bdd 100644 --- a/lib/manifests/auth.rs +++ b/lib/manifests/auth.rs @@ -15,7 +15,7 @@ use crate::{ }; pub const MANIFEST_FILE_NAME: &str = "auth.toml"; -const MANIFEST_DEFAULT_CONTENTS: &str = "\ +pub(super) const MANIFEST_DEFAULT_CONTENTS: &str = " # This file lists authentication tokens managed by Rokit, a toolchain manager for Roblox projects. # For more information, see <|REPOSITORY_URL|> @@ -196,10 +196,9 @@ impl ToString for AuthManifest { impl Default for AuthManifest { fn default() -> Self { - let document = MANIFEST_DEFAULT_CONTENTS - .replace("<|REPOSITORY_URL|>", env!("CARGO_PKG_REPOSITORY")) + let document = super::make_manifest_template(MANIFEST_DEFAULT_CONTENTS) .parse::() - .unwrap(); + .expect("default manifest template should be valid"); Self { document } } } diff --git a/lib/manifests/mod.rs b/lib/manifests/mod.rs index 362ccb1..b61f998 100644 --- a/lib/manifests/mod.rs +++ b/lib/manifests/mod.rs @@ -3,3 +3,54 @@ mod rokit; pub use self::auth::{AuthManifest, MANIFEST_FILE_NAME as AUTH_MANIFEST_FILE_NAME}; pub use self::rokit::{RokitManifest, MANIFEST_FILE_NAME as ROKIT_MANIFEST_FILE_NAME}; + +/** + Helper function to make sure our authored manifest templates + have consistent formatting and the correct repository URL. +*/ +fn make_manifest_template(template: &'static str) -> String { + let mut contents = unindent::unindent(template.trim()) + .replace("<|REPOSITORY_URL|>", env!("CARGO_PKG_REPOSITORY")); + contents.push('\n'); + contents +} + +// Let's also test the formatting a bit to make sure nothing slips through :-) + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn has_no_indentation() { + let auth_contents = make_manifest_template(auth::MANIFEST_DEFAULT_CONTENTS); + let rokit_contents = make_manifest_template(rokit::MANIFEST_DEFAULT_CONTENTS); + + assert!(!auth_contents.contains('\t')); + assert!(!rokit_contents.contains('\t')); + + assert!(!auth_contents.contains("\n ")); + assert!(!rokit_contents.contains("\n ")); + + assert!(!auth_contents.contains(" ")); + assert!(!rokit_contents.contains(" ")); + } + + #[test] + fn ends_with_newline() { + assert!(make_manifest_template(auth::MANIFEST_DEFAULT_CONTENTS).ends_with('\n')); + assert!(make_manifest_template(rokit::MANIFEST_DEFAULT_CONTENTS).ends_with('\n')); + } + + #[test] + fn contains_repo_url() { + let auth_contents = make_manifest_template(auth::MANIFEST_DEFAULT_CONTENTS); + let rokit_contents = make_manifest_template(rokit::MANIFEST_DEFAULT_CONTENTS); + + assert!(auth_contents.contains(env!("CARGO_PKG_REPOSITORY"))); + assert!(rokit_contents.contains(env!("CARGO_PKG_REPOSITORY"))); + + assert!(!auth_contents.contains("REPOSITORY_URL")); + assert!(!rokit_contents.contains("REPOSITORY_URL")); + } +} diff --git a/lib/manifests/rokit.rs b/lib/manifests/rokit.rs index df8322d..c602d55 100644 --- a/lib/manifests/rokit.rs +++ b/lib/manifests/rokit.rs @@ -15,11 +15,12 @@ use crate::{ }; pub const MANIFEST_FILE_NAME: &str = "rokit.toml"; -const MANIFEST_DEFAULT_CONTENTS: &str = " +pub(super) const MANIFEST_DEFAULT_CONTENTS: &str = " # This file lists tools managed by Rokit, a toolchain manager for Roblox projects. # For more information, see <|REPOSITORY_URL|> # New tools can be added by running `rokit add ` in a terminal. + [tools] "; @@ -253,10 +254,9 @@ impl ToString for RokitManifest { impl Default for RokitManifest { fn default() -> Self { - let document = MANIFEST_DEFAULT_CONTENTS - .replace("<|REPOSITORY_URL|>", env!("CARGO_PKG_REPOSITORY")) + let document = super::make_manifest_template(MANIFEST_DEFAULT_CONTENTS) .parse::() - .unwrap(); + .expect("default manifest template should be valid"); Self { document } } }