From fd22fb98e5b8257145cfd3f0d1bbc60735d02450 Mon Sep 17 00:00:00 2001 From: boxbeam Date: Tue, 9 Jan 2024 12:16:48 -0500 Subject: [PATCH] feat(db): Implement DAO for repositories (#1178) * feat: Implement DAO for repositories * Add method to get repository, add test * Apply suggestions * Make delete_repository take an ID instead of name * Return an error on failed update * Use anyhow error instead of custom error * Apply suggested changes * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../migrations/08-repositories-table/down.sql | 1 + .../migrations/08-repositories-table/up.sql | 7 + ee/tabby-db/src/lib.rs | 1 + ee/tabby-db/src/repositories.rs | 127 ++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 ee/tabby-db/migrations/08-repositories-table/down.sql create mode 100644 ee/tabby-db/migrations/08-repositories-table/up.sql create mode 100644 ee/tabby-db/src/repositories.rs diff --git a/ee/tabby-db/migrations/08-repositories-table/down.sql b/ee/tabby-db/migrations/08-repositories-table/down.sql new file mode 100644 index 000000000000..2c8ff6dd7983 --- /dev/null +++ b/ee/tabby-db/migrations/08-repositories-table/down.sql @@ -0,0 +1 @@ +DROP TABLE repositories; diff --git a/ee/tabby-db/migrations/08-repositories-table/up.sql b/ee/tabby-db/migrations/08-repositories-table/up.sql new file mode 100644 index 000000000000..684c071c2d8d --- /dev/null +++ b/ee/tabby-db/migrations/08-repositories-table/up.sql @@ -0,0 +1,7 @@ +CREATE TABLE repositories ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(255) NOT NULL, + git_url VARCHAR(255) NOT NULL, + CONSTRAINT `idx_name` UNIQUE (`name`) + CONSTRAINT `idx_git_url` UNIQUE (`git_url`) +); diff --git a/ee/tabby-db/src/lib.rs b/ee/tabby-db/src/lib.rs index 70c7f7128235..86a23a9c133d 100644 --- a/ee/tabby-db/src/lib.rs +++ b/ee/tabby-db/src/lib.rs @@ -10,6 +10,7 @@ mod invitations; mod job_runs; mod path; mod refresh_tokens; +mod repositories; mod users; use anyhow::Result; diff --git a/ee/tabby-db/src/repositories.rs b/ee/tabby-db/src/repositories.rs new file mode 100644 index 000000000000..48c03df310bc --- /dev/null +++ b/ee/tabby-db/src/repositories.rs @@ -0,0 +1,127 @@ +use anyhow::{anyhow, Result}; +use rusqlite::Row; + +use crate::DbConn; + +pub struct RepositoryDAO { + pub id: i32, + pub name: String, + pub git_url: String, +} + +impl RepositoryDAO { + fn new(id: i32, name: String, git_url: String) -> Self { + Self { id, name, git_url } + } + + fn from_row(row: &Row) -> Result { + Ok(Self::new(row.get(0)?, row.get(1)?, row.get(2)?)) + } +} + +impl DbConn { + pub async fn list_repositories_with_filter( + &self, + limit: Option, + skip_id: Option, + backwards: bool, + ) -> Result> { + let query = Self::make_pagination_query( + "repositories", + &["id", "name", "git_url"], + limit, + skip_id, + backwards, + ); + + self.conn + .call(move |c| { + let thing: Result> = c + .prepare(&query)? + .query_map([], RepositoryDAO::from_row)? + .map(|r| r.map_err(Into::into)) + .collect(); + Ok(thing) + }) + .await? + } + + pub async fn delete_repository(&self, id: i32) -> Result { + Ok(self + .conn + .call(move |c| { + let deleted = c + .execute("DELETE FROM repositories WHERE id=?", [id]) + .is_ok(); + Ok(deleted) + }) + .await?) + } + + pub async fn create_repository(&self, name: String, git_url: String) -> Result<()> { + Ok(self + .conn + .call(|c| { + c.execute( + "INSERT INTO repositories (name, git_url) VALUES (?, ?)", + [name, git_url], + )?; + Ok(()) + }) + .await?) + } + + pub async fn update_repository(&self, id: i32, name: String, git_url: String) -> Result<()> { + let updated = self + .conn + .call(move |c| { + let update_count = c.execute( + "UPDATE repositories SET git_url=?, name=? WHERE id=?", + (git_url, name, id), + )?; + Ok(update_count == 1) + }) + .await?; + if updated { + Ok(()) + } else { + Err(anyhow!("failed to update: repository not found")) + } + } +} + +#[cfg(test)] +mod tests { + use crate::DbConn; + + #[tokio::test] + async fn test_update_repository() { + let conn = DbConn::new_in_memory().await.unwrap(); + + // Insert new repository + conn.create_repository("test".into(), "testurl".into()) + .await + .unwrap(); + + // Test that the url can be retrieved + let repository = &conn + .list_repositories_with_filter(None, None, false) + .await + .unwrap()[0]; + assert_eq!(repository.git_url, "testurl"); + + // Update the repository + let id = repository.id; + conn.update_repository(id, "test2".into(), "testurl2".into()) + .await + .unwrap(); + + // Check the url was updated + let repository = &conn + .list_repositories_with_filter(None, None, false) + .await + .unwrap()[0]; + assert_eq!(repository.git_url, "testurl2"); + assert_eq!(repository.name, "test2"); + } +}