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