Skip to content

octopus-merge (part 4: rewrite tracking in plumbing) #1612

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 13 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,9 @@ serde_derive = ">=1.0.185"

once_cell = "1.18.0"
document-features = { version = "0.2.0", optional = true }

[profile.dev.package]
insta.opt-level = 3
similar.opt-level = 3
gix-object = { opt-level = 3 }
gix-ref = { opt-level = 3 }
#gix-pack = { opt-level = 3 }
Expand Down
28 changes: 18 additions & 10 deletions crate-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,17 +304,24 @@ Check out the [performance discussion][gix-diff-performance] as well.

* **tree**
* [x] changes needed to obtain _other tree_
* **patches**
* There are various ways to generate a patch from two blobs.
* [ ] text
* [ ] binary
* **lines**
* [x] Simple line-by-line diffs powered by the `imara-diff` crate.
* **blobs**
* **patches**
* There are various ways to generate a patch from two blobs.
* [ ] text
* [ ] binary
* [ ] `git-apply` compatibility
* [ ] merge hunks that are close enough based on line-setting (`interhunk-lines`)
* [ ] white-space related settings
* **lines**
* [x] Simple line-by-line diffs powered by the `imara-diff` crate.
* **generic rename tracker to find renames and copies**
* [x] find by exact match
* [x] find by similarity check
* [x] find blobs by exact match
* [x] find blobs by similarity check
* [ ] heuristics to find best candidate
* [ ] find by basename to help detecting simple moves
* [ ] find by basename to support similarity check
* [x] directory tracking
- [x] by identity
- [ ] by similarity
* **blob**
* [x] a choice of to-worktree, to-git and to-worktree-if-needed conversions
* [x] `textconv` filters
Expand All @@ -332,12 +339,13 @@ Check out the [performance discussion][gix-diff-performance] as well.

### gix-merge

