Get the recorded content for a tracked file. This method builds a **change filter** that defines the current view's content perspective, then retrieves file content through the raw transaction. Since all edges live in the global GRAPH, the raw transaction sees everything — the change filter handles view isolation. # Arguments `path` - Path to the file (relative to repository root) # Returns
(
&self,
path: P,
)
| 25 | /// let content = repo.get_file_content("src/main.rs")?; |
| 26 | /// ``` |
| 27 | pub fn get_file_content<P: AsRef<Path>>( |
| 28 | &self, |
| 29 | path: P, |
| 30 | ) -> Result<Option<Vec<u8>>, RepositoryError> { |
| 31 | use atomic_core::output::alive::RetrieveOptions; |
| 32 | let path = path.as_ref(); |
| 33 | let normalized = normalize_path(path); |
| 34 | |
| 35 | let txn = self |
| 36 | .pristine |
| 37 | .read_txn() |
| 38 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 39 | |
| 40 | let view = txn |
| 41 | .get_view(&self.current_view) |
| 42 | .map_err(|e| RepositoryError::Database(e.to_string()))? |
| 43 | .ok_or_else(|| RepositoryError::ViewNotFound { |
| 44 | name: self.current_view.clone(), |
| 45 | })?; |
| 46 | |
| 47 | // Check if file is tracked (tree tables are global) |
| 48 | if !is_tracked(&txn, &normalized).map_err(|e| RepositoryError::Database(e.to_string()))? { |
| 49 | return Ok(None); |
| 50 | } |
| 51 | |
| 52 | // Get inode → position |
| 53 | let inode = match get_inode(&txn, &normalized) { |
| 54 | Ok(Some(inode)) => inode, |
| 55 | Ok(None) => return Ok(None), |
| 56 | Err(e) => return Err(RepositoryError::Database(e.to_string())), |
| 57 | }; |
| 58 | |
| 59 | let position = match txn.inode_position(inode) { |
| 60 | Ok(Some(pos)) => pos, |
| 61 | Ok(None) => return Ok(None), |
| 62 | Err(e) => return Err(RepositoryError::Database(e.to_string())), |
| 63 | }; |
| 64 | |
| 65 | // NOTE on CRDT-driven output (task #24): |
| 66 | // The new `output_file_via_crdt` walker in atomic_core::output::crdt |
| 67 | // is faster and avoids the byte-graph linear-walker bugs that |
| 68 | // overcount bytes on multi-edge vertices. Callers that want the |
| 69 | // *materialized* (no-filter, single-view) content can call it |
| 70 | // directly via `get_file_content_via_crdt`. |
| 71 | // |
| 72 | // We don't use it here because this entry point honors the |
| 73 | // view's `change_filter`, and the CRDT walker reads |
| 74 | // `branch.state` directly — the materialized state across all |
| 75 | // applied changes. For multi-view scenarios that would expose |
| 76 | // branches from views the caller isn't on. |
| 77 | // |
| 78 | // Wiring the CRDT walker into the filter-aware path requires |
| 79 | // either (a) per-(change, branch) state-change tracking or |
| 80 | // (b) replaying BranchOps from filter-in changes — both deferred. |
| 81 | |
| 82 | // Always build the change filter. |
| 83 | // |
| 84 | // There is no "fast path" for shared root views: draft views |