From 1f76872878e28ec7da5750c7c72f61302e08f203 Mon Sep 17 00:00:00 2001 From: Jeremiah Russell Date: Thu, 20 Jun 2024 17:09:50 +0100 Subject: [PATCH 1/3] feat: add method add_link to Changelog * chore(Cargo.lock): update dependencies getrandom to version 0.2.14 and uuid to version 1.8.0 * feat(Cargo.toml): add uuid dependency with version 1.8.0 and features ["v4"] * feat(changelog.rs): add method add_link to Changelog struct * feat(test): add test for adding a link to Changelog * refactor(parser.rs): change log level from debug to trace in Parser struct * refactor(token.rs): change log level from debug to trace in tokenize function --- Cargo.lock | 27 +++++++++++++ Cargo.toml | 1 + src/changelog.rs | 100 +++++++++++++++++++++++++---------------------- src/parser.rs | 2 +- src/token.rs | 2 +- 5 files changed, 83 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b0d2e1..153ae86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -293,6 +293,17 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "glob" version = "0.3.1" @@ -357,6 +368,7 @@ dependencies = [ "regex", "rstest", "semver", + "uuid", ] [[package]] @@ -616,6 +628,21 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.92" diff --git a/Cargo.toml b/Cargo.toml index 1214778..fb0d74c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,3 +26,4 @@ log = "0.4.21" [dev-dependencies] log4rs_test_utils = "0.2.3" rstest = "0.19.0" +uuid = { version = "1.8.0", features = ["v4"] } diff --git a/src/changelog.rs b/src/changelog.rs index 208b222..e7fa926 100644 --- a/src/changelog.rs +++ b/src/changelog.rs @@ -387,6 +387,17 @@ impl Changelog { self } + + /// Add a link to the list of links + /// + pub fn add_link>(&mut self, link: T) -> &mut Self { + let link = Link::parse(link.into()); + + if let Ok(link) = link { + self.links.push(link); + }; + self + } } impl Display for Changelog { @@ -467,6 +478,7 @@ mod test { use log::LevelFilter; use log4rs_test_utils::test_logging; use rstest::rstest; + use uuid::Uuid; use super::*; @@ -740,61 +752,55 @@ mod test { } #[rstest] - #[case( - "tests/data/default_changelog.md", - "tests/tmp/test_rewrite_default_changelog.md" - )] - #[case( - "tests/data/default_changelog_with_unreleased.md", - "tests/tmp/test_rewrite_default_changelog_with_unreleased.md" - )] - #[case( - "tests/data/initial_changelog_unreleased.md", - "tests/tmp/test_rewrite_initial_changelog_unreleased.md" - )] - #[case( - "tests/data/early_changelog.md", - "tests/tmp/test_rewrite_early_changelog.md" - )] - #[case( - "tests/data/early_changelog_multiple_sections.md", - "tests/tmp/test_rewrite_early_changelog.md" - )] - #[case( - "tests/data/default_changelog_compact.md", - "tests/tmp/test_rewrite_default_changelog_compact.md" - )] - #[case( - "tests/data/default_changelog_with_unreleased_compact.md", - "tests/tmp/test_rewrite_default_changelog_with_unreleased_compact.md" - )] - #[case( - "tests/data/initial_changelog_unreleased_compact.md", - "tests/tmp/test_rewrite_initial_changelog_unreleased_compact.md" - )] - #[case( - "tests/data/early_changelog_compact.md", - "tests/tmp/test_rewrite_early_changelog_compact.md" - )] - #[case( - "tests/data/early_changelog_multiple_sections_compact.md", - "tests/tmp/test_rewrite_early_changelog_compact.md" - )] - fn test_save_to_file( - #[case] test_input_file: &str, - #[case] test_output_file: &str, - ) -> Result<()> { + #[case("tests/data/default_changelog.md")] + #[case("tests/data/default_changelog_with_unreleased.md")] + #[case("tests/data/initial_changelog_unreleased.md")] + #[case("tests/data/early_changelog.md")] + #[case("tests/data/early_changelog_multiple_sections.md")] + #[case("tests/data/default_changelog_compact.md")] + #[case("tests/data/default_changelog_with_unreleased_compact.md")] + #[case("tests/data/initial_changelog_unreleased_compact.md")] + #[case("tests/data/early_changelog_compact.md")] + #[case("tests/data/early_changelog_multiple_sections_compact.md")] + fn test_save_to_file(#[case] test_input_file: &str) -> Result<()> { test_logging::init_logging_once_for(vec![], LevelFilter::Debug, None); + let temp_dir_string = format!("tests/tmp/test-{}", Uuid::new_v4()); + let temp_dir = Path::new(&temp_dir_string); + + fs::create_dir_all(temp_dir).expect("failed to create temporary directory"); + + let test_output_file = format!("{}/CHANGELOG.md", temp_dir_string); + + log::debug!("Temporary directory: {:?}", temp_dir); + let changelog = Changelog::parse_from_file(test_input_file, None)?; - changelog.save_to_file(test_output_file)?; - let mut file = File::open(test_output_file)?; + changelog.save_to_file(&test_output_file)?; + let mut file = File::open(&test_output_file)?; let mut content = String::new(); file.read_to_string(&mut content)?; - assert!(are_the_same(test_input_file, test_output_file)?); + assert!(are_the_same(test_input_file, &test_output_file)?); Ok(()) } + + #[test] + fn test_add_link() { + // Create a new ChangelogBuilder instance + let builder = ChangelogBuilder::default(); + let mut changelog = builder.build().unwrap(); + + // Add a link to the builder + changelog.add_link("[anchor]: https://example.com".to_string()); + + // Assert that the link was added correctly + assert_eq!(changelog.links().len(), 1); + assert_eq!(changelog.links().first().unwrap().anchor(), "anchor"); + assert_eq!( + changelog.links().first().unwrap().url(), + "https://example.com" + ); + } } diff --git a/src/parser.rs b/src/parser.rs index b304751..d719fe1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -40,7 +40,7 @@ impl Parser { .parse_links(links)? .parse_footer()? .parse_compact(compact); - log::debug!("Parse output: {:#?}", parse_output); + log::trace!("Parse output: {:#?}", parse_output); parse_output.build() } diff --git a/src/token.rs b/src/token.rs index 8d4c5b5..c058eae 100644 --- a/src/token.rs +++ b/src/token.rs @@ -58,7 +58,7 @@ impl Token { pub fn tokenize(markdown: String) -> Result<(bool, Vec)> { let tokens: Vec = extract_tokens(markdown); - log::debug!("Tokens: {:#?}", tokens); + log::trace!("Tokens: {:#?}", tokens); let mut compact = false; From 61e8ad07672c80727e2a42fc6e128de0e05fc7a4 Mon Sep 17 00:00:00 2001 From: Jeremiah Russell Date: Fri, 21 Jun 2024 08:16:07 +0100 Subject: [PATCH 2/3] docs: add example for add_link * chore(Cargo.lock): update package versions * docs(changelog.rs): add example for adding a link to the list of links --- Cargo.lock | 84 ++++++++++++++++++++++++------------------------ src/changelog.rs | 13 ++++++++ 2 files changed, 55 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 153ae86..cea2b47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,9 +40,9 @@ checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bumpalo" @@ -52,9 +52,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "cc" -version = "1.0.95" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -84,9 +84,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "darling" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ "darling_core", "darling_macro", @@ -94,27 +94,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.60", + "syn 2.0.67", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.60", + "syn 2.0.67", ] [[package]] @@ -157,7 +157,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.67", ] [[package]] @@ -167,7 +167,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core", - "syn 2.0.60", + "syn 2.0.67", ] [[package]] @@ -179,7 +179,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.67", ] [[package]] @@ -254,7 +254,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.67", ] [[package]] @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -379,9 +379,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "log" @@ -427,15 +427,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -460,9 +460,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -478,9 +478,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -490,9 +490,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -501,9 +501,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "relative-path" @@ -536,7 +536,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.60", + "syn 2.0.67", "unicode-ident", ] @@ -551,9 +551,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "slab" @@ -566,9 +566,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" @@ -583,9 +583,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90" dependencies = [ "proc-macro2", "quote", @@ -609,7 +609,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.67", ] [[package]] @@ -664,7 +664,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.67", "wasm-bindgen-shared", ] @@ -686,7 +686,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.67", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/src/changelog.rs b/src/changelog.rs index e7fa926..ec5ee8f 100644 --- a/src/changelog.rs +++ b/src/changelog.rs @@ -390,6 +390,19 @@ impl Changelog { /// Add a link to the list of links /// + /// # Examples + /// ``` + /// # fn main() { + /// let mut changelog = ChangelogBuilder::default().build().unwrap(); + /// + /// changelog.add_link("[anchor]: https://example.com".to_string()); + /// + /// // Assert that the link was added correctly + /// assert_eq!(changelog.links().len(), 1); + /// assert_eq!(changelog.links().first().unwrap().anchor(), "anchor"); + /// assert_eq!(changelog.links().first().unwrap().url(),"https://example.com"); + /// # } + /// pub fn add_link>(&mut self, link: T) -> &mut Self { let link = Link::parse(link.into()); From 4f5966ca5d03868947941605187de3d524c909e9 Mon Sep 17 00:00:00 2001 From: Jeremiah Russell Date: Mon, 24 Jun 2024 12:27:57 +0100 Subject: [PATCH 3/3] refactor: add link based on specified anchor and url * fix(changelog.rs): change add_link method signature to accept both anchor and url parameters * feat(link.rs): add new method to create a Link instance with anchor and url parameters, handle missing anchor and url errors, and add tests for new method --- src/changelog.rs | 6 +++--- src/link.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/changelog.rs b/src/changelog.rs index ec5ee8f..eaadfc3 100644 --- a/src/changelog.rs +++ b/src/changelog.rs @@ -403,8 +403,8 @@ impl Changelog { /// assert_eq!(changelog.links().first().unwrap().url(),"https://example.com"); /// # } /// - pub fn add_link>(&mut self, link: T) -> &mut Self { - let link = Link::parse(link.into()); + pub fn add_link>(&mut self, anchor: S, url: S) -> &mut Self { + let link = Link::new(anchor, url); if let Ok(link) = link { self.links.push(link); @@ -806,7 +806,7 @@ mod test { let mut changelog = builder.build().unwrap(); // Add a link to the builder - changelog.add_link("[anchor]: https://example.com".to_string()); + changelog.add_link("[anchor]:", "https://example.com"); // Assert that the link was added correctly assert_eq!(changelog.links().len(), 1); diff --git a/src/link.rs b/src/link.rs index b1a068e..1aecd86 100644 --- a/src/link.rs +++ b/src/link.rs @@ -1,7 +1,7 @@ use std::fmt::Display; use derive_getters::Getters; -use eyre::{OptionExt, Result}; +use eyre::{eyre, OptionExt, Result}; /// Represents a link in a changelog. #[derive(Debug, Clone, Getters, PartialEq, Eq)] @@ -33,6 +33,23 @@ impl Link { Ok(Self { anchor, url }) } + + pub fn new>(anchor: S, url: S) -> Result { + let anchor = anchor.into(); + let anchor = anchor.replace(['[', ']', ':'], ""); + + if anchor.is_empty() { + return Err(eyre!("Missing anchor: {anchor}")); + } + + let url = url.into(); + + if url.is_empty() { + return Err(eyre!("Missing url")); + } + + Ok(Self { anchor, url }) + } } impl Display for Link { @@ -40,3 +57,38 @@ impl Display for Link { write!(f, "[{}]: {}", self.anchor, self.url) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_new_with_invalid_anchor() { + let result = Link::new("", "https://example.com"); + assert!(result.is_err()); + } + + #[test] + fn test_new_with_invalid_url() { + let result = Link::new("anchor", ""); + assert!(result.is_err()); + } + + #[test] + fn test_new_with_valid_anchor_and_url() { + let result = Link::new("anchor", "https://example.com"); + assert!(result.is_ok()); + let link = result.unwrap(); + assert_eq!(link.anchor(), "anchor"); + assert_eq!(link.url(), "https://example.com"); + } + + #[test] + fn test_new_with_valid_decorarted_anchor_and_url() { + let result = Link::new("[anchor]:", "https://example.com"); + assert!(result.is_ok()); + let link = result.unwrap(); + assert_eq!(link.anchor(), "anchor"); + assert_eq!(link.url(), "https://example.com"); + } +}