Insert a change with automatic dependency resolution. This method attempts to insert a change and all its missing dependencies. Dependencies are inserted in topological order (dependencies before dependents). # Arguments `hash` - The hash of the change to insert `options` - Options controlling insertion behavior # Returns An `InsertOutcome` containing aggregate statistics for all inserted cha
(
&self,
hash: &Hash,
options: InsertOptions,
)
| 1826 | /// println!("Inserted {} changes", result.stats.changes_applied); |
| 1827 | /// ``` |
| 1828 | pub fn insert_change_rec( |
| 1829 | &self, |
| 1830 | hash: &Hash, |
| 1831 | options: InsertOptions, |
| 1832 | ) -> Result<InsertOutcome, RepositoryError> { |
| 1833 | let trace_insert = std::env::var_os("ATOMIC_TRACE_INSERT").is_some(); |
| 1834 | let t0 = std::time::Instant::now(); |
| 1835 | |
| 1836 | // Load the target change to get its dependencies |
| 1837 | let _change = self.load_change(hash)?; |
| 1838 | |
| 1839 | // Get the view name |
| 1840 | let view_name = options.view.as_deref().unwrap_or(&self.current_view); |
| 1841 | |
| 1842 | if trace_insert { |
| 1843 | eprintln!( |
| 1844 | "[insert_change_rec] start hash={} view={}", |
| 1845 | &hash.to_base32()[..12], |
| 1846 | view_name, |
| 1847 | ); |
| 1848 | } |
| 1849 | |
| 1850 | // Get a read transaction to check what's already inserted |
| 1851 | let read_txn = self |
| 1852 | .pristine |
| 1853 | .read_txn() |
| 1854 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 1855 | |
| 1856 | let view = read_txn |
| 1857 | .get_view(view_name) |
| 1858 | .map_err(|e| RepositoryError::Database(e.to_string()))? |
| 1859 | .ok_or_else(|| RepositoryError::ViewNotFound { |
| 1860 | name: view_name.to_string(), |
| 1861 | })?; |
| 1862 | |
| 1863 | // Collect all needed changes (including the target) |
| 1864 | let mut to_insert = Vec::new(); |
| 1865 | let mut visited = std::collections::HashSet::new(); |
| 1866 | let mut queue = std::collections::VecDeque::new(); |
| 1867 | queue.push_back(*hash); |
| 1868 | |
| 1869 | while let Some(current_hash) = queue.pop_front() { |
| 1870 | if visited.contains(¤t_hash) { |
| 1871 | continue; |
| 1872 | } |
| 1873 | visited.insert(current_hash); |
| 1874 | |
| 1875 | // Check if already inserted |
| 1876 | if let Ok(Some(id)) = read_txn.get_internal(¤t_hash) { |
| 1877 | if read_txn.get_change_seq(&view, id).ok().flatten().is_some() { |
| 1878 | continue; // Already inserted |
| 1879 | } |
| 1880 | } |
| 1881 | |
| 1882 | // Load and queue dependencies |
| 1883 | let dep_change = self.load_change(¤t_hash)?; |
| 1884 | for dep in dep_change.dependencies() { |
| 1885 | if !visited.contains(dep) { |
no test coverage detected