add option for asset folder

This commit is contained in:
Moritz Hölting 2024-06-10 16:01:06 +02:00
parent 074bf4cc9d
commit 61959b17e9
7 changed files with 122 additions and 22 deletions

View File

@ -24,8 +24,8 @@ colored = "2.1.0"
serde = { version = "1.0.197", features = ["derive"] } serde = { version = "1.0.197", features = ["derive"] }
thiserror = "1.0.58" thiserror = "1.0.58"
toml = "0.8.12" toml = "0.8.12"
shulkerscript-lang = { git = "https://github.com/moritz-hoelting/shulkerscript-lang", features = ["shulkerbox"], default-features = false, rev = "09b389c2060e73f686d92df3c45290c2c1b34ecb"} shulkerscript-lang = { git = "https://github.com/moritz-hoelting/shulkerscript-lang", features = ["shulkerbox"], default-features = false, rev = "44d634355b4ab5b652de56b0becd61b05680c068"}
shulkerbox = { git = "https://github.com/moritz-hoelting/shulkerbox", default-features = false, rev = "296502dcc5dd29b3d930ffec91ceec3d161e0e47" } shulkerbox = { git = "https://github.com/moritz-hoelting/shulkerbox", default-features = false, rev = "b79c9ecd6d45f9319c9083a8103ef0186839b0c0" }
git2 = { version = "0.18.3", default-features = false } git2 = { version = "0.18.3", default-features = false }
path-absolutize = "3.1.1" path-absolutize = "3.1.1"
color-eyre = "0.6.3" color-eyre = "0.6.3"

View File

