fix: restore删除文件时,级联检查删除空文件夹(除了当前目录)

This commit is contained in:
mrbeanc
2023-12-24 00:30:02 +08:00
parent f61f2627ee
commit 3272b793da
2 changed files with 48 additions and 31 deletions

View File

@@ -68,6 +68,8 @@ pub fn restore_worktree(filter: Option<&Vec<PathBuf>>, 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<PathBuf>>, 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<PathBuf>>, target_blobs: &Vec<(PathBuf,
}
/**
对于工作区中的新文件,若已跟踪,则删除;若未跟踪,则保留<br>
对于暂存区中被删除的文件,同样会恢复
对于暂存区中被删除的文件,同样会恢复<br>
注意:不会删除空文件夹
*/
pub fn restore(paths: Vec<String>, source: String, worktree: bool, staged: bool) {
// TODO 尝试合并restore_index和restore_worktree逻辑上是一致的
@@ -212,11 +199,7 @@ pub fn restore(paths: Vec<String>, 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() {

View File

@@ -253,10 +253,13 @@ pub fn list_subpath(path: &Path) -> io::Result<Vec<PathBuf>> {
}
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<PathBuf> {
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);
}
}