From 037b33f66ddb2a0a864007f2ada74b5251d94656 Mon Sep 17 00:00:00 2001 From: "Luis H. Ball Jr" Date: Wed, 24 Nov 2021 10:17:32 -0800 Subject: [PATCH] feat!: configurable title prefixes (#14) This commit adds the `--prefix` CLI option. Providing this option allows users to tell `gh-stack` their title prefixes begin and/or end with something other than `[]`. Title prefixes can only be 2 characters long. The starting prefix is the first character and the end prefix is the second character. --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- src/main.rs | 27 ++++++++++++++++++++++----- src/persist.rs | 21 ++++++++++++++------- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 943a3d1..5e953f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -319,7 +319,7 @@ dependencies = [ [[package]] name = "gh-stack" -version = "0.2.0" +version = "0.3.0" dependencies = [ "clap", "console", @@ -698,9 +698,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.4.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" [[package]] name = "openssl" @@ -1111,11 +1111,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.0.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 38a05b1..1cc974b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gh-stack" -version = "0.2.0" +version = "0.3.0" authors = ["Timothy Andrew , Luis Ball "] license = "MIT" repository = "https://github.com/luqven/gh-stack" diff --git a/src/main.rs b/src/main.rs index 498d6e5..34287b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; use console::style; use git2::Repository; +use regex::Regex; use std::env; use std::error::Error; use std::rc::Rc; @@ -35,6 +36,11 @@ fn clap<'a, 'b>() -> App<'a, 'b> { .takes_value(false) .help("Skip waiting for confirmation"); + let prefix = Arg::with_name("prefix") + .long("prefix") + .takes_value(true) + .help("PR title prefix identifier to remove from the title"); + let annotate = SubCommand::with_name("annotate") .about("Annotate the descriptions of all PRs in a stack with metadata about all PRs in the stack") .setting(AppSettings::ArgRequiredElseHelp) @@ -42,6 +48,7 @@ fn clap<'a, 'b>() -> App<'a, 'b> { .arg(exclude.clone()) .arg(repository.clone()) .arg(ci.clone()) + .arg(prefix.clone()) .arg(Arg::with_name("prelude") .long("prelude") .short("p") @@ -148,6 +155,12 @@ fn get_excluded(m: &ArgMatches) -> Vec { } } +fn remove_title_prefixes(title: String, prefix: &str) -> String { + let regex = Regex::new(&format!("[{}]", prefix).to_string()).unwrap(); + let result = regex.replace_all(&title, "").into_owned(); + return result; +} + #[tokio::main] async fn main() -> Result<(), Box> { dotenv::from_filename(".gh-stack.env").ok(); @@ -161,6 +174,8 @@ async fn main() -> Result<(), Box> { match matches.subcommand() { ("annotate", Some(m)) => { let identifier = m.value_of("identifier").unwrap(); + let prefix = m.value_of("prefix").unwrap_or("[]"); + let prefix = regex::escape(prefix); // if ci flag is set, set ci to true let ci = m.is_present("ci"); // replace it with the -r argument value if set @@ -173,18 +188,20 @@ async fn main() -> Result<(), Box> { panic!("{}", error); } + let identifier = remove_title_prefixes(identifier.to_string(), &prefix); + println!( "Searching for {} identifier in {} repo", - style(identifier).bold(), + style(&identifier).bold(), style(repository).bold() ); let stack = - build_pr_stack_for_repo(identifier, repository, &credentials, get_excluded(m)) + build_pr_stack_for_repo(&identifier, repository, &credentials, get_excluded(m)) .await?; let table = - markdown::build_table(&stack, identifier, m.value_of("prelude"), repository); + markdown::build_table(&stack, &identifier, m.value_of("prelude"), repository); for (pr, _) in stack.iter() { println!("{}: {}", pr.number(), pr.title()); @@ -195,7 +212,7 @@ async fn main() -> Result<(), Box> { loop_until_confirm("Going to update these PRs ☝️ "); } - persist::persist(&stack, &table, &credentials).await?; + persist::persist(&stack, &table, &credentials, &prefix).await?; println!("Done!"); } @@ -283,7 +300,7 @@ async fn main() -> Result<(), Box> { &project, remote.name().unwrap(), m.value_of("boundary"), - ci + ci, ) .await?; println!("All done!"); diff --git a/src/persist.rs b/src/persist.rs index aa244c1..19cbc65 100644 --- a/src/persist.rs +++ b/src/persist.rs @@ -27,17 +27,24 @@ fn safe_replace(body: &str, table: &str) -> String { } } -fn remove_title_prefixes(row: String) -> String { - // TODO: Make this configurable - let regex = Regex::new(r"\[[^\]]+\]\s*").unwrap(); - regex.replace_all(&row, "").into_owned() +fn remove_title_prefixes(row: String, prefix: &str) -> String { + let prefix = String::from(prefix); + let prefix_1 = &prefix[0..2]; + let prefix_2 = &prefix[2..4]; + let regex_str = format!(r"{}[^\]]+{}\s*", prefix_1, prefix_2); + let regex = Regex::new(®ex_str).unwrap(); + return regex.replace_all(&row, "").into_owned(); } - -pub async fn persist(prs: &FlatDep, table: &str, c: &Credentials) -> Result<(), Box> { +pub async fn persist( + prs: &FlatDep, + table: &str, + c: &Credentials, + prefix: &str, +) -> Result<(), Box> { let futures = prs.iter().map(|(pr, _)| { let body = table.replace(&pr.title()[..], &format!("👉 {}", pr.title())[..]); - let body = remove_title_prefixes(body); + let body = remove_title_prefixes(body, prefix); let description = safe_replace(pr.body(), body.as_ref()); pull_request::update_description(description, pr.clone(), c) });