use crate::{icons, Segment, CONFIG}; use std::path::Path; use url::Url; pub fn segment(segment: &mut Segment, args: &[&str]) { for dir in CONFIG.git.ignore_dirs.iter() { if std::env::current_dir().unwrap() == Path::new( &shellexpand::full_with_context_no_errors( dir, || dirs::home_dir().map(|p| p.to_string_lossy().into_owned()), |s| std::env::var(s).map(Some).unwrap_or_default(), ) .into_owned(), ) .canonicalize() .unwrap() { return; } } if let Ok(mut repo) = git2::Repository::discover(".") { let mut domain = icons::get("git"); if let Ok(origin) = repo.find_remote("origin") { let origin = origin.url().unwrap_or_default(); match Url::parse(origin) { Ok(url) => { match url.domain().unwrap_or_default() { "github.com" => domain = icons::get("github"), "gitlab.com" => domain = icons::get("gitlab"), "bitbucket.org" => domain = icons::get("bitbucket"), "dev.azure.com" => domain = icons::get("azure"), _ => {} } } Err(_) => { if origin.starts_with("git@github.com:") { domain = icons::get("github"); } else if origin.starts_with("git@gitlab.com:") { domain = icons::get("gitlab"); } else if origin.starts_with("git@bitbucket.org:") { domain = icons::get("bitbucket"); } } } } let mut stashes = 0; repo.stash_foreach(|_, _, _| { stashes += 1; true }) .unwrap(); let stashes = icons::repeat("stash", stashes); let mut graph = String::new(); let mut branch = String::new(); if let Ok(head) = repo.head() { branch = head.shorthand().unwrap_or_default().to_owned(); let local = head.target().unwrap(); if let Ok(local_branch) = repo.find_branch(&branch, git2::BranchType::Local) { let upstream = local_branch.upstream(); if let Ok(upstream) = upstream { if let Some(upstream) = upstream.get().target() { let (ahead, behind) = match repo.graph_ahead_behind(local, upstream) { Ok((ahead, behind)) => (ahead, behind), Err(_) => (0, 0), }; graph = icons::repeat("ahead", ahead) + &icons::repeat("behind", behind); } } } } let mut modified = String::new(); let mut staged = String::new(); if let Ok(statuses) = repo.statuses(Some(git2::StatusOptions::new().include_untracked(true))) { for status in statuses.iter() { // dirty segment.background = if args.is_empty() { "yellow" } else { args[0] }.to_owned(); let status = status.status(); if modified.is_empty() && status.is_wt_new() || status.is_wt_modified() || status.is_wt_renamed() || status.is_wt_typechange() { modified = icons::get("modified"); } if staged.is_empty() && status.is_index_new() || status.is_index_modified() || status.is_index_deleted() || status.is_index_renamed() || status.is_index_typechange() { staged = icons::get("staged"); } if !modified.is_empty() && !staged.is_empty() { break; } } } let mut parts = vec![domain]; if !stashes.is_empty() || !graph.is_empty() { parts.push(stashes + &graph); } if !branch.is_empty() { parts.push(branch); } if !modified.is_empty() || !staged.is_empty() { parts.push(modified + &staged); } segment.value = parts.join(" "); } }