diff options
Diffstat (limited to 'dotup_cli/src/commands/link.rs')
| -rw-r--r-- | dotup_cli/src/commands/link.rs | 134 |
1 files changed, 0 insertions, 134 deletions
diff --git a/dotup_cli/src/commands/link.rs b/dotup_cli/src/commands/link.rs deleted file mode 100644 index d1f61ea..0000000 --- a/dotup_cli/src/commands/link.rs +++ /dev/null | |||
| @@ -1,134 +0,0 @@ | |||
| 1 | use std::{ | ||
| 2 | fs::{DirEntry, Metadata}, | ||
| 3 | path::{Path, PathBuf}, | ||
| 4 | }; | ||
| 5 | |||
| 6 | use super::prelude::*; | ||
| 7 | |||
| 8 | /// Creates links | ||
| 9 | /// | ||
| 10 | /// If a link is created for a file that already had a link then the old link will be overwritten. | ||
| 11 | /// By default creating a link to a directory will recursively link all files under that | ||
| 12 | /// directory, to actually link a directory use the --directory flag. | ||
| 13 | #[derive(Parser)] | ||
| 14 | pub struct Opts { | ||
| 15 | /// Treats the paths as directories. This will create links to the actual directories instead | ||
| 16 | /// of recursively linking all files under them. | ||
| 17 | #[clap(long)] | ||
| 18 | directory: bool, | ||
| 19 | |||
| 20 | /// The paths to link. The last path is the destination. | ||
| 21 | paths: Vec<PathBuf>, | ||
| 22 | } | ||
| 23 | |||
| 24 | // TODO: require destination | ||
| 25 | // remove else branch | ||
| 26 | pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> { | ||
| 27 | let mut depot = utils::read_depot(&config.archive_path)?; | ||
| 28 | |||
| 29 | let (origins, destination) = match opts.paths.as_slice() { | ||
| 30 | p @ [] | p @ [_] => (p, None), | ||
| 31 | [o @ .., dest] => (o, Some(dest)), | ||
| 32 | _ => unreachable!(), | ||
| 33 | }; | ||
| 34 | |||
| 35 | if let Some(destination) = destination { | ||
| 36 | let params = if opts.directory { | ||
| 37 | origins | ||
| 38 | .iter() | ||
| 39 | .map(|p| LinkCreateParams { | ||
| 40 | origin: p.to_path_buf(), | ||
| 41 | destination: destination.clone(), | ||
| 42 | }) | ||
| 43 | .collect() | ||
| 44 | } else { | ||
| 45 | let mut params = Vec::new(); | ||
| 46 | for origin in origins { | ||
| 47 | generate_link_params(&depot, origin, destination, origin, &mut params)?; | ||
| 48 | } | ||
| 49 | params | ||
| 50 | }; | ||
| 51 | |||
| 52 | for link_params in params { | ||
| 53 | log::info!("Creating link : {}", link_params); | ||
| 54 | depot.create_link(link_params)?; | ||
| 55 | } | ||
| 56 | } else { | ||
| 57 | let base_path = match origins { | ||
| 58 | [] => std::env::current_dir()?, | ||
| 59 | [path] => path.clone(), | ||
| 60 | _ => unreachable!(), | ||
| 61 | }; | ||
| 62 | |||
| 63 | for link in utils::collect_links_by_base_paths(&depot, std::iter::once(base_path)) { | ||
| 64 | log::info!("{}", link); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | utils::write_depot(&depot)?; | ||
| 69 | |||
| 70 | Ok(()) | ||
| 71 | } | ||
| 72 | |||
| 73 | fn generate_link_params( | ||
| 74 | depot: &Depot, | ||
| 75 | origin: &Path, | ||
| 76 | destination: &Path, | ||
| 77 | base: &Path, | ||
| 78 | params: &mut Vec<LinkCreateParams>, | ||
| 79 | ) -> anyhow::Result<()> { | ||
| 80 | let metadata = std::fs::metadata(origin)?; | ||
| 81 | if metadata.is_file() { | ||
| 82 | generate_file_link_params(depot, origin, destination, base, params)?; | ||
| 83 | } else if metadata.is_dir() { | ||
| 84 | generate_directory_link_params_recursive(depot, origin, destination, base, params)?; | ||
| 85 | } | ||
| 86 | Ok(()) | ||
| 87 | } | ||
| 88 | |||
| 89 | fn generate_file_link_params( | ||
| 90 | depot: &Depot, | ||
| 91 | origin: &Path, | ||
| 92 | destination: &Path, | ||
| 93 | base: &Path, | ||
| 94 | params: &mut Vec<LinkCreateParams>, | ||
| 95 | ) -> anyhow::Result<()> { | ||
| 96 | let origin_canonical = origin | ||
| 97 | .canonicalize() | ||
| 98 | .expect("Failed to canonicalize origin path"); | ||
| 99 | let base_canonical = base | ||
| 100 | .canonicalize() | ||
| 101 | .expect("Failed to canonicalize base path"); | ||
| 102 | |||
| 103 | log::debug!("Origin canonical : {}", origin_canonical.display()); | ||
| 104 | log::debug!("Base : {}", base.display()); | ||
| 105 | |||
| 106 | let partial = origin_canonical | ||
| 107 | .strip_prefix(base_canonical) | ||
| 108 | .expect("Failed to remove prefix from origin path"); | ||
| 109 | let destination = destination.join(partial); | ||
| 110 | let origin = origin_canonical | ||
| 111 | .strip_prefix(depot.base_path()) | ||
| 112 | .unwrap_or(&origin_canonical); | ||
| 113 | |||
| 114 | let link_params = LinkCreateParams { | ||
| 115 | origin: origin.to_path_buf(), | ||
| 116 | destination, | ||
| 117 | }; | ||
| 118 | params.push(link_params); | ||
| 119 | Ok(()) | ||
| 120 | } | ||
| 121 | |||
| 122 | fn generate_directory_link_params_recursive( | ||
| 123 | depot: &Depot, | ||
| 124 | dir_path: &Path, | ||
| 125 | destination: &Path, | ||
| 126 | base: &Path, | ||
| 127 | params: &mut Vec<LinkCreateParams>, | ||
| 128 | ) -> anyhow::Result<()> { | ||
| 129 | for origin in dir_path.read_dir()? { | ||
| 130 | let origin = origin?.path(); | ||
| 131 | generate_link_params(depot, &origin, destination, base, params)?; | ||
| 132 | } | ||
| 133 | Ok(()) | ||
| 134 | } | ||