@ -1,12 +1,15 @@
use std::path::PathBuf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ProjectConfig { pub struct ProjectConfig {
pub pack: PackConfig, pub pack: PackConfig,
pub compiler: Option<CompilerConfig>,
} }
impl ProjectConfig { impl ProjectConfig {
pub fn new(pack: PackConfig) -> Self { pub fn new(pack: PackConfig, compiler: Option<CompilerConfig>) -> Self {
Self { pack } Self { pack, compiler }
} }
} }
@ -47,3 +50,15 @@ impl Default for PackConfig {
fn default_pack_format() -> u8 { fn default_pack_format() -> u8 {
26 26
} }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompilerConfig {
/// The path of a folder which files and subfolders will be copied to the root of the datapack.
pub assets: Option<PathBuf>,
}
impl CompilerConfig {
pub fn new(assets: Option<PathBuf>) -> Self {
Self { assets }
}
}

View File

@ -1,10 +1,11 @@
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
use path_absolutize::Absolutize; use path_absolutize::Absolutize;
use shulkerbox::virtual_fs::VFolder;
use crate::{ use crate::{
config::ProjectConfig, config::ProjectConfig,
error::Error, error::Error,
terminal_output::{print_error, print_info}, terminal_output::{print_error, print_info, print_warning},
}; };
use std::{ use std::{
env, fs, env, fs,
@ -17,8 +18,13 @@ pub struct BuildArgs {
#[clap(default_value = ".")] #[clap(default_value = ".")]
pub path: PathBuf, pub path: PathBuf,
/// The path of the directory to place the compiled datapack. /// The path of the directory to place the compiled datapack.
/// Overrides the `DATAPACK_DIR` environment variable.
#[clap(short, long)] #[clap(short, long)]
pub output: Option<PathBuf>, pub output: Option<PathBuf>,
/// The path of a folder which files and subfolders will be copied to the root of the datapack.
/// Overrides the `assets` field in the pack.toml file.
#[clap(short, long)]
pub assets: Option<PathBuf>,
} }
pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> { pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> {
@ -29,7 +35,7 @@ pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> {
.or_else(|| env::var("DATAPACK_DIR").ok().map(PathBuf::from)) .or_else(|| env::var("DATAPACK_DIR").ok().map(PathBuf::from))
.unwrap_or_else(|| path.join("dist")); .unwrap_or_else(|| path.join("dist"));
print_info(&format!( print_info(format!(
"Building project at {}", "Building project at {}",
path.absolutize()?.display() path.absolutize()?.display()
)); ));
@ -51,11 +57,39 @@ pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> {
let compiled = shulkerscript_lang::compile(&script_paths)?; let compiled = shulkerscript_lang::compile(&script_paths)?;
let assets_path = args.assets.clone().or(project_config
.compiler
.as_ref()
.and_then(|c| c.assets.as_ref().map(|p| path.join(p))));
let output = if let Some(assets_path) = assets_path {
let assets = VFolder::try_from(assets_path.as_path());
if assets.is_err() {
print_error(format!(
"The specified assets path does not exist: {}",
assets_path.display()
));
}
let mut assets = assets?;
let replaced = assets.merge(compiled);
for replaced in replaced {
print_warning(format!(
"Template file {} was replaced by a file in the compiled datapack",
replaced
));
}
assets
} else {
compiled
};
let dist_path = dist_path.join(project_config.pack.name); let dist_path = dist_path.join(project_config.pack.name);
compiled.place(&dist_path)?; output.place(&dist_path)?;
print_info(&format!( print_info(format!(
"Finished building project to {}", "Finished building project to {}",
dist_path.absolutize_from(path)?.display() dist_path.absolutize_from(path)?.display()
)); ));

View File

@ -44,7 +44,7 @@ pub fn clean(verbose: bool, args: &CleanArgs) -> Result<()> {
delete_paths.push(dist_path.join(project_config.pack.name + ".zip")); delete_paths.push(dist_path.join(project_config.pack.name + ".zip"));
} }
print_info(&format!( print_info(format!(
"Cleaning project at {}", "Cleaning project at {}",
path.absolutize_from(path)?.display() path.absolutize_from(path)?.display()
)); ));
@ -67,7 +67,7 @@ pub fn clean(verbose: bool, args: &CleanArgs) -> Result<()> {
&& dist_path.read_dir()?.next().is_none() && dist_path.read_dir()?.next().is_none()
{ {
if verbose { if verbose {
print_info(&format!("Deleting {:?}, as it is empty", dist_path)); print_info(format!("Deleting {:?}, as it is empty", dist_path));
} }
std::fs::remove_dir(&dist_path)?; std::fs::remove_dir(&dist_path)?;
} }

View File

@ -118,7 +118,7 @@ fn create_pack_config(
fs::write(&path, toml::to_string_pretty(&content)?)?; fs::write(&path, toml::to_string_pretty(&content)?)?;
if verbose { if verbose {
print_info(&format!( print_info(format!(
"Created pack.toml file at {}.", "Created pack.toml file at {}.",
path.absolutize()?.display() path.absolutize()?.display()
)); ));
@ -130,7 +130,7 @@ fn create_dir(path: &Path, verbose: bool) -> std::io::Result<()> {
if !path.exists() { if !path.exists() {
fs::create_dir(path)?; fs::create_dir(path)?;
if verbose { if verbose {
print_info(&format!( print_info(format!(
"Created directory at {}.", "Created directory at {}.",
path.absolutize()?.display() path.absolutize()?.display()
)); ));
@ -143,7 +143,7 @@ fn create_gitignore(path: &Path, verbose: bool) -> std::io::Result<()> {
let gitignore = path.join(".gitignore"); let gitignore = path.join(".gitignore");
fs::write(&gitignore, "/dist\n")?; fs::write(&gitignore, "/dist\n")?;
if verbose { if verbose {
print_info(&format!( print_info(format!(
"Created .gitignore file at {}.", "Created .gitignore file at {}.",
gitignore.absolutize()?.display() gitignore.absolutize()?.display()
)); ));
@ -155,7 +155,7 @@ fn create_pack_png(path: &Path, verbose: bool) -> std::io::Result<()> {
let pack_png = path.join("pack.png"); let pack_png = path.join("pack.png");
fs::write(&pack_png, include_bytes!("../../assets/default-icon.png"))?; fs::write(&pack_png, include_bytes!("../../assets/default-icon.png"))?;
if verbose { if verbose {
print_info(&format!( print_info(format!(
"Created pack.png file at {}.", "Created pack.png file at {}.",
pack_png.absolutize()?.display() pack_png.absolutize()?.display()
)); ));
@ -173,7 +173,7 @@ fn create_main_file(path: &Path, namespace: &str, verbose: bool) -> std::io::Res
), ),
)?; )?;
if verbose { if verbose {
print_info(&format!( print_info(format!(
"Created main.shu file at {}.", "Created main.shu file at {}.",
main_file.absolutize()?.display() main_file.absolutize()?.display()
)); ));

View File

@ -2,8 +2,12 @@ use std::{env, path::PathBuf};
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
use path_absolutize::Absolutize; use path_absolutize::Absolutize;
use shulkerbox::virtual_fs::VFolder;
use crate::{error::Error, terminal_output::print_info}; use crate::{
error::Error,
terminal_output::{print_error, print_info, print_warning},
};
use super::BuildArgs; use super::BuildArgs;
@ -22,7 +26,7 @@ pub fn package(_verbose: bool, args: &PackageArgs) -> Result<()> {
.or_else(|| env::var("DATAPACK_DIR").ok().map(PathBuf::from)) .or_else(|| env::var("DATAPACK_DIR").ok().map(PathBuf::from))
.unwrap_or_else(|| path.join("dist")); .unwrap_or_else(|| path.join("dist"));
print_info(&format!( print_info(format!(
"Packaging project at {}", "Packaging project at {}",
path.absolutize()?.display() path.absolutize()?.display()
)); ));
@ -38,11 +42,39 @@ pub fn package(_verbose: bool, args: &PackageArgs) -> Result<()> {
let compiled = shulkerscript_lang::compile(&script_paths)?; let compiled = shulkerscript_lang::compile(&script_paths)?;
let assets_path = args.build_args.assets.clone().or(project_config
.compiler
.as_ref()
.and_then(|c| c.assets.as_ref().map(|p| path.join(p))));
let output = if let Some(assets_path) = assets_path {
let assets = VFolder::try_from(assets_path.as_path());
if assets.is_err() {
print_error(format!(
"The specified assets path does not exist: {}",
assets_path.display()
));
}
let mut assets = assets?;
let replaced = assets.merge(compiled);
for replaced in replaced {
print_warning(format!(
"Template file {} was replaced by a file in the compiled datapack",
replaced
));
}
assets
} else {
compiled
};
let dist_path = dist_path.join(project_config.pack.name + ".zip"); let dist_path = dist_path.join(project_config.pack.name + ".zip");
compiled.zip(&dist_path)?; output.zip(&dist_path)?;
print_info(&format!( print_info(format!(
"Finished packaging project to {}", "Finished packaging project to {}",
dist_path.absolutize_from(path)?.display() dist_path.absolutize_from(path)?.display()
)); ));

View File

@ -1,12 +1,31 @@
use std::fmt::Display;
use colored::Colorize; use colored::Colorize;
pub fn print_info(msg: &str) { pub fn print_info<D>(msg: D)
where
D: Display,
{
println!("[{}] {msg}", "INFO".blue()) println!("[{}] {msg}", "INFO".blue())
} }
pub fn print_success(msg: &str) { pub fn print_success<D>(msg: D)
where
D: Display,
{
println!("[{}] {msg}", "SUCCESS".green()) println!("[{}] {msg}", "SUCCESS".green())
} }
pub fn print_error(msg: &str) {
pub fn print_warning<D>(msg: D)
where
D: Display,
{
println!("[{}] {msg}", "WARNING".yellow())
}
pub fn print_error<D>(msg: D)
where
D: Display,
{
println!("[{}] {msg}", "ERROR".red()) println!("[{}] {msg}", "ERROR".red())
} }