diff options
Diffstat (limited to 'dotup_cli/src/commands/status.rs')
| -rw-r--r-- | dotup_cli/src/commands/status.rs | 175 |
1 files changed, 0 insertions, 175 deletions
diff --git a/dotup_cli/src/commands/status.rs b/dotup_cli/src/commands/status.rs deleted file mode 100644 index b7221db..0000000 --- a/dotup_cli/src/commands/status.rs +++ /dev/null | |||
| @@ -1,175 +0,0 @@ | |||
| 1 | use std::path::{Path, PathBuf}; | ||
| 2 | |||
| 3 | use ansi_term::Colour; | ||
| 4 | use clap::Parser; | ||
| 5 | use dotup::{Depot, Link}; | ||
| 6 | |||
| 7 | use crate::{utils, Config}; | ||
| 8 | |||
| 9 | /// Shows information about links | ||
| 10 | /// | ||
| 11 | /// If a link is created for a file that already had a link then the old link will be overwritten. | ||
| 12 | /// By default creating a link to a directory will recursively link all files under that | ||
| 13 | /// directory, to actually link a directory use the --directory flag. | ||
| 14 | #[derive(Parser)] | ||
| 15 | pub struct Opts { | ||
| 16 | /// The location where links will be installed to. | ||
| 17 | /// Defaults to the home directory. | ||
| 18 | #[clap(long)] | ||
| 19 | install_base: Option<PathBuf>, | ||
| 20 | |||
| 21 | /// The paths to show the status of | ||
| 22 | paths: Vec<PathBuf>, | ||
| 23 | } | ||
| 24 | |||
| 25 | #[derive(Debug)] | ||
| 26 | struct State { | ||
| 27 | max_depth: u32, | ||
| 28 | install_path: PathBuf, | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> { | ||
| 32 | let mut depot = utils::read_depot(&config.archive_path)?; | ||
| 33 | |||
| 34 | // walk dir | ||
| 35 | // if node is file: | ||
| 36 | // if linked | ||
| 37 | // print name in green and destination blue | ||
| 38 | // if invalid | ||
| 39 | // print name and destination red | ||
| 40 | // if not linked | ||
| 41 | // print name in gray | ||
| 42 | // if node is directory: | ||
| 43 | // if linked | ||
| 44 | // print name in green and destination blue | ||
| 45 | // if invalid | ||
| 46 | // print name and destination red | ||
| 47 | // if not linked: | ||
| 48 | // print name in gray | ||
| 49 | // if contains files that are linked/invalid: | ||
| 50 | // recurse into directory | ||
| 51 | // | ||
| 52 | |||
| 53 | let depot_base = depot.base_path(); | ||
| 54 | let mut paths = Vec::new(); | ||
| 55 | for path in opts.paths { | ||
| 56 | let canonical = dotup::utils::weakly_canonical(&path); | ||
| 57 | if canonical.starts_with(depot_base) { | ||
| 58 | paths.push(canonical); | ||
| 59 | } else { | ||
| 60 | log::warn!("Path '{}' is outside the depot", path.display()); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | if paths.is_empty() { | ||
| 65 | paths.push(PathBuf::from(".")); | ||
| 66 | } | ||
| 67 | |||
| 68 | let state = State { | ||
| 69 | max_depth: u32::MAX, | ||
| 70 | install_path: config.install_path, | ||
| 71 | }; | ||
| 72 | |||
| 73 | let (directories, files) = utils::collect_read_dir_split(".")?; | ||
| 74 | for path in directories.into_iter().chain(files.into_iter()) { | ||
| 75 | display_status_path(&depot, &state, &path, 0); | ||
| 76 | } | ||
| 77 | |||
| 78 | utils::write_depot(&depot)?; | ||
| 79 | |||
| 80 | Ok(()) | ||
| 81 | } | ||
| 82 | |||
| 83 | fn display_status_path(depot: &Depot, state: &State, path: &Path, depth: u32) { | ||
| 84 | if depth == state.max_depth { | ||
| 85 | return; | ||
| 86 | } | ||
| 87 | |||
| 88 | if path.is_dir() { | ||
| 89 | display_status_directory(depot, state, path, depth); | ||
| 90 | } else { | ||
| 91 | display_status_file(depot, state, path, depth); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | fn display_status_directory(depot: &Depot, state: &State, path: &Path, depth: u32) { | ||
| 96 | assert!(path.is_dir()); | ||
| 97 | if depth == state.max_depth || !depot.subpath_has_links(path) { | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | if let Some(link) = depot.get_link_by_path(path) { | ||
| 102 | print_link(depot, state, link, depth); | ||
| 103 | } else { | ||
| 104 | for entry in std::fs::read_dir(path).unwrap() { | ||
| 105 | let entry = match entry { | ||
| 106 | Ok(entry) => entry, | ||
| 107 | Err(_) => continue, | ||
| 108 | }; | ||
| 109 | let entry_path = entry.path().canonicalize().unwrap(); | ||
| 110 | let entry_path_stripped = entry_path | ||
| 111 | .strip_prefix(std::env::current_dir().unwrap()) | ||
| 112 | .unwrap(); | ||
| 113 | |||
| 114 | print_identation(depth); | ||
| 115 | println!( | ||
| 116 | "{}", | ||
| 117 | Colour::Yellow.paint(&format!("{}", path.file_name().unwrap().to_string_lossy())) | ||
| 118 | ); | ||
| 119 | |||
| 120 | display_status_path(depot, state, &entry_path_stripped, depth + 1); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | fn display_status_file(depot: &Depot, state: &State, path: &Path, depth: u32) { | ||
| 126 | print_identation(depth); | ||
| 127 | if let Some(link) = depot.get_link_by_path(path) { | ||
| 128 | print_link(depot, state, link, depth); | ||
| 129 | } else { | ||
| 130 | print_unlinked(path, depth); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | fn print_link(depot: &Depot, state: &State, link: &Link, depth: u32) { | ||
| 135 | let origin = link.origin(); | ||
| 136 | let dest = link.destination(); | ||
| 137 | let filename = match origin.file_name() { | ||
| 138 | Some(filename) => filename, | ||
| 139 | None => return, | ||
| 140 | }; | ||
| 141 | |||
| 142 | print_identation(depth); | ||
| 143 | if depot.is_link_installed(link, &state.install_path) { | ||
| 144 | println!( | ||
| 145 | "{} -> {}", | ||
| 146 | Colour::Green.paint(&format!("{}", filename.to_string_lossy())), | ||
| 147 | Colour::Blue.paint(&format!("{}", dest.display())), | ||
| 148 | ); | ||
| 149 | } else { | ||
| 150 | println!( | ||
| 151 | "{}", | ||
| 152 | Colour::Red.paint(&format!( | ||
| 153 | "{} -> {}", | ||
| 154 | filename.to_string_lossy(), | ||
| 155 | dest.display() | ||
| 156 | )) | ||
| 157 | ); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | fn print_unlinked(path: &Path, depth: u32) { | ||
| 162 | let filename = match path.file_name() { | ||
| 163 | Some(filename) => filename, | ||
| 164 | None => return, | ||
| 165 | }; | ||
| 166 | |||
| 167 | print_identation(depth); | ||
| 168 | println!("{}", filename.to_string_lossy()); | ||
| 169 | } | ||
| 170 | |||
| 171 | fn print_identation(depth: u32) { | ||
| 172 | for i in 0..depth { | ||
| 173 | print!(" "); | ||
| 174 | } | ||
| 175 | } | ||
