summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md8
-rw-r--r--Cargo.lock40
-rw-r--r--src/driver.rs35
-rw-r--r--src/lib.rs44
-rw-r--r--src/main.rs6
-rw-r--r--src/util.rs67
6 files changed, 136 insertions, 64 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8d8e817..3d5090b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [Unreleased]
<!-- The latest version contains all changes. -->
+### Added
+
+- Include standard directory feature
+
+### Changed
+
+- Directory walking to skip hidden directories
+
### Removed
- File header comments
diff --git a/Cargo.lock b/Cargo.lock
index 623ea96..8826ed2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -72,9 +72,9 @@ dependencies = [
[[package]]
name = "bstr"
-version = "0.2.14"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf"
+checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
dependencies = [
"lazy_static",
"memchr",
@@ -99,12 +99,6 @@ dependencies = [
[[package]]
name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
-name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
@@ -137,7 +131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
dependencies = [
"autocfg",
- "cfg-if 1.0.0",
+ "cfg-if",
"lazy_static",
]
@@ -219,7 +213,7 @@ version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"libc",
"wasi",
]
@@ -277,9 +271,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "idna"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
+checksum = "de910d521f7cc3135c4de8db1cb910e0b5ed1dc6f57c381cd07e8e661ce10094"
dependencies = [
"matches",
"unicode-bidi",
@@ -315,9 +309,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.82"
+version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
+checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
[[package]]
name = "libgit2-sys"
@@ -335,9 +329,9 @@ dependencies = [
[[package]]
name = "libssh2-sys"
-version = "0.2.20"
+version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df40b13fe7ea1be9b9dffa365a51273816c345fc1811478b57ed7d964fbfc4ce"
+checksum = "e0186af0d8f171ae6b9c4c90ec51898bad5d08a2d5e470903a50d9ad8959cbee"
dependencies = [
"cc",
"libc",
@@ -361,11 +355,11 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
]
[[package]]
@@ -613,9 +607,9 @@ dependencies = [
[[package]]
name = "thread_local"
-version = "1.1.2"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915"
+checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
dependencies = [
"once_cell",
]
@@ -646,9 +640,9 @@ dependencies = [
[[package]]
name = "unicode-normalization"
-version = "0.1.16"
+version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606"
+checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
dependencies = [
"tinyvec",
]
diff --git a/src/driver.rs b/src/driver.rs
index 51cfbcc..f2d0869 100644
--- a/src/driver.rs
+++ b/src/driver.rs
@@ -1,13 +1,16 @@
-use crate::util;
-use eyre::Result;
-use log::debug;
use std::cmp::Ordering;
use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
+
+use eyre::Result;
+use log::debug;
+
+use crate::util;
#[derive(Debug)]
pub struct Config {
pub enable_unpushed_check: bool,
+ pub include_non_repos: bool,
pub no_color: bool,
pub recursive: bool,
pub skip_sort: bool,
@@ -51,27 +54,41 @@ impl Results {
fn execute_in_directory(&mut self, config: &Config, dir: &Path) -> Result<()> {
// FIXME: find ways to add concurrent programming (tokio, async, etc.) to this section.
let path_entries = fs::read_dir(dir)?;
- let mut repos = Vec::new();
+ let mut repos: Vec<PathBuf> = Vec::new();
+ let mut non_repos: Vec<PathBuf> = Vec::new();
for entry in path_entries {
let subpath = &entry?.path();
- if subpath.is_dir() {
+
+ // Ensure that the directory is not hidden.
+ if subpath.is_dir()
+ && !util::get_short_name_for_directory(subpath, dir).starts_with(".")
+ {
if git2::Repository::open(subpath).is_ok() {
repos.push(subpath.to_owned());
- } else if config.recursive {
- debug!("Recursive execution into directory: {:#?}", &subpath);
- self.execute_in_directory(&config, &subpath)?;
+ } else {
+ if config.include_non_repos {
+ non_repos.push(subpath.to_owned());
+ }
+ if config.recursive {
+ debug!("Recursive execution into directory: {:#?}", &subpath);
+ self.execute_in_directory(&config, &subpath)?;
+ }
}
}
}
debug!("Git repositories found: {:#?}", repos);
+ if config.include_non_repos {
+ debug!("Standard directories found: {:#?}", non_repos);
+ }
if !repos.is_empty() {
if !&config.skip_sort {
repos.sort();
}
if let Some(table_wrapper) = util::create_table_from_paths(
repos,
+ non_repos,
&dir,
&config.enable_unpushed_check,
&config.no_color,
diff --git a/src/lib.rs b/src/lib.rs
index 6f63849..649728f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,15 +3,17 @@
#[macro_use]
extern crate prettytable;
-mod driver;
-mod util;
+use std::path::Path;
use eyre::Result;
-use std::path::Path;
+
+mod driver;
+mod util;
/// This function is the primary, backend driver for `gfold`.
///
/// - `enable_unpushed_check`: enable checking for unpushed commits (experimental)
+/// - `include_non_repos`: include standard directories in the result
/// - `no_color`: disables color, bolding, etc.
/// - `path`: the target path to find and parse Git repositories
/// - `recursive`: recursively searches directories for Git repositories
@@ -21,12 +23,14 @@ use std::path::Path;
pub fn run(
path: &Path,
enable_unpushed_check: bool,
+ include_non_repos: bool,
no_color: bool,
recursive: bool,
skip_sort: bool,
) -> Result<()> {
let config = driver::Config {
enable_unpushed_check,
+ include_non_repos,
no_color,
recursive,
skip_sort,
@@ -44,27 +48,43 @@ mod tests {
#[test]
fn current_directory() {
let current_dir = env::current_dir().expect("failed to get CWD");
- assert_ne!(run(&current_dir, false, false, false, false).is_err(), true);
+ assert_ne!(
+ run(&current_dir, false, false, false, false, false).is_err(),
+ true
+ );
}
#[test]
fn parent_directory() {
let mut current_dir = env::current_dir().expect("failed to get CWD");
current_dir.pop();
- assert_ne!(run(&current_dir, false, false, false, false).is_err(), true);
+ assert_ne!(
+ run(&current_dir, false, false, false, false, false).is_err(),
+ true
+ );
}
#[test]
fn parent_directory_all_options() {
let mut current_dir = env::current_dir().expect("failed to get CWD");
current_dir.pop();
- for skip_sort in vec![true, false] {
- for recursive in vec![true, false] {
- for no_color in vec![true, false] {
- assert_ne!(
- run(&current_dir, false, no_color, recursive, skip_sort).is_err(),
- true
- );
+ for include_non_repos in vec![true, false] {
+ for no_color in vec![true, false] {
+ for recursive in vec![true, false] {
+ for skip_sort in vec![true, false] {
+ assert_ne!(
+ run(
+ &current_dir,
+ false,
+ include_non_repos,
+ no_color,
+ recursive,
+ skip_sort
+ )
+ .is_err(),
+ true
+ );
+ }
}
}
}
diff --git a/src/main.rs b/src/main.rs
index 4d223d6..c19e86b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
-use eyre::Result;
use std::env;
use std::path::PathBuf;
+
+use eyre::Result;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
@@ -20,6 +21,8 @@ struct Opt {
help = "Toggle to enable checking for unpushed commits (experimental)"
)]
enable_unpushed_check: bool,
+ #[structopt(short, long, help = "Include standard directories in the result")]
+ include_non_repos: bool,
#[structopt(long = "nc", help = "Disable color output")]
no_color: bool,
#[structopt(parse(from_os_str), help = "Target a different directory")]
@@ -47,6 +50,7 @@ fn main() -> Result<()> {
gfold::run(
&path,
opt.enable_unpushed_check,
+ opt.include_non_repos,
opt.no_color,
opt.recursive,
opt.skip_sort,
diff --git a/src/util.rs b/src/util.rs
index c887d64..7d05190 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,7 +1,9 @@
-use crate::driver;
-use log::debug;
use std::path::{Path, PathBuf};
+use log::{debug, warn};
+
+use crate::driver;
+
#[derive(Debug)]
enum Condition {
Bare,
@@ -13,6 +15,7 @@ enum Condition {
pub fn create_table_from_paths(
repos: Vec<PathBuf>,
+ non_repos: Vec<PathBuf>,
path: &Path,
enable_unpushed_check: &bool,
no_color: &bool,
@@ -52,13 +55,6 @@ pub fn create_table_from_paths(
let branch = head.shorthand().unwrap_or("none");
debug!("[+] branch: {:#?}", branch);
- let name = Path::new(&repo)
- .strip_prefix(path)
- .ok()?
- .to_str()
- .unwrap_or("none");
- debug!("[+] name: {:#?}", name);
-
// FIXME: test using the "is_bare()" method for a repository object.
let mut opts = git2::StatusOptions::new();
let condition = match repo_obj.statuses(Some(&mut opts)) {
@@ -79,33 +75,54 @@ pub fn create_table_from_paths(
Err(_) => Condition::Error,
};
+ // This match block's formatting is aimed at readability (frequent usage of "{}").
match condition {
Condition::Bare if *no_color => {
- table.add_row(row![Fl->name, Fl->"bare", Fl->branch, Fl->url])
+ table.add_row(row![Fl->get_short_name_for_directory(&repo, path), Fl->"bare", Fl->branch, Fl->url])
+ }
+ Condition::Bare => {
+ table.add_row(row![Flb->get_short_name_for_directory(&repo, path), Frl->"bare", Fl->branch, Fl->url])
}
- Condition::Bare => table.add_row(row![Flb->name, Frl->"bare", Fl->branch, Fl->url]),
Condition::Clean if *no_color => {
- table.add_row(row![Fl->name, Fl->"clean", Fl->branch, Fl->url])
+ table.add_row(row![Fl->get_short_name_for_directory(&repo, path), Fl->"clean", Fl->branch, Fl->url])
+ }
+ Condition::Clean => {
+ table.add_row(row![Flb->get_short_name_for_directory(&repo, path), Fgl->"clean", Fl->branch, Fl->url])
}
- Condition::Clean => table.add_row(row![Flb->name, Fgl->"clean", Fl->branch, Fl->url]),
Condition::Unclean if *no_color => {
- table.add_row(row![Fl->name, Fl->"unclean", Fl->branch, Fl->url])
+ table.add_row(row![Fl->get_short_name_for_directory(&repo, path), Fl->"unclean", Fl->branch, Fl->url])
}
Condition::Unclean => {
- table.add_row(row![Flb->name, Fyl->"unclean", Fl->branch, Fl->url])
+ table.add_row(row![Flb->get_short_name_for_directory(&repo, path), Fyl->"unclean", Fl->branch, Fl->url])
}
Condition::Unpushed if *no_color => {
- table.add_row(row![Fl->name, Fl->"unpushed", Fl->branch, Fl->url])
+ table.add_row(row![Fl->get_short_name_for_directory(&repo, path), Fl->"unpushed", Fl->branch, Fl->url])
}
Condition::Unpushed => {
- table.add_row(row![Flb->name, Fcl->"unpushed", Fl->branch, Fl->url])
+ table.add_row(row![Flb->get_short_name_for_directory(&repo, path), Fcl->"unpushed", Fl->branch, Fl->url])
+ }
+ _ if *no_color => {
+ table.add_row(row![Fl->get_short_name_for_directory(&repo, path), Fl->"error", Fl->branch, Fl->url])
+ }
+ _ => {
+ table.add_row(row![Flb->get_short_name_for_directory(&repo, path), Frl->"error", Fl->branch, Fl->url])
}
- _ if *no_color => table.add_row(row![Fl->name, Fl->"error", Fl->branch, Fl->url]),
- _ => table.add_row(row![Flb->name, Frl->"error", Fl->branch, Fl->url]),
};
debug!("[+] condition: {:#?}", condition);
}
+ for non_repo in non_repos {
+ if *no_color {
+ table.add_row(
+ row![Fl->get_short_name_for_directory(&non_repo, path), Fl->"dir", Fl->"-", Fl->"-"],
+ );
+ } else {
+ table.add_row(
+ row![Flb->get_short_name_for_directory(&non_repo, path), Fcl->"dir", Fl->"-", Fl->"-"],
+ );
+ }
+ }
+
debug!("Generated {:#?} rows for table object", table.len());
match table.is_empty() {
true => None,
@@ -116,6 +133,18 @@ pub fn create_table_from_paths(
}
}
+pub fn get_short_name_for_directory(child: &PathBuf, parent: &Path) -> String {
+ let temp_dir = child.clone();
+ let path = match Path::new(&temp_dir).strip_prefix(parent) {
+ Ok(o) => o,
+ Err(e) => {
+ warn!("Encountered error: {:#?}", e);
+ return "none".to_string();
+ }
+ };
+ path.to_str().unwrap_or("none").to_owned()
+}
+
// FIXME: this function may not currently work because "clean", non-main branches can be considered "unpushed".
fn is_unpushed(repo: &git2::Repository, head: &git2::Reference) -> bool {
let local = match head.peel_to_commit() {