libkelp/lib/cli/
save.rs

1use crate::lib::{
2    config::loader::load_cfg,
3    fsutil::{
4        copy::copy,
5        paths::{get_root, get_to_make},
6    },
7    structs::config::KelpDotConfig,
8    util::{os::get_host_os, scripts::run_script},
9};
10use anyhow::Context;
11use kelpdot_macros::*;
12use std::path::Path;
13/// Backup dotfiles
14pub fn save() -> anyhow::Result<()> {
15    let root = get_root()?;
16    cyan_print!("[INFO] Saving dotfiles {}...", root);
17    debug_print!("Building OS list...");
18    let os = get_host_os().with_context(|| red!("Unable to get host OS name!"))?; // Here we get guest os; If OS is unreconized, return a generic GNU / Linux System
19    cyan_print!("[INFO] Found Os {}", os.prettyname);
20    let config: KelpDotConfig = load_cfg(root.clone())?; // Load a KelpConfig struct wich is basically $DOTFILES_ROOT/kelp.yaml
21
22    if let Some(files) = config.homefiles {
23        // If config has "homefiles" keys, copy each $HOME/$FILE
24        let home = std::env::var("HOME").with_context(|| red!("Unable to get env var $HOME!"))?; // Get $HOME path or crash
25        debug_print!("Home: {}", home);
26
27        // Make sur that $DOTFILES_ROOT/home doesn't exist
28        // or doesn't contain files
29        if Path::new(&format!("{}/home", root)).exists() {
30            std::fs::remove_dir_all(&format!("{}/home", root))
31                .with_context(|| red!("Unable to remove old home directory!"))?;
32        }
33        std::fs::create_dir(format!("{}/home", root))?;
34        for f in files {
35            green_print!("[SAVE] Copying file {}...", f);
36            let path = format!("{}/{}", home, f.path);
37            let file = Path::new(&path);
38            // Make sur that file exists
39            if file.exists() {
40                // Get path to make
41                // Example:
42                // home/**.config/i3** directory
43                let tomake = get_to_make(f.path)?;
44                // Create the file
45                std::fs::create_dir_all(format!("{}/home/{}", root, tomake))?;
46                copy(
47                    path.clone(),
48                    format!(
49                        "{}/home/{}/{}",
50                        root,
51                        tomake,
52                        file.file_name().unwrap().to_str().unwrap().to_owned()
53                    ),
54                )?;
55            } else {
56                red_print!("[ERROR] File {} not found, skipping...", path);
57            }
58        }
59        cyan_print!("[OK] Homefiles saved!");
60    }
61    // If config has "rootfiles" key, backup every file
62    if let Some(files) = config.rootfiles {
63        for f in files {
64            green_print!("[SAVE] Copying file {}", f);
65            // Get path to make:
66            // Example:
67            // $DOTFILES_ROOT/etc/portage/repos.conf
68            let path = f.path.to_owned();
69            let tomake = get_to_make(f.path)?;
70            let file = Path::new(&path);
71            if file.exists() {
72                let file_name = file.file_name().unwrap().to_str().unwrap().to_owned();
73                let dest = format!("{}/{}/{}", root, tomake, &file_name);
74                if Path::new(&dest).exists() {
75                    if Path::new(&dest).is_file() {
76                        std::fs::remove_file(dest)?;
77                    } else {
78                        std::fs::remove_dir_all(dest)?;
79                    }
80                }
81                std::fs::create_dir_all(format!("{}/{}", root, tomake))
82                    .with_context(|| red!("Unable to create dir {}/{}", root, tomake))?;
83                copy(path.clone(), format!("{}/{}/{}", root, tomake, file_name))?;
84            }
85        }
86        cyan_print!("[OK] Rootfiles saved!");
87    }
88    if let Some(scripts) = config.postsave {
89        for script in scripts {
90            cyan_print!("[POSTSAVE] Running script {}", script.path);
91            run_script(root.clone(), script)?;
92        }
93    }
94    magenta_print!("[OK] All dotfiles saved!");
95    Ok(())
96}