mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-02 10:03:28 +00:00
expolorer!
This commit is contained in:
parent
6e658b9fcf
commit
fa48b189ba
5
src-tauri/Cargo.lock
generated
5
src-tauri/Cargo.lock
generated
|
@ -3372,6 +3372,7 @@ dependencies = [
|
|||
"strum 0.21.0",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4395,9 +4396,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.10.0"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b"
|
||||
checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num_cpus",
|
||||
|
|
|
@ -33,6 +33,7 @@ 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"
|
||||
log = "0.4.14"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::db;
|
||||
use crate::filesystem::{init, reader};
|
||||
use crate::{db, filesystem};
|
||||
use anyhow::Result;
|
||||
use once_cell::sync::OnceCell;
|
||||
use sea_orm::DatabaseConnection;
|
||||
|
@ -15,14 +15,16 @@ async fn init_db_instance() -> Result<()> {
|
|||
}
|
||||
|
||||
#[tauri::command(async)]
|
||||
pub async fn read_file_command(path: &str) -> Result<String, String> {
|
||||
pub async fn scan_dir(path: &str) -> Result<(), String> {
|
||||
init_db_instance().await.map_err(|e| e.to_string())?;
|
||||
|
||||
let file = reader::path(path).await.map_err(|e| e.to_string());
|
||||
let directories = filesystem::explorer::scan(path)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
println!("file: {:?}", file);
|
||||
println!("file: {:?}", directories);
|
||||
|
||||
Ok("lol".to_owned())
|
||||
Ok(())
|
||||
}
|
||||
// #[tauri::command(async)]
|
||||
// pub async fn generate_buffer_checksum(path: &str) -> Result<File, InvokeError> {
|
||||
|
|
|
@ -28,6 +28,6 @@ pub async fn create_buffer_checksum(path: &str) -> io::Result<String> {
|
|||
Ok(hex)
|
||||
}
|
||||
|
||||
pub fn create_meta_checksum(uri: String, size_in_bytes: u64) -> io::Result<String> {
|
||||
pub fn create_meta_checksum(uri: &str, size_in_bytes: u64) -> io::Result<String> {
|
||||
Ok(digest(format!("{}{}", uri, size_in_bytes.to_string())))
|
||||
}
|
||||
|
|
56
src-tauri/src/filesystem/explorer.rs
Normal file
56
src-tauri/src/filesystem/explorer.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
use crate::db::entity;
|
||||
use crate::filesystem;
|
||||
use anyhow::Result;
|
||||
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_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("."))
|
||||
.unwrap_or(false);
|
||||
|
||||
is_dir && contains_dot
|
||||
}
|
||||
|
||||
pub async fn scan(path: &str) -> Result<()> {
|
||||
println!("Scanning directory: {}", &path);
|
||||
// read the scan directory
|
||||
let file_or_dir = filesystem::reader::path(path, None).await?;
|
||||
|
||||
if let Some(dir) = file_or_dir.dir {
|
||||
let mut current_dir: entity::dir::Model = dir;
|
||||
for entry in WalkDir::new(path)
|
||||
.into_iter()
|
||||
.filter_entry(|e| !is_hidden(e) && !is_app_bundle(e))
|
||||
{
|
||||
let entry = entry?;
|
||||
let path = entry.path().to_str().unwrap();
|
||||
|
||||
let child_file_or_dir = filesystem::reader::path(&path, Some(current_dir.id))
|
||||
.await
|
||||
.unwrap_or_else(|e| {
|
||||
println!("could not read path, {}", e);
|
||||
return filesystem::reader::FileOrDir {
|
||||
dir: None,
|
||||
file: None,
|
||||
};
|
||||
});
|
||||
|
||||
if child_file_or_dir.dir.is_some() {
|
||||
current_dir = child_file_or_dir.dir.unwrap()
|
||||
}
|
||||
|
||||
println!("{}", entry.path().display());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
pub mod checksum;
|
||||
// pub mod device;
|
||||
pub mod explorer;
|
||||
pub mod init;
|
||||
pub mod reader;
|
||||
|
|
|
@ -1,39 +1,47 @@
|
|||
use crate::commands::DB_INSTANCE;
|
||||
use crate::db;
|
||||
use crate::db::entity::dir;
|
||||
use crate::db::entity::file;
|
||||
use crate::filesystem::{checksum, init};
|
||||
use crate::util::time;
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{anyhow, Result};
|
||||
use sea_orm::entity::*;
|
||||
use sea_orm::QueryFilter;
|
||||
use std::ffi::OsStr;
|
||||
use std::{fs, path};
|
||||
pub enum ReaderError {
|
||||
FailedToGetPrimaryLibrary,
|
||||
|
||||
pub struct FileOrDir {
|
||||
pub dir: Option<dir::Model>,
|
||||
pub file: Option<file::Model>,
|
||||
}
|
||||
|
||||
pub async fn path(path: &str) -> Result<()> {
|
||||
let db = DB_INSTANCE.get().unwrap();
|
||||
|
||||
// reads the metadata associated with the file or directory
|
||||
// found at the supplied path and processes accordingly
|
||||
pub async fn path(path: &str, dir_id: Option<u32>) -> Result<FileOrDir> {
|
||||
let path_buff = path::PathBuf::from(path);
|
||||
let metadata = fs::metadata(&path)?;
|
||||
|
||||
if metadata.is_dir() {
|
||||
// read_dir().await?;
|
||||
Ok(FileOrDir {
|
||||
dir: Some(read_dir(path_buff, metadata, &dir_id).await?),
|
||||
file: None,
|
||||
})
|
||||
} else {
|
||||
read_file(&path, path_buff, metadata).await?;
|
||||
Ok(FileOrDir {
|
||||
dir: None,
|
||||
file: Some(read_file(path_buff, metadata, &dir_id).await?),
|
||||
})
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Read a file from path returning the File struct
|
||||
// Generates meta checksum and extracts metadata
|
||||
pub async fn read_file(path: &str, path_buff: path::PathBuf, metadata: fs::Metadata) -> Result<()> {
|
||||
pub async fn read_file(
|
||||
path_buff: path::PathBuf,
|
||||
metadata: fs::Metadata,
|
||||
dir_id: &Option<u32>,
|
||||
) -> Result<file::Model> {
|
||||
let db = DB_INSTANCE.get().unwrap();
|
||||
let size = metadata.len();
|
||||
let meta_checksum = checksum::create_meta_checksum(path.to_owned(), size)?;
|
||||
|
||||
let primary_library = init::get_primary_library(&db).await?;
|
||||
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))
|
||||
|
@ -41,11 +49,14 @@ pub async fn read_file(path: &str, path_buff: path::PathBuf, metadata: fs::Metad
|
|||
.await?;
|
||||
|
||||
if existing_files.len() == 0 {
|
||||
let primary_library = init::get_primary_library(&db).await?;
|
||||
|
||||
let file = file::ActiveModel {
|
||||
meta_checksum: Set(meta_checksum),
|
||||
meta_checksum: Set(meta_checksum.to_owned()),
|
||||
directory_id: Set(*dir_id),
|
||||
name: Set(extract_name(path_buff.file_name())),
|
||||
extension: Set(extract_name(path_buff.extension())),
|
||||
uri: Set(path.to_owned()),
|
||||
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())?)),
|
||||
|
@ -58,10 +69,68 @@ pub async fn read_file(path: &str, path_buff: path::PathBuf, metadata: fs::Metad
|
|||
|
||||
println!("FILE: {:?}", file);
|
||||
|
||||
Ok(())
|
||||
// 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 file = &existing_files[0];
|
||||
Ok(())
|
||||
let existing_file = existing_files.first().unwrap().clone();
|
||||
Ok(existing_file)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn read_dir(
|
||||
path_buff: path::PathBuf,
|
||||
metadata: fs::Metadata,
|
||||
dir_id: &Option<u32>,
|
||||
) -> Result<dir::Model> {
|
||||
let db = DB_INSTANCE.get().unwrap();
|
||||
|
||||
let path_str = path_buff.to_str().unwrap();
|
||||
|
||||
let file_name = path_buff.file_name().unwrap().to_str().unwrap().to_owned();
|
||||
|
||||
if file_name.contains(".") {
|
||||
return Err(anyhow!("Directory is bundle, do not index"));
|
||||
}
|
||||
|
||||
let existing_dirs = dir::Entity::find()
|
||||
.filter(dir::Column::Uri.contains(&path_str))
|
||||
.all(&db)
|
||||
.await?;
|
||||
|
||||
if existing_dirs.is_empty() {
|
||||
let primary_library = init::get_primary_library(&db).await?;
|
||||
let directory = dir::ActiveModel {
|
||||
name: Set(path_buff.file_name().unwrap().to_str().unwrap().to_owned()),
|
||||
uri: Set(path_str.to_owned()),
|
||||
watch: Set(false),
|
||||
parent_directory_id: Set(*dir_id),
|
||||
library_id: Set(primary_library.id),
|
||||
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 directory = directory.save(&db).await?;
|
||||
|
||||
println!("DIR: {:?}", &directory);
|
||||
|
||||
let existing_dirs = dir::Entity::find()
|
||||
.filter(dir::Column::Uri.contains(&path_str))
|
||||
.all(&db)
|
||||
.await?;
|
||||
|
||||
let existing_dir = existing_dirs.first().unwrap().clone();
|
||||
Ok(existing_dir)
|
||||
} else {
|
||||
let existing_dir = existing_dirs.first().unwrap().clone();
|
||||
Ok(existing_dir)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,7 @@ fn main() {
|
|||
// block_on(filesystem::device::discover_storage_devices()).unwrap();
|
||||
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::read_file_command,
|
||||
// commands::generate_buffer_checksum
|
||||
])
|
||||
.invoke_handler(tauri::generate_handler![commands::scan_dir])
|
||||
.menu(menu::get_menu())
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
|
20
src/App.tsx
20
src/App.tsx
|
@ -31,6 +31,7 @@ const theme = extendTheme({
|
|||
export default function App() {
|
||||
const fileUploader = useRef<HTMLInputElement | null>(null);
|
||||
const [fileInputVal, setFileInputVal] = useState('/Users/jamie/Downloads/lol.mkv');
|
||||
const [fileScanInputVal, setFileScanInputVal] = useState('/Users/jamie/Downloads');
|
||||
|
||||
function changeHandler(e: any) {
|
||||
console.log(e);
|
||||
|
@ -46,6 +47,7 @@ export default function App() {
|
|||
value={fileInputVal}
|
||||
onChange={(e) => setFileInputVal(e.target.value)}
|
||||
/>
|
||||
|
||||
<input
|
||||
ref={fileUploader}
|
||||
type="file"
|
||||
|
@ -79,6 +81,24 @@ export default function App() {
|
|||
Close
|
||||
</Button>
|
||||
</div>
|
||||
<div className="">
|
||||
<Input
|
||||
className="mb-2"
|
||||
value={fileScanInputVal}
|
||||
onChange={(e) => setFileScanInputVal(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
variant="solid"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
invoke('scan_dir', {
|
||||
path: fileScanInputVal
|
||||
}).then(console.log);
|
||||
}}
|
||||
>
|
||||
Scan directories
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</VechaiProvider>
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue