diff options
author | tummychow <tummychow@users.noreply.github.com> | 2018-02-25 23:32:46 -0800 |
---|---|---|
committer | tummychow <tummychow@users.noreply.github.com> | 2018-02-25 23:32:46 -0800 |
commit | 2170218bbb752819afa489ff5d4f715edf6a8edb (patch) | |
tree | 265c8632b1e909a66607c187d943a6062932e020 | |
parent | 9d6aea560654ec7ef7903b20100feb445a451db7 (diff) |
implement commuting against an entire patch
-rw-r--r-- | src/commute.rs | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/commute.rs b/src/commute.rs index 85a996e..3741225 100644 --- a/src/commute.rs +++ b/src/commute.rs @@ -103,6 +103,25 @@ pub fn commute(first: &owned::Hunk, second: &owned::Hunk) -> Option<(owned::Hunk }) } +pub fn commute_diff_before<'a, I>(after: &owned::Hunk, before: I) -> Option<owned::Hunk> +where + I: iter::IntoIterator<Item = &'a owned::Hunk>, + <I as iter::IntoIterator>::IntoIter: iter::DoubleEndedIterator, +{ + before + .into_iter() + // the patch's hunks must be iterated in reverse application + // order (last applied to first applied), which also happens + // to be reverse line order (bottom to top), which also + // happens to be reverse of the order they're stored + .rev() + .fold(Some(after.clone()), |after, next| { + after + .and_then(|after| commute(next, &after)) + .map(|(commuted_after, _)| commuted_after) + }) +} + #[cfg(test)] mod tests { use super::*; @@ -173,4 +192,49 @@ mod tests { assert_eq!(new1.added.lines.len(), 2); assert_eq!(new2.added.lines.len(), 4); } + + #[test] + fn test_commute_patch() { + let patch = vec![ + owned::Hunk { + added: owned::Block { + start: 1, + lines: Rc::new(vec![b"bar\n".to_vec()]), + trailing_newline: true, + }, + removed: owned::Block { + start: 0, + lines: Rc::new(vec![]), + trailing_newline: true, + }, + }, + owned::Hunk { + added: owned::Block { + start: 3, + lines: Rc::new(vec![b"bar\n".to_vec()]), + trailing_newline: true, + }, + removed: owned::Block { + start: 1, + lines: Rc::new(vec![]), + trailing_newline: true, + }, + }, + ]; + let hunk = owned::Hunk { + added: owned::Block { + start: 5, + lines: Rc::new(vec![b"bar\n".to_vec()]), + trailing_newline: true, + }, + removed: owned::Block { + start: 4, + lines: Rc::new(vec![]), + trailing_newline: true, + }, + }; + + let commuted = commute_diff_before(&hunk, &patch).unwrap(); + assert_eq!(commuted.added.start, 3); + } } |