arc protect

This commit is contained in:
Nikita Galaiko 2023-03-21 10:50:18 +01:00
parent 244cf5850d
commit 3009958218
No known key found for this signature in database
GPG Key ID: EBAB54E845BA519D
4 changed files with 58 additions and 102 deletions

View File

@ -6,28 +6,16 @@ use std::{
sync::{Arc, Mutex},
};
#[derive(Clone)]
pub struct Store {
project: projects::Project,
git_repository: git2::Repository,
git_repository: Arc<Mutex<git2::Repository>>,
cache: Arc<Mutex<HashMap<String, HashMap<String, Vec<deltas::Delta>>>>>,
}
impl Clone for Store {
fn clone(&self) -> Self {
Self {
project: self.project.clone(),
git_repository: git2::Repository::open(&self.project.path).unwrap(),
cache: self.cache.clone(),
}
}
}
impl Store {
pub fn new(project: projects::Project) -> Result<Self> {
Ok(Self {
git_repository: git2::Repository::open(&project.path)?,
project,
git_repository: Arc::new(Mutex::new(git2::Repository::open(&project.path)?)),
cache: Arc::new(Mutex::new(HashMap::new())),
})
}
@ -40,9 +28,10 @@ impl Store {
)));
}
let git_repository = self.git_repository.lock().unwrap();
let commit_hash = session.hash.as_ref().unwrap();
let commit_id = git2::Oid::from_str(commit_hash)?;
let commit = self.git_repository.find_commit(commit_id)?;
let commit = git_repository.find_commit(commit_id)?;
let tree = commit.tree()?;
let mut blobs = HashMap::new();
@ -60,7 +49,7 @@ impl Store {
let relative_file_path = entry_path.strip_prefix("session/deltas").unwrap();
let blob = entry
.to_object(&self.git_repository)
.to_object(&git_repository)
.and_then(|obj| obj.peel_to_blob());
let content = blob.map(|blob| blob.content().to_vec());

View File

@ -4,30 +4,16 @@ use std::{collections::HashMap, path::Path, time};
use super::{current, persistent};
#[derive(Clone)]
pub struct Store {
project: projects::Project,
persistent: persistent::Store,
current: current::Store,
sessions_store: sessions::Store,
}
impl Clone for Store {
fn clone(&self) -> Self {
Self {
project: self.project.clone(),
current: self.current.clone(),
persistent: self.persistent.clone(),
sessions_store: self.sessions_store.clone(),
}
}
}
impl Store {
pub fn new(project: projects::Project, sessions_store: sessions::Store) -> Result<Self> {
Ok(Self {
project: project.clone(),
current: current::Store::new(project.clone()),
persistent: persistent::Store::new(project)?,
sessions_store,

View File

@ -1,28 +1,23 @@
use std::time;
use std::{
sync::{Arc, Mutex},
time,
};
use crate::{projects, sessions};
use anyhow::{Context, Result};
use uuid::Uuid;
#[derive(Clone)]
pub struct Store {
project: projects::Project,
git_repository: git2::Repository,
}
impl Clone for Store {
fn clone(&self) -> Self {
Self {
project: self.project.clone(),
git_repository: git2::Repository::open(&self.project.path).unwrap(),
}
}
git_repository: Arc<Mutex<git2::Repository>>,
}
impl Store {
pub fn new(git_repository: git2::Repository, project: projects::Project) -> Result<Self> {
Ok(Self {
project: project.clone(),
git_repository,
git_repository: Arc::new(Mutex::new(git_repository)),
})
}
@ -32,7 +27,8 @@ impl Store {
.unwrap()
.as_millis();
let activity = match std::fs::read_to_string(self.git_repository.path().join("logs/HEAD")) {
let git_repository = self.git_repository.lock().unwrap();
let activity = match std::fs::read_to_string(git_repository.path().join("logs/HEAD")) {
Ok(reflog) => reflog
.lines()
.filter_map(|line| sessions::activity::parse_reflog_line(line).ok())
@ -41,7 +37,7 @@ impl Store {
Err(_) => Vec::new(),
};
let meta = match self.git_repository.head() {
let meta = match git_repository.head() {
Ok(head) => sessions::Meta {
start_timestamp_ms: now_ts,
last_timestamp_ms: now_ts,
@ -213,13 +209,15 @@ impl Store {
false => None,
};
let activity_path = self.git_repository.path().join("logs/HEAD");
let git_repository = self.git_repository.lock().unwrap();
let activity_path = git_repository.path().join("logs/HEAD");
let activity = match activity_path.exists() {
true => std::fs::read_to_string(activity_path)
.with_context(|| {
format!(
"failed to read reflog from {}",
self.git_repository.path().join("logs/HEAD").display()
git_repository.path().join("logs/HEAD").display()
)
})?
.lines()

View File

@ -11,51 +11,38 @@ use std::{
sync::{Arc, Mutex},
};
#[derive(Clone)]
pub struct Store {
project: projects::Project,
git_repository: git2::Repository,
git_repository: Arc<Mutex<git2::Repository>>,
files_cache: Arc<Mutex<HashMap<String, HashMap<String, String>>>>,
sessions_cache: Arc<Mutex<Option<Vec<sessions::Session>>>>,
}
impl Clone for Store {
fn clone(&self) -> Self {
Self {
project: self.project.clone(),
git_repository: git2::Repository::open(&self.project.path).unwrap(),
files_cache: self.files_cache.clone(),
sessions_cache: self.sessions_cache.clone(),
}
}
}
impl Store {
pub fn new(git_repository: git2::Repository, project: projects::Project) -> Result<Self> {
Ok(Self {
project: project.clone(),
git_repository,
git_repository: Arc::new(Mutex::new(git_repository)),
files_cache: Arc::new(Mutex::new(HashMap::new())),
sessions_cache: Arc::new(Mutex::new(None)),
})
}
pub fn get_by_id(&self, session_id: &str) -> Result<Option<sessions::Session>> {
let reference = self
.git_repository
.find_reference(&self.project.refname())?;
let head = self
.git_repository
.find_commit(reference.target().unwrap())?;
let mut walker = self.git_repository.revwalk()?;
let git_repository = self.git_repository.lock().unwrap();
let reference = git_repository.find_reference(&self.project.refname())?;
let head = git_repository.find_commit(reference.target().unwrap())?;
let mut walker = git_repository.revwalk()?;
walker.push(head.id())?;
walker.set_sorting(git2::Sort::TIME)?;
for commit_id in walker {
let commit = self.git_repository.find_commit(commit_id?)?;
if sessions::id_from_commit(&self.git_repository, &commit)? == session_id {
let commit = git_repository.find_commit(commit_id?)?;
if sessions::id_from_commit(&git_repository, &commit)? == session_id {
return Ok(Some(sessions::Session::from_commit(
&self.git_repository,
&git_repository,
&commit,
)?));
}
@ -93,23 +80,22 @@ impl Store {
}
fn list_files_from_disk(&self, session_id: &str) -> Result<HashMap<String, String>> {
let reference = self
.git_repository
.find_reference(&self.project.refname())?;
let git_repository = self.git_repository.lock().unwrap();
let reference = git_repository.find_reference(&self.project.refname())?;
let commit = if is_current_session_id(&self.project, session_id)? {
let head_commit = reference.peel_to_commit()?;
Some(head_commit)
} else {
let head_commit = reference.peel_to_commit()?;
let mut walker = self.git_repository.revwalk()?;
let mut walker = git_repository.revwalk()?;
walker.push(head_commit.id())?;
walker.set_sorting(git2::Sort::TOPOLOGICAL | git2::Sort::REVERSE)?;
let mut session_commit = None;
let mut previous_session_commit = None;
for commit_id in walker {
let commit = self.git_repository.find_commit(commit_id?)?;
if sessions::id_from_commit(&self.git_repository, &commit)? == session_id {
let commit = git_repository.find_commit(commit_id?)?;
if sessions::id_from_commit(&git_repository, &commit)? == session_id {
session_commit = Some(commit);
break;
}
@ -149,7 +135,7 @@ impl Store {
}
let blob = entry
.to_object(&self.git_repository)
.to_object(&git_repository)
.and_then(|obj| obj.peel_to_blob());
let content = blob.map(|blob| blob.content().to_vec());
@ -185,29 +171,26 @@ impl Store {
&self,
earliest_timestamp_ms: Option<u128>,
) -> Result<Vec<sessions::Session>> {
let reference = self
.git_repository
.find_reference(&self.project.refname())?;
let head = self
.git_repository
.find_commit(reference.target().unwrap())?;
let git_repository = self.git_repository.lock().unwrap();
let reference = git_repository.find_reference(&self.project.refname())?;
let head = git_repository.find_commit(reference.target().unwrap())?;
// list all commits from gitbutler head to the first commit
let mut walker = self.git_repository.revwalk()?;
let mut walker = git_repository.revwalk()?;
walker.push(head.id())?;
walker.set_sorting(git2::Sort::TOPOLOGICAL)?;
let mut sessions: Vec<sessions::Session> = vec![];
for id in walker {
let id = id?;
let commit = self.git_repository.find_commit(id).with_context(|| {
let commit = git_repository.find_commit(id).with_context(|| {
format!(
"failed to find commit {} in repository {}",
id.to_string(),
self.git_repository.path().display()
git_repository.path().display()
)
})?;
let session = sessions::Session::from_commit(&self.git_repository, &commit)?;
let session = sessions::Session::from_commit(&git_repository, &commit)?;
match earliest_timestamp_ms {
Some(earliest_timestamp_ms) => {
if session.meta.start_timestamp_ms <= earliest_timestamp_ms {
@ -250,27 +233,27 @@ impl Store {
));
}
let wd_tree = build_wd_tree(&self.git_repository, &self.project)
let git_repository = self.git_repository.lock().unwrap();
let wd_tree = build_wd_tree(&git_repository, &self.project)
.with_context(|| "failed to build wd tree for project".to_string())?;
let session_index =
&mut git2::Index::new().with_context(|| format!("failed to create session index"))?;
build_session_index(&self.git_repository, &self.project, session_index)
build_session_index(&git_repository, &self.project, session_index)
.with_context(|| format!("failed to build session index"))?;
let session_tree = session_index
.write_tree_to(&self.git_repository)
.write_tree_to(&git_repository)
.with_context(|| format!("failed to write session tree"))?;
let log_index =
&mut git2::Index::new().with_context(|| format!("failed to create log index"))?;
build_log_index(&self.git_repository, log_index)
build_log_index(&git_repository, log_index)
.with_context(|| format!("failed to build log index"))?;
let log_tree = log_index
.write_tree_to(&self.git_repository)
.write_tree_to(&git_repository)
.with_context(|| format!("failed to write log tree"))?;
let mut tree_builder = self
.git_repository
let mut tree_builder = git_repository
.treebuilder(None)
.with_context(|| format!("failed to create tree builder"))?;
tree_builder
@ -287,13 +270,13 @@ impl Store {
.write()
.with_context(|| format!("failed to write tree"))?;
let commit_oid = write_gb_commit(tree, &self.git_repository, user.clone(), &self.project)
let commit_oid = write_gb_commit(tree, &git_repository, user.clone(), &self.project)
.with_context(|| {
format!(
"failed to write gb commit for {}",
self.git_repository.workdir().unwrap().display()
)
})?;
format!(
"failed to write gb commit for {}",
git_repository.workdir().unwrap().display()
)
})?;
log::info!(
"{}: flushed session {} into commit {}",
@ -309,7 +292,7 @@ impl Store {
hash: Some(commit_oid.to_string()),
};
if let Err(e) = push_to_remote(&self.git_repository, user, &self.project) {
if let Err(e) = push_to_remote(&git_repository, user, &self.project) {
log::error!(
"{}: failed to push gb commit {} to remote: {:#}",
self.project.id,