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

Method run_async

atomic-cli/src/commands/push/command.rs:407–891  ·  view source on GitHub ↗

Async implementation of the push command.

(&self)

Source from the content-addressed store, hash-verified

405
406 /// Async implementation of the push command.
407 async fn run_async(&self) -> CliResult<()> {
408 // Find and open repository
409 let repo_root = find_repository_root()?;
410 let repo = Repository::open(&repo_root).map_err(CliError::Repository)?;
411
412 // Resolve remote name, URL, and identity hint
413 let (remote_name, remote_url, identity_hint) = self.resolve_remote_url(&repo)?;
414
415 // Determine views: the leaf we push, and its name on the remote.
416 let local_view = self.get_local_view(&repo);
417 let remote_view = self.get_remote_view(&local_view);
418
419 // Print header
420 println!(
421 "Pushing to {} ({})",
422 style_view(&remote_name),
423 hint(&remote_url)
424 );
425
426 // Fail fast if we have no usable credentials for this remote. A push is
427 // a write that always requires auth; without a credential the server's
428 // negotiation endpoints return an ambiguous 404 (private projects are
429 // deliberately masked), which surfaces as a misleading "view not found".
430 // Catching the missing credential here gives the user an accurate,
431 // actionable error instead.
432 crate::commands::auth::check_push_credentials(&remote_url, identity_hint.as_deref())?;
433
434 // Build the local ancestor chain, root → leaf. A draft's parent must
435 // exist on the remote before the draft's manifest can reference it,
436 // so the whole chain is synced in order.
437 let chain = build_view_chain(&local_view, |name| {
438 repo.get_view_info(name).map(|info| info.parent_name)
439 })
440 .map_err(|e| match e {
441 ChainError::Cycle { view } => CliError::InvalidRepository {
442 reason: format!("view parent chain contains a cycle at '{}'", view),
443 },
444 ChainError::Lookup(err) => CliError::Repository(err),
445 })?;
446
447 // Connect to remote
448 let spinner = create_spinner("Connecting to remote...");
449 let config = self
450 .build_remote_config(&remote_url, identity_hint.as_deref())
451 .await;
452 let remote = HttpRemote::with_config(&remote_url, config).map_err(|e| {
453 finish_error(&spinner, "Failed to connect");
454 convert_remote_error(e, &remote_url)
455 })?;
456 finish_success(&spinner, "Connected");
457
458 // Plan phase: for each view in the chain, export the local manifest,
459 // fetch the remote's, and compute the fast-forward suffix. Hashes
460 // known to be on the remote (remote prefixes, or stored for an
461 // earlier view in this push) are skipped when storing — a draft's
462 // inherited prefix was already synced with its parent.
463 let mut known_on_remote: HashSet<Hash> = HashSet::new();
464 let mut syncs: Vec<ViewSync> = Vec::with_capacity(chain.len());

Callers 1

runMethod · 0.45

Calls 15

find_repository_rootFunction · 0.85
check_push_credentialsFunction · 0.85
build_view_chainFunction · 0.85
RepositoryClass · 0.85
create_spinnerFunction · 0.85
finish_errorFunction · 0.85
finish_successFunction · 0.85
require_manifest_supportFunction · 0.85
plan_view_syncFunction · 0.85
print_warningFunction · 0.85
print_successFunction · 0.85
create_progress_barFunction · 0.85

Tested by

no test coverage detected