Git · marked(): regions as Git grouped them in marked text, base from diff3
This commit is contained in:
2 files changed
+58
-1
No files matched your search
@@ -161,6 +161,42 @@ pub fn conflicts(text: &str) -> Vec<Conflict> {
|
|||||||
found
|
found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Regions as Git grouped them in marked `text`; base from diff3 sections.
|
||||||
|
pub fn marked(text: &str) -> Vec<Region> {
|
||||||
|
let lines: Vec<String> = text
|
||||||
|
.tokenize_lines()
|
||||||
|
.into_iter()
|
||||||
|
.map(str::to_string)
|
||||||
|
.collect();
|
||||||
|
let same = |range: std::ops::Range<usize>| Region {
|
||||||
|
kind: RegionKind::Unchanged,
|
||||||
|
base: lines[range.clone()].to_vec(),
|
||||||
|
ours: lines[range.clone()].to_vec(),
|
||||||
|
theirs: lines[range].to_vec(),
|
||||||
|
};
|
||||||
|
let mut out = Vec::new();
|
||||||
|
let mut at = 0;
|
||||||
|
for conflict in conflicts(text) {
|
||||||
|
if conflict.start > at {
|
||||||
|
out.push(same(at..conflict.start));
|
||||||
|
}
|
||||||
|
let ours_end = conflict.base.unwrap_or(conflict.middle);
|
||||||
|
out.push(Region {
|
||||||
|
kind: RegionKind::Conflict,
|
||||||
|
ours: lines[conflict.start + 1..ours_end].to_vec(),
|
||||||
|
base: conflict
|
||||||
|
.base
|
||||||
|
.map_or_else(Vec::new, |base| lines[base + 1..conflict.middle].to_vec()),
|
||||||
|
theirs: lines[conflict.middle + 1..conflict.end].to_vec(),
|
||||||
|
});
|
||||||
|
at = conflict.end + 1;
|
||||||
|
}
|
||||||
|
if at < lines.len() {
|
||||||
|
out.push(same(at..lines.len()));
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
/// `text` with conflict `ix` settled; none if absent.
|
/// `text` with conflict `ix` settled; none if absent.
|
||||||
pub fn resolve(text: &str, ix: usize, take: Take) -> Option<String> {
|
pub fn resolve(text: &str, ix: usize, take: Take) -> Option<String> {
|
||||||
let Some(conflict) = conflicts(text).get(ix).copied() else {
|
let Some(conflict) = conflicts(text).get(ix).copied() else {
|
||||||
@@ -191,6 +227,25 @@ pub fn resolve(text: &str, ix: usize, take: Take) -> Option<String> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn marked_text_keeps_gits_grouping_and_its_base() {
|
||||||
|
let text = "first\n<<<<<<< ours\nOURS a\nunchanged\nOURS b\n||||||| base\na\nunchanged\nb\n=======\nTHEIRS a\nunchanged\nTHEIRS b\n>>>>>>> theirs\nlast\n";
|
||||||
|
let found = marked(text);
|
||||||
|
let kinds: Vec<RegionKind> = found.iter().map(|region| region.kind).collect();
|
||||||
|
assert_eq!(
|
||||||
|
kinds,
|
||||||
|
[
|
||||||
|
RegionKind::Unchanged,
|
||||||
|
RegionKind::Conflict,
|
||||||
|
RegionKind::Unchanged
|
||||||
|
],
|
||||||
|
"one block, as Git wrote it"
|
||||||
|
);
|
||||||
|
assert_eq!(found[1].base, ["a\n", "unchanged\n", "b\n"]);
|
||||||
|
assert_eq!(found[1].ours.len(), 3);
|
||||||
|
assert_eq!(found[2].ours, ["last\n"]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn a_diff3_conflict_leaves_its_base_out() {
|
fn a_diff3_conflict_leaves_its_base_out() {
|
||||||
let text = "a\n<<<<<<< HEAD\nours\n||||||| base\nold\n=======\ntheirs\n>>>>>>> side\nz\n";
|
let text = "a\n<<<<<<< HEAD\nours\n||||||| base\nold\n=======\ntheirs\n>>>>>>> side\nz\n";
|
||||||
|
|||||||
+3
-1
@@ -25,7 +25,9 @@ pub use diff::{DiffLine, LineKind, Stretch, diff, mark_words, pairs, stat};
|
|||||||
pub use graph::{GraphRow, Half, Stroke, lanes};
|
pub use graph::{GraphRow, Half, Stroke, lanes};
|
||||||
pub use history::FileHistory;
|
pub use history::FileHistory;
|
||||||
pub use merge::{ConflictResolver, ThreeWayMerge};
|
pub use merge::{ConflictResolver, ThreeWayMerge};
|
||||||
pub use merging::{Conflict, Region, RegionKind, Take, conflicts, regions, resolve, result};
|
pub use merging::{
|
||||||
|
Conflict, Region, RegionKind, Take, conflicts, marked, regions, resolve, result,
|
||||||
|
};
|
||||||
pub use refs::{Branch, BranchList, BranchSelector};
|
pub use refs::{Branch, BranchList, BranchSelector};
|
||||||
pub use review::{PullRequest, PullRequestCard, PullState, ReviewComment, ReviewNote};
|
pub use review::{PullRequest, PullRequestCard, PullState, ReviewComment, ReviewNote};
|
||||||
pub use rows::Place;
|
pub use rows::Place;
|
||||||
|
|||||||
Reference in new issue
Block a user