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

Function analyze_split

atomic-repository/src/repository/split.rs:158–244  ·  view source on GitHub ↗

Compute the reverse-dependency closure of `requested` within `source`. Bounds are `T: ViewTxnT` (which requires `GraphTxnT`), so this works on both read and write transactions and can be reused for dry-run previews.

(
    txn: &T,
    source: &ViewState,
    requested: &[Hash],
)

Source from the content-addressed store, hash-verified

156/// Bounds are `T: ViewTxnT` (which requires `GraphTxnT`), so this works on both
157/// read and write transactions and can be reused for dry-run previews.
158fn analyze_split<T: ViewTxnT>(
159 txn: &T,
160 source: &ViewState,
161 requested: &[Hash],
162) -> Result<SplitAnalysis, RepositoryError> {
163 let db = |e: PristineError| RepositoryError::Database(e.to_string());
164
165 // Resolve each requested hash to an internal id and confirm it is in the
166 // source view's OWN change log.
167 let mut requested_ids: HashSet<NodeId> = HashSet::new();
168 let mut queue: VecDeque<(Hash, NodeId)> = VecDeque::new();
169 for hash in requested {
170 let id =
171 txn.get_internal(hash)
172 .map_err(db)?
173 .ok_or_else(|| RepositoryError::ChangeNotFound {
174 hash: hash.to_base32(),
175 })?;
176 if txn.get_change_seq(source, id).map_err(db)?.is_none() {
177 return Err(RepositoryError::ChangeNotInView {
178 hash: hash.to_base32(),
179 view: source.name.clone(),
180 });
181 }
182 if requested_ids.insert(id) {
183 queue.push_back((*hash, id));
184 }
185 }
186
187 // BFS over reverse dependencies, staying inside the source view.
188 let mut closure_ids: HashSet<NodeId> = requested_ids.clone();
189 while let Some((hash, _id)) = queue.pop_front() {
190 let dependents = txn.get_rev_change_deps(&hash).map_err(db)?;
191 for dep_id in dependents {
192 // Only dependents that actually live in the source view matter;
193 // dependents in other views don't affect this view's coherence.
194 if txn.get_change_seq(source, dep_id).map_err(db)?.is_none() {
195 continue;
196 }
197 if closure_ids.insert(dep_id) {
198 let dep_hash = txn.get_external(dep_id).map_err(db)?.ok_or_else(|| {
199 RepositoryError::ChangeNotFound {
200 hash: format!("id={}", dep_id.0),
201 }
202 })?;
203 queue.push_back((dep_hash, dep_id));
204 }
205 }
206 }
207
208 // Build ordered lists keyed by source sequence.
209 let ordered = |ids: &HashSet<NodeId>| -> Result<Vec<SplitChange>, RepositoryError> {
210 let mut v = Vec::with_capacity(ids.len());
211 for &id in ids {
212 let seq = txn
213 .get_change_seq(source, id)
214 .map_err(db)?
215 .expect("closure member is in source view");

Callers 1

split_viewMethod · 0.85

Calls 12

is_noneMethod · 0.80
get_internalMethod · 0.45
to_base32Method · 0.45
get_change_seqMethod · 0.45
cloneMethod · 0.45
insertMethod · 0.45
get_rev_change_depsMethod · 0.45
get_externalMethod · 0.45
lenMethod · 0.45
pushMethod · 0.45
iterMethod · 0.45
containsMethod · 0.45

Tested by

no test coverage detected