use std::path::{Path, PathBuf};
use rusqlite::Connection;
use crate::error::{Error, Result};
use crate::storage::schema;
const DEFAULT_DIRECTORY: &str = ".githubdw";
const DEFAULT_FILE_NAME: &str = "githubdw.db";
pub struct GithubDW {
connection: Connection,
database_path: PathBuf,
}
impl GithubDW {
pub fn open_default() -> Result<Self> {
Self::open(Self::default_database_path()?)
}
pub fn open(path: impl AsRef<Path>) -> Result<Self> {
let path = path.as_ref().to_path_buf();
if let Some(parent) = path.parent()
&& !parent.as_os_str().is_empty()
{
std::fs::create_dir_all(parent)?;
}
let mut connection = Connection::open(&path)?;
schema::init(&mut connection)?;
Ok(Self {
connection,
database_path: path,
})
}
pub fn open_in_memory() -> Result<Self> {
let mut connection = Connection::open_in_memory()?;
schema::init(&mut connection)?;
Ok(Self {
connection,
database_path: PathBuf::from(":memory:"),
})
}
pub fn default_database_path() -> Result<PathBuf> {
let home = dirs::home_dir()
.ok_or_else(|| Error::Config("could not determine home directory".into()))?;
Ok(home.join(DEFAULT_DIRECTORY).join(DEFAULT_FILE_NAME))
}
pub fn database_path(&self) -> &Path {
&self.database_path
}
pub fn connection(&self) -> &Connection {
&self.connection
}
pub fn connection_mut(&mut self) -> &mut Connection {
&mut self.connection
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn opens_at_explicit_path() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("test.db");
let warehouse = GithubDW::open(&path).expect("open warehouse");
assert!(path.exists());
assert_eq!(warehouse.database_path(), path.as_path());
}
#[test]
fn opens_in_memory() {
let warehouse = GithubDW::open_in_memory().expect("open in-memory");
let count: i64 = warehouse
.connection()
.query_row("SELECT COUNT(*) FROM config", [], |row| row.get(0))
.expect("query config");
assert!(count >= 4);
}
}