JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Please fix

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨2c88faf

Showing ⁨⁨4⁩ changed files⁩ with ⁨⁨151⁩ insertions⁩ and ⁨⁨40⁩ deletions⁩

giterated-daemon/src/backend/git.rs

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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);