adof 0.10.0

ADOF - An Automatic Dot-files Organizer Friend
Documentation
use crate::git::{get_repo, is_remote_exist};
use crate::push::push;
use git2::{BranchType, FetchOptions, RemoteCallbacks};

pub fn link(repo_link: &str) {
    if is_remote_exist() {
        println!("Already exists");
        std::process::exit(1);
    }

    let repo = get_repo();

    repo.remote("origin", repo_link)
        .expect("Failed to add remote");

    push();

    let branch_name = "main";
    let mut config = repo.config().expect("Failed to get config");

    let remote_key = format!("branch.{}.remote", branch_name);
    config
        .set_str(&remote_key, "origin")
        .expect("Failed to set remote branch");

    let merge_key = format!("branch.{}.merge", branch_name);
    config
        .set_str(&merge_key, &format!("refs/heads/{}", branch_name))
        .expect("Failed to set branch merge configuration");

    let mut fetch_options = FetchOptions::new();
    let mut callbacks = RemoteCallbacks::new();

    callbacks.transfer_progress(|stats| {
        println!(
            "Received {} objects in {} bytes",
            stats.received_objects(),
            stats.received_bytes()
        );
        true
    });
    fetch_options.remote_callbacks(callbacks);

    let mut remote = repo.find_remote("origin").expect("Failed to find remote");
    remote
        .fetch(&[branch_name], Some(&mut fetch_options), None)
        .expect("Failed to fetch from remote");

    let origin_main_ref = repo.find_reference("refs/remotes/origin/main");
    if origin_main_ref.is_err() {
        println!("Remote repository does not have a 'main' branch.");
        std::process::exit(1);
    }

    let local_branch = match repo.find_branch(branch_name, BranchType::Local) {
        Ok(branch) => branch,
        Err(_) => {
            let commit = origin_main_ref
                .as_ref()
                .unwrap()
                .peel_to_commit()
                .expect("Failed to find remote main branch commit");
            repo.branch(branch_name, &commit, false)
                .expect("Failed to create local branch")
        }
    };

    local_branch
        .into_reference()
        .set_target(
            origin_main_ref.unwrap().target().unwrap(),
            "Setting up tracking",
        )
        .expect("Failed to set local branch to track origin");

    repo.set_head("refs/heads/main")
        .expect("Failed to set head");

    println!("Remote linked, branch tracking configured, and commits pushed if necessary.");
}