use super::chdman::*;
use super::checksum::*;
use super::database::*;
use super::maxcso::*;
use super::model::*;
use super::prompt::*;
use super::sevenzip::*;
use super::util::*;
use super::SimpleResult;
use async_std::path::{Path, PathBuf};
use clap::{App, Arg, ArgMatches, SubCommand};
use indicatif::ProgressBar;
use rayon::prelude::*;
use sqlx::sqlite::SqlitePool;
use std::collections::HashSet;
use std::str::FromStr;
pub fn subcommand<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("import-roms")
.about("Validates and imports ROM files into oxyromon")
.arg(
Arg::with_name("ROMS")
.help("Sets the ROM files to import")
.required(true)
.multiple(true)
.index(1),
)
.arg(
Arg::with_name("SYSTEM")
.short("s")
.long("system")
.help("Sets the system number to use")
.required(false)
.takes_value(true),
)
}
pub async fn main(
pool: &SqlitePool,
matches: &ArgMatches<'_>,
progress_bar: &ProgressBar,
) -> SimpleResult<()> {
let romfile_paths: Vec<String> = matches.values_of_lossy("ROMS").unwrap();
let system = prompt_for_system(
pool,
matches
.value_of("SYSTEM")
.map(|s| FromStr::from_str(s).expect("Failed to parse number")),
)
.await?;
let header = find_header_by_system_id(pool, system.id).await;
let system_directory = get_system_directory(pool, &system).await?;
for romfile_path in romfile_paths {
let romfile_path = get_canonicalized_path(&romfile_path).await?;
import_rom(
pool,
&progress_bar,
&system_directory,
&system,
&header,
&romfile_path,
)
.await?;
}
Ok(())
}
pub async fn import_rom<P: AsRef<Path>, Q: AsRef<Path>>(
pool: &SqlitePool,
progress_bar: &ProgressBar,
system_directory: &Q,
system: &System,
header: &Option<Header>,
romfile_path: &P,
) -> SimpleResult<()> {
progress_bar.println(&format!(
"Processing {:?}",
romfile_path.as_ref().file_name().unwrap()
));
if find_romfile_by_path(pool, romfile_path.as_ref().as_os_str().to_str().unwrap())
.await
.is_some()
{
progress_bar.println("Already in database");
return Ok(());
}
let romfile_extension = romfile_path
.as_ref()
.extension()
.unwrap()
.to_str()
.unwrap()
.to_lowercase();
if ARCHIVE_EXTENSIONS.contains(&romfile_extension.as_str()) {
import_archive(
pool,
&progress_bar,
&system_directory,
&system,
&header,
&romfile_path,
&romfile_extension,
)
.await?;
} else if CHD_EXTENSION == romfile_extension {
import_chd(
pool,
&progress_bar,
&system_directory,
&system,
&header,
&romfile_path,
)
.await?;
} else if CSO_EXTENSION == romfile_extension {
import_cso(
pool,
&progress_bar,
&system_directory,
&system,
&header,
&romfile_path,
)
.await?;
} else {
import_other(
pool,
&progress_bar,
&system_directory,
&system,
&header,
&romfile_path,
)
.await?;
}
Ok(())
}
async fn import_archive<P: AsRef<Path>, Q: AsRef<Path>>(
pool: &SqlitePool,
progress_bar: &ProgressBar,
system_directory: &Q,
system: &System,
header: &Option<Header>,
romfile_path: &P,
romfile_extension: &str,
) -> SimpleResult<()> {
let tmp_directory = create_tmp_directory(pool).await?;
let sevenzip_infos = parse_archive(progress_bar, romfile_path)?;
let mut roms_sevenzip_infos: Vec<(Rom, &ArchiveInfo, Option<PathBuf>)> = Vec::new();
let mut game_ids: HashSet<i64> = HashSet::new();
for sevenzip_info in &sevenzip_infos {
let size: u64;
let crc: String;
let mut extracted_path = None;
if header.is_some() || sevenzip_info.crc.is_empty() {
extracted_path = Some(
extract_files_from_archive(
&progress_bar,
romfile_path,
&[&sevenzip_info.path],
&tmp_directory.path(),
)?
.remove(0),
);
let size_crc = get_file_size_and_crc(
progress_bar,
extracted_path.as_ref().unwrap(),
&header,
1,
1,
)
.await?;
size = size_crc.0;
crc = size_crc.1;
} else {
size = sevenzip_info.size;
crc = sevenzip_info.crc.clone();
}
match find_rom(pool, size, &crc, &system, &progress_bar).await? {
Some(rom) => {
game_ids.insert(rom.game_id);
roms_sevenzip_infos.push((rom, sevenzip_info, extracted_path));
}
None => {
if sevenzip_infos.len() == 1 {
if let Some(extracted_path) = extracted_path {
remove_file(&extracted_path).await?;
}
move_to_trash(pool, progress_bar, system, romfile_path).await?;
} else {
if let Some(extracted_path) = extracted_path {
move_to_trash(pool, progress_bar, system, &extracted_path).await?;
}
delete_files_from_archive(
progress_bar,
romfile_path,
&vec![sevenzip_info.path.as_str()],
)?;
}
}
}
}
if roms_sevenzip_infos.len() == 1 {
let (rom, sevenzip_info, _) = roms_sevenzip_infos.remove(0);
let new_path = system_directory
.as_ref()
.join(format!("{}.{}", &rom.name, &romfile_extension));
if sevenzip_info.path != rom.name {
rename_file_in_archive(progress_bar, romfile_path, &sevenzip_info.path, &rom.name)?;
}
move_file(progress_bar, romfile_path, &new_path).await?;
create_or_update_romfile(pool, &new_path, &vec![rom]).await;
} else if roms_sevenzip_infos.len() > 1 {
if game_ids.len() == 1 {
let game_id = game_ids.drain().last().unwrap();
let rom_ids: HashSet<i64> = find_roms_by_game_id(pool, game_id)
.await
.into_par_iter()
.map(|rom| rom.id)
.collect();
if rom_ids
.difference(
&roms_sevenzip_infos
.par_iter()
.map(|(rom, _, _)| rom.id)
.collect(),
)
.collect::<Vec<&i64>>()
.len()
== 0
{
let game = find_game_by_id(pool, game_id).await;
for (rom, sevenzip_info, _) in &roms_sevenzip_infos {
if &sevenzip_info.path != &rom.name {
rename_file_in_archive(
progress_bar,
romfile_path,
&sevenzip_info.path,
&rom.name,
)?;
}
}
let new_path = system_directory
.as_ref()
.join(format!("{}.{}", &game.name, &romfile_extension));
move_file(progress_bar, romfile_path, &new_path).await?;
create_or_update_romfile(
pool,
&new_path,
&roms_sevenzip_infos
.into_iter()
.map(|(rom, _, _)| rom)
.collect::<Vec<Rom>>(),
)
.await;
return Ok(());
}
}
for (rom, sevenzip_info, extracted_path) in roms_sevenzip_infos {
let extracted_path = match extracted_path {
Some(extracted_path) => extracted_path,
None => extract_files_from_archive(
&progress_bar,
romfile_path,
&[&sevenzip_info.path],
&tmp_directory.path(),
)?
.remove(0),
};
let new_path = system_directory.as_ref().join(&rom.name);
move_file(progress_bar, &extracted_path, &new_path).await?;
create_or_update_romfile(pool, &new_path, &vec![rom]).await;
}
remove_file(romfile_path).await?;
}
Ok(())
}
async fn import_chd<P: AsRef<Path>, Q: AsRef<Path>>(
pool: &SqlitePool,
progress_bar: &ProgressBar,
system_directory: &Q,
system: &System,
header: &Option<Header>,
romfile_path: &P,
) -> SimpleResult<()> {
let tmp_directory = create_tmp_directory(pool).await?;
let mut cue_path = romfile_path.as_ref().to_path_buf();
cue_path.set_extension(CUE_EXTENSION);
if cue_path.is_file().await {
progress_bar.println("CUE file found, using multiple tracks mode");
let (size, crc) = get_file_size_and_crc(progress_bar, &cue_path, &header, 1, 1).await?;
let cue_rom = match find_rom(pool, size, &crc, &system, &progress_bar).await? {
Some(rom) => rom,
None => {
move_to_trash(pool, progress_bar, system, &cue_path).await?;
return Ok(());
}
};
let roms: Vec<Rom> = find_roms_by_game_id(pool, cue_rom.game_id)
.await
.into_iter()
.filter(|rom| rom.id != cue_rom.id)
.collect();
let names_sizes: Vec<(&str, u64)> = roms
.iter()
.map(|rom| (rom.name.as_str(), rom.size as u64))
.collect();
let bin_paths = extract_chd_to_multiple_tracks(
progress_bar,
romfile_path,
&tmp_directory.path(),
&names_sizes,
)
.await?;
let mut crcs: Vec<String> = Vec::new();
for (i, bin_path) in bin_paths.iter().enumerate() {
let (_, crc) =
get_file_size_and_crc(progress_bar, &bin_path, &header, i, bin_paths.len()).await?;
crcs.push(crc);
remove_file(&bin_path).await?;
}
if roms.iter().enumerate().any(|(i, rom)| crcs[i] != rom.crc) {
progress_bar.println("CRC mismatch");
move_to_trash(pool, progress_bar, system, romfile_path).await?;
return Ok(());
}
let new_cue_path = system_directory.as_ref().join(&cue_rom.name);
let mut new_chd_path = new_cue_path.clone();
new_chd_path.set_extension(CHD_EXTENSION);
move_file(progress_bar, &cue_path, &new_cue_path).await?;
move_file(progress_bar, romfile_path, &new_chd_path).await?;
create_or_update_romfile(pool, &new_cue_path, &vec![cue_rom]).await;
create_or_update_romfile(pool, &new_chd_path, &roms).await;
Ok(())
} else {
progress_bar.println("CUE file not found, using single track mode");
let bin_path =
extract_chd_to_single_track(progress_bar, romfile_path, &tmp_directory.path()).await?;
let (size, crc) = get_file_size_and_crc(progress_bar, &bin_path, &header, 1, 1).await?;
remove_file(&bin_path).await?;
let rom = match find_rom(pool, size, &crc, &system, &progress_bar).await? {
Some(rom) => rom,
None => {
move_to_trash(pool, progress_bar, system, romfile_path).await?;
return Ok(());
}
};
let mut new_chd_path = system_directory.as_ref().join(&rom.name);
new_chd_path.set_extension(CHD_EXTENSION);
move_file(progress_bar, romfile_path, &new_chd_path).await?;
create_or_update_romfile(pool, &new_chd_path, &vec![rom]).await;
Ok(())
}
}
async fn import_cso<P: AsRef<Path>, Q: AsRef<Path>>(
pool: &SqlitePool,
progress_bar: &ProgressBar,
system_directory: &Q,
system: &System,
header: &Option<Header>,
romfile_path: &P,
) -> SimpleResult<()> {
let tmp_directory = create_tmp_directory(pool).await?;
let iso_path = extract_cso(progress_bar, romfile_path, &tmp_directory.path())?;
let (size, crc) = get_file_size_and_crc(progress_bar, &iso_path, &header, 1, 1).await?;
remove_file(&iso_path).await?;
let rom = match find_rom(pool, size, &crc, &system, &progress_bar).await? {
Some(rom) => rom,
None => {
move_to_trash(pool, progress_bar, system, romfile_path).await?;
return Ok(());
}
};
let mut new_cso_path = system_directory.as_ref().join(&rom.name);
new_cso_path.set_extension(CSO_EXTENSION);
move_file(progress_bar, romfile_path, &new_cso_path).await?;
create_or_update_romfile(pool, &new_cso_path, &vec![rom]).await;
Ok(())
}
async fn import_other<P: AsRef<Path>, Q: AsRef<Path>>(
pool: &SqlitePool,
progress_bar: &ProgressBar,
system_directory: &Q,
system: &System,
header: &Option<Header>,
romfile_path: &P,
) -> SimpleResult<()> {
let (size, crc) = get_file_size_and_crc(progress_bar, romfile_path, &header, 1, 1).await?;
let rom = match find_rom(pool, size, &crc, &system, &progress_bar).await? {
Some(rom) => rom,
None => {
move_to_trash(pool, progress_bar, system, romfile_path).await?;
return Ok(());
}
};
let new_path = system_directory.as_ref().join(&rom.name);
move_file(progress_bar, romfile_path, &new_path).await?;
create_or_update_romfile(pool, &new_path, &vec![rom]).await;
Ok(())
}
async fn find_rom(
pool: &SqlitePool,
size: u64,
crc: &str,
system: &System,
progress_bar: &ProgressBar,
) -> SimpleResult<Option<Rom>> {
let rom: Rom;
let mut roms = find_roms_by_size_and_crc_and_system_id(pool, size, crc, system.id).await;
if roms.is_empty() {
progress_bar.println("No match");
return Ok(None);
}
if roms.len() == 1 {
rom = roms.remove(0);
progress_bar.println(&format!("Matches \"{}\"", rom.name));
} else {
rom = prompt_for_rom(&mut roms)?;
}
if rom.romfile_id.is_some() {
let romfile = find_romfile_by_id(pool, rom.romfile_id.unwrap()).await;
progress_bar.println(&format!("Duplicate of \"{}\"", romfile.path));
return Ok(None);
}
Ok(Some(rom))
}
async fn create_or_update_romfile<P: AsRef<Path>>(pool: &SqlitePool, path: &P, roms: &[Rom]) {
let romfile_path = path.as_ref().as_os_str().to_str().unwrap();
let romfile = find_romfile_by_path(pool, romfile_path).await;
let romfile_id = match romfile {
Some(romfile) => {
update_romfile(pool, romfile.id, romfile_path).await;
romfile.id
}
None => create_romfile(pool, romfile_path).await,
};
for rom in roms {
update_rom_romfile(pool, rom.id, Some(romfile_id)).await;
}
}
async fn move_to_trash<P: AsRef<Path>>(
pool: &SqlitePool,
progress_bar: &ProgressBar,
system: &System,
romfile_path: &P,
) -> SimpleResult<()> {
let new_path = get_trash_directory(pool, system)
.await?
.join(romfile_path.as_ref().file_name().unwrap());
move_file(progress_bar, romfile_path, &new_path).await?;
create_romfile(pool, new_path.as_os_str().to_str().unwrap()).await;
Ok(())
}
async fn move_file<P: AsRef<Path>, Q: AsRef<Path>>(
progress_bar: &ProgressBar,
old_path: &P,
new_path: &Q,
) -> SimpleResult<()> {
if old_path.as_ref() != new_path.as_ref() {
progress_bar.println(&format!("Moving to {:?}", new_path.as_ref().as_os_str()));
rename_file(old_path, new_path).await?;
}
Ok(())
}
#[cfg(test)]
mod test {
use super::super::config::*;
use super::super::database::*;
use super::super::import_dats;
use super::*;
use async_std::fs;
use async_std::path::PathBuf;
use std::env;
use tempfile::{NamedTempFile, TempDir};
#[async_std::test]
async fn test_import_sevenzip_single_file() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe).rom.7z");
fs::copy(
test_directory.join("Test Game (USA, Europe).rom.7z"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_archive(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
&romfile_path.extension().unwrap().to_str().unwrap(),
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 1);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 1);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe)");
assert_eq!(game.system_id, system.id);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).rom");
assert_eq!(rom.game_id, game.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).rom.7z")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
#[async_std::test]
async fn test_import_sevenzip_single_file_with_header() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20210402) (Headered).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Headered).rom.7z");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Headered).rom.7z"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
let header = find_header_by_system_id(&pool, system.id).await;
import_archive(
&pool,
&progress_bar,
&system_directory,
&system,
&header,
&romfile_path,
&romfile_path.extension().unwrap().to_str().unwrap(),
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 1);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 1);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe)");
assert_eq!(game.system_id, system.id);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).rom");
assert_eq!(rom.game_id, game.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).rom.7z")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
assert_eq!(rom.romfile_id, Some(romfile.id));
let sevenzip_infos = parse_archive(&progress_bar, &romfile.path).unwrap();
assert_eq!(sevenzip_infos.len(), 1);
assert_eq!(
sevenzip_infos.get(0).unwrap().path,
"Test Game (USA, Europe).rom"
);
}
#[async_std::test]
async fn test_import_sevenzip_multiple_files_full_game() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Full).7z");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Full).7z"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_archive(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
&romfile_path.extension().unwrap().to_str().unwrap(),
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 3);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 1);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe) (CUE BIN)");
assert_eq!(game.system_id, system.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe) (CUE BIN).7z")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe) (Track 01).bin");
assert_eq!(rom.game_id, game.id);
assert_eq!(rom.romfile_id, Some(romfile.id));
let rom = roms.get(1).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe) (Track 02).bin");
assert_eq!(rom.game_id, game.id);
assert_eq!(rom.romfile_id, Some(romfile.id));
let rom = roms.get(2).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).cue");
assert_eq!(rom.game_id, game.id);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
#[async_std::test]
async fn test_import_sevenzip_multiple_files_partial_game() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Partial).7z");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Partial).7z"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_archive(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
&romfile_path.extension().unwrap().to_str().unwrap(),
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 2);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 2);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe) (CUE BIN)");
assert_eq!(game.system_id, system.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe) (Track 01).bin")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe) (Track 01).bin");
assert_eq!(rom.game_id, game.id);
assert_eq!(rom.romfile_id, Some(romfile.id));
let romfile = romfiles.get(1).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).cue")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
let rom = roms.get(1).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).cue");
assert_eq!(rom.game_id, game.id);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
#[async_std::test]
async fn test_import_sevenzip_multiple_files_mixed_games() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Mixed).7z");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Mixed).7z"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_archive(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
&romfile_path.extension().unwrap().to_str().unwrap(),
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 2);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 2);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 2);
let game = games.get(1).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe) (Beta)");
assert_eq!(game.system_id, system.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe) (Beta).rom")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe) (Beta).rom");
assert_eq!(rom.game_id, game.id);
assert_eq!(rom.romfile_id, Some(romfile.id));
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe)");
assert_eq!(game.system_id, system.id);
let romfile = romfiles.get(1).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).rom")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
let rom = roms.get(1).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).rom");
assert_eq!(rom.game_id, game.id);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
#[async_std::test]
async fn test_import_sevenzip_multiple_files_mixed_games_with_header() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20210402) (Headered).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Mixed) (Headered).7z");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Mixed) (Headered).7z"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
let header = find_header_by_system_id(&pool, system.id).await;
import_archive(
&pool,
&progress_bar,
&system_directory,
&system,
&header,
&romfile_path,
&romfile_path.extension().unwrap().to_str().unwrap(),
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 1);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 2);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe)");
assert_eq!(game.system_id, system.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).rom.7z")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).rom");
assert_eq!(rom.game_id, game.id);
assert_eq!(rom.romfile_id, Some(romfile.id));
let sevenzip_infos = parse_archive(&progress_bar, &romfile.path).unwrap();
assert_eq!(sevenzip_infos.len(), 1);
assert_eq!(
sevenzip_infos.get(0).unwrap().path,
"Test Game (USA, Europe).rom"
);
let romfile = romfiles.get(1).unwrap();
assert!(romfile.path.contains("/Trash/"));
}
#[async_std::test]
async fn test_import_zip_single_file() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe).rom.zip");
fs::copy(
test_directory.join("Test Game (USA, Europe).rom.zip"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_archive(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
&romfile_path.extension().unwrap().to_str().unwrap(),
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 1);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 1);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe)");
assert_eq!(game.system_id, system.id);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).rom");
assert_eq!(rom.game_id, game.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).rom.zip")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
#[async_std::test]
async fn test_import_chd_single_track() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Single Track).chd");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Single Track).chd"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_chd(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 1);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 1);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe) (ISO)");
assert_eq!(game.system_id, system.id);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).iso");
assert_eq!(rom.game_id, game.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).chd")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
#[async_std::test]
async fn test_import_chd_multiple_tracks() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Multiple Tracks).cue");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Multiple Tracks).cue"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Multiple Tracks).chd");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Multiple Tracks).chd"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_chd(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 3);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 2);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe) (CUE BIN)");
assert_eq!(game.system_id, system.id);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe) (Track 01).bin");
assert_eq!(rom.game_id, game.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).chd")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
assert_eq!(rom.romfile_id, Some(romfile.id));
let rom = roms.get(1).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe) (Track 02).bin");
assert_eq!(rom.game_id, game.id);
let rom = roms.get(2).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).cue");
assert_eq!(rom.game_id, game.id);
let romfile = romfiles.get(1).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).cue")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
#[async_std::test]
async fn test_import_chd_multiple_tracks_without_cue_should_fail() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Multiple Tracks).chd");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Multiple Tracks).chd"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_chd(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert!(roms.is_empty());
}
#[async_std::test]
async fn test_import_cso() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
env::set_var(
"PATH",
format!(
"{}:{}",
test_directory.as_os_str().to_str().unwrap(),
env::var("PATH").unwrap()
),
);
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe).cso");
fs::copy(
test_directory.join("Test Game (USA, Europe).cso"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_cso(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 1);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 1);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe) (ISO)");
assert_eq!(game.system_id, system.id);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).iso");
assert_eq!(rom.game_id, game.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).cso")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
#[async_std::test]
async fn test_import_other() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20200721).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe).rom");
fs::copy(
test_directory.join("Test Game (USA, Europe).rom"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
import_other(
&pool,
&progress_bar,
&system_directory,
&system,
&None,
&romfile_path,
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 1);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 1);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe)");
assert_eq!(game.system_id, system.id);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).rom");
assert_eq!(rom.game_id, game.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).rom")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
#[async_std::test]
async fn test_import_other_headered() {
let _guard = MUTEX.lock().await;
let test_directory = Path::new("test");
let progress_bar = ProgressBar::hidden();
let db_file = NamedTempFile::new().unwrap();
let pool = establish_connection(db_file.path().to_str().unwrap()).await;
let matches = import_dats::subcommand()
.get_matches_from(&["import-dats", "test/Test System (20210402) (Headered).dat"]);
import_dats::main(&pool, &matches, &progress_bar)
.await
.unwrap();
let rom_directory = TempDir::new_in(&test_directory).unwrap();
let rom_directory = set_rom_directory(PathBuf::from(rom_directory.path()));
let tmp_directory = TempDir::new_in(&test_directory).unwrap();
let tmp_directory = set_tmp_directory(PathBuf::from(tmp_directory.path()));
let system_directory = &rom_directory.join("Test System");
create_directory(&system_directory).await.unwrap();
let romfile_path = tmp_directory.join("Test Game (USA, Europe) (Headered).rom");
fs::copy(
test_directory.join("Test Game (USA, Europe) (Headered).rom"),
&romfile_path.as_os_str().to_str().unwrap(),
)
.await
.unwrap();
let system = find_systems(&pool).await.remove(0);
let header = find_header_by_system_id(&pool, system.id).await;
import_other(
&pool,
&progress_bar,
&system_directory,
&system,
&header,
&romfile_path,
)
.await
.unwrap();
let roms = find_roms_with_romfile_by_system_id(&pool, system.id).await;
assert_eq!(roms.len(), 1);
let romfiles = find_romfiles(&pool).await;
assert_eq!(romfiles.len(), 1);
let games = find_games_by_ids(
&pool,
&roms
.iter()
.map(|rom| rom.game_id)
.collect::<Vec<i64>>()
.as_slice(),
)
.await;
assert_eq!(games.len(), 1);
let game = games.get(0).unwrap();
assert_eq!(game.name, "Test Game (USA, Europe)");
assert_eq!(game.system_id, system.id);
let rom = roms.get(0).unwrap();
assert_eq!(rom.name, "Test Game (USA, Europe).rom");
assert_eq!(rom.game_id, game.id);
let romfile = romfiles.get(0).unwrap();
assert_eq!(
romfile.path,
system_directory
.join("Test Game (USA, Europe).rom")
.as_os_str()
.to_str()
.unwrap(),
);
assert!(Path::new(&romfile.path).is_file().await);
assert_eq!(rom.romfile_id, Some(romfile.id));
}
}