diff --git a/gix-status/src/index_as_worktree/function.rs b/gix-status/src/index_as_worktree/function.rs index 1affadb1c22..c6edc032d69 100644 --- a/gix-status/src/index_as_worktree/function.rs +++ b/gix-status/src/index_as_worktree/function.rs @@ -397,7 +397,14 @@ impl<'index> State<'_, 'index> { .mode .change_to_match_fs(&metadata, self.options.fs.symlink, self.options.fs.executable_bit) { - Some(gix_index::entry::mode::Change::Type { .. }) => return Ok(Some(Change::Type.into())), + Some(gix_index::entry::mode::Change::Type { new_mode }) => { + return Ok(Some( + Change::Type { + worktree_mode: new_mode, + } + .into(), + )) + } Some(gix_index::entry::mode::Change::ExecutableBit) => true, None => false, }; diff --git a/gix-status/src/index_as_worktree/types.rs b/gix-status/src/index_as_worktree/types.rs index 80554a77f38..f38f131e74d 100644 --- a/gix-status/src/index_as_worktree/types.rs +++ b/gix-status/src/index_as_worktree/types.rs @@ -111,7 +111,11 @@ pub enum Change { /// /// A change to a non-file is marked as `modification` in Git, but that's related to the content which we can't evaluate. /// Hence, a type-change is considered more appropriate. - Type, + Type { + /// The mode the worktree file would have if it was added to the index, and the mode that differs compared + /// to what's currently stored in the index. + worktree_mode: gix_index::entry::Mode, + }, /// This worktree file was modified in some form, like a permission change or content change or both, /// as compared to this entry. Modification { diff --git a/gix-status/src/index_as_worktree_with_renames/mod.rs b/gix-status/src/index_as_worktree_with_renames/mod.rs index 6ce99b1a7bf..8368102c246 100644 --- a/gix-status/src/index_as_worktree_with_renames/mod.rs +++ b/gix-status/src/index_as_worktree_with_renames/mod.rs @@ -455,7 +455,7 @@ pub(super) mod function { } EntryStatus::Change(c) => match c { Change::Removed => ChangeKind::Deletion, - Change::Type | Change::Modification { .. } | Change::SubmoduleModification(_) => { + Change::Type { .. } | Change::Modification { .. } | Change::SubmoduleModification(_) => { ChangeKind::Modification } }, diff --git a/gix-status/src/index_as_worktree_with_renames/types.rs b/gix-status/src/index_as_worktree_with_renames/types.rs index dbfdefc8a98..ccf17feaf0f 100644 --- a/gix-status/src/index_as_worktree_with_renames/types.rs +++ b/gix-status/src/index_as_worktree_with_renames/types.rs @@ -230,7 +230,7 @@ impl Entry<'_, ContentChange, SubmoduleStatus> { .. } => match change { Change::SubmoduleModification(_) | Change::Modification { .. } => Summary::Modified, - Change::Type => Summary::TypeChange, + Change::Type { .. } => Summary::TypeChange, Change::Removed => Summary::Removed, }, Entry::DirectoryContents { entry, .. } => { diff --git a/gix-status/tests/status/index_as_worktree.rs b/gix-status/tests/status/index_as_worktree.rs index 3544aedccfc..ff5e7ee5668 100644 --- a/gix-status/tests/status/index_as_worktree.rs +++ b/gix-status/tests/status/index_as_worktree.rs @@ -7,7 +7,7 @@ use bstr::BStr; use filetime::{set_file_mtime, FileTime}; use gix_filter::eol::AutoCrlf; use gix_index as index; -use gix_index::Entry; +use gix_index::{entry, Entry}; use gix_status::index_as_worktree::Context; use gix_status::{ index_as_worktree, @@ -231,7 +231,7 @@ fn deracify_status(status: EntryStatus) -> Option { EntryStatus::Conflict(c) => EntryStatus::Conflict(c), EntryStatus::Change(c) => match c { Change::Removed => Change::Removed, - Change::Type => Change::Type, + Change::Type { worktree_mode } => Change::Type { worktree_mode }, Change::Modification { executable_bit_changed, content_change, @@ -284,7 +284,17 @@ fn nonfile_untracked_are_not_visible() { #[test] #[cfg(unix)] fn tracked_changed_to_non_file() { - nonfile_fixture("tracked-swapped", &[(BStr::new(b"file"), 0, Change::Type.into())]); + nonfile_fixture( + "tracked-swapped", + &[( + BStr::new(b"file"), + 0, + Change::Type { + worktree_mode: entry::Mode::FILE, + } + .into(), + )], + ); } #[test] @@ -384,7 +394,17 @@ fn subomdule_deleted_dir() { #[test] fn subomdule_typechange() { assert_eq!( - submodule_fixture("type-change", &[(BStr::new(b"m1"), 1, Change::Type.into())]), + submodule_fixture( + "type-change", + &[( + BStr::new(b"m1"), + 1, + Change::Type { + worktree_mode: entry::Mode::FILE + } + .into() + )] + ), Outcome { entries_to_process: 2, entries_processed: 2, @@ -596,7 +616,14 @@ fn refresh() { } .into(), ), - (BStr::new(b"empty"), 3, Change::Type.into()), + ( + BStr::new(b"empty"), + 3, + Change::Type { + worktree_mode: entry::Mode::FILE + } + .into() + ), ( BStr::new(b"executable"), 4, @@ -620,7 +647,14 @@ fn refresh() { } .into(), ), - (BStr::new("empty"), 3, Change::Type.into()), + ( + BStr::new("empty"), + 3, + Change::Type { + worktree_mode: entry::Mode::FILE + } + .into() + ), ( BStr::new("executable"), 4, @@ -669,7 +703,14 @@ fn modified() { } .into(), ), - (BStr::new(b"empty"), 3, Change::Type.into()), + ( + BStr::new(b"empty"), + 3, + Change::Type { + worktree_mode: entry::Mode::FILE, + } + .into(), + ), ( BStr::new(b"executable"), 4, @@ -693,7 +734,14 @@ fn modified() { } .into(), ), - (BStr::new("empty"), 3, Change::Type.into()), + ( + BStr::new("empty"), + 3, + Change::Type { + worktree_mode: entry::Mode::FILE, + } + .into(), + ), ( BStr::new("executable"), 4, diff --git a/gix-status/tests/status/index_as_worktree_with_renames.rs b/gix-status/tests/status/index_as_worktree_with_renames.rs index 5ed86f41213..468cbf4322b 100644 --- a/gix-status/tests/status/index_as_worktree_with_renames.rs +++ b/gix-status/tests/status/index_as_worktree_with_renames.rs @@ -2,6 +2,7 @@ use crate::fixture_path; use bstr::ByteSlice; use gix_diff::blob::pipeline::WorktreeRoots; use gix_diff::rewrites::CopySource; +use gix_index::entry; use gix_status::index_as_worktree::traits::FastEq; use gix_status::index_as_worktree::{Change, EntryStatus}; use gix_status::index_as_worktree_with_renames; @@ -123,7 +124,10 @@ fn tracked_changed_to_non_file() { &[], &[Expectation::Modification { rela_path: "file", - status: Change::Type.into(), + status: Change::Type { + worktree_mode: entry::Mode::FILE, + } + .into(), }], None, Some(Default::default()), @@ -393,7 +397,7 @@ impl Expectation<'_> { EntryStatus::Conflict(_) => Summary::Conflict, EntryStatus::Change(change) => match change { Change::Removed => Summary::Removed, - Change::Type => Summary::TypeChange, + Change::Type { .. } => Summary::TypeChange, Change::Modification { .. } | Change::SubmoduleModification(_) => Summary::Modified, }, EntryStatus::NeedsUpdate(_) => return None,