Skip to content

Make author and committer date roundtrip #1935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 25, 2025
Merged
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -377,3 +377,7 @@ no_effect_underscore_binding = "allow" # x1
empty_docs = "allow"
too_long_first_doc_paragraph = "allow"
large_stack_arrays = "allow"

# Fix one day
result_large_err = "allow"
large_enum_variant = "allow"
2 changes: 1 addition & 1 deletion examples/log.rs
Original file line number Diff line number Diff line change
@@ -150,7 +150,7 @@ fn run(args: Args) -> anyhow::Result<()> {
commit_ref.author.actor().write_to(&mut buf)?;
buf.into()
},
time: commit_ref.author.time.format(format::DEFAULT),
time: commit_ref.author.time()?.format(format::DEFAULT),
message: commit_ref.message.to_owned(),
})
}),
7 changes: 4 additions & 3 deletions gitoxide-core/src/corpus/engine.rs
Original file line number Diff line number Diff line change
@@ -57,8 +57,9 @@ impl Engine {
let repos = self.refresh_repos(&corpus_path, corpus_id)?;
self.state.progress.set_name("refresh repos".into());
self.state.progress.info(format!(
"Added or updated {} repositories under {corpus_path:?}",
repos.len()
"Added or updated {} repositories under '{corpus_path}'",
repos.len(),
corpus_path = corpus_path.display(),
));
Ok(())
}
@@ -316,7 +317,7 @@ impl Engine {
out.push(repo);
progress.inc();
}
Err(err) => progress.fail(format!("{repo_path:?}: {err:#?}")),
Err(err) => progress.fail(format!("{repo_path}: {err:#?}", repo_path = repo_path.display())),
}
}
statement.finalize()?;
14 changes: 6 additions & 8 deletions gitoxide-core/src/hours/core.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ const MINUTES_PER_HOUR: f32 = 60.0;
pub const HOURS_PER_WORKDAY: f32 = 8.0;

