mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 12:13:27 +00:00
global db instance, error handling and file stuff
This commit is contained in:
parent
7b144525ed
commit
6e658b9fcf
28
src-tauri/Cargo.lock
generated
28
src-tauri/Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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>;
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ mod app;
|
|||
mod commands;
|
||||
mod crypto;
|
||||
mod db;
|
||||
mod error;
|
||||
mod filesystem;
|
||||
mod util;
|
||||
use crate::app::menu;
|
||||
|
|
|
@ -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)?;
|
||||
|
|
Loading…
Reference in a new issue