Skip to content
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

more merge features #1661

Merged
merged 12 commits into from
Nov 24, 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
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.

7 changes: 5 additions & 2 deletions crate-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ Check out the [performance discussion][gix-diff-performance] as well.
* [x] find blobs by similarity check
* [ ] heuristics to find best candidate
* [ ] find by basename to support similarity check
- Not having it can lead to issues when files with the same or similar content are part of a move
as files can be lost that way.
* [x] directory tracking
- [x] by identity
- [ ] by similarity
Expand Down Expand Up @@ -349,9 +351,9 @@ Check out the [performance discussion][gix-diff-performance] as well.
- [ ] various newlines-related options during the merge (see https://git-scm.com/docs/git-merge#Documentation/git-merge.txt-ignore-space-change).
- [ ] a way to control inter-hunk merging based on proximity (maybe via `gix-diff` feature which could use the same)
* [x] **tree**-diff-heuristics match Git for its test-cases
- [ ] a way to generate an index with stages
- *currently the data it provides won't generate index entries, and possibly can't be used for it yet*
- [x] a way to generate an index with stages, mostly conforming with Git.
- [ ] submodule merges (*right now they count as conflicts if they differ*)
- [ ] assure sparse indices are handled correctly during application - right now we refuse.
* [x] **commits** - with handling of multiple merge bases by recursive merge-base merge
* [x] API documentation
* [ ] Examples
Expand Down Expand Up @@ -462,6 +464,7 @@ Check out the [performance discussion][gix-traverse-performance] as well.
* [x] delegate can support for all fetch features, including shallow, deepen, etc.
* [x] receive parsed shallow refs
* [ ] push
* [ ] remote helper protocol and integration
* [x] API documentation
* [ ] Some examples

Expand Down
8 changes: 6 additions & 2 deletions gitoxide-core/src/repository/merge/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::OutputFormat;
use anyhow::{anyhow, bail, Context};
use gix::bstr::BString;
use gix::bstr::ByteSlice;
use gix::merge::tree::UnresolvedConflict;
use gix::merge::tree::TreatAsUnresolved;
use gix::prelude::Write;

use super::tree::Options;
Expand All @@ -18,6 +18,7 @@ pub fn commit(
format,
file_favor,
in_memory,
debug,
}: Options,
) -> anyhow::Result<()> {
if format != OutputFormat::Human {
Expand Down Expand Up @@ -48,7 +49,7 @@ pub fn commit(
.merge_commits(ours_id, theirs_id, labels, options.into())?
.tree_merge;
let has_conflicts = res.conflicts.is_empty();
let has_unresolved_conflicts = res.has_unresolved_conflicts(UnresolvedConflict::Renames);
let has_unresolved_conflicts = res.has_unresolved_conflicts(TreatAsUnresolved::Renames);
{
let _span = gix::trace::detail!("Writing merged tree");
let mut written = 0;
Expand All @@ -63,6 +64,9 @@ pub fn commit(
writeln!(out, "{tree_id} (wrote {written} trees)")?;
}

if debug {
writeln!(err, "{:#?}", &res.conflicts)?;
}
if !has_conflicts {
writeln!(err, "{} possibly resolved conflicts", res.conflicts.len())?;
}
Expand Down
9 changes: 7 additions & 2 deletions gitoxide-core/src/repository/merge/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub struct Options {
pub format: OutputFormat,
pub file_favor: Option<gix::merge::tree::FileFavor>,
pub in_memory: bool,
pub debug: bool,
}

pub(super) mod function {
Expand All @@ -12,7 +13,7 @@ pub(super) mod function {
use anyhow::{anyhow, bail, Context};
use gix::bstr::BString;
use gix::bstr::ByteSlice;
use gix::merge::tree::UnresolvedConflict;
use gix::merge::tree::TreatAsUnresolved;
use gix::prelude::Write;

use super::Options;
Expand All @@ -29,6 +30,7 @@ pub(super) mod function {
format,
file_favor,
in_memory,
debug,
}: Options,
) -> anyhow::Result<()> {
if format != OutputFormat::Human {
Expand Down Expand Up @@ -62,7 +64,7 @@ pub(super) mod function {
};
let res = repo.merge_trees(base_id, ours_id, theirs_id, labels, options)?;
let has_conflicts = res.conflicts.is_empty();
let has_unresolved_conflicts = res.has_unresolved_conflicts(UnresolvedConflict::Renames);
let has_unresolved_conflicts = res.has_unresolved_conflicts(TreatAsUnresolved::Renames);
{
let _span = gix::trace::detail!("Writing merged tree");
let mut written = 0;
Expand All @@ -77,6 +79,9 @@ pub(super) mod function {
writeln!(out, "{tree_id} (wrote {written} trees)")?;
}

if debug {
writeln!(err, "{:#?}", &res.conflicts)?;
}
if !has_conflicts {
writeln!(err, "{} possibly resolved conflicts", res.conflicts.len())?;
}
Expand Down
2 changes: 1 addition & 1 deletion gix-diff/src/tree/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ fn handle_lhs_and_rhs_with_equal_filenames(
(false, false) => {
delegate.push_path_component(lhs.filename);
debug_assert!(lhs.mode.is_no_tree() && lhs.mode.is_no_tree());
if lhs.oid != rhs.oid
if (lhs.oid != rhs.oid || lhs.mode != rhs.mode)
&& delegate
.visit(Change::Modification {
previous_entry_mode: lhs.mode,
Expand Down
56 changes: 56 additions & 0 deletions gix-diff/src/tree_with_rewrites/change.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,34 @@ impl<'a> ChangeRef<'a> {
}
}

/// Return the current mode of this instance, along with its object id.
pub fn entry_mode_and_id(&self) -> (gix_object::tree::EntryMode, &gix_hash::oid) {
match self {
ChangeRef::Addition { entry_mode, id, .. }
| ChangeRef::Deletion { entry_mode, id, .. }
| ChangeRef::Modification { entry_mode, id, .. }
| ChangeRef::Rewrite { entry_mode, id, .. } => (*entry_mode, id),
}
}

/// Return the *previous* mode and id of the resource where possible, i.e. the source of a rename or copy, or a modification.
pub fn source_entry_mode_and_id(&self) -> (gix_object::tree::EntryMode, &gix_hash::oid) {
match self {
ChangeRef::Addition { entry_mode, id, .. }
| ChangeRef::Deletion { entry_mode, id, .. }
| ChangeRef::Modification {
previous_entry_mode: entry_mode,
previous_id: id,
..
}
| ChangeRef::Rewrite {
source_entry_mode: entry_mode,
source_id: id,
..
} => (*entry_mode, id),
}
}

/// Return the *current* location of the resource, i.e. the destination of a rename or copy, or the
/// location at which an addition, deletion or modification took place.
pub fn location(&self) -> &'a BStr {
Expand Down Expand Up @@ -478,6 +506,34 @@ impl Change {
}
}

/// Return the current mode of this instance, along with its object id.
pub fn entry_mode_and_id(&self) -> (gix_object::tree::EntryMode, &gix_hash::oid) {
match self {
Change::Addition { entry_mode, id, .. }
| Change::Deletion { entry_mode, id, .. }
| Change::Modification { entry_mode, id, .. }
| Change::Rewrite { entry_mode, id, .. } => (*entry_mode, id),
}
}

/// Return the *previous* mode and id of the resource where possible, i.e. the source of a rename or copy, or a modification.
pub fn source_entry_mode_and_id(&self) -> (gix_object::tree::EntryMode, &gix_hash::oid) {
match self {
Change::Addition { entry_mode, id, .. }
| Change::Deletion { entry_mode, id, .. }
| Change::Modification {
previous_entry_mode: entry_mode,
previous_id: id,
..
}
| Change::Rewrite {
source_entry_mode: entry_mode,
source_id: id,
..
} => (*entry_mode, id),
}
}

/// Return the *current* location of the resource, i.e. the destination of a rename or copy, or the
/// location at which an addition, deletion or modification took place.
pub fn location(&self) -> &BStr {
Expand Down
Loading
Loading