smashing errors

This commit is contained in:
Jamie 2021-12-24 04:24:12 -08:00
parent 5adb888926
commit fd745a4d36
24 changed files with 2869 additions and 513 deletions

View file

@ -177,9 +177,9 @@ dependencies = [
[[package]]
name = "async-process"
version = "1.2.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b21b63ab5a0db0369deb913540af2892750e42d949faacc7a61495ac418a1692"
checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6"
dependencies = [
"async-io",
"blocking",
@ -260,9 +260,9 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
[[package]]
name = "async-trait"
version = "0.1.51"
version = "0.1.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
dependencies = [
"proc-macro2",
"quote",
@ -360,12 +360,12 @@ dependencies = [
[[package]]
name = "bae"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec107f431ee3d8a8e45e6dd117adab769556ef463959e77bf6a4888d5fd500cf"
checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a"
dependencies = [
"heck",
"proc-macro-error 0.4.12",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
@ -441,9 +441,9 @@ dependencies = [
[[package]]
name = "blocking"
version = "1.0.2"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9"
checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427"
dependencies = [
"async-channel",
"async-task",
@ -905,20 +905,6 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "crossbeam"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
@ -1142,12 +1128,6 @@ 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"
@ -1208,19 +1188,6 @@ dependencies = [
"syn",
]
[[package]]
name = "env_logger"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "env_proxy"
version = "0.4.1"
@ -1667,7 +1634,7 @@ dependencies = [
"anyhow",
"heck",
"proc-macro-crate 1.1.0",
"proc-macro-error 1.0.4",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
@ -1714,9 +1681,9 @@ dependencies = [
[[package]]
name = "gloo-timers"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f"
checksum = "6f16c88aa13d2656ef20d1c042086b8767bbe2bdb62526894275a1b062161b2e"
dependencies = [
"futures-channel",
"futures-core",
@ -1797,7 +1764,7 @@ dependencies = [
"anyhow",
"heck",
"proc-macro-crate 1.1.0",
"proc-macro-error 1.0.4",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
@ -1888,12 +1855,6 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eee9694f83d9b7c09682fdb32213682939507884e5bcf227be9aff5d644b90dc"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "ico"
version = "0.1.0"
@ -2376,19 +2337,6 @@ dependencies = [
"void",
]
[[package]]
name = "nix"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188"
dependencies = [
"bitflags 1.3.2",
"cc",
"cfg-if 1.0.0",
"libc",
"memoffset",
]
[[package]]
name = "nodrop"
version = "0.1.14"
@ -2625,7 +2573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e23813b1bcb2d41a838849a2bbae40ae5c03c85ecabf04ba97086f438484714"
dependencies = [
"Inflector",
"proc-macro-error 1.0.4",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
@ -2928,45 +2876,19 @@ dependencies = [
"toml",
]
[[package]]
name = "proc-macro-error"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
dependencies = [
"proc-macro-error-attr 0.4.12",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr 1.0.4",
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn-mid",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
@ -3325,9 +3247,9 @@ dependencies = [
[[package]]
name = "rusqlite"
version = "0.25.3"
version = "0.25.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57adcf67c8faaf96f3248c2a7b419a0dbc52ebe36ba83dd57fe83827c1ea4eb3"
checksum = "5c4b1eaf239b47034fb450ee9cdedd7d0226571689d8823030c4b6c2cb407152"
dependencies = [
"bitflags 1.3.2",
"fallible-iterator",
@ -3352,9 +3274,9 @@ dependencies = [
[[package]]
name = "rust_decimal"
version = "1.17.0"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "353775f96a1f400edcca737f843cb201af3645912e741e64456a257c770173e8"
checksum = "71b5a9625a7e6060b23db692facf49082cc78889a7e6ac94a735356ae49db4b0"
dependencies = [
"arrayvec 0.5.2",
"num-traits",
@ -3448,6 +3370,33 @@ dependencies = [
"untrusted",
]
[[package]]
name = "sdcorelib"
version = "0.1.0"
dependencies = [
"anyhow",
"base64",
"bytesize",
"cargo-edit",
"chrono",
"data-encoding",
"futures",
"int-enum",
"log",
"once_cell",
"rebind",
"refinery",
"ring 0.17.0-alpha.10",
"rusqlite",
"sea-orm",
"serde",
"serde_json",
"sha256",
"sqlx",
"strum 0.21.0",
"walkdir",
]
[[package]]
name = "sea-orm"
version = "0.3.2"
@ -3717,9 +3666,9 @@ dependencies = [
[[package]]
name = "signal-hook"
version = "0.3.10"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1"
checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d"
dependencies = [
"libc",
"signal-hook-registry",
@ -3762,27 +3711,6 @@ 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",
"syn",
]
[[package]]
name = "socket2"
version = "0.4.2"
@ -3826,36 +3754,23 @@ version = "0.1.0"
dependencies = [
"anyhow",
"base64",
"bytesize",
"cargo-edit",
"chrono",
"cocoa",
"crossbeam",
"data-encoding",
"env_logger",
"futures",
"int-enum",
"libc",
"log",
"nix 0.23.0",
"objc",
"objc-foundation",
"once_cell",
"rebind",
"refinery",
"ring 0.17.0-alpha.10",
"rusqlite",
"sea-orm",
"sdcorelib",
"serde",
"serde_json",
"sha256",
"snafu",
"sqlx",
"strum 0.21.0",
"swift-rs",
"tauri",
"tauri-build",
"walkdir",
]
[[package]]
@ -4052,7 +3967,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [
"heck",
"proc-macro-error 1.0.4",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
@ -4150,17 +4065,6 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "syn-mid"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "system-deps"
version = "1.3.2"
@ -4977,9 +4881,9 @@ dependencies = [
[[package]]
name = "whoami"
version = "1.2.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c33ac5ee236a4efbf2c98967e12c6cc0c51d93a744159a52957ba206ae6ef5f7"
checksum = "524b58fa5a20a2fb3014dd6358b70e6579692a56ef6fce928834e488f42f65e8"
dependencies = [
"wasm-bindgen",
"web-sys",
@ -5175,7 +5079,7 @@ dependencies = [
"fastrand",
"futures",
"nb-connect",
"nix 0.17.0",
"nix",
"once_cell",
"polling",
"scoped-tls",

View file

@ -2,9 +2,9 @@
name = "spacedrive"
version = "0.1.0"
description = "The next gen private virtual filesystem."
authors = ["you"]
authors = ["NerdHouse, Inc.", "Jamie Pine"]
license = ""
repository = ""
repository = "https://github.com/jamiepine/spacedrive"
default-run = "spacedrive"
edition = "2018"
build = "src/build.rs"
@ -14,38 +14,26 @@ tauri-build = { version = "1.0.0-beta.3" }
swift-rs = "0.2.3"
[dependencies]
# Project dependencies
tauri = { version = "1.0.0-beta.8", features = ["api-all"] }
swift-rs = "0.2.3"
sdcorelib = { path = "../../../packages/core" }
# Universal Dependencies
anyhow = "1.0.44"
log = "0.4.14"
base64 = "0.13.0"
serde = { version = "1.0", features = ["derive"] }
chrono = { version = "0.4.0", features = ["serde"] }
strum = { version = "0.21.0", features = ["derive"] }
serde_json = "1.0"
futures = "0.3"
rebind = "0.2.1"
data-encoding = "2.3.2"
ring = "0.17.0-alpha.10"
chrono = { version = "0.4.0", features = ["serde"] }
crossbeam = "0.8.1"
cargo-edit = "0.8.0"
sha256 = "1.0.2"
int-enum = "0.4.0"
rusqlite = "0.25.3"
refinery = { version = "0.6.0", features = ["rusqlite"] }
sqlx = { version = "0.5.7", features = ["sqlite"] }
sea-orm = { version = "^0.3.1", features = [ "sqlx-sqlite", "runtime-async-std-rustls", "macros", "debug-print" ], default-features = false }
env_logger = "0.9.0"
# libusb-sys = "0.2.3"
anyhow = "1.0.44"
once_cell = "1.8.0"
walkdir = "^2.3.2"
strum = { version = "0.21.0", features = ["derive"] }
snafu = "0.6.10"
bytesize = "1.1.0"
libc = "0.2.103"
nix = "0.23.0"
log = "0.4.14"
objc = "0.2.7"
cocoa = "0.24.0"
objc-foundation = "0.1.1"
swift-rs = "0.2.3"
base64 = "0.13.0"
int-enum = "0.4.0"
[features]
default = [ "custom-protocol" ]

View file

@ -1,2 +0,0 @@
pub mod config;
pub mod menu;

View file

@ -1,14 +1,16 @@
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
mod app;
mod commands;
use crate::app::menu;
mod menu;
use sdcorelib;
use tauri::api::path;
fn main() {
tauri::Builder::default()
.setup(|_app| Ok(()))
.setup(|_app| {
let data_dir = path::data_dir().unwrap_or(std::path::PathBuf::from("./"));
sdcorelib::configure(data_dir);
Ok(())
})
.on_menu_event(|event| menu::handle_menu_event(event))
.invoke_handler(tauri::generate_handler![])
.menu(menu::get_menu())

View file

@ -4,7 +4,9 @@ import ReactDOM from 'react-dom';
ReactDOM.render(
<React.StrictMode>
<div style={{background:"red", display:"flex", flex:1}}>
hello
</div>
</React.StrictMode>,
document.getElementById('root')
);

2504
packages/core/Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,41 @@
[package]
name = "rs-core"
name = "sdcorelib"
version = "0.1.0"
edition = "2021"
description = "The next gen private virtual filesystem."
authors = ["NerdHouse, Inc.", "Jamie Pine"]
license = ""
repository = "https://github.com/jamiepine/spacedrive"
edition = "2018"
include = ["lib/**/*.rs"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "sdcorelib"
# crate-type = ["cdylib"]
# bench = false
path = "lib/main.rs"
[dependencies]
# Universal Dependencies
anyhow = "1.0.44"
log = "0.4.14"
base64 = "0.13.0"
serde = { version = "1.0", features = ["derive"] }
chrono = { version = "0.4.0", features = ["serde"] }
strum = { version = "0.21.0", features = ["derive"] }
serde_json = "1.0"
futures = "0.3"
rebind = "0.2.1"
data-encoding = "2.3.2"
ring = "0.17.0-alpha.10"
cargo-edit = "0.8.0"
sha256 = "1.0.2"
once_cell = "1.8.0"
int-enum = "0.4.0"
# Project dependencies
rusqlite = "0.25.3"
refinery = { version = "0.6.0", features = ["rusqlite"] }
sqlx = { version = "0.5.7", features = ["sqlite"] }
sea-orm = { version = "^0.3.1", features = [ "sqlx-sqlite", "runtime-async-std-rustls", "macros", "debug-print" ], default-features = false }
walkdir = "^2.3.2"
bytesize = "1.1.0"

View file

@ -1,29 +0,0 @@
use serde::Serialize;
use std::fs;
use tauri::api::path;
#[derive(Serialize)]
pub struct AppConfig {
pub primary_db: std::path::PathBuf,
pub data_dir: std::path::PathBuf,
pub file_type_thumb_dir: std::path::PathBuf,
}
// returns the app config struct with complete values
pub fn get_config() -> AppConfig {
let app_name = "SpaceDrive";
let data_dir = path::data_dir()
.unwrap_or(std::path::PathBuf::from("./"))
.join(app_name);
let file_type_thumb_dir = data_dir.join("file_icons");
// create the data directory if not exists
fs::create_dir_all(&data_dir).unwrap();
fs::create_dir_all(&file_type_thumb_dir).unwrap();
AppConfig {
primary_db: data_dir.join("primary.db3"),
data_dir,
file_type_thumb_dir,
}
}

View file

@ -1,66 +0,0 @@
use tauri::{CustomMenuItem, Menu, MenuItem, Submenu, WindowMenuEvent, Wry};
pub(crate) fn get_menu() -> Menu {
// let quit = CustomMenuItem::new("quit".to_string(), "Quit");
// let close = CustomMenuItem::new("close".to_string(), "Close");
// let jeff = CustomMenuItem::new("jeff".to_string(), "Jeff");
// let submenu = Submenu::new(
// "File",
// Menu::new().add_item(quit).add_item(close).add_item(jeff),
// );
let spacedrive = Submenu::new(
"SpaceDrive",
Menu::new()
.add_native_item(MenuItem::About("SpaceDrive".to_string()))
.add_native_item(MenuItem::Separator)
.add_native_item(MenuItem::Services)
.add_native_item(MenuItem::Separator)
.add_native_item(MenuItem::Hide)
.add_native_item(MenuItem::HideOthers)
.add_native_item(MenuItem::ShowAll)
.add_native_item(MenuItem::Separator)
.add_native_item(MenuItem::Quit),
);
let file = Submenu::new(
"File",
Menu::new()
.add_item(CustomMenuItem::new("quit".to_string(), "Quit"))
.add_item(CustomMenuItem::new("close".to_string(), "Close")),
);
let edit = Submenu::new(
"Edit",
Menu::new()
.add_item(CustomMenuItem::new("jeff".to_string(), "Copy"))
.add_item(CustomMenuItem::new("jeffd".to_string(), "Paste")),
);
let view = Submenu::new(
"View",
Menu::new()
.add_item(CustomMenuItem::new(
"command_pallete".to_string(),
"Command Pallete",
))
.add_item(CustomMenuItem::new("jeffd".to_string(), "Layout")),
);
let menu = Menu::new()
.add_submenu(spacedrive)
.add_submenu(file)
.add_submenu(edit)
.add_submenu(view);
menu
}
pub(crate) fn handle_menu_event(event: WindowMenuEvent<Wry>) {
match event.menu_item_id() {
"quit" => {
std::process::exit(0);
}
"close" => {
event.window().close().unwrap();
}
_ => {}
}
}

View file

@ -1,2 +0,0 @@
pub mod config;
pub mod menu;

View file

@ -1,5 +1,5 @@
use crate::app::config;
use anyhow::{Context, Result};
use crate::CONFIG;
use anyhow::Result;
use once_cell::sync::OnceCell;
use rusqlite::Connection;
use sea_orm::{Database, DatabaseConnection, DbErr};
@ -8,47 +8,47 @@ use sea_orm::{Database, DatabaseConnection, DbErr};
// use std::str::FromStr;
pub async fn get_connection() -> Result<DatabaseConnection, DbErr> {
let config = config::get_config();
let config = CONFIG.get().unwrap();
let db_url = format!("{}{}", "sqlite://", config.primary_db.to_str().unwrap());
let db_url = format!("{}{}", "sqlite://", config.primary_db.to_str().unwrap());
let db = Database::connect(&db_url).await?;
let db = Database::connect(&db_url).await?;
Ok(db)
Ok(db)
}
pub static DB_INSTANCE: OnceCell<DatabaseConnection> = OnceCell::new();
pub async fn db_instance() -> Result<&'static DatabaseConnection, String> {
if DB_INSTANCE.get().is_none() {
let db = get_connection().await.map_err(|e| e.to_string())?;
DB_INSTANCE.set(db).unwrap_or_default();
Ok(DB_INSTANCE.get().unwrap())
} else {
Ok(DB_INSTANCE.get().unwrap())
}
if DB_INSTANCE.get().is_none() {
let db = get_connection().await.map_err(|e| e.to_string())?;
DB_INSTANCE.set(db).unwrap_or_default();
Ok(DB_INSTANCE.get().unwrap())
} else {
Ok(DB_INSTANCE.get().unwrap())
}
}
pub async fn create_primary_db() -> Result<(), sqlx::Error> {
let config = config::get_config();
let config = CONFIG.get().unwrap();
let db_url = config.primary_db.to_str().unwrap();
// establish connection, this is only used to create the db if missing
// replace in future
let mut connection = Connection::open(db_url).unwrap();
let db_url = config.primary_db.to_str().unwrap();
// establish connection, this is only used to create the db if missing
// replace in future
let mut connection = Connection::open(db_url).unwrap();
println!("Primary database initialized: {}", &db_url);
println!("Primary database initialized: {}", &db_url);
// migrate db
mod embedded_primary {
use refinery::embed_migrations;
embed_migrations!("src/db/migrations/primary");
}
// migrate db
mod embedded_primary {
use refinery::embed_migrations;
embed_migrations!("lib/db/migrations/primary");
}
embedded_primary::migrations::runner()
.run(&mut connection)
.unwrap();
embedded_primary::migrations::runner()
.run(&mut connection)
.unwrap();
// close and exit cause we don't need this connection anymore
connection.close().unwrap();
Ok(())
// close and exit cause we don't need this connection anymore
connection.close().unwrap();
Ok(())
}

View file

@ -0,0 +1,33 @@
use data_encoding::HEXLOWER;
use ring::digest::{Context, Digest, SHA256};
use sha256::digest;
use std::io;
use std::io::{BufReader, Read};
use std::time::Instant;
fn sha256_digest<R: Read>(mut reader: R) -> io::Result<Digest> {
let mut context = Context::new(&SHA256);
let mut buffer = [0; 1024];
loop {
let count = reader.read(&mut buffer)?;
if count == 0 {
break;
}
context.update(&buffer[..count]);
}
Ok(context.finish())
}
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)?))?;
// create a lowercase hash from
let hex = HEXLOWER.encode(digest.as_ref());
println!("hashing complete in {:?} {}", start.elapsed(), hex);
Ok(hex)
}
pub fn create_meta_checksum(uri: &str, size_in_bytes: u64) -> io::Result<String> {
Ok(digest(format!("{}{}", uri, size_in_bytes.to_string())))
}

View file

@ -0,0 +1,158 @@
use crate::db::connection::DB_INSTANCE;
use crate::db::entity::file;
use crate::file::{checksum, init};
use crate::util::time;
use anyhow::Result;
use sea_orm::entity::*;
use sea_orm::ActiveModelTrait;
use sea_orm::QueryFilter;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::{fs, path};
use walkdir::{DirEntry, WalkDir};
fn is_hidden(entry: &DirEntry) -> bool {
entry
.file_name()
.to_str()
.map(|s| s.starts_with("."))
.unwrap_or(false)
}
fn is_node_modules(entry: &DirEntry) -> bool {
entry
.file_name()
.to_str()
.map(|s| s.contains("node_modules"))
.unwrap_or(false)
}
fn is_app_bundle(entry: &DirEntry) -> bool {
let is_dir = entry.metadata().unwrap().is_dir();
let contains_dot = entry
.file_name()
.to_str()
.map(|s| s.contains(".app") | s.contains(".bundle"))
.unwrap_or(false);
let is_app_bundle = is_dir && contains_dot;
// if is_app_bundle {
// let path_buff = entry.path();
// let path = path_buff.to_str().unwrap();
// self::path(&path, );
// }
is_app_bundle
}
pub async fn scan(path: &str) -> Result<()> {
println!("Scanning directory: {}", &path);
// read the scan directory
let file = self::path(path, None).await?;
// hashmap to store refrences to directories
let mut dirs: HashMap<String, u32> = HashMap::new();
if file.is_dir {
// insert root directory
dirs.insert(path.to_owned(), file.id);
// iterate over files and subdirectories
for entry in WalkDir::new(path).into_iter().filter_entry(|dir| {
let approved = !is_hidden(dir) && !is_app_bundle(dir) && !is_node_modules(dir);
approved
}) {
let entry = entry?;
let child_path = entry.path().to_str().unwrap();
let parent_dir = get_parent_dir_id(&dirs, &entry);
// analyse the child file
let child_file = self::path(&child_path, parent_dir).await.unwrap();
println!(
"Reading file from dir {:?} {:?} assigned id {:?}",
parent_dir, child_path, child_file.id
);
// if this file is a directory, save in hashmap with database id
if child_file.is_dir {
dirs.insert(child_path.to_owned(), child_file.id);
}
// println!("{}", entry.path().display());
}
}
println!("Scanning complete: {}", &path);
Ok(())
}
fn get_parent_dir_id(dirs: &HashMap<String, u32>, entry: &DirEntry) -> Option<u32> {
let path = entry.path();
let parent_path = path
.parent()
.unwrap_or_else(|| path)
.to_str()
.unwrap_or_default();
let parent_dir_id = dirs.get(&parent_path.to_owned());
match parent_dir_id {
Some(x) => Some(x.clone()),
None => None,
}
}
// Read a file from path returning the File struct
// Generates meta checksum and extracts metadata
pub async fn path(path: &str, parent_id: Option<u32>) -> Result<file::Model> {
let db = DB_INSTANCE.get().unwrap();
let path_buff = path::PathBuf::from(path);
let metadata = fs::metadata(&path)?;
let size = metadata.len();
let meta_checksum =
checksum::create_meta_checksum(path_buff.to_str().unwrap_or_default(), size)?;
let existing_files = file::Entity::find()
.filter(file::Column::MetaChecksum.contains(&meta_checksum))
.all(db)
.await?;
if existing_files.len() == 0 {
let primary_library = init::get_primary_library(&db).await?;
let file = file::ActiveModel {
is_dir: Set(metadata.is_dir()),
parent_id: Set(parent_id.map(|x| x.clone())),
meta_checksum: Set(meta_checksum.to_owned()),
name: Set(extract_name(path_buff.file_name())),
extension: Set(extract_name(path_buff.extension())),
uri: Set(path_buff.to_str().unwrap().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())?)),
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.unwrap();
// REPLACE WHEN SEA QL PULLS THROUGH
let existing_files = file::Entity::find()
.filter(file::Column::MetaChecksum.contains(&meta_checksum))
.all(db)
.await?;
let existing_file = existing_files.first().unwrap().clone();
Ok(existing_file)
} else {
let existing_file = existing_files.first().unwrap().clone();
Ok(existing_file)
}
}
// extract name from OsStr returned by PathBuff
fn extract_name(os_string: Option<&OsStr>) -> String {
os_string
.unwrap_or_default()
.to_str()
.unwrap_or_default()
.to_owned()
}

View file

@ -1,33 +0,0 @@
use data_encoding::HEXLOWER;
use ring::digest::{Context, Digest, SHA256};
use sha256::digest;
use std::io;
use std::io::{BufReader, Read};
use std::time::Instant;
fn sha256_digest<R: Read>(mut reader: R) -> io::Result<Digest> {
let mut context = Context::new(&SHA256);
let mut buffer = [0; 1024];
loop {
let count = reader.read(&mut buffer)?;
if count == 0 {
break;
}
context.update(&buffer[..count]);
}
Ok(context.finish())
}
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)?))?;
// create a lowercase hash from
let hex = HEXLOWER.encode(digest.as_ref());
println!("hashing complete in {:?} {}", start.elapsed(), hex);
Ok(hex)
}
pub fn create_meta_checksum(uri: &str, size_in_bytes: u64) -> io::Result<String> {
Ok(digest(format!("{}{}", uri, size_in_bytes.to_string())))
}

View file

@ -1,157 +0,0 @@
use crate::db::connection::DB_INSTANCE;
use crate::db::entity::file;
use crate::filesystem::{checksum, init};
use crate::util::time;
use anyhow::Result;
use sea_orm::entity::*;
use sea_orm::ActiveModelTrait;
use sea_orm::QueryFilter;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::{fs, path};
use walkdir::{DirEntry, WalkDir};
fn is_hidden(entry: &DirEntry) -> bool {
entry
.file_name()
.to_str()
.map(|s| s.starts_with("."))
.unwrap_or(false)
}
fn is_node_modules(entry: &DirEntry) -> bool {
entry
.file_name()
.to_str()
.map(|s| s.contains("node_modules"))
.unwrap_or(false)
}
fn is_app_bundle(entry: &DirEntry) -> bool {
let is_dir = entry.metadata().unwrap().is_dir();
let contains_dot = entry
.file_name()
.to_str()
.map(|s| s.contains(".app") | s.contains(".bundle"))
.unwrap_or(false);
let is_app_bundle = is_dir && contains_dot;
// if is_app_bundle {
// let path_buff = entry.path();
// let path = path_buff.to_str().unwrap();
// self::path(&path, );
// }
is_app_bundle
}
pub async fn scan(path: &str) -> Result<()> {
println!("Scanning directory: {}", &path);
// read the scan directory
let file = self::path(path, None).await?;
// hashmap to store refrences to directories
let mut dirs: HashMap<String, u32> = HashMap::new();
if file.is_dir {
// insert root directory
dirs.insert(path.to_owned(), file.id);
// iterate over files and subdirectories
for entry in WalkDir::new(path).into_iter().filter_entry(|dir| {
let approved = !is_hidden(dir) && !is_app_bundle(dir) && !is_node_modules(dir);
approved
}) {
let entry = entry?;
let child_path = entry.path().to_str().unwrap();
let parent_dir = get_parent_dir_id(&dirs, &entry);
// analyse the child file
let child_file = self::path(&child_path, parent_dir).await.unwrap();
println!(
"Reading file from dir {:?} {:?} assigned id {:?}",
parent_dir, child_path, child_file.id
);
// if this file is a directory, save in hashmap with database id
if child_file.is_dir {
dirs.insert(child_path.to_owned(), child_file.id);
}
// println!("{}", entry.path().display());
}
}
println!("Scanning complete: {}", &path);
Ok(())
}
fn get_parent_dir_id(dirs: &HashMap<String, u32>, entry: &DirEntry) -> Option<u32> {
let path = entry.path();
let parent_path = path
.parent()
.unwrap_or_else(|| path)
.to_str()
.unwrap_or_default();
let parent_dir_id = dirs.get(&parent_path.to_owned());
match parent_dir_id {
Some(x) => Some(x.clone()),
None => None,
}
}
// Read a file from path returning the File struct
// Generates meta checksum and extracts metadata
pub async fn path(path: &str, parent_id: Option<u32>) -> Result<file::Model> {
let db = DB_INSTANCE.get().unwrap();
let path_buff = path::PathBuf::from(path);
let metadata = fs::metadata(&path)?;
let size = metadata.len();
let meta_checksum = checksum::create_meta_checksum(path_buff.to_str().unwrap_or_default(), size)?;
let existing_files = file::Entity::find()
.filter(file::Column::MetaChecksum.contains(&meta_checksum))
.all(db)
.await?;
if existing_files.len() == 0 {
let primary_library = init::get_primary_library(&db).await?;
let file = file::ActiveModel {
is_dir: Set(metadata.is_dir()),
parent_id: Set(parent_id.map(|x| x.clone())),
meta_checksum: Set(meta_checksum.to_owned()),
name: Set(extract_name(path_buff.file_name())),
extension: Set(extract_name(path_buff.extension())),
uri: Set(path_buff.to_str().unwrap().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())?)),
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.unwrap();
// REPLACE WHEN SEA QL PULLS THROUGH
let existing_files = file::Entity::find()
.filter(file::Column::MetaChecksum.contains(&meta_checksum))
.all(db)
.await?;
let existing_file = existing_files.first().unwrap().clone();
Ok(existing_file)
} else {
let existing_file = existing_files.first().unwrap().clone();
Ok(existing_file)
}
}
// extract name from OsStr returned by PathBuff
fn extract_name(os_string: Option<&OsStr>) -> String {
os_string
.unwrap_or_default()
.to_str()
.unwrap_or_default()
.to_owned()
}

View file

@ -1,13 +1,10 @@
pub struct Job {
pub id: i32,
pub timestamp: i32,
pub client_id: i32
pub client_id: i32,
pub target_client_id: i32,
pub file_id: i32,
pub action: Action,
pub status: String,
pub complete: bool,
}
}

View file

@ -1,3 +1,30 @@
use once_cell::sync::OnceCell;
use serde::{Deserialize, Serialize};
mod crypto;
mod db;
mod file;
mod util;
// static configuration
#[derive(Serialize, Deserialize, Debug)]
pub struct AppConfig {
pub data_dir: std::path::PathBuf,
pub primary_db: std::path::PathBuf,
pub file_type_thumb_dir: std::path::PathBuf,
}
pub static CONFIG: OnceCell<AppConfig> = OnceCell::new();
pub fn configure(data_dir: std::path::PathBuf) {
let config = AppConfig {
data_dir: data_dir.clone(),
primary_db: data_dir.clone().join("primary.db3"),
file_type_thumb_dir: data_dir.clone().join("file_icons"),
};
CONFIG.set(config).unwrap();
}
fn main() {
// hello!
println!("Hello, world!");
}

View file

@ -1,16 +1,13 @@
pub enum TransactionType {
CREATE,
UPDATE,
DELETE,
}
pub struct Transaction {
pub id: i32,
pub timestamp: i32,
pub client_id: i32
pub client_id: i32,
pub target_client_id: i32,
type TransactionType
}
// type TransactionType
}