securegit 0.8.5

Zero-trust git replacement with 12 built-in security scanners, LLM redteam bridge, universal undo, durable backups, and a 50-tool MCP server
Documentation
use crate::auth;
use crate::auth::SecureString;
use crate::cli::UI;
use crate::graphrag;
use anyhow::Result;
use std::path::Path;
use tracing::info;

pub fn execute(
    path: &Path,
    remote_name: &str,
    tags: bool,
    token: Option<&SecureString>,
    ssh_key: Option<&std::path::Path>,
    ui: &UI,
) -> Result<()> {
    execute_with_prune(path, remote_name, tags, false, token, ssh_key, ui)
}

pub fn execute_with_prune(
    path: &Path,
    remote_name: &str,
    tags: bool,
    prune: bool,
    token: Option<&SecureString>,
    ssh_key: Option<&std::path::Path>,
    ui: &UI,
) -> Result<()> {
    let repo = crate::ops::open_repo(path)?;
    let mut remote = repo.find_remote(remote_name)?;

    let host = remote
        .url()
        .and_then(|u| url::Url::parse(u).ok())
        .and_then(|u| u.host_str().map(|h| h.to_string()));
    let mut callbacks = auth::build_git2_callbacks(token, ssh_key, host);

    callbacks.transfer_progress(|_progress| true);

    let mut fetch_opts = git2::FetchOptions::new();
    fetch_opts.remote_callbacks(callbacks);
    fetch_opts.prune(if prune {
        git2::FetchPrune::On
    } else {
        git2::FetchPrune::Unspecified
    });

    if tags {
        fetch_opts.download_tags(git2::AutotagOption::All);
    } else {
        fetch_opts.download_tags(git2::AutotagOption::Auto);
    }

    remote.fetch(&[] as &[&str], Some(&mut fetch_opts), None)?;

    let remote_url = remote.url().map(|s| s.to_string());
    info!("Fetched from {}", remote_name);
    ui.info(format!("From {}", remote_url.as_deref().unwrap_or("")));

    if prune {
        ui.info("Pruned stale remote-tracking branches");
    }

    // Trigger GraphRAG indexing after fetch
    graphrag::client::trigger_indexing_sync(path, remote_url.as_deref(), None);

    Ok(())
}