Skip to content

Commit 17ea45d

Browse files
authored
Merge pull request #18 from xynxynxyn/master
Error types instead of process:exit() for main and get_color() moved to impl fn of Info
2 parents ba243b8 + 809d900 commit 17ea45d

File tree

1 file changed

+88
-71
lines changed

1 file changed

+88
-71
lines changed

Diff for: src/main.rs

+88-71
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
extern crate colored;
22
extern crate git2;
3-
extern crate tokei;
43
extern crate license;
4+
extern crate tokei;
55

6+
use colored::Color;
67
use colored::*;
7-
use git2::Error;
88
use git2::Repository;
9-
use std::fmt;
10-
use std::fs;
11-
use std::process::{Command, Stdio};
12-
use std::str::FromStr;
139
use license::License;
14-
use std::ffi::OsStr;
15-
use std::fmt::Write;
16-
use std::process::exit;
10+
use std::{
11+
convert::From,
12+
ffi::OsStr,
13+
fmt,
14+
fmt::Write,
15+
fs,
16+
process::{Command, Stdio},
17+
result,
18+
str::FromStr,
19+
};
20+
21+
type Result<T> = result::Result<T, Error>;
1722

1823
struct Info {
1924
project_name: String,
@@ -27,7 +32,7 @@ struct Info {
2732
impl fmt::Display for Info {
2833
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2934
let mut buffer = String::new();
30-
let color = get_color(&self.language);
35+
let color = self.color();
3136

3237
writeln!(
3338
buffer,
@@ -49,12 +54,7 @@ impl fmt::Display for Info {
4954
"Author: "
5055
};
5156

52-
writeln!(
53-
buffer,
54-
"{}{}",
55-
title.color(color).bold(),
56-
self.authors.first().unwrap()
57-
)?;
57+
writeln!(buffer, "{}{}", title.color(color).bold(), self.authors[0])?;
5858

5959
let title = " ".repeat(title.len());
6060

@@ -119,27 +119,6 @@ enum Language {
119119
TypeScript,
120120
}
121121

122-
fn get_color(l: &Language) -> &str {
123-
match l {
124-
Language::C => "cyan",
125-
Language::Clojure => "cyan",
126-
Language::Cpp => "yellow",
127-
Language::Csharp => "white",
128-
Language::Go => "white",
129-
Language::Haskell => "cyan",
130-
Language::Java => "green",
131-
Language::Lisp => "yellow",
132-
Language::Lua => "blue",
133-
Language::Python => "magenta",
134-
Language::R => "blue",
135-
Language::Ruby => "magenta",
136-
Language::Rust => "cyan",
137-
Language::Scala => "blue",
138-
Language::Shell => "green",
139-
Language::TypeScript => "cyan",
140-
}
141-
}
142-
143122
impl fmt::Display for Language {
144123
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145124
match *self {
@@ -163,42 +142,28 @@ impl fmt::Display for Language {
163142
}
164143
}
165144

166-
fn main() {
145+
fn main() -> Result<()> {
167146
let tokei_langs = project_languages();
168-
let language = match get_dominant_language(&tokei_langs) {
169-
Some(language) => language,
170-
None => {
171-
eprintln!("Error: Could not find any source code in this directory.");
172-
exit(1);
173-
}
174-
};
147+
let language = get_dominant_language(&tokei_langs).ok_or(Error::SourceCodeNotFound)?;
175148

176149
if !is_git_installed() {
177-
eprintln!("Error: Could not execute git for project information.");
178-
exit(1);
150+
return Err(Error::GitNotInstalled);
179151
}
180152

181153
let authors = get_authors(3);
182-
let config: Configuration = match get_configuration() {
183-
Ok(config) => config,
184-
Err(_) => {
185-
eprintln!("Error: Could not retrieve git configuration data");
186-
exit(1);
187-
}
188-
};
189-
190-
154+
let config = get_configuration()?;
191155

192156
let info = Info {
193157
project_name: config.repository_name,
194158
language,
195159
authors,
196160
repo: config.repository_url,
197161
number_of_lines: get_total_loc(&tokei_langs),
198-
license: project_license(),
162+
license: project_license()?,
199163
};
200164

201165
println!("{}", info);
166+
Ok(())
202167
}
203168

204169
fn project_languages() -> tokei::Languages {
@@ -208,25 +173,31 @@ fn project_languages() -> tokei::Languages {
208173
languages
209174
}
210175

211-
fn project_license() -> String {
212-
let output = fs::read_dir(".").unwrap()
213-
.filter_map(Result::ok)
176+
fn project_license() -> Result<String> {
177+
let output = fs::read_dir(".")
178+
.map_err(|_| Error::ReadDirectory)?
179+
.filter_map(result::Result::ok)
214180
.map(|entry| entry.path())
215-
.filter(|entry| entry.is_file()
216-
&& entry.file_name()
181+
.filter(
182+
|entry| {
183+
entry.is_file()
184+
&& entry
185+
.file_name()
217186
.map(OsStr::to_string_lossy)
218187
.unwrap_or("".into())
219-
.starts_with("LICENSE") // TODO: multiple prefixes, like COPYING?
188+
.starts_with("LICENSE")
189+
}, // TODO: multiple prefixes, like COPYING?
220190
)
221191
.map(|entry| license::Kind::from_str(&fs::read_to_string(entry).unwrap_or("".into())))
222-
.filter_map(Result::ok)
192+
.filter_map(result::Result::ok)
223193
.map(|license| license.name().to_string())
224-
.collect::<Vec<_>>().join(", ");
194+
.collect::<Vec<_>>()
195+
.join(", ");
225196

226197
if output == "" {
227-
"Unknown".into()
198+
Ok("Unknown".into())
228199
} else {
229-
output
200+
Ok(output)
230201
}
231202
}
232203

@@ -244,9 +215,9 @@ struct Configuration {
244215
pub repository_url: String,
245216
}
246217

247-
fn get_configuration() -> Result<Configuration, Error> {
248-
let repo = Repository::open("./")?;
249-
let config = repo.config()?;
218+
fn get_configuration() -> Result<Configuration> {
219+
let repo = Repository::open("./").map_err(|_| Error::GitNotInstalled)?;
220+
let config = repo.config().map_err(|_| Error::NoGitData)?;
250221
let mut remote_url = String::new();
251222
let mut repository_name = String::new();
252223
let mut remote_upstream: Option<String> = None;
@@ -303,7 +274,8 @@ fn get_authors(n: usize) -> Vec<String> {
303274

304275
// sort authors by commit count where the one with most commit count is first
305276
let mut authors: Vec<(String, usize)> = authors.into_iter().collect();
306-
authors.sort_by(|(_, count1), (_, count2)| count2.cmp(count1));
277+
authors.sort_by_key(|(_, c)| *c);
278+
authors.reverse();
307279

308280
// truncate the vector so we only get the count of authors we specified as 'n'
309281
authors.truncate(n);
@@ -404,4 +376,49 @@ impl Info {
404376
// _ => include_str!("../resources/unknown.ascii"),
405377
}
406378
}
379+
380+
fn color(&self) -> Color {
381+
match self.language {
382+
Language::C => Color::Cyan,
383+
Language::Clojure => Color::Cyan,
384+
Language::Cpp => Color::Yellow,
385+
Language::Csharp => Color::White,
386+
Language::Go => Color::White,
387+
Language::Haskell => Color::Cyan,
388+
Language::Java => Color::Green,
389+
Language::Lisp => Color::Yellow,
390+
Language::Lua => Color::Blue,
391+
Language::Python => Color::Magenta,
392+
Language::R => Color::Blue,
393+
Language::Ruby => Color::Magenta,
394+
Language::Rust => Color::Cyan,
395+
Language::Scala => Color::Blue,
396+
Language::Shell => Color::Green,
397+
Language::TypeScript => Color::Cyan,
398+
}
399+
}
400+
}
401+
402+
/// Custom error type
403+
enum Error {
404+
/// Sourcecode could be located
405+
SourceCodeNotFound,
406+
/// Git is not installed or did not function properly
407+
GitNotInstalled,
408+
/// Did not find any git data in the directory
409+
NoGitData,
410+
/// An IO error occoured while reading ./
411+
ReadDirectory,
412+
}
413+
414+
impl fmt::Debug for Error {
415+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
416+
let content = match self {
417+
Error::SourceCodeNotFound => "Could not find any source code in this directory",
418+
Error::GitNotInstalled => "Git failed to execute",
419+
Error::NoGitData => "Could not retrieve git configuration data",
420+
Error::ReadDirectory => "Could read directory ./",
421+
};
422+
write!(f, "{}", content)
423+
}
407424
}

0 commit comments

Comments
 (0)