Skip to content

Commit

Permalink
refactor: switch to worlds property (#4)
Browse files Browse the repository at this point in the history
close #4
  • Loading branch information
arexon committed Nov 22, 2022
1 parent 10f850e commit 7d61168
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 33 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2021"
[dependencies]
clap = { version = "4.0.19", features = ["derive"] }
colored = "2.0.0"
glob = "0.3.0"
miette = { version = "5.3.0", features = ["fancy"] }
serde = { version = "1.0.147", features = ["derive"] }
serde_json = "1.0.87"
Expand Down
8 changes: 1 addition & 7 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@ use crate::error::{HazeError, HazeResult};

#[derive(Deserialize)]
pub struct Config {
pub packs: Packs,
}

#[derive(Deserialize)]
pub struct Packs {
#[serde(rename = "worldTemplate")]
pub world_template: String,
pub worlds: Vec<String>,
}

pub fn load(path: String) -> HazeResult<Config> {
Expand Down
18 changes: 17 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use colored::ColoredString;
use miette::Diagnostic;
use std::io;
use std::{fmt, io, path::PathBuf, vec};
use thiserror::Error;

pub type HazeResult<T> = Result<T, HazeError>;
Expand All @@ -15,6 +15,22 @@ pub enum HazeError {
#[diagnostic(code(haze::config::parse_error), help("{0}"))]
ConfigParse(serde_json::Error, ColoredString),

#[error("the `worlds` config property is empty")]
#[diagnostic(help("the property must include at least one pattern"))]
EmptyWorldsProperty,

#[error("invalid glob pattern in `worlds` property `{1}`")]
#[diagnostic(help("{0}"))]
InvalidWorldsGlobPattern(glob::PatternError, String),

#[error("cannot find a worlds directory from the defined patterns `{1:?}`")]
#[diagnostic(code(haze::config::invalid_glob_pattern_error), help("{0}"))]
WorldsDirectoryNotFound(io::ErrorKind, Vec<String>),

#[error("cannot find the world `{1}` in local worlds directory")]
#[diagnostic(help("available worlds: {0:?}"))]
WorldNotFound(Vec<PathBuf>, String),

#[error("unable to find the local appdata directory")]
#[diagnostic(code(haze::world::local_appdata_error), help("{0}"))]
LocalAppData(io::Error),
Expand Down
6 changes: 2 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ fn main() -> Result<()> {

let config = config::load(cli.config)?;
match cli.command {
Command::Test { name, overwrite } => {
world::test(&name, &config.packs.world_template, overwrite)?
}
Command::Save { name } => world::save(&name, &config.packs.world_template)?,
Command::Test { name, overwrite } => world::test(name, config.worlds, overwrite)?, // Command::Save { name } => world::save(&name, &config.worlds)?,
Command::Save { name } => world::save(name, config.worlds)?,
}

Ok(())
Expand Down
61 changes: 40 additions & 21 deletions src/world.rs
Original file line number Diff line number Diff line change
@@ -1,56 +1,76 @@
use colored::Colorize;
use glob::glob;
use std::{
env, fs, io,
path::{Path, PathBuf},
};

use crate::error::{HazeError, HazeResult};

pub fn test(world_name: &str, local_worlds_dir: &str, overwrite: bool) -> HazeResult<()> {
let from: PathBuf = [local_worlds_dir, world_name].iter().collect();
let to = make_mojang_worlds_dir(world_name).map_err(HazeError::LocalAppData)?;
pub fn test(name: String, worlds: Vec<String>, overwrite: bool) -> HazeResult<()> {
let from: PathBuf = local_worlds_dir(worlds, name.clone())?;
let to = mojang_worlds_dir(&name).map_err(HazeError::LocalAppData)?;

if to.exists() && !overwrite {
Err(HazeError::OverwriteWorld(
world_name.to_string().bold().underline(),
))?;
Err(HazeError::OverwriteWorld(name.bold().underline()))?;
}

copy_dir(from, to)
.map_err(|e| HazeError::WorldCopy(e, world_name.to_string().bold().underline()))?;
copy_dir(from, to).map_err(|e| HazeError::WorldCopy(e, name.to_string().bold().underline()))?;

if overwrite {
println!(
"Updated '{}' in '{}' ({})",
world_name,
name,
"minecraftWorlds".bold(),
"overwrite".red()
);
} else {
println!(
"Copied world '{}' to '{}' for testing",
"minecraftWorlds".bold(),
world_name
name
);
}
Ok(())
}

pub fn save(world_name: &str, local_worlds_dir: &str) -> HazeResult<()> {
let from = make_mojang_worlds_dir(world_name).map_err(HazeError::LocalAppData)?;
let to: PathBuf = [local_worlds_dir, world_name].iter().collect();
pub fn save(name: String, worlds: Vec<String>) -> HazeResult<()> {
let from = mojang_worlds_dir(&name).map_err(HazeError::LocalAppData)?;
let to: PathBuf = local_worlds_dir(worlds, name.clone())?;

copy_dir(from, to)
.map_err(|e| HazeError::WorldCopy(e, world_name.to_string().bold().underline()))?;
copy_dir(from, to).map_err(|e| HazeError::WorldCopy(e, name.to_string().bold().underline()))?;

println!(
"Saved world '{}' to local worlds directory",
world_name.bold()
);
println!("Saved world '{}' to local worlds directory", name.bold());
Ok(())
}

fn make_mojang_worlds_dir(name: &str) -> Result<PathBuf, io::Error> {
fn local_worlds_dir(worlds_patterns: Vec<String>, name: String) -> HazeResult<PathBuf> {
let mut paths: Vec<PathBuf> = Vec::new();
for pattern in worlds_patterns.clone() {
for path in glob(&pattern).map_err(|e| HazeError::InvalidWorldsGlobPattern(e, pattern))? {
match path {
Ok(path) => paths.push(path),
Err(e) => {
return Err(HazeError::WorldsDirectoryNotFound(
e.error().kind(),
worlds_patterns,
))
}
}
}
}

if paths.is_empty() {
return Err(HazeError::EmptyWorldsProperty);
}
let Some(path) = paths.iter().find(|p| p.ends_with(&name)) else {
return Err(HazeError::WorldNotFound(paths, name));
};

Ok(path.clone())
}

fn mojang_worlds_dir(name: &str) -> Result<PathBuf, io::Error> {
let base = env::var("LOCALAPPDATA").unwrap();

Ok([
Expand Down Expand Up @@ -79,6 +99,5 @@ fn copy_dir(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<(), io::Erro
fs::copy(entry.path(), to.as_ref().join(entry.file_name()))?;
}
}

Ok(())
}

0 comments on commit 7d61168

Please sign in to comment.