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
use git2::{Oid, Repository}; use slog::Logger; use codealong::{with_authentication, DiffAnalyzer, RepoConfig}; use crate::analyzed_pull_request::AnalyzedPullRequest; use crate::error::{Error, Result}; use crate::pull_request::{PullRequest, Ref}; pub struct PullRequestAnalyzer<'a> { repo: &'a Repository, config: &'a RepoConfig, pr: PullRequest, logger: Logger, } impl<'a> PullRequestAnalyzer<'a> { pub fn new( repo: &'a Repository, pr: PullRequest, config: &'a RepoConfig, parent_logger: &Logger, ) -> PullRequestAnalyzer<'a> { let logger = parent_logger.new(o!("pull_request_id" => pr.id)); PullRequestAnalyzer { repo, pr, config, logger, } } pub fn analyze(self) -> Result<AnalyzedPullRequest> { debug!(self.logger, "Analyzing pull_request"; "updated_at" => &self.pr.updated_at.to_rfc2822(), "user" => &self.pr.user.login, "title" => &self.pr.title); self.fetch_remote(&self.pr.base)?; self.fetch_remote(&self.pr.head)?; let diff = self .repo .find_commit(Oid::from_str(&self.pr.base.sha)?) .map_err::<Error, _>(|e| e.into()) .and_then(|parent| { self.repo .find_commit(Oid::from_str(&self.pr.head.sha)?) .map_err::<Error, _>(|e| e.into()) .and_then(|commit| { Ok(DiffAnalyzer::new( &self.repo, &commit, Some(&parent), &self.config.config, ) .analyze()?) }) }) .ok(); let normalized_author = self .config .config .person_for_github_login(&self.pr.user.login); debug!(self.logger, "Done analyzing"); Ok(AnalyzedPullRequest::new(self.pr, diff, normalized_author)) } fn fetch_remote(&self, reference: &Ref) -> Result<()> { if let Some(ref repo) = reference.repo { let git_config = git2::Config::open_default()?; let url = &repo.ssh_url; with_authentication(url, &git_config, |f| { let mut rcb = git2::RemoteCallbacks::new(); rcb.credentials(f); let mut fo = git2::FetchOptions::new(); fo.remote_callbacks(rcb); Ok(self.repo.remote_anonymous(url).and_then(|mut base| { base.fetch(&[&reference.reference], Some(&mut fo), None) })?) })?; } Ok(()) } }