Unified stack `GetValue` implementation
parent: tbd commit: 325f5af
1 | use Error; |
2 | use async_trait; |
3 | |
4 | use BranchType; |
5 | use ; |
6 | |
7 | use |
8 | AccessList, Commit, DefaultBranch, Description, IssueLabel, LatestCommit, Repository, |
9 | RepositoryChunkLine, RepositoryCommitBeforeRequest, RepositoryDiff, RepositoryDiffFile, |
10 | RepositoryDiffFileChunk, RepositoryDiffFileInfo, RepositoryDiffFileStatus, |
11 | RepositoryDiffPatchRequest, RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest, |
12 | RepositoryFileFromPathRequest, RepositoryFileInspectRequest, RepositoryIssue, |
13 | RepositoryIssueLabelsRequest, RepositoryIssuesCountRequest, RepositoryIssuesRequest, |
14 | RepositoryObjectType, RepositoryTreeEntry, RepositoryVisibility, Visibility, |
15 | ; |
16 | use ; |
17 | use ; |
18 | use ; |
19 | use AuthenticatedUser; |
20 | use Value; |
21 | use PgPool; |
22 | use Deref; |
23 | use |
24 | , |
25 | , | Arc
26 | ; |
27 | use Error; |
28 | use Mutex; |
29 | |
30 | use ; |
31 | |
32 | // TODO: Handle this |
33 | //region database structures |
34 | |
35 | /// Repository in the database |
36 | |
37 | |
38 | #[sqlx(try_from = "String")] |
39 | pub owner_user: User, |
40 | pub name: String, |
41 | pub description: , |
42 | pub visibility: RepositoryVisibility, |
43 | pub default_branch: String, |
44 | |
45 | |
46 | |
47 | // Separate function because "Private" will be expanded later |
48 | /// Checks if the user is allowed to view this repository |
49 | pub async |
50 | &self, |
51 | our_instance: &Instance, |
52 | user: & , |
53 | settings: & , |
54 | |
55 | if matches! |
56 | return true; |
57 | |
58 | |
59 | // User must exist for any further checks to pass |
60 | let user = match user |
61 | Some => user, |
62 | None => return false, |
63 | ; |
64 | |
65 | if *user.deref == self.owner_user |
66 | // owner can always view |
67 | return true; |
68 | |
69 | |
70 | if matches! |
71 | // Check if the user can view |
72 | let mut settings = settings.lock .await; |
73 | |
74 | let access_list = settings |
75 | .repository_get |
76 | &Repository |
77 | owner: self.owner_user.clone, |
78 | name: self.name.clone, |
79 | instance: our_instance.clone, |
80 | , |
81 | , | name
82 | |
83 | .await; |
84 | |
85 | let access_list: AccessList = match access_list |
86 | Ok => from_value .unwrap, |
87 | Err => |
88 | return false; |
89 | |
90 | ; |
91 | |
92 | access_list |
93 | .0 |
94 | .iter |
95 | .find |
96 | .is_some |
97 | else |
98 | false |
99 | |
100 | |
101 | |
102 | // This is in it's own function because I assume I'll have to add logic to this later |
103 | |
104 | &self, |
105 | repository_directory: &str, |
106 | |
107 | match open |
108 | "{}/{}/{}/{}" |
109 | repository_directory, self.owner_user.instance, self.owner_user.username, self.name |
110 | ) |
111 | Ok => Ok, |
112 | Err => |
113 | let err = FailedOpeningFromDisk; |
114 | error!; |
115 | |
116 | Err |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | //endregion |
123 | |
124 | |
125 | |
126 | |
127 | FailedCreatingRepository, |
128 | |
129 | FailedInsertingIntoDatabase, |
130 | |
131 | RepositoryNotFound , |
132 | |
133 | RepositoryAlreadyExists , |
134 | |
135 | CouldNotDeleteFromDisk, |
136 | |
137 | FailedDeletingFromDatabase, |
138 | |
139 | FailedOpeningFromDisk, |
140 | |
141 | RefNotFound, |
142 | |
143 | PathNotFound, |
144 | |
145 | LastCommitNotFound, |
146 | |
147 | InvalidObjectId, |
148 | |
149 | BlobNotFound, |
150 | |
151 | TreeNotFound, |
152 | |
153 | CommitNotFound, |
154 | |
155 | CommitParentNotFound, |
156 | |
157 | FailedDiffing, |
158 | |
159 | |
160 | |
161 | pub pg_pool: PgPool, |
162 | pub repository_folder: String, |
163 | pub instance: Instance, |
164 | pub settings_provider: , |
165 | |
166 | |
167 | |
168 | |
169 | pg_pool: &PgPool, |
170 | repository_folder: &str, |
171 | instance: impl , |
172 | settings_provider: , |
173 | |
174 | Self |
175 | pg_pool: pg_pool.clone, |
176 | repository_folder: repository_folder.to_string, |
177 | instance: instance.to_owned, |
178 | settings_provider, |
179 | |
180 | |
181 | |
182 | pub async |
183 | &self, |
184 | user: &User, |
185 | repository_name: &str, |
186 | |
187 | if let Ok = query_as! |
188 | r#"SELECT owner_user, name, description, visibility as "visibility: _", default_branch FROM repositories WHERE owner_user = $1 AND name = $2"#, |
189 | user.to_string, repository_name |
190 | .fetch_one |
191 | .await |
192 | Ok |
193 | else |
194 | Err |
195 | owner_user: user.to_string, |
196 | name: repository_name.to_string, |
197 | |
198 | |
199 | |
200 | |
201 | pub async |
202 | &self, |
203 | user: &User, |
204 | repository_name: &str, |
205 | |
206 | if let Err = remove_dir_all |
207 | "{}/{}/{}/{}" |
208 | self.repository_folder, user.instance, user.username, repository_name |
209 | ) |
210 | let err = CouldNotDeleteFromDisk; |
211 | error! |
212 | "Couldn't delete repository from disk, this is bad! {:?}", |
213 | err |
214 | ; |
215 | |
216 | return Err; |
217 | |
218 | |
219 | // Delete the repository from the database |
220 | match query! |
221 | "DELETE FROM repositories WHERE owner_user = $1 AND name = $2", |
222 | user.to_string, |
223 | repository_name |
224 | |
225 | .execute |
226 | .await |
227 | |
228 | Ok => Ok, |
229 | Err => Err, |
230 | |
231 | |
232 | |
233 | pub async |
234 | &self, |
235 | owner: &User, |
236 | name: &str, |
237 | requester: & , |
238 | |
239 | let repository = match self |
240 | .find_by_owner_user_name |
241 | // &request.owner.instance.url, |
242 | owner, name, |
243 | |
244 | .await |
245 | |
246 | Ok => repository, |
247 | Err => return Err, |
248 | ; |
249 | |
250 | if let Some = requester |
251 | if !repository |
252 | .can_user_view_repository |
253 | &self.instance, |
254 | &Some, |
255 | &self.settings_provider, |
256 | |
257 | .await |
258 | |
259 | return Err |
260 | owner_user: repository.owner_user.to_string, |
261 | name: repository.name.clone, |
262 | ; |
263 | |
264 | else if matches! |
265 | // Unauthenticated users can never view private repositories |
266 | |
267 | return Err |
268 | owner_user: repository.owner_user.to_string, |
269 | name: repository.name.clone, |
270 | ; |
271 | |
272 | |
273 | match repository.open_git2_repository |
274 | Ok => Ok, |
275 | Err => return Err, |
276 | |
277 | |
278 | |
279 | // TODO: Find where this fits |
280 | // TODO: Cache this and general repository tree and invalidate select files on push |
281 | // TODO: Find better and faster technique for this |
282 | |
283 | path: &str, |
284 | git: & Repository, |
285 | start_commit: & Commit, |
286 | |
287 | let mut revwalk = git.revwalk?; |
288 | revwalk.set_sorting?; |
289 | revwalk.push?; |
290 | |
291 | for oid in revwalk |
292 | let oid = oid?; |
293 | let commit = git.find_commit?; |
294 | |
295 | // Merge commits have 2 or more parents |
296 | // Commits with 0 parents are handled different because we can't diff against them |
297 | if commit.parent_count == 0 |
298 | return Ok; |
299 | else if commit.parent_count == 1 |
300 | let tree = commit.tree?; |
301 | let last_tree = commit.parent?.tree?; |
302 | |
303 | // Get the diff between the current tree and the last one |
304 | let diff = git.diff_tree_to_tree?; |
305 | |
306 | for dd in diff.deltas |
307 | // Get the path of the current file we're diffing against |
308 | let current_path = dd.new_file .path .unwrap; |
309 | |
310 | // Path or directory |
311 | if current_path.eq || current_path.starts_with |
312 | return Ok; |
313 | |
314 | |
315 | |
316 | |
317 | |
318 | Err? |
319 | |
320 | |
321 | |
322 | |
323 | |
324 | async |
325 | &mut self, |
326 | requester: & , |
327 | repository: &Repository, |
328 | |
329 | if let Ok = self |
330 | .find_by_owner_user_name |
331 | .await |
332 | |
333 | Ok |
334 | .can_user_view_repository |
335 | .await |
336 | else |
337 | Ok |
338 | |
339 | |
340 | |
341 | async |
342 | &mut self, |
343 | _user: &AuthenticatedUser, |
344 | request: &RepositoryCreateRequest, |
345 | |
346 | // Check if repository already exists in the database |
347 | if let Ok = self |
348 | .find_by_owner_user_name |
349 | .await |
350 | |
351 | let err = RepositoryAlreadyExists |
352 | owner_user: repository.owner_user.to_string, |
353 | name: repository.name, |
354 | ; |
355 | error!; |
356 | |
357 | return Err; |
358 | |
359 | |
360 | // Insert the repository into the database |
361 | let _ = match query_as! |
362 | r#"INSERT INTO repositories VALUES ($1, $2, $3, $4, $5) RETURNING owner_user, name, description, visibility as "visibility: _", default_branch"#, |
363 | request.owner.to_string, request.name, request.description, request.visibility as _, "master" |
364 | .fetch_one |
365 | .await |
366 | Ok => repository, |
367 | Err => |
368 | let err = FailedInsertingIntoDatabase; |
369 | error!; |
370 | |
371 | return Err; |
372 | |
373 | ; |
374 | |
375 | // Create bare (server side) repository on disk |
376 | match init_bare |
377 | "{}/{}/{}/{}" |
378 | self.repository_folder, request.owner.instance, request.owner.username, request.name |
379 | ) |
380 | Ok => |
381 | debug! |
382 | "Created new repository with the name {}/{}/{}", |
383 | request.owner.instance, request.owner.username, request.name |
384 | ; |
385 | |
386 | let repository = Repository |
387 | owner: request.owner.clone, |
388 | name: request.name.clone, |
389 | instance: request.instance.as_ref .unwrap_or .clone, |
390 | ; |
391 | |
392 | let mut settings_backend = self.settings_provider.lock .await; |
393 | settings_backend |
394 | .repository_write |
395 | &repository, |
396 | , | name
397 | AnySetting |
398 | to_value |
399 | request.description.clone .unwrap_or_default, |
400 | |
401 | .unwrap, |
402 | , |
403 | |
404 | .await |
405 | .unwrap; |
406 | settings_backend |
407 | .repository_write |
408 | &repository, |
409 | , | name
410 | AnySetting |
411 | unwrap, | to_value .
412 | , |
413 | |
414 | .await |
415 | .unwrap; |
416 | settings_backend |
417 | .repository_write |
418 | &repository, |
419 | , | name
420 | AnySetting |
421 | to_value |
422 | .unwrap, |
423 | , |
424 | |
425 | .await |
426 | .unwrap; |
427 | |
428 | Ok |
429 | |
430 | Err => |
431 | let err = FailedCreatingRepository; |
432 | error!; |
433 | |
434 | // Delete repository from database |
435 | self.delete_by_owner_user_name |
436 | .await?; |
437 | |
438 | // ??? |
439 | Err |
440 | |
441 | |
442 | |
443 | |
444 | async |
445 | &mut self, |
446 | repository: &Repository, |
447 | name: &str, |
448 | |
449 | Ok |
450 | if name == value_name |
451 | from_raw |
452 | else if name == value_name |
453 | from_raw |
454 | else if name == value_name |
455 | from_raw |
456 | else if name == value_name |
457 | from_raw |
458 | else |
459 | return Err; |
460 | |
461 | |
462 | |
463 | |
464 | async |
465 | &mut self, |
466 | repository: &Repository, |
467 | name: &str, |
468 | |
469 | let mut provider = self.settings_provider.lock .await; |
470 | |
471 | Ok |
472 | |
473 | |
474 | async |
475 | &mut self, |
476 | repository: &Repository, |
477 | name: &str, |
478 | setting: &Value, |
479 | |
480 | let mut provider = self.settings_provider.lock .await; |
481 | |
482 | provider |
483 | .repository_write |
484 | .await |
485 | |
486 | |
487 | async |
488 | &mut self, |
489 | requester: & , |
490 | repository: &Repository, |
491 | request: &RepositoryFileInspectRequest, |
492 | |
493 | let git = self |
494 | .open_repository_and_check_permissions |
495 | .await?; |
496 | |
497 | // Try and parse the input as a reference and get the object ID |
498 | let mut tree_id = match &request.rev |
499 | None => |
500 | if let Ok = git.head |
501 | // TODO: Fix for symbolic references |
502 | head.target |
503 | else |
504 | // Nothing in database, render empty tree. |
505 | return Ok; |
506 | |
507 | |
508 | Some => |
509 | // Find the reference, otherwise return GitBackendError |
510 | git.refname_to_id .ok |
511 | |
512 | ; |
513 | |
514 | // If the reference wasn't found, try parsing it as a commit ID |
515 | if tree_id.is_none |
516 | if let Ok = from_str |
517 | tree_id = Some |
518 | |
519 | |
520 | |
521 | // If the commit ID wasn't found, try parsing it as a branch and otherwise return error |
522 | if tree_id.is_none |
523 | match git.find_branch |
524 | Ok => tree_id = branch.get .target, |
525 | Err => |
526 | return Err |
527 | request.rev.clone .unwrap, |
528 | |
529 | .into |
530 | |
531 | |
532 | |
533 | |
534 | // unwrap might be dangerous? |
535 | // Get the commit from the oid |
536 | let commit = git.find_commit .unwrap; |
537 | |
538 | // this is stupid |
539 | let mut current_path = request.rev.clone .unwrap_or_else; |
540 | |
541 | // Get the commit tree |
542 | let git_tree = if let Some = &request.path |
543 | // Add it to our full path string |
544 | current_path.push_str; |
545 | // Get the specified path, return an error if it wasn't found. |
546 | let entry = match commit |
547 | .tree |
548 | .unwrap |
549 | .get_path |
550 | .map_err |
551 | |
552 | Ok => entry, |
553 | Err => return Err, |
554 | ; |
555 | // Turn the entry into a git tree |
556 | entry.to_object .unwrap .as_tree .unwrap .clone |
557 | else |
558 | commit.tree .unwrap |
559 | ; |
560 | |
561 | // Iterate over the git tree and collect it into our own tree types |
562 | let mut tree = git_tree |
563 | .iter |
564 | .map |
565 | let object_type = match entry.kind .unwrap |
566 | => Tree, | Tree
567 | => Blob, | Blob
568 | _ => unreachable!, |
569 | ; |
570 | let mut tree_entry = new |
571 | entry.id .to_string .as_str, |
572 | entry.name .unwrap, |
573 | object_type, |
574 | entry.filemode, |
575 | ; |
576 | |
577 | if request.extra_metadata |
578 | // Get the file size if It's a blob |
579 | let object = entry.to_object .unwrap; |
580 | if let Some = object.as_blob |
581 | tree_entry.size = Some; |
582 | |
583 | |
584 | // Could possibly be done better |
585 | let path = if let Some = current_path.split_once |
586 | format! |
587 | else |
588 | entry.name .unwrap .to_string |
589 | ; |
590 | |
591 | // Get the last commit made to the entry |
592 | if let Ok = |
593 | get_last_commit_of_file |
594 | |
595 | tree_entry.last_commit = Some; |
596 | |
597 | |
598 | |
599 | tree_entry |
600 | |
601 | .; |
602 | |
603 | // Sort the tree alphabetically and with tree first |
604 | tree.sort_unstable_by_key; |
605 | tree.sort_unstable_by_key |
606 | Reverse |
607 | ; |
608 | |
609 | Ok |
610 | |
611 | |
612 | async |
613 | &mut self, |
614 | requester: & , |
615 | repository: &Repository, |
616 | request: &RepositoryFileFromIdRequest, |
617 | |
618 | let git = self |
619 | .open_repository_and_check_permissions |
620 | .await?; |
621 | |
622 | // Parse the passed object id |
623 | let oid = match from_str |
624 | Ok => oid, |
625 | Err => |
626 | return Err |
627 | |
628 | ; |
629 | |
630 | // Find the file and turn it into our own struct |
631 | let file = match git.find_blob |
632 | Ok => RepositoryFile |
633 | content: blob.content .to_vec, |
634 | binary: blob.is_binary, |
635 | size: blob.size, |
636 | , |
637 | Err => return Err, |
638 | ; |
639 | |
640 | Ok |
641 | |
642 | |
643 | async |
644 | &mut self, |
645 | requester: & , |
646 | repository: &Repository, |
647 | request: &RepositoryFileFromPathRequest, |
648 | |
649 | let git = self |
650 | .open_repository_and_check_permissions |
651 | .await?; |
652 | |
653 | // TODO: Remove duplicate code with repository_file_inspect, most of it is duplicate. |
654 | // Try and parse the input as a reference and get the object ID |
655 | let mut tree_id = match &request.rev |
656 | None => |
657 | if let Ok = git.head |
658 | // TODO: Fix for symbolic references |
659 | head.target |
660 | else |
661 | // Nothing in database, render empty tree. |
662 | return Err |
663 | request.rev.clone .unwrap, |
664 | |
665 | .into; |
666 | |
667 | |
668 | Some => |
669 | // Find the reference, otherwise return GitBackendError |
670 | git.refname_to_id .ok |
671 | |
672 | ; |
673 | |
674 | // If the reference wasn't found, try parsing it as a commit ID |
675 | if tree_id.is_none |
676 | if let Ok = from_str |
677 | tree_id = Some |
678 | |
679 | |
680 | |
681 | // If the commit ID wasn't found, try parsing it as a branch and otherwise return error |
682 | if tree_id.is_none |
683 | match git.find_branch |
684 | Ok => tree_id = branch.get .target, |
685 | Err => |
686 | return Err |
687 | request.rev.clone .unwrap, |
688 | |
689 | .into |
690 | |
691 | |
692 | |
693 | |
694 | // unwrap might be dangerous? |
695 | // Get the commit from the oid |
696 | let commit = git.find_commit .unwrap; |
697 | |
698 | // this is stupid |
699 | let mut current_path = request.rev.clone .unwrap_or_else; |
700 | |
701 | // Add it to our full path string |
702 | current_path.push_str; |
703 | // Get the specified path, return an error if it wasn't found. |
704 | let entry = match commit |
705 | .tree |
706 | .unwrap |
707 | .get_path |
708 | .map_err |
709 | |
710 | Ok => entry, |
711 | Err => return Err, |
712 | ; |
713 | |
714 | // Find the file and turn it into our own struct |
715 | let file = match git.find_blob |
716 | Ok => RepositoryFile |
717 | content: blob.content .to_vec, |
718 | binary: blob.is_binary, |
719 | size: blob.size, |
720 | , |
721 | Err => |
722 | return Err |
723 | |
724 | ; |
725 | |
726 | Ok |
727 | |
728 | |
729 | async |
730 | &mut self, |
731 | requester: & , |
732 | repository: &Repository, |
733 | request: &RepositoryDiffRequest, |
734 | |
735 | let git = self |
736 | .open_repository_and_check_permissions |
737 | .await?; |
738 | |
739 | // Parse the passed object ids |
740 | let oid_old = from_str |
741 | .map_err?; |
742 | let oid_new = from_str |
743 | .map_err?; |
744 | |
745 | // Get the ids associates commits |
746 | let commit_old = git |
747 | .find_commit |
748 | .map_err?; |
749 | let commit_new = git |
750 | .find_commit |
751 | .map_err?; |
752 | |
753 | // Get the commit trees |
754 | let tree_old = commit_old |
755 | .tree |
756 | .map_err?; |
757 | let tree_new = commit_new |
758 | .tree |
759 | .map_err?; |
760 | |
761 | // Diff the two trees against each other |
762 | let diff = git |
763 | .diff_tree_to_tree |
764 | .map_err |
765 | FailedDiffing |
766 | ?; |
767 | |
768 | // Should be safe to unwrap? |
769 | let stats = diff.stats .unwrap; |
770 | let mut files: = vec!; |
771 | |
772 | diff.deltas .enumerate .for_each |
773 | // Parse the old file info from the delta |
774 | let old_file_info = match delta.old_file .exists |
775 | true => Some |
776 | id: delta.old_file .id .to_string, |
777 | path: delta |
778 | .old_file |
779 | .path |
780 | .unwrap |
781 | .to_str |
782 | .unwrap |
783 | .to_string, |
784 | size: delta.old_file .size, |
785 | binary: delta.old_file .is_binary, |
786 | , |
787 | false => None, |
788 | ; |
789 | // Parse the new file info from the delta |
790 | let new_file_info = match delta.new_file .exists |
791 | true => Some |
792 | id: delta.new_file .id .to_string, |
793 | path: delta |
794 | .new_file |
795 | .path |
796 | .unwrap |
797 | .to_str |
798 | .unwrap |
799 | .to_string, |
800 | size: delta.new_file .size, |
801 | binary: delta.new_file .is_binary, |
802 | , |
803 | false => None, |
804 | ; |
805 | |
806 | let mut chunks: = vec!; |
807 | if let Some = from_diff .ok .flatten |
808 | for chunk_num in 0..patch.num_hunks |
809 | if let Ok = patch.hunk |
810 | let mut lines: = vec!; |
811 | |
812 | for line_num in 0..chunk_num_lines |
813 | if let Ok = patch.line_in_hunk |
814 | if let Ok = String from_utf8 |
815 | lines.push |
816 | change_type: line.origin_value .into, |
817 | content: line_utf8, |
818 | old_line_num: line.old_lineno, |
819 | new_line_num: line.new_lineno, |
820 | ; |
821 | |
822 | |
823 | continue; |
824 | |
825 | |
826 | |
827 | chunks.push |
828 | header: String from_utf8 .ok, |
829 | old_start: chunk.old_start, |
830 | old_lines: chunk.old_lines, |
831 | new_start: chunk.new_start, |
832 | new_lines: chunk.new_lines, |
833 | lines, |
834 | ; |
835 | |
836 | |
837 | ; |
838 | |
839 | let file = RepositoryDiffFile |
840 | status: from, |
841 | old_file_info, |
842 | new_file_info, |
843 | chunks, |
844 | ; |
845 | |
846 | files.push; |
847 | ; |
848 | |
849 | Ok |
850 | new_commit: from, |
851 | files_changed: stats.files_changed, |
852 | insertions: stats.insertions, |
853 | deletions: stats.deletions, |
854 | files, |
855 | |
856 | |
857 | |
858 | async |
859 | &mut self, |
860 | requester: & , |
861 | repository: &Repository, |
862 | request: &RepositoryDiffPatchRequest, |
863 | |
864 | let git = self |
865 | .open_repository_and_check_permissions |
866 | .await?; |
867 | |
868 | // Parse the passed object ids |
869 | let oid_old = from_str |
870 | .map_err?; |
871 | let oid_new = from_str |
872 | .map_err?; |
873 | |
874 | // Get the ids associates commits |
875 | let commit_old = git |
876 | .find_commit |
877 | .map_err?; |
878 | let commit_new = git |
879 | .find_commit |
880 | .map_err?; |
881 | |
882 | // Get the commit trees |
883 | let tree_old = commit_old |
884 | .tree |
885 | .map_err?; |
886 | let tree_new = commit_new |
887 | .tree |
888 | .map_err?; |
889 | |
890 | // Diff the two trees against each other |
891 | let diff = git |
892 | .diff_tree_to_tree |
893 | .map_err |
894 | FailedDiffing |
895 | ?; |
896 | |
897 | // Print the entire patch |
898 | let mut patch = String new; |
899 | |
900 | diff.print |
901 | match line.origin |
902 | '+' | '-' | ' ' => patch.push, |
903 | _ => |
904 | |
905 | patch.push_str; |
906 | true |
907 | |
908 | .unwrap; |
909 | |
910 | Ok |
911 | |
912 | |
913 | async |
914 | &mut self, |
915 | requester: & , |
916 | repository: &Repository, |
917 | request: &RepositoryCommitBeforeRequest, |
918 | |
919 | let git = self |
920 | .open_repository_and_check_permissions |
921 | .await?; |
922 | |
923 | // Parse the passed object id |
924 | let oid = match from_str |
925 | Ok => oid, |
926 | Err => |
927 | return Err |
928 | |
929 | ; |
930 | |
931 | // Find the commit using the parsed oid |
932 | let commit = match git.find_commit |
933 | Ok => commit, |
934 | Err => return Err, |
935 | ; |
936 | |
937 | // Get the first parent it has |
938 | let parent = commit.parent; |
939 | if let Ok = parent |
940 | return Ok; |
941 | else |
942 | // TODO: See if can be done better |
943 | // Walk through the repository commit graph starting at our current commit |
944 | let mut revwalk = git.revwalk?; |
945 | revwalk.set_sorting?; |
946 | revwalk.push?; |
947 | |
948 | if let Some = revwalk.next |
949 | if let Ok = next |
950 | // Find the commit using the parsed oid |
951 | if let Ok = git.find_commit |
952 | return Ok; |
953 | |
954 | |
955 | |
956 | |
957 | Err |
958 | |
959 | |
960 | |
961 | |
962 | |
963 | |
964 | &mut self, |
965 | _requester: & , |
966 | _request: &RepositoryIssuesCountRequest, |
967 | |
968 | todo! |
969 | |
970 | |
971 | |
972 | &mut self, |
973 | _requester: & , |
974 | _request: &RepositoryIssueLabelsRequest, |
975 | |
976 | todo! |
977 | |
978 | |
979 | |
980 | &mut self, |
981 | _requester: & , |
982 | _request: &RepositoryIssuesRequest, |
983 | |
984 | todo! |
985 | |
986 | |
987 | |
988 | |
989 | |
990 | |
991 | pub repository: String, |
992 | pub name: String, |
993 | pub value: String, |
994 | |
995 |