Fixing a bug in unrecord

pmeunier
Apr 21, 2025, 4:46 PM
HP7CKJIW6TOQZFAZKKJFF76LGE7EMQVDTRH2RWPM4POIG2WRKHBAC

Dependencies

  • [2] 4RQHY7LH Support parsing lowercase base32
  • [3] HWIOJHTR Fixing the numbering of conflicts
  • [4] H5DIAL52 Mixed zombie/order conflicts: fixing the bottom vertex
  • [5] OXZVZDQZ Simplification of missing context repairs
  • [6] 7NSTS6PK Adding a cache in find_alive to improve performance in some cases
  • [7] QWIYNMI5 Formatting + big-endian Sanakirja
  • [8] IIV3EL2X Cleanup, formatting, and fixing the Git feature
  • [9] NUMESMN7 Fixing an "asynchronous race condition" in libpijul, where deleted conflict-solving vertices can be misclassified as alive during patch application
  • [10] ATZ3BWSE Fixing the double-deletion of repairs for folder edges
  • [11] X7OHUPL5 Fixing a bug in unrecord, and fixing the tests
  • [12] PNJL5TPZ Version bump
  • [13] GQTC4TJA show first line of change message in conflict markers
  • [14] 6YMDOZIB Refactoring apply
  • [15] 3CFU4DQN Fixing a bug in unrecord, where a patch creating an undeletion conflict would not be properly unrecorded
  • [16] RSFUX6ML Correct find_alive cache system
  • [17] 3I4PAA2A Making a few types and methods public
  • [18] KQTD46KV Unrecord: restore files *after* having unapplied the *entire* change
  • [19] L4EZSH6B Fixing zombie conflicts: known was computed on the wrong thing
  • [20] RRCSHAYZ Formatting
  • [21] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).
  • [22] WTSYM54O Solving a conflict
  • [23] CCLLB7OI Upgrading to Sanakirja 0.15 + version bump
  • [24] GA3P7FOM Nicer conflict markers
  • [25] 3AMEP2Y5 More convenient interface for channels
  • [26] IXC43DSH Fixing a bug in unrecord
  • [27] GHO6DWPI Refactoring iterators
  • [28] HMMMKONL Fixing alive vertices
  • [29] 7FFFKQZU add 'Default' implementations
  • [30] I24UEJQL Various post-fire fixes
  • [31] FZGHF2PE Formatting
  • [32] ZCPGCKKY Fixing a bug where zombie files could be deleted by unrecord, but not their contents
  • [33] 5FI6SBEZ Re-implement change printing and parsing
  • [34] ZDK3GNDB Tag transactions (including a massive refactoring of errors)
  • [35] I52XSRUH Massive cleanup, and simplification
  • [36] MMQCFCIE Correctness of the new algorithm for detecting missing contexts
  • [37] YN63NUZO Sanakirja 1.0
  • [38] ZJWCPRMH Fixing known patches in deleted contexts
  • [39] UNZXTNSJ Change text format: order dependencies in the order they were on the channel at record time
  • [40] VO5OQW4W Removing anyhow in libpijul
  • [*] DJYHARZ7 Skipping old files when recording
  • [*] FMLTNQ4E Turning a panic into an error when making a patch
  • [*] FXEDPLRI Resurrecting tests, and type cleanup (no need for Arc<RwLock<…>> anymore)
  • [*] YXAVFTPP Allowing vertex buffer to use references to the transaction, by changing `output::output` to take an ArcTxn<T> instead of a simple T

