From ffac740f974dd14604ebcd0d5790a272c1079264 Mon Sep 17 00:00:00 2001 From: mrbeanc Date: Wed, 20 Dec 2023 16:37:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=84=E7=90=86Windows=E4=B8=8B=E7=BB=9D?= =?UTF-8?q?=E5=AF=B9=E8=B7=AF=E5=BE=84=E8=BD=AC=E6=8D=A2=E4=BA=A7=E7=94=9F?= =?UTF-8?q?=E7=9A=84"\\\\=3F\\"=E5=89=8D=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/add.rs | 2 +- src/models/blob.rs | 2 +- src/models/index.rs | 24 +++++++++++++++++------- src/utils/util.rs | 37 ++++++++++++++++++++++++++++++++++++- tests/test.rs | 5 ++++- 5 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/commands/add.rs b/src/commands/add.rs index 7bae406..621c6ea 100644 --- a/src/commands/add.rs +++ b/src/commands/add.rs @@ -47,7 +47,7 @@ pub fn add(files: Vec, all: bool, mut update: bool) { } fn add_a_file(file: &Path, index: &mut Index) { - println!("add a file: {}", get_relative_path(file, get_working_dir().unwrap()).display()); + println!("add a file: {}", get_relative_path(file, &*get_working_dir().unwrap()).display()); if !file.exists() { //文件被删除 index.remove(file); } else { //文件存在 diff --git a/src/models/blob.rs b/src/models/blob.rs index 8c34d8e..9370d3c 100644 --- a/src/models/blob.rs +++ b/src/models/blob.rs @@ -17,7 +17,7 @@ pub struct Blob { impl Blob { /// 从源文件新建blob对象,并直接保存到/objects/中 pub fn new(file: &Path) -> Blob { - let data = fs::read_to_string(file).unwrap(); + let data = fs::read_to_string(file).expect("无法读取文件"); let hash = calc_hash(&data); let blob = Blob { hash, data }; blob.save(); diff --git a/src/models/index.rs b/src/models/index.rs index 84cc016..1a66f2e 100644 --- a/src/models/index.rs +++ b/src/models/index.rs @@ -6,6 +6,7 @@ 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)] @@ -116,9 +117,16 @@ impl Index { } /// 二进制序列化 - pub fn save(&self) { + pub fn save(&mut self) { //要先转化为相对路径 - let ser = serde_json::to_string_pretty(&self).unwrap(); + let relative_index: HashMap = self.entries.iter() + .map(|(path, value)| { + println!("path: {:?}", path); + let relative_path = get_relative_path(path, &self.working_dir); + (relative_path, value.clone()) + }) + .collect(); + let ser = serde_json::to_string_pretty(&relative_index).unwrap(); println!("{}", ser); } @@ -153,8 +161,9 @@ mod tests { #[test] fn test_save() { util::setup_test_with_clean_mit(); + let mut index = Index::new(); - let metadata = fs::metadata("../.gitignore").unwrap(); + let metadata = fs::metadata(".mit/HEAD").unwrap(); let file_meta_data = FileMetaData { hash: "123".to_string(), size: metadata.len(), @@ -162,12 +171,13 @@ mod tests { modified_time: metadata.modified().unwrap(), mode: "100644".to_string(), }; - index.add(PathBuf::from(".gitignore"), file_meta_data); + index.add(PathBuf::from(".mit/HEAD"), file_meta_data); + let path = PathBuf::from("../mit_test_storage/中文路径测试.txt"); index.add( - PathBuf::from("../src/models/index.rs"), + path.clone(), FileMetaData::new( - &Blob::new(Path::new("../src/models/index.rs")), - Path::new("../src/models/index.rs"), + &Blob::new(&path), + Path::new(&path), ), ); index.save(); diff --git a/src/utils/util.rs b/src/utils/util.rs index fd61d4c..10ba1ba 100644 --- a/src/utils/util.rs +++ b/src/utils/util.rs @@ -115,7 +115,13 @@ pub fn list_files(path: &Path) -> io::Result> { Ok(files) } -pub fn get_relative_path(path: &Path, dir: PathBuf) -> PathBuf { +/// 获取相对于dir的相对路径 +pub fn get_relative_path(path: &Path, dir: &Path) -> PathBuf { + let path = if path.is_relative() { + get_absolute_path(path) + } else { + path.to_path_buf() + }; let relative_path = path.strip_prefix(dir).unwrap(); relative_path.to_path_buf() } @@ -147,6 +153,35 @@ pub fn get_file_mode(path: &Path) -> String { } } +/// 清除Windows下的绝对路径前缀"\\\\?\\" +/// Windows 系统中的文件路径格式 +pub fn clean_win_abs_path_pre(path: PathBuf) -> PathBuf { + #[cfg(windows)] + { + const DOS_PREFIX: &str = "\\\\?\\"; + let path_str = path.to_string_lossy(); + if path_str.starts_with(DOS_PREFIX) { + PathBuf::from(&path_str[DOS_PREFIX.len()..]) + } else { + path + } + } + #[cfg(not(target_os = "windows"))] + { + path + } +} + +/// 获取绝对路径(相对于当前current_dir) +pub fn get_absolute_path(path: &Path) -> PathBuf { + if path.is_absolute() { + path.to_path_buf() + } else { + let abs_path = path.canonicalize().unwrap(); + clean_win_abs_path_pre(abs_path) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/tests/test.rs b/tests/test.rs index 96e30ef..e426bd2 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,6 +1,7 @@ use sha1::{Sha1, Digest}; use std::fs::File; use std::io::{Write, BufReader, BufRead, Error}; +use mit::utils::util; #[test] fn test_hash() { @@ -8,11 +9,12 @@ fn test_hash() { hasher.update(String::from("hello world")); let result = format!("{:x}", hasher.finalize()); println!("{}", result); - println!("{}", mit::utils::util::calc_hash(&String::from("hello world"))); + println!("{}", util::calc_hash(&String::from("hello world"))); } #[test] fn test_write() -> Result<(), Error> { + util::setup_test_with_mit(); let path = "lines.txt"; //create会截断文件 let mut output = File::create(path)?; // ? 用于传播错误 @@ -22,6 +24,7 @@ fn test_write() -> Result<(), Error> { #[test] fn test_read() -> Result<(), Error> { + util::setup_test_with_mit(); let path = "lines.txt"; let input = File::open(path)?; let buffered = BufReader::new(input);