mirror of
https://github.com/MrBeanCpp/MIT.git
synced 2026-02-09 21:25:08 +08:00
fix: restore删除文件时,级联检查删除空文件夹(除了当前目录)
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user