chore: clean up warnings and public api
This commit is contained in:
parent
bf2336386e
commit
f098430a78
|
@ -1,5 +1,5 @@
|
|||
use crate::utils::{self, ProjectDirError};
|
||||
use log::{debug, info, trace, warn};
|
||||
use log::debug;
|
||||
use save_sync::db::{establish_connection, query::GameSaveQuery, Database};
|
||||
use save_sync::game::{GameFile, GameSaveLocation};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -158,13 +158,13 @@ impl Archive {
|
|||
}
|
||||
|
||||
impl Archive {
|
||||
pub fn drop_game<P: AsRef<Path>>(path: P) -> Result<Option<()>, GameDropError> {
|
||||
pub fn drop_game<P: AsRef<Path>>(path: P) -> Result<usize, GameDropError> {
|
||||
let conn = establish_connection();
|
||||
let query = GameSaveQuery::Path(path.as_ref());
|
||||
Ok(Database::drop_game_save(&conn, query)?)
|
||||
}
|
||||
|
||||
pub fn drop_game_with_friendly(name: &str) -> Result<Option<()>, GameDropError> {
|
||||
pub fn drop_game_with_friendly(name: &str) -> Result<usize, GameDropError> {
|
||||
let conn = establish_connection();
|
||||
let query = GameSaveQuery::FriendlyName(name);
|
||||
Ok(Database::drop_game_save(&conn, query)?)
|
||||
|
|
|
@ -2,9 +2,7 @@ use clap::{crate_authors, crate_description, crate_version, ArgMatches};
|
|||
use clap::{App, Arg, SubCommand};
|
||||
use client::archive::Archive;
|
||||
use dotenv::dotenv;
|
||||
use log::{debug, info};
|
||||
use save_sync::db::{establish_connection, Database};
|
||||
use std::path::Path;
|
||||
use log::info;
|
||||
|
||||
fn main() {
|
||||
dotenv().ok();
|
||||
|
@ -116,8 +114,8 @@ fn tracked_save_info(matches: &ArgMatches) {
|
|||
Archive::get_game(path_str).expect("Failed to get game save info from Archive")
|
||||
};
|
||||
|
||||
let game = maybe_game.expect("No tracked game save found");
|
||||
|
||||
match maybe_game {
|
||||
Some(game) => {
|
||||
if let Some(name) = game.friendly_name {
|
||||
println!("Friendly Name: {}", name);
|
||||
} else {
|
||||
|
@ -134,12 +132,15 @@ fn tracked_save_info(matches: &ArgMatches) {
|
|||
println!();
|
||||
}
|
||||
}
|
||||
None => println!("No tracked game save was found."),
|
||||
}
|
||||
}
|
||||
|
||||
fn list_tracked_saves(_matches: &ArgMatches) {
|
||||
let games = Archive::get_all_games()
|
||||
.expect("Failed to get all Games from the Archive")
|
||||
.expect("There are no tracked Games");
|
||||
let maybe_games = Archive::get_all_games().expect("Failed to get all Games from the Archive");
|
||||
|
||||
match maybe_games {
|
||||
Some(games) => {
|
||||
for game in games {
|
||||
if let Some(name) = game.friendly_name {
|
||||
print!("[{}] ", name);
|
||||
|
@ -149,9 +150,12 @@ fn list_tracked_saves(_matches: &ArgMatches) {
|
|||
println!("---");
|
||||
}
|
||||
}
|
||||
None => println!("There are no tracked games"),
|
||||
}
|
||||
}
|
||||
|
||||
fn drop_save(matches: &ArgMatches) {
|
||||
let maybe_compromised = if let Some(name) = matches.value_of("friendly") {
|
||||
let items_deleted = if let Some(name) = matches.value_of("friendly") {
|
||||
Archive::drop_game_with_friendly(name).expect("Archive failed to delete from database")
|
||||
} else {
|
||||
let path_str = matches
|
||||
|
@ -161,8 +165,9 @@ fn drop_save(matches: &ArgMatches) {
|
|||
Archive::drop_game(path_str).expect("Archive failed to delete from database")
|
||||
};
|
||||
|
||||
match maybe_compromised {
|
||||
Some(()) => println!("Game successfully dropped from the list"),
|
||||
None => panic!("Database Invariant broken. Database is corrupted."),
|
||||
match items_deleted {
|
||||
0 => println!("Save Sync can't drop what was never tracked to begin with"),
|
||||
1 => println!("Save Sync successfully dropped the game from the list of tracked games"),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,6 @@
|
|||
use directories::ProjectDirs;
|
||||
use std::path::Path;
|
||||
use thiserror::Error;
|
||||
|
||||
pub fn calc_file_hash(path: &Path) -> Option<u64> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn archive_directory(src: &Path, dst: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn archive_file(src: &Path, dst: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn unarchive_directory(src: &Path, dst: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn unarchive_file(src: &Path, dst: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn get_project_dirs() -> Result<ProjectDirs, ProjectDirError> {
|
||||
ProjectDirs::from("dev", "musuka", "save-sync").ok_or(ProjectDirError::HomeNotSet)
|
||||
}
|
||||
|
|
103
src/db.rs
103
src/db.rs
|
@ -74,13 +74,11 @@ impl Database {
|
|||
pub fn write_game_file(conn: &SqliteConnection, file: &GameFile, needle: i32) -> Result<()> {
|
||||
use super::models::NewGameFile;
|
||||
use super::schema::game_file;
|
||||
use DatabaseError::InvalidPathError;
|
||||
use DatabaseError::InvalidPath;
|
||||
|
||||
let hash_bytes: [u8; 8] = file.hash.to_be_bytes();
|
||||
let path = &file.original_path;
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| InvalidPathError(path.clone()))?;
|
||||
let path_str = path.to_str().ok_or_else(|| InvalidPath(path.clone()))?;
|
||||
|
||||
let new_game_file = NewGameFile {
|
||||
original_path: path_str,
|
||||
|
@ -104,7 +102,7 @@ impl Database {
|
|||
) -> ResultantOption<GameFile> {
|
||||
use super::models::DbGameFile;
|
||||
use super::schema::game_file::dsl::{file_hash, game_file, original_path};
|
||||
use DatabaseError::InvalidPathError;
|
||||
use DatabaseError::{InvalidPath, UnexpectedBehaviour};
|
||||
|
||||
let game_files = match query {
|
||||
GameFileQuery::Hash(hash) => {
|
||||
|
@ -116,17 +114,17 @@ impl Database {
|
|||
GameFileQuery::Path(path) => {
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| InvalidPathError(path.to_path_buf()))?;
|
||||
.ok_or_else(|| InvalidPath(path.to_path_buf()))?;
|
||||
game_file
|
||||
.filter(original_path.eq(path_str))
|
||||
.load::<DbGameFile>(conn)?
|
||||
}
|
||||
};
|
||||
|
||||
let maybe_game_files = if game_files.len() == 1 {
|
||||
Some((&game_files[0]).into())
|
||||
} else {
|
||||
None
|
||||
let maybe_game_files = match game_files.len() {
|
||||
0 => None,
|
||||
1 => Some((&game_files[0]).into()),
|
||||
num => return Err(UnexpectedBehaviour(format!("{:?}", query), num)),
|
||||
};
|
||||
|
||||
Ok(maybe_game_files)
|
||||
|
@ -168,9 +166,9 @@ impl Database {
|
|||
|
||||
// Drop GameFile Implementations
|
||||
impl Database {
|
||||
fn drop_game_file(conn: &SqliteConnection, query: GameFileQuery) -> ResultantOption<()> {
|
||||
fn drop_game_file(conn: &SqliteConnection, query: GameFileQuery) -> Result<usize> {
|
||||
use super::schema::game_file::dsl::{file_hash, game_file, original_path};
|
||||
use DatabaseError::InvalidPathError;
|
||||
use DatabaseError::{InvalidPath, UnexpectedBehaviour};
|
||||
|
||||
let num_deleted = match query {
|
||||
GameFileQuery::Hash(hash) => {
|
||||
|
@ -181,13 +179,17 @@ impl Database {
|
|||
GameFileQuery::Path(path) => {
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| InvalidPathError(path.to_path_buf()))?;
|
||||
.ok_or_else(|| InvalidPath(path.to_path_buf()))?;
|
||||
let expr = game_file.filter(original_path.eq(path_str));
|
||||
diesel::delete(expr).execute(conn)?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(if num_deleted == 1 { Some(()) } else { None })
|
||||
if num_deleted <= 1 {
|
||||
Ok(num_deleted)
|
||||
} else {
|
||||
Err(UnexpectedBehaviour(format!("{:?}", query), num_deleted))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,13 +221,10 @@ impl Database {
|
|||
// Write Game Save Location to Database
|
||||
use super::models::NewGameSaveLocation;
|
||||
use super::schema::game_save_location;
|
||||
use DatabaseEntry::Location;
|
||||
use DatabaseError::{InvalidPathError, MissingDatabaseEntry};
|
||||
use DatabaseError::InvalidPath;
|
||||
|
||||
let path = &save_loc.original_path;
|
||||
let original_path = path
|
||||
.to_str()
|
||||
.ok_or_else(|| InvalidPathError(path.clone()))?;
|
||||
let original_path = path.to_str().ok_or_else(|| InvalidPath(path.clone()))?;
|
||||
|
||||
let new_game_save = NewGameSaveLocation {
|
||||
friendly_name: save_loc.friendly_name.as_deref(),
|
||||
|
@ -238,17 +237,13 @@ impl Database {
|
|||
.execute(conn)?;
|
||||
|
||||
// Get the ID of the Game Save in the database
|
||||
let maybe_id = Self::get_game_save_id(conn, GameSaveQuery::Uuid(save_loc.uuid))?;
|
||||
let id = Self::get_game_save_id(conn, GameSaveQuery::Uuid(save_loc.uuid))?
|
||||
.expect("Failed to read entry in database after writing it.");
|
||||
|
||||
match maybe_id {
|
||||
Some(id) => {
|
||||
// Write all the GameFiles into the database
|
||||
for game_file in &save_loc.files {
|
||||
Self::write_game_file(conn, game_file, id)?;
|
||||
}
|
||||
}
|
||||
None => return Err(MissingDatabaseEntry(Location(save_loc.clone()))),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -264,7 +259,7 @@ impl Database {
|
|||
use super::schema::game_save_location::dsl::{
|
||||
friendly_name, game_save_location, id, original_path, uuid,
|
||||
};
|
||||
use DatabaseError::InvalidPathError;
|
||||
use DatabaseError::{InvalidPath, UnexpectedBehaviour};
|
||||
|
||||
let save_locs = match query {
|
||||
GameSaveQuery::Id(needle) => game_save_location
|
||||
|
@ -276,7 +271,7 @@ impl Database {
|
|||
GameSaveQuery::Path(path) => {
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| InvalidPathError(path.to_path_buf()))?;
|
||||
.ok_or_else(|| InvalidPath(path.to_path_buf()))?;
|
||||
game_save_location
|
||||
.filter(original_path.eq(path_str))
|
||||
.load::<DbGameSaveLocation>(conn)?
|
||||
|
@ -289,10 +284,10 @@ impl Database {
|
|||
}
|
||||
};
|
||||
|
||||
let maybe_save_loc = if save_locs.len() == 1 {
|
||||
Some((&save_locs[0]).into())
|
||||
} else {
|
||||
None
|
||||
let maybe_save_loc = match save_locs.len() {
|
||||
0 => None,
|
||||
1 => Some((&save_locs[0]).into()),
|
||||
num => return Err(UnexpectedBehaviour(format!("{:?}", query), num)),
|
||||
};
|
||||
|
||||
Ok(maybe_save_loc)
|
||||
|
@ -302,7 +297,7 @@ impl Database {
|
|||
use super::schema::game_save_location::dsl::{
|
||||
friendly_name, game_save_location, id, original_path, uuid,
|
||||
};
|
||||
use DatabaseError::InvalidPathError;
|
||||
use DatabaseError::{InvalidPath, UnexpectedBehaviour};
|
||||
|
||||
let ids = match query {
|
||||
GameSaveQuery::Id(id_value) => vec![id_value], // Why?
|
||||
|
@ -320,7 +315,7 @@ impl Database {
|
|||
GameSaveQuery::Path(path) => {
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| InvalidPathError(path.to_path_buf()))?;
|
||||
.ok_or_else(|| InvalidPath(path.to_path_buf()))?;
|
||||
game_save_location
|
||||
.select(id)
|
||||
.filter(original_path.eq(path_str))
|
||||
|
@ -328,31 +323,44 @@ impl Database {
|
|||
}
|
||||
};
|
||||
|
||||
// FIXME: Is there are more ergonomic way of doing this?
|
||||
Ok(if ids.len() == 1 { Some(ids[0]) } else { None })
|
||||
let maybe_id = match ids.len() {
|
||||
0 => None,
|
||||
1 => Some(ids[0]),
|
||||
num => return Err(UnexpectedBehaviour(format!("{:?}", query), num)),
|
||||
};
|
||||
|
||||
Ok(maybe_id)
|
||||
}
|
||||
|
||||
pub fn get_all_game_saves(conn: &SqliteConnection) -> ResultantOption<Vec<GameSaveLocation>> {
|
||||
use super::models::DbGameSaveLocation;
|
||||
use super::schema::game_save_location::dsl::game_save_location;
|
||||
|
||||
let db_save_locs = game_save_location
|
||||
let save_locs = game_save_location
|
||||
.load::<DbGameSaveLocation>(conn)?
|
||||
.iter()
|
||||
.map(GameSaveLocation::from)
|
||||
.collect();
|
||||
.collect::<Vec<GameSaveLocation>>();
|
||||
|
||||
Ok(Some(db_save_locs))
|
||||
let empty = save_locs.is_empty();
|
||||
Ok(if empty { None } else { Some(save_locs) })
|
||||
}
|
||||
}
|
||||
|
||||
// Drop GameSaveLocation Implementations
|
||||
impl Database {
|
||||
pub fn drop_game_save(conn: &SqliteConnection, query: GameSaveQuery) -> ResultantOption<()> {
|
||||
pub fn drop_game_save(conn: &SqliteConnection, query: GameSaveQuery) -> Result<usize> {
|
||||
use super::schema::game_save_location::dsl::{
|
||||
friendly_name, game_save_location, id, original_path, uuid,
|
||||
};
|
||||
use DatabaseError::InvalidPathError;
|
||||
use DatabaseError::{InvalidPath, UnexpectedBehaviour};
|
||||
|
||||
// Drop all files related to the to-be-deleted Game Save
|
||||
if let Some(game_save) = Self::get_game_save(conn, query)? {
|
||||
for file in game_save.files {
|
||||
Self::drop_game_file(conn, GameFileQuery::Hash(file.hash))?;
|
||||
}
|
||||
}
|
||||
|
||||
let num_deleted = match query {
|
||||
GameSaveQuery::Id(needle) => {
|
||||
|
@ -366,7 +374,7 @@ impl Database {
|
|||
GameSaveQuery::Path(path) => {
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.ok_or_else(|| InvalidPathError(path.to_path_buf()))?;
|
||||
.ok_or_else(|| InvalidPath(path.to_path_buf()))?;
|
||||
let expr = game_save_location.filter(original_path.eq(path_str));
|
||||
diesel::delete(expr).execute(conn)?
|
||||
}
|
||||
|
@ -377,19 +385,24 @@ impl Database {
|
|||
}
|
||||
};
|
||||
|
||||
// FIXME: Is there are more ergonomic way of doing this?
|
||||
Ok(if num_deleted == 1 { Some(()) } else { None })
|
||||
if num_deleted <= 1 {
|
||||
Ok(num_deleted)
|
||||
} else {
|
||||
Err(UnexpectedBehaviour(format!("{:?}", query), num_deleted))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DatabaseError {
|
||||
#[error("The path {0:?} can not be converted to a UTF-8 String")]
|
||||
InvalidPathError(PathBuf),
|
||||
InvalidPath(PathBuf),
|
||||
#[error(transparent)]
|
||||
OrmError(#[from] diesel::result::Error),
|
||||
Orm(#[from] diesel::result::Error),
|
||||
#[error("Expected {0:?} to be present in the DB but it was not")]
|
||||
MissingDatabaseEntry(DatabaseEntry),
|
||||
#[error("The Query: \"{0}\" affected {1} database entries (it should only affect one)")]
|
||||
UnexpectedBehaviour(String, usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
Loading…
Reference in New Issue