pub fn estimate_hours(
commits: &[(u32, gix::actor::SignatureRef<'static>)],
commits: &[(u32, super::SignatureRef<'static>)],
stats: &[(u32, FileStats, LineStats)],
) -> WorkByEmail {
assert!(!commits.is_empty());
@@ -31,7 +31,7 @@ pub fn estimate_hours(
let mut cur = commits.next().expect("at least one commit if we are here");

for next in commits {
let change_in_minutes = (next.time.seconds.saturating_sub(cur.time.seconds)) as f32 / MINUTES_PER_HOUR;
let change_in_minutes = (next.seconds().saturating_sub(cur.seconds())) as f32 / MINUTES_PER_HOUR;
if change_in_minutes < MAX_COMMIT_DIFFERENCE_IN_MINUTES {
hours += change_in_minutes / MINUTES_PER_HOUR;
} else {
@@ -166,13 +166,11 @@ pub fn spawn_tree_delta_threads<'scope>(
(true, true) => {
files.modified += 1;
if let Some(cache) = cache.as_mut() {
let mut diff = change.diff(cache).map_err(|err| {
std::io::Error::new(std::io::ErrorKind::Other, err)
})?;
let mut diff = change.diff(cache).map_err(std::io::Error::other)?;
let mut nl = 0;
if let Some(counts) = diff.line_counts().map_err(|err| {
std::io::Error::new(std::io::ErrorKind::Other, err)
})? {
if let Some(counts) =
diff.line_counts().map_err(std::io::Error::other)?
{
nl += counts.insertions as usize + counts.removals as usize;
lines.added += counts.insertions as usize;
lines.removed += counts.removals as usize;
17 changes: 14 additions & 3 deletions gitoxide-core/src/hours/mod.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ use std::{collections::BTreeSet, io, path::Path, time::Instant};

use anyhow::bail;
use gix::{
actor,
bstr::{BStr, ByteSlice},
prelude::*,
progress, Count, NestedProgress, Progress,
@@ -27,6 +26,18 @@ pub struct Context<W> {
pub out: W,
}

pub struct SignatureRef<'a> {
name: &'a BStr,
email: &'a BStr,
time: gix::date::Time,
}

impl SignatureRef<'_> {
fn seconds(&self) -> gix::date::SecondsSinceUnixEpoch {
self.time.seconds
}
}

/// Estimate the hours it takes to produce the content of the repository in `_working_dir_`, with `_refname_` for
/// the start of the commit graph traversal.
///
@@ -85,7 +96,7 @@ where

out.push((
commit_idx,
actor::SignatureRef {
SignatureRef {
name,
email,
time: author.time,
@@ -97,7 +108,7 @@ where
out.sort_by(|a, b| {
a.1.email
.cmp(b.1.email)
.then(a.1.time.seconds.cmp(&b.1.time.seconds).reverse())
.then(a.1.seconds().cmp(&b.1.seconds()).reverse())
});
Ok(out)
});
3 changes: 2 additions & 1 deletion gitoxide-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -30,9 +30,10 @@
#![deny(rust_2018_idioms)]
#![forbid(unsafe_code)]

use anyhow::bail;
use std::str::FromStr;

use anyhow::bail;

#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
pub enum OutputFormat {
Human,
8 changes: 4 additions & 4 deletions gitoxide-core/src/organize.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::borrow::Cow;
use std::{
borrow::Cow,
ffi::OsStr,
path::{Path, PathBuf},
};
@@ -138,9 +138,9 @@ fn handle(

if let Some(parent_repo_path) = find_parent_repo(git_workdir) {
progress.fail(format!(
"Skipping repository at {:?} as it is nested within repository {:?}",
"Skipping repository at '{}' as it is nested within repository '{}'",
git_workdir.display(),
parent_repo_path
parent_repo_path.display()
));
return Ok(());
}
@@ -157,7 +157,7 @@ fn handle(
};
if url.path.is_empty() {
progress.info(format!(
"Skipping repository at {:?} whose remote does not have a path: {:?}",
"Skipping repository at '{}' whose remote does not have a path: {}",
git_workdir.display(),
url.to_bstring()
));
23 changes: 10 additions & 13 deletions gitoxide-core/src/pack/receive.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::net;
use crate::pack::receive::protocol::fetch::negotiate;
use crate::OutputFormat;
use gix::config::tree::Key;
use gix::protocol::maybe_async;
use gix::remote::fetch::Error;
use gix::DynNestedProgress;
use std::{
io,
path::PathBuf,
sync::{atomic::AtomicBool, Arc},
};

use gix::{config::tree::Key, protocol::maybe_async, remote::fetch::Error, DynNestedProgress};
pub use gix::{
hash::ObjectId,
objs::bstr::{BString, ByteSlice},
@@ -18,11 +18,8 @@ pub use gix::{
},
NestedProgress, Progress,
};
use std::{
io,
path::PathBuf,
sync::{atomic::AtomicBool, Arc},
};

use crate::{net, pack::receive::protocol::fetch::negotiate, OutputFormat};

pub const PROGRESS_RANGE: std::ops::RangeInclusive<u8> = 1..=3;
pub struct Context<W> {
@@ -294,7 +291,7 @@ fn receive_pack_blocking(
None::<gix::objs::find::Never>,
options,
)
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
.map_err(io::Error::other)?;

if let Some(directory) = refs_directory.take() {
write_raw_refs(refs, directory)?;
8 changes: 6 additions & 2 deletions gitoxide-core/src/query/db.rs
Original file line number Diff line number Diff line change
@@ -19,8 +19,12 @@ pub fn create(path: impl AsRef<std::path::Path>) -> anyhow::Result<rusqlite::Con
}
Some(version) if version != VERSION => match con.close() {
Ok(()) => {
std::fs::remove_file(path)
.with_context(|| format!("Failed to remove incompatible database file at {path:?}"))?;
std::fs::remove_file(path).with_context(|| {
format!(
"Failed to remove incompatible database file at {path}",
path = path.display()
)
})?;
con = rusqlite::Connection::open(path)?;
con.execute_batch(meta_table)?;
con.execute("INSERT into meta(version) values(?)", params![VERSION])?;
2 changes: 1 addition & 1 deletion gitoxide-core/src/query/engine/command.rs
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@ impl query::Engine {
usize,
) = row?;
let id = gix::ObjectId::from(hash);
let commit_time = id.attach(&self.repo).object()?.into_commit().committer()?.time;
let commit_time = id.attach(&self.repo).object()?.into_commit().committer()?.time()?;
let mode = FileMode::from_usize(mode).context("invalid file mode")?;
info.push(trace_path::Info {
id,
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/archive.rs
Original file line number Diff line number Diff line change
@@ -84,7 +84,7 @@ fn fetch_rev_info(
Ok(match object.kind {
gix::object::Kind::Commit => {
let commit = object.into_commit();
(Some(commit.committer()?.time.seconds), commit.tree_id()?.detach())
(Some(commit.committer()?.seconds()), commit.tree_id()?.detach())
}
gix::object::Kind::Tree => (None, object.id),
gix::object::Kind::Tag => fetch_rev_info(object.peel_to_kind(gix::object::Kind::Commit)?)?,
4 changes: 2 additions & 2 deletions gitoxide-core/src/repository/attributes/query.rs
Original file line number Diff line number Diff line change
@@ -8,10 +8,10 @@ pub struct Options {
}

pub(crate) mod function {
use std::{borrow::Cow, io, path::Path};

use anyhow::bail;
use gix::bstr::BStr;
use std::borrow::Cow;
use std::{io, path::Path};

use crate::{
is_dir_to_mode,
4 changes: 2 additions & 2 deletions gitoxide-core/src/repository/attributes/validate_baseline.rs
Original file line number Diff line number Diff line change
@@ -44,8 +44,8 @@ pub(crate) mod function {
if repo.is_bare() {
writeln!(
err,
"Repo {:?} is bare - disabling git-ignore baseline as `git check-ignore` needs a worktree",
repo.path()
"Repo at '{repo}' is bare - disabling git-ignore baseline as `git check-ignore` needs a worktree",
repo = repo.path().display()
)
.ok();
ignore = false;
4 changes: 2 additions & 2 deletions gitoxide-core/src/repository/blame.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use gix::bstr::ByteSlice;
use gix::config::tree;
use std::ffi::OsStr;

use gix::{bstr::ByteSlice, config::tree};

pub fn blame_file(
mut repo: gix::Repository,
file: &OsStr,
7 changes: 3 additions & 4 deletions gitoxide-core/src/repository/cat.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::repository::revision::resolve::{BlobFormat, TreeMode};
use anyhow::{anyhow, Context};
use gix::diff::blob::ResourceKind;
use gix::filter::plumbing::driver::apply::Delay;
use gix::revision::Spec;
use gix::{diff::blob::ResourceKind, filter::plumbing::driver::apply::Delay, revision::Spec};

use crate::repository::revision::resolve::{BlobFormat, TreeMode};

pub fn display_object(
repo: &gix::Repository,
26 changes: 16 additions & 10 deletions gitoxide-core/src/repository/clean.rs
Original file line number Diff line number Diff line change
@@ -20,17 +20,23 @@ pub struct Options {
pub find_untracked_repositories: FindRepository,
}
pub(crate) mod function {
use crate::repository::clean::{FindRepository, Options};
use crate::OutputFormat;
use std::{borrow::Cow, path::Path};

use anyhow::bail;
use gix::bstr::BString;
use gix::bstr::ByteSlice;
use gix::dir::entry::{Kind, Status};
use gix::dir::walk::EmissionMode::CollapseDirectory;
use gix::dir::walk::ForDeletionMode::*;
use gix::dir::{walk, EntryRef};
use std::borrow::Cow;
use std::path::Path;
use gix::{
bstr::{BString, ByteSlice},
dir::{
entry::{Kind, Status},
walk,
walk::{EmissionMode::CollapseDirectory, ForDeletionMode::*},
EntryRef,
},
};

use crate::{
repository::clean::{FindRepository, Options},
OutputFormat,
};

pub fn clean(
repo: gix::Repository,
20 changes: 12 additions & 8 deletions gitoxide-core/src/repository/diff.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use anyhow::Context;
use gix::bstr::{BString, ByteSlice};
use gix::diff::blob::intern::TokenSource;
use gix::diff::blob::unified_diff::{ContextSize, NewlineSeparator};
use gix::diff::blob::UnifiedDiff;
use gix::objs::tree::EntryMode;
use gix::odb::store::RefreshMode;
use gix::prelude::ObjectIdExt;
use gix::ObjectId;
use gix::{
bstr::{BString, ByteSlice},
diff::blob::{
intern::TokenSource,
unified_diff::{ContextSize, NewlineSeparator},
UnifiedDiff,
},
objs::tree::EntryMode,
odb::store::RefreshMode,
prelude::ObjectIdExt,
ObjectId,
};

pub fn tree(
mut repo: gix::Repository,
3 changes: 2 additions & 1 deletion gitoxide-core/src/repository/dirty.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::OutputFormat;
use anyhow::bail;

use crate::OutputFormat;

pub enum Mode {
IsClean,
IsDirty,
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/fetch.rs
Original file line number Diff line number Diff line change
@@ -169,7 +169,7 @@ pub(crate) mod function {

let start = std::time::Instant::now();
progress.set_name("layout graph".into());
progress.info(format!("writing {path:?}…"));
progress.info(format!("writing {}…", path.display()));
let mut svg = SVGWriter::new();
vg.do_it(false, false, false, &mut svg);
std::fs::write(path, svg.finalize().as_bytes())?;
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/index/entries.rs
Original file line number Diff line number Diff line change
@@ -23,9 +23,9 @@ pub(crate) mod function {
io::{BufWriter, Write},
};

use gix::index::entry::Stage;
use gix::{
bstr::{BStr, BString},
index::entry::Stage,
worktree::IndexPersistedOrInMemory,
Repository,
};
4 changes: 2 additions & 2 deletions gitoxide-core/src/repository/mailmap.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::bail;
use gix::bstr::{BString, ByteSlice};
use std::io;

use anyhow::bail;
use gix::bstr::{BString, ByteSlice};
#[cfg(feature = "serde")]
use gix::mailmap::Entry;

Loading