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