commit a429b4d66c7de61572254ce104bf7fa636cb030d
parent beb85f468f5edb0c2dbd186ee5ca4a1f4ef204aa
Author: Zack Newman <zack@philomathiclife.com>
Date: Fri, 20 Mar 2026 15:34:44 -0600
update deps and lints. address new deps and lints
Diffstat:
| M | Cargo.toml | | | 157 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
| M | README.md | | | 8 | ++++++-- |
| M | src/args.rs | | | 48 | ++++++++++++++++++++++++++++++++++-------------- |
| M | src/main.rs | | | 114 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
4 files changed, 210 insertions(+), 117 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -9,60 +9,109 @@ name = "git_index"
publish = false
readme = "README.md"
repository = "https://git.philomathiclife.com/repos/git_index/"
-rust-version = "1.86.0"
-version = "0.1.9"
+rust-version = "1.93.1"
+version = "0.1.10"
[lints.rust]
-ambiguous_negative_literals = { level = "deny", priority = -1 }
-closure_returning_async_block = { level = "deny", priority = -1 }
-deprecated_safe = { level = "deny", priority = -1 }
-deref_into_dyn_supertrait = { level = "deny", priority = -1 }
-ffi_unwind_calls = { level = "deny", priority = -1 }
-future_incompatible = { level = "deny", priority = -1 }
-#fuzzy_provenance_casts = { level = "deny", priority = -1 }
-impl_trait_redundant_captures = { level = "deny", priority = -1 }
-keyword_idents = { level = "deny", priority = -1 }
-let_underscore = { level = "deny", priority = -1 }
-linker_messages = { level = "deny", priority = -1 }
-#lossy_provenance_casts = { level = "deny", priority = -1 }
-macro_use_extern_crate = { level = "deny", priority = -1 }
-meta_variable_misuse = { level = "deny", priority = -1 }
-missing_copy_implementations = { level = "deny", priority = -1 }
-missing_debug_implementations = { level = "deny", priority = -1 }
-missing_docs = { level = "deny", priority = -1 }
-#multiple_supertrait_upcastable = { level = "deny", priority = -1 }
-#must_not_suspend = { level = "deny", priority = -1 }
-non_ascii_idents = { level = "deny", priority = -1 }
-#non_exhaustive_omitted_patterns = { level = "deny", priority = -1 }
-nonstandard_style = { level = "deny", priority = -1 }
-redundant_imports = { level = "deny", priority = -1 }
-redundant_lifetimes = { level = "deny", priority = -1 }
-refining_impl_trait = { level = "deny", priority = -1 }
-rust_2018_compatibility = { level = "deny", priority = -1 }
-rust_2018_idioms = { level = "deny", priority = -1 }
-rust_2021_compatibility = { level = "deny", priority = -1 }
-rust_2024_compatibility = { level = "deny", priority = -1 }
-single_use_lifetimes = { level = "deny", priority = -1 }
-#supertrait_item_shadowing_definition = { level = "deny", priority = -1 }
-trivial_casts = { level = "deny", priority = -1 }
-trivial_numeric_casts = { level = "deny", priority = -1 }
-unit_bindings = { level = "deny", priority = -1 }
-unnameable_types = { level = "deny", priority = -1 }
-#unqualified_local_imports = { level = "deny", priority = -1 }
-unreachable_pub = { level = "deny", priority = -1 }
-unsafe_code = { level = "deny", priority = -1 }
-unstable_features = { level = "deny", priority = -1 }
+deprecated-safe = { level = "deny", priority = -1 }
+future-incompatible = { level = "deny", priority = -1 }
+keyword-idents = { level = "deny", priority = -1 }
+let-underscore = { level = "deny", priority = -1 }
+nonstandard-style = { level = "deny", priority = -1 }
+refining-impl-trait = { level = "deny", priority = -1 }
+rust-2018-compatibility = { level = "deny", priority = -1 }
+rust-2018-idioms = { level = "deny", priority = -1 }
+rust-2021-compatibility = { level = "deny", priority = -1 }
+rust-2024-compatibility = { level = "deny", priority = -1 }
+unknown-or-malformed-diagnostic-attributes = { level = "deny", priority = -1 }
unused = { level = "deny", priority = -1 }
-unused_crate_dependencies = { level = "deny", priority = -1 }
-unused_import_braces = { level = "deny", priority = -1 }
-unused_lifetimes = { level = "deny", priority = -1 }
-unused_qualifications = { level = "deny", priority = -1 }
-unused_results = { level = "deny", priority = -1 }
-variant_size_differences = { level = "deny", priority = -1 }
warnings = { level = "deny", priority = -1 }
+ambiguous-negative-literals = { level = "deny", priority = -1 }
+closure-returning-async-block = { level = "deny", priority = -1 }
+deprecated-in-future = { level = "deny", priority = -1 }
+deref-into-dyn-supertrait = { level = "deny", priority = -1 }
+ffi-unwind-calls = { level = "deny", priority = -1 }
+#fuzzy-provenance-casts = { level = "deny", priority = -1 }
+impl-trait-redundant-captures = { level = "deny", priority = -1 }
+linker-messages = { level = "deny", priority = -1 }
+#lossy-provenance-casts = { level = "deny", priority = -1 }
+macro-use-extern-crate = { level = "deny", priority = -1 }
+meta-variable-misuse = { level = "deny", priority = -1 }
+missing-copy-implementations = { level = "deny", priority = -1 }
+missing-debug-implementations = { level = "deny", priority = -1 }
+missing-docs = { level = "deny", priority = -1 }
+#multiple-supertrait-upcastable = { level = "deny", priority = -1 }
+#must-not-suspend = { level = "deny", priority = -1 }
+non-ascii-idents = { level = "deny", priority = -1 }
+#non-exhaustive-omitted-patterns = { level = "deny", priority = -1 }
+redundant-imports = { level = "deny", priority = -1 }
+redundant-lifetimes = { level = "deny", priority = -1 }
+#resolving-to-items-shadowing-supertrait-items = { level = "deny", priority = -1 }
+#shadowing-supertrait-items = { level = "deny", priority = -1 }
+single-use-lifetimes = { level = "deny", priority = -1 }
+trivial-casts = { level = "deny", priority = -1 }
+trivial-numeric-casts = { level = "deny", priority = -1 }
+unit-bindings = { level = "deny", priority = -1 }
+unnameable-types = { level = "deny", priority = -1 }
+#unqualified-local-imports = { level = "deny", priority = -1 }
+unreachable-pub = { level = "deny", priority = -1 }
+unsafe-code = { level = "deny", priority = -1 }
+unstable-features = { level = "deny", priority = -1 }
+unused-crate-dependencies = { level = "deny", priority = -1 }
+unused-import-braces = { level = "deny", priority = -1 }
+unused-lifetimes = { level = "deny", priority = -1 }
+unused-qualifications = { level = "deny", priority = -1 }
+unused-results = { level = "deny", priority = -1 }
+variant-size-differences = { level = "deny", priority = -1 }
+# Before publishing to crates.io, comment above and uncomment below.
+#warnings = { level = "allow", priority = -1 }
+#ambiguous-associated-items = { level = "allow", priority = -1 }
+#arithmetic-overflow = { level = "allow", priority = -1 }
+#binary-asm-labels = { level = "allow", priority = -1 }
+#bindings-with-variant-name = { level = "allow", priority = -1 }
+#conflicting-repr-hints = { level = "allow", priority = -1 }
+#dangerous-implicit-autorefs = { level = "allow", priority = -1 }
+#default-overrides-default-fields = { level = "allow", priority = -1 }
+#dependency-on-unit-never-type-fallback = { level = "allow", priority = -1 }
+#deref-nullptr = { level = "allow", priority = -1 }
+#elided-lifetimes-in-associated-constant = { level = "allow", priority = -1 }
+#enum-intrinsics-non-enums = { level = "allow", priority = -1 }
+#explicit-builtin-cfgs-in-flags = { level = "allow", priority = -1 }
+#ill-formed-attribute-input = { level = "allow", priority = -1 }
+#incomplete-include = { level = "allow", priority = -1 }
+#ineffective-unstable-trait-impl = { level = "allow", priority = -1 }
+#invalid-atomic-ordering = { level = "allow", priority = -1 }
+#invalid-from-utf8-unchecked = { level = "allow", priority = -1 }
+#invalid-macro-export-arguments = { level = "allow", priority = -1 }
+#invalid-null-arguments = { level = "allow", priority = -1 }
+#invalid-reference-casting = { level = "allow", priority = -1 }
+#invalid-type-param-default = { level = "allow", priority = -1 }
+#legacy-derive-helpers = { level = "allow", priority = -1 }
+#let-underscore-lock = { level = "allow", priority = -1 }
+#long-running-const-eval = { level = "allow", priority = -1 }
+#macro-expanded-macro-exports-accessed-by-absolute-paths = { level = "allow", priority = -1 }
+#mutable-transmutes = { level = "allow", priority = -1 }
+#named-asm-labels = { level = "allow", priority = -1 }
+#never-type-fallback-flowing-into-unsafe = { level = "allow", priority = -1 }
+#no-mangle-const-items = { level = "allow", priority = -1 }
+#out-of-scope-macro-calls = { level = "allow", priority = -1 }
+#overflowing-literals = { level = "allow", priority = -1 }
+#patterns-in-fns-without-body = { level = "allow", priority = -1 }
+#proc-macro-derive-resolution-fallback = { level = "allow", priority = -1 }
+#pub-use-of-private-extern-crate = { level = "allow", priority = -1 }
+#repr-transparent-non-zst-fields = { level = "allow", priority = -1 }
+#semicolon-in-expressions-from-macros = { level = "allow", priority = -1 }
+#soft-unstable = { level = "allow", priority = -1 }
+#test-unstable-lint = { level = "allow", priority = -1 }
+#text-direction-codepoint-in-comment = { level = "allow", priority = -1 }
+#text-direction-codepoint-in-literal = { level = "allow", priority = -1 }
+#unconditional-panic = { level = "allow", priority = -1 }
+#undropped-manually-drops = { level = "allow", priority = -1 }
+#unknown-crate-types = { level = "allow", priority = -1 }
+#useless-deprecated = { level = "allow", priority = -1 }
+# Before publishing to crates.io, comment below.
[lints.clippy]
-all = { level = "deny", priority = -1 }
cargo = { level = "deny", priority = -1 }
complexity = { level = "deny", priority = -1 }
correctness = { level = "deny", priority = -1 }
@@ -85,11 +134,19 @@ ref_patterns = "allow"
return_and_then = "allow"
single_call_fn = "allow"
+[lints.rustdoc]
+# Before publishing to crates.io, comment below and uncomment below that.
+all = { level = "deny", priority = -1 }
+#all = "allow"
+
[dependencies]
-jiff = { version = "0.2.15", default-features = false }
-priv_sep = { version = "3.0.0-alpha.1.3", default-features = false }
+jiff = { version = "0.2.23", default-features = false }
+
+[target.'cfg(target_os = "openbsd")'.dependencies]
+priv_sep = { version = "3.0.0-alpha.5.0", default-features = false }
[profile.release]
+codegen-units = 1
lto = true
panic = 'abort'
strip = true
diff --git a/README.md b/README.md
@@ -30,8 +30,12 @@ at your option.
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.
-Before any PR is sent, `cargo clippy` and `cargo t` should be run for both. Additionally
-`RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features` should be run to ensure documentation can be built.
+Before any PR is sent, `cargo clippy --all-targets` and `cargo test --all-targets` should be run using the stable
+and MSRV toolchains. One easy way to achieve this is by invoking [`ci-cargo`](https://crates.io/crates/ci-cargo)
+as `ci-cargo clippy --all-targets test --benches --bins --examples --tests --include-ignored` in the `git_index`
+directory.
+
+Last, `cargo +nightly doc` should be run to ensure documentation can be built.
### Status
diff --git a/src/args.rs b/src/args.rs
@@ -1,44 +1,64 @@
+#[cfg(target_os = "openbsd")]
+use alloc::ffi::CString;
+#[cfg(target_os = "openbsd")]
+use core::ffi::CStr;
use core::{
error::Error,
fmt::{self, Display, Formatter},
};
use std::{
- env::{self, Args},
- path::{Path, PathBuf},
+ env::{self, ArgsOs},
+ ffi::OsString,
+ path::PathBuf,
};
/// Wrapper around an absolute [`PathBuf`] to a directory.
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub(crate) struct AbsDirPath {
/// The directory.
path: PathBuf,
+ /// The directory.
+ #[cfg(target_os = "openbsd")]
+ path_c: CString,
}
impl AbsDirPath {
+ /// Returns `self` as a `CStr`.
+ #[cfg(target_os = "openbsd")]
+ pub(crate) fn as_cstr(&self) -> &CStr {
+ &self.path_c
+ }
+ /// Returns the `PathBuf` `self` is based on.
+ pub(crate) fn into_path_buf(self) -> PathBuf {
+ self.path
+ }
/// Returns an `AbsDirPath` iff `PathBuf::from(val).is_absolute()`.
///
/// If `PathBuf::from(val).as_bytes().last().unwrap() != b'/'`, `val`
/// will have `/` appended to it.
#[expect(clippy::option_if_let_else, reason = "can't without moving val")]
- pub(crate) fn from_string(val: String) -> Option<Self> {
- match val.as_bytes().last() {
+ pub(crate) fn from_string(val: OsString) -> Option<Self> {
+ match val.as_encoded_bytes().last() {
Some(byt) => {
let last = *byt;
let mut path = PathBuf::from(val);
- path.is_absolute().then(|| {
+ if path.is_absolute() {
if last != b'/' {
path.as_mut_os_string().push("/");
}
- Self { path }
- })
+ #[cfg(not(target_os = "openbsd"))]
+ let opt = Some(Self { path });
+ #[cfg(target_os = "openbsd")]
+ let opt = CString::new(path.clone().into_os_string().into_encoded_bytes())
+ .ok()
+ .map(|path_c| Self { path, path_c });
+ opt
+ } else {
+ None
+ }
}
None => None,
}
}
}
-impl AsRef<Path> for AbsDirPath {
- fn as_ref(&self) -> &Path {
- self.path.as_path()
- }
-}
/// Error returned when parsing arguments passed to the application.
#[derive(Debug)]
pub(crate) enum ArgsErr {
@@ -62,12 +82,12 @@ impl Error for ArgsErr {}
/// Returns `AbsDirPath` based on arguments passed to the application.
pub(crate) fn from_env_args() -> Result<AbsDirPath, ArgsErr> {
/// Attempts to parse the next `Arg` into an absolute path to a directory.
- fn get_path(args: &mut Args) -> Result<AbsDirPath, ArgsErr> {
+ fn get_path(args: &mut ArgsOs) -> Result<AbsDirPath, ArgsErr> {
args.next()
.ok_or(ArgsErr::NoArgs)
.and_then(|path| AbsDirPath::from_string(path).ok_or(ArgsErr::InvalidDir))
}
- let mut args = env::args();
+ let mut args = env::args_os();
let Some(_) = args.next() else {
return Err(ArgsErr::NoArgs);
};
diff --git a/src/main.rs b/src/main.rs
@@ -10,34 +10,37 @@ use args::{AbsDirPath, ArgsErr};
use core::convert::Infallible;
use core::{
error,
+ ffi::CStr,
fmt::{self, Display, Formatter},
str::{self, Utf8Error},
};
use jiff::{Error as TimeErr, Timestamp, fmt::temporal::DateTimeParser};
-#[cfg(not(target_os = "openbsd"))]
-use priv_sep as _;
#[cfg(target_os = "openbsd")]
-use priv_sep::{NulOrIoErr, Permissions, Promise, Promises};
+use priv_sep::{Errno, Permissions, Promise, Promises};
use std::{
ffi::OsString,
fs,
io::{self, Error, Write as _},
- path::Path,
+ path::PathBuf,
process::{Command, Stdio},
};
-/// `()` triggers lints when captured by `let`.
-/// This only relevant for the no-op functions.
-#[cfg(not(target_os = "openbsd"))]
-#[derive(Clone, Copy)]
-struct Zst;
/// Module for reading the options passed to the application.
/// Error returned from the program.
enum E {
/// Variant for errors due to incorrect arguments being passed.
Args(ArgsErr),
+ /// Variant for errors due to calls to `pledge`.
#[cfg(target_os = "openbsd")]
+ Pledge(Errno),
+ /// Unify with non-OpenBSD.
+ #[cfg(not(target_os = "openbsd"))]
+ Pledge(Infallible),
/// Variant for errors due to calls to `unveil`.
- Unveil(NulOrIoErr),
+ #[cfg(target_os = "openbsd")]
+ Unveil(Errno),
+ /// Unify with non-OpenBSD.
+ #[cfg(not(target_os = "openbsd"))]
+ Unveil(Infallible),
/// Variant for IO errors.
Io(Error),
/// Variant when a git repo directory is not valid UTF-8.
@@ -63,9 +66,15 @@ impl Display for E {
match *self {
Self::Args(ref e) => e.fmt(f),
#[cfg(target_os = "openbsd")]
- Self::Unveil(ref err) => write!(f, "unveil(2) failed with {err}"),
+ Self::Pledge(err) => write!(f, "pledge(2) failed with {err}"),
+ #[cfg(not(target_os = "openbsd"))]
+ Self::Pledge(e) => match e {},
+ #[cfg(target_os = "openbsd")]
+ Self::Unveil(err) => write!(f, "unveil(2) failed with {err}"),
+ #[cfg(not(target_os = "openbsd"))]
+ Self::Unveil(e) => match e {},
Self::Io(ref e) => e.fmt(f),
- Self::NonUtf8Path(ref e) => write!(f, "{e:?} is not valid UTF-8"),
+ Self::NonUtf8Path(ref e) => write!(f, "{} is not valid UTF-8", e.display()),
Self::GitErr(ref e) => match str::from_utf8(e.as_slice()) {
Ok(err) => write!(f, "git errored with: {err}"),
Err(err) => write!(f, "git errored with an invalid UTF-8 error: {err}"),
@@ -92,18 +101,6 @@ impl From<Error> for E {
Self::Io(value)
}
}
-#[cfg(target_os = "openbsd")]
-impl From<NulOrIoErr> for E {
- fn from(value: NulOrIoErr) -> Self {
- Self::Unveil(value)
- }
-}
-#[cfg(not(target_os = "openbsd"))]
-impl From<Infallible> for E {
- fn from(value: Infallible) -> Self {
- match value {}
- }
-}
impl From<Utf8Error> for E {
fn from(value: Utf8Error) -> Self {
Self::Git(value)
@@ -123,7 +120,7 @@ impl From<TimeErr> for E {
/// to run. Specifically, the `Promise`s `Exec`, `Proc`, `Rpath`, `Stdio`, and `Unveil`
/// are passed.
#[cfg(target_os = "openbsd")]
-fn pledge_init() -> Result<Promises, Error> {
+fn pledge_init() -> Result<Promises, Errno> {
let promises = Promises::new([
Promise::Exec,
Promise::Proc,
@@ -142,12 +139,12 @@ fn pledge_init() -> Result<Promises, Error> {
reason = "consistent API as openbsd feature"
)]
#[cfg(not(target_os = "openbsd"))]
-const fn pledge_init() -> Result<Zst, Infallible> {
- Ok(Zst)
+const fn pledge_init() -> Result<(), Infallible> {
+ Ok(())
}
/// Removes `Promise::Unveil`.
#[cfg(target_os = "openbsd")]
-fn pledge_away_unveil(promises: &mut Promises) -> Result<(), Error> {
+fn pledge_away_unveil(promises: &mut Promises) -> Result<(), Errno> {
promises.remove_then_pledge(Promise::Unveil)
}
/// No-op that returns `Ok`.
@@ -156,12 +153,12 @@ fn pledge_away_unveil(promises: &mut Promises) -> Result<(), Error> {
reason = "consistent API as openbsd feature"
)]
#[cfg(not(target_os = "openbsd"))]
-const fn pledge_away_unveil(_: &mut Zst) -> Result<(), Infallible> {
+const fn pledge_away_unveil(_: &mut ()) -> Result<(), Infallible> {
Ok(())
}
/// Removes all `Promise`s except `Stdio`.
#[cfg(target_os = "openbsd")]
-fn pledge_away_all_but_stdio(promises: &mut Promises) -> Result<(), Error> {
+fn pledge_away_all_but_stdio(promises: &mut Promises) -> Result<(), Errno> {
promises.retain_then_pledge([Promise::Stdio])
}
/// No-op that returns `Ok`.
@@ -170,13 +167,13 @@ fn pledge_away_all_but_stdio(promises: &mut Promises) -> Result<(), Error> {
reason = "consistent API as openbsd feature"
)]
#[cfg(not(target_os = "openbsd"))]
-const fn pledge_away_all_but_stdio(_: &mut Zst) -> Result<(), Infallible> {
+const fn pledge_away_all_but_stdio(_: &mut ()) -> Result<(), Infallible> {
Ok(())
}
/// Calls `unveil_none` on `/`.
#[cfg(target_os = "openbsd")]
-fn veil_all() -> Result<(), NulOrIoErr> {
- Permissions::NONE.unveil("/")
+fn veil_all() -> Result<(), Errno> {
+ Permissions::NONE.unveil(c"/")
}
/// No-op that returns `Ok`.
#[expect(
@@ -187,10 +184,10 @@ fn veil_all() -> Result<(), NulOrIoErr> {
const fn veil_all() -> Result<(), Infallible> {
Ok(())
}
-/// Calls `unveil`_on `GIT` with `Permissions::EXECUTE`.
+/// Calls `unveil`_on `GIT_CSTR` with `Permissions::EXECUTE`.
#[cfg(target_os = "openbsd")]
-fn unveil_git() -> Result<(), NulOrIoErr> {
- Permissions::EXECUTE.unveil(GIT)
+fn unveil_git() -> Result<(), Errno> {
+ Permissions::EXECUTE.unveil(GIT_CSTR)
}
/// No-op that returns `Ok`.
#[expect(
@@ -203,8 +200,8 @@ const fn unveil_git() -> Result<(), Infallible> {
}
/// Calls `unveil`_on `path` with `Permissions::READ`.
#[cfg(target_os = "openbsd")]
-fn unveil_read<P: AsRef<Path>>(path: P) -> Result<(), NulOrIoErr> {
- Permissions::READ.unveil(path)
+fn unveil_read(path: &AbsDirPath) -> Result<(), Errno> {
+ Permissions::READ.unveil(path.as_cstr())
}
/// No-op that returns `Ok`.
#[expect(
@@ -212,11 +209,11 @@ fn unveil_read<P: AsRef<Path>>(path: P) -> Result<(), NulOrIoErr> {
reason = "consistent API as openbsd feature"
)]
#[cfg(not(target_os = "openbsd"))]
-fn unveil_read<P: AsRef<Path>>(_: P) -> Result<(), Infallible> {
+const fn unveil_read(_: &AbsDirPath) -> 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"`.
-fn get_git_data(map: &mut BTreeMap<Timestamp, Vec<String>>, dir: AbsDirPath) -> Result<(), E> {
+fn get_git_data(map: &mut BTreeMap<Timestamp, Vec<String>>, dir: PathBuf) -> Result<(), E> {
let parser = DateTimeParser::new();
for entry in fs::read_dir(dir)? {
let repo = entry?;
@@ -260,16 +257,31 @@ fn write_results(map: BTreeMap<Timestamp, Vec<String>>) -> Result<(), Error> {
})
}
/// The absolute path to `git`.
-const GIT: &str = "/usr/local/bin/git";
+const GIT_CSTR: &CStr = c"/usr/local/bin/git";
+/// The absolute path to `git`.
+const GIT: &str = match GIT_CSTR.to_str() {
+ Ok(val) => val,
+ Err(_) => panic!("/usr/local/bin/git is not a valid str"),
+};
fn main() -> Result<(), E> {
- let mut promises = pledge_init()?;
- veil_all()?;
- let git_dir = args::from_env_args()?;
- unveil_read(git_dir.as_ref())?;
- unveil_git()?;
- pledge_away_unveil(&mut promises)?;
- let mut map = BTreeMap::new();
- get_git_data(&mut map, git_dir)?;
- pledge_away_all_but_stdio(&mut promises)?;
- write_results(map).map_err(E::Io)
+ pledge_init().map_err(E::Pledge).and_then(|mut promises| {
+ veil_all().map_err(E::Unveil).and_then(|()| {
+ args::from_env_args().map_err(E::Args).and_then(|git_dir| {
+ unveil_read(&git_dir).map_err(E::Unveil).and_then(|()| {
+ unveil_git().map_err(E::Unveil).and_then(|()| {
+ pledge_away_unveil(&mut promises)
+ .map_err(E::Pledge)
+ .and_then(|()| {
+ let mut map = BTreeMap::new();
+ get_git_data(&mut map, git_dir.into_path_buf()).and_then(|()| {
+ pledge_away_all_but_stdio(&mut promises)
+ .map_err(E::Pledge)
+ .and_then(|()| write_results(map).map_err(E::Io))
+ })
+ })
+ })
+ })
+ })
+ })
+ })
}