codealong_github/
pull_request_analyzer.rs1use git2::{Oid, Repository};
2use slog::Logger;
3
4use codealong::{with_authentication, DiffAnalyzer, RepoConfig};
5
6use crate::analyzed_pull_request::AnalyzedPullRequest;
7use crate::error::{Error, Result};
8use crate::pull_request::{PullRequest, Ref};
9
10pub struct PullRequestAnalyzer<'a> {
11 repo: &'a Repository,
12 config: &'a RepoConfig,
13 pr: PullRequest,
14 logger: Logger,
15}
16
17impl<'a> PullRequestAnalyzer<'a> {
18 pub fn new(
19 repo: &'a Repository,
20 pr: PullRequest,
21 config: &'a RepoConfig,
22 parent_logger: &Logger,
23 ) -> PullRequestAnalyzer<'a> {
24 let logger = parent_logger.new(o!("pull_request_id" => pr.id));
25 PullRequestAnalyzer {
26 repo,
27 pr,
28 config,
29 logger,
30 }
31 }
32
33 pub fn analyze(self) -> Result<AnalyzedPullRequest> {
34 debug!(self.logger, "Analyzing pull_request"; "updated_at" => &self.pr.updated_at.to_rfc2822(), "user" => &self.pr.user.login, "title" => &self.pr.title);
35 self.fetch_remote(&self.pr.base)?;
36 self.fetch_remote(&self.pr.head)?;
37
38 let diff = self
39 .repo
40 .find_commit(Oid::from_str(&self.pr.base.sha)?)
41 .map_err::<Error, _>(|e| e.into())
42 .and_then(|parent| {
43 self.repo
44 .find_commit(Oid::from_str(&self.pr.head.sha)?)
45 .map_err::<Error, _>(|e| e.into())
46 .and_then(|commit| {
47 Ok(DiffAnalyzer::new(
48 &self.repo,
49 &commit,
50 Some(&parent),
51 &self.config.config,
52 )
53 .analyze()?)
54 })
55 })
56 .ok();
57
58 let normalized_author = self
59 .config
60 .config
61 .person_for_github_login(&self.pr.user.login);
62 debug!(self.logger, "Done analyzing");
63 Ok(AnalyzedPullRequest::new(self.pr, diff, normalized_author))
64 }
65
66 fn fetch_remote(&self, reference: &Ref) -> Result<()> {
67 if let Some(ref repo) = reference.repo {
68 let git_config = git2::Config::open_default()?;
69 let url = &repo.ssh_url;
70 with_authentication(url, &git_config, |f| {
71 let mut rcb = git2::RemoteCallbacks::new();
72 rcb.credentials(f);
73 let mut fo = git2::FetchOptions::new();
74 fo.remote_callbacks(rcb);
75
76 Ok(self.repo.remote_anonymous(url).and_then(|mut base| {
77 base.fetch(&[&reference.reference], Some(&mut fo), None)
78 })?)
79 })?;
80 }
81 Ok(())
82 }
83}