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

Function plan_view_sync

atomic-cli/src/commands/push/helpers.rs:198–306  ·  view source on GitHub ↗

Compute the sync plan for one view: what to store and whether to declare. `remote` is the remote's parsed manifest, or `None` if the view does not exist on the remote (the remote log is empty). The fast-forward rule: the remote log must be a prefix of the local log. The suffix (everything beyond the prefix) is what needs storing — its dependencies are either earlier in the log or already on the

(
    local: &ViewManifest,
    remote: Option<&ViewManifest>,
    force: bool,
    is_leaf: bool,
)

Source from the content-addressed store, hash-verified

196/// genuinely ambiguous (local is behind vs. local shrank), so it is left to the
197/// prefix/divergence rules, which err toward "pull first, or `--force`".
198pub fn plan_view_sync(
199 local: &ViewManifest,
200 remote: Option<&ViewManifest>,
201 force: bool,
202 is_leaf: bool,
203) -> Result<ViewSyncPlan, ViewSyncConflict> {
204 let remote = match remote {
205 None => {
206 // View absent on remote: the whole log is the suffix.
207 return Ok(ViewSyncPlan {
208 suffix: local.changes.clone(),
209 declare: true,
210 forced: false,
211 shrink: false,
212 });
213 }
214 Some(r) => r,
215 };
216
217 // Identity must match: the manifest declares scope and parent, and the
218 // server refuses to mutate an existing view's identity.
219 if remote.scope != local.scope {
220 return Err(ViewSyncConflict::IdentityMismatch {
221 field: "scope",
222 local: local.scope.to_string(),
223 remote: remote.scope.to_string(),
224 });
225 }
226 if remote.parent != local.parent {
227 let show = |p: &Option<String>| p.clone().unwrap_or_else(|| "(none)".to_string());
228 return Err(ViewSyncConflict::IdentityMismatch {
229 field: "parent",
230 local: show(&local.parent),
231 remote: show(&remote.parent),
232 });
233 }
234
235 // Ancestor already satisfied. When this view is NOT the one being pushed (an
236 // ancestor pulled in for a descendant) and the remote already holds every
237 // local change, there is nothing to do: the remote's set already satisfies
238 // the descendant, and pushing a child never implies rewriting a parent. Skip
239 // without error — so a child push is never blocked by an ancestor whose
240 // remote is merely larger (a local shrink) — and flag `shrink` when the
241 // remote is strictly larger so the caller can explain the skip. The leaf
242 // falls through to the prefix/divergence rules below, where `local ⊂ remote`
243 // is ambiguous and errs toward "pull or --force".
244 if !is_leaf {
245 let remote_set: HashSet<&Hash> = remote.changes.iter().collect();
246 if local.changes.iter().all(|h| remote_set.contains(h)) {
247 return Ok(ViewSyncPlan {
248 suffix: Vec::new(),
249 declare: false,
250 forced: false,
251 shrink: local.changes.len() != remote.changes.len(),
252 });
253 }
254 }
255

Calls 7

cloneMethod · 0.45
iterMethod · 0.45
allMethod · 0.45
containsMethod · 0.45
lenMethod · 0.45
positionMethod · 0.45
is_emptyMethod · 0.45