diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/database.rs | 173 | ||||
| -rw-r--r-- | src/main.rs | 16 | 
2 files changed, 103 insertions, 86 deletions
| diff --git a/src/database.rs b/src/database.rs index 2c1c0c8..f23fcd4 100644 --- a/src/database.rs +++ b/src/database.rs @@ -16,7 +16,7 @@  // along with Reflectub. If not, see <https://www.gnu.org/licenses/>. -use sqlx::{self, ConnectOptions, Connection, Executor, Row}; +use rusqlite::{self, OptionalExtension};  use thiserror;  use crate::github; @@ -54,59 +54,66 @@ impl From<&github::Repo> for Repo {  #[derive(Debug, thiserror::Error)]  pub enum Error {      #[error("database error")] -    Db(#[from] sqlx::Error), +    Db(#[from] rusqlite::Error),  }  #[derive(Debug)]  pub struct Db { -    connection: sqlx::SqliteConnection, +    connection: rusqlite::Connection,  }  impl Db {      /// Open a connection to the database. -    pub async fn connect(path: &str) -> Result<Self, Error> { +    pub fn connect(path: &str) -> Result<Self, Error> {          Ok(              Db { -                connection: sqlx::sqlite::SqliteConnectOptions::new() -                    .filename(path) -                    .create_if_missing(true) -                    .connect() -                    .await?, +                connection: rusqlite::Connection::open_with_flags( +                    path, +                    rusqlite::OpenFlags::SQLITE_OPEN_CREATE, +                )?,              }          )      }      /// Initialise the database with tables and indexes. -    pub async fn create(&mut self) -> Result<(), Error> { -        let mut tx = self.connection.begin().await?; - -        tx.execute(r#" -            CREATE TABLE IF NOT EXISTS repositories ( -                id INTEGER PRIMARY KEY, -                name TEXT NOT NULL, -                description TEXT, -                updated_at TEXT NOT NULL -            ); -        "#).await?; - -        tx.execute(r#" -            CREATE UNIQUE INDEX IF NOT EXISTS idx_repositories_id -                ON repositories (id); -        "#).await?; - -        tx.commit().await?; +    pub fn create(&mut self) -> Result<(), Error> { +        let tx = self.connection.transaction()?; + +        tx.execute( +            r#" +                CREATE TABLE IF NOT EXISTS repositories ( +                    id INTEGER PRIMARY KEY, +                    name TEXT NOT NULL, +                    description TEXT, +                    updated_at TEXT NOT NULL +                ); +            "#, +            [], +        )?; + +        tx.execute( +            r#" +                CREATE UNIQUE INDEX IF NOT EXISTS idx_repositories_id +                    ON repositories (id); +            "#, +            [], +        )?; + +        tx.commit()?;          Ok(())      }      /// Get a repository by its ID.      /// -    /// Returns a `sqlx::Error::RowNotFound` error if the row doesn't exist. -    pub async fn repo_get(&mut self, id: i64) -> Result<Repo, Error> { -        let mut tx = self.connection.begin().await?; +    /// Returns a `rusqlite::Error::QueryReturnedNoRows` error if the row +    /// doesn't exist. +    pub fn repo_get(&mut self, id: i64) -> Result<Repo, Error> { +        let tx = self.connection.transaction()?; -        let row = sqlx::query(r#" +        let repo = tx.query_row( +            r#"              SELECT                  id,                  name, @@ -114,41 +121,45 @@ impl Db {                  updated_at              FROM repositories              WHERE id = ? -        "#) -            .bind(id) -            .fetch_one(&mut tx) -            .await?; - -        tx.commit().await?; - -        Ok( -            Repo { -                id: row.get(0), -                name: Some(row.get(1)), -                description: row.get(2), -                updated_at: Some(row.get(3)), -            } -        ) +            "#, +            [id], +            |row| { +                Ok( +                    Repo { +                        id: row.get(0)?, +                        name: Some(row.get(1)?), +                        description: row.get(2)?, +                        updated_at: Some(row.get(3)?), +                    } +                ) +            }, +        )?; + +        tx.commit()?; + +        Ok(repo)      }      /// Insert a new repository. -    pub async fn repo_insert(&mut self, repo: Repo) -> Result<(), Error> { -        let mut tx = self.connection.begin().await?; +    pub fn repo_insert(&mut self, repo: Repo) -> Result<(), Error> { +        let tx = self.connection.transaction()?; -        sqlx::query(r#" +        tx.execute( +            r#"              INSERT INTO repositories                  (id, name, description, updated_at)                  VALUES                  (?, ?, ?, ?) -        "#) -            .bind(repo.id) -            .bind(&repo.name) -            .bind(&repo.description) -            .bind(&repo.updated_at) -            .execute(&mut tx) -            .await?; +            "#, +            rusqlite::params![ +                repo.id, +                &repo.name, +                &repo.description, +                &repo.updated_at, +            ], +        )?; -        tx.commit().await?; +        tx.commit()?;          Ok(())      } @@ -157,53 +168,59 @@ impl Db {      ///      /// Compares the `updated_at` field to find out whether the repository was      /// updated. -    pub async fn repo_is_updated( +    pub fn repo_is_updated(          &mut self,          repo: &Repo,      ) -> Result<bool, Error> { -        let mut tx = self.connection.begin().await?; +        let tx = self.connection.transaction()?; -        let is_updated = match sqlx::query(r#" +        let is_updated = match tx.query_row( +            r#"              SELECT 1              FROM repositories              WHERE id = ?                  AND datetime(updated_at) < datetime(?) -        "#) -            .bind(repo.id) -            .bind(&repo.updated_at) -            .fetch_optional(&mut tx) -            .await +            "#, +            rusqlite::params![ +                repo.id, +                &repo.updated_at, +            ], +            |row| row.get::<usize, u8>(0), +        ) +            .optional()          {              Ok(Some(_)) => Ok(true),              Ok(None) => Ok(false),              Err(e) => Err(e.into()),          }; -        tx.commit().await?; +        tx.commit()?;          is_updated      }      /// Update an existing repository. -    pub async fn repo_update(&mut self, repo: &Repo) -> Result<(), Error> { -        let mut tx = self.connection.begin().await?; +    pub fn repo_update(&mut self, repo: &Repo) -> Result<(), Error> { +        let tx = self.connection.transaction()?; -        sqlx::query(r#" +        tx.execute( +            r#"              UPDATE repositories              SET                  name = ?,                  description = ?,                  updated_at = ?              WHERE id = ? -        "#) -            .bind(&repo.name) -            .bind(&repo.description) -            .bind(&repo.updated_at) -            .bind(repo.id) -            .execute(&mut tx) -            .await?; - -        tx.commit().await?; +            "#, +            rusqlite::params![ +                &repo.name, +                &repo.description, +                &repo.updated_at, +                repo.id, +            ], +        )?; + +        tx.commit()?;          Ok(())      } diff --git a/src/main.rs b/src/main.rs index 6eb4492..3e17c06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ use filetime;  // use futures::{self, executor, future};  use getopts::Options;  use parse_size::parse_size; -use sqlx; +use rusqlite;  use tokio;  use tokio_stream::StreamExt; @@ -127,12 +127,12 @@ async fn run() -> anyhow::Result<()> {      let db = Arc::new(          tokio::sync::Mutex::new( -            database::Db::connect(&database_file).await?, +            database::Db::connect(&database_file)?,          )      );      db.lock().await -        .create().await?; +        .create()?;      // let mut joins = futures::stream::FuturesUnordered::new();      let mut joins = Vec::with_capacity(repos.len()); @@ -206,27 +206,27 @@ async fn process_repo(      let path = clone_path(&mirror_root, &repo);      let db_repo = database::Repo::from(repo); -    match db.repo_get(id).await { +    match db.repo_get(id) {          // If we've already seen the repo and it's been updated, fetch the          // latest.          Ok(current_repo) => { -            if db.repo_is_updated(&db_repo).await? { +            if db.repo_is_updated(&db_repo)? {                  update(&path, ¤t_repo, &repo)?; -                db.repo_update(&db_repo).await?; +                db.repo_update(&db_repo)?;              }          },          // If the repo doesn't exist, mirror it and store it in the          // database. -        Err(database::Error::Db(sqlx::Error::RowNotFound)) => { +        Err(database::Error::Db(rusqlite::Error::QueryReturnedNoRows)) => {              mirror(                  &path,                  &repo,                  base_cgitrc.as_ref(),              )?; -            db.repo_insert(db_repo).await?; +            db.repo_insert(db_repo)?;          },          Err(e) => anyhow::bail!(e), | 
