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