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.
This commit is contained in:
parent
cabd354ec9
commit
037b33f66d
|
@ -319,7 +319,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gh-stack"
|
name = "gh-stack"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"console",
|
"console",
|
||||||
|
@ -698,9 +698,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.4.0"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
|
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
|
@ -1111,11 +1111,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.0.1"
|
version = "1.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "gh-stack"
|
name = "gh-stack"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
authors = ["Timothy Andrew <mail@timothyandrew.net>, Luis Ball <luqven@gmail.com>"]
|
authors = ["Timothy Andrew <mail@timothyandrew.net>, Luis Ball <luqven@gmail.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/luqven/gh-stack"
|
repository = "https://github.com/luqven/gh-stack"
|
||||||
|
|
27
src/main.rs
27
src/main.rs
|
@ -1,6 +1,7 @@
|
||||||
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
||||||
use console::style;
|
use console::style;
|
||||||
use git2::Repository;
|
use git2::Repository;
|
||||||
|
use regex::Regex;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -35,6 +36,11 @@ fn clap<'a, 'b>() -> App<'a, 'b> {
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Skip waiting for confirmation");
|
.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")
|
let annotate = SubCommand::with_name("annotate")
|
||||||
.about("Annotate the descriptions of all PRs in a stack with metadata about all PRs in the stack")
|
.about("Annotate the descriptions of all PRs in a stack with metadata about all PRs in the stack")
|
||||||
.setting(AppSettings::ArgRequiredElseHelp)
|
.setting(AppSettings::ArgRequiredElseHelp)
|
||||||
|
@ -42,6 +48,7 @@ fn clap<'a, 'b>() -> App<'a, 'b> {
|
||||||
.arg(exclude.clone())
|
.arg(exclude.clone())
|
||||||
.arg(repository.clone())
|
.arg(repository.clone())
|
||||||
.arg(ci.clone())
|
.arg(ci.clone())
|
||||||
|
.arg(prefix.clone())
|
||||||
.arg(Arg::with_name("prelude")
|
.arg(Arg::with_name("prelude")
|
||||||
.long("prelude")
|
.long("prelude")
|
||||||
.short("p")
|
.short("p")
|
||||||
|
@ -148,6 +155,12 @@ fn get_excluded(m: &ArgMatches) -> Vec<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
dotenv::from_filename(".gh-stack.env").ok();
|
dotenv::from_filename(".gh-stack.env").ok();
|
||||||
|
@ -161,6 +174,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
("annotate", Some(m)) => {
|
("annotate", Some(m)) => {
|
||||||
let identifier = m.value_of("identifier").unwrap();
|
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
|
// if ci flag is set, set ci to true
|
||||||
let ci = m.is_present("ci");
|
let ci = m.is_present("ci");
|
||||||
// replace it with the -r argument value if set
|
// replace it with the -r argument value if set
|
||||||
|
@ -173,18 +188,20 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
panic!("{}", error);
|
panic!("{}", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let identifier = remove_title_prefixes(identifier.to_string(), &prefix);
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Searching for {} identifier in {} repo",
|
"Searching for {} identifier in {} repo",
|
||||||
style(identifier).bold(),
|
style(&identifier).bold(),
|
||||||
style(repository).bold()
|
style(repository).bold()
|
||||||
);
|
);
|
||||||
|
|
||||||
let stack =
|
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?;
|
.await?;
|
||||||
|
|
||||||
let table =
|
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() {
|
for (pr, _) in stack.iter() {
|
||||||
println!("{}: {}", pr.number(), pr.title());
|
println!("{}: {}", pr.number(), pr.title());
|
||||||
|
@ -195,7 +212,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
loop_until_confirm("Going to update these PRs ☝️ ");
|
loop_until_confirm("Going to update these PRs ☝️ ");
|
||||||
}
|
}
|
||||||
|
|
||||||
persist::persist(&stack, &table, &credentials).await?;
|
persist::persist(&stack, &table, &credentials, &prefix).await?;
|
||||||
|
|
||||||
println!("Done!");
|
println!("Done!");
|
||||||
}
|
}
|
||||||
|
@ -283,7 +300,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
&project,
|
&project,
|
||||||
remote.name().unwrap(),
|
remote.name().unwrap(),
|
||||||
m.value_of("boundary"),
|
m.value_of("boundary"),
|
||||||
ci
|
ci,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
println!("All done!");
|
println!("All done!");
|
||||||
|
|
|
@ -27,17 +27,24 @@ fn safe_replace(body: &str, table: &str) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_title_prefixes(row: String) -> String {
|
fn remove_title_prefixes(row: String, prefix: &str) -> String {
|
||||||
// TODO: Make this configurable
|
let prefix = String::from(prefix);
|
||||||
let regex = Regex::new(r"\[[^\]]+\]\s*").unwrap();
|
let prefix_1 = &prefix[0..2];
|
||||||
regex.replace_all(&row, "").into_owned()
|
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(
|
||||||
pub async fn persist(prs: &FlatDep, table: &str, c: &Credentials) -> Result<(), Box<dyn Error>> {
|
prs: &FlatDep,
|
||||||
|
table: &str,
|
||||||
|
c: &Credentials,
|
||||||
|
prefix: &str,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
let futures = prs.iter().map(|(pr, _)| {
|
let futures = prs.iter().map(|(pr, _)| {
|
||||||
let body = table.replace(&pr.title()[..], &format!("👉 {}", pr.title())[..]);
|
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());
|
let description = safe_replace(pr.body(), body.as_ref());
|
||||||
pull_request::update_description(description, pr.clone(), c)
|
pull_request::update_description(description, pr.clone(), c)
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue