mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
add asset_tweak_or_create
that will create file
This commit is contained in:
@ -128,6 +128,22 @@ impl Asset for DotVoxAsset {
|
|||||||
const EXTENSION: &'static str = "vox";
|
const EXTENSION: &'static str = "vox";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_root() -> Option<PathBuf> {
|
||||||
|
std::env::current_dir().map_or(None, |path| {
|
||||||
|
// If we are in the root, push path
|
||||||
|
if path.join(".git").is_dir() {
|
||||||
|
return Some(path);
|
||||||
|
}
|
||||||
|
// Search .git directory in parent directries
|
||||||
|
for ancestor in path.ancestors().take(10) {
|
||||||
|
if ancestor.join(".git").is_dir() {
|
||||||
|
return Some(ancestor.to_path_buf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// Lazy static to find and cache where the asset directory is.
|
/// Lazy static to find and cache where the asset directory is.
|
||||||
/// Cases we need to account for:
|
/// Cases we need to account for:
|
||||||
@ -154,19 +170,8 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. Root of the repository
|
// 3. Root of the repository
|
||||||
if let Ok(path) = std::env::current_dir() {
|
if let Some(path) = find_root() {
|
||||||
// If we are in the root, push path
|
|
||||||
if path.join(".git").is_dir() {
|
|
||||||
paths.push(path);
|
paths.push(path);
|
||||||
} else {
|
|
||||||
// Search .git directory in parent directries
|
|
||||||
for ancestor in path.ancestors().take(10) {
|
|
||||||
if ancestor.join(".git").is_dir() {
|
|
||||||
paths.push(ancestor.to_path_buf());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. System paths
|
// 4. System paths
|
||||||
@ -255,9 +260,12 @@ impl Compound for Directory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[warn(clippy::pedantic)]
|
||||||
pub mod asset_tweak {
|
pub mod asset_tweak {
|
||||||
use super::{Asset, AssetExt, RonLoader};
|
// Return path to repository by searching 10 directories back
|
||||||
use serde::{de::DeserializeOwned, Deserialize};
|
use super::{find_root, fs, Asset, AssetExt, Path, RonLoader};
|
||||||
|
use ron::ser::{to_writer_pretty, PrettyConfig};
|
||||||
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize)]
|
||||||
struct AssetTweakWrapper<T>(T);
|
struct AssetTweakWrapper<T>(T);
|
||||||
@ -271,46 +279,103 @@ pub mod asset_tweak {
|
|||||||
const EXTENSION: &'static str = "ron";
|
const EXTENSION: &'static str = "ron";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NOTE: Don't use it in code, it's debug only
|
#[must_use]
|
||||||
pub fn tweak_expect<T>(path: &str) -> T
|
/// NOTE: Don't use it in production code, it's debug only
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
/// Create file with content which represent tweaked value
|
||||||
|
///
|
||||||
|
/// Example if you want to tweak integer value
|
||||||
|
/// ```no_run
|
||||||
|
/// use veloren_common_assets::asset_tweak;
|
||||||
|
/// let x: i32 = asset_tweak::tweak_expect("x");
|
||||||
|
/// ```
|
||||||
|
/// File needs to look like that
|
||||||
|
/// ```text
|
||||||
|
/// assets/tweak/x.ron
|
||||||
|
/// (5)
|
||||||
|
/// ```
|
||||||
|
/// Note the parentheses.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// 1) If given `asset_specifier` does not exists
|
||||||
|
pub fn tweak_expect<T>(asset_specifier: &str) -> T
|
||||||
where
|
where
|
||||||
T: Clone + Sized + Send + Sync + 'static + DeserializeOwned,
|
T: Clone + Sized + Send + Sync + 'static + DeserializeOwned,
|
||||||
{
|
{
|
||||||
|
if cfg!(not(any(debug_assertions, test))) {
|
||||||
tracing::warn!("AssetTweaker used in release build!");
|
tracing::warn!("AssetTweaker used in release build!");
|
||||||
let handle = <AssetTweakWrapper<T> as AssetExt>::load_expect(path);
|
}
|
||||||
|
let handle = <AssetTweakWrapper<T> as AssetExt>::load_expect(asset_specifier);
|
||||||
let AssetTweakWrapper(value) = handle.read().clone();
|
let AssetTweakWrapper(value) = handle.read().clone();
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
/// NOTE: Don't use it in production code, it's debug only
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
/// Will create file "assets/tweak/{specifier}.ron" if not exists.
|
||||||
|
/// If exists will read a value from such file.
|
||||||
|
///
|
||||||
|
/// Example if you want to tweak integer value
|
||||||
|
/// ```no_run
|
||||||
|
/// use veloren_common_assets::asset_tweak;
|
||||||
|
/// let x: i32 = asset_tweak::tweak_expect_or_create("x", 5);
|
||||||
|
/// ```
|
||||||
|
/// File needs to look like that
|
||||||
|
/// ```text
|
||||||
|
/// assets/tweak/x.ron
|
||||||
|
/// (5)
|
||||||
|
/// ```
|
||||||
|
/// Note the parentheses.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// 1) If asset is broken
|
||||||
|
/// 2) filesystem errors
|
||||||
|
pub fn tweak_expect_or_create<T>(specifier: &str, value: T) -> T
|
||||||
|
where
|
||||||
|
T: Clone + Sized + Send + Sync + 'static + DeserializeOwned + Serialize,
|
||||||
|
{
|
||||||
|
if cfg!(not(any(debug_assertions, test))) {
|
||||||
|
tracing::warn!("AssetTweaker used in release build!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let root = find_root().expect("failed to discover repository_root");
|
||||||
|
let tweak_dir = root.join("asset/tweak/");
|
||||||
|
let filename = format!("{}.ron", specifier);
|
||||||
|
|
||||||
|
if Path::new(&tweak_dir.join(&filename)).is_file() {
|
||||||
|
let asset_specifier: &str = &format!("tweak.{}", specifier);
|
||||||
|
let handle = <AssetTweakWrapper<T> as AssetExt>::load_expect(asset_specifier);
|
||||||
|
let AssetTweakWrapper(new_value) = handle.read().clone();
|
||||||
|
|
||||||
|
new_value
|
||||||
|
} else {
|
||||||
|
fs::create_dir(&tweak_dir).expect("failed to create directory for tweak files");
|
||||||
|
let f = fs::File::create(tweak_dir.join(&filename)).unwrap_or_else(|err| {
|
||||||
|
panic!("failed to create file {:?}. Error: {:?}", &filename, err)
|
||||||
|
});
|
||||||
|
to_writer_pretty(f, &value, PrettyConfig::new()).unwrap_or_else(|err| {
|
||||||
|
panic!("failed to write to file {:?}. Error: {:?}", &filename, err)
|
||||||
|
});
|
||||||
|
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::asset_tweak::tweak;
|
use super::{asset_tweak::tweak_expect, find_root};
|
||||||
use std::{
|
use std::{
|
||||||
convert::AsRef,
|
convert::AsRef,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::Write,
|
io::Write,
|
||||||
path::{Path, PathBuf},
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return path to repository by searching 10 directories back
|
|
||||||
fn find_root() -> Option<PathBuf> {
|
|
||||||
std::env::current_dir().map_or(None, |path| {
|
|
||||||
// If we are in the root, push path
|
|
||||||
if path.join(".git").is_dir() {
|
|
||||||
return Some(path);
|
|
||||||
}
|
|
||||||
// Search .git directory in parent directries
|
|
||||||
for ancestor in path.ancestors().take(10) {
|
|
||||||
if ancestor.join(".git").is_dir() {
|
|
||||||
return Some(ancestor.to_path_buf());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DirectoryGuard<P>
|
struct DirectoryGuard<P>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
@ -366,13 +431,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_tweaked_string() {
|
fn test_tweaked_string() {
|
||||||
let root = find_root().expect("failed to discover repository_root");
|
let root = find_root().expect("failed to discover repository_root");
|
||||||
let tweak_dir = root.join("assets/common/tweak/");
|
let tweak_dir = root.join("assets/tweak/");
|
||||||
let _dir_guard = DirectoryGuard::create(tweak_dir.clone());
|
let _dir_guard = DirectoryGuard::create(tweak_dir.clone());
|
||||||
|
|
||||||
// define test files
|
// define test files
|
||||||
let from_int = tweak_dir.clone().join("int_tweak.ron");
|
let from_int = tweak_dir.join("int_tweak.ron");
|
||||||
let from_string = tweak_dir.clone().join("string_tweak.ron");
|
let from_string = tweak_dir.join("string_tweak.ron");
|
||||||
let from_map = tweak_dir.clone().join("map_tweak.ron");
|
let from_map = tweak_dir.join("map_tweak.ron");
|
||||||
|
|
||||||
// setup fs guards
|
// setup fs guards
|
||||||
let (_file_guard1, mut file1) = FileGuard::create(from_int);
|
let (_file_guard1, mut file1) = FileGuard::create(from_int);
|
||||||
@ -380,20 +445,22 @@ mod tests {
|
|||||||
let (_file_guard3, mut file3) = FileGuard::create(from_map);
|
let (_file_guard3, mut file3) = FileGuard::create(from_map);
|
||||||
|
|
||||||
// write to file and check result
|
// write to file and check result
|
||||||
file1.write(b"(5)").expect("failed to write to the file");
|
file1
|
||||||
let x = tweak::<i32>("common.tweak.int_tweak");
|
.write_all(b"(5)")
|
||||||
|
.expect("failed to write to the file");
|
||||||
|
let x = tweak_expect::<i32>("tweak.int_tweak");
|
||||||
assert_eq!(x, 5);
|
assert_eq!(x, 5);
|
||||||
|
|
||||||
// write to file and check result
|
// write to file and check result
|
||||||
file2
|
file2
|
||||||
.write(br#"("Hello Zest")"#)
|
.write_all(br#"("Hello Zest")"#)
|
||||||
.expect("failed to write to the file");
|
.expect("failed to write to the file");
|
||||||
let x = tweak::<String>("common.tweak.string_tweak");
|
let x = tweak_expect::<String>("tweak.string_tweak");
|
||||||
assert_eq!(x, "Hello Zest".to_owned());
|
assert_eq!(x, "Hello Zest".to_owned());
|
||||||
|
|
||||||
// write to file and check result
|
// write to file and check result
|
||||||
file3
|
file3
|
||||||
.write(
|
.write_all(
|
||||||
br#"
|
br#"
|
||||||
({
|
({
|
||||||
"wow": 4,
|
"wow": 4,
|
||||||
@ -402,7 +469,7 @@ mod tests {
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.expect("failed to write to the file");
|
.expect("failed to write to the file");
|
||||||
let x: std::collections::HashMap<String, i32> = tweak("common.tweak.map_tweak");
|
let x: std::collections::HashMap<String, i32> = tweak_expect("tweak.map_tweak");
|
||||||
let mut map = std::collections::HashMap::new();
|
let mut map = std::collections::HashMap::new();
|
||||||
map.insert("wow".to_owned(), 4);
|
map.insert("wow".to_owned(), 4);
|
||||||
map.insert("such".to_owned(), 5);
|
map.insert("such".to_owned(), 5);
|
||||||
|
Reference in New Issue
Block a user