Skip to content

Commit 96d3670

Browse files
committed
use relative path in symlink (wip)
1 parent 9396510 commit 96d3670

File tree

4 files changed

+61
-21
lines changed

4 files changed

+61
-21
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2024"
55

66
[dependencies]
77
clap = { version = "4.5.42", features = ["derive"] }
8+
pathdiff = "0.2.3"
89

910
[dev-dependencies]
1011
tempfile = "3.20.0"

src/link.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
use pathdiff::diff_paths;
12
use std::{
3+
env,
24
os::unix::fs::symlink,
35
path::{Path, PathBuf},
46
};
@@ -31,39 +33,54 @@ impl Link {
3133
let package_path = self.dir.join(package);
3234

3335
if !package_path.exists() {
34-
println!("WARNING: Package '{}' not found", package);
36+
println!("Package '{}' not found", package);
3537
return;
3638
}
3739

3840
self.traverse(&package_path, &self.target);
3941
}
4042

4143
fn traverse(&self, source_path: &Path, destination_path: &Path) {
42-
if source_path.is_file() || !destination_path.exists() {
44+
if !destination_path.exists() || source_path.is_file() {
4345
self.create_symlink(source_path, destination_path);
4446
return;
4547
}
4648

4749
traverse(source_path, destination_path, |s, d| self.traverse(s, d));
4850
}
4951

50-
fn create_symlink(&self, src: &Path, dst: &Path) {
51-
if dst.exists() {
52-
let warning = "WARNING: File exists and will not be symlinked";
53-
println!("{}: {}", warning, dst.display());
52+
fn create_symlink(&self, original: &Path, link: &Path) {
53+
if link.exists() {
54+
println!("File exists and will not be symlinked: {}", link.display());
5455
return;
5556
}
5657

57-
let message = format!("LINK: {} => {}", dst.display(), src.display());
58+
let Some(link_parent) = link.parent() else {
59+
println!("Failed to get parent directory for {}", link.display());
60+
return;
61+
};
62+
63+
// for relative path exists check
64+
if let Err(e) = env::set_current_dir(link_parent) {
65+
println!("{e}");
66+
return;
67+
}
68+
69+
let original_relative = diff_paths(original, link_parent)
70+
.filter(|p| p.exists())
71+
.unwrap_or_else(|| original.to_path_buf());
72+
73+
println!(
74+
"LINK: {} => {}",
75+
link.display(),
76+
original_relative.display()
77+
);
5878

5979
if self.simulate {
60-
println!("[SIMULATE] {message}");
6180
return;
6281
};
6382

64-
println!("{message}");
65-
66-
if let Err(e) = symlink(src, dst) {
83+
if let Err(e) = symlink(original_relative, link) {
6784
println!("LINK ERROR: {e}");
6885
}
6986
}

src/unlink.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::{
2-
fs,
2+
env, fs,
33
path::{Path, PathBuf},
44
};
55

@@ -40,29 +40,44 @@ impl Unlink {
4040
traverse(source_path, destination_path, |s, d| self.traverse(s, d));
4141
}
4242

43-
fn remove_symlink(&self, src: &Path, dst: &Path) {
44-
if !dst.exists() || !dst.is_symlink() {
43+
fn remove_symlink(&self, original: &Path, link: &Path) {
44+
if !link.exists() || !link.is_symlink() {
4545
return;
4646
}
4747

48-
let Ok(link_target) = fs::read_link(dst) else {
48+
let Ok(link_target) = fs::read_link(link) else {
4949
return;
5050
};
5151

52-
if link_target != src {
52+
let Some(link_parent) = link.parent() else {
53+
println!("Failed to get parent directory for {}", link.display());
54+
return;
55+
};
56+
57+
if let Err(e) = env::set_current_dir(link_parent) {
58+
println!("{e}");
5359
return;
5460
}
5561

56-
let message = format!("UNLINK: {}", dst.display());
62+
match fs::canonicalize(link_target) {
63+
Ok(link_target) => {
64+
if link_target != original {
65+
return;
66+
}
67+
}
68+
Err(e) => {
69+
println!("{e}");
70+
return;
71+
}
72+
}
73+
74+
println!("UNLINK: {}", link.display());
5775

5876
if self.simulate {
59-
println!("[SIMULATE] {}", message);
6077
return;
6178
}
6279

63-
println!("{message}");
64-
65-
if let Err(e) = fs::remove_file(dst) {
80+
if let Err(e) = fs::remove_file(link) {
6681
println!("UNLINK ERROR: {e}");
6782
}
6883
}

0 commit comments

Comments
 (0)