//! 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::{env, fmt, num, error, result}; use std::io; 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), /// 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 = result::Result; /// Gets the single argument of the program. pub fn first_arg() -> Result { env::args().nth(1).ok_or(Error::WrongArgument) }