From 0b79105894918820187c490ca6024dd103554daf Mon Sep 17 00:00:00 2001 From: Marc Addeo Date: Tue, 28 Jul 2020 13:37:24 -0400 Subject: [PATCH] Add aggregate command (#17) --- .cl/add-aggregate-command.yml | 3 ++ Cargo.lock | 94 +++++++++++++++++++++++++++++++++-- Cargo.toml | 4 +- README.md | 16 ++++++ src/main.rs | 45 +++++++++++++++-- 5 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 .cl/add-aggregate-command.yml diff --git a/.cl/add-aggregate-command.yml b/.cl/add-aggregate-command.yml new file mode 100644 index 0000000..807e0ca --- /dev/null +++ b/.cl/add-aggregate-command.yml @@ -0,0 +1,3 @@ +--- +- fixed: Fix bug that caused cl entries to be not properly nested in their branch directories +- added: Add an aggregate subcommand to aggregate change entries into the CHANGELOG.md file diff --git a/Cargo.lock b/Cargo.lock index f99edcb..562a11d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,10 +64,12 @@ version = "0.8.0" dependencies = [ "anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clparse 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clparse 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive_builder 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "gag 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_empty_subdirs 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "scan_dir 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -92,7 +94,7 @@ dependencies = [ [[package]] name = "clparse" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -254,6 +256,15 @@ name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "gag" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "getopts" version = "0.2.21" @@ -447,6 +458,11 @@ name = "pkg-config" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ppv-lite86" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro-error" version = "0.2.6" @@ -505,11 +521,61 @@ dependencies = [ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "remove_empty_subdirs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc_version" version = "0.2.3" @@ -640,6 +706,19 @@ dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -769,7 +848,7 @@ dependencies = [ "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum clparse 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bafb5c763e21e68b4cd0ca27a566769810f7ea19d487f56efadff832ab5a745f" +"checksum clparse 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b32d1766bacb5f7a4a87a37bdb76c91c522326eceea5875697496e22d812ed0f" "checksum darling 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe629a532efad5526454efb0700f86d5ad7ff001acb37e431c8bf017a432a8e" "checksum darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfbcb0c5961907597a7d1148e3af036268f2b773886b8bb3eeb1e1281d3d3d6" "checksum darling_core 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ee54512bec54b41cf2337a22ddfadb53c7d4c738494dc2a186d7b037ad683b85" @@ -784,6 +863,7 @@ dependencies = [ "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b41487fadaa500d02a819eefcde5f713599a01dd51626ef25d2d72d87115667b" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +"checksum gag 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8cc0b9f53275dc5fada808f1d2f82e3688a6c14d735633d1590b7be8eb2307b5" "checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" "checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" "checksum git2 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39f27186fbb5ec67ece9a56990292bc5aed3c3fc51b9b07b0b52446b1dfb4a82" @@ -808,6 +888,7 @@ dependencies = [ "checksum openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)" = "2c42dcccb832556b5926bc9ae61e8775f2a61e725ab07ab3d1e7fcf8ae62c3b6" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" +"checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" @@ -815,7 +896,13 @@ dependencies = [ "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +"checksum remove_empty_subdirs 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c52a635b39a65100b9503ede35e6ea972cf53869efbee69cf08d7aa440c9986e" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum scan_dir 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1ccb8e3d26f2775b128b053d1827feb90ed954ef97e3cb88c822f42e946c9155" @@ -833,6 +920,7 @@ dependencies = [ "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" +"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" diff --git a/Cargo.toml b/Cargo.toml index eee778a..c14450f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,5 +26,7 @@ serde_yaml = "0.8.11" serde_json = "1.0.41" err-derive = "0.1.6" anyhow = "1.0.31" -clparse = "0.7.0" +clparse = "0.8.0" semver = "0.10.0" +remove_empty_subdirs = "0.1.1" +gag = "0.1.10" diff --git a/README.md b/README.md index 9ccabd3..01f22cd 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ SUBCOMMANDS: security Creates a change entry to be placed in the Security section of the CHANGELOG edit Opens the change file for direct editing yank Mark a specific release as [YANKED] + aggregate Aggregate change entries into the Unreleased section of the CHANGELOG ``` ## Examples @@ -128,3 +129,18 @@ Sometimes a release doesn't go as plan after the fact, and needs to be yanked from history. To do so, simply type `cl yank 1.2.3` where `1.2.3` is the release you wish to yank. This will tag the release as `[YANKED]` and remove it's link from the CHANGELOG. + +### Aggregating unreleased changes +After you've made some changes and they've been merged, you'll likely want to +aggregate your cl entries into the actual CHANGELOG.md file so they can be +easily viewed by users. This can be achieved with the `aggregate` subcommand. + +``` +$ cl aggregate +``` + +This will take any change entries in the `.cl` directory, put them into the +`CHANGELOG.md` file, and then remove them and any empty directories within the +`.cl` directory. + +This command is useful to run via CI after a pull request has been merged. diff --git a/src/main.rs b/src/main.rs index 7fdd357..37e625c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,8 @@ use clparse::changelog::{Change, Changelog, ReleaseBuilder}; use err_derive::Error; use semver::Version; use scan_dir::ScanDir; +use gag::Gag; +use remove_empty_subdirs::remove_empty_subdirs; use std::env; use std::fs::{create_dir_all, OpenOptions}; use std::io::{self, Write}; @@ -139,6 +141,10 @@ fn main() -> Result<()> { .required(true) ) ) + .subcommand( + SubCommand::with_name("aggregate") + .about("Aggregate change entries into the Unreleased section of the CHANGELOG") + ) .get_matches(); match matches.subcommand() { @@ -203,6 +209,19 @@ fn main() -> Result<()> { Ok(()) } + ("aggregate", Some(_)) => { + let mut changelog = get_changelog()?; + + if let Some(unreleased) = changelog.unreleased_mut() { + unreleased.set_changes(get_all_changes()?); + std::fs::write(get_changelog_path()?, format!("{}", changelog))?; + remove_cl_change_entries()?; + } else { + bail!(ClError::ReleaseNotFound("Unreleased".to_string())); + } + + Ok(()) + } (kind, Some(sub_matches)) => { let description = sub_matches .values_of("description") @@ -250,7 +269,7 @@ fn get_cl_path() -> Result { cl_path.push(head); create_dir_all(cl_path.clone())?; - cl_path.set_extension("yml"); + cl_path.push("changes.yml"); Ok(cl_path) } @@ -284,8 +303,7 @@ fn get_unreleased_changes() -> Result> { Ok(get_changelog()?.unreleased_changes()) } -fn get_all_changes() -> Result> { - let mut changes: Vec = get_unreleased_changes()?; +fn get_cl_entry_paths() -> Result> { let mut logs: Vec = Vec::new(); let cl_dir = get_cl_dir()?; @@ -302,6 +320,27 @@ fn get_all_changes() -> Result> { }) .map_err(ClError::ScanError)?; + Ok(logs) +} + +fn remove_cl_change_entries() -> Result<()> { + let logs = get_cl_entry_paths()?; + + for log in logs { + std::fs::remove_file(log)?; + } + + let gag = Gag::stdout()?; + remove_empty_subdirs(get_cl_dir()?.as_path())?; + drop(gag); + + Ok(()) +} + +fn get_all_changes() -> Result> { + let mut changes: Vec = get_unreleased_changes()?; + let logs = get_cl_entry_paths()?; + for log in logs { let mut cl_changes = get_changes(log)?; changes.append(&mut cl_changes);