git_api/
remote.rs

1use git2::{Error, Remote};
2
3use crate::auth::auth_callbacks;
4
5/// 获取远程仓库的引用(refs)
6/// 
7/// 返回值:Vec<(ref_name, is_symref_target, symref_target_or_oid)>
8pub fn remote_refs(repo_url: &str, username: &str, password: &str) -> Result<Vec<(String, bool, String)>, Error> {
9    let callbacks = auth_callbacks(username, password);
10    let mut remote = Remote::create_detached(repo_url)?; // Create a remote with the given URL in-memory
11    remote.connect_auth(git2::Direction::Fetch, Some(callbacks), None)?; // Open a connection to a remote with callbacks and proxy settings
12    // remote.connect(git2::Direction::Fetch)?; // Open a connection to a remote.
13
14    // Get the remote repository's reference advertisement list.
15    let result = remote.list()?.iter().map(|head| {
16        let ref_name = head.name();
17        let oid = head.oid();
18        if let Some(target) = head.symref_target() {
19            (ref_name.into(), true, target.into())
20        } else {
21            (ref_name.into(), false, oid.to_string())
22        }
23    }).collect();
24    Ok(result)
25}
26
27/// 查询远程仓库的主分支
28/// 
29/// 返回值:主分支名,如:Some("master")
30pub fn remote_default_branch(repo_url: &str, username: &str, password: &str) -> Result<Option<String>, Error> {
31    let branchs = remote_refs(repo_url, username, password)?;
32    let Some((_ref_name, _is_symref_target, default_branch)) = branchs.iter()
33        .find(|(ref_name, is_symref_target, _symref_target_or_oid)| {
34            ref_name == "HEAD" && *is_symref_target
35        }) else {
36            return Ok(None);
37        };
38    let default_branch = default_branch.replacen("refs/heads/", "", 1);
39    Ok(Some(default_branch))
40}