|
1 | 1 | use std::num::NonZeroU32; |
2 | 2 |
|
3 | | -use gix_diff::{ |
4 | | - blob::{intern::TokenSource, v2::Hunk}, |
5 | | - tree::Visit, |
6 | | -}; |
| 3 | +#[cfg(feature = "blob-experimental")] |
| 4 | +use gix_diff::blob::v2::Hunk; |
| 5 | + |
| 6 | +use gix_diff::{blob::intern::TokenSource, tree::Visit}; |
7 | 7 | use gix_hash::ObjectId; |
8 | 8 | use gix_object::{ |
9 | 9 | bstr::{BStr, BString}, |
@@ -751,6 +751,102 @@ fn tree_diff_with_rewrites_at_file_path( |
751 | 751 | } |
752 | 752 |
|
753 | 753 | #[allow(clippy::too_many_arguments)] |
| 754 | +#[cfg(not(feature = "blob-experimental"))] |
| 755 | +fn blob_changes( |
| 756 | + odb: impl gix_object::Find + gix_object::FindHeader, |
| 757 | + resource_cache: &mut gix_diff::blob::Platform, |
| 758 | + oid: ObjectId, |
| 759 | + previous_oid: ObjectId, |
| 760 | + file_path: &BStr, |
| 761 | + previous_file_path: &BStr, |
| 762 | + diff_algorithm: gix_diff::blob::Algorithm, |
| 763 | + stats: &mut Statistics, |
| 764 | +) -> Result<Vec<Change>, Error> { |
| 765 | + /// Record all [`Change`]s to learn about additions, deletions and unchanged portions of a *Source File*. |
| 766 | + struct ChangeRecorder { |
| 767 | + last_seen_after_end: u32, |
| 768 | + hunks: Vec<Change>, |
| 769 | + total_number_of_lines: u32, |
| 770 | + } |
| 771 | + |
| 772 | + impl ChangeRecorder { |
| 773 | + /// `total_number_of_lines` is used to fill in the last unchanged hunk if needed |
| 774 | + /// so that the entire file is represented by [`Change`]. |
| 775 | + fn new(total_number_of_lines: u32) -> Self { |
| 776 | + ChangeRecorder { |
| 777 | + last_seen_after_end: 0, |
| 778 | + hunks: Vec::new(), |
| 779 | + total_number_of_lines, |
| 780 | + } |
| 781 | + } |
| 782 | + } |
| 783 | + |
| 784 | + use std::ops::Range; |
| 785 | + |
| 786 | + impl gix_diff::blob::Sink for ChangeRecorder { |
| 787 | + type Out = Vec<Change>; |
| 788 | + |
| 789 | + fn process_change(&mut self, before: Range<u32>, after: Range<u32>) { |
| 790 | + // This checks for unchanged hunks. |
| 791 | + if after.start > self.last_seen_after_end { |
| 792 | + self.hunks |
| 793 | + .push(Change::Unchanged(self.last_seen_after_end..after.start)); |
| 794 | + } |
| 795 | + |
| 796 | + match (!before.is_empty(), !after.is_empty()) { |
| 797 | + (_, true) => { |
| 798 | + self.hunks.push(Change::AddedOrReplaced( |
| 799 | + after.start..after.end, |
| 800 | + before.end - before.start, |
| 801 | + )); |
| 802 | + } |
| 803 | + (true, false) => { |
| 804 | + self.hunks.push(Change::Deleted(after.start, before.end - before.start)); |
| 805 | + } |
| 806 | + (false, false) => unreachable!("BUG: imara-diff provided a non-change"), |
| 807 | + } |
| 808 | + self.last_seen_after_end = after.end; |
| 809 | + } |
| 810 | + |
| 811 | + fn finish(mut self) -> Self::Out { |
| 812 | + if self.total_number_of_lines > self.last_seen_after_end { |
| 813 | + self.hunks |
| 814 | + .push(Change::Unchanged(self.last_seen_after_end..self.total_number_of_lines)); |
| 815 | + } |
| 816 | + self.hunks |
| 817 | + } |
| 818 | + } |
| 819 | + |
| 820 | + resource_cache.set_resource( |
| 821 | + previous_oid, |
| 822 | + gix_object::tree::EntryKind::Blob, |
| 823 | + previous_file_path, |
| 824 | + gix_diff::blob::ResourceKind::OldOrSource, |
| 825 | + &odb, |
| 826 | + )?; |
| 827 | + resource_cache.set_resource( |
| 828 | + oid, |
| 829 | + gix_object::tree::EntryKind::Blob, |
| 830 | + file_path, |
| 831 | + gix_diff::blob::ResourceKind::NewOrDestination, |
| 832 | + &odb, |
| 833 | + )?; |
| 834 | + |
| 835 | + let outcome = resource_cache.prepare_diff()?; |
| 836 | + let input = gix_diff::blob::intern::InternedInput::new( |
| 837 | + tokens_for_diffing(outcome.old.data.as_slice().unwrap_or_default()), |
| 838 | + tokens_for_diffing(outcome.new.data.as_slice().unwrap_or_default()), |
| 839 | + ); |
| 840 | + let number_of_lines_in_destination = input.after.len(); |
| 841 | + let change_recorder = ChangeRecorder::new(number_of_lines_in_destination as u32); |
| 842 | + |
| 843 | + let res = gix_diff::blob::diff(diff_algorithm, &input, change_recorder); |
| 844 | + stats.blobs_diffed += 1; |
| 845 | + Ok(res) |
| 846 | +} |
| 847 | + |
| 848 | +#[allow(clippy::too_many_arguments)] |
| 849 | +#[cfg(feature = "blob-experimental")] |
754 | 850 | fn blob_changes( |
755 | 851 | odb: impl gix_object::Find + gix_object::FindHeader, |
756 | 852 | resource_cache: &mut gix_diff::blob::Platform, |
|
0 commit comments