Skip to content

Commit

Permalink
minor refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
EricDriussi committed Jan 15, 2024
1 parent bf5a730 commit a5c285d
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 64 deletions.
2 changes: 1 addition & 1 deletion src/authors/author.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub struct Author {
}

impl Author {
pub fn new(alias: &str, name: &str, email: &str) -> Self {
pub fn from(alias: &str, name: &str, email: &str) -> Self {
Self {
alias: String::from(alias),
name: String::from(name),
Expand Down
9 changes: 6 additions & 3 deletions src/authors/author_err.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::error::Error;
use std::{
error::Error,
fmt::{Display, Formatter, Result},
};

#[derive(Debug)]
pub struct AuthorError(String);

impl std::fmt::Display for AuthorError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
impl Display for AuthorError {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "AUTHORS: {}", self.0)
}
}
Expand Down
75 changes: 47 additions & 28 deletions src/authors/fs_repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct FSRepo {
}

impl FSRepo {
pub fn new_default() -> Result<Self, Box<dyn Error>> {
pub fn from_cwd_with_home_fallback() -> Result<Self, Box<dyn Error>> {
let mut local_file = env::current_dir().unwrap();
local_file.push(conf::authors_file_name());
if local_file.is_file() {
Expand Down Expand Up @@ -51,7 +51,7 @@ impl FSRepo {
}
}

fn filter_by_alias(line: &str, aliases: &[String]) -> bool {
fn line_contains_any_alias(line: &str, aliases: &[String]) -> bool {
aliases.iter().any(|given_alias| {
let found_alias: &str = line.split(',').collect::<Vec<&str>>()[0];
given_alias.eq_ignore_ascii_case(found_alias.trim())
Expand All @@ -63,41 +63,53 @@ impl FSRepo {
if fields.len() != 3 {
return None;
}
Some(Author::new(fields[0], fields[1], fields[2]))
Some(Author::from(fields[0], fields[1], fields[2]))
}

fn extract_mathcing_authors_from_lines(alias: String, valid_lines: &[String], matching_authors: &mut Vec<Author>) {
for line in valid_lines {
if Self::filter_by_alias(line, &[alias.clone()]) {
if let Some(author) = Self::parse_author(line) {
matching_authors.push(author);
}
}
fn extract_author(line: &str, aliases: &[String]) -> Option<Author> {
if Self::line_contains_any_alias(line, aliases) {
Self::parse_author(line)
} else {
None
}
}

fn extract_mathcing_authors_from_lines(alias: String, valid_lines: &[String]) -> Vec<Author> {
let mut matching_authors: Vec<Author> = Vec::new();
valid_lines.iter().for_each(|line| {
if let Some(author) = Self::extract_author(line, &[alias.clone()]) {
matching_authors.push(author);
}
});
matching_authors
}
}

impl AuthorsRepo for FSRepo {
fn find(&self, aliases: Vec<String>) -> Vec<Author> {
let mut matching_authors: Vec<Author> = Vec::new();

if let Some(lines) = self.read_lines() {
let valid_lines = lines.map_while(Result::ok).collect::<Vec<_>>();
for alias in aliases {
Self::extract_mathcing_authors_from_lines(alias, &valid_lines, &mut matching_authors);
match self.read_lines() {
None => Vec::new(),
Some(lines) => {
let valid_lines = lines.map_while(Result::ok).collect::<Vec<_>>();
let mut matching_authors: Vec<Author> = Vec::new();
aliases.iter().for_each(|alias| {
matching_authors.append(&mut Self::extract_mathcing_authors_from_lines(
alias.clone(),
&valid_lines,
));
});
matching_authors
}
};

matching_authors
}
}

fn all(&self) -> Vec<Author> {
match self.read_lines() {
None => Vec::new(),
Some(lines) => lines
.map_while(Result::ok)
.filter_map(|line| Self::parse_author(line.as_str()))
.collect(),
None => Vec::new(),
}
}
}
Expand All @@ -116,32 +128,39 @@ mod test {

#[test]
fn should_filter_by_alias() {
let matching_alias = FSRepo::filter_by_alias("a,John,Doe", &[String::from("a")]);
let matching_alias = FSRepo::line_contains_any_alias("a,John,Doe", &[String::from("a")]);
assert!(matching_alias);

let no_matching_alias = !FSRepo::filter_by_alias("b,Jane,Dane", &[String::from("a")]);
let no_matching_alias = !FSRepo::line_contains_any_alias("b,Jane,Dane", &[String::from("a")]);
assert!(no_matching_alias);
}

#[test]
fn should_parse_author() {
let valid_result = FSRepo::parse_author("j,John,email");
assert!(valid_result.is_some_and(|a| a == Author::new("j", "John", "email")));
assert!(valid_result.is_some_and(|a| a == Author::from("j", "John", "email")));

let invalid_result = FSRepo::parse_author("hi,invalid_line");
assert!(invalid_result.is_none());
}

#[test]
fn should_extract_author() {
let valid_result = FSRepo::extract_author("j,John,email", &[String::from("j")]);
assert!(valid_result.is_some_and(|a| a == Author::from("j", "John", "email")));

let invalid_result = FSRepo::extract_author("a,alice,gmail", &[String::from("j")]);
assert!(invalid_result.is_none());
}

#[test]
fn should_extract_mathcing_authors_from_lines() {
let matching_authors: &mut Vec<Author> = &mut Vec::new();
FSRepo::extract_mathcing_authors_from_lines(
let matching_authors: Vec<Author> = FSRepo::extract_mathcing_authors_from_lines(
"j".to_string(),
&["j,John,email".to_string(), "a,alice,gmail".to_string()],
matching_authors,
);

assert!(matching_authors.contains(&Author::new("j", "John", "email")));
assert!(!matching_authors.contains(&Author::new("a", "alice", "gmail")));
assert!(matching_authors.contains(&Author::from("j", "John", "email")));
assert!(!matching_authors.contains(&Author::from("a", "alice", "gmail")));
}
}
6 changes: 3 additions & 3 deletions src/authors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ mod author_err;
pub mod fs_repo;
pub mod service;

pub fn fs_setup_from_file(authors_file: String) -> Result<AuthorsService<FSRepo>, Box<dyn Error>> {
pub fn from_file(authors_file: String) -> Result<AuthorsService<FSRepo>, Box<dyn Error>> {
match FSRepo::from(authors_file) {
Ok(repo) => Ok(AuthorsService::new(repo)),
Err(e) => Err(AuthorError::with(format!("Couldn't load file: {}", e))),
}
}

pub fn new_fs_default_setup() -> Result<AuthorsService<FSRepo>, Box<dyn Error>> {
match FSRepo::new_default() {
pub fn default() -> Result<AuthorsService<FSRepo>, Box<dyn Error>> {
match FSRepo::from_cwd_with_home_fallback() {
Ok(repo) => Ok(AuthorsService::new(repo)),
Err(e) => Err(AuthorError::with(format!("Couldn't load file: {}", e))),
}
Expand Down
14 changes: 7 additions & 7 deletions src/authors/test/author.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ fn setup_author() -> Author {
let alias = "a";
let name = "alice";
let email = "[email protected]";
Author::new(alias, name, email)
Author::from(alias, name, email)
}

#[test]
Expand All @@ -28,17 +28,17 @@ fn should_provide_a_name_getter() {

#[test]
fn should_be_equal_to_another_author_with_equal_data() {
let author = Author::new("a", "alice", "[email protected]");
let same_author = Author::new("a", "alice", "[email protected]");
let author = Author::from("a", "alice", "[email protected]");
let same_author = Author::from("a", "alice", "[email protected]");
assert_eq!(author, same_author)
}

#[parameterized(different_author = {
Author::new("b", "alice", "[email protected]"),
Author::new("a", "not_alice", "[email protected]"),
Author::new("a", "alice", "[email protected]")
Author::from("b", "alice", "[email protected]"),
Author::from("a", "not_alice", "[email protected]"),
Author::from("a", "alice", "[email protected]")
})]
fn should_not_be_equal_to_another_author_with_different_data(different_author: Author) {
let author = Author::new("a", "alice", "[email protected]");
let author = Author::from("a", "alice", "[email protected]");
assert_ne!(author, different_author)
}
20 changes: 10 additions & 10 deletions src/authors/test/fs_repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn should_connect_to_an_authors_file_in_cwd_if_available() {
fs::File::create(cwd_authors_file_path.clone()).unwrap();
let _after = AfterAssert::cleanup(&[&cwd_authors_file_path]);

assert!(FSRepo::new_default().is_ok());
assert!(FSRepo::from_cwd_with_home_fallback().is_ok());
}

#[test]
Expand All @@ -26,13 +26,13 @@ fn should_connect_to_the_default_authors_file_if_no_file_is_available_in_cwd() {
fs::File::create(&default_authors_file_path).unwrap();
let _after = AfterAssert::cleanup(&[default_authors_file_path.as_str()]);

assert!(FSRepo::new_default().is_ok());
assert!(FSRepo::from_cwd_with_home_fallback().is_ok());
}

#[test]
#[serial]
fn should_error_when_neither_cwd_or_default_authors_file_are_available() {
assert!(FSRepo::new_default().is_err());
assert!(FSRepo::from_cwd_with_home_fallback().is_err());
}

#[test]
Expand All @@ -59,10 +59,10 @@ fn should_fetch_all_available_authors() {
assert_eq!(
actual_authors,
[
Author::new("a", "Name Surname", "[email protected]"),
Author::new("b", "username", "[email protected]"),
Author::new("b", "username2", "[email protected]"),
Author::new("ab", "Another Surname", "[email protected]"),
Author::from("a", "Name Surname", "[email protected]"),
Author::from("b", "username", "[email protected]"),
Author::from("b", "username2", "[email protected]"),
Author::from("ab", "Another Surname", "[email protected]"),
]
);
}
Expand All @@ -77,7 +77,7 @@ fn should_fetch_authors_based_on_alias() {

assert_eq!(
actual_author,
[Author::new(alias, "Name Surname", "[email protected]")]
[Author::from(alias, "Name Surname", "[email protected]")]
);
}

Expand All @@ -92,8 +92,8 @@ fn should_fetch_all_authors_for_a_given_alias() {
assert_eq!(
actual_authors,
[
Author::new(alias, "username", "[email protected]"),
Author::new(alias, "username2", "[email protected]"),
Author::from(alias, "username", "[email protected]"),
Author::from(alias, "username2", "[email protected]"),
]
);
}
Expand Down
16 changes: 8 additions & 8 deletions src/authors/test/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,26 @@ use crate::{
#[test]
#[serial]
fn authors_module_should_setup_repo_from_default_file_path_if_present() {
assert!(authors::new_fs_default_setup().is_err());
assert!(authors::default().is_err());

let default_authors_file_path = conf::authors_file_path();
fs::File::create(&default_authors_file_path).unwrap();
let _after = AfterAssert::cleanup(&[default_authors_file_path.as_str()]);

assert!(authors::new_fs_default_setup().is_ok());
assert!(authors::default().is_ok());
}

#[test]
fn authors_module_should_setup_repo_from_given_file_path_if_present() {
assert!(authors::fs_setup_from_file("/tmp/not_real".to_string()).is_err());
assert!(authors::from_file("/tmp/not_real".to_string()).is_err());

let result = authors::fs_setup_from_file(conf::dummy_data());
let result = authors::from_file(conf::dummy_data());

assert!(result.is_ok_and(|service| service.all_available()
== [
Author::new("a", "Name Surname", "[email protected]"),
Author::new("b", "username", "[email protected]"),
Author::new("b", "username2", "[email protected]"),
Author::new("ab", "Another Surname", "[email protected]"),
Author::from("a", "Name Surname", "[email protected]"),
Author::from("b", "username", "[email protected]"),
Author::from("b", "username2", "[email protected]"),
Author::from("ab", "Another Surname", "[email protected]"),
]));
}
2 changes: 1 addition & 1 deletion src/authors/test/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl MockRepo {
}

fn hardcoded_authors() -> Vec<Author> {
Vec::from([Author::new("a", "John", "Doe"), Author::new("b", "Jane", "Smith")])
Vec::from([Author::from("a", "John", "Doe"), Author::from("b", "Jane", "Smith")])
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/cli/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn should_parse_an_empty_list_of_aliases() {

#[test]
fn should_format_authors_for_prompt() {
let author = Author::new("alias", "name", "email");
let author = Author::from("alias", "name", "email");
let prompt = FancyCli::format_author(&author);
assert_eq!(strip_ansi::strip_ansi(prompt.as_str()), "⦔ alias -> name");
}
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ pub mod cli;

pub fn handle_authors(args: &Args, cli: &mut impl Cli) -> Result<Vec<String>, Box<dyn Error>> {
let authors_service = match &args.file {
Some(file) => authors::fs_setup_from_file(file.to_string())?,
None => authors::new_fs_default_setup()?,
Some(file) => authors::from_file(file.to_string())?,
None => authors::default()?,
};

if args.all {
return match args.sort {
// TODO: get sorted from service
true => Ok(sort(authors_service.all_signatures())),
false => Ok(authors_service.all_signatures()),
};
Expand Down Expand Up @@ -44,6 +45,7 @@ pub fn handle_commit_msg(args: &Args, cli: &mut impl Cli, prev: String) -> Resul
}
}

// TODO: Don't mutate
pub fn sort<String: Ord>(mut vector: Vec<String>) -> Vec<String> {
vector.sort();
vector
Expand Down

0 comments on commit a5c285d

Please sign in to comment.