aboutsummaryrefslogtreecommitdiff
path: root/dotup_cli/src/commands/link.rs
diff options
context:
space:
mode:
authordiogo464 <[email protected]>2021-07-09 06:40:35 -0400
committerdiogo464 <[email protected]>2021-07-09 06:40:35 -0400
commit3469dd5ab5b475a96f852b8c2e12a0b2c1c09caf (patch)
tree6ef11fad2c1c0a91352daecf0f126cb736cfaf52 /dotup_cli/src/commands/link.rs
parent7ad40992fb16c3bd70cf49981da0b560b2763a7d (diff)
Fixed problem with link creation.
Diffstat (limited to 'dotup_cli/src/commands/link.rs')
-rw-r--r--dotup_cli/src/commands/link.rs120
1 files changed, 70 insertions, 50 deletions
diff --git a/dotup_cli/src/commands/link.rs b/dotup_cli/src/commands/link.rs
index 81c396b..518bd4a 100644
--- a/dotup_cli/src/commands/link.rs
+++ b/dotup_cli/src/commands/link.rs
@@ -32,19 +32,25 @@ pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> {
32 }; 32 };
33 33
34 if let Some(destination) = destination { 34 if let Some(destination) = destination {
35 let collected_paths = if opts.directory { 35 let params = if opts.directory {
36 origins.to_vec() 36 origins
37 .iter()
38 .map(|p| LinkCreateParams {
39 origin: p.to_path_buf(),
40 destination: destination.clone(),
41 })
42 .collect()
37 } else { 43 } else {
38 collect_file_type(origins, FileType::File)? 44 let mut params = Vec::new();
45 for origin in origins {
46 link(&depot, &origin, &destination, &origin, &mut params)?;
47 }
48 params
39 }; 49 };
40 50
41 for path in collected_paths { 51 for link_params in params {
42 let link_desc = LinkCreateParams { 52 log::info!("Creating link : {}", link_params);
43 origin: path, 53 depot.create_link(link_params)?;
44 destination: destination.clone(),
45 };
46 log::info!("Creating link : {}", link_desc);
47 depot.create_link(link_desc)?;
48 } 54 }
49 } else { 55 } else {
50 let base_path = match origins { 56 let base_path = match origins {
@@ -63,48 +69,62 @@ pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> {
63 Ok(()) 69 Ok(())
64} 70}
65 71
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 72fn link(
67enum FileType { 73 depot: &Depot,
68 File, 74 origin: &Path,
69 Directory, 75 destination: &Path,
76 base: &Path,
77 params: &mut Vec<LinkCreateParams>,
78) -> anyhow::Result<()> {
79 let metadata = std::fs::metadata(origin)?;
80 if metadata.is_file() {
81 link_file(depot, origin, destination, base, params)?;
82 } else if metadata.is_dir() {
83 link_directory_recursive(depot, origin, destination, base, params)?;
84 }
85 Ok(())
70} 86}
71 87
72/// Collects canonical files of the given type starting from, and including, entry_paths 88fn link_file(
73fn collect_file_type( 89 depot: &Depot,
74 entry_paths: impl IntoIterator<Item = impl AsRef<Path>>, 90 origin: &Path,
75 collect_type: FileType, 91 destination: &Path,
76) -> anyhow::Result<Vec<PathBuf>> { 92 base: &Path,
77 let entry_paths: Vec<PathBuf> = entry_paths 93 params: &mut Vec<LinkCreateParams>,
78 .into_iter() 94) -> anyhow::Result<()> {
79 .map(|p| p.as_ref().to_path_buf()) 95 let origin_canonical = origin
80 .collect(); 96 .canonicalize()
81 let mut collected = Vec::new(); 97 .expect("Failed to canonicalize origin path");
82 let mut pending: Vec<_> = entry_paths.iter().cloned().filter(|p| p.is_dir()).collect(); 98 let base_canonical = base
83 99 .canonicalize()
84 for path in entry_paths { 100 .expect("Failed to canonicalize base path");
85 let path = path.canonicalize()?; 101
86 if (path.is_file() && collect_type == FileType::File) 102 log::debug!("Origin canonical : {}", origin_canonical.display());
87 || (path.is_dir() && collect_type == FileType::Directory) 103 log::debug!("Base : {}", base.display());
88 { 104
89 collected.push(path); 105 let partial = origin_canonical
90 } 106 .strip_prefix(base_canonical)
91 } 107 .expect("Failed to remove prefix from origin path");
108 let destination = destination.join(partial);
109
110 let link_params = LinkCreateParams {
111 origin: origin_canonical,
112 destination,
113 };
114 params.push(link_params);
115 Ok(())
116}
92 117
93 while let Some(dir_path) = pending.pop() { 118fn link_directory_recursive(
94 for entry in dir_path.read_dir()? { 119 depot: &Depot,
95 let entry = entry?; 120 dir_path: &Path,
96 let filetype = entry.file_type()?; 121 destination: &Path,
97 122 base: &Path,
98 if filetype.is_file() && collect_type == FileType::File { 123 params: &mut Vec<LinkCreateParams>,
99 collected.push(entry.path()); 124) -> anyhow::Result<()> {
100 } else if filetype.is_dir() { 125 for origin in dir_path.read_dir()? {
101 if collect_type == FileType::Directory { 126 let origin = origin?.path();
102 collected.push(entry.path()); 127 link(depot, &origin, destination, base, params)?;
103 }
104 pending.push(entry.path());
105 }
106 }
107 } 128 }
108 129 Ok(())
109 Ok(collected)
110} 130}