This commit is contained in:
Thomas Forgione 2019-02-21 15:21:27 +01:00
parent a56db54b72
commit 101e6a14a6
No known key found for this signature in database
GPG Key ID: 203DAEA747F48F41
5 changed files with 111 additions and 97 deletions

View File

@ -1,13 +1,16 @@
//! This module contains the cache manager.
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, Write};
use std::num::Wrapping;
use std::path::PathBuf;
use std::fs::File;
use std::io::{stdin, stdout, Write, BufRead, BufReader};
use walkdir::WalkDir;
use colored::*;
use crate::{Error, Result};
use walkdir::WalkDir;
use crate::git::GCLONE_PATH;
use crate::{Error, Result};
/// Flushes the stdout.
fn flush_stdout() {
@ -22,20 +25,20 @@ fn flush_stdout() {
pub struct Cache(Vec<String>);
impl Cache {
/// Generates the cache by traversing the files in the git directory.
pub fn generate() -> Cache {
Cache(WalkDir::new(&*GCLONE_PATH)
.max_depth(3)
.into_iter()
.filter_map(|x| x.ok())
.map(|x| x.path().display().to_string())
.collect())
Cache(
WalkDir::new(&*GCLONE_PATH)
.max_depth(3)
.into_iter()
.filter_map(|x| x.ok())
.map(|x| x.path().display().to_string())
.collect(),
)
}
/// Reads the cache file.
pub fn read() -> Result<Cache> {
let mut path = PathBuf::from(&*GCLONE_PATH);
path.push(".cdgcache");
@ -89,21 +92,23 @@ impl Cache {
/// Searches a directory, if multiple where found, prompt user for answer.
pub fn find_interactive(&self, dirname: &str) -> Result<String> {
let matches = self.find(dirname);
match matches.len() {
0 => Err(Error::NoSuchDirectory),
1 => Ok(matches[0].clone()),
len => {
eprintln!("{}", "info: multiple entries found, please select one".bold());
eprintln!(
"{}",
"info: multiple entries found, please select one".bold()
);
for (i, j) in matches.iter().enumerate() {
eprintln!("{} {}",
eprintln!(
"{} {}",
&format!("[{}]", i + 1).bold().blue(),
&format!("{}", j).yellow());
&format!("{}", j).yellow()
);
}
eprint!("{}", "Enter your choice: ".bold());
@ -123,9 +128,8 @@ impl Cache {
}
Ok(matches[value].clone())
},
}
}
}
/// Appends a value to the cache.
@ -133,4 +137,3 @@ impl Cache {
self.0.push(value);
}
}

View File

@ -1,17 +1,14 @@
use std::process::exit;
use std::path::PathBuf;
use std::process::exit;
use colored::*;
use gclone::git::{clone, parse_url, GCLONE_PATH};
use gclone::{first_arg, Cache, Result};
use gclone::git::{GCLONE_PATH, parse_url, clone};
fn help() {
}
fn help() {}
fn main_result() -> Result<()> {
// Parse args
let url = first_arg()?;
@ -38,7 +35,6 @@ fn main_result() -> Result<()> {
cache.write()?;
Ok(())
}
fn main() {

View File

@ -3,7 +3,7 @@
use std::env;
use std::fs::{create_dir_all, remove_dir_all};
use std::path::Path;
use std::process::{Command, Stdio, exit};
use std::process::{exit, Command, Stdio};
use lazy_static::lazy_static;
@ -29,7 +29,7 @@ macro_rules! unwrap {
Some(e) => e,
None => return Err(Error::GitUrlParseError),
}
}
};
}
/// Transforms a git url to a (server, owner, repository) tuple.
@ -52,7 +52,7 @@ fn parse_http_url(input: &str) -> Result<(String, String, String)> {
let repo = String::from(split[split.len() - 1]);
let owner = String::from(split[split.len() - 2]);
let server = split[2 .. split.len() - 2].join("/");
let server = split[2..split.len() - 2].join("/");
Ok((server, owner, repo))
}
@ -75,20 +75,17 @@ fn parse_ssh_url(input: &str) -> Result<(String, String, String)> {
///
/// If an error happens, it deletes the directory created.
pub fn clone<P: AsRef<Path>>(url: &str, place: P) -> Result<()> {
match clone_dirty(url, &place) {
Ok(o) => Ok(o),
Err(e) => {
remove_dir_all(&place).ok();
Err(e)
},
}
}
}
/// Clones a git repository in the right place.
fn clone_dirty<P: AsRef<Path>>(url: &str, place: P) -> Result<()> {
let place = place.as_ref();
if place.exists() {
@ -104,8 +101,7 @@ fn clone_dirty<P: AsRef<Path>>(url: &str, place: P) -> Result<()> {
match command {
Err(e) => Err(Error::GitCloneError(Some(e))),
Ok(o) if ! o.success() => Err(Error::GitCloneError(None)),
Ok(o) if !o.success() => Err(Error::GitCloneError(None)),
Ok(_) => Ok(()),
}
}

View File

@ -12,8 +12,8 @@
#![warn(missing_docs)]
use std::{env, fmt, num, error, result};
use std::io;
use std::{env, error, fmt, num, result};
use colored::*;
@ -29,7 +29,7 @@ macro_rules! impl_from_error {
$variant(e)
}
}
}
};
}
#[derive(Debug)]
@ -70,51 +70,70 @@ impl_from_error!(Error, Error::ParseIntError, num::ParseIntError);
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::NoGclonePath(e) =>
write!(fmt, "{} {} {}",
"error:".bold().red(),
"couldn't read environment variable GCLONE_PATH".bold(),
e),
Error::IoError(e) =>
write!(fmt, "{} {} {}",
"error:".bold().red(),
"couldn't read or write cache:".bold(),
e),
Error::GitUrlParseError =>
write!(fmt, "{} {}",
"error:".bold().red(),
"couldn't guess server, owner and repo from url".bold()),
Error::GitCloneError(Some(e)) =>
write!(fmt, "{} {} {}",
"error:".bold().red(),
"couldn't clone git repository:".bold(),
e),
Error::GitCloneError(None) =>
write!(fmt, "{} {}",
"error:".bold().red(),
"couldn't clone git repository".bold()),
Error::PathAlreadyExists =>
write!(fmt, "{} {}",
"error:".bold().red(),
"the path corresponding to the repository already exists".bold()),
Error::WrongArgument =>
write!(fmt, "{} {}",
"error:".bold().red(),
"this program expects exactly one argument".bold()),
Error::ParseIntError(e) =>
write!(fmt, "{} {} {}",
"error:".bold().red(),
"couldn't parse integer:".bold(),
e),
Error::OutsideRange =>
write!(fmt, "{} {}",
"error:".bold().red(),
"integer is outside the range".bold()),
Error::NoSuchDirectory =>
write!(fmt, "{} {}",
"error:".bold().red(),
"no such directory was found".bold()),
Error::NoGclonePath(e) => write!(
fmt,
"{} {} {}",
"error:".bold().red(),
"couldn't read environment variable GCLONE_PATH".bold(),
e
),
Error::IoError(e) => write!(
fmt,
"{} {} {}",
"error:".bold().red(),
"couldn't read or write cache:".bold(),
e
),
Error::GitUrlParseError => write!(
fmt,
"{} {}",
"error:".bold().red(),
"couldn't guess server, owner and repo from url".bold()
),
Error::GitCloneError(Some(e)) => write!(
fmt,
"{} {} {}",
"error:".bold().red(),
"couldn't clone git repository:".bold(),
e
),
Error::GitCloneError(None) => write!(
fmt,
"{} {}",
"error:".bold().red(),
"couldn't clone git repository".bold()
),
Error::PathAlreadyExists => write!(
fmt,
"{} {}",
"error:".bold().red(),
"the path corresponding to the repository already exists".bold()
),
Error::WrongArgument => write!(
fmt,
"{} {}",
"error:".bold().red(),
"this program expects exactly one argument".bold()
),
Error::ParseIntError(e) => write!(
fmt,
"{} {} {}",
"error:".bold().red(),
"couldn't parse integer:".bold(),
e
),
Error::OutsideRange => write!(
fmt,
"{} {}",
"error:".bold().red(),
"integer is outside the range".bold()
),
Error::NoSuchDirectory => write!(
fmt,
"{} {}",
"error:".bold().red(),
"no such directory was found".bold()
),
}
}
}

