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

Function write_new_vertex

atomic-core/src/apply/insertion.rs:86–222  ·  view source on GitHub ↗

Apply a Insertion atom to the graph. Creates a new span and connects it to the graph via context edges. This is how new content is inserted into files. # Arguments `txn` - Write transaction for graph modifications `workspace` - Workspace for tracking state and conflicts `change_id` - Internal ID of the change being applied `insertion` - The Insertion specification `change` - The full change for

(
    txn: &mut CachedWriteGraphTxn<'_, '_>,
    workspace: &mut Workspace,
    change_id: NodeId,
    insertion: &Insertion<Option<Hash>>,
    change: &Change,
    detect_conflicts: bool,
)

Source from the content-addressed store, hash-verified

84/// - `BlockNotFound`: Context position not found
85/// - `Internal`: Database error
86pub fn write_new_vertex(
87 txn: &mut CachedWriteGraphTxn<'_, '_>,
88 workspace: &mut Workspace,
89 change_id: NodeId,
90 insertion: &Insertion<Option<Hash>>,
91 change: &Change,
92 detect_conflicts: bool,
93) -> Result<(), LocalApplyError> {
94 // Create the new span
95 let node = GraphNode {
96 change: change_id,
97 start: insertion.start,
98 end: insertion.end,
99 };
100
101 // Clear workspace context for this span
102 workspace.clear_context();
103
104 // Fast path for the common "append one more line from this same change"
105 // pattern used by large FileAdd chains. The predecessor is a vertex we
106 // already inserted in this change, there are no successors, and the new
107 // edge can be wired directly without re-running the general context walk.
108 if insertion.successors.is_empty() && insertion.predecessors.len() == 1 {
109 let internal_pos = resolve_position(txn, &insertion.predecessors[0], change_id)?;
110 if let Some(up_vertex) = workspace.get_current_vertex(internal_pos, true) {
111 let resolved_inode = resolve_inode(txn, &insertion.inode, change_id)?;
112 let up_flag = insertion.flag | EdgeFlags::BLOCK;
113 add_edge_with_reverse(txn, resolved_inode, up_flag, up_vertex, node, change_id)?;
114 workspace.add_up_context(up_vertex.end_pos());
115 workspace.add_up_context_vertex(up_vertex);
116 workspace.register_current_vertex(node);
117 return Ok(());
118 }
119 }
120
121 // Resolve predecessors: vertices that come BEFORE this new content.
122 // Uses the unified overlay-aware resolver so Local stacks can find
123 // vertices written to GRAPH earlier in the same change.
124 for up_pos in &insertion.predecessors {
125 let internal_pos = resolve_position(txn, up_pos, change_id)?;
126 let up_vertex = workspace
127 .get_current_vertex(internal_pos, true)
128 .unwrap_or(resolve_context_vertex(txn, internal_pos, true)?);
129 // Store the end position (where new content connects)
130 workspace.add_up_context(up_vertex.end_pos());
131 workspace.add_up_context_vertex(up_vertex);
132
133 // Check if predecessors was deleted by an unknown change
134 if detect_conflicts {
135 check_deleted_context(txn, workspace, change, up_vertex)?;
136 }
137 }
138
139 let exact_inode_successor = resolve_position(txn, &insertion.inode, change_id).ok();
140
141 // Resolve successors: vertices that come AFTER this new content.
142 for down_pos in &insertion.successors {
143 let internal_pos = resolve_position(txn, down_pos, change_id)?;

Callers 1

write_hunkFunction · 0.85

Calls 15

resolve_positionFunction · 0.85
resolve_inodeFunction · 0.85
add_edge_with_reverseFunction · 0.85
resolve_context_vertexFunction · 0.85
check_deleted_contextFunction · 0.85
clear_contextMethod · 0.80
get_current_vertexMethod · 0.80
add_up_contextMethod · 0.80
add_up_context_vertexMethod · 0.80
add_down_contextMethod · 0.80

Tested by

no test coverage detected