From aca75ffdcd3393fe4514835d2bfd1d0ba1e98a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20HAV=C3=89?= Date: Mon, 1 Mar 2021 23:08:13 +0100 Subject: [PATCH] WIP (issue #7) Gather flags for all files in a git directory (panic out of git directory). --- Cargo.lock | 184 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 +- src/app.rs | 18 +++- src/config_file.rs | 6 +- src/core.rs | 17 +++- src/display.rs | 10 ++- src/flags.rs | 7 ++ src/flags/blocks.rs | 27 ++++++ src/flags/git_status.rs | 55 ++++++++++++ src/git.rs | 125 +++++++++++++++++++++++++++ src/logger.rs | 29 +++++++ src/main.rs | 3 + src/meta/filetype.rs | 5 +- src/meta/git_status.rs | 4 + src/meta/mod.rs | 16 +++- 15 files changed, 501 insertions(+), 9 deletions(-) create mode 100644 src/flags/git_status.rs create mode 100644 src/git.rs create mode 100644 src/logger.rs create mode 100644 src/meta/git_status.rs diff --git a/Cargo.lock b/Cargo.lock index 3aa1eba30..6d83b870e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,6 +115,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "cc" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +dependencies = [ + "jobserver", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -233,6 +242,16 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + [[package]] name = "getrandom" version = "0.1.15" @@ -244,6 +263,21 @@ dependencies = [ "wasi 0.9.0+wasi-snapshot-preview1", ] +[[package]] +name = "git2" +version = "0.13.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d250f5f82326884bd39c2853577e70a121775db76818ffa452ed1e80de12986" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + [[package]] name = "glob" version = "0.3.0" @@ -288,6 +322,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "140a09c9305e6d5e557e2ed7cbc68e05765a7d4213975b87cb04920689cc6219" +[[package]] +name = "idna" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "ignore" version = "0.4.16" @@ -315,6 +360,15 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "jobserver" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +dependencies = [ + "libc", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -327,6 +381,46 @@ version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" +[[package]] +name = "libgit2-sys" +version = "0.12.18+1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da6a42da88fc37ee1ecda212ffa254c25713532980005d5f7c0b0fbe7e6e885" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + +[[package]] +name = "libssh2-sys" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0186af0d8f171ae6b9c4c90ec51898bad5d08a2d5e470903a50d9ad8959cbee" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linked-hash-map" version = "0.5.3" @@ -371,9 +465,11 @@ dependencies = [ "chrono-humanize", "clap", "dirs", + "git2", "globset", "human-sort", "libc", + "log", "lscolors", "predicates", "serde", @@ -391,6 +487,12 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + [[package]] name = "memchr" version = "2.3.3" @@ -422,6 +524,25 @@ dependencies = [ "autocfg", ] +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.11.1" @@ -447,6 +568,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + [[package]] name = "ppv-lite86" version = "0.2.9" @@ -762,12 +895,45 @@ dependencies = [ "winapi", ] +[[package]] +name = "tinyvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + [[package]] name = "treeline" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-width" version = "0.1.8" @@ -780,6 +946,18 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "url" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + [[package]] name = "users" version = "0.11.0" @@ -790,6 +968,12 @@ dependencies = [ "log", ] +[[package]] +name = "vcpkg" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" + [[package]] name = "vec_map" version = "0.8.2" diff --git a/Cargo.toml b/Cargo.toml index 526f6b874..e861f5bc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,12 +36,14 @@ xdg = "2.1.*" yaml-rust = "0.4.*" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" +log = { version = "0.4", features = ["release_max_level_warn"] } +git2 = "0.13" [target.'cfg(unix)'.dependencies] users = "0.11.*" [target.'cfg(windows)'.dependencies] -winapi = {version = "0.3.*", features = ["aclapi", "accctrl", "winnt", "winerror", "securitybaseapi", "winbase"]} +winapi = { version = "0.3.*", features = ["aclapi", "accctrl", "winnt", "winerror", "securitybaseapi", "winbase"] } [dependencies.clap] features = ["suggestions", "color", "wrap_help"] diff --git a/src/app.rs b/src/app.rs index ee3da9e3d..a76ab3e2e 100644 --- a/src/app.rs +++ b/src/app.rs @@ -234,13 +234,14 @@ pub fn build() -> App<'static, 'static> { "name", "inode", "links", + "git_status", ]) .help("Specify the blocks that will be displayed and in what order"), ) .arg( Arg::with_name("classic") - .long("classic") - .help("Enable classic mode (no colors or icons)"), + .long("classic") + .help("Enable classic mode (no colors or icons)"), ) .arg( Arg::with_name("no-symlink") @@ -272,6 +273,19 @@ pub fn build() -> App<'static, 'static> { .multiple(true) .help("When showing file information for a symbolic link, show information for the file the link references rather than for the link itself"), ) + .arg( + Arg::with_name("git") + .long("git") + .multiple(true) + .number_of_values(1) + .value_name("mode") + .default_value("flat") + .possible_values(&[ + "flat", + "recursive", + ]) + .help("Git status help ") // TODO + ) } fn validate_date_argument(arg: String) -> Result<(), String> { diff --git a/src/config_file.rs b/src/config_file.rs index c7c1b3d5c..ba9a9a624 100644 --- a/src/config_file.rs +++ b/src/config_file.rs @@ -12,6 +12,7 @@ use std::path::PathBuf; use serde::Deserialize; +use crate::flags::git_status::GitStatus; use std::fs; const CONF_DIR: &str = "lsd"; @@ -40,6 +41,7 @@ pub struct Config { pub no_symlink: Option, pub total_size: Option, pub symlink_arrow: Option, + pub git_status: Option, } #[derive(Eq, PartialEq, Debug, Deserialize)] @@ -88,6 +90,7 @@ impl Config { no_symlink: None, total_size: None, symlink_arrow: None, + git_status: None, } } @@ -170,7 +173,7 @@ classic: false # == Blocks == # This specifies the columns and their order when using the long and the tree # layout. -# Possible values: permission, user, group, size, size_value, date, name, inode +# Possible values: permission, user, group, size, size_value, date, name, inode, git_status blocks: - permission - user @@ -336,6 +339,7 @@ mod tests { no_symlink: Some(false), total_size: Some(false), symlink_arrow: Some("⇒".into()), + git_status: None, }, c ); diff --git a/src/core.rs b/src/core.rs index 07ce931e8..d303db5e1 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,8 +1,9 @@ use crate::color::{self, Colors}; use crate::display; use crate::flags::{ColorOption, Display, Flags, IconOption, IconTheme, Layout, SortOrder}; +use crate::git::GitCache; use crate::icon::{self, Icons}; -use crate::meta::Meta; +use crate::meta::{GitStatus, Meta}; use crate::{print_error, print_output, sort}; use std::path::PathBuf; @@ -96,12 +97,19 @@ impl Core { } }; + // Experimental + let cache = GitCache::new(&path).unwrap(); + let recurse = self.flags.layout == Layout::Tree || self.flags.display != Display::DirectoryOnly; if recurse { - match meta.recurse_into(depth, &self.flags) { + match meta.recurse_into(depth, &self.flags, &cache) { Ok(content) => { meta.content = content; + println!("Git Recurse"); + meta.git_status = Some(GitStatus { + foo: format!("DEBUG2 {:?}", meta.path), + }); meta_list.push(meta); } Err(err) => { @@ -110,6 +118,11 @@ impl Core { } }; } else { + panic!("USELESS?"); + println!("Git Flat"); + meta.git_status = Some(GitStatus { + foo: format!("DEBUG3 {:?}", meta.path), + }); meta_list.push(meta); }; } diff --git a/src/display.rs b/src/display.rs index f1d0084fd..069b468ef 100644 --- a/src/display.rs +++ b/src/display.rs @@ -67,7 +67,7 @@ fn inner_display_grid( for meta in metas { // Maybe skip showing the directory meta now; show its contents later. if skip_dirs - && (matches!(meta.file_type, FileType::Directory{..}) + && (matches!(meta.file_type, FileType::Directory { .. }) || (matches!(meta.file_type, FileType::SymLink { is_dir: true }) && flags.layout != Layout::OneLine)) { @@ -294,6 +294,14 @@ fn get_output<'a>( strings.push(ColoredString::from(s)); } + Block::GitStatus => { + if let Some(s) = &meta.git_status { + // FIXME + strings.push(ColoredString::from(s.foo.clone())) + } else { + strings.push(ColoredString::from(String::from("nop"))) + } + } }; } diff --git a/src/flags.rs b/src/flags.rs index 676a84fae..ef4dc0b4b 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -3,6 +3,7 @@ pub mod color; pub mod date; pub mod dereference; pub mod display; +pub mod git_status; pub mod icons; pub mod ignore_globs; pub mod indicators; @@ -21,6 +22,7 @@ pub use color::ColorOption; pub use date::DateFlag; pub use dereference::Dereference; pub use display::Display; +pub use git_status::GitStatus; pub use icons::IconOption; pub use icons::IconSeparator; pub use icons::IconTheme; @@ -63,6 +65,7 @@ pub struct Flags { pub sorting: Sorting, pub total_size: TotalSize, pub symlink_arrow: SymlinkArrow, + pub git_status: GitStatus, } impl Flags { @@ -89,6 +92,7 @@ impl Flags { sorting: Sorting::configure_from(matches, config), total_size: TotalSize::configure_from(matches, config), symlink_arrow: SymlinkArrow::configure_from(matches, config), + git_status: GitStatus::configure_from(matches, config), }) } } @@ -112,14 +116,17 @@ where /// out warnings. fn configure_from(matches: &ArgMatches, config: &Config) -> T { if let Some(value) = Self::from_arg_matches(matches) { + // println!("from arg {}", std::any::type_name::()); return value; } if let Some(value) = Self::from_environment() { + // println!("from env {}", std::any::type_name::()); return value; } if let Some(value) = Self::from_config(config) { + // println!("from config {}", std::any::type_name::()); return value; } diff --git a/src/flags/blocks.rs b/src/flags/blocks.rs index 0732dc32c..c450f2659 100644 --- a/src/flags/blocks.rs +++ b/src/flags/blocks.rs @@ -51,6 +51,13 @@ impl Blocks { } } + if matches.is_present("git") { + // println!("ADD GIT BLOCK"); + if let Ok(blocks) = result.as_mut() { + blocks.optional_prepend_git_status(); + } + } + result } @@ -144,6 +151,24 @@ impl Blocks { self.prepend_inode() } } + + /// Checks whether `self` already contains a [Block] of variant [INode](Block::INode). + fn contains_git_status(&self) -> bool { + self.0.contains(&Block::GitStatus) + } + + /// Prepends a [Block] of variant [INode](Block::INode) to `self`. + fn prepend_git_status(&mut self) { + self.0.insert(0, Block::GitStatus); + } + + /// Prepends a [Block] of variant [INode](Block::INode), if `self` does not already contain a + /// Block of that variant. + fn optional_prepend_git_status(&mut self) { + if !self.contains_git_status() { + self.prepend_git_status() + } + } } /// The default value for `Blocks` contains a [Vec] of [Name](Block::Name). @@ -165,6 +190,7 @@ pub enum Block { Name, INode, Links, + GitStatus, } impl TryFrom<&str> for Block { @@ -181,6 +207,7 @@ impl TryFrom<&str> for Block { "name" => Ok(Self::Name), "inode" => Ok(Self::INode), "links" => Ok(Self::Links), + "git_status" => Ok(Self::GitStatus), _ => Err(format!("Not a valid block name: {}", &string)), } } diff --git a/src/flags/git_status.rs b/src/flags/git_status.rs new file mode 100644 index 000000000..a74cadb3b --- /dev/null +++ b/src/flags/git_status.rs @@ -0,0 +1,55 @@ +//! This module defines the [GitStatus] flag. To set it up from [ArgMatches], a [Config] and its +//! [Default] value, use the [configure_from](Configurable::configure_from) method. + +use super::Configurable; + +use crate::config_file::Config; + +use clap::ArgMatches; +use serde::Deserialize; + +/// The flag showing how git status is computed +#[derive(Clone, Debug, Copy, PartialEq, Eq, Deserialize)] +pub enum GitStatus { + Flat, + Recursive, +} + +impl Configurable for GitStatus { + /// Get a potential `GitStatus` variant from [ArgMatches]. + /// + /// If any of the "flat" or "recursive" arguments is passed, this returns the + /// corresponding `GitStatus` variant in a [Some]. If neither of them is passed, this returns + /// [None]. + fn from_arg_matches(matches: &ArgMatches) -> Option { + // println!("{:?}", matches); + if matches.is_present("git") { + // println!("DEBUG1"); + Some(Self::Flat) + } else if matches.is_present("recursive") { + // println!("DEBUG2"); + Some(Self::Recursive) + } else { + // println!("DEBUG3"); + None + } + } + + /// Get a potential `GitStatus` variant from a [Config]. + /// + /// If the `Config::git_status` has value and is one of + /// "flat" or "recursive", this returns the corresponding `GitStatus` variant in a [Some]. + /// Otherwise, this returns [None]. + fn from_config(config: &Config) -> Option { + config.git_status + } +} + +/// The default value for `Display` is [Display::VisibleOnly]. +impl Default for GitStatus { + fn default() -> Self { + GitStatus::Flat + } +} + +// FIXME TODO tests diff --git a/src/git.rs b/src/git.rs new file mode 100644 index 000000000..67493e8d5 --- /dev/null +++ b/src/git.rs @@ -0,0 +1,125 @@ +use log::{debug, error, info, trace, warn}; +use std::fs; +use std::path::{Path, PathBuf}; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum GitStatus { + /// No changes + Unmodified, + /// Entry does not exist in old version + New, + /// Entry does not exist in new version + Deleted, + /// Entry content changed between old and new + Modified, + /// Entry was renamed between old and new + Renamed, + /// Entry is ignored item in workdir + Ignored, + /// Type of entry changed between old and new + Typechange, + /// Entry in the index is conflicted + Conflicted, +} + +impl GitStatus { + fn worktree_new(status: git2::Status) -> GitStatus { + match status { + s if s.contains(git2::Status::WT_NEW) => GitStatus::New, + s if s.contains(git2::Status::WT_DELETED) => GitStatus::Deleted, + s if s.contains(git2::Status::WT_MODIFIED) => GitStatus::Modified, + s if s.contains(git2::Status::WT_RENAMED) => GitStatus::Renamed, + s if s.contains(git2::Status::IGNORED) => GitStatus::Ignored, + s if s.contains(git2::Status::WT_TYPECHANGE) => GitStatus::Typechange, + s if s.contains(git2::Status::CONFLICTED) => GitStatus::Conflicted, + _ => GitStatus::Unmodified, + } + } + fn index_new(status: git2::Status) -> GitStatus { + match status { + s if s.contains(git2::Status::INDEX_NEW) => GitStatus::New, + s if s.contains(git2::Status::INDEX_DELETED) => GitStatus::Deleted, + s if s.contains(git2::Status::INDEX_MODIFIED) => GitStatus::Modified, + s if s.contains(git2::Status::INDEX_RENAMED) => GitStatus::Renamed, + s if s.contains(git2::Status::INDEX_TYPECHANGE) => GitStatus::Typechange, + _ => GitStatus::Unmodified, + } + } +} + +impl Default for GitStatus { + fn default() -> Self { + GitStatus::Unmodified + } +} + +pub struct GitCache { + statuses: Vec<(PathBuf, git2::Status)>, + pub currentdir: PathBuf, +} + +impl GitCache { + pub fn new(path: &PathBuf) -> Result { + let cachedir = fs::canonicalize(&path).unwrap(); + info!("GIT PROCESSING {:?}", cachedir); + + let repo = match git2::Repository::discover(&path) { + Ok(r) => r, + Err(e) => { + error!("Error discovering Git repositories: {:?}", e); + return Err(path); + } + }; + + if let Some(workdir) = repo.workdir() { + let mut statuses = Vec::new(); + info!("Getting Git statuses for repo with workdir {:?}", workdir); + match repo.statuses(None) { + Ok(status_list) => { + for status_entry in status_list.iter() { + let path = workdir.join(Path::new(status_entry.path().unwrap())); + let elem = (path, status_entry.status()); + info!("{:?}", elem); + statuses.push(elem); + } + } + Err(e) => { + error!("Error looking up Git statuses: {:?}", e) + } + } + // info!("Cache: {:?}", statuses); + info!("GitCache path: {:?}", cachedir); + + return Ok(GitCache { + statuses, + currentdir: cachedir, + }); // FIXME unwrap + } + return Err(path); + } + + pub fn get(&self, filepath: &PathBuf) -> (GitStatus, GitStatus) { + // let filepath = filepath.strip_prefix("./").unwrap(); + // + info!("Look for {:?}", filepath); + // let repo = match git2::Repository::discover(&self.currentdir) { + // Ok(r) => r, + // Err(e) => { + // panic!("Error discovering Git repositories: {:?}", e); + // } + // }; + // match repo.status_file(filepath) { + // Ok(s) => Some((GitStatus::worktree_new(s), GitStatus::index_new(s))), + // Err(e) => { + // warn!("Not git found {:?} {:?}", filepath, e); + // None + // } + // } + + self.statuses + .iter() + .find(|&x| filepath == &x.0) + .map(|e| (GitStatus::worktree_new(e.1), GitStatus::index_new(e.1))) + .unwrap_or((GitStatus::default(), GitStatus::default())) + } +} diff --git a/src/logger.rs b/src/logger.rs new file mode 100644 index 000000000..0412adf19 --- /dev/null +++ b/src/logger.rs @@ -0,0 +1,29 @@ +use log::{LevelFilter, SetLoggerError}; + +#[derive(Debug)] +struct Logger; + +use log::{Level, Metadata, Record}; + +struct SimpleLogger; + +impl log::Log for SimpleLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + true // metadata.level() <= Level::Info + } + + fn log(&self, record: &Record) { + if self.enabled(record.metadata()) { + println!("{} - {}", record.level(), record.args()); + } + } + + fn flush(&self) {} +} + +static LOGGER: &SimpleLogger = &SimpleLogger; + +pub fn init() -> Result<(), SetLoggerError> { + println!("Logger started"); + log::set_logger(LOGGER).map(|()| log::set_max_level(LevelFilter::Info)) +} diff --git a/src/main.rs b/src/main.rs index e9db8d98a..855c22da5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,7 +34,9 @@ mod config_file; mod core; mod display; mod flags; +mod git; mod icon; +mod logger; mod meta; mod sort; @@ -90,6 +92,7 @@ macro_rules! print_output { } fn main() { + logger::init(); let matches = app::build().get_matches_from(wild::args_os()); // input translate glob FILE without single quote into real names diff --git a/src/meta/filetype.rs b/src/meta/filetype.rs index e7c275f8c..0787d14dd 100644 --- a/src/meta/filetype.rs +++ b/src/meta/filetype.rs @@ -81,7 +81,10 @@ impl FileType { } pub fn is_dirlike(self) -> bool { - matches!(self, FileType::Directory { .. } | FileType::SymLink { is_dir: true }) + matches!( + self, + FileType::Directory { .. } | FileType::SymLink { is_dir: true } + ) } } diff --git a/src/meta/git_status.rs b/src/meta/git_status.rs new file mode 100644 index 000000000..e88813aff --- /dev/null +++ b/src/meta/git_status.rs @@ -0,0 +1,4 @@ +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct GitStatus { + pub foo: String, +} diff --git a/src/meta/mod.rs b/src/meta/mod.rs index 83d311230..4fb1c5a80 100644 --- a/src/meta/mod.rs +++ b/src/meta/mod.rs @@ -1,5 +1,8 @@ +use log::{debug, error, info, trace, warn}; + mod date; mod filetype; +mod git_status; mod indicator; mod inode; mod links; @@ -14,6 +17,7 @@ mod windows_utils; pub use self::date::Date; pub use self::filetype::FileType; +pub use self::git_status::GitStatus; pub use self::indicator::Indicator; pub use self::inode::INode; pub use self::links::Links; @@ -27,6 +31,8 @@ pub use crate::icon::Icons; use crate::flags::{Display, Flags, Layout}; use crate::print_error; +use crate::git::GitCache; +use std::fs; use std::fs::read_link; use std::io::{Error, ErrorKind}; use std::path::{Component, Path, PathBuf}; @@ -45,6 +51,7 @@ pub struct Meta { pub inode: INode, pub links: Links, pub content: Option>, + pub git_status: Option, } impl Meta { @@ -52,6 +59,7 @@ impl Meta { &self, depth: usize, flags: &Flags, + cache: &GitCache, ) -> Result>, std::io::Error> { if depth == 0 { return Ok(None); @@ -121,6 +129,11 @@ impl Meta { } }; + let st = cache.get(&fs::canonicalize(&entry_meta.path).unwrap()); + entry_meta.git_status = Some(GitStatus { + foo: format!("{:?}", st), + }); + // skip files for --tree -d if flags.layout == Layout::Tree { if let Display::DirectoryOnly = flags.display { @@ -130,7 +143,7 @@ impl Meta { } } - match entry_meta.recurse_into(depth - 1, &flags) { + match entry_meta.recurse_into(depth - 1, &flags, &cache) { Ok(content) => entry_meta.content = content, Err(err) => { print_error!("{}: {}.", path.display(), err); @@ -238,6 +251,7 @@ impl Meta { name, file_type, content: None, + git_status: None, }) } }