Skip to content

Commit

Permalink
Merge pull request #1854 from GitoxideLabs/montly-report
Browse files Browse the repository at this point in the history
montly report
  • Loading branch information
Byron authored Feb 22, 2025
2 parents 2efce72 + d28ff1b commit 16a248b
Show file tree
Hide file tree
Showing 136 changed files with 309 additions and 270 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ bin-dir = "gitoxide-max-pure-v{ version }-{ target }/{ bin }{ binary-ext }"
pedantic = { level = "warn", priority = -1 }
#
# Reviewed and allowed lints
needless_continue = "allow"
enum_glob_use = "allow" # x97
missing_errors_doc = "allow" # x1792
missing_panics_doc = "allow" # x447
Expand Down
2 changes: 1 addition & 1 deletion deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# More documentation for the advisories section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
[advisories]
ignore = []
ignore = ['RUSTSEC-2025-0007']



Expand Down
32 changes: 32 additions & 0 deletions etc/reports/25-02.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Like the previous month was the first in 2025 with plenty of news to share, this month is a first as well: I seem to have nothing to write about.

Sure, there were a couple of smaller API improvements, but nothing that would inspire me.
So what did I do all this time? Probably this is the moment where there really is no other way but to talk about GitButler, something I avoided last month just because it doesn't seem to belong into the `gitoxide` newsletter.

## GitButler

[GitButler](https://gitbutler.com) is what I have been working on intensely for the last two months effectively, in a push to help it to unfold its true potential. Thus far it was mostly powered by `git2`, with `gitoxide` sprinkled in there, but the next iteration will be the inverse with `git2` only being used where `gitoxide` is lacking a feature. That way, along with massive architectural changes, it will be able to cope with large repositories and be more compatible with various Git features, too.

I cannot wait to see all this work to finally come to fruition, and of course, to also see myself being pulled to a user interface that truly elevates my workflow and the workflow of other devs just like me who thus far preferred to stay on the command-line.

## Community

### Faster `gix blame`

Christoph Rüßler kept working and managed to greatly improve the `gix blame` performance while increasing its conformance to Git at the same time. This means that now, depending on the sample, `gix blame` *can* be a bit faster than Git, but it typically is still up to 30% slower when commitgraph caches are used. Overall though, the performance is nothing to sneeze at, and it competes quite well except for in pathological cases.
Admittedly, I am quite blown away by the performance and have a feeling that last time I checked, I didn't use the latest version of the `gix` binary.
It's worth noting that rename-tracking still isn't support, but I also see no reason why it shouldn't be eventually, a feature that would make `gix blame` so much more useful in practice.

### `gix blame` with experimental cache

A pretty [slim PR](https://github.com/GitoxideLabs/gitoxide/pull/1852) shows how to use a special cache to greatly speedup blames, from ~300ms down to just ~4ms, a massive 75x speedup that would be very useful for editors and IDEs, or forges, I am sure!
Of course, one first has to build such cache, and probably do so per file, but I am sure there are plenty of use-cases for it when it's driven by dev tooling.

### Gix in Cargo

With `gix status` now available I am planning to integrate it as soon as possible! That didn't happen yet, but… it will, the stack to work off before I can start this is pretty high though so it's unlikely to happen anytime soon.

Cheers
Sebastian

PS: The latest timesheets can be found [here (2025)](https://github.com/Byron/byron/blob/main/timesheets/2025.csv).
2 changes: 1 addition & 1 deletion gitoxide-core/src/hours/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ where
break;
}
Err(err) => return Err(err.into()),
};
}
}
if let Some(tx) = tx_tree_id {
tx.send(chunk).ok();
Expand Down
8 changes: 4 additions & 4 deletions gitoxide-core/src/index/information.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,16 @@ mod serde_only {
});
if f.link().is_some() {
names.push("link");
};
}
if f.resolve_undo().is_some() {
names.push("resolve-undo (REUC)");
};
}
if f.untracked().is_some() {
names.push("untracked (UNTR)");
};
}
if f.fs_monitor().is_some() {
names.push("fs-monitor (FSMN)");
};
}
if f.had_offset_table() {
names.push("offset-table (IEOT)");
}
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub use discover::discover;
pub fn env(mut out: impl std::io::Write, format: OutputFormat) -> anyhow::Result<()> {
if format != OutputFormat::Human {
bail!("JSON output isn't supported");
};
}

let width = 15;
writeln!(
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/pack/explode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ pub fn pack_or_pack_index(
)
})?;

