use std::error::Error; use futures_util::{future::BoxFuture, FutureExt}; use giterated_models::{ authenticated::UserAuthenticationToken, error::{GetValueError, InstanceError, OperationError, RepositoryError, UserError}, instance::{AuthenticationTokenRequest, Instance, RegisterAccountRequest}, object_backend::ObjectBackend, repository::{ Commit, DefaultBranch, Description, LatestCommit, Repository, RepositoryCommitBeforeRequest, RepositoryDiff, RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest, RepositoryFileInspectRequest, RepositoryInfoRequest, RepositorySummary, RepositoryView, Visibility, }, settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError}, user::{User, UserRepositoriesRequest}, value::{AnyValue, GetValue}, }; use giterated_stack::{BackendWrapper, StackOperationState}; use super::DatabaseBackend; pub fn user_get_repositories( object: &User, _operation: UserRepositoriesRequest, state: DatabaseBackend, ) -> BoxFuture<'static, Result, OperationError>> { let object = object.clone(); async move { let mut user_backend = state.user_backend.lock().await; let repositories = user_backend .repositories_for_user(None, &object) .await .map_err(|e| OperationError::Internal(e.to_string()))?; Ok(repositories) } .boxed() } pub fn user_get_value( object: &User, operation: GetValue>, state: DatabaseBackend, ) -> BoxFuture<'static, Result, OperationError>> { let object = object.clone(); async move { let mut user_backend = state.user_backend.lock().await; let value = user_backend .get_value(&object, &operation.value_name) .await .map_err(|e| OperationError::Internal(e.to_string()))?; Ok(value) } .boxed() } pub fn user_get_setting( object: &User, operation: GetSetting, state: DatabaseBackend, ) -> BoxFuture<'static, Result>> { let object = object.clone(); async move { let mut user_backend = state.user_backend.lock().await; let value = user_backend .get_setting(&object, &operation.setting_name) .await .map_err(|e| OperationError::Internal(e.to_string()))?; Ok(value) } .boxed() } pub fn user_set_setting( object: &User, operation: SetSetting, state: DatabaseBackend, ) -> BoxFuture<'static, Result<(), OperationError>> { let object = object.clone(); async move { let mut user_backend = state.user_backend.lock().await; let value = user_backend .write_setting(&object, &operation.setting_name, &operation.value.0) .await .map_err(|e| OperationError::Internal(e.to_string()))?; Ok(value) } .boxed() } pub fn repository_info( object: &Repository, operation: RepositoryInfoRequest, state: DatabaseBackend, operation_state: StackOperationState, backend: BackendWrapper, ) -> BoxFuture<'static, Result>> { let object = object.clone(); async move { let mut object = backend .get_object::(&object.to_string(), &operation_state) .await .unwrap(); let mut repository_backend = state.repository_backend.lock().await; let tree = repository_backend .repository_file_inspect( None, object.object(), &RepositoryFileInspectRequest { extra_metadata: operation.extra_metadata, path: operation.path, rev: operation.rev.clone(), }, ) .await .map_err(|err| OperationError::Internal(format!("{:?}", err)))?; drop(repository_backend); let info = RepositoryView { name: object.object().name.clone(), owner: object.object().owner.clone(), description: object.get::(&operation_state).await.ok(), visibility: object .get::(&operation_state) .await .map_err(|e| OperationError::Internal(format!("{:?}: {}", e.source(), e)))?, default_branch: object .get::(&operation_state) .await .map_err(|e| OperationError::Internal(format!("{:?}: {}", e.source(), e)))?, // TODO: Can't be a simple get function, this needs to be returned alongside the tree as this differs depending on the rev and path. latest_commit: object.get::(&operation_state).await.ok(), tree_rev: operation.rev, tree, }; Ok(info) } .boxed() } pub fn repository_file_from_id( object: &Repository, operation: RepositoryFileFromIdRequest, state: DatabaseBackend, operation_state: StackOperationState, backend: BackendWrapper, ) -> BoxFuture<'static, Result>> { let object = object.clone(); async move { let object = backend .get_object::(&object.to_string(), &operation_state) .await .unwrap(); let mut repository_backend = state.repository_backend.lock().await; let file = repository_backend .repository_file_from_id( None, object.object(), &RepositoryFileFromIdRequest(operation.0), ) .await .map_err(|err| OperationError::Internal(format!("{:?}", err)))?; drop(repository_backend); Ok(file) } .boxed() } pub fn repository_diff( object: &Repository, operation: RepositoryDiffRequest, state: DatabaseBackend, operation_state: StackOperationState, backend: BackendWrapper, ) -> BoxFuture<'static, Result>> { let object = object.clone(); async move { let object = backend .get_object::(&object.to_string(), &operation_state) .await .unwrap(); let mut repository_backend = state.repository_backend.lock().await; let file = repository_backend .repository_diff(None, object.object(), &operation) .await .map_err(|err| OperationError::Internal(format!("{:?}", err)))?; drop(repository_backend); Ok(file) } .boxed() } pub fn repository_commit_before( object: &Repository, operation: RepositoryCommitBeforeRequest, state: DatabaseBackend, operation_state: StackOperationState, backend: BackendWrapper, ) -> BoxFuture<'static, Result>> { let object = object.clone(); async move { let object = backend .get_object::(&object.to_string(), &operation_state) .await .unwrap(); let mut repository_backend = state.repository_backend.lock().await; let file = repository_backend .repository_commit_before(None, object.object(), &operation) .await .map_err(|err| OperationError::Internal(format!("{:?}", err)))?; drop(repository_backend); Ok(file) } .boxed() } pub fn repository_get_value( object: &Repository, operation: GetValue>, state: DatabaseBackend, ) -> BoxFuture<'static, Result, OperationError>> { let object = object.clone(); async move { let mut repository_backend = state.repository_backend.lock().await; let value = repository_backend .get_value(&object, &operation.value_name) .await .map_err(|e| { OperationError::Internal(format!("error getting value: {}", e.to_string())) })?; Ok(value) } .boxed() } pub fn repository_get_setting( object: &Repository, operation: GetSetting, state: DatabaseBackend, ) -> BoxFuture<'static, Result>> { let object = object.clone(); async move { let mut repository_backend = state.repository_backend.lock().await; let value = repository_backend .get_setting(&object, &operation.setting_name) .await .map_err(|e| OperationError::Internal(e.to_string()))?; Ok(value) } .boxed() } pub fn repository_set_setting( object: &Repository, operation: SetSetting, state: DatabaseBackend, ) -> BoxFuture<'static, Result<(), OperationError>> { let object = object.clone(); async move { let mut repository_backend = state.repository_backend.lock().await; let value = repository_backend .write_setting(&object, &operation.setting_name, &operation.value.0) .await .map_err(|e| OperationError::Internal(e.to_string()))?; Ok(value) } .boxed() } pub fn instance_authentication_request( object: &Instance, operation: AuthenticationTokenRequest, state: DatabaseBackend, ) -> BoxFuture<'static, Result>> { let object = object.clone(); async move { let mut backend = state.user_backend.lock().await; backend .login(&object, operation) .await .map_err(|e| OperationError::Internal(e.to_string())) } .boxed() } pub fn instance_registration_request( _object: &Instance, operation: RegisterAccountRequest, state: DatabaseBackend, ) -> BoxFuture<'static, Result>> { async move { let mut backend = state.user_backend.lock().await; backend .register(operation) .await .map_err(|e| OperationError::Internal(e.to_string())) } .boxed() }