gclone/src/lib.rs

150 lines
4.1 KiB
Rust

//! This crate contains the gclone and pgd commands.
//!
//! The `gclone` command automatically clones a git repository and puts it in the right place.
//! The `pgd` command manages a cache for efficiently being able to print a directory corresponding
//! to a repo or an owner. You can then add the following to automatically `cd` to a directory:
//! ``` zsh
//! cdg() {
//! local newdir
//! newdir=$(pgd $1) && cd $newdir
//! }
//! ```
#![warn(missing_docs)]
use std::io;
use std::{env, error, fmt, num, result};
use colored::*;
mod cache;
pub use cache::Cache;
pub mod git;
macro_rules! impl_from_error {
($type: ty, $variant: path, $from: ty) => {
impl From<$from> for $type {
fn from(e: $from) -> $type {
$variant(e)
}
}
};
}
#[derive(Debug)]
/// The error type of gclone.
pub enum Error {
/// Couldn't read the GCLONE_PATH env.
NoGclonePath(env::VarError),
/// An error occured while manipulating files.
IoError(io::Error),
/// Couldn't parse git url.
GitUrlParseError,
/// Couldn't clone the respository.
GitCloneError(Option<io::Error>),
/// The specified directory already exists.
PathAlreadyExists,
/// The binaries of this crate require exactly one argument.
WrongArgument,
/// An error while parsing an int.
ParseIntError(num::ParseIntError),
/// A value is outside a range.
OutsideRange,
/// No such directory was found.
NoSuchDirectory,
}
impl_from_error!(Error, Error::NoGclonePath, env::VarError);
impl_from_error!(Error, Error::IoError, io::Error);
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()
),
}
}
}
impl error::Error for Error {}
/// The result type of gclone.
pub type Result<T> = result::Result<T, Error>;
/// Gets the single argument of the program.
pub fn first_arg() -> Result<String> {
env::args().nth(1).ok_or(Error::WrongArgument)
}