Fix handling stack
parent: tbd commit: c53b026
Showing 15 changed files with 182 insertions and 149 deletions
giterated-daemon/src/backend/git.rs
@@ -5,16 +5,16 @@ use futures_util::StreamExt; | ||
5 | 5 | use giterated_models::instance::{Instance, RepositoryCreateRequest}; |
6 | 6 | |
7 | 7 | use giterated_models::repository::{ |
8 | Commit, IssueLabel, Repository, RepositoryDescription, RepositoryFileInspectRequest, | |
9 | RepositoryIssue, RepositoryIssueLabelsRequest, RepositoryIssuesCountRequest, | |
10 | RepositoryIssuesRequest, RepositorySummary, RepositoryTreeEntry, RepositoryVisibility, | |
11 | RepositoryVisibilitySetting, RepositoryObjectType, Description, Visibility, LatestCommit, DefaultBranch, | |
8 | Commit, DefaultBranch, Description, IssueLabel, LatestCommit, Repository, | |
9 | RepositoryFileInspectRequest, RepositoryIssue, RepositoryIssueLabelsRequest, | |
10 | RepositoryIssuesCountRequest, RepositoryIssuesRequest, RepositoryObjectType, | |
11 | RepositoryTreeEntry, RepositoryVisibility, Visibility, | |
12 | 12 | }; |
13 | 13 | use giterated_models::settings::{AnySetting, Setting}; |
14 | 14 | use giterated_models::user::{User, UserParseError}; |
15 | 15 | use giterated_models::value::{AnyValue, GiteratedObjectValue}; |
16 | 16 | use serde_json::Value; |
17 | use sqlx::{Either, PgPool}; | |
17 | use sqlx::PgPool; | |
18 | 18 | use std::{ |
19 | 19 | path::{Path, PathBuf}, |
20 | 20 | sync::Arc, |
@@ -296,24 +296,13 @@ impl RepositoryBackend for GitBackend { | ||
296 | 296 | ) -> Result<AnyValue<Repository>, Error> { |
297 | 297 | Ok(unsafe { |
298 | 298 | if name == Description::value_name() { |
299 | info!("Description"); | |
300 | AnyValue::from_raw( | |
301 | self.get_setting(repository, RepositoryDescription::name()) | |
302 | .await? | |
303 | .0, | |
304 | ) | |
299 | AnyValue::from_raw(self.get_setting(repository, Description::name()).await?.0) | |
305 | 300 | } else if name == Visibility::value_name() { |
306 | AnyValue::from_raw( | |
307 | self.get_setting(repository, RepositoryVisibilitySetting::name()) | |
308 | .await? | |
309 | .0, | |
310 | ) | |
301 | AnyValue::from_raw(self.get_setting(repository, Visibility::name()).await?.0) | |
311 | 302 | } else if name == DefaultBranch::value_name() { |
312 | AnyValue::from_raw( | |
313 | self.get_setting(repository, DefaultBranch::name()) | |
314 | .await? | |
315 | .0, | |
316 | ) | |
303 | AnyValue::from_raw(self.get_setting(repository, DefaultBranch::name()).await?.0) | |
304 | } else if name == LatestCommit::value_name() { | |
305 | AnyValue::from_raw(serde_json::to_value(LatestCommit(None)).unwrap()) | |
317 | 306 | } else { |
318 | 307 | return Err(UserParseError.into()); |
319 | 308 | } |
@@ -645,14 +634,6 @@ impl RepositoryBackend for GitBackend { | ||
645 | 634 | |
646 | 635 | Ok(tree) |
647 | 636 | } |
648 | ||
649 | async fn repositories_for_user( | |
650 | &mut self, | |
651 | requester: Option<&User>, | |
652 | user: &User, | |
653 | ) -> Result<Vec<RepositorySummary>, Error> { | |
654 | unimplemented!(); | |
655 | } | |
656 | 637 | } |
657 | 638 | |
658 | 639 | impl IssuesBackend for GitBackend { |
giterated-daemon/src/backend/mod.rs
@@ -37,11 +37,6 @@ pub trait RepositoryBackend { | ||
37 | 37 | repository: &Repository, |
38 | 38 | request: &RepositoryFileInspectRequest, |
39 | 39 | ) -> Result<Vec<RepositoryTreeEntry>, Error>; |
40 | async fn repositories_for_user( | |
41 | &mut self, | |
42 | requester: Option<&User>, | |
43 | user: &User, | |
44 | ) -> Result<Vec<RepositorySummary>, Error>; | |
45 | 40 | async fn get_value( |
46 | 41 | &mut self, |
47 | 42 | user: &Repository, |
@@ -100,6 +95,11 @@ pub trait UserBackend: AuthBackend { | ||
100 | 95 | setting: &Value, |
101 | 96 | ) -> Result<(), Error>; |
102 | 97 | async fn exists(&mut self, user: &User) -> Result<bool, Error>; |
98 | async fn repositories_for_user( | |
99 | &mut self, | |
100 | requester: Option<&User>, | |
101 | user: &User, | |
102 | ) -> Result<Vec<RepositorySummary>, Error>; | |
103 | 103 | } |
104 | 104 | |
105 | 105 | #[async_trait::async_trait] |
giterated-daemon/src/backend/settings.rs
@@ -49,7 +49,7 @@ impl MetadataBackend for DatabaseSettings { | ||
49 | 49 | let row = sqlx::query_as!( |
50 | 50 | RepositorySettingRow, |
51 | 51 | "SELECT * FROM repository_settings WHERE repository = $1 AND name = $2", |
52 | format!("{}/{}", repository.owner, repository.name), | |
52 | repository.to_string(), | |
53 | 53 | name |
54 | 54 | ) |
55 | 55 | .fetch_one(&self.pg_pool) |
giterated-daemon/src/backend/user.rs
@@ -1,10 +1,12 @@ | ||
1 | 1 | use anyhow::Error; |
2 | use futures_util::StreamExt; | |
2 | 3 | use giterated_models::authenticated::UserAuthenticationToken; |
3 | 4 | |
4 | 5 | use giterated_models::instance::{AuthenticationTokenRequest, Instance, RegisterAccountRequest}; |
5 | 6 | |
7 | use giterated_models::repository::{Repository, RepositorySummary}; | |
6 | 8 | use giterated_models::settings::{AnySetting, Setting}; |
7 | use giterated_models::user::{User, UserBio, UserDisplayName, UserParseError}; | |
9 | use giterated_models::user::{Bio, DisplayName, User, UserParseError}; | |
8 | 10 | use giterated_models::value::AnyValue; |
9 | 11 | use std::sync::Arc; |
10 | 12 | |
@@ -20,10 +22,11 @@ use rsa::{ | ||
20 | 22 | |
21 | 23 | use secrecy::ExposeSecret; |
22 | 24 | use serde_json::Value; |
23 | use sqlx::PgPool; | |
25 | use sqlx::{Either, PgPool}; | |
24 | 26 | use tokio::sync::Mutex; |
25 | 27 | |
26 | 28 | use crate::authentication::AuthenticationTokenGranter; |
29 | use crate::backend::git::GitRepository; | |
27 | 30 | |
28 | 31 | use super::{AuthBackend, MetadataBackend, UserBackend}; |
29 | 32 | |
@@ -55,11 +58,9 @@ impl UserBackend for UserAuth { | ||
55 | 58 | async fn get_value(&mut self, user: &User, name: &str) -> Result<AnyValue<User>, Error> { |
56 | 59 | Ok(match name { |
57 | 60 | "display_name" => unsafe { |
58 | AnyValue::from_raw(self.get_setting(user, UserDisplayName::name()).await?.0) | |
59 | }, | |
60 | "bio" => unsafe { | |
61 | AnyValue::from_raw(self.get_setting(user, UserBio::name()).await?.0) | |
61 | AnyValue::from_raw(self.get_setting(user, DisplayName::name()).await?.0) | |
62 | 62 | }, |
63 | "bio" => unsafe { AnyValue::from_raw(self.get_setting(user, Bio::name()).await?.0) }, | |
63 | 64 | _ => { |
64 | 65 | return Err(UserParseError.into()); |
65 | 66 | } |
@@ -94,6 +95,37 @@ impl UserBackend for UserAuth { | ||
94 | 95 | .await |
95 | 96 | .is_ok()) |
96 | 97 | } |
98 | ||
99 | async fn repositories_for_user( | |
100 | &mut self, | |
101 | _requester: Option<&User>, | |
102 | user: &User, | |
103 | ) -> Result<Vec<RepositorySummary>, Error> { | |
104 | let mut repositories = sqlx::query_as!( | |
105 | GitRepository, | |
106 | r#"SELECT owner_user, name, description, visibility as "visibility: _", default_branch FROM repositories WHERE owner_user = $1"#, | |
107 | user.to_string() | |
108 | ) | |
109 | .fetch_many(&self.pg_pool); | |
110 | ||
111 | let mut return_repositories = vec![]; | |
112 | ||
113 | while let Some(Ok(Either::Right(repository_row))) = repositories.next().await { | |
114 | return_repositories.push(RepositorySummary { | |
115 | repository: Repository { | |
116 | owner: repository_row.owner_user.clone(), | |
117 | name: repository_row.name, | |
118 | instance: self.this_instance.clone(), | |
119 | }, | |
120 | owner: repository_row.owner_user, | |
121 | visibility: repository_row.visibility, | |
122 | description: repository_row.description, | |
123 | last_commit: None, | |
124 | }) | |
125 | } | |
126 | ||
127 | Ok(return_repositories) | |
128 | } | |
97 | 129 | } |
98 | 130 | |
99 | 131 | #[async_trait::async_trait] |
@@ -183,7 +215,6 @@ impl AuthBackend for UserAuth { | ||
183 | 215 | source: &Instance, |
184 | 216 | request: AuthenticationTokenRequest, |
185 | 217 | ) -> Result<UserAuthenticationToken, Error> { |
186 | info!("fetching!"); | |
187 | 218 | let user = sqlx::query_as!( |
188 | 219 | UserRow, |
189 | 220 | r#"SELECT * FROM users WHERE username = $1"#, |
@@ -198,7 +229,6 @@ impl AuthBackend for UserAuth { | ||
198 | 229 | .verify_password(request.password.expose_secret().0.as_bytes(), &hash) |
199 | 230 | .is_err() |
200 | 231 | { |
201 | info!("invalid password"); | |
202 | 232 | return Err(Error::from(AuthenticationError::InvalidPassword)); |
203 | 233 | } |
204 | 234 |
giterated-daemon/src/cache_backend.rs
@@ -14,8 +14,8 @@ impl ObjectBackend for CacheBackend { | ||
14 | 14 | async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>( |
15 | 15 | &self, |
16 | 16 | _object: O, |
17 | operation: &str, | |
18 | payload: D, | |
17 | _operation: &str, | |
18 | _payload: D, | |
19 | 19 | ) -> Result<D::Success, OperationError<D::Failure>> { |
20 | 20 | // We don't handle operations with this backend |
21 | 21 | Err(OperationError::Unhandled) |
giterated-daemon/src/connection/wrapper.rs
@@ -6,7 +6,7 @@ use std::{ | ||
6 | 6 | use anyhow::Error; |
7 | 7 | use futures_util::{SinkExt, StreamExt}; |
8 | 8 | |
9 | use giterated_models::instance::Instance; | |
9 | use giterated_models::{error::OperationError, instance::Instance}; | |
10 | 10 | |
11 | 11 | use giterated_models::object_backend::ObjectBackend; |
12 | 12 | |
@@ -87,12 +87,23 @@ pub async fn connection_wrapper( | ||
87 | 87 | .object_operation(message.object, &message.operation, message.payload) |
88 | 88 | .await; |
89 | 89 | |
90 | // Map result to Vec<u8> on both | |
91 | let result = match result { | |
92 | Ok(result) => Ok(serde_json::to_vec(&result).unwrap()), | |
93 | Err(err) => Err(match err { | |
94 | OperationError::Operation(err) => { | |
95 | OperationError::Operation(serde_json::to_vec(&err).unwrap()) | |
96 | } | |
97 | OperationError::Internal(err) => OperationError::Internal(err), | |
98 | OperationError::Unhandled => OperationError::Unhandled, | |
99 | }), | |
100 | }; | |
101 | ||
90 | 102 | let mut socket = connection_state.socket.lock().await; |
91 | 103 | let _ = socket |
92 | 104 | .send(Message::Binary(bincode::serialize(&result).unwrap())) |
93 | 105 | .await; |
94 | 106 | |
95 | info!("Done!"); | |
96 | 107 | drop(socket); |
97 | 108 | } |
98 | 109 | _ => { |
giterated-daemon/src/database_backend/handler.rs
@@ -1,14 +1,18 @@ | ||
1 | use std::{collections::HashMap, pin::Pin, sync::Arc}; | |
1 | use std::{collections::HashMap, error::Error, pin::Pin, sync::Arc}; | |
2 | 2 | |
3 | 3 | use futures_util::{future::BoxFuture, Future, FutureExt}; |
4 | 4 | use giterated_models::{ |
5 | error::{GetValueError, OperationError, UserError, RepositoryError}, | |
5 | error::{GetValueError, OperationError, RepositoryError, UserError}, | |
6 | 6 | object::{AnyObject, GiteratedObject}, |
7 | object_backend::ObjectBackend, | |
7 | 8 | operation::{AnyOperation, GiteratedOperation}, |
8 | repository::{Repository, RepositorySummary, RepositoryInfoRequest, RepositoryView, Description, Visibility, DefaultBranch, LatestCommit, RepositoryFileInspectRequest}, | |
9 | repository::{ | |
10 | DefaultBranch, Description, LatestCommit, Repository, RepositoryFileInspectRequest, | |
11 | RepositoryInfoRequest, RepositorySummary, RepositoryView, Visibility, | |
12 | }, | |
9 | 13 | settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError}, |
10 | 14 | user::{User, UserRepositoriesRequest}, |
11 | value::{AnyValue, GetValue}, object_backend::ObjectBackend, | |
15 | value::{AnyValue, GetValue}, | |
12 | 16 | }; |
13 | 17 | |
14 | 18 | use super::DatabaseBackend; |
@@ -122,14 +126,14 @@ impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> { | ||
122 | 126 | |
123 | 127 | pub fn user_get_repositories( |
124 | 128 | object: &User, |
125 | operation: UserRepositoriesRequest, | |
129 | _operation: UserRepositoriesRequest, | |
126 | 130 | state: DatabaseBackend, |
127 | 131 | ) -> BoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> { |
128 | 132 | let object = object.clone(); |
129 | 133 | |
130 | 134 | async move { |
131 | let mut repositories_backend = state.repository_backend.lock().await; | |
132 | let repositories = repositories_backend | |
135 | let mut user_backend = state.user_backend.lock().await; | |
136 | let repositories = user_backend | |
133 | 137 | .repositories_for_user(None, &object) |
134 | 138 | .await |
135 | 139 | .map_err(|e| OperationError::Internal(e.to_string()))?; |
@@ -199,26 +203,50 @@ pub fn user_set_setting( | ||
199 | 203 | pub fn repository_info( |
200 | 204 | object: &Repository, |
201 | 205 | operation: RepositoryInfoRequest, |
202 | state: DatabaseBackend | |
206 | state: DatabaseBackend, | |
203 | 207 | ) -> BoxFuture<'static, Result<RepositoryView, OperationError<RepositoryError>>> { |
204 | 208 | let object = object.clone(); |
205 | 209 | |
206 | 210 | async move { |
207 | let mut object = state.get_object::<Repository>(&object.to_string()).await.unwrap(); | |
211 | let mut object = state | |
212 | .get_object::<Repository>(&object.to_string()) | |
213 | .await | |
214 | .unwrap(); | |
208 | 215 | |
209 | 216 | let mut repository_backend = state.repository_backend.lock().await; |
210 | let tree = repository_backend.repository_file_inspect(None, object.object(), &RepositoryFileInspectRequest { | |
211 | extra_metadata: operation.extra_metadata, | |
212 | path: operation.path, | |
213 | rev: operation.rev.clone(), | |
214 | }).await.map_err(|err| OperationError::Internal(format!("{:?}", err)))?; | |
215 | ||
217 | let tree = repository_backend | |
218 | .repository_file_inspect( | |
219 | None, | |
220 | object.object(), | |
221 | &RepositoryFileInspectRequest { | |
222 | extra_metadata: operation.extra_metadata, | |
223 | path: operation.path, | |
224 | rev: operation.rev.clone(), | |
225 | }, | |
226 | ) | |
227 | .await | |
228 | .map_err(|err| OperationError::Internal(format!("{:?}", err)))?; | |
229 | drop(repository_backend); | |
230 | ||
231 | let _visibility = object.get::<Visibility>().await.map_err(|e| { | |
232 | OperationError::Internal(format!("{:?}: {}", e.source(), e.to_string())) | |
233 | })?; | |
234 | let _default_branch = object.get::<DefaultBranch>().await.map_err(|e| { | |
235 | OperationError::Internal(format!("{:?}: {}", e.source(), e.to_string())) | |
236 | })?; | |
237 | ||
216 | 238 | let info = RepositoryView { |
217 | 239 | name: object.object().name.clone(), |
218 | 240 | owner: object.object().owner.clone(), |
219 | 241 | description: object.get::<Description>().await.ok(), |
220 | visibility: object.get::<Visibility>().await.map_err(|e| OperationError::Internal(e.to_string()))?, | |
221 | default_branch: object.get::<DefaultBranch>().await.map_err(|e| OperationError::Internal(e.to_string()))?, | |
242 | visibility: object | |
243 | .get::<Visibility>() | |
244 | .await | |
245 | .map_err(|e| OperationError::Internal(e.to_string()))?, | |
246 | default_branch: object | |
247 | .get::<DefaultBranch>() | |
248 | .await | |
249 | .map_err(|e| OperationError::Internal(e.to_string()))?, | |
222 | 250 | // 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. |
223 | 251 | latest_commit: object.get::<LatestCommit>().await.ok(), |
224 | 252 | tree_rev: operation.rev, |
@@ -242,7 +270,9 @@ pub fn repository_get_value( | ||
242 | 270 | let value = repository_backend |
243 | 271 | .get_value(&object, &operation.value_name) |
244 | 272 | .await |
245 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
273 | .map_err(|e| { | |
274 | OperationError::Internal(format!("error getting value: {}", e.to_string())) | |
275 | })?; | |
246 | 276 | |
247 | 277 | Ok(value) |
248 | 278 | } |
giterated-daemon/src/database_backend/mod.rs
@@ -1,15 +1,14 @@ | ||
1 | 1 | pub mod handler; |
2 | 2 | |
3 | use std::any::type_name; | |
4 | 3 | use std::{str::FromStr, sync::Arc}; |
5 | 4 | |
6 | 5 | use giterated_models::error::OperationError; |
7 | 6 | use giterated_models::instance::Instance; |
8 | 7 | use giterated_models::object::{ |
9 | AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse, | |
8 | AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, | |
10 | 9 | }; |
11 | 10 | use giterated_models::object_backend::ObjectBackend; |
12 | use giterated_models::operation::{AnyOperation, GiteratedOperation}; | |
11 | use giterated_models::operation::GiteratedOperation; | |
13 | 12 | use giterated_models::repository::Repository; |
14 | 13 | use giterated_models::user::User; |
15 | 14 | use std::fmt::Debug; |
@@ -18,8 +17,8 @@ use tokio::sync::Mutex; | ||
18 | 17 | use crate::backend::{RepositoryBackend, UserBackend}; |
19 | 18 | |
20 | 19 | use self::handler::{ |
21 | repository_get_setting, repository_get_value, repository_set_setting, user_get_repositories, | |
22 | user_get_setting, user_get_value, user_set_setting, OperationHandlers, repository_info, | |
20 | repository_get_setting, repository_get_value, repository_info, repository_set_setting, | |
21 | user_get_repositories, user_get_setting, user_get_value, user_set_setting, OperationHandlers, | |
23 | 22 | }; |
24 | 23 | |
25 | 24 | #[derive(Clone, Debug)] |
@@ -30,8 +29,8 @@ impl ObjectBackend for Foobackend { | ||
30 | 29 | async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>( |
31 | 30 | &self, |
32 | 31 | _object: O, |
33 | operation: &str, | |
34 | payload: D, | |
32 | _operation: &str, | |
33 | _payload: D, | |
35 | 34 | ) -> Result<D::Success, OperationError<D::Failure>> { |
36 | 35 | // We don't handle operations with this backend |
37 | 36 | Err(OperationError::Unhandled) |
@@ -102,10 +101,8 @@ impl ObjectBackend for DatabaseBackend { | ||
102 | 101 | ) |
103 | 102 | .await |
104 | 103 | { |
105 | Ok(result) => Ok( | |
106 | serde_json::from_slice(&serde_json::to_vec(&result).unwrap()) | |
107 | .map_err(|e| OperationError::Internal(e.to_string()))?, | |
108 | ), | |
104 | Ok(result) => Ok(serde_json::from_slice(&result) | |
105 | .map_err(|e| OperationError::Internal(e.to_string()))?), | |
109 | 106 | Err(err) => match err { |
110 | 107 | OperationError::Internal(internal) => Err(OperationError::Internal(internal)), |
111 | 108 | OperationError::Unhandled => Err(OperationError::Unhandled), |
@@ -133,10 +130,8 @@ impl ObjectBackend for DatabaseBackend { | ||
133 | 130 | ) |
134 | 131 | .await |
135 | 132 | { |
136 | Ok(result) => Ok( | |
137 | serde_json::from_slice(&serde_json::to_vec(&result).unwrap()) | |
138 | .map_err(|e| OperationError::Internal(e.to_string()))?, | |
139 | ), | |
133 | Ok(result) => Ok(serde_json::from_slice(&result) | |
134 | .map_err(|e| OperationError::Internal(e.to_string()))?), | |
140 | 135 | Err(err) => match err { |
141 | 136 | OperationError::Internal(internal) => Err(OperationError::Internal(internal)), |
142 | 137 | OperationError::Unhandled => Err(OperationError::Unhandled), |
@@ -167,10 +162,8 @@ impl ObjectBackend for DatabaseBackend { | ||
167 | 162 | }); |
168 | 163 | |
169 | 164 | match result { |
170 | Ok(result) => Ok( | |
171 | serde_json::from_slice(&serde_json::to_vec(&result).unwrap()) | |
172 | .map_err(|e| OperationError::Internal(e.to_string()))?, | |
173 | ), | |
165 | Ok(result) => Ok(serde_json::from_slice(&result) | |
166 | .map_err(|e| OperationError::Internal(e.to_string()))?), | |
174 | 167 | Err(err) => match err { |
175 | 168 | OperationError::Internal(internal) => { |
176 | 169 | Err(OperationError::Internal(internal)) |
@@ -265,7 +258,7 @@ mod test { | ||
265 | 258 | RepositoryTreeEntry, |
266 | 259 | }; |
267 | 260 | use giterated_models::settings::AnySetting; |
268 | use giterated_models::user::{DisplayName, User, UserDisplayName}; | |
261 | use giterated_models::user::{DisplayName, User}; | |
269 | 262 | use giterated_models::value::{AnyValue, GiteratedObjectValue}; |
270 | 263 | use serde_json::Value; |
271 | 264 | use tokio::sync::Mutex; |
@@ -302,6 +295,13 @@ mod test { | ||
302 | 295 | async fn exists(&mut self, user: &User) -> Result<bool, Error> { |
303 | 296 | Ok(user == &User::from_str("test_user:test.giterated.dev").unwrap()) |
304 | 297 | } |
298 | async fn repositories_for_user( | |
299 | &mut self, | |
300 | requester: Option<&User>, | |
301 | user: &User, | |
302 | ) -> Result<Vec<RepositorySummary>, Error> { | |
303 | todo!() | |
304 | } | |
305 | 305 | } |
306 | 306 | |
307 | 307 | #[async_trait::async_trait] |
@@ -341,14 +341,6 @@ mod test { | ||
341 | 341 | ) -> Result<Vec<RepositoryTreeEntry>, Error> { |
342 | 342 | todo!() |
343 | 343 | } |
344 | async fn repositories_for_user( | |
345 | &mut self, | |
346 | _requester: Option<&User>, | |
347 | _user: &User, | |
348 | ) -> Result<Vec<RepositorySummary>, Error> { | |
349 | todo!() | |
350 | } | |
351 | ||
352 | 344 | async fn get_value( |
353 | 345 | &mut self, |
354 | 346 | _repository: &Repository, |
@@ -419,7 +411,7 @@ mod test { | ||
419 | 411 | .await |
420 | 412 | .expect("object should have been returned"); |
421 | 413 | |
422 | user.get_setting::<UserDisplayName>() | |
414 | user.get_setting::<DisplayName>() | |
423 | 415 | .await |
424 | 416 | .expect("object value should have been returned"); |
425 | 417 | } |
@@ -433,7 +425,7 @@ mod test { | ||
433 | 425 | .await |
434 | 426 | .expect("object should have been returned"); |
435 | 427 | |
436 | user.set_setting::<UserDisplayName>(UserDisplayName(String::from("test"))) | |
428 | user.set_setting::<DisplayName>(DisplayName(String::from("test"))) | |
437 | 429 | .await |
438 | 430 | .expect("object value should have been returned"); |
439 | 431 | } |
giterated-models/src/error.rs
@@ -17,7 +17,7 @@ pub enum UserError {} | ||
17 | 17 | #[derive(Debug, thiserror::Error, Serialize, Deserialize)] |
18 | 18 | pub enum GetValueError { |
19 | 19 | #[error("invalid object")] |
20 | InvalidObject | |
20 | InvalidObject, | |
21 | 21 | } |
22 | 22 | |
23 | 23 | #[derive(Serialize, Deserialize, Debug, thiserror::Error)] |
giterated-models/src/object.rs
@@ -56,11 +56,14 @@ impl<'b, O: GiteratedObject + Clone + Debug, B: ObjectBackend> Object<'b, O, B> | ||
56 | 56 | pub async fn get<V: GiteratedObjectValue<Object = O> + Send + Debug>( |
57 | 57 | &mut self, |
58 | 58 | ) -> Result<V, OperationError<GetValueError>> { |
59 | self.request(GetValue { | |
60 | value_name: V::value_name().to_string(), | |
61 | _marker: PhantomData, | |
62 | }) | |
63 | .await | |
59 | let result = self | |
60 | .request(GetValue { | |
61 | value_name: V::value_name().to_string(), | |
62 | _marker: PhantomData, | |
63 | }) | |
64 | .await; | |
65 | ||
66 | result | |
64 | 67 | } |
65 | 68 | |
66 | 69 | pub async fn get_setting<S: Setting + Send + Clone + Debug>( |
giterated-models/src/operation.rs
@@ -20,7 +20,7 @@ pub trait GiteratedOperation<O: GiteratedObject>: Send + Serialize + Deserialize | ||
20 | 20 | pub struct AnyOperation(pub Value); |
21 | 21 | |
22 | 22 | impl<O: GiteratedObject> GiteratedOperation<O> for AnyOperation { |
23 | type Success = Vec<u8>; | |
23 | type Success = Value; | |
24 | 24 | |
25 | type Failure = Vec<u8>; | |
25 | type Failure = Value; | |
26 | 26 | } |
giterated-models/src/repository/operations.rs
@@ -7,7 +7,7 @@ use crate::{ | ||
7 | 7 | operation::GiteratedOperation, |
8 | 8 | }; |
9 | 9 | |
10 | use super::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry, RepositoryView, Commit}; | |
10 | use super::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry, RepositoryView}; | |
11 | 11 | |
12 | 12 | /// A request to get a repository's information. |
13 | 13 | /// |
@@ -97,7 +97,12 @@ impl GiteratedOperation<Repository> for RepositoryFileInspectRequest { | ||
97 | 97 | } |
98 | 98 | |
99 | 99 | impl<B: ObjectBackend + std::fmt::Debug> Object<'_, Repository, B> { |
100 | pub async fn info(&mut self, extra_metadata: bool, rev: Option<String>, path: Option<String>) -> Result<RepositoryView, OperationError<RepositoryError>> { | |
100 | pub async fn info( | |
101 | &mut self, | |
102 | extra_metadata: bool, | |
103 | rev: Option<String>, | |
104 | path: Option<String>, | |
105 | ) -> Result<RepositoryView, OperationError<RepositoryError>> { | |
101 | 106 | self.request::<RepositoryInfoRequest>(RepositoryInfoRequest { |
102 | 107 | extra_metadata, |
103 | 108 | rev, |
giterated-models/src/repository/settings.rs
@@ -1,29 +1,9 @@ | ||
1 | use serde::{Deserialize, Serialize}; | |
2 | ||
3 | 1 | use crate::settings::Setting; |
4 | 2 | |
5 | 3 | use super::DefaultBranch; |
6 | 4 | |
7 | #[derive(Debug, Serialize, Deserialize)] | |
8 | pub struct RepositoryDescription(pub String); | |
9 | ||
10 | impl Setting for RepositoryDescription { | |
11 | fn name() -> &'static str { | |
12 | "Repository Description" | |
13 | } | |
14 | } | |
15 | ||
16 | #[derive(Debug, Serialize, Deserialize)] | |
17 | pub struct RepositoryVisibilitySetting(pub String); | |
18 | ||
19 | impl Setting for RepositoryVisibilitySetting { | |
20 | fn name() -> &'static str { | |
21 | "Repository Visibility" | |
22 | } | |
23 | } | |
24 | ||
25 | 5 | impl Setting for DefaultBranch { |
26 | 6 | fn name() -> &'static str { |
27 | "Default Branch" | |
7 | "default_branch" | |
28 | 8 | } |
29 | } | |
29 | \ No newline at end of file | |
9 | } |
giterated-models/src/repository/values.rs
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; | ||
4 | 4 | |
5 | 5 | use crate::{settings::Setting, value::GiteratedObjectValue}; |
6 | 6 | |
7 | use super::{Repository, RepositoryVisibility, Commit}; | |
7 | use super::{Commit, Repository, RepositoryVisibility}; | |
8 | 8 | |
9 | 9 | // pub struct RepositorySetting<V: GiteratedObjectValue>(pub V); |
10 | 10 | |
@@ -42,6 +42,8 @@ impl Setting for Description { | ||
42 | 42 | } |
43 | 43 | |
44 | 44 | #[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)] |
45 | #[repr(transparent)] | |
46 | #[serde(transparent)] | |
45 | 47 | pub struct Visibility(pub RepositoryVisibility); |
46 | 48 | |
47 | 49 | impl GiteratedObjectValue for Visibility { |
@@ -52,9 +54,23 @@ impl GiteratedObjectValue for Visibility { | ||
52 | 54 | } |
53 | 55 | } |
54 | 56 | |
57 | impl Setting for Visibility { | |
58 | fn name() -> &'static str { | |
59 | "visibility" | |
60 | } | |
61 | } | |
62 | ||
55 | 63 | #[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)] |
64 | #[serde(transparent)] | |
65 | #[repr(transparent)] | |
56 | 66 | pub struct DefaultBranch(pub String); |
57 | 67 | |
68 | impl Display for DefaultBranch { | |
69 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
70 | f.write_str(&self.0) | |
71 | } | |
72 | } | |
73 | ||
58 | 74 | impl GiteratedObjectValue for DefaultBranch { |
59 | 75 | type Object = Repository; |
60 | 76 | |
@@ -64,7 +80,7 @@ impl GiteratedObjectValue for DefaultBranch { | ||
64 | 80 | } |
65 | 81 | |
66 | 82 | #[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)] |
67 | pub struct LatestCommit(pub Commit); | |
83 | pub struct LatestCommit(pub Option<Commit>); | |
68 | 84 | |
69 | 85 | impl GiteratedObjectValue for LatestCommit { |
70 | 86 | type Object = Repository; |
giterated-models/src/user/settings.rs
@@ -1,30 +1,15 @@ | ||
1 | use serde::{Deserialize, Serialize}; | |
2 | ||
3 | 1 | use crate::settings::Setting; |
4 | 2 | |
5 | #[derive(Debug, Serialize, Deserialize, Clone)] | |
6 | pub struct UserBio(pub String); | |
3 | use super::{Bio, DisplayName}; | |
7 | 4 | |
8 | impl Setting for UserBio { | |
5 | impl Setting for Bio { | |
9 | 6 | fn name() -> &'static str { |
10 | "Bio" | |
7 | "bio" | |
11 | 8 | } |
12 | 9 | } |
13 | 10 | |
14 | #[derive(Debug, Serialize, Deserialize, Clone)] | |
15 | pub struct UserDisplayName(pub String); | |
16 | ||
17 | impl Setting for UserDisplayName { | |
18 | fn name() -> &'static str { | |
19 | "Display Name" | |
20 | } | |
21 | } | |
22 | ||
23 | #[derive(Debug, Serialize, Deserialize, Clone)] | |
24 | pub struct UserDisplayImage(pub String); | |
25 | ||
26 | impl Setting for UserDisplayImage { | |
11 | impl Setting for DisplayName { | |
27 | 12 | fn name() -> &'static str { |
28 | "Profile Image" | |
13 | "display_name" | |
29 | 14 | } |
30 | 15 | } |