Insert a change into the current view. This is the high-level method for inserting a single change into the repository. It loads the change from the change store, validates dependencies, applies atoms to the graph, and updates the view state. # Arguments `hash` - The hash of the change to insert `options` - Options controlling insertion behavior # Returns An `InsertOutcome` containing the new
(
&self,
hash: &Hash,
options: InsertOptions,
)
| 1642 | /// println!("New state: {}", result.new_state.to_base32()); |
| 1643 | /// ``` |
| 1644 | pub fn insert_change( |
| 1645 | &self, |
| 1646 | hash: &Hash, |
| 1647 | options: InsertOptions, |
| 1648 | ) -> Result<InsertOutcome, RepositoryError> { |
| 1649 | let trace_insert = std::env::var_os("ATOMIC_TRACE_INSERT").is_some(); |
| 1650 | let t0 = std::time::Instant::now(); |
| 1651 | |
| 1652 | // Load the change from the store |
| 1653 | let change = self.load_change(hash)?; |
| 1654 | |
| 1655 | if trace_insert { |
| 1656 | eprintln!( |
| 1657 | "[insert_change] hash={} load_change elapsed={:?} hunks={} deps={}", |
| 1658 | &hash.to_base32()[..12], |
| 1659 | t0.elapsed(), |
| 1660 | change.hunks().len(), |
| 1661 | change.dependencies().len(), |
| 1662 | ); |
| 1663 | } |
| 1664 | |
| 1665 | // Get write transaction |
| 1666 | let mut txn = self |
| 1667 | .pristine |
| 1668 | .write_txn() |
| 1669 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 1670 | |
| 1671 | // Check if the change's edges are already in the global GRAPH. |
| 1672 | // |
| 1673 | // A change is "already in the global graph" when it is registered |
| 1674 | // (has a NodeId) AND at least one of its vertices exists in the |
| 1675 | // GRAPH B-tree. `has_change_in_graph` performs a single O(log N) |
| 1676 | // range scan — far cheaper and more reliable than the previous |
| 1677 | // approach of loading the Change file and probing individual hunks. |
| 1678 | // |
| 1679 | // This correctly handles: |
| 1680 | // - Changes recorded on a Draft view (edges in GRAPH only) |
| 1681 | // → returns false, so hunks are re-applied to the global GRAPH |
| 1682 | // - Changes already inserted into a Shared view (edges in GRAPH) |
| 1683 | // → returns true, so redundant hunk application is skipped |
| 1684 | // - Changes with only EdgeUpdate hunks (no FileAdd/DirAdd) |
| 1685 | // → correctly detected via the range scan |
| 1686 | let t_check = std::time::Instant::now(); |
| 1687 | let already_in_graph = if let Some(node_id) = txn |
| 1688 | .get_internal(hash) |
| 1689 | .map_err(|e| RepositoryError::Database(e.to_string()))? |
| 1690 | { |
| 1691 | let in_graph = txn |
| 1692 | .has_change_in_graph(node_id) |
| 1693 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 1694 | log::debug!( |
| 1695 | "insert_change: hash={} node_id={:?} already_in_graph={}", |
| 1696 | hash.to_base32(), |
| 1697 | node_id, |
| 1698 | in_graph |
| 1699 | ); |
| 1700 | in_graph |
| 1701 | } else { |