JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Repository commit before request and handler

Type: Feature

erremilia - ⁨2⁩ years ago

parent: tbd commit: ⁨144b159

Showing ⁨⁨5⁩ changed files⁩ with ⁨⁨142⁩ insertions⁩ and ⁨⁨6⁩ deletions⁩

giterated-daemon/src/backend/git.rs

View file
@@ -8,7 +8,7 @@ use giterated_models::repository::{
8 8 Commit, DefaultBranch, Description, IssueLabel, LatestCommit, Repository,
9 9 RepositoryFileInspectRequest, RepositoryIssue, RepositoryIssueLabelsRequest,
10 10 RepositoryIssuesCountRequest, RepositoryIssuesRequest, RepositoryObjectType,
11 RepositoryTreeEntry, RepositoryVisibility, Visibility, RepositoryFile, RepositoryFileFromIdRequest, RepositoryDiffRequest, RepositoryDiff,
11 RepositoryTreeEntry, RepositoryVisibility, Visibility, RepositoryFile, RepositoryFileFromIdRequest, RepositoryDiffRequest, RepositoryDiff, RepositoryCommitBeforeRequest,
12 12 };
13 13 use giterated_models::settings::{AnySetting, Setting};
14 14 use giterated_models::user::{User, UserParseError};
@@ -97,6 +97,10 @@ pub enum GitBackendError {
97 97 BlobNotFound(String),
98 98 #[error("Tree with ID `{0}` not found")]
99 99 TreeNotFound(String),
100 #[error("Commit with ID `{0}` not found")]
101 CommitNotFound(String),
102 #[error("Parent for commit with ID `{0}` not found")]
103 CommitParentNotFound(String),
100 104 #[error("Failed diffing tree with ID `{0}` to tree with ID `{1}`")]
101 105 FailedDiffing(String, String),
102 106 }
@@ -174,6 +178,42 @@ impl GitBackend {
174 178 }
175 179 }
176 180
181 pub async fn open_repository_and_check_permissions(&self, owner: &User, name: &str, requester: Option<&User>) -> Result<git2::Repository, GitBackendError> {
182 let repository = match self
183 .find_by_owner_user_name(
184 // &request.owner.instance.url,
185 owner,
186 name,
187 )
188 .await
189 {
190 Ok(repository) => repository,
191 Err(err) => return Err(err),
192 };
193
194 if let Some(requester) = requester {
195 if !repository.can_user_view_repository(Some(requester)) {
196 return Err(GitBackendError::RepositoryNotFound {
197 owner_user: repository.owner_user.to_string(),
198 name: repository.name.clone(),
199 });
200 }
201 } else if matches!(repository.visibility, RepositoryVisibility::Private) {
202 info!("Unauthenticated");
203 // Unauthenticated users can never view private repositories
204
205 return Err(GitBackendError::RepositoryNotFound {
206 owner_user: repository.owner_user.to_string(),
207 name: repository.name.clone(),
208 });
209 }
210
211 match repository.open_git2_repository(&self.repository_folder) {
212 Ok(git) => Ok(git),
213 Err(err) => return Err(err),
214 }
215 }
216
177 217 // TODO: Find where this fits
178 218 // TODO: Cache this and general repository tree and invalidate select files on push
179 219 // TODO: Find better and faster technique for this
@@ -787,6 +827,35 @@ impl RepositoryBackend for GitBackend {
787 827 patch,
788 828 })
789 829 }
830
831 async fn repository_commit_before(
832 &mut self,
833 requester: Option<&User>,
834 repository: &Repository,
835 request: &RepositoryCommitBeforeRequest,
836 ) -> Result<Commit, Error> {
837 let git = self.open_repository_and_check_permissions(&repository.owner, &repository.name, requester).await?;
838
839 // Parse the passed object id
840 let oid = match git2::Oid::from_str(request.0.as_str()) {
841 Ok(oid) => oid,
842 Err(_) => return Err(Box::new(GitBackendError::InvalidObjectId(request.0.clone())).into()),
843 };
844
845 // Find the commit using the parsed oid
846 let commit = match git.find_commit(oid) {
847 Ok(commit) => commit,
848 Err(_) => return Err(Box::new(GitBackendError::CommitNotFound(oid.to_string())).into()),
849 };
850
851 // Get the first parent it has
852 let parent = match commit.parent(0) {
853 Ok(parent) => Commit::from(parent),
854 Err(_) => return Err(Box::new(GitBackendError::CommitParentNotFound(oid.to_string())).into()),
855 };
856
857 Ok(parent)
858 }
790 859 }
791 860
792 861 impl IssuesBackend for GitBackend {

giterated-daemon/src/backend/mod.rs

View file
@@ -18,7 +18,7 @@ use giterated_models::instance::{
18 18 use giterated_models::repository::{
19 19 IssueLabel, Repository, RepositoryFileInspectRequest, RepositoryIssue,
20 20 RepositoryIssueLabelsRequest, RepositoryIssuesCountRequest, RepositoryIssuesRequest,
21 RepositorySummary, RepositoryTreeEntry, RepositoryFileFromIdRequest, RepositoryFile, RepositoryDiffRequest, RepositoryDiff,
21 RepositorySummary, RepositoryTreeEntry, RepositoryFileFromIdRequest, RepositoryFile, RepositoryDiffRequest, RepositoryDiff, Commit, RepositoryCommitBeforeRequest,
22 22 };
23 23 use giterated_models::settings::AnySetting;
24 24 use giterated_models::user::User;
@@ -49,6 +49,12 @@ pub trait RepositoryBackend {
49 49 repository: &Repository,
50 50 request: &RepositoryDiffRequest,
51 51 ) -> Result<RepositoryDiff, Error>;
52 async fn repository_commit_before(
53 &mut self,
54 requester: Option<&User>,
55 repository: &Repository,
56 request: &RepositoryCommitBeforeRequest,
57 ) -> Result<Commit, Error>;
52 58 async fn get_value(
53 59 &mut self,
54 60 user: &Repository,

giterated-daemon/src/database_backend/handler.rs

View file
@@ -8,7 +8,7 @@ use giterated_models::{
8 8 operation::{AnyOperation, GiteratedOperation},
9 9 repository::{
10 10 DefaultBranch, Description, LatestCommit, Repository, RepositoryFileInspectRequest,
11 RepositoryInfoRequest, RepositorySummary, RepositoryView, Visibility, RepositoryFile, RepositoryFileFromIdRequest, RepositoryDiff, RepositoryDiffRequest,
11 RepositoryInfoRequest, RepositorySummary, RepositoryView, Visibility, RepositoryFile, RepositoryFileFromIdRequest, RepositoryDiff, RepositoryDiffRequest, RepositoryCommitBeforeRequest, Commit,
12 12 },
13 13 settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError},
14 14 user::{User, UserRepositoriesRequest},
@@ -307,6 +307,34 @@ pub fn repository_diff(
307 307 }.boxed()
308 308 }
309 309
310 pub fn repository_commit_before(
311 object: &Repository,
312 operation: RepositoryCommitBeforeRequest,
313 state: DatabaseBackend,
314 ) -> BoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> {
315 let object = object.clone();
316
317 async move {
318 let object = state
319 .get_object::<Repository>(&object.to_string())
320 .await
321 .unwrap();
322
323 let mut repository_backend = state.repository_backend.lock().await;
324 let file = repository_backend
325 .repository_commit_before(
326 None,
327 object.object(),
328 &operation,
329 )
330 .await
331 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
332 drop(repository_backend);
333
334 Ok(file)
335 }.boxed()
336 }
337
310 338 pub fn repository_get_value(
311 339 object: &Repository,
312 340 operation: GetValue<AnyValue<Repository>>,

giterated-daemon/src/database_backend/mod.rs

View file
@@ -18,7 +18,7 @@ use crate::backend::{RepositoryBackend, UserBackend};
18 18
19 19 use self::handler::{
20 20 repository_get_setting, repository_get_value, repository_info, repository_set_setting,
21 user_get_repositories, user_get_setting, user_get_value, user_set_setting, OperationHandlers, repository_file_from_id, repository_diff,
21 user_get_repositories, user_get_setting, user_get_value, user_set_setting, OperationHandlers, repository_file_from_id, repository_diff, repository_commit_before,
22 22 };
23 23
24 24 #[derive(Clone, Debug)]
@@ -119,6 +119,7 @@ impl ObjectBackend for DatabaseBackend {
119 119 .insert(repository_info)
120 120 .insert(repository_file_from_id)
121 121 .insert(repository_diff)
122 .insert(repository_commit_before)
122 123 .insert(repository_get_value)
123 124 .insert(repository_get_setting)
124 125 .insert(repository_set_setting);
@@ -257,7 +258,7 @@ mod test {
257 258
258 259 use giterated_models::repository::{
259 260 Description, Repository, RepositoryFileInspectRequest, RepositorySummary,
260 RepositoryTreeEntry, RepositoryFileFromIdRequest, RepositoryFile, RepositoryDiff, RepositoryDiffRequest
261 RepositoryTreeEntry, RepositoryFileFromIdRequest, RepositoryFile, RepositoryDiff, RepositoryDiffRequest, RepositoryCommitBeforeRequest, Commit
261 262 };
262 263 use giterated_models::settings::AnySetting;
263 264 use giterated_models::user::{DisplayName, User};
@@ -359,6 +360,14 @@ mod test {
359 360 ) -> Result<RepositoryDiff, Error> {
360 361 todo!()
361 362 }
363 async fn repository_commit_before(
364 &mut self,
365 requester: Option<&User>,
366 repository: &Repository,
367 request: &RepositoryCommitBeforeRequest,
368 ) -> Result<Commit, Error> {
369 todo!()
370 }
362 371 async fn get_value(
363 372 &mut self,
364 373 _repository: &Repository,

giterated-models/src/repository/operations.rs

View file
@@ -7,7 +7,7 @@ use crate::{
7 7 operation::GiteratedOperation,
8 8 };
9 9
10 use super::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry, RepositoryView, RepositoryFile, RepositoryDiff};
10 use super::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry, RepositoryView, RepositoryFile, RepositoryDiff, Commit};
11 11
12 12 /// A request to get a repository's information.
13 13 ///
@@ -67,6 +67,23 @@ impl GiteratedOperation<Repository> for RepositoryDiffRequest {
67 67 type Failure = RepositoryError;
68 68 }
69 69
70 /// A request to get the commit before the one with the passed id
71 ///
72 /// # Authentication
73 /// - Instance Authentication
74 /// - Validate request against the `issued_for` public key
75 /// - Validate User token against the user's instance's public key
76 /// # Authorization
77 /// - User Authorization
78 /// - Potential User permissions checks
79 #[derive(Clone, Debug, Serialize, Deserialize)]
80 pub struct RepositoryCommitBeforeRequest(pub String);
81
82 impl GiteratedOperation<Repository> for RepositoryCommitBeforeRequest {
83 type Success = Commit;
84 type Failure = RepositoryError;
85 }
86
70 87 #[derive(Clone, Debug, Serialize, Deserialize)]
71 88 pub struct RepositoryIssuesCountRequest;
72 89
@@ -163,6 +180,13 @@ impl<B: ObjectBackend + std::fmt::Debug> Object<'_, Repository, B> {
163 180 self.request::<RepositoryDiffRequest>(RepositoryDiffRequest { old_id, new_id }).await
164 181 }
165 182
183 pub async fn commit_before(
184 &mut self,
185 id: String,
186 ) -> Result<Commit, OperationError<RepositoryError>> {
187 self.request::<RepositoryCommitBeforeRequest>(RepositoryCommitBeforeRequest(id)).await
188 }
189
166 190 // pub async fn issues_count(&mut self) -> Result<u64, OperationError<RepositoryError>> {
167 191 // self.request::<RepositoryIssuesCountRequest>(RepositoryIssuesCountRequest)
168 192 // .await