Skip to content

Commit 4491418

Browse files
committed
fix: properly handle symlinks - show but don't follow (fixes #1)
1 parent abc954a commit 4491418

4 files changed

Lines changed: 33 additions & 4 deletions

File tree

src/display.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,13 @@ pub fn display_tree(
6161
// Sort: directories first, then alphabetically
6262
entries.sort_by_key(|e| {
6363
let path = e.path();
64-
let is_dir = path.is_dir();
64+
// Check if it's a symlink pointing to a directory
65+
let is_dir = if path.is_symlink() {
66+
// Don't follow symlinks to avoid infinite loops
67+
false
68+
} else {
69+
path.is_dir()
70+
};
6571
let name = e.file_name().to_string_lossy().to_lowercase();
6672
(!is_dir, name)
6773
});
@@ -72,7 +78,14 @@ pub fn display_tree(
7278
let is_last_entry = idx == total - 1;
7379
let path = entry.path();
7480
let name = entry.file_name().to_string_lossy().to_string();
75-
let is_dir = path.is_dir();
81+
82+
// Check if it's a symlink first - NEVER recurse into symlinks
83+
let is_symlink = path.is_symlink();
84+
let is_dir = if is_symlink {
85+
false // Treat symlinks as files to prevent recursion
86+
} else {
87+
path.is_dir()
88+
};
7689

7790
// Check if we should skip this entry
7891
if is_dir {
@@ -90,6 +103,7 @@ pub fn display_tree(
90103
if should_skip {
91104
// Count files in ignored directory
92105
let ignored_count = WalkDir::new(&path)
106+
.follow_links(false)
93107
.into_iter()
94108
.filter_map(|e| e.ok())
95109
.filter(|e| e.file_type().is_file())
@@ -145,7 +159,14 @@ pub fn display_tree(
145159

146160
// Display the entry
147161
let connector = if is_last_entry { "└── " } else { "├── " };
148-
let display_name = if is_dir {
162+
let display_name = if is_symlink {
163+
// Show symlink with arrow
164+
if let Ok(target) = fs::read_link(&path) {
165+
format!("{} -> {}", name, target.display()).cyan()
166+
} else {
167+
name.cyan()
168+
}
169+
} else if is_dir {
149170
format!("{}/", name).blue().bold()
150171
} else if is_executable(&path) {
151172
name.green().bold()

src/search.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub fn search_files(pattern: &str, start_path: &Path, max_depth: usize, flat: bo
2626

2727
// Search through all files
2828
for entry in WalkDir::new(start_path)
29+
.follow_links(false)
2930
.max_depth(max_depth)
3031
.into_iter()
3132
.filter_entry(|e| {

src/summary.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub fn display_summary(path: &Path) {
6565
// Track ignored items
6666
if is_dir {
6767
let file_count = WalkDir::new(&entry_path)
68+
.follow_links(false)
6869
.into_iter()
6970
.filter_map(|e| e.ok())
7071
.filter(|e| e.file_type().is_file())
@@ -121,6 +122,7 @@ fn display_directory_summary(entry_path: &Path, name: &str, custom_ignores: &[Re
121122
if is_subdir && (should_ignore_dir(&subname) || matches_custom_pattern(&subname, custom_ignores)) {
122123
// Count files in ignored subdir
123124
let ignored_count = WalkDir::new(&subpath)
125+
.follow_links(false)
124126
.into_iter()
125127
.filter_map(|e| e.ok())
126128
.filter(|e| e.file_type().is_file())
@@ -132,6 +134,7 @@ fn display_directory_summary(entry_path: &Path, name: &str, custom_ignores: &[Re
132134

133135
// Walk recursively to count visible items (skip ignored directories)
134136
for sub_entry in WalkDir::new(entry_path)
137+
.follow_links(false)
135138
.into_iter()
136139
.filter_entry(|e| {
137140
// Skip ignored directories during traversal
@@ -165,7 +168,10 @@ fn display_directory_summary(entry_path: &Path, name: &str, custom_ignores: &[Re
165168
}
166169

167170
// Get ALL stats recursively (including everything)
168-
for sub_entry in WalkDir::new(entry_path).into_iter().filter_map(|e| e.ok()) {
171+
for sub_entry in WalkDir::new(entry_path)
172+
.follow_links(false)
173+
.into_iter()
174+
.filter_map(|e| e.ok()) {
169175
if sub_entry.file_type().is_file() {
170176
total_file_count += 1;
171177
if let Ok(metadata) = sub_entry.metadata() {

src/utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub fn is_executable(path: &Path) -> bool {
4545
/// Get total size of a directory recursively
4646
pub fn get_dir_size(path: &Path) -> u64 {
4747
WalkDir::new(path)
48+
.follow_links(false)
4849
.into_iter()
4950
.filter_map(|e| e.ok())
5051
.filter_map(|e| e.metadata().ok())

0 commit comments

Comments
 (0)