git_index

Generates arguments to pass to stagit-index in descending order by commit date.
git clone https://git.philomathiclife.com/repos/git_index
Log | Files | Refs | README

args.rs (2816B)


      1 use core::{
      2     error::Error,
      3     fmt::{self, Display, Formatter},
      4 };
      5 use std::{
      6     env::{self, Args},
      7     path::{Path, PathBuf},
      8 };
      9 /// Wrapper around an absolute [`PathBuf`] to a directory.
     10 #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
     11 pub(crate) struct AbsDirPath {
     12     /// The directory.
     13     path: PathBuf,
     14 }
     15 impl AbsDirPath {
     16     /// Returns an `AbsDirPath` iff `PathBuf::from(val).is_absolute()`.
     17     ///
     18     /// If `PathBuf::from(val).as_bytes().last().unwrap() != b'/'`, `val`
     19     /// will have `/` appended to it.
     20     #[expect(clippy::option_if_let_else, reason = "can't without moving val")]
     21     pub(crate) fn from_string(val: String) -> Option<Self> {
     22         match val.as_bytes().last() {
     23             Some(byt) => {
     24                 let last = *byt;
     25                 let mut path = PathBuf::from(val);
     26                 path.is_absolute().then(|| {
     27                     if last != b'/' {
     28                         path.as_mut_os_string().push("/");
     29                     }
     30                     Self { path }
     31                 })
     32             }
     33             None => None,
     34         }
     35     }
     36 }
     37 impl AsRef<Path> for AbsDirPath {
     38     fn as_ref(&self) -> &Path {
     39         self.path.as_path()
     40     }
     41 }
     42 /// Error returned when parsing arguments passed to the application.
     43 #[derive(Debug)]
     44 pub(crate) enum ArgsErr {
     45     /// Error when no arguments were passed to the application.
     46     NoArgs,
     47     /// Error when an option was passed that was not an absolute file path to a directory.
     48     InvalidDir,
     49     /// Error when more than one option is passed.
     50     MoreThanOneOption,
     51 }
     52 impl Display for ArgsErr {
     53     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
     54         match *self {
     55             Self::NoArgs => f.write_str("no arguments were passed, but the absolute path to the directory of git repos must be passed"),
     56             Self::InvalidDir => f.write_str("an absolute path to the directory of git repos was not passed"),
     57             Self::MoreThanOneOption => f.write_str("more than one argument was passed, but only the absolute path to the directory of git repos must be passed"),
     58         }
     59     }
     60 }
     61 impl Error for ArgsErr {}
     62 /// Returns `AbsDirPath` based on arguments passed to the application.
     63 pub(crate) fn from_env_args() -> Result<AbsDirPath, ArgsErr> {
     64     /// Attempts to parse the next `Arg` into an absolute path to a directory.
     65     fn get_path(args: &mut Args) -> Result<AbsDirPath, ArgsErr> {
     66         args.next()
     67             .ok_or(ArgsErr::NoArgs)
     68             .and_then(|path| AbsDirPath::from_string(path).ok_or(ArgsErr::InvalidDir))
     69     }
     70     let mut args = env::args();
     71     let Some(_) = args.next() else {
     72         return Err(ArgsErr::NoArgs);
     73     };
     74     get_path(&mut args).and_then(|path| {
     75         args.next()
     76             .map_or(Ok(path), |_| Err(ArgsErr::MoreThanOneOption))
     77     })
     78 }