diff --git a/giterated-daemon/src/backend/git.rs b/giterated-daemon/src/backend/git.rs index 9cd21a0..c6b1d07 100644 --- a/giterated-daemon/src/backend/git.rs +++ b/giterated-daemon/src/backend/git.rs @@ -4,9 +4,10 @@ use async_trait::async_trait; use git2::BranchType; use giterated_models::instance::{Instance, RepositoryCreateRequest}; +use giterated_models::object::Object; use giterated_models::repository::{ - AccessList, Commit, DefaultBranch, Description, IssueLabel, Repository, RepositoryBranch, - RepositoryBranchFilter, RepositoryBranchesRequest, RepositoryChunkLine, + AccessList, BranchStaleAfter, Commit, DefaultBranch, Description, IssueLabel, Repository, + RepositoryBranch, RepositoryBranchFilter, RepositoryBranchesRequest, RepositoryChunkLine, RepositoryCommitBeforeRequest, RepositoryCommitFromIdRequest, RepositoryDiff, RepositoryDiffFile, RepositoryDiffFileChunk, RepositoryDiffFileInfo, RepositoryDiffFileStatus, RepositoryDiffPatchRequest, RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest, @@ -18,7 +19,7 @@ use giterated_models::repository::{ use giterated_models::user::User; -use giterated_stack::{AuthenticatedUser, GiteratedStack}; +use giterated_stack::{AuthenticatedUser, GiteratedStack, OperationState, StackOperationState}; use sqlx::PgPool; use std::ops::Deref; @@ -397,7 +398,7 @@ impl GitBackend { } } -#[async_trait] +#[async_trait(?Send)] impl RepositoryBackend for GitBackend { async fn exists( &mut self, @@ -785,13 +786,22 @@ impl RepositoryBackend for GitBackend { async fn repository_get_branches( &mut self, requester: &Option, - repository: &Repository, + repository_object: &mut Object<'_, StackOperationState, Repository, GiteratedStack>, + OperationState(operation_state): OperationState, request: &RepositoryBranchesRequest, ) -> Result<(Vec, usize), Error> { + let repository: &Repository = repository_object.object(); let git = self .open_repository_and_check_permissions(&repository.owner, &repository.name, requester) .await?; + // Get the stale(after X seconds) setting + let stale_after = repository_object + .get::(&operation_state) + .await + .unwrap_or_default() + .0; + // Could be done better with the RepositoryBranchFilter::None check done beforehand. let mut filtered_branches = git .branches(None)? @@ -809,8 +819,12 @@ impl RepositoryBackend for GitBackend { return None; }; - // TODO: Implement stale with configurable age - let stale = false; + let stale = !branch.is_head() + && chrono::Utc::now() + .naive_utc() + .signed_duration_since(commit.time) + .num_seconds() + > stale_after.into(); // Filter based on if the branch is stale or not if request.filter != RepositoryBranchFilter::None { diff --git a/giterated-daemon/src/backend/mod.rs b/giterated-daemon/src/backend/mod.rs index 5b2400f..57bf21b 100644 --- a/giterated-daemon/src/backend/mod.rs +++ b/giterated-daemon/src/backend/mod.rs @@ -6,7 +6,8 @@ pub mod user; use anyhow::Error; use async_trait::async_trait; -use giterated_stack::AuthenticatedUser; +use giterated_models::object::Object; +use giterated_stack::{AuthenticatedUser, GiteratedStack, OperationState, StackOperationState}; use serde_json::Value; use crate::backend::git::GitBackendError; @@ -28,7 +29,7 @@ use giterated_models::repository::{ use giterated_models::user::User; -#[async_trait] +#[async_trait(?Send)] pub trait RepositoryBackend { async fn create_repository( &mut self, @@ -92,7 +93,8 @@ pub trait RepositoryBackend { async fn repository_get_branches( &mut self, requester: &Option, - repository: &Repository, + repository_object: &mut Object<'_, StackOperationState, Repository, GiteratedStack>, + OperationState(operation_state): OperationState, request: &RepositoryBranchesRequest, ) -> Result<(Vec, usize), Error>; async fn exists( diff --git a/giterated-daemon/src/database_backend/handler.rs b/giterated-daemon/src/database_backend/handler.rs index f743e87..113f9ba 100644 --- a/giterated-daemon/src/database_backend/handler.rs +++ b/giterated-daemon/src/database_backend/handler.rs @@ -149,14 +149,19 @@ pub async fn repository_get_branches( backend: GiteratedStack, requester: Option, ) -> Result<(Vec, usize), OperationError> { - let object = backend + let mut object = backend .get_object::(&object.to_string(), &operation_state) .await .unwrap(); let mut repository_backend = state.repository_backend.lock().await; let branches = repository_backend - .repository_get_branches(&requester, object.object(), &operation) + .repository_get_branches( + &requester, + &mut object, + OperationState(operation_state), + &operation, + ) .await .as_internal_error()?; drop(repository_backend); diff --git a/giterated-daemon/src/database_backend/mod.rs b/giterated-daemon/src/database_backend/mod.rs index 26e2ee5..866bbd3 100644 --- a/giterated-daemon/src/database_backend/mod.rs +++ b/giterated-daemon/src/database_backend/mod.rs @@ -8,7 +8,7 @@ use anyhow::Context; use giterated_models::instance::Instance; use giterated_models::repository::{ - CommitBodyType, DefaultBranch, Description, Repository, Visibility, + BranchStaleAfter, CommitBodyType, DefaultBranch, Description, Repository, Visibility, }; use giterated_models::user::{Bio, DisplayName, User}; use giterated_stack::provider::MetadataProvider; @@ -76,7 +76,8 @@ impl DatabaseBackend { .value_setting::() .value_setting::() .value_setting::() - .value_setting::(); + .value_setting::() + .value_setting::(); // builder.value(repository_latest_commit); diff --git a/giterated-models/src/repository/values.rs b/giterated-models/src/repository/values.rs index 9b10fd0..c7c03e1 100644 --- a/giterated-models/src/repository/values.rs +++ b/giterated-models/src/repository/values.rs @@ -97,3 +97,30 @@ impl GiteratedObjectValue for CommitBodyType { "commit_body_type" } } + +/// This value determines after how long of a period of inactivity a branch is marked stale in seconds. +/// The default (as we have not implemented it via config) is about 3 months. +#[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct BranchStaleAfter(pub u32); + +impl Default for BranchStaleAfter { + fn default() -> Self { + // TODO: Make default configurable using config + // This is about 3 months in seconds + Self(7889238) + } +} + +impl GiteratedObjectValue for BranchStaleAfter { + type Object = Repository; + + fn value_name() -> &'static str { + "branch_stale_after" + } +} + +impl Setting for BranchStaleAfter { + fn name() -> &'static str { + "branch_stale_after" + } +}