Simple branch staleness implementation
parent: tbd commit: efc3f02
Showing 5 changed files with 63 insertions and 14 deletions
giterated-daemon/src/backend/git.rs
@@ -4,9 +4,10 @@ use async_trait::async_trait; | ||
4 | 4 | use git2::BranchType; |
5 | 5 | use giterated_models::instance::{Instance, RepositoryCreateRequest}; |
6 | 6 | |
7 | use giterated_models::object::Object; | |
7 | 8 | use giterated_models::repository::{ |
8 | AccessList, Commit, DefaultBranch, Description, IssueLabel, Repository, RepositoryBranch, | |
9 | RepositoryBranchFilter, RepositoryBranchesRequest, RepositoryChunkLine, | |
9 | AccessList, BranchStaleAfter, Commit, DefaultBranch, Description, IssueLabel, Repository, | |
10 | RepositoryBranch, RepositoryBranchFilter, RepositoryBranchesRequest, RepositoryChunkLine, | |
10 | 11 | RepositoryCommitBeforeRequest, RepositoryCommitFromIdRequest, RepositoryDiff, |
11 | 12 | RepositoryDiffFile, RepositoryDiffFileChunk, RepositoryDiffFileInfo, RepositoryDiffFileStatus, |
12 | 13 | RepositoryDiffPatchRequest, RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest, |
@@ -18,7 +19,7 @@ use giterated_models::repository::{ | ||
18 | 19 | |
19 | 20 | use giterated_models::user::User; |
20 | 21 | |
21 | use giterated_stack::{AuthenticatedUser, GiteratedStack}; | |
22 | use giterated_stack::{AuthenticatedUser, GiteratedStack, OperationState, StackOperationState}; | |
22 | 23 | |
23 | 24 | use sqlx::PgPool; |
24 | 25 | use std::ops::Deref; |
@@ -397,7 +398,7 @@ impl GitBackend { | ||
397 | 398 | } |
398 | 399 | } |
399 | 400 | |
400 | #[async_trait] | |
401 | #[async_trait(?Send)] | |
401 | 402 | impl RepositoryBackend for GitBackend { |
402 | 403 | async fn exists( |
403 | 404 | &mut self, |
@@ -785,13 +786,22 @@ impl RepositoryBackend for GitBackend { | ||
785 | 786 | async fn repository_get_branches( |
786 | 787 | &mut self, |
787 | 788 | requester: &Option<AuthenticatedUser>, |
788 | repository: &Repository, | |
789 | repository_object: &mut Object<'_, StackOperationState, Repository, GiteratedStack>, | |
790 | OperationState(operation_state): OperationState<StackOperationState>, | |
789 | 791 | request: &RepositoryBranchesRequest, |
790 | 792 | ) -> Result<(Vec<RepositoryBranch>, usize), Error> { |
793 | let repository: &Repository = repository_object.object(); | |
791 | 794 | let git = self |
792 | 795 | .open_repository_and_check_permissions(&repository.owner, &repository.name, requester) |
793 | 796 | .await?; |
794 | 797 | |
798 | // Get the stale(after X seconds) setting | |
799 | let stale_after = repository_object | |
800 | .get::<BranchStaleAfter>(&operation_state) | |
801 | .await | |
802 | .unwrap_or_default() | |
803 | .0; | |
804 | ||
795 | 805 | // Could be done better with the RepositoryBranchFilter::None check done beforehand. |
796 | 806 | let mut filtered_branches = git |
797 | 807 | .branches(None)? |
@@ -809,8 +819,12 @@ impl RepositoryBackend for GitBackend { | ||
809 | 819 | return None; |
810 | 820 | }; |
811 | 821 | |
812 | // TODO: Implement stale with configurable age | |
813 | let stale = false; | |
822 | let stale = !branch.is_head() | |
823 | && chrono::Utc::now() | |
824 | .naive_utc() | |
825 | .signed_duration_since(commit.time) | |
826 | .num_seconds() | |
827 | > stale_after.into(); | |
814 | 828 | |
815 | 829 | // Filter based on if the branch is stale or not |
816 | 830 | if request.filter != RepositoryBranchFilter::None { |
giterated-daemon/src/backend/mod.rs
@@ -6,7 +6,8 @@ pub mod user; | ||
6 | 6 | |
7 | 7 | use anyhow::Error; |
8 | 8 | use async_trait::async_trait; |
9 | use giterated_stack::AuthenticatedUser; | |
9 | use giterated_models::object::Object; | |
10 | use giterated_stack::{AuthenticatedUser, GiteratedStack, OperationState, StackOperationState}; | |
10 | 11 | use serde_json::Value; |
11 | 12 | |
12 | 13 | use crate::backend::git::GitBackendError; |
@@ -28,7 +29,7 @@ use giterated_models::repository::{ | ||
28 | 29 | |
29 | 30 | use giterated_models::user::User; |
30 | 31 | |
31 | #[async_trait] | |
32 | #[async_trait(?Send)] | |
32 | 33 | pub trait RepositoryBackend { |
33 | 34 | async fn create_repository( |
34 | 35 | &mut self, |
@@ -92,7 +93,8 @@ pub trait RepositoryBackend { | ||
92 | 93 | async fn repository_get_branches( |
93 | 94 | &mut self, |
94 | 95 | requester: &Option<AuthenticatedUser>, |
95 | repository: &Repository, | |
96 | repository_object: &mut Object<'_, StackOperationState, Repository, GiteratedStack>, | |
97 | OperationState(operation_state): OperationState<StackOperationState>, | |
96 | 98 | request: &RepositoryBranchesRequest, |
97 | 99 | ) -> Result<(Vec<RepositoryBranch>, usize), Error>; |
98 | 100 | async fn exists( |
giterated-daemon/src/database_backend/handler.rs
@@ -149,14 +149,19 @@ pub async fn repository_get_branches( | ||
149 | 149 | backend: GiteratedStack, |
150 | 150 | requester: Option<AuthenticatedUser>, |
151 | 151 | ) -> Result<(Vec<RepositoryBranch>, usize), OperationError<RepositoryError>> { |
152 | let object = backend | |
152 | let mut object = backend | |
153 | 153 | .get_object::<Repository>(&object.to_string(), &operation_state) |
154 | 154 | .await |
155 | 155 | .unwrap(); |
156 | 156 | |
157 | 157 | let mut repository_backend = state.repository_backend.lock().await; |
158 | 158 | let branches = repository_backend |
159 | .repository_get_branches(&requester, object.object(), &operation) | |
159 | .repository_get_branches( | |
160 | &requester, | |
161 | &mut object, | |
162 | OperationState(operation_state), | |
163 | &operation, | |
164 | ) | |
160 | 165 | .await |
161 | 166 | .as_internal_error()?; |
162 | 167 | drop(repository_backend); |
giterated-daemon/src/database_backend/mod.rs
@@ -8,7 +8,7 @@ use anyhow::Context; | ||
8 | 8 | |
9 | 9 | use giterated_models::instance::Instance; |
10 | 10 | use giterated_models::repository::{ |
11 | CommitBodyType, DefaultBranch, Description, Repository, Visibility, | |
11 | BranchStaleAfter, CommitBodyType, DefaultBranch, Description, Repository, Visibility, | |
12 | 12 | }; |
13 | 13 | use giterated_models::user::{Bio, DisplayName, User}; |
14 | 14 | use giterated_stack::provider::MetadataProvider; |
@@ -76,7 +76,8 @@ impl DatabaseBackend { | ||
76 | 76 | .value_setting::<Repository, Description>() |
77 | 77 | .value_setting::<Repository, Visibility>() |
78 | 78 | .value_setting::<Repository, DefaultBranch>() |
79 | .value_setting::<Repository, CommitBodyType>(); | |
79 | .value_setting::<Repository, CommitBodyType>() | |
80 | .value_setting::<Repository, BranchStaleAfter>(); | |
80 | 81 | |
81 | 82 | // builder.value(repository_latest_commit); |
82 | 83 |
giterated-models/src/repository/values.rs
@@ -97,3 +97,30 @@ impl GiteratedObjectValue for CommitBodyType { | ||
97 | 97 | "commit_body_type" |
98 | 98 | } |
99 | 99 | } |
100 | ||
101 | /// This value determines after how long of a period of inactivity a branch is marked stale in seconds. | |
102 | /// The default (as we have not implemented it via config) is about 3 months. | |
103 | #[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)] | |
104 | pub struct BranchStaleAfter(pub u32); | |
105 | ||
106 | impl Default for BranchStaleAfter { | |
107 | fn default() -> Self { | |
108 | // TODO: Make default configurable using config | |
109 | // This is about 3 months in seconds | |
110 | Self(7889238) | |
111 | } | |
112 | } | |
113 | ||
114 | impl GiteratedObjectValue for BranchStaleAfter { | |
115 | type Object = Repository; | |
116 | ||
117 | fn value_name() -> &'static str { | |
118 | "branch_stale_after" | |
119 | } | |
120 | } | |
121 | ||
122 | impl Setting for BranchStaleAfter { | |
123 | fn name() -> &'static str { | |
124 | "branch_stale_after" | |
125 | } | |
126 | } |