pub fn update_from_repo() -> Result<()> {
        let remote_tips_path = get_remote_tips_path()?;
        let mut repo = match Repository::open(&remote_tips_path) {
            Ok(repo) => repo,
            Err(_) => {

                // If it fails to open, it means either we don't have the .git folder, or we don't have a folder at all.
                // In either case, recreate it and redownload the messages repo. No more steps are needed here.
                // On windows, remove the read-only flags before doing anything else, or this will fail.
                if cfg!(target_os = "windows") {
                    let path = remote_tips_path.to_string_lossy().to_string() + "\\*.*";
                    let _ = SystemCommand::new("attrib").arg("-r").arg(path).arg("/s").output();
                }
                let _ = std::fs::remove_dir_all(&remote_tips_path);
                DirBuilder::new().recursive(true).create(&remote_tips_path)?;
                match Repository::clone(TIPS_REPO, &remote_tips_path) {
                    Ok(_) => return Ok(()),
                    Err(_) => return Err(ErrorKind::MessagesUpdateError.into()),
                }
            }
        };

        // Just in case there are loose changes, stash them.
        // Ignore a fail on this, as it's possible we don't have contents to stash.
        let current_branch_name = Reference::normalize_name(repo.head()?.name().unwrap(), ReferenceFormat::ALLOW_ONELEVEL)?.to_lowercase();
        let master_refname = format!("refs/heads/{}", MASTER);

        let signature = Signature::now("RPFM Updater", "-")?;
        let stash_id = repo.stash_save(&signature, &format!("Stashed changes before update from branch {}", current_branch_name), Some(StashFlags::INCLUDE_UNTRACKED));

        // In case we're not in master, checkout the master branch.
        if current_branch_name != master_refname {
            repo.set_head(&master_refname)?;
        }

        // If it worked, now we have to do a pull from master. Sadly, git2-rs does not support pull.
        // Instead, we kinda force a fast-forward. Made in StackOverflow.
        repo.find_remote(REMOTE)?.fetch(&[MASTER], None, None)?;
        let (analysis, fetch_commit_id) = {
            let fetch_head = repo.find_reference("FETCH_HEAD")?;
            let fetch_commit = repo.reference_to_annotated_commit(&fetch_head)?;
            (repo.merge_analysis(&[&fetch_commit])?, fetch_commit.id())
        };

        // If we're up to date, nothing more is needed.
        if analysis.0.is_up_to_date() {

            // Reset the repo to his original state after the check
            if current_branch_name != master_refname {
                let _ = repo.set_head(&current_branch_name);
            }
            if stash_id.is_ok() {
                let _ = repo.stash_pop(0, None);
            }
            Err(ErrorKind::NoMessagesUpdatesAvailable.into())
        }

        // If we can do a fast-forward, we do it. This is the preferred option.
        else if analysis.0.is_fast_forward() {
            let mut reference = repo.find_reference(&master_refname)?;
            reference.set_target(fetch_commit_id, "Fast-Forward")?;
            repo.set_head(&master_refname)?;
            repo.checkout_head(Some(CheckoutBuilder::default().force())).map_err(From::from)
        }

        // If not, we face multiple problems:
        // - If there are uncommitted changes: covered by the stash.
        // - If we're not in the branch: covered by the branch switch.
        // - If the branches diverged: this one... the cleanest way to deal with it should be redownload the repo.
        else if analysis.0.is_normal() || analysis.0.is_none() || analysis.0.is_unborn() {

            // On windows, remove the read-only flags before doing anything else, or this will fail.
            if cfg!(target_os = "windows") {
                let path = remote_tips_path.to_string_lossy().to_string() + "\\*.*";
                let _ = SystemCommand::new("attrib").arg("-r").arg(path).arg("/s").output();
            }
            let _ = std::fs::remove_dir_all(&remote_tips_path);
            Self::update_from_repo()
        }
        else {

            // Reset the repo to his original state after the check
            if current_branch_name != master_refname {
                let _ = repo.set_head(&current_branch_name);
            }
            if stash_id.is_ok() {
                let _ = repo.stash_pop(0, None);
            }

            Err(ErrorKind::MessagesUpdateError.into())
        }
    }
