mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-23 20:54:50 +03:00
make sure current session is created
This commit is contained in:
parent
f53397cf28
commit
da4ff14a34
@ -1,16 +1,24 @@
|
||||
use std::time;
|
||||
|
||||
use anyhow::{anyhow, Context, Ok, Result};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::sessions;
|
||||
use crate::{projects, sessions};
|
||||
|
||||
use super::{reader, writer};
|
||||
use super::{project_repository, reader, session};
|
||||
|
||||
pub struct Repository {
|
||||
pub(crate) project_id: String,
|
||||
project_store: projects::Storage,
|
||||
git_repository: git2::Repository,
|
||||
}
|
||||
|
||||
impl Repository {
|
||||
pub fn open<P: AsRef<std::path::Path>>(root: P, project_id: String) -> Result<Self> {
|
||||
pub fn open<P: AsRef<std::path::Path>>(
|
||||
root: P,
|
||||
project_id: String,
|
||||
project_store: projects::Storage,
|
||||
) -> Result<Self> {
|
||||
let path = root.as_ref().join(project_id.clone());
|
||||
let git_repository = if path.exists() {
|
||||
git2::Repository::open(path.clone())
|
||||
@ -43,15 +51,66 @@ impl Repository {
|
||||
Ok(Self {
|
||||
project_id,
|
||||
git_repository,
|
||||
project_store,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sessions(&self) -> Result<Vec<sessions::Session>> {
|
||||
Err(anyhow!("TODO"))
|
||||
fn create_current_session(
|
||||
&self,
|
||||
project_repository: &project_repository::Repository,
|
||||
) -> Result<sessions::Session> {
|
||||
log::info!("{}: creating new session", self.project_id);
|
||||
|
||||
let now_ms = time::SystemTime::now()
|
||||
.duration_since(time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_millis();
|
||||
|
||||
let meta = match project_repository.get_head() {
|
||||
Result::Ok(head) => sessions::Meta {
|
||||
start_timestamp_ms: now_ms,
|
||||
last_timestamp_ms: now_ms,
|
||||
branch: head.name().map(|name| name.to_string()),
|
||||
commit: Some(head.peel_to_commit()?.id().to_string()),
|
||||
},
|
||||
Err(_) => sessions::Meta {
|
||||
start_timestamp_ms: now_ms,
|
||||
last_timestamp_ms: now_ms,
|
||||
branch: None,
|
||||
commit: None,
|
||||
},
|
||||
};
|
||||
|
||||
let session = sessions::Session {
|
||||
id: Uuid::new_v4().to_string(),
|
||||
hash: None,
|
||||
meta,
|
||||
activity: vec![],
|
||||
};
|
||||
|
||||
Ok(session)
|
||||
}
|
||||
|
||||
pub fn get_wd_writer(&self) -> writer::DirWriter {
|
||||
writer::DirWriter::open(self.root())
|
||||
pub fn get_current_session_writer(&self) -> Result<session::SessionWriter> {
|
||||
match self
|
||||
.get_current_session()
|
||||
.context("failed to get current session")?
|
||||
{
|
||||
Some(session) => Ok(session::SessionWriter::open(&self, session)?),
|
||||
None => {
|
||||
let project = self
|
||||
.project_store
|
||||
.get_project(&self.project_id)
|
||||
.context("failed to get project")?;
|
||||
if project.is_none() {
|
||||
return Err(anyhow!("project {} does not exist", self.project_id));
|
||||
}
|
||||
let project = project.unwrap();
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
let session = self.create_current_session(&project_repository)?;
|
||||
Ok(session::SessionWriter::open(&self, session)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_wd_reader(&self) -> reader::DirReader {
|
||||
|
102
src-tauri/src/app/gb_repository_tests.rs
Normal file
102
src-tauri/src/app/gb_repository_tests.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use anyhow::Result;
|
||||
use tempfile::tempdir;
|
||||
|
||||
use crate::{app::gb_repository, projects, storage};
|
||||
|
||||
fn test_repository() -> Result<git2::Repository> {
|
||||
let path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let repository = git2::Repository::init(&path)?;
|
||||
let mut index = repository.index()?;
|
||||
let oid = index.write_tree()?;
|
||||
let signature = git2::Signature::now("test", "test@email.com").unwrap();
|
||||
repository.commit(
|
||||
Some("HEAD"),
|
||||
&signature,
|
||||
&signature,
|
||||
"Initial commit",
|
||||
&repository.find_tree(oid)?,
|
||||
&[],
|
||||
)?;
|
||||
Ok(repository)
|
||||
}
|
||||
|
||||
fn test_project(repository: &git2::Repository) -> Result<projects::Project> {
|
||||
let project = projects::Project::from_path(
|
||||
repository
|
||||
.path()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
)?;
|
||||
Ok(project)
|
||||
}
|
||||
|
||||
fn project_store(project: &projects::Project) -> Result<projects::Storage> {
|
||||
let storage = storage::Storage::from_path(tempdir()?.path().to_path_buf());
|
||||
let store = projects::Storage::new(storage);
|
||||
store.add_project(project)?;
|
||||
Ok(store)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_current_session_writer_should_create_session() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
let project = test_project(&repository)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let project_store = project_store(&project)?;
|
||||
let gb_repo =
|
||||
gb_repository::Repository::open(gb_repo_path, project.id.clone(), project_store.clone())?;
|
||||
|
||||
gb_repo.get_current_session_writer()?;
|
||||
|
||||
let current_session = gb_repo.get_current_session()?;
|
||||
assert!(current_session.is_some());
|
||||
let current_session = current_session.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(gb_repo.session_path().join("meta/id"))?,
|
||||
current_session.id
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(gb_repo.session_path().join("meta/branch"))?,
|
||||
current_session.meta.branch.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(gb_repo.session_path().join("meta/commit"))?,
|
||||
current_session.meta.commit.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(gb_repo.session_path().join("meta/last"))?,
|
||||
current_session.meta.last_timestamp_ms.to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(gb_repo.session_path().join("meta/start"))?,
|
||||
current_session.meta.start_timestamp_ms.to_string()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_current_session_writer_should_use_existing_session() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
let project = test_project(&repository)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let project_store = project_store(&project)?;
|
||||
let gb_repo =
|
||||
gb_repository::Repository::open(gb_repo_path, project.id.clone(), project_store.clone())?;
|
||||
|
||||
gb_repo.get_current_session_writer()?;
|
||||
|
||||
let current_session_1 = gb_repo.get_current_session()?;
|
||||
assert!(current_session_1.is_some());
|
||||
|
||||
gb_repo.get_current_session_writer()?;
|
||||
|
||||
let current_session_2 = gb_repo.get_current_session()?;
|
||||
assert_eq!(current_session_1, current_session_2);
|
||||
|
||||
Ok(())
|
||||
}
|
@ -5,7 +5,7 @@ mod session;
|
||||
pub mod watcher;
|
||||
mod writer;
|
||||
|
||||
#[cfg(test)]
|
||||
mod gb_repository_tests;
|
||||
#[cfg(test)]
|
||||
mod reader_tests;
|
||||
|
||||
pub struct App {}
|
||||
|
@ -15,7 +15,7 @@ impl Repository {
|
||||
Ok(Self { git_repository })
|
||||
}
|
||||
|
||||
pub fn head(&self) -> Result<git2::Reference> {
|
||||
pub fn get_head(&self) -> Result<git2::Reference> {
|
||||
let head = self.git_repository.head()?;
|
||||
Ok(head)
|
||||
}
|
||||
|
@ -5,20 +5,20 @@ use anyhow::{anyhow, Context, Result};
|
||||
use crate::{deltas, pty, sessions};
|
||||
|
||||
use super::{
|
||||
gb_repository as repository,
|
||||
gb_repository,
|
||||
reader::{self, Reader},
|
||||
writer::{self, Writer},
|
||||
};
|
||||
|
||||
pub struct SessionWriter<'writer> {
|
||||
repository: &'writer repository::Repository,
|
||||
repository: &'writer gb_repository::Repository,
|
||||
writer: Box<dyn writer::Writer + 'writer>,
|
||||
}
|
||||
|
||||
impl<'writer> SessionWriter<'writer> {
|
||||
pub fn open(
|
||||
repository: &'writer repository::Repository,
|
||||
session: &'writer sessions::Session,
|
||||
repository: &'writer gb_repository::Repository,
|
||||
session: sessions::Session,
|
||||
) -> Result<Self> {
|
||||
let reader = reader::DirReader::open(repository.root());
|
||||
|
||||
@ -194,13 +194,13 @@ impl<'writer> SessionWriter<'writer> {
|
||||
}
|
||||
|
||||
pub struct SessionReader<'reader> {
|
||||
repository: &'reader repository::Repository,
|
||||
repository: &'reader gb_repository::Repository,
|
||||
reader: Box<dyn reader::Reader + 'reader>,
|
||||
}
|
||||
|
||||
impl<'reader> SessionReader<'reader> {
|
||||
pub fn open(
|
||||
repository: &'reader repository::Repository,
|
||||
repository: &'reader gb_repository::Repository,
|
||||
session: sessions::Session,
|
||||
) -> Result<Self> {
|
||||
let wd_reader = reader::DirReader::open(repository.root());
|
||||
|
@ -43,7 +43,7 @@ impl Listener {
|
||||
Some(events::Event::git_activity(&project))
|
||||
} else if path.eq(".git/HEAD") {
|
||||
log::info!("{}: git head changed", project.id);
|
||||
let head_ref = project_repository.head()?;
|
||||
let head_ref = project_repository.get_head()?;
|
||||
if let Some(head) = head_ref.name() {
|
||||
Some(events::Event::git_head(&project, &head))
|
||||
} else {
|
||||
|
@ -4,7 +4,6 @@ use crate::{
|
||||
app::{
|
||||
gb_repository, project_repository,
|
||||
reader::{self, Reader},
|
||||
writer::Writer,
|
||||
},
|
||||
deltas, projects,
|
||||
};
|
||||
@ -150,27 +149,13 @@ impl<'listener> Listener<'listener> {
|
||||
|
||||
log::info!("{}: {} changed", self.project_id, path.display());
|
||||
|
||||
let writer = self.gb_repository.get_wd_writer();
|
||||
|
||||
// save current deltas
|
||||
let writer = self.gb_repository.get_current_session_writer()?;
|
||||
writer
|
||||
.write_string(
|
||||
self.gb_repository
|
||||
.deltas_path()
|
||||
.join(path)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
&serde_json::to_string(&text_doc.get_deltas())?,
|
||||
)
|
||||
.write_deltas(path, text_doc.get_deltas())
|
||||
.with_context(|| "failed to write deltas")?;
|
||||
|
||||
// save file contents corresponding to the deltas
|
||||
writer
|
||||
.write_string(
|
||||
self.gb_repository.wd_path().join(path).to_str().unwrap(),
|
||||
¤t_file_content,
|
||||
)
|
||||
.with_context(|| "failed to write file content")?;
|
||||
.write_file(path, ¤t_file_content)
|
||||
.with_context(|| "failed to write file")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -68,8 +68,10 @@ fn test_register_existing_file() -> Result<()> {
|
||||
let project = test_project(&repository)?;
|
||||
let project_repo = project_repository::Repository::open(&project)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let gb_repo = gb_repository::Repository::open(gb_repo_path, project.id.clone())?;
|
||||
let listener = Listener::new(project.id.clone(), project_store(&project)?, &gb_repo);
|
||||
let project_store = project_store(&project)?;
|
||||
let gb_repo =
|
||||
gb_repository::Repository::open(gb_repo_path, project.id.clone(), project_store.clone())?;
|
||||
let listener = Listener::new(project.id.clone(), project_store, &gb_repo);
|
||||
|
||||
let file_path = std::path::Path::new("test.txt");
|
||||
std::fs::write(project_repo.root().join(file_path), "test")?;
|
||||
@ -100,8 +102,10 @@ fn test_register_new_file() -> Result<()> {
|
||||
let project = test_project(&repository)?;
|
||||
let project_repo = project_repository::Repository::open(&project)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let gb_repo = gb_repository::Repository::open(gb_repo_path, project.id.clone())?;
|
||||
let listener = Listener::new(project.id.clone(), project_store(&project)?, &gb_repo);
|
||||
let project_store = project_store(&project)?;
|
||||
let gb_repo =
|
||||
gb_repository::Repository::open(gb_repo_path, project.id.clone(), project_store.clone())?;
|
||||
let listener = Listener::new(project.id.clone(), project_store, &gb_repo);
|
||||
|
||||
let file_path = std::path::Path::new("test.txt");
|
||||
std::fs::write(project_repo.root().join(file_path), "test")?;
|
||||
@ -130,8 +134,10 @@ fn test_register_new_file_twice() -> Result<()> {
|
||||
let project = test_project(&repository)?;
|
||||
let project_repo = project_repository::Repository::open(&project)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let gb_repo = gb_repository::Repository::open(gb_repo_path, project.id.clone())?;
|
||||
let listener = Listener::new(project.id.clone(), project_store(&project)?, &gb_repo);
|
||||
let project_store = project_store(&project)?;
|
||||
let gb_repo =
|
||||
gb_repository::Repository::open(gb_repo_path, project.id.clone(), project_store.clone())?;
|
||||
let listener = Listener::new(project.id.clone(), project_store, &gb_repo);
|
||||
|
||||
let file_path = std::path::Path::new("test.txt");
|
||||
std::fs::write(project_repo.root().join(file_path), "test")?;
|
||||
|
@ -731,8 +731,12 @@ fn init(app_handle: tauri::AppHandle) -> Result<()> {
|
||||
let project_storage = ps;
|
||||
let user_storage = us;
|
||||
|
||||
let gb_repo = app::gb_repository::Repository::open(local_data_dir, project.id.clone())
|
||||
.expect("failed to open gb repository");
|
||||
let gb_repo = app::gb_repository::Repository::open(
|
||||
local_data_dir,
|
||||
project.id.clone(),
|
||||
project_storage.clone(),
|
||||
)
|
||||
.expect("failed to open gb repository");
|
||||
let (tx, _rx) = std::sync::mpsc::channel::<events::Event>();
|
||||
let w =
|
||||
app::watcher::Watcher::new(project.id, project_storage, user_storage, &gb_repo, tx)
|
||||
|
Loading…
Reference in New Issue
Block a user