MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / output_graph_content

Function output_graph_content

atomic-core/src/output/repo/content.rs:137–268  ·  view source on GitHub ↗

Output the content of an alive graph to a span buffer. This function traverses the graph in SCC order (as computed by [`compute_order`](crate::output::alive::compute_order)) and writes each span's content to the buffer. Conflicts are handled by: - **Cyclic conflicts**: Multi-span SCCs are output with conflict markers - **Zombie content**: Deleted vertices with live edges get zombie markers # Ar

(
    changes: &C,
    hash_fn: F,
    graph: &AliveGraph,
    order: &OrderResult,
    buffer: &mut V,
)

Source from the content-addressed store, hash-verified

135/// 3. For zombie vertices: wrap in zombie conflict markers
136/// 4. Track and report any content retrieval errors
137pub fn output_graph_content<C, F, V>(
138 changes: &C,
139 hash_fn: F,
140 graph: &AliveGraph,
141 order: &OrderResult,
142 buffer: &mut V,
143) -> OutputResult<()>
144where
145 C: ChangeStore,
146 F: Fn(NodeId) -> Option<Hash>,
147 V: VertexBuffer,
148{
149 // Track conflict IDs
150 let mut conflict_id: usize = 0;
151
152 // Track zombie state
153 let mut in_zombie: Option<usize> = None;
154
155 // Process SCCs in reverse order (Tarjan produces reverse topological order,
156 // so we iterate in reverse to get forward topological order for correct output)
157 for scc in order.sccs.iter().rev() {
158 // Skip empty SCCs (shouldn't happen, but be safe)
159 if scc.is_empty() {
160 continue;
161 }
162
163 // Check if this is a cyclic conflict (multi-span SCC)
164 let is_cyclic = scc.len() > 1;
165
166 if is_cyclic {
167 conflict_id += 1;
168 buffer
169 .begin_cyclic_conflict(conflict_id)
170 .map_err(OutputError::io)?;
171 }
172
173 // Output each span in the SCC
174 for (i, &vertex_id) in scc.iter().enumerate() {
175 // Get span data
176 let vertex_data = match graph.try_get_vertex(vertex_id) {
177 Some(v) => v,
178 None => continue,
179 };
180
181 let node = vertex_data.node;
182
183 // Handle zombie state transitions
184 let is_zombie = vertex_data.is_zombie();
185
186 if is_zombie && in_zombie.is_none() {
187 // Entering zombie region
188 conflict_id += 1;
189 in_zombie = Some(conflict_id);
190
191 let hash = hash_fn(node.change);
192 let hashes: Vec<Hash> = hash.into_iter().collect();
193 let hashes_ref: Option<&[Hash]> = if hashes.is_empty() {
194 None

Calls 15

try_get_vertexMethod · 0.80
is_noneMethod · 0.80
getMethod · 0.65
iterMethod · 0.45
is_emptyMethod · 0.45
lenMethod · 0.45
begin_cyclic_conflictMethod · 0.45
is_zombieMethod · 0.45
into_iterMethod · 0.45
begin_zombie_conflictMethod · 0.45
end_zombie_conflictMethod · 0.45
conflict_nextMethod · 0.45