get the tree data structure working (finally)
This commit is contained in:
parent
cccab03886
commit
2371324cf3
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -79,6 +79,12 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixedbitset"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -227,6 +233,7 @@ name = "gh-stack"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
|
"petgraph",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -575,6 +582,16 @@ version = "2.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "petgraph"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
|
||||||
|
dependencies = [
|
||||||
|
"fixedbitset",
|
||||||
|
"indexmap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "0.4.17"
|
version = "0.4.17"
|
||||||
|
@ -11,3 +11,4 @@ reqwest = { version = "0.10.6", features = ["json"] }
|
|||||||
tokio = { version = "0.2", features = ["full"] }
|
tokio = { version = "0.2", features = ["full"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
futures = "0.3.5"
|
futures = "0.3.5"
|
||||||
|
petgraph = "0.5"
|
||||||
|
@ -2,26 +2,28 @@ use futures::future::join_all;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use crate::{api, Credentials};
|
use crate::{api, markdown, Credentials};
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct SearchItem {
|
pub struct SearchItem {
|
||||||
url: String,
|
url: String,
|
||||||
title: String,
|
title: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct PullRequestRef {
|
pub struct PullRequestRef {
|
||||||
label: String,
|
label: String,
|
||||||
r#ref: String,
|
r#ref: String,
|
||||||
sha: String,
|
sha: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct PullRequest {
|
pub struct PullRequest {
|
||||||
id: usize,
|
id: usize,
|
||||||
|
number: usize,
|
||||||
head: PullRequestRef,
|
head: PullRequestRef,
|
||||||
base: PullRequestRef,
|
base: PullRequestRef,
|
||||||
|
merges_into: Option<Box<PullRequest>>,
|
||||||
title: String,
|
title: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,8 +35,22 @@ impl PullRequest {
|
|||||||
pub fn base(&self) -> &str {
|
pub fn base(&self) -> &str {
|
||||||
&self.base.label
|
&self.base.label
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_merges_into(&mut self, into: PullRequest) {
|
||||||
|
// `clone` here to avoid an explosion of lifetime specifiers
|
||||||
|
self.merges_into = Some(Box::new(into))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impl markdown::AsMarkdown for PullRequest {
|
||||||
|
// fn as_markdown_table_row(&self) -> String {
|
||||||
|
// match self.merges_into {
|
||||||
|
// Some(into) => format!("|#{}|{}|#{}|", self.number, self.title, into.number),
|
||||||
|
// None => format!("|#{}|{}|`develop`/feature branch|", self.number, self.title),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
struct SearchResponse {
|
struct SearchResponse {
|
||||||
items: Vec<SearchItem>,
|
items: Vec<SearchItem>,
|
||||||
|
41
src/graph.rs
41
src/graph.rs
@ -1,34 +1,23 @@
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use petgraph::visit::IntoNodeReferences;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use petgraph::Graph;
|
||||||
|
|
||||||
use crate::api::search::PullRequest;
|
use crate::api::search::PullRequest;
|
||||||
|
|
||||||
pub fn build(prs: &[PullRequest]) {
|
pub fn build(prs: Vec<Rc<PullRequest>>) -> Graph<Rc<PullRequest>, usize> {
|
||||||
let mut heads = HashSet::new();
|
let mut tree = Graph::<Rc<PullRequest>, usize>::new();
|
||||||
let mut prs_by_base = HashMap::new();
|
let heads = prs.iter().map(|pr| pr.head());
|
||||||
|
let handles: Vec<_> = prs.iter().map(|pr| tree.add_node(pr.clone())).collect();
|
||||||
|
let handles_by_head: HashMap<_, _> = heads.zip(handles.iter()).collect();
|
||||||
|
|
||||||
for pr in prs.iter() {
|
for (i, pr) in prs.iter().enumerate() {
|
||||||
heads.insert(pr.head());
|
let head_handle = handles[i];
|
||||||
let entry = prs_by_base.entry(pr.base()).or_insert(Vec::new());
|
if let Some(&base_handle) = handles_by_head.get(pr.base()) {
|
||||||
entry.push(pr);
|
tree.add_edge(head_handle, *base_handle, 1);
|
||||||
}
|
|
||||||
|
|
||||||
let roots: Vec<&PullRequest> = prs.iter().filter(|pr| !heads.contains(pr.base())).collect();
|
|
||||||
let results = resolve(&roots, &prs_by_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve<'a>(
|
|
||||||
roots: &Vec<&'a PullRequest>,
|
|
||||||
prs_by_base: &'a HashMap<&str, Vec<&PullRequest>>
|
|
||||||
) -> Vec<&'a PullRequest> {
|
|
||||||
let mut results = Vec::new();
|
|
||||||
|
|
||||||
for &root in roots.iter() {
|
|
||||||
results.push(root);
|
|
||||||
if let Some(children) = prs_by_base.get(root.head()) {
|
|
||||||
let mut children = resolve(children, prs_by_base);
|
|
||||||
results.append(&mut children);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
results
|
tree
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
pub mod api;
|
pub mod api;
|
||||||
pub mod graph;
|
pub mod graph;
|
||||||
|
pub mod markdown;
|
||||||
|
|
||||||
pub struct Credentials {
|
pub struct Credentials {
|
||||||
// Personal access token
|
// Personal access token
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use gh_stack::api;
|
use gh_stack::api;
|
||||||
use gh_stack::graph;
|
use gh_stack::graph;
|
||||||
|
use gh_stack::markdown;
|
||||||
use gh_stack::Credentials;
|
use gh_stack::Credentials;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@ -25,7 +27,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let credentials = Credentials::new(token);
|
let credentials = Credentials::new(token);
|
||||||
|
|
||||||
let prs = api::search::fetch_pull_requests_matching(&pattern, &credentials).await?;
|
let prs = api::search::fetch_pull_requests_matching(&pattern, &credentials).await?;
|
||||||
graph::build(&prs);
|
let prs = prs.into_iter().map(|pr| Rc::new(pr)).collect();
|
||||||
|
let tree = graph::build(prs);
|
||||||
|
println!("{:?}", tree);
|
||||||
|
|
||||||
|
// markdown::build_table(&graph[..]);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
/*
|
/*
|
||||||
|
8
src/markdown.rs
Normal file
8
src/markdown.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::api::search::PullRequest;
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
pub trait AsMarkdown {
|
||||||
|
fn as_markdown_table_row(&self) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_table<T: Display>(graph: &[T]) {}
|
Loading…
Reference in New Issue
Block a user