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