Please fix
parent: tbd commit: 2c88faf
Showing 4 changed files with 151 insertions and 40 deletions
giterated-daemon/src/backend/git.rs
@@ -497,49 +497,126 @@ impl RepositoryBackend for GitBackend { | ||
497 | 497 | |
498 | 498 | async fn repository_file_inspect( |
499 | 499 | &mut self, |
500 | _requester: Option<&User>, | |
501 | _request: &RepositoryFileInspectRequest, | |
500 | requester: Option<&User>, | |
501 | repository: &Repository, | |
502 | request: &RepositoryFileInspectRequest, | |
502 | 503 | ) -> Result<Vec<RepositoryTreeEntry>, Error> { |
503 | todo!() | |
504 | } | |
504 | let repository = match self | |
505 | .find_by_owner_user_name( | |
506 | // &request.owner.instance.url, | |
507 | &repository.owner, | |
508 | &repository.name, | |
509 | ) | |
510 | .await | |
511 | { | |
512 | Ok(repository) => repository, | |
513 | Err(err) => return Err(Box::new(err).into()), | |
514 | }; | |
505 | 515 | |
506 | async fn repositories_for_user( | |
507 | &mut self, | |
508 | requester: Option<&User>, | |
509 | user: &User, | |
510 | ) -> Result<Vec<RepositorySummary>, Error> { | |
511 | let mut repositories = sqlx::query_as!( | |
512 | GitRepository, | |
513 | r#"SELECT visibility as "visibility: _", owner_user, name, description, default_branch FROM repositories WHERE owner_user = $1"#, | |
514 | user.to_string() | |
515 | ) | |
516 | .fetch_many(&self.pg_pool); | |
516 | let git = match repository.open_git2_repository(&self.repository_folder) { | |
517 | Ok(git) => git, | |
518 | Err(err) => return Err(Box::new(err).into()), | |
519 | }; | |
517 | 520 | |
518 | let mut result = vec![]; | |
521 | let rev_name = match &request.rev { | |
522 | None => { | |
523 | if let Ok(head) = git.head() { | |
524 | head.name().unwrap().to_string() | |
525 | } else { | |
526 | // Nothing in database, render empty tree. | |
527 | return Ok(vec![]); | |
528 | } | |
529 | } | |
530 | Some(rev_name) => { | |
531 | // Find the reference, otherwise return GitBackendError | |
532 | match git | |
533 | .find_reference(format!("refs/heads/{}", rev_name).as_str()) | |
534 | .map_err(|_| GitBackendError::RefNotFound(rev_name.to_string())) | |
535 | { | |
536 | Ok(reference) => reference.name().unwrap().to_string(), | |
537 | Err(err) => return Err(Box::new(err).into()), | |
538 | } | |
539 | } | |
540 | }; | |
519 | 541 | |
520 | while let Some(Ok(Either::Right(repository))) = repositories.next().await { | |
521 | // Check if the requesting user is allowed to see the repository | |
522 | if !(matches!( | |
523 | repository.visibility, | |
524 | RepositoryVisibility::Unlisted | RepositoryVisibility::Private | |
525 | ) && Some(&repository.owner_user.clone()) != requester) | |
542 | // Get the git object as a commit | |
543 | let rev = match git | |
544 | .revparse_single(rev_name.as_str()) | |
545 | .map_err(|_| GitBackendError::RefNotFound(rev_name.to_string())) | |
546 | { | |
547 | Ok(rev) => rev, | |
548 | Err(err) => return Err(Box::new(err).into()), | |
549 | }; | |
550 | let commit = rev.as_commit().unwrap(); | |
551 | ||
552 | // this is stupid | |
553 | let mut current_path = rev_name.replace("refs/heads/", ""); | |
554 | ||
555 | // Get the commit tree | |
556 | let git_tree = if let Some(path) = &request.path { | |
557 | // Add it to our full path string | |
558 | current_path.push_str(format!("/{}", path).as_str()); | |
559 | // Get the specified path, return an error if it wasn't found. | |
560 | let entry = match commit | |
561 | .tree() | |
562 | .unwrap() | |
563 | .get_path(&PathBuf::from(path)) | |
564 | .map_err(|_| GitBackendError::PathNotFound(path.to_string())) | |
526 | 565 | { |
527 | result.push(RepositorySummary { | |
528 | repository: Repository { | |
529 | owner: repository.owner_user.clone(), | |
530 | name: repository.name, | |
531 | instance: self.instance.clone(), | |
532 | }, | |
533 | owner: repository.owner_user.clone(), | |
534 | visibility: repository.visibility, | |
535 | description: repository.description, | |
536 | // TODO | |
537 | last_commit: None, | |
538 | }); | |
539 | } | |
540 | } | |
566 | Ok(entry) => entry, | |
567 | Err(err) => return Err(Box::new(err).into()), | |
568 | }; | |
569 | // Turn the entry into a git tree | |
570 | entry.to_object(&git).unwrap().as_tree().unwrap().clone() | |
571 | } else { | |
572 | commit.tree().unwrap() | |
573 | }; | |
541 | 574 | |
542 | Ok(result) | |
575 | // Iterate over the git tree and collect it into our own tree types | |
576 | let mut tree = git_tree | |
577 | .iter() | |
578 | .map(|entry| { | |
579 | let object_type = match entry.kind().unwrap() { | |
580 | ObjectType::Tree => RepositoryObjectType::Tree, | |
581 | ObjectType::Blob => RepositoryObjectType::Blob, | |
582 | _ => unreachable!(), | |
583 | }; | |
584 | let mut tree_entry = | |
585 | RepositoryTreeEntry::new(entry.name().unwrap(), object_type, entry.filemode()); | |
586 | ||
587 | if request.extra_metadata { | |
588 | // Get the file size if It's a blob | |
589 | let object = entry.to_object(&git).unwrap(); | |
590 | if let Some(blob) = object.as_blob() { | |
591 | tree_entry.size = Some(blob.size()); | |
592 | } | |
593 | ||
594 | // Could possibly be done better | |
595 | let path = if let Some(path) = current_path.split_once('/') { | |
596 | format!("{}/{}", path.1, entry.name().unwrap()) | |
597 | } else { | |
598 | entry.name().unwrap().to_string() | |
599 | }; | |
600 | ||
601 | // Get the last commit made to the entry | |
602 | if let Ok(last_commit) = | |
603 | GitBackend::get_last_commit_of_file(&path, &git, commit) | |
604 | { | |
605 | tree_entry.last_commit = Some(last_commit); | |
606 | } | |
607 | } | |
608 | ||
609 | tree_entry | |
610 | }) | |
611 | .collect::<Vec<RepositoryTreeEntry>>(); | |
612 | ||
613 | // Sort the tree alphabetically and with tree first | |
614 | tree.sort_unstable_by_key(|entry| entry.name.to_lowercase()); | |
615 | tree.sort_unstable_by_key(|entry| { | |
616 | std::cmp::Reverse(format!("{:?}", entry.object_type).to_lowercase()) | |
617 | }); | |
618 | ||
619 | todo!() | |
543 | 620 | } |
544 | 621 | } |
545 | 622 |
giterated-daemon/src/backend/mod.rs
@@ -34,6 +34,7 @@ pub trait RepositoryBackend { | ||
34 | 34 | async fn repository_file_inspect( |
35 | 35 | &mut self, |
36 | 36 | requester: Option<&User>, |
37 | repository: &Repository, | |
37 | 38 | request: &RepositoryFileInspectRequest, |
38 | 39 | ) -> Result<Vec<RepositoryTreeEntry>, Error>; |
39 | 40 | async fn repositories_for_user( |
giterated-daemon/src/database_backend/handler.rs
@@ -5,10 +5,10 @@ use giterated_models::{ | ||
5 | 5 | error::{GetValueError, OperationError, UserError}, |
6 | 6 | object::{AnyObject, GiteratedObject}, |
7 | 7 | operation::{AnyOperation, GiteratedOperation}, |
8 | repository::{Repository, RepositorySummary}, | |
8 | repository::{Repository, RepositorySummary, RepositoryInfoRequest, RepositoryView, Description, Visibility, DefaultBranch, LatestCommit, RepositoryFileInspectRequest}, | |
9 | 9 | settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError}, |
10 | 10 | user::{User, UserRepositoriesRequest}, |
11 | value::{AnyValue, GetValue}, | |
11 | value::{AnyValue, GetValue}, object_backend::ObjectBackend, | |
12 | 12 | }; |
13 | 13 | |
14 | 14 | use super::DatabaseBackend; |
@@ -196,6 +196,38 @@ pub fn user_set_setting( | ||
196 | 196 | .boxed() |
197 | 197 | } |
198 | 198 | |
199 | pub fn repository_info( | |
200 | object: &Repository, | |
201 | operation: RepositoryInfoRequest, | |
202 | state: DatabaseBackend | |
203 | ) -> BoxFuture<'static, Result<RepositoryView, OperationError<GetValueError>>> { | |
204 | let object = object.clone(); | |
205 | ||
206 | async move { | |
207 | let object = state.get_object::<Repository>(&object.to_string()).await.unwrap(); | |
208 | ||
209 | let mut repository_backend = state.repository_backend.lock().await; | |
210 | let tree = repository_backend.repository_file_inspect(None, object.object(), &RepositoryFileInspectRequest { | |
211 | path: operation.path.ok_or_else(|| OperationError::Operation(GetValueError::InvalidObject))?, | |
212 | rev: operation.rev, | |
213 | }).await?; | |
214 | ||
215 | let info = RepositoryView { | |
216 | name: object.object().name, | |
217 | owner: object.object().owner, | |
218 | description: object.get::<Description>().await.ok(), | |
219 | visibility: object.get::<Visibility>().await.map_err(|e| OperationError::Internal(e.to_string()))?, | |
220 | default_branch: object.get::<DefaultBranch>().await.map_err(|e| OperationError::Internal(e.to_string()))?, | |
221 | latest_commit: object.get::<LatestCommit>().await.ok(), | |
222 | tree_rev: operation.rev, | |
223 | tree, | |
224 | }; | |
225 | ||
226 | Ok(info) | |
227 | } | |
228 | .boxed() | |
229 | } | |
230 | ||
199 | 231 | pub fn repository_get_value( |
200 | 232 | object: &Repository, |
201 | 233 | operation: GetValue<AnyValue<Repository>>, |
giterated-daemon/src/database_backend/mod.rs
@@ -19,7 +19,7 @@ use crate::backend::{RepositoryBackend, UserBackend}; | ||
19 | 19 | |
20 | 20 | use self::handler::{ |
21 | 21 | repository_get_setting, repository_get_value, repository_set_setting, user_get_repositories, |
22 | user_get_setting, user_get_value, user_set_setting, OperationHandlers, | |
22 | user_get_setting, user_get_value, user_set_setting, OperationHandlers, repository_info, | |
23 | 23 | }; |
24 | 24 | |
25 | 25 | #[derive(Clone, Debug)] |
@@ -119,6 +119,7 @@ impl ObjectBackend for DatabaseBackend { | ||
119 | 119 | let mut handler = OperationHandlers::default(); |
120 | 120 | |
121 | 121 | handler |
122 | .insert(repository_info) | |
122 | 123 | .insert(repository_get_value) |
123 | 124 | .insert(repository_get_setting) |
124 | 125 | .insert(repository_set_setting); |