From 312be5e6314693616e36df7ed8cc158a18ff29ea Mon Sep 17 00:00:00 2001 From: Antoine Gersant Date: Sat, 1 Jul 2017 13:06:55 -0700 Subject: [PATCH] Moved index functionality out of DB struct --- src/api.rs | 9 +-- src/db/mod.rs | 189 +----------------------------------------------- src/index.rs | 193 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 198 insertions(+), 193 deletions(-) diff --git a/src/api.rs b/src/api.rs index 50f641b..877986e 100644 --- a/src/api.rs +++ b/src/api.rs @@ -18,6 +18,7 @@ use url::percent_encoding::percent_decode; use db::DB; use errors::*; use thumbnails::*; +use index; use user; use utils::*; use vfs::VFSSource; @@ -211,7 +212,7 @@ fn browse(request: &mut Request, db: &DB) -> IronResult { Err(e) => return Err(IronError::new(e, status::BadRequest)), Ok(p) => p, }; - let browse_result = db.browse(&path)?; + let browse_result = index::browse(db, &path)?; let result_json = serde_json::to_string(&browse_result); let result_json = match result_json { @@ -228,7 +229,7 @@ fn flatten(request: &mut Request, db: &DB) -> IronResult { Err(e) => return Err(IronError::new(e, status::BadRequest)), Ok(p) => p, }; - let flatten_result = db.flatten(&path)?; + let flatten_result = index::flatten(db, &path)?; let result_json = serde_json::to_string(&flatten_result); let result_json = match result_json { @@ -240,7 +241,7 @@ fn flatten(request: &mut Request, db: &DB) -> IronResult { } fn random(_: &mut Request, db: &DB) -> IronResult { - let random_result = db.get_random_albums(20)?; + let random_result = index::get_random_albums(db, 20)?; let result_json = serde_json::to_string(&random_result); let result_json = match result_json { Ok(j) => j, @@ -250,7 +251,7 @@ fn random(_: &mut Request, db: &DB) -> IronResult { } fn recent(_: &mut Request, db: &DB) -> IronResult { - let recent_result = db.get_recent_albums(20)?; + let recent_result = index::get_recent_albums(db, 20)?; let result_json = serde_json::to_string(&recent_result); let result_json = match result_json { Ok(j) => j, diff --git a/src/db/mod.rs b/src/db/mod.rs index ac5586f..ab9fcb4 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,9 +1,7 @@ use core::ops::Deref; use diesel; -use diesel::expression::sql; use diesel::prelude::*; use diesel::sqlite::SqliteConnection; -use diesel::types; use std::fs; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; @@ -11,13 +9,12 @@ use std::sync::{Arc, Mutex}; use config::{MiscSettings, UserConfig}; use ddns::{DDNSConfigSource, DDNSConfig}; use errors::*; +use index; use user::*; use vfs::{MountPoint, Vfs, VFSSource}; mod schema; -use index; -use index::{CollectionFile, Directory, Song}; pub use self::schema::*; #[allow(dead_code)] @@ -121,125 +118,6 @@ impl DB { pub fn index_update_loop(&self) { index::update_loop(self); } - - fn virtualize_song(&self, vfs: &Vfs, mut song: Song) -> Option { - song.path = match vfs.real_to_virtual(Path::new(&song.path)) { - Ok(p) => p.to_string_lossy().into_owned(), - _ => return None, - }; - if let Some(artwork_path) = song.artwork { - song.artwork = match vfs.real_to_virtual(Path::new(&artwork_path)) { - Ok(p) => Some(p.to_string_lossy().into_owned()), - _ => None, - }; - } - Some(song) - } - - fn virtualize_directory(&self, vfs: &Vfs, mut directory: Directory) -> Option { - directory.path = match vfs.real_to_virtual(Path::new(&directory.path)) { - Ok(p) => p.to_string_lossy().into_owned(), - _ => return None, - }; - if let Some(artwork_path) = directory.artwork { - directory.artwork = match vfs.real_to_virtual(Path::new(&artwork_path)) { - Ok(p) => Some(p.to_string_lossy().into_owned()), - _ => None, - }; - } - Some(directory) - } - - pub fn browse(&self, virtual_path: &Path) -> Result> { - let mut output = Vec::new(); - let vfs = self.get_vfs()?; - let connection = self.connection.lock().unwrap(); - let connection = connection.deref(); - - if virtual_path.components().count() == 0 { - // Browse top-level - let real_directories: Vec = directories::table - .filter(directories::parent.is_null()) - .load(connection)?; - let virtual_directories = real_directories - .into_iter() - .filter_map(|s| self.virtualize_directory(&vfs, s)); - output.extend(virtual_directories - .into_iter() - .map(|d| CollectionFile::Directory(d))); - - } else { - // Browse sub-directory - let real_path = vfs.virtual_to_real(virtual_path)?; - let real_path_string = real_path.as_path().to_string_lossy().into_owned(); - - let real_directories: Vec = directories::table - .filter(directories::parent.eq(&real_path_string)) - .order(sql::("path COLLATE NOCASE ASC")) - .load(connection)?; - let virtual_directories = real_directories - .into_iter() - .filter_map(|s| self.virtualize_directory(&vfs, s)); - output.extend(virtual_directories.map(|d| CollectionFile::Directory(d))); - - let real_songs: Vec = songs::table - .filter(songs::parent.eq(&real_path_string)) - .order(sql::("path COLLATE NOCASE ASC")) - .load(connection)?; - let virtual_songs = real_songs - .into_iter() - .filter_map(|s| self.virtualize_song(&vfs, s)); - output.extend(virtual_songs.map(|s| CollectionFile::Song(s))); - } - - Ok(output) - } - - pub fn flatten(&self, virtual_path: &Path) -> Result> { - use self::songs::dsl::*; - let vfs = self.get_vfs()?; - let connection = self.connection.lock().unwrap(); - let connection = connection.deref(); - let real_path = vfs.virtual_to_real(virtual_path)?; - let like_path = real_path.as_path().to_string_lossy().into_owned() + "%"; - let real_songs: Vec = songs.filter(path.like(&like_path)).load(connection)?; - let virtual_songs = real_songs - .into_iter() - .filter_map(|s| self.virtualize_song(&vfs, s)); - Ok(virtual_songs.collect::>()) - } - - pub fn get_random_albums(&self, count: i64) -> Result> { - use self::directories::dsl::*; - let vfs = self.get_vfs()?; - let connection = self.connection.lock().unwrap(); - let connection = connection.deref(); - let real_directories = directories - .filter(album.is_not_null()) - .limit(count) - .order(sql::("RANDOM()")) - .load(connection)?; - let virtual_directories = real_directories - .into_iter() - .filter_map(|s| self.virtualize_directory(&vfs, s)); - Ok(virtual_directories.collect::>()) - } - - pub fn get_recent_albums(&self, count: i64) -> Result> { - use self::directories::dsl::*; - let vfs = self.get_vfs()?; - let connection = self.connection.lock().unwrap(); - let connection = connection.deref(); - let real_directories: Vec = directories - .filter(album.is_not_null()) - .order(date_added.desc()) - .limit(count) - .load(connection)?; - let virtual_directories = real_directories - .into_iter() - .filter_map(|s| self.virtualize_directory(&vfs, s)); - Ok(virtual_directories.collect::>()) - } } impl ConnectionSource for DB { @@ -303,68 +181,3 @@ fn test_migrations_down() { db.migrate_up().unwrap(); } -#[test] -fn test_browse_top_level() { - let mut root_path = PathBuf::new(); - root_path.push("root"); - - let db = _get_test_db("browse_top_level.sqlite"); - db.index_update().unwrap(); - let results = db.browse(Path::new("")).unwrap(); - - assert_eq!(results.len(), 1); - match results[0] { - CollectionFile::Directory(ref d) => assert_eq!(d.path, root_path.to_str().unwrap()), - _ => panic!("Expected directory"), - } -} - -#[test] -fn test_browse() { - let mut khemmis_path = PathBuf::new(); - khemmis_path.push("root"); - khemmis_path.push("Khemmis"); - - let mut tobokegao_path = PathBuf::new(); - tobokegao_path.push("root"); - tobokegao_path.push("Tobokegao"); - - let db = _get_test_db("browse.sqlite"); - db.index_update().unwrap(); - let results = db.browse(Path::new("root")).unwrap(); - - assert_eq!(results.len(), 2); - match results[0] { - CollectionFile::Directory(ref d) => assert_eq!(d.path, khemmis_path.to_str().unwrap()), - _ => panic!("Expected directory"), - } - match results[1] { - CollectionFile::Directory(ref d) => assert_eq!(d.path, tobokegao_path.to_str().unwrap()), - _ => panic!("Expected directory"), - } -} - -#[test] -fn test_flatten() { - let db = _get_test_db("flatten.sqlite"); - db.index_update().unwrap(); - let results = db.flatten(Path::new("root")).unwrap(); - assert_eq!(results.len(), 12); -} - -#[test] -fn test_random() { - let db = _get_test_db("random.sqlite"); - db.index_update().unwrap(); - let results = db.get_random_albums(1).unwrap(); - assert_eq!(results.len(), 1); -} - -#[test] -fn test_recent() { - let db = _get_test_db("recent.sqlite"); - db.index_update().unwrap(); - let results = db.get_recent_albums(2).unwrap(); - assert_eq!(results.len(), 2); - assert!(results[0].date_added >= results[1].date_added); -} diff --git a/src/index.rs b/src/index.rs index 1c4919f..33c46a5 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1,7 +1,9 @@ use core::ops::Deref; use diesel; +use diesel::expression::sql; use diesel::prelude::*; use diesel::sqlite::SqliteConnection; +use diesel::types; use regex::Regex; use std::fs; use std::path::{Path, PathBuf}; @@ -13,7 +15,7 @@ use config::{MiscSettings, UserConfig}; use db::ConnectionSource; use db::DB; use db::{directories, misc_settings, songs}; -use vfs::VFSSource; +use vfs::{Vfs, VFSSource}; use errors::*; use metadata; @@ -402,6 +404,129 @@ pub fn update_loop(db: &T) where T: ConnectionSource + VFSSource { } } +fn virtualize_song(vfs: &Vfs, mut song: Song) -> Option { + song.path = match vfs.real_to_virtual(Path::new(&song.path)) { + Ok(p) => p.to_string_lossy().into_owned(), + _ => return None, + }; + if let Some(artwork_path) = song.artwork { + song.artwork = match vfs.real_to_virtual(Path::new(&artwork_path)) { + Ok(p) => Some(p.to_string_lossy().into_owned()), + _ => None, + }; + } + Some(song) +} + +fn virtualize_directory(vfs: &Vfs, mut directory: Directory) -> Option { + directory.path = match vfs.real_to_virtual(Path::new(&directory.path)) { + Ok(p) => p.to_string_lossy().into_owned(), + _ => return None, + }; + if let Some(artwork_path) = directory.artwork { + directory.artwork = match vfs.real_to_virtual(Path::new(&artwork_path)) { + Ok(p) => Some(p.to_string_lossy().into_owned()), + _ => None, + }; + } + Some(directory) +} + +pub fn browse(db: &T, virtual_path: &Path) -> Result> where T: ConnectionSource + VFSSource { + let mut output = Vec::new(); + let vfs = db.get_vfs()?; + let connection = db.get_connection(); + let connection = connection.lock().unwrap(); + let connection = connection.deref(); + + if virtual_path.components().count() == 0 { + // Browse top-level + let real_directories: Vec = directories::table + .filter(directories::parent.is_null()) + .load(connection)?; + let virtual_directories = real_directories + .into_iter() + .filter_map(|s| virtualize_directory(&vfs, s)); + output.extend(virtual_directories + .into_iter() + .map(|d| CollectionFile::Directory(d))); + + } else { + // Browse sub-directory + let real_path = vfs.virtual_to_real(virtual_path)?; + let real_path_string = real_path.as_path().to_string_lossy().into_owned(); + + let real_directories: Vec = directories::table + .filter(directories::parent.eq(&real_path_string)) + .order(sql::("path COLLATE NOCASE ASC")) + .load(connection)?; + let virtual_directories = real_directories + .into_iter() + .filter_map(|s| virtualize_directory(&vfs, s)); + output.extend(virtual_directories.map(|d| CollectionFile::Directory(d))); + + let real_songs: Vec = songs::table + .filter(songs::parent.eq(&real_path_string)) + .order(sql::("path COLLATE NOCASE ASC")) + .load(connection)?; + let virtual_songs = real_songs + .into_iter() + .filter_map(|s| virtualize_song(&vfs, s)); + output.extend(virtual_songs.map(|s| CollectionFile::Song(s))); + } + + Ok(output) +} + +pub fn flatten(db: &T, virtual_path: &Path) -> Result> where T: ConnectionSource + VFSSource { + use self::songs::dsl::*; + let vfs = db.get_vfs()?; + let connection = db.get_connection(); + let connection = connection.lock().unwrap(); + let connection = connection.deref(); + let real_path = vfs.virtual_to_real(virtual_path)?; + let like_path = real_path.as_path().to_string_lossy().into_owned() + "%"; + let real_songs: Vec = songs.filter(path.like(&like_path)).load(connection)?; + let virtual_songs = real_songs + .into_iter() + .filter_map(|s| virtualize_song(&vfs, s)); + Ok(virtual_songs.collect::>()) +} + +pub fn get_random_albums(db: &T, count: i64) -> Result> where T: ConnectionSource + VFSSource { + use self::directories::dsl::*; + let vfs = db.get_vfs()?; + let connection = db.get_connection(); + let connection = connection.lock().unwrap(); + let connection = connection.deref(); + let real_directories = directories + .filter(album.is_not_null()) + .limit(count) + .order(sql::("RANDOM()")) + .load(connection)?; + let virtual_directories = real_directories + .into_iter() + .filter_map(|s| virtualize_directory(&vfs, s)); + Ok(virtual_directories.collect::>()) +} + +pub fn get_recent_albums(db: &T, count: i64) -> Result> where T: ConnectionSource + VFSSource { + use self::directories::dsl::*; + let vfs = db.get_vfs()?; + let connection = db.get_connection(); + let connection = connection.lock().unwrap(); + let connection = connection.deref(); + let real_directories: Vec = directories + .filter(album.is_not_null()) + .order(date_added.desc()) + .limit(count) + .load(connection)?; + let virtual_directories = real_directories + .into_iter() + .filter_map(|s| virtualize_directory(&vfs, s)); + Ok(virtual_directories.collect::>()) +} + fn _get_test_db(name: &str) -> DB { let config_path = Path::new("test/config.toml"); let config = UserConfig::parse(&config_path).unwrap(); @@ -471,3 +596,69 @@ fn test_metadata() { assert_eq!(song.artwork, Some(artwork_path.to_string_lossy().into_owned())); } + +#[test] +fn test_browse_top_level() { + let mut root_path = PathBuf::new(); + root_path.push("root"); + + let db = _get_test_db("browse_top_level.sqlite"); + db.index_update().unwrap(); + let results = browse(&db, Path::new("")).unwrap(); + + assert_eq!(results.len(), 1); + match results[0] { + CollectionFile::Directory(ref d) => assert_eq!(d.path, root_path.to_str().unwrap()), + _ => panic!("Expected directory"), + } +} + +#[test] +fn test_browse() { + let mut khemmis_path = PathBuf::new(); + khemmis_path.push("root"); + khemmis_path.push("Khemmis"); + + let mut tobokegao_path = PathBuf::new(); + tobokegao_path.push("root"); + tobokegao_path.push("Tobokegao"); + + let db = _get_test_db("browse.sqlite"); + db.index_update().unwrap(); + let results = browse(&db, Path::new("root")).unwrap(); + + assert_eq!(results.len(), 2); + match results[0] { + CollectionFile::Directory(ref d) => assert_eq!(d.path, khemmis_path.to_str().unwrap()), + _ => panic!("Expected directory"), + } + match results[1] { + CollectionFile::Directory(ref d) => assert_eq!(d.path, tobokegao_path.to_str().unwrap()), + _ => panic!("Expected directory"), + } +} + +#[test] +fn test_flatten() { + let db = _get_test_db("flatten.sqlite"); + db.index_update().unwrap(); + let results = flatten(&db, Path::new("root")).unwrap(); + assert_eq!(results.len(), 12); +} + +#[test] +fn test_random() { + let db = _get_test_db("random.sqlite"); + db.index_update().unwrap(); + let results = get_random_albums(&db, 1).unwrap(); + assert_eq!(results.len(), 1); +} + +#[test] +fn test_recent() { + let db = _get_test_db("recent.sqlite"); + db.index_update().unwrap(); + let results = get_recent_albums(&db, 2).unwrap(); + assert_eq!(results.len(), 2); + assert!(results[0].date_added >= results[1].date_added); +} \ No newline at end of file