添加PathExt Trait,简化Path使用

This commit is contained in:
mrbeanc
2024-01-02 17:21:11 +08:00
parent 642094cfca
commit a802778797
8 changed files with 78 additions and 14 deletions

View File

@@ -5,6 +5,7 @@ use colored::Colorize;
use crate::commands::status;
use crate::models::index::FileMetaData;
use crate::models::*;
use crate::utils::path_ext::PathExt;
use crate::utils::util;
/// add是对index的操作不会对工作区产生影响
@@ -40,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;
@@ -51,7 +52,7 @@ fn add_a_file(file: &Path, index: &mut Index) {
return;
}
let rel_path = util::get_relative_path(file);
let rel_path = file.to_relative();
if !file.exists() {
//文件被删除
index.remove(file);

View File

@@ -4,6 +4,7 @@ use std::{
path::PathBuf,
};
use crate::utils::path_ext::PathExt;
use crate::{
models::*,
utils::{store, util},
@@ -23,7 +24,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自动去重
@@ -39,7 +40,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自动去重
@@ -58,7 +59,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,4 +1,5 @@
use crate::models::head;
use crate::utils::path_ext::PathExt;
use crate::{
models::{Blob, Commit, Index},
utils::util,
@@ -47,7 +48,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
}
@@ -80,7 +81,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 == "" {
// 初始提交
@@ -96,7 +97,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());
}
@@ -119,12 +120,12 @@ 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来判别内容修改
let dry_blob = Blob::dry_new(util::read_workfile(&file));
if !index.verify_hash(&file, &dry_blob.get_hash()) {
change.modified.push(util::to_workdir_relative_path(&file));
change.modified.push(file.to_relative_workdir());
}
}
}
@@ -132,7 +133,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::path_ext::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()
}
// 添加文件

View File

@@ -2,6 +2,7 @@ use std::{collections::HashSet, path::PathBuf};
use serde::{Deserialize, Serialize};
use crate::utils::PathExt;
use crate::utils::{store, util};
use super::{Hash, Index};
@@ -41,7 +42,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,3 +1,5 @@
pub mod path_ext;
pub use path_ext::PathExt;
pub mod store;
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

@@ -8,6 +8,7 @@ use std::{
};
use crate::models::Index;
use crate::utils::PathExt;
// 执行测试的储存库
use super::util;
@@ -114,7 +115,7 @@ pub fn ensure_no_file(path: &Path) {
/** 列出子文件夹 */
pub fn list_subdir(path: &Path) -> io::Result<Vec<PathBuf>> {
let mut files = Vec::new();
let path = util::get_absolute_path(path);
let path = path.to_absolute();
if path.is_dir() {
for entry in fs::read_dir(path)? {
let entry = entry?;