codealong_github/
pull_requests_analyzer.rs1use git2::Repository;
2use slog::Logger;
3
4use codealong::{AnalyzeOpts, Repo, RepoConfig};
5
6use crate::client::Client;
7use crate::cursor::Cursor;
8use crate::error::*;
9use crate::pull_request::PullRequest;
10use crate::pull_request_analyzer::PullRequestAnalyzer;
11
12pub struct PullRequestsAnalyzer<'client> {
13 repo: Repository,
14 config: RepoConfig,
15 client: &'client Client,
16 logger: Logger,
17}
18
19impl<'client> PullRequestsAnalyzer<'client> {
20 pub fn new(
21 repo: Repository,
22 config: RepoConfig,
23 client: &'client Client,
24 parent_logger: &Logger,
25 ) -> PullRequestsAnalyzer<'client> {
26 PullRequestsAnalyzer {
27 repo,
28 logger: parent_logger.new(o!("repo" => config.repo.name.to_owned())),
29 config,
30 client,
31 }
32 }
33
34 pub fn analyze(
35 &self,
36 opts: AnalyzeOpts,
37 ) -> Result<impl Iterator<Item = Result<PullRequestAnalyzer>>> {
38 let cursor = self.build_cursor(opts.clone());
39 Ok(PullRequestsCursor {
40 repo: &self.repo,
41 cursor,
42 config: &self.config,
43 opts,
44 logger: self.logger.clone(),
45 })
46 }
47
48 pub fn guess_len(&self, opts: AnalyzeOpts) -> Result<usize> {
49 if opts.since.is_some() {
50 Ok(self.analyze(opts)?.count())
51 } else {
52 Ok(self
53 .build_cursor(opts)
54 .guess_len()
55 .ok_or("error estimating count of pull requests")?)
56 }
57 }
58
59 pub fn from_repo(repo: &Repo, client: &'client Client, logger: &Logger) -> Result<Self> {
60 Ok(Self::new(repo.repository()?, repo.config(), client, logger))
61 }
62
63 fn build_cursor(&self, _opts: AnalyzeOpts) -> Cursor<PullRequest> {
64 let url = format!(
65 "https://api.github.com/repos/{}/pulls?state=all",
66 self.config.repo.github_name.as_ref().unwrap()
67 );
68 Cursor::new(&self.client, &url, &self.logger)
69 }
70}
71
72struct PullRequestsCursor<'client> {
73 repo: &'client Repository,
74 config: &'client RepoConfig,
75 cursor: Cursor<'client, PullRequest>,
76 opts: AnalyzeOpts,
77 logger: Logger,
78}
79
80impl<'client> Iterator for PullRequestsCursor<'client> {
81 type Item = Result<PullRequestAnalyzer<'client>>;
82
83 fn next(&mut self) -> Option<Result<PullRequestAnalyzer<'client>>> {
84 loop {
85 let pr = self.cursor.next();
86 match pr {
87 None => break None,
88 Some(pr) => {
89 if let Some(ref since) = self.opts.since {
90 if since > &pr.updated_at {
91 break None;
92 }
93 }
94
95 if !self.opts.ignore_unknown_authors
96 || self.config.config.is_github_login_known(&pr.user.login)
97 {
98 let analyzer =
99 PullRequestAnalyzer::new(&self.repo, pr, &self.config, &self.logger);
100 break Some(Ok(analyzer));
101 }
102 }
103 }
104 }
105 }
106}