diff --git a/src/commands/restore.rs b/src/commands/restore.rs index 1fb54c5..656c721 100644 --- a/src/commands/restore.rs +++ b/src/commands/restore.rs @@ -68,6 +68,8 @@ pub fn restore_worktree(filter: Option<&Vec>, target_blobs: &Vec<(PathB let input_paths = preprocess_filters(filter); //预处理filter 将None转化为workdir let target_blobs = preprocess_blobs(target_blobs); //预处理target_blobs 转化为绝对路径HashMap + //TODO 输出不存在于target和worktree中文件 + let deleted_files = get_worktree_deleted_files_in_filters(&input_paths, &target_blobs); //统计所有目录中已删除的文件 let mut file_paths = util::integrate_paths(&input_paths); //根据用户输入整合存在的文件(绝对路径) @@ -101,23 +103,7 @@ pub fn restore_worktree(filter: Option<&Vec>, target_blobs: &Vec<(PathB if index.tracked(path) { //文件已跟踪 fs::remove_file(&path).unwrap(); - } - } - } - } - // 出现在filter中的目录的子目录如果已经是空目录,需要删除 - for path in &input_paths { - if path.is_dir() && util::list_files(path).unwrap().is_empty() { - if !util::check_root_dir(path) { - fs::remove_dir_all(path).unwrap(); - } - } else { - for sub_path in util::list_subpath(path).unwrap() { - if sub_path.is_dir() - && util::list_files(&sub_path).unwrap().is_empty() - && !util::check_root_dir(&sub_path) - { - fs::remove_dir_all(sub_path).unwrap(); + util::clear_empty_dir(&path); // 级联删除 清理空目录 } } } @@ -166,7 +152,8 @@ pub fn restore_index(filter: Option<&Vec>, target_blobs: &Vec<(PathBuf, } /** 对于工作区中的新文件,若已跟踪,则删除;若未跟踪,则保留
-对于暂存区中被删除的文件,同样会恢复 +对于暂存区中被删除的文件,同样会恢复
+注意:不会删除空文件夹 */ pub fn restore(paths: Vec, source: String, worktree: bool, staged: bool) { // TODO 尝试合并restore_index和restore_worktree(逻辑上是一致的) @@ -212,11 +199,7 @@ pub fn restore(paths: Vec, source: String, worktree: bool, staged: bool) mod test { use std::path::PathBuf; - use crate::{ - commands, - models::index::Index, - utils::util::{self, ensure_no_file}, - }; + use crate::{commands, models::index::Index, utils::util}; #[test] fn test_restore_stage() { diff --git a/src/utils/util.rs b/src/utils/util.rs index 6f19e8d..8e2a8ed 100644 --- a/src/utils/util.rs +++ b/src/utils/util.rs @@ -253,10 +253,13 @@ pub fn list_subpath(path: &Path) -> io::Result> { } Ok(files) } -/** 检查一个路径是否是工作目录 */ -pub fn check_root_dir(path: &Path) -> bool { - // 检查子文件夹是否有ROOT - let path = get_absolute_path(path); +/** 检查一个dir是否包含.mit(考虑.mit嵌套) */ +pub fn include_root_dir(dir: &Path) -> bool { + // 检查子文件夹是否有ROOT_DIR + if !dir.is_dir() { + return false; + } + let path = get_absolute_path(dir); for sub_path in fs::read_dir(path).unwrap() { let sub_path = sub_path.unwrap().path(); if sub_path.file_name().unwrap() == ROOT_DIR { @@ -265,6 +268,37 @@ pub fn check_root_dir(path: &Path) -> bool { } return false; } + +/// 级联删除空目录,直到遇到 [工作区根目录 | 当前目录] +pub fn clear_empty_dir(dir: &Path) { + let mut dir = if dir.is_dir() { + dir.to_path_buf() + } else { + dir.parent().unwrap().to_path_buf() + }; + // 不能删除工作区根目录 & 当前目录 + while !include_root_dir(&dir) && !is_cur_dir(&dir) { + if is_empty_dir(&dir) { + fs::remove_dir(&dir).unwrap(); + } else { + break; //一旦发现非空目录,停止级联删除 + } + dir.pop(); + } +} + +pub fn is_empty_dir(dir: &Path) -> bool { + if !dir.is_dir() { + return false; + } + fs::read_dir(dir).unwrap().next().is_none() +} + +pub fn is_cur_dir(dir: &Path) -> bool { + let cur_dir = std::env::current_dir().unwrap(); //应该是绝对路径吧 + get_absolute_path(dir) == cur_dir +} + /// 列出工作区所有文件(包括子文件夹) pub fn list_workdir_files() -> Vec { if let Ok(files) = list_files(&get_working_dir().unwrap()) { @@ -547,14 +581,14 @@ mod tests { fs::remove_file(f).unwrap(); }); list_subpath(Path::new("./")).unwrap().iter().for_each(|f| { - if check_root_dir(f) { + if include_root_dir(f) { fs::remove_dir_all(f).unwrap(); } }); - assert_eq!(check_root_dir(Path::new("./")), true); + assert_eq!(include_root_dir(Path::new("./")), true); fs::create_dir("./src").unwrap_or_default(); - assert_eq!(check_root_dir(Path::new("./src")), false); + assert_eq!(include_root_dir(Path::new("./src")), false); fs::create_dir("./src/.mit").unwrap_or_default(); - assert_eq!(check_root_dir(Path::new("./src")), true); + assert_eq!(include_root_dir(Path::new("./src")), true); } }