{"record":{"id":"884a552bf59832a5","repo":"gitbutlerapp/gitbutler","slug":"swap-connections-of-nodes-as-well","errorCode":null,"errorMessage":"swap connections of nodes as well","messagePattern":"swap connections of nodes as well","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-graph/src/init/walk/mod.rs","lineNumber":352,"sourceCode":"\npub fn swap_queued_segments(queue: &mut Queue, a: SegmentIndex, b: SegmentIndex) {\n    for instruction_to_replace in queue.iter_mut().map(|(_, _, instruction, _)| instruction) {\n        let cmp = instruction_to_replace.segment_idx();\n        if cmp == a {\n            *instruction_to_replace = instruction_to_replace.with_replaced_sidx(b);\n        } else if cmp == b {\n            *instruction_to_replace = instruction_to_replace.with_replaced_sidx(a);\n        }\n    }\n}\n\npub fn swap_commits_and_connections(graph: &mut PetGraph, a: SegmentIndex, b: SegmentIndex) {\n    {\n        let (a, b) = graph.index_twice_mut(a, b);\n        std::mem::swap(&mut a.commits, &mut b.commits);\n    }\n    if graph.edges(a).next().is_some() || graph.edges(b).next().is_some() {\n        todo!(\"swap connections of nodes as well\")\n    }\n}\n\nfn local_branches_by_id(\n    refs_by_id: &RefsById,\n    id: gix::ObjectId,\n) -> Option<impl Iterator<Item = &gix::refs::FullName> + '_> {\n    refs_by_id.get(&id).map(|refs| {\n        refs.iter()\n            .filter(|rn| rn.category() == Some(Category::LocalBranch))\n    })\n}\n\n/// Split `src_sidx` into a new segment (to receive the commit at `info`) and connect it with the new segment\n/// whose id will be returned, if…\n///\n/// * …there is exactly one eligible branch to name it.\n/// * …it is a merge commit.","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-graph/src/init/walk/mod.rs#L334-L370","documentation":"`swap_commits_and_connections` in but-graph's init/walk swaps the commit vectors of two segments, but only when neither segment has graph edges. If either segment has connections (PetGraph edges), it panics with `todo!` - rewiring the connections during the swap was never implemented (crates/but-graph/src/init/walk/mod.rs:352).","triggerScenarios":"A graph-rewriting pass (ordering/topology fixups during init) calls this with two segments where `graph.edges(a)` or `graph.edges(b)` yields at least one edge - i.e. either segment is connected to the rest of the graph rather than standing alone.","commonSituations":"Repositories whose ref graph produces connected segments that the walk wants to reorder; new graph-manipulation code paths added to init; changes to segment sorting rules.","solutions":["Avoid code paths that reorder connected segments - restructure the walk so only edge-free segments are swapped","Upgrade but-graph; track the upstream implementation of edge rewiring","As a maintainer: implement the edge swap by collecting `EdgeReference`s for both indices and re-adding them with swapped endpoints via `graph.add_edge` before removing the old ones"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Only swap edge-free segments\nfn can_swap(graph: &PetGraph, a: SegmentIndex, b: SegmentIndex) -> bool {\n    graph.edges(a).next().is_none() && graph.edges(b).next().is_none()\n}\nif can_swap(&graph, a, b) {\n    swap_commits_and_connections(&mut graph, a, b);\n} else {\n    // pick a different rewrite strategy for connected segments\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Before swapping segments, assert both have degree zero with graph.edges(...).next().is_none()","Keep reordering passes on standalone segments; route connected reorders through implemented graph edits","Pin but-graph versions in lockstep with the walk passes you depend on"],"tags":["rust","but-graph","todo","unimplemented","panic","graph-topology"],"backgroundTag":"unimplemented-todo-panic","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}