/// This function downloads the latest revision of the schema repository.
This function downloads the latest revision of the schema repository.
This function downloads the latest revision of the schema repository .
pub fn update_from_repo() -> Result<()> {
        let remote_tips_path = get_remote_tips_path()?;
        let mut repo = match Repository::open(&remote_tips_path) {
            Ok(repo) => repo,
            Err(_) => {
                // If it fails to open, it means either we don't have the .git folder, or we don't have a folder at all.
                // In either case, recreate it and redownload the messages repo. No more steps are needed here.
                // On windows, remove the read-only flags before doing anything else, or this will fail.
                if cfg!(target_os = "windows") {
                    let path = remote_tips_path.to_string_lossy().to_string() + "\\*.*";
                    let _ = SystemCommand::new("attrib").arg("-r").arg(path).arg("/s").output();
                }
                let _ = std::fs::remove_dir_all(&remote_tips_path);
                DirBuilder::new().recursive(true).create(&remote_tips_path)?;
                match Repository::clone(TIPS_REPO, &remote_tips_path) {
                    Ok(_) => return Ok(()),
                    Err(_) => return Err(ErrorKind::MessagesUpdateError.into()),
                }
            }
        };
        // Just in case there are loose changes, stash them.
        // Ignore a fail on this, as it's possible we don't have contents to stash.
        let current_branch_name = Reference::normalize_name(repo.head()?.name().unwrap(), ReferenceFormat::ALLOW_ONELEVEL)?.to_lowercase();
        let master_refname = format!("refs/heads/{}", MASTER);
        let signature = Signature::now("RPFM Updater", "-")?;
        let stash_id = repo.stash_save(&signature, &format!("Stashed changes before update from branch {}", current_branch_name), Some(StashFlags::INCLUDE_UNTRACKED));
        // In case we're not in master, checkout the master branch.
        if current_branch_name != master_refname {
            repo.set_head(&master_refname)?;
        }
        // If it worked, now we have to do a pull from master. Sadly, git2-rs does not support pull.
        // Instead, we kinda force a fast-forward. Made in StackOverflow.
        repo.find_remote(REMOTE)?.fetch(&[MASTER], None, None)?;
        let (analysis, fetch_commit_id) = {
            let fetch_head = repo.find_reference("FETCH_HEAD")?;
            let fetch_commit = repo.reference_to_annotated_commit(&fetch_head)?;
            (repo.merge_analysis(&[&fetch_commit])?, fetch_commit.id())
        };
        // If we're up to date, nothing more is needed.
        if analysis.0.is_up_to_date() {
            // Reset the repo to his original state after the check
            if current_branch_name != master_refname {
                let _ = repo.set_head(&current_branch_name);
            }
            if stash_id.is_ok() {
                let _ = repo.stash_pop(0, None);
            }
            Err(ErrorKind::NoMessagesUpdatesAvailable.into())
        }
        // If we can do a fast-forward, we do it. This is the preferred option.
        else if analysis.0.is_fast_forward() {
            let mut reference = repo.find_reference(&master_refname)?;
            reference.set_target(fetch_commit_id, "Fast-Forward")?;
            repo.set_head(&master_refname)?;
            repo.checkout_head(Some(CheckoutBuilder::default().force())).map_err(From::from)
        }
        // If not, we face multiple problems:
        // - If there are uncommitted changes: covered by the stash.
        // - If we're not in the branch: covered by the branch switch.
        // - If the branches diverged: this one... the cleanest way to deal with it should be redownload the repo.
        else if analysis.0.is_normal() || analysis.0.is_none() || analysis.0.is_unborn() {
            // On windows, remove the read-only flags before doing anything else, or this will fail.
            if cfg!(target_os = "windows") {
                let path = remote_tips_path.to_string_lossy().to_string() + "\\*.*";
                let _ = SystemCommand::new("attrib").arg("-r").arg(path).arg("/s").output();
            }
            let _ = std::fs::remove_dir_all(&remote_tips_path);
            Self::update_from_repo()
        }
        else {
            // Reset the repo to his original state after the check
            if current_branch_name != master_refname {
                let _ = repo.set_head(&current_branch_name);
            }
            if stash_id.is_ok() {
                let _ = repo.stash_pop(0, None);
            }
            Err(ErrorKind::MessagesUpdateError.into())
        }
    }
