1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use reqwest::header::{Authorization as AuthorizationHeader, RelationType, UserAgent, LinkValue as HeaderLinkValue, Accept as AcceptHeader, Bearer as BearerAuth,
Link as LinkHeader, qitem as quality_item};
use self::super::super::util::{GITHUB_PROJECTS_ACCEPT_MIMETYPE, USER_AGENT};
use serde::de::DeserializeOwned;
use reqwest::{IntoUrl, Client};
use self::super::super::Error;
use self::super::RepoSlug;
use reqwest::mime::Mime;
use serde_json::Value;
fn request<U: IntoUrl, T: DeserializeOwned>(url: U, accept: Option<&Mime>, auth: Option<&str>, desc: &'static str) -> Result<(T, Vec<HeaderLinkValue>), Error> {
let mut bld = Client::builder()
.gzip(true)
.build()
.map_err(|_| {
Error::Io {
desc: desc,
op: "client build",
more: None,
}
})?
.get(url);
bld.header(UserAgent::new(USER_AGENT));
if let Some(acc) = accept {
bld.header(AcceptHeader(vec![quality_item(acc.clone())]));
}
if let Some(auth) = auth {
bld.header(AuthorizationHeader(BearerAuth { token: auth.to_string() }));
}
let mut resp = bld.send()
.map_err(|_| {
Error::Io {
desc: desc,
op: "request",
more: None,
}
})?;
let res = resp.json()
.map_err(|_| {
Error::Io {
desc: desc,
op: "parse",
more: None,
}
})?;
Ok((res, resp.headers().get().map(|lh: &LinkHeader| lh.values().into()).unwrap_or_else(|| vec![])))
}
fn list_things_url(mut url: String, accept: Option<&Mime>, auth: Option<&str>, arg: &'static str) -> Result<Vec<Value>, Error> {
let mut res = vec![];
loop {
let (iss, links): (Vec<Value>, Vec<HeaderLinkValue>) = request(&url, accept, auth, arg)?;
res.extend(iss);
if let Some(next_link) = links.into_iter().find(|l| l.rel().map(|l| l.contains(&RelationType::Next)).unwrap_or(false)) {
url = next_link.link().to_string();
} else {
break;
}
}
Ok(res)
}
fn list_things(repo: &RepoSlug, accept: Option<&Mime>, auth: Option<&str>, arg: &'static str) -> Result<Vec<Value>, Error> {
list_things_url(format!("https://api.github.com/repos/{}/{}?state=all", repo, arg), accept, auth, arg)
}
pub fn list_issues(repo: &RepoSlug, auth: Option<&str>) -> Result<Vec<Value>, Error> {
list_things(repo, None, auth, "issues")
}
pub fn list_pull_requests(repo: &RepoSlug, auth: Option<&str>) -> Result<Vec<Value>, Error> {
list_things(repo, None, auth, "pulls")
}
pub fn list_labels(repo: &RepoSlug, auth: Option<&str>) -> Result<Vec<Value>, Error> {
list_things(repo, None, auth, "labels")
}
pub fn list_milestones(repo: &RepoSlug, auth: Option<&str>) -> Result<Vec<Value>, Error> {
list_things(repo, None, auth, "milestones")
}
pub fn list_projects(repo: &RepoSlug, auth: &str) -> Result<Vec<Value>, Error> {
list_things(repo, Some(&GITHUB_PROJECTS_ACCEPT_MIMETYPE), Some(auth), "projects")
}
pub fn list_comments<S: Into<String>>(comments_url: S, auth: Option<&str>) -> Result<Vec<Value>, Error> {
list_things_url(comments_url.into(), None, auth, "comments")
}