添加PathExt Trait,简化Path使用

This commit is contained in:
mrbeanc
2023-12-30 16:51:22 +08:00
parent 1a79141090
commit 4250d26c4a
9 changed files with 86 additions and 26 deletions

View File

@@ -5,7 +5,7 @@ use colored::Colorize;
use crate::commands::status;
use crate::models::index::FileMetaData;
use crate::models::*;
use crate::utils::util;
use crate::utils::{util, PathExt};
/// add是对index的操作不会对工作区产生影响
/// @see <a href="https://juejin.cn/post/7053831273277554696">git add .git add -Agit add -ugit add * 的区别与联系</a>
@@ -41,7 +41,7 @@ pub fn add(raw_paths: Vec<String>, all: bool, mut update: bool) {
fn add_a_file(file: &Path, index: &mut Index) {
let workdir = util::get_working_dir().unwrap();
if !util::is_sub_path(file, &workdir) {
if !file.is_sub_to(&workdir) {
//文件不在工作区内
println!("fatal: '{}' is outside workdir at '{}'", file.display(), workdir.display());
return;
@@ -52,7 +52,7 @@ fn add_a_file(file: &Path, index: &mut Index) {
return;
}
let rel_path = util::to_cur_relative_path(file);
let rel_path = file.to_relative();
if !file.exists() {
//文件被删除
index.remove(file);

View File

@@ -6,7 +6,7 @@ use std::{
use crate::{
models::*,
utils::{util, Store},
utils::{util, PathExt, Store},
};
/// 统计[工作区]中相对于target_blobs已删除的文件根据filters进行过滤
@@ -18,7 +18,7 @@ fn get_worktree_deleted_files_in_filters(
.iter()
.filter(|(path, _)| {
assert!(path.is_absolute()); //
!path.exists() && util::include_in_paths(path, filters)
!path.exists() && path.include_in(filters)
})
.map(|(path, _)| path.clone())
.collect() //HashSet自动去重
@@ -34,7 +34,7 @@ fn get_index_deleted_files_in_filters(
.iter()
.filter(|(path, _)| {
assert!(path.is_absolute());
!index.contains(path) && util::include_in_paths(path, filters)
!index.contains(path) && path.include_in(filters)
})
.map(|(path, _)| path.clone())
.collect() //HashSet自动去重
@@ -53,7 +53,7 @@ fn preprocess_filters(filters: Option<&Vec<PathBuf>>) -> Vec<PathBuf> {
fn preprocess_blobs(blobs: &Vec<(PathBuf, Hash)>) -> HashMap<PathBuf, Hash> {
blobs // 转为绝对路径 //TODO tree改变路径表示方式后这里需要修改
.iter()
.map(|(path, hash)| (util::to_workdir_absolute_path(path), hash.clone()))
.map(|(path, hash)| (path.to_absolute_workdir(), hash.clone()))
.collect() //to HashMap
}

View File

@@ -1,3 +1,4 @@
use crate::utils::PathExt;
use crate::{
models::{head, Commit, Index},
utils::util,
@@ -45,7 +46,7 @@ impl Changes {
[&mut change.new, &mut change.modified, &mut change.deleted]
.iter_mut()
.for_each(|paths| {
**paths = util::map(&**paths, |p| util::to_workdir_absolute_path(p));
**paths = util::map(&**paths, |p| p.to_absolute_workdir());
});
change
}
@@ -53,11 +54,10 @@ impl Changes {
/// 转换为相对路径to cur_dir注意要先转换为绝对路径
fn to_relative(&self) -> Changes {
let mut change = self.clone();
let cur_dir = util::cur_dir();
[&mut change.new, &mut change.modified, &mut change.deleted]
.iter_mut()
.for_each(|paths| {
**paths = util::map(&**paths, |p| util::get_relative_path(p, &cur_dir));
**paths = util::map(&**paths, |p| p.to_relative());
});
change
}
@@ -73,7 +73,7 @@ pub fn changes_to_be_committed() -> Changes {
let tracked_files = index
.get_tracked_files()
.iter()
.map(|f| util::to_workdir_relative_path(f))
.map(|f| f.to_relative_workdir())
.collect::<Vec<PathBuf>>();
if head_hash == "" {
// 初始提交
@@ -89,7 +89,7 @@ pub fn changes_to_be_committed() -> Changes {
for (tree_file, blob_hash) in tree_files.iter() {
let index_file = index_files.iter().find(|&f| f == tree_file);
if let Some(index_file) = index_file {
let index_path = util::to_workdir_absolute_path(index_file);
let index_path = index_file.to_absolute_workdir();
if !index.verify_hash(&index_path, blob_hash) {
change.modified.push(tree_file.clone());
}
@@ -112,11 +112,11 @@ pub fn changes_to_be_staged() -> Changes {
let index = Index::get_instance();
for file in index.get_tracked_files() {
if !file.exists() {
change.deleted.push(util::to_workdir_relative_path(&file));
change.deleted.push(file.to_relative_workdir());
} else if index.is_modified(&file) {
// 若文件元数据被修改才需要比较暂存区与文件的hash来判别内容修改
if !index.verify_hash(&file, &util::calc_file_hash(&file)) {
change.modified.push(util::to_workdir_relative_path(&file));
change.modified.push(file.to_relative_workdir());
}
}
}
@@ -124,7 +124,7 @@ pub fn changes_to_be_staged() -> Changes {
for file in files {
if !index.tracked(&file) {
//文件未被跟踪
change.new.push(util::to_workdir_relative_path(&file));
change.new.push(file.to_relative_workdir());
}
}
change

View File

@@ -1,3 +1,4 @@
use crate::utils::PathExt;
use crate::{models::*, utils::util};
use once_cell::unsync::Lazy;
use serde::{Deserialize, Serialize};
@@ -76,7 +77,7 @@ impl Index {
/// 预处理路径,统一形式为绝对路径
fn preprocess(path: &Path) -> PathBuf {
util::get_absolute_path(&path)
path.to_absolute()
}
// 添加文件
@@ -173,7 +174,7 @@ impl Index {
.entries
.iter()
.map(|(path, value)| {
let relative_path = util::get_relative_path(path, &self.working_dir);
let relative_path = util::get_relative_path_to_dir(path, &self.working_dir);
(relative_path, value.clone())
})
.collect();

View File

@@ -2,7 +2,7 @@ use std::{collections::HashSet, path::PathBuf};
use serde::{Deserialize, Serialize};
use crate::utils::{util, Store};
use crate::utils::{util, PathExt, Store};
use super::{Hash, Index};
/*Tree
@@ -41,7 +41,7 @@ fn store_path_to_tree(index: &Index, current_root: PathBuf) -> Tree {
let path_entries: Vec<PathBuf> = index
.get_tracked_files()
.iter()
.map(|file| util::to_workdir_relative_path(file))
.map(|file| file.to_relative_workdir())
.filter(|path| path.starts_with(&current_root))
.collect();
for path in path_entries.iter() {

View File

@@ -1,4 +1,6 @@
pub mod store;
pub use store::Store;
pub mod path_ext;
pub use path_ext::PathExt;
pub mod test;
pub mod util;

56
src/utils/path_ext.rs Normal file
View File

@@ -0,0 +1,56 @@
use crate::utils::util;
use std::path::{Path, PathBuf};
/**
Path的扩展 基于util 为了解耦不要再util中使用PathExt
*/
pub trait PathExt {
fn to_absolute(&self) -> PathBuf;
fn to_absolute_workdir(&self) -> PathBuf;
fn to_relative(&self) -> PathBuf;
fn to_relative_workdir(&self) -> PathBuf;
fn is_sub_to(&self, parent: &PathBuf) -> bool;
fn include_in<T, U>(&self, paths: U) -> bool
where
T: AsRef<Path>,
U: IntoIterator<Item = T>;
}
/*
在 Rust 中当你调用一个方法时Rust 会尝试自动解引用和自动引用auto-deref and auto-ref来匹配方法签名。
如果有一个为 Path 实现的方法,你可以在 PathBuf、&PathBuf、&&PathBuf 等上调用这个方法Rust 会自动进行必要的解引用。
*/
impl PathExt for Path {
/// 转换为绝对路径
fn to_absolute(&self) -> PathBuf {
util::get_absolute_path(&self)
}
/// 转换为绝对路径from workdir相对路径
fn to_absolute_workdir(&self) -> PathBuf {
util::to_workdir_absolute_path(&self)
}
/// 转换为相对路径to cur_dir
fn to_relative(&self) -> PathBuf {
util::get_relative_path(&self)
}
/// 转换为相对路径to workdir
fn to_relative_workdir(&self) -> PathBuf {
util::to_workdir_relative_path(&self)
}
/// 从字符串角度判断path是否是parent的子路径不检测存在性)
fn is_sub_to(&self, parent: &PathBuf) -> bool {
util::is_sub_path(&self, parent)
}
/// 判断是否在paths中包括子目录不检查存在
fn include_in<T, U>(&self, paths: U) -> bool
where
T: AsRef<Path>,
U: IntoIterator<Item = T>,
{
util::include_in_paths(&self, paths)
}
}

View File

@@ -95,7 +95,7 @@ pub fn is_sub_path(path: &Path, parent: &Path) -> bool {
is_parent_dir(path, parent)
}
/// 判断文件是否在paths中包括子目录不检查存在性
/// 判断是否在paths中包括子目录不检查存在性
pub fn include_in_paths<T, U>(path: &Path, paths: U) -> bool
where
T: AsRef<Path>,
@@ -252,7 +252,7 @@ pub fn list_workdir_files() -> Vec<PathBuf> {
}
/// 获取相对于dir的 规范化 相对路径(不包含../ ./
pub fn get_relative_path(path: &Path, dir: &Path) -> PathBuf {
pub fn get_relative_path_to_dir(path: &Path, dir: &Path) -> PathBuf {
// 先统一为绝对路径
let abs_path = if path.is_relative() {
get_absolute_path(path)
@@ -287,12 +287,12 @@ pub fn get_common_dir(p1: &Path, p2: &Path) -> PathBuf {
/// 获取相较于工作区(Working Dir)的相对路径
pub fn to_workdir_relative_path(path: &Path) -> PathBuf {
get_relative_path(path, &get_working_dir().unwrap())
get_relative_path_to_dir(path, &get_working_dir().unwrap())
}
/// 获取相较于当前目录的 规范化 相对路径(不包含../ ./
pub fn to_cur_relative_path(path: &Path) -> PathBuf {
get_relative_path(path, &cur_dir())
pub fn get_relative_path(path: &Path) -> PathBuf {
get_relative_path_to_dir(path, &cur_dir())
}
/// 获取相较于工作区(Working Dir)的绝对路径
@@ -336,7 +336,7 @@ pub fn get_file_mode(path: &Path) -> String {
/// 获取绝对路径相对于目录current_dir 不论是否存在
pub fn get_absolute_path(path: &Path) -> PathBuf {
get_absolute_path_to_dir(path, &std::env::current_dir().unwrap())
get_absolute_path_to_dir(path, &cur_dir())
}
/// 获取绝对路径相对于目录dir 不论是否存在
@@ -467,7 +467,7 @@ mod tests {
fn test_get_relative_path() {
test::setup_with_clean_mit();
let path = Path::new("../../src\\main.rs");
let rel_path = get_relative_path(&path, &cur_dir());
let rel_path = get_relative_path_to_dir(&path, &cur_dir());
println!("{:?}", rel_path);
assert_eq!(rel_path, path);

View File

@@ -0,0 +1 @@