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