if !object_path.as_ref().map_or(true, |p| p.as_ref().is_dir()) {
if !object_path.as_ref().is_none_or(|p| p.as_ref().is_dir()) {
return Err(anyhow!(
"The object directory at '{}' is inaccessible",
object_path
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/pack/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ pub fn from_pack(
OutputFormat::Human => drop(human_output(out, res)),
#[cfg(feature = "serde")]
OutputFormat::Json => serde_json::to_writer_pretty(out, &res)?,
};
}
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/pack/receive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,6 @@ fn receive_pack_blocking(
OutputFormat::Json => {
serde_json::to_writer_pretty(&mut out, &JsonOutcome::from_outcome_and_refs(outcome, refs))?;
}
};
}
Ok(())
}
4 changes: 2 additions & 2 deletions gitoxide-core/src/pack/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ where
#[cfg(feature = "serde")]
Some(OutputFormat::Json) => serde_json::to_writer_pretty(out, &multi_index.index_names().iter().zip(res.pack_traverse_statistics).collect::<Vec<_>>())?,
_ => {}
};
}
return Ok(())
},
_ => return Err(anyhow!(
Expand All @@ -195,7 +195,7 @@ where
#[cfg(feature = "serde")]
Some(OutputFormat::Json) => serde_json::to_writer_pretty(out, stats)?,
_ => {}
};
}
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/query/engine/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ pub fn update(
break;
}
Err(err) => return Err(err.into()),
};
}
}
db.send_last_chunk();
let saw_new_commits = !commits.is_empty();
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ pub(crate) mod function {
continue;
}
}
};
}

let is_ignored = matches!(entry.status, gix::dir::entry::Status::Ignored(_));
let entry_path = gix::path::from_bstr(entry.rela_path);
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ pub(crate) mod function {
&mut err,
)?;
}
};
}

if let Some(gix::worktree::state::checkout::Outcome { collisions, errors, .. }) = outcome {
if !(collisions.is_empty() && errors.is_empty()) {
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Filter {
}
(None, _) => {}
(Some(_), None) => return false,
};
}
true
}
}
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ fn write_changes(
writeln!(out, " {:o} -> {:o}", source_entry_mode.0, entry_mode.0)?;
}
}
};
}
}

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ pub(crate) mod function {
gix::remote::fetch::refmap::Source::Ref(r) => {
crate::repository::remote::refs::print_ref(&mut out, r)?;
}
};
}
let mode_and_type = update.type_change.map_or_else(
|| format!("{}", update.mode),
|type_change| {
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/index/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ pub(crate) mod function {
.unwrap_or_default()
},
)
.map_or(true, |m| m.is_excluded());
.is_none_or(|m| m.is_excluded());

let entry_is_submodule = entry.mode.is_submodule();
if entry_is_excluded && (!entry_is_submodule || !recurse_submodules) {
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ mod refs_impl {
out,
&map.remote_refs.into_iter().map(JsonRef::from).collect::<Vec<_>>(),
)?,
};
}
Ok(())
}
}
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/submodule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn print_sm(sm: Submodule<'_>, dirty_suffix: Option<&str>, out: &mut impl std::i
let mut sm_repo = sm.open()?;
if let Some(repo) = sm_repo.as_mut() {
repo.object_cache_size_if_unset(4 * 1024 * 1024);
};
}
writeln!(
out,
" {is_active} {path} {config} head:{head_id} index:{index_id} ({worktree}) [{url}]",
Expand Down
7 changes: 1 addition & 6 deletions gix-attributes/src/search/outcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,7 @@ impl Outcome {
}

fn reduce_and_check_if_done(&mut self, attr: AttributeId) -> bool {
if self.selected.is_empty()
|| self
.selected
.iter()
.any(|(_name, id)| id.map_or(false, |id| id == attr))
{
if self.selected.is_empty() || self.selected.iter().any(|(_name, id)| *id == Some(attr)) {
*self.remaining.as_mut().expect("initialized") -= 1;
}
self.is_done()
Expand Down
2 changes: 1 addition & 1 deletion gix-blame/src/file/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ fn collect_parents(
parent_ids.push((id, parent_commit_time));
}
}
};
}
Ok(parent_ids)
}

Expand Down
2 changes: 1 addition & 1 deletion gix-commitgraph/src/file/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl File {
x => {
return Err(Error::UnsupportedVersion(x));
}
};
}
ofs += 1;

