aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authordiogo464 <[email protected]>2022-02-07 15:45:21 +0000
committerdiogo464 <[email protected]>2022-02-07 15:52:30 +0000
commit406a3e662b3fafd73ab72a6f7bd4e22131654dfb (patch)
treebf044ef831f5938fdb21224f434f9e896c98b8b6 /src/main.rs
parentcbb2edb0b523f2494fd543857195792a8eda1b62 (diff)
snapshot
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs77
1 files changed, 54 insertions, 23 deletions
diff --git a/src/main.rs b/src/main.rs
index 1cb68d4..f623450 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -923,7 +923,7 @@ pub mod dotup {
923 923
924 pub fn link(&mut self, origin: impl AsRef<Path>, destination: impl AsRef<Path>) { 924 pub fn link(&mut self, origin: impl AsRef<Path>, destination: impl AsRef<Path>) {
925 let link_result: anyhow::Result<()> = try { 925 let link_result: anyhow::Result<()> = try {
926 let origin = self.prepare_origin_path(origin.as_ref())?; 926 let origin = self.prepare_relative_path(origin.as_ref())?;
927 let destination = destination.as_ref(); 927 let destination = destination.as_ref();
928 self.depot.link_create(origin, destination)?; 928 self.depot.link_create(origin, destination)?;
929 }; 929 };
@@ -936,7 +936,7 @@ pub mod dotup {
936 pub fn unlink(&mut self, paths: impl Iterator<Item = impl AsRef<Path>>) { 936 pub fn unlink(&mut self, paths: impl Iterator<Item = impl AsRef<Path>>) {
937 for origin in paths { 937 for origin in paths {
938 let unlink_result: anyhow::Result<()> = try { 938 let unlink_result: anyhow::Result<()> = try {
939 let origin = self.prepare_origin_path(origin.as_ref())?; 939 let origin = self.prepare_relative_path(origin.as_ref())?;
940 let search_results = self.depot.link_search(&origin)?; 940 let search_results = self.depot.link_search(&origin)?;
941 match search_results { 941 match search_results {
942 depot::SearchResult::Found(link_id) => { 942 depot::SearchResult::Found(link_id) => {
@@ -959,7 +959,7 @@ pub mod dotup {
959 let mut already_linked: HashSet<LinkID> = Default::default(); 959 let mut already_linked: HashSet<LinkID> = Default::default();
960 for origin in paths { 960 for origin in paths {
961 let install_result: anyhow::Result<()> = try { 961 let install_result: anyhow::Result<()> = try {
962 let origin = self.prepare_origin_path(origin.as_ref())?; 962 let origin = self.prepare_relative_path(origin.as_ref())?;
963 let canonical_pairs = self.canonical_pairs_under(&origin)?; 963 let canonical_pairs = self.canonical_pairs_under(&origin)?;
964 for pair in canonical_pairs { 964 for pair in canonical_pairs {
965 if already_linked.contains(&pair.link_id) { 965 if already_linked.contains(&pair.link_id) {
@@ -978,7 +978,7 @@ pub mod dotup {
978 pub fn uninstall(&self, paths: impl Iterator<Item = impl AsRef<Path>>) { 978 pub fn uninstall(&self, paths: impl Iterator<Item = impl AsRef<Path>>) {
979 for origin in paths { 979 for origin in paths {
980 let uninstall_result: anyhow::Result<()> = try { 980 let uninstall_result: anyhow::Result<()> = try {
981 let origin = self.prepare_origin_path(origin.as_ref())?; 981 let origin = self.prepare_relative_path(origin.as_ref())?;
982 let canonical_pairs = self.canonical_pairs_under(&origin)?; 982 let canonical_pairs = self.canonical_pairs_under(&origin)?;
983 for pair in canonical_pairs { 983 for pair in canonical_pairs {
984 self.symlink_uninstall(&pair.origin, &pair.destination)?; 984 self.symlink_uninstall(&pair.origin, &pair.destination)?;
@@ -1001,7 +1001,7 @@ pub mod dotup {
1001 let origins = { 1001 let origins = {
1002 let mut v = Vec::new(); 1002 let mut v = Vec::new();
1003 for origin in origins { 1003 for origin in origins {
1004 match self.prepare_origin_path(origin.as_ref()) { 1004 match self.prepare_relative_path(origin.as_ref()) {
1005 Ok(origin) => v.push(origin), 1005 Ok(origin) => v.push(origin),
1006 Err(e) => { 1006 Err(e) => {
1007 println!("invalid link {} : {e}", origin.as_ref().display()); 1007 println!("invalid link {} : {e}", origin.as_ref().display());
@@ -1066,7 +1066,7 @@ pub mod dotup {
1066 fn status_path_to_item(&self, canonical_path: &Path) -> anyhow::Result<StatusItem> { 1066 fn status_path_to_item(&self, canonical_path: &Path) -> anyhow::Result<StatusItem> {
1067 debug_assert!(canonical_path.is_absolute()); 1067 debug_assert!(canonical_path.is_absolute());
1068 debug_assert!(canonical_path.exists()); 1068 debug_assert!(canonical_path.exists());
1069 let relative_path = self.prepare_origin_path(&canonical_path)?; 1069 let relative_path = self.prepare_relative_path(&canonical_path)?;
1070 1070
1071 let item = if canonical_path.is_dir() { 1071 let item = if canonical_path.is_dir() {
1072 if let Some(link_id) = self.depot.link_find(&relative_path)? { 1072 if let Some(link_id) = self.depot.link_find(&relative_path)? {
@@ -1204,7 +1204,7 @@ pub mod dotup {
1204 .unwrap_or_default() 1204 .unwrap_or_default()
1205 } 1205 }
1206 1206
1207 fn prepare_origin_path(&self, origin: &Path) -> anyhow::Result<PathBuf> { 1207 fn prepare_relative_path(&self, origin: &Path) -> anyhow::Result<PathBuf> {
1208 let canonical = utils::weakly_canonical(origin); 1208 let canonical = utils::weakly_canonical(origin);
1209 let relative = canonical 1209 let relative = canonical
1210 .strip_prefix(&self.depot_dir) 1210 .strip_prefix(&self.depot_dir)
@@ -1214,7 +1214,7 @@ pub mod dotup {
1214 1214
1215 // returns the canonical pairs for all links under `path`. 1215 // returns the canonical pairs for all links under `path`.
1216 fn canonical_pairs_under(&self, path: &Path) -> anyhow::Result<Vec<CanonicalPair>> { 1216 fn canonical_pairs_under(&self, path: &Path) -> anyhow::Result<Vec<CanonicalPair>> {
1217 let origin = self.prepare_origin_path(path)?; 1217 let origin = self.prepare_relative_path(path)?;
1218 let mut canonical_pairs = Vec::new(); 1218 let mut canonical_pairs = Vec::new();
1219 for link_id in self.depot.links_under(origin)? { 1219 for link_id in self.depot.links_under(origin)? {
1220 canonical_pairs.push(self.canonical_pair_from_link_id(link_id)); 1220 canonical_pairs.push(self.canonical_pair_from_link_id(link_id));
@@ -1250,11 +1250,19 @@ pub mod dotup {
1250 fn symlink_install(&self, origin: &Path, destination: &Path) -> anyhow::Result<()> { 1250 fn symlink_install(&self, origin: &Path, destination: &Path) -> anyhow::Result<()> {
1251 debug_assert!(origin.is_absolute()); 1251 debug_assert!(origin.is_absolute());
1252 debug_assert!(destination.is_absolute()); 1252 debug_assert!(destination.is_absolute());
1253 log::debug!(
1254 "symlink_install : {} -> {}",
1255 origin.display(),
1256 destination.display()
1257 );
1253 1258
1254 if let Some(destination_parent) = destination.parent() { 1259 let destination_parent = destination
1255 std::fs::create_dir_all(destination_parent) 1260 .parent()
1256 .context("Failed to create directories")?; 1261 .ok_or_else(|| anyhow::anyhow!("destination has no parent component"))?;
1257 } 1262 std::fs::create_dir_all(destination_parent).context("Failed to create directories")?;
1263 // need to do this beacause if the destination path ends in '/' because the symlink
1264 // functions will treat it as a directory but we want a file with that name.
1265 let destination = destination.with_file_name(destination.file_name().unwrap());
1258 1266
1259 let destination_exists = destination.exists(); 1267 let destination_exists = destination.exists();
1260 let destination_is_symlink = destination.is_symlink(); 1268 let destination_is_symlink = destination.is_symlink();
@@ -1264,9 +1272,16 @@ pub mod dotup {
1264 } 1272 }
1265 1273
1266 if destination_is_symlink { 1274 if destination_is_symlink {
1275 log::debug!("symlink already exists, removing before recreating");
1267 std::fs::remove_file(&destination)?; 1276 std::fs::remove_file(&destination)?;
1268 } 1277 }
1269 std::os::unix::fs::symlink(origin, destination).context("Failed to create symlink")?; 1278
1279 log::debug!(
1280 "creating filesystem symlink {} -> {}",
1281 origin.display(),
1282 destination.display()
1283 );
1284 std::os::unix::fs::symlink(origin, destination).context("failed to create symlink")?;
1270 1285
1271 Ok(()) 1286 Ok(())
1272 } 1287 }
@@ -1274,6 +1289,7 @@ pub mod dotup {
1274 fn symlink_uninstall(&self, origin: &Path, destination: &Path) -> anyhow::Result<()> { 1289 fn symlink_uninstall(&self, origin: &Path, destination: &Path) -> anyhow::Result<()> {
1275 debug_assert!(origin.is_absolute()); 1290 debug_assert!(origin.is_absolute());
1276 debug_assert!(destination.is_absolute()); 1291 debug_assert!(destination.is_absolute());
1292 let destination = destination.with_file_name(destination.file_name().unwrap());
1277 1293
1278 if destination.is_symlink() { 1294 if destination.is_symlink() {
1279 let symlink_destination = destination.read_link()?.canonicalize()?; 1295 let symlink_destination = destination.read_link()?.canonicalize()?;
@@ -1329,16 +1345,6 @@ mod utils {
1329 1345
1330 pub const DEFAULT_DEPOT_FILE_NAME: &str = ".depot"; 1346 pub const DEFAULT_DEPOT_FILE_NAME: &str = ".depot";
1331 1347
1332 /// collects the result of std::fs::read_dir into two vecs, the first one contains all the
1333 /// directories and the second one all the files.
1334 pub fn collect_read_dir_split(
1335 dir: impl AsRef<Path>,
1336 ) -> anyhow::Result<(Vec<PathBuf>, Vec<PathBuf>)> {
1337 Ok(collect_paths_in_dir(dir)?
1338 .into_iter()
1339 .partition(|p| p.is_dir()))
1340 }
1341
1342 pub fn collect_paths_in_dir(dir: impl AsRef<Path>) -> anyhow::Result<Vec<PathBuf>> { 1348 pub fn collect_paths_in_dir(dir: impl AsRef<Path>) -> anyhow::Result<Vec<PathBuf>> {
1343 Ok(std::fs::read_dir(dir)? 1349 Ok(std::fs::read_dir(dir)?
1344 .filter_map(|e| e.ok()) 1350 .filter_map(|e| e.ok())
@@ -1465,6 +1471,7 @@ mod utils {
1465use std::path::PathBuf; 1471use std::path::PathBuf;
1466 1472
1467use clap::Parser; 1473use clap::Parser;
1474use flexi_logger::Logger;
1468use utils::DEFAULT_DEPOT_FILE_NAME; 1475use utils::DEFAULT_DEPOT_FILE_NAME;
1469 1476
1470#[derive(Parser, Debug)] 1477#[derive(Parser, Debug)]
@@ -1478,8 +1485,19 @@ pub struct Flags {
1478#[derive(Parser, Debug)] 1485#[derive(Parser, Debug)]
1479#[clap(author, version, about, long_about = None)] 1486#[clap(author, version, about, long_about = None)]
1480struct Args { 1487struct Args {
1488 /// A level of verbosity, and can be used multiple times
1489 ///
1490 /// Level 1 - Info
1491 ///
1492 /// Level 2 - Debug
1493 ///
1494 /// Level 3 - Trace
1495 #[clap(short, long, parse(from_occurrences))]
1496 verbose: i32,
1497
1481 #[clap(flatten)] 1498 #[clap(flatten)]
1482 flags: Flags, 1499 flags: Flags,
1500
1483 #[clap(subcommand)] 1501 #[clap(subcommand)]
1484 command: SubCommand, 1502 command: SubCommand,
1485} 1503}
@@ -1497,6 +1515,19 @@ enum SubCommand {
1497 1515
1498fn main() -> anyhow::Result<()> { 1516fn main() -> anyhow::Result<()> {
1499 let args = Args::parse(); 1517 let args = Args::parse();
1518
1519 let log_level = match args.verbose {
1520 0 => "warn",
1521 1 => "info",
1522 2 => "debug",
1523 _ => "trace",
1524 };
1525
1526 Logger::try_with_env_or_str(log_level)?
1527 .format(flexi_logger::colored_default_format)
1528 .set_palette("196;208;32;198;15".to_string())
1529 .start()?;
1530
1500 match args.command { 1531 match args.command {
1501 SubCommand::Init(cmd_args) => command_init(args.flags, cmd_args), 1532 SubCommand::Init(cmd_args) => command_init(args.flags, cmd_args),
1502 SubCommand::Link(cmd_args) => command_link(args.flags, cmd_args), 1533 SubCommand::Link(cmd_args) => command_link(args.flags, cmd_args),