View File

@ -1,5 +1,7 @@
use std::process::exit;
use colored::*;
use gclone::{first_arg, Cache, Error, Result};
fn main() {
@ -15,26 +17,26 @@ fn main_result() -> Result<()> {
}
fn main_with_cache(request: &str, regen: bool) -> Result<()> {
let (cache, just_generated) = match Cache::read() {
Ok(c) => (c, false),
Err(_) => {
let cache = Cache::generate();
cache.write()?;
(cache, true)
},
}
};
let only_match = match cache.find_interactive(&request) {
Err(Error::NoSuchDirectory) if regen && ! just_generated => {
eprintln!("{} {}",
"warning:".bold().yellow(),
"directory not found, regenerating cache...".bold());
let cache = Cache::generate();
cache.write()?;
return main_with_cache(request, false);
},
Err(Error::NoSuchDirectory) if regen && !just_generated => {
eprintln!(
"{} {}",
"warning:".bold().yellow(),
"directory not found, regenerating cache...".bold()
);
let cache = Cache::generate();
cache.write()?;
return main_with_cache(request, false);
}
Err(e) => return Err(e),
Ok(x) => x,
@ -43,6 +45,4 @@ fn main_with_cache(request: &str, regen: bool) -> Result<()> {
println!("{}", only_match);
Ok(())
}