(
&self,
options: StatusOptions,
untracked_policy: UntrackedScanPolicy,
hash_untracked: bool,
)
| 52 | } |
| 53 | |
| 54 | fn status_inner( |
| 55 | &self, |
| 56 | options: StatusOptions, |
| 57 | untracked_policy: UntrackedScanPolicy, |
| 58 | hash_untracked: bool, |
| 59 | ) -> Result<RepositoryStatus, RepositoryError> { |
| 60 | use std::time::SystemTime; |
| 61 | |
| 62 | let overall_start = std::time::Instant::now(); |
| 63 | |
| 64 | let txn = self |
| 65 | .pristine |
| 66 | .read_txn() |
| 67 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 68 | |
| 69 | let view_state = txn |
| 70 | .get_view(&self.current_view) |
| 71 | .map_err(|e| RepositoryError::Database(e.to_string()))? |
| 72 | .map(|s| s.state); |
| 73 | |
| 74 | let mut status = RepositoryStatus::new(self.current_view.clone(), view_state); |
| 75 | |
| 76 | // ── View-aware filtering ─────────────────────────────────────── |
| 77 | // |
| 78 | // Always build the explicit change filter. The TREE table is |
| 79 | // global — it contains entries from ALL views, including child |
| 80 | // views. Without filtering, files recorded on child views leak |
| 81 | // into the parent's status as false "Deleted" entries. |
| 82 | // |
| 83 | // The previous "universal" fast-path (skip filter for |
| 84 | // is_shared() && parent.is_none()) was unsound: the dev view is |
| 85 | // shared with no parent, but child/sibling views may have unique |
| 86 | // changes. Skipping the filter caused TREE entries created by |
| 87 | // those changes to surface as phantom `Deleted` files in dev's |
| 88 | // status. |
| 89 | // |
| 90 | // The filter computation is O(C) where C is changes on the view — |
| 91 | // a single B-tree scan, fast even on large repos. |
| 92 | // |
| 93 | // None means "no current view" (a misconfigured repo); preserve |
| 94 | // the legacy "show everything" behavior in that case rather than |
| 95 | // producing an empty status. |
| 96 | let current_view_change_ids: Option<HashSet<NodeId>> = if let Some(ref view) = txn |
| 97 | .get_view(&self.current_view) |
| 98 | .map_err(|e| RepositoryError::Database(e.to_string()))? |
| 99 | { |
| 100 | Some(collect_visible_change_ids_with_deps(&txn, view)?) |
| 101 | } else { |
| 102 | None |
| 103 | }; |
| 104 | |
| 105 | let phase1_ms = overall_start.elapsed().as_millis(); |
| 106 | log::debug!("status: view filter setup took {}ms", phase1_ms); |
| 107 | |
| 108 | // ── Single-pass TREE scan ────────────────────────────────────── |
| 109 | let tree_start = std::time::Instant::now(); |
| 110 | // |
| 111 | // Build tracked_paths, inode_map, and directory_inodes in ONE |
no test coverage detected