Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add status for subdirectories that are git repositories #797

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d214daa
Add SubdirGitRepo and SubdirGitRepoStatus types (#730)
alpn Jan 31, 2021
d0470d3
Add render() implementation for SubdirGitRepo (#730)
alpn Jan 31, 2021
f931eec
Add SubdirGitRepo::from_path() (#730)
alpn Jan 31, 2021
b55fde4
Add Columns a flag to determine whether or not to show status for sub…
alpn Jan 31, 2021
22a1b29
Add SubdirGitRepoStatus variant to Columns (#730)
alpn Jan 31, 2021
c63455b
Remove unused colours parameter from f::SubdirGitRepo::render()
alpn Jan 31, 2021
da3ce93
Add a dummy SubdirGitRepo::from_path() implementation for
alpn Jan 31, 2021
f17cf3d
Add git branch info to Repo column
alpn Feb 2, 2021
778374e
Merge branch 'master' into master
alpn Jun 30, 2021
5a35944
Add "main" as an alternative name for default branch, in accordance with
alpn Jun 30, 2021
87eb5ed
Merge branch 'master' of https://github.com/ogham/exa
alpn Oct 6, 2021
4504da0
Merge branch 'master' of https://github.com/ogham/exa
alpn Oct 10, 2021
d5381b3
Modify git repo clean/dirty indicators
alpn Oct 10, 2021
d9e2003
Merge branch 'ogham:master' into master
alpn Oct 19, 2021
4510551
Optimize status lookup of subdir git repos
alpn Nov 14, 2021
881c61e
Add indicative truncation for long branch names
alpn Nov 14, 2021
bc5b457
Merge branch 'ogham:master' into master
alpn Dec 5, 2021
36159b3
Merge branch 'ogham:master' into master
alpn Dec 10, 2021
a090985
Merge branch 'ogham:master' into master
alpn Dec 12, 2021
b8ecd67
Merge branch 'ogham:master' into master
alpn Dec 27, 2021
2f1f30e
Merge branch 'ogham:master' into master
alpn Mar 21, 2022
33cef20
Merge branch 'ogham:master' into master
alpn Oct 8, 2022
7703560
Add dedicated flags for displaying sub-directory git repo info, -—git…
alpn Oct 9, 2022
ff0dd7f
Fix interface for #[cfg(not(feature = "git"))] mode
alpn Oct 9, 2022
3969725
Merge branch 'master' into master
alpn Aug 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/fs/feature/git.rs
Expand Up @@ -343,3 +343,52 @@ fn index_status(status: git2::Status) -> f::GitStatus {
_ => f::GitStatus::NotModified,
}
}

fn current_branch(repo: &git2::Repository) -> Option<String>{
let head = match repo.head() {
Ok(head) => Some(head),
Err(ref e) if e.code() == git2::ErrorCode::UnbornBranch || e.code() == git2::ErrorCode::NotFound => return None,
Err(e) => {
error!("Error looking up Git branch: {:?}", e);
return None
}
};

if let Some(h) = head{
if let Some(s) = h.shorthand(){
let branch_name = s.to_owned();
if branch_name.len() > 10 {
return Some(branch_name[..8].to_string()+"..");
}
return Some(branch_name);
}
}
None
}

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{

let branch = current_branch(&repo);
if !status{
return Self{status : f::SubdirGitRepoStatus::GitUnknown, 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};
}
return Self{status : f::SubdirGitRepoStatus::GitClean, branch};
}
Err(e) => {
error!("Error looking up Git statuses: {:?}", e)
}
}
}
Self::default()
}
}
6 changes: 6 additions & 0 deletions src/fs/feature/mod.rs
Expand Up @@ -30,4 +30,10 @@ pub mod git {
unreachable!();
}
}

impl f::SubdirGitRepo{
pub fn from_path(_dir : &Path, _status : bool) -> Self{
panic!("Tried to get subdir Git status, but Git support is disabled")
}
}
}
24 changes: 24 additions & 0 deletions src/fs/fields.rs
Expand Up @@ -259,3 +259,27 @@ impl Default for Git {
}
}
}

#[allow(dead_code)]
#[derive(PartialEq, Copy, Clone)]
pub enum SubdirGitRepoStatus{
NoRepo,
GitClean,
GitDirty,
GitUnknown
}

#[derive(Clone)]
pub struct SubdirGitRepo{
pub status : SubdirGitRepoStatus,
pub branch : Option<String>
}

