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

Method run

atomic-cli/src/commands/restore.rs:331–446  ·  view source on GitHub ↗

Execute the restore command. # Process 1. Find and open the repository 2. Guard a whole-tree restore behind `--force` 3. Determine files to restore 4. If `--dry-run`, preview changes 5. Otherwise, restore files to pristine state

(&self)

Source from the content-addressed store, hash-verified

329 /// 4. If `--dry-run`, preview changes
330 /// 5. Otherwise, restore files to pristine state
331 fn run(&self) -> CliResult<()> {
332 // Find repository
333 let repo_root = find_repository_root()?;
334 let repo = Repository::open(&repo_root).map_err(CliError::Repository)?;
335
336 // Compute status once. Restore only touches tracked files, so we skip
337 // the untracked scan, and we reuse this single status for both the
338 // safety guard and the file list (no second tree walk).
339 let status = repo
340 .status(Self::status_options())
341 .map_err(CliError::Repository)?;
342
343 let has_changes = !status.is_clean();
344
345 // Safety guard: only a whole-working-copy restore (no paths named)
346 // requires --force. Naming specific files is explicit consent to
347 // discard them, exactly like `git restore <file>`.
348 if self.requires_force(has_changes) {
349 return Err(CliError::RequiresForce {
350 operation: "restore".to_string(),
351 });
352 }
353
354 // Determine files to restore, paired with their status.
355 let files_to_restore = self.files_to_restore(&status);
356
357 // Handle dry-run for a single file by printing its pristine content to
358 // stdout (useful for piping). This only makes sense when the argument
359 // is exactly one concrete file:
360 // - a directory or prefix filter (e.g. `src/`) has no pristine content
361 // of its own and must fall through to the listing branch;
362 // - an Added file would be untracked, not restored, so it lists too.
363 let single_added = files_to_restore
364 .first()
365 .map(|(_, s)| *s == FileStatus::Added)
366 .unwrap_or(false);
367 let single_file_arg = self.files.len() == 1
368 && !self.files[0].ends_with('/')
369 && !repo_root.join(&self.files[0]).is_dir();
370 if self.dry_run && single_file_arg && !single_added {
371 return self.dry_run_single_file(&repo, &self.files[0]);
372 }
373
374 // Dry run mode - just show what would happen
375 if self.dry_run {
376 if files_to_restore.is_empty() {
377 println!("{}", self.nothing_to_restore_message());
378 } else {
379 for (path, file_status) in &files_to_restore {
380 if *file_status == FileStatus::Added {
381 println!("Would untrack: {} (kept on disk)", path.display());
382 } else {
383 println!("Would restore: {}", path.display());
384 }
385 }
386 println!();
387 print_hint(&format!(
388 "(dry run - {} would be restored)",

Callers

nothing calls this directly

Calls 14

find_repository_rootFunction · 0.85
print_hintFunction · 0.85
print_warningFunction · 0.85
print_successFunction · 0.85
requires_forceMethod · 0.80
files_to_restoreMethod · 0.80
is_dirMethod · 0.80
dry_run_single_fileMethod · 0.80
displayMethod · 0.80
restore_fileMethod · 0.80
statusMethod · 0.45
is_cleanMethod · 0.45

Tested by

no test coverage detected