let object_hash = gix_hash::Kind::try_from(data[ofs]).map_err(Error::UnsupportedHashVersion)?;
Expand Down
4 changes: 2 additions & 2 deletions gix-config-value/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ impl<'a> Path<'a> {
/// the `home_for_user` function to be provided.
/// The interpolation uses `getpwnam` sys call and is therefore not available on windows.
/// - `%(prefix)/` is expanded to the location where `gitoxide` is installed.
/// This location is not known at compile time and therefore need to be
/// optionally provided by the caller through `git_install_dir`.
/// This location is not known at compile time and therefore need to be
/// optionally provided by the caller through `git_install_dir`.
///
/// Any other, non-empty path value is returned unchanged and error is returned in case of an empty path value or if required input
/// wasn't provided.
Expand Down
2 changes: 1 addition & 1 deletion gix-config/src/file/includes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl File<'static> {
/// which later overwrite portions of the included file, which seems unusual as these would be related to `includes`.
/// We can fix this by 'splitting' the include section if needed so the included sections are put into the right place.
/// - `hasconfig:remote.*.url` will not prevent itself to include files with `[remote "name"]\nurl = x` values, but it also
/// won't match them, i.e. one cannot include something that will cause the condition to match or to always be true.
/// won't match them, i.e. one cannot include something that will cause the condition to match or to always be true.
pub fn resolve_includes(&mut self, options: init::Options<'_>) -> Result<(), Error> {
if options.includes.max_depth == 0 {
return Ok(());
Expand Down
2 changes: 1 addition & 1 deletion gix-config/src/file/init/from_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl File<'static> {
return Err(Error::Io { source: err, path });
}
}
};
}
meta.path = Some(path);

let config = Self::from_bytes_owned(buf, meta, options)?;
Expand Down
2 changes: 1 addition & 1 deletion gix-config/src/file/section/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl Body<'_> {
value_range.end = i;
} else {
value_range.start = i;
};
}
}
_ => (),
}
Expand Down
2 changes: 1 addition & 1 deletion gix-config/src/parse/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ fn from_bytes<'a, 'b>(
events: std::mem::take(&mut events),
});
}
};
}
header = match convert(Event::SectionHeader(next_header)) {
Event::SectionHeader(h) => h,
_ => unreachable!("BUG: convert must not change the event type, just the lifetime"),
Expand Down
2 changes: 1 addition & 1 deletion gix-credentials/tests/program/from_custom_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const SH: &str = "/bin/sh";
fn empty() {
let prog = Program::from_custom_definition("");
let git = *GIT;
assert!(matches!(&prog.kind, Kind::ExternalName { name_and_args } if name_and_args == ""));
assert!(matches!(&prog.kind, Kind::ExternalName { name_and_args } if name_and_args.is_empty()));
assert_eq!(
format!("{:?}", prog.to_command(&helper::Action::Store("egal".into()))),
format!(r#""{git}" "credential-" "store""#),
Expand Down
2 changes: 1 addition & 1 deletion gix-date/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub(crate) mod function {
let mut offset_in_seconds = hours * 3600 + minutes * 60;
if sign == Sign::Minus {
offset_in_seconds *= -1;
};
}
let time = Time {
seconds,
offset: offset_in_seconds,
Expand Down
42 changes: 20 additions & 22 deletions gix-diff/src/blob/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ impl Pipeline {
&& header.size > self.options.large_file_threshold_bytes
{
is_binary = Some(true);
};
}
let data = if is_binary == Some(true) {
Data::Binary { size: header.size }
} else {
Expand Down Expand Up @@ -461,27 +461,25 @@ impl Pipeline {
out.clear();
run_cmd(rela_path, cmd, out)?;
}
None => {
match res {
ToWorktreeOutcome::Unchanged(_) => {}
ToWorktreeOutcome::Buffer(src) => {
out.clear();
out.try_reserve(src.len())?;
out.extend_from_slice(src);
}
ToWorktreeOutcome::Process(MaybeDelayed::Immediate(mut stream)) => {
std::io::copy(&mut stream, out).map_err(|err| {
convert_to_diffable::Error::StreamCopy {
rela_path: rela_path.to_owned(),
source: err,
}
})?;
}
ToWorktreeOutcome::Process(MaybeDelayed::Delayed(_)) => {
unreachable!("we prohibit this")
}
};
}
None => match res {
ToWorktreeOutcome::Unchanged(_) => {}
ToWorktreeOutcome::Buffer(src) => {
out.clear();
out.try_reserve(src.len())?;
out.extend_from_slice(src);
}
ToWorktreeOutcome::Process(MaybeDelayed::Immediate(mut stream)) => {
std::io::copy(&mut stream, out).map_err(|err| {
convert_to_diffable::Error::StreamCopy {
rela_path: rela_path.to_owned(),
source: err,
}
})?;
}
ToWorktreeOutcome::Process(MaybeDelayed::Delayed(_)) => {
unreachable!("we prohibit this")
}
},
}
}

Expand Down
2 changes: 1 addition & 1 deletion gix-diff/src/blob/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ impl Platform {
/// * `mode` is the kind of object (only blobs and links are allowed)
/// * `rela_path` is the relative path as seen from the (work)tree root.
/// * `kind` identifies the side of the diff this resource will be used for.
/// A diff needs both `OldOrSource` *and* `NewOrDestination`.
/// A diff needs both `OldOrSource` *and* `NewOrDestination`.
/// * `objects` provides access to the object database in case the resource can't be read from a worktree.
///
/// Note that it's assumed that either `id + mode (` or `rela_path` can serve as unique identifier for the resource,
Expand Down
Loading

0 comments on commit 16a248b

Please sign in to comment.