Refactor main.rs into separate files

Create new `commands` mod with file for each command line option.

Create a couple more extractor files for moving 7zip and unrar methods into.
This commit is contained in:
2022-02-08 00:02:26 -05:00
parent 51175933d6
commit b8c5f63aeb
11 changed files with 589 additions and 511 deletions

View File

@@ -7,6 +7,10 @@ use std::io::Seek;
use std::io::SeekFrom;
use tracing::{info, info_span};
use crate::models::file::File;
use crate::models::game_mod::Mod;
use crate::plugin_processor::process_plugin;
#[derive(Debug)]
pub struct ExtractorError;
@@ -78,3 +82,19 @@ impl<'a> Iterator for Extractor<'a> {
None
}
}
pub async fn extract_with_compress_tools(
file: &mut std::fs::File,
pool: &sqlx::Pool<sqlx::Postgres>,
db_file: &File,
db_mod: &Mod,
) -> Result<()> {
let extractor = Extractor::new(file);
for plugin in extractor.into_iter() {
let (file_path, mut plugin_buf) = plugin?;
let plugin_span = info_span!("plugin", name = ?file_path);
let _plugin_span = plugin_span.enter();
process_plugin(&mut plugin_buf, &pool, &db_file, &db_mod, &file_path).await?;
}
Ok(())
}

View File

@@ -1 +1,7 @@
pub mod compress_tools;
pub mod seven_zip;
pub mod unrar;
pub use self::compress_tools::extract_with_compress_tools;
pub use self::unrar::extract_with_unrar;
pub use seven_zip::extract_with_7zip;

View File

@@ -0,0 +1,61 @@
use anyhow::Result;
use std::io::{Seek, SeekFrom};
use std::process::Command;
use tempfile::tempdir;
use tracing::{info, info_span};
use walkdir::WalkDir;
use crate::models::file::File;
use crate::models::game_mod::Mod;
use crate::plugin_processor::process_plugin;
pub async fn extract_with_7zip(
file: &mut std::fs::File,
pool: &sqlx::Pool<sqlx::Postgres>,
db_file: &File,
db_mod: &Mod,
) -> Result<()> {
file.seek(SeekFrom::Start(0))?;
let temp_dir = tempdir()?;
let temp_file_path = temp_dir.path().join("download.zip");
let mut temp_file = std::fs::File::create(&temp_file_path)?;
std::io::copy(file, &mut temp_file)?;
drop(temp_file); // close handle to temp file so 7zip process can open it
let extracted_path = temp_dir.path().join("extracted");
Command::new("7z")
.args(&[
"x",
&format!("-o{}", &extracted_path.to_string_lossy()),
&temp_file_path.to_string_lossy().to_string(),
])
.status()?;
for entry in WalkDir::new(&extracted_path)
.contents_first(true)
.into_iter()
.filter_entry(|e| {
if let Some(extension) = e.path().extension() {
extension == "esp" || extension == "esm" || extension == "esl"
} else {
false
}
})
{
let entry = entry?;
let file_path = entry.path();
let plugin_span = info_span!("plugin", name = ?file_path);
let _plugin_span = plugin_span.enter();
info!("processing uncompressed file from downloaded archive");
let mut plugin_buf = std::fs::read(extracted_path.join(file_path))?;
process_plugin(
&mut plugin_buf,
&pool,
&db_file,
&db_mod,
&file_path.to_string_lossy(),
)
.await?;
}
Ok(())
}

88
src/extractors/unrar.rs Normal file
View File

@@ -0,0 +1,88 @@
use anyhow::Result;
use tempfile::tempdir;
use tracing::{error, info, warn};
use unrar::Archive;
use crate::models::file::{self, File};
use crate::models::game_mod::Mod;
use crate::plugin_processor::process_plugin;
pub async fn extract_with_unrar(
file: &mut std::fs::File,
pool: &sqlx::Pool<sqlx::Postgres>,
db_file: &File,
db_mod: &Mod,
checked_metadata: bool,
) -> Result<()> {
let temp_dir = tempdir()?;
let temp_file_path = temp_dir.path().join("download.rar");
let mut temp_file = std::fs::File::create(&temp_file_path)?;
std::io::copy(file, &mut temp_file)?;
let mut plugin_file_paths = Vec::new();
let list = Archive::new(&temp_file_path.to_string_lossy().to_string())?.list();
match list {
Ok(list) => {
for entry in list.flatten() {
if let Some(extension) = entry.filename.extension() {
if entry.is_file()
&& (extension == "esp" || extension == "esm" || extension == "esl")
{
plugin_file_paths.push(entry.filename);
}
}
}
}
Err(_) => {
if !checked_metadata {
warn!("failed to read archive and server has no metadata, skipping file");
file::update_unable_to_extract_plugins(&pool, db_file.id, true).await?;
return Ok(());
} else {
error!("failed to read archive, but server had metadata");
panic!("failed to read archive, but server had metadata");
}
}
}
info!(
num_plugin_files = plugin_file_paths.len(),
"listed plugins in downloaded archive"
);
if !plugin_file_paths.is_empty() {
info!("uncompressing downloaded archive");
let extract = Archive::new(&temp_file_path.to_string_lossy().to_string())?
.extract_to(temp_dir.path().to_string_lossy().to_string());
let mut extract = match extract {
Err(err) => {
warn!(error = %err, "failed to extract with unrar");
file::update_unable_to_extract_plugins(&pool, db_file.id, true).await?;
return Ok(());
}
Ok(extract) => extract,
};
if let Err(err) = extract.process() {
warn!(error = %err, "failed to extract with unrar");
file::update_unable_to_extract_plugins(&pool, db_file.id, true).await?;
return Ok(());
}
for file_path in plugin_file_paths.iter() {
info!(
?file_path,
"processing uncompressed file from downloaded archive"
);
let mut plugin_buf = std::fs::read(temp_dir.path().join(file_path))?;
process_plugin(
&mut plugin_buf,
&pool,
&db_file,
&db_mod,
&file_path.to_string_lossy(),
)
.await?;
}
}
Ok(())
}