merge build and package command

This commit is contained in:
Moritz Hölting 2024-06-12 22:43:57 +02:00
parent cc6cf18406
commit 0284eccfcd
8 changed files with 48 additions and 138 deletions

View File

@ -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

View File

@ -28,7 +28,9 @@ shulkerscript build [OPTIONS] [PATH]
Where [PATH] is the path of the project folder to build [default: `.`]
Options:
- `--assets <ASSETS>` The path to the assets directory [default: `./assets`]
- `--output <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 <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]

View File

@ -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")]

View File

@ -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)]

View File

@ -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<PathBuf>,
/// 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()
));

View File

@ -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")]

View File

@ -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(())
}

View File

@ -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<WatchSubcommand> 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("."),
};