libpijul_compat/
graph.rs

1//! The data structure of the in-memory version of Pijul's main
2//! datastructure, used to edit and organise it (for instance before a
3//! record or before outputting a file).
4use backend::*;
5use conflict;
6use std::cmp::min;
7use std::collections::{HashMap, HashSet};
8use Result;
9
10use rand;
11use std;
12
13bitflags! {
14    struct Flags: u8 {
15        const LINE_HALF_DELETED = 4;
16        const LINE_VISITED = 2;
17        const LINE_ONSTACK = 1;
18    }
19}
20
21/// The elementary datum in the representation of the repository state
22/// at any given point in time. We need this structure (as opposed to
23/// working directly on a branch) in order to add more data, such as
24/// strongly connected component identifier, to each node.
25#[derive(Debug)]
26pub struct Line {
27    /// The internal identifier of the line.
28    pub key: Key<PatchId>,
29
30    // The status of the line with respect to a dfs of
31    // a graph it appears in. This is 0 or
32    // `LINE_HALF_DELETED`.
33    flags: Flags,
34    children: usize,
35    n_children: usize,
36    index: usize,
37    lowlink: usize,
38    scc: usize,
39}
40
41impl Line {
42    pub fn is_zombie(&self) -> bool {
43        self.flags.contains(Flags::LINE_HALF_DELETED)
44    }
45}
46
47/// A graph, representing the whole content of the repository state at
48/// a point in time. The encoding is a "flat adjacency list", where
49/// each vertex contains a index `children` and a number of children
50/// `n_children`. The children of that vertex are then
51/// `&g.children[children .. children + n_children]`.
52#[derive(Debug)]
53pub struct Graph {
54    /// Array of all alive lines in the graph. Line 0 is a dummy line
55    /// at the end, so that all nodes have a common successor
56    pub lines: Vec<Line>,
57    /// Edge + index of the line in the "lines" array above. "None"
58    /// means "dummy line at the end", and corresponds to line number
59    /// 0.
60    children: Vec<(Option<Edge>, VertexId)>,
61}
62
63#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
64struct VertexId(usize);
65
66const DUMMY_VERTEX: VertexId = VertexId(0);
67
68impl std::ops::Index<VertexId> for Graph {
69    type Output = Line;
70    fn index(&self, idx: VertexId) -> &Self::Output {
71        self.lines.index(idx.0)
72    }
73}
74impl std::ops::IndexMut<VertexId> for Graph {
75    fn index_mut(&mut self, idx: VertexId) -> &mut Self::Output {
76        self.lines.index_mut(idx.0)
77    }
78}
79
80use std::io::Write;
81
82impl Graph {
83    fn children(&self, i: VertexId) -> &[(Option<Edge>, VertexId)] {
84        let ref line = self[i];
85        &self.children[line.children..line.children + line.n_children]
86    }
87
88    fn child(&self, i: VertexId, j: usize) -> &(Option<Edge>, VertexId) {
89        &self.children[self[i].children + j]
90    }
91
92    pub fn debug<W: Write>(
93        &self,
94        txn: &Txn,
95        branch: &Branch,
96        add_others: bool,
97        introduced_by: bool,
98        mut w: W,
99    ) -> std::io::Result<()> {
100        writeln!(w, "digraph {{")?;
101        let mut cache = HashMap::new();
102        if add_others {
103            for (line, i) in self.lines.iter().zip(0..) {
104                cache.insert(line.key, i);
105            }
106        }
107        let mut others = HashSet::new();
108        for (line, i) in self.lines.iter().zip(0..) {
109            let contents = {
110                if let Some(c) = txn.get_contents(line.key) {
111                    let c = c.into_cow();
112                    if let Ok(c) = std::str::from_utf8(&c) {
113                        c.split_at(std::cmp::min(50, c.len())).0.to_string()
114                    } else {
115                        "<INVALID>".to_string()
116                    }
117                } else {
118                    "".to_string()
119                }
120            };
121            let contents = format!("{:?}", contents);
122            let contents = contents.split_at(contents.len() - 1).0.split_at(1).1;
123            writeln!(
124                w,
125                "n_{}[label=\"{}: {}.{}: {}\"];",
126                i,
127                i,
128                line.key.patch.to_base58(),
129                line.key.line.to_hex(),
130                contents
131            )?;
132
133            if add_others && !line.key.is_root() {
134                for (_, v) in txn.iter_nodes(branch, Some((line.key, None)))
135                    .take_while(|&(k, _)| k == line.key)
136                {
137                    if let Some(dest) = cache.get(&v.dest) {
138                        writeln!(
139                            w,
140                            "n_{} -> n_{}[color=red,label=\"{:?}{}{}\"];",
141                            i,
142                            dest,
143                            v.flag.bits(),
144                            if introduced_by { " " } else { "" },
145                            if introduced_by {
146                                v.introduced_by.to_base58()
147                            } else {
148                                String::new()
149                            }
150                        )?;
151                    } else {
152                        if !others.contains(&v.dest) {
153                            others.insert(v.dest);
154                            writeln!(
155                                w,
156                                "n_{}[label=\"{}.{}\",color=red];",
157                                v.dest.to_base58(),
158                                v.dest.patch.to_base58(),
159                                v.dest.line.to_hex()
160                            )?;
161                        }
162                        writeln!(
163                            w,
164                            "n_{} -> n_{}[color=red,label=\"{:?}{}{}\"];",
165                            i,
166                            v.dest.to_base58(),
167                            v.flag.bits(),
168                            if introduced_by { " " } else { "" },
169                            if introduced_by {
170                                v.introduced_by.to_base58()
171                            } else {
172                                String::new()
173                            }
174                        )?;
175                    }
176                }
177            }
178            for &(ref edge, VertexId(j)) in
179                &self.children[line.children..line.children + line.n_children]
180            {
181                if let Some(ref edge) = *edge {
182                    writeln!(
183                        w,
184                        "n_{}->n_{}[label=\"{:?}{}{}\"];",
185                        i,
186                        j,
187                        edge.flag.bits(),
188                        if introduced_by { " " } else { "" },
189                        if introduced_by {
190                            edge.introduced_by.to_base58()
191                        } else {
192                            String::new()
193                        }
194                    )?
195                } else {
196                    writeln!(w, "n_{}->n_{}[label=\"none\"];", i, j)?
197                }
198            }
199        }
200        writeln!(w, "}}")?;
201        Ok(())
202    }
203}
204
205use sanakirja::value::Value;
206/// A "line outputter" trait.
207pub trait LineBuffer<'a, T: 'a + Transaction> {
208    fn output_line(&mut self, key: &Key<PatchId>, contents: Value<'a, T>) -> Result<()>;
209
210    fn output_conflict_marker(&mut self, s: &'a str) -> Result<()>;
211    fn begin_conflict(&mut self) -> Result<()> {
212        self.output_conflict_marker(conflict::START_MARKER)
213    }
214    fn conflict_next(&mut self) -> Result<()> {
215        self.output_conflict_marker(conflict::SEPARATOR)
216    }
217    fn end_conflict(&mut self) -> Result<()> {
218        self.output_conflict_marker(conflict::END_MARKER)
219    }
220}
221
222impl<'a, T: 'a + Transaction, W: std::io::Write> LineBuffer<'a, T> for W {
223    fn output_line(&mut self, k: &Key<PatchId>, c: Value<T>) -> Result<()> {
224        for chunk in c {
225            debug!("output line {:?} {:?}", k, std::str::from_utf8(chunk));
226            self.write_all(chunk)?
227        }
228        Ok(())
229    }
230
231    fn output_conflict_marker(&mut self, s: &'a str) -> Result<()> {
232        self.write(s.as_bytes())?;
233        Ok(())
234    }
235}
236
237#[derive(Clone, Debug)]
238pub struct Visits {
239    pub first: usize,
240    pub last: usize,
241    pub begins_conflict: bool,
242    pub ends_conflict: bool,
243    pub has_brothers: bool,
244}
245
246impl Default for Visits {
247    fn default() -> Self {
248        Visits {
249            first: 0,
250            last: 0,
251            ends_conflict: false,
252            begins_conflict: false,
253            has_brothers: false,
254        }
255    }
256}
257
258pub struct DFS {
259    visits: Vec<Visits>,
260    counter: usize,
261    has_conflicts: bool,
262}
263
264impl DFS {
265    pub fn new(n: usize) -> Self {
266        DFS {
267            visits: vec![Visits::default(); n],
268            counter: 1,
269            has_conflicts: false,
270        }
271    }
272}
273
274impl DFS {
275    fn mark_discovered(&mut self, scc: usize) {
276        if self.visits[scc].first == 0 {
277            self.visits[scc].first = self.counter;
278            self.counter += 1;
279        }
280    }
281
282    fn mark_last_visit(&mut self, scc: usize) {
283        self.mark_discovered(scc);
284        self.visits[scc].last = self.counter;
285        self.counter += 1;
286    }
287
288    fn first_visit(&self, scc: usize) -> usize {
289        self.visits[scc].first
290    }
291
292    fn last_visit(&self, scc: usize) -> usize {
293        self.visits[scc].last
294    }
295
296    fn ends_conflict(&mut self, scc: usize) {
297        self.visits[scc].ends_conflict = true
298    }
299    fn begins_conflict(&mut self, scc: usize) {
300        self.visits[scc].begins_conflict = true;
301        self.has_conflicts = true
302    }
303    fn has_brothers(&mut self, scc: usize) {
304        self.visits[scc].has_brothers = true
305    }
306}
307
308impl Graph {
309    /// Tarjan's strongly connected component algorithm, returning a
310    /// vector of strongly connected components, where each SCC is a
311    /// vector of vertex indices.
312    fn tarjan(&mut self) -> Vec<Vec<VertexId>> {
313        if self.lines.len() <= 1 {
314            return vec![vec![VertexId(0)]];
315        }
316
317        let mut call_stack = vec![(VertexId(1), 0, true)];
318
319        let mut index = 0;
320        let mut stack = Vec::new();
321        let mut scc = Vec::new();
322        while let Some((n_l, i, first_visit)) = call_stack.pop() {
323            if first_visit {
324                // First time we visit this node.
325                let ref mut l = self[n_l];
326                debug!("tarjan: {:?}", l.key);
327                (*l).index = index;
328                (*l).lowlink = index;
329                (*l).flags = (*l).flags | Flags::LINE_ONSTACK | Flags::LINE_VISITED;
330                debug!("{:?} {:?} chi", (*l).key, (*l).n_children);
331                stack.push(n_l);
332                index = index + 1;
333            } else {
334                let &(_, n_child) = self.child(n_l, i);
335                self[n_l].lowlink = std::cmp::min(self[n_l].lowlink, self[n_child].lowlink);
336            }
337
338            let call_stack_length = call_stack.len();
339            for j in i..self[n_l].n_children {
340                let &(_, n_child) = self.child(n_l, j);
341                if !self[n_child].flags.contains(Flags::LINE_VISITED) {
342                    call_stack.push((n_l, j, false));
343                    call_stack.push((n_child, 0, true));
344                    break;
345                // self.tarjan_dfs(scc, stack, index, n_child);
346                } else {
347                    if self[n_child].flags.contains(Flags::LINE_ONSTACK) {
348                        self[n_l].lowlink = min(self[n_l].lowlink, self[n_child].index)
349                    }
350                }
351            }
352            if call_stack_length < call_stack.len() {
353                // recursive call
354                continue;
355            }
356            // Here, all children of n_l have been visited.
357
358            if self[n_l].index == self[n_l].lowlink {
359                let mut v = Vec::new();
360                loop {
361                    match stack.pop() {
362                        None => break,
363                        Some(n_p) => {
364                            self[n_p].scc = scc.len();
365                            self[n_p].flags = self[n_p].flags ^ Flags::LINE_ONSTACK;
366                            v.push(n_p);
367                            if n_p == n_l {
368                                break;
369                            }
370                        }
371                    }
372                }
373                scc.push(v);
374            }
375        }
376        scc
377    }
378
379    /// Run a depth-first search on this graph, assigning the
380    /// `first_visit` and `last_visit` numbers to each node.
381    fn dfs<A: Transaction, R>(
382        &mut self,
383        txn: &GenericTxn<A, R>,
384        branch: &Branch,
385        scc: &[Vec<VertexId>],
386        dfs: &mut DFS,
387        forward: &mut Vec<(Key<PatchId>, Edge)>,
388    ) {
389        let mut call_stack: Vec<(_, HashSet<usize>, _, _)> =
390            vec![(scc.len() - 1, HashSet::new(), true, None)];
391        while let Some((n_scc, mut forward_scc, is_first_child, descendants)) = call_stack.pop() {
392            debug!("dfs, n_scc = {:?}", n_scc);
393            for &VertexId(id) in scc[n_scc].iter() {
394                debug!("dfs, n_scc: {:?}", self.lines[id].key);
395            }
396            dfs.mark_discovered(n_scc);
397            debug!(
398                "scc: {:?}, first {} last {}",
399                n_scc,
400                dfs.first_visit(n_scc),
401                dfs.last_visit(n_scc)
402            );
403            let mut descendants = if let Some(descendants) = descendants {
404                descendants
405            } else {
406                // First visit / discovery of SCC n_scc.
407
408                // After Tarjan's algorithm, the SCC numbers are in reverse
409                // topological order.
410                //
411                // Here, we want to visit the first child in topological
412                // order, hence the one with the largest SCC number first.
413                //
414
415                // Collect all descendants of this SCC, in order of increasing
416                // SCC.
417                let mut descendants = Vec::new();
418                for cousin in scc[n_scc].iter() {
419                    for &(_, n_child) in self.children(*cousin) {
420                        let child_component = self[n_child].scc;
421                        if child_component < n_scc {
422                            // If this is a child and not a sibling.
423                            descendants.push(child_component)
424                        }
425                    }
426                }
427                descendants.sort();
428                debug!("sorted descendants: {:?}", descendants);
429                descendants
430            };
431
432            // SCCs to which we have forward edges.
433            let mut recursive_call = None;
434            while let Some(child) = descendants.pop() {
435                debug!(
436                    "child {:?}, first {} last {}",
437                    child,
438                    dfs.first_visit(child),
439                    dfs.last_visit(child)
440                );
441                if dfs.first_visit(child) == 0 {
442                    // This SCC has not yet been visited, visit it.
443                    recursive_call = Some(child);
444                    if !is_first_child {
445                        // Two incomparable children, n_scc starts a conflict
446                        debug!("!is_first_child, n_scc = {:?}", n_scc);
447                        dfs.begins_conflict(n_scc);
448                        dfs.has_brothers(child)
449                    }
450                    break;
451                } else if dfs.last_visit(child) < dfs.first_visit(n_scc) {
452                    dfs.ends_conflict(child)
453                } else if dfs.first_visit(n_scc) < dfs.first_visit(child) {
454                    // This is a forward edge.
455                    debug!("last_visit to {:?}: {:?}", child, dfs.last_visit(child));
456                    forward_scc.insert(child);
457                }
458            }
459            if let Some(child) = recursive_call {
460                call_stack.push((n_scc, forward_scc, false, Some(descendants)));
461                call_stack.push((child, HashSet::new(), true, None));
462            } else {
463                dfs.mark_last_visit(n_scc);
464                // After this, collect forward edges.
465                for cousin in scc[n_scc].iter() {
466                    for &(ref edge, n_child) in self.children(*cousin) {
467                        if let Some(mut edge) = *edge {
468                            // Is this edge a forward edge of the DAG?
469                            if forward_scc.contains(&self[n_child].scc)
470                                && edge.flag.contains(EdgeFlags::PSEUDO_EDGE)
471                                && !txn.test_edge(
472                                    branch,
473                                    self[*cousin].key,
474                                    edge.dest,
475                                    EdgeFlags::DELETED_EDGE,
476                                    EdgeFlags::DELETED_EDGE,
477                                ) {
478                                debug!("forward: {:?} {:?}", self[*cousin].key, edge);
479                                forward.push((self[*cousin].key, edge))
480                            }
481
482                            // Does this edge have parallel PSEUDO edges?
483                            edge.flag = EdgeFlags::PSEUDO_EDGE;
484                            edge.introduced_by = ROOT_PATCH_ID;
485                            let mut edges = txn.iter_nodes(
486                                branch,
487                                Some((self[*cousin].key, Some(&edge))),
488                            ).take_while(|&(k, v)| {
489                                k == self[*cousin].key && v.dest == edge.dest
490                                    && v.flag <= EdgeFlags::FOLDER_EDGE | EdgeFlags::PSEUDO_EDGE
491                            });
492                            edges.next(); // ignore the first pseudo-edge.
493                            forward.extend(edges.map(|(k, &v)| (k, v))); // add all parallel edges.
494                        }
495                    }
496                }
497            }
498        }
499    }
500}
501
502impl<A: Transaction, R> GenericTxn<A, R> {
503    /// This function constructs a graph by reading the branch from the
504    /// input key. It guarantees that all nodes but the first one (index
505    /// 0) have a common descendant, which is index 0.
506    pub fn retrieve<'a>(&'a self, branch: &Branch, key0: Key<PatchId>) -> Graph {
507        let mut graph = Graph {
508            lines: Vec::new(),
509            children: Vec::new(),
510        };
511        // Insert last "dummy" line (so that all lines have a common descendant).
512        graph.lines.push(Line {
513            key: ROOT_KEY,
514            flags: Flags::empty(),
515            children: 0,
516            n_children: 0,
517            index: 0,
518            lowlink: 0,
519            scc: 0,
520        });
521
522        // Avoid the root key.
523        let mut cache: HashMap<Key<PatchId>, VertexId> = HashMap::new();
524        cache.insert(ROOT_KEY.clone(), DUMMY_VERTEX);
525        let mut stack = Vec::new();
526        if self.get_nodes(&branch, key0, None).is_some() {
527            stack.push(key0)
528        }
529        while let Some(key) = stack.pop() {
530            if cache.contains_key(&key) {
531                // We're doing a DFS here, this can definitely happen.
532                continue;
533            }
534
535            let idx = VertexId(graph.lines.len());
536            cache.insert(key.clone(), idx);
537
538            debug!("{:?}", key);
539            let mut is_zombie = false;
540            // Does this vertex have a DELETED/DELETED+FOLDER edge
541            // pointing to it?
542            let mut first_edge = Edge::zero(EdgeFlags::PARENT_EDGE | EdgeFlags::DELETED_EDGE);
543            let mut nodes = self.iter_nodes(&branch, Some((key, Some(&first_edge))));
544            if let Some((k, v)) = nodes.next() {
545                debug!("zombie? {:?} {:?}", k, v);
546                if k == key
547                    && (v.flag | EdgeFlags::FOLDER_EDGE == first_edge.flag | EdgeFlags::FOLDER_EDGE)
548                {
549                    // Does this vertex also have an alive edge
550                    // pointing to it? (might not be the case for the
551                    // first vertex)
552                    if key == key0 {
553                        first_edge.flag = EdgeFlags::PARENT_EDGE;
554                        nodes = self.iter_nodes(&branch, Some((key, Some(&first_edge))));
555                        if let Some((_, v)) = nodes.next() {
556                            // We know the key is `key`.
557                            is_zombie = v.flag | EdgeFlags::FOLDER_EDGE
558                                == first_edge.flag | EdgeFlags::FOLDER_EDGE
559                        }
560                    } else {
561                        is_zombie = true
562                    }
563                }
564            }
565            debug!("is_zombie: {:?}", is_zombie);
566            let mut l = Line {
567                key: key.clone(),
568                flags: if is_zombie {
569                    Flags::LINE_HALF_DELETED
570                } else {
571                    Flags::empty()
572                },
573                children: graph.children.len(),
574                n_children: 0,
575                index: 0,
576                lowlink: 0,
577                scc: 0,
578            };
579
580            let mut last_flag = EdgeFlags::empty();
581            let mut last_dest = ROOT_KEY;
582
583            for (_, v) in self.iter_nodes(&branch, Some((key, None)))
584                .take_while(|&(k, v)| {
585                    k == key
586                        && v.flag
587                            <= EdgeFlags::PSEUDO_EDGE | EdgeFlags::FOLDER_EDGE
588                                | EdgeFlags::EPSILON_EDGE
589                }) {
590                debug!("-> v = {:?}", v);
591                if last_flag == EdgeFlags::PSEUDO_EDGE && last_dest == v.dest {
592                    // This is a doubled edge, it should be removed.
593                } else {
594                    graph.children.push((Some(v.clone()), DUMMY_VERTEX));
595                    l.n_children += 1;
596                    if !cache.contains_key(&v.dest) {
597                        stack.push(v.dest.clone())
598                    } else {
599                        debug!("v already visited");
600                    }
601                    last_flag = v.flag;
602                    last_dest = v.dest;
603                }
604            }
605            // If this key has no children, give it the dummy child.
606            if l.n_children == 0 {
607                debug!("no children for {:?}", l);
608                graph.children.push((None, DUMMY_VERTEX));
609                l.n_children = 1;
610            }
611            graph.lines.push(l)
612        }
613        for &mut (ref child_key, ref mut child_idx) in graph.children.iter_mut() {
614            if let Some(ref child_key) = *child_key {
615                if let Some(idx) = cache.get(&child_key.dest) {
616                    *child_idx = *idx
617                }
618            }
619        }
620        graph
621    }
622}
623
624/// The conflict markers keep track of the number of conflicts, and is
625/// used for outputting conflicts to a given LineBuffer.
626///
627/// "Zombie" conflicts are those conflicts introduced by zombie
628/// vertices in the contained Graph.
629struct ConflictMarkers<'b> {
630    current_is_zombie: bool,
631    current_conflicts: usize,
632    graph: &'b Graph,
633}
634
635impl<'b> ConflictMarkers<'b> {
636    fn output_zombie_markers_if_needed<'a, A: Transaction + 'a, B: LineBuffer<'a, A>>(
637        &mut self,
638        buf: &mut B,
639        vertex: VertexId,
640    ) -> Result<()> {
641        if self.graph[vertex].is_zombie() {
642            if !self.current_is_zombie {
643                debug!("begin zombie conflict: vertex = {:?}", self.graph[vertex]);
644                self.current_is_zombie = true;
645                buf.begin_conflict()?;
646            }
647        } else if self.current_is_zombie {
648            // Zombie segment has ended
649            if !self.current_is_zombie {
650                debug!("end zombie conflict: vertex = {:?}", self.graph[vertex]);
651            }
652            self.current_is_zombie = false;
653            buf.end_conflict()?;
654        }
655        Ok(())
656    }
657
658    fn begin_conflict<'a, A: Transaction + 'a, B: LineBuffer<'a, A>>(
659        &mut self,
660        buf: &mut B,
661    ) -> Result<()> {
662        buf.begin_conflict()?;
663        self.current_conflicts += 1;
664        Ok(())
665    }
666    fn end_conflict<'a, A: Transaction + 'a, B: LineBuffer<'a, A>>(
667        &mut self,
668        buf: &mut B,
669    ) -> Result<()> {
670        if self.current_conflicts > 0 {
671            buf.end_conflict()?;
672            self.current_conflicts -= 1;
673        }
674        Ok(())
675    }
676}
677
678/// In the case of nested conflicts, a single conflict sometimes needs
679/// to be treated like a line.
680#[derive(Debug, Clone)]
681enum ConflictLine {
682    Conflict(Vec<Vec<ConflictLine>>),
683    Line(VertexId),
684}
685
686impl<'a, A: Transaction + 'a, R> GenericTxn<A, R> {
687    fn output_conflict<B: LineBuffer<'a, A>>(
688        &'a self,
689        conflicts: &mut ConflictMarkers,
690        buf: &mut B,
691        graph: &Graph,
692        scc: &[Vec<VertexId>],
693        conflict: &mut [Vec<ConflictLine>],
694    ) -> Result<()> {
695        let mut is_first = true;
696        for side in conflict {
697            if !is_first && !side.is_empty() {
698                buf.conflict_next()?;
699            }
700            is_first = false;
701            debug!("side = {:?}", side);
702            for i in side {
703                match *i {
704                    ConflictLine::Line(i) => {
705                        conflicts.output_zombie_markers_if_needed(buf, i)?;
706                        let key = graph[i].key;
707                        if let Some(cont) = self.get_contents(key) {
708                            debug!("outputting {:?}", cont);
709                            buf.output_line(&key, cont)?;
710                        }
711                    }
712                    ConflictLine::Conflict(ref mut c) => {
713                        debug!("begin conflict {:?}", c);
714                        sort_conflict(graph, c);
715                        conflicts.begin_conflict(buf)?;
716                        self.output_conflict(conflicts, buf, graph, scc, c)?;
717                        conflicts.end_conflict(buf)?;
718                        debug!("end conflict");
719                    }
720                }
721            }
722        }
723        Ok(())
724    }
725
726    pub fn output_file<B: LineBuffer<'a, A>>(
727        &'a self,
728        branch: &Branch,
729        buf: &mut B,
730        graph: &mut Graph,
731        forward: &mut Vec<(Key<PatchId>, Edge)>,
732    ) -> Result<bool> {
733        debug!("output_file");
734        if graph.lines.len() <= 1 {
735            return Ok(false);
736        }
737        let scc = graph.tarjan(); // SCCs are given here in reverse order.
738        debug!("There are {} SCC", scc.len());
739        debug!("SCCs = {:?}", scc);
740
741        let mut dfs = DFS::new(scc.len());
742        graph.dfs(self, branch, &scc, &mut dfs, forward);
743
744        debug!("dfs done");
745
746        buf.output_line(&graph.lines[1].key, Value::from_slice(b""))?;
747        let mut conflict_tree = conflict_tree(graph, &scc, &dfs)?;
748        debug!("conflict_tree = {:?}", conflict_tree);
749        let mut conflicts = ConflictMarkers {
750            current_is_zombie: false,
751            current_conflicts: 0,
752            graph: &graph,
753        };
754        self.output_conflict(&mut conflicts, buf, graph, &scc, &mut conflict_tree)?;
755        // Close any remaining zombie part (if needed).
756        conflicts.output_zombie_markers_if_needed(buf, DUMMY_VERTEX)?;
757        debug!("/output_file");
758        Ok(dfs.has_conflicts)
759    }
760}
761
762fn side_ends_at(graph: &Graph, side: &[ConflictLine], id: VertexId) -> bool {
763    for j in side.iter() {
764        match *j {
765            ConflictLine::Line(j) => {
766                if graph.children(j).iter().any(|&(_, x)| x == id) {
767                    return true;
768                }
769            }
770            ConflictLine::Conflict(ref sides) => {
771                if sides.iter().any(|side| side_ends_at(graph, side, id)) {
772                    return true;
773                }
774            }
775        }
776    }
777    false
778}
779
780fn conflict_tree(
781    graph: &Graph,
782    scc: &[Vec<VertexId>],
783    dfs: &DFS,
784) -> Result<Vec<Vec<ConflictLine>>> {
785    let mut i = scc.len() - 1;
786
787    let mut stack: Vec<Vec<Vec<ConflictLine>>> = vec![Vec::new()];
788    loop {
789        if dfs.visits[i].ends_conflict && stack.len() > 1 {
790            debug!("End conflict {:?}", dfs.visits[i]);
791            let conflict = stack.pop().unwrap();
792
793            // First determine if all sides are ended by the same
794            // line.
795
796            let mut remaining_sides = Vec::new();
797            let mut current_conflict = Vec::with_capacity(conflict.len());
798            for side in conflict.iter() {
799                // Is this side part of the conflict stopped by
800                // this line?
801                if side_ends_at(graph, side, scc[i][0]) {
802                    current_conflict.push(side.clone())
803                } else {
804                    remaining_sides.push(side.clone())
805                }
806            }
807            debug!("remaining sides = {:?}", remaining_sides);
808            if !remaining_sides.is_empty() {
809                // If there are remaining sides to the conflict, then
810                // the sides that ended here must necessarily be
811                // placed at the beginning of a side of the parent
812                // conflict, for else this algorithm would not have
813                // characterised all sides (i.e. all sides from both
814                // `remaining_sides` and `current_conflict`) as part
815                // of the same conflict.
816                remaining_sides.push(vec![ConflictLine::Conflict(current_conflict)]);
817                stack.push(remaining_sides);
818            } else {
819                // If this line ends the current conflict completely,
820                // let's append the conflict at the end of the last
821                // side of the current "pseudo-conflict" (i.e. a
822                // conflict with one or more sides)
823                if let Some(ref mut last) = stack.last_mut() {
824                    if let Some(ref mut last) = last.last_mut() {
825                        last.push(ConflictLine::Conflict(current_conflict))
826                    }
827                }
828            }
829        } else if dfs.visits[i].has_brothers {
830            if let Some(ref mut top) = stack.last_mut() {
831                // top is the last conflict.
832                top.push(Vec::new())
833            }
834        }
835
836        if scc[i].len() > 1 {
837            debug!("cycle conflict: {:?}", scc);
838            // In a cyclic conflict, sides are exactly the members of
839            // `scc[i]`.
840            if let Some(ref mut last) = stack.last_mut() {
841                if let Some(ref mut last) = last.last_mut() {
842                    last.push(ConflictLine::Conflict(
843                        scc[i]
844                            .iter()
845                            .map(|&x| vec![ConflictLine::Line(x)])
846                            .collect(),
847                    ))
848                }
849            }
850        } else if scc[i].len() == 1 {
851            let key = graph[scc[i][0]].key;
852            debug!("scc[{}].len() = 1, key = {:?}", i, key);
853            if key != ROOT_KEY {
854                if let Some(ref mut top) = stack.last_mut() {
855                    // top is the last conflict.
856                    if top.is_empty() {
857                        top.push(Vec::new())
858                    }
859                    if let Some(ref mut last_side) = top.last_mut() {
860                        last_side.push(ConflictLine::Line(scc[i][0]))
861                    }
862                }
863            }
864        }
865
866        if dfs.visits[i].begins_conflict {
867            debug!("Begin conflict {:?} {:?}", i, dfs.visits[i]);
868            stack.push(Vec::new());
869        }
870
871        if i == 0 {
872            break;
873        } else {
874            i -= 1
875        }
876    }
877    Ok(stack.pop().unwrap())
878}
879
880fn sort_conflict(graph: &Graph, conflict: &mut [Vec<ConflictLine>]) {
881    conflict.sort_by(|a, b| first_line(graph, a).cmp(&first_line(graph, b)))
882}
883
884fn first_line(graph: &Graph, conflict: &[ConflictLine]) -> Option<Key<PatchId>> {
885    let mut result = None;
886    for side in conflict {
887        match *side {
888            ConflictLine::Line(l) => {
889                result = if result.is_none() {
890                    Some(graph[l].key)
891                } else {
892                    min(result, Some(graph[l].key))
893                }
894            }
895            ConflictLine::Conflict(ref c) => {
896                let first = c.iter().filter_map(|side| first_line(graph, side)).min();
897                if result.is_none() {
898                    result = first
899                } else if first.is_some() {
900                    result = min(result, first)
901                }
902            }
903        }
904    }
905    result
906}
907
908impl<'env, R: rand::Rng> MutTxn<'env, R> {
909    pub fn remove_redundant_edges(
910        &mut self,
911        branch: &mut Branch,
912        forward: &[(Key<PatchId>, Edge)],
913    ) -> Result<()> {
914        for &(key, edge) in forward.iter() {
915            self.del_nodes_with_rev(branch, key, edge)?;
916        }
917        Ok(())
918    }
919}