use std::collections::HashMap;
use std::path::PathBuf;
use chrono::{DateTime, Local};
use crate::domain::repo::{GitInfo, Repo, RepoKind};
use crate::tui::presentation::{IconSet, status_text};
pub fn effective_info(repo: &Repo, example_mode: bool) -> Option<&GitInfo> {
if example_mode {
repo.example_git_info.as_ref()
} else {
repo.git_info.as_ref()
}
}
pub fn branch_text(info: Option<&GitInfo>) -> String {
match info {
None => "\u{2026}".to_string(),
Some(info) => info
.current_branch_name
.clone()
.unwrap_or_else(|| "-".to_string()),
}
}
pub fn github_text(info: Option<&GitInfo>) -> String {
info.and_then(|info| info.github_repo_name.clone())
.unwrap_or_else(|| "-".to_string())
}
pub fn status_display(info: Option<&GitInfo>, icons: &IconSet) -> String {
match info {
None => "\u{2026}".to_string(),
Some(info) if info.is_path_missing() => "-".to_string(),
Some(info) => status_text(info, icons),
}
}
pub fn zip_date_text(
repo: &Repo,
icons: &IconSet,
zip_backups: &HashMap<PathBuf, DateTime<Local>>,
) -> String {
if !repo.include_in_backup {
return icons.excluded.to_string();
}
zip_backups
.get(&repo.path)
.map_or_else(|| "-".to_string(), |dt| dt.format("%Y-%m-%d").to_string())
}
pub fn git_marker_errored(repo: &Repo, example_mode: bool) -> bool {
match repo.kind {
RepoKind::Git if example_mode => repo.example_error().is_some(),
RepoKind::Git => repo.entry_error().is_some(),
RepoKind::Path => false,
}
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use super::*;
use crate::theme::GlyphVariant;
fn icon_set() -> IconSet {
IconSet::new(GlyphVariant::Unicode)
}
fn git_repo() -> Repo {
Repo::new(PathBuf::from("/code/hop"))
}
fn info_on(branch: Option<&str>) -> GitInfo {
GitInfo {
valid: true,
current_branch_name: branch.map(str::to_string),
..GitInfo::default()
}
}
#[test]
fn example_mode_reads_the_example_info_instead_of_the_live_one() {
let mut repo = git_repo();
repo.git_info = Some(info_on(Some("live")));
repo.example_git_info = Some(info_on(Some("demo")));
assert_eq!(
branch_text(effective_info(&repo, false)),
"live",
"normally the gathered info wins"
);
assert_eq!(
branch_text(effective_info(&repo, true)),
"demo",
"example mode never shows live git data"
);
}
#[test]
fn an_unknown_status_shows_the_loading_marker_not_a_dash() {
assert_eq!(branch_text(None), "\u{2026}");
assert_eq!(status_display(None, &icon_set()), "\u{2026}");
}
#[test]
fn a_repo_without_a_branch_or_remote_reads_as_a_dash() {
let info = info_on(None);
assert_eq!(branch_text(Some(&info)), "-");
assert_eq!(github_text(Some(&info)), "-");
assert_eq!(github_text(None), "-");
}
#[test]
fn an_entry_opted_out_of_backup_shows_the_excluded_glyph() {
let icons = icon_set();
let mut repo = git_repo();
let backups = HashMap::new();
assert_eq!(zip_date_text(&repo, &icons, &backups), "-");
repo.include_in_backup = false;
assert_eq!(
zip_date_text(&repo, &icons, &backups),
icons.excluded.to_string(),
"an excluded entry must not read as 'never backed up'"
);
}
#[test]
fn only_git_entries_are_flagged_by_their_gathered_info() {
let mut path_entry = git_repo();
path_entry.kind = RepoKind::Path;
assert!(!git_marker_errored(&path_entry, false));
let mut unreported = git_repo();
assert!(!git_marker_errored(&unreported, false));
unreported.git_info = Some(GitInfo {
valid: false,
..GitInfo::default()
});
assert!(git_marker_errored(&unreported, false));
}
}