summaryrefslogtreecommitdiffstats
path: root/asyncgit/src/sync/staging/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'asyncgit/src/sync/staging/mod.rs')
-rw-r--r--asyncgit/src/sync/staging/mod.rs308
1 files changed, 154 insertions, 154 deletions
diff --git a/asyncgit/src/sync/staging/mod.rs b/asyncgit/src/sync/staging/mod.rs
index e2830020..1621c9d4 100644
--- a/asyncgit/src/sync/staging/mod.rs
+++ b/asyncgit/src/sync/staging/mod.rs
@@ -5,182 +5,182 @@ pub use discard_tracked::discard_lines;
pub use stage_tracked::stage_lines;
use super::{
- diff::DiffLinePosition, patches::HunkLines, utils::work_dir,
+ diff::DiffLinePosition, patches::HunkLines, utils::work_dir,
};
use crate::error::Result;
use git2::{DiffLine, DiffLineType, Repository};
use std::{
- collections::HashSet, convert::TryFrom, fs::File, io::Read,
+ collections::HashSet, convert::TryFrom, fs::File, io::Read,
};
const NEWLINE: char = '\n';
#[derive(Default)]
struct NewFromOldContent {
- lines: Vec<String>,
- old_index: usize,
+ lines: Vec<String>,
+ old_index: usize,
}
impl NewFromOldContent {
- fn add_from_hunk(&mut self, line: &DiffLine) -> Result<()> {
- let line = String::from_utf8(line.content().into())?;
-
- let line = if line.ends_with(NEWLINE) {
- line[0..line.len() - 1].to_string()
- } else {
- line
- };
-
- self.lines.push(line);
-
- Ok(())
- }
-
- fn skip_old_line(&mut self) {
- self.old_index += 1;
- }
-
- fn add_old_line(&mut self, old_lines: &[&str]) {
- self.lines.push(old_lines[self.old_index].to_string());
- self.old_index += 1;
- }
-
- fn catchup_to_hunkstart(
- &mut self,
- hunk_start: usize,
- old_lines: &[&str],
- ) {
- while hunk_start > self.old_index + 1 {
- self.add_old_line(old_lines);
- }
- }
-
- fn finish(mut self, old_lines: &[&str]) -> String {
- for line in old_lines.iter().skip(self.old_index) {
- self.lines.push((*line).to_string());
- }
- let lines = self.lines.join("\n");
- if lines.ends_with(NEWLINE) {
- lines
- } else {
- let mut lines = lines;
- lines.push(NEWLINE);
- lines
- }
- }
+ fn add_from_hunk(&mut self, line: &DiffLine) -> Result<()> {
+ let line = String::from_utf8(line.content().into())?;
+
+ let line = if line.ends_with(NEWLINE) {
+ line[0..line.len() - 1].to_string()
+ } else {
+ line
+ };
+
+ self.lines.push(line);
+
+ Ok(())
+ }
+
+ fn skip_old_line(&mut self) {
+ self.old_index += 1;
+ }
+
+ fn add_old_line(&mut self, old_lines: &[&str]) {
+ self.lines.push(old_lines[self.old_index].to_string());
+ self.old_index += 1;
+ }
+
+ fn catchup_to_hunkstart(
+ &mut self,
+ hunk_start: usize,
+ old_lines: &[&str],
+ ) {
+ while hunk_start > self.old_index + 1 {
+ self.add_old_line(old_lines);
+ }
+ }
+
+ fn finish(mut self, old_lines: &[&str]) -> String {
+ for line in old_lines.iter().skip(self.old_index) {
+ self.lines.push((*line).to_string());
+ }
+ let lines = self.lines.join("\n");
+ if lines.ends_with(NEWLINE) {
+ lines
+ } else {
+ let mut lines = lines;
+ lines.push(NEWLINE);
+ lines
+ }
+ }
}
// this is the heart of the per line discard,stage,unstage. heavily inspired by the great work in nodegit: https://github.com/nodegit/nodegit
#[allow(clippy::redundant_pub_crate)]
pub(crate) fn apply_selection(
- lines: &[DiffLinePosition],
- hunks: &[HunkLines],
- old_lines: &[&str],
- is_staged: bool,
- reverse: bool,
+ lines: &[DiffLinePosition],
+ hunks: &[HunkLines],
+ old_lines: &[&str],
+ is_staged: bool,
+ reverse: bool,
) -> Result<String> {
- let mut new_content = NewFromOldContent::default();
- let lines = lines.iter().collect::<HashSet<_>>();
-
- let added = if reverse {
- DiffLineType::Deletion
- } else {
- DiffLineType::Addition
- };
- let deleted = if reverse {
- DiffLineType::Addition
- } else {
- DiffLineType::Deletion
- };
-
- let mut first_hunk_encountered = false;
- for hunk in hunks {
- let hunk_start = if is_staged || reverse {
- usize::try_from(hunk.hunk.new_start)?
- } else {
- usize::try_from(hunk.hunk.old_start)?
- };
-
- if !first_hunk_encountered {
- let any_slection_in_hunk =
- hunk.lines.iter().any(|line| {
- let line: DiffLinePosition = line.into();
- lines.contains(&line)
- });
-
- first_hunk_encountered = any_slection_in_hunk;
- }
-
- if first_hunk_encountered {
- new_content.catchup_to_hunkstart(hunk_start, old_lines);
-
- for hunk_line in &hunk.lines {
- let hunk_line_pos: DiffLinePosition =
- hunk_line.into();
- let selected_line = lines.contains(&hunk_line_pos);
-
- log::debug!(
- // println!(
- "{} line: {} [{:?} old, {:?} new] -> {}",
- if selected_line { "*" } else { " " },
- hunk_line.origin(),
- hunk_line.old_lineno(),
- hunk_line.new_lineno(),
- String::from_utf8_lossy(hunk_line.content())
- .trim()
- );
-
- if hunk_line.origin_value()
- == DiffLineType::DeleteEOFNL
- || hunk_line.origin_value()
- == DiffLineType::AddEOFNL
- {
- break;
- }
-
- if (is_staged && !selected_line)
- || (!is_staged && selected_line)
- {
- if hunk_line.origin_value() == added {
- new_content.add_from_hunk(hunk_line)?;
- if is_staged {
- new_content.skip_old_line();
- }
- } else if hunk_line.origin_value() == deleted {
- if !is_staged {
- new_content.skip_old_line();
- }
- } else {
- new_content.add_old_line(old_lines);
- }
- } else {
- if hunk_line.origin_value() != added {
- new_content.add_from_hunk(hunk_line)?;
- }
-
- if (is_staged
- && hunk_line.origin_value() != deleted)
- || (!is_staged
- && hunk_line.origin_value() != added)
- {
- new_content.skip_old_line();
- }
- }
- }
- }
- }
-
- Ok(new_content.finish(old_lines))
+ let mut new_content = NewFromOldContent::default();
+ let lines = lines.iter().collect::<HashSet<_>>();
+
+ let added = if reverse {
+ DiffLineType::Deletion
+ } else {
+ DiffLineType::Addition
+ };
+ let deleted = if reverse {
+ DiffLineType::Addition
+ } else {
+ DiffLineType::Deletion
+ };
+
+ let mut first_hunk_encountered = false;
+ for hunk in hunks {
+ let hunk_start = if is_staged || reverse {
+ usize::try_from(hunk.hunk.new_start)?
+ } else {
+ usize::try_from(hunk.hunk.old_start)?
+ };
+
+ if !first_hunk_encountered {
+ let any_slection_in_hunk =
+ hunk.lines.iter().any(|line| {
+ let line: DiffLinePosition = line.into();
+ lines.contains(&line)
+ });
+
+ first_hunk_encountered = any_slection_in_hunk;
+ }
+
+ if first_hunk_encountered {
+ new_content.catchup_to_hunkstart(hunk_start, old_lines);
+
+ for hunk_line in &hunk.lines {
+ let hunk_line_pos: DiffLinePosition =
+ hunk_line.into();
+ let selected_line = lines.contains(&hunk_line_pos);
+
+ log::debug!(
+ // println!(
+ "{} line: {} [{:?} old, {:?} new] -> {}",
+ if selected_line { "*" } else { " " },
+ hunk_line.origin(),
+ hunk_line.old_lineno(),
+ hunk_line.new_lineno(),
+ String::from_utf8_lossy(hunk_line.content())
+ .trim()
+ );
+
+ if hunk_line.origin_value()
+ == DiffLineType::DeleteEOFNL
+ || hunk_line.origin_value()
+ == DiffLineType::AddEOFNL
+ {
+ break;
+ }
+
+ if (is_staged && !selected_line)
+ || (!is_staged && selected_line)
+ {
+ if hunk_line.origin_value() == added {
+ new_content.add_from_hunk(hunk_line)?;
+ if is_staged {
+ new_content.skip_old_line();
+ }
+ } else if hunk_line.origin_value() == deleted {
+ if !is_staged {
+ new_content.skip_old_line();
+ }
+ } else {
+ new_content.add_old_line(old_lines);
+ }
+ } else {
+ if hunk_line.origin_value() != added {
+ new_content.add_from_hunk(hunk_line)?;
+ }
+
+ if (is_staged
+ && hunk_line.origin_value() != deleted)
+ || (!is_staged
+ && hunk_line.origin_value() != added)
+ {
+ new_content.skip_old_line();
+ }
+ }
+ }
+ }
+ }
+
+ Ok(new_content.finish(old_lines))
}
pub fn load_file(
- repo: &Repository,
- file_path: &str,
+ repo: &Repository,
+ file_path: &str,
) -> Result<String> {
- let repo_path = work_dir(repo)?;
- let mut file = File::open(repo_path.join(file_path).as_path())?;
- let mut res = String::new();
- file.read_to_string(&mut res)?;
+ let repo_path = work_dir(repo)?;
+ let mut file = File::open(repo_path.join(file_path).as_path())?;
+ let mut res = String::new();
+ file.read_to_string(&mut res)?;
- Ok(res)
+ Ok(res)
}