diff --git a/lib/src/backend.rs b/lib/src/backend.rs index 5a6c203ad..c267dc9a5 100644 --- a/lib/src/backend.rs +++ b/lib/src/backend.rs @@ -374,6 +374,29 @@ impl Tree { } } +pub fn make_root_commit(empty_tree_id: TreeId) -> Commit { + let timestamp = Timestamp { + timestamp: MillisSinceEpoch(0), + tz_offset: 0, + }; + let signature = Signature { + name: String::new(), + email: String::new(), + timestamp, + }; + let change_id = ChangeId::new(vec![0; 16]); + Commit { + parents: vec![], + predecessors: vec![], + root_tree: empty_tree_id, + change_id, + description: String::new(), + author: signature.clone(), + committer: signature, + is_open: false, + } +} + pub trait Backend: Send + Sync + Debug { fn hash_length(&self) -> usize; @@ -387,6 +410,8 @@ pub trait Backend: Send + Sync + Debug { fn write_symlink(&self, path: &RepoPath, target: &str) -> BackendResult; + fn root_commit_id(&self) -> &CommitId; + fn empty_tree_id(&self) -> &TreeId; fn read_tree(&self, path: &RepoPath, id: &TreeId) -> BackendResult; diff --git a/lib/src/git_backend.rs b/lib/src/git_backend.rs index bf9f52272..2a49edaef 100644 --- a/lib/src/git_backend.rs +++ b/lib/src/git_backend.rs @@ -24,9 +24,9 @@ use protobuf::Message; use uuid::Uuid; use crate::backend::{ - Backend, BackendError, BackendResult, ChangeId, Commit, CommitId, Conflict, ConflictId, - ConflictPart, FileId, MillisSinceEpoch, Signature, SymlinkId, Timestamp, Tree, TreeId, - TreeValue, + make_root_commit, Backend, BackendError, BackendResult, ChangeId, Commit, CommitId, Conflict, + ConflictId, ConflictPart, FileId, MillisSinceEpoch, Signature, SymlinkId, Timestamp, Tree, + TreeId, TreeValue, }; use crate::repo_path::{RepoPath, RepoPathComponent}; use crate::stacked_table::{TableSegment, TableStore}; @@ -47,15 +47,18 @@ impl From for BackendError { pub struct GitBackend { repo: Mutex, + root_commit_id: CommitId, empty_tree_id: TreeId, extra_metadata_store: TableStore, } impl GitBackend { fn new(repo: git2::Repository, extra_metadata_store: TableStore) -> Self { + let root_commit_id = CommitId::from_bytes(&[0; HASH_LENGTH]); let empty_tree_id = TreeId::from_hex("4b825dc642cb6eb9a060e54bf8d69288fbee4904"); GitBackend { repo: Mutex::new(repo), + root_commit_id, empty_tree_id, extra_metadata_store, } @@ -208,6 +211,10 @@ impl Backend for GitBackend { Ok(SymlinkId::new(oid.as_bytes().to_vec())) } + fn root_commit_id(&self) -> &CommitId { + &self.root_commit_id + } + fn empty_tree_id(&self) -> &TreeId { &self.empty_tree_id } @@ -339,6 +346,10 @@ impl Backend for GitBackend { return Err(BackendError::NotFound); } + if *id == self.root_commit_id { + return Ok(make_root_commit(self.empty_tree_id.clone())); + } + let locked_repo = self.repo.lock().unwrap(); let git_commit_id = Oid::from_bytes(id.as_bytes())?; let commit = locked_repo.find_commit(git_commit_id)?; diff --git a/lib/src/local_backend.rs b/lib/src/local_backend.rs index ac3dec9f9..28aeb644d 100644 --- a/lib/src/local_backend.rs +++ b/lib/src/local_backend.rs @@ -23,9 +23,9 @@ use protobuf::{Message, MessageField}; use tempfile::{NamedTempFile, PersistError}; use crate::backend::{ - Backend, BackendError, BackendResult, ChangeId, Commit, CommitId, Conflict, ConflictId, - ConflictPart, FileId, MillisSinceEpoch, Signature, SymlinkId, Timestamp, Tree, TreeId, - TreeValue, + make_root_commit, Backend, BackendError, BackendResult, ChangeId, Commit, CommitId, Conflict, + ConflictId, ConflictPart, FileId, MillisSinceEpoch, Signature, SymlinkId, Timestamp, Tree, + TreeId, TreeValue, }; use crate::file_util::persist_content_addressed_temp_file; use crate::repo_path::{RepoPath, RepoPathComponent}; @@ -51,6 +51,7 @@ impl From for BackendError { #[derive(Debug)] pub struct LocalBackend { path: PathBuf, + root_commit_id: CommitId, empty_tree_id: TreeId, } @@ -70,9 +71,11 @@ impl LocalBackend { } pub fn load(store_path: PathBuf) -> Self { + let root_commit_id = CommitId::from_bytes(&[0; 64]); let empty_tree_id = TreeId::from_hex("786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"); LocalBackend { path: store_path, + root_commit_id, empty_tree_id, } } @@ -165,6 +168,10 @@ impl Backend for LocalBackend { Ok(id) } + fn root_commit_id(&self) -> &CommitId { + &self.root_commit_id + } + fn empty_tree_id(&self) -> &TreeId { &self.empty_tree_id } @@ -216,6 +223,10 @@ impl Backend for LocalBackend { } fn read_commit(&self, id: &CommitId) -> BackendResult { + if *id == self.root_commit_id { + return Ok(make_root_commit(self.empty_tree_id.clone())); + } + let path = self.commit_path(id); let mut file = File::open(path).map_err(not_found_to_backend_error)?; diff --git a/lib/src/store.rs b/lib/src/store.rs index e4bd74d01..944bf1a0c 100644 --- a/lib/src/store.rs +++ b/lib/src/store.rs @@ -18,8 +18,7 @@ use std::sync::{Arc, RwLock}; use crate::backend; use crate::backend::{ - Backend, BackendResult, ChangeId, CommitId, Conflict, ConflictId, FileId, MillisSinceEpoch, - Signature, SymlinkId, Timestamp, TreeId, + Backend, BackendResult, CommitId, Conflict, ConflictId, FileId, SymlinkId, TreeId, }; use crate::commit::Commit; use crate::repo_path::RepoPath; @@ -31,17 +30,14 @@ use crate::tree_builder::TreeBuilder; #[derive(Debug)] pub struct Store { backend: Box, - root_commit_id: CommitId, commit_cache: RwLock>>, tree_cache: RwLock>>, } impl Store { pub fn new(backend: Box) -> Arc { - let root_commit_id = CommitId::new(vec![0; backend.hash_length()]); Arc::new(Store { backend, - root_commit_id, commit_cache: Default::default(), tree_cache: Default::default(), }) @@ -60,11 +56,11 @@ impl Store { } pub fn root_commit_id(&self) -> &CommitId { - &self.root_commit_id + self.backend.root_commit_id() } pub fn root_commit(self: &Arc) -> Commit { - self.get_commit(&self.root_commit_id).unwrap() + self.get_commit(self.backend.root_commit_id()).unwrap() } pub fn get_commit(self: &Arc, id: &CommitId) -> BackendResult { @@ -72,29 +68,6 @@ impl Store { Ok(Commit::new(self.clone(), id.clone(), data)) } - fn make_root_commit(&self) -> backend::Commit { - let timestamp = Timestamp { - timestamp: MillisSinceEpoch(0), - tz_offset: 0, - }; - let signature = Signature { - name: String::new(), - email: String::new(), - timestamp, - }; - let change_id = ChangeId::new(vec![0; 16]); - backend::Commit { - parents: vec![], - predecessors: vec![], - root_tree: self.backend.empty_tree_id().clone(), - change_id, - description: String::new(), - author: signature.clone(), - committer: signature, - is_open: false, - } - } - fn get_backend_commit(&self, id: &CommitId) -> BackendResult> { { let read_locked_cached = self.commit_cache.read().unwrap(); @@ -102,11 +75,7 @@ impl Store { return Ok(data); } } - let commit = if id == self.root_commit_id() { - self.make_root_commit() - } else { - self.backend.read_commit(id)? - }; + let commit = self.backend.read_commit(id)?; let data = Arc::new(commit); let mut write_locked_cache = self.commit_cache.write().unwrap(); write_locked_cache.insert(id.clone(), data.clone());