wrap up
This commit is contained in:
parent
8724149a04
commit
260f508dda
@ -3,6 +3,7 @@ use reqwest::{Client, RequestBuilder};
|
||||
use std::time::Duration;
|
||||
|
||||
pub mod search;
|
||||
pub mod pull_request;
|
||||
|
||||
fn base_request(client: &Client, credentials: &Credentials, url: &str) -> RequestBuilder {
|
||||
client
|
||||
@ -11,3 +12,11 @@ fn base_request(client: &Client, credentials: &Credentials, url: &str) -> Reques
|
||||
.header("Authorization", format!("token {}", credentials.token))
|
||||
.header("User-Agent", "timothyandrew/gh-stack")
|
||||
}
|
||||
|
||||
fn base_patch_request(client: &Client, credentials: &Credentials, url: &str) -> RequestBuilder {
|
||||
client
|
||||
.patch(url)
|
||||
.timeout(Duration::from_secs(5))
|
||||
.header("Authorization", format!("token {}", credentials.token))
|
||||
.header("User-Agent", "timothyandrew/gh-stack")
|
||||
}
|
20
src/api/pull_request.rs
Normal file
20
src/api/pull_request.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use std::error::Error;
|
||||
use serde::{Serialize};
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{Credentials, api};
|
||||
use crate::api::search::PullRequest;
|
||||
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct UpdateDescriptionRequest<'a> {
|
||||
body: &'a str
|
||||
}
|
||||
|
||||
pub async fn update_description(description: String, pr: Rc<PullRequest>, c: &Credentials) -> Result<(), Box<dyn Error>> {
|
||||
let client = reqwest::Client::new();
|
||||
let body = UpdateDescriptionRequest { body: &description };
|
||||
let request = api::base_patch_request(&client, &c, pr.url()).json(&body);
|
||||
request.send().await?;
|
||||
Ok(())
|
||||
}
|
@ -24,6 +24,8 @@ pub struct PullRequest {
|
||||
head: PullRequestRef,
|
||||
base: PullRequestRef,
|
||||
title: String,
|
||||
url: String,
|
||||
body: String
|
||||
}
|
||||
|
||||
impl PullRequest {
|
||||
@ -35,12 +37,20 @@ impl PullRequest {
|
||||
&self.base.label
|
||||
}
|
||||
|
||||
pub fn url(&self) -> &str {
|
||||
&self.url
|
||||
}
|
||||
|
||||
pub fn number(&self) -> usize {
|
||||
self.number
|
||||
}
|
||||
pub fn title(&self) -> &str {
|
||||
&self.title
|
||||
}
|
||||
|
||||
pub fn body(&self) -> &str {
|
||||
&self.body
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
|
@ -4,7 +4,7 @@ use std::rc::Rc;
|
||||
|
||||
use crate::api::search::PullRequest;
|
||||
|
||||
pub fn build(prs: Vec<Rc<PullRequest>>) -> Graph<Rc<PullRequest>, usize> {
|
||||
pub fn build(prs: &Vec<Rc<PullRequest>>) -> Graph<Rc<PullRequest>, usize> {
|
||||
let mut tree = Graph::<Rc<PullRequest>, usize>::new();
|
||||
let heads = prs.iter().map(|pr| pr.head());
|
||||
let handles: Vec<_> = prs.iter().map(|pr| tree.add_node(pr.clone())).collect();
|
||||
|
@ -1,6 +1,7 @@
|
||||
pub mod api;
|
||||
pub mod graph;
|
||||
pub mod markdown;
|
||||
pub mod persist;
|
||||
|
||||
pub struct Credentials {
|
||||
// Personal access token
|
||||
|
35
src/main.rs
35
src/main.rs
@ -4,11 +4,21 @@ use std::error::Error;
|
||||
use std::process;
|
||||
use std::rc::Rc;
|
||||
|
||||
use gh_stack::api;
|
||||
use gh_stack::graph;
|
||||
use gh_stack::markdown;
|
||||
use gh_stack::{api, persist, graph, markdown};
|
||||
use gh_stack::Credentials;
|
||||
|
||||
use std::io::{self, Write};
|
||||
|
||||
pub fn read_cli_input(message: &str) -> String {
|
||||
print!("{}", message);
|
||||
io::stdout().flush().unwrap();
|
||||
|
||||
let mut buf = String::new();
|
||||
io::stdin().read_line(&mut buf).unwrap();
|
||||
|
||||
buf.trim().to_owned()
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let env: HashMap<String, String> = env::vars().collect();
|
||||
@ -28,9 +38,22 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
let prs = api::search::fetch_pull_requests_matching(&pattern, &credentials).await?;
|
||||
let prs = prs.into_iter().map(|pr| Rc::new(pr)).collect();
|
||||
let tree = graph::build(prs);
|
||||
let table = markdown::build_table(tree);
|
||||
println!("{}", table);
|
||||
let tree = graph::build(&prs);
|
||||
let table = markdown::build_table(tree, pattern);
|
||||
|
||||
for pr in prs.iter() {
|
||||
println!("{}: {}", pr.number(), pr.title());
|
||||
}
|
||||
|
||||
let response = read_cli_input("Going to update these PRs ☝️ (y/n): ");
|
||||
match &response[..] {
|
||||
"y" => persist::persist(&prs, &table, &credentials).await?,
|
||||
_ => std::process::exit(1)
|
||||
}
|
||||
|
||||
persist::persist(&prs, &table, &credentials).await?;
|
||||
|
||||
println!("Done!");
|
||||
|
||||
Ok(())
|
||||
/*
|
||||
|
@ -12,9 +12,9 @@ fn process(row: String) -> String {
|
||||
regex.replace_all(&row, "").into_owned()
|
||||
}
|
||||
|
||||
pub fn build_table(graph: Graph<Rc<PullRequest>, usize>) -> String {
|
||||
pub fn build_table(graph: Graph<Rc<PullRequest>, usize>, title: &str) -> String {
|
||||
let mut out = String::new();
|
||||
out.push_str("## Stacked PR Chain");
|
||||
out.push_str(&format!("### Stacked PR Chain: {}\n", title));
|
||||
out.push_str("| PR | Title | Merges Into |\n");
|
||||
out.push_str("|:--:|:------|:-------------:|\n");
|
||||
|
||||
|
41
src/persist.rs
Normal file
41
src/persist.rs
Normal file
@ -0,0 +1,41 @@
|
||||
use regex::Regex;
|
||||
use std::error::Error;
|
||||
use futures::future::join_all;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::api::search::PullRequest;
|
||||
use crate::Credentials;
|
||||
use crate::api::pull_request;
|
||||
|
||||
const SHIELD_OPEN: &str = "<!---GHSTACKOPEN-->";
|
||||
const SHIELD_CLOSE: &str = "<!---GHSTACKCLOSE-->";
|
||||
|
||||
fn safe_replace(body: &str, table: &str) -> String {
|
||||
let new = format!("\n{}\n{}\n{}\n", SHIELD_OPEN, table, SHIELD_CLOSE);
|
||||
|
||||
if body.contains(SHIELD_OPEN) {
|
||||
let matcher = format!("(?s){}.*{}", regex::escape(SHIELD_OPEN), regex::escape(SHIELD_CLOSE));
|
||||
let re = Regex::new(&matcher).unwrap();
|
||||
re.replace_all(body, &new[..]).into_owned()
|
||||
} else {
|
||||
let mut body: String = body.to_owned();
|
||||
body.push_str(&new);
|
||||
body
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn persist(prs: &Vec<Rc<PullRequest>>, table: &str, c: &Credentials) -> Result<(), Box<dyn Error>> {
|
||||
let futures = prs.iter().map(|pr| {
|
||||
let description = safe_replace(pr.body(), table);
|
||||
pull_request::update_description(description, pr.clone(), c)
|
||||
});
|
||||
|
||||
let results = join_all(futures.collect::<Vec<_>>()).await;
|
||||
|
||||
for result in results {
|
||||
result.unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user