separate league logo type [refs #25]

This commit is contained in:
Thomas Weinhold 2026-01-20 20:40:11 +01:00
commit 41b27f2cc4
10 changed files with 211 additions and 190 deletions

View file

@ -1,17 +1,15 @@
use std::path::{Path, PathBuf};
use std::sync::{Arc, LockResult, RwLock};
use axum_server::tls_rustls::RustlsConfig;
use image::imageops::FilterType;
use image::{GenericImageView, ImageFormat, ImageReader};
use sslo_lib::app_state::SsloAppState;
use sslo_lib::error::SsloError;
use sslo_lib::parameters::{DEFAULT_LOBBY_URL, LEAGUE_LOGO_MAX_DIMENSION};
use sslo_lib::pathbuf::PathBufSslo;
use sslo_lib::sync::command::Commander;
use db2::DatabaseManagerData;
use shutdown_control::ShutdownControl;
use slot_mgr::SlotMgr;
use config::Config;
use crate::app_state::league_logo::LeagueLogo;
use crate::app_state::lobby_mgr::LobbyMgr;
pub mod shutdown_control;
@ -19,6 +17,7 @@ pub mod slot_mgr;
pub mod db2;
pub mod config;
mod lobby_mgr;
mod league_logo;
pub type AppState = SsloAppState<LeagueAppState>;
@ -96,6 +95,15 @@ impl LeagueAppState {
}
};
// league logo
let (league_logo_local, league_logo_http) = match LeagueLogo::install(&database_dir, &config) {
Ok((logo_local, logo_http)) => (Some(logo_local), Some(logo_http)),
Err(e) => {
log::error!("Installing league logo failed: {}", e);
(None, None)
}
};
// setup lobby manager
let lobby_mgr = match LobbyMgr::new(shutdown_control.clone(), &config) {
Ok(lobby_mgr) => lobby_mgr,
@ -112,16 +120,11 @@ impl LeagueAppState {
database_dir,
config,
database,
league_logo_http: None,
league_logo_local: None,
league_logo_http,
league_logo_local,
lobby_mgr,
};
// league logo
if let Err(e) = install_league_logo(&mut app_state) {
log::error!("Installing league logo failed: {}", e);
}
Ok(SsloAppState::new(
app_state.database_dir.clone(),
app_state
@ -159,7 +162,7 @@ impl LeagueAppState {
/// Returns a path to the htdata/ directory
pub fn path_htdata(&self) -> PathBuf {
self.database_dir.clone().push_vec(&["htdata"])
self.database_dir.clone().push_vec_str(&["htdata"])
}
/// Returns the path to the league logo as relative http path
@ -184,104 +187,3 @@ impl LeagueAppState {
}
}
/// A type that stores the path to the league logo - either as svg or png
#[derive(Clone)]
pub enum LeagueLogo {
Png(PathBuf),
Svg(PathBuf),
}
impl LeagueLogo {
/// Returns a reference to the logo path (no matter if svg or png)
pub fn path_ref(&self) -> &Path {
match self {
Self::Svg(path) => path,
Self::Png(path) => path,
}
}
}
fn install_league_logo(app_state: &mut LeagueAppState) -> Result<(), SsloError> {
// image paths
let img_src = app_state.dbpath(&app_state.config.general.logo);
let img_dst_svg = app_state.path_htdata().push_vec(&["league_logo.svg"]);
let img_dst_png = app_state.path_htdata().push_vec(&["league_logo.png"]);
// delete old logo images
if img_dst_svg.is_file() {
std::fs::remove_file(&img_dst_svg).inspect_err(|e| {
log::error!("Failed removing file '{:?}': {}", &img_dst_svg, e);
})?;
}
if img_dst_png.is_file() {
std::fs::remove_file(&img_dst_png).inspect_err(|e| {
log::error!("Failed removing file '{:?}': {}", &img_dst_png, e);
})?;
}
// process images
match img_src.extension() {
None => {
log::warn!("Invalid logo path: '{}'", img_src.display());
}
// svg
Some(extension) if extension.to_ascii_lowercase() == "svg" => {
std::fs::copy(&img_src, &img_dst_svg).inspect_err(|e| {
log::error!("Failed copying file '{:?}': {}", &img_dst_svg, &e);
})?;
app_state.league_logo_http = Some(LeagueLogo::Svg(PathBuf::from("/htdata/league_logo.svg")));
app_state.league_logo_local = Some(LeagueLogo::Svg(img_dst_svg));
},
// pixel graphic
Some(_) => {
// open image
let img = match ImageReader::open(&img_src) {
Ok(img) => match img.with_guessed_format() {
Ok(img) => img,
Err(e) => {
log::error!("Failed to read image '{:?}': {}", &img_src, e);
return Err(SsloError::GeneralError(format!("Failed to read image '{:?}': {}", &img_src, e)));
},
},
Err(e) => {
log::error!("Failed to read image '{:?}': {}", &img_src, e);
return Err(SsloError::GeneralError(format!("Failed to read image '{:?}': {}", &img_src, e)));
}
};
// decode image
let img = match img.decode() {
Ok(img) => img,
Err(e) => {
log::error!("Failed to read image '{:?}': {}", &img_src, e);
return Err(SsloError::GeneralError(format!("Failed to read image '{:?}': {}", &img_src, e)));
},
};
// limit size
let (img_width, img_height) = img.dimensions();
let max_dim = LEAGUE_LOGO_MAX_DIMENSION;
let img = match img_width > max_dim.width || img_height > max_dim.height {
true => img.resize(max_dim.width, max_dim.height, FilterType::Lanczos3),
false => img,
};
// save as png
img.save_with_format(&img_dst_png, ImageFormat::Png).inspect_err(|e| {
log::error!("Failed saving image '{:?}': {}", &img_src, e);
})?;
app_state.league_logo_http = Some(LeagueLogo::Png(PathBuf::from("/htdata/league_logo.png")));
app_state.league_logo_local = Some(LeagueLogo::Png(img_dst_png));
},
}
Ok(())
}

View file

@ -0,0 +1,109 @@
use std::path::{Path, PathBuf};
use image::imageops::FilterType;
use image::{GenericImageView, ImageFormat, ImageReader};
use sslo_lib::error::SsloError;
use sslo_lib::parameters::LEAGUE_LOGO_MAX_DIMENSION;
use sslo_lib::pathbuf::PathBufSslo;
use crate::app_state::config::Config;
/// A type that stores the path to the league logo - either as svg or png
#[derive(Clone)]
pub enum LeagueLogo {
Png(PathBuf),
Svg(PathBuf),
}
impl LeagueLogo {
/// Returns a reference to the logo path (no matter if svg or png)
pub fn path_ref(&self) -> &Path {
match self {
Self::Svg(path) => path,
Self::Png(path) => path,
}
}
/// Returns two instances: Local-Logo-Path and Http-Logo-Path on success
pub fn install(database_dir: &PathBuf, config: &Config) -> Result<(Self, Self), SsloError> {
// image paths
let img_src = database_dir.clone().push_vec_path(&[&config.general.logo]);
let img_dst_svg = database_dir.clone().push_vec_str(&["htdata", "league_logo.svg"]);
let img_dst_png = database_dir.clone().push_vec_str(&["htdata", "league_logo.png"]);
// delete old logo images
if img_dst_svg.is_file() {
std::fs::remove_file(&img_dst_svg).inspect_err(|e| {
log::error!("Failed removing file '{:?}': {}", &img_dst_svg, e);
})?;
}
if img_dst_png.is_file() {
std::fs::remove_file(&img_dst_png).inspect_err(|e| {
log::error!("Failed removing file '{:?}': {}", &img_dst_png, e);
})?;
}
// process images
match img_src.extension() {
None => {
log::warn!("Invalid logo path: '{}'", img_src.display());
Err(SsloError::GeneralError(format!("Invalid logo path (no extension): {}", img_src.display())))
}
// svg
Some(extension) if extension.to_ascii_lowercase() == "svg" => {
std::fs::copy(&img_src, &img_dst_svg).inspect_err(|e| {
log::error!("Failed copying file '{:?}': {}", &img_dst_svg, &e);
})?;
let logo_http = LeagueLogo::Svg(PathBuf::from("/htdata/league_logo.svg"));
let logo_local = LeagueLogo::Svg(img_dst_svg);
Ok((logo_local, logo_http))
},
// pixel graphic
Some(_) => {
// open image
let img = match ImageReader::open(&img_src) {
Ok(img) => match img.with_guessed_format() {
Ok(img) => img,
Err(e) => {
log::error!("Failed to read image '{:?}': {}", &img_src, e);
return Err(SsloError::GeneralError(format!("Failed to read image '{:?}': {}", &img_src, e)));
},
},
Err(e) => {
log::error!("Failed to read image '{:?}': {}", &img_src, e);
return Err(SsloError::GeneralError(format!("Failed to read image '{:?}': {}", &img_src, e)));
}
};
// decode image
let img = match img.decode() {
Ok(img) => img,
Err(e) => {
log::error!("Failed to read image '{:?}': {}", &img_src, e);
return Err(SsloError::GeneralError(format!("Failed to read image '{:?}': {}", &img_src, e)));
},
};
// limit size
let (img_width, img_height) = img.dimensions();
let max_dim = LEAGUE_LOGO_MAX_DIMENSION;
let img = match img_width > max_dim.width || img_height > max_dim.height {
true => img.resize(max_dim.width, max_dim.height, FilterType::Lanczos3),
false => img,
};
// save as png
img.save_with_format(&img_dst_png, ImageFormat::Png).inspect_err(|e| {
log::error!("Failed saving image '{:?}': {}", &img_src, e);
})?;
let logo_http = LeagueLogo::Png(PathBuf::from("/htdata/league_logo.png"));
let logo_local = LeagueLogo::Png(img_dst_png);
Ok((logo_local, logo_http))
},
}
}
}

View file

@ -215,7 +215,7 @@ pub async fn handler_edit(State(app_state): State<AppState>,
};
// save image
let mut img_path = app_state.substate().database_dir.clone().push_vec(&["htdata", "db_content", "classes"]);
let mut img_path = app_state.substate().database_dir.clone().push_vec_str(&["htdata", "db_content", "classes"]);
if let Err(e) = img_path.mkdirs() {
log::error!("Creating directory {:?} failed: {}", &img_path, e);
return ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "Could not save image").into_response();

View file

@ -11,7 +11,7 @@ use crate::app_state::db2::content::countries::CountryItem;
pub async fn install_assetto_corsa(app_state: AppState) -> Result<(), SsloError> {
// check if install package exist
let pkg_dir = app_state.substate().database_dir.clone().push_vec(&["package", "assetto_corsa"]);
let pkg_dir = app_state.substate().database_dir.clone().push_vec_str(&["package", "assetto_corsa"]);
if !pkg_dir.is_dir() {
log::warn!("Skip Assetto Corsa installation, because not found in package");
return Ok(());
@ -219,7 +219,7 @@ async fn scan_cars(app_state: AppState, ac_pkg_dir: &PathBuf) {
let tbl_liveries = app_state.substate().database.db_content().await.tbl_liveries().await;
// crate sorted list of car directories
let cars_dir = ac_pkg_dir.clone().push_vec(&["content", "cars"]);
let cars_dir = ac_pkg_dir.clone().push_vec_str(&["content", "cars"]);
let mut car_dirs: Vec<std::fs::DirEntry> = cars_dir.read_dir().map_err(|e| {
log::error!("Failed reading dir '{:?}': {}", &cars_dir, e);
return;
@ -253,7 +253,7 @@ async fn scan_cars(app_state: AppState, ac_pkg_dir: &PathBuf) {
pbar.inc(1);
// parse ui_car.json
let ui_car = match UiCarJson::from_file(car_dir.path().push_vec(&["ui", "ui_car.json"])) {
let ui_car = match UiCarJson::from_file(car_dir.path().push_vec_str(&["ui", "ui_car.json"])) {
Ok(json) => json,
Err(e) => {
log::warn!("Failed to install car {}: {}", car_id, e);
@ -270,9 +270,9 @@ async fn scan_cars(app_state: AppState, ac_pkg_dir: &PathBuf) {
}
};
if brand.set_deprecated(false).await.is_err() { continue; }
let badge = car_dir.path().push_vec(&["ui", "badge.png"]);
let badge = car_dir.path().push_vec_str(&["ui", "badge.png"]);
if badge.is_file() {
let dst = app_state.substate().database_dir.clone().push_vec(&["htdata", "db_content", "brands", &format!("{}.png", brand.id().await)]);
let dst = app_state.substate().database_dir.clone().push_vec_str(&["htdata", "db_content", "brands", &format!("{}.png", brand.id().await)]);
if let Err(e) = badge.copy_file(&dst) {
log::error!("Failed copying '{:?}' to '{:?}': {}", &badge, &dst, e);
}
@ -288,10 +288,10 @@ async fn scan_cars(app_state: AppState, ac_pkg_dir: &PathBuf) {
};
if car.set_name(&ui_car.name).await.is_err() { continue; }
if car.set_deprecated(false).await.is_err() { continue; }
let car_image = app_state.substate().database_dir.clone().push_vec(&["htdata", "db_content", "cars", &format!("{}.jpg", car.id().await)]);
let car_image = app_state.substate().database_dir.clone().push_vec_str(&["htdata", "db_content", "cars", &format!("{}.jpg", car.id().await)]);
scan_car_skins(&app_state, &car_dir.path(), &car).await;
for livery in tbl_liveries.list_by_car(&car).await {
let livery_image = app_state.substate().database_dir.clone().push_vec(&["htdata", "db_content", "liveries", &format!("{}.jpg", livery.id().await)]);
let livery_image = app_state.substate().database_dir.clone().push_vec_str(&["htdata", "db_content", "liveries", &format!("{}.jpg", livery.id().await)]);
if livery_image.is_file() {
if let Err(e) = livery_image.copy_file(&car_image) {
log::error!("Copying file from '{:?}' to '{:?}' failed: {}", &livery_image, &car_image, e);
@ -307,7 +307,7 @@ async fn scan_cars(app_state: AppState, ac_pkg_dir: &PathBuf) {
async fn scan_car_skins(app_state: &AppState, ac_pkg_car_dir: &PathBuf, car: &CarItem) {
let tbl_livs = app_state.substate().database.db_content().await.tbl_liveries().await;
let skins_dir = ac_pkg_car_dir.clone().push_vec(&["skins"]);
let skins_dir = ac_pkg_car_dir.clone().push_vec_str(&["skins"]);
let skins_dir_iterator = match skins_dir.read_dir() {
Ok(i) => i,
Err(e) => {
@ -328,7 +328,7 @@ async fn scan_car_skins(app_state: &AppState, ac_pkg_car_dir: &PathBuf, car: &Ca
// log::debug!("installing livery: {}", skin_id);
// parse ui_skin.json
let ui_skin = match UiSkinJson::from_file(skin_dir.clone().push_vec(&["ui_skin.json"])) {
let ui_skin = match UiSkinJson::from_file(skin_dir.clone().push_vec_str(&["ui_skin.json"])) {
Ok(json) => json,
Err(e) => {
log::warn!("Failed to install car/skin {}/{}: {}", car.sim_data().await, skin_id, e);
@ -349,9 +349,9 @@ async fn scan_car_skins(app_state: &AppState, ac_pkg_car_dir: &PathBuf, car: &Ca
if livery.set_deprecated(false).await.is_err() { continue; }
// check for preview
let preview = skin_dir.clone().push_vec(&["preview.jpg"]);
let preview = skin_dir.clone().push_vec_str(&["preview.jpg"]);
if preview.is_file() {
let dst = app_state.substate().database_dir.clone().push_vec(&["htdata", "db_content", "liveries", &format!("{}.jpg", livery.id().await)]);
let dst = app_state.substate().database_dir.clone().push_vec_str(&["htdata", "db_content", "liveries", &format!("{}.jpg", livery.id().await)]);
if let Err(e) = preview.copy_file(&dst) {
log::error!("Failed to copy livery image from '{:?}' to '{:?}': {}", &preview, &dst, e);
continue;
@ -374,7 +374,7 @@ async fn scan_tracks(app_state: AppState, ac_pkg_dir: &PathBuf) {
let tbl_tracks = app_state.substate().database.db_content().await.tbl_tracks().await;
// create sorted list of track directories
let tracks_dir = ac_pkg_dir.clone().push_vec(&["content", "tracks"]);
let tracks_dir = ac_pkg_dir.clone().push_vec_str(&["content", "tracks"]);
let mut track_dirs: Vec<std::fs::DirEntry> = tracks_dir.read_dir().map_err(|e| {
log::error!("Failed reading dir '{:?}': {}", &tracks_dir, e);
return;
@ -406,7 +406,7 @@ async fn scan_tracks(app_state: AppState, ac_pkg_dir: &PathBuf) {
pbar.inc(1);
// parse ui_track.json
let file_ui_track = track_dir.path().push_vec(&["ui", "ui_track.json"]);
let file_ui_track = track_dir.path().push_vec_str(&["ui", "ui_track.json"]);
if file_ui_track.is_file() {
let ui_track = match UiTrackJson::from_file(file_ui_track) {
Ok(json) => json,
@ -451,9 +451,9 @@ async fn scan_tracks(app_state: AppState, ac_pkg_dir: &PathBuf) {
log::error!("Failed to update location: {}", e);
continue;
}
let preview = track_dir.path().push_vec(&["ui", "preview.png"]);
let preview = track_dir.path().push_vec_str(&["ui", "preview.png"]);
if preview.is_file() {
let dst = app_state.substate().database_dir.clone().push_vec(&["htdata", "db_content", "locations", &format!("{}.png", location.id().await)]);
let dst = app_state.substate().database_dir.clone().push_vec_str(&["htdata", "db_content", "locations", &format!("{}.png", location.id().await)]);
if let Err(e) = preview.copy_file(&dst) {
log::error!("Failed to copy preview image from '{:?}' to '{:?}': {}", &preview, &dst, e);
continue;
@ -475,7 +475,7 @@ async fn scan_tracks(app_state: AppState, ac_pkg_dir: &PathBuf) {
// install preview
if preview.is_file() {
let dst = app_state.substate().database_dir.clone().push_vec(&["htdata", "db_content", "tracks", &format!("{}.png", track.id().await)]);
let dst = app_state.substate().database_dir.clone().push_vec_str(&["htdata", "db_content", "tracks", &format!("{}.png", track.id().await)]);
if let Err(e) = preview.copy_file(&dst) {
log::error!("Failed to copy preview image from '{:?}' to '{:?}': {}", &preview, &dst, e);
continue;
@ -498,7 +498,7 @@ async fn scan_track_variants(app_state: AppState, ac_track_dir: &PathBuf) {
// gather all ui_track jsons
let mut ui_tracks: Vec<UiTrackJson> = Vec::new();
for track_variant_dir in ac_track_dir.clone()
.push_vec(&["ui"])
.push_vec_str(&["ui"])
.read_dir()
.map_err(|e| { log::error!("Failed reading '{:?}/ui': {}", ac_track_dir, e); return; }).unwrap() {
if let Ok(track_variant_dir) = track_variant_dir {
@ -509,7 +509,7 @@ async fn scan_track_variants(app_state: AppState, ac_track_dir: &PathBuf) {
// };
// parse ui_track.json
let file_ui_track = track_variant_dir.path().push_vec(&["ui_track.json"]);
let file_ui_track = track_variant_dir.path().push_vec_str(&["ui_track.json"]);
if file_ui_track.is_file() {
match UiTrackJson::from_file(file_ui_track.clone()) {
Ok(json) => ui_tracks.push(json),
@ -585,7 +585,7 @@ async fn scan_track_variants(app_state: AppState, ac_track_dir: &PathBuf) {
return;
}
if let Some(preview) = location_preview {
let dst = app_state.substate().database_dir.clone().push_vec(&["htdata", "db_content", "locations", &format!("{}.png", location.id().await)]);
let dst = app_state.substate().database_dir.clone().push_vec_str(&["htdata", "db_content", "locations", &format!("{}.png", location.id().await)]);
if let Err(e) = preview.copy_file(&dst) {
log::error!("Failed to copy preview image from '{:?}' to '{:?}': {}", &preview, &dst, e);
return;
@ -617,9 +617,9 @@ async fn scan_track_variants(app_state: AppState, ac_track_dir: &PathBuf) {
if track.set_deprecated(false).await.is_err() {continue;}
// install preview
let preview = ui_track.path.parent().unwrap().to_path_buf().push_vec(&["preview.png"]);
let preview = ui_track.path.parent().unwrap().to_path_buf().push_vec_str(&["preview.png"]);
if preview.is_file() {
let dst = app_state.substate().database_dir.clone().push_vec(&["htdata", "db_content", "tracks", &format!("{}.png", track.id().await)]);
let dst = app_state.substate().database_dir.clone().push_vec_str(&["htdata", "db_content", "tracks", &format!("{}.png", track.id().await)]);
if let Err(e) = preview.copy_file(&dst) {
log::error!("Failed to copy preview image from '{:?}' to '{:?}': {}", &preview, &dst, e);
continue;

View file

@ -92,7 +92,7 @@ where T: Clone
}
// locate file
let abs_filepath = app_state.database_path().clone().push_vec(&["htdata", &filepath]);
let abs_filepath = app_state.database_path().clone().push_vec_str(&["htdata", &filepath]);
if !abs_filepath.is_file() {
log::warn!("Invalid file requested: {:?}", &filepath);
return Err(StatusCode::NOT_FOUND)

View file

@ -4,7 +4,10 @@ use crate::error::SsloError;
pub trait PathBufSslo {
/// push multiple sub paths into this PathBuf
fn push_vec(self, appendix: &[&str]) -> Self;
fn push_vec_str(self, appendix: &[&str]) -> Self;
/// push multiple sub paths into this PathBuf
fn push_vec_path(self, appendix: &[&Path]) -> Self;
/// When Self is an existing file, it will be copied to dst_file
fn copy_file(&self, dst_file: &Path) -> Result<(), SsloError>;
@ -15,7 +18,14 @@ pub trait PathBufSslo {
impl PathBufSslo for PathBuf {
fn push_vec(mut self, appendix: &[&str]) -> Self {
fn push_vec_str(mut self, appendix: &[&str]) -> Self {
for apx in appendix {
self.push(apx);
}
self
}
fn push_vec_path(mut self, appendix: &[&Path]) -> Self {
for apx in appendix {
self.push(apx);
}

View file

@ -94,6 +94,6 @@ impl LobbyAppState {
/// Returns a path to the htdata/ directory
pub fn path_htdata(&self) -> PathBuf {
self.database_dir.clone().push_vec(&["htdata"])
self.database_dir.clone().push_vec_str(&["htdata"])
}
}

View file

@ -174,7 +174,7 @@ impl LeagueItem {
item_data.row.upsert(&pool).await?
}
let img_path = path_htdata.push_vec(&["db_content", "leagues", &format!("{}.svg", item_data.row.rowid)]);;
let img_path = path_htdata.push_vec_str(&["db_content", "leagues", &format!("{}.svg", item_data.row.rowid)]);;
let mut file = File::create(&img_path).await.inspect_err(|e| {
log::error!("Creating file '{}' failed: {}", img_path.display(), e);
})?;
@ -199,7 +199,7 @@ impl LeagueItem {
item_data.row.upsert(&pool).await?
}
let img_path = path_htdata.push_vec(&["db_content", "leagues", &format!("{}.svg", item_data.row.rowid)]);;
let img_path = path_htdata.push_vec_str(&["db_content", "leagues", &format!("{}.svg", item_data.row.rowid)]);;
img.save_with_format(&img_path, ImageFormat::Png).inspect_err(|e| {
log::error!("Saving image to {:?} failed: {}", &img_path, e);
})?;

View file

@ -200,7 +200,7 @@ pub async fn handler_update_league_logo(State(app_state): State<AppState>,
}
// image path (without actual filename)
let mut img_path = app_state.substate().path_htdata().push_vec(&["db_content", "leagues"]);;
let mut img_path = app_state.substate().path_htdata().push_vec_str(&["db_content", "leagues"]);;
if let Err(e) = img_path.mkdirs() {
log::error!("Creating directory {:?} failed: {}", &img_path, e);
return ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, "Could not save image").into_response();

View file

@ -13,7 +13,7 @@ pub async fn work(app_state: AppState) -> Result<(), SsloError> {
if let Some(config_sim) = &app_state.config.assetto_corsa {
// check if ac exe could be found
let path_expected_ac = config_sim.install_path.clone().push_vec(&["AssettoCorsa.exe"]);
let path_expected_ac = config_sim.install_path.clone().push_vec_str(&["AssettoCorsa.exe"]);
match std::fs::exists(&path_expected_ac) {
Ok(true) => {},
Ok(false) => {
@ -35,15 +35,15 @@ pub async fn work(app_state: AppState) -> Result<(), SsloError> {
})?;
// server
let dir_ac_srv = config_sim.install_path.clone().push_vec(&["server"]);
let dir_pkg_srv = path_pkg_ac.clone().push_vec(&["server"]);
let dir_ac_srv = config_sim.install_path.clone().push_vec_str(&["server"]);
let dir_pkg_srv = path_pkg_ac.clone().push_vec_str(&["server"]);
if let Err(e) = package_server(&dir_ac_srv, &dir_pkg_srv).await {
return Err(e);
}
// tracks
let dir_tracks_ac: PathBuf = config_sim.install_path.clone().push_vec(&["content", "tracks"]);
let dir_tracks_pkg = path_pkg_ac.clone().push_vec(&["content", "tracks"]);
let dir_tracks_ac: PathBuf = config_sim.install_path.clone().push_vec_str(&["content", "tracks"]);
let dir_tracks_pkg = path_pkg_ac.clone().push_vec_str(&["content", "tracks"]);
std::fs::create_dir_all(&dir_tracks_pkg).map_err(|e| {
log::error!("Failed to create directory '{:?}': {}", &path_pkg_ac, e);
SsloError::DirCreateError(path_pkg_ac.clone())
@ -51,8 +51,8 @@ pub async fn work(app_state: AppState) -> Result<(), SsloError> {
scan_tracks(&dir_tracks_ac, &dir_tracks_pkg).await?;
// cars
let dir_cars_ac: PathBuf = config_sim.install_path.clone().push_vec(&["content", "cars"]);
let dir_cars_pkg = path_pkg_ac.clone().push_vec(&["content", "cars"]);
let dir_cars_ac: PathBuf = config_sim.install_path.clone().push_vec_str(&["content", "cars"]);
let dir_cars_pkg = path_pkg_ac.clone().push_vec_str(&["content", "cars"]);
std::fs::create_dir_all(&dir_cars_ac).map_err(|e| {
log::error!("Failed to create directory '{:?}': {}", &path_pkg_ac, e);
SsloError::DirCreateError(path_pkg_ac.clone())
@ -100,18 +100,18 @@ async fn package_server(dir_ac_server: &PathBuf, dir_pkg_server: &PathBuf) -> Re
let mut no_erros = true;
// copy acServer
let src = dir_ac_server.clone().push_vec(&["acServer"]);
let dst = dir_pkg_server.clone().push_vec(&["acServer"]);
let src = dir_ac_server.clone().push_vec_str(&["acServer"]);
let dst = dir_pkg_server.clone().push_vec_str(&["acServer"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy acServer.exe
let src = dir_ac_server.clone().push_vec(&["acServer.exe"]);
let dst = dir_pkg_server.clone().push_vec(&["acServer.exe"]);
let src = dir_ac_server.clone().push_vec_str(&["acServer.exe"]);
let dst = dir_pkg_server.clone().push_vec_str(&["acServer.exe"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy surfaces.ini
let src = dir_ac_server.clone().push_vec(&["system", "data", "surfaces.ini"]);
let dst = dir_pkg_server.clone().push_vec(&["system", "data", "surfaces.ini"]);
let src = dir_ac_server.clone().push_vec_str(&["system", "data", "surfaces.ini"]);
let dst = dir_pkg_server.clone().push_vec_str(&["system", "data", "surfaces.ini"]);
no_erros &= src.copy_file(&dst).is_ok();
// check for errors
@ -176,38 +176,38 @@ fn package_track(ac_track_dir: &PathBuf, pkg_track_dir: &PathBuf) -> Result<(),
let mut no_erros = true;
// check non-variant
let path_ui_json = ac_track_dir.clone().push_vec(&["ui", "ui_track.json"]);
let path_ui_json = ac_track_dir.clone().push_vec_str(&["ui", "ui_track.json"]);
if path_ui_json.is_file() {
// copy ui.json
let dst = pkg_track_dir.clone().push_vec(&["ui", "ui_track.json"]);
let dst = pkg_track_dir.clone().push_vec_str(&["ui", "ui_track.json"]);
no_erros &= path_ui_json.copy_file(&dst).is_ok();
// copy surfaces.ini
let src = ac_track_dir.clone().push_vec(&["data", "surfaces.ini"]);
let dst = pkg_track_dir.clone().push_vec(&["data", "surfaces.ini"]);
let src = ac_track_dir.clone().push_vec_str(&["data", "surfaces.ini"]);
let dst = pkg_track_dir.clone().push_vec_str(&["data", "surfaces.ini"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy drs_zones.ini
let src = ac_track_dir.clone().push_vec(&["data", "drs_zones.ini"]);
let src = ac_track_dir.clone().push_vec_str(&["data", "drs_zones.ini"]);
if src.is_file() {
let dst = pkg_track_dir.clone().push_vec(&["data", "drs_zones.ini"]);
let dst = pkg_track_dir.clone().push_vec_str(&["data", "drs_zones.ini"]);
no_erros &= src.copy_file(&dst).is_ok();
}
// copy outline.png
let src = ac_track_dir.clone().push_vec(&["ui", "outline.png"]);
let dst = pkg_track_dir.clone().push_vec(&["ui", "outline.png"]);
let src = ac_track_dir.clone().push_vec_str(&["ui", "outline.png"]);
let dst = pkg_track_dir.clone().push_vec_str(&["ui", "outline.png"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy preview.png
let src = ac_track_dir.clone().push_vec(&["ui", "preview.png"]);
let dst = pkg_track_dir.clone().push_vec(&["ui", "preview.png"]);
let src = ac_track_dir.clone().push_vec_str(&["ui", "preview.png"]);
let dst = pkg_track_dir.clone().push_vec_str(&["ui", "preview.png"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy map.png
let src = ac_track_dir.clone().push_vec(&["map.png"]);
let dst = pkg_track_dir.clone().push_vec(&["map.png"]);
let src = ac_track_dir.clone().push_vec_str(&["map.png"]);
let dst = pkg_track_dir.clone().push_vec_str(&["map.png"]);
no_erros &= src.copy_file(&dst).is_ok();
// check for errors
@ -217,7 +217,7 @@ fn package_track(ac_track_dir: &PathBuf, pkg_track_dir: &PathBuf) -> Result<(),
}
// check for variants
let track_ui_dir = ac_track_dir.clone().push_vec(&["ui"]);
let track_ui_dir = ac_track_dir.clone().push_vec_str(&["ui"]);
if no_erros && track_ui_dir.is_dir() {
for track_variant_ui in track_ui_dir.read_dir().map_err(|e| {
log::error!("Failed reading dir '{:?}': {}", &ac_track_dir, e);
@ -239,39 +239,39 @@ fn package_track(ac_track_dir: &PathBuf, pkg_track_dir: &PathBuf) -> Result<(),
};
// copy surfaces.ini
let src = ac_track_dir.clone().push_vec(&[&track_variant_name, "data", "surfaces.ini"]);
let src = ac_track_dir.clone().push_vec_str(&[&track_variant_name, "data", "surfaces.ini"]);
if !src.is_file() {
log::warn!("Skip packaging track, because of missing file {:?}", src);
continue;
}
let dst = pkg_track_dir.clone().push_vec(&[&track_variant_name, "data", "surfaces.ini"]);
let dst = pkg_track_dir.clone().push_vec_str(&[&track_variant_name, "data", "surfaces.ini"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy drs_zones.ini
let src = ac_track_dir.clone().push_vec(&[&track_variant_name, "data", "drs_zones.ini"]);
let src = ac_track_dir.clone().push_vec_str(&[&track_variant_name, "data", "drs_zones.ini"]);
if src.is_file() { // not all tracks have DRS
let dst = pkg_track_dir.clone().push_vec(&[&track_variant_name, "data", "drs_zones.ini"]);
let dst = pkg_track_dir.clone().push_vec_str(&[&track_variant_name, "data", "drs_zones.ini"]);
no_erros &= src.copy_file(&dst).is_ok();
}
// copy map.png
let src = ac_track_dir.clone().push_vec(&[&track_variant_name, "map.png"]);
let dst = pkg_track_dir.clone().push_vec(&[&track_variant_name, "map.png"]);
let src = ac_track_dir.clone().push_vec_str(&[&track_variant_name, "map.png"]);
let dst = pkg_track_dir.clone().push_vec_str(&[&track_variant_name, "map.png"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy ui_track.json
let src = track_variant_ui.path().push_vec(&["ui_track.json"]);
let dst = pkg_track_dir.clone().push_vec(&["ui", &track_variant_name, "ui_track.json"]);
let src = track_variant_ui.path().push_vec_str(&["ui_track.json"]);
let dst = pkg_track_dir.clone().push_vec_str(&["ui", &track_variant_name, "ui_track.json"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy outline.png
let src = track_variant_ui.path().push_vec(&["outline.png"]);
let dst = pkg_track_dir.clone().push_vec(&["ui", &track_variant_name, "outline.png"]);
let src = track_variant_ui.path().push_vec_str(&["outline.png"]);
let dst = pkg_track_dir.clone().push_vec_str(&["ui", &track_variant_name, "outline.png"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy preview.png
let src = track_variant_ui.path().push_vec(&["preview.png"]);
let dst = pkg_track_dir.clone().push_vec(&["ui", &track_variant_name, "preview.png"]);
let src = track_variant_ui.path().push_vec_str(&["preview.png"]);
let dst = pkg_track_dir.clone().push_vec_str(&["ui", &track_variant_name, "preview.png"]);
no_erros &= src.copy_file(&dst).is_ok();
// check for errors
@ -345,23 +345,23 @@ fn package_car(ac_car_dir: &PathBuf, pkg_car_dir: &PathBuf) -> Result<(), SsloEr
let mut no_erros = true;
// copy path_data_acd
let src = ac_car_dir.clone().push_vec(&["data.acd"]);
let dst = pkg_car_dir.clone().push_vec(&["data.acd"]);
let src = ac_car_dir.clone().push_vec_str(&["data.acd"]);
let dst = pkg_car_dir.clone().push_vec_str(&["data.acd"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy ui_car.json
let src = ac_car_dir.clone().push_vec(&["ui", "ui_car.json"]);
let dst = pkg_car_dir.clone().push_vec(&["ui", "ui_car.json"]);
let src = ac_car_dir.clone().push_vec_str(&["ui", "ui_car.json"]);
let dst = pkg_car_dir.clone().push_vec_str(&["ui", "ui_car.json"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy badge.png
let src = ac_car_dir.clone().push_vec(&["ui", "badge.png"]);
let dst = pkg_car_dir.clone().push_vec(&["ui", "badge.png"]);
let src = ac_car_dir.clone().push_vec_str(&["ui", "badge.png"]);
let dst = pkg_car_dir.clone().push_vec_str(&["ui", "badge.png"]);
no_erros &= src.copy_file(&dst).is_ok();
// scan skins
if no_erros {
let skins_dir = ac_car_dir.clone().push_vec(&["skins"]);
let skins_dir = ac_car_dir.clone().push_vec_str(&["skins"]);
for skin_entry in skins_dir.read_dir().map_err(|e| {
log::error!("Failed on dir '{:?}': {}", &skins_dir, e);
SsloError::DirReadError(skins_dir.clone())
@ -380,17 +380,17 @@ fn package_car(ac_car_dir: &PathBuf, pkg_car_dir: &PathBuf) -> Result<(), SsloEr
};
// copy ui_skin.json
let src = skin_entry.path().push_vec(&["ui_skin.json"]);
let src = skin_entry.path().push_vec_str(&["ui_skin.json"]);
if !src.is_file() {
log::warn!("Skiping skin, because of missing file: '{:?}'", src);
continue;
}
let dst = pkg_car_dir.clone().push_vec(&["skins", &skin_name, "ui_skin.json"]);
let dst = pkg_car_dir.clone().push_vec_str(&["skins", &skin_name, "ui_skin.json"]);
no_erros &= src.copy_file(&dst).is_ok();
// copy preview.jpg
let src = skin_entry.path().push_vec(&["preview.jpg"]);
let dst = pkg_car_dir.clone().push_vec(&["skins", &skin_name, "preview.jpg"]);
let src = skin_entry.path().push_vec_str(&["preview.jpg"]);
let dst = pkg_car_dir.clone().push_vec_str(&["skins", &skin_name, "preview.jpg"]);
no_erros &= src.copy_file(&dst).is_ok();
}
}