global db instance, error handling and file stuff

This commit is contained in:
Jamie 2021-10-02 17:57:02 -07:00
parent 7b144525ed
commit 6e658b9fcf
12 changed files with 116 additions and 112 deletions

28
src-tauri/Cargo.lock generated
View file

@ -54,9 +54,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.42"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
[[package]]
name = "arrayref"
@ -3349,6 +3349,7 @@ dependencies = [
name = "sd"
version = "0.1.0"
dependencies = [
"anyhow",
"cargo-edit",
"chrono",
"crossbeam",
@ -3357,6 +3358,7 @@ dependencies = [
"futures",
"int-enum",
"log",
"once_cell",
"rebind",
"refinery",
"ring 0.17.0-alpha.10",
@ -3367,6 +3369,7 @@ dependencies = [
"sha256",
"snafu",
"sqlx",
"strum 0.21.0",
"tauri",
"tauri-build",
]
@ -3969,6 +3972,15 @@ version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
[[package]]
name = "strum"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
dependencies = [
"strum_macros 0.21.1",
]
[[package]]
name = "strum_macros"
version = "0.8.0"
@ -3991,6 +4003,18 @@ dependencies = [
"syn 1.0.74",
]
[[package]]
name = "strum_macros"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec"
dependencies = [
"heck",
"proc-macro2",
"quote 1.0.9",
"syn 1.0.74",
]
[[package]]
name = "subprocess"
version = "0.2.8"

View file

@ -30,7 +30,10 @@ refinery = { version = "0.6.0", features = ["rusqlite"] }
sqlx = { version = "0.5.7", features = ["sqlite"] }
sea-orm = { version = "^0", features = [ "sqlx-sqlite", "runtime-async-std-rustls", "macros", "debug-print" ], default-features = false }
env_logger = "0.9.0"
# libusb = "0.3.0"
# libusb-sys = "0.2.3"
anyhow = "1.0.44"
once_cell = "1.8.0"
strum = { version = "0.21.0", features = ["derive"] }
snafu = "0.6.10"
log = "0.4.14"

View file

@ -1,13 +1,24 @@
// use crate::filesystem::checksum;
use crate::filesystem::reader;
use crate::db;
use crate::filesystem::{init, reader};
use anyhow::Result;
use once_cell::sync::OnceCell;
use sea_orm::DatabaseConnection;
use tauri::InvokeError;
pub static DB_INSTANCE: OnceCell<DatabaseConnection> = OnceCell::new();
async fn init_db_instance() -> Result<()> {
let db = db::connection::get_connection().await?;
if DB_INSTANCE.get().is_none() {
DB_INSTANCE.set(db).unwrap_or_default();
}
Ok(())
}
#[tauri::command(async)]
pub async fn read_file_command(path: &str) -> Result<String, InvokeError> {
let file = reader::read_file(path)
.await
.map_err(|error| InvokeError::from(format!("Failed to read file: {}", error)))?;
pub async fn read_file_command(path: &str) -> Result<String, String> {
init_db_instance().await.map_err(|e| e.to_string())?;
let file = reader::path(path).await.map_err(|e| e.to_string());
println!("file: {:?}", file);

View file

@ -1,4 +1,5 @@
use crate::app::config;
use anyhow::{Context, Result};
use rusqlite::Connection;
use sea_orm::{Database, DatabaseConnection, DbErr};
// use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode};

View file

@ -24,8 +24,8 @@ pub struct Model {
pub name: String,
pub extension: String,
pub size_in_bytes: String,
pub library_id: String,
pub directory_id: String,
pub library_id: u32,
pub directory_id: Option<u32>,
// #[sea_orm(column_type = "Int")]
// pub encryption: crypto::Encryption,
// ownership

View file

@ -34,8 +34,8 @@ CREATE TABLE IF NOT EXISTS files (
date_modified DATE NOT NULL DEFAULT (datetime('now')),
date_indexed DATE NOT NULL DEFAULT (datetime('now')),
library_id INTEGER NOT NULL,
storage_device_id INTEGER NOT NULL,
directory_id INTEGER NOT NULL,
storage_device_id INTEGER,
directory_id INTEGER,
capture_device_id INTEGER,
parent_file_id INTEGER,
FOREIGN KEY(library_id) REFERENCES libraries(id),

View file

@ -1,14 +0,0 @@
use sea_orm::DbErr;
use snafu::Snafu;
use std::{io, path::PathBuf};
#[derive(Debug, Snafu)]
pub enum Error {
#[snafu(display("Unable to read configuration from {}: {}", path, source))]
DatabaseConnectionResult { source: DbErr, path: String },
#[snafu(display("Unable to write result to {}: {}", path.display(), source))]
WriteResult { source: io::Error, path: PathBuf },
}
pub type Result<T, E = Error> = std::result::Result<T, E>;

View file

@ -1,15 +1,18 @@
use anyhow::Result;
use libusb;
pub async fn discover_storage_devices () => Result<()> {
let mut context = libusb::Context::new().unwrap();
pub async fn discover_storage_devices() -> Result<()> {
let mut context = libusb::Context::new().unwrap();
for mut device in context.devices().unwrap().iter() {
let device_desc = device.device_descriptor().unwrap();
for mut device in context.devices().unwrap().iter() {
let device_desc = device.device_descriptor().unwrap();
println!("Bus {:03} Device {:03} ID {:04x}:{:04x}",
device.bus_number(),
device.address(),
device_desc.vendor_id(),
device_desc.product_id());
}
}
println!(
"Bus {:03} Device {:03} ID {:04x}:{:04x}",
device.bus_number(),
device.address(),
device_desc.vendor_id(),
device_desc.product_id()
);
}
}

View file

@ -1,19 +1,34 @@
use crate::db::connection;
use crate::db::entity::library;
use sea_orm::entity::*;
use sea_orm::DbErr;
use sea_orm::QueryFilter;
use crate::db::{connection, entity::library};
use anyhow::{bail, Result};
use sea_orm::{entity::*, DatabaseConnection, QueryFilter};
use strum::Display;
pub async fn init_library() -> Result<(), Box<DbErr>> {
let db = connection::get_connection().await?;
#[derive(Display)]
pub enum InitError {
LibraryNotFound,
}
let existing_libs = library::Entity::find()
pub async fn get_primary_library(db: &DatabaseConnection) -> Result<library::Model> {
// get library entity by is_primary column, should be unique
let mut existing_libs = library::Entity::find()
.filter(library::Column::IsPrimary.eq(true))
.all(&db)
.await
.unwrap();
.await?;
// return library
if existing_libs.len() == 0 {
bail!(InitError::LibraryNotFound.to_string());
} else {
Ok(existing_libs.swap_remove(0))
}
}
pub async fn init_library() -> Result<()> {
let db = connection::get_connection().await?;
let library = get_primary_library(&db).await;
// if no library create one now
if library.is_err() {
let library = library::ActiveModel {
name: Set("Primary".to_owned()),
is_primary: Set(true),
@ -22,11 +37,9 @@ pub async fn init_library() -> Result<(), Box<DbErr>> {
let library = library.save(&db).await?;
println!("created library {:?}", library);
println!("created library {:?}", &library);
} else {
let existing_lib = &existing_libs[0];
println!("library loaded {:?}", existing_lib);
println!("library loaded {:?}", library.unwrap());
};
Ok(())
}

View file

@ -1,70 +1,44 @@
use crate::commands::DB_INSTANCE;
use crate::db;
use crate::db::entity::file;
use crate::filesystem::checksum;
use crate::filesystem::{checksum, init};
use crate::util::time;
use anyhow::{Context, Result};
use sea_orm::entity::*;
use sea_orm::QueryFilter;
use std::ffi::OsStr;
use std::{fs, io, path, path::PathBuf};
// use crate::error::*;
use sea_orm::DbErr;
use snafu::{ResultExt, Snafu};
#[derive(Debug, Snafu)]
pub enum Error {
#[snafu(display("Unable to read configuration from {}: {}", path, source))]
DatabaseConnectionResult { source: DbErr, path: String },
#[snafu(display("Unable to read file metadata {}: {}", path.display(), source))]
ReadMetadata { source: io::Error, path: PathBuf },
#[snafu(display("Unable to check existing file {}: {}", meta_checksum, source))]
ExistingFileError {
source: DbErr,
meta_checksum: String,
},
#[snafu(display("Unable to check existing file {}", source))]
MetaChecksumError { source: io::Error },
use std::{fs, path};
pub enum ReaderError {
FailedToGetPrimaryLibrary,
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
pub async fn path(path: &str) -> Result<()> {
let db = db::connection::get_connection()
.await
.context(DatabaseConnectionResult { path })?;
let db = DB_INSTANCE.get().unwrap();
let path_buff = path::PathBuf::from(path);
let metadata = fs::metadata(&path).context(ReadMetadata { path: &path_buff })?;
let metadata = fs::metadata(&path)?;
if metadata.is_dir() {
// read_dir().await?;
} else {
read_file(&path, db, path_buff, metadata).await?;
read_file(&path, path_buff, metadata).await?;
}
Ok(())
}
// Read a file from path returning the File struct
// Generates meta checksum and extracts metadata
pub async fn read_file(
path: &str,
db: sea_orm::DatabaseConnection,
path_buff: path::PathBuf,
metadata: fs::Metadata,
) -> Result<()> {
pub async fn read_file(path: &str, path_buff: path::PathBuf, metadata: fs::Metadata) -> Result<()> {
let db = DB_INSTANCE.get().unwrap();
let size = metadata.len();
let meta_checksum =
checksum::create_meta_checksum(path.to_owned(), size).context(MetaChecksumError {})?;
let meta_checksum = checksum::create_meta_checksum(path.to_owned(), size)?;
let primary_library = init::get_primary_library(&db).await?;
let existing_files = file::Entity::find()
.filter(file::Column::MetaChecksum.contains(&meta_checksum))
.all(&db)
.await
.context(ExistingFileError {
meta_checksum: &meta_checksum,
})?;
.await?;
if existing_files.len() == 0 {
let file = file::ActiveModel {
@ -72,24 +46,15 @@ pub async fn read_file(
name: Set(extract_name(path_buff.file_name())),
extension: Set(extract_name(path_buff.extension())),
uri: Set(path.to_owned()),
library_id: Set(primary_library.id),
size_in_bytes: Set(size.to_string()),
date_created: Set(Some(
time::system_time_to_date_time(metadata.created()).unwrap(),
)),
date_modified: Set(Some(
time::system_time_to_date_time(metadata.modified()).unwrap(),
)),
date_indexed: Set(Some(
time::system_time_to_date_time(metadata.modified()).unwrap(),
)),
date_created: Set(Some(time::system_time_to_date_time(metadata.created())?)),
date_modified: Set(Some(time::system_time_to_date_time(metadata.modified())?)),
date_indexed: Set(Some(time::system_time_to_date_time(metadata.modified())?)),
..Default::default()
};
let file = file
.save(&db)
.await
.map_err(|error| println!("Failed to read file: {}", error))
.unwrap();
let file = file.save(&db).await?;
println!("FILE: {:?}", file);

View file

@ -7,7 +7,6 @@ mod app;
mod commands;
mod crypto;
mod db;
mod error;
mod filesystem;
mod util;
use crate::app::menu;

View file

@ -1,10 +1,9 @@
use anyhow::Result;
use chrono::NaiveDateTime;
use std::io;
use std::time::{SystemTime, UNIX_EPOCH};
pub fn system_time_to_date_time(
system_time: io::Result<SystemTime>,
) -> Result<NaiveDateTime, Box<dyn std::error::Error>> {
pub fn system_time_to_date_time(system_time: io::Result<SystemTime>) -> Result<NaiveDateTime> {
// extract system time or resort to current time if failure
let system_time = system_time.unwrap_or(SystemTime::now());
let std_duration = system_time.duration_since(UNIX_EPOCH)?;