pub fn update_from_repo ( ) -> Result < ( ) > { let remote_tips_path = get_remote_tips_path ( ) ? ; let mut repo = match Repository :: open ( & remote_tips_path ) { Ok ( repo ) => repo , Err ( _ ) => { // If it fails to open, it means either we don't have the .git folder, or we don't have a folder at all. // In either case, recreate it and redownload the messages repo. No more steps are needed here. // On windows, remove the read-only flags before doing anything else, or this will fail. if cfg ! ( target_os " " ) { let path = remote_tips_path . to_string_lossy ( ) . to_string ( ) + " \\ " ; let _ = SystemCommand :: new ( " " ) . arg ( " " ) . arg ( path ) . arg ( " " ) . output ( ) ; } let _ = std :: fs :: remove_dir_all ( & remote_tips_path ) ; DirBuilder :: new ( ) . recursive ( true ) . create ( & remote_tips_path ) ? ; match Repository :: clone ( TIPS_REPO , & remote_tips_path ) { Ok ( _ ) => return Ok ( ( ) ) , Err ( _ ) => return Err ( ErrorKind :: MessagesUpdateError . into ( ) ) , } } } ; // Just in case there are loose changes, stash them. // Ignore a fail on this, as it's possible we don't have contents to stash. let current_branch_name = Reference :: normalize_name ( repo . head ( ) ? . name ( ) . unwrap ( ) , ReferenceFormat :: ALLOW_ONELEVEL ) ? . to_lowercase ( ) ; let master_refname = format ! ( " " MASTER ) ; let signature = Signature :: now ( " " , " " ) ? ; let stash_id = repo . stash_save ( & signature , & format ! ( " " current_branch_name ) , Some ( StashFlags :: INCLUDE_UNTRACKED ) ) ; // In case we're not in master, checkout the master branch. if current_branch_name != master_refname { repo . set_head ( & master_refname ) ? ; } // If it worked, now we have to do a pull from master. Sadly, git2-rs does not support pull. // Instead, we kinda force a fast-forward. Made in StackOverflow. repo . find_remote ( REMOTE ) ? . fetch ( & [ MASTER ] , None , None ) ? ; let ( analysis , fetch_commit_id ) = { let fetch_head = repo . find_reference ( " " ) ? ; let fetch_commit = repo . reference_to_annotated_commit ( & fetch_head ) ? ; ( repo . merge_analysis ( & [ & fetch_commit ] ) ? , fetch_commit . id ( ) ) } ; // If we're up to date, nothing more is needed. if analysis . 0 . is_up_to_date ( ) { // Reset the repo to his original state after the check if current_branch_name != master_refname { let _ = repo . set_head ( & current_branch_name ) ; } if stash_id . is_ok ( ) { let _ = repo . stash_pop ( 0 , None ) ; } Err ( ErrorKind :: NoMessagesUpdatesAvailable . into ( ) ) } // If we can do a fast-forward, we do it. This is the preferred option. else if analysis . 0 . is_fast_forward ( ) { let mut reference = repo . find_reference ( & master_refname ) ? ; reference . set_target ( fetch_commit_id , " " ) ? ; repo . set_head ( & master_refname ) ? ; repo . checkout_head ( Some ( CheckoutBuilder :: default ( ) . force ( ) ) ) . map_err ( From :: from ) } // If not, we face multiple problems: // - If there are uncommitted changes: covered by the stash. // - If we're not in the branch: covered by the branch switch. // - If the branches diverged: this one... the cleanest way to deal with it should be redownload the repo. else if analysis . 0 . is_normal ( ) || analysis . 0 . is_none ( ) || analysis . 0 . is_unborn ( ) { // On windows, remove the read-only flags before doing anything else, or this will fail. if cfg ! ( target_os " " ) { let path = remote_tips_path . to_string_lossy ( ) . to_string ( ) + " \\ " ; let _ = SystemCommand :: new ( " " ) . arg ( " " ) . arg ( path ) . arg ( " " ) . output ( ) ; } let _ = std :: fs :: remove_dir_all ( & remote_tips_path ) ; Self :: update_from_repo ( ) } else { // Reset the repo to his original state after the check if current_branch_name != master_refname { let _ = repo . set_head ( & current_branch_name ) ; } if stash_id . is_ok ( ) { let _ = repo . stash_pop ( 0 , None ) ; } Err ( ErrorKind :: MessagesUpdateError . into ( ) ) } }
This function downloads the latest revision of the schema repository.
This function downloads the latest revision of the schema repository .