mirror of
https://github.com/MrBeanCpp/MIT.git
synced 2026-02-04 10:54:47 +08:00
fix: status命令对当前目录进行过滤 & 改进util泛型模板
This commit is contained in:
@@ -119,7 +119,7 @@ pub fn restore_index(filter: Option<&Vec<PathBuf>>, target_blobs: &Vec<(PathBuf,
|
||||
let deleted_files_index = get_index_deleted_files_in_filters(&index, &input_paths, &target_blobs); //统计所有目录中已删除的文件
|
||||
|
||||
//1.获取index中包含于input_path的文件(使用paths进行过滤)
|
||||
let mut file_paths = util::filter_to_fit_paths(&index.get_tracked_files(), &input_paths);
|
||||
let mut file_paths: HashSet<PathBuf> = util::filter_to_fit_paths(&index.get_tracked_files(), &input_paths);
|
||||
|
||||
// 2.补充index中已删除的文件(相较于target_blobs)
|
||||
file_paths.extend(deleted_files_index); //已删除的文件
|
||||
|
||||
@@ -5,12 +5,13 @@ use crate::{
|
||||
utils::{util, util::check_repo_exist},
|
||||
};
|
||||
use colored::Colorize;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/** 获取需要commit的更改(staged)
|
||||
注:相对路径
|
||||
注:相对路径(to workdir)
|
||||
*/
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Changes {
|
||||
pub new: Vec<PathBuf>,
|
||||
pub modified: Vec<PathBuf>,
|
||||
@@ -21,8 +22,53 @@ impl Changes {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.new.is_empty() && self.modified.is_empty() && self.deleted.is_empty()
|
||||
}
|
||||
|
||||
/// 使用paths过滤,返回绝对路径
|
||||
pub fn filter_abs(&self, paths: &Vec<PathBuf>) -> Changes {
|
||||
let mut change = Changes::default();
|
||||
let abs_self = self.to_absolute(); //先要转换为绝对路径
|
||||
change.new = util::filter_to_fit_paths(&abs_self.new, paths);
|
||||
change.modified = util::filter_to_fit_paths(&abs_self.modified, paths);
|
||||
change.deleted = util::filter_to_fit_paths(&abs_self.deleted, paths);
|
||||
change
|
||||
}
|
||||
|
||||
/// 使用paths过滤,返回相对路径(to cur_dir)
|
||||
pub fn filter_relative(&self, paths: &Vec<PathBuf>) -> Changes {
|
||||
self.filter_abs(paths).to_relative()
|
||||
}
|
||||
|
||||
/// 转换为绝对路径(from workdir相对路径)
|
||||
pub fn to_absolute(&self) -> Changes {
|
||||
let mut change = self.clone();
|
||||
// change.new = util::map(&self.new, |p| util::to_workdir_absolute_path(p));
|
||||
// change.modified = util::map(&self.modified, |p| util::to_workdir_absolute_path(p));
|
||||
// change.deleted = util::map(&self.deleted, |p| util::to_workdir_absolute_path(p));
|
||||
//离谱子
|
||||
[&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));
|
||||
});
|
||||
change
|
||||
}
|
||||
|
||||
/// 转换为相对路径(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));
|
||||
});
|
||||
change
|
||||
}
|
||||
}
|
||||
|
||||
/** 比较暂存区与HEAD(最后一次Commit::Tree)的差异
|
||||
注:相对路径(to workdir)
|
||||
*/
|
||||
pub fn changes_to_be_committed() -> Changes {
|
||||
let mut change = Changes::default();
|
||||
let index = Index::new();
|
||||
@@ -63,11 +109,11 @@ pub fn changes_to_be_committed() -> Changes {
|
||||
change
|
||||
}
|
||||
|
||||
/// 比较工作区与暂存区的差异,返回相对路径(to workdir),不筛选
|
||||
pub fn changes_to_be_staged() -> Changes {
|
||||
let mut change = Changes::default();
|
||||
let index = Index::new();
|
||||
for file in index.get_tracked_files() {
|
||||
//TODO 考虑当前目录
|
||||
if !file.exists() {
|
||||
change.deleted.push(util::to_workdir_relative_path(&file));
|
||||
} else if index.is_modified(&file) {
|
||||
@@ -77,14 +123,13 @@ pub fn changes_to_be_staged() -> Changes {
|
||||
}
|
||||
}
|
||||
}
|
||||
let files = util::list_workdir_files(); //TODO 考虑当前目录
|
||||
let files = util::list_workdir_files(); // all the files
|
||||
for file in files {
|
||||
if !index.tracked(&file) {
|
||||
//文件未被跟踪
|
||||
change.new.push(util::to_workdir_relative_path(&file));
|
||||
}
|
||||
}
|
||||
|
||||
change
|
||||
}
|
||||
|
||||
@@ -104,8 +149,9 @@ pub fn status() {
|
||||
}
|
||||
}
|
||||
|
||||
let staged = changes_to_be_committed();
|
||||
let unstaged = changes_to_be_staged();
|
||||
// 对当前目录进行过滤 & 转换为相对路径
|
||||
let staged = changes_to_be_committed().filter_relative(&vec![util::cur_dir()]);
|
||||
let unstaged = changes_to_be_staged().filter_relative(&vec![util::cur_dir()]);
|
||||
if staged.is_empty() && unstaged.is_empty() {
|
||||
println!("nothing to commit, working tree clean");
|
||||
return;
|
||||
@@ -172,7 +218,7 @@ mod tests {
|
||||
assert_eq!(change.modified.len(), 0);
|
||||
assert_eq!(change.deleted.len(), 0);
|
||||
|
||||
println!("{:?}", change);
|
||||
println!("{:?}", change.to_absolute());
|
||||
|
||||
commit::commit("test commit".to_string(), true);
|
||||
util::ensure_test_file(Path::new(test_file), Some("new content"));
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
path::PathBuf,
|
||||
};
|
||||
use std::{collections::HashSet, path::PathBuf};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
@@ -174,17 +174,38 @@ where
|
||||
}
|
||||
|
||||
/// 过滤列表中的元素,对.iter().filter().cloned().collect()的简化
|
||||
pub fn filter<T, F>(items: &Vec<T>, pred: F) -> Vec<T>
|
||||
pub fn filter<'a, I, O, T, F>(items: I, pred: F) -> O
|
||||
where
|
||||
T: Clone,
|
||||
T: Clone + 'a,
|
||||
I: IntoIterator<Item = &'a T>,
|
||||
O: FromIterator<T>,
|
||||
F: Fn(&T) -> bool,
|
||||
{
|
||||
items.iter().filter(|item| pred(item)).cloned().collect()
|
||||
//items可以是一个引用
|
||||
items.into_iter().filter(|item| pred(item)).cloned().collect::<O>()
|
||||
}
|
||||
|
||||
/// 对列表中的元素应用func,对.iter().map().collect()的简化
|
||||
pub fn map<'a, I, O, T, F>(items: I, func: F) -> O
|
||||
where
|
||||
T: Clone + 'a,
|
||||
I: IntoIterator<Item = &'a T>,
|
||||
O: FromIterator<T>,
|
||||
F: Fn(&T) -> T,
|
||||
{
|
||||
//items可以是一个引用
|
||||
items.into_iter().map(|item| func(item)).collect::<O>()
|
||||
}
|
||||
|
||||
/// 过滤列表中的元素,使其在paths中(包括子目录),不检查存在性
|
||||
pub fn filter_to_fit_paths(items: &Vec<PathBuf>, paths: &Vec<PathBuf>) -> HashSet<PathBuf> {
|
||||
filter(items, |item| include_in_paths(item, paths)).into_iter().collect()
|
||||
pub fn filter_to_fit_paths<T, O>(items: &Vec<T>, paths: &Vec<T>) -> O
|
||||
where
|
||||
T: AsRef<Path> + Clone,
|
||||
O: FromIterator<T> + IntoIterator<Item = T>,
|
||||
{
|
||||
filter::<_, O, _, _>(items, |item| include_in_paths(item.as_ref(), paths))
|
||||
.into_iter()
|
||||
.collect::<O>()
|
||||
}
|
||||
|
||||
/// 检查文件是否在工作区内, 若不存在则false
|
||||
@@ -295,8 +316,11 @@ pub fn is_empty_dir(dir: &Path) -> bool {
|
||||
}
|
||||
|
||||
pub fn is_cur_dir(dir: &Path) -> bool {
|
||||
let cur_dir = std::env::current_dir().unwrap(); //应该是绝对路径吧
|
||||
get_absolute_path(dir) == cur_dir
|
||||
get_absolute_path(dir) == cur_dir()
|
||||
}
|
||||
|
||||
pub fn cur_dir() -> PathBuf {
|
||||
std::env::current_dir().unwrap() //应该是绝对路径吧
|
||||
}
|
||||
|
||||
/// 列出工作区所有文件(包括子文件夹)
|
||||
|
||||
Reference in New Issue
Block a user