Change contents

  • replacement in libpijul/src/unrecord/mod.rs at line 264
    [5.1695][5.2349:2396](),[5.1137][5.2349:2396]()
    crate::apply::clean_obsolete_pseudo_edges(
    [5.1695]
    [5.2396]
    let mut inodes = crate::apply::clean_obsolete_pseudo_edges(
  • edit in libpijul/src/unrecord/mod.rs at line 270
    [5.2490]
    [5.2490]
    debug!("inodes = {:?}", inodes);
    collect_missing_contexts(
    txn,
    txn.graph(channel),
    &mut ws.apply,
    &change,
    change_id,
    &mut inodes,
    )?;
    for i in inodes {
    debug!("inodes: repair zombie {:?}", i);
    crate::apply::repair_zombies(txn, T::graph_mut(channel), i)?;
    }
  • edit in libpijul/src/unrecord/mod.rs at line 285
    [42.925]
    [5.235705]
    debug!("unapply done");
  • edit in libpijul/src/unrecord/mod.rs at line 422
    [5.1099][5.0:79]()
    let hash: Hash = (*txn.get_external(&change_id).unwrap().unwrap()).into();
  • replacement in libpijul/src/unrecord/mod.rs at line 433
    [5.98][5.0:32]()
    if h == &hash {
    [5.98]
    [2.0]
    if h == &ext {
  • replacement in libpijul/src/unrecord/mod.rs at line 441
    [5.381][5.381:461]()
    .knows(edge.introduced_by.as_ref().unwrap_or(&hash), h)
    [5.381]
    [5.461]
    .knows(edge.introduced_by.as_ref().unwrap_or(&ext), h)
  • replacement in libpijul/src/unrecord/mod.rs at line 470
    [5.242243][5.242243:242346]()
    // does a patch introduced by an edge parallel to
    // this one remove this edge from the graph?
    [5.242243]
    [5.242346]
    // does a patch (call it q) other than the one (p) we're
    // unrecording remove this same edge (a, b, intro) from the graph?
    // This can happen e.g. if an edge is deleted twice, in which case
    // this unrecord is likely to introduce a zombie conflict between
    // p and q.
  • replacement in libpijul/src/unrecord/mod.rs at line 492
    [5.2391][5.2391:2449]()
    // reinsert a -> b: that edge was removed by `e`.
    [5.2391]
    [5.2449]
    // reinsert a -> b: that edge was removed when introducing
    // `e`.
  • edit in libpijul/src/unrecord/mod.rs at line 529
    [5.243938]
    [5.12061]
    /// Remove extra pseudo-edges introduced to mark a zombie conflict, if
    /// the conflict is indeed removed by this unrecord.
  • edit in libpijul/src/unrecord/mod.rs at line 572
    [5.3233]
    [5.3233]
    debug!("already seen");
  • edit in libpijul/src/unrecord/mod.rs at line 598
    [5.1910]
    [5.1910]
    debug!("zombies collected");
  • edit in libpijul/src/unrecord/mod.rs at line 716
    [5.3885]
    /// Same as crate::apply::collect_missing_contexts, but with the
    /// directions reversed.
    fn collect_missing_contexts<T: GraphMutTxnT + TreeTxnT>(
    txn: &T,
    channel: &T::Graph,
    ws: &mut crate::apply::Workspace,
    change: &Change,
    change_id: ChangeId,
    inodes: &mut HashSet<Position<ChangeId>>,
    ) -> Result<(), crate::apply::LocalApplyError<T>> {
    debug!("collect_missing_contexts");
    inodes.extend(
    ws.missing_context
    .unknown_parents
    .drain(..)
    .map(|x| internal_pos(txn, &x.2, change_id).unwrap()),
    );
    for atom in change.changes.iter().flat_map(|r| r.iter()) {
    match atom {
    // NewVertex is already collected when applying.
    Atom::NewVertex(_) => {}
    Atom::EdgeMap(ref n) => {
    crate::apply::has_missing_edge_context(
    txn, channel, change_id, change, &n, inodes, true,
    )?;
    }
    }
    }
    Ok(())
    }
  • replacement in libpijul/src/missing_context.rs at line 24
    [5.696724][5.88638:88682]()
    pub(crate) fn load_graph<T: GraphTxnT>(
    [5.696724]
    [5.696763]
    pub fn load_graph<T: GraphTxnT>(
  • replacement in libpijul/src/missing_context.rs at line 236
    [5.706744][5.83467:83505]()
    pub(crate) unknown_parents: Vec<(
    [5.706744]
    [5.706771]
    pub unknown_parents: Vec<(
  • replacement in libpijul/src/missing_context.rs at line 243
    [5.123715][5.83506:83619]()
    pub(crate) parents: HashSet<SerializedEdge>,
    pub(crate) pseudo: Vec<(Vertex<ChangeId>, SerializedEdge)>,
    [5.123715]
    [5.106]
    pub parents: HashSet<SerializedEdge>,
    pub pseudo: Vec<(Vertex<ChangeId>, SerializedEdge)>,
  • replacement in libpijul/src/missing_context.rs at line 246
    [5.147][5.13188:13219](),[5.13219][5.707101:707180](),[5.707101][5.707101:707180](),[5.707180][5.13220:13269]()
    pub(crate) graphs: Graphs,
    pub(crate) covered_parents: HashSet<(Vertex<ChangeId>, Vertex<ChangeId>)>,
    pub(crate) files: HashSet<Vertex<ChangeId>>,
    [5.147]
    [5.1732]
    pub graphs: Graphs,
    pub covered_parents: HashSet<(Vertex<ChangeId>, Vertex<ChangeId>)>,
    pub files: HashSet<Vertex<ChangeId>>,
  • replacement in libpijul/src/missing_context.rs at line 256
    [5.13296][5.13296:13322]()
    pub(crate) struct Graphs(
    [5.13296]
    [5.13322]
    pub struct Graphs(
  • replacement in libpijul/src/lib.rs at line 18
    [5.717621][5.717621:717632]()
    mod apply;
    [5.717621]
    [5.717632]
    pub mod apply;
  • replacement in libpijul/src/lib.rs at line 23
    [5.717722][5.717722:717743]()
    mod missing_context;
    [5.717722]
    [5.717743]
    pub mod missing_context;
  • edit in libpijul/src/change.rs at line 215
    [5.836189]
    [5.836189]
    debug!("ch {:?}", ch);
  • replacement in libpijul/src/change.rs at line 250
    [5.837662][5.118124:118177](),[5.118177][5.837714:837741](),[5.837714][5.837714:837741]()
    let deps = minimize_deps(txn, &channel, &deps)?;
    for d in deps.iter() {
    [5.837662]
    [5.837741]
    debug!("minimize");
    let deps_ = minimize_deps(txn, &channel, &deps)?;
    for d in deps_.iter() {
  • edit in libpijul/src/change.rs at line 330
    [5.119292]
    [5.138625]
    debug!("add_zombie_deps_from {:?}", edge);
  • edit in libpijul/src/change.rs at line 355
    [43.336]
    [5.839314]
    debug!("e_to {:?}", e_to);
  • edit in libpijul/src/change.rs at line 369
    [43.486]
    [5.839565]
    debug!("to_pos {:?} to {:?}", to_pos, to);
    let mut h = HashSet::new();
  • edit in libpijul/src/change.rs at line 372
    [5.839576]
    [5.138990]
    if !h.insert(*to) {
    error!("seen twice: {:?}", to);
    break;
    }
  • edit in libpijul/src/change.rs at line 377
    [5.139045]
    [5.119673]
    debug!("add_zombie_deps_to {:?}", edge);
  • edit in libpijul/src/change.rs at line 394
    [5.840125]
    [5.840125]
    debug!("to {:?} {:?}", to, e_to);
  • replacement in libpijul/src/change.rs at line 418
    [5.840736][5.7238:7313](),[5.7313][5.139419:139460](),[5.7313][5.840811:840887](),[5.64432][5.840811:840887](),[5.120185][5.840811:840887](),[5.139460][5.840811:840887](),[5.840811][5.840811:840887]()
    let time = txn.get_changeset(txn.changes(&channel), id)?.unwrap();
    let time = u64::from_le(time.0);
    debug!("time = {:?}", time);
    min_time = min_time.min(time);
    [5.840736]
    [5.840887]
    if let Some(time) = txn.get_changeset(txn.changes(&channel), id)? {
    let time = u64::from_le(time.0);
    debug!("time = {:?}", time);
    min_time = min_time.min(time);
    }
  • edit in libpijul/src/change.rs at line 1090
    [5.120624]
    [5.860276]
    debug!("globalize");
  • replacement in libpijul/src/change.rs at line 1099
    [5.860484][5.120625:120674](),[5.120674][5.860530:860639](),[5.860530][5.860530:860639](),[5.860639][5.19658:19856](),[5.19856][5.860716:860923](),[5.120761][5.860716:860923](),[5.139684][5.860716:860923](),[5.860716][5.860716:860923](),[5.860923][5.19857:20057](),[5.20057][5.861002:861217](),[5.120850][5.861002:861217](),[5.139798][5.861002:861217](),[5.861002][5.861002:861217](),[5.861217][5.20058:20243](),[5.20243][5.861293:861348](),[5.120936][5.861293:861348](),[5.139909][5.861293:861348](),[5.861293][5.861293:861348](),[5.861348][5.120937:121036](),[5.121036][5.861443:861673](),[5.861443][5.861443:861673](),[5.861673][5.20244:20323]()
    }) => Ok(Atom::NewVertex(NewVertex {
    up_context: up_context
    .iter()
    .map(|&up| Position {
    change: up
    .change
    .as_ref()
    .and_then(|a| txn.get_external(a).unwrap().map(Into::into)),
    pos: up.pos,
    })
    .collect(),
    down_context: down_context
    .iter()
    .map(|&down| Position {
    change: down
    .change
    .as_ref()
    .and_then(|a| txn.get_external(a).unwrap().map(Into::into)),
    pos: down.pos,
    })
    .collect(),
    start: *start,
    end: *end,
    flag: *flag,
    inode: Position {
    change: inode
    .change
    .as_ref()
    .and_then(|a| txn.get_external(a).unwrap().map(Into::into)),
    pos: inode.pos,
    },
    })),
    Atom::EdgeMap(EdgeMap { edges, inode }) => Ok(Atom::EdgeMap(EdgeMap {
    edges: edges
    .iter()
    .map(|edge| NewEdge {
    previous: edge.previous,
    flag: edge.flag,
    from: Position {
    change: edge
    .from
    [5.860484]
    [5.20323]
    }) => {
    debug!(
    "globalize vertex {:?} {:?}",
    up_context.len(),
    down_context.len()
    );
    Ok(Atom::NewVertex(NewVertex {
    up_context: up_context
    .iter()
    .map(|&up| Position {
    change: up
  • replacement in libpijul/src/change.rs at line 1113
    [5.20498][5.861761:861873](),[5.121134][5.861761:861873](),[5.140032][5.861761:861873](),[5.861761][5.861761:861873](),[5.861873][5.20499:20576]()
    pos: edge.from.pos,
    },
    to: Vertex {
    change: edge
    .to
    [5.20498]
    [5.20576]
    pos: up.pos,
    })
    .collect(),
    down_context: down_context
    .iter()
    .map(|&down| Position {
    change: down
  • replacement in libpijul/src/change.rs at line 1123
    [5.20751][5.861959:862082](),[5.121230][5.861959:862082](),[5.140153][5.861959:862082](),[5.861959][5.861959:862082](),[5.862082][5.140154:140231](),[5.140231][5.121231:121307](),[5.862150][5.121231:121307](),[5.121307][5.140232:140273](),[5.140273][5.862251:862500](),[5.862251][5.862251:862500](),[5.862500][5.20752:20937](),[5.20937][5.862576:862631](),[5.121393][5.862576:862631](),[5.140384][5.862576:862631](),[5.862576][5.862576:862631](),[5.862631][5.121394:121411]()
    start: edge.to.start,
    end: edge.to.end,
    },
    introduced_by: edge.introduced_by.as_ref().map(|a| {
    if let Some(a) = txn.get_external(a).unwrap() {
    a.into()
    } else {
    panic!("introduced by {:?}", a);
    }
    }),
    })
    .collect(),
    inode: Position {
    change: inode
    .change
    .as_ref()
    .and_then(|a| txn.get_external(a).unwrap().map(Into::into)),
    pos: inode.pos,
    },
    })),
    [5.20751]
    [5.862647]
    pos: down.pos,
    })
    .collect(),
    start: *start,
    end: *end,
    flag: *flag,
    inode: Position {
    change: inode
    .change
    .as_ref()
    .and_then(|a| txn.get_external(a).unwrap().map(Into::into)),
    pos: inode.pos,
    },
    }))
    }
    Atom::EdgeMap(EdgeMap { edges, inode }) => {
    debug!("globalize edgemap {:?}", edges.len());
    Ok(Atom::EdgeMap(EdgeMap {
    edges: edges
    .iter()
    .map(|edge| NewEdge {
    previous: edge.previous,
    flag: edge.flag,
    from: Position {
    change: edge
    .from
    .change
    .as_ref()
    .and_then(|a| txn.get_external(a).unwrap().map(Into::into)),
    pos: edge.from.pos,
    },
    to: Vertex {
    change: edge
    .to
    .change
    .as_ref()
    .and_then(|a| txn.get_external(a).unwrap().map(Into::into)),
    start: edge.to.start,
    end: edge.to.end,
    },
    introduced_by: edge.introduced_by.as_ref().map(|a| {
    if let Some(a) = txn.get_external(a).unwrap() {
    a.into()
    } else {
    panic!("introduced by {:?}", a);
    }
    }),
    })
    .collect(),
    inode: Position {
    change: inode
    .change
    .as_ref()
    .and_then(|a| txn.get_external(a).unwrap().map(Into::into)),
    pos: inode.pos,
    },
    }))
    }
  • edit in libpijul/src/change.rs at line 1391
    [43.1058]
    [44.105473]
    info!("computing dependencies");
  • edit in libpijul/src/change.rs at line 1394
    [5.867547]
    [5.867547]
    info!("hashing patch");
  • edit in libpijul/src/change/text_changes.rs at line 265
    [5.11439]
    [5.11439]
    debug!("dep hash {:?}", dep.hash);
  • replacement in libpijul/src/apply.rs at line 10
    [5.93417][5.1216:1237]()
    pub(crate) mod edge;
    [5.93417]
    [5.89930]
    pub mod edge;
  • replacement in libpijul/src/apply.rs at line 12
    [5.89954][5.89954:89966]()
    mod vertex;
    [5.89954]
    [5.89966]
    pub mod vertex;
  • replacement in libpijul/src/apply.rs at line 519
    [5.961195][5.961195:961276](),[5.961276][5.145857:145934](),[5.145934][5.19463:19498](),[5.961343][5.19463:19498](),[5.19498][5.961391:961430](),[5.961391][5.961391:961430](),[5.961430][5.69614:69655](),[5.69655][5.961479:961591](),[5.961479][5.961479:961591](),[5.961591][5.145935:145968](),[5.145968][5.241:341]()
    parents: HashSet<Vertex<ChangeId>>,
    children: HashSet<Vertex<ChangeId>>,
    pseudo: Vec<(Vertex<ChangeId>, SerializedEdge, Position<Option<Hash>>)>,
    deleted_by: HashSet<ChangeId>,
    up_context: Vec<Vertex<ChangeId>>,
    down_context: Vec<Vertex<ChangeId>>,
    pub(crate) missing_context: crate::missing_context::Workspace,
    rooted: HashMap<Vertex<ChangeId>, bool>,
    adjbuf: Vec<SerializedEdge>,
    alive_folder: HashMap<Vertex<ChangeId>, bool>,
    folder_stack: Vec<(Vertex<ChangeId>, bool)>,
    [5.961195]
    [5.961591]
    pub parents: HashSet<Vertex<ChangeId>>,
    pub children: HashSet<Vertex<ChangeId>>,
    pub pseudo: Vec<(Vertex<ChangeId>, SerializedEdge, Position<Option<Hash>>)>,
    pub deleted_by: HashSet<ChangeId>,
    pub up_context: Vec<Vertex<ChangeId>>,
    pub down_context: Vec<Vertex<ChangeId>>,
    pub missing_context: crate::missing_context::Workspace,
    pub rooted: HashMap<Vertex<ChangeId>, bool>,
    pub adjbuf: Vec<SerializedEdge>,
    pub alive_folder: HashMap<Vertex<ChangeId>, bool>,
    pub folder_stack: Vec<(Vertex<ChangeId>, bool)>,
  • edit in libpijul/src/apply.rs at line 598
    [4.531][4.531:572]()
    debug!("visited {:?}", visited);
  • edit in libpijul/src/apply.rs at line 600
    [4.653][4.653:707]()
    debug!("descendants {:#?}", descendants);
  • edit in libpijul/src/apply.rs at line 602
    [4.821]
    [4.821]
    debug!("descendant {:#?}", r);
  • edit in libpijul/src/apply.rs at line 613
    [4.1081]
    [5.35835]
    // Reconnect with ancestor.
    for v in stack.iter().rev() {
    if v.is_on_path {
    debug!("on path: {:?}", v);
    // If the last vertex on the path to `current` is not
    // alive, a reconnect is needed.
    if v.is_alive() {
    // We need to reconnect, and we can do it now
    // since we won't have a chance to visit that
    // edge (because non-PARENT edge we are
    // inserting now starts from a vertex that is
    // on the path, which means we've already
    // pushed all its children onto the stack.).
    put_graph_with_rev(
    txn,
    channel,
    EdgeFlags::PSEUDO,
    v.vertex,
    elt.vertex,
    ChangeId::ROOT,
    )?;
    break;
    } else {
    // Remember that those dead vertices have
    // `elt.vertex` as a descendant.
    descendants.insert((v.vertex, elt.vertex));
    }
    }
    }
  • edit in libpijul/src/apply.rs at line 693
    [4.2236]
    [4.2236]
    debug!("on path: {:?}", v);
  • replacement in libpijul/src/apply.rs at line 707
    [4.2971][4.2971:3015]()
    elt.last_alive,
    [4.2971]
    [4.3015]
    v.last_alive,
  • replacement in libpijul/src/apply.rs at line 715
    [4.3330][4.3330:3409]()
    descendants.insert((v.vertex, stack[len - 1].vertex));
    [4.3330]
    [4.3409]
    descendants.insert((v.vertex, elt.vertex));
  • replacement in libpijul/src/apply.rs at line 898
    [5.3809][5.5424:5481]()
    fn collect_missing_contexts<T: GraphMutTxnT + TreeTxnT>(
    [5.3809]
    [5.5481]
    pub fn collect_missing_contexts<T: GraphMutTxnT + TreeTxnT>(
  • replacement in libpijul/src/apply.rs at line 951
    [5.976997][5.7258:7345]()
    has_missing_edge_context(txn, channel, change_id, change, n, inodes)?;
    [5.976997]
    [5.133135]
    has_missing_edge_context(txn, channel, change_id, change, n, inodes, false)?;
  • replacement in libpijul/src/apply.rs at line 958
    [5.24008][5.7346:7403]()
    fn has_missing_edge_context<T: GraphMutTxnT + TreeTxnT>(
    [5.24008]
    [5.7403]
    /// Collect inodes with missing contexts into `inodes`.
    pub(crate) fn has_missing_edge_context<T: GraphMutTxnT + TreeTxnT>(
  • edit in libpijul/src/apply.rs at line 966
    [5.7487]
    [5.42707]
    reverse: bool,
  • replacement in libpijul/src/apply.rs at line 969
    [5.7545][5.7545:8133](),[5.8133][5.36342:36481](),[5.36481][5.8311:8416](),[5.1384][5.8311:8416]()
    if !inodes.contains(&inode) {
    for e in n.edges.iter() {
    assert!(!e.flag.contains(EdgeFlags::PARENT));
    if e.flag.contains(EdgeFlags::DELETED) {
    trace!("repairing context deleted {:?}", e);
    if has_missing_context_deleted(txn, channel, change_id, |h| change.knows(&h), e)
    .map_err(LocalApplyError::from_missing)?
    {
    inodes.insert(inode);
    break;
    }
    } else {
    trace!("repairing context nondeleted {:?}", e);
    if has_missing_context_nondeleted(txn, channel, change_id, e)
    .map_err(LocalApplyError::from_missing)?
    {
    inodes.insert(inode);
    break;
    }
    [5.7545]
    [5.8416]
    // If the inode is already in there, no need to do anything.
    if inodes.contains(&inode) {
    return Ok(());
    }
    let ext: Hash = if reverse {
    (*txn.get_external(&change_id).unwrap().unwrap()).into()
    } else {
    // Unused, hence we avoid one Sanakirja lookup.
    Hash::None
    };
    for e in n.edges.iter() {
    let e = if reverse {
    e.reverse(Some(ext))
    } else {
    e.clone()
    };
    assert!(!e.flag.contains(EdgeFlags::PARENT));
    if e.flag.contains(EdgeFlags::DELETED) {
    trace!("repairing context deleted {:?}", e);
    if has_missing_context_deleted(txn, channel, change_id, |h| change.knows(&h), &e)
    .map_err(LocalApplyError::from_missing)?
    {
    inodes.insert(inode);
    break;
    }
    } else {
    trace!("repairing context nondeleted {:?}", e);
    if has_missing_context_nondeleted(txn, channel, change_id, &e)
    .map_err(LocalApplyError::from_missing)?
    {
    inodes.insert(inode);
    break;
  • replacement in libpijul/src/apply/edge.rs at line 118
    [5.99267][5.1552:1589]()
    fn collect_nondeleted_zombies<T, K>(
    [5.99267]
    [5.99307]
    pub fn collect_nondeleted_zombies<T, K>(
  • replacement in libpijul/src/apply/edge.rs at line 224
    [5.102516][5.43866:43919]()
    fn collect_pseudo_edges<T: GraphMutTxnT + TreeTxnT>(
    [5.102516]
    [5.102558]
    pub fn collect_pseudo_edges<T: GraphMutTxnT + TreeTxnT>(
  • replacement in libpijul/src/apply/edge.rs at line 263
    [5.103722][5.43959:44014]()
    fn reconnect_pseudo_edges<T: GraphMutTxnT + TreeTxnT>(
    [5.103722]
    [5.103766]
    pub fn reconnect_pseudo_edges<T: GraphMutTxnT + TreeTxnT>(
  • edit in libpijul/src/alive/output.rs at line 130
    [5.7130]
    [5.6094]
    debug!("end zombie conflict {id} (line {})", line!());
  • edit in libpijul/src/alive/output.rs at line 137
    [5.7281]
    [5.6209]
    debug!("end zombie conflict {id} (line {})", line!());
  • replacement in libpijul/src/alive/output.rs at line 213
    [5.7560][3.0:47]()
    vbuf.begin_cyclic_conflict::<P>(*id)?;
    [5.7560]
    [5.993175]
    debug!("begin cyclic conflict {id_cyclic}");
    vbuf.begin_cyclic_conflict::<P>(id_cyclic)?;
  • edit in libpijul/src/alive/output.rs at line 222
    [5.7638]
    [45.9909]
    debug!("begin zombie conflict {id}");
  • edit in libpijul/src/alive/output.rs at line 228
    [5.7863]
    [5.6448]
    debug!("end zombie conflict {id}");