Make old operations use new types
parent: tbd commit: b22dd12
1 | use Error; |
2 | use async_trait; |
3 | |
4 | use BranchType; |
5 | use ; |
6 | |
7 | use ; |
8 | use Object; |
9 | use |
10 | AccessList, Commit, DefaultBranch, Description, Repository, RepositoryBranch, |
11 | RepositoryBranchRequest, RepositoryBranchesRequest, RepositoryCommitBeforeRequest, |
12 | RepositoryCommitFromIdRequest, RepositoryDiff, RepositoryDiffPatchRequest, |
13 | RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest, |
14 | RepositoryFileFromPathRequest, RepositoryFileInspectRequest, RepositoryIssueTagsRequest, |
15 | RepositoryIssuesCountRequest, RepositoryIssuesRequest, RepositoryLastCommitOfFileRequest, |
16 | RepositoryStatistics, RepositoryStatisticsRequest, RepositoryTag, RepositoryTagRequest, |
17 | RepositoryTagsRequest, RepositoryTreeEntry, RepositoryVisibility, Visibility, |
18 | ; |
19 | |
20 | use User; |
21 | |
22 | use ; |
23 | |
24 | use PgPool; |
25 | use Deref; |
26 | use ; |
27 | use Error; |
28 | use OnceCell; |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | use ; |
37 | |
38 | //region database structures |
39 | |
40 | /// Repository in the database |
41 | |
42 | |
43 | #[sqlx(try_from = "String")] |
44 | pub owner_user: User, |
45 | pub name: String, |
46 | pub description: , |
47 | pub visibility: RepositoryVisibility, |
48 | pub default_branch: String, |
49 | |
50 | |
51 | |
52 | // Separate function because "Private" will be expanded later |
53 | /// Checks if the user is allowed to view this repository |
54 | pub async |
55 | &self, |
56 | our_instance: &Instance, |
57 | user: & , |
58 | stack: &GiteratedStack, |
59 | |
60 | if matches! |
61 | return true; |
62 | |
63 | |
64 | // User must exist for any further checks to pass |
65 | let user = match user |
66 | Some => user, |
67 | None => return false, |
68 | ; |
69 | |
70 | if *user.deref == self.owner_user |
71 | // owner can always view |
72 | return true; |
73 | |
74 | |
75 | if matches! |
76 | // Check if the user can view\ |
77 | let access_list = stack |
78 | . |
79 | owner: self.owner_user.clone, |
80 | name: self.name.clone, |
81 | instance: our_instance.clone, |
82 | |
83 | .await |
84 | .unwrap; |
85 | |
86 | access_list |
87 | .0 |
88 | .iter |
89 | .any |
90 | else |
91 | false |
92 | |
93 | |
94 | |
95 | // This is in it's own function because I assume I'll have to add logic to this later |
96 | |
97 | &self, |
98 | repository_directory: &str, |
99 | |
100 | match open |
101 | "{}/{}/{}/{}" |
102 | repository_directory, self.owner_user.instance, self.owner_user.username, self.name |
103 | ) |
104 | Ok => Ok, |
105 | Err => |
106 | let err = FailedOpeningFromDisk; |
107 | error!; |
108 | |
109 | Err |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | //endregion |
116 | |
117 | |
118 | |
119 | |
120 | FailedCreatingRepository, |
121 | |
122 | FailedInsertingIntoDatabase, |
123 | |
124 | RepositoryNotFound , |
125 | |
126 | RepositoryAlreadyExists , |
127 | |
128 | CouldNotDeleteFromDisk, |
129 | |
130 | FailedDeletingFromDatabase, |
131 | |
132 | FailedOpeningFromDisk, |
133 | |
134 | RefNotFound, |
135 | |
136 | HeadNotFound, |
137 | |
138 | DefaultNotFound, |
139 | |
140 | TagNotFound, |
141 | |
142 | PathNotFound, |
143 | |
144 | BranchNotFound, |
145 | |
146 | LastCommitNotFound, |
147 | |
148 | InvalidObjectId, |
149 | |
150 | BlobNotFound, |
151 | |
152 | TreeNotFound, |
153 | |
154 | CommitNotFound, |
155 | |
156 | CommitParentNotFound, |
157 | |
158 | FailedDiffing, |
159 | |
160 | |
161 | /// Parses and trims a git message (commit, tag) into a summary and body. |
162 | |
163 | // Iterate over the lines |
164 | let mut lines = message |
165 | .lines |
166 | .filter_map |
167 | if line.is_empty |
168 | None |
169 | else |
170 | // Trim the whitespace for every line |
171 | let mut whitespace_removed = String with_capacity; |
172 | |
173 | line.split_whitespace .for_each |
174 | if !whitespace_removed.is_empty |
175 | whitespace_removed.push; |
176 | |
177 | |
178 | whitespace_removed.push_str; |
179 | ; |
180 | |
181 | Some |
182 | |
183 | |
184 | .; |
185 | |
186 | let summary = Some; |
187 | let body = if lines.is_empty |
188 | None |
189 | else |
190 | Some |
191 | ; |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | pg_pool: PgPool, |
198 | repository_folder: String, |
199 | instance: Instance, |
200 | stack: , |
201 | |
202 | |
203 | |
204 | |
205 | pg_pool: &PgPool, |
206 | repository_folder: &str, |
207 | instance: impl , |
208 | stack: , |
209 | |
210 | let instance = instance.to_owned; |
211 | |
212 | Self |
213 | pg_pool: pg_pool.clone, |
214 | // We make sure there's no end slash |
215 | repository_folder: repository_folder.trim_end_matches .to_string, |
216 | instance, |
217 | stack, |
218 | |
219 | |
220 | |
221 | pub async |
222 | &self, |
223 | user: &User, |
224 | repository_name: &str, |
225 | |
226 | // TODO: Patch for use with new GetValue system |
227 | if let Ok = query_as! |
228 | r#"SELECT owner_user, name, description, visibility as "visibility: _", default_branch FROM repositories WHERE owner_user = $1 AND name = $2"#, |
229 | user.to_string, repository_name |
230 | .fetch_one |
231 | .await |
232 | Ok |
233 | else |
234 | Err |
235 | owner_user: user.to_string, |
236 | name: repository_name.to_string, |
237 | |
238 | |
239 | |
240 | |
241 | pub async |
242 | &self, |
243 | user: &User, |
244 | repository_name: &str, |
245 | |
246 | if let Err = remove_dir_all |
247 | "{}/{}/{}/{}" |
248 | self.repository_folder, user.instance, user.username, repository_name |
249 | ) |
250 | let err = CouldNotDeleteFromDisk; |
251 | error! |
252 | "Couldn't delete repository from disk, this is bad! {:?}", |
253 | err |
254 | ; |
255 | |
256 | return Err; |
257 | |
258 | |
259 | // Delete the repository from the database |
260 | self.delete_from_database .await |
261 | |
262 | |
263 | /// Deletes the repository from the database |
264 | pub async |
265 | &self, |
266 | user: &User, |
267 | repository_name: &str, |
268 | |
269 | match query! |
270 | "DELETE FROM repositories WHERE owner_user = $1 AND name = $2", |
271 | user.to_string, |
272 | repository_name |
273 | |
274 | .execute |
275 | .await |
276 | |
277 | Ok => Ok, |
278 | Err => Err, |
279 | |
280 | |
281 | |
282 | pub async |
283 | &self, |
284 | owner: &User, |
285 | name: &str, |
286 | requester: & , |
287 | |
288 | let repository = match self |
289 | .find_by_owner_user_name |
290 | // &request.owner.instance.url, |
291 | owner, name, |
292 | |
293 | .await |
294 | |
295 | Ok => repository, |
296 | Err => return Err, |
297 | ; |
298 | |
299 | if let Some = requester |
300 | if !repository |
301 | .can_user_view_repository |
302 | &self.instance, |
303 | &Some, |
304 | self.stack.get .unwrap, |
305 | |
306 | .await |
307 | |
308 | return Err |
309 | owner_user: repository.owner_user.to_string, |
310 | name: repository.name.clone, |
311 | ; |
312 | |
313 | else if matches! |
314 | // Unauthenticated users can never view private repositories |
315 | |
316 | return Err |
317 | owner_user: repository.owner_user.to_string, |
318 | name: repository.name.clone, |
319 | ; |
320 | |
321 | |
322 | match repository.open_git2_repository |
323 | Ok => Ok, |
324 | Err => Err, |
325 | |
326 | |
327 | |
328 | /// Attempts to get the oid in this order: |
329 | /// 1. Full refname (refname_to_id) |
330 | /// 2. Short branch name (find_branch) |
331 | /// 3. Other (revparse_single) |
332 | |
333 | git: & Repository, |
334 | rev: , |
335 | default_branch: &DefaultBranch, |
336 | |
337 | // If the rev is None try and get the default branch instead |
338 | let rev = rev.unwrap_or; |
339 | |
340 | // TODO: This is far from ideal or speedy and would love for a better way to check this in the same order, but I can't find proper methods to do any of this. |
341 | trace!; |
342 | |
343 | // Try getting it as a refname (refs/heads/name) |
344 | if let Ok = git.refname_to_id |
345 | Ok |
346 | // Try finding it as a short branch name |
347 | else if let Ok = git.find_branch |
348 | // SHOULD be safe to unwrap |
349 | Ok |
350 | // As last resort, try revparsing (will catch short oid and tags) |
351 | else if let Ok = git.revparse_single |
352 | Ok |
353 | Some => |
354 | if let Ok = object.peel_to_commit |
355 | commit.id |
356 | else |
357 | object.id |
358 | |
359 | |
360 | _ => object.id, |
361 | |
362 | else |
363 | Err |
364 | |
365 | |
366 | |
367 | |
368 | |
369 | |
370 | async |
371 | &mut self, |
372 | _user: &AuthenticatedUser, |
373 | request: &RepositoryCreateRequest, |
374 | |
375 | // Check if repository already exists in the database |
376 | if let Ok = self |
377 | .find_by_owner_user_name |
378 | .await |
379 | |
380 | let err = RepositoryAlreadyExists |
381 | owner_user: repository.owner_user.to_string, |
382 | name: repository.name, |
383 | ; |
384 | error!; |
385 | |
386 | return Err; |
387 | |
388 | |
389 | // Insert the repository into the database |
390 | let _ = match query_as! |
391 | r#"INSERT INTO repositories VALUES ($1, $2, $3, $4, $5) RETURNING owner_user, name, description, visibility as "visibility: _", default_branch"#, |
392 | request.owner.to_string, request.name, request.description, request.visibility as _, "master" |
393 | .fetch_one |
394 | .await |
395 | Ok => repository, |
396 | Err => |
397 | let err = FailedInsertingIntoDatabase; |
398 | error!; |
399 | |
400 | return Err; |
401 | |
402 | ; |
403 | |
404 | // Create bare (server side) repository on disk |
405 | match init_bare |
406 | "{}/{}/{}/{}" |
407 | self.repository_folder, request.owner.instance, request.owner.username, request.name |
408 | ) |
409 | Ok => |
410 | debug! |
411 | "Created new repository with the name {}/{}/{}", |
412 | request.owner.instance, request.owner.username, request.name |
413 | ; |
414 | |
415 | let stack = self.stack.get .unwrap; |
416 | |
417 | let repository = Repository |
418 | owner: request.owner.clone, |
419 | name: request.name.clone, |
420 | instance: request.instance.as_ref .unwrap_or .clone, |
421 | ; |
422 | |
423 | stack |
424 | .write_setting |
425 | &repository, |
426 | Description, |
427 | |
428 | .await |
429 | .unwrap; |
430 | |
431 | stack |
432 | .write_setting |
433 | .await |
434 | .unwrap; |
435 | |
436 | stack |
437 | .write_setting |
438 | .await |
439 | .unwrap; |
440 | |
441 | Ok |
442 | |
443 | Err => |
444 | let err = FailedCreatingRepository; |
445 | error!; |
446 | |
447 | // Delete repository from database |
448 | self.delete_from_database |
449 | .await?; |
450 | |
451 | // ??? |
452 | Err |
453 | |
454 | |
455 | |
456 | |
457 | /// If the OID can't be found because there's no repository head, this will return an empty `Vec`. |
458 | async |
459 | &mut self, |
460 | requester: & , |
461 | repository_object: &mut , |
462 | OperationState | : ,
463 | request: &RepositoryFileInspectRequest, |
464 | |
465 | self.handle_repository_file_inspect |
466 | requester, |
467 | repository_object, |
468 | OperationState, |
469 | request, |
470 | |
471 | .await |
472 | |
473 | |
474 | async |
475 | &mut self, |
476 | requester: & , |
477 | repository_object: &mut , |
478 | OperationState | : ,
479 | request: &RepositoryFileFromIdRequest, |
480 | |
481 | self.handle_repository_file_from_id |
482 | requester, |
483 | repository_object, |
484 | OperationState, |
485 | request, |
486 | |
487 | .await |
488 | |
489 | |
490 | async |
491 | &mut self, |
492 | requester: & , |
493 | repository_object: &mut , |
494 | OperationState | : ,
495 | request: &RepositoryFileFromPathRequest, |
496 | |
497 | self.handle_repository_file_from_path |
498 | requester, |
499 | repository_object, |
500 | OperationState, |
501 | request, |
502 | |
503 | .await |
504 | |
505 | |
506 | async |
507 | &mut self, |
508 | requester: & , |
509 | repository_object: &mut , |
510 | OperationState | : ,
511 | request: &RepositoryCommitFromIdRequest, |
512 | |
513 | self.handle_repository_commit_from_id |
514 | requester, |
515 | repository_object, |
516 | OperationState, |
517 | request, |
518 | |
519 | .await |
520 | |
521 | |
522 | async |
523 | &mut self, |
524 | requester: & , |
525 | repository_object: &mut , |
526 | OperationState | : ,
527 | request: &RepositoryLastCommitOfFileRequest, |
528 | |
529 | self.handle_repository_last_commit_of_file |
530 | requester, |
531 | repository_object, |
532 | OperationState, |
533 | request, |
534 | |
535 | .await |
536 | |
537 | |
538 | async |
539 | &mut self, |
540 | requester: & , |
541 | repository_object: &mut , |
542 | OperationState | : ,
543 | request: &RepositoryDiffRequest, |
544 | |
545 | self.handle_repository_diff |
546 | requester, |
547 | repository_object, |
548 | OperationState, |
549 | request, |
550 | |
551 | .await |
552 | |
553 | |
554 | async |
555 | &mut self, |
556 | requester: & , |
557 | repository_object: &mut , |
558 | OperationState | : ,
559 | request: &RepositoryDiffPatchRequest, |
560 | |
561 | self.handle_repository_diff_patch |
562 | requester, |
563 | repository_object, |
564 | OperationState, |
565 | request, |
566 | |
567 | .await |
568 | |
569 | |
570 | async |
571 | &mut self, |
572 | requester: & , |
573 | repository_object: &mut , |
574 | OperationState | : ,
575 | request: &RepositoryCommitBeforeRequest, |
576 | |
577 | self.handle_repository_commit_before |
578 | requester, |
579 | repository_object, |
580 | OperationState, |
581 | request, |
582 | |
583 | .await |
584 | |
585 | |
586 | // TODO: See where this would need to go in terms of being split up into a different file |
587 | /// Returns zero for all statistics if an OID wasn't found |
588 | async |
589 | &mut self, |
590 | requester: & , |
591 | repository_object: &mut , |
592 | OperationState | : ,
593 | request: &RepositoryStatisticsRequest, |
594 | |
595 | let repository = repository_object.object; |
596 | let git = self |
597 | .open_repository_and_check_permissions |
598 | .await?; |
599 | |
600 | let default_branch = repository_object |
601 | . |
602 | .await?; |
603 | let tree_id = |
604 | match Self get_oid_from_reference |
605 | Ok => oid, |
606 | Err => return Ok, |
607 | ; |
608 | |
609 | // Count the amount of branches and tags |
610 | let mut branches = 0; |
611 | let mut tags = 0; |
612 | if let Ok = git.references |
613 | for reference in references.flatten |
614 | if reference.is_branch |
615 | branches += 1; |
616 | else if reference.is_tag |
617 | tags += 1; |
618 | |
619 | |
620 | |
621 | |
622 | // Attempt to get the commit from the oid |
623 | let commits = if let Ok = git.find_commit |
624 | // Get the total commit count if we found the tree oid commit |
625 | ? | get_total_commit_count
626 | else |
627 | 0 |
628 | ; |
629 | |
630 | Ok |
631 | commits, |
632 | branches, |
633 | tags, |
634 | |
635 | |
636 | |
637 | /// .0: List of branches filtering by passed requirements. |
638 | /// .1: Total amount of branches after being filtered |
639 | async |
640 | &mut self, |
641 | requester: & , |
642 | repository_object: &mut , |
643 | OperationState | : ,
644 | request: &RepositoryBranchesRequest, |
645 | |
646 | self.handle_repository_get_branches |
647 | requester, |
648 | repository_object, |
649 | OperationState, |
650 | request, |
651 | |
652 | .await |
653 | |
654 | |
655 | async |
656 | &mut self, |
657 | requester: & , |
658 | repository_object: &mut , |
659 | OperationState | : ,
660 | request: &RepositoryBranchRequest, |
661 | |
662 | self.handle_repository_get_branch |
663 | requester, |
664 | repository_object, |
665 | OperationState, |
666 | request, |
667 | |
668 | .await |
669 | |
670 | |
671 | /// .0: List of tags in passed range |
672 | /// .1: Total amount of tags |
673 | async |
674 | &mut self, |
675 | requester: & , |
676 | repository_object: &mut , |
677 | OperationState | : ,
678 | request: &RepositoryTagsRequest, |
679 | |
680 | self.handle_repository_get_tags |
681 | requester, |
682 | repository_object, |
683 | OperationState, |
684 | request, |
685 | |
686 | .await |
687 | |
688 | |
689 | async |
690 | &mut self, |
691 | requester: & , |
692 | repository_object: &mut , |
693 | OperationState | : ,
694 | request: &RepositoryTagRequest, |
695 | |
696 | self.handle_repository_get_tag |
697 | requester, |
698 | repository_object, |
699 | OperationState, |
700 | request, |
701 | |
702 | .await |
703 | |
704 | |
705 | async |
706 | &mut self, |
707 | requester: & , |
708 | repository: &Repository, |
709 | |
710 | if let Ok = self |
711 | .find_by_owner_user_name |
712 | .await |
713 | |
714 | Ok |
715 | .can_user_view_repository |
716 | .await |
717 | else |
718 | Ok |
719 | |
720 | |
721 | |
722 | |
723 | |
724 | |
725 | &mut self, |
726 | _requester: & , |
727 | _request: &RepositoryIssuesCountRequest, |
728 | |
729 | todo! |
730 | |
731 | |
732 | |
733 | &mut self, |
734 | _requester: & , |
735 | _request: &RepositoryIssueTagsRequest, |
736 | |
737 | todo! |
738 | |
739 | |
740 | |
741 | &mut self, |
742 | _requester: & , |
743 | _request: &RepositoryIssuesRequest, |
744 | |
745 | todo! |
746 | |
747 | |
748 | |
749 | |
750 | |
751 | |
752 | pub repository: String, |
753 | pub name: String, |
754 | pub value: String, |
755 | |
756 |