修改Blob逻辑,主要变更为 Blob 与 objects文件解构。store作为与objects文件交互的唯一依赖。具体为:

1. Blob使用Content新建而不是path
2. workdir的读写能力由util::read|write workfile提供
3. 判断文件是否更改不直接计算hash,经由新建一个不保存的Blob进行。现在Hash算法只由Store决定。
This commit is contained in:
HouXiaoxuan
2023-12-28 22:23:44 +08:00
parent b3aea1d0d1
commit f88ab0e33a
9 changed files with 91 additions and 67 deletions

View File

@@ -1,5 +1,7 @@
use std::path::PathBuf;
use sha1::{Digest, Sha1};
use crate::models::Hash;
use super::util;
@@ -13,6 +15,13 @@ pub struct Store {
* 每一个object文件名与内容的hash值相同
*/
impl Store {
fn calc_hash(data: &String) -> String {
let mut hasher = Sha1::new();
hasher.update(data);
let hash = hasher.finalize();
hex::encode(hash)
}
pub fn new() -> Store {
util::check_repo_exist();
let store_path = util::get_storage_path().unwrap();
@@ -29,16 +38,6 @@ impl Store {
}
}
/// 将hash对应的文件内容(主要是blob)还原到file
pub fn restore_to_file(&self, hash: &Hash, file: &PathBuf) {
let content = self.load(hash);
// 保证文件层次存在
let mut parent = file.clone();
parent.pop();
std::fs::create_dir_all(parent).unwrap();
std::fs::write(file, content).unwrap();
}
/** 根据前缀搜索,有歧义时返回 None */
pub fn search(&self, hash: &String) -> Option<Hash> {
if hash.is_empty() {
@@ -65,10 +64,9 @@ impl Store {
}
}
pub fn save(&self, content: &String) -> String {
pub fn save(&self, content: &String) -> Hash {
/* 保存文件内容 */
let hash = util::calc_hash(content);
let hash = Self::calc_hash(content);
let mut path = self.store_path.clone();
path.push("objects");
path.push(&hash);
@@ -82,6 +80,13 @@ impl Store {
Err(_) => panic!("储存库疑似损坏,无法写入文件"),
}
}
pub fn dry_save(&self, content: &String) -> Hash {
/* 不实际保存文件返回Hash */
let hash = Self::calc_hash(content);
// TODO more such as check
hash
}
}
#[cfg(test)]
mod tests {

View File

@@ -1,4 +1,4 @@
use sha1::{Digest, Sha1};
use std::{
collections::HashSet,
fs, io,
@@ -10,18 +10,6 @@ use crate::models::{commit::Commit, object::Hash, tree::Tree};
pub const ROOT_DIR: &str = ".mit";
/* tools for mit */
pub fn calc_hash(data: &String) -> String {
let mut hasher = Sha1::new();
hasher.update(data);
let hash = hasher.finalize();
hex::encode(hash)
}
/// 计算文件的hash
pub fn calc_file_hash(path: &Path) -> String {
let data = fs::read_to_string(path).expect(&format!("无法读取文件:{}", path.display()));
calc_hash(&data)
}
pub fn storage_exist() -> bool {
/*检查是否存在储存库 */
@@ -427,11 +415,25 @@ pub fn is_typeof_commit(hash: Hash) -> bool {
check_object_type(hash) == ObjectType::Commit
}
/// 将内容对应的文件内容(主要是blob)还原到file
pub fn write_workfile(content: String, file: &PathBuf) {
let mut parent = file.clone();
parent.pop();
std::fs::create_dir_all(parent).unwrap();
std::fs::write(file, content).unwrap();
}
/// 从工作区读取文件内容
pub fn read_workfile(file: &Path) -> String {
std::fs::read_to_string(file).unwrap()
}
#[cfg(test)]
mod tests {
use crate::{
models::{blob::Blob, index::Index},
utils::{test_util, util::*},
utils::{test_util, util::{*, self}},
};
#[test]
@@ -536,7 +538,8 @@ mod tests {
test_util::setup_test_with_clean_mit();
assert_eq!(check_object_type("123".into()), ObjectType::Invalid);
test_util::ensure_test_file(Path::new("test.txt"), Some("test"));
let hash = Blob::new(get_working_dir().unwrap().join("test.txt").as_path()).get_hash();
let content = util::read_workfile(get_working_dir().unwrap().join("test.txt").as_path());
let hash = Blob::new(content).get_hash();
assert_eq!(check_object_type(hash), ObjectType::Blob);
let mut commit = Commit::new(&Index::get_instance(), vec![], "test".to_string());
assert_eq!(check_object_type(commit.get_tree_hash()), ObjectType::Tree);