Solving a conflict

pmeunier
Nov 13, 2022, 12:27 PM
WBTE6H6V4MUWBSHDQ7ZMDBLT64FHS63T2SUSL446E3HSXBXMME6QC

Dependencies

  • [2] UEWNF7X3 Detecting "self-solving" zombie folder (or file) conflicts
  • [3] JSSEYW7N Solving a conflict (this was a double conflict, actually)
  • [4] 7FFFKQZU add 'Default' implementations
  • [5] VO5OQW4W Removing anyhow in libpijul
  • [6] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).
  • [7] TQOZXRKL Solving a conflict

Change contents

  • resurrect zombie in libpijul/src/missing_context.rs at line 253
    [3.26882][2.45:4001](),[3.26882][2.45:4001]()
    /// If we're deleting a folder edge, there is a possibility that this
    /// solves a "zombie conflict", by removing the last child of a folder
    /// that was a zombie, in which case that parent folder can finally
    /// rest in peace.
    ///
    /// This function takes care of this for the entire change, by
    /// removing all obsolete folder conflict edges.
    pub(crate) fn detect_folder_conflict_resolutions<T: GraphMutTxnT>(
    txn: &mut T,
    channel: &mut T::Graph,
    ws: &mut Workspace,
    change_id: ChangeId,
    change: &Change,
    ) -> Result<(), MissingError<T::GraphError>> {
    for change_ in change.changes.iter() {
    for change_ in change_.iter() {
    if let Atom::EdgeMap(ref n) = *change_ {
    for edge in n.edges.iter() {
    if !edge.flag.contains(EdgeFlags::DELETED) {
    continue;
    }
    detect_folder_conflict_resolution(txn, channel, ws, change_id, &n.inode, edge)?
    }
    }
    }
    }
    Ok(())
    }
    fn detect_folder_conflict_resolution<T: GraphMutTxnT>(
    txn: &mut T,
    channel: &mut T::Graph,
    ws: &mut Workspace,
    change_id: ChangeId,
    inode: &Position<Option<Hash>>,
    e: &NewEdge<Option<Hash>>,
    ) -> Result<(), MissingError<T::GraphError>> {
    let mut stack = vec![if e.flag.contains(EdgeFlags::FOLDER) {
    if e.to.is_empty() {
    internal_pos(txn, &e.to.start_pos(), change_id)?
    } else {
    internal_pos(txn, &e.from, change_id)?
    }
    } else {
    internal_pos(txn, &inode, change_id)?
    }];
    let len = ws.pseudo.len();
    while let Some(pos) = stack.pop() {
    let dest_vertex = if let Ok(&dest_vertex) = txn.find_block_end(&channel, pos) {
    if !dest_vertex.is_empty() {
    continue;
    }
    dest_vertex
    } else {
    continue;
    };
    // Is `dest_vertex` alive? If so, stop this path.
    let f0 = EdgeFlags::FOLDER | EdgeFlags::PARENT;
    let f1 = EdgeFlags::FOLDER | EdgeFlags::PARENT | EdgeFlags::BLOCK;
    if let Some(e) = iter_adjacent(txn, channel, dest_vertex, f0, f1)?
    .filter_map(|e| e.ok())
    .filter(|e| !e.flag().contains(EdgeFlags::PSEUDO))
    .next()
    {
    debug!("is_alive: {:?}", e);
    continue;
    }
    // Does `dest_vertex` have alive or zombie descendants? If
    // so, stop this path.
    let f0 = EdgeFlags::empty();
    let f1 = EdgeFlags::FOLDER | EdgeFlags::BLOCK | EdgeFlags::PSEUDO;
    if let Some(e) = iter_adjacent(txn, channel, dest_vertex, f0, f1)?.next() {
    debug!("child is_alive: {:?}", e);
    continue;
    }
    // Else, `dest_vertex` is dead. We should remove its
    // pseudo-parents.
    let f = EdgeFlags::FOLDER | EdgeFlags::PARENT | EdgeFlags::PSEUDO;
    for e in iter_adjacent(txn, channel, dest_vertex, f, f)? {
    let e = e?;
    ws.pseudo.push((dest_vertex, *e));
    let gr = *txn.find_block_end(&channel, e.dest()).unwrap();
    for e in iter_adjacent(txn, channel, gr, f, f)? {
    let e = e?;
    ws.pseudo.push((gr, *e));
    stack.push(e.dest())
    }
    }
    }
    // Finally, we were only squatting the `.pseudo` field of the
    // workspace, since that field is normally used for missing
    // children, and pseudo-edges from that field are treated in a
    // special way (by `delete_pseudo_edges` in this module).
    //
    // Therefore, we need to delete our folder-pseudo-edges now.
    for (v, e) in ws.pseudo.drain(len..) {
    let p = *txn.find_block_end(channel, e.dest())?;
    del_graph_with_rev(
    txn,
    channel,
    e.flag() - EdgeFlags::PARENT,
    p,
    v,
    e.introduced_by(),
    )?;
    }
    Ok(())
    }