make sure current session is created

This commit is contained in:
Nikita Galaiko 2023-04-14 13:18:44 +02:00
parent f53397cf28
commit da4ff14a34
9 changed files with 200 additions and 44 deletions

View File

@ -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 {

View 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(())
}

View File

@ -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 {}

View File

@ -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)
}

View File

@ -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());

View File

@ -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 {

View File

@ -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(),
&current_file_content,
)
.with_context(|| "failed to write file content")?;
.write_file(path, &current_file_content)
.with_context(|| "failed to write file")?;
Ok(())
}

View File

@ -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")?;

View File

@ -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)