qlty_analysis/git/
upstream.rs1use anyhow::Result;
2use git2::Repository;
3use qlty_config::Workspace;
4use tracing::{info, debug};
5
6pub fn compute_upstream(workspace: &Workspace, specified: &Option<String>) -> Option<String> {
7 if let Some(specified) = specified {
8 Some(specified.to_owned())
9 } else if let Ok(upstream) = infer_upstream(workspace) {
10 info!("Inferred upstream: {:?}", upstream);
11 upstream
12 } else {
13 None
14 }
15}
16
17fn find_remote_default_branch(repo: &Repository) -> Option<String> {
18 if let Ok(_) = repo.find_remote("origin") {
19 if let Ok(head) = repo.find_reference("refs/remotes/origin/HEAD") {
20 if let Some(target) = head.symbolic_target() {
21 return Some(target.replace("refs/remotes/", ""));
22 }
23 debug!("Target not found for HEAD");
24 }
25 }
26
27 None
28}
29
30fn infer_upstream(workspace: &Workspace) -> Result<Option<String>> {
31 let repo = workspace.repo()?;
32
33 match find_remote_default_branch(&repo) {
34 Some(branch) => Ok(Some(branch)),
35 None => {
36 debug!("Could not find HEAD branch for remote 'origin'. Checking for main/master/develop.");
37 default_upstream(&repo)
38 },
39 }
40}
41
42fn default_upstream(repo: &Repository) -> Result<Option<String>> {
43 let known_default_branches = vec!["main", "master", "develop"];
44
45 for branch_name in known_default_branches.iter() {
46 if repo.find_branch(&branch_name, git2::BranchType::Local).is_ok() {
47 debug!("Found {} branch. Using as upstream.", branch_name);
48 return Ok(Some(branch_name.to_string()));
49 }
50 };
51
52 debug!("No main/master/develop branch found.");
53 Ok(None)
54}