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 100 101 102 103 104 105 106
use git2::Repository; use slog::Logger; use codealong::{AnalyzeOpts, Repo, RepoConfig}; use crate::client::Client; use crate::cursor::Cursor; use crate::error::*; use crate::pull_request::PullRequest; use crate::pull_request_analyzer::PullRequestAnalyzer; pub struct PullRequestsAnalyzer<'client> { repo: Repository, config: RepoConfig, client: &'client Client, logger: Logger, } impl<'client> PullRequestsAnalyzer<'client> { pub fn new( repo: Repository, config: RepoConfig, client: &'client Client, parent_logger: &Logger, ) -> PullRequestsAnalyzer<'client> { PullRequestsAnalyzer { repo, logger: parent_logger.new(o!("repo" => config.repo.name.to_owned())), config, client, } } pub fn analyze( &self, opts: AnalyzeOpts, ) -> Result<impl Iterator<Item = Result<PullRequestAnalyzer>>> { let cursor = self.build_cursor(opts.clone()); Ok(PullRequestsCursor { repo: &self.repo, cursor, config: &self.config, opts, logger: self.logger.clone(), }) } pub fn guess_len(&self, opts: AnalyzeOpts) -> Result<usize> { if opts.since.is_some() { Ok(self.analyze(opts)?.count()) } else { Ok(self .build_cursor(opts) .guess_len() .ok_or("error estimating count of pull requests")?) } } pub fn from_repo(repo: &Repo, client: &'client Client, logger: &Logger) -> Result<Self> { Ok(Self::new(repo.repository()?, repo.config(), client, logger)) } fn build_cursor(&self, _opts: AnalyzeOpts) -> Cursor<PullRequest> { let url = format!( "https://api.github.com/repos/{}/pulls?state=all", self.config.repo.github_name.as_ref().unwrap() ); Cursor::new(&self.client, &url, &self.logger) } } struct PullRequestsCursor<'client> { repo: &'client Repository, config: &'client RepoConfig, cursor: Cursor<'client, PullRequest>, opts: AnalyzeOpts, logger: Logger, } impl<'client> Iterator for PullRequestsCursor<'client> { type Item = Result<PullRequestAnalyzer<'client>>; fn next(&mut self) -> Option<Result<PullRequestAnalyzer<'client>>> { loop { let pr = self.cursor.next(); match pr { None => break None, Some(pr) => { if let Some(ref since) = self.opts.since { if since > &pr.updated_at { break None; } } if !self.opts.ignore_unknown_authors || self.config.config.is_github_login_known(&pr.user.login) { let analyzer = PullRequestAnalyzer::new(&self.repo, pr, &self.config, &self.logger); break Some(Ok(analyzer)); } } } } } }