From 3bab236d3233bd7e87ce5cb85843b8916fabfd75 Mon Sep 17 00:00:00 2001 From: AmrDeveloper Date: Sat, 4 Jan 2025 12:14:37 +0100 Subject: [PATCH] Issue #139: Add support for Copy mode and improve the structure of DataProvider --- docs/structure/tables.md | 16 +-- src/gitql/gitql_data_provider.rs | 219 ++----------------------------- src/gitql/values/diff_changes.rs | 99 ++++++++++++-- 3 files changed, 106 insertions(+), 228 deletions(-) diff --git a/docs/structure/tables.md b/docs/structure/tables.md index 1b864b3..97b5968 100644 --- a/docs/structure/tables.md +++ b/docs/structure/tables.md @@ -55,14 +55,14 @@ show tables ## Diffs Changes table -| Name | Type | Description | -| ---------- | ------- | ------------------------------------------------------------------------ | -| commit_id | Text | Commit id | -| insertions | Integer | Number of inserted lines in one change | -| removals | Integer | Number of deleted lines in one change | -| mode | Text | Change mode A for Add, D for Delete, M for Modification or R for Rewrite | -| path | Text | Location of the change | -| repo | Text | Repository full path | +| Name | Type | Description | +| ---------- | ------- | ------------------------------------------------------------------------------------ | +| commit_id | Text | Commit id | +| insertions | Integer | Number of inserted lines in one change | +| removals | Integer | Number of deleted lines in one change | +| mode | Text | Change mode A for Add, D for Delete, M for Modification, C for Copy or R for Rewrite | +| path | Text | Location of the change | +| repo | Text | Repository full path | --- diff --git a/src/gitql/gitql_data_provider.rs b/src/gitql/gitql_data_provider.rs index 836a90a..6799eee 100644 --- a/src/gitql/gitql_data_provider.rs +++ b/src/gitql/gitql_data_provider.rs @@ -10,12 +10,9 @@ use gitql_core::values::text::TextValue; use gitql_engine::data_provider::DataProvider; use gix::diff::blob::pipeline::Mode; -use gix::object::tree::diff::Change; use gix::refs::Category; use super::values::diff_changes::DiffChange; -use super::values::diff_changes::DiffChangeInfo; -use super::values::diff_changes::DiffChangeKind; use super::values::diff_changes::DiffChangesValue; pub struct GitQLDataProvider { @@ -341,115 +338,11 @@ fn select_diffs(repo: &gix::Repository, selected_columns: &[String]) -> Result { - let mut diff_change = DiffChange::new(DiffChangeKind::Addition); - diff_change.location = location.to_string(); - if let Ok(object) = repo.find_object(id) { - if let Ok(blob) = object.try_into_blob() { - diff_change.content = blob.data.clone(); - } - } - - if let Ok(mut platform) = change.diff(&mut diff_cache) { - if let Ok(Some(counts)) = platform.line_counts() { - diff_change.insertions += counts.insertions; - diff_change.removals += counts.removals; - } - } - - insertions += diff_change.insertions; - removals += diff_change.removals; - diff_changes.push(diff_change); - } - Change::Deletion { - location, - entry_mode: _, - relation: _, - id, - } => { - let mut diff_change = DiffChange::new(DiffChangeKind::Deletion); - diff_change.location = location.to_string(); - if let Ok(object) = repo.find_object(id) { - if let Ok(blob) = object.try_into_blob() { - diff_change.content = blob.data.clone(); - } - } - - if let Ok(mut platform) = change.diff(&mut diff_cache) { - if let Ok(Some(counts)) = platform.line_counts() { - diff_change.insertions += counts.insertions; - diff_change.removals += counts.removals; - } - } - - insertions += diff_change.insertions; - removals += diff_change.removals; - diff_changes.push(diff_change); - } - Change::Modification { - location, - previous_entry_mode: _, - previous_id: _, - entry_mode: _, - id, - } => { - let mut diff_change = - DiffChange::new(DiffChangeKind::Modification); - diff_change.location = location.to_string(); - if let Ok(object) = repo.find_object(id) { - if let Ok(blob) = object.try_into_blob() { - diff_change.content = blob.data.clone(); - } - } - - if let Ok(mut platform) = change.diff(&mut diff_cache) { - if let Ok(Some(counts)) = platform.line_counts() { - diff_change.insertions += counts.insertions; - diff_change.removals += counts.removals; - } - } - - insertions += diff_change.insertions; - removals += diff_change.removals; - diff_changes.push(diff_change); - } - Change::Rewrite { - source_location: _, - source_relation: _, - source_entry_mode: _, - source_id: _, - diff, - entry_mode: _, - location, - id, - relation: _, - copy: _, - } => { - let mut diff_change = DiffChange::new(DiffChangeKind::Rewrite); - diff_change.location = location.to_string(); - if let Ok(object) = repo.find_object(id) { - if let Ok(blob) = object.try_into_blob() { - diff_change.content = blob.data.clone(); - } - } - - if let Some(diff_line_stats) = diff { - diff_change.insertions += diff_line_stats.insertions; - diff_change.removals += diff_line_stats.removals; - - insertions += diff_line_stats.insertions; - removals += diff_line_stats.removals; - } - - diff_changes.push(diff_change); - } - } + let diff_change = + DiffChange::new_with_content(&change, &mut diff_cache, &repo); + insertions += diff_change.insertions; + removals += diff_change.removals; + diff_changes.push(diff_change); Ok::<_, Infallible>(Default::default()) }, ); @@ -559,101 +452,7 @@ fn select_diffs_changes( &parent, &mut rewrite_cache, |change| { - let diff_change = match change { - Change::Addition { - location, - entry_mode: _, - relation: _, - id: _, - } => { - let mut change_info = DiffChangeInfo { - path: location.to_string(), - insertions: 0, - removals: 0, - mode: 'A', - }; - - if let Ok(mut platform) = change.diff(&mut diff_cache) { - if let Ok(Some(counts)) = platform.line_counts() { - change_info.insertions += counts.insertions; - change_info.removals += counts.removals; - } - } - - change_info - } - Change::Deletion { - location, - entry_mode: _, - relation: _, - id: _, - } => { - let mut change_info = DiffChangeInfo { - path: location.to_string(), - insertions: 0, - removals: 0, - mode: 'D', - }; - - if let Ok(mut platform) = change.diff(&mut diff_cache) { - if let Ok(Some(counts)) = platform.line_counts() { - change_info.insertions += counts.insertions; - change_info.removals += counts.removals; - } - } - - change_info - } - Change::Modification { - location, - previous_entry_mode: _, - previous_id: _, - entry_mode: _, - id: _, - } => { - let mut change_info = DiffChangeInfo { - path: location.to_string(), - insertions: 0, - removals: 0, - mode: 'M', - }; - - if let Ok(mut platform) = change.diff(&mut diff_cache) { - if let Ok(Some(counts)) = platform.line_counts() { - change_info.insertions += counts.insertions; - change_info.removals += counts.removals; - } - } - - change_info - } - Change::Rewrite { - source_location: _, - source_relation: _, - source_entry_mode: _, - source_id: _, - diff, - entry_mode: _, - location, - id: _, - relation: _, - copy: _, - } => { - let mut change_info = DiffChangeInfo { - path: location.to_string(), - insertions: 0, - removals: 0, - mode: 'R', - }; - - if let Some(diff_line_stats) = diff { - change_info.insertions += diff_line_stats.insertions; - change_info.removals += diff_line_stats.removals; - } - - change_info - } - }; + let diff_change = DiffChange::new_without_content(&change, &mut diff_cache); let mut values: Vec> = Vec::with_capacity(selected_columns_len); @@ -674,12 +473,14 @@ fn select_diffs_changes( } if column_name == "mode" { - values.push(Box::new(TextValue::new(diff_change.mode.to_string()))); + let mode = diff_change.kind.mode().to_string(); + values.push(Box::new(TextValue::new(mode))); continue; } if column_name == "path" { - values.push(Box::new(TextValue::new(diff_change.path.to_string()))); + let path = diff_change.location.to_string(); + values.push(Box::new(TextValue::new(path))); continue; } diff --git a/src/gitql/values/diff_changes.rs b/src/gitql/values/diff_changes.rs index f51257c..fa3bf4a 100644 --- a/src/gitql/values/diff_changes.rs +++ b/src/gitql/values/diff_changes.rs @@ -3,6 +3,9 @@ use std::cmp::Ordering; use gitql_ast::types::base::DataType; use gitql_core::values::base::Value; +use gix::diff::blob::Platform; +use gix::object::tree::diff::Change; +use gix::Repository; use crate::gitql::types::diff_changes::DiffChangesType; @@ -12,6 +15,45 @@ pub enum DiffChangeKind { Deletion, Modification, Rewrite, + Copy, +} + +impl DiffChangeKind { + pub fn from(change: &Change) -> Self { + match change { + Change::Addition { .. } => DiffChangeKind::Addition, + Change::Deletion { .. } => DiffChangeKind::Deletion, + Change::Modification { .. } => DiffChangeKind::Modification, + Change::Rewrite { + source_location: _, + source_relation: _, + source_entry_mode: _, + source_id: _, + diff: _, + entry_mode: _, + location: _, + id: _, + relation: _, + copy, + } => { + if *copy { + DiffChangeKind::Rewrite + } else { + DiffChangeKind::Copy + } + } + } + } + + pub fn mode(&self) -> char { + match self { + DiffChangeKind::Addition => 'A', + DiffChangeKind::Deletion => 'D', + DiffChangeKind::Modification => 'M', + DiffChangeKind::Rewrite => 'R', + DiffChangeKind::Copy => 'C', + } + } } #[derive(Clone)] @@ -23,23 +65,58 @@ pub struct DiffChange { pub kind: DiffChangeKind, } -pub(crate) struct DiffChangeInfo { - pub(crate) path: String, - pub(crate) insertions: u32, - pub(crate) removals: u32, - pub(crate) mode: char, -} - impl DiffChange { - pub fn new(kind: DiffChangeKind) -> Self { + pub fn new_without_content(change: &Change, diff_cache: &mut Platform) -> Self { + let location = change.location().to_string(); + let kind = DiffChangeKind::from(change); + + let (mut insertions, mut removals) = (0, 0); + match change { + Change::Rewrite { + source_location: _, + source_relation: _, + source_entry_mode: _, + source_id: _, + diff, + entry_mode: _, + location: _, + id: _, + relation: _, + copy: _, + } => { + if let Some(diff_line_stats) = diff { + insertions = diff_line_stats.insertions; + removals = diff_line_stats.removals; + } + } + _ => { + if let Ok(mut platform) = change.diff(diff_cache) { + if let Ok(Some(counts)) = platform.line_counts() { + insertions = counts.insertions; + removals = counts.removals; + } + }; + } + } + DiffChange { - location: String::default(), + location, content: vec![], - insertions: 0, - removals: 0, + insertions, + removals, kind, } } + + pub fn new_with_content(change: &Change, diff_cache: &mut Platform, repo: &Repository) -> Self { + let mut diff_change = DiffChange::new_without_content(change, diff_cache); + if let Ok(object) = repo.find_object(change.id()) { + if let Ok(blob) = object.try_into_blob() { + diff_change.content = blob.data.clone() + } + } + diff_change + } } #[derive(Clone)]