unify TryFrom<&AppHandler> implementations

This commit is contained in:
Nikita Galaiko 2024-02-13 10:45:21 +01:00 committed by Kiril Videlov
parent 90c8884bbf
commit ddbeca298c
33 changed files with 681 additions and 513 deletions

View File

@ -12,6 +12,7 @@ use crate::{
users, watcher,
};
#[derive(Clone)]
pub struct App {
local_data_dir: path::PathBuf,
projects: projects::Controller,
@ -36,21 +37,39 @@ impl TryFrom<&AppHandle> for App {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
local_data_dir: path,
projects: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
watchers: value.state::<watcher::Watchers>().inner().clone(),
sessions_database: sessions::Database::from(value),
})
if let Some(app) = value.try_state::<App>() {
Ok(app.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let projects = projects::Controller::try_from(value)?;
let users = users::Controller::try_from(value)?;
let watchers = watcher::Watchers::try_from(value)?;
let sessions_database = sessions::Database::try_from(value)?;
let app = App::new(app_data_dir, projects, users, watchers, sessions_database);
value.manage(app.clone());
Ok(app)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl App {
fn new(
local_data_dir: path::PathBuf,
projects: projects::Controller,
users: users::Controller,
watchers: watcher::Watchers,
sessions_database: sessions::Database,
) -> Self {
Self {
local_data_dir,
projects,
users,
watchers,
sessions_database,
}
}
pub fn init_project(&self, project: &projects::Project) -> Result<()> {
self.watchers.watch(project).context(format!(
"failed to start watcher for project {}",

View File

@ -2,7 +2,7 @@ use std::{collections::HashMap, fs, path, sync};
use anyhow::{Context, Result};
use futures::future::join_all;
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use tokio::sync::Semaphore;
use url::Url;
@ -20,33 +20,34 @@ pub struct Proxy {
semaphores: sync::Arc<tokio::sync::Mutex<HashMap<url::Url, Semaphore>>>,
}
impl From<&path::PathBuf> for Proxy {
fn from(value: &path::PathBuf) -> Self {
Self {
cache_dir: value.clone(),
semaphores: sync::Arc::new(tokio::sync::Mutex::new(HashMap::new())),
}
}
}
impl TryFrom<&AppHandle> for Proxy {
type Error = anyhow::Error;
fn try_from(handle: &AppHandle) -> Result<Self, Self::Error> {
let app_cache_dir = handle
.path_resolver()
.app_cache_dir()
.context("failed to get cache dir")?;
fs::create_dir_all(&app_cache_dir).context("failed to create cache dir")?;
let cache_dir = app_cache_dir.join("images");
Ok(Self::from(&cache_dir))
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(proxy) = value.try_state::<Proxy>() {
Ok(proxy.inner().clone())
} else if let Some(app_cache_dir) = value.path_resolver().app_cache_dir() {
fs::create_dir_all(&app_cache_dir).context("failed to create cache dir")?;
let cache_dir = app_cache_dir.join("images");
let proxy = Self::new(cache_dir);
value.manage(proxy.clone());
Ok(proxy)
} else {
Err(anyhow::anyhow!("failed to get app cache dir"))
}
}
}
const ASSET_SCHEME: &str = "asset";
impl Proxy {
fn new(cache_dir: path::PathBuf) -> Self {
Proxy {
cache_dir,
semaphores: sync::Arc::new(tokio::sync::Mutex::new(HashMap::new())),
}
}
pub async fn proxy_user(&self, user: users::User) -> users::User {
match Url::parse(&user.picture) {
Ok(picture) => users::User {

View File

@ -103,7 +103,7 @@ fn main() {
.expect("failed to initialize zipc controller ");
tauri_app.manage(zipper);
let deltas_controller = deltas::Controller::from(&app_handle);
let deltas_controller = deltas::Controller::try_from(&app_handle).expect("failed to initialize deltas controller");
app_handle.manage(deltas_controller);
let sessions_controller = sessions::Controller::try_from(&app_handle)
@ -119,10 +119,10 @@ fn main() {
.expect("failed to initialize virtual branches controller");
app_handle.manage(vbranch_contoller);
let keys_controller = keys::Controller::from(&app_handle);
let keys_controller = keys::Controller::try_from(&app_handle).expect("failed to initialize keys controller");
app_handle.manage(keys_controller);
let users_controller = users::Controller::from(&app_handle);
let users_controller = users::Controller::try_from(&app_handle).expect("failed to initialize users controller");
let stores = tauri_app.state::<StoreCollection<Wry>>();
if let Some(path) = app_handle.path_resolver().app_config_dir().map(|path| path.join(PathBuf::from("settings.json"))) {

View File

@ -6,7 +6,7 @@ use r2d2::Pool;
use r2d2_sqlite::SqliteConnectionManager;
use refinery::config::Config;
use rusqlite::Transaction;
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
mod embedded {
use refinery::embed_migrations;
@ -18,24 +18,18 @@ pub struct Database {
pool: Arc<Pool<SqliteConnectionManager>>,
}
impl TryFrom<&path::PathBuf> for Database {
type Error = anyhow::Error;
fn try_from(path: &path::PathBuf) -> Result<Self, Self::Error> {
fs::create_dir_all(path).context("Failed to create local data dir")?;
Self::open(path.join("database.sqlite3"))
}
}
impl TryFrom<&AppHandle> for Database {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Self::try_from(&path)
if let Some(database) = value.try_state::<Database>() {
Ok(database.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
fs::create_dir_all(&app_data_dir).context("failed to create local data dir")?;
Self::open(app_data_dir.join("database.sqlite3"))
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}

View File

@ -1,19 +1,27 @@
use std::collections::HashMap;
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use crate::{projects::ProjectId, sessions::SessionId};
use super::{database, Delta};
#[derive(Clone)]
pub struct Controller {
database: database::Database,
}
impl From<&AppHandle> for Controller {
fn from(handle: &AppHandle) -> Self {
Self {
database: database::Database::from(handle),
impl TryFrom<&AppHandle> for Controller {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(controller) = value.try_state::<Controller>() {
Ok(controller.inner().clone())
} else {
let database = database::Database::try_from(value)?;
let controller = Controller::new(database);
value.manage(controller.clone());
Ok(controller)
}
}
}
@ -25,6 +33,10 @@ pub enum ListError {
}
impl Controller {
fn new(database: database::Database) -> Controller {
Controller { database }
}
pub fn list_by_session_id(
&self,
project_id: &ProjectId,

View File

@ -12,19 +12,25 @@ pub struct Database {
database: database::Database,
}
impl From<database::Database> for Database {
fn from(database: database::Database) -> Self {
Self { database }
}
}
impl TryFrom<&AppHandle> for Database {
type Error = anyhow::Error;
impl From<&AppHandle> for Database {
fn from(value: &AppHandle) -> Self {
Self::from(value.state::<database::Database>().inner().clone())
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(database) = value.try_state::<Database>() {
Ok(database.inner().clone())
} else {
let database = Database::new(database::Database::try_from(value)?);
value.manage(database.clone());
Ok(database)
}
}
}
impl Database {
fn new(database: database::Database) -> Database {
Database { database }
}
pub fn insert(
&self,
project_id: &ProjectId,
@ -108,8 +114,8 @@ fn list_by_project_id_session_id_stmt<'conn>(
) -> Result<rusqlite::CachedStatement<'conn>> {
Ok(tx.prepare_cached(
"
SELECT `file_path`, `timestamp_ms`, `operations`
FROM `deltas`
SELECT `file_path`, `timestamp_ms`, `operations`
FROM `deltas`
WHERE `session_id` = :session_id AND `project_id` = :project_id
ORDER BY `timestamp_ms` ASC",
)?)

View File

@ -14,15 +14,25 @@ pub struct Sender {
app_handle: tauri::AppHandle,
}
impl From<&AppHandle> for Sender {
fn from(value: &AppHandle) -> Self {
Self {
app_handle: value.clone(),
impl TryFrom<&AppHandle> for Sender {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(sender) = value.try_state::<Sender>() {
Ok(sender.inner().clone())
} else {
let sender = Sender::new(value.clone());
value.manage(sender.clone());
Ok(sender)
}
}
}
impl Sender {
fn new(app_handle: AppHandle) -> Sender {
Sender { app_handle }
}
pub fn send(&self, event: &Event) -> Result<()> {
self.app_handle
.emit_all(&event.name, Some(&event.payload))

View File

@ -1,6 +1,6 @@
use std::{env, path};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use crate::{keys, project_repository, projects, users};
@ -76,19 +76,20 @@ pub struct Helper {
home_dir: Option<path::PathBuf>,
}
impl From<&AppHandle> for Helper {
fn from(value: &AppHandle) -> Self {
let keys = keys::Controller::from(value);
let users = users::Controller::from(value);
Self::new(keys, users, env::var_os("HOME").map(path::PathBuf::from))
}
}
impl TryFrom<&AppHandle> for Helper {
type Error = anyhow::Error;
impl From<&path::PathBuf> for Helper {
fn from(value: &path::PathBuf) -> Self {
let keys = keys::Controller::from(value);
let users = users::Controller::from(value);
Self::new(keys, users, env::var_os("HOME").map(path::PathBuf::from))
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(helper) = value.try_state::<Helper>() {
Ok(helper.inner().clone())
} else {
let keys = keys::Controller::try_from(value)?;
let users = users::Controller::try_from(value)?;
let home_dir = env::var_os("HOME").map(path::PathBuf::from);
let helper = Helper::new(keys, users, home_dir);
value.manage(helper.clone());
Ok(helper)
}
}
}

View File

@ -1,9 +1,5 @@
use std::path;
use anyhow::Context;
use tauri::AppHandle;
use crate::storage;
use tauri::{AppHandle, Manager};
use super::{storage::Storage, PrivateKey};
@ -12,35 +8,23 @@ pub struct Controller {
storage: Storage,
}
impl From<&path::PathBuf> for Controller {
fn from(value: &path::PathBuf) -> Self {
Self {
storage: Storage::from(value),
}
}
}
impl TryFrom<&AppHandle> for Controller {
type Error = anyhow::Error;
impl From<&storage::Storage> for Controller {
fn from(value: &storage::Storage) -> Self {
Self {
storage: Storage::from(value),
}
}
}
impl From<&AppHandle> for Controller {
fn from(value: &AppHandle) -> Self {
Self {
storage: Storage::from(value),
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(controller) = value.try_state::<Controller>() {
Ok(controller.inner().clone())
} else {
let controller = Controller::new(Storage::try_from(value)?);
value.manage(controller.clone());
Ok(controller)
}
}
}
impl Controller {
pub fn new(storage: &Storage) -> Self {
Self {
storage: storage.clone(),
}
fn new(storage: Storage) -> Self {
Self { storage }
}
pub fn get_or_create(&self) -> Result<PrivateKey, GetOrCreateError> {

View File

@ -1,5 +1,3 @@
use std::path;
use tauri::{AppHandle, Manager};
use crate::storage;
@ -19,27 +17,25 @@ pub enum Error {
SSHKey(#[from] ssh_key::Error),
}
impl From<&storage::Storage> for Storage {
fn from(storage: &storage::Storage) -> Self {
Self {
storage: storage.clone(),
impl TryFrom<&AppHandle> for Storage {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(storage) = value.try_state::<Storage>() {
Ok(storage.inner().clone())
} else {
let storage = Storage::new(storage::Storage::try_from(value)?);
value.manage(storage.clone());
Ok(storage)
}
}
}
impl From<&AppHandle> for Storage {
fn from(handle: &AppHandle) -> Self {
Self::from(handle.state::<storage::Storage>().inner())
}
}
impl From<&path::PathBuf> for Storage {
fn from(value: &path::PathBuf) -> Self {
Self::from(&storage::Storage::from(value))
}
}
impl Storage {
fn new(storage: storage::Storage) -> Storage {
Storage { storage }
}
pub fn get(&self) -> Result<Option<PrivateKey>, Error> {
self.storage
.read("keys/ed25519")

View File

@ -19,26 +19,17 @@ impl TryFrom<&AppHandle> for Controller {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
local_data_dir: path,
projects_storage: storage::Storage::from(value),
users: users::Controller::from(value),
watchers: Some(value.state::<watcher::Watchers>().inner().clone()),
})
}
}
impl From<&path::PathBuf> for Controller {
fn from(value: &path::PathBuf) -> Self {
Self {
local_data_dir: value.clone(),
projects_storage: storage::Storage::from(value),
users: users::Controller::from(value),
watchers: None,
if let Some(controller) = value.try_state::<Controller>() {
Ok(controller.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
Ok(Self {
local_data_dir: app_data_dir,
projects_storage: storage::Storage::try_from(value)?,
users: users::Controller::try_from(value)?,
watchers: Some(watcher::Watchers::try_from(value)?),
})
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}

View File

@ -1,5 +1,3 @@
use std::path;
use serde::{Deserialize, Serialize};
use tauri::{AppHandle, Manager};
@ -15,26 +13,20 @@ pub struct Storage {
storage: storage::Storage,
}
impl From<&storage::Storage> for Storage {
fn from(storage: &storage::Storage) -> Self {
Storage {
storage: storage.clone(),
impl TryFrom<&AppHandle> for Storage {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(storage) = value.try_state::<Storage>() {
Ok(storage.inner().clone())
} else {
let storage = Storage::new(storage::Storage::try_from(value)?);
value.manage(storage.clone());
Ok(storage)
}
}
}
impl From<&path::PathBuf> for Storage {
fn from(value: &path::PathBuf) -> Self {
Self::from(&storage::Storage::from(value))
}
}
impl From<&AppHandle> for Storage {
fn from(value: &AppHandle) -> Self {
Self::from(value.state::<storage::Storage>().inner())
}
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct UpdateRequest {
pub id: ProjectId,
@ -60,6 +52,10 @@ pub enum Error {
}
impl Storage {
fn new(storage: storage::Storage) -> Storage {
Storage { storage }
}
pub fn list(&self) -> Result<Vec<project::Project>, Error> {
match self.storage.read(PROJECTS_FILE)? {
Some(projects) => {

View File

@ -1,7 +1,7 @@
use std::path;
use anyhow::Context;
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use crate::{
gb_repository, project_repository,
@ -11,6 +11,7 @@ use crate::{
use super::{Database, Session};
#[derive(Clone)]
pub struct Controller {
local_data_dir: path::PathBuf,
sessions_database: Database,
@ -23,16 +24,18 @@ impl TryFrom<&AppHandle> for Controller {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
local_data_dir: path,
sessions_database: Database::from(value),
projects: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
})
if let Some(controller) = value.try_state::<Controller>() {
Ok(controller.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
Ok(Self {
local_data_dir: app_data_dir,
sessions_database: Database::try_from(value)?,
projects: projects::Controller::try_from(value)?,
users: users::Controller::try_from(value)?,
})
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}

View File

@ -10,21 +10,25 @@ pub struct Database {
database: database::Database,
}
impl From<database::Database> for Database {
fn from(database: database::Database) -> Self {
Self { database }
}
}
impl TryFrom<&AppHandle> for Database {
type Error = anyhow::Error;
impl From<&AppHandle> for Database {
fn from(value: &AppHandle) -> Self {
Self {
database: value.state::<database::Database>().inner().clone(),
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(database) = value.try_state::<Database>() {
Ok(database.inner().clone())
} else {
let database = Database::new(database::Database::try_from(value)?);
value.manage(database.clone());
Ok(database)
}
}
}
impl Database {
fn new(database: database::Database) -> Database {
Database { database }
}
pub fn insert(&self, project_id: &ProjectId, sessions: &[&session::Session]) -> Result<()> {
self.database.transaction(|tx| -> Result<()> {
let mut stmt = insert_stmt(tx).context("Failed to prepare insert statement")?;

View File

@ -1,13 +1,13 @@
use std::{
fs,
path::{self, Path, PathBuf},
path::{Path, PathBuf},
sync::{Arc, RwLock},
};
#[cfg(target_family = "unix")]
use std::os::unix::prelude::*;
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
#[derive(Debug, Default, Clone)]
pub struct Storage {
@ -24,25 +24,25 @@ impl TryFrom<&AppHandle> for Storage {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
let path = value.path_resolver().app_data_dir();
match path {
Some(path) => Ok(Self::from(&path)),
// None => Error::new("failed to get app data dir"),
None => Err(anyhow::anyhow!("failed to get app data dir")),
// None => Ok(Self::default()),
}
}
}
impl From<&path::PathBuf> for Storage {
fn from(value: &path::PathBuf) -> Self {
Storage {
local_data_dir: Arc::new(RwLock::new(value.clone())),
if let Some(storage) = value.try_state::<Storage>() {
Ok(storage.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let storage = Storage::new(app_data_dir);
value.manage(storage.clone());
Ok(storage)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl Storage {
fn new<P: AsRef<Path>>(local_data_dir: P) -> Storage {
Storage {
local_data_dir: Arc::new(RwLock::new(local_data_dir.as_ref().to_path_buf())),
}
}
pub fn read<P: AsRef<Path>>(&self, path: P) -> Result<Option<String>, Error> {
let local_data_dir = self.local_data_dir.read().unwrap();
let file_path = local_data_dir.join(path);

View File

@ -1,9 +1,5 @@
use std::path;
use anyhow::Context;
use tauri::AppHandle;
use crate::storage;
use tauri::{AppHandle, Manager};
use super::{storage::Storage, User};
@ -12,31 +8,25 @@ pub struct Controller {
storage: Storage,
}
impl From<&path::PathBuf> for Controller {
fn from(value: &path::PathBuf) -> Self {
Self {
storage: Storage::from(value),
}
}
}
impl TryFrom<&AppHandle> for Controller {
type Error = anyhow::Error;
impl From<&storage::Storage> for Controller {
fn from(storage: &storage::Storage) -> Self {
Self {
storage: Storage::from(storage),
}
}
}
impl From<&AppHandle> for Controller {
fn from(app: &AppHandle) -> Self {
Self {
storage: Storage::from(app),
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(controller) = value.try_state::<Controller>() {
Ok(controller.inner().clone())
} else {
let controller = Controller::new(Storage::try_from(value)?);
value.manage(controller.clone());
Ok(controller)
}
}
}
impl Controller {
fn new(storage: Storage) -> Controller {
Controller { storage }
}
pub fn get_user(&self) -> Result<Option<User>, GetError> {
self.storage
.get()

View File

@ -1,5 +1,3 @@
use std::path;
use anyhow::Result;
use tauri::{AppHandle, Manager};
@ -20,27 +18,25 @@ pub enum Error {
Json(#[from] serde_json::Error),
}
impl From<&storage::Storage> for Storage {
fn from(storage: &storage::Storage) -> Self {
Self {
storage: storage.clone(),
impl TryFrom<&AppHandle> for Storage {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(storage) = value.try_state::<Storage>() {
Ok(storage.inner().clone())
} else {
let storage = Storage::new(storage::Storage::try_from(value)?);
value.manage(storage.clone());
Ok(storage)
}
}
}
impl From<&AppHandle> for Storage {
fn from(value: &AppHandle) -> Self {
Self::from(value.state::<storage::Storage>().inner())
}
}
impl From<&path::PathBuf> for Storage {
fn from(value: &path::PathBuf) -> Self {
Self::from(&storage::Storage::from(value))
}
}
impl Storage {
fn new(storage: storage::Storage) -> Storage {
Storage { storage }
}
pub fn get(&self) -> Result<Option<user::User>, Error> {
match self.storage.read(USER_FILE)? {
Some(data) => Ok(Some(serde_json::from_str(&data)?)),

View File

@ -1,7 +1,7 @@
use std::{collections::HashMap, path, sync::Arc};
use anyhow::Context;
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use tokio::sync::Semaphore;
use crate::{
@ -35,36 +35,38 @@ impl TryFrom<&AppHandle> for Controller {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
let data_dir = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self::new(
&data_dir,
&projects::Controller::from(&data_dir),
&users::Controller::from(&data_dir),
&keys::Controller::from(&data_dir),
&git::credentials::Helper::from(&data_dir),
))
if let Some(controller) = value.try_state::<Controller>() {
Ok(controller.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
Ok(Self::new(
app_data_dir,
projects::Controller::try_from(value)?,
users::Controller::try_from(value)?,
keys::Controller::try_from(value)?,
git::credentials::Helper::try_from(value)?,
))
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl Controller {
pub fn new(
data_dir: &path::Path,
projects: &projects::Controller,
users: &users::Controller,
keys: &keys::Controller,
helper: &git::credentials::Helper,
local_data_dir: path::PathBuf,
projects: projects::Controller,
users: users::Controller,
keys: keys::Controller,
helper: git::credentials::Helper,
) -> Self {
Self {
by_project_id: Arc::new(tokio::sync::Mutex::new(HashMap::new())),
local_data_dir: data_dir.to_path_buf(),
projects: projects.clone(),
users: users.clone(),
keys: keys.clone(),
helper: helper.clone(),
local_data_dir,
projects,
users,
keys,
helper,
}
}
@ -385,18 +387,6 @@ where
Other(#[from] anyhow::Error),
}
impl From<&path::PathBuf> for ControllerInner {
fn from(value: &path::PathBuf) -> Self {
Self::new(
value,
&projects::Controller::from(value),
&users::Controller::from(value),
&keys::Controller::from(value),
&git::credentials::Helper::from(value),
)
}
}
impl ControllerInner {
pub fn new(
data_dir: &path::Path,

View File

@ -7,7 +7,7 @@ use std::{collections::HashMap, path, sync::Arc, time};
pub use events::Event;
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use tokio::{
sync::{
mpsc::{unbounded_channel, UnboundedSender},
@ -28,15 +28,25 @@ pub struct Watchers {
impl TryFrom<&AppHandle> for Watchers {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
Ok(Self {
app_handle: value.clone(),
watchers: Arc::new(Mutex::new(HashMap::new())),
})
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(watchers) = value.try_state::<Watchers>() {
Ok(watchers.inner().clone())
} else {
let watchers = Watchers::new(value.clone());
value.manage(watchers.clone());
Ok(watchers)
}
}
}
impl Watchers {
fn new(app_handle: AppHandle) -> Self {
Self {
app_handle,
watchers: Arc::new(Mutex::new(HashMap::new())),
}
}
pub fn watch(&self, project: &projects::Project) -> Result<()> {
let watcher = Watcher::try_from(&self.app_handle)?;

View File

@ -13,7 +13,7 @@ mod tick_handler;
use std::time;
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use tracing::instrument;
use crate::events as app_events;
@ -41,26 +41,60 @@ impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
Ok(Self {
events_sender: app_events::Sender::from(value),
tick_handler: tick_handler::Handler::try_from(value)?,
git_file_change_handler: git_file_change::Handler::try_from(value)?,
index_handler: index_handler::Handler::try_from(value)?,
flush_session_handler: flush_session::Handler::try_from(value)?,
push_gitbutler_handler: push_gitbutler_data::Handler::try_from(value)?,
fetch_project_handler: fetch_project_data::Handler::try_from(value)?,
fetch_gitbutler_handler: fetch_gitbutler_data::Handler::try_from(value)?,
analytics_handler: analytics_handler::Handler::from(value),
push_project_to_gitbutler: push_project_to_gitbutler::Handler::try_from(value)?,
calculate_vbranches_handler: caltulate_virtual_branches_handler::Handler::try_from(
value,
)?,
calculate_deltas_handler: calculate_deltas_handler::Handler::try_from(value)?,
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else {
let handler = Handler::new(
git_file_change::Handler::try_from(value)?,
tick_handler::Handler::try_from(value)?,
flush_session::Handler::try_from(value)?,
fetch_project_data::Handler::try_from(value)?,
fetch_gitbutler_data::Handler::try_from(value)?,
push_gitbutler_data::Handler::try_from(value)?,
analytics_handler::Handler::try_from(value)?,
index_handler::Handler::try_from(value)?,
push_project_to_gitbutler::Handler::try_from(value)?,
caltulate_virtual_branches_handler::Handler::try_from(value)?,
calculate_deltas_handler::Handler::try_from(value)?,
app_events::Sender::try_from(value)?,
);
value.manage(handler.clone());
Ok(handler)
}
}
}
impl Handler {
fn new(
git_file_change_handler: git_file_change::Handler,
tick_handler: tick_handler::Handler,
flush_session_handler: flush_session::Handler,
fetch_project_handler: fetch_project_data::Handler,
fetch_gitbutler_handler: fetch_gitbutler_data::Handler,
push_gitbutler_handler: push_gitbutler_data::Handler,
analytics_handler: analytics_handler::Handler,
index_handler: index_handler::Handler,
push_project_to_gitbutler: push_project_to_gitbutler::Handler,
calculate_vbranches_handler: caltulate_virtual_branches_handler::Handler,
calculate_deltas_handler: calculate_deltas_handler::Handler,
events_sender: app_events::Sender,
) -> Self {
Self {
git_file_change_handler,
tick_handler,
flush_session_handler,
fetch_project_handler,
fetch_gitbutler_handler,
push_gitbutler_handler,
analytics_handler,
index_handler,
push_project_to_gitbutler,
calculate_vbranches_handler,
calculate_deltas_handler,
events_sender,
}
}
#[instrument(skip(self), fields(event = %event), level = "debug")]
pub async fn handle(
&self,

View File

@ -11,22 +11,31 @@ pub struct Handler {
client: analytics::Client,
}
impl From<&AppHandle> for Handler {
fn from(value: &AppHandle) -> Self {
let client = value
.try_state::<analytics::Client>()
.map_or(analytics::Client::default(), |client| {
client.inner().clone()
});
impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
Self {
client,
users: users::Controller::from(value),
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else {
let client = value
.try_state::<analytics::Client>()
.map_or(analytics::Client::default(), |client| {
client.inner().clone()
});
let users = users::Controller::try_from(value)?;
let handler = Handler::new(users, client);
value.manage(handler.clone());
Ok(handler)
}
}
}
impl Handler {
fn new(users: users::Controller, client: analytics::Client) -> Handler {
Handler { users, client }
}
pub async fn handle(&self, event: &analytics::Event) -> Result<Vec<events::Event>> {
if let Some(user) = self.users.get_user().context("failed to get user")? {
self.client.send(&user, event).await;

View File

@ -1,7 +1,7 @@
use std::{path, vec};
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use crate::{
deltas, gb_repository, project_repository,
@ -18,33 +18,39 @@ pub struct Handler {
users: users::Controller,
}
impl From<&path::PathBuf> for Handler {
fn from(value: &path::PathBuf) -> Self {
Self {
local_data_dir: value.clone(),
projects: projects::Controller::from(value),
users: users::Controller::from(value),
}
}
}
impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
local_data_dir: path,
projects: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let handler = Self::new(
app_data_dir,
projects::Controller::try_from(value)?,
users::Controller::try_from(value)?,
);
value.manage(handler.clone());
Ok(handler)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl Handler {
fn new(
local_data_dir: path::PathBuf,
projects: projects::Controller,
users: users::Controller,
) -> Self {
Self {
local_data_dir,
projects,
users,
}
}
// Returns Some(file_content) or None if the file is ignored.
fn get_current_file(
project_repository: &project_repository::Repository,

View File

@ -19,23 +19,36 @@ use super::events;
#[derive(Clone)]
pub struct Handler {
inner: Arc<Mutex<HandlerInner>>,
inner: Arc<Mutex<InnerHandler>>,
limit: Arc<RateLimiter<NotKeyed, InMemoryState, QuantaClock>>,
}
impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let inner = HandlerInner::try_from(value)?;
let quota = Quota::with_period(Duration::from_millis(100)).expect("valid quota");
Ok(Self {
inner: Arc::new(Mutex::new(inner)),
limit: Arc::new(RateLimiter::direct(quota)),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else {
let vbranches = virtual_branches::Controller::try_from(value)?;
let proxy = assets::Proxy::try_from(value)?;
let inner = InnerHandler::new(vbranches, proxy);
let handler = Handler::new(inner);
value.manage(handler.clone());
Ok(handler)
}
}
}
impl Handler {
fn new(inner: InnerHandler) -> Self {
let quota = Quota::with_period(Duration::from_millis(100)).expect("valid quota");
Self {
inner: Arc::new(Mutex::new(inner)),
limit: Arc::new(RateLimiter::direct(quota)),
}
}
pub async fn handle(&self, project_id: &ProjectId) -> Result<Vec<events::Event>> {
if self.limit.check().is_err() {
Ok(vec![])
@ -47,25 +60,19 @@ impl Handler {
}
}
struct HandlerInner {
struct InnerHandler {
vbranch_controller: virtual_branches::Controller,
assets_proxy: assets::Proxy,
}
impl TryFrom<&AppHandle> for HandlerInner {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
Ok(Self {
vbranch_controller: value
.state::<virtual_branches::Controller>()
.inner()
.clone(),
assets_proxy: value.state::<assets::Proxy>().inner().clone(),
})
impl InnerHandler {
fn new(vbranch_controller: virtual_branches::Controller, assets_proxy: assets::Proxy) -> Self {
Self {
vbranch_controller,
assets_proxy,
}
}
}
impl HandlerInner {
pub async fn handle(&self, project_id: &ProjectId) -> Result<Vec<events::Event>> {
match self
.vbranch_controller

View File

@ -1,7 +1,7 @@
use std::{path, sync::Arc, time};
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use tokio::sync::Mutex;
use crate::{gb_repository, project_repository, projects, projects::ProjectId, users};
@ -10,21 +10,35 @@ use super::events;
#[derive(Clone)]
pub struct Handler {
inner: Arc<Mutex<HandlerInner>>,
inner: Arc<Mutex<InnerHandler>>,
}
impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let inner = HandlerInner::try_from(value)?;
Ok(Self {
inner: Arc::new(Mutex::new(inner)),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let projects = projects::Controller::try_from(value)?;
let users = users::Controller::try_from(value)?;
let inner = InnerHandler::new(app_data_dir, projects, users);
let handler = Handler::new(inner);
value.manage(handler.clone());
Ok(handler)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl Handler {
fn new(inner: InnerHandler) -> Self {
Self {
inner: Arc::new(Mutex::new(inner)),
}
}
pub async fn handle(
&self,
project_id: &ProjectId,
@ -38,29 +52,25 @@ impl Handler {
}
}
struct HandlerInner {
struct InnerHandler {
local_data_dir: path::PathBuf,
projects: projects::Controller,
users: users::Controller,
}
impl TryFrom<&AppHandle> for HandlerInner {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let local_data_dir = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
impl InnerHandler {
fn new(
local_data_dir: path::PathBuf,
projects: projects::Controller,
users: users::Controller,
) -> Self {
Self {
local_data_dir,
projects: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
})
projects,
users,
}
}
}
impl HandlerInner {
pub async fn handle(
&self,
project_id: &ProjectId,
@ -189,7 +199,7 @@ mod test {
})
.await?;
let listener = HandlerInner {
let listener = InnerHandler {
local_data_dir: suite.local_app_data,
projects: suite.projects,
users: suite.users,
@ -208,7 +218,7 @@ mod test {
let suite = Suite::default();
let Case { project, .. } = suite.new_case();
let listener = HandlerInner {
let listener = InnerHandler {
local_data_dir: suite.local_app_data,
projects: suite.projects,
users: suite.users,

View File

@ -1,7 +1,7 @@
use std::sync::Arc;
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use tokio::sync::Mutex;
use crate::{
@ -19,14 +19,25 @@ impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let inner = HandlerInner::try_from(value)?;
Ok(Self {
inner: Arc::new(Mutex::new(inner)),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else {
let vbranches = virtual_branches::Controller::try_from(value)?;
let inner = HandlerInner::new(vbranches);
let handler = Handler::new(inner);
value.manage(handler.clone());
Ok(handler)
}
}
}
impl Handler {
fn new(inner: HandlerInner) -> Handler {
Handler {
inner: Arc::new(Mutex::new(inner)),
}
}
pub async fn handle(&self, project_id: &ProjectId) -> Result<Vec<events::Event>> {
if let Ok(inner) = self.inner.try_lock() {
inner.handle(project_id).await
@ -40,17 +51,11 @@ struct HandlerInner {
vbranches: virtual_branches::Controller,
}
impl TryFrom<&AppHandle> for HandlerInner {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
Ok(Self {
vbranches: virtual_branches::Controller::try_from(value)?,
})
}
}
impl HandlerInner {
fn new(vbranches: virtual_branches::Controller) -> HandlerInner {
HandlerInner { vbranches }
}
pub async fn handle(&self, project_id: &ProjectId) -> Result<Vec<events::Event>> {
match self.vbranches.fetch_from_target(project_id).await {
Ok(_)

View File

@ -1,7 +1,7 @@
use std::{path, sync::Arc};
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use tokio::sync::Mutex;
use crate::{gb_repository, project_repository, projects, projects::ProjectId, sessions, users};
@ -17,14 +17,29 @@ impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let inner = HandlerInner::try_from(value)?;
Ok(Self {
inner: Arc::new(Mutex::new(inner)),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let projects = projects::Controller::try_from(value)?;
let users = users::Controller::try_from(value)?;
let inner = HandlerInner::new(app_data_dir, projects, users);
let handler = Handler::new(inner);
value.manage(handler.clone());
Ok(handler)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl Handler {
fn new(inner: HandlerInner) -> Handler {
Handler {
inner: Arc::new(Mutex::new(inner)),
}
}
pub fn handle(
&self,
project_id: &ProjectId,
@ -44,23 +59,19 @@ struct HandlerInner {
users: users::Controller,
}
impl TryFrom<&AppHandle> for HandlerInner {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
local_data_dir: path,
project_store: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
})
}
}
impl HandlerInner {
fn new(
local_data_dir: path::PathBuf,
project_store: projects::Controller,
users: users::Controller,
) -> HandlerInner {
HandlerInner {
local_data_dir,
project_store,
users,
}
}
pub fn handle(
&self,
project_id: &ProjectId,

View File

@ -1,7 +1,7 @@
use std::path;
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use crate::{
analytics, events as app_events, gb_repository, project_repository,
@ -22,19 +22,33 @@ impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
local_data_dir: path,
projects: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let projects = projects::Controller::try_from(value)?;
let users = users::Controller::try_from(value)?;
let handler = Handler::new(app_data_dir, projects, users);
value.manage(handler.clone());
Ok(handler)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl Handler {
fn new(
local_data_dir: path::PathBuf,
projects: projects::Controller,
users: users::Controller,
) -> Self {
Self {
local_data_dir,
projects,
users,
}
}
pub fn handle<P: AsRef<std::path::Path>>(
&self,
path: P,

View File

@ -1,7 +1,7 @@
use std::path;
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use crate::{
deltas, events as app_events, gb_repository, project_repository,
@ -25,21 +25,45 @@ impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
local_data_dir: path,
projects: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
sessions_database: sessions::Database::from(value),
deltas_database: deltas::Database::from(value),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let projects = projects::Controller::try_from(value)?;
let users = users::Controller::try_from(value)?;
let sessions_database = sessions::Database::try_from(value)?;
let deltas_database = deltas::Database::try_from(value)?;
let handler = Handler::new(
app_data_dir,
projects,
users,
sessions_database,
deltas_database,
);
value.manage(handler.clone());
Ok(handler)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl Handler {
fn new(
local_data_dir: path::PathBuf,
projects: projects::Controller,
users: users::Controller,
sessions_database: sessions::Database,
deltas_database: deltas::Database,
) -> Handler {
Handler {
local_data_dir,
projects,
users,
sessions_database,
deltas_database,
}
}
pub fn index_deltas(
&self,
project_id: &ProjectId,

View File

@ -2,7 +2,7 @@ use std::path;
use std::sync::{Arc, Mutex, TryLockError};
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use crate::gb_repository::RemoteError;
use crate::projects::ProjectId;
@ -19,13 +19,28 @@ impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
Ok(Self {
inner: Arc::new(Mutex::new(HandlerInner::try_from(value)?)),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let projects = projects::Controller::try_from(value)?;
let users = users::Controller::try_from(value)?;
let inner = HandlerInner::new(app_data_dir, projects, users);
let handler = Handler::new(inner);
value.manage(handler.clone());
Ok(handler)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl Handler {
fn new(inner: HandlerInner) -> Self {
Self {
inner: Arc::new(Mutex::new(inner)),
}
}
pub fn handle(&self, project_id: &ProjectId) -> Result<Vec<events::Event>> {
match self.inner.try_lock() {
Ok(inner) => inner.handle(project_id),
@ -41,22 +56,6 @@ struct HandlerInner {
users: users::Controller,
}
impl TryFrom<&AppHandle> for HandlerInner {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self::new(
path,
projects::Controller::try_from(value)?,
users::Controller::from(value),
))
}
}
impl HandlerInner {
fn new(
local_data_dir: path::PathBuf,

View File

@ -2,7 +2,7 @@ use std::{path, sync::Arc, time};
use anyhow::{Context, Result};
use itertools::Itertools;
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use tokio::sync::Mutex;
use crate::{
@ -24,14 +24,28 @@ impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let inner = HandlerInner::try_from(value)?;
Ok(Self {
inner: Arc::new(Mutex::new(inner)),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let projects = projects::Controller::try_from(value)?;
let users = users::Controller::try_from(value)?;
let inner = HandlerInner::new(app_data_dir, projects, users);
let handler = Handler::new(inner);
value.manage(handler.clone());
Ok(handler)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
impl Handler {
fn new(inner: HandlerInner) -> Self {
Self {
inner: Arc::new(Mutex::new(inner)),
}
}
pub async fn handle(&self, project_id: &ProjectId) -> Result<Vec<events::Event>> {
if let Ok(inner) = self.inner.try_lock() {
inner.handle(project_id).await
@ -48,24 +62,20 @@ pub struct HandlerInner {
batch_size: usize,
}
impl TryFrom<&AppHandle> for HandlerInner {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
batch_size: 1000,
local_data_dir: path,
project_store: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
})
}
}
impl HandlerInner {
fn new(
local_data_dir: path::PathBuf,
project_store: projects::Controller,
users: users::Controller,
) -> Self {
Self {
local_data_dir,
project_store,
users,
batch_size: 1000,
}
}
pub async fn handle(&self, project_id: &ProjectId) -> Result<Vec<events::Event>> {
let project = self
.project_store

View File

@ -1,7 +1,7 @@
use std::{path, time};
use anyhow::{Context, Result};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use crate::{
gb_repository, project_repository,
@ -22,15 +22,19 @@ impl TryFrom<&AppHandle> for Handler {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> std::result::Result<Self, Self::Error> {
let path = value
.path_resolver()
.app_data_dir()
.context("failed to get app data dir")?;
Ok(Self {
local_data_dir: path,
projects: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
})
if let Some(handler) = value.try_state::<Handler>() {
Ok(handler.inner().clone())
} else if let Some(app_data_dir) = value.path_resolver().app_data_dir() {
let handler = Handler::new(
app_data_dir,
projects::Controller::try_from(value)?,
users::Controller::try_from(value)?,
);
value.manage(handler.clone());
Ok(handler)
} else {
Err(anyhow::anyhow!("failed to get app data dir"))
}
}
}
@ -39,6 +43,18 @@ const PROJECT_FETCH_INTERVAL: time::Duration = time::Duration::new(15 * 60, 0);
const PROJECT_PUSH_INTERVAL: time::Duration = time::Duration::new(15 * 60, 0);
impl Handler {
fn new(
local_data_dir: path::PathBuf,
projects: projects::Controller,
users: users::Controller,
) -> Self {
Self {
local_data_dir,
projects,
users,
}
}
pub fn handle(
&self,
project_id: &ProjectId,

View File

@ -10,37 +10,39 @@ use std::{
use anyhow::{Context, Result};
use sha2::{Digest, Sha256};
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use walkdir::{DirEntry, WalkDir};
use zip::{result::ZipError, write, CompressionMethod, ZipWriter};
#[derive(Clone)]
pub struct Zipper {
cache: path::PathBuf,
}
impl From<&path::PathBuf> for Zipper {
fn from(value: &path::PathBuf) -> Self {
Self {
cache: value.clone(),
}
}
}
impl TryFrom<&AppHandle> for Zipper {
type Error = anyhow::Error;
fn try_from(handle: &AppHandle) -> Result<Self> {
let cache_dir = handle
.path_resolver()
.app_cache_dir()
.context("failed to get cache dir")?;
fs::create_dir_all(&cache_dir).context("failed to create cache dir")?;
let cache = cache_dir.join("archives");
Ok(Self::from(&cache))
if let Some(zipper) = handle.try_state::<Self>() {
Ok(zipper.inner().clone())
} else {
let app_cache_dir = handle
.path_resolver()
.app_cache_dir()
.context("failed to get app cache dir")?;
Self::new(app_cache_dir)
}
}
}
impl Zipper {
fn new<P: AsRef<path::Path>>(cache_dir: P) -> Result<Self, anyhow::Error> {
let cache_dir = cache_dir.as_ref().to_path_buf();
fs::create_dir_all(&cache_dir).context("failed to create cache dir")?;
let cache = cache_dir.join("archives");
Ok(Self { cache })
}
// takes a path to create zip of, returns path of a created archive.
pub fn zip<P: AsRef<path::Path>>(&self, path: P) -> Result<path::PathBuf> {
let path = path.as_ref();

View File

@ -1,11 +1,12 @@
use std::path;
use tauri::AppHandle;
use tauri::{AppHandle, Manager};
use crate::projects::{self, ProjectId};
use super::Zipper;
#[derive(Clone)]
pub struct Controller {
local_data_dir: path::PathBuf,
logs_dir: path::PathBuf,
@ -17,24 +18,41 @@ impl TryFrom<&AppHandle> for Controller {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
let local_data_dir = value
.path_resolver()
.app_data_dir()
.ok_or_else(|| anyhow::anyhow!("failed to get local data dir"))?;
let logs_dir = value
.path_resolver()
.app_log_dir()
.ok_or_else(|| anyhow::anyhow!("failed to get logs dir"))?;
Ok(Self {
local_data_dir,
logs_dir,
zipper: Zipper::try_from(value)?,
projects_controller: projects::Controller::try_from(value)?,
})
if let Some(controller) = value.try_state::<Controller>() {
Ok(controller.inner().clone())
} else {
let local_data_dir = value
.path_resolver()
.app_data_dir()
.ok_or_else(|| anyhow::anyhow!("failed to get local data dir"))?;
let logs_dir = value
.path_resolver()
.app_log_dir()
.ok_or_else(|| anyhow::anyhow!("failed to get logs dir"))?;
let zipper = Zipper::try_from(value)?;
let projects = projects::Controller::try_from(value)?;
let controller = Controller::new(local_data_dir, logs_dir, zipper, projects);
value.manage(controller.clone());
Ok(controller)
}
}
}
impl Controller {
fn new(
local_data_dir: path::PathBuf,
logs_dir: path::PathBuf,
zipper: Zipper,
projects_controller: projects::Controller,
) -> Self {
Self {
local_data_dir,
logs_dir,
zipper,
projects_controller,
}
}
pub fn archive(&self, project_id: &ProjectId) -> Result<path::PathBuf, ArchiveError> {
let project = self.projects_controller.get(project_id)?;
self.zipper.zip(project.path).map_err(Into::into)