impl Default for SubdirGitRepo{
fn default() -> Self {
Self{
status : SubdirGitRepoStatus::NoRepo,
branch : None
}
}
}
10 changes: 6 additions & 4 deletions src/options/flags.rs
Expand Up @@ -62,9 +62,11 @@ pub static NO_TIME: Arg = Arg { short: None, long: "no-time", takes_value: Takes
pub static NO_ICONS: Arg = Arg { short: None, long: "no-icons", takes_value: TakesValue::Forbidden };

// optional feature options
pub static GIT: Arg = Arg { short: None, long: "git", takes_value: TakesValue::Forbidden };
pub static EXTENDED: Arg = Arg { short: Some(b'@'), long: "extended", takes_value: TakesValue::Forbidden };
pub static OCTAL: Arg = Arg { short: None, long: "octal-permissions", takes_value: TakesValue::Forbidden };
pub static GIT: Arg = Arg { short: None, long: "git", takes_value: TakesValue::Forbidden };
pub static GIT_REPOS: Arg = Arg { short: None, long: "git-repos", takes_value: TakesValue::Forbidden };
pub static GIT_REPOS_NO_STAT: Arg = Arg { short: None, long: "git-repos-no-status", takes_value: TakesValue::Forbidden };
pub static EXTENDED: Arg = Arg { short: Some(b'@'), long: "extended", takes_value: TakesValue::Forbidden };
pub static OCTAL: Arg = Arg { short: None, long: "octal-permissions", takes_value: TakesValue::Forbidden };


pub static ALL_ARGS: Args = Args(&[
Expand All @@ -80,5 +82,5 @@ pub static ALL_ARGS: Args = Args(&[
&BLOCKS, &TIME, &ACCESSED, &CREATED, &TIME_STYLE,
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME, &NO_ICONS,

&GIT, &EXTENDED, &OCTAL
&GIT, &GIT_REPOS, &GIT_REPOS_NO_STAT, &EXTENDED, &OCTAL
]);
5 changes: 4 additions & 1 deletion src/options/view.rs
Expand Up @@ -199,7 +199,10 @@ impl TableOptions {
impl Columns {
fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
let time_types = TimeTypes::deduce(matches)?;

let git = matches.has(&flags::GIT)?;
let subdir_git_repos = matches.has(&flags::GIT_REPOS)?;
let subdir_git_repos_no_stat = !subdir_git_repos && matches.has(&flags::GIT_REPOS_NO_STAT)?;

let blocks = matches.has(&flags::BLOCKS)?;
let group = matches.has(&flags::GROUP)?;
Expand All @@ -211,7 +214,7 @@ impl Columns {
let filesize = ! matches.has(&flags::NO_FILESIZE)?;
let user = ! matches.has(&flags::NO_USER)?;

Ok(Self { time_types, inode, links, blocks, group, git, octal, permissions, filesize, user })
Ok(Self { time_types, inode, links, blocks, group, git, subdir_git_repos, subdir_git_repos_no_stat,octal, permissions, filesize, user })
}
}

Expand Down
27 changes: 26 additions & 1 deletion src/output/render/git.rs
@@ -1,4 +1,4 @@
use ansi_term::{ANSIString, Style};
use ansi_term::{ANSIString, Style, Color};

use crate::output::cell::{TextCell, DisplayWidth};
use crate::fs::fields as f;
Expand All @@ -16,6 +16,31 @@ 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.paint("- "),
};

TextCell {
width: DisplayWidth::from(2 + branch.len()),
contents: vec![s,branch].into(),
}
}
}

impl f::GitStatus {
fn render(self, colours: &dyn Colours) -> ANSIString<'static> {
Expand Down
29 changes: 29 additions & 0 deletions src/output/table.rs
Expand Up @@ -43,6 +43,8 @@ pub struct Columns {
pub blocks: bool,
pub group: bool,
pub git: bool,
pub subdir_git_repos: bool,
pub subdir_git_repos_no_stat: bool,
pub octal: bool,

// Defaults to true:
Expand Down Expand Up @@ -113,6 +115,14 @@ impl Columns {
columns.push(Column::GitStatus);
}

if self.subdir_git_repos {
columns.push(Column::SubdirGitRepoStatus);
}

if self.subdir_git_repos_no_stat {
columns.push(Column::SubdirGitRepoNoStatus);
}

columns
}
}
Expand All @@ -135,6 +145,8 @@ pub enum Column {
#[cfg(unix)]
Inode,
GitStatus,
SubdirGitRepoStatus,
SubdirGitRepoNoStatus,
#[cfg(unix)]
Octal,
}
Expand Down Expand Up @@ -192,6 +204,8 @@ impl Column {
#[cfg(unix)]
Self::Inode => "inode",
Self::GitStatus => "Git",
Self::SubdirGitRepoStatus => "Repo",
Self::SubdirGitRepoNoStatus => "Repo",
#[cfg(unix)]
Self::Octal => "Octal",
}
Expand Down Expand Up @@ -496,6 +510,12 @@ impl<'a, 'f> 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()
}
#[cfg(unix)]
Column::Octal => {
self.octal_permissions(file).render(self.theme.ui.octal)
Expand Down Expand Up @@ -524,6 +544,15 @@ impl<'a, 'f> Table<'a> {
.unwrap_or_default()
}

fn subdir_git_repo(&self, file: &File<'_>, status : bool) -> f::SubdirGitRepo {
debug!("Getting subdir repo status for path {:?}", file.path);

if file.is_directory(){
return f::SubdirGitRepo::from_path(&file.path, status);
}
f::SubdirGitRepo::default()
}

pub fn render(&self, row: Row) -> TextCell {
let mut cell = TextCell::default();

Expand Down