mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-24 13:37:34 +03:00
arc protect
This commit is contained in:
parent
244cf5850d
commit
3009958218
@ -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());
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user