+ pub(crate) fn repair_up<T: GraphMutTxnT + TreeTxnT>(
+ txn: &mut T,
+ channel: &mut T::Graph,
+ root: Position<ChangeId>,
+ ) -> Result<(), LocalApplyError<T>> {
+ info!("repair_zombies {:?}", root);
+ let mut stack = vec![root.inode_vertex()];
+ let mut visited = BTreeSet::new();
+ let mut add = Vec::new();
+ while let Some(elt) = stack.pop() {
+ if !visited.insert(elt) {
+ continue;
+ }
+ let mut is_alive = false;
+ let mut is_dead = false;
+ for e in iter_adjacent(
+ txn,
+ channel,
+ elt,
+ EdgeFlags::PARENT | EdgeFlags::FOLDER,
+ EdgeFlags::all(),
+ )? {
+ let e = e?;
+ let deleted = e.flag().contains(EdgeFlags::DELETED);
+ if e.flag().contains(EdgeFlags::PARENT | EdgeFlags::FOLDER) {
+ is_alive |= !deleted;
+ is_dead |= deleted;
+ }
+ }
+ if is_dead && !is_alive {
+ for e in iter_adjacent(
+ txn,
+ channel,
+ elt,
+ EdgeFlags::PARENT | EdgeFlags::FOLDER,
+ EdgeFlags::all(),
+ )? {
+ let e = e?;
+ if e.flag()
+ .contains(EdgeFlags::PARENT | EdgeFlags::DELETED | EdgeFlags::FOLDER)
+ {
+ let parent = txn.find_block_end(channel, e.dest())?;
+ add.push((*parent, elt));
+ stack.push(*parent)
+ }
+ }
+
+ for (a, b) in add.drain(..) {
+ put_graph_with_rev(
+ txn,
+ channel,
+ EdgeFlags::PSEUDO | EdgeFlags::FOLDER,
+ a,
+ b,
+ ChangeId::ROOT,
+ )?;
+ }
+ }
+ }
+
+ Ok(())
+ }
+