* [x] three-way merge analysis of blobs with choice of how to resolve conflicts
* [x] three-way merge analysis of **blobs** with choice of how to resolve conflicts
- [ ] choose how to resolve conflicts on the data-structure
- [ ] produce a new blob based on data-structure containing possible resolutions
- [x] `merge` style
- [x] `diff3` style
- [x] `zdiff` style
- [ ] a way to control inter-hunk merging based on proximity (maybe via `gix-diff` feature which could use the same)
* [ ] diff-heuristics match Git perfectly
* [x] API documentation
* [ ] Examples
Expand Down
14 changes: 8 additions & 6 deletions gitoxide-core/src/hours/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,22 +125,23 @@ pub fn spawn_tree_delta_threads<'scope>(
None => continue,
};
from.changes()?
.track_filename()
.track_rewrites(None)
.options(|opts| {
opts.track_filename().track_rewrites(None);
})
.for_each_to_obtain_tree(&to, |change| {
use gix::object::tree::diff::change::Event::*;
use gix::object::tree::diff::Change::*;
changes.fetch_add(1, Ordering::Relaxed);
match change.event {
match change {
Rewrite { .. } => {
unreachable!("we turned that off")
}
Addition { entry_mode, id } => {
Addition { entry_mode, id, .. } => {
if entry_mode.is_no_tree() {
files.added += 1;
add_lines(line_stats, &lines_count, &mut lines, id);
}
}
Deletion { entry_mode, id } => {
Deletion { entry_mode, id, .. } => {
if entry_mode.is_no_tree() {
files.removed += 1;
remove_lines(line_stats, &lines_count, &mut lines, id);
Expand All @@ -151,6 +152,7 @@ pub fn spawn_tree_delta_threads<'scope>(
previous_entry_mode,
id,
previous_id,
..
} => match (previous_entry_mode.is_blob(), entry_mode.is_blob()) {
(false, false) => {}
(false, true) => {
Expand Down
4 changes: 2 additions & 2 deletions gitoxide-core/src/hours/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pub struct WorkByPerson {
pub lines: LineStats,
}

impl<'a> WorkByPerson {
pub fn merge(&mut self, other: &'a WorkByEmail) {
impl WorkByPerson {
pub fn merge(&mut self, other: &WorkByEmail) {
if !self.name.contains(&other.name) {
self.name.push(other.name);
}
Expand Down
44 changes: 26 additions & 18 deletions gitoxide-core/src/query/engine/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,34 +207,36 @@ pub fn update(
rewrite_cache.clear_resource_cache_keep_allocation();
diff_cache.clear_resource_cache_keep_allocation();
from.changes()?
.track_path()
.track_rewrites(Some(rewrites))
.options(|opts| {
opts.track_path().track_rewrites(Some(rewrites));
})
.for_each_to_obtain_tree_with_cache(&to, &mut rewrite_cache, |change| {
use gix::object::tree::diff::change::Event::*;
use gix::object::tree::diff::Change::*;
change_counter.fetch_add(1, Ordering::SeqCst);
match change.event {
Addition { entry_mode, id } => {
match change {
Addition {
entry_mode,
id,
location,
..
} => {
if entry_mode.is_blob_or_symlink() {
add_lines(&mut out, change.location, &lines_counter, id);
add_lines(&mut out, location, &lines_counter, id);
}
}
Modification {
entry_mode,
previous_entry_mode,
id,
previous_id,
location,
} => match (previous_entry_mode.is_blob(), entry_mode.is_blob()) {
(false, false) => {}
(false, true) => {
add_lines(&mut out, change.location, &lines_counter, id);
add_lines(&mut out, location, &lines_counter, id);
}
(true, false) => {
add_lines(
&mut out,
change.location,
&lines_counter,
previous_id,
);
add_lines(&mut out, location, &lines_counter, previous_id);
}
(true, true) => {
if let Ok(cache) =
Expand Down Expand Up @@ -266,7 +268,7 @@ pub fn update(
lines_counter
.fetch_add(nl, Ordering::SeqCst);
out.push(FileChange {
relpath: change.location.to_owned(),
relpath: location.to_owned(),
mode: FileMode::Modified,
source_relpath: None,
lines: Some(lines),
Expand All @@ -281,19 +283,25 @@ pub fn update(
}
}
},
Deletion { entry_mode, id } => {
Deletion {
entry_mode,
id,
location,
..
} => {
if entry_mode.is_blob_or_symlink() {
remove_lines(&mut out, change.location, &lines_counter, id);
remove_lines(&mut out, location, &lines_counter, id);
}
}
Rewrite {
source_location,
diff,
copy,
location,
..
} => {
out.push(FileChange {
relpath: change.location.to_owned(),
relpath: location.to_owned(),
source_relpath: Some(source_location.to_owned()),
mode: if copy { FileMode::Copy } else { FileMode::Rename },
lines: diff.map(|d| LineStats {
Expand Down Expand Up @@ -369,7 +377,7 @@ pub fn update(
}
}

impl<'a, Find> gix::prelude::Find for Db<'a, Find>
impl<Find> gix::prelude::Find for Db<'_, Find>
where
Find: gix::prelude::Find + Clone,
{
Expand Down
8 changes: 4 additions & 4 deletions gitoxide-core/src/repository/revision/explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl<'a> Explain<'a> {
}
}

impl<'a> delegate::Revision for Explain<'a> {
impl delegate::Revision for Explain<'_> {
fn find_ref(&mut self, name: &BStr) -> Option<()> {
self.prefix()?;
self.ref_name = Some(name.into());
Expand Down Expand Up @@ -121,7 +121,7 @@ impl<'a> delegate::Revision for Explain<'a> {
}
}

impl<'a> delegate::Navigate for Explain<'a> {
impl delegate::Navigate for Explain<'_> {
fn traverse(&mut self, kind: Traversal) -> Option<()> {
self.prefix()?;
let name = self.revision_name();
Expand Down Expand Up @@ -194,7 +194,7 @@ impl<'a> delegate::Navigate for Explain<'a> {
}
}

impl<'a> delegate::Kind for Explain<'a> {
impl delegate::Kind for Explain<'_> {
fn kind(&mut self, kind: spec::Kind) -> Option<()> {
self.prefix()?;
self.call = 0;
Expand All @@ -215,7 +215,7 @@ impl<'a> delegate::Kind for Explain<'a> {
}
}

impl<'a> Delegate for Explain<'a> {
impl Delegate for Explain<'_> {
fn done(&mut self) {
if !self.has_implicit_anchor && self.ref_name.is_none() && self.oid_prefix.is_none() {
self.err = Some("Incomplete specification lacks its anchor, like a reference or object name".into());
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ mod entries {
}
}

impl<'repo, 'a> gix::traverse::tree::Visit for Traverse<'repo, 'a> {
impl gix::traverse::tree::Visit for Traverse<'_, '_> {
fn pop_front_tracked_path_and_set_current(&mut self) {
self.path = self.path_deque.pop_front().expect("every parent is set only once");
}
Expand Down
2 changes: 1 addition & 1 deletion gix-actor/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ mod write {
}
}

impl<'a> IdentityRef<'a> {
impl IdentityRef<'_> {
/// Serialize this instance to `out` in the git serialization format for signatures (but without timestamp).
pub fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> {
out.write_all(validated_token(self.name)?)?;
Expand Down
2 changes: 1 addition & 1 deletion gix-actor/src/signature/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub(crate) mod write {
}
}

impl<'a> SignatureRef<'a> {
impl SignatureRef<'_> {
/// Serialize this instance to `out` in the git serialization format for actors.
pub fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> {
out.write_all(validated_token(self.name)?)?;
Expand Down
2 changes: 1 addition & 1 deletion gix-attributes/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{Name, NameRef};
use bstr::{BStr, BString, ByteSlice};
use kstring::KStringRef;

impl<'a> NameRef<'a> {
impl NameRef<'_> {
/// Turn this ref into its owned counterpart.
pub fn to_owned(self) -> Name {
Name(self.0.into())
Expand Down
2 changes: 1 addition & 1 deletion gix-attributes/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl<'a> StateRef<'a> {
}

/// Access
impl<'a> StateRef<'a> {
impl StateRef<'_> {
/// Turn ourselves into our owned counterpart.
pub fn to_owned(self) -> State {
self.into()
Expand Down
Loading
Loading