mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-02 10:03:28 +00:00
errors
This commit is contained in:
parent
2ea36666bc
commit
7b144525ed
28
src-tauri/Cargo.lock
generated
28
src-tauri/Cargo.lock
generated
|
@ -1121,6 +1121,12 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.15.0"
|
||||
|
@ -3359,6 +3365,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"sha256",
|
||||
"snafu",
|
||||
"sqlx",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
|
@ -3669,6 +3676,27 @@ dependencies = [
|
|||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snafu"
|
||||
version = "0.6.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7"
|
||||
dependencies = [
|
||||
"doc-comment",
|
||||
"snafu-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snafu-derive"
|
||||
version = "0.6.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.74",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.1"
|
||||
|
|
|
@ -30,6 +30,8 @@ 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"
|
||||
snafu = "0.6.10"
|
||||
log = "0.4.14"
|
||||
|
||||
[features]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// use crate::filesystem::checksum;
|
||||
use crate::filesystem::file;
|
||||
use crate::filesystem::reader;
|
||||
|
||||
use tauri::InvokeError;
|
||||
|
||||
#[tauri::command(async)]
|
||||
pub async fn read_file_command(path: &str) -> Result<String, InvokeError> {
|
||||
let file = file::read_file(path)
|
||||
let file = reader::read_file(path)
|
||||
.await
|
||||
.map_err(|error| InvokeError::from(format!("Failed to read file: {}", error)))?;
|
||||
|
||||
|
|
|
@ -13,17 +13,48 @@ pub struct Model {
|
|||
pub id: u32,
|
||||
pub name: String,
|
||||
pub uri: String,
|
||||
pub watch: bool,
|
||||
pub calculated_size_in_bytes: Option<String>,
|
||||
pub calculated_file_count: Option<u32>,
|
||||
pub date_created: Option<NaiveDateTime>,
|
||||
pub date_modified: Option<NaiveDateTime>,
|
||||
pub date_indexed: Option<NaiveDateTime>,
|
||||
pub library_id: u32,
|
||||
pub storage_device_id: Option<u32>,
|
||||
pub parent_directory_id: Option<u32>,
|
||||
pub storage_device_id: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {}
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
StorageDevice,
|
||||
Library,
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Library => Entity::belongs_to(super::library::Entity)
|
||||
.from(Column::LibraryId)
|
||||
.to(super::library::Column::Id)
|
||||
.into(),
|
||||
Self::StorageDevice => Entity::belongs_to(super::storage_device::Entity)
|
||||
.from(Column::StorageDeviceId)
|
||||
.to(super::storage_device::Column::Id)
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::library::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Library.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::storage_device::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::StorageDevice.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
|
|
@ -24,6 +24,8 @@ pub struct Model {
|
|||
pub name: String,
|
||||
pub extension: String,
|
||||
pub size_in_bytes: String,
|
||||
pub library_id: String,
|
||||
pub directory_id: String,
|
||||
// #[sea_orm(column_type = "Int")]
|
||||
// pub encryption: crypto::Encryption,
|
||||
// ownership
|
||||
|
@ -39,13 +41,24 @@ pub struct Model {
|
|||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Library,
|
||||
Directory,
|
||||
StorageDevice,
|
||||
CaptureDevice,
|
||||
ParentFile,
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Library => Entity::belongs_to(super::library::Entity)
|
||||
.from(Column::LibraryId)
|
||||
.to(super::library::Column::Id)
|
||||
.into(),
|
||||
Self::Directory => Entity::belongs_to(super::dir::Entity)
|
||||
.from(Column::DirectoryId)
|
||||
.to(super::dir::Column::Id)
|
||||
.into(),
|
||||
Self::StorageDevice => Entity::belongs_to(super::storage_device::Entity)
|
||||
.from(Column::StorageDeviceId)
|
||||
.to(super::storage_device::Column::Id)
|
||||
|
@ -54,9 +67,23 @@ impl RelationTrait for Relation {
|
|||
.from(Column::CaptureDeviceId)
|
||||
.to(super::capture_device::Column::Id)
|
||||
.into(),
|
||||
Self::ParentFile => Entity::belongs_to(Entity)
|
||||
.from(Column::ParentFileId)
|
||||
.to(Column::Id)
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Related<super::library::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Library.def()
|
||||
}
|
||||
}
|
||||
impl Related<super::dir::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Directory.def()
|
||||
}
|
||||
}
|
||||
impl Related<super::storage_device::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::StorageDevice.def()
|
||||
|
@ -67,5 +94,10 @@ impl Related<super::capture_device::Entity> for Entity {
|
|||
Relation::CaptureDevice.def()
|
||||
}
|
||||
}
|
||||
impl Related<Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::ParentFile.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
|
|
@ -35,7 +35,7 @@ CREATE TABLE IF NOT EXISTS files (
|
|||
date_indexed DATE NOT NULL DEFAULT (datetime('now')),
|
||||
library_id INTEGER NOT NULL,
|
||||
storage_device_id INTEGER NOT NULL,
|
||||
directory_id INTEGER,
|
||||
directory_id INTEGER NOT NULL,
|
||||
capture_device_id INTEGER,
|
||||
parent_file_id INTEGER,
|
||||
FOREIGN KEY(library_id) REFERENCES libraries(id),
|
||||
|
@ -48,6 +48,7 @@ CREATE TABLE IF NOT EXISTS directories (
|
|||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT,
|
||||
uri TEXT NOT NULL,
|
||||
watch BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
encryption INTEGER DEFAULT 0,
|
||||
calculated_size_in_bytes TEXT DEFAULT "0",
|
||||
calculated_file_count INTEGER DEFAULT 0,
|
||||
|
|
14
src-tauri/src/error.rs
Normal file
14
src-tauri/src/error.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
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>;
|
|
@ -18,7 +18,7 @@ fn sha256_digest<R: Read>(mut reader: R) -> io::Result<Digest> {
|
|||
Ok(context.finish())
|
||||
}
|
||||
|
||||
pub async fn create_hash(path: &str) -> io::Result<String> {
|
||||
pub async fn create_buffer_checksum(path: &str) -> io::Result<String> {
|
||||
let start = Instant::now();
|
||||
// read file as buffer and convert to digest
|
||||
let digest = sha256_digest(BufReader::new(std::fs::File::open(path)?))?;
|
||||
|
@ -28,6 +28,6 @@ pub async fn create_hash(path: &str) -> io::Result<String> {
|
|||
Ok(hex)
|
||||
}
|
||||
|
||||
pub fn create_meta_hash(uri: String, size_in_bytes: u64) -> io::Result<String> {
|
||||
pub fn create_meta_checksum(uri: String, size_in_bytes: u64) -> io::Result<String> {
|
||||
Ok(digest(format!("{}{}", uri, size_in_bytes.to_string())))
|
||||
}
|
||||
|
|
15
src-tauri/src/filesystem/device.rs
Normal file
15
src-tauri/src/filesystem/device.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use libusb;
|
||||
|
||||
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();
|
||||
|
||||
println!("Bus {:03} Device {:03} ID {:04x}:{:04x}",
|
||||
device.bus_number(),
|
||||
device.address(),
|
||||
device_desc.vendor_id(),
|
||||
device_desc.product_id());
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
use chrono::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Directory {
|
||||
// identity
|
||||
pub id: Option<u64>,
|
||||
pub name: String,
|
||||
// calculations
|
||||
pub calculated_size_in_bytes: u64,
|
||||
pub calculated_file_count: u32,
|
||||
// ownership
|
||||
pub user_id: Option<u64>,
|
||||
pub storage_device_id: Option<u64>,
|
||||
pub parent_directory_id: Option<u32>,
|
||||
// date
|
||||
pub date_created: DateTime<Utc>,
|
||||
pub date_modified: DateTime<Utc>,
|
||||
pub date_indexed: DateTime<Utc>,
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
pub mod checksum;
|
||||
pub mod directory;
|
||||
pub mod file;
|
||||
// pub mod device;
|
||||
pub mod init;
|
||||
pub mod reader;
|
||||
|
|
|
@ -1,31 +1,70 @@
|
|||
use crate::db;
|
||||
use crate::db::entity::file;
|
||||
use crate::filesystem::checksum;
|
||||
use crate::util::time;
|
||||
use sea_orm::entity::*;
|
||||
use sea_orm::QueryFilter;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path;
|
||||
use std::{fs, io, path, path::PathBuf};
|
||||
// use crate::error::*;
|
||||
use sea_orm::DbErr;
|
||||
use snafu::{ResultExt, Snafu};
|
||||
|
||||
use crate::db::entity::file;
|
||||
#[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 },
|
||||
}
|
||||
|
||||
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 path_buff = path::PathBuf::from(path);
|
||||
let metadata = fs::metadata(&path).context(ReadMetadata { path: &path_buff })?;
|
||||
|
||||
if metadata.is_dir() {
|
||||
// read_dir().await?;
|
||||
} else {
|
||||
read_file(&path, db, 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) -> io::Result<()> {
|
||||
let db = db::connection::get_connection().await.unwrap();
|
||||
|
||||
let path_buff = path::PathBuf::from(path);
|
||||
let metadata = fs::metadata(&path)?;
|
||||
|
||||
pub async fn read_file(
|
||||
path: &str,
|
||||
db: sea_orm::DatabaseConnection,
|
||||
path_buff: path::PathBuf,
|
||||
metadata: fs::Metadata,
|
||||
) -> Result<()> {
|
||||
let size = metadata.len();
|
||||
let meta_checksum = checksum::create_meta_hash(path.to_owned(), size)?;
|
||||
let meta_checksum =
|
||||
checksum::create_meta_checksum(path.to_owned(), size).context(MetaChecksumError {})?;
|
||||
|
||||
let existing_files = file::Entity::find()
|
||||
.filter(file::Column::MetaChecksum.contains(&meta_checksum))
|
||||
.all(&db)
|
||||
.await
|
||||
.unwrap();
|
||||
.context(ExistingFileError {
|
||||
meta_checksum: &meta_checksum,
|
||||
})?;
|
||||
|
||||
if existing_files.len() == 0 {
|
||||
let file = file::ActiveModel {
|
||||
|
@ -69,8 +108,3 @@ fn extract_name(os_string: Option<&OsStr>) -> String {
|
|||
.unwrap_or_default()
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
// pub async fn commit_file(file: &File) -> Result<(), InvokeError> {
|
||||
// let connection = db::connection::get_connection()?;
|
||||
|
||||
// });
|
|
@ -7,6 +7,7 @@ mod app;
|
|||
mod commands;
|
||||
mod crypto;
|
||||
mod db;
|
||||
mod error;
|
||||
mod filesystem;
|
||||
mod util;
|
||||
use crate::app::menu;
|
||||
|
@ -25,6 +26,8 @@ fn main() {
|
|||
// init filesystem and create library if missing
|
||||
block_on(filesystem::init::init_library()).unwrap();
|
||||
|
||||
// block_on(filesystem::device::discover_storage_devices()).unwrap();
|
||||
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::read_file_command,
|
||||
|
|
Loading…
Reference in a new issue