aboutsummaryrefslogtreecommitdiff
path: root/src/dots.rs
diff options
context:
space:
mode:
author[object Object] <max@bossi.ng>2025-07-29 16:52:39 +0200
committerGitHub <noreply@github.com>2025-07-29 16:52:39 +0200
commit5b2e7756e808151b5487f7e67b53accc745bee07 (patch)
treeb4b603501db9f659ff237cb1536c1e1c5759b793 /src/dots.rs
parent9c161a33c576b4ccb5908305b19c8e3e252e3a18 (diff)
merge develop into masterHEADmaster
* refactor: move platform-specifics into separate module * feat: Windows Support (wip) This is untested because I do not own Windows machines, and I think there are some problems concerning unlinking. * wip: inplementation of platform-agnostic deploying and removing etc... * feat: host-based deployment condition * feat: command flag to skip hostname checks * simplyfing the whole preparation step quite a bit
Diffstat (limited to 'src/dots.rs')
-rw-r--r--src/dots.rs46
1 files changed, 28 insertions, 18 deletions
diff --git a/src/dots.rs b/src/dots.rs
index 0259c0c..29059a1 100644
--- a/src/dots.rs
+++ b/src/dots.rs
@@ -1,42 +1,52 @@
-use std::fs::{remove_file, symlink_metadata};
-use std::os::unix::fs::symlink;
+use std::process::Command;
+use std::fs::symlink_metadata;
use std::path::PathBuf;
use dirs::home_dir;
use crate::config::Dot;
+use symlink::{symlink_auto, remove_symlink_auto};
-pub fn deploy_dots(dots: Vec<Dot>, dots_dir: PathBuf) {
- let prepended_dots = dots.iter().map(|m|
+
+fn prepare_dots(dots: Vec<Dot>, dots_dir: PathBuf, no_hostname_check: bool) -> Vec<Dot> {
+ let mut hostname = "*".to_string();
+ if !no_hostname_check {
+ // Deeply saddened there is no better way to do this :(
+ let hostname_cmd = Command::new("hostname").output().expect("failed to get hostname: command \"hostname\" failed");
+ let hostname_stdout = hostname_cmd.stdout;
+ let mut new_hostname = String::from_utf8(hostname_stdout.clone()).expect("failed to get hostname: unknown hostname encoding");
+ new_hostname.pop(); // stdout contains a newline
+ hostname = new_hostname;
+ }
+
+ let prepared_dots = dots.iter().filter(|dot| if no_hostname_check { true } else { dot.host == "*" || dot.host == hostname }).map(|m|
Dot {
source: dots_dir.join(&m.source),
- destination: if m.destination.is_absolute() { m.destination.clone() } else { prepend_user_dir(&m.destination) }
+ destination: if m.destination.is_absolute() { m.destination.clone() } else { prepend_user_dir(&m.destination) },
+ host: m.host.clone()
}
);
- for dot in prepended_dots {
+ prepared_dots.collect()
+}
+
+pub fn deploy_dots(dots: Vec<Dot>, dots_dir: PathBuf, no_hostname_check: bool) {
+ for dot in prepare_dots(dots, dots_dir, no_hostname_check) {
println!("linking from {} to {}", dot.source.display(), dot.destination.display());
- let _ = symlink(&dot.source, &dot.destination).map_err(|err|
+ let _ = symlink_auto(&dot.source, &dot.destination).map_err(|err|
eprintln!("failed to symlink: {}", err.to_string())
);
}
}
-pub fn unlink_dots(dots: Vec<Dot>, dots_dir: PathBuf) {
- let prepended_dots = dots.iter().map(|m|
- Dot {
- source: dots_dir.join(&m.source),
- destination: prepend_user_dir(&m.destination)
- }
- );
-
- for dot in prepended_dots {
- println!("unlinking {}", dot.destination.display());
+pub fn unlink_dots(dots: Vec<Dot>, dots_dir: PathBuf, no_hostname_check: bool) {
+ for dot in prepare_dots(dots, dots_dir, no_hostname_check) {
+ println!("unlinking {}", dot.destination.display());
let metadata = symlink_metadata(dot.destination.clone());
if metadata.is_err() {
eprintln!("failed to query metadata for {}: {}", dot.destination.display(), metadata.err().unwrap());
continue
}
if metadata.ok().unwrap().is_symlink() {
- let _ = remove_file(dot.destination).map_err(|err|
+ let _ = remove_symlink_auto(dot.destination).map_err(|err|
eprintln!("failed to remove symlink: {}", err)
);
}