diff --git a/src/commands/status.rs b/src/commands/status.rs index 605cc60..02f200e 100644 --- a/src/commands/status.rs +++ b/src/commands/status.rs @@ -2,20 +2,21 @@ use std::path::PathBuf; use crate::{ head, - models::{blob, index}, + models::{blob, index, commit}, utils::util, }; +use crate::utils::util::to_workdir_absolute_path; /** 获取需要commit的更改(staged) */ -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Changes { - pub new: Vec, + pub new: Vec, //todo PathBuf? pub modified: Vec, pub deleted: Vec, } fn __file_string(path: &PathBuf) -> String { - util::to_root_relative_path(&path) //todo: to_string_lossy() + util::to_root_relative_path(path) //todo: to_string_lossy() .as_os_str() .to_str() .unwrap() @@ -23,51 +24,40 @@ fn __file_string(path: &PathBuf) -> String { } pub fn changes_to_be_committed() -> Changes { - let mut change = Changes { //todo: Changes::default() - new: vec![], - modified: vec![], - deleted: vec![], - }; + let mut change = Changes::default(); let index = index::Index::new(); let head_hash = head::current_head_commit(); - if head_hash == "".to_string() { //todo: head_hash.is_empty() or head_hash == "" - // 初始提交 - change.new = index - .get_tracked_files() + let tracked_files = index.get_tracked_files(); + if head_hash == "" { // 初始提交 + change.new = tracked_files .iter() - .map(|f| __file_string(f)) + .map(__file_string) .collect(); return change; } - let commit = crate::models::commit::Commit::load(&head_hash); + let commit = commit::Commit::load(&head_hash); let tree = commit.get_tree(); - let tree_files = tree.get_recursive_blobs(); - let index_files: Vec = index - .get_tracked_files() + let tree_files = tree.get_recursive_blobs(); //相对路径 + let index_files: Vec = tracked_files .iter() .map(|f| util::to_root_relative_path(f)) .collect(); for tree_item in tree_files.iter() { - let index_file = index_files.iter().find(|f| **f == tree_item.0); - if index_file.is_none() { - change.deleted.push(__file_string(&tree_item.0)); //todo: abs_path? - } else { - let index_blob = blob::Blob::new( //todo: index有函数可以获取blob_hash 不需要new - util::get_working_dir() //todo: 优化:提取为变量 - .unwrap() - .join(index_file.unwrap()) - .as_path(), - ); - // XXX @mrbeanc 我看到Blob的new被改成调用save了。这里的实现希望比较Blob内容,不然就得读取文件内容。 - if index_blob.get_hash() != tree_item.1.get_hash() { + let index_file = index_files.iter().find(|&f| *f == tree_item.0); + if let Some(index_file) = index_file { + let index_path = to_workdir_absolute_path(index_file); + if !index.verify_hash(&index_path, &tree_item.1.get_hash()) { change.modified.push(__file_string(&tree_item.0)); } + } else { + change.deleted.push(__file_string(&tree_item.0)); //todo: abs_path? } + } for index_file in index_files.iter() { - let tree_item = tree_files.iter().find(|f| f.0 == **index_file); + let tree_item = tree_files.iter().find(|f| f.0 == *index_file); if tree_item.is_none() { change.new.push(__file_string(&index_file)); } @@ -87,7 +77,7 @@ pub fn status() { mod tests { use super::*; use crate::{commands::commit, utils::util}; - use std::{fs, path::Path}; + use std::{path::Path}; #[test] fn test_changes_to_be_committed() { @@ -107,6 +97,8 @@ mod tests { assert_eq!(change.modified.len(), 0); assert_eq!(change.deleted.len(), 0); + println!("{:?}", change); + commit::commit("test commit".to_string(), true); util::ensure_test_file(Path::new(test_file), Some("new content")); index.add( @@ -119,6 +111,8 @@ mod tests { assert_eq!(change.modified.len(), 1); assert_eq!(change.deleted.len(), 0); + println!("{:?}", change); + commit::commit("test commit".to_string(), true); index.remove( util::get_working_dir() @@ -131,5 +125,7 @@ mod tests { assert_eq!(change.new.len(), 0); assert_eq!(change.modified.len(), 0); assert_eq!(change.deleted.len(), 1); + + println!("{:?}", change); } } diff --git a/src/head.rs b/src/head.rs index 026425c..e602fe5 100644 --- a/src/head.rs +++ b/src/head.rs @@ -2,7 +2,7 @@ use crate::utils::util; pub enum Head { Detached(String), - Branch(String), + Branch(String), //todo Hash } pub fn current_head() -> Head { diff --git a/src/models/tree.rs b/src/models/tree.rs index e0ddf88..a1df197 100644 --- a/src/models/tree.rs +++ b/src/models/tree.rs @@ -1,6 +1,6 @@ use std::{ collections::HashMap, - path::{Component, PathBuf}, + path::{PathBuf}, }; use serde::{Deserialize, Serialize}; @@ -19,6 +19,7 @@ pub struct TreeEntry { pub name: String, // file name } +/// 相对路径 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Tree { #[serde(skip)] @@ -137,6 +138,7 @@ impl Tree { files } + ///注:相对路径 pub fn get_recursive_blobs(&self) -> Vec<(PathBuf, super::blob::Blob)> { let mut blobs = Vec::new(); for entry in self.entries.iter() { @@ -151,7 +153,7 @@ impl Tree { sub_blobs .iter() .map(|(path, blob)| { - (PathBuf::from(entry.name.clone()).join(path), blob.clone()) //todo: why join? + (PathBuf::from(entry.name.clone()).join(path), blob.clone()) }) .collect::>() .as_mut(), diff --git a/src/utils/util.rs b/src/utils/util.rs index 82d6e41..cf56731 100644 --- a/src/utils/util.rs +++ b/src/utils/util.rs @@ -169,8 +169,13 @@ pub fn to_root_relative_path(path: &Path) -> PathBuf { //todo: rename get_relative_path(path, &get_working_dir().unwrap()) } +/// 获取相较于工作区(Working Dir)的绝对路径 pub fn to_workdir_absolute_path(path: &Path) -> PathBuf { - get_working_dir().unwrap().join(path) + if path.is_relative() { + get_working_dir().unwrap().join(path) + } else { + path.to_path_buf() + } } fn is_executable(path: &str) -> bool {