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

commit 3fcbebcff12a01e87595b233252bfae039b99723
parent b389ced12ab816f47f019e6cb3d4e21ba9c05eac
Author: Zack Newman <zack@philomathiclife.com>
Date:   Fri,  6 Sep 2024 18:38:22 -0600

update deps. lint reasons

Diffstat:
MCargo.toml | 15++++++---------
MREADME.md | 28+++++++++++++++++++++-------
Msrc/args.rs | 15++++-----------
Msrc/main.rs | 67++++++++++++++++++++++++++++++++++---------------------------------
4 files changed, 65 insertions(+), 60 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -8,20 +8,17 @@ license = "MIT OR Apache-2.0" name = "git_index" readme = "README.md" repository = "https://git.philomathiclife.com/repos/git_index/" -version = "0.1.3" +rust-version = "1.81.0" +version = "0.1.4" -[[bin]] -name = "git_index" -path = "src/main.rs" +[badges] +maintenance = { status = "actively-developed" } [dependencies] -time = { version = "0.3.34", default-features = false, features = ["parsing"] } +time = { version = "0.3.36", default-features = false, features = ["parsing"] } [target.'cfg(target_os = "openbsd")'.dependencies] -priv_sep = { version = "1.0.1", default-features = false, features = ["openbsd"] } - -[badges] -maintenance = { status = "actively-developed" } +priv_sep = { version = "2.1.0", default-features = false, features = ["openbsd"] } [profile.release] lto = true diff --git a/README.md b/README.md @@ -1,12 +1,26 @@ -# git_index - +# git_index + `git_index` invokes [`stagit-index`](https://codemadness.org/stagit.html) by passing in `git` repos in descending -order by commit date. The absolute path to the parent directory containing `git` repos is passed via `-d`/`--dir`. - -### Status - +order by commit date. The absolute path to the parent directory containing `git` repos is passed via `-d`/`--dir`. + +## License + +Licensed under either of + +* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0). +* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT). + +at your option. + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, +as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + +### Status + This package is self-serving. I host `git.philomathiclife.com` which serves my `git` repos in addition to an HTTPS -front-end via [`httpd`](https://man.openbsd.org/OpenBSD-7.4/amd64/httpd.8) on OpenBSD-stable. The static HTML files +front-end via [`httpd`](https://man.openbsd.org/OpenBSD-7.5/amd64/httpd.8) on OpenBSD-stable. The static HTML files are created with `stagit`, and the index file is created by `stagit-index`. `stagit-index` requires one to pass the directories via arguments. The order of the arguments dictates the order of the resulting entries in `index.html`. This program simply extracts the most recent commit from each repo via `git log` and writes the diff --git a/src/args.rs b/src/args.rs @@ -1,10 +1,10 @@ use core::{ convert::AsRef, + error::Error, fmt::{self, Display, Formatter}, }; use std::{ env::{self, Args}, - error::Error, path::{Path, PathBuf}, }; /// Wrapper around an absolute [`PathBuf`] to a directory. @@ -18,9 +18,7 @@ impl AbsDirPath { /// /// If `PathBuf::from(val).as_bytes().last().unwrap() != b'/'`, `val` /// will have `/` appended to it. - #[allow(clippy::option_if_let_else)] - #[inline] - #[must_use] + #[expect(clippy::option_if_let_else, reason = "can't without moving val")] pub fn from_string(val: String) -> Option<Self> { match val.as_bytes().last() { Some(byt) => { @@ -38,13 +36,12 @@ impl AbsDirPath { } } impl AsRef<Path> for AbsDirPath { - #[inline] fn as_ref(&self) -> &Path { self.path.as_path() } } /// Error returned when parsing arguments passed to the application. -#[allow(clippy::exhaustive_enums, clippy::module_name_repetitions)] +#[expect(clippy::module_name_repetitions, reason = "like the name")] #[derive(Debug)] pub enum ArgsErr { /// Error when no arguments were passed to the application. @@ -55,7 +52,6 @@ pub enum ArgsErr { MoreThanOneOption, } impl Display for ArgsErr { - #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { Self::NoArgs => f.write_str("no arguments were passed, but the absolute path to the directory of git repos must be passed"), @@ -66,12 +62,9 @@ impl Display for ArgsErr { } impl Error for ArgsErr {} /// Returns `AbsDirPath` based on arguments passed to the application. -#[allow(clippy::module_name_repetitions)] -#[inline] +#[expect(clippy::module_name_repetitions, reason = "like the name")] pub fn from_env_args() -> Result<AbsDirPath, ArgsErr> { /// Attempts to parse the next `Arg` into an absolute path to a directory. - #[allow(clippy::option_if_let_else)] - #[inline] fn get_path(args: &mut Args) -> Result<AbsDirPath, ArgsErr> { args.next() .ok_or(ArgsErr::NoArgs) diff --git a/src/main.rs b/src/main.rs @@ -12,6 +12,7 @@ rust_2024_compatibility, unsafe_code, unused, + unused_crate_dependencies, warnings, clippy::all, clippy::cargo, @@ -24,13 +25,15 @@ clippy::style, clippy::suspicious )] -#![allow( +#![expect( clippy::blanket_clippy_restriction_lints, clippy::implicit_return, clippy::min_ident_chars, clippy::missing_trait_methods, + clippy::ref_patterns, clippy::question_mark_used, - clippy::single_call_fn + clippy::single_call_fn, + reason = "noisy, opinionated, and likely doesn't prevent bugs or improve APIs" )] extern crate alloc; /// Module that parsed passed options into the application. @@ -40,13 +43,13 @@ use args::{AbsDirPath, ArgsErr}; #[cfg(not(target_os = "openbsd"))] use core::convert::Infallible; use core::{ + error, fmt::{self, Display, Formatter}, str::{self, Utf8Error}, }; #[cfg(target_os = "openbsd")] use priv_sep::{Permissions, Promise, Promises, UnveilErr}; use std::{ - error, ffi::OsString, fs, io::{self, Error, Write}, @@ -79,14 +82,15 @@ enum E { Time(Parse), } impl fmt::Debug for E { - #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { <Self as Display>::fmt(self, f) } } impl Display for E { - #[allow(clippy::use_debug, clippy::ref_patterns)] - #[inline] + #[expect( + clippy::use_debug, + reason = "some contained errors don't implement Display" + )] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { Self::Args(ref e) => e.fmt(f), @@ -111,45 +115,38 @@ impl Display for E { } impl error::Error for E {} impl From<ArgsErr> for E { - #[inline] fn from(value: ArgsErr) -> Self { Self::Args(value) } } impl From<Error> for E { - #[inline] fn from(value: Error) -> Self { Self::Io(value) } } #[cfg(target_os = "openbsd")] impl From<UnveilErr> for E { - #[inline] fn from(value: UnveilErr) -> Self { Self::Unveil(value) } } #[cfg(not(target_os = "openbsd"))] impl From<Infallible> for E { - #[inline] fn from(value: Infallible) -> Self { match value {} } } impl From<Utf8Error> for E { - #[inline] fn from(value: Utf8Error) -> Self { Self::Git(value) } } impl From<OsString> for E { - #[inline] fn from(value: OsString) -> Self { Self::NonUtf8Path(value) } } impl From<Parse> for E { - #[inline] fn from(value: Parse) -> Self { Self::Time(value) } @@ -158,7 +155,6 @@ impl From<Parse> for E { /// to run. Specifically, the `Promise`s `Exec`, `Proc`, `Rpath`, `Stdio`, and `Unveil` /// are passed. #[cfg(target_os = "openbsd")] -#[inline] fn pledge_init() -> Result<Promises<5>, Error> { let promises = Promises::new([ Promise::Exec, @@ -173,81 +169,87 @@ fn pledge_init() -> Result<Promises<5>, Error> { } } /// No-op that returns `Ok`. +#[expect( + clippy::unnecessary_wraps, + reason = "consistent API as openbsd feature" +)] #[cfg(not(target_os = "openbsd"))] -#[allow(clippy::unnecessary_wraps)] -#[inline] const fn pledge_init() -> Result<Zst, Infallible> { Ok(Zst) } /// Removes `Promise::Unveil`. #[cfg(target_os = "openbsd")] -#[inline] fn pledge_away_unveil(promises: &mut Promises<5>) -> Result<(), Error> { promises.remove(Promise::Unveil); promises.pledge() } /// No-op that returns `Ok`. +#[expect( + clippy::unnecessary_wraps, + reason = "consistent API as openbsd feature" +)] #[cfg(not(target_os = "openbsd"))] -#[allow(clippy::unnecessary_wraps)] -#[inline] fn pledge_away_unveil(_: &mut Zst) -> Result<(), Infallible> { Ok(()) } /// Removes all `Promise`s except `Stdio`. #[cfg(target_os = "openbsd")] -#[inline] fn pledge_away_all_but_stdio(promises: &mut Promises<5>) -> Result<(), Error> { promises.retain([Promise::Stdio]); promises.pledge() } /// No-op that returns `Ok`. +#[expect( + clippy::unnecessary_wraps, + reason = "consistent API as openbsd feature" +)] #[cfg(not(target_os = "openbsd"))] -#[allow(clippy::unnecessary_wraps)] -#[inline] fn pledge_away_all_but_stdio(_: &mut Zst) -> Result<(), Infallible> { Ok(()) } /// Calls `unveil_none` on `/`. #[cfg(target_os = "openbsd")] -#[inline] fn veil_all() -> Result<(), UnveilErr> { Permissions::NONE.unveil("/") } /// No-op that returns `Ok`. +#[expect( + clippy::unnecessary_wraps, + reason = "consistent API as openbsd feature" +)] #[cfg(not(target_os = "openbsd"))] -#[allow(clippy::unnecessary_wraps)] -#[inline] const fn veil_all() -> Result<(), Infallible> { Ok(()) } /// Calls `unveil`_on `GIT` with `Permissions::EXECUTE`. #[cfg(target_os = "openbsd")] -#[inline] fn unveil_git() -> Result<(), UnveilErr> { Permissions::EXECUTE.unveil(GIT) } /// No-op that returns `Ok`. +#[expect( + clippy::unnecessary_wraps, + reason = "consistent API as openbsd feature" +)] #[cfg(not(target_os = "openbsd"))] -#[allow(clippy::unnecessary_wraps)] -#[inline] const fn unveil_git() -> Result<(), Infallible> { Ok(()) } /// Calls `unveil`_on `path` with `Permissions::READ`. #[cfg(target_os = "openbsd")] -#[inline] fn unveil_read<P: AsRef<Path>>(path: P) -> Result<(), UnveilErr> { Permissions::READ.unveil(path) } /// No-op that returns `Ok`. +#[expect( + clippy::unnecessary_wraps, + reason = "consistent API as openbsd feature" +)] #[cfg(not(target_os = "openbsd"))] -#[allow(clippy::unnecessary_wraps)] -#[inline] fn unveil_read<P: AsRef<Path>>(_: P) -> Result<(), Infallible> { Ok(()) } /// For each entry in `dir`, `git` is forked and invoked with `-C <dir><entry_in_dir> log -1 --date=iso-strict --pretty=format:"%cd"`. -#[inline] fn get_git_data(map: &mut BTreeMap<OffsetDateTime, Vec<String>>, dir: AbsDirPath) -> Result<(), E> { let iso_format = Iso8601::DEFAULT; for entry in fs::read_dir(dir)? { @@ -283,7 +285,6 @@ fn get_git_data(map: &mut BTreeMap<OffsetDateTime, Vec<String>>, dir: AbsDirPath } /// Writes each `String` in each `Vec` to `stdout` with spaces in between in descending order /// of `map`. -#[inline] fn write_results(map: BTreeMap<OffsetDateTime, Vec<String>>) -> Result<(), Error> { let mut stdout = io::stdout().lock(); map.into_values().rev().try_fold((), |(), paths| {