git_workspace/commands/
archive.rs

1use super::lock;
2use crate::lockfile::Lockfile;
3use crate::utils;
4use anyhow::Context;
5use console::style;
6use std::path::{Path, PathBuf};
7
8use super::get_all_repositories_to_archive;
9
10pub fn archive(workspace: &Path, force: bool) -> anyhow::Result<()> {
11    // Archive any repositories that have been deleted from the lockfile.
12    lock(workspace)?;
13
14    let lockfile = Lockfile::new(workspace.join("workspace-lock.toml"));
15    let repositories = lockfile.read().context("Error reading lockfile")?;
16    let repos_to_archive = get_all_repositories_to_archive(workspace, repositories)?;
17
18    if !force {
19        for (from_path, to_path) in &repos_to_archive {
20            let relative_from_path = from_path.strip_prefix(workspace).unwrap();
21            let relative_to_path = to_path.strip_prefix(workspace).unwrap();
22            println!(
23                "Move {} to {}",
24                style(relative_from_path.display()).yellow(),
25                style(relative_to_path.display()).green()
26            );
27        }
28        println!(
29            "Will archive {} projects",
30            style(repos_to_archive.len()).red()
31        );
32        if repos_to_archive.is_empty() || !utils::confirm("Proceed?", false, " ", true) {
33            return Ok(());
34        }
35    }
36    if !repos_to_archive.is_empty() {
37        archive_repositories(repos_to_archive)?;
38    }
39    Ok(())
40}
41
42fn archive_repositories(to_archive: Vec<(PathBuf, PathBuf)>) -> anyhow::Result<()> {
43    println!("Archiving {} repositories", to_archive.len());
44    for (from_dir, to_dir) in to_archive.into_iter() {
45        let parent_dir = &to_dir.parent().with_context(|| {
46            format!("Failed to get the parent directory of {}", to_dir.display())
47        })?;
48        // Create all the directories that are needed:
49        fs_extra::dir::create_all(parent_dir, false)
50            .with_context(|| format!("Error creating directory {}", to_dir.display()))?;
51
52        // Move the directory to the archive directory:
53        match std::fs::rename(&from_dir, &to_dir) {
54            Ok(_) => {
55                println!(
56                    "Moved {} to {}",
57                    style(from_dir.display()).yellow(),
58                    style(to_dir.display()).green()
59                );
60            }
61            Err(e) => {
62                eprintln!(
63                    "{} {e}\n  Target: {}\n  Dest:   {}\nPlease remove existing directory before retrying",
64                    style("Error moving directory!").red(),
65                    style(from_dir.display()).yellow(),
66                    style(to_dir.display()).green()
67                );
68            }
69        };
70    }
71
72    Ok(())
73}