From 0284eccfcd3cf9e7fd522cd8977e476442db74bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20H=C3=B6lting?= <87192362+moritz-hoelting@users.noreply.github.com> Date: Wed, 12 Jun 2024 22:43:57 +0200 Subject: [PATCH] merge build and package command --- CHANGELOG.md | 3 +- README.md | 14 +----- src/cli.rs | 5 --- src/error.rs | 2 + src/subcommands/build.rs | 41 +++++++++++++++-- src/subcommands/mod.rs | 5 --- src/subcommands/package.rs | 91 -------------------------------------- src/subcommands/watch.rs | 25 +++-------- 8 files changed, 48 insertions(+), 138 deletions(-) delete mode 100644 src/subcommands/package.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 8eb62f0..bd8998f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,9 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Subcommand `build` to build a project - Compiles the project to a datapack directory - Allows changing the output directory and setting a assets directory -- Subcommand `package` to build and package a project to a zip file - - Same options as `build` - Subcommand `clean` to clean the output directory +- Subcommand `watch` to watch for changes and run a command - Subcommand `lang-debug` to debug the language parser - Allows to print the parsed tokens, AST and shulkerbox datapack representation diff --git a/README.md b/README.md index 10858b0..94dac03 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,9 @@ shulkerscript build [OPTIONS] [PATH] Where [PATH] is the path of the project folder to build [default: `.`] Options: +- `--assets ` The path to the assets directory [default: `./assets`] - `--output ` The output directory, overrides the `DATAPACK_DIR` environment variable +- `--zip` Package the output into a zip file Environment variables: - `DATAPACK_DIR` The output directory [default: `./dist`] @@ -45,18 +47,6 @@ Options: Environment variables: - `DATAPACK_DIR` The output directory [default: `./dist`] -### Package a project -```bash -shulkerscript package [OPTIONS] [PATH] -``` -Where [PATH] is the path of the project folder to package [default: `.`] - -Options: -- `--output ` The output directory, overrides the `DATAPACK_DIR` environment variable - -Environment variables: -- `DATAPACK_DIR` The output directory [default: `./dist`] - ### Watch for changes ```bash shulkerscript watch [OPTIONS] [SUBCOMMAND] diff --git a/src/cli.rs b/src/cli.rs index d156b86..1f451e2 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -21,9 +21,6 @@ pub enum Command { /// Clean build artifacts. /// This will remove the `dist` directory. Clean(CleanArgs), - #[cfg(feature = "zip")] - /// Build and package the project. - Package(subcommands::PackageArgs), #[cfg(feature = "watch")] /// Watch for changes and execute command. Watch(subcommands::WatchArgs), @@ -44,8 +41,6 @@ impl Command { Command::Init(args) => subcommands::init(verbose, args)?, Command::Build(args) => subcommands::build(verbose, args)?, Command::Clean(args) => subcommands::clean(verbose, args)?, - #[cfg(feature = "zip")] - Command::Package(args) => subcommands::package(verbose, args)?, #[cfg(feature = "watch")] Command::Watch(args) => subcommands::watch(verbose, args)?, #[cfg(feature = "lang-debug")] diff --git a/src/error.rs b/src/error.rs index 2e5e484..187ba07 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,6 +11,8 @@ pub enum Error { NotDirectoryError(PathBuf), #[error("An error occured because the path is neither a pack directory or a pack.toml file.")] InvalidPackPathError(PathBuf), + #[error("An error occured because the feature {0} is not enabled.")] + FeatureNotEnabledError(String), } #[allow(dead_code)] diff --git a/src/subcommands/build.rs b/src/subcommands/build.rs index e5cad5a..9f6575a 100644 --- a/src/subcommands/build.rs +++ b/src/subcommands/build.rs @@ -1,4 +1,4 @@ -use color_eyre::eyre::Result; +use color_eyre::eyre::{Report, Result}; use path_absolutize::Absolutize; use shulkerbox::virtual_fs::{VFile, VFolder}; @@ -25,9 +25,30 @@ pub struct BuildArgs { /// Overrides the `assets` field in the pack.toml file. #[clap(short, long)] pub assets: Option, + /// Whether to package the project to a zip file. + #[clap(short, long)] + pub zip: bool, +} + +impl Default for BuildArgs { + fn default() -> Self { + Self { + path: PathBuf::from("."), + output: None, + assets: None, + zip: false, + } + } } pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> { + if args.zip && !cfg!(feature = "zip") { + print_error("The zip feature is not enabled. Please install with the `zip` feature enabled to use the `--zip` option."); + return Err(Report::from(Error::FeatureNotEnabledError( + "zip".to_string(), + ))); + } + let path = args.path.as_path(); let dist_path = args .output @@ -35,8 +56,10 @@ pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> { .or_else(|| env::var("DATAPACK_DIR").ok().map(PathBuf::from)) .unwrap_or_else(|| path.join("dist")); + let and_package_msg = if args.zip { " and packaging" } else { "" }; + print_info(format!( - "Building project at {}", + "Building{and_package_msg} project at {}", path.absolutize()?.display() )); @@ -87,12 +110,22 @@ pub fn build(_verbose: bool, args: &BuildArgs) -> Result<()> { compiled }; - let dist_path = dist_path.join(project_config.pack.name); + let dist_extension = if args.zip { ".zip" } else { "" }; + let dist_path = dist_path.join(project_config.pack.name + dist_extension); + + #[cfg(feature = "zip")] + if args.zip { + output.zip(&dist_path)?; + } else { + output.place(&dist_path)?; + } + + #[cfg(not(feature = "zip"))] output.place(&dist_path)?; print_info(format!( - "Finished building project to {}", + "Finished building{and_package_msg} project to {}", dist_path.absolutize_from(path)?.display() )); diff --git a/src/subcommands/mod.rs b/src/subcommands/mod.rs index 7b784be..7bc4590 100644 --- a/src/subcommands/mod.rs +++ b/src/subcommands/mod.rs @@ -7,11 +7,6 @@ pub use build::{build, BuildArgs}; mod clean; pub use clean::{clean, CleanArgs}; -#[cfg(feature = "zip")] -mod package; -#[cfg(feature = "zip")] -pub use package::{package, PackageArgs}; - #[cfg(feature = "watch")] mod watch; #[cfg(feature = "watch")] diff --git a/src/subcommands/package.rs b/src/subcommands/package.rs deleted file mode 100644 index 4ee95d3..0000000 --- a/src/subcommands/package.rs +++ /dev/null @@ -1,91 +0,0 @@ -use std::{env, fs, path::PathBuf}; - -use color_eyre::eyre::Result; -use path_absolutize::Absolutize; -use shulkerbox::virtual_fs::{VFile, VFolder}; - -use crate::{ - error::Error, - terminal_output::{print_error, print_info, print_warning}, -}; - -use super::BuildArgs; - -#[derive(Debug, clap::Args, Clone)] -pub struct PackageArgs { - #[clap(flatten)] - pub build_args: BuildArgs, -} - -pub fn package(_verbose: bool, args: &PackageArgs) -> Result<()> { - let path = args.build_args.path.as_path(); - let dist_path = args - .build_args - .output - .clone() - .or_else(|| env::var("DATAPACK_DIR").ok().map(PathBuf::from)) - .unwrap_or_else(|| path.join("dist")); - - print_info(format!( - "Packaging project at {}", - path.absolutize()?.display() - )); - - let (project_config, toml_path) = super::build::get_pack_config(path)?; - - let script_paths = super::build::get_script_paths( - &toml_path - .parent() - .ok_or(Error::InvalidPackPathError(path.to_path_buf()))? - .join("src"), - )?; - - let mut compiled = shulkerscript::compile(&script_paths)?; - - let icon_path = toml_path.parent().unwrap().join("pack.png"); - - if icon_path.is_file() { - if let Ok(icon_data) = fs::read(icon_path) { - compiled.add_file("pack.png", VFile::Binary(icon_data)); - } - } - - 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"); - - output.zip(&dist_path)?; - - print_info(format!( - "Finished packaging project to {}", - dist_path.absolutize_from(path)?.display() - )); - - Ok(()) -} diff --git a/src/subcommands/watch.rs b/src/subcommands/watch.rs index 7a4fbb6..846513e 100644 --- a/src/subcommands/watch.rs +++ b/src/subcommands/watch.rs @@ -1,8 +1,4 @@ -use std::{ - path::{Path, PathBuf}, - thread, - time::Duration, -}; +use std::{path::Path, thread, time::Duration}; use clap::Subcommand; use notify_debouncer_mini::{new_debouncer, notify::*, DebounceEventResult}; @@ -31,34 +27,25 @@ pub struct WatchArgs { pub enum WatchSubcommand { /// Build the project. Build(BuildArgs), - #[cfg(feature = "zip")] - /// Build and package the project. - Package(super::PackageArgs), } impl From for Command { fn from(value: WatchSubcommand) -> Self { match value { WatchSubcommand::Build(args) => Command::Build(args), - #[cfg(feature = "zip")] - WatchSubcommand::Package(args) => Command::Package(args), } } } pub fn watch(verbose: bool, args: &WatchArgs) -> Result<()> { - let cmd = Command::from(args.cmd.to_owned().unwrap_or_else(|| { - WatchSubcommand::Build(BuildArgs { - path: PathBuf::from("."), - output: None, - assets: None, - }) - })); + let cmd = Command::from( + args.cmd + .to_owned() + .unwrap_or_else(|| WatchSubcommand::Build(BuildArgs::default())), + ); let project_path = match &args.cmd { Some(WatchSubcommand::Build(args)) => args.path.as_path(), - #[cfg(feature = "zip")] - Some(WatchSubcommand::Package(args)) => args.build_args.path.as_path(), None => Path::new("."), };