Repository: eza-community/eza (language: rust)

Issue:
bug: `--git-repos` should not use colors when `--color=never`
```sh
nix run github:eza-community/eza -- --version
# v0.13.0 [+git]

cd $(mktemp -d)
git init repository
nix run github:eza-community/eza -- --color=never --git-repos --long
```

![Screenshot_20230919_040449](https://github.com/eza-community/eza/assets/3747318/1d99fd57-28a2-4f04-bb59-777b8e9e1a74)

The output of `--git-repos` uses colors even when `--color=never` is set.


Discussion / hints:
@PThorpe92 would you be available to look into this? Seems like you know this part of the code best.

Fix patch:
diff --git a/src/fs/feature/git.rs b/src/fs/feature/git.rs
index 9bda58f12..a470d0f74 100644
--- a/src/fs/feature/git.rs
+++ b/src/fs/feature/git.rs
@@ -389,27 +389,28 @@ fn current_branch(repo: &git2::Repository) -> Option<String>{
 
 impl f::SubdirGitRepo{
     pub fn from_path(dir : &Path, status : bool) -> Self{
-
         let path = &reorient(dir);
-        let g = git2::Repository::open(path);
-        if let Ok(repo) = g{
 
+        if let Ok(repo) = git2::Repository::open(path) {
             let branch = current_branch(&repo);
             if !status{
-                return Self{status : f::SubdirGitRepoStatus::GitUnknown, branch};
+                return Self{ status: None, branch };
             }
             match repo.statuses(None) {
                 Ok(es) => {
-                    if es.iter().filter(|s| s.status() != git2::Status::IGNORED).any(|_| true){
-                        return Self{status : f::SubdirGitRepoStatus::GitDirty, branch};
+                    if es.iter().any(|s| s.status() != git2::Status::IGNORED) {
+                        return Self { status: Some(f::SubdirGitRepoStatus::GitDirty), branch };
                     }
-                    return Self{status : f::SubdirGitRepoStatus::GitClean, branch};
+                    return Self { status: Some(f::SubdirGitRepoStatus::GitClean), branch };
                 }
                 Err(e) => {
                     error!("Error looking up Git statuses: {e:?}");
                 }
             }
         }
-        Self::default()
+        f::SubdirGitRepo {
+            status: if status { Some(f::SubdirGitRepoStatus::NoRepo) } else { None },
+            branch: None,
+        }
     }
 }
diff --git a/src/fs/fields.rs b/src/fs/fields.rs
index 2aa95ae4e..b40fda00b 100644
--- a/src/fs/fields.rs
+++ b/src/fs/fields.rs
@@ -271,20 +271,19 @@ pub enum SubdirGitRepoStatus{
     NoRepo,
     GitClean,
     GitDirty,
-    GitUnknown
 }
 
 #[derive(Clone)]
 pub struct SubdirGitRepo{
-    pub status : SubdirGitRepoStatus,
+    pub status : Option<SubdirGitRepoStatus>,
     pub branch : Option<String>
 }
 
 impl Default for SubdirGitRepo{
     fn default() -> Self {
         Self{
-            status : SubdirGitRepoStatus::NoRepo,
-            branch : None
+            status: Some(SubdirGitRepoStatus::NoRepo),
+            branch: None
         }
     }
 }
diff --git a/src/output/render/git.rs b/src/output/render/git.rs
index 34befa6bf..f51042089 100644
--- a/src/output/render/git.rs
+++ b/src/output/render/git.rs
@@ -1,4 +1,4 @@
-use ansiterm::{ANSIString, Style, Color};
+use ansiterm::{ANSIString, Style};
 
 use crate::output::cell::{TextCell, DisplayWidth};
 use crate::fs::fields as f;
@@ -16,32 +16,6 @@ impl f::Git {
     }
 }
 
-impl f::SubdirGitRepo {
-    pub fn render(self) -> TextCell {
-        let style = Style::new();
-        let branch_style = match self.branch.as_deref(){
-            Some("master") => style.fg(Color::Green),
-            Some("main") => style.fg(Color::Green),
-            Some(_) => style.fg(Color::Fixed(208)),
-            _ => style,
-        };
-        
-        let branch = branch_style.paint(self.branch.unwrap_or(String::from("-")));
-
-        let s = match self.status {
-            f::SubdirGitRepoStatus::NoRepo => style.paint("- "),
-            f::SubdirGitRepoStatus::GitClean => style.fg(Color::Green).paint("| "),
-            f::SubdirGitRepoStatus::GitDirty => style.bold().fg(Color::Red).paint("+ "),
-            f::SubdirGitRepoStatus::GitUnknown => style.fg(Color::Green).bold().paint("~ "),
-        };
-
-        TextCell {
-            width: DisplayWidth::from(2 + branch.len()),
-            contents: vec![s,branch].into(),
-        }
-    }
-}
-
 impl f::GitStatus {
     fn render(self, colours: &dyn Colours) -> ANSIString<'static> {
         match self {
@@ -57,7 +31,6 @@ impl f::GitStatus {
     }
 }
 
-
 pub trait Colours {
     fn not_modified(&self) -> Style;
     // FIXME: this amount of allows needed to keep clippy happy should be enough
@@ -73,6 +46,53 @@ pub trait Colours {
 }
 
 
+impl f::SubdirGitRepo {
+    pub fn render(self, colours: &dyn RepoColours) -> TextCell {
+        let branch_name = match self.branch {
+            Some(name) => {
+                if name == "main" || name == "master" { colours.branch_main().paint(name) }
+                else { colours.branch_other().paint(name) }
+            },
+            None => colours.no_repo().paint("-"),
+        };
+
+        if let Some(status) = self.status {
+            TextCell {
+                width: DisplayWidth::from(2) + DisplayWidth::from(branch_name.as_str()),
+                contents: vec![
+                    status.render(colours),
+                    Style::default().paint(" "),
+                    branch_name,
+                ].into(),
+            }
+        } else {
+            TextCell {
+                width: DisplayWidth::from(branch_name.as_str()),
+                contents: vec![branch_name].into(),
+            }
+        }
+    }
+}
+
+impl f::SubdirGitRepoStatus {
+    pub fn render(self, colours: &dyn RepoColours) -> ANSIString<'static> {
+        match self {
+            Self::NoRepo => colours.no_repo().paint("-"),
+            Self::GitClean => colours.git_clean().paint("|"),
+            Self::GitDirty => colours.git_dirty().paint("+"),
+        }
+    }
+}
+
+pub trait RepoColours {
+    fn branch_main(&self) -> Style;
+    fn branch_other(&self) -> Style;
+    fn no_repo(&self) -> Style;
+    fn git_clean(&self) -> Style;
+    fn git_dirty(&self) -> Style;
+}
+
+
 #[cfg(test)]
 pub mod test {
     use super::Colours;
diff --git a/src/output/render/mod.rs b/src/output/render/mod.rs
index 9cc7bd3e9..1326b2cf8 100644
--- a/src/output/render/mod.rs
+++ b/src/output/render/mod.rs
@@ -8,6 +8,7 @@ pub use self::filetype::Colours as FiletypeColours;
 
 mod git;
 pub use self::git::Colours as GitColours;
+pub use self::git::RepoColours as GitRepoColours;
 
 #[cfg(unix)]
 mod groups;
diff --git a/src/output/table.rs b/src/output/table.rs
index 95f73b798..c6bac9240 100644
--- a/src/output/table.rs
+++ b/src/output/table.rs
@@ -128,11 +128,11 @@ impl Columns {
         }
 
         if self.subdir_git_repos {
-            columns.push(Column::SubdirGitRepoStatus);
+            columns.push(Column::SubdirGitRepo(true));
         }
 
         if self.subdir_git_repos_no_stat {
-            columns.push(Column::SubdirGitRepoNoStatus);
+            columns.push(Column::SubdirGitRepo(false));
         }
 
         columns
@@ -157,8 +157,7 @@ pub enum Column {
     #[cfg(unix)]
     Inode,
     GitStatus,
-    SubdirGitRepoStatus,
-    SubdirGitRepoNoStatus,
+    SubdirGitRepo(bool),
     #[cfg(unix)]
     Octal,
     #[cfg(unix)]
@@ -220,8 +219,7 @@ impl Column {
             #[cfg(unix)]
             Self::Inode         => "inode",
             Self::GitStatus     => "Git",
-            Self::SubdirGitRepoStatus => "Repo",
-            Self::SubdirGitRepoNoStatus => "Repo",
+            Self::SubdirGitRepo(_) => "Repo",
             #[cfg(unix)]
             Self::Octal         => "Octal",
             #[cfg(unix)]
@@ -488,11 +486,8 @@ impl<'a> Table<'a> {
             Column::GitStatus => {
                 self.git_status(file).render(self.theme)
             }
-            Column::SubdirGitRepoStatus => {
-                self.subdir_git_repo(file, true).render()
-            }
-            Column::SubdirGitRepoNoStatus => {
-                self.subdir_git_repo(file, false).render()
+            Column::SubdirGitRepo(status) => {
+                self.subdir_git_repo(file, status).render(self.theme)
             }
             #[cfg(unix)]
             Column::Octal => {
diff --git a/src/theme/default_theme.rs b/src/theme/default_theme.rs
index 6bebe59e6..6d0f99460 100644
--- a/src/theme/default_theme.rs
+++ b/src/theme/default_theme.rs
@@ -67,6 +67,13 @@ impl UiStyles {
                 conflicted:  Red.normal(),
             },
 
+            git_repo: GitRepo {
+                branch_main: Green.normal(),
+                branch_other: Yellow.normal(),
+                git_clean: Green.normal(),
+                git_dirty: Yellow.bold(),
+            },
+
             security_context: SecurityContext {
                 none:       Style::default(),
                 selinux: SELinuxContext {
diff --git a/src/theme/mod.rs b/src/theme/mod.rs
index 347b46924..81fa6f218 100644
--- a/src/theme/mod.rs
+++ b/src/theme/mod.rs
@@ -273,6 +273,14 @@ impl render::GitColours for Theme {
     fn conflicted(&self)    -> Style { self.ui.git.conflicted }
 }
 
+impl render::GitRepoColours for Theme {
+    fn branch_main(&self) -> Style { self.ui.git_repo.branch_main }
+    fn branch_other(&self) -> Style { self.ui.git_repo.branch_other }
+    fn no_repo(&self) -> Style { self.ui.punctuation }
+    fn git_clean(&self) -> Style { self.ui.git_repo.git_clean }
+    fn git_dirty(&self) -> Style { self.ui.git_repo.git_dirty }
+}
+
 #[cfg(unix)]
 impl render::GroupColours for Theme {
     fn yours(&self)      -> Style { self.ui.users.group_yours }
diff --git a/src/theme/ui_styles.rs b/src/theme/ui_styles.rs
index 026f61007..2b77aee05 100644
--- a/src/theme/ui_styles.rs
+++ b/src/theme/ui_styles.rs
@@ -13,6 +13,7 @@ pub struct UiStyles {
     pub users:            Users,
     pub links:            Links,
     pub git:              Git,
+    pub git_repo:         GitRepo,
     pub security_context: SecurityContext,
     pub file_type:        FileType,
 
@@ -107,6 +108,14 @@ pub struct Git {
     pub conflicted: Style,  // gc
 }
 
+#[derive(Clone, Copy, Debug, Default, PartialEq)]
+pub struct GitRepo {
+    pub branch_main: Style,
+    pub branch_other: Style,
+    pub git_clean: Style,
+    pub git_dirty: Style,
+}
+
 #[derive(Clone, Copy, Debug, Default, PartialEq)]
 pub struct SELinuxContext {
     pub colon: Style,


Test patch:
diff --git a/tests/cmd/long_git_repos_no_status_nix.stdout b/tests/cmd/long_git_repos_no_status_nix.stdout
index ccb059104..89080589e 100644
--- a/tests/cmd/long_git_repos_no_status_nix.stdout
+++ b/tests/cmd/long_git_repos_no_status_nix.stdout
@@ -3,7 +3,7 @@
 .rw-r--r--  0 nixbld  1 Jan  1970 - - c
 .rw-r--r--  0 nixbld  1 Jan  1970 - - d
 .rw-r--r--  0 nixbld  1 Jan  1970 - - e
-drwxr-xr-x  - nixbld  1 Jan  1970 - - exa
+drwxr-xr-x  - nixbld  1 Jan  1970 -   exa
 .rw-r--r--  0 nixbld  1 Jan  1970 - - f
 .rw-r--r--  0 nixbld  1 Jan  1970 - - g
 .rw-r--r--  0 nixbld  1 Jan  1970 - - h
@@ -18,4 +18,4 @@ drwxr-xr-x  - nixbld  1 Jan  1970 - - exa
 .rw-r--r--  0 nixbld  1 Jan  1970 - - o
 .rw-r--r--  0 nixbld  1 Jan  1970 - - p
 .rw-r--r--  0 nixbld  1 Jan  1970 - - q
-drwxr-xr-x  - nixbld  1 Jan  1970 - - vagrant
+drwxr-xr-x  - nixbld  1 Jan  1970 -   vagrant