feat(renaming): add move to parent directory functionality - #11
Conversation
There was a problem hiding this comment.
Pull Request Overview
This pull request adds functionality to handle directory renaming edge cases where the entire directory name gets cleaned (becomes empty), by moving the directory's contents to the parent directory instead of creating an empty directory name.
- Adds a new
MoveToParentoperation type to handle directories whose names are completely cleaned - Implements logic to detect when directory cleaning results in empty names and triggers the move operation
- Adds comprehensive file moving logic with conflict resolution and cleanup of empty directories
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/data.rs | Adds new MoveToParent enum variant to the Operation enum |
| src/main.rs | Implements detection logic for empty directory names and file moving operations with conflict resolution |
| src/p2tree.rs | Adds display formatting for the new MoveToParent operation in the tree view |
| if counter > 999 { | ||
| eprintln!( | ||
| "{} 无法找到可用的移动目标(尝试了999个后缀): {:?}", | ||
| "[错误]".red(), |
There was a problem hiding this comment.
The magic number 999 should be defined as a named constant to improve maintainability and make the limit configurable.
| if counter > 999 { | |
| eprintln!( | |
| "{} 无法找到可用的移动目标(尝试了999个后缀): {:?}", | |
| "[错误]".red(), | |
| if counter > MAX_FILENAME_ATTEMPTS { | |
| eprintln!( | |
| "{} 无法找到可用的移动目标(尝试了{}个后缀): {:?}", | |
| "[错误]".red(), | |
| MAX_FILENAME_ATTEMPTS, |
| if counter > 999 { | ||
| eprintln!( | ||
| "{} 无法找到可用的移动目标(尝试了999个后缀): {:?}", | ||
| "[错误]".red(), |
There was a problem hiding this comment.
The hardcoded number 999 in the error message should reference the same constant as the counter limit to avoid inconsistency.
| if counter > 999 { | |
| eprintln!( | |
| "{} 无法找到可用的移动目标(尝试了999个后缀): {:?}", | |
| "[错误]".red(), | |
| if counter > COUNTER_LIMIT { | |
| eprintln!( | |
| "{} 无法找到可用的移动目标(尝试了{}个后缀): {:?}", | |
| "[错误]".red(), | |
| COUNTER_LIMIT, |
| if let Ok(entries) = std::fs::read_dir(&dir_path) { | ||
| for entry in entries { | ||
| if let Ok(entry) = entry { | ||
| let source_path = entry.path(); | ||
| let filename = entry.file_name(); | ||
| let mut target_path = parent_dir.join(&filename); | ||
|
|
||
| // 处理命名冲突 | ||
| if target_path.exists() { | ||
| let original_name = filename.to_string_lossy(); | ||
| let (name_without_ext, extension) = |
There was a problem hiding this comment.
The error case for read_dir failure is handled at line 488, but this silent failure here could mask important errors. Consider logging or handling the error case explicitly.
| if let Ok(entries) = std::fs::read_dir(&dir_path) { | |
| for entry in entries { | |
| if let Ok(entry) = entry { | |
| let source_path = entry.path(); | |
| let filename = entry.file_name(); | |
| let mut target_path = parent_dir.join(&filename); | |
| // 处理命名冲突 | |
| if target_path.exists() { | |
| let original_name = filename.to_string_lossy(); | |
| let (name_without_ext, extension) = | |
| match std::fs::read_dir(&dir_path) { | |
| Ok(entries) => { | |
| for entry in entries { | |
| if let Ok(entry) = entry { | |
| let source_path = entry.path(); | |
| let filename = entry.file_name(); | |
| let mut target_path = parent_dir.join(&filename); | |
| // 处理命名冲突 | |
| if target_path.exists() { | |
| let original_name = filename.to_string_lossy(); | |
| let (name_without_ext, extension) = |
| if let Ok(entries) = std::fs::read_dir(&dir_path) { | ||
| for entry in entries { | ||
| if let Ok(entry) = entry { | ||
| let source_path = entry.path(); | ||
| let filename = entry.file_name(); | ||
| let mut target_path = parent_dir.join(&filename); | ||
|
|
||
| // 处理命名冲突 | ||
| if target_path.exists() { | ||
| let original_name = filename.to_string_lossy(); | ||
| let (name_without_ext, extension) = |
There was a problem hiding this comment.
[nitpick] Consider collecting entries into a vector first to handle potential I/O errors more gracefully and provide better error reporting when multiple entries fail to process.
| if let Ok(entries) = std::fs::read_dir(&dir_path) { | |
| for entry in entries { | |
| if let Ok(entry) = entry { | |
| let source_path = entry.path(); | |
| let filename = entry.file_name(); | |
| let mut target_path = parent_dir.join(&filename); | |
| // 处理命名冲突 | |
| if target_path.exists() { | |
| let original_name = filename.to_string_lossy(); | |
| let (name_without_ext, extension) = | |
| let entries: Vec<_> = match std::fs::read_dir(&dir_path) { | |
| Ok(read_dir) => read_dir | |
| .filter_map(|entry| match entry { | |
| Ok(entry) => Some(entry), | |
| Err(e) => { | |
| eprintln!( | |
| "{} 无法读取目录条目: {:?}: {}", | |
| "[错误]".red(), | |
| dir_path, | |
| e | |
| ); | |
| None | |
| } | |
| }) | |
| .collect(), | |
| Err(e) => { | |
| eprintln!("{} 无法读取目录内容: {:?}: {}", "[错误]".red(), dir_path, e); | |
| Vec::new() | |
| } | |
| }; | |
| for entry in entries { | |
| let source_path = entry.path(); | |
| let filename = entry.file_name(); | |
| let mut target_path = parent_dir.join(&filename); | |
| // 处理命名冲突 | |
| if target_path.exists() { | |
| let original_name = filename.to_string_lossy(); | |
| let (name_without_ext, extension) = |
当整个目录名符合清理规则被清理时,将其下内容移动到上一层。(因为系统不允许空的目录名)