diff --git a/src/models/index.rs b/src/models/index.rs index 00a6dd6..053f277 100644 --- a/src/models/index.rs +++ b/src/models/index.rs @@ -1,12 +1,12 @@ use crate::models::blob::Blob; use crate::models::object::Hash; use crate::utils::util; +use crate::utils::util::get_relative_path; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; use std::time::SystemTime; -use crate::utils::util::{get_relative_path}; // 文件元数据结构 #[derive(Serialize, Deserialize, Debug, Clone)] @@ -105,12 +105,12 @@ impl Index { } /// 与暂存区比较,确定文件自上次add以来是否被编辑(内容不一定修改,还需要算hash) - pub fn is_modified(&self, file: &Path) -> bool{ + pub fn is_modified(&self, file: &Path) -> bool { if let Some(self_data) = self.get(file) { if let Ok(meta) = file.metadata() { - let same = self_data.created_time == meta.created().unwrap_or(SystemTime::now()) - && self_data.modified_time == meta.modified().unwrap_or(SystemTime::now()) - && self_data.size == meta.len(); + let same = self_data.created_time == meta.created().unwrap_or(SystemTime::now()) + && self_data.modified_time == meta.modified().unwrap_or(SystemTime::now()) + && self_data.size == meta.len(); !same } else { @@ -131,8 +131,10 @@ impl Index { let path = Index::get_path(); if path.exists() { let json = fs::read_to_string(path).expect("无法读取index"); - let relative_index: HashMap = serde_json::from_str(&json).expect("无法解析index"); - self.entries = relative_index.into_iter() + let relative_index: HashMap = + serde_json::from_str(&json).expect("无法解析index"); + self.entries = relative_index + .into_iter() .map(|(path, value)| { let abs_path = self.working_dir.join(path); (abs_path, value) @@ -151,7 +153,9 @@ impl Index { /// 二进制序列化 pub fn save(&mut self) { //要先转化为相对路径 - let relative_index: HashMap = self.entries.iter() + let relative_index: HashMap = self + .entries + .iter() .map(|(path, value)| { let relative_path = get_relative_path(path, &self.working_dir); (relative_path, value.clone()) @@ -200,19 +204,15 @@ mod tests { #[test] fn test_save() { util::setup_test_with_clean_mit(); - let mut index = Index::new(); let path = PathBuf::from("../mit_test_storage/.mit/HEAD"); //测试../相对路径的处理 index.add(path.clone(), FileMetaData::new(&Blob::new(&path), &path)); - let path = PathBuf::from("中文路径测试.txt"); - index.add( - path.clone(), - FileMetaData::new( - &Blob::new(&path), - &path, - ), - ); + let 中文路径 = "中文路径.txt"; + util::ensure_test_file(Path::new(中文路径), None); + let path = PathBuf::from(中文路径); + index.add(path.clone(), FileMetaData::new(&Blob::new(&path), &path)); index.save(); + println!("{:?}", index.entries); } } diff --git a/src/utils/util.rs b/src/utils/util.rs index 30d086e..983415b 100644 --- a/src/utils/util.rs +++ b/src/utils/util.rs @@ -1,10 +1,12 @@ use sha1::{Digest, Sha1}; +use std::io::Write; use std::path::{Path, PathBuf}; -use std::{fs, io}; +use std::{fs, io, option}; pub const ROOT_DIR: &str = ".mit"; pub const TEST_DIR: &str = "mit_test_storage"; // 执行测试的储存库 +/* tools for test */ fn setup_test_dir() { color_backtrace::install(); // colorize backtrace let cargo_path = std::env::var("CARGO_MANIFEST_DIR"); @@ -57,6 +59,20 @@ pub fn setup_test_without_mit() { } } +pub fn ensure_test_file(path: &Path, content: option::Option<&str>) { + // 以测试目录为根目录,创建文件 + let mut file = fs::File::create(get_working_dir().unwrap().join(path)) + .expect(format!("无法创建文件:{:?}", path).as_str()); + if let Some(content) = content { + file.write(content.as_bytes()).unwrap(); + } else { + // 写入文件名 + file.write(path.file_name().unwrap().to_str().unwrap().as_bytes()) + .unwrap(); + } +} + +/* tools for mit */ pub fn calc_hash(data: &String) -> String { let mut hasher = Sha1::new(); hasher.update(data); @@ -147,6 +163,10 @@ pub fn get_relative_path(path: &Path, dir: &Path) -> PathBuf { relative_path.to_path_buf() } +pub fn to_root_relative_path(path: &Path) -> PathBuf { + get_relative_path(path, &get_working_dir().unwrap()) +} + fn is_executable(path: &str) -> bool { #[cfg(not(target_os = "windows"))] { @@ -167,8 +187,15 @@ fn is_executable(path: &str) -> bool { } pub fn get_file_mode(path: &Path) -> String { - if is_executable(path.to_str().unwrap()) { - "100755".to_string() + // if is_executable(path.to_str().unwrap()) { + // "100755".to_string() + // } else { + // "100644".to_string() + // } + if path.is_dir() { + "40000".to_string() // 目录 + } else if is_executable(path.to_str().unwrap()) { + "100755".to_string() // 可执行文件 } else { "100644".to_string() }